@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
package/docs/README.md
CHANGED
|
@@ -1,31 +1,72 @@
|
|
|
1
1
|
# Docs index
|
|
2
2
|
|
|
3
|
-
Two audiences share this directory
|
|
3
|
+
Two audiences share this directory: people using Reticle and people working on it. Every page carries a `description` in its frontmatter saying what it answers; this index is the shortcut when you want to scan all of them at once.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Everything here is published to [docs.reticle.sh](https://docs.reticle.sh) by `docs.json`, which is the Mintlify config for this directory. Five tabs. **Guides** to learn in order, grouped by what you are doing (get started, install, instrument, verify and ship, work with agents, and when it goes wrong). **Reference** to look one thing up. **Desktop** because Electron and Tauri are a different shape of problem and deserve their own front door, **Resources** to decide or to check a claim, and **Contributing** for people working on Reticle. Contributor docs sit in a tab rather than hidden, since they were reachable by URL anyway, and an unlisted page is a page nobody finds.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## For people using Reticle
|
|
10
10
|
|
|
11
|
-
**Start:** [
|
|
11
|
+
**Start:** [quickstart.mdx](quickstart.mdx) → [usage.md](usage.md) (the full tool reference).
|
|
12
12
|
|
|
13
13
|
| Page | What it answers |
|
|
14
14
|
| --- | --- |
|
|
15
|
+
| [quickstart.mdx](quickstart.mdx) | five minutes to a real verdict; every response on it was captured live |
|
|
16
|
+
| [what-is-reticle.mdx](what-is-reticle.mdx) | the definition, what Reticle is NOT, and what it needs to run |
|
|
17
|
+
| [why-reticle.mdx](why-reticle.mdx) | the false-green problem, the measured case, and where we lose |
|
|
18
|
+
| [install-agentic.mdx](install-agentic.mdx) | what `npx @reticlehq/server init` writes, and how to read its marks |
|
|
19
|
+
| [install-manual.mdx](install-manual.mdx) | wiring the MCP server and SDK by hand, per agent and framework |
|
|
15
20
|
| [getting-started.md](getting-started.md) | install it, connect an agent, verify something |
|
|
16
|
-
| [usage.md](usage.md) |
|
|
21
|
+
| [usage.md](usage.md) | the long-form narrative; most of it now has a focused page, and it says so at the top |
|
|
22
|
+
| [predicates.mdx](predicates.mdx) | the predicate grammar, and which kinds actually prove something |
|
|
23
|
+
| [capabilities.mdx](capabilities.mdx) | coverage, storage, fake clocks, crawl, visual diff, network mocking |
|
|
24
|
+
| [recipes.mdx](recipes.mdx) | worked examples for real situations, with the response each returned |
|
|
25
|
+
| [actions.mdx](actions.mdx) | every action and its arguments, including `press` and its history |
|
|
26
|
+
| [faq.mdx](faq.mdx) | production, frameworks, comparisons, and the honest limits |
|
|
27
|
+
| [tools-overview.mdx](tools-overview.mdx) | the 18 advertised tools, the 30 in the cold tail, and why |
|
|
28
|
+
| [tools-snapshot.mdx](tools-snapshot.mdx) | `reticle_snapshot`: three modes, from full tree to a 25-token route check |
|
|
29
|
+
| [tools-query.mdx](tools-query.mdx) | `reticle_query` finds elements by testing-library semantics |
|
|
30
|
+
| [tools-inspect.mdx](tools-inspect.mdx) | `reticle_inspect`: one element, down to source and design tokens |
|
|
31
|
+
| [tools-navigate.mdx](tools-navigate.mdx) | `reticle_navigate`, and why `ok` does not mean the page arrived |
|
|
32
|
+
| [tools-act.mdx](tools-act.mdx) | `reticle_act` acts, proves nothing, and says so |
|
|
33
|
+
| [tools-act-and-wait.mdx](tools-act-and-wait.mdx) | `reticle_act_and_wait`, the tool that produces a verdict |
|
|
34
|
+
| [tools-act-sequence.mdx](tools-act-sequence.mdx) | `reticle_act_sequence`: batch a form into one round trip |
|
|
35
|
+
| [tools-observe.mdx](tools-observe.mdx) | `reticle_observe`, the whole timeline when you don't know what broke |
|
|
36
|
+
| [tools-network.mdx](tools-network.mdx) | `reticle_network`: the request log, redaction, and buffer honesty |
|
|
37
|
+
| [tools-console.mdx](tools-console.mdx) | `reticle_console`, and an empty result that proves it looked |
|
|
38
|
+
| [tools-state.mdx](tools-state.mdx) | `reticle_state`: what the app believes, not what it drew |
|
|
39
|
+
| [tools-wait-for.mdx](tools-wait-for.mdx) | `reticle_wait_for`, for consequences you did not cause |
|
|
40
|
+
| [tools-assert.mdx](tools-assert.mdx) | `reticle_assert`: verdicts, and a real failure explained |
|
|
41
|
+
| [tools-sessions.mdx](tools-sessions.mdx) | `reticle_sessions`: the health fields that decide if driving works |
|
|
42
|
+
| [tools-tools-and-run.mdx](tools-tools-and-run.mdx) | `reticle_tools` / `reticle_run`, reaching the other 30 |
|
|
43
|
+
| [tools-session-and-feedback.mdx](tools-session-and-feedback.mdx) | `reticle_session` / `reticle_feedback`, the human boundary |
|
|
44
|
+
| [packages.mdx](packages.mdx) | every library at a glance: what it does, why it exists, when you need it |
|
|
45
|
+
| [packages/](packages/) | one page per published package, with its real exported API and dependencies |
|
|
46
|
+
| [best-practices.mdx](best-practices.mdx) | the habits that make a verdict worth trusting |
|
|
47
|
+
| [skill-file.mdx](skill-file.mdx) | the paste-one-URL skill that teaches an agent Reticle |
|
|
17
48
|
| [agent-cheatsheet.md](agent-cheatsheet.md) | the condensed version an agent keeps in context |
|
|
49
|
+
| [for-agents.md](for-agents.md) | how to fetch these docs as Markdown or `llms.txt` |
|
|
18
50
|
| [architecture.md](architecture.md) | how it works, and why it is built this way |
|
|
19
51
|
| [platform-integration.md](platform-integration.md) | Vite, Next, Remix, Astro, plain HTML |
|
|
20
|
-
| [desktop
|
|
52
|
+
| [desktop.mdx](desktop.mdx) | Electron and Tauri in full: setup, IPC, screenshots, headless, troubleshooting |
|
|
53
|
+
| [frameworks.mdx](frameworks.mdx) | what is supported, what is wired-but-unverified, and the wiring |
|
|
54
|
+
| [state-management.mdx](state-management.mdx) | zustand, Redux, and eight adapters |
|
|
55
|
+
| [instrumentation.mdx](instrumentation.mdx) | stores, signals, testids, and how verdicts get stronger |
|
|
56
|
+
| [troubleshooting.mdx](troubleshooting.mdx) | nothing connected, click did nothing, verdict says unknown |
|
|
57
|
+
| [cli.mdx](cli.mdx) | the CLI at a glance, with real output and measured exit codes |
|
|
58
|
+
| [cli/](cli/) | one page per command: every flag, what it prints, and its exit codes |
|
|
21
59
|
| [integration-patterns.md](integration-patterns.md) | wiring it into a real codebase |
|
|
22
60
|
| [flows.md](flows.md) | record → save → replay → heal |
|
|
23
|
-
| [testing.md](testing.md) | `@reticlehq/test
|
|
61
|
+
| [testing.md](testing.md) | `@reticlehq/test`, turning a session into a CI suite |
|
|
24
62
|
| [multi-agent-testing.md](multi-agent-testing.md) | more than one agent on one app |
|
|
25
63
|
| [human-control.md](human-control.md) | taking the wheel back from the agent |
|
|
26
64
|
| [deploy-checks.md](deploy-checks.md) | running Reticle against a deployed build |
|
|
27
65
|
| [token-efficiency.md](token-efficiency.md) | why it costs less than a screenshot loop |
|
|
28
66
|
| [benchmarks.md](benchmarks.md) | how the numbers were measured, including where Reticle loses |
|
|
67
|
+
| [vs-playwright-mcp.mdx](vs-playwright-mcp.mdx) | outside-in vs inside-out, and when Playwright is right |
|
|
68
|
+
| [vs-chrome-devtools-mcp.mdx](vs-chrome-devtools-mcp.mdx) | cheaper per look, catches less: the trade, measured |
|
|
69
|
+
| [vs-screenshots.mdx](vs-screenshots.mdx) | why a better vision model does not fix a non-visual bug |
|
|
29
70
|
| [telemetry.md](telemetry.md) | what is collected, and how to turn it off |
|
|
30
71
|
| [local-registry.md](local-registry.md) | installing an unpublished build |
|
|
31
72
|
| [enterprise.md](enterprise.md) | the licensed surface |
|
|
@@ -36,20 +77,23 @@ Two audiences share this directory, which is why it looked like twenty-five unso
|
|
|
36
77
|
|
|
37
78
|
| Page | What it answers |
|
|
38
79
|
| --- | --- |
|
|
39
|
-
| [gates.md](gates.md) | **I changed some files
|
|
80
|
+
| [gates.md](gates.md) | **I changed some files. Which gate do I run?** |
|
|
40
81
|
| [gate-plan.md](gate-plan.md) | why the gates are shaped this way, and what is still unbuilt |
|
|
41
82
|
| [system-map.md](system-map.md) | how a tool call reaches the app, and which failures are silent |
|
|
42
83
|
| [telemetry-contract.md](telemetry-contract.md) | required reading before touching anything that emits |
|
|
43
|
-
| [
|
|
84
|
+
| [telemetry-events.mdx](telemetry-events.mdx) | every event kind and its payload, and the question each one exists to answer |
|
|
85
|
+
| [debugging.md](debugging.md) | debugging Reticle itself: the four signals and what each answers |
|
|
44
86
|
| [fixtures.md](fixtures.md) | the sibling `reticle-fixtures` repo: install complexity, not regressions |
|
|
45
|
-
| [matrix/README.md](matrix/README.md) | submitting an MCP-client compatibility record
|
|
87
|
+
| [matrix/README.md](matrix/README.md) | submitting an MCP-client compatibility record, the best first contribution |
|
|
46
88
|
| [matrix/MATRIX.md](matrix/MATRIX.md) | which clients are known to work (generated; do not hand-edit) |
|
|
47
89
|
| [`../apps/README.md`](../apps/README.md) | what belongs in `apps/`, and what does not |
|
|
48
90
|
| [`../apps/e2e/harness-rules.md`](../apps/e2e/harness-rules.md) | the four rules every gate obeys, and the incident behind each |
|
|
49
91
|
| [`../bench/README.md`](../bench/README.md) | what in `bench/` is live and what is a kept one-off study |
|
|
50
92
|
|
|
51
|
-
`fixtures-dispatch-receiver.yml` is not a doc
|
|
93
|
+
`fixtures-dispatch-receiver.yml` is not a doc; it is the workflow template `reticle-fixtures` needs, kept in this repo so the two ends of the contract cannot drift apart.
|
|
52
94
|
|
|
53
95
|
---
|
|
54
96
|
|
|
55
|
-
**Adding a page?**
|
|
97
|
+
**Adding a page?** Three things, all required. Give it `title` + `description` frontmatter and no `# H1`. Mintlify renders the frontmatter title as the heading, so an H1 shows up twice. Add its slug to the right tab in `docs.json`. Add a row to the right table above. A page missing from `docs.json` is one nobody can reach; a page missing from this index is one no contributor knows exists.
|
|
98
|
+
|
|
99
|
+
**Adding a second product?** Do not nest these files under a product folder pre-emptively; that renames every live URL to buy nothing. Mintlify supports `navigation.products`, where each product declares its own `directory`. When the second product exists, put its pages in `docs/<product>/`, switch `docs.json` from `tabs` to `products`, and give this product `"directory": ""` so today's URLs keep working.
|
package/docs/actions.mdx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Action reference: lights, camera, click'
|
|
3
|
+
sidebarTitle: Actions
|
|
4
|
+
description: Every action reticle_act and reticle_act_and_wait can perform, with its arguments and the one that has a history.
|
|
5
|
+
icon: hand-pointer
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Every action Reticle can perform takes the same shape: a `ref` from [`reticle_snapshot`](/tools-snapshot) or [`reticle_query`](/tools-query), an `action` name, and an optional `args` object. The same seventeen actions are available on [`reticle_act`](/tools-act), which proves nothing, and on [`reticle_act_and_wait`](/tools-act-and-wait), which returns a verdict.
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{ "ref": "e104", "action": "fill", "args": { "value": "reticle" } }
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Action | Arguments | Notes |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| `click` / `dblclick` | none | Dispatches a real click |
|
|
17
|
+
| `hover` | none | `mouseover` + `mouseenter`, so JS hover state triggers |
|
|
18
|
+
| `focus` / `blur` | none | |
|
|
19
|
+
| `fill` | `{ value }` | Sets value via a React-safe native setter, then `input` and `change` |
|
|
20
|
+
| `type` | `{ text }` | **Appends** to the current value |
|
|
21
|
+
| `clear` | none | Empties an input |
|
|
22
|
+
| `select` | `{ value }` | For `<select>` |
|
|
23
|
+
| `check` / `uncheck` | none | Checkbox and radio |
|
|
24
|
+
| `submit` | none | Submits the element's `<form>` |
|
|
25
|
+
| `press` | `{ text }` | The key **name**: `Escape`, `Tab`, `Enter` |
|
|
26
|
+
| `scrollIntoView` | none | |
|
|
27
|
+
| `upload` | `{ content?, name?, type? }` | Sets a file on `<input type="file">`. All three default, to `"reticle test file"`, `"file.txt"` and `"text/plain"` |
|
|
28
|
+
| `drag` | `{ toRef }` | Pointer-based drag (dnd-kit, react-beautiful-dnd) plus HTML5 DnD. `target` is an alias |
|
|
29
|
+
| `webmcp` | `{ tool, params }` | Calls a `navigator.modelContext` tool, if the site exposes one |
|
|
30
|
+
|
|
31
|
+
### Arguments that are not actions
|
|
32
|
+
|
|
33
|
+
Three `args` keys apply across actions rather than belonging to one:
|
|
34
|
+
|
|
35
|
+
| Key | What it does |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `native` | Forces a trusted native click instead of the occlusion-honest synthetic path. For file pickers and clipboard access |
|
|
38
|
+
| `holdMs` | Keeps the pointer **down** for that long between mousedown and mouseup. The only way to drive a hold-to-confirm control. `effect.heldMs` reports the hold actually achieved |
|
|
39
|
+
| `confirmDangerous` | A permission gate for a control Reticle judged destructive. It is **not** a duration |
|
|
40
|
+
|
|
41
|
+
<Warning>
|
|
42
|
+
`confirmDangerous` and `holdMs` are routinely confused because both show up around delete buttons.
|
|
43
|
+
`holdMs` is how long the button is held; `confirmDangerous` is permission to press it at all.
|
|
44
|
+
Passing the wrong one gets you either a refusal or a press that was never held.
|
|
45
|
+
</Warning>
|
|
46
|
+
|
|
47
|
+
### The refusal you will meet first
|
|
48
|
+
|
|
49
|
+
Reticle blocks a control that looks destructive before acting on it:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"error": "potentially destructive action blocked; retry with args.confirmDangerous=true",
|
|
54
|
+
"recovery": "Reticle blocked a potentially destructive control (delete, remove, revoke…) on purpose. If you mean it, retry the same action with args.confirmDangerous set to true. This is a deliberate refusal, not a defect: there is nothing to report."
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
A stale ref is refused the same way, with `"ref 'e303' no longer resolves to an element"` and a recovery note telling you to re-query. Both refusals cost a turn and prevent a false green, which is the trade.
|
|
59
|
+
|
|
60
|
+
## `fill` versus `type`
|
|
61
|
+
|
|
62
|
+
`fill` replaces. `type` appends. Reaching for `type` when you meant `fill` is how a field ends up containing `hellohello`, and neither call will complain.
|
|
63
|
+
|
|
64
|
+
## `press` takes `text`, not `key`
|
|
65
|
+
|
|
66
|
+
Both are accepted today, and `text` wins when both are present. Use `text`. It is what the tool description documents.
|
|
67
|
+
|
|
68
|
+
<Warning>
|
|
69
|
+
This one has history worth knowing. The implementation used to read `args.key` and **default to
|
|
70
|
+
`Enter`**, so the documented call, `{ action: "press", args: { text: "Escape" } }`, silently sent
|
|
71
|
+
`Enter` and reported success.
|
|
72
|
+
|
|
73
|
+
Three consequences, worst last: the requested key never arrived, so Escape-to-close and Tab-traversal went unverified while looking verified; nothing in the result said the argument had been ignored; and `Enter` is not a neutral substitute. On a focused field inside a form it **submits it**. A request to close a dialog could file the form behind it.
|
|
74
|
+
|
|
75
|
+
Two field reports were exactly this, both diagnosed as "synthetic events don't reach the app". Wrong root cause: the event reached the app perfectly well and simply said `Enter`.
|
|
76
|
+
|
|
77
|
+
</Warning>
|
|
78
|
+
|
|
79
|
+
That bug is fixed, and the reason it is written down here is that it is the exact shape of failure Reticle exists to catch. An action that reports success while doing something else.
|
|
80
|
+
|
|
81
|
+
## Batching
|
|
82
|
+
|
|
83
|
+
Several actions in one round trip:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"steps": [
|
|
88
|
+
{ "ref": "e603", "action": "fill", "args": { "value": "admin@reticle.dev" } },
|
|
89
|
+
{ "ref": "e604", "action": "fill", "args": { "value": "hunter2" } },
|
|
90
|
+
{ "ref": "e605", "action": "click" }
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
<Warning>
|
|
96
|
+
[`reticle_act_sequence`](/tools-act-sequence) returns `ok: true` when the steps were
|
|
97
|
+
**dispatched**, not when they worked. Batch the setup, then prove the outcome with
|
|
98
|
+
[`reticle_act_and_wait`](/tools-act-and-wait) on the final step.
|
|
99
|
+
</Warning>
|
|
100
|
+
|
|
101
|
+
## Real versus synthetic input
|
|
102
|
+
|
|
103
|
+
`inputMode` in the response says which you got. `synthetic` means events dispatched programmatically. Correct for the overwhelming majority of apps. `real` means native CDP input, available under `reticle drive`, and needed by a few drag-and-drop and pointer-gesture libraries.
|
|
104
|
+
|
|
105
|
+
<Warning>
|
|
106
|
+
On a throttled tab, synthetic timers and pointer gestures can silently no-op. Pass
|
|
107
|
+
`refuseWhenThrottled: true` to fail loudly instead of acting into a tab the browser has paused.
|
|
108
|
+
</Warning>
|
|
109
|
+
|
|
110
|
+
## What every action reports
|
|
111
|
+
|
|
112
|
+
`dispatched`, `targetMatched`, `visible`, `enabled`, `valueChanged`, `focusMoved`, `domMutatedWithin`, `defaultPrevented`, `occluded`, `occludedBy` and `scrolledIntoView`. Plus the element's `testid`, `component`, `role`, `name` and `source` file and line.
|
|
113
|
+
|
|
114
|
+
Fields sitting at their uninformative default are **omitted**, so a clean action collapses to its consequence. A missing `visible` means `true`, not `false`. Read an absence as "nothing to report" rather than as a failure.
|
|
115
|
+
|
|
116
|
+
`occluded` is the answer to a large share of "the button doesn't work" reports: the click landed on the modal overlay sitting on top of it.
|
|
117
|
+
|
|
118
|
+
<Card title="Full field-by-field walkthrough" icon="hand-pointer" href="/tools-act">
|
|
119
|
+
What each effect field tells you, with a real response.
|
|
120
|
+
</Card>
|
package/docs/agent-cheatsheet.md
CHANGED
|
@@ -1,29 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Agent cheat sheet
|
|
3
|
+
description: 'One screen to get fluent: the look → act → observe → assert loop, with the exact calls to make.'
|
|
4
|
+
icon: bolt
|
|
5
|
+
---
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
The loop is **look → act → observe → assert**, and only `reticle_act_and_wait` and `reticle_assert` produce a verdict. Reach for `reticle_act_and_wait({ ref, action, until })` first: it names the expected consequence before the action, which is the difference between a check and a rationalisation. `verified: "unknown"` is not a pass.
|
|
8
|
+
|
|
9
|
+
One screen to get fluent. Reticle is the **proof layer for AI agents**: no screenshots, no vision model, evidence not prose. Everything below returns structured data. Full guide: [usage.md](usage.md).
|
|
4
10
|
|
|
5
11
|
## The core loop: look → act → observe → assert
|
|
6
12
|
|
|
7
13
|
| Verb | Tool | One-liner |
|
|
8
14
|
| --- | --- | --- |
|
|
9
15
|
| **look** | `reticle_snapshot` / `reticle_query` | See the page (semantic tree) / find one specific element. |
|
|
10
|
-
| **act** | **`reticle_act_and_wait`** / `reticle_act_sequence` / `reticle_act` | **Act + name the consequence, one hop
|
|
16
|
+
| **act** | **`reticle_act_and_wait`** / `reticle_act_sequence` / `reticle_act` | **Act + name the consequence, one hop. Reach for this first.** / batch a whole journey in one hop / move the app and prove nothing. |
|
|
11
17
|
| **observe** | `reticle_observe` / `reticle_wait_for` | Everything the app did after `since` / block until true. |
|
|
12
18
|
| **assert** | `reticle_assert` | Evaluate a predicate → `{ pass, evidence, failureReason? }`. The end of every loop. |
|
|
13
19
|
|
|
14
|
-
> **Only `reticle_act_and_wait` and `reticle_assert` produce a verdict.** Everything else moves or reads the app and proves nothing, so a drive ending without one of those two has no result however many tools it used. `reticle_act` is the tool agents reach for by habit and it catches nothing; `act_and_wait` is where defects actually surface. And `verified: "unknown"` is not a pass
|
|
20
|
+
> **Only `reticle_act_and_wait` and `reticle_assert` produce a verdict.** Everything else moves or reads the app and proves nothing, so a drive ending without one of those two has no result however many tools it used. `reticle_act` is the tool agents reach for by habit and it catches nothing; `act_and_wait` is where defects actually surface. And `verified: "unknown"` is not a pass: it means Reticle drove the app and could not tell what happened. Report it as unknown.
|
|
15
21
|
|
|
16
|
-
`reticle_act` returns a `since` cursor
|
|
22
|
+
`reticle_act` returns a `since` cursor; pass it to `reticle_observe({ since })` to scope the window. Elements are addressed by stable refs (`e7`) from `snapshot`/`query`; they re-resolve across re-renders.
|
|
17
23
|
|
|
18
|
-
**`assert`/`wait_for` are auto-scoped to your last act.** By default they only count events buffered _since_ the most recent act, so a stale signal from a previous step can't fake a pass
|
|
24
|
+
**`assert`/`wait_for` are auto-scoped to your last act.** By default they only count events buffered _since_ the most recent act, so a stale signal from a previous step can't fake a pass. Pass an explicit `since` to override. **Clicks run the code, not pixels:** `reticle_act` click fires the full pointer sequence on the element (no coordinate gesture for the HUD to intercept), reports `occluded:true` when something covers the target, and stays synthetic even with CDP configured (use `args:{ native:true }` for a trusted native click).
|
|
19
25
|
|
|
20
|
-
**Never sleep
|
|
26
|
+
**Never sleep. Wait deterministically.** Fixed sleeps are the #1 cause of flaky agent tests. Instead:
|
|
21
27
|
|
|
22
|
-
- `reticle_act_and_wait({ ref, action })` with **no `until`** waits for the page to _settle_ (network + structural DOM idle; ambient count-up/spinner churn is ignored so an animated page still settles) before returning
|
|
28
|
+
- `reticle_act_and_wait({ ref, action })` with **no `until`** waits for the page to _settle_ (network + structural DOM idle; ambient count-up/spinner churn is ignored so an animated page still settles) before returning: the one-call replacement for "click then sleep 500ms".
|
|
23
29
|
- Need to wait without acting? `reticle_wait_for({ predicate: { kind: "settled", quietMs } })`.
|
|
24
30
|
- Waiting for a specific outcome? Pass that consequence as the predicate (`{ signal }` / `{ net }`), or `allOf` it with `{ kind: "settled" }` to wait for both the event _and_ the page going quiet.
|
|
25
31
|
|
|
26
|
-
**A predicate that does not parse produces NO verdict
|
|
32
|
+
**A predicate that does not parse produces NO verdict, not a failing one.** Nothing runs, so the drive ends with no result at all, which is strictly worse than a failure. The shapes below are the ones agents reach for most; the first column now works, but knowing the second saves you the round trip:
|
|
27
33
|
|
|
28
34
|
| You may write | It means |
|
|
29
35
|
| --- | --- |
|
|
@@ -31,11 +37,54 @@ One screen to get fluent. Reticle is the **proof layer for AI agents** — no sc
|
|
|
31
37
|
| `{ kind: "element", role: "button", text: "Save" }` | `{ kind: "element", query: { role, text } }` |
|
|
32
38
|
| `{ kind: "route", url: "/checkout" }` | `{ kind: "route", contains: "/checkout" }` |
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
**New in 2.8.0, and it changes what some existing assertions mean.** An element predicate now CHECKS `value` and `text` instead of quietly folding them into the locator and ignoring them.
|
|
41
|
+
|
|
42
|
+
```jsonc
|
|
43
|
+
// Now a real assertion about the field's contents. Before 2.8.0 this passed
|
|
44
|
+
// whatever the input held, because `value` was read as a locator operand and,
|
|
45
|
+
// with no `by`, silently did nothing.
|
|
46
|
+
{ "kind": "element", "role": "textbox", "name": "GST amount", "value": "274.58" }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Two consequences worth knowing before you write your next predicate:
|
|
50
|
+
|
|
51
|
+
- **You can now assert what a field contains.** That was not possible before; agents worked around it by reading the value out of band with `reticle_query` and comparing in prose, which produces no verdict and therefore does not count as verification.
|
|
52
|
+
- **`{ role, text }` now checks the text.** It used to match on role alone, so it matched every button on the page. If an assertion you have used for months starts failing, that is the likely reason, and the failure is the truth arriving late.
|
|
53
|
+
|
|
54
|
+
Fields that nothing can check are refused rather than ignored: `by` without a `value`, and `label`, `placeholder`, `testid`, `alt` or `component` when a higher-precedence field already selected the element. An element query is a first-match dispatch, not a conjunction.
|
|
55
|
+
|
|
56
|
+
**Combinators take `predicates`, not a bare array.** This is the shape most often got wrong, and it is the one that produces no verdict at all:
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
// WRONG: neither of these parses
|
|
60
|
+
{ "allOf": [ … ] }
|
|
61
|
+
{ "kind": "allOf", "allOf": [ … ] }
|
|
62
|
+
|
|
63
|
+
// RIGHT
|
|
64
|
+
{ "kind": "allOf", "predicates": [ … ] }
|
|
65
|
+
{ "kind": "anyOf", "predicates": [ … ] }
|
|
66
|
+
{ "kind": "not", "predicate": { … } }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Each child reports its own evidence, in order:
|
|
35
70
|
|
|
36
|
-
|
|
71
|
+
```jsonc
|
|
72
|
+
{
|
|
73
|
+
"kind": "allOf",
|
|
74
|
+
"predicates": [
|
|
75
|
+
{ "kind": "signal", "name": "auth:granted" },
|
|
76
|
+
{ "kind": "net", "method": "POST", "urlContains": "/api/login", "count": 1 },
|
|
77
|
+
{ "kind": "console", "level": "error", "absent": true },
|
|
78
|
+
],
|
|
79
|
+
}
|
|
80
|
+
// -> evidence: [ { name: "auth:granted", … }, { matched: 1 }, { absent: true } ]
|
|
81
|
+
```
|
|
37
82
|
|
|
38
|
-
|
|
83
|
+
If a predicate is still rejected, the error names the fields **that kind** accepts. Read it rather than guessing again, and note `state` spells its selector `path` while `route` spells its `pathname`.
|
|
84
|
+
|
|
85
|
+
**Assert a consequence, not just presence.** `{ signal }` / `{ net }` prove the feature actually did something; `{ element }` / `{ text }` only prove something is on screen, which a stale render or a locator healed to the wrong element can fake. A _passing_ presence-only `reticle_assert` returns `advice` nudging you to a consequence; heed it on anything that matters.
|
|
86
|
+
|
|
87
|
+
## The 4-layer cross-check: never trust a green the state contradicts
|
|
39
88
|
|
|
40
89
|
A claim is real only when the layers agree. Check more than the UI:
|
|
41
90
|
|
|
@@ -48,50 +97,67 @@ A claim is real only when the layers agree. Check more than the UI:
|
|
|
48
97
|
|
|
49
98
|
> **Rule:** a passing UI assert that the store, network, or signal contradicts is a **false green**.
|
|
50
99
|
|
|
51
|
-
**Session health is universal.** Every live-session tool result carries a `session` block (`throttled`, `focused`, `lastSeenMs`); when `throttled:true` it also adds a `warning` + `recommendation` (refocus, or `reticle drive`). A throttled/backgrounded tab can silently no-op timers/rAF/pointer gestures
|
|
100
|
+
**Session health is universal.** Every live-session tool result carries a `session` block (`throttled`, `focused`, `lastSeenMs`); when `throttled:true` it also adds a `warning` + `recommendation` (refocus, or `reticle drive`). A throttled/backgrounded tab can silently no-op timers/rAF/pointer gestures. If you see `session.throttled`, distrust a green and refocus first.
|
|
52
101
|
|
|
53
102
|
> Store reads (`reticle_state`) are the reliable path; the DOM can lie (optimistic UI, stale render).
|
|
54
103
|
|
|
55
|
-
**Truncation and coverage are declared, never silent.** A big `reticle_state` read carries `truncation` when the transport caps dropped items
|
|
104
|
+
**Truncation and coverage are declared, never silent.** A big `reticle_state` read carries `truncation` when the transport caps dropped items; its presence means "this is NOT the whole value", so an absence assertion over a truncated read proves nothing; scope with `path`/`depth` instead. A `reticle_assert` verdict carries `coverage` when part of the page was unobservable (cross-origin iframe, closed shadow root); a green then means "nothing failed in the part I could see", not "the page is correct". Both fields are **omitted when everything was fine**, so their presence is the warning.
|
|
56
105
|
|
|
57
|
-
**Charts report their own geometry faults.** Any element descriptor containing a broken plot carries `chart: [{ kind, tag, attr, sample }]
|
|
106
|
+
**Charts report their own geometry faults.** Any element descriptor containing a broken plot carries `chart: [{ kind, tag, attr, sample }]`, one of `non-finite-coordinates` (a zero-range scale divided by zero; always a bug), `empty-geometry` (mounted but no data reached it), `degenerate-geometry` (every point identical). No extra call and no flag: query the chart as you would anyway. A healthy chart adds nothing. This matters because a chart is the one widget whose correctness is _geometry_: the store can be right while the polyline is blank, and neither a state read nor a screenshot catches it. Canvas charts are pixels, not DOM: read their data with `canvasChartData(canvasEl, window)` instead.
|
|
58
107
|
|
|
59
108
|
**Reads never go silently empty.** A zero-result read returns a `hint`, not a bare `[]`: `reticle_query` → `{ route, presentTestids, knownEmptyState }`; `reticle_network` → `{ totalInWindow, present[] }` (what DID fire); `reticle_console` → `{ totalInWindow, byLevel }` (so "0 errors" ≠ "silent page"); `reticle_state` lists `storeNames` when a store isn't found. Read the hint before assuming "not there." Scope big stores with `reticle_state({ store, path:"a.b.0", depth })` instead of paying for the whole tree; a wrong `path` returns `{ found:false, availableKeys }` so it's self-correcting.
|
|
60
109
|
|
|
61
110
|
## Core tool set
|
|
62
111
|
|
|
63
|
-
The tools advertised DIRECTLY
|
|
112
|
+
The tools advertised DIRECTLY, i.e. what you'll use 90% of the time. Everything else is one `reticle_run` away (see Token note below).
|
|
64
113
|
|
|
65
114
|
`reticle_sessions` · `reticle_navigate` · `reticle_snapshot` · `reticle_query` · `reticle_act` · `reticle_act_sequence` · `reticle_act_and_wait` · `reticle_observe` · `reticle_network` · `reticle_console` · `reticle_wait_for` · `reticle_assert` · `reticle_state` · `reticle_inspect` (DOM node → `src/App.tsx:104`) · `reticle_feedback` (tell the maintainers what is missing) · `reticle_session` (hand back: `{action:"yield"}` the moment you stop driving, `{action:"resume"}` after a human pause).
|
|
66
115
|
|
|
67
|
-
Frequently useful but NOT core, so reach them through `reticle_run({ tool, args })`: `
|
|
116
|
+
Frequently useful but NOT core, so reach them through `reticle_run({ tool, args })`: `reticle_capabilities` (the app's whole testable surface in one call; `{fromDisk:true}` needs no browser), `reticle_domain` (learn the app + gaps), `reticle_baseline {action:"diff"}`, `reticle_project` (run history).
|
|
68
117
|
|
|
69
|
-
**Reach past core when…** you need to record/replay a journey (`reticle_record {action:"start"}/stop`, `reticle_replay`), persist a self-healing golden flow (`reticle_flow_save*` / `reticle_flow_replay` / `reticle_flow_heal`), compile annotations (`reticle_annotate`), explore autonomously (`reticle_explore` lists controls; `reticle_crawl` clicks them all and reports anomalies
|
|
118
|
+
**Reach past core when…** you need to record/replay a journey (`reticle_record {action:"start"}/stop`, `reticle_replay`), persist a self-healing golden flow (`reticle_flow_save*` / `reticle_flow_replay` / `reticle_flow_heal`), compile annotations (`reticle_annotate`), explore autonomously (`reticle_explore` lists controls; `reticle_crawl` clicks them all and reports anomalies, and is **destructive**), reveal a virtualized off-screen row (`reticle_scroll_to`, for when `reticle_query` finds nothing because a windowed list hasn't rendered it yet), visual-check (`reticle_screenshot` / `reticle_visual_diff`, pinned with `reticle_viewport` for reproducible baselines), test error/edge states by stubbing the network (`reticle_network_mock`: 500 / offline / delay, driven mode), control time for toasts/debounces/auto-dismiss (`reticle_clock { freeze | advanceMs | reset }`), or work with a human (`reticle_session {action:"end"}` / `reticle_session {action:"resume"}` / `reticle_session {action:"messages"}`, and **`reticle_session {action:"review"}`** to drain + fix the bugs the human flagged from the panel).
|
|
70
119
|
|
|
71
120
|
## flows vs baselines vs project.json (the persistence layers)
|
|
72
121
|
|
|
73
122
|
| Artifact | Tool(s) | What it is |
|
|
74
123
|
| --- | --- | --- |
|
|
75
|
-
| **flows** | `reticle_flow_save*` / `reticle_flow_replay` / `reticle_flow_heal` | Replayable **golden journeys**, anchored to testids/signals
|
|
124
|
+
| **flows** | `reticle_flow_save*` / `reticle_flow_replay` / `reticle_flow_heal` | Replayable **golden journeys**, anchored to testids/signals; drift is legible and self-heals. |
|
|
76
125
|
| **baselines** | `reticle_baseline {action:"save"}` / `reticle_baseline {action:"diff"}` | Structural **"before" snapshots**; `reticle_baseline {action:"diff"}` flags regressions against them. |
|
|
77
|
-
| **project.json** | `reticle_project` | Cross-run **run-history
|
|
126
|
+
| **project.json** | `reticle_project` | Cross-run **run-history**: "did it behave like last run?" read via `reticle_project`. |
|
|
78
127
|
|
|
79
128
|
> `reticle_project` / `project.json` are the **run-history layer**. flows answer "does the journey still work?"; baselines answer "did the structure change?"; project.json answers "is this run consistent with prior runs?".
|
|
80
129
|
|
|
81
|
-
**Visual layer (opt-in).** `reticle_screenshot` saves a PNG baseline to `.reticle/visual/<name>.png`; `reticle_visual_diff` perceptually compares the live page to it (`{ masks }` to ignore volatile regions, `{ maxRatio }` tolerance) → `{ matched, changedPixels, ratio, region, diffPath }`. It answers "does it **look** right"
|
|
130
|
+
**Visual layer (opt-in).** `reticle_screenshot` saves a PNG baseline to `.reticle/visual/<name>.png`; `reticle_visual_diff` perceptually compares the live page to it (`{ masks }` to ignore volatile regions, `{ maxRatio }` tolerance) → `{ matched, changedPixels, ratio, region, diffPath }`. It answers "does it **look** right", complementary to the behavioral layers, never a replacement. Both need a **driven browser** (`reticle drive <url>` / `RETICLE_CDP_URL`); without one they return `{ ok:false, reason:"no-visual-provider" }` (the always-on SDK ships no screenshotter).
|
|
131
|
+
|
|
132
|
+
## Fields worth reading that you may not know are there
|
|
133
|
+
|
|
134
|
+
Recent additions, each of which answers a question agents were previously asking a second call to resolve:
|
|
135
|
+
|
|
136
|
+
| Field | On | What it tells you |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `expiresInMs` | `reticle_lease { action: "acquire" }` | How long the lease lives if untouched, reset by every call that targets it. Plan a pass to finish inside it, or re-acquire deliberately, rather than losing a measurement to a silent expiry. |
|
|
139
|
+
| `scroll` | `reticle_inspect` | `scrollTop`, `scrollHeight`, `clientHeight`, `overflowY`. Whether the element scrolls, which you cannot infer from geometry alone. |
|
|
140
|
+
| `timeline_omitted` | `reticle_record { action: "stop" }` | The raw event timeline is not in the response. It says how many events there were and names the call that returns them, with the cursor filled in. |
|
|
141
|
+
| `elided` | `reticle_act_and_wait` | Some diff arrays were capped. The count is real even when the list is trimmed, so a small array does not mean a quiet app. |
|
|
142
|
+
| `colorTokens`, `themeScope` | `reticle_inspect` | Every design token matching a colour, not one arbitrary winner, and which theme the reading was taken under. The singular `colorToken` is `null` when several tokens share a colour, because naming one of them was the defect. |
|
|
143
|
+
| `why` | `reticle_sessions`, when the list is empty | Why nothing is connected, and the next action. An empty list is never the end of the road. |
|
|
144
|
+
|
|
145
|
+
**When a verdict comes back `unsettled`,** it now names what it was waiting for and what the window actually held. Read those before retrying: an `unknown` that explains itself is a retry with a better `until`, and one that does not is a dead end.
|
|
146
|
+
|
|
147
|
+
**If the port is taken,** `reticle kill` frees it and leaves your own MCP proxy alone. Do not reach for `lsof -i :4400` and kill what it lists; that matches every process on the port, including the proxy you are talking through.
|
|
82
148
|
|
|
83
149
|
## Start here
|
|
84
150
|
|
|
85
|
-
0. Just ran `reticle init` / started the dev server? Poll `reticle_sessions()` until your tab appears
|
|
86
|
-
1. `reticle_sessions`
|
|
87
|
-
2. `reticle_domain`
|
|
151
|
+
0. Just ran `reticle init` / started the dev server? Poll `reticle_sessions()` until your tab appears. Readiness is server-internal now, so the first live call already blocks until the SDK connects.
|
|
152
|
+
1. `reticle_sessions` finds the connected tab (omit `sessionId` if there's only one). **An empty list is not a dead end: read the `why` field.** It names which case this is (no app running, an app running that has never dialled this daemon, a project that never went through `init`, or a tab that closed) and the fix for each. Do not fall back to static reasoning until you have read it.
|
|
153
|
+
2. `reticle_domain` learns the app BEFORE testing: the saved flows, what each asserts, and the **gaps** (declared signals/testids that no flow verifies, i.e. untested intent). Tells you what to test and where the real risk is without crawling the whole app. Falls back to `reticle_capabilities` for the raw testable surface (`testids`, `signals`, `stores`, `flows`).
|
|
88
154
|
3. Run the loop: **look → act → observe → assert**, cross-checking the 4 layers on anything that matters.
|
|
89
155
|
|
|
90
156
|
## Token note
|
|
91
157
|
|
|
92
158
|
- **Keep observation cheap.** Prefer `reticle_query` / scoped or `interactive` `reticle_snapshot` / `reticle_assert` over dumping the full tree. A full verify loop is ~100 tokens; see [token-efficiency.md](token-efficiency.md) (~73× leaner than full-tree snapshots).
|
|
93
|
-
- **Re-look with `reticle_snapshot({ diff:true })`** after an action
|
|
94
|
-
- **Cap broad reads.** `reticle_query` takes `limit` (caps descriptors; reports `total`/`truncated`) and `count_only` (just the match count). `reticle_network` / `reticle_console` take `limit` (most-recent-N, reports `droppedOldest`) and carry the same `cost` hint
|
|
95
|
-
- **A saved flow tells you if it's a real test.** `reticle_flow_save` returns `assertions.grade` (`asserted` / `presence-only` / `assertion-free`); if it's not `asserted`, add a consequence (`reticle_annotate` assert-signal/assert-net or a success-state) so it can't pass while broken. On replay, an ambiguous heal (two testids tie) is surfaced, never auto-applied
|
|
96
|
-
- **Predicate schema is not bloated.** The recursive predicate DSL used by `reticle_assert` / `reticle_wait_for` / `reticle_act_and_wait` is **factored, not inlined**: when converted to the JSON Schema MCP sends, the predicate body is emitted **once** (~2.7k chars ≈ **~685 tokens** per tool) and recursion is handled by self-`$ref` (`#/properties/predicate`)
|
|
97
|
-
- **One tool surface.** Reticle advertises the core set directly (sessions/navigate/snapshot/query/act/act_and_wait/observe/network/console/wait_for/assert/state/inspect/feedback/session
|
|
159
|
+
- **Re-look with `reticle_snapshot({ diff:true })`** after an action; it returns only what changed (`mode:delta`/`unchanged`), ~99% fewer tokens than a full re-snapshot and no stale tree to mis-read. Every snapshot/query result carries `cost:{ bytes, tokens }`, so re-scope before reading if it's large.
|
|
160
|
+
- **Cap broad reads.** `reticle_query` takes `limit` (caps descriptors; reports `total`/`truncated`) and `count_only` (just the match count). `reticle_network` / `reticle_console` take `limit` (most-recent-N, reports `droppedOldest`) and carry the same `cost` hint, so a busy page or wide window never floods your context unnoticed.
|
|
161
|
+
- **A saved flow tells you if it's a real test.** `reticle_flow_save` returns `assertions.grade` (`asserted` / `presence-only` / `assertion-free`); if it's not `asserted`, add a consequence (`reticle_annotate` assert-signal/assert-net or a success-state) so it can't pass while broken. On replay, an ambiguous heal (two testids tie) is surfaced, never auto-applied. And an `apply` heal re-replays the rebound flow and **refuses to write** if the success consequence no longer fires (`status:consequence_broken`): it heals the locator, never the intent.
|
|
162
|
+
- **Predicate schema is not bloated.** The recursive predicate DSL used by `reticle_assert` / `reticle_wait_for` / `reticle_act_and_wait` is **factored, not inlined**: when converted to the JSON Schema MCP sends, the predicate body is emitted **once** (~2.7k chars ≈ **~685 tokens** per tool) and recursion is handled by self-`$ref` (`#/properties/predicate`), with no per-recursion duplication. No action needed.
|
|
163
|
+
- **One tool surface.** Reticle advertises the core set directly (sessions/navigate/snapshot/query/act/act_and_wait/observe/network/console/wait_for/assert/state/inspect/feedback/session: the whole detect loop, plus the file-pointer, the feedback channel and the handback) PLUS two meta-tools that keep every other tool one call away: `reticle_tools` (discover; no args lists every tool name + summary, `names:[…]` loads full params on demand) and `reticle_run({ tool, args })` (invoke any tool by name; a top-level `sessionId` is forwarded to the target, so you need not nest it in `args`). So to record/replay/verify a flow, call `reticle_run({ tool:"reticle_flow_verify", sessionId })` (or `reticle_tools` first to see params). There is nothing to pick. `RETICLE_ADVERTISE_ALL_TOOLS=1` (read by the daemon at startup, so restart it) advertises everything with output schemas: a verification switch for suites, not a way to run agents. **Sizes are deliberately not quoted here.** A count in prose goes stale, and has three times already. `reticle_tools` reports the live surface, and SKILL.md carries the one gated table.
|