@bharanidev/bhgraph-darwin-x64 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (842) hide show
  1. package/bin/bhgraph +19 -0
  2. package/lib/dist/bin/bhgraph.d.ts +26 -0
  3. package/lib/dist/bin/bhgraph.d.ts.map +1 -0
  4. package/lib/dist/bin/bhgraph.js +2207 -0
  5. package/lib/dist/bin/bhgraph.js.map +1 -0
  6. package/lib/dist/bin/command-supervision.d.ts +12 -0
  7. package/lib/dist/bin/command-supervision.d.ts.map +1 -0
  8. package/lib/dist/bin/command-supervision.js +89 -0
  9. package/lib/dist/bin/command-supervision.js.map +1 -0
  10. package/lib/dist/bin/fatal-handler.d.ts +20 -0
  11. package/lib/dist/bin/fatal-handler.d.ts.map +1 -0
  12. package/lib/dist/bin/fatal-handler.js +118 -0
  13. package/lib/dist/bin/fatal-handler.js.map +1 -0
  14. package/lib/dist/bin/node-version-check.d.ts +37 -0
  15. package/lib/dist/bin/node-version-check.d.ts.map +1 -0
  16. package/lib/dist/bin/node-version-check.js +79 -0
  17. package/lib/dist/bin/node-version-check.js.map +1 -0
  18. package/lib/dist/bin/uninstall.d.ts +14 -0
  19. package/lib/dist/bin/uninstall.d.ts.map +1 -0
  20. package/lib/dist/bin/uninstall.js +36 -0
  21. package/lib/dist/bin/uninstall.js.map +1 -0
  22. package/lib/dist/context/formatter.d.ts +30 -0
  23. package/lib/dist/context/formatter.d.ts.map +1 -0
  24. package/lib/dist/context/formatter.js +263 -0
  25. package/lib/dist/context/formatter.js.map +1 -0
  26. package/lib/dist/context/index.d.ts +119 -0
  27. package/lib/dist/context/index.d.ts.map +1 -0
  28. package/lib/dist/context/index.js +1296 -0
  29. package/lib/dist/context/index.js.map +1 -0
  30. package/lib/dist/context/markers.d.ts +19 -0
  31. package/lib/dist/context/markers.d.ts.map +1 -0
  32. package/lib/dist/context/markers.js +22 -0
  33. package/lib/dist/context/markers.js.map +1 -0
  34. package/lib/dist/db/index.d.ts +142 -0
  35. package/lib/dist/db/index.d.ts.map +1 -0
  36. package/lib/dist/db/index.js +335 -0
  37. package/lib/dist/db/index.js.map +1 -0
  38. package/lib/dist/db/migrations.d.ts +44 -0
  39. package/lib/dist/db/migrations.d.ts.map +1 -0
  40. package/lib/dist/db/migrations.js +182 -0
  41. package/lib/dist/db/migrations.js.map +1 -0
  42. package/lib/dist/db/queries.d.ts +452 -0
  43. package/lib/dist/db/queries.d.ts.map +1 -0
  44. package/lib/dist/db/queries.js +1740 -0
  45. package/lib/dist/db/queries.js.map +1 -0
  46. package/lib/dist/db/schema.sql +182 -0
  47. package/lib/dist/db/sqlite-adapter.d.ts +53 -0
  48. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -0
  49. package/lib/dist/db/sqlite-adapter.js +117 -0
  50. package/lib/dist/db/sqlite-adapter.js.map +1 -0
  51. package/lib/dist/directory.d.ts +183 -0
  52. package/lib/dist/directory.d.ts.map +1 -0
  53. package/lib/dist/directory.js +797 -0
  54. package/lib/dist/directory.js.map +1 -0
  55. package/lib/dist/errors.d.ts +136 -0
  56. package/lib/dist/errors.d.ts.map +1 -0
  57. package/lib/dist/errors.js +219 -0
  58. package/lib/dist/errors.js.map +1 -0
  59. package/lib/dist/extraction/astro-extractor.d.ts +79 -0
  60. package/lib/dist/extraction/astro-extractor.d.ts.map +1 -0
  61. package/lib/dist/extraction/astro-extractor.js +320 -0
  62. package/lib/dist/extraction/astro-extractor.js.map +1 -0
  63. package/lib/dist/extraction/cfml-extractor.d.ts +107 -0
  64. package/lib/dist/extraction/cfml-extractor.d.ts.map +1 -0
  65. package/lib/dist/extraction/cfml-extractor.js +494 -0
  66. package/lib/dist/extraction/cfml-extractor.js.map +1 -0
  67. package/lib/dist/extraction/dfm-extractor.d.ts +31 -0
  68. package/lib/dist/extraction/dfm-extractor.d.ts.map +1 -0
  69. package/lib/dist/extraction/dfm-extractor.js +151 -0
  70. package/lib/dist/extraction/dfm-extractor.js.map +1 -0
  71. package/lib/dist/extraction/extraction-version.d.ts +25 -0
  72. package/lib/dist/extraction/extraction-version.d.ts.map +1 -0
  73. package/lib/dist/extraction/extraction-version.js +28 -0
  74. package/lib/dist/extraction/extraction-version.js.map +1 -0
  75. package/lib/dist/extraction/function-ref.d.ts +118 -0
  76. package/lib/dist/extraction/function-ref.d.ts.map +1 -0
  77. package/lib/dist/extraction/function-ref.js +727 -0
  78. package/lib/dist/extraction/function-ref.js.map +1 -0
  79. package/lib/dist/extraction/generated-detection.d.ts +30 -0
  80. package/lib/dist/extraction/generated-detection.d.ts.map +1 -0
  81. package/lib/dist/extraction/generated-detection.js +83 -0
  82. package/lib/dist/extraction/generated-detection.js.map +1 -0
  83. package/lib/dist/extraction/grammars.d.ts +123 -0
  84. package/lib/dist/extraction/grammars.d.ts.map +1 -0
  85. package/lib/dist/extraction/grammars.js +589 -0
  86. package/lib/dist/extraction/grammars.js.map +1 -0
  87. package/lib/dist/extraction/index.d.ts +232 -0
  88. package/lib/dist/extraction/index.d.ts.map +1 -0
  89. package/lib/dist/extraction/index.js +2269 -0
  90. package/lib/dist/extraction/index.js.map +1 -0
  91. package/lib/dist/extraction/languages/arkts.d.ts +3 -0
  92. package/lib/dist/extraction/languages/arkts.d.ts.map +1 -0
  93. package/lib/dist/extraction/languages/arkts.js +127 -0
  94. package/lib/dist/extraction/languages/arkts.js.map +1 -0
  95. package/lib/dist/extraction/languages/c-cpp.d.ts +110 -0
  96. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -0
  97. package/lib/dist/extraction/languages/c-cpp.js +837 -0
  98. package/lib/dist/extraction/languages/c-cpp.js.map +1 -0
  99. package/lib/dist/extraction/languages/cfquery.d.ts +12 -0
  100. package/lib/dist/extraction/languages/cfquery.d.ts.map +1 -0
  101. package/lib/dist/extraction/languages/cfquery.js +28 -0
  102. package/lib/dist/extraction/languages/cfquery.js.map +1 -0
  103. package/lib/dist/extraction/languages/cfscript.d.ts +3 -0
  104. package/lib/dist/extraction/languages/cfscript.d.ts.map +1 -0
  105. package/lib/dist/extraction/languages/cfscript.js +73 -0
  106. package/lib/dist/extraction/languages/cfscript.js.map +1 -0
  107. package/lib/dist/extraction/languages/cobol.d.ts +33 -0
  108. package/lib/dist/extraction/languages/cobol.d.ts.map +1 -0
  109. package/lib/dist/extraction/languages/cobol.js +499 -0
  110. package/lib/dist/extraction/languages/cobol.js.map +1 -0
  111. package/lib/dist/extraction/languages/csharp.d.ts +25 -0
  112. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -0
  113. package/lib/dist/extraction/languages/csharp.js +175 -0
  114. package/lib/dist/extraction/languages/csharp.js.map +1 -0
  115. package/lib/dist/extraction/languages/dart.d.ts +3 -0
  116. package/lib/dist/extraction/languages/dart.d.ts.map +1 -0
  117. package/lib/dist/extraction/languages/dart.js +374 -0
  118. package/lib/dist/extraction/languages/dart.js.map +1 -0
  119. package/lib/dist/extraction/languages/erlang.d.ts +3 -0
  120. package/lib/dist/extraction/languages/erlang.d.ts.map +1 -0
  121. package/lib/dist/extraction/languages/erlang.js +350 -0
  122. package/lib/dist/extraction/languages/erlang.js.map +1 -0
  123. package/lib/dist/extraction/languages/go.d.ts +3 -0
  124. package/lib/dist/extraction/languages/go.d.ts.map +1 -0
  125. package/lib/dist/extraction/languages/go.js +111 -0
  126. package/lib/dist/extraction/languages/go.js.map +1 -0
  127. package/lib/dist/extraction/languages/index.d.ts +10 -0
  128. package/lib/dist/extraction/languages/index.d.ts.map +1 -0
  129. package/lib/dist/extraction/languages/index.js +71 -0
  130. package/lib/dist/extraction/languages/index.js.map +1 -0
  131. package/lib/dist/extraction/languages/java.d.ts +3 -0
  132. package/lib/dist/extraction/languages/java.d.ts.map +1 -0
  133. package/lib/dist/extraction/languages/java.js +315 -0
  134. package/lib/dist/extraction/languages/java.js.map +1 -0
  135. package/lib/dist/extraction/languages/javascript.d.ts +3 -0
  136. package/lib/dist/extraction/languages/javascript.d.ts.map +1 -0
  137. package/lib/dist/extraction/languages/javascript.js +106 -0
  138. package/lib/dist/extraction/languages/javascript.js.map +1 -0
  139. package/lib/dist/extraction/languages/kotlin.d.ts +3 -0
  140. package/lib/dist/extraction/languages/kotlin.d.ts.map +1 -0
  141. package/lib/dist/extraction/languages/kotlin.js +379 -0
  142. package/lib/dist/extraction/languages/kotlin.js.map +1 -0
  143. package/lib/dist/extraction/languages/lua.d.ts +3 -0
  144. package/lib/dist/extraction/languages/lua.d.ts.map +1 -0
  145. package/lib/dist/extraction/languages/lua.js +150 -0
  146. package/lib/dist/extraction/languages/lua.js.map +1 -0
  147. package/lib/dist/extraction/languages/luau.d.ts +3 -0
  148. package/lib/dist/extraction/languages/luau.d.ts.map +1 -0
  149. package/lib/dist/extraction/languages/luau.js +37 -0
  150. package/lib/dist/extraction/languages/luau.js.map +1 -0
  151. package/lib/dist/extraction/languages/nix.d.ts +3 -0
  152. package/lib/dist/extraction/languages/nix.d.ts.map +1 -0
  153. package/lib/dist/extraction/languages/nix.js +294 -0
  154. package/lib/dist/extraction/languages/nix.js.map +1 -0
  155. package/lib/dist/extraction/languages/objc.d.ts +3 -0
  156. package/lib/dist/extraction/languages/objc.d.ts.map +1 -0
  157. package/lib/dist/extraction/languages/objc.js +175 -0
  158. package/lib/dist/extraction/languages/objc.js.map +1 -0
  159. package/lib/dist/extraction/languages/pascal.d.ts +3 -0
  160. package/lib/dist/extraction/languages/pascal.d.ts.map +1 -0
  161. package/lib/dist/extraction/languages/pascal.js +77 -0
  162. package/lib/dist/extraction/languages/pascal.js.map +1 -0
  163. package/lib/dist/extraction/languages/php.d.ts +3 -0
  164. package/lib/dist/extraction/languages/php.d.ts.map +1 -0
  165. package/lib/dist/extraction/languages/php.js +196 -0
  166. package/lib/dist/extraction/languages/php.js.map +1 -0
  167. package/lib/dist/extraction/languages/python.d.ts +3 -0
  168. package/lib/dist/extraction/languages/python.d.ts.map +1 -0
  169. package/lib/dist/extraction/languages/python.js +56 -0
  170. package/lib/dist/extraction/languages/python.js.map +1 -0
  171. package/lib/dist/extraction/languages/r.d.ts +3 -0
  172. package/lib/dist/extraction/languages/r.d.ts.map +1 -0
  173. package/lib/dist/extraction/languages/r.js +314 -0
  174. package/lib/dist/extraction/languages/r.js.map +1 -0
  175. package/lib/dist/extraction/languages/ruby.d.ts +3 -0
  176. package/lib/dist/extraction/languages/ruby.d.ts.map +1 -0
  177. package/lib/dist/extraction/languages/ruby.js +149 -0
  178. package/lib/dist/extraction/languages/ruby.js.map +1 -0
  179. package/lib/dist/extraction/languages/rust.d.ts +3 -0
  180. package/lib/dist/extraction/languages/rust.d.ts.map +1 -0
  181. package/lib/dist/extraction/languages/rust.js +142 -0
  182. package/lib/dist/extraction/languages/rust.js.map +1 -0
  183. package/lib/dist/extraction/languages/scala.d.ts +3 -0
  184. package/lib/dist/extraction/languages/scala.d.ts.map +1 -0
  185. package/lib/dist/extraction/languages/scala.js +209 -0
  186. package/lib/dist/extraction/languages/scala.js.map +1 -0
  187. package/lib/dist/extraction/languages/solidity.d.ts +3 -0
  188. package/lib/dist/extraction/languages/solidity.d.ts.map +1 -0
  189. package/lib/dist/extraction/languages/solidity.js +293 -0
  190. package/lib/dist/extraction/languages/solidity.js.map +1 -0
  191. package/lib/dist/extraction/languages/swift.d.ts +3 -0
  192. package/lib/dist/extraction/languages/swift.d.ts.map +1 -0
  193. package/lib/dist/extraction/languages/swift.js +152 -0
  194. package/lib/dist/extraction/languages/swift.js.map +1 -0
  195. package/lib/dist/extraction/languages/terraform.d.ts +3 -0
  196. package/lib/dist/extraction/languages/terraform.d.ts.map +1 -0
  197. package/lib/dist/extraction/languages/terraform.js +641 -0
  198. package/lib/dist/extraction/languages/terraform.js.map +1 -0
  199. package/lib/dist/extraction/languages/typescript.d.ts +16 -0
  200. package/lib/dist/extraction/languages/typescript.d.ts.map +1 -0
  201. package/lib/dist/extraction/languages/typescript.js +167 -0
  202. package/lib/dist/extraction/languages/typescript.js.map +1 -0
  203. package/lib/dist/extraction/languages/vbnet.d.ts +11 -0
  204. package/lib/dist/extraction/languages/vbnet.d.ts.map +1 -0
  205. package/lib/dist/extraction/languages/vbnet.js +141 -0
  206. package/lib/dist/extraction/languages/vbnet.js.map +1 -0
  207. package/lib/dist/extraction/liquid-extractor.d.ts +59 -0
  208. package/lib/dist/extraction/liquid-extractor.d.ts.map +1 -0
  209. package/lib/dist/extraction/liquid-extractor.js +357 -0
  210. package/lib/dist/extraction/liquid-extractor.js.map +1 -0
  211. package/lib/dist/extraction/mybatis-extractor.d.ts +68 -0
  212. package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  213. package/lib/dist/extraction/mybatis-extractor.js +300 -0
  214. package/lib/dist/extraction/mybatis-extractor.js.map +1 -0
  215. package/lib/dist/extraction/parse-pool.d.ts +126 -0
  216. package/lib/dist/extraction/parse-pool.d.ts.map +1 -0
  217. package/lib/dist/extraction/parse-pool.js +319 -0
  218. package/lib/dist/extraction/parse-pool.js.map +1 -0
  219. package/lib/dist/extraction/parse-worker.d.ts +8 -0
  220. package/lib/dist/extraction/parse-worker.d.ts.map +1 -0
  221. package/lib/dist/extraction/parse-worker.js +97 -0
  222. package/lib/dist/extraction/parse-worker.js.map +1 -0
  223. package/lib/dist/extraction/razor-extractor.d.ts +42 -0
  224. package/lib/dist/extraction/razor-extractor.d.ts.map +1 -0
  225. package/lib/dist/extraction/razor-extractor.js +285 -0
  226. package/lib/dist/extraction/razor-extractor.js.map +1 -0
  227. package/lib/dist/extraction/svelte-extractor.d.ts +56 -0
  228. package/lib/dist/extraction/svelte-extractor.d.ts.map +1 -0
  229. package/lib/dist/extraction/svelte-extractor.js +275 -0
  230. package/lib/dist/extraction/svelte-extractor.js.map +1 -0
  231. package/lib/dist/extraction/tree-sitter-helpers.d.ts +28 -0
  232. package/lib/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
  233. package/lib/dist/extraction/tree-sitter-helpers.js +153 -0
  234. package/lib/dist/extraction/tree-sitter-helpers.js.map +1 -0
  235. package/lib/dist/extraction/tree-sitter-types.d.ts +258 -0
  236. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -0
  237. package/lib/dist/extraction/tree-sitter-types.js +10 -0
  238. package/lib/dist/extraction/tree-sitter-types.js.map +1 -0
  239. package/lib/dist/extraction/tree-sitter.d.ts +706 -0
  240. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -0
  241. package/lib/dist/extraction/tree-sitter.js +6506 -0
  242. package/lib/dist/extraction/tree-sitter.js.map +1 -0
  243. package/lib/dist/extraction/vue-extractor.d.ts +51 -0
  244. package/lib/dist/extraction/vue-extractor.d.ts.map +1 -0
  245. package/lib/dist/extraction/vue-extractor.js +254 -0
  246. package/lib/dist/extraction/vue-extractor.js.map +1 -0
  247. package/lib/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  248. package/lib/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  249. package/lib/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  250. package/lib/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  251. package/lib/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  252. package/lib/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  253. package/lib/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  254. package/lib/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  255. package/lib/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  256. package/lib/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  257. package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  258. package/lib/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  259. package/lib/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  260. package/lib/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
  261. package/lib/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  262. package/lib/dist/extraction/wasm-runtime-flags.d.ts +38 -0
  263. package/lib/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  264. package/lib/dist/extraction/wasm-runtime-flags.js +106 -0
  265. package/lib/dist/extraction/wasm-runtime-flags.js.map +1 -0
  266. package/lib/dist/graph/index.d.ts +8 -0
  267. package/lib/dist/graph/index.d.ts.map +1 -0
  268. package/lib/dist/graph/index.js +13 -0
  269. package/lib/dist/graph/index.js.map +1 -0
  270. package/lib/dist/graph/queries.d.ts +106 -0
  271. package/lib/dist/graph/queries.d.ts.map +1 -0
  272. package/lib/dist/graph/queries.js +339 -0
  273. package/lib/dist/graph/queries.js.map +1 -0
  274. package/lib/dist/graph/traversal.d.ts +127 -0
  275. package/lib/dist/graph/traversal.d.ts.map +1 -0
  276. package/lib/dist/graph/traversal.js +599 -0
  277. package/lib/dist/graph/traversal.js.map +1 -0
  278. package/lib/dist/index.d.ts +642 -0
  279. package/lib/dist/index.d.ts.map +1 -0
  280. package/lib/dist/index.js +1387 -0
  281. package/lib/dist/index.js.map +1 -0
  282. package/lib/dist/installer/config-writer.d.ts +28 -0
  283. package/lib/dist/installer/config-writer.d.ts.map +1 -0
  284. package/lib/dist/installer/config-writer.js +91 -0
  285. package/lib/dist/installer/config-writer.js.map +1 -0
  286. package/lib/dist/installer/index.d.ts +100 -0
  287. package/lib/dist/installer/index.d.ts.map +1 -0
  288. package/lib/dist/installer/index.js +526 -0
  289. package/lib/dist/installer/index.js.map +1 -0
  290. package/lib/dist/installer/instructions-template.d.ts +41 -0
  291. package/lib/dist/installer/instructions-template.d.ts.map +1 -0
  292. package/lib/dist/installer/instructions-template.js +53 -0
  293. package/lib/dist/installer/instructions-template.js.map +1 -0
  294. package/lib/dist/installer/targets/antigravity.d.ts +57 -0
  295. package/lib/dist/installer/targets/antigravity.d.ts.map +1 -0
  296. package/lib/dist/installer/targets/antigravity.js +308 -0
  297. package/lib/dist/installer/targets/antigravity.js.map +1 -0
  298. package/lib/dist/installer/targets/claude.d.ts +62 -0
  299. package/lib/dist/installer/targets/claude.d.ts.map +1 -0
  300. package/lib/dist/installer/targets/claude.js +454 -0
  301. package/lib/dist/installer/targets/claude.js.map +1 -0
  302. package/lib/dist/installer/targets/codex.d.ts +18 -0
  303. package/lib/dist/installer/targets/codex.d.ts.map +1 -0
  304. package/lib/dist/installer/targets/codex.js +185 -0
  305. package/lib/dist/installer/targets/codex.js.map +1 -0
  306. package/lib/dist/installer/targets/cursor.d.ts +35 -0
  307. package/lib/dist/installer/targets/cursor.d.ts.map +1 -0
  308. package/lib/dist/installer/targets/cursor.js +254 -0
  309. package/lib/dist/installer/targets/cursor.js.map +1 -0
  310. package/lib/dist/installer/targets/gemini.d.ts +26 -0
  311. package/lib/dist/installer/targets/gemini.d.ts.map +1 -0
  312. package/lib/dist/installer/targets/gemini.js +165 -0
  313. package/lib/dist/installer/targets/gemini.js.map +1 -0
  314. package/lib/dist/installer/targets/hermes.d.ts +18 -0
  315. package/lib/dist/installer/targets/hermes.d.ts.map +1 -0
  316. package/lib/dist/installer/targets/hermes.js +359 -0
  317. package/lib/dist/installer/targets/hermes.js.map +1 -0
  318. package/lib/dist/installer/targets/kiro.d.ts +27 -0
  319. package/lib/dist/installer/targets/kiro.d.ts.map +1 -0
  320. package/lib/dist/installer/targets/kiro.js +178 -0
  321. package/lib/dist/installer/targets/kiro.js.map +1 -0
  322. package/lib/dist/installer/targets/opencode.d.ts +38 -0
  323. package/lib/dist/installer/targets/opencode.d.ts.map +1 -0
  324. package/lib/dist/installer/targets/opencode.js +288 -0
  325. package/lib/dist/installer/targets/opencode.js.map +1 -0
  326. package/lib/dist/installer/targets/registry.d.ts +35 -0
  327. package/lib/dist/installer/targets/registry.d.ts.map +1 -0
  328. package/lib/dist/installer/targets/registry.js +91 -0
  329. package/lib/dist/installer/targets/registry.js.map +1 -0
  330. package/lib/dist/installer/targets/shared.d.ts +101 -0
  331. package/lib/dist/installer/targets/shared.d.ts.map +1 -0
  332. package/lib/dist/installer/targets/shared.js +264 -0
  333. package/lib/dist/installer/targets/shared.js.map +1 -0
  334. package/lib/dist/installer/targets/toml.d.ts +52 -0
  335. package/lib/dist/installer/targets/toml.d.ts.map +1 -0
  336. package/lib/dist/installer/targets/toml.js +147 -0
  337. package/lib/dist/installer/targets/toml.js.map +1 -0
  338. package/lib/dist/installer/targets/types.d.ts +108 -0
  339. package/lib/dist/installer/targets/types.d.ts.map +1 -0
  340. package/lib/dist/installer/targets/types.js +16 -0
  341. package/lib/dist/installer/targets/types.js.map +1 -0
  342. package/lib/dist/mcp/daemon-manager.d.ts +42 -0
  343. package/lib/dist/mcp/daemon-manager.d.ts.map +1 -0
  344. package/lib/dist/mcp/daemon-manager.js +129 -0
  345. package/lib/dist/mcp/daemon-manager.js.map +1 -0
  346. package/lib/dist/mcp/daemon-paths.d.ts +73 -0
  347. package/lib/dist/mcp/daemon-paths.d.ts.map +1 -0
  348. package/lib/dist/mcp/daemon-paths.js +165 -0
  349. package/lib/dist/mcp/daemon-paths.js.map +1 -0
  350. package/lib/dist/mcp/daemon-registry.d.ts +47 -0
  351. package/lib/dist/mcp/daemon-registry.d.ts.map +1 -0
  352. package/lib/dist/mcp/daemon-registry.js +233 -0
  353. package/lib/dist/mcp/daemon-registry.js.map +1 -0
  354. package/lib/dist/mcp/daemon.d.ts +290 -0
  355. package/lib/dist/mcp/daemon.d.ts.map +1 -0
  356. package/lib/dist/mcp/daemon.js +840 -0
  357. package/lib/dist/mcp/daemon.js.map +1 -0
  358. package/lib/dist/mcp/dynamic-boundaries.d.ts +41 -0
  359. package/lib/dist/mcp/dynamic-boundaries.d.ts.map +1 -0
  360. package/lib/dist/mcp/dynamic-boundaries.js +360 -0
  361. package/lib/dist/mcp/dynamic-boundaries.js.map +1 -0
  362. package/lib/dist/mcp/early-ppid.d.ts +26 -0
  363. package/lib/dist/mcp/early-ppid.d.ts.map +1 -0
  364. package/lib/dist/mcp/early-ppid.js +29 -0
  365. package/lib/dist/mcp/early-ppid.js.map +1 -0
  366. package/lib/dist/mcp/engine.d.ts +122 -0
  367. package/lib/dist/mcp/engine.d.ts.map +1 -0
  368. package/lib/dist/mcp/engine.js +350 -0
  369. package/lib/dist/mcp/engine.js.map +1 -0
  370. package/lib/dist/mcp/index.d.ts +113 -0
  371. package/lib/dist/mcp/index.d.ts.map +1 -0
  372. package/lib/dist/mcp/index.js +498 -0
  373. package/lib/dist/mcp/index.js.map +1 -0
  374. package/lib/dist/mcp/liveness-watchdog.d.ts +18 -0
  375. package/lib/dist/mcp/liveness-watchdog.d.ts.map +1 -0
  376. package/lib/dist/mcp/liveness-watchdog.js +207 -0
  377. package/lib/dist/mcp/liveness-watchdog.js.map +1 -0
  378. package/lib/dist/mcp/ppid-watchdog.d.ts +62 -0
  379. package/lib/dist/mcp/ppid-watchdog.d.ts.map +1 -0
  380. package/lib/dist/mcp/ppid-watchdog.js +64 -0
  381. package/lib/dist/mcp/ppid-watchdog.js.map +1 -0
  382. package/lib/dist/mcp/proxy.d.ts +87 -0
  383. package/lib/dist/mcp/proxy.d.ts.map +1 -0
  384. package/lib/dist/mcp/proxy.js +659 -0
  385. package/lib/dist/mcp/proxy.js.map +1 -0
  386. package/lib/dist/mcp/query-pool.d.ts +94 -0
  387. package/lib/dist/mcp/query-pool.d.ts.map +1 -0
  388. package/lib/dist/mcp/query-pool.js +297 -0
  389. package/lib/dist/mcp/query-pool.js.map +1 -0
  390. package/lib/dist/mcp/query-worker.d.ts +24 -0
  391. package/lib/dist/mcp/query-worker.d.ts.map +1 -0
  392. package/lib/dist/mcp/query-worker.js +87 -0
  393. package/lib/dist/mcp/query-worker.js.map +1 -0
  394. package/lib/dist/mcp/server-instructions.d.ts +34 -0
  395. package/lib/dist/mcp/server-instructions.d.ts.map +1 -0
  396. package/lib/dist/mcp/server-instructions.js +106 -0
  397. package/lib/dist/mcp/server-instructions.js.map +1 -0
  398. package/lib/dist/mcp/session.d.ts +79 -0
  399. package/lib/dist/mcp/session.d.ts.map +1 -0
  400. package/lib/dist/mcp/session.js +330 -0
  401. package/lib/dist/mcp/session.js.map +1 -0
  402. package/lib/dist/mcp/startup-handshake.d.ts +44 -0
  403. package/lib/dist/mcp/startup-handshake.d.ts.map +1 -0
  404. package/lib/dist/mcp/startup-handshake.js +73 -0
  405. package/lib/dist/mcp/startup-handshake.js.map +1 -0
  406. package/lib/dist/mcp/stdin-teardown.d.ts +27 -0
  407. package/lib/dist/mcp/stdin-teardown.d.ts.map +1 -0
  408. package/lib/dist/mcp/stdin-teardown.js +49 -0
  409. package/lib/dist/mcp/stdin-teardown.js.map +1 -0
  410. package/lib/dist/mcp/tools.d.ts +613 -0
  411. package/lib/dist/mcp/tools.d.ts.map +1 -0
  412. package/lib/dist/mcp/tools.js +4424 -0
  413. package/lib/dist/mcp/tools.js.map +1 -0
  414. package/lib/dist/mcp/transport.d.ts +188 -0
  415. package/lib/dist/mcp/transport.d.ts.map +1 -0
  416. package/lib/dist/mcp/transport.js +359 -0
  417. package/lib/dist/mcp/transport.js.map +1 -0
  418. package/lib/dist/mcp/version.d.ts +19 -0
  419. package/lib/dist/mcp/version.d.ts.map +1 -0
  420. package/lib/dist/mcp/version.js +71 -0
  421. package/lib/dist/mcp/version.js.map +1 -0
  422. package/lib/dist/project-config.d.ts +94 -0
  423. package/lib/dist/project-config.d.ts.map +1 -0
  424. package/lib/dist/project-config.js +374 -0
  425. package/lib/dist/project-config.js.map +1 -0
  426. package/lib/dist/resolution/c-fnptr-synthesizer.d.ts +5 -0
  427. package/lib/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -0
  428. package/lib/dist/resolution/c-fnptr-synthesizer.js +1038 -0
  429. package/lib/dist/resolution/c-fnptr-synthesizer.js.map +1 -0
  430. package/lib/dist/resolution/callback-synthesizer.d.ts +15 -0
  431. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  432. package/lib/dist/resolution/callback-synthesizer.js +3658 -0
  433. package/lib/dist/resolution/callback-synthesizer.js.map +1 -0
  434. package/lib/dist/resolution/cooperative-yield.d.ts +32 -0
  435. package/lib/dist/resolution/cooperative-yield.d.ts.map +1 -0
  436. package/lib/dist/resolution/cooperative-yield.js +42 -0
  437. package/lib/dist/resolution/cooperative-yield.js.map +1 -0
  438. package/lib/dist/resolution/frameworks/astro.d.ts +9 -0
  439. package/lib/dist/resolution/frameworks/astro.d.ts.map +1 -0
  440. package/lib/dist/resolution/frameworks/astro.js +169 -0
  441. package/lib/dist/resolution/frameworks/astro.js.map +1 -0
  442. package/lib/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
  443. package/lib/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  444. package/lib/dist/resolution/frameworks/cargo-workspace.js +225 -0
  445. package/lib/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  446. package/lib/dist/resolution/frameworks/cics.d.ts +20 -0
  447. package/lib/dist/resolution/frameworks/cics.d.ts.map +1 -0
  448. package/lib/dist/resolution/frameworks/cics.js +90 -0
  449. package/lib/dist/resolution/frameworks/cics.js.map +1 -0
  450. package/lib/dist/resolution/frameworks/csharp.d.ts +8 -0
  451. package/lib/dist/resolution/frameworks/csharp.d.ts.map +1 -0
  452. package/lib/dist/resolution/frameworks/csharp.js +241 -0
  453. package/lib/dist/resolution/frameworks/csharp.js.map +1 -0
  454. package/lib/dist/resolution/frameworks/drupal.d.ts +51 -0
  455. package/lib/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  456. package/lib/dist/resolution/frameworks/drupal.js +367 -0
  457. package/lib/dist/resolution/frameworks/drupal.js.map +1 -0
  458. package/lib/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  459. package/lib/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  460. package/lib/dist/resolution/frameworks/expo-modules.js +148 -0
  461. package/lib/dist/resolution/frameworks/expo-modules.js.map +1 -0
  462. package/lib/dist/resolution/frameworks/express.d.ts +8 -0
  463. package/lib/dist/resolution/frameworks/express.d.ts.map +1 -0
  464. package/lib/dist/resolution/frameworks/express.js +308 -0
  465. package/lib/dist/resolution/frameworks/express.js.map +1 -0
  466. package/lib/dist/resolution/frameworks/fabric.d.ts +3 -0
  467. package/lib/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  468. package/lib/dist/resolution/frameworks/fabric.js +354 -0
  469. package/lib/dist/resolution/frameworks/fabric.js.map +1 -0
  470. package/lib/dist/resolution/frameworks/go.d.ts +8 -0
  471. package/lib/dist/resolution/frameworks/go.d.ts.map +1 -0
  472. package/lib/dist/resolution/frameworks/go.js +161 -0
  473. package/lib/dist/resolution/frameworks/go.js.map +1 -0
  474. package/lib/dist/resolution/frameworks/goframe.d.ts +41 -0
  475. package/lib/dist/resolution/frameworks/goframe.d.ts.map +1 -0
  476. package/lib/dist/resolution/frameworks/goframe.js +112 -0
  477. package/lib/dist/resolution/frameworks/goframe.js.map +1 -0
  478. package/lib/dist/resolution/frameworks/index.d.ts +50 -0
  479. package/lib/dist/resolution/frameworks/index.d.ts.map +1 -0
  480. package/lib/dist/resolution/frameworks/index.js +175 -0
  481. package/lib/dist/resolution/frameworks/index.js.map +1 -0
  482. package/lib/dist/resolution/frameworks/java.d.ts +8 -0
  483. package/lib/dist/resolution/frameworks/java.d.ts.map +1 -0
  484. package/lib/dist/resolution/frameworks/java.js +517 -0
  485. package/lib/dist/resolution/frameworks/java.js.map +1 -0
  486. package/lib/dist/resolution/frameworks/laravel.d.ts +13 -0
  487. package/lib/dist/resolution/frameworks/laravel.d.ts.map +1 -0
  488. package/lib/dist/resolution/frameworks/laravel.js +257 -0
  489. package/lib/dist/resolution/frameworks/laravel.js.map +1 -0
  490. package/lib/dist/resolution/frameworks/nestjs.d.ts +26 -0
  491. package/lib/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
  492. package/lib/dist/resolution/frameworks/nestjs.js +698 -0
  493. package/lib/dist/resolution/frameworks/nestjs.js.map +1 -0
  494. package/lib/dist/resolution/frameworks/play.d.ts +19 -0
  495. package/lib/dist/resolution/frameworks/play.d.ts.map +1 -0
  496. package/lib/dist/resolution/frameworks/play.js +111 -0
  497. package/lib/dist/resolution/frameworks/play.js.map +1 -0
  498. package/lib/dist/resolution/frameworks/python.d.ts +10 -0
  499. package/lib/dist/resolution/frameworks/python.d.ts.map +1 -0
  500. package/lib/dist/resolution/frameworks/python.js +400 -0
  501. package/lib/dist/resolution/frameworks/python.js.map +1 -0
  502. package/lib/dist/resolution/frameworks/react-native.d.ts +3 -0
  503. package/lib/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  504. package/lib/dist/resolution/frameworks/react-native.js +410 -0
  505. package/lib/dist/resolution/frameworks/react-native.js.map +1 -0
  506. package/lib/dist/resolution/frameworks/react.d.ts +8 -0
  507. package/lib/dist/resolution/frameworks/react.d.ts.map +1 -0
  508. package/lib/dist/resolution/frameworks/react.js +334 -0
  509. package/lib/dist/resolution/frameworks/react.js.map +1 -0
  510. package/lib/dist/resolution/frameworks/ruby.d.ts +8 -0
  511. package/lib/dist/resolution/frameworks/ruby.d.ts.map +1 -0
  512. package/lib/dist/resolution/frameworks/ruby.js +302 -0
  513. package/lib/dist/resolution/frameworks/ruby.js.map +1 -0
  514. package/lib/dist/resolution/frameworks/rust.d.ts +8 -0
  515. package/lib/dist/resolution/frameworks/rust.d.ts.map +1 -0
  516. package/lib/dist/resolution/frameworks/rust.js +304 -0
  517. package/lib/dist/resolution/frameworks/rust.js.map +1 -0
  518. package/lib/dist/resolution/frameworks/svelte.d.ts +9 -0
  519. package/lib/dist/resolution/frameworks/svelte.d.ts.map +1 -0
  520. package/lib/dist/resolution/frameworks/svelte.js +253 -0
  521. package/lib/dist/resolution/frameworks/svelte.js.map +1 -0
  522. package/lib/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  523. package/lib/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  524. package/lib/dist/resolution/frameworks/swift-objc.js +252 -0
  525. package/lib/dist/resolution/frameworks/swift-objc.js.map +1 -0
  526. package/lib/dist/resolution/frameworks/swift.d.ts +10 -0
  527. package/lib/dist/resolution/frameworks/swift.d.ts.map +1 -0
  528. package/lib/dist/resolution/frameworks/swift.js +400 -0
  529. package/lib/dist/resolution/frameworks/swift.js.map +1 -0
  530. package/lib/dist/resolution/frameworks/terraform.d.ts +38 -0
  531. package/lib/dist/resolution/frameworks/terraform.d.ts.map +1 -0
  532. package/lib/dist/resolution/frameworks/terraform.js +277 -0
  533. package/lib/dist/resolution/frameworks/terraform.js.map +1 -0
  534. package/lib/dist/resolution/frameworks/vue.d.ts +9 -0
  535. package/lib/dist/resolution/frameworks/vue.d.ts.map +1 -0
  536. package/lib/dist/resolution/frameworks/vue.js +303 -0
  537. package/lib/dist/resolution/frameworks/vue.js.map +1 -0
  538. package/lib/dist/resolution/go-module.d.ts +26 -0
  539. package/lib/dist/resolution/go-module.d.ts.map +1 -0
  540. package/lib/dist/resolution/go-module.js +78 -0
  541. package/lib/dist/resolution/go-module.js.map +1 -0
  542. package/lib/dist/resolution/goframe-synthesizer.d.ts +28 -0
  543. package/lib/dist/resolution/goframe-synthesizer.d.ts.map +1 -0
  544. package/lib/dist/resolution/goframe-synthesizer.js +158 -0
  545. package/lib/dist/resolution/goframe-synthesizer.js.map +1 -0
  546. package/lib/dist/resolution/import-resolver.d.ts +85 -0
  547. package/lib/dist/resolution/import-resolver.d.ts.map +1 -0
  548. package/lib/dist/resolution/import-resolver.js +1974 -0
  549. package/lib/dist/resolution/import-resolver.js.map +1 -0
  550. package/lib/dist/resolution/index.d.ts +238 -0
  551. package/lib/dist/resolution/index.d.ts.map +1 -0
  552. package/lib/dist/resolution/index.js +1633 -0
  553. package/lib/dist/resolution/index.js.map +1 -0
  554. package/lib/dist/resolution/lru-cache.d.ts +24 -0
  555. package/lib/dist/resolution/lru-cache.d.ts.map +1 -0
  556. package/lib/dist/resolution/lru-cache.js +62 -0
  557. package/lib/dist/resolution/lru-cache.js.map +1 -0
  558. package/lib/dist/resolution/name-matcher.d.ts +112 -0
  559. package/lib/dist/resolution/name-matcher.d.ts.map +1 -0
  560. package/lib/dist/resolution/name-matcher.js +1701 -0
  561. package/lib/dist/resolution/name-matcher.js.map +1 -0
  562. package/lib/dist/resolution/path-aliases.d.ts +68 -0
  563. package/lib/dist/resolution/path-aliases.d.ts.map +1 -0
  564. package/lib/dist/resolution/path-aliases.js +238 -0
  565. package/lib/dist/resolution/path-aliases.js.map +1 -0
  566. package/lib/dist/resolution/strip-comments.d.ts +27 -0
  567. package/lib/dist/resolution/strip-comments.d.ts.map +1 -0
  568. package/lib/dist/resolution/strip-comments.js +492 -0
  569. package/lib/dist/resolution/strip-comments.js.map +1 -0
  570. package/lib/dist/resolution/swift-objc-bridge.d.ts +134 -0
  571. package/lib/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  572. package/lib/dist/resolution/swift-objc-bridge.js +256 -0
  573. package/lib/dist/resolution/swift-objc-bridge.js.map +1 -0
  574. package/lib/dist/resolution/types.d.ts +253 -0
  575. package/lib/dist/resolution/types.d.ts.map +1 -0
  576. package/lib/dist/resolution/types.js +8 -0
  577. package/lib/dist/resolution/types.js.map +1 -0
  578. package/lib/dist/resolution/workspace-packages.d.ts +58 -0
  579. package/lib/dist/resolution/workspace-packages.d.ts.map +1 -0
  580. package/lib/dist/resolution/workspace-packages.js +346 -0
  581. package/lib/dist/resolution/workspace-packages.js.map +1 -0
  582. package/lib/dist/search/identifier-segments.d.ts +60 -0
  583. package/lib/dist/search/identifier-segments.d.ts.map +1 -0
  584. package/lib/dist/search/identifier-segments.js +176 -0
  585. package/lib/dist/search/identifier-segments.js.map +1 -0
  586. package/lib/dist/search/query-parser.d.ts +57 -0
  587. package/lib/dist/search/query-parser.d.ts.map +1 -0
  588. package/lib/dist/search/query-parser.js +177 -0
  589. package/lib/dist/search/query-parser.js.map +1 -0
  590. package/lib/dist/search/query-utils.d.ts +87 -0
  591. package/lib/dist/search/query-utils.d.ts.map +1 -0
  592. package/lib/dist/search/query-utils.js +449 -0
  593. package/lib/dist/search/query-utils.js.map +1 -0
  594. package/lib/dist/sync/git-hooks.d.ts +45 -0
  595. package/lib/dist/sync/git-hooks.d.ts.map +1 -0
  596. package/lib/dist/sync/git-hooks.js +227 -0
  597. package/lib/dist/sync/git-hooks.js.map +1 -0
  598. package/lib/dist/sync/index.d.ts +19 -0
  599. package/lib/dist/sync/index.d.ts.map +1 -0
  600. package/lib/dist/sync/index.js +35 -0
  601. package/lib/dist/sync/index.js.map +1 -0
  602. package/lib/dist/sync/watch-policy.d.ts +48 -0
  603. package/lib/dist/sync/watch-policy.d.ts.map +1 -0
  604. package/lib/dist/sync/watch-policy.js +124 -0
  605. package/lib/dist/sync/watch-policy.js.map +1 -0
  606. package/lib/dist/sync/watcher.d.ts +355 -0
  607. package/lib/dist/sync/watcher.d.ts.map +1 -0
  608. package/lib/dist/sync/watcher.js +848 -0
  609. package/lib/dist/sync/watcher.js.map +1 -0
  610. package/lib/dist/sync/worktree.d.ts +63 -0
  611. package/lib/dist/sync/worktree.d.ts.map +1 -0
  612. package/lib/dist/sync/worktree.js +182 -0
  613. package/lib/dist/sync/worktree.js.map +1 -0
  614. package/lib/dist/telemetry/index.d.ts +143 -0
  615. package/lib/dist/telemetry/index.d.ts.map +1 -0
  616. package/lib/dist/telemetry/index.js +541 -0
  617. package/lib/dist/telemetry/index.js.map +1 -0
  618. package/lib/dist/types.d.ts +415 -0
  619. package/lib/dist/types.d.ts.map +1 -0
  620. package/lib/dist/types.js +91 -0
  621. package/lib/dist/types.js.map +1 -0
  622. package/lib/dist/ui/glyphs.d.ts +42 -0
  623. package/lib/dist/ui/glyphs.d.ts.map +1 -0
  624. package/lib/dist/ui/glyphs.js +78 -0
  625. package/lib/dist/ui/glyphs.js.map +1 -0
  626. package/lib/dist/ui/shimmer-progress.d.ts +11 -0
  627. package/lib/dist/ui/shimmer-progress.d.ts.map +1 -0
  628. package/lib/dist/ui/shimmer-progress.js +90 -0
  629. package/lib/dist/ui/shimmer-progress.js.map +1 -0
  630. package/lib/dist/ui/shimmer-worker.d.ts +2 -0
  631. package/lib/dist/ui/shimmer-worker.d.ts.map +1 -0
  632. package/lib/dist/ui/shimmer-worker.js +118 -0
  633. package/lib/dist/ui/shimmer-worker.js.map +1 -0
  634. package/lib/dist/ui/types.d.ts +17 -0
  635. package/lib/dist/ui/types.d.ts.map +1 -0
  636. package/lib/dist/ui/types.js +3 -0
  637. package/lib/dist/ui/types.js.map +1 -0
  638. package/lib/dist/upgrade/index.d.ts +132 -0
  639. package/lib/dist/upgrade/index.d.ts.map +1 -0
  640. package/lib/dist/upgrade/index.js +498 -0
  641. package/lib/dist/upgrade/index.js.map +1 -0
  642. package/lib/dist/utils.d.ts +224 -0
  643. package/lib/dist/utils.d.ts.map +1 -0
  644. package/lib/dist/utils.js +583 -0
  645. package/lib/dist/utils.js.map +1 -0
  646. package/lib/node_modules/.package-lock.json +125 -0
  647. package/lib/node_modules/@clack/core/CHANGELOG.md +348 -0
  648. package/lib/node_modules/@clack/core/LICENSE +9 -0
  649. package/lib/node_modules/@clack/core/README.md +22 -0
  650. package/lib/node_modules/@clack/core/dist/index.d.mts +363 -0
  651. package/lib/node_modules/@clack/core/dist/index.mjs +17 -0
  652. package/lib/node_modules/@clack/core/dist/index.mjs.map +1 -0
  653. package/lib/node_modules/@clack/core/package.json +63 -0
  654. package/lib/node_modules/@clack/prompts/CHANGELOG.md +591 -0
  655. package/lib/node_modules/@clack/prompts/LICENSE +9 -0
  656. package/lib/node_modules/@clack/prompts/README.md +375 -0
  657. package/lib/node_modules/@clack/prompts/dist/index.d.mts +396 -0
  658. package/lib/node_modules/@clack/prompts/dist/index.mjs +144 -0
  659. package/lib/node_modules/@clack/prompts/dist/index.mjs.map +1 -0
  660. package/lib/node_modules/@clack/prompts/package.json +68 -0
  661. package/lib/node_modules/commander/LICENSE +22 -0
  662. package/lib/node_modules/commander/Readme.md +1176 -0
  663. package/lib/node_modules/commander/esm.mjs +16 -0
  664. package/lib/node_modules/commander/index.js +24 -0
  665. package/lib/node_modules/commander/lib/argument.js +150 -0
  666. package/lib/node_modules/commander/lib/command.js +2777 -0
  667. package/lib/node_modules/commander/lib/error.js +39 -0
  668. package/lib/node_modules/commander/lib/help.js +747 -0
  669. package/lib/node_modules/commander/lib/option.js +380 -0
  670. package/lib/node_modules/commander/lib/suggestSimilar.js +101 -0
  671. package/lib/node_modules/commander/package-support.json +19 -0
  672. package/lib/node_modules/commander/package.json +82 -0
  673. package/lib/node_modules/commander/typings/esm.d.mts +3 -0
  674. package/lib/node_modules/commander/typings/index.d.ts +1113 -0
  675. package/lib/node_modules/fast-string-truncated-width/dist/index.d.ts +4 -0
  676. package/lib/node_modules/fast-string-truncated-width/dist/index.js +111 -0
  677. package/lib/node_modules/fast-string-truncated-width/dist/types.d.ts +19 -0
  678. package/lib/node_modules/fast-string-truncated-width/dist/types.js +2 -0
  679. package/lib/node_modules/fast-string-truncated-width/dist/utils.d.ts +4 -0
  680. package/lib/node_modules/fast-string-truncated-width/dist/utils.js +20 -0
  681. package/lib/node_modules/fast-string-truncated-width/license +21 -0
  682. package/lib/node_modules/fast-string-truncated-width/package.json +35 -0
  683. package/lib/node_modules/fast-string-truncated-width/readme.md +59 -0
  684. package/lib/node_modules/fast-string-width/dist/index.d.ts +4 -0
  685. package/lib/node_modules/fast-string-width/dist/index.js +14 -0
  686. package/lib/node_modules/fast-string-width/license +21 -0
  687. package/lib/node_modules/fast-string-width/package.json +34 -0
  688. package/lib/node_modules/fast-string-width/readme.md +42 -0
  689. package/lib/node_modules/fast-wrap-ansi/LICENSE +23 -0
  690. package/lib/node_modules/fast-wrap-ansi/README.md +26 -0
  691. package/lib/node_modules/fast-wrap-ansi/lib/main.d.ts +6 -0
  692. package/lib/node_modules/fast-wrap-ansi/lib/main.js +219 -0
  693. package/lib/node_modules/fast-wrap-ansi/lib/main.js.map +1 -0
  694. package/lib/node_modules/fast-wrap-ansi/package.json +51 -0
  695. package/lib/node_modules/ignore/LICENSE-MIT +21 -0
  696. package/lib/node_modules/ignore/README.md +452 -0
  697. package/lib/node_modules/ignore/index.d.ts +81 -0
  698. package/lib/node_modules/ignore/index.js +784 -0
  699. package/lib/node_modules/ignore/legacy.js +681 -0
  700. package/lib/node_modules/ignore/package.json +87 -0
  701. package/lib/node_modules/jsonc-parser/CHANGELOG.md +76 -0
  702. package/lib/node_modules/jsonc-parser/LICENSE.md +21 -0
  703. package/lib/node_modules/jsonc-parser/README.md +364 -0
  704. package/lib/node_modules/jsonc-parser/SECURITY.md +41 -0
  705. package/lib/node_modules/jsonc-parser/lib/esm/impl/edit.js +185 -0
  706. package/lib/node_modules/jsonc-parser/lib/esm/impl/format.js +261 -0
  707. package/lib/node_modules/jsonc-parser/lib/esm/impl/parser.js +659 -0
  708. package/lib/node_modules/jsonc-parser/lib/esm/impl/scanner.js +443 -0
  709. package/lib/node_modules/jsonc-parser/lib/esm/impl/string-intern.js +29 -0
  710. package/lib/node_modules/jsonc-parser/lib/esm/main.d.ts +351 -0
  711. package/lib/node_modules/jsonc-parser/lib/esm/main.js +178 -0
  712. package/lib/node_modules/jsonc-parser/lib/umd/impl/edit.js +201 -0
  713. package/lib/node_modules/jsonc-parser/lib/umd/impl/format.js +275 -0
  714. package/lib/node_modules/jsonc-parser/lib/umd/impl/parser.js +682 -0
  715. package/lib/node_modules/jsonc-parser/lib/umd/impl/scanner.js +456 -0
  716. package/lib/node_modules/jsonc-parser/lib/umd/impl/string-intern.js +42 -0
  717. package/lib/node_modules/jsonc-parser/lib/umd/main.d.ts +351 -0
  718. package/lib/node_modules/jsonc-parser/lib/umd/main.js +194 -0
  719. package/lib/node_modules/jsonc-parser/package.json +37 -0
  720. package/lib/node_modules/picomatch/LICENSE +21 -0
  721. package/lib/node_modules/picomatch/README.md +738 -0
  722. package/lib/node_modules/picomatch/index.js +17 -0
  723. package/lib/node_modules/picomatch/lib/constants.js +180 -0
  724. package/lib/node_modules/picomatch/lib/parse.js +1085 -0
  725. package/lib/node_modules/picomatch/lib/picomatch.js +341 -0
  726. package/lib/node_modules/picomatch/lib/scan.js +391 -0
  727. package/lib/node_modules/picomatch/lib/utils.js +72 -0
  728. package/lib/node_modules/picomatch/package.json +83 -0
  729. package/lib/node_modules/picomatch/posix.js +3 -0
  730. package/lib/node_modules/sisteransi/license +21 -0
  731. package/lib/node_modules/sisteransi/package.json +34 -0
  732. package/lib/node_modules/sisteransi/readme.md +113 -0
  733. package/lib/node_modules/sisteransi/src/index.js +58 -0
  734. package/lib/node_modules/sisteransi/src/sisteransi.d.ts +35 -0
  735. package/lib/node_modules/tree-sitter-wasms/LICENSE +24 -0
  736. package/lib/node_modules/tree-sitter-wasms/README.md +23 -0
  737. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-bash.wasm +0 -0
  738. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-c.wasm +0 -0
  739. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-c_sharp.wasm +0 -0
  740. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-cpp.wasm +0 -0
  741. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-css.wasm +0 -0
  742. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-dart.wasm +0 -0
  743. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-elisp.wasm +0 -0
  744. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-elixir.wasm +0 -0
  745. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-elm.wasm +0 -0
  746. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-embedded_template.wasm +0 -0
  747. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-go.wasm +0 -0
  748. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-html.wasm +0 -0
  749. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-java.wasm +0 -0
  750. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-javascript.wasm +0 -0
  751. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-json.wasm +0 -0
  752. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-kotlin.wasm +0 -0
  753. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-lua.wasm +0 -0
  754. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-objc.wasm +0 -0
  755. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-ocaml.wasm +0 -0
  756. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-php.wasm +0 -0
  757. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-python.wasm +0 -0
  758. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-ql.wasm +0 -0
  759. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-rescript.wasm +0 -0
  760. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-ruby.wasm +0 -0
  761. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-rust.wasm +0 -0
  762. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-scala.wasm +0 -0
  763. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-solidity.wasm +0 -0
  764. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-swift.wasm +0 -0
  765. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-systemrdl.wasm +0 -0
  766. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-tlaplus.wasm +0 -0
  767. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-toml.wasm +0 -0
  768. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-tsx.wasm +0 -0
  769. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-typescript.wasm +0 -0
  770. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-vue.wasm +0 -0
  771. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-yaml.wasm +0 -0
  772. package/lib/node_modules/tree-sitter-wasms/out/tree-sitter-zig.wasm +0 -0
  773. package/lib/node_modules/tree-sitter-wasms/package.json +64 -0
  774. package/lib/node_modules/web-tree-sitter/LICENSE +21 -0
  775. package/lib/node_modules/web-tree-sitter/README.md +269 -0
  776. package/lib/node_modules/web-tree-sitter/debug/tree-sitter.cjs +4558 -0
  777. package/lib/node_modules/web-tree-sitter/debug/tree-sitter.cjs.map +7 -0
  778. package/lib/node_modules/web-tree-sitter/debug/tree-sitter.js +4516 -0
  779. package/lib/node_modules/web-tree-sitter/debug/tree-sitter.js.map +7 -0
  780. package/lib/node_modules/web-tree-sitter/debug/tree-sitter.wasm +0 -0
  781. package/lib/node_modules/web-tree-sitter/debug/tree-sitter.wasm.map +31 -0
  782. package/lib/node_modules/web-tree-sitter/lib/alloc.c +48 -0
  783. package/lib/node_modules/web-tree-sitter/lib/alloc.h +41 -0
  784. package/lib/node_modules/web-tree-sitter/lib/array.h +291 -0
  785. package/lib/node_modules/web-tree-sitter/lib/atomic.h +68 -0
  786. package/lib/node_modules/web-tree-sitter/lib/clock.h +146 -0
  787. package/lib/node_modules/web-tree-sitter/lib/error_costs.h +11 -0
  788. package/lib/node_modules/web-tree-sitter/lib/get_changed_ranges.c +523 -0
  789. package/lib/node_modules/web-tree-sitter/lib/get_changed_ranges.h +36 -0
  790. package/lib/node_modules/web-tree-sitter/lib/host.h +21 -0
  791. package/lib/node_modules/web-tree-sitter/lib/language.c +293 -0
  792. package/lib/node_modules/web-tree-sitter/lib/language.h +293 -0
  793. package/lib/node_modules/web-tree-sitter/lib/length.h +52 -0
  794. package/lib/node_modules/web-tree-sitter/lib/lexer.c +483 -0
  795. package/lib/node_modules/web-tree-sitter/lib/lexer.h +54 -0
  796. package/lib/node_modules/web-tree-sitter/lib/lib.c +12 -0
  797. package/lib/node_modules/web-tree-sitter/lib/node.c +875 -0
  798. package/lib/node_modules/web-tree-sitter/lib/parser.c +2297 -0
  799. package/lib/node_modules/web-tree-sitter/lib/parser.h +286 -0
  800. package/lib/node_modules/web-tree-sitter/lib/point.h +48 -0
  801. package/lib/node_modules/web-tree-sitter/lib/query.c +4347 -0
  802. package/lib/node_modules/web-tree-sitter/lib/reduce_action.h +34 -0
  803. package/lib/node_modules/web-tree-sitter/lib/reusable_node.h +95 -0
  804. package/lib/node_modules/web-tree-sitter/lib/stack.c +912 -0
  805. package/lib/node_modules/web-tree-sitter/lib/stack.h +133 -0
  806. package/lib/node_modules/web-tree-sitter/lib/subtree.c +1034 -0
  807. package/lib/node_modules/web-tree-sitter/lib/subtree.h +399 -0
  808. package/lib/node_modules/web-tree-sitter/lib/tree-sitter.c +987 -0
  809. package/lib/node_modules/web-tree-sitter/lib/tree-sitter.cjs +2988 -0
  810. package/lib/node_modules/web-tree-sitter/lib/tree-sitter.wasm +0 -0
  811. package/lib/node_modules/web-tree-sitter/lib/tree-sitter.wasm.map +1 -0
  812. package/lib/node_modules/web-tree-sitter/lib/tree.c +170 -0
  813. package/lib/node_modules/web-tree-sitter/lib/tree.h +31 -0
  814. package/lib/node_modules/web-tree-sitter/lib/tree_cursor.c +716 -0
  815. package/lib/node_modules/web-tree-sitter/lib/tree_cursor.h +48 -0
  816. package/lib/node_modules/web-tree-sitter/lib/ts_assert.h +11 -0
  817. package/lib/node_modules/web-tree-sitter/lib/unicode.h +75 -0
  818. package/lib/node_modules/web-tree-sitter/lib/wasm_store.c +1937 -0
  819. package/lib/node_modules/web-tree-sitter/lib/wasm_store.h +31 -0
  820. package/lib/node_modules/web-tree-sitter/package.json +98 -0
  821. package/lib/node_modules/web-tree-sitter/src/bindings.ts +26 -0
  822. package/lib/node_modules/web-tree-sitter/src/constants.ts +133 -0
  823. package/lib/node_modules/web-tree-sitter/src/index.ts +31 -0
  824. package/lib/node_modules/web-tree-sitter/src/language.ts +291 -0
  825. package/lib/node_modules/web-tree-sitter/src/lookahead_iterator.ts +75 -0
  826. package/lib/node_modules/web-tree-sitter/src/marshal.ts +176 -0
  827. package/lib/node_modules/web-tree-sitter/src/node.ts +646 -0
  828. package/lib/node_modules/web-tree-sitter/src/parser.ts +325 -0
  829. package/lib/node_modules/web-tree-sitter/src/query.ts +973 -0
  830. package/lib/node_modules/web-tree-sitter/src/tree.ts +145 -0
  831. package/lib/node_modules/web-tree-sitter/src/tree_cursor.ts +318 -0
  832. package/lib/node_modules/web-tree-sitter/tree-sitter.cjs +4031 -0
  833. package/lib/node_modules/web-tree-sitter/tree-sitter.cjs.map +7 -0
  834. package/lib/node_modules/web-tree-sitter/tree-sitter.js +3980 -0
  835. package/lib/node_modules/web-tree-sitter/tree-sitter.js.map +7 -0
  836. package/lib/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
  837. package/lib/node_modules/web-tree-sitter/tree-sitter.wasm.map +30 -0
  838. package/lib/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1030 -0
  839. package/lib/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +56 -0
  840. package/lib/package.json +64 -0
  841. package/node +0 -0
  842. package/package.json +17 -0
@@ -0,0 +1,1740 @@
1
+ "use strict";
2
+ /**
3
+ * Database Queries
4
+ *
5
+ * Prepared statements for CRUD operations on the knowledge graph.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.QueryBuilder = void 0;
9
+ const utils_1 = require("../utils");
10
+ const query_utils_1 = require("../search/query-utils");
11
+ const query_parser_1 = require("../search/query-parser");
12
+ const generated_detection_1 = require("../extraction/generated-detection");
13
+ const identifier_segments_1 = require("../search/identifier-segments");
14
+ /**
15
+ * Path-only heuristic for files that should not be candidates for
16
+ * "dominant file" detection: test/spec files and tool-generated files.
17
+ * Generated files (`*.pb.go`, `*.pulsar.go`, mock outputs, …) often
18
+ * have huge in-file edge counts that dwarf the real source — etcd's
19
+ * `rpc.pb.go` has 4× the in-file edges of `server.go`.
20
+ */
21
+ function isLowValueFile(filePath) {
22
+ const lp = filePath.toLowerCase();
23
+ return (/(?:^|\/)(tests?|__tests?__|spec)\//.test(lp) ||
24
+ /_test\.go$/.test(lp) ||
25
+ /(?:^|\/)test_[^/]+\.py$/.test(lp) ||
26
+ /_test\.py$/.test(lp) ||
27
+ /_spec\.rb$/.test(lp) ||
28
+ /_test\.rb$/.test(lp) ||
29
+ /\.(test|spec)\.[jt]sx?$/.test(lp) ||
30
+ /(test|spec|tests)\.(java|kt|scala)$/.test(lp) ||
31
+ /(tests?|spec)\.cs$/.test(lp) ||
32
+ /tests?\.swift$/.test(lp) ||
33
+ /_test\.dart$/.test(lp) ||
34
+ (0, generated_detection_1.isGeneratedFile)(filePath));
35
+ }
36
+ const SQLITE_PARAM_CHUNK_SIZE = 500;
37
+ /**
38
+ * Convert database row to Node object
39
+ */
40
+ function rowToNode(row) {
41
+ return {
42
+ id: row.id,
43
+ kind: row.kind,
44
+ name: row.name,
45
+ qualifiedName: row.qualified_name,
46
+ filePath: row.file_path,
47
+ language: row.language,
48
+ startLine: row.start_line,
49
+ endLine: row.end_line,
50
+ startColumn: row.start_column,
51
+ endColumn: row.end_column,
52
+ docstring: row.docstring ?? undefined,
53
+ signature: row.signature ?? undefined,
54
+ visibility: row.visibility,
55
+ isExported: row.is_exported === 1,
56
+ isAsync: row.is_async === 1,
57
+ isStatic: row.is_static === 1,
58
+ isAbstract: row.is_abstract === 1,
59
+ decorators: row.decorators ? (0, utils_1.safeJsonParse)(row.decorators, undefined) : undefined,
60
+ typeParameters: row.type_parameters ? (0, utils_1.safeJsonParse)(row.type_parameters, undefined) : undefined,
61
+ returnType: row.return_type ?? undefined,
62
+ updatedAt: row.updated_at,
63
+ };
64
+ }
65
+ /**
66
+ * Convert database row to Edge object
67
+ */
68
+ function rowToEdge(row) {
69
+ return {
70
+ source: row.source,
71
+ target: row.target,
72
+ kind: row.kind,
73
+ metadata: row.metadata ? (0, utils_1.safeJsonParse)(row.metadata, undefined) : undefined,
74
+ line: row.line ?? undefined,
75
+ column: row.col ?? undefined,
76
+ provenance: row.provenance,
77
+ };
78
+ }
79
+ /**
80
+ * Convert database row to FileRecord object
81
+ */
82
+ function rowToFileRecord(row) {
83
+ return {
84
+ path: row.path,
85
+ contentHash: row.content_hash,
86
+ language: row.language,
87
+ size: row.size,
88
+ modifiedAt: row.modified_at,
89
+ indexedAt: row.indexed_at,
90
+ nodeCount: row.node_count,
91
+ errors: row.errors ? (0, utils_1.safeJsonParse)(row.errors, undefined) : undefined,
92
+ };
93
+ }
94
+ /**
95
+ * Query builder for the knowledge graph database
96
+ */
97
+ class QueryBuilder {
98
+ db;
99
+ // Project-name tokens (go.mod / package.json / repo dir), normalized. A query
100
+ // word matching one is dropped from path-relevance scoring — it names the
101
+ // whole project, not a symbol, so it carries no discriminative signal (#720).
102
+ // Set once by the BHGraph instance; empty by default (no down-weighting).
103
+ projectNameTokens = new Set();
104
+ // Node cache for frequently accessed nodes (LRU-style, max 1000 entries)
105
+ nodeCache = new Map();
106
+ maxCacheSize = 1000;
107
+ // Prepared statements (lazily initialized)
108
+ stmts = {};
109
+ // Names whose segments were already written this session — skips re-splitting
110
+ // and re-inserting for the same-named nodes that repeat across files ("get",
111
+ // "render", …). Purely a write-path fast path; INSERT OR IGNORE is the
112
+ // correctness backstop. Bounded so a pathological repo can't grow it forever.
113
+ segmentedNames = new Set();
114
+ static MAX_SEGMENTED_NAMES = 65536;
115
+ constructor(db) {
116
+ this.db = db;
117
+ }
118
+ /** Set the normalized project-name tokens used to down-weight non-discriminative
119
+ * query words in path scoring (#720). Called once when the project opens. */
120
+ setProjectNameTokens(tokens) {
121
+ this.projectNameTokens = tokens;
122
+ }
123
+ /** The normalized project-name tokens (#720); empty if none were derived. */
124
+ getProjectNameTokens() {
125
+ return this.projectNameTokens;
126
+ }
127
+ // ===========================================================================
128
+ // Node Operations
129
+ // ===========================================================================
130
+ /**
131
+ * Insert a new node
132
+ */
133
+ insertNode(node) {
134
+ if (!this.stmts.insertNode) {
135
+ this.stmts.insertNode = this.db.prepare(`
136
+ INSERT OR REPLACE INTO nodes (
137
+ id, kind, name, qualified_name, file_path, language,
138
+ start_line, end_line, start_column, end_column,
139
+ docstring, signature, visibility,
140
+ is_exported, is_async, is_static, is_abstract,
141
+ decorators, type_parameters, return_type, updated_at
142
+ ) VALUES (
143
+ @id, @kind, @name, @qualifiedName, @filePath, @language,
144
+ @startLine, @endLine, @startColumn, @endColumn,
145
+ @docstring, @signature, @visibility,
146
+ @isExported, @isAsync, @isStatic, @isAbstract,
147
+ @decorators, @typeParameters, @returnType, @updatedAt
148
+ )
149
+ `);
150
+ }
151
+ // Validate required fields to prevent SQLite bind errors
152
+ if (!node.id || !node.kind || !node.name || !node.filePath || !node.language) {
153
+ console.error('[BHGraph] Skipping node with missing required fields:', {
154
+ id: node.id,
155
+ kind: node.kind,
156
+ name: node.name,
157
+ filePath: node.filePath,
158
+ language: node.language,
159
+ });
160
+ return;
161
+ }
162
+ // INSERT OR REPLACE may overwrite a node we have cached. Drop the
163
+ // stale entry so the next getNodeById sees the new row, not the old
164
+ // one (matches the cache-invalidation pattern used by updateNode and
165
+ // deleteNode below).
166
+ this.nodeCache.delete(node.id);
167
+ this.stmts.insertNode.run({
168
+ id: node.id,
169
+ kind: node.kind,
170
+ name: node.name,
171
+ qualifiedName: node.qualifiedName ?? node.name,
172
+ filePath: node.filePath,
173
+ language: node.language,
174
+ startLine: node.startLine ?? 0,
175
+ endLine: node.endLine ?? 0,
176
+ startColumn: node.startColumn ?? 0,
177
+ endColumn: node.endColumn ?? 0,
178
+ docstring: node.docstring ?? null,
179
+ signature: node.signature ?? null,
180
+ visibility: node.visibility ?? null,
181
+ isExported: node.isExported ? 1 : 0,
182
+ isAsync: node.isAsync ? 1 : 0,
183
+ isStatic: node.isStatic ? 1 : 0,
184
+ isAbstract: node.isAbstract ? 1 : 0,
185
+ decorators: node.decorators ? JSON.stringify(node.decorators) : null,
186
+ typeParameters: node.typeParameters ? JSON.stringify(node.typeParameters) : null,
187
+ returnType: node.returnType ?? null,
188
+ updatedAt: node.updatedAt ?? Date.now(),
189
+ });
190
+ // Segment vocabulary rides the same write path (and transaction) so it can
191
+ // never drift ahead of the nodes it describes. Deletes intentionally leave
192
+ // orphans behind — vocab rows are proposals re-verified against nodes
193
+ // before use, and a full index clears the table at its start. File nodes
194
+ // are excluded: a file's basename duplicates the symbols inside it
195
+ // (state-machine.ts / OrderStateMachine), which double-counts every
196
+ // concept and defeats the singleton-vs-cluster rarity statistics. Import
197
+ // nodes are excluded too (#1144): they're named after module specifiers
198
+ // ("external-unindexed-pkg", "./utils/helpers"), not symbols — an
199
+ // import-only name can never be surfaced (getSegmentMatches requires a
200
+ // real definition), so its rows would only inflate the rarity statistics.
201
+ if (this.isSegmentableKind(node.kind))
202
+ this.insertNameSegments(node.name);
203
+ }
204
+ /** Which node kinds contribute their name to the segment vocabulary — the
205
+ * single gate shared by insertNode, updateNode, and the rebuild page query
206
+ * (getDistinctNodeNames), so the write paths can't drift apart. */
207
+ isSegmentableKind(kind) {
208
+ return kind !== 'file' && kind !== 'import';
209
+ }
210
+ /** Write `name`'s segments into name_segment_vocab (idempotent). */
211
+ insertNameSegments(name) {
212
+ if (this.segmentedNames.has(name))
213
+ return;
214
+ if (this.segmentedNames.size >= QueryBuilder.MAX_SEGMENTED_NAMES)
215
+ this.segmentedNames.clear();
216
+ this.segmentedNames.add(name);
217
+ if (!this.stmts.insertNameSegment) {
218
+ this.stmts.insertNameSegment = this.db.prepare('INSERT OR IGNORE INTO name_segment_vocab (segment, name) VALUES (?, ?)');
219
+ }
220
+ for (const segment of (0, identifier_segments_1.splitIdentifierSegments)(name)) {
221
+ this.stmts.insertNameSegment.run(segment, name);
222
+ }
223
+ }
224
+ /**
225
+ * Insert multiple nodes in a transaction
226
+ */
227
+ insertNodes(nodes) {
228
+ this.db.transaction(() => {
229
+ for (const node of nodes) {
230
+ this.insertNode(node);
231
+ }
232
+ })();
233
+ }
234
+ /**
235
+ * Update an existing node
236
+ */
237
+ updateNode(node) {
238
+ if (!this.stmts.updateNode) {
239
+ this.stmts.updateNode = this.db.prepare(`
240
+ UPDATE nodes SET
241
+ kind = @kind,
242
+ name = @name,
243
+ qualified_name = @qualifiedName,
244
+ file_path = @filePath,
245
+ language = @language,
246
+ start_line = @startLine,
247
+ end_line = @endLine,
248
+ start_column = @startColumn,
249
+ end_column = @endColumn,
250
+ docstring = @docstring,
251
+ signature = @signature,
252
+ visibility = @visibility,
253
+ is_exported = @isExported,
254
+ is_async = @isAsync,
255
+ is_static = @isStatic,
256
+ is_abstract = @isAbstract,
257
+ decorators = @decorators,
258
+ type_parameters = @typeParameters,
259
+ return_type = @returnType,
260
+ updated_at = @updatedAt
261
+ WHERE id = @id
262
+ `);
263
+ }
264
+ // Invalidate cache before update
265
+ this.nodeCache.delete(node.id);
266
+ // Validate required fields
267
+ if (!node.id || !node.kind || !node.name || !node.filePath || !node.language) {
268
+ console.error('[BHGraph] Skipping node update with missing required fields:', node.id);
269
+ return;
270
+ }
271
+ this.stmts.updateNode.run({
272
+ id: node.id,
273
+ kind: node.kind,
274
+ name: node.name,
275
+ qualifiedName: node.qualifiedName ?? node.name,
276
+ filePath: node.filePath,
277
+ language: node.language,
278
+ startLine: node.startLine ?? 0,
279
+ endLine: node.endLine ?? 0,
280
+ startColumn: node.startColumn ?? 0,
281
+ endColumn: node.endColumn ?? 0,
282
+ docstring: node.docstring ?? null,
283
+ signature: node.signature ?? null,
284
+ visibility: node.visibility ?? null,
285
+ isExported: node.isExported ? 1 : 0,
286
+ isAsync: node.isAsync ? 1 : 0,
287
+ isStatic: node.isStatic ? 1 : 0,
288
+ isAbstract: node.isAbstract ? 1 : 0,
289
+ decorators: node.decorators ? JSON.stringify(node.decorators) : null,
290
+ typeParameters: node.typeParameters ? JSON.stringify(node.typeParameters) : null,
291
+ returnType: node.returnType ?? null,
292
+ updatedAt: node.updatedAt ?? Date.now(),
293
+ });
294
+ // updateNode is a second real write path to `nodes` — framework
295
+ // post-extract passes rewrite names through it (NestJS route prefixing),
296
+ // and a renamed node's new name must reach the segment vocabulary just
297
+ // like an inserted one's (#1141). Without this the rename left the new
298
+ // name permanently unsearchable: the old name's rows became honest-gate
299
+ // orphans and the only backfill is gated on the vocab being EMPTY.
300
+ // insertNameSegments is idempotent (in-memory set + INSERT OR IGNORE),
301
+ // so no name-changed check is needed.
302
+ if (this.isSegmentableKind(node.kind))
303
+ this.insertNameSegments(node.name);
304
+ }
305
+ /**
306
+ * Delete a node by ID
307
+ */
308
+ deleteNode(id) {
309
+ if (!this.stmts.deleteNode) {
310
+ this.stmts.deleteNode = this.db.prepare('DELETE FROM nodes WHERE id = ?');
311
+ }
312
+ // Invalidate cache
313
+ this.nodeCache.delete(id);
314
+ this.stmts.deleteNode.run(id);
315
+ }
316
+ /**
317
+ * Delete all nodes for a file
318
+ */
319
+ deleteNodesByFile(filePath) {
320
+ if (!this.stmts.deleteNodesByFile) {
321
+ this.stmts.deleteNodesByFile = this.db.prepare('DELETE FROM nodes WHERE file_path = ?');
322
+ }
323
+ // Invalidate cache for nodes in this file
324
+ for (const [id, node] of this.nodeCache) {
325
+ if (node.filePath === filePath) {
326
+ this.nodeCache.delete(id);
327
+ }
328
+ }
329
+ this.stmts.deleteNodesByFile.run(filePath);
330
+ }
331
+ // ===========================================================================
332
+ // Name-segment vocabulary (prompt-hook graph-derived gate)
333
+ // ===========================================================================
334
+ /** Wipe the segment vocabulary. A full index calls this at its start; the
335
+ * node write path repopulates it as files (re-)index, so the end state is
336
+ * exactly the current names with no orphan rows. */
337
+ clearNameSegmentVocab() {
338
+ this.db.exec('DELETE FROM name_segment_vocab');
339
+ this.segmentedNames.clear();
340
+ }
341
+ /** True when the vocab has no rows — an index built before the table existed.
342
+ * `sync` uses this to heal such databases (see rebuildNameSegmentVocabFrom). */
343
+ isNameSegmentVocabEmpty() {
344
+ const row = this.db.prepare('SELECT 1 FROM name_segment_vocab LIMIT 1').get();
345
+ return row === undefined;
346
+ }
347
+ /** One page of distinct segmentable node names, for batched vocab rebuilds
348
+ * (file basenames and import specifiers are excluded from the vocab — see
349
+ * insertNode). */
350
+ getDistinctNodeNames(limit, offset) {
351
+ const rows = this.db
352
+ .prepare("SELECT DISTINCT name FROM nodes WHERE kind NOT IN ('file', 'import') ORDER BY name LIMIT ? OFFSET ?")
353
+ .all(limit, offset);
354
+ return rows.map((r) => r.name);
355
+ }
356
+ /** Insert segments for a batch of names in one transaction (vocab heal path). */
357
+ insertNameSegmentsBatch(names) {
358
+ this.db.transaction(() => {
359
+ for (const name of names)
360
+ this.insertNameSegments(name);
361
+ })();
362
+ }
363
+ /**
364
+ * Names whose segments cover at least `minWords` distinct PROMPT WORDS —
365
+ * the co-occurrence probe behind the prompt hook's medium tier: the words
366
+ * "state" and "machine" both being segments of `OrderStateMachine` is strong
367
+ * evidence the prompt names that symbol in prose. Ordered by coverage.
368
+ *
369
+ * Takes (segment variant → original word) pairs and folds variants back to
370
+ * their word INSIDE the SQL: a name matching both `service` and `services`
371
+ * counts ONE word, not two. Counting raw variants let plural-variant pairs
372
+ * of a single word tie with genuine two-word matches and — because ORDER
373
+ * BY/LIMIT run here, before any JS-side re-check — crowd a real match past
374
+ * the LIMIT on vocab-heavy repos (#1146).
375
+ */
376
+ getSegmentCoOccurrence(variants, minWords, limit) {
377
+ if (variants.length === 0)
378
+ return [];
379
+ const placeholders = variants.map(() => '?').join(', ');
380
+ const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
381
+ const rows = this.db
382
+ .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
383
+ FROM name_segment_vocab
384
+ WHERE segment IN (${placeholders})
385
+ GROUP BY name
386
+ HAVING matches >= ?
387
+ ORDER BY matches DESC, length(name) ASC
388
+ LIMIT ?`)
389
+ .all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
390
+ return rows;
391
+ }
392
+ /** How many distinct names each segment appears in — the rarity signal that
393
+ * separates a discriminative word ("checkout") from a ubiquitous one ("state"). */
394
+ getSegmentNameCounts(segments) {
395
+ if (segments.length === 0)
396
+ return new Map();
397
+ const placeholders = segments.map(() => '?').join(', ');
398
+ const rows = this.db
399
+ .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
400
+ WHERE segment IN (${placeholders}) GROUP BY segment`)
401
+ .all(...segments);
402
+ return new Map(rows.map((r) => [r.segment, r.n]));
403
+ }
404
+ /** Names containing the given segment (rare-single-word tier). */
405
+ getNamesForSegment(segment, limit) {
406
+ const rows = this.db
407
+ .prepare('SELECT name FROM name_segment_vocab WHERE segment = ? ORDER BY length(name) ASC LIMIT ?')
408
+ .all(segment, limit);
409
+ return rows.map((r) => r.name);
410
+ }
411
+ /**
412
+ * Get a node by ID
413
+ */
414
+ getNodeById(id) {
415
+ // Check cache first
416
+ if (this.nodeCache.has(id)) {
417
+ const cached = this.nodeCache.get(id);
418
+ // Move to end to implement LRU (delete and re-add)
419
+ this.nodeCache.delete(id);
420
+ this.nodeCache.set(id, cached);
421
+ return cached;
422
+ }
423
+ if (!this.stmts.getNodeById) {
424
+ this.stmts.getNodeById = this.db.prepare('SELECT * FROM nodes WHERE id = ?');
425
+ }
426
+ const row = this.stmts.getNodeById.get(id);
427
+ if (!row) {
428
+ return null;
429
+ }
430
+ const node = rowToNode(row);
431
+ this.cacheNode(node);
432
+ return node;
433
+ }
434
+ /**
435
+ * Batch lookup: fetch many nodes by ID in a single SQL round-trip.
436
+ *
437
+ * Replaces the N+1 pattern in graph traversal where every edge would
438
+ * trigger its own `getNodeById` call. For a function with 50 callers
439
+ * this collapses 50 point reads into one IN-list query (~10-50x
440
+ * faster end-to-end).
441
+ *
442
+ * Returns a Map keyed by id so callers can preserve their own ordering
443
+ * (typically the order edges were returned from the graph). Missing IDs
444
+ * are simply absent from the map.
445
+ *
446
+ * Cache-aware: ids already in the LRU cache are served from memory and
447
+ * the SQL query only touches the misses.
448
+ */
449
+ getNodesByIds(ids) {
450
+ const out = new Map();
451
+ if (ids.length === 0)
452
+ return out;
453
+ // Serve cache hits first; build the miss list for SQL.
454
+ const misses = [];
455
+ for (const id of ids) {
456
+ const cached = this.nodeCache.get(id);
457
+ if (cached !== undefined) {
458
+ // LRU touch
459
+ this.nodeCache.delete(id);
460
+ this.nodeCache.set(id, cached);
461
+ out.set(id, cached);
462
+ }
463
+ else {
464
+ misses.push(id);
465
+ }
466
+ }
467
+ if (misses.length === 0)
468
+ return out;
469
+ // Chunk under SQLite's parameter limit (default 999, raised to 32766
470
+ // in better-sqlite3 builds — chunk at 500 for safety across both
471
+ // backends and to keep the query plan simple).
472
+ for (let i = 0; i < misses.length; i += SQLITE_PARAM_CHUNK_SIZE) {
473
+ const chunk = misses.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
474
+ const placeholders = chunk.map(() => '?').join(',');
475
+ const rows = this.db
476
+ .prepare(`SELECT * FROM nodes WHERE id IN (${placeholders})`)
477
+ .all(...chunk);
478
+ for (const row of rows) {
479
+ const node = rowToNode(row);
480
+ out.set(node.id, node);
481
+ this.cacheNode(node);
482
+ }
483
+ }
484
+ return out;
485
+ }
486
+ getExistingNodeIds(ids) {
487
+ const out = new Set();
488
+ if (ids.length === 0)
489
+ return out;
490
+ const uniqueIds = [...new Set(ids)];
491
+ for (let i = 0; i < uniqueIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
492
+ const chunk = uniqueIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
493
+ const placeholders = chunk.map(() => '?').join(',');
494
+ const rows = this.db
495
+ .prepare(`SELECT id FROM nodes WHERE id IN (${placeholders})`)
496
+ .all(...chunk);
497
+ for (const row of rows) {
498
+ out.add(row.id);
499
+ }
500
+ }
501
+ return out;
502
+ }
503
+ /**
504
+ * Add a node to the cache, evicting oldest if needed
505
+ */
506
+ cacheNode(node) {
507
+ if (this.nodeCache.size >= this.maxCacheSize) {
508
+ // Evict oldest (first) entry
509
+ const firstKey = this.nodeCache.keys().next().value;
510
+ if (firstKey) {
511
+ this.nodeCache.delete(firstKey);
512
+ }
513
+ }
514
+ this.nodeCache.set(node.id, node);
515
+ }
516
+ /**
517
+ * Clear the node cache
518
+ */
519
+ clearCache() {
520
+ this.nodeCache.clear();
521
+ }
522
+ /**
523
+ * Get all nodes in a file
524
+ */
525
+ getNodesByFile(filePath) {
526
+ if (!this.stmts.getNodesByFile) {
527
+ this.stmts.getNodesByFile = this.db.prepare('SELECT * FROM nodes WHERE file_path = ? ORDER BY start_line');
528
+ }
529
+ const rows = this.stmts.getNodesByFile.all(filePath);
530
+ return rows.map(rowToNode);
531
+ }
532
+ /**
533
+ * Find the file that holds the densest concentration of the project's
534
+ * internal call graph — the "core" file. Used by context-builder to
535
+ * boost ranking of symbols in that file's directory (so e.g. sinatra
536
+ * queries surface `lib/sinatra/base.rb`'s `route!` instead of
537
+ * `sinatra-contrib/lib/sinatra/multi_route.rb`'s `route` extension).
538
+ *
539
+ * Returns null if no file has a meaningful concentration (e.g. spread
540
+ * evenly across many files, or empty index).
541
+ *
542
+ * "Internal" = source and target are in the same file. Cross-file
543
+ * edges aren't useful here — they don't tell us which file is the
544
+ * functional center.
545
+ *
546
+ * Excludes test/spec files from candidacy via path-pattern. The agent's
547
+ * typical question is "how does X work", not "how is X tested", so
548
+ * boosting a test file's directory would be a misfire.
549
+ */
550
+ getDominantFile() {
551
+ if (!this.stmts.getDominantFile) {
552
+ // Pull top 20 candidates; we then filter out test/generated files
553
+ // in code (regex-grade matching that SQL LIKE can't express). The
554
+ // generated-file filter is critical — without it, etcd's
555
+ // `api/etcdserverpb/rpc.pb.go` (1916 in-file edges, generated
556
+ // protobuf stub) outranks the real `server/etcdserver/server.go`
557
+ // (470 edges) by 4×, and the boost would push the agent toward
558
+ // generated code.
559
+ this.stmts.getDominantFile = this.db.prepare(`
560
+ SELECT n.file_path AS file_path, COUNT(*) AS edge_count
561
+ FROM edges e
562
+ JOIN nodes n ON e.source = n.id
563
+ JOIN nodes m ON e.target = m.id
564
+ WHERE n.file_path = m.file_path
565
+ GROUP BY n.file_path
566
+ ORDER BY edge_count DESC
567
+ LIMIT 20
568
+ `);
569
+ }
570
+ const rows = this.stmts.getDominantFile.all();
571
+ const filtered = rows.filter(r => !isLowValueFile(r.file_path));
572
+ if (filtered.length === 0 || filtered[0].edge_count < 20)
573
+ return null;
574
+ return {
575
+ filePath: filtered[0].file_path,
576
+ edgeCount: filtered[0].edge_count,
577
+ nextEdgeCount: filtered[1]?.edge_count ?? 0,
578
+ };
579
+ }
580
+ /**
581
+ * Find the file that holds the densest concentration of the project's
582
+ * `route` nodes (framework-emitted: Express/Gin/Flask/Rails/Drupal/etc.).
583
+ * Used by handleContext on small repos to inline the project's routing
584
+ * config when the agent's query is about request flow — eliminating the
585
+ * "Glob + Read routes.rb" pattern that beats bhgraph on tiny realworld
586
+ * template repos.
587
+ *
588
+ * Excludes test/generated files from candidacy. Returns null if there
589
+ * are fewer than 3 non-test routes total, or if no file holds at least
590
+ * 30% of them (diffuse routing → no single answer file).
591
+ */
592
+ getTopRouteFile() {
593
+ if (!this.stmts.getTopRouteFile) {
594
+ this.stmts.getTopRouteFile = this.db.prepare(`
595
+ SELECT file_path, COUNT(*) AS cnt
596
+ FROM nodes
597
+ WHERE kind = 'route'
598
+ GROUP BY file_path
599
+ ORDER BY cnt DESC
600
+ LIMIT 20
601
+ `);
602
+ }
603
+ const rows = this.stmts.getTopRouteFile.all();
604
+ const filtered = rows.filter(r => !isLowValueFile(r.file_path));
605
+ if (filtered.length === 0)
606
+ return null;
607
+ const totalRoutes = filtered.reduce((sum, r) => sum + r.cnt, 0);
608
+ const top = filtered[0];
609
+ if (totalRoutes < 3 || top.cnt < 3)
610
+ return null;
611
+ if (top.cnt / totalRoutes < 0.30)
612
+ return null;
613
+ return { filePath: top.file_path, routeCount: top.cnt, totalRoutes };
614
+ }
615
+ /**
616
+ * Build a URL → handler manifest from the index. Each route node's
617
+ * `references` edge points at the function/method that handles the
618
+ * request. We join them in one pass; the agent gets the canonical
619
+ * routing answer ("POST /users/login → AuthController#login") without
620
+ * having to parse the framework's route DSL itself.
621
+ *
622
+ * Also returns the file with the most handler endpoints — used as the
623
+ * "top handler file" to inline source for, so the agent has both the
624
+ * mapping AND the handler implementations.
625
+ */
626
+ getRoutingManifest(limit = 40) {
627
+ if (!this.stmts.getRoutingManifest) {
628
+ // Edge kind varies across framework resolvers: Spring/Rails/
629
+ // Laravel/Drupal emit `references`, Express emits `calls`. Accept
630
+ // both — the semantic is the same (route → its handler).
631
+ this.stmts.getRoutingManifest = this.db.prepare(`
632
+ SELECT
633
+ r.name AS url,
634
+ h.name AS handler,
635
+ h.file_path AS handler_file,
636
+ h.start_line AS handler_line,
637
+ h.kind AS handler_kind
638
+ FROM nodes r
639
+ JOIN edges e ON e.source = r.id
640
+ JOIN nodes h ON e.target = h.id
641
+ WHERE r.kind = 'route'
642
+ AND e.kind IN ('references', 'calls')
643
+ AND h.kind IN ('function', 'method', 'class')
644
+ ORDER BY r.file_path, r.start_line
645
+ LIMIT ?
646
+ `);
647
+ }
648
+ const rows = this.stmts.getRoutingManifest.all(limit);
649
+ // Drop test/generated handlers — same hygiene as elsewhere.
650
+ const filtered = rows.filter(r => !isLowValueFile(r.handler_file));
651
+ if (filtered.length < 3)
652
+ return null;
653
+ // Identify the file holding the most handlers (the "primary handler file").
654
+ const fileCounts = new Map();
655
+ for (const r of filtered) {
656
+ fileCounts.set(r.handler_file, (fileCounts.get(r.handler_file) ?? 0) + 1);
657
+ }
658
+ let topHandlerFile = null;
659
+ let topHandlerFileCount = 0;
660
+ for (const [file, count] of fileCounts) {
661
+ if (count > topHandlerFileCount) {
662
+ topHandlerFile = file;
663
+ topHandlerFileCount = count;
664
+ }
665
+ }
666
+ return {
667
+ entries: filtered.map(r => ({
668
+ url: r.url,
669
+ handler: r.handler,
670
+ handlerFile: r.handler_file,
671
+ handlerLine: r.handler_line,
672
+ handlerKind: r.handler_kind,
673
+ })),
674
+ topHandlerFile,
675
+ topHandlerFileCount,
676
+ totalRoutes: filtered.length,
677
+ };
678
+ }
679
+ /**
680
+ * Get all nodes of a specific kind
681
+ */
682
+ getNodesByKind(kind) {
683
+ if (!this.stmts.getNodesByKind) {
684
+ this.stmts.getNodesByKind = this.db.prepare('SELECT * FROM nodes WHERE kind = ?');
685
+ }
686
+ const rows = this.stmts.getNodesByKind.all(kind);
687
+ return rows.map(rowToNode);
688
+ }
689
+ /**
690
+ * Stream every node of a kind one at a time (lazy) instead of materializing
691
+ * them all like {@link getNodesByKind}. For unbounded kinds (`function`,
692
+ * `method`) on a symbol-dense project the full array is gigabytes; the
693
+ * dynamic-edge synthesizers only scan-and-filter, so they iterate to keep
694
+ * memory O(1) in the node count rather than O(nodes) (#610).
695
+ */
696
+ *iterateNodesByKind(kind) {
697
+ // Fresh statement per call (not a cached one): an iterator holds an open
698
+ // cursor, so a shared statement would conflict across overlapping scans.
699
+ const stmt = this.db.prepare('SELECT * FROM nodes WHERE kind = ?');
700
+ for (const row of stmt.iterate(kind)) {
701
+ yield rowToNode(row);
702
+ }
703
+ }
704
+ /**
705
+ * Get all nodes in the database
706
+ */
707
+ getAllNodes() {
708
+ const rows = this.db.prepare('SELECT * FROM nodes').all();
709
+ return rows.map(rowToNode);
710
+ }
711
+ /**
712
+ * Get nodes by exact name match (uses idx_nodes_name index)
713
+ */
714
+ getNodesByName(name) {
715
+ if (!this.stmts.getNodesByName) {
716
+ this.stmts.getNodesByName = this.db.prepare('SELECT * FROM nodes WHERE name = ?');
717
+ }
718
+ const rows = this.stmts.getNodesByName.all(name);
719
+ return rows.map(rowToNode);
720
+ }
721
+ /**
722
+ * Nodes whose name starts with `prefix`, by index range scan (a LIKE would
723
+ * skip idx_nodes_name under SQLite's default case-insensitive LIKE).
724
+ */
725
+ getNodesByNamePrefix(prefix, limit = 20) {
726
+ if (!this.stmts.getNodesByNamePrefix) {
727
+ this.stmts.getNodesByNamePrefix = this.db.prepare('SELECT * FROM nodes WHERE name >= ? AND name < ? ORDER BY name LIMIT ?');
728
+ }
729
+ const rows = this.stmts.getNodesByNamePrefix.all(prefix, prefix + '￿', limit);
730
+ return rows.map(rowToNode);
731
+ }
732
+ /**
733
+ * Get nodes by exact qualified name match (uses idx_nodes_qualified_name index)
734
+ */
735
+ getNodesByQualifiedNameExact(qualifiedName) {
736
+ if (!this.stmts.getNodesByQualifiedNameExact) {
737
+ this.stmts.getNodesByQualifiedNameExact = this.db.prepare('SELECT * FROM nodes WHERE qualified_name = ?');
738
+ }
739
+ const rows = this.stmts.getNodesByQualifiedNameExact.all(qualifiedName);
740
+ return rows.map(rowToNode);
741
+ }
742
+ /**
743
+ * Get nodes by lowercase name match (uses idx_nodes_lower_name expression index)
744
+ */
745
+ getNodesByLowerName(lowerName) {
746
+ if (!this.stmts.getNodesByLowerName) {
747
+ this.stmts.getNodesByLowerName = this.db.prepare('SELECT * FROM nodes WHERE lower(name) = ?');
748
+ }
749
+ const rows = this.stmts.getNodesByLowerName.all(lowerName);
750
+ return rows.map(rowToNode);
751
+ }
752
+ /**
753
+ * Search nodes by name using FTS with fallback to LIKE for better matching
754
+ *
755
+ * Search strategy:
756
+ * 1. Try FTS5 prefix match (query*) for word-start matching
757
+ * 2. If no results, try LIKE for substring matching (e.g., "signIn" finds "signInWithGoogle")
758
+ * 3. Score results based on match quality
759
+ */
760
+ searchNodes(query, options = {}) {
761
+ const { limit = 100, offset = 0 } = options;
762
+ // Parse field-qualified bits out of the raw query (kind:, lang:,
763
+ // path:, name:). Anything not recognised stays in `text` and goes
764
+ // to FTS unchanged. Filters compose with the SearchOptions arg —
765
+ // both are applied (intersection-style).
766
+ const parsed = (0, query_parser_1.parseQuery)(query);
767
+ const mergedKinds = parsed.kinds.length > 0
768
+ ? Array.from(new Set([...(options.kinds ?? []), ...parsed.kinds]))
769
+ : options.kinds;
770
+ const mergedLanguages = parsed.languages.length > 0
771
+ ? Array.from(new Set([...(options.languages ?? []), ...parsed.languages]))
772
+ : options.languages;
773
+ const pathFilters = parsed.pathFilters;
774
+ const nameFilters = parsed.nameFilters;
775
+ // The text portion drives FTS/LIKE; if all the user typed was
776
+ // filters (`kind:function`), we still need *some* candidate set,
777
+ // so synthesise an empty-text path that returns everything matching
778
+ // the filters.
779
+ const text = parsed.text;
780
+ const kinds = mergedKinds;
781
+ const languages = mergedLanguages;
782
+ // First try FTS5 with prefix matching
783
+ let results = text
784
+ ? this.searchNodesFTS(text, { kinds, languages, limit, offset })
785
+ // Over-fetch by 5× when running filter-only (no text). The
786
+ // post-scoring path: + name: filters can be very selective, so
787
+ // a smaller multiplier risks returning fewer than `limit`
788
+ // results despite the DB having plenty of matches.
789
+ : this.searchAllByFilters({ kinds, languages, limit: limit * 5 });
790
+ // If no FTS results, try LIKE-based substring search
791
+ if (results.length === 0 && text.length >= 2) {
792
+ results = this.searchNodesLike(text, { kinds, languages, limit, offset });
793
+ }
794
+ // Final fuzzy fallback: scan all known names and keep those within
795
+ // a tight Levenshtein distance. Only fires when both FTS and LIKE
796
+ // returned nothing AND there's a text portion long enough to be
797
+ // worth fuzzing (1-char queries would match too much).
798
+ if (results.length === 0 && text.length >= 3) {
799
+ results = this.searchNodesFuzzy(text, { kinds, languages, limit });
800
+ }
801
+ // Supplement: ensure exact name matches are always candidates.
802
+ // BM25 can bury short exact-match names (e.g. "getBean") under hundreds of
803
+ // compound names (e.g. "getBeanDescriptor") in large codebases,
804
+ // pushing them past the FTS fetch limit before post-hoc scoring can help.
805
+ // Use the max BM25 score as the base so the nameMatchBonus (exact=30 vs
806
+ // prefix=20) actually differentiates them after rescoring.
807
+ if (results.length > 0 && query) {
808
+ const existingIds = new Set(results.map(r => r.node.id));
809
+ const maxFtsScore = Math.max(...results.map(r => r.score));
810
+ const terms = query.split(/\s+/).filter(t => t.length >= 2);
811
+ for (const term of terms) {
812
+ let sql = 'SELECT * FROM nodes WHERE name = ? COLLATE NOCASE';
813
+ const params = [term];
814
+ if (kinds && kinds.length > 0) {
815
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
816
+ params.push(...kinds);
817
+ }
818
+ if (languages && languages.length > 0) {
819
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
820
+ params.push(...languages);
821
+ }
822
+ sql += ' LIMIT 20';
823
+ const rows = this.db.prepare(sql).all(...params);
824
+ for (const row of rows) {
825
+ if (!existingIds.has(row.id)) {
826
+ results.push({ node: rowToNode(row), score: maxFtsScore });
827
+ existingIds.add(row.id);
828
+ }
829
+ }
830
+ }
831
+ }
832
+ // Apply multi-signal scoring
833
+ if (results.length > 0 && (text || query)) {
834
+ const scoringQuery = text || query;
835
+ results = results.map(r => ({
836
+ ...r,
837
+ score: r.score
838
+ + (0, query_utils_1.kindBonus)(r.node.kind)
839
+ + (0, query_utils_1.scorePathRelevance)(r.node.filePath, scoringQuery, this.projectNameTokens)
840
+ + (0, query_utils_1.nameMatchBonus)(r.node.name, scoringQuery),
841
+ }));
842
+ results.sort((a, b) => b.score - a.score);
843
+ // Trim to requested limit after rescoring
844
+ if (results.length > limit) {
845
+ results = results.slice(0, limit);
846
+ }
847
+ }
848
+ // Apply path: + name: filters AFTER scoring. Scoring already uses
849
+ // path/name as a soft signal; the explicit filters here are a hard
850
+ // gate. Done last so the FTS limit fetched plenty of candidates to
851
+ // narrow from.
852
+ if (pathFilters.length > 0) {
853
+ const lowered = pathFilters.map((p) => p.toLowerCase());
854
+ results = results.filter((r) => {
855
+ const fp = r.node.filePath.toLowerCase();
856
+ return lowered.some((p) => fp.includes(p));
857
+ });
858
+ }
859
+ if (nameFilters.length > 0) {
860
+ const lowered = nameFilters.map((n) => n.toLowerCase());
861
+ results = results.filter((r) => {
862
+ const nm = r.node.name.toLowerCase();
863
+ return lowered.some((n) => nm.includes(n));
864
+ });
865
+ }
866
+ return results;
867
+ }
868
+ /**
869
+ * Match-everything path used when the user supplied only field
870
+ * filters (`kind:function lang:typescript`) with no text. Returns
871
+ * candidates ordered by name; the caller's filter pass narrows to
872
+ * what was asked for.
873
+ */
874
+ searchAllByFilters(options) {
875
+ const { kinds, languages, limit } = options;
876
+ let sql = 'SELECT * FROM nodes WHERE 1=1';
877
+ const params = [];
878
+ if (kinds && kinds.length > 0) {
879
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
880
+ params.push(...kinds);
881
+ }
882
+ if (languages && languages.length > 0) {
883
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
884
+ params.push(...languages);
885
+ }
886
+ sql += ' ORDER BY name LIMIT ?';
887
+ params.push(limit);
888
+ const rows = this.db.prepare(sql).all(...params);
889
+ return rows.map((row) => ({ node: rowToNode(row), score: 1 }));
890
+ }
891
+ /**
892
+ * Fuzzy fallback: when zero FTS/LIKE hits, try an edit-distance
893
+ * sweep over the distinct symbol-name set. Caps `maxDist` at 2 so
894
+ * `getUssr` finds `getUser` but `process` doesn't match `prosody`.
895
+ * Bounded edit distance keeps each comparison cheap; the per-query
896
+ * scan is O(distinct-name-count) which is far smaller than total
897
+ * node count on any real codebase.
898
+ */
899
+ searchNodesFuzzy(text, options) {
900
+ const { kinds, languages, limit } = options;
901
+ const lowered = text.toLowerCase();
902
+ const maxDist = lowered.length <= 4 ? 1 : 2;
903
+ // Pull the distinct name list once. The set is cached on QueryBuilder
904
+ // by getAllNodeNames(); even on a 200k-node project the distinct
905
+ // name set is typically O(10k) because most names repeat. The
906
+ // candidate-cap below bounds memory regardless.
907
+ const allNames = this.getAllNodeNames();
908
+ const candidates = [];
909
+ for (const name of allNames) {
910
+ const dist = (0, query_parser_1.boundedEditDistance)(name.toLowerCase(), lowered, maxDist);
911
+ if (dist <= maxDist)
912
+ candidates.push({ name, dist });
913
+ }
914
+ candidates.sort((a, b) => a.dist - b.dist);
915
+ // Cap the per-name follow-up queries. Each survivor triggers a
916
+ // separate `SELECT * FROM nodes WHERE name = ?`; without this cap
917
+ // a project with many similar names (`getUser1`, `getUser2`...)
918
+ // could fan out far beyond `limit` queries before the inner-loop
919
+ // limit kicks in.
920
+ const FUZZY_FOLLOWUP_CAP = Math.max(limit * 2, 50);
921
+ const cappedCandidates = candidates.slice(0, FUZZY_FOLLOWUP_CAP);
922
+ const results = [];
923
+ const seen = new Set();
924
+ for (const c of cappedCandidates) {
925
+ if (results.length >= limit)
926
+ break;
927
+ let sql = 'SELECT * FROM nodes WHERE name = ?';
928
+ const params = [c.name];
929
+ if (kinds && kinds.length > 0) {
930
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
931
+ params.push(...kinds);
932
+ }
933
+ if (languages && languages.length > 0) {
934
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
935
+ params.push(...languages);
936
+ }
937
+ sql += ' LIMIT 5';
938
+ const rows = this.db.prepare(sql).all(...params);
939
+ for (const row of rows) {
940
+ if (seen.has(row.id))
941
+ continue;
942
+ seen.add(row.id);
943
+ // Lower the score for each edit step away from the query so
944
+ // exact-match fallbacks (dist 0) outrank dist-2 typos.
945
+ results.push({ node: rowToNode(row), score: 1 / (1 + c.dist) });
946
+ if (results.length >= limit)
947
+ break;
948
+ }
949
+ }
950
+ return results;
951
+ }
952
+ /**
953
+ * FTS5 search with prefix matching
954
+ */
955
+ searchNodesFTS(query, options) {
956
+ const { kinds, languages, limit = 100, offset = 0 } = options;
957
+ // Add prefix wildcard for better matching (e.g., "auth" matches "AuthService", "authenticate")
958
+ // Escape special FTS5 characters and add prefix wildcard.
959
+ //
960
+ // `::` is a qualifier separator in Rust/C++/Ruby, not a token char,
961
+ // so treat it as whitespace before the strip step. Otherwise queries
962
+ // like `stage_apply::run` collapse to `stage_applyrun` (the colons
963
+ // are stripped without splitting) and find nothing. See #173.
964
+ const ftsQuery = query
965
+ .replace(/::/g, ' ') // Rust/C++/Ruby qualifier separator
966
+ .replace(/['"*():^]/g, '') // Remove FTS5 special chars
967
+ .split(/\s+/)
968
+ .filter(term => term.length > 0)
969
+ // Strip FTS5 boolean operators to prevent query manipulation
970
+ .filter(term => !/^(AND|OR|NOT|NEAR)$/i.test(term))
971
+ .map(term => `"${term}"*`) // Prefix match each term
972
+ .join(' OR ');
973
+ if (!ftsQuery) {
974
+ return [];
975
+ }
976
+ // BM25 column weights: id=0, name=20, qualified_name=5, docstring=1, signature=2
977
+ // Heavy name weight ensures exact/prefix name matches rank above incidental
978
+ // mentions in long docstrings or qualified names of nested symbols.
979
+ // Fetch 5x requested limit so post-hoc rescoring (kindBonus, pathRelevance,
980
+ // nameMatchBonus) can promote results that BM25 alone undervalues.
981
+ const ftsLimit = Math.max(limit * 5, 100);
982
+ let sql = `
983
+ SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
984
+ FROM nodes_fts
985
+ JOIN nodes ON nodes_fts.id = nodes.id
986
+ WHERE nodes_fts MATCH ?
987
+ `;
988
+ const params = [ftsQuery];
989
+ if (kinds && kinds.length > 0) {
990
+ sql += ` AND nodes.kind IN (${kinds.map(() => '?').join(',')})`;
991
+ params.push(...kinds);
992
+ }
993
+ if (languages && languages.length > 0) {
994
+ sql += ` AND nodes.language IN (${languages.map(() => '?').join(',')})`;
995
+ params.push(...languages);
996
+ }
997
+ sql += ' ORDER BY score LIMIT ? OFFSET ?';
998
+ params.push(ftsLimit, offset);
999
+ try {
1000
+ const rows = this.db.prepare(sql).all(...params);
1001
+ return rows.map((row) => ({
1002
+ node: rowToNode(row),
1003
+ score: Math.abs(row.score), // bm25 returns negative scores
1004
+ }));
1005
+ }
1006
+ catch {
1007
+ // FTS query failed, return empty
1008
+ return [];
1009
+ }
1010
+ }
1011
+ /**
1012
+ * LIKE-based substring search for cases where FTS doesn't match
1013
+ * Useful for camelCase matching (e.g., "signIn" finds "signInWithGoogle")
1014
+ */
1015
+ searchNodesLike(query, options) {
1016
+ const { kinds, languages, limit = 100, offset = 0 } = options;
1017
+ let sql = `
1018
+ SELECT nodes.*,
1019
+ CASE
1020
+ WHEN name = ? THEN 1.0
1021
+ WHEN name LIKE ? THEN 0.9
1022
+ WHEN name LIKE ? THEN 0.8
1023
+ WHEN qualified_name LIKE ? THEN 0.7
1024
+ ELSE 0.5
1025
+ END as score
1026
+ FROM nodes
1027
+ WHERE (
1028
+ name LIKE ? OR
1029
+ qualified_name LIKE ? OR
1030
+ name LIKE ?
1031
+ )
1032
+ `;
1033
+ // Pattern variants for better matching
1034
+ const exactMatch = query;
1035
+ const startsWith = `${query}%`;
1036
+ const contains = `%${query}%`;
1037
+ const params = [
1038
+ exactMatch, // Exact match score
1039
+ startsWith, // Starts with score
1040
+ contains, // Contains score
1041
+ contains, // Qualified name score
1042
+ contains, // WHERE: name contains
1043
+ contains, // WHERE: qualified_name contains
1044
+ startsWith, // WHERE: name starts with
1045
+ ];
1046
+ if (kinds && kinds.length > 0) {
1047
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1048
+ params.push(...kinds);
1049
+ }
1050
+ if (languages && languages.length > 0) {
1051
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
1052
+ params.push(...languages);
1053
+ }
1054
+ sql += ' ORDER BY score DESC, length(name) ASC LIMIT ? OFFSET ?';
1055
+ params.push(limit, offset);
1056
+ const rows = this.db.prepare(sql).all(...params);
1057
+ return rows.map((row) => ({
1058
+ node: rowToNode(row),
1059
+ score: row.score,
1060
+ }));
1061
+ }
1062
+ /**
1063
+ * Find nodes by exact name match
1064
+ *
1065
+ * Used for hybrid search - looks up symbols by exact name or case-insensitive match.
1066
+ * Returns high-confidence matches for known symbol names extracted from query.
1067
+ *
1068
+ * @param names - Array of symbol names to look up
1069
+ * @param options - Search options (kinds, languages, limit)
1070
+ * @returns SearchResult array with exact matches scored at 1.0
1071
+ */
1072
+ findNodesByExactName(names, options = {}) {
1073
+ if (names.length === 0)
1074
+ return [];
1075
+ const { kinds, languages, limit = 50 } = options;
1076
+ // Two-pass approach to handle common names (e.g., "run" has 40+ matches):
1077
+ // Pass 1: Find which files contain distinctive (rare) symbols from the query.
1078
+ // Pass 2: Query each name, boosting results that co-locate with distinctive symbols.
1079
+ // Pass 1: Find files containing each queried name, identify distinctive names
1080
+ const nameToFiles = new Map();
1081
+ for (const name of names) {
1082
+ let sql = 'SELECT DISTINCT file_path FROM nodes WHERE name COLLATE NOCASE = ?';
1083
+ const params = [name];
1084
+ if (kinds && kinds.length > 0) {
1085
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1086
+ params.push(...kinds);
1087
+ }
1088
+ sql += ' LIMIT 100';
1089
+ const rows = this.db.prepare(sql).all(...params);
1090
+ nameToFiles.set(name.toLowerCase(), new Set(rows.map(r => r.file_path)));
1091
+ }
1092
+ // Distinctive names are those with fewer than 10 file matches (e.g., "scrapeLoop" = 1 file)
1093
+ const distinctiveFiles = new Set();
1094
+ for (const [, files] of nameToFiles) {
1095
+ if (files.size > 0 && files.size < 10) {
1096
+ for (const f of files)
1097
+ distinctiveFiles.add(f);
1098
+ }
1099
+ }
1100
+ // Pass 2: Query each name with per-name limit, scoring by co-location
1101
+ const perNameLimit = Math.max(8, Math.ceil(limit / names.length));
1102
+ const allResults = [];
1103
+ const seenIds = new Set();
1104
+ for (const name of names) {
1105
+ let sql = `
1106
+ SELECT nodes.*, 1.0 as score
1107
+ FROM nodes
1108
+ WHERE name COLLATE NOCASE = ?
1109
+ `;
1110
+ const params = [name];
1111
+ if (kinds && kinds.length > 0) {
1112
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1113
+ params.push(...kinds);
1114
+ }
1115
+ if (languages && languages.length > 0) {
1116
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
1117
+ params.push(...languages);
1118
+ }
1119
+ // Fetch enough to find co-located results among common names
1120
+ sql += ' LIMIT ?';
1121
+ params.push(Math.max(perNameLimit * 3, 50));
1122
+ const rows = this.db.prepare(sql).all(...params);
1123
+ const nameResults = [];
1124
+ for (const row of rows) {
1125
+ const node = rowToNode(row);
1126
+ if (seenIds.has(node.id))
1127
+ continue;
1128
+ // Boost results in files that also contain distinctive symbols
1129
+ const coLocationBoost = distinctiveFiles.has(node.filePath) ? 20 : 0;
1130
+ nameResults.push({ node, score: row.score + coLocationBoost });
1131
+ }
1132
+ // Sort by score (co-located first), take per-name limit
1133
+ nameResults.sort((a, b) => b.score - a.score);
1134
+ for (const r of nameResults.slice(0, perNameLimit)) {
1135
+ seenIds.add(r.node.id);
1136
+ allResults.push(r);
1137
+ }
1138
+ }
1139
+ // Sort all results by score so co-located results bubble up
1140
+ allResults.sort((a, b) => b.score - a.score);
1141
+ return allResults.slice(0, limit);
1142
+ }
1143
+ /**
1144
+ * Find nodes whose name contains a substring (LIKE-based).
1145
+ * Useful for CamelCase-part matching where FTS fails because
1146
+ * e.g. "TransportSearchAction" is one FTS token, not matchable by "Search"*.
1147
+ *
1148
+ * Results are ordered by name length (shorter = more likely to be the core type).
1149
+ */
1150
+ findNodesByNameSubstring(substring, options = {}) {
1151
+ const { kinds, languages, limit = 30, excludePrefix } = options;
1152
+ let sql = `
1153
+ SELECT nodes.*, 1.0 as score
1154
+ FROM nodes
1155
+ WHERE name LIKE ?
1156
+ `;
1157
+ const params = [`%${substring}%`];
1158
+ // Exclude prefix matches (handled by FTS-based prefix search in Step 2b)
1159
+ if (excludePrefix) {
1160
+ sql += ` AND name NOT LIKE ?`;
1161
+ params.push(`${substring}%`);
1162
+ }
1163
+ if (kinds && kinds.length > 0) {
1164
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1165
+ params.push(...kinds);
1166
+ }
1167
+ if (languages && languages.length > 0) {
1168
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
1169
+ params.push(...languages);
1170
+ }
1171
+ sql += ' ORDER BY length(name) ASC LIMIT ?';
1172
+ params.push(limit);
1173
+ const rows = this.db.prepare(sql).all(...params);
1174
+ return rows.map((row) => ({
1175
+ node: rowToNode(row),
1176
+ score: row.score,
1177
+ }));
1178
+ }
1179
+ // ===========================================================================
1180
+ // Edge Operations
1181
+ // ===========================================================================
1182
+ /**
1183
+ * Insert a new edge
1184
+ */
1185
+ insertEdge(edge) {
1186
+ if (!this.stmts.insertEdge) {
1187
+ this.stmts.insertEdge = this.db.prepare(`
1188
+ INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
1189
+ VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
1190
+ `);
1191
+ }
1192
+ this.stmts.insertEdge.run({
1193
+ source: edge.source,
1194
+ target: edge.target,
1195
+ kind: edge.kind,
1196
+ metadata: edge.metadata ? JSON.stringify(edge.metadata) : null,
1197
+ line: edge.line ?? null,
1198
+ col: edge.column ?? null,
1199
+ provenance: edge.provenance ?? null,
1200
+ });
1201
+ }
1202
+ /**
1203
+ * Insert multiple edges in a transaction
1204
+ */
1205
+ insertEdges(edges) {
1206
+ if (edges.length === 0)
1207
+ return;
1208
+ this.db.transaction(() => {
1209
+ const endpointIds = new Set();
1210
+ for (const edge of edges) {
1211
+ endpointIds.add(edge.source);
1212
+ endpointIds.add(edge.target);
1213
+ }
1214
+ const existingNodeIds = this.getExistingNodeIds([...endpointIds]);
1215
+ for (const edge of edges) {
1216
+ if (!existingNodeIds.has(edge.source) || !existingNodeIds.has(edge.target)) {
1217
+ continue;
1218
+ }
1219
+ this.insertEdge(edge);
1220
+ }
1221
+ })();
1222
+ }
1223
+ /**
1224
+ * Delete all edges from a source node
1225
+ */
1226
+ deleteEdgesBySource(sourceId) {
1227
+ if (!this.stmts.deleteEdgesBySource) {
1228
+ this.stmts.deleteEdgesBySource = this.db.prepare('DELETE FROM edges WHERE source = ?');
1229
+ }
1230
+ this.stmts.deleteEdgesBySource.run(sourceId);
1231
+ }
1232
+ /**
1233
+ * Get outgoing edges from a node
1234
+ */
1235
+ getOutgoingEdges(sourceId, kinds, provenance) {
1236
+ if ((kinds && kinds.length > 0) || provenance) {
1237
+ let sql = 'SELECT * FROM edges WHERE source = ?';
1238
+ const params = [sourceId];
1239
+ if (kinds && kinds.length > 0) {
1240
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1241
+ params.push(...kinds);
1242
+ }
1243
+ if (provenance) {
1244
+ sql += ' AND provenance = ?';
1245
+ params.push(provenance);
1246
+ }
1247
+ const rows = this.db.prepare(sql).all(...params);
1248
+ return rows.map(rowToEdge);
1249
+ }
1250
+ if (!this.stmts.getEdgesBySource) {
1251
+ this.stmts.getEdgesBySource = this.db.prepare('SELECT * FROM edges WHERE source = ?');
1252
+ }
1253
+ const rows = this.stmts.getEdgesBySource.all(sourceId);
1254
+ return rows.map(rowToEdge);
1255
+ }
1256
+ /**
1257
+ * Get incoming edges to a node
1258
+ */
1259
+ getIncomingEdges(targetId, kinds) {
1260
+ if (kinds && kinds.length > 0) {
1261
+ const sql = `SELECT * FROM edges WHERE target = ? AND kind IN (${kinds.map(() => '?').join(',')})`;
1262
+ const rows = this.db.prepare(sql).all(targetId, ...kinds);
1263
+ return rows.map(rowToEdge);
1264
+ }
1265
+ if (!this.stmts.getEdgesByTarget) {
1266
+ this.stmts.getEdgesByTarget = this.db.prepare('SELECT * FROM edges WHERE target = ?');
1267
+ }
1268
+ const rows = this.stmts.getEdgesByTarget.all(targetId);
1269
+ return rows.map(rowToEdge);
1270
+ }
1271
+ /**
1272
+ * Find all edges where both source and target are in the given node set.
1273
+ * Useful for recovering inter-node connectivity after BFS.
1274
+ */
1275
+ findEdgesBetweenNodes(nodeIds, kinds) {
1276
+ if (nodeIds.length === 0)
1277
+ return [];
1278
+ const idsJson = JSON.stringify(nodeIds);
1279
+ let sql = `SELECT * FROM edges WHERE source IN (SELECT value FROM json_each(?)) AND target IN (SELECT value FROM json_each(?))`;
1280
+ const params = [idsJson, idsJson];
1281
+ if (kinds && kinds.length > 0) {
1282
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1283
+ params.push(...kinds);
1284
+ }
1285
+ const rows = this.db.prepare(sql).all(...params);
1286
+ return rows.map(rowToEdge);
1287
+ }
1288
+ /**
1289
+ * Distinct file paths that DEPEND ON `filePath`: every file containing a
1290
+ * symbol with a cross-file edge (any kind except `contains`) into a symbol
1291
+ * of this file. This is the file-level projection of the symbol dependency
1292
+ * graph and the basis for blast-radius / `affected` test selection.
1293
+ *
1294
+ * It deliberately does NOT restrict to `imports` edges. In this graph an
1295
+ * `imports` edge connects a file to its own local import declarations
1296
+ * (it is always same-file), so an imports-only lookup returns zero
1297
+ * cross-file dependents for every file. The real cross-file dependency
1298
+ * signal is the resolved call/reference graph — calls, references,
1299
+ * instantiates, extends, implements, overrides, type_of, returns,
1300
+ * decorates — exactly what {@link GraphTraverser.getImpactRadius} traverses.
1301
+ * `contains` is excluded: a parent containing a symbol does not *depend* on
1302
+ * it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
1303
+ */
1304
+ getDependentFilePaths(filePath) {
1305
+ const sql = `SELECT DISTINCT src.file_path AS fp
1306
+ FROM edges e
1307
+ JOIN nodes tgt ON tgt.id = e.target
1308
+ JOIN nodes src ON src.id = e.source
1309
+ WHERE tgt.file_path = ?
1310
+ AND e.kind != 'contains'
1311
+ AND src.file_path != ?`;
1312
+ const rows = this.db.prepare(sql).all(filePath, filePath);
1313
+ return rows.map((r) => r.fp);
1314
+ }
1315
+ /**
1316
+ * Distinct file paths that `filePath` DEPENDS ON — the inverse of
1317
+ * {@link getDependentFilePaths}: every file containing a symbol that a
1318
+ * symbol of this file has a cross-file edge into. Same edge-kind rules
1319
+ * (all kinds except `contains`); same reason imports-only is insufficient.
1320
+ */
1321
+ getDependencyFilePaths(filePath) {
1322
+ const sql = `SELECT DISTINCT tgt.file_path AS fp
1323
+ FROM edges e
1324
+ JOIN nodes src ON src.id = e.source
1325
+ JOIN nodes tgt ON tgt.id = e.target
1326
+ WHERE src.file_path = ?
1327
+ AND e.kind != 'contains'
1328
+ AND tgt.file_path != ?`;
1329
+ const rows = this.db.prepare(sql).all(filePath, filePath);
1330
+ return rows.map((r) => r.fp);
1331
+ }
1332
+ /**
1333
+ * Cross-file edges whose TARGET is a node in `filePath` and whose SOURCE is a
1334
+ * node in a *different* file, paired with the target node's (name, kind) so a
1335
+ * caller can re-resolve the edge to the re-indexed target's new ID (node IDs
1336
+ * are `sha256(filePath:kind:name:line)`, so any line shift in the callee file
1337
+ * changes target IDs and a naive re-insert by old ID silently drops them).
1338
+ * Used by `storeExtractionResult` to preserve incoming edges across a file
1339
+ * re-index (issue #899). Same edge-kind rules as
1340
+ * {@link getDependentFilePaths}: all kinds except `contains`.
1341
+ */
1342
+ getCrossFileIncomingEdgesWithTarget(filePath) {
1343
+ const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind
1344
+ FROM edges e
1345
+ JOIN nodes tgt ON tgt.id = e.target
1346
+ JOIN nodes src ON src.id = e.source
1347
+ WHERE tgt.file_path = ?
1348
+ AND e.kind != 'contains'
1349
+ AND src.file_path != ?`;
1350
+ const rows = this.db.prepare(sql).all(filePath, filePath);
1351
+ return rows.map(row => ({
1352
+ ...rowToEdge(row),
1353
+ targetName: row.target_name,
1354
+ targetKind: row.target_kind,
1355
+ }));
1356
+ }
1357
+ // ===========================================================================
1358
+ // File Operations
1359
+ // ===========================================================================
1360
+ /**
1361
+ * Insert or update a file record
1362
+ */
1363
+ upsertFile(file) {
1364
+ if (!this.stmts.upsertFile) {
1365
+ this.stmts.upsertFile = this.db.prepare(`
1366
+ INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors)
1367
+ VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors)
1368
+ ON CONFLICT(path) DO UPDATE SET
1369
+ content_hash = @contentHash,
1370
+ language = @language,
1371
+ size = @size,
1372
+ modified_at = @modifiedAt,
1373
+ indexed_at = @indexedAt,
1374
+ node_count = @nodeCount,
1375
+ errors = @errors
1376
+ `);
1377
+ }
1378
+ this.stmts.upsertFile.run({
1379
+ path: file.path,
1380
+ contentHash: file.contentHash,
1381
+ language: file.language,
1382
+ size: file.size,
1383
+ modifiedAt: file.modifiedAt,
1384
+ indexedAt: file.indexedAt,
1385
+ nodeCount: file.nodeCount,
1386
+ errors: file.errors ? JSON.stringify(file.errors) : null,
1387
+ });
1388
+ }
1389
+ /**
1390
+ * Delete a file record and its nodes
1391
+ */
1392
+ deleteFile(filePath) {
1393
+ this.db.transaction(() => {
1394
+ this.deleteNodesByFile(filePath);
1395
+ if (!this.stmts.deleteFile) {
1396
+ this.stmts.deleteFile = this.db.prepare('DELETE FROM files WHERE path = ?');
1397
+ }
1398
+ this.stmts.deleteFile.run(filePath);
1399
+ })();
1400
+ }
1401
+ /**
1402
+ * Get a file record by path
1403
+ */
1404
+ getFileByPath(filePath) {
1405
+ if (!this.stmts.getFileByPath) {
1406
+ this.stmts.getFileByPath = this.db.prepare('SELECT * FROM files WHERE path = ?');
1407
+ }
1408
+ const row = this.stmts.getFileByPath.get(filePath);
1409
+ return row ? rowToFileRecord(row) : null;
1410
+ }
1411
+ /**
1412
+ * Get all tracked files
1413
+ */
1414
+ getAllFiles() {
1415
+ if (!this.stmts.getAllFiles) {
1416
+ this.stmts.getAllFiles = this.db.prepare('SELECT * FROM files ORDER BY path');
1417
+ }
1418
+ const rows = this.stmts.getAllFiles.all();
1419
+ return rows.map(rowToFileRecord);
1420
+ }
1421
+ /**
1422
+ * Most recent index timestamp (ms since epoch) across all tracked files, or
1423
+ * null when nothing is indexed yet. One indexed aggregate, no per-row scan. (#329)
1424
+ */
1425
+ getLastIndexedAt() {
1426
+ const row = this.db
1427
+ .prepare('SELECT MAX(indexed_at) AS last FROM files')
1428
+ .get();
1429
+ return row?.last ?? null;
1430
+ }
1431
+ /**
1432
+ * Get files that need re-indexing (hash changed)
1433
+ */
1434
+ getStaleFiles(currentHashes) {
1435
+ const files = this.getAllFiles();
1436
+ return files.filter((f) => {
1437
+ const currentHash = currentHashes.get(f.path);
1438
+ return currentHash && currentHash !== f.contentHash;
1439
+ });
1440
+ }
1441
+ // ===========================================================================
1442
+ // Unresolved References
1443
+ // ===========================================================================
1444
+ /**
1445
+ * Insert an unresolved reference
1446
+ */
1447
+ insertUnresolvedRef(ref) {
1448
+ if (!this.stmts.insertUnresolved) {
1449
+ this.stmts.insertUnresolved = this.db.prepare(`
1450
+ INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
1451
+ VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
1452
+ `);
1453
+ }
1454
+ this.stmts.insertUnresolved.run({
1455
+ fromNodeId: ref.fromNodeId,
1456
+ referenceName: ref.referenceName,
1457
+ referenceKind: ref.referenceKind,
1458
+ line: ref.line,
1459
+ col: ref.column,
1460
+ candidates: ref.candidates ? JSON.stringify(ref.candidates) : null,
1461
+ filePath: ref.filePath ?? '',
1462
+ language: ref.language ?? 'unknown',
1463
+ });
1464
+ }
1465
+ /**
1466
+ * Insert multiple unresolved references in a transaction
1467
+ */
1468
+ insertUnresolvedRefsBatch(refs) {
1469
+ if (refs.length === 0)
1470
+ return;
1471
+ const insert = this.db.transaction(() => {
1472
+ for (const ref of refs) {
1473
+ this.insertUnresolvedRef(ref);
1474
+ }
1475
+ });
1476
+ insert();
1477
+ }
1478
+ /**
1479
+ * Delete unresolved references from a node
1480
+ */
1481
+ deleteUnresolvedByNode(nodeId) {
1482
+ if (!this.stmts.deleteUnresolvedByNode) {
1483
+ this.stmts.deleteUnresolvedByNode = this.db.prepare('DELETE FROM unresolved_refs WHERE from_node_id = ?');
1484
+ }
1485
+ this.stmts.deleteUnresolvedByNode.run(nodeId);
1486
+ }
1487
+ /**
1488
+ * Get unresolved references by name (for resolution)
1489
+ */
1490
+ getUnresolvedByName(name) {
1491
+ if (!this.stmts.getUnresolvedByName) {
1492
+ this.stmts.getUnresolvedByName = this.db.prepare('SELECT * FROM unresolved_refs WHERE reference_name = ?');
1493
+ }
1494
+ const rows = this.stmts.getUnresolvedByName.all(name);
1495
+ return rows.map((row) => ({
1496
+ fromNodeId: row.from_node_id,
1497
+ referenceName: row.reference_name,
1498
+ referenceKind: row.reference_kind,
1499
+ line: row.line,
1500
+ column: row.col,
1501
+ candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1502
+ filePath: row.file_path,
1503
+ language: row.language,
1504
+ }));
1505
+ }
1506
+ /**
1507
+ * Get all unresolved references
1508
+ */
1509
+ getUnresolvedReferences() {
1510
+ const rows = this.db.prepare('SELECT * FROM unresolved_refs').all();
1511
+ return rows.map((row) => ({
1512
+ fromNodeId: row.from_node_id,
1513
+ referenceName: row.reference_name,
1514
+ referenceKind: row.reference_kind,
1515
+ line: row.line,
1516
+ column: row.col,
1517
+ candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1518
+ filePath: row.file_path,
1519
+ language: row.language,
1520
+ }));
1521
+ }
1522
+ /**
1523
+ * Get the count of unresolved references without loading them into memory
1524
+ */
1525
+ getUnresolvedReferencesCount() {
1526
+ if (!this.stmts.getUnresolvedCount) {
1527
+ this.stmts.getUnresolvedCount = this.db.prepare('SELECT COUNT(*) as count FROM unresolved_refs');
1528
+ }
1529
+ const row = this.stmts.getUnresolvedCount.get();
1530
+ return row.count;
1531
+ }
1532
+ /**
1533
+ * Get a batch of unresolved references using LIMIT/OFFSET pagination.
1534
+ * Used to process references in bounded memory chunks.
1535
+ */
1536
+ getUnresolvedReferencesBatch(offset, limit) {
1537
+ if (!this.stmts.getUnresolvedBatch) {
1538
+ this.stmts.getUnresolvedBatch = this.db.prepare('SELECT * FROM unresolved_refs LIMIT ? OFFSET ?');
1539
+ }
1540
+ const rows = this.stmts.getUnresolvedBatch.all(limit, offset);
1541
+ return rows.map((row) => ({
1542
+ fromNodeId: row.from_node_id,
1543
+ referenceName: row.reference_name,
1544
+ referenceKind: row.reference_kind,
1545
+ line: row.line,
1546
+ column: row.col,
1547
+ candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1548
+ filePath: row.file_path,
1549
+ language: row.language,
1550
+ }));
1551
+ }
1552
+ /**
1553
+ * Get all tracked file paths (lightweight — no full FileRecord objects)
1554
+ */
1555
+ getAllFilePaths() {
1556
+ if (!this.stmts.getAllFilePaths) {
1557
+ this.stmts.getAllFilePaths = this.db.prepare('SELECT path FROM files ORDER BY path');
1558
+ }
1559
+ const rows = this.stmts.getAllFilePaths.all();
1560
+ return rows.map((r) => r.path);
1561
+ }
1562
+ /**
1563
+ * Get all distinct node names (lightweight — just name strings for pre-filtering)
1564
+ */
1565
+ getAllNodeNames() {
1566
+ if (!this.stmts.getAllNodeNames) {
1567
+ this.stmts.getAllNodeNames = this.db.prepare('SELECT DISTINCT name FROM nodes');
1568
+ }
1569
+ const rows = this.stmts.getAllNodeNames.all();
1570
+ return rows.map((r) => r.name);
1571
+ }
1572
+ /**
1573
+ * Get unresolved references scoped to specific file paths.
1574
+ * Uses the idx_unresolved_file_path index for efficient lookup.
1575
+ */
1576
+ getUnresolvedReferencesByFiles(filePaths) {
1577
+ if (filePaths.length === 0)
1578
+ return [];
1579
+ // Chunk under SQLite's parameter limit: the first sync of a very large repo
1580
+ // passes every changed file here, which an unbounded `IN (...)` would bind
1581
+ // as one parameter each — exceeding MAX_VARIABLE_NUMBER and aborting with
1582
+ // "too many SQL variables". (#540)
1583
+ const rows = [];
1584
+ for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1585
+ const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1586
+ const placeholders = chunk.map(() => '?').join(',');
1587
+ const chunkRows = this.db
1588
+ .prepare(`SELECT * FROM unresolved_refs WHERE file_path IN (${placeholders})`)
1589
+ .all(...chunk);
1590
+ rows.push(...chunkRows);
1591
+ }
1592
+ return rows.map((row) => ({
1593
+ fromNodeId: row.from_node_id,
1594
+ referenceName: row.reference_name,
1595
+ referenceKind: row.reference_kind,
1596
+ line: row.line,
1597
+ column: row.col,
1598
+ candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1599
+ filePath: row.file_path,
1600
+ language: row.language,
1601
+ }));
1602
+ }
1603
+ /**
1604
+ * Delete all unresolved references (after resolution)
1605
+ */
1606
+ clearUnresolvedReferences() {
1607
+ this.db.exec('DELETE FROM unresolved_refs');
1608
+ }
1609
+ /**
1610
+ * Delete resolved references by their IDs
1611
+ */
1612
+ deleteResolvedReferences(fromNodeIds) {
1613
+ if (fromNodeIds.length === 0)
1614
+ return;
1615
+ // Chunk under SQLite's parameter limit, matching every other IN-list in
1616
+ // this file. The internal resolution path uses deleteSpecificResolvedReferences
1617
+ // instead, but QueryBuilder is part of the public API, so a library consumer
1618
+ // passing more ids than SQLITE_MAX_VARIABLE_NUMBER (32766 on the bundled
1619
+ // node:sqlite) would otherwise hit "too many SQL variables". (#540, #1001)
1620
+ for (let i = 0; i < fromNodeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1621
+ const chunk = fromNodeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1622
+ const placeholders = chunk.map(() => '?').join(',');
1623
+ this.db.prepare(`DELETE FROM unresolved_refs WHERE from_node_id IN (${placeholders})`).run(...chunk);
1624
+ }
1625
+ }
1626
+ /**
1627
+ * Delete specific resolved references by (fromNodeId, referenceName, referenceKind) tuples.
1628
+ * More precise than deleteResolvedReferences — only removes refs that were actually resolved.
1629
+ */
1630
+ deleteSpecificResolvedReferences(refs) {
1631
+ if (refs.length === 0)
1632
+ return;
1633
+ const stmt = this.db.prepare('DELETE FROM unresolved_refs WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?');
1634
+ const deleteMany = this.db.transaction((items) => {
1635
+ for (const ref of items) {
1636
+ stmt.run(ref.fromNodeId, ref.referenceName, ref.referenceKind);
1637
+ }
1638
+ });
1639
+ deleteMany(refs);
1640
+ }
1641
+ // ===========================================================================
1642
+ // Statistics
1643
+ // ===========================================================================
1644
+ /**
1645
+ * Lightweight (nodes, edges) count snapshot. Used around an index/sync
1646
+ * run to compute true additions across extraction + resolution +
1647
+ * synthesis — the per-phase counter in the orchestrator only sees
1648
+ * extraction's contribution, which is why the CLI summary under-reported
1649
+ * the edge count (resolution + synthesizer edges were invisible).
1650
+ */
1651
+ getNodeAndEdgeCount() {
1652
+ return this.db
1653
+ .prepare('SELECT (SELECT COUNT(*) FROM nodes) AS nodes, (SELECT COUNT(*) FROM edges) AS edges')
1654
+ .get();
1655
+ }
1656
+ /**
1657
+ * Get graph statistics
1658
+ */
1659
+ getStats() {
1660
+ // Single query for all three aggregate counts
1661
+ const counts = this.db.prepare(`
1662
+ SELECT
1663
+ (SELECT COUNT(*) FROM nodes) AS node_count,
1664
+ (SELECT COUNT(*) FROM edges) AS edge_count,
1665
+ (SELECT COUNT(*) FROM files) AS file_count
1666
+ `).get();
1667
+ const nodesByKind = {};
1668
+ const nodeKindRows = this.db
1669
+ .prepare('SELECT kind, COUNT(*) as count FROM nodes GROUP BY kind')
1670
+ .all();
1671
+ for (const row of nodeKindRows) {
1672
+ nodesByKind[row.kind] = row.count;
1673
+ }
1674
+ const edgesByKind = {};
1675
+ const edgeKindRows = this.db
1676
+ .prepare('SELECT kind, COUNT(*) as count FROM edges GROUP BY kind')
1677
+ .all();
1678
+ for (const row of edgeKindRows) {
1679
+ edgesByKind[row.kind] = row.count;
1680
+ }
1681
+ const filesByLanguage = {};
1682
+ const languageRows = this.db
1683
+ .prepare('SELECT language, COUNT(*) as count FROM files GROUP BY language')
1684
+ .all();
1685
+ for (const row of languageRows) {
1686
+ filesByLanguage[row.language] = row.count;
1687
+ }
1688
+ return {
1689
+ nodeCount: counts.node_count,
1690
+ edgeCount: counts.edge_count,
1691
+ fileCount: counts.file_count,
1692
+ nodesByKind,
1693
+ edgesByKind,
1694
+ filesByLanguage,
1695
+ dbSizeBytes: 0, // Set by caller using DatabaseConnection.getSize()
1696
+ lastUpdated: Date.now(),
1697
+ };
1698
+ }
1699
+ // ===========================================================================
1700
+ // Project Metadata
1701
+ // ===========================================================================
1702
+ /**
1703
+ * Get a metadata value by key
1704
+ */
1705
+ getMetadata(key) {
1706
+ const row = this.db.prepare('SELECT value FROM project_metadata WHERE key = ?').get(key);
1707
+ return row?.value ?? null;
1708
+ }
1709
+ /**
1710
+ * Set a metadata key-value pair (upsert)
1711
+ */
1712
+ setMetadata(key, value) {
1713
+ this.db.prepare('INSERT INTO project_metadata (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at').run(key, value, Date.now());
1714
+ }
1715
+ /**
1716
+ * Get all metadata as a key-value record
1717
+ */
1718
+ getAllMetadata() {
1719
+ const rows = this.db.prepare('SELECT key, value FROM project_metadata').all();
1720
+ const result = {};
1721
+ for (const row of rows) {
1722
+ result[row.key] = row.value;
1723
+ }
1724
+ return result;
1725
+ }
1726
+ /**
1727
+ * Clear all data from the database
1728
+ */
1729
+ clear() {
1730
+ this.nodeCache.clear();
1731
+ this.db.transaction(() => {
1732
+ this.db.exec('DELETE FROM unresolved_refs');
1733
+ this.db.exec('DELETE FROM edges');
1734
+ this.db.exec('DELETE FROM nodes');
1735
+ this.db.exec('DELETE FROM files');
1736
+ })();
1737
+ }
1738
+ }
1739
+ exports.QueryBuilder = QueryBuilder;
1740
+ //# sourceMappingURL=queries.js.map