An indexing run killed mid-"Resolving refs" (crash, Ctrl-C, the #1122
watchdog kill) left the refs it never reached parked in unresolved_refs.
The git-scoped sync fast path only re-resolves changed files' refs, so
those files' call edges were missing permanently — a too-small blast
radius clustering by package/module (the #1187 field report: 3 of 10
caller files for a Spring @Resource-injected method) — until a full
re-index.
- sync() now sweeps leftover unresolved refs with the batched resolver
after its scoped pass, including on no-change syncs, so a bare
`codegraph sync` recovers a wedged index (and heals pre-fix indexes
on the first post-upgrade sync)
- the scoped pass deletes unresolvable rows too (parity with the
batched path), making "rows at rest" a sound orphan signal
- drop the batched loop's early break that abandoned all later batches
when one batch was all-unresolvable (its rows WERE consumed — that
early stop could orphan the rest of the table at init)
- surface the state: `codegraph status` warns, `status --json` gains
index.pendingRefs, and MCP codegraph_status tells agents the blast
radius is incomplete until the next sync
Verified end-to-end on a 2,414-file synthetic Spring repo: SIGKILL
mid-resolution reproduces the reporter's exact 3-of-10-callers state;
a bare sync now heals it to 10/10 with the edge count converging to
the clean-init total; a healthy-index sync stays a no-op.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>