@reticlehq/server 3.8.2 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (477) hide show
  1. package/LICENSE +201 -104
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/SKILL.md +13 -12
  5. package/bin/launch.js +13 -0
  6. package/bin/package.json +3 -0
  7. package/bin/reticle.js +66 -8
  8. package/dist/chromium-launch-options.d.ts +25 -0
  9. package/dist/chromium-launch-options.js +21 -1
  10. package/dist/command/cli/adhoc-suite.js +2 -0
  11. package/dist/command/cli/adhoc-verdict.d.ts +2 -43
  12. package/dist/command/cli/adhoc-verdict.js +50 -160
  13. package/dist/command/cli/answers/gate-exit.d.ts +6 -2
  14. package/dist/command/cli/answers/gate-exit.js +12 -2
  15. package/dist/command/cli/answers/mcp-connection-hint.d.ts +2 -0
  16. package/dist/command/cli/answers/mcp-connection-hint.js +6 -0
  17. package/dist/command/cli/ci-hint.d.ts +44 -0
  18. package/dist/command/cli/ci-hint.js +72 -0
  19. package/dist/command/cli/cli-doctor.d.ts +6 -1
  20. package/dist/command/cli/cli-doctor.js +46 -5
  21. package/dist/command/cli/cli-flow-commands.d.ts +7 -1
  22. package/dist/command/cli/cli-flow-commands.js +39 -24
  23. package/dist/command/cli/cli-kill.d.ts +21 -0
  24. package/dist/command/cli/cli-kill.js +47 -4
  25. package/dist/command/cli/cli-parse-compare.d.ts +22 -0
  26. package/dist/command/cli/cli-parse-compare.js +75 -0
  27. package/dist/command/cli/cli-parse-grade.d.ts +36 -0
  28. package/dist/command/cli/cli-parse-grade.js +75 -0
  29. package/dist/command/cli/cli-parse-grammar.d.ts +2 -0
  30. package/dist/command/cli/cli-parse-grammar.js +18 -20
  31. package/dist/command/cli/cli-parse-verify.d.ts +10 -0
  32. package/dist/command/cli/cli-parse-verify.js +63 -14
  33. package/dist/command/cli/cli-parse.d.ts +22 -17
  34. package/dist/command/cli/cli-parse.js +54 -32
  35. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  36. package/dist/command/cli/cli-update-commands.js +29 -20
  37. package/dist/command/cli/cli-usage.js +61 -31
  38. package/dist/command/cli/cli-verify.d.ts +17 -3
  39. package/dist/command/cli/cli-verify.js +59 -21
  40. package/dist/command/cli/cloud-cli.js +2 -119
  41. package/dist/command/cli/daemon-link/daemon-client.d.ts +45 -0
  42. package/dist/command/cli/daemon-link/daemon-client.js +205 -0
  43. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +6 -1
  44. package/dist/command/cli/doctor/browser/chromium-hint.js +11 -5
  45. package/dist/command/cli/doctor/doctor-daemon-line.js +6 -3
  46. package/dist/command/cli/doctor/doctor-fix.d.ts +44 -0
  47. package/dist/command/cli/doctor/doctor-fix.js +89 -0
  48. package/dist/command/cli/doctor/doctor-launcher-line.d.ts +23 -0
  49. package/dist/command/cli/doctor/doctor-launcher-line.js +60 -0
  50. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  51. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  52. package/dist/command/cli/doctor-repairs.d.ts +64 -0
  53. package/dist/command/cli/doctor-repairs.js +214 -0
  54. package/dist/command/cli/drive/drive-command.js +3 -7
  55. package/dist/command/cli/ensure-daemon.d.ts +26 -0
  56. package/dist/command/cli/ensure-daemon.js +57 -0
  57. package/dist/command/cli/finished-run/grade-command.d.ts +23 -0
  58. package/dist/command/cli/finished-run/grade-command.js +180 -0
  59. package/dist/command/cli/first-use-checks.d.ts +41 -0
  60. package/dist/command/cli/first-use-checks.js +127 -0
  61. package/dist/command/cli/first-verdict-node.d.ts +3 -0
  62. package/dist/command/cli/first-verdict-node.js +189 -0
  63. package/dist/command/cli/first-verdict.d.ts +126 -0
  64. package/dist/command/cli/first-verdict.js +267 -0
  65. package/dist/command/cli/launch/sdk-version-match.d.ts +3 -2
  66. package/dist/command/cli/launch/sdk-version-match.js +3 -2
  67. package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +1 -1
  68. package/dist/command/cli/lifecycle/daemon-lifecycle.js +7 -6
  69. package/dist/command/cli/mcp-command.js +13 -4
  70. package/dist/command/cli/ports/port-holder.d.ts +11 -0
  71. package/dist/command/cli/ports/port-holder.js +36 -4
  72. package/dist/command/cli/setup-mcp-cli.d.ts +27 -1
  73. package/dist/command/cli/setup-mcp-cli.js +98 -23
  74. package/dist/command/cli/status/status-lines.d.ts +2 -0
  75. package/dist/command/cli/status/status-lines.js +72 -17
  76. package/dist/command/cli/status-fields.d.ts +5 -1
  77. package/dist/command/cli/status-fields.js +24 -6
  78. package/dist/command/cli/try-command.d.ts +7 -0
  79. package/dist/command/cli/try-command.js +11 -3
  80. package/dist/command/cli/two-builds/compare-command.d.ts +48 -0
  81. package/dist/command/cli/two-builds/compare-command.js +314 -0
  82. package/dist/command/cli/verify-against.d.ts +61 -0
  83. package/dist/command/cli/verify-against.js +187 -0
  84. package/dist/command/cli/verify-no-session.d.ts +2 -0
  85. package/dist/command/cli/verify-no-session.js +13 -0
  86. package/dist/command/cli/verify-results.d.ts +35 -2
  87. package/dist/command/cli/verify-results.js +76 -10
  88. package/dist/command/cli.js +112 -70
  89. package/dist/command/daemon/binding/daemon-status-probe.d.ts +3 -1
  90. package/dist/command/daemon/binding/daemon-status-probe.js +4 -2
  91. package/dist/command/daemon/daemon-argv.d.ts +9 -0
  92. package/dist/command/daemon/daemon-argv.js +11 -0
  93. package/dist/command/daemon/daemon-resolve.d.ts +8 -1
  94. package/dist/command/daemon/daemon-resolve.js +27 -1
  95. package/dist/command/daemon/daemon.d.ts +22 -4
  96. package/dist/command/daemon/daemon.js +52 -10
  97. package/dist/command/daemon/lifetime/daemon-exit.d.ts +24 -0
  98. package/dist/command/daemon/lifetime/daemon-exit.js +39 -0
  99. package/dist/command/daemon/lifetime/death-cause.d.ts +15 -0
  100. package/dist/command/daemon/lifetime/death-cause.js +149 -0
  101. package/dist/command/daemon/lifetime/heartbeat.d.ts +7 -15
  102. package/dist/command/daemon/lifetime/heartbeat.js +11 -15
  103. package/dist/command/daemon/lifetime/startup-failure.d.ts +29 -0
  104. package/dist/command/daemon/lifetime/startup-failure.js +62 -0
  105. package/dist/command/daemon/port-state.d.ts +14 -0
  106. package/dist/command/daemon/port-state.js +31 -0
  107. package/dist/command/setup/agent-configs.d.ts +2 -0
  108. package/dist/command/setup/agent-configs.js +42 -15
  109. package/dist/command/setup/agent-next-steps.d.ts +77 -0
  110. package/dist/command/setup/agent-next-steps.js +284 -0
  111. package/dist/command/setup/agent-writer.js +11 -6
  112. package/dist/command/setup/bringup/dev-server-files.d.ts +9 -0
  113. package/dist/command/setup/bringup/dev-server-files.js +17 -0
  114. package/dist/command/setup/bringup/static-page-server.d.ts +14 -2
  115. package/dist/command/setup/bringup/static-page-server.js +43 -9
  116. package/dist/command/setup/init/init-host.js +2 -0
  117. package/dist/command/setup/init/init-runtime.d.ts +6 -1
  118. package/dist/command/setup/init/init-runtime.js +63 -21
  119. package/dist/command/setup/mcp-launcher.d.ts +3 -0
  120. package/dist/command/setup/mcp-launcher.js +11 -0
  121. package/dist/command/setup/node-effects.d.ts +3 -2
  122. package/dist/command/setup/node-effects.js +9 -3
  123. package/dist/command/setup/remaining-steps.d.ts +8 -0
  124. package/dist/command/setup/remaining-steps.js +10 -0
  125. package/dist/command/setup/run-setup.d.ts +2 -0
  126. package/dist/command/setup/run-setup.js +9 -1
  127. package/dist/command/setup/setup-command.js +36 -15
  128. package/dist/command/setup/setup-mcp.d.ts +8 -0
  129. package/dist/command/setup/setup-mcp.js +47 -20
  130. package/dist/command/setup/start-dev-server.d.ts +8 -0
  131. package/dist/command/setup/start-dev-server.js +43 -0
  132. package/dist/command/update/updater.js +6 -0
  133. package/dist/command/version/identity/server-version.d.ts +2 -0
  134. package/dist/command/version/identity/server-version.js +2 -0
  135. package/dist/command/version/version-skew.d.ts +7 -0
  136. package/dist/command/version/version-skew.js +14 -3
  137. package/dist/features/compare/action-plan.d.ts +260 -0
  138. package/dist/features/compare/action-plan.js +543 -0
  139. package/dist/features/compare/behaviour-compare.d.ts +24 -0
  140. package/dist/features/compare/behaviour-compare.js +85 -0
  141. package/dist/features/compare/behaviour-diff.d.ts +97 -0
  142. package/dist/features/compare/behaviour-diff.js +202 -0
  143. package/dist/features/compare/behaviour-report.d.ts +40 -0
  144. package/dist/features/compare/behaviour-report.js +128 -0
  145. package/dist/features/compare/build-readings.d.ts +106 -0
  146. package/dist/features/compare/build-readings.js +250 -0
  147. package/dist/features/compare/compare-diff.d.ts +62 -0
  148. package/dist/features/compare/compare-diff.js +177 -0
  149. package/dist/features/compare/compare-report-html.d.ts +6 -0
  150. package/dist/features/compare/compare-report-html.js +102 -0
  151. package/dist/features/compare/compare-report.d.ts +15 -0
  152. package/dist/features/compare/compare-report.js +73 -0
  153. package/dist/features/compare/compare-run.d.ts +60 -0
  154. package/dist/features/compare/compare-run.js +123 -0
  155. package/dist/features/compare/outside/effect-lines.d.ts +26 -0
  156. package/dist/features/compare/outside/effect-lines.js +103 -0
  157. package/dist/features/compare/outside/state-sources.d.ts +76 -0
  158. package/dist/features/compare/outside/state-sources.js +164 -0
  159. package/dist/features/compare/outside/value-dictionary.d.ts +51 -0
  160. package/dist/features/compare/outside/value-dictionary.js +227 -0
  161. package/dist/features/compare/visible-content.d.ts +20 -0
  162. package/dist/features/compare/visible-content.js +125 -0
  163. package/dist/features/crawl/crawl-empty.js +2 -1
  164. package/dist/features/crawl/crawl-exhaustive.d.ts +55 -0
  165. package/dist/features/crawl/crawl-exhaustive.js +138 -0
  166. package/dist/features/crawl/crawl-tools.d.ts +9 -2
  167. package/dist/features/crawl/crawl-tools.js +28 -12
  168. package/dist/features/crawl/crawl.d.ts +8 -9
  169. package/dist/features/crawl/crawl.js +61 -65
  170. package/dist/features/exhaust/app-coverage.d.ts +5 -1
  171. package/dist/features/exhaust/app-coverage.js +3 -1
  172. package/dist/features/exhaust/code-coverage.js +8 -4
  173. package/dist/features/exhaust/edge-cases.d.ts +133 -0
  174. package/dist/features/exhaust/edge-cases.js +310 -0
  175. package/dist/features/exhaust/edges/edge-drive.d.ts +42 -0
  176. package/dist/features/exhaust/edges/edge-drive.js +364 -0
  177. package/dist/features/exhaust/edges/edge-run.d.ts +59 -0
  178. package/dist/features/exhaust/edges/edge-run.js +169 -0
  179. package/dist/features/exhaust/explorer.d.ts +87 -14
  180. package/dist/features/exhaust/explorer.js +159 -25
  181. package/dist/features/exhaust/failure-branches.d.ts +5 -0
  182. package/dist/features/exhaust/failure-branches.js +29 -11
  183. package/dist/features/exhaust/invariants.d.ts +112 -0
  184. package/dist/features/exhaust/invariants.js +188 -0
  185. package/dist/features/exhaust/ledger.d.ts +68 -0
  186. package/dist/features/exhaust/ledger.js +121 -13
  187. package/dist/features/exhaust/session-fold.d.ts +10 -0
  188. package/dist/features/exhaust/session-fold.js +46 -3
  189. package/dist/features/exhaust/session-port.d.ts +3 -1
  190. package/dist/features/exhaust/session-port.js +97 -28
  191. package/dist/features/grade/grade-answer.d.ts +99 -0
  192. package/dist/features/grade/grade-answer.js +112 -0
  193. package/dist/features/grade/grade-noise.d.ts +27 -0
  194. package/dist/features/grade/grade-noise.js +55 -0
  195. package/dist/features/grade/grade-renumber.d.ts +12 -0
  196. package/dist/features/grade/grade-renumber.js +86 -0
  197. package/dist/features/grade/grade-state.d.ts +50 -0
  198. package/dist/features/grade/grade-state.js +93 -0
  199. package/dist/features/grade/grade-suggest.d.ts +33 -0
  200. package/dist/features/grade/grade-suggest.js +98 -0
  201. package/dist/features/license/license.d.ts +11 -71
  202. package/dist/features/license/license.js +43 -136
  203. package/dist/features/visual/desktop-capture.d.ts +33 -0
  204. package/dist/features/visual/desktop-capture.js +94 -0
  205. package/dist/features/visual/step-shots.js +139 -35
  206. package/dist/features/visual/visual-tools.d.ts +0 -18
  207. package/dist/features/visual/visual-tools.js +67 -99
  208. package/dist/import-graph.js +5 -6
  209. package/dist/index.d.ts +3 -1
  210. package/dist/index.js +19 -7
  211. package/dist/judgement/capsule/causal-summary.js +9 -2
  212. package/dist/judgement/runs/artifact/replay-mapping.d.ts +13 -1
  213. package/dist/judgement/runs/artifact/replay-mapping.js +1 -1
  214. package/dist/judgement/runs/reticle-runner.js +16 -2
  215. package/dist/judgement/runs/run-ledger.d.ts +7 -5
  216. package/dist/judgement/runs/run-ledger.js +98 -69
  217. package/dist/judgement/runs/runner-port.d.ts +2 -0
  218. package/dist/judgement/runs/runner-port.js +23 -5
  219. package/dist/judgement/runs/verification-sync.d.ts +6 -3
  220. package/dist/judgement/runs/verification-sync.js +21 -10
  221. package/dist/language/flows/affected-tools.d.ts +1 -1
  222. package/dist/language/flows/affected-tools.js +49 -30
  223. package/dist/language/flows/change/git-changed.d.ts +2 -1
  224. package/dist/language/flows/change/git-changed.js +19 -2
  225. package/dist/language/flows/fields/flow-secret-field.d.ts +1 -13
  226. package/dist/language/flows/fields/flow-secret-field.js +77 -21
  227. package/dist/language/flows/flow-anchor.d.ts +60 -2
  228. package/dist/language/flows/flow-anchor.js +125 -20
  229. package/dist/language/flows/flow-classify.d.ts +20 -0
  230. package/dist/language/flows/flow-classify.js +90 -12
  231. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  232. package/dist/language/flows/flow-cross-step.js +25 -1
  233. package/dist/language/flows/flow-journey.d.ts +38 -4
  234. package/dist/language/flows/flow-journey.js +138 -8
  235. package/dist/language/flows/flow-replay-run.d.ts +0 -16
  236. package/dist/language/flows/flow-replay-run.js +76 -14
  237. package/dist/language/flows/flow-replay-types.d.ts +4 -2
  238. package/dist/language/flows/flow-replay.d.ts +19 -1
  239. package/dist/language/flows/flow-replay.js +169 -52
  240. package/dist/language/flows/flow-replayable.js +7 -1
  241. package/dist/language/flows/flow-start-path.d.ts +34 -5
  242. package/dist/language/flows/flow-start-path.js +202 -15
  243. package/dist/language/flows/flow-step-runners.d.ts +14 -13
  244. package/dist/language/flows/flow-step-runners.js +184 -109
  245. package/dist/language/flows/flow-store-for-session.d.ts +26 -25
  246. package/dist/language/flows/flow-store-for-session.js +51 -5
  247. package/dist/language/flows/flow-tools.js +46 -33
  248. package/dist/language/flows/flows.js +176 -76
  249. package/dist/language/flows/recording/tape/recordings.d.ts +21 -16
  250. package/dist/language/flows/recording/tape/recordings.js +112 -49
  251. package/dist/language/flows/replay.d.ts +36 -12
  252. package/dist/language/flows/replay.js +193 -50
  253. package/dist/language/flows/steps/page-steps.d.ts +68 -0
  254. package/dist/language/flows/steps/page-steps.js +198 -0
  255. package/dist/language/flows/suite/sequential-run.d.ts +68 -0
  256. package/dist/language/flows/suite/sequential-run.js +96 -0
  257. package/dist/language/flows/verify-change-tools.js +26 -15
  258. package/dist/launch-chromium.d.ts +1 -0
  259. package/dist/launch-chromium.js +49 -12
  260. package/dist/memory/cloud/background-sync.d.ts +13 -0
  261. package/dist/memory/cloud/background-sync.js +24 -3
  262. package/dist/memory/cloud/sync-daemon.js +26 -27
  263. package/dist/memory/cloud/sync-screenshots.js +6 -1
  264. package/dist/memory/journal/attach-journal.js +2 -1
  265. package/dist/memory/journal/drive-flow.d.ts +7 -0
  266. package/dist/memory/journal/drive-flow.js +44 -13
  267. package/dist/memory/journal/journal-recorder.d.ts +4 -2
  268. package/dist/memory/journal/session-journal.d.ts +7 -0
  269. package/dist/memory/journal/session-journal.js +58 -10
  270. package/dist/memory/project/root-claims.d.ts +9 -0
  271. package/dist/memory/project/root-claims.js +9 -4
  272. package/dist/portal/bridge/bridge.d.ts +13 -4
  273. package/dist/portal/bridge/bridge.js +10 -9
  274. package/dist/portal/input/download-capture.d.ts +7 -0
  275. package/dist/portal/input/download-capture.js +92 -0
  276. package/dist/portal/input/network-detail.d.ts +6 -0
  277. package/dist/portal/input/network-detail.js +12 -1
  278. package/dist/portal/input/network-mock-tools.js +49 -13
  279. package/dist/portal/input/network-mock.d.ts +8 -0
  280. package/dist/portal/input/network-mock.js +30 -10
  281. package/dist/portal/input/page-capture.d.ts +24 -0
  282. package/dist/portal/input/page-capture.js +33 -0
  283. package/dist/portal/input/real-input.d.ts +35 -18
  284. package/dist/portal/input/real-input.js +99 -33
  285. package/dist/portal/input/viewport-tools.d.ts +8 -0
  286. package/dist/portal/input/viewport-tools.js +81 -21
  287. package/dist/portal/pool/browser-pool.d.ts +16 -30
  288. package/dist/portal/pool/browser-pool.js +64 -52
  289. package/dist/portal/pool/context-permissions.d.ts +34 -17
  290. package/dist/portal/pool/context-permissions.js +94 -1
  291. package/dist/portal/pool/csp-widen.d.ts +62 -0
  292. package/dist/portal/pool/csp-widen.js +132 -0
  293. package/dist/portal/pool/determinism.d.ts +52 -0
  294. package/dist/portal/pool/determinism.js +259 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +34 -1
  296. package/dist/portal/pool/lease-emulation.js +18 -0
  297. package/dist/portal/pool/lease-marker-stamp.d.ts +6 -0
  298. package/dist/portal/pool/lease-marker-stamp.js +15 -1
  299. package/dist/portal/pool/lease-page-error.d.ts +56 -0
  300. package/dist/portal/pool/lease-page-error.js +160 -0
  301. package/dist/portal/pool/page-error-journal.d.ts +63 -0
  302. package/dist/portal/pool/page-error-journal.js +208 -0
  303. package/dist/portal/pool/playwright-launcher.js +71 -15
  304. package/dist/portal/pool/pool-contract.d.ts +49 -1
  305. package/dist/portal/pool/pool-lease.d.ts +70 -2
  306. package/dist/portal/pool/pool-lease.js +23 -0
  307. package/dist/portal/pool/zero-install.d.ts +8 -0
  308. package/dist/portal/pool/zero-install.js +91 -1
  309. package/dist/portal/session/dev-server/dev-command.d.ts +11 -2
  310. package/dist/portal/session/dev-server/dev-command.js +110 -16
  311. package/dist/portal/session/dev-server/dev-server-probe.d.ts +7 -0
  312. package/dist/portal/session/dev-server/dev-server-probe.js +9 -0
  313. package/dist/portal/session/dev-server/project-ports.d.ts +21 -0
  314. package/dist/portal/session/dev-server/project-ports.js +62 -0
  315. package/dist/portal/session/facts/departed-network.d.ts +66 -0
  316. package/dist/portal/session/facts/departed-network.js +142 -0
  317. package/dist/portal/session/no-session-diagnosis.d.ts +9 -0
  318. package/dist/portal/session/no-session-diagnosis.js +76 -27
  319. package/dist/portal/session/no-session-next-action.d.ts +14 -0
  320. package/dist/portal/session/no-session-next-action.js +56 -7
  321. package/dist/portal/session/no-session-watch.d.ts +6 -0
  322. package/dist/portal/session/no-session-watch.js +41 -4
  323. package/dist/portal/session/page-commands/undeclared-command.d.ts +9 -3
  324. package/dist/portal/session/page-commands/undeclared-command.js +16 -7
  325. package/dist/portal/session/recorded-gaps.d.ts +1 -1
  326. package/dist/portal/session/recorded-gaps.js +5 -2
  327. package/dist/portal/session/serving-directory.d.ts +10 -0
  328. package/dist/portal/session/serving-directory.js +39 -8
  329. package/dist/portal/session/session-manager.d.ts +10 -0
  330. package/dist/portal/session/session-manager.js +211 -81
  331. package/dist/portal/session/session.js +4 -3
  332. package/dist/portal/session/zero-install-first-call.d.ts +20 -1
  333. package/dist/portal/session/zero-install-first-call.js +34 -2
  334. package/dist/start-wiring.d.ts +30 -2
  335. package/dist/start-wiring.js +74 -9
  336. package/dist/surface/mcp/mcp-proxy.js +10 -2
  337. package/dist/surface/mcp/mcp.js +8 -5
  338. package/dist/surface/mcp/peer/agents-connected.d.ts +6 -0
  339. package/dist/surface/mcp/peer/agents-connected.js +58 -0
  340. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +17 -5
  341. package/dist/surface/mcp/shared-params.d.ts +2 -0
  342. package/dist/surface/mcp/shared-params.js +31 -0
  343. package/dist/surface/tools/act/act-observation.d.ts +40 -2
  344. package/dist/surface/tools/act/act-observation.js +118 -12
  345. package/dist/surface/tools/act/act-preflight.js +38 -18
  346. package/dist/surface/tools/act/act-sequence-retry.d.ts +23 -2
  347. package/dist/surface/tools/act/act-sequence-retry.js +61 -5
  348. package/dist/surface/tools/act/act-target.js +3 -1
  349. package/dist/surface/tools/act/after-match.d.ts +10 -0
  350. package/dist/surface/tools/act/after-match.js +40 -0
  351. package/dist/surface/tools/act/already-true.js +1 -1
  352. package/dist/surface/tools/act/navigation/reload-result.d.ts +12 -1
  353. package/dist/surface/tools/act/navigation/reload-result.js +25 -2
  354. package/dist/surface/tools/act/resolve-target.d.ts +17 -1
  355. package/dist/surface/tools/act/resolve-target.js +59 -9
  356. package/dist/surface/tools/act/sequence-grade.d.ts +15 -1
  357. package/dist/surface/tools/act/sequence-grade.js +45 -27
  358. package/dist/surface/tools/act/settle-in-flight.js +27 -15
  359. package/dist/surface/tools/act-command.d.ts +23 -0
  360. package/dist/surface/tools/act-command.js +50 -0
  361. package/dist/surface/tools/act-sequence-tool.js +81 -50
  362. package/dist/surface/tools/act-tools.d.ts +1 -13
  363. package/dist/surface/tools/act-tools.js +83 -95
  364. package/dist/surface/tools/agent/build-staleness.d.ts +1 -1
  365. package/dist/surface/tools/agent/build-staleness.js +1 -1
  366. package/dist/surface/tools/assert/assert-verdict.js +18 -12
  367. package/dist/surface/tools/browser-tools.js +87 -13
  368. package/dist/surface/tools/compare-tools.d.ts +11 -0
  369. package/dist/surface/tools/compare-tools.js +94 -0
  370. package/dist/surface/tools/coverage-tools.js +1 -1
  371. package/dist/surface/tools/dynamic-tools.js +11 -3
  372. package/dist/surface/tools/empty-session-list.d.ts +2 -0
  373. package/dist/surface/tools/empty-session-list.js +4 -2
  374. package/dist/surface/tools/error-recovery.d.ts +12 -1
  375. package/dist/surface/tools/error-recovery.js +131 -40
  376. package/dist/surface/tools/explore-tools.js +1 -1
  377. package/dist/surface/tools/invoke-tool.js +29 -21
  378. package/dist/surface/tools/lease-coverage-tools.d.ts +49 -0
  379. package/dist/surface/tools/lease-coverage-tools.js +128 -0
  380. package/dist/surface/tools/lease-hint.d.ts +42 -1
  381. package/dist/surface/tools/lease-hint.js +52 -3
  382. package/dist/surface/tools/lease-readiness.d.ts +47 -0
  383. package/dist/surface/tools/lease-readiness.js +126 -0
  384. package/dist/surface/tools/lease-seed.d.ts +16 -1
  385. package/dist/surface/tools/lease-seed.js +37 -4
  386. package/dist/surface/tools/lease-tools.d.ts +3 -41
  387. package/dist/surface/tools/lease-tools.js +104 -124
  388. package/dist/surface/tools/lease-url-identity.d.ts +46 -0
  389. package/dist/surface/tools/lease-url-identity.js +97 -0
  390. package/dist/surface/tools/merge-tools.js +99 -2
  391. package/dist/surface/tools/merged-name-redirect.js +5 -1
  392. package/dist/surface/tools/observe-tools.js +15 -9
  393. package/dist/surface/tools/read/console-pre-attach.d.ts +19 -0
  394. package/dist/surface/tools/read/console-pre-attach.js +23 -0
  395. package/dist/surface/tools/read-tools.js +33 -30
  396. package/dist/surface/tools/real-input-attempt.d.ts +0 -8
  397. package/dist/surface/tools/real-input-attempt.js +143 -28
  398. package/dist/surface/tools/repeat-hint.d.ts +40 -0
  399. package/dist/surface/tools/repeat-hint.js +171 -0
  400. package/dist/surface/tools/run-report.d.ts +2 -2
  401. package/dist/surface/tools/run-report.js +27 -15
  402. package/dist/surface/tools/session-ports.d.ts +14 -0
  403. package/dist/surface/tools/session-ports.js +53 -0
  404. package/dist/surface/tools/tool-kit.d.ts +18 -0
  405. package/dist/surface/tools/tool-kit.js +9 -3
  406. package/dist/surface/tools/tool-surface.js +0 -1
  407. package/dist/surface/tools/tools.js +54 -18
  408. package/dist/surface/tools/type-spelling.d.ts +13 -0
  409. package/dist/surface/tools/type-spelling.js +36 -0
  410. package/dist/telemetry/agent-client.d.ts +6 -0
  411. package/dist/telemetry/agent-client.js +10 -0
  412. package/dist/telemetry/argument-shape.js +17 -7
  413. package/dist/telemetry/cli-telemetry.d.ts +10 -1
  414. package/dist/telemetry/cli-telemetry.js +15 -0
  415. package/dist/telemetry/init-telemetry.d.ts +2 -1
  416. package/dist/telemetry/init-telemetry.js +47 -2
  417. package/dist/telemetry/install-trace.js +23 -4
  418. package/dist/telemetry/onboarding-funnel.d.ts +19 -2
  419. package/dist/telemetry/onboarding-funnel.js +25 -3
  420. package/dist/telemetry/proxy-telemetry.d.ts +2 -1
  421. package/dist/telemetry/proxy-telemetry.js +2 -2
  422. package/dist/telemetry/session-metrics.d.ts +1 -1
  423. package/dist/telemetry/session-metrics.js +67 -27
  424. package/dist/telemetry/telemetry.d.ts +3 -1
  425. package/dist/telemetry/telemetry.js +60 -28
  426. package/dist/telemetry/tool-refused.d.ts +6 -3
  427. package/dist/telemetry/tool-refused.js +15 -3
  428. package/docs/actions.mdx +3 -3
  429. package/docs/agent-cheatsheet.md +1 -1
  430. package/docs/architecture.md +3 -6
  431. package/docs/capabilities.mdx +61 -1
  432. package/docs/cli/affected.mdx +9 -7
  433. package/docs/cli/cloud.mdx +3 -3
  434. package/docs/cli/compare.mdx +94 -0
  435. package/docs/cli/doctor.mdx +41 -2
  436. package/docs/cli/grade.mdx +97 -0
  437. package/docs/cli/help.mdx +4 -2
  438. package/docs/cli/license.mdx +13 -12
  439. package/docs/cli/restart.mdx +7 -5
  440. package/docs/cli/rollback.mdx +5 -5
  441. package/docs/cli/setup.mdx +13 -2
  442. package/docs/cli/status.mdx +4 -0
  443. package/docs/cli/stop.mdx +3 -3
  444. package/docs/cli/update.mdx +2 -2
  445. package/docs/cli/verify.mdx +23 -1
  446. package/docs/cli.mdx +34 -24
  447. package/docs/deploy-checks.md +25 -0
  448. package/docs/desktop.mdx +1 -1
  449. package/docs/enterprise.md +17 -22
  450. package/docs/environment.mdx +1 -0
  451. package/docs/first-drive.md +1 -1
  452. package/docs/flows.md +11 -1
  453. package/docs/frameworks.mdx +9 -9
  454. package/docs/getting-started.md +1 -1
  455. package/docs/install-manual.mdx +16 -1
  456. package/docs/license-activation.mdx +3 -3
  457. package/docs/packages/engine.mdx +1 -1
  458. package/docs/packages/server.mdx +1 -1
  459. package/docs/packages/tauri.mdx +1 -1
  460. package/docs/packages/test.mdx +1 -1
  461. package/docs/packages.mdx +1 -1
  462. package/docs/platform-integration.md +1 -1
  463. package/docs/predicates.mdx +1 -1
  464. package/docs/quickstart.mdx +68 -49
  465. package/docs/skill-setup.md +1 -1
  466. package/docs/skill.md +14 -13
  467. package/docs/telemetry.md +6 -4
  468. package/docs/tools/navigate.mdx +1 -1
  469. package/docs/tools/verify.mdx +4 -1
  470. package/docs/troubleshooting.mdx +1 -1
  471. package/docs/usage.md +17 -14
  472. package/package.json +18 -14
  473. package/LICENSE-ENTERPRISE +0 -37
  474. package/dist/features/ee/audit-log.d.ts +0 -14
  475. package/dist/features/ee/audit-log.js +0 -11
  476. package/dist/features/exhaust/exhaust-run.d.ts +0 -33
  477. package/dist/features/exhaust/exhaust-run.js +0 -82
@@ -9,6 +9,7 @@ import { type ChangedFiles } from '../../language/flows/change/git-changed.js';
9
9
  import { type ProjectId } from '@reticlehq/core';
10
10
  import { type FileSystemPort } from '../../memory/project/fs/fs-port.js';
11
11
  import { type NamedFlow } from '../../language/flows/change/flow-sources.js';
12
+ import { type GateCompleted } from '@reticlehq/core/telemetry';
12
13
  /** Load the {name, steps} of every saved flow for the active project. */
13
14
  /** Explicit files plus, when --since is given, the git-changed files since that ref. */
14
15
  /**
@@ -30,4 +31,9 @@ export declare function handleGate(files: string[], since: string | undefined,
30
31
  /** Hook mode: prose for a human, and silence when there was simply nothing to check. */
31
32
  hook?: boolean,
32
33
  /** Accept today's coverage levels as the best before judging, for a drop that was intended. */
33
- acceptCoverage?: boolean): Promise<void>;
34
+ acceptCoverage?: boolean,
35
+ /**
36
+ * Called once with how the gate ended, on every path. `cli.ts` passes the `gate_completed`
37
+ * sender: telemetry already reaches this directory, so this directory does not reach back.
38
+ */
39
+ reportGateCompleted?: (gate: GateCompleted) => void): Promise<void>;
@@ -5,7 +5,7 @@
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, MSG_GATE_NO_FLOWS, msgGateRegression, msgGateRefused, gateExitWith, } from './answers/gate-exit.js';
8
+ import { GATE_OUTCOME, GateExit, MSG_GATE_NO_FLOWS, msgGateRegression, msgGateRefused, gateExitWith, } from './answers/gate-exit.js';
9
9
  import { knownRegression } from './known-regression.js';
10
10
  import { gateHookMessage, GATE_SKIP_ENV } from './answers/gate-hook-message.js';
11
11
  import { readProjectId } from './ports/resolve/cli-port.js';
@@ -13,6 +13,7 @@ import { changedFilesSince } from '../../language/flows/change/git-changed.js';
13
13
  import { isAbsolute, join, sep } from 'node:path';
14
14
  import { ReticleDir } from '@reticlehq/core';
15
15
  import { FlowStore } from '../../language/flows/flows.js';
16
+ import { namedFlowsIn } from '../../language/flows/flow-store-for-session.js';
16
17
  import { RunStore } from '../../judgement/runs/artifact/run-store.js';
17
18
  import { createNodeFileSystem } from '../../memory/project/fs/fs-port.js';
18
19
  import { affectedSavedFlows, toFlowSources, } from '../../language/flows/change/flow-sources.js';
@@ -25,6 +26,7 @@ import { detectDowngrades } from '../../judgement/outcome/assertion-integrity.js
25
26
  import { computeCoverage, flowCoverageReport } from '../../language/flows/suite/coverage.js';
26
27
  import { readFileSync, statSync } from 'node:fs';
27
28
  import { log } from '../../log.js';
29
+ import { GateOutcome } from '@reticlehq/core/telemetry';
28
30
  /** Load the {name, steps} of every saved flow for the active project. */
29
31
  /** Explicit files plus, when --since is given, the git-changed files since that ref. */
30
32
  /**
@@ -34,8 +36,9 @@ import { log } from '../../log.js';
34
36
  */
35
37
  export async function resolveChangedFiles(files, since, cwd) {
36
38
  // No ref means no question was asked of git, which is not a failure to answer one.
37
- if (since === undefined)
39
+ if (since === undefined) {
38
40
  return { files, failed: false };
41
+ }
39
42
  const changed = await changedFilesSince(since, cwd);
40
43
  return {
41
44
  files: [...new Set([...files, ...changed.files])],
@@ -52,14 +55,7 @@ export async function resolveChangedFiles(files, since, cwd) {
52
55
  * confident negative about somebody else's project, which is worse than an error.
53
56
  */
54
57
  export async function loadNamedFlows(fs, reticleRoot, projectId) {
55
- const store = new FlowStore(fs, reticleRoot, { now: () => Date.now() });
56
- const flows = [];
57
- for (const name of await store.list(projectId)) {
58
- const loaded = await store.load(name, projectId);
59
- if (loaded.ok)
60
- flows.push({ name: loaded.value.name, steps: loaded.value.steps });
61
- }
62
- return flows;
58
+ return await namedFlowsIn(new FlowStore(fs, reticleRoot, { now: () => Date.now() }), projectId);
63
59
  }
64
60
  /**
65
61
  * `reticle gate <file...>` — exit non-zero unless passing artifacts cover the flows affected by the
@@ -81,8 +77,9 @@ function atChangedPath(cwd, file, read) {
81
77
  return undefined;
82
78
  }
83
79
  };
84
- if (isAbsolute(file))
80
+ if (isAbsolute(file)) {
85
81
  return attempt(file);
82
+ }
86
83
  const parts = file.split('/');
87
84
  const cwdParts = cwd.split(sep);
88
85
  for (let i = 0; i < parts.length; i += 1) {
@@ -91,8 +88,9 @@ function atChangedPath(cwd, file, read) {
91
88
  continue;
92
89
  }
93
90
  const found = attempt(join(cwd, ...parts.slice(i)));
94
- if (found !== undefined)
91
+ if (found !== undefined) {
95
92
  return found;
93
+ }
96
94
  }
97
95
  return undefined;
98
96
  }
@@ -122,8 +120,9 @@ async function currentPassing(fs, root, flows, affected, changed) {
122
120
  const own = 0 === sources.length ? changed : changed.filter((f) => sourceMatchesChange(f, sources));
123
121
  const stale = affected.includes(name) &&
124
122
  own.some((f) => !((changedFileModifiedAt(cwd, f) ?? Infinity) < at));
125
- if (!stale)
123
+ if (!stale) {
126
124
  passing.push(name);
125
+ }
127
126
  }
128
127
  return passing;
129
128
  }
@@ -131,7 +130,12 @@ export async function handleGate(files, since,
131
130
  /** Hook mode: prose for a human, and silence when there was simply nothing to check. */
132
131
  hook = false,
133
132
  /** Accept today's coverage levels as the best before judging, for a drop that was intended. */
134
- acceptCoverage = false) {
133
+ acceptCoverage = false,
134
+ /**
135
+ * Called once with how the gate ended, on every path. `cli.ts` passes the `gate_completed`
136
+ * sender: telemetry already reaches this directory, so this directory does not reach back.
137
+ */
138
+ reportGateCompleted = () => undefined) {
135
139
  try {
136
140
  const fs = createNodeFileSystem();
137
141
  const reticleRoot = join(process.cwd(), ReticleDir.ROOT);
@@ -207,13 +211,17 @@ acceptCoverage = false) {
207
211
  // once the exit code is: it said "pass": true over an exit of 1 or 3.
208
212
  const known = await knownRegression(reticleRoot);
209
213
  const regressed = known.broken;
210
- const local = pass
211
- ? GateExit.PASS
212
- : result.pass && flowCoverage.outcome !== undefined
213
- ? GateExit.NOTHING_TO_CHECK
214
- : GateExit.FAIL;
214
+ let local = GateExit.FAIL;
215
+ if (pass) {
216
+ local = GateExit.PASS;
217
+ }
218
+ else if (result.pass && flowCoverage.outcome !== undefined) {
219
+ local = GateExit.NOTHING_TO_CHECK;
220
+ }
215
221
  // Fails closed in CI, not in an agent's stop hook, where it would block over a key, not a change.
216
222
  const code = gateExitWith(local, regressed?.length, !hook && known.refused !== undefined);
223
+ // What the gate judged, sent before a hook's skip can turn the exit code into a pass.
224
+ reportGateCompleted({ outcome: GATE_OUTCOME[code], flowsChecked: affected.length });
217
225
  log('reticle_gate', {
218
226
  pass: GateExit.PASS === code,
219
227
  uncovered: result.uncovered,
@@ -237,14 +245,18 @@ acceptCoverage = false) {
237
245
  // A regression the platform already knows fails the build here too, with `reticle runs
238
246
  // regression`'s code, so the gate is the one command CI needs. Best-effort: unlinked or offline
239
247
  // changes nothing.
240
- if (regressed !== undefined && 0 < regressed.length)
248
+ if (regressed !== undefined && 0 < regressed.length) {
241
249
  log('reticle_gate_regression', { broken: regressed });
242
- if (known.refused !== undefined)
250
+ }
251
+ if (known.refused !== undefined) {
243
252
  process.stderr.write(`${msgGateRefused(known.refused)}\n`);
244
- if (GateExit.NOTHING_TO_CHECK === code && !hook)
253
+ }
254
+ if (GateExit.NOTHING_TO_CHECK === code && !hook) {
245
255
  process.stderr.write(`${MSG_GATE_NO_FLOWS}\n`);
246
- if (GateExit.REGRESSION === code && !hook && regressed !== undefined)
256
+ }
257
+ if (GateExit.REGRESSION === code && !hook && regressed !== undefined) {
247
258
  process.stderr.write(`${msgGateRegression(regressed)}\n`);
259
+ }
248
260
  if (GateExit.PASS !== code) {
249
261
  process.exitCode = code;
250
262
  if (hook) {
@@ -267,13 +279,16 @@ acceptCoverage = false) {
267
279
  unexecuted: result.unexecuted,
268
280
  regressed: regressed?.length ?? 0,
269
281
  });
270
- if (message !== undefined)
282
+ if (message !== undefined) {
271
283
  process.stderr.write(`${message}\n`);
284
+ }
272
285
  }
273
286
  }
274
287
  }
275
288
  catch (error) {
276
289
  log('reticle_gate_failed', { error: error instanceof Error ? error.message : String(error) });
290
+ // No flow count: the gate broke before it judged, so a count would describe nothing.
291
+ reportGateCompleted({ outcome: GateOutcome.ERROR });
277
292
  process.exitCode = GateExit.FAIL;
278
293
  }
279
294
  }
@@ -17,6 +17,7 @@
17
17
  * written, or belongs to a daemon from another checkout. `kill` asks the PORT, which is the thing the
18
18
  * user actually wants freed, and falls back to the pid file only where the lookup cannot run.
19
19
  */
20
+ import { PortPresence } from '../daemon/binding/port-presence.js';
20
21
  import { type PortHolder } from './ports/port-holder.js';
21
22
  /** What the plan says to do with the port. */
22
23
  export declare const KillAction: {
@@ -62,6 +63,26 @@ export declare function planKill(input: {
62
63
  * wrong token, or no answer: the caller then sends the signal as before.
63
64
  */
64
65
  export declare function requestShutdown(port: number, token?: string | undefined): Promise<boolean>;
66
+ /**
67
+ * How long the second look waits for `/status`. The usual probe gives up after 1 second, and on a
68
+ * busy machine a healthy daemon took longer than that. A daemon that answers slowly is busy, not
69
+ * stuck, and other agents can use it.
70
+ */
71
+ export declare const WEDGED_STATUS_TIMEOUT_MS = 10000;
72
+ /**
73
+ * Stop a Reticle daemon that holds `port` and does not answer. True when it stopped one (#1937).
74
+ *
75
+ * The MCP proxy used to move to another port when it found one. The app's SDK dials the old port,
76
+ * so the new daemon got no page. Stopping the stuck daemon keeps the port the app dials. The holder
77
+ * must have a Reticle daemon's command line, so a stranger and the proxy itself are never signalled.
78
+ */
79
+ export declare function stopWedgedDaemon(port: number, deps?: {
80
+ /** `statusTimeoutMs`: how long to wait for `/status`. Absent: the usual short probe. */
81
+ presence: (statusTimeoutMs?: number) => Promise<PortPresence>;
82
+ holder: () => PortHolder | null;
83
+ kill: () => Promise<boolean>;
84
+ wait: (ms: number) => Promise<void>;
85
+ }): Promise<boolean>;
65
86
  /** `reticle kill` — free the port. Resolves to whether the port is now free. */
66
87
  export declare function runKill(port: number, force: boolean): Promise<boolean>;
67
88
  export {};
@@ -22,7 +22,8 @@ import { isAlive, readPid, removePid } from '../daemon/daemon.js';
22
22
  import { probeDaemon } from '../../surface/mcp/mcp-proxy.js';
23
23
  import { log } from '../../log.js';
24
24
  import { fetchStatus } from '../daemon/binding/daemon-status-probe.js';
25
- import { captureLookup, findPortHolder } from './ports/port-holder.js';
25
+ import { captureLookup } from './ports/port-holder.js';
26
+ import { identifyPortHolder } from '../daemon/port-state.js';
26
27
  import * as http from 'node:http';
27
28
  import { LOOPBACK_HOST, SHUTDOWN_PATH } from '@reticlehq/core';
28
29
  import { storedPairingToken } from '../../portal/bridge/pairing-token.js';
@@ -50,7 +51,8 @@ export function planKill(input) {
50
51
  return { action: KillAction.NOTHING, forced: false, identifiedListener: false };
51
52
  return { action: KillAction.KILL, pid: recordedPid, forced: false, identifiedListener: false };
52
53
  }
53
- const ours = answersStatus || listener.pid === recordedPid;
54
+ // `reticleDaemon`: its command line says so, though it answers nothing and no pid file names it.
55
+ const ours = answersStatus || listener.pid === recordedPid || true === listener.reticleDaemon;
54
56
  if (ours || force) {
55
57
  return {
56
58
  action: KillAction.KILL,
@@ -67,7 +69,7 @@ export function planKill(input) {
67
69
  holder: listener,
68
70
  reason: `pid ${String(listener.pid)} ("${listener.command}") is listening, and it is not a Reticle ` +
69
71
  `daemon — it never answered /status and it is not the pid Reticle recorded. Killing it would ` +
70
- `be killing someone else's process. If that is what you meant, \`reticle restart ${FORCE_FLAG}\` ` +
72
+ `be killing someone else's process. If that is what you meant, \`reticle serve --restart ${FORCE_FLAG}\` ` +
71
73
  `stops it and starts Reticle there (\`stop ${FORCE_FLAG}\` never does); or start Reticle on ` +
72
74
  `another port.`,
73
75
  };
@@ -156,12 +158,53 @@ async function terminate(pid, asked = false) {
156
158
  */
157
159
  const PROXY_SPARED_NOTE = 'only the listener was signalled. Any `reticle mcp` proxy on this port holds a client connection, ' +
158
160
  'not the port, and was left alone — it goes dormant and starts a fresh daemon on the next tool call.';
161
+ /**
162
+ * How long a daemon that holds the port gets to answer before it counts as stuck. A daemon that has
163
+ * just bound answers in far less, so a second look after this does not stop one that is starting.
164
+ */
165
+ const WEDGED_GRACE_MS = 2_000;
166
+ /**
167
+ * How long the second look waits for `/status`. The usual probe gives up after 1 second, and on a
168
+ * busy machine a healthy daemon took longer than that. A daemon that answers slowly is busy, not
169
+ * stuck, and other agents can use it.
170
+ */
171
+ export const WEDGED_STATUS_TIMEOUT_MS = 10_000;
172
+ /**
173
+ * Stop a Reticle daemon that holds `port` and does not answer. True when it stopped one (#1937).
174
+ *
175
+ * The MCP proxy used to move to another port when it found one. The app's SDK dials the old port,
176
+ * so the new daemon got no page. Stopping the stuck daemon keeps the port the app dials. The holder
177
+ * must have a Reticle daemon's command line, so a stranger and the proxy itself are never signalled.
178
+ */
179
+ export async function stopWedgedDaemon(port, deps = {
180
+ presence: (statusTimeoutMs) => probePresence(port, {
181
+ tcpOpen: probeDaemon,
182
+ status: (p) => fetchStatus(p, LOOPBACK_HOST, false, statusTimeoutMs),
183
+ }),
184
+ holder: () => identifyPortHolder(port, captureLookup),
185
+ kill: () => runKill(port, false),
186
+ wait: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
187
+ }) {
188
+ if (PortPresence.FOREIGN !== (await deps.presence())) {
189
+ return false;
190
+ }
191
+ const holder = deps.holder();
192
+ if (true !== holder?.reticleDaemon) {
193
+ return false;
194
+ }
195
+ await deps.wait(WEDGED_GRACE_MS);
196
+ if (PortPresence.FOREIGN !== (await deps.presence(WEDGED_STATUS_TIMEOUT_MS))) {
197
+ return false;
198
+ }
199
+ log('reticle_wedged_daemon_stopping', { port, pid: holder.pid });
200
+ return deps.kill();
201
+ }
159
202
  /** `reticle kill` — free the port. Resolves to whether the port is now free. */
160
203
  export async function runKill(port, force) {
161
204
  const presence = await probePresence(port, { tcpOpen: probeDaemon, status: fetchStatus });
162
205
  const recorded = readPid(port);
163
206
  const plan = planKill({
164
- listener: findPortHolder(port, captureLookup),
207
+ listener: identifyPortHolder(port, captureLookup),
165
208
  recordedPid: null !== recorded && isAlive(recorded) ? recorded : null,
166
209
  answersStatus: presence === PortPresence.DAEMON,
167
210
  force,
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `reticle compare <reference-url> <candidate-url> [--base <url>] [--state <file>] [--json] [--report <file>]`. The
3
+ * command has one recipe. `--state` names the app's stored data to read, and `--port` names the
4
+ * daemon, as on every command that uses one.
5
+ *
6
+ * Split out of `cli-parse.ts` when that file came near the 1000-line cap.
7
+ */
8
+ import { type ParseError } from './cli-parse-grammar.js';
9
+ export declare const COMPARE_COMMAND = "compare";
10
+ export type CompareArgs = {
11
+ kind: 'ok';
12
+ reference: string;
13
+ candidate: string;
14
+ base?: string;
15
+ /** The path of the state sources file. */
16
+ state?: string;
17
+ /** Where to write the HTML report. */
18
+ report?: string;
19
+ json: boolean;
20
+ port: number;
21
+ } | ParseError;
22
+ export declare function parseCompareArgs(args: readonly string[], defaultPort: number): CompareArgs;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * `reticle compare <reference-url> <candidate-url> [--base <url>] [--state <file>] [--json] [--report <file>]`. The
3
+ * command has one recipe. `--state` names the app's stored data to read, and `--port` names the
4
+ * daemon, as on every command that uses one.
5
+ *
6
+ * Split out of `cli-parse.ts` when that file came near the 1000-line cap.
7
+ */
8
+ import { JSON_FLAG, PORT_FLAG, missingOperand, missingValue, notANumber, unknownArgument, } from './cli-parse-grammar.js';
9
+ export const COMPARE_COMMAND = 'compare';
10
+ /** `compare --base <url>`: the build before the change. */
11
+ const BASE_FLAG = '--base';
12
+ /** `compare --state <file.json>`: the declared state sources to read after each sequence. */
13
+ const STATE_FLAG = '--state';
14
+ /** `compare --report <file>`: also write the result as one HTML page. */
15
+ const REPORT_FLAG = '--report';
16
+ /** `compare` takes exactly a reference url and a candidate url. */
17
+ const COMPARE_URLS = 2;
18
+ export function parseCompareArgs(args, defaultPort) {
19
+ const urls = [];
20
+ let base;
21
+ let state;
22
+ let report;
23
+ let json = false;
24
+ let port = defaultPort;
25
+ for (let i = 0; i < args.length; i += 1) {
26
+ const arg = args[i] ?? '';
27
+ if (JSON_FLAG === arg) {
28
+ json = true;
29
+ continue;
30
+ }
31
+ if (BASE_FLAG === arg || STATE_FLAG === arg || REPORT_FLAG === arg || PORT_FLAG === arg) {
32
+ const value = args[i + 1];
33
+ if (value === undefined || value.startsWith('--')) {
34
+ return missingValue(arg);
35
+ }
36
+ i += 1;
37
+ if (BASE_FLAG === arg) {
38
+ base = value;
39
+ continue;
40
+ }
41
+ if (STATE_FLAG === arg) {
42
+ state = value;
43
+ continue;
44
+ }
45
+ if (REPORT_FLAG === arg) {
46
+ report = value;
47
+ continue;
48
+ }
49
+ const n = Number(value);
50
+ if (!Number.isInteger(n)) {
51
+ return notANumber(arg, value);
52
+ }
53
+ port = n;
54
+ continue;
55
+ }
56
+ if (arg.startsWith('--') || COMPARE_URLS === urls.length) {
57
+ return unknownArgument(arg);
58
+ }
59
+ urls.push(arg);
60
+ }
61
+ const [reference, candidate] = urls;
62
+ if (reference === undefined || candidate === undefined) {
63
+ return missingOperand(COMPARE_COMMAND, 'a reference url and a candidate url');
64
+ }
65
+ return {
66
+ kind: 'ok',
67
+ reference,
68
+ candidate,
69
+ ...(base === undefined ? {} : { base }),
70
+ ...(state === undefined ? {} : { state }),
71
+ ...(report === undefined ? {} : { report }),
72
+ json,
73
+ port,
74
+ };
75
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `reticle grade <snapshot|judge|tables|suggest> [flags]`: grade a finished run of an app from
3
+ * snapshots of its stored data. The rules are in `@/features/grade/`.
4
+ */
5
+ import { type ParseError } from './cli-parse-grammar.js';
6
+ export declare const GRADE_COMMAND = "grade";
7
+ export declare const GradeStep: {
8
+ readonly SNAPSHOT: "snapshot";
9
+ readonly JUDGE: "judge";
10
+ readonly TABLES: "tables";
11
+ readonly SUGGEST: "suggest";
12
+ };
13
+ export type GradeStep = (typeof GradeStep)[keyof typeof GradeStep];
14
+ /** Each flag that takes a value, and the field it fills. */
15
+ declare const VALUE_FLAGS: {
16
+ readonly '--state': "state";
17
+ readonly '--out': "out";
18
+ readonly '--url': "url";
19
+ readonly '--reference': "reference";
20
+ readonly '--again': "again";
21
+ readonly '--candidate': "candidate";
22
+ readonly '--expect': "expect";
23
+ readonly '--answer': "answer";
24
+ readonly '--list': "list";
25
+ readonly '--rows': "rows";
26
+ readonly '--container': "container";
27
+ readonly '--skip': "skip";
28
+ };
29
+ type GradeField = (typeof VALUE_FLAGS)[keyof typeof VALUE_FLAGS];
30
+ export type GradeArgs = ({
31
+ kind: 'ok';
32
+ step: GradeStep;
33
+ json: boolean;
34
+ } & Partial<Record<GradeField, string>>) | ParseError;
35
+ export declare function parseGradeArgs(args: readonly string[]): GradeArgs;
36
+ export {};
@@ -0,0 +1,75 @@
1
+ /**
2
+ * `reticle grade <snapshot|judge|tables|suggest> [flags]`: grade a finished run of an app from
3
+ * snapshots of its stored data. The rules are in `@/features/grade/`.
4
+ */
5
+ import { JSON_FLAG, missingOperand, missingValue, unknownArgument, } from './cli-parse-grammar.js';
6
+ export const GRADE_COMMAND = 'grade';
7
+ export const GradeStep = {
8
+ SNAPSHOT: 'snapshot',
9
+ JUDGE: 'judge',
10
+ TABLES: 'tables',
11
+ SUGGEST: 'suggest',
12
+ };
13
+ /** Each flag that takes a value, and the field it fills. */
14
+ const VALUE_FLAGS = {
15
+ '--state': 'state',
16
+ '--out': 'out',
17
+ '--url': 'url',
18
+ '--reference': 'reference',
19
+ '--again': 'again',
20
+ '--candidate': 'candidate',
21
+ '--expect': 'expect',
22
+ '--answer': 'answer',
23
+ '--list': 'list',
24
+ '--rows': 'rows',
25
+ '--container': 'container',
26
+ '--skip': 'skip',
27
+ };
28
+ /** The flags each step needs, and the flags it also takes. */
29
+ const STEP_FLAGS = {
30
+ [GradeStep.SNAPSHOT]: { needs: ['state', 'out'], takes: ['url'] },
31
+ [GradeStep.JUDGE]: {
32
+ needs: ['reference', 'again', 'candidate'],
33
+ takes: ['expect', 'answer'],
34
+ },
35
+ [GradeStep.TABLES]: { needs: ['list', 'rows', 'out'], takes: ['container', 'skip'] },
36
+ [GradeStep.SUGGEST]: { needs: ['state', 'reference', 'again', 'out'], takes: [] },
37
+ };
38
+ const isStep = (word) => Object.values(GradeStep).some((step) => step === word);
39
+ const isValueFlag = (arg) => arg in VALUE_FLAGS;
40
+ const flagOf = (field) => Object.keys(VALUE_FLAGS).find((f) => VALUE_FLAGS[f] === field) ??
41
+ field;
42
+ export function parseGradeArgs(args) {
43
+ const [step, ...rest] = args;
44
+ if (!isStep(step)) {
45
+ // A known flag before the step is a missing step, not an unknown flag.
46
+ return step === undefined || isValueFlag(step) || JSON_FLAG === step
47
+ ? missingOperand(GRADE_COMMAND, `a step first: ${Object.values(GradeStep).join(', ')}`)
48
+ : unknownArgument(step);
49
+ }
50
+ const allowed = new Set([...STEP_FLAGS[step].needs, ...STEP_FLAGS[step].takes]);
51
+ const values = {};
52
+ let json = false;
53
+ for (let i = 0; i < rest.length; i += 1) {
54
+ const arg = rest[i] ?? '';
55
+ if (JSON_FLAG === arg && GradeStep.JUDGE === step) {
56
+ json = true;
57
+ continue;
58
+ }
59
+ if (!isValueFlag(arg) || !allowed.has(VALUE_FLAGS[arg])) {
60
+ return unknownArgument(arg);
61
+ }
62
+ const value = rest[i + 1];
63
+ // An answer may start with "--"; every other value may not.
64
+ if (value === undefined || ('--answer' !== arg && value.startsWith('--'))) {
65
+ return missingValue(arg);
66
+ }
67
+ values[VALUE_FLAGS[arg]] = value;
68
+ i += 1;
69
+ }
70
+ const missing = STEP_FLAGS[step].needs.filter((field) => values[field] === undefined);
71
+ if (missing.length > 0) {
72
+ return missingOperand(`${GRADE_COMMAND} ${step}`, missing.map(flagOf).join(', '));
73
+ }
74
+ return { kind: 'ok', step, json, ...values };
75
+ }
@@ -26,6 +26,8 @@ export declare const missingOperand: (command: string, what: string) => ParseErr
26
26
  /** Show the browser. Shared by every command that can drive one. */
27
27
  export declare const HEADED_FLAG = "--headed";
28
28
  export declare const PORT_FLAG = "--port";
29
+ /** Print one JSON object. */
30
+ export declare const JSON_FLAG = "--json";
29
31
  export declare const VERIFY_COMMAND = "verify";
30
32
  /**
31
33
  * The predicate flag, shared for the same reason the rest of this file is: two places have to name
@@ -36,6 +36,8 @@ export const missingOperand = (command, what) => ({
36
36
  /** Show the browser. Shared by every command that can drive one. */
37
37
  export const HEADED_FLAG = '--headed';
38
38
  export const PORT_FLAG = '--port';
39
+ /** Print one JSON object. */
40
+ export const JSON_FLAG = '--json';
39
41
  export const VERIFY_COMMAND = 'verify';
40
42
  /**
41
43
  * The predicate flag, shared for the same reason the rest of this file is: two places have to name
@@ -49,37 +51,22 @@ export const EXPECT_FLAG = '--expect';
49
51
  * that the dispatcher and the telemetry vocabulary read one list instead of two.
50
52
  */
51
53
  export const CLOUD_COMMANDS = [
52
- 'login',
53
54
  'connect',
54
55
  'try',
55
56
  'logout',
56
- 'whoami',
57
- 'link',
58
- 'project',
59
57
  'config',
60
- 'issues',
61
- 'memory',
62
- 'push',
63
58
  'sync',
64
59
  'runs',
65
- 'regression',
66
- 'share',
67
60
  ];
68
61
  /**
69
62
  * Old command names that still run, for one release, under the name that replaced them. Each one
70
63
  * prints a single line saying so, then does what it always did.
71
64
  */
72
65
  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'],
66
+ ['affected', 'gate --list'],
67
+ ['license', 'status'],
68
+ ['rollback', 'update --rollback'],
69
+ ['restart', 'serve --restart'],
83
70
  ]);
84
71
  const HELP_FLAGS = new Set(['--help', '-h']);
85
72
  /**
@@ -98,13 +85,24 @@ export function renamedCommandFor(argv) {
98
85
  */
99
86
  export const REMOVED_COMMANDS = new Map([
100
87
  ['hunt', 'it has no replacement'],
101
- ['watch', 'use `reticle affected` after you save, or `reticle gate` before you commit'],
88
+ ['watch', 'use `reticle gate --list` after you save, or `reticle gate` before you commit'],
102
89
  ['capsules', 'it has no replacement; saved capsules stay in .reticle/capsules'],
103
90
  ['tutorial', "use `reticle init` in your app's folder, or `reticle try <url>`"],
104
91
  [
105
92
  'identify',
106
93
  'it has no replacement; delete ~/.reticle/identity.json to forget a saved identity, and use `reticle feedback` to reach us',
107
94
  ],
95
+ // Renamed one release earlier, and kept for that one release.
96
+ ['kill', 'use `reticle stop --force`'],
97
+ ['login', 'use `reticle connect`'],
98
+ ['link', 'use `reticle connect`'],
99
+ ['project', 'use `reticle connect --project <name|id>`'],
100
+ ['whoami', 'use `reticle status`'],
101
+ ['push', 'use `reticle sync`'],
102
+ ['regression', 'use `reticle runs regression`'],
103
+ ['share', 'use `reticle runs share <runId>`'],
104
+ ['issues', 'use `reticle runs issues`'],
105
+ ['memory', 'use `reticle runs memory`'],
108
106
  ]);
109
107
  export const removedNote = (command, instead) => `\`reticle ${command}\` was removed in this version; ${instead}`;
110
108
  const DIM = '\u001b[2m';
@@ -1,3 +1,9 @@
1
+ /** A missing step 1 control on a freshly loaded start page fails the flow (#2061). */
2
+ export declare const REQUIRE_START_CONTROL_FLAG = "--require-start-control";
3
+ /** Keep judging after a step whose consequence failed, so every step gets a verdict (the score). */
4
+ export declare const SWEEP_FLAG = "--sweep";
5
+ /** Compare the url with this reference build, and report each difference in what users see. */
6
+ export declare const AGAINST_FLAG = "--against";
1
7
  export type VerifySuffix = {
2
8
  kind: 'ok';
3
9
  url: string;
@@ -14,6 +20,10 @@ export type VerifySuffix = {
14
20
  select?: string[];
15
21
  resultsJson?: string;
16
22
  confirmDangerous?: boolean;
23
+ requireStartControl?: boolean;
24
+ sweep?: boolean;
25
+ /** The reference build's url, when the url is to be compared with it. */
26
+ against?: string;
17
27
  } | {
18
28
  kind: 'error';
19
29
  message: string;