homegraph 1.5.7 → 1.5.10

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 (555) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +2 -2
  3. package/dist/bin/homegraph.js +16 -14
  4. package/dist/db/index.d.ts +1 -1
  5. package/dist/db/index.js +11 -25
  6. package/dist/db/queries.d.ts +5 -1
  7. package/dist/db/queries.js +31 -2
  8. package/dist/db/sqlite-adapter.d.ts +6 -12
  9. package/dist/db/sqlite-adapter.js +13 -41
  10. package/dist/directory.d.ts +1 -1
  11. package/dist/directory.js +25 -1
  12. package/dist/extraction/grammars.d.ts +2 -0
  13. package/dist/extraction/grammars.js +7 -7
  14. package/dist/extraction/index.js +17 -12
  15. package/dist/extraction/languages/arkts.d.ts +40 -7
  16. package/dist/extraction/languages/arkts.js +290 -84
  17. package/dist/extraction/tree-sitter.js +12 -3
  18. package/dist/graph/evidence-paths.d.ts +63 -0
  19. package/dist/graph/evidence-paths.js +245 -0
  20. package/dist/index.d.ts +6 -1
  21. package/dist/index.js +78 -29
  22. package/dist/mcp/arkts-evidence-packs.d.ts +67 -0
  23. package/dist/mcp/arkts-evidence-packs.js +352 -0
  24. package/dist/mcp/daemon.js +1 -1
  25. package/dist/mcp/engine.d.ts +20 -7
  26. package/dist/mcp/engine.js +113 -106
  27. package/dist/mcp/index-availability.d.ts +31 -0
  28. package/dist/mcp/index-availability.js +105 -0
  29. package/dist/mcp/index.js +5 -4
  30. package/dist/mcp/query-cache.d.ts +1 -1
  31. package/dist/mcp/query-cache.js +6 -2
  32. package/dist/mcp/query-worker.d.ts +1 -1
  33. package/dist/mcp/query-worker.js +1 -1
  34. package/dist/mcp/server-instructions.d.ts +2 -11
  35. package/dist/mcp/server-instructions.js +42 -75
  36. package/dist/mcp/session.js +12 -4
  37. package/dist/mcp/source-slice-identity.d.ts +3 -0
  38. package/dist/mcp/source-slice-identity.js +11 -0
  39. package/dist/mcp/tools.d.ts +29 -6
  40. package/dist/mcp/tools.js +240 -122
  41. package/dist/project-map/index.js +2 -42
  42. package/dist/spec/llm/client.js +3 -15
  43. package/dist/spec/llm/openai-sdk.d.ts +14 -0
  44. package/dist/spec/llm/openai-sdk.js +37 -0
  45. package/dist/spec/llm/retry.js +8 -9
  46. package/dist/utils.d.ts +5 -0
  47. package/dist/utils.js +24 -0
  48. package/package.json +4 -6
  49. package/dist/addons/dynamic-import.d.ts.map +0 -1
  50. package/dist/addons/dynamic-import.js.map +0 -1
  51. package/dist/addons/init-template.d.ts.map +0 -1
  52. package/dist/addons/init-template.js.map +0 -1
  53. package/dist/addons/loader.d.ts.map +0 -1
  54. package/dist/addons/loader.js.map +0 -1
  55. package/dist/addons/manager.d.ts.map +0 -1
  56. package/dist/addons/manager.js.map +0 -1
  57. package/dist/addons/paths.d.ts.map +0 -1
  58. package/dist/addons/paths.js.map +0 -1
  59. package/dist/addons/registry.d.ts.map +0 -1
  60. package/dist/addons/registry.js.map +0 -1
  61. package/dist/addons/semver.d.ts.map +0 -1
  62. package/dist/addons/semver.js.map +0 -1
  63. package/dist/addons/types.d.ts.map +0 -1
  64. package/dist/addons/types.js.map +0 -1
  65. package/dist/addons/validate.d.ts.map +0 -1
  66. package/dist/addons/validate.js.map +0 -1
  67. package/dist/arkui/index.d.ts.map +0 -1
  68. package/dist/arkui/index.js.map +0 -1
  69. package/dist/arkui/migrate-passage.d.ts.map +0 -1
  70. package/dist/arkui/migrate-passage.js.map +0 -1
  71. package/dist/arkui/migrate-semantics.d.ts.map +0 -1
  72. package/dist/arkui/migrate-semantics.js.map +0 -1
  73. package/dist/arkui/migrate-snapshot.d.ts.map +0 -1
  74. package/dist/arkui/migrate-snapshot.js.map +0 -1
  75. package/dist/bin/addon-commands.d.ts.map +0 -1
  76. package/dist/bin/addon-commands.js.map +0 -1
  77. package/dist/bin/command-supervision.d.ts.map +0 -1
  78. package/dist/bin/command-supervision.js.map +0 -1
  79. package/dist/bin/fatal-handler.d.ts.map +0 -1
  80. package/dist/bin/fatal-handler.js.map +0 -1
  81. package/dist/bin/homegraph.d.ts.map +0 -1
  82. package/dist/bin/homegraph.js.map +0 -1
  83. package/dist/bin/node-version-check.d.ts.map +0 -1
  84. package/dist/bin/node-version-check.js.map +0 -1
  85. package/dist/bin/uninstall.d.ts.map +0 -1
  86. package/dist/bin/uninstall.js.map +0 -1
  87. package/dist/context/formatter.d.ts.map +0 -1
  88. package/dist/context/formatter.js.map +0 -1
  89. package/dist/context/index.d.ts.map +0 -1
  90. package/dist/context/index.js.map +0 -1
  91. package/dist/context/markers.d.ts.map +0 -1
  92. package/dist/context/markers.js.map +0 -1
  93. package/dist/db/index.d.ts.map +0 -1
  94. package/dist/db/index.js.map +0 -1
  95. package/dist/db/migrations.d.ts.map +0 -1
  96. package/dist/db/migrations.js.map +0 -1
  97. package/dist/db/queries.d.ts.map +0 -1
  98. package/dist/db/queries.js.map +0 -1
  99. package/dist/db/sqlite-adapter.d.ts.map +0 -1
  100. package/dist/db/sqlite-adapter.js.map +0 -1
  101. package/dist/db/wal-valve.d.ts.map +0 -1
  102. package/dist/db/wal-valve.js.map +0 -1
  103. package/dist/directory.d.ts.map +0 -1
  104. package/dist/directory.js.map +0 -1
  105. package/dist/errors.d.ts.map +0 -1
  106. package/dist/errors.js.map +0 -1
  107. package/dist/extraction/arkts-batch-worker.d.ts.map +0 -1
  108. package/dist/extraction/arkts-batch-worker.js.map +0 -1
  109. package/dist/extraction/astro-extractor.d.ts.map +0 -1
  110. package/dist/extraction/astro-extractor.js.map +0 -1
  111. package/dist/extraction/cfml-extractor.d.ts.map +0 -1
  112. package/dist/extraction/cfml-extractor.js.map +0 -1
  113. package/dist/extraction/context.d.ts.map +0 -1
  114. package/dist/extraction/context.js.map +0 -1
  115. package/dist/extraction/default-ignore.d.ts.map +0 -1
  116. package/dist/extraction/default-ignore.js.map +0 -1
  117. package/dist/extraction/dfm-extractor.d.ts.map +0 -1
  118. package/dist/extraction/dfm-extractor.js.map +0 -1
  119. package/dist/extraction/extraction-version.d.ts.map +0 -1
  120. package/dist/extraction/extraction-version.js.map +0 -1
  121. package/dist/extraction/function-ref.d.ts.map +0 -1
  122. package/dist/extraction/function-ref.js.map +0 -1
  123. package/dist/extraction/generated-detection.d.ts.map +0 -1
  124. package/dist/extraction/generated-detection.js.map +0 -1
  125. package/dist/extraction/grammars.d.ts.map +0 -1
  126. package/dist/extraction/grammars.js.map +0 -1
  127. package/dist/extraction/index.d.ts.map +0 -1
  128. package/dist/extraction/index.js.map +0 -1
  129. package/dist/extraction/languages/arkts.d.ts.map +0 -1
  130. package/dist/extraction/languages/arkts.js.map +0 -1
  131. package/dist/extraction/languages/c-cpp.d.ts.map +0 -1
  132. package/dist/extraction/languages/c-cpp.js.map +0 -1
  133. package/dist/extraction/languages/cfquery.d.ts.map +0 -1
  134. package/dist/extraction/languages/cfquery.js.map +0 -1
  135. package/dist/extraction/languages/cfscript.d.ts.map +0 -1
  136. package/dist/extraction/languages/cfscript.js.map +0 -1
  137. package/dist/extraction/languages/cobol.d.ts.map +0 -1
  138. package/dist/extraction/languages/cobol.js.map +0 -1
  139. package/dist/extraction/languages/csharp.d.ts.map +0 -1
  140. package/dist/extraction/languages/csharp.js.map +0 -1
  141. package/dist/extraction/languages/dart.d.ts.map +0 -1
  142. package/dist/extraction/languages/dart.js.map +0 -1
  143. package/dist/extraction/languages/erlang.d.ts.map +0 -1
  144. package/dist/extraction/languages/erlang.js.map +0 -1
  145. package/dist/extraction/languages/go.d.ts.map +0 -1
  146. package/dist/extraction/languages/go.js.map +0 -1
  147. package/dist/extraction/languages/index.d.ts.map +0 -1
  148. package/dist/extraction/languages/index.js.map +0 -1
  149. package/dist/extraction/languages/java.d.ts.map +0 -1
  150. package/dist/extraction/languages/java.js.map +0 -1
  151. package/dist/extraction/languages/javascript.d.ts.map +0 -1
  152. package/dist/extraction/languages/javascript.js.map +0 -1
  153. package/dist/extraction/languages/kotlin.d.ts.map +0 -1
  154. package/dist/extraction/languages/kotlin.js.map +0 -1
  155. package/dist/extraction/languages/lua.d.ts.map +0 -1
  156. package/dist/extraction/languages/lua.js.map +0 -1
  157. package/dist/extraction/languages/luau.d.ts.map +0 -1
  158. package/dist/extraction/languages/luau.js.map +0 -1
  159. package/dist/extraction/languages/nix.d.ts.map +0 -1
  160. package/dist/extraction/languages/nix.js.map +0 -1
  161. package/dist/extraction/languages/objc.d.ts.map +0 -1
  162. package/dist/extraction/languages/objc.js.map +0 -1
  163. package/dist/extraction/languages/pascal.d.ts.map +0 -1
  164. package/dist/extraction/languages/pascal.js.map +0 -1
  165. package/dist/extraction/languages/php.d.ts.map +0 -1
  166. package/dist/extraction/languages/php.js.map +0 -1
  167. package/dist/extraction/languages/python.d.ts.map +0 -1
  168. package/dist/extraction/languages/python.js.map +0 -1
  169. package/dist/extraction/languages/r.d.ts.map +0 -1
  170. package/dist/extraction/languages/r.js.map +0 -1
  171. package/dist/extraction/languages/ruby.d.ts.map +0 -1
  172. package/dist/extraction/languages/ruby.js.map +0 -1
  173. package/dist/extraction/languages/rust.d.ts.map +0 -1
  174. package/dist/extraction/languages/rust.js.map +0 -1
  175. package/dist/extraction/languages/scala.d.ts.map +0 -1
  176. package/dist/extraction/languages/scala.js.map +0 -1
  177. package/dist/extraction/languages/solidity.d.ts.map +0 -1
  178. package/dist/extraction/languages/solidity.js.map +0 -1
  179. package/dist/extraction/languages/swift.d.ts.map +0 -1
  180. package/dist/extraction/languages/swift.js.map +0 -1
  181. package/dist/extraction/languages/terraform.d.ts.map +0 -1
  182. package/dist/extraction/languages/terraform.js.map +0 -1
  183. package/dist/extraction/languages/typescript.d.ts.map +0 -1
  184. package/dist/extraction/languages/typescript.js.map +0 -1
  185. package/dist/extraction/languages/vbnet.d.ts.map +0 -1
  186. package/dist/extraction/languages/vbnet.js.map +0 -1
  187. package/dist/extraction/liquid-extractor.d.ts.map +0 -1
  188. package/dist/extraction/liquid-extractor.js.map +0 -1
  189. package/dist/extraction/mybatis-extractor.d.ts.map +0 -1
  190. package/dist/extraction/mybatis-extractor.js.map +0 -1
  191. package/dist/extraction/parse-pool.d.ts.map +0 -1
  192. package/dist/extraction/parse-pool.js.map +0 -1
  193. package/dist/extraction/parse-worker.d.ts.map +0 -1
  194. package/dist/extraction/parse-worker.js.map +0 -1
  195. package/dist/extraction/razor-extractor.d.ts.map +0 -1
  196. package/dist/extraction/razor-extractor.js.map +0 -1
  197. package/dist/extraction/store-worker.d.ts.map +0 -1
  198. package/dist/extraction/store-worker.js.map +0 -1
  199. package/dist/extraction/store-writer.d.ts.map +0 -1
  200. package/dist/extraction/store-writer.js.map +0 -1
  201. package/dist/extraction/svelte-extractor.d.ts.map +0 -1
  202. package/dist/extraction/svelte-extractor.js.map +0 -1
  203. package/dist/extraction/tree-sitter-helpers.d.ts.map +0 -1
  204. package/dist/extraction/tree-sitter-helpers.js.map +0 -1
  205. package/dist/extraction/tree-sitter-types.d.ts.map +0 -1
  206. package/dist/extraction/tree-sitter-types.js.map +0 -1
  207. package/dist/extraction/tree-sitter.d.ts.map +0 -1
  208. package/dist/extraction/tree-sitter.js.map +0 -1
  209. package/dist/extraction/vue-extractor.d.ts.map +0 -1
  210. package/dist/extraction/vue-extractor.js.map +0 -1
  211. package/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  212. package/dist/extraction/wasm-runtime-flags.d.ts.map +0 -1
  213. package/dist/extraction/wasm-runtime-flags.js.map +0 -1
  214. package/dist/graph/index.d.ts.map +0 -1
  215. package/dist/graph/index.js.map +0 -1
  216. package/dist/graph/queries.d.ts.map +0 -1
  217. package/dist/graph/queries.js.map +0 -1
  218. package/dist/graph/traversal.d.ts.map +0 -1
  219. package/dist/graph/traversal.js.map +0 -1
  220. package/dist/graph-sources.d.ts.map +0 -1
  221. package/dist/graph-sources.js.map +0 -1
  222. package/dist/index.d.ts.map +0 -1
  223. package/dist/index.js.map +0 -1
  224. package/dist/installer/config-writer.d.ts.map +0 -1
  225. package/dist/installer/config-writer.js.map +0 -1
  226. package/dist/installer/index.d.ts.map +0 -1
  227. package/dist/installer/index.js.map +0 -1
  228. package/dist/installer/instructions-template.d.ts.map +0 -1
  229. package/dist/installer/instructions-template.js.map +0 -1
  230. package/dist/installer/targets/antigravity.d.ts.map +0 -1
  231. package/dist/installer/targets/antigravity.js.map +0 -1
  232. package/dist/installer/targets/claude.d.ts.map +0 -1
  233. package/dist/installer/targets/claude.js.map +0 -1
  234. package/dist/installer/targets/codebuddy.d.ts.map +0 -1
  235. package/dist/installer/targets/codebuddy.js.map +0 -1
  236. package/dist/installer/targets/codex.d.ts.map +0 -1
  237. package/dist/installer/targets/codex.js.map +0 -1
  238. package/dist/installer/targets/cursor.d.ts.map +0 -1
  239. package/dist/installer/targets/cursor.js.map +0 -1
  240. package/dist/installer/targets/deveco.d.ts.map +0 -1
  241. package/dist/installer/targets/deveco.js.map +0 -1
  242. package/dist/installer/targets/gemini.d.ts.map +0 -1
  243. package/dist/installer/targets/gemini.js.map +0 -1
  244. package/dist/installer/targets/hermes.d.ts.map +0 -1
  245. package/dist/installer/targets/hermes.js.map +0 -1
  246. package/dist/installer/targets/kiro.d.ts.map +0 -1
  247. package/dist/installer/targets/kiro.js.map +0 -1
  248. package/dist/installer/targets/opencode.d.ts.map +0 -1
  249. package/dist/installer/targets/opencode.js.map +0 -1
  250. package/dist/installer/targets/registry.d.ts.map +0 -1
  251. package/dist/installer/targets/registry.js.map +0 -1
  252. package/dist/installer/targets/shared.d.ts.map +0 -1
  253. package/dist/installer/targets/shared.js.map +0 -1
  254. package/dist/installer/targets/toml.d.ts.map +0 -1
  255. package/dist/installer/targets/toml.js.map +0 -1
  256. package/dist/installer/targets/types.d.ts.map +0 -1
  257. package/dist/installer/targets/types.js.map +0 -1
  258. package/dist/mcp/daemon-manager.d.ts.map +0 -1
  259. package/dist/mcp/daemon-manager.js.map +0 -1
  260. package/dist/mcp/daemon-paths.d.ts.map +0 -1
  261. package/dist/mcp/daemon-paths.js.map +0 -1
  262. package/dist/mcp/daemon-registry.d.ts.map +0 -1
  263. package/dist/mcp/daemon-registry.js.map +0 -1
  264. package/dist/mcp/daemon.d.ts.map +0 -1
  265. package/dist/mcp/daemon.js.map +0 -1
  266. package/dist/mcp/diff-impact.d.ts.map +0 -1
  267. package/dist/mcp/diff-impact.js.map +0 -1
  268. package/dist/mcp/dynamic-boundaries.d.ts.map +0 -1
  269. package/dist/mcp/dynamic-boundaries.js.map +0 -1
  270. package/dist/mcp/early-ppid.d.ts.map +0 -1
  271. package/dist/mcp/early-ppid.js.map +0 -1
  272. package/dist/mcp/engine.d.ts.map +0 -1
  273. package/dist/mcp/engine.js.map +0 -1
  274. package/dist/mcp/evidence-rendering.d.ts.map +0 -1
  275. package/dist/mcp/evidence-rendering.js.map +0 -1
  276. package/dist/mcp/explore-dedup.d.ts.map +0 -1
  277. package/dist/mcp/explore-dedup.js.map +0 -1
  278. package/dist/mcp/explore-repeat-guard.d.ts.map +0 -1
  279. package/dist/mcp/explore-repeat-guard.js.map +0 -1
  280. package/dist/mcp/explore-session-state.d.ts.map +0 -1
  281. package/dist/mcp/explore-session-state.js.map +0 -1
  282. package/dist/mcp/index.d.ts.map +0 -1
  283. package/dist/mcp/index.js.map +0 -1
  284. package/dist/mcp/liveness-watchdog.d.ts.map +0 -1
  285. package/dist/mcp/liveness-watchdog.js.map +0 -1
  286. package/dist/mcp/memory-budget.d.ts.map +0 -1
  287. package/dist/mcp/memory-budget.js.map +0 -1
  288. package/dist/mcp/ppid-watchdog.d.ts.map +0 -1
  289. package/dist/mcp/ppid-watchdog.js.map +0 -1
  290. package/dist/mcp/proxy.d.ts.map +0 -1
  291. package/dist/mcp/proxy.js.map +0 -1
  292. package/dist/mcp/query-cache.d.ts.map +0 -1
  293. package/dist/mcp/query-cache.js.map +0 -1
  294. package/dist/mcp/query-pool.d.ts.map +0 -1
  295. package/dist/mcp/query-pool.js.map +0 -1
  296. package/dist/mcp/query-worker.d.ts.map +0 -1
  297. package/dist/mcp/query-worker.js.map +0 -1
  298. package/dist/mcp/server-instructions.d.ts.map +0 -1
  299. package/dist/mcp/server-instructions.js.map +0 -1
  300. package/dist/mcp/session.d.ts.map +0 -1
  301. package/dist/mcp/session.js.map +0 -1
  302. package/dist/mcp/startup-handshake.d.ts.map +0 -1
  303. package/dist/mcp/startup-handshake.js.map +0 -1
  304. package/dist/mcp/stdin-teardown.d.ts.map +0 -1
  305. package/dist/mcp/stdin-teardown.js.map +0 -1
  306. package/dist/mcp/tools.d.ts.map +0 -1
  307. package/dist/mcp/tools.js.map +0 -1
  308. package/dist/mcp/transport.d.ts.map +0 -1
  309. package/dist/mcp/transport.js.map +0 -1
  310. package/dist/mcp/version.d.ts.map +0 -1
  311. package/dist/mcp/version.js.map +0 -1
  312. package/dist/project-config.d.ts.map +0 -1
  313. package/dist/project-config.js.map +0 -1
  314. package/dist/project-map/index.d.ts.map +0 -1
  315. package/dist/project-map/index.js.map +0 -1
  316. package/dist/resolution/c-fnptr-synthesizer.d.ts.map +0 -1
  317. package/dist/resolution/c-fnptr-synthesizer.js.map +0 -1
  318. package/dist/resolution/callback-synthesizer.d.ts.map +0 -1
  319. package/dist/resolution/callback-synthesizer.js.map +0 -1
  320. package/dist/resolution/cooperative-yield.d.ts.map +0 -1
  321. package/dist/resolution/cooperative-yield.js.map +0 -1
  322. package/dist/resolution/frameworks/arkts-entry.d.ts.map +0 -1
  323. package/dist/resolution/frameworks/arkts-entry.js.map +0 -1
  324. package/dist/resolution/frameworks/arkts-napi.d.ts.map +0 -1
  325. package/dist/resolution/frameworks/arkts-napi.js.map +0 -1
  326. package/dist/resolution/frameworks/astro.d.ts.map +0 -1
  327. package/dist/resolution/frameworks/astro.js.map +0 -1
  328. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +0 -1
  329. package/dist/resolution/frameworks/cargo-workspace.js.map +0 -1
  330. package/dist/resolution/frameworks/cics.d.ts.map +0 -1
  331. package/dist/resolution/frameworks/cics.js.map +0 -1
  332. package/dist/resolution/frameworks/csharp.d.ts.map +0 -1
  333. package/dist/resolution/frameworks/csharp.js.map +0 -1
  334. package/dist/resolution/frameworks/drupal.d.ts.map +0 -1
  335. package/dist/resolution/frameworks/drupal.js.map +0 -1
  336. package/dist/resolution/frameworks/expo-modules.d.ts.map +0 -1
  337. package/dist/resolution/frameworks/expo-modules.js.map +0 -1
  338. package/dist/resolution/frameworks/express.d.ts.map +0 -1
  339. package/dist/resolution/frameworks/express.js.map +0 -1
  340. package/dist/resolution/frameworks/fabric.d.ts.map +0 -1
  341. package/dist/resolution/frameworks/fabric.js.map +0 -1
  342. package/dist/resolution/frameworks/go.d.ts.map +0 -1
  343. package/dist/resolution/frameworks/go.js.map +0 -1
  344. package/dist/resolution/frameworks/goframe.d.ts.map +0 -1
  345. package/dist/resolution/frameworks/goframe.js.map +0 -1
  346. package/dist/resolution/frameworks/index.d.ts.map +0 -1
  347. package/dist/resolution/frameworks/index.js.map +0 -1
  348. package/dist/resolution/frameworks/java.d.ts.map +0 -1
  349. package/dist/resolution/frameworks/java.js.map +0 -1
  350. package/dist/resolution/frameworks/laravel.d.ts.map +0 -1
  351. package/dist/resolution/frameworks/laravel.js.map +0 -1
  352. package/dist/resolution/frameworks/nestjs.d.ts.map +0 -1
  353. package/dist/resolution/frameworks/nestjs.js.map +0 -1
  354. package/dist/resolution/frameworks/play.d.ts.map +0 -1
  355. package/dist/resolution/frameworks/play.js.map +0 -1
  356. package/dist/resolution/frameworks/python.d.ts.map +0 -1
  357. package/dist/resolution/frameworks/python.js.map +0 -1
  358. package/dist/resolution/frameworks/react-native.d.ts.map +0 -1
  359. package/dist/resolution/frameworks/react-native.js.map +0 -1
  360. package/dist/resolution/frameworks/react.d.ts.map +0 -1
  361. package/dist/resolution/frameworks/react.js.map +0 -1
  362. package/dist/resolution/frameworks/ruby.d.ts.map +0 -1
  363. package/dist/resolution/frameworks/ruby.js.map +0 -1
  364. package/dist/resolution/frameworks/rust.d.ts.map +0 -1
  365. package/dist/resolution/frameworks/rust.js.map +0 -1
  366. package/dist/resolution/frameworks/svelte.d.ts.map +0 -1
  367. package/dist/resolution/frameworks/svelte.js.map +0 -1
  368. package/dist/resolution/frameworks/swift-objc.d.ts.map +0 -1
  369. package/dist/resolution/frameworks/swift-objc.js.map +0 -1
  370. package/dist/resolution/frameworks/swift.d.ts.map +0 -1
  371. package/dist/resolution/frameworks/swift.js.map +0 -1
  372. package/dist/resolution/frameworks/terraform.d.ts.map +0 -1
  373. package/dist/resolution/frameworks/terraform.js.map +0 -1
  374. package/dist/resolution/frameworks/vue.d.ts.map +0 -1
  375. package/dist/resolution/frameworks/vue.js.map +0 -1
  376. package/dist/resolution/go-module.d.ts.map +0 -1
  377. package/dist/resolution/go-module.js.map +0 -1
  378. package/dist/resolution/goframe-synthesizer.d.ts.map +0 -1
  379. package/dist/resolution/goframe-synthesizer.js.map +0 -1
  380. package/dist/resolution/import-resolver.d.ts.map +0 -1
  381. package/dist/resolution/import-resolver.js.map +0 -1
  382. package/dist/resolution/index.d.ts.map +0 -1
  383. package/dist/resolution/index.js.map +0 -1
  384. package/dist/resolution/lru-cache.d.ts.map +0 -1
  385. package/dist/resolution/lru-cache.js.map +0 -1
  386. package/dist/resolution/memory-budget.d.ts.map +0 -1
  387. package/dist/resolution/memory-budget.js.map +0 -1
  388. package/dist/resolution/name-matcher.d.ts.map +0 -1
  389. package/dist/resolution/name-matcher.js.map +0 -1
  390. package/dist/resolution/path-aliases.d.ts.map +0 -1
  391. package/dist/resolution/path-aliases.js.map +0 -1
  392. package/dist/resolution/resolver-pool.d.ts.map +0 -1
  393. package/dist/resolution/resolver-pool.js.map +0 -1
  394. package/dist/resolution/resolver-worker.d.ts.map +0 -1
  395. package/dist/resolution/resolver-worker.js.map +0 -1
  396. package/dist/resolution/strip-comments.d.ts.map +0 -1
  397. package/dist/resolution/strip-comments.js.map +0 -1
  398. package/dist/resolution/swift-objc-bridge.d.ts.map +0 -1
  399. package/dist/resolution/swift-objc-bridge.js.map +0 -1
  400. package/dist/resolution/types.d.ts.map +0 -1
  401. package/dist/resolution/types.js.map +0 -1
  402. package/dist/resolution/workspace-packages.d.ts.map +0 -1
  403. package/dist/resolution/workspace-packages.js.map +0 -1
  404. package/dist/search/identifier-segments.d.ts.map +0 -1
  405. package/dist/search/identifier-segments.js.map +0 -1
  406. package/dist/search/literal-evidence.d.ts.map +0 -1
  407. package/dist/search/literal-evidence.js.map +0 -1
  408. package/dist/search/query-parser.d.ts.map +0 -1
  409. package/dist/search/query-parser.js.map +0 -1
  410. package/dist/search/query-plan-provider.d.ts.map +0 -1
  411. package/dist/search/query-plan-provider.js.map +0 -1
  412. package/dist/search/query-plan.d.ts.map +0 -1
  413. package/dist/search/query-plan.js.map +0 -1
  414. package/dist/search/query-utils.d.ts.map +0 -1
  415. package/dist/search/query-utils.js.map +0 -1
  416. package/dist/spec/build/diff-parser.d.ts.map +0 -1
  417. package/dist/spec/build/diff-parser.js.map +0 -1
  418. package/dist/spec/build/pipeline.d.ts.map +0 -1
  419. package/dist/spec/build/pipeline.js.map +0 -1
  420. package/dist/spec/build/scan.d.ts.map +0 -1
  421. package/dist/spec/build/scan.js.map +0 -1
  422. package/dist/spec/build/scope-resolver.d.ts.map +0 -1
  423. package/dist/spec/build/scope-resolver.js.map +0 -1
  424. package/dist/spec/build/spec-extractor.d.ts.map +0 -1
  425. package/dist/spec/build/spec-extractor.js.map +0 -1
  426. package/dist/spec/config.d.ts.map +0 -1
  427. package/dist/spec/config.js.map +0 -1
  428. package/dist/spec/db/commit-node.d.ts.map +0 -1
  429. package/dist/spec/db/commit-node.js.map +0 -1
  430. package/dist/spec/db/fragment-node.d.ts.map +0 -1
  431. package/dist/spec/db/fragment-node.js.map +0 -1
  432. package/dist/spec/db/fts.d.ts.map +0 -1
  433. package/dist/spec/db/fts.js.map +0 -1
  434. package/dist/spec/db/index.d.ts.map +0 -1
  435. package/dist/spec/db/index.js.map +0 -1
  436. package/dist/spec/db/persist.d.ts.map +0 -1
  437. package/dist/spec/db/persist.js.map +0 -1
  438. package/dist/spec/db/relations.d.ts.map +0 -1
  439. package/dist/spec/db/relations.js.map +0 -1
  440. package/dist/spec/db/schema.d.ts.map +0 -1
  441. package/dist/spec/db/schema.js.map +0 -1
  442. package/dist/spec/db/spec-node.d.ts.map +0 -1
  443. package/dist/spec/db/spec-node.js.map +0 -1
  444. package/dist/spec/db/sql-utils.d.ts.map +0 -1
  445. package/dist/spec/db/sql-utils.js.map +0 -1
  446. package/dist/spec/evolve/cluster-context.d.ts.map +0 -1
  447. package/dist/spec/evolve/cluster-context.js.map +0 -1
  448. package/dist/spec/evolve/commit-spec-analyzer.d.ts.map +0 -1
  449. package/dist/spec/evolve/commit-spec-analyzer.js.map +0 -1
  450. package/dist/spec/evolve/commit-spec-persister.d.ts.map +0 -1
  451. package/dist/spec/evolve/commit-spec-persister.js.map +0 -1
  452. package/dist/spec/evolve/impact-locator.d.ts.map +0 -1
  453. package/dist/spec/evolve/impact-locator.js.map +0 -1
  454. package/dist/spec/evolve/pipeline.d.ts.map +0 -1
  455. package/dist/spec/evolve/pipeline.js.map +0 -1
  456. package/dist/spec/evolve/spec-rewriter.d.ts.map +0 -1
  457. package/dist/spec/evolve/spec-rewriter.js.map +0 -1
  458. package/dist/spec/git/commits.d.ts.map +0 -1
  459. package/dist/spec/git/commits.js.map +0 -1
  460. package/dist/spec/git/exec.d.ts.map +0 -1
  461. package/dist/spec/git/exec.js.map +0 -1
  462. package/dist/spec/git/index.d.ts.map +0 -1
  463. package/dist/spec/git/index.js.map +0 -1
  464. package/dist/spec/graph/index.d.ts.map +0 -1
  465. package/dist/spec/graph/index.js.map +0 -1
  466. package/dist/spec/graph/queries.d.ts.map +0 -1
  467. package/dist/spec/graph/queries.js.map +0 -1
  468. package/dist/spec/llm/agent-client.d.ts.map +0 -1
  469. package/dist/spec/llm/agent-client.js.map +0 -1
  470. package/dist/spec/llm/agents/claude-code.d.ts.map +0 -1
  471. package/dist/spec/llm/agents/claude-code.js.map +0 -1
  472. package/dist/spec/llm/agents/codex.d.ts.map +0 -1
  473. package/dist/spec/llm/agents/codex.js.map +0 -1
  474. package/dist/spec/llm/agents/detect-utils.d.ts.map +0 -1
  475. package/dist/spec/llm/agents/detect-utils.js.map +0 -1
  476. package/dist/spec/llm/agents/deveco-code.d.ts.map +0 -1
  477. package/dist/spec/llm/agents/deveco-code.js.map +0 -1
  478. package/dist/spec/llm/agents/index.d.ts.map +0 -1
  479. package/dist/spec/llm/agents/index.js.map +0 -1
  480. package/dist/spec/llm/agents/types.d.ts.map +0 -1
  481. package/dist/spec/llm/agents/types.js.map +0 -1
  482. package/dist/spec/llm/client.d.ts.map +0 -1
  483. package/dist/spec/llm/client.js.map +0 -1
  484. package/dist/spec/llm/factory.d.ts.map +0 -1
  485. package/dist/spec/llm/factory.js.map +0 -1
  486. package/dist/spec/llm/prompts.d.ts.map +0 -1
  487. package/dist/spec/llm/prompts.js.map +0 -1
  488. package/dist/spec/llm/retry.d.ts.map +0 -1
  489. package/dist/spec/llm/retry.js.map +0 -1
  490. package/dist/spec/mine/addon/adapter.d.ts.map +0 -1
  491. package/dist/spec/mine/addon/adapter.js.map +0 -1
  492. package/dist/spec/mine/addon/render.d.ts.map +0 -1
  493. package/dist/spec/mine/addon/render.js.map +0 -1
  494. package/dist/spec/mine/addon/types.d.ts.map +0 -1
  495. package/dist/spec/mine/addon/types.js.map +0 -1
  496. package/dist/spec/mine/clustering/features.d.ts.map +0 -1
  497. package/dist/spec/mine/clustering/features.js.map +0 -1
  498. package/dist/spec/mine/clustering/index.d.ts.map +0 -1
  499. package/dist/spec/mine/clustering/index.js.map +0 -1
  500. package/dist/spec/mine/clustering/leiden.d.ts.map +0 -1
  501. package/dist/spec/mine/clustering/leiden.js.map +0 -1
  502. package/dist/spec/mine/clustering/text-similarity.d.ts.map +0 -1
  503. package/dist/spec/mine/clustering/text-similarity.js.map +0 -1
  504. package/dist/spec/mine/generator.d.ts.map +0 -1
  505. package/dist/spec/mine/generator.js.map +0 -1
  506. package/dist/spec/mine/persist.d.ts.map +0 -1
  507. package/dist/spec/mine/persist.js.map +0 -1
  508. package/dist/spec/mine/pipeline.d.ts.map +0 -1
  509. package/dist/spec/mine/pipeline.js.map +0 -1
  510. package/dist/spec/mine/scanner.d.ts.map +0 -1
  511. package/dist/spec/mine/scanner.js.map +0 -1
  512. package/dist/spec/types.d.ts.map +0 -1
  513. package/dist/spec/types.js.map +0 -1
  514. package/dist/spec/ui/index.d.ts.map +0 -1
  515. package/dist/spec/ui/index.js.map +0 -1
  516. package/dist/spec/ui/progress-handler.d.ts.map +0 -1
  517. package/dist/spec/ui/progress-handler.js.map +0 -1
  518. package/dist/spec/ui/progress.d.ts.map +0 -1
  519. package/dist/spec/ui/progress.js.map +0 -1
  520. package/dist/spec/utils/fs.d.ts.map +0 -1
  521. package/dist/spec/utils/fs.js.map +0 -1
  522. package/dist/spec/utils/index.d.ts.map +0 -1
  523. package/dist/spec/utils/index.js.map +0 -1
  524. package/dist/spec/utils/meta.d.ts.map +0 -1
  525. package/dist/spec/utils/meta.js.map +0 -1
  526. package/dist/spec/utils/truncate.d.ts.map +0 -1
  527. package/dist/spec/utils/truncate.js.map +0 -1
  528. package/dist/sync/git-hooks.d.ts.map +0 -1
  529. package/dist/sync/git-hooks.js.map +0 -1
  530. package/dist/sync/index.d.ts.map +0 -1
  531. package/dist/sync/index.js.map +0 -1
  532. package/dist/sync/watch-policy.d.ts.map +0 -1
  533. package/dist/sync/watch-policy.js.map +0 -1
  534. package/dist/sync/watcher.d.ts.map +0 -1
  535. package/dist/sync/watcher.js.map +0 -1
  536. package/dist/sync/worktree.d.ts.map +0 -1
  537. package/dist/sync/worktree.js.map +0 -1
  538. package/dist/types.d.ts.map +0 -1
  539. package/dist/types.js.map +0 -1
  540. package/dist/ui/glyphs.d.ts.map +0 -1
  541. package/dist/ui/glyphs.js.map +0 -1
  542. package/dist/ui/shimmer-progress.d.ts.map +0 -1
  543. package/dist/ui/shimmer-progress.js.map +0 -1
  544. package/dist/ui/shimmer-worker.d.ts.map +0 -1
  545. package/dist/ui/shimmer-worker.js.map +0 -1
  546. package/dist/ui/types.d.ts.map +0 -1
  547. package/dist/ui/types.js.map +0 -1
  548. package/dist/upgrade/index.d.ts.map +0 -1
  549. package/dist/upgrade/index.js.map +0 -1
  550. package/dist/upgrade/remove-binary.d.ts.map +0 -1
  551. package/dist/upgrade/remove-binary.js.map +0 -1
  552. package/dist/upgrade/update-check.d.ts.map +0 -1
  553. package/dist/upgrade/update-check.js.map +0 -1
  554. package/dist/utils.d.ts.map +0 -1
  555. package/dist/utils.js.map +0 -1
package/dist/mcp/tools.js CHANGED
@@ -21,9 +21,12 @@ exports.queryAsBareSymbolInventory = queryAsBareSymbolInventory;
21
21
  exports.hasPositiveAnswerNowDirective = hasPositiveAnswerNowDirective;
22
22
  exports.reconcilePartialAnswerNow = reconcilePartialAnswerNow;
23
23
  const query_pool_1 = require("./query-pool");
24
+ const source_slice_identity_1 = require("./source-slice-identity");
24
25
  const evidence_rendering_1 = require("./evidence-rendering");
26
+ const arkts_evidence_packs_1 = require("./arkts-evidence-packs");
27
+ const evidence_paths_1 = require("../graph/evidence-paths");
25
28
  const query_plan_1 = require("../search/query-plan");
26
- const memory_budget_1 = require("./memory-budget");
29
+ const index_availability_1 = require("./index-availability");
27
30
  const directory_1 = require("../directory");
28
31
  // Lazy-load the heavy HomeGraph chain off the MCP startup path — see the same
29
32
  // helper in engine.ts. ToolHandler must load to answer tools/list (static
@@ -657,7 +660,7 @@ exports.tools = [
657
660
  {
658
661
  name: 'homegraph_search',
659
662
  description: 'LAST RESORT spelling lookup — locations only, no source. Required: `query` (e.g. "signIn"). ' +
660
- 'Prefer explore/callers/node when names are known. ' +
663
+ 'Use ordinary scoped search/read when names or paths are known; use graph tools only for missing structural evidence. ' +
661
664
  'DO NOT call for topic file-lists, concept compares, or SDK/@kit feature catalogs (those return Skip guidance). ' +
662
665
  'Also skip literal string/pattern greps — use Grep instead. ' +
663
666
  'Bare-name search may return a compact explore result instead of locations.',
@@ -687,7 +690,7 @@ exports.tools = [
687
690
  {
688
691
  name: 'homegraph_callers',
689
692
  description: 'Compact caller list for one NAMED in-repo symbol (no bodies). Required: `symbol` (e.g. "authenticate"). ' +
690
- 'Cheaper than explore when you only need who-calls-X. For multi-file flows use homegraph_explore. ' +
693
+ 'Cheaper than explore when you only need who-calls-X. For an unresolved cross-symbol flow, consider homegraph_explore. ' +
691
694
  'DO NOT call for SDK catalogs, topic file-lists, concept compares, or hypothetics.',
692
695
  inputSchema: {
693
696
  type: 'object',
@@ -714,7 +717,7 @@ exports.tools = [
714
717
  {
715
718
  name: 'homegraph_callees',
716
719
  description: 'Compact callee list for one NAMED in-repo symbol (no bodies). Required: `symbol` (e.g. "authenticate"). ' +
717
- 'Cheaper than explore when you only need what-X-calls. For multi-file flows use homegraph_explore. ' +
720
+ 'Cheaper than explore when you only need what-X-calls. For an unresolved cross-symbol flow, consider homegraph_explore. ' +
718
721
  'DO NOT use for out-of-repo SDK catalogs or counterfactual analysis.',
719
722
  inputSchema: {
720
723
  type: 'object',
@@ -815,9 +818,9 @@ exports.tools = [
815
818
  'Cheaper than explore when you already know the name and only need one body. ' +
816
819
  'FILE: `file` only → line-numbered source + dependents. ' +
817
820
  'SYMBOL: body via includeCode + short trail; overloads return every body. ' +
818
- 'DO NOT call after explore already returned that symbol/file (multiplies tokens). ' +
819
- 'DO NOT crawl a feature with repeated node calls (prefer one explore for flows). ' +
820
- 'Treat returned source as already Read.',
821
+ 'Reuse complete unchanged source ranges already returned by any tool; refresh missing, truncated or edited ranges. ' +
822
+ 'Avoid repeated node calls over the same evidence; use explore only for an unresolved cross-symbol flow. ' +
823
+ 'Treat complete returned source ranges as already Read, not an entire file inferred from an excerpt.',
821
824
  inputSchema: {
822
825
  type: 'object',
823
826
  properties: {
@@ -860,7 +863,7 @@ exports.tools = [
860
863
  },
861
864
  {
862
865
  name: 'homegraph_usages',
863
- description: 'PRIMARY first tool for a narrow WHERE-USED question about one named API, `.member`, ALL_CAPS constant, field, or mutex. ' +
866
+ description: 'Optional focused tool for an unresolved WHERE-USED question about one named API, `.member`, ALL_CAPS constant, field, or mutex. ' +
864
867
  'Choose this instead of homegraph_explore when the requested answer is usage/reference locations. ' +
865
868
  'Required: `query`. Returns usage files/lines only; it does not build a general flow or source dump. ' +
866
869
  '`homegraph_explore` auto-routes equivalent high-confidence queries here only for compatibility.',
@@ -879,7 +882,7 @@ exports.tools = [
879
882
  },
880
883
  {
881
884
  name: 'homegraph_modules',
882
- description: 'PRIMARY first tool for a narrow DEPENDENCY/CYCLE question about named path modules or `*common` / `*service` / `*component` / `*constants` modules. ' +
885
+ description: 'Optional focused tool for an unresolved DEPENDENCY/CYCLE question about named path modules or `*common` / `*service` / `*component` / `*constants` modules. ' +
883
886
  'Choose this instead of homegraph_explore when the requested answer is module topology. ' +
884
887
  'Required: `query`. It does not build a general code flow or scan unrelated survey families. ' +
885
888
  '`homegraph_explore` auto-routes equivalent high-confidence dependency questions here only for compatibility.',
@@ -898,7 +901,7 @@ exports.tools = [
898
901
  },
899
902
  {
900
903
  name: 'homegraph_native',
901
- description: 'PRIMARY first tool for a narrow NAPI/NATIVE EXPORT or registration question about one named path or Type. ' +
904
+ description: 'Optional focused tool for an unresolved NAPI/NATIVE EXPORT or registration question about one named path or Type. ' +
902
905
  'Choose this instead of homegraph_explore when the requested answer is the ArkTS↔native export surface. Required: `query`. ' +
903
906
  'Returns indexed export descriptors/registration sites without a general domain file dump. ' +
904
907
  '`homegraph_explore` auto-routes equivalent high-confidence NAPI/export questions here only for compatibility.',
@@ -917,26 +920,16 @@ exports.tools = [
917
920
  },
918
921
  {
919
922
  name: 'homegraph_explore',
920
- description: 'GENERAL PRIMARY entry for understanding THIS repo before you edit or answer structural questions. ' +
921
- 'For an explicit narrow where-used, named module dependency/cycle, or NAPI/native export inventory, choose ' +
922
- 'homegraph_usages, homegraph_modules, or homegraph_native instead; this tool keeps conservative auto-routing only for compatibility. ' +
923
- 'Returns call paths + compact line-numbered source for the relevant symbols. Required: `query`. ' +
924
- 'CALL FIRST (alone, no parallel Grep/Read) when you will change an existing codebase — pass the user task or domain keywords ' +
925
- '(page/module/feature/component words); locate where to edit before writing code. Also CALL FIRST for how/wired questions, ' +
926
- 'named Type/Component/Page/Dialog, Type.member, click→handler, inheritance/subtypes, declaration/attribute sites, ' +
927
- 'or a cross-symbol mechanism/flow. Use the named focused tools for exact usage, module-topology, or native-export inventories. ' +
928
- 'PascalCase names optional when domain keywords suffice. ' +
929
- 'For edits preserve the requested action, target product/module and exclusions; taskContext may carry the full task. ' +
930
- 'Prefer callers/node when one named symbol is already enough. ' +
931
- 'DO NOT call for topic file-lists with no Type/file, literal copy hunts / pure existence compares with no anchors, ' +
932
- 'official-docs-only asks, empty-project-from-scratch scaffolds, git history, or media/binary asset inventories — those return Skip. ' +
933
- '@kit / OHOS API questions ARE in scope when the SDK API graph is available — exact where-used → homegraph_usages; ' +
934
- 'mechanism/API-symbol flow → homegraph_explore. ' +
935
- 'Literal string/pattern hunts → Grep; media assets → Glob; git history → git. ' +
936
- 'One explore; then answer or edit from Source + trail — do not re-grep/node/read the same symbols. ' +
937
- 'Overlapping paraphrase explores are refused (name a new Type/file/@kit to continue). ' +
938
- 'Busy/partial → retry ONCE with the named Next anchor or ONE narrow Grep — not a Grep/node storm '
939
- + '(session refuses further explore / depth fan-out after Partial).',
923
+ description: 'Optional graph evidence for a concrete unresolved cross-symbol mechanism in THIS repo. Required: `query`. ' +
924
+ 'Use ordinary bash/search/read for paths, symbols, literal strings and local changes; continue editing when that evidence suffices. ' +
925
+ 'Do not call for routine pre-edit orientation or merely because implementation is difficult. ' +
926
+ 'For a missing usage, dependency/cycle or native-registration relation, use ' +
927
+ 'homegraph_usages, homegraph_modules, or homegraph_native instead. ' +
928
+ 'Returns call paths and compact line-numbered source. ArkTS symbol evidence uses complete declarations and bounded directed paths with intermediate source dependencies; explicit Gaps and stop reasons name omitted or unverified evidence. Qualify ambiguous symbols by owning type or file. State the missing relation with known anchors, requested action, scope and constraints; taskContext can carry the full task. ' +
929
+ 'Reuse unchanged complete ranges; refresh missing, edited or truncated evidence. ' +
930
+ 'No new evidence → change to a targeted source inspection, not a paraphrased explore. ' +
931
+ 'Partial/busy → at most one focused recovery for the named gap; budgets are ceilings, not required calls. ' +
932
+ 'Retrieval completion is not task completion: continue implementation and required validation.',
940
933
  inputSchema: {
941
934
  type: 'object',
942
935
  properties: {
@@ -1015,7 +1008,7 @@ exports.tools = [
1015
1008
  {
1016
1009
  name: 'homegraph_files',
1017
1010
  description: 'Indexed directory tree (paths and symbol counts only — NO source). ' +
1018
- 'Only for coarse folder layout when explore cannot help. For where/what/how code questions use homegraph_explore.',
1011
+ 'Optional coarse folder inventory; prefer ordinary file listing for known paths. Use graph tools only for missing structural evidence.',
1019
1012
  inputSchema: {
1020
1013
  type: 'object',
1021
1014
  properties: {
@@ -1483,7 +1476,6 @@ class ToolHandler {
1483
1476
  return withRequiredProjectPath(visible);
1484
1477
  try {
1485
1478
  const stats = this.cg.getStats();
1486
- const budget = getExploreBudget(stats.fileCount);
1487
1479
  // Tiny-repo tool gating: on projects under TINY_REPO_FILE_THRESHOLD
1488
1480
  // files, only expose the core trio (search, node, explore) — one
1489
1481
  // below even the 4-tool default: at this scale callers, too, reduces
@@ -1524,7 +1516,7 @@ class ToolHandler {
1524
1516
  if (tool.name === 'homegraph_explore') {
1525
1517
  return {
1526
1518
  ...tool,
1527
- description: `${tool.description} Budget: make at most ${budget} calls for this project (${stats.fileCount.toLocaleString()} files indexed).`,
1519
+ description: `${tool.description} ${this.exploreSuffix(stats.fileCount)}`,
1528
1520
  };
1529
1521
  }
1530
1522
  return tool;
@@ -1534,6 +1526,52 @@ class ToolHandler {
1534
1526
  return visible;
1535
1527
  }
1536
1528
  }
1529
+ /**
1530
+ * Per-repo suffix appended to homegraph_explore's description (Spec 0027).
1531
+ *
1532
+ * fileCount === 0 must not read as "this project is empty": hosts snapshot
1533
+ * tools/list once at connect (#964), and an auto-init that is still building
1534
+ * reports 0 at that instant. Field evidence (DevEco Code bench, 3 sessions,
1535
+ * zero homegraph calls): agents read "make at most 1 calls for this project
1536
+ * (0 files indexed)" as terminal — "homegraph isn't indexed for this
1537
+ * project" — and permanently fell back to Read/Grep even though the index
1538
+ * completed seconds later. Mirror maybeDeepToolPhaseGate's success-shaped
1539
+ * guidance so the frozen description and the live call-time response tell
1540
+ * the same story: failed build → say so (indexing is the user's call, so
1541
+ * the agent relays it); still building → point at homegraph_project and
1542
+ * retry; genuinely empty → honest empty note. Only fileCount > 0 carries a
1543
+ * call budget — there is nothing to budget over an unbuilt index.
1544
+ */
1545
+ exploreSuffix(fileCount) {
1546
+ if (fileCount > 0) {
1547
+ return `Budget: make at most ${getExploreBudget(fileCount)} calls for this project (${fileCount.toLocaleString()} files indexed).`;
1548
+ }
1549
+ const cg = this.cg;
1550
+ if (cg) {
1551
+ try {
1552
+ // Failed check comes first: a failed full build rolls build_phase back
1553
+ // to 'fast' (startBackgroundFullBuild catch), so the building branch
1554
+ // below would otherwise mask the failure.
1555
+ if (cg.getQueryBuilder().getMetadata('index_state') === 'failed') {
1556
+ return 'The last full index build for this project failed, so results will be empty. Tell the user to re-run `homegraph index`.';
1557
+ }
1558
+ const state = (0, index_availability_1.resolveProductIndexState)(cg);
1559
+ if (state === 'empty') {
1560
+ return (0, index_availability_1.productIndexGuidance)('empty');
1561
+ }
1562
+ if (state === 'fast') {
1563
+ return (0, index_availability_1.productIndexGuidance)('fast');
1564
+ }
1565
+ if (state === 'syncing') {
1566
+ return (0, index_availability_1.productIndexGuidance)('syncing');
1567
+ }
1568
+ }
1569
+ catch {
1570
+ /* metadata is advisory — fall through to the empty note */
1571
+ }
1572
+ }
1573
+ return 'No files are indexed for this project; results will be empty until an index is built.';
1574
+ }
1537
1575
  /**
1538
1576
  * Get HomeGraph instance for a project
1539
1577
  *
@@ -1854,55 +1892,61 @@ class ToolHandler {
1854
1892
  const composed = `${formatDegradedBanner(reason)}\n\n${head.text}`;
1855
1893
  return { ...result, content: [{ type: 'text', text: composed }, ...tail] };
1856
1894
  }
1857
- // Defensive: some test fakes inject a partial HomeGraph stub without the
1858
- // newer pending-files API. Treat missing/throwing as "no pending files."
1859
- let pending = [];
1860
- try {
1861
- pending = cg.getPendingFiles?.() ?? [];
1862
- }
1863
- catch {
1864
- return result;
1865
- }
1866
- if (pending.length === 0)
1895
+ // Spec 0035: pending/dirty is a one-line status footer (withProductStatusFooter),
1896
+ // not the long ⚠️ stale banner. Keep formatStaleBanner helpers for tests /
1897
+ // status tool; do not prepend them on every read tool.
1898
+ return result;
1899
+ }
1900
+ /**
1901
+ * Append a one-line product index status footer (Spec 0035).
1902
+ * Guidance-only replies that already start with `HomeGraph status=` are left alone.
1903
+ */
1904
+ withProductStatusFooter(result, projectPath) {
1905
+ if (result.isError)
1867
1906
  return result;
1868
1907
  const [first, ...rest] = result.content;
1869
1908
  if (!first || first.type !== 'text')
1870
1909
  return result;
1871
- const text = first.text;
1872
- const inResponse = [];
1873
- const elsewhere = [];
1874
- for (const p of pending) {
1875
- // Substring match against the project-relative POSIX path — that's
1876
- // exactly the format both the watcher and every homegraph response
1877
- // emit, so a plain includes() is sufficient and avoids regex pitfalls.
1878
- if (text.includes(p.path))
1879
- inResponse.push(p);
1880
- else
1881
- elsewhere.push(p);
1910
+ if ((0, index_availability_1.textAlreadyHasProductStatus)(first.text))
1911
+ return result;
1912
+ let cg;
1913
+ try {
1914
+ cg = this.getHomeGraph(projectPath);
1915
+ }
1916
+ catch {
1917
+ return result;
1882
1918
  }
1883
- let banner = '';
1884
- if (inResponse.length > 0) {
1885
- let dbPath = null;
1919
+ if (this.cg && cg !== this.cg) {
1886
1920
  try {
1887
- // Large indexes skip catch-up — soft banner so agents don't abandon HG for Read.
1888
- const root = cg.getProjectRoot();
1889
- dbPath = (0, path_1.resolve)(root, '.homegraph', 'homegraph.db');
1921
+ const sameProject = (0, path_1.resolve)(this.cg.getProjectRoot()) === (0, path_1.resolve)(cg.getProjectRoot());
1922
+ if (sameProject)
1923
+ cg = this.cg;
1890
1924
  }
1891
1925
  catch {
1892
- dbPath = null;
1926
+ /* leave cg */
1893
1927
  }
1894
- banner = formatStaleBanner(inResponse, {
1895
- catchUpDeferred: (0, memory_budget_1.shouldSkipCatchUpSync)(dbPath),
1896
- });
1897
1928
  }
1898
- let footer = '';
1899
- if (elsewhere.length > 0) {
1900
- footer = formatStaleFooter(elsewhere);
1929
+ let state;
1930
+ try {
1931
+ state = (0, index_availability_1.resolveProductIndexState)(cg);
1901
1932
  }
1902
- if (!banner && !footer)
1933
+ catch {
1903
1934
  return result;
1904
- const composed = [banner, text, footer].filter(Boolean).join('\n\n');
1905
- return { ...result, content: [{ type: 'text', text: composed }, ...rest] };
1935
+ }
1936
+ let pendingPaths;
1937
+ if (state === 'dirty') {
1938
+ try {
1939
+ pendingPaths = (cg.getPendingFiles?.() ?? []).map((p) => p.path);
1940
+ }
1941
+ catch {
1942
+ pendingPaths = [];
1943
+ }
1944
+ }
1945
+ const line = (0, index_availability_1.formatProductStatusLine)(state, { pendingPaths });
1946
+ return {
1947
+ ...result,
1948
+ content: [{ type: 'text', text: `${first.text}\n\n${line}` }, ...rest],
1949
+ };
1906
1950
  }
1907
1951
  /**
1908
1952
  * Execute a tool by name.
@@ -1913,7 +1957,7 @@ class ToolHandler {
1913
1957
  async execute(toolName, args, sessionState) {
1914
1958
  const requestStartedAt = Date.now();
1915
1959
  args = { ...args };
1916
- for (const key of [QUERY_PLAN_ARG, QUERY_DEADLINE_ARG, QUERY_STARTED_ARG, QUERY_INDEX_STATE_ARG, QUERY_FAST_ATTEMPTED_ARG])
1960
+ for (const key of [QUERY_PLAN_ARG, QUERY_DEADLINE_ARG, QUERY_STARTED_ARG, QUERY_INDEX_STATE_ARG, QUERY_FAST_ATTEMPTED_ARG, '_hgEvidenceMaxChars'])
1917
1961
  delete args[key];
1918
1962
  try {
1919
1963
  // Block the first tool call on the engine's post-open reconcile so we
@@ -2023,10 +2067,13 @@ class ToolHandler {
2023
2067
  }
2024
2068
  cacheKey = (0, query_cache_1.buildMcpQueryCacheKey)(toolName, args, fileCount);
2025
2069
  const cached = cacheIndex.getEntry(cacheQueries, cacheKey);
2026
- if (cached) {
2070
+ const packMeta = cached?._meta?.homegraphEvidencePacks;
2071
+ const cachedFiles = cached?._meta?.homegraphEvidence?.files;
2072
+ if (cached && (!packMeta || (packMeta.status === 'complete'
2073
+ && this.areEvidenceFilesCurrent(cachedFiles ?? [], cacheCg.getProjectRoot())))) {
2027
2074
  const diagnosed = this.withQueryPlanDiagnostics(cached, args, true);
2028
2075
  const withWorktree = this.withWorktreeNotice(diagnosed, projectPath);
2029
- return this.withStalenessNotice(withWorktree, projectPath);
2076
+ return this.withProductStatusFooter(this.withStalenessNotice(withWorktree, projectPath), projectPath);
2030
2077
  }
2031
2078
  }
2032
2079
  catch {
@@ -2082,15 +2129,15 @@ class ToolHandler {
2082
2129
  // Fast explore must still file Partial/ANSWER meta into the session
2083
2130
  // so explore + depth fuses see it (textResult-only paths used to skip).
2084
2131
  let served = fast;
2085
- if (toolName === 'homegraph_explore' && sessionState) {
2086
- served = this.takeExploreEmission(this.ensureExploreEmission(fast, rootFast, q), sessionState);
2132
+ if ((toolName === 'homegraph_explore' && sessionState) || fast._meta?.homegraphEvidencePacks) {
2133
+ served = this.takeExploreEmission(this.ensureExploreEmission(fast, rootFast, q), toolName === 'homegraph_explore' ? sessionState : undefined);
2087
2134
  }
2088
2135
  served = this.withQueryPlanDiagnostics(served, args);
2089
2136
  if (cacheEnabled && cacheKey && cacheQueries && cacheIndex && !served.isError) {
2090
2137
  cacheIndex.setEntry(cacheQueries, cacheKey, toolName, served);
2091
2138
  }
2092
2139
  const withWorktree = this.withWorktreeNotice(served, projectPath);
2093
- return this.withStalenessNotice(withWorktree, projectPath);
2140
+ return this.withProductStatusFooter(this.withStalenessNotice(withWorktree, projectPath), projectPath);
2094
2141
  }
2095
2142
  if (requestPlan)
2096
2143
  args[QUERY_FAST_ATTEMPTED_ARG] = true;
@@ -2121,7 +2168,7 @@ class ToolHandler {
2121
2168
  cacheIndex.setEntry(cacheQueries, cacheKey, toolName, result);
2122
2169
  }
2123
2170
  const withWorktree = this.withWorktreeNotice(result, projectPath);
2124
- return this.withStalenessNotice(withWorktree, projectPath);
2171
+ return this.withProductStatusFooter(this.withStalenessNotice(withWorktree, projectPath), projectPath);
2125
2172
  }
2126
2173
  catch (err) {
2127
2174
  // Expected condition, not a malfunction: answer as a SUCCESS so the
@@ -2137,7 +2184,11 @@ class ToolHandler {
2137
2184
  if (err instanceof PathRefusalError) {
2138
2185
  return this.errorResult(err.message);
2139
2186
  }
2140
- return this.errorResult(`Tool execution failed: ${err instanceof Error ? err.message : String(err)}. ` +
2187
+ const msg = err instanceof Error ? err.message : String(err);
2188
+ if ((0, index_availability_1.isSqliteBusyMessage)(msg)) {
2189
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
2190
+ }
2191
+ return this.errorResult(`Tool execution failed: ${msg}. ` +
2141
2192
  'This is an internal homegraph error — retry the call once; if it persists, ' +
2142
2193
  'continue without homegraph for this task.');
2143
2194
  }
@@ -2193,6 +2244,10 @@ class ToolHandler {
2193
2244
  if (decision.reason !== 'overlap')
2194
2245
  return true;
2195
2246
  const files = decision.matched?.files.filter((file) => file.bytes > 0 && file.ranges.length > 0) ?? [];
2247
+ return this.areEvidenceFilesCurrent(files, projectRoot);
2248
+ }
2249
+ /** Same bounded fingerprint check for repeat protection and cached source packs. */
2250
+ areEvidenceFilesCurrent(files, projectRoot) {
2196
2251
  if (files.length === 0 || files.length > 24)
2197
2252
  return false;
2198
2253
  let remainingBytes = 2 * 1024 * 1024;
@@ -2406,7 +2461,11 @@ class ToolHandler {
2406
2461
  if (err instanceof PathRefusalError) {
2407
2462
  return this.errorResult(err.message);
2408
2463
  }
2409
- return this.errorResult(`Tool execution failed: ${err instanceof Error ? err.message : String(err)}. ` +
2464
+ const msg = err instanceof Error ? err.message : String(err);
2465
+ if ((0, index_availability_1.isSqliteBusyMessage)(msg)) {
2466
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
2467
+ }
2468
+ return this.errorResult(`Tool execution failed: ${msg}. ` +
2410
2469
  'This is an internal homegraph error — retry the call once; if it persists, ' +
2411
2470
  'continue without homegraph for this task.');
2412
2471
  }
@@ -2449,34 +2508,31 @@ class ToolHandler {
2449
2508
  }
2450
2509
  }
2451
2510
  /**
2452
- * Gate symbol/graph tools while auto-init is still on the fast map or
2453
- * background full index (and no nodes exist yet). Success-shaped guidance —
2454
- * never isError — so agents keep using HomeGraph.
2511
+ * Gate symbol/graph tools by product index state (Spec 0032).
2512
+ * Success-shaped guidance — never isError — so agents keep using HomeGraph.
2455
2513
  */
2456
2514
  maybeDeepToolPhaseGate(cg, _toolName) {
2457
- const phase = cg.getBuildPhase();
2458
- if (phase === 'full')
2515
+ const state = (0, index_availability_1.resolveProductIndexState)(cg);
2516
+ if (state === 'full' || state === 'dirty')
2459
2517
  return null;
2518
+ if (state === 'syncing') {
2519
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
2520
+ }
2521
+ if (state === 'empty') {
2522
+ return this.textResult((0, index_availability_1.productIndexGuidance)('empty'));
2523
+ }
2524
+ // fast: allow deep tools once some symbols exist (partial index).
2460
2525
  try {
2461
2526
  if (cg.getStats().nodeCount > 0)
2462
2527
  return null;
2463
2528
  }
2464
- catch {
2465
- /* ignore */
2466
- }
2467
- if (phase === 'fast' || phase === 'indexing') {
2468
- return this.textResult([
2469
- `Full symbol index is still building (phase=${phase}).`,
2470
- 'Use `homegraph_project` for the module/file map now, then retry this tool once indexing finishes.',
2471
- ].join('\n'));
2472
- }
2473
- if (phase === 'building_fast' || phase === 'none') {
2474
- return this.textResult([
2475
- 'HomeGraph is still preparing the project map.',
2476
- 'Retry in a few seconds, or call `homegraph_project` once the fast build completes.',
2477
- ].join('\n'));
2529
+ catch (err) {
2530
+ const msg = err instanceof Error ? err.message : String(err);
2531
+ if ((0, index_availability_1.isSqliteBusyMessage)(msg)) {
2532
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
2533
+ }
2478
2534
  }
2479
- return null;
2535
+ return this.textResult((0, index_availability_1.productIndexGuidance)('fast'));
2480
2536
  }
2481
2537
  async handleSearch(args) {
2482
2538
  const query = this.validateString(args.query, 'query');
@@ -5339,7 +5395,7 @@ class ToolHandler {
5339
5395
  } } };
5340
5396
  }
5341
5397
  /** Select once; legacy section builders consume the same canonical query/features. */
5342
- tryPlannedFastPath(cg, plan, root) {
5398
+ tryPlannedFastPath(cg, plan, root, evidenceMaxChars) {
5343
5399
  const query = plan.canonicalQuery;
5344
5400
  if (plan.route === 'usages' || plan.route === 'modules' || plan.route === 'native') {
5345
5401
  return this.runSpecializedExploreRoute(plan.route, cg, query, root, plan);
@@ -5350,8 +5406,8 @@ class ToolHandler {
5350
5406
  if (plan.source === 'llm' && (plan.intent === 'general' || plan.intent === 'flow'))
5351
5407
  return null;
5352
5408
  return this.tryFastInventoryExplore(cg, query, root, plan)
5353
- ?? this.tryLightMechanismExplore(cg, query, root, plan)
5354
- ?? this.tryCompactLocalSymbolExplore(cg, query, root, plan);
5409
+ ?? this.tryLightMechanismExplore(cg, query, root, plan, evidenceMaxChars)
5410
+ ?? this.tryCompactLocalSymbolExplore(cg, query, root, plan, evidenceMaxChars);
5355
5411
  }
5356
5412
  /** Internal execution only: no recursive MCP calls, model requests or new deadline. */
5357
5413
  async executePlannedStep(args, plan) {
@@ -5385,7 +5441,7 @@ class ToolHandler {
5385
5441
  return served;
5386
5442
  }
5387
5443
  const fast = args[QUERY_FAST_ATTEMPTED_ARG] === true && plan.source === 'rules'
5388
- ? null : this.tryPlannedFastPath(cg, plan, cg.getProjectRoot());
5444
+ ? null : this.tryPlannedFastPath(cg, plan, cg.getProjectRoot(), args._hgEvidenceMaxChars);
5389
5445
  if (fast)
5390
5446
  return fast;
5391
5447
  return this.handleExplore({ ...args, query, [QUERY_PLAN_ARG]: plan });
@@ -5448,7 +5504,10 @@ class ToolHandler {
5448
5504
  }
5449
5505
  seenQueries.add(`${compiled.intent}:${compiled.canonicalQuery}`);
5450
5506
  try {
5451
- const result = await this.executePlannedStep({ ...args, [QUERY_DEADLINE_ARG]: deadline }, compiled);
5507
+ const stepCap = Math.max(0, Math.floor((outputBudget - used) / Math.max(1, plan.steps.length - diagnostics.length + 1)) - 100);
5508
+ const result = await this.executePlannedStep({ ...args, [QUERY_DEADLINE_ARG]: deadline,
5509
+ ...(multi ? { _hgEvidenceMaxChars: Math.max(0, stepCap - Math.min(1600, Math.floor(stepCap / 2)) - 2) } : {}),
5510
+ }, compiled);
5452
5511
  const body = result.content.map((part) => part.text).join('\n');
5453
5512
  const candidates = result.isError ? [] : this.locatedPlanBindings(cg, result, resolved);
5454
5513
  const childEmission = result[explore_session_state_1.EXPLORE_EMISSION_KEY];
@@ -5491,7 +5550,16 @@ class ToolHandler {
5491
5550
  bindings.set(step.id, visibleBindings);
5492
5551
  const bodyCap = Math.max(0, cap - receipt.length - 2);
5493
5552
  const trimmed = neutralBody.length > bodyCap;
5494
- const kept = (0, evidence_rendering_1.trimEvidenceAtLine)(neutralBody, bodyCap);
5553
+ const atomic = !!result._meta?.homegraphEvidencePacks;
5554
+ const kept = atomic && trimmed
5555
+ ? '[Partial source: complete evidence pack omitted by the shared output budget.]'.slice(0, bodyCap)
5556
+ : atomic ? neutralBody : (0, evidence_rendering_1.trimEvidenceAtLine)(neutralBody, bodyCap);
5557
+ if (atomic && trimmed) {
5558
+ receipt = '';
5559
+ diagnostic.locatedNodes = [];
5560
+ diagnostic.resolvedAnchors = [];
5561
+ bindings.set(step.id, []);
5562
+ }
5495
5563
  if (trimmed)
5496
5564
  diagnostic.status = 'partial';
5497
5565
  else
@@ -6185,9 +6253,29 @@ class ToolHandler {
6185
6253
  }
6186
6254
  return finishCompact('Inventory sections above are complete for this query. **ANSWER NOW.**');
6187
6255
  }
6188
- /**
6189
- * Render a compact symbol-bounded slice of one file (lightweight mechanism path).
6190
- */
6256
+ /** Pack already-located ArkTS evidence before legacy windowing can cut it. */
6257
+ tryArktsEvidenceExplore(cg, query, projectRoot, nodes, focusIds, maxChars, maxFiles, plan) {
6258
+ if (process.env.HOMEGRAPH_ARKTS_EVIDENCE_PACKS === '0')
6259
+ return null;
6260
+ if (!nodes.some(n => /\.ets$/i.test(n.filePath) && !n.filePath.startsWith('ohos-sdk:')))
6261
+ return null;
6262
+ const budget = getExploreOutputBudget(cg.getStats().fileCount);
6263
+ const queryPaths = process.env.HOMEGRAPH_ARKTS_QUERY_PATHS !== '0';
6264
+ if (queryPaths)
6265
+ nodes = (0, evidence_paths_1.completeEvidencePathCandidates)(query, nodes, (name, limit) => cg.getQueryBuilder().getNodesByQualifiedNameExact(name, limit), plan);
6266
+ const pathSearch = !queryPaths ? undefined : (0, evidence_paths_1.searchEvidencePaths)({
6267
+ getNode: id => cg.getNode(id),
6268
+ getEdges: (id, direction, kinds, limit, preferred) => cg.getQueryBuilder().getEvidenceEdges(id, direction, kinds, limit, preferred),
6269
+ }, (0, evidence_paths_1.resolveEvidencePathGoal)(query, nodes, focusIds, plan));
6270
+ const result = (0, arkts_evidence_packs_1.buildArktsEvidencePacks)(cg, { projectRoot, query, nodes, focusIds,
6271
+ maxChars: Math.min(budget.maxOutputChars, maxChars ?? budget.maxOutputChars), maxFiles, pathSearch });
6272
+ if (!result)
6273
+ return null;
6274
+ // The pack renderer already supplies neutral guidance and exact source bytes.
6275
+ return { content: [{ type: 'text', text: result.text }], [explore_session_state_1.EXPLORE_EMISSION_KEY]: result.emission,
6276
+ _meta: { homegraphEvidencePacks: result.metadata } };
6277
+ }
6278
+ /** Render a compact symbol-bounded slice on the legacy mechanism path. */
6191
6279
  renderLightMechanismSource(projectRoot, filePath, nodes, maxChars) {
6192
6280
  const absPath = (0, utils_1.validatePathWithinRoot)(projectRoot, filePath);
6193
6281
  if (!absPath || !(0, fs_1.existsSync)(absPath))
@@ -6223,7 +6311,7 @@ class ToolHandler {
6223
6311
  * findRelevantContext. Fast enough for MCP budget; complete enough to avoid
6224
6312
  * agent grep/read loops (token savings).
6225
6313
  */
6226
- tryLightMechanismExplore(cg, query, projectRoot, plan) {
6314
+ tryLightMechanismExplore(cg, query, projectRoot, plan, evidenceMaxChars) {
6227
6315
  if (!planFeature(plan, 'shouldTryLightMechanismExplore', query, query_utils_1.shouldTryLightMechanismExplore))
6228
6316
  return null;
6229
6317
  const STRUCTURE_KINDS = new Set(['class', 'struct', 'interface', 'component', 'method', 'function']);
@@ -6394,6 +6482,9 @@ class ToolHandler {
6394
6482
  const seeds = (0, query_utils_1.extractMechanismEntrySeeds)(query);
6395
6483
  const flow = this.buildFlowFromNamedSymbols(cg, `${query} ${seeds.join(' ')}`);
6396
6484
  const hasFlowPath = flow.pathNodeIds.size > 1;
6485
+ const evidence = this.tryArktsEvidenceExplore(cg, query, projectRoot, [...fileNodes.values()].flat().concat([...flow.pathNodeIds].flatMap(id => { const n = cg.getNode(id); return n ? [n] : []; })), new Set([...seedIds, ...flow.pathNodeIds]), evidenceMaxChars, undefined, plan);
6486
+ if (evidence)
6487
+ return evidence;
6397
6488
  const managerSection = this.formatDomainRoleInventory(managerHits.length > 0
6398
6489
  ? managerHits
6399
6490
  : [...seedIds].map((id) => cg.getNode(id)).filter((n) => !!n && (0, query_utils_1.isDomainRoleSymbol)(n.name, n.filePath, domainPathTokens)));
@@ -6861,7 +6952,7 @@ class ToolHandler {
6861
6952
  * Compact explore for local-symbol behavior questions — skips findRelevantContext
6862
6953
  * and caps to 1–2 defining files (avoids the ~24K related-file dump).
6863
6954
  */
6864
- tryCompactLocalSymbolExplore(cg, query, projectRoot, plan) {
6955
+ tryCompactLocalSymbolExplore(cg, query, projectRoot, plan, evidenceMaxChars) {
6865
6956
  // Inventory runs *before* this on the call sites. Do not refuse compact
6866
6957
  // merely because inventory *intent* matched — empty inventory must fall
6867
6958
  // through here (bare callbacks like OnSurfaceChangedCB).
@@ -7041,6 +7132,9 @@ class ToolHandler {
7041
7132
  }
7042
7133
  if (seedIds.size === 0)
7043
7134
  return null;
7135
+ const evidence = this.tryArktsEvidenceExplore(cg, query, projectRoot, [...fileNodes.values()].flat(), seedIds, evidenceMaxChars, undefined, plan);
7136
+ if (evidence)
7137
+ return evidence;
7044
7138
  const pathAffinity = (seedPath, otherPath) => {
7045
7139
  const a = seedPath.replace(/\\/g, '/').split('/');
7046
7140
  const b = otherPath.replace(/\\/g, '/').split('/');
@@ -10312,6 +10406,13 @@ class ToolHandler {
10312
10406
  }
10313
10407
  const flow = this.buildFlowFromNamedSymbols(cg, flowQuery);
10314
10408
  const hasFlowPath = flow.pathNodeIds.size > 0;
10409
+ // Keep literal/resource and specialized inventory rendering intact. This
10410
+ // first batch changes symbol-grounded structural evidence only.
10411
+ if ((hasFlowPath || flow.text.length > 0 || plan?.intent === 'flow') && !subgraph.literalEvidence?.hits.length) {
10412
+ const evidence = this.tryArktsEvidenceExplore(cg, query, projectRoot, [...subgraph.nodes.values()].concat([...flow.pathNodeIds].flatMap(id => { const n = cg.getNode(id); return n ? [n] : []; })), new Set([...subgraph.roots, ...flow.namedNodeIds, ...flow.pathNodeIds]), args._hgEvidenceMaxChars, explicitMaxFiles ? maxFiles : undefined, plan);
10413
+ if (evidence)
10414
+ return evidence;
10415
+ }
10315
10416
  budget = tightenExploreBudgetForQuery(budget, query, { hasFlowPath });
10316
10417
  // Honor an explicit maxFiles from the caller — budget.defaultMaxFiles is only
10317
10418
  // a default when the agent didn't ask for more (adaptive sibling tests pass 12).
@@ -11980,21 +12081,18 @@ class ToolHandler {
11980
12081
  lines.push(`**Build phase:** ${cg.getBuildPhase()}`, `**Files indexed:** ${stats.fileCount}`, `**Total nodes:** ${stats.nodeCount}`, `**Total edges:** ${stats.edgeCount}`, `**Database size:** ${(stats.dbSizeBytes / 1024 / 1024).toFixed(2)} MB`, ...(stats.walSizeBytes > 0
11981
12082
  ? [`**WAL size:** ${(stats.walSizeBytes / 1024 / 1024).toFixed(2)} MB`]
11982
12083
  : []), `**Graph sources:** ${cg.getGraphSources()}`);
11983
- // Surface the active SQLite backend: node:sqlite → better-sqlite3 → wasm.
12084
+ // Surface the active SQLite backend: node:sqlite → wasm.
11984
12085
  const backend = cg.getBackend();
11985
12086
  if (backend === 'node-sqlite') {
11986
12087
  lines.push(`**Backend:** node-sqlite (built-in)`);
11987
12088
  }
11988
- else if (backend === 'native') {
11989
- lines.push(`**Backend:** native (better-sqlite3)`);
11990
- }
11991
12089
  else {
11992
12090
  lines.push(`**Backend:** ⚠ wasm (no WAL backend available) — ` +
11993
12091
  `5-10x slower than WAL. Fix: ${sqlite_adapter_1.WASM_FALLBACK_FIX_RECIPE}`);
11994
12092
  }
11995
12093
  // Effective journal mode. 'wal' ⇒ concurrent reads never block on a writer;
11996
- // anything else ⇒ they can ("database is locked"). node:sqlite / native
11997
- // support WAL; wasm remaps to DELETE.
12094
+ // anything else ⇒ they can ("database is locked"). node:sqlite supports WAL;
12095
+ // wasm remaps to DELETE.
11998
12096
  const journalMode = cg.getJournalMode();
11999
12097
  if (journalMode === 'wal') {
12000
12098
  lines.push(`**Journal mode:** wal (concurrent reads safe)`);
@@ -12047,10 +12145,27 @@ class ToolHandler {
12047
12145
  */
12048
12146
  async handleProject(args) {
12049
12147
  const cg = this.getHomeGraph(args.projectPath);
12050
- const phase = cg.getBuildPhase();
12051
- if (phase === 'building_fast') {
12052
- return this.textResult('Fast project map is still building — retry in a few seconds.');
12148
+ const state = (0, index_availability_1.resolveProductIndexState)(cg);
12149
+ if (state === 'empty') {
12150
+ return this.textResult((0, index_availability_1.productIndexGuidance)('empty'));
12053
12151
  }
12152
+ if (state === 'syncing') {
12153
+ // Prefer returning the map when readable; only hard-stop if phase has no map.
12154
+ try {
12155
+ const peek = cg.getProjectMap({ includeFiles: false });
12156
+ if (peek.modules.length === 0) {
12157
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
12158
+ }
12159
+ }
12160
+ catch (err) {
12161
+ const msg = err instanceof Error ? err.message : String(err);
12162
+ if ((0, index_availability_1.isSqliteBusyMessage)(msg)) {
12163
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
12164
+ }
12165
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
12166
+ }
12167
+ }
12168
+ const phase = cg.getBuildPhase();
12054
12169
  let map = cg.getProjectMap({
12055
12170
  module: typeof args.module === 'string' ? args.module : undefined,
12056
12171
  includeFiles: args.includeFiles !== false,
@@ -12069,6 +12184,9 @@ class ToolHandler {
12069
12184
  }
12070
12185
  catch (err) {
12071
12186
  const message = err instanceof Error ? err.message : String(err);
12187
+ if ((0, index_availability_1.isSqliteBusyMessage)(message)) {
12188
+ return this.textResult((0, index_availability_1.productIndexGuidance)('syncing'));
12189
+ }
12072
12190
  return this.textResult(`Failed to build project map: ${message}`);
12073
12191
  }
12074
12192
  }
@@ -12081,9 +12199,6 @@ class ToolHandler {
12081
12199
  `modules: ${map.modules.length} · files: ${map.fileCount}`,
12082
12200
  '',
12083
12201
  ];
12084
- if (map.phase === 'fast' || map.phase === 'indexing') {
12085
- lines.push('_Full symbol index still building — this map has modules/files only (no call graph)._', '');
12086
- }
12087
12202
  for (const m of map.modules) {
12088
12203
  const rootLabel = m.rootPath || '.';
12089
12204
  lines.push(`### ${m.name} (\`${rootLabel}\`) · ${m.kind} · ${m.fileCount} files`);
@@ -12979,6 +13094,9 @@ class ToolHandler {
12979
13094
  // Line-numbered (cat -n style, like homegraph_explore and Read) so the
12980
13095
  // agent can cite/edit exact lines without re-Reading the file for them.
12981
13096
  const numbered = node.startLine ? numberSourceLines(code, node.startLine) : code;
13097
+ if (node.startLine && process.env.HOMEGRAPH_SOURCE_RECEIPTS === '1') {
13098
+ lines.push('', (0, source_slice_identity_1.sourceSliceIdentity)(node.filePath, node.startLine, code));
13099
+ }
12982
13100
  lines.push('', '```' + node.language, numbered, '```');
12983
13101
  }
12984
13102
  return lines.join('\n');