The short answer
A living software specification is a maintained, structured record of product intent. It changes through explicit, reviewable revisions, and it stays the shared reference for product, engineering, QA, and the coding agents working alongside them.
- Structured entities, not one long document
- Proposed changes look different from decisions
- History explains why behaviour changed
- People and agents can retrieve one slice of it
On this page · 5 sections
A document is not living just because it is online
The file format was never the problem. The change process was.
A page in a collaborative editor goes stale exactly as fast as an emailed attachment. What keeps a specification current is not where it is stored but whether there is a reliable path from a new decision to the text describing it.
Decisions get made in chat, in tickets, and in meetings. Somebody has to know which part of the specification each one affects, and how that decision becomes authoritative. Without the path, the document quietly turns into a historical artifact that everyone stops trusting and nobody deletes.
A shared page
- Anyone edits; nobody owns the result
- The newest text wins, whether or not it was agreed
- History is a diff of characters, not of decisions
- You read the whole thing to find one rule
A living specification
- One published version is the current answer
- Proposals stay visible and separate until accepted
- History records what changed and who approved it
- You address a flow, a role, or a model directly
The four properties that make a spec durable
Structure, review, history, access. Drop one and it rots.
Durable specifications do not predict every implementation detail. They remove ambiguity about product behaviour, and they keep removing it as the product changes. Four operational properties do most of that work.
| Property | What it means | What breaks without it |
|---|---|---|
| Structure | Flows, roles, models, terms, and test cases are separate entities with explicit relationships | Rules hide in prose and contradict each other unnoticed |
| Review | A proposed change has an owner and an approval decision before it becomes the source of truth | The loudest recent edit becomes the de facto product |
| History | Revisions preserve what changed and the reasoning around it | Nobody can tell a deliberate decision from a drift |
| Access | People and tools retrieve the slice they need without copying the whole document | Every consumer works from a private, ageing copy |
What belongs in the specification
Behaviour and constraints go in. Local implementation choices stay out.
Start with behaviour. A flow names its trigger, its actors, its ordered steps, its decision branches, and the outcome you can observe. Roles state permissions and responsibilities. Data models name fields, types, and relationships. Test cases connect expected behaviour back to the flow they verify.
Leave it in the codebase
- Component structure and file layout
- Library choices with no product consequence
- Caching strategy, unless a user can observe it
- Anything a refactor could change without telling anyone
Put it in the spec
- Who may do what, and who must not
- State transitions and irreversible actions
- Cross-team contracts and integration behaviour
- Retention, deletion, and anything with a legal shadow
The test is whether somebody outside the codebase needs the fact to reason about the product. Shared intent belongs here. A second copy of the source code does not.
How to keep it alive without process theatre
Attach spec updates to decisions the team already makes.
Nobody maintains a specification as a separate chore. It survives when updating it belongs to a moment that already exists in the week.
Discovery
Capture the outcome and the non-goals while they are still cheap to argue about.
Design review
Turn the discussion into flows and branches. Disagreement here costs a conversation, not a sprint.
Refinement
Point each ticket at the entities it changes, so scope is inherited rather than re-described.
Implementation
When code reveals a case the spec never covered, raise it as a proposal instead of deciding silently.
QA
Failing behaviour is either a bug or an outdated acceptance case. Deciding which is worth recording.
After shipping
Fold accepted changes and real exceptions back in, then publish the revision.
Keep small changes small. Reserve the heavier review path for decisions that touch security, permissions, billing, data retention, or more than one team.
Living specs and coding agents
Agents are reliable in proportion to how bounded their context is.
A coding agent does its best work with current, narrow context. A structured specification lets it retrieve the flow, role, model, and test cases for one task — safer than a long planning document whose status and internal contradictions it has no way to judge.
That changes what you hand an agent:
- The task and the revision it applies to, rather than a folder of documents.
- The entities the task actually touches, rather than everything known about the product.
- Named acceptance cases, rather than a description of done written from memory.
The human approval boundary stays where it was. An agent can propose a specification edit when implementation reveals a missing case. Published intent changes only after a person accepts the consequence.
Is your specification actually alive?
- A new teammate can identify the currently approved behaviour.
- Reviewers see a proposed change before it becomes authoritative.
- Every test case traces to a flow or a requirement.
- A coding agent can retrieve only the context its task needs.
- The team can explain why a behaviour changed six months later.