@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
@@ -1,9 +1,10 @@
1
1
  import { SECRET_FIELD_ARG, SECRET_NAME_ARG, secretKeyForFill, secretValue, } from './fields/flow-secret-field.js';
2
- import { EventType, FlowPredicateSchema, MUTATING_METHODS, Verified, isDevToolingUrl, pathOf, } from '@reticlehq/core';
2
+ import { EventType, FlowPredicateSchema, MUTATING_METHODS, isDevToolingUrl, } from '@reticlehq/core';
3
3
  import { DANGEROUS_ACTION_CONFIRM_ARG, DOCUMENT_ANCHOR_ROLE, ReticleCommand, QueryBy, isGlobalPressCall, } from '@reticlehq/core';
4
4
  import { ReticleTool, invokedFlowMissing } from '@reticlehq/core';
5
5
  import { formatStepAddress } from 'open-verification';
6
6
  import { refFor } from './flow-anchor.js';
7
+ import { navigablePath, routeOfUrl } from '@reticlehq/engine/question/predicate/predicate-route.js';
7
8
  import { asRecord, asString } from '@reticlehq/core';
8
9
  /**
9
10
  * The note attached when a testid resolves to multiple live elements (the first match is used).
@@ -21,9 +22,36 @@ function ambiguousRoleNote(role, name) {
21
22
  * replay engines (replayProgram + flow-replay's step runner) so element extraction — the core of anchor
22
23
  * resolution — can't drift between them.
23
24
  */
25
+ /**
26
+ * The refs of a role query's matches that have NO accessible name, in page order.
27
+ *
28
+ * A role query without a name returns every control of the role, named ones included. A nameless
29
+ * anchor's recorded position (`nth` of `of`) counts only the nameless ones — an icon-only edit
30
+ * button is the 2nd nameless button of its row, not the 5th button — so the named ones are dropped
31
+ * before the position is read.
32
+ */
33
+ export function namelessRefs(result) {
34
+ if (!result.ok) {
35
+ return [];
36
+ }
37
+ const elements = asRecord(result.result)['elements'];
38
+ if (!Array.isArray(elements)) {
39
+ return [];
40
+ }
41
+ const refs = [];
42
+ for (const element of elements) {
43
+ const e = asRecord(element);
44
+ const ref = asString(e['ref']);
45
+ if (0 === (asString(e['name']) ?? '').trim().length && ref !== undefined) {
46
+ refs.push(ref);
47
+ }
48
+ }
49
+ return refs;
50
+ }
24
51
  export function queryRefs(result) {
25
- if (!result.ok)
52
+ if (!result.ok) {
26
53
  return [];
54
+ }
27
55
  const payload = asRecord(result.result);
28
56
  const elements = Array.isArray(payload['elements']) ? payload['elements'] : [];
29
57
  return elements.map((e) => asString(asRecord(e)['ref']) ?? '').filter((r) => r.length > 0);
@@ -47,12 +75,14 @@ export function replayActionArgs(value, confirmDangerous = false, field) {
47
75
  const key = field === undefined ? undefined : secretKeyForFill(args, field);
48
76
  delete args[SECRET_NAME_ARG];
49
77
  delete args[SECRET_FIELD_ARG];
50
- if (confirmDangerous)
78
+ if (confirmDangerous) {
51
79
  args[DANGEROUS_ACTION_CONFIRM_ARG] = true;
80
+ }
52
81
  if (key !== undefined) {
53
82
  const supplied = secretValue(key, process.env);
54
- if (supplied !== undefined && supplied.length > 0)
83
+ if (supplied !== undefined && supplied.length > 0) {
55
84
  args['value'] = supplied;
85
+ }
56
86
  }
57
87
  return args;
58
88
  }
@@ -62,37 +92,52 @@ export function replayActionArgs(value, confirmDangerous = false, field) {
62
92
  */
63
93
  function recordedFieldName(step) {
64
94
  const by = asString(step['by']);
65
- if (QueryBy.TESTID === by)
95
+ if (QueryBy.TESTID === by) {
66
96
  return asString(step['value']);
67
- if (QueryBy.ROLE === by)
97
+ }
98
+ if (QueryBy.ROLE === by) {
68
99
  return asString(step['name']);
100
+ }
69
101
  return undefined;
70
102
  }
71
103
  /** The element's source location from an action result, when the framework stamped one. */
72
104
  function sourceFromResult(res) {
73
105
  const source = asRecord(res['source']);
74
- if (typeof source['file'] !== 'string' || typeof source['line'] !== 'number')
106
+ if (typeof source['file'] !== 'string' || typeof source['line'] !== 'number') {
75
107
  return undefined;
108
+ }
76
109
  const out = { file: source['file'], line: source['line'] };
77
- if ('number' === typeof source['column'])
110
+ if ('number' === typeof source['column']) {
78
111
  out['column'] = source['column'];
112
+ }
79
113
  return out;
80
114
  }
81
115
  /**
82
- * The pathname of a session's live url, or undefined when it has none yet.
116
+ * The page a session's live url is on, as a NAVIGABLE path: pathname + query + hash, with
117
+ * Reticle's own params dropped. Undefined when the session has no url yet.
83
118
  *
84
- * Pathname rather than the whole url, because that is what `startPath` is compared against and what
85
- * a hash-routed app makes meaningless in the document location — see routeOfEvent.
119
+ * Every recorded page comes from here: a step's page, the route a tape is cut on, and the
120
+ * `startPath` and route `requires` of a saved flow. The pathname alone dropped the query, so a
121
+ * journey leased on `/?showModal=login` saved `startPath: "/"`, and its replay asserted "the modal
122
+ * is absent" on a page where the modal never opens. Under a hash router it dropped the hash too,
123
+ * which made every page `/` (#1411).
86
124
  */
87
- export { pathOf };
125
+ export function pageOf(url) {
126
+ if (url === undefined) {
127
+ return undefined;
128
+ }
129
+ const parts = routeOfUrl(url);
130
+ return parts === undefined ? undefined : navigablePath(parts);
131
+ }
88
132
  /**
89
133
  * Did the app send a write request in this window? A step that did is saved `writes: true`, so a
90
134
  * replay does not repeat it unasked. The dev server's own traffic is not the app's.
91
135
  */
92
136
  export function wroteIn(events) {
93
137
  return events.some((event) => {
94
- if (EventType.NET_REQUEST !== event.type)
138
+ if (EventType.NET_REQUEST !== event.type) {
95
139
  return false;
140
+ }
96
141
  const method = asString(event.data['method'])?.toUpperCase() ?? '';
97
142
  return MUTATING_METHODS.includes(method) && !isDevToolingUrl(asString(event.data['url']));
98
143
  });
@@ -122,7 +167,9 @@ route,
122
167
  /** The session that acted: only recordings it started take the step. */
123
168
  session,
124
169
  /** The act's window sent a write request; see `wroteIn`. */
125
- wrote = false) {
170
+ wrote = false,
171
+ /** The act as the ambient tape keeps it, when that differs. See RecordingStore.capture. */
172
+ ambientArgs) {
126
173
  // NO `active()` gate. `RecordingStore.capture` opens the AMBIENT tape on its first step, and that
127
174
  // branch was unreachable from here: this returned early whenever nothing was open, and the only
128
175
  // thing that opened anything was `reticle_record { action: "start" }`. So the comment on `capture`
@@ -134,8 +181,15 @@ wrote = false) {
134
181
  // recorded cannot contribute to either.
135
182
  // A click on Reticle's own panel (the HUD exposed) is not a step of the app's journey: saved, the
136
183
  // app's flow pressed Run Harness on replay, a paid drive, under an intent that never named it.
137
- if (true === asRecord(res)['reticleUi'])
184
+ if (true === asRecord(res)['reticleUi']) {
138
185
  return;
186
+ }
187
+ const step = capturedStep(args, res, route, wrote);
188
+ const ambient = ambientArgs === undefined ? undefined : capturedStep(ambientArgs, res, route, wrote);
189
+ recordings.capture(step, route, session, ambient);
190
+ }
191
+ /** One act as a recorded step, with the claim the agent declared on it. */
192
+ function capturedStep(args, res, route, wrote) {
139
193
  const step = compileActStep(args, res);
140
194
  // Keep the assertion the agent actually made. `act_and_wait { until }` IS the agent saying what
141
195
  // success means — the large majority of calls carry one — and dropping it produced a flow graded
@@ -143,36 +197,50 @@ wrote = false) {
143
197
  // story failing at its last step. See enforceableExpect below.
144
198
  const declared = args['until'] ?? args['predicate'];
145
199
  const expect = enforceableExpect(declared);
146
- if (expect !== undefined)
200
+ if (expect !== undefined) {
147
201
  step.expect = expect;
148
- else if (declared !== undefined)
202
+ }
203
+ else if (declared !== undefined) {
149
204
  step.unkeptExpect = UNKEPT_EXPECT;
150
- if (route !== undefined)
205
+ }
206
+ if (route !== undefined) {
151
207
  step.page = route;
208
+ }
152
209
  const intent = asString(args['intent'])?.trim();
153
- if (intent !== undefined && intent.length > 0)
210
+ if (intent !== undefined && intent.length > 0) {
154
211
  step.intent = intent;
155
- if (wrote)
212
+ }
213
+ if (wrote) {
156
214
  step.writes = true;
157
- recordings.capture(step, route, session);
215
+ }
216
+ return step;
158
217
  }
159
218
  /**
160
- * Capture an act_and_wait once its verdict is known, keeping `until` as the step's expectation only
161
- * on a yes. Recorded before the verdict, a step kept an `until` that came back `no` or `no-fault` —
162
- * a regression test asserting something never once observed to hold because of the action. The
163
- * action itself is always recorded: it happened, and replay needs it to reach the next step.
219
+ * Capture an act_and_wait once its verdict is known.
220
+ *
221
+ * The rule act_sequence keeps (#988). A recording somebody opened keeps every claim the agent
222
+ * declared, held or not: dropping a refuted one saved a flow that replayed green on the defect it
223
+ * had caught. The ambient tape keeps a claim only if the action made it hold (`held`), so a flow cut
224
+ * from it never replays a claim that was never once true because of the action. The action is
225
+ * always recorded: replay needs it to reach the next step.
226
+ *
227
+ * Keyed on `held`, not on `verified: yes`. A claim the action made hold under an `unknown` or a
228
+ * contradicted verdict is still what the agent proved about the page, and dropping it left the
229
+ * replay with no check at all. One function decides both tapes: a second rule that took the claim off the tape
230
+ * after the fact ran before this capture, so it took the PREVIOUS step's claim, which had passed.
164
231
  */
165
- export function captureVerdictedAct(recordings, args, res, route, verified, session,
232
+ export function captureVerdictedAct(recordings, args, res, route, held, session,
166
233
  /** The act's window sent a write request; see `wroteIn`. */
167
234
  wrote = false) {
168
235
  const { until: _until, predicate: _predicate, ...unproved } = args;
169
- captureAct(recordings, Verified.YES === verified ? args : unproved, res, route, session, wrote);
236
+ captureAct(recordings, args, res, route, session, wrote, held ? undefined : unproved);
170
237
  }
171
238
  /** Fold a PASSING standalone assertion into the step it proved. See RecordingStore.attachExpect. */
172
239
  export function captureAssertion(recordings, raw, session) {
173
240
  const expect = enforceableExpect(raw);
174
- if (expect !== undefined)
241
+ if (expect !== undefined) {
175
242
  recordings.attachExpect(expect, session);
243
+ }
176
244
  }
177
245
  /**
178
246
  * A declared predicate, as a recorded expectation — or nothing.
@@ -186,8 +254,9 @@ export function captureAssertion(recordings, raw, session) {
186
254
  * Every one of those was a claim the agent made and the file did not keep.
187
255
  */
188
256
  function enforceableExpect(raw) {
189
- if (raw === undefined)
257
+ if (raw === undefined) {
190
258
  return undefined;
259
+ }
191
260
  // The flow file's own schema, so capture keeps exactly what a load would accept — a predicate
192
261
  // holding a session ref is refused by both, rather than recorded here and rejected on read.
193
262
  const parsed = FlowPredicateSchema.safeParse(raw);
@@ -232,8 +301,9 @@ function compileAnchorArgs(r, ref, action, actArgs) {
232
301
  const compiled = anchorArgs(r, ref, action, actArgs);
233
302
  // The SDK says the target holds a secret (a password input, whatever its label). Carried beside
234
303
  // the anchor so the saved flow redacts the fill by what the field IS, not by what it is called.
235
- if (true === r['secret'])
304
+ if (true === r['secret']) {
236
305
  compiled.args[SECRET_FIELD_ARG] = true;
306
+ }
237
307
  return compiled;
238
308
  }
239
309
  function anchorArgs(r, ref, action, actArgs) {
@@ -262,10 +332,15 @@ function anchorArgs(r, ref, action, actArgs) {
262
332
  action,
263
333
  args: actArgs,
264
334
  };
265
- if (source !== undefined)
335
+ if (source !== undefined) {
266
336
  testidArgs['source'] = source;
267
- if (testidOf !== undefined)
337
+ }
338
+ if (testidOf !== undefined) {
268
339
  testidArgs['of'] = testidOf;
340
+ if ('number' === typeof r['testidNth'] && 0 <= r['testidNth']) {
341
+ testidArgs['nth'] = r['testidNth'];
342
+ }
343
+ }
269
344
  return { args: testidArgs, stable: true };
270
345
  }
271
346
  // Role + NAME before component: a component/source anchor names the JSX site, so every row's copy
@@ -282,21 +357,64 @@ function anchorArgs(r, ref, action, actArgs) {
282
357
  action,
283
358
  args: actArgs,
284
359
  };
285
- if (source !== undefined)
360
+ if (source !== undefined) {
286
361
  roleArgs['source'] = source;
362
+ }
287
363
  if ('number' === typeof r['nth'] && 'number' === typeof r['of']) {
288
364
  roleArgs['nth'] = r['nth'];
289
365
  roleArgs['of'] = r['of'];
290
366
  }
367
+ if (Array.isArray(r['within'])) {
368
+ roleArgs['within'] = r['within'];
369
+ }
291
370
  return { args: roleArgs, stable: true };
292
371
  }
372
+ // A role and NO accessible name (an icon-only button): the role plus the control's position among
373
+ // the nameless controls of that role. Without this branch the step fell to a component anchor or
374
+ // to the stale ref, and a replay on a fresh page could not find the control again.
375
+ if (role !== undefined &&
376
+ role !== 'generic' &&
377
+ name === undefined &&
378
+ asString(r['component']) === undefined) {
379
+ const namelessArgs = {
380
+ by: QueryBy.ROLE,
381
+ value: role,
382
+ action,
383
+ args: actArgs,
384
+ };
385
+ if (source !== undefined) {
386
+ namelessArgs['source'] = source;
387
+ }
388
+ if ('number' === typeof r['nth'] && 'number' === typeof r['of']) {
389
+ namelessArgs['nth'] = r['nth'];
390
+ namelessArgs['of'] = r['of'];
391
+ }
392
+ return { args: namelessArgs, stable: true };
393
+ }
293
394
  const component = asString(r['component']);
294
395
  if (component !== undefined || source !== undefined) {
295
396
  const componentArgs = { by: QueryBy.COMPONENT, action, args: actArgs };
296
- if (component !== undefined)
397
+ if (component !== undefined) {
297
398
  componentArgs['component'] = component;
298
- if (source !== undefined)
399
+ }
400
+ if (source !== undefined) {
299
401
  componentArgs['source'] = source;
402
+ }
403
+ // Which of the elements this anchor matches was acted on: a list renders every item from one site.
404
+ // The element's own words, when it has no accessible name: they survive a change of layout.
405
+ const ownText = asString(r['ownText']);
406
+ if (ownText !== undefined && ownText.length > 0) {
407
+ componentArgs['text'] = ownText;
408
+ }
409
+ // The role, too: a nameless control with no own words has no other identity a layout keeps.
410
+ const role = asString(r['role']);
411
+ if (role !== undefined && role.length > 0) {
412
+ componentArgs['role'] = role;
413
+ }
414
+ if ('number' === typeof r['componentNth'] && 'number' === typeof r['componentOf']) {
415
+ componentArgs['nth'] = r['componentNth'];
416
+ componentArgs['of'] = r['componentOf'];
417
+ }
300
418
  return { args: componentArgs, stable: true };
301
419
  }
302
420
  return { args: { ref, action, args: actArgs }, stable: false };
@@ -312,26 +430,38 @@ export function compileSequenceStep(args, res) {
312
430
  ? asRecord(res)['steps']
313
431
  : [];
314
432
  let stable = inputSteps.length > 0;
433
+ // A declared `expect` that a flow cannot keep (a session ref), said on save as for a single act (#2188).
434
+ let unkept = false;
315
435
  const subSteps = inputSteps.flatMap((raw, i) => {
316
436
  // A step on Reticle's own panel is not a step of the app's journey, as for a single act.
317
- if (true === asRecord(resolved[i])['reticleUi'])
437
+ if (true === asRecord(resolved[i])['reticleUi']) {
318
438
  return [];
439
+ }
319
440
  const step = asRecord(raw);
320
441
  const compiled = compileAnchorArgs(asRecord(resolved[i]), asString(step['ref']) ?? '', asString(step['action']) ?? '', replayActionArgs(step['args']));
321
- if (!compiled.stable)
442
+ if (!compiled.stable) {
322
443
  stable = false;
444
+ }
323
445
  // Each sub-step keeps its OWN declared consequence. A sequence records one step and replays as
324
446
  // one batch, but what each step CLAIMED is per step -- folding them together would let one
325
447
  // signal answer for every click in the journey.
326
448
  const expect = enforceableExpect(step['expect']);
449
+ if (expect === undefined && step['expect'] !== undefined) {
450
+ unkept = true;
451
+ }
327
452
  return [expect === undefined ? compiled.args : { ...compiled.args, expect }];
328
453
  });
329
454
  const timeoutMs = explicitTimeoutMs(args);
455
+ // The pace is part of what the sequence did: replay at the default settle answered differently (#2130).
456
+ const burst = args['burst'];
457
+ const burstMs = 'number' === typeof burst && Number.isFinite(burst) && 0 <= burst ? burst : undefined;
330
458
  return {
331
459
  tool: ReticleTool.ACT_SEQUENCE,
332
460
  stable,
333
461
  args: { steps: subSteps },
334
462
  ...(timeoutMs === undefined ? {} : { timeoutMs }),
463
+ ...(burstMs === undefined ? {} : { burstMs }),
464
+ ...(unkept ? { unkeptExpect: UNKEPT_EXPECT } : {}),
335
465
  };
336
466
  }
337
467
  /**
@@ -346,18 +476,21 @@ export function compileSequenceStep(args, res) {
346
476
  */
347
477
  async function resolveRef(session, step) {
348
478
  // Dispatched the way it ran live: at the document, with no ref. See compileAnchorArgs.
349
- if (isDocumentPress(step))
479
+ if (isDocumentPress(step)) {
350
480
  return { ref: '' };
481
+ }
351
482
  const by = asString(step.by);
352
483
  const value = asString(step.value);
353
484
  if (by === QueryBy.TESTID && value !== undefined) {
354
485
  const result = await session.command(ReticleCommand.QUERY, { by, value });
355
- if (!result.ok)
486
+ if (!result.ok) {
356
487
  throw new Error(result.error ?? 'query failed');
488
+ }
357
489
  const refs = queryRefs(result);
358
490
  const ref = refs[0];
359
- if (ref === undefined)
491
+ if (ref === undefined) {
360
492
  throw new Error(`testid '${value}' did not resolve in current page`);
493
+ }
361
494
  return refs.length > 1 ? { ref, note: ambiguousTestidNote(value) } : { ref };
362
495
  }
363
496
  // Role + accessible NAME: the anchor that distinguishes one row's control from another's, which
@@ -366,13 +499,16 @@ async function resolveRef(session, step) {
366
499
  const name = asString(step.name);
367
500
  const query = { by, value, ...(name === undefined ? {} : { name }) };
368
501
  const result = await session.command(ReticleCommand.QUERY, query);
369
- if (!result.ok)
502
+ if (!result.ok) {
370
503
  throw new Error(result.error ?? 'query failed');
371
- const refs = queryRefs(result);
504
+ }
505
+ const refs = name === undefined ? namelessRefs(result) : queryRefs(result);
372
506
  const meant = refFor(step, refs);
373
507
  const ref = meant ?? refs[0];
374
508
  if (ref === undefined) {
375
- throw new Error(`${value} named '${String(name)}' did not resolve in current page`);
509
+ throw new Error(name === undefined
510
+ ? `no ${value} with no accessible name resolved in current page`
511
+ : `${value} named '${String(name)}' did not resolve in current page`);
376
512
  }
377
513
  return meant === undefined ? { ref, note: ambiguousRoleNote(value, String(name)) } : { ref };
378
514
  }
@@ -385,8 +521,9 @@ async function resolveRef(session, step) {
385
521
  ...(source === undefined ? {} : { source }),
386
522
  };
387
523
  const result = await session.command(ReticleCommand.QUERY, query);
388
- if (!result.ok)
524
+ if (!result.ok) {
389
525
  throw new Error(result.error ?? 'query failed');
526
+ }
390
527
  const refs = queryRefs(result);
391
528
  const ref = refs[0];
392
529
  if (ref === undefined) {
@@ -468,8 +605,9 @@ via = []) {
468
605
  ...via,
469
606
  ]);
470
607
  results.push(...nested);
471
- if (nested.some((r) => !r.ok))
608
+ if (nested.some((r) => !r.ok)) {
472
609
  break;
610
+ }
473
611
  continue;
474
612
  }
475
613
  try {
@@ -480,8 +618,9 @@ via = []) {
480
618
  for (const raw of subs) {
481
619
  const sub = asRecord(raw);
482
620
  const { ref, note } = await resolveRef(session, sub);
483
- if (note !== undefined)
621
+ if (note !== undefined) {
484
622
  notes.push(note);
623
+ }
485
624
  liveSteps.push({
486
625
  ref,
487
626
  action: asString(sub['action']) ?? '',
@@ -502,8 +641,9 @@ via = []) {
502
641
  session.finishAction();
503
642
  }
504
643
  results.push(buildResult(step.tool, r.ok, r.error, notes));
505
- if (!r.ok)
644
+ if (!r.ok) {
506
645
  break;
646
+ }
507
647
  }
508
648
  else {
509
649
  const { ref, note } = await resolveRef(session, step.args);
@@ -520,8 +660,9 @@ via = []) {
520
660
  session.finishAction();
521
661
  }
522
662
  results.push(buildResult(step.tool, r.ok, r.error, note !== undefined ? [note] : []));
523
- if (!r.ok)
663
+ if (!r.ok) {
524
664
  break;
665
+ }
525
666
  }
526
667
  }
527
668
  catch (e) {
@@ -537,9 +678,11 @@ via = []) {
537
678
  }
538
679
  function buildResult(tool, ok, error, notes) {
539
680
  const base = { tool, ok };
540
- if (!ok)
681
+ if (!ok) {
541
682
  base.error = error ?? 'command failed';
542
- if (notes.length > 0)
683
+ }
684
+ if (notes.length > 0) {
543
685
  base.note = notes.join('; ');
686
+ }
544
687
  return base;
545
688
  }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Steps that reach past the page the journey is on: one opens another page (`navigate`), one sends a
3
+ * request to the app (`request`). Neither acts on an element, and both depend on a caller that owns
4
+ * what the replay cannot reach by itself: the sessions, the origin, the cookies.
5
+ */
6
+ import { type Drift, type FlowRequest, type FlowStep, type FlowStepResult } from '@reticlehq/core';
7
+ /**
8
+ * Opens the page a `navigate` step names and returns the session of the page that loaded, or why no
9
+ * page of the app answered. A full page load ends the session that asked for it, so only the caller
10
+ * that owns the sessions can do this.
11
+ */
12
+ export type OpenPage<S> = (url: string) => Promise<{
13
+ session: S;
14
+ } | {
15
+ error: string;
16
+ }>;
17
+ /**
18
+ * Sends the request a `request` step names and returns the answer, or why nothing could be sent.
19
+ * Supplied by the caller that knows the app's origin and the page's cookies.
20
+ */
21
+ export type SendRequest = (request: FlowRequest) => Promise<{
22
+ status: number;
23
+ body: string;
24
+ } | {
25
+ error: string;
26
+ }>;
27
+ /** Where the page's cookies come from: the driven browser's storage state. */
28
+ interface CookieSource {
29
+ storageState?(sessionUrl: string): Promise<unknown>;
30
+ }
31
+ /** The step's result before its `expect` is judged, and the session to go on with. */
32
+ export declare function openStepPage<S>(step: FlowStep, index: number, open: OpenPage<S> | undefined): Promise<{
33
+ result: FlowStepResult;
34
+ session?: S;
35
+ }>;
36
+ export declare function runRequestStep(step: FlowStep, index: number, send: SendRequest | undefined, judged: boolean,
37
+ /**
38
+ * The run's own yes to steps that change data, never the flow file's: flow files are shared, and a
39
+ * saved `DELETE` would otherwise run with the user's cookies on any app the flow is pointed at.
40
+ */
41
+ confirmDangerous: boolean): Promise<FlowStepResult>;
42
+ /** True for a step that reaches past the page: `navigate` or `request`. */
43
+ export declare function isPageStep(step: FlowStep): boolean;
44
+ /**
45
+ * Run a `navigate` or `request` step. `judge` evaluates an `expect` on a page; it comes from the
46
+ * replay so this file does not import the replay back. `checked` is false for a setup step, whose
47
+ * consequence is not checked. A navigate step returns the session to go on with.
48
+ */
49
+ export declare function runPageStep<S>(step: FlowStep, index: number, ctx: {
50
+ open?: OpenPage<S> | undefined;
51
+ send?: SendRequest | undefined;
52
+ checked: boolean;
53
+ confirmDangerous: boolean;
54
+ judge: (session: S, expect: NonNullable<FlowStep['expect']>) => Promise<Drift | undefined>;
55
+ route: (session: S) => string | undefined;
56
+ }): Promise<{
57
+ result: FlowStepResult;
58
+ session?: S;
59
+ }>;
60
+ /**
61
+ * The sender a `request` step uses: same origin as the page only, the page's cookies unless the step
62
+ * is anonymous, no redirects followed (a 302 is the answer to judge). `pageUrl` is read at send time,
63
+ * because a `navigate` step changes the page.
64
+ */
65
+ export declare function requestSender(pageUrl: () => string | undefined, provider: CookieSource | undefined,
66
+ /** The `Cookie` header of the account a step names in `as`, or undefined when not supplied. */
67
+ accountCookie?: (name: string) => string | undefined): SendRequest;
68
+ export {};