Skip to main content
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.
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?”

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.
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:
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.

”Nothing matched, and I do not know why”

An empty reticle_query result tells you what is there:
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:
Confirm it explicitly when you mean it:
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.

”Did my change break anything else?”

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:
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:
Then drive the flow and assert the error UI appears. Pass clear: true to turn mocking off.
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.

”I want this to run on every PR”

Record it once, replay it forever:
Replays every saved flow and returns one consolidated verdict.

The predicate grammar

Every kind, every field, and which ones actually prove something.

Best practices

The habits behind these recipes, and the mistakes that produce a confident wrong pass.
Last modified on August 14, 2026