@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
@@ -8,15 +8,108 @@
8
8
  * Barriers cannot deadlock: a journey only waits on one in an EARLIER lane (`checkScript`), lanes
9
9
  * are started in order, so whatever is waited on has already started.
10
10
  */
11
- import { PredicateKind, ReplayStatus, ReticleTool, ScriptStatus, Verified, asRecord, } from '@reticlehq/core';
12
- import { ScriptStepKind, barriersOf, stepLabel, } from '@reticlehq/core/artifacts';
13
- import { checkTally } from '../drive-report.js';
14
- import { goalsIn } from '../goals.js';
11
+ import { PredicateKind, ReplayStatus, ReticleTool, ScriptStatus, Verified, asRecord, asString, } from '@reticlehq/core';
12
+ import { JourneyBy, JourneyOutcome, ScriptStepKind, barriersOf, stepLabel, } from '@reticlehq/core/artifacts';
13
+ import { ReplayOutcome, checkTally, replayedFlows } from '../drive-report.js';
14
+ import { endOf, lookFor } from '../goals.js';
15
15
  import { DEFAULT_MAX_STEPS, StopReason, } from '../harness.js';
16
16
  /** Why a journey failed when its goal, not a check, is what was missing. */
17
17
  const GOAL_NOT_REACHED = 'the goal was not reached, though its checks may have held';
18
18
  /** A planned open journey gets the same budget a named persona drive gets. */
19
19
  const OPEN_GOAL_STEPS = DEFAULT_MAX_STEPS;
20
+ /** Fewer model turns left than this and a continuation could not take the step it is sent for. */
21
+ const MIN_CONTINUE_STEPS = 3;
22
+ /** Why a journey whose replays decided nothing was handed to the model. */
23
+ const FELL_BACK = 'its replays decided nothing, so the model drove its goal';
24
+ /** A replay that neither held nor failed: drifted, unverifiable, or a flow not on this computer. */
25
+ const UNDECIDED_REPLAY = new Set([
26
+ ReplayOutcome.DRIFT,
27
+ ReplayOutcome.MISSING,
28
+ ReplayStatus.UNVERIFIABLE,
29
+ undefined,
30
+ ]);
31
+ /**
32
+ * The journey's replays decided nothing about the app: one could not anchor or run, and none failed.
33
+ * A held sign-in beside a drifted mid-session flow is not a failure of the app, and read "Failed".
34
+ */
35
+ function replaysDecidedNothing(calls) {
36
+ const replays = replayedFlows(calls);
37
+ return (replays.some((r) => UNDECIDED_REPLAY.has(r.status)) &&
38
+ !replays.some((r) => ReplayOutcome.ERROR === r.status));
39
+ }
40
+ /** Why a journey whose replay could not anchor or run is undecided, not failed. */
41
+ const msgReplayUndecided = (flow) => `the recording ${flow} could not anchor or run on this app, which decides nothing about the app`;
42
+ /** The flows a journey replayed or saved, each once, in the order it touched them. */
43
+ function flowsOf(calls) {
44
+ const names = calls.flatMap((call) => {
45
+ if (ReticleTool.FLOW_REPLAY === call.name)
46
+ return [asString(asRecord(call.args)['flowName'])];
47
+ if (ReticleTool.FLOW_SAVE !== call.name || call.isError)
48
+ return [];
49
+ const args = asRecord(call.args);
50
+ return [
51
+ asString(asRecord(call.result)['name']) ??
52
+ asString(args['saveAs']) ??
53
+ asString(args['flowName']),
54
+ ];
55
+ });
56
+ return [...new Set(names.filter((n) => n !== undefined))];
57
+ }
58
+ /** What a journey's own model drives cost, and what it touched. */
59
+ function journeyRun(id, calls, own) {
60
+ const credits = own.flatMap((d) => (d.creditsSpent === undefined ? [] : [d.creditsSpent]));
61
+ // Replayed only when it replayed: a model goal the end-already-shown guard stopped spent no
62
+ // tokens and was called "replayed, no model tokens" on a journey that had no replay at all.
63
+ const by = 0 < own.length
64
+ ? JourneyBy.MODEL
65
+ : 0 < replayedFlows(calls).length
66
+ ? JourneyBy.REPLAY
67
+ : undefined;
68
+ return {
69
+ id,
70
+ ...(by === undefined ? {} : { by }),
71
+ tokens: own.reduce((n, d) => n + d.usage.input + d.usage.output + d.usage.cacheRead + d.usage.cacheWrite, 0),
72
+ ...(0 === credits.length ? {} : { credits: credits.reduce((a, b) => a + b, 0) }),
73
+ flows: flowsOf([...calls, ...own.flatMap((d) => d.toolCalls)]),
74
+ };
75
+ }
76
+ /** Two lanes' runs of one journey, as one: the model's cost added, every flow kept. */
77
+ function mergeRuns(a, b) {
78
+ const credits = a.credits === undefined && b.credits === undefined
79
+ ? undefined
80
+ : (a.credits ?? 0) + (b.credits ?? 0);
81
+ const by = [JourneyBy.MODEL, JourneyBy.REPLAY].find((k) => k === a.by || k === b.by);
82
+ return {
83
+ id: a.id,
84
+ ...(by === undefined ? {} : { by }),
85
+ tokens: a.tokens + b.tokens,
86
+ ...(credits === undefined ? {} : { credits }),
87
+ flows: [...new Set([...a.flows, ...b.flows])],
88
+ };
89
+ }
90
+ /** How a journey was answered, as its line says it: only what was measured. */
91
+ function byText(run) {
92
+ if (run?.by === undefined)
93
+ return '';
94
+ return JourneyBy.REPLAY === run.by
95
+ ? ' · replayed, no model tokens'
96
+ : ` · driven by the model, ${String(run.tokens)} tokens`;
97
+ }
98
+ /** Why a journey whose end the page showed before it acted is not credited with it. */
99
+ const msgEndAlreadyShown = (end) => `"${end}" was already on the page before this journey acted, so reaching it proves nothing`;
100
+ /**
101
+ * Whether a journey picks up where the one before it in its lane left off: it builds on one there
102
+ * (`dependsOn`), or it looks at how one failed. Every other journey starts from the lane's start.
103
+ */
104
+ function continuesLane(journey, before) {
105
+ return (journey.dependsOn.some((id) => before.has(id)) ||
106
+ (journey.when !== undefined &&
107
+ JourneyOutcome.FAILED === journey.when.is &&
108
+ before.has(journey.when.journey)));
109
+ }
110
+ /** What a drive that stopped short of its end state is sent back with. */
111
+ const continueGoal = (goal, end) => `${goal}\n\nContinue from the page you are on: it does not show "${end}" yet. ` +
112
+ 'Take the next step this journey names; do not start over.';
20
113
  export async function runScript(script, ports, onChange = () => undefined) {
21
114
  const view = planView(script, Math.min(ports.parallel, script.maxParallel ?? ports.parallel));
22
115
  const toolCalls = [];
@@ -30,7 +123,8 @@ export async function runScript(script, ports, onChange = () => undefined) {
30
123
  /* the picture of a drive is never a reason to stop it */
31
124
  }
32
125
  };
33
- // A journey that sits in several lanes is answered by the FIRST lane holding it; barriers wait on that.
126
+ // A journey that sits in several lanes is answered by the FIRST lane holding it; barriers wait on
127
+ // that. It is answered with how it ended, because a condition can be waiting for a failure.
34
128
  const outcome = new Map();
35
129
  const firstLane = new Map();
36
130
  for (const lane of script.lanes) {
@@ -47,45 +141,134 @@ export async function runScript(script, ports, onChange = () => undefined) {
47
141
  /** Journeys whose checks may have held but whose goal the drive did not reach. */
48
142
  const goalMissed = new Set();
49
143
  const broken = new Map();
144
+ /** Per card, for its line; per id, for the platform. */
145
+ const runOf = new Map();
146
+ const runs = new Map();
50
147
  tell();
51
148
  const runLane = async (lane, laneIndex) => {
52
149
  const cards = view.lanes[laneIndex]?.journeys ?? [];
53
- const settleOwned = (id, ok) => {
150
+ const settleOwned = (id, status) => {
54
151
  if (firstLane.get(id) === lane.id)
55
- outcome.get(id)?.settle(ok);
152
+ outcome.get(id)?.settle(status);
56
153
  };
57
154
  let lease;
58
155
  let blocked = false;
156
+ /** Where the lane's first journey started, and the journeys the lane has driven since. */
157
+ let start;
158
+ const driven = new Set();
59
159
  try {
60
160
  for (const [position, id] of lane.journeys.entries()) {
61
161
  const card = cards[position];
62
162
  const journey = journeyById.get(id);
63
163
  if (card === undefined || journey === undefined)
64
164
  continue;
65
- const waits = await Promise.all(barriersOf(script, lane.id, id).map((dep) => outcome.get(dep)?.promise ?? Promise.resolve(false)));
66
- if (blocked || stopped || ports.stopped() || waits.includes(false)) {
67
- blocked = true;
165
+ const ended = (dep) => outcome.get(dep)?.promise ?? Promise.resolve(ScriptStatus.BLOCKED);
166
+ const waits = await Promise.all(barriersOf(script, lane.id, id).map(ended));
167
+ // A conditional journey is decided by how the journey it names ended, not by the lane: a
168
+ // failure earlier in the lane is often exactly what it is there to look at.
169
+ const when = journey.when;
170
+ const lanePast = when === undefined && blocked;
171
+ if (lanePast ||
172
+ stopped ||
173
+ ports.stopped() ||
174
+ waits.some((s) => ScriptStatus.PASSED !== s)) {
175
+ if (when === undefined)
176
+ blocked = true;
68
177
  card.status = ScriptStatus.BLOCKED;
69
- settleOwned(id, false);
178
+ settleOwned(id, ScriptStatus.BLOCKED);
179
+ tell();
180
+ continue;
181
+ }
182
+ if (when !== undefined && (await ended(when.journey)) !== when.is) {
183
+ card.status = ScriptStatus.NOT_TAKEN;
184
+ settleOwned(id, ScriptStatus.NOT_TAKEN);
70
185
  tell();
71
186
  continue;
72
187
  }
73
188
  lease ??= await ports.lease(lane.id);
74
- const tools = recording(ports.toolset(lease.sessionId, journey.persona), toolCalls);
189
+ const raw = ports.toolset(lease.sessionId, journey.persona);
190
+ // Unrecorded: where the journey starts is set-up, not something it drove or checked.
191
+ // Kept for a journey with a fallback too: its goal starts where the journey began, not
192
+ // on the page its own replays left (where the end may already show).
193
+ if (0 === driven.size && (1 < lane.journeys.length || journey.fallback !== undefined))
194
+ start = asString(asRecord(asRecord(await call(raw, ReticleTool.SNAPSHOT, {}))['status'])['route']);
195
+ else if (start !== undefined && !continuesLane(journey, driven))
196
+ await call(raw, ReticleTool.NAVIGATE, { url: start });
197
+ driven.add(id);
198
+ // This journey's calls alone too: lanes share `toolCalls`, and its replays decide its fallback.
199
+ const mine = [];
200
+ const tools = recording(recording(raw, toolCalls), mine);
75
201
  card.status = ScriptStatus.RUNNING;
76
202
  tell();
77
203
  // This journey's own drives: lanes run side by side, so a slice of the shared list after the
78
204
  // await could hold another lane's missed goal and blame it on this journey.
79
205
  const own = [];
80
- const ok = await runJourney(journey, card.steps, tools, ports, own, tell, () => {
206
+ const stop = () => {
81
207
  stopped = true;
82
- });
83
- card.status = ok ? ScriptStatus.PASSED : ScriptStatus.FAILED;
208
+ };
209
+ // The end the fallback goal names, and whether the page showed it before anything ran: a
210
+ // replay can only be credited with an end it put there.
211
+ const end = journey.fallback === undefined ? undefined : endOf(journey.fallback.goal);
212
+ const endBefore = end !== undefined && (await lookFor(raw.invoke.bind(raw), end, ports.own));
213
+ let ran = await runJourney(journey, card.steps, tools, ports, own, tell, stop);
214
+ // Replay first: replays that decided nothing hand the journey's goal to the model. One that
215
+ // failed is a regression, and a regression is reported, never re-driven into a pass.
216
+ let refused;
217
+ if (!ran.ok &&
218
+ ran.notTaken === undefined &&
219
+ journey.fallback !== undefined &&
220
+ !ports.stopped() &&
221
+ replaysDecidedNothing(mine)) {
222
+ // Replays that decided nothing can still have driven the journey to its end. Driven
223
+ // over MCP: the replay pressed Generate and the page showed the goal's end text; the
224
+ // Harness threw that away, re-drove from a start that signed the app out, and failed a
225
+ // working app. The end is judged where the replay left it, by an assert kept as the
226
+ // run's check — and never when the page showed it before the journey ran.
227
+ const replayReachedEnd = end !== undefined &&
228
+ !endBefore &&
229
+ (await lookFor(raw.invoke.bind(raw), end, ports.own)) &&
230
+ (await holds(tools, { kind: PredicateKind.TEXT, contains: end }));
231
+ if (replayReachedEnd)
232
+ ran = { ok: true };
233
+ else
234
+ refused = await ports.fallbackRefused?.();
235
+ if (!replayReachedEnd && refused === undefined) {
236
+ if (start !== undefined)
237
+ await call(raw, ReticleTool.NAVIGATE, { url: start });
238
+ ran = await runFallback(journey.fallback.goal, tools, ports, own, stop);
239
+ }
240
+ }
241
+ const ok = ran.ok;
242
+ // A drive the platform cut off (credits gone, a refusal, a 5xx) judged nothing: blocked, and
243
+ // its reason said, never "failed" over an app nobody finished driving.
244
+ const cutDrive = own.find((d) => StopReason.BROKEN === d.stopReason);
245
+ const cut = refused === undefined ? cutDrive : { error: refused, stopReason: StopReason.BROKEN };
246
+ if (cut !== undefined)
247
+ broken.set(lane.id, cut.error ?? StopReason.BROKEN);
248
+ card.status = ok
249
+ ? ScriptStatus.PASSED
250
+ : cut !== undefined
251
+ ? ScriptStatus.BLOCKED
252
+ : ran.notTaken !== undefined
253
+ ? ScriptStatus.NOT_TAKEN
254
+ : true === ran.undecided
255
+ ? ScriptStatus.UNDECIDED
256
+ : ScriptStatus.FAILED;
257
+ if (ran.notTaken !== undefined)
258
+ card.why = ran.notTaken;
259
+ if (ran.why !== undefined)
260
+ card.why = ran.why;
84
261
  drives.push(...own);
262
+ const thisRun = journeyRun(id, mine, own);
263
+ runOf.set(card, thisRun);
264
+ const before = runs.get(id);
265
+ runs.set(id, before === undefined ? thisRun : mergeRuns(before, thisRun));
85
266
  if (!ok && own.some((d) => false === d.goalMet))
86
267
  goalMissed.add(card);
87
- blocked = !ok;
88
- settleOwned(id, ok);
268
+ // A conditional journey that failed leaves the lane as it found it: it was a side road.
269
+ if (when === undefined)
270
+ blocked = !ok;
271
+ settleOwned(id, card.status);
89
272
  tell();
90
273
  }
91
274
  }
@@ -99,7 +282,7 @@ export async function runScript(script, ports, onChange = () => undefined) {
99
282
  }
100
283
  }
101
284
  for (const id of lane.journeys)
102
- settleOwned(id, false);
285
+ settleOwned(id, ScriptStatus.BLOCKED);
103
286
  tell();
104
287
  }
105
288
  finally {
@@ -121,13 +304,22 @@ export async function runScript(script, ports, onChange = () => undefined) {
121
304
  ? broken.get(lane.id)
122
305
  : goalMissed.has(card)
123
306
  ? GOAL_NOT_REACHED
124
- : undefined;
125
- return `${mark(card.status)} ${lane.id} · ${card.title} — ${card.status}${why === undefined ? '' : ` (${why.slice(0, 160)})`}`;
307
+ : card.why;
308
+ return `${mark(card.status)} ${lane.id} · ${card.title} — ${card.status}${why === undefined ? '' : ` (${why.slice(0, 160)})`}${byText(runOf.get(card))}`;
126
309
  }));
127
- return { view, toolCalls, drives, stopped: stopped || ports.stopped(), lines };
310
+ return {
311
+ view,
312
+ toolCalls,
313
+ drives,
314
+ stopped: stopped || ports.stopped(),
315
+ lines,
316
+ journeys: [...runs.values()],
317
+ };
128
318
  }
129
319
  async function runJourney(journey, cards, tools, ports, drives, tell, stop) {
130
320
  const checkpoints = new Map();
321
+ // One journey is one chain: a replay after the first continues the page the one before it left.
322
+ let replayed = false;
131
323
  for (const [index, step] of journey.steps.entries()) {
132
324
  const card = cards[index];
133
325
  if (card === undefined)
@@ -135,32 +327,87 @@ async function runJourney(journey, cards, tools, ports, drives, tell, stop) {
135
327
  if (ports.stopped()) {
136
328
  card.status = ScriptStatus.BLOCKED;
137
329
  tell();
138
- return false;
330
+ return { ok: false };
139
331
  }
140
332
  card.status = ScriptStatus.RUNNING;
141
333
  tell();
142
334
  let ok;
143
- if (ScriptStepKind.CHECKPOINT === step.kind) {
144
- checkpoints.set(step.id, step.reenter);
145
- ok = true;
146
- }
147
- else if (ScriptStepKind.BRANCH === step.kind) {
148
- ok = await runBranch(step, checkpoints.get(step.at), tools, ports, drives, stop);
335
+ let notTaken;
336
+ let why;
337
+ let undecided = false;
338
+ try {
339
+ if (ScriptStepKind.CHECKPOINT === step.kind) {
340
+ checkpoints.set(step.id, step.reenter);
341
+ ok = true;
342
+ }
343
+ else if (ScriptStepKind.BRANCH === step.kind) {
344
+ ok = await runBranch(step, checkpoints.get(step.at), tools, ports, drives, stop);
345
+ }
346
+ else {
347
+ ok = await runLeaf(step, tools, ports, drives, stop, replayed);
348
+ if (ScriptStepKind.REPLAY === step.kind)
349
+ replayed = true;
350
+ }
149
351
  }
150
- else {
151
- ok = await runLeaf(step, tools, ports, drives, stop);
352
+ catch (error) {
353
+ if (error instanceof Undecided) {
354
+ why = error.message;
355
+ undecided = true;
356
+ }
357
+ else if (error instanceof StepNotTaken)
358
+ notTaken = error.message;
359
+ else
360
+ throw error;
361
+ ok = false;
152
362
  }
153
- card.status = ok ? ScriptStatus.PASSED : ScriptStatus.FAILED;
363
+ card.status = ok
364
+ ? ScriptStatus.PASSED
365
+ : notTaken !== undefined
366
+ ? ScriptStatus.NOT_TAKEN
367
+ : undecided
368
+ ? ScriptStatus.UNDECIDED
369
+ : ScriptStatus.FAILED;
154
370
  tell();
155
371
  if (!ok) {
156
372
  for (const rest of cards.slice(index + 1))
157
373
  rest.status = ScriptStatus.BLOCKED;
158
374
  tell();
159
- return false;
375
+ return {
376
+ ok: false,
377
+ ...(notTaken === undefined ? {} : { notTaken }),
378
+ ...(why === undefined ? {} : { why }),
379
+ ...(undecided ? { undecided: true } : {}),
380
+ };
160
381
  }
161
382
  }
162
- return true;
383
+ return { ok: true };
384
+ }
385
+ /** The journey's goal, driven by the model in place of replays that decided nothing. */
386
+ async function runFallback(goal, tools, ports, drives, stop) {
387
+ try {
388
+ const ok = await runLeaf({ kind: ScriptStepKind.ACT, goal }, tools, ports, drives, stop);
389
+ return ok ? { ok } : { ok, why: FELL_BACK };
390
+ }
391
+ catch (error) {
392
+ if (error instanceof Undecided)
393
+ return { ok: false, why: error.message, undecided: true };
394
+ throw error;
395
+ }
163
396
  }
397
+ /** The guard stopped a destructive step nobody acknowledged: the step was not taken, not failed. */
398
+ class StepNotTaken extends Error {
399
+ }
400
+ /** The journey ran and decided nothing: neither proved nor a failure of the app. */
401
+ class Undecided extends Error {
402
+ }
403
+ /** The journey's end was on the page before it acted: undecided, never credited, no model spent. */
404
+ class EndAlreadyShown extends Undecided {
405
+ }
406
+ /** Why a journey that reached its goal with no check that could go red proves nothing. */
407
+ const MSG_GOAL_WITHOUT_CHECK = 'it reached its goal, and no check could have gone red there';
408
+ /** What the guard's refusal names, as `drive-report.ts` reads it too. */
409
+ const DESTRUCTIVE_REFUSAL = 'confirmDangerous';
410
+ const MSG_NOT_TAKEN = 'not taken: a step the flow marks destructive needs a person to acknowledge it (Run plan, Re-verify)';
164
411
  /**
165
412
  * Every case drives from the checkpoint. The first starts where the journey already is; each later
166
413
  * one re-enters it first, so no case inherits the page the previous case left behind.
@@ -188,35 +435,73 @@ async function runBranch(step, reenter, tools, ports, drives, stop) {
188
435
  }
189
436
  return all;
190
437
  }
191
- async function runLeaf(step, tools, ports, drives, stop) {
438
+ async function runLeaf(step, tools, ports, drives, stop,
439
+ /** A replay ran before this one in the journey: continue its page, never reload it. */
440
+ chained = false) {
192
441
  switch (step.kind) {
193
442
  case ScriptStepKind.REPLAY:
194
443
  return replay(tools, {
195
444
  flowName: step.flow,
196
- ...(step.at === undefined ? {} : { at: step.at }),
445
+ ...(step.at === undefined ? (chained ? { at: 0 } : {}) : { at: step.at }),
197
446
  ...(step.to === undefined ? {} : { to: step.to }),
447
+ // The flow's own steps, acknowledged by the person who started the run.
448
+ ...(true === ports.confirmDangerous ? { [DESTRUCTIVE_REFUSAL]: true } : {}),
198
449
  });
199
450
  case ScriptStepKind.ASSERT:
200
451
  return holds(tools, step.predicate);
201
452
  case ScriptStepKind.ACT: {
202
453
  if (step.goal !== undefined) {
203
- const drive = await ports.drive(tools, step.goal, step.maxSteps ?? OPEN_GOAL_STEPS);
454
+ const budget = step.maxSteps ?? OPEN_GOAL_STEPS;
455
+ // Parsed before the drive: an end the page already shows is already true, never proved.
456
+ const ending = endOf(step.goal);
457
+ if (ending !== undefined && (await lookFor(tools.invoke.bind(tools), ending, ports.own)))
458
+ throw new EndAlreadyShown(msgEndAlreadyShown(ending));
459
+ let drive = await ports.drive(tools, step.goal, budget);
204
460
  drives.push(drive);
205
461
  if (StopReason.STOPPED === drive.stopReason)
206
462
  stop();
207
- // Passed means its checks held, not that it ran one: a refund journey whose two checks both
208
- // failed was marked passed because a check had run.
209
- const tally = checkTally(drive.toolCalls);
210
- if (0 < tally.failed || false === drive.goalMet)
211
- return false;
212
463
  // A goal that quotes where it ends is judged there, by an assert kept as the run's check:
213
464
  // the model clicked a counter with no `until` and the journey failed on a counter that worked.
214
- // ponytail: the LAST quote is the end state ("from "count: 0" to "count: 1""); a goal that
215
- // quotes its end first needs the planner to say which quote is the end.
216
- const end = goalsIn(step.goal).at(-1);
217
- if (end !== undefined)
218
- return holds(tools, { kind: PredicateKind.TEXT, contains: end });
219
- return 0 < tally.held;
465
+ // ponytail: the LAST quote the goal does not negate is the end state ("from "count: 0" to
466
+ // "count: 1""); a goal that quotes its end first needs the planner to say which is the end.
467
+ const end = ending;
468
+ if (end === undefined) {
469
+ // Passed means its checks held, not that it ran one: a refund journey whose two checks
470
+ // both failed was marked passed because a check had run.
471
+ if (0 < checkTally(drive.toolCalls).failed)
472
+ return false;
473
+ if (0 < checkTally(drive.toolCalls).held)
474
+ return false !== drive.goalMet;
475
+ // Reached, by its own word, with nothing checked: not proved, and not a failure either.
476
+ if (true === drive.goalMet)
477
+ throw new Undecided(MSG_GOAL_WITHOUT_CHECK);
478
+ return false;
479
+ }
480
+ // The drive's failures are judged after its end is: the model's own early look at the end
481
+ // ("Generated script for", asserted before the request that writes it had answered) is
482
+ // superseded when the end then holds, by the same rule as the run's verdict.
483
+ const failedBeside = (calls, endHeld) => 0 < checkTally(endHeld ? [...calls, endHeldCall(end)] : calls).failed;
484
+ let shown = await lookFor(tools.invoke.bind(tools), end, ports.own);
485
+ // A drive that finished with turns to spare, short of the end its own plan names (joined,
486
+ // opened Runs, never clicked Team), is sent on once from where it stands, not graded there.
487
+ const left = budget - drive.steps;
488
+ if (!shown && StopReason.FINISHED === drive.stopReason && MIN_CONTINUE_STEPS <= left) {
489
+ if (failedBeside(drive.toolCalls, false))
490
+ return false;
491
+ drive = await ports.drive(tools, continueGoal(step.goal, end), left);
492
+ drives.push(drive);
493
+ if (StopReason.STOPPED === drive.stopReason)
494
+ stop();
495
+ shown = await lookFor(tools.invoke.bind(tools), end, ports.own);
496
+ }
497
+ // Never reached is the journey's miss, not a failed check on the app: no assert is kept. The
498
+ // page decides it, not the driver's word: an end the page shows was reached, whatever the
499
+ // driver said (a drive started on a dead link reached it and was failed on its own "no").
500
+ if (!shown)
501
+ return false;
502
+ const endHeld = await holds(tools, { kind: PredicateKind.TEXT, contains: end });
503
+ // Passed means its checks held, not that it ran one.
504
+ return endHeld && !failedBeside(drive.toolCalls, true);
220
505
  }
221
506
  const result = await call(tools, ReticleTool.ACT_AND_WAIT, {
222
507
  ...(step.target === undefined ? {} : { target: step.target }),
@@ -229,11 +514,33 @@ async function runLeaf(step, tools, ports, drives, stop) {
229
514
  }
230
515
  }
231
516
  async function replay(tools, args) {
232
- return ReplayStatus.OK === asRecord(await call(tools, ReticleTool.FLOW_REPLAY, args))['status'];
517
+ const result = asRecord(await call(tools, ReticleTool.FLOW_REPLAY, args));
518
+ if (ReplayStatus.OK === result['status'])
519
+ return true;
520
+ const error = result['error'];
521
+ const message = asString(error) ?? asString(asRecord(error)['message']) ?? '';
522
+ if (message.includes(DESTRUCTIVE_REFUSAL))
523
+ throw new StepNotTaken(MSG_NOT_TAKEN);
524
+ const [outcome] = replayedFlows([
525
+ { id: 'replay', name: ReticleTool.FLOW_REPLAY, args, result, isError: false },
526
+ ]);
527
+ if (UNDECIDED_REPLAY.has(outcome?.status))
528
+ throw new Undecided(msgReplayUndecided(String(args['flowName'])));
529
+ return false;
233
530
  }
234
531
  async function holds(tools, predicate) {
235
532
  return true === asRecord(await call(tools, ReticleTool.ASSERT, { predicate }))['pass'];
236
533
  }
534
+ /** The end check `holds` keeps, as a call the drive's tally can read beside the model's own. */
535
+ function endHeldCall(end) {
536
+ return {
537
+ id: 'end',
538
+ name: ReticleTool.ASSERT,
539
+ args: { predicate: { kind: PredicateKind.TEXT, contains: end } },
540
+ result: { verified: Verified.YES },
541
+ isError: false,
542
+ };
543
+ }
237
544
  /** A tool that throws is a failed step, not a crashed run. */
238
545
  async function call(tools, name, args) {
239
546
  try {
@@ -39,14 +39,14 @@ declare const LicensePayloadSchema: z.ZodObject<{
39
39
  exp: z.ZodNumber;
40
40
  features: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
41
41
  }, "strip", z.ZodTypeAny, {
42
- org: string;
43
42
  plan: string;
43
+ org: string;
44
44
  lid: string;
45
45
  exp: number;
46
46
  features?: string[] | undefined;
47
47
  }, {
48
- org: string;
49
48
  plan: string;
49
+ org: string;
50
50
  lid: string;
51
51
  exp: number;
52
52
  features?: string[] | undefined;
@@ -0,0 +1,31 @@
1
+ import { ScreenshotSource, type FlowStepResult } from '@reticlehq/core';
2
+ import type { ToolDeps } from '../../surface/tools/tool-kit.js';
3
+ export interface ShotOptions {
4
+ step?: string;
5
+ verdict?: boolean;
6
+ }
7
+ /** What a tool result carries: where the picture is and how it was taken, or why there is none. */
8
+ export type ScreenshotField = {
9
+ path: string;
10
+ source: ScreenshotSource;
11
+ } | {
12
+ error: string;
13
+ };
14
+ /**
15
+ * Width and height from a JPEG's frame header, or undefined when the bytes are not a JPEG.
16
+ * Read rather than trusted: the run record and the upload both state the size.
17
+ */
18
+ export declare function jpegSize(bytes: Uint8Array): {
19
+ width: number;
20
+ height: number;
21
+ } | undefined;
22
+ /**
23
+ * Photograph the tab a step just ran on. Returns the result field; never throws, because a
24
+ * screenshot is evidence about a step and must never be the reason the step's answer is lost.
25
+ *
26
+ * `step` names the flow step a replay was on, as `<flow>#<index>`, so the run can pin the picture
27
+ * to it; `verdict` says the call produced a verdict, so the run can pair the picture with its check.
28
+ */
29
+ export declare function takeStepShot(deps: ToolDeps, sessionId: string, tool: string, opts?: ShotOptions): Promise<ScreenshotField>;
30
+ /** The replay hook that gives every reported flow step its screenshot, filed as `<flow>#<step>`. */
31
+ export declare function replayStepShooter(deps: ToolDeps, sessionId: string): (result: FlowStepResult, flow: string) => Promise<void>;