fix(mcp): never serve a mis-sliced symbol body from a file that drifted from its index (#1474) (#1492)

codegraph_node / codegraph_explore read CURRENT bytes but slice them at
INDEXED line ranges; after an un-synced edit that slice can be a DIFFERENT
symbol's code served under the requested name — isError: false, introduced
by the 'verbatim … do not Read' guarantee. The watcher-based pending (#403)
and degraded (#876) banners cannot cover a project reached via projectPath:
cross-project instances have no watcher, by construction.

Freshness is now verified at the point of emission from data the index
already stores: one stat per rendered file (size + floored mtime, the sync
fast path's own test), sha256 content-hash compare only on stat mismatch
(so a touch/identical rewrite never false-positives), memoized briefly per
handler. On drift:

- codegraph_node: small files ship WHOLE and CURRENT (Read-parity, still
  no Read needed); large ones omit the body with an explicit notice
  steering to the tool's file-read mode or Read. Location/signature stay,
  flagged as possibly shifted.
- codegraph_explore: the whole-file render (already correct by
  construction) is kept and flagged; adaptive/skeleton/cluster slicing is
  disabled for drifted files — a too-big drifted file is omitted with a
  notice instead. The verbatim/do-not-Read header gains a per-file
  exception, and a trailing note flags shifted line references (flow,
  blast radius, symbol lists).

The guarantee itself is preserved: everything actually rendered is still
byte-accurate — drifted files ship whole or not at all, never as a
possibly-wrong slice. A re-sync of the target project restores normal
output (covered by test).

Adds __setLoadCodeGraphForTests (same seam pattern as __setFsWatchForTests)
so in-process tests can exercise a genuine cross-project open, which
vitest's transform cannot service through the lazy require.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-08-01 01:12:52 -05:00
committed by GitHub
co-authored by Claude Fable 5
parent 02c0e2c935
commit f2a5df34de
4 changed files with 418 additions and 3 deletions
+1
View File
@@ -15,6 +15,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- The background server's watchdog no longer kills a healthy server that is just waiting on a slow disk: like indexing already does, it now checks whether the database files are still making progress before concluding the process is stuck. Fewer spurious kills also means fewer leftover write-ahead logs. (#1431)
- `codegraph status` now shows the write-ahead log's size next to the database size and warns when killed sessions have left it oversized, and every line in the background server's log now carries a timestamp so kills and restarts can be placed in time. (#1431)
- On Windows, the Claude Code prompt hook written by `codegraph install` failed with "command not found" when hooks run through Git Bash, which needs the `.cmd` extension to find the launcher. The installer now writes the platform-correct command, and re-running `codegraph install` (or `codegraph upgrade`) repairs an existing install in place. (#1466)
- When a file changed on disk after its last index sync, `codegraph_node` and `codegraph_explore` could return a different symbol's code under the requested name — current file bytes cut at outdated line positions — while presenting it as verbatim, trustworthy source. This hit hardest on projects queried through `projectPath` (for example, sub-projects of a monorepo), which have no live file watcher to flag pending edits. Both tools now verify each file against the index before showing sliced code: an out-of-date file is either shown whole with its full current source, or its code is withheld with a clear "changed on disk" notice — never served as a wrong slice. A fresh re-index restores normal output automatically. Thanks @inth3shadows for the thorough report and verification passes. (#1474)
## [1.5.0] - 2026-07-21