@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
@@ -7,83 +7,35 @@
7
7
  * nothing grades) but the flows that now exist on disk, because every future run replays those
8
8
  * deterministically with no model in the loop at all.
9
9
  */
10
- import { ReticleEnv, ReticleTool, cloudUrlFrom, asRecord } from '@reticlehq/core';
10
+ import { serverDriver, serverOptionsFromEnv } from '../../features/harness/platform/server-driver.js';
11
+ import { exploreScript } from './harness-script.js';
12
+ import { randomUUID } from 'node:crypto';
13
+ import { harnessRunId, noteHarnessDisparity, noteHarnessGoal, noteHarnessSpan, } from '../../judgement/runs/drive-run.js';
14
+ import { ReticleEnv, ReticleTool, asProjectId, asRecord } from '@reticlehq/core';
15
+ import { flowsForSession } from '../../language/flows/flow-store-for-session.js';
11
16
  import { projectForRoot } from '../../memory/project/project-for-root.js';
12
- import { harnessDriver, harnessOptionsFromEnv, } from '../../features/harness/driver.js';
13
- import { fillValues } from '../../features/harness/fill-values.js';
14
- import { openFillValues } from '../../memory/project/dir/fill-value-store.js';
15
- import { ANTHROPIC_DRIVER_NAME, CUSTOM_DRIVER_NAME, DRIVER_NAMES, JEV_DRIVER_NAME, OPENAI_DRIVER_NAME, } from '../../features/harness/drivers.js';
16
- import { jevDriver, jevOptionsFromEnv } from '../../features/harness/jev-driver.js';
17
+ import { actedOnApp, checkTally, pagesReached, typedValues, verdictLine, } from '../../features/harness/drive-report.js';
18
+ import { CUSTOM_DRIVER_NAME, SERVER_DRIVER } from '../../features/harness/drivers.js';
17
19
  import { buildDomainModel } from '../../judgement/domain/domain-model.js';
18
20
  import { readContract } from '../../memory/project/dir/reticle-dir.js';
19
- import { sessionRoot } from '../../memory/project/session-root.js';
20
- import { buildHarnessPlan, planAsText } from './harness-plan.js';
21
- import { openAiDriver, openAiOptionsFromEnv, } from '../../features/harness/openai-driver.js';
22
- import { fetchPlatformConfig } from '../../features/harness/platform-config.js';
23
- import { DEFAULT_MAX_STEPS, runHarness, } from '../../features/harness/harness.js';
21
+ import { sessionRoot, sessionTarget } from '../../memory/project/session-root.js';
22
+ import { dashboardPlanUrl, dashboardRunUrl, readDashboardUrl, readLinkedProjectId, } from '../../memory/project/sync-status.js';
23
+ import { buildHarnessPlan, drivingPlan, planAsText } from './harness-plan.js';
24
+ import { allSessionIntents } from '../../memory/intent/open-intents.js';
25
+ import { DEFAULT_MAX_STEPS, runHarness, StopReason, } from '../../features/harness/harness.js';
24
26
  import { reticleToolset } from './harness-toolset.js';
25
- import { secretEnvKey } from '../../language/flows/flows.js';
26
- /**
27
- * Why the harness is unavailable, phrased as the way to make it available.
28
- *
29
- * A missing key is a configuration fact, not a fault, and the sentence a user reads has to tell them
30
- * the one thing to do about it. Named here because both the CLI and the honest no-flows refusal
31
- * print it, and two copies of this sentence would drift.
32
- */
33
- export const MSG_NO_HARNESS_KEY = `No model configured to drive the app: set ${ReticleEnv.HARNESS_KEY}, or run \`reticle link\` and ` +
34
- `set ${ReticleEnv.CLOUD_KEY}, to let Reticle explore it for you. Without either, flows are ` +
35
- `recorded by your own coding agent through the MCP tools.`;
36
- /** Asked for Jev specifically and it is not configured. Distinct from having no model at all. */
37
- export const MSG_NO_JEV_KEY = `The \`${JEV_DRIVER_NAME}\` driver was asked for but is not configured: set ` +
38
- `${ReticleEnv.HARNESS_JEV_KEY}, or run \`reticle link\` and set ${ReticleEnv.CLOUD_KEY}. ` +
39
- `Refusing rather than quietly driving with another model, which would misattribute the result.`;
40
- /** Asked for OpenAI specifically and it is not configured. Never substituted, same as Jev. */
41
- export const MSG_NO_OPENAI_KEY = `The \`${OPENAI_DRIVER_NAME}\` driver was asked for but is not configured: set ` +
42
- `${ReticleEnv.HARNESS_OPENAI_KEY}, or run \`reticle link\` and set ${ReticleEnv.CLOUD_KEY}. ` +
43
- `Refusing rather than quietly driving with another model, which would misattribute the result.`;
44
- const msgUnknownDriver = (asked) => `Unknown harness driver \`${asked}\`. Known drivers: ${DRIVER_NAMES.join(', ')}.`;
45
- /**
46
- * The environment, plus the credential this machine already has.
47
- *
48
- * `reticle link` mints a project-scoped key and files it in `~/.reticle/credentials.json`; the CLI
49
- * has read it from there for as long as it has existed. The harness did not, and read only
50
- * `process.env` — so somebody who had signed in, linked their project and been told they were
51
- * connected still got "no model configured to drive the app", and the only way out was to find the
52
- * key in the console and export it by hand. Five manual steps to reach a feature they had already
53
- * finished setting up.
54
- *
55
- * Resolved into the env rather than threaded through four call sites: the drivers and the
56
- * preference lookup all read an env record, and giving them a completed one leaves each of them
57
- * exactly as simple as it was. The key precedence is the resolver's, the same as sync's and the
58
- * CLI's: the stored key for the link's host, else the exported one (which is how CI, with no
59
- * keystore, gets here). An explicitly exported HOST still wins, so a proxy is not overridden.
60
- *
61
- * The credential arrives through `deps.linkedCloud`, a port, because resolving it here would make
62
- * the tool surface reach into `memory/cloud` — a reach the directory guard refused, correctly.
63
- */
64
- export async function withLinkedCredential(deps, env) {
65
- try {
66
- const linked = await deps.linkedCloud?.();
67
- if (linked === undefined || null === linked)
68
- return env;
69
- return {
70
- ...env,
71
- [ReticleEnv.API_KEY]: linked.apiKey,
72
- [ReticleEnv.CLOUD_URL]: cloudUrlFrom(env) ?? linked.url,
73
- };
74
- }
75
- catch {
76
- // A credential store that cannot be read is "not linked", not an error. The harness is optional
77
- // and its absence is a routine answer; a drive must never fail because a JSON file was odd.
78
- return env;
79
- }
80
- }
81
- /** Is there a model the harness can drive with? A read, because "not configured" is not a failure. */
82
- export function harnessAvailable(env) {
83
- return (harnessOptionsFromEnv(env) !== undefined ||
84
- jevOptionsFromEnv(env) !== undefined ||
85
- openAiOptionsFromEnv(env) !== undefined);
86
- }
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';
36
+ /** A driver named that this build no longer has: every Harness decision is the platform's now. */
37
+ const msgUnknownDriver = (asked) => `The Harness driver \`${asked}\` is not available: the Harness runs on the Reticle platform, ` +
38
+ `which drives with the model set for the project in the dashboard.`;
87
39
  /**
88
40
  * Read the step ceiling out of the environment.
89
41
  *
@@ -106,52 +58,272 @@ export function maxStepsFromEnv(env) {
106
58
  * that says it saved a flow and did not is the same false green as an app that says it saved a
107
59
  * record and did not — and this product does not get to make that mistake about its own work.
108
60
  */
109
- export async function exploreApp(deps, env, options = {}) {
110
- 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);
111
68
  if (refusal !== undefined)
112
- throw new Error(refusal);
69
+ throw new DriveRefusedError(refusal);
70
+ // The flows a drive reads and diffs are the PROJECT's, which is where its saves land.
71
+ const reads = withProjectFlows(deps, options.sessionId);
72
+ // No journey named: plan the drive first. The platform's Harness proposes the people worth being;
73
+ // the saved flows, the user's request and the unproved intents fill in the rest. The plan is drawn
74
+ // on the HUD and updated as each part runs.
75
+ const before = new Set(await reads.flows.list());
76
+ // Without a named journey the drive is always planned; with one, it is planned by the platform
77
+ // when there is one, and driven here as before when there is not.
78
+ if (options.focus === undefined ||
79
+ options.planId !== undefined ||
80
+ serverOptionsFromEnv(env) !== undefined) {
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.
83
+ if (scripted !== undefined)
84
+ return {
85
+ ...scripted,
86
+ ...runUrlFor(deps, options.sessionId, scripted.runIds?.[0]),
87
+ ...planUrlFor(deps, options.sessionId, scripted.planId),
88
+ };
89
+ }
113
90
  const maxSteps = options.maxSteps ?? maxStepsFromEnv(env);
114
- const before = new Set(await deps.flows.list());
115
91
  // `.reticle` FIRST, before the app and before anything reads a line of source. It already holds
116
92
  // every saved flow, the consequence that must hold for each, and the declared intent nobody has
117
93
  // tested — which is the whole of what a drive should be deciding against.
118
- const plan = await readPlan(deps, options.sessionId);
119
- /*
120
- * The fixtures this project has already paid for.
121
- *
122
- * A drive is a sequence of DECISIONS and, occasionally, one COMPOSITION: what to type into a box
123
- * whose label nothing can guess from. The cheap driver cannot write a string at all, so those
124
- * boxes used to receive the words "reticle harness". This is the seam where a generating model
125
- * answers instead -- for about 6% of steps, once per label, and never again on any later drive,
126
- * because the answer is written into `.reticle` beside the flows that use it.
127
- */
128
- const fills = await openFillValues(deps.fs, safeRoot(deps, options.sessionId));
129
- const requested = options.driverName ?? env[ReticleEnv.HARNESS_DRIVER] ?? (await preferredDriver(env, options));
94
+ const plan = await readPlan(reads, options.sessionId);
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);
99
+ // Every action this drive takes carries who took it, so the run it folds into is the Harness's own
100
+ // and not mixed into the run of whichever agent shares the tab.
101
+ const harnessId = options.harnessId ?? randomUUID();
102
+ const driverLabel = options.driver === undefined ? SERVER_DRIVER : CUSTOM_DRIVER_NAME;
103
+ const toolset = reticleToolset(deps, {
104
+ ...pinned(options),
105
+ drivenBy: {
106
+ harness: harnessId,
107
+ driver: driverLabel,
108
+ ...(options.focus === undefined ? {} : { persona: options.focus }),
109
+ },
110
+ ...(options.focus === undefined ? {} : { asked: options.focus }),
111
+ });
112
+ const narrate = narrator(deps, options);
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);
130
116
  const built = options.driver === undefined
131
- ? buildDriver(env, maxSteps, plan, requested, fills)
117
+ ? buildDriver(env, maxSteps, driving, options.driverName, options.focus, undefined, map)
132
118
  : { driver: options.driver, name: CUSTOM_DRIVER_NAME };
133
119
  const driver = built.driver;
134
- const toolset = reticleToolset(deps, pinned(options));
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();
135
124
  const drive = await runHarness(driver, toolset, {
125
+ ...steering(options),
136
126
  maxSteps,
127
+ routes: knownRoutes(map),
137
128
  // The plan rides in as standing instruction, so it is in front of the model on every turn
138
129
  // rather than remembered from a first one. `focus` is the caller's own words and goes last:
139
130
  // somebody who named a journey meant that journey, whatever the project's backlog says.
140
131
  focus: [
141
- planAsText(plan),
132
+ planAsText(driving),
142
133
  ...(options.focus === undefined ? [] : [`Focus: ${options.focus}`]),
143
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 ?? '')),
144
139
  });
145
- // Written once, after the drive, whatever the drive did: a run that broke still learned what it
146
- // learned, and the next one should not pay for it again.
147
- await fills.flush();
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);
143
+ narrate(StopReason.STOPPED === drive.stopReason
144
+ ? `Autonomous driving switched off — the Harness stopped after ${String(drive.steps)} steps. What it drove is kept.`
145
+ : StopReason.BROKEN === drive.stopReason
146
+ ? msgDriveCutOff(drive.error)
147
+ : `Harness finished — ${verdictLine(checkTally(drive.toolCalls))}`, true);
148
148
  // MANDATORY, and deliberately outside the loop. A drive that runs out of budget mid-journey, or
149
149
  // breaks, or whose model simply stops asking for tools, leaves a recording open and everything it
150
150
  // drove unsaved — work paid for and thrown away. Saving is not a decision any model gets to make
151
151
  // and not something a step budget gets to cut off, so it happens here, after the loop, always.
152
- await bankOpenRecording(toolset, drive);
153
- const after = await deps.flows.list();
154
- return { drive, plan, driverName: built.name, ...reconcileFlows(before, after, drive.toolCalls) };
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);
175
+ const after = await reads.flows.list();
176
+ const reconciled = reconcileFlows(before, after, [...drive.toolCalls, ...banked]);
177
+ if (options.focus !== undefined) {
178
+ await recordPersona(reads, [...reconciled.savedFlows, ...reconciled.rewroteFlows], options.focus);
179
+ }
180
+ const unverifiedFlows = await flowsThatCheckNothing(reads, [
181
+ ...reconciled.savedFlows,
182
+ ...reconciled.rewroteFlows,
183
+ ]);
184
+ const runId = harnessRunId(harnessId);
185
+ return {
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
+ },
193
+ plan,
194
+ driverName: built.name,
195
+ ...reconciled,
196
+ unverifiedFlows,
197
+ goals,
198
+ ...(0 === graded.disparity.length ? {} : { disparity: graded.disparity }),
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 }),
208
+ };
209
+ }
210
+ /** A line in the HUD's Agent Log for the person watching; nobody watching is not an error. */
211
+ export function narrator(deps, options) {
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);
216
+ try {
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 });
221
+ }
222
+ catch {
223
+ /* nobody is watching: the drive still runs */
224
+ }
225
+ };
226
+ }
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
+ }
260
+ export async function productRules(deps, sessionId) {
261
+ try {
262
+ return (await allSessionIntents(deps, sessionId)).map((intent) => intent.statement);
263
+ }
264
+ catch {
265
+ return [];
266
+ }
267
+ }
268
+ /** `deps` whose flow store is the session's own project, where the drive's saves land. */
269
+ export function withProjectFlows(deps, sessionId) {
270
+ try {
271
+ return { ...deps, flows: flowsForSession(deps, sessionTarget(deps, sessionId)).flows };
272
+ }
273
+ catch {
274
+ return deps;
275
+ }
276
+ }
277
+ /**
278
+ * Write the persona onto every flow the drive saved or rewrote without an intent.
279
+ *
280
+ * Whichever driver saved it, and in whatever words: the cheap driver's own teardown saved its flow
281
+ * with no intent at all, so a replay could never say which journey it was meant to prove. A flow
282
+ * that already carries an intent keeps it. Best effort: a flow that cannot be read or rewritten is
283
+ * still a saved flow.
284
+ */
285
+ export async function recordPersona(deps, names, persona) {
286
+ // Only the journey itself, "Name: journey": the plan appends the product's rules below it, and
287
+ // keeping them made each plan append them again to a goal that already carried them.
288
+ const intent = (persona.split('\n')[0] ?? '').trim();
289
+ if (0 === intent.length)
290
+ return;
291
+ for (const name of names) {
292
+ try {
293
+ const loaded = await deps.flows.load(name);
294
+ if (!loaded.ok || (loaded.value.intent ?? '').length > 0)
295
+ continue;
296
+ // Its own project: without it the store files a flat duplicate beside the original.
297
+ const project = loaded.value.projectId;
298
+ await deps.flows.saveFlow({ ...loaded.value, intent }, project === undefined ? undefined : asProjectId(project));
299
+ }
300
+ catch {
301
+ /* the flow stays as it was saved */
302
+ }
303
+ }
304
+ }
305
+ /**
306
+ * The saved flows with no step that asserts a consequence.
307
+ *
308
+ * Such a flow replays as "verified nothing": it clicks through the journey and would pass with the
309
+ * feature broken. Named so the drive's report does not count it as evidence. A flow that cannot be
310
+ * read is left out rather than guessed at.
311
+ */
312
+ export async function flowsThatCheckNothing(deps, names) {
313
+ const empty = [];
314
+ for (const name of names) {
315
+ try {
316
+ const loaded = await deps.flows.load(name);
317
+ if (!loaded.ok)
318
+ continue;
319
+ if (!loaded.value.steps.some((step) => step.expect !== undefined))
320
+ empty.push(name);
321
+ }
322
+ catch {
323
+ /* unreadable is not the same as empty */
324
+ }
325
+ }
326
+ return empty;
155
327
  }
156
328
  /**
157
329
  * What a drive actually left behind, split into flows that are NEW and flows it wrote over.
@@ -183,117 +355,30 @@ export function reconcileFlows(before, after, toolCalls) {
183
355
  return 'string' === typeof flowName ? flowName : undefined;
184
356
  })
185
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.
186
360
  return {
187
- savedFlows: after.filter((name) => !before.has(name)),
361
+ savedFlows: [...new Set(claimed.filter((name) => !before.has(name)))],
188
362
  rewroteFlows: [...new Set(claimed.filter((name) => before.has(name)))],
189
363
  };
190
364
  }
191
365
  /**
192
- * The driver this project chose on the platform, if it chose one, we can reach it, and we have it.
193
- *
194
- * Only asked when nobody has been explicit, so the cost is paid exactly once per drive and never on
195
- * a path where it could not change the answer. An unreachable platform returns undefined and the
196
- * environment decides, exactly as it did before this lookup existed.
197
- *
198
- * A preference naming a driver this build does not have is IGNORED rather than refused, and that
199
- * asymmetry with the per-call argument is deliberate. The platform offers providers this daemon may
200
- * be too old to know about — it already offers `openai`, which has no binding here — so a stored
201
- * preference is a statement about the account, not an instruction for this drive, and a daemon that
202
- * refused to run because a web UI knew one more word than it does would be broken by its own
203
- * upgrade cycle. Naming a driver in the CALL is an instruction, and an unknown one is still an
204
- * error there.
205
- *
206
- * It is not a silent substitution either way: the result reports the driver that actually drove.
207
- */
208
- async function preferredDriver(env, options) {
209
- if (true === options.skipPlatformConfig)
210
- return undefined;
211
- return knownDriver((await platformConfig(env, options))?.provider);
212
- }
213
- /**
214
- * What a person said about autonomous driving on the platform, honoured here.
215
- *
216
- * The switch existed, persisted and round-tripped, and the daemon read it and threw it away — so
217
- * turning the harness OFF changed a value in a database and nothing else. A control that does not
218
- * control anything is worse than no control: somebody turns it off, watches Reticle drive their app
219
- * anyway, and now correctly distrusts every other switch in the product.
220
- *
221
- * Absent means ON. The platform's own default is on, and a machine that cannot reach the platform —
222
- * offline, CI, no link — must not silently lose a feature it was never told to stop using.
223
- */
224
- export const MSG_HARNESS_DISABLED = 'Autonomous driving is turned OFF for this project. Turn it back on in the Reticle dashboard ' +
225
- '(Settings → Verification model), or drive the app yourself through the MCP tools.';
226
- /**
227
- * The other reason a drive can be refused, and it is NOT the same reason.
228
- *
229
- * A drive through the platform spends Reticle's model budget. That is free for three months and
230
- * included on a paid plan, and outside both it is somebody else's money being spent on nothing. The
231
- * message says which of the two it is and what to do, because "the harness is off" told to a person
232
- * who never turned anything off is a support ticket rather than an answer.
233
- */
234
- export const MSG_HARNESS_UNCLAIMED = 'This workspace has no harness entitlement, so autonomous driving would run on Reticle’s model ' +
235
- 'budget with nothing paying for it. Claim the free 3 months in the Reticle dashboard, or export a ' +
236
- 'model API key of your own and drive with that.';
237
- /**
238
- * Whether a drive would be paid for by the person asking for it.
239
- *
240
- * Entitlement gates OUR spend, so it has no business stopping somebody who brought their own key:
241
- * their harness costs us nothing whether they ever claim anything or not. Reading the same options
242
- * the drivers read keeps the two answers from drifting apart.
243
- */
244
- function ownsAModelKey(env) {
245
- // The DIRECT variables only. Every driver also accepts the platform key as a fallback, so asking
246
- // `jevOptionsFromEnv` here would answer "they have a key" for exactly the person whose drive would
247
- // be billed to us — which is the one case this gate exists for.
248
- return [ReticleEnv.HARNESS_KEY, ReticleEnv.HARNESS_JEV_KEY, ReticleEnv.HARNESS_OPENAI_KEY].some((name) => {
249
- const value = env[name];
250
- return value !== undefined && 0 < value.length;
251
- });
252
- }
253
- /** One read, however many questions are asked of the answer. */
254
- function platformConfig(env, options) {
255
- return options.configFetch === undefined
256
- ? fetchPlatformConfig(env)
257
- : fetchPlatformConfig(env, options.configFetch);
258
- }
259
- /**
260
- * The reason this drive must not start, or `undefined` to go ahead.
261
- *
262
- * It FAILS OPEN, and that is worth stating plainly because the argument for it changed under it.
263
- * `fetchPlatformConfig` answers `undefined` on a network error, a non-2xx, a body that does not
264
- * parse, or a two-second timeout, and all four land here as "carry on". When this endpoint only
265
- * answered "which model does this project prefer", failing open cost nothing: the drive used the
266
- * environment and nobody was worse off. It now also answers "is anybody paying for this", and the
267
- * same silence means a drive runs on Reticle's model budget unmetered.
268
- *
269
- * Kept open anyway, deliberately: a settings endpoint having a slow second must not break somebody
270
- * mid-verification, and the exposure is one drive's worth of a very cheap model. But this is
271
- * best-effort, not enforcement -- if the spend needs a hard floor, it belongs at the proxy, which
272
- * is the only side that cannot be talked out of it by a dropped packet.
273
- */
274
- async function refusedByPlatform(env, options) {
275
- if (true === options.skipPlatformConfig)
276
- return undefined;
277
- const config = await platformConfig(env, options);
278
- if (config === undefined)
279
- return undefined;
280
- if (!config.harnessEnabled)
281
- return MSG_HARNESS_DISABLED;
282
- if (!config.harnessEntitled && !ownsAModelKey(env))
283
- return MSG_HARNESS_UNCLAIMED;
284
- return undefined;
285
- }
286
- /**
287
- * A stored preference, kept only if this build can actually honour it.
288
- *
289
- * Exported because it is the whole of the asymmetry with the per-call argument, and the asymmetry
290
- * is the part somebody will later think is a bug.
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.
291
369
  */
292
- export function knownDriver(provider) {
293
- if (provider === undefined)
370
+ export function cutOffReason(drive) {
371
+ if (StopReason.BROKEN !== drive.stopReason && StopReason.STOPPED !== drive.stopReason)
294
372
  return undefined;
295
- return DRIVER_NAMES.some((name) => name === provider) ? provider : 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.`;
296
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.'}`;
297
382
  /**
298
383
  * Close and save whatever recording the drive left open.
299
384
  *
@@ -306,19 +391,34 @@ export function knownDriver(provider) {
306
391
  * already closed the stop is refused and there is nothing to do, and a drive must not fail at the
307
392
  * finish line because the thing it was trying to rescue did not need rescuing.
308
393
  */
309
- async function bankOpenRecording(toolset, drive) {
394
+ /**
395
+ * What a banked recording says it was for: the persona the caller named, when there was one.
396
+ *
397
+ * It used to be "Autonomous drive of X, banked after the run ended" whatever the caller asked for,
398
+ * so a replay could never say which journey the flow was meant to prove.
399
+ */
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();
404
+ return named !== undefined && 0 < named.length
405
+ ? named
406
+ : `Exploring the app, recorded as ${open} and saved after the run ended.`;
407
+ }
408
+ export async function bankOpenRecording(toolset, drive, persona, journey) {
310
409
  const open = openRecordingName(drive.toolCalls);
311
410
  if (open === undefined)
312
- return;
411
+ return [];
412
+ const args = { flowName: open, intent: bankedIntent(persona, open, journey) };
313
413
  try {
314
414
  await toolset.invoke(ReticleTool.RECORD, { action: 'stop', recordingName: open });
315
- await toolset.invoke(ReticleTool.FLOW_SAVE, {
316
- flowName: open,
317
- intent: `Autonomous drive of ${open}, banked after the run ended.`,
318
- });
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 }];
319
418
  }
320
419
  catch {
321
420
  /* last chance, not a checkpoint */
421
+ return [];
322
422
  }
323
423
  }
324
424
  /** The recording started and never stopped, if there is one. Exported because it is the decision. */
@@ -345,14 +445,23 @@ export function openRecordingName(toolCalls) {
345
445
  * ordinary state of a new project and not a reason to refuse to drive — so it answers an empty
346
446
  * plan rather than throwing.
347
447
  */
348
- async function readPlan(deps, sessionId) {
448
+ export async function readFlows(deps) {
449
+ const flows = [];
349
450
  try {
350
- const flows = [];
351
451
  for (const name of await deps.flows.list()) {
352
452
  const loaded = await deps.flows.load(name);
353
453
  if (loaded.ok)
354
454
  flows.push(loaded.value);
355
455
  }
456
+ }
457
+ catch {
458
+ // An unreadable store plans from what it could read, as `readPlan` does.
459
+ }
460
+ return flows;
461
+ }
462
+ export async function readPlan(deps, sessionId) {
463
+ try {
464
+ const flows = await readFlows(deps);
356
465
  const root = sessionRoot(deps, sessionId);
357
466
  const contract = await readContract(deps.fs, root);
358
467
  const project = await projectForRoot(deps, root).read();
@@ -366,93 +475,36 @@ async function readPlan(deps, sessionId) {
366
475
  };
367
476
  }
368
477
  }
369
- /**
370
- * The project directory, or nothing.
371
- *
372
- * `sessionRoot` needs a session and a project to answer, and a drive can legitimately be asked for
373
- * before either is resolvable. Everything else that reads `.reticle` here already treats that as
374
- * "no project record" rather than as a failure; the fixtures file is no different, and a throw on
375
- * this path would turn a missing directory into a refused drive.
376
- */
377
- function safeRoot(deps, sessionId) {
378
- try {
379
- return sessionRoot(deps, sessionId);
380
- }
381
- catch {
382
- return undefined;
383
- }
384
- }
385
- function pinned(options) {
478
+ export function pinned(options) {
386
479
  return options.sessionId === undefined ? {} : { sessionId: options.sessionId };
387
480
  }
388
481
  /**
389
- * Pick the driver.
390
- *
391
- * The Anthropic driver stays the default, and an explicit `RETICLE_HARNESS_DRIVER=jev` is the only
392
- * thing that moves off it when both are configured — a driver change is a change in how the app gets
393
- * driven, and inferring one from which key happens to be exported would swap it under people who
394
- * merely linked their account.
395
- *
396
- * The fall-through is the other direction and is not a preference: with no Anthropic key and a
397
- * platform key present, Jev is not the cheaper option, it is the only one. Choosing it there is what
398
- * makes the harness work for somebody who never had a model API key of their own, which is most
399
- * people — and the reason this driver is worth having at all.
482
+ * The driver: the platform's Harness, which decides every step on its side while this machine
483
+ * executes. There is no other: the decisions, the models and the planning run only on the platform.
400
484
  */
401
- function buildDriver(env, maxSteps, plan, requested, fills) {
402
- // The two halves of what `.reticle` knows, handed to the one driver that can use both: what is
403
- // worth doing, and the names the app uses for what it does. The second is what lets a declared
404
- // consequence be SAVED rather than merely proved; see `consequencesFor`.
405
- const fromReticle = {
406
- plan: plan.steps,
407
- vocabulary: plan.vocabulary,
408
- /*
409
- * Generation is offered ONLY when a generating model is already configured, and it stays out of
410
- * the per-turn loop either way: put a text model on every turn and you pay its per-turn tax on
411
- * the 94% of steps that are clicks, which is the entire cost the cheap driver exists to avoid.
412
- * With no such key the label heuristic answers, exactly as it did before this existed.
413
- */
414
- fillValue: fillValues({
415
- secret: (label) => env[secretEnvKey(label)],
416
- ...(fills === undefined ? {} : { cache: fills }),
417
- // GPT first: a linked machine reaches it through the platform with no key of its own.
418
- ...(openAiOptionsFromEnv(env) === undefined
419
- ? {}
420
- : { openai: openAiOptionsFromEnv(env) }),
421
- ...(harnessOptionsFromEnv(env) === undefined
422
- ? {}
423
- : { generator: harnessOptionsFromEnv(env) }),
485
+ export function buildDriver(env, maxSteps, plan, requested, persona,
486
+ /** A goal driven with no persona: it names the drive's flows as a persona would. */
487
+ journey,
488
+ /** The survey of the app, which the platform's engine looks goals up in. */
489
+ siteMap) {
490
+ if (requested !== undefined && SERVER_DRIVER !== requested)
491
+ throw new Error(msgUnknownDriver(requested));
492
+ const platform = serverOptionsFromEnv(env);
493
+ if (platform === undefined)
494
+ throw new Error(MSG_NO_HARNESS_KEY);
495
+ return {
496
+ driver: serverDriver({
497
+ ...platform,
498
+ ...(persona === undefined ? {} : { persona }),
499
+ ...(journey === undefined ? {} : { journey }),
500
+ plan: planAsText(plan),
501
+ planSteps: plan.steps,
502
+ vocabulary: plan.vocabulary,
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,
424
507
  }),
508
+ name: SERVER_DRIVER,
425
509
  };
426
- const jev = jevOptionsFromEnv(env);
427
- const anthropic = harnessOptionsFromEnv(env);
428
- const asked = requested;
429
- // A driver that was ASKED for and is not configured is an error, never a substitution. Quietly
430
- // falling back would make every comparison between two drivers a possible lie about which one
431
- // produced the result — and comparing them is the main reason anyone names one.
432
- if (JEV_DRIVER_NAME === asked) {
433
- if (jev === undefined)
434
- throw new Error(MSG_NO_JEV_KEY);
435
- // The Jev driver is told the budget because it has a teardown to reach; the Anthropic driver is
436
- // not, because it calls `finish` itself and being handed a number it did not ask for is how a
437
- // second copy of the budget starts drifting from the loop's.
438
- return { driver: jevDriver({ ...jev, maxSteps, ...fromReticle }), name: JEV_DRIVER_NAME };
439
- }
440
- if (ANTHROPIC_DRIVER_NAME === asked) {
441
- if (anthropic === undefined)
442
- throw new Error(MSG_NO_HARNESS_KEY);
443
- return { driver: harnessDriver(anthropic), name: ANTHROPIC_DRIVER_NAME };
444
- }
445
- if (OPENAI_DRIVER_NAME === asked) {
446
- const openai = openAiOptionsFromEnv(env);
447
- if (openai === undefined)
448
- throw new Error(MSG_NO_OPENAI_KEY);
449
- return { driver: openAiDriver(openai), name: OPENAI_DRIVER_NAME };
450
- }
451
- if (asked !== undefined && 0 < asked.length)
452
- throw new Error(msgUnknownDriver(asked));
453
- if (anthropic !== undefined)
454
- return { driver: harnessDriver(anthropic), name: ANTHROPIC_DRIVER_NAME };
455
- if (jev !== undefined)
456
- return { driver: jevDriver({ ...jev, maxSteps, ...fromReticle }), name: JEV_DRIVER_NAME };
457
- throw new Error(MSG_NO_HARNESS_KEY);
458
510
  }