# Goal tests in CI

> A pass or fail for every deploy, with exit codes CI can read.

`--goal` gives every prospect the same goal and turns the run into a pass or fail. The exit code tells CI whether your site stopped someone or the run itself broke.

## Run a goal test

One flag turns any run into a test.

```
leakdown your-site.com --goal "log in and get an API key" --steps 15 --yes --headless  3 prospect(s) queued, one at a time: cold, warm, hot | claude, headless
  [------------------------] 0/3 agents finished
  ...
  goal FAIL: 2/3 session(s) completed "log in and get an API key"

```

That run exits 1: one prospect did not get the key. `--steps` (1 to 50) caps each session. Everything else stays the same: same personas, same reports, same recordings.

## Exit codes

The exit code separates a broken site from a broken run.

| Code | Meaning | What to do |
|---|---|---|

| `0` | Every session completed the goal. | Ship. |
| `1` | A session walked out or hit a guardrail. The site failed someone. | Open the report. |
| `2` | Nothing failed, but a session could not run: unreachable URL, model down, setup error. | Check the runner, not the site. |

## Check values with --expect

Add `--expect "label=value"`, as many times as you need. A completion only counts when the page shows every value. The check is a plain text match that ignores whitespace, and the report's Assertions section quotes what it found.

```
leakdown your-site.com --goal "apply SAVE20" --expect "total=$96.00" --yes
```

```
Assertions
  expected total=$96.00, found 'Total: $120.00'
```

## In a CI job

With no terminal attached nothing is ever asked, so pass the brain, model and effort explicitly to keep runs reproducible.

```
name: signup
on: [deployment_status]
jobs:
  goal:
    if: github.event.deployment_status.state == 'success'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { repository: 0xSarnavo/leakdown-cli }
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci && npm run build && npx playwright install --with-deps chromium
      # log in your AI CLI here (see the note below)
      - run: >
          node dist/cli.js ${{ github.event.deployment_status.target_url }}
          --goal "sign up and get an API key" --steps 15
          --brain claude --model sonnet --yes --headless
```

The AI CLI needs a login on the runner

`ANTHROPIC_API_KEY` and `OPENAI_API_KEY` are passed through if set, but that path is untested. Automating a consumer subscription is between you and that provider's terms.

### Tips

- Point it at a preview or staging deploy, never production checkout.
- Treat exit 2 as a retry, not a failed build.
- Keep `runs/` as a build artifact so the video is there when a check fails.

---
Source: https://docs.leakdown.dev/goal-tests
