diff --git a/.claude/skills/gitnexus-debugging/SKILL.md b/.claude/skills/gitnexus-debugging/SKILL.md index 0f2385477..beebb532e 100644 --- a/.claude/skills/gitnexus-debugging/SKILL.md +++ b/.claude/skills/gitnexus-debugging/SKILL.md @@ -15,31 +15,35 @@ description: "Use when the user is debugging a bug, tracing an error, or asking ## Bind the repository first -A root cause traced in the wrong repository is a wrong root cause. Call -`list_repos {}`. With one indexed repository, use the examples below as -written. With more than one, pass `repo` explicitly on every call — an omitted -`repo` errors, or silently resolves to a configured default — and stop and ask -if the intended repository is ambiguous. This matters most for `cypher`, whose -statement carries no in-band hint of which database it ran against. See -`references/repository-identity.md`. +A root cause traced in the wrong repository is a wrong root cause. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. This matters most for `cypher`, whose +statement carries no in-band hint of which database it ran against. + +A stale index describes the code from before your bug, so refresh before +trusting a trace, and state the repository and index freshness with the +diagnosis. ## Workflow ``` -0. list_repos {} → Bind repo (and worktree) -1. query({search_query: ""[, repo: ""]}) → Find related execution flows -2. context({name: ""[, repo: ""]}) → See callers/callees/processes +0. list_repos {} → Bind repo +1. query({search_query: ""}) → Find related execution flows +2. context({name: ""}) → See callers/callees/processes 3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow -4. cypher({statement: "MATCH path..."[, repo: ""]}) → Custom traces if needed +4. cypher({statement: "MATCH path..."}) → Custom traces if needed ``` -> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in the bound checkout. -> A stale index describes the code before your bug; refresh before trusting a trace. +> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. ## Checklist ``` -- [ ] list_repos {} — bind repo; explicit repo when total > 1, ask if ambiguous +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] Understand the symptom (error message, unexpected behavior) - [ ] query for error text or related code - [ ] Identify the suspect function from returned processes @@ -58,7 +62,7 @@ statement carries no in-band hint of which database it ran against. See | Wrong return value | `context` on the function → trace callees for data flow | | Intermittent failure | `context` → look for external calls, async deps | | Performance issue | `context` → find symbols with many callers (hot paths) | -| Recent regression | `detect_changes` to see what your changes affect — pass `worktree` if your changes are in a linked worktree | +| Recent regression | `detect_changes` to see what your changes affect — pass `worktree` for a linked worktree | | "How does A reach B?" | `trace` between the two symbols — shortest call chain in one call | ## Tools @@ -84,11 +88,9 @@ context({name: "validatePayment", repo: "my-app"}) Cypher text itself names no repository, so the result is unattributable without it: -``` -cypher({repo: "my-app", statement: ` +```cypher MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"}) RETURN [n IN nodes(path) | n.name] AS chain -`}) ``` **trace** — shortest call chain between two symbols ("how does A reach B?"), one call instead of chaining `context` hops: diff --git a/.claude/skills/gitnexus-debugging/references/repository-identity.md b/.claude/skills/gitnexus-debugging/references/repository-identity.md deleted file mode 100644 index b2f1adb93..000000000 --- a/.claude/skills/gitnexus-debugging/references/repository-identity.md +++ /dev/null @@ -1,86 +0,0 @@ -# Repository and worktree identity - -This file is the shared identity contract for the per-repository GitNexus -skills. `gitnexus-exploring`, `gitnexus-debugging`, `gitnexus-impact-analysis` -and `gitnexus-refactoring` carry byte-identical copies so each skill works -without relying on another skill's install. - -Two independent questions must be answered before any graph or diff result can -be trusted, and a wrong answer to either produces a well-formed report about -code you were not asking about: - -- **`repo` — which indexed project.** Every graph tool (`query`, `context`, - `impact`, `trace`, `rename`, `cypher`, `explain`, `pdg_query`) runs against - exactly one registered repository's database. Registered repositories are - independent stores, so the failure is never leakage between them; it is - selecting the wrong one. -- **`worktree` — which checkout of that project.** Diff-based tools - (`detect_changes`) shell out to `git diff` and need a working directory. - Linked worktrees share one object store but hold different files and - different uncommitted changes. - -## Preflight - -Run once per task, before the first tool call: - -1. Call `list_repos {}` and read `total`. -2. If `total` is 1, use that repository; the `repo` argument may be omitted and - examples stay as written. -3. If `total` is greater than 1, resolve the intended repository and pass - `repo` explicitly on **every** subsequent call. Do not infer it from the - current working directory, and do not let the server pick: an omitted `repo` - normally errors, but under an MCP policy with a configured default it - resolves silently to that default. -4. If the intended repository cannot be resolved, stop and ask. An ambiguous - identity is not a detail to settle later — every result below it inherits - the ambiguity. -5. If the target repository is absent from `list_repos`, it is not indexed. - Index it rather than querying a neighbour that happens to share symbol - names. - -`list_repos` is paginated (`limit` default 50, max 200). Page with -`offset: pagination.nextOffset` until `hasMore` is false before concluding a -repository is absent; `total` is the true count regardless of page size. - -## Worktree - -The server auto-detects a linked worktree only when it was launched from inside -that worktree. When the server runs from the canonical root and your changes -are in a linked worktree, pass `worktree: ""` to -`detect_changes` explicitly. - -Omitting it runs `git diff` in the wrong checkout, which reports zero changed -symbols. That zero is indistinguishable in shape from a genuine clean result -and reads as a passed check. Confirm the checkout you are editing is the -checkout that was diffed before treating any empty change set as evidence. - -## Index freshness - -Identity includes *when*. A correctly bound repository whose index predates the -code answers about the old code. Check the staleness signal — `query`, -`context`, `impact` and `cypher` attach a `staleness` field with -`commitsBehind` when the index is behind HEAD — and refresh with -`node .gitnexus/run.cjs analyze --index-only` in the target checkout before -trusting results. If `.gitnexus/run.cjs` is missing, fall back to the installed -`gitnexus` CLI, then `npx gitnexus`. - -## Echo before claiming - -State the bound identity before reporting conclusions: - -``` -Repository: () Worktree: Index: , behind HEAD -``` - -Where the identity is partly unresolved, say which part and do not describe the -result as a complete graph-backed answer. This mirrors the provenance rule in -`gitnexus-review`: the graph and the diff must describe the same code, and a -reader must be able to tell from the output whether they did. - -## Scope - -Bind identity for any task that reads or writes a specific repository. Skip it -only for questions about GitNexus itself that touch no repository data. When -one task legitimately spans two repositories, bind each explicitly and label -which repository each result came from; never blend results from different -repositories into a single undifferentiated list. diff --git a/.claude/skills/gitnexus-exploring/SKILL.md b/.claude/skills/gitnexus-exploring/SKILL.md index ec5900192..c232565b1 100644 --- a/.claude/skills/gitnexus-exploring/SKILL.md +++ b/.claude/skills/gitnexus-exploring/SKILL.md @@ -15,35 +15,36 @@ description: "Use when the user asks how code works, wants to understand archite ## Bind the repository first -Step 1 discovers what is indexed; the calls after it must say which of those -they mean. With one indexed repository, use the examples below as written. With -more than one, pass `repo` explicitly on every call — an omitted `repo` errors, -or silently resolves to a configured default — and stop and ask if the intended -repository is ambiguous. See `references/repository-identity.md`. +Step 1 discovers what is indexed; every call after it must say which of those +it means. With one indexed repository, use the examples below as written. With +more than one, pass `repo` on every call: an omitted `repo` normally errors, +but under an MCP policy with a configured default it resolves to that default +silently. If you cannot tell which repository is meant, stop and ask. Report +the bound repository and index freshness alongside your explanation. ## Workflow ``` -1. list_repos {} or READ gitnexus://repos → Discover indexed repos; bind one +1. list_repos {} or READ gitnexus://repos → Discover indexed repos 2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness -3. query({search_query: ""[, repo: ""]}) → Find related execution flows -4. context({name: ""[, repo: ""]}) → Deep dive on specific symbol +3. query({search_query: ""}) → Find related execution flows +4. context({name: ""}) → Deep dive on specific symbol 5. READ gitnexus://repo/{name}/process/{name} → Trace full execution flow ``` -> If step 2 says "Index is stale" → run `node .gitnexus/run.cjs analyze` in the bound checkout. +> If step 2 says "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. ## Checklist ``` -- [ ] list_repos {} — bind repo; explicit repo when total > 1, ask if ambiguous +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] READ gitnexus://repo/{name}/context - [ ] query for the concept you want to understand - [ ] Review returned processes (execution flows) - [ ] context on key symbols for callers/callees - [ ] READ process resource for full execution traces - [ ] Read source files for implementation details -- [ ] State the repository and index freshness alongside the explanation +- [ ] State the repository and index freshness with the explanation ``` ## Resources @@ -81,7 +82,7 @@ with a single one. ``` 1. list_repos {} → total: 1 (my-app) — bind it - READ gitnexus://repo/my-app/context → 918 symbols, 45 processes, index current + READ gitnexus://repo/my-app/context → 918 symbols, 45 processes 2. query({search_query: "payment processing"}) → CheckoutFlow: processPayment → validateCard → chargeStripe → RefundFlow: initiateRefund → calculateRefund → processRefund diff --git a/.claude/skills/gitnexus-exploring/references/repository-identity.md b/.claude/skills/gitnexus-exploring/references/repository-identity.md deleted file mode 100644 index b2f1adb93..000000000 --- a/.claude/skills/gitnexus-exploring/references/repository-identity.md +++ /dev/null @@ -1,86 +0,0 @@ -# Repository and worktree identity - -This file is the shared identity contract for the per-repository GitNexus -skills. `gitnexus-exploring`, `gitnexus-debugging`, `gitnexus-impact-analysis` -and `gitnexus-refactoring` carry byte-identical copies so each skill works -without relying on another skill's install. - -Two independent questions must be answered before any graph or diff result can -be trusted, and a wrong answer to either produces a well-formed report about -code you were not asking about: - -- **`repo` — which indexed project.** Every graph tool (`query`, `context`, - `impact`, `trace`, `rename`, `cypher`, `explain`, `pdg_query`) runs against - exactly one registered repository's database. Registered repositories are - independent stores, so the failure is never leakage between them; it is - selecting the wrong one. -- **`worktree` — which checkout of that project.** Diff-based tools - (`detect_changes`) shell out to `git diff` and need a working directory. - Linked worktrees share one object store but hold different files and - different uncommitted changes. - -## Preflight - -Run once per task, before the first tool call: - -1. Call `list_repos {}` and read `total`. -2. If `total` is 1, use that repository; the `repo` argument may be omitted and - examples stay as written. -3. If `total` is greater than 1, resolve the intended repository and pass - `repo` explicitly on **every** subsequent call. Do not infer it from the - current working directory, and do not let the server pick: an omitted `repo` - normally errors, but under an MCP policy with a configured default it - resolves silently to that default. -4. If the intended repository cannot be resolved, stop and ask. An ambiguous - identity is not a detail to settle later — every result below it inherits - the ambiguity. -5. If the target repository is absent from `list_repos`, it is not indexed. - Index it rather than querying a neighbour that happens to share symbol - names. - -`list_repos` is paginated (`limit` default 50, max 200). Page with -`offset: pagination.nextOffset` until `hasMore` is false before concluding a -repository is absent; `total` is the true count regardless of page size. - -## Worktree - -The server auto-detects a linked worktree only when it was launched from inside -that worktree. When the server runs from the canonical root and your changes -are in a linked worktree, pass `worktree: ""` to -`detect_changes` explicitly. - -Omitting it runs `git diff` in the wrong checkout, which reports zero changed -symbols. That zero is indistinguishable in shape from a genuine clean result -and reads as a passed check. Confirm the checkout you are editing is the -checkout that was diffed before treating any empty change set as evidence. - -## Index freshness - -Identity includes *when*. A correctly bound repository whose index predates the -code answers about the old code. Check the staleness signal — `query`, -`context`, `impact` and `cypher` attach a `staleness` field with -`commitsBehind` when the index is behind HEAD — and refresh with -`node .gitnexus/run.cjs analyze --index-only` in the target checkout before -trusting results. If `.gitnexus/run.cjs` is missing, fall back to the installed -`gitnexus` CLI, then `npx gitnexus`. - -## Echo before claiming - -State the bound identity before reporting conclusions: - -``` -Repository: () Worktree: Index: , behind HEAD -``` - -Where the identity is partly unresolved, say which part and do not describe the -result as a complete graph-backed answer. This mirrors the provenance rule in -`gitnexus-review`: the graph and the diff must describe the same code, and a -reader must be able to tell from the output whether they did. - -## Scope - -Bind identity for any task that reads or writes a specific repository. Skip it -only for questions about GitNexus itself that touch no repository data. When -one task legitimately spans two repositories, bind each explicitly and label -which repository each result came from; never blend results from different -repositories into a single undifferentiated list. diff --git a/.claude/skills/gitnexus-impact-analysis/SKILL.md b/.claude/skills/gitnexus-impact-analysis/SKILL.md index 058788d29..4fb73f3e6 100644 --- a/.claude/skills/gitnexus-impact-analysis/SKILL.md +++ b/.claude/skills/gitnexus-impact-analysis/SKILL.md @@ -17,37 +17,55 @@ description: "Use when the user wants to know what will break if they change som ## Bind the repository first Impact analysis is the gate that authorizes an edit, so it must answer for the -repository you are about to edit. Call `list_repos {}`. With one indexed -repository, use the examples below as written. With more than one, pass `repo` -explicitly on every call — an omitted `repo` errors, or silently resolves to a -configured default — and stop and ask if the intended repository is ambiguous. -Pass `worktree` to `detect_changes` when your changes live in a linked worktree -the server was not launched from. See `references/repository-identity.md`. +repository you are about to edit. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask — every result below an ambiguous +identity inherits the ambiguity. `list_repos` is paginated, so page with +`offset: pagination.nextOffset` until `hasMore` is false before concluding a +repository is absent. + +`detect_changes` takes `worktree` when your changes are in a linked worktree +the MCP server was not launched from. The server auto-detects a worktree only +when it was launched from inside one; otherwise `git diff` runs in the wrong +checkout and reports zero changed symbols — a false clean check that carries +none of the degradation flags described below. In the CLI fallbacks, `--repo .` +means the current checkout; pass the intended repository path instead when you +are not standing in it. + +State the bound identity with your risk report: + +``` +Repository: () Worktree: Index: , behind HEAD +``` ## Workflow ``` 0. list_repos {} → Bind repo (and worktree) -1. impact({target: "X", direction: "upstream"[, repo: ""]}) or `node .gitnexus/run.cjs impact "X" --direction upstream --repo ` +1. impact({target: "X", direction: "upstream"}) or `node .gitnexus/run.cjs impact "X" --direction upstream --repo .` 2. READ gitnexus://repo/{name}/processes → Check affected execution flows -3. detect_changes({scope: "all"[, repo: ""][, worktree: ""]}) or `node .gitnexus/run.cjs detect-changes --scope all --repo ` -4. Assess risk and report to user, echoing the bound repo/worktree/index +3. detect_changes({scope: "all"}) or `node .gitnexus/run.cjs detect-changes --scope all --repo .` +4. Assess risk and report to user, echoing repo/worktree/index identity ``` -> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in the bound checkout. +> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. > If `.gitnexus/run.cjs` is missing, replace `node .gitnexus/run.cjs` with `npx gitnexus` in the fallback commands. ## Checklist ``` -- [ ] list_repos {} — bind repo; explicit repo when total > 1, ask if ambiguous +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] impact({target, direction: "upstream"}) or CLI fallback to find dependents - [ ] Review d=1 items first (these WILL BREAK) - [ ] Check high-confidence (>0.8) dependencies - [ ] READ processes to check affected execution flows - [ ] detect_changes({scope: "all"}) or CLI fallback for pre-commit check - [ ] Confirm the checkout you edited is the checkout that was diffed -- [ ] Assess risk level and report, stating repo/worktree/index freshness +- [ ] Assess risk level and report, stating repo/worktree/index identity ``` ## Understanding Output @@ -77,7 +95,7 @@ treating the symbol as safe to change or delete. ## Tools -**impact** — the primary tool for symbol blast radius. If MCP is unavailable, use `node .gitnexus/run.cjs impact --direction upstream --repo ` instead: +**impact** — the primary tool for symbol blast radius. If MCP is unavailable, use `node .gitnexus/run.cjs impact --direction upstream --repo .` instead: ``` impact({ @@ -96,27 +114,28 @@ impact({ - authRouter (src/routes/auth.ts:22) [CALLS, 95%] ``` -**detect_changes** — git-diff based impact analysis. If MCP is unavailable, use `node .gitnexus/run.cjs detect-changes --scope all --repo ` instead: +**detect_changes** — git-diff based impact analysis. If MCP is unavailable, use `node .gitnexus/run.cjs detect-changes --scope all --repo .` instead: ``` -detect_changes({scope: "all", repo: "my-app", worktree: "/abs/path/to/checkout"}) +detect_changes({scope: "all"}) → Changed: 5 symbols in 3 files → Affected: LoginFlow, TokenRefresh, APIMiddlewarePipeline → Risk: MEDIUM ``` -`repo` is required once more than one repository is indexed. `worktree` is -needed when your changes are in a linked worktree the MCP server was not -launched from — omit it there and `git diff` runs in the wrong checkout, -reporting zero changed symbols for a tree full of edits. +Add `repo` once more than one repository is indexed, and `worktree: ""` when your changes are in a linked worktree the server was not launched +from. `partial: true` (a graph query failed) or `truncated: true` (the changed-symbol listing was capped) means the result is short of the truth, and reads like -`UNKNOWN` above: a zero there means unseen, not unaffected. A wrong-worktree -zero carries none of those flags and looks exactly like a clean result, so -confirm the checkout you edited is the checkout that was diffed. Re-run it -rather than tick the pre-commit check. +`UNKNOWN` above: a zero there means unseen, not unaffected. Re-run it rather +than tick the pre-commit check. + +A wrong-worktree zero carries neither flag and is shape-identical to a genuine +clean result, so confirm the checkout you edited is the one that was diffed +before treating an empty change set as a passed check. ## Example: "What breaks if I change validateUser?" @@ -124,8 +143,7 @@ rather than tick the pre-commit check. 0. list_repos {} → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly -1. impact({target: "validateUser", repo: "my-app", direction: "upstream"}) - or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo /abs/path/my-app` +1. impact({target: "validateUser", repo: "my-app", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` → d=1: loginHandler, apiMiddleware (WILL BREAK) → d=2: authRouter, sessionManager (LIKELY AFFECTED) diff --git a/.claude/skills/gitnexus-impact-analysis/references/repository-identity.md b/.claude/skills/gitnexus-impact-analysis/references/repository-identity.md deleted file mode 100644 index b2f1adb93..000000000 --- a/.claude/skills/gitnexus-impact-analysis/references/repository-identity.md +++ /dev/null @@ -1,86 +0,0 @@ -# Repository and worktree identity - -This file is the shared identity contract for the per-repository GitNexus -skills. `gitnexus-exploring`, `gitnexus-debugging`, `gitnexus-impact-analysis` -and `gitnexus-refactoring` carry byte-identical copies so each skill works -without relying on another skill's install. - -Two independent questions must be answered before any graph or diff result can -be trusted, and a wrong answer to either produces a well-formed report about -code you were not asking about: - -- **`repo` — which indexed project.** Every graph tool (`query`, `context`, - `impact`, `trace`, `rename`, `cypher`, `explain`, `pdg_query`) runs against - exactly one registered repository's database. Registered repositories are - independent stores, so the failure is never leakage between them; it is - selecting the wrong one. -- **`worktree` — which checkout of that project.** Diff-based tools - (`detect_changes`) shell out to `git diff` and need a working directory. - Linked worktrees share one object store but hold different files and - different uncommitted changes. - -## Preflight - -Run once per task, before the first tool call: - -1. Call `list_repos {}` and read `total`. -2. If `total` is 1, use that repository; the `repo` argument may be omitted and - examples stay as written. -3. If `total` is greater than 1, resolve the intended repository and pass - `repo` explicitly on **every** subsequent call. Do not infer it from the - current working directory, and do not let the server pick: an omitted `repo` - normally errors, but under an MCP policy with a configured default it - resolves silently to that default. -4. If the intended repository cannot be resolved, stop and ask. An ambiguous - identity is not a detail to settle later — every result below it inherits - the ambiguity. -5. If the target repository is absent from `list_repos`, it is not indexed. - Index it rather than querying a neighbour that happens to share symbol - names. - -`list_repos` is paginated (`limit` default 50, max 200). Page with -`offset: pagination.nextOffset` until `hasMore` is false before concluding a -repository is absent; `total` is the true count regardless of page size. - -## Worktree - -The server auto-detects a linked worktree only when it was launched from inside -that worktree. When the server runs from the canonical root and your changes -are in a linked worktree, pass `worktree: ""` to -`detect_changes` explicitly. - -Omitting it runs `git diff` in the wrong checkout, which reports zero changed -symbols. That zero is indistinguishable in shape from a genuine clean result -and reads as a passed check. Confirm the checkout you are editing is the -checkout that was diffed before treating any empty change set as evidence. - -## Index freshness - -Identity includes *when*. A correctly bound repository whose index predates the -code answers about the old code. Check the staleness signal — `query`, -`context`, `impact` and `cypher` attach a `staleness` field with -`commitsBehind` when the index is behind HEAD — and refresh with -`node .gitnexus/run.cjs analyze --index-only` in the target checkout before -trusting results. If `.gitnexus/run.cjs` is missing, fall back to the installed -`gitnexus` CLI, then `npx gitnexus`. - -## Echo before claiming - -State the bound identity before reporting conclusions: - -``` -Repository: () Worktree: Index: , behind HEAD -``` - -Where the identity is partly unresolved, say which part and do not describe the -result as a complete graph-backed answer. This mirrors the provenance rule in -`gitnexus-review`: the graph and the diff must describe the same code, and a -reader must be able to tell from the output whether they did. - -## Scope - -Bind identity for any task that reads or writes a specific repository. Skip it -only for questions about GitNexus itself that touch no repository data. When -one task legitimately spans two repositories, bind each explicitly and label -which repository each result came from; never blend results from different -repositories into a single undifferentiated list. diff --git a/.claude/skills/gitnexus-refactoring/SKILL.md b/.claude/skills/gitnexus-refactoring/SKILL.md index 7cdceb4b7..6c5412b51 100644 --- a/.claude/skills/gitnexus-refactoring/SKILL.md +++ b/.claude/skills/gitnexus-refactoring/SKILL.md @@ -17,72 +17,72 @@ description: "Use when the user wants to rename, extract, split, move, or restru Refactoring writes to disk. `rename` with `dry_run: false` edits files in whichever repository was resolved, so binding identity here is a safety gate, -not bookkeeping. Call `list_repos {}`. With one indexed repository, use the -examples below as written. With more than one, pass `repo` explicitly on every -call — an omitted `repo` errors, or silently resolves to a configured default — -and stop and ask if the intended repository is ambiguous. Pass `worktree` to -`detect_changes` when you are editing a linked worktree the server was not -launched from. See `references/repository-identity.md`. +not bookkeeping. -Never run `rename` with `dry_run: false` until the preview in the same bound -repository has been reviewed. +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. Never run `rename` with +`dry_run: false` until the preview in the same bound repository has been +reviewed — its returned `file_path` values show which checkout is about to be +written, so read them as a confirmation of identity. + +`detect_changes` takes `worktree` when you are editing a linked worktree the +MCP server was not launched from; otherwise `git diff` runs in the wrong +checkout and reports nothing changed, which reads as a verified refactor. ## Workflow ``` 0. list_repos {} → Bind repo (and worktree) -1. impact({target: "X", direction: "upstream"[, repo: ""]}) → Map all dependents -2. query({search_query: "X"[, repo: ""]}) → Find execution flows involving X -3. context({name: "X"[, repo: ""]}) → See all incoming/outgoing refs +1. impact({target: "X", direction: "upstream"}) → Map all dependents +2. query({search_query: "X"}) → Find execution flows involving X +3. context({name: "X"}) → See all incoming/outgoing refs 4. Plan update order: interfaces → implementations → callers → tests ``` -> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in the bound checkout. -> A stale index under a rename means edits planned against code that has moved. +> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. ## Checklists ### Rename Symbol ``` -- [ ] list_repos {} — bind repo; explicit repo when total > 1, ask if ambiguous +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] rename({symbol_name: "oldName", new_name: "newName", dry_run: true}) — preview all edits - [ ] Confirm the previewed file paths are in the bound repository/worktree - [ ] Review graph edits (high confidence) and text_search edits (review carefully) - [ ] If satisfied: rename({..., dry_run: false}) — apply edits -- [ ] detect_changes({scope: "all"}) — verify only expected files changed +- [ ] detect_changes() — verify only expected files changed - [ ] Run tests for affected processes ``` ### Extract Module ``` -- [ ] list_repos {} — bind repo; explicit repo when total > 1, ask if ambiguous +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — see all incoming/outgoing refs - [ ] impact({target, direction: "upstream"}) — find all external callers - [ ] Define new module interface - [ ] Extract code, update imports -- [ ] detect_changes({scope: "all"}) — verify affected scope +- [ ] detect_changes() — verify affected scope - [ ] Run tests for affected processes ``` ### Split Function/Service ``` -- [ ] list_repos {} — bind repo; explicit repo when total > 1, ask if ambiguous +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — understand all callees - [ ] Group callees by responsibility - [ ] impact({target, direction: "upstream"}) — map callers to update - [ ] Create new functions/services - [ ] Update callers -- [ ] detect_changes({scope: "all"}) — verify affected scope +- [ ] detect_changes() — verify affected scope - [ ] Run tests for affected processes ``` -Each `detect_changes` above takes `worktree` when the checkout you edited is -not the one the MCP server was launched from. Without it the diff runs in the -wrong tree and reports nothing changed, which reads as a verified refactor. - ## Tools **rename** — automated multi-file rename: @@ -94,10 +94,6 @@ rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app → Changes: [{file_path, edits: [{line, old_text, new_text, confidence}]}] ``` -Read the returned `file_path` values as a confirmation of identity: they show -which checkout is about to be written. If they are not the paths you intend, -stop — do not re-run with `dry_run: false`. - **impact** — map all dependents first: ``` @@ -109,7 +105,7 @@ impact({target: "validateUser", repo: "my-app", direction: "upstream"}) **detect_changes** — verify your changes after refactoring: ``` -detect_changes({scope: "all", repo: "my-app", worktree: "/abs/path/to/checkout"}) +detect_changes({scope: "all"}) → Changed: 8 files, 12 symbols → Affected processes: LoginFlow, TokenRefresh → Risk: MEDIUM @@ -117,19 +113,17 @@ detect_changes({scope: "all", repo: "my-app", worktree: "/abs/path/to/checkout"} `partial: true` (a graph query failed) or `truncated: true` (the changed-symbol listing was capped) means the result is short of the truth: a short or empty -list is not proof that only the expected files changed. A wrong-worktree zero -carries neither flag and is indistinguishable from a clean verification, so -confirm the diffed checkout is the one you edited. Re-run it rather than treat -the refactor as verified. +list is not proof that only the expected files changed. Re-run it rather than +treat the refactor as verified. -**cypher** — custom reference queries. Pass `repo` alongside the statement; the -Cypher text names no repository: +A wrong-worktree zero carries neither flag and is indistinguishable from a +clean verification, so confirm the diffed checkout is the one you edited. -``` -cypher({repo: "my-app", statement: ` +**cypher** — custom reference queries: + +```cypher MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"}) RETURN caller.name, caller.filePath ORDER BY caller.filePath -`}) ``` ## Risk Rules @@ -140,7 +134,7 @@ RETURN caller.name, caller.filePath ORDER BY caller.filePath | Cross-area refs | Use detect_changes after to verify scope | | String/dynamic refs | query to find them | | External/public API | Version and deprecate properly | -| Same symbol name in another indexed repo | Bind `repo` explicitly; verify previewed paths before applying | +| Same name in another indexed repo | Bind `repo`; verify previewed paths before applying | ## Example: Rename `validateUser` to `authenticateUser` @@ -148,16 +142,13 @@ RETURN caller.name, caller.filePath ORDER BY caller.filePath 0. list_repos {} → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly -1. rename({symbol_name: "validateUser", new_name: "authenticateUser", - repo: "my-app", dry_run: true}) +1. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits: 10 graph (safe), 2 text_search (review) → Files: validator.ts, login.ts, middleware.ts, config.json... - → Paths are under /abs/path/my-app — the intended checkout ✓ 2. Review text_search edits (config.json: dynamic reference!) -3. rename({symbol_name: "validateUser", new_name: "authenticateUser", - repo: "my-app", dry_run: false}) +3. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: false}) → Applied 12 edits across 8 files 4. detect_changes({scope: "all", repo: "my-app"}) diff --git a/.claude/skills/gitnexus-refactoring/references/repository-identity.md b/.claude/skills/gitnexus-refactoring/references/repository-identity.md deleted file mode 100644 index b2f1adb93..000000000 --- a/.claude/skills/gitnexus-refactoring/references/repository-identity.md +++ /dev/null @@ -1,86 +0,0 @@ -# Repository and worktree identity - -This file is the shared identity contract for the per-repository GitNexus -skills. `gitnexus-exploring`, `gitnexus-debugging`, `gitnexus-impact-analysis` -and `gitnexus-refactoring` carry byte-identical copies so each skill works -without relying on another skill's install. - -Two independent questions must be answered before any graph or diff result can -be trusted, and a wrong answer to either produces a well-formed report about -code you were not asking about: - -- **`repo` — which indexed project.** Every graph tool (`query`, `context`, - `impact`, `trace`, `rename`, `cypher`, `explain`, `pdg_query`) runs against - exactly one registered repository's database. Registered repositories are - independent stores, so the failure is never leakage between them; it is - selecting the wrong one. -- **`worktree` — which checkout of that project.** Diff-based tools - (`detect_changes`) shell out to `git diff` and need a working directory. - Linked worktrees share one object store but hold different files and - different uncommitted changes. - -## Preflight - -Run once per task, before the first tool call: - -1. Call `list_repos {}` and read `total`. -2. If `total` is 1, use that repository; the `repo` argument may be omitted and - examples stay as written. -3. If `total` is greater than 1, resolve the intended repository and pass - `repo` explicitly on **every** subsequent call. Do not infer it from the - current working directory, and do not let the server pick: an omitted `repo` - normally errors, but under an MCP policy with a configured default it - resolves silently to that default. -4. If the intended repository cannot be resolved, stop and ask. An ambiguous - identity is not a detail to settle later — every result below it inherits - the ambiguity. -5. If the target repository is absent from `list_repos`, it is not indexed. - Index it rather than querying a neighbour that happens to share symbol - names. - -`list_repos` is paginated (`limit` default 50, max 200). Page with -`offset: pagination.nextOffset` until `hasMore` is false before concluding a -repository is absent; `total` is the true count regardless of page size. - -## Worktree - -The server auto-detects a linked worktree only when it was launched from inside -that worktree. When the server runs from the canonical root and your changes -are in a linked worktree, pass `worktree: ""` to -`detect_changes` explicitly. - -Omitting it runs `git diff` in the wrong checkout, which reports zero changed -symbols. That zero is indistinguishable in shape from a genuine clean result -and reads as a passed check. Confirm the checkout you are editing is the -checkout that was diffed before treating any empty change set as evidence. - -## Index freshness - -Identity includes *when*. A correctly bound repository whose index predates the -code answers about the old code. Check the staleness signal — `query`, -`context`, `impact` and `cypher` attach a `staleness` field with -`commitsBehind` when the index is behind HEAD — and refresh with -`node .gitnexus/run.cjs analyze --index-only` in the target checkout before -trusting results. If `.gitnexus/run.cjs` is missing, fall back to the installed -`gitnexus` CLI, then `npx gitnexus`. - -## Echo before claiming - -State the bound identity before reporting conclusions: - -``` -Repository: () Worktree: Index: , behind HEAD -``` - -Where the identity is partly unresolved, say which part and do not describe the -result as a complete graph-backed answer. This mirrors the provenance rule in -`gitnexus-review`: the graph and the diff must describe the same code, and a -reader must be able to tell from the output whether they did. - -## Scope - -Bind identity for any task that reads or writes a specific repository. Skip it -only for questions about GitNexus itself that touch no repository data. When -one task legitimately spans two repositories, bind each explicitly and label -which repository each result came from; never blend results from different -repositories into a single undifferentiated list. diff --git a/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md b/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md index 4a33e589a..beebb532e 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md @@ -13,9 +13,25 @@ description: "Use when the user is debugging a bug, tracing an error, or asking - "This endpoint returns 500" - Investigating bugs, errors, or unexpected behavior +## Bind the repository first + +A root cause traced in the wrong repository is a wrong root cause. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. This matters most for `cypher`, whose +statement carries no in-band hint of which database it ran against. + +A stale index describes the code from before your bug, so refresh before +trusting a trace, and state the repository and index freshness with the +diagnosis. + ## Workflow ``` +0. list_repos {} → Bind repo 1. query({search_query: ""}) → Find related execution flows 2. context({name: ""}) → See callers/callees/processes 3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow @@ -27,6 +43,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] Understand the symptom (error message, unexpected behavior) - [ ] query for error text or related code - [ ] Identify the suspect function from returned processes @@ -34,6 +51,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking - [ ] Trace execution flow via process resource if applicable - [ ] cypher for custom call chain traces if needed - [ ] Read source files to confirm root cause +- [ ] State the repository and index freshness with the diagnosis ``` ## Debugging Patterns @@ -44,7 +62,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking | Wrong return value | `context` on the function → trace callees for data flow | | Intermittent failure | `context` → look for external calls, async deps | | Performance issue | `context` → find symbols with many callers (hot paths) | -| Recent regression | `detect_changes` to see what your changes affect | +| Recent regression | `detect_changes` to see what your changes affect — pass `worktree` for a linked worktree | | "How does A reach B?" | `trace` between the two symbols — shortest call chain in one call | ## Tools @@ -52,7 +70,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking **query** — find code related to error: ``` -query({search_query: "payment validation error"}) +query({search_query: "payment validation error", repo: "my-app"}) → Processes: CheckoutFlow, ErrorHandling → Symbols: validatePayment, handlePaymentError, PaymentException ``` @@ -60,13 +78,15 @@ query({search_query: "payment validation error"}) **context** — full context for a suspect: ``` -context({name: "validatePayment"}) +context({name: "validatePayment", repo: "my-app"}) → Incoming calls: processCheckout, webhookHandler → Outgoing calls: verifyCard, fetchRates (external API!) → Processes: CheckoutFlow (step 3/7) ``` -**cypher** — custom call chain traces: +**cypher** — custom call chain traces. Pass `repo` alongside the statement; the +Cypher text itself names no repository, so the result is unattributable without +it: ```cypher MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"}) @@ -76,7 +96,7 @@ RETURN [n IN nodes(path) | n.name] AS chain **trace** — shortest call chain between two symbols ("how does A reach B?"), one call instead of chaining `context` hops: ``` -trace({ from: "processCheckout", to: "fetchRates" }) +trace({ from: "processCheckout", to: "fetchRates", repo: "my-app" }) → status: ok, hopCount: 3 → hops: processCheckout → validatePayment → verifyCard → fetchRates → edges: CALLS (1.0), CALLS (0.95), CALLS (1.0) @@ -87,15 +107,22 @@ When no path exists, `trace` reports the furthest reachable node — exactly whe ## Example: "Payment endpoint returns 500 intermittently" ``` -1. query({search_query: "payment error handling"}) +0. list_repos {} + → total: 2 (my-app, billing-api) — bind my-app explicitly on every call + +1. query({search_query: "payment error handling", repo: "my-app"}) → Processes: CheckoutFlow, ErrorHandling → Symbols: validatePayment, handlePaymentError -2. context({name: "validatePayment"}) +2. context({name: "validatePayment", repo: "my-app"}) → Outgoing calls: verifyCard, fetchRates (external API!) 3. READ gitnexus://repo/my-app/process/CheckoutFlow → Step 3: validatePayment → calls fetchRates (external) 4. Root cause: fetchRates calls external API without proper timeout + Repository: my-app Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md b/gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md index f483c2fd6..c232565b1 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md @@ -13,10 +13,19 @@ description: "Use when the user asks how code works, wants to understand archite - "Where is the database logic?" - Understanding code you haven't seen before +## Bind the repository first + +Step 1 discovers what is indexed; every call after it must say which of those +it means. With one indexed repository, use the examples below as written. With +more than one, pass `repo` on every call: an omitted `repo` normally errors, +but under an MCP policy with a configured default it resolves to that default +silently. If you cannot tell which repository is meant, stop and ask. Report +the bound repository and index freshness alongside your explanation. + ## Workflow ``` -1. READ gitnexus://repos → Discover indexed repos +1. list_repos {} or READ gitnexus://repos → Discover indexed repos 2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness 3. query({search_query: ""}) → Find related execution flows 4. context({name: ""}) → Deep dive on specific symbol @@ -28,12 +37,14 @@ description: "Use when the user asks how code works, wants to understand archite ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] READ gitnexus://repo/{name}/context - [ ] query for the concept you want to understand - [ ] Review returned processes (execution flows) - [ ] context on key symbols for callers/callees - [ ] READ process resource for full execution traces - [ ] Read source files for implementation details +- [ ] State the repository and index freshness with the explanation ``` ## Resources @@ -50,7 +61,7 @@ description: "Use when the user asks how code works, wants to understand archite **query** — find execution flows related to a concept: ``` -query({search_query: "payment processing"}) +query({search_query: "payment processing", repo: "my-app"}) → Processes: CheckoutFlow, RefundFlow, WebhookHandler → Symbols grouped by flow with file locations ``` @@ -58,16 +69,20 @@ query({search_query: "payment processing"}) **context** — 360-degree view of a symbol: ``` -context({name: "validateUser"}) +context({name: "validateUser", repo: "my-app"}) → Incoming calls: loginHandler, apiMiddleware → Outgoing calls: checkToken, getUserById → Processes: LoginFlow (step 2/5), TokenRefresh (step 1/3) ``` +`repo` is required once more than one repository is indexed, and may be omitted +with a single one. + ## Example: "How does payment processing work?" ``` -1. READ gitnexus://repo/my-app/context → 918 symbols, 45 processes +1. list_repos {} → total: 1 (my-app) — bind it + READ gitnexus://repo/my-app/context → 918 symbols, 45 processes 2. query({search_query: "payment processing"}) → CheckoutFlow: processPayment → validateCard → chargeStripe → RefundFlow: initiateRefund → calculateRefund → processRefund @@ -75,4 +90,8 @@ context({name: "validateUser"}) → Incoming: checkoutHandler, webhookHandler → Outgoing: validateCard, chargeStripe, saveTransaction 4. Read src/payments/processor.ts for implementation details +5. Answer, noting: Repository my-app, index current ``` + +Had step 1 returned two repositories, every call above would carry +`repo: "my-app"`. diff --git a/gitnexus-claude-plugin/skills/gitnexus-impact-analysis/SKILL.md b/gitnexus-claude-plugin/skills/gitnexus-impact-analysis/SKILL.md index ee1cd3496..4fb73f3e6 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-impact-analysis/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-impact-analysis/SKILL.md @@ -14,13 +14,42 @@ description: "Use when the user wants to know what will break if they change som - Before making non-trivial code changes - Before committing — to understand what your changes affect +## Bind the repository first + +Impact analysis is the gate that authorizes an edit, so it must answer for the +repository you are about to edit. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask — every result below an ambiguous +identity inherits the ambiguity. `list_repos` is paginated, so page with +`offset: pagination.nextOffset` until `hasMore` is false before concluding a +repository is absent. + +`detect_changes` takes `worktree` when your changes are in a linked worktree +the MCP server was not launched from. The server auto-detects a worktree only +when it was launched from inside one; otherwise `git diff` runs in the wrong +checkout and reports zero changed symbols — a false clean check that carries +none of the degradation flags described below. In the CLI fallbacks, `--repo .` +means the current checkout; pass the intended repository path instead when you +are not standing in it. + +State the bound identity with your risk report: + +``` +Repository: () Worktree: Index: , behind HEAD +``` + ## Workflow ``` +0. list_repos {} → Bind repo (and worktree) 1. impact({target: "X", direction: "upstream"}) or `node .gitnexus/run.cjs impact "X" --direction upstream --repo .` 2. READ gitnexus://repo/{name}/processes → Check affected execution flows 3. detect_changes({scope: "all"}) or `node .gitnexus/run.cjs detect-changes --scope all --repo .` -4. Assess risk and report to user +4. Assess risk and report to user, echoing repo/worktree/index identity ``` > If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. @@ -29,12 +58,14 @@ description: "Use when the user wants to know what will break if they change som ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] impact({target, direction: "upstream"}) or CLI fallback to find dependents - [ ] Review d=1 items first (these WILL BREAK) - [ ] Check high-confidence (>0.8) dependencies - [ ] READ processes to check affected execution flows - [ ] detect_changes({scope: "all"}) or CLI fallback for pre-commit check -- [ ] Assess risk level and report to user +- [ ] Confirm the checkout you edited is the checkout that was diffed +- [ ] Assess risk level and report, stating repo/worktree/index identity ``` ## Understanding Output @@ -69,6 +100,7 @@ treating the symbol as safe to change or delete. ``` impact({ target: "validateUser", + repo: "my-app", // required once >1 repository is indexed direction: "upstream", minConfidence: 0.8, maxDepth: 3 @@ -92,15 +124,26 @@ detect_changes({scope: "all"}) → Risk: MEDIUM ``` +Add `repo` once more than one repository is indexed, and `worktree: ""` when your changes are in a linked worktree the server was not launched +from. + `partial: true` (a graph query failed) or `truncated: true` (the changed-symbol listing was capped) means the result is short of the truth, and reads like `UNKNOWN` above: a zero there means unseen, not unaffected. Re-run it rather than tick the pre-commit check. +A wrong-worktree zero carries neither flag and is shape-identical to a genuine +clean result, so confirm the checkout you edited is the one that was diffed +before treating an empty change set as a passed check. + ## Example: "What breaks if I change validateUser?" ``` -1. impact({target: "validateUser", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` +0. list_repos {} + → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly + +1. impact({target: "validateUser", repo: "my-app", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` → d=1: loginHandler, apiMiddleware (WILL BREAK) → d=2: authRouter, sessionManager (LIKELY AFFECTED) @@ -108,4 +151,8 @@ than tick the pre-commit check. → LoginFlow and TokenRefresh touch validateUser 3. Risk: 2 direct callers, 2 processes = MEDIUM + Repository: my-app (/abs/path/my-app) Worktree: same Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md b/gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md index 4f10bbc6a..6c5412b51 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md @@ -13,9 +13,29 @@ description: "Use when the user wants to rename, extract, split, move, or restru - "Move this to a new file" - Any task involving renaming, extracting, splitting, or restructuring code +## Bind the repository first + +Refactoring writes to disk. `rename` with `dry_run: false` edits files in +whichever repository was resolved, so binding identity here is a safety gate, +not bookkeeping. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. Never run `rename` with +`dry_run: false` until the preview in the same bound repository has been +reviewed — its returned `file_path` values show which checkout is about to be +written, so read them as a confirmation of identity. + +`detect_changes` takes `worktree` when you are editing a linked worktree the +MCP server was not launched from; otherwise `git diff` runs in the wrong +checkout and reports nothing changed, which reads as a verified refactor. + ## Workflow ``` +0. list_repos {} → Bind repo (and worktree) 1. impact({target: "X", direction: "upstream"}) → Map all dependents 2. query({search_query: "X"}) → Find execution flows involving X 3. context({name: "X"}) → See all incoming/outgoing refs @@ -29,7 +49,9 @@ description: "Use when the user wants to rename, extract, split, move, or restru ### Rename Symbol ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] rename({symbol_name: "oldName", new_name: "newName", dry_run: true}) — preview all edits +- [ ] Confirm the previewed file paths are in the bound repository/worktree - [ ] Review graph edits (high confidence) and text_search edits (review carefully) - [ ] If satisfied: rename({..., dry_run: false}) — apply edits - [ ] detect_changes() — verify only expected files changed @@ -39,6 +61,7 @@ description: "Use when the user wants to rename, extract, split, move, or restru ### Extract Module ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — see all incoming/outgoing refs - [ ] impact({target, direction: "upstream"}) — find all external callers - [ ] Define new module interface @@ -50,6 +73,7 @@ description: "Use when the user wants to rename, extract, split, move, or restru ### Split Function/Service ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — understand all callees - [ ] Group callees by responsibility - [ ] impact({target, direction: "upstream"}) — map callers to update @@ -64,7 +88,7 @@ description: "Use when the user wants to rename, extract, split, move, or restru **rename** — automated multi-file rename: ``` -rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true}) +rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits across 8 files → 10 graph edits (high confidence), 2 text_search edits (review) → Changes: [{file_path, edits: [{line, old_text, new_text, confidence}]}] @@ -73,7 +97,7 @@ rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true **impact** — map all dependents first: ``` -impact({target: "validateUser", direction: "upstream"}) +impact({target: "validateUser", repo: "my-app", direction: "upstream"}) → d=1: loginHandler, apiMiddleware, testUtils → Affected Processes: LoginFlow, TokenRefresh ``` @@ -92,6 +116,9 @@ listing was capped) means the result is short of the truth: a short or empty list is not proof that only the expected files changed. Re-run it rather than treat the refactor as verified. +A wrong-worktree zero carries neither flag and is indistinguishable from a +clean verification, so confirm the diffed checkout is the one you edited. + **cypher** — custom reference queries: ```cypher @@ -107,20 +134,28 @@ RETURN caller.name, caller.filePath ORDER BY caller.filePath | Cross-area refs | Use detect_changes after to verify scope | | String/dynamic refs | query to find them | | External/public API | Version and deprecate properly | +| Same name in another indexed repo | Bind `repo`; verify previewed paths before applying | ## Example: Rename `validateUser` to `authenticateUser` ``` -1. rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true}) +0. list_repos {} + → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly + +1. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits: 10 graph (safe), 2 text_search (review) → Files: validator.ts, login.ts, middleware.ts, config.json... 2. Review text_search edits (config.json: dynamic reference!) -3. rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: false}) +3. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: false}) → Applied 12 edits across 8 files -4. detect_changes({scope: "all"}) +4. detect_changes({scope: "all", repo: "my-app"}) → Affected: LoginFlow, TokenRefresh → Risk: MEDIUM — run tests for these flows + Repository: my-app (/abs/path/my-app) Worktree: same Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md b/gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md index 6f8944fd4..beebb532e 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md @@ -1,20 +1,37 @@ --- name: gitnexus-debugging -description: Trace bugs through call chains using knowledge graph +description: "Use when the user is debugging a bug, tracing an error, or asking why something fails. Examples: \"Why is X failing?\", \"Where does this error come from?\", \"Trace this bug\"" --- # Debugging with GitNexus ## When to Use + - "Why is this function failing?" - "Trace where this error comes from" - "Who calls this method?" - "This endpoint returns 500" - Investigating bugs, errors, or unexpected behavior +## Bind the repository first + +A root cause traced in the wrong repository is a wrong root cause. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. This matters most for `cypher`, whose +statement carries no in-band hint of which database it ran against. + +A stale index describes the code from before your bug, so refresh before +trusting a trace, and state the repository and index freshness with the +diagnosis. + ## Workflow ``` +0. list_repos {} → Bind repo 1. query({search_query: ""}) → Find related execution flows 2. context({name: ""}) → See callers/callees/processes 3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow @@ -26,6 +43,7 @@ description: Trace bugs through call chains using knowledge graph ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] Understand the symptom (error message, unexpected behavior) - [ ] query for error text or related code - [ ] Identify the suspect function from returned processes @@ -33,45 +51,52 @@ description: Trace bugs through call chains using knowledge graph - [ ] Trace execution flow via process resource if applicable - [ ] cypher for custom call chain traces if needed - [ ] Read source files to confirm root cause +- [ ] State the repository and index freshness with the diagnosis ``` ## Debugging Patterns -| Symptom | GitNexus Approach | -|---------|-------------------| -| Error message | `query` for error text → `context` on throw sites | -| Wrong return value | `context` on the function → trace callees for data flow | -| Intermittent failure | `context` → look for external calls, async deps | -| Performance issue | `context` → find symbols with many callers (hot paths) | -| Recent regression | `detect_changes` to see what your changes affect | +| Symptom | GitNexus Approach | +| -------------------- | ---------------------------------------------------------- | +| Error message | `query` for error text → `context` on throw sites | +| Wrong return value | `context` on the function → trace callees for data flow | +| Intermittent failure | `context` → look for external calls, async deps | +| Performance issue | `context` → find symbols with many callers (hot paths) | +| Recent regression | `detect_changes` to see what your changes affect — pass `worktree` for a linked worktree | | "How does A reach B?" | `trace` between the two symbols — shortest call chain in one call | ## Tools **query** — find code related to error: + ``` -query({search_query: "payment validation error"}) +query({search_query: "payment validation error", repo: "my-app"}) → Processes: CheckoutFlow, ErrorHandling → Symbols: validatePayment, handlePaymentError, PaymentException ``` **context** — full context for a suspect: + ``` -context({name: "validatePayment"}) +context({name: "validatePayment", repo: "my-app"}) → Incoming calls: processCheckout, webhookHandler → Outgoing calls: verifyCard, fetchRates (external API!) → Processes: CheckoutFlow (step 3/7) ``` -**cypher** — custom call chain traces: +**cypher** — custom call chain traces. Pass `repo` alongside the statement; the +Cypher text itself names no repository, so the result is unattributable without +it: + ```cypher MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"}) RETURN [n IN nodes(path) | n.name] AS chain ``` **trace** — shortest call chain between two symbols ("how does A reach B?"), one call instead of chaining `context` hops: + ``` -trace({ from: "processCheckout", to: "fetchRates" }) +trace({ from: "processCheckout", to: "fetchRates", repo: "my-app" }) → status: ok, hopCount: 3 → hops: processCheckout → validatePayment → verifyCard → fetchRates → edges: CALLS (1.0), CALLS (0.95), CALLS (1.0) @@ -82,15 +107,22 @@ When no path exists, `trace` reports the furthest reachable node — exactly whe ## Example: "Payment endpoint returns 500 intermittently" ``` -1. query({search_query: "payment error handling"}) +0. list_repos {} + → total: 2 (my-app, billing-api) — bind my-app explicitly on every call + +1. query({search_query: "payment error handling", repo: "my-app"}) → Processes: CheckoutFlow, ErrorHandling → Symbols: validatePayment, handlePaymentError -2. context({name: "validatePayment"}) +2. context({name: "validatePayment", repo: "my-app"}) → Outgoing calls: verifyCard, fetchRates (external API!) 3. READ gitnexus://repo/my-app/process/CheckoutFlow → Step 3: validatePayment → calls fetchRates (external) 4. Root cause: fetchRates calls external API without proper timeout + Repository: my-app Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md b/gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md index 993a38481..c232565b1 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md @@ -1,21 +1,31 @@ --- name: gitnexus-exploring -description: Navigate unfamiliar code using GitNexus knowledge graph +description: "Use when the user asks how code works, wants to understand architecture, trace execution flows, or explore unfamiliar parts of the codebase. Examples: \"How does X work?\", \"What calls this function?\", \"Show me the auth flow\"" --- # Exploring Codebases with GitNexus ## When to Use + - "How does authentication work?" - "What's the project structure?" - "Show me the main components" - "Where is the database logic?" - Understanding code you haven't seen before +## Bind the repository first + +Step 1 discovers what is indexed; every call after it must say which of those +it means. With one indexed repository, use the examples below as written. With +more than one, pass `repo` on every call: an omitted `repo` normally errors, +but under an MCP policy with a configured default it resolves to that default +silently. If you cannot tell which repository is meant, stop and ask. Report +the bound repository and index freshness alongside your explanation. + ## Workflow ``` -1. READ gitnexus://repos → Discover indexed repos +1. list_repos {} or READ gitnexus://repos → Discover indexed repos 2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness 3. query({search_query: ""}) → Find related execution flows 4. context({name: ""}) → Deep dive on specific symbol @@ -27,44 +37,52 @@ description: Navigate unfamiliar code using GitNexus knowledge graph ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] READ gitnexus://repo/{name}/context - [ ] query for the concept you want to understand - [ ] Review returned processes (execution flows) - [ ] context on key symbols for callers/callees - [ ] READ process resource for full execution traces - [ ] Read source files for implementation details +- [ ] State the repository and index freshness with the explanation ``` ## Resources -| Resource | What you get | -|----------|-------------| -| `gitnexus://repo/{name}/context` | Stats, staleness warning (~150 tokens) | -| `gitnexus://repo/{name}/clusters` | All functional areas with cohesion scores (~300 tokens) | -| `gitnexus://repo/{name}/cluster/{name}` | Area members with file paths (~500 tokens) | -| `gitnexus://repo/{name}/process/{name}` | Step-by-step execution trace (~200 tokens) | +| Resource | What you get | +| --------------------------------------- | ------------------------------------------------------- | +| `gitnexus://repo/{name}/context` | Stats, staleness warning (~150 tokens) | +| `gitnexus://repo/{name}/clusters` | All functional areas with cohesion scores (~300 tokens) | +| `gitnexus://repo/{name}/cluster/{name}` | Area members with file paths (~500 tokens) | +| `gitnexus://repo/{name}/process/{name}` | Step-by-step execution trace (~200 tokens) | ## Tools **query** — find execution flows related to a concept: + ``` -query({search_query: "payment processing"}) +query({search_query: "payment processing", repo: "my-app"}) → Processes: CheckoutFlow, RefundFlow, WebhookHandler → Symbols grouped by flow with file locations ``` **context** — 360-degree view of a symbol: + ``` -context({name: "validateUser"}) +context({name: "validateUser", repo: "my-app"}) → Incoming calls: loginHandler, apiMiddleware → Outgoing calls: checkToken, getUserById → Processes: LoginFlow (step 2/5), TokenRefresh (step 1/3) ``` +`repo` is required once more than one repository is indexed, and may be omitted +with a single one. + ## Example: "How does payment processing work?" ``` -1. READ gitnexus://repo/my-app/context → 918 symbols, 45 processes +1. list_repos {} → total: 1 (my-app) — bind it + READ gitnexus://repo/my-app/context → 918 symbols, 45 processes 2. query({search_query: "payment processing"}) → CheckoutFlow: processPayment → validateCard → chargeStripe → RefundFlow: initiateRefund → calculateRefund → processRefund @@ -72,4 +90,8 @@ context({name: "validateUser"}) → Incoming: checkoutHandler, webhookHandler → Outgoing: validateCard, chargeStripe, saveTransaction 4. Read src/payments/processor.ts for implementation details +5. Answer, noting: Repository my-app, index current ``` + +Had step 1 returned two repositories, every call above would carry +`repo: "my-app"`. diff --git a/gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md b/gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md index e3817d111..4fb73f3e6 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-impact-analysis/SKILL.md @@ -1,11 +1,12 @@ --- name: gitnexus-impact-analysis -description: Analyze blast radius before making code changes +description: "Use when the user wants to know what will break if they change something, or needs safety analysis before editing code. Examples: \"Is it safe to change X?\", \"What depends on this?\", \"What will break?\"" --- # Impact Analysis with GitNexus ## When to Use + - "Is it safe to change this function?" - "What will break if I modify X?" - "Show me the blast radius" @@ -13,13 +14,42 @@ description: Analyze blast radius before making code changes - Before making non-trivial code changes - Before committing — to understand what your changes affect +## Bind the repository first + +Impact analysis is the gate that authorizes an edit, so it must answer for the +repository you are about to edit. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask — every result below an ambiguous +identity inherits the ambiguity. `list_repos` is paginated, so page with +`offset: pagination.nextOffset` until `hasMore` is false before concluding a +repository is absent. + +`detect_changes` takes `worktree` when your changes are in a linked worktree +the MCP server was not launched from. The server auto-detects a worktree only +when it was launched from inside one; otherwise `git diff` runs in the wrong +checkout and reports zero changed symbols — a false clean check that carries +none of the degradation flags described below. In the CLI fallbacks, `--repo .` +means the current checkout; pass the intended repository path instead when you +are not standing in it. + +State the bound identity with your risk report: + +``` +Repository: () Worktree: Index: , behind HEAD +``` + ## Workflow ``` +0. list_repos {} → Bind repo (and worktree) 1. impact({target: "X", direction: "upstream"}) or `node .gitnexus/run.cjs impact "X" --direction upstream --repo .` 2. READ gitnexus://repo/{name}/processes → Check affected execution flows 3. detect_changes({scope: "all"}) or `node .gitnexus/run.cjs detect-changes --scope all --repo .` -4. Assess risk and report to user +4. Assess risk and report to user, echoing repo/worktree/index identity ``` > If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. @@ -28,31 +58,31 @@ description: Analyze blast radius before making code changes ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] impact({target, direction: "upstream"}) or CLI fallback to find dependents - [ ] Review d=1 items first (these WILL BREAK) - [ ] Check high-confidence (>0.8) dependencies - [ ] READ processes to check affected execution flows - [ ] detect_changes({scope: "all"}) or CLI fallback for pre-commit check -- [ ] Assess risk level and report to user +- [ ] Confirm the checkout you edited is the checkout that was diffed +- [ ] Assess risk level and report, stating repo/worktree/index identity ``` -> `partial: true` (a graph query failed) or `truncated: true` (the changed-symbol listing was capped) means the result is short of the truth: a zero there means unseen, not unaffected. Re-run it rather than tick the pre-commit check. - ## Understanding Output -| Depth | Risk Level | Meaning | -|-------|-----------|---------| -| d=1 | **WILL BREAK** | Direct callers/importers | -| d=2 | LIKELY AFFECTED | Indirect dependencies | -| d=3 | MAY NEED TESTING | Transitive effects | +| Depth | Risk Level | Meaning | +| ----- | ---------------- | ------------------------ | +| d=1 | **WILL BREAK** | Direct callers/importers | +| d=2 | LIKELY AFFECTED | Indirect dependencies | +| d=3 | MAY NEED TESTING | Transitive effects | ## Risk Assessment -| Affected | Risk | -|----------|------| -| <5 symbols, few processes | LOW | -| 5-15 symbols, 2-5 processes | MEDIUM | -| >15 symbols or many processes | HIGH | +| Affected | Risk | +| ------------------------------ | -------- | +| <5 symbols, few processes | LOW | +| 5-15 symbols, 2-5 processes | MEDIUM | +| >15 symbols or many processes | HIGH | | Critical path (auth, payments) | CRITICAL | | **Zero callers found** | **UNKNOWN** | @@ -66,9 +96,11 @@ treating the symbol as safe to change or delete. ## Tools **impact** — the primary tool for symbol blast radius. If MCP is unavailable, use `node .gitnexus/run.cjs impact --direction upstream --repo .` instead: + ``` impact({ target: "validateUser", + repo: "my-app", // required once >1 repository is indexed direction: "upstream", minConfidence: 0.8, maxDepth: 3 @@ -83,6 +115,7 @@ impact({ ``` **detect_changes** — git-diff based impact analysis. If MCP is unavailable, use `node .gitnexus/run.cjs detect-changes --scope all --repo .` instead: + ``` detect_changes({scope: "all"}) @@ -91,10 +124,26 @@ detect_changes({scope: "all"}) → Risk: MEDIUM ``` +Add `repo` once more than one repository is indexed, and `worktree: ""` when your changes are in a linked worktree the server was not launched +from. + +`partial: true` (a graph query failed) or `truncated: true` (the changed-symbol +listing was capped) means the result is short of the truth, and reads like +`UNKNOWN` above: a zero there means unseen, not unaffected. Re-run it rather +than tick the pre-commit check. + +A wrong-worktree zero carries neither flag and is shape-identical to a genuine +clean result, so confirm the checkout you edited is the one that was diffed +before treating an empty change set as a passed check. + ## Example: "What breaks if I change validateUser?" ``` -1. impact({target: "validateUser", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` +0. list_repos {} + → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly + +1. impact({target: "validateUser", repo: "my-app", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` → d=1: loginHandler, apiMiddleware (WILL BREAK) → d=2: authRouter, sessionManager (LIKELY AFFECTED) @@ -102,4 +151,8 @@ detect_changes({scope: "all"}) → LoginFlow and TokenRefresh touch validateUser 3. Risk: 2 direct callers, 2 processes = MEDIUM + Repository: my-app (/abs/path/my-app) Worktree: same Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md b/gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md index 66f2c2982..6c5412b51 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md @@ -1,20 +1,41 @@ --- name: gitnexus-refactoring -description: Plan safe refactors using blast radius and dependency mapping +description: "Use when the user wants to rename, extract, split, move, or restructure code safely. Examples: \"Rename this function\", \"Extract this into a module\", \"Refactor this class\", \"Move this to a separate file\"" --- # Refactoring with GitNexus ## When to Use + - "Rename this function safely" - "Extract this into a module" - "Split this service" - "Move this to a new file" - Any task involving renaming, extracting, splitting, or restructuring code +## Bind the repository first + +Refactoring writes to disk. `rename` with `dry_run: false` edits files in +whichever repository was resolved, so binding identity here is a safety gate, +not bookkeeping. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. Never run `rename` with +`dry_run: false` until the preview in the same bound repository has been +reviewed — its returned `file_path` values show which checkout is about to be +written, so read them as a confirmation of identity. + +`detect_changes` takes `worktree` when you are editing a linked worktree the +MCP server was not launched from; otherwise `git diff` runs in the wrong +checkout and reports nothing changed, which reads as a verified refactor. + ## Workflow ``` +0. list_repos {} → Bind repo (and worktree) 1. impact({target: "X", direction: "upstream"}) → Map all dependents 2. query({search_query: "X"}) → Find execution flows involving X 3. context({name: "X"}) → See all incoming/outgoing refs @@ -23,13 +44,14 @@ description: Plan safe refactors using blast radius and dependency mapping > If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. -> Every `detect_changes()` below: `partial: true` (a graph query failed) or `truncated: true` (the changed-symbol listing was capped) means the result is short of the truth — a short or empty list is not proof that only the expected files changed. Re-run it rather than treat the refactor as verified. - ## Checklists ### Rename Symbol + ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] rename({symbol_name: "oldName", new_name: "newName", dry_run: true}) — preview all edits +- [ ] Confirm the previewed file paths are in the bound repository/worktree - [ ] Review graph edits (high confidence) and text_search edits (review carefully) - [ ] If satisfied: rename({..., dry_run: false}) — apply edits - [ ] detect_changes() — verify only expected files changed @@ -37,7 +59,9 @@ description: Plan safe refactors using blast radius and dependency mapping ``` ### Extract Module + ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — see all incoming/outgoing refs - [ ] impact({target, direction: "upstream"}) — find all external callers - [ ] Define new module interface @@ -47,7 +71,9 @@ description: Plan safe refactors using blast radius and dependency mapping ``` ### Split Function/Service + ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — understand all callees - [ ] Group callees by responsibility - [ ] impact({target, direction: "upstream"}) — map callers to update @@ -60,21 +86,24 @@ description: Plan safe refactors using blast radius and dependency mapping ## Tools **rename** — automated multi-file rename: + ``` -rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true}) +rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits across 8 files → 10 graph edits (high confidence), 2 text_search edits (review) → Changes: [{file_path, edits: [{line, old_text, new_text, confidence}]}] ``` **impact** — map all dependents first: + ``` -impact({target: "validateUser", direction: "upstream"}) +impact({target: "validateUser", repo: "my-app", direction: "upstream"}) → d=1: loginHandler, apiMiddleware, testUtils → Affected Processes: LoginFlow, TokenRefresh ``` **detect_changes** — verify your changes after refactoring: + ``` detect_changes({scope: "all"}) → Changed: 8 files, 12 symbols @@ -82,7 +111,16 @@ detect_changes({scope: "all"}) → Risk: MEDIUM ``` +`partial: true` (a graph query failed) or `truncated: true` (the changed-symbol +listing was capped) means the result is short of the truth: a short or empty +list is not proof that only the expected files changed. Re-run it rather than +treat the refactor as verified. + +A wrong-worktree zero carries neither flag and is indistinguishable from a +clean verification, so confirm the diffed checkout is the one you edited. + **cypher** — custom reference queries: + ```cypher MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"}) RETURN caller.name, caller.filePath ORDER BY caller.filePath @@ -90,26 +128,34 @@ RETURN caller.name, caller.filePath ORDER BY caller.filePath ## Risk Rules -| Risk Factor | Mitigation | -|-------------|------------| -| Many callers (>5) | Use rename for automated updates | -| Cross-area refs | Use detect_changes after to verify scope | -| String/dynamic refs | query to find them | -| External/public API | Version and deprecate properly | +| Risk Factor | Mitigation | +| ------------------- | ----------------------------------------- | +| Many callers (>5) | Use rename for automated updates | +| Cross-area refs | Use detect_changes after to verify scope | +| String/dynamic refs | query to find them | +| External/public API | Version and deprecate properly | +| Same name in another indexed repo | Bind `repo`; verify previewed paths before applying | ## Example: Rename `validateUser` to `authenticateUser` ``` -1. rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true}) +0. list_repos {} + → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly + +1. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits: 10 graph (safe), 2 text_search (review) → Files: validator.ts, login.ts, middleware.ts, config.json... 2. Review text_search edits (config.json: dynamic reference!) -3. rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: false}) +3. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: false}) → Applied 12 edits across 8 files -4. detect_changes({scope: "all"}) +4. detect_changes({scope: "all", repo: "my-app"}) → Affected: LoginFlow, TokenRefresh → Risk: MEDIUM — run tests for these flows + Repository: my-app (/abs/path/my-app) Worktree: same Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus/skills/gitnexus-debugging.md b/gitnexus/skills/gitnexus-debugging.md index 4a33e589a..beebb532e 100644 --- a/gitnexus/skills/gitnexus-debugging.md +++ b/gitnexus/skills/gitnexus-debugging.md @@ -13,9 +13,25 @@ description: "Use when the user is debugging a bug, tracing an error, or asking - "This endpoint returns 500" - Investigating bugs, errors, or unexpected behavior +## Bind the repository first + +A root cause traced in the wrong repository is a wrong root cause. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. This matters most for `cypher`, whose +statement carries no in-band hint of which database it ran against. + +A stale index describes the code from before your bug, so refresh before +trusting a trace, and state the repository and index freshness with the +diagnosis. + ## Workflow ``` +0. list_repos {} → Bind repo 1. query({search_query: ""}) → Find related execution flows 2. context({name: ""}) → See callers/callees/processes 3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow @@ -27,6 +43,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] Understand the symptom (error message, unexpected behavior) - [ ] query for error text or related code - [ ] Identify the suspect function from returned processes @@ -34,6 +51,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking - [ ] Trace execution flow via process resource if applicable - [ ] cypher for custom call chain traces if needed - [ ] Read source files to confirm root cause +- [ ] State the repository and index freshness with the diagnosis ``` ## Debugging Patterns @@ -44,7 +62,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking | Wrong return value | `context` on the function → trace callees for data flow | | Intermittent failure | `context` → look for external calls, async deps | | Performance issue | `context` → find symbols with many callers (hot paths) | -| Recent regression | `detect_changes` to see what your changes affect | +| Recent regression | `detect_changes` to see what your changes affect — pass `worktree` for a linked worktree | | "How does A reach B?" | `trace` between the two symbols — shortest call chain in one call | ## Tools @@ -52,7 +70,7 @@ description: "Use when the user is debugging a bug, tracing an error, or asking **query** — find code related to error: ``` -query({search_query: "payment validation error"}) +query({search_query: "payment validation error", repo: "my-app"}) → Processes: CheckoutFlow, ErrorHandling → Symbols: validatePayment, handlePaymentError, PaymentException ``` @@ -60,13 +78,15 @@ query({search_query: "payment validation error"}) **context** — full context for a suspect: ``` -context({name: "validatePayment"}) +context({name: "validatePayment", repo: "my-app"}) → Incoming calls: processCheckout, webhookHandler → Outgoing calls: verifyCard, fetchRates (external API!) → Processes: CheckoutFlow (step 3/7) ``` -**cypher** — custom call chain traces: +**cypher** — custom call chain traces. Pass `repo` alongside the statement; the +Cypher text itself names no repository, so the result is unattributable without +it: ```cypher MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"}) @@ -76,7 +96,7 @@ RETURN [n IN nodes(path) | n.name] AS chain **trace** — shortest call chain between two symbols ("how does A reach B?"), one call instead of chaining `context` hops: ``` -trace({ from: "processCheckout", to: "fetchRates" }) +trace({ from: "processCheckout", to: "fetchRates", repo: "my-app" }) → status: ok, hopCount: 3 → hops: processCheckout → validatePayment → verifyCard → fetchRates → edges: CALLS (1.0), CALLS (0.95), CALLS (1.0) @@ -87,15 +107,22 @@ When no path exists, `trace` reports the furthest reachable node — exactly whe ## Example: "Payment endpoint returns 500 intermittently" ``` -1. query({search_query: "payment error handling"}) +0. list_repos {} + → total: 2 (my-app, billing-api) — bind my-app explicitly on every call + +1. query({search_query: "payment error handling", repo: "my-app"}) → Processes: CheckoutFlow, ErrorHandling → Symbols: validatePayment, handlePaymentError -2. context({name: "validatePayment"}) +2. context({name: "validatePayment", repo: "my-app"}) → Outgoing calls: verifyCard, fetchRates (external API!) 3. READ gitnexus://repo/my-app/process/CheckoutFlow → Step 3: validatePayment → calls fetchRates (external) 4. Root cause: fetchRates calls external API without proper timeout + Repository: my-app Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus/skills/gitnexus-exploring.md b/gitnexus/skills/gitnexus-exploring.md index f483c2fd6..c232565b1 100644 --- a/gitnexus/skills/gitnexus-exploring.md +++ b/gitnexus/skills/gitnexus-exploring.md @@ -13,10 +13,19 @@ description: "Use when the user asks how code works, wants to understand archite - "Where is the database logic?" - Understanding code you haven't seen before +## Bind the repository first + +Step 1 discovers what is indexed; every call after it must say which of those +it means. With one indexed repository, use the examples below as written. With +more than one, pass `repo` on every call: an omitted `repo` normally errors, +but under an MCP policy with a configured default it resolves to that default +silently. If you cannot tell which repository is meant, stop and ask. Report +the bound repository and index freshness alongside your explanation. + ## Workflow ``` -1. READ gitnexus://repos → Discover indexed repos +1. list_repos {} or READ gitnexus://repos → Discover indexed repos 2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness 3. query({search_query: ""}) → Find related execution flows 4. context({name: ""}) → Deep dive on specific symbol @@ -28,12 +37,14 @@ description: "Use when the user asks how code works, wants to understand archite ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] READ gitnexus://repo/{name}/context - [ ] query for the concept you want to understand - [ ] Review returned processes (execution flows) - [ ] context on key symbols for callers/callees - [ ] READ process resource for full execution traces - [ ] Read source files for implementation details +- [ ] State the repository and index freshness with the explanation ``` ## Resources @@ -50,7 +61,7 @@ description: "Use when the user asks how code works, wants to understand archite **query** — find execution flows related to a concept: ``` -query({search_query: "payment processing"}) +query({search_query: "payment processing", repo: "my-app"}) → Processes: CheckoutFlow, RefundFlow, WebhookHandler → Symbols grouped by flow with file locations ``` @@ -58,16 +69,20 @@ query({search_query: "payment processing"}) **context** — 360-degree view of a symbol: ``` -context({name: "validateUser"}) +context({name: "validateUser", repo: "my-app"}) → Incoming calls: loginHandler, apiMiddleware → Outgoing calls: checkToken, getUserById → Processes: LoginFlow (step 2/5), TokenRefresh (step 1/3) ``` +`repo` is required once more than one repository is indexed, and may be omitted +with a single one. + ## Example: "How does payment processing work?" ``` -1. READ gitnexus://repo/my-app/context → 918 symbols, 45 processes +1. list_repos {} → total: 1 (my-app) — bind it + READ gitnexus://repo/my-app/context → 918 symbols, 45 processes 2. query({search_query: "payment processing"}) → CheckoutFlow: processPayment → validateCard → chargeStripe → RefundFlow: initiateRefund → calculateRefund → processRefund @@ -75,4 +90,8 @@ context({name: "validateUser"}) → Incoming: checkoutHandler, webhookHandler → Outgoing: validateCard, chargeStripe, saveTransaction 4. Read src/payments/processor.ts for implementation details +5. Answer, noting: Repository my-app, index current ``` + +Had step 1 returned two repositories, every call above would carry +`repo: "my-app"`. diff --git a/gitnexus/skills/gitnexus-impact-analysis.md b/gitnexus/skills/gitnexus-impact-analysis.md index ee1cd3496..4fb73f3e6 100644 --- a/gitnexus/skills/gitnexus-impact-analysis.md +++ b/gitnexus/skills/gitnexus-impact-analysis.md @@ -14,13 +14,42 @@ description: "Use when the user wants to know what will break if they change som - Before making non-trivial code changes - Before committing — to understand what your changes affect +## Bind the repository first + +Impact analysis is the gate that authorizes an edit, so it must answer for the +repository you are about to edit. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask — every result below an ambiguous +identity inherits the ambiguity. `list_repos` is paginated, so page with +`offset: pagination.nextOffset` until `hasMore` is false before concluding a +repository is absent. + +`detect_changes` takes `worktree` when your changes are in a linked worktree +the MCP server was not launched from. The server auto-detects a worktree only +when it was launched from inside one; otherwise `git diff` runs in the wrong +checkout and reports zero changed symbols — a false clean check that carries +none of the degradation flags described below. In the CLI fallbacks, `--repo .` +means the current checkout; pass the intended repository path instead when you +are not standing in it. + +State the bound identity with your risk report: + +``` +Repository: () Worktree: Index: , behind HEAD +``` + ## Workflow ``` +0. list_repos {} → Bind repo (and worktree) 1. impact({target: "X", direction: "upstream"}) or `node .gitnexus/run.cjs impact "X" --direction upstream --repo .` 2. READ gitnexus://repo/{name}/processes → Check affected execution flows 3. detect_changes({scope: "all"}) or `node .gitnexus/run.cjs detect-changes --scope all --repo .` -4. Assess risk and report to user +4. Assess risk and report to user, echoing repo/worktree/index identity ``` > If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal. @@ -29,12 +58,14 @@ description: "Use when the user wants to know what will break if they change som ## Checklist ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] impact({target, direction: "upstream"}) or CLI fallback to find dependents - [ ] Review d=1 items first (these WILL BREAK) - [ ] Check high-confidence (>0.8) dependencies - [ ] READ processes to check affected execution flows - [ ] detect_changes({scope: "all"}) or CLI fallback for pre-commit check -- [ ] Assess risk level and report to user +- [ ] Confirm the checkout you edited is the checkout that was diffed +- [ ] Assess risk level and report, stating repo/worktree/index identity ``` ## Understanding Output @@ -69,6 +100,7 @@ treating the symbol as safe to change or delete. ``` impact({ target: "validateUser", + repo: "my-app", // required once >1 repository is indexed direction: "upstream", minConfidence: 0.8, maxDepth: 3 @@ -92,15 +124,26 @@ detect_changes({scope: "all"}) → Risk: MEDIUM ``` +Add `repo` once more than one repository is indexed, and `worktree: ""` when your changes are in a linked worktree the server was not launched +from. + `partial: true` (a graph query failed) or `truncated: true` (the changed-symbol listing was capped) means the result is short of the truth, and reads like `UNKNOWN` above: a zero there means unseen, not unaffected. Re-run it rather than tick the pre-commit check. +A wrong-worktree zero carries neither flag and is shape-identical to a genuine +clean result, so confirm the checkout you edited is the one that was diffed +before treating an empty change set as a passed check. + ## Example: "What breaks if I change validateUser?" ``` -1. impact({target: "validateUser", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` +0. list_repos {} + → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly + +1. impact({target: "validateUser", repo: "my-app", direction: "upstream"}) or `node .gitnexus/run.cjs impact "validateUser" --direction upstream --repo .` → d=1: loginHandler, apiMiddleware (WILL BREAK) → d=2: authRouter, sessionManager (LIKELY AFFECTED) @@ -108,4 +151,8 @@ than tick the pre-commit check. → LoginFlow and TokenRefresh touch validateUser 3. Risk: 2 direct callers, 2 processes = MEDIUM + Repository: my-app (/abs/path/my-app) Worktree: same Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above. diff --git a/gitnexus/skills/gitnexus-refactoring.md b/gitnexus/skills/gitnexus-refactoring.md index 4f10bbc6a..6c5412b51 100644 --- a/gitnexus/skills/gitnexus-refactoring.md +++ b/gitnexus/skills/gitnexus-refactoring.md @@ -13,9 +13,29 @@ description: "Use when the user wants to rename, extract, split, move, or restru - "Move this to a new file" - Any task involving renaming, extracting, splitting, or restructuring code +## Bind the repository first + +Refactoring writes to disk. `rename` with `dry_run: false` edits files in +whichever repository was resolved, so binding identity here is a safety gate, +not bookkeeping. + +Call `list_repos {}` before the first tool call. With one indexed repository, +use the examples below as written. With more than one, pass `repo` on every +call: an omitted `repo` normally errors, but under an MCP policy with a +configured default it resolves to that default silently. If you cannot tell +which repository is meant, stop and ask. Never run `rename` with +`dry_run: false` until the preview in the same bound repository has been +reviewed — its returned `file_path` values show which checkout is about to be +written, so read them as a confirmation of identity. + +`detect_changes` takes `worktree` when you are editing a linked worktree the +MCP server was not launched from; otherwise `git diff` runs in the wrong +checkout and reports nothing changed, which reads as a verified refactor. + ## Workflow ``` +0. list_repos {} → Bind repo (and worktree) 1. impact({target: "X", direction: "upstream"}) → Map all dependents 2. query({search_query: "X"}) → Find execution flows involving X 3. context({name: "X"}) → See all incoming/outgoing refs @@ -29,7 +49,9 @@ description: "Use when the user wants to rename, extract, split, move, or restru ### Rename Symbol ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] rename({symbol_name: "oldName", new_name: "newName", dry_run: true}) — preview all edits +- [ ] Confirm the previewed file paths are in the bound repository/worktree - [ ] Review graph edits (high confidence) and text_search edits (review carefully) - [ ] If satisfied: rename({..., dry_run: false}) — apply edits - [ ] detect_changes() — verify only expected files changed @@ -39,6 +61,7 @@ description: "Use when the user wants to rename, extract, split, move, or restru ### Extract Module ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — see all incoming/outgoing refs - [ ] impact({target, direction: "upstream"}) — find all external callers - [ ] Define new module interface @@ -50,6 +73,7 @@ description: "Use when the user wants to rename, extract, split, move, or restru ### Split Function/Service ``` +- [ ] list_repos {} — bind repo; explicit repo when >1 indexed, ask if ambiguous - [ ] context({name: target}) — understand all callees - [ ] Group callees by responsibility - [ ] impact({target, direction: "upstream"}) — map callers to update @@ -64,7 +88,7 @@ description: "Use when the user wants to rename, extract, split, move, or restru **rename** — automated multi-file rename: ``` -rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true}) +rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits across 8 files → 10 graph edits (high confidence), 2 text_search edits (review) → Changes: [{file_path, edits: [{line, old_text, new_text, confidence}]}] @@ -73,7 +97,7 @@ rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true **impact** — map all dependents first: ``` -impact({target: "validateUser", direction: "upstream"}) +impact({target: "validateUser", repo: "my-app", direction: "upstream"}) → d=1: loginHandler, apiMiddleware, testUtils → Affected Processes: LoginFlow, TokenRefresh ``` @@ -92,6 +116,9 @@ listing was capped) means the result is short of the truth: a short or empty list is not proof that only the expected files changed. Re-run it rather than treat the refactor as verified. +A wrong-worktree zero carries neither flag and is indistinguishable from a +clean verification, so confirm the diffed checkout is the one you edited. + **cypher** — custom reference queries: ```cypher @@ -107,20 +134,28 @@ RETURN caller.name, caller.filePath ORDER BY caller.filePath | Cross-area refs | Use detect_changes after to verify scope | | String/dynamic refs | query to find them | | External/public API | Version and deprecate properly | +| Same name in another indexed repo | Bind `repo`; verify previewed paths before applying | ## Example: Rename `validateUser` to `authenticateUser` ``` -1. rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true}) +0. list_repos {} + → total: 2 (my-app, billing-api) — both define validateUser, so bind explicitly + +1. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: true}) → 12 edits: 10 graph (safe), 2 text_search (review) → Files: validator.ts, login.ts, middleware.ts, config.json... 2. Review text_search edits (config.json: dynamic reference!) -3. rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: false}) +3. rename({symbol_name: "validateUser", new_name: "authenticateUser", repo: "my-app", dry_run: false}) → Applied 12 edits across 8 files -4. detect_changes({scope: "all"}) +4. detect_changes({scope: "all", repo: "my-app"}) → Affected: LoginFlow, TokenRefresh → Risk: MEDIUM — run tests for these flows + Repository: my-app (/abs/path/my-app) Worktree: same Index: current ``` + +With a single indexed repository, step 0 returns `total: 1` and the `repo` +argument drops out of every call above.