@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,6 +1,6 @@
1
- import { REDACTED_FILL, SECRET_NAME_ARG, secretEnvKey, secretValue, } from './fields/flow-secret-field.js';
2
- import { FlowPredicateSchema, Verified } from '@reticlehq/core';
3
- import { DANGEROUS_ACTION_CONFIRM_ARG, ReticleCommand, QueryBy, } from '@reticlehq/core';
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';
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';
@@ -44,11 +44,13 @@ export function queryRefs(result) {
44
44
  export function replayActionArgs(value, confirmDangerous = false, field) {
45
45
  const args = { ...asRecord(value) };
46
46
  delete args[DANGEROUS_ACTION_CONFIRM_ARG];
47
+ const key = field === undefined ? undefined : secretKeyForFill(args, field);
47
48
  delete args[SECRET_NAME_ARG];
49
+ delete args[SECRET_FIELD_ARG];
48
50
  if (confirmDangerous)
49
51
  args[DANGEROUS_ACTION_CONFIRM_ARG] = true;
50
- if (REDACTED_FILL === args['value'] && field !== undefined) {
51
- const supplied = secretValue(secretEnvKey(field), process.env);
52
+ if (key !== undefined) {
53
+ const supplied = secretValue(key, process.env);
52
54
  if (supplied !== undefined && supplied.length > 0)
53
55
  args['value'] = supplied;
54
56
  }
@@ -82,14 +84,26 @@ function sourceFromResult(res) {
82
84
  * Pathname rather than the whole url, because that is what `startPath` is compared against and what
83
85
  * a hash-routed app makes meaningless in the document location — see routeOfEvent.
84
86
  */
85
- export function pathOf(url) {
86
- if (url === undefined)
87
- return undefined;
87
+ export { pathOf };
88
+ /**
89
+ * Did the app send a write request in this window? A step that did is saved `writes: true`, so a
90
+ * replay does not repeat it unasked. The dev server's own traffic is not the app's.
91
+ */
92
+ export function wroteIn(events) {
93
+ return events.some((event) => {
94
+ if (EventType.NET_REQUEST !== event.type)
95
+ return false;
96
+ const method = asString(event.data['method'])?.toUpperCase() ?? '';
97
+ return MUTATING_METHODS.includes(method) && !isDevToolingUrl(asString(event.data['url']));
98
+ });
99
+ }
100
+ /** `wroteIn` over a session's window, best-effort: the record must never fail the drive it records. */
101
+ export function wroteSince(session, since) {
88
102
  try {
89
- return new URL(url).pathname;
103
+ return wroteIn(session.eventsSince(since));
90
104
  }
91
105
  catch {
92
- return undefined;
106
+ return false;
93
107
  }
94
108
  }
95
109
  /** What a saved flow could not keep, and the fix. See RecordedStep.unkeptExpect. */
@@ -106,7 +120,9 @@ export function captureAct(recordings, args, res,
106
120
  /** Where this step ran, so the ambient tape can be cut into journeys. See RecordedStep.route. */
107
121
  route,
108
122
  /** The session that acted: only recordings it started take the step. */
109
- session) {
123
+ session,
124
+ /** The act's window sent a write request; see `wroteIn`. */
125
+ wrote = false) {
110
126
  // NO `active()` gate. `RecordingStore.capture` opens the AMBIENT tape on its first step, and that
111
127
  // branch was unreachable from here: this returned early whenever nothing was open, and the only
112
128
  // thing that opened anything was `reticle_record { action: "start" }`. So the comment on `capture`
@@ -116,6 +132,10 @@ session) {
116
132
  // That is the whole supply of regression tests this product could have had for free: few saved
117
133
  // flows are mutation-testable and few steps declare a consequence, and a drive that is never
118
134
  // recorded cannot contribute to either.
135
+ // A click on Reticle's own panel (the HUD exposed) is not a step of the app's journey: saved, the
136
+ // app's flow pressed Run Harness on replay, a paid drive, under an intent that never named it.
137
+ if (true === asRecord(res)['reticleUi'])
138
+ return;
119
139
  const step = compileActStep(args, res);
120
140
  // Keep the assertion the agent actually made. `act_and_wait { until }` IS the agent saying what
121
141
  // success means — the large majority of calls carry one — and dropping it produced a flow graded
@@ -132,6 +152,8 @@ session) {
132
152
  const intent = asString(args['intent'])?.trim();
133
153
  if (intent !== undefined && intent.length > 0)
134
154
  step.intent = intent;
155
+ if (wrote)
156
+ step.writes = true;
135
157
  recordings.capture(step, route, session);
136
158
  }
137
159
  /**
@@ -140,9 +162,11 @@ session) {
140
162
  * a regression test asserting something never once observed to hold because of the action. The
141
163
  * action itself is always recorded: it happened, and replay needs it to reach the next step.
142
164
  */
143
- export function captureVerdictedAct(recordings, args, res, route, verified, session) {
165
+ export function captureVerdictedAct(recordings, args, res, route, verified, session,
166
+ /** The act's window sent a write request; see `wroteIn`. */
167
+ wrote = false) {
144
168
  const { until: _until, predicate: _predicate, ...unproved } = args;
145
- captureAct(recordings, Verified.YES === verified ? args : unproved, res, route, session);
169
+ captureAct(recordings, Verified.YES === verified ? args : unproved, res, route, session, wrote);
146
170
  }
147
171
  /** Fold a PASSING standalone assertion into the step it proved. See RecordingStore.attachExpect. */
148
172
  export function captureAssertion(recordings, raw, session) {
@@ -205,9 +229,31 @@ function explicitTimeoutMs(args) {
205
229
  * perfectly stable anchor.
206
230
  */
207
231
  function compileAnchorArgs(r, ref, action, actArgs) {
232
+ const compiled = anchorArgs(r, ref, action, actArgs);
233
+ // The SDK says the target holds a secret (a password input, whatever its label). Carried beside
234
+ // 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'])
236
+ compiled.args[SECRET_FIELD_ARG] = true;
237
+ return compiled;
238
+ }
239
+ function anchorArgs(r, ref, action, actArgs) {
240
+ // A document-key press with no ref ran live against no element (act-target resolves it to the
241
+ // document), so there is nothing to anchor and nothing missing. It used to fall through to the
242
+ // ref-bound branch with an empty ref, which saved as the degraded placeholder and drifted on every
243
+ // replay with "add a data-testid", on a step that has no element to add one to (#1559).
244
+ if (0 === ref.length && isGlobalPressCall({ action, args: actArgs })) {
245
+ return {
246
+ args: { by: QueryBy.ROLE, value: DOCUMENT_ANCHOR_ROLE, action, args: actArgs },
247
+ stable: true,
248
+ };
249
+ }
208
250
  const testid = asString(r['testid']);
209
251
  const source = sourceFromResult(r);
210
- if (testid !== undefined) {
252
+ // Several elements carry this test id, so a replay would take the first: anchor on role and name
253
+ // when the element has them, else keep the test id and say how many share it.
254
+ const testidOf = 'number' === typeof r['testidOf'] && 1 < r['testidOf'] ? r['testidOf'] : undefined;
255
+ const named = asString(r['role']) !== undefined && asString(r['name']) !== undefined;
256
+ if (testid !== undefined && !(testidOf !== undefined && named)) {
211
257
  // The testid anchors the step; source rides along purely so a failure can name a file. Carrying
212
258
  // both was the point of separating anchor from provenance at capture time.
213
259
  const testidArgs = {
@@ -218,6 +264,8 @@ function compileAnchorArgs(r, ref, action, actArgs) {
218
264
  };
219
265
  if (source !== undefined)
220
266
  testidArgs['source'] = source;
267
+ if (testidOf !== undefined)
268
+ testidArgs['of'] = testidOf;
221
269
  return { args: testidArgs, stable: true };
222
270
  }
223
271
  // Role + NAME before component: a component/source anchor names the JSX site, so every row's copy
@@ -264,7 +312,10 @@ export function compileSequenceStep(args, res) {
264
312
  ? asRecord(res)['steps']
265
313
  : [];
266
314
  let stable = inputSteps.length > 0;
267
- const subSteps = inputSteps.map((raw, i) => {
315
+ const subSteps = inputSteps.flatMap((raw, i) => {
316
+ // 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'])
318
+ return [];
268
319
  const step = asRecord(raw);
269
320
  const compiled = compileAnchorArgs(asRecord(resolved[i]), asString(step['ref']) ?? '', asString(step['action']) ?? '', replayActionArgs(step['args']));
270
321
  if (!compiled.stable)
@@ -273,7 +324,7 @@ export function compileSequenceStep(args, res) {
273
324
  // one batch, but what each step CLAIMED is per step -- folding them together would let one
274
325
  // signal answer for every click in the journey.
275
326
  const expect = enforceableExpect(step['expect']);
276
- return expect === undefined ? compiled.args : { ...compiled.args, expect };
327
+ return [expect === undefined ? compiled.args : { ...compiled.args, expect }];
277
328
  });
278
329
  const timeoutMs = explicitTimeoutMs(args);
279
330
  return {
@@ -294,6 +345,9 @@ export function compileSequenceStep(args, res) {
294
345
  * the first of them.
295
346
  */
296
347
  async function resolveRef(session, step) {
348
+ // Dispatched the way it ran live: at the document, with no ref. See compileAnchorArgs.
349
+ if (isDocumentPress(step))
350
+ return { ref: '' };
297
351
  const by = asString(step.by);
298
352
  const value = asString(step.value);
299
353
  if (by === QueryBy.TESTID && value !== undefined) {
@@ -354,6 +408,19 @@ async function resolveRef(session, step) {
354
408
  }
355
409
  return { ref, note: 'replayed by stale ref (not portable across sessions)' };
356
410
  }
411
+ /**
412
+ * A compiled step that presses a document key at no element (#1559).
413
+ *
414
+ * Both halves are required. The anchor alone is not enough, because a hand-edited `role: document`
415
+ * on a click would then dispatch that click at nothing; and the press alone is not enough, because a
416
+ * recorded Escape aimed at a named element keeps that element.
417
+ */
418
+ export function isDocumentPress(step) {
419
+ return (QueryBy.ROLE === step['by'] &&
420
+ DOCUMENT_ANCHOR_ROLE === step['value'] &&
421
+ undefined === step['name'] &&
422
+ isGlobalPressCall({ action: step['action'], args: step['args'] }));
423
+ }
357
424
  /** Re-execute every step of a compiled program in order, stopping at the first failure. */
358
425
  export async function replayProgram(session, program, confirmDangerous = false,
359
426
  /**
@@ -19,7 +19,7 @@ import { withFileLock } from '../../../memory/project/file-lock.js';
19
19
  */
20
20
  const AssertionTiersFileSchema = z.object({
21
21
  version: z.literal(1),
22
- flows: z.record(z.object({
22
+ flows: z.record(z.string(), z.object({
23
23
  steps: z.array(z.object({ step: z.number(), expect: z.unknown().optional() })),
24
24
  /** Source files this flow covered when it last passed — lets the gate scope DELETION findings to
25
25
  * the files that actually changed, instead of flagging every intentionally-removed flow. */
@@ -33,6 +33,15 @@ interface Coverage {
33
33
  }
34
34
  /** The gate's outcome when the project has recorded no flows at all — not a pass, and not a failure. */
35
35
  export declare const NO_FLOWS = "no_flows";
36
+ /**
37
+ * How to get a first flow, in calls that work on every tool surface (#1547).
38
+ *
39
+ * `reticle_record` and `reticle_flow_save` are not on the default surface, so naming them bare sent
40
+ * an agent looking for tools it did not have, and it stopped. A journey driven with
41
+ * `reticle_act_and_wait` and an `until` is saved as a flow when the session ends, so that leads;
42
+ * recording by hand goes through `reticle_run`, which every surface advertises.
43
+ */
44
+ export declare const RECORD_A_FLOW: string;
36
45
  /** The gate's flow-coverage line. `pct` and `outcome` are mutually exclusive by construction. */
37
46
  interface FlowCoverageReport {
38
47
  covered: number;
@@ -6,6 +6,17 @@
6
6
  */
7
7
  /** The gate's outcome when the project has recorded no flows at all — not a pass, and not a failure. */
8
8
  export const NO_FLOWS = 'no_flows';
9
+ /**
10
+ * How to get a first flow, in calls that work on every tool surface (#1547).
11
+ *
12
+ * `reticle_record` and `reticle_flow_save` are not on the default surface, so naming them bare sent
13
+ * an agent looking for tools it did not have, and it stopped. A journey driven with
14
+ * `reticle_act_and_wait` and an `until` is saved as a flow when the session ends, so that leads;
15
+ * recording by hand goes through `reticle_run`, which every surface advertises.
16
+ */
17
+ export const RECORD_A_FLOW = 'Drive a journey with reticle_act_and_wait and an `until`: it is saved as a flow when the session ends. ' +
18
+ 'Or record one by hand with reticle_run { tool: "reticle_record", args: { action: "start" } }, then ' +
19
+ 'reticle_run { tool: "reticle_flow_save", args: { flowName } }.';
9
20
  /**
10
21
  * What to do about it, since the empty state is otherwise indistinguishable from success.
11
22
  *
@@ -13,7 +24,7 @@ export const NO_FLOWS = 'no_flows';
13
24
  * that errors is a second dead end on top of the first (see suggested-commands-exist.test.ts). Same
14
25
  * wording as the empty-suite verdict, which is the same situation reached from `reticle verify`.
15
26
  */
16
- const NO_FLOWS_NOTE = 'no flows recorded — nothing was checked. Record one with reticle_record { action: "start" }, then reticle_flow_save.';
27
+ const NO_FLOWS_NOTE = `no flows recorded — nothing was checked. ${RECORD_A_FLOW}`;
17
28
  /**
18
29
  * Report flow coverage so that an EMPTY suite cannot be read as a passing one.
19
30
  *
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Which flows a suite run replays, resolved against the store.
3
+ *
4
+ * Shared by the MCP tool and the `reticle verify` command so the two cannot disagree about what a
5
+ * selection means.
6
+ *
7
+ * Lives beside the flow store rather than under `suite/` on purpose: it needs `flowsForSession`, and
8
+ * from `suite/` that import made `suite` and `flows` need EACH OTHER -- a mutual pair, which the
9
+ * reach guard forbids growing because two directories that need each other cannot be read, moved or
10
+ * tested apart. Here it adds no edge at all: `flows` reaching itself is nothing, and `cli -> flows`
11
+ * already existed. The pure rule lives in core (`selectFlows`); this is the part that has to read
12
+ * the files, because a label lives in one and `list` returns only names.
13
+ */
14
+ import { type FlowFile } from '@reticlehq/core';
1
15
  import type { ProjectTarget } from '../../memory/project/session-root.js';
2
16
  import type { ToolDeps } from '../../surface/tools/tool-kit.js';
3
17
  /**
@@ -14,6 +28,8 @@ export declare function resolveSuiteSelection(deps: ToolDeps, target: ProjectTar
14
28
  run: string[];
15
29
  quarantined: string[];
16
30
  unmatched: string[];
31
+ /** Flows held back by `skipWrites`: replaying them would send their write requests again. */
32
+ writing?: string[];
17
33
  /** Flows in a dependency cycle — none of them ran. */
18
34
  cycles?: string[];
19
35
  /** A flow whose prerequisite is not in this run, so it did not run either. */
@@ -30,3 +46,12 @@ export declare function resolveSuiteSelection(deps: ToolDeps, target: ProjectTar
30
46
  */
31
47
  knownRoutes: string[];
32
48
  }>;
49
+ /** The flows a replay would change real data with: a step sent, or expects, a write request. */
50
+ export declare function writingFlows(flows: readonly FlowFile[]): string[];
51
+ /** How the refusal of an unknown flow name opens: the error table recognizes it by these words. */
52
+ export declare const UNKNOWN_FLOW_OPENING = "No saved flow is named";
53
+ /**
54
+ * The refusal for flow names no saved flow carries, or `undefined` when every name is known. Names
55
+ * the flows that do exist, so the typo can be fixed in the next call.
56
+ */
57
+ export declare function unknownFlowRefusal(wanted: readonly string[], known: readonly string[]): Error | undefined;
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { FLOW_FILE_VERSION, orderFlows, selectFlows } from '@reticlehq/core';
15
15
  import { flowsForSession } from './flow-store-for-session.js';
16
+ import { readyForReplay, replayability } from './flow-replayable.js';
16
17
  /**
17
18
  * Resolve what a suite run should replay, and what it is holding back.
18
19
  *
@@ -55,23 +56,29 @@ export async function resolveSuiteSelection(deps, target, args) {
55
56
  ...(0 === wantedLabels.length ? {} : { labels: wantedLabels }),
56
57
  });
57
58
  /*
58
- * A name the caller asked for that no file matches is still ATTEMPTED.
59
- *
60
- * Replay already answers a missing flow with the real reason, and that is a better answer than
61
- * quietly running one fewer flow than was asked for. `unmatched` therefore reports labels, where
62
- * a typo has no other way of surfacing -- ask for `@smoek` and, without this, a suite of zero
63
- * flows reports a clean pass.
59
+ * A name no saved flow carries is refused before anything runs. It used to be ATTEMPTED, so a
60
+ * typo became a failed check and a failed run on the dashboard, with "check the element state" as
61
+ * the advice. `unmatched` still reports labels, where a typo has no other way of surfacing -- ask
62
+ * for `@smoek` and, without it, a suite of zero flows reports a clean pass.
64
63
  */
65
- const missingNames = wantedNames.filter((name) => !names.includes(name));
64
+ const unknown = unknownFlowRefusal(wantedNames, names);
65
+ if (unknown !== undefined)
66
+ throw unknown;
66
67
  /*
67
68
  * Ordered AFTER selection, so a prerequisite filtered out by a label is reported rather than
68
69
  * silently pulled back in. A flow whose `login` was excluded does not run: failing it here would
69
70
  * produce a failure about the wrong thing, and quietly adding `login` back would run a flow the
70
71
  * caller did not ask for.
71
72
  */
72
- const ordered = orderFlows(chosen.run);
73
+ /*
74
+ * A certify run must not change real data. A flow whose step sent a write request when it was
75
+ * recorded (or whose expect names one) is held back and named, never replayed, when asked.
76
+ */
77
+ const writing = true === args['skipWrites'] ? writingFlows(chosen.run) : [];
78
+ const ordered = orderFlows(chosen.run.filter((flow) => !writing.includes(flow.name)));
73
79
  return {
74
- run: [...ordered.run.map((flow) => flow.name), ...missingNames],
80
+ run: ordered.run.map((flow) => flow.name),
81
+ ...(0 === writing.length ? {} : { writing }),
75
82
  quarantined: chosen.quarantined,
76
83
  unmatched: chosen.unmatched.filter((entry) => !wantedNames.includes(entry)),
77
84
  ...(0 === ordered.cycles.length ? {} : { cycles: ordered.cycles }),
@@ -83,3 +90,28 @@ export async function resolveSuiteSelection(deps, target, args) {
83
90
  ],
84
91
  };
85
92
  }
93
+ /** The flows a replay would change real data with: a step sent, or expects, a write request. */
94
+ export function writingFlows(flows) {
95
+ return flows
96
+ .filter((flow) => true === replayability(readyForReplay(flow)).writes)
97
+ .map((flow) => flow.name);
98
+ }
99
+ /** How the refusal of an unknown flow name opens: the error table recognizes it by these words. */
100
+ export const UNKNOWN_FLOW_OPENING = 'No saved flow is named';
101
+ /** How many saved flow names a refusal lists before it says how many more there are. */
102
+ const KNOWN_SHOWN = 10;
103
+ /**
104
+ * The refusal for flow names no saved flow carries, or `undefined` when every name is known. Names
105
+ * the flows that do exist, so the typo can be fixed in the next call.
106
+ */
107
+ export function unknownFlowRefusal(wanted, known) {
108
+ const missing = wanted.filter((name) => !known.includes(name));
109
+ if (0 === missing.length)
110
+ return undefined;
111
+ const asked = missing.map((name) => `"${name}"`).join(', ');
112
+ const more = known.length - KNOWN_SHOWN;
113
+ const saved = 0 === known.length
114
+ ? 'No flows are saved for this project yet: drive the journey once and it is saved.'
115
+ : `Saved flows: ${known.slice(0, KNOWN_SHOWN).join(', ')}${more > 0 ? `, and ${String(more)} more (reticle_flow {action:"list"})` : ''}.`;
116
+ return new Error(`${UNKNOWN_FLOW_OPENING} ${asked}, so nothing ran. ${saved}`);
117
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * True when git answers that it does not ignore `path`, so a checkout gets the file from git. False
3
+ * when git ignores it, and when git cannot answer. Asked once for each path in this process. `path`
4
+ * need not exist yet.
5
+ */
6
+ export declare function gitTracks(path: string): boolean;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Whether git gives a checkout a path, or ignores it. One `git check-ignore` for each path.
3
+ */
4
+ import { spawnSync } from 'node:child_process';
5
+ import { existsSync } from 'node:fs';
6
+ import { dirname } from 'node:path';
7
+ /** Exit status of `git check-ignore` for a path that git does not ignore. */
8
+ const CHECK_IGNORE_NOT_IGNORED = 1;
9
+ const GIT_TIMEOUT_MS = 2_000;
10
+ const tracked = new Map();
11
+ /**
12
+ * True when git answers that it does not ignore `path`, so a checkout gets the file from git. False
13
+ * when git ignores it, and when git cannot answer. Asked once for each path in this process. `path`
14
+ * need not exist yet.
15
+ */
16
+ export function gitTracks(path) {
17
+ const known = tracked.get(path);
18
+ if (known !== undefined)
19
+ return known;
20
+ const result = spawnSync('git', ['check-ignore', '-q', path], {
21
+ cwd: existingAncestor(path),
22
+ stdio: 'ignore',
23
+ timeout: GIT_TIMEOUT_MS,
24
+ windowsHide: true,
25
+ });
26
+ const answer = CHECK_IGNORE_NOT_IGNORED === result.status;
27
+ tracked.set(path, answer);
28
+ return answer;
29
+ }
30
+ /** `path`, or the nearest directory above it that exists: git needs a real working directory. */
31
+ function existingAncestor(path) {
32
+ let dir = dirname(path);
33
+ while (!existsSync(dir) && dirname(dir) !== dir)
34
+ dir = dirname(dir);
35
+ return dir;
36
+ }
@@ -0,0 +1,25 @@
1
+ import type { ProjectCloud } from './cloud-config.js';
2
+ export declare const BackgroundSyncState: {
3
+ readonly ON: "on";
4
+ readonly OPTED_OUT: "opted-out";
5
+ readonly UNLINKED: "unlinked";
6
+ readonly SIGNED_OUT: "signed-out";
7
+ /** The platform refused the credential (401/403). Stays stopped until the sign-in changes. */
8
+ readonly REFUSED: "refused";
9
+ };
10
+ export type BackgroundSyncState = (typeof BackgroundSyncState)[keyof typeof BackgroundSyncState];
11
+ export interface BackgroundSyncGate {
12
+ state: BackgroundSyncState;
13
+ /** In words a person can act on. */
14
+ why: string;
15
+ /** Who is sending, when it is ON: a new value after a new sign-in or a new key. */
16
+ credential?: string;
17
+ }
18
+ /** May the daemon send this root's work now? Reads the disk, never the network. */
19
+ export declare function backgroundSyncGate(input: {
20
+ reticleRoot: string;
21
+ cloud: ProjectCloud;
22
+ env: NodeJS.ProcessEnv;
23
+ /** The signed-in session's token for that address, or undefined. */
24
+ signedIn: (url: string) => string | undefined;
25
+ }): BackgroundSyncGate;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Whether the daemon's background sync may send a project's work.
3
+ *
4
+ * The daemon sends without anybody asking, so it sends only when every one of these holds:
5
+ *
6
+ * - Nobody switched it off: `RETICLE_BACKGROUND_SYNC=0` on the machine, `"backgroundSync": false`
7
+ * in the project's `.reticle.json`.
8
+ * - The project is LINKED, by its own `.reticle/cloud.json`. The address comes from that link and
9
+ * nowhere else. An environment address is never used: a repository's `.env` that named the
10
+ * hosted service once sent another app's runs to the wrong workspace.
11
+ * - Somebody is signed in to that address, and this machine holds a key for the link. `reticle
12
+ * logout` stops it on the next tick; `reticle login` starts it again. OR the link's key is
13
+ * `RETICLE_API_KEY` from the environment, which is how CI runs: a committed `cloud.json`, a key
14
+ * kept as a secret, and nobody to sign in. The address still comes from the link, and
15
+ * `resolveProjectCloud` uses the environment's key only when it is for that address.
16
+ *
17
+ * `reticle sync` stays the explicit way to send now, and none of this applies to it.
18
+ */
19
+ import { dirname } from 'node:path';
20
+ import { ReticleEnv, apiKeyFrom } from '@reticlehq/core';
21
+ import { projectSetting } from '../intent/record-request.js';
22
+ export const BackgroundSyncState = {
23
+ ON: 'on',
24
+ OPTED_OUT: 'opted-out',
25
+ UNLINKED: 'unlinked',
26
+ SIGNED_OUT: 'signed-out',
27
+ /** The platform refused the credential (401/403). Stays stopped until the sign-in changes. */
28
+ REFUSED: 'refused',
29
+ };
30
+ const OFF_VALUES = new Set(['0', 'false', 'off', 'no']);
31
+ const BACKGROUND_SYNC_SETTING = 'backgroundSync';
32
+ /** May the daemon send this root's work now? Reads the disk, never the network. */
33
+ export function backgroundSyncGate(input) {
34
+ const { reticleRoot, cloud, env, signedIn } = input;
35
+ if (OFF_VALUES.has((env[ReticleEnv.BACKGROUND_SYNC] ?? '').toLowerCase())) {
36
+ return {
37
+ state: BackgroundSyncState.OPTED_OUT,
38
+ why: `off on this machine (${ReticleEnv.BACKGROUND_SYNC})`,
39
+ };
40
+ }
41
+ if (false === projectSetting(dirname(reticleRoot), BACKGROUND_SYNC_SETTING)) {
42
+ return {
43
+ state: BackgroundSyncState.OPTED_OUT,
44
+ why: `off in this project ("${BACKGROUND_SYNC_SETTING}": false in .reticle.json)`,
45
+ };
46
+ }
47
+ // `link` is set only from the project's own link file; an environment key leaves it unset.
48
+ if (cloud.link === undefined) {
49
+ return {
50
+ state: BackgroundSyncState.UNLINKED,
51
+ why: 'this project is not linked: run `reticle connect`',
52
+ };
53
+ }
54
+ if (null === cloud.config) {
55
+ return {
56
+ state: BackgroundSyncState.SIGNED_OUT,
57
+ why: cloud.reason ?? 'no key for this link: run `reticle connect`',
58
+ };
59
+ }
60
+ if (cloud.config.apiKey === apiKeyFrom(env)) {
61
+ return {
62
+ state: BackgroundSyncState.ON,
63
+ why: `sends to ${cloud.config.url} with ${ReticleEnv.API_KEY}`,
64
+ credential: cloud.config.apiKey,
65
+ };
66
+ }
67
+ const token = signedIn(cloud.config.url);
68
+ if (token === undefined) {
69
+ return {
70
+ state: BackgroundSyncState.SIGNED_OUT,
71
+ why: `nobody is signed in to ${cloud.config.url}: run \`reticle connect --url ${cloud.config.url}\``,
72
+ };
73
+ }
74
+ return {
75
+ state: BackgroundSyncState.ON,
76
+ why: `sends to ${cloud.config.url}`,
77
+ credential: `${cloud.config.apiKey}\u0000${token}`,
78
+ };
79
+ }
@@ -1,4 +1,4 @@
1
- import type { FileSystemPort } from '../project/fs/fs-port.js';
1
+ import { type FileSystemPort } from '../project/fs/fs-port.js';
2
2
  import { type CloudConfig } from './cloud-sync.js';
3
3
  /** `<reticleRoot>/cloud.json` — the project's cloud binding + sync policy (non-secret). */
4
4
  /** Re-exported so the existing importers keep working; the string itself lives in core. */
@@ -31,6 +31,17 @@ interface SyncPolicy {
31
31
  * a project that keeps its runs local has not agreed to send pictures of its pages either.
32
32
  */
33
33
  screenshots: boolean;
34
+ /**
35
+ * Push the frames filmed between steps (about one a second while Reticle drives a tab), which the
36
+ * dashboard plays as the run's video. Follows `screenshots` when the link does not say.
37
+ */
38
+ video: boolean;
39
+ /**
40
+ * Upload the episode log (every tool call and its whole result). Never a default and never
41
+ * inherited from another switch: only `"episodes": true` here, and even then only to a workspace
42
+ * that consented to share its data. See `episodesMaySync`.
43
+ */
44
+ episodes?: boolean;
34
45
  }
35
46
  /** Where a verification actually executes. Reserved for the hosted-runner path; default local. */
36
47
  export declare const VerifyMode: {