@reticlehq/server 3.6.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 (614) hide show
  1. package/SKILL.md +122 -123
  2. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  3. package/dist/command/cli/adhoc-suite.js +42 -7
  4. package/dist/command/cli/adhoc-verdict.d.ts +18 -2
  5. package/dist/command/cli/adhoc-verdict.js +70 -6
  6. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  7. package/dist/command/cli/answers/gate-exit.js +45 -0
  8. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  9. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  10. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  11. package/dist/command/cli/auth/device-flow.js +17 -0
  12. package/dist/command/cli/cli-doctor.js +14 -0
  13. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  14. package/dist/command/cli/cli-flow-commands.js +28 -105
  15. package/dist/command/cli/cli-kill.js +3 -2
  16. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  17. package/dist/command/cli/cli-parse-grammar.js +75 -0
  18. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  19. package/dist/command/cli/cli-parse-verify.js +18 -0
  20. package/dist/command/cli/cli-parse.d.ts +19 -28
  21. package/dist/command/cli/cli-parse.js +82 -182
  22. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  23. package/dist/command/cli/cli-update-commands.js +61 -9
  24. package/dist/command/cli/cli-usage.d.ts +33 -0
  25. package/dist/command/cli/cli-usage.js +287 -0
  26. package/dist/command/cli/cli-verify.d.ts +34 -4
  27. package/dist/command/cli/cli-verify.js +81 -12
  28. package/dist/command/cli/cloud-cli.d.ts +13 -0
  29. package/dist/command/cli/cloud-cli.js +145 -333
  30. package/dist/command/cli/cloud-kit.d.ts +12 -0
  31. package/dist/command/cli/cloud-kit.js +41 -2
  32. package/dist/command/cli/cloud-link.d.ts +57 -0
  33. package/dist/command/cli/cloud-link.js +308 -0
  34. package/dist/command/cli/cloud-login.d.ts +15 -1
  35. package/dist/command/cli/cloud-login.js +67 -13
  36. package/dist/command/cli/context-command.d.ts +1 -0
  37. package/dist/command/cli/context-command.js +33 -0
  38. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  39. package/dist/command/cli/daemon-start-options.js +24 -3
  40. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  41. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  42. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  43. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  44. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  45. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  46. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  47. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  48. package/dist/command/cli/known-regression.d.ts +13 -0
  49. package/dist/command/cli/known-regression.js +34 -0
  50. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  51. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  52. package/dist/command/cli/lifecycle/daemon-lifecycle.js +11 -2
  53. package/dist/command/cli/mcp-command.d.ts +6 -0
  54. package/dist/command/cli/mcp-command.js +13 -5
  55. package/dist/command/cli/ports/port-holder.js +1 -1
  56. package/dist/command/cli/project-name.d.ts +29 -1
  57. package/dist/command/cli/project-name.js +107 -2
  58. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  59. package/dist/command/cli/setup-mcp-cli.js +29 -8
  60. package/dist/command/cli/status/status-lines.d.ts +1 -0
  61. package/dist/command/cli/status/status-lines.js +47 -2
  62. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  63. package/dist/command/cli/status/workspace-links.js +29 -0
  64. package/dist/command/cli/try-command.d.ts +96 -0
  65. package/dist/command/cli/try-command.js +362 -0
  66. package/dist/command/cli/tutorial.d.ts +0 -100
  67. package/dist/command/cli/tutorial.js +0 -178
  68. package/dist/command/cli/verify-results.d.ts +19 -0
  69. package/dist/command/cli/verify-results.js +29 -0
  70. package/dist/command/cli-onboarding.d.ts +0 -11
  71. package/dist/command/cli-onboarding.js +0 -15
  72. package/dist/command/cli.d.ts +14 -0
  73. package/dist/command/cli.js +103 -83
  74. package/dist/command/daemon/daemon-resilience.js +4 -4
  75. package/dist/command/daemon/daemon-resolve.d.ts +9 -1
  76. package/dist/command/daemon/daemon-resolve.js +49 -10
  77. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  78. package/dist/command/setup/bringup/bridge-port.js +13 -3
  79. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  80. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  81. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  82. package/dist/command/setup/init/agent-restart.js +28 -0
  83. package/dist/command/setup/init/init-port.d.ts +10 -1
  84. package/dist/command/setup/init/init-port.js +22 -2
  85. package/dist/command/setup/init/init-runtime.d.ts +12 -2
  86. package/dist/command/setup/init/init-runtime.js +96 -37
  87. package/dist/command/setup/node-effects.d.ts +2 -0
  88. package/dist/command/setup/node-effects.js +36 -8
  89. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  90. package/dist/command/setup/probe/existing-app.js +14 -0
  91. package/dist/command/setup/remaining-steps.js +1 -1
  92. package/dist/command/setup/run-setup.d.ts +29 -9
  93. package/dist/command/setup/run-setup.js +34 -28
  94. package/dist/command/setup/setup-command.d.ts +23 -0
  95. package/dist/command/setup/setup-command.js +57 -4
  96. package/dist/command/setup/setup-mcp.js +25 -2
  97. package/dist/command/setup/tauri-signing.d.ts +19 -0
  98. package/dist/command/setup/tauri-signing.js +79 -0
  99. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  100. package/dist/command/setup/terminal/listeners.js +37 -6
  101. package/dist/command/update/update-nudge.d.ts +9 -0
  102. package/dist/command/update/update-nudge.js +1 -1
  103. package/dist/command/update/updater.js +11 -15
  104. package/dist/command/version/version-nudge.js +3 -0
  105. package/dist/command/version/version-skew.d.ts +20 -1
  106. package/dist/command/version/version-skew.js +38 -2
  107. package/dist/features/crawl/crawl.js +14 -1
  108. package/dist/features/exhaust/ledger.d.ts +14 -14
  109. package/dist/features/harness/drive-report.d.ts +39 -5
  110. package/dist/features/harness/drive-report.js +271 -54
  111. package/dist/features/harness/drive-runs.d.ts +120 -0
  112. package/dist/features/harness/drive-runs.js +289 -0
  113. package/dist/features/harness/drivers.d.ts +1 -1
  114. package/dist/features/harness/drivers.js +1 -1
  115. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  116. package/dist/features/harness/explore/console-pages.js +146 -0
  117. package/dist/features/harness/explore/disparity.d.ts +19 -0
  118. package/dist/features/harness/explore/disparity.js +71 -0
  119. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  120. package/dist/features/harness/explore/fake-app.js +49 -0
  121. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  122. package/dist/features/harness/explore/goal-search.js +144 -0
  123. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  124. package/dist/features/harness/explore/page-tree.js +148 -0
  125. package/dist/features/harness/explore/site-map.d.ts +34 -0
  126. package/dist/features/harness/explore/site-map.js +150 -0
  127. package/dist/features/harness/goals.d.ts +68 -7
  128. package/dist/features/harness/goals.js +289 -36
  129. package/dist/features/harness/harness.d.ts +30 -1
  130. package/dist/features/harness/harness.js +141 -7
  131. package/dist/features/harness/platform/local-apps.d.ts +36 -3
  132. package/dist/features/harness/platform/local-apps.js +81 -5
  133. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  134. package/dist/features/harness/platform/persona-credentials.js +69 -0
  135. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  136. package/dist/features/harness/platform/platform-drives.js +114 -0
  137. package/dist/features/harness/platform/refusal.d.ts +52 -0
  138. package/dist/features/harness/platform/refusal.js +71 -0
  139. package/dist/features/harness/platform/remote-drive.d.ts +8 -2
  140. package/dist/features/harness/platform/remote-drive.js +22 -9
  141. package/dist/features/harness/platform/script.d.ts +57 -11
  142. package/dist/features/harness/platform/script.js +144 -12
  143. package/dist/features/harness/platform/server-driver.d.ts +17 -4
  144. package/dist/features/harness/platform/server-driver.js +29 -26
  145. package/dist/features/harness/platform-config.d.ts +38 -5
  146. package/dist/features/harness/platform-config.js +93 -8
  147. package/dist/features/harness/route-guess.d.ts +13 -0
  148. package/dist/features/harness/route-guess.js +49 -0
  149. package/dist/features/harness/script/script-run.d.ts +30 -1
  150. package/dist/features/harness/script/script-run.js +355 -48
  151. package/dist/features/license/license.d.ts +2 -2
  152. package/dist/features/visual/step-shots.d.ts +31 -0
  153. package/dist/features/visual/step-shots.js +231 -0
  154. package/dist/features/visual/visual-tools.js +22 -14
  155. package/dist/hooks/client-directory.d.ts +18 -0
  156. package/dist/hooks/client-directory.js +57 -0
  157. package/dist/hooks/coding-agents.d.ts +34 -0
  158. package/dist/hooks/coding-agents.js +117 -0
  159. package/dist/hooks/driven-by.d.ts +21 -2
  160. package/dist/hooks/driven-by.js +42 -2
  161. package/dist/hooks/hook-bus.d.ts +4 -0
  162. package/dist/hooks/hook-bus.js +18 -0
  163. package/dist/index.d.ts +1 -0
  164. package/dist/index.js +26 -183
  165. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  166. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  167. package/dist/judgement/capsule/causal-summary.js +33 -0
  168. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  169. package/dist/judgement/runs/artifact/build-verification-run.js +20 -4
  170. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  171. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  172. package/dist/judgement/runs/artifact/replay-mapping.js +25 -9
  173. package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
  174. package/dist/judgement/runs/artifact/run-store.js +175 -8
  175. package/dist/judgement/runs/context-tools.js +59 -1
  176. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  177. package/dist/judgement/runs/default-run-id.js +16 -0
  178. package/dist/judgement/runs/drive-run.d.ts +53 -5
  179. package/dist/judgement/runs/drive-run.js +234 -20
  180. package/dist/judgement/runs/resume.d.ts +44 -0
  181. package/dist/judgement/runs/resume.js +137 -0
  182. package/dist/judgement/runs/reticle-runner.js +5 -2
  183. package/dist/judgement/runs/runner-port.d.ts +5 -1
  184. package/dist/judgement/runs/runner-port.js +8 -2
  185. package/dist/judgement/runs/verification-sync.d.ts +2 -0
  186. package/dist/judgement/runs/verification-sync.js +36 -15
  187. package/dist/language/flows/decision.js +2 -1
  188. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  189. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  190. package/dist/language/flows/flow-anchor.d.ts +7 -2
  191. package/dist/language/flows/flow-anchor.js +10 -3
  192. package/dist/language/flows/flow-intent.d.ts +1 -0
  193. package/dist/language/flows/flow-journey.d.ts +6 -0
  194. package/dist/language/flows/flow-journey.js +20 -0
  195. package/dist/language/flows/flow-learning.d.ts +4 -0
  196. package/dist/language/flows/flow-learning.js +37 -3
  197. package/dist/language/flows/flow-replay-run.js +16 -18
  198. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  199. package/dist/language/flows/flow-replay.d.ts +18 -1
  200. package/dist/language/flows/flow-replay.js +22 -7
  201. package/dist/language/flows/flow-result.d.ts +22 -1
  202. package/dist/language/flows/flow-result.js +47 -2
  203. package/dist/language/flows/flow-step-runners.d.ts +2 -0
  204. package/dist/language/flows/flow-step-runners.js +12 -6
  205. package/dist/language/flows/flow-store-for-session.js +5 -1
  206. package/dist/language/flows/flow-tools.d.ts +10 -0
  207. package/dist/language/flows/flow-tools.js +61 -62
  208. package/dist/language/flows/flows.d.ts +16 -1
  209. package/dist/language/flows/flows.js +69 -10
  210. package/dist/language/flows/narrow-write.d.ts +7 -0
  211. package/dist/language/flows/narrow-write.js +36 -1
  212. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  213. package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
  214. package/dist/language/flows/recording/tape/recordings.js +60 -10
  215. package/dist/language/flows/replay.js +29 -6
  216. package/dist/language/flows/single-replay.d.ts +7 -0
  217. package/dist/language/flows/single-replay.js +26 -0
  218. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  219. package/dist/language/flows/verify-change-tools.js +200 -193
  220. package/dist/memory/cloud/cloud-config.d.ts +10 -1
  221. package/dist/memory/cloud/cloud-config.js +19 -5
  222. package/dist/memory/cloud/cloud-sync.js +3 -3
  223. package/dist/memory/cloud/harness-config.d.ts +49 -0
  224. package/dist/memory/cloud/harness-config.js +16 -20
  225. package/dist/memory/cloud/memory-scope.d.ts +17 -0
  226. package/dist/memory/cloud/memory-scope.js +22 -0
  227. package/dist/memory/cloud/sync-cycle.d.ts +32 -4
  228. package/dist/memory/cloud/sync-cycle.js +113 -12
  229. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  230. package/dist/memory/cloud/sync-daemon.js +114 -4
  231. package/dist/memory/cloud/sync-disk.js +26 -2
  232. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  233. package/dist/memory/cloud/sync-screenshots.js +105 -0
  234. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  235. package/dist/memory/cloud/unsynced-roots.js +166 -0
  236. package/dist/memory/impact/account-watch.d.ts +16 -1
  237. package/dist/memory/impact/account-watch.js +26 -1
  238. package/dist/memory/impact/impact-store.d.ts +1 -4
  239. package/dist/memory/impact/impact-store.js +32 -42
  240. package/dist/memory/intent/inline-intent.d.ts +1 -0
  241. package/dist/memory/intent/intent-shard-store.js +16 -4
  242. package/dist/memory/intent/intent-shard.d.ts +12 -0
  243. package/dist/memory/intent/intent-store.d.ts +1 -0
  244. package/dist/memory/intent/intent-tools.js +42 -2
  245. package/dist/memory/intent/open-intents.d.ts +6 -0
  246. package/dist/memory/intent/open-intents.js +10 -1
  247. package/dist/memory/intent/settled-words.d.ts +24 -0
  248. package/dist/memory/intent/settled-words.js +130 -0
  249. package/dist/memory/journal/drive-flow.d.ts +16 -0
  250. package/dist/memory/journal/drive-flow.js +34 -2
  251. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  252. package/dist/memory/journal/drive-run-flush.js +20 -5
  253. package/dist/memory/journal/journal-recorder.js +46 -3
  254. package/dist/memory/journal/on-disk/retention.d.ts +5 -0
  255. package/dist/memory/journal/on-disk/retention.js +27 -2
  256. package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
  257. package/dist/memory/journal/session-end.d.ts +15 -1
  258. package/dist/memory/journal/session-end.js +38 -7
  259. package/dist/memory/project/artifact-root-resolver.js +33 -5
  260. package/dist/memory/project/artifact-root.d.ts +4 -3
  261. package/dist/memory/project/artifact-root.js +2 -2
  262. package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
  263. package/dist/memory/project/dir/reticle-dir.js +23 -2
  264. package/dist/memory/project/link-directory.d.ts +15 -0
  265. package/dist/memory/project/link-directory.js +44 -0
  266. package/dist/memory/project/root-claims.d.ts +6 -0
  267. package/dist/memory/project/root-claims.js +39 -0
  268. package/dist/memory/project/session-root.d.ts +2 -0
  269. package/dist/memory/project/session-root.js +9 -1
  270. package/dist/memory/project/sync-status.d.ts +46 -0
  271. package/dist/memory/project/sync-status.js +135 -1
  272. package/dist/memory/recall/memory-tools.js +46 -3
  273. package/dist/memory/recall/platform-memory.d.ts +34 -0
  274. package/dist/memory/recall/platform-memory.js +139 -0
  275. package/dist/memory/recall/project-memory.js +36 -8
  276. package/dist/portal/bridge/bridge.d.ts +9 -5
  277. package/dist/portal/bridge/bridge.js +66 -23
  278. package/dist/portal/bridge/harness-request.d.ts +23 -0
  279. package/dist/portal/bridge/harness-request.js +27 -0
  280. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  281. package/dist/portal/bridge/wrong-path.js +35 -0
  282. package/dist/portal/input/network-mock-tools.js +11 -2
  283. package/dist/portal/input/real-input.d.ts +2 -0
  284. package/dist/portal/input/real-input.js +13 -10
  285. package/dist/portal/pool/browser-pool.d.ts +48 -0
  286. package/dist/portal/pool/browser-pool.js +120 -2
  287. package/dist/portal/pool/context-permissions.d.ts +33 -0
  288. package/dist/portal/pool/context-permissions.js +33 -0
  289. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  290. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  291. package/dist/portal/pool/playwright-launcher.d.ts +27 -5
  292. package/dist/portal/pool/playwright-launcher.js +59 -14
  293. package/dist/portal/pool/pool-contract.d.ts +21 -1
  294. package/dist/portal/session/agent-link.d.ts +8 -0
  295. package/dist/portal/session/agent-link.js +17 -0
  296. package/dist/portal/session/command-payload.js +6 -1
  297. package/dist/portal/session/daemon-answers.d.ts +3 -3
  298. package/dist/portal/session/daemon-answers.js +4 -2
  299. package/dist/portal/session/dev-server/dev-command.d.ts +9 -0
  300. package/dist/portal/session/dev-server/dev-command.js +27 -1
  301. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  302. package/dist/portal/session/facts/observed-state.js +46 -3
  303. package/dist/portal/session/human/live-control.d.ts +9 -2
  304. package/dist/portal/session/human/live-control.js +12 -3
  305. package/dist/portal/session/live-control-tools.js +82 -13
  306. package/dist/portal/session/narration-args.d.ts +5 -0
  307. package/dist/portal/session/narration-args.js +17 -0
  308. package/dist/portal/session/no-session-diagnosis.d.ts +1 -1
  309. package/dist/portal/session/no-session-diagnosis.js +31 -9
  310. package/dist/portal/session/no-session-next-action.d.ts +20 -0
  311. package/dist/portal/session/no-session-next-action.js +134 -61
  312. package/dist/portal/session/no-session-watch.js +179 -22
  313. package/dist/portal/session/presence/session-lease.js +1 -1
  314. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  315. package/dist/portal/session/recorded-gaps.js +251 -0
  316. package/dist/portal/session/session-health.d.ts +11 -0
  317. package/dist/portal/session/session-health.js +3 -1
  318. package/dist/portal/session/session-info.js +2 -1
  319. package/dist/portal/session/session-manager.d.ts +18 -0
  320. package/dist/portal/session/session-manager.js +54 -3
  321. package/dist/portal/session/session-successor.d.ts +8 -0
  322. package/dist/portal/session/session-successor.js +1 -1
  323. package/dist/portal/session/session.d.ts +15 -28
  324. package/dist/portal/session/session.js +60 -61
  325. package/dist/portal/session/timing/command-timeout.js +25 -1
  326. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  327. package/dist/portal/session/timing/wall-clock.js +1 -1
  328. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  329. package/dist/portal/session/zero-install-first-call.js +88 -0
  330. package/dist/start-options.d.ts +7 -1
  331. package/dist/start-wiring.d.ts +63 -0
  332. package/dist/start-wiring.js +169 -0
  333. package/dist/status-payload.d.ts +13 -1
  334. package/dist/status-payload.js +13 -1
  335. package/dist/surface/http-server.js +7 -1
  336. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  337. package/dist/surface/mcp/attach-memory.js +12 -1
  338. package/dist/surface/mcp/mcp-proxy.d.ts +4 -0
  339. package/dist/surface/mcp/mcp-proxy.js +29 -8
  340. package/dist/surface/mcp/mcp.d.ts +23 -0
  341. package/dist/surface/mcp/mcp.js +34 -4
  342. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  343. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  344. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  345. package/dist/surface/mcp/server-instructions.js +22 -14
  346. package/dist/surface/mcp/shared-params.js +1 -1
  347. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  348. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  349. package/dist/surface/tools/account-tool.d.ts +22 -0
  350. package/dist/surface/tools/account-tool.js +157 -0
  351. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  352. package/dist/surface/tools/act/act-danger.js +38 -1
  353. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  354. package/dist/surface/tools/act/act-observation.js +57 -0
  355. package/dist/surface/tools/act/act-preflight.js +25 -2
  356. package/dist/surface/tools/act/act-target.js +8 -3
  357. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  358. package/dist/surface/tools/act/resolve-target.js +18 -3
  359. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  360. package/dist/surface/tools/act/screen-request.js +113 -0
  361. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  362. package/dist/surface/tools/act/sequence-grade.js +13 -2
  363. package/dist/surface/tools/act-sequence-tool.js +136 -27
  364. package/dist/surface/tools/act-tools.d.ts +0 -9
  365. package/dist/surface/tools/act-tools.js +48 -34
  366. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  367. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  368. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  369. package/dist/surface/tools/agent/app-notes.js +48 -0
  370. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  371. package/dist/surface/tools/agent/build-staleness.js +62 -0
  372. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  373. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  374. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  375. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  376. package/dist/surface/tools/agent/notices.d.ts +50 -0
  377. package/dist/surface/tools/agent/notices.js +152 -0
  378. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  379. package/dist/surface/tools/agent/reteach.js +50 -0
  380. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  381. package/dist/surface/tools/args/alias-args.js +10 -0
  382. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  383. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  384. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  385. package/dist/surface/tools/assert/assert-source.js +40 -0
  386. package/dist/surface/tools/assert/assert-verdict.js +25 -15
  387. package/dist/surface/tools/browser-tools.js +43 -1
  388. package/dist/surface/tools/chat-drives.d.ts +75 -0
  389. package/dist/surface/tools/chat-drives.js +265 -21
  390. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  391. package/dist/surface/tools/coverage-tools.js +2 -53
  392. package/dist/surface/tools/dynamic-tools.js +29 -1
  393. package/dist/surface/tools/empty-session-list.d.ts +10 -0
  394. package/dist/surface/tools/empty-session-list.js +45 -5
  395. package/dist/surface/tools/error-recovery.d.ts +8 -0
  396. package/dist/surface/tools/error-recovery.js +69 -5
  397. package/dist/surface/tools/explore-tools.d.ts +23 -2
  398. package/dist/surface/tools/explore-tools.js +377 -74
  399. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  400. package/dist/surface/tools/feedback-tools.js +4 -3
  401. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  402. package/dist/surface/tools/gap-novelty.js +8 -1
  403. package/dist/surface/tools/harness-explore.d.ts +52 -73
  404. package/dist/surface/tools/harness-explore.js +177 -146
  405. package/dist/surface/tools/harness-gate.d.ts +88 -0
  406. package/dist/surface/tools/harness-gate.js +235 -0
  407. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  408. package/dist/surface/tools/harness-hunt.js +215 -0
  409. package/dist/surface/tools/harness-plan.d.ts +5 -0
  410. package/dist/surface/tools/harness-plan.js +7 -0
  411. package/dist/surface/tools/harness-script.d.ts +22 -0
  412. package/dist/surface/tools/harness-script.js +256 -38
  413. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  414. package/dist/surface/tools/harness-tab-guard.js +27 -0
  415. package/dist/surface/tools/harness-toolset.d.ts +8 -0
  416. package/dist/surface/tools/harness-toolset.js +27 -4
  417. package/dist/surface/tools/human-notes.d.ts +16 -0
  418. package/dist/surface/tools/human-notes.js +27 -0
  419. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  420. package/dist/surface/tools/invoke-tool.js +220 -93
  421. package/dist/surface/tools/lease-hint.js +26 -5
  422. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  423. package/dist/surface/tools/lease-permissions.js +73 -0
  424. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  425. package/dist/surface/tools/lease-readiness.js +57 -0
  426. package/dist/surface/tools/lease-seed.d.ts +20 -0
  427. package/dist/surface/tools/lease-seed.js +45 -1
  428. package/dist/surface/tools/lease-tools.d.ts +10 -1
  429. package/dist/surface/tools/lease-tools.js +119 -69
  430. package/dist/surface/tools/live-call-text.js +2 -2
  431. package/dist/surface/tools/merge-tools.js +42 -2
  432. package/dist/surface/tools/merged-name-redirect.js +4 -0
  433. package/dist/surface/tools/next-step.d.ts +11 -1
  434. package/dist/surface/tools/next-step.js +73 -18
  435. package/dist/surface/tools/observe-tools.js +43 -5
  436. package/dist/surface/tools/platform-moment.d.ts +60 -0
  437. package/dist/surface/tools/platform-moment.js +132 -4
  438. package/dist/surface/tools/read-tools.js +65 -14
  439. package/dist/surface/tools/reticle-result.d.ts +120 -0
  440. package/dist/surface/tools/reticle-result.js +364 -0
  441. package/dist/surface/tools/tool-kit.d.ts +68 -2
  442. package/dist/surface/tools/tool-kit.js +73 -1
  443. package/dist/surface/tools/tools.js +25 -13
  444. package/dist/telemetry/account-envelope.d.ts +7 -0
  445. package/dist/telemetry/account-envelope.js +61 -0
  446. package/dist/telemetry/agent-client.d.ts +15 -0
  447. package/dist/telemetry/agent-client.js +57 -0
  448. package/dist/telemetry/app-instrumented.js +9 -2
  449. package/dist/telemetry/argument-shape.d.ts +7 -0
  450. package/dist/telemetry/argument-shape.js +86 -1
  451. package/dist/telemetry/automation-hint.d.ts +2 -3
  452. package/dist/telemetry/automation-hint.js +33 -8
  453. package/dist/telemetry/cli-telemetry.js +7 -2
  454. package/dist/telemetry/daemon-telemetry.js +3 -0
  455. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  456. package/dist/telemetry/error-fingerprint.js +61 -5
  457. package/dist/telemetry/feedback-cli.d.ts +0 -13
  458. package/dist/telemetry/feedback-cli.js +0 -77
  459. package/dist/telemetry/feedback.d.ts +13 -0
  460. package/dist/telemetry/feedback.js +183 -17
  461. package/dist/telemetry/harness-run.d.ts +18 -0
  462. package/dist/telemetry/harness-run.js +80 -0
  463. package/dist/telemetry/hud-events.d.ts +16 -0
  464. package/dist/telemetry/hud-events.js +27 -0
  465. package/dist/telemetry/hud-metrics.d.ts +27 -6
  466. package/dist/telemetry/hud-metrics.js +99 -25
  467. package/dist/telemetry/init-telemetry.js +2 -2
  468. package/dist/telemetry/install-source.d.ts +13 -25
  469. package/dist/telemetry/install-source.js +44 -3
  470. package/dist/telemetry/mcp-connection.d.ts +0 -14
  471. package/dist/telemetry/mcp-connection.js +5 -1
  472. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  473. package/dist/telemetry/onboarding-firsts.js +81 -6
  474. package/dist/telemetry/platform-linked.d.ts +5 -0
  475. package/dist/telemetry/platform-linked.js +32 -0
  476. package/dist/telemetry/project-profile.js +5 -3
  477. package/dist/telemetry/proxy-telemetry.js +4 -1
  478. package/dist/telemetry/session-metrics.d.ts +15 -4
  479. package/dist/telemetry/session-metrics.js +88 -52
  480. package/dist/telemetry/telemetry.d.ts +26 -2
  481. package/dist/telemetry/telemetry.js +102 -21
  482. package/dist/telemetry/verification-of.d.ts +3 -1
  483. package/dist/telemetry/verification-of.js +12 -4
  484. package/dist/wire-journal.d.ts +2 -2
  485. package/dist/wire-journal.js +16 -5
  486. package/docs/README.md +2 -2
  487. package/docs/actions.mdx +6 -3
  488. package/docs/adapters.md +1 -1
  489. package/docs/agent-cheatsheet.md +24 -27
  490. package/docs/architecture.md +5 -5
  491. package/docs/autodrive.md +13 -12
  492. package/docs/benchmarks.md +5 -5
  493. package/docs/best-practices.mdx +27 -9
  494. package/docs/capabilities.mdx +14 -16
  495. package/docs/cli/affected.mdx +1 -1
  496. package/docs/cli/cloud.mdx +54 -75
  497. package/docs/cli/doctor.mdx +8 -3
  498. package/docs/cli/drive.mdx +12 -12
  499. package/docs/cli/feedback.mdx +3 -3
  500. package/docs/cli/gate.mdx +7 -2
  501. package/docs/cli/help.mdx +50 -55
  502. package/docs/cli/init.mdx +32 -15
  503. package/docs/cli/license.mdx +12 -8
  504. package/docs/cli/mcp.mdx +4 -4
  505. package/docs/cli/open.mdx +3 -3
  506. package/docs/cli/report.mdx +4 -2
  507. package/docs/cli/restart.mdx +2 -2
  508. package/docs/cli/rollback.mdx +14 -8
  509. package/docs/cli/serve.mdx +4 -4
  510. package/docs/cli/setup.mdx +23 -0
  511. package/docs/cli/status.mdx +13 -4
  512. package/docs/cli/stop.mdx +67 -8
  513. package/docs/cli/try.mdx +62 -0
  514. package/docs/cli/update.mdx +4 -3
  515. package/docs/cli/verify.mdx +17 -6
  516. package/docs/cli/version.mdx +3 -2
  517. package/docs/cli.mdx +110 -41
  518. package/docs/debugging.md +3 -3
  519. package/docs/deploy-checks.md +1 -1
  520. package/docs/desktop.mdx +5 -3
  521. package/docs/enterprise.md +11 -10
  522. package/docs/environment.mdx +5 -2
  523. package/docs/faq.mdx +3 -3
  524. package/docs/first-drive.md +5 -4
  525. package/docs/flows.md +35 -27
  526. package/docs/for-agents.md +4 -5
  527. package/docs/frameworks.mdx +32 -21
  528. package/docs/getting-started.md +66 -64
  529. package/docs/human-control.md +15 -14
  530. package/docs/index.mdx +15 -43
  531. package/docs/install-agentic.mdx +22 -37
  532. package/docs/install-manual.mdx +22 -12
  533. package/docs/instrumentation.mdx +5 -3
  534. package/docs/integration-patterns.md +7 -7
  535. package/docs/license-activation.mdx +1 -1
  536. package/docs/multi-agent-testing.md +24 -6
  537. package/docs/packages/babel-plugin.mdx +4 -2
  538. package/docs/packages/browser.mdx +16 -10
  539. package/docs/packages/core.mdx +12 -5
  540. package/docs/packages/electron.mdx +3 -2
  541. package/docs/packages/engine.mdx +1 -1
  542. package/docs/packages/eslint-plugin.mdx +18 -12
  543. package/docs/packages/next.mdx +8 -7
  544. package/docs/packages/open-verification.mdx +1 -1
  545. package/docs/packages/server.mdx +5 -5
  546. package/docs/packages/tauri.mdx +8 -8
  547. package/docs/packages/test.mdx +4 -10
  548. package/docs/packages/vite-plugin.mdx +11 -4
  549. package/docs/packages.mdx +11 -15
  550. package/docs/platform-integration.md +6 -5
  551. package/docs/predicates.mdx +40 -24
  552. package/docs/quickstart.mdx +58 -29
  553. package/docs/required-checks.md +8 -7
  554. package/docs/reticle-manual.md +15 -5
  555. package/docs/skill-file.mdx +17 -79
  556. package/docs/skill-setup.md +9 -9
  557. package/docs/skill.md +200 -0
  558. package/docs/system-map.md +7 -7
  559. package/docs/telemetry.md +22 -24
  560. package/docs/testing.md +4 -4
  561. package/docs/token-efficiency.md +12 -12
  562. package/docs/tools/act-and-wait.mdx +9 -2
  563. package/docs/tools/act-sequence.mdx +6 -7
  564. package/docs/tools/act.mdx +2 -2
  565. package/docs/tools/assert.mdx +18 -17
  566. package/docs/tools/console.mdx +9 -9
  567. package/docs/tools/inspect.mdx +16 -7
  568. package/docs/tools/look.mdx +24 -0
  569. package/docs/tools/navigate.mdx +5 -3
  570. package/docs/tools/network.mdx +2 -2
  571. package/docs/tools/observe.mdx +6 -6
  572. package/docs/tools/overview.mdx +34 -33
  573. package/docs/tools/query.mdx +5 -5
  574. package/docs/tools/session-and-feedback.mdx +13 -4
  575. package/docs/tools/sessions.mdx +8 -8
  576. package/docs/tools/snapshot.mdx +6 -5
  577. package/docs/tools/state.mdx +9 -9
  578. package/docs/tools/tools-and-run.mdx +26 -24
  579. package/docs/tools/verify.mdx +28 -0
  580. package/docs/tools/wait-for.mdx +8 -4
  581. package/docs/troubleshooting.mdx +21 -6
  582. package/docs/usage.md +51 -45
  583. package/docs/use-cases.mdx +3 -3
  584. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  585. package/docs/vs-playwright-mcp.mdx +3 -1
  586. package/docs/what-is-recorded.md +7 -5
  587. package/docs/what-is-reticle.mdx +2 -2
  588. package/docs/why-reticle.mdx +1 -1
  589. package/package.json +6 -5
  590. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  591. package/dist/command/cli/demo/demo-page.js +0 -249
  592. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  593. package/dist/command/cli/demo/demo-run.js +0 -138
  594. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  595. package/dist/judgement/hunt/hunt-report.js +0 -84
  596. package/dist/language/flows/buddy-status.d.ts +0 -25
  597. package/dist/language/flows/buddy-status.js +0 -32
  598. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  599. package/dist/language/flows/change/watch-batcher.js +0 -19
  600. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  601. package/dist/memory/cloud/harness-offer.js +0 -145
  602. package/dist/surface/tools/feature-capture.d.ts +0 -151
  603. package/dist/surface/tools/feature-capture.js +0 -235
  604. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  605. package/dist/surface/tools/tool-hit-rate.js +0 -90
  606. package/dist/telemetry/harness-drive.d.ts +0 -4
  607. package/dist/telemetry/harness-drive.js +0 -35
  608. package/dist/telemetry/identify.d.ts +0 -22
  609. package/dist/telemetry/identify.js +0 -73
  610. package/docs/cli/capsules.mdx +0 -70
  611. package/docs/cli/hunt.mdx +0 -73
  612. package/docs/cli/identify.mdx +0 -76
  613. package/docs/cli/kill.mdx +0 -91
  614. package/docs/cli/watch.mdx +0 -62
@@ -10,14 +10,26 @@
10
10
  import { type FlowFile } from '@reticlehq/core';
11
11
  import type { ToolDeps } from './tool-kit.js';
12
12
  import { type HarnessPlan } from './harness-plan.js';
13
- import { type ConfigFetch } from '../../features/harness/platform-config.js';
14
- import { type HarnessResult, type HarnessToolset, type ModelDriver, type ToolOutcome } from '../../features/harness/harness.js';
13
+ import type { ConfigFetch } from '../../features/harness/platform-config.js';
14
+ import type { JourneyResult } from '../../features/harness/platform/script.js';
15
+ import { type HarnessOptions, type HarnessResult, type HarnessToolset, type ModelDriver, type ToolOutcome } from '../../features/harness/harness.js';
15
16
  import { type GoalCheck } from '../../features/harness/goals.js';
17
+ import type { RunDisparity } from '@reticlehq/core';
18
+ import type { HarnessMap } from '@reticlehq/core/artifacts';
19
+ export { MSG_HARNESS_DISABLED, MSG_HARNESS_UNCLAIMED, MSG_HARNESS_UNCONFIRMED, } from '../../features/harness/platform/refusal.js';
20
+ export { MSG_GATE_PROMPT_LEAD, MSG_NO_HARNESS_KEY, coverageRefusal, firstLine, harnessAvailable, harnessLockRefusal, refusedByPlatform, withLinkedCredential, } from './harness-gate.js';
16
21
  export interface ExploreOptions {
17
22
  /** Who to be, or what to accomplish. Appended to the standing instruction. */
18
23
  focus?: string;
24
+ /**
25
+ * A person started this run (Run plan from the dashboard) and acknowledged the saved flows' own
26
+ * destructive steps: a planned replay may take them. Never a step the model decides.
27
+ */
28
+ confirmDangerous?: boolean;
19
29
  /** Texts the drive must leave on the page. Default: whatever `focus` quoted. See goals.ts. */
20
30
  goals?: readonly string[];
31
+ /** The outcome the journey must end in, as a reticle_assert predicate. See `checkExpect`. */
32
+ expect?: Record<string, unknown>;
21
33
  /** Pinned tab, when the app has more than one connected. */
22
34
  sessionId?: string;
23
35
  /** Hard ceiling on model turns. Bounds cost, not value — the drive is usable however it ends. */
@@ -48,6 +60,14 @@ export interface ExploreOptions {
48
60
  * supposed to cover the OFF switch was asserting on a path where the platform is never asked.
49
61
  */
50
62
  configFetch?: ConfigFetch;
63
+ /** The drive's harness id, minted by the caller so its run id is known before the drive starts. */
64
+ harnessId?: string;
65
+ /** A plan the platform saved (`hp_…`): run it as it stands, instead of asking for a new one. */
66
+ planId?: string;
67
+ /** Asked between turns: whoever started the drive asked it to stop. */
68
+ stopped?: () => boolean;
69
+ /** Asked between turns: what whoever started the drive said to it since. */
70
+ inbox?: () => readonly string[];
51
71
  }
52
72
  export interface ExploreResult {
53
73
  drive: HarnessResult;
@@ -85,40 +105,17 @@ export interface ExploreResult {
85
105
  driverName: string;
86
106
  /** The run this drive syncs as (`harness-<id>`), so a caller can find it on the platform. */
87
107
  runIds?: readonly string[];
108
+ /** The run's page on the dashboard, when the project is linked. */
109
+ runUrl?: string;
110
+ /** How each journey of a platform plan ended, worst lane first. Absent for an unplanned drive. */
111
+ journeys?: readonly JourneyResult[];
112
+ /** The platform plan this run drove, which the dashboard keeps, edits and runs again. */
113
+ planId?: string;
114
+ /** That plan's page on the dashboard. */
115
+ planUrl?: string;
116
+ /** Each goal the session's coding agent also judged, and how the two verdicts compare. */
117
+ disparity?: readonly RunDisparity[];
88
118
  }
89
- /**
90
- * Why the harness is unavailable, phrased as the way to make it available.
91
- *
92
- * A missing key is a configuration fact, not a fault, and the sentence a user reads has to tell them
93
- * the one thing to do about it. Named here because both the CLI and the honest no-flows refusal
94
- * print it, and two copies of this sentence would drift.
95
- */
96
- export declare const MSG_NO_HARNESS_KEY: string;
97
- /**
98
- * The environment, plus the credential this machine already has.
99
- *
100
- * `reticle link` mints a project-scoped key and files it in `~/.reticle/credentials.json`; the CLI
101
- * has read it from there for as long as it has existed. The harness did not, and read only
102
- * `process.env` — so somebody who had signed in, linked their project and been told they were
103
- * connected still got "no model configured to drive the app", and the only way out was to find the
104
- * key in the console and export it by hand. Five manual steps to reach a feature they had already
105
- * finished setting up.
106
- *
107
- * Resolved into the env rather than threaded through four call sites: the drivers and the
108
- * preference lookup all read an env record, and giving them a completed one leaves each of them
109
- * exactly as simple as it was. The key precedence is the resolver's, the same as sync's and the
110
- * CLI's: the stored key for the link's host, else the exported one (which is how CI, with no
111
- * keystore, gets here). An explicitly exported HOST still wins, so a proxy is not overridden.
112
- *
113
- * The credential arrives through `deps.linkedCloud`, a port, because resolving it here would make
114
- * the tool surface reach into `memory/cloud` — a reach the directory guard refused, correctly.
115
- */
116
- export declare function withLinkedCredential(deps: ToolDeps, env: Record<string, string | undefined>): Promise<Record<string, string | undefined>>;
117
- /**
118
- * Can this machine reach the Harness? Only through the platform: a linked project or a platform
119
- * key. Whether the workspace is entitled is the platform's answer, asked when the drive starts.
120
- */
121
- export declare function harnessAvailable(env: Record<string, string | undefined>): boolean;
122
119
  /**
123
120
  * Read the step ceiling out of the environment.
124
121
  *
@@ -135,10 +132,11 @@ export declare function maxStepsFromEnv(env: Record<string, string | undefined>)
135
132
  * that says it saved a flow and did not is the same false green as an app that says it saved a
136
133
  * record and did not — and this product does not get to make that mistake about its own work.
137
134
  */
138
- export declare function exploreApp(deps: ToolDeps, env: Record<string, string | undefined>, options?: ExploreOptions): Promise<ExploreResult>;
135
+ export declare function exploreApp(deps: ToolDeps, given: Record<string, string | undefined>, asked?: ExploreOptions): Promise<ExploreResult>;
136
+ /** The stop and the words of whoever started the drive, for `runHarness`. */
137
+ export declare function steering(options: ExploreOptions): Pick<HarnessOptions, 'stopped' | 'inbox'>;
139
138
  /** A line in the HUD's Agent Log for the person watching; nobody watching is not an error. */
140
- export declare function narrator(deps: ToolDeps, options: ExploreOptions): (text: string) => void;
141
- /** What this project's memory says must hold, in its own words. Nothing recorded is none. */
139
+ export declare function narrator(deps: ToolDeps, options: ExploreOptions): (text: string, summary?: boolean) => void;
142
140
  export declare function productRules(deps: ToolDeps, sessionId?: string): Promise<string[]>;
143
141
  /** `deps` whose flow store is the session's own project, where the drive's saves land. */
144
142
  export declare function withProjectFlows(deps: ToolDeps, sessionId?: string): ToolDeps;
@@ -181,39 +179,16 @@ export declare function reconcileFlows(before: ReadonlySet<string>, after: reado
181
179
  rewroteFlows: readonly string[];
182
180
  };
183
181
  /**
184
- * What a person said about autonomous driving on the platform, honoured here.
185
- *
186
- * The switch existed, persisted and round-tripped, and the daemon read it and threw it away — so
187
- * turning the harness OFF changed a value in a database and nothing else. A control that does not
188
- * control anything is worse than no control: somebody turns it off, watches Reticle drive their app
189
- * anyway, and now correctly distrusts every other switch in the product.
190
- *
191
- * Absent means ON. The platform's own default is on, and a machine that cannot reach the platform —
192
- * offline, CI, no link — must not silently lose a feature it was never told to stop using.
193
- */
194
- export declare const MSG_HARNESS_DISABLED: string;
195
- /**
196
- * The other reason a drive can be refused, and it is NOT the same reason.
197
- *
198
- * A drive through the platform spends Reticle's model budget, bounded by the workspace's monthly
199
- * Harness credits. The platform answers this only when something other than the switch stops it.
200
- */
201
- export declare const MSG_HARNESS_UNCLAIMED: string;
202
- /** The platform could not be asked, and the drive would spend Reticle's budget without its yes. */
203
- export declare const MSG_HARNESS_UNCONFIRMED: string;
204
- /**
205
- * The reason this drive must not start, or `undefined` to go ahead.
206
- *
207
- * A drive on somebody's OWN model key never waits on the platform beyond the off switch: their key,
208
- * their spend. A drive through the platform proxy bills Reticle, and that one needs a confirmed yes
209
- * — enabled, entitled, and a model ready. It used to fail open: `fetchPlatformConfig` answers
210
- * `undefined` on a network error, a non-2xx, a body that does not parse, or a two-second timeout,
211
- * and all four read as "carry on", so a slow second on a settings endpoint let an unentitled
212
- * workspace drive on Reticle's budget. Now the same silence refuses with a message that says to
213
- * retry or bring a key. Fields an older platform omits still default to yes inside
214
- * `fetchPlatformConfig`; only an answer that never arrived is a no.
182
+ * Why a drive must not be replayed into a verdict, or undefined when it may. A drive the platform
183
+ * cut off (credits gone: 402 needs_card) had saved one partial flow, and replaying it printed PASS
184
+ * with no word about the credits. The one test both CLI explore paths answer through.
215
185
  */
216
- export declare function refusedByPlatform(env: Record<string, string | undefined>, options: ExploreOptions): Promise<string | undefined>;
186
+ export declare function cutOffReason(drive: {
187
+ stopReason?: unknown;
188
+ error?: unknown;
189
+ }): string | undefined;
190
+ /** The Agent Log's last line for a drive the platform cut off: its reason, and that it proved nothing. */
191
+ export declare const msgDriveCutOff: (error: string | undefined) => string;
217
192
  /**
218
193
  * Close and save whatever recording the drive left open.
219
194
  *
@@ -232,8 +207,10 @@ export declare function refusedByPlatform(env: Record<string, string | undefined
232
207
  * It used to be "Autonomous drive of X, banked after the run ended" whatever the caller asked for,
233
208
  * so a replay could never say which journey the flow was meant to prove.
234
209
  */
235
- export declare function bankedIntent(persona: string | undefined, open: string): string;
236
- export declare function bankOpenRecording(toolset: HarnessToolset, drive: HarnessResult, persona: string | undefined): Promise<void>;
210
+ export declare function bankedIntent(persona: string | undefined, open: string,
211
+ /** The journey the drive was for, when no persona was named. */
212
+ journey?: string): string;
213
+ export declare function bankOpenRecording(toolset: HarnessToolset, drive: HarnessResult, persona: string | undefined, journey?: string): Promise<ToolOutcome[]>;
237
214
  /** The recording started and never stopped, if there is one. Exported because it is the decision. */
238
215
  export declare function openRecordingName(toolCalls: readonly ToolOutcome[]): string | undefined;
239
216
  /**
@@ -254,7 +231,9 @@ export declare function pinned(options: ExploreOptions): {
254
231
  */
255
232
  export declare function buildDriver(env: Record<string, string | undefined>, maxSteps: number, plan: HarnessPlan, requested?: string, persona?: string,
256
233
  /** A goal driven with no persona: it names the drive's flows as a persona would. */
257
- journey?: string): {
234
+ journey?: string,
235
+ /** The survey of the app, which the platform's engine looks goals up in. */
236
+ siteMap?: HarnessMap): {
258
237
  driver: ModelDriver;
259
238
  name: string;
260
239
  };
@@ -10,78 +10,32 @@
10
10
  import { serverDriver, serverOptionsFromEnv } from '../../features/harness/platform/server-driver.js';
11
11
  import { exploreScript } from './harness-script.js';
12
12
  import { randomUUID } from 'node:crypto';
13
- import { harnessRunId } from '../../judgement/runs/drive-run.js';
14
- import { ReticleEnv, ReticleTool, asProjectId, cloudUrlFrom, asRecord, } from '@reticlehq/core';
13
+ import { harnessRunId, noteHarnessDisparity, noteHarnessGoal, noteHarnessSpan, } from '../../judgement/runs/drive-run.js';
14
+ import { ReticleEnv, ReticleTool, asProjectId, asRecord } from '@reticlehq/core';
15
15
  import { flowsForSession } from '../../language/flows/flow-store-for-session.js';
16
16
  import { projectForRoot } from '../../memory/project/project-for-root.js';
17
- import { checkTally, verdictLine } from '../../features/harness/drive-report.js';
17
+ import { actedOnApp, checkTally, pagesReached, typedValues, verdictLine, } from '../../features/harness/drive-report.js';
18
18
  import { CUSTOM_DRIVER_NAME, SERVER_DRIVER } from '../../features/harness/drivers.js';
19
19
  import { buildDomainModel } from '../../judgement/domain/domain-model.js';
20
20
  import { readContract } from '../../memory/project/dir/reticle-dir.js';
21
21
  import { sessionRoot, sessionTarget } from '../../memory/project/session-root.js';
22
- import { buildHarnessPlan, planAsText, withoutReplays } from './harness-plan.js';
22
+ import { dashboardPlanUrl, dashboardRunUrl, readDashboardUrl, readLinkedProjectId, } from '../../memory/project/sync-status.js';
23
+ import { buildHarnessPlan, drivingPlan, planAsText } from './harness-plan.js';
23
24
  import { allSessionIntents } from '../../memory/intent/open-intents.js';
24
- import { fetchPlatformConfig } from '../../features/harness/platform-config.js';
25
25
  import { DEFAULT_MAX_STEPS, runHarness, StopReason, } from '../../features/harness/harness.js';
26
26
  import { reticleToolset } from './harness-toolset.js';
27
- import { checkGoals, goalsIn } from '../../features/harness/goals.js';
28
- /**
29
- * Why the harness is unavailable, phrased as the way to make it available.
30
- *
31
- * A missing key is a configuration fact, not a fault, and the sentence a user reads has to tell them
32
- * the one thing to do about it. Named here because both the CLI and the honest no-flows refusal
33
- * print it, and two copies of this sentence would drift.
34
- */
35
- export const MSG_NO_HARNESS_KEY = `The Reticle Harness runs on the Reticle platform, and every plan includes it (Free comes with ` +
36
- `monthly Harness credits): run \`reticle connect\` to link this project and sign in. ` +
37
- `Without it, drive the journey yourself with reticle_act_and_wait and an \`until\` on its last step: ` +
38
- `what you drive is saved as a flow just the same.`;
27
+ import { DriveRefusedError, noteDriveLine } from '../../features/harness/drive-runs.js';
28
+ import { personaCredentials } from '../../features/harness/platform/persona-credentials.js';
29
+ import { endOf, goalOfDrive, parseGoals, readOpening, unprovedGoals, } from '../../features/harness/goals.js';
30
+ import { mapForPlatform } from '../../features/harness/explore/site-map.js';
31
+ import { huntAndGrade, knownRoutes, refreshMap, siteMapFor } from './harness-hunt.js';
32
+ export { MSG_HARNESS_DISABLED, MSG_HARNESS_UNCLAIMED, MSG_HARNESS_UNCONFIRMED, } from '../../features/harness/platform/refusal.js';
33
+ import { MSG_NO_HARNESS_KEY, refusedForPlan } from './harness-gate.js';
34
+ // The gate a drive passes before it starts moved to its own module; its names are still asked for here.
35
+ export { MSG_GATE_PROMPT_LEAD, MSG_NO_HARNESS_KEY, coverageRefusal, firstLine, harnessAvailable, harnessLockRefusal, refusedByPlatform, withLinkedCredential, } from './harness-gate.js';
39
36
  /** A driver named that this build no longer has: every Harness decision is the platform's now. */
40
37
  const msgUnknownDriver = (asked) => `The Harness driver \`${asked}\` is not available: the Harness runs on the Reticle platform, ` +
41
38
  `which drives with the model set for the project in the dashboard.`;
42
- /**
43
- * The environment, plus the credential this machine already has.
44
- *
45
- * `reticle link` mints a project-scoped key and files it in `~/.reticle/credentials.json`; the CLI
46
- * has read it from there for as long as it has existed. The harness did not, and read only
47
- * `process.env` — so somebody who had signed in, linked their project and been told they were
48
- * connected still got "no model configured to drive the app", and the only way out was to find the
49
- * key in the console and export it by hand. Five manual steps to reach a feature they had already
50
- * finished setting up.
51
- *
52
- * Resolved into the env rather than threaded through four call sites: the drivers and the
53
- * preference lookup all read an env record, and giving them a completed one leaves each of them
54
- * exactly as simple as it was. The key precedence is the resolver's, the same as sync's and the
55
- * CLI's: the stored key for the link's host, else the exported one (which is how CI, with no
56
- * keystore, gets here). An explicitly exported HOST still wins, so a proxy is not overridden.
57
- *
58
- * The credential arrives through `deps.linkedCloud`, a port, because resolving it here would make
59
- * the tool surface reach into `memory/cloud` — a reach the directory guard refused, correctly.
60
- */
61
- export async function withLinkedCredential(deps, env) {
62
- try {
63
- const linked = await deps.linkedCloud?.();
64
- if (linked === undefined || null === linked)
65
- return env;
66
- return {
67
- ...env,
68
- [ReticleEnv.API_KEY]: linked.apiKey,
69
- [ReticleEnv.CLOUD_URL]: cloudUrlFrom(env) ?? linked.url,
70
- };
71
- }
72
- catch {
73
- // A credential store that cannot be read is "not linked", not an error. The harness is optional
74
- // and its absence is a routine answer; a drive must never fail because a JSON file was odd.
75
- return env;
76
- }
77
- }
78
- /**
79
- * Can this machine reach the Harness? Only through the platform: a linked project or a platform
80
- * key. Whether the workspace is entitled is the platform's answer, asked when the drive starts.
81
- */
82
- export function harnessAvailable(env) {
83
- return serverOptionsFromEnv(env) !== undefined;
84
- }
85
39
  /**
86
40
  * Read the step ceiling out of the environment.
87
41
  *
@@ -104,10 +58,15 @@ export function maxStepsFromEnv(env) {
104
58
  * that says it saved a flow and did not is the same false green as an app that says it saved a
105
59
  * record and did not — and this product does not get to make that mistake about its own work.
106
60
  */
107
- export async function exploreApp(deps, env, options = {}) {
108
- const refusal = await refusedByPlatform(env, options);
61
+ export async function exploreApp(deps, given, asked = {}) {
62
+ // Every drive starts here. The credentials a persona names fill its sign-in fields on this
63
+ // machine, and only the redacted text travels on: to the platform, into flows and synced runs.
64
+ const named = asked.focus === undefined ? undefined : personaCredentials(asked.focus);
65
+ const env = named === undefined ? given : { ...given, ...named.secrets };
66
+ const options = named === undefined ? asked : { ...asked, focus: named.persona };
67
+ const refusal = await refusedForPlan(env, options);
109
68
  if (refusal !== undefined)
110
- throw new Error(refusal);
69
+ throw new DriveRefusedError(refusal);
111
70
  // The flows a drive reads and diffs are the PROJECT's, which is where its saves land.
112
71
  const reads = withProjectFlows(deps, options.sessionId);
113
72
  // No journey named: plan the drive first. The platform's Harness proposes the people worth being;
@@ -116,36 +75,56 @@ export async function exploreApp(deps, env, options = {}) {
116
75
  const before = new Set(await reads.flows.list());
117
76
  // Without a named journey the drive is always planned; with one, it is planned by the platform
118
77
  // when there is one, and driven here as before when there is not.
119
- if (options.focus === undefined || serverOptionsFromEnv(env) !== undefined) {
78
+ if (options.focus === undefined ||
79
+ options.planId !== undefined ||
80
+ serverOptionsFromEnv(env) !== undefined) {
120
81
  const scripted = await exploreScript(deps, env, options, before);
82
+ // Where the person opens it: the run, and the plan the dashboard keeps and runs again.
121
83
  if (scripted !== undefined)
122
- return scripted;
84
+ return {
85
+ ...scripted,
86
+ ...runUrlFor(deps, options.sessionId, scripted.runIds?.[0]),
87
+ ...planUrlFor(deps, options.sessionId, scripted.planId),
88
+ };
123
89
  }
124
90
  const maxSteps = options.maxSteps ?? maxStepsFromEnv(env);
125
91
  // `.reticle` FIRST, before the app and before anything reads a line of source. It already holds
126
92
  // every saved flow, the consequence that must hold for each, and the declared intent nobody has
127
93
  // tested — which is the whole of what a drive should be deciding against.
128
94
  const plan = await readPlan(reads, options.sessionId);
129
- const driving = withoutReplays(plan);
130
- const built = options.driver === undefined
131
- ? buildDriver(env, maxSteps, driving, options.driverName, options.focus)
132
- : { driver: options.driver, name: CUSTOM_DRIVER_NAME };
133
- const driver = built.driver;
95
+ const driving = drivingPlan(plan, options.focus);
96
+ // Refused before anything touches the app: an unknown driver, or no platform to drive with.
97
+ if (options.driver === undefined)
98
+ buildDriver(env, maxSteps, driving, options.driverName, options.focus);
134
99
  // Every action this drive takes carries who took it, so the run it folds into is the Harness's own
135
100
  // and not mixed into the run of whichever agent shares the tab.
136
- const harnessId = randomUUID();
101
+ const harnessId = options.harnessId ?? randomUUID();
102
+ const driverLabel = options.driver === undefined ? SERVER_DRIVER : CUSTOM_DRIVER_NAME;
137
103
  const toolset = reticleToolset(deps, {
138
104
  ...pinned(options),
139
105
  drivenBy: {
140
106
  harness: harnessId,
141
- driver: built.name,
107
+ driver: driverLabel,
142
108
  ...(options.focus === undefined ? {} : { persona: options.focus }),
143
109
  },
110
+ ...(options.focus === undefined ? {} : { asked: options.focus }),
144
111
  });
145
112
  const narrate = narrator(deps, options);
146
- narrate(`Harness is driving${options.focus === undefined ? '' : `: ${options.focus}`}`);
113
+ const invoke = (name, args) => toolset.invoke(name, args);
114
+ // Map first: survey the app (no model) unless this app's map is fresh, and leave the tab at start.
115
+ const map = await siteMapFor(deps, options.sessionId, invoke);
116
+ const built = options.driver === undefined
117
+ ? buildDriver(env, maxSteps, driving, options.driverName, options.focus, undefined, map)
118
+ : { driver: options.driver, name: CUSTOM_DRIVER_NAME };
119
+ const driver = built.driver;
120
+ // Read before anything is driven: a goal this page already shows proves nothing at the end.
121
+ const opening = await readOpening(invoke);
122
+ narrate(`Harness is driving${options.focus === undefined ? '' : `: ${options.focus}`}`, true);
123
+ const driveStarted = deps.now();
147
124
  const drive = await runHarness(driver, toolset, {
125
+ ...steering(options),
148
126
  maxSteps,
127
+ routes: knownRoutes(map),
149
128
  // The plan rides in as standing instruction, so it is in front of the model on every turn
150
129
  // rather than remembered from a first one. `focus` is the caller's own words and goes last:
151
130
  // somebody who named a journey meant that journey, whatever the project's backlog says.
@@ -153,18 +132,48 @@ export async function exploreApp(deps, env, options = {}) {
153
132
  planAsText(driving),
154
133
  ...(options.focus === undefined ? [] : [`Focus: ${options.focus}`]),
155
134
  ].join('\n\n'),
135
+ // The end the caller's words quote stops the drive once it shows: see HarnessOptions.endsAt.
136
+ ...((end) => end === undefined || options.focus === undefined
137
+ ? {}
138
+ : { endsAt: { text: end, own: [options.focus] } })(endOf(options.focus ?? '')),
156
139
  });
140
+ // Before the session ends and is graded: a drive whose goal was missed, or that was cut off part-way,
141
+ // must not sync as "Proved" on the checks that held before it stopped.
142
+ noteHarnessGoal(harnessId, drive.goalMet);
157
143
  narrate(StopReason.STOPPED === drive.stopReason
158
144
  ? `Autonomous driving switched off — the Harness stopped after ${String(drive.steps)} steps. What it drove is kept.`
159
- : `Harness finished — ${verdictLine(checkTally(drive.toolCalls))}`);
145
+ : StopReason.BROKEN === drive.stopReason
146
+ ? msgDriveCutOff(drive.error)
147
+ : `Harness finished — ${verdictLine(checkTally(drive.toolCalls))}`, true);
160
148
  // MANDATORY, and deliberately outside the loop. A drive that runs out of budget mid-journey, or
161
149
  // breaks, or whose model simply stops asking for tools, leaves a recording open and everything it
162
150
  // drove unsaved — work paid for and thrown away. Saving is not a decision any model gets to make
163
151
  // and not something a step budget gets to cut off, so it happens here, after the loop, always.
164
- await bankOpenRecording(toolset, drive, options.focus);
165
- const goals = await checkGoals((name, args) => toolset.invoke(name, args), options.goals ?? goalsIn(options.focus));
152
+ const banked = await bankOpenRecording(toolset, drive, options.focus);
153
+ await refreshMap(deps, options.sessionId, map, drive.toolCalls);
154
+ // Hunt for the journey's end before grading: never a `no` from where the drive happened to stop.
155
+ const graded = await huntAndGrade(deps, invoke, {
156
+ sessionId: options.sessionId,
157
+ goals: options.goals ?? parseGoals(options.focus),
158
+ expect: options.expect,
159
+ opening,
160
+ journey: options.focus,
161
+ map,
162
+ reached: pagesReached(drive.toolCalls),
163
+ typed: typedValues(drive.toolCalls),
164
+ });
165
+ const goals = graded.goals;
166
+ noteHarnessDisparity(harnessId, graded.disparity);
167
+ // The goals it was given decide whether the journey was done, not a click that held on the way,
168
+ // and never the driver's word over a drive that did nothing.
169
+ const goalMet = goalOfDrive(drive.goalMet, goals, actedOnApp(drive.toolCalls));
170
+ noteHarnessGoal(harnessId, goalMet);
171
+ noteHarnessSpan(harnessId, deps.now() - driveStarted);
172
+ const unproved = unprovedGoals(goals);
173
+ if (unproved !== undefined)
174
+ narrate(unproved, true);
166
175
  const after = await reads.flows.list();
167
- const reconciled = reconcileFlows(before, after, drive.toolCalls);
176
+ const reconciled = reconcileFlows(before, after, [...drive.toolCalls, ...banked]);
168
177
  if (options.focus !== undefined) {
169
178
  await recordPersona(reads, [...reconciled.savedFlows, ...reconciled.rewroteFlows], options.focus);
170
179
  }
@@ -174,27 +183,80 @@ export async function exploreApp(deps, env, options = {}) {
174
183
  ]);
175
184
  const runId = harnessRunId(harnessId);
176
185
  return {
177
- drive,
186
+ // The hunt's navigations after the drive's own calls: they are the Harness driving the app too.
187
+ // After the goal is decided, which counts only what the drive itself did.
188
+ drive: {
189
+ ...drive,
190
+ toolCalls: [...drive.toolCalls, ...graded.moved],
191
+ ...(goalMet === undefined ? {} : { goalMet }),
192
+ },
178
193
  plan,
179
194
  driverName: built.name,
180
195
  ...reconciled,
181
196
  unverifiedFlows,
182
197
  goals,
198
+ ...(0 === graded.disparity.length ? {} : { disparity: graded.disparity }),
183
199
  ...(runId === undefined ? {} : { runIds: [runId] }),
200
+ ...runUrlFor(deps, options.sessionId, runId),
201
+ };
202
+ }
203
+ /** The stop and the words of whoever started the drive, for `runHarness`. */
204
+ export function steering(options) {
205
+ return {
206
+ ...(options.stopped === undefined ? {} : { stopped: options.stopped }),
207
+ ...(options.inbox === undefined ? {} : { inbox: options.inbox }),
184
208
  };
185
209
  }
186
210
  /** A line in the HUD's Agent Log for the person watching; nobody watching is not an error. */
187
211
  export function narrator(deps, options) {
188
- return (text) => {
212
+ return (text, summary = false) => {
213
+ // The drive's poll answers with its latest line, whether or not a tab is watching.
214
+ if (options.harnessId !== undefined)
215
+ noteDriveLine(options.harnessId, text);
189
216
  try {
190
- deps.sessions.resolve(options.sessionId).pushNarration(text);
217
+ // Filed in the HUD's Harness log; its start and end lines in the Agent Log too.
218
+ deps.sessions
219
+ .resolve(options.sessionId)
220
+ .pushNarration(text, true, { harness: true, summary });
191
221
  }
192
222
  catch {
193
223
  /* nobody is watching: the drive still runs */
194
224
  }
195
225
  };
196
226
  }
197
- /** What this project's memory says must hold, in its own words. Nothing recorded is none. */
227
+ /** The plan's page on the dashboard, where it is edited and run again; nothing when unlinked. */
228
+ function planUrlFor(deps, sessionId, planId) {
229
+ if (planId === undefined)
230
+ return {};
231
+ try {
232
+ const root = sessionRoot(deps, sessionId);
233
+ const dashboard = readDashboardUrl(root);
234
+ return dashboard === undefined
235
+ ? {}
236
+ : {
237
+ planUrl: dashboardPlanUrl({
238
+ dashboardUrl: dashboard,
239
+ planId,
240
+ projectId: readLinkedProjectId(root),
241
+ }),
242
+ };
243
+ }
244
+ catch {
245
+ return {};
246
+ }
247
+ }
248
+ /** The run's page on the dashboard, when the tab's project is linked; nothing when it is not. */
249
+ function runUrlFor(deps, sessionId, runId) {
250
+ if (runId === undefined)
251
+ return {};
252
+ try {
253
+ const dashboard = readDashboardUrl(sessionRoot(deps, sessionId));
254
+ return dashboard === undefined ? {} : { runUrl: dashboardRunUrl(dashboard, runId) };
255
+ }
256
+ catch {
257
+ return {}; // no tab, no project: the run is still reported, without a link
258
+ }
259
+ }
198
260
  export async function productRules(deps, sessionId) {
199
261
  try {
200
262
  return (await allSessionIntents(deps, sessionId)).map((intent) => intent.statement);
@@ -293,69 +355,30 @@ export function reconcileFlows(before, after, toolCalls) {
293
355
  return 'string' === typeof flowName ? flowName : undefined;
294
356
  })
295
357
  .filter((name) => name !== undefined && present.has(name));
358
+ // Only what this drive's own saves wrote: a before/after diff of the project's flows claimed the
359
+ // flows other agents saved in the same project at the same time.
296
360
  return {
297
- savedFlows: after.filter((name) => !before.has(name)),
361
+ savedFlows: [...new Set(claimed.filter((name) => !before.has(name)))],
298
362
  rewroteFlows: [...new Set(claimed.filter((name) => before.has(name)))],
299
363
  };
300
364
  }
301
365
  /**
302
- * What a person said about autonomous driving on the platform, honoured here.
303
- *
304
- * The switch existed, persisted and round-tripped, and the daemon read it and threw it away — so
305
- * turning the harness OFF changed a value in a database and nothing else. A control that does not
306
- * control anything is worse than no control: somebody turns it off, watches Reticle drive their app
307
- * anyway, and now correctly distrusts every other switch in the product.
308
- *
309
- * Absent means ON. The platform's own default is on, and a machine that cannot reach the platform —
310
- * offline, CI, no link — must not silently lose a feature it was never told to stop using.
311
- */
312
- export const MSG_HARNESS_DISABLED = 'Autonomous driving is turned OFF for this project. Turn it back on in the Reticle dashboard ' +
313
- '(Settings → Verification model), or drive the app yourself through the MCP tools.';
314
- /**
315
- * The other reason a drive can be refused, and it is NOT the same reason.
316
- *
317
- * A drive through the platform spends Reticle's model budget, bounded by the workspace's monthly
318
- * Harness credits. The platform answers this only when something other than the switch stops it.
366
+ * Why a drive must not be replayed into a verdict, or undefined when it may. A drive the platform
367
+ * cut off (credits gone: 402 needs_card) had saved one partial flow, and replaying it printed PASS
368
+ * with no word about the credits. The one test both CLI explore paths answer through.
319
369
  */
320
- export const MSG_HARNESS_UNCLAIMED = 'The Reticle platform says this workspace cannot drive the Harness right now. Every workspace, ' +
321
- 'Free included, gets Harness credits each month: see Settings → Plan in the Reticle dashboard.';
322
- /** The platform could not be asked, and the drive would spend Reticle's budget without its yes. */
323
- export const MSG_HARNESS_UNCONFIRMED = 'Could not confirm Harness access with the Reticle platform, so the drive did not start. Try ' +
324
- 'again in a moment.';
325
- /** One read, however many questions are asked of the answer. */
326
- function platformConfig(env, options) {
327
- return options.configFetch === undefined
328
- ? fetchPlatformConfig(env)
329
- : fetchPlatformConfig(env, options.configFetch);
330
- }
331
- /**
332
- * The reason this drive must not start, or `undefined` to go ahead.
333
- *
334
- * A drive on somebody's OWN model key never waits on the platform beyond the off switch: their key,
335
- * their spend. A drive through the platform proxy bills Reticle, and that one needs a confirmed yes
336
- * — enabled, entitled, and a model ready. It used to fail open: `fetchPlatformConfig` answers
337
- * `undefined` on a network error, a non-2xx, a body that does not parse, or a two-second timeout,
338
- * and all four read as "carry on", so a slow second on a settings endpoint let an unentitled
339
- * workspace drive on Reticle's budget. Now the same silence refuses with a message that says to
340
- * retry or bring a key. Fields an older platform omits still default to yes inside
341
- * `fetchPlatformConfig`; only an answer that never arrived is a no.
342
- */
343
- export async function refusedByPlatform(env, options) {
344
- if (true === options.skipPlatformConfig)
370
+ export function cutOffReason(drive) {
371
+ if (StopReason.BROKEN !== drive.stopReason && StopReason.STOPPED !== drive.stopReason)
345
372
  return undefined;
346
- // No platform, no Harness: it runs there, on the workspace's credits.
347
- if (serverOptionsFromEnv(env) === undefined)
348
- return MSG_NO_HARNESS_KEY;
349
- const config = await platformConfig(env, options);
350
- // It needs a confirmed yes, not the absence of a no. The platform also checks on every turn.
351
- if (config === undefined)
352
- return MSG_HARNESS_UNCONFIRMED;
353
- if (!config.harnessEnabled)
354
- return MSG_HARNESS_DISABLED;
355
- if (!config.harnessEntitled)
356
- return MSG_HARNESS_UNCLAIMED;
357
- return undefined;
373
+ const why = 'string' === typeof drive.error && 0 < drive.error.length
374
+ ? drive.error
375
+ : StopReason.STOPPED === drive.stopReason
376
+ ? 'autonomous driving was switched off.'
377
+ : 'the drive broke.';
378
+ return `The drive stopped before it finished: ${why} Nothing was proved; what it saved stays, and the next run replays it.`;
358
379
  }
380
+ /** The Agent Log's last line for a drive the platform cut off: its reason, and that it proved nothing. */
381
+ export const msgDriveCutOff = (error) => `Harness stopped before it finished, so nothing is proved: ${error ?? 'the drive broke.'}`;
359
382
  /**
360
383
  * Close and save whatever recording the drive left open.
361
384
  *
@@ -374,25 +397,28 @@ export async function refusedByPlatform(env, options) {
374
397
  * It used to be "Autonomous drive of X, banked after the run ended" whatever the caller asked for,
375
398
  * so a replay could never say which journey the flow was meant to prove.
376
399
  */
377
- export function bankedIntent(persona, open) {
378
- const named = persona?.trim();
400
+ export function bankedIntent(persona, open,
401
+ /** The journey the drive was for, when no persona was named. */
402
+ journey) {
403
+ const named = (persona ?? journey)?.trim();
379
404
  return named !== undefined && 0 < named.length
380
405
  ? named
381
- : `Autonomous drive of ${open}, banked after the run ended.`;
406
+ : `Exploring the app, recorded as ${open} and saved after the run ended.`;
382
407
  }
383
- export async function bankOpenRecording(toolset, drive, persona) {
408
+ export async function bankOpenRecording(toolset, drive, persona, journey) {
384
409
  const open = openRecordingName(drive.toolCalls);
385
410
  if (open === undefined)
386
- return;
411
+ return [];
412
+ const args = { flowName: open, intent: bankedIntent(persona, open, journey) };
387
413
  try {
388
414
  await toolset.invoke(ReticleTool.RECORD, { action: 'stop', recordingName: open });
389
- await toolset.invoke(ReticleTool.FLOW_SAVE, {
390
- flowName: open,
391
- intent: bankedIntent(persona, open),
392
- });
415
+ const result = await toolset.invoke(ReticleTool.FLOW_SAVE, args);
416
+ // Returned so the save is this drive's own, as a save the model made is.
417
+ return [{ id: 'bank', name: ReticleTool.FLOW_SAVE, args, result, isError: false }];
393
418
  }
394
419
  catch {
395
420
  /* last chance, not a checkpoint */
421
+ return [];
396
422
  }
397
423
  }
398
424
  /** The recording started and never stopped, if there is one. Exported because it is the decision. */
@@ -458,7 +484,9 @@ export function pinned(options) {
458
484
  */
459
485
  export function buildDriver(env, maxSteps, plan, requested, persona,
460
486
  /** A goal driven with no persona: it names the drive's flows as a persona would. */
461
- journey) {
487
+ journey,
488
+ /** The survey of the app, which the platform's engine looks goals up in. */
489
+ siteMap) {
462
490
  if (requested !== undefined && SERVER_DRIVER !== requested)
463
491
  throw new Error(msgUnknownDriver(requested));
464
492
  const platform = serverOptionsFromEnv(env);
@@ -473,6 +501,9 @@ journey) {
473
501
  planSteps: plan.steps,
474
502
  vocabulary: plan.vocabulary,
475
503
  maxSteps,
504
+ ...(siteMap === undefined ? {} : { siteMap: mapForPlatform(siteMap) }),
505
+ // Secret fields fill from the drive's own env: a persona's credentials ride in it.
506
+ env,
476
507
  }),
477
508
  name: SERVER_DRIVER,
478
509
  };