@reticlehq/server 2.7.0 → 2.9.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 (357) hide show
  1. package/README.md +14 -5
  2. package/SKILL.md +130 -778
  3. package/dist/bridge/bridge.d.ts +23 -0
  4. package/dist/bridge/bridge.js +80 -2
  5. package/dist/bridge/bridge.test-harness.d.ts +5 -0
  6. package/dist/bridge/bridge.test-harness.js +6 -4
  7. package/dist/capsule/causal-summary.d.ts +36 -1
  8. package/dist/capsule/causal-summary.js +33 -7
  9. package/dist/capsule/divergence.js +7 -1
  10. package/dist/cli/chromium-hint.d.ts +33 -5
  11. package/dist/cli/chromium-hint.js +82 -12
  12. package/dist/cli/cli-doctor.js +65 -34
  13. package/dist/cli/cli-flow-commands.js +8 -8
  14. package/dist/cli/cli-kill.d.ts +58 -0
  15. package/dist/cli/cli-kill.js +162 -0
  16. package/dist/cli/cli-parse.d.ts +16 -1
  17. package/dist/cli/cli-parse.js +32 -9
  18. package/dist/cli/cli-port.d.ts +32 -0
  19. package/dist/cli/cli-port.js +82 -35
  20. package/dist/cli/cli-verify.d.ts +21 -0
  21. package/dist/cli/cli-verify.js +47 -3
  22. package/dist/cli/config-discovery.d.ts +35 -0
  23. package/dist/cli/config-discovery.js +163 -0
  24. package/dist/cli/doctor-daemon-line.js +4 -1
  25. package/dist/cli/doctor-project-line.d.ts +37 -0
  26. package/dist/cli/doctor-project-line.js +35 -0
  27. package/dist/cli/doctor-rows.d.ts +51 -0
  28. package/dist/cli/doctor-rows.js +54 -0
  29. package/dist/cli/doctor-sessions-line.d.ts +12 -0
  30. package/dist/cli/doctor-sessions-line.js +69 -0
  31. package/dist/cli/drive-attach.d.ts +99 -0
  32. package/dist/cli/drive-attach.js +203 -0
  33. package/dist/cli/drive-command.d.ts +13 -0
  34. package/dist/cli/drive-command.js +103 -0
  35. package/dist/cli/open-note.d.ts +20 -0
  36. package/dist/cli/open-note.js +37 -0
  37. package/dist/cli/port-holder.d.ts +10 -0
  38. package/dist/cli/port-holder.js +26 -2
  39. package/dist/cli/status-next-action.d.ts +37 -0
  40. package/dist/cli/status-next-action.js +61 -0
  41. package/dist/cli.js +119 -39
  42. package/dist/crawl/crawl-tools.js +12 -2
  43. package/dist/crawl/crawl.d.ts +13 -0
  44. package/dist/crawl/crawl.js +50 -2
  45. package/dist/events/contradictions.d.ts +46 -0
  46. package/dist/events/contradictions.js +35 -22
  47. package/dist/events/declared.d.ts +45 -0
  48. package/dist/events/declared.js +73 -0
  49. package/dist/events/echo-mismatch.d.ts +8 -2
  50. package/dist/events/echo-mismatch.js +33 -5
  51. package/dist/events/event-filters.d.ts +1 -1
  52. package/dist/events/event-filters.js +7 -4
  53. package/dist/events/predicate-eval.d.ts +17 -72
  54. package/dist/events/predicate-eval.js +117 -236
  55. package/dist/events/predicate-parse.js +31 -3
  56. package/dist/events/predicate-route.d.ts +32 -0
  57. package/dist/events/predicate-route.js +102 -0
  58. package/dist/events/predicate-schema.d.ts +99 -0
  59. package/dist/events/predicate-schema.js +309 -0
  60. package/dist/events/predicate.d.ts +8 -0
  61. package/dist/events/predicate.js +296 -22
  62. package/dist/flows/annotate-tools.js +3 -0
  63. package/dist/flows/annotate.js +18 -4
  64. package/dist/flows/coverage.d.ts +38 -5
  65. package/dist/flows/coverage.js +30 -4
  66. package/dist/flows/decision.d.ts +15 -0
  67. package/dist/flows/decision.js +1 -1
  68. package/dist/flows/flow-classify.js +1 -1
  69. package/dist/flows/flow-replay-run.js +8 -1
  70. package/dist/flows/flow-tools.js +21 -5
  71. package/dist/flows/heal-run.js +1 -1
  72. package/dist/flows/replay.js +3 -0
  73. package/dist/honesty/accepted-write.d.ts +3 -0
  74. package/dist/honesty/accepted-write.js +8 -3
  75. package/dist/honesty/already-true.js +15 -0
  76. package/dist/honesty/blind-spots.js +10 -2
  77. package/dist/honesty/honesty.d.ts +11 -0
  78. package/dist/honesty/honesty.js +1 -0
  79. package/dist/honesty/uncaptured-bodies.d.ts +4 -2
  80. package/dist/honesty/uncaptured-bodies.js +9 -2
  81. package/dist/honesty/unread-outcome.d.ts +8 -0
  82. package/dist/honesty/unread-outcome.js +36 -9
  83. package/dist/honesty/unsettled.d.ts +49 -0
  84. package/dist/honesty/unsettled.js +82 -0
  85. package/dist/honesty/verified.d.ts +36 -3
  86. package/dist/honesty/verified.js +54 -11
  87. package/dist/http-server.d.ts +19 -0
  88. package/dist/http-server.js +202 -4
  89. package/dist/impact/impact-recorder.d.ts +23 -0
  90. package/dist/impact/impact-recorder.js +76 -0
  91. package/dist/impact/impact-store.d.ts +47 -0
  92. package/dist/impact/impact-store.js +171 -0
  93. package/dist/index.d.ts +7 -0
  94. package/dist/index.js +47 -10
  95. package/dist/init/agent-rules.d.ts +36 -0
  96. package/dist/init/agent-rules.js +132 -22
  97. package/dist/init/astro-patch.d.ts +2 -1
  98. package/dist/init/astro-patch.js +38 -6
  99. package/dist/init/capabilities.d.ts +22 -0
  100. package/dist/init/capabilities.js +76 -0
  101. package/dist/init/confirm.d.ts +114 -0
  102. package/dist/init/confirm.js +165 -0
  103. package/dist/init/connect-steps.d.ts +2 -0
  104. package/dist/init/connect-steps.js +50 -0
  105. package/dist/init/cra.js +3 -2
  106. package/dist/init/csp-check.d.ts +38 -0
  107. package/dist/init/csp-check.js +92 -0
  108. package/dist/init/csp-doctor.d.ts +25 -0
  109. package/dist/init/csp-doctor.js +49 -0
  110. package/dist/init/cursor.js +6 -9
  111. package/dist/init/detect.d.ts +8 -0
  112. package/dist/init/detect.js +33 -3
  113. package/dist/init/mcp-clients.d.ts +1 -0
  114. package/dist/init/mcp-clients.js +51 -7
  115. package/dist/init/mcp.d.ts +15 -0
  116. package/dist/init/mcp.js +19 -0
  117. package/dist/init/non-js-project.js +29 -5
  118. package/dist/init/plan-framework.d.ts +10 -0
  119. package/dist/init/plan-framework.js +78 -16
  120. package/dist/init/plan.d.ts +47 -6
  121. package/dist/init/plan.js +228 -69
  122. package/dist/init/run.d.ts +24 -2
  123. package/dist/init/run.js +157 -45
  124. package/dist/init/slash-command.d.ts +1 -1
  125. package/dist/init/slash-command.js +54 -6
  126. package/dist/init/snippets.d.ts +45 -5
  127. package/dist/init/snippets.js +194 -42
  128. package/dist/init/vite-config.js +53 -5
  129. package/dist/input/network-mock-tools.d.ts +19 -0
  130. package/dist/input/network-mock-tools.js +37 -5
  131. package/dist/input/scroll-find.d.ts +6 -0
  132. package/dist/input/scroll-find.js +17 -2
  133. package/dist/input/scroll-tools.js +4 -0
  134. package/dist/journal/attach-journal.d.ts +9 -1
  135. package/dist/journal/attach-journal.js +13 -2
  136. package/dist/journal/journal-query.d.ts +13 -0
  137. package/dist/journal/journal-query.js +28 -3
  138. package/dist/journal/workspace-gitignore.d.ts +10 -0
  139. package/dist/journal/workspace-gitignore.js +59 -0
  140. package/dist/license/license.js +1 -1
  141. package/dist/mcp/mcp-proxy.d.ts +35 -30
  142. package/dist/mcp/mcp-proxy.js +306 -104
  143. package/dist/mcp/mcp.d.ts +10 -1
  144. package/dist/mcp/mcp.js +70 -34
  145. package/dist/mcp/proxy-handshake.d.ts +82 -1
  146. package/dist/mcp/proxy-handshake.js +109 -2
  147. package/dist/mcp/proxy-lifecycle.d.ts +11 -2
  148. package/dist/mcp/proxy-lifecycle.js +12 -3
  149. package/dist/mcp/proxy-log.d.ts +63 -0
  150. package/dist/mcp/proxy-log.js +132 -0
  151. package/dist/mcp/server-instructions.d.ts +17 -0
  152. package/dist/mcp/server-instructions.js +56 -0
  153. package/dist/mcp/shared-params.d.ts +27 -0
  154. package/dist/mcp/shared-params.js +36 -0
  155. package/dist/pool/browser-pool.d.ts +22 -2
  156. package/dist/pool/browser-pool.js +44 -4
  157. package/dist/project/learned-routes.d.ts +24 -0
  158. package/dist/project/learned-routes.js +63 -0
  159. package/dist/project/project-store.d.ts +6 -0
  160. package/dist/project/project-store.js +25 -1
  161. package/dist/project/reticle-dir.d.ts +2 -0
  162. package/dist/project/reticle-dir.js +1 -0
  163. package/dist/session/connection-memory.d.ts +59 -0
  164. package/dist/session/connection-memory.js +108 -0
  165. package/dist/session/dev-command.d.ts +26 -0
  166. package/dist/session/dev-command.js +89 -0
  167. package/dist/session/dev-server-probe.d.ts +68 -0
  168. package/dist/session/dev-server-probe.js +102 -7
  169. package/dist/session/last-act.d.ts +26 -0
  170. package/dist/session/last-act.js +35 -1
  171. package/dist/session/live-control-tools.js +42 -5
  172. package/dist/session/no-session-diagnosis.d.ts +67 -2
  173. package/dist/session/no-session-diagnosis.js +236 -27
  174. package/dist/session/no-session-next-action.d.ts +46 -0
  175. package/dist/session/no-session-next-action.js +85 -0
  176. package/dist/session/no-session-watch.d.ts +40 -1
  177. package/dist/session/no-session-watch.js +174 -8
  178. package/dist/session/pending-commands.d.ts +12 -0
  179. package/dist/session/pending-commands.js +13 -1
  180. package/dist/session/ref-provenance.d.ts +54 -0
  181. package/dist/session/ref-provenance.js +61 -0
  182. package/dist/session/session-lease.js +1 -1
  183. package/dist/session/session-manager.d.ts +4 -0
  184. package/dist/session/session-manager.js +35 -5
  185. package/dist/session/session.d.ts +10 -1
  186. package/dist/session/session.js +146 -5
  187. package/dist/telemetry/app-instrumented.d.ts +8 -0
  188. package/dist/telemetry/app-instrumented.js +10 -0
  189. package/dist/telemetry/automation-hint.d.ts +17 -0
  190. package/dist/telemetry/automation-hint.js +71 -0
  191. package/dist/telemetry/bug-found.d.ts +15 -17
  192. package/dist/telemetry/bug-found.js +52 -21
  193. package/dist/telemetry/cli-telemetry.js +7 -1
  194. package/dist/telemetry/daemon-telemetry.js +24 -0
  195. package/dist/telemetry/feedback.js +1 -1
  196. package/dist/telemetry/init-telemetry.js +9 -1
  197. package/dist/telemetry/install-source.d.ts +56 -0
  198. package/dist/telemetry/install-source.js +74 -0
  199. package/dist/telemetry/instrumentation-stall.d.ts +50 -0
  200. package/dist/telemetry/instrumentation-stall.js +90 -0
  201. package/dist/telemetry/run-telemetry.js +4 -1
  202. package/dist/telemetry/session-metrics.d.ts +8 -0
  203. package/dist/telemetry/session-metrics.js +15 -0
  204. package/dist/telemetry/telemetry.d.ts +7 -1
  205. package/dist/telemetry/telemetry.js +26 -2
  206. package/dist/telemetry/tool-refused.d.ts +19 -0
  207. package/dist/telemetry/tool-refused.js +55 -0
  208. package/dist/telemetry/verification-of.js +46 -7
  209. package/dist/temp-dir.d.ts +27 -0
  210. package/dist/temp-dir.js +46 -0
  211. package/dist/tools/act-tools.js +209 -28
  212. package/dist/tools/assert-grade.d.ts +1 -1
  213. package/dist/tools/assert-grade.js +27 -5
  214. package/dist/tools/assert-verdict.js +49 -7
  215. package/dist/tools/browser-tools.js +10 -0
  216. package/dist/tools/contract-tools.js +4 -0
  217. package/dist/tools/dynamic-tools.js +16 -7
  218. package/dist/tools/error-recovery.d.ts +10 -0
  219. package/dist/tools/error-recovery.js +73 -9
  220. package/dist/tools/feedback-invite.js +1 -1
  221. package/dist/tools/invoke-tool.js +159 -26
  222. package/dist/tools/lease-hint.d.ts +30 -8
  223. package/dist/tools/lease-hint.js +65 -14
  224. package/dist/tools/lease-tools.d.ts +40 -1
  225. package/dist/tools/lease-tools.js +181 -83
  226. package/dist/tools/navigate-result.js +1 -1
  227. package/dist/tools/observe-tools.js +10 -4
  228. package/dist/tools/observed-nothing.js +1 -1
  229. package/dist/tools/react-grace.d.ts +52 -0
  230. package/dist/tools/react-grace.js +90 -0
  231. package/dist/tools/read-tools.js +67 -5
  232. package/dist/tools/resolve-target.d.ts +33 -0
  233. package/dist/tools/resolve-target.js +53 -0
  234. package/dist/tools/settle-in-flight.d.ts +94 -0
  235. package/dist/tools/settle-in-flight.js +146 -0
  236. package/dist/tools/snapshot-delta.d.ts +10 -0
  237. package/dist/tools/snapshot-delta.js +194 -9
  238. package/dist/tools/tool-kit.d.ts +8 -0
  239. package/dist/tools/tool-surface.d.ts +60 -0
  240. package/dist/tools/tool-surface.js +86 -1
  241. package/dist/tools/tools.js +61 -8
  242. package/dist/tools/unadvertised-help.js +9 -6
  243. package/docs/README.md +55 -11
  244. package/docs/actions.mdx +120 -0
  245. package/docs/agent-cheatsheet.md +95 -29
  246. package/docs/architecture.md +52 -35
  247. package/docs/benchmarks.md +127 -75
  248. package/docs/best-practices.mdx +216 -0
  249. package/docs/capabilities.mdx +534 -0
  250. package/docs/cli/affected.mdx +53 -0
  251. package/docs/cli/capsules.mdx +70 -0
  252. package/docs/cli/cloud.mdx +153 -0
  253. package/docs/cli/doctor.mdx +109 -0
  254. package/docs/cli/drive.mdx +74 -0
  255. package/docs/cli/feedback.mdx +67 -0
  256. package/docs/cli/gate.mdx +64 -0
  257. package/docs/cli/help.mdx +94 -0
  258. package/docs/cli/hunt.mdx +73 -0
  259. package/docs/cli/identify.mdx +76 -0
  260. package/docs/cli/init.mdx +121 -0
  261. package/docs/cli/kill.mdx +91 -0
  262. package/docs/cli/license.mdx +48 -0
  263. package/docs/cli/mcp.mdx +61 -0
  264. package/docs/cli/open.mdx +74 -0
  265. package/docs/cli/restart.mdx +60 -0
  266. package/docs/cli/rollback.mdx +35 -0
  267. package/docs/cli/serve.mdx +69 -0
  268. package/docs/cli/status.mdx +88 -0
  269. package/docs/cli/stop.mdx +64 -0
  270. package/docs/cli/telemetry.mdx +57 -0
  271. package/docs/cli/update.mdx +52 -0
  272. package/docs/cli/verify.mdx +76 -0
  273. package/docs/cli/version.mdx +39 -0
  274. package/docs/cli/watch.mdx +62 -0
  275. package/docs/cli.mdx +241 -0
  276. package/docs/debugging.md +16 -10
  277. package/docs/deploy-checks.md +45 -12
  278. package/docs/desktop.mdx +384 -0
  279. package/docs/docs.json +364 -0
  280. package/docs/enterprise.md +22 -16
  281. package/docs/faq.mdx +102 -0
  282. package/docs/fixtures.md +13 -7
  283. package/docs/flows.md +29 -23
  284. package/docs/for-agents.md +71 -0
  285. package/docs/frameworks.mdx +238 -0
  286. package/docs/gate-plan.md +48 -42
  287. package/docs/gates.md +28 -22
  288. package/docs/getting-started.md +129 -77
  289. package/docs/human-control.md +24 -18
  290. package/docs/index.mdx +143 -0
  291. package/docs/install-agentic.mdx +224 -0
  292. package/docs/install-manual.mdx +196 -0
  293. package/docs/instrumentation.mdx +238 -0
  294. package/docs/integration-patterns.md +41 -35
  295. package/docs/local-registry.md +19 -13
  296. package/docs/multi-agent-testing.md +19 -13
  297. package/docs/packages/babel-plugin.mdx +79 -0
  298. package/docs/packages/browser.mdx +111 -0
  299. package/docs/packages/core.mdx +116 -0
  300. package/docs/packages/electron.mdx +85 -0
  301. package/docs/packages/eslint-plugin.mdx +86 -0
  302. package/docs/packages/next.mdx +89 -0
  303. package/docs/packages/react.mdx +91 -0
  304. package/docs/packages/server.mdx +98 -0
  305. package/docs/packages/tauri.mdx +63 -0
  306. package/docs/packages/test.mdx +119 -0
  307. package/docs/packages/vite-plugin.mdx +94 -0
  308. package/docs/packages.mdx +218 -0
  309. package/docs/platform-integration.md +35 -26
  310. package/docs/predicates.mdx +248 -0
  311. package/docs/quickstart.mdx +257 -0
  312. package/docs/recipes.mdx +282 -0
  313. package/docs/skill-file.mdx +107 -0
  314. package/docs/state-management.mdx +199 -0
  315. package/docs/style.css +14 -0
  316. package/docs/system-map.md +50 -33
  317. package/docs/telemetry-contract.md +106 -52
  318. package/docs/telemetry-events.mdx +475 -0
  319. package/docs/telemetry.md +63 -55
  320. package/docs/testing.md +44 -6
  321. package/docs/token-efficiency.md +37 -27
  322. package/docs/tools-act-and-wait.mdx +173 -0
  323. package/docs/tools-act-sequence.mdx +137 -0
  324. package/docs/tools-act.mdx +95 -0
  325. package/docs/tools-assert.mdx +129 -0
  326. package/docs/tools-console.mdx +63 -0
  327. package/docs/tools-inspect.mdx +88 -0
  328. package/docs/tools-navigate.mdx +99 -0
  329. package/docs/tools-network.mdx +119 -0
  330. package/docs/tools-observe.mdx +145 -0
  331. package/docs/tools-overview.mdx +160 -0
  332. package/docs/tools-query.mdx +126 -0
  333. package/docs/tools-session-and-feedback.mdx +112 -0
  334. package/docs/tools-sessions.mdx +94 -0
  335. package/docs/tools-snapshot.mdx +129 -0
  336. package/docs/tools-state.mdx +104 -0
  337. package/docs/tools-tools-and-run.mdx +156 -0
  338. package/docs/tools-wait-for.mdx +85 -0
  339. package/docs/troubleshooting.mdx +263 -0
  340. package/docs/usage.md +209 -165
  341. package/docs/vs-chrome-devtools-mcp.mdx +123 -0
  342. package/docs/vs-playwright-mcp.mdx +125 -0
  343. package/docs/vs-screenshots.mdx +137 -0
  344. package/docs/what-is-reticle.mdx +63 -0
  345. package/docs/why-reticle.mdx +109 -0
  346. package/package.json +5 -5
  347. package/docs/desktop-apps.md +0 -256
  348. package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
  349. package/docs/matrix/2.5.0/codex-machine.json +0 -20
  350. package/docs/matrix/2.5.0/cursor-machine.json +0 -22
  351. package/docs/matrix/2.5.0/gemini-machine.json +0 -22
  352. package/docs/matrix/2.5.0/opencode-machine.json +0 -22
  353. package/docs/matrix/2.5.0/vscode-machine.json +0 -22
  354. package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
  355. package/docs/matrix/MATRIX.md +0 -26
  356. package/docs/matrix/README.md +0 -59
  357. package/docs/mint.json +0 -61
@@ -0,0 +1,534 @@
1
+ ---
2
+ title: Beyond the verify loop
3
+ description: Coverage, storage, fake clocks, autonomous crawling, visual diffing and network mocking. What Reticle does once look-act-observe-assert is not enough.
4
+ icon: sparkles
5
+ ---
6
+
7
+ These are the Reticle tools that do something other than look, act, observe and assert: control coverage, client storage, a fake clock, autonomous crawling, semantic and visual baselines, network mocking, flow recording and replay, and the CI artifact. Reach for them when the verify loop is not the shape of the question. None of them live in the default advertised surface, so all of them are called through [`reticle_run`](/tools-tools-and-run).
8
+
9
+ Most of the time you want the verify loop. Look, act, observe, assert. These are the tools for the times you want something else, and they are the ones people are most surprised exist.
10
+
11
+ ## Available anywhere
12
+
13
+ These work through the always-on SDK, in any connected session.
14
+
15
+ ### Coverage: what you have not driven yet
16
+
17
+ ```json
18
+ { "tool": "reticle_coverage" }
19
+ ```
20
+
21
+ ```json
22
+ {
23
+ "total": 43,
24
+ "exercised": 2,
25
+ "untouched": [
26
+ { "ref": "e619", "label": "button \"Overview\"" },
27
+ { "ref": "e627", "label": "button \"Compose\"" },
28
+ { "ref": "e632", "label": "textbox \"Filter by service…\"" },
29
+ { "ref": "e635", "label": "button \"Row actions\"" }
30
+ ]
31
+ }
32
+ ```
33
+
34
+ That is a real capture with 39 of the 41 untouched entries trimmed out. Two controls driven out of forty-three.
35
+
36
+ Not code coverage. Control coverage: which interactive elements this session has actually touched.
37
+
38
+ Useful at the end of a drive, when the agent is about to report success. "I verified the page" reads differently next to `exercised: 0`.
39
+
40
+ ### Storage: the persistence layer
41
+
42
+ ```json
43
+ { "tool": "reticle_storage" }
44
+ ```
45
+
46
+ ```json
47
+ {
48
+ "local": { "reticle.bench.authToken": "[REDACTED]" },
49
+ "session": {
50
+ "__reticle_ref_base": "700",
51
+ "__reticle_session": "s223e0fad-e012-43f9-a23d-6d585470c90d",
52
+ "reticle.bench.sessionId": "[REDACTED]"
53
+ },
54
+ "cookies": { "bench_session": "724fa5c2-d913-4d19-8a90-3a4d85dc09a0" }
55
+ }
56
+ ```
57
+
58
+ Note the token redaction. Credential-shaped values are stripped here exactly as they are in [`reticle_network`](/tools-network), so reading storage never puts a session token in your context.
59
+
60
+ localStorage, sessionStorage and readable cookies.
61
+
62
+ This is where the "logged in but nothing persisted" bug lives. A login can fire its success signal, mutate state, and write nothing. Reload, and you are back at the login screen.
63
+
64
+ <Tip>
65
+ `storageKeysChanged` already appears in every `act_and_wait` summary, so you often do not need
66
+ this tool. Read it there first.
67
+ </Tip>
68
+
69
+ ### Clock: freeze time, skip the wait
70
+
71
+ ```json
72
+ { "tool": "reticle_clock", "args": { "freeze": true } }
73
+ ```
74
+
75
+ ```json
76
+ { "frozen": true }
77
+ ```
78
+
79
+ ```json
80
+ { "tool": "reticle_clock", "args": { "advanceMs": 5000 } }
81
+ { "tool": "reticle_clock", "args": { "reset": true } }
82
+ ```
83
+
84
+ `advanceMs` answers `{ "frozen": true }`, because advancing keeps the clock frozen at the new time. `reset` answers `{ "frozen": false }` and hands time back to the browser.
85
+
86
+ Toasts that auto-dismiss, debounced search, polling, session timeouts, retry backoff. All of these are normally verified by sleeping, which is slow and flaky in equal measure.
87
+
88
+ Freeze the clock, advance it by exactly the interval, assert the consequence. No sleeping, no guessing, and the same result on a fast laptop and a loaded CI runner.
89
+
90
+ ### Crawl: click everything, report anomalies
91
+
92
+ ```json
93
+ { "tool": "reticle_crawl", "args": { "maxSteps": 6 } }
94
+ ```
95
+
96
+ ```json
97
+ {
98
+ "interactiveFound": 43,
99
+ "stepsRun": 6,
100
+ "anomalies": [],
101
+ "counts": { "consoleErrors": 0, "failedRequests": 0, "deadControls": 0, "contradictions": 0 },
102
+ "visited": [
103
+ "- button \"Overview\"",
104
+ "- button \"Deployments40\"",
105
+ "- button \"Compose\"",
106
+ "- button \"Diagnostics\"",
107
+ "- button \"Hostile\"",
108
+ "- button \"Search or jump to…⌘K\""
109
+ ],
110
+ "truncated": true,
111
+ "coverageNote": "the page changed as you clicked: 7 control(s) that did not exist when this crawl started were never visited, interactiveFound is a floor, not a total; re-run the crawl from the state you are now in to cover them"
112
+ }
113
+ ```
114
+
115
+ Read `coverageNote` before you read the counts. `interactiveFound` is measured when the crawl starts, so on any app where clicking reveals new controls it is a floor rather than a total, and the tool says so rather than letting `43` read as complete.
116
+
117
+ Autonomously clicks every reachable control and reports what went wrong. No script, no plan. The counts are the useful part: `deadControls` and `contradictions` are the two that indicate a real problem rather than a busy page.
118
+
119
+ This is the tool for an app you did not write and do not understand yet.
120
+
121
+ <Warning>
122
+ It clicks **everything**, so point it at a dev environment. `maxSteps` bounds it, defaulting to
123
+ 25.
124
+ </Warning>
125
+
126
+ ### Reconcile: what the API said versus what rendered
127
+
128
+ ```json
129
+ { "tool": "reticle_reconcile" }
130
+ ```
131
+
132
+ ```json
133
+ {
134
+ "mismatches": [],
135
+ "compared": 2,
136
+ "note": "compared 2 response(s); nothing on screen contradicts them"
137
+ }
138
+ ```
139
+
140
+ Compares the data an endpoint returned against what the page actually displays. `compared` is the field that makes the empty `mismatches` meaningful: `compared: 0` would mean it had nothing to check, not that everything agreed.
141
+
142
+ The bug it catches is specific and common: the API returned ten rows, the table shows nine, and nothing errored. Neither the network log nor the DOM is wrong on its own. Only the comparison is.
143
+
144
+ ### Domain: which of your flows actually prove anything
145
+
146
+ The most useful tool nobody knows about.
147
+
148
+ ```json
149
+ { "tool": "reticle_domain" }
150
+ ```
151
+
152
+ ```json
153
+ {
154
+ "flowCount": 47,
155
+ "coverage": { "asserted": 14, "presenceOnly": 2, "assertionFree": 31 },
156
+ "gaps": {
157
+ "declaredUntestedSignals": [
158
+ "deploy:created",
159
+ "deploy:shipped",
160
+ "modal:opened",
161
+ "toast:shown",
162
+ "…"
163
+ ],
164
+ "declaredUntestedTestids": ["deploy-submit", "drawer", "palette", "…"]
165
+ },
166
+ "summary": "47 flows: 14 asserted, 2 presence-only, 31 assertion-free. test first: asserted-demo2 (last run drifted). 13 declared signal(s) no flow asserts. 33 flow(s) assert no consequence."
167
+ }
168
+ ```
169
+
170
+ Read that summary again. Thirty-one of forty-seven flows **assert no consequence**, which means they replay green whatever the app does. That is a suite that looks like coverage and is not.
171
+
172
+ Each flow comes back graded, with the consequence that must hold and a risk level:
173
+
174
+ ```json
175
+ {
176
+ "name": "deploy-journey",
177
+ "grade": "asserted",
178
+ "mustHold": "nav:changed",
179
+ "risk": { "level": "high", "reason": "last run drifted", "lastStatus": "drift" }
180
+ }
181
+ ```
182
+
183
+ ```json
184
+ {
185
+ "name": "console-compose",
186
+ "grade": "assertion-free",
187
+ "warning": "This flow performs actions but asserts no observable consequence, so it will pass even if the feature is broken. Add a consequence assertion with reticle_annotate (assert-signal / assert-net) or a success-state."
188
+ }
189
+ ```
190
+
191
+ `declaredUntestedSignals` is the other half: signals your app emits that no flow ever checks. It is a to-do list for your test suite, generated from what the app says about itself. The full response also carries `declared` (the app's registered testids, signals and stores), `riskRanked` (every flow ordered worst first) and `unassertedFlows`.
192
+
193
+ <Tip>
194
+ Run this before writing a new flow. It tells you what is already covered, what is covered badly,
195
+ and which declared signal has never been asserted. All three are better starting points than
196
+ guessing.
197
+ </Tip>
198
+
199
+ ### Baselines: semantic snapshots, not pixels
200
+
201
+ ```json
202
+ { "tool": "reticle_baseline", "args": { "action": "save", "name": "checkout-empty" } }
203
+ ```
204
+
205
+ ```json
206
+ { "baseline": "checkout-empty", "lineCount": 174 }
207
+ ```
208
+
209
+ ```json
210
+ { "tool": "reticle_baseline", "args": { "action": "diff", "name": "checkout-empty" } }
211
+ ```
212
+
213
+ ```json
214
+ {
215
+ "baseline": "checkout-empty",
216
+ "removed": [],
217
+ "added": [],
218
+ "consoleErrors": 0,
219
+ "routeChanged": false
220
+ }
221
+ ```
222
+
223
+ Records the meaningful state of a page and compares later. Structure and content rather than pixels, so a font change does not fail your check and a missing row does. `action: "list"` returns the saved names.
224
+
225
+ ## Needs a driven browser
226
+
227
+ Four tools apply their effects through the Chrome DevTools Protocol. The always-on SDK cannot do that, so they need a browser Reticle is driving.
228
+
229
+ <Warning>
230
+ **A pooled lease is not enough.** Re-verified on 2026-08-16: acquire one with `reticle_lease` and
231
+ `reticle_screenshot` answers
232
+
233
+ ```json
234
+ {
235
+ "ok": false,
236
+ "reason": "no-visual-provider",
237
+ "recommendation": "visual capture needs a driven browser, start with `reticle drive <url>` or set RETICLE_CDP_URL; the always-on SDK does not ship a screenshotter"
238
+ }
239
+ ```
240
+
241
+ while `reticle_network_mock` answers `{ "applied": false, "count": 0, "ok": false, "reason": "no-cdp-provider" }`. Under a driven browser, all four work: the captures below were taken that way.
242
+
243
+ Run `reticle drive <url>`, or point `RETICLE_CDP_URL` at a Chrome started with `--remote-debugging-port`.
244
+
245
+ </Warning>
246
+
247
+ ### Screenshots and visual diffing
248
+
249
+ ```json
250
+ { "tool": "reticle_screenshot", "args": { "name": "login-baseline" } }
251
+ ```
252
+
253
+ ```json
254
+ {
255
+ "ok": true,
256
+ "saved": true,
257
+ "name": "login-baseline",
258
+ "path": ".reticle/visual/login-baseline.png",
259
+ "bytes": 191150
260
+ }
261
+ ```
262
+
263
+ ```json
264
+ { "tool": "reticle_visual_diff", "args": { "baseline": "login-baseline" } }
265
+ ```
266
+
267
+ ```json
268
+ {
269
+ "ok": true,
270
+ "matched": true,
271
+ "changedPixels": 0,
272
+ "totalPixels": 921600,
273
+ "ratio": 0,
274
+ "dimensionMismatch": false,
275
+ "baseline": { "width": 1280, "height": 720 },
276
+ "current": { "width": 1280, "height": 720 },
277
+ "diffPath": ".reticle/visual/login-baseline.diff.png"
278
+ }
279
+ ```
280
+
281
+ `dimensionMismatch` is the field that saves an afternoon. A diff between two different viewport sizes is meaningless, and this says so rather than reporting a huge `ratio`.
282
+
283
+ <Warning>
284
+ Note the asymmetry. `reticle_screenshot` names the baseline with **`name`**; `reticle_visual_diff`
285
+ refers to it with **`baseline`**. Passing `name` to the diff is rejected, and it is an easy
286
+ mistake to make twice.
287
+ </Warning>
288
+
289
+ `fullPage` captures the whole scroll height. `ref` or `clip` scopes to one element or region. `threshold` sets the pixel-difference tolerance, defaulting to `0.01`, `maxRatio` caps the acceptable changed fraction, and `masks` excludes regions that are expected to change.
290
+
291
+ Reticle reads program truth, not pixels, so this is the deliberate exception: a font that failed to load or a compositing glitch is only visible in the actual frame.
292
+
293
+ ### Viewport pinning
294
+
295
+ ```json
296
+ { "tool": "reticle_viewport", "args": { "width": 1280, "height": 800 } }
297
+ ```
298
+
299
+ ```json
300
+ { "applied": true, "width": 1280, "height": 800 }
301
+ ```
302
+
303
+ Fixes the viewport so a visual baseline is reproducible across machines. Without it, a diff taken on a laptop and re-run in CI compares two different layouts and fails for a reason nobody wants to debug.
304
+
305
+ ### Network mocking
306
+
307
+ ```json
308
+ {
309
+ "tool": "reticle_network_mock",
310
+ "args": { "mocks": [{ "urlContains": "/api/deploys", "status": 500 }] }
311
+ }
312
+ ```
313
+
314
+ ```json
315
+ { "applied": true, "count": 1 }
316
+ ```
317
+
318
+ Return a 500, force offline, or delay a response. First matching rule wins. `clear: true` turns it off and answers `{ "applied": true, "count": 0 }`.
319
+
320
+ Most error states have never actually run. This is how you find out whether yours works, without touching the backend or waiting for a real outage to tell you.
321
+
322
+ ## Flows: record once, replay forever
323
+
324
+ The loop closer, and the reason Reticle is not only an interactive tool.
325
+
326
+ ```json
327
+ { "tool": "reticle_record", "args": { "action": "start", "recordingName": "ship-a-deploy" } }
328
+ { "tool": "reticle_record", "args": { "action": "stop", "recordingName": "ship-a-deploy" } }
329
+ { "tool": "reticle_flow_save", "args": { "flowName": "ship-a-deploy" } }
330
+ { "tool": "reticle_flow_verify" }
331
+ ```
332
+
333
+ <Warning>
334
+ The argument names are not interchangeable. `reticle_record` takes **`recordingName`**,
335
+ `reticle_flow_save` takes **`flowName`**, and neither accepts `name`. Reticle rejects the call
336
+ rather than guessing, which is the right call and still costs you a turn.
337
+ </Warning>
338
+
339
+ Stopping a recording used to return a very large payload, almost all of it the raw `events` array. It no longer does. The timeline is omitted and replaced with a pointer, so a stop is under a kilobyte. This is a real capture of a one-click recording, complete rather than trimmed:
340
+
341
+ ```json
342
+ {
343
+ "recordingName": "docs-check",
344
+ "program": {
345
+ "name": "docs-check",
346
+ "version": 1,
347
+ "steps": [{ "tool": "reticle_act", "stable": true, "args": { … } }]
348
+ },
349
+ "timeline_omitted": "445 event(s) were recorded and are not included here. Call reticle_observe { since: 11445 } for the raw timeline.",
350
+ "proposedConsequences": [
351
+ { "predicate": { "kind": "signal", "name": "auth:granted" }, "tier": 0, "label": "signal \"auth:granted\" fires", "weak": false },
352
+ { "predicate": { "kind": "state", "store": "app", "path": "auth" }, "tier": 1, "label": "state \"app\" changes", "weak": false },
353
+ { "predicate": { "kind": "net", "method": "POST", "urlContains": "/api/login", "status": 200 }, "tier": 1, "label": "POST /api/login responds", "weak": false }
354
+ ],
355
+ "window_ms": 17387,
356
+ "summary": { "total": 445, "network": 1, "domChanged": 304, "consoleErrors": 0, "animations": 12, "signals": 1 },
357
+ "cost": { "events": 445, "bytes": 953 }
358
+ }
359
+ ```
360
+
361
+ Each step's `args` is elided above because a recorded step is an anchor, not a call you make by hand: it resolves a testid at replay time rather than a `ref`, so copying it into [`reticle_act`](/tools-act) would not work.
362
+
363
+ Nine hundred and fifty-three bytes for 445 recorded events. `timeline_omitted` hands you the exact `reticle_observe` call to make if you want them, so nothing is lost, it is only not charged for by default.
364
+
365
+ <Note>
366
+ `reticle_record` takes `action`, `recordingName` and `sessionId` and nothing else. `max_events`
367
+ and `filters` are rejected, which no longer matters now that the timeline is omitted anyway.
368
+ </Note>
369
+
370
+ `proposedConsequences` is the useful part and the reason to record at all. Reticle watched the interaction and worked out what would have proved it, ranked by strength. Tier 0 is the app's own signal. You do not have to invent the assertion; you pick one.
371
+
372
+ ### Saving and replaying
373
+
374
+ ```json
375
+ { "tool": "reticle_flow_save", "args": { "flowName": "ship-a-deploy" } }
376
+ ```
377
+
378
+ ```json
379
+ {
380
+ "name": "ship-a-deploy",
381
+ "stepCount": 1,
382
+ "degraded": 0,
383
+ "empty": false,
384
+ "assertions": {
385
+ "grade": "assertion-free",
386
+ "hasConsequenceAssertion": false,
387
+ "totalSteps": 1,
388
+ "consequenceSteps": 0,
389
+ "weakSteps": 0,
390
+ "successIsConsequence": false,
391
+ "intentVerified": false,
392
+ "warning": "This flow performs actions but asserts no observable consequence, so it will pass even if the feature is broken. Add a consequence assertion with reticle_annotate (assert-signal / assert-net) or a success-state."
393
+ }
394
+ }
395
+ ```
396
+
397
+ Reticle grades the flow as you save it, and tells you when you have just created a test that cannot fail. Take the warning seriously: an assertion-free flow replays green whatever the app does.
398
+
399
+ A replay against a drifted app names what moved and where. This is `reticle_flow_verify` reporting the same flow after the app changed underneath it:
400
+
401
+ ```json
402
+ {
403
+ "status": "fail",
404
+ "total": 1,
405
+ "passed": 0,
406
+ "failed": 1,
407
+ "failures": [
408
+ {
409
+ "flow": "docs-check",
410
+ "verdict": "drift",
411
+ "whatChanged": "testid \"login-submit\" not found",
412
+ "whereInSource": "src/components/Login.tsx:81",
413
+ "nextAction": "rebind the anchor to \"sign-out\" (closest survivor), or update the flow if the change was intended."
414
+ }
415
+ ],
416
+ "flaky": ["suite-500", "suite-route", "drift-demo", "stitch-probe"]
417
+ }
418
+ ```
419
+
420
+ Passing flows are counted, not described. Only failures carry detail, because the detail is the actionable part. `flaky` lists flows seen to both pass and fail on unchanged code, which is a bug in the flow rather than in the app.
421
+
422
+ `reticle_flow_heal` proposes the rebind. It refuses when it is not confident:
423
+
424
+ ```json
425
+ {
426
+ "status": "unhealable",
427
+ "applied": false,
428
+ "message": "drift found, but no nearest match cleared the confidence floor (HEAL_CONFIDENCE_MIN=0.5); file left untouched; add a data-testid or fix the flow by hand"
429
+ }
430
+ ```
431
+
432
+ Flows live in `.reticle/` as human-readable files, so they are reviewed in pull requests and diffed like code. They anchor on meaning, a testid plus a signal, rather than volatile refs or coordinates.
433
+
434
+ <Card title="Flows in full" icon="repeat" href="/flows">
435
+ Recording, replay, self-healing, and what lives in `.reticle/`.
436
+ </Card>
437
+
438
+ ## Handing results to something else
439
+
440
+ ### The CI artifact
441
+
442
+ ```json
443
+ { "tool": "reticle_run_export" }
444
+ ```
445
+
446
+ ```json
447
+ {
448
+ "run": {
449
+ "schemaVersion": 1,
450
+ "runId": "1f49b2d8-e402-4629-b202-819566fcace5",
451
+ "createdAt": 1786817831460,
452
+ "durationMs": 4,
453
+ "profile": "dev",
454
+ "project": { "name": "reticle", "framework": "other" },
455
+ "agent": { "id": "reticle-mcp", "kind": "coding-agent" },
456
+ "trigger": { "kind": "manual" },
457
+ "changedFiles": [],
458
+ "flows": [
459
+ {
460
+ "name": "sweep-flow",
461
+ "status": "fail",
462
+ "steps": 0,
463
+ "durationMs": 4,
464
+ "failureReason": "no such flow on disk, run reticle_flow{action:\"list\"} to see saved flows"
465
+ }
466
+ ],
467
+ "checks": [],
468
+ "risks": [],
469
+ "evidence": {
470
+ "consoleErrors": [],
471
+ "networkAnomalies": [],
472
+ "stateAssertions": [],
473
+ "timeline": []
474
+ },
475
+ "verdict": {
476
+ "status": "fail",
477
+ "reasons": ["flow sweep-flow: no such flow on disk"],
478
+ "confidence": "medium",
479
+ "blockingRisks": 0
480
+ }
481
+ }
482
+ }
483
+ ```
484
+
485
+ Note the `run` wrapper. The artifact is nested one level down, which matters if you are parsing it in CI.
486
+
487
+ A versioned, machine-readable record of a verification run. This is what you hand to CI, a dashboard, or a platform embedding Reticle in its pipeline. A passing flow additionally carries `oracle`, the consequence that made it a pass, so a green row says what it proved rather than only that it was green.
488
+
489
+ ### The capability contract
490
+
491
+ ```json
492
+ { "tool": "reticle_contract_save" }
493
+ ```
494
+
495
+ ```json
496
+ { "saved": true, "path": ".reticle/contract.json", "testidCount": 49, "signalCount": 16 }
497
+ ```
498
+
499
+ Read it back with `reticle_capabilities { "fromDisk": true }`, which needs no browser at all.
500
+
501
+ Persists the app's live capability registry to a git-checked file. A fresh agent can read it without booting the app, and a diff shows when someone removes a signal something depended on.
502
+
503
+ ### Talking to the human
504
+
505
+ ```json
506
+ { "tool": "reticle_session", "args": { "action": "narrate", "text": "Checking the deploy flow." } }
507
+ { "tool": "reticle_session", "args": { "action": "review" } }
508
+ ```
509
+
510
+ `narrate` writes a line into the presenter panel, so the person watching knows what you are doing. `review` drains the bugs they pinned on elements from that panel:
511
+
512
+ ```json
513
+ { "marks": [], "pendingCount": 0 }
514
+ ```
515
+
516
+ An empty list here is a real reading, not a missing one.
517
+
518
+ ## Discovering the rest
519
+
520
+ ```json
521
+ { "tool": "reticle_tools" }
522
+ ```
523
+
524
+ Returns every tool with a one-line summary, and the profile currently in force. Load the full argument grammar for the ones you want before calling them:
525
+
526
+ ```json
527
+ { "names": ["reticle_network_mock", "reticle_clock"] }
528
+ ```
529
+
530
+ <Tip>
531
+ Do this rather than guessing at arguments. Reticle refuses a call with unknown parameters rather
532
+ than running it, and says why: *"NOT applied, so any result would be an answer to a different
533
+ question."* Good behaviour, but a wasted turn you can skip.
534
+ </Tip>
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: reticle affected
3
+ description: List which saved flows must re-verify for a set of changed files.
4
+ icon: code-branch
5
+ ---
6
+
7
+ `reticle affected` answers one question: given these changed files, which saved flows cover them? It is the foundation the [gate](/cli/gate) and [watch](/cli/watch) are built on, and it costs your agent nothing per turn because it runs in the environment.
8
+
9
+ ```bash
10
+ npx @reticlehq/server affected [--since <ref>] [file...]
11
+ ```
12
+
13
+ ## Arguments and flags
14
+
15
+ | Argument | Type | Default | What it does |
16
+ | --- | --- | --- | --- |
17
+ | `file...` | strings, positional | none | Explicit changed files |
18
+ | `--since <ref>` | string | `HEAD` when no files are given | Also include files git reports as changed since this ref |
19
+
20
+ With nothing after it, `reticle affected` means the working tree against `HEAD`. It used to be a usage error, while the rule `reticle init` writes into the agent's own instruction file told the agent to run it.
21
+
22
+ ## What it prints
23
+
24
+ One `reticle_affected` line. Real capture from this repository, with the file and flow lists trimmed for length:
25
+
26
+ ```json
27
+ {
28
+ "t": "2026-08-15T18:42:58.072Z",
29
+ "event": "reticle_affected",
30
+ "changedFiles": ["docs/cli.mdx"],
31
+ "affected": ["WEB-flow", "console-compose", "deploy-journey", "verify-route"],
32
+ "unknownProvenance": ["WEB-flow", "console-compose", "deploy-journey", "verify-route"]
33
+ }
34
+ ```
35
+
36
+ The real run named 47 flows in each list. The CLI prints this as a single line of JSON; it is pretty-printed here to be readable.
37
+
38
+ | Field | Meaning |
39
+ | --- | --- |
40
+ | `changedFiles` | The resolved file set: your positional arguments plus whatever `--since` added |
41
+ | `affected` | Saved flows that cover at least one of those files |
42
+ | `unknownProvenance` | Flows with no recorded source mapping. They are listed as affected because the safe assumption is that they might be |
43
+
44
+ ## Exit codes
45
+
46
+ Always `0`. A load error is logged as `reticle_affected_failed`, not thrown. Use [`reticle gate`](/cli/gate) when you want a non-zero exit.
47
+
48
+ ## Worked example
49
+
50
+ ```bash
51
+ npx @reticlehq/server affected --since origin/main
52
+ npx @reticlehq/server affected src/components/Login.tsx
53
+ ```
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: reticle capsules
3
+ description: List the saved fail-to-pass bug capsules recorded from failed assertions.
4
+ icon: capsules
5
+ ---
6
+
7
+ `reticle capsules` lists what is in `.reticle/capsules`. A capsule is a minimal failing reproduction plus the consequence that should have held. Replay one with the `reticle_flow_replay` tool.
8
+
9
+ ```bash
10
+ npx @reticlehq/server capsules
11
+ ```
12
+
13
+ No flags.
14
+
15
+ ## What it prints
16
+
17
+ One `reticle_capsules` line: a `count` and an array. Real capture from this repository, trimmed to three of the seventy-nine entries and pretty-printed (the CLI prints it as a single line):
18
+
19
+ ```json
20
+ {
21
+ "t": "2026-08-15T18:42:48.790Z",
22
+ "event": "reticle_capsules",
23
+ "count": 79,
24
+ "capsules": [
25
+ {
26
+ "id": "1786793143459-e5",
27
+ "origin": "failed-assert",
28
+ "expected": "signal auth:granted",
29
+ "observed": "signal \"auth:granted\" never fired",
30
+ "steps": 1
31
+ },
32
+ {
33
+ "id": "1786791565180-e12",
34
+ "origin": "failed-assert",
35
+ "expected": "declared consequence",
36
+ "observed": "route is '/actions', expected '/server-actions'",
37
+ "steps": 1
38
+ },
39
+ {
40
+ "id": "1785653101906-e3",
41
+ "origin": "failed-assert",
42
+ "expected": "declared consequence",
43
+ "observed": "not settled: 236 request(s) still in flight",
44
+ "steps": 1
45
+ }
46
+ ]
47
+ }
48
+ ```
49
+
50
+ | Field | Meaning |
51
+ | ---------- | ------------------------------------------------ |
52
+ | `id` | Capsule id, timestamp plus a cursor |
53
+ | `flow` | Present when the capsule came from a named flow |
54
+ | `origin` | How it was captured, for example `failed-assert` |
55
+ | `expected` | The consequence that was declared |
56
+ | `observed` | What actually happened |
57
+ | `steps` | How many steps the reproduction is |
58
+
59
+ ## Exit codes
60
+
61
+ | Code | Meaning |
62
+ | ---- | ------------------------------------------------------------------------ |
63
+ | `0` | Listed, even when the count is zero |
64
+ | `1` | The capsule store could not be read. Logged as `reticle_capsules_failed` |
65
+
66
+ ## Worked example
67
+
68
+ ```bash
69
+ npx @reticlehq/server capsules | jq '.capsules[] | select(.origin == "failed-assert") | .observed'
70
+ ```