> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reticle.sh/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Reticle is a dev-only, localhost-only verification layer for AI coding agents. It reads program truth (network, state, console, routing, animations, framework state) from inside a running web app and returns a deterministic verdict with evidence. It is not a screenshot tool and not a browser automation library.
> Only `reticle_act_and_wait` and `reticle_assert` produce a verdict. Every other tool moves or reads the app and proves nothing. A drive that ends without one of those two has no result, however many tools it used.
> A verdict of `verified: "unknown"` is not a pass. It means Reticle drove the app and could not tell what happened. Report it as unknown; never weaken a check to make it pass.
> Package names are scoped `@reticlehq/*` and the CLI is `reticle`. Install with `npx reticle init`. The complete tool surface is on the `/usage` page; `/agent-cheatsheet` is the one-screen version.

# Recipes

> Worked examples for the situations you are actually in, with the real response each one returned.

Each recipe is a situation, the call that verifies it, and what came back. Every response on this page was captured from a running app.

## "Did the login actually work?"

One call, three conditions. The signal fired, exactly one request went out, and nothing was logged.

```json theme={"dark"}
{
  "ref": "e5",
  "action": "click",
  "until": {
    "kind": "allOf",
    "predicates": [
      { "kind": "signal", "name": "auth:granted" },
      { "kind": "net", "method": "POST", "urlContains": "/api/login", "count": 1 },
      { "kind": "console", "level": "error", "absent": true }
    ]
  }
}
```

```json theme={"dark"}
{
  "verified": "yes",
  "because": "assertion held at signal grade over a clean capture with no channel disagreeing",
  "verdict": {
    "pass": true,
    "evidence": [
      { "name": "auth:granted", "data": { "email": "admin@reticle.dev" } },
      { "matched": 1 },
      { "absent": true }
    ]
  },
  "summary": {
    "stateDiffs": [{ "path": "auth", "from": null, "to": "{…}" }],
    "storageKeysChanged": ["reticle.bench.authToken", "reticle.bench.sessionId"]
  },
  "honesty": { "grade": "signal", "coverage": { "pct": 100, "partial": false } }
}
```

Each child predicate reports its own evidence, in order. `count: 1` is the part that catches double-submit, and it costs nothing to ask for.

## "Did navigating actually change the view?"

```json theme={"dark"}
{ "ref": "e17", "action": "click", "until": { "kind": "signal", "name": "nav:changed" } }
```

```json theme={"dark"}
{
  "verified": "yes",
  "verdict": {
    "pass": true,
    "evidence": { "name": "nav:changed", "data": { "view": "deployments" } }
  },
  "summary": {
    "stateDiffs": [{ "path": "view", "from": "overview", "to": "deployments" }],
    "route": "/deployments"
  }
}
```

The signal carries the destination in its payload, so one predicate proves both that navigation happened and that it went to the right place.

## "Did the modal open?" and the lesson in getting it wrong

Here is a real failure, kept because it teaches more than another pass.

```json theme={"dark"}
{
  "ref": "e23",
  "action": "click",
  "until": {
    "kind": "allOf",
    "predicates": [
      { "kind": "element", "query": { "role": "dialog" }, "state": "visible" },
      { "kind": "console", "level": "error", "absent": true }
    ]
  }
}
```

```json theme={"dark"}
{
  "verified": "no",
  "verdict": {
    "pass": false,
    "evidence": [
      {
        "pass": false,
        "expected": "an element matching {\"role\":\"dialog\"} in state 'visible'",
        "observed": "no matching element on the page",
        "evidence": { "presentTestids": ["deploy-table", "filter-search", "env-filter", "…"] }
      },
      { "pass": true, "evidence": { "absent": true } }
    ]
  },
  "summary": {
    "stateDiffs": [{ "path": "newDeployOpen", "from": false, "to": true }],
    "signals": ["modal:opened"]
  }
}
```

Read the `summary`. The modal **did** open. `newDeployOpen` went `false → true` and the app fired `modal:opened`.

The assertion was wrong, not the app. That modal is a `div` with no `role="dialog"`, so a role query could never match it. (Which is also an accessibility bug worth fixing, found for free.)

The right predicate was sitting in the response the whole time:

```json theme={"dark"}
{ "until": { "kind": "signal", "name": "modal:opened" } }
```

<Tip>
  When an assertion fails, read `summary.signals` and `summary.stateDiffs` before you assume the
  feature is broken. They tell you what actually happened, and usually hand you the predicate you
  should have written.
</Tip>

## "Nothing matched, and I do not know why"

An empty `reticle_query` result tells you what *is* there:

```json theme={"dark"}
{
  "count": 0,
  "elements": [],
  "hint": {
    "route": "/",
    "knownEmptyState": true,
    "presentTestids": ["nav-overview", "nav-deployments", "kpi-deploys", "…"]
  }
}
```

In this case the testid existed, on another route. The hint saved a snapshot and a guess.

## "Is this button destructive?"

Reticle refuses controls that look destructive, before acting:

```json theme={"dark"}
{
  "error": "potentially destructive action blocked; retry with args.confirmDangerous=true",
  "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."
}
```

Confirm it explicitly when you mean it:

```json theme={"dark"}
{ "ref": "e23", "action": "click", "args": { "confirmDangerous": true }, "until": { … } }
```

<Note>
  The matcher is conservative and will occasionally stop something harmless. A button labelled "New
  deploy" trips it. That is the trade: a false stop costs you one argument, and a false start costs
  you a deleted record.
</Note>

## "Did my change break anything else?"

```json theme={"dark"}
{ "tool": "reticle_verify_change", "args": { "since": "HEAD~1" } }
```

Give it the files you edited, or a git ref. It works out which saved flows cover them and replays only those.

## "What is even testable in this app?"

The best first call on an unfamiliar codebase:

```json theme={"dark"}
{ "tool": "reticle_capabilities" }
```

```json theme={"dark"}
{
  "testids": ["login-email", "login-submit", "new-deploy", "deploy-submit", "…"],
  "signals": ["auth:granted", "auth:denied", "deploy:created", "modal:opened", "…"],
  "stores": ["app"],
  "flows": [
    {
      "name": "ship-a-deploy",
      "steps": ["nav-deployments", "new-deploy", "deploy-name", "deploy-submit"]
    }
  ],
  "source": "live"
}
```

That is the app stating what it considers testable, which beats snapshotting the DOM and inferring it from element names.

## "The error state has never been tested"

Most error states have never run. Force one:

```json theme={"dark"}
{
  "tool": "reticle_network_mock",
  "args": { "mocks": [{ "urlContains": "/api/deploys", "status": 500 }] }
}
```

Then drive the flow and assert the error UI appears. Pass `clear: true` to turn mocking off.

<Warning>
  This one needs a **Reticle-driven browser**, because mocks are applied through CDP and the always-on
  SDK cannot do that. A pooled lease is **not** enough. Verified: `reticle_lease` still returns
  `{ "ok": false, "reason": "no-cdp-provider" }`.

  Your route is `RETICLE_CDP_URL` pointed at a Chrome started with `--remote-debugging-port`. The same applies to `reticle_screenshot`, `reticle_visual_diff` and `reticle_viewport`.
</Warning>

## "I want this to run on every PR"

Record it once, replay it forever:

```json theme={"dark"}
{ "tool": "reticle_flow_verify" }
```

Replays every saved flow and returns one consolidated verdict.

<CardGroup cols={2}>
  <Card title="The predicate grammar" icon="filter" href="/predicates">
    Every kind, every field, and which ones actually prove something.
  </Card>

  <Card title="Best practices" icon="star" href="/best-practices">
    The habits behind these recipes, and the mistakes that produce a confident wrong pass.
  </Card>
</CardGroup>
