@optave/codegraph 3.4.0 → 3.5.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 (453) hide show
  1. package/README.md +23 -22
  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/rules/javascript.d.ts.map +1 -1
  6. package/dist/ast-analysis/rules/javascript.js +1 -0
  7. package/dist/ast-analysis/rules/javascript.js.map +1 -1
  8. package/dist/ast-analysis/shared.d.ts.map +1 -1
  9. package/dist/ast-analysis/shared.js +0 -1
  10. package/dist/ast-analysis/shared.js.map +1 -1
  11. package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
  12. package/dist/ast-analysis/visitors/ast-store-visitor.js +103 -35
  13. package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
  14. package/dist/ast-analysis/visitors/cfg-conditionals.d.ts +5 -0
  15. package/dist/ast-analysis/visitors/cfg-conditionals.d.ts.map +1 -0
  16. package/dist/ast-analysis/visitors/cfg-conditionals.js +166 -0
  17. package/dist/ast-analysis/visitors/cfg-conditionals.js.map +1 -0
  18. package/dist/ast-analysis/visitors/cfg-loops.d.ts +7 -0
  19. package/dist/ast-analysis/visitors/cfg-loops.d.ts.map +1 -0
  20. package/dist/ast-analysis/visitors/cfg-loops.js +73 -0
  21. package/dist/ast-analysis/visitors/cfg-loops.js.map +1 -0
  22. package/dist/ast-analysis/visitors/cfg-shared.d.ts +56 -0
  23. package/dist/ast-analysis/visitors/cfg-shared.d.ts.map +1 -0
  24. package/dist/ast-analysis/visitors/cfg-shared.js +107 -0
  25. package/dist/ast-analysis/visitors/cfg-shared.js.map +1 -0
  26. package/dist/ast-analysis/visitors/cfg-try-catch.d.ts +4 -0
  27. package/dist/ast-analysis/visitors/cfg-try-catch.d.ts.map +1 -0
  28. package/dist/ast-analysis/visitors/cfg-try-catch.js +100 -0
  29. package/dist/ast-analysis/visitors/cfg-try-catch.js.map +1 -0
  30. package/dist/ast-analysis/visitors/cfg-visitor.d.ts +2 -2
  31. package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -1
  32. package/dist/ast-analysis/visitors/cfg-visitor.js +11 -445
  33. package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -1
  34. package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
  35. package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
  36. package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
  37. package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
  38. package/dist/cli/commands/batch.d.ts.map +1 -1
  39. package/dist/cli/commands/batch.js +4 -3
  40. package/dist/cli/commands/batch.js.map +1 -1
  41. package/dist/cli/commands/branch-compare.js +1 -1
  42. package/dist/cli/commands/branch-compare.js.map +1 -1
  43. package/dist/cli/commands/build.js +1 -1
  44. package/dist/cli/commands/build.js.map +1 -1
  45. package/dist/cli/commands/info.d.ts.map +1 -1
  46. package/dist/cli/commands/info.js +1 -2
  47. package/dist/cli/commands/info.js.map +1 -1
  48. package/dist/cli/commands/path.d.ts.map +1 -1
  49. package/dist/cli/commands/path.js +7 -2
  50. package/dist/cli/commands/path.js.map +1 -1
  51. package/dist/cli/commands/plot.d.ts.map +1 -1
  52. package/dist/cli/commands/plot.js +2 -2
  53. package/dist/cli/commands/plot.js.map +1 -1
  54. package/dist/cli/commands/watch.js +1 -1
  55. package/dist/cli/commands/watch.js.map +1 -1
  56. package/dist/cli/index.js +2 -2
  57. package/dist/cli/index.js.map +1 -1
  58. package/dist/cli/shared/open-graph.d.ts +2 -2
  59. package/dist/cli/shared/open-graph.d.ts.map +1 -1
  60. package/dist/cli/shared/open-graph.js.map +1 -1
  61. package/dist/cli/types.d.ts +1 -1
  62. package/dist/cli/types.d.ts.map +1 -1
  63. package/dist/cli.js +2 -3
  64. package/dist/cli.js.map +1 -1
  65. package/dist/db/better-sqlite3.d.ts +3 -0
  66. package/dist/db/better-sqlite3.d.ts.map +1 -0
  67. package/dist/db/better-sqlite3.js +19 -0
  68. package/dist/db/better-sqlite3.js.map +1 -0
  69. package/dist/db/connection.d.ts +30 -2
  70. package/dist/db/connection.d.ts.map +1 -1
  71. package/dist/db/connection.js +167 -4
  72. package/dist/db/connection.js.map +1 -1
  73. package/dist/db/index.d.ts +2 -2
  74. package/dist/db/index.d.ts.map +1 -1
  75. package/dist/db/index.js +1 -1
  76. package/dist/db/index.js.map +1 -1
  77. package/dist/db/migrations.d.ts.map +1 -1
  78. package/dist/db/migrations.js +9 -0
  79. package/dist/db/migrations.js.map +1 -1
  80. package/dist/db/query-builder.d.ts +5 -5
  81. package/dist/db/query-builder.d.ts.map +1 -1
  82. package/dist/db/query-builder.js +20 -4
  83. package/dist/db/query-builder.js.map +1 -1
  84. package/dist/db/repository/index.d.ts +1 -0
  85. package/dist/db/repository/index.d.ts.map +1 -1
  86. package/dist/db/repository/index.js +1 -0
  87. package/dist/db/repository/index.js.map +1 -1
  88. package/dist/db/repository/native-repository.d.ts +58 -0
  89. package/dist/db/repository/native-repository.d.ts.map +1 -0
  90. package/dist/db/repository/native-repository.js +261 -0
  91. package/dist/db/repository/native-repository.js.map +1 -0
  92. package/dist/db/repository/nodes.d.ts +4 -4
  93. package/dist/db/repository/nodes.d.ts.map +1 -1
  94. package/dist/db/repository/nodes.js +6 -6
  95. package/dist/db/repository/nodes.js.map +1 -1
  96. package/dist/domain/analysis/brief.d.ts.map +1 -1
  97. package/dist/domain/analysis/brief.js +1 -3
  98. package/dist/domain/analysis/brief.js.map +1 -1
  99. package/dist/domain/analysis/context.d.ts.map +1 -1
  100. package/dist/domain/analysis/context.js +2 -4
  101. package/dist/domain/analysis/context.js.map +1 -1
  102. package/dist/domain/analysis/dependencies.d.ts +49 -0
  103. package/dist/domain/analysis/dependencies.d.ts.map +1 -1
  104. package/dist/domain/analysis/dependencies.js +145 -0
  105. package/dist/domain/analysis/dependencies.js.map +1 -1
  106. package/dist/domain/analysis/diff-impact.d.ts +76 -0
  107. package/dist/domain/analysis/diff-impact.d.ts.map +1 -0
  108. package/dist/domain/analysis/diff-impact.js +282 -0
  109. package/dist/domain/analysis/diff-impact.js.map +1 -0
  110. package/dist/domain/analysis/exports.d.ts.map +1 -1
  111. package/dist/domain/analysis/exports.js +0 -1
  112. package/dist/domain/analysis/exports.js.map +1 -1
  113. package/dist/domain/analysis/fn-impact.d.ts +66 -0
  114. package/dist/domain/analysis/fn-impact.d.ts.map +1 -0
  115. package/dist/domain/analysis/fn-impact.js +189 -0
  116. package/dist/domain/analysis/fn-impact.js.map +1 -0
  117. package/dist/domain/analysis/impact.d.ts +8 -148
  118. package/dist/domain/analysis/impact.d.ts.map +1 -1
  119. package/dist/domain/analysis/impact.js +8 -568
  120. package/dist/domain/analysis/impact.js.map +1 -1
  121. package/dist/domain/analysis/module-map.d.ts.map +1 -1
  122. package/dist/domain/analysis/module-map.js +1 -3
  123. package/dist/domain/analysis/module-map.js.map +1 -1
  124. package/dist/domain/graph/builder/context.d.ts +3 -3
  125. package/dist/domain/graph/builder/context.d.ts.map +1 -1
  126. package/dist/domain/graph/builder/context.js +1 -0
  127. package/dist/domain/graph/builder/context.js.map +1 -1
  128. package/dist/domain/graph/builder/helpers.d.ts +4 -5
  129. package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
  130. package/dist/domain/graph/builder/helpers.js +1 -2
  131. package/dist/domain/graph/builder/helpers.js.map +1 -1
  132. package/dist/domain/graph/builder/incremental.d.ts +2 -3
  133. package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
  134. package/dist/domain/graph/builder/incremental.js.map +1 -1
  135. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
  136. package/dist/domain/graph/builder/pipeline.js +34 -6
  137. package/dist/domain/graph/builder/pipeline.js.map +1 -1
  138. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
  139. package/dist/domain/graph/builder/stages/build-edges.js +113 -15
  140. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
  141. package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
  142. package/dist/domain/graph/builder/stages/build-structure.js +186 -62
  143. package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
  144. package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
  145. package/dist/domain/graph/builder/stages/collect-files.js +71 -7
  146. package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
  147. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
  148. package/dist/domain/graph/builder/stages/detect-changes.js +42 -20
  149. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
  150. package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
  151. package/dist/domain/graph/builder/stages/finalize.js +111 -64
  152. package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
  153. package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
  154. package/dist/domain/graph/builder/stages/insert-nodes.js +104 -9
  155. package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
  156. package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
  157. package/dist/domain/graph/builder/stages/resolve-imports.js +58 -11
  158. package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
  159. package/dist/domain/graph/cycles.js +2 -2
  160. package/dist/domain/graph/cycles.js.map +1 -1
  161. package/dist/domain/graph/resolve.d.ts.map +1 -1
  162. package/dist/domain/graph/resolve.js +10 -8
  163. package/dist/domain/graph/resolve.js.map +1 -1
  164. package/dist/domain/graph/watcher.d.ts.map +1 -1
  165. package/dist/domain/graph/watcher.js +1 -3
  166. package/dist/domain/graph/watcher.js.map +1 -1
  167. package/dist/domain/parser.d.ts.map +1 -1
  168. package/dist/domain/parser.js +12 -12
  169. package/dist/domain/parser.js.map +1 -1
  170. package/dist/domain/queries.d.ts +3 -2
  171. package/dist/domain/queries.d.ts.map +1 -1
  172. package/dist/domain/queries.js +3 -2
  173. package/dist/domain/queries.js.map +1 -1
  174. package/dist/domain/search/generator.d.ts.map +1 -1
  175. package/dist/domain/search/generator.js.map +1 -1
  176. package/dist/extractors/csharp.js +2 -2
  177. package/dist/extractors/csharp.js.map +1 -1
  178. package/dist/extractors/go.js +2 -2
  179. package/dist/extractors/go.js.map +1 -1
  180. package/dist/extractors/helpers.d.ts +5 -0
  181. package/dist/extractors/helpers.d.ts.map +1 -1
  182. package/dist/extractors/helpers.js +5 -0
  183. package/dist/extractors/helpers.js.map +1 -1
  184. package/dist/extractors/javascript.js +111 -98
  185. package/dist/extractors/javascript.js.map +1 -1
  186. package/dist/extractors/php.js +2 -2
  187. package/dist/extractors/php.js.map +1 -1
  188. package/dist/extractors/python.js +2 -2
  189. package/dist/extractors/python.js.map +1 -1
  190. package/dist/extractors/rust.js +4 -3
  191. package/dist/extractors/rust.js.map +1 -1
  192. package/dist/features/ast.d.ts +14 -1
  193. package/dist/features/ast.d.ts.map +1 -1
  194. package/dist/features/ast.js +38 -1
  195. package/dist/features/ast.js.map +1 -1
  196. package/dist/features/audit.d.ts.map +1 -1
  197. package/dist/features/audit.js +1 -2
  198. package/dist/features/audit.js.map +1 -1
  199. package/dist/features/branch-compare.d.ts.map +1 -1
  200. package/dist/features/branch-compare.js +5 -4
  201. package/dist/features/branch-compare.js.map +1 -1
  202. package/dist/features/cfg.d.ts.map +1 -1
  203. package/dist/features/cfg.js +2 -4
  204. package/dist/features/cfg.js.map +1 -1
  205. package/dist/features/cochange.js +4 -4
  206. package/dist/features/cochange.js.map +1 -1
  207. package/dist/features/communities.js +4 -4
  208. package/dist/features/communities.js.map +1 -1
  209. package/dist/features/complexity-query.d.ts +37 -0
  210. package/dist/features/complexity-query.d.ts.map +1 -0
  211. package/dist/features/complexity-query.js +263 -0
  212. package/dist/features/complexity-query.js.map +1 -0
  213. package/dist/features/complexity.d.ts +2 -30
  214. package/dist/features/complexity.d.ts.map +1 -1
  215. package/dist/features/complexity.js +7 -261
  216. package/dist/features/complexity.js.map +1 -1
  217. package/dist/features/dataflow.d.ts.map +1 -1
  218. package/dist/features/dataflow.js +8 -24
  219. package/dist/features/dataflow.js.map +1 -1
  220. package/dist/features/export.d.ts +7 -8
  221. package/dist/features/export.d.ts.map +1 -1
  222. package/dist/features/export.js.map +1 -1
  223. package/dist/features/flow.d.ts.map +1 -1
  224. package/dist/features/flow.js.map +1 -1
  225. package/dist/features/graph-enrichment.d.ts.map +1 -1
  226. package/dist/features/graph-enrichment.js +1 -3
  227. package/dist/features/graph-enrichment.js.map +1 -1
  228. package/dist/features/manifesto.js +8 -8
  229. package/dist/features/manifesto.js.map +1 -1
  230. package/dist/features/snapshot.js +2 -2
  231. package/dist/features/snapshot.js.map +1 -1
  232. package/dist/features/structure-query.d.ts +76 -0
  233. package/dist/features/structure-query.d.ts.map +1 -0
  234. package/dist/features/structure-query.js +245 -0
  235. package/dist/features/structure-query.js.map +1 -0
  236. package/dist/features/structure.d.ts +12 -67
  237. package/dist/features/structure.d.ts.map +1 -1
  238. package/dist/features/structure.js +188 -244
  239. package/dist/features/structure.js.map +1 -1
  240. package/dist/features/triage.js +2 -2
  241. package/dist/features/triage.js.map +1 -1
  242. package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
  243. package/dist/graph/algorithms/leiden/adapter.js +2 -9
  244. package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
  245. package/dist/graph/classifiers/roles.d.ts +5 -1
  246. package/dist/graph/classifiers/roles.d.ts.map +1 -1
  247. package/dist/graph/classifiers/roles.js +20 -12
  248. package/dist/graph/classifiers/roles.js.map +1 -1
  249. package/dist/index.d.ts +1 -0
  250. package/dist/index.d.ts.map +1 -1
  251. package/dist/index.js.map +1 -1
  252. package/dist/infrastructure/config.d.ts.map +1 -1
  253. package/dist/infrastructure/config.js +12 -11
  254. package/dist/infrastructure/config.js.map +1 -1
  255. package/dist/infrastructure/native.d.ts.map +1 -1
  256. package/dist/infrastructure/native.js +7 -3
  257. package/dist/infrastructure/native.js.map +1 -1
  258. package/dist/infrastructure/registry.d.ts.map +1 -1
  259. package/dist/infrastructure/registry.js +1 -1
  260. package/dist/infrastructure/registry.js.map +1 -1
  261. package/dist/infrastructure/update-check.js +3 -3
  262. package/dist/infrastructure/update-check.js.map +1 -1
  263. package/dist/mcp/server.d.ts.map +1 -1
  264. package/dist/mcp/server.js +4 -17
  265. package/dist/mcp/server.js.map +1 -1
  266. package/dist/mcp/tool-registry.d.ts.map +1 -1
  267. package/dist/mcp/tool-registry.js +9 -4
  268. package/dist/mcp/tool-registry.js.map +1 -1
  269. package/dist/mcp/tools/audit.js +1 -1
  270. package/dist/mcp/tools/audit.js.map +1 -1
  271. package/dist/mcp/tools/cfg.js +1 -1
  272. package/dist/mcp/tools/cfg.js.map +1 -1
  273. package/dist/mcp/tools/check.js +2 -2
  274. package/dist/mcp/tools/check.js.map +1 -1
  275. package/dist/mcp/tools/dataflow.js +2 -2
  276. package/dist/mcp/tools/dataflow.js.map +1 -1
  277. package/dist/mcp/tools/export-graph.js +1 -1
  278. package/dist/mcp/tools/export-graph.js.map +1 -1
  279. package/dist/mcp/tools/index.d.ts.map +1 -1
  280. package/dist/mcp/tools/index.js.map +1 -1
  281. package/dist/mcp/tools/path.d.ts +1 -0
  282. package/dist/mcp/tools/path.d.ts.map +1 -1
  283. package/dist/mcp/tools/path.js +9 -0
  284. package/dist/mcp/tools/path.js.map +1 -1
  285. package/dist/mcp/tools/query.js +1 -1
  286. package/dist/mcp/tools/query.js.map +1 -1
  287. package/dist/mcp/tools/semantic-search.js +1 -1
  288. package/dist/mcp/tools/semantic-search.js.map +1 -1
  289. package/dist/mcp/tools/sequence.js +1 -1
  290. package/dist/mcp/tools/sequence.js.map +1 -1
  291. package/dist/mcp/tools/symbol-children.js +1 -1
  292. package/dist/mcp/tools/symbol-children.js.map +1 -1
  293. package/dist/mcp/tools/triage.js +1 -1
  294. package/dist/mcp/tools/triage.js.map +1 -1
  295. package/dist/presentation/audit.d.ts.map +1 -1
  296. package/dist/presentation/audit.js +0 -1
  297. package/dist/presentation/audit.js.map +1 -1
  298. package/dist/presentation/diff-impact-mermaid.d.ts +11 -0
  299. package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -0
  300. package/dist/presentation/diff-impact-mermaid.js +105 -0
  301. package/dist/presentation/diff-impact-mermaid.js.map +1 -0
  302. package/dist/presentation/flow.d.ts.map +1 -1
  303. package/dist/presentation/flow.js +0 -2
  304. package/dist/presentation/flow.js.map +1 -1
  305. package/dist/presentation/manifesto.d.ts.map +1 -1
  306. package/dist/presentation/manifesto.js +0 -1
  307. package/dist/presentation/manifesto.js.map +1 -1
  308. package/dist/presentation/queries-cli/inspect.d.ts.map +1 -1
  309. package/dist/presentation/queries-cli/inspect.js.map +1 -1
  310. package/dist/presentation/queries-cli/path.d.ts.map +1 -1
  311. package/dist/presentation/queries-cli/path.js +45 -1
  312. package/dist/presentation/queries-cli/path.js.map +1 -1
  313. package/dist/presentation/result-formatter.d.ts.map +1 -1
  314. package/dist/presentation/result-formatter.js +1 -3
  315. package/dist/presentation/result-formatter.js.map +1 -1
  316. package/dist/presentation/sequence.d.ts.map +1 -1
  317. package/dist/presentation/sequence.js +0 -1
  318. package/dist/presentation/sequence.js.map +1 -1
  319. package/dist/presentation/structure.d.ts.map +1 -1
  320. package/dist/presentation/structure.js.map +1 -1
  321. package/dist/presentation/triage.d.ts.map +1 -1
  322. package/dist/presentation/triage.js +0 -1
  323. package/dist/presentation/triage.js.map +1 -1
  324. package/dist/shared/constants.d.ts +9 -3
  325. package/dist/shared/constants.d.ts.map +1 -1
  326. package/dist/shared/constants.js +6 -3
  327. package/dist/shared/constants.js.map +1 -1
  328. package/dist/shared/errors.d.ts +2 -0
  329. package/dist/shared/errors.d.ts.map +1 -1
  330. package/dist/shared/errors.js +4 -0
  331. package/dist/shared/errors.js.map +1 -1
  332. package/dist/shared/version.d.ts +2 -0
  333. package/dist/shared/version.d.ts.map +1 -0
  334. package/dist/shared/version.js +5 -0
  335. package/dist/shared/version.js.map +1 -0
  336. package/dist/types.d.ts +230 -2
  337. package/dist/types.d.ts.map +1 -1
  338. package/package.json +62 -11
  339. package/src/ast-analysis/engine.ts +3 -9
  340. package/src/ast-analysis/rules/javascript.ts +1 -0
  341. package/src/ast-analysis/shared.ts +0 -1
  342. package/src/ast-analysis/visitors/ast-store-visitor.ts +102 -33
  343. package/src/ast-analysis/visitors/cfg-conditionals.ts +227 -0
  344. package/src/ast-analysis/visitors/cfg-loops.ts +136 -0
  345. package/src/ast-analysis/visitors/cfg-shared.ts +196 -0
  346. package/src/ast-analysis/visitors/cfg-try-catch.ts +142 -0
  347. package/src/ast-analysis/visitors/cfg-visitor.ts +34 -655
  348. package/src/ast-analysis/visitors/complexity-visitor.ts +0 -1
  349. package/src/ast-analysis/visitors/dataflow-visitor.ts +0 -1
  350. package/src/cli/commands/batch.ts +4 -3
  351. package/src/cli/commands/branch-compare.ts +1 -1
  352. package/src/cli/commands/build.ts +1 -1
  353. package/src/cli/commands/info.ts +1 -2
  354. package/src/cli/commands/path.ts +7 -2
  355. package/src/cli/commands/plot.ts +2 -2
  356. package/src/cli/commands/watch.ts +1 -1
  357. package/src/cli/index.ts +2 -2
  358. package/src/cli/shared/open-graph.ts +2 -2
  359. package/src/cli/types.ts +1 -1
  360. package/src/cli.ts +2 -3
  361. package/src/db/better-sqlite3.ts +20 -0
  362. package/src/db/connection.ts +191 -16
  363. package/src/db/index.ts +5 -1
  364. package/src/db/migrations.ts +9 -0
  365. package/src/db/query-builder.ts +30 -5
  366. package/src/db/repository/index.ts +1 -0
  367. package/src/db/repository/native-repository.ts +361 -0
  368. package/src/db/repository/nodes.ts +7 -3
  369. package/src/domain/analysis/brief.ts +0 -1
  370. package/src/domain/analysis/context.ts +2 -6
  371. package/src/domain/analysis/dependencies.ts +165 -0
  372. package/src/domain/analysis/diff-impact.ts +354 -0
  373. package/src/domain/analysis/exports.ts +0 -2
  374. package/src/domain/analysis/fn-impact.ts +241 -0
  375. package/src/domain/analysis/impact.ts +8 -718
  376. package/src/domain/analysis/module-map.ts +1 -5
  377. package/src/domain/graph/builder/context.ts +4 -2
  378. package/src/domain/graph/builder/helpers.ts +14 -11
  379. package/src/domain/graph/builder/incremental.ts +33 -28
  380. package/src/domain/graph/builder/pipeline.ts +37 -5
  381. package/src/domain/graph/builder/stages/build-edges.ts +131 -20
  382. package/src/domain/graph/builder/stages/build-structure.ts +245 -80
  383. package/src/domain/graph/builder/stages/collect-files.ts +84 -7
  384. package/src/domain/graph/builder/stages/detect-changes.ts +49 -32
  385. package/src/domain/graph/builder/stages/finalize.ts +132 -84
  386. package/src/domain/graph/builder/stages/insert-nodes.ts +141 -18
  387. package/src/domain/graph/builder/stages/resolve-imports.ts +75 -10
  388. package/src/domain/graph/cycles.ts +2 -2
  389. package/src/domain/graph/resolve.ts +14 -8
  390. package/src/domain/graph/watcher.ts +2 -4
  391. package/src/domain/parser.ts +12 -13
  392. package/src/domain/queries.ts +2 -2
  393. package/src/domain/search/generator.ts +3 -4
  394. package/src/extractors/csharp.ts +2 -2
  395. package/src/extractors/go.ts +2 -2
  396. package/src/extractors/helpers.ts +6 -0
  397. package/src/extractors/javascript.ts +112 -97
  398. package/src/extractors/php.ts +2 -2
  399. package/src/extractors/python.ts +2 -2
  400. package/src/extractors/rust.ts +4 -3
  401. package/src/features/ast.ts +66 -1
  402. package/src/features/audit.ts +1 -2
  403. package/src/features/branch-compare.ts +6 -10
  404. package/src/features/cfg.ts +2 -4
  405. package/src/features/cochange.ts +4 -4
  406. package/src/features/communities.ts +4 -4
  407. package/src/features/complexity-query.ts +370 -0
  408. package/src/features/complexity.ts +6 -365
  409. package/src/features/dataflow.ts +48 -70
  410. package/src/features/export.ts +12 -16
  411. package/src/features/flow.ts +0 -1
  412. package/src/features/graph-enrichment.ts +1 -3
  413. package/src/features/manifesto.ts +8 -8
  414. package/src/features/snapshot.ts +3 -3
  415. package/src/features/structure-query.ts +387 -0
  416. package/src/features/structure.ts +231 -376
  417. package/src/features/triage.ts +2 -2
  418. package/src/graph/algorithms/leiden/adapter.ts +2 -9
  419. package/src/graph/classifiers/roles.ts +22 -13
  420. package/src/index.ts +1 -0
  421. package/src/infrastructure/config.ts +12 -13
  422. package/src/infrastructure/native.ts +7 -3
  423. package/src/infrastructure/registry.ts +1 -1
  424. package/src/infrastructure/update-check.ts +3 -3
  425. package/src/mcp/server.ts +4 -20
  426. package/src/mcp/tool-registry.ts +11 -4
  427. package/src/mcp/tools/audit.ts +1 -1
  428. package/src/mcp/tools/cfg.ts +1 -1
  429. package/src/mcp/tools/check.ts +2 -2
  430. package/src/mcp/tools/dataflow.ts +2 -2
  431. package/src/mcp/tools/export-graph.ts +1 -1
  432. package/src/mcp/tools/index.ts +0 -1
  433. package/src/mcp/tools/path.ts +10 -0
  434. package/src/mcp/tools/query.ts +1 -1
  435. package/src/mcp/tools/semantic-search.ts +1 -1
  436. package/src/mcp/tools/sequence.ts +1 -1
  437. package/src/mcp/tools/symbol-children.ts +1 -1
  438. package/src/mcp/tools/triage.ts +1 -1
  439. package/src/presentation/audit.ts +0 -1
  440. package/src/presentation/diff-impact-mermaid.ts +127 -0
  441. package/src/presentation/flow.ts +0 -2
  442. package/src/presentation/manifesto.ts +0 -1
  443. package/src/presentation/queries-cli/inspect.ts +0 -1
  444. package/src/presentation/queries-cli/path.ts +71 -1
  445. package/src/presentation/result-formatter.ts +0 -1
  446. package/src/presentation/sequence.ts +0 -1
  447. package/src/presentation/structure.ts +0 -12
  448. package/src/presentation/triage.ts +0 -1
  449. package/src/shared/constants.ts +33 -19
  450. package/src/shared/errors.ts +5 -0
  451. package/src/shared/version.ts +10 -0
  452. package/src/types.ts +277 -10
  453. 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
@@ -10,6 +10,7 @@ import { createRequire } from 'node:module';
10
10
  const require = createRequire(import.meta.url);
11
11
  const { version: PKG_VERSION } = require('../../package.json') as { version: string };
12
12
 
13
+ import { getDatabase } from '../db/better-sqlite3.js';
13
14
  import { findDbPath } from '../db/index.js';
14
15
  import { loadConfig } from '../infrastructure/config.js';
15
16
  import { CodegraphError, ConfigError } from '../shared/errors.js';
@@ -24,14 +25,11 @@ import { TOOL_HANDLERS } from './tools/index.js';
24
25
  * Because tests use vi.resetModules(), this module-level variable resets
25
26
  * on each re-import — but the process-level flag on `process` persists.
26
27
  */
27
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK server type is lazy-loaded
28
28
  let _activeServer: any = null;
29
29
 
30
30
  export interface McpToolContext {
31
31
  dbPath: string | undefined;
32
- // biome-ignore lint/suspicious/noExplicitAny: lazy-loaded queries module
33
32
  getQueries(): Promise<any>;
34
- // biome-ignore lint/suspicious/noExplicitAny: lazy-loaded better-sqlite3 constructor
35
33
  getDatabase(): any;
36
34
  findDbPath: typeof findDbPath;
37
35
  allowedRepos: string[] | undefined;
@@ -67,22 +65,13 @@ async function loadMCPSdk(): Promise<{
67
65
 
68
66
  function createLazyLoaders(): {
69
67
  getQueries(): Promise<unknown>;
70
- getDatabase(): unknown;
71
68
  } {
72
69
  let _queries: unknown;
73
- let _Database: unknown;
74
70
  return {
75
71
  async getQueries(): Promise<unknown> {
76
72
  if (!_queries) _queries = await import('../domain/queries.js');
77
73
  return _queries;
78
74
  },
79
- getDatabase(): unknown {
80
- if (!_Database) {
81
- const require = createRequire(import.meta.url);
82
- _Database = require('better-sqlite3');
83
- }
84
- return _Database;
85
- },
86
75
  };
87
76
  }
88
77
 
@@ -138,9 +127,8 @@ export async function startMCPServer(
138
127
  // `initialize` request while heavy modules (queries, better-sqlite3)
139
128
  // are still loading. These are lazy-loaded on the first tool call
140
129
  // and cached for subsequent calls.
141
- const { getQueries, getDatabase } = createLazyLoaders();
130
+ const { getQueries } = createLazyLoaders();
142
131
 
143
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK types are lazy-loaded and untyped
144
132
  const server = new (Server as any)(
145
133
  { name: 'codegraph', version: PKG_VERSION },
146
134
  { capabilities: { tools: {} } },
@@ -150,7 +138,6 @@ export async function startMCPServer(
150
138
  tools: buildToolList(multiRepo),
151
139
  }));
152
140
 
153
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK request type is dynamic
154
141
  server.setRequestHandler(CallToolRequestSchema, async (request: any) => {
155
142
  const { name, arguments: args } = request.params;
156
143
  try {
@@ -185,7 +172,6 @@ export async function startMCPServer(
185
172
  }
186
173
  });
187
174
 
188
- // biome-ignore lint/suspicious/noExplicitAny: MCP SDK types are lazy-loaded and untyped
189
175
  const transport = new (StdioServerTransport as any)();
190
176
 
191
177
  // Graceful shutdown — when the client disconnects (e.g. session clear),
@@ -197,10 +183,8 @@ export async function startMCPServer(
197
183
  // Register handlers once per process to avoid listener accumulation.
198
184
  // Use a process-level flag so it survives vi.resetModules() in tests.
199
185
  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;
186
+ if (!g.__codegraph_shutdown_installed) {
187
+ g.__codegraph_shutdown_installed = true;
204
188
 
205
189
  const shutdown = async () => {
206
190
  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