kirograph 0.27.1 → 0.28.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 (222) hide show
  1. package/README.md +35 -2
  2. package/dist/bin/commands/annotations.js +56 -0
  3. package/dist/bin/commands/annotations.js.map +7 -0
  4. package/dist/bin/commands/ast-rewrite.js +55 -0
  5. package/dist/bin/commands/ast-rewrite.js.map +7 -0
  6. package/dist/bin/commands/bench.js +103 -0
  7. package/dist/bin/commands/bench.js.map +7 -0
  8. package/dist/bin/commands/branch.js +133 -0
  9. package/dist/bin/commands/branch.js.map +7 -0
  10. package/dist/bin/commands/callees.js +76 -0
  11. package/dist/bin/commands/callees.js.map +7 -0
  12. package/dist/bin/commands/callers.js +76 -0
  13. package/dist/bin/commands/callers.js.map +7 -0
  14. package/dist/bin/commands/changelog.js +55 -0
  15. package/dist/bin/commands/changelog.js.map +7 -0
  16. package/dist/bin/commands/circular-deps.js +68 -0
  17. package/dist/bin/commands/circular-deps.js.map +7 -0
  18. package/dist/bin/commands/commit-context.js +55 -0
  19. package/dist/bin/commands/commit-context.js.map +7 -0
  20. package/dist/bin/commands/complexity.js +60 -0
  21. package/dist/bin/commands/complexity.js.map +7 -0
  22. package/dist/bin/commands/cost.js +146 -0
  23. package/dist/bin/commands/cost.js.map +7 -0
  24. package/dist/bin/commands/dependency-depth.js +55 -0
  25. package/dist/bin/commands/dependency-depth.js.map +7 -0
  26. package/dist/bin/commands/diff-context.js +55 -0
  27. package/dist/bin/commands/diff-context.js.map +7 -0
  28. package/dist/bin/commands/distribution.js +56 -0
  29. package/dist/bin/commands/distribution.js.map +7 -0
  30. package/dist/bin/commands/doc-coverage.js +56 -0
  31. package/dist/bin/commands/doc-coverage.js.map +7 -0
  32. package/dist/bin/commands/doctor.js +202 -0
  33. package/dist/bin/commands/doctor.js.map +7 -0
  34. package/dist/bin/commands/dsm.js +56 -0
  35. package/dist/bin/commands/dsm.js.map +7 -0
  36. package/dist/bin/commands/gini.js +55 -0
  37. package/dist/bin/commands/gini.js.map +7 -0
  38. package/dist/bin/commands/god-class.js +56 -0
  39. package/dist/bin/commands/god-class.js.map +7 -0
  40. package/dist/bin/commands/health.js +55 -0
  41. package/dist/bin/commands/health.js.map +7 -0
  42. package/dist/bin/commands/help.js +224 -45
  43. package/dist/bin/commands/help.js.map +2 -2
  44. package/dist/bin/commands/impact.js +76 -0
  45. package/dist/bin/commands/impact.js.map +7 -0
  46. package/dist/bin/commands/inheritance-depth.js +56 -0
  47. package/dist/bin/commands/inheritance-depth.js.map +7 -0
  48. package/dist/bin/commands/insert-at.js +55 -0
  49. package/dist/bin/commands/insert-at.js.map +7 -0
  50. package/dist/bin/commands/largest.js +56 -0
  51. package/dist/bin/commands/largest.js.map +7 -0
  52. package/dist/bin/commands/manifest.js +158 -0
  53. package/dist/bin/commands/manifest.js.map +7 -0
  54. package/dist/bin/commands/module-api.js +57 -0
  55. package/dist/bin/commands/module-api.js.map +7 -0
  56. package/dist/bin/commands/monitor.js +91 -0
  57. package/dist/bin/commands/monitor.js.map +7 -0
  58. package/dist/bin/commands/multi-replace.js +66 -0
  59. package/dist/bin/commands/multi-replace.js.map +7 -0
  60. package/dist/bin/commands/pr-context.js +55 -0
  61. package/dist/bin/commands/pr-context.js.map +7 -0
  62. package/dist/bin/commands/query.js +19 -1
  63. package/dist/bin/commands/query.js.map +3 -3
  64. package/dist/bin/commands/rank.js +56 -0
  65. package/dist/bin/commands/rank.js.map +7 -0
  66. package/dist/bin/commands/read.js +1 -1
  67. package/dist/bin/commands/read.js.map +2 -2
  68. package/dist/bin/commands/recursion.js +56 -0
  69. package/dist/bin/commands/recursion.js.map +7 -0
  70. package/dist/bin/commands/rename-preview.js +56 -0
  71. package/dist/bin/commands/rename-preview.js.map +7 -0
  72. package/dist/bin/commands/session.js +60 -0
  73. package/dist/bin/commands/session.js.map +7 -0
  74. package/dist/bin/commands/simplify-scan.js +56 -0
  75. package/dist/bin/commands/simplify-scan.js.map +7 -0
  76. package/dist/bin/commands/str-replace.js +55 -0
  77. package/dist/bin/commands/str-replace.js.map +7 -0
  78. package/dist/bin/commands/test-coverage.js +59 -0
  79. package/dist/bin/commands/test-coverage.js.map +7 -0
  80. package/dist/bin/commands/test-map.js +56 -0
  81. package/dist/bin/commands/test-map.js.map +7 -0
  82. package/dist/bin/commands/test-risk.js +59 -0
  83. package/dist/bin/commands/test-risk.js.map +7 -0
  84. package/dist/bin/commands/type-hierarchy.js +76 -0
  85. package/dist/bin/commands/type-hierarchy.js.map +7 -0
  86. package/dist/bin/commands/unused-imports.js +55 -0
  87. package/dist/bin/commands/unused-imports.js.map +7 -0
  88. package/dist/bin/commands/upgrade.js +78 -0
  89. package/dist/bin/commands/upgrade.js.map +7 -0
  90. package/dist/bin/installer/common.js +19 -9
  91. package/dist/bin/installer/common.js.map +2 -2
  92. package/dist/bin/installer/config-prompt.js +147 -12
  93. package/dist/bin/installer/config-prompt.js.map +3 -3
  94. package/dist/bin/installer/index.js +62 -6
  95. package/dist/bin/installer/index.js.map +2 -2
  96. package/dist/bin/installer/instructions.js +14 -25
  97. package/dist/bin/installer/instructions.js.map +2 -2
  98. package/dist/bin/installer/mcp.js.map +2 -2
  99. package/dist/bin/installer/steering.js +569 -100
  100. package/dist/bin/installer/steering.js.map +2 -2
  101. package/dist/bin/installer/targets/aider.js +3 -3
  102. package/dist/bin/installer/targets/aider.js.map +2 -2
  103. package/dist/bin/installer/targets/amp.js +3 -3
  104. package/dist/bin/installer/targets/amp.js.map +2 -2
  105. package/dist/bin/installer/targets/antigravity.js +4 -4
  106. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  107. package/dist/bin/installer/targets/augment.js +3 -3
  108. package/dist/bin/installer/targets/augment.js.map +2 -2
  109. package/dist/bin/installer/targets/claude.js +3 -3
  110. package/dist/bin/installer/targets/claude.js.map +2 -2
  111. package/dist/bin/installer/targets/cline.js +4 -4
  112. package/dist/bin/installer/targets/cline.js.map +2 -2
  113. package/dist/bin/installer/targets/codex.js +4 -4
  114. package/dist/bin/installer/targets/codex.js.map +2 -2
  115. package/dist/bin/installer/targets/continue.js +4 -4
  116. package/dist/bin/installer/targets/continue.js.map +2 -2
  117. package/dist/bin/installer/targets/copilot-cli.js +4 -4
  118. package/dist/bin/installer/targets/copilot-cli.js.map +2 -2
  119. package/dist/bin/installer/targets/copilot.js +4 -4
  120. package/dist/bin/installer/targets/copilot.js.map +2 -2
  121. package/dist/bin/installer/targets/cursor.js +5 -5
  122. package/dist/bin/installer/targets/cursor.js.map +2 -2
  123. package/dist/bin/installer/targets/devin.js +4 -4
  124. package/dist/bin/installer/targets/devin.js.map +2 -2
  125. package/dist/bin/installer/targets/gemini-cli.js +4 -4
  126. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  127. package/dist/bin/installer/targets/generic.js +2 -2
  128. package/dist/bin/installer/targets/generic.js.map +2 -2
  129. package/dist/bin/installer/targets/goose.js +3 -4
  130. package/dist/bin/installer/targets/goose.js.map +3 -3
  131. package/dist/bin/installer/targets/index.js.map +1 -1
  132. package/dist/bin/installer/targets/junie.js +4 -4
  133. package/dist/bin/installer/targets/junie.js.map +2 -2
  134. package/dist/bin/installer/targets/kilo.js +4 -4
  135. package/dist/bin/installer/targets/kilo.js.map +2 -2
  136. package/dist/bin/installer/targets/kiro.js +27 -3
  137. package/dist/bin/installer/targets/kiro.js.map +2 -2
  138. package/dist/bin/installer/targets/opencode.js +3 -3
  139. package/dist/bin/installer/targets/opencode.js.map +2 -2
  140. package/dist/bin/installer/targets/openhands.js +3 -3
  141. package/dist/bin/installer/targets/openhands.js.map +2 -2
  142. package/dist/bin/installer/targets/qoder.js +2 -2
  143. package/dist/bin/installer/targets/qoder.js.map +2 -2
  144. package/dist/bin/installer/targets/qwen.js +2 -2
  145. package/dist/bin/installer/targets/qwen.js.map +2 -2
  146. package/dist/bin/installer/targets/replit.js +3 -3
  147. package/dist/bin/installer/targets/replit.js.map +2 -2
  148. package/dist/bin/installer/targets/roo.js +4 -4
  149. package/dist/bin/installer/targets/roo.js.map +2 -2
  150. package/dist/bin/installer/targets/tabnine.js +3 -3
  151. package/dist/bin/installer/targets/tabnine.js.map +2 -2
  152. package/dist/bin/installer/targets/trae.js +3 -3
  153. package/dist/bin/installer/targets/trae.js.map +2 -2
  154. package/dist/bin/installer/targets/warp.js +4 -4
  155. package/dist/bin/installer/targets/warp.js.map +2 -2
  156. package/dist/bin/installer/targets/windsurf.js +4 -4
  157. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  158. package/dist/bin/kirograph.js +83 -1
  159. package/dist/bin/kirograph.js.map +3 -3
  160. package/dist/config.js +30 -8
  161. package/dist/config.js.map +2 -2
  162. package/dist/core/branch-manager.js +111 -0
  163. package/dist/core/branch-manager.js.map +7 -0
  164. package/dist/core/pipeline.js +3 -3
  165. package/dist/core/pipeline.js.map +2 -2
  166. package/dist/data/pixelrag-bridge.js +93 -0
  167. package/dist/data/pixelrag-bridge.js.map +7 -0
  168. package/dist/data/pixelrag-manager.js +416 -0
  169. package/dist/data/pixelrag-manager.js.map +7 -0
  170. package/dist/db/database.js +34 -7
  171. package/dist/db/database.js.map +2 -2
  172. package/dist/db/schema.sql +7 -1
  173. package/dist/extraction/complexity.js +116 -0
  174. package/dist/extraction/complexity.js.map +7 -0
  175. package/dist/extraction/extractor.js +52 -1
  176. package/dist/extraction/extractor.js.map +2 -2
  177. package/dist/graph/git-context.js +229 -0
  178. package/dist/graph/git-context.js.map +7 -0
  179. package/dist/index.js +4 -2
  180. package/dist/index.js.map +2 -2
  181. package/dist/mcp/cache.js +1 -1
  182. package/dist/mcp/cache.js.map +2 -2
  183. package/dist/mcp/handler.js +446 -0
  184. package/dist/mcp/handler.js.map +7 -0
  185. package/dist/mcp/handlers/architecture.js +297 -0
  186. package/dist/mcp/handlers/architecture.js.map +7 -0
  187. package/dist/mcp/handlers/branch.js +175 -0
  188. package/dist/mcp/handlers/branch.js.map +7 -0
  189. package/dist/mcp/handlers/code-health.js +563 -0
  190. package/dist/mcp/handlers/code-health.js.map +7 -0
  191. package/dist/mcp/handlers/complexity.js +267 -0
  192. package/dist/mcp/handlers/complexity.js.map +7 -0
  193. package/dist/mcp/handlers/core.js +611 -0
  194. package/dist/mcp/handlers/core.js.map +7 -0
  195. package/dist/mcp/handlers/data.js +337 -0
  196. package/dist/mcp/handlers/data.js.map +7 -0
  197. package/dist/mcp/handlers/docs.js +159 -0
  198. package/dist/mcp/handlers/docs.js.map +7 -0
  199. package/dist/mcp/handlers/edit-primitives.js +200 -0
  200. package/dist/mcp/handlers/edit-primitives.js.map +7 -0
  201. package/dist/mcp/handlers/git-context.js +286 -0
  202. package/dist/mcp/handlers/git-context.js.map +7 -0
  203. package/dist/mcp/handlers/memory.js +363 -0
  204. package/dist/mcp/handlers/memory.js.map +7 -0
  205. package/dist/mcp/handlers/patterns.js +310 -0
  206. package/dist/mcp/handlers/patterns.js.map +7 -0
  207. package/dist/mcp/handlers/security.js +699 -0
  208. package/dist/mcp/handlers/security.js.map +7 -0
  209. package/dist/mcp/handlers/utils.js +97 -0
  210. package/dist/mcp/handlers/utils.js.map +7 -0
  211. package/dist/mcp/handlers/watchmen.js +104 -0
  212. package/dist/mcp/handlers/watchmen.js.map +7 -0
  213. package/dist/mcp/handlers/wiki.js +242 -0
  214. package/dist/mcp/handlers/wiki.js.map +7 -0
  215. package/dist/mcp/server.js +72 -3
  216. package/dist/mcp/server.js.map +2 -2
  217. package/dist/mcp/tool-names.js +136 -10
  218. package/dist/mcp/tool-names.js.map +2 -2
  219. package/dist/mcp/tools.js +846 -3019
  220. package/dist/mcp/tools.js.map +3 -3
  221. package/dist/types.js.map +2 -2
  222. package/package.json +36 -10
@@ -102,8 +102,13 @@ function buildSteeringContent(opts) {
102
102
  const enablePatterns = opts?.enablePatterns ?? false;
103
103
  const enableWiki = opts?.enableWiki ?? false;
104
104
  const enableCodeHealth = opts?.enableCodeHealth ?? false;
105
- const enableAdvancedAnalysis = opts?.enableAdvancedAnalysis ?? false;
105
+ const enableNavigation = opts?.enableNavigation ?? false;
106
+ const enableGitContext = opts?.enableGitContext ?? false;
107
+ const enableComplexity = opts?.enableComplexity ?? false;
108
+ const enableEditPrimitives = opts?.enableEditPrimitives ?? false;
109
+ const enableBranch = opts?.enableBranch ?? false;
106
110
  const enableAgentUtils = opts?.enableAgentUtils ?? false;
111
+ const enableGeneralCompression = opts?.enableGeneralCompression ?? false;
107
112
  const trackCallSites = opts?.trackCallSites ?? false;
108
113
  const guideRows = [
109
114
  "| Where do I start on this task? | `kirograph_context` |",
@@ -113,15 +118,17 @@ function buildSteeringContent(opts) {
113
118
  "| Who calls function X? | `kirograph_callers` |",
114
119
  "| What does function X call? | `kirograph_callees` |"
115
120
  ] : [],
116
- "| What breaks if I change X? | `kirograph_impact` |",
117
- "| How are X and Y connected? | `kirograph_path` |",
118
- ...enableAdvancedAnalysis ? ["| What extends / implements this type? | `kirograph_type_hierarchy` |"] : [],
121
+ ...enableNavigation ? [
122
+ "| What breaks if I change X? | `kirograph_impact` |",
123
+ "| What files are indexed? | `kirograph_files` |",
124
+ "| Is the index healthy? | `kirograph_status` |"
125
+ ] : [],
119
126
  ...enableCodeHealth ? [
127
+ "| How are X and Y connected? | `kirograph_path` |",
128
+ "| What extends / implements this type? | `kirograph_type_hierarchy` |",
120
129
  "| Which code is never called? | `kirograph_dead_code` |",
121
130
  "| Are there import cycles? | `kirograph_circular_deps` |"
122
131
  ] : [],
123
- "| What files are indexed? | `kirograph_files` |",
124
- "| Is the index healthy? | `kirograph_status` |",
125
132
  ...enableCodeHealth ? [
126
133
  "| What are the most critical symbols? | `kirograph_hotspots` |",
127
134
  "| Any unexpected cross-module coupling? | `kirograph_surprising` |",
@@ -133,6 +140,7 @@ function buildSteeringContent(opts) {
133
140
  "| What does package X depend on? | `kirograph_package` |"
134
141
  ] : [],
135
142
  ...enableCompression ? ["| Run a command with token savings | `kirograph_exec` |"] : [],
143
+ ...enableGeneralCompression ? ["| Compress text or shell output before sending | `kirograph_compress` |"] : [],
136
144
  ...enableAgentUtils ? ["| Check token savings stats | `kirograph_gain` |"] : [],
137
145
  ...enableData ? [
138
146
  "| What data files are indexed? | `kirograph_data_list` |",
@@ -149,7 +157,30 @@ function buildSteeringContent(opts) {
149
157
  "| Generate SBOM/VEX | `kirograph_sbom` / `kirograph_vex` |",
150
158
  "| Add a private CVE | `kirograph_vuln_add` |"
151
159
  ] : [],
152
- ...enablePatterns ? ["| Find structural code patterns? | `kirograph_live_search` |"] : []
160
+ ...enablePatterns ? ["| Find structural code patterns? | `kirograph_live_search` |"] : [],
161
+ ...enableComplexity ? [
162
+ "| Overall graph health score | `kirograph_health` |",
163
+ "| Most complex functions? | `kirograph_complexity` |",
164
+ "| Which functions are highest risk to change? | `kirograph_test_risk` |",
165
+ "| How are modules coupled? | `kirograph_dsm` |"
166
+ ] : [],
167
+ ...enableGitContext ? [
168
+ "| What symbols did I change? | `kirograph_diff_context` |",
169
+ "| Build commit message context | `kirograph_commit_context` |",
170
+ "| Generate PR description | `kirograph_pr_context` |",
171
+ "| What tests cover symbol X? | `kirograph_test_map` |",
172
+ "| Show per-file coverage report | `kirograph_test_coverage` |"
173
+ ] : [],
174
+ ...enableEditPrimitives ? [
175
+ "| Replace a unique string in a file | `kirograph_str_replace` |",
176
+ "| Insert content before/after an anchor | `kirograph_insert_at` |",
177
+ "| Atomic multi-replacement in a file | `kirograph_multi_str_replace` |"
178
+ ] : [],
179
+ ...enableBranch ? [
180
+ "| List tracked branches | `kirograph_branch_list` |",
181
+ "| What changed between branches? | `kirograph_branch_diff` |",
182
+ "| Search symbols in another branch | `kirograph_branch_search` |"
183
+ ] : []
153
184
  ];
154
185
  let toolRef = `
155
186
  ## Tool reference
@@ -203,7 +234,8 @@ BFS over outgoing \`calls\` edges (depth 1).
203
234
  kirograph_callees(symbol: "handleRequest")
204
235
  \`\`\``;
205
236
  }
206
- toolRef += `
237
+ if (enableNavigation) {
238
+ toolRef += `
207
239
 
208
240
  ### \`kirograph_impact\`: blast radius before a change
209
241
 
@@ -211,7 +243,10 @@ Traverses all incoming edges up to \`depth\` hops. Call this before editing a sy
211
243
 
212
244
  \`\`\`
213
245
  kirograph_impact(symbol: "UserRepository", depth: 3)
214
- \`\`\`
246
+ \`\`\``;
247
+ }
248
+ if (enableCodeHealth) {
249
+ toolRef += `
215
250
 
216
251
  ### \`kirograph_path\`: how are two symbols connected?
217
252
 
@@ -219,9 +254,7 @@ BFS shortest path across all edge types.
219
254
 
220
255
  \`\`\`
221
256
  kirograph_path(from: "LoginController", to: "DatabasePool")
222
- \`\`\``;
223
- if (enableAdvancedAnalysis) {
224
- toolRef += `
257
+ \`\`\`
225
258
 
226
259
  ### \`kirograph_type_hierarchy\`: class/interface inheritance
227
260
 
@@ -252,6 +285,7 @@ kirograph_circular_deps()
252
285
  }
253
286
  toolRef += `
254
287
 
288
+ ${enableNavigation ? `
255
289
  ### \`kirograph_files\`: indexed file structure
256
290
 
257
291
  \`\`\`
@@ -264,7 +298,7 @@ kirograph_files(pattern: "**/*.test.ts")
264
298
 
265
299
  ### \`kirograph_status\`: index health
266
300
 
267
- Returns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.`;
301
+ Returns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.` : ""}`;
268
302
  if (enableCodeHealth) {
269
303
  toolRef += `
270
304
 
@@ -330,6 +364,168 @@ Returns metadata, coupling metrics, outgoing deps, incoming dependents, and file
330
364
  \`\`\`
331
365
  kirograph_package(package: "auth")
332
366
  kirograph_package(package: "src/services", includeFiles: false)
367
+ \`\`\``;
368
+ }
369
+ if (enableComplexity) {
370
+ toolRef += `
371
+
372
+ ---
373
+
374
+ ## Complexity tools *(require \`enableComplexity: true\` in config)*
375
+
376
+ ### \`kirograph_health\`: composite graph health score
377
+
378
+ Returns a 0\u201310000 score across four dimensions: complexity, dead code, coupling, circular deps.
379
+ Higher is better. Excellent \u2265 9000 \xB7 Good \u2265 7000 \xB7 Fair \u2265 5000 \xB7 Poor \u2265 3000 \xB7 Critical < 3000.
380
+
381
+ \`\`\`
382
+ kirograph_health()
383
+ \`\`\`
384
+
385
+ ### \`kirograph_complexity\`: rank functions by complexity
386
+
387
+ Returns cyclomatic complexity (CC), cognitive complexity, maintainability index (MI), and nesting depth, sorted by chosen metric.
388
+
389
+ \`\`\`
390
+ kirograph_complexity(metric: "cyclomatic", limit: 30, threshold: 10)
391
+ kirograph_complexity(metric: "cognitive")
392
+ kirograph_complexity(metric: "maintainability") // sort ASC \u2014 lowest MI first
393
+ \`\`\`
394
+
395
+ ### \`kirograph_dsm\`: design structure matrix
396
+
397
+ Groups nodes by top-level directory and shows a dependency count matrix between groups. Reveals which modules depend on which others and where tight coupling lives.
398
+
399
+ \`\`\`
400
+ kirograph_dsm()
401
+ kirograph_dsm(limit: 10) // cap number of groups shown
402
+ \`\`\`
403
+
404
+ ### \`kirograph_test_risk\`: risk-ranked functions
405
+
406
+ Risk = complexity \xD7 fan-in. Highest-risk functions are most likely to cause failures when changed.
407
+
408
+ \`\`\`
409
+ kirograph_test_risk(limit: 20)
410
+ kirograph_test_risk(threshold: 50) // only show risk score \u2265 50
411
+ \`\`\``;
412
+ }
413
+ if (enableGitContext) {
414
+ toolRef += `
415
+
416
+ ---
417
+
418
+ ## Git Context tools *(require \`enableGitContext: true\` in config)*
419
+
420
+ ### \`kirograph_diff_context\`: changed symbols in working tree
421
+
422
+ Returns symbols whose definitions overlap with \`git diff\` line ranges, plus their callers and callees. Use before a commit to understand what you actually changed.
423
+
424
+ \`\`\`
425
+ kirograph_diff_context() // unstaged changes
426
+ kirograph_diff_context(staged: true) // staged changes only
427
+ \`\`\`
428
+
429
+ ### \`kirograph_commit_context\`: staged changes summary
430
+
431
+ Returns staged files, diff stat, and affected symbols. Ready to paste into a commit message prompt.
432
+
433
+ \`\`\`
434
+ kirograph_commit_context()
435
+ \`\`\`
436
+
437
+ ### \`kirograph_pr_context\`: semantic diff between two refs
438
+
439
+ Returns symbols added/removed/changed between two git refs. Use for PR descriptions.
440
+
441
+ \`\`\`
442
+ kirograph_pr_context(base: "main", head: "HEAD")
443
+ kirograph_pr_context(base: "v1.2.0")
444
+ \`\`\`
445
+
446
+ ### \`kirograph_test_map\`: symbol \u2192 test file mapping
447
+
448
+ Shows which test files cover a symbol (by caller graph), and which symbols have no test coverage at all.
449
+
450
+ \`\`\`
451
+ kirograph_test_map() // all uncovered symbols
452
+ kirograph_test_map(symbol: "processPayment") // tests for a specific symbol
453
+ \`\`\`
454
+
455
+ ### \`kirograph_test_coverage\`: per-file coverage report
456
+
457
+ Parses lcov/Istanbul/Cobertura files. Sorted worst-first by default.
458
+
459
+ \`\`\`
460
+ kirograph_test_coverage()
461
+ kirograph_test_coverage(sortBy: "desc", limit: 20) // best coverage first
462
+ \`\`\``;
463
+ }
464
+ if (enableEditPrimitives) {
465
+ toolRef += `
466
+
467
+ ---
468
+
469
+ ## Edit Primitives *(require \`enableEditPrimitives: true\` in config)*
470
+
471
+ Atomic file edit tools. Each validates the anchor is unique before writing, then triggers \`kirograph sync\` to keep the graph up to date.
472
+
473
+ ### \`kirograph_str_replace\`: replace a unique string
474
+
475
+ Fails on 0 or >1 matches \u2014 safe to use without counting occurrences first.
476
+
477
+ \`\`\`
478
+ kirograph_str_replace(file: "src/auth.ts", old_str: "const timeout = 5000", new_str: "const timeout = 10000")
479
+ \`\`\`
480
+
481
+ ### \`kirograph_multi_str_replace\`: N replacements as one transaction
482
+
483
+ All-or-nothing: if any replacement fails, none are applied.
484
+
485
+ \`\`\`
486
+ kirograph_multi_str_replace(file: "src/auth.ts", pairs: [
487
+ { old_str: "oldFunctionName", new_str: "newFunctionName" },
488
+ { old_str: "OldClass", new_str: "NewClass" }
489
+ ])
490
+ \`\`\`
491
+
492
+ ### \`kirograph_insert_at\`: insert before/after an anchor
493
+
494
+ \`\`\`
495
+ kirograph_insert_at(file: "src/routes.ts", anchor: "// END ROUTES", content: "router.get('/health', healthCheck);", position: "before")
496
+ \`\`\`
497
+
498
+ ### \`kirograph_refactor\`: structured search-and-replace across the graph
499
+
500
+ \`\`\`
501
+ kirograph_refactor(symbol: "OldName", newName: "NewName", kind: "function")
502
+ \`\`\``;
503
+ }
504
+ if (enableBranch) {
505
+ toolRef += `
506
+
507
+ ---
508
+
509
+ ## Branch tools *(require \`enableBranch: true\` in config)*
510
+
511
+ Each branch gets its own SQLite DB at \`.kirograph/branch-<name>.db\`. Use \`kirograph branch add\` to start tracking a branch.
512
+
513
+ ### \`kirograph_branch_list\`: tracked branches
514
+
515
+ \`\`\`
516
+ kirograph_branch_list()
517
+ \`\`\`
518
+
519
+ ### \`kirograph_branch_diff\`: symbols added/removed/changed between branches
520
+
521
+ \`\`\`
522
+ kirograph_branch_diff(branchA: "feature/new-auth", branchB: "main")
523
+ \`\`\`
524
+
525
+ ### \`kirograph_branch_search\`: search symbols in another branch
526
+
527
+ \`\`\`
528
+ kirograph_branch_search(query: "processPayment", branch: "main")
333
529
  \`\`\``;
334
530
  }
335
531
  let bugFixWorkflow = `**Bug fix or feature:**
@@ -376,13 +572,53 @@ ${bugFixWorkflow}`;
376
572
  2. \`kirograph_circular_deps\`: find import cycles to untangle.
377
573
  3. \`kirograph_surprising\`: find unexpected coupling to decouple.`;
378
574
  }
575
+ if (enableComplexity) {
576
+ workflows += `
577
+
578
+ **Code quality audit:**
579
+ 1. \`kirograph_health\`: get overall health score and breakdown.
580
+ 2. \`kirograph_complexity\`: rank functions by cyclomatic complexity \u2014 focus on CC > 10.
581
+ 3. \`kirograph_test_risk\`: find highest-risk functions (complexity \xD7 fan-in) to prioritize test coverage.
582
+ 4. \`kirograph_dsm\`: check architectural coupling \u2014 high off-diagonal counts = tight coupling.`;
583
+ }
584
+ if (enableGitContext) {
585
+ workflows += `
586
+
587
+ **Pre-commit / pre-push review:**
588
+ 1. \`kirograph_diff_context\`: understand what symbols changed and who calls them.
589
+ 2. \`kirograph_test_map\`: verify changed symbols have test coverage.
590
+ 3. \`kirograph_commit_context\`: build a structured commit message.
591
+
592
+ **PR description:**
593
+ 1. \`kirograph_pr_context(base: "main")\`: get semantic diff between branches.
594
+ 2. Use the output as structured context for the PR summary.`;
595
+ }
596
+ if (enableEditPrimitives) {
597
+ workflows += `
598
+
599
+ **Safe atomic edit:**
600
+ 1. \`kirograph_impact\`: check blast radius before editing.
601
+ 2. \`kirograph_str_replace\` or \`kirograph_insert_at\`: apply atomic change \u2014 validates uniqueness first.
602
+ 3. After edit: \`kirograph_diff\` to verify only intended symbols changed.`;
603
+ }
604
+ if (enableBranch) {
605
+ workflows += `
606
+
607
+ **Cross-branch investigation:**
608
+ 1. \`kirograph_branch_list\`: see which branches are tracked.
609
+ 2. \`kirograph_branch_diff\`: find symbols added/removed/changed vs target branch.
610
+ 3. \`kirograph_branch_search\`: locate a symbol in another branch's graph.`;
611
+ }
612
+ const hasRichFeatures = enableNavigation || enableCodeHealth || trackCallSites;
379
613
  const workflowRows = [
380
614
  ...enableSecurity ? ["| security audit, check vulnerabilities, CVE review | `.kiro/steering/kirograph-security.md` |"] : [],
381
- "| code review, review this PR | `.kiro/steering/kirograph-review.md` |",
382
- "| debug, trace this bug, root cause | `.kiro/steering/kirograph-debug.md` |",
615
+ ...hasRichFeatures ? ["| code review, review this PR | `.kiro/steering/kirograph-review.md` |"] : [],
616
+ ...hasRichFeatures ? ["| debug, trace this bug, root cause | `.kiro/steering/kirograph-debug.md` |"] : [],
383
617
  ...enableArchitecture ? ["| architecture, understand structure, package map | `.kiro/steering/kirograph-architecture.md` |"] : [],
384
- "| onboard, understand this codebase | `.kiro/steering/kirograph-onboard.md` |",
385
- "| refactor, rename, safe refactoring | `.kiro/steering/kirograph-refactor.md` |",
618
+ ...hasRichFeatures ? ["| onboard, understand this codebase | `.kiro/steering/kirograph-onboard.md` |"] : [],
619
+ ...hasRichFeatures ? ["| refactor, rename, safe refactoring | `.kiro/steering/kirograph-refactor.md` |"] : [],
620
+ ...enableGitContext ? ["| git diff review, PR context, commit message | `.kiro/steering/kirograph-git-context.md` |"] : [],
621
+ ...enableComplexity ? ["| code quality audit, complexity, health score | `.kiro/steering/kirograph-complexity.md` |"] : [],
386
622
  ...enableMemory ? ["| memory, recall decisions, conflict detection | `.kiro/steering/kirograph-mem-workflow.md` |"] : [],
387
623
  ...enableWiki ? ["| wiki, update knowledge base, ingest docs | `.kiro/steering/kirograph-wiki-workflow.md` |"] : []
388
624
  ];
@@ -545,6 +781,42 @@ KiroGraph can search for structural code patterns using @ast-grep/napi.
545
781
  `;
546
782
  content = content.trimEnd() + "\n\n" + patternsSection.trim() + "\n";
547
783
  }
784
+ if (enableGeneralCompression) {
785
+ const generalCompressionSection = `
786
+ ## General-purpose compression
787
+
788
+ \`kirograph_compress\` is an on-demand tool for reducing token usage before content reaches the model.
789
+ Call it whenever you receive large input that you need to reason over but not reproduce verbatim.
790
+
791
+ **Two engines \u2014 auto-routed by the \`command\` parameter:**
792
+
793
+ | Scenario | Call |
794
+ |----------|------|
795
+ | Paste of shell output (git log, npm install, test run, docker ps\u2026) | \`kirograph_compress(text: "...", command: "git log")\` |
796
+ | Prose text, RAG chunk, observation, or mixed content | \`kirograph_compress(text: "...")\` |
797
+
798
+ - **With \`command\`:** rtk-style structural filters \u2014 pattern-matched to the command family (git, test, lint, docker, etc.), removes noise, deduplicates repeated lines, keeps structure.
799
+ - **Without \`command\`:** caveman grammar \u2014 removes filler words, articles, hedging phrases, and (at ultra level) applies standard abbreviations. Preserves code blocks, paths, URLs, and identifiers unchanged.
800
+
801
+ **Compression levels** (same enum for both engines):
802
+ - \`lite\` / \`normal\` \u2014 light touch: remove noise and filler only
803
+ - \`full\` / \`aggressive\` \u2014 default: also remove articles, hedging, group repeated output
804
+ - \`ultra\` \u2014 maximum: abbreviations, causality arrows (\u2192), conjunction compression (+)
805
+
806
+ **When to use:**
807
+ - You received a large file diff, log dump, or search result and only need the structure
808
+ - You want to store an observation in memory and the text is verbose
809
+ - A tool output is close to or over budget and you need to trim before reasoning
810
+
811
+ **When NOT to use:**
812
+ - Content that must be reproduced exactly (code to be written to disk, user quotes)
813
+ - Short content (< 200 tokens) \u2014 overhead not worth it
814
+ - Already-compressed output (kirograph_exec already applies rtk filters automatically)
815
+
816
+ **Savings are reported inline:** \`[42% saved | 1800\u21921044 | rtk:git:aggressive]\`
817
+ `;
818
+ content = content.trimEnd() + "\n\n" + generalCompressionSection.trim() + "\n";
819
+ }
548
820
  if (enableWiki) {
549
821
  const wikiSection = `
550
822
  ## Wiki
@@ -640,39 +912,63 @@ function writeWorkflowSteering(steeringDir, opts) {
640
912
  const trackCallSites = opts?.trackCallSites ?? false;
641
913
  const enableCodeHealth = opts?.enableCodeHealth ?? false;
642
914
  const enableArchitecture = opts?.enableArchitecture ?? false;
643
- const enableAdvancedAnalysis = opts?.enableAdvancedAnalysis ?? false;
644
- const reviewSteps = [
645
- `1. **Understand the change scope**
915
+ const enableNavigation = opts?.enableNavigation ?? false;
916
+ const enableGitContext = opts?.enableGitContext ?? false;
917
+ const enableComplexity = opts?.enableComplexity ?? false;
918
+ const enableEditPrimitives = opts?.enableEditPrimitives ?? false;
919
+ const hasRichFeatures = enableNavigation || enableCodeHealth || trackCallSites;
920
+ if (hasRichFeatures) {
921
+ const reviewSteps = [
922
+ `1. **Understand the change scope**
646
923
  \`\`\`
647
924
  kirograph_context(task: "<describe what changed>")
648
- \`\`\``,
649
- `2. **Analyze blast radius**
925
+ \`\`\``
926
+ ];
927
+ if (enableGitContext) {
928
+ reviewSteps.push(`2. **See exactly what symbols changed**
929
+ \`\`\`
930
+ kirograph_diff_context(staged: true)
931
+ \`\`\`
932
+ Lists changed symbols, their callers (who may break), and callees (what they depend on).`);
933
+ }
934
+ reviewSteps.push(`${reviewSteps.length + 1}. **Analyze blast radius**
650
935
  For each key symbol that was modified:
651
936
  \`\`\`
652
937
  kirograph_impact(symbol: "<changed symbol>", depth: 2)
653
- \`\`\``
654
- ];
655
- if (trackCallSites) {
656
- reviewSteps.push(`3. **Check test coverage**
938
+ \`\`\``);
939
+ if (enableGitContext) {
940
+ reviewSteps.push(`${reviewSteps.length + 1}. **Verify test coverage for changed symbols**
941
+ \`\`\`
942
+ kirograph_test_map(symbol: "<changed symbol>")
943
+ \`\`\`
944
+ Flag any changed symbols with no test files in their caller graph.`);
945
+ } else if (trackCallSites) {
946
+ reviewSteps.push(`${reviewSteps.length + 1}. **Check test coverage**
657
947
  \`\`\`
658
948
  kirograph_callers(symbol: "<changed symbol>")
659
949
  \`\`\`
660
950
  Look for test files among the callers. Flag untested changes.`);
661
- }
662
- if (enableCodeHealth) {
663
- const n = reviewSteps.length + 1;
664
- reviewSteps.push(`${n}. **Look for surprising coupling**
951
+ }
952
+ if (enableComplexity) {
953
+ reviewSteps.push(`${reviewSteps.length + 1}. **Check risk score of changed functions**
954
+ \`\`\`
955
+ kirograph_test_risk(limit: 10)
956
+ \`\`\`
957
+ High risk (complexity \xD7 fan-in) = extra scrutiny warranted.`);
958
+ }
959
+ if (enableCodeHealth) {
960
+ reviewSteps.push(`${reviewSteps.length + 1}. **Look for surprising coupling**
665
961
  \`\`\`
666
962
  kirograph_surprising(limit: 10)
667
963
  \`\`\``);
668
- }
669
- const findingsN = reviewSteps.length + 1;
670
- reviewSteps.push(`${findingsN}. **Produce findings** grouped by risk level (high/medium/low) with:
964
+ }
965
+ const findingsN = reviewSteps.length + 1;
966
+ reviewSteps.push(`${findingsN}. **Produce findings** grouped by risk level (high/medium/low) with:
671
967
  - What changed and why it matters
672
968
  - Test coverage status
673
969
  - Suggested improvements
674
970
  - Overall merge recommendation`);
675
- fs.writeFileSync(path.join(steeringDir, "kirograph-review.md"), `---
971
+ fs.writeFileSync(path.join(steeringDir, "kirograph-review.md"), `---
676
972
  inclusion: manual
677
973
  ---
678
974
 
@@ -684,40 +980,47 @@ Follow these steps for a structured, risk-aware code review using the knowledge
684
980
 
685
981
  ${reviewSteps.join("\n\n")}
686
982
  `);
687
- const debugSteps = [
688
- `1. **Find related code**
983
+ const debugSteps = [
984
+ `1. **Find related code**
689
985
  \`\`\`
690
986
  kirograph_search(query: "<error message or symptom keywords>")
691
987
  \`\`\``,
692
- `2. **Get full context**
988
+ `2. **Get full context**
693
989
  \`\`\`
694
990
  kirograph_context(task: "<describe the bug>")
695
991
  \`\`\``
696
- ];
697
- if (trackCallSites) {
698
- debugSteps.push(`3. **Trace the call chain**
992
+ ];
993
+ if (enableGitContext) {
994
+ debugSteps.push(`3. **Check what recently changed in related symbols**
699
995
  \`\`\`
700
- kirograph_callers(symbol: "<suspected function>")
701
- kirograph_callees(symbol: "<suspected function>")
702
- \`\`\``);
703
- }
704
- if (enableCodeHealth) {
705
- const n = debugSteps.length + 1;
706
- debugSteps.push(`${n}. **Check what changed recently**
996
+ kirograph_diff_context()
997
+ \`\`\`
998
+ Most bugs trace back to recent changes \u2014 this surfaces them immediately.`);
999
+ } else if (enableCodeHealth) {
1000
+ debugSteps.push(`3. **Check what changed recently**
707
1001
  \`\`\`
708
1002
  kirograph_diff()
709
1003
  \`\`\``);
710
- }
711
- const blastN = debugSteps.length + 1;
712
- debugSteps.push(`${blastN}. **Understand blast radius**
1004
+ }
1005
+ if (trackCallSites) {
1006
+ const n = debugSteps.length + 1;
1007
+ debugSteps.push(`${n}. **Trace the call chain**
1008
+ \`\`\`
1009
+ kirograph_callers(symbol: "<suspected function>")
1010
+ kirograph_callees(symbol: "<suspected function>")
1011
+ \`\`\``);
1012
+ }
1013
+ const blastN = debugSteps.length + 1;
1014
+ debugSteps.push(`${blastN}. **Understand blast radius**
713
1015
  \`\`\`
714
1016
  kirograph_impact(symbol: "<root cause symbol>", depth: 3)
715
1017
  \`\`\``);
716
- const debugTips = [];
717
- if (trackCallSites) debugTips.push("- Check both callers and callees to understand the full context");
718
- if (enableCodeHealth) debugTips.push("- Recent changes (via diff) are the most common source of new issues");
719
- debugTips.push("- Use `kirograph_path` to trace how two symbols are connected");
720
- fs.writeFileSync(path.join(steeringDir, "kirograph-debug.md"), `---
1018
+ const debugTips = [];
1019
+ if (trackCallSites) debugTips.push("- Check both callers and callees to understand the full context");
1020
+ if (enableGitContext) debugTips.push("- `kirograph_diff_context` is the fastest way to spot a regression \u2014 check it first");
1021
+ else if (enableCodeHealth) debugTips.push("- Recent changes (via diff) are the most common source of new issues");
1022
+ debugTips.push("- Use `kirograph_path` to trace how two symbols are connected");
1023
+ fs.writeFileSync(path.join(steeringDir, "kirograph-debug.md"), `---
721
1024
  inclusion: manual
722
1025
  ---
723
1026
 
@@ -732,44 +1035,44 @@ ${debugSteps.join("\n\n")}
732
1035
  ## Tips
733
1036
  ${debugTips.join("\n")}
734
1037
  `);
735
- const onboardSteps = [
736
- `1. **Project overview**
1038
+ const onboardSteps = [
1039
+ `1. **Project overview**
737
1040
  \`\`\`
738
1041
  kirograph_status()
739
1042
  \`\`\``,
740
- `2. **File structure**
1043
+ `2. **File structure**
741
1044
  \`\`\`
742
1045
  kirograph_files(format: "tree", maxDepth: 2)
743
1046
  \`\`\``
744
- ];
745
- if (enableCodeHealth) {
746
- onboardSteps.push(`3. **Key entry points**
1047
+ ];
1048
+ if (enableCodeHealth) {
1049
+ onboardSteps.push(`3. **Key entry points**
747
1050
  \`\`\`
748
1051
  kirograph_hotspots(limit: 15)
749
1052
  \`\`\``);
750
- }
751
- if (enableArchitecture) {
752
- const n = onboardSteps.length + 1;
753
- onboardSteps.push(`${n}. **Architecture layers**
1053
+ }
1054
+ if (enableArchitecture) {
1055
+ const n = onboardSteps.length + 1;
1056
+ onboardSteps.push(`${n}. **Architecture layers**
754
1057
  \`\`\`
755
1058
  kirograph_architecture()
756
1059
  \`\`\``);
757
- }
758
- const exploreN = onboardSteps.length + 1;
759
- onboardSteps.push(`${exploreN}. **Explore a specific area**
1060
+ }
1061
+ const exploreN = onboardSteps.length + 1;
1062
+ onboardSteps.push(`${exploreN}. **Explore a specific area**
760
1063
  \`\`\`
761
1064
  kirograph_context(task: "<area you want to understand>")
762
1065
  \`\`\``);
763
- const symbolN = onboardSteps.length + 1;
764
- onboardSteps.push(`${symbolN}. **Understand a key symbol**
1066
+ const symbolN = onboardSteps.length + 1;
1067
+ onboardSteps.push(`${symbolN}. **Understand a key symbol**
765
1068
  \`\`\`
766
1069
  kirograph_node(symbol: "<symbol name>", includeCode: true)
767
1070
  \`\`\``);
768
- const onboardTips = ["- Start broad (status, files) then narrow down"];
769
- if (enableCodeHealth) onboardTips[0] = "- Start broad (status, files, hotspots) then narrow down";
770
- if (enableAdvancedAnalysis) onboardTips.push("- Use `kirograph_type_hierarchy` to understand inheritance patterns");
771
- if (trackCallSites) onboardTips.push("- Use `kirograph_callees` on entry points to trace execution flow");
772
- fs.writeFileSync(path.join(steeringDir, "kirograph-onboard.md"), `---
1071
+ const onboardTips = ["- Start broad (status, files) then narrow down"];
1072
+ if (enableCodeHealth) onboardTips[0] = "- Start broad (status, files, hotspots) then narrow down";
1073
+ if (enableCodeHealth) onboardTips.push("- Use `kirograph_type_hierarchy` to understand inheritance patterns");
1074
+ if (trackCallSites) onboardTips.push("- Use `kirograph_callees` on entry points to trace execution flow");
1075
+ fs.writeFileSync(path.join(steeringDir, "kirograph-onboard.md"), `---
773
1076
  inclusion: manual
774
1077
  ---
775
1078
 
@@ -784,44 +1087,45 @@ ${onboardSteps.join("\n\n")}
784
1087
  ## Tips
785
1088
  ${onboardTips.join("\n")}
786
1089
  `);
787
- const refactorSteps = [
788
- `1. **Understand what you're changing**
1090
+ const refactorSteps = [
1091
+ `1. **Understand what you're changing**
789
1092
  \`\`\`
790
1093
  kirograph_node(symbol: "<target symbol>", includeCode: true)
791
1094
  \`\`\``,
792
- `2. **Check blast radius**
1095
+ `2. **Check blast radius**
793
1096
  \`\`\`
794
1097
  kirograph_impact(symbol: "<target symbol>", depth: 3)
795
1098
  \`\`\``
796
- ];
797
- if (trackCallSites) {
798
- refactorSteps.push(`3. **Find all callers (rename preview)**
1099
+ ];
1100
+ if (trackCallSites) {
1101
+ refactorSteps.push(`3. **Find all callers (rename preview)**
799
1102
  \`\`\`
800
1103
  kirograph_callers(symbol: "<target symbol>", limit: 50)
801
1104
  \`\`\``);
802
- }
803
- if (enableCodeHealth) {
804
- let n = refactorSteps.length + 1;
805
- refactorSteps.push(`${n}. **Check for cycles that might complicate the refactor**
1105
+ }
1106
+ if (enableCodeHealth) {
1107
+ let n = refactorSteps.length + 1;
1108
+ refactorSteps.push(`${n}. **Check for cycles that might complicate the refactor**
806
1109
  \`\`\`
807
1110
  kirograph_circular_deps()
808
1111
  \`\`\``);
809
- n++;
810
- refactorSteps.push(`${n}. **Find dead code to clean up**
1112
+ n++;
1113
+ refactorSteps.push(`${n}. **Find dead code to clean up**
811
1114
  \`\`\`
812
1115
  kirograph_dead_code(limit: 30)
813
1116
  \`\`\``);
814
- n++;
815
- refactorSteps.push(`${n}. **Verify after changes**
1117
+ n++;
1118
+ refactorSteps.push(`${n}. **Verify after changes**
816
1119
  Run \`kirograph sync\` then:
817
1120
  \`\`\`
818
1121
  kirograph_diff()
819
1122
  \`\`\``);
820
- }
821
- const refactorChecks = ["- Always check `kirograph_impact` before major refactors"];
822
- if (trackCallSites) refactorChecks.push("- Use `kirograph_callers` as a rename preview (all locations that reference the symbol)");
823
- if (enableCodeHealth) refactorChecks.push("- After changes, use `kirograph_diff` to verify only intended symbols changed");
824
- fs.writeFileSync(path.join(steeringDir, "kirograph-refactor.md"), `---
1123
+ }
1124
+ const refactorChecks = ["- Always check `kirograph_impact` before major refactors"];
1125
+ if (trackCallSites) refactorChecks.push("- Use `kirograph_callers` as a rename preview (all locations that reference the symbol)");
1126
+ if (enableCodeHealth) refactorChecks.push("- After changes, use `kirograph_diff` to verify only intended symbols changed");
1127
+ if (enableEditPrimitives) refactorChecks.push("- Use `kirograph_str_replace` / `kirograph_multi_str_replace` for atomic edits that auto-sync the graph");
1128
+ fs.writeFileSync(path.join(steeringDir, "kirograph-refactor.md"), `---
825
1129
  inclusion: manual
826
1130
  ---
827
1131
 
@@ -836,6 +1140,7 @@ ${refactorSteps.join("\n\n")}
836
1140
  ## Safety Checks
837
1141
  ${refactorChecks.join("\n")}
838
1142
  `);
1143
+ }
839
1144
  if (enableArchitecture) {
840
1145
  const archSteps = [
841
1146
  `1. **Get project overview**
@@ -868,6 +1173,27 @@ ${refactorChecks.join("\n")}
868
1173
  kirograph_circular_deps()
869
1174
  \`\`\``);
870
1175
  }
1176
+ if (enableComplexity) {
1177
+ let n = archSteps.length + 1;
1178
+ archSteps.push(`${n}. **Module coupling matrix (DSM)**
1179
+ \`\`\`
1180
+ kirograph_dsm()
1181
+ \`\`\`
1182
+ High off-diagonal counts = tight coupling. Complements \`kirograph_coupling\` (package-level) with a symbol-level view.`);
1183
+ n++;
1184
+ archSteps.push(`${n}. **Overall health score**
1185
+ \`\`\`
1186
+ kirograph_health()
1187
+ \`\`\`
1188
+ The circular deps and coupling components directly reflect architectural quality.`);
1189
+ }
1190
+ const archInterpretation = [
1191
+ "- High Ca (afferent) = load-bearing, risky to change interface",
1192
+ "- High Ce (efferent) = depends on many things, safe to refactor internals",
1193
+ ...enableCodeHealth ? ["- Surprising edges = hidden coupling that may break during refactoring"] : [],
1194
+ ...enableComplexity ? ["- DSM diagonal = self-coupling (normal). Off-diagonal = cross-module coupling (minimize)."] : [],
1195
+ ...enableComplexity ? ["- Health circular_score < 1500 = architectural debt requiring attention"] : []
1196
+ ];
871
1197
  fs.writeFileSync(path.join(steeringDir, "kirograph-architecture.md"), `---
872
1198
  inclusion: manual
873
1199
  ---
@@ -881,11 +1207,24 @@ Follow these steps to understand the high-level structure of the codebase.
881
1207
  ${archSteps.join("\n\n")}
882
1208
 
883
1209
  ## Interpretation
884
- - High Ca (afferent) = load-bearing, risky to change interface
885
- - High Ce (efferent) = depends on many things, safe to refactor internals
886
- ${enableCodeHealth ? "- Surprising edges = hidden coupling that may break during refactoring\n" : ""}`);
1210
+ ${archInterpretation.join("\n")}
1211
+ `);
887
1212
  }
888
1213
  if (opts?.enableSecurity) {
1214
+ const securityPatternsStep = opts?.enablePatterns ? `
1215
+ ### 5b. Structural vulnerability patterns (AST search)
1216
+ \`\`\`
1217
+ kirograph_live_search(pattern: "eval($X)", language: "javascript")
1218
+ kirograph_live_search(pattern: "$OBJ.query($A + $B)", language: "typescript")
1219
+ \`\`\`
1220
+ Use \`kirograph pattern --list\` to browse bundled SAST rules (SQL injection, path traversal, hardcoded secrets, etc.).
1221
+ These patterns find code issues missed by dependency scanning.` : "";
1222
+ const securityComplexityStep = enableComplexity ? `
1223
+ ### 5c. High-complexity code in security-critical paths
1224
+ \`\`\`
1225
+ kirograph_test_risk(limit: 15)
1226
+ \`\`\`
1227
+ High risk (complexity \xD7 fan-in) in auth/payment/session code = higher attack surface. Cross-reference with reachability results.` : "";
889
1228
  fs.writeFileSync(path.join(steeringDir, "kirograph-security.md"), `---
890
1229
  inclusion: manual
891
1230
  ---
@@ -937,6 +1276,7 @@ kirograph_licenses(policy: true)
937
1276
  \`\`\`
938
1277
  Review any DENY violations \u2014 these must be resolved before shipping.
939
1278
  WARN violations should be documented and approved by the team.
1279
+ ${securityPatternsStep}${securityComplexityStep}
940
1280
 
941
1281
  ### 6. Dependency staleness
942
1282
  \`\`\`
@@ -967,7 +1307,7 @@ kirograph_vex() // Vulnerability Exploitability eXchange
967
1307
  | \`not_affected\` | No reachable path found | Document, no action needed |
968
1308
  | \`under_investigation\` | Reachability unclear | Manual review required |
969
1309
  | Stale >= 0.7 | Very outdated | Review for accumulated CVEs |
970
- | License DENY | Policy violation | Must resolve before release |
1310
+ | License DENY | Policy violation | Must resolve before release |${opts?.enablePatterns ? "\n| Pattern match in security-critical code | Code-level vulnerability pattern found | Review context with `kirograph_node` |" : ""}
971
1311
  `);
972
1312
  console.log(` \u2713 Security workflow steering file written`);
973
1313
  }
@@ -1247,13 +1587,142 @@ superseded via \`kirograph_mem_judge\`.
1247
1587
  `);
1248
1588
  console.log(` \u2713 Memory workflow steering file written`);
1249
1589
  }
1250
- const written = ["review", "debug", "onboard", "refactor"];
1590
+ if (enableGitContext) {
1591
+ fs.writeFileSync(path.join(steeringDir, "kirograph-git-context.md"), `---
1592
+ inclusion: manual
1593
+ ---
1594
+
1595
+ # KiroGraph: Git Context Workflow
1596
+
1597
+ Use this workflow for pre-commit reviews, PR descriptions, and understanding what changed.
1598
+
1599
+ ## 1. Before committing \u2014 understand what you changed
1600
+
1601
+ \`\`\`
1602
+ kirograph_diff_context() // unstaged \u2014 see what's touched
1603
+ kirograph_diff_context(staged: true) // staged \u2014 final check before commit
1604
+ \`\`\`
1605
+
1606
+ This shows changed symbols, their callers (who might break), and their callees (what they call).
1607
+
1608
+ ## 2. Build commit message context
1609
+
1610
+ \`\`\`
1611
+ kirograph_commit_context()
1612
+ \`\`\`
1613
+
1614
+ Returns staged files, diff stat, and affected symbols. Feed into commit message generation.
1615
+
1616
+ ## 3. Check test coverage for changed symbols
1617
+
1618
+ \`\`\`
1619
+ kirograph_test_map() // all symbols with no test coverage
1620
+ kirograph_test_map(symbol: "<changed fn>") // tests for a specific symbol
1621
+ \`\`\`
1622
+
1623
+ ## 4. PR description
1624
+
1625
+ \`\`\`
1626
+ kirograph_pr_context(base: "main", head: "HEAD")
1627
+ \`\`\`
1628
+
1629
+ Returns symbols added/removed/changed between refs. Use as structured context for PR summary.
1630
+
1631
+ ## 5. Coverage report (if lcov/Istanbul files exist)
1632
+
1633
+ \`\`\`
1634
+ kirograph_test_coverage() // worst-covered files first
1635
+ kirograph_test_coverage(sortBy: "desc") // best-covered files first
1636
+ \`\`\`
1637
+
1638
+ ## Quick reference
1639
+
1640
+ | Intent | Tool |
1641
+ |--------|------|
1642
+ | What did I change? | \`kirograph_diff_context\` |
1643
+ | Commit message | \`kirograph_commit_context\` |
1644
+ | PR description | \`kirograph_pr_context\` |
1645
+ | Are my changes tested? | \`kirograph_test_map\` |
1646
+ | Per-file coverage % | \`kirograph_test_coverage\` |
1647
+ | Semantic changelog | \`kirograph_changelog\` |
1648
+ `);
1649
+ console.log(` \u2713 Git context workflow steering file written`);
1650
+ }
1651
+ if (enableComplexity) {
1652
+ fs.writeFileSync(path.join(steeringDir, "kirograph-complexity.md"), `---
1653
+ inclusion: manual
1654
+ ---
1655
+
1656
+ # KiroGraph: Code Quality Workflow
1657
+
1658
+ Use this workflow to audit code quality, find high-risk functions, and track health over time.
1659
+
1660
+ ## 1. Get an overall health score
1661
+
1662
+ \`\`\`
1663
+ kirograph_health()
1664
+ \`\`\`
1665
+
1666
+ Returns a 0\u201310000 score across complexity, dead code, coupling, and circular dependencies.
1667
+ Check all four components \u2014 a high total can mask one very low component.
1668
+
1669
+ ## 2. Find complex functions
1670
+
1671
+ \`\`\`
1672
+ kirograph_complexity(metric: "cyclomatic", threshold: 10)
1673
+ kirograph_complexity(metric: "maintainability") // lowest MI first \u2014 most unmaintainable
1674
+ \`\`\`
1675
+
1676
+ **Thresholds:** CC > 10 = review candidate. CC > 20 = refactor. MI < 50 = unmaintainable.
1677
+
1678
+ ## 3. Find highest-risk functions to change
1679
+
1680
+ \`\`\`
1681
+ kirograph_test_risk(limit: 20)
1682
+ \`\`\`
1683
+
1684
+ Risk = complexity \xD7 fan-in. These functions will have the widest blast radius if they break.
1685
+
1686
+ ## 4. Check architectural coupling
1687
+
1688
+ \`\`\`
1689
+ kirograph_dsm()
1690
+ \`\`\`
1691
+
1692
+ High off-diagonal counts = tight coupling. Aim for low counts outside the diagonal.
1693
+
1694
+ ## 5. Scan for simplification candidates
1695
+
1696
+ \`\`\`
1697
+ kirograph_simplify_scan()
1698
+ \`\`\`
1699
+
1700
+ Lists functions that fail on CC, MI, or LOC thresholds.
1701
+
1702
+ ## Quick reference
1703
+
1704
+ | Intent | Tool |
1705
+ |--------|------|
1706
+ | Overall health | \`kirograph_health\` |
1707
+ | Most complex functions | \`kirograph_complexity\` |
1708
+ | Highest-risk to change | \`kirograph_test_risk\` |
1709
+ | Module coupling matrix | \`kirograph_dsm\` |
1710
+ | Simplification candidates | \`kirograph_simplify_scan\` |
1711
+ `);
1712
+ console.log(` \u2713 Complexity workflow steering file written`);
1713
+ }
1714
+ const written = [];
1715
+ if (hasRichFeatures) written.push("review", "debug", "onboard", "refactor");
1251
1716
  if (opts?.enableArchitecture) written.push("architecture");
1252
1717
  if (opts?.enableSecurity) written.push("security");
1253
1718
  if (opts?.enablePatterns) written.push("patterns");
1719
+ if (enableGitContext) written.push("git-context");
1720
+ if (enableComplexity) written.push("complexity");
1254
1721
  if (opts?.enableMemory) written.push("memory");
1255
1722
  if (opts?.enableWiki) written.push("wiki");
1256
- console.log(` \u2713 Workflow steering files written (${written.join(", ")})`);
1723
+ if (written.length > 0) {
1724
+ console.log(` \u2713 Workflow steering files written (${written.join(", ")})`);
1725
+ }
1257
1726
  }
1258
1727
  // Annotate the CommonJS export names for ESM import in node:
1259
1728
  0 && (module.exports = {