Skip to content

feat: warn when a query borrows another git worktree's index#312

Open
shinju4n wants to merge 1 commit into
colbymchenry:mainfrom
shinju4n:feat/warn-worktree-index-mismatch
Open

feat: warn when a query borrows another git worktree's index#312
shinju4n wants to merge 1 commit into
colbymchenry:mainfrom
shinju4n:feat/warn-worktree-index-mismatch

Conversation

@shinju4n
Copy link
Copy Markdown

feat: warn when a query borrows another git worktree's index

Refs #155

Problem

CodeGraph resolves a project's index by walking up to the nearest .codegraph/
(findNearestCodeGraphRoot). That walk is unaware of git worktrees.

When a worktree is created inside the main checkout — which is exactly what
several agent tools do (e.g. placing worktrees under gitignored paths like
.claude/worktrees/<name>/) — a command run from the worktree walks up and
silently resolves the main checkout's index. Every query then returns
results from the main tree's code (usually a different branch) rather than the
worktree the user is actually editing. Symbols added or changed only in the
worktree are invisible, and nothing tells the user this is happening.

This is the silent footgun behind #155. (Note: a single shared index cannot
be correct for multiple worktrees at once — each can be on a different branch —
so the right primitive is to make the situation visible, then let users opt into
a worktree-local index.)

What this PR does

Adds detection + a non-fatal warning, scoped intentionally small:

  • src/sync/worktree.tsdetectWorktreeIndexMismatch(startPath, indexRoot)
    compares the caller's git working-tree root against the resolved index root via
    git rev-parse --show-toplevel. Returns null (no warning) when: not a git
    repo / git unavailable, the index lives in the caller's own tree, or the index
    root is a plain (non-worktree) ancestor directory. So non-worktree and
    monorepo-subdir layouts are unaffected.
  • codegraph status (CLI) — prints the warning, and adds a
    worktreeMismatch field to --json output.
  • codegraph_status (MCP tool) — prepends the warning to the status text.

Example (status run inside a nested worktree):

Project: /repo
⚠ This CodeGraph index belongs to a different git working tree.
  Running in: /repo/wt
  Index from: /repo
Results reflect that tree's code (often a different branch), not this worktree —
symbols changed only here are missing. Run "codegraph init -i" in this worktree
for a worktree-local index.

Tests

__tests__/worktree-detection.test.ts — drives real git worktree add
(no mocking, matching the existing mcp-roots.test.ts style):

  • flags a nested worktree borrowing the main index
  • returns null for same-tree, subdirectory, non-git, and plain-ancestor cases
  • gitWorktreeRoot reports each tree distinctly
  • warning text names both trees and the fix

tsc build passes. Verified end-to-end with the bundled FTS5 Node runtime:
the warning fires in a worktree and is absent in the main checkout.

Deliberately out of scope (happy to follow up per your preference)

  • Surfacing the warning on every tool (search/context/…), not just status.
  • An opt-in auto-init path so a nested worktree builds its own local index
    (the natural next step once the detection primitive lands).

I kept the surface area minimal to make review easy — glad to extend in whatever
direction you'd prefer for #155.

When a worktree is nested inside the main checkout (e.g. tools that place
worktrees under gitignored paths like .claude/worktrees/<name>/), the
nearest-.codegraph walk resolves UP to the main checkout's index. Queries
then silently return the main branch's code instead of the worktree being
edited — symbols changed only in the worktree are invisible.

Add detectWorktreeIndexMismatch() (src/sync/worktree.ts) which compares the
caller's git working-tree root against the resolved index root via
'git rev-parse --show-toplevel', and surface a non-fatal warning in both
'codegraph status' (CLI, incl. --json) and the codegraph_status MCP tool.
Detection is best-effort: no git / not a repo / index in a plain ancestor
all report no mismatch, so existing non-worktree and monorepo-subdir layouts
are unaffected.

Refs colbymchenry#155

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant