purecontext-mcp 1.1.7 → 1.2.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.
Files changed (182) hide show
  1. package/AGENT_INSTRUCTIONS.md +393 -0
  2. package/AGENT_INSTRUCTIONS_SHORT.md +53 -0
  3. package/AST-SEARCH.md +274 -0
  4. package/CHANGELOG.md +62 -0
  5. package/CODE-INTELLIGENCE.md +369 -0
  6. package/HEALTH-DASHBOARDS.md +241 -0
  7. package/README.md +7 -0
  8. package/REFACTORING-SAFELY.md +279 -0
  9. package/UNDERSTANDING-RELATIONSHIPS.md +240 -0
  10. package/USER-GUIDE.md +14 -0
  11. package/VISUALIZING-CODE.md +199 -0
  12. package/WORKFLOW-TECH-DEBT.md +286 -0
  13. package/dist/core/db/dep-store.d.ts +75 -0
  14. package/dist/core/db/dep-store.d.ts.map +1 -1
  15. package/dist/core/db/dep-store.js +277 -0
  16. package/dist/core/db/dep-store.js.map +1 -1
  17. package/dist/core/db/schema.d.ts.map +1 -1
  18. package/dist/core/db/schema.js +12 -0
  19. package/dist/core/db/schema.js.map +1 -1
  20. package/dist/core/index-manager.js +1 -1
  21. package/dist/core/index-manager.js.map +1 -1
  22. package/dist/core/token-tracker.d.ts +0 -9
  23. package/dist/core/token-tracker.d.ts.map +1 -1
  24. package/dist/core/token-tracker.js +0 -21
  25. package/dist/core/token-tracker.js.map +1 -1
  26. package/dist/core/types.d.ts +5 -0
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/graph/diagram-renderer.d.ts +83 -0
  29. package/dist/graph/diagram-renderer.d.ts.map +1 -0
  30. package/dist/graph/diagram-renderer.js +294 -0
  31. package/dist/graph/diagram-renderer.js.map +1 -0
  32. package/dist/graph/graph-traversal.d.ts +92 -0
  33. package/dist/graph/graph-traversal.d.ts.map +1 -1
  34. package/dist/graph/graph-traversal.js +440 -2
  35. package/dist/graph/graph-traversal.js.map +1 -1
  36. package/dist/server/http-server.d.ts.map +1 -1
  37. package/dist/server/http-server.js +30 -1
  38. package/dist/server/http-server.js.map +1 -1
  39. package/dist/server/mcp-server.d.ts.map +1 -1
  40. package/dist/server/mcp-server.js +145 -0
  41. package/dist/server/mcp-server.js.map +1 -1
  42. package/dist/server/tools/_meta.d.ts +0 -2
  43. package/dist/server/tools/_meta.d.ts.map +1 -1
  44. package/dist/server/tools/_meta.js +1 -4
  45. package/dist/server/tools/_meta.js.map +1 -1
  46. package/dist/server/tools/check-delete-safe.d.ts +50 -0
  47. package/dist/server/tools/check-delete-safe.d.ts.map +1 -0
  48. package/dist/server/tools/check-delete-safe.js +308 -0
  49. package/dist/server/tools/check-delete-safe.js.map +1 -0
  50. package/dist/server/tools/check-move-safe.d.ts +44 -0
  51. package/dist/server/tools/check-move-safe.d.ts.map +1 -0
  52. package/dist/server/tools/check-move-safe.js +266 -0
  53. package/dist/server/tools/check-move-safe.js.map +1 -0
  54. package/dist/server/tools/check-rename-safe.d.ts +48 -0
  55. package/dist/server/tools/check-rename-safe.d.ts.map +1 -0
  56. package/dist/server/tools/check-rename-safe.js +218 -0
  57. package/dist/server/tools/check-rename-safe.js.map +1 -0
  58. package/dist/server/tools/diff-health-radar.d.ts +44 -0
  59. package/dist/server/tools/diff-health-radar.d.ts.map +1 -0
  60. package/dist/server/tools/diff-health-radar.js +192 -0
  61. package/dist/server/tools/diff-health-radar.js.map +1 -0
  62. package/dist/server/tools/find-cycles.d.ts +31 -0
  63. package/dist/server/tools/find-cycles.d.ts.map +1 -0
  64. package/dist/server/tools/find-cycles.js +85 -0
  65. package/dist/server/tools/find-cycles.js.map +1 -0
  66. package/dist/server/tools/find-implementations.d.ts +47 -0
  67. package/dist/server/tools/find-implementations.d.ts.map +1 -0
  68. package/dist/server/tools/find-implementations.js +167 -0
  69. package/dist/server/tools/find-implementations.js.map +1 -0
  70. package/dist/server/tools/find-untested-symbols.d.ts +52 -0
  71. package/dist/server/tools/find-untested-symbols.d.ts.map +1 -0
  72. package/dist/server/tools/find-untested-symbols.js +308 -0
  73. package/dist/server/tools/find-untested-symbols.js.map +1 -0
  74. package/dist/server/tools/get-architecture-snapshot.d.ts +43 -0
  75. package/dist/server/tools/get-architecture-snapshot.d.ts.map +1 -0
  76. package/dist/server/tools/get-architecture-snapshot.js +292 -0
  77. package/dist/server/tools/get-architecture-snapshot.js.map +1 -0
  78. package/dist/server/tools/get-call-hierarchy.d.ts +43 -0
  79. package/dist/server/tools/get-call-hierarchy.d.ts.map +1 -0
  80. package/dist/server/tools/get-call-hierarchy.js +119 -0
  81. package/dist/server/tools/get-call-hierarchy.js.map +1 -0
  82. package/dist/server/tools/get-class-hierarchy.d.ts +36 -0
  83. package/dist/server/tools/get-class-hierarchy.d.ts.map +1 -0
  84. package/dist/server/tools/get-class-hierarchy.js +125 -0
  85. package/dist/server/tools/get-class-hierarchy.js.map +1 -0
  86. package/dist/server/tools/get-complexity-hotspots.d.ts +50 -0
  87. package/dist/server/tools/get-complexity-hotspots.d.ts.map +1 -0
  88. package/dist/server/tools/get-complexity-hotspots.js +282 -0
  89. package/dist/server/tools/get-complexity-hotspots.js.map +1 -0
  90. package/dist/server/tools/get-coupling-map.d.ts +39 -0
  91. package/dist/server/tools/get-coupling-map.d.ts.map +1 -0
  92. package/dist/server/tools/get-coupling-map.js +107 -0
  93. package/dist/server/tools/get-coupling-map.js.map +1 -0
  94. package/dist/server/tools/get-debt-report.d.ts +44 -0
  95. package/dist/server/tools/get-debt-report.d.ts.map +1 -0
  96. package/dist/server/tools/get-debt-report.js +606 -0
  97. package/dist/server/tools/get-debt-report.js.map +1 -0
  98. package/dist/server/tools/get-entry-points.d.ts +79 -0
  99. package/dist/server/tools/get-entry-points.d.ts.map +1 -0
  100. package/dist/server/tools/get-entry-points.js +362 -0
  101. package/dist/server/tools/get-entry-points.js.map +1 -0
  102. package/dist/server/tools/get-public-api.d.ts +53 -0
  103. package/dist/server/tools/get-public-api.d.ts.map +1 -0
  104. package/dist/server/tools/get-public-api.js +218 -0
  105. package/dist/server/tools/get-public-api.js.map +1 -0
  106. package/dist/server/tools/get-savings-stats.d.ts.map +1 -1
  107. package/dist/server/tools/get-savings-stats.js +1 -3
  108. package/dist/server/tools/get-savings-stats.js.map +1 -1
  109. package/dist/server/tools/get-test-coverage-map.d.ts +66 -0
  110. package/dist/server/tools/get-test-coverage-map.d.ts.map +1 -0
  111. package/dist/server/tools/get-test-coverage-map.js +588 -0
  112. package/dist/server/tools/get-test-coverage-map.js.map +1 -0
  113. package/dist/server/tools/get-todos.d.ts +51 -0
  114. package/dist/server/tools/get-todos.d.ts.map +1 -0
  115. package/dist/server/tools/get-todos.js +180 -0
  116. package/dist/server/tools/get-todos.js.map +1 -0
  117. package/dist/server/tools/get-type-graph.d.ts +73 -0
  118. package/dist/server/tools/get-type-graph.d.ts.map +1 -0
  119. package/dist/server/tools/get-type-graph.js +437 -0
  120. package/dist/server/tools/get-type-graph.js.map +1 -0
  121. package/dist/server/tools/health-radar.d.ts +50 -0
  122. package/dist/server/tools/health-radar.d.ts.map +1 -0
  123. package/dist/server/tools/health-radar.js +426 -0
  124. package/dist/server/tools/health-radar.js.map +1 -0
  125. package/dist/server/tools/plan-refactoring.d.ts +74 -0
  126. package/dist/server/tools/plan-refactoring.d.ts.map +1 -0
  127. package/dist/server/tools/plan-refactoring.js +644 -0
  128. package/dist/server/tools/plan-refactoring.js.map +1 -0
  129. package/dist/server/tools/render-call-graph.d.ts +40 -0
  130. package/dist/server/tools/render-call-graph.d.ts.map +1 -0
  131. package/dist/server/tools/render-call-graph.js +215 -0
  132. package/dist/server/tools/render-call-graph.js.map +1 -0
  133. package/dist/server/tools/render-class-hierarchy.d.ts +42 -0
  134. package/dist/server/tools/render-class-hierarchy.d.ts.map +1 -0
  135. package/dist/server/tools/render-class-hierarchy.js +265 -0
  136. package/dist/server/tools/render-class-hierarchy.js.map +1 -0
  137. package/dist/server/tools/render-dep-matrix.d.ts +38 -0
  138. package/dist/server/tools/render-dep-matrix.d.ts.map +1 -0
  139. package/dist/server/tools/render-dep-matrix.js +186 -0
  140. package/dist/server/tools/render-dep-matrix.js.map +1 -0
  141. package/dist/server/tools/render-diagram.d.ts +47 -0
  142. package/dist/server/tools/render-diagram.d.ts.map +1 -0
  143. package/dist/server/tools/render-diagram.js +266 -0
  144. package/dist/server/tools/render-diagram.js.map +1 -0
  145. package/dist/server/tools/render-import-graph.d.ts +41 -0
  146. package/dist/server/tools/render-import-graph.d.ts.map +1 -0
  147. package/dist/server/tools/render-import-graph.js +158 -0
  148. package/dist/server/tools/render-import-graph.js.map +1 -0
  149. package/dist/server/tools/search-ast.d.ts +55 -0
  150. package/dist/server/tools/search-ast.d.ts.map +1 -0
  151. package/dist/server/tools/search-ast.js +279 -0
  152. package/dist/server/tools/search-ast.js.map +1 -0
  153. package/dist/server/tools/search-by-complexity.d.ts +92 -0
  154. package/dist/server/tools/search-by-complexity.d.ts.map +1 -0
  155. package/dist/server/tools/search-by-complexity.js +268 -0
  156. package/dist/server/tools/search-by-complexity.js.map +1 -0
  157. package/dist/server/tools/search-by-decorator.d.ts +48 -0
  158. package/dist/server/tools/search-by-decorator.d.ts.map +1 -0
  159. package/dist/server/tools/search-by-decorator.js +518 -0
  160. package/dist/server/tools/search-by-decorator.js.map +1 -0
  161. package/dist/server/tools/search-by-signature.d.ts +56 -0
  162. package/dist/server/tools/search-by-signature.d.ts.map +1 -0
  163. package/dist/server/tools/search-by-signature.js +200 -0
  164. package/dist/server/tools/search-by-signature.js.map +1 -0
  165. package/dist/ui/assets/BlastRadius-QdgESOL8.js +1 -0
  166. package/dist/ui/assets/{DependencyGraph-CDtBHM0U.js → DependencyGraph-BSMhzwWV.js} +6 -6
  167. package/dist/ui/assets/{NotFound-Cdt6X8pl.js → NotFound-CipFP_s1.js} +1 -1
  168. package/dist/ui/assets/RepoDetail-Dfp5z5Kq.js +1 -0
  169. package/dist/ui/assets/{RepoList-B9LaZvob.js → RepoList-BKtST3hB.js} +1 -1
  170. package/dist/ui/assets/{Search-CLqv2KGV.js → Search-DzhGDViy.js} +1 -1
  171. package/dist/ui/assets/{SymbolView-BlbDR1DU.js → SymbolView-ryVEwAHG.js} +1 -1
  172. package/dist/ui/assets/{index-DADf5y_L.css → index-Ny8gn9F0.css} +1 -1
  173. package/dist/ui/assets/{index-i3Q1XbEh.js → index-nX2chMqi.js} +6 -6
  174. package/dist/ui/assets/{useSearch-mbMk6-M1.js → useSearch-BnBCRKui.js} +1 -1
  175. package/dist/ui/index.html +2 -2
  176. package/dist/version.d.ts +1 -1
  177. package/dist/version.js +1 -1
  178. package/docs/dev/jcodemunch-gap-analysis.md +198 -0
  179. package/package.json +9 -1
  180. package/user-manual.md +2466 -0
  181. package/dist/ui/assets/BlastRadius-BDZWhEk-.js +0 -1
  182. package/dist/ui/assets/RepoDetail-M6WaYbZ3.js +0 -1
@@ -0,0 +1,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 pre-change pattern
254
+
255
+ For any significant structural change, this is the workflow:
256
+
257
+ ```
258
+ 1. Run the relevant safety check
259
+ check_rename_safe / check_delete_safe / check_move_safe
260
+ → get the verdict and full impact list
261
+
262
+ 2. If safe: get the sequenced plan
263
+ plan_refactoring(goal: "...")
264
+ → step-by-step with risk annotations
265
+
266
+ 3. Execute from leaf to hub, test after each step
267
+
268
+ 4. Re-index after all changes
269
+ index_folder(path, force: false)
270
+ → incremental, picks up only what changed
271
+
272
+ 5. Verify no dead code was created
273
+ find_dead_code(repoId)
274
+ → check nothing is now unreferenced
275
+ ```
276
+
277
+ ---
278
+
279
+ → Reference: [MCP Tools Reference](docs/06-tools-reference.md) — `check_rename_safe`, `check_delete_safe`, `check_move_safe`, `plan_refactoring`
@@ -0,0 +1,240 @@
1
+ # Understanding Code Relationships
2
+
3
+ The dependency graph gives you the broad picture — what imports what. But most real questions about a codebase go deeper: *who implements this interface?*, *what does this function call at runtime?*, *why is this module so hard to change?*, *where are the circular imports that are blocking our refactoring?*
4
+
5
+ PureContext has a dedicated set of tools for answering these structural questions without reading source files.
6
+
7
+ ---
8
+
9
+ ## Finding all implementations of an interface
10
+
11
+ When you're working with a codebase that uses interfaces heavily — whether for dependency injection, plugin systems, or polymorphism — you regularly need to know: *what concrete classes actually implement this?*
12
+
13
+ **Scenario:** You're changing the `UserRepository` interface to add a new method. Before you change the interface, you need to know which classes implement it so you can update them all.
14
+
15
+ > "Which classes implement the UserRepository interface?"
16
+
17
+ ```
18
+ find_implementations(symbolId: "UserRepository-id") →
19
+
20
+ Interface: UserRepository (src/core/repositories/user.ts)
21
+
22
+ Implementations:
23
+ PostgresUserRepository src/db/postgres/user-repo.ts implements all 7 methods ✓
24
+ InMemoryUserRepository src/test/mocks/user-repo.ts implements all 7 methods ✓
25
+ CachedUserRepository src/cache/user-repo.ts missing: batchGet, streamAll ✗
26
+
27
+ Total: 3 implementations
28
+ ```
29
+
30
+ You can see immediately that `CachedUserRepository` is incomplete — it's missing two methods. Adding a third method to the interface will require updating all three classes. You know the scope before you change a single line.
31
+
32
+ **Including abstract subclasses:**
33
+
34
+ ```
35
+ find_implementations(symbolId: "UserRepository-id", includeAbstract: true)
36
+ ```
37
+
38
+ This surfaces abstract classes that extend the interface — useful in Java or Kotlin codebases where abstract base classes form an intermediate layer.
39
+
40
+ ---
41
+
42
+ ## Understanding the call hierarchy
43
+
44
+ `get_blast_radius` tells you which *files* import a symbol. `get_call_hierarchy` tells you how a function is actually *called at runtime* — the actual call stack, structured as a tree.
45
+
46
+ **Scenario:** You're investigating a performance issue. The `generateReport` function is slow, but you're not sure if the problem is in the function itself or in something it calls deep down.
47
+
48
+ > "Show me what generateReport calls, three levels deep."
49
+
50
+ ```
51
+ get_call_hierarchy(symbolId: "generateReport-id", direction: "callees", maxDepth: 3) →
52
+
53
+ generateReport() [root]
54
+ ├── fetchReportData() depth 1 — called 1×
55
+ │ ├── queryUserEvents() depth 2 — called 1×
56
+ │ │ └── buildSQLQuery() depth 3 — called 3×
57
+ │ └── queryMetrics() depth 2 — called 1×
58
+ │ └── buildSQLQuery() depth 3 — called 1× [cyclic: seen above]
59
+ ├── formatReportRows() depth 1 — called 1×
60
+ │ └── formatCurrency() depth 2 — called N×
61
+ └── generatePDF() depth 1 — called 1×
62
+ └── compressOutput() depth 2 — called 1×
63
+
64
+ Total nodes: 10
65
+ ```
66
+
67
+ `buildSQLQuery` is called four times from two different paths. `formatCurrency` is called in a loop. The tree structure lets you see exactly where the CPU time is going without running a profiler.
68
+
69
+ **Checking who calls a function:**
70
+
71
+ > "Who calls sendEmail? I need to know all the places it's triggered."
72
+
73
+ ```
74
+ get_call_hierarchy(symbolId: "sendEmail-id", direction: "callers", maxDepth: 2) →
75
+
76
+ sendEmail() [root]
77
+ ├── triggerWelcomeEmail() depth 1 — src/onboarding/welcome.ts
78
+ ├── sendPasswordReset() depth 1 — src/auth/password.ts
79
+ │ └── resetPassword() depth 2 — src/api/routes/auth.ts
80
+ ├── notifyPaymentFailed() depth 1 — src/billing/notify.ts
81
+ └── weeklyDigest() depth 1 — src/workers/digest.ts
82
+ ```
83
+
84
+ Four callers, one with a caller of its own. This is the full list of places that trigger email sending — a complete picture for changing the email system.
85
+
86
+ ---
87
+
88
+ ## Tracing inheritance chains
89
+
90
+ When working with class hierarchies — especially in enterprise codebases with deep inheritance — you need to understand both directions: what does a class inherit from, and what inherits from it?
91
+
92
+ **Scenario:** You're refactoring `BaseController`. Before you change it, you want to know the full inheritance chain.
93
+
94
+ > "Show me the full class hierarchy for BaseController."
95
+
96
+ ```
97
+ get_class_hierarchy(symbolId: "BaseController-id", direction: "both") →
98
+
99
+ Ancestors (BaseController extends):
100
+ BaseController → Object (external, not indexed)
101
+
102
+ Descendants (classes that extend BaseController):
103
+ BaseController
104
+ ├── AuthenticatedController
105
+ │ ├── UserController
106
+ │ ├── AdminController
107
+ │ └── ApiController
108
+ │ ├── RestApiController
109
+ │ └── GraphQLController
110
+ └── PublicController
111
+ └── LandingController
112
+
113
+ Total: 9 nodes
114
+ ```
115
+
116
+ Seven classes will be affected by changes to `BaseController`. The deepest chains (`RestApiController`, `GraphQLController`) are four levels of inheritance — a sign that these might benefit from composition instead.
117
+
118
+ **Checking ancestors only:**
119
+
120
+ ```
121
+ get_class_hierarchy(symbolId: "UserController-id", direction: "ancestors")
122
+ → UserController → AuthenticatedController → BaseController → Object
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Finding circular dependencies
128
+
129
+ Circular imports are one of the most common causes of "this module is impossible to change independently." They also cause subtle initialization bugs and make testing harder.
130
+
131
+ **Scenario:** You've noticed that changes to `src/core/` always seem to require changes in `src/utils/`, and vice versa. You suspect a circular dependency.
132
+
133
+ > "Find all circular imports in the codebase. Start with cycles involving the core directory."
134
+
135
+ ```
136
+ find_cycles(filePath: "src/core/") →
137
+
138
+ Cycle 1 (severity: error — tight 2-node cycle):
139
+ src/core/billing.ts → src/utils/currency.ts → src/core/billing.ts
140
+
141
+ Cycle 2 (severity: error — tight 3-node cycle):
142
+ src/core/auth.ts → src/models/user.ts → src/core/session.ts → src/core/auth.ts
143
+
144
+ Cycle 3 (severity: warning — longer chain):
145
+ src/core/events.ts → src/handlers/payment.ts → src/core/billing.ts
146
+ → src/core/events.ts
147
+
148
+ Total: 3 cycles found
149
+ ```
150
+
151
+ The first cycle is the one you suspected — `billing.ts` and `currency.ts` are mutually dependent. Breaking this cycle (typically by extracting the shared types into a third module that both can import) is the fix.
152
+
153
+ **Checking cycles in the whole repo:**
154
+
155
+ ```
156
+ find_cycles(maxCycles: 50) → finds all cycles up to the limit
157
+ find_cycles(minLength: 3) → skips direct mutual imports, shows only longer chains
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Measuring coupling
163
+
164
+ Coupling tells you which files are the most dangerous to change — not because they're complex, but because everything else depends on them.
165
+
166
+ **Scenario:** You're planning a major refactoring sprint. Before you start, you want to know which files have the highest coupling — both in terms of what they import and what imports them.
167
+
168
+ > "Which files in src/ have the highest coupling? I want to know where the structural risk is."
169
+
170
+ ```
171
+ get_coupling_map(repoId, topN: 10) →
172
+
173
+ src/utils/helpers.ts
174
+ efferentCoupling (imports): 3 ← imports only 3 files
175
+ afferentCoupling (imported by): 41 ← but 41 files depend on it
176
+ instability: 0.07 ← near 0 = maximally stable = risky to change
177
+
178
+ src/core/auth.ts
179
+ efferentCoupling: 12
180
+ afferentCoupling: 28
181
+ instability: 0.30 ← stable hub
182
+
183
+ src/api/middleware/logging.ts
184
+ efferentCoupling: 18
185
+ afferentCoupling: 2
186
+ instability: 0.90 ← near 1 = leaf node = safe to change
187
+
188
+ ...
189
+ ```
190
+
191
+ `helpers.ts` is the hidden risk: 41 files depend on it, but it only imports 3 things. Its instability score of 0.07 means it's a stable hub — every change to it ripples out to 41 files. That's the file to touch last, if at all.
192
+
193
+ **Inspecting a single file's dependency list:**
194
+
195
+ > "Who depends on src/core/auth.ts, and what does auth.ts itself depend on?"
196
+
197
+ ```
198
+ get_coupling_map(repoId, filePath: "src/core/auth.ts", direction: "both") →
199
+
200
+ Imports (efferent — what auth.ts depends on):
201
+ src/models/user.ts
202
+ src/db/queries/auth.ts
203
+ src/utils/crypto.ts
204
+ ... (9 more)
205
+
206
+ Imported by (afferent — what depends on auth.ts):
207
+ src/api/middleware/auth-guard.ts
208
+ src/api/routes/login.ts
209
+ src/workers/session-cleanup.ts
210
+ ... (25 more)
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Putting it together: pre-refactoring analysis
216
+
217
+ Before a significant structural refactoring, combine these tools:
218
+
219
+ ```
220
+ 1. find_cycles(repoId)
221
+ → identify which circular deps are blocking modularization
222
+
223
+ 2. get_coupling_map(repoId, topN: 20)
224
+ → rank files by coupling to find the stable hubs
225
+
226
+ 3. get_class_hierarchy(symbolId)
227
+ → understand inheritance depth in affected areas
228
+
229
+ 4. find_implementations(symbolId)
230
+ → know how many classes implement interfaces you plan to change
231
+
232
+ 5. get_call_hierarchy(symbolId, direction: "callers")
233
+ → verify you've found all callers before changing a function signature
234
+ ```
235
+
236
+ This analysis takes minutes and replaces hours of manual code reading.
237
+
238
+ ---
239
+
240
+ → Reference: [MCP Tools Reference](docs/06-tools-reference.md) — `find_implementations`, `get_call_hierarchy`, `get_class_hierarchy`, `find_cycles`, `get_coupling_map`
package/USER-GUIDE.md CHANGED
@@ -20,6 +20,10 @@ For parameter-level documentation — every tool input, output, and flag — see
20
20
 
21
21
  - [Making Changes Safely](safe-changes.md) — Blast radius analysis before touching anything, context bundles for understanding dependencies, the full pre-change workflow, and architectural violation detection
22
22
 
23
+ - [Understanding Code Relationships](understanding-relationships.md) — Call hierarchies, class hierarchies, interface implementations, circular dependency detection, and coupling maps
24
+
25
+ - [Refactoring Safely](refactoring-safely.md) — Pre-flight checks before renaming, deleting, or moving symbols. Sequenced, risk-annotated refactoring plans for structural changes.
26
+
23
27
  - [Understanding Code History](code-history.md) — Symbol-level git history (not file-level), churn analysis for identifying risk, ownership mapping, and PR analysis before you read a diff
24
28
 
25
29
  ---
@@ -32,6 +36,14 @@ For parameter-level documentation — every tool input, output, and flag — see
32
36
 
33
37
  - [Code Health & Architecture Analysis](code-health.md) — Quality metrics, anti-pattern detection, auto-generated architecture docs, CI enforcement, and finding refactoring opportunities before they become crises
34
38
 
39
+ - [Health Dashboards & Debt Reporting](health-dashboards.md) — Five-axis health radar, before/after PR comparisons, and comprehensive debt reports with prioritized action items
40
+
41
+ - [Visualizing Code Structure](visualizing-code.md) — Mermaid and DOT diagrams of import graphs, call graphs, class hierarchies, and dependency matrices. Architecture snapshots for tracking structural change over time.
42
+
43
+ - [AST-Level Search](ast-search.md) — Find any tree-sitter node type, search by type signature pattern, find symbols by decorator, and filter by complexity thresholds
44
+
45
+ - [Code Intelligence](code-intelligence.md) — Entry points, public API surface, TODO inventory, complexity hotspots, type graphs, untested symbols, and coverage mapping
46
+
35
47
  ---
36
48
 
37
49
  ## For teams and enterprise
@@ -50,6 +62,8 @@ Complete end-to-end examples showing how PureContext fits into real development
50
62
 
51
63
  - [Reviewing a Pull Request](workflow-pr-review.md) — A 40-file authentication migration PR: structured review in 45 minutes that found two real issues before reading most of the diff
52
64
 
65
+ - [Running a Tech Debt Sprint](workflow-tech-debt.md) — Full lifecycle of a two-week debt reduction sprint: assessment, planning, safe execution, and proving the improvement with snapshots
66
+
53
67
  ---
54
68
 
55
69
  ## Reference Manual