# Stop treating shipped specs as documentation

> Specs guide the build, then become history.

- **Published:** 2026-07-22
- **Tags:** engineering, ai
- **Canonical:** https://nbarwicki.com/blog/24-specs-as-documentation/

---

I close a GitHub issue after the code ships. I open it again in about **one case out of a hundred**.

The issue might contain a detailed PRD and every decision an agent needs to implement the feature.
I read it before the work starts. The agent uses it during the build. We share the same target.

I need the document until the code ships. After that, I treat it as *history*.

Spec-driven development goes wrong when we treat the plan used to build a feature as permanent
documentation of that feature. The application keeps changing. Teams write new PRDs, replace old decisions and leave several confident explanations of the same system in the repository.

Several files give the next developer different answers to the same question.

## A spec is a task

I put specs at the center of my workflow.

**Before an agent writes code,** I want a clear PRD. I settle the scope and answer the open questions.
The agent and everyone on the team need the same target.

We use the spec to describe the change while the work is open.

**Once the team implements those requirements,** the codebase contains the choices we made during the
build. We wrote the PRD before those choices. Anyone reading the code can see their result.

A neat folder full of specifications looks like organizational memory. During active development,
you have to maintain that folder as a second system.

Your team changes an earlier assumption while building the next feature. A developer adds behavior
to fix a bug, but the old PRD says nothing about it. You now update the code and each document that
describes it, or leave the contradiction for the next agent to resolve.

**The codebase is the source of truth for the system we have built.**

The codebase can contain bugs. Humans wrote the requirements, and humans make mistakes. With one
source of truth, the next developer knows what to trust when the code and a six-month-old document
disagree. This rule cannot remove bugs.

## Static documents let contradictions survive

Two Markdown files can make opposite claims for years without triggering an error. Both look
official, use the same confident tone, and give a fresh agent session plausible instructions.

The **compiler, test runner, and schema validator** expose more contradictions in the codebase. A
rejected change gives the developer a conflict to inspect instead of two paragraphs to choose from.

I trust a test more than a paragraph that describes the tested behavior. Tests cover what someone
chose to assert. A stale paragraph provides no check, and another stale paragraph can contradict it
without producing a warning.

We create more files because AI tools make generation cheap. Before lunch, we can produce:

- a PRD,
- a technical design,
- a task list,
- and an architecture summary.

Keeping those files consistent with code that changes each day still costs time.

Agents then read the mess they helped create. A fresh session lacks the understanding your team
built over months. Give the agent three old documents and current code, and you force it to guess
which version of your system you meant.

Spend that effort making the code readable and the repository easy to search. Clear module
boundaries give the next agent a path through the primary source.

## Keep the docs the code cannot replace

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">1. Delete the docs you create to explain your code<br/>2. Take the tokens you save on updating those docs<br/>3. Spend them on making your code self-explanatory</p>&mdash; Matt Pocock (@mattpocockuk) <a href="https://x.com/mattpocockuk/status/2076596585069174925?ref_src=twsrc%5Etfw">July 13, 2026</a></blockquote> <script async src="https://platform.x.com/widgets.js" charset="utf-8"></script> 

SSOT means *one authority for each question*:

- Read the **codebase** to learn current behavior.
- Read **ADRs** for decision history.
- Use the **glossary** for domain language.

**ADRs preserve why.** You can see which database, queue, or module boundary the team chose in the
code. You cannot see the rejected options or the constraint that made one option win. I keep
Architecture Decision Records because deleting that reasoning would delete information.

**Glossaries preserve meaning.** Teams often give one domain concept several names as a project
grows. One developer says customer, another says account, and an agent writes client in the next
chat. The same entity now has three names across prompts, issues, and code.

Teams did this before LLMs. Coding agents raise the cost because each session starts without the
shared understanding your team built over months. If you use several words for one concept, the
agent has to infer whether they mean the same thing. The agent may write a wrong guess into the
codebase as another term.

I started keeping a centralized glossary based on the ubiquitous language from domain-driven
design. I spend less time clarifying terms in agent chats, and the team uses the same names in
discussions. I name an entity, behavior, or module, and the agent knows which part of the system I
mean.

**Navigation pointers show where to start.** Use a thin file to point a newcomer to the billing
module, the glossary, or a specific ADR. The newcomer reads the source instead of a copied summary.

Keep the documentation engineers use to perform tasks that may not be clear from implementation
code:

- READMEs,
- setup instructions,
- public API guides,
- and incident runbooks.

Delete the walls of prose that mirror the codebase.

## Make the code worth reading

Forcing each newcomer to reconstruct the product from code sounds wasteful.

I expect them to explore it. Current coding agents can inspect a repository, follow references,
search for a concept, and answer questions about what they find. Human engineers should follow
their curiosity and ask questions too.

A newcomer saves time with a summary until a code change makes it wrong. Then they read the
summary, discover that the code disagrees, and explore the repository anyway.

The codebase already contains the answers. Documentation should help you find them, not maintain a
second copy of them.

- Use the **PRD** to align everyone before the build, then close it when the work ships.
- Keep the **ADR** that explains why and the **glossary** that fixes the language.
- Use **navigation pointers** to show newcomers where to look.

Make your codebase clear enough to carry the rest.
