@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
@@ -0,0 +1,52 @@
1
+ /**
2
+ * What a drive found that no single click's check could: the page rendering something other than
3
+ * what the API sent (`reticle_reconcile`, run on each page the Harness reaches), and the crawl's
4
+ * anomalies (blank routes, dead controls, console errors, contradictions).
5
+ *
6
+ * Listed in the drive's report beside the verdict, because the agent reading it reports what it is
7
+ * shown: a defect the drive saw and the report left out is a defect nobody hears about.
8
+ */
9
+ import { ReticleTool, asRecord, asString } from '@reticlehq/core';
10
+ /** Enough to act on without burying the verdict. */
11
+ const MAX_FINDINGS = 20;
12
+ export function appFindings(toolCalls) {
13
+ const seen = new Set();
14
+ const lines = [];
15
+ const add = (key, line) => {
16
+ if (seen.has(key) || MAX_FINDINGS <= lines.length)
17
+ return;
18
+ seen.add(key);
19
+ lines.push(line);
20
+ };
21
+ for (const call of toolCalls) {
22
+ if (call.isError)
23
+ continue;
24
+ const result = asRecord(call.result);
25
+ if (ReticleTool.RECONCILE === call.name) {
26
+ const mismatches = result['mismatches'];
27
+ for (const raw of Array.isArray(mismatches) ? mismatches : []) {
28
+ const m = asRecord(raw);
29
+ const entity = asString(m['entity']) ?? '?';
30
+ const field = asString(m['field']) ?? '?';
31
+ const shown = asString(m['rendered']);
32
+ add(`r:${entity}:${field}`, ` RENDERED ≠ API: ${entity} ${field} — the API says ${String(m['api'])}${shown === undefined ? '' : `, the page shows ${shown}`} (${asString(m['why']) ?? ''})`);
33
+ }
34
+ }
35
+ if (ReticleTool.CRAWL === call.name) {
36
+ const anomalies = result['anomalies'];
37
+ for (const raw of Array.isArray(anomalies) ? anomalies : []) {
38
+ const a = asRecord(raw);
39
+ const kind = asString(a['kind']) ?? 'anomaly';
40
+ const desc = asString(a['desc']) ?? '';
41
+ const detail = asString(a['detail']);
42
+ add(`c:${kind}:${desc}`, ` CRAWL ${kind}: ${desc}${detail === undefined ? '' : ` — ${detail}`}`);
43
+ }
44
+ }
45
+ }
46
+ return 0 === lines.length
47
+ ? []
48
+ : [
49
+ 'Found beyond the clicks (each page compared with the API, and a crawl of the app):',
50
+ ...lines,
51
+ ];
52
+ }
@@ -17,6 +17,7 @@
17
17
  * that is what a coding agent has to gate on, and it says "not proved" in those words rather than
18
18
  * leaving a verdict of `unknown` to be read as a pass.
19
19
  */
20
+ import { Verified } from '@reticlehq/core';
20
21
  import type { ToolOutcome } from './harness.js';
21
22
  /** One driven action, reduced to what a reader needs: what was done, and what it proved. */
22
23
  export interface DrivenStep {
@@ -26,6 +27,8 @@ export interface DrivenStep {
26
27
  target: string;
27
28
  /** The engine's verdict for this step, when the step declared anything. */
28
29
  verified: string | undefined;
30
+ /** A route claim that missed: the driver's own guess, or a menu it opened. Never a check. */
31
+ guess?: true;
29
32
  /** The one sentence naming the deciding evidence. */
30
33
  because: string | undefined;
31
34
  /**
@@ -37,7 +40,15 @@ export interface DrivenStep {
37
40
  * noise, and the report is read every drive.
38
41
  */
39
42
  claimed: string | undefined;
43
+ /**
44
+ * What the engine saw that decided it: each channel that disagreed, and any write the app sent
45
+ * that failed. The act's own result carries all of it; a report that kept only the verdict word
46
+ * handed the caller "unit-mismatch" and left it unable to say what was wrong.
47
+ */
48
+ evidence: string[];
40
49
  }
50
+ /** Driving calls that ran with the destructive-action permission: these really changed the app. */
51
+ export declare function confirmedDestructive(toolCalls: readonly ToolOutcome[]): number;
41
52
  /**
42
53
  * Replays this drive ran, and what each came back with.
43
54
  *
@@ -54,6 +65,10 @@ export declare const ReplayOutcome: {
54
65
  readonly OK: "ok";
55
66
  readonly DRIFT: "drift";
56
67
  readonly ERROR: "error";
68
+ /** Stopped at a step the flow marks destructive: not run, which is not a regression. */
69
+ readonly GUARDED: "guarded";
70
+ /** Not saved on this computer: nothing ran, which is not a regression either. */
71
+ readonly MISSING: "missing";
57
72
  };
58
73
  export declare function replayedFlows(toolCalls: readonly ToolOutcome[]): {
59
74
  name: string;
@@ -61,4 +76,49 @@ export declare function replayedFlows(toolCalls: readonly ToolOutcome[]): {
61
76
  }[];
62
77
  /** Reduce the raw call log to the actions that actually drove the app. */
63
78
  export declare function drivenSteps(toolCalls: readonly ToolOutcome[]): DrivenStep[];
64
- export declare function describeDrive(toolCalls: readonly ToolOutcome[], savedFlows: readonly string[]): string;
79
+ /** Whether the drive did anything to the app: an action that ran, or a flow it replayed. */
80
+ export declare function actedOnApp(toolCalls: readonly ToolOutcome[]): boolean;
81
+ /** The pages the drive's own snapshots reported, in order, each distinct page once. */
82
+ export declare function pagesReached(toolCalls: readonly ToolOutcome[]): string[];
83
+ /** The values the drive's acts filled or typed, sequence steps included. */
84
+ export declare function typedValues(toolCalls: readonly ToolOutcome[]): string[];
85
+ /** How the drive's checks came out: act_and_wait with an `until`, and asserts. */
86
+ export declare function checkTally(toolCalls: readonly ToolOutcome[]): {
87
+ held: number;
88
+ failed: number;
89
+ undecided: number;
90
+ };
91
+ /** A plan journey's status, as far as the run's verdict reads it. */
92
+ export interface JourneyStatus {
93
+ status: string;
94
+ }
95
+ /** A run's verdict and the line that says it: the word is decided once, never read back out of the line. */
96
+ export interface RunVerdict {
97
+ verified: Verified;
98
+ line: string;
99
+ }
100
+ /**
101
+ * The first line a caller reads, and the one the HUD ends on, with the verdict it states. A drive
102
+ * whose only passing check was a page change, beside a refund that failed, is NOT "proved its
103
+ * checks"; that line ended a run where the journey it was asked to prove had failed.
104
+ */
105
+ export declare function runVerdict(tally: {
106
+ held: number;
107
+ failed: number;
108
+ undecided: number;
109
+ }, goalMet?: boolean,
110
+ /** A plan's journeys: when there are any, their verdict is the run's. */
111
+ journeys?: readonly JourneyStatus[]): RunVerdict;
112
+ /** The line alone. */
113
+ export declare function verdictLine(tally: {
114
+ held: number;
115
+ failed: number;
116
+ undecided: number;
117
+ }, goalMet?: boolean, journeys?: readonly JourneyStatus[]): string;
118
+ /** Whether the run is proved, exactly as its headline says: the `proved` an answer carries. */
119
+ export declare function runProved(tally: {
120
+ held: number;
121
+ failed: number;
122
+ undecided: number;
123
+ }, goalMet?: boolean, journeys?: readonly JourneyStatus[]): boolean;
124
+ export declare function describeDrive(toolCalls: readonly ToolOutcome[], savedFlows: readonly string[], unverifiedFlows?: readonly string[], goalMet?: boolean, journeys?: readonly JourneyStatus[]): string;
@@ -17,9 +17,76 @@
17
17
  * that is what a coding agent has to gate on, and it says "not proved" in those words rather than
18
18
  * leaving a verdict of `unknown` to be read as a pass.
19
19
  */
20
- import { asRecord, asString, ReticleTool, Verified } from '@reticlehq/core';
20
+ import { appFindings } from './app-findings.js';
21
+ import { MSG_OPENED_MENU, MSG_ROUTE_GUESS_MISSED, claimsOnlyRoute } from './route-guess.js';
22
+ import { asRecord, asString, ActionType, NO_SUCH_FLOW, ReplayStatus, ReticleTool, ScriptStatus, Verified, } from '@reticlehq/core';
23
+ import { supersededChecks } from '@reticlehq/engine/evidence/superseded-checks.js';
24
+ import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate-schema.js';
25
+ import { describeWaitTarget } from '@reticlehq/engine/evidence/unsettled.js';
26
+ function refusedAsDestructive(call) {
27
+ const error = asString(asRecord(call.result)['error']) ?? '';
28
+ return call.isError && error.includes(DESTRUCTIVE_REFUSAL);
29
+ }
30
+ /** Driving calls that ran with the destructive-action permission: these really changed the app. */
31
+ export function confirmedDestructive(toolCalls) {
32
+ return toolCalls.filter((call) => DRIVING_TOOLS.has(call.name) &&
33
+ !call.isError &&
34
+ true === asRecord(asRecord(call.args)['args'])[DESTRUCTIVE_REFUSAL]).length;
35
+ }
36
+ /**
37
+ * A failed claim whose page then showed a dialog: the control opens a confirmation, and the drive
38
+ * guessed it would send the request itself. Reported as a defect, a row's "Refund" button that opens
39
+ * the "Refund now" dialog sent the caller looking for a dead control.
40
+ */
41
+ function openedADialog(result, after) {
42
+ if (Verified.NO !== result['verified'])
43
+ return [];
44
+ const next = after.find((call) => ReticleTool.SNAPSHOT === call.name);
45
+ const dialogs = asRecord(asRecord(next?.result)['status'])['visibleDialogs'];
46
+ return Array.isArray(dialogs) && 0 < dialogs.length
47
+ ? [
48
+ 'it opened a dialog instead: likely the drive guessed the consequence wrong, not an app defect',
49
+ ]
50
+ : [];
51
+ }
52
+ /** Characters of a response body quoted in the evidence: enough for an error message. */
53
+ const MAX_BODY_CHARS = 200;
54
+ /** Contradictions quoted per step. */
55
+ const MAX_EVIDENCE = 3;
56
+ /** The deciding evidence an act result carries, as short lines. */
57
+ function evidenceOf(result) {
58
+ const lines = [];
59
+ const contradictions = result['contradictions'];
60
+ if (Array.isArray(contradictions)) {
61
+ for (const raw of contradictions.slice(0, MAX_EVIDENCE)) {
62
+ const c = asRecord(raw);
63
+ const parts = [asString(c['counter']), asString(c['detail'])].filter((part) => part !== undefined && 0 < part.length);
64
+ lines.push(`${asString(c['kind']) ?? 'contradiction'}: ${parts.join(' — ')}`);
65
+ }
66
+ }
67
+ const verdict = asRecord(result['verdict']);
68
+ const seen = asRecord(verdict['evidence']);
69
+ const status = seen['status'];
70
+ if ('number' === typeof status && 400 <= status) {
71
+ const body = asString(seen['responseBody']);
72
+ lines.push(`${asString(seen['method']) ?? ''} ${asString(seen['url']) ?? ''} → ${String(status)}` +
73
+ (body === undefined ? '' : ` ${body.slice(0, MAX_BODY_CHARS)}`));
74
+ }
75
+ const observed = asString(verdict['observed']);
76
+ if (false === verdict['pass'] && observed !== undefined)
77
+ lines.push(`observed: ${observed}`);
78
+ return lines;
79
+ }
80
+ /** The permission a destructive action needs, named in the gate's refusal and carried on a retry. */
81
+ const DESTRUCTIVE_REFUSAL = 'confirmDangerous';
21
82
  /** How many steps are listed before the account starts counting instead of naming. */
22
83
  const MAX_LISTED = 12;
84
+ /**
85
+ * Failures are listed first, and up to this many of them however long the run. Listed in drive
86
+ * order, a whole-app run named 12 of 70 actions and left its failures in "… and 58 more", so the
87
+ * agent reading it could not say what any of them was.
88
+ */
89
+ const MAX_FAILED = 40;
23
90
  /** Actions that change the app. Reads are not part of the story of what was driven. */
24
91
  const DRIVING_TOOLS = new Set([
25
92
  ReticleTool.ACT,
@@ -61,16 +128,33 @@ function targetOf(args, result) {
61
128
  * resolving — the app moved under a recording, which is a finding about the RECORDING rather than
62
129
  * proof the feature broke, and collapsing it into "failed" would send somebody to fix working code.
63
130
  */
64
- export const ReplayOutcome = { OK: 'ok', DRIFT: 'drift', ERROR: 'error' };
131
+ export const ReplayOutcome = {
132
+ OK: 'ok',
133
+ DRIFT: 'drift',
134
+ ERROR: 'error',
135
+ /** Stopped at a step the flow marks destructive: not run, which is not a regression. */
136
+ GUARDED: 'guarded',
137
+ /** Not saved on this computer: nothing ran, which is not a regression either. */
138
+ MISSING: 'missing',
139
+ };
65
140
  export function replayedFlows(toolCalls) {
66
141
  const out = [];
67
142
  for (const call of toolCalls) {
68
143
  if (ReticleTool.FLOW_REPLAY !== call.name)
69
144
  continue;
70
145
  const name = asString(asRecord(call.args)['flowName']) ?? 'a flow';
146
+ const result = asRecord(call.result);
147
+ const message = asString(asRecord(result['error'])['message']) ?? asString(result['error']) ?? '';
148
+ const status = call.isError ? ReplayOutcome.ERROR : asString(result['status']);
71
149
  out.push({
72
150
  name,
73
- status: call.isError ? ReplayOutcome.ERROR : asString(asRecord(call.result)['status']),
151
+ status: ReplayOutcome.ERROR !== status
152
+ ? status
153
+ : message.includes(DESTRUCTIVE_REFUSAL)
154
+ ? ReplayOutcome.GUARDED
155
+ : message.includes(NO_SUCH_FLOW)
156
+ ? ReplayOutcome.MISSING
157
+ : status,
74
158
  });
75
159
  }
76
160
  return out;
@@ -106,25 +190,134 @@ function describeClaim(until) {
106
190
  return 'a request or a signal';
107
191
  return kind;
108
192
  }
193
+ /** The declared consequence: `until`, or `predicate`, its alias on act_and_wait and on assert. */
194
+ function untilOf(args) {
195
+ return args['until'] ?? args['predicate'];
196
+ }
197
+ /** A `no` on a click whose only claim was a route: the driver's guess, not the app (route-guess.ts). */
198
+ function routeGuessMissed(args, result) {
199
+ return Verified.NO === result['verified'] && claimsOnlyRoute(untilOf(args));
200
+ }
201
+ /** The line a re-press graded undecided carries instead of the raw `no`. */
202
+ const MSG_REPRESS = "a second press of a control whose claim already held: the Harness's own extra action, not the app";
203
+ /** Every check in drive order: act_and_wait with an `until` and asserts, through reticle_run too. */
204
+ function gradedChecks(toolCalls) {
205
+ const heldPresses = new Set();
206
+ const out = [];
207
+ const checks = toolCalls.flatMap((made, index) => {
208
+ const call = throughRun(made);
209
+ const args = asRecord(call.args);
210
+ const until = untilOf(args);
211
+ const isCheck = ReticleTool.ASSERT === call.name ||
212
+ (ReticleTool.ACT_AND_WAIT === call.name && until !== undefined);
213
+ if (!isCheck || call.isError)
214
+ return [];
215
+ const predicate = PredicateSchema.safeParse(until);
216
+ const key = predicate.success
217
+ ? `${predicate.data.kind}|${describeWaitTarget(predicate.data)}`
218
+ : JSON.stringify(until ?? null);
219
+ return [{ index, call, args, result: asRecord(call.result), key }];
220
+ });
221
+ const superseded = supersededChecks(checks.map(({ call, result, key }) => ({
222
+ key,
223
+ passive: ReticleTool.ASSERT === call.name,
224
+ held: Verified.YES === asString(result['verified']),
225
+ failed: Verified.NO === asString(result['verified']),
226
+ })));
227
+ for (const [at, { index, args, result, key }] of checks.entries()) {
228
+ // The driver's own wrong guess about the route checked the driver, not the app.
229
+ if (routeGuessMissed(args, result))
230
+ continue;
231
+ const verified = asString(result['verified']);
232
+ // A passive assert that read too early: see superseded-checks.ts.
233
+ if (superseded.has(at))
234
+ continue;
235
+ // A second press of a control whose claim already held is the Harness's own extra action.
236
+ const ref = asString(args['ref']);
237
+ const pressed = ref === undefined ? undefined : `${ref}|${key}`;
238
+ const repress = Verified.NO === verified && pressed !== undefined && heldPresses.has(pressed);
239
+ if (Verified.YES === verified && pressed !== undefined)
240
+ heldPresses.add(pressed);
241
+ const outcome = Verified.YES === verified
242
+ ? 'held'
243
+ : Verified.NO === verified && !repress
244
+ ? 'failed'
245
+ : 'undecided';
246
+ out.push({ index, key, outcome, repress });
247
+ }
248
+ return out;
249
+ }
250
+ /**
251
+ * A `reticle_run` call as the tool it ran. A navigation made through it was recorded under the
252
+ * run's name, and a run that navigated between two pages said it made no action against the app.
253
+ */
254
+ function throughRun(call) {
255
+ if (ReticleTool.RUN !== call.name)
256
+ return call;
257
+ const args = asRecord(call.args);
258
+ const name = asString(args['tool']);
259
+ return name === undefined ? call : { ...call, name, args: asRecord(args['args']) };
260
+ }
109
261
  /** Reduce the raw call log to the actions that actually drove the app. */
110
262
  export function drivenSteps(toolCalls) {
111
263
  const steps = [];
112
- for (const call of toolCalls) {
264
+ const represses = new Set(gradedChecks(toolCalls)
265
+ .filter((check) => check.repress)
266
+ .map((check) => check.index));
267
+ for (const [index, made] of toolCalls.entries()) {
268
+ const call = throughRun(made);
113
269
  if (!DRIVING_TOOLS.has(call.name))
114
270
  continue;
115
271
  const args = asRecord(call.args);
116
272
  const result = asRecord(call.result);
273
+ // The gate's refusal never reached the app; listed beside the confirmed retry, it read as "the
274
+ // refund was blocked" to the agent reading this, about a refund that had gone through.
275
+ if (refusedAsDestructive(call))
276
+ continue;
117
277
  const action = ReticleTool.NAVIGATE === call.name ? 'navigate' : (asString(args['action']) ?? 'act');
278
+ const guessMissed = !call.isError && routeGuessMissed(args, result);
279
+ if (represses.has(index)) {
280
+ steps.push({
281
+ action,
282
+ target: targetOf(args, result),
283
+ verified: Verified.UNKNOWN,
284
+ because: MSG_REPRESS,
285
+ claimed: describeClaim(untilOf(args)),
286
+ evidence: [],
287
+ });
288
+ continue;
289
+ }
290
+ // A menu or dialog it opened is the way to the route it named, not a wrong guess.
291
+ const opened = guessMissed && 0 < openedADialog(result, toolCalls.slice(index + 1)).length;
118
292
  steps.push({
293
+ ...(guessMissed ? { guess: true } : {}),
119
294
  action,
120
295
  target: targetOf(args, result),
121
- verified: call.isError ? 'error' : asString(result['verified']),
122
- because: call.isError ? asString(result['error']) : asString(result['because']),
123
- claimed: describeClaim(args['until']),
296
+ verified: call.isError
297
+ ? 'error'
298
+ : guessMissed
299
+ ? Verified.UNKNOWN
300
+ : asString(result['verified']),
301
+ because: call.isError
302
+ ? asString(result['error'])
303
+ : opened
304
+ ? MSG_OPENED_MENU
305
+ : guessMissed
306
+ ? MSG_ROUTE_GUESS_MISSED
307
+ : asString(result['because']),
308
+ claimed: describeClaim(untilOf(args)),
309
+ evidence: call.isError || opened
310
+ ? []
311
+ : [...evidenceOf(result), ...openedADialog(result, toolCalls.slice(index + 1))],
124
312
  });
125
313
  }
126
314
  return steps;
127
315
  }
316
+ /** Whether the drive did anything to the app: an action that ran, or a flow it replayed. */
317
+ export function actedOnApp(toolCalls) {
318
+ return (drivenSteps(toolCalls).some((step) => 'error' !== step.verified) ||
319
+ 0 < replayedFlows(toolCalls).length);
320
+ }
128
321
  /**
129
322
  * The account, as lines.
130
323
  *
@@ -134,19 +327,147 @@ export function drivenSteps(toolCalls) {
134
327
  * rather than as a failure — it calls for a better check, not a code change, and collapsing the two
135
328
  * would send an agent to rewrite working code.
136
329
  */
330
+ /** Every `__reticle_*` query parameter, wherever it sits in the route. */
331
+ const RETICLE_PARAMS = /[?&]__reticle_[^&#]*/g;
137
332
  /** The pages the drive's own snapshots reported, in order, each distinct page once. */
138
- function pagesReached(toolCalls) {
333
+ export function pagesReached(toolCalls) {
139
334
  const pages = [];
140
335
  for (const call of toolCalls) {
141
336
  if (ReticleTool.SNAPSHOT !== call.name || call.isError)
142
337
  continue;
143
- const route = asString(asRecord(asRecord(call.result)['status'])['route']);
338
+ const raw = asString(asRecord(asRecord(call.result)['status'])['route']);
339
+ // Reticle's own parameters (a leased tab's session and project) are not part of the page.
340
+ const route = raw?.replace(RETICLE_PARAMS, '').replace(/^\/\?(?=#|$)/, '/');
144
341
  if (route !== undefined && !pages.includes(route))
145
342
  pages.push(route);
146
343
  }
147
344
  return pages;
148
345
  }
149
- export function describeDrive(toolCalls, savedFlows) {
346
+ /** The values the drive's acts filled or typed, sequence steps included. */
347
+ export function typedValues(toolCalls) {
348
+ const out = [];
349
+ const read = (act) => {
350
+ const inner = asRecord(act['args']);
351
+ const value = asString(inner['value']) ?? asString(inner['text']);
352
+ if (value !== undefined &&
353
+ (ActionType.FILL === act['action'] || ActionType.TYPE === act['action']))
354
+ out.push(value);
355
+ };
356
+ for (const call of toolCalls) {
357
+ const steps = call.args['steps'];
358
+ if (Array.isArray(steps))
359
+ for (const step of steps)
360
+ read(asRecord(step));
361
+ else
362
+ read(call.args);
363
+ }
364
+ return out;
365
+ }
366
+ /** How the drive's checks came out: act_and_wait with an `until`, and asserts. */
367
+ export function checkTally(toolCalls) {
368
+ // One check per (kind, claim, outcome), exactly as the platform counts a run's checks: a live
369
+ // drive pressed "Sign in" fifteen times and read "15 of 15 check(s) held" for one fact, and an
370
+ // answer that counted by control said "2 of 2" beside a dashboard counting the same run otherwise.
371
+ const seen = new Set();
372
+ const tally = { held: 0, failed: 0, undecided: 0 };
373
+ const count = (key, now) => {
374
+ if (seen.has(`${key}|${now}`))
375
+ return;
376
+ seen.add(`${key}|${now}`);
377
+ tally[now] += 1;
378
+ };
379
+ for (const check of gradedChecks(toolCalls))
380
+ count(check.key, check.outcome);
381
+ // A replayed flow is a check too: its own expects decided it. A passed replay counted as "no
382
+ // check" and its run read NOT PROVED beside a dashboard that said Passed.
383
+ for (const replay of replayedFlows(toolCalls)) {
384
+ const now = REPLAY_CHECK[replay.status ?? ''];
385
+ if (now === undefined)
386
+ continue;
387
+ count(`${ReticleTool.FLOW_REPLAY}|${replay.name}`, now);
388
+ }
389
+ return tally;
390
+ }
391
+ /** A replay as a check. Guarded and missing never ran, so they are no check at all. */
392
+ const REPLAY_CHECK = {
393
+ [ReplayOutcome.OK]: 'held',
394
+ [ReplayOutcome.ERROR]: 'failed',
395
+ [ReplayOutcome.DRIFT]: 'undecided',
396
+ [ReplayStatus.UNVERIFIABLE]: 'undecided',
397
+ };
398
+ /** Statuses that leave a plan proved: passed, or a side road deliberately not taken (named in its line). */
399
+ const SETTLED_JOURNEY = new Set([ScriptStatus.PASSED, ScriptStatus.NOT_TAKEN]);
400
+ /**
401
+ * A plan run's verdict is its journeys', decided as the platform decides it (`planRunVerdict`): any
402
+ * failed → failed; every journey passed (or deliberately not taken) → proved; some passed beside
403
+ * journeys left undecided or blocked → not proved. Undefined when there is no plan.
404
+ *
405
+ * "Any passed → proved" read PROVED for a plan whose other journeys a credit cut-off had blocked:
406
+ * one journey proved and the rest never decided, reported as the whole plan proved.
407
+ */
408
+ function journeysVerdict(journeys, counts) {
409
+ if (0 === journeys.length)
410
+ return undefined;
411
+ const of = (status) => journeys.filter((j) => status === j.status).length;
412
+ const total = String(journeys.length);
413
+ const passed = of(ScriptStatus.PASSED);
414
+ if (0 < of(ScriptStatus.FAILED))
415
+ return {
416
+ verified: Verified.NO,
417
+ line: `NOT PROVED — ${String(of(ScriptStatus.FAILED))} of ${total} journey(s) failed${counts}.`,
418
+ };
419
+ if (0 < passed && journeys.every((j) => SETTLED_JOURNEY.has(j.status)))
420
+ return {
421
+ verified: Verified.YES,
422
+ line: `PROVED — ${String(passed)} of ${total} journey(s) passed${counts}.`,
423
+ };
424
+ if (0 < passed)
425
+ return {
426
+ verified: Verified.UNKNOWN,
427
+ line: `NOT PROVED — ${String(passed)} of ${total} journey(s) passed and the rest were not decided${counts}.`,
428
+ };
429
+ return { verified: Verified.UNKNOWN, line: `NOT PROVED — no journey passed${counts}.` };
430
+ }
431
+ /**
432
+ * The first line a caller reads, and the one the HUD ends on, with the verdict it states. A drive
433
+ * whose only passing check was a page change, beside a refund that failed, is NOT "proved its
434
+ * checks"; that line ended a run where the journey it was asked to prove had failed.
435
+ */
436
+ export function runVerdict(tally, goalMet,
437
+ /** A plan's journeys: when there are any, their verdict is the run's. */
438
+ journeys = []) {
439
+ const total = tally.held + tally.failed + tally.undecided;
440
+ const counts = `${String(tally.held)} of ${String(total)} check(s) held, ${String(tally.failed)} failed, ${String(tally.undecided)} undecided`;
441
+ const planned = journeysVerdict(journeys, 0 === total ? '' : `; ${counts}`);
442
+ const not = (line) => ({ verified: Verified.UNKNOWN, line });
443
+ // Journeys that passed are not the run's goal reached: the goals the run was asked decide it too.
444
+ if (Verified.YES === planned?.verified && false === goalMet)
445
+ return not(`NOT PROVED — ${planned.line.slice('PROVED — '.length).replace(/\.$/, '')}, but the goal was not reached.`);
446
+ if (planned !== undefined)
447
+ return planned;
448
+ if (0 === total)
449
+ return not('NOT PROVED: the drive ran no check.');
450
+ if (0 < tally.failed)
451
+ return {
452
+ verified: Verified.NO,
453
+ line: `NOT PROVED — ${counts}. The failures below are findings.`,
454
+ };
455
+ if (0 < tally.undecided)
456
+ return not(`NOT PROVED — ${counts}.`);
457
+ // Checks that held on the way are not the journey done.
458
+ if (false === goalMet)
459
+ return not(`NOT PROVED — ${counts}, but the goal was not reached.`);
460
+ return { verified: Verified.YES, line: `PROVED — ${counts}.` };
461
+ }
462
+ /** The line alone. */
463
+ export function verdictLine(tally, goalMet, journeys = []) {
464
+ return runVerdict(tally, goalMet, journeys).line;
465
+ }
466
+ /** Whether the run is proved, exactly as its headline says: the `proved` an answer carries. */
467
+ export function runProved(tally, goalMet, journeys = []) {
468
+ return Verified.YES === runVerdict(tally, goalMet, journeys).verified;
469
+ }
470
+ export function describeDrive(toolCalls, savedFlows, unverifiedFlows = [], goalMet, journeys = []) {
150
471
  const steps = drivenSteps(toolCalls);
151
472
  const replays = replayedFlows(toolCalls);
152
473
  /*
@@ -162,34 +483,59 @@ export function describeDrive(toolCalls, savedFlows) {
162
483
  const held = replays.filter((r) => ReplayOutcome.OK === r.status);
163
484
  const failed = replays.filter((r) => ReplayOutcome.ERROR === r.status);
164
485
  const drifted = replays.filter((r) => ReplayOutcome.DRIFT === r.status);
486
+ const guarded = replays.filter((r) => ReplayOutcome.GUARDED === r.status);
487
+ const missing = replays.filter((r) => ReplayOutcome.MISSING === r.status);
165
488
  const lines = [
166
489
  `Replayed ${String(replays.length)} recorded journey(s) with NO model in the loop: ` +
167
- `${String(held.length)} still hold, ${String(failed.length)} failed, ${String(drifted.length)} drifted.`,
490
+ `${String(held.length)} still hold, ${String(failed.length)} failed, ${String(drifted.length)} drifted` +
491
+ `${0 === guarded.length ? '' : `, ${String(guarded.length)} not run`}` +
492
+ `${0 === missing.length ? '' : `, ${String(missing.length)} not on this computer`}.`,
168
493
  ];
494
+ if (0 < missing.length)
495
+ lines.push(` MISSING: ${missing.map((r) => r.name).join(', ')} — not saved on this computer, or calls a flow that is not, so it never ran. Not a regression: pull or record them here first.`);
169
496
  if (0 < failed.length)
170
497
  lines.push(` FAILED: ${failed.map((r) => r.name).join(', ')} — regressions in journeys that used to pass.`);
498
+ if (0 < guarded.length)
499
+ lines.push(` NOT RUN: ${guarded.map((r) => r.name).join(', ')} — stopped at a step marked destructive. Not a regression: replay with confirmDangerous to run it.`);
171
500
  if (0 < drifted.length)
172
501
  lines.push(` DRIFTED: ${drifted.map((r) => r.name).join(', ')} — the app moved under these recordings; the flow needs re-anchoring, not the app fixing.`);
173
502
  return lines.join('\n');
174
503
  })();
175
- if (0 === steps.length)
176
- return (replayLine ??
177
- 'Nothing was driven and nothing was replayed: the run made no action against the app.');
504
+ // A plan run leads with its journeys' verdict even when the model drove nothing: its replays, or
505
+ // a journey a guard stopped, are a result, never "no action against the app".
506
+ if (0 === steps.length) {
507
+ const lead = 0 === journeys.length ? undefined : verdictLine(checkTally(toolCalls), goalMet, journeys);
508
+ return [
509
+ lead,
510
+ replayLine ??
511
+ (lead === undefined
512
+ ? 'Nothing was driven and nothing was replayed: the run made no action against the app.'
513
+ : undefined),
514
+ ]
515
+ .filter((line) => line !== undefined)
516
+ .join('\n');
517
+ }
178
518
  const proved = steps.filter((step) => Verified.YES === step.verified);
179
519
  const failed = steps.filter((step) => Verified.NO === step.verified);
180
- const undecided = steps.filter((step) => Verified.YES !== step.verified && Verified.NO !== step.verified);
520
+ // The driver's own route guesses are no check (as `checkTally` counts), so not "not decided".
521
+ const guesses = steps.filter((step) => true === step.guess);
522
+ const undecided = steps.filter((step) => true !== step.guess && Verified.YES !== step.verified && Verified.NO !== step.verified);
181
523
  const pages = pagesReached(toolCalls);
182
524
  const lines = [
525
+ verdictLine(checkTally(toolCalls), goalMet, journeys),
183
526
  ...(replayLine === undefined ? [] : [replayLine]),
184
- `Drove ${String(steps.length)} action(s): ${String(proved.length)} proved, ` +
185
- `${String(failed.length)} failed, ${String(undecided.length)} not decided.`,
527
+ // The outcomes are counted once, in the checks line above: no second breakdown here.
528
+ `Drove ${String(steps.length)} action(s)` +
529
+ (0 === guesses.length ? '.' : `; ${String(guesses.length)} guess of its own, not a check.`),
186
530
  // How DEEP it got. An action count reads the same for a checkout walked to its receipt and for
187
531
  // eleven clicks on the home page; the pages reached are what tell them apart.
188
532
  ...(0 === pages.length
189
533
  ? []
190
534
  : [`Reached ${String(pages.length)} page(s): ${pages.join(' → ')}.`]),
535
+ ...appFindings(toolCalls),
191
536
  ];
192
- for (const step of steps.slice(0, MAX_LISTED)) {
537
+ const listed = [...failed, ...proved, ...undecided, ...guesses].slice(0, Math.max(MAX_LISTED, Math.min(failed.length, MAX_FAILED)));
538
+ for (const step of listed) {
193
539
  const verdict = step.verified ?? 'nothing declared';
194
540
  const because = step.because === undefined ? '' : ` — ${step.because}`;
195
541
  // The claim, on failures only: it is what separates "the app is broken" from "the drive guessed
@@ -201,14 +547,36 @@ export function describeDrive(toolCalls, savedFlows) {
201
547
  ? ` (claimed ${step.claimed})`
202
548
  : '';
203
549
  lines.push(` ${step.action} ${step.target}: ${verdict}${claimed}${because}`);
550
+ for (const line of step.evidence)
551
+ lines.push(` ${line}`);
552
+ }
553
+ if (listed.length < steps.length) {
554
+ const unlistedFailed = Math.max(0, failed.length - MAX_FAILED);
555
+ lines.push(` … and ${String(steps.length - listed.length)} more` +
556
+ (0 === unlistedFailed
557
+ ? ', none of them failed.'
558
+ : `, ${String(unlistedFailed)} of them failed.`));
204
559
  }
205
- if (MAX_LISTED < steps.length)
206
- lines.push(` … and ${String(steps.length - MAX_LISTED)} more.`);
207
- if (0 < failed.length)
208
- lines.push(`${String(failed.length)} action(s) FAILED — the app did not do what the drive declared it would. These are findings.`);
209
- if (0 < undecided.length)
210
- lines.push(`${String(undecided.length)} action(s) were NOT PROVED. That is undecided evidence, not a failure: it calls for a better check, not a code change.`);
211
- if (0 < savedFlows.length)
212
- lines.push(`Replay any of this without a model: reticle_verify { action: "flows" } — saved ${savedFlows.join(', ')}.`);
560
+ const confirmed = confirmedDestructive(toolCalls);
561
+ if (0 < confirmed)
562
+ lines.push(`${String(confirmed)} destructive action(s) were confirmed and REALLY RAN against the app (the drive confirms one only after the gate refuses it; the refusal itself changed nothing).`);
563
+ // Counted from the same graded checks as the checks line, never from the raw step verdicts: an
564
+ // answer read "0 failed" beside "1 action(s) FAILED … These are findings" about one re-press.
565
+ const tally = checkTally(toolCalls);
566
+ if (0 < tally.failed)
567
+ lines.push(`${String(tally.failed)} check(s) FAILED — the app did not do what the drive declared it would. These are findings.`);
568
+ if (0 < tally.undecided)
569
+ lines.push(`${String(tally.undecided)} check(s) undecided. That is undecided evidence, not a failure: it calls for a better check, not a code change.`);
570
+ const undeclared = undecided.filter((step) => step.claimed === undefined).length;
571
+ if (0 < undeclared)
572
+ lines.push(`${String(undeclared)} action(s) declared no consequence, so they prove nothing either way: not a check, not a failure.`);
573
+ // A flow with no step that asserts anything replays as "verified nothing": offered as a replay it
574
+ // reads as evidence, so it is named for what it is instead.
575
+ const empty = new Set(unverifiedFlows);
576
+ const replayable = savedFlows.filter((name) => !empty.has(name));
577
+ if (0 < replayable.length)
578
+ lines.push(`Replay any of this without a model: reticle_verify { action: "flows" } — saved ${replayable.join(', ')}.`);
579
+ for (const name of unverifiedFlows)
580
+ lines.push(`Saved ${name}, but ${name} checks nothing: no step asserts a consequence, so its replay will verify nothing. Drive again naming the end state, or add an expect to its last step.`);
213
581
  return lines.join('\n');
214
582
  }