Skip to content

fix: dogfood fixes 9.1–9.4 — version warning, barrel exports, quieter tsconfig, Set compat#634

Open
carlos-alm wants to merge 3 commits intomainfrom
feat/dogfood-fixes-9.1-9.4
Open

fix: dogfood fixes 9.1–9.4 — version warning, barrel exports, quieter tsconfig, Set compat#634
carlos-alm wants to merge 3 commits intomainfrom
feat/dogfood-fixes-9.1-9.4

Conversation

@carlos-alm
Copy link
Contributor

Summary

Addresses four dogfooding issues from the v3.4.0 report:

  • 9.1 DB Version Warning: openReadonlyOrFail() now checks build_meta.codegraph_version against the running version and warns (once per process) with a suggestion to build --no-incremental
  • 9.2 Barrel File Export Tracing: Barrel-only files were entirely skipped in buildImportEdges, so no reexports edges were created. Now only non-reexport imports are skipped, letting codegraph exports follow re-export chains through barrel files
  • 9.3 Quieter tsconfig.json Warning: Demoted "Failed to parse tsconfig.json" from warn to debug so it only appears with --verbose
  • 9.4 EXTENSIONS/IGNORE_DIRS Set Compat: Documented the Array→Set breaking change in CHANGELOG. Added .toArray() convenience method and exported ArrayCompatSet type for consumers migrating from the pre-3.4 array API

Test plan

  • codegraph build && codegraph exports src/index.ts — should show re-exported symbols instead of "No exported symbols found"
  • Edit build_meta.codegraph_version in DB to a different value, run any query — should see version mismatch warning once
  • codegraph build without --verbose — no tsconfig.json warning
  • import { EXTENSIONS } from '@optave/codegraph'; EXTENSIONS.toArray() — returns string array

@claude
Copy link

claude bot commented Mar 26, 2026

Claude finished @carlos-alm's task —— View job


PR Review Analysis

Todo List

  • Phase 1: Root cause analysis - understand what problems this PR solves
  • Phase 2: Configuration change detection - check for rule relaxation
  • Phase 3: Test integrity verification
  • Phase 4: Code quality review
  • Phase 5: Backlog compliance assessment
  • Final recommendation

Phase 1: Root Cause Analysis ✅

Problems Being Solved:

  • Issue 9.1 (DB Version Warning): Users get no feedback when running queries against stale databases built with different codegraph versions, leading to confusion about incorrect results
  • Issue 9.2 (Barrel Export Tracing): codegraph exports fails to follow re-export chains through barrel files, showing "No exported symbols found" instead of actual exports
  • Issue 9.3 (Noisy tsconfig Warning): Non-critical tsconfig.json parse failures spam users with warnings during normal operation
  • Issue 9.4 (EXTENSIONS/IGNORE_DIRS Set Compat): Breaking change in v3.4.0 converted arrays to Sets without migration path for existing consumers

Root Cause Assessment: All fixes address real user pain points without masking underlying issues. The approaches are sound.

Phase 2: Configuration Change Detection ✅

No HIGH-RISK changes detected:

  • No biome/linting rules disabled or relaxed
  • No test timeouts increased or coverage thresholds lowered
  • No build configuration changes
  • No TypeScript strict mode flags disabled

Appropriate warning level change: tsconfig.json parse failure demoted from warn to debug — justified since it's non-critical during path alias loading.

Phase 3: Test Integrity ✅

No test integrity issues:

  • No tests removed or weakened
  • No assertions made less strict
  • No eslint-disable comments added
  • Changes are additive (version warning, reexport edges, compat methods)
  • Test plan in PR covers all 4 changes

Phase 4: Code Quality ✅

Implementation Quality:

9.1 DB Version Check (src/db/connection.ts:224-241):

  • ✅ Proper once-per-process warning with _versionWarned flag
  • ✅ Graceful error handling with try-catch (older DBs may lack build_meta table)
  • ✅ Clear actionable message suggesting --no-incremental
  • ✅ Uses lazy-loaded package version to avoid unnecessary I/O

9.2 Barrel Export Tracing (src/domain/graph/builder/stages/build-edges.ts:111-112):

  • ✅ Surgical fix: only skip non-reexport imports for barrel-only files
  • ✅ Preserves reexport edges that codegraph exports needs to follow chains
  • ✅ Logic correctly implemented: if (isBarrelOnly && !imp.reexport) continue;

9.3 Quieter tsconfig (src/domain/graph/builder/helpers.ts:152):

  • ✅ Changed warn to debug for tsconfig parse failures
  • ✅ Appropriate since this is non-critical path alias loading
  • ✅ Still logged with --verbose for debugging

9.4 Set Compatibility (src/shared/constants.ts):

  • ArrayCompatSet<T> interface extends Set<T> with toArray() method
  • withArrayCompat() function adds method without mutation
  • ✅ CHANGELOG.md properly documents breaking change and migration path
  • ✅ Exported type allows consumers to type their variables correctly

Potential Issues: None found. All implementations are defensive, well-structured, and maintain backward compatibility where possible.

Phase 5: Backlog Compliance ✅

Zero-dep: ✅ No new runtime dependencies added
Foundation-aligned: ✅ Fully compliant - improves user experience without violating core principles
Problem-fit: 4/5 - Directly improves agent experience by reducing noise and providing better export tracing
Breaking: Partially - Set change is breaking but properly documented with migration path
Tier: 1 (zero-dep ✅ + foundation-aligned ✅)

Final Assessment

## Root Cause Analysis
**Problem Being Solved**: Four specific dogfooding pain points from v3.4.0 - stale DB confusion, broken barrel export tracing, noisy tsconfig warnings, and Set migration friction
**Why This Approach**: Each fix is surgical and addresses root causes without masking symptoms
**Risk Assessment**: Low risk - all changes are additive/defensive with proper error handling

## Backlog Compliance  
- Zero-dep: ✅ — no new dependencies
- Foundation-aligned: ✅ — improves UX without violating principles
- Problem-fit: 4 — directly helps AI agents navigate codebases with less noise
- Breaking: Documented — Set change has migration path in CHANGELOG  
- Tier: 1

## Critical Concerns
None. This is high-quality maintenance work that directly addresses user feedback.

## Final Recommendation
- Rating: ⭐⭐⭐⭐☆ (4/5)
- Action: APPROVE 
- Reasoning: Excellent surgical fixes for real user pain points. Clean implementations with proper error handling. Breaking change is well-documented with migration support. Only minor: could benefit from tests for the new functionality.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 26, 2026

Greptile Summary

This PR addresses four dogfooding regressions from the v3.4.0 report: a DB version mismatch warning, barrel file re-export edge tracing, quieter tsconfig parse noise, and backward-compatible Set constants. The fixes are well-scoped and the prior review concerns (redundant per-call version queries, in-place mutation of SUPPORTED_EXTENSIONS) have both been resolved in the latest commit.

Key changes:

  • 9.1 – Version warning (src/db/connection.ts): openReadonlyOrFail() lazily reads package.json and compares against build_meta.codegraph_version, emitting a one-shot warn() with a --no-incremental hint. The _versionWarned flag is now set unconditionally after the first check, eliminating repeated DB round-trips on subsequent calls.
  • 9.2 – Barrel export tracing (build-edges.ts, resolve-imports.ts): The old continue that skipped barrel-only files entirely in buildImportEdges is replaced with a per-import guard that skips only non-reexport entries. Incremental builds additionally re-parse known barrel files and delete their stale outgoing edges before re-insertion — though that deletion happens outside the buildEdges transaction (see inline comment).
  • 9.3 – Quieter tsconfig warning (helpers.ts): Demotes warndebug for tsconfig parse failures.
  • 9.4 – ArrayCompatSet (constants.ts, index.ts): EXTENSIONS and IGNORE_DIRS are now typed as ArrayCompatSet<string>, exposing a .toArray() shim. Both wrap a fresh Set copy so the original SUPPORTED_EXTENSIONS export from domain/parser is not mutated.

Confidence Score: 4/5

Safe to merge for normal usage; one P1 transactional gap in the incremental barrel cleanup path can cause silent edge loss on mid-build failures.

Three of the four fixes are clean and the previously flagged issues have been addressed. The remaining concern is the non-transactional deletion in resolve-imports.ts: if the pipeline fails after deleteOutgoingEdges.run() commits but before buildEdges inserts the replacement edges, the barrel file's reexports edges are permanently absent from the DB and the file won't re-appear in barrelCandidates on subsequent incremental runs. This is a real but narrow failure window (requires a mid-build crash), and users can recover with --no-incremental. Score reflects convergence from prior review rounds.

src/domain/graph/builder/stages/resolve-imports.ts — the deleteOutgoingEdges call at line 61 should ideally be moved inside the buildEdges transaction to be atomic with edge re-creation.

Important Files Changed

Filename Overview
src/db/connection.ts Adds one-shot version mismatch warning via lazy package.json read and _versionWarned guard; prior review concern about redundant per-call queries addressed by moving the flag set unconditionally after the first check.
src/domain/graph/builder/stages/build-edges.ts Barrel-only file handling changed from skip-entire-file to skip-non-reexport-imports, correctly enabling reexport edge creation while suppressing irrelevant import edges.
src/domain/graph/builder/stages/resolve-imports.ts Adds stale-edge cleanup for incremental barrel builds, but the deletion is committed outside the buildEdges transaction, creating a window where edges can be deleted without being re-created if a later pipeline stage fails.
src/shared/constants.ts Introduces ArrayCompatSet and withArrayCompat; prior mutation-of-original-set concern resolved by wrapping in new Set(SUPPORTED_EXTENSIONS) for EXTENSIONS and a fresh new Set([...]) for IGNORE_DIRS.
src/index.ts Adds export type { ArrayCompatSet } to the public API surface — clean type-only re-export, no issues.
src/domain/graph/builder/helpers.ts Demotes tsconfig parse failure from warn to debug — straightforward fix with no issues.
CHANGELOG.md Documents the Array→Set breaking change under a ### Notes section correctly placed in the 3.4.0 block.

Sequence Diagram

sequenceDiagram
    participant Build as buildGraph()
    participant RI as resolveImports()
    participant DB as SQLite DB
    participant BE as buildEdges()

    Build->>RI: await resolveImports(ctx)
    RI->>DB: SELECT barrel candidates (reexports edges)
    loop each barrel candidate not in fileSymbols
        RI->>RI: parseFilesAuto(absPath)
        RI->>DB: DELETE outgoing edges (outside tx)
        RI->>RI: fileSymbols.set / barrelOnlyFiles.add
    end
    RI-->>Build: ctx updated

    Build->>BE: await buildEdges(ctx)
    BE->>DB: BEGIN TRANSACTION
    loop each file in fileSymbols
        alt isBarrelOnly && !imp.reexport
            BE->>BE: skip (regular import)
        else
            BE->>DB: insert reexports / imports edge
        end
    end
    BE->>DB: COMMIT
    BE-->>Build: done

    note over RI,DB: If buildEdges fails, the DELETE is already committed but INSERT is rolled back
Loading

Reviews (2): Last reviewed commit: "fix: address review feedback — version c..." | Re-trigger Greptile

Comment on lines +225 to +241
if (!_versionWarned) {
try {
const row = db
.prepare<{ value: string }>('SELECT value FROM build_meta WHERE key = ?')
.get('codegraph_version');
const buildVersion = row?.value;
const currentVersion = getPackageVersion();
if (buildVersion && currentVersion && buildVersion !== currentVersion) {
warn(
`DB was built with codegraph v${buildVersion}, running v${currentVersion}. Consider: codegraph build --no-incremental`,
);
_versionWarned = true;
}
} catch {
// build_meta table may not exist in older DBs — silently ignore
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Version check runs on every call when versions match

_versionWarned is only set to true when a mismatch is detected, so every subsequent call to openReadonlyOrFail() with matching versions will still execute the prepare(...).get(...) round-trip against build_meta. In normal usage (versions match, multiple queries in one session), this adds a redundant DB query per call. The guard comment says "Warn once per process" which is accurate, but the check also runs repeatedly.

Moving _versionWarned = true outside the mismatch conditional would prevent the repeated query:

Suggested change
if (!_versionWarned) {
try {
const row = db
.prepare<{ value: string }>('SELECT value FROM build_meta WHERE key = ?')
.get('codegraph_version');
const buildVersion = row?.value;
const currentVersion = getPackageVersion();
if (buildVersion && currentVersion && buildVersion !== currentVersion) {
warn(
`DB was built with codegraph v${buildVersion}, running v${currentVersion}. Consider: codegraph build --no-incremental`,
);
_versionWarned = true;
}
} catch {
// build_meta table may not exist in older DBs — silently ignore
}
}
// Warn once if the DB was built with a different codegraph version
if (!_versionWarned) {
try {
const row = db
.prepare<{ value: string }>('SELECT value FROM build_meta WHERE key = ?')
.get('codegraph_version');
const buildVersion = row?.value;
const currentVersion = getPackageVersion();
if (buildVersion && currentVersion && buildVersion !== currentVersion) {
warn(
`DB was built with codegraph v${buildVersion}, running v${currentVersion}. Consider: codegraph build --no-incremental`,
);
}
} catch {
// build_meta table may not exist in older DBs — silently ignore
}
_versionWarned = true;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b60fbb7. Moved _versionWarned = true outside the mismatch conditional so the flag is set unconditionally after the first check, eliminating the redundant build_meta query on every subsequent call when versions match.

);

export { SUPPORTED_EXTENSIONS as EXTENSIONS };
export const EXTENSIONS: ArrayCompatSet<string> = withArrayCompat(SUPPORTED_EXTENSIONS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 withArrayCompat mutates SUPPORTED_EXTENSIONS in place

withArrayCompat(SUPPORTED_EXTENSIONS) casts the original Set to ArrayCompatSet and directly assigns .toArray onto it, mutating the module-level SUPPORTED_EXTENSIONS export from domain/parser.js. Any code that imports SUPPORTED_EXTENSIONS directly will now see the toArray property on it as a side effect of loading constants.ts. While adding a property to a Set won't interfere with .has() or iteration, it's an unintentional mutation of a sibling module's export.

Wrapping in a fresh Set keeps the original untouched:

Suggested change
export const EXTENSIONS: ArrayCompatSet<string> = withArrayCompat(SUPPORTED_EXTENSIONS);
export const EXTENSIONS: ArrayCompatSet<string> = withArrayCompat(new Set(SUPPORTED_EXTENSIONS));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b60fbb7. EXTENSIONS is now wrapped in new Set(SUPPORTED_EXTENSIONS) so withArrayCompat mutates the copy rather than the original SUPPORTED_EXTENSIONS export from the parser module.

… compat

9.1 — Warn on graph load when DB was built with a different codegraph
version. The check runs once per process in openReadonlyOrFail() and
suggests `build --no-incremental`.

9.2 — Barrel-only files now emit reexport edges during build. Previously
the entire file was skipped in buildImportEdges; now only non-reexport
imports are skipped, so `codegraph exports` can follow re-export chains.

9.3 — Demote "Failed to parse tsconfig.json" from warn to debug level
so it no longer clutters every build output.

9.4 — Document EXTENSIONS/IGNORE_DIRS Array→Set breaking change in
CHANGELOG. Add .toArray() convenience method and export ArrayCompatSet
type for consumers migrating from the pre-3.4 array API.
…ge duplication (#634)

- Move _versionWarned flag outside mismatch conditional to avoid
  redundant build_meta queries when versions match.
- Wrap SUPPORTED_EXTENSIONS in new Set() to avoid mutating the
  sibling module's export.
- Delete outgoing edges for barrel-only files before re-adding them
  to fileSymbols during incremental builds, preventing duplicate
  reexport edges.
@carlos-alm carlos-alm force-pushed the feat/dogfood-fixes-9.1-9.4 branch from 62852b8 to b60fbb7 Compare March 26, 2026 08:55
@carlos-alm
Copy link
Contributor Author

Both P2 items addressed in b60fbb7:

  1. _versionWarned redundant query — flag now set unconditionally after first check, preventing repeated build_meta queries when versions match.
  2. withArrayCompat mutationEXTENSIONS now wraps new Set(SUPPORTED_EXTENSIONS) to avoid mutating the sibling module's export.
  3. Bonus fix: barrel edge duplication in incremental builds — discovered that the reexport edge change caused duplicate edges during incremental rebuilds (barrel-only files' outgoing edges weren't deleted before buildEdges re-created them). Added deleteOutgoingEdges in resolve-imports.ts when barrel files are loaded into fileSymbols. This also fixes the CI test failures in incremental-parity.test.ts and incr-edge-gap.test.ts.
  4. Commitlint fix — lowercased "DB" to "db" in the commit subject to pass the subject-case rule.

@greptileai

Comment on lines +51 to 62
const deleteOutgoingEdges = db.prepare(
'DELETE FROM edges WHERE source_id IN (SELECT id FROM nodes WHERE file = ?)',
);
for (const { file: relPath } of barrelCandidates) {
if (fileSymbols.has(relPath)) continue;
const absPath = path.join(rootDir, relPath);
try {
const symbols = await parseFilesAuto([absPath], rootDir, engineOpts);
const fileSym = symbols.get(relPath);
if (fileSym) {
deleteOutgoingEdges.run(relPath);
fileSymbols.set(relPath, fileSym);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Edge deletion is not transactional with edge re-creation

deleteOutgoingEdges.run(relPath) commits immediately to the DB (outside any transaction), but the corresponding reexports edges aren't re-created until buildEdges runs its own db.transaction() later. If the process crashes or buildEdges throws between those two points, the barrel file's outgoing edges are gone from the DB — but because the reexports rows no longer exist, the file won't appear in barrelCandidates on the next incremental run either. The file silently disappears from the barrel graph until the user explicitly runs --no-incremental.

The cleanest fix is to push the deletion into the buildEdges transaction so delete and insert are atomic:

// In buildImportEdges, before inserting reexport edges for a barrel-only file:
if (isBarrelOnly) {
  db.prepare(
    'DELETE FROM edges WHERE source_id IN (SELECT id FROM nodes WHERE file = ?)',
  ).run(relPath);
}

If keeping the deletion in resolveImports is preferred, wrapping the loop body in a savepoint or a db.transaction() call would achieve the same atomicity guarantee.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant