@reticlehq/server 2.8.0 → 2.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 (318) hide show
  1. package/SKILL.md +130 -813
  2. package/dist/bridge/bridge.d.ts +23 -0
  3. package/dist/bridge/bridge.js +80 -2
  4. package/dist/bridge/bridge.test-harness.d.ts +5 -0
  5. package/dist/bridge/bridge.test-harness.js +6 -4
  6. package/dist/capsule/capsule-store.d.ts +2 -2
  7. package/dist/capsule/causal-summary.d.ts +16 -1
  8. package/dist/capsule/causal-summary.js +2 -1
  9. package/dist/cli/cli-doctor.js +41 -13
  10. package/dist/cli/cli-flow-commands.js +8 -8
  11. package/dist/cli/cli-launch.d.ts +0 -17
  12. package/dist/cli/cli-launch.js +0 -28
  13. package/dist/cli/cli-parse.d.ts +1 -1
  14. package/dist/cli/cli-parse.js +1 -1
  15. package/dist/cli/cli-port.d.ts +24 -0
  16. package/dist/cli/cli-port.js +66 -35
  17. package/dist/cli/cli-verify.d.ts +21 -0
  18. package/dist/cli/cli-verify.js +45 -1
  19. package/dist/cli/config-discovery.d.ts +35 -0
  20. package/dist/cli/config-discovery.js +163 -0
  21. package/dist/cli/doctor-daemon-line.js +4 -1
  22. package/dist/cli/doctor-project-line.d.ts +37 -0
  23. package/dist/cli/doctor-project-line.js +35 -0
  24. package/dist/cli/doctor-rows.d.ts +51 -0
  25. package/dist/cli/doctor-rows.js +54 -0
  26. package/dist/cli/doctor-sessions-line.js +6 -3
  27. package/dist/cli/drive-attach.d.ts +99 -0
  28. package/dist/cli/drive-attach.js +203 -0
  29. package/dist/cli/drive-command.d.ts +13 -0
  30. package/dist/cli/drive-command.js +103 -0
  31. package/dist/cli/open-note.d.ts +20 -0
  32. package/dist/cli/open-note.js +37 -0
  33. package/dist/cli/status-next-action.d.ts +37 -0
  34. package/dist/cli/status-next-action.js +61 -0
  35. package/dist/cli.js +65 -70
  36. package/dist/crawl/crawl.d.ts +7 -2
  37. package/dist/crawl/crawl.js +52 -9
  38. package/dist/ee/audit-log.js +2 -2
  39. package/dist/events/body-failures.d.ts +2 -2
  40. package/dist/events/contradiction-folds.d.ts +45 -0
  41. package/dist/events/contradiction-folds.js +42 -0
  42. package/dist/events/contradictions.d.ts +51 -1
  43. package/dist/events/contradictions.js +26 -7
  44. package/dist/events/declared.d.ts +45 -0
  45. package/dist/events/declared.js +73 -0
  46. package/dist/events/echo-mismatch.d.ts +9 -3
  47. package/dist/events/echo-mismatch.js +33 -5
  48. package/dist/events/event-filters.d.ts +1 -1
  49. package/dist/events/event-filters.js +7 -4
  50. package/dist/events/predicate-eval.d.ts +17 -91
  51. package/dist/events/predicate-eval.js +85 -326
  52. package/dist/events/predicate-parse.js +31 -3
  53. package/dist/events/predicate-route.d.ts +32 -0
  54. package/dist/events/predicate-route.js +102 -0
  55. package/dist/events/predicate-schema.d.ts +99 -0
  56. package/dist/events/predicate-schema.js +309 -0
  57. package/dist/events/predicate.d.ts +8 -0
  58. package/dist/events/predicate.js +127 -5
  59. package/dist/events/stale-response.d.ts +2 -3
  60. package/dist/events/stale-response.js +49 -2
  61. package/dist/events/unit-mismatch.d.ts +2 -2
  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-replay-run.js +8 -1
  69. package/dist/flows/flow-tools.js +9 -1
  70. package/dist/flows/replay.js +3 -0
  71. package/dist/flows/verify-change-tools.js +1 -1
  72. package/dist/honesty/accepted-write.d.ts +3 -0
  73. package/dist/honesty/accepted-write.js +8 -3
  74. package/dist/honesty/already-true.js +15 -0
  75. package/dist/honesty/blind-spots.js +4 -0
  76. package/dist/honesty/honesty.d.ts +11 -0
  77. package/dist/honesty/honesty.js +1 -0
  78. package/dist/honesty/uncaptured-bodies.d.ts +4 -2
  79. package/dist/honesty/uncaptured-bodies.js +9 -2
  80. package/dist/honesty/unread-outcome.d.ts +8 -0
  81. package/dist/honesty/unread-outcome.js +36 -9
  82. package/dist/honesty/unsettled.d.ts +9 -0
  83. package/dist/honesty/unsettled.js +7 -3
  84. package/dist/honesty/verified.d.ts +29 -3
  85. package/dist/honesty/verified.js +67 -8
  86. package/dist/http-server.d.ts +19 -0
  87. package/dist/http-server.js +202 -4
  88. package/dist/impact/impact-recorder.d.ts +23 -0
  89. package/dist/impact/impact-recorder.js +76 -0
  90. package/dist/impact/impact-store.d.ts +47 -0
  91. package/dist/impact/impact-store.js +171 -0
  92. package/dist/index.d.ts +25 -0
  93. package/dist/index.js +60 -10
  94. package/dist/init/agent-rules.d.ts +20 -0
  95. package/dist/init/agent-rules.js +36 -0
  96. package/dist/init/astro-patch.js +27 -1
  97. package/dist/init/confirm.d.ts +21 -3
  98. package/dist/init/confirm.js +32 -5
  99. package/dist/init/connect-steps.d.ts +2 -0
  100. package/dist/init/connect-steps.js +50 -0
  101. package/dist/init/csp-check.d.ts +38 -0
  102. package/dist/init/csp-check.js +92 -0
  103. package/dist/init/csp-doctor.d.ts +25 -0
  104. package/dist/init/csp-doctor.js +49 -0
  105. package/dist/init/cursor.js +6 -9
  106. package/dist/init/detect.d.ts +8 -0
  107. package/dist/init/detect.js +33 -3
  108. package/dist/init/mcp-clients.d.ts +1 -0
  109. package/dist/init/mcp-clients.js +51 -7
  110. package/dist/init/mcp.d.ts +16 -2
  111. package/dist/init/mcp.js +23 -1
  112. package/dist/init/plan-framework.d.ts +10 -0
  113. package/dist/init/plan-framework.js +25 -1
  114. package/dist/init/plan.d.ts +7 -2
  115. package/dist/init/plan.js +66 -30
  116. package/dist/init/run.js +11 -5
  117. package/dist/init/slash-command.d.ts +1 -1
  118. package/dist/init/slash-command.js +12 -4
  119. package/dist/init/snippets.d.ts +1 -1
  120. package/dist/init/snippets.js +35 -7
  121. package/dist/init/vite-config.js +24 -2
  122. package/dist/input/network-mock-tools.js +8 -1
  123. package/dist/input/scroll-find.d.ts +6 -0
  124. package/dist/input/scroll-find.js +17 -2
  125. package/dist/input/scroll-tools.js +4 -0
  126. package/dist/journal/attach-journal.d.ts +9 -1
  127. package/dist/journal/attach-journal.js +13 -2
  128. package/dist/journal/journal-query.d.ts +13 -0
  129. package/dist/journal/journal-query.js +28 -3
  130. package/dist/journal/workspace-gitignore.d.ts +10 -0
  131. package/dist/journal/workspace-gitignore.js +59 -0
  132. package/dist/license/license.d.ts +69 -4
  133. package/dist/license/license.js +84 -15
  134. package/dist/mcp/mcp-proxy.d.ts +7 -93
  135. package/dist/mcp/mcp-proxy.js +183 -250
  136. package/dist/mcp/mcp.d.ts +27 -2
  137. package/dist/mcp/mcp.js +77 -36
  138. package/dist/mcp/proxy-daemon-probe.d.ts +8 -0
  139. package/dist/mcp/proxy-daemon-probe.js +48 -0
  140. package/dist/mcp/proxy-handshake.d.ts +82 -1
  141. package/dist/mcp/proxy-handshake.js +110 -3
  142. package/dist/mcp/proxy-lifecycle.d.ts +10 -1
  143. package/dist/mcp/proxy-lifecycle.js +11 -2
  144. package/dist/mcp/proxy-log.d.ts +63 -0
  145. package/dist/mcp/proxy-log.js +132 -0
  146. package/dist/mcp/server-instructions.d.ts +17 -0
  147. package/dist/mcp/server-instructions.js +56 -0
  148. package/dist/mcp/shared-params.d.ts +27 -0
  149. package/dist/mcp/shared-params.js +36 -0
  150. package/dist/mcp/sse-frame-parser.d.ts +19 -0
  151. package/dist/mcp/sse-frame-parser.js +41 -0
  152. package/dist/project/reticle-dir.d.ts +2 -0
  153. package/dist/project/reticle-dir.js +1 -0
  154. package/dist/session/connection-memory.d.ts +59 -0
  155. package/dist/session/connection-memory.js +108 -0
  156. package/dist/session/dev-command.d.ts +26 -0
  157. package/dist/session/dev-command.js +89 -0
  158. package/dist/session/dev-server-probe.d.ts +68 -0
  159. package/dist/session/dev-server-probe.js +102 -7
  160. package/dist/session/last-act.d.ts +26 -0
  161. package/dist/session/last-act.js +35 -1
  162. package/dist/session/live-control-tools.js +42 -5
  163. package/dist/session/no-session-diagnosis.d.ts +55 -2
  164. package/dist/session/no-session-diagnosis.js +199 -22
  165. package/dist/session/no-session-next-action.d.ts +46 -0
  166. package/dist/session/no-session-next-action.js +85 -0
  167. package/dist/session/no-session-watch.d.ts +40 -1
  168. package/dist/session/no-session-watch.js +172 -11
  169. package/dist/session/pending-commands.d.ts +12 -0
  170. package/dist/session/pending-commands.js +13 -1
  171. package/dist/session/session-manager.d.ts +4 -0
  172. package/dist/session/session-manager.js +35 -5
  173. package/dist/session/session-readiness.js +1 -1
  174. package/dist/session/session.d.ts +10 -1
  175. package/dist/session/session.js +146 -5
  176. package/dist/telemetry/app-instrumented.d.ts +8 -0
  177. package/dist/telemetry/app-instrumented.js +10 -0
  178. package/dist/telemetry/bug-found.d.ts +18 -0
  179. package/dist/telemetry/bug-found.js +14 -0
  180. package/dist/telemetry/daemon-telemetry.js +29 -0
  181. package/dist/telemetry/install-source.d.ts +20 -0
  182. package/dist/telemetry/install-source.js +34 -0
  183. package/dist/telemetry/instrumentation-stall.d.ts +57 -0
  184. package/dist/telemetry/instrumentation-stall.js +103 -0
  185. package/dist/telemetry/license-activation.d.ts +48 -0
  186. package/dist/telemetry/license-activation.js +57 -0
  187. package/dist/telemetry/session-metrics.d.ts +8 -0
  188. package/dist/telemetry/session-metrics.js +10 -0
  189. package/dist/telemetry/telemetry.d.ts +3 -1
  190. package/dist/telemetry/telemetry.js +23 -3
  191. package/dist/tools/act-tools.js +166 -29
  192. package/dist/tools/assert-verdict.js +32 -7
  193. package/dist/tools/browser-tools.js +10 -0
  194. package/dist/tools/dynamic-tools.js +17 -8
  195. package/dist/tools/error-recovery.js +10 -6
  196. package/dist/tools/feedback-tools.js +31 -6
  197. package/dist/tools/invoke-tool.d.ts +1 -1
  198. package/dist/tools/invoke-tool.js +30 -8
  199. package/dist/tools/lease-hint.d.ts +30 -8
  200. package/dist/tools/lease-hint.js +65 -14
  201. package/dist/tools/lease-tools.d.ts +11 -0
  202. package/dist/tools/lease-tools.js +141 -96
  203. package/dist/tools/observe-tools.js +9 -3
  204. package/dist/tools/react-grace.d.ts +4 -0
  205. package/dist/tools/react-grace.js +6 -3
  206. package/dist/tools/read-tools.js +47 -1
  207. package/dist/tools/resolve-target.d.ts +33 -0
  208. package/dist/tools/resolve-target.js +53 -0
  209. package/dist/tools/settle-in-flight.d.ts +15 -0
  210. package/dist/tools/settle-in-flight.js +42 -2
  211. package/dist/tools/snapshot-delta.d.ts +3 -0
  212. package/dist/tools/snapshot-delta.js +67 -6
  213. package/dist/tools/tool-kit.d.ts +38 -3
  214. package/dist/tools/tool-names.d.ts +2 -0
  215. package/dist/tools/tool-names.js +2 -0
  216. package/dist/tools/tool-surface.d.ts +60 -0
  217. package/dist/tools/tool-surface.js +84 -19
  218. package/dist/tools/tools.js +61 -5
  219. package/dist/tools/unadvertised-help.js +9 -6
  220. package/docs/README.md +1 -2
  221. package/docs/actions.mdx +41 -8
  222. package/docs/agent-cheatsheet.md +6 -4
  223. package/docs/architecture.md +6 -0
  224. package/docs/benchmarks.md +60 -12
  225. package/docs/best-practices.mdx +11 -6
  226. package/docs/capabilities.mdx +204 -57
  227. package/docs/cli/affected.mdx +6 -4
  228. package/docs/cli/capsules.mdx +9 -8
  229. package/docs/cli/cloud.mdx +30 -4
  230. package/docs/cli/doctor.mdx +41 -8
  231. package/docs/cli/drive.mdx +34 -15
  232. package/docs/cli/gate.mdx +6 -6
  233. package/docs/cli/help.mdx +8 -6
  234. package/docs/cli/hunt.mdx +20 -4
  235. package/docs/cli/identify.mdx +16 -2
  236. package/docs/cli/init.mdx +35 -8
  237. package/docs/cli/kill.mdx +5 -5
  238. package/docs/cli/license.mdx +1 -1
  239. package/docs/cli/open.mdx +6 -0
  240. package/docs/cli/restart.mdx +6 -6
  241. package/docs/cli/serve.mdx +10 -3
  242. package/docs/cli/status.mdx +29 -5
  243. package/docs/cli/stop.mdx +8 -0
  244. package/docs/cli/verify.mdx +20 -1
  245. package/docs/cli/version.mdx +1 -1
  246. package/docs/cli/watch.mdx +9 -2
  247. package/docs/cli.mdx +44 -22
  248. package/docs/debugging.md +3 -1
  249. package/docs/deploy-checks.md +31 -2
  250. package/docs/desktop.mdx +276 -80
  251. package/docs/docs.json +13 -12
  252. package/docs/enterprise.md +9 -3
  253. package/docs/faq.mdx +49 -35
  254. package/docs/fixtures.md +2 -0
  255. package/docs/flows.md +7 -5
  256. package/docs/for-agents.md +3 -3
  257. package/docs/frameworks.mdx +46 -7
  258. package/docs/gate-plan.md +4 -2
  259. package/docs/gates.md +8 -6
  260. package/docs/getting-started.md +53 -12
  261. package/docs/human-control.md +2 -0
  262. package/docs/index.mdx +43 -1
  263. package/docs/install-agentic.mdx +13 -4
  264. package/docs/install-manual.mdx +6 -4
  265. package/docs/instrumentation.mdx +7 -1
  266. package/docs/integration-patterns.md +3 -1
  267. package/docs/local-registry.md +4 -2
  268. package/docs/multi-agent-testing.md +3 -1
  269. package/docs/packages/babel-plugin.mdx +15 -6
  270. package/docs/packages/browser.mdx +2 -2
  271. package/docs/packages/core.mdx +26 -16
  272. package/docs/packages/electron.mdx +5 -7
  273. package/docs/packages/eslint-plugin.mdx +5 -3
  274. package/docs/packages/next.mdx +3 -5
  275. package/docs/packages/react.mdx +3 -3
  276. package/docs/packages/server.mdx +2 -2
  277. package/docs/packages/tauri.mdx +6 -6
  278. package/docs/packages/test.mdx +18 -7
  279. package/docs/packages/vite-plugin.mdx +4 -6
  280. package/docs/packages.mdx +14 -13
  281. package/docs/platform-integration.md +2 -0
  282. package/docs/predicates.mdx +76 -7
  283. package/docs/quickstart.mdx +51 -5
  284. package/docs/recipes.mdx +63 -23
  285. package/docs/skill-file.mdx +3 -1
  286. package/docs/state-management.mdx +2 -0
  287. package/docs/system-map.md +3 -1
  288. package/docs/telemetry-contract.md +33 -5
  289. package/docs/telemetry-events.mdx +63 -18
  290. package/docs/telemetry.md +8 -5
  291. package/docs/testing.md +35 -1
  292. package/docs/token-efficiency.md +8 -2
  293. package/docs/tools-act-and-wait.mdx +64 -14
  294. package/docs/tools-act-sequence.mdx +34 -17
  295. package/docs/tools-act.mdx +24 -11
  296. package/docs/tools-assert.mdx +69 -10
  297. package/docs/tools-console.mdx +11 -7
  298. package/docs/tools-inspect.mdx +11 -8
  299. package/docs/tools-navigate.mdx +41 -5
  300. package/docs/tools-network.mdx +42 -9
  301. package/docs/tools-observe.mdx +66 -10
  302. package/docs/tools-overview.mdx +26 -23
  303. package/docs/tools-query.mdx +52 -8
  304. package/docs/tools-session-and-feedback.mdx +35 -9
  305. package/docs/tools-sessions.mdx +39 -10
  306. package/docs/tools-snapshot.mdx +57 -3
  307. package/docs/tools-state.mdx +24 -1
  308. package/docs/tools-tools-and-run.mdx +55 -24
  309. package/docs/tools-wait-for.mdx +34 -15
  310. package/docs/troubleshooting.mdx +80 -10
  311. package/docs/usage.md +46 -24
  312. package/docs/vs-chrome-devtools-mcp.mdx +41 -0
  313. package/docs/vs-playwright-mcp.mdx +42 -2
  314. package/docs/vs-screenshots.mdx +42 -1
  315. package/docs/what-is-reticle.mdx +1 -1
  316. package/docs/why-reticle.mdx +3 -1
  317. package/package.json +5 -5
  318. package/docs/desktop-apps.md +0 -265
@@ -1,33 +1,35 @@
1
1
  ---
2
- title: Tools overview: 18 up front, 30 on call
2
+ title: Reticle tools overview
3
3
  sidebarTitle: Tools overview
4
- description: The 18 tools your agent sees every turn, the 30 more it can reach on demand, and why the surface is deliberately small.
4
+ description: The tools your agent sees every turn, the many more it can reach on demand, and why the advertised surface is deliberately small.
5
5
  icon: wrench
6
6
  ---
7
7
 
8
- Reticle ships 48 tools. Your agent is shown **18** of them.
8
+ Reticle ships 46 tools plus two meta-tools. On the default profile your agent is shown **19** of them: 17 that do the work, plus `reticle_tools` and `reticle_run`, which reach the other 29 on demand. Only `reticle_act_and_wait` and `reticle_assert` produce a verdict.
9
9
 
10
10
  That is not a limitation, it's the design. MCP re-sends every advertised tool definition to the model on **every single turn**, so the tool list is not a menu you pay for once. It's rent.
11
11
 
12
- A wider surface costs tokens on every message. Less obviously, it makes the model wander: give it forty ways to look at a page and it will try several before doing anything useful.
12
+ A wider surface costs tokens on every message. Less obviously, it makes the model wander: give it fifty ways to look at a page and it will try several before doing anything useful.
13
13
 
14
- The other 30 tools are one call away, never unreachable. `reticle_tools` lists them and `reticle_run` invokes them.
14
+ The other 29 are one call away, never unreachable. `reticle_tools` lists them and `reticle_run` invokes them.
15
15
 
16
16
  <Note>
17
- Measured off the real wire on 2026-08-14, by reading `tools/list` from a fresh daemon: the default
18
- surface is **18 tools at 21,468 bytes**, against **48 tools at 134,368 bytes**. That is 6.3x more,
19
- charged on every message. In real tokenizer terms that is roughly **4,930** and **30,200** tokens
20
- per turn ([measured by `bench/harness/schema-tax.mjs`](/token-efficiency), which puts every server
21
- through one tokenizer in a single pass). Re-measure before quoting these; the surface grows.
17
+ Measured off the real wire on 2026-08-16, by reading `tools/list` from a fresh daemon: the default
18
+ surface is **19 tools at 22,023 bytes**, against **48 tools at 134,992 bytes** when
19
+ `RETICLE_ADVERTISE_ALL_TOOLS` is set. That is 6.1x more, charged on every message.
20
+ [`bench/harness/schema-tax.mjs`](/token-efficiency) converts those bytes to tokens by putting
21
+ every server through one tokenizer in a single pass. Re-measure before quoting any of it; the
22
+ surface grows.
22
23
  </Note>
23
24
 
24
- ## The default 18
25
+ ## The default 19
25
26
 
26
27
  Grouped by the job they do in the verify loop.
27
28
 
28
29
  <CardGroup cols={2}>
29
30
  <Card title="Look" icon="magnifying-glass">
30
- `reticle_snapshot` · `reticle_query` · `reticle_inspect` · `reticle_sessions`
31
+ `reticle_snapshot` · `reticle_query` · `reticle_inspect` · `reticle_sessions` ·
32
+ `reticle_capabilities`
31
33
  </Card>
32
34
  <Card title="Act" icon="hand-pointer">
33
35
  `reticle_act` · `reticle_act_and_wait` · `reticle_act_sequence` · `reticle_navigate`
@@ -49,7 +51,7 @@ Grouped by the job they do in the verify loop.
49
51
  however many tools it used and however confident the summary sounds.
50
52
  </Warning>
51
53
 
52
- ## Why these 18 and not others
54
+ ## Why these and not others
53
55
 
54
56
  Each one earned its slot, and a couple are there because of measured mistakes.
55
57
 
@@ -64,16 +66,16 @@ Those repeats were not retries. The calls succeeded and got repeated, because th
64
66
  Direct `reticle_network` and `reticle_console` stay advertised even though `reticle_observe` can filter for both, because two obvious tools beat one clever tool with a filter grammar.
65
67
 
66
68
  <Tip>
67
- Trimming further has a floor. An 8-tool cut measurably dropped real-agent accuracy, because the
68
- model loses scaffolding and wanders on harder flows. That reading is old enough to be dated
69
+ Trimming further has a floor. An eight-tool cut measurably dropped real-agent accuracy, because
70
+ the model loses scaffolding and wanders on harder flows. That reading is old enough to be dated
69
71
  evidence rather than proof, and a fresh A/B against a leaner surface is still unrun. Small is
70
72
  good; empty is not.
71
73
  </Tip>
72
74
 
73
- ## Reaching the other 30
75
+ ## Reaching the other 29
74
76
 
75
77
  ```json
76
- { "name": "reticle_flow_verify", "args": {} }
78
+ { "tool": "reticle_verify", "args": { "action": "flows" } }
77
79
  ```
78
80
 
79
81
  `reticle_run` takes a tool name and its arguments. `reticle_tools` lists what's available and returns the full argument grammar for any of them, so your agent can discover a tool mid-task without you having pre-loaded its schema.
@@ -85,10 +87,10 @@ Notable residents of the cold tail: flow recording and replay, visual diffing an
85
87
  Reticle tells you what each answer cost, because a verification tool that quietly eats your context window is not saving you anything:
86
88
 
87
89
  ```json
88
- "cost": { "bytes": 938, "tokens": 235 }
90
+ "cost": { "bytes": 944, "tokens": 236 }
89
91
  ```
90
92
 
91
- That is a real `reticle_query` response: seven buttons found, with source pointers, for 235 tokens.
93
+ That is a real `reticle_query` response: seven buttons found, with source pointers, for 236 tokens.
92
94
 
93
95
  ## Every response tells you when not to trust it
94
96
 
@@ -104,8 +106,8 @@ When the event buffer has evicted old events, a negative result might be a false
104
106
 
105
107
  ```json
106
108
  "buffer": {
107
- "held": 15,
108
- "dropped": 529,
109
+ "held": 535,
110
+ "dropped": 10,
109
111
  "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."
110
112
  }
111
113
  ```
@@ -122,6 +124,7 @@ A tool that says "no requests found" when it actually means "I lost the ones you
122
124
  | [`reticle_query`](/tools-query) | Where is the thing I mean? |
123
125
  | [`reticle_inspect`](/tools-inspect) | Everything about one element, down to source and design tokens |
124
126
  | [`reticle_sessions`](/tools-sessions) | Which tabs are connected, and can they actually be driven? |
127
+ | [`reticle_capabilities`](/tools-tools-and-run) | What does this app say is testable? Testids, signals, stores, flows |
125
128
 
126
129
  ### Act
127
130
 
@@ -148,10 +151,10 @@ A tool that says "no requests found" when it actually means "I lost the ones you
148
151
  | --- | --- |
149
152
  | [`reticle_assert`](/tools-assert) | Did the named consequence hold? **Produces a verdict** |
150
153
  | [`reticle_tools`](/tools-tools-and-run) | What else is available, and what are its arguments? |
151
- | [`reticle_run`](/tools-tools-and-run) | Invoke any of the other 30 |
154
+ | [`reticle_run`](/tools-tools-and-run) | Invoke any of the other 29 |
152
155
  | [`reticle_session`](/tools-session-and-feedback) | Hand control back to the human |
153
156
  | [`reticle_feedback`](/tools-session-and-feedback) | Tell the maintainers Reticle got something wrong |
154
157
 
155
158
  <Card title="The complete reference" icon="book" href="/usage">
156
- Every tool, every argument, including the 30 in the cold tail.
159
+ Every tool, every argument, including the 29 in the cold tail.
157
160
  </Card>
@@ -12,14 +12,14 @@ icon: magnifying-glass
12
12
  { "by": "role", "value": "button", "limit": 6 }
13
13
  ```
14
14
 
15
- Real response from a running app:
15
+ Real response from a running app, with four of the six elements trimmed out for length:
16
16
 
17
17
  ```json
18
18
  {
19
19
  "count": 7,
20
20
  "elements": [
21
21
  {
22
- "ref": "e18",
22
+ "ref": "e118",
23
23
  "role": "button",
24
24
  "name": "Overview",
25
25
  "visible": true,
@@ -27,7 +27,7 @@ Real response from a running app:
27
27
  "states": ["present", "visible", "enabled"]
28
28
  },
29
29
  {
30
- "ref": "e20",
30
+ "ref": "e120",
31
31
  "role": "button",
32
32
  "name": "Compose",
33
33
  "visible": true,
@@ -37,11 +37,11 @@ Real response from a running app:
37
37
  ],
38
38
  "total": 7,
39
39
  "truncated": true,
40
- "cost": { "bytes": 938, "tokens": 235 }
40
+ "cost": { "bytes": 944, "tokens": 236 }
41
41
  }
42
42
  ```
43
43
 
44
- Seven buttons, each with a `ref` to act on and a source file to open, for 235 tokens.
44
+ Seven buttons, each with a `ref` to act on and a source file to open, for 236 tokens.
45
45
 
46
46
  ## Arguments
47
47
 
@@ -63,16 +63,60 @@ Every argument also has a predicate spelling, so `{ "role": "button" }` works as
63
63
  "Are there still three rows?" does not require three row descriptors:
64
64
 
65
65
  ```json
66
- { "by": "testid", "value": "todo-row", "count_only": true }
66
+ { "by": "testid", "value": "login-submit", "count_only": true }
67
67
  ```
68
68
 
69
+ ```json
70
+ { "count": 1, "cost": { "bytes": 11, "tokens": 3 } }
71
+ ```
72
+
73
+ Three tokens. Note that `total` is not emitted on this path, because `count` already is the total.
74
+
75
+ ## A zero-match result tells you what _is_ there
76
+
77
+ ```json
78
+ { "by": "testid", "value": "compose-prompt" }
79
+ ```
80
+
81
+ ```json
82
+ {
83
+ "count": 0,
84
+ "elements": [],
85
+ "hint": {
86
+ "route": "/hostile",
87
+ "knownEmptyState": true,
88
+ "presentTestids": [
89
+ "brand",
90
+ "nav-overview",
91
+ "nav-deployments",
92
+ "nav-compose",
93
+ "nav-diagnostics",
94
+ "nav-hostile",
95
+ "session-pill",
96
+ "cmdk-open",
97
+ "sign-out",
98
+ "hostile-view",
99
+ "hostile-ticker",
100
+ "hostile-feed-count"
101
+ ],
102
+ "presentRegions": [
103
+ { "role": "list", "childCount": 0, "name": "hostile-feed", "sample": [] },
104
+ { "role": "banner", "childCount": 0, "sample": [] }
105
+ ]
106
+ },
107
+ "cost": { "bytes": 402, "tokens": 101 }
108
+ }
109
+ ```
110
+
111
+ The testid existed, on another route. `hint.route` says where you actually are, `presentTestids` says what is on this page instead, and `presentRegions` distinguishes an empty list from a missing one. All of it without paying for a snapshot.
112
+
69
113
  ## Reading the response
70
114
 
71
115
  `ref` is the handle for every other tool: `act`, `inspect`, `state`. It stays valid until the element leaves the DOM, so you do not need to re-snapshot between actions on the same element.
72
116
 
73
- `source` appears when `@reticlehq/react` is installed. Note that all five sidebar buttons above report `Sidebar.tsx:41`. That is the line where the component renders them in a loop, which is exactly the line you want to edit.
117
+ `source` appears when `@reticlehq/react` is installed. Note that both sidebar buttons above report `Sidebar.tsx:41`, and so do the three trimmed out of the example. That is the line where the component renders all five in a loop, which is exactly the line you want to edit.
74
118
 
75
- `truncated: true` with `total: 7` means `limit` cut the list, not that Reticle ran out of room.
119
+ `truncated: true` with `total: 7` means `limit` cut the list, not that Reticle ran out of room. Neither field is emitted when nothing was cut, so their absence is itself the signal that you are looking at every match.
76
120
 
77
121
  `states` distinguishes `present` from `visible` from `enabled`. An element can be all three and still be covered by a modal. [`reticle_inspect`](/tools-inspect) reports `occluded` for that.
78
122
 
@@ -4,26 +4,36 @@ description: Hand the session back to the human, end it cleanly, and tell the ma
4
4
  icon: comments
5
5
  ---
6
6
 
7
- Two tools that are not about your app at all. One manages the boundary between agent and human; the other is how Reticle finds out it is broken.
7
+ `reticle_session` manages the boundary between the agent and the human watching: hand control back, end the session, narrate what you are doing, and drain the bugs they pinned on elements. `reticle_feedback` is how you tell the Reticle maintainers that Reticle itself got something wrong. Neither tool touches your app, and neither produces a verdict.
8
8
 
9
9
  ## reticle_session
10
10
 
11
11
  The presenter panel in your app shows a live transcript of what the agent is doing. It reads "live" until the agent says otherwise. So an agent that wanders off without a word leaves a panel claiming work is in progress forever.
12
12
 
13
- | Action | What it does |
14
- | ------- | ------------------------------------------------------------------------ |
15
- | `yield` | Hand control back between turns. `mode: "waiting"` or `"ask"`. Revivable |
16
- | `end` | The task is done. Frees the session; revives on the next action |
17
- | `tune` | Adjust session behaviour, such as the idle-end window |
13
+ | Action | What it does |
14
+ | ---------- | ------------------------------------------------------------------------ |
15
+ | `yield` | Hand control back between turns. `mode: "waiting"` or `"ask"`. Revivable |
16
+ | `end` | The task is done. Frees the session; revives on the next action |
17
+ | `tune` | Adjust session behaviour, such as `idleEndMs`, the idle-end window |
18
+ | `resume` | Clear a pause the human applied |
19
+ | `messages` | Drain the human-to-agent inbox |
20
+ | `review` | List, and with `resolve`, retire the mistakes a human pinned to elements |
21
+ | `narrate` | State your intent on the presenter panel, with an optional `level` |
18
22
 
19
23
  ```json
20
24
  { "action": "yield", "mode": "waiting" }
21
25
  ```
22
26
 
23
- Reticle nudges you about this. Every response on a long-running session carries a reminder:
27
+ `review` returns a real reading rather than a silent empty:
24
28
 
25
29
  ```json
26
- "session_age_warning": "Session s7fe3a790… has been open for 15 minutes. If your task is complete, call reticle_session{action:\"end\"} now."
30
+ { "marks": [], "pendingCount": 0 }
31
+ ```
32
+
33
+ Reticle nudges you about all of this. Every response on a long-running session carries a reminder:
34
+
35
+ ```json
36
+ "session_age_warning": "Session s223e0fad-e012-43f9-a23d-6d585470c90d has been open for 21 minutes. If your task is complete, call reticle_session{action:\"end\"} now."
27
37
  ```
28
38
 
29
39
  And each lease carries the rule in the payload itself:
@@ -60,6 +70,11 @@ Reticle is built for agents, which creates an unusual problem: the primary user'
60
70
  | `ambiguity` | The check ran but you could not tell what the answer meant |
61
71
  | `feature_request` | You wished a capability existed |
62
72
  | `improvement` | It works, but costs too many calls |
73
+ | `experience` | Something worked notably well (pair it with `rating`, 1-5) |
74
+
75
+ `experience` is the only kind here that is not a complaint, and that is why it exists. Every other row grows the corpus into a defect list, which says nothing about which parts are worth protecting when we change them. File it unprompted, when you actually notice it, and name the concrete moment: which call, what it saved you, what you would have done instead.
76
+
77
+ The `rating` is secondary to that text on purpose. A score produced because something asked for one is indistinguishable from a score that was earned, and once both sit in the same column neither means anything. The text is the part that can be acted on or quoted.
63
78
 
64
79
  ### It will tell you when it cannot send
65
80
 
@@ -69,11 +84,22 @@ Feedback is not fire-and-forget, and it does not pretend to succeed:
69
84
  {
70
85
  "sent": false,
71
86
  "accepted": false,
72
- "reason": "this is a Reticle source checkout, where telemetry is disabled by design, so feedback has nowhere to go. Open an issue at https://github.com/reticlehq/reticle/issues instead.",
87
+ "reason": "this is a Reticle source checkout, where telemetry is disabled by design, so feedback has nowhere to go. Open an issue at https://github.com/reticlehq/reticle/issues instead, or run from the app you are verifying.",
88
+ "redacted": [],
89
+ "context": {
90
+ "stack": "react",
91
+ "client": "claude-code",
92
+ "runtime": "web",
93
+ "engine": "blink",
94
+ "driver": "cdp",
95
+ "mcpScope": "user"
96
+ },
73
97
  "note": "NOT accepted (see reason). Tell the human what you found so it is not lost."
74
98
  }
75
99
  ```
76
100
 
101
+ `redacted` names anything stripped from your report before it left the machine, so you can see what was and was not sent. `context` is the environment attached automatically, which is why a useful report costs one call and no boilerplate.
102
+
77
103
  That is a real response, captured while writing these docs. The instruction in `note` is the important part: when the report cannot be delivered, say so in your answer to the human rather than letting the finding evaporate.
78
104
 
79
105
  ### From the shell, when the tools are unreachable
@@ -4,34 +4,63 @@ description: List every connected browser tab, with the health fields that tell
4
4
  icon: list-check
5
5
  ---
6
6
 
7
+ `reticle_sessions` lists every browser tab currently connected to the Reticle daemon, with the health fields that decide whether it can actually be driven. Reach for it first when a tool says no session is connected, and after every [`reticle_navigate`](/tools-navigate) that came back `confirmed: false`.
8
+
7
9
  ```json
8
10
  {}
9
11
  ```
10
12
 
11
- Real response, one session shown:
13
+ Real response from a healthy session:
12
14
 
13
15
  ```json
14
16
  {
15
17
  "sessions": [
16
18
  {
17
- "sessionId": "s7fe3a790-ab02-4ebb-82b2-24d08a76fd59",
18
- "url": "http://localhost:4312/",
19
+ "sessionId": "sba6117a6-24ec-494d-8c2c-e2958cff2e7f",
20
+ "url": "http://localhost:4310/",
19
21
  "title": "Reticle · Mission Control",
20
22
  "adapters": ["react"],
21
23
  "hasCapabilities": true,
22
- "hidden": true,
23
- "throttled": true,
24
- "focused": false,
25
- "lastSeenMs": 21944,
24
+ "hidden": false,
25
+ "lastSeenMs": 155,
26
+ "throttled": false,
27
+ "focused": true,
28
+ "attachment": { "connectedSinceMs": 18654, "outages": 0 },
26
29
  "realInputAvailable": false,
27
- "leased": false,
28
- "attachment": { "connectedSinceMs": 827874, "outages": 0 },
29
- "recommendation": "tab hidden/throttled and may be un-focusable from here; refocus it, or run `reticle drive <url>` for a guaranteed scriptable context"
30
+ "leased": false
30
31
  }
31
32
  ]
32
33
  }
33
34
  ```
34
35
 
36
+ A backgrounded tab adds a `recommendation` telling you what to do about it, and `attachment` grows a `lastOutage` once the connection has dropped at least once:
37
+
38
+ ```json
39
+ {
40
+ "hidden": false,
41
+ "throttled": true,
42
+ "attachment": {
43
+ "connectedSinceMs": 1217047,
44
+ "outages": 3,
45
+ "lastOutage": { "startedMs": 1786818483776, "durationMs": 967 }
46
+ },
47
+ "recommendation": "tab hidden/throttled and may be un-focusable from here; refocus it, or run `reticle drive <url>` for a guaranteed scriptable context"
48
+ }
49
+ ```
50
+
51
+ ## When nothing is connected
52
+
53
+ An empty list is not silent. It comes back with a `why` that separates the two causes, and refuses to guess between them:
54
+
55
+ ```json
56
+ {
57
+ "sessions": [],
58
+ "why": "no browser session connected. Two things to weigh, and neither of them is proof. (1) Nothing is listening on the ports Reticle scans, so the dev server may not be running. That scan is narrow though: a server on any other port is invisible to it, so if the app IS running, ask for its URL rather than assuming it is down, and open it with `reticle open <url>`. (2) There is no `.reticle.json` in the directory this daemon is running in. That is the file `reticle init` writes, so the app may carry no Reticle SDK."
59
+ }
60
+ ```
61
+
62
+ That string is trimmed. The full text also lists the exact ports it scanned and warns that in a monorepo the daemon often runs at the root while the app lives in a subdirectory, so you should check the app's own directory before re-running `init`.
63
+
35
64
  ## The fields that decide whether driving will work
36
65
 
37
66
  | Field | Why it matters |
@@ -24,6 +24,7 @@ icon: camera
24
24
  {
25
25
  "tree": "",
26
26
  "nodes": 0,
27
+ "truncated": false,
27
28
  "status": { "route": "/", "title": "Reticle · Mission Control" },
28
29
  "cost": { "bytes": 98, "tokens": 25 }
29
30
  }
@@ -39,7 +40,7 @@ Ninety-eight bytes to answer "where am I?". Use it after a navigation instead of
39
40
 
40
41
  ```json
41
42
  {
42
- "tree": "- textbox \"Email\" (ref=e101) [value=\"admin@reticle.dev\"]\n- textbox \"Password\" (ref=e102) [value=\"[REDACTED]\"]\n- button \"Sign in\" (ref=e103)",
43
+ "tree": "- textbox \"Email\" (ref=e303) [value=\"admin@reticle.dev\"]\n- textbox \"Password\" (ref=e304) [value=\"[REDACTED]\"]\n- button \"Sign in\" (ref=e305)",
43
44
  "nodes": 3,
44
45
  "truncated": false,
45
46
  "status": { "route": "/deployments", "title": "Reticle · Mission Control" },
@@ -63,7 +64,45 @@ Everything you can act on, with a `ref` for each, for 65 tokens. Note the passwo
63
64
  { "mode": "interactive", "diff": true }
64
65
  ```
65
66
 
66
- After the first snapshot, ask only for the delta. On a page where one row appeared, you get one row rather than the whole list again.
67
+ When nothing moved since your last look of the same scope and mode, that costs 20 tokens and says so:
68
+
69
+ ```json
70
+ {
71
+ "mode": "unchanged",
72
+ "status": { "route": "/", "title": "Reticle · Mission Control" },
73
+ "cost": { "bytes": 79, "tokens": 20 }
74
+ }
75
+ ```
76
+
77
+ When something did move, you get only what changed. This is the same call after a login replaced the form with the app shell:
78
+
79
+ ```json
80
+ {
81
+ "mode": "delta",
82
+ "delta": {
83
+ "added": [
84
+ "- button \"Overview\" (ref=e17)",
85
+ "- button \"Deployments40\" (ref=e18)",
86
+ "- button \"Compose\" (ref=e19)",
87
+ "- button \"Diagnostics\" (ref=e20)",
88
+ "- button \"Hostile\" (ref=e21)",
89
+ "- button \"Search or jump to…⌘K\" (ref=e22)",
90
+ "- button \"Sign out\" (ref=e23)"
91
+ ],
92
+ "removed": [
93
+ "- textbox \"Email\" (ref=e4) [value=\"admin@reticle.dev\"]",
94
+ "- textbox \"Password\" (ref=e5) [value=\"[REDACTED]\"]",
95
+ "- button \"Sign in\" (ref=e3)"
96
+ ],
97
+ "addedCount": 7,
98
+ "removedCount": 3
99
+ },
100
+ "status": { "route": "/", "title": "Reticle · Mission Control" },
101
+ "cost": { "bytes": 545, "tokens": 137 }
102
+ }
103
+ ```
104
+
105
+ A route change resets it: the next call after one returns a full snapshot rather than a delta against a page that no longer exists.
67
106
 
68
107
  <Tip>
69
108
  Reach for [`reticle_query`](/tools-query) instead when you already know what you're looking for.
@@ -72,4 +111,19 @@ After the first snapshot, ask only for the delta. On a page where one row appear
72
111
 
73
112
  ## Refs change across documents
74
113
 
75
- Refs are stable while the element is in the DOM. A full navigation builds a new document, so refs are re-issued. The same "Sign in" button was `e5` before a navigation and `e103` after. Snapshot after navigating; don't reuse refs across one.
114
+ Refs are stable while the element is in the DOM. A full navigation builds a new document, so refs are re-issued. Across the captures on this page the same "Sign in" button was `e105`, then `e305`, then `e3`, because each reload built a new document. Snapshot after navigating; don't reuse refs across one.
115
+
116
+ Reticle refuses a stale ref rather than clicking whatever now occupies that slot:
117
+
118
+ ```json
119
+ {
120
+ "error": "ref 'e303' no longer resolves to an element",
121
+ "recovery": "That ref is stale: refs are invalidated whenever the DOM re-renders, so any action that navigated, opened a modal, re-sorted a list or changed the page invalidates every ref taken before it. Call reticle_query again for a fresh ref and retry the action."
122
+ }
123
+ ```
124
+
125
+ <Note>
126
+ That `recovery` string is trimmed. The full text also recommends
127
+ [`reticle_act_and_wait`](/tools-act-and-wait) with `until`, so the next ref is taken after the
128
+ page settles.
129
+ </Note>
@@ -4,6 +4,8 @@ description: Read live framework state directly from the running app. What it be
4
4
  icon: database
5
5
  ---
6
6
 
7
+ `reticle_state` reads live framework state straight out of the running app, without the app broadcasting anything. Reach for it when the DOM looks right and you want to know whether the application actually accepted the change, which is where false greens live.
8
+
7
9
  The DOM tells you what the app _drew_. `reticle_state` tells you what it _believes_. The gap between those two is where false greens live: a row appears in the table, the store never changed, and a reload makes the row vanish.
8
10
 
9
11
  ## Example
@@ -46,6 +48,25 @@ Drill in once you know what you want:
46
48
  { "store": "app", "path": "auth" }
47
49
  ```
48
50
 
51
+ ```json
52
+ {
53
+ "store": "app",
54
+ "path": "auth",
55
+ "found": true,
56
+ "value": { "email": "admin@reticle.dev" },
57
+ "storeNames": ["__reticle_renders", "app", "queries"]
58
+ }
59
+ ```
60
+
61
+ A wrong `path` comes back `{ "found": false, "availableKeys": [...] }` rather than an empty value, so a typo is diagnosable instead of looking like an empty store.
62
+
63
+ <Warning>
64
+ `reticle_state` asks the page and waits. On a backgrounded tab the page may never answer, and you
65
+ get `"command 'state_read' timed out after 8000ms"` with a recovery note pointing at
66
+ [`reticle_sessions`](/tools-sessions). That is a fact about the tab, not a Reticle failure. Bring
67
+ it to the front, or drive your own browser.
68
+ </Warning>
69
+
49
70
  ## You have to register stores first
50
71
 
51
72
  `reticle_state` reads what your app registered in `src/reticle-dev.ts`. With nothing registered, `storeNames` comes back empty and this tool has nothing to say.
@@ -71,7 +92,9 @@ A `POST` returning `200` proves the server was reachable. A row in the DOM prove
71
92
  State does. When [`reticle_act_and_wait`](/quickstart) reports
72
93
 
73
94
  ```json
74
- "stateDiffs": [{ "path": "auth", "from": null, "to": "{\"email\":\"admin@reticle.dev\"}" }]
95
+ "stateDiffs": [
96
+ { "path": "auth", "from": null, "to": "{\"email\":\"admin@reticle.dev\"}", "atMs": 44403 }
97
+ ]
75
98
  ```
76
99
 
77
100
  that is the app itself saying the login took. A mock that returns `200` without touching state gets caught right there, and nowhere else.
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  title: reticle_tools and reticle_run
3
- description: Discover the 30 tools that are not advertised, load their argument grammar on demand, and invoke any of them by name.
3
+ description: Discover the tools that are not advertised, load their argument grammar on demand, and invoke any of them by name.
4
4
  icon: boxes-stacked
5
5
  ---
6
6
 
7
- Reticle advertises 18 tools and ships 48. These two meta-tools are how your agent reaches the other 30 without paying for their schemas on every turn.
7
+ `reticle_tools` lists every Reticle tool and, on request, returns the full argument grammar for the ones you name. `reticle_run` then invokes any of them. Reach for the pair whenever you need a capability that is not in the default advertised surface, which is most of what Reticle can do.
8
8
 
9
- `reticle_tools` discovers. `reticle_run` invokes. Together they cost two tool definitions instead of thirty.
9
+ Reticle ships 46 tools plus these two meta-tools. On the default profile your agent is shown 17 of them plus the meta pair, so 29 sit in the cold tail. These two are how it reaches those 29 without paying for their schemas on every turn.
10
+
11
+ `reticle_tools` discovers. `reticle_run` invokes. Together they cost two tool definitions instead of twenty-nine.
10
12
 
11
13
  ## Discovering what exists
12
14
 
@@ -16,35 +18,37 @@ Reticle advertises 18 tools and ships 48. These two meta-tools are how your agen
16
18
 
17
19
  Returns every tool with a one-line summary. A sample of what lives in the cold tail:
18
20
 
19
- | Tool | What it does |
20
- | ----------------------- | ---------------------------------------------------------------------- |
21
- | `reticle_capabilities` | The app's advertised testable surface, testids, signals, stores, flows |
22
- | `reticle_flow_verify` | Replay every saved flow, return one consolidated suite verdict |
23
- | `reticle_screenshot` | Pixel screenshot of the driven page, saved as a visual baseline |
24
- | `reticle_visual_diff` | Perceptually diff the live page against that baseline |
25
- | `reticle_network_mock` | Force a 500, go offline, or delay a response |
26
- | `reticle_viewport` | Pin the viewport so screenshots are reproducible across machines |
27
- | `reticle_crawl` | Click every reachable control and report anomalies, with no script |
28
- | `reticle_clock` | Freeze time or fast-forward timers, toasts, debounces, auto-dismiss |
29
- | `reticle_storage` | localStorage, sessionStorage and readable cookies |
30
- | `reticle_coverage` | Which controls you have driven this session, and which you have not |
31
- | `reticle_verify_change` | Give it the files you edited; it replays the flows that cover them |
32
- | `reticle_reconcile` | Compare what the API returned against what the page actually renders |
33
- | `reticle_scroll_to` | Find a row in a virtualised list that has not rendered yet |
21
+ | Tool | What it does |
22
+ | --- | --- |
23
+ | `reticle_capabilities` | The app's advertised testable surface, testids, signals, stores, flows |
24
+ | `reticle_verify` (`flows`) | Replay every saved flow, return one consolidated suite verdict |
25
+ | `reticle_screenshot` | Pixel screenshot of the driven page, saved as a visual baseline |
26
+ | `reticle_visual_diff` | Perceptually diff the live page against that baseline |
27
+ | `reticle_network_mock` | Force a 500, go offline, or delay a response |
28
+ | `reticle_viewport` | Pin the viewport so screenshots are reproducible across machines |
29
+ | `reticle_verify` (`crawl`) | Click every reachable control and report anomalies, with no script |
30
+ | `reticle_clock` | Freeze time or fast-forward timers, toasts, debounces, auto-dismiss |
31
+ | `reticle_storage` | localStorage, sessionStorage and readable cookies |
32
+ | `reticle_verify` (`coverage`) | Which controls you have driven this session, and which you have not |
33
+ | `reticle_verify` (`change`) | Give it the files you edited; it replays the flows that cover them |
34
+ | `reticle_reconcile` | Compare what the API returned against what the page actually renders |
35
+ | `reticle_scroll_to` | Find a row in a virtualised list that has not rendered yet |
34
36
 
35
37
  The response also tells you which surface is active:
36
38
 
37
39
  ```json
38
40
  {
39
41
  "profile": {
40
- "active": "default",
41
- "source": "the one tool surface (RETICLE_ADVERTISE_ALL_TOOLS unset when the daemon started)",
42
- "note": "The profile is read once at daemon startup: change it and restart the daemon, or it has no effect."
42
+ "active": "all",
43
+ "source": "RETICLE_ADVERTISE_ALL_TOOLS set in the DAEMON's environment at startup",
44
+ "note": "The profile is read once at daemon startup: change RETICLE_TOOL_PROFILE and restart the daemon, or it has no effect. Under this profile every unadvertised tool is reachable through reticle_run; under `full` there are no meta-tools because every tool is advertised directly."
43
45
  },
44
46
  "next": "Load params with reticle_tools { names:[…] }, then call reticle_run { tool, args }."
45
47
  }
46
48
  ```
47
49
 
50
+ That capture is from a daemon started with `RETICLE_ADVERTISE_ALL_TOOLS=1`. On a default daemon, `active` reads `default` and names the environment variable as unset.
51
+
48
52
  <Warning>
49
53
  "Read once at daemon startup" is doing real work in that sentence. Setting the environment
50
54
  variable in a shell where a daemon is already running changes nothing, and the resulting "I set it
@@ -59,7 +63,27 @@ Summaries are enough to choose a tool, not to call one. Load the full parameters
59
63
  { "names": ["reticle_network_mock", "reticle_clock"] }
60
64
  ```
61
65
 
62
- This is the point of the design. Schemas arrive when they are needed, rather than on every turn forever.
66
+ Each named tool comes back with its full description and a `params` array of `{ name, required, description }`. This is the point of the design. Schemas arrive when they are needed, rather than on every turn forever.
67
+
68
+ <Warning>
69
+ Do this rather than guessing. `reticle_run` refuses an unknown parameter instead of running the
70
+ call, and hands you the real parameter list so the retry is one turn rather than three:
71
+
72
+ ```json
73
+ {
74
+ "error": "unknown parameter for reticle_flow_save: name",
75
+ "tool": "reticle_flow_save",
76
+ "params": [
77
+ { "name": "flow", "required": false, "description": "Alias for `flowName`." },
78
+ { "name": "flowName", "required": true, "description": "Name for the flow file." }
79
+ ],
80
+ "hint": "fix the arguments and call reticle_run again"
81
+ }
82
+ ```
83
+
84
+ The full `error` string continues: _"NOT applied, so any result would be an answer to a different question."_
85
+
86
+ </Warning>
63
87
 
64
88
  ## Invoking
65
89
 
@@ -98,12 +122,15 @@ Real response from an instrumented app, trimmed:
98
122
  "name": "ship-a-deploy",
99
123
  "steps": ["nav-deployments", "new-deploy", "deploy-name", "deploy-submit"]
100
124
  },
101
- { "name": "generate-a-script", "steps": ["nav-compose", "compose-prompt", "compose-generate"] }
125
+ { "name": "generate-a-script", "steps": ["nav-compose", "compose-prompt", "compose-generate"] },
126
+ { "name": "find-old-deploy", "steps": ["nav-deployments", "scroll-to row-3600"] }
102
127
  ],
103
128
  "source": "live"
104
129
  }
105
130
  ```
106
131
 
132
+ The full response on this fixture carries 49 testids and 16 signals. `source: "live"` means it was read from the running app; pass `{ "fromDisk": true }` to read the git-checked `.reticle/contract.json` instead, which works with no browser attached at all.
133
+
107
134
  ## Start here, not with a snapshot
108
135
 
109
136
  That `reticle_capabilities` output is the single best first call on an unfamiliar app. It is the app telling you what it considers testable: the elements worth driving, the signals that mean success, and the flows somebody already thought were important.
@@ -117,7 +144,11 @@ Compared with snapshotting the page and guessing from element names, it is both
117
144
  }
118
145
  ```
119
146
 
120
- Then drive the flow and see whether your error state actually works. Most do not, which is the point.
147
+ ```json
148
+ { "applied": true, "count": 1 }
149
+ ```
150
+
151
+ Then drive the flow and see whether your error state actually works. Most do not, which is the point. `{ "clear": true }` turns it off and answers `{ "applied": true, "count": 0 }`.
121
152
 
122
153
  <Note>
123
154
  `reticle_run` returns whatever the invoked tool returns, unchanged. It is a transport, not a