@reticlehq/server 3.5.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (721) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +123 -116
  3. package/dist/chromium-launch-options.d.ts +3 -1
  4. package/dist/chromium-launch-options.js +2 -1
  5. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  6. package/dist/command/cli/adhoc-suite.js +42 -7
  7. package/dist/command/cli/adhoc-verdict.d.ts +19 -2
  8. package/dist/command/cli/adhoc-verdict.js +76 -9
  9. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  10. package/dist/command/cli/answers/gate-exit.js +45 -0
  11. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  12. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  13. package/dist/command/cli/answers/open-note.d.ts +2 -0
  14. package/dist/command/cli/answers/open-note.js +22 -0
  15. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  16. package/dist/command/cli/auth/device-flow.js +17 -0
  17. package/dist/command/cli/cli-doctor.js +14 -0
  18. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  19. package/dist/command/cli/cli-flow-commands.js +31 -112
  20. package/dist/command/cli/cli-kill.js +3 -2
  21. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  22. package/dist/command/cli/cli-parse-grammar.js +75 -0
  23. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  24. package/dist/command/cli/cli-parse-verify.js +18 -0
  25. package/dist/command/cli/cli-parse.d.ts +19 -28
  26. package/dist/command/cli/cli-parse.js +82 -182
  27. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  28. package/dist/command/cli/cli-update-commands.js +61 -9
  29. package/dist/command/cli/cli-usage.d.ts +33 -0
  30. package/dist/command/cli/cli-usage.js +287 -0
  31. package/dist/command/cli/cli-verify.d.ts +35 -5
  32. package/dist/command/cli/cli-verify.js +114 -35
  33. package/dist/command/cli/cloud-cli.d.ts +13 -0
  34. package/dist/command/cli/cloud-cli.js +192 -341
  35. package/dist/command/cli/cloud-kit.d.ts +12 -0
  36. package/dist/command/cli/cloud-kit.js +41 -2
  37. package/dist/command/cli/cloud-link.d.ts +57 -0
  38. package/dist/command/cli/cloud-link.js +308 -0
  39. package/dist/command/cli/cloud-login.d.ts +22 -0
  40. package/dist/command/cli/cloud-login.js +96 -8
  41. package/dist/command/cli/context-command.d.ts +1 -0
  42. package/dist/command/cli/context-command.js +33 -0
  43. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  44. package/dist/command/cli/daemon-start-options.js +24 -3
  45. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
  46. package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
  47. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  48. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  49. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  50. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  51. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  52. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  53. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  54. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  55. package/dist/command/cli/drive/drive-attach.d.ts +27 -2
  56. package/dist/command/cli/drive/drive-attach.js +71 -4
  57. package/dist/command/cli/drive/drive-command.d.ts +2 -1
  58. package/dist/command/cli/drive/drive-command.js +13 -7
  59. package/dist/command/cli/known-regression.d.ts +13 -0
  60. package/dist/command/cli/known-regression.js +34 -0
  61. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  62. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  63. package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
  64. package/dist/command/cli/mcp-command.d.ts +6 -0
  65. package/dist/command/cli/mcp-command.js +13 -5
  66. package/dist/command/cli/ports/port-holder.d.ts +10 -0
  67. package/dist/command/cli/ports/port-holder.js +25 -1
  68. package/dist/command/cli/project-name.d.ts +29 -1
  69. package/dist/command/cli/project-name.js +107 -2
  70. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  71. package/dist/command/cli/setup-mcp-cli.js +35 -12
  72. package/dist/command/cli/status/status-lines.d.ts +1 -0
  73. package/dist/command/cli/status/status-lines.js +47 -2
  74. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  75. package/dist/command/cli/status/workspace-links.js +29 -0
  76. package/dist/command/cli/try-command.d.ts +96 -0
  77. package/dist/command/cli/try-command.js +362 -0
  78. package/dist/command/cli/tutorial.d.ts +0 -100
  79. package/dist/command/cli/tutorial.js +0 -181
  80. package/dist/command/cli/verify-results.d.ts +19 -0
  81. package/dist/command/cli/verify-results.js +29 -0
  82. package/dist/command/cli-onboarding.d.ts +0 -11
  83. package/dist/command/cli-onboarding.js +0 -15
  84. package/dist/command/cli.d.ts +20 -0
  85. package/dist/command/cli.js +130 -104
  86. package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
  87. package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
  88. package/dist/command/daemon/daemon-resilience.js +4 -4
  89. package/dist/command/daemon/daemon-resolve.d.ts +23 -1
  90. package/dist/command/daemon/daemon-resolve.js +79 -9
  91. package/dist/command/setup/agent-writer.d.ts +1 -1
  92. package/dist/command/setup/agent-writer.js +3 -2
  93. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  94. package/dist/command/setup/bringup/bridge-port.js +13 -3
  95. package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
  96. package/dist/command/setup/bringup/connect-lease.js +1 -0
  97. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  98. package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
  99. package/dist/command/setup/bringup/dev-server-wait.js +19 -0
  100. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  101. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  102. package/dist/command/setup/init/agent-restart.js +28 -0
  103. package/dist/command/setup/init/init-port.d.ts +14 -1
  104. package/dist/command/setup/init/init-port.js +32 -2
  105. package/dist/command/setup/init/init-runtime.d.ts +22 -2
  106. package/dist/command/setup/init/init-runtime.js +114 -38
  107. package/dist/command/setup/node-effects.d.ts +2 -0
  108. package/dist/command/setup/node-effects.js +38 -9
  109. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  110. package/dist/command/setup/probe/existing-app.js +14 -0
  111. package/dist/command/setup/remaining-steps.js +2 -1
  112. package/dist/command/setup/run-setup.d.ts +34 -9
  113. package/dist/command/setup/run-setup.js +65 -51
  114. package/dist/command/setup/setup-command.d.ts +25 -1
  115. package/dist/command/setup/setup-command.js +59 -4
  116. package/dist/command/setup/setup-mcp.js +25 -2
  117. package/dist/command/setup/tauri-signing.d.ts +19 -0
  118. package/dist/command/setup/tauri-signing.js +79 -0
  119. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  120. package/dist/command/setup/terminal/listeners.js +37 -6
  121. package/dist/command/update/update-nudge.d.ts +9 -0
  122. package/dist/command/update/update-nudge.js +1 -1
  123. package/dist/command/update/updater.js +11 -15
  124. package/dist/command/version/version-nudge.js +3 -0
  125. package/dist/command/version/version-skew.d.ts +20 -1
  126. package/dist/command/version/version-skew.js +49 -4
  127. package/dist/features/crawl/crawl-tools.js +4 -0
  128. package/dist/features/crawl/crawl.d.ts +6 -0
  129. package/dist/features/crawl/crawl.js +23 -2
  130. package/dist/features/exhaust/ledger.d.ts +21 -14
  131. package/dist/features/exhaust/ledger.js +35 -9
  132. package/dist/features/harness/app-findings.d.ts +2 -0
  133. package/dist/features/harness/app-findings.js +52 -0
  134. package/dist/features/harness/drive-report.d.ts +61 -1
  135. package/dist/features/harness/drive-report.js +394 -26
  136. package/dist/features/harness/drive-runs.d.ts +120 -0
  137. package/dist/features/harness/drive-runs.js +289 -0
  138. package/dist/features/harness/drivers.d.ts +10 -14
  139. package/dist/features/harness/drivers.js +10 -14
  140. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  141. package/dist/features/harness/explore/console-pages.js +146 -0
  142. package/dist/features/harness/explore/disparity.d.ts +19 -0
  143. package/dist/features/harness/explore/disparity.js +71 -0
  144. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  145. package/dist/features/harness/explore/fake-app.js +49 -0
  146. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  147. package/dist/features/harness/explore/goal-search.js +144 -0
  148. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  149. package/dist/features/harness/explore/page-tree.js +148 -0
  150. package/dist/features/harness/explore/site-map.d.ts +34 -0
  151. package/dist/features/harness/explore/site-map.js +150 -0
  152. package/dist/features/harness/fill-values.d.ts +3 -73
  153. package/dist/features/harness/fill-values.js +3 -169
  154. package/dist/features/harness/goals.d.ts +82 -0
  155. package/dist/features/harness/goals.js +330 -0
  156. package/dist/features/harness/harness.d.ts +51 -1
  157. package/dist/features/harness/harness.js +207 -6
  158. package/dist/features/harness/platform/drive-target.d.ts +30 -0
  159. package/dist/features/harness/platform/drive-target.js +81 -0
  160. package/dist/features/harness/platform/local-apps.d.ts +127 -0
  161. package/dist/features/harness/platform/local-apps.js +280 -0
  162. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  163. package/dist/features/harness/platform/persona-credentials.js +69 -0
  164. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  165. package/dist/features/harness/platform/platform-drives.js +114 -0
  166. package/dist/features/harness/platform/refusal.d.ts +52 -0
  167. package/dist/features/harness/platform/refusal.js +71 -0
  168. package/dist/features/harness/platform/remote-drive.d.ts +186 -0
  169. package/dist/features/harness/platform/remote-drive.js +378 -0
  170. package/dist/features/harness/platform/script.d.ts +94 -0
  171. package/dist/features/harness/platform/script.js +260 -0
  172. package/dist/features/harness/platform/server-driver.d.ts +54 -0
  173. package/dist/features/harness/platform/server-driver.js +182 -0
  174. package/dist/features/harness/platform-config.d.ts +41 -1
  175. package/dist/features/harness/platform-config.js +106 -9
  176. package/dist/features/harness/route-guess.d.ts +13 -0
  177. package/dist/features/harness/route-guess.js +49 -0
  178. package/dist/features/harness/script/app-controls.d.ts +5 -0
  179. package/dist/features/harness/script/app-controls.js +40 -0
  180. package/dist/features/harness/script/lane-ids.d.ts +14 -0
  181. package/dist/features/harness/script/lane-ids.js +16 -0
  182. package/dist/features/harness/script/script-run.d.ts +70 -0
  183. package/dist/features/harness/script/script-run.js +606 -0
  184. package/dist/features/license/license.d.ts +2 -2
  185. package/dist/features/visual/step-shots.d.ts +31 -0
  186. package/dist/features/visual/step-shots.js +231 -0
  187. package/dist/features/visual/visual-tools.d.ts +10 -1
  188. package/dist/features/visual/visual-tools.js +62 -17
  189. package/dist/hooks/client-directory.d.ts +18 -0
  190. package/dist/hooks/client-directory.js +57 -0
  191. package/dist/hooks/coding-agents.d.ts +34 -0
  192. package/dist/hooks/coding-agents.js +117 -0
  193. package/dist/hooks/driven-by.d.ts +23 -0
  194. package/dist/hooks/driven-by.js +56 -0
  195. package/dist/hooks/hook-bus.d.ts +4 -0
  196. package/dist/hooks/hook-bus.js +18 -0
  197. package/dist/hooks/hook-commands.js +15 -4
  198. package/dist/hooks/tool-log.d.ts +9 -0
  199. package/dist/hooks/tool-log.js +29 -0
  200. package/dist/index.d.ts +2 -0
  201. package/dist/index.js +80 -243
  202. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  203. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  204. package/dist/judgement/capsule/causal-summary.js +33 -0
  205. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  206. package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
  207. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  208. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  209. package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
  210. package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
  211. package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
  212. package/dist/judgement/runs/artifact/run-store.js +195 -3
  213. package/dist/judgement/runs/context-tools.js +59 -1
  214. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  215. package/dist/judgement/runs/default-run-id.js +16 -0
  216. package/dist/judgement/runs/drive-run.d.ts +71 -1
  217. package/dist/judgement/runs/drive-run.js +317 -5
  218. package/dist/judgement/runs/repair-prompt.js +1 -1
  219. package/dist/judgement/runs/resume.d.ts +44 -0
  220. package/dist/judgement/runs/resume.js +137 -0
  221. package/dist/judgement/runs/reticle-runner.js +13 -3
  222. package/dist/judgement/runs/runner-port.d.ts +5 -1
  223. package/dist/judgement/runs/runner-port.js +8 -2
  224. package/dist/judgement/runs/verification-sync.d.ts +5 -2
  225. package/dist/judgement/runs/verification-sync.js +40 -18
  226. package/dist/language/flows/change/gate.d.ts +10 -0
  227. package/dist/language/flows/change/gate.js +22 -0
  228. package/dist/language/flows/decision.js +36 -1
  229. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  230. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  231. package/dist/language/flows/flow-anchor.d.ts +61 -10
  232. package/dist/language/flows/flow-anchor.js +98 -6
  233. package/dist/language/flows/flow-cross-step.d.ts +15 -0
  234. package/dist/language/flows/flow-cross-step.js +21 -0
  235. package/dist/language/flows/flow-intent.d.ts +1 -0
  236. package/dist/language/flows/flow-journey.d.ts +6 -0
  237. package/dist/language/flows/flow-journey.js +20 -0
  238. package/dist/language/flows/flow-learning.d.ts +4 -0
  239. package/dist/language/flows/flow-learning.js +45 -14
  240. package/dist/language/flows/flow-mutate-tools.js +5 -3
  241. package/dist/language/flows/flow-replay-run.d.ts +23 -9
  242. package/dist/language/flows/flow-replay-run.js +115 -110
  243. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  244. package/dist/language/flows/flow-replay.d.ts +40 -1
  245. package/dist/language/flows/flow-replay.js +110 -22
  246. package/dist/language/flows/flow-result.d.ts +22 -1
  247. package/dist/language/flows/flow-result.js +47 -2
  248. package/dist/language/flows/flow-scope.js +5 -1
  249. package/dist/language/flows/flow-step-runners.d.ts +22 -2
  250. package/dist/language/flows/flow-step-runners.js +247 -47
  251. package/dist/language/flows/flow-store-for-session.d.ts +2 -2
  252. package/dist/language/flows/flow-store-for-session.js +7 -3
  253. package/dist/language/flows/flow-tools.d.ts +10 -0
  254. package/dist/language/flows/flow-tools.js +112 -89
  255. package/dist/language/flows/flows.d.ts +16 -1
  256. package/dist/language/flows/flows.js +74 -12
  257. package/dist/language/flows/heal-run.js +6 -4
  258. package/dist/language/flows/narrow-write.d.ts +7 -0
  259. package/dist/language/flows/narrow-write.js +36 -1
  260. package/dist/language/flows/recording/flake.d.ts +2 -2
  261. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  262. package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
  263. package/dist/language/flows/recording/tape/recordings.js +95 -13
  264. package/dist/language/flows/replay-from-hud.d.ts +20 -0
  265. package/dist/language/flows/replay-from-hud.js +51 -0
  266. package/dist/language/flows/replay.d.ts +9 -5
  267. package/dist/language/flows/replay.js +56 -15
  268. package/dist/language/flows/single-replay.d.ts +7 -0
  269. package/dist/language/flows/single-replay.js +26 -0
  270. package/dist/language/flows/suite/suite-flakes.js +2 -0
  271. package/dist/language/flows/suite-selection.d.ts +2 -15
  272. package/dist/language/flows/suite-selection.js +4 -3
  273. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  274. package/dist/language/flows/verify-change-tools.js +202 -191
  275. package/dist/launch-chromium.d.ts +27 -5
  276. package/dist/launch-chromium.js +38 -8
  277. package/dist/memory/cloud/cloud-config.d.ts +22 -1
  278. package/dist/memory/cloud/cloud-config.js +34 -5
  279. package/dist/memory/cloud/cloud-sync.d.ts +17 -14
  280. package/dist/memory/cloud/cloud-sync.js +15 -4
  281. package/dist/memory/cloud/harness-config.d.ts +75 -1
  282. package/dist/memory/cloud/harness-config.js +115 -24
  283. package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
  284. package/dist/memory/cloud/hud-notices-source.js +128 -0
  285. package/dist/memory/cloud/memory-scope.d.ts +161 -0
  286. package/dist/memory/cloud/memory-scope.js +227 -0
  287. package/dist/memory/cloud/sync-cycle.d.ts +44 -7
  288. package/dist/memory/cloud/sync-cycle.js +129 -15
  289. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  290. package/dist/memory/cloud/sync-daemon.js +121 -9
  291. package/dist/memory/cloud/sync-disk.d.ts +1 -1
  292. package/dist/memory/cloud/sync-disk.js +31 -10
  293. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  294. package/dist/memory/cloud/sync-screenshots.js +105 -0
  295. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  296. package/dist/memory/cloud/unsynced-roots.js +166 -0
  297. package/dist/memory/impact/account-watch.d.ts +34 -0
  298. package/dist/memory/impact/account-watch.js +59 -0
  299. package/dist/memory/impact/impact-recorder.d.ts +8 -0
  300. package/dist/memory/impact/impact-recorder.js +12 -2
  301. package/dist/memory/impact/impact-store.d.ts +17 -4
  302. package/dist/memory/impact/impact-store.js +169 -63
  303. package/dist/memory/intent/inline-intent.d.ts +1 -0
  304. package/dist/memory/intent/intent-shard-store.js +16 -4
  305. package/dist/memory/intent/intent-shard.d.ts +14 -2
  306. package/dist/memory/intent/intent-store.d.ts +1 -0
  307. package/dist/memory/intent/intent-tools.js +122 -4
  308. package/dist/memory/intent/open-intents.d.ts +6 -0
  309. package/dist/memory/intent/open-intents.js +10 -1
  310. package/dist/memory/intent/settled-words.d.ts +24 -0
  311. package/dist/memory/intent/settled-words.js +130 -0
  312. package/dist/memory/journal/drive-flow.d.ts +16 -0
  313. package/dist/memory/journal/drive-flow.js +34 -2
  314. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  315. package/dist/memory/journal/drive-run-flush.js +20 -5
  316. package/dist/memory/journal/envelope.d.ts +8 -8
  317. package/dist/memory/journal/journal-recorder.js +52 -3
  318. package/dist/memory/journal/on-disk/retention.d.ts +8 -0
  319. package/dist/memory/journal/on-disk/retention.js +32 -2
  320. package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
  321. package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
  322. package/dist/memory/journal/session-end.d.ts +15 -1
  323. package/dist/memory/journal/session-end.js +42 -9
  324. package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
  325. package/dist/memory/project/artifact-root-resolver.js +125 -16
  326. package/dist/memory/project/artifact-root.d.ts +46 -8
  327. package/dist/memory/project/artifact-root.js +89 -10
  328. package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
  329. package/dist/memory/project/dir/reticle-dir.js +26 -3
  330. package/dist/memory/project/link-directory.d.ts +15 -0
  331. package/dist/memory/project/link-directory.js +44 -0
  332. package/dist/memory/project/project-tools.js +22 -3
  333. package/dist/memory/project/root-claims.d.ts +6 -0
  334. package/dist/memory/project/root-claims.js +39 -0
  335. package/dist/memory/project/session-root.d.ts +26 -1
  336. package/dist/memory/project/session-root.js +49 -5
  337. package/dist/memory/project/sync-status.d.ts +85 -0
  338. package/dist/memory/project/sync-status.js +224 -0
  339. package/dist/memory/recall/memory-tools.js +47 -2
  340. package/dist/memory/recall/platform-memory.d.ts +34 -0
  341. package/dist/memory/recall/platform-memory.js +139 -0
  342. package/dist/memory/recall/project-memory.d.ts +19 -0
  343. package/dist/memory/recall/project-memory.js +80 -13
  344. package/dist/portal/bridge/bridge.d.ts +9 -3
  345. package/dist/portal/bridge/bridge.js +82 -22
  346. package/dist/portal/bridge/harness-request.d.ts +23 -0
  347. package/dist/portal/bridge/harness-request.js +27 -0
  348. package/dist/portal/bridge/pairing-token.d.ts +9 -0
  349. package/dist/portal/bridge/pairing-token.js +17 -0
  350. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  351. package/dist/portal/bridge/wrong-path.js +35 -0
  352. package/dist/portal/input/network-mock-tools.js +11 -2
  353. package/dist/portal/input/real-input.d.ts +83 -10
  354. package/dist/portal/input/real-input.js +218 -30
  355. package/dist/portal/input/viewport-tools.js +3 -3
  356. package/dist/portal/pool/browser-pool.d.ts +70 -9
  357. package/dist/portal/pool/browser-pool.js +190 -37
  358. package/dist/portal/pool/context-permissions.d.ts +33 -0
  359. package/dist/portal/pool/context-permissions.js +33 -0
  360. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  361. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  362. package/dist/portal/pool/playwright-launcher.d.ts +35 -0
  363. package/dist/portal/pool/playwright-launcher.js +64 -3
  364. package/dist/portal/pool/pool-contract.d.ts +28 -5
  365. package/dist/portal/session/agent-link.d.ts +8 -0
  366. package/dist/portal/session/agent-link.js +17 -0
  367. package/dist/portal/session/command-payload.d.ts +8 -0
  368. package/dist/portal/session/command-payload.js +24 -0
  369. package/dist/portal/session/daemon-answers.d.ts +3 -3
  370. package/dist/portal/session/daemon-answers.js +4 -2
  371. package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
  372. package/dist/portal/session/dev-server/dev-command.js +87 -12
  373. package/dist/portal/session/facts/departure-note.d.ts +22 -0
  374. package/dist/portal/session/facts/departure-note.js +47 -0
  375. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  376. package/dist/portal/session/facts/observed-state.js +46 -3
  377. package/dist/portal/session/facts/session-replaced.d.ts +5 -0
  378. package/dist/portal/session/facts/session-replaced.js +5 -0
  379. package/dist/portal/session/first-run-wiring.d.ts +42 -0
  380. package/dist/portal/session/first-run-wiring.js +132 -0
  381. package/dist/portal/session/human/live-control.d.ts +9 -2
  382. package/dist/portal/session/human/live-control.js +12 -3
  383. package/dist/portal/session/human/notes-ledger.d.ts +20 -0
  384. package/dist/portal/session/human/notes-ledger.js +55 -0
  385. package/dist/portal/session/human/review-store.d.ts +12 -0
  386. package/dist/portal/session/human/review-store.js +18 -10
  387. package/dist/portal/session/live-control-tools.d.ts +0 -13
  388. package/dist/portal/session/live-control-tools.js +107 -13
  389. package/dist/portal/session/narration-args.d.ts +5 -0
  390. package/dist/portal/session/narration-args.js +17 -0
  391. package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
  392. package/dist/portal/session/no-session-diagnosis.js +46 -9
  393. package/dist/portal/session/no-session-next-action.d.ts +31 -0
  394. package/dist/portal/session/no-session-next-action.js +159 -60
  395. package/dist/portal/session/no-session-watch.d.ts +14 -1
  396. package/dist/portal/session/no-session-watch.js +227 -17
  397. package/dist/portal/session/presence/session-lease.js +1 -1
  398. package/dist/portal/session/presence/session-mirror.js +3 -0
  399. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  400. package/dist/portal/session/recorded-gaps.js +251 -0
  401. package/dist/portal/session/serving-directory.d.ts +27 -0
  402. package/dist/portal/session/serving-directory.js +45 -0
  403. package/dist/portal/session/session-health.d.ts +18 -0
  404. package/dist/portal/session/session-health.js +9 -1
  405. package/dist/portal/session/session-info.d.ts +8 -1
  406. package/dist/portal/session/session-info.js +8 -1
  407. package/dist/portal/session/session-manager.d.ts +39 -0
  408. package/dist/portal/session/session-manager.js +98 -11
  409. package/dist/portal/session/session-reaper.js +4 -1
  410. package/dist/portal/session/session-successor.d.ts +13 -0
  411. package/dist/portal/session/session-successor.js +1 -1
  412. package/dist/portal/session/session-tools.js +26 -3
  413. package/dist/portal/session/session.d.ts +22 -30
  414. package/dist/portal/session/session.js +81 -79
  415. package/dist/portal/session/timing/command-timeout.js +25 -1
  416. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  417. package/dist/portal/session/timing/wall-clock.js +1 -1
  418. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  419. package/dist/portal/session/zero-install-first-call.js +88 -0
  420. package/dist/start-options.d.ts +12 -0
  421. package/dist/start-wiring.d.ts +63 -0
  422. package/dist/start-wiring.js +169 -0
  423. package/dist/status-payload.d.ts +23 -1
  424. package/dist/status-payload.js +36 -1
  425. package/dist/surface/http-server.js +18 -2
  426. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  427. package/dist/surface/mcp/attach-memory.js +12 -1
  428. package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
  429. package/dist/surface/mcp/mcp-proxy.js +65 -13
  430. package/dist/surface/mcp/mcp.d.ts +34 -6
  431. package/dist/surface/mcp/mcp.js +61 -17
  432. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  433. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  434. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  435. package/dist/surface/mcp/server-instructions.d.ts +4 -2
  436. package/dist/surface/mcp/server-instructions.js +32 -14
  437. package/dist/surface/mcp/shared-params.js +2 -2
  438. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  439. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  440. package/dist/surface/tools/account-tool.d.ts +22 -0
  441. package/dist/surface/tools/account-tool.js +157 -0
  442. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  443. package/dist/surface/tools/act/act-danger.js +38 -1
  444. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  445. package/dist/surface/tools/act/act-observation.js +57 -0
  446. package/dist/surface/tools/act/act-preflight.js +25 -2
  447. package/dist/surface/tools/act/act-target.js +8 -3
  448. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
  449. package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
  450. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  451. package/dist/surface/tools/act/resolve-target.js +18 -3
  452. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  453. package/dist/surface/tools/act/screen-request.js +113 -0
  454. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  455. package/dist/surface/tools/act/sequence-grade.js +13 -2
  456. package/dist/surface/tools/act/settle-in-flight.js +25 -3
  457. package/dist/surface/tools/act-sequence-tool.js +138 -29
  458. package/dist/surface/tools/act-tools.d.ts +0 -9
  459. package/dist/surface/tools/act-tools.js +71 -41
  460. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  461. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  462. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  463. package/dist/surface/tools/agent/app-notes.js +48 -0
  464. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  465. package/dist/surface/tools/agent/build-staleness.js +62 -0
  466. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  467. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  468. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  469. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  470. package/dist/surface/tools/agent/notices.d.ts +50 -0
  471. package/dist/surface/tools/agent/notices.js +152 -0
  472. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  473. package/dist/surface/tools/agent/reteach.js +50 -0
  474. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  475. package/dist/surface/tools/args/alias-args.js +10 -0
  476. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  477. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  478. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  479. package/dist/surface/tools/assert/assert-source.js +40 -0
  480. package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
  481. package/dist/surface/tools/assert/assert-verdict.js +42 -17
  482. package/dist/surface/tools/browser-tools.js +51 -2
  483. package/dist/surface/tools/chat-drives.d.ts +101 -0
  484. package/dist/surface/tools/chat-drives.js +409 -0
  485. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  486. package/dist/surface/tools/coverage-tools.js +2 -53
  487. package/dist/surface/tools/dynamic-tools.js +29 -1
  488. package/dist/surface/tools/empty-session-list.d.ts +51 -0
  489. package/dist/surface/tools/empty-session-list.js +120 -0
  490. package/dist/surface/tools/error-recovery.d.ts +14 -0
  491. package/dist/surface/tools/error-recovery.js +105 -8
  492. package/dist/surface/tools/explore-tools.d.ts +31 -1
  493. package/dist/surface/tools/explore-tools.js +438 -66
  494. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  495. package/dist/surface/tools/feedback-tools.js +18 -3
  496. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  497. package/dist/surface/tools/gap-novelty.js +8 -1
  498. package/dist/surface/tools/harness-explore.d.ts +118 -57
  499. package/dist/surface/tools/harness-explore.js +344 -292
  500. package/dist/surface/tools/harness-gate.d.ts +88 -0
  501. package/dist/surface/tools/harness-gate.js +235 -0
  502. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  503. package/dist/surface/tools/harness-hunt.js +215 -0
  504. package/dist/surface/tools/harness-plan.d.ts +17 -0
  505. package/dist/surface/tools/harness-plan.js +38 -0
  506. package/dist/surface/tools/harness-script.d.ts +30 -0
  507. package/dist/surface/tools/harness-script.js +560 -0
  508. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  509. package/dist/surface/tools/harness-tab-guard.js +27 -0
  510. package/dist/surface/tools/harness-toolset.d.ts +22 -1
  511. package/dist/surface/tools/harness-toolset.js +101 -7
  512. package/dist/surface/tools/human-notes.d.ts +16 -0
  513. package/dist/surface/tools/human-notes.js +27 -0
  514. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  515. package/dist/surface/tools/invoke-tool.js +263 -85
  516. package/dist/surface/tools/lease-hint.js +26 -5
  517. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  518. package/dist/surface/tools/lease-permissions.js +73 -0
  519. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  520. package/dist/surface/tools/lease-readiness.js +57 -0
  521. package/dist/surface/tools/lease-seed.d.ts +49 -0
  522. package/dist/surface/tools/lease-seed.js +167 -0
  523. package/dist/surface/tools/lease-tools.d.ts +13 -24
  524. package/dist/surface/tools/lease-tools.js +146 -197
  525. package/dist/surface/tools/live-call-text.js +4 -4
  526. package/dist/surface/tools/merge-tools.js +42 -2
  527. package/dist/surface/tools/merged-name-redirect.js +4 -0
  528. package/dist/surface/tools/next-step.d.ts +29 -0
  529. package/dist/surface/tools/next-step.js +214 -0
  530. package/dist/surface/tools/observe-tools.js +45 -9
  531. package/dist/surface/tools/platform-moment.d.ts +72 -0
  532. package/dist/surface/tools/platform-moment.js +296 -0
  533. package/dist/surface/tools/query-hint-schema.d.ts +7 -0
  534. package/dist/surface/tools/query-hint-schema.js +10 -0
  535. package/dist/surface/tools/read-tools.js +71 -14
  536. package/dist/surface/tools/real-input-attempt.js +96 -13
  537. package/dist/surface/tools/reticle-result.d.ts +120 -0
  538. package/dist/surface/tools/reticle-result.js +364 -0
  539. package/dist/surface/tools/tool-kit.d.ts +83 -3
  540. package/dist/surface/tools/tool-kit.js +77 -7
  541. package/dist/surface/tools/tools.js +43 -59
  542. package/dist/telemetry/account-envelope.d.ts +7 -0
  543. package/dist/telemetry/account-envelope.js +61 -0
  544. package/dist/telemetry/agent-client.d.ts +15 -0
  545. package/dist/telemetry/agent-client.js +57 -0
  546. package/dist/telemetry/app-instrumented.js +9 -2
  547. package/dist/telemetry/argument-shape.d.ts +7 -0
  548. package/dist/telemetry/argument-shape.js +86 -1
  549. package/dist/telemetry/automation-hint.d.ts +2 -3
  550. package/dist/telemetry/automation-hint.js +33 -8
  551. package/dist/telemetry/cli-telemetry.js +7 -2
  552. package/dist/telemetry/daemon-telemetry.js +3 -0
  553. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  554. package/dist/telemetry/error-fingerprint.js +61 -5
  555. package/dist/telemetry/feedback-cli.d.ts +0 -13
  556. package/dist/telemetry/feedback-cli.js +0 -77
  557. package/dist/telemetry/feedback.d.ts +13 -0
  558. package/dist/telemetry/feedback.js +183 -17
  559. package/dist/telemetry/harness-run.d.ts +18 -0
  560. package/dist/telemetry/harness-run.js +80 -0
  561. package/dist/telemetry/hud-events.d.ts +16 -0
  562. package/dist/telemetry/hud-events.js +27 -0
  563. package/dist/telemetry/hud-metrics.d.ts +29 -6
  564. package/dist/telemetry/hud-metrics.js +116 -25
  565. package/dist/telemetry/init-telemetry.js +2 -2
  566. package/dist/telemetry/install-source.d.ts +13 -25
  567. package/dist/telemetry/install-source.js +44 -3
  568. package/dist/telemetry/mcp-connection.d.ts +0 -14
  569. package/dist/telemetry/mcp-connection.js +5 -1
  570. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  571. package/dist/telemetry/onboarding-firsts.js +81 -6
  572. package/dist/telemetry/platform-linked.d.ts +5 -0
  573. package/dist/telemetry/platform-linked.js +32 -0
  574. package/dist/telemetry/project-profile.js +5 -3
  575. package/dist/telemetry/proxy-telemetry.js +4 -1
  576. package/dist/telemetry/session-metrics.d.ts +15 -4
  577. package/dist/telemetry/session-metrics.js +88 -52
  578. package/dist/telemetry/telemetry.d.ts +38 -2
  579. package/dist/telemetry/telemetry.js +144 -34
  580. package/dist/telemetry/verification-of.d.ts +3 -1
  581. package/dist/telemetry/verification-of.js +13 -4
  582. package/dist/wire-journal.d.ts +2 -2
  583. package/dist/wire-journal.js +20 -6
  584. package/docs/README.md +3 -3
  585. package/docs/actions.mdx +6 -3
  586. package/docs/adapters.md +1 -1
  587. package/docs/agent-cheatsheet.md +25 -28
  588. package/docs/architecture.md +5 -5
  589. package/docs/autodrive.md +33 -28
  590. package/docs/benchmarks.md +5 -5
  591. package/docs/best-practices.mdx +27 -9
  592. package/docs/capabilities.mdx +14 -16
  593. package/docs/cli/affected.mdx +1 -1
  594. package/docs/cli/cloud.mdx +54 -75
  595. package/docs/cli/doctor.mdx +14 -3
  596. package/docs/cli/drive.mdx +20 -14
  597. package/docs/cli/feedback.mdx +3 -3
  598. package/docs/cli/gate.mdx +7 -2
  599. package/docs/cli/help.mdx +50 -55
  600. package/docs/cli/init.mdx +43 -28
  601. package/docs/cli/license.mdx +12 -8
  602. package/docs/cli/mcp.mdx +4 -4
  603. package/docs/cli/open.mdx +3 -3
  604. package/docs/cli/report.mdx +4 -2
  605. package/docs/cli/restart.mdx +2 -2
  606. package/docs/cli/rollback.mdx +14 -8
  607. package/docs/cli/serve.mdx +4 -4
  608. package/docs/cli/setup.mdx +23 -0
  609. package/docs/cli/status.mdx +18 -5
  610. package/docs/cli/stop.mdx +67 -8
  611. package/docs/cli/try.mdx +62 -0
  612. package/docs/cli/update.mdx +4 -3
  613. package/docs/cli/verify.mdx +17 -6
  614. package/docs/cli/version.mdx +5 -4
  615. package/docs/cli.mdx +111 -42
  616. package/docs/debugging.md +3 -3
  617. package/docs/deploy-checks.md +1 -1
  618. package/docs/desktop.mdx +9 -3
  619. package/docs/enterprise.md +11 -10
  620. package/docs/environment.mdx +7 -8
  621. package/docs/faq.mdx +3 -3
  622. package/docs/first-drive.md +5 -4
  623. package/docs/flows.md +35 -27
  624. package/docs/for-agents.md +4 -5
  625. package/docs/frameworks.mdx +32 -21
  626. package/docs/getting-started.md +65 -61
  627. package/docs/human-control.md +16 -16
  628. package/docs/index.mdx +15 -42
  629. package/docs/install-agentic.mdx +22 -37
  630. package/docs/install-manual.mdx +23 -13
  631. package/docs/instrumentation.mdx +5 -3
  632. package/docs/integration-patterns.md +7 -7
  633. package/docs/license-activation.mdx +1 -1
  634. package/docs/multi-agent-testing.md +24 -6
  635. package/docs/packages/babel-plugin.mdx +4 -2
  636. package/docs/packages/browser.mdx +16 -10
  637. package/docs/packages/core.mdx +12 -5
  638. package/docs/packages/electron.mdx +3 -2
  639. package/docs/packages/engine.mdx +1 -1
  640. package/docs/packages/eslint-plugin.mdx +18 -12
  641. package/docs/packages/next.mdx +8 -7
  642. package/docs/packages/open-verification.mdx +1 -1
  643. package/docs/packages/server.mdx +5 -5
  644. package/docs/packages/tauri.mdx +9 -9
  645. package/docs/packages/test.mdx +4 -10
  646. package/docs/packages/vite-plugin.mdx +32 -4
  647. package/docs/packages.mdx +11 -15
  648. package/docs/platform-integration.md +6 -5
  649. package/docs/predicates.mdx +40 -24
  650. package/docs/quickstart.mdx +69 -30
  651. package/docs/required-checks.md +8 -7
  652. package/docs/reticle-manual.md +15 -5
  653. package/docs/skill-file.mdx +17 -79
  654. package/docs/skill-setup.md +9 -9
  655. package/docs/skill.md +200 -0
  656. package/docs/system-map.md +7 -7
  657. package/docs/telemetry.md +23 -25
  658. package/docs/testing.md +4 -4
  659. package/docs/token-efficiency.md +12 -12
  660. package/docs/tools/act-and-wait.mdx +9 -2
  661. package/docs/tools/act-sequence.mdx +6 -7
  662. package/docs/tools/act.mdx +2 -2
  663. package/docs/tools/assert.mdx +18 -17
  664. package/docs/tools/console.mdx +9 -9
  665. package/docs/tools/inspect.mdx +16 -7
  666. package/docs/tools/look.mdx +24 -0
  667. package/docs/tools/navigate.mdx +5 -3
  668. package/docs/tools/network.mdx +2 -2
  669. package/docs/tools/observe.mdx +6 -6
  670. package/docs/tools/overview.mdx +34 -33
  671. package/docs/tools/query.mdx +5 -5
  672. package/docs/tools/session-and-feedback.mdx +22 -13
  673. package/docs/tools/sessions.mdx +8 -8
  674. package/docs/tools/snapshot.mdx +6 -5
  675. package/docs/tools/state.mdx +9 -9
  676. package/docs/tools/tools-and-run.mdx +26 -24
  677. package/docs/tools/verify.mdx +28 -0
  678. package/docs/tools/wait-for.mdx +8 -4
  679. package/docs/troubleshooting.mdx +21 -6
  680. package/docs/usage.md +55 -46
  681. package/docs/use-cases.mdx +3 -3
  682. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  683. package/docs/vs-playwright-mcp.mdx +3 -1
  684. package/docs/what-is-recorded.md +17 -5
  685. package/docs/what-is-reticle.mdx +5 -3
  686. package/docs/why-reticle.mdx +1 -1
  687. package/package.json +9 -12
  688. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  689. package/dist/command/cli/demo/demo-page.js +0 -241
  690. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  691. package/dist/command/cli/demo/demo-run.js +0 -138
  692. package/dist/features/harness/driver.d.ts +0 -50
  693. package/dist/features/harness/driver.js +0 -236
  694. package/dist/features/harness/jev-driver.d.ts +0 -188
  695. package/dist/features/harness/jev-driver.js +0 -678
  696. package/dist/features/harness/openai-driver.d.ts +0 -58
  697. package/dist/features/harness/openai-driver.js +0 -206
  698. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  699. package/dist/judgement/hunt/hunt-report.js +0 -84
  700. package/dist/language/flows/buddy-status.d.ts +0 -25
  701. package/dist/language/flows/buddy-status.js +0 -32
  702. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  703. package/dist/language/flows/change/watch-batcher.js +0 -19
  704. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  705. package/dist/memory/cloud/harness-offer.js +0 -145
  706. package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
  707. package/dist/memory/project/dir/fill-value-store.js +0 -88
  708. package/dist/surface/tools/feature-capture.d.ts +0 -151
  709. package/dist/surface/tools/feature-capture.js +0 -235
  710. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  711. package/dist/surface/tools/tool-hit-rate.js +0 -90
  712. package/dist/telemetry/harness-drive.d.ts +0 -4
  713. package/dist/telemetry/harness-drive.js +0 -35
  714. package/dist/telemetry/identify.d.ts +0 -22
  715. package/dist/telemetry/identify.js +0 -73
  716. package/docs/cli/capsules.mdx +0 -70
  717. package/docs/cli/hunt.mdx +0 -73
  718. package/docs/cli/identify.mdx +0 -76
  719. package/docs/cli/kill.mdx +0 -91
  720. package/docs/cli/watch.mdx +0 -62
  721. package/docs/local-registry.md +0 -143
@@ -1,4 +1,5 @@
1
1
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { CLI_CLIENT_NAME } from '../../judgement/runs/verification-sync.js';
2
3
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
3
4
  import { LOOPBACK_HOST, MCP_SSE_PATH } from '@reticlehq/core';
4
5
  import { TOKEN_QUERY_PARAM } from '../../portal/bridge/token-auth.js';
@@ -20,12 +21,30 @@ const leaseFailedLine = (url) => `could not open ${url} in a Reticle browser, so
20
21
  * the caller must hand to `releaseLease`; `{ failed }` is the lease's own refusal, as lines to print —
21
22
  * a missing browser, an app that is not up — so nothing is asserted against a page that never opened.
22
23
  */
23
- export async function leaseIfNoTab(caller, url, sessions) {
24
+ export async function leaseIfNoTab(caller, url, sessions,
25
+ /** The caller's project `.reticle`, so the lease's runs land where this command looks. */
26
+ root) {
24
27
  const open = [...(await sessions())];
25
28
  if ('open' !== decideOpen(open, url).action) {
26
29
  return open.some((s) => sameDocument(s.url, url)) ? { alreadyAt: true } : {};
27
30
  }
28
- return acquireLease(caller, url);
31
+ return acquireLease(caller, url, false, root);
32
+ }
33
+ /**
34
+ * Whether the tab named by `sessionId` already shows `url`'s document.
35
+ *
36
+ * Read from the same status the unpinned path reads. A status read that fails, or a session the
37
+ * daemon does not list, answers false: navigating is the old behaviour, so a doubt costs a reload
38
+ * rather than an assert against a page that is not there.
39
+ */
40
+ async function pinnedTabIsAt(sessions, sessionId, url) {
41
+ try {
42
+ const pinned = (await sessions()).find((s) => s.sessionId === sessionId);
43
+ return pinned !== undefined && sameDocument(pinned.url, url);
44
+ }
45
+ catch {
46
+ return false;
47
+ }
29
48
  }
30
49
  /**
31
50
  * Whether two urls name the same document, ignoring a trailing slash and the hash.
@@ -50,11 +69,26 @@ function sameDocument(a, b) {
50
69
  * caller hands to `releaseLease`; `{ failed }` is the lease's own refusal, as lines to print.
51
70
  * `init`'s connect proof on a machine with no system browser takes this path directly.
52
71
  */
53
- export async function acquireLease(caller, url) {
54
- const acquired = await caller.call(ReticleTool.RUN, { tool: ReticleTool.LEASE, args: { action: LeaseAction.ACQUIRE, url } }, LEASE_TIMEOUT_MS);
55
- const sessionId = verdictOf(acquired, 'sessionId')?.['sessionId'];
56
- if ('string' === typeof sessionId)
57
- return { leased: sessionId };
72
+ export async function acquireLease(caller, url,
73
+ /** Open it in a window somebody can watch, whatever the daemon was started as. */
74
+ headed,
75
+ /** The `.reticle` the lease's runs belong in: the caller's project, not wherever the page resolves. */
76
+ root) {
77
+ const acquired = await caller.call(ReticleTool.RUN, {
78
+ tool: ReticleTool.LEASE,
79
+ args: {
80
+ action: LeaseAction.ACQUIRE,
81
+ url,
82
+ ...(true === headed ? { headed } : {}),
83
+ ...(root === undefined ? {} : { root }),
84
+ },
85
+ }, LEASE_TIMEOUT_MS);
86
+ const report = verdictOf(acquired, 'sessionId');
87
+ const sessionId = report?.['sessionId'];
88
+ // `zeroInstall`: the page never dialled in, so the lease supplied Reticle's own reader.
89
+ if ('string' === typeof sessionId) {
90
+ return { leased: sessionId, zeroInstall: true === report?.['zeroInstall'] };
91
+ }
58
92
  const why = verdictOf(acquired, 'error')?.['error'];
59
93
  return {
60
94
  failed: [
@@ -81,7 +115,7 @@ export function endpointFor(port, token) {
81
115
  return url;
82
116
  }
83
117
  export async function connectOverSse(endpoint) {
84
- const client = new Client({ name: 'reticle-cli', version: '1' }, { capabilities: {} });
118
+ const client = new Client({ name: CLI_CLIENT_NAME, version: '1' }, { capabilities: {} });
85
119
  await client.connect(new SSEClientTransport(endpoint));
86
120
  return {
87
121
  call: async (name, args, timeoutMs) => await client.callTool({ name, arguments: args }, undefined, timeoutMs === undefined ? undefined : { timeout: timeoutMs }),
@@ -190,8 +224,14 @@ export async function runAdhocVerdict(options) {
190
224
  // OTHER listening port as the one to open. The caller already said which url; open it here, in
191
225
  // a Reticle browser, and hand the lease back when the verdict is in.
192
226
  let alreadyAt = false;
227
+ // A named tab gets the same same-document rule: navigating to the url it already shows is a
228
+ // reload, which throws away client-only state (page 2, a half-filled form) and in a desktop
229
+ // window disconnects the session the assert is about to read (#1409).
230
+ if (url !== undefined && options.sessionId !== undefined && options.sessions !== undefined) {
231
+ alreadyAt = await pinnedTabIsAt(options.sessions, options.sessionId, url);
232
+ }
193
233
  if (url !== undefined && options.sessionId === undefined && options.sessions !== undefined) {
194
- const opened = await leaseIfNoTab(caller, url, options.sessions);
234
+ const opened = await leaseIfNoTab(caller, url, options.sessions, options.root);
195
235
  if ('failed' in opened)
196
236
  return { code: 1, lines: ['verified: unknown', ...opened.failed] };
197
237
  leased = opened.leased;
@@ -237,3 +277,30 @@ export async function runAdhocVerdict(options) {
237
277
  await caller.close().catch(() => undefined);
238
278
  }
239
279
  }
280
+ const EXPLORE_ACTION = 'explore';
281
+ const DRIVE_RUNNING = 'running';
282
+ /** The most one explore call waits on its drive (the tool's own ceiling), and the call's slack. */
283
+ const EXPLORE_WAIT_MAX_S = 240;
284
+ const CALL_SLACK_MS = 15_000;
285
+ const MS_PER_S = 1000;
286
+ /**
287
+ * One Harness drive through the daemon, polled to its end or until `budgetMs` runs out.
288
+ *
289
+ * An explore answers `{ status: "running", runId }` when its drive outlasts the call's wait, so a
290
+ * caller that wants the finished report asks again by `runId` rather than starting a second drive.
291
+ */
292
+ export async function exploreToEnd(caller, args, budgetMs, now = Date.now) {
293
+ const deadline = now() + budgetMs;
294
+ const ask = (more) => {
295
+ const wait = Math.max(0, Math.min(EXPLORE_WAIT_MAX_S, Math.floor((deadline - now() - CALL_SLACK_MS) / MS_PER_S)));
296
+ return caller.call(ReticleTool.VERIFY, { ...more, action: EXPLORE_ACTION, wait }, wait * MS_PER_S + CALL_SLACK_MS);
297
+ };
298
+ let result = await ask(args);
299
+ for (;;) {
300
+ const report = verdictOf(result, 'status');
301
+ const runId = report?.['runId'];
302
+ if (DRIVE_RUNNING !== report?.['status'] || 'string' !== typeof runId || now() >= deadline)
303
+ return result;
304
+ result = await ask({ runId });
305
+ }
306
+ }
@@ -18,4 +18,27 @@ export declare const GateExit: {
18
18
  readonly FAIL: 1;
19
19
  /** The gate ran and had nothing to judge — no flows recorded. Non-zero, but not a regression. */
20
20
  readonly NOTHING_TO_CHECK: 2;
21
+ /** The platform knows a flow that passed before and is broken now: `reticle runs regression`'s code. */
22
+ readonly REGRESSION: 3;
21
23
  };
24
+ /**
25
+ * The gate's code once the platform has been asked about regressions: a known one fails the build
26
+ * with `reticle runs regression`'s code, whatever the local answer was, so the gate is the one
27
+ * command CI needs. `undefined` (not linked, or the platform did not answer) changes nothing.
28
+ */
29
+ export declare function gateExitWith(local: number, regressed: number | undefined,
30
+ /** The platform the project is linked to refused its credential: the gate fails closed. */
31
+ refused?: boolean): number;
32
+ /**
33
+ * Said when the linked platform refused the key. A CI pipeline whose key was revoked stayed green
34
+ * and silent: the gate lost the platform's regression report and the only trace was a log line.
35
+ */
36
+ export declare function msgGateRefused(why: string): string;
37
+ /** Said when the gate had no saved flows to judge, so exit 2 does not read as the change failing. */
38
+ export declare const MSG_GATE_NO_FLOWS: string;
39
+ /**
40
+ * Said when the platform knows a regression, outside a hook. Exit 3 printed only the JSON log, whose
41
+ * coverage field still read "no flows recorded — nothing was checked", so nothing a person read
42
+ * said "regression".
43
+ */
44
+ export declare function msgGateRegression(broken: readonly unknown[]): string;
@@ -18,4 +18,49 @@ export const GateExit = {
18
18
  FAIL: 1,
19
19
  /** The gate ran and had nothing to judge — no flows recorded. Non-zero, but not a regression. */
20
20
  NOTHING_TO_CHECK: 2,
21
+ /** The platform knows a flow that passed before and is broken now: `reticle runs regression`'s code. */
22
+ REGRESSION: 3,
21
23
  };
24
+ /**
25
+ * The gate's code once the platform has been asked about regressions: a known one fails the build
26
+ * with `reticle runs regression`'s code, whatever the local answer was, so the gate is the one
27
+ * command CI needs. `undefined` (not linked, or the platform did not answer) changes nothing.
28
+ */
29
+ export function gateExitWith(local, regressed,
30
+ /** The platform the project is linked to refused its credential: the gate fails closed. */
31
+ refused = false) {
32
+ if (regressed !== undefined && 0 < regressed)
33
+ return GateExit.REGRESSION;
34
+ return refused && GateExit.PASS === local ? GateExit.FAIL : local;
35
+ }
36
+ /**
37
+ * Said when the linked platform refused the key. A CI pipeline whose key was revoked stayed green
38
+ * and silent: the gate lost the platform's regression report and the only trace was a log line.
39
+ */
40
+ export function msgGateRefused(why) {
41
+ return (`Reticle gate: ${why.replace(/\.+$/, '')}. The gate could not ask the platform this project is linked to for its ` +
42
+ 'regression report, so it fails closed rather than pass without it.');
43
+ }
44
+ /** Said when the gate had no saved flows to judge, so exit 2 does not read as the change failing. */
45
+ export const MSG_GATE_NO_FLOWS = 'Reticle gate: no saved flows here, so there was nothing to check; this is not a failure of this ' +
46
+ 'change. Record one by driving the app with reticle_act_and_wait, or run ' +
47
+ '`reticle verify <url> --explore`, then run the gate again.';
48
+ /**
49
+ * Said when the platform knows a regression, outside a hook. Exit 3 printed only the JSON log, whose
50
+ * coverage field still read "no flows recorded — nothing was checked", so nothing a person read
51
+ * said "regression".
52
+ */
53
+ export function msgGateRegression(broken) {
54
+ const names = broken.map((entry) => {
55
+ if ('string' === typeof entry)
56
+ return entry;
57
+ const record = 'object' === typeof entry && null !== entry ? entry : {};
58
+ const name = record['flowName'] ?? record['name'];
59
+ const was = record['previousStatus'];
60
+ const now = record['currentStatus'];
61
+ const flow = 'string' === typeof name ? name : 'a flow';
62
+ return 'string' === typeof was && 'string' === typeof now ? `${flow} (${was} → ${now})` : flow;
63
+ });
64
+ return (`Reticle gate: regression — ${names.join(', ')} passed before and fails now on the platform. ` +
65
+ 'See `reticle runs regression`.');
66
+ }
@@ -27,6 +27,8 @@ interface GateHookInput {
27
27
  coverageRegressed?: readonly string[];
28
28
  /** Changed files the browser loaded and never ran a function of. */
29
29
  unexecuted?: readonly string[];
30
+ /** Flows the platform says passed before and are broken now. */
31
+ regressed?: number;
30
32
  }
31
33
  /**
32
34
  * The message, or undefined when there is nothing to say.
@@ -28,9 +28,11 @@ function name(list) {
28
28
  * interrupted.
29
29
  */
30
30
  export function gateHookMessage(exit, input) {
31
- if (GateExit.FAIL !== exit)
31
+ if (GateExit.FAIL !== exit && GateExit.REGRESSION !== exit)
32
32
  return undefined;
33
33
  const lines = ['Reticle: this change is not verified.'];
34
+ if (input.regressed !== undefined && 0 < input.regressed)
35
+ lines.push(` ${String(input.regressed)} flow(s) that passed before are broken now — \`reticle runs regression\` names them`);
34
36
  if (input.uncovered.length > 0)
35
37
  lines.push(` no passing run covers: ${name(input.uncovered)}`);
36
38
  if (input.downgraded.length > 0)
@@ -18,3 +18,5 @@
18
18
  * So the substitution is stated FIRST, with both numbers, before any cause that assumes they match.
19
19
  */
20
20
  export declare function openFailureNote(port: number, requestedPort: number): string;
21
+ /** Recovery when the OS could not open a URL: agents can use Reticle's browser lease instead. */
22
+ export declare function openLaunchFailureNote(url: string, launcher: string): string;
@@ -1,3 +1,18 @@
1
+ import { ReticleTool } from '@reticlehq/core';
2
+ const LeaseAction = { ACQUIRE: 'acquire' };
3
+ const LeaseArgument = {
4
+ TOOL: 'tool',
5
+ ARGS: 'args',
6
+ ACTION: 'action',
7
+ URL: 'url',
8
+ };
9
+ const OpenLaunchFailureCopy = {
10
+ NOTHING_OPENED: 'Nothing was opened.',
11
+ OS_BROWSER: 'This command asks the OS to open a url in your default browser',
12
+ LAUNCH_FAILED: (launcher) => `(\`${launcher}\` on this platform) and that failed,`,
13
+ OPEN_MANUALLY: 'so open the url yourself or set a default browser.',
14
+ RETICLE_BROWSER: 'If you are using Reticle tools, open it in a Reticle-owned browser with',
15
+ };
1
16
  /**
2
17
  * What `reticle open` says when it launched a URL and no session appeared.
3
18
  *
@@ -35,3 +50,10 @@ export function openFailureNote(port, requestedPort) {
35
50
  `non-localhost host, which needs BOTH allowNonLocalhost: true AND a pairing token ` +
36
51
  `(~/.reticle/pairing-token) — the flag alone is not sufficient.`);
37
52
  }
53
+ /** Recovery when the OS could not open a URL: agents can use Reticle's browser lease instead. */
54
+ export function openLaunchFailureNote(url, launcher) {
55
+ return (`${OpenLaunchFailureCopy.NOTHING_OPENED} ${OpenLaunchFailureCopy.OS_BROWSER} ` +
56
+ `${OpenLaunchFailureCopy.LAUNCH_FAILED(launcher)} ${OpenLaunchFailureCopy.OPEN_MANUALLY} ` +
57
+ `${OpenLaunchFailureCopy.RETICLE_BROWSER} ` +
58
+ `\`${ReticleTool.RUN} { ${LeaseArgument.TOOL}: "${ReticleTool.LEASE}", ${LeaseArgument.ARGS}: { ${LeaseArgument.ACTION}: "${LeaseAction.ACQUIRE}", ${LeaseArgument.URL}: ${JSON.stringify(url)} } }\`.`);
59
+ }
@@ -19,19 +19,19 @@ export declare const DeviceStartSchema: z.ZodObject<{
19
19
  interval: z.ZodNumber;
20
20
  expiresAt: z.ZodNumber;
21
21
  }, "strip", z.ZodTypeAny, {
22
- expiresAt: number;
23
22
  deviceCode: string;
24
23
  userCode: string;
25
24
  verificationUri: string;
26
25
  verificationUriComplete: string;
27
26
  interval: number;
28
- }, {
29
27
  expiresAt: number;
28
+ }, {
30
29
  deviceCode: string;
31
30
  userCode: string;
32
31
  verificationUri: string;
33
32
  verificationUriComplete: string;
34
33
  interval: number;
34
+ expiresAt: number;
35
35
  }>;
36
36
  /**
37
37
  * What `/v1/auth/device/token` answers while polling. Everything past `status` is optional because
@@ -66,6 +66,17 @@ export declare const DevicePollSchema: z.ZodObject<{
66
66
  id?: string | undefined;
67
67
  } | undefined;
68
68
  }>;
69
+ /**
70
+ * Where a sign-in started, carried to the approval page as `from` so the platform can attribute the
71
+ * signup. The platform's `/device` reads the same closed set (plus `app`, its own).
72
+ */
73
+ export declare const LoginOrigin: {
74
+ readonly TERMINAL: "terminal";
75
+ readonly HUD: "hud";
76
+ };
77
+ export type LoginOrigin = (typeof LoginOrigin)[keyof typeof LoginOrigin];
78
+ /** The approval URL with `from` set; a URL that does not parse is left as the cloud sent it. */
79
+ export declare function withLoginOrigin(url: string, from: LoginOrigin): string;
69
80
  /**
70
81
  * Best-effort open the approval page in the default browser.
71
82
  *
@@ -31,6 +31,23 @@ export const DevicePollSchema = z.object({
31
31
  token: z.string().optional(),
32
32
  org: z.object({ id: z.string().optional(), name: z.string() }).optional(),
33
33
  });
34
+ /**
35
+ * Where a sign-in started, carried to the approval page as `from` so the platform can attribute the
36
+ * signup. The platform's `/device` reads the same closed set (plus `app`, its own).
37
+ */
38
+ export const LoginOrigin = { TERMINAL: 'terminal', HUD: 'hud' };
39
+ const FROM_PARAM = 'from';
40
+ /** The approval URL with `from` set; a URL that does not parse is left as the cloud sent it. */
41
+ export function withLoginOrigin(url, from) {
42
+ try {
43
+ const parsed = new URL(url);
44
+ parsed.searchParams.set(FROM_PARAM, from);
45
+ return parsed.toString();
46
+ }
47
+ catch {
48
+ return url;
49
+ }
50
+ }
34
51
  /**
35
52
  * Best-effort open the approval page in the default browser.
36
53
  *
@@ -1,4 +1,5 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
+ import { keychainNoteFor } from './doctor/doctor-signing-line.js';
2
3
  import { join } from 'node:path';
3
4
  import { devServersForProject, ReticleEnv } from '@reticlehq/core';
4
5
  import { readPid, reticleStateHome } from '../daemon/daemon.js';
@@ -18,6 +19,11 @@ import { CONTRACT_FINGERPRINT } from '@reticlehq/core';
18
19
  import { CspBasis, diagnoseDesktop, diagnoseObservedWebCsp, diagnoseWebCsp, isDesktopProject, resolveWebCspFindings, webCspOptionsFor, } from '@reticlehq/init';
19
20
  import { RETICLE_CONFIG_BASENAME, diagnosePortMismatch, readProjectFramework, readProjectId, readProjectPort, } from './ports/resolve/cli-port.js';
20
21
  import { DoctorRow, doctorRow } from './doctor/doctor-rows.js';
22
+ import { coverageLines } from './doctor/doctor-coverage-line.js';
23
+ import { homedir } from 'node:os';
24
+ import { createNodeFileSystem } from '../../memory/project/fs/fs-port.js';
25
+ import { describeUnsynced } from '../../memory/cloud/unsynced-roots.js';
26
+ import { machineUnsyncedRoots } from '../../memory/project/sync-status.js';
21
27
  import { attachState, describeAttachState } from '../../surface/mcp/attach-memory.js';
22
28
  import { findOccupiedSiblings, siblingListenerNote } from './ports/sibling-ports.js';
23
29
  import { daemonsServingProjectElsewhere, resolveDaemonForProject, splitBrainNote, wrongDaemonNote, } from '../daemon/daemon-resolve.js';
@@ -118,6 +124,11 @@ export async function handleDoctor(port) {
118
124
  }
119
125
  if (sessions !== undefined)
120
126
  line(sessions.text);
127
+ for (const row of coverageLines(daemonStatus))
128
+ line(row);
129
+ // Runs nothing will send, named by folder with the one command that sends them.
130
+ for (const entry of await machineUnsyncedRoots(createNodeFileSystem(), homedir(), process.env))
131
+ line(doctorRow(DoctorRow.UNSYNCED, `✗ ${describeUnsynced(entry, process.cwd())}`));
121
132
  line(doctorRow(DoctorRow.BRIDGE_PORT, `${port} (your app must dial THIS port, not your dev-server port)`));
122
133
  const projectPort = readProjectPort(process.cwd());
123
134
  const mismatch = diagnosePortMismatch(port, projectPort);
@@ -234,4 +245,7 @@ export async function handleDoctor(port) {
234
245
  // findings above exist to remove.
235
246
  line(doctorRow(DoctorRow.DESKTOP, '✓ desktop wiring looks right'));
236
247
  }
248
+ const keychain = keychainNoteFor({ read: readProjectFile });
249
+ if (keychain !== undefined)
250
+ line(doctorRow(DoctorRow.DESKTOP, `⚠ ${keychain}`));
237
251
  }
@@ -26,17 +26,6 @@ export declare function resolveChangedFiles(files: string[], since: string | und
26
26
  * confident negative about somebody else's project, which is worse than an error.
27
27
  */
28
28
  export declare function loadNamedFlows(fs: FileSystemPort, reticleRoot: string, projectId: ProjectId | undefined): Promise<NamedFlow[]>;
29
- /**
30
- * `reticle watch [url]` — on every save, report which saved flows must re-verify (the affected set).
31
- * Environment-side (costs the agent nothing per turn); the buddy loop. This v1 detects + reports on
32
- * change; auto-replaying the affected flows against the app is the next increment. Long-running.
33
- */
34
- export declare function handleWatch(): void;
35
- /**
36
- * `reticle capsules` — list saved fail-to-pass bug capsules (.reticle/capsules). Each is a minimal
37
- * failing reproduction plus the consequence that should have held; replay one with reticle_flow_replay.
38
- */
39
- export declare function handleCapsules(): Promise<void>;
40
29
  export declare function handleGate(files: string[], since: string | undefined,
41
30
  /** Hook mode: prose for a human, and silence when there was simply nothing to check. */
42
31
  hook?: boolean,
@@ -5,27 +5,25 @@
5
5
  * opens first. These five functions form one cohesive group: they all read the flow store and report on
6
6
  * verification state, and none of them touch daemon lifecycle, which is what the rest of cli.ts does.
7
7
  */
8
- import { GateExit } from './answers/gate-exit.js';
8
+ import { GateExit, MSG_GATE_NO_FLOWS, msgGateRegression, msgGateRefused, gateExitWith, } from './answers/gate-exit.js';
9
+ import { knownRegression } from './known-regression.js';
9
10
  import { gateHookMessage, GATE_SKIP_ENV } from './answers/gate-hook-message.js';
10
11
  import { readProjectId } from './ports/resolve/cli-port.js';
11
12
  import { changedFilesSince } from '../../language/flows/change/git-changed.js';
12
13
  import { join } from 'node:path';
13
- import { ReticleDir, RunFlowStatus } from '@reticlehq/core';
14
+ import { ReticleDir } from '@reticlehq/core';
14
15
  import { FlowStore } from '../../language/flows/flows.js';
15
16
  import { RunStore } from '../../judgement/runs/artifact/run-store.js';
16
17
  import { createNodeFileSystem } from '../../memory/project/fs/fs-port.js';
17
18
  import { affectedSavedFlows, toFlowSources, } from '../../language/flows/change/flow-sources.js';
18
19
  import { isInteractiveSource, unflowedFiles } from '../../language/flows/change/affected.js';
19
20
  import { LedgerStore, regressions, staleChanged, unexecutedChanged, } from '../../features/exhaust/ledger.js';
20
- import { gateDecision } from '../../language/flows/change/gate.js';
21
+ import { gateDecision, passingFlowNames } from '../../language/flows/change/gate.js';
21
22
  import { FlakeStore } from '../../language/flows/stores/flake-store.js';
22
- import { formatBuddyStatus } from '../../language/flows/buddy-status.js';
23
- import { CapsuleStore } from '../../judgement/capsule/capsule-store.js';
24
23
  import { AssertionTiersStore } from '../../language/flows/stores/assertion-tiers-store.js';
25
24
  import { detectDowngrades } from '../../judgement/outcome/assertion-integrity.js';
26
25
  import { computeCoverage, flowCoverageReport } from '../../language/flows/suite/coverage.js';
27
- import { createWatchBatcher } from '../../language/flows/change/watch-batcher.js';
28
- import { readFileSync, statSync, watch } from 'node:fs';
26
+ import { readFileSync, statSync } from 'node:fs';
29
27
  import { log } from '../../log.js';
30
28
  /** Load the {name, steps} of every saved flow for the active project. */
31
29
  /** Explicit files plus, when --since is given, the git-changed files since that ref. */
@@ -63,103 +61,6 @@ export async function loadNamedFlows(fs, reticleRoot, projectId) {
63
61
  }
64
62
  return flows;
65
63
  }
66
- /** File-change extensions worth reacting to (skip node_modules churn, dotfiles, build output). */
67
- /**
68
- * The buddy channel: one ambient line a human can park in a statusline. Deliberately best-effort
69
- * and silent on failure — a status line that throws is worse than no status line, and it must never
70
- * interfere with the watch loop it rides on.
71
- */
72
- async function emitBuddyStatus(fs, reticleRoot, flows, affected) {
73
- try {
74
- const latest = await new RunStore(fs, reticleRoot).latest();
75
- const passingNames = new Set((latest?.flows ?? [])
76
- .filter((f) => f.status === RunFlowStatus.PASS || f.status === RunFlowStatus.HEALED)
77
- .map((f) => f.name));
78
- const quarantined = await new FlakeStore(fs, reticleRoot).flakyFlows();
79
- const flaky = new Set(quarantined);
80
- // A deviation is an at-risk flow with no passing artifact — and a quarantined flake is not a deviation.
81
- const deviations = affected.filter((n) => !passingNames.has(n) && !flaky.has(n));
82
- log('reticle_buddy', {
83
- status: formatBuddyStatus({
84
- total: flows.length,
85
- passing: passingNames.size,
86
- deviations,
87
- quarantined,
88
- }),
89
- });
90
- }
91
- catch {
92
- // never let the ambient line break the watcher
93
- }
94
- }
95
- const WATCHED_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
96
- const WATCH_DEBOUNCE_MS = 200;
97
- /**
98
- * `reticle watch [url]` — on every save, report which saved flows must re-verify (the affected set).
99
- * Environment-side (costs the agent nothing per turn); the buddy loop. This v1 detects + reports on
100
- * change; auto-replaying the affected flows against the app is the next increment. Long-running.
101
- */
102
- export function handleWatch() {
103
- const fs = createNodeFileSystem();
104
- const reticleRoot = join(process.cwd(), ReticleDir.ROOT);
105
- const batcher = createWatchBatcher({
106
- debounceMs: WATCH_DEBOUNCE_MS,
107
- schedule: (fn, ms) => {
108
- setTimeout(fn, ms).unref();
109
- },
110
- onFlush: (files) => {
111
- void loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()))
112
- .then(async (flows) => {
113
- const result = affectedSavedFlows(flows, files);
114
- if (result.affected.length > 0) {
115
- log('reticle_watch_affected', { changed: files, affected: result.affected });
116
- }
117
- await emitBuddyStatus(fs, reticleRoot, flows, result.affected);
118
- })
119
- .catch((error) => {
120
- log('reticle_watch_failed', {
121
- error: error instanceof Error ? error.message : String(error),
122
- });
123
- });
124
- },
125
- });
126
- log('reticle_watch_started', { cwd: process.cwd() });
127
- // Print the ambient line once at startup so the human sees where they stand before touching anything.
128
- void loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()))
129
- .then((flows) => emitBuddyStatus(fs, reticleRoot, flows, []))
130
- .catch(() => undefined);
131
- watch(process.cwd(), { recursive: true }, (_event, filename) => {
132
- if ('string' === typeof filename && WATCHED_EXTENSIONS.test(filename))
133
- batcher.onChange(filename);
134
- });
135
- }
136
- /**
137
- * `reticle capsules` — list saved fail-to-pass bug capsules (.reticle/capsules). Each is a minimal
138
- * failing reproduction plus the consequence that should have held; replay one with reticle_flow_replay.
139
- */
140
- export async function handleCapsules() {
141
- try {
142
- const fs = createNodeFileSystem();
143
- const capsules = await new CapsuleStore(fs, join(process.cwd(), ReticleDir.ROOT)).all();
144
- log('reticle_capsules', {
145
- count: capsules.length,
146
- capsules: capsules.map((c) => ({
147
- id: c.id,
148
- ...(c.flow === undefined ? {} : { flow: c.flow }),
149
- origin: c.origin,
150
- expected: c.expected,
151
- observed: c.observed,
152
- steps: c.steps.length,
153
- })),
154
- });
155
- }
156
- catch (error) {
157
- log('reticle_capsules_failed', {
158
- error: error instanceof Error ? error.message : String(error),
159
- });
160
- process.exitCode = 1;
161
- }
162
- }
163
64
  /**
164
65
  * `reticle gate <file...>` — exit non-zero unless passing artifacts cover the flows affected by the
165
66
  * changed files. Flaky flows are quarantined (surfaced, not blocking). The environment-side enforcement
@@ -202,9 +103,7 @@ acceptCoverage = false) {
202
103
  const allFlows = await loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()));
203
104
  const affected = affectedSavedFlows(allFlows, changed).affected;
204
105
  const latest = await new RunStore(fs, reticleRoot).latest();
205
- const passing = (latest?.flows ?? [])
206
- .filter((f) => f.status === RunFlowStatus.PASS || f.status === RunFlowStatus.HEALED)
207
- .map((f) => f.name);
106
+ const passing = passingFlowNames(latest?.flows ?? []);
208
107
  const flaky = await new FlakeStore(fs, reticleRoot).flakyFlows();
209
108
  // Anti-reward-hacking: diff each flow's CURRENT assertions against what it asserted the last
210
109
  // time it passed. A mustHold that dropped from a real consequence to a fakeable presence check is a
@@ -264,8 +163,19 @@ acceptCoverage = false) {
264
163
  // verdict already applies to `reticle verify`; see flowCoverageReport.
265
164
  const flowCoverage = flowCoverageReport(coverage.flows);
266
165
  const pass = result.pass && flowCoverage.outcome === undefined;
166
+ // What the platform knows decides too (a regression, a refused key), so the line is written
167
+ // once the exit code is: it said "pass": true over an exit of 1 or 3.
168
+ const known = await knownRegression(reticleRoot);
169
+ const regressed = known.broken;
170
+ const local = pass
171
+ ? GateExit.PASS
172
+ : result.pass && flowCoverage.outcome !== undefined
173
+ ? GateExit.NOTHING_TO_CHECK
174
+ : GateExit.FAIL;
175
+ // Fails closed in CI, not in an agent's stop hook, where it would block over a key, not a change.
176
+ const code = gateExitWith(local, regressed?.length, !hook && known.refused !== undefined);
267
177
  log('reticle_gate', {
268
- pass,
178
+ pass: GateExit.PASS === code,
269
179
  uncovered: result.uncovered,
270
180
  quarantined: result.quarantined,
271
181
  ...(result.downgraded.length > 0 ? { downgraded: result.downgraded } : {}),
@@ -283,10 +193,18 @@ acceptCoverage = false) {
283
193
  // problem to fail. A Stop hook wants to block a real regression and NOT block a project that
284
194
  // has simply not recorded a flow yet — which is every project on its first day, and measured
285
195
  // before this change as an exit 1 that would have blocked every stop. See GateExit.
286
- if (!pass) {
287
- const code = result.pass && flowCoverage.outcome !== undefined
288
- ? GateExit.NOTHING_TO_CHECK
289
- : GateExit.FAIL;
196
+ // A regression the platform already knows fails the build here too, with `reticle runs
197
+ // regression`'s code, so the gate is the one command CI needs. Best-effort: unlinked or offline
198
+ // changes nothing.
199
+ if (regressed !== undefined && 0 < regressed.length)
200
+ log('reticle_gate_regression', { broken: regressed });
201
+ if (known.refused !== undefined)
202
+ process.stderr.write(`${msgGateRefused(known.refused)}\n`);
203
+ if (GateExit.NOTHING_TO_CHECK === code && !hook)
204
+ process.stderr.write(`${MSG_GATE_NO_FLOWS}\n`);
205
+ if (GateExit.REGRESSION === code && !hook && regressed !== undefined)
206
+ process.stderr.write(`${msgGateRegression(regressed)}\n`);
207
+ if (GateExit.PASS !== code) {
290
208
  process.exitCode = code;
291
209
  if (hook) {
292
210
  // An honest escape hatch, because the alternative to one is not compliance — it is somebody
@@ -305,6 +223,7 @@ acceptCoverage = false) {
305
223
  unflowed: result.unflowed,
306
224
  coverageRegressed: result.coverageRegressed.map((r) => `${r.level} ${String(r.was)}% -> ${String(r.now)}%`),
307
225
  unexecuted: result.unexecuted,
226
+ regressed: regressed?.length ?? 0,
308
227
  });
309
228
  if (message !== undefined)
310
229
  process.stderr.write(`${message}\n`);
@@ -64,8 +64,9 @@ export function planKill(input) {
64
64
  holder: listener,
65
65
  reason: `pid ${String(listener.pid)} ("${listener.command}") is listening, and it is not a Reticle ` +
66
66
  `daemon — it never answered /status and it is not the pid Reticle recorded. Killing it would ` +
67
- `be killing someone else's process. Run it again with ${FORCE_FLAG} if that is what you ` +
68
- `meant, or start Reticle on another port.`,
67
+ `be killing someone else's process. If that is what you meant, \`reticle restart ${FORCE_FLAG}\` ` +
68
+ `stops it and starts Reticle there (\`stop ${FORCE_FLAG}\` never does); or start Reticle on ` +
69
+ `another port.`,
69
70
  };
70
71
  }
71
72
  /** How long the target gets to exit on SIGTERM before we stop asking politely. */
@@ -34,3 +34,27 @@ export declare const VERIFY_COMMAND = "verify";
34
34
  * missed for a release.
35
35
  */
36
36
  export declare const EXPECT_FLAG = "--expect";
37
+ /**
38
+ * The account and cloud commands. They are dispatched before the typed parser, and listed here so
39
+ * that the dispatcher and the telemetry vocabulary read one list instead of two.
40
+ */
41
+ export declare const CLOUD_COMMANDS: readonly string[];
42
+ /**
43
+ * Old command names that still run, for one release, under the name that replaced them. Each one
44
+ * prints a single line saying so, then does what it always did.
45
+ */
46
+ export declare const RENAMED_COMMANDS: ReadonlyMap<string, string>;
47
+ /**
48
+ * The command an old name now goes by, when the note saying so should print; otherwise undefined.
49
+ * Not for a request for help (that answer names the new command itself), and not for
50
+ * `login --email`, which `connect --help` documents as the sign-in for CI and agents.
51
+ */
52
+ export declare function renamedCommandFor(argv: readonly string[]): string | undefined;
53
+ /**
54
+ * Commands that were removed, and what to use instead. They stay in the telemetry vocabulary, so
55
+ * the people still typing one show up as that name rather than as `unknown`.
56
+ */
57
+ export declare const REMOVED_COMMANDS: ReadonlyMap<string, string>;
58
+ export declare const removedNote: (command: string, instead: string) => string;
59
+ /** One line on stderr when an old name ran: dim on a terminal, plain anywhere else. */
60
+ export declare const renamedNote: (command: string, now: string, colour: boolean) => string;