Skip to main content

Chapter 4: Spec-First Development


Learning Objectives

By the end of this chapter, you will be able to:

  • Define spec-first development and distinguish it from code-first development
  • Write a specification before implementation for any feature
  • Use a specification to improve AI code generation quality by 2-3x
  • Identify when specifications drift from code and the consequences of that drift
  • Assess whether your current workflow qualifies as spec-first

What Spec-First Means

Spec-first development is the simplest form of SDD: write a specification before you write code.

That's it. No specialized tooling. No automated validation. No code generation pipelines. Just the discipline of articulating what you want before asking an AI (or yourself) to build it.

Spec-First Workflow:

1. Write specification (what and why)
2. Review and refine specification
3. Implement from specification (with AI or manually)
4. Validate implementation against specification

This sounds obvious — of course you should know what you're building before you build it. But in practice, the vast majority of AI-assisted development skips this step entirely. Developers open their AI assistant and start typing: "Build me a dashboard", "Add search functionality", "Create a payment system".

Spec-first development inserts a deliberate pause between the idea and the implementation: the specification.


The Specification as Communication Protocol

A specification is a communication protocol between you and your AI assistant. Like any protocol, it has structure, conventions, and expectations.

Minimum Viable Specification

Every feature specification should include at least these five elements:

# Feature: [Name]

## Problem
[What problem does this feature solve? Who experiences it?]

## User Stories
[Concrete scenarios from the user's perspective]
- As a [role], I can [action] so that [benefit]

## Acceptance Criteria
[Testable conditions that define "done"]
- Given [precondition], When [action], Then [expected result]

## Constraints
[What this feature must NOT do]
- Must not [constraint]

## Non-Goals
[What is explicitly out of scope for this iteration]
- Will not [non-goal]

Why Each Element Matters

Problem: Forces you to articulate why this feature exists. AI agents that understand the problem produce better solutions than AI agents that only know the feature name.

User Stories: Ground the specification in concrete usage scenarios. They prevent the common trap of building features that are technically correct but don't match how users actually work.

Acceptance Criteria: Define "done" in testable terms. These become the validation checklist after implementation and often translate directly into automated tests.

Constraints: Prevent AI from adding unwanted capabilities. Without explicit constraints, AI agents tend to over-generate — adding features that weren't requested and creating complexity that wasn't needed.

Non-Goals: Prevent scope creep. By explicitly stating what you're not building, you keep the AI focused and prevent it from solving adjacent problems.


Tutorial: Spec-First Feature Development

Let's build a feature using spec-first methodology. We'll create a bookmark system for a web application.

Step 1: Write the Specification

Before touching any code or AI tool, write the specification:

# Feature: Article Bookmarks

## Problem
Users find interesting articles but have no way to save them for later
reading. They resort to browser bookmarks which are unorganized and
not accessible across devices.

## User Stories
- As a logged-in user, I can bookmark an article by clicking a
bookmark icon on the article page
- As a logged-in user, I can view all my bookmarked articles in a
dedicated "Saved Articles" page, sorted by most recently bookmarked
- As a logged-in user, I can remove a bookmark from the article page
or from the "Saved Articles" page
- As a logged-in user, I can see a visual indicator (filled icon)
on articles I have already bookmarked

## Acceptance Criteria
- Given I am logged in and viewing an article I haven't bookmarked,
When I click the bookmark icon, Then the icon changes to filled
and the article appears in my Saved Articles
- Given I am logged in and viewing a bookmarked article, When I
click the bookmark icon, Then the icon changes to unfilled and
the article is removed from my Saved Articles
- Given I am not logged in, When I click the bookmark icon, Then
I am redirected to the login page
- Given I have 50 bookmarked articles, When I view Saved Articles,
Then they display paginated (20 per page) with most recent first

## API Design
- POST /api/bookmarks { article_id } → 201 Created
- DELETE /api/bookmarks/:article_id → 204 No Content
- GET /api/bookmarks?page=1 → 200 with paginated results

## Constraints
- A user cannot bookmark the same article twice (idempotent operation)
- Bookmarks are private — users cannot see other users' bookmarks
- Maximum 500 bookmarks per user (show "limit reached" message)

## Non-Goals
- No bookmark folders or categories (future iteration)
- No bookmark sharing or public bookmark lists
- No bookmark search or filtering (this iteration uses pagination only)
- No bookmark import/export

Step 2: Review the Specification

Before implementation, review your specification for completeness. Ask yourself:

  1. Could an AI implement this without asking questions? If any part requires guessing, add more detail.
  2. Are the acceptance criteria testable? Each criterion should have a clear pass/fail condition.
  3. Are the constraints explicit? Have you stated what should NOT happen?
  4. Are the non-goals clear? Will they prevent scope creep during implementation?

Step 3: Implement from the Specification

Now give the specification to your AI assistant:

"Here is a feature specification for an article bookmark system. Implement this specification exactly as written. Do not add features not listed in the specification. For each acceptance criterion, write a corresponding test. Use the API design exactly as specified."

Step 4: Validate Against the Specification

After receiving the implementation, check each element:

## Validation Checklist

### User Stories
- [ ] Can bookmark an article (click icon)
- [ ] Can view Saved Articles page (sorted by recency)
- [ ] Can remove bookmark (from article and from Saved page)
- [ ] Visual indicator on bookmarked articles

### Acceptance Criteria
- [ ] Bookmark adds article to saved list
- [ ] Un-bookmark removes article from saved list
- [ ] Not-logged-in redirects to login
- [ ] Pagination works with 50+ bookmarks

### Constraints
- [ ] Duplicate bookmark attempt is handled (idempotent)
- [ ] Bookmarks are user-scoped (no cross-user visibility)
- [ ] 500-bookmark limit enforced

### Non-Goals (should NOT be present)
- [ ] No folder/category system implemented
- [ ] No sharing functionality implemented
- [ ] No search/filter implemented
- [ ] No import/export implemented

The Drift Problem

Spec-first development has one significant limitation: specifications can drift from code over time.

After initial implementation, the team continues developing. New features are added, bugs are fixed, edge cases are handled. But these changes often happen in the code without updating the specification.

Week 1:  Spec says "max 500 bookmarks"
Code enforces 500-bookmark limit
✅ Aligned

Week 4: Customer requests higher limit
Developer changes code to 1000
Spec still says 500
⚠️ Drifted

Week 8: New developer reads spec
Implements related feature assuming 500 limit
Bug: feature breaks at 501 bookmarks
❌ Drift caused a bug

This drift is the primary weakness of spec-first development. The specification exists, but there's no automated mechanism to keep it aligned with the code.

Mitigating Drift

Several practices reduce drift:

  1. Spec review in pull requests: When code changes, require the corresponding spec update in the same PR.

  2. Spec-linked tests: Write tests that reference specification requirements. When tests change, the specification trigger is visible.

  3. Periodic spec audits: Schedule quarterly reviews where the team compares specifications to current system behavior.

  4. Change logs: Maintain a change log section in each specification that records when and why it was updated.

These mitigations help, but they rely on human discipline. The next maturity level — Spec-Anchored Development — solves drift through automation.


Maturity Assessment: Are You Spec-First?

Score your current workflow:

PracticePoints
Features have written specifications before coding begins+20
Specifications include acceptance criteria+15
Specifications include constraints and non-goals+10
AI receives the specification before generating code+15
Implementation is validated against the specification+15
Specifications are version-controlled alongside code+10
Specifications are updated when requirements change+10
New team members read specifications during onboarding+5

Scoring:

  • 0-20: Not spec-first. You're in code-first or vibe-coding mode.
  • 20-50: Partially spec-first. You write some specs but inconsistently.
  • 50-80: Solidly spec-first. You have the discipline but may suffer from drift.
  • 80-100: Advanced spec-first. You're ready to progress to spec-anchored.

Try With AI

Prompt 1: The Spec-First Challenge

"I want to practice spec-first development. Give me a feature idea, then challenge me to write the specification before you implement anything. After I write my spec, critique it for completeness, ambiguity, and testability. Only implement after my spec scores 8/10 or higher."

Prompt 2: Drift Detection

"I'm going to give you a specification and its corresponding implementation. Identify every place where the code has drifted from the specification — features added that aren't in the spec, constraints in the spec that aren't enforced in code, or behaviors that differ. Give me a drift report."

Prompt 3: Spec Refinement Dialogue

"Let's collaboratively refine a specification. I'll describe a feature in one sentence. You ask me clarifying questions — one at a time — until the specification is complete enough that you could implement it without guessing. After each question, show me the current state of the specification. Let's start: 'Users should be able to export their data.'"


Practice Exercises

Exercise 1: Retroactive Specification

Choose a feature in your current project that has no specification. Write one retroactively by reading the code and documenting what it actually does (not what you think it should do). Include acceptance criteria, constraints, and non-goals.

Expected outcome: The process will reveal undocumented business rules, inconsistent behaviors, and missing edge case handling.

Exercise 2: Before-and-After Comparison

Build the same feature twice: once with vibe coding (just tell the AI what you want informally) and once with a written specification. Compare the results on completeness, consistency, and production-readiness.

Expected outcome: The spec-first version will consistently score higher, particularly on edge case handling and constraint enforcement.

Exercise 3: Team Specification Review

Write a specification for a feature and have a colleague review it. Track every question they ask or ambiguity they identify. These are the same ambiguities that would cause an AI to guess — and potentially guess wrong.

Expected outcome: A list of 5-15 ambiguities per specification, demonstrating the value of specification review.


Key Takeaways

  1. Spec-first development is the entry point to SDD: write a specification before writing code. No special tools required.

  2. A minimum viable specification includes: problem, user stories, acceptance criteria, constraints, and non-goals.

  3. The specification acts as a communication protocol between you and your AI assistant, reducing implicit decisions and improving output quality.

  4. The primary weakness of spec-first is drift — specifications becoming outdated as code evolves without corresponding spec updates.

  5. A maturity assessment helps you understand where you are and what practices to adopt next.


Chapter Quiz

  1. What are the five elements of a minimum viable specification?

  2. Why are "non-goals" important in a specification?

  3. What is specification drift, and when does it typically begin?

  4. Name three practices that mitigate specification drift in spec-first development.

  5. A developer says: "Writing specs slows me down." How would you respond with evidence from this chapter?

  6. What's the difference between a constraint and a non-goal?

  7. Score your current project against the maturity assessment. What's your score?

  8. Why does a specification help AI produce better code, even though the AI is the same in both cases (with and without spec)?