homegraph 1.4.1 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +305 -268
  3. package/dist/bin/command-supervision.d.ts.map +1 -1
  4. package/dist/bin/command-supervision.js +7 -4
  5. package/dist/bin/command-supervision.js.map +1 -1
  6. package/dist/bin/homegraph.js +304 -81
  7. package/dist/bin/homegraph.js.map +1 -1
  8. package/dist/context/index.d.ts.map +1 -1
  9. package/dist/context/index.js +32 -11
  10. package/dist/context/index.js.map +1 -1
  11. package/dist/db/index.d.ts +143 -1
  12. package/dist/db/index.d.ts.map +1 -1
  13. package/dist/db/index.js +305 -28
  14. package/dist/db/index.js.map +1 -1
  15. package/dist/db/migrations.js +37 -37
  16. package/dist/db/queries.d.ts +43 -4
  17. package/dist/db/queries.d.ts.map +1 -1
  18. package/dist/db/queries.js +294 -170
  19. package/dist/db/queries.js.map +1 -1
  20. package/dist/db/schema.sql +203 -203
  21. package/dist/db/sqlite-adapter.d.ts +24 -17
  22. package/dist/db/sqlite-adapter.d.ts.map +1 -1
  23. package/dist/db/sqlite-adapter.js +292 -36
  24. package/dist/db/sqlite-adapter.js.map +1 -1
  25. package/dist/db/wal-valve.d.ts +15 -2
  26. package/dist/db/wal-valve.d.ts.map +1 -1
  27. package/dist/db/wal-valve.js +88 -6
  28. package/dist/db/wal-valve.js.map +1 -1
  29. package/dist/directory.js +5 -5
  30. package/dist/extraction/arkts-batch-worker.js +3 -2
  31. package/dist/extraction/arkts-batch-worker.js.map +1 -1
  32. package/dist/extraction/default-ignore.d.ts +39 -0
  33. package/dist/extraction/default-ignore.d.ts.map +1 -0
  34. package/dist/extraction/default-ignore.js +221 -0
  35. package/dist/extraction/default-ignore.js.map +1 -0
  36. package/dist/extraction/index.d.ts +9 -10
  37. package/dist/extraction/index.d.ts.map +1 -1
  38. package/dist/extraction/index.js +227 -323
  39. package/dist/extraction/index.js.map +1 -1
  40. package/dist/extraction/languages/arkts-viewtree.d.ts +2 -4
  41. package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
  42. package/dist/extraction/languages/arkts-viewtree.js +6 -21
  43. package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
  44. package/dist/extraction/languages/arkts.d.ts +100 -6
  45. package/dist/extraction/languages/arkts.d.ts.map +1 -1
  46. package/dist/extraction/languages/arkts.js +1777 -173
  47. package/dist/extraction/languages/arkts.js.map +1 -1
  48. package/dist/extraction/store-worker.d.ts +20 -0
  49. package/dist/extraction/store-worker.d.ts.map +1 -0
  50. package/dist/extraction/store-worker.js +102 -0
  51. package/dist/extraction/store-worker.js.map +1 -0
  52. package/dist/extraction/store-writer.d.ts +48 -0
  53. package/dist/extraction/store-writer.d.ts.map +1 -0
  54. package/dist/extraction/store-writer.js +167 -0
  55. package/dist/extraction/store-writer.js.map +1 -0
  56. package/dist/extraction/tree-sitter.d.ts.map +1 -1
  57. package/dist/extraction/tree-sitter.js +47 -0
  58. package/dist/extraction/tree-sitter.js.map +1 -1
  59. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  60. package/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  61. package/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  62. package/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  63. package/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  64. package/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  65. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  66. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  67. package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  68. package/dist/extraction/wasm-runtime-flags.d.ts +14 -4
  69. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
  70. package/dist/extraction/wasm-runtime-flags.js +55 -7
  71. package/dist/extraction/wasm-runtime-flags.js.map +1 -1
  72. package/dist/index.d.ts +16 -5
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +135 -97
  75. package/dist/index.js.map +1 -1
  76. package/dist/installer/instructions-template.js +9 -9
  77. package/dist/mcp/liveness-watchdog.d.ts +18 -0
  78. package/dist/mcp/liveness-watchdog.d.ts.map +1 -1
  79. package/dist/mcp/liveness-watchdog.js +185 -73
  80. package/dist/mcp/liveness-watchdog.js.map +1 -1
  81. package/dist/mcp/query-worker.d.ts +2 -2
  82. package/dist/mcp/query-worker.js +2 -2
  83. package/dist/mcp/server-instructions.js +47 -47
  84. package/dist/mcp/tools.d.ts.map +1 -1
  85. package/dist/mcp/tools.js +42 -26
  86. package/dist/mcp/tools.js.map +1 -1
  87. package/dist/reasoning/reasoner.js +32 -32
  88. package/dist/resolution/callback-synthesizer.d.ts +52 -16
  89. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  90. package/dist/resolution/callback-synthesizer.js +234 -180
  91. package/dist/resolution/callback-synthesizer.js.map +1 -1
  92. package/dist/resolution/cooperative-yield.d.ts +10 -2
  93. package/dist/resolution/cooperative-yield.d.ts.map +1 -1
  94. package/dist/resolution/cooperative-yield.js +6 -4
  95. package/dist/resolution/cooperative-yield.js.map +1 -1
  96. package/dist/resolution/frameworks/go.d.ts.map +1 -1
  97. package/dist/resolution/frameworks/go.js +29 -6
  98. package/dist/resolution/frameworks/go.js.map +1 -1
  99. package/dist/resolution/import-resolver.d.ts +2 -3
  100. package/dist/resolution/import-resolver.d.ts.map +1 -1
  101. package/dist/resolution/import-resolver.js +166 -7
  102. package/dist/resolution/import-resolver.js.map +1 -1
  103. package/dist/resolution/index.d.ts +87 -2
  104. package/dist/resolution/index.d.ts.map +1 -1
  105. package/dist/resolution/index.js +739 -131
  106. package/dist/resolution/index.js.map +1 -1
  107. package/dist/resolution/memory-budget.d.ts +48 -0
  108. package/dist/resolution/memory-budget.d.ts.map +1 -0
  109. package/dist/resolution/memory-budget.js +162 -0
  110. package/dist/resolution/memory-budget.js.map +1 -0
  111. package/dist/resolution/name-matcher.d.ts +12 -1
  112. package/dist/resolution/name-matcher.d.ts.map +1 -1
  113. package/dist/resolution/name-matcher.js +439 -97
  114. package/dist/resolution/name-matcher.js.map +1 -1
  115. package/dist/resolution/resolver-pool.d.ts +106 -0
  116. package/dist/resolution/resolver-pool.d.ts.map +1 -0
  117. package/dist/resolution/resolver-pool.js +344 -0
  118. package/dist/resolution/resolver-pool.js.map +1 -0
  119. package/dist/resolution/resolver-worker.d.ts +17 -0
  120. package/dist/resolution/resolver-worker.d.ts.map +1 -0
  121. package/dist/resolution/resolver-worker.js +141 -0
  122. package/dist/resolution/resolver-worker.js.map +1 -0
  123. package/dist/resolution/types.d.ts +3 -0
  124. package/dist/resolution/types.d.ts.map +1 -1
  125. package/dist/spec/build/diff-parser.d.ts +55 -0
  126. package/dist/spec/build/diff-parser.d.ts.map +1 -0
  127. package/dist/spec/build/diff-parser.js +205 -0
  128. package/dist/spec/build/diff-parser.js.map +1 -0
  129. package/dist/spec/build/pipeline.d.ts +54 -0
  130. package/dist/spec/build/pipeline.d.ts.map +1 -0
  131. package/dist/spec/build/pipeline.js +170 -0
  132. package/dist/spec/build/pipeline.js.map +1 -0
  133. package/dist/spec/build/scan.d.ts +48 -0
  134. package/dist/spec/build/scan.d.ts.map +1 -0
  135. package/dist/spec/build/scan.js +89 -0
  136. package/dist/spec/build/scan.js.map +1 -0
  137. package/dist/spec/build/scope-resolver.d.ts +50 -0
  138. package/dist/spec/build/scope-resolver.d.ts.map +1 -0
  139. package/dist/spec/build/scope-resolver.js +105 -0
  140. package/dist/spec/build/scope-resolver.js.map +1 -0
  141. package/dist/spec/build/spec-extractor.d.ts +74 -0
  142. package/dist/spec/build/spec-extractor.d.ts.map +1 -0
  143. package/dist/spec/build/spec-extractor.js +344 -0
  144. package/dist/spec/build/spec-extractor.js.map +1 -0
  145. package/dist/spec/config.d.ts +35 -1
  146. package/dist/spec/config.d.ts.map +1 -1
  147. package/dist/spec/config.js +30 -5
  148. package/dist/spec/config.js.map +1 -1
  149. package/dist/spec/db/commit-node.js +4 -4
  150. package/dist/spec/db/fragment-node.js +10 -10
  151. package/dist/spec/db/fts.d.ts.map +1 -1
  152. package/dist/spec/db/fts.js +27 -58
  153. package/dist/spec/db/fts.js.map +1 -1
  154. package/dist/spec/db/index.d.ts +5 -3
  155. package/dist/spec/db/index.d.ts.map +1 -1
  156. package/dist/spec/db/index.js +16 -1
  157. package/dist/spec/db/index.js.map +1 -1
  158. package/dist/spec/db/persist.d.ts +45 -0
  159. package/dist/spec/db/persist.d.ts.map +1 -0
  160. package/dist/spec/db/persist.js +66 -0
  161. package/dist/spec/db/persist.js.map +1 -0
  162. package/dist/spec/db/relations.d.ts +80 -1
  163. package/dist/spec/db/relations.d.ts.map +1 -1
  164. package/dist/spec/db/relations.js +218 -47
  165. package/dist/spec/db/relations.js.map +1 -1
  166. package/dist/spec/db/schema.d.ts +4 -0
  167. package/dist/spec/db/schema.d.ts.map +1 -1
  168. package/dist/spec/db/schema.js +10 -6
  169. package/dist/spec/db/schema.js.map +1 -1
  170. package/dist/spec/db/schema.sql +121 -117
  171. package/dist/spec/db/spec-node.d.ts +5 -0
  172. package/dist/spec/db/spec-node.d.ts.map +1 -1
  173. package/dist/spec/db/spec-node.js +15 -9
  174. package/dist/spec/db/spec-node.js.map +1 -1
  175. package/dist/spec/db/sql-utils.d.ts +11 -0
  176. package/dist/spec/db/sql-utils.d.ts.map +1 -0
  177. package/dist/spec/db/sql-utils.js +19 -0
  178. package/dist/spec/db/sql-utils.js.map +1 -0
  179. package/dist/spec/evolve/cluster-context.d.ts +30 -0
  180. package/dist/spec/evolve/cluster-context.d.ts.map +1 -0
  181. package/dist/spec/evolve/cluster-context.js +78 -0
  182. package/dist/spec/evolve/cluster-context.js.map +1 -0
  183. package/dist/spec/evolve/commit-spec-analyzer.d.ts +51 -0
  184. package/dist/spec/evolve/commit-spec-analyzer.d.ts.map +1 -0
  185. package/dist/spec/evolve/commit-spec-analyzer.js +88 -0
  186. package/dist/spec/evolve/commit-spec-analyzer.js.map +1 -0
  187. package/dist/spec/evolve/commit-spec-persister.d.ts +53 -0
  188. package/dist/spec/evolve/commit-spec-persister.d.ts.map +1 -0
  189. package/dist/spec/evolve/commit-spec-persister.js +93 -0
  190. package/dist/spec/evolve/commit-spec-persister.js.map +1 -0
  191. package/dist/spec/evolve/impact-locator.d.ts +23 -7
  192. package/dist/spec/evolve/impact-locator.d.ts.map +1 -1
  193. package/dist/spec/evolve/impact-locator.js +58 -14
  194. package/dist/spec/evolve/impact-locator.js.map +1 -1
  195. package/dist/spec/evolve/pipeline.d.ts +62 -25
  196. package/dist/spec/evolve/pipeline.d.ts.map +1 -1
  197. package/dist/spec/evolve/pipeline.js +436 -457
  198. package/dist/spec/evolve/pipeline.js.map +1 -1
  199. package/dist/spec/evolve/spec-rewriter.d.ts +13 -13
  200. package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
  201. package/dist/spec/evolve/spec-rewriter.js +45 -45
  202. package/dist/spec/evolve/spec-rewriter.js.map +1 -1
  203. package/dist/spec/git/commits.d.ts +85 -0
  204. package/dist/spec/git/commits.d.ts.map +1 -0
  205. package/dist/spec/git/commits.js +218 -0
  206. package/dist/spec/git/commits.js.map +1 -0
  207. package/dist/spec/git/exec.d.ts +13 -0
  208. package/dist/spec/git/exec.d.ts.map +1 -0
  209. package/dist/spec/git/exec.js +19 -0
  210. package/dist/spec/git/exec.js.map +1 -0
  211. package/dist/spec/git/index.d.ts +9 -0
  212. package/dist/spec/git/index.d.ts.map +1 -0
  213. package/dist/spec/git/index.js +22 -0
  214. package/dist/spec/git/index.js.map +1 -0
  215. package/dist/spec/graph/index.d.ts +8 -0
  216. package/dist/spec/graph/index.d.ts.map +1 -0
  217. package/dist/spec/graph/index.js +17 -0
  218. package/dist/spec/graph/index.js.map +1 -0
  219. package/dist/spec/graph/queries.d.ts +6 -35
  220. package/dist/spec/graph/queries.d.ts.map +1 -1
  221. package/dist/spec/graph/queries.js +71 -248
  222. package/dist/spec/graph/queries.js.map +1 -1
  223. package/dist/spec/llm/agent-client.d.ts +59 -0
  224. package/dist/spec/llm/agent-client.d.ts.map +1 -0
  225. package/dist/spec/llm/agent-client.js +213 -0
  226. package/dist/spec/llm/agent-client.js.map +1 -0
  227. package/dist/spec/llm/agents/claude-code.d.ts +32 -0
  228. package/dist/spec/llm/agents/claude-code.d.ts.map +1 -0
  229. package/dist/spec/llm/agents/claude-code.js +125 -0
  230. package/dist/spec/llm/agents/claude-code.js.map +1 -0
  231. package/dist/spec/llm/agents/codex.d.ts +32 -0
  232. package/dist/spec/llm/agents/codex.d.ts.map +1 -0
  233. package/dist/spec/llm/agents/codex.js +145 -0
  234. package/dist/spec/llm/agents/codex.js.map +1 -0
  235. package/dist/spec/llm/agents/detect-utils.d.ts +28 -0
  236. package/dist/spec/llm/agents/detect-utils.d.ts.map +1 -0
  237. package/dist/spec/llm/agents/detect-utils.js +91 -0
  238. package/dist/spec/llm/agents/detect-utils.js.map +1 -0
  239. package/dist/spec/llm/agents/deveco-code.d.ts +33 -0
  240. package/dist/spec/llm/agents/deveco-code.d.ts.map +1 -0
  241. package/dist/spec/llm/agents/deveco-code.js +165 -0
  242. package/dist/spec/llm/agents/deveco-code.js.map +1 -0
  243. package/dist/spec/llm/agents/index.d.ts +31 -0
  244. package/dist/spec/llm/agents/index.d.ts.map +1 -0
  245. package/dist/spec/llm/agents/index.js +65 -0
  246. package/dist/spec/llm/agents/index.js.map +1 -0
  247. package/dist/spec/llm/agents/types.d.ts +76 -0
  248. package/dist/spec/llm/agents/types.d.ts.map +1 -0
  249. package/dist/spec/llm/agents/types.js +15 -0
  250. package/dist/spec/llm/agents/types.js.map +1 -0
  251. package/dist/spec/llm/client.d.ts +31 -11
  252. package/dist/spec/llm/client.d.ts.map +1 -1
  253. package/dist/spec/llm/client.js +143 -81
  254. package/dist/spec/llm/client.js.map +1 -1
  255. package/dist/spec/llm/factory.d.ts +41 -0
  256. package/dist/spec/llm/factory.d.ts.map +1 -0
  257. package/dist/spec/llm/factory.js +80 -0
  258. package/dist/spec/llm/factory.js.map +1 -0
  259. package/dist/spec/llm/prompts.d.ts +24 -8
  260. package/dist/spec/llm/prompts.d.ts.map +1 -1
  261. package/dist/spec/llm/prompts.js +112 -62
  262. package/dist/spec/llm/prompts.js.map +1 -1
  263. package/dist/spec/llm/retry.d.ts +53 -0
  264. package/dist/spec/llm/retry.d.ts.map +1 -0
  265. package/dist/spec/llm/retry.js +153 -0
  266. package/dist/spec/llm/retry.js.map +1 -0
  267. package/dist/spec/mine/clustering/features.d.ts +38 -0
  268. package/dist/spec/mine/clustering/features.d.ts.map +1 -0
  269. package/dist/spec/mine/clustering/features.js +108 -0
  270. package/dist/spec/mine/clustering/features.js.map +1 -0
  271. package/dist/spec/mine/clustering/index.d.ts +62 -0
  272. package/dist/spec/mine/clustering/index.d.ts.map +1 -0
  273. package/dist/spec/mine/clustering/index.js +259 -0
  274. package/dist/spec/mine/clustering/index.js.map +1 -0
  275. package/dist/spec/mine/clustering/leiden.d.ts +61 -0
  276. package/dist/spec/mine/clustering/leiden.d.ts.map +1 -0
  277. package/dist/spec/mine/clustering/leiden.js +489 -0
  278. package/dist/spec/mine/clustering/leiden.js.map +1 -0
  279. package/dist/spec/mine/clustering/text-similarity.d.ts +22 -0
  280. package/dist/spec/mine/clustering/text-similarity.d.ts.map +1 -0
  281. package/dist/spec/mine/clustering/text-similarity.js +98 -0
  282. package/dist/spec/mine/clustering/text-similarity.js.map +1 -0
  283. package/dist/spec/mine/generator.d.ts +54 -0
  284. package/dist/spec/mine/generator.d.ts.map +1 -0
  285. package/dist/spec/mine/generator.js +267 -0
  286. package/dist/spec/mine/generator.js.map +1 -0
  287. package/dist/spec/mine/persist.d.ts +37 -0
  288. package/dist/spec/mine/persist.d.ts.map +1 -0
  289. package/dist/spec/mine/persist.js +170 -0
  290. package/dist/spec/mine/persist.js.map +1 -0
  291. package/dist/spec/mine/pipeline.d.ts +41 -0
  292. package/dist/spec/mine/pipeline.d.ts.map +1 -0
  293. package/dist/spec/mine/pipeline.js +236 -0
  294. package/dist/spec/mine/pipeline.js.map +1 -0
  295. package/dist/spec/mine/scanner.d.ts +59 -0
  296. package/dist/spec/mine/scanner.d.ts.map +1 -0
  297. package/dist/spec/mine/scanner.js +383 -0
  298. package/dist/spec/mine/scanner.js.map +1 -0
  299. package/dist/spec/types.d.ts +32 -0
  300. package/dist/spec/types.d.ts.map +1 -1
  301. package/dist/spec/ui/index.d.ts +9 -0
  302. package/dist/spec/ui/index.d.ts.map +1 -0
  303. package/dist/spec/ui/index.js +16 -0
  304. package/dist/spec/ui/index.js.map +1 -0
  305. package/dist/spec/ui/progress-handler.d.ts +33 -0
  306. package/dist/spec/ui/progress-handler.d.ts.map +1 -0
  307. package/dist/spec/ui/progress-handler.js +132 -0
  308. package/dist/spec/ui/progress-handler.js.map +1 -0
  309. package/dist/spec/ui/progress.d.ts +24 -0
  310. package/dist/spec/ui/progress.d.ts.map +1 -0
  311. package/dist/spec/ui/progress.js +13 -0
  312. package/dist/spec/ui/progress.js.map +1 -0
  313. package/dist/spec/utils/fs.d.ts +45 -0
  314. package/dist/spec/utils/fs.d.ts.map +1 -0
  315. package/dist/spec/utils/fs.js +163 -0
  316. package/dist/spec/utils/fs.js.map +1 -0
  317. package/dist/spec/utils/index.d.ts +12 -0
  318. package/dist/spec/utils/index.d.ts.map +1 -0
  319. package/dist/spec/utils/index.js +26 -0
  320. package/dist/spec/utils/index.js.map +1 -0
  321. package/dist/spec/utils/meta.d.ts +32 -0
  322. package/dist/spec/utils/meta.d.ts.map +1 -0
  323. package/dist/spec/utils/meta.js +122 -0
  324. package/dist/spec/utils/meta.js.map +1 -0
  325. package/dist/spec/utils/truncate.d.ts +86 -0
  326. package/dist/spec/utils/truncate.d.ts.map +1 -0
  327. package/dist/spec/utils/truncate.js +172 -0
  328. package/dist/spec/utils/truncate.js.map +1 -0
  329. package/dist/sync/watcher.d.ts +25 -1
  330. package/dist/sync/watcher.d.ts.map +1 -1
  331. package/dist/sync/watcher.js +76 -3
  332. package/dist/sync/watcher.js.map +1 -1
  333. package/dist/telemetry/index.js +3 -3
  334. package/dist/telemetry/index.js.map +1 -1
  335. package/dist/types.d.ts +3 -0
  336. package/dist/types.d.ts.map +1 -1
  337. package/package.json +62 -58
  338. package/scripts/_tmp-cfwk-resolve.log +0 -0
  339. package/scripts/_tmp-cfwk-sig.log +0 -0
  340. package/scripts/_tmp-cfwk-vt.log +0 -0
  341. package/scripts/add-lang/bench.sh +60 -60
  342. package/scripts/add-lang/check-grammar.mjs +75 -75
  343. package/scripts/add-lang/dump-ast.mjs +103 -103
  344. package/scripts/add-lang/verify-extraction.mjs +70 -70
  345. package/scripts/agent-eval/ab-adoption.sh +91 -91
  346. package/scripts/agent-eval/ab-hook.sh +86 -86
  347. package/scripts/agent-eval/ab-impl.sh +78 -78
  348. package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -102
  349. package/scripts/agent-eval/ab-sufficiency.sh +78 -78
  350. package/scripts/agent-eval/arms-F.sh +21 -21
  351. package/scripts/agent-eval/arms-matrix.sh +37 -37
  352. package/scripts/agent-eval/audit.sh +68 -68
  353. package/scripts/agent-eval/bench-readme.sh +28 -28
  354. package/scripts/agent-eval/bench-why-repo.sh +22 -22
  355. package/scripts/agent-eval/block-read-hook.sh +19 -19
  356. package/scripts/agent-eval/hook-settings.json +15 -15
  357. package/scripts/agent-eval/itrun.sh +120 -120
  358. package/scripts/agent-eval/offload-eval-3arm.sh +72 -72
  359. package/scripts/agent-eval/offload-eval-cost.mjs +133 -133
  360. package/scripts/agent-eval/offload-eval-effort.mjs +108 -108
  361. package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -25
  362. package/scripts/agent-eval/offload-eval-frontload.sh +47 -47
  363. package/scripts/agent-eval/offload-eval-ground-truth.json +18 -18
  364. package/scripts/agent-eval/offload-eval-hook.mjs +84 -84
  365. package/scripts/agent-eval/offload-eval-judge.mjs +103 -103
  366. package/scripts/agent-eval/offload-eval-matrix.sh +20 -20
  367. package/scripts/agent-eval/offload-eval-metrics.mjs +94 -94
  368. package/scripts/agent-eval/offload-eval-refs1.sh +50 -50
  369. package/scripts/agent-eval/offload-eval-setup.sh +24 -24
  370. package/scripts/agent-eval/offload-eval-styles.sh +71 -71
  371. package/scripts/agent-eval/offload-eval-summarize.mjs +68 -68
  372. package/scripts/agent-eval/offload-eval.md +76 -76
  373. package/scripts/agent-eval/parse-arms.mjs +116 -116
  374. package/scripts/agent-eval/parse-bench-readme.mjs +84 -84
  375. package/scripts/agent-eval/parse-run.mjs +45 -45
  376. package/scripts/agent-eval/parse-session.mjs +93 -93
  377. package/scripts/agent-eval/probe-context.mjs +21 -21
  378. package/scripts/agent-eval/probe-explore.mjs +40 -40
  379. package/scripts/agent-eval/probe-node.mjs +20 -20
  380. package/scripts/agent-eval/probe-sweep.mjs +119 -119
  381. package/scripts/agent-eval/probe-trace.mjs +20 -20
  382. package/scripts/agent-eval/redirect-read-hook.sh +38 -38
  383. package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -119
  384. package/scripts/agent-eval/repro-daemon-clients.mjs +125 -125
  385. package/scripts/agent-eval/run-agent.sh +34 -34
  386. package/scripts/agent-eval/run-all.sh +75 -75
  387. package/scripts/agent-eval/run-arms.sh +56 -56
  388. package/scripts/agent-eval/seq-matrix.mjs +137 -137
  389. package/scripts/bench-arkts-init-rss.log +0 -0
  390. package/scripts/build-bundle.sh +123 -123
  391. package/scripts/exp_boundary_eval/README.md +247 -247
  392. package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
  393. package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-38.pyc +0 -0
  394. package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
  395. package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-38.pyc +0 -0
  396. package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-38.pyc +0 -0
  397. package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-310.pyc +0 -0
  398. package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-38.pyc +0 -0
  399. package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
  400. package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-38.pyc +0 -0
  401. package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
  402. package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-38.pyc +0 -0
  403. package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
  404. package/scripts/exp_boundary_eval/__pycache__/setup.cpython-38.pyc +0 -0
  405. package/scripts/exp_boundary_eval/__pycache__/win_mcp_launcher.cpython-38.pyc +0 -0
  406. package/scripts/exp_boundary_eval/_test_mcp_chain.py +78 -78
  407. package/scripts/exp_boundary_eval/_test_stdin.py +8 -8
  408. package/scripts/exp_boundary_eval/_utils.py +1116 -1116
  409. package/scripts/exp_boundary_eval/analyze.py +1313 -1313
  410. package/scripts/exp_boundary_eval/deveco_arm.py +519 -519
  411. package/scripts/exp_boundary_eval/run_all.py +378 -378
  412. package/scripts/exp_boundary_eval/run_one.py +165 -165
  413. package/scripts/exp_boundary_eval/run_session.py +158 -158
  414. package/scripts/exp_boundary_eval/setup.py +120 -120
  415. package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -73
  416. package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -36
  417. package/scripts/exp_boundary_eval/win_node_launcher.py +24 -24
  418. package/scripts/extract-release-notes.mjs +130 -130
  419. package/scripts/local-install.sh +41 -41
  420. package/scripts/npm-sdk.js +75 -75
  421. package/scripts/npm-shim.js +275 -275
  422. package/scripts/ohos-sdk-publish.mjs +133 -133
  423. package/scripts/pack-npm.sh +119 -119
  424. package/scripts/prepare-release.mjs +270 -270
  425. package/scripts/probe-arkts-mem-why-run.log +0 -0
  426. package/scripts/probe-banner-livecard-ir.log +0 -0
  427. package/scripts/probe-cfwk-ast.stderr.log +0 -0
  428. package/scripts/probe-cfwk-ast.stdout.log +0 -0
  429. package/scripts/probe-cfwk-attr-shape.log +0 -0
  430. package/scripts/probe-cfwk-cfgdump.stderr.log +0 -0
  431. package/scripts/probe-cfwk-cfgdump.stdout.log +0 -0
  432. package/scripts/probe-cfwk-cvc.stderr.log +0 -0
  433. package/scripts/probe-cfwk-cvc.stdout.log +0 -0
  434. package/scripts/probe-cfwk-diag2.log +0 -0
  435. package/scripts/probe-cfwk-diag3.log +0 -0
  436. package/scripts/probe-cfwk-fedbg.stderr.log +0 -0
  437. package/scripts/probe-cfwk-fedbg.stdout.log +0 -0
  438. package/scripts/probe-cfwk-fileresult.log +0 -0
  439. package/scripts/probe-cfwk-fix.stderr.log +0 -0
  440. package/scripts/probe-cfwk-fix.stdout.log +0 -0
  441. package/scripts/probe-cfwk-fix2.stderr.log +0 -0
  442. package/scripts/probe-cfwk-fix2.stdout.log +0 -0
  443. package/scripts/probe-cfwk-fix3.stderr.log +0 -0
  444. package/scripts/probe-cfwk-fix3.stdout.log +0 -0
  445. package/scripts/probe-cfwk-foreach.log +0 -0
  446. package/scripts/probe-cfwk-getmethod-throw.log +0 -0
  447. package/scripts/probe-cfwk-hg-extract.log +0 -0
  448. package/scripts/probe-cfwk-pr1003-noprior.stderr.log +0 -0
  449. package/scripts/probe-cfwk-pr1003-noprior.stdout.log +0 -0
  450. package/scripts/probe-cfwk-pr1003.stderr.log +0 -0
  451. package/scripts/probe-cfwk-pr1003.stdout.log +0 -0
  452. package/scripts/probe-cfwk-preroot-noprior.stderr.log +0 -0
  453. package/scripts/probe-cfwk-preroot-noprior.stdout.log +0 -0
  454. package/scripts/probe-cfwk-preroot-prior.stderr.log +0 -0
  455. package/scripts/probe-cfwk-preroot-prior.stdout.log +0 -0
  456. package/scripts/probe-cfwk-preroot-skipstate.stderr.log +0 -0
  457. package/scripts/probe-cfwk-preroot-skipstate.stdout.log +0 -0
  458. package/scripts/probe-cfwk-resolve-sim.log +0 -0
  459. package/scripts/probe-cfwk-tree-shape.log +0 -0
  460. package/scripts/probe-cfwk-walk-abort.log +0 -0
  461. package/scripts/probe-cfwk.log +0 -0
  462. package/scripts/probe-force-index.log +0 -0
  463. package/scripts/probe-no-force-index.log +0 -0
  464. package/scripts/probe-samefile-ir.stderr.log +0 -0
  465. package/scripts/probe-samefile-ir.stdout.log +224 -0
  466. package/scripts/probe-sdk-vs-project.log +0 -0
  467. package/scripts/probe-viewtree-downgrade.log +0 -0
  468. package/dist/arkts/ohos-api-index.d.ts +0 -15
  469. package/dist/arkts/ohos-api-index.d.ts.map +0 -1
  470. package/dist/arkts/ohos-api-index.js +0 -190
  471. package/dist/arkts/ohos-api-index.js.map +0 -1
  472. package/dist/arkts/ohos-sdk-input.d.ts +0 -36
  473. package/dist/arkts/ohos-sdk-input.d.ts.map +0 -1
  474. package/dist/arkts/ohos-sdk-input.js +0 -214
  475. package/dist/arkts/ohos-sdk-input.js.map +0 -1
  476. package/dist/extraction/languages/arkts-state-decorators.d.ts +0 -13
  477. package/dist/extraction/languages/arkts-state-decorators.d.ts.map +0 -1
  478. package/dist/extraction/languages/arkts-state-decorators.js +0 -26
  479. package/dist/extraction/languages/arkts-state-decorators.js.map +0 -1
  480. package/dist/extraction/languages/ohos-api-consumer.d.ts +0 -34
  481. package/dist/extraction/languages/ohos-api-consumer.d.ts.map +0 -1
  482. package/dist/extraction/languages/ohos-api-consumer.js +0 -283
  483. package/dist/extraction/languages/ohos-api-consumer.js.map +0 -1
@@ -154,9 +154,54 @@ class QueryBuilder {
154
154
  ohosApiDbPath = null;
155
155
  // Prepared statements (lazily initialized)
156
156
  stmts = {};
157
+ // Multi-row INSERT statements, cached per (statement kind × row count).
158
+ batchStmts = new Map();
159
+ static BATCH_SIZES = [128, 32, 8, 1];
160
+ /**
161
+ * Run `rows` through a multi-row `INSERT` built as `head + (tuple,)*n`,
162
+ * decomposed greedily into the cached batch sizes. Preserves row order.
163
+ */
164
+ runBatched(kind, head, tuple, rows) {
165
+ if (rows.length === 0)
166
+ return;
167
+ let i = 0;
168
+ for (const size of QueryBuilder.BATCH_SIZES) {
169
+ while (rows.length - i >= size) {
170
+ const key = `${kind}:${size}`;
171
+ let stmt = this.batchStmts.get(key);
172
+ if (!stmt) {
173
+ stmt = this.db.prepare(head + new Array(size).fill(tuple).join(','));
174
+ this.batchStmts.set(key, stmt);
175
+ }
176
+ if (size === 1) {
177
+ stmt.run(...rows[i]);
178
+ }
179
+ else {
180
+ const params = [];
181
+ for (let r = 0; r < size; r++) {
182
+ const row = rows[i + r];
183
+ for (let c = 0; c < row.length; c++)
184
+ params.push(row[c]);
185
+ }
186
+ stmt.run(...params);
187
+ }
188
+ i += size;
189
+ }
190
+ }
191
+ }
157
192
  constructor(db) {
158
193
  this.db = db;
159
194
  }
195
+ /**
196
+ * Swap the underlying connection in place. Used by pool workers'
197
+ * connection recycling: a long-lived read connection pins WAL checkpoint
198
+ * progress; workers close and reopen at the pool-idle boundary.
199
+ */
200
+ rebind(db) {
201
+ this.db = db;
202
+ this.stmts = {};
203
+ this.batchStmts.clear();
204
+ }
160
205
  /** Attach a versioned OHOS API db for federated symbol lookup. */
161
206
  attachOhosApiDb(dbPath) {
162
207
  if (dbPath === this.ohosApiDbPath)
@@ -210,20 +255,20 @@ class QueryBuilder {
210
255
  */
211
256
  insertNode(node) {
212
257
  if (!this.stmts.insertNode) {
213
- this.stmts.insertNode = this.db.prepare(`
214
- INSERT OR REPLACE INTO nodes (
215
- id, kind, name, qualified_name, file_path, language,
216
- start_line, end_line, start_column, end_column,
217
- docstring, signature, visibility,
218
- is_exported, is_async, is_static, is_abstract,
219
- decorators, type_parameters, return_type, updated_at
220
- ) VALUES (
221
- @id, @kind, @name, @qualifiedName, @filePath, @language,
222
- @startLine, @endLine, @startColumn, @endColumn,
223
- @docstring, @signature, @visibility,
224
- @isExported, @isAsync, @isStatic, @isAbstract,
225
- @decorators, @typeParameters, @returnType, @updatedAt
226
- )
258
+ this.stmts.insertNode = this.db.prepare(`
259
+ INSERT OR REPLACE INTO nodes (
260
+ id, kind, name, qualified_name, file_path, language,
261
+ start_line, end_line, start_column, end_column,
262
+ docstring, signature, visibility,
263
+ is_exported, is_async, is_static, is_abstract,
264
+ decorators, type_parameters, return_type, updated_at
265
+ ) VALUES (
266
+ @id, @kind, @name, @qualifiedName, @filePath, @language,
267
+ @startLine, @endLine, @startColumn, @endColumn,
268
+ @docstring, @signature, @visibility,
269
+ @isExported, @isAsync, @isStatic, @isAbstract,
270
+ @decorators, @typeParameters, @returnType, @updatedAt
271
+ )
227
272
  `);
228
273
  }
229
274
  // Validate required fields to prevent SQLite bind errors
@@ -280,34 +325,68 @@ class QueryBuilder {
280
325
  }
281
326
  })();
282
327
  }
328
+ /**
329
+ * Store one file's whole extraction bundle — nodes, edges, unresolved refs,
330
+ * and the file record — in a SINGLE transaction. The bulk-index path calls
331
+ * this once per file instead of opening one transaction per table (#1015
332
+ * file-order commit discipline is unchanged: callers still invoke it in file
333
+ * order, and row order within is input order).
334
+ *
335
+ * Edges MUST already be endpoint-filtered by the caller (the store path
336
+ * filters to the file's own inserted node ids), so the per-file existence
337
+ * SELECT that insertEdges() pays is skipped here.
338
+ */
339
+ storeFileBundle(bundle) {
340
+ this.db.transaction(() => {
341
+ this.insertNodes(bundle.nodes);
342
+ if (bundle.edges.length > 0) {
343
+ const rows = [];
344
+ for (const edge of bundle.edges) {
345
+ rows.push([
346
+ edge.source,
347
+ edge.target,
348
+ edge.kind,
349
+ edge.metadata ? JSON.stringify(edge.metadata) : null,
350
+ edge.line ?? null,
351
+ edge.column ?? null,
352
+ edge.provenance ?? null,
353
+ ]);
354
+ }
355
+ this.runBatched('insertEdges', 'INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance) VALUES ', '(?,?,?,?,?,?,?)', rows);
356
+ }
357
+ if (bundle.refs.length > 0)
358
+ this.insertUnresolvedRefsBatch(bundle.refs);
359
+ this.upsertFile(bundle.file);
360
+ })();
361
+ }
283
362
  /**
284
363
  * Update an existing node
285
364
  */
286
365
  updateNode(node) {
287
366
  if (!this.stmts.updateNode) {
288
- this.stmts.updateNode = this.db.prepare(`
289
- UPDATE nodes SET
290
- kind = @kind,
291
- name = @name,
292
- qualified_name = @qualifiedName,
293
- file_path = @filePath,
294
- language = @language,
295
- start_line = @startLine,
296
- end_line = @endLine,
297
- start_column = @startColumn,
298
- end_column = @endColumn,
299
- docstring = @docstring,
300
- signature = @signature,
301
- visibility = @visibility,
302
- is_exported = @isExported,
303
- is_async = @isAsync,
304
- is_static = @isStatic,
305
- is_abstract = @isAbstract,
306
- decorators = @decorators,
307
- type_parameters = @typeParameters,
308
- return_type = @returnType,
309
- updated_at = @updatedAt
310
- WHERE id = @id
367
+ this.stmts.updateNode = this.db.prepare(`
368
+ UPDATE nodes SET
369
+ kind = @kind,
370
+ name = @name,
371
+ qualified_name = @qualifiedName,
372
+ file_path = @filePath,
373
+ language = @language,
374
+ start_line = @startLine,
375
+ end_line = @endLine,
376
+ start_column = @startColumn,
377
+ end_column = @endColumn,
378
+ docstring = @docstring,
379
+ signature = @signature,
380
+ visibility = @visibility,
381
+ is_exported = @isExported,
382
+ is_async = @isAsync,
383
+ is_static = @isStatic,
384
+ is_abstract = @isAbstract,
385
+ decorators = @decorators,
386
+ type_parameters = @typeParameters,
387
+ return_type = @returnType,
388
+ updated_at = @updatedAt
389
+ WHERE id = @id
311
390
  `);
312
391
  }
313
392
  // Invalidate cache before update
@@ -439,12 +518,12 @@ class QueryBuilder {
439
518
  const placeholders = variants.map(() => '?').join(', ');
440
519
  const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
441
520
  const rows = this.db
442
- .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
443
- FROM name_segment_vocab
444
- WHERE segment IN (${placeholders})
445
- GROUP BY name
446
- HAVING matches >= ?
447
- ORDER BY matches DESC, length(name) ASC
521
+ .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
522
+ FROM name_segment_vocab
523
+ WHERE segment IN (${placeholders})
524
+ GROUP BY name
525
+ HAVING matches >= ?
526
+ ORDER BY matches DESC, length(name) ASC
448
527
  LIMIT ?`)
449
528
  .all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
450
529
  return rows;
@@ -456,7 +535,7 @@ class QueryBuilder {
456
535
  return new Map();
457
536
  const placeholders = segments.map(() => '?').join(', ');
458
537
  const rows = this.db
459
- .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
538
+ .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
460
539
  WHERE segment IN (${placeholders}) GROUP BY segment`)
461
540
  .all(...segments);
462
541
  return new Map(rows.map((r) => [r.segment, r.n]));
@@ -616,15 +695,15 @@ class QueryBuilder {
616
695
  // protobuf stub) outranks the real `server/etcdserver/server.go`
617
696
  // (470 edges) by 4×, and the boost would push the agent toward
618
697
  // generated code.
619
- this.stmts.getDominantFile = this.db.prepare(`
620
- SELECT n.file_path AS file_path, COUNT(*) AS edge_count
621
- FROM edges e
622
- JOIN nodes n ON e.source = n.id
623
- JOIN nodes m ON e.target = m.id
624
- WHERE n.file_path = m.file_path
625
- GROUP BY n.file_path
626
- ORDER BY edge_count DESC
627
- LIMIT 20
698
+ this.stmts.getDominantFile = this.db.prepare(`
699
+ SELECT n.file_path AS file_path, COUNT(*) AS edge_count
700
+ FROM edges e
701
+ JOIN nodes n ON e.source = n.id
702
+ JOIN nodes m ON e.target = m.id
703
+ WHERE n.file_path = m.file_path
704
+ GROUP BY n.file_path
705
+ ORDER BY edge_count DESC
706
+ LIMIT 20
628
707
  `);
629
708
  }
630
709
  const rows = this.stmts.getDominantFile.all();
@@ -651,13 +730,13 @@ class QueryBuilder {
651
730
  */
652
731
  getTopRouteFile() {
653
732
  if (!this.stmts.getTopRouteFile) {
654
- this.stmts.getTopRouteFile = this.db.prepare(`
655
- SELECT file_path, COUNT(*) AS cnt
656
- FROM nodes
657
- WHERE kind = 'route'
658
- GROUP BY file_path
659
- ORDER BY cnt DESC
660
- LIMIT 20
733
+ this.stmts.getTopRouteFile = this.db.prepare(`
734
+ SELECT file_path, COUNT(*) AS cnt
735
+ FROM nodes
736
+ WHERE kind = 'route'
737
+ GROUP BY file_path
738
+ ORDER BY cnt DESC
739
+ LIMIT 20
661
740
  `);
662
741
  }
663
742
  const rows = this.stmts.getTopRouteFile.all();
@@ -688,21 +767,21 @@ class QueryBuilder {
688
767
  // Edge kind varies across framework resolvers: Spring/Rails/
689
768
  // Laravel/Drupal emit `references`, Express emits `calls`. Accept
690
769
  // both — the semantic is the same (route → its handler).
691
- this.stmts.getRoutingManifest = this.db.prepare(`
692
- SELECT
693
- r.name AS url,
694
- h.name AS handler,
695
- h.file_path AS handler_file,
696
- h.start_line AS handler_line,
697
- h.kind AS handler_kind
698
- FROM nodes r
699
- JOIN edges e ON e.source = r.id
700
- JOIN nodes h ON e.target = h.id
701
- WHERE r.kind = 'route'
702
- AND e.kind IN ('references', 'calls')
703
- AND h.kind IN ('function', 'method', 'class')
704
- ORDER BY r.file_path, r.start_line
705
- LIMIT ?
770
+ this.stmts.getRoutingManifest = this.db.prepare(`
771
+ SELECT
772
+ r.name AS url,
773
+ h.name AS handler,
774
+ h.file_path AS handler_file,
775
+ h.start_line AS handler_line,
776
+ h.kind AS handler_kind
777
+ FROM nodes r
778
+ JOIN edges e ON e.source = r.id
779
+ JOIN nodes h ON e.target = h.id
780
+ WHERE r.kind = 'route'
781
+ AND e.kind IN ('references', 'calls')
782
+ AND h.kind IN ('function', 'method', 'class')
783
+ ORDER BY r.file_path, r.start_line
784
+ LIMIT ?
706
785
  `);
707
786
  }
708
787
  const rows = this.stmts.getRoutingManifest.all(limit);
@@ -957,10 +1036,10 @@ class QueryBuilder {
957
1036
  const seen = new Set(existing.map((r) => r.node.id));
958
1037
  const merged = [...existing];
959
1038
  const apiLimit = Math.min(20, Math.max(5, Math.floor(limit / 4)));
960
- let sql = `
961
- SELECT nodes.*, 0.9 as score
962
- FROM ohos_api.nodes
963
- WHERE (name LIKE ? OR qualified_name LIKE ?)
1039
+ let sql = `
1040
+ SELECT nodes.*, 0.9 as score
1041
+ FROM ohos_api.nodes
1042
+ WHERE (name LIKE ? OR qualified_name LIKE ?)
964
1043
  `;
965
1044
  const pattern = `%${text}%`;
966
1045
  const params = [pattern, pattern];
@@ -1099,11 +1178,11 @@ class QueryBuilder {
1099
1178
  // Fetch 5x requested limit so post-hoc rescoring (kindBonus, pathRelevance,
1100
1179
  // nameMatchBonus) can promote results that BM25 alone undervalues.
1101
1180
  const ftsLimit = Math.max(limit * 5, 100);
1102
- let sql = `
1103
- SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1104
- FROM nodes_fts
1105
- JOIN nodes ON nodes_fts.id = nodes.id
1106
- WHERE nodes_fts MATCH ?
1181
+ let sql = `
1182
+ SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1183
+ FROM nodes_fts
1184
+ JOIN nodes ON nodes_fts.id = nodes.id
1185
+ WHERE nodes_fts MATCH ?
1107
1186
  `;
1108
1187
  const params = [ftsQuery];
1109
1188
  if (kinds && kinds.length > 0) {
@@ -1134,21 +1213,21 @@ class QueryBuilder {
1134
1213
  */
1135
1214
  searchNodesLike(query, options) {
1136
1215
  const { kinds, languages, limit = 100, offset = 0 } = options;
1137
- let sql = `
1138
- SELECT nodes.*,
1139
- CASE
1140
- WHEN name = ? THEN 1.0
1141
- WHEN name LIKE ? THEN 0.9
1142
- WHEN name LIKE ? THEN 0.8
1143
- WHEN qualified_name LIKE ? THEN 0.7
1144
- ELSE 0.5
1145
- END as score
1146
- FROM nodes
1147
- WHERE (
1148
- name LIKE ? OR
1149
- qualified_name LIKE ? OR
1150
- name LIKE ?
1151
- )
1216
+ let sql = `
1217
+ SELECT nodes.*,
1218
+ CASE
1219
+ WHEN name = ? THEN 1.0
1220
+ WHEN name LIKE ? THEN 0.9
1221
+ WHEN name LIKE ? THEN 0.8
1222
+ WHEN qualified_name LIKE ? THEN 0.7
1223
+ ELSE 0.5
1224
+ END as score
1225
+ FROM nodes
1226
+ WHERE (
1227
+ name LIKE ? OR
1228
+ qualified_name LIKE ? OR
1229
+ name LIKE ?
1230
+ )
1152
1231
  `;
1153
1232
  // Pattern variants for better matching
1154
1233
  const exactMatch = query;
@@ -1222,10 +1301,10 @@ class QueryBuilder {
1222
1301
  const allResults = [];
1223
1302
  const seenIds = new Set();
1224
1303
  for (const name of names) {
1225
- let sql = `
1226
- SELECT nodes.*, 1.0 as score
1227
- FROM nodes
1228
- WHERE name COLLATE NOCASE = ?
1304
+ let sql = `
1305
+ SELECT nodes.*, 1.0 as score
1306
+ FROM nodes
1307
+ WHERE name COLLATE NOCASE = ?
1229
1308
  `;
1230
1309
  const params = [name];
1231
1310
  if (kinds && kinds.length > 0) {
@@ -1256,10 +1335,10 @@ class QueryBuilder {
1256
1335
  allResults.push(r);
1257
1336
  }
1258
1337
  if (this.hasOhosApiAttached()) {
1259
- let apiSql = `
1260
- SELECT nodes.*, 0.95 as score
1261
- FROM ohos_api.nodes
1262
- WHERE name COLLATE NOCASE = ?
1338
+ let apiSql = `
1339
+ SELECT nodes.*, 0.95 as score
1340
+ FROM ohos_api.nodes
1341
+ WHERE name COLLATE NOCASE = ?
1263
1342
  `;
1264
1343
  const apiParams = [name];
1265
1344
  if (kinds && kinds.length > 0) {
@@ -1295,10 +1374,10 @@ class QueryBuilder {
1295
1374
  */
1296
1375
  findNodesByNameSubstring(substring, options = {}) {
1297
1376
  const { kinds, languages, limit = 30, excludePrefix } = options;
1298
- let sql = `
1299
- SELECT nodes.*, 1.0 as score
1300
- FROM nodes
1301
- WHERE name LIKE ?
1377
+ let sql = `
1378
+ SELECT nodes.*, 1.0 as score
1379
+ FROM nodes
1380
+ WHERE name LIKE ?
1302
1381
  `;
1303
1382
  const params = [`%${substring}%`];
1304
1383
  // Exclude prefix matches (handled by FTS-based prefix search in Step 2b)
@@ -1330,9 +1409,9 @@ class QueryBuilder {
1330
1409
  */
1331
1410
  insertEdge(edge) {
1332
1411
  if (!this.stmts.insertEdge) {
1333
- this.stmts.insertEdge = this.db.prepare(`
1334
- INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
1335
- VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
1412
+ this.stmts.insertEdge = this.db.prepare(`
1413
+ INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
1414
+ VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
1336
1415
  `);
1337
1416
  }
1338
1417
  this.stmts.insertEdge.run({
@@ -1459,12 +1538,12 @@ class QueryBuilder {
1459
1538
  * it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
1460
1539
  */
1461
1540
  getDependentFilePaths(filePath) {
1462
- const sql = `SELECT DISTINCT src.file_path AS fp
1463
- FROM edges e
1464
- JOIN nodes tgt ON tgt.id = e.target
1465
- JOIN nodes src ON src.id = e.source
1466
- WHERE tgt.file_path = ?
1467
- AND e.kind != 'contains'
1541
+ const sql = `SELECT DISTINCT src.file_path AS fp
1542
+ FROM edges e
1543
+ JOIN nodes tgt ON tgt.id = e.target
1544
+ JOIN nodes src ON src.id = e.source
1545
+ WHERE tgt.file_path = ?
1546
+ AND e.kind != 'contains'
1468
1547
  AND src.file_path != ?`;
1469
1548
  const rows = this.db.prepare(sql).all(filePath, filePath);
1470
1549
  return rows.map((r) => r.fp);
@@ -1476,12 +1555,12 @@ class QueryBuilder {
1476
1555
  * (all kinds except `contains`); same reason imports-only is insufficient.
1477
1556
  */
1478
1557
  getDependencyFilePaths(filePath) {
1479
- const sql = `SELECT DISTINCT tgt.file_path AS fp
1480
- FROM edges e
1481
- JOIN nodes src ON src.id = e.source
1482
- JOIN nodes tgt ON tgt.id = e.target
1483
- WHERE src.file_path = ?
1484
- AND e.kind != 'contains'
1558
+ const sql = `SELECT DISTINCT tgt.file_path AS fp
1559
+ FROM edges e
1560
+ JOIN nodes src ON src.id = e.source
1561
+ JOIN nodes tgt ON tgt.id = e.target
1562
+ WHERE src.file_path = ?
1563
+ AND e.kind != 'contains'
1485
1564
  AND tgt.file_path != ?`;
1486
1565
  const rows = this.db.prepare(sql).all(filePath, filePath);
1487
1566
  return rows.map((r) => r.fp);
@@ -1497,13 +1576,13 @@ class QueryBuilder {
1497
1576
  * {@link getDependentFilePaths}: all kinds except `contains`.
1498
1577
  */
1499
1578
  getCrossFileIncomingEdgesWithTarget(filePath) {
1500
- const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1501
- src.file_path AS source_file_path, src.language AS source_language
1502
- FROM edges e
1503
- JOIN nodes tgt ON tgt.id = e.target
1504
- JOIN nodes src ON src.id = e.source
1505
- WHERE tgt.file_path = ?
1506
- AND e.kind != 'contains'
1579
+ const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1580
+ src.file_path AS source_file_path, src.language AS source_language
1581
+ FROM edges e
1582
+ JOIN nodes tgt ON tgt.id = e.target
1583
+ JOIN nodes src ON src.id = e.source
1584
+ WHERE tgt.file_path = ?
1585
+ AND e.kind != 'contains'
1507
1586
  AND src.file_path != ?`;
1508
1587
  const rows = this.db.prepare(sql).all(filePath, filePath);
1509
1588
  return rows.map(row => ({
@@ -1520,10 +1599,10 @@ class QueryBuilder {
1520
1599
  */
1521
1600
  deleteArkTSCrossFileCallEdges() {
1522
1601
  const result = this.db
1523
- .prepare(`DELETE FROM edges
1524
- WHERE kind = 'calls'
1525
- AND provenance = 'heuristic'
1526
- AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
1602
+ .prepare(`DELETE FROM edges
1603
+ WHERE kind = 'calls'
1604
+ AND provenance = 'heuristic'
1605
+ AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
1527
1606
  AND metadata LIKE '%"sourceFile"%'`)
1528
1607
  .run();
1529
1608
  return result.changes;
@@ -1536,17 +1615,17 @@ class QueryBuilder {
1536
1615
  */
1537
1616
  upsertFile(file) {
1538
1617
  if (!this.stmts.upsertFile) {
1539
- this.stmts.upsertFile = this.db.prepare(`
1540
- INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors)
1541
- VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors)
1542
- ON CONFLICT(path) DO UPDATE SET
1543
- content_hash = @contentHash,
1544
- language = @language,
1545
- size = @size,
1546
- modified_at = @modifiedAt,
1547
- indexed_at = @indexedAt,
1548
- node_count = @nodeCount,
1549
- errors = @errors
1618
+ this.stmts.upsertFile = this.db.prepare(`
1619
+ INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors)
1620
+ VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors)
1621
+ ON CONFLICT(path) DO UPDATE SET
1622
+ content_hash = @contentHash,
1623
+ language = @language,
1624
+ size = @size,
1625
+ modified_at = @modifiedAt,
1626
+ indexed_at = @indexedAt,
1627
+ node_count = @nodeCount,
1628
+ errors = @errors
1550
1629
  `);
1551
1630
  }
1552
1631
  this.stmts.upsertFile.run({
@@ -1620,9 +1699,9 @@ class QueryBuilder {
1620
1699
  */
1621
1700
  insertUnresolvedRef(ref) {
1622
1701
  if (!this.stmts.insertUnresolved) {
1623
- this.stmts.insertUnresolved = this.db.prepare(`
1624
- INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
1625
- VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
1702
+ this.stmts.insertUnresolved = this.db.prepare(`
1703
+ INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
1704
+ VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
1626
1705
  `);
1627
1706
  }
1628
1707
  this.stmts.insertUnresolved.run({
@@ -1709,7 +1788,7 @@ class QueryBuilder {
1709
1788
  */
1710
1789
  getUnresolvedReferencesBatch(offset, limit) {
1711
1790
  if (!this.stmts.getUnresolvedBatch) {
1712
- this.stmts.getUnresolvedBatch = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' LIMIT ? OFFSET ?");
1791
+ this.stmts.getUnresolvedBatch = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' ORDER BY rowid LIMIT ? OFFSET ?");
1713
1792
  }
1714
1793
  const rows = this.stmts.getUnresolvedBatch.all(limit, offset);
1715
1794
  return rows.map((row) => ({
@@ -1721,6 +1800,32 @@ class QueryBuilder {
1721
1800
  candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1722
1801
  filePath: row.file_path,
1723
1802
  language: row.language,
1803
+ rowId: row.id,
1804
+ }));
1805
+ }
1806
+ /**
1807
+ * Keyset variant of {@link getUnresolvedReferencesBatch} for the batched
1808
+ * resolution loop: seek past the last-seen row id instead of OFFSET-walking.
1809
+ * OFFSET reads re-scan the accumulated failed-row prefix on every batch —
1810
+ * O(failed rows) per read, measured at 54.6s of the kernel-scale batch loop
1811
+ * (§7a.2) — while the seek is O(batch) forever. `id` is the rowid alias, so
1812
+ * the enumeration order is identical to the OFFSET reader's.
1813
+ */
1814
+ getUnresolvedReferencesBatchAfter(afterRowId, limit) {
1815
+ if (!this.stmts.getUnresolvedBatchAfter) {
1816
+ this.stmts.getUnresolvedBatchAfter = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' AND id > ? ORDER BY id LIMIT ?");
1817
+ }
1818
+ const rows = this.stmts.getUnresolvedBatchAfter.all(afterRowId, limit);
1819
+ return rows.map((row) => ({
1820
+ fromNodeId: row.from_node_id,
1821
+ referenceName: row.reference_name,
1822
+ referenceKind: row.reference_kind,
1823
+ line: row.line,
1824
+ column: row.col,
1825
+ candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1826
+ filePath: row.file_path,
1827
+ language: row.language,
1828
+ rowId: row.id,
1724
1829
  }));
1725
1830
  }
1726
1831
  /**
@@ -1759,14 +1864,16 @@ class QueryBuilder {
1759
1864
  */
1760
1865
  markReferencesFailed(refs) {
1761
1866
  if (refs.length === 0)
1762
- return;
1867
+ return 0;
1763
1868
  const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?");
1869
+ let changed = 0;
1764
1870
  const markMany = this.db.transaction((items) => {
1765
1871
  for (const ref of items) {
1766
- stmt.run(referenceNameTail(ref.referenceName), ref.fromNodeId, ref.referenceName, ref.referenceKind);
1872
+ changed += stmt.run(referenceNameTail(ref.referenceName), ref.fromNodeId, ref.referenceName, ref.referenceKind).changes;
1767
1873
  }
1768
1874
  });
1769
1875
  markMany(refs);
1876
+ return changed;
1770
1877
  }
1771
1878
  /**
1772
1879
  * Delete unresolved-ref rows by row id — the precise cleanup for refs a
@@ -1778,12 +1885,25 @@ class QueryBuilder {
1778
1885
  */
1779
1886
  deleteReferencesByRowIds(rowIds) {
1780
1887
  if (rowIds.length === 0)
1781
- return;
1782
- for (let i = 0; i < rowIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1783
- const chunk = rowIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1784
- const placeholders = chunk.map(() => '?').join(',');
1785
- this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`).run(...chunk);
1786
- }
1888
+ return 0;
1889
+ let changed = 0;
1890
+ this.db.transaction(() => {
1891
+ for (let i = 0; i < rowIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1892
+ const chunk = rowIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1893
+ if (chunk.length === SQLITE_PARAM_CHUNK_SIZE) {
1894
+ if (!this.stmts.deleteRefsByRowIdsFull) {
1895
+ const placeholders = new Array(SQLITE_PARAM_CHUNK_SIZE).fill('?').join(',');
1896
+ this.stmts.deleteRefsByRowIdsFull = this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`);
1897
+ }
1898
+ changed += this.stmts.deleteRefsByRowIdsFull.run(...chunk).changes;
1899
+ }
1900
+ else {
1901
+ const placeholders = chunk.map(() => '?').join(',');
1902
+ changed += this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`).run(...chunk).changes;
1903
+ }
1904
+ }
1905
+ })();
1906
+ return changed;
1787
1907
  }
1788
1908
  /**
1789
1909
  * Park refs as status='failed' by row id — the precise counterpart of
@@ -1795,14 +1915,16 @@ class QueryBuilder {
1795
1915
  */
1796
1916
  markReferencesFailedByRowIds(refs) {
1797
1917
  if (refs.length === 0)
1798
- return;
1918
+ return 0;
1799
1919
  const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE id = ?");
1920
+ let changed = 0;
1800
1921
  const markMany = this.db.transaction((items) => {
1801
1922
  for (const ref of items) {
1802
- stmt.run(referenceNameTail(ref.referenceName), ref.rowId);
1923
+ changed += stmt.run(referenceNameTail(ref.referenceName), ref.rowId).changes;
1803
1924
  }
1804
1925
  });
1805
1926
  markMany(refs);
1927
+ return changed;
1806
1928
  }
1807
1929
  /**
1808
1930
  * Failed refs whose name tail matches one of the given symbol names — the
@@ -1919,7 +2041,7 @@ class QueryBuilder {
1919
2041
  // this file. The internal resolution path uses deleteSpecificResolvedReferences
1920
2042
  // instead, but QueryBuilder is part of the public API, so a library consumer
1921
2043
  // passing more ids than SQLITE_MAX_VARIABLE_NUMBER (32766 on the bundled
1922
- // node:sqlite) would otherwise hit "too many SQL variables". (#540, #1001)
2044
+ // SQLite would otherwise hit "too many SQL variables". (#540, #1001)
1923
2045
  for (let i = 0; i < fromNodeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1924
2046
  const chunk = fromNodeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1925
2047
  const placeholders = chunk.map(() => '?').join(',');
@@ -1932,14 +2054,16 @@ class QueryBuilder {
1932
2054
  */
1933
2055
  deleteSpecificResolvedReferences(refs) {
1934
2056
  if (refs.length === 0)
1935
- return;
2057
+ return 0;
1936
2058
  const stmt = this.db.prepare('DELETE FROM unresolved_refs WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?');
2059
+ let changed = 0;
1937
2060
  const deleteMany = this.db.transaction((items) => {
1938
2061
  for (const ref of items) {
1939
- stmt.run(ref.fromNodeId, ref.referenceName, ref.referenceKind);
2062
+ changed += stmt.run(ref.fromNodeId, ref.referenceName, ref.referenceKind).changes;
1940
2063
  }
1941
2064
  });
1942
2065
  deleteMany(refs);
2066
+ return changed;
1943
2067
  }
1944
2068
  // ===========================================================================
1945
2069
  // Statistics
@@ -1961,11 +2085,11 @@ class QueryBuilder {
1961
2085
  */
1962
2086
  getStats() {
1963
2087
  // Single query for all three aggregate counts
1964
- const counts = this.db.prepare(`
1965
- SELECT
1966
- (SELECT COUNT(*) FROM nodes) AS node_count,
1967
- (SELECT COUNT(*) FROM edges) AS edge_count,
1968
- (SELECT COUNT(*) FROM files) AS file_count
2088
+ const counts = this.db.prepare(`
2089
+ SELECT
2090
+ (SELECT COUNT(*) FROM nodes) AS node_count,
2091
+ (SELECT COUNT(*) FROM edges) AS edge_count,
2092
+ (SELECT COUNT(*) FROM files) AS file_count
1969
2093
  `).get();
1970
2094
  const nodesByKind = {};
1971
2095
  const nodeKindRows = this.db