A long-lived MCP server (the shared daemon) cached both the project handle
(projectCache) and the worktree-mismatch verdict (worktreeMismatchCache) for
its whole lifetime — cleared only on shutdown — keyed off the input path and
never re-checked. So a worktree path first resolved BEFORE it had its own
.codegraph/ — when the walk-up reached the main checkout — stayed pinned to
the main checkout: every query kept hitting the wrong index and every result
carried a false "this index belongs to a different git working tree" warning,
until the server restarted. The CLI was correct (fresh process per run);
re-indexing didn't help.
- getCodeGraph: re-resolve findNearestCodeGraphRoot on every call (cheap stat
walk, no git, no reopen) and cache the open DB by RESOLVED ROOT only. Drops
the input-path short-circuit that pinned the first resolution, and the
double-keying (which also double-closed each instance in closeAll()).
- worktreeMismatchFor: key the verdict on (startPath, indexRoot) so a changed
index root recomputes instead of serving the stale "borrowed the parent's
index" verdict.
Adds a regression test that fails pre-fix (the stale warning survives the
index-root flip); the existing "no further git spawn" caching test still
passes. The query-staleness half (a second project opened through the handler)
isn't unit-testable under vitest, so it was validated with a dist A/B.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>