@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.
- package/README.md +14 -5
- package/SKILL.md +130 -778
- package/dist/bridge/bridge.d.ts +23 -0
- package/dist/bridge/bridge.js +80 -2
- package/dist/bridge/bridge.test-harness.d.ts +5 -0
- package/dist/bridge/bridge.test-harness.js +6 -4
- package/dist/capsule/causal-summary.d.ts +36 -1
- package/dist/capsule/causal-summary.js +33 -7
- package/dist/capsule/divergence.js +7 -1
- package/dist/cli/chromium-hint.d.ts +33 -5
- package/dist/cli/chromium-hint.js +82 -12
- package/dist/cli/cli-doctor.js +65 -34
- package/dist/cli/cli-flow-commands.js +8 -8
- package/dist/cli/cli-kill.d.ts +58 -0
- package/dist/cli/cli-kill.js +162 -0
- package/dist/cli/cli-parse.d.ts +16 -1
- package/dist/cli/cli-parse.js +32 -9
- package/dist/cli/cli-port.d.ts +32 -0
- package/dist/cli/cli-port.js +82 -35
- package/dist/cli/cli-verify.d.ts +21 -0
- package/dist/cli/cli-verify.js +47 -3
- package/dist/cli/config-discovery.d.ts +35 -0
- package/dist/cli/config-discovery.js +163 -0
- package/dist/cli/doctor-daemon-line.js +4 -1
- package/dist/cli/doctor-project-line.d.ts +37 -0
- package/dist/cli/doctor-project-line.js +35 -0
- package/dist/cli/doctor-rows.d.ts +51 -0
- package/dist/cli/doctor-rows.js +54 -0
- package/dist/cli/doctor-sessions-line.d.ts +12 -0
- package/dist/cli/doctor-sessions-line.js +69 -0
- package/dist/cli/drive-attach.d.ts +99 -0
- package/dist/cli/drive-attach.js +203 -0
- package/dist/cli/drive-command.d.ts +13 -0
- package/dist/cli/drive-command.js +103 -0
- package/dist/cli/open-note.d.ts +20 -0
- package/dist/cli/open-note.js +37 -0
- package/dist/cli/port-holder.d.ts +10 -0
- package/dist/cli/port-holder.js +26 -2
- package/dist/cli/status-next-action.d.ts +37 -0
- package/dist/cli/status-next-action.js +61 -0
- package/dist/cli.js +119 -39
- package/dist/crawl/crawl-tools.js +12 -2
- package/dist/crawl/crawl.d.ts +13 -0
- package/dist/crawl/crawl.js +50 -2
- package/dist/events/contradictions.d.ts +46 -0
- package/dist/events/contradictions.js +35 -22
- package/dist/events/declared.d.ts +45 -0
- package/dist/events/declared.js +73 -0
- package/dist/events/echo-mismatch.d.ts +8 -2
- package/dist/events/echo-mismatch.js +33 -5
- package/dist/events/event-filters.d.ts +1 -1
- package/dist/events/event-filters.js +7 -4
- package/dist/events/predicate-eval.d.ts +17 -72
- package/dist/events/predicate-eval.js +117 -236
- package/dist/events/predicate-parse.js +31 -3
- package/dist/events/predicate-route.d.ts +32 -0
- package/dist/events/predicate-route.js +102 -0
- package/dist/events/predicate-schema.d.ts +99 -0
- package/dist/events/predicate-schema.js +309 -0
- package/dist/events/predicate.d.ts +8 -0
- package/dist/events/predicate.js +296 -22
- package/dist/flows/annotate-tools.js +3 -0
- package/dist/flows/annotate.js +18 -4
- package/dist/flows/coverage.d.ts +38 -5
- package/dist/flows/coverage.js +30 -4
- package/dist/flows/decision.d.ts +15 -0
- package/dist/flows/decision.js +1 -1
- package/dist/flows/flow-classify.js +1 -1
- package/dist/flows/flow-replay-run.js +8 -1
- package/dist/flows/flow-tools.js +21 -5
- package/dist/flows/heal-run.js +1 -1
- package/dist/flows/replay.js +3 -0
- package/dist/honesty/accepted-write.d.ts +3 -0
- package/dist/honesty/accepted-write.js +8 -3
- package/dist/honesty/already-true.js +15 -0
- package/dist/honesty/blind-spots.js +10 -2
- package/dist/honesty/honesty.d.ts +11 -0
- package/dist/honesty/honesty.js +1 -0
- package/dist/honesty/uncaptured-bodies.d.ts +4 -2
- package/dist/honesty/uncaptured-bodies.js +9 -2
- package/dist/honesty/unread-outcome.d.ts +8 -0
- package/dist/honesty/unread-outcome.js +36 -9
- package/dist/honesty/unsettled.d.ts +49 -0
- package/dist/honesty/unsettled.js +82 -0
- package/dist/honesty/verified.d.ts +36 -3
- package/dist/honesty/verified.js +54 -11
- package/dist/http-server.d.ts +19 -0
- package/dist/http-server.js +202 -4
- package/dist/impact/impact-recorder.d.ts +23 -0
- package/dist/impact/impact-recorder.js +76 -0
- package/dist/impact/impact-store.d.ts +47 -0
- package/dist/impact/impact-store.js +171 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +47 -10
- package/dist/init/agent-rules.d.ts +36 -0
- package/dist/init/agent-rules.js +132 -22
- package/dist/init/astro-patch.d.ts +2 -1
- package/dist/init/astro-patch.js +38 -6
- package/dist/init/capabilities.d.ts +22 -0
- package/dist/init/capabilities.js +76 -0
- package/dist/init/confirm.d.ts +114 -0
- package/dist/init/confirm.js +165 -0
- package/dist/init/connect-steps.d.ts +2 -0
- package/dist/init/connect-steps.js +50 -0
- package/dist/init/cra.js +3 -2
- package/dist/init/csp-check.d.ts +38 -0
- package/dist/init/csp-check.js +92 -0
- package/dist/init/csp-doctor.d.ts +25 -0
- package/dist/init/csp-doctor.js +49 -0
- package/dist/init/cursor.js +6 -9
- package/dist/init/detect.d.ts +8 -0
- package/dist/init/detect.js +33 -3
- package/dist/init/mcp-clients.d.ts +1 -0
- package/dist/init/mcp-clients.js +51 -7
- package/dist/init/mcp.d.ts +15 -0
- package/dist/init/mcp.js +19 -0
- package/dist/init/non-js-project.js +29 -5
- package/dist/init/plan-framework.d.ts +10 -0
- package/dist/init/plan-framework.js +78 -16
- package/dist/init/plan.d.ts +47 -6
- package/dist/init/plan.js +228 -69
- package/dist/init/run.d.ts +24 -2
- package/dist/init/run.js +157 -45
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/slash-command.js +54 -6
- package/dist/init/snippets.d.ts +45 -5
- package/dist/init/snippets.js +194 -42
- package/dist/init/vite-config.js +53 -5
- package/dist/input/network-mock-tools.d.ts +19 -0
- package/dist/input/network-mock-tools.js +37 -5
- package/dist/input/scroll-find.d.ts +6 -0
- package/dist/input/scroll-find.js +17 -2
- package/dist/input/scroll-tools.js +4 -0
- package/dist/journal/attach-journal.d.ts +9 -1
- package/dist/journal/attach-journal.js +13 -2
- package/dist/journal/journal-query.d.ts +13 -0
- package/dist/journal/journal-query.js +28 -3
- package/dist/journal/workspace-gitignore.d.ts +10 -0
- package/dist/journal/workspace-gitignore.js +59 -0
- package/dist/license/license.js +1 -1
- package/dist/mcp/mcp-proxy.d.ts +35 -30
- package/dist/mcp/mcp-proxy.js +306 -104
- package/dist/mcp/mcp.d.ts +10 -1
- package/dist/mcp/mcp.js +70 -34
- package/dist/mcp/proxy-handshake.d.ts +82 -1
- package/dist/mcp/proxy-handshake.js +109 -2
- package/dist/mcp/proxy-lifecycle.d.ts +11 -2
- package/dist/mcp/proxy-lifecycle.js +12 -3
- package/dist/mcp/proxy-log.d.ts +63 -0
- package/dist/mcp/proxy-log.js +132 -0
- package/dist/mcp/server-instructions.d.ts +17 -0
- package/dist/mcp/server-instructions.js +56 -0
- package/dist/mcp/shared-params.d.ts +27 -0
- package/dist/mcp/shared-params.js +36 -0
- package/dist/pool/browser-pool.d.ts +22 -2
- package/dist/pool/browser-pool.js +44 -4
- package/dist/project/learned-routes.d.ts +24 -0
- package/dist/project/learned-routes.js +63 -0
- package/dist/project/project-store.d.ts +6 -0
- package/dist/project/project-store.js +25 -1
- package/dist/project/reticle-dir.d.ts +2 -0
- package/dist/project/reticle-dir.js +1 -0
- package/dist/session/connection-memory.d.ts +59 -0
- package/dist/session/connection-memory.js +108 -0
- package/dist/session/dev-command.d.ts +26 -0
- package/dist/session/dev-command.js +89 -0
- package/dist/session/dev-server-probe.d.ts +68 -0
- package/dist/session/dev-server-probe.js +102 -7
- package/dist/session/last-act.d.ts +26 -0
- package/dist/session/last-act.js +35 -1
- package/dist/session/live-control-tools.js +42 -5
- package/dist/session/no-session-diagnosis.d.ts +67 -2
- package/dist/session/no-session-diagnosis.js +236 -27
- package/dist/session/no-session-next-action.d.ts +46 -0
- package/dist/session/no-session-next-action.js +85 -0
- package/dist/session/no-session-watch.d.ts +40 -1
- package/dist/session/no-session-watch.js +174 -8
- package/dist/session/pending-commands.d.ts +12 -0
- package/dist/session/pending-commands.js +13 -1
- package/dist/session/ref-provenance.d.ts +54 -0
- package/dist/session/ref-provenance.js +61 -0
- package/dist/session/session-lease.js +1 -1
- package/dist/session/session-manager.d.ts +4 -0
- package/dist/session/session-manager.js +35 -5
- package/dist/session/session.d.ts +10 -1
- package/dist/session/session.js +146 -5
- package/dist/telemetry/app-instrumented.d.ts +8 -0
- package/dist/telemetry/app-instrumented.js +10 -0
- package/dist/telemetry/automation-hint.d.ts +17 -0
- package/dist/telemetry/automation-hint.js +71 -0
- package/dist/telemetry/bug-found.d.ts +15 -17
- package/dist/telemetry/bug-found.js +52 -21
- package/dist/telemetry/cli-telemetry.js +7 -1
- package/dist/telemetry/daemon-telemetry.js +24 -0
- package/dist/telemetry/feedback.js +1 -1
- package/dist/telemetry/init-telemetry.js +9 -1
- package/dist/telemetry/install-source.d.ts +56 -0
- package/dist/telemetry/install-source.js +74 -0
- package/dist/telemetry/instrumentation-stall.d.ts +50 -0
- package/dist/telemetry/instrumentation-stall.js +90 -0
- package/dist/telemetry/run-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +8 -0
- package/dist/telemetry/session-metrics.js +15 -0
- package/dist/telemetry/telemetry.d.ts +7 -1
- package/dist/telemetry/telemetry.js +26 -2
- package/dist/telemetry/tool-refused.d.ts +19 -0
- package/dist/telemetry/tool-refused.js +55 -0
- package/dist/telemetry/verification-of.js +46 -7
- package/dist/temp-dir.d.ts +27 -0
- package/dist/temp-dir.js +46 -0
- package/dist/tools/act-tools.js +209 -28
- package/dist/tools/assert-grade.d.ts +1 -1
- package/dist/tools/assert-grade.js +27 -5
- package/dist/tools/assert-verdict.js +49 -7
- package/dist/tools/browser-tools.js +10 -0
- package/dist/tools/contract-tools.js +4 -0
- package/dist/tools/dynamic-tools.js +16 -7
- package/dist/tools/error-recovery.d.ts +10 -0
- package/dist/tools/error-recovery.js +73 -9
- package/dist/tools/feedback-invite.js +1 -1
- package/dist/tools/invoke-tool.js +159 -26
- package/dist/tools/lease-hint.d.ts +30 -8
- package/dist/tools/lease-hint.js +65 -14
- package/dist/tools/lease-tools.d.ts +40 -1
- package/dist/tools/lease-tools.js +181 -83
- package/dist/tools/navigate-result.js +1 -1
- package/dist/tools/observe-tools.js +10 -4
- package/dist/tools/observed-nothing.js +1 -1
- package/dist/tools/react-grace.d.ts +52 -0
- package/dist/tools/react-grace.js +90 -0
- package/dist/tools/read-tools.js +67 -5
- package/dist/tools/resolve-target.d.ts +33 -0
- package/dist/tools/resolve-target.js +53 -0
- package/dist/tools/settle-in-flight.d.ts +94 -0
- package/dist/tools/settle-in-flight.js +146 -0
- package/dist/tools/snapshot-delta.d.ts +10 -0
- package/dist/tools/snapshot-delta.js +194 -9
- package/dist/tools/tool-kit.d.ts +8 -0
- package/dist/tools/tool-surface.d.ts +60 -0
- package/dist/tools/tool-surface.js +86 -1
- package/dist/tools/tools.js +61 -8
- package/dist/tools/unadvertised-help.js +9 -6
- package/docs/README.md +55 -11
- package/docs/actions.mdx +120 -0
- package/docs/agent-cheatsheet.md +95 -29
- package/docs/architecture.md +52 -35
- package/docs/benchmarks.md +127 -75
- package/docs/best-practices.mdx +216 -0
- package/docs/capabilities.mdx +534 -0
- package/docs/cli/affected.mdx +53 -0
- package/docs/cli/capsules.mdx +70 -0
- package/docs/cli/cloud.mdx +153 -0
- package/docs/cli/doctor.mdx +109 -0
- package/docs/cli/drive.mdx +74 -0
- package/docs/cli/feedback.mdx +67 -0
- package/docs/cli/gate.mdx +64 -0
- package/docs/cli/help.mdx +94 -0
- package/docs/cli/hunt.mdx +73 -0
- package/docs/cli/identify.mdx +76 -0
- package/docs/cli/init.mdx +121 -0
- package/docs/cli/kill.mdx +91 -0
- package/docs/cli/license.mdx +48 -0
- package/docs/cli/mcp.mdx +61 -0
- package/docs/cli/open.mdx +74 -0
- package/docs/cli/restart.mdx +60 -0
- package/docs/cli/rollback.mdx +35 -0
- package/docs/cli/serve.mdx +69 -0
- package/docs/cli/status.mdx +88 -0
- package/docs/cli/stop.mdx +64 -0
- package/docs/cli/telemetry.mdx +57 -0
- package/docs/cli/update.mdx +52 -0
- package/docs/cli/verify.mdx +76 -0
- package/docs/cli/version.mdx +39 -0
- package/docs/cli/watch.mdx +62 -0
- package/docs/cli.mdx +241 -0
- package/docs/debugging.md +16 -10
- package/docs/deploy-checks.md +45 -12
- package/docs/desktop.mdx +384 -0
- package/docs/docs.json +364 -0
- package/docs/enterprise.md +22 -16
- package/docs/faq.mdx +102 -0
- package/docs/fixtures.md +13 -7
- package/docs/flows.md +29 -23
- package/docs/for-agents.md +71 -0
- package/docs/frameworks.mdx +238 -0
- package/docs/gate-plan.md +48 -42
- package/docs/gates.md +28 -22
- package/docs/getting-started.md +129 -77
- package/docs/human-control.md +24 -18
- package/docs/index.mdx +143 -0
- package/docs/install-agentic.mdx +224 -0
- package/docs/install-manual.mdx +196 -0
- package/docs/instrumentation.mdx +238 -0
- package/docs/integration-patterns.md +41 -35
- package/docs/local-registry.md +19 -13
- package/docs/multi-agent-testing.md +19 -13
- package/docs/packages/babel-plugin.mdx +79 -0
- package/docs/packages/browser.mdx +111 -0
- package/docs/packages/core.mdx +116 -0
- package/docs/packages/electron.mdx +85 -0
- package/docs/packages/eslint-plugin.mdx +86 -0
- package/docs/packages/next.mdx +89 -0
- package/docs/packages/react.mdx +91 -0
- package/docs/packages/server.mdx +98 -0
- package/docs/packages/tauri.mdx +63 -0
- package/docs/packages/test.mdx +119 -0
- package/docs/packages/vite-plugin.mdx +94 -0
- package/docs/packages.mdx +218 -0
- package/docs/platform-integration.md +35 -26
- package/docs/predicates.mdx +248 -0
- package/docs/quickstart.mdx +257 -0
- package/docs/recipes.mdx +282 -0
- package/docs/skill-file.mdx +107 -0
- package/docs/state-management.mdx +199 -0
- package/docs/style.css +14 -0
- package/docs/system-map.md +50 -33
- package/docs/telemetry-contract.md +106 -52
- package/docs/telemetry-events.mdx +475 -0
- package/docs/telemetry.md +63 -55
- package/docs/testing.md +44 -6
- package/docs/token-efficiency.md +37 -27
- package/docs/tools-act-and-wait.mdx +173 -0
- package/docs/tools-act-sequence.mdx +137 -0
- package/docs/tools-act.mdx +95 -0
- package/docs/tools-assert.mdx +129 -0
- package/docs/tools-console.mdx +63 -0
- package/docs/tools-inspect.mdx +88 -0
- package/docs/tools-navigate.mdx +99 -0
- package/docs/tools-network.mdx +119 -0
- package/docs/tools-observe.mdx +145 -0
- package/docs/tools-overview.mdx +160 -0
- package/docs/tools-query.mdx +126 -0
- package/docs/tools-session-and-feedback.mdx +112 -0
- package/docs/tools-sessions.mdx +94 -0
- package/docs/tools-snapshot.mdx +129 -0
- package/docs/tools-state.mdx +104 -0
- package/docs/tools-tools-and-run.mdx +156 -0
- package/docs/tools-wait-for.mdx +85 -0
- package/docs/troubleshooting.mdx +263 -0
- package/docs/usage.md +209 -165
- package/docs/vs-chrome-devtools-mcp.mdx +123 -0
- package/docs/vs-playwright-mcp.mdx +125 -0
- package/docs/vs-screenshots.mdx +137 -0
- package/docs/what-is-reticle.mdx +63 -0
- package/docs/why-reticle.mdx +109 -0
- package/package.json +5 -5
- package/docs/desktop-apps.md +0 -256
- package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
- package/docs/matrix/2.5.0/codex-machine.json +0 -20
- package/docs/matrix/2.5.0/cursor-machine.json +0 -22
- package/docs/matrix/2.5.0/gemini-machine.json +0 -22
- package/docs/matrix/2.5.0/opencode-machine.json +0 -22
- package/docs/matrix/2.5.0/vscode-machine.json +0 -22
- package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
- package/docs/matrix/MATRIX.md +0 -26
- package/docs/matrix/README.md +0 -59
- package/docs/mint.json +0 -61
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle_query
|
|
3
|
+
description: Find elements by Testing-Library semantics. Role, text, label, placeholder, testid, alt, or React component, including inside open shadow roots.
|
|
4
|
+
icon: magnifying-glass
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle_query` answers "where is the thing I mean?" without dumping the whole page into your context window. It queries the way a testing library does. By role, label, text, testid. So your agent binds to meaning rather than to DOM structure that a refactor will move.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{ "by": "role", "value": "button", "limit": 6 }
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Real response from a running app, with four of the six elements trimmed out for length:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"count": 7,
|
|
20
|
+
"elements": [
|
|
21
|
+
{
|
|
22
|
+
"ref": "e118",
|
|
23
|
+
"role": "button",
|
|
24
|
+
"name": "Overview",
|
|
25
|
+
"visible": true,
|
|
26
|
+
"source": "src/components/Sidebar.tsx:41",
|
|
27
|
+
"states": ["present", "visible", "enabled"]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"ref": "e120",
|
|
31
|
+
"role": "button",
|
|
32
|
+
"name": "Compose",
|
|
33
|
+
"visible": true,
|
|
34
|
+
"source": "src/components/Sidebar.tsx:41",
|
|
35
|
+
"states": ["present", "visible", "enabled"]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"total": 7,
|
|
39
|
+
"truncated": true,
|
|
40
|
+
"cost": { "bytes": 944, "tokens": 236 }
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Seven buttons, each with a `ref` to act on and a source file to open, for 236 tokens.
|
|
45
|
+
|
|
46
|
+
## Arguments
|
|
47
|
+
|
|
48
|
+
| Argument | What it does |
|
|
49
|
+
| ------------ | -------------------------------------------------------------------------- |
|
|
50
|
+
| `by` | `role` · `text` · `label` · `placeholder` · `testid` · `alt` · `component` |
|
|
51
|
+
| `value` | The query value for that strategy |
|
|
52
|
+
| `name` | Accessible-name filter. Narrows a broad `role` query |
|
|
53
|
+
| `scope` | CSS selector or ref, to search inside a subtree |
|
|
54
|
+
| `limit` | Cap the descriptors returned. Cuts tokens hard on broad queries |
|
|
55
|
+
| `count_only` | Return just `{ count }`, around 30x smaller |
|
|
56
|
+
| `attrs` | Extra attributes per match, e.g. `['href']` to inventory links |
|
|
57
|
+
| `self` | Return the `scope` element itself instead of searching inside it |
|
|
58
|
+
|
|
59
|
+
Every argument also has a predicate spelling, so `{ "role": "button" }` works as shorthand for `{ "by": "role", "value": "button" }`.
|
|
60
|
+
|
|
61
|
+
## Use `count_only` when you only need a number
|
|
62
|
+
|
|
63
|
+
"Are there still three rows?" does not require three row descriptors:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{ "by": "testid", "value": "login-submit", "count_only": true }
|
|
67
|
+
```
|
|
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
|
+
|
|
113
|
+
## Reading the response
|
|
114
|
+
|
|
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.
|
|
116
|
+
|
|
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.
|
|
118
|
+
|
|
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.
|
|
120
|
+
|
|
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.
|
|
122
|
+
|
|
123
|
+
<Tip>
|
|
124
|
+
Query by `testid` when you can. Role and text queries survive refactors well; testids survive
|
|
125
|
+
redesigns, translations, and the day someone rewrites your button labels for the marketing team.
|
|
126
|
+
</Tip>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle_session and reticle_feedback
|
|
3
|
+
description: Hand the session back to the human, end it cleanly, and tell the maintainers when Reticle got something wrong.
|
|
4
|
+
icon: comments
|
|
5
|
+
---
|
|
6
|
+
|
|
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
|
+
|
|
9
|
+
## reticle_session
|
|
10
|
+
|
|
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
|
+
|
|
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` |
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{ "action": "yield", "mode": "waiting" }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`review` returns a real reading rather than a silent empty:
|
|
28
|
+
|
|
29
|
+
```json
|
|
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."
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
And each lease carries the rule in the payload itself:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
"session_lease": {
|
|
43
|
+
"IMPORTANT": "When you stop driving, call reticle_session {action:\"yield\", mode:\"waiting\"|\"ask\"}. The panel reads \"live\" until you do."
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
<Tip>
|
|
48
|
+
`yield` when you are pausing and might come back. `end` when you are finished. Both revive on your
|
|
49
|
+
next action, so neither is destructive. The difference is what the human watching the panel is
|
|
50
|
+
told.
|
|
51
|
+
</Tip>
|
|
52
|
+
|
|
53
|
+
## reticle_feedback
|
|
54
|
+
|
|
55
|
+
Reticle is built for agents, which creates an unusual problem: the primary user's experience vanishes the moment its context does. If an agent hits a gap and works around it silently, nobody ever learns the gap existed.
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"kind": "bug",
|
|
60
|
+
"text": "What I called, what I expected, what I got, and why Reticle is at fault.",
|
|
61
|
+
"currentApproach": "How I am working around it today.",
|
|
62
|
+
"impact": "What measurably improves if this is fixed."
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| `kind` | Use it when |
|
|
67
|
+
| ----------------- | ---------------------------------------------------------- |
|
|
68
|
+
| `bug` | A tool returned a wrong or broken result |
|
|
69
|
+
| `gap` | Reticle could not observe something you needed at all |
|
|
70
|
+
| `ambiguity` | The check ran but you could not tell what the answer meant |
|
|
71
|
+
| `feature_request` | You wished a capability existed |
|
|
72
|
+
| `improvement` | It works, but costs too many calls |
|
|
73
|
+
|
|
74
|
+
### It will tell you when it cannot send
|
|
75
|
+
|
|
76
|
+
Feedback is not fire-and-forget, and it does not pretend to succeed:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"sent": false,
|
|
81
|
+
"accepted": false,
|
|
82
|
+
"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.",
|
|
83
|
+
"redacted": [],
|
|
84
|
+
"context": {
|
|
85
|
+
"stack": "react",
|
|
86
|
+
"client": "claude-code",
|
|
87
|
+
"runtime": "web",
|
|
88
|
+
"engine": "blink",
|
|
89
|
+
"driver": "cdp",
|
|
90
|
+
"mcpScope": "user"
|
|
91
|
+
},
|
|
92
|
+
"note": "NOT accepted (see reason). Tell the human what you found so it is not lost."
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`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.
|
|
97
|
+
|
|
98
|
+
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.
|
|
99
|
+
|
|
100
|
+
### From the shell, when the tools are unreachable
|
|
101
|
+
|
|
102
|
+
The setup that failed to finish is exactly the setup that most needs reporting, and in that state the MCP tools do not exist:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx @reticlehq/server feedback --agent --kind gap "reticle init finished but no session ever connected"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
<Note>
|
|
109
|
+
Report defects in **Reticle**. A bug you find in the app under test is Reticle working correctly,
|
|
110
|
+
and belongs in your answer to the user. Not in a bug report to us. We get a surprising number of
|
|
111
|
+
those, and each one is quietly a compliment.
|
|
112
|
+
</Note>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle_sessions
|
|
3
|
+
description: List every connected browser tab, with the health fields that tell you whether it can actually be driven.
|
|
4
|
+
icon: list-check
|
|
5
|
+
---
|
|
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
|
+
|
|
9
|
+
```json
|
|
10
|
+
{}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Real response from a healthy session:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"sessions": [
|
|
18
|
+
{
|
|
19
|
+
"sessionId": "sba6117a6-24ec-494d-8c2c-e2958cff2e7f",
|
|
20
|
+
"url": "http://localhost:4310/",
|
|
21
|
+
"title": "Reticle · Mission Control",
|
|
22
|
+
"adapters": ["react"],
|
|
23
|
+
"hasCapabilities": true,
|
|
24
|
+
"hidden": false,
|
|
25
|
+
"lastSeenMs": 155,
|
|
26
|
+
"throttled": false,
|
|
27
|
+
"focused": true,
|
|
28
|
+
"attachment": { "connectedSinceMs": 18654, "outages": 0 },
|
|
29
|
+
"realInputAvailable": false,
|
|
30
|
+
"leased": false
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
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
|
+
|
|
64
|
+
## The fields that decide whether driving will work
|
|
65
|
+
|
|
66
|
+
| Field | Why it matters |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `throttled` | The browser is deprioritising a background tab. Synthetic timers and pointer gestures may silently no-op |
|
|
69
|
+
| `hidden` / `focused` | Why it's throttled, and what to do about it |
|
|
70
|
+
| `hasCapabilities` | Whether the app registered testids, signals and stores. `false` means [`reticle_state`](/tools-state) has nothing to read |
|
|
71
|
+
| `adapters` | `["react"]` means you get component names and source pointers |
|
|
72
|
+
| `realInputAvailable` | `true` when native CDP input is available, under `reticle drive` |
|
|
73
|
+
| `outages` | How often the connection has dropped. Non-zero is worth investigating |
|
|
74
|
+
|
|
75
|
+
<Warning>
|
|
76
|
+
`throttled: true` is the most common cause of "the click did nothing". Focus the tab, or drive a
|
|
77
|
+
dedicated context. It is not your app being broken. It is the browser saving battery on a tab
|
|
78
|
+
nobody is looking at.
|
|
79
|
+
</Warning>
|
|
80
|
+
|
|
81
|
+
## Confirm after navigating
|
|
82
|
+
|
|
83
|
+
[`reticle_navigate`](/tools-navigate) can only report that a navigation was dispatched. `sessions` is how you confirm one arrived: a session at the new URL means the page loaded **and** is instrumented. No session means one of those two is false, and you find out now rather than after three confusing failures.
|
|
84
|
+
|
|
85
|
+
## Scoping
|
|
86
|
+
|
|
87
|
+
You rarely need to pass `sessionId` to other tools. Reticle scopes to your project, prefers the active tab, and refuses rather than guesses when the choice is ambiguous. A refusal you can act on beats a silent pick of the wrong tab.
|
|
88
|
+
|
|
89
|
+
Pass it explicitly when you genuinely mean one specific tab, such as when testing two apps at once.
|
|
90
|
+
|
|
91
|
+
<Note>
|
|
92
|
+
Sessions accumulate. A stale entry pointing at a dev server you have since restarted will sit there
|
|
93
|
+
looking plausible. `reticle_session { action: "end" }` clears one out.
|
|
94
|
+
</Note>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle_snapshot
|
|
3
|
+
description: A semantic accessibility snapshot of the page or a subtree, in three sizes. From the full tree down to a 25-token route check.
|
|
4
|
+
icon: camera
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`reticle_snapshot` is how an agent gets its bearings. It returns the page as semantic structure, not pixels and not raw HTML, and it comes in three sizes so you can pay for only what you need.
|
|
8
|
+
|
|
9
|
+
## Three modes, three prices
|
|
10
|
+
|
|
11
|
+
| Mode | Returns | Real cost on one page |
|
|
12
|
+
| ------------- | ------------------------------------- | --------------------- |
|
|
13
|
+
| `status` | Route and title only | **25 tokens** |
|
|
14
|
+
| `interactive` | Only clickable and focusable elements | **65 tokens** |
|
|
15
|
+
| `full` | Every element | Depends on the page |
|
|
16
|
+
|
|
17
|
+
### `status`. the cheapest possible check
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{ "mode": "status" }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"tree": "",
|
|
26
|
+
"nodes": 0,
|
|
27
|
+
"truncated": false,
|
|
28
|
+
"status": { "route": "/", "title": "Reticle · Mission Control" },
|
|
29
|
+
"cost": { "bytes": 98, "tokens": 25 }
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Ninety-eight bytes to answer "where am I?". Use it after a navigation instead of re-reading the page.
|
|
34
|
+
|
|
35
|
+
### `interactive`. the default working view
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{ "mode": "interactive" }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"tree": "- textbox \"Email\" (ref=e303) [value=\"admin@reticle.dev\"]\n- textbox \"Password\" (ref=e304) [value=\"[REDACTED]\"]\n- button \"Sign in\" (ref=e305)",
|
|
44
|
+
"nodes": 3,
|
|
45
|
+
"truncated": false,
|
|
46
|
+
"status": { "route": "/deployments", "title": "Reticle · Mission Control" },
|
|
47
|
+
"cost": { "bytes": 260, "tokens": 65 }
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Everything you can act on, with a `ref` for each, for 65 tokens. Note the password arrives `[REDACTED]` without anyone configuring it.
|
|
52
|
+
|
|
53
|
+
## Arguments
|
|
54
|
+
|
|
55
|
+
| Argument | What it does |
|
|
56
|
+
| -------- | ---------------------------------------------------------------------------- |
|
|
57
|
+
| `mode` | `full` · `interactive` · `status` |
|
|
58
|
+
| `scope` | CSS selector or ref, to snapshot one subtree |
|
|
59
|
+
| `diff` | Return only what changed since your last snapshot of the same scope and mode |
|
|
60
|
+
|
|
61
|
+
## `diff` is how you keep a long session cheap
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{ "mode": "interactive", "diff": true }
|
|
65
|
+
```
|
|
66
|
+
|
|
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.
|
|
106
|
+
|
|
107
|
+
<Tip>
|
|
108
|
+
Reach for [`reticle_query`](/tools-query) instead when you already know what you're looking for.
|
|
109
|
+
Snapshot is for orientation; query is for retrieval, and it's almost always cheaper.
|
|
110
|
+
</Tip>
|
|
111
|
+
|
|
112
|
+
## Refs change across documents
|
|
113
|
+
|
|
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>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: reticle_state
|
|
3
|
+
description: Read live framework state directly from the running app. What it believes, not just what it rendered, without the app broadcasting anything.
|
|
4
|
+
icon: database
|
|
5
|
+
---
|
|
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
|
+
|
|
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.
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{ "depth": 2 }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Real response:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"found": true,
|
|
22
|
+
"value": {
|
|
23
|
+
"stores": {
|
|
24
|
+
"__reticle_renders": "{…1 keys}",
|
|
25
|
+
"app": "{…30 keys}",
|
|
26
|
+
"queries": "{…0 keys}"
|
|
27
|
+
},
|
|
28
|
+
"storeNames": ["__reticle_renders", "app", "queries"]
|
|
29
|
+
},
|
|
30
|
+
"storeNames": ["__reticle_renders", "app", "queries"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`depth: 2` collapsed the contents to size markers: `{…30 keys}` rather than thirty keys of JSON. On a large store this is the difference between a cheap look and a very expensive one.
|
|
35
|
+
|
|
36
|
+
## Arguments
|
|
37
|
+
|
|
38
|
+
| Argument | What it does |
|
|
39
|
+
| -------- | ------------------------------------------------------------ |
|
|
40
|
+
| `store` | A registered store name, e.g. `app` |
|
|
41
|
+
| `path` | Dot-path into a store, e.g. `cart.items.0.qty` |
|
|
42
|
+
| `depth` | Collapse anything deeper than N levels to a size marker |
|
|
43
|
+
| `ref` | Best-effort read of the nearest React component's hook state |
|
|
44
|
+
|
|
45
|
+
Drill in once you know what you want:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{ "store": "app", "path": "auth" }
|
|
49
|
+
```
|
|
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
|
+
|
|
70
|
+
## You have to register stores first
|
|
71
|
+
|
|
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.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
registerCapabilities({
|
|
76
|
+
stores: [{ name: 'app', store: appStore }],
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
<Warning>
|
|
81
|
+
Pass the **store**, not `() => store.getState()`. The store form wires `subscribe` too, so every
|
|
82
|
+
mutation emits a state diff. The getter form is read-only and silently produces empty diffs, which
|
|
83
|
+
looks like "nothing changed" and is really "I was never watching".
|
|
84
|
+
</Warning>
|
|
85
|
+
|
|
86
|
+
That distinction is the single most common instrumentation mistake, and its failure mode is a verdict that passes when it should not.
|
|
87
|
+
|
|
88
|
+
## Why this is the strongest evidence you have
|
|
89
|
+
|
|
90
|
+
A `POST` returning `200` proves the server was reachable. A row in the DOM proves React rendered something. Neither proves your application accepted the change.
|
|
91
|
+
|
|
92
|
+
State does. When [`reticle_act_and_wait`](/quickstart) reports
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
"stateDiffs": [
|
|
96
|
+
{ "path": "auth", "from": null, "to": "{\"email\":\"admin@reticle.dev\"}", "atMs": 44403 }
|
|
97
|
+
]
|
|
98
|
+
```
|
|
99
|
+
|
|
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.
|
|
101
|
+
|
|
102
|
+
<Card title="Instrument your app" icon="wrench" href="/instrumentation">
|
|
103
|
+
Registering one store for your most important flow is the highest-value line you can write.
|
|
104
|
+
</Card>
|