practice · stories & scope
Story writing
A story is one moment in one named person's activity, deliverable in 1–3 days, with at least three testable acceptance criteria — one of them negative. The form is what makes the story interpretable across the trio without further conversation.
TL;DR
A story has five sections: story sentence (as–I want–so that), journey reference (J-number), states to handle (empty / loading / success / error / edges), 4–7 testable acceptance criteria with at least one negative, and out-of-scope. The story passes the 9-point Definition of Ready before it is pullable. If any of the nine fails, the story goes back to amigos, not into the sprint.
What it is
A story is the smallest unit of work the chain can move end-to-end. It is named in What We Shape · Story Writing and made ready through amigos. A story carries enough constraint that a developer and a QA can both pick it up without further conversation, and enough room that the developer chooses the implementation.
Distinguish from
Feature Brief — many stories per brief. Epic — a coherent set of stories that ship a journey-level change. Task — sub-story granularity; sub-tasks are a developer concern. See Confusable with at the foot.
Why it matters
Without the story discipline:
- States ship late — empty/error/loading states emerge in QA, not at scope. Cost compounds.
- Negative cases are not surfaced — the trio never confronts what happens when the input is bad.
- Sizing breaks — stories that "feel small" turn out to be epics in disguise mid-sprint.
- Amigos has nothing to attack — the story is too vague for the trio to surface anti-flows.
The 9-point DoR is the corpus's discipline against the "we'll figure it out in code" pattern.
How to do it
Step 1 — Write the story sentence with a named person
As Gal, an exam grader at our customer's flagship campus, I
want the LMS to display Hebrew names correctly without
re-typing, so that I can grade without breaking my flow.The role description after the name carries the context the developer needs. Gal at the flagship campus is different from Gal internal QA. Never as a user. If you cannot name the person, the story is not ready — the Feature Brief is unfinished.
Step 2 — Reference the journey step
Journey: J6 — Hebrew name editing workaround during gradingThe J-number anchors the story to the journey map. A story without a J-reference may be a real story; it is not yet a story the brief committed to.
Step 3 — Name the states explicitly
States to handle:
- Empty: no submissions in the grader's queue
- Loading: queue is loading (slow network, cold cache)
- Success: Hebrew name renders inline; copy-paste works
- Error: name contains unsupported unicode form
- Edge: hyphenated name overflows the columnThe states section is the section most teams under-use. Every interactive moment has these four states plus the moment-specific edges. If you skip them at story-writing, you ship them at QA — at higher cost.
Step 4 — Write 4–7 acceptance criteria, at least one negative
Each AC is testable. Given/When/Then form.
AC1 — Given a submission with a Hebrew name including hyphens,
when Gal opens the queue, then the name renders inline
with no encoding warnings in the application log.
AC2 — Given a submission with a name containing a unicode form
not in the supported set, when Gal opens it, then the name
renders with the fallback character AND Gal can still
submit the grade.
AC3 (negative) — Given an unauthenticated session, when the
grader endpoint is called, then the response is 401 and
no name data is returned in the body.
AC4 — Given a Hebrew name, when Gal copies-and-pastes the name
into the feedback field, then the pasted text retains
diacritics correctly.The negative case is the discipline. AC3 tests what happens when the input is wrong. Stories without negatives ship features that break the first time a user does something unexpected.
Step 5 — Out of scope (with rationale)
Out of scope (this story):
- Right-to-left layout for non-name fields.
Reason: not on this J-step; tracked in J7 story.
- Name normalisation in legacy submissions.
Reason: backfill story exists separately.Stories without an out-of-scope leak. The discipline is the same as Feature Briefs.
Step 6 — Run the 9-point Definition of Ready
Walk the DoR checklist. If any of the nine fails, the story is not pullable.
A complete story
Story: Hebrew name rendering on grader queue
As Gal, an exam grader at our customer's flagship campus, I
want the LMS to display Hebrew names correctly without
re-typing, so that I can grade without breaking my flow.
Journey: J6 — Hebrew name editing workaround during grading.
States to handle:
- Empty: no submissions in queue
- Loading: cold cache / slow network
- Success: Hebrew name renders inline with diacritics
- Error: unicode form not in supported set
- Edge: hyphenated names overflowing the column
Acceptance criteria:
1. Hebrew names with hyphens render inline, no encoding
warnings in logs.
2. Unicode form not in supported set renders with fallback
and grade can still be submitted.
3. (negative) Unauthenticated session returns 401, no name
data in response.
4. Copy-paste of name into feedback retains diacritics.
Out of scope (this story):
- RTL layout for non-name fields (tracked in J7).
- Legacy submission backfill (separate story).
DoR checklist:
1. Story format ✅
2. Journey reference J6 ✅
3. ≥3 ACs incl. negative ✅
4. Figma frame V2-J6 ✅
5. Copy defined ✅
6. Event: name.normalized ✅
7. Dependencies: none ✅
8. Sized 2 days ✅
9. Tech feasibility ✅Evidence
Across our cycles, stories that survived contact with reality shared three properties.
- States were named at scope, not at QA. Stories whose states section was filled at amigos shipped with state-defect bugs 4× less often than stories whose states emerged during code review.
- At least one negative AC was non-trivial. Stories where the negative case tested an unhappy path (not just "input rejected") caught Discovery-level defects in 1 of 4 cycles before code began.
- The story was sized at 1–3 days. Stories sized "small / medium / large" without days slipped 60% of the time; stories with a developer-signed day estimate slipped 25%.
Anti-patterns
| Pattern | What it looks like | Where to fix |
|---|---|---|
| As a user | No named person | Clinic — A brief that didn't witness; fix the brief, not the story |
| No states section | Empty/loading/error left to "common sense" | Clinic — A story without a state |
| No negative AC | All ACs describe happy paths | Add at least one; if you can't, the trio hasn't held amigos honestly |
| Out-of-scope is empty | "We'll see what comes up" | Scope leaks. Name what is not changing. |
| DoR has yellows | Story pulled into sprint with ⚠ marks | The story is not ready; back to amigos |
| Story sized in "small/medium/large" | No day estimate | The TL has not sketched the work; story is not feasibility-confirmed |
Confusable with
| This | Not this | Difference |
|---|---|---|
| Story | Feature | Story = one moment, 1–3 days. Feature = an Epic's worth of stories. |
| Story | Task | Task is sub-story (a developer's plan). Stories are the chain's unit. |
| Acceptance criterion | Test case | An AC is what good looks like. A test case is how QA tests it. ACs precede test cases. |
| DoR | DoD | Ready = pullable. Done = shippable. |
Further reading
- Canon — What We Shape · Story Writing · Amigos & Gherkin
- Practice — Holding amigos
- Template — Story · Gherkin scenario set
- Checklist — Story · Definition of Ready · Amigos 45-minute agenda
- Clinic — A story without a state
- Skill path — PO foundations · Step 6 · Developer foundations · Step 4 · QA foundations · Step 4
- Reference — Area · Story Writing