A4.4 · From stories to a .stories.md · dive 3
INVEST and invariants
A story carries more than its sentence. Its INVEST line names the invariants it encodes and whether it is testable — the link from a story to the rule it must not break.
INVEST is six properties — Independent, Negotiable, Valuable, Estimable, Small, Testable — and on the line a story states which invariants it encodes, plus a Priority and a Size. Two parts matter for the spec contract: which invariants a story exercises, and whether it is testable. Pick a story on the right; the content figure reads an invariant back to the stories that exercise it.
A story's INVEST line · pick a story
What the INVEST line carries
Every story carries an INVEST line — the six properties (Independent, Negotiable,
Valuable, Estimable, Small, Testable) compressed to a short gloss, followed by a Priority, a Size, and the
deliverables it implements. The two parts that bind it to the spec are these: which invariants the
story encodes, and whether it is testable. An invariant is a property the increment
must never break; encodes is the story's claim that its acceptance exercises that
property.
A story that encodes no invariant and is not testable accepts nothing — it is a wish, not a check. Naming the invariant on the line is what ties the story back to the spec's Invariants section, so a reviewer can confirm that every invariant the rung declares is exercised by at least one testable story. That tie is what the next chapter, on invariants, makes its own subject; here it is read off the line.
- INVEST
- Independent, Negotiable, Valuable, Estimable, Small, Testable — the six properties of a good story.
- encodes
- The invariants a story's acceptance exercises, named on its INVEST line (e.g. US2 encodes F6.1-INV1).
- testable
- The story states how it is checked; a non-testable story accepts nothing.
- invariant
- A property the increment must never break — declared in the spec, exercised by a story that encodes it.
A story names the invariants it encodes; the spec declares those invariants. The two meet on the INVEST line — the line is where a story claims its part of the rung's correctness.
Read an invariant back to the stories that exercise it
The hero figure read from the story side — pick a story, read the invariants it encodes. The figure below reads the other way: pick an invariant and see which stories encode it. An invariant exercised by at least one testable story is pinned by a check; an invariant no story encodes is merely asserted, the kind of gate the course warns against. F6.1's master invariant, INV1, is encoded by US2 and US3 — so the rule “the web layer calls only the facade” is exercised twice.
This is the reverse audit. The Coverage line proved every deliverable has a story; this proves every invariant has a story too. The two figures teach different moves: the hero reads a story's INVEST line, this one reads an invariant back to the stories that pin it — the same encodes map, read from the invariant end.
An invariant, exercised by stories · pick one
Each story names the invariants it encodes; read an invariant back and the stories that pin it appear — an invariant no story encodes is merely asserted.
On the Portal — US2's INVEST line
On the Portal — the learning platform this course builds — the story
F6.1-US2, settled at F6.1 · Bootstrap the Phoenix PortalThe first web rung: stand the F5 engine up as a Phoenix app, with one facade-backed route and a liveness route.View the spec ladder →, carries the INVEST line below.
It encodes F6.1-INV1, the master invariant: PortalWeb calls only the Portal
facade and renders only the closed %Portal.Error{} set. Because US2 is testable
by rendered output for three cases, that invariant is pinned by an acceptance check, not merely asserted. The
markdown below carries US2's INVEST line verbatim.
# f6.1.stories.md — F6.1-US2's INVEST line (markdown, not code). # As a visitor, I want to open a course page for a given user… # The INVEST line — testability and the invariant it encodes: INVEST — valuable on its own (the first real page); testable by rendered output for the three cases; encodes F6.1-INV1. Priority: must · Size: 3 · Implements deliverables: F6.1-D3, F6.1-D4, F6.1-D5. # F6.1-INV1 (master): PortalWeb calls only the Portal facade and renders only the # closed %Portal.Error{} set — exercised here, so the rule is checked, not asserted.
Each story names the invariants it encodes and whether it is testable; an invariant encoded by no testable story is unexercised — a gate asserted rather than run.
F6.1-US2 encodes the master invariant INV1 and is testable by rendered output — so “the web layer calls only the facade” is pinned by an acceptance check.
The INVEST line is where a story claims its part of the rung's correctness — the invariants it encodes, pinned by the check that makes it testable.
Recap — the line ties a story to the rules
A story's INVEST line names the invariants it encodes and whether it is testable. Read from the story side, a story shows the rules it exercises; read from the invariant side, an invariant shows the stories that pin it. An invariant no testable story encodes is asserted, not checked — the gap this reverse audit surfaces. With deliverable→story, the Coverage line, and the INVEST line all read, the module's move is complete: a spec's deliverables become a covered stories file whose every invariant is exercised. The chapter turns next to invariants in their own right.
Back to A4.4 · From stories to a .stories.md to revisit the module, then on to A4.5 · Invariants — a property that must always hold, set apart from a check that holds for one scenario.
References
Sources for INVEST and the story's tie to the rules it must not break, and where this connects in the course.
Sources
- Wake, B. — INVEST in Good Stories — the six properties named on every story's INVEST line.
- Cohn, M. — User Stories Applied — the story and its acceptance, the testable face of a requirement.
- Adzic, G. — Specification by Example — examples that exercise the rules an increment must never break.
Related in this course
- A4.4 · From stories to a .stories.md — the module hub.
- A4.4.2 · The Coverage line — the previous dive.
- A4.4.1 · Deliverable to story — the map this completes.
- A2.03 · INVEST — the six properties of a good story.
- A4 · The spec layer — the chapter.
- F6 · The Portal on the web (Phoenix) — the real chapter these invariants govern.