From fc885a4bf3edddf9214df633d8d1c0767ef58af9 Mon Sep 17 00:00:00 2001 From: Shane Thurston Wijaya <129602553+sanguine59@users.noreply.github.com> Date: Tue, 18 Aug 2026 21:09:09 +0700 Subject: [PATCH] docs(claude-skills): bind repository and worktree identity in multi repo skills (#2981) --- .claude/skills/gitnexus-debugging/SKILL.md | 44 ++++++++-- .claude/skills/gitnexus-exploring/SKILL.md | 30 ++++++- .../skills/gitnexus-impact-analysis/SKILL.md | 53 +++++++++++- .claude/skills/gitnexus-refactoring/SKILL.md | 48 +++++++++-- .../skills/gitnexus-debugging/SKILL.md | 44 ++++++++-- .../skills/gitnexus-exploring/SKILL.md | 30 ++++++- .../skills/gitnexus-impact-analysis/SKILL.md | 53 +++++++++++- .../skills/gitnexus-refactoring/SKILL.md | 48 +++++++++-- .../skills/gitnexus-debugging/SKILL.md | 63 +++++++++++--- .../skills/gitnexus-exploring/SKILL.md | 47 +++++++--- .../skills/gitnexus-impact-analysis/SKILL.md | 85 +++++++++++++++---- .../skills/gitnexus-refactoring/SKILL.md | 77 ++++++++++++++--- gitnexus/skills/gitnexus-debugging.md | 44 ++++++++-- gitnexus/skills/gitnexus-exploring.md | 30 ++++++- gitnexus/skills/gitnexus-impact-analysis.md | 53 +++++++++++- gitnexus/skills/gitnexus-refactoring.md | 48 +++++++++-- .../test/unit/shipped-skills-sync.test.ts | 38 +++++++++ 17 files changed, 723 insertions(+), 112 deletions(-) diff --git a/.claude/skills/gitnexus-debugging/SKILL.md b/.claude/skills/gitnexus-debugging/SKILL.md index 4a33e589a..41fb568f8 100644 --- a/.claude/skills/gitnexus-debugging/SKILL.md +++ b/.claude/skills/gitnexus-debugging/SKILL.md @@ -13,9 +13,28 @@ 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + +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 +46,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 +54,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 +65,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 +73,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 +81,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 +99,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 +110,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/.claude/skills/gitnexus-exploring/SKILL.md b/.claude/skills/gitnexus-exploring/SKILL.md index f483c2fd6..46fc187ce 100644 --- a/.claude/skills/gitnexus-exploring/SKILL.md +++ b/.claude/skills/gitnexus-exploring/SKILL.md @@ -13,10 +13,22 @@ 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + ## 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 +40,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 +64,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 +72,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 +93,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/.claude/skills/gitnexus-impact-analysis/SKILL.md b/.claude/skills/gitnexus-impact-analysis/SKILL.md index ee1cd3496..4fb73f3e6 100644 --- a/.claude/skills/gitnexus-impact-analysis/SKILL.md +++ b/.claude/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/.claude/skills/gitnexus-refactoring/SKILL.md b/.claude/skills/gitnexus-refactoring/SKILL.md index 4f10bbc6a..9d63eb6e3 100644 --- a/.claude/skills/gitnexus-refactoring/SKILL.md +++ b/.claude/skills/gitnexus-refactoring/SKILL.md @@ -13,9 +13,32 @@ 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. + +`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 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 +52,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 +64,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 +76,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 +91,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 +100,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 +119,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 +137,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-claude-plugin/skills/gitnexus-debugging/SKILL.md b/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md index 4a33e589a..41fb568f8 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-debugging/SKILL.md @@ -13,9 +13,28 @@ 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + +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 +46,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 +54,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 +65,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 +73,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 +81,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 +99,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 +110,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..46fc187ce 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-exploring/SKILL.md @@ -13,10 +13,22 @@ 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + ## 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 +40,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 +64,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 +72,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 +93,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..9d63eb6e3 100644 --- a/gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md +++ b/gitnexus-claude-plugin/skills/gitnexus-refactoring/SKILL.md @@ -13,9 +13,32 @@ 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. + +`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 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 +52,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 +64,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 +76,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 +91,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 +100,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 +119,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 +137,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..41fb568f8 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-debugging/SKILL.md @@ -1,20 +1,40 @@ --- 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + +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 +46,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 +54,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 +110,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..46fc187ce 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-exploring/SKILL.md @@ -1,21 +1,34 @@ --- 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + ## 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 +40,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 +93,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..9d63eb6e3 100644 --- a/gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md +++ b/gitnexus-cursor-integration/skills/gitnexus-refactoring/SKILL.md @@ -1,20 +1,44 @@ --- 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. + +`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 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 +47,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 +62,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 +74,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 +89,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 +114,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 +131,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..41fb568f8 100644 --- a/gitnexus/skills/gitnexus-debugging.md +++ b/gitnexus/skills/gitnexus-debugging.md @@ -13,9 +13,28 @@ 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + +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 +46,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 +54,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 +65,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 +73,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 +81,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 +99,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 +110,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..46fc187ce 100644 --- a/gitnexus/skills/gitnexus-exploring.md +++ b/gitnexus/skills/gitnexus-exploring.md @@ -13,10 +13,22 @@ 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. + +`list_repos` is paginated, so page with `offset: pagination.nextOffset` until +`hasMore` is false before concluding a repository is absent. + ## 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 +40,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 +64,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 +72,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 +93,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..9d63eb6e3 100644 --- a/gitnexus/skills/gitnexus-refactoring.md +++ b/gitnexus/skills/gitnexus-refactoring.md @@ -13,9 +13,32 @@ 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. + +`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 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 +52,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 +64,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 +76,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 +91,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 +100,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 +119,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 +137,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/test/unit/shipped-skills-sync.test.ts b/gitnexus/test/unit/shipped-skills-sync.test.ts index 52501f5c3..c82e45321 100644 --- a/gitnexus/test/unit/shipped-skills-sync.test.ts +++ b/gitnexus/test/unit/shipped-skills-sync.test.ts @@ -247,6 +247,44 @@ describe('intended standard-skill improvements stay in every applicable copy', ( } }); + // Same reasoning as the UNKNOWN guard above: these copies are not + // byte-compared, so an edit to one copy alone silently ships four + // distributions that disagree about whether identity is required. The + // fragments are matched against whitespace-normalized text because the + // copies wrap the same sentences at different columns. + const IDENTITY_CONTRACT_SKILLS = [ + 'gitnexus-impact-analysis', + 'gitnexus-refactoring', + 'gitnexus-debugging', + 'gitnexus-exploring', + ] as const; + + const normalize = (text: string): string => text.replace(/\s+/g, ' '); + + it.each(IDENTITY_CONTRACT_SKILLS)( + 'keeps the repository-identity contract in every %s copy', + (name) => { + const required = [ + 'list_repos {}', + '`offset: pagination.nextOffset`', + '`hasMore` is false', + + 'an omitted `repo` normally errors', + 'stop and ask', + + 'repo: "my-app"', + + 'bind repo; explicit repo when >1 indexed, ask if ambiguous', + ]; + const copies = standardSkillCopies(name); + expect(copies.length).toBeGreaterThan(1); + for (const file of copies) { + const content = normalize(fs.readFileSync(file, 'utf-8')); + for (const fragment of required) expect(content).toContain(normalize(fragment)); + } + }, + ); + it("uses the rename API's text_search vocabulary in every refactoring copy", () => { for (const file of standardSkillCopies('gitnexus-refactoring')) { const content = fs.readFileSync(file, 'utf-8');