@reticlehq/server 3.5.0 → 3.7.0

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 (721) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +123 -116
  3. package/dist/chromium-launch-options.d.ts +3 -1
  4. package/dist/chromium-launch-options.js +2 -1
  5. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  6. package/dist/command/cli/adhoc-suite.js +42 -7
  7. package/dist/command/cli/adhoc-verdict.d.ts +19 -2
  8. package/dist/command/cli/adhoc-verdict.js +76 -9
  9. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  10. package/dist/command/cli/answers/gate-exit.js +45 -0
  11. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  12. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  13. package/dist/command/cli/answers/open-note.d.ts +2 -0
  14. package/dist/command/cli/answers/open-note.js +22 -0
  15. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  16. package/dist/command/cli/auth/device-flow.js +17 -0
  17. package/dist/command/cli/cli-doctor.js +14 -0
  18. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  19. package/dist/command/cli/cli-flow-commands.js +31 -112
  20. package/dist/command/cli/cli-kill.js +3 -2
  21. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  22. package/dist/command/cli/cli-parse-grammar.js +75 -0
  23. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  24. package/dist/command/cli/cli-parse-verify.js +18 -0
  25. package/dist/command/cli/cli-parse.d.ts +19 -28
  26. package/dist/command/cli/cli-parse.js +82 -182
  27. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  28. package/dist/command/cli/cli-update-commands.js +61 -9
  29. package/dist/command/cli/cli-usage.d.ts +33 -0
  30. package/dist/command/cli/cli-usage.js +287 -0
  31. package/dist/command/cli/cli-verify.d.ts +35 -5
  32. package/dist/command/cli/cli-verify.js +114 -35
  33. package/dist/command/cli/cloud-cli.d.ts +13 -0
  34. package/dist/command/cli/cloud-cli.js +192 -341
  35. package/dist/command/cli/cloud-kit.d.ts +12 -0
  36. package/dist/command/cli/cloud-kit.js +41 -2
  37. package/dist/command/cli/cloud-link.d.ts +57 -0
  38. package/dist/command/cli/cloud-link.js +308 -0
  39. package/dist/command/cli/cloud-login.d.ts +22 -0
  40. package/dist/command/cli/cloud-login.js +96 -8
  41. package/dist/command/cli/context-command.d.ts +1 -0
  42. package/dist/command/cli/context-command.js +33 -0
  43. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  44. package/dist/command/cli/daemon-start-options.js +24 -3
  45. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
  46. package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
  47. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  48. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  49. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  50. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  51. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  52. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  53. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  54. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  55. package/dist/command/cli/drive/drive-attach.d.ts +27 -2
  56. package/dist/command/cli/drive/drive-attach.js +71 -4
  57. package/dist/command/cli/drive/drive-command.d.ts +2 -1
  58. package/dist/command/cli/drive/drive-command.js +13 -7
  59. package/dist/command/cli/known-regression.d.ts +13 -0
  60. package/dist/command/cli/known-regression.js +34 -0
  61. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  62. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  63. package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
  64. package/dist/command/cli/mcp-command.d.ts +6 -0
  65. package/dist/command/cli/mcp-command.js +13 -5
  66. package/dist/command/cli/ports/port-holder.d.ts +10 -0
  67. package/dist/command/cli/ports/port-holder.js +25 -1
  68. package/dist/command/cli/project-name.d.ts +29 -1
  69. package/dist/command/cli/project-name.js +107 -2
  70. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  71. package/dist/command/cli/setup-mcp-cli.js +35 -12
  72. package/dist/command/cli/status/status-lines.d.ts +1 -0
  73. package/dist/command/cli/status/status-lines.js +47 -2
  74. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  75. package/dist/command/cli/status/workspace-links.js +29 -0
  76. package/dist/command/cli/try-command.d.ts +96 -0
  77. package/dist/command/cli/try-command.js +362 -0
  78. package/dist/command/cli/tutorial.d.ts +0 -100
  79. package/dist/command/cli/tutorial.js +0 -181
  80. package/dist/command/cli/verify-results.d.ts +19 -0
  81. package/dist/command/cli/verify-results.js +29 -0
  82. package/dist/command/cli-onboarding.d.ts +0 -11
  83. package/dist/command/cli-onboarding.js +0 -15
  84. package/dist/command/cli.d.ts +20 -0
  85. package/dist/command/cli.js +130 -104
  86. package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
  87. package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
  88. package/dist/command/daemon/daemon-resilience.js +4 -4
  89. package/dist/command/daemon/daemon-resolve.d.ts +23 -1
  90. package/dist/command/daemon/daemon-resolve.js +79 -9
  91. package/dist/command/setup/agent-writer.d.ts +1 -1
  92. package/dist/command/setup/agent-writer.js +3 -2
  93. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  94. package/dist/command/setup/bringup/bridge-port.js +13 -3
  95. package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
  96. package/dist/command/setup/bringup/connect-lease.js +1 -0
  97. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  98. package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
  99. package/dist/command/setup/bringup/dev-server-wait.js +19 -0
  100. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  101. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  102. package/dist/command/setup/init/agent-restart.js +28 -0
  103. package/dist/command/setup/init/init-port.d.ts +14 -1
  104. package/dist/command/setup/init/init-port.js +32 -2
  105. package/dist/command/setup/init/init-runtime.d.ts +22 -2
  106. package/dist/command/setup/init/init-runtime.js +114 -38
  107. package/dist/command/setup/node-effects.d.ts +2 -0
  108. package/dist/command/setup/node-effects.js +38 -9
  109. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  110. package/dist/command/setup/probe/existing-app.js +14 -0
  111. package/dist/command/setup/remaining-steps.js +2 -1
  112. package/dist/command/setup/run-setup.d.ts +34 -9
  113. package/dist/command/setup/run-setup.js +65 -51
  114. package/dist/command/setup/setup-command.d.ts +25 -1
  115. package/dist/command/setup/setup-command.js +59 -4
  116. package/dist/command/setup/setup-mcp.js +25 -2
  117. package/dist/command/setup/tauri-signing.d.ts +19 -0
  118. package/dist/command/setup/tauri-signing.js +79 -0
  119. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  120. package/dist/command/setup/terminal/listeners.js +37 -6
  121. package/dist/command/update/update-nudge.d.ts +9 -0
  122. package/dist/command/update/update-nudge.js +1 -1
  123. package/dist/command/update/updater.js +11 -15
  124. package/dist/command/version/version-nudge.js +3 -0
  125. package/dist/command/version/version-skew.d.ts +20 -1
  126. package/dist/command/version/version-skew.js +49 -4
  127. package/dist/features/crawl/crawl-tools.js +4 -0
  128. package/dist/features/crawl/crawl.d.ts +6 -0
  129. package/dist/features/crawl/crawl.js +23 -2
  130. package/dist/features/exhaust/ledger.d.ts +21 -14
  131. package/dist/features/exhaust/ledger.js +35 -9
  132. package/dist/features/harness/app-findings.d.ts +2 -0
  133. package/dist/features/harness/app-findings.js +52 -0
  134. package/dist/features/harness/drive-report.d.ts +61 -1
  135. package/dist/features/harness/drive-report.js +394 -26
  136. package/dist/features/harness/drive-runs.d.ts +120 -0
  137. package/dist/features/harness/drive-runs.js +289 -0
  138. package/dist/features/harness/drivers.d.ts +10 -14
  139. package/dist/features/harness/drivers.js +10 -14
  140. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  141. package/dist/features/harness/explore/console-pages.js +146 -0
  142. package/dist/features/harness/explore/disparity.d.ts +19 -0
  143. package/dist/features/harness/explore/disparity.js +71 -0
  144. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  145. package/dist/features/harness/explore/fake-app.js +49 -0
  146. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  147. package/dist/features/harness/explore/goal-search.js +144 -0
  148. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  149. package/dist/features/harness/explore/page-tree.js +148 -0
  150. package/dist/features/harness/explore/site-map.d.ts +34 -0
  151. package/dist/features/harness/explore/site-map.js +150 -0
  152. package/dist/features/harness/fill-values.d.ts +3 -73
  153. package/dist/features/harness/fill-values.js +3 -169
  154. package/dist/features/harness/goals.d.ts +82 -0
  155. package/dist/features/harness/goals.js +330 -0
  156. package/dist/features/harness/harness.d.ts +51 -1
  157. package/dist/features/harness/harness.js +207 -6
  158. package/dist/features/harness/platform/drive-target.d.ts +30 -0
  159. package/dist/features/harness/platform/drive-target.js +81 -0
  160. package/dist/features/harness/platform/local-apps.d.ts +127 -0
  161. package/dist/features/harness/platform/local-apps.js +280 -0
  162. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  163. package/dist/features/harness/platform/persona-credentials.js +69 -0
  164. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  165. package/dist/features/harness/platform/platform-drives.js +114 -0
  166. package/dist/features/harness/platform/refusal.d.ts +52 -0
  167. package/dist/features/harness/platform/refusal.js +71 -0
  168. package/dist/features/harness/platform/remote-drive.d.ts +186 -0
  169. package/dist/features/harness/platform/remote-drive.js +378 -0
  170. package/dist/features/harness/platform/script.d.ts +94 -0
  171. package/dist/features/harness/platform/script.js +260 -0
  172. package/dist/features/harness/platform/server-driver.d.ts +54 -0
  173. package/dist/features/harness/platform/server-driver.js +182 -0
  174. package/dist/features/harness/platform-config.d.ts +41 -1
  175. package/dist/features/harness/platform-config.js +106 -9
  176. package/dist/features/harness/route-guess.d.ts +13 -0
  177. package/dist/features/harness/route-guess.js +49 -0
  178. package/dist/features/harness/script/app-controls.d.ts +5 -0
  179. package/dist/features/harness/script/app-controls.js +40 -0
  180. package/dist/features/harness/script/lane-ids.d.ts +14 -0
  181. package/dist/features/harness/script/lane-ids.js +16 -0
  182. package/dist/features/harness/script/script-run.d.ts +70 -0
  183. package/dist/features/harness/script/script-run.js +606 -0
  184. package/dist/features/license/license.d.ts +2 -2
  185. package/dist/features/visual/step-shots.d.ts +31 -0
  186. package/dist/features/visual/step-shots.js +231 -0
  187. package/dist/features/visual/visual-tools.d.ts +10 -1
  188. package/dist/features/visual/visual-tools.js +62 -17
  189. package/dist/hooks/client-directory.d.ts +18 -0
  190. package/dist/hooks/client-directory.js +57 -0
  191. package/dist/hooks/coding-agents.d.ts +34 -0
  192. package/dist/hooks/coding-agents.js +117 -0
  193. package/dist/hooks/driven-by.d.ts +23 -0
  194. package/dist/hooks/driven-by.js +56 -0
  195. package/dist/hooks/hook-bus.d.ts +4 -0
  196. package/dist/hooks/hook-bus.js +18 -0
  197. package/dist/hooks/hook-commands.js +15 -4
  198. package/dist/hooks/tool-log.d.ts +9 -0
  199. package/dist/hooks/tool-log.js +29 -0
  200. package/dist/index.d.ts +2 -0
  201. package/dist/index.js +80 -243
  202. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  203. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  204. package/dist/judgement/capsule/causal-summary.js +33 -0
  205. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  206. package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
  207. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  208. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  209. package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
  210. package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
  211. package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
  212. package/dist/judgement/runs/artifact/run-store.js +195 -3
  213. package/dist/judgement/runs/context-tools.js +59 -1
  214. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  215. package/dist/judgement/runs/default-run-id.js +16 -0
  216. package/dist/judgement/runs/drive-run.d.ts +71 -1
  217. package/dist/judgement/runs/drive-run.js +317 -5
  218. package/dist/judgement/runs/repair-prompt.js +1 -1
  219. package/dist/judgement/runs/resume.d.ts +44 -0
  220. package/dist/judgement/runs/resume.js +137 -0
  221. package/dist/judgement/runs/reticle-runner.js +13 -3
  222. package/dist/judgement/runs/runner-port.d.ts +5 -1
  223. package/dist/judgement/runs/runner-port.js +8 -2
  224. package/dist/judgement/runs/verification-sync.d.ts +5 -2
  225. package/dist/judgement/runs/verification-sync.js +40 -18
  226. package/dist/language/flows/change/gate.d.ts +10 -0
  227. package/dist/language/flows/change/gate.js +22 -0
  228. package/dist/language/flows/decision.js +36 -1
  229. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  230. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  231. package/dist/language/flows/flow-anchor.d.ts +61 -10
  232. package/dist/language/flows/flow-anchor.js +98 -6
  233. package/dist/language/flows/flow-cross-step.d.ts +15 -0
  234. package/dist/language/flows/flow-cross-step.js +21 -0
  235. package/dist/language/flows/flow-intent.d.ts +1 -0
  236. package/dist/language/flows/flow-journey.d.ts +6 -0
  237. package/dist/language/flows/flow-journey.js +20 -0
  238. package/dist/language/flows/flow-learning.d.ts +4 -0
  239. package/dist/language/flows/flow-learning.js +45 -14
  240. package/dist/language/flows/flow-mutate-tools.js +5 -3
  241. package/dist/language/flows/flow-replay-run.d.ts +23 -9
  242. package/dist/language/flows/flow-replay-run.js +115 -110
  243. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  244. package/dist/language/flows/flow-replay.d.ts +40 -1
  245. package/dist/language/flows/flow-replay.js +110 -22
  246. package/dist/language/flows/flow-result.d.ts +22 -1
  247. package/dist/language/flows/flow-result.js +47 -2
  248. package/dist/language/flows/flow-scope.js +5 -1
  249. package/dist/language/flows/flow-step-runners.d.ts +22 -2
  250. package/dist/language/flows/flow-step-runners.js +247 -47
  251. package/dist/language/flows/flow-store-for-session.d.ts +2 -2
  252. package/dist/language/flows/flow-store-for-session.js +7 -3
  253. package/dist/language/flows/flow-tools.d.ts +10 -0
  254. package/dist/language/flows/flow-tools.js +112 -89
  255. package/dist/language/flows/flows.d.ts +16 -1
  256. package/dist/language/flows/flows.js +74 -12
  257. package/dist/language/flows/heal-run.js +6 -4
  258. package/dist/language/flows/narrow-write.d.ts +7 -0
  259. package/dist/language/flows/narrow-write.js +36 -1
  260. package/dist/language/flows/recording/flake.d.ts +2 -2
  261. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  262. package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
  263. package/dist/language/flows/recording/tape/recordings.js +95 -13
  264. package/dist/language/flows/replay-from-hud.d.ts +20 -0
  265. package/dist/language/flows/replay-from-hud.js +51 -0
  266. package/dist/language/flows/replay.d.ts +9 -5
  267. package/dist/language/flows/replay.js +56 -15
  268. package/dist/language/flows/single-replay.d.ts +7 -0
  269. package/dist/language/flows/single-replay.js +26 -0
  270. package/dist/language/flows/suite/suite-flakes.js +2 -0
  271. package/dist/language/flows/suite-selection.d.ts +2 -15
  272. package/dist/language/flows/suite-selection.js +4 -3
  273. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  274. package/dist/language/flows/verify-change-tools.js +202 -191
  275. package/dist/launch-chromium.d.ts +27 -5
  276. package/dist/launch-chromium.js +38 -8
  277. package/dist/memory/cloud/cloud-config.d.ts +22 -1
  278. package/dist/memory/cloud/cloud-config.js +34 -5
  279. package/dist/memory/cloud/cloud-sync.d.ts +17 -14
  280. package/dist/memory/cloud/cloud-sync.js +15 -4
  281. package/dist/memory/cloud/harness-config.d.ts +75 -1
  282. package/dist/memory/cloud/harness-config.js +115 -24
  283. package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
  284. package/dist/memory/cloud/hud-notices-source.js +128 -0
  285. package/dist/memory/cloud/memory-scope.d.ts +161 -0
  286. package/dist/memory/cloud/memory-scope.js +227 -0
  287. package/dist/memory/cloud/sync-cycle.d.ts +44 -7
  288. package/dist/memory/cloud/sync-cycle.js +129 -15
  289. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  290. package/dist/memory/cloud/sync-daemon.js +121 -9
  291. package/dist/memory/cloud/sync-disk.d.ts +1 -1
  292. package/dist/memory/cloud/sync-disk.js +31 -10
  293. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  294. package/dist/memory/cloud/sync-screenshots.js +105 -0
  295. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  296. package/dist/memory/cloud/unsynced-roots.js +166 -0
  297. package/dist/memory/impact/account-watch.d.ts +34 -0
  298. package/dist/memory/impact/account-watch.js +59 -0
  299. package/dist/memory/impact/impact-recorder.d.ts +8 -0
  300. package/dist/memory/impact/impact-recorder.js +12 -2
  301. package/dist/memory/impact/impact-store.d.ts +17 -4
  302. package/dist/memory/impact/impact-store.js +169 -63
  303. package/dist/memory/intent/inline-intent.d.ts +1 -0
  304. package/dist/memory/intent/intent-shard-store.js +16 -4
  305. package/dist/memory/intent/intent-shard.d.ts +14 -2
  306. package/dist/memory/intent/intent-store.d.ts +1 -0
  307. package/dist/memory/intent/intent-tools.js +122 -4
  308. package/dist/memory/intent/open-intents.d.ts +6 -0
  309. package/dist/memory/intent/open-intents.js +10 -1
  310. package/dist/memory/intent/settled-words.d.ts +24 -0
  311. package/dist/memory/intent/settled-words.js +130 -0
  312. package/dist/memory/journal/drive-flow.d.ts +16 -0
  313. package/dist/memory/journal/drive-flow.js +34 -2
  314. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  315. package/dist/memory/journal/drive-run-flush.js +20 -5
  316. package/dist/memory/journal/envelope.d.ts +8 -8
  317. package/dist/memory/journal/journal-recorder.js +52 -3
  318. package/dist/memory/journal/on-disk/retention.d.ts +8 -0
  319. package/dist/memory/journal/on-disk/retention.js +32 -2
  320. package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
  321. package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
  322. package/dist/memory/journal/session-end.d.ts +15 -1
  323. package/dist/memory/journal/session-end.js +42 -9
  324. package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
  325. package/dist/memory/project/artifact-root-resolver.js +125 -16
  326. package/dist/memory/project/artifact-root.d.ts +46 -8
  327. package/dist/memory/project/artifact-root.js +89 -10
  328. package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
  329. package/dist/memory/project/dir/reticle-dir.js +26 -3
  330. package/dist/memory/project/link-directory.d.ts +15 -0
  331. package/dist/memory/project/link-directory.js +44 -0
  332. package/dist/memory/project/project-tools.js +22 -3
  333. package/dist/memory/project/root-claims.d.ts +6 -0
  334. package/dist/memory/project/root-claims.js +39 -0
  335. package/dist/memory/project/session-root.d.ts +26 -1
  336. package/dist/memory/project/session-root.js +49 -5
  337. package/dist/memory/project/sync-status.d.ts +85 -0
  338. package/dist/memory/project/sync-status.js +224 -0
  339. package/dist/memory/recall/memory-tools.js +47 -2
  340. package/dist/memory/recall/platform-memory.d.ts +34 -0
  341. package/dist/memory/recall/platform-memory.js +139 -0
  342. package/dist/memory/recall/project-memory.d.ts +19 -0
  343. package/dist/memory/recall/project-memory.js +80 -13
  344. package/dist/portal/bridge/bridge.d.ts +9 -3
  345. package/dist/portal/bridge/bridge.js +82 -22
  346. package/dist/portal/bridge/harness-request.d.ts +23 -0
  347. package/dist/portal/bridge/harness-request.js +27 -0
  348. package/dist/portal/bridge/pairing-token.d.ts +9 -0
  349. package/dist/portal/bridge/pairing-token.js +17 -0
  350. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  351. package/dist/portal/bridge/wrong-path.js +35 -0
  352. package/dist/portal/input/network-mock-tools.js +11 -2
  353. package/dist/portal/input/real-input.d.ts +83 -10
  354. package/dist/portal/input/real-input.js +218 -30
  355. package/dist/portal/input/viewport-tools.js +3 -3
  356. package/dist/portal/pool/browser-pool.d.ts +70 -9
  357. package/dist/portal/pool/browser-pool.js +190 -37
  358. package/dist/portal/pool/context-permissions.d.ts +33 -0
  359. package/dist/portal/pool/context-permissions.js +33 -0
  360. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  361. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  362. package/dist/portal/pool/playwright-launcher.d.ts +35 -0
  363. package/dist/portal/pool/playwright-launcher.js +64 -3
  364. package/dist/portal/pool/pool-contract.d.ts +28 -5
  365. package/dist/portal/session/agent-link.d.ts +8 -0
  366. package/dist/portal/session/agent-link.js +17 -0
  367. package/dist/portal/session/command-payload.d.ts +8 -0
  368. package/dist/portal/session/command-payload.js +24 -0
  369. package/dist/portal/session/daemon-answers.d.ts +3 -3
  370. package/dist/portal/session/daemon-answers.js +4 -2
  371. package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
  372. package/dist/portal/session/dev-server/dev-command.js +87 -12
  373. package/dist/portal/session/facts/departure-note.d.ts +22 -0
  374. package/dist/portal/session/facts/departure-note.js +47 -0
  375. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  376. package/dist/portal/session/facts/observed-state.js +46 -3
  377. package/dist/portal/session/facts/session-replaced.d.ts +5 -0
  378. package/dist/portal/session/facts/session-replaced.js +5 -0
  379. package/dist/portal/session/first-run-wiring.d.ts +42 -0
  380. package/dist/portal/session/first-run-wiring.js +132 -0
  381. package/dist/portal/session/human/live-control.d.ts +9 -2
  382. package/dist/portal/session/human/live-control.js +12 -3
  383. package/dist/portal/session/human/notes-ledger.d.ts +20 -0
  384. package/dist/portal/session/human/notes-ledger.js +55 -0
  385. package/dist/portal/session/human/review-store.d.ts +12 -0
  386. package/dist/portal/session/human/review-store.js +18 -10
  387. package/dist/portal/session/live-control-tools.d.ts +0 -13
  388. package/dist/portal/session/live-control-tools.js +107 -13
  389. package/dist/portal/session/narration-args.d.ts +5 -0
  390. package/dist/portal/session/narration-args.js +17 -0
  391. package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
  392. package/dist/portal/session/no-session-diagnosis.js +46 -9
  393. package/dist/portal/session/no-session-next-action.d.ts +31 -0
  394. package/dist/portal/session/no-session-next-action.js +159 -60
  395. package/dist/portal/session/no-session-watch.d.ts +14 -1
  396. package/dist/portal/session/no-session-watch.js +227 -17
  397. package/dist/portal/session/presence/session-lease.js +1 -1
  398. package/dist/portal/session/presence/session-mirror.js +3 -0
  399. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  400. package/dist/portal/session/recorded-gaps.js +251 -0
  401. package/dist/portal/session/serving-directory.d.ts +27 -0
  402. package/dist/portal/session/serving-directory.js +45 -0
  403. package/dist/portal/session/session-health.d.ts +18 -0
  404. package/dist/portal/session/session-health.js +9 -1
  405. package/dist/portal/session/session-info.d.ts +8 -1
  406. package/dist/portal/session/session-info.js +8 -1
  407. package/dist/portal/session/session-manager.d.ts +39 -0
  408. package/dist/portal/session/session-manager.js +98 -11
  409. package/dist/portal/session/session-reaper.js +4 -1
  410. package/dist/portal/session/session-successor.d.ts +13 -0
  411. package/dist/portal/session/session-successor.js +1 -1
  412. package/dist/portal/session/session-tools.js +26 -3
  413. package/dist/portal/session/session.d.ts +22 -30
  414. package/dist/portal/session/session.js +81 -79
  415. package/dist/portal/session/timing/command-timeout.js +25 -1
  416. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  417. package/dist/portal/session/timing/wall-clock.js +1 -1
  418. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  419. package/dist/portal/session/zero-install-first-call.js +88 -0
  420. package/dist/start-options.d.ts +12 -0
  421. package/dist/start-wiring.d.ts +63 -0
  422. package/dist/start-wiring.js +169 -0
  423. package/dist/status-payload.d.ts +23 -1
  424. package/dist/status-payload.js +36 -1
  425. package/dist/surface/http-server.js +18 -2
  426. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  427. package/dist/surface/mcp/attach-memory.js +12 -1
  428. package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
  429. package/dist/surface/mcp/mcp-proxy.js +65 -13
  430. package/dist/surface/mcp/mcp.d.ts +34 -6
  431. package/dist/surface/mcp/mcp.js +61 -17
  432. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  433. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  434. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  435. package/dist/surface/mcp/server-instructions.d.ts +4 -2
  436. package/dist/surface/mcp/server-instructions.js +32 -14
  437. package/dist/surface/mcp/shared-params.js +2 -2
  438. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  439. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  440. package/dist/surface/tools/account-tool.d.ts +22 -0
  441. package/dist/surface/tools/account-tool.js +157 -0
  442. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  443. package/dist/surface/tools/act/act-danger.js +38 -1
  444. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  445. package/dist/surface/tools/act/act-observation.js +57 -0
  446. package/dist/surface/tools/act/act-preflight.js +25 -2
  447. package/dist/surface/tools/act/act-target.js +8 -3
  448. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
  449. package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
  450. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  451. package/dist/surface/tools/act/resolve-target.js +18 -3
  452. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  453. package/dist/surface/tools/act/screen-request.js +113 -0
  454. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  455. package/dist/surface/tools/act/sequence-grade.js +13 -2
  456. package/dist/surface/tools/act/settle-in-flight.js +25 -3
  457. package/dist/surface/tools/act-sequence-tool.js +138 -29
  458. package/dist/surface/tools/act-tools.d.ts +0 -9
  459. package/dist/surface/tools/act-tools.js +71 -41
  460. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  461. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  462. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  463. package/dist/surface/tools/agent/app-notes.js +48 -0
  464. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  465. package/dist/surface/tools/agent/build-staleness.js +62 -0
  466. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  467. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  468. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  469. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  470. package/dist/surface/tools/agent/notices.d.ts +50 -0
  471. package/dist/surface/tools/agent/notices.js +152 -0
  472. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  473. package/dist/surface/tools/agent/reteach.js +50 -0
  474. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  475. package/dist/surface/tools/args/alias-args.js +10 -0
  476. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  477. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  478. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  479. package/dist/surface/tools/assert/assert-source.js +40 -0
  480. package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
  481. package/dist/surface/tools/assert/assert-verdict.js +42 -17
  482. package/dist/surface/tools/browser-tools.js +51 -2
  483. package/dist/surface/tools/chat-drives.d.ts +101 -0
  484. package/dist/surface/tools/chat-drives.js +409 -0
  485. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  486. package/dist/surface/tools/coverage-tools.js +2 -53
  487. package/dist/surface/tools/dynamic-tools.js +29 -1
  488. package/dist/surface/tools/empty-session-list.d.ts +51 -0
  489. package/dist/surface/tools/empty-session-list.js +120 -0
  490. package/dist/surface/tools/error-recovery.d.ts +14 -0
  491. package/dist/surface/tools/error-recovery.js +105 -8
  492. package/dist/surface/tools/explore-tools.d.ts +31 -1
  493. package/dist/surface/tools/explore-tools.js +438 -66
  494. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  495. package/dist/surface/tools/feedback-tools.js +18 -3
  496. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  497. package/dist/surface/tools/gap-novelty.js +8 -1
  498. package/dist/surface/tools/harness-explore.d.ts +118 -57
  499. package/dist/surface/tools/harness-explore.js +344 -292
  500. package/dist/surface/tools/harness-gate.d.ts +88 -0
  501. package/dist/surface/tools/harness-gate.js +235 -0
  502. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  503. package/dist/surface/tools/harness-hunt.js +215 -0
  504. package/dist/surface/tools/harness-plan.d.ts +17 -0
  505. package/dist/surface/tools/harness-plan.js +38 -0
  506. package/dist/surface/tools/harness-script.d.ts +30 -0
  507. package/dist/surface/tools/harness-script.js +560 -0
  508. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  509. package/dist/surface/tools/harness-tab-guard.js +27 -0
  510. package/dist/surface/tools/harness-toolset.d.ts +22 -1
  511. package/dist/surface/tools/harness-toolset.js +101 -7
  512. package/dist/surface/tools/human-notes.d.ts +16 -0
  513. package/dist/surface/tools/human-notes.js +27 -0
  514. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  515. package/dist/surface/tools/invoke-tool.js +263 -85
  516. package/dist/surface/tools/lease-hint.js +26 -5
  517. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  518. package/dist/surface/tools/lease-permissions.js +73 -0
  519. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  520. package/dist/surface/tools/lease-readiness.js +57 -0
  521. package/dist/surface/tools/lease-seed.d.ts +49 -0
  522. package/dist/surface/tools/lease-seed.js +167 -0
  523. package/dist/surface/tools/lease-tools.d.ts +13 -24
  524. package/dist/surface/tools/lease-tools.js +146 -197
  525. package/dist/surface/tools/live-call-text.js +4 -4
  526. package/dist/surface/tools/merge-tools.js +42 -2
  527. package/dist/surface/tools/merged-name-redirect.js +4 -0
  528. package/dist/surface/tools/next-step.d.ts +29 -0
  529. package/dist/surface/tools/next-step.js +214 -0
  530. package/dist/surface/tools/observe-tools.js +45 -9
  531. package/dist/surface/tools/platform-moment.d.ts +72 -0
  532. package/dist/surface/tools/platform-moment.js +296 -0
  533. package/dist/surface/tools/query-hint-schema.d.ts +7 -0
  534. package/dist/surface/tools/query-hint-schema.js +10 -0
  535. package/dist/surface/tools/read-tools.js +71 -14
  536. package/dist/surface/tools/real-input-attempt.js +96 -13
  537. package/dist/surface/tools/reticle-result.d.ts +120 -0
  538. package/dist/surface/tools/reticle-result.js +364 -0
  539. package/dist/surface/tools/tool-kit.d.ts +83 -3
  540. package/dist/surface/tools/tool-kit.js +77 -7
  541. package/dist/surface/tools/tools.js +43 -59
  542. package/dist/telemetry/account-envelope.d.ts +7 -0
  543. package/dist/telemetry/account-envelope.js +61 -0
  544. package/dist/telemetry/agent-client.d.ts +15 -0
  545. package/dist/telemetry/agent-client.js +57 -0
  546. package/dist/telemetry/app-instrumented.js +9 -2
  547. package/dist/telemetry/argument-shape.d.ts +7 -0
  548. package/dist/telemetry/argument-shape.js +86 -1
  549. package/dist/telemetry/automation-hint.d.ts +2 -3
  550. package/dist/telemetry/automation-hint.js +33 -8
  551. package/dist/telemetry/cli-telemetry.js +7 -2
  552. package/dist/telemetry/daemon-telemetry.js +3 -0
  553. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  554. package/dist/telemetry/error-fingerprint.js +61 -5
  555. package/dist/telemetry/feedback-cli.d.ts +0 -13
  556. package/dist/telemetry/feedback-cli.js +0 -77
  557. package/dist/telemetry/feedback.d.ts +13 -0
  558. package/dist/telemetry/feedback.js +183 -17
  559. package/dist/telemetry/harness-run.d.ts +18 -0
  560. package/dist/telemetry/harness-run.js +80 -0
  561. package/dist/telemetry/hud-events.d.ts +16 -0
  562. package/dist/telemetry/hud-events.js +27 -0
  563. package/dist/telemetry/hud-metrics.d.ts +29 -6
  564. package/dist/telemetry/hud-metrics.js +116 -25
  565. package/dist/telemetry/init-telemetry.js +2 -2
  566. package/dist/telemetry/install-source.d.ts +13 -25
  567. package/dist/telemetry/install-source.js +44 -3
  568. package/dist/telemetry/mcp-connection.d.ts +0 -14
  569. package/dist/telemetry/mcp-connection.js +5 -1
  570. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  571. package/dist/telemetry/onboarding-firsts.js +81 -6
  572. package/dist/telemetry/platform-linked.d.ts +5 -0
  573. package/dist/telemetry/platform-linked.js +32 -0
  574. package/dist/telemetry/project-profile.js +5 -3
  575. package/dist/telemetry/proxy-telemetry.js +4 -1
  576. package/dist/telemetry/session-metrics.d.ts +15 -4
  577. package/dist/telemetry/session-metrics.js +88 -52
  578. package/dist/telemetry/telemetry.d.ts +38 -2
  579. package/dist/telemetry/telemetry.js +144 -34
  580. package/dist/telemetry/verification-of.d.ts +3 -1
  581. package/dist/telemetry/verification-of.js +13 -4
  582. package/dist/wire-journal.d.ts +2 -2
  583. package/dist/wire-journal.js +20 -6
  584. package/docs/README.md +3 -3
  585. package/docs/actions.mdx +6 -3
  586. package/docs/adapters.md +1 -1
  587. package/docs/agent-cheatsheet.md +25 -28
  588. package/docs/architecture.md +5 -5
  589. package/docs/autodrive.md +33 -28
  590. package/docs/benchmarks.md +5 -5
  591. package/docs/best-practices.mdx +27 -9
  592. package/docs/capabilities.mdx +14 -16
  593. package/docs/cli/affected.mdx +1 -1
  594. package/docs/cli/cloud.mdx +54 -75
  595. package/docs/cli/doctor.mdx +14 -3
  596. package/docs/cli/drive.mdx +20 -14
  597. package/docs/cli/feedback.mdx +3 -3
  598. package/docs/cli/gate.mdx +7 -2
  599. package/docs/cli/help.mdx +50 -55
  600. package/docs/cli/init.mdx +43 -28
  601. package/docs/cli/license.mdx +12 -8
  602. package/docs/cli/mcp.mdx +4 -4
  603. package/docs/cli/open.mdx +3 -3
  604. package/docs/cli/report.mdx +4 -2
  605. package/docs/cli/restart.mdx +2 -2
  606. package/docs/cli/rollback.mdx +14 -8
  607. package/docs/cli/serve.mdx +4 -4
  608. package/docs/cli/setup.mdx +23 -0
  609. package/docs/cli/status.mdx +18 -5
  610. package/docs/cli/stop.mdx +67 -8
  611. package/docs/cli/try.mdx +62 -0
  612. package/docs/cli/update.mdx +4 -3
  613. package/docs/cli/verify.mdx +17 -6
  614. package/docs/cli/version.mdx +5 -4
  615. package/docs/cli.mdx +111 -42
  616. package/docs/debugging.md +3 -3
  617. package/docs/deploy-checks.md +1 -1
  618. package/docs/desktop.mdx +9 -3
  619. package/docs/enterprise.md +11 -10
  620. package/docs/environment.mdx +7 -8
  621. package/docs/faq.mdx +3 -3
  622. package/docs/first-drive.md +5 -4
  623. package/docs/flows.md +35 -27
  624. package/docs/for-agents.md +4 -5
  625. package/docs/frameworks.mdx +32 -21
  626. package/docs/getting-started.md +65 -61
  627. package/docs/human-control.md +16 -16
  628. package/docs/index.mdx +15 -42
  629. package/docs/install-agentic.mdx +22 -37
  630. package/docs/install-manual.mdx +23 -13
  631. package/docs/instrumentation.mdx +5 -3
  632. package/docs/integration-patterns.md +7 -7
  633. package/docs/license-activation.mdx +1 -1
  634. package/docs/multi-agent-testing.md +24 -6
  635. package/docs/packages/babel-plugin.mdx +4 -2
  636. package/docs/packages/browser.mdx +16 -10
  637. package/docs/packages/core.mdx +12 -5
  638. package/docs/packages/electron.mdx +3 -2
  639. package/docs/packages/engine.mdx +1 -1
  640. package/docs/packages/eslint-plugin.mdx +18 -12
  641. package/docs/packages/next.mdx +8 -7
  642. package/docs/packages/open-verification.mdx +1 -1
  643. package/docs/packages/server.mdx +5 -5
  644. package/docs/packages/tauri.mdx +9 -9
  645. package/docs/packages/test.mdx +4 -10
  646. package/docs/packages/vite-plugin.mdx +32 -4
  647. package/docs/packages.mdx +11 -15
  648. package/docs/platform-integration.md +6 -5
  649. package/docs/predicates.mdx +40 -24
  650. package/docs/quickstart.mdx +69 -30
  651. package/docs/required-checks.md +8 -7
  652. package/docs/reticle-manual.md +15 -5
  653. package/docs/skill-file.mdx +17 -79
  654. package/docs/skill-setup.md +9 -9
  655. package/docs/skill.md +200 -0
  656. package/docs/system-map.md +7 -7
  657. package/docs/telemetry.md +23 -25
  658. package/docs/testing.md +4 -4
  659. package/docs/token-efficiency.md +12 -12
  660. package/docs/tools/act-and-wait.mdx +9 -2
  661. package/docs/tools/act-sequence.mdx +6 -7
  662. package/docs/tools/act.mdx +2 -2
  663. package/docs/tools/assert.mdx +18 -17
  664. package/docs/tools/console.mdx +9 -9
  665. package/docs/tools/inspect.mdx +16 -7
  666. package/docs/tools/look.mdx +24 -0
  667. package/docs/tools/navigate.mdx +5 -3
  668. package/docs/tools/network.mdx +2 -2
  669. package/docs/tools/observe.mdx +6 -6
  670. package/docs/tools/overview.mdx +34 -33
  671. package/docs/tools/query.mdx +5 -5
  672. package/docs/tools/session-and-feedback.mdx +22 -13
  673. package/docs/tools/sessions.mdx +8 -8
  674. package/docs/tools/snapshot.mdx +6 -5
  675. package/docs/tools/state.mdx +9 -9
  676. package/docs/tools/tools-and-run.mdx +26 -24
  677. package/docs/tools/verify.mdx +28 -0
  678. package/docs/tools/wait-for.mdx +8 -4
  679. package/docs/troubleshooting.mdx +21 -6
  680. package/docs/usage.md +55 -46
  681. package/docs/use-cases.mdx +3 -3
  682. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  683. package/docs/vs-playwright-mcp.mdx +3 -1
  684. package/docs/what-is-recorded.md +17 -5
  685. package/docs/what-is-reticle.mdx +5 -3
  686. package/docs/why-reticle.mdx +1 -1
  687. package/package.json +9 -12
  688. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  689. package/dist/command/cli/demo/demo-page.js +0 -241
  690. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  691. package/dist/command/cli/demo/demo-run.js +0 -138
  692. package/dist/features/harness/driver.d.ts +0 -50
  693. package/dist/features/harness/driver.js +0 -236
  694. package/dist/features/harness/jev-driver.d.ts +0 -188
  695. package/dist/features/harness/jev-driver.js +0 -678
  696. package/dist/features/harness/openai-driver.d.ts +0 -58
  697. package/dist/features/harness/openai-driver.js +0 -206
  698. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  699. package/dist/judgement/hunt/hunt-report.js +0 -84
  700. package/dist/language/flows/buddy-status.d.ts +0 -25
  701. package/dist/language/flows/buddy-status.js +0 -32
  702. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  703. package/dist/language/flows/change/watch-batcher.js +0 -19
  704. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  705. package/dist/memory/cloud/harness-offer.js +0 -145
  706. package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
  707. package/dist/memory/project/dir/fill-value-store.js +0 -88
  708. package/dist/surface/tools/feature-capture.d.ts +0 -151
  709. package/dist/surface/tools/feature-capture.js +0 -235
  710. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  711. package/dist/surface/tools/tool-hit-rate.js +0 -90
  712. package/dist/telemetry/harness-drive.d.ts +0 -4
  713. package/dist/telemetry/harness-drive.js +0 -35
  714. package/dist/telemetry/identify.d.ts +0 -22
  715. package/dist/telemetry/identify.js +0 -73
  716. package/docs/cli/capsules.mdx +0 -70
  717. package/docs/cli/hunt.mdx +0 -73
  718. package/docs/cli/identify.mdx +0 -76
  719. package/docs/cli/kill.mdx +0 -91
  720. package/docs/cli/watch.mdx +0 -62
  721. package/docs/local-registry.md +0 -143
@@ -1,4 +1,5 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { randomUUID } from 'node:crypto';
2
3
  import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
3
4
  import { z } from 'zod';
4
5
  import { isPredicateParam } from '@reticlehq/engine/question/predicate/predicate-eval.js';
@@ -8,7 +9,7 @@ import { filterTools, describeToolSurface, TOOL_SURFACE, } from '../tools/tool-s
8
9
  import { ReticleTool } from '@reticlehq/core';
9
10
  import { SHARED_PARAM_SHORT } from './shared-params.js';
10
11
  import { buildDynamicTools } from '../tools/dynamic-tools.js';
11
- import { runTool, SESSION_BOUND_TOOLS } from '../tools/invoke-tool.js';
12
+ import { runTool } from '../tools/invoke-tool.js';
12
13
  import { sessionEnvelopeShape, newSnapshotCache } from '../tools/tool-kit.js';
13
14
  import { buildErrorPayload } from '../tools/error-recovery.js';
14
15
  import { takeVersionSkewOnto } from '../../command/version/version-nudge.js';
@@ -37,15 +38,20 @@ import { SERVER_VERSION } from '../../command/version/identity/server-version.js
37
38
  import { setMcpClientNameHook } from '../../telemetry/feedback-context.js';
38
39
  import { getSessionMetrics } from '../../telemetry/session-metrics.js';
39
40
  import { reportMcpConnected } from '../../telemetry/mcp-connection.js';
41
+ import { noteAgentAttached, noteAgentDetached, runAsAgent } from '../../hooks/coding-agents.js';
40
42
  import { parsePredicate } from '@reticlehq/engine/question/predicate/predicate-parse.js';
41
43
  /**
42
- * Merge the runtime-spliced envelope (health/lease/age/control) into a session-bound tool's declared
43
- * outputSchema so structuredContent validation keeps those fields instead of dropping them. The tool's
44
- * own keys win over the permissive envelope defaults (e.g. ACT keeps its typed `session` shape).
45
- * Non-session-bound tools (and tools with no outputSchema) are returned unchanged.
44
+ * Merge the runtime-spliced envelope into a tool's declared outputSchema so structuredContent
45
+ * validation keeps those fields instead of rejecting the call. The tool's own keys win over the
46
+ * permissive envelope defaults (e.g. ACT keeps its typed `session` shape).
47
+ *
48
+ * EVERY tool with an output schema, not only the session-bound ones: `runTool` adds `next`,
49
+ * `update_available`, `version_skew` and the feedback keys to any tool's result, and a session-exempt
50
+ * tool with a strict schema (`reticle_context`) failed the whole call on a validating client the
51
+ * first time one of them rode on it.
46
52
  */
47
- export function withSessionEnvelope(name, outputSchema) {
48
- if (outputSchema === undefined || !SESSION_BOUND_TOOLS.has(name))
53
+ export function withSessionEnvelope(_name, outputSchema) {
54
+ if (outputSchema === undefined)
49
55
  return outputSchema;
50
56
  return { ...sessionEnvelopeShape, ...outputSchema };
51
57
  }
@@ -134,7 +140,7 @@ const COMPACT_PREDICATE_DESCRIPTION = `${PREDICATE_KINDS}${PREDICATE_FIELD_GRAMM
134
140
  * schema cost; the first clause keeps each param's purpose and any enum hints. Params without a
135
141
  * description pass through unchanged. Predicate params are replaced wholesale — see above.
136
142
  */
137
- function leanZodShape(shape, predicateAnchor) {
143
+ function leanZodShape(shape, advertised, predicateAnchor) {
138
144
  const out = {};
139
145
  // The navigation hint is said ONCE per turn, so it is anchored to one parameter — not one tool.
140
146
  // A tool can carry two predicate parameters (a canonical name plus a neighbouring tool's alias),
@@ -160,8 +166,13 @@ function leanZodShape(shape, predicateAnchor) {
160
166
  out[key] = schema.describe(shared);
161
167
  continue;
162
168
  }
169
+ // Through the same rewrite as tool descriptions: a parameter that says "a ref from
170
+ // reticle_snapshot" names a tool this surface does not have.
163
171
  const desc = schema.description;
164
- out[key] = 'string' === typeof desc ? schema.describe(firstSentence(desc)) : schema;
172
+ out[key] =
173
+ 'string' === typeof desc
174
+ ? schema.describe(liveCallText(firstSentence(desc), advertised))
175
+ : schema;
165
176
  }
166
177
  return out;
167
178
  }
@@ -182,6 +193,27 @@ export function encodeResult(result, encoding) {
182
193
  }
183
194
  return encoding === PRETTY_VALUE ? JSON.stringify(result, null, 2) : JSON.stringify(result);
184
195
  }
196
+ const PROGRESS_NOTIFICATION = 'notifications/progress';
197
+ /**
198
+ * The request's cancellation and, when the client sent a progress token, a progress reporter. A
199
+ * long call (a Harness drive's wait) reports each step, so a client that resets its timeout on
200
+ * progress keeps waiting instead of abandoning a call that is working.
201
+ */
202
+ export function toolCallOf(extra) {
203
+ const token = extra?._meta?.progressToken;
204
+ const send = extra?.sendNotification;
205
+ return {
206
+ ...(extra?.signal === undefined ? {} : { signal: extra.signal }),
207
+ ...(token === undefined || send === undefined
208
+ ? {}
209
+ : {
210
+ progress: (progress, message) => void send({
211
+ method: PROGRESS_NOTIFICATION,
212
+ params: { progressToken: token, progress, message },
213
+ }).catch(() => undefined),
214
+ }),
215
+ };
216
+ }
185
217
  /**
186
218
  * The tools a profile advertises directly.
187
219
  *
@@ -292,9 +324,13 @@ export function advertisedConfig(tool, advertised, profile) {
292
324
  // Against the advertised set, for the same reason results are: `reticle_navigate`'s own
293
325
  // description told the reader to confirm a reload with `reticle_sessions`, on the surface
294
326
  // where that name is gone. A description is advice like any other.
295
- liveCallText(terse ? firstSentence(tool.description) : tool.description, new Set(advertised.map((each) => each.name))), tool.example),
327
+ // Not on the meta-tools: they exist to name what is reachable only through `reticle_run`,
328
+ // and rewriting those names to advertised ones turned `reticle_tools` into nonsense.
329
+ isMetaTool
330
+ ? tool.description
331
+ : liveCallText(terse ? firstSentence(tool.description) : tool.description, new Set(advertised.map((each) => each.name))), tool.example),
296
332
  inputSchema: terse
297
- ? leanZodShape(tool.inputSchema, tool.name === anchor ? undefined : anchor)
333
+ ? leanZodShape(tool.inputSchema, new Set(advertised.map((each) => each.name)), tool.name === anchor ? undefined : anchor)
298
334
  : tool.inputSchema,
299
335
  ...(outputSchema !== undefined ? { outputSchema } : {}),
300
336
  };
@@ -416,8 +452,10 @@ function installUnadvertisedToolHelp(server, advertised, known) {
416
452
  return original(asCallOf(request, moved.tool, moved.action), extra);
417
453
  }
418
454
  const help = name === undefined ? undefined : unadvertisedToolHelp(name, advertised, known);
455
+ // A failed RESULT, not a JSON-RPC error: a client that reads only `result` rendered the error
456
+ // as an empty success, and the agent believed `reticle_flow_save` had saved its flow.
419
457
  if (help !== undefined)
420
- throw new McpError(ErrorCode.InvalidParams, help);
458
+ return { content: [{ type: 'text', text: help }], isError: true };
421
459
  return original(request, extra);
422
460
  });
423
461
  }
@@ -491,7 +529,7 @@ tools = tableForSurface(profile)) {
491
529
  * runs once per client connection, which makes it the right owner; a caller that supplies its own
492
530
  * store keeps it.
493
531
  */
494
- const deps = { snapshots: newSnapshotCache(), ...rawDeps };
532
+ const deps = { snapshots: newSnapshotCache(), attachId: randomUUID(), ...rawDeps };
495
533
  const encoding = (process.env[ENCODING_ENV] ?? '').toLowerCase();
496
534
  // Which surface this daemon advertises. The 18-tool default and the 48-tool full surface are
497
535
  // different products from inside an agent's context, so outcomes are only comparable when the
@@ -499,7 +537,7 @@ tools = tableForSurface(profile)) {
499
537
  getSessionMetrics().recordSurface(profile);
500
538
  const server = new McpServer(SERVER_INFO, {
501
539
  instructions: buildServerInstructions({
502
- previouslyConnected,
540
+ ...('boolean' === typeof previouslyConnected ? { previouslyConnected } : previouslyConnected),
503
541
  // The surface this server is about to serve. Without it the briefing describes the tools this
504
542
  // package SHIPS rather than the ones this daemon advertises, and on any trimmed surface that
505
543
  // is a briefing for a different product — measured cost: an agent that stopped driving.
@@ -523,12 +561,15 @@ tools = tableForSurface(profile)) {
523
561
  if (info?.name === undefined)
524
562
  return;
525
563
  getSessionMetrics().recordClient(info.name, info.version);
564
+ // So the HUD can say which agent is connected, and credit a note to the one that read it.
565
+ noteAgentAttached(deps.attachId, info.name);
526
566
  // The one signal that separates "Reticle is running" from "somebody is USING it", reported from
527
567
  // the first moment it can carry WHO. It used to fire from the SSE `connect()` resolution, which
528
568
  // happens before the handshake — so every connect row was anonymous, and the field meant to say
529
569
  // which agent client converts best was empty on every event ever sent.
530
- reportMcpConnected(info.name);
570
+ void runAsAgent(deps.attachId, () => Promise.resolve(reportMcpConnected(info.name)));
531
571
  };
572
+ server.server.onclose = () => noteAgentDetached(deps.attachId);
532
573
  // Which agent is on the other end, for a feedback report. Registered as a lazy hook rather than
533
574
  // read here: the handshake has not happened yet at construction time, and a report filed twenty
534
575
  // tool calls later is exactly when we want the answer.
@@ -610,9 +651,12 @@ tools = tableForSurface(profile)) {
610
651
  // clients. This removes the single largest remaining slice of the per-request tax (~36% of the
611
652
  // hybrid payload) with no loss the agent can observe.
612
653
  const config = advertisedConfig(tool, advertised, profile);
613
- registerTool(tool.name, config, async (args) => {
654
+ registerTool(tool.name, config, async (args, extra) => {
614
655
  try {
615
- const result = await runTool(tool, deps, args);
656
+ // Inside the caller's connection, so the telemetry this call emits after its handler (the
657
+ // verdict, a defect, a refusal) is credited to the agent that made it, not to whichever
658
+ // agent is attached.
659
+ const result = await runAsAgent(deps.attachId, () => runTool(tool, deps, args, toolCallOf(extra)));
616
660
  // A tool this codebase did not write may not hand the agent a verdict.
617
661
  //
618
662
  // Only reached for a tool absent from the first-party table, so the shipped surface pays a
@@ -0,0 +1,10 @@
1
+ /** A `tools/call` of reticle_verify explore, directly or through the reticle_run hatch. */
2
+ export declare function isHarnessDriveCall(msg: {
3
+ method?: unknown;
4
+ params?: unknown;
5
+ }): boolean;
6
+ /**
7
+ * A drive lives in the daemon, not in the call: a lost connection does not end it, and retrying the
8
+ * call as if it had not run pays for a second drive.
9
+ */
10
+ export declare const MSG_DRIVE_MAY_BE_RUNNING: string;
@@ -0,0 +1,27 @@
1
+ /** Which proxied calls are Harness drives, and what to tell an agent whose drive call was lost. */
2
+ import { ReticleTool } from '@reticlehq/core';
3
+ const TOOLS_CALL = 'tools/call';
4
+ const EXPLORE_ACTION = 'explore';
5
+ /** A `tools/call` of reticle_verify explore, directly or through the reticle_run hatch. */
6
+ export function isHarnessDriveCall(msg) {
7
+ if (TOOLS_CALL !== msg.method)
8
+ return false;
9
+ const params = (msg.params ?? {});
10
+ const args = (params.arguments ?? {});
11
+ if (ReticleTool.VERIFY_EXPLORE === params.name)
12
+ return true;
13
+ if (ReticleTool.VERIFY === params.name)
14
+ return EXPLORE_ACTION === args['action'];
15
+ if (ReticleTool.RUN !== params.name)
16
+ return false;
17
+ const inner = (args['args'] ?? {});
18
+ return (ReticleTool.VERIFY_EXPLORE === args['tool'] ||
19
+ (ReticleTool.VERIFY === args['tool'] && EXPLORE_ACTION === inner['action']));
20
+ }
21
+ /**
22
+ * A drive lives in the daemon, not in the call: a lost connection does not end it, and retrying the
23
+ * call as if it had not run pays for a second drive.
24
+ */
25
+ export const MSG_DRIVE_MAY_BE_RUNNING = `The Harness drive this call started or polled may still be running in the daemon. Once ` +
26
+ `Reticle reconnects, call ${ReticleTool.VERIFY} {action:"explore"} with no runId to get the ` +
27
+ `running drive back (it will not start a second), then poll it by runId.`;
@@ -7,6 +7,7 @@
7
7
  * saying honestly that it never arrived — and the file it came from is about the SSE stream.
8
8
  */
9
9
  import * as http from 'node:http';
10
+ import { MCP_CLIENT_DIRECTORY_HEADER } from '@reticlehq/core';
10
11
  import { log } from '../../../log.js';
11
12
  import { getSessionMetrics } from '../../../telemetry/session-metrics.js';
12
13
  import { reconnectDelayMs } from './proxy-backoff.js';
@@ -47,6 +48,10 @@ export function postToSession(url, body, request = (options, callback) => http.r
47
48
  headers: {
48
49
  'Content-Type': 'application/json',
49
50
  'Content-Length': bodyBuf.byteLength,
51
+ // The project this proxy was started in. The daemon serves every project; without this
52
+ // it can only see the directory it itself started in. Percent-encoded: a cwd such as
53
+ // `/work/项目` is not a legal header value, and Node throws before the request is sent.
54
+ [MCP_CLIENT_DIRECTORY_HEADER]: encodeURIComponent(process.cwd()),
50
55
  },
51
56
  };
52
57
  // A keep-alive socket carries historical bytes; retry safety depends on this request's delta.
@@ -1,4 +1,6 @@
1
- interface InstructionState {
1
+ /** The nudge set for the AGENT's directory: a shared daemon briefs from where IT started. */
2
+ export declare function localizeInstructions(instructions: string, appHere: boolean): string;
3
+ export interface InstructionState {
2
4
  /**
3
5
  * The names this surface actually advertises. Every tool the prose mentions is resolved from it.
4
6
  *
@@ -15,6 +17,7 @@ interface InstructionState {
15
17
  * is whether this install has EVER worked, not whether it is working this second.
16
18
  */
17
19
  previouslyConnected: boolean;
20
+ appHere?: boolean;
18
21
  }
19
22
  /** The instructions this daemon should advertise, given what it knows about the project. */
20
23
  /**
@@ -23,4 +26,3 @@ interface InstructionState {
23
26
  * repeated across every parameter description. See shared-params.ts.
24
27
  */
25
28
  export declare function buildServerInstructions(state: InstructionState): string;
26
- export {};
@@ -1,4 +1,4 @@
1
- import { ReticleTool } from '@reticlehq/core';
1
+ import { ReticleTool, WRITING_RULE_SHORT } from '@reticlehq/core';
2
2
  import { SHARED_PARAM_GUIDANCE } from './shared-params.js';
3
3
  import { defaultAdvertisedNames } from '../tools/tool-surface.js';
4
4
  import { surfaceVocabulary, listOf } from './surface-vocabulary.js';
@@ -44,9 +44,9 @@ import { surfaceVocabulary, listOf } from './surface-vocabulary.js';
44
44
  */
45
45
  const verdictDiscipline = (v) => `Reticle verifies a running web app from the inside: go (${v.navigate}), look (${listOf(v.look, v.find)}), act and prove in one hop (${v.actAndWait}), observe (${listOf(v.observe, v.state, v.network, v.console)}), assert (${v.assert}). Verify a user-facing change against the real app before you call it done — \`npx @reticlehq/server gate --since <ref>\` fails unless a passing artifact covers every flow your edits affect — and never weaken a check to make it pass.
46
46
 
47
- Only ${v.act.length > 0 ? `${v.actAndWait}, ${v.assert} and ${v.act}{steps}` : `${v.actAndWait} and ${v.assert}`} produce a verdict. Everything else moves or reads the app and proves nothing, so a drive that ends without one of those two has no result however many tools it used. Prefer ${v.actAndWait}({ ref, action, until }) — it names the expected consequence BEFORE the action, which is the difference between a check and a rationalisation. Only verified:"yes" is a pass — "unknown" means Reticle could not tell what happened, "no-fault" means nothing was declared to prove. Report either as not proved.
47
+ Only ${v.act.length > 0 ? `${v.actAndWait}, ${v.assert} and ${v.act}{steps}` : `${v.actAndWait} and ${v.assert}`} produce a verdict. Everything else proves nothing; a drive without one has no result. Prefer ${v.actAndWait}({ ref, action, until }) — it names the expected consequence BEFORE the action, which is the difference between a check and a rationalisation. Only verified:"yes" is a pass; "unknown" and "no-fault" (nothing declared) are not proved, never failed. When a verdict catches what reading the code missed, say Reticle found it. Do a result's \`next\`.
48
48
 
49
- Done is the journey's END proved, not its first step: drive each step your change touches and give the last an \`until\` naming the end state (\`durable: true\` if it must persist). A "yes" on it over a clean capture IS the answer — stop.
49
+ Done is the journey's END proved, not its first step: drive each step your change touches and give the last an \`until\` naming the end state (\`durable: true\` if it must persist). A "yes" on it over a clean capture IS the answer — stop.${v.act.length > 0 ? ` Several steps? ONE ${v.act}{ steps: [{ target, action, expect }] } drives them all and stops at the first expect that fails; the last expect is the end state.` : ''}
50
50
 
51
51
  DIAGNOSING a bug? Read the source first — Reticle proves what the app DOES, not why. Drive to CONFIRM a fix, not to find one.`;
52
52
  /**
@@ -77,8 +77,15 @@ const replayFirst = (v) => {
77
77
  if (0 === v.replayChange.length)
78
78
  return '';
79
79
  const ask = v.affected.length > 0 ? `${v.affected} names the saved flows covering your edits; ` : '';
80
- return `Changed code? Replay before you drive. ${ask}${v.replayChange} replays them for one verified + because — hundreds of tokens where driving the same journey costs tens of thousands. "yes": proved, stop. "no": names the step that broke. "unknown": NO saved flow covers it, so nothing was proved — drive it, and never report it as passing. What you drive by hand is saved as a flow automatically.`;
80
+ return `Changed code? Replay before you drive. ${ask}${v.replayChange} replays them for one verified + because — far cheaper than driving it again. "yes": proved, stop. "no": names the step that broke. "unknown": NO saved flow covers it, so nothing was proved — drive it, and never report it as passing. What you drive by hand is saved as a flow automatically.${driveOnce(v)}`;
81
81
  };
82
+ /**
83
+ * A drive outlives a client's timeout, so its call answers with a run id instead of waiting for the
84
+ * end; an agent that retried instead of polling paid for a second drive.
85
+ */
86
+ const driveOnce = (v) => 0 === v.explore.length
87
+ ? ''
88
+ : ` Drivers: you, or the Harness (${v.explore}; opt-in at 80% instrumentation): poll its runId; never start two.`;
82
89
  /**
83
90
  * The first move, for a project no app has ever connected to.
84
91
  *
@@ -90,9 +97,22 @@ const replayFirst = (v) => {
90
97
  * common way this step half-succeeds. Telling every agent to restart sent them to kill the server
91
98
  * `init` had just started.
92
99
  */
93
- const firstMoveFor = (v) => `FIRST: no app has ever connected to Reticle in this project, so nothing here can be verified yet. Having these tools is not the same as being set up — the tools reach a daemon, and the daemon has nothing to look at until the app itself is instrumented.
100
+ // The lead is a snapshot, not a present fact: these instructions are sent ONCE, at the handshake, and
101
+ // the app can connect a minute later. Stated as fact, it kept agents running setup while the session
102
+ // list showed the app connected (#1362).
103
+ const firstMoveFor = (v, appHere) => `FIRST: when this session started, no app had connected to Reticle in this project. Having these tools is not the same as being set up — the tools reach a daemon that has nothing to look at until the app is instrumented.
94
104
 
95
- Fix that before anything else: run \`npx @reticlehq/server init\` in the project. It starts the dev server and opens the app itself; only if a dev server was ALREADY running without Reticle, restart it and reload the tab. Confirm with ${v.sessions} — a session listed there is the proof, and until one appears no other tool can tell you anything about this app.`;
105
+ Fix that first: call ${v.sessions}. Its first call wires the app (\`init\`, dev server, browser) and \`wired\` lists the files it changed; tell the user. If it answers \`run_init\`, run that command in the app's directory. A session on this project's app listed there is the proof; until one appears no other tool can tell you anything about this app.${appHere ? TELL_THE_USER : ''}`;
106
+ const UNWIRED_LEAD_END = 'can tell you anything about this app.';
107
+ // An agent never asked to verify anything never reads "fix that first"; this makes it raise wiring.
108
+ const TELL_THE_USER = ' If none is listed, this directory holds a web app that is not wired: in your first reply, even if their request is unrelated, tell the user in one line and offer to wire it (the first session call does it). Do it only if they agree; if they decline, do not raise it again.';
109
+ /** The nudge set for the AGENT's directory: a shared daemon briefs from where IT started. */
110
+ export function localizeInstructions(instructions, appHere) {
111
+ const without = instructions.replace(TELL_THE_USER, '');
112
+ if (!appHere || !without.includes(UNWIRED_LEAD_END))
113
+ return without;
114
+ return without.replace(UNWIRED_LEAD_END, `${UNWIRED_LEAD_END}${TELL_THE_USER}`);
115
+ }
96
116
  /**
97
117
  * When to reach for the tools that are advertised but never explained, and how to reach the two
98
118
  * that are explained but not advertised. Both halves of the same defect.
@@ -120,16 +140,14 @@ const reachFor = (v) => {
120
140
  // surface-vocabulary.ts. Where there is no cold tail, there is nothing to say about reaching it.
121
141
  if (v.coldTail.length > 0) {
122
142
  lines.push(`${v.coldTail} Two to know early: ${ReticleTool.RUN}({ tool: "${ReticleTool.CONTEXT}", args: {} }) returns what this run already established, after a compaction or handover, and ${ReticleTool.RUN}({ tool: "${ReticleTool.INTENT}", args: { action: "declare", ... } }) declares what a change was MEANT to do, so the verdict has something to check against other than itself.`);
143
+ // Measured: in 8 real agent runs asked to test an app, none read what Reticle already held
144
+ // first, and none could tell its user the credits or the Harness state.
145
+ lines.push(`Before testing, read what Reticle knows: ${ReticleTool.RUN}({ tool: "${ReticleTool.MEMORY}", args: {} })${v.yield.length > 0 ? ` and ${ReticleTool.SESSION} {action:"account"} (plan, credits, Harness)` : ''}.`);
123
146
  }
124
147
  return lines.join('\n\n');
125
148
  };
126
149
  /** The feedback ask. Constant: an agent that cannot get set up is the report we most need. */
127
- const feedbackAsk = (v) => `Feedback is first-class here, not a courtesy. Reticle is built FOR agents, so your experience is the only signal that decides what gets built or fixed — and it disappears when your context does. Send it with \`${v.feedback}\` the moment you notice, then carry on with your task:
128
- - Reticle broke, lied, or could not see something you needed (\`bug\` / \`gap\` / \`ambiguity\`).
129
- - You wished it could do something, or something works but costs too many calls (\`feature_request\` / \`improvement\`).
130
- - The install, the wiring, or the setup itself gave you trouble — including anything you had to work around by hand.
131
-
132
- Nothing is too minor, and a report costs one call. If the tools are unreachable (setup unfinished, daemon down), file the same report from the shell instead: \`reticle feedback --agent --kind <one of those kinds> "what happened"\`. Report defects in RETICLE — a bug you find in the app under test is Reticle working, and belongs in your answer to the user.`;
150
+ const feedbackAsk = (v) => `Feedback is first-class here: once per session, when Reticle got in your way, send \`${v.feedback}\` and carry on — it broke, lied or missed something (\`bug\` / \`gap\` / \`ambiguity\`), cost too many calls or lacked something (\`improvement\` / \`feature_request\`), or the install, the wiring, or the setup gave you trouble. Tools unreachable? \`reticle feedback --agent --kind <kind> "what happened"\`. A bug in the app under test belongs in your answer to the user.`;
133
151
  /** The instructions this daemon should advertise, given what it knows about the project. */
134
152
  /**
135
153
  * Instructions are sent ONCE at initialize; the tool surface is re-sent every turn, and costs an
@@ -146,7 +164,7 @@ export function buildServerInstructions(state) {
146
164
  // passing a surface, so a stale fallback here is what every agent reaching Reticle through
147
165
  // `reticle mcp` reads — naming tools the surface it is being served does not have.
148
166
  const v = surfaceVocabulary(state.advertised ?? defaultAdvertisedNames());
149
- const firstMove = firstMoveFor(v);
167
+ const firstMove = firstMoveFor(v, true === state.appHere);
150
168
  /*
151
169
  * Said in BOTH states, and gated only on whether the surface can reach replay.
152
170
  *
@@ -165,5 +183,5 @@ export function buildServerInstructions(state) {
165
183
  ? `${verdictDiscipline(v)}\n\n${reachFor(v)}\n\n${feedbackAsk(v)}`
166
184
  : `${firstMove}\n\n${verdictDiscipline(v)}\n\n${feedbackAsk(v)}`;
167
185
  const withReplay = replay.length > 0 ? `${base}\n\n${replay}` : base;
168
- return `${withReplay}\n\n${SHARED_PARAM_GUIDANCE}`;
186
+ return `${withReplay}\n\n${SHARED_PARAM_GUIDANCE}\n\n${WRITING_RULE_SHORT}`;
169
187
  }
@@ -22,14 +22,14 @@
22
22
  /** The short form left in the per-turn schema. Must still make sense with no instructions at all. */
23
23
  export const SHARED_PARAM_SHORT = {
24
24
  sessionId: 'Target a specific tab. Omit unless you mean one — see instructions.',
25
- since: 'Cursor from a prior reticle_act/reticle_observe.',
25
+ since: 'Cursor from a prior act/observe, or a git ref.',
26
26
  limit: 'Cap descriptors to the first N.',
27
27
  };
28
28
  /** The full text, sent once at initialize. Everything trimmed above is restated here. */
29
29
  export const SHARED_PARAM_GUIDANCE = 'Arguments that mean the same thing on every tool: `sessionId` — omit unless you mean a specific ' +
30
30
  'tab; Reticle scopes to your project, prefers the active one, and refuses rather than guesses when ' +
31
31
  'ambiguous. `since` — a cursor from a prior act/observe, bounding an observation to what came ' +
32
- 'after it. `limit` — caps returned descriptors, cutting tokens on broad queries.';
32
+ 'after it, or a git ref when verifying a change. `limit` — caps returned descriptors.';
33
33
  /** Is this a parameter whose guidance now lives in the instructions block? */
34
34
  export function isSharedParam(name) {
35
35
  return Object.hasOwn(SHARED_PARAM_SHORT, name);
@@ -41,6 +41,8 @@ export interface SurfaceVocabulary {
41
41
  replayAll: string;
42
42
  /** Rebind a drifted locator, or empty when the surface cannot reach it. */
43
43
  heal: string;
44
+ /** Start or poll a Harness drive, or empty when the surface cannot reach it. */
45
+ explore: string;
44
46
  }
45
47
  /** Drop the empty slots, so a sentence never reads "look (), find ()". */
46
48
  export declare function listOf(...calls: readonly string[]): string;
@@ -52,5 +52,6 @@ export function surfaceVocabulary(advertisedNames) {
52
52
  replayChange: call(ReticleTool.VERIFY_CHANGE, ReticleTool.VERIFY, 'change'),
53
53
  replayAll: call(ReticleTool.FLOW_REPLAY, ReticleTool.VERIFY, 'flows'),
54
54
  heal: advertised.has(ReticleTool.FLOW_HEAL) ? ReticleTool.FLOW_HEAL : '',
55
+ explore: call(ReticleTool.VERIFY_EXPLORE, ReticleTool.VERIFY, 'explore'),
55
56
  };
56
57
  }
@@ -0,0 +1,22 @@
1
+ import type { ToolDef } from './tool-kit.js';
2
+ /** What the agent is told to do next, in plain words: one step, the first one that applies. */
3
+ export declare const ACCOUNT_NEXT: {
4
+ readonly SIGN_IN: "The user is not signed in to Reticle. Ask them to run `reticle connect` in the app folder: it signs them in and links this project. A new account gets 10 free credits.";
5
+ readonly LINK: "This project does not report to the dashboard yet. Ask the user to press \"Link this project\" on the Harness page of the HUD, or to run `reticle connect` in the app folder.";
6
+ readonly UNREACHABLE: "The Reticle platform did not answer, so credits and the Harness are not known now. Local checks still work.";
7
+ readonly NO_CREDITS: (said: string) => string;
8
+ readonly locked: (percent: number, missing: string) => string;
9
+ readonly OFF: "Reticle Harness is off for this project. The user can switch it on in the HUD (the Harness row at the foot of the Agent Log) or on the dashboard.";
10
+ readonly NO_PROVIDER: "The platform has no model provider set, so Reticle Harness cannot run now. Tell the user; it is not on their side.";
11
+ readonly ready: (typical: number | undefined, max: number | undefined) => string;
12
+ };
13
+ export interface AccountInput {
14
+ signedIn: boolean;
15
+ workspace?: string;
16
+ dashboardUrl?: string;
17
+ /** The platform's `/v1/model/config` answer; undefined when unlinked, null when it did not answer. */
18
+ platform: Record<string, unknown> | null | undefined;
19
+ }
20
+ /** The facts and the next step. Pure: the tool's I/O is in `readAccount`. */
21
+ export declare function accountFacts(input: AccountInput): Record<string, unknown>;
22
+ export declare const ACCOUNT_TOOLS: ToolDef[];
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Where the user stands with Reticle, for the coding agent: signed in or not, whether this project
3
+ * reports to the dashboard, the plan and credits left, whether Reticle Harness is on and unlocked,
4
+ * what a Harness run costs, and the one thing to do next.
5
+ *
6
+ * In 16 real Claude Code and Codex runs, no agent could answer "how many credits do I have" or "can
7
+ * the Harness run" from a tool: those facts lived only in the HUD and the dashboard. This reads the
8
+ * same sources they do (the HUD's snapshot for the account, the platform's model config for the
9
+ * plan, credits and gate), so the agent and the HUD cannot disagree.
10
+ */
11
+ import { z } from 'zod';
12
+ import { ReticleTool, asRecord, asString } from '@reticlehq/core';
13
+ import { creditsUsageText } from '@reticlehq/core/hud';
14
+ import { impactSnapshot } from '../../memory/impact/impact-recorder.js';
15
+ import { readDashboardUrl } from '../../memory/project/sync-status.js';
16
+ import { sessionRoot } from '../../memory/project/session-root.js';
17
+ import { platformHeaders } from '../../features/harness/platform/server-driver.js';
18
+ const CONFIG_PATH = '/v1/model/config';
19
+ const CONFIG_TIMEOUT_MS = 3_000;
20
+ const UNLOCK_PERCENT = 80;
21
+ /** What the agent is told to do next, in plain words: one step, the first one that applies. */
22
+ export const ACCOUNT_NEXT = {
23
+ SIGN_IN: 'The user is not signed in to Reticle. Ask them to run `reticle connect` in the app folder: it signs them in and links this project. A new account gets 10 free credits.',
24
+ LINK: 'This project does not report to the dashboard yet. Ask the user to press "Link this project" on the Harness page of the HUD, or to run `reticle connect` in the app folder.',
25
+ UNREACHABLE: 'The Reticle platform did not answer, so credits and the Harness are not known now. Local checks still work.',
26
+ NO_CREDITS: (said) => `${said} Reticle Harness cannot run until the user gets more credits on the dashboard's Plan and usage page.`,
27
+ locked: (percent, missing) =>
28
+ // The platform's own sentence already names the score and the gaps: said once, not twice.
29
+ `${0 < missing.length ? missing : `Setup score ${String(percent)}%: Reticle Harness needs ${String(UNLOCK_PERCENT)}%.`} Offer to close these gaps, then drive one flow to raise the score.`,
30
+ OFF: 'Reticle Harness is off for this project. The user can switch it on in the HUD (the Harness row at the foot of the Agent Log) or on the dashboard.',
31
+ NO_PROVIDER: 'The platform has no model provider set, so Reticle Harness cannot run now. Tell the user; it is not on their side.',
32
+ ready: (typical, max) => 'Reticle Harness is on and ready: reticle_verify { action: "explore", persona: "<the journey, with the text the page must show at the end in quotes>" }' +
33
+ (typical === undefined
34
+ ? '.'
35
+ : `. A run costs about ${String(typical)} credits${max === undefined ? '' : `, at most ${String(max)}`}.`),
36
+ };
37
+ const num = (v) => ('number' === typeof v ? v : undefined);
38
+ const str = (v) => ('string' === typeof v ? v : undefined);
39
+ /** The facts and the next step. Pure: the tool's I/O is in `readAccount`. */
40
+ export function accountFacts(input) {
41
+ const base = {
42
+ signedIn: input.signedIn,
43
+ ...(input.workspace === undefined ? {} : { workspace: input.workspace }),
44
+ linked: input.platform !== undefined,
45
+ ...(input.dashboardUrl === undefined ? {} : { dashboardUrl: input.dashboardUrl }),
46
+ };
47
+ if (!input.signedIn)
48
+ return { ...base, next: ACCOUNT_NEXT.SIGN_IN };
49
+ if (input.platform === undefined)
50
+ return { ...base, next: ACCOUNT_NEXT.LINK };
51
+ if (null === input.platform)
52
+ return { ...base, next: ACCOUNT_NEXT.UNREACHABLE };
53
+ const p = input.platform;
54
+ const rawCredits = asRecord(p['credits']);
55
+ const used = num(rawCredits['used']);
56
+ const limit = num(rawCredits['limit']);
57
+ const plan = asRecord(p['plan']);
58
+ const daysLeft = num(plan['daysLeft']);
59
+ const kind = str(rawCredits['kind']);
60
+ const credits = used === undefined || limit === undefined
61
+ ? undefined
62
+ : {
63
+ used,
64
+ limit,
65
+ left: Math.max(0, limit - used),
66
+ ...(kind === undefined ? {} : { kind }),
67
+ said: creditsUsageText({
68
+ used,
69
+ limit,
70
+ ...('free' === kind || 'trial' === kind || 'paid' === kind ? { kind } : {}),
71
+ ...(daysLeft === undefined ? {} : { daysLeft }),
72
+ }),
73
+ };
74
+ const runCost = asRecord(p['harnessRunCredits']);
75
+ const typical = num(runCost['typical']);
76
+ const max = num(runCost['max']);
77
+ const lock = asRecord(p['harnessLock']);
78
+ const score = num(p['coverageScore']);
79
+ const percent = score === undefined ? undefined : Math.floor(score * 100 + 1e-9);
80
+ const unlocked = true === p['harnessUnlocked'];
81
+ const provider = str(p['provider']);
82
+ const providerReady = provider === undefined ? true : asRecord(p['available'])[provider] !== false;
83
+ const harness = {
84
+ on: true === p['harnessEnabled'],
85
+ unlocked,
86
+ ...(percent === undefined ? {} : { setupScore: percent }),
87
+ ...(str(lock['reason']) === undefined ? {} : { missing: str(lock['reason']) }),
88
+ ...(str(lock['prompt']) === undefined ? {} : { setupPrompt: str(lock['prompt']) }),
89
+ ...(typical === undefined
90
+ ? {}
91
+ : { runCredits: { typical, ...(max === undefined ? {} : { max }) } }),
92
+ };
93
+ const facts = {
94
+ ...base,
95
+ ...(0 === Object.keys(plan).length ? {} : { plan }),
96
+ ...(credits === undefined ? {} : { credits }),
97
+ harness,
98
+ };
99
+ const next = credits !== undefined && 0 === credits.left
100
+ ? ACCOUNT_NEXT.NO_CREDITS(credits.said)
101
+ : !unlocked
102
+ ? ACCOUNT_NEXT.locked(percent ?? 0, str(lock['reason']) ?? '')
103
+ : !providerReady
104
+ ? ACCOUNT_NEXT.NO_PROVIDER
105
+ : !harness.on
106
+ ? ACCOUNT_NEXT.OFF
107
+ : ACCOUNT_NEXT.ready(typical, max);
108
+ return { ...facts, next };
109
+ }
110
+ /** The platform's model config with this project's linked key; undefined unlinked, null on no answer. */
111
+ async function platformConfig(deps) {
112
+ // The project's own link, not the environment: an agent asks about the project it is in.
113
+ const platform = (await deps.linkedCloud?.()) ?? null;
114
+ if (null === platform)
115
+ return undefined;
116
+ try {
117
+ const res = await fetch(`${platform.url.replace(/\/+$/, '')}${CONFIG_PATH}`, {
118
+ method: 'GET',
119
+ headers: platformHeaders(platform),
120
+ signal: AbortSignal.timeout(CONFIG_TIMEOUT_MS),
121
+ });
122
+ if (!res.ok)
123
+ return null;
124
+ return asRecord(JSON.parse(await res.text()));
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
130
+ async function readAccount(deps, sessionId) {
131
+ let root;
132
+ try {
133
+ root = sessionRoot(deps, sessionId);
134
+ }
135
+ catch {
136
+ root = undefined; // no tab: the account still answers, without a project
137
+ }
138
+ const snapshot = impactSnapshot(root);
139
+ const account = snapshot?.account;
140
+ const dashboardUrl = root === undefined ? undefined : readDashboardUrl(root);
141
+ return accountFacts({
142
+ signedIn: true === account?.signedIn,
143
+ ...(account?.org === undefined ? {} : { workspace: account.org }),
144
+ ...(dashboardUrl === undefined ? {} : { dashboardUrl }),
145
+ platform: await platformConfig(deps),
146
+ });
147
+ }
148
+ export const ACCOUNT_TOOLS = [
149
+ {
150
+ name: ReticleTool.ACCOUNT,
151
+ description: 'Where the user stands with Reticle: signed in or not, whether this project reports to the dashboard, the plan and credits left, whether Reticle Harness is on and unlocked, the setup score and what is missing, what a Harness run costs, and the one thing to do next. Read it before you tell the user anything about credits, the plan or the Harness.',
152
+ inputSchema: {
153
+ sessionId: z.string().optional().describe('Target a specific tab. Omit unless you mean one.'),
154
+ },
155
+ handler: async (deps, args) => readAccount(deps, asString(args['sessionId'])),
156
+ },
157
+ ];
@@ -18,3 +18,14 @@ export declare function assertDragNotDestructive(innerArgs: Record<string, unkno
18
18
  export declare const NATIVE_INPUT_UNSUPPORTED: string;
19
19
  /** Refuse rather than silently drop a native-input request the act-then-wait path cannot honour. */
20
20
  export declare function assertNativeInputSupported(innerArgs: Record<string, unknown>): void;
21
+ /**
22
+ * The agent's own declaration counts as the confirmation, for that one control.
23
+ *
24
+ * `reticle_act_and_wait { target: { role: "button", name: "Place order" }, until }` names the
25
+ * control by the very words the guard flags AND names the consequence before acting: asking again
26
+ * for `confirmDangerous` cost a round trip per step on a shop's ordinary path and protected nothing.
27
+ * A `ref` or `testid` does not count — neither says what the control does, and a stale ref is
28
+ * exactly how the wrong button gets pressed. A Harness call never takes this path: its outward
29
+ * guard decides alone.
30
+ */
31
+ export declare function confirmedByDeclaration(innerArgs: Record<string, unknown>, target: unknown, declared: boolean): Record<string, unknown>;