purecontext-mcp 1.5.2 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_INSTRUCTIONS.md +18 -10
- package/AGENT_REFERENCE.md +684 -561
- package/CHANGELOG.md +567 -445
- package/CODE-HISTORY.md +29 -1
- package/FRAMEWORK-ADAPTERS.md +368 -351
- package/FULL-INSTALLATION-GUIDE.md +351 -341
- package/README.md +411 -339
- package/REFACTORING-SAFELY.md +338 -279
- package/SAFE-CHANGES.md +208 -156
- package/USER-GUIDE.md +3 -1
- package/WHY-PURECONTEXT.md +103 -73
- package/WORKFLOW-PR-REVIEW.md +245 -199
- package/dist/adapters/astro-preprocessor.d.ts +25 -0
- package/dist/adapters/astro-preprocessor.d.ts.map +1 -0
- package/dist/adapters/astro-preprocessor.js +50 -0
- package/dist/adapters/astro-preprocessor.js.map +1 -0
- package/dist/adapters/astro.d.ts +13 -0
- package/dist/adapters/astro.d.ts.map +1 -0
- package/dist/adapters/astro.js +83 -0
- package/dist/adapters/astro.js.map +1 -0
- package/dist/adapters/detect-utils.d.ts +38 -0
- package/dist/adapters/detect-utils.d.ts.map +1 -0
- package/dist/adapters/detect-utils.js +95 -0
- package/dist/adapters/detect-utils.js.map +1 -0
- package/dist/adapters/nuxt.d.ts +20 -0
- package/dist/adapters/nuxt.d.ts.map +1 -1
- package/dist/adapters/nuxt.js +128 -13
- package/dist/adapters/nuxt.js.map +1 -1
- package/dist/adapters/svelte-preprocessor.d.ts +29 -0
- package/dist/adapters/svelte-preprocessor.d.ts.map +1 -0
- package/dist/adapters/svelte-preprocessor.js +83 -0
- package/dist/adapters/svelte-preprocessor.js.map +1 -0
- package/dist/adapters/svelte.d.ts +13 -0
- package/dist/adapters/svelte.d.ts.map +1 -0
- package/dist/adapters/svelte.js +96 -0
- package/dist/adapters/svelte.js.map +1 -0
- package/dist/adapters/vue.d.ts.map +1 -1
- package/dist/adapters/vue.js +87 -20
- package/dist/adapters/vue.js.map +1 -1
- package/dist/bin.d.ts +16 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +21 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/hooks.d.ts +2 -2
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +123 -135
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/install-writers.d.ts.map +1 -1
- package/dist/cli/install-writers.js +281 -36
- package/dist/cli/install-writers.js.map +1 -1
- package/dist/cli/resolve-node.d.ts +53 -0
- package/dist/cli/resolve-node.d.ts.map +1 -0
- package/dist/cli/resolve-node.js +84 -0
- package/dist/cli/resolve-node.js.map +1 -0
- package/dist/config/config-loader.js +24 -0
- package/dist/config/config-loader.js.map +1 -1
- package/dist/config/config-schema.d.ts +71 -0
- package/dist/config/config-schema.d.ts.map +1 -1
- package/dist/config/config-schema.js +102 -0
- package/dist/config/config-schema.js.map +1 -1
- package/dist/core/db/api-keys.d.ts +1 -1
- package/dist/core/db/api-keys.d.ts.map +1 -1
- package/dist/core/db/api-keys.js +39 -39
- package/dist/core/db/api-keys.js.map +1 -1
- package/dist/core/db/co-change-store.d.ts +34 -0
- package/dist/core/db/co-change-store.d.ts.map +1 -0
- package/dist/core/db/co-change-store.js +78 -0
- package/dist/core/db/co-change-store.js.map +1 -0
- package/dist/core/db/schema.d.ts +3 -3
- package/dist/core/db/schema.d.ts.map +1 -1
- package/dist/core/db/schema.js +12 -30
- package/dist/core/db/schema.js.map +1 -1
- package/dist/core/db/sqlite-loader.d.ts +51 -0
- package/dist/core/db/sqlite-loader.d.ts.map +1 -0
- package/dist/core/db/sqlite-loader.js +94 -0
- package/dist/core/db/sqlite-loader.js.map +1 -0
- package/dist/core/db/wasm-sqlite.d.ts +4 -0
- package/dist/core/db/wasm-sqlite.d.ts.map +1 -0
- package/dist/core/db/wasm-sqlite.js +270 -0
- package/dist/core/db/wasm-sqlite.js.map +1 -0
- package/dist/core/diff-parser.d.ts.map +1 -1
- package/dist/core/diff-parser.js +6 -1
- package/dist/core/diff-parser.js.map +1 -1
- package/dist/core/git-log-reader.d.ts +28 -0
- package/dist/core/git-log-reader.d.ts.map +1 -1
- package/dist/core/git-log-reader.js +74 -3
- package/dist/core/git-log-reader.js.map +1 -1
- package/dist/core/index-manager.d.ts.map +1 -1
- package/dist/core/index-manager.js +29 -3
- package/dist/core/index-manager.js.map +1 -1
- package/dist/core/indexing-worker.d.ts +2 -0
- package/dist/core/indexing-worker.d.ts.map +1 -1
- package/dist/core/indexing-worker.js +2 -0
- package/dist/core/indexing-worker.js.map +1 -1
- package/dist/core/watcher/file-watcher.d.ts +6 -0
- package/dist/core/watcher/file-watcher.d.ts.map +1 -1
- package/dist/core/watcher/file-watcher.js +11 -1
- package/dist/core/watcher/file-watcher.js.map +1 -1
- package/dist/graph/path-resolver.js +86 -17
- package/dist/graph/path-resolver.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/node-guard.d.ts +15 -0
- package/dist/node-guard.d.ts.map +1 -0
- package/dist/node-guard.js +33 -0
- package/dist/node-guard.js.map +1 -0
- package/dist/server/admin-api.d.ts +1 -1
- package/dist/server/admin-api.d.ts.map +1 -1
- package/dist/server/admin-api.js +2 -2
- package/dist/server/admin-api.js.map +1 -1
- package/dist/server/auth/api-key.d.ts +1 -1
- package/dist/server/auth/api-key.d.ts.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +25 -0
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/tools/analyze-diff.d.ts +8 -0
- package/dist/server/tools/analyze-diff.d.ts.map +1 -1
- package/dist/server/tools/analyze-diff.js +80 -16
- package/dist/server/tools/analyze-diff.js.map +1 -1
- package/dist/server/tools/change-synthesis.d.ts +90 -0
- package/dist/server/tools/change-synthesis.d.ts.map +1 -0
- package/dist/server/tools/change-synthesis.js +236 -0
- package/dist/server/tools/change-synthesis.js.map +1 -0
- package/dist/server/tools/co-change.d.ts +65 -0
- package/dist/server/tools/co-change.d.ts.map +1 -0
- package/dist/server/tools/co-change.js +146 -0
- package/dist/server/tools/co-change.js.map +1 -0
- package/dist/server/tools/compare-change-impact.d.ts +58 -0
- package/dist/server/tools/compare-change-impact.d.ts.map +1 -0
- package/dist/server/tools/compare-change-impact.js +0 -0
- package/dist/server/tools/compare-change-impact.js.map +1 -0
- package/dist/server/tools/find-refactoring-opportunities.d.ts +1 -1
- package/dist/server/tools/get-architecture-snapshot.d.ts.map +1 -1
- package/dist/server/tools/get-architecture-snapshot.js +28 -14
- package/dist/server/tools/get-architecture-snapshot.js.map +1 -1
- package/dist/server/tools/get-churn-metrics.d.ts.map +1 -1
- package/dist/server/tools/get-churn-metrics.js +1 -12
- package/dist/server/tools/get-churn-metrics.js.map +1 -1
- package/dist/server/tools/get-co-change.d.ts +37 -0
- package/dist/server/tools/get-co-change.d.ts.map +1 -0
- package/dist/server/tools/get-co-change.js +120 -0
- package/dist/server/tools/get-co-change.js.map +1 -0
- package/dist/server/tools/get-context-bundle.d.ts.map +1 -1
- package/dist/server/tools/get-context-bundle.js +56 -3
- package/dist/server/tools/get-context-bundle.js.map +1 -1
- package/dist/server/tools/get-entry-points.d.ts +1 -1
- package/dist/server/tools/get-symbol-risk.d.ts +25 -0
- package/dist/server/tools/get-symbol-risk.d.ts.map +1 -0
- package/dist/server/tools/get-symbol-risk.js +60 -0
- package/dist/server/tools/get-symbol-risk.js.map +1 -0
- package/dist/server/tools/get-symbol-source.d.ts +2 -0
- package/dist/server/tools/get-symbol-source.d.ts.map +1 -1
- package/dist/server/tools/get-symbol-source.js +18 -1
- package/dist/server/tools/get-symbol-source.js.map +1 -1
- package/dist/server/tools/index-repo.d.ts.map +1 -1
- package/dist/server/tools/index-repo.js +8 -2
- package/dist/server/tools/index-repo.js.map +1 -1
- package/dist/server/tools/prepare-change.d.ts +61 -0
- package/dist/server/tools/prepare-change.d.ts.map +1 -0
- package/dist/server/tools/prepare-change.js +262 -0
- package/dist/server/tools/prepare-change.js.map +1 -0
- package/dist/server/tools/search-symbols.d.ts +2 -0
- package/dist/server/tools/search-symbols.d.ts.map +1 -1
- package/dist/server/tools/search-symbols.js +33 -0
- package/dist/server/tools/search-symbols.js.map +1 -1
- package/dist/server/tools/symbol-lines.d.ts +25 -0
- package/dist/server/tools/symbol-lines.d.ts.map +1 -0
- package/dist/server/tools/symbol-lines.js +40 -0
- package/dist/server/tools/symbol-lines.js.map +1 -0
- package/dist/server/tools/symbol-risk.d.ts +109 -0
- package/dist/server/tools/symbol-risk.d.ts.map +1 -0
- package/dist/server/tools/symbol-risk.js +251 -0
- package/dist/server/tools/symbol-risk.js.map +1 -0
- package/dist/server/tools/verify-change.d.ts +40 -0
- package/dist/server/tools/verify-change.d.ts.map +1 -0
- package/dist/server/tools/verify-change.js +149 -0
- package/dist/server/tools/verify-change.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/01-introduction.md +2 -2
- package/docs/02-installation.md +97 -89
- package/docs/03-quick-start.md +138 -135
- package/docs/04-configuration.md +247 -214
- package/docs/05-cli-reference.md +236 -219
- package/docs/06-tools-reference.md +902 -499
- package/docs/14-transport-modes.md +170 -167
- package/docs/18-git-history.md +43 -0
- package/docs/23-performance.md +123 -121
- package/docs/26-troubleshooting.md +249 -234
- package/grammars/README.md +88 -0
- package/package.json +7 -25
- package/AGENT_INSTRUCTIONS_SHORT.md +0 -150
package/REFACTORING-SAFELY.md
CHANGED
|
@@ -1,279 +1,338 @@
|
|
|
1
|
-
# Refactoring Safely
|
|
2
|
-
|
|
3
|
-
Refactoring is risky not because the changes are hard, but because the side effects are invisible. You rename a function and forget about the string-literal reference in a config file. You delete a helper and miss the one call site that imported it from a different path. You move a file and half the codebase's import paths silently break.
|
|
4
|
-
|
|
5
|
-
PureContext's refactoring safety tools give you a complete impact analysis before you make any change — so you know exactly what you're dealing with before you start.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Before renaming a symbol
|
|
10
|
-
|
|
11
|
-
Renaming a function, class, or constant affects every file that references it. The question is always: *exactly how many places, which ones, and are there any that a text-replace can't fix automatically?*
|
|
12
|
-
|
|
13
|
-
**Scenario:** You're renaming `validateToken` to `verifyAuthToken` to align with the new naming convention. Before you do it in your editor, get the full picture.
|
|
14
|
-
|
|
15
|
-
> "I want to rename validateToken to verifyAuthToken. Is that safe? Show me everywhere it's used."
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
check_rename_safe(repoId, symbolId: "validateToken-id", newName: "verifyAuthToken") →
|
|
19
|
-
|
|
20
|
-
safe: true
|
|
21
|
-
verdict: "Rename is safe. All references are in import statements and call sites
|
|
22
|
-
that can be updated automatically. No string-literal references detected."
|
|
23
|
-
|
|
24
|
-
Affected files (12):
|
|
25
|
-
src/auth/index.ts:3 import — import { validateToken } from './validator'
|
|
26
|
-
src/auth/index.ts:47 call — const result = validateToken(req.headers.auth)
|
|
27
|
-
src/api/middleware/auth.ts:12 import — import { validateToken } ...
|
|
28
|
-
src/api/middleware/auth.ts:67 call — validateToken(bearer)
|
|
29
|
-
src/api/routes/login.ts:23 call — if (!validateToken(session)) ...
|
|
30
|
-
test/auth/validator.test.ts:15 call — expect(validateToken('expired')).toBe(false)
|
|
31
|
-
test/auth/validator.test.ts:31 call — validateToken(validToken)
|
|
32
|
-
... (5 more)
|
|
33
|
-
|
|
34
|
-
No conflicts: "verifyAuthToken" does not exist in any of these files.
|
|
35
|
-
No string-literal references that require manual updates.
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Safe to proceed. All 12 references are structured code — imports and call sites — that any rename tool can update mechanically. No surprises.
|
|
39
|
-
|
|
40
|
-
**When it's not safe:**
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
check_rename_safe(repoId, symbolId: "processPayment-id", newName: "handlePayment") →
|
|
44
|
-
|
|
45
|
-
safe: false
|
|
46
|
-
blockers:
|
|
47
|
-
1. String-literal reference found:
|
|
48
|
-
src/config/routes.json:34 "handler": "processPayment"
|
|
49
|
-
← This is a string, not a code reference. A rename tool won't catch it.
|
|
50
|
-
|
|
51
|
-
2. Name conflict:
|
|
52
|
-
src/billing/processor.ts already contains a symbol named "handlePayment"
|
|
53
|
-
← Two functions with the same name in the same import scope will conflict.
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Two blockers. The string-literal reference in `routes.json` needs a manual update — it's used as a string key to look up the handler dynamically. The name conflict needs to be resolved before the rename can proceed.
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## Before deleting a symbol
|
|
61
|
-
|
|
62
|
-
Deleting code that's still called causes runtime errors. `check_delete_safe` finds every live reference before you delete anything.
|
|
63
|
-
|
|
64
|
-
**Scenario:** You think `formatDateLegacy` is dead code. You want to confirm before deleting it.
|
|
65
|
-
|
|
66
|
-
> "Is formatDateLegacy safe to delete?"
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
check_delete_safe(repoId, symbolId: "formatDateLegacy-id") →
|
|
70
|
-
|
|
71
|
-
safe: true
|
|
72
|
-
verdict: "No live references found. Symbol is unexported. Safe to delete."
|
|
73
|
-
|
|
74
|
-
Risks found:
|
|
75
|
-
test-subject test/utils/date.test.ts:45 — test file references this symbol
|
|
76
|
-
(informational — deleting will require updating the test)
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
No production code references it. The only reference is in a test file — which is expected and will need to be cleaned up alongside the deletion. Safe to proceed.
|
|
80
|
-
|
|
81
|
-
**When there are live references:**
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
check_delete_safe(repoId, symbolId: "getUserById-id") →
|
|
85
|
-
|
|
86
|
-
safe: false
|
|
87
|
-
verdict: "3 live references found. Deletion would cause runtime errors."
|
|
88
|
-
|
|
89
|
-
Risks:
|
|
90
|
-
live-reference src/api/routes/users.ts:67
|
|
91
|
-
const user = getUserById(req.params.id);
|
|
92
|
-
|
|
93
|
-
live-reference src/workers/sync.ts:34
|
|
94
|
-
const admin = getUserById(config.adminId);
|
|
95
|
-
|
|
96
|
-
exported-symbol (symbol is exported — may be consumed by external packages)
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Not safe. Two active call sites would break immediately. The exported flag also indicates external consumers may exist outside the indexed codebase.
|
|
100
|
-
|
|
101
|
-
**Checking an entire file for deletion:**
|
|
102
|
-
|
|
103
|
-
> "I want to delete src/legacy/auth-v1.ts entirely. What would break?"
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
check_delete_safe(repoId, filePath: "src/legacy/auth-v1.ts") →
|
|
107
|
-
|
|
108
|
-
safe: false (aggregate verdict across 8 symbols in this file)
|
|
109
|
-
|
|
110
|
-
Breakdown:
|
|
111
|
-
generateLegacyToken() → safe: true (0 references)
|
|
112
|
-
validateBasicAuth() → safe: true (0 references)
|
|
113
|
-
LegacySession → safe: false (2 live references)
|
|
114
|
-
live-reference src/api/middleware/legacy-compat.ts:23
|
|
115
|
-
live-reference src/workers/migrate-sessions.ts:67
|
|
116
|
-
... (5 more symbols, all safe)
|
|
117
|
-
|
|
118
|
-
Summary: 2 of 8 symbols have live references. Remove references first.
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
You can delete most of the file immediately. Two symbols — `LegacySession` — need their callers updated first. The tool tells you exactly which two files.
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Before moving a file
|
|
126
|
-
|
|
127
|
-
Moving a file changes all the import paths that reference it. `check_move_safe` shows you every import that will need updating, and flags any that require manual intervention.
|
|
128
|
-
|
|
129
|
-
**Scenario:** You're reorganizing the project structure and want to move `src/utils/auth-helpers.ts` into `src/auth/helpers.ts`.
|
|
130
|
-
|
|
131
|
-
> "If I move auth-helpers.ts to src/auth/helpers.ts, what import paths will break?"
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
check_move_safe(repoId,
|
|
135
|
-
filePath: "src/utils/auth-helpers.ts",
|
|
136
|
-
newFilePath: "src/auth/helpers.ts") →
|
|
137
|
-
|
|
138
|
-
safe: true
|
|
139
|
-
verdict: "All 9 import references use relative paths and can be updated automatically."
|
|
140
|
-
|
|
141
|
-
Import updates needed (9 files):
|
|
142
|
-
src/api/middleware/auth.ts:2
|
|
143
|
-
current: import { hashToken } from '../../utils/auth-helpers'
|
|
144
|
-
updated: import { hashToken } from '../auth/helpers'
|
|
145
|
-
|
|
146
|
-
src/auth/validator.ts:1
|
|
147
|
-
current: import { compareHash } from '../utils/auth-helpers'
|
|
148
|
-
updated: import { compareHash } from './helpers'
|
|
149
|
-
|
|
150
|
-
src/core/session.ts:3
|
|
151
|
-
current: import { generateSecret } from '../utils/auth-helpers'
|
|
152
|
-
updated: import { generateSecret } from '../auth/helpers'
|
|
153
|
-
|
|
154
|
-
... (6 more, all relative paths)
|
|
155
|
-
|
|
156
|
-
manualUpdatesRequired: false
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
All relative paths — a find-and-replace-style operation can handle this automatically.
|
|
160
|
-
|
|
161
|
-
**When manual updates are required:**
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
check_move_safe(repoId,
|
|
165
|
-
filePath: "src/core/database.ts",
|
|
166
|
-
newFilePath: "src/db/database.ts") →
|
|
167
|
-
|
|
168
|
-
safe: false
|
|
169
|
-
manualUpdatesRequired: true
|
|
170
|
-
|
|
171
|
-
Problems:
|
|
172
|
-
src/config/jest.config.ts:14
|
|
173
|
-
moduleNameMapper: { '@core/database': './src/core/database' }
|
|
174
|
-
← Path alias in Jest config — not a TypeScript import. Requires manual update.
|
|
175
|
-
|
|
176
|
-
src/build/webpack.config.js:56
|
|
177
|
-
resolve: { alias: { 'core/database': path.resolve('./src/core/database') } }
|
|
178
|
-
← Webpack alias. Requires manual update.
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
The TypeScript imports can be updated automatically. The Jest and Webpack configs use the old path as a string — those need manual updates before the move.
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## Getting a complete refactoring plan
|
|
186
|
-
|
|
187
|
-
When the scope is larger — breaking a circular dependency, extracting a module, reducing coupling — `plan_refactoring` synthesizes all the individual safety checks into a sequenced, risk-annotated action plan.
|
|
188
|
-
|
|
189
|
-
**Scenario:** You want to rename a widely-used symbol, and you want a step-by-step plan rather than a raw impact list.
|
|
190
|
-
|
|
191
|
-
> "Give me a complete refactoring plan for renaming validateToken to verifyAuthToken."
|
|
192
|
-
|
|
193
|
-
```
|
|
194
|
-
plan_refactoring(repoId, goal: "rename-symbol",
|
|
195
|
-
symbolId: "validateToken-id", newName: "verifyAuthToken") →
|
|
196
|
-
|
|
197
|
-
Goal: rename-symbol
|
|
198
|
-
Estimated files: 12
|
|
199
|
-
Estimated risk: low
|
|
200
|
-
|
|
201
|
-
Steps (execute in order):
|
|
202
|
-
|
|
203
|
-
1. [LOW RISK] Update test references (2 files)
|
|
204
|
-
test/auth/validator.test.ts — update 2 call sites
|
|
205
|
-
test/integration/auth.test.ts — update 1 import + 3 calls
|
|
206
|
-
Reason: Start with tests — they validate the rename worked correctly.
|
|
207
|
-
|
|
208
|
-
2. [LOW RISK] Update leaf callers (4 files)
|
|
209
|
-
src/api/routes/login.ts — update 1 call site
|
|
210
|
-
src/api/routes/refresh.ts — update 1 call site
|
|
211
|
-
src/workers/session-cleanup.ts — update 1 call site
|
|
212
|
-
src/api/middleware/auth.ts — update 1 import + 2 calls
|
|
213
|
-
Reason: These files import validateToken but nothing else imports them in this context.
|
|
214
|
-
|
|
215
|
-
3. [MEDIUM RISK] Update hub callers (2 files)
|
|
216
|
-
src/auth/index.ts — update export re-export
|
|
217
|
-
src/core/auth.ts — update 1 import + 4 calls
|
|
218
|
-
Reason: These are imported by 8+ other files. Change here last.
|
|
219
|
-
|
|
220
|
-
4. [FINAL] Rename the declaration
|
|
221
|
-
src/auth/validator.ts — rename the function
|
|
222
|
-
Reason: Always rename the declaration last, after all references are updated.
|
|
223
|
-
|
|
224
|
-
Warnings:
|
|
225
|
-
- After step 4, run index_folder to update the symbol index.
|
|
226
|
-
- Run tests after each step to catch regressions early.
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
The plan is sequenced bottom-up: leaf files first, hub files last, the declaration itself final. This minimizes the window between "declaration renamed" and "all references updated," reducing the chance of a broken build.
|
|
230
|
-
|
|
231
|
-
**Other refactoring goals:**
|
|
232
|
-
|
|
233
|
-
```
|
|
234
|
-
plan_refactoring(repoId, goal: "delete-symbol", symbolId: "...")
|
|
235
|
-
→ sequenced steps for removing all references then deleting
|
|
236
|
-
|
|
237
|
-
plan_refactoring(repoId, goal: "break-cycle", filePath: "src/core/auth.ts")
|
|
238
|
-
→ identifies the specific import causing the cycle and how to break it
|
|
239
|
-
|
|
240
|
-
plan_refactoring(repoId, goal: "extract-module",
|
|
241
|
-
filePath: "src/utils/helpers.ts", newFilePath: "src/format/currency.ts")
|
|
242
|
-
→ step-by-step extraction with all affected import updates
|
|
243
|
-
|
|
244
|
-
plan_refactoring(repoId, goal: "reduce-coupling", filePath: "src/core/auth.ts")
|
|
245
|
-
→ identifies the highest-coupling imports and suggests what to decouple
|
|
246
|
-
|
|
247
|
-
plan_refactoring(repoId, goal: "general", filePath: "src/utils/helpers.ts")
|
|
248
|
-
→ open-ended: surfaces the top structural issues in this file
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
---
|
|
252
|
-
|
|
253
|
-
## The
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
1
|
+
# Refactoring Safely
|
|
2
|
+
|
|
3
|
+
Refactoring is risky not because the changes are hard, but because the side effects are invisible. You rename a function and forget about the string-literal reference in a config file. You delete a helper and miss the one call site that imported it from a different path. You move a file and half the codebase's import paths silently break.
|
|
4
|
+
|
|
5
|
+
PureContext's refactoring safety tools give you a complete impact analysis before you make any change — so you know exactly what you're dealing with before you start.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Before renaming a symbol
|
|
10
|
+
|
|
11
|
+
Renaming a function, class, or constant affects every file that references it. The question is always: *exactly how many places, which ones, and are there any that a text-replace can't fix automatically?*
|
|
12
|
+
|
|
13
|
+
**Scenario:** You're renaming `validateToken` to `verifyAuthToken` to align with the new naming convention. Before you do it in your editor, get the full picture.
|
|
14
|
+
|
|
15
|
+
> "I want to rename validateToken to verifyAuthToken. Is that safe? Show me everywhere it's used."
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
check_rename_safe(repoId, symbolId: "validateToken-id", newName: "verifyAuthToken") →
|
|
19
|
+
|
|
20
|
+
safe: true
|
|
21
|
+
verdict: "Rename is safe. All references are in import statements and call sites
|
|
22
|
+
that can be updated automatically. No string-literal references detected."
|
|
23
|
+
|
|
24
|
+
Affected files (12):
|
|
25
|
+
src/auth/index.ts:3 import — import { validateToken } from './validator'
|
|
26
|
+
src/auth/index.ts:47 call — const result = validateToken(req.headers.auth)
|
|
27
|
+
src/api/middleware/auth.ts:12 import — import { validateToken } ...
|
|
28
|
+
src/api/middleware/auth.ts:67 call — validateToken(bearer)
|
|
29
|
+
src/api/routes/login.ts:23 call — if (!validateToken(session)) ...
|
|
30
|
+
test/auth/validator.test.ts:15 call — expect(validateToken('expired')).toBe(false)
|
|
31
|
+
test/auth/validator.test.ts:31 call — validateToken(validToken)
|
|
32
|
+
... (5 more)
|
|
33
|
+
|
|
34
|
+
No conflicts: "verifyAuthToken" does not exist in any of these files.
|
|
35
|
+
No string-literal references that require manual updates.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Safe to proceed. All 12 references are structured code — imports and call sites — that any rename tool can update mechanically. No surprises.
|
|
39
|
+
|
|
40
|
+
**When it's not safe:**
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
check_rename_safe(repoId, symbolId: "processPayment-id", newName: "handlePayment") →
|
|
44
|
+
|
|
45
|
+
safe: false
|
|
46
|
+
blockers:
|
|
47
|
+
1. String-literal reference found:
|
|
48
|
+
src/config/routes.json:34 "handler": "processPayment"
|
|
49
|
+
← This is a string, not a code reference. A rename tool won't catch it.
|
|
50
|
+
|
|
51
|
+
2. Name conflict:
|
|
52
|
+
src/billing/processor.ts already contains a symbol named "handlePayment"
|
|
53
|
+
← Two functions with the same name in the same import scope will conflict.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Two blockers. The string-literal reference in `routes.json` needs a manual update — it's used as a string key to look up the handler dynamically. The name conflict needs to be resolved before the rename can proceed.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Before deleting a symbol
|
|
61
|
+
|
|
62
|
+
Deleting code that's still called causes runtime errors. `check_delete_safe` finds every live reference before you delete anything.
|
|
63
|
+
|
|
64
|
+
**Scenario:** You think `formatDateLegacy` is dead code. You want to confirm before deleting it.
|
|
65
|
+
|
|
66
|
+
> "Is formatDateLegacy safe to delete?"
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
check_delete_safe(repoId, symbolId: "formatDateLegacy-id") →
|
|
70
|
+
|
|
71
|
+
safe: true
|
|
72
|
+
verdict: "No live references found. Symbol is unexported. Safe to delete."
|
|
73
|
+
|
|
74
|
+
Risks found:
|
|
75
|
+
test-subject test/utils/date.test.ts:45 — test file references this symbol
|
|
76
|
+
(informational — deleting will require updating the test)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
No production code references it. The only reference is in a test file — which is expected and will need to be cleaned up alongside the deletion. Safe to proceed.
|
|
80
|
+
|
|
81
|
+
**When there are live references:**
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
check_delete_safe(repoId, symbolId: "getUserById-id") →
|
|
85
|
+
|
|
86
|
+
safe: false
|
|
87
|
+
verdict: "3 live references found. Deletion would cause runtime errors."
|
|
88
|
+
|
|
89
|
+
Risks:
|
|
90
|
+
live-reference src/api/routes/users.ts:67
|
|
91
|
+
const user = getUserById(req.params.id);
|
|
92
|
+
|
|
93
|
+
live-reference src/workers/sync.ts:34
|
|
94
|
+
const admin = getUserById(config.adminId);
|
|
95
|
+
|
|
96
|
+
exported-symbol (symbol is exported — may be consumed by external packages)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Not safe. Two active call sites would break immediately. The exported flag also indicates external consumers may exist outside the indexed codebase.
|
|
100
|
+
|
|
101
|
+
**Checking an entire file for deletion:**
|
|
102
|
+
|
|
103
|
+
> "I want to delete src/legacy/auth-v1.ts entirely. What would break?"
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
check_delete_safe(repoId, filePath: "src/legacy/auth-v1.ts") →
|
|
107
|
+
|
|
108
|
+
safe: false (aggregate verdict across 8 symbols in this file)
|
|
109
|
+
|
|
110
|
+
Breakdown:
|
|
111
|
+
generateLegacyToken() → safe: true (0 references)
|
|
112
|
+
validateBasicAuth() → safe: true (0 references)
|
|
113
|
+
LegacySession → safe: false (2 live references)
|
|
114
|
+
live-reference src/api/middleware/legacy-compat.ts:23
|
|
115
|
+
live-reference src/workers/migrate-sessions.ts:67
|
|
116
|
+
... (5 more symbols, all safe)
|
|
117
|
+
|
|
118
|
+
Summary: 2 of 8 symbols have live references. Remove references first.
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
You can delete most of the file immediately. Two symbols — `LegacySession` — need their callers updated first. The tool tells you exactly which two files.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Before moving a file
|
|
126
|
+
|
|
127
|
+
Moving a file changes all the import paths that reference it. `check_move_safe` shows you every import that will need updating, and flags any that require manual intervention.
|
|
128
|
+
|
|
129
|
+
**Scenario:** You're reorganizing the project structure and want to move `src/utils/auth-helpers.ts` into `src/auth/helpers.ts`.
|
|
130
|
+
|
|
131
|
+
> "If I move auth-helpers.ts to src/auth/helpers.ts, what import paths will break?"
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
check_move_safe(repoId,
|
|
135
|
+
filePath: "src/utils/auth-helpers.ts",
|
|
136
|
+
newFilePath: "src/auth/helpers.ts") →
|
|
137
|
+
|
|
138
|
+
safe: true
|
|
139
|
+
verdict: "All 9 import references use relative paths and can be updated automatically."
|
|
140
|
+
|
|
141
|
+
Import updates needed (9 files):
|
|
142
|
+
src/api/middleware/auth.ts:2
|
|
143
|
+
current: import { hashToken } from '../../utils/auth-helpers'
|
|
144
|
+
updated: import { hashToken } from '../auth/helpers'
|
|
145
|
+
|
|
146
|
+
src/auth/validator.ts:1
|
|
147
|
+
current: import { compareHash } from '../utils/auth-helpers'
|
|
148
|
+
updated: import { compareHash } from './helpers'
|
|
149
|
+
|
|
150
|
+
src/core/session.ts:3
|
|
151
|
+
current: import { generateSecret } from '../utils/auth-helpers'
|
|
152
|
+
updated: import { generateSecret } from '../auth/helpers'
|
|
153
|
+
|
|
154
|
+
... (6 more, all relative paths)
|
|
155
|
+
|
|
156
|
+
manualUpdatesRequired: false
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
All relative paths — a find-and-replace-style operation can handle this automatically.
|
|
160
|
+
|
|
161
|
+
**When manual updates are required:**
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
check_move_safe(repoId,
|
|
165
|
+
filePath: "src/core/database.ts",
|
|
166
|
+
newFilePath: "src/db/database.ts") →
|
|
167
|
+
|
|
168
|
+
safe: false
|
|
169
|
+
manualUpdatesRequired: true
|
|
170
|
+
|
|
171
|
+
Problems:
|
|
172
|
+
src/config/jest.config.ts:14
|
|
173
|
+
moduleNameMapper: { '@core/database': './src/core/database' }
|
|
174
|
+
← Path alias in Jest config — not a TypeScript import. Requires manual update.
|
|
175
|
+
|
|
176
|
+
src/build/webpack.config.js:56
|
|
177
|
+
resolve: { alias: { 'core/database': path.resolve('./src/core/database') } }
|
|
178
|
+
← Webpack alias. Requires manual update.
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The TypeScript imports can be updated automatically. The Jest and Webpack configs use the old path as a string — those need manual updates before the move.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Getting a complete refactoring plan
|
|
186
|
+
|
|
187
|
+
When the scope is larger — breaking a circular dependency, extracting a module, reducing coupling — `plan_refactoring` synthesizes all the individual safety checks into a sequenced, risk-annotated action plan.
|
|
188
|
+
|
|
189
|
+
**Scenario:** You want to rename a widely-used symbol, and you want a step-by-step plan rather than a raw impact list.
|
|
190
|
+
|
|
191
|
+
> "Give me a complete refactoring plan for renaming validateToken to verifyAuthToken."
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
plan_refactoring(repoId, goal: "rename-symbol",
|
|
195
|
+
symbolId: "validateToken-id", newName: "verifyAuthToken") →
|
|
196
|
+
|
|
197
|
+
Goal: rename-symbol
|
|
198
|
+
Estimated files: 12
|
|
199
|
+
Estimated risk: low
|
|
200
|
+
|
|
201
|
+
Steps (execute in order):
|
|
202
|
+
|
|
203
|
+
1. [LOW RISK] Update test references (2 files)
|
|
204
|
+
test/auth/validator.test.ts — update 2 call sites
|
|
205
|
+
test/integration/auth.test.ts — update 1 import + 3 calls
|
|
206
|
+
Reason: Start with tests — they validate the rename worked correctly.
|
|
207
|
+
|
|
208
|
+
2. [LOW RISK] Update leaf callers (4 files)
|
|
209
|
+
src/api/routes/login.ts — update 1 call site
|
|
210
|
+
src/api/routes/refresh.ts — update 1 call site
|
|
211
|
+
src/workers/session-cleanup.ts — update 1 call site
|
|
212
|
+
src/api/middleware/auth.ts — update 1 import + 2 calls
|
|
213
|
+
Reason: These files import validateToken but nothing else imports them in this context.
|
|
214
|
+
|
|
215
|
+
3. [MEDIUM RISK] Update hub callers (2 files)
|
|
216
|
+
src/auth/index.ts — update export re-export
|
|
217
|
+
src/core/auth.ts — update 1 import + 4 calls
|
|
218
|
+
Reason: These are imported by 8+ other files. Change here last.
|
|
219
|
+
|
|
220
|
+
4. [FINAL] Rename the declaration
|
|
221
|
+
src/auth/validator.ts — rename the function
|
|
222
|
+
Reason: Always rename the declaration last, after all references are updated.
|
|
223
|
+
|
|
224
|
+
Warnings:
|
|
225
|
+
- After step 4, run index_folder to update the symbol index.
|
|
226
|
+
- Run tests after each step to catch regressions early.
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The plan is sequenced bottom-up: leaf files first, hub files last, the declaration itself final. This minimizes the window between "declaration renamed" and "all references updated," reducing the chance of a broken build.
|
|
230
|
+
|
|
231
|
+
**Other refactoring goals:**
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
plan_refactoring(repoId, goal: "delete-symbol", symbolId: "...")
|
|
235
|
+
→ sequenced steps for removing all references then deleting
|
|
236
|
+
|
|
237
|
+
plan_refactoring(repoId, goal: "break-cycle", filePath: "src/core/auth.ts")
|
|
238
|
+
→ identifies the specific import causing the cycle and how to break it
|
|
239
|
+
|
|
240
|
+
plan_refactoring(repoId, goal: "extract-module",
|
|
241
|
+
filePath: "src/utils/helpers.ts", newFilePath: "src/format/currency.ts")
|
|
242
|
+
→ step-by-step extraction with all affected import updates
|
|
243
|
+
|
|
244
|
+
plan_refactoring(repoId, goal: "reduce-coupling", filePath: "src/core/auth.ts")
|
|
245
|
+
→ identifies the highest-coupling imports and suggests what to decouple
|
|
246
|
+
|
|
247
|
+
plan_refactoring(repoId, goal: "general", filePath: "src/utils/helpers.ts")
|
|
248
|
+
→ open-ended: surfaces the top structural issues in this file
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## The closed loop: prepare → edit → verify → compare
|
|
254
|
+
|
|
255
|
+
The safety checks above are the *before*. PureContext also closes the loop *after* the edit — confirming the change was not just safe to start but actually **complete**. These three tools never edit code; they tell you what's safe and what's still missing, with reasons.
|
|
256
|
+
|
|
257
|
+
**Before editing — `prepare_change`:** state the intent and target, get one impact verdict.
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
prepare_change(repoId, intent: "rename", targetSymbolId: "validateToken-id") →
|
|
261
|
+
|
|
262
|
+
verdict: "ready"
|
|
263
|
+
predictedChange: { changedFilePaths: [ ...12 files... ] }
|
|
264
|
+
risk: { band: "review" }
|
|
265
|
+
missingCoChange: [ "src/api/session-store.ts" ] ← historically moves with this, NOT in your plan
|
|
266
|
+
coverageGaps: [ ]
|
|
267
|
+
reasons: [
|
|
268
|
+
"Aggregate change risk: review.",
|
|
269
|
+
"1 file historically co-changes with the target but is NOT in the predicted change: src/api/session-store.ts."
|
|
270
|
+
]
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
It tells you up front the file you were about to forget. If the target is ambiguous it returns `verdict: "ambiguous_target"` with candidates and refuses to guess.
|
|
274
|
+
|
|
275
|
+
**After editing — `verify_change`:** hand back the real diff plus the prediction.
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
verify_change(repoId, diff: "<git diff>",
|
|
279
|
+
predictedFilePaths: [ ...12... ],
|
|
280
|
+
predictedCoChange: [ "src/api/session-store.ts" ]) →
|
|
281
|
+
|
|
282
|
+
verdict: "incomplete"
|
|
283
|
+
unaddressedCoChange: [ "src/api/session-store.ts" ] ← you planned around it; still untouched
|
|
284
|
+
unplannedChanges: [ ]
|
|
285
|
+
reasons: [ "1 historically co-changing file you planned around is still untouched: ..." ]
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`complete` means every planned file was touched with no co-change or coverage gaps; `scope_expanded` flags files you changed that weren't predicted.
|
|
289
|
+
|
|
290
|
+
**Architecture regression — `compare_change_impact`:** snapshot before, compare after.
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
get_architecture_snapshot(repoId, action: "create", label: "before-refactor") → snapshotId
|
|
294
|
+
... edit + re-index ...
|
|
295
|
+
compare_change_impact(repoId, baselineSnapshotId: "<id>") →
|
|
296
|
+
|
|
297
|
+
verdict: "regressed"
|
|
298
|
+
newCycles: [ [ "src/auth/index.ts", "src/core/session.ts" ] ] ← introduced by THIS change
|
|
299
|
+
newLayerViolations: [ ]
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
It reports only what the change *introduced* (or resolved) — never pre-existing issues.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## The pre-change pattern
|
|
307
|
+
|
|
308
|
+
For any significant structural change, this is the workflow:
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
1. Pre-flight the change
|
|
312
|
+
prepare_change(intent, target) — or check_rename_safe / check_delete_safe / check_move_safe
|
|
313
|
+
→ verdict + impact + the co-change files you're about to forget
|
|
314
|
+
|
|
315
|
+
2. If safe: get the sequenced plan (optional, for larger refactors)
|
|
316
|
+
plan_refactoring(goal: "...")
|
|
317
|
+
→ step-by-step with risk annotations
|
|
318
|
+
|
|
319
|
+
3. (optional) Snapshot the architecture
|
|
320
|
+
get_architecture_snapshot(action: "create")
|
|
321
|
+
|
|
322
|
+
4. Execute from leaf to hub, test after each step
|
|
323
|
+
|
|
324
|
+
5. Re-index after all changes
|
|
325
|
+
index_folder(path, force: false)
|
|
326
|
+
|
|
327
|
+
6. Verify the change is complete
|
|
328
|
+
verify_change(diff, predictedFilePaths, predictedCoChange)
|
|
329
|
+
→ complete / incomplete / scope_expanded
|
|
330
|
+
compare_change_impact(baselineSnapshotId)
|
|
331
|
+
→ did this introduce a new cycle / layer violation?
|
|
332
|
+
find_dead_code(repoId)
|
|
333
|
+
→ check nothing is now unreferenced
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
→ Reference: [MCP Tools Reference](docs/06-tools-reference.md) — `prepare_change`, `verify_change`, `compare_change_impact`, `check_rename_safe`, `check_delete_safe`, `check_move_safe`, `plan_refactoring`
|