@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
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: 'Quickstart: proof in five minutes'
3
3
  sidebarTitle: Quickstart
4
- description: Install Reticle, connect your coding agent, and get a real verdict with evidence in about five minutes.
4
+ description: Check your app with one command, connect your coding agent, and get a real verdict with evidence in about five minutes.
5
5
  icon: rocket
6
6
  ---
7
7
 
8
- **Run the installer once per machine, then `reticle init` once per project. The dashboard (`reticle connect`) is optional.** Skip `init` and your agent can still check the app with the zero-install lease, and it asks you before it wires the app. Reticle embeds a dev-only SDK in your running app and proves a browser session connected. No account needed for steps 1 and 2.
8
+ **Start with one command in your app's folder: `npx @reticlehq/server`.** It checks the running app with nothing installed and prints a verdict. Then `npx @reticlehq/server init`, once per project, connects your coding agent. The dashboard (`reticle connect`) is optional. No account is needed for steps 1 and 2.
9
9
 
10
10
  By the end of this page your agent will click a button in your app and prove what happened: the request that fired, the state that changed, and the file to open if it didn't.
11
11
 
@@ -18,52 +18,47 @@ By the end of this page your agent will click a button in your app and prove wha
18
18
 
19
19
  - Node 20.11 or newer
20
20
  - A web app you can run locally, and its dev server
21
- - A coding agent that speaks MCP (Claude Code, Cursor, Codex, OpenCode, Windsurf, VS Code)
21
+ - For step 2, a coding agent that speaks MCP (Claude Code, Cursor, Codex, OpenCode, Windsurf, VS Code)
22
22
 
23
- ## Step 1. Install it on this machine
23
+ ## Step 1. Check your app, with nothing installed
24
24
 
25
- In a terminal, before you open your coding agent:
25
+ In your app's folder:
26
26
 
27
- <CodeGroup>
28
-
29
- ```bash macOS / Linux
30
- curl -fsSL https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.sh | sh
27
+ ```bash
28
+ cd path/to/your-app
29
+ npx @reticlehq/server
31
30
  ```
32
31
 
33
- ```powershell Windows
34
- irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1 | iex
35
- ```
32
+ It finds your app's dev server. If the app does not run, it starts the dev script, and it stops that server at the end. It opens the app in a Reticle browser and installs nothing in your app. It checks that the page loads, that there is no console error and no failed request, and that each same-origin link opens (8 at most). On a small app with two links, it printed:
36
33
 
37
- </CodeGroup>
38
-
39
- This puts `reticle` on your PATH and registers the MCP server with every coding agent it can reach: Claude Code, Cursor, Windsurf, VS Code, Zed, Gemini CLI, Copilot CLI, OpenCode, Antigravity, Warp, Kiro, Amazon Q, Cline, Roo Code, Amp, Continue and Factory Droid. Nothing is asked. It does not wire your app, and says so: that is step 2. Want a verdict first? Signed in, `reticle try <url>` drives a URL once in a window you watch.
34
+ ```text
35
+ Starting your dev server: npm run dev
36
+ Reticle is checking http://localhost:58440/. It installs nothing in your app.
37
+ ✓ The page loads.
38
+ ✓ No console error.
39
+ ✓ No failed request.
40
+ ✓ 2 of 2 link(s) opened with no fault.
41
+ ```
40
42
 
41
- Codex CLI keeps a TOML config. With the `codex` command installed, the installer registers Reticle through `codex mcp add`. Without it, the installer prints the lines to paste and the file to paste them into. Reticle then adds one line, `default_tools_approval_mode = "approve"`, under `[mcp_servers.reticle]` in `~/.codex/config.toml`. This line approves Reticle's own tools, so Codex does not ask before each call. Reticle changes no other line, and it keeps a mode that you set. To undo it, change that line to `default_tools_approval_mode = "prompt"`. Reticle does not change a mode that is already there.
43
+ Then the verdict line, `verified: yes` with the URL it checked, and the next step, `npx @reticlehq/server init`. A fault gives `verified: no`, and one `✗` line for each fault, for example `✗ Failed request on /broken: GET http://localhost:58473/api/missing: HTTP 404`. The command exits 0 only on `yes`. When the app sends the page to a sign-in page, Reticle verifies up to there and says so.
42
44
 
43
45
  <Note>
44
- **Run this before opening your agent, and there is nothing to restart.** A coding agent reads its
45
- MCP server list once at startup. Install while it is closed and the tools are simply there when
46
- you open it. If it was already open, quit and reopen it once.
46
+ **Not in the app's folder?** It checks the one dev server that runs on this computer. When several
47
+ run, it names them and does not choose. In a folder that `init` already wired, the same command
48
+ starts the Reticle server (`reticle serve`) instead.
47
49
  </Note>
48
50
 
49
- Prefer not to pipe a script into a shell? The same result by hand:
51
+ ## Step 2. Connect your coding agent
50
52
 
51
- ```bash
52
- npm install -g @reticlehq/server
53
- npx @reticlehq/server setup mcp
54
- ```
55
-
56
- ## Step 2. Wire this project
57
-
58
- In your project directory, before opening your coding agent:
53
+ In the same folder, before you open your coding agent, run the command that step 1 printed:
59
54
 
60
55
  ```bash
61
56
  RETICLE_INSTALL_SOURCE=docs_site npx @reticlehq/server init
62
57
  ```
63
58
 
64
- This installs the dev-only SDK, wires your build config, starts the dev server, and checks that a browser session connected. Nothing from your project leaves your machine. If your dev server was already running, restart it once and hard-reload the tab: it read your build config before `init` edited it. Open your coding agent once this command finishes; if it was already open during installation, restart it to load the new tools. The `RETICLE_INSTALL_SOURCE` prefix is optional and only tells us which page you installed from. It is idempotent: run it twice and the second run reports what was already done rather than doing it again.
59
+ This installs the dev-only SDK, wires your build config, and registers Reticle with every coding agent it finds on this machine. Then it starts the dev server and checks that a browser session connected. Nothing from your project leaves your machine. If your dev server was already running, restart it once and hard-reload the tab: it read your build config before `init` edited it. Open your coding agent once this command finishes. If it was open while `init` ran, restart it once: a coding agent reads its MCP server list only when it starts. The `RETICLE_INSTALL_SOURCE` prefix is optional and only tells us which page you installed from. It is idempotent: run it twice and the second run reports what was already done rather than doing it again.
65
60
 
66
- Step 1 is once per machine. This step is once per project. **Skipping it is a common reason Reticle "does nothing":** the agent has the tools, but there is no app on the other end for them to see.
61
+ This step is once per project. **Skipping it is a common reason Reticle "does nothing":** the agent has no tools, or no app on the other end for them to see.
67
62
 
68
63
  <Note>
69
64
  **Skipped this step?** Ask your agent to verify something in the app. Its first `reticle_session`
@@ -73,21 +68,6 @@ Step 1 is once per machine. This step is once per project. **Skipping it is a co
73
68
  second project while Reticle is already running for another one.
74
69
  </Note>
75
70
 
76
- Prefer to install the skill and let the agent run setup itself? On Claude Code the plugin registers the MCP server and the skill in one step:
77
-
78
- ```text
79
- /plugin marketplace add reticlehq/reticle
80
- /plugin install reticle@reticlehq
81
- ```
82
-
83
- On Cursor, Codex, Copilot, Gemini and anything else the skills CLI supports:
84
-
85
- ```bash
86
- npx skills add reticlehq/reticle --skill reticle
87
- ```
88
-
89
- Then type `/reticle` and the agent runs the install from the skill.
90
-
91
71
  Useful flags for the local-only `reticle init` path:
92
72
 
93
73
  ```
@@ -110,6 +90,44 @@ Start with `reticle init --dry-run` if you want to see the app changes before an
110
90
 
111
91
  Prefer to wire it yourself? See [Manual install](/install-manual). It is about ten lines, and worth reading once even if you let the agent do it, because it explains what the agent actually changed.
112
92
 
93
+ ### Other ways to connect your agent
94
+
95
+ **On Claude Code, the plugin** registers the MCP server and the skill in one step. Type `/reload-plugins` after the install and the tools load in the open session:
96
+
97
+ ```text
98
+ /plugin marketplace add reticlehq/reticle
99
+ /plugin install reticle@reticlehq
100
+ ```
101
+
102
+ **On Cursor, Codex, Copilot, Gemini** and anything else the skills CLI supports, add the skill, then type `/reticle` and the agent runs the setup from the skill:
103
+
104
+ ```bash
105
+ npx skills add reticlehq/reticle --skill reticle
106
+ ```
107
+
108
+ **The installer** puts `reticle` on your PATH once per machine and registers the MCP server with every coding agent it can reach: Claude Code, Cursor, Windsurf, VS Code, Zed, Gemini CLI, Copilot CLI, OpenCode, Antigravity, Warp, Kiro, Amazon Q, Cline, Roo Code, Amp, Continue and Factory Droid. It asks no questions and does not wire your app. Run it before you open your coding agent:
109
+
110
+ <CodeGroup>
111
+
112
+ ```bash macOS / Linux
113
+ curl -fsSL https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.sh | sh
114
+ ```
115
+
116
+ ```powershell Windows
117
+ irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1 | iex
118
+ ```
119
+
120
+ </CodeGroup>
121
+
122
+ Prefer not to pipe a script into a shell? The same result by hand:
123
+
124
+ ```bash
125
+ npm install -g @reticlehq/server
126
+ npx @reticlehq/server setup mcp
127
+ ```
128
+
129
+ Codex CLI keeps a TOML config. With the `codex` command installed, the installer registers Reticle through `codex mcp add`. Without it, the installer prints the lines to paste and the file to paste them into. Reticle then adds one line, `default_tools_approval_mode = "approve"`, under `[mcp_servers.reticle]` in `~/.codex/config.toml`. This line approves Reticle's own tools, so Codex does not ask before each call. Reticle changes no other line, and it keeps a mode that you set. To undo it, change that line to `default_tools_approval_mode = "prompt"`. Reticle does not change a mode that is already there.
130
+
113
131
  ## Step 3. Connect the dashboard (optional)
114
132
 
115
133
  Skip this if you only want local verdicts. Everything above works without an account.
@@ -272,10 +290,11 @@ That third state is the one that matters. Most tools have two outcomes and quiet
272
290
 
273
291
  <AccordionGroup>
274
292
  <Accordion title="How long does it actually take to install Reticle?">
275
- Two commands, and no restart if you run them in order. The installer registers the MCP server
276
- with every agent on the machine, so opening your agent afterwards is all that is needed. Then
277
- `npx @reticlehq/server init` wires the project, starts your dev server and opens the app for you. The MCP
278
- registration is global, so every later project starts with the tools already there.
293
+ Two commands in your app's folder. `npx @reticlehq/server` gives a first verdict with nothing
294
+ installed. Then `npx @reticlehq/server init` wires the project, registers Reticle with every
295
+ coding agent on the machine, starts your dev server and opens the app for you. Run them before
296
+ you open your agent, and it needs no restart. For most agents the MCP registration is global, so
297
+ a later project starts with the tools already there.
279
298
  </Accordion>
280
299
 
281
300
  <Accordion title="Do I need to write tests or learn a query syntax?">
@@ -97,7 +97,7 @@ Enterprise features are unlocked by a signed key, verified locally with Ed25519
97
97
  npx @reticlehq/server@latest init --license <key>
98
98
  ```
99
99
 
100
- That writes `RETICLE_LICENSE_KEY` to the project's `.env` and adds `.env` to `.gitignore` if nothing there covers it. Do not do those two by hand: a key committed to git is a leaked credential, and it stays leaked after the file is removed. Confirm with `npx @reticlehq/server license`, which prints `active`, `eval`, `missing`, `invalid` or `expired`.
100
+ That writes `RETICLE_LICENSE_KEY` to the project's `.env` and adds `.env` to `.gitignore` if nothing there covers it. Do not do those two by hand: a key committed to git is a leaked credential, and it stays leaked after the file is removed. Confirm with `npx @reticlehq/server status --json`. Its `license.status` is `active`, `eval`, `missing`, `invalid` or `expired`.
101
101
 
102
102
  Never echo the key back in your reply, and never put it in a commit, a code comment, or a feedback report. The rest: `curl https://docs.reticle.sh/enterprise.md`.
103
103
 
package/docs/skill.md CHANGED
@@ -3,7 +3,7 @@ name: reticle-docs
3
3
  description: Install, instrument and verify this running web app from the inside (DOM, network, routing, console and framework state) instead of screenshots or guessing. Drives one real flow end to end and returns a verdict with the file:line to fix. Use when the user asks to set up or install Reticle, when a user-facing change needs proving before you call it done, when a test passes but the UI is broken, or when the user types /reticle.
4
4
  license: Apache-2.0
5
5
  metadata:
6
- version: 3.8.2
6
+ version: 3.10.0
7
7
  homepage: https://docs.reticle.sh
8
8
  repository: https://github.com/reticlehq/reticle
9
9
  internal: true
@@ -13,30 +13,31 @@ metadata:
13
13
 
14
14
  Reticle is the proof layer for AI coding agents. A dev-only SDK inside the user's running app gives you `reticle_*` MCP tools that read the DOM, network, routing, console and framework state. You act on the real app and get a verdict: `yes`, `no`, or `unknown` (could not tell), with evidence and the `file:line` to open. No screenshots: it drives the tab the user already has open.
15
15
 
16
- **Your first goal: one real verdict in the user's app.** Do the three steps in order. Do not stop to explain Reticle first.
16
+ **Your first goal: one real verdict in the user's app.** Do the steps in order. Do not stop to explain Reticle first.
17
17
 
18
- ## 1. Install (once per machine)
18
+ ## 1. Check the app, with nothing installed
19
19
 
20
- **`reticle_*` tools visible?** Go to step 2.
20
+ **`reticle_*` tools visible?** Call `reticle_session { action: "list" }`. It changes no file. On a wired project, go to step 3. On a project that is not wired, its `next_step` names the zero-install lease and asks the consent question for `init`.
21
21
 
22
- **Not visible?** Hand the user one line for a terminal, outside this client, and stop:
22
+ **No tools, or an app with no `.reticle.json`?** Run this in the app's folder. It changes no file:
23
23
 
24
24
  ```bash
25
- curl -fsSL https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.sh | sh
26
- irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1 | iex # Windows
25
+ npx @reticlehq/server@latest
27
26
  ```
28
27
 
29
- It registers Reticle with every coding agent it finds and prints the next steps: restart the agent (a client loads MCP servers only at start, so a prompt cannot replace this command), then paste the prompt it printed. Do not register the server yourself and work around your client not having reloaded. If your client did register mid-session, `npx @reticlehq/server init --relaunch` prints the command that resumes this conversation with the tools.
28
+ It starts the dev server if the app does not run, opens the app in a Reticle browser and checks it: the page loads, no console error, no failed request, and each same-origin link opens. It prints `verified: yes` or `verified: no` with each fault. Show the user that verdict, then offer `init`.
30
29
 
31
30
  ## 2. Wire this app (once per project)
32
31
 
33
- In the project, call `reticle_session { action: "list" }`. It changes no file. On a project that is not wired, its `next_step` asks the consent question for `init`. When an app is running, it also names the zero-install lease, which checks that app now with nothing installed. `init` changes files, so run it only when the user agrees. A request to set up Reticle is that agreement. Run it in the app's folder:
32
+ `init` changes files, so run it only when the user agrees. A request to set up Reticle is that agreement. Run it in the app's folder:
34
33
 
35
34
  ```bash
36
35
  RETICLE_INSTALL_SOURCE=skill_file npx @reticlehq/server@latest init
37
36
  ```
38
37
 
39
- A dev server that was running when `init` ran must be restarted once. If `init` cannot finish alone, read SETUP below.
38
+ It registers Reticle with every coding agent it finds. A dev server that was running when `init` ran must be restarted once. If `init` cannot finish alone, read SETUP below.
39
+
40
+ **Still no `reticle_*` tools?** A client loads MCP servers only at start, so a prompt cannot add them. `npx @reticlehq/server init --relaunch` prints the command that resumes this conversation with the tools. Else ask the user to restart the agent. Do not register the server yourself and work around your client not having reloaded.
40
41
 
41
42
  ## 3. Prove one flow
42
43
 
@@ -87,7 +88,7 @@ The advertised surface is deliberately small (`default` 10, `all` 30). `RETICLE_
87
88
  | `reticle_verify` | replay, coverage, Harness | `action`: `change` `flows` `affected` `coverage` `crawl` `explore` `mutate` `heal` |
88
89
  | `reticle_tools` / `reticle_run` | everything else (below) | `names`; `tool`, `args` |
89
90
 
90
- Actions: `click` `dblclick` `hover` `focus` `blur` `fill` `type` `clear` `select` `check` `uncheck` `submit` `press` `upload` `scrollIntoView` `scroll` `drag` `tap` `zoom`. `args`: `{ value }` for fill/select, `{ text: "Enter" }` for press, `{ toRef }` for drag, `{ path }` for upload, `{ native: true }` for a trusted click. A control whose label reads as destructive is refused until you pass `args.confirmDangerous: true`, and only do that when the user asked for it.
91
+ Actions: `click` `dblclick` `hover` `focus` `blur` `fill` `type` `clear` `select` `check` `uncheck` `submit` `press` `upload` `scrollIntoView` `scroll` `drag` `tap` `zoom` `insertText`. `args`: `{ value }` for fill/select, `{ text: "Enter" }` for press, `{ toRef }` for drag, `{ path }` for upload, `{ native: true }` for a trusted click. `insertText` takes `{ text }` and types into a contenteditable/Tiptap/ProseMirror editor, where `fill` and `type` are refused. A control whose label reads as destructive is refused until you pass `args.confirmDangerous: true`, and only do that when the user asked for it.
91
92
 
92
93
  Beyond the advertised set, one hop each:
93
94
 
@@ -105,7 +106,7 @@ Every `until`, `predicate` and `expect` is `{ kind, ...fields }`; unknown fields
105
106
 
106
107
  | kind | fields |
107
108
  | --- | --- |
108
- | `element` | `query: { testid \| role+name \| text \| label \| placeholder \| alt \| component, scope? }`, `state?`: `visible` `hidden` `enabled` `disabled` `checked` `expanded` `pressed` `focused` `present` `inViewport`, `absent?` |
109
+ | `element` | `query: { testid \| role+name \| text \| label \| placeholder \| alt \| component, scope? }`, `state?`: `visible` `hidden` `enabled` `disabled` `checked` `expanded` `pressed` `focused` `present` `inViewport` `receivesPointer`, `absent?` |
109
110
  | `text` | `contains`, `scope?`, `visible?`, `absent?`, `ignoreCase?`, `satisfies?` |
110
111
  | `net` | `method`, `urlContains`, `status`, `ok`, `count` (exact; omit = ≥1; 0 = never), `bodyContains`, `bodyMatches`, `requestBodyMatches`, `repeatable` |
111
112
  | `route` | `pathname` or `contains` |
@@ -115,7 +116,7 @@ Every `until`, `predicate` and `expect` is `{ kind, ...fields }`; unknown fields
115
116
  | `settled` / `animation` / `compare` | `quietMs`, `channel?` / `name`, `completed` / `left`, `right`, `as` |
116
117
  | `allOf` / `anyOf` / `not` | `predicates: [...]` / `predicates: [...]` / `predicate` |
117
118
 
118
- `satisfies` asserts a property when the exact value varies: `nonEmpty`, `oneOf`, `withinTolerance`, `matchesPattern`, `type`, `changed`, `unchanged`, `increased`, `decreased`. Composites hold only predicates: `absent` belongs inside a child, and an `element` takes a `query`, never a `ref`. A bare `route` or `state` is already true before the action and proves nothing; pair it with what the action causes.
119
+ `satisfies` asserts a property when the exact value varies: `nonEmpty`, `oneOf`, `withinTolerance`, `matchesPattern`, `type`, `changed`, `unchanged`, `increased`, `decreased`. Composites hold only predicates: `absent` belongs inside a child, and an `element` takes a `query`, never a `ref`. A bare `route` or `state` is already true before the action and proves nothing; pair it with what the action causes. `absent` means not in the DOM; to say a thing is not shown, add `visible: true`. Assert what the requirement names, not a label you saw: another correct build can name it differently.
119
120
 
120
121
  ## Feedback is first-class
121
122
 
package/docs/telemetry.md CHANGED
@@ -40,20 +40,21 @@ Twenty-five kinds of events, each a single small JSON object. This is the whole
40
40
  | `mcp_proxy_exited` | The process that gives your agent its Reticle tools ends | Why it ended (`stdin_end`, `idle`, `client_gone_storm`, `wake_failed`), how long it ran, and two counts: how many times it lost the daemon and how many tool calls it carried, with its random id. Never what the calls were |
41
41
  | `daemon_died_unclean` | Reticle finds that an earlier daemon stopped without a clean exit | How long that daemon had run. Nothing else |
42
42
  | `wake_refused` | Reticle will not use the daemon port it found, because something else holds it | Whether the holder was another program (`foreign`) or a Reticle daemon for another project (`other_project`). Never the port or the project |
43
- | `onboarding_step` | One step of getting set up begins, finishes, fails, is skipped, or is walked away from | Which phase (`install`, `onboard`, `first_run`), which step, what became of it, how long it took, and the framework. The step name comes from a closed list we define -- it can only ever be one of the names in `core/src/onboarding.ts`, so nothing you typed or any path on your disk can arrive in it. `unattended` says whether anybody was asked anything |
43
+ | `onboarding_step` | One step of getting set up begins, finishes, fails, is skipped, or is walked away from | Which phase (`install`, `onboard`, `first_run`), which step, what became of it, how long it took, and the framework. The step name comes from a closed list we define -- it can only ever be one of the names in `core/src/onboarding.ts`, so nothing you typed or any path on your disk can arrive in it. `unattended` says whether anybody was asked anything. A step that failed can carry why setup stopped, also from a closed list (`no_node`, `node_too_old`, `no_web_app`, `dev_server_failed`, `chromium_unavailable`, and so on) |
44
44
  | `init_completed` | `reticle init` finishes | Whether it worked, a classified reason when it did not, and which published install route you came through, DECLARED by that route via `RETICLE_INSTALL_SOURCE` and never inferred, and `unknown` when nothing declared one |
45
45
  | `bug_found` | Reticle finds a defect in the app under test | The **kind** of defect (`signal-contradicted`, `console-error`, …) and how it was found, never what it was found in |
46
- | `tool_refused` | A tool cannot do what an agent asked | Which tool, why (one of six buckets: no session, no match, unsupported, bad arguments, not ready, other), and whether the same call was retried. **Never the message**, because a refusal interpolates whatever you asked for, so only the tool name and the bucket are sent. Capped at 50 per daemon run |
46
+ | `tool_refused` | A tool cannot do what an agent asked | Which tool, why (one of six buckets: no session, no match, unsupported, bad arguments, not ready, other), the cause inside the bucket as a name from a closed list (such as `chromium_missing` or `throttled`), and whether the same call was retried. **Never the message**, because a refusal interpolates whatever you asked for, so only the tool name and the bucket are sent. Capped at 50 per daemon run |
47
47
  | `feedback_submitted` | **Only** when you or your agent explicitly send feedback | The report; see [Feedback](#feedback). The AGENT's call does not wait for the network: the receipt says `accepted` (validated, redacted, queued), never `sent`, and a delivery that then fails is reported back on the agent's next tool result. `reticle feedback` typed by a human still waits, because a person at a terminal is owed the real answer |
48
48
  | `hud_viewed` | You open a page of the in-page HUD (Agent Log, Flows, Notes, Harness, Impact, Settings) or its account menu | Which page, from a closed list, and how many tabs had a HUD (a bucket: `1`, `2-3`, and so on). The same page opened again within 30 seconds counts once for the whole daemon run, also after a reload. The Agent Log that the HUD opens by itself when a page loads is not a view |
49
49
  | `hud_signin_prompted` | The HUD shows you a sign-in or "link this project" prompt | Which prompt (`rail`, `harness` or `header`), once per prompt for each daemon run |
50
50
  | `platform_linked` | A project on this machine is linked to a Reticle workspace | How (`connect`, `hud` or `link`) and the workspace's id; see [The platform side](#the-platform-side) |
51
51
  | `harness_run` | A Reticle Harness run starts, and again when it ends | Who started it (`agent`, `hud`, `dashboard`, `cli_try`, `plan`), whether the platform drove it, and at the end how it went (`proved`, `not_proved`, `failed`, `blocked`, `stopped`), how many journeys it answered and replayed, as buckets, and for a `blocked` or `failed` run why it did not drive, from a closed list (`not_linked`, `harness_off`, `no_credits`, and so on) |
52
+ | `gate_completed` | `reticle gate` ends | How it ended (`pass`, `fail`, `nothing_to_check`, `regression` or `error`) and how many saved flows it judged. Never a flow name or a file path |
52
53
  | `identified` | **Never** from this version. Only an earlier version's `reticle identify`, which has been removed | What you chose to tell us then; see [Telling us who you are](#telling-us-who-you-are) |
53
54
 
54
55
  **There is no per-tool-call event.** Tool usage is counted in memory and leaves once, inside `daemon_stopped`, as a histogram like `{"reticle_act": 40, "reticle_assert": 12}`. That is counts of tool NAMES from a fixed list we define, never arguments, results, selectors, or URLs.
55
56
 
56
- **Parameter and flag NAMES are collected; their VALUES are not.** We record that `reticle_act` was called with `ref` and `action`, and that you ran `reticle serve --headed --port`. We do not record what you set them to. This distinction is the whole safety property, and it is absolute for CLI flags: `--http-token` holds a secret, `--drive` holds a URL, `--storage-state` holds a file path, so no flag value is ever sent. For tool parameters there is one narrow exception: a short, explicit allowlist of parameters whose values are enums _we_ defined (`action: "click"`), listed in [`argument-shape.ts`](https://github.com/reticlehq/reticle/blob/main/server/src/telemetry/argument-shape.ts). A value outside that allowlist reports as `other`, so a future schema change cannot quietly start forwarding free text. `reticle_act`'s `args` (the text being typed into your app, which on a login form is a password) is **never** in that allowlist.
57
+ **Parameter and flag NAMES are collected; their VALUES are not.** We record that `reticle_act` was called with `ref` and `action`, and that you ran `reticle serve --headed --port`. We do not record what you set them to. This distinction is the whole safety property, and it is absolute for CLI flags: `--http-token` holds a secret, `--drive` holds a URL, `--storage-state` holds a file path, so no flag value is ever sent. For tool parameters there is one narrow exception: a short, explicit allowlist of parameters whose values are enums _we_ defined (`action: "click"`, and the name of the Reticle tool that `reticle_run` calls), listed in [`argument-shape.ts`](https://github.com/reticlehq/reticle/blob/main/server/src/telemetry/argument-shape.ts). A value outside that allowlist reports as `other`, so a future schema change cannot quietly start forwarding free text. `reticle_act`'s `args` (the text being typed into your app, which on a login form is a password) is **never** in that allowlist.
57
58
 
58
59
  `daemon_stopped` carries: how long the session ran, how many tool calls and of which tools, how many of those calls came before an app connected, the version of the Reticle SDK in the last page that connected, how long each tool took (total and worst case), how many failed, how many verifications ran, browser/lease connection attempts with their failure causes, and which MCP clients connected (`claude-code`, `cursor`). It also carries how the in-page HUD was used: presses per control (`hudControls`, by the control's name from a closed list Reticle defines, a toggle as `name:on` / `name:off`), how long the HUD sat as a bubble, collapsed or open and on which page (`hudViewMs`, `hudPanelMs`), which rail slides were shown (`hudSlides`), and the order of those presses and views, cut at 60 (`hudJourney`). Control names, never anything typed or shown on the page.
59
60
 
@@ -61,7 +62,7 @@ It also carries a snapshot of the **machine's** state (our own process's memory,
61
62
 
62
63
  ### Why a verdict came out that way
63
64
 
64
- `verification_completed` carries the **clause** that decided the verdict, from a fixed list we define: `proved`, `contradicted`, `assertion_failed`, `already_true`, `hidden_match`, `unclean_capture`, `vacuous_grade`, `nothing_declared`, `outcome_pending`, `outcome_unread`, `unsettled`, `evidence_incomplete`, `absence_blind_spot`, `observation_lost`, `window_closed_early`, `inconclusive`, `version_skew`, `capability-absent`.
65
+ `verification_completed` carries the **clause** that decided the verdict, from a fixed list we define: `proved`, `contradicted`, `assertion_failed`, `already_true`, `hidden_match`, `unclean_capture`, `vacuous_grade`, `nothing_declared`, `outcome_pending`, `outcome_unread`, `unsettled`, `evidence_incomplete`, `absence_blind_spot`, `observation_lost`, `window_closed_early`, `dialog_declined`, `inconclusive`, `version_skew`, `capability-absent`.
65
66
 
66
67
  It exists because `verified: "unknown"` covered seven different situations belonging to three different owners (your app, your agent, and Reticle's own blind spots), and they arrived as one value. It is a **name from our own vocabulary**, never a description of your app: `contradicted` says two channels disagreed, not which ones, about what, or on which page.
67
68
 
@@ -113,6 +114,7 @@ Every event carries the same few fields:
113
114
  | `version` | The Reticle version running | n/a |
114
115
  | `os` | The platform (`darwin` / `linux` / `win32`) | Not the OS version, hostname, or hardware |
115
116
  | `ci` | Whether the run is inside CI | n/a |
117
+ | `internal` | `true`, only on the Reticle team's own machines and test runs, which set it on purpose | Not set for anybody else, and never guessed from a name, an email or a path |
116
118
 
117
119
  There are no IP-based profiles, no cookies, no fingerprinting, and no person profiles: events are processed in "personless" mode, so they are never joined into a person profile.
118
120
 
@@ -77,7 +77,7 @@ with [`reticle_session`](/tools/sessions), and only then look at the page. If no
77
77
  | --- | --- |
78
78
  | `url` | Where to go. Relative paths work |
79
79
  | `reload` | Reload in place instead of navigating |
80
- | `hard` | With `reload`, bypass the cache |
80
+ | `hard` | With `reload`, bypass the cache. On a leased tab the browser reloads with its cache ignored (`hardReload: "cache_ignored"`). On a tab Reticle does not drive, only the document is fetched again, and scripts and modules can come from the cache (`hardReload: "document_only"`) |
81
81
  | `timeout_ms` | How long to wait for the page to come back before `confirmed: false`. Default 5000; 0 looks once |
82
82
 
83
83
  ## Client-side routing is different
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: reticle_verify
3
- description: Prove what is and is not working, by action. Replay saved flows for a change or for the whole suite, list coverage, crawl, explore, mutate or heal.
3
+ description: Prove what is and is not working, by action. Replay saved flows for a change or for the whole suite, list coverage, crawl, explore, mutate, heal, or compare two builds.
4
4
  icon: shield-check
5
5
  ---
6
6
 
@@ -20,9 +20,12 @@ icon: shield-check
20
20
  | `explore` | The Harness, Reticle's model-driven explorer, drives the journey you name in `persona` and saves what it drove as flows. Runs on the Reticle platform: run `reticle connect` first. A new account gets free credits to try it. **Destructive** | no |
21
21
  | `mutate` | Grades a saved flow: breaks the endpoint it depends on and replays it. A flow that stays green is a click sequence, not a test | no |
22
22
  | `heal` | Rebinds a flow whose locator was renamed. Re-asserts the saved consequence first and refuses if it stops firing. `apply: true` writes the fix | no |
23
+ | `compare` | Drives two running builds (`reference`, `candidate`, optional `base`) the same way and lists each difference in what users see and in the requests and console errors the app made. Nothing is installed in the app. Answers the JSON of [`reticle compare --json`](/cli/compare), with `verified` `yes` (same), `no` (different) or `unknown` (the run proves nothing). Within `wait` seconds it gives the result, or `{ status: "running", runId }` to poll with `runId`. **Destructive:** it presses every button it finds | yes |
23
24
 
24
25
  Only `verified: "yes"` is a pass. `unknown` means Reticle could not tell, and `no-fault` means nothing was declared to prove.
25
26
 
27
+ For `action: "flows"` and `action: "change"`, `parallel` opens one isolated lease per replayed flow. These leases inherit the source lease's certificate setting. Set `ignoreHTTPSErrors: true` to accept a self-signed or local-CA certificate when the source is not a lease. An explicit `false` keeps certificate checks on.
28
+
26
29
  Replay before you drive: a covered journey re-verifies for a few hundred tokens, where driving it again costs tens of thousands.
27
30
 
28
31
  From a terminal, `reticle verify <url>` replays the saved flows and exits `0` on pass. See [`reticle verify`](/cli/verify).
@@ -263,7 +263,7 @@ Some clients read their MCP tool list once, at startup, and never again. Cursor
263
263
  ## Restarting things
264
264
 
265
265
  ```bash
266
- npx @reticlehq/server restart # clean stop, then start and wait until it listens
266
+ npx @reticlehq/server serve --restart # clean stop, then start and wait until it listens
267
267
  npx @reticlehq/server status # confirm it is back
268
268
  ```
269
269
 
package/docs/usage.md CHANGED
@@ -129,7 +129,7 @@ Deep detail on one element, including the signals a snapshot/a11y tree omits, so
129
129
  Perform one action / several in order.
130
130
 
131
131
  - **`reticle_act` args:** `ref`, `action`, `args?`, `refuseWhenThrottled?`, `sessionId?`. → `{ since, dispatched, settled, settleReason, result, session, warning? }` where `result = { ok, ref, action, dispatched, settled, settleReason, effect }`. The `session` block `{ lastSeenMs, throttled, focused }` reports tab health on every act; when `throttled` is true a `warning` string is also attached. Pass `refuseWhenThrottled: true` to hard-fail instead of warning (opt-in; default is warn-only so background testing never breaks).
132
- - **`reticle_act { steps: [...] }` args:** `steps: [{ ref | target, action, args?, expect? }]`. `expect` takes the same predicate as `reticle_act_and_wait` `until`. A step with `expect` proves its consequence. The call stops at the first `expect` that fails and returns `verified` and `because`. Each step takes `ref` (from a snapshot/query) or `target` (`{ testid }` / `{ label }` / `{ role, name }` / `{ text }`). That is the same locator `reticle_act` accepts. → `{ since, dispatched, result }` where `result = { ok, count, effects: [...], steps: [...] }` (one `effect` per step; each step carries its own `dispatched`/`settled`/`settleReason`).
132
+ - **`reticle_act { steps: [...] }` args:** `steps: [{ ref | target, action, args?, expect? }]`. `expect` takes the same predicate as `reticle_act_and_wait` `until`. A step with `expect` proves its consequence. The call stops at the first `expect` that fails and returns `verified` and `because`. When a step could not be judged, the plan is `verified: "unknown"` (`verifiedReason: "inconclusive"`), and `because` names that step and what was missing: `step 2 (click) could not be judged: the assertion could not be evaluated: …`. `stopped_at` is the index of the same step, counted from 0. Each step takes `ref` (from a snapshot/query) or `target` (`{ testid }` / `{ label }` / `{ role, name }` / `{ text }`). That is the same locator `reticle_act` accepts. → `{ since, dispatched, result }` where `result = { ok, count, effects: [...], steps: [...] }` (one `effect` per step; each step carries its own `dispatched`/`settled`/`settleReason`).
133
133
  - See [§5](#5-actions-full-list) for the action list.
134
134
 
135
135
  **Dispatch vs settle.** (Settle means the page has stopped changing for now.) The action is two phases: the **dispatch** (the synchronous click/fill, which is what can fail) and the **settle** (waiting one animation frame so React's commit lands before we return). The settle is **bounded** (~200ms): in a throttled/background tab `requestAnimationFrame` never fires, so Reticle falls back to a timer and resolves anyway. A settle timeout is therefore **never an error**: `reticle_act` resolves with `settled:false, settleReason:"timeout"` and the dispatch (the click) has still landed. Only a real dispatch failure (stale ref, wrong element type) throws.
@@ -148,9 +148,9 @@ Perform one action / several in order.
148
148
  | `targetMatched` | the ref still resolved to a connected element |
149
149
  | `visible` | element was visible at the start of the action |
150
150
  | `enabled` | element was not disabled / aria-disabled at the start |
151
- | `defaultPrevented` | a handler called `preventDefault()` on the primary cancelable event. Only meaningful for `click`/`dblclick`/`hover`/`fill`/`type`/`clear`/`press`/`upload`/`drag`; always `false` for non-cancelable events (`focus`/`blur`/`select`/`check`/`uncheck`/`submit`/`scrollIntoView`) |
151
+ | `defaultPrevented` | a handler called `preventDefault()` on the primary cancelable event. Only meaningful for `click`/`dblclick`/`hover`/`fill`/`type`/`insertText`/`clear`/`press`/`upload`/`drag`; always `false` for non-cancelable events (`focus`/`blur`/`select`/`check`/`uncheck`/`submit`/`scrollIntoView`). For `insertText`, `true` with `valueChanged: true` means an editor that owns its input took the text: that is success, not a refusal |
152
152
  | `focusMoved` | `"<prevRef>-><newRef>"` if `document.activeElement` changed, else `null` (body counts as `null`) |
153
- | `valueChanged` | `fill`/`type`/`clear` only: input value before !== after; otherwise `false` |
153
+ | `valueChanged` | `fill`/`type`/`clear`, and `insertText`: the field value (or the editor's text) before !== after; otherwise `false` |
154
154
  | `domMutatedWithin` | count of MutationObserver records seen in the window |
155
155
  | `occluded` | `click`/`dblclick` only: the click point hit-tested to a _foreign_ element (an overlay is on top). Synthetic dispatch still delivered the event, but **a real user could not click it**, so treat the target as visually blocked. `false` when not click-like or not hit-testable |
156
156
  | `occludedBy` | the ref of the element actually on top at the click point when `occluded`, else `null` |
@@ -283,13 +283,13 @@ Show the agent's intent on the page, and control time (toasts/debounces/auto-dis
283
283
 
284
284
  Regression detection. See [§8](#8-regression-baselines--diff).
285
285
 
286
- ### `reticle_run { tool: "reticle_record", args: { action: "start" } }` / `reticle_run { tool: "reticle_record", args: { action: "stop" } }` / `reticle_replay`
286
+ ### `reticle_run { tool: "reticle_record", args: { action: "start" | "stop" | "replay" } }`
287
287
 
288
288
  Capture a flow's reaction report and compile it into a replayable program. See [§9](#9-recording-a-flow). `reticle_run { tool: "reticle_record", args: { action: "stop" } }` also returns a `cost:{ events, bytes }` hint alongside the reaction report so you can gauge the recording's size.
289
289
 
290
- ### `reticle_explore`
290
+ ### Autonomous exploration
291
291
 
292
- List interactive elements + console-error count for autonomous exploration. See [§10](#10-autonomous-exploration).
292
+ List the interactive elements with `reticle_snapshot { mode: "interactive" }` and read console errors with `reticle_console`. See [§10](#10-autonomous-exploration).
293
293
 
294
294
  ### Flows, recorder & self-healing (`.reticle/`)
295
295
 
@@ -356,7 +356,9 @@ A **predicate** declares what should be true. `reticle_assert` / `reticle_assert
356
356
  // An element exists / is in a state
357
357
  { "kind": "element", "query": { "role": "dialog", "name": "Confirm" }, "state": "visible" }
358
358
  // query supports: role, name, text, label, placeholder, testid, alt, scope
359
- // state: visible | hidden | enabled | disabled | checked | expanded | pressed | focused | present | inViewport
359
+ // state: visible | hidden | enabled | disabled | checked | expanded | pressed | focused | present | inViewport | receivesPointer
360
+ // receivesPointer asserts that a tap at the element's centre reaches it: visible, in the viewport, and no app element on top
361
+ // (a fixed header over a close button leaves it `visible` and untappable). Reticle's own UI never counts as a cover.
360
362
  // inViewport asserts the element is in the viewport NOW (not just in the DOM), so a scrollIntoView is gradeable
361
363
  // add "absent": true to assert it is NOT there (regression / removal)
362
364
 
@@ -419,11 +421,12 @@ A `state` assertion is graded as a **consequence** (a wrong element or stale ren
419
421
  | `focus` / `blur` | n/a | |
420
422
  | `fill` | `{ value }` | sets value via React-safe native setter + `input`/`change` |
421
423
  | `type` | `{ text }` | appends to current value |
424
+ | `insertText` | `{ text }` | inserts plain text into a contenteditable/Tiptap/ProseMirror editor through the browser editing pipeline: it announces `beforeinput` first, then lets the browser insert, so the editor's own model updates. `fill` and `type` refuse these surfaces. It refuses an EditContext editor (Monaco, CodeMirror 6), where a scripted update fires no `textupdate` for the model, and it refuses when the native command exists and fails, rather than writing the DOM while the editor's model stays stale |
422
425
  | `clear` | n/a | empties an input |
423
426
  | `select` | `{ value }` | `<select>` option |
424
427
  | `check` / `uncheck` | n/a | checkbox/radio |
425
428
  | `submit` | n/a | submits the element's `<form>` |
426
- | `press` | `{ text, modifiers?, holdMs?, keys?, code? }` | keydown/up (default `Enter`). `text` is the key name (`Escape`, `Tab`); `key` is an accepted alias; `modifiers`: an array of `Meta` / `Control` / `Shift` / `Alt` for Cmd+K-style shortcuts. With a `ref` the key is dispatched AT that element; with NO ref it is a document key (Escape, Tab, a shortcut) and goes through the real keyboard, so it can actually move focus. `holdMs` keeps the key DOWN for that long (hold-to-confirm, hold-to-reveal). `keys` holds several keys together, pressed in order and released in reverse, and `code` names the physical key: both stay on the in-page dispatcher, which is the only path that can express them |
429
+ | `press` | `{ text, modifiers?, holdMs?, keys?, code?, document? }` | keydown/up (default `Enter`). `document: true` makes any key a document key, so it needs no `ref`. `text` is the key name (`Escape`, `Tab`); `key` is an accepted alias; `modifiers`: an array of `Meta` / `Control` / `Shift` / `Alt` for Cmd+K-style shortcuts. With a `ref` the key is dispatched AT that element; with NO ref it is a document key (Escape, Tab, an arrow key, a shortcut) and goes through the real keyboard, so it can actually move focus. `holdMs` keeps the key DOWN for that long (hold-to-confirm, hold-to-reveal). `keys` holds several keys together, pressed in order and released in reverse, and `code` names the physical key: both stay on the in-page dispatcher, which is the only path that can express them |
427
430
  | `scrollIntoView` | n/a | |
428
431
  | `scroll` | `{ dy?, dx?, fraction? }` | Scrolls the nearest scrollable container (or the page, with no `ref`) by `dy`/`dx` pixels, either direction. `fraction` (0 to 1) jumps to that point of the height. No args steps down most of a screen |
429
432
  | `tap` | `{ holdMs? }` | A touch tap: pointer and touch events, then `click`. `holdMs` makes it a long press |
@@ -441,7 +444,7 @@ A `state` assertion is graded as a **consequence** (a wrong element or stale ren
441
444
  - **`interactive`** (~100 tokens): only actionable elements (buttons, inputs, tabs…). "What can I click?" Non-interactive content (e.g. 1,000 list rows) is skipped.
442
445
  - **`full`**: the whole semantic tree. Use only when you truly need everything.
443
446
 
444
- **`scope`** narrows any snapshot or query to a subtree, either a CSS selector (`scope: "[data-testid=item-list]"`) or a ref. This is the main lever for keeping payloads small and queries unambiguous on big pages.
447
+ **`scope`** narrows any snapshot or query to a subtree, either a CSS selector (`scope: "[data-testid=item-list]"`) or a ref. This is the main lever for keeping payloads small and queries unambiguous on big pages. In a query or a check, a CSS selector that matches several elements searches all of them, and the result reports how many it matched in `scopeMatches`. A ref names one element.
445
448
 
446
449
  ---
447
450
 
@@ -666,7 +669,7 @@ reticle_run({ tool: "reticle_record", args: { action: "stop", recordingName: "ch
666
669
  `reticle_run { tool: "reticle_record", args: { action: "stop" } }` returns a compiled, replayable `program`: the agent's `reticle_act` / `reticle_act { steps: [...] }` invocations captured during the span, with each ref normalized to its element's `data-testid` where resolvable. Re-run it later:
667
670
 
668
671
  ```jsonc
669
- reticle_run({ tool: "reticle_replay", args: { recordingName: "checkout" } })
672
+ reticle_run({ tool: "reticle_record", args: { action: "replay", recordingName: "checkout" } })
670
673
  // re-resolves each step by testid and re-runs the actions in order
671
674
  // → { recordingName, ok, steps: [{ tool, ok, error?, note? }] } // stops at the first failure
672
675
  ```
@@ -680,8 +683,8 @@ reticle_run({ tool: "reticle_replay", args: { recordingName: "checkout" } })
680
683
  Have the agent crawl and stress a screen without a script:
681
684
 
682
685
  ```jsonc
683
- reticle_run({ tool: "reticle_explore", args: { scope: "main" } })
684
- // → { interactive: [ { ref, desc }, … ], consoleErrors, hint }
686
+ reticle_snapshot({ mode: "interactive", scope: "main" }) // the controls, with refs
687
+ reticle_console({}) // the console errors so far
685
688
  ```
686
689
 
687
690
  The agent then acts on each ref, observes the reaction, and reports anomalies (failed requests, console errors, dead controls). Good for "click everything on this page and tell me what breaks."
@@ -1043,9 +1046,9 @@ registerCapabilities({ testids: [...], signals: [...], stores: [...], flows: [..
1043
1046
  reticle_run({ tool: "reticle_capabilities", args: {} }) // → { testids, signals, stores, flows }
1044
1047
  ```
1045
1048
 
1046
- ### `reticle_replay`: recordings become re-runnable programs
1049
+ ### `reticle_record { action: "replay" }`: recordings become re-runnable programs
1047
1050
 
1048
- `reticle_run { tool: "reticle_record", args: { action: "start" } }` → drive the flow → `reticle_run { tool: "reticle_record", args: { action: "stop" } }` returns a **compiled program** (steps bound to testids/signals, not volatile refs). `reticle_run({ tool: "reticle_replay", args: { recordingName } })` re-executes it, so your flow becomes a deterministic regression run, not a checklist.
1051
+ `reticle_run { tool: "reticle_record", args: { action: "start" } }` → drive the flow → `reticle_run { tool: "reticle_record", args: { action: "stop" } }` returns a **compiled program** (steps bound to testids/signals, not volatile refs). `reticle_run({ tool: "reticle_record", args: { action: "replay", recordingName } })` re-executes it, so your flow becomes a deterministic regression run, not a checklist.
1049
1052
 
1050
1053
  ---
1051
1054
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reticlehq/server",
3
- "version": "3.8.2",
3
+ "version": "3.10.0",
4
4
  "mcpName": "io.github.reticlehq/reticle",
5
5
  "description": "Reticle CLI, bridge and MCP server: a coding agent drives your running web app from the inside and gets a verdict with evidence, for change verification, access control, accessibility, performance and SEO checks.",
6
6
  "type": "module",
@@ -20,26 +20,26 @@
20
20
  }
21
21
  },
22
22
  "dependencies": {
23
- "@modelcontextprotocol/sdk": "^1.31.0",
24
- "ws": "^8.21.3",
23
+ "@modelcontextprotocol/sdk": "^1.32.2",
24
+ "ws": "^8.22.1",
25
25
  "zod": "^4.6.6",
26
- "@reticlehq/browser": "3.8.2",
27
- "@reticlehq/engine": "3.8.2",
28
- "open-verification": "1.1.0",
29
- "@reticlehq/core": "3.8.2",
30
- "@reticlehq/init": "3.8.2"
26
+ "@reticlehq/browser": "3.10.0",
27
+ "@reticlehq/init": "3.10.0",
28
+ "@reticlehq/core": "3.10.0",
29
+ "@reticlehq/engine": "3.10.0",
30
+ "open-verification": "1.1.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/pngjs": "^6.0.5",
34
- "@types/ws": "^8.5.13",
34
+ "@types/ws": "^8.18.2",
35
35
  "yaml": "^2.9.1"
36
36
  },
37
37
  "optionalDependencies": {
38
38
  "pixelmatch": "^8.0.0",
39
- "playwright": "^1.63.0",
39
+ "playwright": "^1.64.1",
40
40
  "pngjs": "^7.0.0"
41
41
  },
42
- "license": "FSL-1.1-ALv2",
42
+ "license": "Apache-2.0",
43
43
  "author": "Reticle contributors",
44
44
  "repository": {
45
45
  "type": "git",
@@ -52,7 +52,8 @@
52
52
  "bin",
53
53
  "dist",
54
54
  "README.md",
55
- "LICENSE-ENTERPRISE",
55
+ "LICENSE",
56
+ "NOTICE",
56
57
  "SKILL.md",
57
58
  "docs"
58
59
  ],
@@ -64,8 +65,11 @@
64
65
  "cli"
65
66
  ],
66
67
  "reticle": {
67
- "changelog": "3.8.1 could not record a verdict: every run it built or read failed with an Invalid element at key subject error. 3.8.2 fixes it. Update the CLI and the SDK in your app.",
68
- "breakingChanges": []
68
+ "changelog": "3.10.0 checks every change against what worked before. reticle compare and verify --against list what users would see change between two builds, and reticle grade grades a finished run from the app's stored data. Several false verdicts are fixed, most of them text checks that answered no for text that was on the page. An agent in a Claude Code worktree now reaches its own tab. Update the CLI and the SDK in your app.",
69
+ "breakingChanges": [
70
+ "The commands kill, login, link, project, whoami, push, regression, share, issues and memory are removed. Each prints the command that replaces it and exits 1. See MIGRATION.md.",
71
+ "The MCP tools reticle_explore and reticle_replay left the tool surface. Use reticle_look { action: \"page\", mode: \"interactive\" } and reticle_record { action: \"replay\" }."
72
+ ]
69
73
  },
70
74
  "publishConfig": {
71
75
  "access": "public"
@@ -1,37 +0,0 @@
1
- The Reticle Enterprise License (the "Enterprise License")
2
- Copyright (c) 2026 Reticle Labs
3
-
4
- With regard to the Reticle software (the "Software"):
5
-
6
- This Software and associated documentation files (the "Software") may only be
7
- used in production if you (and any entity that you represent) hold a valid Reticle
8
- Enterprise subscription for the correct number of seats and/or usage as agreed
9
- with Reticle Labs.
10
-
11
- Subject to the foregoing, you are free to use, copy, modify, and create
12
- derivative works of the Software for development, testing, and evaluation
13
- purposes without a subscription.
14
-
15
- You may not move, change, disable, or circumvent the license-key functionality
16
- in the Software, and you may not remove or obscure any functionality in the
17
- Software that is protected by the license key.
18
-
19
- You may not alter, remove, or obscure any licensing, copyright, or other
20
- notices.
21
-
22
- Any use of the Software in violation of this Enterprise License will
23
- automatically terminate your rights under this Enterprise License for the
24
- current and all other versions of the Software.
25
-
26
- This Enterprise License does not grant you any rights to any trademark, trade
27
- name, service mark, logo, or product name of Reticle Labs.
28
-
29
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
- SOFTWARE.
36
-
37
- For a Reticle Enterprise subscription: hey@reticle.sh
@@ -1,14 +0,0 @@
1
- /**
2
- * Example enterprise feature (Reticle Enterprise License — see./LICENSE). Demonstrates the pattern every
3
- * ee feature follows: call assertEnterprise...) first, then do the privileged work. The body here is a
4
- * stub — the real audit sink is the hosted control plane. It exists now to prove the gate.
5
- */
6
- import { type GateContext } from '../license/license.js';
7
- interface AuditEvent {
8
- actor: string;
9
- action: string;
10
- at: number;
11
- }
12
- /** Record an audit event — gated. Throws EnterpriseLicenseError in production without a valid license. */
13
- export declare function recordAuditEvent(event: AuditEvent, ctx: GateContext): AuditEvent;
14
- export {};