fix: v0.45.1 — refuse multi-repo workspace parent (cross-project index bleed)#45
Merged
Merged
Conversation
…x bleed) start.sh always passes an explicit project root, so startServer's git-root narrowing (the `!explicitRoot` branch) never runs. When the session starts from a non-git workspace parent nesting several project repos (e.g. /work/loom holding token-pilot, loom-host, aimux), the raw parent was used verbatim and ast-index indexed every sibling into one index — find_usages / read_symbol then bled matches across unrelated projects. isDangerousRoot only caught system/home dirs, so the parent slipped through. Add isMultiRepoParent(root) guard (core/validation.ts): a non-git dir with >=2 immediate child git repos. On match, ast-index is disabled (skipAstIndex) and a warning tells the user to set CLAUDE_PROJECT_DIR to the specific project — fail safe instead of bleeding. Wired into startServer and the server.ts MCP-roots auto-detect. Single-repo roots, monorepos, and roots that are themselves a git repo are unaffected. Tests: tests/core/multi-repo-parent.test.ts (7 cases). tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a Claude Code session is launched from a non-git workspace parent that nests several project repos — e.g.
/home/.../loomholdingtoken-pilot,loom-host,aimux,task-jorunal— token-pilot indexed all of them into one ast-index. Symbol lookups then bled across projects:find_usages/read_symbolreturned matches from the wrong repo, orsymbol not found.Root cause
start.shalways passes an explicit root:So in
startServerexplicitRootis always truthy → the entire git-root narrowing block (if (!explicitRoot)) is skipped and the raw arg is used verbatim. When that arg is a workspace parent (not a git repo),isDangerousRootdoesn't catch it (it only guards system/home dirs), so ast-index scans every sibling repo.Fix
New guard
isMultiRepoParent(root)incore/validation.ts: returns true for a non-git directory with >=2 immediate child git repos. On match:skipAstIndexis set (ast-index disabled) — fail safe instead of bleeding.CLAUDE_PROJECT_DIRto the specific project.Wired into:
startServer(src/index.ts) —skipAstIndex+ warning.server.tsMCP-roots auto-detect (Strategy 1) — a client-reported parent is rejected too. Strategy 2 (git toplevel) is inherently single-repo, left untouched.Unaffected: single-repo roots, monorepos, and roots that are themselves a git repo (submodules/vendored repos underneath stay intentional).
Tests
tests/core/multi-repo-parent.test.ts— 7 cases: >=2 child repos -> true; one/zero child repos -> false; root is itself a repo -> false;.git-as-file (submodule/worktree) counted; missing path / empty string -> false.tsc --noEmitclean.🤖 Generated with Claude Code