Skip to main content
This guide builds a real scenario end-to-end. You’ll write a markdown file, run it with the CLI, interpret the satisfaction score, and wire it into CI. We’ll test a welcome-email flow against the Resend mirror. The same pattern works for any mirror.

What we’re testing

Imagine your application has a signup endpoint that sends a welcome email via Resend. A passing test needs to prove that:
  1. An email was actually created in Resend (not just that the SDK call returned).
  2. The from address matches the configured sender.
  3. The webhook for delivery confirmation arrived.
  4. The webhook signature was verified.
  5. The subject line is reasonable.
  6. Bounces are handled.
The first four are mechanical — you can count emails, check strings, count webhooks. The last two are subjective — “reasonable subject” and “handles bounces gracefully” aren’t something a test with expect(…).toBe(…) can verify cleanly. That’s exactly the check: vs judge: split.

1. Write the scenario

Create scenarios/welcome-email.md:
That’s the whole scenario. Every section is explained in the scenario format reference.

2. Run it

3. Read the score

86% means 18 of 21 criteria passes. Five check: criteria ran 3 times each and all passed — that’s deterministic, not a coincidence. One judge: criterion passed all 3 — the subject line is fine. One judge: criterion failed all 3 — bounce handling is missing. The 3/3 vs 0/3 pattern matters: if bounces are sometimes handled and sometimes not, the evaluator would show 1/3 or 2/3, and you’d know it’s flaky code. A clean 0/3 means it’s genuinely missing.

4. Fix the failing criterion

Add bounce handling to your webhook route:
Re-run:

5. Wire it into CI

GitHub Actions example:
--fail-below=0.9 exits the job non-zero if satisfaction drops below 90% — your PR fails CI, and the mirra-result.json artifact is attached for inspection.

6. Iterate

As your code changes, keep the scenario tight to what you actually promise users:
  • Add check: lines for new assertions you can mechanically verify.
  • Use judge: sparingly and only for genuinely subjective calls.
  • Increase runs: if you want tighter confidence; decrease if CI is slow.
  • Split one bloated scenario into several focused ones — welcome-email.md, bounce-handling.md, quota-exceeded.md — each gating what it gates.

Where to go next

Scenario format reference

Every valid section, every config key.

Coding agents + MCP

Let Claude Code or Cursor drive scenarios directly.

Vitest plugin

Drive scenarios from an existing Vitest suite.

mirra run reference

Every flag, every exit code, every output format.