homegraph 1.5.1 → 1.5.3

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 (382) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/LICENSE +21 -21
  3. package/README.md +312 -305
  4. package/dist/arkui/index.d.ts +4 -0
  5. package/dist/arkui/index.d.ts.map +1 -0
  6. package/dist/arkui/index.js +23 -0
  7. package/dist/arkui/index.js.map +1 -0
  8. package/dist/arkui/migrate-passage.d.ts +28 -0
  9. package/dist/arkui/migrate-passage.d.ts.map +1 -0
  10. package/dist/arkui/migrate-passage.js +310 -0
  11. package/dist/arkui/migrate-passage.js.map +1 -0
  12. package/dist/arkui/migrate-semantics.d.ts +47 -0
  13. package/dist/arkui/migrate-semantics.d.ts.map +1 -0
  14. package/dist/arkui/migrate-semantics.js +229 -0
  15. package/dist/arkui/migrate-semantics.js.map +1 -0
  16. package/dist/arkui/migrate-snapshot.d.ts +79 -0
  17. package/dist/arkui/migrate-snapshot.d.ts.map +1 -0
  18. package/dist/arkui/migrate-snapshot.js +340 -0
  19. package/dist/arkui/migrate-snapshot.js.map +1 -0
  20. package/dist/bin/fatal-handler.js +2 -2
  21. package/dist/bin/homegraph.js +111 -162
  22. package/dist/bin/homegraph.js.map +1 -1
  23. package/dist/bin/node-version-check.d.ts +6 -15
  24. package/dist/bin/node-version-check.d.ts.map +1 -1
  25. package/dist/bin/node-version-check.js +8 -37
  26. package/dist/bin/node-version-check.js.map +1 -1
  27. package/dist/db/index.d.ts +36 -1
  28. package/dist/db/index.d.ts.map +1 -1
  29. package/dist/db/index.js +124 -38
  30. package/dist/db/index.js.map +1 -1
  31. package/dist/db/migrations.d.ts +1 -1
  32. package/dist/db/migrations.d.ts.map +1 -1
  33. package/dist/db/migrations.js +52 -38
  34. package/dist/db/migrations.js.map +1 -1
  35. package/dist/db/queries.d.ts +42 -0
  36. package/dist/db/queries.d.ts.map +1 -1
  37. package/dist/db/queries.js +330 -163
  38. package/dist/db/queries.js.map +1 -1
  39. package/dist/db/schema.sql +208 -203
  40. package/dist/db/sqlite-adapter.d.ts +8 -3
  41. package/dist/db/sqlite-adapter.d.ts.map +1 -1
  42. package/dist/db/sqlite-adapter.js +45 -3
  43. package/dist/db/sqlite-adapter.js.map +1 -1
  44. package/dist/directory.js +5 -5
  45. package/dist/extraction/extraction-version.d.ts +1 -1
  46. package/dist/extraction/extraction-version.js +1 -1
  47. package/dist/extraction/generated-detection.d.ts +42 -11
  48. package/dist/extraction/generated-detection.d.ts.map +1 -1
  49. package/dist/extraction/generated-detection.js +141 -20
  50. package/dist/extraction/generated-detection.js.map +1 -1
  51. package/dist/extraction/index.d.ts +43 -1
  52. package/dist/extraction/index.d.ts.map +1 -1
  53. package/dist/extraction/index.js +150 -43
  54. package/dist/extraction/index.js.map +1 -1
  55. package/dist/extraction/languages/arkts.d.ts +70 -6
  56. package/dist/extraction/languages/arkts.d.ts.map +1 -1
  57. package/dist/extraction/languages/arkts.js +958 -108
  58. package/dist/extraction/languages/arkts.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.map +1 -1
  69. package/dist/extraction/wasm-runtime-flags.js +9 -6
  70. package/dist/extraction/wasm-runtime-flags.js.map +1 -1
  71. package/dist/graph-sources.d.ts +41 -0
  72. package/dist/graph-sources.d.ts.map +1 -0
  73. package/dist/graph-sources.js +82 -0
  74. package/dist/graph-sources.js.map +1 -0
  75. package/dist/index.d.ts +19 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +80 -9
  78. package/dist/index.js.map +1 -1
  79. package/dist/installer/index.d.ts.map +1 -1
  80. package/dist/installer/index.js +0 -48
  81. package/dist/installer/index.js.map +1 -1
  82. package/dist/installer/instructions-template.js +9 -9
  83. package/dist/installer/targets/antigravity.js +1 -1
  84. package/dist/installer/targets/antigravity.js.map +1 -1
  85. package/dist/installer/targets/deveco.js +1 -1
  86. package/dist/installer/targets/deveco.js.map +1 -1
  87. package/dist/installer/targets/hermes.d.ts +1 -1
  88. package/dist/installer/targets/hermes.js +2 -2
  89. package/dist/installer/targets/hermes.js.map +1 -1
  90. package/dist/installer/targets/opencode.js +1 -1
  91. package/dist/installer/targets/opencode.js.map +1 -1
  92. package/dist/installer/targets/shared.js +1 -1
  93. package/dist/installer/targets/shared.js.map +1 -1
  94. package/dist/mcp/daemon-paths.d.ts +5 -4
  95. package/dist/mcp/daemon-paths.d.ts.map +1 -1
  96. package/dist/mcp/daemon-paths.js +28 -13
  97. package/dist/mcp/daemon-paths.js.map +1 -1
  98. package/dist/mcp/daemon-registry.d.ts.map +1 -1
  99. package/dist/mcp/daemon-registry.js +4 -1
  100. package/dist/mcp/daemon-registry.js.map +1 -1
  101. package/dist/mcp/daemon.d.ts +1 -1
  102. package/dist/mcp/daemon.js +1 -1
  103. package/dist/mcp/diff-impact.d.ts +131 -0
  104. package/dist/mcp/diff-impact.d.ts.map +1 -0
  105. package/dist/mcp/diff-impact.js +385 -0
  106. package/dist/mcp/diff-impact.js.map +1 -0
  107. package/dist/mcp/engine.d.ts.map +1 -1
  108. package/dist/mcp/engine.js +12 -3
  109. package/dist/mcp/engine.js.map +1 -1
  110. package/dist/mcp/explore-dedup.d.ts +137 -0
  111. package/dist/mcp/explore-dedup.d.ts.map +1 -0
  112. package/dist/mcp/explore-dedup.js +236 -0
  113. package/dist/mcp/explore-dedup.js.map +1 -0
  114. package/dist/mcp/explore-session-state.d.ts +217 -0
  115. package/dist/mcp/explore-session-state.d.ts.map +1 -0
  116. package/dist/mcp/explore-session-state.js +322 -0
  117. package/dist/mcp/explore-session-state.js.map +1 -0
  118. package/dist/mcp/index.d.ts.map +1 -1
  119. package/dist/mcp/index.js +4 -7
  120. package/dist/mcp/index.js.map +1 -1
  121. package/dist/mcp/liveness-watchdog.js +51 -51
  122. package/dist/mcp/proxy.d.ts.map +1 -1
  123. package/dist/mcp/proxy.js +5 -14
  124. package/dist/mcp/proxy.js.map +1 -1
  125. package/dist/mcp/query-worker.d.ts +1 -1
  126. package/dist/mcp/query-worker.js +1 -1
  127. package/dist/mcp/server-instructions.d.ts +7 -2
  128. package/dist/mcp/server-instructions.d.ts.map +1 -1
  129. package/dist/mcp/server-instructions.js +125 -47
  130. package/dist/mcp/server-instructions.js.map +1 -1
  131. package/dist/mcp/session.d.ts +14 -3
  132. package/dist/mcp/session.d.ts.map +1 -1
  133. package/dist/mcp/session.js +17 -14
  134. package/dist/mcp/session.js.map +1 -1
  135. package/dist/mcp/startup-handshake.d.ts +1 -1
  136. package/dist/mcp/startup-handshake.js +1 -1
  137. package/dist/mcp/tools.d.ts +138 -12
  138. package/dist/mcp/tools.d.ts.map +1 -1
  139. package/dist/mcp/tools.js +3279 -476
  140. package/dist/mcp/tools.js.map +1 -1
  141. package/dist/resolution/callback-synthesizer.d.ts +2 -1
  142. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  143. package/dist/resolution/callback-synthesizer.js +153 -53
  144. package/dist/resolution/callback-synthesizer.js.map +1 -1
  145. package/dist/resolution/frameworks/arkts-entry.d.ts.map +1 -1
  146. package/dist/resolution/frameworks/arkts-entry.js +20 -9
  147. package/dist/resolution/frameworks/arkts-entry.js.map +1 -1
  148. package/dist/resolution/frameworks/arkts-napi.d.ts +14 -0
  149. package/dist/resolution/frameworks/arkts-napi.d.ts.map +1 -1
  150. package/dist/resolution/frameworks/arkts-napi.js +169 -49
  151. package/dist/resolution/frameworks/arkts-napi.js.map +1 -1
  152. package/dist/resolution/index.d.ts.map +1 -1
  153. package/dist/resolution/index.js +1 -1
  154. package/dist/resolution/index.js.map +1 -1
  155. package/dist/resolution/memory-budget.d.ts +33 -0
  156. package/dist/resolution/memory-budget.d.ts.map +1 -1
  157. package/dist/resolution/memory-budget.js +58 -0
  158. package/dist/resolution/memory-budget.js.map +1 -1
  159. package/dist/resolution/resolver-pool.d.ts +2 -0
  160. package/dist/resolution/resolver-pool.d.ts.map +1 -1
  161. package/dist/resolution/resolver-pool.js +4 -0
  162. package/dist/resolution/resolver-pool.js.map +1 -1
  163. package/dist/search/query-utils.d.ts +116 -4
  164. package/dist/search/query-utils.d.ts.map +1 -1
  165. package/dist/search/query-utils.js +869 -60
  166. package/dist/search/query-utils.js.map +1 -1
  167. package/dist/spec/db/commit-node.js +4 -4
  168. package/dist/spec/db/fragment-node.js +10 -10
  169. package/dist/spec/db/fts.js +8 -8
  170. package/dist/spec/db/relations.js +88 -88
  171. package/dist/spec/db/schema.js +6 -6
  172. package/dist/spec/db/schema.sql +121 -121
  173. package/dist/spec/db/spec-node.js +4 -4
  174. package/dist/spec/llm/prompts.js +53 -53
  175. package/dist/types.d.ts +8 -0
  176. package/dist/types.d.ts.map +1 -1
  177. package/dist/ui/shimmer-progress.d.ts.map +1 -1
  178. package/dist/ui/shimmer-progress.js +4 -1
  179. package/dist/ui/shimmer-progress.js.map +1 -1
  180. package/dist/upgrade/index.d.ts +14 -26
  181. package/dist/upgrade/index.d.ts.map +1 -1
  182. package/dist/upgrade/index.js +28 -123
  183. package/dist/upgrade/index.js.map +1 -1
  184. package/dist/upgrade/remove-binary.d.ts +19 -19
  185. package/dist/upgrade/remove-binary.d.ts.map +1 -1
  186. package/dist/upgrade/remove-binary.js +20 -21
  187. package/dist/upgrade/remove-binary.js.map +1 -1
  188. package/dist/upgrade/update-check.d.ts +4 -3
  189. package/dist/upgrade/update-check.d.ts.map +1 -1
  190. package/dist/upgrade/update-check.js +4 -3
  191. package/dist/upgrade/update-check.js.map +1 -1
  192. package/package.json +65 -62
  193. package/dist/extraction/languages/arkts-viewtree.d.ts +0 -22
  194. package/dist/extraction/languages/arkts-viewtree.d.ts.map +0 -1
  195. package/dist/extraction/languages/arkts-viewtree.js +0 -133
  196. package/dist/extraction/languages/arkts-viewtree.js.map +0 -1
  197. package/dist/reasoning/config.d.ts +0 -45
  198. package/dist/reasoning/config.d.ts.map +0 -1
  199. package/dist/reasoning/config.js +0 -171
  200. package/dist/reasoning/config.js.map +0 -1
  201. package/dist/reasoning/credentials.d.ts +0 -5
  202. package/dist/reasoning/credentials.d.ts.map +0 -1
  203. package/dist/reasoning/credentials.js +0 -83
  204. package/dist/reasoning/credentials.js.map +0 -1
  205. package/dist/reasoning/login.d.ts +0 -21
  206. package/dist/reasoning/login.d.ts.map +0 -1
  207. package/dist/reasoning/login.js +0 -85
  208. package/dist/reasoning/login.js.map +0 -1
  209. package/dist/reasoning/reasoner.d.ts +0 -43
  210. package/dist/reasoning/reasoner.d.ts.map +0 -1
  211. package/dist/reasoning/reasoner.js +0 -308
  212. package/dist/reasoning/reasoner.js.map +0 -1
  213. package/dist/spec/evolve/llm-client.d.ts +0 -50
  214. package/dist/spec/evolve/llm-client.d.ts.map +0 -1
  215. package/dist/spec/evolve/llm-client.js +0 -176
  216. package/dist/spec/evolve/llm-client.js.map +0 -1
  217. package/dist/spec/evolve/logic-checker.d.ts +0 -12
  218. package/dist/spec/evolve/logic-checker.d.ts.map +0 -1
  219. package/dist/spec/evolve/logic-checker.js +0 -24
  220. package/dist/spec/evolve/logic-checker.js.map +0 -1
  221. package/dist/spec/llm/index.d.ts +0 -3
  222. package/dist/spec/llm/index.d.ts.map +0 -1
  223. package/dist/spec/llm/index.js +0 -11
  224. package/dist/spec/llm/index.js.map +0 -1
  225. package/dist/spec/mining/diff-parser.d.ts +0 -33
  226. package/dist/spec/mining/diff-parser.d.ts.map +0 -1
  227. package/dist/spec/mining/diff-parser.js +0 -166
  228. package/dist/spec/mining/diff-parser.js.map +0 -1
  229. package/dist/spec/mining/git-scanner.d.ts +0 -103
  230. package/dist/spec/mining/git-scanner.d.ts.map +0 -1
  231. package/dist/spec/mining/git-scanner.js +0 -307
  232. package/dist/spec/mining/git-scanner.js.map +0 -1
  233. package/dist/spec/mining/pipeline.d.ts +0 -53
  234. package/dist/spec/mining/pipeline.d.ts.map +0 -1
  235. package/dist/spec/mining/pipeline.js +0 -178
  236. package/dist/spec/mining/pipeline.js.map +0 -1
  237. package/dist/spec/mining/scope-resolver.d.ts +0 -45
  238. package/dist/spec/mining/scope-resolver.d.ts.map +0 -1
  239. package/dist/spec/mining/scope-resolver.js +0 -103
  240. package/dist/spec/mining/scope-resolver.js.map +0 -1
  241. package/dist/spec/mining/spec-extractor.d.ts +0 -69
  242. package/dist/spec/mining/spec-extractor.d.ts.map +0 -1
  243. package/dist/spec/mining/spec-extractor.js +0 -369
  244. package/dist/spec/mining/spec-extractor.js.map +0 -1
  245. package/dist/spec/utils.d.ts +0 -167
  246. package/dist/spec/utils.d.ts.map +0 -1
  247. package/dist/spec/utils.js +0 -463
  248. package/dist/spec/utils.js.map +0 -1
  249. package/dist/telemetry/index.d.ts +0 -143
  250. package/dist/telemetry/index.d.ts.map +0 -1
  251. package/dist/telemetry/index.js +0 -541
  252. package/dist/telemetry/index.js.map +0 -1
  253. package/scripts/_tmp-cfwk-resolve.log +0 -0
  254. package/scripts/_tmp-cfwk-sig.log +0 -0
  255. package/scripts/_tmp-cfwk-vt.log +0 -0
  256. package/scripts/add-lang/bench.sh +0 -60
  257. package/scripts/add-lang/check-grammar.mjs +0 -75
  258. package/scripts/add-lang/dump-ast.mjs +0 -103
  259. package/scripts/add-lang/verify-extraction.mjs +0 -70
  260. package/scripts/agent-eval/ab-adoption.sh +0 -91
  261. package/scripts/agent-eval/ab-hook.sh +0 -86
  262. package/scripts/agent-eval/ab-impl.sh +0 -78
  263. package/scripts/agent-eval/ab-new-vs-baseline.sh +0 -102
  264. package/scripts/agent-eval/ab-sufficiency.sh +0 -78
  265. package/scripts/agent-eval/arms-F.sh +0 -21
  266. package/scripts/agent-eval/arms-matrix.sh +0 -37
  267. package/scripts/agent-eval/audit.sh +0 -68
  268. package/scripts/agent-eval/bench-readme.sh +0 -28
  269. package/scripts/agent-eval/bench-why-repo.sh +0 -22
  270. package/scripts/agent-eval/block-read-hook.sh +0 -19
  271. package/scripts/agent-eval/hook-settings.json +0 -15
  272. package/scripts/agent-eval/itrun.sh +0 -120
  273. package/scripts/agent-eval/offload-eval-3arm.sh +0 -72
  274. package/scripts/agent-eval/offload-eval-cost.mjs +0 -133
  275. package/scripts/agent-eval/offload-eval-effort.mjs +0 -108
  276. package/scripts/agent-eval/offload-eval-frontload-matrix.sh +0 -25
  277. package/scripts/agent-eval/offload-eval-frontload.sh +0 -47
  278. package/scripts/agent-eval/offload-eval-ground-truth.json +0 -18
  279. package/scripts/agent-eval/offload-eval-hook.mjs +0 -84
  280. package/scripts/agent-eval/offload-eval-judge.mjs +0 -103
  281. package/scripts/agent-eval/offload-eval-matrix.sh +0 -20
  282. package/scripts/agent-eval/offload-eval-metrics.mjs +0 -94
  283. package/scripts/agent-eval/offload-eval-refs1.sh +0 -50
  284. package/scripts/agent-eval/offload-eval-setup.sh +0 -24
  285. package/scripts/agent-eval/offload-eval-styles.sh +0 -72
  286. package/scripts/agent-eval/offload-eval-summarize.mjs +0 -68
  287. package/scripts/agent-eval/offload-eval.md +0 -76
  288. package/scripts/agent-eval/parse-arms.mjs +0 -116
  289. package/scripts/agent-eval/parse-bench-readme.mjs +0 -84
  290. package/scripts/agent-eval/parse-run.mjs +0 -45
  291. package/scripts/agent-eval/parse-session.mjs +0 -93
  292. package/scripts/agent-eval/probe-context.mjs +0 -21
  293. package/scripts/agent-eval/probe-explore.mjs +0 -40
  294. package/scripts/agent-eval/probe-node.mjs +0 -20
  295. package/scripts/agent-eval/probe-sweep.mjs +0 -119
  296. package/scripts/agent-eval/probe-trace.mjs +0 -20
  297. package/scripts/agent-eval/redirect-read-hook.sh +0 -38
  298. package/scripts/agent-eval/repro-concurrent-explore.mjs +0 -119
  299. package/scripts/agent-eval/repro-daemon-clients.mjs +0 -125
  300. package/scripts/agent-eval/run-agent.sh +0 -34
  301. package/scripts/agent-eval/run-all.sh +0 -75
  302. package/scripts/agent-eval/run-arms.sh +0 -56
  303. package/scripts/agent-eval/seq-matrix.mjs +0 -137
  304. package/scripts/bench-arkts-init-rss.log +0 -0
  305. package/scripts/build-bundle.sh +0 -123
  306. package/scripts/exp_boundary_eval/README.md +0 -247
  307. package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
  308. package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-38.pyc +0 -0
  309. package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
  310. package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-38.pyc +0 -0
  311. package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-38.pyc +0 -0
  312. package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-310.pyc +0 -0
  313. package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-38.pyc +0 -0
  314. package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
  315. package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-38.pyc +0 -0
  316. package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
  317. package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-38.pyc +0 -0
  318. package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
  319. package/scripts/exp_boundary_eval/__pycache__/setup.cpython-38.pyc +0 -0
  320. package/scripts/exp_boundary_eval/__pycache__/win_mcp_launcher.cpython-38.pyc +0 -0
  321. package/scripts/exp_boundary_eval/_test_mcp_chain.py +0 -78
  322. package/scripts/exp_boundary_eval/_test_stdin.py +0 -8
  323. package/scripts/exp_boundary_eval/_utils.py +0 -1116
  324. package/scripts/exp_boundary_eval/analyze.py +0 -1313
  325. package/scripts/exp_boundary_eval/deveco_arm.py +0 -519
  326. package/scripts/exp_boundary_eval/run_all.py +0 -378
  327. package/scripts/exp_boundary_eval/run_one.py +0 -165
  328. package/scripts/exp_boundary_eval/run_session.py +0 -158
  329. package/scripts/exp_boundary_eval/setup.py +0 -120
  330. package/scripts/exp_boundary_eval/win_mcp_launcher.py +0 -73
  331. package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +0 -36
  332. package/scripts/exp_boundary_eval/win_node_launcher.py +0 -24
  333. package/scripts/extract-release-notes.mjs +0 -130
  334. package/scripts/local-install.sh +0 -41
  335. package/scripts/npm-sdk.js +0 -75
  336. package/scripts/npm-shim.js +0 -275
  337. package/scripts/ohos-sdk-publish.mjs +0 -133
  338. package/scripts/pack-npm.sh +0 -119
  339. package/scripts/prepare-release.mjs +0 -270
  340. package/scripts/probe-arkts-mem-why-run.log +0 -0
  341. package/scripts/probe-banner-livecard-ir.log +0 -0
  342. package/scripts/probe-cfwk-ast.stderr.log +0 -0
  343. package/scripts/probe-cfwk-ast.stdout.log +0 -0
  344. package/scripts/probe-cfwk-attr-shape.log +0 -0
  345. package/scripts/probe-cfwk-cfgdump.stderr.log +0 -0
  346. package/scripts/probe-cfwk-cfgdump.stdout.log +0 -0
  347. package/scripts/probe-cfwk-cvc.stderr.log +0 -0
  348. package/scripts/probe-cfwk-cvc.stdout.log +0 -0
  349. package/scripts/probe-cfwk-diag2.log +0 -0
  350. package/scripts/probe-cfwk-diag3.log +0 -0
  351. package/scripts/probe-cfwk-fedbg.stderr.log +0 -0
  352. package/scripts/probe-cfwk-fedbg.stdout.log +0 -0
  353. package/scripts/probe-cfwk-fileresult.log +0 -0
  354. package/scripts/probe-cfwk-fix.stderr.log +0 -0
  355. package/scripts/probe-cfwk-fix.stdout.log +0 -0
  356. package/scripts/probe-cfwk-fix2.stderr.log +0 -0
  357. package/scripts/probe-cfwk-fix2.stdout.log +0 -0
  358. package/scripts/probe-cfwk-fix3.stderr.log +0 -0
  359. package/scripts/probe-cfwk-fix3.stdout.log +0 -0
  360. package/scripts/probe-cfwk-foreach.log +0 -0
  361. package/scripts/probe-cfwk-getmethod-throw.log +0 -0
  362. package/scripts/probe-cfwk-hg-extract.log +0 -0
  363. package/scripts/probe-cfwk-pr1003-noprior.stderr.log +0 -0
  364. package/scripts/probe-cfwk-pr1003-noprior.stdout.log +0 -0
  365. package/scripts/probe-cfwk-pr1003.stderr.log +0 -0
  366. package/scripts/probe-cfwk-pr1003.stdout.log +0 -0
  367. package/scripts/probe-cfwk-preroot-noprior.stderr.log +0 -0
  368. package/scripts/probe-cfwk-preroot-noprior.stdout.log +0 -0
  369. package/scripts/probe-cfwk-preroot-prior.stderr.log +0 -0
  370. package/scripts/probe-cfwk-preroot-prior.stdout.log +0 -0
  371. package/scripts/probe-cfwk-preroot-skipstate.stderr.log +0 -0
  372. package/scripts/probe-cfwk-preroot-skipstate.stdout.log +0 -0
  373. package/scripts/probe-cfwk-resolve-sim.log +0 -0
  374. package/scripts/probe-cfwk-tree-shape.log +0 -0
  375. package/scripts/probe-cfwk-walk-abort.log +0 -0
  376. package/scripts/probe-cfwk.log +0 -0
  377. package/scripts/probe-force-index.log +0 -0
  378. package/scripts/probe-no-force-index.log +0 -0
  379. package/scripts/probe-samefile-ir.stderr.log +0 -0
  380. package/scripts/probe-samefile-ir.stdout.log +0 -224
  381. package/scripts/probe-sdk-vs-project.log +0 -0
  382. package/scripts/probe-viewtree-downgrade.log +0 -0
@@ -133,6 +133,7 @@ function rowToFileRecord(row) {
133
133
  indexedAt: row.indexed_at,
134
134
  nodeCount: row.node_count,
135
135
  errors: row.errors ? (0, utils_1.safeJsonParse)(row.errors, undefined) : undefined,
136
+ generated: row.generated === 1,
136
137
  };
137
138
  }
138
139
  /**
@@ -152,6 +153,11 @@ class QueryBuilder {
152
153
  maxCacheSize = 1000;
153
154
  /** Attached prebuilt OHOS API db (see arkts.ts). */
154
155
  ohosApiDbPath = null;
156
+ /**
157
+ * When false, name/search lookups skip the project `nodes` table and only
158
+ * return attached `ohos_api` rows (`HOMEGRAPH_SOURCES=sdk`). Default true.
159
+ */
160
+ includeProjectNodes = true;
155
161
  // Prepared statements (lazily initialized)
156
162
  stmts = {};
157
163
  // Multi-row INSERT statements, cached per (statement kind × row count).
@@ -202,6 +208,16 @@ class QueryBuilder {
202
208
  this.stmts = {};
203
209
  this.batchStmts.clear();
204
210
  }
211
+ /**
212
+ * Toggle whether project-index nodes participate in lookups.
213
+ * SDK-only sessions set this false after opening the project db for ATTACH.
214
+ */
215
+ setIncludeProjectNodes(include) {
216
+ this.includeProjectNodes = include;
217
+ }
218
+ getIncludeProjectNodes() {
219
+ return this.includeProjectNodes;
220
+ }
205
221
  /** Attach a versioned OHOS API db for federated symbol lookup. */
206
222
  attachOhosApiDb(dbPath) {
207
223
  if (dbPath === this.ohosApiDbPath)
@@ -255,20 +271,20 @@ class QueryBuilder {
255
271
  */
256
272
  insertNode(node) {
257
273
  if (!this.stmts.insertNode) {
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
- )
274
+ this.stmts.insertNode = this.db.prepare(`
275
+ INSERT OR REPLACE INTO nodes (
276
+ id, kind, name, qualified_name, file_path, language,
277
+ start_line, end_line, start_column, end_column,
278
+ docstring, signature, visibility,
279
+ is_exported, is_async, is_static, is_abstract,
280
+ decorators, type_parameters, return_type, updated_at
281
+ ) VALUES (
282
+ @id, @kind, @name, @qualifiedName, @filePath, @language,
283
+ @startLine, @endLine, @startColumn, @endColumn,
284
+ @docstring, @signature, @visibility,
285
+ @isExported, @isAsync, @isStatic, @isAbstract,
286
+ @decorators, @typeParameters, @returnType, @updatedAt
287
+ )
272
288
  `);
273
289
  }
274
290
  // Validate required fields to prevent SQLite bind errors
@@ -364,29 +380,29 @@ class QueryBuilder {
364
380
  */
365
381
  updateNode(node) {
366
382
  if (!this.stmts.updateNode) {
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
383
+ this.stmts.updateNode = this.db.prepare(`
384
+ UPDATE nodes SET
385
+ kind = @kind,
386
+ name = @name,
387
+ qualified_name = @qualifiedName,
388
+ file_path = @filePath,
389
+ language = @language,
390
+ start_line = @startLine,
391
+ end_line = @endLine,
392
+ start_column = @startColumn,
393
+ end_column = @endColumn,
394
+ docstring = @docstring,
395
+ signature = @signature,
396
+ visibility = @visibility,
397
+ is_exported = @isExported,
398
+ is_async = @isAsync,
399
+ is_static = @isStatic,
400
+ is_abstract = @isAbstract,
401
+ decorators = @decorators,
402
+ type_parameters = @typeParameters,
403
+ return_type = @returnType,
404
+ updated_at = @updatedAt
405
+ WHERE id = @id
390
406
  `);
391
407
  }
392
408
  // Invalidate cache before update
@@ -518,12 +534,12 @@ class QueryBuilder {
518
534
  const placeholders = variants.map(() => '?').join(', ');
519
535
  const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
520
536
  const rows = this.db
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
537
+ .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
538
+ FROM name_segment_vocab
539
+ WHERE segment IN (${placeholders})
540
+ GROUP BY name
541
+ HAVING matches >= ?
542
+ ORDER BY matches DESC, length(name) ASC
527
543
  LIMIT ?`)
528
544
  .all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
529
545
  return rows;
@@ -535,7 +551,7 @@ class QueryBuilder {
535
551
  return new Map();
536
552
  const placeholders = segments.map(() => '?').join(', ');
537
553
  const rows = this.db
538
- .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
554
+ .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
539
555
  WHERE segment IN (${placeholders}) GROUP BY segment`)
540
556
  .all(...segments);
541
557
  return new Map(rows.map((r) => [r.segment, r.n]));
@@ -695,15 +711,15 @@ class QueryBuilder {
695
711
  // protobuf stub) outranks the real `server/etcdserver/server.go`
696
712
  // (470 edges) by 4×, and the boost would push the agent toward
697
713
  // generated code.
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
714
+ this.stmts.getDominantFile = this.db.prepare(`
715
+ SELECT n.file_path AS file_path, COUNT(*) AS edge_count
716
+ FROM edges e
717
+ JOIN nodes n ON e.source = n.id
718
+ JOIN nodes m ON e.target = m.id
719
+ WHERE n.file_path = m.file_path
720
+ GROUP BY n.file_path
721
+ ORDER BY edge_count DESC
722
+ LIMIT 20
707
723
  `);
708
724
  }
709
725
  const rows = this.stmts.getDominantFile.all();
@@ -730,13 +746,13 @@ class QueryBuilder {
730
746
  */
731
747
  getTopRouteFile() {
732
748
  if (!this.stmts.getTopRouteFile) {
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
749
+ this.stmts.getTopRouteFile = this.db.prepare(`
750
+ SELECT file_path, COUNT(*) AS cnt
751
+ FROM nodes
752
+ WHERE kind = 'route'
753
+ GROUP BY file_path
754
+ ORDER BY cnt DESC
755
+ LIMIT 20
740
756
  `);
741
757
  }
742
758
  const rows = this.stmts.getTopRouteFile.all();
@@ -767,21 +783,21 @@ class QueryBuilder {
767
783
  // Edge kind varies across framework resolvers: Spring/Rails/
768
784
  // Laravel/Drupal emit `references`, Express emits `calls`. Accept
769
785
  // both — the semantic is the same (route → its handler).
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 ?
786
+ this.stmts.getRoutingManifest = this.db.prepare(`
787
+ SELECT
788
+ r.name AS url,
789
+ h.name AS handler,
790
+ h.file_path AS handler_file,
791
+ h.start_line AS handler_line,
792
+ h.kind AS handler_kind
793
+ FROM nodes r
794
+ JOIN edges e ON e.source = r.id
795
+ JOIN nodes h ON e.target = h.id
796
+ WHERE r.kind = 'route'
797
+ AND e.kind IN ('references', 'calls')
798
+ AND h.kind IN ('function', 'method', 'class')
799
+ ORDER BY r.file_path, r.start_line
800
+ LIMIT ?
785
801
  `);
786
802
  }
787
803
  const rows = this.stmts.getRoutingManifest.all(limit);
@@ -878,15 +894,21 @@ class QueryBuilder {
878
894
  * Get nodes by exact name match (uses idx_nodes_name index)
879
895
  */
880
896
  getNodesByName(name) {
881
- if (!this.stmts.getNodesByName) {
882
- this.stmts.getNodesByName = this.db.prepare('SELECT * FROM nodes WHERE name = ?');
897
+ const main = [];
898
+ if (this.includeProjectNodes) {
899
+ if (!this.stmts.getNodesByName) {
900
+ // Content-derived order (not insertion/rowid order): sync appends nodes
901
+ // as files change, so without ORDER BY the same tree can resolve
902
+ // differently than a full rebuild that writes in scan order.
903
+ this.stmts.getNodesByName = this.db.prepare('SELECT * FROM nodes WHERE name = ? ORDER BY file_path, start_line');
904
+ }
905
+ const rows = this.stmts.getNodesByName.all(name);
906
+ main.push(...rows.map(rowToNode));
883
907
  }
884
- const rows = this.stmts.getNodesByName.all(name);
885
- const main = rows.map(rowToNode);
886
908
  if (!this.hasOhosApiAttached())
887
909
  return main;
888
910
  const apiRows = this.db
889
- .prepare('SELECT * FROM ohos_api.nodes WHERE name = ?')
911
+ .prepare('SELECT * FROM ohos_api.nodes WHERE name = ? ORDER BY file_path, start_line')
890
912
  .all(name);
891
913
  const seen = new Set(main.map((n) => n.id));
892
914
  const api = apiRows.map((r) => this.mapOhosApiNodeRow(r)).filter((n) => !seen.has(n.id));
@@ -942,12 +964,17 @@ class QueryBuilder {
942
964
  const text = parsed.text;
943
965
  const kinds = mergedKinds;
944
966
  const languages = mergedLanguages;
967
+ // SDK-only: skip project FTS entirely; federate OHOS API hits only.
968
+ if (!this.includeProjectNodes) {
969
+ if (!this.hasOhosApiAttached() || text.length < 2)
970
+ return [];
971
+ return this.mergeOhosApiTextSearch(text, { kinds, languages, limit }, []);
972
+ }
945
973
  // First try FTS5 with prefix matching
946
974
  let results = text
947
975
  ? this.searchNodesFTS(text, { kinds, languages, limit, offset })
948
976
  // Over-fetch by 5× when running filter-only (no text). The
949
- // post-scoring path: + name: filters can be very selective, so
950
- // a smaller multiplier risks returning fewer than `limit`
977
+ // post-scoring path: + name: filters can be very selective, so // a smaller multiplier risks returning fewer than `limit`
951
978
  // results despite the DB having plenty of matches.
952
979
  : this.searchAllByFilters({ kinds, languages, limit: limit * 5 });
953
980
  // If no FTS results, try LIKE-based substring search
@@ -1036,10 +1063,10 @@ class QueryBuilder {
1036
1063
  const seen = new Set(existing.map((r) => r.node.id));
1037
1064
  const merged = [...existing];
1038
1065
  const apiLimit = Math.min(20, Math.max(5, Math.floor(limit / 4)));
1039
- let sql = `
1040
- SELECT nodes.*, 0.9 as score
1041
- FROM ohos_api.nodes
1042
- WHERE (name LIKE ? OR qualified_name LIKE ?)
1066
+ let sql = `
1067
+ SELECT nodes.*, 0.9 as score
1068
+ FROM ohos_api.nodes
1069
+ WHERE (name LIKE ? OR qualified_name LIKE ?)
1043
1070
  `;
1044
1071
  const pattern = `%${text}%`;
1045
1072
  const params = [pattern, pattern];
@@ -1178,11 +1205,11 @@ class QueryBuilder {
1178
1205
  // Fetch 5x requested limit so post-hoc rescoring (kindBonus, pathRelevance,
1179
1206
  // nameMatchBonus) can promote results that BM25 alone undervalues.
1180
1207
  const ftsLimit = Math.max(limit * 5, 100);
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 ?
1208
+ let sql = `
1209
+ SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1210
+ FROM nodes_fts
1211
+ JOIN nodes ON nodes_fts.id = nodes.id
1212
+ WHERE nodes_fts MATCH ?
1186
1213
  `;
1187
1214
  const params = [ftsQuery];
1188
1215
  if (kinds && kinds.length > 0) {
@@ -1213,21 +1240,21 @@ class QueryBuilder {
1213
1240
  */
1214
1241
  searchNodesLike(query, options) {
1215
1242
  const { kinds, languages, limit = 100, offset = 0 } = options;
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
- )
1243
+ let sql = `
1244
+ SELECT nodes.*,
1245
+ CASE
1246
+ WHEN name = ? THEN 1.0
1247
+ WHEN name LIKE ? THEN 0.9
1248
+ WHEN name LIKE ? THEN 0.8
1249
+ WHEN qualified_name LIKE ? THEN 0.7
1250
+ ELSE 0.5
1251
+ END as score
1252
+ FROM nodes
1253
+ WHERE (
1254
+ name LIKE ? OR
1255
+ qualified_name LIKE ? OR
1256
+ name LIKE ?
1257
+ )
1231
1258
  `;
1232
1259
  // Pattern variants for better matching
1233
1260
  const exactMatch = query;
@@ -1272,6 +1299,42 @@ class QueryBuilder {
1272
1299
  if (names.length === 0)
1273
1300
  return [];
1274
1301
  const { kinds, languages, limit = 50 } = options;
1302
+ // SDK-only: skip project co-location passes; exact-name against ohos_api only.
1303
+ if (!this.includeProjectNodes) {
1304
+ if (!this.hasOhosApiAttached())
1305
+ return [];
1306
+ const perNameLimit = Math.max(8, Math.ceil(limit / names.length));
1307
+ const allResults = [];
1308
+ const seenIds = new Set();
1309
+ for (const name of names) {
1310
+ let apiSql = `
1311
+ SELECT nodes.*, 0.95 as score
1312
+ FROM ohos_api.nodes
1313
+ WHERE name COLLATE NOCASE = ?
1314
+ `;
1315
+ const apiParams = [name];
1316
+ if (kinds && kinds.length > 0) {
1317
+ apiSql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1318
+ apiParams.push(...kinds);
1319
+ }
1320
+ if (languages && languages.length > 0) {
1321
+ apiSql += ` AND language IN (${languages.map(() => '?').join(',')})`;
1322
+ apiParams.push(...languages);
1323
+ }
1324
+ apiSql += ' LIMIT ?';
1325
+ apiParams.push(perNameLimit);
1326
+ const apiRows = this.db.prepare(apiSql).all(...apiParams);
1327
+ for (const row of apiRows) {
1328
+ const node = this.mapOhosApiNodeRow(row);
1329
+ if (seenIds.has(node.id))
1330
+ continue;
1331
+ seenIds.add(node.id);
1332
+ allResults.push({ node, score: row.score });
1333
+ }
1334
+ }
1335
+ allResults.sort((a, b) => b.score - a.score);
1336
+ return allResults.slice(0, limit);
1337
+ }
1275
1338
  // Two-pass approach to handle common names (e.g., "run" has 40+ matches):
1276
1339
  // Pass 1: Find which files contain distinctive (rare) symbols from the query.
1277
1340
  // Pass 2: Query each name, boosting results that co-locate with distinctive symbols.
@@ -1301,10 +1364,10 @@ class QueryBuilder {
1301
1364
  const allResults = [];
1302
1365
  const seenIds = new Set();
1303
1366
  for (const name of names) {
1304
- let sql = `
1305
- SELECT nodes.*, 1.0 as score
1306
- FROM nodes
1307
- WHERE name COLLATE NOCASE = ?
1367
+ let sql = `
1368
+ SELECT nodes.*, 1.0 as score
1369
+ FROM nodes
1370
+ WHERE name COLLATE NOCASE = ?
1308
1371
  `;
1309
1372
  const params = [name];
1310
1373
  if (kinds && kinds.length > 0) {
@@ -1335,10 +1398,10 @@ class QueryBuilder {
1335
1398
  allResults.push(r);
1336
1399
  }
1337
1400
  if (this.hasOhosApiAttached()) {
1338
- let apiSql = `
1339
- SELECT nodes.*, 0.95 as score
1340
- FROM ohos_api.nodes
1341
- WHERE name COLLATE NOCASE = ?
1401
+ let apiSql = `
1402
+ SELECT nodes.*, 0.95 as score
1403
+ FROM ohos_api.nodes
1404
+ WHERE name COLLATE NOCASE = ?
1342
1405
  `;
1343
1406
  const apiParams = [name];
1344
1407
  if (kinds && kinds.length > 0) {
@@ -1374,10 +1437,10 @@ class QueryBuilder {
1374
1437
  */
1375
1438
  findNodesByNameSubstring(substring, options = {}) {
1376
1439
  const { kinds, languages, limit = 30, excludePrefix } = options;
1377
- let sql = `
1378
- SELECT nodes.*, 1.0 as score
1379
- FROM nodes
1380
- WHERE name LIKE ?
1440
+ let sql = `
1441
+ SELECT nodes.*, 1.0 as score
1442
+ FROM nodes
1443
+ WHERE name LIKE ?
1381
1444
  `;
1382
1445
  const params = [`%${substring}%`];
1383
1446
  // Exclude prefix matches (handled by FTS-based prefix search in Step 2b)
@@ -1409,9 +1472,9 @@ class QueryBuilder {
1409
1472
  */
1410
1473
  insertEdge(edge) {
1411
1474
  if (!this.stmts.insertEdge) {
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)
1475
+ this.stmts.insertEdge = this.db.prepare(`
1476
+ INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
1477
+ VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
1415
1478
  `);
1416
1479
  }
1417
1480
  this.stmts.insertEdge.run({
@@ -1538,12 +1601,12 @@ class QueryBuilder {
1538
1601
  * it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
1539
1602
  */
1540
1603
  getDependentFilePaths(filePath) {
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'
1604
+ const sql = `SELECT DISTINCT src.file_path AS fp
1605
+ FROM edges e
1606
+ JOIN nodes tgt ON tgt.id = e.target
1607
+ JOIN nodes src ON src.id = e.source
1608
+ WHERE tgt.file_path = ?
1609
+ AND e.kind != 'contains'
1547
1610
  AND src.file_path != ?`;
1548
1611
  const rows = this.db.prepare(sql).all(filePath, filePath);
1549
1612
  return rows.map((r) => r.fp);
@@ -1555,12 +1618,12 @@ class QueryBuilder {
1555
1618
  * (all kinds except `contains`); same reason imports-only is insufficient.
1556
1619
  */
1557
1620
  getDependencyFilePaths(filePath) {
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'
1621
+ const sql = `SELECT DISTINCT tgt.file_path AS fp
1622
+ FROM edges e
1623
+ JOIN nodes src ON src.id = e.source
1624
+ JOIN nodes tgt ON tgt.id = e.target
1625
+ WHERE src.file_path = ?
1626
+ AND e.kind != 'contains'
1564
1627
  AND tgt.file_path != ?`;
1565
1628
  const rows = this.db.prepare(sql).all(filePath, filePath);
1566
1629
  return rows.map((r) => r.fp);
@@ -1576,13 +1639,13 @@ class QueryBuilder {
1576
1639
  * {@link getDependentFilePaths}: all kinds except `contains`.
1577
1640
  */
1578
1641
  getCrossFileIncomingEdgesWithTarget(filePath) {
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'
1642
+ const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1643
+ src.file_path AS source_file_path, src.language AS source_language
1644
+ FROM edges e
1645
+ JOIN nodes tgt ON tgt.id = e.target
1646
+ JOIN nodes src ON src.id = e.source
1647
+ WHERE tgt.file_path = ?
1648
+ AND e.kind != 'contains'
1586
1649
  AND src.file_path != ?`;
1587
1650
  const rows = this.db.prepare(sql).all(filePath, filePath);
1588
1651
  return rows.map(row => ({
@@ -1599,10 +1662,10 @@ class QueryBuilder {
1599
1662
  */
1600
1663
  deleteArkTSCrossFileCallEdges() {
1601
1664
  const result = this.db
1602
- .prepare(`DELETE FROM edges
1603
- WHERE kind = 'calls'
1604
- AND provenance = 'heuristic'
1605
- AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
1665
+ .prepare(`DELETE FROM edges
1666
+ WHERE kind = 'calls'
1667
+ AND provenance = 'heuristic'
1668
+ AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
1606
1669
  AND metadata LIKE '%"sourceFile"%'`)
1607
1670
  .run();
1608
1671
  return result.changes;
@@ -1615,17 +1678,18 @@ class QueryBuilder {
1615
1678
  */
1616
1679
  upsertFile(file) {
1617
1680
  if (!this.stmts.upsertFile) {
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
1681
+ this.stmts.upsertFile = this.db.prepare(`
1682
+ INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors, generated)
1683
+ VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors, @generated)
1684
+ ON CONFLICT(path) DO UPDATE SET
1685
+ content_hash = @contentHash,
1686
+ language = @language,
1687
+ size = @size,
1688
+ modified_at = @modifiedAt,
1689
+ indexed_at = @indexedAt,
1690
+ node_count = @nodeCount,
1691
+ errors = @errors,
1692
+ generated = @generated
1629
1693
  `);
1630
1694
  }
1631
1695
  this.stmts.upsertFile.run({
@@ -1637,6 +1701,7 @@ class QueryBuilder {
1637
1701
  indexedAt: file.indexedAt,
1638
1702
  nodeCount: file.nodeCount,
1639
1703
  errors: file.errors ? JSON.stringify(file.errors) : null,
1704
+ generated: file.generated ? 1 : 0,
1640
1705
  });
1641
1706
  }
1642
1707
  /**
@@ -1699,9 +1764,9 @@ class QueryBuilder {
1699
1764
  */
1700
1765
  insertUnresolvedRef(ref) {
1701
1766
  if (!this.stmts.insertUnresolved) {
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)
1767
+ this.stmts.insertUnresolved = this.db.prepare(`
1768
+ INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
1769
+ VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
1705
1770
  `);
1706
1771
  }
1707
1772
  this.stmts.insertUnresolved.run({
@@ -1994,6 +2059,107 @@ class QueryBuilder {
1994
2059
  }
1995
2060
  return [...names];
1996
2061
  }
2062
+ /**
2063
+ * Resolution edges targeting any of the given node names — candidates for the
2064
+ * sync rebind pass when a definition set changes. Includes source file/language
2065
+ * so a dropped edge can be resurrected as its original unresolved ref.
2066
+ *
2067
+ * Names matching more than `perNameCeiling` edges are skipped entirely, same
2068
+ * rationale and same default as {@link getRetryableFailedReferences}: at that
2069
+ * population the name is generic (`get`, `clear`, …); one definition changing
2070
+ * won't flip most of them, and rebinding an arbitrary subset is both wasted
2071
+ * work and incoherent coverage.
2072
+ */
2073
+ getResolutionEdgesByTargetName(names, perNameCeiling = 500) {
2074
+ if (names.length === 0)
2075
+ return [];
2076
+ // Pass 1: per-name edge counts, chunked under the SQLite parameter limit.
2077
+ const keep = [];
2078
+ for (let i = 0; i < names.length; i += SQLITE_PARAM_CHUNK_SIZE) {
2079
+ const chunk = names.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
2080
+ const placeholders = chunk.map(() => '?').join(',');
2081
+ const counts = this.db
2082
+ .prepare(`SELECT tgt.name AS name, COUNT(*) AS count
2083
+ FROM edges e
2084
+ JOIN nodes tgt ON tgt.id = e.target
2085
+ WHERE tgt.name IN (${placeholders})
2086
+ AND (e.provenance IS NULL OR e.provenance != 'heuristic')
2087
+ GROUP BY tgt.name`)
2088
+ .all(...chunk);
2089
+ for (const row of counts) {
2090
+ if (row.count <= perNameCeiling)
2091
+ keep.push(row.name);
2092
+ }
2093
+ }
2094
+ if (keep.length === 0)
2095
+ return [];
2096
+ // Pass 2: load the surviving edges with the source file context a
2097
+ // resurrection needs.
2098
+ const out = [];
2099
+ for (let i = 0; i < keep.length; i += SQLITE_PARAM_CHUNK_SIZE) {
2100
+ const chunk = keep.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
2101
+ const placeholders = chunk.map(() => '?').join(',');
2102
+ const rows = this.db
2103
+ .prepare(`SELECT e.*, src.file_path AS source_file_path, src.language AS source_language
2104
+ FROM edges e
2105
+ JOIN nodes tgt ON tgt.id = e.target
2106
+ JOIN nodes src ON src.id = e.source
2107
+ WHERE tgt.name IN (${placeholders})
2108
+ AND (e.provenance IS NULL OR e.provenance != 'heuristic')`)
2109
+ .all(...chunk);
2110
+ for (const row of rows) {
2111
+ out.push({
2112
+ ...rowToEdge(row),
2113
+ edgeId: row.id,
2114
+ sourceFilePath: row.source_file_path,
2115
+ sourceLanguage: row.source_language,
2116
+ });
2117
+ }
2118
+ }
2119
+ return out;
2120
+ }
2121
+ /** Delete edges by primary key — the rebind pass's half of a re-resolution. */
2122
+ deleteEdgesByIds(edgeIds) {
2123
+ if (edgeIds.length === 0)
2124
+ return 0;
2125
+ let changed = 0;
2126
+ this.db.transaction(() => {
2127
+ for (let i = 0; i < edgeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
2128
+ const chunk = edgeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
2129
+ const placeholders = chunk.map(() => '?').join(',');
2130
+ changed += this.db.prepare(`DELETE FROM edges WHERE id IN (${placeholders})`).run(...chunk).changes;
2131
+ }
2132
+ })();
2133
+ return changed;
2134
+ }
2135
+ /**
2136
+ * Distinct `file\0name` pairs defined by the given files — the shape sync's
2137
+ * definition delta needs.
2138
+ *
2139
+ * Deliberately NOT `getNodeNamesByFiles`: a bare name set is taken over the
2140
+ * WHOLE changed batch, so a name that moves between two files in one commit
2141
+ * (or exists in one changed file and is newly added to another) appears on
2142
+ * both sides and cancels out of the symmetric difference — even though a
2143
+ * definition genuinely appeared or vanished and every reference to that name
2144
+ * repo-wide may now bind elsewhere. Keying by file makes each definition its
2145
+ * own fact, so the move is seen as one removal plus one addition.
2146
+ */
2147
+ getNodeNamePairsByFiles(filePaths) {
2148
+ const pairs = new Set();
2149
+ if (filePaths.length === 0)
2150
+ return pairs;
2151
+ for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) {
2152
+ const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
2153
+ const placeholders = chunk.map(() => '?').join(',');
2154
+ const rows = this.db
2155
+ .prepare(`SELECT DISTINCT file_path, name FROM nodes WHERE file_path IN (${placeholders})`)
2156
+ .all(...chunk);
2157
+ // NUL-joined: a path or a symbol name can contain a space, never a NUL.
2158
+ for (const row of rows)
2159
+ pairs.add(`${row.file_path}\0${row.name}`);
2160
+ }
2161
+ return pairs;
2162
+ }
1997
2163
  /**
1998
2164
  * Get unresolved references scoped to specific file paths.
1999
2165
  * Uses the idx_unresolved_file_path index for efficient lookup.
@@ -2085,11 +2251,11 @@ class QueryBuilder {
2085
2251
  */
2086
2252
  getStats() {
2087
2253
  // Single query for all three aggregate counts
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
2254
+ const counts = this.db.prepare(`
2255
+ SELECT
2256
+ (SELECT COUNT(*) FROM nodes) AS node_count,
2257
+ (SELECT COUNT(*) FROM edges) AS edge_count,
2258
+ (SELECT COUNT(*) FROM files) AS file_count
2093
2259
  `).get();
2094
2260
  const nodesByKind = {};
2095
2261
  const nodeKindRows = this.db
@@ -2120,6 +2286,7 @@ class QueryBuilder {
2120
2286
  edgesByKind,
2121
2287
  filesByLanguage,
2122
2288
  dbSizeBytes: 0, // Set by caller using DatabaseConnection.getSize()
2289
+ walSizeBytes: 0, // Set by caller using DatabaseConnection.getWalSizeBytes()
2123
2290
  lastUpdated: Date.now(),
2124
2291
  };
2125
2292
  }