Version: 1.4.1
Summary
After an interrupted index leaves orphaned unresolved_refs, a bare codegraph sync correctly runs the orphan sweep (added in #1191) and resolves the pending refs — but the CLI still prints "Already up to date", because the sweep's work is not reflected in SyncResult. A user reasonably concludes sync did nothing and reaches for a full codegraph index unnecessarily; downstream tooling built on callers/callees ends up documenting "only a full index fixes it," which is wrong.
Reproduction (deterministic)
codegraph init <any multi-file repo>
- Rebuild and interrupt it mid-resolution:
codegraph index <repo> & # kill it during the "Resolving refs" phase
codegraph status <repo> →
⚠ N references from an interrupted run are awaiting resolution — some callers/impact edges are missing. Run "codegraph sync" to resolve them.
codegraph sync <repo> → prints Already up to date
codegraph status <repo> → the pending count has dropped by thousands — sync did sweep.
Observed on a 173-file repo with full extraction (so there were genuinely zero file changes): one Already up to date sync took pending refs from 23,960 → 8,948. It was silently doing ~15k refs of work while reporting nothing.
Root cause
The orphan sweep runs in src/index.ts (getUnresolvedReferencesCount() / resolveReferencesBatched, ~lines 887-892) after file-change detection. But SyncResult (src/extraction/index.ts:110-115) carries only file counters (filesAdded/filesModified/nodesUpdated) — there is no field for swept/resolved refs. So totalChanges === 0, and src/bin/codegraph.ts:883 prints Already up to date even when the sweep resolved thousands of refs.
Impact
Undermines trust in sync as the recovery command — which is the whole point of #1191. Users and downstream tool authors conclude the wedged index needs a full reindex.
Suggested fixes (tradeoffs)
- A — report the swept count (most correct): add a
refsResolved (or orphansSwept) field to SyncResult, set it from the sweep, and print e.g. Recovered interrupted index: resolved N pending references. Cost: one type field + threading the count out of the sweep.
- B — minimal, no type change: compare
getUnresolvedReferencesCount() before/after the sweep and, if it dropped, print a distinct line even when file changes are 0. Cost: two COUNT queries; leaves SyncResult untouched.
- C — cheapest, message-only: only print
Already up to date when nothing (files or orphans) changed; otherwise print that orphans were resolved. Least informative but a one-line fix.
I would lean A — the count is genuinely useful signal and the sweep already knows it.
Version: 1.4.1
Summary
After an interrupted index leaves orphaned
unresolved_refs, a barecodegraph synccorrectly runs the orphan sweep (added in #1191) and resolves the pending refs — but the CLI still prints "Already up to date", because the sweep's work is not reflected inSyncResult. A user reasonably concludessyncdid nothing and reaches for a fullcodegraph indexunnecessarily; downstream tooling built oncallers/calleesends up documenting "only a full index fixes it," which is wrong.Reproduction (deterministic)
codegraph init <any multi-file repo>codegraph status <repo>→codegraph sync <repo>→ printsAlready up to datecodegraph status <repo>→ the pending count has dropped by thousands —syncdid sweep.Observed on a 173-file repo with full extraction (so there were genuinely zero file changes): one
Already up to datesync took pending refs from 23,960 → 8,948. It was silently doing ~15k refs of work while reporting nothing.Root cause
The orphan sweep runs in
src/index.ts(getUnresolvedReferencesCount()/resolveReferencesBatched, ~lines 887-892) after file-change detection. ButSyncResult(src/extraction/index.ts:110-115) carries only file counters (filesAdded/filesModified/nodesUpdated) — there is no field for swept/resolved refs. SototalChanges === 0, andsrc/bin/codegraph.ts:883printsAlready up to dateeven when the sweep resolved thousands of refs.Impact
Undermines trust in
syncas the recovery command — which is the whole point of #1191. Users and downstream tool authors conclude the wedged index needs a full reindex.Suggested fixes (tradeoffs)
refsResolved(ororphansSwept) field toSyncResult, set it from the sweep, and print e.g.Recovered interrupted index: resolved N pending references. Cost: one type field + threading the count out of the sweep.getUnresolvedReferencesCount()before/after the sweep and, if it dropped, print a distinct line even when file changes are 0. Cost: two COUNT queries; leavesSyncResultuntouched.Already up to datewhen nothing (files or orphans) changed; otherwise print that orphans were resolved. Least informative but a one-line fix.I would lean A — the count is genuinely useful signal and the sweep already knows it.