From cb7fb61e76c2762b3027d3bdd5968c4c75b9a80b Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Fri, 30 Oct 2026 13:47:59 +0000 Subject: [PATCH] fix(docs): agent and command lists match the code; worktree warning drops init -i (#3067) The warning for a git worktree answered from another checkout's index still said to run "codegraph init -i", a flag that has done nothing since init started indexing by default. Its one-line form is prepended to every read-tool result and codegraph_status embeds the long form, so both told the agent to build the index, which the server instructions rule out ("Indexing is the user's decision ... don't run it yourself"). The CLI's codegraph status now says: Run "codegraph init" in this worktree. What an agent reads (the read-tool notice, which also reaches it through the prompt hook and the explore/node CLI, and codegraph_status) says the user can run "codegraph init" there. Docs that no longer matched the code: - AGENTS.md listed 4 of the 11 installer targets, called a new one "a 5th agent", said the contract suite covers "all 4" targets, and listed 11 of the 24 subcommands. It now lists every target and subcommand, and names the hidden ones (serve --mcp, prompt-hook, and ui/web unless CODEGRAPH_UI=1). - README's Supported Agents section said no instructions file is written, but Claude Code, Codex CLI, Gemini CLI and opencode get the short CodeGraph section. Its Codex entry now says the Codex IDE extension reads the same config: $CODEX_HOME/config.toml (default ~/.codex/config.toml) for a global install, and .codex/config.toml, used only in a trusted project, for a local one. - README's WSL2 "Transport closed" entry named only the in-process fallback. The daemon also moves its socket to the temp directory when the project's filesystem can't host one. - init -i and -iv leftovers in internal docs, scripts, the add-lang skill and the repo's own Cursor rule, which now also leaves indexing to the user. Two stay on purpose: scripts/agent-eval/audit.sh can audit a published version older than 0.9.8, where init built the index only with -i (now commented there), and docs/benchmarks/codegraph-ab-matrix.md records a 0.9.4 run. Validation: - worktree-detection.test.ts: on main 61776927's worktree.ts and tools.ts, 4 of its 20 tests fail (the CLI wording, the agent wording, the read-tool notice and codegraph_status). With only the worktree.ts fix, the codegraph_status test still fails. All 20 pass here, and so do mcp-nested-repo-projectpath.test.ts's 13. - Full suite on this patch over 61776927 (CODEGRAPH_KERNEL_EXPECT=1, 4 workers): 815 files (809 passed, 6 skipped), 9608 tests passed, 0 failed, 86 skipped. - Rebased unchanged onto f67eafcb. Its three new commits share only CHANGELOG.md with this PR, in other bullets. On the rebased tree these pass (81 tests): worktree-detection, mcp-nested-repo-projectpath, and the new commits' default-export-declaration, rust-path-attribute-modules, rust-path-super-glob, search-special-characters and strip-comments. Reimplements #549 by @ashishpatel26, #651 by @GaoSSR, #885 and #886 by @Dashsoap, and #1083 by @zengwenliang416. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/add-lang/SKILL.md | 2 +- .cursor/rules/codegraph.mdc | 2 +- AGENTS.md | 8 ++--- CHANGELOG.md | 1 + README.md | 11 +++--- __tests__/worktree-detection.test.ts | 27 +++++++++++++-- docs/SEARCH_QUALITY_LOOP.md | 6 ++-- docs/design/callback-edge-synthesis.md | 2 +- .../dynamic-dispatch-coverage-playbook.md | 4 +-- scripts/add-lang/bench.sh | 2 +- scripts/agent-eval/audit.sh | 2 ++ src/mcp/tools.ts | 6 ++-- src/sync/worktree.ts | 34 ++++++++++++++----- 13 files changed, 77 insertions(+), 30 deletions(-) diff --git a/.claude/skills/add-lang/SKILL.md b/.claude/skills/add-lang/SKILL.md index 24ac69ef4..d71d15430 100644 --- a/.claude/skills/add-lang/SKILL.md +++ b/.claude/skills/add-lang/SKILL.md @@ -134,7 +134,7 @@ npm run build # tsc + copy-assets (copies any vendored *.wasm into di ``` Index a small sample repo and check extraction: ```bash -( cd && codegraph init -i ) +( cd && codegraph init ) node scripts/add-lang/verify-extraction.mjs ``` `verify-extraction.mjs` fails (exit 1) if the language isn't detected or only diff --git a/.cursor/rules/codegraph.mdc b/.cursor/rules/codegraph.mdc index 17d144a60..a51308252 100644 --- a/.cursor/rules/codegraph.mdc +++ b/.cursor/rules/codegraph.mdc @@ -20,5 +20,5 @@ Reach for `codegraph_explore` before grep/find or Read for any **structural** qu ### If `.codegraph/` doesn't exist -The MCP server returns "not initialized." Ask the user: *"I notice this project doesn't have CodeGraph initialized. Want me to run `codegraph init -i` to build the index?"* +The MCP tools say the project isn't indexed. Indexing is the user's decision: tell them they can run `codegraph init` to build the index, but don't run it yourself. diff --git a/AGENTS.md b/AGENTS.md index 77e5ed7c1..01752bd63 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -86,7 +86,7 @@ The public API surface is `src/index.ts` — the `CodeGraph` class wires all the - `src/sync/` — `FileWatcher` (native FSEvents/inotify/RDCW) with debounce + filter, and git-hook helpers. - `src/mcp/` — MCP server (`MCPServer`, `tools.ts`, `transport.ts`). `server-instructions.ts` is what the server returns in the MCP `initialize` response — keep it in sync with the user-facing tool guidance. - `src/installer/` — see below. -- `src/bin/codegraph.ts` — CLI (commander). Subcommands: `install`, `init`, `uninit`, `index`, `sync`, `status`, `query`, `files`, `context`, `affected`, `serve --mcp`. +- `src/bin/codegraph.ts` — CLI (commander). Subcommands: `install`, `uninstall`, `init`, `uninit`, `index`, `sync`, `status`, `unlock`, `query`, `explore`, `context`, `node`, `files`, `callers`, `callees`, `impact`, `affected`, `daemon`, `telemetry`, `upgrade`, `version`. Hidden from `--help`: `serve --mcp`, `prompt-hook`, and `ui`/`web` unless `CODEGRAPH_UI=1`. - `src/ui/` — terminal UI (shimmer progress, worker). - `src/ui-server/` -- read-only JSON API for the `codegraph ui` browser viewer (`api/`: `node`, `flow`, `map`, `screens`, `steps`, `deadcode`, `trails`, `program`, ...) plus static server; Svelte viewer lives in `ui/` (see `docs/design/codegraph-ui-design-spec.md`). `screens`/`steps`/`program` share one fold (`via`/`when` via `graph/branch-guards.ts`); `api/effects.ts` curates calls that leave the index; `api/route-roots.ts` names where a route's code starts. Derivations rendered by more than one surface belong in `src/graph/`, not `ToolHandler`. **Not released yet:** `codegraph ui` / `web` are refused (and hidden from `--help`) unless `CODEGRAPH_UI=1` is set — `src/bin/viewer-gate.ts`. Viewer changelog entries wait in `docs/viewer-launch-changelog.md`, not under `[Unreleased]`. At launch: delete the gate, move those entries back, drop the "not released yet" notes from `site/`. @@ -103,8 +103,8 @@ Defined in `src/types.ts`. Both extractors and resolvers must use these exact st `src/installer/` is the entry point for `codegraph install` (and the bare `codegraph`/`npx @colbymchenry/codegraph` invocation). Architecture: - `targets/registry.ts` lists every supported agent. -- `targets/types.ts` defines the `AgentTarget` interface — adding a 5th agent (Continue, Zed, Windsurf…) is **one new file in `targets/` + one entry in `registry.ts`**. Each target owns its config-file location and MCP-server JSON/TOML/JSONC writing. (Claude, Codex, Gemini and opencode also write a short instructions-file block — see below.) -- Current targets: `claude.ts`, `cursor.ts`, `codex.ts`, `opencode.ts`. +- `targets/types.ts` defines the `AgentTarget` interface — adding another agent (Continue, Zed, Windsurf…) is **one new file in `targets/` + one entry in `registry.ts`**. Each target owns its config-file location and MCP-server JSON/TOML/JSONC writing. (Claude, Codex, Gemini and opencode also write a short instructions-file block — see below.) +- Current targets: `claude.ts`, `cursor.ts`, `codex.ts`, `opencode.ts`, `hermes.ts`, `gemini.ts`, `antigravity.ts`, `kiro.ts`, `copilot-vscode.ts`, `copilot-cli.ts`, `copilot-jetbrains.ts`. - `targets/toml.ts` is a hand-rolled TOML serializer scoped to `[mcp_servers.codegraph]` (used by Codex). Sibling tables and `[[array_of_tables]]` are preserved verbatim. No new dependency. - opencode reads `opencode.jsonc` by default; the installer prefers existing `.jsonc`, falls back to `.json`, and creates `.jsonc` for greenfield installs. Edits are surgical via `jsonc-parser` so user comments and formatting survive install/re-install/uninstall round-trips. The MCP entry is OpenCode 2's native `mcp.servers.codegraph` with `disabled: false` and `codemode: false` (so `codegraph_explore` stays on the native tool list); a pre-#1698 `mcp.codegraph` + `enabled` entry is migrated on re-install and removed by uninstall. - `instructions-template.ts` holds `CODEGRAPH_INSTRUCTIONS_BLOCK`, a deliberately short marker-fenced (``/``) `## CodeGraph` block. The Claude, Codex, Gemini and opencode targets write it into their instructions file (`CLAUDE.md` / `~/.codex/AGENTS.md` / `~/.gemini/GEMINI.md` / `~/.config/opencode/AGENTS.md`) via `upsertInstructionsEntry`, and `uninstall` removes it. History: #529 removed the old full playbook because it duplicated the MCP `initialize` instructions; #704 brought back this small block because the instructions file reaches two audiences `initialize` cannot — Task-tool subagents and non-MCP harnesses (the `codegraph explore` CLI). Cursor and Kiro write no block; their `install` only strips one a previous install left behind. Keep the block to command names and the two surfaces; tool guidance itself still belongs in `server-instructions.ts`. @@ -174,7 +174,7 @@ Full methodology (feedback metrics, CLI contamination guard, Sonnet/`--effort hi Tests live in `__tests__/` and mirror the module they cover. Notable ones beyond the obvious: -- `installer-targets.test.ts` — parameterized contract suite across all 4 agent targets (see installer notes above). +- `installer-targets.test.ts` — parameterized contract suite across every registered target (`ALL_TARGETS`); see the installer notes above. - `evaluation/` — `runner.ts` + `test-cases.ts` exercise codegraph against synthetic projects and score the results; run via `npm run eval` (builds first). Not part of `npm test`. - `sqlite-backend.test.ts` / `node-sqlite-backend.test.ts` — pin that `node:sqlite` is the sole backend: `getBackend()` reports `node-sqlite` and the DB comes up in WAL. - `pr19-improvements.test.ts`, `frameworks-integration.test.ts` — regression coverage for specific past PRs/incidents; don't rename these, the names anchor to git history. diff --git a/CHANGELOG.md b/CHANGELOG.md index d7b176088..7ef6b7e4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - When CodeGraph can't open a project's database, it now says what went wrong: SQLite's error, the file's path, and what to check, such as another program holding the file open, a folder you can't write to, or a network share. Before, every such failure read "CodeGraph requires node:sqlite (Node.js 22.5+)", and an agent was told no project was loaded. That hint now appears only when Node really can't load its built-in SQLite, a case that used to end in an unhandled error instead. - On Windows, a project at the root of a drive, such as a mapped network drive like `Z:\`, a `subst` drive or the root of a network share, now indexes. Before, every file was refused as "Path traversal blocked", so the index came out empty, and the code of such a project couldn't be shown either. Thanks @Kamilslaoui93. - On Windows, a git worktree inside your main checkout, such as one under `.claude/worktrees/`, is now recognized however its path is written: with a lowercase drive letter, as VS Code and Cursor pass it, in different capitals, through a `subst` drive or by its short 8.3 name. Before, `codegraph status` didn't warn that the worktree was answered from the main checkout's index, and an agent working there was told the worktree wasn't indexed and to stop using CodeGraph for it. Thanks @nk33-dev. +- When a git worktree is answered from another checkout's index, `codegraph status` now suggests plain `codegraph init` in the worktree, without the `-i` flag that no longer does anything, and the warning your agent sees, with its results and in `codegraph_status`, now says you can run it there instead of telling the agent to build the index itself. Thanks @GaoSSR. - `codegraph upgrade` no longer wipes your agent instructions file, such as a global `AGENTS.md`, `CLAUDE.md` or `GEMINI.md`, when it refreshes CodeGraph's section in it: a stray `` line above that section, like one left behind when part of an older section was deleted by hand, made the refresh replace everything in between, often the whole file. CodeGraph now rewrites only its own section, in `codegraph install` and `codegraph uninstall` too, and keeps everything around it exactly as it was, Windows line endings included. Thanks @pzaj2 for the report. (#2506) - `codegraph install`, `upgrade` and `uninstall` now write through an instructions or config file that is a symbolic link, such as a `~/.codex/AGENTS.md` or `~/.claude.json` linked from your dotfiles, instead of replacing the link with a copy: the shared file gets CodeGraph's settings, uninstall takes them out again, and the link stays in place. A link CodeGraph can't write through, like one to a read-only file or into a folder that doesn't exist, is now reported by name and left alone, and an upgrade still refreshes your other agents. Thanks @jguerra6 for the report, and @meganemura and @danusha2345 for the first fixes. (#2721) - `codegraph install` and `upgrade` no longer break Codex's `config.toml` when CodeGraph's `[mcp_servers.codegraph]` entry is written differently from how CodeGraph writes it, such as indented, with spaces or quotes inside the brackets, or with Windows line endings: the entry is now updated in place, where before a second copy was added and Codex could load none of the file. A file already broken that way is repaired on the next install or upgrade, an example of the entry inside a multiline setting such as `developer_instructions` is no longer mistaken for it, uninstall removes the entry however it is written, and an entry you wrote with dotted keys or as an inline table is left as you wrote it. When your `mcp_servers` settings are one inline table, CodeGraph now says it can't add itself instead of breaking the file. Thanks @dencoseca for the report, and @danusha2345 and @rudycelekli for the first fixes. (#2562) diff --git a/README.md b/README.md index baac93178..707329655 100644 --- a/README.md +++ b/README.md @@ -794,12 +794,15 @@ See [Get Started](#get-started) for the one-line install commands. ## Supported Agents The interactive installer auto-detects and configures each of these — wiring up -the MCP server (which delivers its own usage guidance, so no instructions file -is written): +the MCP server, which delivers its own usage guidance. For Claude Code, Codex +CLI, Gemini CLI and opencode it also writes a short marker-fenced CodeGraph +section into the agent's instructions file (`CLAUDE.md` / `AGENTS.md` / +`GEMINI.md`), so subagents and non-MCP agents learn the `codegraph explore` +command: - **Claude Code** - **Cursor** -- **Codex CLI** +- **Codex CLI** — the Codex IDE extension reads the same config: a global install writes `$CODEX_HOME/config.toml` (default `~/.codex/config.toml`), and a local install writes `.codex/config.toml`, which Codex uses only in a project you've marked as trusted - **opencode** — MCP entry is OpenCode 2's `mcp.servers.codegraph` with `codemode: false` (keeps `codegraph_explore` on the native tool list; `codegraph install` migrates the older `mcp.codegraph` shape) - **Hermes Agent** - **Gemini CLI** @@ -892,7 +895,7 @@ Framework routing is validated the same way, on a canonical app per framework: E **Two `codegraph serve --mcp` on one project fight over the index / auto-sync stops** — CodeGraph allows one live MCP *writer* per project (the shared background daemon, or a single direct-mode process). Extra clients should proxy to that daemon. If you set `CODEGRAPH_NO_DAEMON=1`, run only one `serve --mcp` for that project; a second instance exits with a clear writer-lock error (see `writer.pid` under `.codegraph/`). Prefer leaving the daemon enabled so multiple MCP hosts share one watcher. -**MCP tool calls fail with `Transport closed` while `codegraph status`/`sync` are healthy** — almost always WSL2 with the project on a Windows drive (a `/mnt/c` or `/mnt/d` path), where the local socket CodeGraph uses to share one background server across sessions is unreliable. CodeGraph now falls back to serving the session in-process instead of dropping the connection, but if you still hit it, set `CODEGRAPH_NO_DAEMON=1` in your MCP server's environment to skip the shared server entirely (each session runs in its own process). Moving the project onto the Linux-native filesystem (e.g. under `~/` instead of `/mnt/`) restores the shared server. +**MCP tool calls fail with `Transport closed` while `codegraph status`/`sync` are healthy** — almost always WSL2 with the project on a Windows drive (a `/mnt/c` or `/mnt/d` path), where the local socket CodeGraph uses to share one background server across sessions is unreliable. CodeGraph works around this itself now: when the project's filesystem can't host that socket, the shared server puts it in the system temp directory instead, and when the shared server still can't be reached, or drops, the session is served in-process instead of losing the connection. If you still hit it, set `CODEGRAPH_NO_DAEMON=1` in your MCP server's environment to skip the shared server entirely (each session runs in its own process). Moving the project onto the Linux-native filesystem (e.g. under `~/` instead of `/mnt/`) restores the shared server. **Missing symbols** — The MCP server auto-syncs on save (wait a couple seconds). Run `codegraph sync` manually if needed. Check that the file's language is supported and isn't inside a `.gitignore`d or default-excluded directory (e.g. `node_modules`, `dist`). diff --git a/__tests__/worktree-detection.test.ts b/__tests__/worktree-detection.test.ts index a5d9be2c9..5266aa826 100644 --- a/__tests__/worktree-detection.test.ts +++ b/__tests__/worktree-detection.test.ts @@ -20,6 +20,7 @@ import { detectWorktreeIndexMismatch, nestedRepositoryBelow, worktreeMismatchWarning, + worktreeMismatchNotice, gitWorktreeRoot, gitCommonDir, } from '../src/sync/worktree'; @@ -102,10 +103,29 @@ describe('detectWorktreeIndexMismatch (issue #155)', () => { const msg = worktreeMismatchWarning(detectWorktreeIndexMismatch(worktree, mainRepo)!); expect(msg).toContain(real(worktree)); expect(msg).toContain(real(mainRepo)); - expect(msg).toContain('codegraph init'); + expect(msg).toContain('Run "codegraph init" in this worktree'); + expect(msg).not.toContain('init -i'); + }); + + it('words the fix as the user\'s option when an agent reads it', () => { + const m = detectWorktreeIndexMismatch(worktree, mainRepo)!; + expectAgentAdvice(worktreeMismatchWarning(m, 'agent')); + expectAgentAdvice(worktreeMismatchNotice(m)); }); }); +/** + * What an agent is told about a borrowed index. Indexing is the user's + * decision (the server instructions tell the agent not to run `codegraph init` + * itself), so the text says the user can build a worktree-local index, never + * tells the agent to, and doesn't name the `-i` flag, which does nothing now. + */ +function expectAgentAdvice(text: string): void { + expect(text).toContain('The user can run "codegraph init" in this worktree'); + expect(text).not.toContain('Run "codegraph init'); + expect(text).not.toContain('init -i'); +} + /** * Windows spells one directory several ways. VS Code and Cursor pass a * lowercase drive letter (`d:\repo`), a `subst` drive is a second name for a @@ -220,7 +240,7 @@ describe('worktree mismatch surfaces on hot read tools (issue #155)', () => { expect(res.isError).toBeFalsy(); expect(text).toContain('different git worktree'); expect(text).toContain(real(worktree)); - expect(text).toContain('codegraph init'); + expectAgentAdvice(text); }); it('does NOT prefix when the default project is the main checkout itself', async () => { @@ -235,6 +255,7 @@ describe('worktree mismatch surfaces on hot read tools (issue #155)', () => { const text = res.content[0].text; expect(text).toContain('different git working tree'); expect(text).toContain(real(worktree)); + expectAgentAdvice(text); }); it('caches detection — a later tool call needs no further git spawn', async () => { @@ -337,7 +358,7 @@ describe('worktree mismatch verdict re-resolves when the index root changes (iss * super-repo descends into its submodules and gitlinked clones, so a query run * from inside one resolves up to the parent index — which genuinely contains * that nested repo's symbols. The warning's premise is false there, and its - * "run codegraph init -i" advice would fragment the unified index. (#1031, #1033) + * "codegraph init" advice would fragment the unified index. (#1031, #1033) */ describe('detectWorktreeIndexMismatch — nested repos covered by the parent index (#1031, #1033)', () => { let parent: string; // super-repo that owns the .codegraph index diff --git a/docs/SEARCH_QUALITY_LOOP.md b/docs/SEARCH_QUALITY_LOOP.md index 97d57dedf..3c70027a9 100644 --- a/docs/SEARCH_QUALITY_LOOP.md +++ b/docs/SEARCH_QUALITY_LOOP.md @@ -11,10 +11,10 @@ A language is NOT verified until an LLM can reliably use CodeGraph's MCP tools t ```bash npm run build rm -rf /.codegraph -node dist/bin/codegraph.js init -iv +node dist/bin/codegraph.js init -v ``` -The `-iv` flag gives verbose output showing extraction progress, node/edge counts, and timing. +`init` builds the index; the `-v` flag gives verbose output showing extraction progress, node/edge counts, and timing. ### 2. Quick sanity check @@ -470,7 +470,7 @@ test().catch(console.error); ```bash npm run build rm -rf /.codegraph -node dist/bin/codegraph.js init -iv +node dist/bin/codegraph.js init -v # Re-run the failing tests from above ``` diff --git a/docs/design/callback-edge-synthesis.md b/docs/design/callback-edge-synthesis.md index a915dc6a3..58fa2394b 100644 --- a/docs/design/callback-edge-synthesis.md +++ b/docs/design/callback-edge-synthesis.md @@ -37,7 +37,7 @@ We synthesize `dispatcher → callback` edges that static parsing misses. It wor ```bash npm run build rm -rf /tmp/codegraph-corpus/excalidraw/.codegraph -( cd /tmp/codegraph-corpus/excalidraw && codegraph init -i ) +( cd /tmp/codegraph-corpus/excalidraw && codegraph init ) # synthesized edges (provenance='heuristic', metadata.synthesizedBy in {callback,event-emitter,…,http-client,queue-job,event-bus}): sqlite3 /tmp/codegraph-corpus/excalidraw/.codegraph/codegraph.db \ "select s.name||' → '||t.name||' '||coalesce(e.metadata,'') from edges e \ diff --git a/docs/design/dynamic-dispatch-coverage-playbook.md b/docs/design/dynamic-dispatch-coverage-playbook.md index 8ec0a8e38..8224fcaef 100644 --- a/docs/design/dynamic-dispatch-coverage-playbook.md +++ b/docs/design/dynamic-dispatch-coverage-playbook.md @@ -150,7 +150,7 @@ question and a real repo (add to `.claude/skills/agent-eval/corpus.json`). Examp ### Step 2 — Measure the hole (deterministic, no agent) ```bash -rm -rf /.codegraph && ( cd && codegraph init -i ) +rm -rf /.codegraph && ( cd && codegraph init ) node scripts/agent-eval/probe-trace.mjs # does the flow break? where? node scripts/agent-eval/probe-node.mjs # trail: is the next hop missing? ``` @@ -229,7 +229,7 @@ were found). Confirm it's dynamic by reading the break symbol's body. | `sqlite3 /.codegraph/codegraph.db` | direct edge/node inspection (provenance, metadata, counts) | Probe scripts use the built `dist/` — run `npm run build` first. Reindex after any -extraction or resolution change (`rm -rf /.codegraph && codegraph init -i`) — the +extraction or resolution change (`rm -rf /.codegraph && codegraph init`) — the synthesizer/resolvers run at index time. Test fixtures: keep a tiny per-pattern fixture (see `/tmp/cb-fixture/bus.js`; **move into `__tests__/`** when shipping). diff --git a/scripts/add-lang/bench.sh b/scripts/add-lang/bench.sh index 08dcd2ade..cd7637eb6 100755 --- a/scripts/add-lang/bench.sh +++ b/scripts/add-lang/bench.sh @@ -59,7 +59,7 @@ fi # 2. Wipe + index with the binary under test. echo "→ wiping .codegraph and indexing" rm -rf "$REPO/.codegraph" -( cd "$REPO" && codegraph init -i ) || { echo "indexing failed"; exit 1; } +( cd "$REPO" && codegraph init ) || { echo "indexing failed"; exit 1; } # 3. Verify extraction (cheap guard before the paid A/B). echo "→ verifying extraction" diff --git a/scripts/agent-eval/audit.sh b/scripts/agent-eval/audit.sh index 979e88e62..380bdae02 100755 --- a/scripts/agent-eval/audit.sh +++ b/scripts/agent-eval/audit.sh @@ -49,6 +49,8 @@ fi # 3. Wipe + re-index with THIS version (the index must be built by the same # binary that serves it — different versions extract differently). +# Keep -i: may predate 0.9.8, where `init` built the index only +# with it. Newer versions index by default and still accept the flag. echo "→ [3/4] wiping .codegraph and re-indexing with $ACTUAL" rm -rf "$REPO/.codegraph" ( cd "$REPO" && codegraph init -i ) || { echo "indexing failed"; exit 1; } diff --git a/src/mcp/tools.ts b/src/mcp/tools.ts index 438d989d7..e92b09f54 100644 --- a/src/mcp/tools.ts +++ b/src/mcp/tools.ts @@ -8445,7 +8445,9 @@ export class ToolHandler { // (e.g. the server resolved up from a nested worktree to the main checkout). // Queries then reflect that tree's branch, not the worktree being edited. // status shows the verbose, multi-line form; the read tools get the compact - // one-liner via withWorktreeNotice. Both share the cached detection. + // one-liner via withWorktreeNotice. Both share the cached detection, and + // both are worded for the agent: the user can index the worktree, the + // agent doesn't. const mismatch = this.worktreeMismatchFor(args.projectPath as string | undefined); const lines: string[] = [ @@ -8453,7 +8455,7 @@ export class ToolHandler { '', ]; if (mismatch) { - lines.push(`> ⚠ ${worktreeMismatchWarning(mismatch).replace(/\n/g, '\n> ')}`, ''); + lines.push(`> ⚠ ${worktreeMismatchWarning(mismatch, 'agent').replace(/\n/g, '\n> ')}`, ''); } lines.push( `**Files indexed:** ${stats.fileCount}`, diff --git a/src/sync/worktree.ts b/src/sync/worktree.ts index a3b241076..e5a577061 100644 --- a/src/sync/worktree.ts +++ b/src/sync/worktree.ts @@ -111,8 +111,8 @@ export function detectWorktreeIndexMismatch( // and gitlinked clones, so a query run from inside one resolves up to the // parent index — whose graph *does* contain that nested repo's files. The // warning's premise ("results are a different branch; symbols changed only - // here are missing") is false there, and its "run codegraph init -i" advice - // would needlessly fragment the unified workspace index. A genuine borrowed + // here are missing") is false there, and its "codegraph init" advice would + // needlessly fragment the unified workspace index. A genuine borrowed // worktree and the index root are the SAME repository (they share a git // common dir); a submodule/embedded clone is a DIFFERENT repository and does // not — so suppress only when the two clearly differ. (#1031, #1033) @@ -207,15 +207,32 @@ function directoryIdentity(p: string): string { return process.platform === 'win32' ? real.toLowerCase() : real; } -/** One-line-per-fact warning describing a detected mismatch. */ -export function worktreeMismatchWarning(m: WorktreeIndexMismatch): string { +/** + * The way out of a borrowed index: one built in the worktree itself. A person + * at the CLI is told to build it. An agent is told the user can: indexing is + * the user's decision, and the server instructions tell the agent not to run + * `codegraph init` itself, so a tool result must not tell it to. + */ +function worktreeIndexAdvice(audience: 'user' | 'agent'): string { + return audience === 'agent' + ? 'The user can run "codegraph init" in this worktree for a worktree-local index.' + : 'Run "codegraph init" in this worktree for a worktree-local index.'; +} + +/** + * One-line-per-fact warning describing a detected mismatch: `codegraph status` + * prints it for the user, and `codegraph_status` shows the agent's wording. + */ +export function worktreeMismatchWarning( + m: WorktreeIndexMismatch, + audience: 'user' | 'agent' = 'user', +): string { return ( `This CodeGraph index belongs to a different git working tree.\n` + ` Running in: ${m.worktreeRoot}\n` + ` Index from: ${m.indexRoot}\n` + `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.` + `symbols changed only here are missing. ${worktreeIndexAdvice(audience)}` ); } @@ -223,13 +240,14 @@ export function worktreeMismatchWarning(m: WorktreeIndexMismatch): string { * Compact, single-line variant for prefixing a tool's result. Read tools * return their answer inline, so the heads-up has to ride on the same payload * the agent is already reading — a multi-line block would bury the result. + * Its reader is an agent, through MCP, the prompt hook or the `codegraph + * explore` and `codegraph node` CLI. */ export function worktreeMismatchNotice(m: WorktreeIndexMismatch): string { return ( `⚠ CodeGraph results below come from a different git worktree (${m.indexRoot}), ` + `not where you're working (${m.worktreeRoot}) — they may reflect another branch, ` + - `and symbols changed only here are missing. Run "codegraph init -i" here for a ` + - `worktree-local index.` + `and symbols changed only here are missing. ${worktreeIndexAdvice('agent')}` ); }