@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
@@ -158,6 +158,7 @@ const COMMON_QUERY_PATTERNS: string[] = [
158
158
  '(variable_declarator name: (identifier) @varfn_name value: (generator_function) @varfn_value)',
159
159
  '(method_definition name: (property_identifier) @meth_name) @meth_node',
160
160
  '(method_definition name: (private_property_identifier) @meth_name) @meth_node',
161
+ '(method_definition name: (computed_property_name) @meth_name) @meth_node',
161
162
  '(import_statement source: (string) @imp_source) @imp_node',
162
163
  '(export_statement) @exp_node',
163
164
  '(call_expression function: (identifier) @callfn_name) @callfn_node',
@@ -221,7 +222,9 @@ async function doLoadLanguage(entry: LanguageRegistryEntry): Promise<void> {
221
222
  file: entry.grammarFile,
222
223
  cause: e as Error,
223
224
  });
224
- warn(
225
+ const isEnoent = (e as NodeJS.ErrnoException).code === 'ENOENT';
226
+ const log = isEnoent ? debug : warn;
227
+ log(
225
228
  `${entry.id} parser failed to initialize: ${(e as Error).message}. ${entry.id} files will be skipped.`,
226
229
  );
227
230
  _cachedParsers!.set(entry.id, null);
@@ -465,7 +468,7 @@ export function getInstalledWasmExtensions(): Set<string> {
465
468
  * Lowercase file extensions covered by the native Rust addon.
466
469
  *
467
470
  * Mirrors `LanguageKind::from_extension` in
468
- * `crates/codegraph-core/src/parser_registry.rs`. Used to classify why the
471
+ * `crates/codegraph-core/src/domain/parser.rs`. Used to classify why the
469
472
  * native orchestrator dropped a file: extensions outside this set are a
470
473
  * legitimate parser limit (no Rust extractor exists), while extensions inside
471
474
  * it indicate a real native bug (parse/read/extract failure).
@@ -713,7 +716,17 @@ function patchReturnTypeMap(r: any): void {
713
716
  }
714
717
 
715
718
  /** Wrap bindingType into binding object for dataflow argFlows and mutations. */
716
- function patchDataflow(dataflow: any): void {
719
+ /**
720
+ * Normalise a DataflowResult from the native Rust extractor to the VisitorArgFlow
721
+ * shape expected by the TypeScript dataflow analysis layer.
722
+ *
723
+ * The Rust `DataflowArgFlow` emits `bindingType: string | null` as a flat field.
724
+ * The TS analysis layer (`buildDataflowVerticesAndEdges`, `collectCallerStitchCandidates`)
725
+ * expects `binding: { type: string; index?: number }` on each argFlow/mutation entry.
726
+ * This normalisation must be applied whenever `extractDataflowAnalysis` is called
727
+ * outside the standard `patchNativeResult` pipeline.
728
+ */
729
+ export function patchDataflowResult(dataflow: any): void {
717
730
  if (dataflow.argFlows) {
718
731
  for (const f of dataflow.argFlows) {
719
732
  f.binding = f.bindingType ? { type: f.bindingType } : null;
@@ -735,7 +748,7 @@ function patchNativeResult(r: any): ExtractorOutput {
735
748
  if (r.imports) patchImports(r.imports);
736
749
  patchTypeMap(r);
737
750
  patchReturnTypeMap(r);
738
- if (r.dataflow) patchDataflow(r.dataflow);
751
+ if (r.dataflow) patchDataflowResult(r.dataflow);
739
752
 
740
753
  return r;
741
754
  }
@@ -1181,12 +1194,25 @@ async function parseFilesWasm(
1181
1194
  /**
1182
1195
  * Files at or below this count use the inline parse path (no worker spawn).
1183
1196
  *
1184
- * Sized for typical engine-parity drops: a handful of fixture files in one
1185
- * or two languages (the recurring HCL case is 4 files). Above this, the
1186
- * worker-pool's IPC + crash-isolation cost (#965) is amortized over enough
1187
- * parse work to be worth paying; below it, the ~1–2s cold-start dominates.
1197
+ * The worker pool exists for crash safety (#965): exotic (non-required) WASM
1198
+ * grammars can trigger uncatchable V8 fatal errors that would kill the main
1199
+ * process. Running them in a worker means only the worker dies; the pool
1200
+ * detects the exit, skips the file, respawns, and continues.
1201
+ *
1202
+ * JS/TS/TSX are required-tier grammars — they have never triggered the V8
1203
+ * fatal crash class and are safe to run inline. The primary hot caller
1204
+ * (this/super dispatch post-pass) exclusively handles JS/TS/TSX files and
1205
+ * measured ~55–64ms/file through the pool vs ~8–10ms/file inline (#1435);
1206
+ * IPC overhead scales linearly with file count, not amortised.
1207
+ *
1208
+ * The threshold is set high enough to keep typical this-dispatch batches
1209
+ * (≤ 18 files on the codegraph corpus) on the inline path, while still
1210
+ * routing truly large exotic-language drops (rare; typical HCL case is 4
1211
+ * files) through the pool for crash isolation. Exotic-language drops are
1212
+ * almost always well under this limit anyway, so they benefit from the
1213
+ * inline fast path too without meaningful crash risk increase.
1188
1214
  */
1189
- const INLINE_BACKFILL_THRESHOLD = 16;
1215
+ const INLINE_BACKFILL_THRESHOLD = 32;
1190
1216
 
1191
1217
  /**
1192
1218
  * Inline WASM parse (no worker) for small file batches.
@@ -1198,11 +1224,16 @@ const INLINE_BACKFILL_THRESHOLD = 16;
1198
1224
  *
1199
1225
  * Returns symbols with `_tree` set so `runAnalyses` can run AST/CFG/dataflow
1200
1226
  * visitors via the unified walker (mirrors how WASM-engine results behaved
1201
- * before the worker pool was introduced).
1227
+ * before the worker pool was introduced), unless `symbolsOnly` is true — in
1228
+ * that case `_tree` is not set, skipping all analysis visitor walks. Use
1229
+ * `symbolsOnly` when only definitions/calls/typeMap are needed (e.g. the
1230
+ * this/super dispatch post-pass) to avoid the analysis overhead on the inline
1231
+ * path, matching the optimization already applied to the worker-pool path.
1202
1232
  */
1203
1233
  async function parseFilesWasmInline(
1204
1234
  filePaths: string[],
1205
1235
  rootDir: string,
1236
+ symbolsOnly = false,
1206
1237
  ): Promise<Map<string, ExtractorOutput>> {
1207
1238
  const result = new Map<string, ExtractorOutput>();
1208
1239
  if (filePaths.length === 0) return result;
@@ -1220,7 +1251,18 @@ async function parseFilesWasmInline(
1220
1251
  if (!extracted) continue;
1221
1252
  const relPath = path.relative(rootDir, filePath).split(path.sep).join('/');
1222
1253
  const symbols = extracted.symbols as ExtractorOutput & { _tree?: unknown; _langId?: string };
1223
- symbols._tree = extracted.tree;
1254
+ // When symbolsOnly=true, skip setting _tree so runAnalyses does not run
1255
+ // AST/complexity/CFG/dataflow visitor walks — only definitions/calls/typeMap
1256
+ // are needed by callers like the this/super dispatch post-pass.
1257
+ if (!symbolsOnly) {
1258
+ symbols._tree = extracted.tree;
1259
+ } else if (typeof (extracted.tree as any)?.delete === 'function') {
1260
+ // Free the WASM-backed tree immediately — web-tree-sitter trees are backed
1261
+ // by WASM linear memory and require explicit disposal. When symbolsOnly is
1262
+ // true the tree is never stored anywhere, so we must delete it here to
1263
+ // avoid leaking WASM heap on every incremental rebuild.
1264
+ (extracted.tree as any).delete();
1265
+ }
1224
1266
  symbols._langId = extracted.langId;
1225
1267
  result.set(relPath, symbols);
1226
1268
  }
@@ -1230,14 +1272,13 @@ async function parseFilesWasmInline(
1230
1272
  /**
1231
1273
  * Backfill helper: small batches use the inline (main-thread) path; larger
1232
1274
  * batches keep the worker-pool isolation against tree-sitter WASM crashes
1233
- * (#965). Threshold matches typical engine-parity drop sizes (a few fixture
1234
- * files in one or two languages).
1275
+ * (#965). See INLINE_BACKFILL_THRESHOLD for threshold rationale.
1235
1276
  *
1236
1277
  * `opts.symbolsOnly` skips the AST/complexity/CFG/dataflow visitors in the
1237
1278
  * worker (and their result serialization across the thread boundary) for
1238
1279
  * callers that only consume definitions/calls/typeMap — the native
1239
- * orchestrator's prototype-methods and this-dispatch post-passes. Callers
1240
- * that ingest the files into the DB (dropped-language backfill) must keep
1280
+ * orchestrator's this-dispatch post-pass. Callers that ingest the files into
1281
+ * the DB (dropped-language backfill) must keep
1241
1282
  * the default full analysis.
1242
1283
  */
1243
1284
  export async function parseFilesWasmForBackfill(
@@ -1246,7 +1287,7 @@ export async function parseFilesWasmForBackfill(
1246
1287
  opts: { symbolsOnly?: boolean } = {},
1247
1288
  ): Promise<Map<string, ExtractorOutput>> {
1248
1289
  if (filePaths.length <= INLINE_BACKFILL_THRESHOLD) {
1249
- return parseFilesWasmInline(filePaths, rootDir);
1290
+ return parseFilesWasmInline(filePaths, rootDir, opts.symbolsOnly);
1250
1291
  }
1251
1292
  return parseFilesWasm(filePaths, rootDir, opts.symbolsOnly ? EXTRACT_ONLY : FULL_ANALYSIS);
1252
1293
  }
@@ -39,7 +39,7 @@ export {
39
39
  moduleMapData,
40
40
  statsData,
41
41
  } from './analysis/module-map.js';
42
- export { rolesData } from './analysis/roles.js';
42
+ export { dynamicCallsData, rolesData } from './analysis/roles.js';
43
43
  // ── Analysis modules ─────────────────────────────────────────────────────
44
44
  export {
45
45
  childrenData,
@@ -115,6 +115,7 @@ const COMMON_QUERY_PATTERNS: string[] = [
115
115
  '(variable_declarator name: (identifier) @varfn_name value: (generator_function) @varfn_value)',
116
116
  '(method_definition name: (property_identifier) @meth_name) @meth_node',
117
117
  '(method_definition name: (private_property_identifier) @meth_name) @meth_node',
118
+ '(method_definition name: (computed_property_name) @meth_name) @meth_node',
118
119
  '(import_statement source: (string) @imp_source) @imp_node',
119
120
  '(export_statement) @exp_node',
120
121
  '(call_expression function: (identifier) @callfn_name) @callfn_node',
@@ -125,11 +126,17 @@ const COMMON_QUERY_PATTERNS: string[] = [
125
126
  '(expression_statement (assignment_expression left: (member_expression) @assign_left right: (_) @assign_right)) @assign_node',
126
127
  ];
127
128
 
128
- const JS_CLASS_PATTERN: string = '(class_declaration name: (identifier) @cls_name) @cls_node';
129
+ const JS_CLASS_PATTERNS: string[] = [
130
+ '(class_declaration name: (identifier) @cls_name) @cls_node',
131
+ // class expressions: `return class Foo extends Bar { ... }` or `const X = class Foo { ... }`
132
+ '(class name: (identifier) @cls_name) @cls_node',
133
+ ];
129
134
 
130
135
  const TS_EXTRA_PATTERNS: string[] = [
131
136
  '(class_declaration name: (type_identifier) @cls_name) @cls_node',
132
137
  '(abstract_class_declaration name: (type_identifier) @cls_name) @cls_node',
138
+ // class expressions: `return class Foo extends Bar { ... }`
139
+ '(class name: (type_identifier) @cls_name) @cls_node',
133
140
  '(interface_declaration name: (type_identifier) @iface_name) @iface_node',
134
141
  '(type_alias_declaration name: (type_identifier) @type_name) @type_node',
135
142
  ];
@@ -433,7 +440,7 @@ async function loadLanguageLazy(entry: LanguageRegistryEntry): Promise<Parser |
433
440
  const isTS = entry.id === 'typescript' || entry.id === 'tsx';
434
441
  const patterns = isTS
435
442
  ? [...COMMON_QUERY_PATTERNS, ...TS_EXTRA_PATTERNS]
436
- : [...COMMON_QUERY_PATTERNS, JS_CLASS_PATTERN];
443
+ : [...COMMON_QUERY_PATTERNS, ...JS_CLASS_PATTERNS];
437
444
  _queries.set(entry.id, new Query(lang, patterns.join('\n')));
438
445
  }
439
446
  return parser;
@@ -818,6 +825,7 @@ function serializeExtractorOutput(
818
825
  ...(symbols.objectPropBindings?.length
819
826
  ? { objectPropBindings: symbols.objectPropBindings }
820
827
  : {}),
828
+ ...(symbols.thisCallBindings?.length ? { thisCallBindings: symbols.thisCallBindings } : {}),
821
829
  ...(symbols.newExpressions?.length ? { newExpressions: symbols.newExpressions } : {}),
822
830
  ...(symbols.definePropertyReceivers?.size
823
831
  ? { definePropertyReceivers: Array.from(symbols.definePropertyReceivers.entries()) }
@@ -826,6 +834,9 @@ function serializeExtractorOutput(
826
834
  ? { returnTypeMap: Array.from(symbols.returnTypeMap.entries()) }
827
835
  : {}),
828
836
  ...(symbols.callAssignments?.length ? { callAssignments: symbols.callAssignments } : {}),
837
+ ...(symbols.cjsRequireBindings?.length
838
+ ? { cjsRequireBindings: symbols.cjsRequireBindings }
839
+ : {}),
829
840
  };
830
841
  }
831
842
 
@@ -86,11 +86,14 @@ interface PendingJob {
86
86
  */
87
87
  const WORKER_PARSE_TIMEOUT_MS = 60_000;
88
88
 
89
- function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutput | null {
90
- if (!ser) return null;
89
+ /** Deserialize the core fields and metadata scalars from a serialized result. */
90
+ function deserializeCoreFields(
91
+ ser: SerializedExtractorOutput,
92
+ ): Pick<ExtractorOutput, 'definitions' | 'calls' | 'imports' | 'classes' | 'exports' | 'typeMap'> &
93
+ Partial<Pick<ExtractorOutput, '_langId' | '_lineCount' | 'dataflow' | 'astNodes'>> {
91
94
  const typeMap = new Map<string, TypeMapEntry>();
92
95
  for (const [k, v] of ser.typeMap) typeMap.set(k, v);
93
- const out: ExtractorOutput = {
96
+ const out: ReturnType<typeof deserializeCoreFields> = {
94
97
  definitions: ser.definitions,
95
98
  calls: ser.calls,
96
99
  imports: ser.imports,
@@ -106,6 +109,11 @@ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutp
106
109
  // {line, kind, name, text?, receiver?} shape — see engine.ts:822 where the
107
110
  // visitor output is cast the same way.
108
111
  if (ser.astNodes !== undefined) out.astNodes = ser.astNodes as unknown as ASTNodeRow[];
112
+ return out;
113
+ }
114
+
115
+ /** Deserialize the simple array binding fields (present when non-empty). */
116
+ function deserializeBindingFields(ser: SerializedExtractorOutput, out: ExtractorOutput): void {
109
117
  if (ser.fnRefBindings?.length) out.fnRefBindings = ser.fnRefBindings;
110
118
  if (ser.paramBindings?.length) out.paramBindings = ser.paramBindings;
111
119
  if (ser.arrayElemBindings?.length) out.arrayElemBindings = ser.arrayElemBindings;
@@ -115,7 +123,14 @@ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutp
115
123
  if (ser.objectRestParamBindings?.length)
116
124
  out.objectRestParamBindings = ser.objectRestParamBindings;
117
125
  if (ser.objectPropBindings?.length) out.objectPropBindings = ser.objectPropBindings;
126
+ if (ser.thisCallBindings?.length) out.thisCallBindings = ser.thisCallBindings;
118
127
  if (ser.newExpressions?.length) out.newExpressions = ser.newExpressions;
128
+ if (ser.callAssignments?.length) out.callAssignments = ser.callAssignments;
129
+ if (ser.cjsRequireBindings?.length) out.cjsRequireBindings = ser.cjsRequireBindings;
130
+ }
131
+
132
+ /** Deserialize the Map-typed fields that require entry-by-entry reconstruction. */
133
+ function deserializeMapFields(ser: SerializedExtractorOutput, out: ExtractorOutput): void {
119
134
  if (ser.definePropertyReceivers?.length) {
120
135
  const m = new Map<string, string>();
121
136
  for (const [k, v] of ser.definePropertyReceivers) m.set(k, v);
@@ -126,7 +141,17 @@ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutp
126
141
  for (const [k, v] of ser.returnTypeMap) returnTypeMap.set(k, v);
127
142
  out.returnTypeMap = returnTypeMap;
128
143
  }
129
- if (ser.callAssignments?.length) out.callAssignments = ser.callAssignments;
144
+ }
145
+
146
+ function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutput | null {
147
+ if (!ser) return null;
148
+ // deserializeCoreFields supplies all required ExtractorOutput fields (definitions,
149
+ // calls, imports, classes, exports, typeMap). The cast is safe: every required field
150
+ // is present in the returned Pick. If a new required field is added to ExtractorOutput,
151
+ // add it to deserializeCoreFields' return Pick and body to keep the cast honest.
152
+ const out = { ...deserializeCoreFields(ser) } as ExtractorOutput;
153
+ deserializeBindingFields(ser, out);
154
+ deserializeMapFields(ser, out);
130
155
  return out;
131
156
  }
132
157
 
@@ -71,11 +71,16 @@ export interface SerializedExtractorOutput {
71
71
  objectRestParamBindings?: import('../types.js').ObjectRestParamBinding[];
72
72
  objectPropBindings?: import('../types.js').ObjectPropBinding[];
73
73
  paramBindings?: import('../types.js').ParamBinding[];
74
+ thisCallBindings?: import('../types.js').ThisCallBinding[];
74
75
  newExpressions?: readonly string[];
75
76
  /** Serialized definePropertyReceivers map (funcName → receiverVarName) as tuple array. */
76
77
  definePropertyReceivers?: Array<[string, string]>;
77
78
  returnTypeMap?: Array<[string, TypeMapEntry]>;
78
79
  callAssignments?: CallAssignment[];
80
+ /** Variable-level dataflow vertices extracted during parsing (P1+). */
81
+ dataflowVertices?: import('../types.js').DataflowVertex[];
82
+ /** CJS require bindings — see ExtractorOutput.cjsRequireBindings (#1661). */
83
+ cjsRequireBindings?: Array<{ names: string[]; source: string }>;
79
84
  }
80
85
 
81
86
  export interface WorkerParseResponseOk {
@@ -5,7 +5,13 @@ import type {
5
5
  TreeSitterNode,
6
6
  TreeSitterTree,
7
7
  } from '../types.js';
8
- import { extractModifierVisibility, findChild, nodeEndLine } from './helpers.js';
8
+ import {
9
+ extractModifierVisibility,
10
+ findChild,
11
+ isCPrimitiveType,
12
+ nodeEndLine,
13
+ setTypeMapEntry,
14
+ } from './helpers.js';
9
15
 
10
16
  /**
11
17
  * Extract symbols from C++ files.
@@ -50,6 +56,9 @@ function walkCppNode(node: TreeSitterNode, ctx: ExtractorOutput): void {
50
56
  case 'call_expression':
51
57
  handleCppCallExpression(node, ctx);
52
58
  break;
59
+ case 'declaration':
60
+ handleCppDeclaration(node, ctx);
61
+ break;
53
62
  }
54
63
 
55
64
  for (let i = 0; i < node.childCount; i++) {
@@ -204,6 +213,40 @@ function handleCppInclude(node: TreeSitterNode, ctx: ExtractorOutput): void {
204
213
  });
205
214
  }
206
215
 
216
+ /**
217
+ * Seed typeMap for declaration-typed locals: `UserService svc;` and
218
+ * `UserService svc = makeService();` both yield typeMap["svc"] = "UserService"
219
+ * at confidence 0.9. Mirrors `match_c_family_type_map` ("declaration" branch)
220
+ * in the native Rust C++ extractor.
221
+ */
222
+ function handleCppDeclaration(node: TreeSitterNode, ctx: ExtractorOutput): void {
223
+ const typeNode = node.childForFieldName('type');
224
+ if (!typeNode) return;
225
+ const typeName = typeNode.text;
226
+ // Skip primitive types — they are never class/struct receivers
227
+ if (isCPrimitiveType(typeName)) return;
228
+ for (let i = 0; i < node.childCount; i++) {
229
+ const child = node.child(i);
230
+ if (!child) continue;
231
+ const kind = child.type;
232
+ let nameNode: TreeSitterNode | null = null;
233
+ if (kind === 'init_declarator') {
234
+ nameNode = child.childForFieldName('declarator') ?? null;
235
+ } else if (kind === 'identifier') {
236
+ nameNode = child;
237
+ }
238
+ // Note: pointer_declarator / reference_declarator children (e.g. `UserService *svc;`)
239
+ // are intentionally skipped here — they are also skipped by the native Rust
240
+ // match_c_family_type_map helper, which only handles 'init_declarator' and
241
+ // 'identifier' children. Both engines have the same scope for this case.
242
+ if (!nameNode) continue;
243
+ const varName = unwrapCppDeclaratorName(nameNode);
244
+ if (varName) {
245
+ setTypeMapEntry(ctx.typeMap, varName, typeName, 0.9);
246
+ }
247
+ }
248
+ }
249
+
207
250
  function handleCppCallExpression(node: TreeSitterNode, ctx: ExtractorOutput): void {
208
251
  const funcNode = node.childForFieldName('function');
209
252
  if (!funcNode) return;
@@ -5,7 +5,13 @@ import type {
5
5
  TreeSitterNode,
6
6
  TreeSitterTree,
7
7
  } from '../types.js';
8
- import { extractModifierVisibility, findChild, nodeEndLine } from './helpers.js';
8
+ import {
9
+ extractModifierVisibility,
10
+ findChild,
11
+ isCPrimitiveType,
12
+ nodeEndLine,
13
+ setTypeMapEntry,
14
+ } from './helpers.js';
9
15
 
10
16
  /**
11
17
  * Extract symbols from CUDA files.
@@ -63,6 +69,9 @@ function walkCudaNode(node: TreeSitterNode, ctx: ExtractorOutput): void {
63
69
  case 'call_expression':
64
70
  handleCudaCallExpression(node, ctx);
65
71
  break;
72
+ case 'declaration':
73
+ handleCudaDeclaration(node, ctx);
74
+ break;
66
75
  }
67
76
 
68
77
  for (let i = 0; i < node.childCount; i++) {
@@ -204,6 +213,40 @@ function handleCudaInclude(node: TreeSitterNode, ctx: ExtractorOutput): void {
204
213
  });
205
214
  }
206
215
 
216
+ /**
217
+ * Seed typeMap for declaration-typed locals: `UserService svc;` and
218
+ * `UserService svc = make();` both yield typeMap["svc"] = "UserService"
219
+ * at confidence 0.9. Mirrors `match_c_family_type_map` ("declaration" branch)
220
+ * in the native Rust CUDA extractor.
221
+ */
222
+ function handleCudaDeclaration(node: TreeSitterNode, ctx: ExtractorOutput): void {
223
+ const typeNode = node.childForFieldName('type');
224
+ if (!typeNode) return;
225
+ const typeName = typeNode.text;
226
+ // Skip primitive types — they are never class/struct receivers
227
+ if (isCPrimitiveType(typeName)) return;
228
+ for (let i = 0; i < node.childCount; i++) {
229
+ const child = node.child(i);
230
+ if (!child) continue;
231
+ const kind = child.type;
232
+ let nameNode: TreeSitterNode | null = null;
233
+ if (kind === 'init_declarator') {
234
+ nameNode = child.childForFieldName('declarator') ?? null;
235
+ } else if (kind === 'identifier') {
236
+ nameNode = child;
237
+ }
238
+ // Note: pointer_declarator / reference_declarator children (e.g. `UserService *svc;`)
239
+ // are intentionally skipped here — they are also skipped by the native Rust
240
+ // match_c_family_type_map helper, which only handles 'init_declarator' and
241
+ // 'identifier' children. Both engines have the same scope for this case.
242
+ if (!nameNode) continue;
243
+ const varName = extractCudaFieldName(nameNode);
244
+ if (varName) {
245
+ setTypeMapEntry(ctx.typeMap, varName, typeName, 0.9);
246
+ }
247
+ }
248
+ }
249
+
207
250
  function handleCudaCallExpression(node: TreeSitterNode, ctx: ExtractorOutput): void {
208
251
  const funcNode = node.childForFieldName('function');
209
252
  if (!funcNode) return;
@@ -255,14 +255,59 @@ function handleDartSelector(node: TreeSitterNode, ctx: ExtractorOutput): void {
255
255
  const argPart = findChild(node, 'argument_part');
256
256
  if (!argPart) return;
257
257
 
258
- // Look for the identifier this selector belongs to
258
+ const line = node.startPosition.row + 1;
259
+
260
+ // Look for the identifier this selector belongs to.
261
+ // Two layouts are possible depending on grammar version:
262
+ // A) selector has both unconditional_assignable_selector + argument_part (same node)
263
+ // B) one selector node holds unconditional_assignable_selector (.method),
264
+ // the next holds argument_part (the call args) — method name is in the previous sibling
259
265
  const unconditional = findChild(node, 'unconditional_assignable_selector');
266
+ let methodName: string | null = null;
267
+
260
268
  if (unconditional) {
261
269
  const id = findChild(unconditional, 'identifier');
262
- if (id) {
263
- ctx.calls.push({ name: id.text, line: node.startPosition.row + 1 });
270
+ if (id) methodName = id.text;
271
+ } else {
272
+ // Layout B: look at the previous sibling selector for the method name
273
+ const parent = node.parent;
274
+ if (parent) {
275
+ for (let i = 0; i < parent.childCount; i++) {
276
+ const sibling = parent.child(i);
277
+ if (sibling === node) break;
278
+ if (sibling?.type === 'selector') {
279
+ const unc2 = findChild(sibling, 'unconditional_assignable_selector');
280
+ if (unc2) {
281
+ const id2 = findChild(unc2, 'identifier');
282
+ if (id2) methodName = id2.text;
283
+ }
284
+ }
285
+ }
264
286
  }
265
287
  }
288
+
289
+ if (!methodName) return;
290
+
291
+ // Function.apply(fn, positionalArgs, namedArgs) — dynamic higher-order dispatch
292
+ if (methodName === 'apply') {
293
+ const parent = node.parent;
294
+ if (parent) {
295
+ for (let i = 0; i < parent.childCount; i++) {
296
+ const sibling = parent.child(i);
297
+ if (sibling && sibling !== node && sibling.text === 'Function') {
298
+ ctx.calls.push({
299
+ name: '<dynamic:unresolved>',
300
+ line,
301
+ dynamic: true,
302
+ dynamicKind: 'unresolved-dynamic',
303
+ });
304
+ return;
305
+ }
306
+ }
307
+ }
308
+ }
309
+
310
+ ctx.calls.push({ name: methodName, line });
266
311
  }
267
312
 
268
313
  function handleDartTypeAlias(node: TreeSitterNode, ctx: ExtractorOutput): void {
@@ -292,8 +292,26 @@ function handleGroovyImport(node: TreeSitterNode, ctx: ExtractorOutput): void {
292
292
  }
293
293
  }
294
294
 
295
+ /** Extract the first string literal argument from a Groovy call node. */
296
+ function getFirstStringArgGroovy(node: TreeSitterNode): string | null {
297
+ const args = node.childForFieldName('arguments') || findChild(node, 'argument_list');
298
+ if (!args) return null;
299
+ for (let i = 0; i < args.childCount; i++) {
300
+ const child = args.child(i);
301
+ if (!child) continue;
302
+ const t = child.type;
303
+ if (t === '(' || t === ')' || t === ',') continue;
304
+ if (t === 'string' || t === 'string_literal' || t === 'string_fragment') {
305
+ return child.text.replace(/^["']|["']$/g, '');
306
+ }
307
+ break;
308
+ }
309
+ return null;
310
+ }
311
+
295
312
  function handleGroovyCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void {
296
313
  const call: Call = { name: '', line: node.startPosition.row + 1 };
314
+ let fieldNode: TreeSitterNode | null = null;
297
315
 
298
316
  // Try standard call_expression pattern
299
317
  const funcNode = node.childForFieldName('function') || node.childForFieldName('method');
@@ -301,7 +319,10 @@ function handleGroovyCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void
301
319
  if (funcNode.type === 'field_expression' || funcNode.type === 'member_access') {
302
320
  const field = funcNode.childForFieldName('field') || funcNode.childForFieldName('property');
303
321
  const obj = funcNode.childForFieldName('argument') || funcNode.childForFieldName('object');
304
- if (field) call.name = field.text;
322
+ if (field) {
323
+ fieldNode = field;
324
+ call.name = field.text;
325
+ }
305
326
  if (obj) call.receiver = obj.text;
306
327
  } else {
307
328
  call.name = funcNode.text;
@@ -311,12 +332,51 @@ function handleGroovyCallExpr(node: TreeSitterNode, ctx: ExtractorOutput): void
311
332
  const nameNode = node.childForFieldName('name');
312
333
  const obj = node.childForFieldName('object');
313
334
  if (nameNode) {
335
+ fieldNode = nameNode;
314
336
  call.name = nameNode.text;
315
337
  if (obj) call.receiver = obj.text;
316
338
  }
317
339
  }
318
340
 
319
- if (call.name) ctx.calls.push(call);
341
+ if (!call.name) return;
342
+
343
+ // obj."$dyn"() or obj."${var}"() — GString method name; cannot resolve statically
344
+ if (fieldNode && (fieldNode.type === 'gstring' || fieldNode.type === 'template_string')) {
345
+ ctx.calls.push({
346
+ name: '<dynamic:unresolved>',
347
+ line: call.line,
348
+ dynamic: true,
349
+ dynamicKind: 'unresolved-dynamic',
350
+ receiver: call.receiver,
351
+ });
352
+ return;
353
+ }
354
+
355
+ // obj.invokeMethod("name", args) — Groovy's explicit dynamic dispatch
356
+ if (call.name === 'invokeMethod') {
357
+ const literal = getFirstStringArgGroovy(node);
358
+ if (literal) {
359
+ ctx.calls.push({
360
+ name: literal,
361
+ line: call.line,
362
+ dynamic: true,
363
+ dynamicKind: 'reflection',
364
+ keyExpr: literal,
365
+ receiver: call.receiver,
366
+ });
367
+ } else {
368
+ ctx.calls.push({
369
+ name: '<dynamic:computed-key>',
370
+ line: call.line,
371
+ dynamic: true,
372
+ dynamicKind: 'computed-key',
373
+ receiver: call.receiver,
374
+ });
375
+ }
376
+ return;
377
+ }
378
+
379
+ ctx.calls.push(call);
320
380
  }
321
381
 
322
382
  function handleGroovyObjectCreation(node: TreeSitterNode, ctx: ExtractorOutput): void {
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  Call,
3
+ DynamicKind,
3
4
  ExtractorOutput,
4
5
  Import,
5
6
  SubDeclaration,
@@ -270,18 +271,20 @@ export function extractModifierVisibility(
270
271
 
271
272
  /**
272
273
  * Append a `Call` to the extractor output. `line` defaults to the start line of
273
- * `node`; pass `extra` for `receiver` / `dynamic` flags.
274
+ * `node`; pass `extra` for `receiver` / `dynamic` / `dynamicKind` / `keyExpr` fields.
274
275
  */
275
276
  export function pushCall(
276
277
  ctx: ExtractorOutput,
277
278
  node: TreeSitterNode,
278
279
  name: string,
279
- extra: { receiver?: string; dynamic?: boolean } = {},
280
+ extra: { receiver?: string; dynamic?: boolean; dynamicKind?: DynamicKind; keyExpr?: string } = {},
280
281
  ): void {
281
282
  if (!name) return;
282
283
  const call: Call = { name, line: nodeStartLine(node) };
283
284
  if (extra.receiver !== undefined) call.receiver = extra.receiver;
284
285
  if (extra.dynamic !== undefined) call.dynamic = extra.dynamic;
286
+ if (extra.dynamicKind !== undefined) call.dynamicKind = extra.dynamicKind;
287
+ if (extra.keyExpr !== undefined) call.keyExpr = extra.keyExpr;
285
288
  ctx.calls.push(call);
286
289
  }
287
290
 
@@ -305,6 +308,49 @@ export function pushImport(
305
308
  ctx.imports.push(entry);
306
309
  }
307
310
 
311
+ // ── C-family primitive types ───────────────────────────────────────────────
312
+
313
+ /**
314
+ * Primitive C/C++/CUDA types that are never class/struct receivers. Seeding
315
+ * these into typeMap would produce spurious receiver edges (e.g. `int x` → `int`).
316
+ * Shared between the C++ and CUDA extractors to prevent divergence.
317
+ */
318
+ export const C_PRIMITIVE_TYPES: ReadonlySet<string> = new Set([
319
+ 'int',
320
+ 'long',
321
+ 'short',
322
+ 'unsigned',
323
+ 'signed',
324
+ 'float',
325
+ 'double',
326
+ 'char',
327
+ 'bool',
328
+ 'void',
329
+ 'wchar_t',
330
+ 'auto',
331
+ 'size_t',
332
+ 'uint8_t',
333
+ 'uint16_t',
334
+ 'uint32_t',
335
+ 'uint64_t',
336
+ 'int8_t',
337
+ 'int16_t',
338
+ 'int32_t',
339
+ 'int64_t',
340
+ 'ptrdiff_t',
341
+ 'intptr_t',
342
+ 'uintptr_t',
343
+ ]);
344
+
345
+ /**
346
+ * Return true when `typeName` is a primitive C/C++/CUDA type.
347
+ * Strips leading qualifiers (`const int` → `int`) before checking.
348
+ */
349
+ export function isCPrimitiveType(typeName: string): boolean {
350
+ const base = typeName.split(/\s+/).pop() ?? typeName;
351
+ return C_PRIMITIVE_TYPES.has(base) || C_PRIMITIVE_TYPES.has(typeName);
352
+ }
353
+
308
354
  // ── Parameter extraction ───────────────────────────────────────────────────
309
355
 
310
356
  /**