@optave/codegraph 3.4.0 → 3.4.1

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 (410) hide show
  1. package/README.md +7 -7
  2. package/dist/ast-analysis/engine.d.ts.map +1 -1
  3. package/dist/ast-analysis/engine.js +3 -9
  4. package/dist/ast-analysis/engine.js.map +1 -1
  5. package/dist/ast-analysis/shared.d.ts.map +1 -1
  6. package/dist/ast-analysis/shared.js +0 -1
  7. package/dist/ast-analysis/shared.js.map +1 -1
  8. package/dist/ast-analysis/visitors/cfg-conditionals.d.ts +5 -0
  9. package/dist/ast-analysis/visitors/cfg-conditionals.d.ts.map +1 -0
  10. package/dist/ast-analysis/visitors/cfg-conditionals.js +166 -0
  11. package/dist/ast-analysis/visitors/cfg-conditionals.js.map +1 -0
  12. package/dist/ast-analysis/visitors/cfg-loops.d.ts +7 -0
  13. package/dist/ast-analysis/visitors/cfg-loops.d.ts.map +1 -0
  14. package/dist/ast-analysis/visitors/cfg-loops.js +73 -0
  15. package/dist/ast-analysis/visitors/cfg-loops.js.map +1 -0
  16. package/dist/ast-analysis/visitors/cfg-shared.d.ts +56 -0
  17. package/dist/ast-analysis/visitors/cfg-shared.d.ts.map +1 -0
  18. package/dist/ast-analysis/visitors/cfg-shared.js +107 -0
  19. package/dist/ast-analysis/visitors/cfg-shared.js.map +1 -0
  20. package/dist/ast-analysis/visitors/cfg-try-catch.d.ts +4 -0
  21. package/dist/ast-analysis/visitors/cfg-try-catch.d.ts.map +1 -0
  22. package/dist/ast-analysis/visitors/cfg-try-catch.js +100 -0
  23. package/dist/ast-analysis/visitors/cfg-try-catch.js.map +1 -0
  24. package/dist/ast-analysis/visitors/cfg-visitor.d.ts +2 -2
  25. package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -1
  26. package/dist/ast-analysis/visitors/cfg-visitor.js +11 -445
  27. package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -1
  28. package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
  29. package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
  30. package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
  31. package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
  32. package/dist/cli/commands/batch.d.ts.map +1 -1
  33. package/dist/cli/commands/batch.js +4 -3
  34. package/dist/cli/commands/batch.js.map +1 -1
  35. package/dist/cli/commands/branch-compare.js +1 -1
  36. package/dist/cli/commands/branch-compare.js.map +1 -1
  37. package/dist/cli/commands/build.js +1 -1
  38. package/dist/cli/commands/build.js.map +1 -1
  39. package/dist/cli/commands/info.d.ts.map +1 -1
  40. package/dist/cli/commands/info.js +1 -2
  41. package/dist/cli/commands/info.js.map +1 -1
  42. package/dist/cli/commands/path.d.ts.map +1 -1
  43. package/dist/cli/commands/path.js +7 -2
  44. package/dist/cli/commands/path.js.map +1 -1
  45. package/dist/cli/commands/plot.d.ts.map +1 -1
  46. package/dist/cli/commands/plot.js +2 -2
  47. package/dist/cli/commands/plot.js.map +1 -1
  48. package/dist/cli/commands/watch.js +1 -1
  49. package/dist/cli/commands/watch.js.map +1 -1
  50. package/dist/cli/index.js +2 -2
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/cli/shared/open-graph.d.ts +2 -2
  53. package/dist/cli/shared/open-graph.d.ts.map +1 -1
  54. package/dist/cli/shared/open-graph.js.map +1 -1
  55. package/dist/cli/types.d.ts +1 -1
  56. package/dist/cli/types.d.ts.map +1 -1
  57. package/dist/cli.js +2 -3
  58. package/dist/cli.js.map +1 -1
  59. package/dist/db/connection.d.ts +17 -0
  60. package/dist/db/connection.d.ts.map +1 -1
  61. package/dist/db/connection.js +91 -2
  62. package/dist/db/connection.js.map +1 -1
  63. package/dist/db/index.d.ts +1 -1
  64. package/dist/db/index.d.ts.map +1 -1
  65. package/dist/db/index.js +1 -1
  66. package/dist/db/index.js.map +1 -1
  67. package/dist/db/migrations.d.ts.map +1 -1
  68. package/dist/db/migrations.js +7 -0
  69. package/dist/db/migrations.js.map +1 -1
  70. package/dist/domain/analysis/brief.d.ts.map +1 -1
  71. package/dist/domain/analysis/brief.js +1 -3
  72. package/dist/domain/analysis/brief.js.map +1 -1
  73. package/dist/domain/analysis/context.d.ts.map +1 -1
  74. package/dist/domain/analysis/context.js +2 -4
  75. package/dist/domain/analysis/context.js.map +1 -1
  76. package/dist/domain/analysis/dependencies.d.ts +49 -0
  77. package/dist/domain/analysis/dependencies.d.ts.map +1 -1
  78. package/dist/domain/analysis/dependencies.js +145 -0
  79. package/dist/domain/analysis/dependencies.js.map +1 -1
  80. package/dist/domain/analysis/diff-impact.d.ts +76 -0
  81. package/dist/domain/analysis/diff-impact.d.ts.map +1 -0
  82. package/dist/domain/analysis/diff-impact.js +282 -0
  83. package/dist/domain/analysis/diff-impact.js.map +1 -0
  84. package/dist/domain/analysis/exports.d.ts.map +1 -1
  85. package/dist/domain/analysis/exports.js +0 -1
  86. package/dist/domain/analysis/exports.js.map +1 -1
  87. package/dist/domain/analysis/fn-impact.d.ts +66 -0
  88. package/dist/domain/analysis/fn-impact.d.ts.map +1 -0
  89. package/dist/domain/analysis/fn-impact.js +189 -0
  90. package/dist/domain/analysis/fn-impact.js.map +1 -0
  91. package/dist/domain/analysis/impact.d.ts +8 -148
  92. package/dist/domain/analysis/impact.d.ts.map +1 -1
  93. package/dist/domain/analysis/impact.js +8 -568
  94. package/dist/domain/analysis/impact.js.map +1 -1
  95. package/dist/domain/analysis/module-map.d.ts.map +1 -1
  96. package/dist/domain/analysis/module-map.js +1 -3
  97. package/dist/domain/analysis/module-map.js.map +1 -1
  98. package/dist/domain/graph/builder/context.d.ts +2 -3
  99. package/dist/domain/graph/builder/context.d.ts.map +1 -1
  100. package/dist/domain/graph/builder/context.js.map +1 -1
  101. package/dist/domain/graph/builder/helpers.d.ts +4 -5
  102. package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
  103. package/dist/domain/graph/builder/helpers.js +1 -2
  104. package/dist/domain/graph/builder/helpers.js.map +1 -1
  105. package/dist/domain/graph/builder/incremental.d.ts +2 -3
  106. package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
  107. package/dist/domain/graph/builder/incremental.js.map +1 -1
  108. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
  109. package/dist/domain/graph/builder/pipeline.js +6 -0
  110. package/dist/domain/graph/builder/pipeline.js.map +1 -1
  111. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
  112. package/dist/domain/graph/builder/stages/build-edges.js +12 -2
  113. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
  114. package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
  115. package/dist/domain/graph/builder/stages/build-structure.js +155 -59
  116. package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
  117. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
  118. package/dist/domain/graph/builder/stages/detect-changes.js +6 -6
  119. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
  120. package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
  121. package/dist/domain/graph/builder/stages/finalize.js +85 -61
  122. package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
  123. package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
  124. package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
  125. package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
  126. package/dist/domain/graph/builder/stages/resolve-imports.js +58 -11
  127. package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
  128. package/dist/domain/graph/cycles.js +2 -2
  129. package/dist/domain/graph/cycles.js.map +1 -1
  130. package/dist/domain/graph/resolve.d.ts.map +1 -1
  131. package/dist/domain/graph/resolve.js +10 -8
  132. package/dist/domain/graph/resolve.js.map +1 -1
  133. package/dist/domain/graph/watcher.d.ts.map +1 -1
  134. package/dist/domain/graph/watcher.js +1 -3
  135. package/dist/domain/graph/watcher.js.map +1 -1
  136. package/dist/domain/parser.d.ts.map +1 -1
  137. package/dist/domain/parser.js +11 -12
  138. package/dist/domain/parser.js.map +1 -1
  139. package/dist/domain/queries.d.ts +3 -2
  140. package/dist/domain/queries.d.ts.map +1 -1
  141. package/dist/domain/queries.js +3 -2
  142. package/dist/domain/queries.js.map +1 -1
  143. package/dist/domain/search/generator.d.ts.map +1 -1
  144. package/dist/domain/search/generator.js.map +1 -1
  145. package/dist/extractors/csharp.js +2 -2
  146. package/dist/extractors/csharp.js.map +1 -1
  147. package/dist/extractors/go.js +2 -2
  148. package/dist/extractors/go.js.map +1 -1
  149. package/dist/extractors/helpers.d.ts +5 -0
  150. package/dist/extractors/helpers.d.ts.map +1 -1
  151. package/dist/extractors/helpers.js +5 -0
  152. package/dist/extractors/helpers.js.map +1 -1
  153. package/dist/extractors/javascript.js +58 -60
  154. package/dist/extractors/javascript.js.map +1 -1
  155. package/dist/extractors/php.js +2 -2
  156. package/dist/extractors/php.js.map +1 -1
  157. package/dist/extractors/python.js +2 -2
  158. package/dist/extractors/python.js.map +1 -1
  159. package/dist/extractors/rust.js +2 -2
  160. package/dist/extractors/rust.js.map +1 -1
  161. package/dist/features/audit.d.ts.map +1 -1
  162. package/dist/features/audit.js +1 -2
  163. package/dist/features/audit.js.map +1 -1
  164. package/dist/features/branch-compare.d.ts.map +1 -1
  165. package/dist/features/branch-compare.js +2 -3
  166. package/dist/features/branch-compare.js.map +1 -1
  167. package/dist/features/cfg.d.ts.map +1 -1
  168. package/dist/features/cfg.js +2 -4
  169. package/dist/features/cfg.js.map +1 -1
  170. package/dist/features/cochange.js +4 -4
  171. package/dist/features/cochange.js.map +1 -1
  172. package/dist/features/communities.js +4 -4
  173. package/dist/features/communities.js.map +1 -1
  174. package/dist/features/complexity-query.d.ts +37 -0
  175. package/dist/features/complexity-query.d.ts.map +1 -0
  176. package/dist/features/complexity-query.js +263 -0
  177. package/dist/features/complexity-query.js.map +1 -0
  178. package/dist/features/complexity.d.ts +2 -30
  179. package/dist/features/complexity.d.ts.map +1 -1
  180. package/dist/features/complexity.js +7 -261
  181. package/dist/features/complexity.js.map +1 -1
  182. package/dist/features/dataflow.d.ts.map +1 -1
  183. package/dist/features/dataflow.js +8 -24
  184. package/dist/features/dataflow.js.map +1 -1
  185. package/dist/features/export.d.ts +7 -8
  186. package/dist/features/export.d.ts.map +1 -1
  187. package/dist/features/export.js.map +1 -1
  188. package/dist/features/flow.d.ts.map +1 -1
  189. package/dist/features/flow.js.map +1 -1
  190. package/dist/features/graph-enrichment.d.ts.map +1 -1
  191. package/dist/features/graph-enrichment.js +1 -3
  192. package/dist/features/graph-enrichment.js.map +1 -1
  193. package/dist/features/manifesto.js +8 -8
  194. package/dist/features/manifesto.js.map +1 -1
  195. package/dist/features/snapshot.d.ts.map +1 -1
  196. package/dist/features/snapshot.js +0 -1
  197. package/dist/features/snapshot.js.map +1 -1
  198. package/dist/features/structure-query.d.ts +76 -0
  199. package/dist/features/structure-query.d.ts.map +1 -0
  200. package/dist/features/structure-query.js +245 -0
  201. package/dist/features/structure-query.js.map +1 -0
  202. package/dist/features/structure.d.ts +12 -67
  203. package/dist/features/structure.d.ts.map +1 -1
  204. package/dist/features/structure.js +188 -244
  205. package/dist/features/structure.js.map +1 -1
  206. package/dist/features/triage.js +2 -2
  207. package/dist/features/triage.js.map +1 -1
  208. package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
  209. package/dist/graph/algorithms/leiden/adapter.js +2 -9
  210. package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
  211. package/dist/graph/classifiers/roles.d.ts +5 -1
  212. package/dist/graph/classifiers/roles.d.ts.map +1 -1
  213. package/dist/graph/classifiers/roles.js +20 -12
  214. package/dist/graph/classifiers/roles.js.map +1 -1
  215. package/dist/index.d.ts +1 -0
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js.map +1 -1
  218. package/dist/infrastructure/config.d.ts.map +1 -1
  219. package/dist/infrastructure/config.js +12 -11
  220. package/dist/infrastructure/config.js.map +1 -1
  221. package/dist/infrastructure/native.d.ts.map +1 -1
  222. package/dist/infrastructure/native.js +7 -3
  223. package/dist/infrastructure/native.js.map +1 -1
  224. package/dist/infrastructure/registry.d.ts.map +1 -1
  225. package/dist/infrastructure/registry.js +1 -1
  226. package/dist/infrastructure/registry.js.map +1 -1
  227. package/dist/infrastructure/update-check.js +3 -3
  228. package/dist/infrastructure/update-check.js.map +1 -1
  229. package/dist/mcp/server.d.ts.map +1 -1
  230. package/dist/mcp/server.js +2 -8
  231. package/dist/mcp/server.js.map +1 -1
  232. package/dist/mcp/tool-registry.d.ts.map +1 -1
  233. package/dist/mcp/tool-registry.js +9 -4
  234. package/dist/mcp/tool-registry.js.map +1 -1
  235. package/dist/mcp/tools/audit.js +1 -1
  236. package/dist/mcp/tools/audit.js.map +1 -1
  237. package/dist/mcp/tools/cfg.js +1 -1
  238. package/dist/mcp/tools/cfg.js.map +1 -1
  239. package/dist/mcp/tools/check.js +2 -2
  240. package/dist/mcp/tools/check.js.map +1 -1
  241. package/dist/mcp/tools/dataflow.js +2 -2
  242. package/dist/mcp/tools/dataflow.js.map +1 -1
  243. package/dist/mcp/tools/export-graph.js +1 -1
  244. package/dist/mcp/tools/export-graph.js.map +1 -1
  245. package/dist/mcp/tools/index.d.ts.map +1 -1
  246. package/dist/mcp/tools/index.js.map +1 -1
  247. package/dist/mcp/tools/path.d.ts +1 -0
  248. package/dist/mcp/tools/path.d.ts.map +1 -1
  249. package/dist/mcp/tools/path.js +9 -0
  250. package/dist/mcp/tools/path.js.map +1 -1
  251. package/dist/mcp/tools/query.js +1 -1
  252. package/dist/mcp/tools/query.js.map +1 -1
  253. package/dist/mcp/tools/semantic-search.js +1 -1
  254. package/dist/mcp/tools/semantic-search.js.map +1 -1
  255. package/dist/mcp/tools/sequence.js +1 -1
  256. package/dist/mcp/tools/sequence.js.map +1 -1
  257. package/dist/mcp/tools/symbol-children.js +1 -1
  258. package/dist/mcp/tools/symbol-children.js.map +1 -1
  259. package/dist/mcp/tools/triage.js +1 -1
  260. package/dist/mcp/tools/triage.js.map +1 -1
  261. package/dist/presentation/audit.d.ts.map +1 -1
  262. package/dist/presentation/audit.js +0 -1
  263. package/dist/presentation/audit.js.map +1 -1
  264. package/dist/presentation/diff-impact-mermaid.d.ts +11 -0
  265. package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -0
  266. package/dist/presentation/diff-impact-mermaid.js +105 -0
  267. package/dist/presentation/diff-impact-mermaid.js.map +1 -0
  268. package/dist/presentation/flow.d.ts.map +1 -1
  269. package/dist/presentation/flow.js +0 -2
  270. package/dist/presentation/flow.js.map +1 -1
  271. package/dist/presentation/manifesto.d.ts.map +1 -1
  272. package/dist/presentation/manifesto.js +0 -1
  273. package/dist/presentation/manifesto.js.map +1 -1
  274. package/dist/presentation/queries-cli/inspect.d.ts.map +1 -1
  275. package/dist/presentation/queries-cli/inspect.js.map +1 -1
  276. package/dist/presentation/queries-cli/path.d.ts.map +1 -1
  277. package/dist/presentation/queries-cli/path.js +45 -1
  278. package/dist/presentation/queries-cli/path.js.map +1 -1
  279. package/dist/presentation/result-formatter.d.ts.map +1 -1
  280. package/dist/presentation/result-formatter.js +1 -3
  281. package/dist/presentation/result-formatter.js.map +1 -1
  282. package/dist/presentation/sequence.d.ts.map +1 -1
  283. package/dist/presentation/sequence.js +0 -1
  284. package/dist/presentation/sequence.js.map +1 -1
  285. package/dist/presentation/structure.d.ts.map +1 -1
  286. package/dist/presentation/structure.js.map +1 -1
  287. package/dist/presentation/triage.d.ts.map +1 -1
  288. package/dist/presentation/triage.js +0 -1
  289. package/dist/presentation/triage.js.map +1 -1
  290. package/dist/shared/constants.d.ts +9 -3
  291. package/dist/shared/constants.d.ts.map +1 -1
  292. package/dist/shared/constants.js +6 -3
  293. package/dist/shared/constants.js.map +1 -1
  294. package/dist/shared/errors.d.ts +2 -0
  295. package/dist/shared/errors.d.ts.map +1 -1
  296. package/dist/shared/errors.js +4 -0
  297. package/dist/shared/errors.js.map +1 -1
  298. package/dist/shared/version.d.ts +2 -0
  299. package/dist/shared/version.d.ts.map +1 -0
  300. package/dist/shared/version.js +5 -0
  301. package/dist/shared/version.js.map +1 -0
  302. package/dist/types.d.ts +2 -2
  303. package/dist/types.d.ts.map +1 -1
  304. package/package.json +8 -7
  305. package/src/ast-analysis/engine.ts +3 -9
  306. package/src/ast-analysis/shared.ts +0 -1
  307. package/src/ast-analysis/visitors/cfg-conditionals.ts +227 -0
  308. package/src/ast-analysis/visitors/cfg-loops.ts +136 -0
  309. package/src/ast-analysis/visitors/cfg-shared.ts +196 -0
  310. package/src/ast-analysis/visitors/cfg-try-catch.ts +142 -0
  311. package/src/ast-analysis/visitors/cfg-visitor.ts +34 -655
  312. package/src/ast-analysis/visitors/complexity-visitor.ts +0 -1
  313. package/src/ast-analysis/visitors/dataflow-visitor.ts +0 -1
  314. package/src/cli/commands/batch.ts +4 -3
  315. package/src/cli/commands/branch-compare.ts +1 -1
  316. package/src/cli/commands/build.ts +1 -1
  317. package/src/cli/commands/info.ts +1 -2
  318. package/src/cli/commands/path.ts +7 -2
  319. package/src/cli/commands/plot.ts +2 -2
  320. package/src/cli/commands/watch.ts +1 -1
  321. package/src/cli/index.ts +2 -2
  322. package/src/cli/shared/open-graph.ts +2 -2
  323. package/src/cli/types.ts +1 -1
  324. package/src/cli.ts +2 -3
  325. package/src/db/connection.ts +97 -13
  326. package/src/db/index.ts +2 -0
  327. package/src/db/migrations.ts +7 -0
  328. package/src/domain/analysis/brief.ts +0 -1
  329. package/src/domain/analysis/context.ts +2 -6
  330. package/src/domain/analysis/dependencies.ts +165 -0
  331. package/src/domain/analysis/diff-impact.ts +354 -0
  332. package/src/domain/analysis/exports.ts +0 -2
  333. package/src/domain/analysis/fn-impact.ts +241 -0
  334. package/src/domain/analysis/impact.ts +8 -718
  335. package/src/domain/analysis/module-map.ts +1 -5
  336. package/src/domain/graph/builder/context.ts +2 -2
  337. package/src/domain/graph/builder/helpers.ts +14 -11
  338. package/src/domain/graph/builder/incremental.ts +33 -28
  339. package/src/domain/graph/builder/pipeline.ts +8 -0
  340. package/src/domain/graph/builder/stages/build-edges.ts +17 -4
  341. package/src/domain/graph/builder/stages/build-structure.ts +205 -76
  342. package/src/domain/graph/builder/stages/detect-changes.ts +11 -12
  343. package/src/domain/graph/builder/stages/finalize.ts +100 -81
  344. package/src/domain/graph/builder/stages/insert-nodes.ts +12 -8
  345. package/src/domain/graph/builder/stages/resolve-imports.ts +75 -10
  346. package/src/domain/graph/cycles.ts +2 -2
  347. package/src/domain/graph/resolve.ts +14 -8
  348. package/src/domain/graph/watcher.ts +2 -4
  349. package/src/domain/parser.ts +11 -13
  350. package/src/domain/queries.ts +2 -2
  351. package/src/domain/search/generator.ts +3 -4
  352. package/src/extractors/csharp.ts +2 -2
  353. package/src/extractors/go.ts +2 -2
  354. package/src/extractors/helpers.ts +6 -0
  355. package/src/extractors/javascript.ts +58 -61
  356. package/src/extractors/php.ts +2 -2
  357. package/src/extractors/python.ts +2 -2
  358. package/src/extractors/rust.ts +2 -2
  359. package/src/features/audit.ts +1 -2
  360. package/src/features/branch-compare.ts +3 -9
  361. package/src/features/cfg.ts +2 -4
  362. package/src/features/cochange.ts +4 -4
  363. package/src/features/communities.ts +4 -4
  364. package/src/features/complexity-query.ts +370 -0
  365. package/src/features/complexity.ts +6 -365
  366. package/src/features/dataflow.ts +48 -70
  367. package/src/features/export.ts +12 -16
  368. package/src/features/flow.ts +0 -1
  369. package/src/features/graph-enrichment.ts +1 -3
  370. package/src/features/manifesto.ts +8 -8
  371. package/src/features/snapshot.ts +1 -2
  372. package/src/features/structure-query.ts +387 -0
  373. package/src/features/structure.ts +231 -376
  374. package/src/features/triage.ts +2 -2
  375. package/src/graph/algorithms/leiden/adapter.ts +2 -9
  376. package/src/graph/classifiers/roles.ts +22 -13
  377. package/src/index.ts +1 -0
  378. package/src/infrastructure/config.ts +12 -13
  379. package/src/infrastructure/native.ts +7 -3
  380. package/src/infrastructure/registry.ts +1 -1
  381. package/src/infrastructure/update-check.ts +3 -3
  382. package/src/mcp/server.ts +2 -10
  383. package/src/mcp/tool-registry.ts +11 -4
  384. package/src/mcp/tools/audit.ts +1 -1
  385. package/src/mcp/tools/cfg.ts +1 -1
  386. package/src/mcp/tools/check.ts +2 -2
  387. package/src/mcp/tools/dataflow.ts +2 -2
  388. package/src/mcp/tools/export-graph.ts +1 -1
  389. package/src/mcp/tools/index.ts +0 -1
  390. package/src/mcp/tools/path.ts +10 -0
  391. package/src/mcp/tools/query.ts +1 -1
  392. package/src/mcp/tools/semantic-search.ts +1 -1
  393. package/src/mcp/tools/sequence.ts +1 -1
  394. package/src/mcp/tools/symbol-children.ts +1 -1
  395. package/src/mcp/tools/triage.ts +1 -1
  396. package/src/presentation/audit.ts +0 -1
  397. package/src/presentation/diff-impact-mermaid.ts +127 -0
  398. package/src/presentation/flow.ts +0 -2
  399. package/src/presentation/manifesto.ts +0 -1
  400. package/src/presentation/queries-cli/inspect.ts +0 -1
  401. package/src/presentation/queries-cli/path.ts +71 -1
  402. package/src/presentation/result-formatter.ts +0 -1
  403. package/src/presentation/sequence.ts +0 -1
  404. package/src/presentation/structure.ts +0 -12
  405. package/src/presentation/triage.ts +0 -1
  406. package/src/shared/constants.ts +33 -19
  407. package/src/shared/errors.ts +5 -0
  408. package/src/shared/version.ts +10 -0
  409. package/src/types.ts +4 -10
  410. package/src/vendor.d.ts +0 -39
@@ -50,18 +50,11 @@ function taAdd(a: Float64Array, i: number, v: number): void {
50
50
  a[i] = taGet(a, i) + v;
51
51
  }
52
52
 
53
- function taSub(a: Float64Array, i: number, v: number): void {
54
- a[i] = taGet(a, i) - v;
55
- }
56
-
57
53
  export function makeGraphAdapter(graph: CodeGraph, opts: GraphAdapterOptions = {}): GraphAdapter {
58
54
  const linkWeight: (attrs: EdgeAttrs) => number =
59
- opts.linkWeight ||
60
- // biome-ignore lint/complexity/useLiteralKeys: index signature requires bracket access
61
- ((attrs) => (attrs && typeof attrs['weight'] === 'number' ? attrs['weight'] : 1));
55
+ opts.linkWeight || ((attrs) => (attrs && typeof attrs.weight === 'number' ? attrs.weight : 1));
62
56
  const nodeSize: (attrs: NodeAttrs) => number =
63
- // biome-ignore lint/complexity/useLiteralKeys: index signature requires bracket access
64
- opts.nodeSize || ((attrs) => (attrs && typeof attrs['size'] === 'number' ? attrs['size'] : 1));
57
+ opts.nodeSize || ((attrs) => (attrs && typeof attrs.size === 'number' ? attrs.size : 1));
65
58
  const directed: boolean = !!opts.directed;
66
59
  const baseNodeIds: string[] | undefined = opts.baseNodeIds;
67
60
 
@@ -58,7 +58,7 @@ function classifyDeadSubRole(node: ClassifiableNode): DeadSubRole {
58
58
 
59
59
  // ── Helpers ────────────────────────────────────────────────────────
60
60
 
61
- function median(sorted: number[]): number {
61
+ export function median(sorted: number[]): number {
62
62
  if (sorted.length === 0) return 0;
63
63
  const mid = Math.floor(sorted.length / 2);
64
64
  return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;
@@ -79,20 +79,29 @@ export interface RoleClassificationNode {
79
79
  /**
80
80
  * Classify nodes into architectural roles based on fan-in/fan-out metrics.
81
81
  */
82
- export function classifyRoles(nodes: RoleClassificationNode[]): Map<string, Role> {
82
+ export function classifyRoles(
83
+ nodes: RoleClassificationNode[],
84
+ medianOverrides?: { fanIn: number; fanOut: number },
85
+ ): Map<string, Role> {
83
86
  if (nodes.length === 0) return new Map();
84
87
 
85
- const nonZeroFanIn = nodes
86
- .filter((n) => n.fanIn > 0)
87
- .map((n) => n.fanIn)
88
- .sort((a, b) => a - b);
89
- const nonZeroFanOut = nodes
90
- .filter((n) => n.fanOut > 0)
91
- .map((n) => n.fanOut)
92
- .sort((a, b) => a - b);
93
-
94
- const medFanIn = median(nonZeroFanIn);
95
- const medFanOut = median(nonZeroFanOut);
88
+ let medFanIn: number;
89
+ let medFanOut: number;
90
+ if (medianOverrides) {
91
+ medFanIn = medianOverrides.fanIn;
92
+ medFanOut = medianOverrides.fanOut;
93
+ } else {
94
+ const nonZeroFanIn = nodes
95
+ .filter((n) => n.fanIn > 0)
96
+ .map((n) => n.fanIn)
97
+ .sort((a, b) => a - b);
98
+ const nonZeroFanOut = nodes
99
+ .filter((n) => n.fanOut > 0)
100
+ .map((n) => n.fanOut)
101
+ .sort((a, b) => a - b);
102
+ medFanIn = median(nonZeroFanIn);
103
+ medFanOut = median(nonZeroFanOut);
104
+ }
96
105
 
97
106
  const result = new Map<string, Role>();
98
107
 
package/src/index.ts CHANGED
@@ -53,6 +53,7 @@ export { sequenceData } from './features/sequence.js';
53
53
  export { hotspotsData, moduleBoundariesData, structureData } from './features/structure.js';
54
54
  export { triageData } from './features/triage.js';
55
55
  export { loadConfig } from './infrastructure/config.js';
56
+ export type { ArrayCompatSet } from './shared/constants.js';
56
57
  export { EXTENSIONS, IGNORE_DIRS } from './shared/constants.js';
57
58
  export {
58
59
  AnalysisError,
@@ -1,6 +1,7 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
+ import { toErrorMessage } from '../shared/errors.js';
4
5
  import type { CodegraphConfig } from '../types.js';
5
6
  import { debug, warn } from './logger.js';
6
7
 
@@ -170,11 +171,9 @@ export function loadConfig(cwd?: string): CodegraphConfig {
170
171
  debug(`Loaded config from ${filePath}`);
171
172
  const merged = mergeConfig(DEFAULTS as unknown as Record<string, unknown>, config);
172
173
  if ('excludeTests' in config && !(config.query && 'excludeTests' in config.query)) {
173
- (merged['query'] as Record<string, unknown>)['excludeTests'] = Boolean(
174
- config.excludeTests,
175
- );
174
+ (merged.query as Record<string, unknown>).excludeTests = Boolean(config.excludeTests);
176
175
  }
177
- delete merged['excludeTests'];
176
+ delete merged.excludeTests;
178
177
  const result = resolveSecrets(applyEnvOverrides(merged as unknown as CodegraphConfig));
179
178
  _configCache.set(cwd, structuredClone(result));
180
179
  return result;
@@ -227,7 +226,7 @@ export function resolveSecrets(config: CodegraphConfig): CodegraphConfig {
227
226
  stdio: ['ignore', 'pipe', 'pipe'],
228
227
  }).trim();
229
228
  if (result) {
230
- (config.llm as Record<string, unknown>)['apiKey'] = result;
229
+ (config.llm as Record<string, unknown>).apiKey = result;
231
230
  }
232
231
  } catch (err: unknown) {
233
232
  warn(`apiKeyCommand failed: ${(err as Error).message}`);
@@ -310,8 +309,8 @@ function resolveWorkspaceEntry(pkgDir: string): string | null {
310
309
  const candidate = path.resolve(pkgDir, idx);
311
310
  if (fs.existsSync(candidate)) return candidate;
312
311
  }
313
- } catch {
314
- /* ignore */
312
+ } catch (e) {
313
+ debug(`resolveWorkspaceEntry: package.json probe failed for ${pkgDir}: ${toErrorMessage(e)}`);
315
314
  }
316
315
  return null;
317
316
  }
@@ -344,8 +343,8 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
344
343
  }
345
344
  }
346
345
  }
347
- } catch {
348
- /* ignore */
346
+ } catch (e) {
347
+ debug(`detectWorkspaces: failed to parse pnpm-workspace.yaml: ${toErrorMessage(e)}`);
349
348
  }
350
349
  }
351
350
 
@@ -363,8 +362,8 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
363
362
  // Yarn classic format: { packages: [...], nohoist: [...] }
364
363
  patterns.push(...ws.packages);
365
364
  }
366
- } catch {
367
- /* ignore */
365
+ } catch (e) {
366
+ debug(`detectWorkspaces: failed to parse package.json workspaces: ${toErrorMessage(e)}`);
368
367
  }
369
368
  }
370
369
  }
@@ -379,8 +378,8 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
379
378
  if (Array.isArray(lerna.packages)) {
380
379
  patterns.push(...lerna.packages);
381
380
  }
382
- } catch {
383
- /* ignore */
381
+ } catch (e) {
382
+ debug(`detectWorkspaces: failed to parse lerna.json: ${toErrorMessage(e)}`);
384
383
  }
385
384
  }
386
385
  }
@@ -8,8 +8,9 @@
8
8
 
9
9
  import { createRequire } from 'node:module';
10
10
  import os from 'node:os';
11
- import { EngineError } from '../shared/errors.js';
11
+ import { EngineError, toErrorMessage } from '../shared/errors.js';
12
12
  import type { NativeAddon } from '../types.js';
13
+ import { debug } from './logger.js';
13
14
 
14
15
  let _cached: NativeAddon | null | undefined; // undefined = not yet tried, null = failed, NativeAddon = module
15
16
  let _loadError: Error | null = null;
@@ -26,7 +27,9 @@ function detectLibc(): 'gnu' | 'musl' {
26
27
  if (files.some((f: string) => f.startsWith('ld-musl-') && f.endsWith('.so.1'))) {
27
28
  return 'musl';
28
29
  }
29
- } catch {}
30
+ } catch (e) {
31
+ debug(`detectLibc: failed to read /lib: ${toErrorMessage(e)}`);
32
+ }
30
33
  return 'gnu';
31
34
  }
32
35
 
@@ -92,7 +95,8 @@ export function getNativePackageVersion(): string | null {
92
95
  try {
93
96
  const pkgJson = _require(`${pkg}/package.json`) as { version?: string };
94
97
  return pkgJson.version || null;
95
- } catch {
98
+ } catch (e) {
99
+ debug(`getNativePackageVersion: failed to read package.json for ${pkg}: ${toErrorMessage(e)}`);
96
100
  return null;
97
101
  }
98
102
  }
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import { debug, warn } from './logger.js';
5
5
 
6
6
  export const REGISTRY_PATH: string =
7
- process.env['CODEGRAPH_REGISTRY_PATH'] || path.join(os.homedir(), '.codegraph', 'registry.json');
7
+ process.env.CODEGRAPH_REGISTRY_PATH || path.join(os.homedir(), '.codegraph', 'registry.json');
8
8
 
9
9
  /** Default TTL: entries not accessed within 30 days are pruned. */
10
10
  export const DEFAULT_TTL_DAYS = 30;
@@ -4,7 +4,7 @@ import os from 'node:os';
4
4
  import path from 'node:path';
5
5
 
6
6
  const CACHE_PATH: string =
7
- process.env['CODEGRAPH_UPDATE_CACHE_PATH'] ||
7
+ process.env.CODEGRAPH_UPDATE_CACHE_PATH ||
8
8
  path.join(os.homedir(), '.codegraph', 'update-check.json');
9
9
 
10
10
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
@@ -120,8 +120,8 @@ export async function checkForUpdates(
120
120
  options: CheckForUpdatesOptions = {},
121
121
  ): Promise<UpdateResult | null> {
122
122
  // Suppress in non-interactive / CI contexts
123
- if (process.env['CI']) return null;
124
- if (process.env['NO_UPDATE_CHECK']) return null;
123
+ if (process.env.CI) return null;
124
+ if (process.env.NO_UPDATE_CHECK) return null;
125
125
  if (!process.stderr.isTTY) return null;
126
126
  if (currentVersion.includes('-')) return null;
127
127
 
package/src/mcp/server.ts CHANGED
@@ -24,14 +24,11 @@ import { TOOL_HANDLERS } from './tools/index.js';
24
24
  * Because tests use vi.resetModules(), this module-level variable resets
25
25
  * on each re-import — but the process-level flag on `process` persists.
26
26
  */
27
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK server type is lazy-loaded
28
27
  let _activeServer: any = null;
29
28
 
30
29
  export interface McpToolContext {
31
30
  dbPath: string | undefined;
32
- // biome-ignore lint/suspicious/noExplicitAny: lazy-loaded queries module
33
31
  getQueries(): Promise<any>;
34
- // biome-ignore lint/suspicious/noExplicitAny: lazy-loaded better-sqlite3 constructor
35
32
  getDatabase(): any;
36
33
  findDbPath: typeof findDbPath;
37
34
  allowedRepos: string[] | undefined;
@@ -140,7 +137,6 @@ export async function startMCPServer(
140
137
  // and cached for subsequent calls.
141
138
  const { getQueries, getDatabase } = createLazyLoaders();
142
139
 
143
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK types are lazy-loaded and untyped
144
140
  const server = new (Server as any)(
145
141
  { name: 'codegraph', version: PKG_VERSION },
146
142
  { capabilities: { tools: {} } },
@@ -150,7 +146,6 @@ export async function startMCPServer(
150
146
  tools: buildToolList(multiRepo),
151
147
  }));
152
148
 
153
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK request type is dynamic
154
149
  server.setRequestHandler(CallToolRequestSchema, async (request: any) => {
155
150
  const { name, arguments: args } = request.params;
156
151
  try {
@@ -185,7 +180,6 @@ export async function startMCPServer(
185
180
  }
186
181
  });
187
182
 
188
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK types are lazy-loaded and untyped
189
183
  const transport = new (StdioServerTransport as any)();
190
184
 
191
185
  // Graceful shutdown — when the client disconnects (e.g. session clear),
@@ -197,10 +191,8 @@ export async function startMCPServer(
197
191
  // Register handlers once per process to avoid listener accumulation.
198
192
  // Use a process-level flag so it survives vi.resetModules() in tests.
199
193
  const g = globalThis as Record<string, unknown>;
200
- // biome-ignore lint/complexity/useLiteralKeys: bracket notation required by TS noPropertyAccessFromIndexSignature
201
- if (!g['__codegraph_shutdown_installed']) {
202
- // biome-ignore lint/complexity/useLiteralKeys: bracket notation required by TS noPropertyAccessFromIndexSignature
203
- g['__codegraph_shutdown_installed'] = true;
194
+ if (!g.__codegraph_shutdown_installed) {
195
+ g.__codegraph_shutdown_installed = true;
204
196
 
205
197
  const shutdown = async () => {
206
198
  try {
@@ -77,20 +77,27 @@ const BASE_TOOLS: ToolSchema[] = [
77
77
  },
78
78
  {
79
79
  name: 'path',
80
- description: 'Find shortest path between two symbols in the dependency graph',
80
+ description:
81
+ 'Find shortest path between two symbols (or files with file_mode) in the dependency graph',
81
82
  inputSchema: {
82
83
  type: 'object',
83
84
  properties: {
84
- from: { type: 'string', description: 'Source symbol name' },
85
- to: { type: 'string', description: 'Target symbol name' },
85
+ from: { type: 'string', description: 'Source symbol name (or file path with file_mode)' },
86
+ to: { type: 'string', description: 'Target symbol name (or file path with file_mode)' },
86
87
  depth: { type: 'number', description: 'Max traversal depth (default: 10)' },
87
88
  edge_kinds: {
88
89
  type: 'array',
89
90
  items: { type: 'string', enum: EVERY_EDGE_KIND },
90
- description: 'Edge kinds to follow (default: ["calls"])',
91
+ description:
92
+ 'Edge kinds to follow (default: ["calls"] for symbols, ["imports","imports-type"] for files)',
91
93
  },
92
94
  from_file: { type: 'string', description: 'Disambiguate source by file' },
93
95
  to_file: { type: 'string', description: 'Disambiguate target by file' },
96
+ file_mode: {
97
+ type: 'boolean',
98
+ description: 'Treat from/to as file paths and find file-to-file shortest path',
99
+ default: false,
100
+ },
94
101
  no_tests: { type: 'boolean', description: 'Exclude test files', default: false },
95
102
  },
96
103
  required: ['from', 'to'],
@@ -19,7 +19,7 @@ export async function handler(args: AuditArgs, ctx: McpToolContext): Promise<unk
19
19
  const { explainData } = await ctx.getQueries();
20
20
  return explainData(args.target, ctx.dbPath, {
21
21
  noTests: args.no_tests,
22
- limit: Math.min(args.limit ?? MCP_DEFAULTS['explain'] ?? 100, MCP_MAX_LIMIT),
22
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.explain ?? 100, MCP_MAX_LIMIT),
23
23
  offset: effectiveOffset(args),
24
24
  });
25
25
  }
@@ -19,7 +19,7 @@ export async function handler(args: CfgArgs, ctx: McpToolContext): Promise<unkno
19
19
  file: args.file,
20
20
  kind: args.kind,
21
21
  noTests: args.no_tests,
22
- limit: Math.min(args.limit ?? MCP_DEFAULTS['query'] ?? 100, ctx.MCP_MAX_LIMIT),
22
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.query ?? 100, ctx.MCP_MAX_LIMIT),
23
23
  offset: effectiveOffset(args),
24
24
  });
25
25
  if (args.format === 'dot') {
@@ -28,7 +28,7 @@ export async function handler(args: CheckArgs, ctx: McpToolContext): Promise<unk
28
28
  file: args.file,
29
29
  noTests: args.no_tests,
30
30
  kind: args.kind,
31
- limit: Math.min(args.limit ?? MCP_DEFAULTS['manifesto'] ?? 100, MCP_MAX_LIMIT),
31
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.manifesto ?? 100, MCP_MAX_LIMIT),
32
32
  offset: effectiveOffset(args),
33
33
  });
34
34
  }
@@ -51,7 +51,7 @@ export async function handler(args: CheckArgs, ctx: McpToolContext): Promise<unk
51
51
  file: args.file,
52
52
  noTests: args.no_tests,
53
53
  kind: args.kind,
54
- limit: Math.min(args.limit ?? MCP_DEFAULTS['manifesto'] ?? 100, MCP_MAX_LIMIT),
54
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.manifesto ?? 100, MCP_MAX_LIMIT),
55
55
  offset: effectiveOffset(args),
56
56
  });
57
57
  return { check: checkResult, manifesto: manifestoResult };
@@ -23,7 +23,7 @@ export async function handler(args: DataflowArgs, ctx: McpToolContext): Promise<
23
23
  file: args.file,
24
24
  kind: args.kind,
25
25
  noTests: args.no_tests,
26
- limit: Math.min(args.limit ?? MCP_DEFAULTS['fn_impact'] ?? 100, ctx.MCP_MAX_LIMIT),
26
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.fn_impact ?? 100, ctx.MCP_MAX_LIMIT),
27
27
  offset: effectiveOffset(args),
28
28
  });
29
29
  }
@@ -32,7 +32,7 @@ export async function handler(args: DataflowArgs, ctx: McpToolContext): Promise<
32
32
  file: args.file,
33
33
  kind: args.kind,
34
34
  noTests: args.no_tests,
35
- limit: Math.min(args.limit ?? MCP_DEFAULTS['query'] ?? 100, ctx.MCP_MAX_LIMIT),
35
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.query ?? 100, ctx.MCP_MAX_LIMIT),
36
36
  offset: effectiveOffset(args),
37
37
  });
38
38
  }
@@ -19,7 +19,7 @@ export async function handler(args: ExportGraphArgs, ctx: McpToolContext): Promi
19
19
  const fileLevel = args.file_level !== false;
20
20
  const exportLimit = args.limit
21
21
  ? Math.min(args.limit, MCP_MAX_LIMIT)
22
- : (MCP_DEFAULTS['export_graph'] ?? 500);
22
+ : (MCP_DEFAULTS.export_graph ?? 500);
23
23
 
24
24
  let result: unknown;
25
25
  try {
@@ -6,7 +6,6 @@ import type { McpToolContext } from '../server.js';
6
6
 
7
7
  export interface McpToolHandler {
8
8
  name: string;
9
- // biome-ignore lint/suspicious/noExplicitAny: tool arg types vary per handler
10
9
  handler(args: any, ctx: McpToolContext): Promise<unknown>;
11
10
  }
12
11
 
@@ -10,9 +10,19 @@ interface PathArgs {
10
10
  from_file?: string;
11
11
  to_file?: string;
12
12
  no_tests?: boolean;
13
+ file_mode?: boolean;
13
14
  }
14
15
 
15
16
  export async function handler(args: PathArgs, ctx: McpToolContext): Promise<unknown> {
17
+ if (args.file_mode) {
18
+ const { filePathData } = await ctx.getQueries();
19
+ return filePathData(args.from, args.to, ctx.dbPath, {
20
+ maxDepth: args.depth ?? 10,
21
+ edgeKinds: args.edge_kinds,
22
+ reverse: false,
23
+ noTests: args.no_tests,
24
+ });
25
+ }
16
26
  const { pathData } = await ctx.getQueries();
17
27
  return pathData(args.from, args.to, ctx.dbPath, {
18
28
  maxDepth: args.depth ?? 10,
@@ -41,7 +41,7 @@ export async function handler(args: QueryArgs, ctx: McpToolContext): Promise<unk
41
41
  file: args.file,
42
42
  kind: args.kind,
43
43
  noTests: args.no_tests,
44
- limit: Math.min(args.limit ?? MCP_DEFAULTS['query'] ?? 100, ctx.MCP_MAX_LIMIT),
44
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.query ?? 100, ctx.MCP_MAX_LIMIT),
45
45
  offset: effectiveOffset(args),
46
46
  });
47
47
  }
@@ -14,7 +14,7 @@ interface SemanticSearchArgs {
14
14
  export async function handler(args: SemanticSearchArgs, ctx: McpToolContext): Promise<unknown> {
15
15
  const mode = args.mode || 'hybrid';
16
16
  const searchOpts = {
17
- limit: Math.min(args.limit ?? MCP_DEFAULTS['semantic_search'] ?? 100, ctx.MCP_MAX_LIMIT),
17
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.semantic_search ?? 100, ctx.MCP_MAX_LIMIT),
18
18
  offset: effectiveOffset(args),
19
19
  minScore: args.min_score,
20
20
  };
@@ -23,7 +23,7 @@ export async function handler(args: SequenceArgs, ctx: McpToolContext): Promise<
23
23
  kind: args.kind,
24
24
  dataflow: args.dataflow,
25
25
  noTests: args.no_tests,
26
- limit: Math.min(args.limit ?? MCP_DEFAULTS['execution_flow'] ?? 100, ctx.MCP_MAX_LIMIT),
26
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.execution_flow ?? 100, ctx.MCP_MAX_LIMIT),
27
27
  offset: effectiveOffset(args),
28
28
  });
29
29
  return args.format === 'json' ? seqResult : { text: sequenceToMermaid(seqResult), ...seqResult };
@@ -18,7 +18,7 @@ export async function handler(args: SymbolChildrenArgs, ctx: McpToolContext): Pr
18
18
  file: args.file,
19
19
  kind: args.kind,
20
20
  noTests: args.no_tests,
21
- limit: Math.min(args.limit ?? MCP_DEFAULTS['context'] ?? 100, ctx.MCP_MAX_LIMIT),
21
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.context ?? 100, ctx.MCP_MAX_LIMIT),
22
22
  offset: effectiveOffset(args),
23
23
  });
24
24
  }
@@ -30,7 +30,7 @@ export async function handler(args: TriageArgs, ctx: McpToolContext): Promise<un
30
30
  return hotspotsData(ctx.dbPath, {
31
31
  metric,
32
32
  level: args.level,
33
- limit: Math.min(args.limit ?? MCP_DEFAULTS['hotspots'] ?? 100, MCP_MAX_LIMIT),
33
+ limit: Math.min(args.limit ?? MCP_DEFAULTS.hotspots ?? 100, MCP_MAX_LIMIT),
34
34
  offset: effectiveOffset(args),
35
35
  noTests: args.no_tests,
36
36
  });
@@ -20,7 +20,6 @@ export function audit(
20
20
  customDbPath: string | undefined,
21
21
  opts: AuditOpts = {},
22
22
  ): void {
23
- // biome-ignore lint/suspicious/noExplicitAny: audit data shape is dynamic
24
23
  const data: any = auditData(target, customDbPath, opts as any);
25
24
 
26
25
  if (outputResult(data, null, opts)) return;
@@ -0,0 +1,127 @@
1
+ import { diffImpactData } from '../domain/analysis/diff-impact.js';
2
+
3
+ export function diffImpactMermaid(
4
+ customDbPath: string,
5
+ opts: {
6
+ noTests?: boolean;
7
+ depth?: number;
8
+ staged?: boolean;
9
+ ref?: string;
10
+ includeImplementors?: boolean;
11
+ limit?: number;
12
+ offset?: number;
13
+ config?: any;
14
+ } = {},
15
+ ): string {
16
+ const data: any = diffImpactData(customDbPath, opts);
17
+ if ('error' in data) return data.error as string;
18
+ if (data.changedFiles === 0 || data.affectedFunctions.length === 0) {
19
+ return 'flowchart TB\n none["No impacted functions detected"]';
20
+ }
21
+
22
+ const newFileSet = new Set(data.newFiles || []);
23
+ const lines = ['flowchart TB'];
24
+
25
+ // Assign stable Mermaid node IDs
26
+ let nodeCounter = 0;
27
+ const nodeIdMap = new Map<string, string>();
28
+ const nodeLabels = new Map<string, string>();
29
+ function nodeId(key: string, label?: string): string {
30
+ if (!nodeIdMap.has(key)) {
31
+ nodeIdMap.set(key, `n${nodeCounter++}`);
32
+ if (label) nodeLabels.set(key, label);
33
+ }
34
+ return nodeIdMap.get(key)!;
35
+ }
36
+
37
+ // Register all nodes (changed functions + their callers)
38
+ for (const fn of data.affectedFunctions) {
39
+ nodeId(`${fn.file}::${fn.name}:${fn.line}`, fn.name);
40
+ for (const callers of Object.values(fn.levels || {})) {
41
+ for (const c of callers as Array<{ name: string; file: string; line: number }>) {
42
+ nodeId(`${c.file}::${c.name}:${c.line}`, c.name);
43
+ }
44
+ }
45
+ }
46
+
47
+ // Collect all edges and determine blast radius
48
+ const allEdges = new Set<string>();
49
+ const edgeFromNodes = new Set<string>();
50
+ const edgeToNodes = new Set<string>();
51
+ const changedKeys = new Set<string>();
52
+
53
+ for (const fn of data.affectedFunctions) {
54
+ changedKeys.add(`${fn.file}::${fn.name}:${fn.line}`);
55
+ for (const edge of fn.edges || []) {
56
+ const edgeKey = `${edge.from}|${edge.to}`;
57
+ if (!allEdges.has(edgeKey)) {
58
+ allEdges.add(edgeKey);
59
+ edgeFromNodes.add(edge.from);
60
+ edgeToNodes.add(edge.to);
61
+ }
62
+ }
63
+ }
64
+
65
+ // Blast radius: caller nodes that are never a source (leaf nodes of the impact tree)
66
+ const blastRadiusKeys = new Set<string>();
67
+ for (const key of edgeToNodes) {
68
+ if (!edgeFromNodes.has(key) && !changedKeys.has(key)) {
69
+ blastRadiusKeys.add(key);
70
+ }
71
+ }
72
+
73
+ // Intermediate callers: not changed, not blast radius
74
+ const intermediateKeys = new Set<string>();
75
+ for (const key of edgeToNodes) {
76
+ if (!changedKeys.has(key) && !blastRadiusKeys.has(key)) {
77
+ intermediateKeys.add(key);
78
+ }
79
+ }
80
+
81
+ // Group changed functions by file
82
+ const fileGroups = new Map<string, typeof data.affectedFunctions>();
83
+ for (const fn of data.affectedFunctions) {
84
+ if (!fileGroups.has(fn.file)) fileGroups.set(fn.file, []);
85
+ fileGroups.get(fn.file)!.push(fn);
86
+ }
87
+
88
+ // Emit changed-file subgraphs
89
+ let sgCounter = 0;
90
+ for (const [file, fns] of fileGroups) {
91
+ const isNew = newFileSet.has(file);
92
+ const tag = isNew ? 'new' : 'modified';
93
+ const sgId = `sg${sgCounter++}`;
94
+ lines.push(` subgraph ${sgId}["${file} **(${tag})**"]`);
95
+ for (const fn of fns) {
96
+ const key = `${fn.file}::${fn.name}:${fn.line}`;
97
+ lines.push(` ${nodeIdMap.get(key)}["${fn.name}"]`);
98
+ }
99
+ lines.push(' end');
100
+ const style = isNew ? 'fill:#e8f5e9,stroke:#4caf50' : 'fill:#fff3e0,stroke:#ff9800';
101
+ lines.push(` style ${sgId} ${style}`);
102
+ }
103
+
104
+ // Emit intermediate caller nodes (outside subgraphs)
105
+ for (const key of intermediateKeys) {
106
+ lines.push(` ${nodeIdMap.get(key)}["${nodeLabels.get(key)}"]`);
107
+ }
108
+
109
+ // Emit blast radius subgraph
110
+ if (blastRadiusKeys.size > 0) {
111
+ const sgId = `sg${sgCounter++}`;
112
+ lines.push(` subgraph ${sgId}["Callers **(blast radius)**"]`);
113
+ for (const key of blastRadiusKeys) {
114
+ lines.push(` ${nodeIdMap.get(key)}["${nodeLabels.get(key)}"]`);
115
+ }
116
+ lines.push(' end');
117
+ lines.push(` style ${sgId} fill:#f3e5f5,stroke:#9c27b0`);
118
+ }
119
+
120
+ // Emit edges (impact flows from changed fn toward callers)
121
+ for (const edgeKey of allEdges) {
122
+ const [from, to] = edgeKey.split('|') as [string, string];
123
+ lines.push(` ${nodeIdMap.get(from)} --> ${nodeIdMap.get(to)}`);
124
+ }
125
+
126
+ return lines.join('\n');
127
+ }
@@ -26,7 +26,6 @@ export function flow(
26
26
  noTests: opts.noTests,
27
27
  limit: opts.limit,
28
28
  offset: opts.offset,
29
- // biome-ignore lint/suspicious/noExplicitAny: dynamic shape from listEntryPointsData
30
29
  }) as any;
31
30
  if (outputResult(data, 'entries', opts)) return;
32
31
  if (data.count === 0) {
@@ -56,7 +55,6 @@ export function flow(
56
55
  return;
57
56
  }
58
57
 
59
- // biome-ignore lint/suspicious/noExplicitAny: dynamic shape from flowData
60
58
  const data = flowData(name, dbPath, opts) as any;
61
59
  if (outputResult(data, 'steps', opts)) return;
62
60
 
@@ -23,7 +23,6 @@ interface ManifestoViolationRow {
23
23
  }
24
24
 
25
25
  export function manifesto(customDbPath: string | undefined, opts: ManifestoOpts = {}): void {
26
- // biome-ignore lint/suspicious/noExplicitAny: dynamic shape from manifestoData
27
26
  const data = manifestoData(customDbPath, opts as any) as any;
28
27
 
29
28
  if (outputResult(data, 'violations', opts)) {
@@ -163,7 +163,6 @@ interface FunctionExplainResult extends SymbolRef {
163
163
 
164
164
  interface ExplainData {
165
165
  kind: 'file' | 'function';
166
- // biome-ignore lint/suspicious/noExplicitAny: union of file/function results
167
166
  results: any[];
168
167
  }
169
168