@reticlehq/server 3.6.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 (614) hide show
  1. package/SKILL.md +122 -123
  2. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  3. package/dist/command/cli/adhoc-suite.js +42 -7
  4. package/dist/command/cli/adhoc-verdict.d.ts +18 -2
  5. package/dist/command/cli/adhoc-verdict.js +70 -6
  6. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  7. package/dist/command/cli/answers/gate-exit.js +45 -0
  8. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  9. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  10. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  11. package/dist/command/cli/auth/device-flow.js +17 -0
  12. package/dist/command/cli/cli-doctor.js +14 -0
  13. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  14. package/dist/command/cli/cli-flow-commands.js +28 -105
  15. package/dist/command/cli/cli-kill.js +3 -2
  16. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  17. package/dist/command/cli/cli-parse-grammar.js +75 -0
  18. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  19. package/dist/command/cli/cli-parse-verify.js +18 -0
  20. package/dist/command/cli/cli-parse.d.ts +19 -28
  21. package/dist/command/cli/cli-parse.js +82 -182
  22. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  23. package/dist/command/cli/cli-update-commands.js +61 -9
  24. package/dist/command/cli/cli-usage.d.ts +33 -0
  25. package/dist/command/cli/cli-usage.js +287 -0
  26. package/dist/command/cli/cli-verify.d.ts +34 -4
  27. package/dist/command/cli/cli-verify.js +81 -12
  28. package/dist/command/cli/cloud-cli.d.ts +13 -0
  29. package/dist/command/cli/cloud-cli.js +145 -333
  30. package/dist/command/cli/cloud-kit.d.ts +12 -0
  31. package/dist/command/cli/cloud-kit.js +41 -2
  32. package/dist/command/cli/cloud-link.d.ts +57 -0
  33. package/dist/command/cli/cloud-link.js +308 -0
  34. package/dist/command/cli/cloud-login.d.ts +15 -1
  35. package/dist/command/cli/cloud-login.js +67 -13
  36. package/dist/command/cli/context-command.d.ts +1 -0
  37. package/dist/command/cli/context-command.js +33 -0
  38. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  39. package/dist/command/cli/daemon-start-options.js +24 -3
  40. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  41. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  42. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  43. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  44. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  45. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  46. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  47. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  48. package/dist/command/cli/known-regression.d.ts +13 -0
  49. package/dist/command/cli/known-regression.js +34 -0
  50. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  51. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  52. package/dist/command/cli/lifecycle/daemon-lifecycle.js +11 -2
  53. package/dist/command/cli/mcp-command.d.ts +6 -0
  54. package/dist/command/cli/mcp-command.js +13 -5
  55. package/dist/command/cli/ports/port-holder.js +1 -1
  56. package/dist/command/cli/project-name.d.ts +29 -1
  57. package/dist/command/cli/project-name.js +107 -2
  58. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  59. package/dist/command/cli/setup-mcp-cli.js +29 -8
  60. package/dist/command/cli/status/status-lines.d.ts +1 -0
  61. package/dist/command/cli/status/status-lines.js +47 -2
  62. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  63. package/dist/command/cli/status/workspace-links.js +29 -0
  64. package/dist/command/cli/try-command.d.ts +96 -0
  65. package/dist/command/cli/try-command.js +362 -0
  66. package/dist/command/cli/tutorial.d.ts +0 -100
  67. package/dist/command/cli/tutorial.js +0 -178
  68. package/dist/command/cli/verify-results.d.ts +19 -0
  69. package/dist/command/cli/verify-results.js +29 -0
  70. package/dist/command/cli-onboarding.d.ts +0 -11
  71. package/dist/command/cli-onboarding.js +0 -15
  72. package/dist/command/cli.d.ts +14 -0
  73. package/dist/command/cli.js +103 -83
  74. package/dist/command/daemon/daemon-resilience.js +4 -4
  75. package/dist/command/daemon/daemon-resolve.d.ts +9 -1
  76. package/dist/command/daemon/daemon-resolve.js +49 -10
  77. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  78. package/dist/command/setup/bringup/bridge-port.js +13 -3
  79. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  80. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  81. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  82. package/dist/command/setup/init/agent-restart.js +28 -0
  83. package/dist/command/setup/init/init-port.d.ts +10 -1
  84. package/dist/command/setup/init/init-port.js +22 -2
  85. package/dist/command/setup/init/init-runtime.d.ts +12 -2
  86. package/dist/command/setup/init/init-runtime.js +96 -37
  87. package/dist/command/setup/node-effects.d.ts +2 -0
  88. package/dist/command/setup/node-effects.js +36 -8
  89. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  90. package/dist/command/setup/probe/existing-app.js +14 -0
  91. package/dist/command/setup/remaining-steps.js +1 -1
  92. package/dist/command/setup/run-setup.d.ts +29 -9
  93. package/dist/command/setup/run-setup.js +34 -28
  94. package/dist/command/setup/setup-command.d.ts +23 -0
  95. package/dist/command/setup/setup-command.js +57 -4
  96. package/dist/command/setup/setup-mcp.js +25 -2
  97. package/dist/command/setup/tauri-signing.d.ts +19 -0
  98. package/dist/command/setup/tauri-signing.js +79 -0
  99. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  100. package/dist/command/setup/terminal/listeners.js +37 -6
  101. package/dist/command/update/update-nudge.d.ts +9 -0
  102. package/dist/command/update/update-nudge.js +1 -1
  103. package/dist/command/update/updater.js +11 -15
  104. package/dist/command/version/version-nudge.js +3 -0
  105. package/dist/command/version/version-skew.d.ts +20 -1
  106. package/dist/command/version/version-skew.js +38 -2
  107. package/dist/features/crawl/crawl.js +14 -1
  108. package/dist/features/exhaust/ledger.d.ts +14 -14
  109. package/dist/features/harness/drive-report.d.ts +39 -5
  110. package/dist/features/harness/drive-report.js +271 -54
  111. package/dist/features/harness/drive-runs.d.ts +120 -0
  112. package/dist/features/harness/drive-runs.js +289 -0
  113. package/dist/features/harness/drivers.d.ts +1 -1
  114. package/dist/features/harness/drivers.js +1 -1
  115. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  116. package/dist/features/harness/explore/console-pages.js +146 -0
  117. package/dist/features/harness/explore/disparity.d.ts +19 -0
  118. package/dist/features/harness/explore/disparity.js +71 -0
  119. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  120. package/dist/features/harness/explore/fake-app.js +49 -0
  121. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  122. package/dist/features/harness/explore/goal-search.js +144 -0
  123. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  124. package/dist/features/harness/explore/page-tree.js +148 -0
  125. package/dist/features/harness/explore/site-map.d.ts +34 -0
  126. package/dist/features/harness/explore/site-map.js +150 -0
  127. package/dist/features/harness/goals.d.ts +68 -7
  128. package/dist/features/harness/goals.js +289 -36
  129. package/dist/features/harness/harness.d.ts +30 -1
  130. package/dist/features/harness/harness.js +141 -7
  131. package/dist/features/harness/platform/local-apps.d.ts +36 -3
  132. package/dist/features/harness/platform/local-apps.js +81 -5
  133. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  134. package/dist/features/harness/platform/persona-credentials.js +69 -0
  135. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  136. package/dist/features/harness/platform/platform-drives.js +114 -0
  137. package/dist/features/harness/platform/refusal.d.ts +52 -0
  138. package/dist/features/harness/platform/refusal.js +71 -0
  139. package/dist/features/harness/platform/remote-drive.d.ts +8 -2
  140. package/dist/features/harness/platform/remote-drive.js +22 -9
  141. package/dist/features/harness/platform/script.d.ts +57 -11
  142. package/dist/features/harness/platform/script.js +144 -12
  143. package/dist/features/harness/platform/server-driver.d.ts +17 -4
  144. package/dist/features/harness/platform/server-driver.js +29 -26
  145. package/dist/features/harness/platform-config.d.ts +38 -5
  146. package/dist/features/harness/platform-config.js +93 -8
  147. package/dist/features/harness/route-guess.d.ts +13 -0
  148. package/dist/features/harness/route-guess.js +49 -0
  149. package/dist/features/harness/script/script-run.d.ts +30 -1
  150. package/dist/features/harness/script/script-run.js +355 -48
  151. package/dist/features/license/license.d.ts +2 -2
  152. package/dist/features/visual/step-shots.d.ts +31 -0
  153. package/dist/features/visual/step-shots.js +231 -0
  154. package/dist/features/visual/visual-tools.js +22 -14
  155. package/dist/hooks/client-directory.d.ts +18 -0
  156. package/dist/hooks/client-directory.js +57 -0
  157. package/dist/hooks/coding-agents.d.ts +34 -0
  158. package/dist/hooks/coding-agents.js +117 -0
  159. package/dist/hooks/driven-by.d.ts +21 -2
  160. package/dist/hooks/driven-by.js +42 -2
  161. package/dist/hooks/hook-bus.d.ts +4 -0
  162. package/dist/hooks/hook-bus.js +18 -0
  163. package/dist/index.d.ts +1 -0
  164. package/dist/index.js +26 -183
  165. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  166. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  167. package/dist/judgement/capsule/causal-summary.js +33 -0
  168. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  169. package/dist/judgement/runs/artifact/build-verification-run.js +20 -4
  170. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  171. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  172. package/dist/judgement/runs/artifact/replay-mapping.js +25 -9
  173. package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
  174. package/dist/judgement/runs/artifact/run-store.js +175 -8
  175. package/dist/judgement/runs/context-tools.js +59 -1
  176. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  177. package/dist/judgement/runs/default-run-id.js +16 -0
  178. package/dist/judgement/runs/drive-run.d.ts +53 -5
  179. package/dist/judgement/runs/drive-run.js +234 -20
  180. package/dist/judgement/runs/resume.d.ts +44 -0
  181. package/dist/judgement/runs/resume.js +137 -0
  182. package/dist/judgement/runs/reticle-runner.js +5 -2
  183. package/dist/judgement/runs/runner-port.d.ts +5 -1
  184. package/dist/judgement/runs/runner-port.js +8 -2
  185. package/dist/judgement/runs/verification-sync.d.ts +2 -0
  186. package/dist/judgement/runs/verification-sync.js +36 -15
  187. package/dist/language/flows/decision.js +2 -1
  188. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  189. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  190. package/dist/language/flows/flow-anchor.d.ts +7 -2
  191. package/dist/language/flows/flow-anchor.js +10 -3
  192. package/dist/language/flows/flow-intent.d.ts +1 -0
  193. package/dist/language/flows/flow-journey.d.ts +6 -0
  194. package/dist/language/flows/flow-journey.js +20 -0
  195. package/dist/language/flows/flow-learning.d.ts +4 -0
  196. package/dist/language/flows/flow-learning.js +37 -3
  197. package/dist/language/flows/flow-replay-run.js +16 -18
  198. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  199. package/dist/language/flows/flow-replay.d.ts +18 -1
  200. package/dist/language/flows/flow-replay.js +22 -7
  201. package/dist/language/flows/flow-result.d.ts +22 -1
  202. package/dist/language/flows/flow-result.js +47 -2
  203. package/dist/language/flows/flow-step-runners.d.ts +2 -0
  204. package/dist/language/flows/flow-step-runners.js +12 -6
  205. package/dist/language/flows/flow-store-for-session.js +5 -1
  206. package/dist/language/flows/flow-tools.d.ts +10 -0
  207. package/dist/language/flows/flow-tools.js +61 -62
  208. package/dist/language/flows/flows.d.ts +16 -1
  209. package/dist/language/flows/flows.js +69 -10
  210. package/dist/language/flows/narrow-write.d.ts +7 -0
  211. package/dist/language/flows/narrow-write.js +36 -1
  212. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  213. package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
  214. package/dist/language/flows/recording/tape/recordings.js +60 -10
  215. package/dist/language/flows/replay.js +29 -6
  216. package/dist/language/flows/single-replay.d.ts +7 -0
  217. package/dist/language/flows/single-replay.js +26 -0
  218. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  219. package/dist/language/flows/verify-change-tools.js +200 -193
  220. package/dist/memory/cloud/cloud-config.d.ts +10 -1
  221. package/dist/memory/cloud/cloud-config.js +19 -5
  222. package/dist/memory/cloud/cloud-sync.js +3 -3
  223. package/dist/memory/cloud/harness-config.d.ts +49 -0
  224. package/dist/memory/cloud/harness-config.js +16 -20
  225. package/dist/memory/cloud/memory-scope.d.ts +17 -0
  226. package/dist/memory/cloud/memory-scope.js +22 -0
  227. package/dist/memory/cloud/sync-cycle.d.ts +32 -4
  228. package/dist/memory/cloud/sync-cycle.js +113 -12
  229. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  230. package/dist/memory/cloud/sync-daemon.js +114 -4
  231. package/dist/memory/cloud/sync-disk.js +26 -2
  232. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  233. package/dist/memory/cloud/sync-screenshots.js +105 -0
  234. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  235. package/dist/memory/cloud/unsynced-roots.js +166 -0
  236. package/dist/memory/impact/account-watch.d.ts +16 -1
  237. package/dist/memory/impact/account-watch.js +26 -1
  238. package/dist/memory/impact/impact-store.d.ts +1 -4
  239. package/dist/memory/impact/impact-store.js +32 -42
  240. package/dist/memory/intent/inline-intent.d.ts +1 -0
  241. package/dist/memory/intent/intent-shard-store.js +16 -4
  242. package/dist/memory/intent/intent-shard.d.ts +12 -0
  243. package/dist/memory/intent/intent-store.d.ts +1 -0
  244. package/dist/memory/intent/intent-tools.js +42 -2
  245. package/dist/memory/intent/open-intents.d.ts +6 -0
  246. package/dist/memory/intent/open-intents.js +10 -1
  247. package/dist/memory/intent/settled-words.d.ts +24 -0
  248. package/dist/memory/intent/settled-words.js +130 -0
  249. package/dist/memory/journal/drive-flow.d.ts +16 -0
  250. package/dist/memory/journal/drive-flow.js +34 -2
  251. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  252. package/dist/memory/journal/drive-run-flush.js +20 -5
  253. package/dist/memory/journal/journal-recorder.js +46 -3
  254. package/dist/memory/journal/on-disk/retention.d.ts +5 -0
  255. package/dist/memory/journal/on-disk/retention.js +27 -2
  256. package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
  257. package/dist/memory/journal/session-end.d.ts +15 -1
  258. package/dist/memory/journal/session-end.js +38 -7
  259. package/dist/memory/project/artifact-root-resolver.js +33 -5
  260. package/dist/memory/project/artifact-root.d.ts +4 -3
  261. package/dist/memory/project/artifact-root.js +2 -2
  262. package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
  263. package/dist/memory/project/dir/reticle-dir.js +23 -2
  264. package/dist/memory/project/link-directory.d.ts +15 -0
  265. package/dist/memory/project/link-directory.js +44 -0
  266. package/dist/memory/project/root-claims.d.ts +6 -0
  267. package/dist/memory/project/root-claims.js +39 -0
  268. package/dist/memory/project/session-root.d.ts +2 -0
  269. package/dist/memory/project/session-root.js +9 -1
  270. package/dist/memory/project/sync-status.d.ts +46 -0
  271. package/dist/memory/project/sync-status.js +135 -1
  272. package/dist/memory/recall/memory-tools.js +46 -3
  273. package/dist/memory/recall/platform-memory.d.ts +34 -0
  274. package/dist/memory/recall/platform-memory.js +139 -0
  275. package/dist/memory/recall/project-memory.js +36 -8
  276. package/dist/portal/bridge/bridge.d.ts +9 -5
  277. package/dist/portal/bridge/bridge.js +66 -23
  278. package/dist/portal/bridge/harness-request.d.ts +23 -0
  279. package/dist/portal/bridge/harness-request.js +27 -0
  280. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  281. package/dist/portal/bridge/wrong-path.js +35 -0
  282. package/dist/portal/input/network-mock-tools.js +11 -2
  283. package/dist/portal/input/real-input.d.ts +2 -0
  284. package/dist/portal/input/real-input.js +13 -10
  285. package/dist/portal/pool/browser-pool.d.ts +48 -0
  286. package/dist/portal/pool/browser-pool.js +120 -2
  287. package/dist/portal/pool/context-permissions.d.ts +33 -0
  288. package/dist/portal/pool/context-permissions.js +33 -0
  289. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  290. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  291. package/dist/portal/pool/playwright-launcher.d.ts +27 -5
  292. package/dist/portal/pool/playwright-launcher.js +59 -14
  293. package/dist/portal/pool/pool-contract.d.ts +21 -1
  294. package/dist/portal/session/agent-link.d.ts +8 -0
  295. package/dist/portal/session/agent-link.js +17 -0
  296. package/dist/portal/session/command-payload.js +6 -1
  297. package/dist/portal/session/daemon-answers.d.ts +3 -3
  298. package/dist/portal/session/daemon-answers.js +4 -2
  299. package/dist/portal/session/dev-server/dev-command.d.ts +9 -0
  300. package/dist/portal/session/dev-server/dev-command.js +27 -1
  301. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  302. package/dist/portal/session/facts/observed-state.js +46 -3
  303. package/dist/portal/session/human/live-control.d.ts +9 -2
  304. package/dist/portal/session/human/live-control.js +12 -3
  305. package/dist/portal/session/live-control-tools.js +82 -13
  306. package/dist/portal/session/narration-args.d.ts +5 -0
  307. package/dist/portal/session/narration-args.js +17 -0
  308. package/dist/portal/session/no-session-diagnosis.d.ts +1 -1
  309. package/dist/portal/session/no-session-diagnosis.js +31 -9
  310. package/dist/portal/session/no-session-next-action.d.ts +20 -0
  311. package/dist/portal/session/no-session-next-action.js +134 -61
  312. package/dist/portal/session/no-session-watch.js +179 -22
  313. package/dist/portal/session/presence/session-lease.js +1 -1
  314. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  315. package/dist/portal/session/recorded-gaps.js +251 -0
  316. package/dist/portal/session/session-health.d.ts +11 -0
  317. package/dist/portal/session/session-health.js +3 -1
  318. package/dist/portal/session/session-info.js +2 -1
  319. package/dist/portal/session/session-manager.d.ts +18 -0
  320. package/dist/portal/session/session-manager.js +54 -3
  321. package/dist/portal/session/session-successor.d.ts +8 -0
  322. package/dist/portal/session/session-successor.js +1 -1
  323. package/dist/portal/session/session.d.ts +15 -28
  324. package/dist/portal/session/session.js +60 -61
  325. package/dist/portal/session/timing/command-timeout.js +25 -1
  326. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  327. package/dist/portal/session/timing/wall-clock.js +1 -1
  328. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  329. package/dist/portal/session/zero-install-first-call.js +88 -0
  330. package/dist/start-options.d.ts +7 -1
  331. package/dist/start-wiring.d.ts +63 -0
  332. package/dist/start-wiring.js +169 -0
  333. package/dist/status-payload.d.ts +13 -1
  334. package/dist/status-payload.js +13 -1
  335. package/dist/surface/http-server.js +7 -1
  336. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  337. package/dist/surface/mcp/attach-memory.js +12 -1
  338. package/dist/surface/mcp/mcp-proxy.d.ts +4 -0
  339. package/dist/surface/mcp/mcp-proxy.js +29 -8
  340. package/dist/surface/mcp/mcp.d.ts +23 -0
  341. package/dist/surface/mcp/mcp.js +34 -4
  342. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  343. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  344. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  345. package/dist/surface/mcp/server-instructions.js +22 -14
  346. package/dist/surface/mcp/shared-params.js +1 -1
  347. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  348. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  349. package/dist/surface/tools/account-tool.d.ts +22 -0
  350. package/dist/surface/tools/account-tool.js +157 -0
  351. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  352. package/dist/surface/tools/act/act-danger.js +38 -1
  353. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  354. package/dist/surface/tools/act/act-observation.js +57 -0
  355. package/dist/surface/tools/act/act-preflight.js +25 -2
  356. package/dist/surface/tools/act/act-target.js +8 -3
  357. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  358. package/dist/surface/tools/act/resolve-target.js +18 -3
  359. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  360. package/dist/surface/tools/act/screen-request.js +113 -0
  361. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  362. package/dist/surface/tools/act/sequence-grade.js +13 -2
  363. package/dist/surface/tools/act-sequence-tool.js +136 -27
  364. package/dist/surface/tools/act-tools.d.ts +0 -9
  365. package/dist/surface/tools/act-tools.js +48 -34
  366. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  367. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  368. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  369. package/dist/surface/tools/agent/app-notes.js +48 -0
  370. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  371. package/dist/surface/tools/agent/build-staleness.js +62 -0
  372. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  373. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  374. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  375. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  376. package/dist/surface/tools/agent/notices.d.ts +50 -0
  377. package/dist/surface/tools/agent/notices.js +152 -0
  378. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  379. package/dist/surface/tools/agent/reteach.js +50 -0
  380. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  381. package/dist/surface/tools/args/alias-args.js +10 -0
  382. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  383. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  384. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  385. package/dist/surface/tools/assert/assert-source.js +40 -0
  386. package/dist/surface/tools/assert/assert-verdict.js +25 -15
  387. package/dist/surface/tools/browser-tools.js +43 -1
  388. package/dist/surface/tools/chat-drives.d.ts +75 -0
  389. package/dist/surface/tools/chat-drives.js +265 -21
  390. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  391. package/dist/surface/tools/coverage-tools.js +2 -53
  392. package/dist/surface/tools/dynamic-tools.js +29 -1
  393. package/dist/surface/tools/empty-session-list.d.ts +10 -0
  394. package/dist/surface/tools/empty-session-list.js +45 -5
  395. package/dist/surface/tools/error-recovery.d.ts +8 -0
  396. package/dist/surface/tools/error-recovery.js +69 -5
  397. package/dist/surface/tools/explore-tools.d.ts +23 -2
  398. package/dist/surface/tools/explore-tools.js +377 -74
  399. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  400. package/dist/surface/tools/feedback-tools.js +4 -3
  401. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  402. package/dist/surface/tools/gap-novelty.js +8 -1
  403. package/dist/surface/tools/harness-explore.d.ts +52 -73
  404. package/dist/surface/tools/harness-explore.js +177 -146
  405. package/dist/surface/tools/harness-gate.d.ts +88 -0
  406. package/dist/surface/tools/harness-gate.js +235 -0
  407. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  408. package/dist/surface/tools/harness-hunt.js +215 -0
  409. package/dist/surface/tools/harness-plan.d.ts +5 -0
  410. package/dist/surface/tools/harness-plan.js +7 -0
  411. package/dist/surface/tools/harness-script.d.ts +22 -0
  412. package/dist/surface/tools/harness-script.js +256 -38
  413. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  414. package/dist/surface/tools/harness-tab-guard.js +27 -0
  415. package/dist/surface/tools/harness-toolset.d.ts +8 -0
  416. package/dist/surface/tools/harness-toolset.js +27 -4
  417. package/dist/surface/tools/human-notes.d.ts +16 -0
  418. package/dist/surface/tools/human-notes.js +27 -0
  419. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  420. package/dist/surface/tools/invoke-tool.js +220 -93
  421. package/dist/surface/tools/lease-hint.js +26 -5
  422. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  423. package/dist/surface/tools/lease-permissions.js +73 -0
  424. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  425. package/dist/surface/tools/lease-readiness.js +57 -0
  426. package/dist/surface/tools/lease-seed.d.ts +20 -0
  427. package/dist/surface/tools/lease-seed.js +45 -1
  428. package/dist/surface/tools/lease-tools.d.ts +10 -1
  429. package/dist/surface/tools/lease-tools.js +119 -69
  430. package/dist/surface/tools/live-call-text.js +2 -2
  431. package/dist/surface/tools/merge-tools.js +42 -2
  432. package/dist/surface/tools/merged-name-redirect.js +4 -0
  433. package/dist/surface/tools/next-step.d.ts +11 -1
  434. package/dist/surface/tools/next-step.js +73 -18
  435. package/dist/surface/tools/observe-tools.js +43 -5
  436. package/dist/surface/tools/platform-moment.d.ts +60 -0
  437. package/dist/surface/tools/platform-moment.js +132 -4
  438. package/dist/surface/tools/read-tools.js +65 -14
  439. package/dist/surface/tools/reticle-result.d.ts +120 -0
  440. package/dist/surface/tools/reticle-result.js +364 -0
  441. package/dist/surface/tools/tool-kit.d.ts +68 -2
  442. package/dist/surface/tools/tool-kit.js +73 -1
  443. package/dist/surface/tools/tools.js +25 -13
  444. package/dist/telemetry/account-envelope.d.ts +7 -0
  445. package/dist/telemetry/account-envelope.js +61 -0
  446. package/dist/telemetry/agent-client.d.ts +15 -0
  447. package/dist/telemetry/agent-client.js +57 -0
  448. package/dist/telemetry/app-instrumented.js +9 -2
  449. package/dist/telemetry/argument-shape.d.ts +7 -0
  450. package/dist/telemetry/argument-shape.js +86 -1
  451. package/dist/telemetry/automation-hint.d.ts +2 -3
  452. package/dist/telemetry/automation-hint.js +33 -8
  453. package/dist/telemetry/cli-telemetry.js +7 -2
  454. package/dist/telemetry/daemon-telemetry.js +3 -0
  455. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  456. package/dist/telemetry/error-fingerprint.js +61 -5
  457. package/dist/telemetry/feedback-cli.d.ts +0 -13
  458. package/dist/telemetry/feedback-cli.js +0 -77
  459. package/dist/telemetry/feedback.d.ts +13 -0
  460. package/dist/telemetry/feedback.js +183 -17
  461. package/dist/telemetry/harness-run.d.ts +18 -0
  462. package/dist/telemetry/harness-run.js +80 -0
  463. package/dist/telemetry/hud-events.d.ts +16 -0
  464. package/dist/telemetry/hud-events.js +27 -0
  465. package/dist/telemetry/hud-metrics.d.ts +27 -6
  466. package/dist/telemetry/hud-metrics.js +99 -25
  467. package/dist/telemetry/init-telemetry.js +2 -2
  468. package/dist/telemetry/install-source.d.ts +13 -25
  469. package/dist/telemetry/install-source.js +44 -3
  470. package/dist/telemetry/mcp-connection.d.ts +0 -14
  471. package/dist/telemetry/mcp-connection.js +5 -1
  472. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  473. package/dist/telemetry/onboarding-firsts.js +81 -6
  474. package/dist/telemetry/platform-linked.d.ts +5 -0
  475. package/dist/telemetry/platform-linked.js +32 -0
  476. package/dist/telemetry/project-profile.js +5 -3
  477. package/dist/telemetry/proxy-telemetry.js +4 -1
  478. package/dist/telemetry/session-metrics.d.ts +15 -4
  479. package/dist/telemetry/session-metrics.js +88 -52
  480. package/dist/telemetry/telemetry.d.ts +26 -2
  481. package/dist/telemetry/telemetry.js +102 -21
  482. package/dist/telemetry/verification-of.d.ts +3 -1
  483. package/dist/telemetry/verification-of.js +12 -4
  484. package/dist/wire-journal.d.ts +2 -2
  485. package/dist/wire-journal.js +16 -5
  486. package/docs/README.md +2 -2
  487. package/docs/actions.mdx +6 -3
  488. package/docs/adapters.md +1 -1
  489. package/docs/agent-cheatsheet.md +24 -27
  490. package/docs/architecture.md +5 -5
  491. package/docs/autodrive.md +13 -12
  492. package/docs/benchmarks.md +5 -5
  493. package/docs/best-practices.mdx +27 -9
  494. package/docs/capabilities.mdx +14 -16
  495. package/docs/cli/affected.mdx +1 -1
  496. package/docs/cli/cloud.mdx +54 -75
  497. package/docs/cli/doctor.mdx +8 -3
  498. package/docs/cli/drive.mdx +12 -12
  499. package/docs/cli/feedback.mdx +3 -3
  500. package/docs/cli/gate.mdx +7 -2
  501. package/docs/cli/help.mdx +50 -55
  502. package/docs/cli/init.mdx +32 -15
  503. package/docs/cli/license.mdx +12 -8
  504. package/docs/cli/mcp.mdx +4 -4
  505. package/docs/cli/open.mdx +3 -3
  506. package/docs/cli/report.mdx +4 -2
  507. package/docs/cli/restart.mdx +2 -2
  508. package/docs/cli/rollback.mdx +14 -8
  509. package/docs/cli/serve.mdx +4 -4
  510. package/docs/cli/setup.mdx +23 -0
  511. package/docs/cli/status.mdx +13 -4
  512. package/docs/cli/stop.mdx +67 -8
  513. package/docs/cli/try.mdx +62 -0
  514. package/docs/cli/update.mdx +4 -3
  515. package/docs/cli/verify.mdx +17 -6
  516. package/docs/cli/version.mdx +3 -2
  517. package/docs/cli.mdx +110 -41
  518. package/docs/debugging.md +3 -3
  519. package/docs/deploy-checks.md +1 -1
  520. package/docs/desktop.mdx +5 -3
  521. package/docs/enterprise.md +11 -10
  522. package/docs/environment.mdx +5 -2
  523. package/docs/faq.mdx +3 -3
  524. package/docs/first-drive.md +5 -4
  525. package/docs/flows.md +35 -27
  526. package/docs/for-agents.md +4 -5
  527. package/docs/frameworks.mdx +32 -21
  528. package/docs/getting-started.md +66 -64
  529. package/docs/human-control.md +15 -14
  530. package/docs/index.mdx +15 -43
  531. package/docs/install-agentic.mdx +22 -37
  532. package/docs/install-manual.mdx +22 -12
  533. package/docs/instrumentation.mdx +5 -3
  534. package/docs/integration-patterns.md +7 -7
  535. package/docs/license-activation.mdx +1 -1
  536. package/docs/multi-agent-testing.md +24 -6
  537. package/docs/packages/babel-plugin.mdx +4 -2
  538. package/docs/packages/browser.mdx +16 -10
  539. package/docs/packages/core.mdx +12 -5
  540. package/docs/packages/electron.mdx +3 -2
  541. package/docs/packages/engine.mdx +1 -1
  542. package/docs/packages/eslint-plugin.mdx +18 -12
  543. package/docs/packages/next.mdx +8 -7
  544. package/docs/packages/open-verification.mdx +1 -1
  545. package/docs/packages/server.mdx +5 -5
  546. package/docs/packages/tauri.mdx +8 -8
  547. package/docs/packages/test.mdx +4 -10
  548. package/docs/packages/vite-plugin.mdx +11 -4
  549. package/docs/packages.mdx +11 -15
  550. package/docs/platform-integration.md +6 -5
  551. package/docs/predicates.mdx +40 -24
  552. package/docs/quickstart.mdx +58 -29
  553. package/docs/required-checks.md +8 -7
  554. package/docs/reticle-manual.md +15 -5
  555. package/docs/skill-file.mdx +17 -79
  556. package/docs/skill-setup.md +9 -9
  557. package/docs/skill.md +200 -0
  558. package/docs/system-map.md +7 -7
  559. package/docs/telemetry.md +22 -24
  560. package/docs/testing.md +4 -4
  561. package/docs/token-efficiency.md +12 -12
  562. package/docs/tools/act-and-wait.mdx +9 -2
  563. package/docs/tools/act-sequence.mdx +6 -7
  564. package/docs/tools/act.mdx +2 -2
  565. package/docs/tools/assert.mdx +18 -17
  566. package/docs/tools/console.mdx +9 -9
  567. package/docs/tools/inspect.mdx +16 -7
  568. package/docs/tools/look.mdx +24 -0
  569. package/docs/tools/navigate.mdx +5 -3
  570. package/docs/tools/network.mdx +2 -2
  571. package/docs/tools/observe.mdx +6 -6
  572. package/docs/tools/overview.mdx +34 -33
  573. package/docs/tools/query.mdx +5 -5
  574. package/docs/tools/session-and-feedback.mdx +13 -4
  575. package/docs/tools/sessions.mdx +8 -8
  576. package/docs/tools/snapshot.mdx +6 -5
  577. package/docs/tools/state.mdx +9 -9
  578. package/docs/tools/tools-and-run.mdx +26 -24
  579. package/docs/tools/verify.mdx +28 -0
  580. package/docs/tools/wait-for.mdx +8 -4
  581. package/docs/troubleshooting.mdx +21 -6
  582. package/docs/usage.md +51 -45
  583. package/docs/use-cases.mdx +3 -3
  584. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  585. package/docs/vs-playwright-mcp.mdx +3 -1
  586. package/docs/what-is-recorded.md +7 -5
  587. package/docs/what-is-reticle.mdx +2 -2
  588. package/docs/why-reticle.mdx +1 -1
  589. package/package.json +6 -5
  590. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  591. package/dist/command/cli/demo/demo-page.js +0 -249
  592. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  593. package/dist/command/cli/demo/demo-run.js +0 -138
  594. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  595. package/dist/judgement/hunt/hunt-report.js +0 -84
  596. package/dist/language/flows/buddy-status.d.ts +0 -25
  597. package/dist/language/flows/buddy-status.js +0 -32
  598. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  599. package/dist/language/flows/change/watch-batcher.js +0 -19
  600. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  601. package/dist/memory/cloud/harness-offer.js +0 -145
  602. package/dist/surface/tools/feature-capture.d.ts +0 -151
  603. package/dist/surface/tools/feature-capture.js +0 -235
  604. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  605. package/dist/surface/tools/tool-hit-rate.js +0 -90
  606. package/dist/telemetry/harness-drive.d.ts +0 -4
  607. package/dist/telemetry/harness-drive.js +0 -35
  608. package/dist/telemetry/identify.d.ts +0 -22
  609. package/dist/telemetry/identify.js +0 -73
  610. package/docs/cli/capsules.mdx +0 -70
  611. package/docs/cli/hunt.mdx +0 -73
  612. package/docs/cli/identify.mdx +0 -76
  613. package/docs/cli/kill.mdx +0 -91
  614. package/docs/cli/watch.mdx +0 -62
@@ -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,8 +69,20 @@ 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);
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);
55
86
  const report = verdictOf(acquired, 'sessionId');
56
87
  const sessionId = report?.['sessionId'];
57
88
  // `zeroInstall`: the page never dialled in, so the lease supplied Reticle's own reader.
@@ -84,7 +115,7 @@ export function endpointFor(port, token) {
84
115
  return url;
85
116
  }
86
117
  export async function connectOverSse(endpoint) {
87
- const client = new Client({ name: 'reticle-cli', version: '1' }, { capabilities: {} });
118
+ const client = new Client({ name: CLI_CLIENT_NAME, version: '1' }, { capabilities: {} });
88
119
  await client.connect(new SSEClientTransport(endpoint));
89
120
  return {
90
121
  call: async (name, args, timeoutMs) => await client.callTool({ name, arguments: args }, undefined, timeoutMs === undefined ? undefined : { timeout: timeoutMs }),
@@ -193,8 +224,14 @@ export async function runAdhocVerdict(options) {
193
224
  // OTHER listening port as the one to open. The caller already said which url; open it here, in
194
225
  // a Reticle browser, and hand the lease back when the verdict is in.
195
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
+ }
196
233
  if (url !== undefined && options.sessionId === undefined && options.sessions !== undefined) {
197
- const opened = await leaseIfNoTab(caller, url, options.sessions);
234
+ const opened = await leaseIfNoTab(caller, url, options.sessions, options.root);
198
235
  if ('failed' in opened)
199
236
  return { code: 1, lines: ['verified: unknown', ...opened.failed] };
200
237
  leased = opened.leased;
@@ -240,3 +277,30 @@ export async function runAdhocVerdict(options) {
240
277
  await caller.close().catch(() => undefined);
241
278
  }
242
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)
@@ -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,7 +5,8 @@
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';
@@ -19,13 +20,10 @@ import { isInteractiveSource, unflowedFiles } from '../../language/flows/change/
19
20
  import { LedgerStore, regressions, staleChanged, unexecutedChanged, } from '../../features/exhaust/ledger.js';
20
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,101 +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(passingFlowNames(latest?.flows ?? []));
76
- const quarantined = await new FlakeStore(fs, reticleRoot).flakyFlows();
77
- const flaky = new Set(quarantined);
78
- // A deviation is an at-risk flow with no passing artifact — and a quarantined flake is not a deviation.
79
- const deviations = affected.filter((n) => !passingNames.has(n) && !flaky.has(n));
80
- log('reticle_buddy', {
81
- status: formatBuddyStatus({
82
- total: flows.length,
83
- passing: passingNames.size,
84
- deviations,
85
- quarantined,
86
- }),
87
- });
88
- }
89
- catch {
90
- // never let the ambient line break the watcher
91
- }
92
- }
93
- const WATCHED_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
94
- const WATCH_DEBOUNCE_MS = 200;
95
- /**
96
- * `reticle watch [url]` — on every save, report which saved flows must re-verify (the affected set).
97
- * Environment-side (costs the agent nothing per turn); the buddy loop. This v1 detects + reports on
98
- * change; auto-replaying the affected flows against the app is the next increment. Long-running.
99
- */
100
- export function handleWatch() {
101
- const fs = createNodeFileSystem();
102
- const reticleRoot = join(process.cwd(), ReticleDir.ROOT);
103
- const batcher = createWatchBatcher({
104
- debounceMs: WATCH_DEBOUNCE_MS,
105
- schedule: (fn, ms) => {
106
- setTimeout(fn, ms).unref();
107
- },
108
- onFlush: (files) => {
109
- void loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()))
110
- .then(async (flows) => {
111
- const result = affectedSavedFlows(flows, files);
112
- if (result.affected.length > 0) {
113
- log('reticle_watch_affected', { changed: files, affected: result.affected });
114
- }
115
- await emitBuddyStatus(fs, reticleRoot, flows, result.affected);
116
- })
117
- .catch((error) => {
118
- log('reticle_watch_failed', {
119
- error: error instanceof Error ? error.message : String(error),
120
- });
121
- });
122
- },
123
- });
124
- log('reticle_watch_started', { cwd: process.cwd() });
125
- // Print the ambient line once at startup so the human sees where they stand before touching anything.
126
- void loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()))
127
- .then((flows) => emitBuddyStatus(fs, reticleRoot, flows, []))
128
- .catch(() => undefined);
129
- watch(process.cwd(), { recursive: true }, (_event, filename) => {
130
- if ('string' === typeof filename && WATCHED_EXTENSIONS.test(filename))
131
- batcher.onChange(filename);
132
- });
133
- }
134
- /**
135
- * `reticle capsules` — list saved fail-to-pass bug capsules (.reticle/capsules). Each is a minimal
136
- * failing reproduction plus the consequence that should have held; replay one with reticle_flow_replay.
137
- */
138
- export async function handleCapsules() {
139
- try {
140
- const fs = createNodeFileSystem();
141
- const capsules = await new CapsuleStore(fs, join(process.cwd(), ReticleDir.ROOT)).all();
142
- log('reticle_capsules', {
143
- count: capsules.length,
144
- capsules: capsules.map((c) => ({
145
- id: c.id,
146
- ...(c.flow === undefined ? {} : { flow: c.flow }),
147
- origin: c.origin,
148
- expected: c.expected,
149
- observed: c.observed,
150
- steps: c.steps.length,
151
- })),
152
- });
153
- }
154
- catch (error) {
155
- log('reticle_capsules_failed', {
156
- error: error instanceof Error ? error.message : String(error),
157
- });
158
- process.exitCode = 1;
159
- }
160
- }
161
64
  /**
162
65
  * `reticle gate <file...>` — exit non-zero unless passing artifacts cover the flows affected by the
163
66
  * changed files. Flaky flows are quarantined (surfaced, not blocking). The environment-side enforcement
@@ -260,8 +163,19 @@ acceptCoverage = false) {
260
163
  // verdict already applies to `reticle verify`; see flowCoverageReport.
261
164
  const flowCoverage = flowCoverageReport(coverage.flows);
262
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);
263
177
  log('reticle_gate', {
264
- pass,
178
+ pass: GateExit.PASS === code,
265
179
  uncovered: result.uncovered,
266
180
  quarantined: result.quarantined,
267
181
  ...(result.downgraded.length > 0 ? { downgraded: result.downgraded } : {}),
@@ -279,10 +193,18 @@ acceptCoverage = false) {
279
193
  // problem to fail. A Stop hook wants to block a real regression and NOT block a project that
280
194
  // has simply not recorded a flow yet — which is every project on its first day, and measured
281
195
  // before this change as an exit 1 that would have blocked every stop. See GateExit.
282
- if (!pass) {
283
- const code = result.pass && flowCoverage.outcome !== undefined
284
- ? GateExit.NOTHING_TO_CHECK
285
- : 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) {
286
208
  process.exitCode = code;
287
209
  if (hook) {
288
210
  // An honest escape hatch, because the alternative to one is not compliance — it is somebody
@@ -301,6 +223,7 @@ acceptCoverage = false) {
301
223
  unflowed: result.unflowed,
302
224
  coverageRegressed: result.coverageRegressed.map((r) => `${r.level} ${String(r.was)}% -> ${String(r.now)}%`),
303
225
  unexecuted: result.unexecuted,
226
+ regressed: regressed?.length ?? 0,
304
227
  });
305
228
  if (message !== undefined)
306
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;
@@ -44,3 +44,78 @@ export const VERIFY_COMMAND = 'verify';
44
44
  * missed for a release.
45
45
  */
46
46
  export const EXPECT_FLAG = '--expect';
47
+ /**
48
+ * The account and cloud commands. They are dispatched before the typed parser, and listed here so
49
+ * that the dispatcher and the telemetry vocabulary read one list instead of two.
50
+ */
51
+ export const CLOUD_COMMANDS = [
52
+ 'login',
53
+ 'connect',
54
+ 'try',
55
+ 'logout',
56
+ 'whoami',
57
+ 'link',
58
+ 'project',
59
+ 'config',
60
+ 'issues',
61
+ 'memory',
62
+ 'push',
63
+ 'sync',
64
+ 'runs',
65
+ 'regression',
66
+ 'share',
67
+ ];
68
+ /**
69
+ * Old command names that still run, for one release, under the name that replaced them. Each one
70
+ * prints a single line saying so, then does what it always did.
71
+ */
72
+ export const RENAMED_COMMANDS = new Map([
73
+ ['kill', 'stop --force'],
74
+ ['login', 'connect'],
75
+ ['link', 'connect'],
76
+ ['project', 'connect --project <name|id>'],
77
+ ['whoami', 'status'],
78
+ ['push', 'sync'],
79
+ ['regression', 'runs regression'],
80
+ ['share', 'runs share <runId>'],
81
+ ['issues', 'runs issues'],
82
+ ['memory', 'runs memory'],
83
+ ]);
84
+ const HELP_FLAGS = new Set(['--help', '-h']);
85
+ /** `login --email` is the documented sign-in without a browser, so it is not a renamed `connect`. */
86
+ const BROWSERLESS_LOGIN = { command: 'login', flag: '--email' };
87
+ /**
88
+ * The command an old name now goes by, when the note saying so should print; otherwise undefined.
89
+ * Not for a request for help (that answer names the new command itself), and not for
90
+ * `login --email`, which `connect --help` documents as the sign-in for CI and agents.
91
+ */
92
+ export function renamedCommandFor(argv) {
93
+ const name = argv[0];
94
+ if (name === undefined || argv.some((arg) => HELP_FLAGS.has(arg)))
95
+ return undefined;
96
+ if (BROWSERLESS_LOGIN.command === name && argv.includes(BROWSERLESS_LOGIN.flag))
97
+ return undefined;
98
+ return RENAMED_COMMANDS.get(name);
99
+ }
100
+ /**
101
+ * Commands that were removed, and what to use instead. They stay in the telemetry vocabulary, so
102
+ * the people still typing one show up as that name rather than as `unknown`.
103
+ */
104
+ export const REMOVED_COMMANDS = new Map([
105
+ ['hunt', 'it has no replacement'],
106
+ ['watch', 'use `reticle affected` after you save, or `reticle gate` before you commit'],
107
+ ['capsules', 'it has no replacement; saved capsules stay in .reticle/capsules'],
108
+ ['tutorial', "use `reticle init` in your app's folder, or `reticle try <url>`"],
109
+ [
110
+ 'identify',
111
+ 'it has no replacement; delete ~/.reticle/identity.json to forget a saved identity, and use `reticle feedback` to reach us',
112
+ ],
113
+ ]);
114
+ export const removedNote = (command, instead) => `\`reticle ${command}\` was removed in this version; ${instead}`;
115
+ const DIM = '\u001b[2m';
116
+ const RESET = '\u001b[0m';
117
+ /** One line on stderr when an old name ran: dim on a terminal, plain anywhere else. */
118
+ export const renamedNote = (command, now, colour) => {
119
+ const line = `\`reticle ${command}\` is now \`reticle ${now}\``;
120
+ return colour ? `${DIM}${line}${RESET}` : line;
121
+ };
@@ -12,6 +12,8 @@ export type VerifySuffix = {
12
12
  explore?: boolean;
13
13
  persona?: string;
14
14
  select?: string[];
15
+ resultsJson?: string;
16
+ confirmDangerous?: boolean;
15
17
  } | {
16
18
  kind: 'error';
17
19
  message: string;