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
@@ -2,13 +2,9 @@
2
2
  /**
3
3
  * Session-level explore repeat / partial guidance (generic).
4
4
  *
5
- * Stops agents from treating `homegraph_explore` as an iterative keyword
6
- * searcher: overlapping queries after a successful explore get a short refuse
7
- * instead of another multi-kB payload. Partial/busy replies carry concrete
8
- * retry anchors extracted from the query — never an empty 242-char shell.
9
- *
10
- * Failure fuse (post A/B): hard-cap explores per session, require tight
11
- * single-Type follow-ups after 2 calls, and bind Partial → named Next anchor.
5
+ * Repeated evidence is deduplicated; lexical overlap alone cannot prove that a
6
+ * follow-up's evidence obligation is already covered. Incomplete retrieval gets
7
+ * one bounded recovery, including when the first response was short or SDK-only.
12
8
  *
13
9
  * Shape-driven only — no product nouns.
14
10
  */
@@ -36,6 +32,7 @@ exports.formatSecondPartialStopFooter = formatSecondPartialStopFooter;
36
32
  exports.extractRetryIntentHints = extractRetryIntentHints;
37
33
  exports.formatPartialExploreGuidance = formatPartialExploreGuidance;
38
34
  const query_utils_1 = require("../search/query-utils");
35
+ const explore_session_state_1 = require("./explore-session-state");
39
36
  /** Tokens that do not distinguish one explore bag from another. */
40
37
  const STOP = new Set([
41
38
  'the', 'a', 'an', 'and', 'or', 'of', 'to', 'in', 'on', 'for', 'with', 'from',
@@ -153,21 +150,17 @@ function extractNextAnchorFromText(text) {
153
150
  return id?.slice(0, 120);
154
151
  }
155
152
  function inferExplorePartialMeta(text) {
156
- // Soft-close / coarse-locate ANSWER must win over a leftover Partial header
157
- // (same response used to emit both — session fuse must treat it as closed).
158
- const closedAnswer = /\*\*ANSWER NOW\*\*|Mechanism explore complete — \*\*ANSWER NOW\*\*|Explore complete — ANSWER NOW|Coarse locate — ANSWER|Coarse locate complete/i
159
- .test(text);
160
- const partial = /\*\*Partial locator\*\*|Partial locator|⚠️ \*\*Partial result\*\*|\*\*Partial result\*\*/i.test(text)
161
- && !closedAnswer;
153
+ // Compatibility for renderers without structured receipts. A positive
154
+ // completion slogan must never erase a separately reported coverage gap.
155
+ const partial = /\*\*Partial locator\*\*|Partial locator|⚠️ \*\*Partial result\*\*|\*\*Partial result\*\*/i.test(text);
162
156
  return {
163
157
  partial,
164
158
  nextAnchor: partial ? extractNextAnchorFromText(text) : undefined,
165
159
  };
166
160
  }
167
- const OVERLAP_THRESHOLD = 0.45;
168
161
  /**
169
- * Absolute explore fuse per session/project (counted responses ≥400 chars).
170
- * After this many, refuse — answer from prior Anchors or ONE narrow Grep.
162
+ * Absolute retrieval budget per session/project. Empty receipts count as
163
+ * attempts too, so failed recovery cannot create an unbounded retry loop.
171
164
  */
172
165
  const MAX_EXPLORES = 2;
173
166
  /**
@@ -177,21 +170,7 @@ const MAX_EXPLORES = 2;
177
170
  */
178
171
  const MAX_DEPTH_AFTER_PARTIAL = 1;
179
172
  function isCountedCall(call) {
180
- return (call.responseBytes || 0) >= 400;
181
- }
182
- /** Shared mechanism domain stems (theme/install/xml/…) between two queries. */
183
- function domainStemOverlap(a, b) {
184
- const sa = new Set((0, query_utils_1.mechanismDomainPathTokens)(a));
185
- const sb = new Set((0, query_utils_1.mechanismDomainPathTokens)(b));
186
- let shared = 0;
187
- for (const t of sa) {
188
- if (sb.has(t))
189
- shared++;
190
- }
191
- return shared;
192
- }
193
- function hadClosedExplore(calls) {
194
- return calls.some((c) => isCountedCall(c) && c.partial !== true);
173
+ return call.evidenceStatus !== undefined || (call.responseBytes || 0) >= 400;
195
174
  }
196
175
  /**
197
176
  * Whether this explore should short-refuse instead of re-running.
@@ -199,59 +178,31 @@ function hadClosedExplore(calls) {
199
178
  function decideExploreRepeat(prior, query) {
200
179
  if (!prior || prior.calls.length === 0)
201
180
  return { refuse: false, reason: 'ok' };
202
- const qTokens = exploreQueryTokens(query);
203
181
  const counted = prior.calls.filter(isCountedCall);
204
- const novel = novelAnchorsVsPriors(query, prior.calls);
205
182
  const last = counted[counted.length - 1];
206
- // Hard fuse — never explore×N after two counted calls (inventory Manager hops included).
207
- if (counted.length >= MAX_EXPLORES) {
183
+ // Keep the lifetime budget even if bounded state has evicted early receipts.
184
+ if (Math.max(prior.callCount, counted.length) >= MAX_EXPLORES) {
208
185
  return {
209
186
  refuse: true,
210
187
  matched: last,
211
188
  reason: 'hard-cap',
212
189
  };
213
190
  }
214
- // Partial named a Next anchor — follow-up MUST include that name (no novel-Type bypass).
215
- if (last?.partial && last.nextAnchor) {
216
- const na = last.nextAnchor.toLowerCase();
217
- if (!query.toLowerCase().includes(na)) {
218
- return {
219
- refuse: true,
220
- matched: last,
221
- reason: 'next-anchor',
222
- };
223
- }
224
- }
225
- // After a closed ANSWER explore, refuse NL paraphrase bags that share domain
226
- // stems (theme/install/parse…) — stops D33-style explore×N token storms.
227
- if (hadClosedExplore(counted) && !isTightExploreFollowUp(query)) {
228
- for (const call of counted) {
229
- if (call.partial === true)
230
- continue;
231
- const overlap = queryTokenOverlapScore(qTokens, exploreQueryTokens(call.query));
232
- const domainShared = domainStemOverlap(query, call.query);
233
- if (domainShared >= 2 || overlap >= 0.28) {
234
- return { refuse: true, matched: call, reason: 'overlap' };
235
- }
236
- }
237
- }
238
- // Overlap with any prior counted explore — unless a tight novel Type/file bag
239
- // (and, after Partial, only when Next anchor is already in the query above).
240
- if (novel.length > 0 && isTightExploreFollowUp(query)) {
191
+ // Missing or SDK-only evidence is not a successfully answered query. Permit
192
+ // its single recovery even if the query overlaps or uses another next anchor.
193
+ if (last && (0, explore_session_state_1.inferExploreEvidenceStatus)(last) !== 'complete') {
241
194
  return { refuse: false, reason: 'ok' };
242
195
  }
243
- let best;
244
- let bestScore = 0;
196
+ const normalized = (s) => s.trim().toLowerCase().replace(/\s+/g, ' ');
245
197
  for (const call of counted) {
246
- const score = queryTokenOverlapScore(qTokens, exploreQueryTokens(call.query));
247
- if (score > bestScore) {
248
- bestScore = score;
249
- best = call;
198
+ if ((0, explore_session_state_1.inferExploreEvidenceStatus)(call) !== 'complete')
199
+ continue;
200
+ // Even the same token bag can reverse a relation ("A calls B" versus
201
+ // "B calls A"). Only an identical normalized request proves repetition.
202
+ if (normalized(query) === normalized(call.query)) {
203
+ return { refuse: true, matched: call, reason: 'overlap' };
250
204
  }
251
205
  }
252
- if (best && bestScore >= OVERLAP_THRESHOLD) {
253
- return { refuse: true, matched: best, reason: 'overlap' };
254
- }
255
206
  return { refuse: false, reason: 'ok' };
256
207
  }
257
208
  /** Short success-shaped refuse when a repeat explore would waste tokens. */
@@ -262,12 +213,12 @@ function formatExploreRepeatRefuse(decision, query) {
262
213
  ? `\nAlready covered files include: ${files.map((f) => `\`${f}\``).join(', ')}.`
263
214
  : '';
264
215
  const next = decision.matched?.nextAnchor
265
- ? `\nPrior **Next anchor** was \`${decision.matched.nextAnchor}\` — use that name, or ONE narrow Grep.`
216
+ ? `\nSuggested **Next anchor:** \`${decision.matched.nextAnchor}\`.`
266
217
  : '';
267
218
  let why;
268
219
  switch (decision.reason) {
269
220
  case 'hard-cap':
270
- why = `This session already ran **${MAX_EXPLORES}** \`homegraph_explore\` calls on this project. Stop exploring.`;
221
+ why = `This session reached its **${MAX_EXPLORES}** \`homegraph_explore\` retrieval attempts on this project, including incomplete attempts.`;
271
222
  break;
272
223
  case 'next-anchor':
273
224
  why = `Prior explore was Partial and named a **Next anchor** — do not re-explore a paraphrase of "${priorQ}${priorQ.length >= 100 ? '…' : ''}".`;
@@ -276,14 +227,14 @@ function formatExploreRepeatRefuse(decision, query) {
276
227
  why = `Explore call budget exhausted for this project in the session.`;
277
228
  break;
278
229
  default:
279
- why = `This query overlaps a prior explore (bag ≈ "${priorQ}${priorQ.length >= 100 ? '…' : ''}").`;
230
+ why = `This query repeats the same evidence request as "${priorQ}${priorQ.length >= 100 ? '…' : ''}".`;
280
231
  }
281
232
  return [
282
- '**Skip repeat explore — stop HomeGraph drill-down.**',
233
+ '**Explore retrieval limit — reuse evidence already returned.**',
283
234
  why + fileLine + next,
284
235
  `Current query: "${query.trim().slice(0, 160)}${query.trim().length > 160 ? '…' : ''}"`,
285
- 'Answer from Anchors / digests already in this conversation, or run **ONE narrow Grep** for residual unindexed wiring.',
286
- 'Do **not** glob/read the whole repo, and do **not** fan out `homegraph_explore` / `homegraph_node` / callers on the same bag.',
236
+ 'This limit does not mean the task or its evidence is complete. Inspect missing source with a targeted Read or narrow Grep, then continue the requested edits and validation.',
237
+ 'Do not repeat the same explore or reread unchanged source already shown; keep any remaining inspection scoped to uncovered evidence.',
287
238
  ].join('\n');
288
239
  }
289
240
  /** Latest counted explore call (≥400 response bytes), if any. */
@@ -301,21 +252,14 @@ function latestCountedExplore(prior) {
301
252
  * Whether `homegraph_node` / callers / callees should short-refuse after a
302
253
  * Partial explore (same failure class as explore×N — depth fan-out).
303
254
  *
304
- * After Partial: callers/callees are refused immediately (wrong tool + often a
305
- * multi-def token bomb). `homegraph_node` gets one shot, then refuse.
255
+ * Any one focused depth tool may recover missing evidence. The shared budget
256
+ * prevents fan-out without declaring callers/callees intrinsically invalid.
306
257
  */
307
- function decideDepthToolFuse(prior, depthCallCount, toolName) {
258
+ function decideDepthToolFuse(prior, depthCallCount, _toolName) {
308
259
  const last = latestCountedExplore(prior);
309
- if (!last?.partial)
260
+ if (!last || (0, explore_session_state_1.inferExploreEvidenceStatus)(last) === 'complete')
310
261
  return { refuse: false, reason: 'ok' };
311
262
  const nextAnchor = last.nextAnchor;
312
- if (toolName === 'homegraph_callers' || toolName === 'homegraph_callees') {
313
- return {
314
- refuse: true,
315
- reason: 'partial-no-callers',
316
- nextAnchor,
317
- };
318
- }
319
263
  if (depthCallCount >= MAX_DEPTH_AFTER_PARTIAL) {
320
264
  return {
321
265
  refuse: true,
@@ -328,20 +272,18 @@ function decideDepthToolFuse(prior, depthCallCount, toolName) {
328
272
  /** Success-shaped refuse when Partial already spent its one depth drill. */
329
273
  function formatDepthToolRefuse(decision, toolName, symbolHint) {
330
274
  const next = decision.nextAnchor
331
- ? `\nPrior **Next anchor** was \`${decision.nextAnchor}\` — ONE \`homegraph_node\` / tighter explore with that name, or ONE narrow Grep.`
275
+ ? `\nSuggested **Next anchor:** \`${decision.nextAnchor}\`.`
332
276
  : '';
333
277
  const sym = symbolHint?.trim()
334
278
  ? `\nRequested: \`${symbolHint.trim().slice(0, 80)}\``
335
279
  : '';
336
- const why = decision.reason === 'partial-no-callers'
337
- ? `Prior \`homegraph_explore\` was a Partial locator — do **not** call \`${toolName}\` next (multi-def dumps + fan-out).`
338
- : `Prior \`homegraph_explore\` was a Partial locator; this session already used its **${MAX_DEPTH_AFTER_PARTIAL}** `
339
- + `allowed \`homegraph_node\` call on this project.`;
280
+ const why = `Prior retrieval was incomplete; this session already used its **${MAX_DEPTH_AFTER_PARTIAL}** `
281
+ + `focused depth recovery call on this project (requested \`${toolName}\`).`;
340
282
  return [
341
- '**Skip HomeGraph depth drill — stop after Partial.**',
283
+ '**Depth recovery budget reached — evidence may still be incomplete.**',
342
284
  why + next + sym,
343
- 'Answer from Anchors / digests already in this conversation, or run **ONE narrow Grep** for residual unindexed wiring.',
344
- 'Do **not** fan out more `homegraph_node` / callers / callees, and do **not** glob/read the whole repo.',
285
+ 'Use a targeted Read or narrow Grep for the missing evidence, then continue the requested edits and validation.',
286
+ 'Reuse source already shown and avoid repeating the same depth query.',
345
287
  ].join('\n');
346
288
  }
347
289
  /**
@@ -446,33 +388,31 @@ function formatNextAnchorCaption(c) {
446
388
  return `\`${c.name}\` (${c.kind}) — \`${c.filePath.replace(/\\/g, '/')}:${line}\``;
447
389
  }
448
390
  /**
449
- * Soft-close opening banner (must match footer — never pair with Partial locator).
391
+ * Coarse retrieval banner: source reuse is separate from task completion.
450
392
  */
451
393
  function formatMechanismSoftCloseHeader() {
452
- return ('> **Coarse locate — ANSWER from anchors + digests below.** '
453
- + 'Treat inventory + Source as already Read. '
454
- + 'ONE narrow Grep only for residual unindexed wiring — do not re-explore or fan out depth tools.');
394
+ return ('> **Coarse source evidence below.** '
395
+ + 'Reuse the source shown for these symbols. '
396
+ + 'Check relevance and uncovered wiring before continuing the requested edits or explanation.');
455
397
  }
456
398
  /**
457
- * Soft-close footer: enough inventory + digest to answer without another explore.
458
- * Must NOT contain "Partial locator" so the session fuse treats the call as closed.
399
+ * Coarse retrieval footer; never claims that an inventory completes the task.
459
400
  */
460
401
  function formatMechanismSoftCloseFooter(next) {
461
402
  const hint = next
462
403
  ? ` Primary Type: \`${next.name}\`.`
463
404
  : '';
464
- return ('> **Coarse locate — ANSWER from anchors + digests above.**'
405
+ return ('> **Coarse source evidence returned.**'
465
406
  + hint
466
- + ' ONE narrow Grep only for residual unindexed wiring named above. '
467
- + 'Do **not** re-explore, fan out `homegraph_node` / callers, or glob/read the repo.');
407
+ + ' Retrieval is not task completion. Reuse the displayed source; inspect uncovered code '
408
+ + 'with one focused follow-up or targeted Read/Grep, then continue authorized edits and checks.');
468
409
  }
469
410
  /** Honest Partial footer with a single Next anchor + ONE Grep. */
470
411
  function formatMechanismPartialFooter(nextCaption) {
471
412
  return ('> **Partial locator** — not a full mechanism closure. '
472
413
  + `**Next anchor:** ${nextCaption}. `
473
- + 'ONE tighter `homegraph_explore` **only** with that exact name, '
474
- + 'or **ONE narrow Grep** for residual unindexed wiring — '
475
- + 'do **not** fan out `homegraph_node` / Read / glob, and do **not** ANSWER NOW from inventory alone.');
414
+ + 'One focused recovery may use this anchor or a different uncovered part of the task. '
415
+ + 'Use targeted Read/Grep if the evidence remains missing; an inventory alone does not establish behavior.');
476
416
  }
477
417
  /**
478
418
  * Appended when a second counted Partial is emitted in the same session —
@@ -485,10 +425,10 @@ function formatSecondPartialStopFooter(nextAnchor) {
485
425
  return [
486
426
  '',
487
427
  '---',
488
- '> **Second Partial — stop HomeGraph.** Do **not** call `homegraph_explore` again.'
428
+ '> **Second Partial — explore retrieval budget reached.** Do not repeat `homegraph_explore`.'
489
429
  + next
490
- + ' Answer from Anchors / digests already returned, or **ONE narrow Grep** for residual unindexed wiring. '
491
- + 'Do not glob/read the whole repo.',
430
+ + ' Evidence remains incomplete. Inspect only missing source with targeted Read or narrow Grep, '
431
+ + 'then continue the requested edits and validation. Reuse unchanged source already returned.',
492
432
  ].join('\n');
493
433
  }
494
434
  /**
@@ -531,10 +471,10 @@ function formatPartialExploreGuidance(opts) {
531
471
  : 'If you retry, ONE tight \`homegraph_explore\` with a single Type / file / `@kit` name — not a broad paraphrase.';
532
472
  return [
533
473
  `⚠️ **Partial result** — ${why}. This is NOT an error.`,
534
- 'Prefer **ONE narrow Grep** for residual unindexed wiring using names already in the question — do **not** glob/read the repo.',
474
+ 'A targeted Read or **ONE narrow Grep** may recover missing evidence using names already in the question.',
535
475
  anchorLine,
536
- 'At most **one** `homegraph_node` (or callers/callees) after Partial — further depth calls are refused. Do not open a Grep/Read storm.',
537
- 'If a second explore still Partials, **stop HomeGraph** and answer from anchors + ONE narrow Grep.',
476
+ 'At most **one** focused `homegraph_node` or callers/callees recovery after Partial; reuse source already returned.',
477
+ 'If a second explore is still Partial, its retrieval budget is exhausted. Inspect missing source directly and continue the requested work; do not infer task completion.',
538
478
  ].join('\n');
539
479
  }
540
480
  //# sourceMappingURL=explore-repeat-guard.js.map
@@ -74,6 +74,8 @@ export interface ExploreFileEmission {
74
74
  /** Set when ranges were dropped to stay under the per-file bound. */
75
75
  rangesTruncated?: boolean;
76
76
  }
77
+ /** Retrieval coverage only; even complete evidence does not complete a coding task. */
78
+ export type ExploreEvidenceStatus = 'complete' | 'partial' | 'empty' | 'sdk-only';
77
79
  /** What one explore call emitted, as reported by the handler. */
78
80
  export interface ExploreEmission {
79
81
  /** Resolved project root — the key state is filed under. */
@@ -85,14 +87,30 @@ export interface ExploreEmission {
85
87
  sourceBytes: number;
86
88
  /** Total chars of the response the agent received. */
87
89
  responseBytes: number;
90
+ /** Internal receipt: declarations actually shown, not all retrieval candidates.
91
+ * A located node is source-grounded, not proof of relevance to the user's task.
92
+ */
93
+ locatedNodes?: Array<{
94
+ id: string;
95
+ name: string;
96
+ qualifiedName?: string;
97
+ filePath: string;
98
+ startLine: number;
99
+ }>;
100
+ /** Derived by the executor from emitted evidence, never from a completion banner. */
101
+ evidenceStatus?: ExploreEvidenceStatus;
102
+ /** Bounded descriptions of retrieval obligations with emitted supporting evidence. */
103
+ coveredObligations?: string[];
104
+ /** Requested retrieval obligations that the emitted evidence did not cover. */
105
+ uncoveredObligations?: string[];
88
106
  /**
89
- * True when the response was an honest Partial / coarse locator (not a
90
- * closed ANSWER NOW). Used by the repeat guard to fuse failures.
107
+ * True when some requested evidence is missing. Legacy renderers may supply
108
+ * this without evidenceStatus; a textual completion banner cannot clear it.
91
109
  */
92
110
  partial?: boolean;
93
111
  /**
94
- * Concrete next Type / file the Partial named — follow-up explore must
95
- * include this string (case-insensitive) or be refused as paraphrase churn.
112
+ * Suggested next Type / file. Advisory: a missing evidence obligation may
113
+ * require a different source, especially after an irrelevant first hit.
96
114
  */
97
115
  nextAnchor?: string;
98
116
  }
@@ -140,7 +158,11 @@ export declare const EXPLORE_SESSION_LIMITS: {
140
158
  readonly MAX_RANGES_PER_FILE: 24;
141
159
  /** Most-recent calls per project included in {@link ExploreSessionView}. */
142
160
  readonly MAX_VIEW_CALLS: 4;
161
+ readonly MAX_LOCATED_NODES: 64;
162
+ readonly MAX_OBLIGATIONS: 12;
143
163
  };
164
+ /** Conservative fallback for older renderers that have not supplied a receipt. */
165
+ export declare function inferExploreEvidenceStatus(emission: ExploreEmission): ExploreEvidenceStatus;
144
166
  /**
145
167
  * Key a project root is filed under. Resolved so `/repo` and `/repo/` agree;
146
168
  * case-folded on the two platforms whose filesystems are case-insensitive, so a
@@ -73,6 +73,7 @@ var __importStar = (this && this.__importStar) || (function () {
73
73
  })();
74
74
  Object.defineProperty(exports, "__esModule", { value: true });
75
75
  exports.ExploreSessionState = exports.EXPLORE_SESSION_LIMITS = exports.EXPLORE_SESSION_VIEW_ARG = exports.EXPLORE_EMISSION_KEY = void 0;
76
+ exports.inferExploreEvidenceStatus = inferExploreEvidenceStatus;
76
77
  exports.exploreProjectKey = exploreProjectKey;
77
78
  exports.coalesceRanges = coalesceRanges;
78
79
  exports.rangesCover = rangesCover;
@@ -113,7 +114,31 @@ exports.EXPLORE_SESSION_LIMITS = {
113
114
  MAX_RANGES_PER_FILE: 24,
114
115
  /** Most-recent calls per project included in {@link ExploreSessionView}. */
115
116
  MAX_VIEW_CALLS: 4,
117
+ MAX_LOCATED_NODES: 64,
118
+ MAX_OBLIGATIONS: 12,
116
119
  };
120
+ /** Conservative fallback for older renderers that have not supplied a receipt. */
121
+ function inferExploreEvidenceStatus(emission) {
122
+ if (emission.evidenceStatus === 'empty' || emission.evidenceStatus === 'sdk-only') {
123
+ return emission.evidenceStatus;
124
+ }
125
+ if (emission.partial || emission.uncoveredObligations?.length || emission.evidenceStatus === 'partial') {
126
+ return 'partial';
127
+ }
128
+ if (emission.evidenceStatus === 'complete')
129
+ return 'complete';
130
+ const paths = [
131
+ ...(Array.isArray(emission.files) ? emission.files : [])
132
+ .filter((f) => f && f.bytes > 0 && f.ranges?.length > 0).map((f) => f.path),
133
+ ...(Array.isArray(emission.locatedNodes) ? emission.locatedNodes : [])
134
+ .filter((n) => n && typeof n.filePath === 'string').map((n) => n.filePath),
135
+ ];
136
+ if (paths.length === 0)
137
+ return 'empty';
138
+ if (paths.every((p) => /^(?:ohos-sdk|sdk):/i.test(p)))
139
+ return 'sdk-only';
140
+ return 'complete';
141
+ }
117
142
  /**
118
143
  * Key a project root is filed under. Resolved so `/repo` and `/repo/` agree;
119
144
  * case-folded on the two platforms whose filesystems are case-insensitive, so a
@@ -195,7 +220,13 @@ class ExploreSessionState {
195
220
  files: this.boundFiles(emission.files),
196
221
  sourceBytes: Math.max(0, emission.sourceBytes || 0),
197
222
  responseBytes: Math.max(0, emission.responseBytes || 0),
198
- partial: emission.partial === true,
223
+ evidenceStatus: inferExploreEvidenceStatus(emission),
224
+ coveredObligations: boundObligations(emission.coveredObligations),
225
+ uncoveredObligations: boundObligations(emission.uncoveredObligations),
226
+ locatedNodes: (Array.isArray(emission.locatedNodes) ? emission.locatedNodes : []).filter((n) => n && typeof n.id === 'string'
227
+ && typeof n.name === 'string' && typeof n.filePath === 'string' && Number.isFinite(n.startLine))
228
+ .slice(0, exports.EXPLORE_SESSION_LIMITS.MAX_LOCATED_NODES).map((n) => ({ ...n })),
229
+ partial: inferExploreEvidenceStatus(emission) !== 'complete',
199
230
  nextAnchor: typeof emission.nextAnchor === 'string' && emission.nextAnchor.trim()
200
231
  ? emission.nextAnchor.trim().slice(0, 120)
201
232
  : undefined,
@@ -204,7 +235,7 @@ class ExploreSessionState {
204
235
  if (state.calls.length > exports.EXPLORE_SESSION_LIMITS.MAX_CALLS_RETAINED) {
205
236
  state.calls.splice(0, state.calls.length - exports.EXPLORE_SESSION_LIMITS.MAX_CALLS_RETAINED);
206
237
  }
207
- // Fresh explore → reset depth fuse window (Partial gets one drill; closed clears).
238
+ // Fresh retrieval resets the bounded recovery window; task completion is unrelated.
208
239
  if (record.partial)
209
240
  this.depthAfterPartial.set(key, 0);
210
241
  else
@@ -253,7 +284,7 @@ class ExploreSessionState {
253
284
  responseBytes: state.responseBytes,
254
285
  calls: state.calls
255
286
  .slice(-exports.EXPLORE_SESSION_LIMITS.MAX_VIEW_CALLS)
256
- .map((c) => ({ ...c, files: c.files.map((f) => ({ ...f, ranges: [...f.ranges] })) })),
287
+ .map(cloneCall),
257
288
  })),
258
289
  };
259
290
  }
@@ -318,7 +349,22 @@ function cloneProject(state) {
318
349
  projectRoot: state.projectRoot,
319
350
  callCount: state.callCount,
320
351
  responseBytes: state.responseBytes,
321
- calls: state.calls.map((c) => ({ ...c, files: c.files.map((f) => ({ ...f, ranges: [...f.ranges] })) })),
352
+ calls: state.calls.map(cloneCall),
353
+ };
354
+ }
355
+ function boundObligations(values) {
356
+ if (!Array.isArray(values))
357
+ return undefined;
358
+ return [...new Set(values.filter((s) => typeof s === 'string' && s.trim())
359
+ .map((s) => s.trim().slice(0, 240)))].slice(0, exports.EXPLORE_SESSION_LIMITS.MAX_OBLIGATIONS);
360
+ }
361
+ function cloneCall(c) {
362
+ return {
363
+ ...c,
364
+ files: c.files.map((f) => ({ ...f, ranges: f.ranges.map((r) => ({ ...r })) })),
365
+ locatedNodes: c.locatedNodes?.map((n) => ({ ...n })),
366
+ coveredObligations: c.coveredObligations ? [...c.coveredObligations] : undefined,
367
+ uncoveredObligations: c.uncoveredObligations ? [...c.uncoveredObligations] : undefined,
322
368
  };
323
369
  }
324
370
  /**
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Product-facing index availability for MCP tool results (Spec 0032).
3
+ *
4
+ * Internal `build_phase` stays as-is; this layer maps it (+ write-lock / busy)
5
+ * to the four states hosts and agents should see in tool text.
6
+ */
7
+ import type HomeGraph from '../index';
8
+ /** Agent-visible index readiness (tool return copy — not tools/list gating). */
9
+ export type ProductIndexState = 'empty' | 'fast' | 'full' | 'syncing';
10
+ export declare function productIndexGuidance(state: Exclude<ProductIndexState, 'full'>): string;
11
+ /**
12
+ * Resolve the product state from a live HomeGraph handle.
13
+ *
14
+ * - empty: fast map not ready (`none` / `building_fast`)
15
+ * - fast: map ready, full index not done (`fast` / `indexing`)
16
+ * - full: symbol index ready
17
+ * - syncing: full (or empty-while-contended-init) and a writer holds the lock /
18
+ * this process is indexing — reads may fail or see a moving target
19
+ */
20
+ export declare function resolveProductIndexState(cg: HomeGraph): ProductIndexState;
21
+ /** True when an error message indicates SQLite writer contention. */
22
+ export declare function isSqliteBusyMessage(message: string): boolean;
23
+ //# sourceMappingURL=index-availability.d.ts.map
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * Product-facing index availability for MCP tool results (Spec 0032).
4
+ *
5
+ * Internal `build_phase` stays as-is; this layer maps it (+ write-lock / busy)
6
+ * to the four states hosts and agents should see in tool text.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.productIndexGuidance = productIndexGuidance;
10
+ exports.resolveProductIndexState = resolveProductIndexState;
11
+ exports.isSqliteBusyMessage = isSqliteBusyMessage;
12
+ const EMPTY_LINES = [
13
+ 'HomeGraph status=empty — project map is not ready yet.',
14
+ 'Retry in a few seconds (or call `homegraph_project` once the fast build completes).',
15
+ ];
16
+ const FAST_LINES = [
17
+ 'HomeGraph status=fast — module/file map is ready; full symbol index is still building.',
18
+ 'Use `homegraph_project` for the module/file map now, then retry this tool once indexing finishes.',
19
+ ];
20
+ const SYNCING_LINES = [
21
+ 'HomeGraph status=syncing — the index is being written (lock held or local index/sync in progress).',
22
+ 'Retry this tool shortly; do not busy-loop.',
23
+ ];
24
+ function productIndexGuidance(state) {
25
+ switch (state) {
26
+ case 'empty':
27
+ return EMPTY_LINES.join('\n');
28
+ case 'fast':
29
+ return FAST_LINES.join('\n');
30
+ case 'syncing':
31
+ return SYNCING_LINES.join('\n');
32
+ }
33
+ }
34
+ /**
35
+ * Resolve the product state from a live HomeGraph handle.
36
+ *
37
+ * - empty: fast map not ready (`none` / `building_fast`)
38
+ * - fast: map ready, full index not done (`fast` / `indexing`)
39
+ * - full: symbol index ready
40
+ * - syncing: full (or empty-while-contended-init) and a writer holds the lock /
41
+ * this process is indexing — reads may fail or see a moving target
42
+ */
43
+ function resolveProductIndexState(cg) {
44
+ let phase;
45
+ try {
46
+ phase = cg.getBuildPhase();
47
+ }
48
+ catch {
49
+ return 'syncing';
50
+ }
51
+ if (phase === 'building_fast' || phase === 'none') {
52
+ try {
53
+ if (cg.isWriteLockedByOther())
54
+ return 'syncing';
55
+ }
56
+ catch {
57
+ return 'syncing';
58
+ }
59
+ return 'empty';
60
+ }
61
+ if (phase === 'fast' || phase === 'indexing') {
62
+ return 'fast';
63
+ }
64
+ // full
65
+ try {
66
+ if (cg.isWriteLockedByOther() || cg.isIndexing())
67
+ return 'syncing';
68
+ }
69
+ catch {
70
+ return 'syncing';
71
+ }
72
+ return 'full';
73
+ }
74
+ /** True when an error message indicates SQLite writer contention. */
75
+ function isSqliteBusyMessage(message) {
76
+ return /SQLITE_BUSY|database is locked/i.test(message);
77
+ }
78
+ //# sourceMappingURL=index-availability.js.map
package/dist/mcp/index.js CHANGED
@@ -142,8 +142,9 @@ function daemonInternalSet() {
142
142
  * fail to share the daemon.
143
143
  */
144
144
  function resolveDaemonRoot(explicitPath) {
145
- const candidate = explicitPath ?? process.cwd();
146
- const root = (0, directory_1.findNearestHomeGraphRoot)(candidate);
145
+ // An explicit host path is also the walk-up floor (spec 0028): a stray
146
+ // ancestor .homegraph must not redirect the daemon to the wrong tree.
147
+ const root = (0, directory_1.findNearestHomeGraphRoot)(explicitPath ?? process.cwd(), explicitPath ?? undefined);
147
148
  if (!root)
148
149
  return null;
149
150
  try {
@@ -349,7 +350,7 @@ class MCPServer {
349
350
  // is a second V8 isolate + a second open of the project DB, and on large
350
351
  // indexes (hundreds of MB) that alone pushed process-tree RSS to ~5GB.
351
352
  // Soft deadlines + compact-before-pool still run on the warm main connection.
352
- this.engine = new engine_1.MCPEngine({ queryPool: false });
353
+ this.engine = new engine_1.MCPEngine({ queryPool: false, rootFloor: this.projectPath ?? undefined });
353
354
  const transport = new transport_1.StdioTransport();
354
355
  this.session = new session_1.MCPSession(transport, this.engine, {
355
356
  explicitProjectPath: this.projectPath,
@@ -471,7 +472,7 @@ class MCPServer {
471
472
  getDaemonSocket,
472
473
  // Daemon-unavailable fallback is one client — same as direct mode: no
473
474
  // pool. Duplicating the DB open here blew RSS on large indexes.
474
- makeEngine: () => new engine_1.MCPEngine({ queryPool: false }),
475
+ makeEngine: () => new engine_1.MCPEngine({ queryPool: false, rootFloor: root ?? undefined }),
475
476
  root,
476
477
  });
477
478
  }
@@ -15,7 +15,7 @@
15
15
  import type { QueryBuilder } from '../db/queries';
16
16
  import type { ToolResult } from './tools';
17
17
  /** Bump when cache-key normalization or cached payload shape changes. */
18
- export declare const QUERY_CACHE_FORMAT_VERSION = 1;
18
+ export declare const QUERY_CACHE_FORMAT_VERSION = 5;
19
19
  export declare function isMcpQueryCacheEnabled(): boolean;
20
20
  export declare function isCacheableMcpTool(toolName: string): boolean;
21
21
  /**