docs(claude-skills): update gitnexus-refactoring

This commit is contained in:
sanguine59 2026-08-16 14:05:49 +07:00
parent c4564b0226
commit d5914f6248

View file

@ -13,67 +13,95 @@ 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 {}`. 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`.
Never run `rename` with `dry_run: false` until the preview in the same bound
repository has been reviewed.
## Workflow
```
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
0. list_repos {} → Bind repo (and worktree)
1. impact({target: "X", direction: "upstream"[, repo: "<repo>"]}) → Map all dependents
2. query({search_query: "X"[, repo: "<repo>"]}) → Find execution flows involving X
3. context({name: "X"[, repo: "<repo>"]}) → See all incoming/outgoing refs
4. Plan update order: interfaces → implementations → callers → tests
```
> If "Index is stale" → run `node .gitnexus/run.cjs analyze` in terminal.
> 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.
## Checklists
### Rename Symbol
```
- [ ] list_repos {} — bind repo; explicit repo when total > 1, 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
- [ ] detect_changes({scope: "all"}) — verify only expected files changed
- [ ] Run tests for affected processes
```
### Extract Module
```
- [ ] list_repos {} — bind repo; explicit repo when total > 1, 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() — verify affected scope
- [ ] detect_changes({scope: "all"}) — verify affected scope
- [ ] Run tests for affected processes
```
### Split Function/Service
```
- [ ] list_repos {} — bind repo; explicit repo when total > 1, 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() — verify affected scope
- [ ] detect_changes({scope: "all"}) — 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:
```
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}]}]
```
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:
```
impact({target: "validateUser", direction: "upstream"})
impact({target: "validateUser", repo: "my-app", direction: "upstream"})
→ d=1: loginHandler, apiMiddleware, testUtils
→ Affected Processes: LoginFlow, TokenRefresh
```
@ -81,7 +109,7 @@ impact({target: "validateUser", direction: "upstream"})
**detect_changes** — verify your changes after refactoring:
```
detect_changes({scope: "all"})
detect_changes({scope: "all", repo: "my-app", worktree: "/abs/path/to/checkout"})
→ Changed: 8 files, 12 symbols
→ Affected processes: LoginFlow, TokenRefresh
→ Risk: MEDIUM
@ -89,14 +117,19 @@ detect_changes({scope: "all"})
`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.
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.
**cypher** — custom reference queries:
**cypher** — custom reference queries. Pass `repo` alongside the statement; the
Cypher text names no repository:
```cypher
```
cypher({repo: "my-app", statement: `
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"})
RETURN caller.name, caller.filePath ORDER BY caller.filePath
`})
```
## Risk Rules
@ -107,20 +140,31 @@ 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 |
## 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...
→ 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", 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.