Spec-driven development: keeping specifications and code aligned
Learn which specifications to maintain, how they differ from implementation plans, and what to do when the written rule, tests and running code disagree.
Spec-driven development starts with a written description of what the software should do, then uses it to guide coding and testing. Decide which specifications must stay current after the task ends, so later changes do not follow an outdated rule.
Imagine a specification that says a deleted file can be restored for seven days, while the code deletes it immediately. Do not simply edit the document to match the code. First find out which behaviour was agreed, then fix whichever part is wrong.
A specification says deleted files can be restored. The code destroys them immediately. Making the two agree is not enough: an agent could achieve that by deleting the promise from the document. First establish what users should receive.
Write what the software must do#
A specification describes required behaviour and constraints. It should let someone implement and assess the result without reconstructing the conversation that produced it. It does not need to dictate every class, method or line of code.
GitHub’s Spec Kit is one toolkit for organising specifications, plans and implementation tasks for coding agents. It can provide a process and templates. It cannot establish that a new product choice in a generated document was approved.
Follow three changes to a file-restoration feature#
In this hypothetical product, ordinary deletion should allow an attachment to be restored for seven days. The duration is an invented product rule, not a retention recommendation. An endpoint that immediately destroys the file does not meet that rule. Rewriting the specification to describe destruction would conceal missing implementation work.
Later, the team approves a separate operation for permanent deletion. Now the sentence “Every deleted attachment can be restored” needs an exception. The code can be correct while the document is outdated.
A third decision says that restoration requires the user’s current permission. Someone who uploaded a file but later lost access must be denied. A test that only restores a file as an authorised user may still pass, even if the implementation never checks revoked access.
An approved change now requires current permission when restoring a file.
Before reconciliation
- Current policyA user without current access must be denied.
- Old implementationThe original uploader can restore.
- Existing testOriginal uploader restores: PASS.
After the approved change
- Maintained specificationState the current-access rule and its scope.
- ImplementationCheck current permission before restoration.
- New regression caseRevoke access, then restore: DENIED.
Why the old result was insufficientThe earlier test never revoked access. It could pass while the newly approved policy was violated.
Illustrative policy evolution. Establish the approved behaviour before changing the specification, code or tests to match one another.
These are examples of spec drift: the written rules, code and tests no longer describe the same behaviour. The repair starts by finding the agreed policy. Making all three agree on an invented rule would create consistency without correctness.
Distinguish requirements, plans and test results#
“This endpoint destroys the file” is a research finding about existing behaviour. “Ordinary deletion must allow restoration” is a requirement. “Store a deletion timestamp” is a design choice. The steps for adding the column form an implementation plan. The executed restoration test provides a result to inspect.
These statements have different jobs even when they appear in one document. Do not turn a finding about current behaviour into a new requirement, or treat a proposed implementation step as proof that it happened.
Research, plan, implement explains how these pieces support a task. Here the additional question is which ones must remain current after the task is complete.
Decide which documents stay current#
In her October 2025 analysis, Birgitta Böckeler distinguishes three approaches. Spec-first writes a specification to guide a task. Spec-anchored keeps it updated as the feature changes. Spec-as-source makes the specification the primary editable source from which code is produced.
Those choices create different maintenance work. They are not stages every team needs to reach. Decide which approach you are using rather than leaving future readers to infer it from a folder of documents.
The restoration policy is useful for later features, so keep it current. The plan to add a timestamp column describes one completed change. Preserve that history, mark it complete and record its base revision. An old requirement can still apply; a recently edited plan can still be obsolete.
For a maintained specification, name its scope, who updates it and which checks exercise its important rules. Keep design decisions as history too. A later decision can supersede an earlier one without silently rewriting the explanation of past work.
Keep the design understandable as code changes#
Reviewing a short specification does not approve every implementation an agent can produce from it. Matt Pocock’s talk Software Fundamentals Matter More Than Ever argues that faster code generation makes understandable design more important. That is an engineering argument, not evidence that every spec-driven workflow fails or that one method guarantees a productivity gain.
Consider the restoration example. An agent could copy the seven-day calculation into the restore endpoint and the cleanup job. Both may pass today’s examples. A later change to the recovery period must now keep two implementations aligned. A shared, well-defined policy can reduce that duplicated work without prescribing every method in the specification.
Ask what the change leaves behind: where the rule lives, which callers rely on it and which checks would reveal a mismatch. Google’s review guidance treats design, complexity and the wider code context as review concerns, not optional decoration after the tests pass.
Regeneration can still be useful, especially for a disposable experiment. For maintained software, inspect the resulting design and behaviour instead of assuming the specification makes them sound. The module-review example shows how a clear interface can reduce what a reviewer must reconstruct without turning approval into a quick skim.
Find the agreed rule before fixing the mismatch#
Record the disputed statement, requirement version, code revision and environment where the behaviour was observed. Then find out why they differ. Passing tests cannot settle whether those tests check the right rule.
| Situation | Take | Because |
|---|---|---|
| The agreed rule still applies, but the code violates it. | Fix the implementation | Add a test that reveals the mismatch, then correct the behaviour. |
| A newer approved decision replaced the old written rule. | Update the specification | Check the document, code and tests against that newer decision. |
| Nobody has decided the disputed case. | Ask the responsible person | Existing behaviour and a generated proposal do not establish what was approved. |
| The observation came from an older release or another environment. | Check the right version | Do not rewrite a current requirement to explain an unrelated deployment. |
- Situation
- The agreed rule still applies, but the code violates it.
- Take
- Fix the implementation
- Because
- Add a test that reveals the mismatch, then correct the behaviour.
- Situation
- A newer approved decision replaced the old written rule.
- Take
- Update the specification
- Because
- Check the document, code and tests against that newer decision.
- Situation
- Nobody has decided the disputed case.
- Take
- Ask the responsible person
- Because
- Existing behaviour and a generated proposal do not establish what was approved.
- Situation
- The observation came from an older release or another environment.
- Take
- Check the right version
- Because
- Do not rewrite a current requirement to explain an unrelated deployment.
An agent can find the affected files and prepare a correction. It should not weaken the requirement because meeting it is difficult, nor restore old behaviour merely because an obsolete plan still describes it.
Review the changed rule with the code and tests#
“Restoration now checks current permission” gives a reviewer a specific decision to inspect. Show the updated requirement, the implementation and a test where the user’s access has been revoked. A long file-by-file plan can make that same decision harder to spot.
Exercise ordinary recovery and its boundaries: an expired recovery period, permanent deletion and revoked access. Name what remains untested, such as historical data or a background cleanup job. One successful local test does not cover those cases automatically.
Once the change is accepted, update the maintained policy and mark the task plan complete. Future searches should distinguish current rules from historical instructions so another agent does not reintroduce the earlier behaviour.
Do not mistake a generated draft for an agreement#
An AI-written specification can help explain a change. Its polished wording can also hide a choice nobody made. Have it distinguish supplied requirements, observed behaviour, proposed decisions and unanswered questions.
For restoration, a useful review asks who may permanently delete a file and what should happen after access is revoked. Asking for more detail can add pages without answering either question. Preparing a ready ticket helps find those missing decisions; architecture decision records preserve the reasons for important design choices.
Avoid documents that nobody needs to maintain#
A spelling correction does not need a feature specification. A local bug with clear expected behaviour may need only an explanation and a reproducing test. Add a lasting document when future work needs its rules, not simply because an agent can generate one.
Before creating it, identify who will use it and which future change should trigger an update. Without either answer, the document may become another outdated instruction for the next agent.
IF YOU REMEMBER ONE THING
Keep the agreed behaviour current and mark finished implementation plans as history. When code and specification disagree, find the applicable decision before making them match.
Questions people also ask
4 QUESTIONSDoes spec-driven development require a particular toolkit?
No. A short versioned document can be enough. Tools can organise the specification and tasks, but someone still needs to decide what the software should do, review the result and update the rules that future work relies on.
Should specifications or code be the source of truth?
They answer different questions. An approved specification says what should happen. Inspected code and observed behaviour show what currently happens. When they disagree, find the applicable requirement before deciding whether the code, tests or document needs correction.
Does a reviewed specification remove the need to review generated code?
No. It records the intended behaviour, not proof of the resulting implementation. Check the actual change, its interfaces and appropriate tests. Even when code is regenerated from a specification, maintainers need to understand the resulting system and how it can fail.
Should completed implementation plans be deleted?
Not necessarily. A completed plan can explain past work when it is marked as history and tied to its code revision. The important part is preventing a future agent from mistaking the old plan for instructions that still apply.