@optave/codegraph 3.13.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 (458) hide show
  1. package/README.md +35 -34
  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/config.d.ts.map +1 -1
  51. package/dist/cli/commands/config.js +137 -134
  52. package/dist/cli/commands/config.js.map +1 -1
  53. package/dist/cli/commands/roles.d.ts.map +1 -1
  54. package/dist/cli/commands/roles.js +6 -1
  55. package/dist/cli/commands/roles.js.map +1 -1
  56. package/dist/db/better-sqlite3.d.ts +2 -1
  57. package/dist/db/better-sqlite3.d.ts.map +1 -1
  58. package/dist/db/better-sqlite3.js.map +1 -1
  59. package/dist/db/connection.d.ts +7 -1
  60. package/dist/db/connection.d.ts.map +1 -1
  61. package/dist/db/connection.js +20 -5
  62. package/dist/db/connection.js.map +1 -1
  63. package/dist/db/index.d.ts +1 -1
  64. package/dist/db/index.d.ts.map +1 -1
  65. package/dist/db/index.js +1 -1
  66. package/dist/db/index.js.map +1 -1
  67. package/dist/db/migrations.d.ts.map +1 -1
  68. package/dist/db/migrations.js +68 -0
  69. package/dist/db/migrations.js.map +1 -1
  70. package/dist/db/repository/build-stmts.d.ts.map +1 -1
  71. package/dist/db/repository/build-stmts.js +18 -0
  72. package/dist/db/repository/build-stmts.js.map +1 -1
  73. package/dist/db/repository/dataflow.d.ts +5 -0
  74. package/dist/db/repository/dataflow.d.ts.map +1 -1
  75. package/dist/db/repository/dataflow.js +14 -0
  76. package/dist/db/repository/dataflow.js.map +1 -1
  77. package/dist/db/repository/index.d.ts +1 -1
  78. package/dist/db/repository/index.d.ts.map +1 -1
  79. package/dist/db/repository/index.js +1 -1
  80. package/dist/db/repository/index.js.map +1 -1
  81. package/dist/db/repository/native-repository.d.ts.map +1 -1
  82. package/dist/db/repository/native-repository.js +47 -34
  83. package/dist/db/repository/native-repository.js.map +1 -1
  84. package/dist/domain/analysis/context.d.ts +2 -2
  85. package/dist/domain/analysis/dependencies.d.ts +2 -2
  86. package/dist/domain/analysis/diff-impact.d.ts +2 -2
  87. package/dist/domain/analysis/fn-impact.d.ts +3 -1
  88. package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
  89. package/dist/domain/analysis/fn-impact.js +4 -0
  90. package/dist/domain/analysis/fn-impact.js.map +1 -1
  91. package/dist/domain/analysis/implementations.d.ts +2 -2
  92. package/dist/domain/analysis/module-map.d.ts.map +1 -1
  93. package/dist/domain/analysis/module-map.js +32 -5
  94. package/dist/domain/analysis/module-map.js.map +1 -1
  95. package/dist/domain/analysis/roles.d.ts +7 -1
  96. package/dist/domain/analysis/roles.d.ts.map +1 -1
  97. package/dist/domain/analysis/roles.js +16 -0
  98. package/dist/domain/analysis/roles.js.map +1 -1
  99. package/dist/domain/analysis/symbol-lookup.d.ts +4 -4
  100. package/dist/domain/graph/builder/call-resolver.d.ts +17 -5
  101. package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
  102. package/dist/domain/graph/builder/call-resolver.js +85 -220
  103. package/dist/domain/graph/builder/call-resolver.js.map +1 -1
  104. package/dist/domain/graph/builder/context.d.ts +1 -0
  105. package/dist/domain/graph/builder/context.d.ts.map +1 -1
  106. package/dist/domain/graph/builder/context.js.map +1 -1
  107. package/dist/domain/graph/builder/helpers.d.ts +16 -1
  108. package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
  109. package/dist/domain/graph/builder/helpers.js +162 -72
  110. package/dist/domain/graph/builder/helpers.js.map +1 -1
  111. package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
  112. package/dist/domain/graph/builder/incremental.js +166 -97
  113. package/dist/domain/graph/builder/incremental.js.map +1 -1
  114. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
  115. package/dist/domain/graph/builder/pipeline.js +10 -4
  116. package/dist/domain/graph/builder/pipeline.js.map +1 -1
  117. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
  118. package/dist/domain/graph/builder/stages/build-edges.js +496 -250
  119. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
  120. package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
  121. package/dist/domain/graph/builder/stages/collect-files.js +10 -7
  122. package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
  123. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
  124. package/dist/domain/graph/builder/stages/detect-changes.js +2 -1
  125. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
  126. package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
  127. package/dist/domain/graph/builder/stages/native-orchestrator.js +895 -545
  128. package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
  129. package/dist/domain/graph/resolver/points-to.d.ts.map +1 -1
  130. package/dist/domain/graph/resolver/points-to.js +105 -57
  131. package/dist/domain/graph/resolver/points-to.js.map +1 -1
  132. package/dist/domain/graph/resolver/strategy.d.ts +61 -0
  133. package/dist/domain/graph/resolver/strategy.d.ts.map +1 -0
  134. package/dist/domain/graph/resolver/strategy.js +222 -0
  135. package/dist/domain/graph/resolver/strategy.js.map +1 -0
  136. package/dist/domain/graph/watcher.d.ts.map +1 -1
  137. package/dist/domain/graph/watcher.js +16 -9
  138. package/dist/domain/graph/watcher.js.map +1 -1
  139. package/dist/domain/parser.d.ts +12 -0
  140. package/dist/domain/parser.d.ts.map +1 -1
  141. package/dist/domain/parser.js +12 -2
  142. package/dist/domain/parser.js.map +1 -1
  143. package/dist/domain/queries.d.ts +1 -1
  144. package/dist/domain/queries.d.ts.map +1 -1
  145. package/dist/domain/queries.js +1 -1
  146. package/dist/domain/queries.js.map +1 -1
  147. package/dist/domain/wasm-worker-entry.js +3 -0
  148. package/dist/domain/wasm-worker-entry.js.map +1 -1
  149. package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
  150. package/dist/domain/wasm-worker-pool.js +24 -5
  151. package/dist/domain/wasm-worker-pool.js.map +1 -1
  152. package/dist/domain/wasm-worker-protocol.d.ts +7 -0
  153. package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
  154. package/dist/extractors/dart.js +48 -3
  155. package/dist/extractors/dart.js.map +1 -1
  156. package/dist/extractors/groovy.js +62 -3
  157. package/dist/extractors/groovy.js.map +1 -1
  158. package/dist/extractors/helpers.d.ts +4 -2
  159. package/dist/extractors/helpers.d.ts.map +1 -1
  160. package/dist/extractors/helpers.js +5 -1
  161. package/dist/extractors/helpers.js.map +1 -1
  162. package/dist/extractors/java.js +77 -1
  163. package/dist/extractors/java.js.map +1 -1
  164. package/dist/extractors/javascript.d.ts.map +1 -1
  165. package/dist/extractors/javascript.js +549 -163
  166. package/dist/extractors/javascript.js.map +1 -1
  167. package/dist/extractors/kotlin.js +58 -3
  168. package/dist/extractors/kotlin.js.map +1 -1
  169. package/dist/extractors/objc.js +25 -2
  170. package/dist/extractors/objc.js.map +1 -1
  171. package/dist/extractors/scala.js +62 -2
  172. package/dist/extractors/scala.js.map +1 -1
  173. package/dist/extractors/swift.js +52 -3
  174. package/dist/extractors/swift.js.map +1 -1
  175. package/dist/features/audit.js +26 -23
  176. package/dist/features/audit.js.map +1 -1
  177. package/dist/features/boundaries.d.ts.map +1 -1
  178. package/dist/features/boundaries.js +12 -9
  179. package/dist/features/boundaries.js.map +1 -1
  180. package/dist/features/cfg.d.ts.map +1 -1
  181. package/dist/features/cfg.js +25 -18
  182. package/dist/features/cfg.js.map +1 -1
  183. package/dist/features/check.d.ts.map +1 -1
  184. package/dist/features/check.js +18 -5
  185. package/dist/features/check.js.map +1 -1
  186. package/dist/features/communities.d.ts +4 -2
  187. package/dist/features/communities.d.ts.map +1 -1
  188. package/dist/features/communities.js +6 -4
  189. package/dist/features/communities.js.map +1 -1
  190. package/dist/features/dataflow.d.ts +60 -0
  191. package/dist/features/dataflow.d.ts.map +1 -1
  192. package/dist/features/dataflow.js +530 -6
  193. package/dist/features/dataflow.js.map +1 -1
  194. package/dist/features/manifesto.d.ts.map +1 -1
  195. package/dist/features/manifesto.js +59 -72
  196. package/dist/features/manifesto.js.map +1 -1
  197. package/dist/features/sequence.d.ts.map +1 -1
  198. package/dist/features/sequence.js +27 -22
  199. package/dist/features/sequence.js.map +1 -1
  200. package/dist/features/snapshot.d.ts.map +1 -1
  201. package/dist/features/snapshot.js +36 -28
  202. package/dist/features/snapshot.js.map +1 -1
  203. package/dist/features/structure.d.ts.map +1 -1
  204. package/dist/features/structure.js +150 -62
  205. package/dist/features/structure.js.map +1 -1
  206. package/dist/features/triage.d.ts.map +1 -1
  207. package/dist/features/triage.js +18 -11
  208. package/dist/features/triage.js.map +1 -1
  209. package/dist/graph/algorithms/bfs.d.ts +1 -1
  210. package/dist/graph/algorithms/bfs.d.ts.map +1 -1
  211. package/dist/graph/algorithms/bfs.js +14 -13
  212. package/dist/graph/algorithms/bfs.js.map +1 -1
  213. package/dist/graph/algorithms/tarjan.d.ts.map +1 -1
  214. package/dist/graph/algorithms/tarjan.js +5 -0
  215. package/dist/graph/algorithms/tarjan.js.map +1 -1
  216. package/dist/graph/builders/dependency.js +28 -22
  217. package/dist/graph/builders/dependency.js.map +1 -1
  218. package/dist/graph/classifiers/roles.d.ts +10 -1
  219. package/dist/graph/classifiers/roles.d.ts.map +1 -1
  220. package/dist/graph/classifiers/roles.js +60 -6
  221. package/dist/graph/classifiers/roles.js.map +1 -1
  222. package/dist/infrastructure/config.d.ts +10 -0
  223. package/dist/infrastructure/config.d.ts.map +1 -1
  224. package/dist/infrastructure/config.js +31 -3
  225. package/dist/infrastructure/config.js.map +1 -1
  226. package/dist/infrastructure/registry.d.ts +0 -7
  227. package/dist/infrastructure/registry.d.ts.map +1 -1
  228. package/dist/infrastructure/registry.js +29 -13
  229. package/dist/infrastructure/registry.js.map +1 -1
  230. package/dist/infrastructure/update-check.d.ts.map +1 -1
  231. package/dist/infrastructure/update-check.js +49 -31
  232. package/dist/infrastructure/update-check.js.map +1 -1
  233. package/dist/mcp/server.d.ts +2 -10
  234. package/dist/mcp/server.d.ts.map +1 -1
  235. package/dist/mcp/server.js.map +1 -1
  236. package/dist/mcp/tools/ast-query.d.ts +1 -1
  237. package/dist/mcp/tools/ast-query.d.ts.map +1 -1
  238. package/dist/mcp/tools/audit.d.ts +1 -1
  239. package/dist/mcp/tools/audit.d.ts.map +1 -1
  240. package/dist/mcp/tools/batch-query.d.ts +1 -1
  241. package/dist/mcp/tools/batch-query.d.ts.map +1 -1
  242. package/dist/mcp/tools/branch-compare.d.ts +1 -1
  243. package/dist/mcp/tools/branch-compare.d.ts.map +1 -1
  244. package/dist/mcp/tools/brief.d.ts +1 -1
  245. package/dist/mcp/tools/brief.d.ts.map +1 -1
  246. package/dist/mcp/tools/cfg.d.ts +1 -1
  247. package/dist/mcp/tools/cfg.d.ts.map +1 -1
  248. package/dist/mcp/tools/check.d.ts +1 -1
  249. package/dist/mcp/tools/check.d.ts.map +1 -1
  250. package/dist/mcp/tools/co-changes.d.ts +1 -1
  251. package/dist/mcp/tools/co-changes.d.ts.map +1 -1
  252. package/dist/mcp/tools/code-owners.d.ts +1 -1
  253. package/dist/mcp/tools/code-owners.d.ts.map +1 -1
  254. package/dist/mcp/tools/communities.d.ts +1 -1
  255. package/dist/mcp/tools/communities.d.ts.map +1 -1
  256. package/dist/mcp/tools/complexity.d.ts +1 -1
  257. package/dist/mcp/tools/complexity.d.ts.map +1 -1
  258. package/dist/mcp/tools/context.d.ts +1 -1
  259. package/dist/mcp/tools/context.d.ts.map +1 -1
  260. package/dist/mcp/tools/dataflow.d.ts +1 -1
  261. package/dist/mcp/tools/dataflow.d.ts.map +1 -1
  262. package/dist/mcp/tools/diff-impact.d.ts +1 -1
  263. package/dist/mcp/tools/diff-impact.d.ts.map +1 -1
  264. package/dist/mcp/tools/execution-flow.d.ts +1 -1
  265. package/dist/mcp/tools/execution-flow.d.ts.map +1 -1
  266. package/dist/mcp/tools/export-graph.d.ts +1 -1
  267. package/dist/mcp/tools/export-graph.d.ts.map +1 -1
  268. package/dist/mcp/tools/file-deps.d.ts +1 -1
  269. package/dist/mcp/tools/file-deps.d.ts.map +1 -1
  270. package/dist/mcp/tools/file-exports.d.ts +1 -1
  271. package/dist/mcp/tools/file-exports.d.ts.map +1 -1
  272. package/dist/mcp/tools/find-cycles.d.ts +1 -1
  273. package/dist/mcp/tools/find-cycles.d.ts.map +1 -1
  274. package/dist/mcp/tools/fn-impact.d.ts +1 -1
  275. package/dist/mcp/tools/fn-impact.d.ts.map +1 -1
  276. package/dist/mcp/tools/impact-analysis.d.ts +1 -1
  277. package/dist/mcp/tools/impact-analysis.d.ts.map +1 -1
  278. package/dist/mcp/tools/implementations.d.ts +1 -1
  279. package/dist/mcp/tools/implementations.d.ts.map +1 -1
  280. package/dist/mcp/tools/index.d.ts +2 -5
  281. package/dist/mcp/tools/index.d.ts.map +1 -1
  282. package/dist/mcp/tools/index.js.map +1 -1
  283. package/dist/mcp/tools/interfaces.d.ts +1 -1
  284. package/dist/mcp/tools/interfaces.d.ts.map +1 -1
  285. package/dist/mcp/tools/list-functions.d.ts +1 -1
  286. package/dist/mcp/tools/list-functions.d.ts.map +1 -1
  287. package/dist/mcp/tools/list-repos.d.ts +1 -1
  288. package/dist/mcp/tools/list-repos.d.ts.map +1 -1
  289. package/dist/mcp/tools/module-map.d.ts +1 -1
  290. package/dist/mcp/tools/module-map.d.ts.map +1 -1
  291. package/dist/mcp/tools/node-roles.d.ts +1 -1
  292. package/dist/mcp/tools/node-roles.d.ts.map +1 -1
  293. package/dist/mcp/tools/path.d.ts +1 -1
  294. package/dist/mcp/tools/path.d.ts.map +1 -1
  295. package/dist/mcp/tools/query.d.ts +1 -1
  296. package/dist/mcp/tools/query.d.ts.map +1 -1
  297. package/dist/mcp/tools/semantic-search.d.ts +1 -1
  298. package/dist/mcp/tools/semantic-search.d.ts.map +1 -1
  299. package/dist/mcp/tools/sequence.d.ts +1 -1
  300. package/dist/mcp/tools/sequence.d.ts.map +1 -1
  301. package/dist/mcp/tools/structure.d.ts +1 -1
  302. package/dist/mcp/tools/structure.d.ts.map +1 -1
  303. package/dist/mcp/tools/symbol-children.d.ts +1 -1
  304. package/dist/mcp/tools/symbol-children.d.ts.map +1 -1
  305. package/dist/mcp/tools/triage.d.ts +1 -1
  306. package/dist/mcp/tools/triage.d.ts.map +1 -1
  307. package/dist/mcp/tools/where.d.ts +1 -1
  308. package/dist/mcp/tools/where.d.ts.map +1 -1
  309. package/dist/mcp/types.d.ts +19 -0
  310. package/dist/mcp/types.d.ts.map +1 -0
  311. package/dist/mcp/types.js +6 -0
  312. package/dist/mcp/types.js.map +1 -0
  313. package/dist/presentation/queries-cli/index.d.ts +1 -1
  314. package/dist/presentation/queries-cli/index.d.ts.map +1 -1
  315. package/dist/presentation/queries-cli/index.js +1 -1
  316. package/dist/presentation/queries-cli/index.js.map +1 -1
  317. package/dist/presentation/queries-cli/overview.d.ts +1 -0
  318. package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
  319. package/dist/presentation/queries-cli/overview.js +20 -1
  320. package/dist/presentation/queries-cli/overview.js.map +1 -1
  321. package/dist/presentation/queries-cli.d.ts +1 -1
  322. package/dist/presentation/queries-cli.d.ts.map +1 -1
  323. package/dist/presentation/queries-cli.js +1 -1
  324. package/dist/presentation/queries-cli.js.map +1 -1
  325. package/dist/presentation/viewer.d.ts.map +1 -1
  326. package/dist/presentation/viewer.js +45 -32
  327. package/dist/presentation/viewer.js.map +1 -1
  328. package/dist/shared/constants.d.ts +21 -0
  329. package/dist/shared/constants.d.ts.map +1 -1
  330. package/dist/shared/constants.js +25 -0
  331. package/dist/shared/constants.js.map +1 -1
  332. package/dist/shared/normalize.d.ts.map +1 -1
  333. package/dist/shared/normalize.js +12 -22
  334. package/dist/shared/normalize.js.map +1 -1
  335. package/dist/shared/paginate.d.ts +4 -17
  336. package/dist/shared/paginate.d.ts.map +1 -1
  337. package/dist/shared/paginate.js.map +1 -1
  338. package/dist/types.d.ts +76 -1
  339. package/dist/types.d.ts.map +1 -1
  340. package/grammars/tree-sitter-erlang.wasm +0 -0
  341. package/package.json +7 -7
  342. package/src/ast-analysis/engine.ts +43 -63
  343. package/src/ast-analysis/rules/b2.ts +263 -0
  344. package/src/ast-analysis/rules/b3.ts +127 -0
  345. package/src/ast-analysis/rules/b4.ts +378 -0
  346. package/src/ast-analysis/rules/b5.ts +65 -0
  347. package/src/ast-analysis/rules/c.ts +157 -0
  348. package/src/ast-analysis/rules/index.ts +34 -0
  349. package/src/ast-analysis/rules/javascript.ts +3 -0
  350. package/src/ast-analysis/shared.ts +2 -0
  351. package/src/ast-analysis/visitor-utils.ts +5 -0
  352. package/src/ast-analysis/visitor.ts +82 -52
  353. package/src/ast-analysis/visitors/cfg-visitor.ts +198 -84
  354. package/src/ast-analysis/visitors/complexity-visitor.ts +44 -16
  355. package/src/ast-analysis/visitors/dataflow-visitor.ts +68 -29
  356. package/src/cli/commands/config.ts +184 -184
  357. package/src/cli/commands/roles.ts +6 -1
  358. package/src/db/better-sqlite3.ts +5 -4
  359. package/src/db/connection.ts +23 -5
  360. package/src/db/index.ts +1 -0
  361. package/src/db/migrations.ts +68 -0
  362. package/src/db/repository/build-stmts.ts +30 -0
  363. package/src/db/repository/dataflow.ts +16 -0
  364. package/src/db/repository/index.ts +1 -1
  365. package/src/db/repository/native-repository.ts +56 -40
  366. package/src/domain/analysis/fn-impact.ts +4 -0
  367. package/src/domain/analysis/module-map.ts +38 -6
  368. package/src/domain/analysis/roles.ts +23 -0
  369. package/src/domain/graph/builder/call-resolver.ts +112 -232
  370. package/src/domain/graph/builder/context.ts +1 -0
  371. package/src/domain/graph/builder/helpers.ts +190 -72
  372. package/src/domain/graph/builder/incremental.ts +249 -120
  373. package/src/domain/graph/builder/pipeline.ts +11 -5
  374. package/src/domain/graph/builder/stages/build-edges.ts +696 -296
  375. package/src/domain/graph/builder/stages/collect-files.ts +12 -6
  376. package/src/domain/graph/builder/stages/detect-changes.ts +3 -1
  377. package/src/domain/graph/builder/stages/native-orchestrator.ts +1102 -590
  378. package/src/domain/graph/resolver/points-to.ts +182 -59
  379. package/src/domain/graph/resolver/strategy.ts +265 -0
  380. package/src/domain/graph/watcher.ts +19 -9
  381. package/src/domain/parser.ts +12 -2
  382. package/src/domain/queries.ts +1 -1
  383. package/src/domain/wasm-worker-entry.ts +3 -0
  384. package/src/domain/wasm-worker-pool.ts +28 -4
  385. package/src/domain/wasm-worker-protocol.ts +4 -0
  386. package/src/extractors/dart.ts +48 -3
  387. package/src/extractors/groovy.ts +62 -2
  388. package/src/extractors/helpers.ts +5 -2
  389. package/src/extractors/java.ts +80 -1
  390. package/src/extractors/javascript.ts +566 -161
  391. package/src/extractors/kotlin.ts +57 -3
  392. package/src/extractors/objc.ts +25 -1
  393. package/src/extractors/scala.ts +63 -1
  394. package/src/extractors/swift.ts +46 -3
  395. package/src/features/audit.ts +43 -34
  396. package/src/features/boundaries.ts +17 -9
  397. package/src/features/cfg.ts +31 -22
  398. package/src/features/check.ts +21 -5
  399. package/src/features/communities.ts +28 -19
  400. package/src/features/dataflow.ts +755 -6
  401. package/src/features/manifesto.ts +76 -75
  402. package/src/features/sequence.ts +29 -23
  403. package/src/features/snapshot.ts +36 -25
  404. package/src/features/structure.ts +185 -55
  405. package/src/features/triage.ts +28 -15
  406. package/src/graph/algorithms/bfs.ts +13 -12
  407. package/src/graph/algorithms/tarjan.ts +5 -0
  408. package/src/graph/builders/dependency.ts +35 -23
  409. package/src/graph/classifiers/roles.ts +74 -7
  410. package/src/infrastructure/config.ts +32 -3
  411. package/src/infrastructure/registry.ts +44 -20
  412. package/src/infrastructure/update-check.ts +55 -33
  413. package/src/mcp/server.ts +2 -8
  414. package/src/mcp/tools/ast-query.ts +1 -1
  415. package/src/mcp/tools/audit.ts +1 -1
  416. package/src/mcp/tools/batch-query.ts +1 -1
  417. package/src/mcp/tools/branch-compare.ts +1 -1
  418. package/src/mcp/tools/brief.ts +1 -1
  419. package/src/mcp/tools/cfg.ts +1 -1
  420. package/src/mcp/tools/check.ts +1 -1
  421. package/src/mcp/tools/co-changes.ts +1 -1
  422. package/src/mcp/tools/code-owners.ts +1 -1
  423. package/src/mcp/tools/communities.ts +1 -1
  424. package/src/mcp/tools/complexity.ts +1 -1
  425. package/src/mcp/tools/context.ts +1 -1
  426. package/src/mcp/tools/dataflow.ts +1 -1
  427. package/src/mcp/tools/diff-impact.ts +1 -1
  428. package/src/mcp/tools/execution-flow.ts +1 -1
  429. package/src/mcp/tools/export-graph.ts +1 -1
  430. package/src/mcp/tools/file-deps.ts +1 -1
  431. package/src/mcp/tools/file-exports.ts +1 -1
  432. package/src/mcp/tools/find-cycles.ts +1 -1
  433. package/src/mcp/tools/fn-impact.ts +1 -1
  434. package/src/mcp/tools/impact-analysis.ts +1 -1
  435. package/src/mcp/tools/implementations.ts +1 -1
  436. package/src/mcp/tools/index.ts +2 -5
  437. package/src/mcp/tools/interfaces.ts +1 -1
  438. package/src/mcp/tools/list-functions.ts +1 -1
  439. package/src/mcp/tools/list-repos.ts +1 -1
  440. package/src/mcp/tools/module-map.ts +1 -1
  441. package/src/mcp/tools/node-roles.ts +1 -1
  442. package/src/mcp/tools/path.ts +1 -1
  443. package/src/mcp/tools/query.ts +1 -1
  444. package/src/mcp/tools/semantic-search.ts +1 -1
  445. package/src/mcp/tools/sequence.ts +1 -1
  446. package/src/mcp/tools/structure.ts +1 -1
  447. package/src/mcp/tools/symbol-children.ts +1 -1
  448. package/src/mcp/tools/triage.ts +1 -1
  449. package/src/mcp/tools/where.ts +1 -1
  450. package/src/mcp/types.ts +21 -0
  451. package/src/presentation/queries-cli/index.ts +1 -1
  452. package/src/presentation/queries-cli/overview.ts +35 -1
  453. package/src/presentation/queries-cli.ts +1 -0
  454. package/src/presentation/viewer.ts +98 -87
  455. package/src/shared/constants.ts +26 -0
  456. package/src/shared/normalize.ts +13 -22
  457. package/src/shared/paginate.ts +4 -18
  458. package/src/types.ts +86 -1
@@ -41,38 +41,17 @@ export type PointsToMap = Map<string, Set<string>>;
41
41
  const MAX_SOLVER_ITERATIONS = 50;
42
42
 
43
43
  /**
44
- * Build a points-to map for one file.
45
- *
46
- * Seeds concrete function names (locally-defined functions + imported names),
47
- * then propagates assignments through fixed-point iteration until stable.
48
- *
49
- * Each "concrete target" in a pts set is a name that `resolveCallTargets` can
50
- * look up — either a locally-defined function name (found via byNameAndFile) or
51
- * an imported name (found via importedNames → byNameAndFile in the source file).
44
+ * Seed the pts map from locally-defined functions, imported names, and
45
+ * fnRefBindings (direct assignment aliases: `const fn = handler`).
52
46
  *
53
- * @param fnRefBindings - identifier/member-expr bindings from the extractor
54
- * @param definitionNames - locally-defined callable names in this file
55
- * @param importedNames - names imported into this file (name → resolved file)
56
- * @param paramBindings - call-site arg→param bindings (Phase 8.3c)
57
- * @param definitionParams - per-function ordered parameter names (Phase 8.3c)
58
- * @param arrayElemBindings - array literal element bindings (Phase 8.3e)
59
- * @param spreadArgBindings - spread-argument bindings (Phase 8.3e)
60
- * @param forOfBindings - for-of iteration variable bindings (Phase 8.3e)
61
- * @param arrayCallbackBindings - Array.from/callback bindings (Phase 8.3e)
47
+ * Returns the seeded pts map and the base constraint list built from
48
+ * fnRefBindings (member-expression aliases: `const fn = obj.method`).
62
49
  */
63
- export function buildPointsToMap(
50
+ function buildThisAssignmentMap(
64
51
  fnRefBindings: readonly FnRefBinding[],
65
52
  definitionNames: ReadonlySet<string>,
66
53
  importedNames: ReadonlyMap<string, string>,
67
- paramBindings?: readonly ParamBinding[],
68
- definitionParams?: ReadonlyMap<string, readonly string[]>,
69
- arrayElemBindings?: readonly ArrayElemBinding[],
70
- spreadArgBindings?: readonly SpreadArgBinding[],
71
- forOfBindings?: readonly ForOfBinding[],
72
- arrayCallbackBindings?: readonly ArrayCallbackBinding[],
73
- objectRestParamBindings?: readonly ObjectRestParamBinding[],
74
- objectPropBindings?: readonly ObjectPropBinding[],
75
- ): PointsToMap {
54
+ ): { pts: PointsToMap; constraints: Array<{ lhs: string; rhsKey: string }> } {
76
55
  const pts: PointsToMap = new Map();
77
56
 
78
57
  // Seed: each locally-defined function points to itself.
@@ -96,6 +75,24 @@ export function buildPointsToMap(
96
75
  rhsKey: b.rhsReceiver ? `${b.rhsReceiver}.${b.rhs}` : b.rhs,
97
76
  }));
98
77
 
78
+ return { pts, constraints };
79
+ }
80
+
81
+ /**
82
+ * Append parameter-flow and array/spread/forOf/callback constraints (Phases 8.3c and 8.3e).
83
+ *
84
+ * Mutates `pts` (seeds array-element entries) and appends to `constraints`.
85
+ */
86
+ function buildParamAndArrayConstraints(
87
+ pts: PointsToMap,
88
+ constraints: Array<{ lhs: string; rhsKey: string }>,
89
+ paramBindings?: readonly ParamBinding[],
90
+ definitionParams?: ReadonlyMap<string, readonly string[]>,
91
+ arrayElemBindings?: readonly ArrayElemBinding[],
92
+ spreadArgBindings?: readonly SpreadArgBinding[],
93
+ forOfBindings?: readonly ForOfBinding[],
94
+ arrayCallbackBindings?: readonly ArrayCallbackBinding[],
95
+ ): void {
99
96
  // Phase 8.3c: parameter-flow constraints.
100
97
  // For each call f(x) at argIndex i where f is locally defined, add
101
98
  // constraint: pts(f::paramName_i) ⊇ pts(x). This makes the pts solver
@@ -180,46 +177,113 @@ export function buildPointsToMap(
180
177
  constraints.push({ lhs: `${calleeName}::${params[0]}`, rhsKey: `${sourceName}[*]` });
181
178
  }
182
179
  }
180
+ }
183
181
 
184
- // Phase 8.3f: object-rest parameter dispatch.
185
- // `function f({ ...rest }) {}` + `f(obj)` + `const obj = { prop: fn }` →
186
- // seed pts["rest.prop"] = {"fn"} so that `rest.prop()` resolves to `fn`.
187
- if (objectRestParamBindings && objectPropBindings && paramBindings) {
188
- // Index paramBindings: "callee::argIndex" argName[] (O(|paramBindings|) build,
189
- // O(1) lookup — avoids scanning paramBindings for each rest binding).
190
- const paramByCalleeIdx = new Map<string, string[]>();
191
- for (const { callee, argIndex, argName } of paramBindings) {
192
- const k = `${callee}::${argIndex}`;
193
- const list = paramByCalleeIdx.get(k);
194
- if (list) list.push(argName);
195
- else paramByCalleeIdx.set(k, [argName]);
196
- }
182
+ /**
183
+ * Seed pts entries for object-rest parameter dispatch (Phase 8.3f).
184
+ *
185
+ * `function f({ ...rest }) {}` + `f(obj)` + `const obj = { prop: fn }` →
186
+ * seeds pts["rest.prop"] = {"fn"} so that `rest.prop()` resolves to `fn`.
187
+ *
188
+ * Mutates `pts` in place.
189
+ */
190
+ function buildObjectRestConstraints(
191
+ pts: PointsToMap,
192
+ definitionNames: ReadonlySet<string>,
193
+ importedNames: ReadonlyMap<string, string>,
194
+ paramBindings: readonly ParamBinding[],
195
+ objectRestParamBindings: readonly ObjectRestParamBinding[],
196
+ objectPropBindings: readonly ObjectPropBinding[],
197
+ ): void {
198
+ // Index paramBindings: "callee::argIndex" → argName[] (O(|paramBindings|) build,
199
+ // O(1) lookup — avoids scanning paramBindings for each rest binding).
200
+ const paramByCalleeIdx = new Map<string, string[]>();
201
+ for (const { callee, argIndex, argName } of paramBindings) {
202
+ const k = `${callee}::${argIndex}`;
203
+ const list = paramByCalleeIdx.get(k);
204
+ if (list) list.push(argName);
205
+ else paramByCalleeIdx.set(k, [argName]);
206
+ }
197
207
 
198
- // Index objectPropBindings: objectName → {propName, valueName}[]
199
- const propsByObject = new Map<string, Array<{ propName: string; valueName: string }>>();
200
- for (const { objectName, propName, valueName } of objectPropBindings) {
201
- const list = propsByObject.get(objectName);
202
- if (list) list.push({ propName, valueName });
203
- else propsByObject.set(objectName, [{ propName, valueName }]);
204
- }
208
+ // Index objectPropBindings: objectName → {propName, valueName}[]
209
+ const propsByObject = new Map<string, Array<{ propName: string; valueName: string }>>();
210
+ for (const { objectName, propName, valueName } of objectPropBindings) {
211
+ const list = propsByObject.get(objectName);
212
+ if (list) list.push({ propName, valueName });
213
+ else propsByObject.set(objectName, [{ propName, valueName }]);
214
+ }
205
215
 
206
- for (const { callee, restName, argIndex } of objectRestParamBindings) {
207
- const argNames = paramByCalleeIdx.get(`${callee}::${argIndex}`) ?? [];
208
- for (const argName of argNames) {
209
- const props = propsByObject.get(argName) ?? [];
210
- for (const { propName, valueName } of props) {
211
- if (!definitionNames.has(valueName) && !importedNames.has(valueName)) continue;
212
- const key = `${restName}.${propName}`;
213
- if (!pts.has(key)) pts.set(key, new Set());
214
- pts.get(key)!.add(valueName);
215
- }
216
+ for (const { callee, restName, argIndex } of objectRestParamBindings) {
217
+ const argNames = paramByCalleeIdx.get(`${callee}::${argIndex}`) ?? [];
218
+ for (const argName of argNames) {
219
+ const props = propsByObject.get(argName) ?? [];
220
+ for (const { propName, valueName } of props) {
221
+ if (!definitionNames.has(valueName) && !importedNames.has(valueName)) continue;
222
+ const key = `${restName}.${propName}`;
223
+ if (!pts.has(key)) pts.set(key, new Set());
224
+ pts.get(key)!.add(valueName);
216
225
  }
217
226
  }
218
227
  }
228
+ }
219
229
 
220
- if (constraints.length === 0) return pts;
230
+ /**
231
+ * Append higher-order constraints to the constraint list based on how
232
+ * function values flow through call sites, arrays, for-of loops, callbacks,
233
+ * and object rest-param destructuring.
234
+ *
235
+ * Coordinates buildParamAndArrayConstraints (Phase 8.3c/e) and
236
+ * buildObjectRestConstraints (Phase 8.3f).
237
+ *
238
+ * Mutates `pts` (seeds array-element and object-rest entries) and appends to `constraints`.
239
+ */
240
+ function appendAdvancedConstraints(
241
+ pts: PointsToMap,
242
+ constraints: Array<{ lhs: string; rhsKey: string }>,
243
+ definitionNames: ReadonlySet<string>,
244
+ importedNames: ReadonlyMap<string, string>,
245
+ paramBindings?: readonly ParamBinding[],
246
+ definitionParams?: ReadonlyMap<string, readonly string[]>,
247
+ arrayElemBindings?: readonly ArrayElemBinding[],
248
+ spreadArgBindings?: readonly SpreadArgBinding[],
249
+ forOfBindings?: readonly ForOfBinding[],
250
+ arrayCallbackBindings?: readonly ArrayCallbackBinding[],
251
+ objectRestParamBindings?: readonly ObjectRestParamBinding[],
252
+ objectPropBindings?: readonly ObjectPropBinding[],
253
+ ): void {
254
+ buildParamAndArrayConstraints(
255
+ pts,
256
+ constraints,
257
+ paramBindings,
258
+ definitionParams,
259
+ arrayElemBindings,
260
+ spreadArgBindings,
261
+ forOfBindings,
262
+ arrayCallbackBindings,
263
+ );
264
+
265
+ if (objectRestParamBindings && objectPropBindings && paramBindings) {
266
+ buildObjectRestConstraints(
267
+ pts,
268
+ definitionNames,
269
+ importedNames,
270
+ paramBindings,
271
+ objectRestParamBindings,
272
+ objectPropBindings,
273
+ );
274
+ }
275
+ }
221
276
 
222
- // Fixed-point iteration: propagate pts sets until no new information flows.
277
+ /**
278
+ * Run the fixed-point solver: propagate pts sets through constraints until
279
+ * no new information flows (or MAX_SOLVER_ITERATIONS is reached).
280
+ *
281
+ * Mutates `pts` in place.
282
+ */
283
+ function buildCallSiteTypeMap(
284
+ pts: PointsToMap,
285
+ constraints: ReadonlyArray<{ lhs: string; rhsKey: string }>,
286
+ ): void {
223
287
  for (let iter = 0; iter < MAX_SOLVER_ITERATIONS; iter++) {
224
288
  let changed = false;
225
289
  for (const { lhs, rhsKey } of constraints) {
@@ -236,6 +300,65 @@ export function buildPointsToMap(
236
300
  }
237
301
  if (!changed) break;
238
302
  }
303
+ }
304
+
305
+ /**
306
+ * Build a points-to map for one file.
307
+ *
308
+ * Seeds concrete function names (locally-defined functions + imported names),
309
+ * then propagates assignments through fixed-point iteration until stable.
310
+ *
311
+ * Each "concrete target" in a pts set is a name that `resolveCallTargets` can
312
+ * look up — either a locally-defined function name (found via byNameAndFile) or
313
+ * an imported name (found via importedNames → byNameAndFile in the source file).
314
+ *
315
+ * @param fnRefBindings - identifier/member-expr bindings from the extractor
316
+ * @param definitionNames - locally-defined callable names in this file
317
+ * @param importedNames - names imported into this file (name → resolved file)
318
+ * @param paramBindings - call-site arg→param bindings (Phase 8.3c)
319
+ * @param definitionParams - per-function ordered parameter names (Phase 8.3c)
320
+ * @param arrayElemBindings - array literal element bindings (Phase 8.3e)
321
+ * @param spreadArgBindings - spread-argument bindings (Phase 8.3e)
322
+ * @param forOfBindings - for-of iteration variable bindings (Phase 8.3e)
323
+ * @param arrayCallbackBindings - Array.from/callback bindings (Phase 8.3e)
324
+ */
325
+ export function buildPointsToMap(
326
+ fnRefBindings: readonly FnRefBinding[],
327
+ definitionNames: ReadonlySet<string>,
328
+ importedNames: ReadonlyMap<string, string>,
329
+ paramBindings?: readonly ParamBinding[],
330
+ definitionParams?: ReadonlyMap<string, readonly string[]>,
331
+ arrayElemBindings?: readonly ArrayElemBinding[],
332
+ spreadArgBindings?: readonly SpreadArgBinding[],
333
+ forOfBindings?: readonly ForOfBinding[],
334
+ arrayCallbackBindings?: readonly ArrayCallbackBinding[],
335
+ objectRestParamBindings?: readonly ObjectRestParamBinding[],
336
+ objectPropBindings?: readonly ObjectPropBinding[],
337
+ ): PointsToMap {
338
+ const { pts, constraints } = buildThisAssignmentMap(
339
+ fnRefBindings,
340
+ definitionNames,
341
+ importedNames,
342
+ );
343
+
344
+ appendAdvancedConstraints(
345
+ pts,
346
+ constraints,
347
+ definitionNames,
348
+ importedNames,
349
+ paramBindings,
350
+ definitionParams,
351
+ arrayElemBindings,
352
+ spreadArgBindings,
353
+ forOfBindings,
354
+ arrayCallbackBindings,
355
+ objectRestParamBindings,
356
+ objectPropBindings,
357
+ );
358
+
359
+ if (constraints.length === 0) return pts;
360
+
361
+ buildCallSiteTypeMap(pts, constraints);
239
362
 
240
363
  return pts;
241
364
  }
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Call resolution strategy helpers — extracted from call-resolver.ts.
3
+ *
4
+ * `resolveByMethodOrGlobal` in call-resolver.ts dispatches to two sub-strategies:
5
+ * - resolveByReceiver — receiver is a concrete object/class (not this/self/super)
6
+ * - resolveByGlobal — bare call or this/self/super receiver
7
+ *
8
+ * Splitting them here keeps each strategy unit-testable and reduces call-resolver.ts
9
+ * cognitive complexity from 107 to a thin dispatcher.
10
+ *
11
+ * This file intentionally does NOT import from ../builder/call-resolver.ts to avoid
12
+ * a circular dependency. The StrategyLookup interface mirrors CallNodeLookup structurally
13
+ * (TypeScript structural typing ensures compatibility without an explicit import).
14
+ */
15
+ import { computeConfidence } from '../resolve.js';
16
+
17
+ // ── Lookup adapter (structural mirror of CallNodeLookup) ──────────────────────
18
+
19
+ /**
20
+ * Structural mirror of `CallNodeLookup` from call-resolver.ts.
21
+ * Any `CallNodeLookup` instance satisfies this type without explicit declaration.
22
+ * Defined here to break the circular import that would arise from importing
23
+ * `CallNodeLookup` directly from call-resolver.ts.
24
+ */
25
+ export interface StrategyLookup {
26
+ byNameAndFile(
27
+ name: string,
28
+ file: string,
29
+ ): ReadonlyArray<{ id: number; file: string; kind?: string }>;
30
+ byName(name: string): ReadonlyArray<{ id: number; file: string; kind?: string }>;
31
+ isBarrel(file: string): boolean;
32
+ resolveBarrel(barrelFile: string, symbolName: string): string | null;
33
+ nodeId(name: string, kind: string, file: string, line: number): { id: number } | undefined;
34
+ }
35
+
36
+ // ── Module-scoped language detection ─────────────────────────────────────────
37
+
38
+ /**
39
+ * Languages where bare `foo()` calls inside a class method are lexically scoped
40
+ * to the module, not the class — there is no implicit this/class binding.
41
+ * For these languages, the same-class fallback must not run for bare (no-receiver)
42
+ * calls that found no exact same-file match.
43
+ */
44
+ const MODULE_SCOPED_BARE_CALL_EXTENSIONS = new Set([
45
+ '.js',
46
+ '.mjs',
47
+ '.cjs',
48
+ '.jsx',
49
+ '.ts',
50
+ '.tsx',
51
+ '.mts',
52
+ '.cts',
53
+ ]);
54
+
55
+ export function isModuleScopedLanguage(relPath: string): boolean {
56
+ const ext = relPath.slice(relPath.lastIndexOf('.'));
57
+ return MODULE_SCOPED_BARE_CALL_EXTENSIONS.has(ext);
58
+ }
59
+
60
+ // ── resolveByReceiver ─────────────────────────────────────────────────────────
61
+
62
+ /**
63
+ * Resolve a call site whose receiver is a concrete object reference
64
+ * (i.e. `receiver` is present and is NOT `this`, `self`, or `super`).
65
+ *
66
+ * Resolution cascade:
67
+ * 1. typeMap class-scoped lookup (`ClassName.prop` key) for `this.prop` receivers.
68
+ * 2. typeMap bare key, full-receiver key, callee-scoped rest-param key.
69
+ * 3. Inline `new Ctor()` heuristic for un-normalised receiver text.
70
+ * 4. Typed method lookup via `TypeName.methodName` in symbol DB.
71
+ * 5. Prototype alias: `Foo.prototype.bar = identifier` via typeMap.
72
+ * 6. Direct qualified method lookup: `ClassName.staticMethod()`.
73
+ * 7. Composite pts key: `obj.prop` → callback target function.
74
+ */
75
+ export function resolveByReceiver(
76
+ lookup: StrategyLookup,
77
+ call: { name: string; receiver: string },
78
+ relPath: string,
79
+ typeMap: Map<string, unknown>,
80
+ callerName?: string | null,
81
+ ): ReadonlyArray<{ id: number; file: string }> {
82
+ // Strip "this." so `this.repo.method()` resolves via typeMap["repo"]
83
+ // (or the "this.repo" key seeded directly by the TSC property-declaration enricher).
84
+ const effectiveReceiver = call.receiver.startsWith('this.')
85
+ ? call.receiver.slice('this.'.length)
86
+ : call.receiver;
87
+
88
+ // For this.prop receivers, prefer the class-scoped key (ClassName.prop) seeded by
89
+ // handlePropWriteTypeMap / handleFieldDefTypeMap — prevents false edges when multiple
90
+ // classes define the same property name (issues #1323, #1458).
91
+ // Class-scoped lookup runs first so bare fallback keys (confidence 0.6) don't shadow
92
+ // the correct per-class entry when callerName is available.
93
+ let typeEntry: unknown;
94
+ if (call.receiver.startsWith('this.') && callerName) {
95
+ const dotIdx = callerName.lastIndexOf('.');
96
+ if (dotIdx > -1) {
97
+ const callerClass = callerName.slice(0, dotIdx);
98
+ typeEntry = typeMap.get(`${callerClass}.${effectiveReceiver}`);
99
+ }
100
+ }
101
+ typeEntry ??=
102
+ typeMap.get(effectiveReceiver) ??
103
+ typeMap.get(call.receiver) ??
104
+ // Phase 8.3f: callee-scoped rest-param key (`callee::restName`) to avoid
105
+ // same-name rest-binding collision across functions in the same file (#1358).
106
+ (callerName ? typeMap.get(`${callerName}::${effectiveReceiver}`) : undefined);
107
+
108
+ let typeName = typeEntry
109
+ ? typeof typeEntry === 'string'
110
+ ? typeEntry
111
+ : (typeEntry as { type?: string }).type
112
+ : null;
113
+
114
+ // Belt-and-suspenders fallback for inline new-expression receivers that
115
+ // extractReceiverName did not normalise (e.g. raw text leaked from an
116
+ // unhandled AST node type). extractReceiverName already handles the common
117
+ // `new_expression` / `parenthesized_expression(new_expression)` shapes by
118
+ // returning the constructor name directly, so this branch is exercised only
119
+ // by future node types or constructs that fall through to the raw-text path.
120
+ // The uppercase-initial restriction ([A-Z_$]) is a heuristic to distinguish
121
+ // constructors (PascalCase) from regular functions and avoids false positives
122
+ // on `(new xmlParser()).parse()` style calls.
123
+ if (!typeName && call.receiver) {
124
+ const m = /^\(?\s*new\s+([A-Z_$][A-Za-z0-9_$]*)/.exec(call.receiver);
125
+ if (m?.[1]) typeName = m[1];
126
+ }
127
+
128
+ if (typeName) {
129
+ const typed = lookup
130
+ .byName(`${typeName}.${call.name}`)
131
+ .filter((n) => n.kind === 'method' && computeConfidence(relPath, n.file, null) >= 0.5);
132
+ if (typed.length > 0) return typed;
133
+
134
+ // Prototype alias: `Foo.prototype.bar = identifier` seeds typeMap['Foo.bar'] = { type: identifier }.
135
+ // Checked after the symbol-DB lookup so an actual method definition always wins.
136
+ const protoEntry = typeMap.get(`${typeName}.${call.name}`);
137
+ const protoTarget = protoEntry
138
+ ? typeof protoEntry === 'string'
139
+ ? protoEntry
140
+ : (protoEntry as { type?: string }).type
141
+ : null;
142
+ if (protoTarget) {
143
+ const resolved = lookup
144
+ .byName(protoTarget)
145
+ .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
146
+ if (resolved.length > 0) return resolved;
147
+ }
148
+ }
149
+
150
+ // Direct qualified method lookup: ClassName.staticMethod() or ClassName.instanceMethod()
151
+ // when the receiver is a class name with no typeMap entry. Handles static method calls
152
+ // like `C6.staticMethod()` or `D.d()` where the receiver IS the class.
153
+ // Matches both 'method' and 'function' kinds to cover field-initializer synthetic defs.
154
+ if (!typeName) {
155
+ const qualifiedName = `${effectiveReceiver}.${call.name}`;
156
+ const direct = lookup
157
+ .byName(qualifiedName)
158
+ .filter(
159
+ (n) =>
160
+ (n.kind === 'method' || n.kind === 'function') &&
161
+ computeConfidence(relPath, n.file, null) >= 0.5,
162
+ );
163
+ if (direct.length > 0) return direct;
164
+ }
165
+
166
+ // Phase 8.3d: composite pts key — `obj.prop = fn` seeds typeMap['obj.prop'] = { type: 'fn' }.
167
+ // When a call site references `obj.prop` as a callback, resolve directly to the target fn.
168
+ const compositeEntry = typeMap.get(`${call.receiver}.${call.name}`);
169
+ const ptsTarget = compositeEntry
170
+ ? typeof compositeEntry === 'string'
171
+ ? compositeEntry
172
+ : (compositeEntry as { type?: string }).type
173
+ : null;
174
+ if (ptsTarget) {
175
+ const resolved = lookup
176
+ .byName(ptsTarget)
177
+ .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
178
+ if (resolved.length > 0) return resolved;
179
+ }
180
+
181
+ return [];
182
+ }
183
+
184
+ // ── resolveByGlobal ───────────────────────────────────────────────────────────
185
+
186
+ /**
187
+ * Resolve a call site with no receiver, or whose receiver is `this`, `self`,
188
+ * or `super`.
189
+ *
190
+ * Resolution cascade:
191
+ * 1. Accessor this-dispatch via Object.defineProperty (Phase 8.3f).
192
+ * 2. Exact global name lookup with confidence filter.
193
+ * 3. Same-class sibling method fallback (C#/Java static siblings, this.method()).
194
+ */
195
+ export function resolveByGlobal(
196
+ lookup: StrategyLookup,
197
+ call: { name: string; receiver?: string | null },
198
+ relPath: string,
199
+ typeMap: Map<string, unknown>,
200
+ callerName?: string | null,
201
+ ): ReadonlyArray<{ id: number; file: string }> {
202
+ // Phase 8.3f: accessor this-dispatch via Object.defineProperty.
203
+ // When a plain function (no class prefix) is registered as a get/set accessor for `obj`
204
+ // via Object.defineProperty, typeMap seeds 'callerName:this' = 'obj'.
205
+ // We then resolve this.method() → typeMap['obj.method'] → the concrete definition.
206
+ // This runs before the broad exact-name lookup to avoid false positives from
207
+ // unrelated same-file definitions.
208
+ if (call.receiver === 'this' && callerName && !callerName.includes('.')) {
209
+ const accessorThisEntry = typeMap.get(`${callerName}:this`);
210
+ const objName = accessorThisEntry
211
+ ? typeof accessorThisEntry === 'string'
212
+ ? accessorThisEntry
213
+ : (accessorThisEntry as { type?: string }).type
214
+ : null;
215
+ if (objName) {
216
+ const objMethodEntry = typeMap.get(`${objName}.${call.name}`);
217
+ const targetFn = objMethodEntry
218
+ ? typeof objMethodEntry === 'string'
219
+ ? objMethodEntry
220
+ : (objMethodEntry as { type?: string }).type
221
+ : null;
222
+ if (targetFn) {
223
+ const resolved = lookup
224
+ .byName(targetFn)
225
+ .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
226
+ if (resolved.length > 0) return resolved;
227
+ }
228
+ }
229
+ }
230
+
231
+ const exact = lookup
232
+ .byName(call.name)
233
+ .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
234
+ if (exact.length > 0) return exact;
235
+
236
+ // Try same-class method lookup via callerName.
237
+ // e.g. `this.area()` inside `Shape.describe` → try `Shape.area`.
238
+ // Also covers no-receiver calls inside class methods, e.g. `IsValidEmail(x)` inside
239
+ // `Validators.ValidateUser` → try `Validators.IsValidEmail` (C#/Java static siblings).
240
+ // This seeds the initial edge that runChaPostPass later expands to subclass overrides.
241
+ //
242
+ // For JS/TS, bare (no-receiver) calls are module-scoped — there is no implicit class
243
+ // binding. Skip the same-class fallback for bare calls in those languages to prevent
244
+ // false positives (e.g. `flush()` inside `Processor.run` must not resolve to
245
+ // `Processor.flush`). this.method() calls are unaffected: they still reach the fallback
246
+ // because `call.receiver === 'this'` is truthy, not a bare call.
247
+ const isBareCall = !call.receiver;
248
+ if (callerName && !(isBareCall && isModuleScopedLanguage(relPath))) {
249
+ const dotIdx = callerName.lastIndexOf('.');
250
+ if (dotIdx > -1) {
251
+ // Extract only the segment immediately before the method name so that
252
+ // 'Namespace.ClassName.method' yields 'ClassName', not 'Namespace.ClassName'.
253
+ // Symbols are stored under their bare class name, not their qualified path.
254
+ const prevDot = callerName.lastIndexOf('.', dotIdx - 1);
255
+ const callerClass = callerName.slice(prevDot + 1, dotIdx);
256
+ const qualifiedName = `${callerClass}.${call.name}`;
257
+ const sameClass = lookup
258
+ .byName(qualifiedName)
259
+ .filter((t) => t.kind === 'method' && computeConfidence(relPath, t.file, null) >= 0.5);
260
+ if (sameClass.length > 0) return sameClass;
261
+ }
262
+ }
263
+
264
+ return exact; // empty
265
+ }
@@ -1,17 +1,18 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { closeDb, getNodeId as getNodeIdQuery, initSchema, openDb } from '../../db/index.js';
4
+ import { loadConfig } from '../../infrastructure/config.js';
4
5
  import { debug, info, warn } from '../../infrastructure/logger.js';
5
- import { isSupportedFile, normalizePath, shouldIgnore } from '../../shared/constants.js';
6
+ import { buildIgnoreSet, isSupportedFile, normalizePath } from '../../shared/constants.js';
6
7
  import { DbError } from '../../shared/errors.js';
7
8
  import { createParseTreeCache, getActiveEngine } from '../parser.js';
8
9
  import { type IncrementalStmts, rebuildFile } from './builder/incremental.js';
9
10
  import { appendChangeEvents, buildChangeEvent, diffSymbols } from './change-journal.js';
10
11
  import { appendJournalEntriesAndStampHeader } from './journal.js';
11
12
 
12
- function shouldIgnorePath(filePath: string): boolean {
13
+ function shouldIgnorePath(filePath: string, ignoreSet: ReadonlySet<string>): boolean {
13
14
  const parts = filePath.split(path.sep);
14
- return parts.some((p) => shouldIgnore(p));
15
+ return parts.some((p) => ignoreSet.has(p) || p.startsWith('.'));
15
16
  }
16
17
 
17
18
  /** Prepare all SQL statements needed by the watcher's incremental rebuild. */
@@ -139,7 +140,7 @@ function logRebuildResults(updates: RebuildResult[]): void {
139
140
  }
140
141
 
141
142
  /** Recursively collect tracked source files for stat-based polling. */
142
- function collectTrackedFiles(dir: string, result: string[]): void {
143
+ function collectTrackedFiles(dir: string, result: string[], ignoreSet: ReadonlySet<string>): void {
143
144
  let entries: fs.Dirent[];
144
145
  try {
145
146
  entries = fs.readdirSync(dir, { withFileTypes: true });
@@ -148,10 +149,10 @@ function collectTrackedFiles(dir: string, result: string[]): void {
148
149
  return;
149
150
  }
150
151
  for (const entry of entries) {
151
- if (shouldIgnore(entry.name)) continue;
152
+ if (ignoreSet.has(entry.name) || entry.name.startsWith('.')) continue;
152
153
  const full = path.join(dir, entry.name);
153
154
  if (entry.isDirectory()) {
154
- collectTrackedFiles(full, result);
155
+ collectTrackedFiles(full, result, ignoreSet);
155
156
  } else if (isSupportedFile(entry.name)) {
156
157
  result.push(full);
157
158
  }
@@ -168,6 +169,8 @@ interface WatcherContext {
168
169
  pending: Set<string>;
169
170
  timer: ReturnType<typeof setTimeout> | null;
170
171
  debounceMs: number;
172
+ /** Merged ignore set from IGNORE_DIRS + config.ignoreDirs + config.ignoreAdditionalDirs. */
173
+ ignoreSet: ReadonlySet<string>;
171
174
  }
172
175
 
173
176
  /** Initialize DB, engine, cache, and statements for watch mode. */
@@ -177,6 +180,12 @@ function setupWatcher(rootDir: string, opts: { engine?: string; dbPath?: string
177
180
  throw new DbError('No graph.db found. Run `codegraph build` first.', { file: dbPath });
178
181
  }
179
182
 
183
+ // Load repo config so ignoreDirs and ignoreAdditionalDirs are respected by
184
+ // the watcher the same way they are by collectFiles in the batch build path.
185
+ const config = loadConfig(rootDir);
186
+ const extraDirs = [...(config.ignoreDirs ?? []), ...(config.ignoreAdditionalDirs ?? [])];
187
+ const ignoreSet = buildIgnoreSet(extraDirs.length ? extraDirs : undefined);
188
+
180
189
  const db = openDb(dbPath);
181
190
  initSchema(db);
182
191
  const engineOpts: import('../../types.js').EngineOpts = {
@@ -205,6 +214,7 @@ function setupWatcher(rootDir: string, opts: { engine?: string; dbPath?: string
205
214
  pending: new Set<string>(),
206
215
  timer: null,
207
216
  debounceMs: 300,
217
+ ignoreSet,
208
218
  };
209
219
  }
210
220
 
@@ -223,7 +233,7 @@ function startPollingWatcher(ctx: WatcherContext, pollIntervalMs: number): () =>
223
233
  const mtimeMap = new Map<string, number>();
224
234
 
225
235
  const initial: string[] = [];
226
- collectTrackedFiles(ctx.rootDir, initial);
236
+ collectTrackedFiles(ctx.rootDir, initial, ctx.ignoreSet);
227
237
  for (const f of initial) {
228
238
  try {
229
239
  mtimeMap.set(f, fs.statSync(f).mtimeMs);
@@ -235,7 +245,7 @@ function startPollingWatcher(ctx: WatcherContext, pollIntervalMs: number): () =>
235
245
 
236
246
  const pollTimer = setInterval(() => {
237
247
  const current: string[] = [];
238
- collectTrackedFiles(ctx.rootDir, current);
248
+ collectTrackedFiles(ctx.rootDir, current, ctx.ignoreSet);
239
249
  const currentSet = new Set(current);
240
250
 
241
251
  for (const f of current) {
@@ -270,7 +280,7 @@ function startPollingWatcher(ctx: WatcherContext, pollIntervalMs: number): () =>
270
280
  function startNativeWatcher(ctx: WatcherContext): () => void {
271
281
  const watcher = fs.watch(ctx.rootDir, { recursive: true }, (_eventType, filename) => {
272
282
  if (!filename) return;
273
- if (shouldIgnorePath(filename)) return;
283
+ if (shouldIgnorePath(filename, ctx.ignoreSet)) return;
274
284
  if (!isSupportedFile(filename)) return;
275
285
 
276
286
  ctx.pending.add(path.join(ctx.rootDir, filename));
@@ -716,7 +716,17 @@ function patchReturnTypeMap(r: any): void {
716
716
  }
717
717
 
718
718
  /** Wrap bindingType into binding object for dataflow argFlows and mutations. */
719
- 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 {
720
730
  if (dataflow.argFlows) {
721
731
  for (const f of dataflow.argFlows) {
722
732
  f.binding = f.bindingType ? { type: f.bindingType } : null;
@@ -738,7 +748,7 @@ function patchNativeResult(r: any): ExtractorOutput {
738
748
  if (r.imports) patchImports(r.imports);
739
749
  patchTypeMap(r);
740
750
  patchReturnTypeMap(r);
741
- if (r.dataflow) patchDataflow(r.dataflow);
751
+ if (r.dataflow) patchDataflowResult(r.dataflow);
742
752
 
743
753
  return r;
744
754
  }