Skip to content

sync prints "Already up to date" while it is actually resolving thousands of orphaned refs (misleading output) #1360

Description

@inth3shadows

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)

  1. codegraph init <any multi-file repo>
  2. Rebuild and interrupt it mid-resolution:
    codegraph index <repo> &      # kill it during the "Resolving refs" phase
    
  3. codegraph status <repo>

    ⚠ N references from an interrupted run are awaiting resolution — some callers/impact edges are missing. Run "codegraph sync" to resolve them.

  4. codegraph sync <repo> → prints Already up to date
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions