acceptance-criteria-authoring

verified

371fd8e4-09e4-401b-a94d-5df291f86a4d

Write unambiguous, testable acceptance criteria (given/when/then) so "done" is checkable by a machine, not a vibe. Use when defining what "complete" means for any task.

Metadata

Skill ID
371fd8e4-09e4-401b-a94d-5df291f86a4d
Version
1
Owner
387274b7-2891-478b-81b8-e11d5adb9319
Tags
acceptance-criteriadefinition-of-donebddrequirementstestable
Signature
verified
Integrity
OK
Content hash
1e9b287a7acbcb1fcc5b44adaac841574eb336f3af1e4ff5f41faef208572a51
Created
2026-08-15T05:24:21Z

Skill file

Raw skill file (markdown source)
# Acceptance Criteria Authoring

Use when defining what "done" means for a task, story, or feature. Well-written
acceptance criteria turn "it feels done" into "this command passes, so it is done."

## 1. The Given/When/Then template

Every criterion uses this structure — no exceptions:

```text
Given <precondition>
When  <action>
Then  <observable result>
```

Worked example:

```text
Given an admin user is authenticated
When  they call DELETE /users/{id} with a valid, existing user id
Then  the user is removed from the database, their data is cascade-deleted,
      HTTP 204 is returned, and an audit log entry is created.
```

Anti-examples (NOT criteria — uncheckable):

| Bad criterion | Why it fails |
|---|---|
| "The system works correctly." | Not observable; not specific. |
| "It should be fast." | Not measurable; no threshold. |
| "Users will like it." | Requires human judgment. |
| "The endpoint is implemented." | Repeats the task, does not define success. |

## 2. Mapping each criterion to an automated check

Every acceptance criterion must have a machine check. Write the check next to each
criterion; if you cannot, the criterion is not concrete enough.

| Criterion (Given/When/Then) | Automated check |
|---|---|
| Given valid input, When processed, Then 200 + JSON matches schema | `pytest -k test_schema` |
| Given invalid input, When processed, Then 400 + error code `INVALID_INPUT` | `curl -X POST ... -d bad && assert response.code == 400` |
| Given duplicate user, When created, Then 409 + message "already exists" | `pytest -k test_duplicate` |
| Given 50 concurrent requests, When processed, Then all return within 2s | `wrk -c50 -d5s ...` or `pytest -k test_concurrency` |

The check can be a `pytest` invocation, a `curl` + shell assertion, a `sql` query,
or a load-test command. What matters: it runs, it returns pass/fail, and it ties
directly to the criterion.

## 3. Boundary criteria: cover more than the happy path

For every feature, write at least these categories:

| Category | Example |
|---|---|
| **Happy path** | Valid input → expected success response |
| **Missing/empty** | Null, empty string, missing field → validation error |
| **Malformed** | Wrong type, over-length, bad encoding → error |
| **Large input** | Max-size payload, boundary values → handled or rejected |
| **Permission** | Wrong role / no auth → 401/403 |
| **Concurrency** | Simultaneous identical requests → one succeeds, other gets conflict |
| **Not found** | Reference to nonexistent resource → 404 |

Not every feature needs every category, but a feature with only the happy path
criterion is **under-specified**.

## 4. The completeness test

Apply this to a set of criteria:

1. Can you run a test/command that definitively says "this criterion passed"?
2. Do the criteria collectively cover at least one happy path and one failure case?
3. Would a new teammate reading only the criteria know when to stop coding?

If "no" to any, add criteria until "yes".

## 5. Acceptance criteria for non-UI work

Given/When/Then works for backend, data, and infra too — just replace "user action"
with "operation":

| Domain | Example criterion |
|---|---|
| Backend API | Given a valid auth header, When POST /orders is called, Then 201 and the order id is in the Location header |
| Data pipeline | Given 1000 input rows, When the job runs, Then 1000 output rows, 0 dropped, and duplicates deduped |
| Migration | Given the old schema, When `alembic upgrade head` runs, Then the new column exists and old data is preserved |
| Infra/config | Given a deploy, When GET /healthz is hit, Then 200 within 5s of startup |
| CLI tool | Given `--verbose`, When the command runs, Then stderr includes per-step timing |

The constant across domains: the "Then" names an observable, machine-checkable
result, never a feeling.

## 6. Reviewing someone else's criteria

When handed criteria to review, run these four checks:

1. **Unambiguous?** Could two people disagree on whether it passed?
2. **Checkable?** Is there a command/test that returns pass/fail?
3. **Complete?** Does it cover failure, empty, and large inputs — not just the happy path?
4. **Minimal?** Are there criteria that repeat, or that are actually non-goals?

Reject criteria that fail #1 or #2 outright; request more on #3; trim on #4.

## Guardrails

- Do **not** write criteria that require human judgment ("looks good", "is
  intuitive"). Machine-checkable only.
- Do **not** write criteria that are just the task title rephrased ("the feature
  works" is noise).
- Do **not** skip the failure cases — a feature without an error criterion has an
  undefined error contract.
- Do write criteria *before* code so they can guide implementation, not after as
  a retroactive checkbox exercise.

## Pitfalls

- **"Works correctly"** — the most common acceptance-criteria anti-pattern. It says
  nothing and checks nothing.
- **Untestable criteria** — "the user experience is smooth" cannot be automated.
- **Happy-path-only** — ignoring failure cases means the implementation is undefined
  when things go wrong.
- **Criteria without a check** — a list of criteria with no verify command per item
  is still a vibe.
- **Over-specification** — 30 criteria for a 10-line script is ceremony, not rigor.

## Verify / Checklist

- [ ] Every criterion is written in Given/When/Then format.
- [ ] Every criterion has an explicit automated check (command, test, script).
- [ ] The set includes at least one happy-path and at least one failure/edge criterion.
- [ ] No criterion relies on human judgment.
- [ ] A new engineer reading only the criteria would know when the task is done.
- [ ] Criteria are written and reviewed *before* implementation begins.

Attached files

No attached files.