In 2024 the prompt was the artifact. In 2026 the spec is. The teams shipping reliable software with AI coding agents are not the ones with the cleverest prompts; they are the ones who write down what the system should do, precisely enough that an agent, or a new developer, can build it without guessing.
We build from specs daily, for our own products and for client work, so this is a practitioner's guide rather than tool coverage. It goes through what changed, the five sections a buildable spec contains, a worked example you can copy, where spec-driven development breaks, and how we run it with clients. It will not rank the dozen SDD tools that shipped this year, because the tool matters far less than the document you feed it.
What changed: vague prompts started failing in production
Coding agents got good enough that the bottleneck moved. When we benchmarked Cursor, Claude Code, and Copilot, the gap between the top tools was smaller than the gap between a clear task definition and a vague one fed to the same tool. Agents write plausible code fast. Plausible is the problem: code that compiles, demos well, and quietly does the wrong thing on the edge cases nobody described.
The industry data backs the pattern. Independent analyses put vulnerability rates in AI-generated code between 9.8% and 42.1% depending on language and model, and the highest rates cluster around loosely specified tasks (Augment Code's SDD guide collects the studies). We see the downstream version of this weekly: half our inbound rescue work is prompt-built apps that collapsed on their first real users, a pattern we documented in our vibe-coded app rescue post.
Tooling followed the failure. GitHub open-sourced Spec Kit in September 2025 and it passed 80,000 stars within a year. AWS Kiro built an entire IDE around spec-first workflows and documents customer features that took 40 hours of ad-hoc prompting shipping in under 8 hours of human time when authored as specs first. Cursor shipped Plan Mode. Claude Code grew spec-driven slash-command workflows. Different vendors, one conclusion: agents are excellent at writing code and terrible at guessing what you meant.
What a buildable spec contains
A spec is not a PRD. A PRD says why the feature exists and who it serves. A spec says what the system does, in testable statements. Ours have five sections, and every section exists because we watched a build fail without it.
| Section | The question it answers | The failure it prevents |
|---|---|---|
| Behavior | What happens on the happy path? | The agent invents its own flow |
| Edge cases | What happens when input is wrong, late, duplicated, or hostile? | Support tickets in week two |
| Data contracts | What are the exact shapes, types, and validation rules? | Silent schema drift between services |
| Acceptance criteria | How do we know it is done? | Endless "almost done" cycles |
| Out of scope | What are we explicitly not building? | Scope creep and gold-plating by the agent |
Behavior: write it as testable statements
We use a loose version of EARS notation: "WHEN a user submits X, the system SHALL do Y." The format sounds bureaucratic and takes ten minutes to learn, and it forces every sentence to name a trigger and an observable result. If a behavior statement cannot fail a test, it is not a behavior statement, it is marketing.
Edge cases: this section earns the whole exercise
Happy paths survive vague prompts. Edge cases do not. Duplicate submissions, empty files, a user deleted mid-process, a third-party API timing out, a number that is negative when nobody expected negatives. In our experience roughly 70% of post-launch bugs in agent-built code trace back to an edge case nobody wrote down. The spec is where you pay that cost early, at the price of a sentence instead of an incident.
Data contracts and acceptance criteria
Data contracts pin the exact field names, types, nullability, and validation rules at every boundary: API payloads, database columns, file formats. Agents are confident improvisers, and an unpinned field name will drift between two services generated in separate sessions. Acceptance criteria then close the loop: a numbered list of checks that either pass or fail, which doubles as the test plan and, on client work, the demo script.
Length calibration: one to three pages per feature. A 40-page document for the whole system is a different artifact with a different failure mode, which we cover below.
A worked example: bulk employee import
Here is a trimmed spec from an HR platform feature we shipped: importing employees from a CSV file. This took about 45 minutes to write.
Behavior. WHEN an admin uploads a CSV, the system SHALL validate every row before writing any row. WHEN validation passes, the system SHALL create employee records and email the admin a summary. WHEN any row fails, the system SHALL import nothing and return a per-row error report with line numbers.
Edge cases. Duplicate email inside the file: reject the file, name both line numbers. Email already in the database: skip the row, list it in the summary as skipped, do not fail the import. Empty file, header-only file, or file over 10,000 rows: reject with a specific message for each. Dates in any format other than YYYY-MM-DD: reject the row. Upload interrupted mid-request: no partial state may exist.
Data contract. Required columns: full_name (string, 2 to 100 chars), email (RFC 5322, unique), department (must match an existing department ID), start_date (YYYY-MM-DD, not more than 1 year in the future). Extra columns are ignored, not errors.
Acceptance criteria. Eleven numbered checks, including: a 5,000-row valid file imports in under 60 seconds; a file with one bad row imports zero rows; the error report names line numbers; re-uploading the same file twice creates no duplicates.
Out of scope. Excel files, column mapping UI, scheduled imports.
The first agent-generated implementation passed 9 of the 11 acceptance checks. The two failures were both edge cases we had written down: the interrupted-upload check and the duplicate-inside-file check. That is the system working. Without the spec, those two failures do not disappear; they surface three weeks later as corrupted data and an angry customer, at 50x the fix cost.
The waterfall objection, and where SDD actually breaks
The standard criticism, argued at length in the Hacker News thread "Spec-Driven Development: The Waterfall Strikes Back", is that big upfront documents failed in 2005 and will fail again. The criticism is right about the failure and wrong about the target. Waterfall failed because a 200-page spec written six months before coding cannot survive contact with reality. A 2-page spec written the day before the feature is built, versioned in the same repo, and updated in the same pull request is a different object.
Where SDD genuinely breaks, from our own scar tissue:
- Exploratory work. If you do not yet know what you want, a spec is premature. Prototype first, throw it away, then spec what you learned. Writing the spec after the prototype is still spec-driven; the spec drives the production build.
- Spec-as-source purism. Some tools promise you will only ever edit specs and never read code. We do not buy it, and neither do the production incidents. Humans still review the generated code on anything that touches money or personal data.
- Specs nobody maintains. A stale spec is worse than no spec, because agents and new hires trust it. The rule that keeps ours alive: a behavior change without a spec change fails code review.
- Solo throwaway scripts. A one-off migration script does not need EARS notation. Judgment still applies.
How we use specs with clients
The spec changed our client process more than any AI tool did. The workflow: discovery call, then we write the spec, then the client approves the behavior and edge-case sections in plain English before a line of code exists. A client who cannot read TypeScript can absolutely read "WHEN a payment fails, the system SHALL retry twice, then email the customer." Most catch a wrong assumption at that stage, which costs a sentence to fix instead of a sprint. This discipline came out of our custom software and fintech work, where an unwritten edge case is not a bug, it is a compliance finding.
Three downstream effects, all measurable on our side. Fixed-price quotes became viable again, because the spec bounds the work. Disputes dropped to near zero, because "done" is a checklist both sides signed. And change requests became spec diffs: the client edits the behavior list, we price the diff. Nobody argues about what was promised, because it is written down.
It also reshaped roles. The developers who thrive with us now are the ones who write and review specs well, not the ones who type fastest, a shift we unpack in how AI is changing software development jobs. Specification is the skill that survives the tooling churn.
Frequently asked questions
What is spec-driven development in simple terms?
You write a short, precise document describing what a feature should do, including edge cases, exact data shapes, and pass/fail acceptance criteria, before any code is written. An AI agent or a developer then builds from that document, and the build is verified against it. The spec, not the chat history, is the source of truth.
How is a spec different from a PRD or a user story?
A PRD explains why a feature exists and who it serves. A user story is a one-line intent. A spec is the testable middle layer: observable behaviors, edge cases, data contracts, and acceptance criteria. You need the spec because agents and contractors execute exactly what is written, and a PRD leaves the expensive details unwritten.
Does writing specs slow development down?
It moves 45 to 90 minutes of thinking to the start of each feature and removes the regenerate-review-regenerate loop that eats days at the end. AWS Kiro documents 40-hour features shipping in under 8 hours of human time when authored spec-first, and our own delivery data points the same direction. The slow version is discovering your requirements one production incident at a time.
Do I need Spec Kit or Kiro to do spec-driven development?
No. The tools add structure and enforcement, and they are worth trying, but the value is in the document. A markdown file in the repo with behavior, edge cases, data contracts, acceptance criteria, and out-of-scope sections gets you 90% of the benefit with any coding agent, or with no agent at all.
Key takeaways
- Coding agents made specification, not code generation, the bottleneck. The spec is now the primary artifact.
- A buildable spec has five sections: behavior, edge cases, data contracts, acceptance criteria, and out of scope.
- Keep specs at one to three pages per feature, versioned with the code and updated in the same pull request.
- Edge cases are where the money is: a sentence in the spec versus an incident in production.
- Clients can approve behavior lists in plain English before the build, which makes fixed pricing and clean acceptance possible.
Sources
- GitHub Spec Kit repository
- AWS Kiro, spec-driven agentic IDE
- Augment Code: What Is Spec-Driven Development
- Hacker News: Spec-Driven Development, The Waterfall Strikes Back
What to do next
If you have a feature or a product in mind, the cheapest way to test this discipline is to have the spec written before you commit to a build. Send us the feature you are planning and we will write the first spec page with you: behavior, edge cases, and acceptance criteria. If the spec reveals the feature is smaller than you thought, you will get a smaller quote, and if it reveals you do not need custom software at all, we will say so.
