homegraph 1.5.6 → 1.5.8

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 (560) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +12 -6
  3. package/dist/bin/homegraph.js +16 -14
  4. package/dist/context/index.js +120 -15
  5. package/dist/db/index.d.ts +1 -1
  6. package/dist/db/index.js +11 -25
  7. package/dist/db/queries.d.ts +5 -1
  8. package/dist/db/queries.js +31 -2
  9. package/dist/db/sqlite-adapter.d.ts +6 -12
  10. package/dist/db/sqlite-adapter.js +13 -41
  11. package/dist/directory.d.ts +1 -1
  12. package/dist/directory.js +25 -1
  13. package/dist/extraction/grammars.d.ts +2 -0
  14. package/dist/extraction/grammars.js +7 -7
  15. package/dist/extraction/languages/arkts.d.ts +25 -3
  16. package/dist/extraction/languages/arkts.js +184 -22
  17. package/dist/graph/evidence-paths.d.ts +63 -0
  18. package/dist/graph/evidence-paths.js +245 -0
  19. package/dist/index.d.ts +6 -1
  20. package/dist/index.js +55 -17
  21. package/dist/mcp/arkts-evidence-packs.d.ts +67 -0
  22. package/dist/mcp/arkts-evidence-packs.js +352 -0
  23. package/dist/mcp/daemon.js +1 -1
  24. package/dist/mcp/engine.d.ts +20 -7
  25. package/dist/mcp/engine.js +113 -106
  26. package/dist/mcp/evidence-rendering.d.ts +10 -0
  27. package/dist/mcp/evidence-rendering.js +71 -0
  28. package/dist/mcp/explore-repeat-guard.d.ts +8 -13
  29. package/dist/mcp/explore-repeat-guard.js +54 -114
  30. package/dist/mcp/explore-session-state.d.ts +26 -4
  31. package/dist/mcp/explore-session-state.js +50 -4
  32. package/dist/mcp/index-availability.d.ts +23 -0
  33. package/dist/mcp/index-availability.js +78 -0
  34. package/dist/mcp/index.js +5 -4
  35. package/dist/mcp/query-cache.d.ts +1 -1
  36. package/dist/mcp/query-cache.js +90 -3
  37. package/dist/mcp/query-worker.d.ts +1 -1
  38. package/dist/mcp/query-worker.js +1 -1
  39. package/dist/mcp/server-instructions.d.ts +4 -9
  40. package/dist/mcp/server-instructions.js +34 -61
  41. package/dist/mcp/session.js +12 -4
  42. package/dist/mcp/source-slice-identity.d.ts +3 -0
  43. package/dist/mcp/source-slice-identity.js +11 -0
  44. package/dist/mcp/tools.d.ts +43 -9
  45. package/dist/mcp/tools.js +859 -155
  46. package/dist/search/literal-evidence.d.ts +44 -0
  47. package/dist/search/literal-evidence.js +278 -0
  48. package/dist/search/query-plan-provider.d.ts +6 -0
  49. package/dist/search/query-plan-provider.js +289 -0
  50. package/dist/search/query-plan.d.ts +98 -0
  51. package/dist/search/query-plan.js +334 -0
  52. package/dist/search/query-utils.d.ts +6 -1
  53. package/dist/search/query-utils.js +64 -5
  54. package/dist/spec/llm/client.js +3 -15
  55. package/dist/spec/llm/openai-sdk.d.ts +14 -0
  56. package/dist/spec/llm/openai-sdk.js +37 -0
  57. package/dist/spec/llm/retry.js +8 -9
  58. package/dist/types.d.ts +17 -0
  59. package/dist/utils.d.ts +5 -0
  60. package/dist/utils.js +24 -0
  61. package/package.json +3 -5
  62. package/dist/addons/dynamic-import.d.ts.map +0 -1
  63. package/dist/addons/dynamic-import.js.map +0 -1
  64. package/dist/addons/init-template.d.ts.map +0 -1
  65. package/dist/addons/init-template.js.map +0 -1
  66. package/dist/addons/loader.d.ts.map +0 -1
  67. package/dist/addons/loader.js.map +0 -1
  68. package/dist/addons/manager.d.ts.map +0 -1
  69. package/dist/addons/manager.js.map +0 -1
  70. package/dist/addons/paths.d.ts.map +0 -1
  71. package/dist/addons/paths.js.map +0 -1
  72. package/dist/addons/registry.d.ts.map +0 -1
  73. package/dist/addons/registry.js.map +0 -1
  74. package/dist/addons/semver.d.ts.map +0 -1
  75. package/dist/addons/semver.js.map +0 -1
  76. package/dist/addons/types.d.ts.map +0 -1
  77. package/dist/addons/types.js.map +0 -1
  78. package/dist/addons/validate.d.ts.map +0 -1
  79. package/dist/addons/validate.js.map +0 -1
  80. package/dist/arkui/index.d.ts.map +0 -1
  81. package/dist/arkui/index.js.map +0 -1
  82. package/dist/arkui/migrate-passage.d.ts.map +0 -1
  83. package/dist/arkui/migrate-passage.js.map +0 -1
  84. package/dist/arkui/migrate-semantics.d.ts.map +0 -1
  85. package/dist/arkui/migrate-semantics.js.map +0 -1
  86. package/dist/arkui/migrate-snapshot.d.ts.map +0 -1
  87. package/dist/arkui/migrate-snapshot.js.map +0 -1
  88. package/dist/bin/addon-commands.d.ts.map +0 -1
  89. package/dist/bin/addon-commands.js.map +0 -1
  90. package/dist/bin/command-supervision.d.ts.map +0 -1
  91. package/dist/bin/command-supervision.js.map +0 -1
  92. package/dist/bin/fatal-handler.d.ts.map +0 -1
  93. package/dist/bin/fatal-handler.js.map +0 -1
  94. package/dist/bin/homegraph.d.ts.map +0 -1
  95. package/dist/bin/homegraph.js.map +0 -1
  96. package/dist/bin/node-version-check.d.ts.map +0 -1
  97. package/dist/bin/node-version-check.js.map +0 -1
  98. package/dist/bin/uninstall.d.ts.map +0 -1
  99. package/dist/bin/uninstall.js.map +0 -1
  100. package/dist/context/formatter.d.ts.map +0 -1
  101. package/dist/context/formatter.js.map +0 -1
  102. package/dist/context/index.d.ts.map +0 -1
  103. package/dist/context/index.js.map +0 -1
  104. package/dist/context/markers.d.ts.map +0 -1
  105. package/dist/context/markers.js.map +0 -1
  106. package/dist/db/index.d.ts.map +0 -1
  107. package/dist/db/index.js.map +0 -1
  108. package/dist/db/migrations.d.ts.map +0 -1
  109. package/dist/db/migrations.js.map +0 -1
  110. package/dist/db/queries.d.ts.map +0 -1
  111. package/dist/db/queries.js.map +0 -1
  112. package/dist/db/sqlite-adapter.d.ts.map +0 -1
  113. package/dist/db/sqlite-adapter.js.map +0 -1
  114. package/dist/db/wal-valve.d.ts.map +0 -1
  115. package/dist/db/wal-valve.js.map +0 -1
  116. package/dist/directory.d.ts.map +0 -1
  117. package/dist/directory.js.map +0 -1
  118. package/dist/errors.d.ts.map +0 -1
  119. package/dist/errors.js.map +0 -1
  120. package/dist/extraction/arkts-batch-worker.d.ts.map +0 -1
  121. package/dist/extraction/arkts-batch-worker.js.map +0 -1
  122. package/dist/extraction/astro-extractor.d.ts.map +0 -1
  123. package/dist/extraction/astro-extractor.js.map +0 -1
  124. package/dist/extraction/cfml-extractor.d.ts.map +0 -1
  125. package/dist/extraction/cfml-extractor.js.map +0 -1
  126. package/dist/extraction/context.d.ts.map +0 -1
  127. package/dist/extraction/context.js.map +0 -1
  128. package/dist/extraction/default-ignore.d.ts.map +0 -1
  129. package/dist/extraction/default-ignore.js.map +0 -1
  130. package/dist/extraction/dfm-extractor.d.ts.map +0 -1
  131. package/dist/extraction/dfm-extractor.js.map +0 -1
  132. package/dist/extraction/extraction-version.d.ts.map +0 -1
  133. package/dist/extraction/extraction-version.js.map +0 -1
  134. package/dist/extraction/function-ref.d.ts.map +0 -1
  135. package/dist/extraction/function-ref.js.map +0 -1
  136. package/dist/extraction/generated-detection.d.ts.map +0 -1
  137. package/dist/extraction/generated-detection.js.map +0 -1
  138. package/dist/extraction/grammars.d.ts.map +0 -1
  139. package/dist/extraction/grammars.js.map +0 -1
  140. package/dist/extraction/index.d.ts.map +0 -1
  141. package/dist/extraction/index.js.map +0 -1
  142. package/dist/extraction/languages/arkts.d.ts.map +0 -1
  143. package/dist/extraction/languages/arkts.js.map +0 -1
  144. package/dist/extraction/languages/c-cpp.d.ts.map +0 -1
  145. package/dist/extraction/languages/c-cpp.js.map +0 -1
  146. package/dist/extraction/languages/cfquery.d.ts.map +0 -1
  147. package/dist/extraction/languages/cfquery.js.map +0 -1
  148. package/dist/extraction/languages/cfscript.d.ts.map +0 -1
  149. package/dist/extraction/languages/cfscript.js.map +0 -1
  150. package/dist/extraction/languages/cobol.d.ts.map +0 -1
  151. package/dist/extraction/languages/cobol.js.map +0 -1
  152. package/dist/extraction/languages/csharp.d.ts.map +0 -1
  153. package/dist/extraction/languages/csharp.js.map +0 -1
  154. package/dist/extraction/languages/dart.d.ts.map +0 -1
  155. package/dist/extraction/languages/dart.js.map +0 -1
  156. package/dist/extraction/languages/erlang.d.ts.map +0 -1
  157. package/dist/extraction/languages/erlang.js.map +0 -1
  158. package/dist/extraction/languages/go.d.ts.map +0 -1
  159. package/dist/extraction/languages/go.js.map +0 -1
  160. package/dist/extraction/languages/index.d.ts.map +0 -1
  161. package/dist/extraction/languages/index.js.map +0 -1
  162. package/dist/extraction/languages/java.d.ts.map +0 -1
  163. package/dist/extraction/languages/java.js.map +0 -1
  164. package/dist/extraction/languages/javascript.d.ts.map +0 -1
  165. package/dist/extraction/languages/javascript.js.map +0 -1
  166. package/dist/extraction/languages/kotlin.d.ts.map +0 -1
  167. package/dist/extraction/languages/kotlin.js.map +0 -1
  168. package/dist/extraction/languages/lua.d.ts.map +0 -1
  169. package/dist/extraction/languages/lua.js.map +0 -1
  170. package/dist/extraction/languages/luau.d.ts.map +0 -1
  171. package/dist/extraction/languages/luau.js.map +0 -1
  172. package/dist/extraction/languages/nix.d.ts.map +0 -1
  173. package/dist/extraction/languages/nix.js.map +0 -1
  174. package/dist/extraction/languages/objc.d.ts.map +0 -1
  175. package/dist/extraction/languages/objc.js.map +0 -1
  176. package/dist/extraction/languages/pascal.d.ts.map +0 -1
  177. package/dist/extraction/languages/pascal.js.map +0 -1
  178. package/dist/extraction/languages/php.d.ts.map +0 -1
  179. package/dist/extraction/languages/php.js.map +0 -1
  180. package/dist/extraction/languages/python.d.ts.map +0 -1
  181. package/dist/extraction/languages/python.js.map +0 -1
  182. package/dist/extraction/languages/r.d.ts.map +0 -1
  183. package/dist/extraction/languages/r.js.map +0 -1
  184. package/dist/extraction/languages/ruby.d.ts.map +0 -1
  185. package/dist/extraction/languages/ruby.js.map +0 -1
  186. package/dist/extraction/languages/rust.d.ts.map +0 -1
  187. package/dist/extraction/languages/rust.js.map +0 -1
  188. package/dist/extraction/languages/scala.d.ts.map +0 -1
  189. package/dist/extraction/languages/scala.js.map +0 -1
  190. package/dist/extraction/languages/solidity.d.ts.map +0 -1
  191. package/dist/extraction/languages/solidity.js.map +0 -1
  192. package/dist/extraction/languages/swift.d.ts.map +0 -1
  193. package/dist/extraction/languages/swift.js.map +0 -1
  194. package/dist/extraction/languages/terraform.d.ts.map +0 -1
  195. package/dist/extraction/languages/terraform.js.map +0 -1
  196. package/dist/extraction/languages/typescript.d.ts.map +0 -1
  197. package/dist/extraction/languages/typescript.js.map +0 -1
  198. package/dist/extraction/languages/vbnet.d.ts.map +0 -1
  199. package/dist/extraction/languages/vbnet.js.map +0 -1
  200. package/dist/extraction/liquid-extractor.d.ts.map +0 -1
  201. package/dist/extraction/liquid-extractor.js.map +0 -1
  202. package/dist/extraction/mybatis-extractor.d.ts.map +0 -1
  203. package/dist/extraction/mybatis-extractor.js.map +0 -1
  204. package/dist/extraction/parse-pool.d.ts.map +0 -1
  205. package/dist/extraction/parse-pool.js.map +0 -1
  206. package/dist/extraction/parse-worker.d.ts.map +0 -1
  207. package/dist/extraction/parse-worker.js.map +0 -1
  208. package/dist/extraction/razor-extractor.d.ts.map +0 -1
  209. package/dist/extraction/razor-extractor.js.map +0 -1
  210. package/dist/extraction/store-worker.d.ts.map +0 -1
  211. package/dist/extraction/store-worker.js.map +0 -1
  212. package/dist/extraction/store-writer.d.ts.map +0 -1
  213. package/dist/extraction/store-writer.js.map +0 -1
  214. package/dist/extraction/svelte-extractor.d.ts.map +0 -1
  215. package/dist/extraction/svelte-extractor.js.map +0 -1
  216. package/dist/extraction/tree-sitter-helpers.d.ts.map +0 -1
  217. package/dist/extraction/tree-sitter-helpers.js.map +0 -1
  218. package/dist/extraction/tree-sitter-types.d.ts.map +0 -1
  219. package/dist/extraction/tree-sitter-types.js.map +0 -1
  220. package/dist/extraction/tree-sitter.d.ts.map +0 -1
  221. package/dist/extraction/tree-sitter.js.map +0 -1
  222. package/dist/extraction/vue-extractor.d.ts.map +0 -1
  223. package/dist/extraction/vue-extractor.js.map +0 -1
  224. package/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  225. package/dist/extraction/wasm-runtime-flags.d.ts.map +0 -1
  226. package/dist/extraction/wasm-runtime-flags.js.map +0 -1
  227. package/dist/graph/index.d.ts.map +0 -1
  228. package/dist/graph/index.js.map +0 -1
  229. package/dist/graph/queries.d.ts.map +0 -1
  230. package/dist/graph/queries.js.map +0 -1
  231. package/dist/graph/traversal.d.ts.map +0 -1
  232. package/dist/graph/traversal.js.map +0 -1
  233. package/dist/graph-sources.d.ts.map +0 -1
  234. package/dist/graph-sources.js.map +0 -1
  235. package/dist/index.d.ts.map +0 -1
  236. package/dist/index.js.map +0 -1
  237. package/dist/installer/config-writer.d.ts.map +0 -1
  238. package/dist/installer/config-writer.js.map +0 -1
  239. package/dist/installer/index.d.ts.map +0 -1
  240. package/dist/installer/index.js.map +0 -1
  241. package/dist/installer/instructions-template.d.ts.map +0 -1
  242. package/dist/installer/instructions-template.js.map +0 -1
  243. package/dist/installer/targets/antigravity.d.ts.map +0 -1
  244. package/dist/installer/targets/antigravity.js.map +0 -1
  245. package/dist/installer/targets/claude.d.ts.map +0 -1
  246. package/dist/installer/targets/claude.js.map +0 -1
  247. package/dist/installer/targets/codebuddy.d.ts.map +0 -1
  248. package/dist/installer/targets/codebuddy.js.map +0 -1
  249. package/dist/installer/targets/codex.d.ts.map +0 -1
  250. package/dist/installer/targets/codex.js.map +0 -1
  251. package/dist/installer/targets/cursor.d.ts.map +0 -1
  252. package/dist/installer/targets/cursor.js.map +0 -1
  253. package/dist/installer/targets/deveco.d.ts.map +0 -1
  254. package/dist/installer/targets/deveco.js.map +0 -1
  255. package/dist/installer/targets/gemini.d.ts.map +0 -1
  256. package/dist/installer/targets/gemini.js.map +0 -1
  257. package/dist/installer/targets/hermes.d.ts.map +0 -1
  258. package/dist/installer/targets/hermes.js.map +0 -1
  259. package/dist/installer/targets/kiro.d.ts.map +0 -1
  260. package/dist/installer/targets/kiro.js.map +0 -1
  261. package/dist/installer/targets/opencode.d.ts.map +0 -1
  262. package/dist/installer/targets/opencode.js.map +0 -1
  263. package/dist/installer/targets/registry.d.ts.map +0 -1
  264. package/dist/installer/targets/registry.js.map +0 -1
  265. package/dist/installer/targets/shared.d.ts.map +0 -1
  266. package/dist/installer/targets/shared.js.map +0 -1
  267. package/dist/installer/targets/toml.d.ts.map +0 -1
  268. package/dist/installer/targets/toml.js.map +0 -1
  269. package/dist/installer/targets/types.d.ts.map +0 -1
  270. package/dist/installer/targets/types.js.map +0 -1
  271. package/dist/mcp/daemon-manager.d.ts.map +0 -1
  272. package/dist/mcp/daemon-manager.js.map +0 -1
  273. package/dist/mcp/daemon-paths.d.ts.map +0 -1
  274. package/dist/mcp/daemon-paths.js.map +0 -1
  275. package/dist/mcp/daemon-registry.d.ts.map +0 -1
  276. package/dist/mcp/daemon-registry.js.map +0 -1
  277. package/dist/mcp/daemon.d.ts.map +0 -1
  278. package/dist/mcp/daemon.js.map +0 -1
  279. package/dist/mcp/diff-impact.d.ts.map +0 -1
  280. package/dist/mcp/diff-impact.js.map +0 -1
  281. package/dist/mcp/dynamic-boundaries.d.ts.map +0 -1
  282. package/dist/mcp/dynamic-boundaries.js.map +0 -1
  283. package/dist/mcp/early-ppid.d.ts.map +0 -1
  284. package/dist/mcp/early-ppid.js.map +0 -1
  285. package/dist/mcp/engine.d.ts.map +0 -1
  286. package/dist/mcp/engine.js.map +0 -1
  287. package/dist/mcp/explore-dedup.d.ts.map +0 -1
  288. package/dist/mcp/explore-dedup.js.map +0 -1
  289. package/dist/mcp/explore-repeat-guard.d.ts.map +0 -1
  290. package/dist/mcp/explore-repeat-guard.js.map +0 -1
  291. package/dist/mcp/explore-session-state.d.ts.map +0 -1
  292. package/dist/mcp/explore-session-state.js.map +0 -1
  293. package/dist/mcp/index.d.ts.map +0 -1
  294. package/dist/mcp/index.js.map +0 -1
  295. package/dist/mcp/liveness-watchdog.d.ts.map +0 -1
  296. package/dist/mcp/liveness-watchdog.js.map +0 -1
  297. package/dist/mcp/memory-budget.d.ts.map +0 -1
  298. package/dist/mcp/memory-budget.js.map +0 -1
  299. package/dist/mcp/ppid-watchdog.d.ts.map +0 -1
  300. package/dist/mcp/ppid-watchdog.js.map +0 -1
  301. package/dist/mcp/proxy.d.ts.map +0 -1
  302. package/dist/mcp/proxy.js.map +0 -1
  303. package/dist/mcp/query-cache.d.ts.map +0 -1
  304. package/dist/mcp/query-cache.js.map +0 -1
  305. package/dist/mcp/query-pool.d.ts.map +0 -1
  306. package/dist/mcp/query-pool.js.map +0 -1
  307. package/dist/mcp/query-worker.d.ts.map +0 -1
  308. package/dist/mcp/query-worker.js.map +0 -1
  309. package/dist/mcp/server-instructions.d.ts.map +0 -1
  310. package/dist/mcp/server-instructions.js.map +0 -1
  311. package/dist/mcp/session.d.ts.map +0 -1
  312. package/dist/mcp/session.js.map +0 -1
  313. package/dist/mcp/startup-handshake.d.ts.map +0 -1
  314. package/dist/mcp/startup-handshake.js.map +0 -1
  315. package/dist/mcp/stdin-teardown.d.ts.map +0 -1
  316. package/dist/mcp/stdin-teardown.js.map +0 -1
  317. package/dist/mcp/tools.d.ts.map +0 -1
  318. package/dist/mcp/tools.js.map +0 -1
  319. package/dist/mcp/transport.d.ts.map +0 -1
  320. package/dist/mcp/transport.js.map +0 -1
  321. package/dist/mcp/version.d.ts.map +0 -1
  322. package/dist/mcp/version.js.map +0 -1
  323. package/dist/project-config.d.ts.map +0 -1
  324. package/dist/project-config.js.map +0 -1
  325. package/dist/project-map/index.d.ts.map +0 -1
  326. package/dist/project-map/index.js.map +0 -1
  327. package/dist/resolution/c-fnptr-synthesizer.d.ts.map +0 -1
  328. package/dist/resolution/c-fnptr-synthesizer.js.map +0 -1
  329. package/dist/resolution/callback-synthesizer.d.ts.map +0 -1
  330. package/dist/resolution/callback-synthesizer.js.map +0 -1
  331. package/dist/resolution/cooperative-yield.d.ts.map +0 -1
  332. package/dist/resolution/cooperative-yield.js.map +0 -1
  333. package/dist/resolution/frameworks/arkts-entry.d.ts.map +0 -1
  334. package/dist/resolution/frameworks/arkts-entry.js.map +0 -1
  335. package/dist/resolution/frameworks/arkts-napi.d.ts.map +0 -1
  336. package/dist/resolution/frameworks/arkts-napi.js.map +0 -1
  337. package/dist/resolution/frameworks/astro.d.ts.map +0 -1
  338. package/dist/resolution/frameworks/astro.js.map +0 -1
  339. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +0 -1
  340. package/dist/resolution/frameworks/cargo-workspace.js.map +0 -1
  341. package/dist/resolution/frameworks/cics.d.ts.map +0 -1
  342. package/dist/resolution/frameworks/cics.js.map +0 -1
  343. package/dist/resolution/frameworks/csharp.d.ts.map +0 -1
  344. package/dist/resolution/frameworks/csharp.js.map +0 -1
  345. package/dist/resolution/frameworks/drupal.d.ts.map +0 -1
  346. package/dist/resolution/frameworks/drupal.js.map +0 -1
  347. package/dist/resolution/frameworks/expo-modules.d.ts.map +0 -1
  348. package/dist/resolution/frameworks/expo-modules.js.map +0 -1
  349. package/dist/resolution/frameworks/express.d.ts.map +0 -1
  350. package/dist/resolution/frameworks/express.js.map +0 -1
  351. package/dist/resolution/frameworks/fabric.d.ts.map +0 -1
  352. package/dist/resolution/frameworks/fabric.js.map +0 -1
  353. package/dist/resolution/frameworks/go.d.ts.map +0 -1
  354. package/dist/resolution/frameworks/go.js.map +0 -1
  355. package/dist/resolution/frameworks/goframe.d.ts.map +0 -1
  356. package/dist/resolution/frameworks/goframe.js.map +0 -1
  357. package/dist/resolution/frameworks/index.d.ts.map +0 -1
  358. package/dist/resolution/frameworks/index.js.map +0 -1
  359. package/dist/resolution/frameworks/java.d.ts.map +0 -1
  360. package/dist/resolution/frameworks/java.js.map +0 -1
  361. package/dist/resolution/frameworks/laravel.d.ts.map +0 -1
  362. package/dist/resolution/frameworks/laravel.js.map +0 -1
  363. package/dist/resolution/frameworks/nestjs.d.ts.map +0 -1
  364. package/dist/resolution/frameworks/nestjs.js.map +0 -1
  365. package/dist/resolution/frameworks/play.d.ts.map +0 -1
  366. package/dist/resolution/frameworks/play.js.map +0 -1
  367. package/dist/resolution/frameworks/python.d.ts.map +0 -1
  368. package/dist/resolution/frameworks/python.js.map +0 -1
  369. package/dist/resolution/frameworks/react-native.d.ts.map +0 -1
  370. package/dist/resolution/frameworks/react-native.js.map +0 -1
  371. package/dist/resolution/frameworks/react.d.ts.map +0 -1
  372. package/dist/resolution/frameworks/react.js.map +0 -1
  373. package/dist/resolution/frameworks/ruby.d.ts.map +0 -1
  374. package/dist/resolution/frameworks/ruby.js.map +0 -1
  375. package/dist/resolution/frameworks/rust.d.ts.map +0 -1
  376. package/dist/resolution/frameworks/rust.js.map +0 -1
  377. package/dist/resolution/frameworks/svelte.d.ts.map +0 -1
  378. package/dist/resolution/frameworks/svelte.js.map +0 -1
  379. package/dist/resolution/frameworks/swift-objc.d.ts.map +0 -1
  380. package/dist/resolution/frameworks/swift-objc.js.map +0 -1
  381. package/dist/resolution/frameworks/swift.d.ts.map +0 -1
  382. package/dist/resolution/frameworks/swift.js.map +0 -1
  383. package/dist/resolution/frameworks/terraform.d.ts.map +0 -1
  384. package/dist/resolution/frameworks/terraform.js.map +0 -1
  385. package/dist/resolution/frameworks/vue.d.ts.map +0 -1
  386. package/dist/resolution/frameworks/vue.js.map +0 -1
  387. package/dist/resolution/go-module.d.ts.map +0 -1
  388. package/dist/resolution/go-module.js.map +0 -1
  389. package/dist/resolution/goframe-synthesizer.d.ts.map +0 -1
  390. package/dist/resolution/goframe-synthesizer.js.map +0 -1
  391. package/dist/resolution/import-resolver.d.ts.map +0 -1
  392. package/dist/resolution/import-resolver.js.map +0 -1
  393. package/dist/resolution/index.d.ts.map +0 -1
  394. package/dist/resolution/index.js.map +0 -1
  395. package/dist/resolution/lru-cache.d.ts.map +0 -1
  396. package/dist/resolution/lru-cache.js.map +0 -1
  397. package/dist/resolution/memory-budget.d.ts.map +0 -1
  398. package/dist/resolution/memory-budget.js.map +0 -1
  399. package/dist/resolution/name-matcher.d.ts.map +0 -1
  400. package/dist/resolution/name-matcher.js.map +0 -1
  401. package/dist/resolution/path-aliases.d.ts.map +0 -1
  402. package/dist/resolution/path-aliases.js.map +0 -1
  403. package/dist/resolution/resolver-pool.d.ts.map +0 -1
  404. package/dist/resolution/resolver-pool.js.map +0 -1
  405. package/dist/resolution/resolver-worker.d.ts.map +0 -1
  406. package/dist/resolution/resolver-worker.js.map +0 -1
  407. package/dist/resolution/strip-comments.d.ts.map +0 -1
  408. package/dist/resolution/strip-comments.js.map +0 -1
  409. package/dist/resolution/swift-objc-bridge.d.ts.map +0 -1
  410. package/dist/resolution/swift-objc-bridge.js.map +0 -1
  411. package/dist/resolution/types.d.ts.map +0 -1
  412. package/dist/resolution/types.js.map +0 -1
  413. package/dist/resolution/workspace-packages.d.ts.map +0 -1
  414. package/dist/resolution/workspace-packages.js.map +0 -1
  415. package/dist/search/identifier-segments.d.ts.map +0 -1
  416. package/dist/search/identifier-segments.js.map +0 -1
  417. package/dist/search/query-parser.d.ts.map +0 -1
  418. package/dist/search/query-parser.js.map +0 -1
  419. package/dist/search/query-utils.d.ts.map +0 -1
  420. package/dist/search/query-utils.js.map +0 -1
  421. package/dist/spec/build/diff-parser.d.ts.map +0 -1
  422. package/dist/spec/build/diff-parser.js.map +0 -1
  423. package/dist/spec/build/pipeline.d.ts.map +0 -1
  424. package/dist/spec/build/pipeline.js.map +0 -1
  425. package/dist/spec/build/scan.d.ts.map +0 -1
  426. package/dist/spec/build/scan.js.map +0 -1
  427. package/dist/spec/build/scope-resolver.d.ts.map +0 -1
  428. package/dist/spec/build/scope-resolver.js.map +0 -1
  429. package/dist/spec/build/spec-extractor.d.ts.map +0 -1
  430. package/dist/spec/build/spec-extractor.js.map +0 -1
  431. package/dist/spec/config.d.ts.map +0 -1
  432. package/dist/spec/config.js.map +0 -1
  433. package/dist/spec/db/commit-node.d.ts.map +0 -1
  434. package/dist/spec/db/commit-node.js.map +0 -1
  435. package/dist/spec/db/fragment-node.d.ts.map +0 -1
  436. package/dist/spec/db/fragment-node.js.map +0 -1
  437. package/dist/spec/db/fts.d.ts.map +0 -1
  438. package/dist/spec/db/fts.js.map +0 -1
  439. package/dist/spec/db/index.d.ts.map +0 -1
  440. package/dist/spec/db/index.js.map +0 -1
  441. package/dist/spec/db/persist.d.ts.map +0 -1
  442. package/dist/spec/db/persist.js.map +0 -1
  443. package/dist/spec/db/relations.d.ts.map +0 -1
  444. package/dist/spec/db/relations.js.map +0 -1
  445. package/dist/spec/db/schema.d.ts.map +0 -1
  446. package/dist/spec/db/schema.js.map +0 -1
  447. package/dist/spec/db/spec-node.d.ts.map +0 -1
  448. package/dist/spec/db/spec-node.js.map +0 -1
  449. package/dist/spec/db/sql-utils.d.ts.map +0 -1
  450. package/dist/spec/db/sql-utils.js.map +0 -1
  451. package/dist/spec/evolve/cluster-context.d.ts.map +0 -1
  452. package/dist/spec/evolve/cluster-context.js.map +0 -1
  453. package/dist/spec/evolve/commit-spec-analyzer.d.ts.map +0 -1
  454. package/dist/spec/evolve/commit-spec-analyzer.js.map +0 -1
  455. package/dist/spec/evolve/commit-spec-persister.d.ts.map +0 -1
  456. package/dist/spec/evolve/commit-spec-persister.js.map +0 -1
  457. package/dist/spec/evolve/impact-locator.d.ts.map +0 -1
  458. package/dist/spec/evolve/impact-locator.js.map +0 -1
  459. package/dist/spec/evolve/pipeline.d.ts.map +0 -1
  460. package/dist/spec/evolve/pipeline.js.map +0 -1
  461. package/dist/spec/evolve/spec-rewriter.d.ts.map +0 -1
  462. package/dist/spec/evolve/spec-rewriter.js.map +0 -1
  463. package/dist/spec/git/commits.d.ts.map +0 -1
  464. package/dist/spec/git/commits.js.map +0 -1
  465. package/dist/spec/git/exec.d.ts.map +0 -1
  466. package/dist/spec/git/exec.js.map +0 -1
  467. package/dist/spec/git/index.d.ts.map +0 -1
  468. package/dist/spec/git/index.js.map +0 -1
  469. package/dist/spec/graph/index.d.ts.map +0 -1
  470. package/dist/spec/graph/index.js.map +0 -1
  471. package/dist/spec/graph/queries.d.ts.map +0 -1
  472. package/dist/spec/graph/queries.js.map +0 -1
  473. package/dist/spec/llm/agent-client.d.ts.map +0 -1
  474. package/dist/spec/llm/agent-client.js.map +0 -1
  475. package/dist/spec/llm/agents/claude-code.d.ts.map +0 -1
  476. package/dist/spec/llm/agents/claude-code.js.map +0 -1
  477. package/dist/spec/llm/agents/codex.d.ts.map +0 -1
  478. package/dist/spec/llm/agents/codex.js.map +0 -1
  479. package/dist/spec/llm/agents/detect-utils.d.ts.map +0 -1
  480. package/dist/spec/llm/agents/detect-utils.js.map +0 -1
  481. package/dist/spec/llm/agents/deveco-code.d.ts.map +0 -1
  482. package/dist/spec/llm/agents/deveco-code.js.map +0 -1
  483. package/dist/spec/llm/agents/index.d.ts.map +0 -1
  484. package/dist/spec/llm/agents/index.js.map +0 -1
  485. package/dist/spec/llm/agents/types.d.ts.map +0 -1
  486. package/dist/spec/llm/agents/types.js.map +0 -1
  487. package/dist/spec/llm/client.d.ts.map +0 -1
  488. package/dist/spec/llm/client.js.map +0 -1
  489. package/dist/spec/llm/factory.d.ts.map +0 -1
  490. package/dist/spec/llm/factory.js.map +0 -1
  491. package/dist/spec/llm/prompts.d.ts.map +0 -1
  492. package/dist/spec/llm/prompts.js.map +0 -1
  493. package/dist/spec/llm/retry.d.ts.map +0 -1
  494. package/dist/spec/llm/retry.js.map +0 -1
  495. package/dist/spec/mine/addon/adapter.d.ts.map +0 -1
  496. package/dist/spec/mine/addon/adapter.js.map +0 -1
  497. package/dist/spec/mine/addon/render.d.ts.map +0 -1
  498. package/dist/spec/mine/addon/render.js.map +0 -1
  499. package/dist/spec/mine/addon/types.d.ts.map +0 -1
  500. package/dist/spec/mine/addon/types.js.map +0 -1
  501. package/dist/spec/mine/clustering/features.d.ts.map +0 -1
  502. package/dist/spec/mine/clustering/features.js.map +0 -1
  503. package/dist/spec/mine/clustering/index.d.ts.map +0 -1
  504. package/dist/spec/mine/clustering/index.js.map +0 -1
  505. package/dist/spec/mine/clustering/leiden.d.ts.map +0 -1
  506. package/dist/spec/mine/clustering/leiden.js.map +0 -1
  507. package/dist/spec/mine/clustering/text-similarity.d.ts.map +0 -1
  508. package/dist/spec/mine/clustering/text-similarity.js.map +0 -1
  509. package/dist/spec/mine/generator.d.ts.map +0 -1
  510. package/dist/spec/mine/generator.js.map +0 -1
  511. package/dist/spec/mine/persist.d.ts.map +0 -1
  512. package/dist/spec/mine/persist.js.map +0 -1
  513. package/dist/spec/mine/pipeline.d.ts.map +0 -1
  514. package/dist/spec/mine/pipeline.js.map +0 -1
  515. package/dist/spec/mine/scanner.d.ts.map +0 -1
  516. package/dist/spec/mine/scanner.js.map +0 -1
  517. package/dist/spec/types.d.ts.map +0 -1
  518. package/dist/spec/types.js.map +0 -1
  519. package/dist/spec/ui/index.d.ts.map +0 -1
  520. package/dist/spec/ui/index.js.map +0 -1
  521. package/dist/spec/ui/progress-handler.d.ts.map +0 -1
  522. package/dist/spec/ui/progress-handler.js.map +0 -1
  523. package/dist/spec/ui/progress.d.ts.map +0 -1
  524. package/dist/spec/ui/progress.js.map +0 -1
  525. package/dist/spec/utils/fs.d.ts.map +0 -1
  526. package/dist/spec/utils/fs.js.map +0 -1
  527. package/dist/spec/utils/index.d.ts.map +0 -1
  528. package/dist/spec/utils/index.js.map +0 -1
  529. package/dist/spec/utils/meta.d.ts.map +0 -1
  530. package/dist/spec/utils/meta.js.map +0 -1
  531. package/dist/spec/utils/truncate.d.ts.map +0 -1
  532. package/dist/spec/utils/truncate.js.map +0 -1
  533. package/dist/sync/git-hooks.d.ts.map +0 -1
  534. package/dist/sync/git-hooks.js.map +0 -1
  535. package/dist/sync/index.d.ts.map +0 -1
  536. package/dist/sync/index.js.map +0 -1
  537. package/dist/sync/watch-policy.d.ts.map +0 -1
  538. package/dist/sync/watch-policy.js.map +0 -1
  539. package/dist/sync/watcher.d.ts.map +0 -1
  540. package/dist/sync/watcher.js.map +0 -1
  541. package/dist/sync/worktree.d.ts.map +0 -1
  542. package/dist/sync/worktree.js.map +0 -1
  543. package/dist/types.d.ts.map +0 -1
  544. package/dist/types.js.map +0 -1
  545. package/dist/ui/glyphs.d.ts.map +0 -1
  546. package/dist/ui/glyphs.js.map +0 -1
  547. package/dist/ui/shimmer-progress.d.ts.map +0 -1
  548. package/dist/ui/shimmer-progress.js.map +0 -1
  549. package/dist/ui/shimmer-worker.d.ts.map +0 -1
  550. package/dist/ui/shimmer-worker.js.map +0 -1
  551. package/dist/ui/types.d.ts.map +0 -1
  552. package/dist/ui/types.js.map +0 -1
  553. package/dist/upgrade/index.d.ts.map +0 -1
  554. package/dist/upgrade/index.js.map +0 -1
  555. package/dist/upgrade/remove-binary.d.ts.map +0 -1
  556. package/dist/upgrade/remove-binary.js.map +0 -1
  557. package/dist/upgrade/update-check.d.ts.map +0 -1
  558. package/dist/upgrade/update-check.js.map +0 -1
  559. package/dist/utils.d.ts.map +0 -1
  560. package/dist/utils.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,57 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
10
10
  ## [Unreleased]
11
11
 
12
12
 
13
+ ## [1.5.8] - 2026-09-15
14
+
15
+ ### Improvements
16
+
17
+ - SQLite no longer depends on optional `better-sqlite3`. Backends are **`node:sqlite`** (Node ≥22.5 with FTS5) then **`node-sqlite3-wasm`**. Install trees drop ~10 MiB of unused native-addon source when vendor/offline packaging skips `prebuild-install`. `HOMEGRAPH_SQLITE_BACKEND=native` is ignored (use `node-sqlite` or `wasm`). Prefer Node 22.5+ for WAL (Spec 0033).
18
+ - Published `dist/` no longer includes source maps; vendored tree-sitter grammars are copied from an explicit list (unlisted files such as leftover wasm are not shipped). The `openai` package is an optional dependency used only by spec LLM commands — install it when running `homegraph spec` against an API (`npm install openai`). MCP `serve mcp` does not require it (Spec 0031).
19
+ - MCP product hosts get a unified **four-state** index readiness in tool results (`empty` / `fast` / `full` / `syncing`): deep tools and `homegraph_project` return success-shaped guidance with `status=…` instead of ambiguous phase prose; `tools/list` stays fully exposed. Auto-init cold start sets `building_fast` immediately after creating the empty DB, serializes empty-DB creation with `homegraph.lock`, and opens an existing index when a concurrent init wins. **Fast build** runs in-process; **full build** continues in the same MCP/daemon process in the background (`indexAll` yields between batches — no sibling `homegraph index` CLI, so there is no second writer to lock against). SQLite busy / write-lock contention maps to `syncing` rather than `isError`. The file watcher starts after the full build finishes (Spec 0032).
20
+ - ArkTS exploration now finds bounded directed paths between named anchors, selecting intermediate declarations and registration sources together. Typed state/event goals, exact qualified-name recovery, ambiguity gaps and explicit stop reasons reduce missing connections without treating shared callees as a path. `HOMEGRAPH_ARKTS_QUERY_PATHS=0` restores the first-batch evidence strategy for comparison; indexing and external tool interfaces are unchanged (Spec 0030).
21
+ - ArkTS symbol/flow exploration now selects complete source declarations and the dependencies of static relation evidence together. Explicit gaps identify omitted, stale and unindexed evidence; output and planner budgets no longer cut these packs mid-body. Virtual ArkAnalyzer entries are excluded, cache hits validate source fingerprints, and `HOMEGRAPH_ARKTS_EVIDENCE_PACKS=0` restores legacy rendering for comparison (Spec 0029). Literal/resource and focused usages/modules/native routes retain their existing behavior.
22
+
23
+ ### Fixes
24
+
25
+ - An MCP host's explicit project declaration (`--path`, or the client's `rootUri`/`workspaceFolders`) is now a **floor** for root resolution: a stray ancestor `.homegraph/` above it is never adopted. Previously a nested server walked up unbounded and could latch onto an unrelated ancestor index — observed live as a DevEco evaluation session creating `.homegraph` at a benchmark harness root, after which every nested project's daemon tried to index the entire result tree (OOM at 3.5GB in 48s) while its server was SIGKILL'd by the 60s liveness watchdog with every tool call hanging as `Connection closed`. Bare `serve mcp` and CLI commands keep the git-style unbounded walk-up; tool-level `projectPath` resolution is unchanged (Spec 0028).
26
+ - `homegraph_explore`'s description no longer reports `Budget: make at most 1 calls for this project (0 files indexed)` while auto-init is still building. Hosts snapshot `tools/list` once at connect, so that transient "0 files" read as terminal and agents abandoned HomeGraph for the whole session even though the index completed seconds later. The 0-file description now matches what a call actually returns: a failed build asks the agent to relay `homegraph index` to the user, an in-flight build points at `homegraph_project` and says to retry once indexing finishes, and a genuinely empty project says so honestly. Indexed repos keep the usual call-budget note unchanged (Spec 0027).
27
+
28
+ ## [1.5.7] - 2026-09-09
29
+
30
+ ### Fixes
31
+
32
+ - ArkTS indexing aligns with ArkAnalyzer `ClassCategory`: **object literals**, **type literals**, and **unions** are no longer stored as HomeGraph `class` nodes (they were inflating `graph_class` as `<Object$anon@N>` / `%AC*` under the file). Real classes — including true anonymous `ClassCategory.CLASS` — are unchanged. Re-index to refresh existing databases (Spec 0026).
33
+ - Harmony multi-module ArkTS indexing: register **synthetic PROJECT modules** for ArkAnalyzer sources that sit outside `build-profile.json5` `srcPath` (e.g. ohrouter `HMRouterPlugin/**/*.ts`), so they enter the same `analyseByModule` pipeline instead of being skipped by both AA and tree-sitter. Incremental dirty mapping can target those synthetic roots. AA-persisted files now get truthful `files`/`nodes.language` by extension (`.ets`→`arkts`, `.ts`/`.d.ts`→`typescript`) instead of hard-coding `arkts` (Spec 0025).
34
+
35
+ ### Improvements
36
+
37
+ - Prefer ordinary bash/search/read for source localization and use graph tools only for an unresolved relation. Remove mandatory explore-first guidance in both MCP initialization and tool descriptions; retain indexing, query schemas and validation requirements (Spec 0028).
38
+ - Preserve the action and constraints in explore queries, use repository-relative paths, and optionally label node source excerpts with a content identity for trace analysis (`HOMEGRAPH_SOURCE_RECEIPTS=1`, Spec 0027).
39
+
40
+ - MCP `initialize` instructions: **single-file path-pinned edits → Read + edit, skip `homegraph_*`**; explore only when locate/cross-file is needed.
41
+ - Explore **defers** (`Skip HomeGraph`, kind `path-pinned-edit`) when the query names one `…/File.ext` and is a code-change shape — avoids explore context tax on 082-style tasks.
42
+ - Path scaffolding (`features/.../Foo.ets` + basename-as-Type) no longer counts as multi-anchor; `.ets`/`.ts`/… are not parsed as member access.
43
+
44
+ ### New Features
45
+
46
+ - Standard-library Python retrieval debugger with an original-source Spatial Upscale demo, interactive steps, rules/LLM comparison, and persistent MCP/Planner evidence and error records (Spec 0025).
47
+
48
+ - Experimental structured query planning for explore (Spec 0022): shared local routing features; optional, explicitly configured one-call model intent/decomposition/rephrase; bounded dependent retrieval with a shared deadline/output budget, validated anchors, worker propagation, context hints and direction-aware cache keys. Model failures fall back locally; compact diagnostic metadata includes planning usage/time and per-step coverage. No remote model calls by default.
49
+
50
+ ### Fixes
51
+
52
+ - Grounded retrieval plans separate concise semantic concepts, verbatim UI text, exact anchors, source scope and relationship direction. Unanchored reference requests first discover source and retain the missing reference obligation. Bounded literal/resource lookup prioritizes local application evidence; rendering deduplicates same-source declarations and marks incomplete evidence. Repeat protection permits a bounded recovery for weak or changed evidence, and retrieval guidance no longer closes the coding task (Spec 0024).
53
+ - The optional model planner now requests English step queries and short English semantic search terms, while preserving literal identifiers, paths and task constraints. This is a prompt-only refinement: retrieval, anchor validation, request count and budgets are unchanged (Spec 0023).
54
+ - Model-planned explore steps now keep their own retrieval terms instead of repeating the whole task as search seeds. General/flow steps consume planned hints through full context retrieval; task constraints remain separate. Dependency candidates come only from displayed source declarations and retain node/file identity, with visible location receipts surviving shared-output trimming. Unseen fuzzy hits and inherited nodes no longer manufacture new bindings; default rule routes are unchanged (Spec 0023).
55
+ - Explicit model planning now considers task-scoped natural-language queries before shape fast paths; exact symbol/path lookups remain cheap. Compact metadata explains planning eligibility, skip reasons and the original rule route, separately from provider failures (Spec 0023).
56
+ - Planner instructions distinguish read-only evidence lookup from code-editing workflows and provide a compact JSON shape; more than three steps still fail closed, with a specific step-count diagnostic and no silent truncation or retry (Spec 0023).
57
+ - After a model planning request fails, local fallback retrieval now uses the remaining shared deadline instead of the unbounded main-thread fast path; rule-only fast retrieval is unchanged (Spec 0023).
58
+ - Query planning keeps framework labels out of lexical retrieval, preserves host-provided task constraints before agent shorthand, accepts bounded numeric step IDs, and supports an explicit planning timeout up to 10 seconds while reserving retrieval time within the shared deadline (default remains 5 seconds; Spec 0023).
59
+ - Experimental query planning (Spec 0023): focused feature queries cannot be broadened into whole-project overviews by a model rewrite. Optional bounded task context preserves original actions/product scope across planning and cache keys; model-proposed broad anchors are discarded when an unauthorized overview is downgraded. Explicit project maps remain supported.
60
+ - An explicit `HOMEGRAPH_MCP_TOOLS` selection now overrides default small-repository tool trimming, so requested specialized tools remain callable on small ArkTS projects (Spec 0023).
61
+
62
+ - MCP first-tool guidance now gives `homegraph_usages`, `homegraph_modules`, and `homegraph_native` mutually exclusive priority for their narrow intents instead of simultaneously telling agents those questions are explore-first; general `homegraph_explore` remains the compatibility fallback and still auto-routes high-confidence shapes.
63
+
13
64
  ## [1.5.6] - 2026-09-03
14
65
 
15
66
  ### New Features
@@ -187,3 +238,5 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
187
238
  [1.5.0]: https://gitcode.com/ProgramAnalysis/homegraph/tags/v1.5.0
188
239
  [1.4.1]: https://gitcode.com/ProgramAnalysis/homegraph/tags/v1.4.1
189
240
  [1.5.6]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.6
241
+ [1.5.7]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.7
242
+ [1.5.8]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.8
package/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  ### 1. 安装 CLI
17
17
 
18
- 需要 **Node.js 22+**(推荐 22.5+ 或 24)。SQLite 优先用内置 `node:sqlite`(≥22.5),否则 `better-sqlite3`(12.x),再不行回退 `node-sqlite3-wasm`。
18
+ 需要 **Node.js 22+**(推荐 22.5+ 或 24)。SQLite 优先用内置 `node:sqlite`(≥22.5 且含 FTS5),否则回退 `node-sqlite3-wasm`。
19
19
 
20
20
  ```bash
21
21
  npm install -g homegraph
@@ -179,10 +179,10 @@ Agent 侧工具名前缀为 `homegraph_`。
179
179
 
180
180
  | 工具 | 用途 |
181
181
  |------|------|
182
- | `homegraph_explore` | **主工具**:一次调用返回相关符号的完整源码、调用路径与影响范围;支持自然语言问题或符号/文件名列表。高置信度的用法 / 模块依赖 / NAPI 问法会委派到下方三个聚焦工具的同一套 survey |
183
- | `homegraph_usages` | 只读用法清单:命名 API / member / field / 常量的引用与调用点(常量袋可走有界文本扫描) |
184
- | `homegraph_modules` | 只读模块依赖 / 循环依赖清单(命名模块或路径) |
185
- | `homegraph_native` | 只读 NAPI / native export 清单(命名路径或 Type) |
182
+ | `homegraph_usages` | **精确用法清单首选**:查询一个已命名 API、成员、常量或字段在哪里被引用 |
183
+ | `homegraph_modules` | **模块拓扑首选**:查询已命名模块之间的依赖关系或循环依赖 |
184
+ | `homegraph_native` | **Native 边界首选**:查询已命名路径或类型的 NAPI/native 导出和注册位置 |
185
+ | `homegraph_explore` | **通用结构探索**:一次调用返回相关符号的源码、调用路径与影响范围;窄清单问题优先使用上面三个专用工具 |
186
186
  | `homegraph_search` | 按名称快速搜索符号(仅返回位置,不含源码) |
187
187
  | `homegraph_node` | 读取单个符号或整个文件的源码(带行号)及调用关系;可替代 Read 读文件 |
188
188
  | `homegraph_callers` / `homegraph_callees` | 查看调用方 / 被调用方 |
@@ -195,6 +195,12 @@ Agent 侧工具名前缀为 `homegraph_`。
195
195
  | `homegraph_spec_find` | 根据文件路径反向查找关联的Spec |
196
196
  | `homegraph_spec_trace` | 根据代码符号追溯回关联的Spec |
197
197
 
198
+ ### 查询规划(实验性)
199
+
200
+ `homegraph_explore` 现在共用结构化查询计划:默认 `HOMEGRAPH_QUERY_PLANNER=rules`,保持本地确定性路由;`off` 可回退旧执行路径。显式启用 `llm` 后,复杂问题可在一次模型调用中做意图识别、问题分解和检索改写,再复用既有工具的内部实现。
201
+
202
+ 模型规划需要单独配置 URL、模型和密钥;仅发送问题,不发送仓库源码。最多 3 个子任务共用截止时间和输出预算,规划失败退回本地规则。配置、指标、限制见 [查询规划指南](docs/query-planning.md)。这不是新增的 CodeGraph 构建算法,也尚未证明能降低真实任务的 token 或延迟。
203
+
198
204
  ### Commit4Spec(Spec知识图谱)
199
205
 
200
206
  Commit4Spec 提供两条互补路径将设计Spec与 Git 历史关联,存入 `.homegraph/commit4spec/commit4spec.db`:
@@ -350,7 +356,7 @@ Cursor 等项目级配置写入 `./.cursor/mcp.json`,格式相同。推荐使
350
356
 
351
357
  ## 环境要求
352
358
 
353
- - Node.js **22+**(推荐 22.5+ 或 24;SQLite:`node:sqlite` → better-sqlite3 12.x → wasm)
359
+ - Node.js **22+**(推荐 22.5+ 或 24;SQLite:`node:sqlite` → wasm)
354
360
  - 首次索引时会对项目源码做 AST 解析,大型仓库首次 `init -i` 可能需要数分钟
355
361
  - WSL2 下若项目位于 Windows 盘符(`/mnt/c` 等)且 MCP 连接不稳定,可设置 `HOMEGRAPH_NO_DAEMON=1` 跳过共享后台服务,每个会话独立运行
356
362
 
@@ -573,6 +573,7 @@ function main() {
573
573
  .option('-f, --force', 'Index even if the path looks like your home directory or a filesystem root')
574
574
  .option('-q, --quiet', 'Suppress progress output')
575
575
  .option('-v, --verbose', 'Show detailed worker lifecycle and memory info')
576
+ .option('--inplace', 'Index into the existing database without recreating it (MCP auto-init; DB may already be open by the parent)')
576
577
  .action(async (pathArg, options) => {
577
578
  const projectPath = resolveProjectPath(pathArg);
578
579
  try {
@@ -589,16 +590,13 @@ function main() {
589
590
  process.exit(1);
590
591
  }
591
592
  const { default: HomeGraph } = await loadHomeGraph();
592
- // `index` is a FULL re-index — identical to a fresh `init`. RECREATE the
593
- // database from scratch (discard .homegraph/homegraph.db + its WAL) rather
594
- // than opening the old graph and DELETE-ing every row. The clear-then-index
595
- // approach reported "0 nodes" without the clear (#874); the recreate keeps
596
- // that fixed AND avoids the failure mode where, on a large or pre-fix
597
- // poisoned index, the per-row FTS delete churn wedged the main thread long
598
- // enough to trip the liveness watchdog before scanning even began (#1067).
599
- // recreate() hands back a fresh, empty instance — no clear() needed. For
600
- // fast incremental updates use `sync`.
601
- const cg = await HomeGraph.recreate(projectPath);
593
+ // Default `index` is a FULL re-index via recreate(). MCP auto-init already
594
+ // created an empty DB and keeps it open in the parent — recreate() cannot
595
+ // unlink the file on Windows (EPERM) and the detached child exits with 0
596
+ // files (Spec 0032). `--inplace` opens the existing DB and indexAll()s.
597
+ const cg = options.inplace
598
+ ? await HomeGraph.open(projectPath, { sources: 'both' })
599
+ : await HomeGraph.recreate(projectPath);
602
600
  // Supervise the indexer: self-terminate if orphaned (parent shim killed)
603
601
  // or if the main thread wedges — neither was guarded on this path (#999).
604
602
  const supervision = (0, command_supervision_1.installCommandSupervision)('index');
@@ -809,10 +807,9 @@ function main() {
809
807
  warn('The write-ahead log is larger than the database — killed sessions left it behind. It is reclaimed automatically on open; if it persists across runs, another live HomeGraph process is holding it.');
810
808
  }
811
809
  }
812
- // Prefer node:sqlite → better-sqlite3; wasm is last-resort (no WAL).
810
+ // Prefer node:sqlite; wasm is last-resort (no WAL).
813
811
  const backendLabel = backend === 'node-sqlite' ? chalk.green('node-sqlite')
814
- : backend === 'native' ? chalk.green('native (better-sqlite3)')
815
- : chalk.yellow(`wasm ${(0, glyphs_1.getGlyphs)().dash} slower fallback; use Node 22.5+ or \`npm rebuild better-sqlite3\``);
812
+ : chalk.yellow(`wasm ${(0, glyphs_1.getGlyphs)().dash} slower fallback; use Node 22.5+ for built-in node:sqlite`);
816
813
  console.log(` Backend: ${backendLabel}`);
817
814
  const journalLabel = journalMode === 'wal'
818
815
  ? chalk.green('wal')
@@ -1415,7 +1412,12 @@ function main() {
1415
1412
  * explains this to anyone who runs it by hand.
1416
1413
  */
1417
1414
  async function runServeMcp(options) {
1418
- const projectPath = options.path ? resolveProjectPath(options.path) : undefined;
1415
+ // An MCP host's --path is a DECLARATION of the project root, not a search
1416
+ // hint: resolve it literally and never walk up past it (spec 0028). A stray
1417
+ // ancestor .homegraph above the declared root otherwise hijacks the session
1418
+ // (observed as a harness-root index poisoning every nested bench project).
1419
+ // resolveProjectPath keeps its subdir walk-up for the human CLI subcommands.
1420
+ const projectPath = options.path ? path.resolve(options.path) : undefined;
1419
1421
  // Commander sets watch=false when --no-watch is passed. Route it through
1420
1422
  // the same env-var chokepoint the watcher and MCP server already honor.
1421
1423
  if (options.watch === false) {
@@ -48,6 +48,7 @@ const errors_1 = require("../errors");
48
48
  const utils_1 = require("../utils");
49
49
  const query_utils_1 = require("../search/query-utils");
50
50
  const markers_1 = require("./markers");
51
+ const literal_evidence_1 = require("../search/literal-evidence");
51
52
  /**
52
53
  * Extract likely symbol names from a natural language query
53
54
  *
@@ -204,6 +205,33 @@ const DEFAULT_FIND_OPTIONS = {
204
205
  edgeKinds: [],
205
206
  nodeKinds: HIGH_VALUE_NODE_KINDS, // Filter out imports/exports by default
206
207
  };
208
+ /** Hints may cross a worker/library boundary; never trust their runtime shape. */
209
+ function normalizeRetrievalHints(value) {
210
+ if (!value || typeof value !== 'object' || Array.isArray(value))
211
+ return undefined;
212
+ const hints = value;
213
+ if (!Array.isArray(hints.symbols) || !Array.isArray(hints.searchTerms))
214
+ return undefined;
215
+ const normalize = (items, lowerCase) => {
216
+ const result = new Set();
217
+ for (const item of items.slice(0, 32)) {
218
+ if (typeof item !== 'string' || item.length > 256 || /[\u0000-\u001f\u007f]/.test(item))
219
+ continue;
220
+ const term = item.trim();
221
+ if (term)
222
+ result.add(lowerCase ? term.toLowerCase() : term);
223
+ }
224
+ return [...result];
225
+ };
226
+ return {
227
+ symbols: normalize(hints.symbols, false),
228
+ searchTerms: normalize(hints.searchTerms, true),
229
+ ...(Array.isArray(hints.nodeIds) ? { nodeIds: normalize(hints.nodeIds, false) } : {}),
230
+ ...(Array.isArray(hints.literalTexts) ? { literalTexts: (0, literal_evidence_1.normalizeLiteralTexts)(hints.literalTexts) } : {}),
231
+ ...(['local', 'sdk', 'all'].includes(String(hints.sourceScope))
232
+ ? { sourceScope: hints.sourceScope } : {}),
233
+ };
234
+ }
207
235
  // Re-export the low-confidence sentinel (defined in a dependency-free leaf so
208
236
  // the MCP layer can import it without pulling this module's deps onto the
209
237
  // cold-start path). Builder code below uses the imported binding directly.
@@ -455,18 +483,58 @@ class ContextBuilder {
455
483
  */
456
484
  async findRelevantContext(query, options = {}) {
457
485
  const opts = { ...DEFAULT_FIND_OPTIONS, ...options };
486
+ const hints = normalizeRetrievalHints(opts.retrievalHints);
458
487
  // Start with empty subgraph
459
488
  const nodes = new Map();
460
489
  const edges = [];
461
490
  const roots = [];
462
- // Handle empty query - return empty subgraph
463
- if (!query || query.trim().length === 0) {
491
+ // Identity-only retrieval does not need to invent a lexical query.
492
+ if ((!query || query.trim().length === 0) && !hints?.nodeIds?.length && !hints?.literalTexts?.length) {
464
493
  return { nodes, edges, roots };
465
494
  }
466
495
  // === HYBRID SEARCH ===
467
- // Step 1: Extract potential symbol names from query
468
- const symbolsFromQuery = extractSymbolsFromQuery(query);
469
- (0, errors_1.logDebug)('Extracted symbols from query', { query, symbols: symbolsFromQuery });
496
+ // Step 1: Reuse the shared plan when supplied. An intentionally empty hint
497
+ // list remains empty: re-extracting from the question would undo planning.
498
+ const symbolsFromQuery = hints?.symbols ?? extractSymbolsFromQuery(query);
499
+ const searchTerms = hints?.searchTerms ?? (0, query_utils_1.extractSearchTerms)(query);
500
+ (0, errors_1.logDebug)('Context retrieval symbols', { query, symbols: symbolsFromQuery, planned: !!hints });
501
+ // A binding is an identity, not a name search hint. Revalidate it in this
502
+ // index and keep it outside fuzzy scoring/import redirection: converting a
503
+ // bound ID back to a bare name can silently switch to another file's node.
504
+ // Explicit kind filters still apply; the default lexical kind filter must
505
+ // not discard an explicitly bound file/import/property node.
506
+ const boundResults = [];
507
+ for (const id of hints?.nodeIds ?? []) {
508
+ const node = this.queries.getNodeById(id);
509
+ if (!node || (options.nodeKinds?.length && !options.nodeKinds.includes(node.kind)))
510
+ continue;
511
+ boundResults.push({ node, score: 0 });
512
+ }
513
+ const boundIds = new Set(boundResults.map(result => result.node.id));
514
+ // Verbatim labels are an independent retrieval channel. The witness range
515
+ // stays available even when the UI/resource file has no extracted AST node.
516
+ const literalEvidence = hints?.literalTexts?.length && hints.sourceScope !== 'sdk'
517
+ ? (0, literal_evidence_1.findLiteralEvidence)(this.projectRoot, {
518
+ literalTexts: hints.literalTexts,
519
+ files: this.queries.getAllFiles().map(file => file.path),
520
+ }) : undefined;
521
+ const literalResults = [];
522
+ const literalIds = new Set();
523
+ for (const hit of literalEvidence?.hits ?? []) {
524
+ const candidates = this.queries.getNodesByFile(hit.filePath)
525
+ .filter(node => node.startLine <= hit.line && node.endLine >= hit.line
526
+ && !['import', 'export', 'parameter'].includes(node.kind)
527
+ && (!options.nodeKinds?.length || options.nodeKinds.includes(node.kind)))
528
+ .sort((a, b) => {
529
+ const callable = (node) => ['method', 'function', 'component'].includes(node.kind) ? 1 : 0;
530
+ return callable(b) - callable(a) || (a.endLine - a.startLine) - (b.endLine - b.startLine);
531
+ });
532
+ const node = candidates[0];
533
+ if (node && !literalIds.has(node.id)) {
534
+ literalIds.add(node.id);
535
+ literalResults.push({ node, score: 1000 });
536
+ }
537
+ }
470
538
  // Step 2: Look up exact matches for extracted symbols
471
539
  let exactMatches = [];
472
540
  if (symbolsFromQuery.length > 0) {
@@ -618,7 +686,6 @@ class ContextBuilder {
618
686
  // where file names are the primary identifiers.
619
687
  let textResults = [];
620
688
  try {
621
- const searchTerms = (0, query_utils_1.extractSearchTerms)(query);
622
689
  if (searchTerms.length > 0) {
623
690
  // Search each term individually to get broader coverage,
624
691
  // then boost results that match multiple terms
@@ -736,7 +803,7 @@ class ContextBuilder {
736
803
  // than nodes matching just one generic term. Without this, "ExecutionUtils"
737
804
  // (matches only "execution") fills budget slots meant for "ShardSearchRequest"
738
805
  // (matches "shard" + "search" + "request").
739
- const queryTermsForBoost = (0, query_utils_1.extractSearchTerms)(query);
806
+ const queryTermsForBoost = searchTerms;
740
807
  if (queryTermsForBoost.length >= 2) {
741
808
  // Group terms that are substrings of each other (stem variants of the same
742
809
  // root word). "indexed", "indexe", "index" should count as ONE concept match,
@@ -976,6 +1043,13 @@ class ContextBuilder {
976
1043
  // Final sort and truncation — all search channels (exact, text, CamelCase,
977
1044
  // compound) have now contributed. Sort by score so multi-term matches from
978
1045
  // later steps can outrank dampened single-term matches from earlier steps.
1046
+ // Planner scope is explicit, not a growing vocabulary of prose stopwords.
1047
+ // SDK-only lexical matches cannot establish a local business entry point.
1048
+ const isSdkResult = (result) => result.node.filePath.startsWith('ohos-sdk:');
1049
+ if (hints?.sourceScope === 'local')
1050
+ searchResults = searchResults.filter(result => !isSdkResult(result));
1051
+ else if (hints?.sourceScope === 'sdk')
1052
+ searchResults = searchResults.filter(isSdkResult);
979
1053
  searchResults.sort((a, b) => b.score - a.score);
980
1054
  searchResults = searchResults.slice(0, opts.searchLimit * 3);
981
1055
  // Filter by minimum score
@@ -984,6 +1058,22 @@ class ContextBuilder {
984
1058
  // If someone searches "terminal" and finds `import { TerminalPanel }`,
985
1059
  // they want the TerminalPanel class, not the import statement
986
1060
  filteredResults = this.resolveImportsToDefinitions(filteredResults);
1061
+ if (hints?.sourceScope === 'local')
1062
+ filteredResults = filteredResults.filter(result => !isSdkResult(result));
1063
+ if (hints?.sourceScope === 'sdk')
1064
+ filteredResults = filteredResults.filter(isSdkResult);
1065
+ if (literalResults.length) {
1066
+ // Reserve first roots for observed UI text before native graph-density
1067
+ // heuristics. Bound identities, if supplied below, still take priority.
1068
+ filteredResults = [...literalResults, ...filteredResults.filter(result => !literalIds.has(result.node.id))];
1069
+ }
1070
+ if (boundResults.length > 0) {
1071
+ const rootLimit = Math.max(0, Math.min(Number.isFinite(opts.searchLimit) ? Math.floor(opts.searchLimit) : DEFAULT_FIND_OPTIONS.searchLimit, Number.isFinite(opts.maxNodes) ? Math.floor(opts.maxNodes) : DEFAULT_FIND_OPTIONS.maxNodes));
1072
+ filteredResults = [
1073
+ ...boundResults,
1074
+ ...filteredResults.filter(result => !boundIds.has(result.node.id)),
1075
+ ].slice(0, rootLimit);
1076
+ }
987
1077
  // Cap entry points so traversal budget isn't spread too thin.
988
1078
  // With 36 entry points and maxNodes=120, each gets only 3 nodes — useless.
989
1079
  // Cap to searchLimit so each entry point gets a meaningful traversal budget.
@@ -999,7 +1089,8 @@ class ContextBuilder {
999
1089
  // Single-keyword and symbol-name queries are exempt (their single match IS the
1000
1090
  // answer), so the handoff never fires on them.
1001
1091
  let confidence = 'high';
1002
- const confTerms = (0, query_utils_1.extractSearchTerms)(query, { stems: false }).filter(t => t.length >= 3);
1092
+ const confTerms = (hints?.searchTerms ?? (0, query_utils_1.extractSearchTerms)(query, { stems: false }))
1093
+ .filter(t => t.length >= 3);
1003
1094
  if (confTerms.length >= 2 && filteredResults.length > 0) {
1004
1095
  const distinctive = new Set(symbolsFromQuery.filter(query_utils_1.isDistinctiveIdentifier).map(s => s.toLowerCase()));
1005
1096
  const anyStrong = filteredResults.some(r => {
@@ -1016,7 +1107,7 @@ class ContextBuilder {
1016
1107
  }
1017
1108
  return false;
1018
1109
  });
1019
- if (!anyStrong)
1110
+ if (!anyStrong && !literalResults.length)
1020
1111
  confidence = 'low';
1021
1112
  }
1022
1113
  // Add entry points to subgraph
@@ -1030,7 +1121,10 @@ class ContextBuilder {
1030
1121
  // ensures subclasses and superclasses always appear in results.
1031
1122
  // Budget: up to maxNodes/4 hierarchy nodes to avoid flooding.
1032
1123
  const typeHierarchyKinds = new Set(['class', 'interface', 'struct', 'trait', 'protocol']);
1033
- const maxHierarchyNodes = Math.ceil(opts.maxNodes / 4);
1124
+ // Identity-bound retrieval uses the bounded BFS below for hierarchy edges
1125
+ // as well. The legacy full hierarchy survey ignores traversalDepth and can
1126
+ // visit an entire family even for a depth-zero binding lookup.
1127
+ const maxHierarchyNodes = boundResults.length > 0 ? 0 : Math.ceil(opts.maxNodes / 4);
1034
1128
  let hierarchyNodesAdded = 0;
1035
1129
  for (const result of filteredResults) {
1036
1130
  if (hierarchyNodesAdded >= maxHierarchyNodes)
@@ -1153,14 +1247,19 @@ class ContextBuilder {
1153
1247
  method: 1, function: 1, property: 0, field: 0, variable: 0,
1154
1248
  };
1155
1249
  nodeIds.sort((a, b) => {
1250
+ const bindingOrder = Number(boundIds.has(b)) - Number(boundIds.has(a));
1251
+ if (bindingOrder)
1252
+ return bindingOrder;
1156
1253
  const aRoot = rootSet.has(a) ? 10 : 0;
1157
1254
  const bRoot = rootSet.has(b) ? 10 : 0;
1158
1255
  const aKind = kindPriority[finalNodes.get(a).kind] ?? 0;
1159
1256
  const bKind = kindPriority[finalNodes.get(b).kind] ?? 0;
1160
1257
  return (bRoot + bKind) - (aRoot + aKind);
1161
1258
  });
1162
- // Remove excess nodes (keep the highest-priority ones)
1163
- for (const id of nodeIds.slice(maxPerFile)) {
1259
+ // Explicit identities already paid for a bounded root slot. Diversity
1260
+ // preferences must not erase them; total maxNodes still remains a cap.
1261
+ const keepPerFile = Math.max(maxPerFile, nodeIds.filter(id => boundIds.has(id)).length);
1262
+ for (const id of nodeIds.slice(keepPerFile)) {
1164
1263
  finalNodes.delete(id);
1165
1264
  }
1166
1265
  }
@@ -1168,12 +1267,13 @@ class ContextBuilder {
1168
1267
  // at most 15% of the budget. Many codebases have dozens of near-identical
1169
1268
  // test implementations (e.g., 6 Guard classes in integration tests) that
1170
1269
  // individually survive score dampening but collectively flood the result.
1171
- // Test entry points are NOT exempt — they should be evicted too.
1270
+ // Lexically chosen test entry points are NOT exempt. Explicit identity
1271
+ // bindings are exempt from this preference, but not from maxNodes.
1172
1272
  if (!isTestQuery) {
1173
1273
  const maxNonProd = Math.max(3, Math.ceil(opts.maxNodes * 0.15));
1174
1274
  const nonProdIds = [];
1175
1275
  for (const [id, node] of finalNodes) {
1176
- if ((0, query_utils_1.isTestFile)(node.filePath)) {
1276
+ if ((0, query_utils_1.isTestFile)(node.filePath) && !boundIds.has(id)) {
1177
1277
  nonProdIds.push(id);
1178
1278
  }
1179
1279
  }
@@ -1201,7 +1301,12 @@ class ContextBuilder {
1201
1301
  existingEdgeKeys.add(key);
1202
1302
  }
1203
1303
  }
1204
- return { nodes: finalNodes, edges: finalEdges, roots, confidence };
1304
+ return {
1305
+ nodes: finalNodes, edges: finalEdges,
1306
+ roots: boundResults.length > 0 ? roots.filter(id => finalNodes.has(id)) : roots,
1307
+ confidence,
1308
+ ...(literalEvidence ? { literalEvidence } : {}),
1309
+ };
1205
1310
  }
1206
1311
  /**
1207
1312
  * Get the source code for a node
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { SqliteDatabase, SqliteBackend } from './sqlite-adapter';
7
7
  import { SchemaVersion } from '../types';
8
- export { SqliteDatabase, SqliteBackend, WASM_FALLBACK_FIX_RECIPE, isNodeSqliteAvailable, isNodeSqliteFts5Available, isNativeSqliteAvailable, } from './sqlite-adapter';
8
+ export { SqliteDatabase, SqliteBackend, WASM_FALLBACK_FIX_RECIPE, isNodeSqliteAvailable, isNodeSqliteFts5Available, } from './sqlite-adapter';
9
9
  /**
10
10
  * WAL size past which `healOversizedWal` (run at every `open`) checkpoints and
11
11
  * truncates the file, and to which `journal_size_limit` clips the WAL after any
package/dist/db/index.js CHANGED
@@ -38,7 +38,7 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  };
39
39
  })();
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.DATABASE_FILENAME = exports.DatabaseConnection = exports.WAL_HEAL_THRESHOLD_BYTES = exports.isNativeSqliteAvailable = exports.isNodeSqliteFts5Available = exports.isNodeSqliteAvailable = exports.WASM_FALLBACK_FIX_RECIPE = void 0;
41
+ exports.DATABASE_FILENAME = exports.DatabaseConnection = exports.WAL_HEAL_THRESHOLD_BYTES = exports.isNodeSqliteFts5Available = exports.isNodeSqliteAvailable = exports.WASM_FALLBACK_FIX_RECIPE = void 0;
42
42
  exports.resolveWalHealBytes = resolveWalHealBytes;
43
43
  exports.getDatabasePath = getDatabasePath;
44
44
  exports.removeDatabaseFiles = removeDatabaseFiles;
@@ -51,7 +51,6 @@ var sqlite_adapter_2 = require("./sqlite-adapter");
51
51
  Object.defineProperty(exports, "WASM_FALLBACK_FIX_RECIPE", { enumerable: true, get: function () { return sqlite_adapter_2.WASM_FALLBACK_FIX_RECIPE; } });
52
52
  Object.defineProperty(exports, "isNodeSqliteAvailable", { enumerable: true, get: function () { return sqlite_adapter_2.isNodeSqliteAvailable; } });
53
53
  Object.defineProperty(exports, "isNodeSqliteFts5Available", { enumerable: true, get: function () { return sqlite_adapter_2.isNodeSqliteFts5Available; } });
54
- Object.defineProperty(exports, "isNativeSqliteAvailable", { enumerable: true, get: function () { return sqlite_adapter_2.isNativeSqliteAvailable; } });
55
54
  /**
56
55
  * Apply connection-level PRAGMAs. Shared by `initialize` and `open` so the two
57
56
  * paths can't drift.
@@ -62,9 +61,9 @@ Object.defineProperty(exports, "isNativeSqliteAvailable", { enumerable: true, ge
62
61
  * the lock instead of throwing "database is locked" immediately. See issue #238.
63
62
  *
64
63
  * The 5s window (was 120s) rides out a normal incremental sync; the old
65
- * 2-minute wait presented as a frozen, hung agent. With WAL (node:sqlite or
66
- * better-sqlite3), reads never block on a writer, so this timeout only governs
67
- * cross-process write contention. The WASM fallback remaps WAL → DELETE.
64
+ * 2-minute wait presented as a frozen, hung agent. With WAL (node:sqlite),
65
+ * reads never block on a writer, so this timeout only governs cross-process
66
+ * write contention. The WASM fallback remaps WAL → DELETE.
68
67
  */
69
68
  function configureConnection(db) {
70
69
  db.pragma('busy_timeout = 5000'); // MUST be first — see above
@@ -593,9 +592,8 @@ class DatabaseConnection {
593
592
  return null;
594
593
  }
595
594
  }
596
- // WASM has no real WAL; mixing node:sqlite with a better-sqlite3 main
597
- // connection (e.g. Node 23 where node:sqlite lacks FTS5) corrupts WAL state.
598
- if (this.backend !== 'node-sqlite' && this.backend !== 'native') {
595
+ // WASM has no real WAL — only checkpoint node:sqlite connections.
596
+ if (this.backend !== 'node-sqlite') {
599
597
  return null;
600
598
  }
601
599
  try {
@@ -605,14 +603,8 @@ class DatabaseConnection {
605
603
  let row = null;
606
604
  let err = null;
607
605
  try {
608
- let db = null;
609
- if (workerData.backend === 'native') {
610
- const Database = require('better-sqlite3');
611
- db = new Database(workerData.dbPath);
612
- } else {
613
- const { DatabaseSync } = require('node:sqlite');
614
- db = new DatabaseSync(workerData.dbPath);
615
- }
606
+ const { DatabaseSync } = require('node:sqlite');
607
+ const db = new DatabaseSync(workerData.dbPath);
616
608
  const mode = workerData.mode === 'TRUNCATE' ? 'TRUNCATE' : 'PASSIVE';
617
609
  try {
618
610
  if (mode === 'TRUNCATE') db.exec('PRAGMA busy_timeout = 2000');
@@ -633,7 +625,7 @@ class DatabaseConnection {
633
625
  try {
634
626
  const worker = new Worker(workerSource, {
635
627
  eval: true,
636
- workerData: { dbPath: this.dbPath, mode, backend: this.backend },
628
+ workerData: { dbPath: this.dbPath, mode },
637
629
  });
638
630
  worker.once('message', (m) => {
639
631
  if (m?.err && process.env.HOMEGRAPH_WAL_VALVE_DEBUG) {
@@ -721,14 +713,8 @@ class DatabaseConnection {
721
713
  const workerSource = `
722
714
  const { workerData, parentPort } = require('node:worker_threads');
723
715
  try {
724
- let db = null;
725
- try {
726
- const { DatabaseSync } = require('node:sqlite');
727
- db = new DatabaseSync(workerData.dbPath);
728
- } catch {
729
- const Database = require('better-sqlite3');
730
- db = new Database(workerData.dbPath);
731
- }
716
+ const { DatabaseSync } = require('node:sqlite');
717
+ const db = new DatabaseSync(workerData.dbPath);
732
718
  for (const p of workerData.pragmas) { try { db.exec(p); } catch {} }
733
719
  try { db.close(); } catch {}
734
720
  } catch {}
@@ -268,7 +268,7 @@ export declare class QueryBuilder {
268
268
  /**
269
269
  * Get nodes by exact qualified name match (uses idx_nodes_qualified_name index)
270
270
  */
271
- getNodesByQualifiedNameExact(qualifiedName: string): Node[];
271
+ getNodesByQualifiedNameExact(qualifiedName: string, limit?: number): Node[];
272
272
  /**
273
273
  * Get nodes by lowercase name match (uses idx_nodes_lower_name expression index)
274
274
  */
@@ -349,6 +349,10 @@ export declare class QueryBuilder {
349
349
  * Get incoming edges to a node
350
350
  */
351
351
  getIncomingEdges(targetId: string, kinds?: EdgeKind[], limit?: number): Edge[];
352
+ /** Bounded local adjacency for evidence search; never load a whole hub into JS.
353
+ * Known endpoints get a small indexed lookup before the bounded neighbor scan.
354
+ */
355
+ getEvidenceEdges(nodeId: string, direction: 'outgoing' | 'incoming', kinds: EdgeKind[], limit: number, preferredIds?: string[]): Edge[];
352
356
  /**
353
357
  * Find all edges where both source and target are in the given node set.
354
358
  * Useful for recovering inter-node connectivity after BFS.
@@ -626,7 +626,7 @@ class QueryBuilder {
626
626
  if (misses.length === 0)
627
627
  return out;
628
628
  // Chunk under SQLite's parameter limit (default 999, raised to 32766
629
- // in better-sqlite3 builds — chunk at 500 for safety across both
629
+ // across node:sqlite / wasm builds — chunk at 500 for safety across both
630
630
  // backends and to keep the query plan simple).
631
631
  for (let i = 0; i < misses.length; i += SQLITE_PARAM_CHUNK_SIZE) {
632
632
  const chunk = misses.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
@@ -921,7 +921,12 @@ class QueryBuilder {
921
921
  /**
922
922
  * Get nodes by exact qualified name match (uses idx_nodes_qualified_name index)
923
923
  */
924
- getNodesByQualifiedNameExact(qualifiedName) {
924
+ getNodesByQualifiedNameExact(qualifiedName, limit) {
925
+ if (limit !== undefined) {
926
+ const cap = Number.isFinite(limit) ? Math.max(1, Math.min(100, Math.floor(limit))) : 25;
927
+ return this.db.prepare('SELECT * FROM nodes WHERE qualified_name = ? LIMIT ?')
928
+ .all(qualifiedName, cap).map(rowToNode);
929
+ }
925
930
  if (!this.stmts.getNodesByQualifiedNameExact) {
926
931
  this.stmts.getNodesByQualifiedNameExact = this.db.prepare('SELECT * FROM nodes WHERE qualified_name = ?');
927
932
  }
@@ -1571,6 +1576,30 @@ class QueryBuilder {
1571
1576
  const rows = this.stmts.getEdgesByTarget.all(targetId);
1572
1577
  return rows.map(rowToEdge);
1573
1578
  }
1579
+ /** Bounded local adjacency for evidence search; never load a whole hub into JS.
1580
+ * Known endpoints get a small indexed lookup before the bounded neighbor scan.
1581
+ */
1582
+ getEvidenceEdges(nodeId, direction, kinds, limit, preferredIds = []) {
1583
+ if (!kinds.length)
1584
+ return [];
1585
+ const cap = Number.isFinite(limit) ? Math.max(1, Math.min(100, Math.floor(limit))) : 25;
1586
+ const column = direction === 'incoming' ? 'target' : 'source';
1587
+ const opposite = direction === 'incoming' ? 'source' : 'target';
1588
+ const kindsSql = kinds.map(() => '?').join(',');
1589
+ const preferred = [...new Set(preferredIds)].slice(0, 4);
1590
+ const base = `SELECT * FROM edges WHERE ${column} = ? AND kind IN (${kindsSql})`;
1591
+ const rows = [];
1592
+ if (preferred.length) {
1593
+ rows.push(...this.db.prepare(`${base} AND ${opposite} IN (${preferred.map(() => '?').join(',')}) LIMIT ?`)
1594
+ .all(nodeId, ...kinds, ...preferred, cap));
1595
+ }
1596
+ if (rows.length < cap) {
1597
+ const omitPreferred = preferred.length ? ` AND ${opposite} NOT IN (${preferred.map(() => '?').join(',')})` : '';
1598
+ rows.push(...this.db.prepare(`${base}${omitPreferred} LIMIT ?`)
1599
+ .all(nodeId, ...kinds, ...preferred, cap - rows.length));
1600
+ }
1601
+ return rows.map(rowToEdge);
1602
+ }
1574
1603
  /**
1575
1604
  * Find all edges where both source and target are in the given node set.
1576
1605
  * Useful for recovering inter-node connectivity after BFS.