SpecScore's acceptance-evidence layer

Run your specs. Prove your software does what its docs promise.

Rehearse turns Markdown scenarios into real, executable checks — bash, SQL, HTTP — that run the promises in your specification for real. No glue code. No mocks.

Pre-v1

Rehearse is in active development. Everything below is shipped and runs today (in the specscore-cli runtime). There is no stable release yet — expect changes, and don't build on it as if the format were frozen.

One login page. Three methods. Success and failure.

Your app has a login page. Users sign in three ways — email/password, Google, Facebook. Different flows, but after ANY successful sign-in the same things must be true: a hardened session cookie, a redirect to the dashboard. And each method must handle failure. How do you test that — for real — without copy-pasting the checks into every flow?

Rehearse answers that in four moves, and each move is a real feature you can run today.

A scenario is real commands. No glue, no mocks.

Start with email sign-in. Given/When/Then, but the steps are actual commands that run:

email-sign-in.md
# Rehearse: Email sign-in

## Given a registered user
```bash
echo 'email=ada@example.com&password=s3cr3t' > form.txt
```

## When the form is POSTed to the sign-in endpoint
```bash
printf 'HTTP/1.1 302 Found\r\nLocation: /dashboard\r\nSet-Cookie: session=abc; HttpOnly; Secure\r\n\r\n' > out.txt
```

## Then the response redirects
```bash
grep -q '302 Found' out.txt || exit 1
```

No step-definition layer, no mock server — the description is the test. (Real project: swap the printf for a real curl against the running app.)

Write the check once. Reuse it across every method.

The post-auth verification — "the session cookie is hardened" — is IDENTICAL for email, Google, and Facebook. So write it once, as a reusable check:

_checks/session-hardened.check.md
# Check: session-hardened
**Params:** response_file

```bash
grep -qi '^set-cookie: session=' {{response_file}} || { echo "no session cookie"; exit 1; }
grep -i  '^set-cookie: session=' {{response_file}} | grep -qi 'HttpOnly' || { echo "cookie not HttpOnly"; exit 1; }
```

Then invoke it from any scenario with one line — the SAME line in the email, Google, and Facebook flows:

email-sign-in.md, google-sign-in.md, facebook-sign-in.md — each reuses it
## Then the session is hardened
**Use:** [session-hardened](./_checks/session-hardened.check.md) with response_file=out.txt

Three sign-in methods, one check. Tighten the rule (also require Secure) and every method stays honest — you edit one file, not three. No copy-paste.

Branch success and failure from one shared setup.

Google sign-in can succeed or be denied. Both start from the same account. Express that as a nested suite — one ## Given, multiple ### When branches (describe/context/it):

google-sign-in.md
## Given a Google identity mapped to a user
```bash
echo 'sub=10432' > identity.txt
```

### When the OAuth callback succeeds
```bash
printf 'HTTP/1.1 302 Found\r\nLocation: /dashboard\r\nSet-Cookie: session=g0og; HttpOnly; Secure\r\n\r\n' > out.txt
```
#### Then the session is hardened
**Use:** [session-hardened](./_checks/session-hardened.check.md) with response_file=out.txt

### When the user denies consent
```bash
printf 'HTTP/1.1 302 Found\r\nLocation: /login?error=access_denied\r\n\r\n' > out.txt
```
#### Then no session is issued and the user returns to login
```bash
grep -qi '^set-cookie: session=' out.txt && exit 1
grep -qi '^Location: /login' out.txt || exit 1
```

That one file runs as two independent casesgoogle-sign-in.md › When the OAuth callback succeeds and … › When the user denies consent — each in its own sandbox, sharing the setup. The success branch even reuses the check from Act 2. (The success branch reuses the **Use:** check; the denial branch has its own outcome.)

The criteria are thin, and their summary is generated.

The things that must be true — "session hardened," "redirected to dashboard" — are thin acceptance criteria: one file each, intent only, no test machinery.

_acs/session-hardened.ac.md
# AC: session-hardened
**Status:** accepted

## Statement
After any successful sign-in, the session cookie is HttpOnly and Secure.

Run specscore rehearse acs spec/features/auth/login and it generates the feature's ## Acceptance Criteria summary table from the _acs/ files — every criterion's intent readable in one glance (a person skims it; an agent reads it in one shot, no per-file lookups), while each .ac.md stays the single source of truth.

One login page, three methods, success and failure — and the shared verification is written once, the branches read like behaviour, the criteria are one glance away, and every line runs for real. That's Rehearse.

Rehearse is one layer. See the whole SpecScore artifact tree behind this login example — from the first Idea to the running proof: Explained by example: a login feature →