@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
@@ -5,8 +5,16 @@
5
5
  * Both callers supply a `CallNodeLookup` adapter that abstracts their
6
6
  * node-lookup mechanism (pre-loaded Maps vs. per-query SQLite statements).
7
7
  * The resolution logic lives here exactly once.
8
+ *
9
+ * `resolveByMethodOrGlobal` delegates its two branches to strategy helpers
10
+ * in `../resolver/strategy.ts` to keep per-strategy complexity manageable.
8
11
  */
9
12
  import { computeConfidence } from '../resolve.js';
13
+ import {
14
+ isModuleScopedLanguage,
15
+ resolveByGlobal,
16
+ resolveByReceiver,
17
+ } from '../resolver/strategy.js';
10
18
 
11
19
  // ── Public interface ─────────────────────────────────────────────────────
12
20
 
@@ -23,165 +31,148 @@ export interface CallNodeLookup {
23
31
 
24
32
  export const RECEIVER_KINDS = new Set(['class', 'struct', 'interface', 'type', 'module']);
25
33
 
34
+ // Re-export so consumers that import isModuleScopedLanguage from this module
35
+ // continue to work without changes (build-edges.ts, etc.).
36
+ export { isModuleScopedLanguage };
37
+
38
+ // ── Shared resolution functions ──────────────────────────────────────────
39
+
26
40
  /**
27
- * Languages where bare `foo()` calls inside a class method are lexically scoped
28
- * to the module, not the class there is no implicit this/class binding.
29
- * For these languages, the same-class fallback must not run for bare (no-receiver)
30
- * calls that found no exact same-file match.
41
+ * Callable definition kinds variable/constant bindings are NOT callable
42
+ * in the function-as-enclosing-scope sense (they are local declarations, not
43
+ * function bodies). Top-level variable bindings (e.g. Haskell `main = do …`)
44
+ * are handled separately as a fallback tier.
31
45
  */
32
- const MODULE_SCOPED_BARE_CALL_EXTENSIONS = new Set([
33
- '.js',
34
- '.mjs',
35
- '.cjs',
36
- '.jsx',
37
- '.ts',
38
- '.tsx',
39
- '.mts',
40
- '.cts',
41
- ]);
46
+ const CALLABLE_KINDS = new Set(['function', 'method']);
42
47
 
43
- export function isModuleScopedLanguage(relPath: string): boolean {
44
- const ext = relPath.slice(relPath.lastIndexOf('.'));
45
- return MODULE_SCOPED_BARE_CALL_EXTENSIONS.has(ext);
46
- }
48
+ /**
49
+ * Variable-like binding kinds that may act as top-level callers when no
50
+ * enclosing function/method exists (e.g. Haskell top-level `main` is a
51
+ * `bind` node → kind `variable`). Local variable declarations inside a
52
+ * function body must NOT win over the enclosing function.
53
+ */
54
+ const TOP_LEVEL_BINDING_KINDS = new Set(['variable', 'constant']);
47
55
 
48
- // ── Shared resolution functions ──────────────────────────────────────────
56
+ type Def = { name: string; kind: string; line: number; endLine?: number | null };
57
+ type CallerMatch = { id: number; name: string } | null;
49
58
 
50
- export function findCaller(
59
+ /**
60
+ * Find the narrowest enclosing function/method definition for `callLine`.
61
+ * Returns the DB node and name, or null if none encloses the call.
62
+ */
63
+ function findEnclosingCallable(
51
64
  lookup: CallNodeLookup,
52
- call: { line: number },
53
- definitions: ReadonlyArray<{
54
- name: string;
55
- kind: string;
56
- line: number;
57
- endLine?: number | null;
58
- }>,
65
+ callLine: number,
66
+ definitions: ReadonlyArray<Def>,
59
67
  relPath: string,
60
- fileNodeRow: { id: number },
61
- ): { id: number; callerName: string | null } {
62
- let caller: { id: number } | null = null;
63
- let callerName: string | null = null;
64
- let callerSpan = Infinity;
68
+ ): CallerMatch {
69
+ let best: CallerMatch = null;
70
+ let bestSpan = Infinity;
65
71
  for (const def of definitions) {
66
- if (def.line <= call.line) {
67
- const end = def.endLine || Infinity;
68
- if (call.line <= end) {
69
- const span = end - def.line;
70
- if (span < callerSpan) {
71
- const row = lookup.nodeId(def.name, def.kind, relPath, def.line);
72
- if (row) {
73
- caller = row;
74
- callerName = def.name;
75
- callerSpan = span;
76
- }
77
- }
72
+ if (!CALLABLE_KINDS.has(def.kind)) continue;
73
+ if (def.line > callLine) continue;
74
+ const end = def.endLine ?? Infinity;
75
+ if (callLine > end) continue;
76
+ const span = end === Infinity ? Infinity : end - def.line;
77
+ if (span < bestSpan) {
78
+ const row = lookup.nodeId(def.name, def.kind, relPath, def.line);
79
+ if (row) {
80
+ best = { ...row, name: def.name };
81
+ bestSpan = span;
78
82
  }
79
83
  }
80
84
  }
81
- return { ...(caller ?? fileNodeRow), callerName };
85
+ return best;
82
86
  }
83
87
 
84
- export function resolveByMethodOrGlobal(
88
+ /**
89
+ * Find the widest (outermost) enclosing variable/constant binding for `callLine`.
90
+ * Used as fallback for top-level bindings (e.g. Haskell `main = do …`).
91
+ * We pick the WIDEST span so that nested `let` bindings inside `main`'s
92
+ * do-block do not shadow `main` itself as the attributing caller.
93
+ */
94
+ function findEnclosingBinding(
85
95
  lookup: CallNodeLookup,
86
- call: { name: string; receiver?: string | null },
96
+ callLine: number,
97
+ definitions: ReadonlyArray<Def>,
87
98
  relPath: string,
88
- typeMap: Map<string, unknown>,
89
- callerName?: string | null,
90
- ): ReadonlyArray<{ id: number; file: string }> {
91
- if (call.receiver) {
92
- // Strip "this." so `this.repo.method()` resolves via typeMap["repo"]
93
- // (or the "this.repo" key seeded directly by the TSC property-declaration enricher).
94
- const effectiveReceiver = call.receiver.startsWith('this.')
95
- ? call.receiver.slice('this.'.length)
96
- : call.receiver;
97
- // For this.prop receivers, also try the class-scoped key (ClassName.prop) seeded by
98
- // handlePropWriteTypeMap prevents false edges when multiple classes define the same
99
- // property name (issue #1323).
100
- let typeEntry =
101
- typeMap.get(effectiveReceiver) ??
102
- typeMap.get(call.receiver) ??
103
- // Phase 8.3f: callee-scoped rest-param key (`callee::restName`) to avoid
104
- // same-name rest-binding collision across functions in the same file (#1358).
105
- (callerName ? typeMap.get(`${callerName}::${effectiveReceiver}`) : undefined);
106
- if (!typeEntry && call.receiver.startsWith('this.') && callerName) {
107
- const dotIdx = callerName.lastIndexOf('.');
108
- if (dotIdx > -1) {
109
- const callerClass = callerName.slice(0, dotIdx);
110
- typeEntry = typeMap.get(`${callerClass}.${effectiveReceiver}`);
99
+ ): CallerMatch {
100
+ let best: CallerMatch = null;
101
+ let bestSpan = -1; // looking for WIDEST span, so start at -1
102
+ for (const def of definitions) {
103
+ if (!TOP_LEVEL_BINDING_KINDS.has(def.kind)) continue;
104
+ if (def.line > callLine) continue;
105
+ const end = def.endLine ?? Infinity;
106
+ if (callLine > end) continue;
107
+ const span = end === Infinity ? Infinity : end - def.line;
108
+ if (span > bestSpan) {
109
+ const row = lookup.nodeId(def.name, def.kind, relPath, def.line);
110
+ if (row) {
111
+ best = { ...row, name: def.name };
112
+ bestSpan = span;
111
113
  }
112
114
  }
113
- let typeName = typeEntry
114
- ? typeof typeEntry === 'string'
115
- ? typeEntry
116
- : (typeEntry as { type?: string }).type
117
- : null;
115
+ }
116
+ return best;
117
+ }
118
118
 
119
- // Belt-and-suspenders fallback for inline new-expression receivers that
120
- // extractReceiverName did not normalise (e.g. raw text leaked from an
121
- // unhandled AST node type). extractReceiverName already handles the common
122
- // `new_expression` / `parenthesized_expression(new_expression)` shapes by
123
- // returning the constructor name directly, so this branch is exercised only
124
- // by future node types or constructs that fall through to the raw-text path.
125
- // The uppercase-initial restriction ([A-Z_$]) is a heuristic to distinguish
126
- // constructors (PascalCase) from regular functions and avoids false positives
127
- // on `(new xmlParser()).parse()` style calls.
128
- if (!typeName && call.receiver) {
129
- const m = /^\(?\s*new\s+([A-Z_$][A-Za-z0-9_$]*)/.exec(call.receiver);
130
- if (m?.[1]) typeName = m[1];
131
- }
119
+ export function findCaller(
120
+ lookup: CallNodeLookup,
121
+ call: { line: number },
122
+ definitions: ReadonlyArray<Def>,
123
+ relPath: string,
124
+ fileNodeRow: { id: number },
125
+ ): { id: number; callerName: string | null } {
126
+ // Pass 1: find the narrowest enclosing function/method.
127
+ const fnCaller = findEnclosingCallable(lookup, call.line, definitions, relPath);
132
128
 
133
- if (typeName) {
134
- const typed = lookup
135
- .byName(`${typeName}.${call.name}`)
136
- .filter((n) => n.kind === 'method' && computeConfidence(relPath, n.file, null) >= 0.5);
137
- if (typed.length > 0) return typed;
129
+ // Prefer function/method enclosing scope over variable binding.
130
+ // Only fall back to a variable/constant binding when the call is at
131
+ // top-level scope (no enclosing function/method found), which handles
132
+ // languages like Haskell where `main` is a top-level `bind` node.
133
+ if (fnCaller) {
134
+ return { id: fnCaller.id, callerName: fnCaller.name };
135
+ }
138
136
 
139
- // Prototype alias: `Foo.prototype.bar = identifier` seeds typeMap['Foo.bar'] = { type: identifier }.
140
- // Checked after the symbol-DB lookup so an actual method definition always wins.
141
- const protoEntry = typeMap.get(`${typeName}.${call.name}`);
142
- const protoTarget = protoEntry
143
- ? typeof protoEntry === 'string'
144
- ? protoEntry
145
- : (protoEntry as { type?: string }).type
146
- : null;
147
- if (protoTarget) {
148
- const resolved = lookup
149
- .byName(protoTarget)
150
- .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
151
- if (resolved.length > 0) return resolved;
152
- }
153
- }
137
+ // Pass 2: find the widest (outermost) enclosing variable/constant binding.
138
+ const varCaller = findEnclosingBinding(lookup, call.line, definitions, relPath);
139
+ if (varCaller) {
140
+ return { id: varCaller.id, callerName: varCaller.name };
141
+ }
154
142
 
155
- // Direct qualified method lookup: ClassName.staticMethod() or ClassName.instanceMethod()
156
- // when the receiver is a class name with no typeMap entry. Handles static method calls
157
- // like `C6.staticMethod()` or `D.d()` where the receiver IS the class.
158
- // Matches both 'method' and 'function' kinds to cover field-initializer synthetic defs.
159
- if (!typeName) {
160
- const qualifiedName = `${effectiveReceiver}.${call.name}`;
161
- const direct = lookup
162
- .byName(qualifiedName)
163
- .filter(
164
- (n) =>
165
- (n.kind === 'method' || n.kind === 'function') &&
166
- computeConfidence(relPath, n.file, null) >= 0.5,
167
- );
168
- if (direct.length > 0) return direct;
169
- }
143
+ return { ...fileNodeRow, callerName: null };
144
+ }
170
145
 
171
- // Phase 8.3d: composite pts key — `obj.prop = fn` seeds typeMap['obj.prop'] = { type: 'fn' }.
172
- // When a call site references `obj.prop` as a callback, resolve directly to the target fn.
173
- const compositeEntry = typeMap.get(`${call.receiver}.${call.name}`);
174
- const ptsTarget = compositeEntry
175
- ? typeof compositeEntry === 'string'
176
- ? compositeEntry
177
- : (compositeEntry as { type?: string }).type
178
- : null;
179
- if (ptsTarget) {
180
- const resolved = lookup
181
- .byName(ptsTarget)
182
- .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
183
- if (resolved.length > 0) return resolved;
184
- }
146
+ /**
147
+ * Dispatcher for call-site resolution.
148
+ *
149
+ * Delegates to two strategy helpers (in `../resolver/strategy.ts`) to keep
150
+ * each branch independently readable and under the complexity threshold:
151
+ * - resolveByReceiver — receiver is a concrete object/class reference
152
+ * - resolveByGlobal — bare call, or this/self/super receiver
153
+ *
154
+ * The original logic is unchanged; only the physical location moved.
155
+ */
156
+ export function resolveByMethodOrGlobal(
157
+ lookup: CallNodeLookup,
158
+ call: { name: string; receiver?: string | null },
159
+ relPath: string,
160
+ typeMap: Map<string, unknown>,
161
+ callerName?: string | null,
162
+ ): ReadonlyArray<{ id: number; file: string }> {
163
+ if (
164
+ call.receiver &&
165
+ call.receiver !== 'this' &&
166
+ call.receiver !== 'self' &&
167
+ call.receiver !== 'super'
168
+ ) {
169
+ return resolveByReceiver(
170
+ lookup,
171
+ call as { name: string; receiver: string },
172
+ relPath,
173
+ typeMap,
174
+ callerName,
175
+ );
185
176
  }
186
177
  if (
187
178
  !call.receiver ||
@@ -189,68 +180,7 @@ export function resolveByMethodOrGlobal(
189
180
  call.receiver === 'self' ||
190
181
  call.receiver === 'super'
191
182
  ) {
192
- // Phase 8.3f: accessor this-dispatch via Object.defineProperty.
193
- // When a plain function (no class prefix) is registered as a get/set accessor for `obj`
194
- // via Object.defineProperty, typeMap seeds 'callerName:this' = 'obj'.
195
- // We then resolve this.method() → typeMap['obj.method'] → the concrete definition.
196
- // This runs before the broad exact-name lookup to avoid false positives from
197
- // unrelated same-file definitions.
198
- if (call.receiver === 'this' && callerName && !callerName.includes('.')) {
199
- const accessorThisEntry = typeMap.get(`${callerName}:this`);
200
- const objName = accessorThisEntry
201
- ? typeof accessorThisEntry === 'string'
202
- ? accessorThisEntry
203
- : (accessorThisEntry as { type?: string }).type
204
- : null;
205
- if (objName) {
206
- const objMethodEntry = typeMap.get(`${objName}.${call.name}`);
207
- const targetFn = objMethodEntry
208
- ? typeof objMethodEntry === 'string'
209
- ? objMethodEntry
210
- : (objMethodEntry as { type?: string }).type
211
- : null;
212
- if (targetFn) {
213
- const resolved = lookup
214
- .byName(targetFn)
215
- .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
216
- if (resolved.length > 0) return resolved;
217
- }
218
- }
219
- }
220
-
221
- const exact = lookup
222
- .byName(call.name)
223
- .filter((t) => computeConfidence(relPath, t.file, null) >= 0.5);
224
- if (exact.length > 0) return exact;
225
-
226
- // Try same-class method lookup via callerName.
227
- // e.g. `this.area()` inside `Shape.describe` → try `Shape.area`.
228
- // Also covers no-receiver calls inside class methods, e.g. `IsValidEmail(x)` inside
229
- // `Validators.ValidateUser` → try `Validators.IsValidEmail` (C#/Java static siblings).
230
- // This seeds the initial edge that runChaPostPass later expands to subclass overrides.
231
- //
232
- // For JS/TS, bare (no-receiver) calls are module-scoped — there is no implicit class
233
- // binding. Skip the same-class fallback for bare calls in those languages to prevent
234
- // false positives (e.g. `flush()` inside `Processor.run` must not resolve to
235
- // `Processor.flush`). this.method() calls are unaffected: they still reach the fallback
236
- // because `call.receiver === 'this'` is truthy, not a bare call.
237
- const isBareCall = !call.receiver;
238
- if (callerName && !(isBareCall && isModuleScopedLanguage(relPath))) {
239
- const dotIdx = callerName.lastIndexOf('.');
240
- if (dotIdx > -1) {
241
- // Extract only the segment immediately before the method name so that
242
- // 'Namespace.ClassName.method' yields 'ClassName', not 'Namespace.ClassName'.
243
- // Symbols are stored under their bare class name, not their qualified path.
244
- const prevDot = callerName.lastIndexOf('.', dotIdx - 1);
245
- const callerClass = callerName.slice(prevDot + 1, dotIdx);
246
- const qualifiedName = `${callerClass}.${call.name}`;
247
- const sameClass = lookup
248
- .byName(qualifiedName)
249
- .filter((t) => t.kind === 'method' && computeConfidence(relPath, t.file, null) >= 0.5);
250
- if (sameClass.length > 0) return sameClass;
251
- }
252
- }
253
- return exact; // empty
183
+ return resolveByGlobal(lookup, call, relPath, typeMap, callerName);
254
184
  }
255
185
  return [];
256
186
  }
@@ -263,6 +193,12 @@ export function resolveCallTargets(
263
193
  typeMap: Map<string, unknown>,
264
194
  callerName?: string | null,
265
195
  ): { targets: Array<{ id: number; file: string }>; importedFrom: string | undefined } {
196
+ // Flagged dynamic calls use synthetic names like '<dynamic:eval>'. Short-circuit
197
+ // so they never accidentally match a real symbol via lookup.byName.
198
+ if (call.name.startsWith('<dynamic:')) {
199
+ return { targets: [], importedFrom: undefined };
200
+ }
201
+
266
202
  const importedFrom = importedNames.get(call.name);
267
203
  let targets: ReadonlyArray<{ id: number; file: string }> | undefined;
268
204
 
@@ -299,13 +235,17 @@ export function resolveCallTargets(
299
235
  * Returns the edge tuple to insert, or null if nothing matched or the edge
300
236
  * was already seen. Callers are responsible for the actual DB/array insert.
301
237
  *
302
- * Receiver resolution collects all same-file candidates first (no kind
303
- * filter), falls back to global candidates only when the same-file set is
304
- * entirely empty, then filters the chosen set by RECEIVER_KINDS. This
305
- * matches the native Rust build path: if a file imports a name that happens
306
- * to be emitted as `kind='function'` in the importer, the same-file set is
307
- * non-empty and blocks the global fallback, so no receiver edge is emitted.
308
- * Keeping this behaviour identical to the Rust path maintains engine parity.
238
+ * Receiver resolution:
239
+ * 1. Look up same-file nodes for `effectiveReceiver` (unfiltered by kind).
240
+ * 2. If any same-file node exists AND `effectiveReceiver` is not in `importedNames`
241
+ * (i.e. it is a locally-defined symbol, not an import artifact), apply
242
+ * RECEIVER_KINDS and return the filtered set no global fallback.
243
+ * A local `function C(){}` means this file owns `C`; no cross-file class
244
+ * should win over it (issue #1539).
245
+ * 3. If the same-file node IS an import artifact (e.g. destructured require),
246
+ * or no same-file node exists at all, fall back to global candidates filtered
247
+ * by RECEIVER_KINDS. This preserves the pre-#1539 behaviour for cases where
248
+ * an imported name appears as kind='function' in the importer file.
309
249
  */
310
250
  export function resolveReceiverEdge(
311
251
  lookup: CallNodeLookup,
@@ -314,6 +254,7 @@ export function resolveReceiverEdge(
314
254
  relPath: string,
315
255
  typeMap: Map<string, unknown>,
316
256
  seenCallEdges: Set<string>,
257
+ importedNames: ReadonlyMap<string, string>,
317
258
  ): { callerId: number; receiverId: number; confidence: number } | null {
318
259
  const typeEntry = typeMap.get(call.receiver);
319
260
  const typeName = typeEntry
@@ -326,18 +267,15 @@ export function resolveReceiverEdge(
326
267
  ? ((typeEntry as { confidence?: number }).confidence ?? null)
327
268
  : null;
328
269
  const effectiveReceiver = typeName || call.receiver;
329
- // Filter-before: apply RECEIVER_KINDS to same-file candidates first, then
330
- // fall back to global candidates (also filtered) only when same-file yields
331
- // nothing. This prevents an imported name emitted as kind='function' in the
332
- // importing file from blocking the fallback to the actual class/struct/etc.
333
- // node in the defining file.
334
- const sameFileCandidates = lookup
335
- .byNameAndFile(effectiveReceiver, relPath)
336
- .filter((n) => RECEIVER_KINDS.has(n.kind ?? ''));
337
- const candidates =
338
- sameFileCandidates.length > 0
339
- ? sameFileCandidates
340
- : lookup.byName(effectiveReceiver).filter((n) => RECEIVER_KINDS.has(n.kind ?? ''));
270
+ // Block global fallback only when the same-file node is a local definition,
271
+ // not when it's an import artifact (e.g. `const { C } = require(…)` seeds a
272
+ // kind='function' node in the importer but the real class lives elsewhere).
273
+ const sameFileAll = lookup.byNameAndFile(effectiveReceiver, relPath);
274
+ const isLocalDefinition = sameFileAll.length > 0 && !importedNames?.has(effectiveReceiver);
275
+ const sameFileCandidates = sameFileAll.filter((n) => RECEIVER_KINDS.has(n.kind ?? ''));
276
+ const candidates = isLocalDefinition
277
+ ? sameFileCandidates
278
+ : lookup.byName(effectiveReceiver).filter((n) => RECEIVER_KINDS.has(n.kind ?? ''));
341
279
  if (candidates.length === 0) return null;
342
280
  const recvTarget = candidates[0]!;
343
281
  const recvKey = `recv|${caller.id}|${recvTarget.id}`;
@@ -96,6 +96,14 @@ export function buildChaContext(fileSymbols: ReadonlyMap<string, ExtractorOutput
96
96
  * For `super`, resolution starts from the parent of the caller's class.
97
97
  * For `this`/`self`, resolution starts from the caller's own class and walks
98
98
  * up the inheritance chain (supporting inherited method lookup).
99
+ *
100
+ * When `callerFile` is provided, same-file method nodes are preferred: if the
101
+ * hierarchy walk finds a qualified method that exists in both the caller's own
102
+ * file AND in unrelated files (e.g. a class named `A` that appears in multiple
103
+ * fixture files), only the same-file nodes are returned. This prevents
104
+ * cross-fixture false edges caused by accidental name collisions across
105
+ * unrelated files in the same project build. When no same-file nodes exist,
106
+ * all found nodes are returned as before.
99
107
  */
100
108
  export function resolveThisDispatch(
101
109
  methodName: string,
@@ -103,6 +111,7 @@ export function resolveThisDispatch(
103
111
  receiver: 'this' | 'self' | 'super',
104
112
  chaCtx: ChaContext,
105
113
  lookup: CallNodeLookup,
114
+ callerFile?: string | null,
106
115
  ): ReadonlyArray<{ id: number; file: string }> {
107
116
  if (!callerName) return [];
108
117
  const dotIdx = callerName.indexOf('.');
@@ -119,7 +128,15 @@ export function resolveThisDispatch(
119
128
  visited.add(current);
120
129
  const qualified = `${current}.${methodName}`;
121
130
  const found = lookup.byName(qualified).filter((n) => n.kind === 'method');
122
- if (found.length > 0) return found;
131
+ if (found.length > 0) {
132
+ // When the caller's file is known, prefer same-file nodes to avoid
133
+ // emitting cross-file edges to identically-named methods in unrelated
134
+ // files. Only fall back to the full set when no same-file node exists.
135
+ if (callerFile && found.some((n) => n.file === callerFile)) {
136
+ return found.filter((n) => n.file === callerFile);
137
+ }
138
+ return found;
139
+ }
123
140
  current = chaCtx.parents.get(current);
124
141
  }
125
142
  return [];
@@ -91,6 +91,7 @@ export class PipelineContext {
91
91
  confidence: number;
92
92
  dynamic: number;
93
93
  technique: string | null;
94
+ dynamicKind: string | null;
94
95
  }> = [];
95
96
 
96
97
  // ── Misc state ─────────────────────────────────────────────────────