@reticlehq/server 3.8.2 → 3.10.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 (477) hide show
  1. package/LICENSE +201 -104
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/SKILL.md +13 -12
  5. package/bin/launch.js +13 -0
  6. package/bin/package.json +3 -0
  7. package/bin/reticle.js +66 -8
  8. package/dist/chromium-launch-options.d.ts +25 -0
  9. package/dist/chromium-launch-options.js +21 -1
  10. package/dist/command/cli/adhoc-suite.js +2 -0
  11. package/dist/command/cli/adhoc-verdict.d.ts +2 -43
  12. package/dist/command/cli/adhoc-verdict.js +50 -160
  13. package/dist/command/cli/answers/gate-exit.d.ts +6 -2
  14. package/dist/command/cli/answers/gate-exit.js +12 -2
  15. package/dist/command/cli/answers/mcp-connection-hint.d.ts +2 -0
  16. package/dist/command/cli/answers/mcp-connection-hint.js +6 -0
  17. package/dist/command/cli/ci-hint.d.ts +44 -0
  18. package/dist/command/cli/ci-hint.js +72 -0
  19. package/dist/command/cli/cli-doctor.d.ts +6 -1
  20. package/dist/command/cli/cli-doctor.js +46 -5
  21. package/dist/command/cli/cli-flow-commands.d.ts +7 -1
  22. package/dist/command/cli/cli-flow-commands.js +39 -24
  23. package/dist/command/cli/cli-kill.d.ts +21 -0
  24. package/dist/command/cli/cli-kill.js +47 -4
  25. package/dist/command/cli/cli-parse-compare.d.ts +22 -0
  26. package/dist/command/cli/cli-parse-compare.js +75 -0
  27. package/dist/command/cli/cli-parse-grade.d.ts +36 -0
  28. package/dist/command/cli/cli-parse-grade.js +75 -0
  29. package/dist/command/cli/cli-parse-grammar.d.ts +2 -0
  30. package/dist/command/cli/cli-parse-grammar.js +18 -20
  31. package/dist/command/cli/cli-parse-verify.d.ts +10 -0
  32. package/dist/command/cli/cli-parse-verify.js +63 -14
  33. package/dist/command/cli/cli-parse.d.ts +22 -17
  34. package/dist/command/cli/cli-parse.js +54 -32
  35. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  36. package/dist/command/cli/cli-update-commands.js +29 -20
  37. package/dist/command/cli/cli-usage.js +61 -31
  38. package/dist/command/cli/cli-verify.d.ts +17 -3
  39. package/dist/command/cli/cli-verify.js +59 -21
  40. package/dist/command/cli/cloud-cli.js +2 -119
  41. package/dist/command/cli/daemon-link/daemon-client.d.ts +45 -0
  42. package/dist/command/cli/daemon-link/daemon-client.js +205 -0
  43. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +6 -1
  44. package/dist/command/cli/doctor/browser/chromium-hint.js +11 -5
  45. package/dist/command/cli/doctor/doctor-daemon-line.js +6 -3
  46. package/dist/command/cli/doctor/doctor-fix.d.ts +44 -0
  47. package/dist/command/cli/doctor/doctor-fix.js +89 -0
  48. package/dist/command/cli/doctor/doctor-launcher-line.d.ts +23 -0
  49. package/dist/command/cli/doctor/doctor-launcher-line.js +60 -0
  50. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  51. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  52. package/dist/command/cli/doctor-repairs.d.ts +64 -0
  53. package/dist/command/cli/doctor-repairs.js +214 -0
  54. package/dist/command/cli/drive/drive-command.js +3 -7
  55. package/dist/command/cli/ensure-daemon.d.ts +26 -0
  56. package/dist/command/cli/ensure-daemon.js +57 -0
  57. package/dist/command/cli/finished-run/grade-command.d.ts +23 -0
  58. package/dist/command/cli/finished-run/grade-command.js +180 -0
  59. package/dist/command/cli/first-use-checks.d.ts +41 -0
  60. package/dist/command/cli/first-use-checks.js +127 -0
  61. package/dist/command/cli/first-verdict-node.d.ts +3 -0
  62. package/dist/command/cli/first-verdict-node.js +189 -0
  63. package/dist/command/cli/first-verdict.d.ts +126 -0
  64. package/dist/command/cli/first-verdict.js +267 -0
  65. package/dist/command/cli/launch/sdk-version-match.d.ts +3 -2
  66. package/dist/command/cli/launch/sdk-version-match.js +3 -2
  67. package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +1 -1
  68. package/dist/command/cli/lifecycle/daemon-lifecycle.js +7 -6
  69. package/dist/command/cli/mcp-command.js +13 -4
  70. package/dist/command/cli/ports/port-holder.d.ts +11 -0
  71. package/dist/command/cli/ports/port-holder.js +36 -4
  72. package/dist/command/cli/setup-mcp-cli.d.ts +27 -1
  73. package/dist/command/cli/setup-mcp-cli.js +98 -23
  74. package/dist/command/cli/status/status-lines.d.ts +2 -0
  75. package/dist/command/cli/status/status-lines.js +72 -17
  76. package/dist/command/cli/status-fields.d.ts +5 -1
  77. package/dist/command/cli/status-fields.js +24 -6
  78. package/dist/command/cli/try-command.d.ts +7 -0
  79. package/dist/command/cli/try-command.js +11 -3
  80. package/dist/command/cli/two-builds/compare-command.d.ts +48 -0
  81. package/dist/command/cli/two-builds/compare-command.js +314 -0
  82. package/dist/command/cli/verify-against.d.ts +61 -0
  83. package/dist/command/cli/verify-against.js +187 -0
  84. package/dist/command/cli/verify-no-session.d.ts +2 -0
  85. package/dist/command/cli/verify-no-session.js +13 -0
  86. package/dist/command/cli/verify-results.d.ts +35 -2
  87. package/dist/command/cli/verify-results.js +76 -10
  88. package/dist/command/cli.js +112 -70
  89. package/dist/command/daemon/binding/daemon-status-probe.d.ts +3 -1
  90. package/dist/command/daemon/binding/daemon-status-probe.js +4 -2
  91. package/dist/command/daemon/daemon-argv.d.ts +9 -0
  92. package/dist/command/daemon/daemon-argv.js +11 -0
  93. package/dist/command/daemon/daemon-resolve.d.ts +8 -1
  94. package/dist/command/daemon/daemon-resolve.js +27 -1
  95. package/dist/command/daemon/daemon.d.ts +22 -4
  96. package/dist/command/daemon/daemon.js +52 -10
  97. package/dist/command/daemon/lifetime/daemon-exit.d.ts +24 -0
  98. package/dist/command/daemon/lifetime/daemon-exit.js +39 -0
  99. package/dist/command/daemon/lifetime/death-cause.d.ts +15 -0
  100. package/dist/command/daemon/lifetime/death-cause.js +149 -0
  101. package/dist/command/daemon/lifetime/heartbeat.d.ts +7 -15
  102. package/dist/command/daemon/lifetime/heartbeat.js +11 -15
  103. package/dist/command/daemon/lifetime/startup-failure.d.ts +29 -0
  104. package/dist/command/daemon/lifetime/startup-failure.js +62 -0
  105. package/dist/command/daemon/port-state.d.ts +14 -0
  106. package/dist/command/daemon/port-state.js +31 -0
  107. package/dist/command/setup/agent-configs.d.ts +2 -0
  108. package/dist/command/setup/agent-configs.js +42 -15
  109. package/dist/command/setup/agent-next-steps.d.ts +77 -0
  110. package/dist/command/setup/agent-next-steps.js +284 -0
  111. package/dist/command/setup/agent-writer.js +11 -6
  112. package/dist/command/setup/bringup/dev-server-files.d.ts +9 -0
  113. package/dist/command/setup/bringup/dev-server-files.js +17 -0
  114. package/dist/command/setup/bringup/static-page-server.d.ts +14 -2
  115. package/dist/command/setup/bringup/static-page-server.js +43 -9
  116. package/dist/command/setup/init/init-host.js +2 -0
  117. package/dist/command/setup/init/init-runtime.d.ts +6 -1
  118. package/dist/command/setup/init/init-runtime.js +63 -21
  119. package/dist/command/setup/mcp-launcher.d.ts +3 -0
  120. package/dist/command/setup/mcp-launcher.js +11 -0
  121. package/dist/command/setup/node-effects.d.ts +3 -2
  122. package/dist/command/setup/node-effects.js +9 -3
  123. package/dist/command/setup/remaining-steps.d.ts +8 -0
  124. package/dist/command/setup/remaining-steps.js +10 -0
  125. package/dist/command/setup/run-setup.d.ts +2 -0
  126. package/dist/command/setup/run-setup.js +9 -1
  127. package/dist/command/setup/setup-command.js +36 -15
  128. package/dist/command/setup/setup-mcp.d.ts +8 -0
  129. package/dist/command/setup/setup-mcp.js +47 -20
  130. package/dist/command/setup/start-dev-server.d.ts +8 -0
  131. package/dist/command/setup/start-dev-server.js +43 -0
  132. package/dist/command/update/updater.js +6 -0
  133. package/dist/command/version/identity/server-version.d.ts +2 -0
  134. package/dist/command/version/identity/server-version.js +2 -0
  135. package/dist/command/version/version-skew.d.ts +7 -0
  136. package/dist/command/version/version-skew.js +14 -3
  137. package/dist/features/compare/action-plan.d.ts +260 -0
  138. package/dist/features/compare/action-plan.js +543 -0
  139. package/dist/features/compare/behaviour-compare.d.ts +24 -0
  140. package/dist/features/compare/behaviour-compare.js +85 -0
  141. package/dist/features/compare/behaviour-diff.d.ts +97 -0
  142. package/dist/features/compare/behaviour-diff.js +202 -0
  143. package/dist/features/compare/behaviour-report.d.ts +40 -0
  144. package/dist/features/compare/behaviour-report.js +128 -0
  145. package/dist/features/compare/build-readings.d.ts +106 -0
  146. package/dist/features/compare/build-readings.js +250 -0
  147. package/dist/features/compare/compare-diff.d.ts +62 -0
  148. package/dist/features/compare/compare-diff.js +177 -0
  149. package/dist/features/compare/compare-report-html.d.ts +6 -0
  150. package/dist/features/compare/compare-report-html.js +102 -0
  151. package/dist/features/compare/compare-report.d.ts +15 -0
  152. package/dist/features/compare/compare-report.js +73 -0
  153. package/dist/features/compare/compare-run.d.ts +60 -0
  154. package/dist/features/compare/compare-run.js +123 -0
  155. package/dist/features/compare/outside/effect-lines.d.ts +26 -0
  156. package/dist/features/compare/outside/effect-lines.js +103 -0
  157. package/dist/features/compare/outside/state-sources.d.ts +76 -0
  158. package/dist/features/compare/outside/state-sources.js +164 -0
  159. package/dist/features/compare/outside/value-dictionary.d.ts +51 -0
  160. package/dist/features/compare/outside/value-dictionary.js +227 -0
  161. package/dist/features/compare/visible-content.d.ts +20 -0
  162. package/dist/features/compare/visible-content.js +125 -0
  163. package/dist/features/crawl/crawl-empty.js +2 -1
  164. package/dist/features/crawl/crawl-exhaustive.d.ts +55 -0
  165. package/dist/features/crawl/crawl-exhaustive.js +138 -0
  166. package/dist/features/crawl/crawl-tools.d.ts +9 -2
  167. package/dist/features/crawl/crawl-tools.js +28 -12
  168. package/dist/features/crawl/crawl.d.ts +8 -9
  169. package/dist/features/crawl/crawl.js +61 -65
  170. package/dist/features/exhaust/app-coverage.d.ts +5 -1
  171. package/dist/features/exhaust/app-coverage.js +3 -1
  172. package/dist/features/exhaust/code-coverage.js +8 -4
  173. package/dist/features/exhaust/edge-cases.d.ts +133 -0
  174. package/dist/features/exhaust/edge-cases.js +310 -0
  175. package/dist/features/exhaust/edges/edge-drive.d.ts +42 -0
  176. package/dist/features/exhaust/edges/edge-drive.js +364 -0
  177. package/dist/features/exhaust/edges/edge-run.d.ts +59 -0
  178. package/dist/features/exhaust/edges/edge-run.js +169 -0
  179. package/dist/features/exhaust/explorer.d.ts +87 -14
  180. package/dist/features/exhaust/explorer.js +159 -25
  181. package/dist/features/exhaust/failure-branches.d.ts +5 -0
  182. package/dist/features/exhaust/failure-branches.js +29 -11
  183. package/dist/features/exhaust/invariants.d.ts +112 -0
  184. package/dist/features/exhaust/invariants.js +188 -0
  185. package/dist/features/exhaust/ledger.d.ts +68 -0
  186. package/dist/features/exhaust/ledger.js +121 -13
  187. package/dist/features/exhaust/session-fold.d.ts +10 -0
  188. package/dist/features/exhaust/session-fold.js +46 -3
  189. package/dist/features/exhaust/session-port.d.ts +3 -1
  190. package/dist/features/exhaust/session-port.js +97 -28
  191. package/dist/features/grade/grade-answer.d.ts +99 -0
  192. package/dist/features/grade/grade-answer.js +112 -0
  193. package/dist/features/grade/grade-noise.d.ts +27 -0
  194. package/dist/features/grade/grade-noise.js +55 -0
  195. package/dist/features/grade/grade-renumber.d.ts +12 -0
  196. package/dist/features/grade/grade-renumber.js +86 -0
  197. package/dist/features/grade/grade-state.d.ts +50 -0
  198. package/dist/features/grade/grade-state.js +93 -0
  199. package/dist/features/grade/grade-suggest.d.ts +33 -0
  200. package/dist/features/grade/grade-suggest.js +98 -0
  201. package/dist/features/license/license.d.ts +11 -71
  202. package/dist/features/license/license.js +43 -136
  203. package/dist/features/visual/desktop-capture.d.ts +33 -0
  204. package/dist/features/visual/desktop-capture.js +94 -0
  205. package/dist/features/visual/step-shots.js +139 -35
  206. package/dist/features/visual/visual-tools.d.ts +0 -18
  207. package/dist/features/visual/visual-tools.js +67 -99
  208. package/dist/import-graph.js +5 -6
  209. package/dist/index.d.ts +3 -1
  210. package/dist/index.js +19 -7
  211. package/dist/judgement/capsule/causal-summary.js +9 -2
  212. package/dist/judgement/runs/artifact/replay-mapping.d.ts +13 -1
  213. package/dist/judgement/runs/artifact/replay-mapping.js +1 -1
  214. package/dist/judgement/runs/reticle-runner.js +16 -2
  215. package/dist/judgement/runs/run-ledger.d.ts +7 -5
  216. package/dist/judgement/runs/run-ledger.js +98 -69
  217. package/dist/judgement/runs/runner-port.d.ts +2 -0
  218. package/dist/judgement/runs/runner-port.js +23 -5
  219. package/dist/judgement/runs/verification-sync.d.ts +6 -3
  220. package/dist/judgement/runs/verification-sync.js +21 -10
  221. package/dist/language/flows/affected-tools.d.ts +1 -1
  222. package/dist/language/flows/affected-tools.js +49 -30
  223. package/dist/language/flows/change/git-changed.d.ts +2 -1
  224. package/dist/language/flows/change/git-changed.js +19 -2
  225. package/dist/language/flows/fields/flow-secret-field.d.ts +1 -13
  226. package/dist/language/flows/fields/flow-secret-field.js +77 -21
  227. package/dist/language/flows/flow-anchor.d.ts +60 -2
  228. package/dist/language/flows/flow-anchor.js +125 -20
  229. package/dist/language/flows/flow-classify.d.ts +20 -0
  230. package/dist/language/flows/flow-classify.js +90 -12
  231. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  232. package/dist/language/flows/flow-cross-step.js +25 -1
  233. package/dist/language/flows/flow-journey.d.ts +38 -4
  234. package/dist/language/flows/flow-journey.js +138 -8
  235. package/dist/language/flows/flow-replay-run.d.ts +0 -16
  236. package/dist/language/flows/flow-replay-run.js +76 -14
  237. package/dist/language/flows/flow-replay-types.d.ts +4 -2
  238. package/dist/language/flows/flow-replay.d.ts +19 -1
  239. package/dist/language/flows/flow-replay.js +169 -52
  240. package/dist/language/flows/flow-replayable.js +7 -1
  241. package/dist/language/flows/flow-start-path.d.ts +34 -5
  242. package/dist/language/flows/flow-start-path.js +202 -15
  243. package/dist/language/flows/flow-step-runners.d.ts +14 -13
  244. package/dist/language/flows/flow-step-runners.js +184 -109
  245. package/dist/language/flows/flow-store-for-session.d.ts +26 -25
  246. package/dist/language/flows/flow-store-for-session.js +51 -5
  247. package/dist/language/flows/flow-tools.js +46 -33
  248. package/dist/language/flows/flows.js +176 -76
  249. package/dist/language/flows/recording/tape/recordings.d.ts +21 -16
  250. package/dist/language/flows/recording/tape/recordings.js +112 -49
  251. package/dist/language/flows/replay.d.ts +36 -12
  252. package/dist/language/flows/replay.js +193 -50
  253. package/dist/language/flows/steps/page-steps.d.ts +68 -0
  254. package/dist/language/flows/steps/page-steps.js +198 -0
  255. package/dist/language/flows/suite/sequential-run.d.ts +68 -0
  256. package/dist/language/flows/suite/sequential-run.js +96 -0
  257. package/dist/language/flows/verify-change-tools.js +26 -15
  258. package/dist/launch-chromium.d.ts +1 -0
  259. package/dist/launch-chromium.js +49 -12
  260. package/dist/memory/cloud/background-sync.d.ts +13 -0
  261. package/dist/memory/cloud/background-sync.js +24 -3
  262. package/dist/memory/cloud/sync-daemon.js +26 -27
  263. package/dist/memory/cloud/sync-screenshots.js +6 -1
  264. package/dist/memory/journal/attach-journal.js +2 -1
  265. package/dist/memory/journal/drive-flow.d.ts +7 -0
  266. package/dist/memory/journal/drive-flow.js +44 -13
  267. package/dist/memory/journal/journal-recorder.d.ts +4 -2
  268. package/dist/memory/journal/session-journal.d.ts +7 -0
  269. package/dist/memory/journal/session-journal.js +58 -10
  270. package/dist/memory/project/root-claims.d.ts +9 -0
  271. package/dist/memory/project/root-claims.js +9 -4
  272. package/dist/portal/bridge/bridge.d.ts +13 -4
  273. package/dist/portal/bridge/bridge.js +10 -9
  274. package/dist/portal/input/download-capture.d.ts +7 -0
  275. package/dist/portal/input/download-capture.js +92 -0
  276. package/dist/portal/input/network-detail.d.ts +6 -0
  277. package/dist/portal/input/network-detail.js +12 -1
  278. package/dist/portal/input/network-mock-tools.js +49 -13
  279. package/dist/portal/input/network-mock.d.ts +8 -0
  280. package/dist/portal/input/network-mock.js +30 -10
  281. package/dist/portal/input/page-capture.d.ts +24 -0
  282. package/dist/portal/input/page-capture.js +33 -0
  283. package/dist/portal/input/real-input.d.ts +35 -18
  284. package/dist/portal/input/real-input.js +99 -33
  285. package/dist/portal/input/viewport-tools.d.ts +8 -0
  286. package/dist/portal/input/viewport-tools.js +81 -21
  287. package/dist/portal/pool/browser-pool.d.ts +16 -30
  288. package/dist/portal/pool/browser-pool.js +64 -52
  289. package/dist/portal/pool/context-permissions.d.ts +34 -17
  290. package/dist/portal/pool/context-permissions.js +94 -1
  291. package/dist/portal/pool/csp-widen.d.ts +62 -0
  292. package/dist/portal/pool/csp-widen.js +132 -0
  293. package/dist/portal/pool/determinism.d.ts +52 -0
  294. package/dist/portal/pool/determinism.js +259 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +34 -1
  296. package/dist/portal/pool/lease-emulation.js +18 -0
  297. package/dist/portal/pool/lease-marker-stamp.d.ts +6 -0
  298. package/dist/portal/pool/lease-marker-stamp.js +15 -1
  299. package/dist/portal/pool/lease-page-error.d.ts +56 -0
  300. package/dist/portal/pool/lease-page-error.js +160 -0
  301. package/dist/portal/pool/page-error-journal.d.ts +63 -0
  302. package/dist/portal/pool/page-error-journal.js +208 -0
  303. package/dist/portal/pool/playwright-launcher.js +71 -15
  304. package/dist/portal/pool/pool-contract.d.ts +49 -1
  305. package/dist/portal/pool/pool-lease.d.ts +70 -2
  306. package/dist/portal/pool/pool-lease.js +23 -0
  307. package/dist/portal/pool/zero-install.d.ts +8 -0
  308. package/dist/portal/pool/zero-install.js +91 -1
  309. package/dist/portal/session/dev-server/dev-command.d.ts +11 -2
  310. package/dist/portal/session/dev-server/dev-command.js +110 -16
  311. package/dist/portal/session/dev-server/dev-server-probe.d.ts +7 -0
  312. package/dist/portal/session/dev-server/dev-server-probe.js +9 -0
  313. package/dist/portal/session/dev-server/project-ports.d.ts +21 -0
  314. package/dist/portal/session/dev-server/project-ports.js +62 -0
  315. package/dist/portal/session/facts/departed-network.d.ts +66 -0
  316. package/dist/portal/session/facts/departed-network.js +142 -0
  317. package/dist/portal/session/no-session-diagnosis.d.ts +9 -0
  318. package/dist/portal/session/no-session-diagnosis.js +76 -27
  319. package/dist/portal/session/no-session-next-action.d.ts +14 -0
  320. package/dist/portal/session/no-session-next-action.js +56 -7
  321. package/dist/portal/session/no-session-watch.d.ts +6 -0
  322. package/dist/portal/session/no-session-watch.js +41 -4
  323. package/dist/portal/session/page-commands/undeclared-command.d.ts +9 -3
  324. package/dist/portal/session/page-commands/undeclared-command.js +16 -7
  325. package/dist/portal/session/recorded-gaps.d.ts +1 -1
  326. package/dist/portal/session/recorded-gaps.js +5 -2
  327. package/dist/portal/session/serving-directory.d.ts +10 -0
  328. package/dist/portal/session/serving-directory.js +39 -8
  329. package/dist/portal/session/session-manager.d.ts +10 -0
  330. package/dist/portal/session/session-manager.js +211 -81
  331. package/dist/portal/session/session.js +4 -3
  332. package/dist/portal/session/zero-install-first-call.d.ts +20 -1
  333. package/dist/portal/session/zero-install-first-call.js +34 -2
  334. package/dist/start-wiring.d.ts +30 -2
  335. package/dist/start-wiring.js +74 -9
  336. package/dist/surface/mcp/mcp-proxy.js +10 -2
  337. package/dist/surface/mcp/mcp.js +8 -5
  338. package/dist/surface/mcp/peer/agents-connected.d.ts +6 -0
  339. package/dist/surface/mcp/peer/agents-connected.js +58 -0
  340. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +17 -5
  341. package/dist/surface/mcp/shared-params.d.ts +2 -0
  342. package/dist/surface/mcp/shared-params.js +31 -0
  343. package/dist/surface/tools/act/act-observation.d.ts +40 -2
  344. package/dist/surface/tools/act/act-observation.js +118 -12
  345. package/dist/surface/tools/act/act-preflight.js +38 -18
  346. package/dist/surface/tools/act/act-sequence-retry.d.ts +23 -2
  347. package/dist/surface/tools/act/act-sequence-retry.js +61 -5
  348. package/dist/surface/tools/act/act-target.js +3 -1
  349. package/dist/surface/tools/act/after-match.d.ts +10 -0
  350. package/dist/surface/tools/act/after-match.js +40 -0
  351. package/dist/surface/tools/act/already-true.js +1 -1
  352. package/dist/surface/tools/act/navigation/reload-result.d.ts +12 -1
  353. package/dist/surface/tools/act/navigation/reload-result.js +25 -2
  354. package/dist/surface/tools/act/resolve-target.d.ts +17 -1
  355. package/dist/surface/tools/act/resolve-target.js +59 -9
  356. package/dist/surface/tools/act/sequence-grade.d.ts +15 -1
  357. package/dist/surface/tools/act/sequence-grade.js +45 -27
  358. package/dist/surface/tools/act/settle-in-flight.js +27 -15
  359. package/dist/surface/tools/act-command.d.ts +23 -0
  360. package/dist/surface/tools/act-command.js +50 -0
  361. package/dist/surface/tools/act-sequence-tool.js +81 -50
  362. package/dist/surface/tools/act-tools.d.ts +1 -13
  363. package/dist/surface/tools/act-tools.js +83 -95
  364. package/dist/surface/tools/agent/build-staleness.d.ts +1 -1
  365. package/dist/surface/tools/agent/build-staleness.js +1 -1
  366. package/dist/surface/tools/assert/assert-verdict.js +18 -12
  367. package/dist/surface/tools/browser-tools.js +87 -13
  368. package/dist/surface/tools/compare-tools.d.ts +11 -0
  369. package/dist/surface/tools/compare-tools.js +94 -0
  370. package/dist/surface/tools/coverage-tools.js +1 -1
  371. package/dist/surface/tools/dynamic-tools.js +11 -3
  372. package/dist/surface/tools/empty-session-list.d.ts +2 -0
  373. package/dist/surface/tools/empty-session-list.js +4 -2
  374. package/dist/surface/tools/error-recovery.d.ts +12 -1
  375. package/dist/surface/tools/error-recovery.js +131 -40
  376. package/dist/surface/tools/explore-tools.js +1 -1
  377. package/dist/surface/tools/invoke-tool.js +29 -21
  378. package/dist/surface/tools/lease-coverage-tools.d.ts +49 -0
  379. package/dist/surface/tools/lease-coverage-tools.js +128 -0
  380. package/dist/surface/tools/lease-hint.d.ts +42 -1
  381. package/dist/surface/tools/lease-hint.js +52 -3
  382. package/dist/surface/tools/lease-readiness.d.ts +47 -0
  383. package/dist/surface/tools/lease-readiness.js +126 -0
  384. package/dist/surface/tools/lease-seed.d.ts +16 -1
  385. package/dist/surface/tools/lease-seed.js +37 -4
  386. package/dist/surface/tools/lease-tools.d.ts +3 -41
  387. package/dist/surface/tools/lease-tools.js +104 -124
  388. package/dist/surface/tools/lease-url-identity.d.ts +46 -0
  389. package/dist/surface/tools/lease-url-identity.js +97 -0
  390. package/dist/surface/tools/merge-tools.js +99 -2
  391. package/dist/surface/tools/merged-name-redirect.js +5 -1
  392. package/dist/surface/tools/observe-tools.js +15 -9
  393. package/dist/surface/tools/read/console-pre-attach.d.ts +19 -0
  394. package/dist/surface/tools/read/console-pre-attach.js +23 -0
  395. package/dist/surface/tools/read-tools.js +33 -30
  396. package/dist/surface/tools/real-input-attempt.d.ts +0 -8
  397. package/dist/surface/tools/real-input-attempt.js +143 -28
  398. package/dist/surface/tools/repeat-hint.d.ts +40 -0
  399. package/dist/surface/tools/repeat-hint.js +171 -0
  400. package/dist/surface/tools/run-report.d.ts +2 -2
  401. package/dist/surface/tools/run-report.js +27 -15
  402. package/dist/surface/tools/session-ports.d.ts +14 -0
  403. package/dist/surface/tools/session-ports.js +53 -0
  404. package/dist/surface/tools/tool-kit.d.ts +18 -0
  405. package/dist/surface/tools/tool-kit.js +9 -3
  406. package/dist/surface/tools/tool-surface.js +0 -1
  407. package/dist/surface/tools/tools.js +54 -18
  408. package/dist/surface/tools/type-spelling.d.ts +13 -0
  409. package/dist/surface/tools/type-spelling.js +36 -0
  410. package/dist/telemetry/agent-client.d.ts +6 -0
  411. package/dist/telemetry/agent-client.js +10 -0
  412. package/dist/telemetry/argument-shape.js +17 -7
  413. package/dist/telemetry/cli-telemetry.d.ts +10 -1
  414. package/dist/telemetry/cli-telemetry.js +15 -0
  415. package/dist/telemetry/init-telemetry.d.ts +2 -1
  416. package/dist/telemetry/init-telemetry.js +47 -2
  417. package/dist/telemetry/install-trace.js +23 -4
  418. package/dist/telemetry/onboarding-funnel.d.ts +19 -2
  419. package/dist/telemetry/onboarding-funnel.js +25 -3
  420. package/dist/telemetry/proxy-telemetry.d.ts +2 -1
  421. package/dist/telemetry/proxy-telemetry.js +2 -2
  422. package/dist/telemetry/session-metrics.d.ts +1 -1
  423. package/dist/telemetry/session-metrics.js +67 -27
  424. package/dist/telemetry/telemetry.d.ts +3 -1
  425. package/dist/telemetry/telemetry.js +60 -28
  426. package/dist/telemetry/tool-refused.d.ts +6 -3
  427. package/dist/telemetry/tool-refused.js +15 -3
  428. package/docs/actions.mdx +3 -3
  429. package/docs/agent-cheatsheet.md +1 -1
  430. package/docs/architecture.md +3 -6
  431. package/docs/capabilities.mdx +61 -1
  432. package/docs/cli/affected.mdx +9 -7
  433. package/docs/cli/cloud.mdx +3 -3
  434. package/docs/cli/compare.mdx +94 -0
  435. package/docs/cli/doctor.mdx +41 -2
  436. package/docs/cli/grade.mdx +97 -0
  437. package/docs/cli/help.mdx +4 -2
  438. package/docs/cli/license.mdx +13 -12
  439. package/docs/cli/restart.mdx +7 -5
  440. package/docs/cli/rollback.mdx +5 -5
  441. package/docs/cli/setup.mdx +13 -2
  442. package/docs/cli/status.mdx +4 -0
  443. package/docs/cli/stop.mdx +3 -3
  444. package/docs/cli/update.mdx +2 -2
  445. package/docs/cli/verify.mdx +23 -1
  446. package/docs/cli.mdx +34 -24
  447. package/docs/deploy-checks.md +25 -0
  448. package/docs/desktop.mdx +1 -1
  449. package/docs/enterprise.md +17 -22
  450. package/docs/environment.mdx +1 -0
  451. package/docs/first-drive.md +1 -1
  452. package/docs/flows.md +11 -1
  453. package/docs/frameworks.mdx +9 -9
  454. package/docs/getting-started.md +1 -1
  455. package/docs/install-manual.mdx +16 -1
  456. package/docs/license-activation.mdx +3 -3
  457. package/docs/packages/engine.mdx +1 -1
  458. package/docs/packages/server.mdx +1 -1
  459. package/docs/packages/tauri.mdx +1 -1
  460. package/docs/packages/test.mdx +1 -1
  461. package/docs/packages.mdx +1 -1
  462. package/docs/platform-integration.md +1 -1
  463. package/docs/predicates.mdx +1 -1
  464. package/docs/quickstart.mdx +68 -49
  465. package/docs/skill-setup.md +1 -1
  466. package/docs/skill.md +14 -13
  467. package/docs/telemetry.md +6 -4
  468. package/docs/tools/navigate.mdx +1 -1
  469. package/docs/tools/verify.mdx +4 -1
  470. package/docs/troubleshooting.mdx +1 -1
  471. package/docs/usage.md +17 -14
  472. package/package.json +18 -14
  473. package/LICENSE-ENTERPRISE +0 -37
  474. package/dist/features/ee/audit-log.d.ts +0 -14
  475. package/dist/features/ee/audit-log.js +0 -11
  476. package/dist/features/exhaust/exhaust-run.d.ts +0 -33
  477. package/dist/features/exhaust/exhaust-run.js +0 -82
@@ -2,13 +2,14 @@
2
2
  * Replay's arrival at a flow's start page: navigate (or reload) before step 1, wait for the session
3
3
  * the SDK reconnects as, and say what happened when it does not.
4
4
  */
5
- import { EventType, ReticleCommand, } from '@reticlehq/core';
6
- import { establishedState, samePath, startPathBudgetMs } from './flow-journey.js';
5
+ import { AnchorKind, EventType, ReticleCommand, } from '@reticlehq/core';
6
+ import { declaredRoute, establishedState, fillRouteParams, isRoutePattern, onRoute, samePath, startPathBudgetMs, unmetRouteClaim, } from './flow-journey.js';
7
7
  import { asRecord } from '@reticlehq/core';
8
8
  import { navigablePath, routeOfEvent, routeOfUrl, } from '@reticlehq/engine/question/predicate/predicate-route.js';
9
9
  import { carryReticleIdentity } from '../../surface/tools/lease-tools.js';
10
10
  import { anchorPrecondition, anchorQueryArgs } from './flow-step-runners.js';
11
11
  import { queryRefs } from './replay.js';
12
+ import { refFor } from './flow-anchor.js';
12
13
  import { isDocumentGoneError } from '../../portal/session/facts/session-replaced.js';
13
14
  /**
14
15
  * The route the tab is on now: the last observed route.change, falling back to the pathname of the
@@ -136,12 +137,20 @@ async function firstStepResolvesHere(session, flow) {
136
137
  return false;
137
138
  }
138
139
  try {
139
- return 0 < queryRefs(await session.command(ReticleCommand.QUERY, args)).length;
140
+ // THE control the recording meant, by the same rule replay applies to the step: one match, or
141
+ // the recorded position among exactly as many namesakes. A name that also appears elsewhere
142
+ // (30 "Edit" links on another page, 10 where the flow was recorded) is not "step 1 starts here".
143
+ return (refFor(first.anchor, queryRefs(await session.command(ReticleCommand.QUERY, args))) !==
144
+ undefined);
140
145
  }
141
146
  catch {
142
147
  return false;
143
148
  }
144
149
  }
150
+ /** An anchor that is the app's own name for one control (a testid, a component): the same on every page. */
151
+ function namesTheControl(anchor) {
152
+ return AnchorKind.TESTID === anchor?.kind || AnchorKind.COMPONENT === anchor?.kind;
153
+ }
145
154
  /** The replay result, with how long replay waited for its start page when that went past the budget. */
146
155
  export function withStartPageWait(result, arrival) {
147
156
  return arrival.wait === undefined ? result : { ...result, startPageWait: arrival.wait };
@@ -150,6 +159,20 @@ export function withStartPageWait(result, arrival) {
150
159
  function waitOf(outcome) {
151
160
  return outcome.wait === undefined ? {} : { wait: outcome.wait };
152
161
  }
162
+ /*
163
+ * The page each tab was on when its last replay ended, by session id. A page load gives the tab a
164
+ * new id, so an entry still matches only when nothing loaded since: the query on that page is what
165
+ * the last flow left, not what the caller chose.
166
+ * ponytail: one entry per replayed tab, never pruned; prune on session close if tabs ever churn.
167
+ */
168
+ const leftByReplay = new Map();
169
+ /** Record where a replay left the tab, so the next reset does not keep that flow's query. */
170
+ export function noteReplayEnded(session) {
171
+ const path = currentPathOf(session);
172
+ if (path !== undefined) {
173
+ leftByReplay.set(session.id, path);
174
+ }
175
+ }
153
176
  /**
154
177
  * Replay's half of the FlowFile contract: put the tab on the flow's `startPath` before step 1, and
155
178
  * RELOAD it if it is already there.
@@ -164,6 +187,10 @@ function waitOf(outcome) {
164
187
  * or from the wrong page. Silence is not an opt-out: a flow that depends on leftovers without
165
188
  * saying so is a flow whose green means nothing on a fresh machine, and CI is a fresh machine.
166
189
  *
190
+ * A route in `requires` is not an opt-out. It is the page the flow needs, and replay goes there:
191
+ * see `arriveAtDeclaredRoute`. A suite ran such a flow on the page the previous flow left open,
192
+ * and its anchors then failed, or matched ambiguously, on an unrelated page (#2034).
193
+ *
167
194
  * A full-page load tears down the session socket, so the navigation must happen here — before any
168
195
  * step runs — and the replay continues on the session the SDK reconnects as (found via the same
169
196
  * tombstone rebind that lets `resolve(oldId)` answer after any navigation). Best-effort by design:
@@ -174,6 +201,16 @@ function waitOf(outcome) {
174
201
  export async function arriveAtStartPath(sessions, session, flow, timeoutMs = startPathBudgetMs(flow), clock = REAL_ARRIVAL_CLOCK,
175
202
  /** Whether the tab is still loading. Replay passes one for a pool lease, the only tab it can ask. */
176
203
  stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
204
+ const move = {
205
+ timeoutMs,
206
+ clock,
207
+ loadingCapMs,
208
+ ...(stillLoading === undefined ? {} : { stillLoading }),
209
+ };
210
+ const route = declaredRoute(flow);
211
+ if (route !== undefined) {
212
+ return arriveAtDeclaredRoute(sessions, session, flow, route, move);
213
+ }
177
214
  const target = flow.startPath;
178
215
  if (target === undefined || 0 === target.length) {
179
216
  return {};
@@ -190,30 +227,50 @@ stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
190
227
  // A route mismatch that step 1 can start from anyway is not worth a page load: navigating away
191
228
  // from a persistent anchor could only hurt, and did. Arriving is the goal; resetting a tab that is
192
229
  // ALREADY here is a different decision, taken above, and this must not override it.
193
- if (!here && (await firstStepResolvesHere(session, flow))) {
230
+ // Only for an anchor that names the control itself (a testid, a component): a role and a name
231
+ // found on another page can be that page's own control, and step 1 then acts on the wrong one.
232
+ if (!here &&
233
+ namesTheControl(flow.steps?.[0]?.anchor) &&
234
+ (await firstStepResolvesHere(session, flow))) {
194
235
  return {};
195
236
  }
237
+ // A refused navigation left the tab untouched, and replay goes on with the connected session.
238
+ return (await moveTo(sessions, session, flow, target, here, current, move)) ?? {};
239
+ }
240
+ /**
241
+ * Navigate (or reload, when `here`) to `target` and say what came back. Undefined when the tab was
242
+ * not moved at all: no usable base URL, or the browser refused the navigation.
243
+ */
244
+ async function moveTo(sessions, session, flow, target, here, current, move) {
196
245
  let destination;
197
246
  try {
198
247
  // startPath is a pathname (a host belongs to the machine, not the journey) — resolve it
199
248
  // against the tab's own URL to get something the browser can be sent to. Already HERE, the
200
249
  // reset reloads the page the tab is on: `samePath` ignored a query the flow did not record, and
201
250
  // navigating to `target` would strip it, so the replay would test a different page than the one
202
- // it just agreed it was on.
203
- destination = new URL(here ? current : target, session.url).toString();
251
+ // it just agreed it was on. A query that the last replay left is not kept: it is the previous
252
+ // flow's state, and keeping it gave the next flow a filtered page that it never recorded.
253
+ const keepQuery = here && leftByReplay.get(session.id) !== current;
254
+ destination = new URL(keepQuery ? current : target, session.url).toString();
204
255
  }
205
256
  catch {
206
- return {}; // no usable base URL — nowhere to navigate from
257
+ return undefined; // no usable base URL — nowhere to navigate from
207
258
  }
208
259
  // Measured either side of the reset, and only when the reset is a reload: reachable before and
209
260
  // gone after is the reload's doing, not the flow file's. Without this, an app holding its session
210
261
  // in memory comes back signed out and step 1 blames a component that is completely fine.
211
262
  const resolvedBefore = here && (await firstStepResolvesHere(session, flow));
212
- const outcome = await navigateAndAwait(sessions, session, destination, target, timeoutMs, clock, here, stillLoading, loadingCapMs);
263
+ const outcome = await navigateAndAwait(sessions, session, destination, target, move.timeoutMs, move.clock, {
264
+ isReload: here,
265
+ ...(move.stillLoading === undefined ? {} : { stillLoading: move.stillLoading }),
266
+ loadingCapMs: move.loadingCapMs,
267
+ });
213
268
  if ('lost' === outcome.kind) {
214
269
  const why = outcome.stillLoading
215
270
  ? 'The page was still loading when replay stopped waiting: check that the app finishes loading, then replay'
216
- : 'A slow or backgrounded tab can take longer to come back: bring it to the front and replay';
271
+ : 'A dev server that compiles on the first load can take longer than that: raise the wait with ' +
272
+ '`timeoutMs` on step 1 or `signalTimeoutMs` in the flow file, then replay. A backgrounded tab ' +
273
+ 'can also be slow: bring it to the front';
217
274
  return {
218
275
  lost: `replay ${here ? 'reloaded' : 'navigated to'} ${target} before step 1 and no page was connected ` +
219
276
  `after ${String(outcome.waitedMs)}ms, so the session it was driving is gone and nothing ran. ${why}`,
@@ -221,7 +278,7 @@ stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
221
278
  };
222
279
  }
223
280
  if ('refused' === outcome.kind) {
224
- return {};
281
+ return undefined;
225
282
  }
226
283
  if ('redirected' === outcome.kind) {
227
284
  const path = currentPathOf(outcome.session) ?? 'another route';
@@ -241,6 +298,107 @@ stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
241
298
  ...waitOf(outcome),
242
299
  };
243
300
  }
301
+ /**
302
+ * The arrival for a replay that continues at a step and so does not move the tab. A declared route
303
+ * claim must still hold where the tab is, as it did when it was a precondition the run checked.
304
+ */
305
+ export function routeClaimsWhereTheTabIs(flow, session) {
306
+ const route = declaredRoute(flow);
307
+ if (route === undefined) {
308
+ return {};
309
+ }
310
+ const current = currentPathOf(session);
311
+ const unmet = current === undefined
312
+ ? 'replay cannot see which page it is on'
313
+ : unmetRouteClaim(flow, current);
314
+ if (unmet === undefined) {
315
+ return {};
316
+ }
317
+ return {
318
+ unreached: unreachedReason(route, current, `replay continues mid-flow there, and ${unmet}`),
319
+ };
320
+ }
321
+ /**
322
+ * Replay's arrival for a flow that declares the route it needs in `requires` (#2034).
323
+ *
324
+ * The tab goes to that route before step 1, the same way it goes to a `startPath`, and the same
325
+ * reset applies once it is there. Two differences, both because the flow SAID where it must be:
326
+ *
327
+ * - A route with an entity id (`/cases/:id/notes`) keeps the id of the page the tab is on when that
328
+ * page matches. The recorded address names one record, and that record can be deleted since: a
329
+ * replay sent there ran a generic flow on a fixture that no longer existed and answered `unknown`.
330
+ * - When replay cannot put the tab on the route, it says so and nothing runs. Running anyway gave a
331
+ * verdict about another page, reported as a missing or ambiguous anchor.
332
+ */
333
+ async function arriveAtDeclaredRoute(sessions, session, flow, route, move) {
334
+ const current = currentPathOf(session);
335
+ if (current === undefined) {
336
+ return {
337
+ unreached: unreachedReason(route, undefined, 'replay cannot see which page it is on'),
338
+ };
339
+ }
340
+ const here = onRoute(current, route);
341
+ // The opt-out keeps the tab as it is. It does not make another page the right one.
342
+ if (0 < establishedState(flow).length) {
343
+ if (unmetRouteClaim(flow, current) === undefined) {
344
+ return {};
345
+ }
346
+ return {
347
+ unreached: unreachedReason(route, current, 'the flow also declares state that a page load would discard, so replay does not move the tab'),
348
+ };
349
+ }
350
+ const target = routeTarget(flow, route, current, here);
351
+ if (target === undefined) {
352
+ return {
353
+ unreached: unreachedReason(route, current, 'the route names an entity id, and the flow records no address on that route to open'),
354
+ };
355
+ }
356
+ const moved = await moveTo(sessions, session, flow, target, samePath(current, target), current, move);
357
+ if (moved === undefined) {
358
+ return { unreached: unreachedReason(route, current, `the page refused to open ${target}`) };
359
+ }
360
+ const landed = moved.session === undefined ? current : currentPathOf(moved.session);
361
+ // Every declared route claim, its `contains` too, is checked on the page replay arrived at.
362
+ const unmet = landed === undefined ? 'replay cannot see which page it is on' : unmetRouteClaim(flow, landed);
363
+ if (unmet === undefined) {
364
+ return moved;
365
+ }
366
+ const { redirected, ...rest } = moved;
367
+ const why = redirected === undefined
368
+ ? `replay opened ${target}, and ${unmet}`
369
+ : `replay opened ${target}, and the app sent the tab to another page`;
370
+ return { ...rest, unreached: unreachedReason(route, landed, why) };
371
+ }
372
+ /**
373
+ * Where replay sends the tab for a declared route.
374
+ *
375
+ * A pattern that the tab already matches: the tab's own page, so its id is kept. A pattern whose
376
+ * ids the tab can give (another section of the same case): the route with those ids. Else the
377
+ * flow's `startPath` when it is on the route, because it is the page the journey was recorded on.
378
+ * Else the route itself when it is a plain path. A pattern with no address to open has no target.
379
+ */
380
+ function routeTarget(flow, route, current, here) {
381
+ const pattern = isRoutePattern(route);
382
+ if (here && pattern) {
383
+ // Without its query: `moveTo` keeps the query unless the previous replay left it.
384
+ return current.replace(/\?[^#]*/, '');
385
+ }
386
+ const filled = pattern ? fillRouteParams(route, current) : undefined;
387
+ if (filled !== undefined) {
388
+ return filled;
389
+ }
390
+ const start = flow.startPath;
391
+ if (start !== undefined && 0 < start.length && onRoute(start, route)) {
392
+ return start;
393
+ }
394
+ return pattern ? undefined : route;
395
+ }
396
+ /** Why a flow with a declared route did not run, and the one move that lets it. */
397
+ function unreachedReason(route, current, why) {
398
+ const where = current ?? 'a page replay cannot see';
399
+ return (`this flow declares that it starts on ${route}, but the tab is on ${where}: ${why}. ` +
400
+ `Nothing ran and nothing was proved. Open a page on ${route} (reticle_navigate), then replay`);
401
+ }
244
402
  /**
245
403
  * Why step 1 failed after the reset, and the one line that opts the flow out.
246
404
  *
@@ -256,11 +414,32 @@ function resetCostHint(flow, target) {
256
414
  return (`replay reloaded ${target} before step 1 and the first anchor did not come back — this flow ` +
257
415
  `starts from state a page load discards. ${optOut}, or record it from a cold page`);
258
416
  }
259
- export async function navigateAndAwait(sessions, session, destination, expectedPath, timeoutMs, clock = REAL_ARRIVAL_CLOCK,
260
- /** True when the destination is the page we are already on — see `arrivedSuccessor`. */
261
- isReload = false,
262
- /** Whether the navigated page is still loading; absent when it cannot be asked. */
263
- stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
417
+ /**
418
+ * Whether assigning `to` from `from` is a jump within the same document. That is the case when the
419
+ * URLs differ at most in the fragment and `to` has a fragment; a browser then loads no page. Without
420
+ * a fragment, the same URL reloads by itself. Undefined or unparsable URLs are not a jump.
421
+ */
422
+ export function isFragmentJump(from, to) {
423
+ if (from === undefined) {
424
+ return false;
425
+ }
426
+ try {
427
+ const a = new URL(from);
428
+ const b = new URL(to);
429
+ if (0 === b.hash.length) {
430
+ return false;
431
+ }
432
+ a.hash = '';
433
+ b.hash = '';
434
+ return a.href === b.href;
435
+ }
436
+ catch {
437
+ return false;
438
+ }
439
+ }
440
+ export async function navigateAndAwait(sessions, session, destination, expectedPath, timeoutMs, clock = REAL_ARRIVAL_CLOCK, options = {}) {
441
+ const { isReload = false, stillLoading, acceptRedirect = false } = options;
442
+ const loadingCapMs = options.loadingCapMs ?? START_PATH_LOADING_CAP_MS;
264
443
  // A leased tab is addressed by URL params, so navigating without them would strand the lease.
265
444
  const url = carryReticleIdentity(session.url, destination);
266
445
  try {
@@ -268,6 +447,11 @@ stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
268
447
  if (!outcome.ok || true !== asRecord(outcome.result)['ok']) {
269
448
  return { kind: 'refused' };
270
449
  }
450
+ // A same-document URL with a fragment loads no page: the browser only jumps within it. Ask for
451
+ // the load this function waits for. A hash-routed app's replay never started without it.
452
+ if (isFragmentJump(session.url, url)) {
453
+ await session.command(ReticleCommand.REFRESH, {});
454
+ }
271
455
  }
272
456
  catch (error) {
273
457
  // A navigation that unloads the page rejects the very command that asked for it — the transport
@@ -291,6 +475,9 @@ stillLoading, loadingCapMs = START_PATH_LOADING_CAP_MS) {
291
475
  if (true === arrived?.matches) {
292
476
  return { kind: 'arrived', session: arrived.session, ...extendedWait() };
293
477
  }
478
+ if (acceptRedirect && arrived !== undefined) {
479
+ return { kind: 'redirected', session: arrived.session, ...extendedWait() };
480
+ }
294
481
  if (clock.now() >= deadline) {
295
482
  // A live redirect is a different result from no SDK reconnection at all.
296
483
  if (arrived !== undefined) {
@@ -1,6 +1,7 @@
1
1
  import { AnchorKind, type Drift, type FlowAnchor, type FlowReplayResult, type FlowStep, type FlowStepResult, type Predicate } from '@reticlehq/core';
2
2
  import type { FlowReplaySession, Sleep } from './flow-replay-types.js';
3
3
  import { type Reresolved } from './flow-anchor.js';
4
+ import { type Baselines } from '@reticlehq/engine/evidence/baseline.js';
4
5
  /** The live act_sequence tool gives each step this transport budget when none was supplied. */
5
6
  export declare const DEFAULT_SEQUENCE_STEP_TIMEOUT_MS = 8000;
6
7
  export declare function runRoleStep(session: FlowReplaySession, step: FlowStep, index: number, anchor: Extract<FlowAnchor, {
@@ -83,7 +84,15 @@ export declare function anchorPrecondition(anchor: FlowAnchor): Predicate | unde
83
84
  * Left alone, so the ordinary verdict stands, when anything else is in the run: a drifted anchor is
84
85
  * drift whatever else happened, and a failure that is not staleness is a failure.
85
86
  */
86
- export declare function staleTargetResult(name: string, steps: readonly FlowStepResult[]): FlowReplayResult | undefined;
87
+ export declare function staleTargetResult(name: string, steps: readonly FlowStepResult[],
88
+ /**
89
+ * `startControlRequired`: replay loaded the start page itself, with no redirect, and the caller
90
+ * asked that a missing step 1 control fail. Then the miss means the app does not offer the control
91
+ * the journey starts with (#2061), so it stays drift. Without it, the miss is not proved.
92
+ */
93
+ options?: {
94
+ startControlRequired?: boolean;
95
+ }): FlowReplayResult | undefined;
87
96
  /**
88
97
  * The honest answer when a step acted on a target no person could have clicked (covered, of no
89
98
  * size, off screen). The replay stopped there, and nothing about the app was decided: undecided as a
@@ -93,19 +102,11 @@ export declare function staleTargetResult(name: string, steps: readonly FlowStep
93
102
  export declare function unreachableTargetResult(name: string, steps: readonly FlowStepResult[]): FlowReplayResult | undefined;
94
103
  /**
95
104
  * Run an act_sequence step: resolve every sub-step's OWN anchor, then dispatch the whole thing as one
96
- * ACT_SEQUENCE — the same shape `replayProgram` already uses, so a recorded sequence and a saved one
97
- * execute identically.
98
- *
99
- * `replayFlow` had no sequence branch at all. It dispatches on `anchor.kind`, so a saved sequence fell
100
- * to the testid runner and ran ONE act with `action: ''` (a saved sequence carries no top-level
101
- * action) — sub-steps 2..n never executed. Fixing the anchor without this would have turned a visible
102
- * drift into a silent partial replay reporting ok.
105
+ * ACT_SEQUENCE, the shape `replayProgram` uses, so a recorded sequence and a saved one run the same.
103
106
  */
104
107
  export declare function runSequenceStep(session: FlowReplaySession, step: FlowStep, index: number, subs: readonly FlowStep[], confirmDangerous: boolean, sleep: Sleep,
105
108
  /** Testids whose presence is deliberately NOT asserted — the LLM-output case. */
106
109
  dynamic?: ReadonlySet<string>,
107
- /**
108
- * Judge one sub-step's `expect` over the window from `since`, which opens just before that
109
- * sub-step's dispatch. Omitted for a setup step, whose consequences are not checked.
110
- */
111
- judge?: (expectation: Predicate, since: number) => Promise<Drift | undefined>): Promise<FlowStepResult>;
110
+ /** Judge a sub-step's `expect` from `since`, just before its dispatch, against the `before`
111
+ * reading; omitted for a setup step, whose consequences are not checked. */
112
+ judge?: (expectation: Predicate, since: number, before?: Baselines) => Promise<Drift | undefined>): Promise<FlowStepResult>;