> ## 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/*`. Run every CLI command as `npx @reticlehq/server <command>`, for example `npx @reticlehq/server init`. `reticle` is a bin name that `@reticlehq/server` installs once it is on your PATH, NOT a package on npm: `npx reticle` fetches an unrelated package published by somebody else, so never run that. The complete tool surface is on the `/usage` page; `/agent-cheatsheet` is the one-screen version.

# reticle_act_and_wait

> Act on an element and wait for a named consequence in one call. This is the tool that produces a verdict, and the one you should reach for by default.

`reticle_act_and_wait` performs one action on an element and waits for a named consequence, returning a verdict in the same call. Reach for it whenever an action is supposed to cause something: it is one of only two Reticle tools that produce a verdict, the other being [`reticle_assert`](/tools/assert).

This is the tool Reticle exists for. It does the act, observe and assert steps in one round trip, and it makes you name the expected consequence **before** the action runs.

That ordering is not a convenience. An agent that acts first and then decides what counts as success will always find something that counts. Naming the consequence up front is the difference between a check and a rationalisation.

## Example

```json theme={"dark"}
{
  "ref": "e105",
  "action": "click",
  "until": { "kind": "net", "method": "POST" }
}
```

Real response. The `initiatorStack`, `storageDiffs` and per-event trace detail are trimmed out for length; nothing else is changed:

```json theme={"dark"}
{
  "verified": "yes",
  "verifiedReason": "proved",
  "because": "assertion held at presence grade over a clean capture with no channel disagreeing",
  "effect": {
    "ok": true,
    "ref": "e105",
    "action": "click",
    "dispatched": true,
    "settled": true,
    "settleReason": null,
    "testid": "login-submit",
    "component": "Login",
    "role": "button",
    "name": "Sign in",
    "effect": { "focusMoved": "e104->null", "domMutatedWithin": 8, "appeared": "Signing in…" },
    "source": { "file": "src/components/Login.tsx", "line": 81, "column": 8 }
  },
  "verdict": {
    "pass": true,
    "evidence": {
      "id": "n2",
      "method": "POST",
      "url": "http://localhost:8787/api/login",
      "status": 200,
      "ok": true,
      "durationMs": 4,
      "initiator": "fetch",
      "statusText": "OK",
      "contentType": "application/json; charset=utf-8",
      "responseSize": 67,
      "requestBody": "{\"email\":\"admin@reticle.dev\",\"password\":\"[REDACTED]\"}",
      "responseBody": "{\"token\":\"[REDACTED]\",\"user\":{\"email\":\"admin@reticle.dev\"}}"
    }
  },
  "trace": {
    "window_ms": 31,
    "summary": {
      "total": 21,
      "network": 1,
      "domAdded": 0,
      "domRemoved": 1,
      "domChanged": 6,
      "routeChanges": 0,
      "consoleErrors": 0,
      "animations": 0,
      "signals": 1
    }
  },
  "summary": {
    "net": { "total": 1, "errors": 0 },
    "consoleErrors": 0,
    "statePathsChanged": ["app"],
    "storageKeysChanged": ["reticle.bench.authToken", "reticle.bench.sessionId"],
    "stateDiffs": [
      { "path": "auth", "from": null, "to": "{\"email\":\"admin@reticle.dev\"}", "atMs": 44403 }
    ],
    "signals": ["auth:granted"],
    "layoutShift": 0.016486682891845704,
    "longTasks": 0
  },
  "honesty": {
    "grade": "presence",
    "attribution": "window",
    "coverage": { "pct": 100, "partial": false },
    "integrity": { "clean": true, "issues": [] }
  },
  "since": 44395
}
```

`trace` is a digest of what the app did in the window. When the counts are not enough, pass the top-level `since` cursor to [`reticle_observe`](/tools/observe) for the per-event timeline.

## The predicate grammar

`until` takes `{ kind, ...fields }`. The kinds:

| Kind                      | Asserts                                                        |
| ------------------------- | -------------------------------------------------------------- |
| `signal`                  | The app fired a named signal, the strongest evidence available |
| `state`                   | A store path reached a value                                   |
| `net`                     | A request matched; `count` asserts an **exact** number         |
| `route`                   | The route **changed**                                          |
| `element`                 | An element appeared; `absent: true` asserts it went away       |
| `text`                    | Text appeared or, with `absent`, disappeared                   |
| `console`                 | Something logged; `absent: true` asserts a clean console       |
| `animation`               | An animation ran or finished                                   |
| `settled`                 | The page went quiet                                            |
| `allOf` / `anyOf` / `not` | Combine the above                                              |

### Predicates that catch real bugs

```json theme={"dark"}
{ "until": { "kind": "net", "method": "POST", "count": 1 } }
```

Exactly one request. Double-submit fails this at two, and no screenshot will ever tell you.

```json theme={"dark"}
{ "until": { "kind": "console", "absent": true } }
```

The action completed **and** logged nothing. "It worked but threw a warning" stops passing.

```json theme={"dark"}
{ "until": { "kind": "signal", "name": "deploy:created" } }
```

The app itself declared success. This is the highest grade of evidence, and it requires [instrumenting your app](/instrumentation). Which is the main reason to bother.

## Reading `verified`

<CardGroup cols={3}>
  <Card title="yes" icon="circle-check">
    The named consequence happened, with evidence attached.
  </Card>

  <Card title="no" icon="circle-xmark">
    It did not. A finding, with a source pointer.
  </Card>

  <Card title="unknown" icon="circle-question">
    Reticle could not tell. **Not a pass.** Report it as unknown.
  </Card>
</CardGroup>

## The `honesty` block

`grade` is how strong the evidence was. A fired signal outranks an element appearing. `coverage.partial: true` means Reticle did not observe the whole window. `integrity.clean: false` means something interfered with the capture and the verdict deserves less trust.

A verification tool that cannot describe the quality of its own evidence is asking you to take its word for it, which is precisely the problem we started with.

## Arguments

| Argument                | What it does                                                                |
| ----------------------- | --------------------------------------------------------------------------- |
| `ref`, `action`, `args` | As [`reticle_act`](/tools/act)                                              |
| `until`                 | The predicate to wait for. Omit it to wait for the page to settle           |
| `predicate`             | Alias for `until`, the name `assert` and `wait_for` use                     |
| `timeout_ms`            | Maximum wait, defaulting to 4000. `0` evaluates the predicate once, no wait |
| `refuseWhenThrottled`   | Throw rather than act on a throttled tab                                    |

Omitting `until` waits for network and DOM idle, which is the deterministic replacement for a fixed sleep. To assert a consequence **and** settle, combine them:

```json theme={"dark"}
{
  "kind": "allOf",
  "predicates": [{ "kind": "signal", "name": "deploy:created" }, { "kind": "settled" }]
}
```
