jonnifyagile agents
jonnify / Agile Agent Workflow / A4 · The spec layer / A4.4 / A4.4.3 · INVEST and invariants

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

F6.1 stories · each names the invariants it encodes US1 encodes INV2, INV3 · must US2 encodes INV1 (master) · must US3 encodes INV1, INV2 · must US4 encodes INV2 · should US5 encodes INV4, INV5 · should
US1 encodes F6.1-INV2, INV3. Priority: must · Size: 3 · Testable: yes — by a boot check and a health request.

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

F6.1 invariants · each exercised by the stories that encode it INV1 · master: web layer calls only the facade US2, US3 INV2 · the two-supervisor split, self-healing US1, US3, US4 INV3 · the endpoint is the outermost plug US1 INV4 · an expected failure renders a status, not a 500 US5 INV5 · parse, don't validate: the facade is the parser US5
F6.1-INV1 (the master invariant) is encoded by US2, US3 — exercised by 2 stories, so it is pinned by a check.

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 , 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.
the principle

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.

on the Portal

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

Related in this course