@optave/codegraph 3.12.0 → 3.15.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 (524) hide show
  1. package/README.md +83 -46
  2. package/dist/ast-analysis/engine.d.ts.map +1 -1
  3. package/dist/ast-analysis/engine.js +38 -40
  4. package/dist/ast-analysis/engine.js.map +1 -1
  5. package/dist/ast-analysis/rules/b2.d.ts +7 -0
  6. package/dist/ast-analysis/rules/b2.d.ts.map +1 -0
  7. package/dist/ast-analysis/rules/b2.js +240 -0
  8. package/dist/ast-analysis/rules/b2.js.map +1 -0
  9. package/dist/ast-analysis/rules/b3.d.ts +6 -0
  10. package/dist/ast-analysis/rules/b3.d.ts.map +1 -0
  11. package/dist/ast-analysis/rules/b3.js +105 -0
  12. package/dist/ast-analysis/rules/b3.js.map +1 -0
  13. package/dist/ast-analysis/rules/b4.d.ts +9 -0
  14. package/dist/ast-analysis/rules/b4.d.ts.map +1 -0
  15. package/dist/ast-analysis/rules/b4.js +361 -0
  16. package/dist/ast-analysis/rules/b4.js.map +1 -0
  17. package/dist/ast-analysis/rules/b5.d.ts +4 -0
  18. package/dist/ast-analysis/rules/b5.d.ts.map +1 -0
  19. package/dist/ast-analysis/rules/b5.js +52 -0
  20. package/dist/ast-analysis/rules/b5.js.map +1 -0
  21. package/dist/ast-analysis/rules/c.d.ts +4 -0
  22. package/dist/ast-analysis/rules/c.d.ts.map +1 -0
  23. package/dist/ast-analysis/rules/c.js +143 -0
  24. package/dist/ast-analysis/rules/c.js.map +1 -0
  25. package/dist/ast-analysis/rules/index.d.ts.map +1 -1
  26. package/dist/ast-analysis/rules/index.js +34 -0
  27. package/dist/ast-analysis/rules/index.js.map +1 -1
  28. package/dist/ast-analysis/rules/javascript.d.ts.map +1 -1
  29. package/dist/ast-analysis/rules/javascript.js +3 -0
  30. package/dist/ast-analysis/rules/javascript.js.map +1 -1
  31. package/dist/ast-analysis/shared.d.ts.map +1 -1
  32. package/dist/ast-analysis/shared.js +2 -0
  33. package/dist/ast-analysis/shared.js.map +1 -1
  34. package/dist/ast-analysis/visitor-utils.d.ts +1 -0
  35. package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
  36. package/dist/ast-analysis/visitor-utils.js +5 -0
  37. package/dist/ast-analysis/visitor-utils.js.map +1 -1
  38. package/dist/ast-analysis/visitor.d.ts.map +1 -1
  39. package/dist/ast-analysis/visitor.js +60 -47
  40. package/dist/ast-analysis/visitor.js.map +1 -1
  41. package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -1
  42. package/dist/ast-analysis/visitors/cfg-visitor.js +126 -76
  43. package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -1
  44. package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
  45. package/dist/ast-analysis/visitors/complexity-visitor.js +27 -15
  46. package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
  47. package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
  48. package/dist/ast-analysis/visitors/dataflow-visitor.js +54 -21
  49. package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
  50. package/dist/cli/commands/audit.d.ts.map +1 -1
  51. package/dist/cli/commands/audit.js +2 -1
  52. package/dist/cli/commands/audit.js.map +1 -1
  53. package/dist/cli/commands/batch.d.ts.map +1 -1
  54. package/dist/cli/commands/batch.js +1 -0
  55. package/dist/cli/commands/batch.js.map +1 -1
  56. package/dist/cli/commands/build.d.ts.map +1 -1
  57. package/dist/cli/commands/build.js +6 -1
  58. package/dist/cli/commands/build.js.map +1 -1
  59. package/dist/cli/commands/config.d.ts +3 -0
  60. package/dist/cli/commands/config.d.ts.map +1 -0
  61. package/dist/cli/commands/config.js +275 -0
  62. package/dist/cli/commands/config.js.map +1 -0
  63. package/dist/cli/commands/roles.d.ts.map +1 -1
  64. package/dist/cli/commands/roles.js +6 -1
  65. package/dist/cli/commands/roles.js.map +1 -1
  66. package/dist/cli/commands/triage.js +1 -1
  67. package/dist/cli/commands/triage.js.map +1 -1
  68. package/dist/cli/index.d.ts.map +1 -1
  69. package/dist/cli/index.js +10 -0
  70. package/dist/cli/index.js.map +1 -1
  71. package/dist/cli/shared/options.d.ts +2 -1
  72. package/dist/cli/shared/options.d.ts.map +1 -1
  73. package/dist/cli/shared/options.js +11 -1
  74. package/dist/cli/shared/options.js.map +1 -1
  75. package/dist/cli/types.d.ts +2 -0
  76. package/dist/cli/types.d.ts.map +1 -1
  77. package/dist/db/better-sqlite3.d.ts +2 -1
  78. package/dist/db/better-sqlite3.d.ts.map +1 -1
  79. package/dist/db/better-sqlite3.js.map +1 -1
  80. package/dist/db/connection.d.ts +7 -1
  81. package/dist/db/connection.d.ts.map +1 -1
  82. package/dist/db/connection.js +20 -5
  83. package/dist/db/connection.js.map +1 -1
  84. package/dist/db/index.d.ts +1 -1
  85. package/dist/db/index.d.ts.map +1 -1
  86. package/dist/db/index.js +1 -1
  87. package/dist/db/index.js.map +1 -1
  88. package/dist/db/migrations.d.ts.map +1 -1
  89. package/dist/db/migrations.js +69 -1
  90. package/dist/db/migrations.js.map +1 -1
  91. package/dist/db/repository/build-stmts.d.ts.map +1 -1
  92. package/dist/db/repository/build-stmts.js +18 -0
  93. package/dist/db/repository/build-stmts.js.map +1 -1
  94. package/dist/db/repository/dataflow.d.ts +5 -0
  95. package/dist/db/repository/dataflow.d.ts.map +1 -1
  96. package/dist/db/repository/dataflow.js +14 -0
  97. package/dist/db/repository/dataflow.js.map +1 -1
  98. package/dist/db/repository/index.d.ts +1 -1
  99. package/dist/db/repository/index.d.ts.map +1 -1
  100. package/dist/db/repository/index.js +1 -1
  101. package/dist/db/repository/index.js.map +1 -1
  102. package/dist/db/repository/native-repository.d.ts.map +1 -1
  103. package/dist/db/repository/native-repository.js +47 -34
  104. package/dist/db/repository/native-repository.js.map +1 -1
  105. package/dist/domain/analysis/context.d.ts +2 -2
  106. package/dist/domain/analysis/dependencies.d.ts +2 -2
  107. package/dist/domain/analysis/diff-impact.d.ts +2 -2
  108. package/dist/domain/analysis/fn-impact.d.ts +3 -1
  109. package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
  110. package/dist/domain/analysis/fn-impact.js +4 -0
  111. package/dist/domain/analysis/fn-impact.js.map +1 -1
  112. package/dist/domain/analysis/implementations.d.ts +2 -2
  113. package/dist/domain/analysis/module-map.d.ts.map +1 -1
  114. package/dist/domain/analysis/module-map.js +32 -5
  115. package/dist/domain/analysis/module-map.js.map +1 -1
  116. package/dist/domain/analysis/roles.d.ts +7 -1
  117. package/dist/domain/analysis/roles.d.ts.map +1 -1
  118. package/dist/domain/analysis/roles.js +16 -0
  119. package/dist/domain/analysis/roles.js.map +1 -1
  120. package/dist/domain/analysis/symbol-lookup.d.ts +4 -4
  121. package/dist/domain/graph/builder/call-resolver.d.ts +29 -13
  122. package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
  123. package/dist/domain/graph/builder/call-resolver.js +125 -205
  124. package/dist/domain/graph/builder/call-resolver.js.map +1 -1
  125. package/dist/domain/graph/builder/cha.d.ts +9 -1
  126. package/dist/domain/graph/builder/cha.d.ts.map +1 -1
  127. package/dist/domain/graph/builder/cha.js +17 -2
  128. package/dist/domain/graph/builder/cha.js.map +1 -1
  129. package/dist/domain/graph/builder/context.d.ts +1 -0
  130. package/dist/domain/graph/builder/context.d.ts.map +1 -1
  131. package/dist/domain/graph/builder/context.js.map +1 -1
  132. package/dist/domain/graph/builder/helpers.d.ts +24 -1
  133. package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
  134. package/dist/domain/graph/builder/helpers.js +174 -65
  135. package/dist/domain/graph/builder/helpers.js.map +1 -1
  136. package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
  137. package/dist/domain/graph/builder/incremental.js +166 -97
  138. package/dist/domain/graph/builder/incremental.js.map +1 -1
  139. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
  140. package/dist/domain/graph/builder/pipeline.js +46 -5
  141. package/dist/domain/graph/builder/pipeline.js.map +1 -1
  142. package/dist/domain/graph/builder/stages/build-edges.d.ts +0 -2
  143. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
  144. package/dist/domain/graph/builder/stages/build-edges.js +554 -538
  145. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
  146. package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
  147. package/dist/domain/graph/builder/stages/collect-files.js +10 -7
  148. package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
  149. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
  150. package/dist/domain/graph/builder/stages/detect-changes.js +3 -2
  151. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
  152. package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
  153. package/dist/domain/graph/builder/stages/finalize.js +4 -0
  154. package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
  155. package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
  156. package/dist/domain/graph/builder/stages/native-orchestrator.js +952 -343
  157. package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
  158. package/dist/domain/graph/builder/stages/resolve-imports.js +1 -1
  159. package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
  160. package/dist/domain/graph/resolver/points-to.d.ts.map +1 -1
  161. package/dist/domain/graph/resolver/points-to.js +105 -57
  162. package/dist/domain/graph/resolver/points-to.js.map +1 -1
  163. package/dist/domain/graph/resolver/strategy.d.ts +61 -0
  164. package/dist/domain/graph/resolver/strategy.d.ts.map +1 -0
  165. package/dist/domain/graph/resolver/strategy.js +222 -0
  166. package/dist/domain/graph/resolver/strategy.js.map +1 -0
  167. package/dist/domain/graph/watcher.d.ts.map +1 -1
  168. package/dist/domain/graph/watcher.js +16 -9
  169. package/dist/domain/graph/watcher.js.map +1 -1
  170. package/dist/domain/parser.d.ts +16 -5
  171. package/dist/domain/parser.d.ts.map +1 -1
  172. package/dist/domain/parser.js +58 -17
  173. package/dist/domain/parser.js.map +1 -1
  174. package/dist/domain/queries.d.ts +1 -1
  175. package/dist/domain/queries.d.ts.map +1 -1
  176. package/dist/domain/queries.js +1 -1
  177. package/dist/domain/queries.js.map +1 -1
  178. package/dist/domain/wasm-worker-entry.js +13 -2
  179. package/dist/domain/wasm-worker-entry.js.map +1 -1
  180. package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
  181. package/dist/domain/wasm-worker-pool.js +26 -5
  182. package/dist/domain/wasm-worker-pool.js.map +1 -1
  183. package/dist/domain/wasm-worker-protocol.d.ts +8 -0
  184. package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
  185. package/dist/extractors/cpp.d.ts.map +1 -1
  186. package/dist/extractors/cpp.js +42 -1
  187. package/dist/extractors/cpp.js.map +1 -1
  188. package/dist/extractors/cuda.d.ts.map +1 -1
  189. package/dist/extractors/cuda.js +42 -1
  190. package/dist/extractors/cuda.js.map +1 -1
  191. package/dist/extractors/dart.js +48 -3
  192. package/dist/extractors/dart.js.map +1 -1
  193. package/dist/extractors/groovy.js +62 -3
  194. package/dist/extractors/groovy.js.map +1 -1
  195. package/dist/extractors/helpers.d.ts +15 -2
  196. package/dist/extractors/helpers.d.ts.map +1 -1
  197. package/dist/extractors/helpers.js +45 -1
  198. package/dist/extractors/helpers.js.map +1 -1
  199. package/dist/extractors/java.d.ts.map +1 -1
  200. package/dist/extractors/java.js +85 -8
  201. package/dist/extractors/java.js.map +1 -1
  202. package/dist/extractors/javascript.d.ts.map +1 -1
  203. package/dist/extractors/javascript.js +686 -169
  204. package/dist/extractors/javascript.js.map +1 -1
  205. package/dist/extractors/kotlin.js +58 -3
  206. package/dist/extractors/kotlin.js.map +1 -1
  207. package/dist/extractors/objc.js +25 -2
  208. package/dist/extractors/objc.js.map +1 -1
  209. package/dist/extractors/scala.js +62 -2
  210. package/dist/extractors/scala.js.map +1 -1
  211. package/dist/extractors/swift.js +52 -3
  212. package/dist/extractors/swift.js.map +1 -1
  213. package/dist/features/audit.js +26 -23
  214. package/dist/features/audit.js.map +1 -1
  215. package/dist/features/boundaries.d.ts.map +1 -1
  216. package/dist/features/boundaries.js +12 -9
  217. package/dist/features/boundaries.js.map +1 -1
  218. package/dist/features/cfg.d.ts.map +1 -1
  219. package/dist/features/cfg.js +25 -18
  220. package/dist/features/cfg.js.map +1 -1
  221. package/dist/features/check.d.ts.map +1 -1
  222. package/dist/features/check.js +18 -5
  223. package/dist/features/check.js.map +1 -1
  224. package/dist/features/communities.d.ts +4 -2
  225. package/dist/features/communities.d.ts.map +1 -1
  226. package/dist/features/communities.js +6 -4
  227. package/dist/features/communities.js.map +1 -1
  228. package/dist/features/dataflow.d.ts +60 -0
  229. package/dist/features/dataflow.d.ts.map +1 -1
  230. package/dist/features/dataflow.js +530 -6
  231. package/dist/features/dataflow.js.map +1 -1
  232. package/dist/features/manifesto.d.ts.map +1 -1
  233. package/dist/features/manifesto.js +59 -72
  234. package/dist/features/manifesto.js.map +1 -1
  235. package/dist/features/sequence.d.ts.map +1 -1
  236. package/dist/features/sequence.js +27 -22
  237. package/dist/features/sequence.js.map +1 -1
  238. package/dist/features/snapshot.d.ts.map +1 -1
  239. package/dist/features/snapshot.js +36 -28
  240. package/dist/features/snapshot.js.map +1 -1
  241. package/dist/features/structure-query.d.ts +1 -1
  242. package/dist/features/structure-query.d.ts.map +1 -1
  243. package/dist/features/structure-query.js +6 -6
  244. package/dist/features/structure-query.js.map +1 -1
  245. package/dist/features/structure.d.ts.map +1 -1
  246. package/dist/features/structure.js +150 -62
  247. package/dist/features/structure.js.map +1 -1
  248. package/dist/features/triage.d.ts.map +1 -1
  249. package/dist/features/triage.js +18 -11
  250. package/dist/features/triage.js.map +1 -1
  251. package/dist/graph/algorithms/bfs.d.ts +1 -1
  252. package/dist/graph/algorithms/bfs.d.ts.map +1 -1
  253. package/dist/graph/algorithms/bfs.js +14 -13
  254. package/dist/graph/algorithms/bfs.js.map +1 -1
  255. package/dist/graph/algorithms/tarjan.d.ts.map +1 -1
  256. package/dist/graph/algorithms/tarjan.js +5 -0
  257. package/dist/graph/algorithms/tarjan.js.map +1 -1
  258. package/dist/graph/builders/dependency.js +28 -22
  259. package/dist/graph/builders/dependency.js.map +1 -1
  260. package/dist/graph/classifiers/roles.d.ts +10 -1
  261. package/dist/graph/classifiers/roles.d.ts.map +1 -1
  262. package/dist/graph/classifiers/roles.js +60 -6
  263. package/dist/graph/classifiers/roles.js.map +1 -1
  264. package/dist/index.d.ts +1 -1
  265. package/dist/index.d.ts.map +1 -1
  266. package/dist/index.js +1 -1
  267. package/dist/index.js.map +1 -1
  268. package/dist/infrastructure/config.d.ts +87 -4
  269. package/dist/infrastructure/config.d.ts.map +1 -1
  270. package/dist/infrastructure/config.js +424 -22
  271. package/dist/infrastructure/config.js.map +1 -1
  272. package/dist/infrastructure/registry.d.ts +27 -7
  273. package/dist/infrastructure/registry.d.ts.map +1 -1
  274. package/dist/infrastructure/registry.js +79 -5
  275. package/dist/infrastructure/registry.js.map +1 -1
  276. package/dist/infrastructure/update-check.d.ts.map +1 -1
  277. package/dist/infrastructure/update-check.js +49 -31
  278. package/dist/infrastructure/update-check.js.map +1 -1
  279. package/dist/mcp/server.d.ts +2 -10
  280. package/dist/mcp/server.d.ts.map +1 -1
  281. package/dist/mcp/server.js.map +1 -1
  282. package/dist/mcp/tools/ast-query.d.ts +1 -1
  283. package/dist/mcp/tools/ast-query.d.ts.map +1 -1
  284. package/dist/mcp/tools/audit.d.ts +1 -1
  285. package/dist/mcp/tools/audit.d.ts.map +1 -1
  286. package/dist/mcp/tools/batch-query.d.ts +1 -1
  287. package/dist/mcp/tools/batch-query.d.ts.map +1 -1
  288. package/dist/mcp/tools/branch-compare.d.ts +1 -1
  289. package/dist/mcp/tools/branch-compare.d.ts.map +1 -1
  290. package/dist/mcp/tools/brief.d.ts +1 -1
  291. package/dist/mcp/tools/brief.d.ts.map +1 -1
  292. package/dist/mcp/tools/cfg.d.ts +1 -1
  293. package/dist/mcp/tools/cfg.d.ts.map +1 -1
  294. package/dist/mcp/tools/check.d.ts +1 -1
  295. package/dist/mcp/tools/check.d.ts.map +1 -1
  296. package/dist/mcp/tools/co-changes.d.ts +1 -1
  297. package/dist/mcp/tools/co-changes.d.ts.map +1 -1
  298. package/dist/mcp/tools/code-owners.d.ts +1 -1
  299. package/dist/mcp/tools/code-owners.d.ts.map +1 -1
  300. package/dist/mcp/tools/communities.d.ts +1 -1
  301. package/dist/mcp/tools/communities.d.ts.map +1 -1
  302. package/dist/mcp/tools/complexity.d.ts +1 -1
  303. package/dist/mcp/tools/complexity.d.ts.map +1 -1
  304. package/dist/mcp/tools/context.d.ts +1 -1
  305. package/dist/mcp/tools/context.d.ts.map +1 -1
  306. package/dist/mcp/tools/dataflow.d.ts +1 -1
  307. package/dist/mcp/tools/dataflow.d.ts.map +1 -1
  308. package/dist/mcp/tools/diff-impact.d.ts +1 -1
  309. package/dist/mcp/tools/diff-impact.d.ts.map +1 -1
  310. package/dist/mcp/tools/execution-flow.d.ts +1 -1
  311. package/dist/mcp/tools/execution-flow.d.ts.map +1 -1
  312. package/dist/mcp/tools/export-graph.d.ts +1 -1
  313. package/dist/mcp/tools/export-graph.d.ts.map +1 -1
  314. package/dist/mcp/tools/file-deps.d.ts +1 -1
  315. package/dist/mcp/tools/file-deps.d.ts.map +1 -1
  316. package/dist/mcp/tools/file-exports.d.ts +1 -1
  317. package/dist/mcp/tools/file-exports.d.ts.map +1 -1
  318. package/dist/mcp/tools/find-cycles.d.ts +1 -1
  319. package/dist/mcp/tools/find-cycles.d.ts.map +1 -1
  320. package/dist/mcp/tools/fn-impact.d.ts +1 -1
  321. package/dist/mcp/tools/fn-impact.d.ts.map +1 -1
  322. package/dist/mcp/tools/impact-analysis.d.ts +1 -1
  323. package/dist/mcp/tools/impact-analysis.d.ts.map +1 -1
  324. package/dist/mcp/tools/implementations.d.ts +1 -1
  325. package/dist/mcp/tools/implementations.d.ts.map +1 -1
  326. package/dist/mcp/tools/index.d.ts +2 -5
  327. package/dist/mcp/tools/index.d.ts.map +1 -1
  328. package/dist/mcp/tools/index.js.map +1 -1
  329. package/dist/mcp/tools/interfaces.d.ts +1 -1
  330. package/dist/mcp/tools/interfaces.d.ts.map +1 -1
  331. package/dist/mcp/tools/list-functions.d.ts +1 -1
  332. package/dist/mcp/tools/list-functions.d.ts.map +1 -1
  333. package/dist/mcp/tools/list-repos.d.ts +1 -1
  334. package/dist/mcp/tools/list-repos.d.ts.map +1 -1
  335. package/dist/mcp/tools/module-map.d.ts +1 -1
  336. package/dist/mcp/tools/module-map.d.ts.map +1 -1
  337. package/dist/mcp/tools/node-roles.d.ts +1 -1
  338. package/dist/mcp/tools/node-roles.d.ts.map +1 -1
  339. package/dist/mcp/tools/path.d.ts +1 -1
  340. package/dist/mcp/tools/path.d.ts.map +1 -1
  341. package/dist/mcp/tools/query.d.ts +1 -1
  342. package/dist/mcp/tools/query.d.ts.map +1 -1
  343. package/dist/mcp/tools/semantic-search.d.ts +1 -1
  344. package/dist/mcp/tools/semantic-search.d.ts.map +1 -1
  345. package/dist/mcp/tools/sequence.d.ts +1 -1
  346. package/dist/mcp/tools/sequence.d.ts.map +1 -1
  347. package/dist/mcp/tools/structure.d.ts +1 -1
  348. package/dist/mcp/tools/structure.d.ts.map +1 -1
  349. package/dist/mcp/tools/symbol-children.d.ts +1 -1
  350. package/dist/mcp/tools/symbol-children.d.ts.map +1 -1
  351. package/dist/mcp/tools/triage.d.ts +1 -1
  352. package/dist/mcp/tools/triage.d.ts.map +1 -1
  353. package/dist/mcp/tools/where.d.ts +1 -1
  354. package/dist/mcp/tools/where.d.ts.map +1 -1
  355. package/dist/mcp/types.d.ts +19 -0
  356. package/dist/mcp/types.d.ts.map +1 -0
  357. package/dist/mcp/types.js +6 -0
  358. package/dist/mcp/types.js.map +1 -0
  359. package/dist/presentation/queries-cli/index.d.ts +1 -1
  360. package/dist/presentation/queries-cli/index.d.ts.map +1 -1
  361. package/dist/presentation/queries-cli/index.js +1 -1
  362. package/dist/presentation/queries-cli/index.js.map +1 -1
  363. package/dist/presentation/queries-cli/overview.d.ts +1 -0
  364. package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
  365. package/dist/presentation/queries-cli/overview.js +20 -1
  366. package/dist/presentation/queries-cli/overview.js.map +1 -1
  367. package/dist/presentation/queries-cli.d.ts +1 -1
  368. package/dist/presentation/queries-cli.d.ts.map +1 -1
  369. package/dist/presentation/queries-cli.js +1 -1
  370. package/dist/presentation/queries-cli.js.map +1 -1
  371. package/dist/presentation/structure.d.ts +1 -1
  372. package/dist/presentation/structure.d.ts.map +1 -1
  373. package/dist/presentation/structure.js +2 -2
  374. package/dist/presentation/structure.js.map +1 -1
  375. package/dist/presentation/viewer.d.ts.map +1 -1
  376. package/dist/presentation/viewer.js +45 -32
  377. package/dist/presentation/viewer.js.map +1 -1
  378. package/dist/shared/constants.d.ts +21 -0
  379. package/dist/shared/constants.d.ts.map +1 -1
  380. package/dist/shared/constants.js +25 -0
  381. package/dist/shared/constants.js.map +1 -1
  382. package/dist/shared/normalize.d.ts.map +1 -1
  383. package/dist/shared/normalize.js +12 -22
  384. package/dist/shared/normalize.js.map +1 -1
  385. package/dist/shared/paginate.d.ts +4 -17
  386. package/dist/shared/paginate.d.ts.map +1 -1
  387. package/dist/shared/paginate.js.map +1 -1
  388. package/dist/types.d.ts +113 -1
  389. package/dist/types.d.ts.map +1 -1
  390. package/grammars/tree-sitter-erlang.wasm +0 -0
  391. package/grammars/tree-sitter-gleam.wasm +0 -0
  392. package/package.json +7 -8
  393. package/src/ast-analysis/engine.ts +43 -63
  394. package/src/ast-analysis/rules/b2.ts +263 -0
  395. package/src/ast-analysis/rules/b3.ts +127 -0
  396. package/src/ast-analysis/rules/b4.ts +378 -0
  397. package/src/ast-analysis/rules/b5.ts +65 -0
  398. package/src/ast-analysis/rules/c.ts +157 -0
  399. package/src/ast-analysis/rules/index.ts +34 -0
  400. package/src/ast-analysis/rules/javascript.ts +3 -0
  401. package/src/ast-analysis/shared.ts +2 -0
  402. package/src/ast-analysis/visitor-utils.ts +5 -0
  403. package/src/ast-analysis/visitor.ts +82 -52
  404. package/src/ast-analysis/visitors/cfg-visitor.ts +198 -84
  405. package/src/ast-analysis/visitors/complexity-visitor.ts +44 -16
  406. package/src/ast-analysis/visitors/dataflow-visitor.ts +68 -29
  407. package/src/cli/commands/audit.ts +2 -1
  408. package/src/cli/commands/batch.ts +1 -0
  409. package/src/cli/commands/build.ts +6 -1
  410. package/src/cli/commands/config.ts +353 -0
  411. package/src/cli/commands/roles.ts +6 -1
  412. package/src/cli/commands/triage.ts +1 -1
  413. package/src/cli/index.ts +10 -0
  414. package/src/cli/shared/options.ts +11 -1
  415. package/src/cli/types.ts +2 -0
  416. package/src/db/better-sqlite3.ts +5 -4
  417. package/src/db/connection.ts +23 -5
  418. package/src/db/index.ts +1 -0
  419. package/src/db/migrations.ts +69 -1
  420. package/src/db/repository/build-stmts.ts +30 -0
  421. package/src/db/repository/dataflow.ts +16 -0
  422. package/src/db/repository/index.ts +1 -1
  423. package/src/db/repository/native-repository.ts +56 -40
  424. package/src/domain/analysis/fn-impact.ts +4 -0
  425. package/src/domain/analysis/module-map.ts +38 -6
  426. package/src/domain/analysis/roles.ts +23 -0
  427. package/src/domain/graph/builder/call-resolver.ts +156 -218
  428. package/src/domain/graph/builder/cha.ts +18 -1
  429. package/src/domain/graph/builder/context.ts +1 -0
  430. package/src/domain/graph/builder/helpers.ts +205 -67
  431. package/src/domain/graph/builder/incremental.ts +249 -119
  432. package/src/domain/graph/builder/pipeline.ts +59 -6
  433. package/src/domain/graph/builder/stages/build-edges.ts +783 -652
  434. package/src/domain/graph/builder/stages/collect-files.ts +12 -6
  435. package/src/domain/graph/builder/stages/detect-changes.ts +4 -2
  436. package/src/domain/graph/builder/stages/finalize.ts +4 -0
  437. package/src/domain/graph/builder/stages/native-orchestrator.ts +1214 -398
  438. package/src/domain/graph/builder/stages/resolve-imports.ts +1 -1
  439. package/src/domain/graph/resolver/points-to.ts +182 -59
  440. package/src/domain/graph/resolver/strategy.ts +265 -0
  441. package/src/domain/graph/watcher.ts +19 -9
  442. package/src/domain/parser.ts +57 -16
  443. package/src/domain/queries.ts +1 -1
  444. package/src/domain/wasm-worker-entry.ts +13 -2
  445. package/src/domain/wasm-worker-pool.ts +29 -4
  446. package/src/domain/wasm-worker-protocol.ts +5 -0
  447. package/src/extractors/cpp.ts +44 -1
  448. package/src/extractors/cuda.ts +44 -1
  449. package/src/extractors/dart.ts +48 -3
  450. package/src/extractors/groovy.ts +62 -2
  451. package/src/extractors/helpers.ts +48 -2
  452. package/src/extractors/java.ts +88 -8
  453. package/src/extractors/javascript.ts +693 -167
  454. package/src/extractors/kotlin.ts +57 -3
  455. package/src/extractors/objc.ts +25 -1
  456. package/src/extractors/scala.ts +63 -1
  457. package/src/extractors/swift.ts +46 -3
  458. package/src/features/audit.ts +43 -34
  459. package/src/features/boundaries.ts +17 -9
  460. package/src/features/cfg.ts +31 -22
  461. package/src/features/check.ts +21 -5
  462. package/src/features/communities.ts +28 -19
  463. package/src/features/dataflow.ts +755 -6
  464. package/src/features/manifesto.ts +76 -75
  465. package/src/features/sequence.ts +29 -23
  466. package/src/features/snapshot.ts +36 -25
  467. package/src/features/structure-query.ts +7 -7
  468. package/src/features/structure.ts +185 -55
  469. package/src/features/triage.ts +28 -15
  470. package/src/graph/algorithms/bfs.ts +13 -12
  471. package/src/graph/algorithms/tarjan.ts +5 -0
  472. package/src/graph/builders/dependency.ts +35 -23
  473. package/src/graph/classifiers/roles.ts +74 -7
  474. package/src/index.ts +5 -1
  475. package/src/infrastructure/config.ts +511 -23
  476. package/src/infrastructure/registry.ts +117 -12
  477. package/src/infrastructure/update-check.ts +55 -33
  478. package/src/mcp/server.ts +2 -8
  479. package/src/mcp/tools/ast-query.ts +1 -1
  480. package/src/mcp/tools/audit.ts +1 -1
  481. package/src/mcp/tools/batch-query.ts +1 -1
  482. package/src/mcp/tools/branch-compare.ts +1 -1
  483. package/src/mcp/tools/brief.ts +1 -1
  484. package/src/mcp/tools/cfg.ts +1 -1
  485. package/src/mcp/tools/check.ts +1 -1
  486. package/src/mcp/tools/co-changes.ts +1 -1
  487. package/src/mcp/tools/code-owners.ts +1 -1
  488. package/src/mcp/tools/communities.ts +1 -1
  489. package/src/mcp/tools/complexity.ts +1 -1
  490. package/src/mcp/tools/context.ts +1 -1
  491. package/src/mcp/tools/dataflow.ts +1 -1
  492. package/src/mcp/tools/diff-impact.ts +1 -1
  493. package/src/mcp/tools/execution-flow.ts +1 -1
  494. package/src/mcp/tools/export-graph.ts +1 -1
  495. package/src/mcp/tools/file-deps.ts +1 -1
  496. package/src/mcp/tools/file-exports.ts +1 -1
  497. package/src/mcp/tools/find-cycles.ts +1 -1
  498. package/src/mcp/tools/fn-impact.ts +1 -1
  499. package/src/mcp/tools/impact-analysis.ts +1 -1
  500. package/src/mcp/tools/implementations.ts +1 -1
  501. package/src/mcp/tools/index.ts +2 -5
  502. package/src/mcp/tools/interfaces.ts +1 -1
  503. package/src/mcp/tools/list-functions.ts +1 -1
  504. package/src/mcp/tools/list-repos.ts +1 -1
  505. package/src/mcp/tools/module-map.ts +1 -1
  506. package/src/mcp/tools/node-roles.ts +1 -1
  507. package/src/mcp/tools/path.ts +1 -1
  508. package/src/mcp/tools/query.ts +1 -1
  509. package/src/mcp/tools/semantic-search.ts +1 -1
  510. package/src/mcp/tools/sequence.ts +1 -1
  511. package/src/mcp/tools/structure.ts +1 -1
  512. package/src/mcp/tools/symbol-children.ts +1 -1
  513. package/src/mcp/tools/triage.ts +1 -1
  514. package/src/mcp/tools/where.ts +1 -1
  515. package/src/mcp/types.ts +21 -0
  516. package/src/presentation/queries-cli/index.ts +1 -1
  517. package/src/presentation/queries-cli/overview.ts +35 -1
  518. package/src/presentation/queries-cli.ts +1 -0
  519. package/src/presentation/structure.ts +3 -3
  520. package/src/presentation/viewer.ts +98 -87
  521. package/src/shared/constants.ts +26 -0
  522. package/src/shared/normalize.ts +13 -22
  523. package/src/shared/paginate.ts +4 -18
  524. package/src/types.ts +127 -1
@@ -8,8 +8,8 @@ import fs from 'node:fs';
8
8
  import path from 'node:path';
9
9
  import { purgeFilesData } from '../../../db/index.js';
10
10
  import { debug, warn } from '../../../infrastructure/logger.js';
11
- import { EXTENSIONS, IGNORE_DIRS, normalizePath } from '../../../shared/constants.js';
12
- import { compileGlobs, matchesAny } from '../../../shared/globs.js';
11
+ import { buildIgnoreSet, EXTENSIONS, normalizePath } from '../../../shared/constants.js';
12
+ import { compileGlobs, globToRegex, matchesAny } from '../../../shared/globs.js';
13
13
  import type {
14
14
  BetterSqlite3Database,
15
15
  CodegraphConfig,
@@ -48,14 +48,20 @@ export const BUILTIN_RECEIVERS: Set<string> = new Set([
48
48
  'require',
49
49
  ]);
50
50
 
51
+ /** Phase 8.6: confidence penalty applied to CHA-dispatch edges. */
52
+ export const CHA_DISPATCH_PENALTY = 0.1;
53
+ /** Phase 8.6: fixed confidence for typed-receiver (interface/CHA) dispatch edges.
54
+ * File proximity is not meaningful for virtual dispatch — all three engine paths
55
+ * (WASM inline, WASM post-pass, native post-pass) must agree on this value. */
56
+ export const CHA_TYPED_DISPATCH_CONFIDENCE = 0.8;
57
+
51
58
  /** Check if a directory entry should be skipped (ignored dirs, dotfiles). */
52
- function shouldSkipEntry(entry: fs.Dirent, extraIgnore: Set<string> | null): boolean {
59
+ function shouldSkipEntry(entry: fs.Dirent, ignoreSet: ReadonlySet<string>): boolean {
53
60
  if (entry.name.startsWith('.') && entry.name !== '.') {
54
- if (IGNORE_DIRS.has(entry.name)) return true;
61
+ if (ignoreSet.has(entry.name)) return true;
55
62
  if (entry.isDirectory()) return true;
56
63
  }
57
- if (IGNORE_DIRS.has(entry.name)) return true;
58
- if (extraIgnore?.has(entry.name)) return true;
64
+ if (ignoreSet.has(entry.name)) return true;
59
65
  return false;
60
66
  }
61
67
 
@@ -76,13 +82,65 @@ export function passesIncludeExclude(
76
82
  return true;
77
83
  }
78
84
 
85
+ /**
86
+ * Parse the `.gitignore` file at the project root and return compiled regexes
87
+ * for each non-negated, non-comment pattern.
88
+ *
89
+ * Only the root-level `.gitignore` is read — nested `.gitignore` files and
90
+ * global gitignore are not consulted. This gives the WASM file-collection
91
+ * walker the same coarse gitignore respect that the Rust engine gets from the
92
+ * `ignore` crate's `git_ignore(true)` option, without requiring an additional
93
+ * npm dependency.
94
+ *
95
+ * Negation patterns (`!pattern`) are intentionally skipped — honoring them
96
+ * correctly requires ordered evaluation which is outside scope here. The Rust
97
+ * engine's `ignore` crate handles negation natively.
98
+ */
99
+ export function readGitignorePatterns(rootDir: string): readonly RegExp[] {
100
+ const gitignorePath = path.join(rootDir, '.gitignore');
101
+ let contents: string;
102
+ try {
103
+ contents = fs.readFileSync(gitignorePath, 'utf-8');
104
+ } catch {
105
+ return [];
106
+ }
107
+
108
+ const regexes: RegExp[] = [];
109
+ for (const rawLine of contents.split(/\r?\n/)) {
110
+ const line = rawLine.trim();
111
+ // Skip empty lines, comments, and negation patterns
112
+ if (!line || line.startsWith('#') || line.startsWith('!')) continue;
113
+ // Strip trailing slash (directory indicator) — we match files by path regardless
114
+ const pattern = line.endsWith('/') ? line.slice(0, -1) : line;
115
+ try {
116
+ // If pattern contains no '/', it should match at any depth — prefix with `**/`.
117
+ // If pattern starts with '/', it is anchored to root — strip the leading slash.
118
+ // Otherwise use as-is (e.g. `crates/codegraph-core/index.js`).
119
+ let normalized: string;
120
+ if (pattern.startsWith('/')) {
121
+ normalized = pattern.slice(1);
122
+ } else if (!pattern.includes('/')) {
123
+ normalized = `**/${pattern}`;
124
+ } else {
125
+ normalized = pattern;
126
+ }
127
+ regexes.push(globToRegex(normalized));
128
+ } catch {
129
+ // Ignore patterns that don't compile (e.g. those with unsupported syntax)
130
+ }
131
+ }
132
+ return Object.freeze(regexes);
133
+ }
134
+
79
135
  /** Per-walk state computed once at the top-level invocation. */
80
136
  interface CollectContext {
81
137
  readonly rootDir: string;
82
138
  readonly includeRegexes: readonly RegExp[];
83
139
  readonly excludeRegexes: readonly RegExp[];
140
+ readonly gitignoreRegexes: readonly RegExp[];
84
141
  readonly hasGlobFilters: boolean;
85
- readonly extraIgnore: Set<string> | null;
142
+ /** Merged set of IGNORE_DIRS + config.ignoreDirs + config.ignoreAdditionalDirs. */
143
+ readonly ignoreSet: ReadonlySet<string>;
86
144
  readonly visited: Set<string>;
87
145
  }
88
146
 
@@ -115,8 +173,10 @@ function readDirSafe(dir: string): fs.Dirent[] | null {
115
173
  /** True if `entry` is a source file we should collect under `ctx`. */
116
174
  function isCollectableSourceFile(full: string, entry: fs.Dirent, ctx: CollectContext): boolean {
117
175
  if (!EXTENSIONS.has(path.extname(entry.name))) return false;
118
- if (!ctx.hasGlobFilters) return true;
119
176
  const rel = normalizePath(path.relative(ctx.rootDir, full));
177
+ // Respect .gitignore patterns before applying include/exclude globs
178
+ if (ctx.gitignoreRegexes.length > 0 && matchesAny(ctx.gitignoreRegexes, rel)) return false;
179
+ if (!ctx.hasGlobFilters) return true;
120
180
  return passesIncludeExclude(rel, ctx.includeRegexes, ctx.excludeRegexes);
121
181
  }
122
182
 
@@ -133,7 +193,7 @@ function walkCollect(
133
193
 
134
194
  let hasFiles = false;
135
195
  for (const entry of entries) {
136
- if (shouldSkipEntry(entry, ctx.extraIgnore)) continue;
196
+ if (shouldSkipEntry(entry, ctx.ignoreSet)) continue;
137
197
 
138
198
  const full = path.join(dir, entry.name);
139
199
  if (entry.isDirectory()) {
@@ -176,12 +236,19 @@ export function collectFiles(
176
236
  const trackDirs = directories instanceof Set;
177
237
  const includeRegexes = compileGlobs(config.include);
178
238
  const excludeRegexes = compileGlobs(config.exclude);
239
+ const gitignoreRegexes = readGitignorePatterns(dir);
240
+ // Build the merged ignore set:
241
+ // - config.ignoreDirs are appended to IGNORE_DIRS (existing behaviour: per-repo overrides)
242
+ // - config.ignoreAdditionalDirs are also merged in on top of IGNORE_DIRS (new feature)
243
+ const extraDirs = [...(config.ignoreDirs ?? []), ...(config.ignoreAdditionalDirs ?? [])];
244
+ const ignoreSet = buildIgnoreSet(extraDirs.length ? extraDirs : undefined);
179
245
  const ctx: CollectContext = {
180
246
  rootDir: dir,
181
247
  includeRegexes,
182
248
  excludeRegexes,
249
+ gitignoreRegexes,
183
250
  hasGlobFilters: includeRegexes.length > 0 || excludeRegexes.length > 0,
184
- extraIgnore: config.ignoreDirs ? new Set(config.ignoreDirs) : null,
251
+ ignoreSet,
185
252
  visited: new Set(),
186
253
  };
187
254
 
@@ -313,9 +380,9 @@ function getEdgeStmt(db: BetterSqlite3Database, chunkSize: number): SqliteStatem
313
380
  }
314
381
  let stmt = cache.get(chunkSize);
315
382
  if (!stmt) {
316
- const ph = '(?,?,?,?,?,?)';
383
+ const ph = '(?,?,?,?,?,?,?)';
317
384
  stmt = db.prepare(
318
- 'INSERT INTO edges (source_id,target_id,kind,confidence,dynamic,technique) VALUES ' +
385
+ 'INSERT INTO edges (source_id,target_id,kind,confidence,dynamic,technique,dynamic_kind) VALUES ' +
319
386
  Array.from({ length: chunkSize }, () => ph).join(','),
320
387
  );
321
388
  cache.set(chunkSize, stmt);
@@ -344,7 +411,7 @@ export function batchInsertNodes(db: BetterSqlite3Database, rows: unknown[][]):
344
411
 
345
412
  /**
346
413
  * Batch-insert edge rows via multi-value INSERT statements.
347
- * Each row: [source_id, target_id, kind, confidence, dynamic, technique]
414
+ * Each row: [source_id, target_id, kind, confidence, dynamic, technique, dynamic_kind]
348
415
  */
349
416
  export function batchInsertEdges(db: BetterSqlite3Database, rows: unknown[][]): void {
350
417
  if (!rows.length) return;
@@ -355,32 +422,26 @@ export function batchInsertEdges(db: BetterSqlite3Database, rows: unknown[][]):
355
422
  const vals: unknown[] = [];
356
423
  for (let j = i; j < end; j++) {
357
424
  const r = rows[j] as unknown[];
358
- vals.push(r[0], r[1], r[2], r[3], r[4], r[5] ?? null);
425
+ vals.push(r[0], r[1], r[2], r[3], r[4], r[5] ?? null, r[6] ?? null);
359
426
  }
360
427
  stmt.run(...vals);
361
428
  }
362
429
  }
363
430
 
431
+ /** Confidence assigned to CHA-expanded interface/abstract dispatch edges. */
432
+ export const CHA_DISPATCH_CONFIDENCE = 0.8;
433
+
364
434
  /**
365
- * CHA (Class Hierarchy Analysis) post-pass.
366
- *
367
- * Expands virtual-dispatch call edges for class hierarchies and interface
368
- * implementations already present in the DB:
369
- *
370
- * 1. Build implementors map: parent/interface → [child/implementing class] from
371
- * `extends` and `implements` edges.
372
- * 2. Collect RTA evidence: class nodes that appear as `calls` targets (new X()).
373
- * 3. Find all `calls` edges to qualified method nodes (name contains '.').
374
- * 4. For each such call, expand to concrete overrides via the implementors map,
375
- * filtered by RTA when evidence exists.
376
- *
377
- * Used by both the native orchestrator post-pass and the WASM build-edges pass.
435
+ * Build the parent→children implementor map from `extends`/`implements` edges.
436
+ * Returns null if no hierarchy edges exist.
378
437
  */
379
- export function runChaPostPass(db: BetterSqlite3Database): number {
438
+ function buildImplementorMap(
439
+ db: BetterSqlite3Database,
440
+ ): { implementors: Map<string, string[]>; implementorSets: Map<string, Set<string>> } | null {
380
441
  const hasHierarchy = db
381
442
  .prepare(`SELECT 1 FROM edges WHERE kind IN ('extends', 'implements') LIMIT 1`)
382
443
  .get();
383
- if (!hasHierarchy) return 0;
444
+ if (!hasHierarchy) return null;
384
445
 
385
446
  const hierarchyRows = db
386
447
  .prepare(
@@ -401,11 +462,22 @@ export function runChaPostPass(db: BetterSqlite3Database): number {
401
462
  }
402
463
  set.add(row.child_name);
403
464
  }
404
- if (implementorSets.size === 0) return 0;
405
- // Convert to arrays for iteration compatibility with the rest of the function
465
+ if (implementorSets.size === 0) return null;
466
+
467
+ // Convert to arrays for iteration compatibility
406
468
  const implementors = new Map([...implementorSets.entries()].map(([k, v]) => [k, [...v]]));
469
+ return { implementors, implementorSets };
470
+ }
407
471
 
408
- // RTA: collect class names instantiated via constructor calls (`new X()`).
472
+ /**
473
+ * Collect RTA (Rapid Type Analysis) evidence: class names instantiated via
474
+ * constructor calls (`new X()`). Falls back to constructor/function-kind nodes
475
+ * for languages that record constructor calls differently (e.g. TS via WASM).
476
+ */
477
+ function collectRtaInstantiated(
478
+ db: BetterSqlite3Database,
479
+ implementorSets: Map<string, Set<string>>,
480
+ ): Set<string> {
409
481
  let rtaRows = db
410
482
  .prepare(
411
483
  `SELECT DISTINCT tgt.name
@@ -414,6 +486,7 @@ export function runChaPostPass(db: BetterSqlite3Database): number {
414
486
  WHERE e.kind = 'calls' AND tgt.kind = 'class'`,
415
487
  )
416
488
  .all() as Array<{ name: string }>;
489
+
417
490
  if (rtaRows.length === 0) {
418
491
  // Fallback: some languages (e.g. TypeScript via WASM) record constructor calls as
419
492
  // 'function' or 'constructor' kind rather than 'class'. Restrict to names that are
@@ -446,7 +519,89 @@ export function runChaPostPass(db: BetterSqlite3Database): number {
446
519
  }
447
520
  }
448
521
  }
449
- const instantiated = new Set(rtaRows.map((r) => r.name));
522
+
523
+ return new Set(rtaRows.map((r) => r.name));
524
+ }
525
+
526
+ /**
527
+ * BFS-expand a single call-to-qualified-method into CHA dispatch edges.
528
+ *
529
+ * For `source_id` calling `typeName.methodSuffix`, walks the implementors
530
+ * map (BFS) and emits an edge for each concrete override that passes the
531
+ * RTA filter. New edges are appended to `newEdges`; `seen` is updated in
532
+ * place to prevent duplicate insertions within the same pass.
533
+ */
534
+ function expandChaCall(
535
+ sourceId: number,
536
+ typeName: string,
537
+ methodSuffix: string,
538
+ implementors: Map<string, string[]>,
539
+ instantiated: Set<string>,
540
+ noRtaEvidence: boolean,
541
+ findMethodStmt: { all(name: string): unknown[] },
542
+ seen: Set<string>,
543
+ newEdges: Array<[number, number, string, number, number, string]>,
544
+ ): void {
545
+ // BFS over the implementors map — handles multi-level hierarchies where
546
+ // abstract/non-instantiated classes sit between the call-site type and
547
+ // the concrete leaf implementations (matches runPostNativeCha, issue #1311).
548
+ const bfsQueue: string[] = [typeName];
549
+ const bfsVisited = new Set<string>([typeName]);
550
+ while (bfsQueue.length > 0) {
551
+ const current = bfsQueue.shift()!;
552
+ const children = implementors.get(current);
553
+ if (!children?.length) continue;
554
+
555
+ for (const cls of children) {
556
+ if (bfsVisited.has(cls)) continue;
557
+ bfsVisited.add(cls);
558
+
559
+ if (noRtaEvidence || instantiated.has(cls)) {
560
+ const qualifiedName = `${cls}.${methodSuffix}`;
561
+ const methodNodes = findMethodStmt.all(qualifiedName) as Array<{ id: number }>;
562
+ for (const methodNode of methodNodes) {
563
+ if (methodNode.id === sourceId) continue; // skip self-loops
564
+ const key = `${sourceId}|${methodNode.id}`;
565
+ if (seen.has(key)) continue;
566
+ seen.add(key);
567
+ newEdges.push([
568
+ sourceId,
569
+ methodNode.id,
570
+ 'calls',
571
+ CHA_TYPED_DISPATCH_CONFIDENCE,
572
+ 0,
573
+ 'cha-expanded',
574
+ ]);
575
+ }
576
+ }
577
+
578
+ // Always traverse children — non-instantiated classes may have instantiated subclasses.
579
+ bfsQueue.push(cls);
580
+ }
581
+ }
582
+ }
583
+
584
+ /**
585
+ * CHA (Class Hierarchy Analysis) post-pass.
586
+ *
587
+ * Expands virtual-dispatch call edges for class hierarchies and interface
588
+ * implementations already present in the DB:
589
+ *
590
+ * 1. Build implementors map: parent/interface → [child/implementing class] from
591
+ * `extends` and `implements` edges.
592
+ * 2. Collect RTA evidence: class nodes that appear as `calls` targets (new X()).
593
+ * 3. Find all `calls` edges to qualified method nodes (name contains '.').
594
+ * 4. For each such call, expand to concrete overrides via the implementors map,
595
+ * filtered by RTA when evidence exists.
596
+ *
597
+ * Used by both the native orchestrator post-pass and the WASM build-edges pass.
598
+ */
599
+ export function runChaPostPass(db: BetterSqlite3Database): number {
600
+ const hierarchy = buildImplementorMap(db);
601
+ if (!hierarchy) return 0;
602
+ const { implementors, implementorSets } = hierarchy;
603
+
604
+ const instantiated = collectRtaInstantiated(db, implementorSets);
450
605
  const noRtaEvidence = instantiated.size === 0;
451
606
  if (noRtaEvidence) {
452
607
  debug('runChaPostPass: no constructor-call evidence — proceeding without RTA filter');
@@ -454,19 +609,21 @@ export function runChaPostPass(db: BetterSqlite3Database): number {
454
609
 
455
610
  const callToMethods = db
456
611
  .prepare(
457
- `SELECT e.source_id, tgt.name AS method_name
612
+ `SELECT e.source_id, src.name AS caller_name, tgt.name AS method_name
458
613
  FROM edges e
459
614
  JOIN nodes tgt ON e.target_id = tgt.id
615
+ JOIN nodes src ON e.source_id = src.id
460
616
  WHERE e.kind = 'calls' AND tgt.kind = 'method'
461
- AND INSTR(tgt.name, '.') > 0`,
617
+ AND INSTR(tgt.name, '.') > 0
618
+ AND (e.technique IS NULL OR e.technique != 'cha-expanded')`,
462
619
  )
463
- .all() as Array<{ source_id: number; method_name: string }>;
620
+ .all() as Array<{ source_id: number; caller_name: string; method_name: string }>;
464
621
 
465
- const seen = new Set<string>();
466
622
  // Scope deduplication to only the source_ids we are about to expand, avoiding
467
623
  // a full-table scan. CHA only inserts edges FROM callers that already call a
468
624
  // qualified method (the source_ids in callToMethods), so we only need to
469
625
  // check existing edges for those specific callers.
626
+ const seen = new Set<string>();
470
627
  const callerIds = [...new Set(callToMethods.map((r) => r.source_id))];
471
628
  if (callerIds.length > 0) {
472
629
  // Chunk to stay within SQLite SQLITE_MAX_VARIABLE_NUMBER (999 in many builds).
@@ -492,36 +649,17 @@ export function runChaPostPass(db: BetterSqlite3Database): number {
492
649
  if (dotIdx === -1) continue;
493
650
  const typeName = method_name.slice(0, dotIdx);
494
651
  const methodSuffix = method_name.slice(dotIdx + 1);
495
-
496
- // BFS over the implementors map — handles multi-level hierarchies where
497
- // abstract/non-instantiated classes sit between the call-site type and
498
- // the concrete leaf implementations (matches runPostNativeCha, issue #1311).
499
- const bfsQueue: string[] = [typeName];
500
- const bfsVisited = new Set<string>([typeName]);
501
- while (bfsQueue.length > 0) {
502
- const current = bfsQueue.shift()!;
503
- const children = implementors.get(current);
504
- if (!children?.length) continue;
505
-
506
- for (const cls of children) {
507
- if (bfsVisited.has(cls)) continue;
508
- bfsVisited.add(cls);
509
-
510
- if (noRtaEvidence || instantiated.has(cls)) {
511
- const qualifiedName = `${cls}.${methodSuffix}`;
512
- const methodNodes = findMethodStmt.all(qualifiedName) as Array<{ id: number }>;
513
- for (const methodNode of methodNodes) {
514
- const key = `${source_id}|${methodNode.id}`;
515
- if (seen.has(key)) continue;
516
- seen.add(key);
517
- newEdges.push([source_id, methodNode.id, 'calls', 0.8, 0, 'cha']);
518
- }
519
- }
520
-
521
- // Always traverse children — non-instantiated classes may have instantiated subclasses.
522
- bfsQueue.push(cls);
523
- }
524
- }
652
+ expandChaCall(
653
+ source_id,
654
+ typeName,
655
+ methodSuffix,
656
+ implementors,
657
+ instantiated,
658
+ noRtaEvidence,
659
+ findMethodStmt,
660
+ seen,
661
+ newEdges,
662
+ );
525
663
  }
526
664
 
527
665
  if (newEdges.length > 0) {