A legend, not a vocabulary suggestion
Every map worth reading has a legend: a small, fixed set of symbols, and a promise that every mark on the map is one of them. Requirements-as-code imposes such a legend on the domain of justification. It is not a vocabulary you are invited to adopt; it is the alphabet the artifacts are made of.
Figure 1 — The legend REQ ↔ FEAT ↔ AC ↔ TEST ↔ IMPL ↔ EVIDENCE. Read left to right it is a descent from intention to proof; the dashed return edge is the loop closing — evidence in CI confirming the original why.
Each node is a kind of thing, and each arrow is a kind of relationship — satisfies, verifies, refines. Those are not decorative labels; they are the terms of the ubiquitous language, and the system holds everyone to them. When a product manager and a developer sit down to name an acceptance criterion, they are not drafting prose — they are minting a term in a language the compiler also speaks.
What each node is for
- REQ — the why. The promise and its reason. Not "the system has retries" but "the system shall retry transient failures because the March incident cost us four hours of orders." A requirement that cannot say because is a feature in disguise.
- FEAT — the what. The functional answer to a why. One feature can answer several requirements; one requirement can be answered by several features. The link is many-to-many and, as the next part shows, deliberately loose.
- AC — how measured. The criterion that makes the why falsifiable. This is the hinge of the whole map: an AC turns an aspiration ("should be fast") into something a test can pass or fail ("p95 latency under 200ms on the search endpoint").
- TEST — the proof. The executable that exercises the implementation against the criterion. Not "we tested it" in a status meeting — a named test, bound to a named AC.
- IMPL — the code. The territory. The only node that was ever going to exist anyway; the legend's job is to make sure the other five point at it truthfully.
- EVIDENCE — that it runs. Coverage, a green gate, a metric inside its threshold. The artifact that closes the loop back to the why and lets you say we know, not we believe.
Why typing it changes everything
You could write all six of those in prose. Teams do, constantly. A heading per requirement, a bullet list of acceptance criteria, a sentence saying "covered by the integration suite." It reads fine. It also rots the instant the code moves, because prose has no referent the compiler can check. The word "covered" in a document is a claim; nothing connects it to a test that exists.
Typing the legend converts every claim into a reference. "This AC is verified by that test" stops being a sentence and becomes an edge in a graph the build can walk. And that has two consequences that prose can never have:
It cannot silently lie. Rename the feature and forget a reference, and the chain breaks at compile time. Delete the test that was the only proof of an AC, and
compliance --strictreports an uncovered criterion. The map is forced to stay true to the territory because they are checked against each other by a machine, not by a human's good intentions.It is traversable by an agent. A model cannot reliably parse "see the integration suite" into an action. It can walk a typed graph: given this requirement, which features satisfy it; given this feature, which ACs it specifies; given this AC, which test proves it, and whether that test exists. The legend is precisely the structure that lets an AI ask what is missing and get an answer in the shape of a list, not a paragraph to interpret.
This is the quiet reason the whole approach scales to machines. We did not type the requirements to please a linter. We typed them so that the map — the why, all the way down to the proof — became a data structure. A human reads the legend as documentation. An agent reads it as an addressable graph it can query, extend, and verify against.
The next part is where the legend earns its subtlety. The arrow from a requirement to its acceptance criteria looks like it should be the tightest link on the map. It is, on purpose, the loosest — and that looseness is itself a typed, default-provided thing called a Style.