@reticlehq/server 3.7.0 → 3.8.1

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 (578) hide show
  1. package/SKILL.md +59 -68
  2. package/bin/reticle.js +9 -2
  3. package/dist/command/cli/adhoc-suite.js +1 -1
  4. package/dist/command/cli/adhoc-verdict.d.ts +12 -0
  5. package/dist/command/cli/adhoc-verdict.js +62 -4
  6. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  7. package/dist/command/cli/answers/gate-hook-message.js +5 -1
  8. package/dist/command/cli/auth/cloud-session.d.ts +11 -19
  9. package/dist/command/cli/auth/cloud-session.js +23 -0
  10. package/dist/command/cli/auth/device-flow.d.ts +3 -37
  11. package/dist/command/cli/cli-doctor.js +66 -21
  12. package/dist/command/cli/cli-flow-commands.js +53 -11
  13. package/dist/command/cli/cli-kill.d.ts +8 -0
  14. package/dist/command/cli/cli-kill.js +43 -3
  15. package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
  16. package/dist/command/cli/cli-parse-feedback.js +13 -1
  17. package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
  18. package/dist/command/cli/cli-parse-grammar.js +1 -6
  19. package/dist/command/cli/cli-parse-serve.d.ts +24 -0
  20. package/dist/command/cli/cli-parse-serve.js +124 -0
  21. package/dist/command/cli/cli-parse.d.ts +12 -11
  22. package/dist/command/cli/cli-parse.js +100 -123
  23. package/dist/command/cli/cli-usage.d.ts +0 -11
  24. package/dist/command/cli/cli-usage.js +43 -16
  25. package/dist/command/cli/cli-verify.d.ts +1 -1
  26. package/dist/command/cli/cli-verify.js +29 -14
  27. package/dist/command/cli/cloud-cli.js +27 -9
  28. package/dist/command/cli/cloud-kit.js +3 -3
  29. package/dist/command/cli/cloud-link.d.ts +1 -20
  30. package/dist/command/cli/cloud-link.js +2 -0
  31. package/dist/command/cli/cloud-login.d.ts +6 -2
  32. package/dist/command/cli/cloud-login.js +13 -41
  33. package/dist/command/cli/config/checkout.d.ts +10 -0
  34. package/dist/command/cli/config/checkout.js +78 -0
  35. package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
  36. package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
  37. package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
  38. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  39. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  40. package/dist/command/cli/drive/drive-attach.d.ts +5 -0
  41. package/dist/command/cli/drive/drive-attach.js +21 -1
  42. package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
  43. package/dist/command/cli/hook/codex-transcript.js +224 -0
  44. package/dist/command/cli/hook/episode-structure.d.ts +24 -0
  45. package/dist/command/cli/hook/episode-structure.js +138 -0
  46. package/dist/command/cli/hook/hook-command.d.ts +9 -0
  47. package/dist/command/cli/hook/hook-command.js +211 -0
  48. package/dist/command/cli/hook/hook-fast.d.ts +31 -0
  49. package/dist/command/cli/hook/hook-fast.js +136 -0
  50. package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
  51. package/dist/command/cli/hook/prompt-hook.js +199 -0
  52. package/dist/command/cli/hook/tool-hook.d.ts +21 -0
  53. package/dist/command/cli/hook/tool-hook.js +259 -0
  54. package/dist/command/cli/launch/cli-launch.d.ts +2 -0
  55. package/dist/command/cli/launch/cli-launch.js +22 -2
  56. package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
  57. package/dist/command/cli/mcp-command.d.ts +9 -0
  58. package/dist/command/cli/mcp-command.js +127 -41
  59. package/dist/command/cli/open-navigate.d.ts +43 -0
  60. package/dist/command/cli/open-navigate.js +85 -0
  61. package/dist/command/cli/ports/port-holder.d.ts +16 -4
  62. package/dist/command/cli/ports/port-holder.js +58 -12
  63. package/dist/command/cli/ports/resolve/cli-port.js +18 -2
  64. package/dist/command/cli/project-name.d.ts +1 -7
  65. package/dist/command/cli/project-name.js +1 -0
  66. package/dist/command/cli/report-command.d.ts +8 -2
  67. package/dist/command/cli/report-command.js +95 -18
  68. package/dist/command/cli/status-fields.d.ts +9 -2
  69. package/dist/command/cli/status-fields.js +148 -4
  70. package/dist/command/cli/try-command.d.ts +3 -4
  71. package/dist/command/cli/try-command.js +6 -11
  72. package/dist/command/cli/verify-results.d.ts +4 -1
  73. package/dist/command/cli/verify-results.js +3 -1
  74. package/dist/command/cli.d.ts +1 -7
  75. package/dist/command/cli.js +79 -160
  76. package/dist/command/daemon/daemon-resilience.d.ts +6 -1
  77. package/dist/command/daemon/daemon-resilience.js +31 -18
  78. package/dist/command/daemon/daemon.d.ts +11 -0
  79. package/dist/command/daemon/daemon.js +70 -2
  80. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
  81. package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
  82. package/dist/command/daemon/wake-decision.js +4 -2
  83. package/dist/command/daemon/win32-escape.d.ts +32 -0
  84. package/dist/command/daemon/win32-escape.js +119 -0
  85. package/dist/command/setup/agent-configs.d.ts +9 -0
  86. package/dist/command/setup/agent-configs.js +9 -0
  87. package/dist/command/setup/auto-approve.d.ts +10 -3
  88. package/dist/command/setup/auto-approve.js +51 -3
  89. package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
  90. package/dist/command/setup/bringup/dev-server-wait.js +5 -1
  91. package/dist/command/setup/bringup/ensure-daemon.js +4 -7
  92. package/dist/command/setup/init/init-host.js +6 -0
  93. package/dist/command/setup/init/init-port.js +5 -4
  94. package/dist/command/setup/init/init-runtime.js +7 -1
  95. package/dist/command/setup/node-effects.d.ts +8 -0
  96. package/dist/command/setup/node-effects.js +36 -4
  97. package/dist/command/setup/probe/dev-port.d.ts +26 -0
  98. package/dist/command/setup/probe/dev-port.js +117 -0
  99. package/dist/command/setup/probe/page-probe.d.ts +1 -1
  100. package/dist/command/setup/probe/page-probe.js +11 -3
  101. package/dist/command/setup/remaining-steps.d.ts +0 -7
  102. package/dist/command/setup/remaining-steps.js +3 -2
  103. package/dist/command/setup/run-setup.d.ts +11 -0
  104. package/dist/command/setup/run-setup.js +33 -5
  105. package/dist/command/setup/setup-command.d.ts +2 -0
  106. package/dist/command/setup/setup-command.js +22 -4
  107. package/dist/command/update/updater.d.ts +1 -6
  108. package/dist/command/update/updater.js +4 -5
  109. package/dist/command/update/version-seen.d.ts +24 -0
  110. package/dist/command/update/version-seen.js +65 -0
  111. package/dist/command/version/peer-announce.d.ts +9 -1
  112. package/dist/command/version/peer-announce.js +25 -2
  113. package/dist/command/version/sdk-fix.d.ts +5 -6
  114. package/dist/command/version/sdk-fix.js +17 -32
  115. package/dist/command/version/version-skew.d.ts +16 -1
  116. package/dist/command/version/version-skew.js +84 -10
  117. package/dist/features/crawl/crawl-tools.js +2 -2
  118. package/dist/features/crawl/crawl.js +2 -0
  119. package/dist/features/exhaust/ledger.d.ts +15 -96
  120. package/dist/features/exhaust/ledger.js +3 -3
  121. package/dist/features/harness/drive-runs.d.ts +28 -4
  122. package/dist/features/harness/drive-runs.js +99 -7
  123. package/dist/features/harness/drivers.d.ts +1 -1
  124. package/dist/features/harness/drivers.js +1 -1
  125. package/dist/features/harness/harness.d.ts +5 -0
  126. package/dist/features/harness/harness.js +24 -12
  127. package/dist/features/harness/platform/platform-drives.d.ts +7 -1
  128. package/dist/features/harness/platform/platform-drives.js +12 -7
  129. package/dist/features/harness/platform/refusal.d.ts +1 -1
  130. package/dist/features/harness/platform/refusal.js +4 -4
  131. package/dist/features/harness/platform/remote-drive.js +70 -28
  132. package/dist/features/harness/platform/server-driver.js +22 -1
  133. package/dist/features/harness/platform-config.d.ts +1 -10
  134. package/dist/features/harness/platform-config.js +0 -20
  135. package/dist/features/license/license.d.ts +2 -14
  136. package/dist/features/visual/step-shots.d.ts +33 -1
  137. package/dist/features/visual/step-shots.js +155 -1
  138. package/dist/features/visual/visual-tools.js +12 -4
  139. package/dist/hooks/coding-agents.d.ts +6 -0
  140. package/dist/hooks/coding-agents.js +24 -3
  141. package/dist/hooks/episode-stamp.d.ts +32 -0
  142. package/dist/hooks/episode-stamp.js +61 -0
  143. package/dist/hooks/hook-commands.js +19 -9
  144. package/dist/index.d.ts +5 -1
  145. package/dist/index.js +66 -24
  146. package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
  147. package/dist/judgement/app-graph/journal-steps.js +92 -0
  148. package/dist/judgement/capsule/capsule-store.d.ts +2 -39
  149. package/dist/judgement/domain/domain-model.js +1 -10
  150. package/dist/judgement/domain/domain-tools.js +4 -2
  151. package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
  152. package/dist/judgement/runs/artifact/run-store.js +153 -28
  153. package/dist/judgement/runs/default-run-id.d.ts +3 -1
  154. package/dist/judgement/runs/default-run-id.js +15 -3
  155. package/dist/judgement/runs/drive-run.d.ts +3 -3
  156. package/dist/judgement/runs/drive-run.js +11 -7
  157. package/dist/judgement/runs/run-ledger.d.ts +21 -0
  158. package/dist/judgement/runs/run-ledger.js +143 -0
  159. package/dist/judgement/runs/runner-port.d.ts +1 -1
  160. package/dist/judgement/runs/runner-port.js +8 -2
  161. package/dist/judgement/runs/verification-sync.d.ts +4 -3
  162. package/dist/judgement/runs/verification-sync.js +27 -5
  163. package/dist/language/flows/affected-tools.js +2 -1
  164. package/dist/language/flows/annotate-notes/annotate.js +8 -3
  165. package/dist/language/flows/annotate-tools.js +1 -1
  166. package/dist/language/flows/change/affected.d.ts +8 -0
  167. package/dist/language/flows/change/affected.js +20 -7
  168. package/dist/language/flows/decision.js +19 -4
  169. package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
  170. package/dist/language/flows/fields/flow-secret-field.js +67 -5
  171. package/dist/language/flows/flow-anchor.d.ts +5 -0
  172. package/dist/language/flows/flow-anchor.js +4 -0
  173. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  174. package/dist/language/flows/flow-cross-step.js +9 -0
  175. package/dist/language/flows/flow-expect-grammar.js +15 -10
  176. package/dist/language/flows/flow-intent.js +6 -1
  177. package/dist/language/flows/flow-journey.d.ts +8 -0
  178. package/dist/language/flows/flow-journey.js +13 -0
  179. package/dist/language/flows/flow-lease.d.ts +27 -0
  180. package/dist/language/flows/flow-lease.js +59 -0
  181. package/dist/language/flows/flow-replay-run.d.ts +1 -87
  182. package/dist/language/flows/flow-replay-run.js +111 -310
  183. package/dist/language/flows/flow-replay.js +21 -19
  184. package/dist/language/flows/flow-replayable.d.ts +38 -0
  185. package/dist/language/flows/flow-replayable.js +179 -0
  186. package/dist/language/flows/flow-start-path.d.ts +108 -0
  187. package/dist/language/flows/flow-start-path.js +313 -0
  188. package/dist/language/flows/flow-step-runners.d.ts +23 -2
  189. package/dist/language/flows/flow-step-runners.js +191 -32
  190. package/dist/language/flows/flow-store-for-session.d.ts +8 -1
  191. package/dist/language/flows/flow-store-for-session.js +6 -0
  192. package/dist/language/flows/flow-tools.d.ts +2 -23
  193. package/dist/language/flows/flow-tools.js +63 -113
  194. package/dist/language/flows/flows.d.ts +4 -6
  195. package/dist/language/flows/flows.js +90 -15
  196. package/dist/language/flows/heal-run.d.ts +10 -4
  197. package/dist/language/flows/heal-run.js +26 -9
  198. package/dist/language/flows/recording/flake.d.ts +3 -27
  199. package/dist/language/flows/recording/flake.js +1 -1
  200. package/dist/language/flows/recording/recording-backtrack.js +1 -4
  201. package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
  202. package/dist/language/flows/recording/tape/recordings.js +9 -3
  203. package/dist/language/flows/replay.d.ts +25 -5
  204. package/dist/language/flows/replay.js +83 -16
  205. package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
  206. package/dist/language/flows/suite/coverage.d.ts +9 -0
  207. package/dist/language/flows/suite/coverage.js +12 -1
  208. package/dist/language/flows/suite-selection.d.ts +25 -0
  209. package/dist/language/flows/suite-selection.js +41 -9
  210. package/dist/machine/git-tracks.d.ts +6 -0
  211. package/dist/machine/git-tracks.js +36 -0
  212. package/dist/memory/cloud/background-sync.d.ts +25 -0
  213. package/dist/memory/cloud/background-sync.js +79 -0
  214. package/dist/memory/cloud/cloud-config.d.ts +12 -1
  215. package/dist/memory/cloud/cloud-config.js +39 -13
  216. package/dist/memory/cloud/cloud-sync.d.ts +3 -24
  217. package/dist/memory/cloud/cloud-sync.js +5 -2
  218. package/dist/memory/cloud/harness-config.d.ts +0 -7
  219. package/dist/memory/cloud/memory-scope.d.ts +19 -0
  220. package/dist/memory/cloud/memory-scope.js +48 -0
  221. package/dist/memory/cloud/sync-answer.d.ts +43 -0
  222. package/dist/memory/cloud/sync-answer.js +42 -0
  223. package/dist/memory/cloud/sync-cycle.d.ts +40 -10
  224. package/dist/memory/cloud/sync-cycle.js +97 -144
  225. package/dist/memory/cloud/sync-daemon.d.ts +50 -3
  226. package/dist/memory/cloud/sync-daemon.js +473 -83
  227. package/dist/memory/cloud/sync-describe.d.ts +28 -0
  228. package/dist/memory/cloud/sync-describe.js +92 -0
  229. package/dist/memory/cloud/sync-disk.d.ts +9 -1
  230. package/dist/memory/cloud/sync-disk.js +137 -33
  231. package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
  232. package/dist/memory/cloud/sync-flow-versions.js +42 -0
  233. package/dist/memory/impact/impact-store.js +32 -15
  234. package/dist/memory/intent/intent-shard.d.ts +41 -266
  235. package/dist/memory/intent/intent-tools.js +20 -61
  236. package/dist/memory/intent/record-request.d.ts +27 -0
  237. package/dist/memory/intent/record-request.js +88 -0
  238. package/dist/memory/intent/settled-words.js +9 -1
  239. package/dist/memory/journal/drive-flow.d.ts +3 -0
  240. package/dist/memory/journal/drive-flow.js +11 -41
  241. package/dist/memory/journal/envelope-store.js +1 -1
  242. package/dist/memory/journal/envelope.d.ts +6 -154
  243. package/dist/memory/journal/episode-log.d.ts +107 -0
  244. package/dist/memory/journal/episode-log.js +302 -0
  245. package/dist/memory/journal/journal-recorder.d.ts +7 -0
  246. package/dist/memory/journal/journal-recorder.js +22 -9
  247. package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
  248. package/dist/memory/journal/on-disk/ambient-file.js +1 -1
  249. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
  250. package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
  251. package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
  252. package/dist/memory/journal/self-observation.js +3 -1
  253. package/dist/memory/journal/session-end.js +23 -9
  254. package/dist/memory/journal/session-journal.js +39 -20
  255. package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
  256. package/dist/memory/project/artifact-root-resolver.js +68 -23
  257. package/dist/memory/project/artifact-root.d.ts +17 -3
  258. package/dist/memory/project/artifact-root.js +47 -9
  259. package/dist/memory/project/fs/fs-port.d.ts +5 -0
  260. package/dist/memory/project/fs/fs-port.js +13 -0
  261. package/dist/memory/project/learned-routes.d.ts +3 -4
  262. package/dist/memory/project/learned-routes.js +3 -11
  263. package/dist/memory/project/link-directory.js +5 -2
  264. package/dist/memory/project/root-claims.d.ts +3 -1
  265. package/dist/memory/project/root-claims.js +41 -7
  266. package/dist/memory/project/session-root.d.ts +1 -1
  267. package/dist/memory/project/session-root.js +1 -15
  268. package/dist/memory/project/sync-status.js +5 -6
  269. package/dist/memory/recall/memory-tools.js +2 -2
  270. package/dist/memory/recall/platform-memory.d.ts +3 -1
  271. package/dist/memory/recall/platform-memory.js +9 -1
  272. package/dist/memory/recall/project-memory.js +15 -19
  273. package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
  274. package/dist/portal/bridge/auth-failure-reason.js +19 -0
  275. package/dist/portal/bridge/bridge.d.ts +19 -4
  276. package/dist/portal/bridge/bridge.js +150 -177
  277. package/dist/portal/bridge/harness-request.d.ts +15 -0
  278. package/dist/portal/bridge/harness-request.js +19 -0
  279. package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
  280. package/dist/portal/bridge/origin/origin-follow.js +110 -0
  281. package/dist/portal/bridge/pairing-token.d.ts +6 -0
  282. package/dist/portal/bridge/pairing-token.js +47 -16
  283. package/dist/portal/bridge/protocol-skew.d.ts +27 -2
  284. package/dist/portal/bridge/protocol-skew.js +66 -2
  285. package/dist/portal/bridge/session-nonces.d.ts +46 -0
  286. package/dist/portal/bridge/session-nonces.js +72 -0
  287. package/dist/portal/input/viewport-tools.d.ts +31 -0
  288. package/dist/portal/input/viewport-tools.js +106 -15
  289. package/dist/portal/pool/bounded-close.d.ts +23 -0
  290. package/dist/portal/pool/bounded-close.js +38 -0
  291. package/dist/portal/pool/browser-pool.d.ts +44 -39
  292. package/dist/portal/pool/browser-pool.js +247 -95
  293. package/dist/portal/pool/context-permissions.d.ts +9 -1
  294. package/dist/portal/pool/context-permissions.js +26 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +37 -0
  296. package/dist/portal/pool/lease-emulation.js +29 -0
  297. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  298. package/dist/portal/pool/playwright-launcher.js +74 -7
  299. package/dist/portal/pool/pool-contract.d.ts +23 -1
  300. package/dist/portal/pool/pool-lease.d.ts +128 -0
  301. package/dist/portal/pool/pool-lease.js +49 -0
  302. package/dist/portal/pool/zero-install.d.ts +8 -1
  303. package/dist/portal/pool/zero-install.js +24 -2
  304. package/dist/portal/production/production-activation.d.ts +136 -0
  305. package/dist/portal/production/production-activation.js +173 -0
  306. package/dist/portal/production/production-drive.d.ts +52 -0
  307. package/dist/portal/production/production-drive.js +301 -0
  308. package/dist/portal/production/production-hello.d.ts +23 -0
  309. package/dist/portal/production/production-hello.js +23 -0
  310. package/dist/portal/realm/web-realm.js +42 -15
  311. package/dist/portal/session/control-envelope.d.ts +1 -1
  312. package/dist/portal/session/dev-server/served-document.d.ts +0 -5
  313. package/dist/portal/session/dev-server/served-document.js +6 -8
  314. package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
  315. package/dist/portal/session/first-run-wiring.d.ts +3 -36
  316. package/dist/portal/session/first-run-wiring.js +10 -103
  317. package/dist/portal/session/live-control-tools.js +61 -19
  318. package/dist/portal/session/no-session-next-action.d.ts +11 -0
  319. package/dist/portal/session/no-session-next-action.js +40 -15
  320. package/dist/portal/session/no-session-watch.d.ts +7 -0
  321. package/dist/portal/session/no-session-watch.js +67 -23
  322. package/dist/portal/session/output-budget.d.ts +10 -0
  323. package/dist/portal/session/output-budget.js +16 -0
  324. package/dist/portal/session/presence/session-lease.d.ts +2 -0
  325. package/dist/portal/session/presence/session-lease.js +8 -0
  326. package/dist/portal/session/recorded-gaps.d.ts +15 -11
  327. package/dist/portal/session/recorded-gaps.js +39 -18
  328. package/dist/portal/session/serving-directory.d.ts +24 -2
  329. package/dist/portal/session/serving-directory.js +93 -5
  330. package/dist/portal/session/session-info.d.ts +26 -0
  331. package/dist/portal/session/session-info.js +20 -0
  332. package/dist/portal/session/session-manager.d.ts +35 -3
  333. package/dist/portal/session/session-manager.js +69 -14
  334. package/dist/portal/session/session-successor.js +1 -9
  335. package/dist/portal/session/session-tools.js +22 -4
  336. package/dist/portal/session/session.d.ts +10 -10
  337. package/dist/portal/session/session.js +37 -29
  338. package/dist/portal/session/zero-install-first-call.d.ts +7 -2
  339. package/dist/portal/session/zero-install-first-call.js +43 -20
  340. package/dist/start-wiring.d.ts +2 -2
  341. package/dist/start-wiring.js +17 -3
  342. package/dist/status-payload.d.ts +11 -1
  343. package/dist/status-payload.js +7 -1
  344. package/dist/surface/agent-presence-grace.d.ts +11 -0
  345. package/dist/surface/agent-presence-grace.js +34 -0
  346. package/dist/surface/http-server.d.ts +12 -1
  347. package/dist/surface/http-server.js +64 -15
  348. package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
  349. package/dist/surface/mcp/faults/mcp-outage.js +19 -1
  350. package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
  351. package/dist/surface/mcp/mcp-proxy.js +194 -267
  352. package/dist/surface/mcp/mcp.d.ts +20 -3
  353. package/dist/surface/mcp/mcp.js +88 -25
  354. package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
  355. package/dist/surface/mcp/proxy/drive-calls.js +114 -5
  356. package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
  357. package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
  358. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
  359. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
  360. package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
  361. package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
  362. package/dist/surface/mcp/server-instructions.js +35 -16
  363. package/dist/surface/mcp/shared-params.d.ts +8 -0
  364. package/dist/surface/mcp/shared-params.js +15 -1
  365. package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
  366. package/dist/surface/mcp/sse-frame-parser.js +18 -0
  367. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  368. package/dist/surface/mcp/surface-vocabulary.js +13 -0
  369. package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
  370. package/dist/surface/mcp/tool-catalog-cache.js +14 -4
  371. package/dist/surface/tools/account-tool.d.ts +4 -3
  372. package/dist/surface/tools/account-tool.js +20 -31
  373. package/dist/surface/tools/act/act-danger.d.ts +2 -0
  374. package/dist/surface/tools/act/act-danger.js +41 -14
  375. package/dist/surface/tools/act/act-observation.d.ts +11 -0
  376. package/dist/surface/tools/act/act-observation.js +33 -0
  377. package/dist/surface/tools/act/act-preflight.js +10 -3
  378. package/dist/surface/tools/act/act-sequence-retry.js +2 -1
  379. package/dist/surface/tools/act/act-target.js +19 -5
  380. package/dist/surface/tools/act/durable.js +1 -1
  381. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
  382. package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
  383. package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
  384. package/dist/surface/tools/act/unsettled-find.js +71 -0
  385. package/dist/surface/tools/act-sequence-tool.js +53 -24
  386. package/dist/surface/tools/act-tools.d.ts +2 -3
  387. package/dist/surface/tools/act-tools.js +49 -47
  388. package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
  389. package/dist/surface/tools/agent/for-the-agent.js +41 -3
  390. package/dist/surface/tools/assert/assert-grade.js +8 -3
  391. package/dist/surface/tools/assert/assert-verdict.js +4 -2
  392. package/dist/surface/tools/browser-tools.js +7 -4
  393. package/dist/surface/tools/chat-drives.js +50 -25
  394. package/dist/surface/tools/coverage-tools.js +1 -1
  395. package/dist/surface/tools/dynamic-tools.d.ts +8 -0
  396. package/dist/surface/tools/dynamic-tools.js +89 -34
  397. package/dist/surface/tools/empty-session-list.d.ts +18 -25
  398. package/dist/surface/tools/empty-session-list.js +67 -38
  399. package/dist/surface/tools/error-recovery.d.ts +17 -7
  400. package/dist/surface/tools/error-recovery.js +53 -20
  401. package/dist/surface/tools/explore-tools.d.ts +10 -0
  402. package/dist/surface/tools/explore-tools.js +72 -19
  403. package/dist/surface/tools/feedback-tools.js +23 -2
  404. package/dist/surface/tools/gap-novelty.d.ts +6 -0
  405. package/dist/surface/tools/gap-novelty.js +9 -0
  406. package/dist/surface/tools/gaps/capability-absences.js +4 -3
  407. package/dist/surface/tools/harness-explore.d.ts +1 -1
  408. package/dist/surface/tools/harness-explore.js +6 -4
  409. package/dist/surface/tools/harness-gate.d.ts +43 -21
  410. package/dist/surface/tools/harness-gate.js +55 -81
  411. package/dist/surface/tools/harness-script.d.ts +2 -0
  412. package/dist/surface/tools/harness-script.js +11 -6
  413. package/dist/surface/tools/harness-toolset.js +3 -4
  414. package/dist/surface/tools/invoke-tool.d.ts +0 -8
  415. package/dist/surface/tools/invoke-tool.js +164 -178
  416. package/dist/surface/tools/lease-hint.d.ts +9 -0
  417. package/dist/surface/tools/lease-hint.js +22 -3
  418. package/dist/surface/tools/lease-permissions.d.ts +1 -1
  419. package/dist/surface/tools/lease-readiness.d.ts +55 -0
  420. package/dist/surface/tools/lease-readiness.js +150 -2
  421. package/dist/surface/tools/lease-tools.d.ts +3 -75
  422. package/dist/surface/tools/lease-tools.js +124 -188
  423. package/dist/surface/tools/map-tools.d.ts +20 -0
  424. package/dist/surface/tools/map-tools.js +145 -0
  425. package/dist/surface/tools/merge-tools.js +11 -7
  426. package/dist/surface/tools/next-step.js +6 -3
  427. package/dist/surface/tools/observe-tools.js +46 -35
  428. package/dist/surface/tools/platform-moment.d.ts +3 -12
  429. package/dist/surface/tools/platform-moment.js +12 -24
  430. package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
  431. package/dist/surface/tools/read/complete-snapshot.js +13 -2
  432. package/dist/surface/tools/read/query-paginate.js +6 -0
  433. package/dist/surface/tools/read/query-shape.d.ts +9 -0
  434. package/dist/surface/tools/read/query-shape.js +15 -0
  435. package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
  436. package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
  437. package/dist/surface/tools/read-tools.js +5 -5
  438. package/dist/surface/tools/real-input-attempt.d.ts +11 -0
  439. package/dist/surface/tools/real-input-attempt.js +206 -38
  440. package/dist/surface/tools/reconcile-tools.js +21 -8
  441. package/dist/surface/tools/reticle-result.d.ts +3 -0
  442. package/dist/surface/tools/reticle-result.js +8 -1
  443. package/dist/surface/tools/run-report.d.ts +22 -0
  444. package/dist/surface/tools/run-report.js +141 -0
  445. package/dist/surface/tools/session-ports.d.ts +57 -0
  446. package/dist/surface/tools/session-ports.js +102 -0
  447. package/dist/surface/tools/tool-kit.d.ts +58 -4
  448. package/dist/surface/tools/tool-kit.js +140 -6
  449. package/dist/surface/tools/tool-surface.d.ts +2 -0
  450. package/dist/surface/tools/tool-surface.js +45 -0
  451. package/dist/surface/tools/tools.js +49 -87
  452. package/dist/telemetry/automation-hint.d.ts +5 -0
  453. package/dist/telemetry/automation-hint.js +7 -0
  454. package/dist/telemetry/cli-telemetry.d.ts +22 -0
  455. package/dist/telemetry/cli-telemetry.js +80 -11
  456. package/dist/telemetry/daemon-telemetry.d.ts +3 -1
  457. package/dist/telemetry/daemon-telemetry.js +9 -2
  458. package/dist/telemetry/feedback-cli.d.ts +1 -1
  459. package/dist/telemetry/feedback-cli.js +8 -3
  460. package/dist/telemetry/feedback.d.ts +1 -1
  461. package/dist/telemetry/feedback.js +51 -4
  462. package/dist/telemetry/harness-run.d.ts +3 -3
  463. package/dist/telemetry/harness-run.js +18 -7
  464. package/dist/telemetry/hud-events.d.ts +1 -1
  465. package/dist/telemetry/hud-metrics.d.ts +6 -3
  466. package/dist/telemetry/hud-metrics.js +20 -8
  467. package/dist/telemetry/install-source.js +1 -1
  468. package/dist/telemetry/mcp-connection.d.ts +1 -1
  469. package/dist/telemetry/mcp-connection.js +21 -2
  470. package/dist/telemetry/onboarding-firsts.d.ts +6 -1
  471. package/dist/telemetry/onboarding-firsts.js +41 -1
  472. package/dist/telemetry/proxy-telemetry.d.ts +42 -0
  473. package/dist/telemetry/proxy-telemetry.js +70 -1
  474. package/dist/telemetry/session-metrics.d.ts +1 -3
  475. package/dist/telemetry/session-metrics.js +16 -12
  476. package/dist/telemetry/telemetry.d.ts +9 -1
  477. package/dist/telemetry/telemetry.js +16 -1
  478. package/dist/telemetry/verification-of.d.ts +3 -1
  479. package/dist/telemetry/verification-of.js +7 -1
  480. package/dist/wire-journal.js +12 -2
  481. package/docs/README.md +4 -2
  482. package/docs/actions.mdx +7 -6
  483. package/docs/adapters.md +2 -1
  484. package/docs/agent-cheatsheet.md +19 -5
  485. package/docs/architecture.md +13 -10
  486. package/docs/autodrive.md +6 -5
  487. package/docs/benchmarks.md +2 -2
  488. package/docs/capabilities.mdx +1 -1
  489. package/docs/cli/affected.mdx +1 -1
  490. package/docs/cli/cloud.mdx +6 -6
  491. package/docs/cli/doctor.mdx +3 -1
  492. package/docs/cli/feedback.mdx +11 -7
  493. package/docs/cli/gate.mdx +1 -1
  494. package/docs/cli/help.mdx +1 -1
  495. package/docs/cli/init.mdx +20 -16
  496. package/docs/cli/mcp.mdx +5 -2
  497. package/docs/cli/open.mdx +5 -2
  498. package/docs/cli/report.mdx +1 -1
  499. package/docs/cli/restart.mdx +1 -1
  500. package/docs/cli/rollback.mdx +4 -4
  501. package/docs/cli/serve.mdx +7 -5
  502. package/docs/cli/setup.mdx +1 -1
  503. package/docs/cli/status.mdx +6 -2
  504. package/docs/cli/stop.mdx +3 -3
  505. package/docs/cli/telemetry.mdx +5 -1
  506. package/docs/cli/try.mdx +8 -8
  507. package/docs/cli/update.mdx +8 -5
  508. package/docs/cli/verify.mdx +12 -5
  509. package/docs/cli/version.mdx +1 -1
  510. package/docs/cli.mdx +10 -6
  511. package/docs/debugging.md +1 -1
  512. package/docs/deploy-checks.md +8 -6
  513. package/docs/desktop.mdx +14 -18
  514. package/docs/enterprise.md +6 -6
  515. package/docs/environment.mdx +5 -3
  516. package/docs/faq.mdx +9 -6
  517. package/docs/first-drive.md +19 -9
  518. package/docs/flows.md +3 -4
  519. package/docs/for-agents.md +1 -1
  520. package/docs/frameworks.mdx +34 -11
  521. package/docs/getting-started.md +46 -29
  522. package/docs/http-transport.md +2 -2
  523. package/docs/human-control.md +8 -8
  524. package/docs/index.mdx +2 -2
  525. package/docs/install-agentic.mdx +18 -19
  526. package/docs/install-manual.mdx +8 -4
  527. package/docs/integration-patterns.md +5 -5
  528. package/docs/multi-agent-testing.md +7 -5
  529. package/docs/packages/browser.mdx +34 -2
  530. package/docs/packages/core.mdx +2 -1
  531. package/docs/packages/electron.mdx +15 -3
  532. package/docs/packages/eslint-plugin.mdx +1 -1
  533. package/docs/packages/next.mdx +17 -5
  534. package/docs/packages/react.mdx +8 -1
  535. package/docs/packages/server.mdx +3 -3
  536. package/docs/packages/tauri.mdx +3 -3
  537. package/docs/packages/vite-plugin.mdx +1 -1
  538. package/docs/packages.mdx +19 -6
  539. package/docs/platform-integration.md +12 -4
  540. package/docs/predicates.mdx +18 -7
  541. package/docs/production-mode.md +108 -0
  542. package/docs/prompt-capture.md +99 -0
  543. package/docs/quickstart.mdx +14 -12
  544. package/docs/recipes.mdx +9 -8
  545. package/docs/required-checks.md +3 -2
  546. package/docs/skill-file.mdx +4 -3
  547. package/docs/skill-setup.md +2 -2
  548. package/docs/skill.md +62 -70
  549. package/docs/state-files.md +1 -0
  550. package/docs/state-management.mdx +11 -9
  551. package/docs/system-map.md +14 -13
  552. package/docs/telemetry.md +32 -24
  553. package/docs/testing.md +9 -5
  554. package/docs/tools/act-and-wait.mdx +17 -13
  555. package/docs/tools/act-sequence.mdx +40 -66
  556. package/docs/tools/act.mdx +7 -5
  557. package/docs/tools/assert.mdx +1 -1
  558. package/docs/tools/look.mdx +1 -1
  559. package/docs/tools/navigate.mdx +1 -1
  560. package/docs/tools/network.mdx +13 -11
  561. package/docs/tools/overview.mdx +3 -3
  562. package/docs/tools/query.mdx +3 -3
  563. package/docs/tools/session-and-feedback.mdx +9 -6
  564. package/docs/tools/sessions.mdx +7 -0
  565. package/docs/tools/snapshot.mdx +9 -7
  566. package/docs/tools/tools-and-run.mdx +11 -10
  567. package/docs/tools/verify.mdx +1 -1
  568. package/docs/troubleshooting.mdx +21 -9
  569. package/docs/usage.md +58 -43
  570. package/docs/use-cases.mdx +2 -2
  571. package/docs/vs-chrome-devtools-mcp.mdx +5 -5
  572. package/docs/vs-playwright-mcp.mdx +5 -4
  573. package/docs/what-is-recorded.md +12 -7
  574. package/docs/what-is-reticle.mdx +2 -2
  575. package/docs/why-reticle.mdx +1 -1
  576. package/package.json +9 -12
  577. package/dist/command/dev/stale-issue-guard.d.ts +0 -34
  578. package/dist/command/dev/stale-issue-guard.js +0 -69
@@ -1,4 +1,4 @@
1
- import { ActionType, DANGEROUS_ACTION_CONFIRM_ARG, NATIVE_INPUT_ARG, isDangerousActionText, outwardActionOf, outwardRefusal, } from '@reticlehq/core';
1
+ import { ActionType, DANGEROUS_ACTION_CONFIRM_ARG, NATIVE_INPUT_ARG, OutwardAction, isDangerousActionText, isDangerousNavigation, isInertHref, isPaymentProviderUrl, outwardActionOf, outwardRefusal, withoutFilenameTokens, } from '@reticlehq/core';
2
2
  import { currentDrivenBy, harnessOutwardAllowed } from '../../../hooks/driven-by.js';
3
3
  import { asRecord, asString } from '@reticlehq/core';
4
4
  /**
@@ -14,10 +14,12 @@ import { asRecord, asString } from '@reticlehq/core';
14
14
  */
15
15
  function descriptorText(value) {
16
16
  const descriptor = asRecord(value);
17
+ // Filename tokens are stripped from the name, the text and the value only: an href or a
18
+ // formAction is a target, not words on the control, and its destination must be read whole.
17
19
  return [
18
- asString(descriptor['name']) ?? '',
19
- asString(descriptor['text']) ?? '',
20
- asString(descriptor['value']) ?? '',
20
+ withoutFilenameTokens(asString(descriptor['name']) ?? ''),
21
+ withoutFilenameTokens(asString(descriptor['text']) ?? ''),
22
+ withoutFilenameTokens(asString(descriptor['value']) ?? ''),
21
23
  asString(descriptor['href']) ?? '',
22
24
  asString(descriptor['formAction']) ?? '',
23
25
  asString(descriptor['formText']) ?? '',
@@ -28,27 +30,47 @@ function descriptorRole(value) {
28
30
  return role !== undefined && role.length > 0 ? role : undefined;
29
31
  }
30
32
  function isDestructiveDescriptor(value) {
33
+ // A real link is a navigation, judged by where it goes: the same rule as the SDK path.
34
+ const href = asString(asRecord(value)['href']);
35
+ if (href !== undefined && !isInertHref(href)) {
36
+ return isDangerousNavigation(href);
37
+ }
31
38
  return isDangerousActionText(descriptorText(value), descriptorRole(value));
32
39
  }
33
40
  /** A Harness call presses an outward control only when its journey asked (`harnessOutwardAllowed`). */
34
41
  function assertOutwardAllowed(...descriptors) {
35
42
  const allowed = harnessOutwardAllowed();
36
- if (allowed === undefined)
43
+ if (allowed === undefined) {
37
44
  return;
45
+ }
38
46
  for (const descriptor of descriptors) {
39
47
  const kind = outwardActionOf(descriptorText(descriptor), descriptorRole(descriptor));
40
- if (kind !== undefined && !allowed.includes(kind))
48
+ if (kind !== undefined && !allowed.includes(kind)) {
41
49
  throw new Error(outwardRefusal(kind));
50
+ }
51
+ }
52
+ }
53
+ /** A Harness call goes to a payment provider's origin only when its journey asked to pay. */
54
+ export function assertNotPaymentNavigation(url) {
55
+ const allowed = harnessOutwardAllowed();
56
+ if (allowed === undefined || allowed.includes(OutwardAction.PAY)) {
57
+ return;
58
+ }
59
+ if (isPaymentProviderUrl(url)) {
60
+ throw new Error(outwardRefusal(OutwardAction.PAY));
42
61
  }
43
62
  }
44
63
  export function assertNotDestructive(action, innerArgs, inspected) {
45
- if (action !== ActionType.CLICK && action !== ActionType.DBLCLICK)
64
+ if (action !== ActionType.CLICK && action !== ActionType.DBLCLICK) {
46
65
  return;
66
+ }
47
67
  assertOutwardAllowed(inspected);
48
- if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG])
68
+ if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG]) {
49
69
  return;
50
- if (!isDestructiveDescriptor(inspected))
70
+ }
71
+ if (!isDestructiveDescriptor(inspected)) {
51
72
  return;
73
+ }
52
74
  throw new Error(`potentially destructive native action blocked; retry with args.${DANGEROUS_ACTION_CONFIRM_ARG}=true`);
53
75
  }
54
76
  /**
@@ -58,10 +80,12 @@ export function assertNotDestructive(action, innerArgs, inspected) {
58
80
  */
59
81
  export function assertDragNotDestructive(innerArgs, from, to) {
60
82
  assertOutwardAllowed(from, to);
61
- if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG])
83
+ if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG]) {
62
84
  return;
63
- if (!isDestructiveDescriptor(from) && !isDestructiveDescriptor(to))
85
+ }
86
+ if (!isDestructiveDescriptor(from) && !isDestructiveDescriptor(to)) {
64
87
  return;
88
+ }
65
89
  throw new Error(`potentially destructive native action blocked; retry with args.${DANGEROUS_ACTION_CONFIRM_ARG}=true`);
66
90
  }
67
91
  /**
@@ -78,8 +102,9 @@ export const NATIVE_INPUT_UNSUPPORTED = `reticle_act_and_wait cannot drive nativ
78
102
  'consequence with reticle_assert / reticle_observe using the `since` cursor it returns.';
79
103
  /** Refuse rather than silently drop a native-input request the act-then-wait path cannot honour. */
80
104
  export function assertNativeInputSupported(innerArgs) {
81
- if (true === innerArgs[NATIVE_INPUT_ARG])
105
+ if (true === innerArgs[NATIVE_INPUT_ARG]) {
82
106
  throw new Error(NATIVE_INPUT_UNSUPPORTED);
107
+ }
83
108
  }
84
109
  /**
85
110
  * The agent's own declaration counts as the confirmation, for that one control.
@@ -92,10 +117,12 @@ export function assertNativeInputSupported(innerArgs) {
92
117
  * guard decides alone.
93
118
  */
94
119
  export function confirmedByDeclaration(innerArgs, target, declared) {
95
- if (!declared || true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG])
120
+ if (!declared || true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG]) {
96
121
  return innerArgs;
97
- if (currentDrivenBy() !== undefined)
122
+ }
123
+ if (currentDrivenBy() !== undefined) {
98
124
  return innerArgs;
125
+ }
99
126
  const named = asRecord(target);
100
127
  // The words must themselves be the dangerous ones: naming "Continue" on a button whose form posts
101
128
  // to /delete-account consents to nothing, and the guard still reads the whole control.
@@ -47,6 +47,17 @@ export declare const DISABLED_TARGET_NOTE: string;
47
47
  * consequence then says nothing about the app, so the verdict is undecided rather than "no".
48
48
  */
49
49
  export declare function disabledTargetNote(pass: boolean, actResult: unknown): string | undefined;
50
+ /**
51
+ * Why the click behind a verdict is not one a person could have made, or undefined when it is.
52
+ *
53
+ * Synthetic dispatch reaches a covered, sizeless or off-screen target all the same, so the declared
54
+ * consequence can hold. A "yes" on it says nothing about what the app's users can do: the act
55
+ * result already warned, and the verdict now agrees. Undecided, never a pass and never the app's
56
+ * failure, whichever way the consequence went.
57
+ */
58
+ export declare function unreachableTargetNote(actResult: unknown): string | undefined;
59
+ /** Why the acted target leaves the verdict undecided: no person could reach it, or it was disabled. */
60
+ export declare function actTargetNote(pass: boolean, actResult: unknown): string | undefined;
50
61
  /**
51
62
  * The requests of a failed check's window, as its record carries them: method, url, status and the
52
63
  * start of the response body (redacted in the page before it was ever sent). Dev tooling is left out.
@@ -48,6 +48,39 @@ export function disabledTargetNote(pass, actResult) {
48
48
  return undefined;
49
49
  return false === asRecord(actResult)['enabled'] ? DISABLED_TARGET_NOTE : undefined;
50
50
  }
51
+ /** The words a verdict carries for a click no person could have made. */
52
+ const UNREACHABLE = {
53
+ covered: (by) => `a person could not have clicked the target: it is covered by ${by}. Dismiss or move what ` +
54
+ 'covers it, then act again',
55
+ NO_SIZE: 'a person could not have clicked the target: it has no size (0×0). Give it a size, or act on ' +
56
+ 'the control a person actually clicks',
57
+ OFF_VIEWPORT: 'a person could not have clicked the target: it is outside the viewport even after scrolling ' +
58
+ 'it into view. Bring it on screen, then act again',
59
+ };
60
+ /**
61
+ * Why the click behind a verdict is not one a person could have made, or undefined when it is.
62
+ *
63
+ * Synthetic dispatch reaches a covered, sizeless or off-screen target all the same, so the declared
64
+ * consequence can hold. A "yes" on it says nothing about what the app's users can do: the act
65
+ * result already warned, and the verdict now agrees. Undecided, never a pass and never the app's
66
+ * failure, whichever way the consequence went.
67
+ */
68
+ export function unreachableTargetNote(actResult) {
69
+ const effect = asRecord(asRecord(actResult)['effect']);
70
+ if (true === effect['occluded']) {
71
+ const by = asString(effect['occluderName']) ?? asString(effect['occludedBy']);
72
+ return UNREACHABLE.covered(by ?? 'another element');
73
+ }
74
+ if (true === effect['noSize'])
75
+ return UNREACHABLE.NO_SIZE;
76
+ if (true === effect['offViewport'])
77
+ return UNREACHABLE.OFF_VIEWPORT;
78
+ return undefined;
79
+ }
80
+ /** Why the acted target leaves the verdict undecided: no person could reach it, or it was disabled. */
81
+ export function actTargetNote(pass, actResult) {
82
+ return unreachableTargetNote(actResult) ?? disabledTargetNote(pass, actResult);
83
+ }
51
84
  /** Calls quoted on a failed check, and how much of each response body. */
52
85
  const MAX_NET_CALLS = 5;
53
86
  const MAX_BODY_CHARS = 300;
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate-schema.js';
14
14
  import { SESSION_REF, isGlobalPressCall, unissuedRefRefusal } from '@reticlehq/core';
15
+ import { isDocumentGoneError } from '../../../portal/session/facts/session-replaced.js';
15
16
  import { SessionReplacedError } from '../../../portal/session/page-commands/pending-commands.js';
16
17
  import { assertNativeInputSupported } from './act-danger.js';
17
18
  import { unevaluablePredicateReason, vacuousPredicateReason, } from '@reticlehq/engine/question/predicate/predicate-precheck.js';
@@ -118,8 +119,14 @@ export function assertSequenceSteps(steps) {
118
119
  * the very thing it just wrote. Same false green as an unreadable key, through a key this tool
119
120
  * does read.
120
121
  */
121
- if (step['expect'] !== undefined && !PredicateSchema.safeParse(step['expect']).success) {
122
- throw new Error(`step ${String(i)} carries an \`expect\` this tool cannot parse. ` +
122
+ const parsed = step['expect'] === undefined ? undefined : PredicateSchema.safeParse(step['expect']);
123
+ if (parsed !== undefined && !parsed.success) {
124
+ // The schema's own words, such as the keys it saw when it could not tell the kind.
125
+ const said = parsed.error.issues
126
+ .filter((issue) => 'custom' === issue.code)
127
+ .map((issue) => ` ${issue.message}.`)
128
+ .join('');
129
+ throw new Error(`step ${String(i)} carries an \`expect\` this tool cannot parse.${said} ` +
123
130
  'A consequence is a predicate object with a `kind` — e.g. { kind: "signal", name: ' +
124
131
  '"order:placed" }, { kind: "element", by: "testid", value: "receipt" }, or ' +
125
132
  '{ kind: "settled" } — the same shape reticle_act_and_wait takes as `until`. ' +
@@ -184,7 +191,7 @@ export async function dispatchAct(send) {
184
191
  return await send();
185
192
  }
186
193
  catch (error) {
187
- if (error instanceof SessionReplacedError)
194
+ if (error instanceof SessionReplacedError || isDocumentGoneError(error))
188
195
  return null;
189
196
  throw error;
190
197
  }
@@ -50,7 +50,8 @@ export function describeStepResult(step, result) {
50
50
  settled: result['settled'] ?? null,
51
51
  settleReason: result['settleReason'] ?? null,
52
52
  };
53
- for (const key of ['testid', 'component', 'role', 'name', 'source', 'warning']) {
53
+ // `reticleUi`: the step hit Reticle's own HUD, so the recorder leaves it out of the app's flow.
54
+ for (const key of ['testid', 'component', 'role', 'name', 'source', 'warning', 'reticleUi']) {
54
55
  if (result[key] !== undefined)
55
56
  out[key] = result[key];
56
57
  }
@@ -8,7 +8,7 @@
8
8
  * line count. This resolves a TARGET and dispatches only QUERY, so that guard is untouched.
9
9
  */
10
10
  import { ReticleCommand, SESSION_REF, isGlobalPressCall, unissuedRefRefusal, } from '@reticlehq/core';
11
- import { normalizeQueryArgs } from '../read/query-shape.js';
11
+ import { emptyQueryRefusal, normalizeQueryArgs } from '../read/query-shape.js';
12
12
  import { resolveTargetRef } from './resolve-target.js';
13
13
  import { asRecord, asString, asNumber } from '@reticlehq/core';
14
14
  import { appearanceDecision } from '@reticlehq/engine/window/appearance-budget.js';
@@ -52,17 +52,29 @@ appearanceMs) {
52
52
  if (ref !== undefined && ref.length > 0) {
53
53
  // Refused here, at the boundary, and never re-read as a `target`: guessing what an arbitrary
54
54
  // string meant is the silent re-resolution the stale-ref refusal exists to prevent.
55
- if (!SESSION_REF.test(ref))
55
+ if (!SESSION_REF.test(ref)) {
56
56
  return { kind: 'error', message: unissuedRefRefusal(ref) };
57
+ }
57
58
  return { kind: 'ref', ref };
58
59
  }
59
60
  const target = args['target'];
60
61
  if (target === undefined) {
61
- if (isGlobalPressCall(args))
62
+ if (isGlobalPressCall(args)) {
62
63
  return { kind: 'global', ref: '' };
64
+ }
63
65
  return { kind: 'error', message: MISSING_ACT_TARGET };
64
66
  }
67
+ // A ref from a look, given as the target. It is the agent's own explicit ref, not a guess.
68
+ if ('string' === typeof target && SESSION_REF.test(target)) {
69
+ return { kind: 'ref', ref: target };
70
+ }
65
71
  const q = normalizeQueryArgs(asRecord(target));
72
+ // A target that names nothing (a CSS string, an empty object) is not sent to the page: there it
73
+ // read as "matched no element", which says the element is gone when nothing was searched.
74
+ const empty = emptyQueryRefusal(q);
75
+ if (empty !== undefined) {
76
+ return { kind: 'error', message: empty.message };
77
+ }
66
78
  /*
67
79
  * Look again while the step's own budget lasts, instead of once.
68
80
  *
@@ -87,8 +99,9 @@ appearanceMs) {
87
99
  name: q['name'],
88
100
  scope: q['scope'],
89
101
  });
90
- if (!out.ok)
102
+ if (!out.ok) {
91
103
  return { kind: 'error', message: out.error ?? 'target query failed' };
104
+ }
92
105
  const elements = asRecord(out.result)['elements'];
93
106
  const found = Array.isArray(elements) ? elements : [];
94
107
  const decision = appearanceDecision({
@@ -98,8 +111,9 @@ appearanceMs) {
98
111
  });
99
112
  // One match, or an ambiguity: both are answered by the existing resolver, which already ranks
100
113
  // candidates inside its refusal so the next turn needs no snapshot.
101
- if ('wait' !== decision.do)
114
+ if ('wait' !== decision.do) {
102
115
  return resolveTargetRef(found, asRecord(out.result)['hint']);
116
+ }
103
117
  await new Promise((resolve) => setTimeout(resolve, decision.waitMs));
104
118
  }
105
119
  }
@@ -20,7 +20,7 @@ export const durableArg = z
20
20
  .describe('After a yes, reload and require the element/text/state part of `until` to hold again.');
21
21
  // Loose and undescribed on purpose: the output surface is re-sent every turn. `because` carries
22
22
  // the answer; this is the detail — { held?, observed?, skipped? }.
23
- export const durableOutput = z.record(z.unknown()).optional();
23
+ export const durableOutput = z.record(z.string(), z.unknown()).optional();
24
24
  const RE_READABLE = new Set([
25
25
  PredicateKind.ELEMENT,
26
26
  PredicateKind.TEXT,
@@ -67,17 +67,19 @@ export interface ArrivalScope {
67
67
  * document identity proves the replacement; `undefined` on both sides proves nothing and waits.
68
68
  */
69
69
  navigatedFromDocumentId?: string;
70
- /** Sessions already on the target before dispatch cannot prove this navigation arrived. */
70
+ /**
71
+ * Sessions connected before dispatch cannot prove this navigation arrived. One already on the
72
+ * target was there before it. One elsewhere, such as a lease on the same app, is another tab: it
73
+ * can reach the target during the wait, but it is not the new document of the navigated tab.
74
+ */
71
75
  priorIds: ReadonlySet<string>;
72
76
  }
73
77
  /**
74
- * The sessions already on `target` — the set `ArrivalScope.priorIds` is built from, sampled before
75
- * the navigation is dispatched.
76
- *
77
- * Shares `samePage` with the arrival scan on purpose: "was it already there" and "is it there now"
78
- * are the same question asked at two moments, and two spellings of it would eventually disagree.
78
+ * The sessions connected when the navigation is dispatched: the set `ArrivalScope.priorIds` is
79
+ * built from. The navigated tab's new document is not one of them, so none of the others can be
80
+ * the arrival.
79
81
  */
80
- export declare function idsAtTarget(sessions: SessionManager, target: string): ReadonlySet<string>;
82
+ export declare function idsOpenAtDispatch(sessions: SessionManager): ReadonlySet<string>;
81
83
  export interface ArrivalClock {
82
84
  now: () => number;
83
85
  sleep: (ms: number) => Promise<void>;
@@ -17,7 +17,7 @@
17
17
  * would make the daemon wait. `assert` / `wait_for` / `act_and_wait` all spend the caller's
18
18
  * `timeout_ms` (resolve-within.ts); this is the same budget applied to the same wait.
19
19
  */
20
- import { awaitDocumentSuccessor } from '../../../../portal/session/session-successor.js';
20
+ import { awaitDocumentSuccessor, claimedSessionOf, } from '../../../../portal/session/session-successor.js';
21
21
  /**
22
22
  * The default when the caller gives no `timeout_ms`: long enough for a dev server to serve a page
23
23
  * and the SDK to dial back; short enough to not hang. A caller who knows the app is slower says so.
@@ -71,19 +71,12 @@ export function absoluteTarget(target, base) {
71
71
  }
72
72
  }
73
73
  /**
74
- * The sessions already on `target` — the set `ArrivalScope.priorIds` is built from, sampled before
75
- * the navigation is dispatched.
76
- *
77
- * Shares `samePage` with the arrival scan on purpose: "was it already there" and "is it there now"
78
- * are the same question asked at two moments, and two spellings of it would eventually disagree.
74
+ * The sessions connected when the navigation is dispatched: the set `ArrivalScope.priorIds` is
75
+ * built from. The navigated tab's new document is not one of them, so none of the others can be
76
+ * the arrival.
79
77
  */
80
- export function idsAtTarget(sessions, target) {
81
- const ids = new Set();
82
- for (const s of sessions.all()) {
83
- if (samePage(s.url, target))
84
- ids.add(s.id);
85
- }
86
- return ids;
78
+ export function idsOpenAtDispatch(sessions) {
79
+ return new Set(sessions.all().map((s) => s.id));
87
80
  }
88
81
  /**
89
82
  * Whether `current` is a different document from the one the navigation was dispatched on.
@@ -124,10 +117,14 @@ function findArrival(sessions, target, scope, currentSession) {
124
117
  // the document has a chance to reach the requested target.
125
118
  continue;
126
119
  }
127
- // A different session that was already at the target cannot prove this
120
+ // A different session that was connected at dispatch cannot prove this
128
121
  // navigation arrived.
129
122
  if (scope.priorIds.has(s.id))
130
123
  continue;
124
+ // A session that claims another identity (a lease) is another tab, not the new document of
125
+ // the navigated one, even when it reconnects at the target during the wait.
126
+ if (claimedSessionOf(s.url) !== claimedSessionOf(scope.navigatedFrom))
127
+ continue;
131
128
  // While the replaced document is still connected, a DIFFERENT session at the target is an
132
129
  // unrelated arrival (a second tab, a neighbour app): the replacement this navigation waits
133
130
  // for has not reported yet, and letting the newcomer stand in would confirm too early and
@@ -0,0 +1,36 @@
1
+ /**
2
+ * A zero-match `find` read while the last act is still landing says so (#1259).
3
+ *
4
+ * `reticle_act` returns before an async render: a click that opens a modal after a fetch, then an
5
+ * immediate `find` for the modal's combobox, answers 0. A find is a point-in-time read, and an agent
6
+ * reads 0 as "not there" and goes down the wrong path. The read itself stays instant. What changes
7
+ * is that a 0 taken while the page is demonstrably still moving carries `unsettled`, naming why and
8
+ * the call that waits.
9
+ */
10
+ import { type ReticleEvent } from '@reticlehq/core';
11
+ /** A DOM change this recent means the render the act started may not have landed yet. */
12
+ export declare const UNSETTLED_DOM_QUIET_MS = 500;
13
+ export interface UnsettledFind {
14
+ reason: string;
15
+ inFlight?: string[];
16
+ lastDomChangeMsAgo?: number;
17
+ }
18
+ /** The slice of a session this reads: the last act's window and the clock. */
19
+ export interface UnsettledFindSession {
20
+ lastAct: {
21
+ cursor(): number | undefined;
22
+ };
23
+ eventsSince(cursor: number): readonly ReticleEvent[];
24
+ elapsed(): number;
25
+ url: string;
26
+ background: readonly string[];
27
+ }
28
+ /**
29
+ * `unsettled` for a zero-match read taken while the last act's window is still moving, else nothing.
30
+ *
31
+ * Moving means a request that window started has not come back, or the DOM changed within
32
+ * `UNSETTLED_DOM_QUIET_MS`. With no act yet there is no window to judge, so nothing is said.
33
+ */
34
+ export declare function unsettledFind(session: UnsettledFindSession, result: unknown): UnsettledFind | undefined;
35
+ /** The query result, with `unsettled` added when a zero-match read was taken mid-render. */
36
+ export declare function withUnsettledFind(session: UnsettledFindSession, result: unknown): unknown;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * A zero-match `find` read while the last act is still landing says so (#1259).
3
+ *
4
+ * `reticle_act` returns before an async render: a click that opens a modal after a fetch, then an
5
+ * immediate `find` for the modal's combobox, answers 0. A find is a point-in-time read, and an agent
6
+ * reads 0 as "not there" and goes down the wrong path. The read itself stays instant. What changes
7
+ * is that a 0 taken while the page is demonstrably still moving carries `unsettled`, naming why and
8
+ * the call that waits.
9
+ */
10
+ import { EventType } from '@reticlehq/core';
11
+ import { inFlightRequestLabels } from './settle-in-flight.js';
12
+ /** A DOM change this recent means the render the act started may not have landed yet. */
13
+ export const UNSETTLED_DOM_QUIET_MS = 500;
14
+ const DOM_CHANGES = new Set([
15
+ EventType.DOM_ADDED,
16
+ EventType.DOM_REMOVED,
17
+ EventType.DOM_ATTR,
18
+ EventType.DOM_TEXT,
19
+ ]);
20
+ /** What the next call should be, in the words every unsettled answer uses. */
21
+ const WAIT_INSTEAD = 'a 0 here may only mean it has not rendered yet. Wait for it with reticle_assert { action: "wait", predicate: { kind: "element", query: ... } }, or act with reticle_act_and_wait { until } next time';
22
+ /** How many elements a query result matched, or `undefined` when it is not a query result. */
23
+ function matchedCount(result) {
24
+ if (null === result || 'object' !== typeof result)
25
+ return undefined;
26
+ const rec = result;
27
+ if ('number' === typeof rec['count'])
28
+ return rec['count'];
29
+ return Array.isArray(rec['elements']) ? rec['elements'].length : undefined;
30
+ }
31
+ /**
32
+ * `unsettled` for a zero-match read taken while the last act's window is still moving, else nothing.
33
+ *
34
+ * Moving means a request that window started has not come back, or the DOM changed within
35
+ * `UNSETTLED_DOM_QUIET_MS`. With no act yet there is no window to judge, so nothing is said.
36
+ */
37
+ export function unsettledFind(session, result) {
38
+ if (0 !== matchedCount(result))
39
+ return undefined;
40
+ // A test double, or any session that cannot say what its last act was, gets the read as before.
41
+ if (undefined === session.lastAct)
42
+ return undefined;
43
+ const cursor = session.lastAct.cursor();
44
+ if (cursor === undefined)
45
+ return undefined;
46
+ const window = session.eventsSince(cursor);
47
+ const inFlight = inFlightRequestLabels(window, session.url, session.background);
48
+ let lastDom;
49
+ for (const e of window)
50
+ if (DOM_CHANGES.has(e.type))
51
+ lastDom = Math.max(lastDom ?? e.t, e.t);
52
+ const msAgo = lastDom === undefined ? undefined : Math.max(0, session.elapsed() - lastDom);
53
+ const recent = msAgo !== undefined && msAgo < UNSETTLED_DOM_QUIET_MS;
54
+ if (0 === inFlight.length && !recent)
55
+ return undefined;
56
+ const why = 0 < inFlight.length
57
+ ? `the last act started ${String(inFlight.length)} request(s) that have not come back`
58
+ : `the page changed ${String(msAgo)} ms ago, after the last act`;
59
+ return {
60
+ reason: `this read found nothing while the page was still changing: ${why}, so ${WAIT_INSTEAD}`,
61
+ ...(0 < inFlight.length ? { inFlight } : {}),
62
+ ...(msAgo === undefined ? {} : { lastDomChangeMsAgo: msAgo }),
63
+ };
64
+ }
65
+ /** The query result, with `unsettled` added when a zero-match read was taken mid-render. */
66
+ export function withUnsettledFind(session, result) {
67
+ const unsettled = unsettledFind(session, result);
68
+ if (unsettled === undefined || null === result || 'object' !== typeof result)
69
+ return result;
70
+ return { ...result, unsettled };
71
+ }