@saluzi/codegraph 0.1.0 → 0.2.1

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 (712) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +885 -0
  3. package/dist/bin/codegraph.d.ts +2 -1
  4. package/dist/bin/codegraph.d.ts.map +1 -0
  5. package/dist/bin/codegraph.js +2248 -0
  6. package/dist/bin/codegraph.js.map +1 -0
  7. package/dist/bin/command-supervision.d.ts +49 -0
  8. package/dist/bin/command-supervision.d.ts.map +1 -0
  9. package/dist/bin/command-supervision.js +95 -0
  10. package/dist/bin/command-supervision.js.map +1 -0
  11. package/dist/bin/fatal-handler.d.ts +20 -0
  12. package/dist/bin/fatal-handler.d.ts.map +1 -0
  13. package/dist/bin/fatal-handler.js +118 -0
  14. package/dist/bin/fatal-handler.js.map +1 -0
  15. package/dist/bin/node-version-check.d.ts.map +1 -0
  16. package/dist/bin/node-version-check.js +79 -0
  17. package/dist/bin/node-version-check.js.map +1 -0
  18. package/dist/bin/uninstall.d.ts.map +1 -0
  19. package/dist/bin/uninstall.js +36 -0
  20. package/dist/bin/uninstall.js.map +1 -0
  21. package/dist/context/formatter.d.ts +6 -9
  22. package/dist/context/formatter.d.ts.map +1 -0
  23. package/dist/context/formatter.js +25 -6
  24. package/dist/context/formatter.js.map +1 -0
  25. package/dist/context/index.d.ts +102 -100
  26. package/dist/context/index.d.ts.map +1 -0
  27. package/dist/context/index.js +252 -6
  28. package/dist/context/index.js.map +1 -0
  29. package/dist/context/markers.d.ts +19 -0
  30. package/dist/context/markers.d.ts.map +1 -0
  31. package/dist/context/markers.js +22 -0
  32. package/dist/context/markers.js.map +1 -0
  33. package/dist/db/index.d.ts +185 -85
  34. package/dist/db/index.d.ts.map +1 -0
  35. package/dist/db/index.js +257 -14
  36. package/dist/db/index.js.map +1 -0
  37. package/dist/db/migrations.d.ts +15 -18
  38. package/dist/db/migrations.d.ts.map +1 -0
  39. package/dist/db/migrations.js +82 -1
  40. package/dist/db/migrations.js.map +1 -0
  41. package/dist/db/queries.d.ts +503 -281
  42. package/dist/db/queries.d.ts.map +1 -0
  43. package/dist/db/queries.js +644 -107
  44. package/dist/db/queries.js.map +1 -0
  45. package/dist/db/schema.sql +69 -26
  46. package/dist/db/sqlite-adapter.d.ts +26 -22
  47. package/dist/db/sqlite-adapter.d.ts.map +1 -0
  48. package/dist/db/sqlite-adapter.js +11 -35
  49. package/dist/db/sqlite-adapter.js.map +1 -0
  50. package/dist/db/wal-valve.d.ts +106 -0
  51. package/dist/db/wal-valve.d.ts.map +1 -0
  52. package/dist/db/wal-valve.js +208 -0
  53. package/dist/db/wal-valve.js.map +1 -0
  54. package/dist/directory.d.ts +140 -19
  55. package/dist/directory.d.ts.map +1 -0
  56. package/dist/directory.js +568 -35
  57. package/dist/directory.js.map +1 -0
  58. package/dist/errors.d.ts +32 -45
  59. package/dist/errors.d.ts.map +1 -0
  60. package/dist/errors.js.map +1 -0
  61. package/dist/extraction/astro-extractor.d.ts +79 -0
  62. package/dist/extraction/astro-extractor.d.ts.map +1 -0
  63. package/dist/extraction/astro-extractor.js +320 -0
  64. package/dist/extraction/astro-extractor.js.map +1 -0
  65. package/dist/extraction/cfml-extractor.d.ts +107 -0
  66. package/dist/extraction/cfml-extractor.d.ts.map +1 -0
  67. package/dist/extraction/cfml-extractor.js +494 -0
  68. package/dist/extraction/cfml-extractor.js.map +1 -0
  69. package/dist/extraction/dfm-extractor.d.ts +17 -17
  70. package/dist/extraction/dfm-extractor.d.ts.map +1 -0
  71. package/dist/extraction/dfm-extractor.js.map +1 -0
  72. package/dist/extraction/extraction-version.d.ts +25 -0
  73. package/dist/extraction/extraction-version.d.ts.map +1 -0
  74. package/dist/extraction/extraction-version.js +28 -0
  75. package/dist/extraction/extraction-version.js.map +1 -0
  76. package/dist/extraction/function-ref.d.ts +118 -0
  77. package/dist/extraction/function-ref.d.ts.map +1 -0
  78. package/dist/extraction/function-ref.js +727 -0
  79. package/dist/extraction/function-ref.js.map +1 -0
  80. package/dist/extraction/generated-detection.d.ts +30 -0
  81. package/dist/extraction/generated-detection.d.ts.map +1 -0
  82. package/dist/extraction/generated-detection.js +83 -0
  83. package/dist/extraction/generated-detection.js.map +1 -0
  84. package/dist/extraction/grammars.d.ts +74 -30
  85. package/dist/extraction/grammars.d.ts.map +1 -0
  86. package/dist/extraction/grammars.js +289 -15
  87. package/dist/extraction/grammars.js.map +1 -0
  88. package/dist/extraction/index.d.ts +193 -109
  89. package/dist/extraction/index.d.ts.map +1 -0
  90. package/dist/extraction/index.js +1485 -362
  91. package/dist/extraction/index.js.map +1 -0
  92. package/dist/extraction/languages/arkts.d.ts +3 -0
  93. package/dist/extraction/languages/arkts.d.ts.map +1 -0
  94. package/dist/extraction/languages/arkts.js +127 -0
  95. package/dist/extraction/languages/arkts.js.map +1 -0
  96. package/dist/extraction/languages/c-cpp.d.ts +110 -4
  97. package/dist/extraction/languages/c-cpp.d.ts.map +1 -0
  98. package/dist/extraction/languages/c-cpp.js +713 -2
  99. package/dist/extraction/languages/c-cpp.js.map +1 -0
  100. package/dist/extraction/languages/cfquery.d.ts +12 -0
  101. package/dist/extraction/languages/cfquery.d.ts.map +1 -0
  102. package/dist/extraction/languages/cfquery.js +28 -0
  103. package/dist/extraction/languages/cfquery.js.map +1 -0
  104. package/dist/extraction/languages/cfscript.d.ts +3 -0
  105. package/dist/extraction/languages/cfscript.d.ts.map +1 -0
  106. package/dist/extraction/languages/cfscript.js +73 -0
  107. package/dist/extraction/languages/cfscript.js.map +1 -0
  108. package/dist/extraction/languages/cobol.d.ts +33 -0
  109. package/dist/extraction/languages/cobol.d.ts.map +1 -0
  110. package/dist/extraction/languages/cobol.js +499 -0
  111. package/dist/extraction/languages/cobol.js.map +1 -0
  112. package/dist/extraction/languages/csharp.d.ts +25 -3
  113. package/dist/extraction/languages/csharp.d.ts.map +1 -0
  114. package/dist/extraction/languages/csharp.js +106 -3
  115. package/dist/extraction/languages/csharp.js.map +1 -0
  116. package/dist/extraction/languages/dart.d.ts +3 -3
  117. package/dist/extraction/languages/dart.d.ts.map +1 -0
  118. package/dist/extraction/languages/dart.js +183 -1
  119. package/dist/extraction/languages/dart.js.map +1 -0
  120. package/dist/extraction/languages/erlang.d.ts +3 -0
  121. package/dist/extraction/languages/erlang.d.ts.map +1 -0
  122. package/dist/extraction/languages/erlang.js +350 -0
  123. package/dist/extraction/languages/erlang.js.map +1 -0
  124. package/dist/extraction/languages/go.d.ts +3 -3
  125. package/dist/extraction/languages/go.d.ts.map +1 -0
  126. package/dist/extraction/languages/go.js +55 -2
  127. package/dist/extraction/languages/go.js.map +1 -0
  128. package/dist/extraction/languages/index.d.ts +4 -4
  129. package/dist/extraction/languages/index.d.ts.map +1 -0
  130. package/dist/extraction/languages/index.js +22 -0
  131. package/dist/extraction/languages/index.js.map +1 -0
  132. package/dist/extraction/languages/java.d.ts +3 -3
  133. package/dist/extraction/languages/java.d.ts.map +1 -0
  134. package/dist/extraction/languages/java.js +252 -1
  135. package/dist/extraction/languages/java.js.map +1 -0
  136. package/dist/extraction/languages/javascript.d.ts +3 -3
  137. package/dist/extraction/languages/javascript.d.ts.map +1 -0
  138. package/dist/extraction/languages/javascript.js +16 -0
  139. package/dist/extraction/languages/javascript.js.map +1 -0
  140. package/dist/extraction/languages/kotlin.d.ts +3 -3
  141. package/dist/extraction/languages/kotlin.d.ts.map +1 -0
  142. package/dist/extraction/languages/kotlin.js +126 -0
  143. package/dist/extraction/languages/kotlin.js.map +1 -0
  144. package/dist/extraction/languages/lua.d.ts +3 -3
  145. package/dist/extraction/languages/lua.d.ts.map +1 -0
  146. package/dist/extraction/languages/lua.js.map +1 -0
  147. package/dist/extraction/languages/luau.d.ts +3 -3
  148. package/dist/extraction/languages/luau.d.ts.map +1 -0
  149. package/dist/extraction/languages/luau.js.map +1 -0
  150. package/dist/extraction/languages/nix.d.ts +3 -0
  151. package/dist/extraction/languages/nix.d.ts.map +1 -0
  152. package/dist/extraction/languages/nix.js +294 -0
  153. package/dist/extraction/languages/nix.js.map +1 -0
  154. package/dist/extraction/languages/objc.d.ts +3 -0
  155. package/dist/extraction/languages/objc.d.ts.map +1 -0
  156. package/dist/extraction/languages/objc.js +175 -0
  157. package/dist/extraction/languages/objc.js.map +1 -0
  158. package/dist/extraction/languages/pascal.d.ts +3 -3
  159. package/dist/extraction/languages/pascal.d.ts.map +1 -0
  160. package/dist/extraction/languages/pascal.js +11 -0
  161. package/dist/extraction/languages/pascal.js.map +1 -0
  162. package/dist/extraction/languages/php.d.ts +3 -3
  163. package/dist/extraction/languages/php.d.ts.map +1 -0
  164. package/dist/extraction/languages/php.js +90 -1
  165. package/dist/extraction/languages/php.js.map +1 -0
  166. package/dist/extraction/languages/python.d.ts +3 -3
  167. package/dist/extraction/languages/python.d.ts.map +1 -0
  168. package/dist/extraction/languages/python.js.map +1 -0
  169. package/dist/extraction/languages/r.d.ts +3 -0
  170. package/dist/extraction/languages/r.d.ts.map +1 -0
  171. package/dist/extraction/languages/r.js +314 -0
  172. package/dist/extraction/languages/r.js.map +1 -0
  173. package/dist/extraction/languages/ruby.d.ts +3 -3
  174. package/dist/extraction/languages/ruby.d.ts.map +1 -0
  175. package/dist/extraction/languages/ruby.js +35 -0
  176. package/dist/extraction/languages/ruby.js.map +1 -0
  177. package/dist/extraction/languages/rust.d.ts +3 -3
  178. package/dist/extraction/languages/rust.d.ts.map +1 -0
  179. package/dist/extraction/languages/rust.js +35 -2
  180. package/dist/extraction/languages/rust.js.map +1 -0
  181. package/dist/extraction/languages/scala.d.ts +3 -3
  182. package/dist/extraction/languages/scala.d.ts.map +1 -0
  183. package/dist/extraction/languages/scala.js +80 -10
  184. package/dist/extraction/languages/scala.js.map +1 -0
  185. package/dist/extraction/languages/solidity.d.ts +3 -0
  186. package/dist/extraction/languages/solidity.d.ts.map +1 -0
  187. package/dist/extraction/languages/solidity.js +293 -0
  188. package/dist/extraction/languages/solidity.js.map +1 -0
  189. package/dist/extraction/languages/swift.d.ts +3 -3
  190. package/dist/extraction/languages/swift.d.ts.map +1 -0
  191. package/dist/extraction/languages/swift.js +61 -0
  192. package/dist/extraction/languages/swift.js.map +1 -0
  193. package/dist/extraction/languages/terraform.d.ts +3 -0
  194. package/dist/extraction/languages/terraform.d.ts.map +1 -0
  195. package/dist/extraction/languages/terraform.js +641 -0
  196. package/dist/extraction/languages/terraform.js.map +1 -0
  197. package/dist/extraction/languages/typescript.d.ts +16 -3
  198. package/dist/extraction/languages/typescript.d.ts.map +1 -0
  199. package/dist/extraction/languages/typescript.js +38 -0
  200. package/dist/extraction/languages/typescript.js.map +1 -0
  201. package/dist/extraction/languages/vbnet.d.ts +11 -0
  202. package/dist/extraction/languages/vbnet.d.ts.map +1 -0
  203. package/dist/extraction/languages/vbnet.js +141 -0
  204. package/dist/extraction/languages/vbnet.js.map +1 -0
  205. package/dist/extraction/liquid-extractor.d.ts +48 -41
  206. package/dist/extraction/liquid-extractor.d.ts.map +1 -0
  207. package/dist/extraction/liquid-extractor.js +53 -9
  208. package/dist/extraction/liquid-extractor.js.map +1 -0
  209. package/dist/extraction/mybatis-extractor.d.ts +68 -0
  210. package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  211. package/dist/extraction/mybatis-extractor.js +300 -0
  212. package/dist/extraction/mybatis-extractor.js.map +1 -0
  213. package/dist/extraction/parse-pool.d.ts +152 -0
  214. package/dist/extraction/parse-pool.d.ts.map +1 -0
  215. package/dist/extraction/parse-pool.js +387 -0
  216. package/dist/extraction/parse-pool.js.map +1 -0
  217. package/dist/extraction/parse-worker.d.ts +2 -2
  218. package/dist/extraction/parse-worker.d.ts.map +1 -0
  219. package/dist/extraction/parse-worker.js +13 -3
  220. package/dist/extraction/parse-worker.js.map +1 -0
  221. package/dist/extraction/razor-extractor.d.ts +42 -0
  222. package/dist/extraction/razor-extractor.d.ts.map +1 -0
  223. package/dist/extraction/razor-extractor.js +285 -0
  224. package/dist/extraction/razor-extractor.js.map +1 -0
  225. package/dist/extraction/svelte-extractor.d.ts +42 -42
  226. package/dist/extraction/svelte-extractor.d.ts.map +1 -0
  227. package/dist/extraction/svelte-extractor.js +6 -3
  228. package/dist/extraction/svelte-extractor.js.map +1 -0
  229. package/dist/extraction/tree-sitter-helpers.d.ts +7 -18
  230. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
  231. package/dist/extraction/tree-sitter-helpers.js +60 -10
  232. package/dist/extraction/tree-sitter-helpers.js.map +1 -0
  233. package/dist/extraction/tree-sitter-types.d.ts +224 -157
  234. package/dist/extraction/tree-sitter-types.d.ts.map +1 -0
  235. package/dist/extraction/tree-sitter-types.js.map +1 -0
  236. package/dist/extraction/tree-sitter.d.ts +689 -221
  237. package/dist/extraction/tree-sitter.d.ts.map +1 -0
  238. package/dist/extraction/tree-sitter.js +4193 -117
  239. package/dist/extraction/tree-sitter.js.map +1 -0
  240. package/dist/extraction/vue-extractor.d.ts +40 -25
  241. package/dist/extraction/vue-extractor.d.ts.map +1 -0
  242. package/dist/extraction/vue-extractor.js +94 -3
  243. package/dist/extraction/vue-extractor.js.map +1 -0
  244. package/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  245. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  246. package/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  247. package/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  248. package/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  249. package/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  250. package/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  251. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  252. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  253. package/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  254. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  255. package/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
  256. package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  257. package/dist/extraction/wasm-runtime-flags.d.ts +6 -14
  258. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  259. package/dist/extraction/wasm-runtime-flags.js +1 -0
  260. package/dist/extraction/wasm-runtime-flags.js.map +1 -0
  261. package/dist/graph/index.d.ts +3 -3
  262. package/dist/graph/index.d.ts.map +1 -0
  263. package/dist/graph/index.js.map +1 -0
  264. package/dist/graph/queries.d.ts +96 -99
  265. package/dist/graph/queries.d.ts.map +1 -0
  266. package/dist/graph/queries.js +13 -40
  267. package/dist/graph/queries.js.map +1 -0
  268. package/dist/graph/traversal.d.ts +117 -127
  269. package/dist/graph/traversal.d.ts.map +1 -0
  270. package/dist/graph/traversal.js +92 -21
  271. package/dist/graph/traversal.js.map +1 -0
  272. package/dist/index.d.ts +615 -481
  273. package/dist/index.d.ts.map +1 -0
  274. package/dist/index.js +709 -18
  275. package/dist/index.js.map +1 -0
  276. package/dist/installer/config-writer.d.ts +13 -14
  277. package/dist/installer/config-writer.d.ts.map +1 -0
  278. package/dist/installer/config-writer.js +91 -0
  279. package/dist/installer/config-writer.js.map +1 -0
  280. package/dist/installer/index.d.ts +84 -82
  281. package/dist/installer/index.d.ts.map +1 -0
  282. package/dist/installer/index.js +619 -0
  283. package/dist/installer/index.js.map +1 -0
  284. package/dist/installer/instructions-template.d.ts +35 -24
  285. package/dist/installer/instructions-template.d.ts.map +1 -0
  286. package/dist/installer/instructions-template.js +53 -0
  287. package/dist/installer/instructions-template.js.map +1 -0
  288. package/dist/installer/targets/antigravity.d.ts +57 -0
  289. package/dist/installer/targets/antigravity.d.ts.map +1 -0
  290. package/dist/installer/targets/antigravity.js +308 -0
  291. package/dist/installer/targets/antigravity.js.map +1 -0
  292. package/dist/installer/targets/claude.d.ts +34 -27
  293. package/dist/installer/targets/claude.d.ts.map +1 -0
  294. package/dist/installer/targets/claude.js +454 -0
  295. package/dist/installer/targets/claude.js.map +1 -0
  296. package/dist/installer/targets/codex.d.ts +3 -3
  297. package/dist/installer/targets/codex.d.ts.map +1 -0
  298. package/dist/installer/targets/codex.js +185 -0
  299. package/dist/installer/targets/codex.js.map +1 -0
  300. package/dist/installer/targets/cursor.d.ts +3 -3
  301. package/dist/installer/targets/cursor.d.ts.map +1 -0
  302. package/dist/installer/targets/cursor.js +254 -0
  303. package/dist/installer/targets/cursor.js.map +1 -0
  304. package/dist/installer/targets/gemini.d.ts +26 -0
  305. package/dist/installer/targets/gemini.d.ts.map +1 -0
  306. package/dist/installer/targets/gemini.js +165 -0
  307. package/dist/installer/targets/gemini.js.map +1 -0
  308. package/dist/installer/targets/hermes.d.ts +3 -3
  309. package/dist/installer/targets/hermes.d.ts.map +1 -0
  310. package/dist/installer/targets/hermes.js +359 -0
  311. package/dist/installer/targets/hermes.js.map +1 -0
  312. package/dist/installer/targets/kiro.d.ts +27 -0
  313. package/dist/installer/targets/kiro.d.ts.map +1 -0
  314. package/dist/installer/targets/kiro.js +178 -0
  315. package/dist/installer/targets/kiro.js.map +1 -0
  316. package/dist/installer/targets/opencode.d.ts +12 -4
  317. package/dist/installer/targets/opencode.d.ts.map +1 -0
  318. package/dist/installer/targets/opencode.js +288 -0
  319. package/dist/installer/targets/opencode.js.map +1 -0
  320. package/dist/installer/targets/registry.d.ts +9 -12
  321. package/dist/installer/targets/registry.d.ts.map +1 -0
  322. package/dist/installer/targets/registry.js +91 -0
  323. package/dist/installer/targets/registry.js.map +1 -0
  324. package/dist/installer/targets/shared.d.ts +38 -29
  325. package/dist/installer/targets/shared.d.ts.map +1 -0
  326. package/dist/installer/targets/shared.js +264 -0
  327. package/dist/installer/targets/shared.js.map +1 -0
  328. package/dist/installer/targets/toml.d.ts +11 -23
  329. package/dist/installer/targets/toml.d.ts.map +1 -0
  330. package/dist/installer/targets/toml.js +147 -0
  331. package/dist/installer/targets/toml.js.map +1 -0
  332. package/dist/installer/targets/types.d.ts +62 -76
  333. package/dist/installer/targets/types.d.ts.map +1 -0
  334. package/dist/installer/targets/types.js +16 -0
  335. package/dist/installer/targets/types.js.map +1 -0
  336. package/dist/mcp/daemon-manager.d.ts +42 -0
  337. package/dist/mcp/daemon-manager.d.ts.map +1 -0
  338. package/dist/mcp/daemon-manager.js +129 -0
  339. package/dist/mcp/daemon-manager.js.map +1 -0
  340. package/dist/mcp/daemon-paths.d.ts +73 -0
  341. package/dist/mcp/daemon-paths.d.ts.map +1 -0
  342. package/dist/mcp/daemon-paths.js +165 -0
  343. package/dist/mcp/daemon-paths.js.map +1 -0
  344. package/dist/mcp/daemon-registry.d.ts +47 -0
  345. package/dist/mcp/daemon-registry.d.ts.map +1 -0
  346. package/dist/mcp/daemon-registry.js +233 -0
  347. package/dist/mcp/daemon-registry.js.map +1 -0
  348. package/dist/mcp/daemon.d.ts +290 -0
  349. package/dist/mcp/daemon.d.ts.map +1 -0
  350. package/dist/mcp/daemon.js +862 -0
  351. package/dist/mcp/daemon.js.map +1 -0
  352. package/dist/mcp/dynamic-boundaries.d.ts +41 -0
  353. package/dist/mcp/dynamic-boundaries.d.ts.map +1 -0
  354. package/dist/mcp/dynamic-boundaries.js +360 -0
  355. package/dist/mcp/dynamic-boundaries.js.map +1 -0
  356. package/dist/mcp/early-ppid.d.ts +26 -0
  357. package/dist/mcp/early-ppid.d.ts.map +1 -0
  358. package/dist/mcp/early-ppid.js +29 -0
  359. package/dist/mcp/early-ppid.js.map +1 -0
  360. package/dist/mcp/engine.d.ts +122 -0
  361. package/dist/mcp/engine.d.ts.map +1 -0
  362. package/dist/mcp/engine.js +350 -0
  363. package/dist/mcp/engine.js.map +1 -0
  364. package/dist/mcp/index.d.ts +89 -74
  365. package/dist/mcp/index.d.ts.map +1 -0
  366. package/dist/mcp/index.js +506 -0
  367. package/dist/mcp/index.js.map +1 -0
  368. package/dist/mcp/liveness-watchdog.d.ts +35 -0
  369. package/dist/mcp/liveness-watchdog.d.ts.map +1 -0
  370. package/dist/mcp/liveness-watchdog.js +267 -0
  371. package/dist/mcp/liveness-watchdog.js.map +1 -0
  372. package/dist/mcp/ppid-watchdog.d.ts +62 -0
  373. package/dist/mcp/ppid-watchdog.d.ts.map +1 -0
  374. package/dist/mcp/ppid-watchdog.js +64 -0
  375. package/dist/mcp/ppid-watchdog.js.map +1 -0
  376. package/dist/mcp/proxy.d.ts +87 -0
  377. package/dist/mcp/proxy.d.ts.map +1 -0
  378. package/dist/mcp/proxy.js +667 -0
  379. package/dist/mcp/proxy.js.map +1 -0
  380. package/dist/mcp/query-pool.d.ts +108 -0
  381. package/dist/mcp/query-pool.d.ts.map +1 -0
  382. package/dist/mcp/query-pool.js +315 -0
  383. package/dist/mcp/query-pool.js.map +1 -0
  384. package/dist/mcp/query-worker.d.ts +24 -0
  385. package/dist/mcp/query-worker.d.ts.map +1 -0
  386. package/dist/mcp/query-worker.js +87 -0
  387. package/dist/mcp/query-worker.js.map +1 -0
  388. package/dist/mcp/server-instructions.d.ts +22 -8
  389. package/dist/mcp/server-instructions.d.ts.map +1 -0
  390. package/dist/mcp/server-instructions.js +106 -0
  391. package/dist/mcp/server-instructions.js.map +1 -0
  392. package/dist/mcp/session.d.ts +93 -0
  393. package/dist/mcp/session.d.ts.map +1 -0
  394. package/dist/mcp/session.js +357 -0
  395. package/dist/mcp/session.js.map +1 -0
  396. package/dist/mcp/startup-handshake.d.ts +44 -0
  397. package/dist/mcp/startup-handshake.d.ts.map +1 -0
  398. package/dist/mcp/startup-handshake.js +73 -0
  399. package/dist/mcp/startup-handshake.js.map +1 -0
  400. package/dist/mcp/stdin-teardown.d.ts +27 -0
  401. package/dist/mcp/stdin-teardown.d.ts.map +1 -0
  402. package/dist/mcp/stdin-teardown.js +49 -0
  403. package/dist/mcp/stdin-teardown.js.map +1 -0
  404. package/dist/mcp/tools.d.ts +557 -213
  405. package/dist/mcp/tools.d.ts.map +1 -0
  406. package/dist/mcp/tools.js +4477 -0
  407. package/dist/mcp/tools.js.map +1 -0
  408. package/dist/mcp/transport.d.ts +158 -87
  409. package/dist/mcp/transport.d.ts.map +1 -0
  410. package/dist/mcp/transport.js +377 -0
  411. package/dist/mcp/transport.js.map +1 -0
  412. package/dist/mcp/version.d.ts +19 -0
  413. package/dist/mcp/version.d.ts.map +1 -0
  414. package/dist/mcp/version.js +71 -0
  415. package/dist/mcp/version.js.map +1 -0
  416. package/dist/project-config.d.ts +94 -0
  417. package/dist/project-config.d.ts.map +1 -0
  418. package/dist/project-config.js +374 -0
  419. package/dist/project-config.js.map +1 -0
  420. package/dist/resolution/c-fnptr-synthesizer.d.ts +6 -0
  421. package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -0
  422. package/dist/resolution/c-fnptr-synthesizer.js +1062 -0
  423. package/dist/resolution/c-fnptr-synthesizer.js.map +1 -0
  424. package/dist/resolution/callback-synthesizer.d.ts +15 -0
  425. package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  426. package/dist/resolution/callback-synthesizer.js +3938 -0
  427. package/dist/resolution/callback-synthesizer.js.map +1 -0
  428. package/dist/resolution/cooperative-yield.d.ts +32 -0
  429. package/dist/resolution/cooperative-yield.d.ts.map +1 -0
  430. package/dist/resolution/cooperative-yield.js +42 -0
  431. package/dist/resolution/cooperative-yield.js.map +1 -0
  432. package/dist/resolution/frameworks/astro.d.ts +9 -0
  433. package/dist/resolution/frameworks/astro.d.ts.map +1 -0
  434. package/dist/resolution/frameworks/astro.js +169 -0
  435. package/dist/resolution/frameworks/astro.js.map +1 -0
  436. package/dist/resolution/frameworks/cargo-workspace.d.ts +3 -5
  437. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  438. package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  439. package/dist/resolution/frameworks/cics.d.ts +20 -0
  440. package/dist/resolution/frameworks/cics.d.ts.map +1 -0
  441. package/dist/resolution/frameworks/cics.js +90 -0
  442. package/dist/resolution/frameworks/cics.js.map +1 -0
  443. package/dist/resolution/frameworks/csharp.d.ts +3 -3
  444. package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
  445. package/dist/resolution/frameworks/csharp.js +36 -8
  446. package/dist/resolution/frameworks/csharp.js.map +1 -0
  447. package/dist/resolution/frameworks/drupal.d.ts +3 -3
  448. package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  449. package/dist/resolution/frameworks/drupal.js +44 -12
  450. package/dist/resolution/frameworks/drupal.js.map +1 -0
  451. package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  452. package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  453. package/dist/resolution/frameworks/expo-modules.js +148 -0
  454. package/dist/resolution/frameworks/expo-modules.js.map +1 -0
  455. package/dist/resolution/frameworks/express.d.ts +3 -3
  456. package/dist/resolution/frameworks/express.d.ts.map +1 -0
  457. package/dist/resolution/frameworks/express.js +102 -19
  458. package/dist/resolution/frameworks/express.js.map +1 -0
  459. package/dist/resolution/frameworks/fabric.d.ts +3 -0
  460. package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  461. package/dist/resolution/frameworks/fabric.js +354 -0
  462. package/dist/resolution/frameworks/fabric.js.map +1 -0
  463. package/dist/resolution/frameworks/go.d.ts +3 -3
  464. package/dist/resolution/frameworks/go.d.ts.map +1 -0
  465. package/dist/resolution/frameworks/go.js +6 -3
  466. package/dist/resolution/frameworks/go.js.map +1 -0
  467. package/dist/resolution/frameworks/goframe.d.ts +41 -0
  468. package/dist/resolution/frameworks/goframe.d.ts.map +1 -0
  469. package/dist/resolution/frameworks/goframe.js +112 -0
  470. package/dist/resolution/frameworks/goframe.js.map +1 -0
  471. package/dist/resolution/frameworks/index.d.ts +29 -31
  472. package/dist/resolution/frameworks/index.d.ts.map +1 -0
  473. package/dist/resolution/frameworks/index.js +39 -1
  474. package/dist/resolution/frameworks/index.js.map +1 -0
  475. package/dist/resolution/frameworks/java.d.ts +3 -3
  476. package/dist/resolution/frameworks/java.d.ts.map +1 -0
  477. package/dist/resolution/frameworks/java.js +352 -12
  478. package/dist/resolution/frameworks/java.js.map +1 -0
  479. package/dist/resolution/frameworks/laravel.d.ts +4 -4
  480. package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
  481. package/dist/resolution/frameworks/laravel.js +17 -8
  482. package/dist/resolution/frameworks/laravel.js.map +1 -0
  483. package/dist/resolution/frameworks/nestjs.d.ts +3 -3
  484. package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
  485. package/dist/resolution/frameworks/nestjs.js +324 -0
  486. package/dist/resolution/frameworks/nestjs.js.map +1 -0
  487. package/dist/resolution/frameworks/play.d.ts +19 -0
  488. package/dist/resolution/frameworks/play.d.ts.map +1 -0
  489. package/dist/resolution/frameworks/play.js +111 -0
  490. package/dist/resolution/frameworks/play.js.map +1 -0
  491. package/dist/resolution/frameworks/python.d.ts +5 -5
  492. package/dist/resolution/frameworks/python.d.ts.map +1 -0
  493. package/dist/resolution/frameworks/python.js +138 -16
  494. package/dist/resolution/frameworks/python.js.map +1 -0
  495. package/dist/resolution/frameworks/react-native.d.ts +3 -0
  496. package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  497. package/dist/resolution/frameworks/react-native.js +410 -0
  498. package/dist/resolution/frameworks/react-native.js.map +1 -0
  499. package/dist/resolution/frameworks/react.d.ts +3 -3
  500. package/dist/resolution/frameworks/react.d.ts.map +1 -0
  501. package/dist/resolution/frameworks/react.js +122 -60
  502. package/dist/resolution/frameworks/react.js.map +1 -0
  503. package/dist/resolution/frameworks/ruby.d.ts +3 -3
  504. package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
  505. package/dist/resolution/frameworks/ruby.js +106 -2
  506. package/dist/resolution/frameworks/ruby.js.map +1 -0
  507. package/dist/resolution/frameworks/rust.d.ts +3 -3
  508. package/dist/resolution/frameworks/rust.d.ts.map +1 -0
  509. package/dist/resolution/frameworks/rust.js +102 -5
  510. package/dist/resolution/frameworks/rust.js.map +1 -0
  511. package/dist/resolution/frameworks/svelte.d.ts +3 -3
  512. package/dist/resolution/frameworks/svelte.d.ts.map +1 -0
  513. package/dist/resolution/frameworks/svelte.js +5 -1
  514. package/dist/resolution/frameworks/svelte.js.map +1 -0
  515. package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  516. package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  517. package/dist/resolution/frameworks/swift-objc.js +252 -0
  518. package/dist/resolution/frameworks/swift-objc.js.map +1 -0
  519. package/dist/resolution/frameworks/swift.d.ts +5 -5
  520. package/dist/resolution/frameworks/swift.d.ts.map +1 -0
  521. package/dist/resolution/frameworks/swift.js +30 -6
  522. package/dist/resolution/frameworks/swift.js.map +1 -0
  523. package/dist/resolution/frameworks/terraform.d.ts +38 -0
  524. package/dist/resolution/frameworks/terraform.d.ts.map +1 -0
  525. package/dist/resolution/frameworks/terraform.js +277 -0
  526. package/dist/resolution/frameworks/terraform.js.map +1 -0
  527. package/dist/resolution/frameworks/vue.d.ts +3 -3
  528. package/dist/resolution/frameworks/vue.d.ts.map +1 -0
  529. package/dist/resolution/frameworks/vue.js +24 -27
  530. package/dist/resolution/frameworks/vue.js.map +1 -0
  531. package/dist/resolution/go-module.d.ts +26 -0
  532. package/dist/resolution/go-module.d.ts.map +1 -0
  533. package/dist/resolution/go-module.js +78 -0
  534. package/dist/resolution/go-module.js.map +1 -0
  535. package/dist/resolution/goframe-synthesizer.d.ts +29 -0
  536. package/dist/resolution/goframe-synthesizer.d.ts.map +1 -0
  537. package/dist/resolution/goframe-synthesizer.js +163 -0
  538. package/dist/resolution/goframe-synthesizer.js.map +1 -0
  539. package/dist/resolution/import-resolver.d.ts +53 -29
  540. package/dist/resolution/import-resolver.d.ts.map +1 -0
  541. package/dist/resolution/import-resolver.js +1319 -8
  542. package/dist/resolution/import-resolver.js.map +1 -0
  543. package/dist/resolution/index.d.ts +243 -103
  544. package/dist/resolution/index.d.ts.map +1 -0
  545. package/dist/resolution/index.js +1055 -53
  546. package/dist/resolution/index.js.map +1 -0
  547. package/dist/resolution/lru-cache.d.ts +9 -9
  548. package/dist/resolution/lru-cache.d.ts.map +1 -0
  549. package/dist/resolution/lru-cache.js.map +1 -0
  550. package/dist/resolution/name-matcher.d.ts +91 -29
  551. package/dist/resolution/name-matcher.d.ts.map +1 -0
  552. package/dist/resolution/name-matcher.js +1478 -32
  553. package/dist/resolution/name-matcher.js.map +1 -0
  554. package/dist/resolution/path-aliases.d.ts +23 -27
  555. package/dist/resolution/path-aliases.d.ts.map +1 -0
  556. package/dist/resolution/path-aliases.js.map +1 -0
  557. package/dist/resolution/strip-comments.d.ts +3 -16
  558. package/dist/resolution/strip-comments.d.ts.map +1 -0
  559. package/dist/resolution/strip-comments.js +51 -0
  560. package/dist/resolution/strip-comments.js.map +1 -0
  561. package/dist/resolution/swift-objc-bridge.d.ts +134 -0
  562. package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  563. package/dist/resolution/swift-objc-bridge.js +256 -0
  564. package/dist/resolution/swift-objc-bridge.js.map +1 -0
  565. package/dist/resolution/types.d.ts +217 -136
  566. package/dist/resolution/types.d.ts.map +1 -0
  567. package/dist/resolution/types.js.map +1 -0
  568. package/dist/resolution/workspace-packages.d.ts +58 -0
  569. package/dist/resolution/workspace-packages.d.ts.map +1 -0
  570. package/dist/resolution/workspace-packages.js +346 -0
  571. package/dist/resolution/workspace-packages.js.map +1 -0
  572. package/dist/search/identifier-segments.d.ts +60 -0
  573. package/dist/search/identifier-segments.d.ts.map +1 -0
  574. package/dist/search/identifier-segments.js +176 -0
  575. package/dist/search/identifier-segments.js.map +1 -0
  576. package/dist/search/query-parser.d.ts +14 -18
  577. package/dist/search/query-parser.d.ts.map +1 -0
  578. package/dist/search/query-parser.js.map +1 -0
  579. package/dist/search/query-utils.d.ts +45 -17
  580. package/dist/search/query-utils.d.ts.map +1 -0
  581. package/dist/search/query-utils.js +113 -47
  582. package/dist/search/query-utils.js.map +1 -0
  583. package/dist/sync/git-hooks.d.ts +13 -22
  584. package/dist/sync/git-hooks.d.ts.map +1 -0
  585. package/dist/sync/git-hooks.js +4 -0
  586. package/dist/sync/git-hooks.js.map +1 -0
  587. package/dist/sync/index.d.ts +6 -12
  588. package/dist/sync/index.d.ts.map +1 -0
  589. package/dist/sync/index.js +8 -1
  590. package/dist/sync/index.js.map +1 -0
  591. package/dist/sync/watch-policy.d.ts +8 -11
  592. package/dist/sync/watch-policy.d.ts.map +1 -0
  593. package/dist/sync/watch-policy.js.map +1 -0
  594. package/dist/sync/watcher.d.ts +335 -63
  595. package/dist/sync/watcher.d.ts.map +1 -0
  596. package/dist/sync/watcher.js +709 -53
  597. package/dist/sync/watcher.js.map +1 -0
  598. package/dist/sync/worktree.d.ts +63 -0
  599. package/dist/sync/worktree.d.ts.map +1 -0
  600. package/dist/sync/worktree.js +182 -0
  601. package/dist/sync/worktree.js.map +1 -0
  602. package/dist/telemetry/index.d.ts +143 -0
  603. package/dist/telemetry/index.d.ts.map +1 -0
  604. package/dist/telemetry/index.js +541 -0
  605. package/dist/telemetry/index.js.map +1 -0
  606. package/dist/types.d.ts +308 -326
  607. package/dist/types.d.ts.map +1 -0
  608. package/dist/types.js +16 -0
  609. package/dist/types.js.map +1 -0
  610. package/dist/ui/glyphs.d.ts +20 -20
  611. package/dist/ui/glyphs.d.ts.map +1 -0
  612. package/dist/ui/glyphs.js +78 -0
  613. package/dist/ui/glyphs.js.map +1 -0
  614. package/dist/ui/shimmer-progress.d.ts +7 -7
  615. package/dist/ui/shimmer-progress.d.ts.map +1 -0
  616. package/dist/ui/shimmer-progress.js +90 -0
  617. package/dist/ui/shimmer-progress.js.map +1 -0
  618. package/dist/ui/shimmer-worker.d.ts +2 -2
  619. package/dist/ui/shimmer-worker.d.ts.map +1 -0
  620. package/dist/ui/shimmer-worker.js +118 -0
  621. package/dist/ui/shimmer-worker.js.map +1 -0
  622. package/dist/ui/types.d.ts +14 -17
  623. package/dist/ui/types.d.ts.map +1 -0
  624. package/dist/ui/types.js +3 -0
  625. package/dist/ui/types.js.map +1 -0
  626. package/dist/upgrade/index.d.ts +164 -0
  627. package/dist/upgrade/index.d.ts.map +1 -0
  628. package/dist/upgrade/index.js +646 -0
  629. package/dist/upgrade/index.js.map +1 -0
  630. package/dist/upgrade/remove-binary.d.ts +87 -0
  631. package/dist/upgrade/remove-binary.d.ts.map +1 -0
  632. package/dist/upgrade/remove-binary.js +289 -0
  633. package/dist/upgrade/remove-binary.js.map +1 -0
  634. package/dist/upgrade/update-check.d.ts +92 -0
  635. package/dist/upgrade/update-check.d.ts.map +1 -0
  636. package/dist/upgrade/update-check.js +258 -0
  637. package/dist/upgrade/update-check.js.map +1 -0
  638. package/dist/utils.d.ts +116 -123
  639. package/dist/utils.d.ts.map +1 -0
  640. package/dist/utils.js +83 -49
  641. package/dist/utils.js.map +1 -0
  642. package/package.json +42 -10
  643. package/scripts/add-lang/bench.sh +60 -0
  644. package/scripts/add-lang/check-grammar.mjs +75 -0
  645. package/scripts/add-lang/dump-ast.mjs +103 -0
  646. package/scripts/add-lang/verify-extraction.mjs +70 -0
  647. package/scripts/agent-eval/ab-adoption.sh +91 -0
  648. package/scripts/agent-eval/ab-hook.sh +86 -0
  649. package/scripts/agent-eval/ab-impl.sh +78 -0
  650. package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -0
  651. package/scripts/agent-eval/ab-sufficiency.sh +78 -0
  652. package/scripts/agent-eval/arms-F.sh +21 -0
  653. package/scripts/agent-eval/arms-matrix.sh +37 -0
  654. package/scripts/agent-eval/audit.sh +68 -0
  655. package/scripts/agent-eval/bench-readme.sh +28 -0
  656. package/scripts/agent-eval/bench-why-repo.sh +22 -0
  657. package/scripts/agent-eval/block-read-hook.sh +19 -0
  658. package/scripts/agent-eval/hook-settings.json +15 -0
  659. package/scripts/agent-eval/itrun.sh +120 -0
  660. package/scripts/agent-eval/offload-eval-3arm.sh +72 -0
  661. package/scripts/agent-eval/offload-eval-cost.mjs +133 -0
  662. package/scripts/agent-eval/offload-eval-effort.mjs +108 -0
  663. package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -0
  664. package/scripts/agent-eval/offload-eval-frontload.sh +47 -0
  665. package/scripts/agent-eval/offload-eval-ground-truth.json +18 -0
  666. package/scripts/agent-eval/offload-eval-hook.mjs +84 -0
  667. package/scripts/agent-eval/offload-eval-judge.mjs +103 -0
  668. package/scripts/agent-eval/offload-eval-matrix.sh +20 -0
  669. package/scripts/agent-eval/offload-eval-metrics.mjs +94 -0
  670. package/scripts/agent-eval/offload-eval-refs1.sh +50 -0
  671. package/scripts/agent-eval/offload-eval-setup.sh +24 -0
  672. package/scripts/agent-eval/offload-eval-styles.sh +72 -0
  673. package/scripts/agent-eval/offload-eval-summarize.mjs +68 -0
  674. package/scripts/agent-eval/offload-eval.md +76 -0
  675. package/scripts/agent-eval/parse-arms.mjs +116 -0
  676. package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
  677. package/scripts/agent-eval/parse-run.mjs +45 -0
  678. package/scripts/agent-eval/parse-session.mjs +93 -0
  679. package/scripts/agent-eval/probe-context.mjs +21 -0
  680. package/scripts/agent-eval/probe-explore.mjs +40 -0
  681. package/scripts/agent-eval/probe-node.mjs +20 -0
  682. package/scripts/agent-eval/probe-sweep.mjs +119 -0
  683. package/scripts/agent-eval/probe-trace.mjs +20 -0
  684. package/scripts/agent-eval/redirect-read-hook.sh +38 -0
  685. package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
  686. package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
  687. package/scripts/agent-eval/run-agent.sh +34 -0
  688. package/scripts/agent-eval/run-all.sh +75 -0
  689. package/scripts/agent-eval/run-arms.sh +56 -0
  690. package/scripts/agent-eval/seq-matrix.mjs +137 -0
  691. package/scripts/build-bundle.sh +123 -0
  692. package/scripts/extract-release-notes.mjs +130 -0
  693. package/scripts/local-install.sh +41 -0
  694. package/scripts/npm-sdk.js +75 -0
  695. package/scripts/npm-shim.js +275 -0
  696. package/scripts/pack-npm.sh +119 -0
  697. package/scripts/prepare-release.mjs +270 -0
  698. package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
  699. package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
  700. package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
  701. package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  702. package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  703. package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  704. package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
  705. package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
  706. package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  707. package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
  708. package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
  709. package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
  710. package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  711. package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  712. package/dist/installer/claude-md-template.d.ts +0 -19
@@ -48,9 +48,28 @@ const path = __importStar(require("path"));
48
48
  const name_matcher_1 = require("./name-matcher");
49
49
  const import_resolver_1 = require("./import-resolver");
50
50
  const frameworks_1 = require("./frameworks");
51
+ const callback_synthesizer_1 = require("./callback-synthesizer");
52
+ const cooperative_yield_1 = require("./cooperative-yield");
51
53
  const path_aliases_1 = require("./path-aliases");
54
+ const go_module_1 = require("./go-module");
55
+ const workspace_packages_1 = require("./workspace-packages");
52
56
  const errors_1 = require("../errors");
53
57
  const lru_cache_1 = require("./lru-cache");
58
+ /** Node kinds that can declare supertypes (extends/implements). */
59
+ const SUPERTYPE_BEARING_KINDS = new Set([
60
+ 'class', 'struct', 'interface', 'trait', 'protocol', 'enum',
61
+ ]);
62
+ /**
63
+ * Languages whose chained static-factory/fluent calls defer to the conformance
64
+ * second pass. Dotted-receiver languages resolve via matchDottedCallChain; the
65
+ * `::`-receiver ones (Rust) via matchScopedCallChain.
66
+ */
67
+ const CHAIN_LANGUAGES = new Set(['java', 'kotlin', 'csharp', 'swift', 'rust', 'go', 'scala', 'dart', 'objc', 'pascal']);
68
+ const SCOPED_CHAIN_LANGUAGES = new Set(['rust']);
69
+ /** The extractor's chained-receiver encoding: `<inner>().<method>`. */
70
+ const CHAIN_SHAPE = /^(.+)\(\)\.(\w+)$/;
71
+ /** PHP `$this->prop->method()` encoded as `this->prop.method` — no `()`, so CHAIN_SHAPE misses it. */
72
+ const PHP_PROP_SHAPE = /^this->\w+\.\w+$/;
54
73
  /**
55
74
  * Cache size limits. Each per-resolver cache is bounded so memory
56
75
  * stays flat on large codebases (20k+ files). Sizes were chosen to
@@ -147,6 +166,47 @@ const PASCAL_BUILT_INS = new Set([
147
166
  'Exception', 'EAbort', 'EConvertError', 'EAccessViolation',
148
167
  'IInterface', 'IUnknown',
149
168
  ]);
169
+ const C_BUILT_INS = new Set([
170
+ // Standard C library functions
171
+ 'printf', 'fprintf', 'sprintf', 'snprintf', 'scanf', 'fscanf', 'sscanf',
172
+ 'malloc', 'calloc', 'realloc', 'free',
173
+ 'memcpy', 'memmove', 'memset', 'memcmp', 'memchr',
174
+ 'strlen', 'strcpy', 'strncpy', 'strcat', 'strncat', 'strcmp', 'strncmp',
175
+ 'strstr', 'strchr', 'strrchr', 'strtok', 'strdup',
176
+ 'fopen', 'fclose', 'fread', 'fwrite', 'fgets', 'fputs', 'fputc', 'fgetc',
177
+ 'feof', 'ferror', 'fflush', 'fseek', 'ftell', 'rewind',
178
+ 'exit', 'abort', 'atexit', 'atoi', 'atol', 'atof', 'strtol', 'strtoul', 'strtod',
179
+ 'qsort', 'bsearch',
180
+ 'abs', 'labs', 'rand', 'srand',
181
+ 'sin', 'cos', 'tan', 'sqrt', 'pow', 'log', 'log10', 'exp', 'ceil', 'floor', 'fabs',
182
+ 'time', 'clock', 'difftime', 'mktime', 'localtime', 'gmtime', 'strftime', 'asctime',
183
+ 'assert', 'errno',
184
+ 'perror', 'remove', 'rename', 'tmpfile', 'tmpnam',
185
+ 'getenv', 'system',
186
+ 'signal', 'raise',
187
+ 'setjmp', 'longjmp',
188
+ 'va_start', 'va_end', 'va_arg', 'va_copy',
189
+ 'NULL', 'EOF', 'BUFSIZ', 'FILENAME_MAX', 'RAND_MAX', 'EXIT_SUCCESS', 'EXIT_FAILURE',
190
+ 'size_t', 'ptrdiff_t', 'wchar_t', 'intptr_t', 'uintptr_t',
191
+ 'int8_t', 'int16_t', 'int32_t', 'int64_t',
192
+ 'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t',
193
+ 'FILE',
194
+ // POSIX additions commonly seen
195
+ 'stat', 'lstat', 'fstat', 'open', 'close', 'read', 'write', 'pipe',
196
+ 'fork', 'exec', 'waitpid', 'getpid', 'getppid', 'kill', 'sleep', 'usleep',
197
+ 'pthread_create', 'pthread_join', 'pthread_mutex_lock', 'pthread_mutex_unlock',
198
+ 'dlopen', 'dlsym', 'dlclose',
199
+ ]);
200
+ const CPP_BUILT_INS = new Set([
201
+ // iostream objects (often used without std:: prefix via using)
202
+ 'cout', 'cin', 'cerr', 'clog', 'endl', 'flush', 'ws',
203
+ 'std', // the namespace itself when used as std::something
204
+ // Common C++ keywords that leak as references
205
+ 'nullptr', 'true', 'false', 'this', 'sizeof', 'alignof', 'typeid',
206
+ 'static_cast', 'dynamic_cast', 'reinterpret_cast', 'const_cast',
207
+ 'make_unique', 'make_shared', 'make_pair',
208
+ 'move', 'forward', 'swap',
209
+ ]);
150
210
  /**
151
211
  * Reference Resolver
152
212
  *
@@ -157,6 +217,21 @@ class ReferenceResolver {
157
217
  queries;
158
218
  context;
159
219
  frameworks = [];
220
+ // Chained static-factory/fluent call refs the first pass couldn't resolve,
221
+ // collected in-memory (the batched resolver deletes unresolved refs from the
222
+ // DB, so they can't be re-read). Drained by resolveChainedCallsViaConformance
223
+ // once implements/extends edges exist, to resolve methods on a supertype the
224
+ // receiver conforms to (#750).
225
+ deferredChainRefs = [];
226
+ // `this.<member>` function-as-value refs whose member is NOT on the
227
+ // enclosing class itself — possibly inherited. Collected in-memory for the
228
+ // same reason as deferredChainRefs and drained by
229
+ // resolveDeferredThisMemberRefs once implements/extends edges exist (#808).
230
+ deferredThisMemberRefs = [];
231
+ // Per-`.razor`/`.cshtml`-file `@using` namespace set (own directives + folder
232
+ // `_Imports.razor`, cascading to the project root). Used to disambiguate a
233
+ // markup type ref to the right C# namespace.
234
+ razorUsingsCache = new Map();
160
235
  // All per-resolver caches are LRU-bounded. Previously these were
161
236
  // unbounded Maps that grew with every distinct lookup and OOM'd on
162
237
  // codebases with 20k+ files (see issue: unbounded cache growth).
@@ -167,6 +242,17 @@ class ReferenceResolver {
167
242
  nameCache; // name → nodes cache
168
243
  lowerNameCache; // lower(name) → nodes cache
169
244
  qualifiedNameCache; // qualified_name → nodes cache
245
+ fileLinesCache; // file → split lines cache
246
+ methodMatchCache; // lang\0Type::method → matching method nodes
247
+ // Node kinds are a small fixed set (~24), so this is a plain Map, not an LRU.
248
+ // getNodesByKind returns the FULL node list for a kind; it was previously
249
+ // uncached — a per-ref `SELECT * FROM nodes WHERE kind=?` + row-mapping. Called
250
+ // for every dotted call ref by the Spring resolver (constants) and every
251
+ // `hook_` ref by the Drupal resolver (functions), that scan dominated
252
+ // resolution on large repos (#1180). The node set is stable within a
253
+ // resolution pass (same lifetime assumption as nameCache); clearCaches() resets
254
+ // it between passes. Callers must treat the returned array as read-only.
255
+ nodesByKindCache = new Map();
170
256
  knownNames = null; // all known symbol names for fast pre-filtering
171
257
  knownFiles = null;
172
258
  cachesWarmed = false;
@@ -174,6 +260,10 @@ class ReferenceResolver {
174
260
  // `null` = computed and absent. Treated as immutable for the
175
261
  // resolver's lifetime; callers re-create the resolver if config changes.
176
262
  projectAliases = undefined;
263
+ // go.mod module path. Same lazy/immutable convention as projectAliases.
264
+ goModule = undefined;
265
+ // Monorepo workspace member packages. Same lazy/immutable convention.
266
+ workspacePackages = undefined;
177
267
  constructor(projectRoot, queries) {
178
268
  this.projectRoot = projectRoot;
179
269
  this.queries = queries;
@@ -188,6 +278,10 @@ class ReferenceResolver {
188
278
  this.nameCache = new lru_cache_1.LRUCache(limit);
189
279
  this.lowerNameCache = new lru_cache_1.LRUCache(limit);
190
280
  this.qualifiedNameCache = new lru_cache_1.LRUCache(limit);
281
+ // Split-lines arrays are heavier than content strings; refs arrive
282
+ // file-ordered, so a small cache still hits nearly always.
283
+ this.fileLinesCache = new lru_cache_1.LRUCache(contentLimit);
284
+ this.methodMatchCache = new lru_cache_1.LRUCache(limit);
191
285
  this.context = this.createContext();
192
286
  }
193
287
  /**
@@ -197,6 +291,37 @@ class ReferenceResolver {
197
291
  this.frameworks = (0, frameworks_1.detectFrameworks)(this.context);
198
292
  this.clearCaches();
199
293
  }
294
+ /**
295
+ * Run each framework resolver's cross-file finalization pass and persist
296
+ * the returned node updates. Idempotent — safe to call after every indexAll
297
+ * and every incremental sync. Returns the number of nodes updated.
298
+ *
299
+ * Caches are cleared before/after so the post-extract pass sees fresh DB
300
+ * state and downstream queries see the updated names.
301
+ */
302
+ runPostExtract() {
303
+ let updated = 0;
304
+ this.clearCaches();
305
+ for (const fw of this.frameworks) {
306
+ if (!fw.postExtract)
307
+ continue;
308
+ try {
309
+ const nodes = fw.postExtract(this.context);
310
+ for (const node of nodes) {
311
+ this.queries.updateNode(node);
312
+ updated++;
313
+ }
314
+ }
315
+ catch (err) {
316
+ (0, errors_1.logDebug)(`Framework '${fw.name}' postExtract failed`, {
317
+ error: err instanceof Error ? err.message : String(err),
318
+ });
319
+ }
320
+ }
321
+ if (updated > 0)
322
+ this.clearCaches();
323
+ return updated;
324
+ }
200
325
  /**
201
326
  * Pre-build lightweight caches for resolution.
202
327
  * Node lookups are now handled by indexed SQLite queries instead of
@@ -212,6 +337,28 @@ class ReferenceResolver {
212
337
  this.knownNames = new Set(this.queries.getAllNodeNames());
213
338
  this.cachesWarmed = true;
214
339
  }
340
+ /**
341
+ * warmCaches for the async resolution entry points: streams the distinct
342
+ * name set with periodic yields instead of one synchronous `.all()`. On a
343
+ * multi-million-node index the DISTINCT scan is a solid multi-second block
344
+ * (measured up to 28s inside `codegraph sync` on the Linux kernel index),
345
+ * long enough to matter to the #850 watchdog on slower hardware. Same
346
+ * result, same memory — only the event loop keeps turning.
347
+ */
348
+ async warmCachesYielding(onYield) {
349
+ if (this.cachesWarmed)
350
+ return;
351
+ this.knownFiles = new Set(this.queries.getAllFilePaths());
352
+ const names = new Set();
353
+ let scanned = 0;
354
+ for (const name of this.queries.iterateNodeNames()) {
355
+ names.add(name);
356
+ if ((++scanned & 8191) === 0)
357
+ await onYield();
358
+ }
359
+ this.knownNames = names;
360
+ this.cachesWarmed = true;
361
+ }
215
362
  /**
216
363
  * Clear internal caches
217
364
  */
@@ -223,10 +370,30 @@ class ReferenceResolver {
223
370
  this.nameCache.clear();
224
371
  this.lowerNameCache.clear();
225
372
  this.qualifiedNameCache.clear();
373
+ this.fileLinesCache.clear();
374
+ this.methodMatchCache.clear();
375
+ this.nodesByKindCache.clear();
226
376
  this.knownNames = null;
227
377
  this.knownFiles = null;
228
378
  this.cachesWarmed = false;
229
379
  }
380
+ /** `readFile` through the LRU content cache (null = read failed, also cached). */
381
+ readFileCached(filePath) {
382
+ if (this.fileCache.has(filePath)) {
383
+ return this.fileCache.get(filePath);
384
+ }
385
+ const fullPath = path.join(this.projectRoot, filePath);
386
+ try {
387
+ const content = fs.readFileSync(fullPath, 'utf-8');
388
+ this.fileCache.set(filePath, content);
389
+ return content;
390
+ }
391
+ catch (error) {
392
+ (0, errors_1.logDebug)('Failed to read file for resolution', { filePath, error: String(error) });
393
+ this.fileCache.set(filePath, null);
394
+ return null;
395
+ }
396
+ }
230
397
  /**
231
398
  * Create the resolution context
232
399
  */
@@ -246,6 +413,30 @@ class ReferenceResolver {
246
413
  this.nameCache.set(name, result);
247
414
  return result;
248
415
  },
416
+ getMethodMatches: (typeName, methodName, language) => {
417
+ const key = `${language} ${typeName}::${methodName}`;
418
+ const cached = this.methodMatchCache.get(key);
419
+ if (cached !== undefined)
420
+ return cached;
421
+ let candidates = this.nameCache.get(methodName);
422
+ if (candidates === undefined) {
423
+ candidates = this.queries.getNodesByName(methodName);
424
+ this.nameCache.set(methodName, candidates);
425
+ }
426
+ const want = `${typeName}::${methodName}`;
427
+ const matches = [];
428
+ for (const m of candidates) {
429
+ if (m.kind !== 'method')
430
+ continue;
431
+ if (m.language !== language)
432
+ continue;
433
+ const qn = m.qualifiedName;
434
+ if (qn === want || qn.endsWith(`::${want}`))
435
+ matches.push(m);
436
+ }
437
+ this.methodMatchCache.set(key, matches);
438
+ return matches;
439
+ },
249
440
  getNodesByQualifiedName: (qualifiedName) => {
250
441
  const cached = this.qualifiedNameCache.get(qualifiedName);
251
442
  if (cached !== undefined)
@@ -255,8 +446,18 @@ class ReferenceResolver {
255
446
  return result;
256
447
  },
257
448
  getNodesByKind: (kind) => {
258
- return this.queries.getNodesByKind(kind);
449
+ const cached = this.nodesByKindCache.get(kind);
450
+ if (cached !== undefined)
451
+ return cached;
452
+ const result = this.queries.getNodesByKind(kind);
453
+ this.nodesByKindCache.set(kind, result);
454
+ return result;
259
455
  },
456
+ // Streamed, uncached — synthesizers scan-and-filter whole kinds, and
457
+ // both the materialized array AND the per-kind cache retention are
458
+ // O(nodes) memory (#1212). Per-ref resolvers keep the cached array
459
+ // variant above.
460
+ iterateNodesByKind: (kind) => this.queries.iterateNodesByKind(kind),
260
461
  fileExists: (filePath) => {
261
462
  // Check pre-built known files set first (O(1))
262
463
  if (this.knownFiles) {
@@ -275,21 +476,15 @@ class ReferenceResolver {
275
476
  return false;
276
477
  }
277
478
  },
278
- readFile: (filePath) => {
279
- if (this.fileCache.has(filePath)) {
280
- return this.fileCache.get(filePath);
281
- }
282
- const fullPath = path.join(this.projectRoot, filePath);
283
- try {
284
- const content = fs.readFileSync(fullPath, 'utf-8');
285
- this.fileCache.set(filePath, content);
286
- return content;
287
- }
288
- catch (error) {
289
- (0, errors_1.logDebug)('Failed to read file for resolution', { filePath, error: String(error) });
290
- this.fileCache.set(filePath, null);
291
- return null;
292
- }
479
+ readFile: (filePath) => this.readFileCached(filePath),
480
+ getFileLines: (filePath) => {
481
+ const cached = this.fileLinesCache.get(filePath);
482
+ if (cached !== undefined)
483
+ return cached;
484
+ const source = this.readFileCached(filePath);
485
+ const lines = source === null ? null : source.split(/\r?\n/);
486
+ this.fileLinesCache.set(filePath, lines);
487
+ return lines;
293
488
  },
294
489
  getProjectRoot: () => this.projectRoot,
295
490
  getAllFiles: () => {
@@ -321,6 +516,29 @@ class ReferenceResolver {
321
516
  this.lowerNameCache.set(lowerName, result);
322
517
  return result;
323
518
  },
519
+ getNodeById: (id) => {
520
+ return this.queries.getNodeById(id);
521
+ },
522
+ getSupertypes: (typeName, language) => {
523
+ // Union the `implements`/`extends` targets of every same-named type node.
524
+ // Matching by simple name (not id) reconciles a type declared in one node
525
+ // (`KF::Builder`) with conformance declared in a separate extension node
526
+ // (`KF.Builder: KFOptionSetter`) — both have name `Builder`.
527
+ const typeNodes = this.context
528
+ .getNodesByName(typeName)
529
+ .filter((n) => SUPERTYPE_BEARING_KINDS.has(n.kind) && n.language === language);
530
+ if (typeNodes.length === 0)
531
+ return [];
532
+ const supertypes = new Set();
533
+ for (const tn of typeNodes) {
534
+ for (const edge of this.queries.getOutgoingEdges(tn.id, ['implements', 'extends'])) {
535
+ const target = this.queries.getNodeById(edge.target);
536
+ if (target?.name && target.name !== typeName)
537
+ supertypes.add(target.name);
538
+ }
539
+ }
540
+ return [...supertypes];
541
+ },
324
542
  getImportMappings: (filePath, language) => {
325
543
  const cacheKey = filePath;
326
544
  const cached = this.importMappingCache.get(cacheKey);
@@ -341,6 +559,18 @@ class ReferenceResolver {
341
559
  }
342
560
  return this.projectAliases;
343
561
  },
562
+ getGoModule: () => {
563
+ if (this.goModule === undefined) {
564
+ this.goModule = (0, go_module_1.loadGoModule)(this.projectRoot);
565
+ }
566
+ return this.goModule;
567
+ },
568
+ getWorkspacePackages: () => {
569
+ if (this.workspacePackages === undefined) {
570
+ this.workspacePackages = (0, workspace_packages_1.loadWorkspacePackages)(this.projectRoot);
571
+ }
572
+ return this.workspacePackages;
573
+ },
344
574
  getReExports: (filePath, language) => {
345
575
  const cached = this.reExportCache.get(filePath);
346
576
  if (cached)
@@ -350,10 +580,21 @@ class ReferenceResolver {
350
580
  this.reExportCache.set(filePath, []);
351
581
  return [];
352
582
  }
353
- const reExports = (0, import_resolver_1.extractReExports)(content, language);
583
+ // Re-exports are a JS/TS-only construct, and what matters is the
584
+ // BARREL file's own language — not the consuming reference's. A
585
+ // `.svelte`/`.vue` consumer threads its own language down the
586
+ // re-export chase, which would make extractReExports() bail on a
587
+ // `.ts` index barrel and silently break the chain (#629). Re-key
588
+ // the parse on the barrel's extension so the chase works no matter
589
+ // what kind of file imports through it.
590
+ const isJsFamily = /\.(?:d\.ts|[cm]?tsx?|[cm]?jsx?|ets)$/i.test(filePath);
591
+ const reExports = (0, import_resolver_1.extractReExports)(content, isJsFamily ? 'typescript' : language);
354
592
  this.reExportCache.set(filePath, reExports);
355
593
  return reExports;
356
594
  },
595
+ getCppIncludeDirs: () => {
596
+ return (0, import_resolver_1.loadCppIncludeDirs)(this.projectRoot);
597
+ },
357
598
  };
358
599
  }
359
600
  /**
@@ -374,7 +615,7 @@ class ReferenceResolver {
374
615
  column: ref.column,
375
616
  filePath: ref.filePath || this.getFilePathFromNodeId(ref.fromNodeId),
376
617
  language: ref.language || this.getLanguageFromNodeId(ref.fromNodeId),
377
- })).filter((ref) => ref.referenceName != null && ref.referenceName !== '');
618
+ }));
378
619
  const total = refs.length;
379
620
  let lastReportedPercent = -1;
380
621
  for (let i = 0; i < refs.length; i++) {
@@ -433,6 +674,15 @@ class ReferenceResolver {
433
674
  const capitalized = receiver.charAt(0).toUpperCase() + receiver.slice(1);
434
675
  if (this.knownNames.has(capitalized))
435
676
  return true;
677
+ // JVM FQN: `com.example.foo.Bar` — the only useful segment is the
678
+ // last one (`Bar`); the earlier check finds `example.foo.Bar` which
679
+ // never matches a node name.
680
+ const lastDot = name.lastIndexOf('.');
681
+ if (lastDot > dotIdx) {
682
+ const tail = name.substring(lastDot + 1);
683
+ if (tail && this.knownNames.has(tail))
684
+ return true;
685
+ }
436
686
  }
437
687
  const colonIdx = name.indexOf('::');
438
688
  if (colonIdx > 0) {
@@ -440,6 +690,35 @@ class ReferenceResolver {
440
690
  const member = name.substring(colonIdx + 2);
441
691
  if (this.knownNames.has(receiver) || this.knownNames.has(member))
442
692
  return true;
693
+ // Multi-segment path `a::b::c` (a Rust/C++ module call like
694
+ // `database::profiles::find`) — the only segment that names a symbol is
695
+ // the last (`c`); `member` above is `b::c`, which never matches a node
696
+ // name, so without this the pre-filter drops the ref before the Rust path
697
+ // resolver ever sees it. Mirror the dotted-name leaf check above.
698
+ const lastColon = name.lastIndexOf('::');
699
+ if (lastColon > colonIdx) {
700
+ const tail = name.substring(lastColon + 2);
701
+ if (tail && this.knownNames.has(tail))
702
+ return true;
703
+ }
704
+ }
705
+ // Lua/Luau method calls use a single `:` (`lg:log`); R uses `$` (`lg$log`).
706
+ // Check the member (and receiver) around these separators too, so the ref
707
+ // isn't dropped here before the method-call resolver ever sees it. The `:`
708
+ // case is skipped when the name actually contains `::` (handled above).
709
+ for (const sep of [':', '$']) {
710
+ if (sep === ':' && name.includes('::'))
711
+ continue;
712
+ const sepIdx = name.indexOf(sep);
713
+ if (sepIdx > 0) {
714
+ const receiver = name.substring(0, sepIdx);
715
+ const member = name.substring(sepIdx + 1);
716
+ if (this.knownNames.has(member) || this.knownNames.has(receiver))
717
+ return true;
718
+ const capitalized = receiver.charAt(0).toUpperCase() + receiver.slice(1);
719
+ if (this.knownNames.has(capitalized))
720
+ return true;
721
+ }
443
722
  }
444
723
  // For path-like references (e.g., "snippets/drawer-menu.liquid"), check the filename
445
724
  const slashIdx = name.lastIndexOf('/');
@@ -475,19 +754,84 @@ class ReferenceResolver {
475
754
  if (this.isBuiltInOrExternal(ref)) {
476
755
  return null;
477
756
  }
757
+ // CFML component paths in inheritance (#1152): `extends="coldbox.system.web.
758
+ // Controller"` names the supertype by its dot-separated path (or `extends=
759
+ // "../base"` by relative file path) — the graph indexes the class under its
760
+ // final segment only, so these die at the fast pre-filter below and never
761
+ // resolved. Handled by a dedicated path-corroborated matcher, gated to
762
+ // inheritance refs only (a dotted `calls` ref is a member-access chain, not
763
+ // a component path). No fallthrough on miss: the full path string can only
764
+ // ever mis-match downstream, and an unresolvable supertype usually lives in
765
+ // an out-of-repo library (mxunit, testbox) — silent beats wrong.
766
+ if ((ref.language === 'cfml' || ref.language === 'cfscript') &&
767
+ (ref.referenceKind === 'extends' || ref.referenceKind === 'implements') &&
768
+ (ref.referenceName.includes('.') || ref.referenceName.includes('/'))) {
769
+ return this.resolveCfmlComponentPath(ref);
770
+ }
478
771
  // Fast pre-filter: skip if no symbol with this name exists anywhere
479
772
  // AND the name doesn't match a local import. The import escape is
480
773
  // necessary because re-export rename chains (`import { login }
481
774
  // from './barrel'` where the barrel has `export { signIn as login }
482
775
  // from './auth'`) intentionally call a name that has no
483
776
  // declaration anywhere — only the renamed upstream symbol does.
484
- if (!this.hasAnyPossibleMatch(ref.referenceName) && !this.matchesAnyImport(ref)) {
777
+ // ArkTS chained-attribute refs carry a leading dot (`.titleStyle`) that
778
+ // routes them to the decorator-gated matcher; the symbol itself is
779
+ // indexed under the bare name, so the existence check strips the dot.
780
+ // Nix static path imports (`import ./x.nix`) name a FILE, not a symbol —
781
+ // they bypass the symbol-existence check and resolve via resolveViaImport.
782
+ const existenceName = ref.language === 'arkts' && ref.referenceName.startsWith('.')
783
+ ? ref.referenceName.slice(1)
784
+ : ref.referenceName;
785
+ if (!(0, import_resolver_1.isNixPathImportRef)(ref) &&
786
+ !this.hasAnyPossibleMatch(existenceName) &&
787
+ !this.matchesAnyImport(ref) &&
788
+ !this.frameworks.some((f) => f.claimsReference?.(ref.referenceName))) {
485
789
  return null;
486
790
  }
791
+ // Function-as-value refs (#756) get a dedicated, strictly-gated path:
792
+ // import-based resolution first (an imported callback resolves through its
793
+ // import, the most precise cross-file signal), then matchFunctionRef
794
+ // (same-file first, unique-only cross-file, function/method targets only).
795
+ // They never reach the framework or fuzzy strategies below.
796
+ if (ref.referenceKind === 'function_ref') {
797
+ // `this.<member>` values (TS/JS) resolve ONLY against the enclosing
798
+ // class's own members — never a same-named symbol elsewhere.
799
+ if (ref.referenceName.startsWith('this.')) {
800
+ return this.gateLanguage(this.resolveThisMemberFnRef(ref), ref);
801
+ }
802
+ const viaImport = this.gateLanguage((0, import_resolver_1.resolveViaImport)(ref, this.context), ref);
803
+ if (viaImport) {
804
+ const target = this.queries.getNodeById(viaImport.targetNodeId);
805
+ if (target && (target.kind === 'function' || target.kind === 'method')) {
806
+ return viaImport;
807
+ }
808
+ }
809
+ return this.gateLanguage((0, name_matcher_1.matchFunctionRef)(ref, this.context), ref);
810
+ }
811
+ // JVM FQN imports skip framework/name-matcher: `import com.example.Bar`
812
+ // resolves directly through the qualifiedName index, which is unambiguous
813
+ // even when several `Bar` classes exist in different packages.
814
+ const jvmImport = (0, import_resolver_1.resolveJvmImport)(ref, this.context);
815
+ if (jvmImport)
816
+ return jvmImport;
817
+ // Razor/Blazor: a markup or `@code` type ref resolves through the file's
818
+ // `@using` namespaces (incl. folder `_Imports.razor`). This precisely
819
+ // disambiguates a simple name that exists in several namespaces — e.g.
820
+ // `CatalogBrand` resolving to `BlazorShared.Models::CatalogBrand` (the DTO,
821
+ // which the `.razor` `@using`s) rather than the same-named domain entity.
822
+ if (ref.language === 'razor') {
823
+ const razorResult = this.resolveRazorUsing(ref);
824
+ if (razorResult)
825
+ return razorResult;
826
+ }
487
827
  const candidates = [];
488
- // Strategy 1: Try framework-specific resolution
828
+ // Strategy 1: Try framework-specific resolution. Cross-language bridges
829
+ // are deliberately preserved (Drupal `routing.yml` → PHP controller, RN
830
+ // JS → native `calls`) — `gateFrameworkLanguage` only drops a type/import
831
+ // edge between two KNOWN families (see its doc), never a `calls` bridge or
832
+ // a config↔code edge.
489
833
  for (const framework of this.frameworks) {
490
- const result = framework.resolve(ref, this.context);
834
+ const result = this.gateFrameworkLanguage(framework.resolve(ref, this.context), ref);
491
835
  if (result) {
492
836
  if (result.confidence >= 0.9)
493
837
  return result; // High confidence, return immediately
@@ -495,19 +839,73 @@ class ReferenceResolver {
495
839
  }
496
840
  }
497
841
  // Strategy 2: Try import-based resolution
498
- const importResult = (0, import_resolver_1.resolveViaImport)(ref, this.context);
842
+ const importResult = this.gateLanguage((0, import_resolver_1.resolveViaImport)(ref, this.context), ref);
499
843
  if (importResult) {
500
844
  if (importResult.confidence >= 0.9)
501
845
  return importResult;
502
846
  candidates.push(importResult);
503
847
  }
848
+ // PHP include/require paths resolve to files via import resolution only.
849
+ // If that didn't find the file, do NOT fall back to the symbol
850
+ // name-matcher — it would mis-connect e.g. "inc/db.php" to an unrelated
851
+ // db.php elsewhere in the tree (a wrong edge is worse than none, #660).
852
+ // Terraform refs are directory-scoped by language semantics — the
853
+ // framework resolver IS the whole rulebook (`var.X` can never legally
854
+ // bind outside its module directory), so the name-matcher's
855
+ // qualified-name fallback would only ever add wrong cross-module edges.
856
+ // Nix static path imports are file references for the same reason —
857
+ // falling through would let "./x.nix" name-match an unrelated node.
858
+ if ((0, import_resolver_1.isPhpIncludePathRef)(ref) || (0, import_resolver_1.isCobolCopybookRef)(ref) || (0, import_resolver_1.isNixPathImportRef)(ref) || ref.language === 'terraform') {
859
+ return candidates.length > 0
860
+ ? candidates.reduce((best, curr) => curr.confidence > best.confidence ? curr : best)
861
+ : null;
862
+ }
504
863
  // Strategy 3: Try name matching
505
- const nameResult = (0, name_matcher_1.matchReference)(ref, this.context);
864
+ let nameResult = this.gateLanguage((0, name_matcher_1.matchReference)(ref, this.context), ref);
865
+ // Nix has no ambient cross-file namespace — a callee binds lexically
866
+ // (same file) or through explicit import/callPackage wiring (the import
867
+ // path above). A cross-file name match is wrong by construction: every
868
+ // module `inherit (lib) mkOption`s the same nixpkgs helpers, so the
869
+ // matcher would link each `mkOption` call to whichever file's inherit
870
+ // binding it happened to pick. Same-file matches only.
871
+ if (nameResult) {
872
+ const target = this.queries.getNodeById(nameResult.targetNodeId);
873
+ if (ref.language === 'nix') {
874
+ if (!target || target.filePath !== ref.filePath) {
875
+ nameResult = null;
876
+ }
877
+ }
878
+ else if (target && target.language === 'nix') {
879
+ // The reverse direction is just as impossible: no other language can
880
+ // symbolically call into a .nix binding (interop is eval/CLI, never a
881
+ // linkable symbol) — without this, a Python script's `split()` lands
882
+ // on some module's `split = ...` binding as a low-confidence match.
883
+ nameResult = null;
884
+ }
885
+ }
506
886
  if (nameResult) {
507
887
  candidates.push(nameResult);
508
888
  }
509
- if (candidates.length === 0)
889
+ if (candidates.length === 0) {
890
+ // Defer a chained static-factory/fluent call the first pass couldn't
891
+ // resolve — its method may live on a supertype the receiver conforms to,
892
+ // resolvable once implements/extends edges exist (the conformance pass).
893
+ if (ref.referenceKind === 'calls' &&
894
+ CHAIN_LANGUAGES.has(ref.language) &&
895
+ CHAIN_SHAPE.test(ref.referenceName)) {
896
+ this.deferredChainRefs.push(ref);
897
+ }
898
+ else if (
899
+ // PHP `$this->prop->method()` (encoded `this->prop.method`): its method
900
+ // may live on the property's declared supertype, resolvable only once
901
+ // implements/extends edges exist — defer to the same conformance pass.
902
+ ref.referenceKind === 'calls' &&
903
+ ref.language === 'php' &&
904
+ PHP_PROP_SHAPE.test(ref.referenceName)) {
905
+ this.deferredChainRefs.push(ref);
906
+ }
510
907
  return null;
908
+ }
511
909
  // Return highest confidence candidate
512
910
  return candidates.reduce((best, curr) => curr.confidence > best.confidence ? curr : best);
513
911
  }
@@ -516,7 +914,12 @@ class ReferenceResolver {
516
914
  */
517
915
  createEdges(resolved) {
518
916
  return resolved.map((ref) => {
519
- let kind = ref.original.referenceKind;
917
+ // `function_ref` (#756) is internal-only: it persists as a `references`
918
+ // edge (the registration site depends on the callback), distinguishable
919
+ // by metadata.resolvedBy === 'function-ref'. callers/impact already
920
+ // traverse `references`, so registration sites surface with no
921
+ // graph-layer changes.
922
+ let kind = ref.original.referenceKind === 'function_ref' ? 'references' : ref.original.referenceKind;
520
923
  // Promote "extends" to "implements" when a class/struct targets an interface
521
924
  if (kind === 'extends') {
522
925
  const targetNode = this.queries.getNodeById(ref.targetNodeId);
@@ -547,6 +950,23 @@ class ReferenceResolver {
547
950
  metadata: {
548
951
  confidence: ref.confidence,
549
952
  resolvedBy: ref.resolvedBy,
953
+ // The ORIGINAL reference text (and kind, when edge-kind promotion
954
+ // rewrote it — calls→instantiates, extends→implements,
955
+ // function_ref→references). If this edge's target is later removed
956
+ // by a re-index, the edge is resurrected as exactly this ref and
957
+ // re-resolved (#1240 removal case) — a faithful resurrection, so
958
+ // re-resolution can never bind anywhere a full re-index wouldn't.
959
+ // Reconstruction from the target node's name instead would strip
960
+ // receiver/qualifier context (`h.greet` → `greet`) and risk a
961
+ // wrong rebind; edges without refName (pre-#1240, synthesized) are
962
+ // deliberately NOT resurrected for the same reason.
963
+ refName: ref.original.referenceName,
964
+ ...(ref.original.referenceKind !== kind ? { refKind: ref.original.referenceKind } : {}),
965
+ // Uniform marker for function-as-value edges (#756), regardless of
966
+ // which strategy resolved them (import vs matchFunctionRef) — lets
967
+ // tooling label "callback registration" and lets validation diff
968
+ // exactly the edges this feature added.
969
+ ...(ref.original.referenceKind === 'function_ref' ? { fnRef: true } : {}),
550
970
  },
551
971
  };
552
972
  });
@@ -570,17 +990,176 @@ class ReferenceResolver {
570
990
  referenceKind: r.original.referenceKind,
571
991
  })));
572
992
  }
993
+ // Park unresolvable refs as status='failed' — parity with
994
+ // resolveAndPersistBatched. Deleting them was wrong (#1240): a ref whose
995
+ // own file never changes is otherwise gone forever, so when a DIFFERENT
996
+ // file later gains the export/symbol that would satisfy it, no sync can
997
+ // recreate the edge — only a full re-index. Failed rows are excluded from
998
+ // the pending readers, which preserves the #1187 orphan sweep's
999
+ // invariant in status form: after a COMPLETED pass nothing it processed
1000
+ // is still 'pending', so any pending row at rest belongs to an
1001
+ // interrupted run and the sweep can key off the pending count.
1002
+ if (result.unresolved.length > 0) {
1003
+ this.queries.markReferencesFailed(result.unresolved.map((r) => ({
1004
+ fromNodeId: r.fromNodeId,
1005
+ referenceName: r.referenceName,
1006
+ referenceKind: r.referenceKind,
1007
+ })));
1008
+ }
573
1009
  return result;
574
1010
  }
1011
+ /**
1012
+ * Yielding counterpart of {@link resolveAndPersist} for a caller-supplied
1013
+ * ref list — used by sync's failed-ref retry pass (#1240). Same persistence
1014
+ * semantics: resolved refs become edges and their rows are deleted;
1015
+ * still-unresolvable refs are (re-)marked failed (a no-op for rows already
1016
+ * in that status). Yields per-ref because sync can run on the daemon's
1017
+ * liveness-watchdog thread (#850/#1091) and a retry set is unbounded when
1018
+ * a large edit lands many popular symbol names at once.
1019
+ */
1020
+ async resolveAndPersistListYielding(refs) {
1021
+ const maybeYield = (0, cooperative_yield_1.createYielder)();
1022
+ const result = await this.resolveBatchYielding(refs, maybeYield);
1023
+ const PERSIST_CHUNK = 1000;
1024
+ const edges = this.createEdges(result.resolved);
1025
+ for (let i = 0; i < edges.length; i += PERSIST_CHUNK) {
1026
+ this.queries.insertEdges(edges.slice(i, i + PERSIST_CHUNK));
1027
+ await maybeYield();
1028
+ }
1029
+ const resolvedKeys = result.resolved.map((r) => ({
1030
+ fromNodeId: r.original.fromNodeId,
1031
+ referenceName: r.original.referenceName,
1032
+ referenceKind: r.original.referenceKind,
1033
+ }));
1034
+ for (let i = 0; i < resolvedKeys.length; i += PERSIST_CHUNK) {
1035
+ this.queries.deleteSpecificResolvedReferences(resolvedKeys.slice(i, i + PERSIST_CHUNK));
1036
+ await maybeYield();
1037
+ }
1038
+ const unresolvedKeys = result.unresolved.map((r) => ({
1039
+ fromNodeId: r.fromNodeId,
1040
+ referenceName: r.referenceName,
1041
+ referenceKind: r.referenceKind,
1042
+ }));
1043
+ for (let i = 0; i < unresolvedKeys.length; i += PERSIST_CHUNK) {
1044
+ this.queries.markReferencesFailed(unresolvedKeys.slice(i, i + PERSIST_CHUNK));
1045
+ await maybeYield();
1046
+ }
1047
+ return result;
1048
+ }
1049
+ /**
1050
+ * Second resolution pass for chained static-factory / fluent calls whose
1051
+ * chained method is defined on a SUPERTYPE the receiver's type conforms to —
1052
+ * a protocol-extension / inherited / default-interface method (#750). The
1053
+ * first pass can't resolve these because `implements`/`extends` edges aren't
1054
+ * built yet; this runs AFTER edges are persisted, so `context.getSupertypes`
1055
+ * (and the conformance fallback in resolveMethodOnType) can walk them.
1056
+ *
1057
+ * Operates only on the leftover unresolved refs that have the `inner().method`
1058
+ * chain shape, for the dotted-chain languages — a small set — and is idempotent
1059
+ * (re-resolving an already-resolved ref is a no-op since it's been deleted).
1060
+ * Returns the number of newly-created edges.
1061
+ */
1062
+ async resolveChainedCallsViaConformance() {
1063
+ const deferred = this.deferredChainRefs;
1064
+ this.deferredChainRefs = [];
1065
+ if (deferred.length === 0)
1066
+ return 0;
1067
+ // Read fresh edges (the main pass built the implements/extends edges after
1068
+ // these refs were deferred). matchDottedCallChain now resolves a method on a
1069
+ // supertype via context.getSupertypes -> resolveMethodOnType's conformance walk.
1070
+ this.clearCaches();
1071
+ // This post-pass runs synchronously on the indexer's main thread; yield
1072
+ // periodically so the #850 liveness watchdog heartbeat can fire on a repo
1073
+ // with many deferred chained calls (#1091).
1074
+ const maybeYield = (0, cooperative_yield_1.createYielder)();
1075
+ const resolved = [];
1076
+ for (const ref of deferred) {
1077
+ // PHP `this->prop.method` resolves via matchMethodCall (declared-type
1078
+ // inference + resolveMethodOnType conformance walk); `::`-receiver
1079
+ // languages (Rust) split on `::` (matchScopedCallChain); other
1080
+ // dotted-receiver languages on `.` (matchDottedCallChain).
1081
+ const chainMatch = (ref.language === 'php' && PHP_PROP_SHAPE.test(ref.referenceName))
1082
+ ? (0, name_matcher_1.matchMethodCall)(ref, this.context)
1083
+ : SCOPED_CHAIN_LANGUAGES.has(ref.language)
1084
+ ? (0, name_matcher_1.matchScopedCallChain)(ref, this.context)
1085
+ : (0, name_matcher_1.matchDottedCallChain)(ref, this.context);
1086
+ const match = this.gateLanguage(chainMatch, ref);
1087
+ if (match)
1088
+ resolved.push(match);
1089
+ await maybeYield();
1090
+ }
1091
+ if (resolved.length === 0)
1092
+ return 0;
1093
+ const edges = this.createEdges(resolved);
1094
+ if (edges.length > 0) {
1095
+ this.queries.insertEdges(edges);
1096
+ this.clearCaches();
1097
+ }
1098
+ return edges.length;
1099
+ }
1100
+ /**
1101
+ * Resolve one batch with a yield checkpoint between EVERY ref so the #850
1102
+ * liveness heartbeat can fire on a slow/dense batch (#1091). The checkpoint
1103
+ * granularity is per-ref — not per-N-refs — because per-ref cost is unbounded
1104
+ * in the worst case (a collision-heavy method name whose candidate set misses
1105
+ * the LRU re-fetches tens of thousands of rows): any fixed N multiplies that
1106
+ * worst case into the watchdog window, which is how v1.2.0 still got killed
1107
+ * at "Resolving refs" on large Java monorepos (#1122). `maybeYield()` is a
1108
+ * ~ns time check when under budget, so per-ref checkpoints cost nothing.
1109
+ * Behaviourally identical to `resolveAll(batch)`: `warmCaches()` is
1110
+ * idempotent (guarded) and `resolveOne` is independent per ref, so yielding
1111
+ * between refs changes only timing, never which edges get created.
1112
+ */
1113
+ async resolveBatchYielding(batch, maybeYield) {
1114
+ this.warmCaches();
1115
+ const resolved = [];
1116
+ const unresolved = [];
1117
+ const byMethod = {};
1118
+ for (const raw of batch) {
1119
+ const ref = {
1120
+ fromNodeId: raw.fromNodeId,
1121
+ referenceName: raw.referenceName,
1122
+ referenceKind: raw.referenceKind,
1123
+ line: raw.line,
1124
+ column: raw.column,
1125
+ filePath: raw.filePath || this.getFilePathFromNodeId(raw.fromNodeId),
1126
+ language: raw.language || this.getLanguageFromNodeId(raw.fromNodeId),
1127
+ };
1128
+ const result = this.resolveOne(ref);
1129
+ if (result) {
1130
+ resolved.push(result);
1131
+ byMethod[result.resolvedBy] = (byMethod[result.resolvedBy] || 0) + 1;
1132
+ }
1133
+ else {
1134
+ unresolved.push(ref);
1135
+ }
1136
+ await maybeYield();
1137
+ }
1138
+ return {
1139
+ resolved,
1140
+ unresolved,
1141
+ stats: {
1142
+ total: batch.length,
1143
+ resolved: resolved.length,
1144
+ unresolved: unresolved.length,
1145
+ byMethod,
1146
+ },
1147
+ };
1148
+ }
575
1149
  /**
576
1150
  * Resolve and persist in batches to keep memory bounded.
577
1151
  * Processes unresolved references in chunks, persisting edges and cleaning
578
1152
  * up resolved refs after each batch to avoid accumulating large arrays.
579
1153
  */
580
1154
  async resolveAndPersistBatched(onProgress, batchSize = 5000) {
581
- this.warmCaches();
582
- // Remove null/empty reference_name rows that would cause infinite batch loops
583
- this.queries.deleteNullReferenceNames();
1155
+ // Resolution runs on the indexer's MAIN thread, and the #850 liveness
1156
+ // watchdog SIGKILLs a process whose event loop stalls past its window (60s
1157
+ // by default). A single dense batch's resolveAll — or the synthesis pass
1158
+ // below — can exceed that on a large repo, killing a VALID in-progress index
1159
+ // (#1091). A shared yielder lets both give the watchdog heartbeat a regular
1160
+ // window to fire; see ./cooperative-yield.
1161
+ const maybeYield = (0, cooperative_yield_1.createYielder)();
1162
+ await this.warmCachesYielding(maybeYield);
584
1163
  const total = this.queries.getUnresolvedReferencesCount();
585
1164
  let processed = 0;
586
1165
  const aggregateStats = {
@@ -589,33 +1168,52 @@ class ReferenceResolver {
589
1168
  unresolved: 0,
590
1169
  byMethod: {},
591
1170
  };
592
- // Process in batches. We always read from offset 0 because resolved refs
593
- // are deleted after each batch, shifting the remaining rows forward.
1171
+ // Process in batches. We always read from offset 0 because every ref the
1172
+ // batch processed leaves the pending set (resolved rows are deleted,
1173
+ // unresolvable ones flip to status='failed'), shifting the remaining
1174
+ // pending rows forward.
1175
+ let prevRemaining = Number.POSITIVE_INFINITY;
594
1176
  while (true) {
595
1177
  const batch = this.queries.getUnresolvedReferencesBatch(0, batchSize);
596
1178
  if (batch.length === 0)
597
1179
  break;
598
- const result = this.resolveAll(batch);
1180
+ const result = await this.resolveBatchYielding(batch, maybeYield);
1181
+ // Persist in bounded sub-transactions with yields between: a whole
1182
+ // batch's edge insert / keyed deletes are otherwise one solid
1183
+ // synchronous span each on a multi-GB index, sitting BETWEEN the
1184
+ // per-ref yields — the last unyielded stretch of the resolution loop.
1185
+ // Crash semantics are unchanged (already several transactions): edges
1186
+ // land before their refs are deleted, so a kill mid-way re-resolves
1187
+ // the remainder idempotently on the next run/sweep (#1187).
1188
+ const PERSIST_CHUNK = 1000;
599
1189
  // Persist edges immediately
600
1190
  const edges = this.createEdges(result.resolved);
601
- if (edges.length > 0) {
602
- this.queries.insertEdges(edges);
1191
+ for (let i = 0; i < edges.length; i += PERSIST_CHUNK) {
1192
+ this.queries.insertEdges(edges.slice(i, i + PERSIST_CHUNK));
1193
+ await maybeYield();
603
1194
  }
604
1195
  // Clean up resolved refs so they don't appear in the next batch
605
- if (result.resolved.length > 0) {
606
- this.queries.deleteSpecificResolvedReferences(result.resolved.map((r) => ({
607
- fromNodeId: r.original.fromNodeId,
608
- referenceName: r.original.referenceName,
609
- referenceKind: r.original.referenceKind,
610
- })));
611
- }
612
- // Delete unresolvable refs from this batch to avoid re-processing them
613
- if (result.unresolved.length > 0) {
614
- this.queries.deleteSpecificResolvedReferences(result.unresolved.map((r) => ({
615
- fromNodeId: r.fromNodeId,
616
- referenceName: r.referenceName,
617
- referenceKind: r.referenceKind,
618
- })));
1196
+ const resolvedKeys = result.resolved.map((r) => ({
1197
+ fromNodeId: r.original.fromNodeId,
1198
+ referenceName: r.original.referenceName,
1199
+ referenceKind: r.original.referenceKind,
1200
+ }));
1201
+ for (let i = 0; i < resolvedKeys.length; i += PERSIST_CHUNK) {
1202
+ this.queries.deleteSpecificResolvedReferences(resolvedKeys.slice(i, i + PERSIST_CHUNK));
1203
+ await maybeYield();
1204
+ }
1205
+ // Park unresolvable refs from this batch as status='failed' so they
1206
+ // leave the pending set (the batch reader and non-progress guard below
1207
+ // only see pending rows) but stay retryable when a later sync adds a
1208
+ // symbol that could satisfy them (#1240).
1209
+ const unresolvedKeys = result.unresolved.map((r) => ({
1210
+ fromNodeId: r.fromNodeId,
1211
+ referenceName: r.referenceName,
1212
+ referenceKind: r.referenceKind,
1213
+ }));
1214
+ for (let i = 0; i < unresolvedKeys.length; i += PERSIST_CHUNK) {
1215
+ this.queries.markReferencesFailed(unresolvedKeys.slice(i, i + PERSIST_CHUNK));
1216
+ await maybeYield();
619
1217
  }
620
1218
  // Aggregate stats
621
1219
  aggregateStats.total += result.stats.total;
@@ -628,11 +1226,36 @@ class ReferenceResolver {
628
1226
  onProgress?.(processed, total);
629
1227
  // Yield so progress UI can render between batches
630
1228
  await new Promise(resolve => setImmediate(resolve));
631
- // If nothing was resolved or removed in this batch, we'd loop forever
632
- // on the same rows. Break to avoid infinite loop.
633
- if (result.resolved.length === 0 && result.unresolved.length === batch.length) {
1229
+ // NOTE: there used to be an extra early break here when a batch resolved
1230
+ // nothing (`result.unresolved.length === batch.length`). That was wrong:
1231
+ // an all-unresolvable batch still DELETES its rows (progress), yet the
1232
+ // break abandoned every batch after it in the same run — on a repo whose
1233
+ // first 5000 refs are all external/stdlib calls, resolution stopped at
1234
+ // batch one and left the rest of the table as permanent orphans (#1187).
1235
+ // The count-based guard below catches the true no-progress case.
1236
+ // Non-progress guard (defense-in-depth). Because we re-read from offset 0
1237
+ // each pass, the PENDING population MUST shrink every iteration — resolved
1238
+ // refs are deleted and unresolvable ones are marked failed above, and both
1239
+ // leave the pending set the batch reader sees. If it didn't shrink, a
1240
+ // resolver returned a match whose `original.referenceName` differs from the
1241
+ // stored row, so the keyed delete/update no-ops, and we'd re-read +
1242
+ // re-resolve + re-insert the same rows forever (the runaway that grew a
1243
+ // 99-file repo to 5M edges / 1.4 GB before the Go-fallback fix). Stop
1244
+ // rather than grow the graph without bound.
1245
+ const remaining = this.queries.getUnresolvedReferencesCount();
1246
+ if (remaining >= prevRemaining)
634
1247
  break;
635
- }
1248
+ prevRemaining = remaining;
1249
+ }
1250
+ // Dynamic-edge synthesis: now that all base `calls` edges are persisted,
1251
+ // synthesize observer/callback dispatch edges (dispatcher → registered
1252
+ // callbacks) that static parsing leaves out. Best-effort — never fail the
1253
+ // index on it. See docs/design/callback-edge-synthesis.md.
1254
+ try {
1255
+ aggregateStats.byMethod['callback-synthesis'] = await (0, callback_synthesizer_1.synthesizeCallbackEdges)(this.queries, this.context);
1256
+ }
1257
+ catch {
1258
+ // synthesis is additive and optional; ignore failures
636
1259
  }
637
1260
  return {
638
1261
  resolved: [],
@@ -652,11 +1275,18 @@ class ReferenceResolver {
652
1275
  isBuiltInOrExternal(ref) {
653
1276
  const name = ref.referenceName;
654
1277
  const isJsTs = ref.language === 'typescript' || ref.language === 'javascript'
655
- || ref.language === 'tsx' || ref.language === 'jsx';
1278
+ || ref.language === 'tsx' || ref.language === 'jsx' || ref.language === 'arkts';
656
1279
  // JavaScript/TypeScript built-ins
657
1280
  if (isJsTs && JS_BUILT_INS.has(name)) {
658
1281
  return true;
659
1282
  }
1283
+ // ArkTS resource-reference intrinsics — `$r('app.string.x')` /
1284
+ // `$rawfile('x.png')` are framework-provided and appear dozens of times
1285
+ // per UI file; without this they can resolve to a stray same-named
1286
+ // symbol (e.g. a checked-in hvigor wrapper's `$r`).
1287
+ if (ref.language === 'arkts' && (name === '$r' || name === '$rawfile')) {
1288
+ return true;
1289
+ }
660
1290
  // Common JS/TS library calls (console.log, Math.floor, JSON.parse)
661
1291
  if (isJsTs && (name.startsWith('console.') || name.startsWith('Math.') || name.startsWith('JSON.'))) {
662
1292
  return true;
@@ -689,7 +1319,13 @@ class ReferenceResolver {
689
1319
  }
690
1320
  }
691
1321
  }
692
- if (PYTHON_BUILT_IN_METHODS.has(name)) {
1322
+ // A bare name colliding with a builtin method (index, get, update, count…)
1323
+ // is only a builtin when NOTHING in the codebase declares it. A declared
1324
+ // symbol with that exact name — e.g. a Flask/FastAPI view `def index()` or
1325
+ // `def get()` — is a real reference target. Mirrors the knownNames guard on
1326
+ // the dotted branch above; without it, every handler named after a builtin
1327
+ // method silently loses its route→handler edge.
1328
+ if (PYTHON_BUILT_IN_METHODS.has(name) && !this.knownNames?.has(name)) {
693
1329
  return true;
694
1330
  }
695
1331
  }
@@ -715,6 +1351,24 @@ class ReferenceResolver {
715
1351
  return true;
716
1352
  }
717
1353
  }
1354
+ // C/C++ standard library symbols (printf, malloc, std::vector, etc.).
1355
+ // Names that collide with user-defined symbols are NOT filtered —
1356
+ // C and C++ projects routinely shadow stdlib names (custom allocators
1357
+ // define `malloc`/`free`, stream wrappers define `read`/`write`/`open`,
1358
+ // containers define `move`/`swap`, logging libs wrap `printf`). Killing
1359
+ // those resolutions makes the graph wrong, not cleaner. We only filter
1360
+ // when there's no user node with this name — then name-matching would
1361
+ // produce zero edges anyway and the filter just short-circuits work.
1362
+ if (ref.language === 'c' || ref.language === 'cpp') {
1363
+ // C++ std:: namespace prefix — safe to filter unconditionally,
1364
+ // since `std::foo` is never a user-defined qualified name in
1365
+ // tree-sitter output.
1366
+ if (name.startsWith('std::'))
1367
+ return true;
1368
+ if (C_BUILT_INS.has(name) || CPP_BUILT_INS.has(name)) {
1369
+ return !this.hasAnyPossibleMatch(name);
1370
+ }
1371
+ }
718
1372
  return false;
719
1373
  }
720
1374
  /**
@@ -731,6 +1385,354 @@ class ReferenceResolver {
731
1385
  const node = this.queries.getNodeById(nodeId);
732
1386
  return node?.language || 'unknown';
733
1387
  }
1388
+ /**
1389
+ * Drop an import/name-strategy resolution that crosses a language family.
1390
+ * Two regimes (mirrors `applyLanguageGate`'s candidate filter):
1391
+ * - `references` (type usage): STRICT — a `Type.member` static read names a
1392
+ * same-family type, never a coincidentally same-named symbol in another
1393
+ * language. Drops any non-same-family target.
1394
+ * - `imports` (import binding / `#include`): both-known — a C++ `#include
1395
+ * "X.h"` must not resolve to a same-named ObjC header on another platform
1396
+ * (basename collision), but a singleton-family / SFC language (`vue` →
1397
+ * `.ts`) importing across is left alone.
1398
+ * Applies to the import (strategy 2) + name-match (strategy 3) results.
1399
+ */
1400
+ /**
1401
+ * Collect the `@using` namespaces in scope for a `.razor`/`.cshtml` file: its
1402
+ * own `@using` directives plus every `_Imports.razor` from the file's folder up
1403
+ * to the project root (Razor `_Imports` cascade). Cached per file.
1404
+ */
1405
+ getRazorUsings(filePath) {
1406
+ const cached = this.razorUsingsCache.get(filePath);
1407
+ if (cached)
1408
+ return cached;
1409
+ const usings = new Set();
1410
+ const addFrom = (src) => {
1411
+ if (!src)
1412
+ return;
1413
+ for (const m of src.matchAll(/^\s*@using\s+(?:static\s+)?([A-Za-z_][\w.]*)/gm))
1414
+ usings.add(m[1]);
1415
+ };
1416
+ addFrom(this.context.readFile(filePath));
1417
+ let dir = filePath.includes('/') ? filePath.slice(0, filePath.lastIndexOf('/')) : '';
1418
+ // Walk up to the project root, reading each level's _Imports.razor.
1419
+ for (;;) {
1420
+ addFrom(this.context.readFile(dir ? `${dir}/_Imports.razor` : '_Imports.razor'));
1421
+ if (!dir)
1422
+ break;
1423
+ const slash = dir.lastIndexOf('/');
1424
+ dir = slash >= 0 ? dir.slice(0, slash) : '';
1425
+ }
1426
+ const arr = [...usings];
1427
+ this.razorUsingsCache.set(filePath, arr);
1428
+ return arr;
1429
+ }
1430
+ /**
1431
+ * Resolve a Razor/Blazor simple type ref through the file's `@using`
1432
+ * namespaces: `CatalogBrand` + `@using BlazorShared.Models` → the node whose
1433
+ * qualified name is `BlazorShared.Models::CatalogBrand`. Only resolves when the
1434
+ * `@using` set yields exactly ONE type (otherwise it stays ambiguous and falls
1435
+ * through to name-matching).
1436
+ */
1437
+ resolveRazorUsing(ref) {
1438
+ if (ref.referenceName.includes('.') || ref.referenceName.includes('::'))
1439
+ return null;
1440
+ const usings = this.getRazorUsings(ref.filePath);
1441
+ if (usings.length === 0)
1442
+ return null;
1443
+ const found = new Map();
1444
+ for (const ns of usings) {
1445
+ for (const cand of this.context.getNodesByQualifiedName(`${ns}::${ref.referenceName}`)) {
1446
+ found.set(cand.id, cand);
1447
+ }
1448
+ }
1449
+ if (found.size !== 1)
1450
+ return null;
1451
+ const target = found.values().next().value;
1452
+ return { original: ref, targetNodeId: target.id, confidence: 0.9, resolvedBy: 'import' };
1453
+ }
1454
+ /**
1455
+ * Resolve a CFML inheritance reference written as a component path (#1152).
1456
+ * Two forms exist in real code:
1457
+ *
1458
+ * - Dotted: `extends="coldbox.system.web.Controller"` — dots are directory
1459
+ * separators from the webroot or a CFML mapping. Mappings live in server
1460
+ * config / Application.cfc, so the leading segments may not exist in the
1461
+ * repo at all (in the coldbox repo itself the path is `system/web/
1462
+ * Controller.cfc` — the `coldbox.` root IS the repo). Matched by final
1463
+ * segment (the class), corroborated right-to-left against the candidate's
1464
+ * parent directories.
1465
+ * - Relative: `extends="../base"` / `extends="./base"` (the FW/1 style) —
1466
+ * resolved against the referencing file's own directory.
1467
+ *
1468
+ * Conservative by design: a candidate needs at least one corroborating
1469
+ * directory segment (a dotted path whose only same-named class sits in an
1470
+ * unrelated directory is almost always an out-of-repo library supertype —
1471
+ * mxunit/testbox/coldbox-as-dependency), and a corroboration tie yields no
1472
+ * edge. Directory comparison is case-insensitive (CFML path resolution is);
1473
+ * the class segment itself is matched exactly, which real code satisfies —
1474
+ * dotted paths are written to match the on-disk file name.
1475
+ */
1476
+ resolveCfmlComponentPath(ref) {
1477
+ const cfmlCandidates = (name) => this.context
1478
+ .getNodesByName(name)
1479
+ .filter((n) => (n.kind === 'class' || n.kind === 'interface') &&
1480
+ (n.language === 'cfml' || n.language === 'cfscript'));
1481
+ const norm = (p) => p.replace(/\\/g, '/').toLowerCase();
1482
+ // Relative-path form: `../base`, `./base`, `sub/thing` — resolve against
1483
+ // the referencing file's directory and require an exact (case-insensitive)
1484
+ // file match.
1485
+ if (ref.referenceName.includes('/')) {
1486
+ const rel = ref.referenceName.replace(/\.cfc$/i, '');
1487
+ const fromDir = ref.filePath.replace(/\\/g, '/').split('/').slice(0, -1);
1488
+ const parts = [...fromDir];
1489
+ for (const seg of rel.split('/')) {
1490
+ if (seg === '' || seg === '.')
1491
+ continue;
1492
+ if (seg === '..') {
1493
+ if (parts.length === 0)
1494
+ return null; // escapes the project root
1495
+ parts.pop();
1496
+ }
1497
+ else {
1498
+ parts.push(seg);
1499
+ }
1500
+ }
1501
+ const wantPath = norm(parts.join('/') + '.cfc');
1502
+ const className = parts[parts.length - 1];
1503
+ if (!className)
1504
+ return null;
1505
+ const target = cfmlCandidates(className).find((c) => norm(c.filePath) === wantPath);
1506
+ return target
1507
+ ? { original: ref, targetNodeId: target.id, confidence: 0.95, resolvedBy: 'file-path' }
1508
+ : null;
1509
+ }
1510
+ // Dotted form.
1511
+ const segments = ref.referenceName.split('.').map((s) => s.trim()).filter(Boolean);
1512
+ if (segments.length < 2)
1513
+ return null;
1514
+ const className = segments[segments.length - 1];
1515
+ const dirSegments = segments.slice(0, -1);
1516
+ let best = null;
1517
+ let bestScore = 0;
1518
+ let tie = false;
1519
+ for (const cand of cfmlCandidates(className)) {
1520
+ const dirs = cand.filePath.replace(/\\/g, '/').split('/').slice(0, -1);
1521
+ // Count matching directory segments right-to-left: for
1522
+ // `coldbox.system.web.Controller` vs `system/web/Controller.cfc`,
1523
+ // `web` and `system` match, then the repo root ends the run → score 2.
1524
+ let score = 0;
1525
+ while (score < dirSegments.length &&
1526
+ score < dirs.length &&
1527
+ dirSegments[dirSegments.length - 1 - score].toLowerCase() ===
1528
+ dirs[dirs.length - 1 - score].toLowerCase()) {
1529
+ score++;
1530
+ }
1531
+ if (score > bestScore) {
1532
+ best = cand;
1533
+ bestScore = score;
1534
+ tie = false;
1535
+ }
1536
+ else if (score === bestScore && score > 0) {
1537
+ tie = true;
1538
+ }
1539
+ }
1540
+ if (!best || bestScore === 0 || tie)
1541
+ return null;
1542
+ return { original: ref, targetNodeId: best.id, confidence: 0.9, resolvedBy: 'qualified-name' };
1543
+ }
1544
+ /**
1545
+ * Resolve a `this.<member>` function-as-value reference (#756/#808) to the
1546
+ * ENCLOSING CLASS's own member — never a same-named symbol elsewhere. The
1547
+ * registration idiom (`btn.on('click', this.handleClick)`) names a member
1548
+ * of the class being defined, so the only valid target shares the
1549
+ * from-symbol's qualified-name scope. Function/method targets only — a
1550
+ * property (a data field, post-#808 classification) yields no edge — same
1551
+ * file required, no fallback of any kind.
1552
+ */
1553
+ resolveThisMemberFnRef(ref) {
1554
+ const member = ref.referenceName.slice('this.'.length);
1555
+ if (!member)
1556
+ return null;
1557
+ const fromNode = this.queries.getNodeById(ref.fromNodeId);
1558
+ if (!fromNode)
1559
+ return null;
1560
+ // A hook declared at class-body level (Ruby `before_action :authenticate`)
1561
+ // attributes to the CLASS node itself — its qualified name IS the scope.
1562
+ // For members, strip the member segment.
1563
+ let classPrefix;
1564
+ if (SUPERTYPE_BEARING_KINDS.has(fromNode.kind) || fromNode.kind === 'module') {
1565
+ classPrefix = fromNode.qualifiedName;
1566
+ }
1567
+ else {
1568
+ const sep = fromNode.qualifiedName.lastIndexOf('::');
1569
+ if (sep <= 0)
1570
+ return null; // not inside a class scope
1571
+ classPrefix = fromNode.qualifiedName.slice(0, sep);
1572
+ }
1573
+ const candidates = this.context
1574
+ .getNodesByQualifiedName(`${classPrefix}::${member}`)
1575
+ .filter((n) => (n.kind === 'function' || n.kind === 'method') &&
1576
+ n.filePath === ref.filePath &&
1577
+ n.id !== ref.fromNodeId);
1578
+ if (candidates.length === 0) {
1579
+ // Not on the class itself — possibly INHERITED. implements/extends
1580
+ // edges don't exist yet in this pass, so retry in the supertype pass
1581
+ // (resolveDeferredThisMemberRefs) instead of giving up.
1582
+ this.deferredThisMemberRefs.push(ref);
1583
+ return null;
1584
+ }
1585
+ const target = candidates.reduce((a, b) => (a.startLine <= b.startLine ? a : b));
1586
+ return {
1587
+ original: ref,
1588
+ targetNodeId: target.id,
1589
+ confidence: 0.95,
1590
+ resolvedBy: 'function-ref',
1591
+ };
1592
+ }
1593
+ /**
1594
+ * Second pass for `this.<member>` refs whose member wasn't on the enclosing
1595
+ * class itself (#808): once implements/extends edges exist, walk the
1596
+ * class's supertypes (transitively, depth-capped) and resolve the member on
1597
+ * the nearest one that declares it — `this.handleSubmit` registered in a
1598
+ * subclass resolves to `FormBase::handleSubmit`. Validated targets only
1599
+ * (function/method kind, same language family); no match → no edge.
1600
+ * Mirrors resolveChainedCallsViaConformance's lifecycle. Returns the number
1601
+ * of newly-created edges.
1602
+ */
1603
+ async resolveDeferredThisMemberRefs() {
1604
+ const deferred = this.deferredThisMemberRefs;
1605
+ this.deferredThisMemberRefs = [];
1606
+ if (deferred.length === 0)
1607
+ return 0;
1608
+ this.clearCaches();
1609
+ // Synchronous main-thread post-pass with a per-ref supertype BFS — yield
1610
+ // periodically so the #850 liveness watchdog heartbeat can fire (#1091).
1611
+ const maybeYield = (0, cooperative_yield_1.createYielder)();
1612
+ const resolved = [];
1613
+ for (const ref of deferred) {
1614
+ await maybeYield();
1615
+ const member = ref.referenceName.slice('this.'.length);
1616
+ const fromNode = this.queries.getNodeById(ref.fromNodeId);
1617
+ if (!fromNode || !member)
1618
+ continue;
1619
+ // Class-body-level hooks (Ruby) attribute to the CLASS node itself.
1620
+ let className;
1621
+ if (SUPERTYPE_BEARING_KINDS.has(fromNode.kind) || fromNode.kind === 'module') {
1622
+ className = fromNode.name;
1623
+ }
1624
+ else {
1625
+ const sep = fromNode.qualifiedName.lastIndexOf('::');
1626
+ if (sep <= 0)
1627
+ continue;
1628
+ const classPrefix = fromNode.qualifiedName.slice(0, sep);
1629
+ className = classPrefix.includes('::')
1630
+ ? classPrefix.slice(classPrefix.lastIndexOf('::') + 2)
1631
+ : classPrefix;
1632
+ }
1633
+ // NODE-anchored BFS up the supertype graph: start from the class node
1634
+ // in the ref's own file (never a same-named class elsewhere — rails has
1635
+ // a dozen `Engine`s), follow implements/extends EDGES to supertype
1636
+ // NODES, and look members up through `contains` edges. No name-based
1637
+ // unions anywhere — a name-keyed getSupertypes('Engine') merged every
1638
+ // Engine's parents and produced a cross-class wrong edge on rails.
1639
+ let frontierNodes = this.context
1640
+ .getNodesByName(className)
1641
+ .filter((n) => SUPERTYPE_BEARING_KINDS.has(n.kind) &&
1642
+ n.filePath === ref.filePath);
1643
+ if (frontierNodes.length === 0) {
1644
+ // The class itself may be declared in another file (partial/reopened
1645
+ // classes); fall back to same-family nodes of that name.
1646
+ frontierNodes = this.context
1647
+ .getNodesByName(className)
1648
+ .filter((n) => SUPERTYPE_BEARING_KINDS.has(n.kind) &&
1649
+ (0, name_matcher_1.sameLanguageFamily)(n.language, ref.language));
1650
+ }
1651
+ const seenNodes = new Set(frontierNodes.map((n) => n.id));
1652
+ let target = null;
1653
+ for (let depth = 0; depth < 5 && frontierNodes.length > 0 && !target; depth++) {
1654
+ const next = [];
1655
+ for (const typeNode of frontierNodes) {
1656
+ for (const edge of this.queries.getOutgoingEdges(typeNode.id, ['implements', 'extends'])) {
1657
+ const superNode = this.queries.getNodeById(edge.target);
1658
+ if (!superNode || seenNodes.has(superNode.id))
1659
+ continue;
1660
+ seenNodes.add(superNode.id);
1661
+ if (!SUPERTYPE_BEARING_KINDS.has(superNode.kind))
1662
+ continue;
1663
+ // Member lookup anchored on the supertype's contains edges.
1664
+ for (const c of this.queries.getOutgoingEdges(superNode.id, ['contains'])) {
1665
+ const m = this.queries.getNodeById(c.target);
1666
+ if (m &&
1667
+ m.name === member &&
1668
+ (m.kind === 'function' || m.kind === 'method') &&
1669
+ (0, name_matcher_1.sameLanguageFamily)(m.language, ref.language)) {
1670
+ target = m;
1671
+ break;
1672
+ }
1673
+ }
1674
+ if (target)
1675
+ break;
1676
+ next.push(superNode);
1677
+ }
1678
+ if (target)
1679
+ break;
1680
+ }
1681
+ frontierNodes = next;
1682
+ }
1683
+ if (target) {
1684
+ resolved.push({
1685
+ original: ref,
1686
+ targetNodeId: target.id,
1687
+ confidence: 0.85,
1688
+ resolvedBy: 'function-ref',
1689
+ });
1690
+ }
1691
+ }
1692
+ if (resolved.length === 0)
1693
+ return 0;
1694
+ const edges = this.createEdges(resolved);
1695
+ if (edges.length > 0) {
1696
+ this.queries.insertEdges(edges);
1697
+ this.clearCaches();
1698
+ }
1699
+ return edges.length;
1700
+ }
1701
+ gateLanguage(result, ref) {
1702
+ if (!result)
1703
+ return result;
1704
+ const tgt = this.getLanguageFromNodeId(result.targetNodeId);
1705
+ if (!tgt || !ref.language)
1706
+ return result;
1707
+ if ((ref.referenceKind === 'references' || ref.referenceKind === 'function_ref') && !(0, name_matcher_1.sameLanguageFamily)(tgt, ref.language))
1708
+ return null;
1709
+ if (ref.referenceKind === 'imports' && (0, name_matcher_1.crossesKnownFamily)(tgt, ref.language))
1710
+ return null;
1711
+ return result;
1712
+ }
1713
+ /**
1714
+ * Drop a FRAMEWORK-strategy resolution that crosses two *known* language
1715
+ * families for a type-usage (`references`) or import-binding (`imports`)
1716
+ * edge. The framework strategy is intentionally ungated for cross-language
1717
+ * bridges, but those legitimate bridges are either `calls` edges (RN/Expo
1718
+ * JS → native) or config↔code edges whose config side (`yaml`/`blade`/…) is
1719
+ * not a known programming-language family. A `references`/`imports` edge
1720
+ * between two *known* families is always a coincidental name collision — the
1721
+ * React/Svelte/Vue PascalCase component resolvers name-match `getNodesByName`
1722
+ * without a language check, so a TS `<TestRunner>` ref happily matched a
1723
+ * Kotlin `class TestRunner`. Gating only the both-known-cross-family case
1724
+ * lets config bridges and `calls` bridges through untouched.
1725
+ */
1726
+ gateFrameworkLanguage(result, ref) {
1727
+ if (!result)
1728
+ return result;
1729
+ if (ref.referenceKind !== 'references' && ref.referenceKind !== 'imports')
1730
+ return result;
1731
+ const tgt = this.getLanguageFromNodeId(result.targetNodeId);
1732
+ if (tgt && ref.language && (0, name_matcher_1.crossesKnownFamily)(tgt, ref.language))
1733
+ return null;
1734
+ return result;
1735
+ }
734
1736
  }
735
1737
  exports.ReferenceResolver = ReferenceResolver;
736
1738
  /**