R
Renan Botasse
Guest
Generating code today is cheap. Generating code nobody understands is expensive, and the bill arrives later. With AI producing hundreds of lines in seconds, writing code is no longer the bottleneck. The bottleneck is knowing exactly what you want to build and being able to review what was generated. Spec-Driven Development (SDD) tackles this by reversing the traditional order: first the intent, then the specification, and only then the code.
AI sped up code generation, but review is still manual, slow, and, let’s be honest, tedious. When code shows up too fast, it carries decisions nobody made consciously. A project with hundreds of generated files and no method becomes a tangle nobody wants to review, and anyone who claims they review everything is being overly optimistic.
Vibe coding (ask, generate, test, ask again) works well for prototypes, one-off scripts, and proofs of concept. But it has clear limits:
In SDD, the specification stops being forgotten documentation sitting in a folder and becomes the source of truth, versioned alongside the code. The code is derived from it. If code and specification diverge, the specification wins. Yes, this is a heavy idea for anyone used to coding first and documenting never.
This changes the economics: code becomes a regenerable artifact, and what holds lasting value is the recorded intent. Refactoring turns into regenerating from the same spec. Anyone who has had to rewrite an entire system because nobody knew what it actually did, raise your hand. Yeah, that’s what I thought.
Each phase produces a file. The order doesn’t change, not even when you’re in a hurry, and you will always be in a hurry.
Phase 0 · Constitution (
The rules that apply to the entire project: stack, architecture patterns, quality. It’s the law of the project. Every other spec references this file.
Phase 1 · Specification (
The what and the why. Business objective, functional requirements, users, edge cases, and what’s out of scope. No technical terms. If a database name shows up here, something went wrong.
Phase 2 · Clarification (
Reread v1.0, ask the AI to point out ambiguities, and close the blind spots. This version must be reviewed by you. First human gate. This is the step almost everyone skips, and it’s exactly where most of the savings are.
Phase 3 · Plan (
The technical how: architecture, HTTP contracts, data model, decisions, and risks. This is the only place where technologies belong.
Phase 4 · Tasks (
Atomic, ordered units, each with an ID, origin, dependency, and completion criteria. Unlike the internal plan the AI makes on its own, you can read and review this, which is a huge advantage.
Phase 5 · Analysis
A report cross-checking spec, plan, and tasks: are there requirements without coverage? Tasks without origin? Inconsistencies? Second human gate.
Phase 6 · Implementation
Execute one task at a time, with a focused prompt. Example:
Golden rule: if the result isn’t what you expected, don’t ask the AI to patch the code. That’s the strongest temptation of the method, and it’s exactly why the rule exists. Go back to the specification and rerun the flow from there.
To illustrate, a small service that generates strong passwords and returns a GUID to retrieve them later. Nothing revolutionary, but enough to show the path.
Notice how every step traces back to a line in the specification. If something breaks six months from now, you know where it came from.
Before starting a feature:
Before generating code:
During implementation:
When something changes:
I know this isn’t the most glamorous method out there. Nobody gets excited about writing acceptance criteria, reviewing an analysis report, or stopping to update the spec when you’d rather just fix the bug. But that boring part is exactly what separates developers who use AI to ship reliable software from those who use it to ship problems at scale. So pick a real feature from your current project, run it through the six phases, and see what happens. If the result doesn’t convince you, go back to vibe coding without guilt. But if it does, and I bet it will, you’ll find it hard to go back to coding any other way. Let’s try it. Open your editor, write that first constitution, and see where it takes you.
The problem SDD solves
AI sped up code generation, but review is still manual, slow, and, let’s be honest, tedious. When code shows up too fast, it carries decisions nobody made consciously. A project with hundreds of generated files and no method becomes a tangle nobody wants to review, and anyone who claims they review everything is being overly optimistic.
Vibe coding (ask, generate, test, ask again) works well for prototypes, one-off scripts, and proofs of concept. But it has clear limits:
- The context lives only in the chat window and is lost with every new conversation.
- Review happens through behavior, not by reading the code. “It works” has become a synonym for “it’s done,” and it isn’t.
- In teams, two identical prompts can produce different results, which makes maintenance harder.
- Business rules, auditing, and compliance require traceability that a chat doesn’t provide.
What SDD is
In SDD, the specification stops being forgotten documentation sitting in a folder and becomes the source of truth, versioned alongside the code. The code is derived from it. If code and specification diverge, the specification wins. Yes, this is a heavy idea for anyone used to coding first and documenting never.
This changes the economics: code becomes a regenerable artifact, and what holds lasting value is the recorded intent. Refactoring turns into regenerating from the same spec. Anyone who has had to rewrite an entire system because nobody knew what it actually did, raise your hand. Yeah, that’s what I thought.
The four principles
- Intent before implementation. Think about the why first. Stack and technology don’t belong here, no matter how tempting it is to start naming frameworks right away.
- Executable specification. Every requirement must be verifiable and be born with acceptance criteria. “The system must be fast” is useless, it’s just a wish. “The listing responds within 300 ms with 10,000 records” works.
- Explicit context. Business rules can’t live only in one person’s head or in a chat conversation. If a decision didn’t make it into the file, it doesn’t exist. I’ve seen an entire system depend on a colleague who was about to retire and was the only one who knew why a certain process worked the way it did.
- Review gates. A human validates each phase before moving on. Approving without reading defeats the entire method.
The six-phase flow
Each phase produces a file. The order doesn’t change, not even when you’re in a hurry, and you will always be in a hurry.
Phase 0 · Constitution (
constitution.md)The rules that apply to the entire project: stack, architecture patterns, quality. It’s the law of the project. Every other spec references this file.
Phase 1 · Specification (
spec.md, v1.0)The what and the why. Business objective, functional requirements, users, edge cases, and what’s out of scope. No technical terms. If a database name shows up here, something went wrong.
Phase 2 · Clarification (
spec.md, v2.0)Reread v1.0, ask the AI to point out ambiguities, and close the blind spots. This version must be reviewed by you. First human gate. This is the step almost everyone skips, and it’s exactly where most of the savings are.
Phase 3 · Plan (
plan.md)The technical how: architecture, HTTP contracts, data model, decisions, and risks. This is the only place where technologies belong.
Phase 4 · Tasks (
tasks.md)Atomic, ordered units, each with an ID, origin, dependency, and completion criteria. Unlike the internal plan the AI makes on its own, you can read and review this, which is a huge advantage.
Phase 5 · Analysis
A report cross-checking spec, plan, and tasks: are there requirements without coverage? Tasks without origin? Inconsistencies? Second human gate.
Phase 6 · Implementation
Execute one task at a time, with a focused prompt. Example:
“Read the constitution, the plan, and the analysis report. Execute only task T03 from tasks.md. Do not change files outside the scope of the task.”
Golden rule: if the result isn’t what you expected, don’t ask the AI to patch the code. That’s the strongest temptation of the method, and it’s exactly why the rule exists. Go back to the specification and rerun the flow from there.
Practical example: password generator
To illustrate, a small service that generates strong passwords and returns a GUID to retrieve them later. Nothing revolutionary, but enough to show the path.
- Spec v1.0: “RF_01: generate a 16-character password with letters, numbers, and symbols.”
- Spec v2.0 (after clarification): “RN_01: the password never contains whitespace. RN_02: the GUID is unique per password. RN_03: if generation fails, nothing partial is saved to the database.”
- Plan:
POST /api/passwords/generatecontract,Passwordstable, use ofRandomNumberGenerator. - Tasks: T01 install packages, T02 create entity and context, T03 write failing tests (Red), T04 implement until they pass (Green).
Notice how every step traces back to a line in the specification. If something breaks six months from now, you know where it came from.
Day-to-day checklist
Before starting a feature:
- Does the constitution exist and is it up to date?
- Does the spec have verifiable requirements, each with acceptance criteria?
- Is the spec free of technical terms?
Before generating code:
- Did I read and approve the clarification (v2.0)?
- Did I review the plan and the tasks, not just accept them?
- Did I review the analysis report?
During implementation:
- Does each prompt execute a single task?
- Were the tests written together with the task?
- Were new decisions recorded in the spec or the plan, not left in the chat?
When something changes:
- Did the change start in the specification?
- Was the flow redone from the affected phase?
When to use it
I know this isn’t the most glamorous method out there. Nobody gets excited about writing acceptance criteria, reviewing an analysis report, or stopping to update the spec when you’d rather just fix the bug. But that boring part is exactly what separates developers who use AI to ship reliable software from those who use it to ship problems at scale. So pick a real feature from your current project, run it through the six phases, and see what happens. If the result doesn’t convince you, go back to vibe coding without guilt. But if it does, and I bet it will, you’ll find it hard to go back to coding any other way. Let’s try it. Open your editor, write that first constitution, and see where it takes you.