@reticlehq/server 2.6.0 → 2.8.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 (276) hide show
  1. package/README.md +14 -5
  2. package/SKILL.md +251 -33
  3. package/dist/bridge/bridge.d.ts +6 -1
  4. package/dist/bridge/bridge.js +27 -4
  5. package/dist/capsule/causal-summary.d.ts +20 -0
  6. package/dist/capsule/causal-summary.js +31 -6
  7. package/dist/capsule/divergence.js +7 -1
  8. package/dist/cli/chromium-hint.d.ts +68 -0
  9. package/dist/cli/chromium-hint.js +145 -0
  10. package/dist/cli/cli-doctor.js +31 -36
  11. package/dist/cli/cli-kill.d.ts +58 -0
  12. package/dist/cli/cli-kill.js +162 -0
  13. package/dist/cli/cli-launch.d.ts +18 -0
  14. package/dist/cli/cli-launch.js +32 -1
  15. package/dist/cli/cli-parse.d.ts +16 -1
  16. package/dist/cli/cli-parse.js +32 -9
  17. package/dist/cli/cli-port.d.ts +8 -0
  18. package/dist/cli/cli-port.js +36 -1
  19. package/dist/cli/cli-verify.js +2 -2
  20. package/dist/cli/doctor-daemon-line.js +10 -1
  21. package/dist/cli/doctor-sessions-line.d.ts +12 -0
  22. package/dist/cli/doctor-sessions-line.js +66 -0
  23. package/dist/cli/port-holder.d.ts +10 -0
  24. package/dist/cli/port-holder.js +26 -2
  25. package/dist/cli.js +139 -23
  26. package/dist/crawl/crawl-tools.js +12 -2
  27. package/dist/crawl/crawl.d.ts +13 -0
  28. package/dist/crawl/crawl.js +50 -2
  29. package/dist/daemon/daemon-resilience.js +2 -2
  30. package/dist/daemon/loopback-alias.d.ts +32 -0
  31. package/dist/daemon/loopback-alias.js +80 -0
  32. package/dist/events/contradictions.d.ts +14 -0
  33. package/dist/events/contradictions.js +26 -17
  34. package/dist/events/predicate-eval.d.ts +26 -3
  35. package/dist/events/predicate-eval.js +284 -95
  36. package/dist/events/predicate-parse.d.ts +1 -1
  37. package/dist/events/predicate-parse.js +18 -4
  38. package/dist/events/predicate.js +170 -18
  39. package/dist/events/ring-buffer.d.ts +8 -0
  40. package/dist/events/ring-buffer.js +34 -1
  41. package/dist/flows/flow-classify.js +1 -1
  42. package/dist/flows/flow-tools.js +12 -4
  43. package/dist/flows/heal-run.js +1 -1
  44. package/dist/honesty/blind-spots.js +6 -2
  45. package/dist/honesty/honesty.d.ts +11 -0
  46. package/dist/honesty/honesty.js +9 -1
  47. package/dist/honesty/unsettled.d.ts +40 -0
  48. package/dist/honesty/unsettled.js +78 -0
  49. package/dist/honesty/verified.d.ts +7 -0
  50. package/dist/honesty/verified.js +27 -4
  51. package/dist/http-server.js +11 -1
  52. package/dist/index.js +29 -2
  53. package/dist/init/agent-rules.d.ts +16 -0
  54. package/dist/init/agent-rules.js +96 -17
  55. package/dist/init/astro-patch.d.ts +2 -1
  56. package/dist/init/astro-patch.js +11 -5
  57. package/dist/init/capabilities.d.ts +22 -0
  58. package/dist/init/capabilities.js +76 -0
  59. package/dist/init/confirm.d.ts +96 -0
  60. package/dist/init/confirm.js +138 -0
  61. package/dist/init/cra.js +3 -2
  62. package/dist/init/detect.d.ts +8 -0
  63. package/dist/init/detect.js +15 -0
  64. package/dist/init/non-js-project.d.ts +27 -0
  65. package/dist/init/non-js-project.js +84 -0
  66. package/dist/init/plan-framework.d.ts +9 -0
  67. package/dist/init/plan-framework.js +72 -16
  68. package/dist/init/plan.d.ts +40 -4
  69. package/dist/init/plan.js +183 -43
  70. package/dist/init/run.d.ts +24 -2
  71. package/dist/init/run.js +181 -46
  72. package/dist/init/slash-command.d.ts +1 -1
  73. package/dist/init/slash-command.js +46 -6
  74. package/dist/init/snippets.d.ts +64 -5
  75. package/dist/init/snippets.js +220 -31
  76. package/dist/init/vite-config.js +29 -3
  77. package/dist/input/network-mock-tools.d.ts +19 -0
  78. package/dist/input/network-mock-tools.js +29 -4
  79. package/dist/license/license.js +1 -1
  80. package/dist/mcp/mcp-proxy.d.ts +69 -3
  81. package/dist/mcp/mcp-proxy.js +215 -23
  82. package/dist/mcp/mcp.js +58 -7
  83. package/dist/mcp/proxy-lifecycle.d.ts +20 -1
  84. package/dist/mcp/proxy-lifecycle.js +22 -1
  85. package/dist/pool/browser-pool.d.ts +22 -2
  86. package/dist/pool/browser-pool.js +44 -4
  87. package/dist/pool/playwright-launcher.js +10 -2
  88. package/dist/project/learned-routes.d.ts +24 -0
  89. package/dist/project/learned-routes.js +63 -0
  90. package/dist/project/project-store.d.ts +6 -0
  91. package/dist/project/project-store.js +25 -1
  92. package/dist/session/live-control-tools.js +39 -2
  93. package/dist/session/live-control.d.ts +7 -9
  94. package/dist/session/live-control.js +34 -1
  95. package/dist/session/no-session-diagnosis.d.ts +23 -4
  96. package/dist/session/no-session-diagnosis.js +128 -44
  97. package/dist/session/no-session-watch.js +12 -0
  98. package/dist/session/ref-provenance.d.ts +54 -0
  99. package/dist/session/ref-provenance.js +61 -0
  100. package/dist/session/review-store.d.ts +19 -0
  101. package/dist/session/review-store.js +34 -5
  102. package/dist/session/session-lease.js +1 -1
  103. package/dist/session/session-manager.d.ts +9 -0
  104. package/dist/session/session-manager.js +11 -0
  105. package/dist/session/session.d.ts +8 -0
  106. package/dist/session/session.js +12 -0
  107. package/dist/status-payload.d.ts +13 -1
  108. package/dist/status-payload.js +6 -1
  109. package/dist/telemetry/app-instrumented.d.ts +37 -0
  110. package/dist/telemetry/app-instrumented.js +54 -0
  111. package/dist/telemetry/automation-hint.d.ts +17 -0
  112. package/dist/telemetry/automation-hint.js +71 -0
  113. package/dist/telemetry/bug-found.d.ts +0 -20
  114. package/dist/telemetry/bug-found.js +38 -21
  115. package/dist/telemetry/cli-telemetry.js +7 -1
  116. package/dist/telemetry/daemon-telemetry.d.ts +4 -4
  117. package/dist/telemetry/daemon-telemetry.js +8 -4
  118. package/dist/telemetry/feedback.js +1 -1
  119. package/dist/telemetry/init-telemetry.js +9 -1
  120. package/dist/telemetry/install-source.d.ts +36 -0
  121. package/dist/telemetry/install-source.js +40 -0
  122. package/dist/telemetry/run-telemetry.js +4 -1
  123. package/dist/telemetry/session-metrics.d.ts +3 -3
  124. package/dist/telemetry/session-metrics.js +9 -4
  125. package/dist/telemetry/telemetry.d.ts +7 -1
  126. package/dist/telemetry/telemetry.js +17 -2
  127. package/dist/telemetry/tool-refused.d.ts +19 -0
  128. package/dist/telemetry/tool-refused.js +55 -0
  129. package/dist/telemetry/verification-of.js +72 -8
  130. package/dist/temp-dir.d.ts +27 -0
  131. package/dist/temp-dir.js +46 -0
  132. package/dist/tools/act-tools.js +77 -11
  133. package/dist/tools/assert-grade.d.ts +1 -1
  134. package/dist/tools/assert-grade.js +27 -5
  135. package/dist/tools/assert-verdict.js +25 -1
  136. package/dist/tools/contract-tools.js +4 -0
  137. package/dist/tools/dynamic-tools.js +1 -1
  138. package/dist/tools/error-recovery.d.ts +10 -0
  139. package/dist/tools/error-recovery.js +70 -5
  140. package/dist/tools/feedback-invite.js +1 -1
  141. package/dist/tools/invoke-tool.js +149 -32
  142. package/dist/tools/lease-tools.d.ts +29 -1
  143. package/dist/tools/lease-tools.js +58 -5
  144. package/dist/tools/navigate-result.js +1 -1
  145. package/dist/tools/observe-tools.js +1 -1
  146. package/dist/tools/observed-nothing.js +1 -1
  147. package/dist/tools/react-grace.d.ts +48 -0
  148. package/dist/tools/react-grace.js +87 -0
  149. package/dist/tools/read-tools.js +20 -4
  150. package/dist/tools/settle-in-flight.d.ts +79 -0
  151. package/dist/tools/settle-in-flight.js +106 -0
  152. package/dist/tools/snapshot-delta.d.ts +7 -0
  153. package/dist/tools/snapshot-delta.js +130 -6
  154. package/dist/tools/tool-kit.d.ts +52 -5
  155. package/dist/tools/tool-kit.js +55 -24
  156. package/dist/tools/tool-surface.js +28 -9
  157. package/dist/tools/tools.js +38 -4
  158. package/dist/visual/capture-cleanup.d.ts +16 -0
  159. package/dist/visual/capture-cleanup.js +39 -0
  160. package/dist/visual/visual-tools.d.ts +18 -0
  161. package/dist/visual/visual-tools.js +24 -5
  162. package/docs/README.md +56 -11
  163. package/docs/actions.mdx +87 -0
  164. package/docs/agent-cheatsheet.md +102 -26
  165. package/docs/architecture.md +46 -35
  166. package/docs/benchmarks.md +76 -72
  167. package/docs/best-practices.mdx +211 -0
  168. package/docs/capabilities.mdx +387 -0
  169. package/docs/cli/affected.mdx +51 -0
  170. package/docs/cli/capsules.mdx +69 -0
  171. package/docs/cli/cloud.mdx +127 -0
  172. package/docs/cli/doctor.mdx +76 -0
  173. package/docs/cli/drive.mdx +55 -0
  174. package/docs/cli/feedback.mdx +67 -0
  175. package/docs/cli/gate.mdx +64 -0
  176. package/docs/cli/help.mdx +92 -0
  177. package/docs/cli/hunt.mdx +57 -0
  178. package/docs/cli/identify.mdx +62 -0
  179. package/docs/cli/init.mdx +94 -0
  180. package/docs/cli/kill.mdx +91 -0
  181. package/docs/cli/license.mdx +48 -0
  182. package/docs/cli/mcp.mdx +61 -0
  183. package/docs/cli/open.mdx +68 -0
  184. package/docs/cli/restart.mdx +60 -0
  185. package/docs/cli/rollback.mdx +35 -0
  186. package/docs/cli/serve.mdx +62 -0
  187. package/docs/cli/status.mdx +64 -0
  188. package/docs/cli/stop.mdx +56 -0
  189. package/docs/cli/telemetry.mdx +57 -0
  190. package/docs/cli/update.mdx +52 -0
  191. package/docs/cli/verify.mdx +57 -0
  192. package/docs/cli/version.mdx +39 -0
  193. package/docs/cli/watch.mdx +55 -0
  194. package/docs/cli.mdx +219 -0
  195. package/docs/debugging.md +13 -9
  196. package/docs/deploy-checks.md +15 -11
  197. package/docs/desktop-apps.md +49 -40
  198. package/docs/desktop.mdx +188 -0
  199. package/docs/docs.json +363 -0
  200. package/docs/enterprise.md +20 -16
  201. package/docs/faq.mdx +88 -0
  202. package/docs/fixtures.md +11 -7
  203. package/docs/flows.md +26 -22
  204. package/docs/for-agents.md +71 -0
  205. package/docs/frameworks.mdx +199 -0
  206. package/docs/gate-plan.md +45 -41
  207. package/docs/gates.md +23 -19
  208. package/docs/getting-started.md +76 -65
  209. package/docs/human-control.md +22 -18
  210. package/docs/index.mdx +101 -0
  211. package/docs/install-agentic.mdx +215 -0
  212. package/docs/install-manual.mdx +194 -0
  213. package/docs/instrumentation.mdx +232 -0
  214. package/docs/integration-patterns.md +38 -34
  215. package/docs/local-registry.md +16 -12
  216. package/docs/multi-agent-testing.md +16 -12
  217. package/docs/packages/babel-plugin.mdx +70 -0
  218. package/docs/packages/browser.mdx +111 -0
  219. package/docs/packages/core.mdx +106 -0
  220. package/docs/packages/electron.mdx +87 -0
  221. package/docs/packages/eslint-plugin.mdx +84 -0
  222. package/docs/packages/next.mdx +91 -0
  223. package/docs/packages/react.mdx +91 -0
  224. package/docs/packages/server.mdx +98 -0
  225. package/docs/packages/tauri.mdx +63 -0
  226. package/docs/packages/test.mdx +108 -0
  227. package/docs/packages/vite-plugin.mdx +96 -0
  228. package/docs/packages.mdx +217 -0
  229. package/docs/platform-integration.md +33 -26
  230. package/docs/predicates.mdx +179 -0
  231. package/docs/quickstart.mdx +211 -0
  232. package/docs/recipes.mdx +242 -0
  233. package/docs/skill-file.mdx +105 -0
  234. package/docs/state-management.mdx +197 -0
  235. package/docs/style.css +14 -0
  236. package/docs/system-map.md +47 -32
  237. package/docs/telemetry-contract.md +101 -46
  238. package/docs/telemetry-events.mdx +430 -0
  239. package/docs/telemetry.md +63 -50
  240. package/docs/testing.md +10 -6
  241. package/docs/token-efficiency.md +30 -26
  242. package/docs/tools-act-and-wait.mdx +123 -0
  243. package/docs/tools-act-sequence.mdx +120 -0
  244. package/docs/tools-act.mdx +82 -0
  245. package/docs/tools-assert.mdx +70 -0
  246. package/docs/tools-console.mdx +59 -0
  247. package/docs/tools-inspect.mdx +85 -0
  248. package/docs/tools-navigate.mdx +63 -0
  249. package/docs/tools-network.mdx +86 -0
  250. package/docs/tools-observe.mdx +89 -0
  251. package/docs/tools-overview.mdx +157 -0
  252. package/docs/tools-query.mdx +82 -0
  253. package/docs/tools-session-and-feedback.mdx +91 -0
  254. package/docs/tools-sessions.mdx +65 -0
  255. package/docs/tools-snapshot.mdx +75 -0
  256. package/docs/tools-state.mdx +81 -0
  257. package/docs/tools-tools-and-run.mdx +125 -0
  258. package/docs/tools-wait-for.mdx +66 -0
  259. package/docs/troubleshooting.mdx +193 -0
  260. package/docs/usage.md +175 -153
  261. package/docs/vs-chrome-devtools-mcp.mdx +82 -0
  262. package/docs/vs-playwright-mcp.mdx +85 -0
  263. package/docs/vs-screenshots.mdx +96 -0
  264. package/docs/what-is-reticle.mdx +63 -0
  265. package/docs/why-reticle.mdx +107 -0
  266. package/package.json +2 -2
  267. package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
  268. package/docs/matrix/2.5.0/codex-machine.json +0 -20
  269. package/docs/matrix/2.5.0/cursor-machine.json +0 -22
  270. package/docs/matrix/2.5.0/gemini-machine.json +0 -22
  271. package/docs/matrix/2.5.0/opencode-machine.json +0 -22
  272. package/docs/matrix/2.5.0/vscode-machine.json +0 -22
  273. package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
  274. package/docs/matrix/MATRIX.md +0 -26
  275. package/docs/matrix/README.md +0 -59
  276. package/docs/mint.json +0 -61
@@ -0,0 +1,120 @@
1
+ ---
2
+ title: reticle_act_sequence
3
+ description: Run several actions in order in one round trip. Fill, fill, submit. Instead of paying a full turn for each step.
4
+ icon: layer-group
5
+ ---
6
+
7
+ A login is three actions. Driving it one call at a time costs three round trips and three turns of context. `reticle_act_sequence` does it in one.
8
+
9
+ This tool exists because of a measured problem: agents were driving forms one call at a time, over and over. Those repeats were not retries. The calls succeeded and got repeated, because the batching tool was not advertised and so nobody knew it was there.
10
+
11
+ ## Example
12
+
13
+ ```json
14
+ {
15
+ "steps": [
16
+ { "ref": "e101", "action": "fill", "args": { "value": "admin@reticle.dev" } },
17
+ { "ref": "e102", "action": "fill", "args": { "value": "correct-horse-battery-staple" } },
18
+ { "ref": "e103", "action": "click" }
19
+ ]
20
+ }
21
+ ```
22
+
23
+ Real response, trimmed:
24
+
25
+ ```json
26
+ {
27
+ "since": 13776,
28
+ "dispatched": true,
29
+ "result": {
30
+ "ok": true,
31
+ "count": 3,
32
+ "effects": [
33
+ {
34
+ "dispatched": true,
35
+ "focusMoved": "null->e101",
36
+ "valueChanged": false,
37
+ "domMutatedWithin": 6
38
+ },
39
+ {
40
+ "dispatched": true,
41
+ "focusMoved": "e101->e102",
42
+ "valueChanged": true,
43
+ "domMutatedWithin": 10
44
+ },
45
+ {
46
+ "dispatched": true,
47
+ "focusMoved": "e102->null",
48
+ "domMutatedWithin": 15,
49
+ "appeared": "Signing in… | Invalid email or password | Sign in"
50
+ }
51
+ ],
52
+ "steps": [
53
+ {
54
+ "ref": "e101",
55
+ "action": "fill",
56
+ "testid": "login-email",
57
+ "source": { "file": "src/components/Login.tsx", "line": 48 }
58
+ },
59
+ {
60
+ "ref": "e102",
61
+ "action": "fill",
62
+ "testid": "login-password",
63
+ "source": { "file": "src/components/Login.tsx", "line": 59 }
64
+ },
65
+ {
66
+ "ref": "e103",
67
+ "action": "click",
68
+ "testid": "login-submit",
69
+ "source": { "file": "src/components/Login.tsx", "line": 81 }
70
+ }
71
+ ]
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## Read that response again
77
+
78
+ `ok: true`. `count: 3`. Every step dispatched. And the login **failed**, look at `appeared`:
79
+
80
+ ```
81
+ "appeared": "Signing in… | Invalid email or password | Sign in"
82
+ ```
83
+
84
+ That password was wrong. The app rejected it. And this tool still reported `ok: true`, correctly, because `ok` means _the three actions were dispatched_, which they were.
85
+
86
+ <Warning>
87
+ This is the whole reason `act` and `act_sequence` do not produce verdicts. `ok: true` is a
88
+ statement about the input, not about the outcome. Follow a sequence with
89
+ [`reticle_act_and_wait`](/tools-act-and-wait) on the final step, or with an
90
+ [`reticle_assert`](/tools-assert), or you have proved nothing.
91
+ </Warning>
92
+
93
+ The honest pattern is: batch the setup, prove the outcome.
94
+
95
+ ```json
96
+ {
97
+ "steps": [
98
+ { "ref": "e101", "action": "fill", "args": { "value": "admin@reticle.dev" } },
99
+ { "ref": "e102", "action": "fill", "args": { "value": "reticle" } }
100
+ ]
101
+ }
102
+ ```
103
+
104
+ then
105
+
106
+ ```json
107
+ { "ref": "e103", "action": "click", "until": { "kind": "signal", "name": "auth:granted" } }
108
+ ```
109
+
110
+ Two calls instead of four, and the last one returns a verdict.
111
+
112
+ ## What each step reports
113
+
114
+ Every step comes back with the same `effect` fields as [`reticle_act`](/tools-act): `valueChanged`, `focusMoved`, `domMutatedWithin`, `occluded`. Plus its `testid`, `component` and `source`. When a sequence goes wrong, that per-step detail tells you which step, and which line of which file.
115
+
116
+ <Note>
117
+ Steps run in order and do not stop on a soft failure, because "the field rejected the value" is
118
+ not an exception. It's a result you need to see. Read `effects[]` rather than assuming `ok: true`
119
+ means all three did what you wanted.
120
+ </Note>
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: reticle_act
3
+ description: Perform an action without checking the result. Useful for setup steps, and dangerous as a final step, because ok means dispatched, not worked.
4
+ icon: hand-pointer
5
+ ---
6
+
7
+ `reticle_act` clicks, fills, types, selects, drags. It does exactly one thing and makes exactly one promise: the event was dispatched.
8
+
9
+ <Warning>
10
+ `reticle_act` **proves nothing**. If the action is supposed to cause something, use
11
+ [`reticle_act_and_wait`](/tools-act-and-wait) and get the verdict in the same call. A drive that
12
+ ends on `reticle_act` has no result.
13
+ </Warning>
14
+
15
+ ## Example
16
+
17
+ ```json
18
+ { "ref": "e102", "action": "fill", "args": { "value": "reticle" } }
19
+ ```
20
+
21
+ Real response:
22
+
23
+ ```json
24
+ {
25
+ "since": 28123,
26
+ "inputMode": "synthetic",
27
+ "dispatched": true,
28
+ "settled": false,
29
+ "settleReason": "timeout",
30
+ "result": {
31
+ "ok": true,
32
+ "ref": "e102",
33
+ "action": "fill",
34
+ "testid": "login-password",
35
+ "component": "Login",
36
+ "role": "textbox",
37
+ "name": "Password",
38
+ "effect": {
39
+ "visible": false,
40
+ "focusMoved": "null->e102",
41
+ "valueChanged": true,
42
+ "domMutatedWithin": 15
43
+ },
44
+ "source": { "file": "src/components/Login.tsx", "line": 59, "column": 8 }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Actions
50
+
51
+ `click` · `dblclick` · `hover` · `focus` · `blur` · `fill` · `type` · `clear` · `select` · `check` · `uncheck` · `submit` · `press` · `upload` · `scrollIntoView` · `drag` · `webmcp`
52
+
53
+ | Action | Arguments |
54
+ | ---------------- | --------------------------------------------------------------- |
55
+ | `fill`, `select` | `{ value }` |
56
+ | `type`, `press` | `{ text }`. For `press`, the key _name_, e.g. `Escape` or `Tab` |
57
+ | `drag` | `{ toRef }`. The ref to drop onto |
58
+ | `upload` | file arguments |
59
+
60
+ ## Reading the effect block
61
+
62
+ This is where `act` earns its place even though it proves nothing.
63
+
64
+ - **`valueChanged: true`**. The field actually took the value. `false` on a `fill` usually means the input is controlled and rejected it, or it's readonly.
65
+ - **`focusMoved: "null->e102"`**, focus went where you expected.
66
+ - **`domMutatedWithin: 15`**, something re-rendered within 15ms. A `fill` that mutates nothing often means no handler is attached.
67
+ - **`defaultPrevented`**. A handler called `preventDefault()`, which is why your form didn't submit.
68
+ - **`occluded` / `occludedBy`**. The click landed on something else. This is the answer to at least half of all "the button doesn't work" reports.
69
+
70
+ ## `settled: false` is not a failure
71
+
72
+ `settleReason: "timeout"` means the page was still busy when Reticle stopped watching. On a `fill` that's normal and uninteresting. On a click you expected to complete something, it's a hint that you wanted `act_and_wait` with an explicit `until`.
73
+
74
+ ## `inputMode` tells you how real the input was
75
+
76
+ `synthetic` means Reticle dispatched events programmatically. `real` means native CDP input, available under `reticle drive`. Synthetic input is fine for the overwhelming majority of apps; a few drag-and-drop and pointer-gesture libraries only respond to the real thing.
77
+
78
+ <Warning>
79
+ When the tab is backgrounded, synthetic timers and pointer gestures can silently no-op. Every
80
+ response carries a `warning` when the tab is throttled. Pass `refuseWhenThrottled: true` to make
81
+ Reticle throw instead of pretending it acted.
82
+ </Warning>
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: reticle_assert
3
+ description: Evaluate a predicate against what the app actually did, and get a verdict. Including a clear explanation when it fails.
4
+ icon: gavel
5
+ ---
6
+
7
+ `reticle_assert` is the second of the two tools that produce a verdict. It takes the same predicate grammar as [`reticle_act_and_wait`](/tools-act-and-wait) and evaluates it against what already happened.
8
+
9
+ ## A real failure
10
+
11
+ Failures are more instructive than passes, so here is one. I asserted a route change to `/` on a page that was already at `/`:
12
+
13
+ ```json
14
+ { "predicate": { "kind": "route", "path": "/" } }
15
+ ```
16
+
17
+ ```json
18
+ {
19
+ "verified": "no",
20
+ "verifiedReason": "assertion_failed",
21
+ "because": "the declared consequence did not hold",
22
+ "pass": false,
23
+ "failureReason": "no route change observed",
24
+ "observed": "no route change in the window",
25
+ "expected": "a route change to /",
26
+ "assertion": "route.changed",
27
+ "source": "src/components/Login.tsx:81"
28
+ }
29
+ ```
30
+
31
+ <Warning>
32
+ Read `assertion: "route.changed"` carefully. The `route` predicate asserts that the route
33
+ **changed**, not that it currently equals a value. Asserting the route you are already on will
34
+ always fail. This catches people out, and the response says so in `expected` rather than leaving
35
+ you to work it out.
36
+ </Warning>
37
+
38
+ Note also `expected` and `observed` side by side. A verdict that says only "failed" makes you go digging; this one tells you what it wanted, what it saw, and where in your source the relevant element lives.
39
+
40
+ ## Arguments
41
+
42
+ | Argument | What it does |
43
+ | ------------------------ | ---------------------------------------------------------- |
44
+ | `predicate` (or `until`) | `{ kind, ...fields }` |
45
+ | `timeout_ms` | If above zero, wait this long before failing |
46
+ | `since` | Cursor from a prior act. Scope to events after that action |
47
+
48
+ ## Scope it with `since`
49
+
50
+ Without `since`, an assertion evaluates against the recent buffer, which may contain events from before your action. That can pass for the wrong reason. The request you are asserting fired, but it fired two clicks ago.
51
+
52
+ ```json
53
+ { "predicate": { "kind": "net", "method": "POST" }, "since": 28123 }
54
+ ```
55
+
56
+ The cursor comes from the preceding `reticle_act` response. Use it whenever you are asserting something an action was supposed to cause.
57
+
58
+ ## When to use assert over act_and_wait
59
+
60
+ Use [`reticle_act_and_wait`](/tools-act-and-wait) when you are performing the action. Use `reticle_assert` when:
61
+
62
+ - you are checking a precondition before acting;
63
+ - the state was reached by several actions and you want one verdict over the lot;
64
+ - you want to assert something extra about an action you already ran, using its `since` cursor.
65
+
66
+ <Note>
67
+ `verified: "unknown"` means Reticle could not tell. It is not a pass, and it is not a failure, it
68
+ is a statement that the evidence was insufficient. Report it as unknown rather than rounding it in
69
+ either direction.
70
+ </Note>
@@ -0,0 +1,59 @@
1
+ ---
2
+ title: reticle_console
3
+ description: The console log, filtered by level, and an empty result that tells you it is a real reading rather than a missing one.
4
+ icon: terminal
5
+ ---
6
+
7
+ ```json
8
+ { "limit": 3 }
9
+ ```
10
+
11
+ Real response from a page with a clean console:
12
+
13
+ ```json
14
+ {
15
+ "logs": [],
16
+ "buffer": {
17
+ "held": 15,
18
+ "dropped": 571,
19
+ "note": "event buffer evicted older events (age/size cap): a negative result here may be a false negative; the evidence may have expired. Grade sooner or widen the buffer."
20
+ },
21
+ "observed": true,
22
+ "note": "no console lines; the observation ran and found none, which is a result, not a missing reading",
23
+ "cost": { "bytes": 340, "tokens": 85 }
24
+ }
25
+ ```
26
+
27
+ ## The empty result is the interesting one
28
+
29
+ An empty array is ambiguous in almost every tool that returns one. Did nothing happen, or did the observation not run? Reticle answers both:
30
+
31
+ - **`observed: true`** with that `note`. The observation ran and genuinely found nothing. You may treat a clean console as a fact.
32
+ - **`buffer.dropped: 571`**, older events were evicted. If you are asking about something from a while ago, the honest answer is "not in what I still have", not "it didn't happen".
33
+
34
+ Read both fields together. `observed: true` with a large `dropped` count means _recently_ clean, which is usually what you wanted but is not the same as _always_ clean.
35
+
36
+ ## Arguments
37
+
38
+ | Argument | What it does |
39
+ | ----------------- | ---------------------------------------------------- |
40
+ | `level` | `log` · `warn` · `error` · `info` |
41
+ | `limit` | Most recent N. Older matches are dropped and counted |
42
+ | `actionId` | Only lines attributed to one action |
43
+ | `since` / `until` | Cursors from a prior act |
44
+
45
+ ## The check worth making by default
46
+
47
+ Plenty of features "work" while quietly throwing. Assert the clean console as part of the action rather than checking afterwards:
48
+
49
+ ```json
50
+ { "ref": "e103", "action": "click", "until": { "kind": "console", "absent": true } }
51
+ ```
52
+
53
+ That fails if the click succeeds _and_ logs an error, which is exactly the case a human reviewer tends to wave through.
54
+
55
+ <Tip>
56
+ `level: "error"` is the fast triage read. If it comes back empty with `observed: true`, stop
57
+ looking at the console and go look at [`reticle_network`](/tools-network) or
58
+ [`reticle_state`](/tools-state) instead.
59
+ </Tip>
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: reticle_inspect
3
+ description: Everything about one element. Accessibility properties, geometry, computed styles, design tokens, React component stack, and the exact source file and line.
4
+ icon: crosshairs
5
+ ---
6
+
7
+ `reticle_query` finds elements. `reticle_inspect` tells you everything about one of them. It is the tool that turns a finding into an edit, because it ends with a file and a line number.
8
+
9
+ ## Example
10
+
11
+ ```json
12
+ { "ref": "e20" }
13
+ ```
14
+
15
+ Real response:
16
+
17
+ ```json
18
+ {
19
+ "ref": "e20",
20
+ "role": "button",
21
+ "name": "Compose",
22
+ "visible": true,
23
+ "source": "src/components/Sidebar.tsx:41",
24
+ "tag": "button",
25
+ "occluded": false,
26
+ "states": ["present", "visible", "enabled"],
27
+ "box": { "x": 14, "y": 211.75, "width": 219, "height": 37.5 },
28
+ "styles": {
29
+ "color": "rgb(147, 152, 168)",
30
+ "backgroundColor": "rgba(0, 0, 0, 0)",
31
+ "opacity": "1",
32
+ "cursor": "pointer",
33
+ "display": "flex",
34
+ "visibility": "visible"
35
+ },
36
+ "theme": {
37
+ "colorToken": "--muted",
38
+ "colorTokens": ["--muted"],
39
+ "backgroundToken": null,
40
+ "backgroundTokens": [],
41
+ "offTheme": false,
42
+ "tokenCount": 17,
43
+ "themeScope": ":root"
44
+ },
45
+ "component": {
46
+ "componentStack": ["Sidebar", "App", "QueryClientProvider"],
47
+ "source": { "file": "src/components/Sidebar.tsx", "line": 41, "column": 8 }
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## What each block is for
53
+
54
+ **`component`** is the payoff. The stack `["Sidebar", "App", "QueryClientProvider"]` tells your agent where this element lives in the tree, and `source` tells it which file to open. This needs `@reticlehq/react`; without it you still get everything else.
55
+
56
+ **`theme`** catches a bug class most tools cannot see. `colorToken: "--muted"` means this colour came from your design system. `offTheme: false` means nothing here is a hardcoded hex that slipped past review. An agent that pastes `color: #939AA8` instead of using the token produces a change that looks identical and quietly forks your design system. This field is how that gets caught.
57
+
58
+ Read `colorTokens` rather than `colorToken` when it matters. Design systems routinely give several tokens the same value, and the singular field is `null` whenever more than one matches, because naming an arbitrary winner is worse than admitting the palette cannot tell them apart. `themeScope` says which theme the reading was taken under, so two inspects either side of a theme toggle are comparable instead of quietly contradictory.
59
+
60
+ **`occluded`** is the difference between "visible" and "actually clickable". An element can be present, visible and enabled while sitting under a modal overlay. `states` will look perfect; `occluded: true` is the honest answer.
61
+
62
+ **`box`** is geometry in CSS pixels. Useful for layout assertions and for working out whether something is off-screen rather than hidden.
63
+
64
+ ## When to reach for it
65
+
66
+ <CardGroup cols={2}>
67
+ <Card title="A click did nothing" icon="hand-pointer">
68
+ Check `occluded` and `states` before assuming the handler is broken. Very often the handler is
69
+ fine and something is sitting on top of it.
70
+ </Card>
71
+ <Card title="You need to edit the code" icon="file-pen">
72
+ `component.source` is the file and line. This is the fastest path from symptom to diff.
73
+ </Card>
74
+ <Card title="A style looks wrong" icon="palette">
75
+ `theme.offTheme` tells you whether the value came from your tokens or from somebody's clipboard.
76
+ </Card>
77
+ <Card title="Layout is suspicious" icon="ruler">
78
+ `box` gives you real geometry, no screenshot and no vision model required.
79
+ </Card>
80
+ </CardGroup>
81
+
82
+ <Note>
83
+ `inspect` returns one element in detail. If you find yourself inspecting six things in a row, you
84
+ probably want [`reticle_query`](/tools-query) with `attrs` instead, one call, six answers.
85
+ </Note>
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: reticle_navigate
3
+ description: Move the connected tab to a URL or reload it, and understand why ok does not mean the page arrived.
4
+ icon: compass
5
+ ---
6
+
7
+ ```json
8
+ { "url": "/deployments" }
9
+ ```
10
+
11
+ Real response:
12
+
13
+ ```json
14
+ {
15
+ "ok": true,
16
+ "url": "http://localhost:4312/deployments",
17
+ "confirmed": false,
18
+ "note": "ok means the navigation was DISPATCHED, not that the page arrived. The SDK is torn down by the navigation itself, so nothing here can see the new document. Call reticle_sessions to confirm a session reconnected at the new URL before acting; if none appears, the page did not load or is not instrumented."
19
+ }
20
+ ```
21
+
22
+ ## `confirmed: false` is the honest part
23
+
24
+ A full navigation destroys the document the SDK was living in. Reticle cannot report on the new page from inside the old one, because the old one no longer exists. So it tells you what it actually knows: the navigation was dispatched.
25
+
26
+ Most tools would return `ok: true` and let you assume arrival. When the page then fails to load, or loads without instrumentation, you get a confusing cascade of "element not found" errors several calls later, with nothing pointing at the real cause.
27
+
28
+ ## The pattern after navigating
29
+
30
+ ```json
31
+ { "url": "/deployments" }
32
+ ```
33
+
34
+ then confirm a session reconnected:
35
+
36
+ ```json
37
+ {}
38
+ ```
39
+
40
+ with [`reticle_sessions`](/tools-sessions), and only then snapshot. If no session appears at the new URL, the page did not load or is not instrumented. And you know that immediately rather than three calls later.
41
+
42
+ <Warning>
43
+ **Refs do not survive a navigation.** A new document means new refs. The same "Sign in" button was
44
+ `e5` before a navigation and `e103` after. Re-snapshot; never carry refs across.
45
+ </Warning>
46
+
47
+ ## Arguments
48
+
49
+ | Argument | What it does |
50
+ | -------- | ------------------------------------- |
51
+ | `url` | Where to go. Relative paths work |
52
+ | `reload` | Reload in place instead of navigating |
53
+ | `hard` | With `reload`, bypass the cache |
54
+
55
+ ## Client-side routing is different
56
+
57
+ In a single-page app, clicking a link usually changes the route without destroying the document. That is a route change, not a navigation. Refs survive, and you can assert it directly:
58
+
59
+ ```json
60
+ { "ref": "e19", "action": "click", "until": { "kind": "route", "path": "/deployments" } }
61
+ ```
62
+
63
+ Use `reticle_navigate` for a genuine document load. A deep link, a hard reload, or the first visit.
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: reticle_network
3
+ description: A filtered log of every request the app made, with bodies, status, timing, automatic credential redaction, and an honest note when evidence has expired.
4
+ icon: satellite-dish
5
+ ---
6
+
7
+ `reticle_network` is how an agent checks the thing a screenshot fundamentally cannot show: whether the request actually happened, what it sent, and what came back.
8
+
9
+ ## Example
10
+
11
+ ```json
12
+ { "limit": 3 }
13
+ ```
14
+
15
+ Real response:
16
+
17
+ ```json
18
+ {
19
+ "calls": [
20
+ {
21
+ "method": "POST",
22
+ "url": "http://localhost:8787/api/login",
23
+ "status": 200,
24
+ "statusText": "OK",
25
+ "contentType": "application/json; charset=utf-8",
26
+ "responseSize": 67,
27
+ "requestBody": "{\"email\":\"admin@reticle.dev\",\"password\":\"[REDACTED]\"}",
28
+ "responseBody": "{\"token\":\"[REDACTED]\",\"user\":{\"email\":\"admin@reticle.dev\"}}",
29
+ "ms": 67
30
+ }
31
+ ],
32
+ "buffer": {
33
+ "held": 15,
34
+ "dropped": 529,
35
+ "note": "event buffer evicted older events (age/size cap): a negative result here may be a false negative; the evidence may have expired. Grade sooner or widen the buffer."
36
+ },
37
+ "cost": { "bytes": 547, "tokens": 137 }
38
+ }
39
+ ```
40
+
41
+ ## Redaction is automatic
42
+
43
+ Look at `requestBody`. The password is `[REDACTED]` and so is the returned token, without anyone configuring anything. Reticle strips credential-shaped values before they leave the page, so your agent's context. And any transcript of it, never holds them.
44
+
45
+ The email is not redacted, because an email is not a credential. The line is drawn at secrets.
46
+
47
+ ## The buffer note is the important bit
48
+
49
+ ```json
50
+ "buffer": { "held": 15, "dropped": 529, "note": "…the evidence may have expired…" }
51
+ ```
52
+
53
+ Reticle keeps a bounded event buffer. When it overflows, older events are evicted. And if you then ask "did a POST to `/api/orders` happen?", the honest answer is not "no". It is "not in what I still have."
54
+
55
+ Most tools would return an empty array and let you draw the wrong conclusion. This one tells you the result may be a false negative and suggests grading sooner or widening the buffer. Take that note seriously: a confident "no requests fired" built on evicted evidence is exactly the kind of false green Reticle exists to prevent.
56
+
57
+ ## Filters
58
+
59
+ | Argument | What it does |
60
+ | ----------------- | ---------------------------------------------------------------------- |
61
+ | `urlContains` | Substring the URL must contain |
62
+ | `method` | `GET` · `POST` · `PUT` · `DELETE` · `PATCH` |
63
+ | `status` | Exact status code, e.g. `500` |
64
+ | `ok` | `false` keeps only failures. The fastest way to "did anything break?" |
65
+ | `limit` | Most recent N. Older matches are dropped and counted |
66
+ | `actionId` | Only requests attributed to one action: "what did that click request?" |
67
+ | `since` / `until` | Cursors from a prior act, to scope to a window between two actions |
68
+
69
+ ## Catching a double submit
70
+
71
+ The bug where one click fires two POSTs is invisible on screen and obvious here:
72
+
73
+ ```json
74
+ { "urlContains": "/api/orders", "method": "POST" }
75
+ ```
76
+
77
+ If `calls` has two entries with near-identical timestamps, you have found it. Better still, assert it up front so the agent cannot rationalise it afterwards. `reticle_act_and_wait` accepts an exact count predicate, which turns "roughly one request" into a check that fails at two.
78
+
79
+ ## Checking that nothing fired
80
+
81
+ `ok: false` on an empty result is a genuinely useful answer. Provided the buffer note says nothing was dropped. Read both.
82
+
83
+ <Card title="Prove it, don't just look at it" icon="circle-check" href="/quickstart">
84
+ `reticle_network` reads. It does not produce a verdict. Name the expected request in
85
+ `reticle_act_and_wait` instead.
86
+ </Card>
@@ -0,0 +1,89 @@
1
+ ---
2
+ title: reticle_observe
3
+ description: The full timeline of everything the app did in a window. DOM, network, routing, console, animations and signals, with a summary.
4
+ icon: timeline
5
+ ---
6
+
7
+ `reticle_observe` is the wide-angle lens. Where `reticle_network` and `reticle_console` answer one question each, `observe` returns everything that happened in a window, in order.
8
+
9
+ ## Example
10
+
11
+ ```json
12
+ { "window_ms": 4000, "max_events": 4 }
13
+ ```
14
+
15
+ Real response:
16
+
17
+ ```json
18
+ {
19
+ "window_ms": 4000,
20
+ "events": [
21
+ {
22
+ "t": 925870,
23
+ "type": "page.health",
24
+ "seq": 586,
25
+ "data": {
26
+ "hidden": true,
27
+ "focused": false,
28
+ "runtime": "web",
29
+ "engine": "blink",
30
+ "brand": "chrome",
31
+ "reason": "heartbeat"
32
+ }
33
+ }
34
+ ],
35
+ "summary": {
36
+ "total": 1,
37
+ "network": 0,
38
+ "domAdded": 0,
39
+ "domRemoved": 0,
40
+ "domChanged": 0,
41
+ "routeChanges": 0,
42
+ "consoleErrors": 0,
43
+ "animations": 0,
44
+ "signals": 0
45
+ },
46
+ "cost": { "events": 1, "bytes": 374 }
47
+ }
48
+ ```
49
+
50
+ A quiet window, honestly reported as quiet.
51
+
52
+ ## Read the summary first
53
+
54
+ The `summary` block is the cheap answer. `consoleErrors: 0` and `network: 0` tells you most of what you need without reading a single event. Pull the timeline only when the summary says something interesting happened.
55
+
56
+ ## Arguments
57
+
58
+ | Argument | What it does |
59
+ | ----------------- | ------------------------------------------------------------------ |
60
+ | `window_ms` | How far back to look |
61
+ | `since` / `until` | Cursors from a prior act. The precise way to scope |
62
+ | `actionId` | Only events attributed to one action: "what did that click cause?" |
63
+ | `filters` | Event-type allowlist. The cheapest way to shrink a big timeline |
64
+ | `max_events` | Cap the timeline to the most recent N |
65
+
66
+ ## Scope by cursor, not by clock
67
+
68
+ Every `reticle_act` response includes a `since` cursor. Passing it to `observe` scopes the timeline to exactly what followed that action, with no guessing about how many milliseconds to look back:
69
+
70
+ ```json
71
+ { "since": 28123 }
72
+ ```
73
+
74
+ This is more precise than `window_ms` and it does not drift when the machine is slow. Which matters, because a timing-based window that works on your laptop and fails in CI is a flaky test waiting to happen.
75
+
76
+ ## When to use it
77
+
78
+ Use `observe` when you do not yet know what went wrong. Use the narrow tools when you do.
79
+
80
+ <CardGroup cols={2}>
81
+ <Card title="Good use" icon="circle-check">
82
+ "Something broke after that click, show me everything that happened."
83
+ </Card>
84
+ <Card title="Wasteful use" icon="circle-xmark">
85
+ "Did a POST fire?" [`reticle_network`](/tools-network) answers that far more cheaply.
86
+ </Card>
87
+ </CardGroup>
88
+
89
+ <Note>`observe` reads. It does not produce a verdict. It is for diagnosis, not proof.</Note>