On this page#
What changes when an agent does this#
Spec driven development moves the bottleneck from writing code to defining, constraining, and reviewing change. The agent can generate an implementation quickly; the scarce work is deciding what “correct” means, expressing repository invariants, and detecting a plausible solution that satisfies the prompt while quietly violating the system.
A coding agent is an interface around a large language model: a model that generates likely continuations from context rather than independently proving that a change is correct. That distinction matters. More context can improve its output, but context is not a guarantee.
So the unit of work changes. It is no longer:
- Describe the feature.
- Generate code.
- See whether it runs.
It becomes:
- Inspect the repository.
- Write a falsifiable specification.
- Challenge the specification.
- Approve the plan.
- Implement within explicit boundaries.
- Verify against the specification.
- Review the resulting diff.
- Preserve a clean rollback point.
“What is spec-driven development?” has a practical answer: it is a workflow in which an executable change is governed by an explicit contract written before implementation. The spec names behavior, invariants, exclusions, verification commands, and acceptance evidence. The agent may propose the contract, but it must not silently approve its own assumptions.
Tools such as Claude Code can inspect files, edit code, and run commands, as described in the Claude Code documentation. Those capabilities shorten execution. They do not remove the need for judgment; they make weak judgment propagate faster.
Photo by Christina Morillo on Pexels.
The prompt chain#
The prompt chain separates discovery, specification, planning, implementation, and verification so that uncertainty cannot hide inside a single polished answer. Each stage produces an artifact that the next stage may challenge. Combining everything into “implement this feature” is the wrong default for a repository with real invariants.
1. Establish the repository contract#
Start by asking for facts, not code:
Inspect the repository for this change. Do not edit files.
Return:
- relevant entry points and data flows
- existing conventions that constrain the solution
- tests covering adjacent behavior
- public APIs, schemas, or persisted data that must remain compatible
- security, concurrency, and failure-handling invariants
- unknowns that cannot be resolved from the repository
Cite every claim with a file path and symbol. Separate observed facts from assumptions.This prompt blocks premature implementation and makes unsupported claims visible. File paths matter because summaries can sound authoritative while being wrong. The “facts versus assumptions” split is essential: an agent should never convert missing evidence into repository policy.
If the repository is unfamiliar, the free foundations track is the appropriate next step before adding more automation. A longer prompt cannot compensate for an operator who cannot evaluate the resulting contract.
2. Draft a falsifiable specification#
Turn the inspected facts into a contract:
Draft a specification for the requested change. Do not implement it.
Include:
- user-visible behavior
- inputs, outputs, and error behavior
- repository invariants that must remain true
- non-goals
- compatibility constraints
- acceptance criteria written as observable pass/fail statements
- required test coverage
- unresolved decisions
Do not invent requirements. Mark each unresolved product or architecture choice explicitly.“Observable pass/fail” prevents acceptance criteria such as “works correctly” or “is robust.” Those phrases cannot reject a bad patch. A useful criterion names an input, an outcome, and the evidence that demonstrates it.
3. Attack the specification#
Do not let the same draft pass unchallenged:
Review this specification as a hostile maintainer.
Find:
- ambiguous acceptance criteria
- missing failure cases
- conflicts with repository behavior
- hidden migration or rollback requirements
- changes that exceed the stated scope
- criteria that cannot be verified
Return proposed corrections only. Do not write implementation code.The point is not theatrical debate. Large language models can produce coherent text without establishing that every premise is true. An adversarial pass changes the task from completing the draft to finding reasons it should be rejected.
4. Produce a bounded implementation plan#
Only after the spec is stable should the agent plan edits:
Create an implementation plan for the approved specification.
For each step, list:
- files expected to change
- symbols or interfaces affected
- invariant preserved
- test or command that verifies the step
- rollback boundary
Flag any step that requires broader refactoring. Do not implement yet.This exposes scope inflation before it reaches the diff. If a small behavior change suddenly requires a framework rewrite, stop. The plan is probably solving the agent’s preferred problem rather than the requested one.
5. Implement one approved slice#
Keep implementation mechanically constrained:
Implement only the next approved plan step.
Rules:
- preserve all named invariants
- do not modify unrelated files
- do not add dependencies without approval
- do not weaken, delete, or skip existing tests
- add the specified coverage
- stop if repository evidence contradicts the plan
Afterward, report changed files, verification results, and remaining steps.The stop condition is more important than elaborate prose. Agent documentation can explain capabilities and controls—see the Claude Code documentation—but your repository-specific authority boundary must come from you.
6. Verify against the contract#
Finish with an evidence request, not a victory lap:
Verify the implementation against every acceptance criterion.
For each criterion, report:
- pass, fail, or not verified
- exact supporting test or inspection evidence
- relevant file and symbol
- residual risk
Then inspect the complete diff for unrelated edits, weakened tests,
compatibility breaks, and missing rollback work. Do not fix new findings.“Do not fix” creates another review boundary. Otherwise the agent can discover a defect, patch it, introduce a second defect, and summarize the entire loop as complete.
For a packaged version of this review discipline, use PairFoundry’s Review and Repair. The broader workflow library shows where this chain belongs among recurring engineering tasks.
The gate#
The gate is the mandatory human stop between the challenged specification and implementation. A person must approve the behavior, non-goals, invariants, acceptance criteria, and expected file scope. If those cannot be reviewed quickly, the specification is not ready; letting the agent proceed merely converts ambiguity into code.
Use a compact approval checklist:
- Does every requirement have observable pass/fail evidence?
- Are assumptions visibly labeled?
- Are compatibility and persisted-data constraints named?
- Are security and failure paths covered?
- Are non-goals explicit?
- Is the expected diff proportional to the request?
- Can every planned step be reverted independently?
The human is not reviewing syntax at this gate. The human is accepting consequences. That decision cannot be delegated to the system that proposed the consequences.
There should be a second, smaller gate before completion: compare the final diff with the approved file list and acceptance matrix. Green tests are necessary, but they only prove what the suite checks. PairFoundry’s three-pack overview is useful when deciding how much structure a team needs around planning, execution, and review.
Photo by Daniil Komov on Pexels.
What it gets wrong#
Spec driven development fails when the specification is treated as authoritative merely because it is structured. An agent can produce an elegant contract from a false repository model, omit an inconvenient invariant, or satisfy every written criterion while breaking behavior nobody remembered to specify. Structure improves inspection; it does not create truth.
Watch for these failure modes:
| Failure mode | Recognition signal | |---|---| | Invented convention | The agent names a “repository pattern” without a file and symbol. | | Spec laundering | An assumption appears later as an approved requirement. | | Test-shaped implementation | Production design mirrors test fixtures instead of domain behavior. | | Scope drift | Files outside the approved plan change without a stop. | | Compatibility blindness | A type or endpoint passes local tests while its public contract changes. | | Verification theater | The report says “verified” without an exact command or criterion mapping. | | Self-approved repair | The agent finds and fixes new issues during the final review. |
Another common error is asking one context to be author, critic, implementer, and approver without interruption. The outputs may be consistent because the same mistaken premise survives every phase. Consistency is not correctness.
The remedy is traceability: requirement to plan step, plan step to diff, and acceptance criterion to evidence. Missing links are findings, not paperwork defects.
Rollback#
Rollback should restore the repository to the last approved boundary without requiring the agent to remember what it changed. Create a clean checkpoint before implementation, keep each approved slice isolated, and separate generated artifacts, migrations, dependency changes, and behavioral edits whenever they have different reversal risks.
Before each slice, record:
- the approved spec revision;
- the exact planned file scope;
- the repository checkpoint;
- external state the change may mutate;
- the command or procedure that proves restoration.
If verification fails, stop adding fixes. Revert the failed slice, confirm the working tree matches the checkpoint, rerun the pre-change verification, and revise the spec or plan. “Keep patching until green” destroys the evidence needed to identify which assumption was wrong.
Database and external-state changes require a rollback procedure before execution, not after failure. If reversal cannot be described, the slice is too large or the migration design is incomplete.
Photo by panumas nikhomkhai on Pexels.
Related reading#
- Claude Code planning mode: making the output reviewable, not just correct
- Claude Code documentation — the workflow, the gate, and the rollback
FAQ#
What is a spec-driven development?#
Spec-driven development is a workflow where an explicit, reviewable contract controls implementation. The contract defines observable behavior, invariants, non-goals, compatibility limits, verification evidence, and rollback boundaries before code changes begin. The agent can help draft and execute it, but a human approves the consequential decisions.
What is the difference between BDD and spec-driven development?#
BDD expresses behavior through examples and scenarios, usually to align product intent with executable tests. Spec driven development is broader: it also governs repository constraints, architecture boundaries, non-goals, implementation scope, verification, and rollback. BDD scenarios can be part of the spec, but they are not the whole operating contract.
Does spec-driven development actually work?#
Yes, when the spec is falsifiable, grounded in repository evidence, challenged before implementation, and enforced through human gates. It fails when teams treat a generated document as truth or allow the agent to approve its own assumptions. The benefit comes from controlled boundaries and traceability, not from document volume.
Is SDLC outdated?#
No. The software development lifecycle still describes the necessary movement from requirements through implementation, verification, release, and maintenance. Coding agents compress parts of that lifecycle; they do not eliminate them. Spec driven development makes the compressed workflow safer by preserving explicit decisions, review gates, evidence, and rollback points.