Friday, September 11, 2026

Spec-Driven Development: Building Software from a Clear Specification

See All on GenAI    « Previously

Spec-Driven Development: Building Software from a Clear Specification

A practical guide to SDD, using VS Code and GitHub Copilot, and how it differs from vibe coding.

AI coding assistants have changed the way software is built. Instead of writing every line of code manually, developers can describe what they want and let an AI assistant generate much of the implementation. But there is an important question: what exactly should the AI build?

This is where Spec-Driven Development (SDD) comes in. Rather than starting with code or an informal conversation with an AI assistant, SDD starts with a clear description of the desired behavior, requirements, constraints, interfaces, and acceptance criteria. The specification becomes the source of truth that guides both the developer and the AI coding agent.

The central idea In Spec-Driven Development, you don't primarily tell the AI, "Write some code that does this." You first establish what the software must do, then use the specification to drive the design, implementation, testing, and review.

1. What Is Spec-Driven Development?

Spec-Driven Development is a software development approach in which a written specification acts as the primary guide for creating a feature or system.

The specification describes the intended outcome before implementation begins. Depending on the project, it can contain functional requirements, user stories, API contracts, data models, business rules, constraints, edge cases, non-functional requirements, and acceptance criteria.

The important distinction is that the specification is not merely documentation written after the code. It is an input to the development process.

A simple example

Imagine that you want to add a password-reset feature to an application. A vague instruction might be:

Build a password reset feature.

An AI coding assistant can certainly generate code from this instruction. However, many important questions remain unanswered:

  • How long should a reset link remain valid?
  • Can a reset token be used more than once?
  • What happens when the email address does not exist?
  • How should expired tokens behave?
  • What password rules apply?
  • Should the system reveal whether an email address is registered?
  • What tests must pass before the feature is considered complete?

A specification makes these decisions explicit before implementation.

Feature: Password Reset

Requirements:
1. A user can request a password reset using their email address.
2. The reset token expires after 30 minutes.
3. A token can be used only once.
4. Invalid or expired tokens must be rejected.
5. The system must not reveal whether an email address is registered.
6. The new password must satisfy the application's password policy.

Acceptance criteria:
- Valid reset requests produce a reset email.
- Expired tokens are rejected.
- Reused tokens are rejected.
- Invalid tokens are rejected.
- Successful reset invalidates the token.

Now the implementation has something much more useful than a general instruction: it has a contract to satisfy.

2. Why SDD Matters in AI-Assisted Development

Traditional development already benefits from requirements and design documents. AI-assisted development makes this discipline even more important.

An AI coding assistant can generate code extremely quickly. That is both its strength and its weakness. If the instructions are vague, the assistant can produce a large amount of code that is technically plausible but does not actually solve the intended problem.

SDD addresses this by moving more attention toward the problem definition before asking AI to perform the implementation.

1 Specify Define what must be built.
2 Clarify Resolve ambiguity and edge cases.
3 Plan Decide how the specification will be implemented.
4 Implement Use AI to generate and modify code.
5 Verify Test the implementation against the specification.

Notice that code comes after specification. AI is not removed from the process; instead, its role changes from guessing what you want to implementing a clearly defined requirement.

3. How SDD Can Be Done Using VS Code and GitHub Copilot

VS Code and GitHub Copilot can support an SDD workflow by keeping the specification close to the code and using it as context for AI-assisted planning, implementation, and verification.

The exact Copilot capabilities and interface can evolve over time, but the underlying workflow remains straightforward: write the specification, give the specification to the coding agent, review the plan, implement incrementally, and verify against the requirements.

Step 1: Create a specification

Start by creating a specification file in the repository. The format is less important than the clarity of the content. Markdown is often convenient because it is readable by both humans and AI tools.

docs/specs/password-reset.md

A useful specification should answer questions such as:

  • What problem are we solving?
  • Who is the feature for?
  • What behavior is required?
  • What behavior is explicitly not required?
  • What constraints must be respected?
  • What are the important edge cases?
  • How will we know the implementation is correct?

Step 2: Ask Copilot to analyze the specification

Instead of immediately asking Copilot to write code, ask it to understand and analyze the specification first.

Read docs/specs/password-reset.md.

Analyze the requirements and identify:
- ambiguities
- missing edge cases
- affected parts of the existing codebase
- likely implementation constraints
- tests that will be required

Do not modify any files yet.

This is an important SDD habit: separate understanding from implementation.

Step 3: Ask Copilot for an implementation plan

Once the specification is clear, ask Copilot to create a plan.

Using docs/specs/password-reset.md as the source of truth,
create an implementation plan.

For each step:
- identify the files that need to change
- explain what will change
- identify dependencies
- identify tests that should be added

Do not implement the changes yet.

The plan gives the developer an opportunity to catch incorrect assumptions before code is generated.

Step 4: Review the plan

This is where human judgment becomes particularly important.

Ask questions such as:

  • Does the plan actually satisfy every requirement?
  • Did Copilot misunderstand any business rule?
  • Is the proposed design consistent with the existing architecture?
  • Are security and performance constraints being considered?
  • Are the tests sufficient?

If the plan is wrong, fix the specification or clarify it before implementation begins.

Step 5: Implement in small increments

Instead of giving Copilot one enormous request such as "build the entire feature," work through the plan incrementally.

Implement step 1 from the approved plan.

Use the password-reset specification as the source of truth.
Do not modify unrelated functionality.

After making the changes, explain:
- what changed
- which requirements are now satisfied
- what remains to be implemented

Smaller changes make AI-generated code easier to review, test, and revert.

Step 6: Generate and run tests

Tests should not be an afterthought. The acceptance criteria in the specification should translate into concrete verification.

Review the acceptance criteria in
docs/specs/password-reset.md.

Identify any missing automated tests and add them.
Then run the relevant test suite.

Report:
- tests added
- tests executed
- failures
- requirements that remain unverified

This creates a useful feedback loop:

Specification
      ↓
Implementation plan
      ↓
Code
      ↓
Tests
      ↓
Verification against specification
      ↓
Refinement

Step 7: Keep the specification synchronized

Software changes. Requirements can change too. If the implementation evolves but the specification does not, the repository eventually contains two conflicting sources of truth.

Therefore, when a requirement changes, update the specification deliberately and then update the implementation to match it.

A useful rule: If a behavior matters enough to test or review, it probably matters enough to express clearly in the specification.

4. SDD vs. Vibe Coding

Vibe coding generally describes an AI-assisted development style where the developer gives natural-language instructions, accepts generated code, observes the result, and continues prompting based on what happens.

Vibe coding can be surprisingly productive for prototypes, experiments, throwaway projects, and situations where the cost of being wrong is low.

The problem appears when the same approach is used for software that has important requirements, dependencies, security implications, or long-term maintenance needs.

Aspect Spec-Driven Development Vibe Coding
Starting point A defined specification and acceptance criteria. A natural-language idea or desired outcome.
AI's role Implement and verify against explicit requirements. Generate and refine code through conversational prompts.
Planning Planning is explicit and reviewed before implementation. Planning may emerge during the interaction.
Requirements Made explicit and traceable. Often implicit in the conversation.
Verification Measured against defined acceptance criteria. Often based on whether the result appears to work.
Change management Changes can be reflected in the specification first. Changes may happen through successive prompts.
Best suited for Production systems and requirements-heavy work. Prototypes, exploration, learning, and low-risk experiments.

The key difference

The difference is not simply "writing specifications versus talking to AI." The deeper difference is where the source of truth lives.

In a vibe-coding workflow, the developer's evolving conversation with the AI can become the effective source of truth.

In SDD, the specification is deliberately made explicit so that the developer, AI, reviewer, and tests can all refer to the same intended behavior.

SDD does not mean "never vibe." You can use conversational AI during an SDD workflow. The difference is that the conversation operates within clearly defined requirements rather than replacing them.

5. What to Do in Spec-Driven Development

✓ Do

  • Write requirements before implementation.
  • Define acceptance criteria that can actually be verified.
  • Document important business rules and constraints.
  • Identify edge cases explicitly.
  • Ask Copilot to analyze before asking it to implement.
  • Review AI-generated implementation plans.
  • Implement incrementally.
  • Keep tests aligned with the specification.
  • Review generated code instead of blindly accepting it.
  • Update the specification when requirements change.

✗ Don't

  • Assume AI understands unstated business requirements.
  • Write huge specifications full of unnecessary implementation details.
  • Ask AI to change the entire codebase without boundaries.
  • Treat generated code as automatically correct.
  • Skip tests because the AI says the feature is complete.
  • Allow the specification and implementation to drift apart.
  • Ignore security, performance, or compatibility constraints.
  • Use the specification as an excuse to stop thinking critically.
  • Accept a technically elegant solution that violates the requirements.

6. What Makes a Good Specification?

A good specification should be clear enough to remove important ambiguity without becoming an unnecessarily detailed implementation manual.

For example, instead of specifying every class and method that an AI must create, describe the behavior those components must provide.

Less useful:

Create a PasswordResetService class with a ResetPassword()
method that uses a Dictionary to store tokens.

More useful:

Requirements:
- Generate a cryptographically secure reset token.
- Associate the token with the requesting account.
- Expire the token after 30 minutes.
- Permit a token to be consumed only once.
- Reject invalid and expired tokens.

The second version describes what must be true while leaving room for the implementation to choose an appropriate design.

A practical specification structure

# Feature: Password Reset

## Problem
Users need a secure way to regain access to their account.

## Goal
Allow users to reset their password without administrator intervention.

## Functional Requirements
- ...
- ...
- ...

## Constraints
- ...
- ...
- ...

## Edge Cases
- ...
- ...
- ...

## Acceptance Criteria
- ...
- ...
- ...

## Out of Scope
- ...
- ...

## Verification
- Unit tests
- Integration tests
- Security checks

This structure is simple enough for humans to maintain and structured enough to provide useful context to an AI coding agent.

7. Keep the Specification Focused on Outcomes

One of the easiest mistakes in SDD is turning the specification into a detailed description of the code you have already imagined.

Specifications are generally more valuable when they focus on behavior, requirements, constraints, and outcomes.

For example:

Good:
"The API must return HTTP 404 when the requested product does not exist."

Less useful:
"Create ProductController.GetProduct(), then call ProductRepository.Find()
and return NotFound()."

The first statement defines an externally observable requirement. The second prescribes one particular implementation.

This distinction gives both the developer and AI more flexibility while preserving correctness.

8. SDD Is Not About Writing More Documentation

It is tempting to think that SDD simply means producing more documents. That misses the main point.

The purpose of a specification is to create a shared, explicit contract between the problem, the developer, the AI agent, and the verification process.

A short specification containing ten precise requirements can be more useful than a fifty-page document containing vague prose.

The goal is not documentation for documentation's sake. The goal is to reduce ambiguity.

9. A Practical SDD Workflow for Everyday Development

For a typical feature, you can use the following lightweight workflow in VS Code:

  1. Create a feature specification. Describe the problem, requirements, constraints, edge cases, and acceptance criteria.
  2. Ask Copilot to review it. Have it identify ambiguity, missing cases, and affected parts of the codebase.
  3. Resolve questions. Update the specification until the intended behavior is clear.
  4. Generate an implementation plan. Ask Copilot to propose changes without modifying files.
  5. Review the plan. Confirm that it addresses the specification and fits the existing architecture.
  6. Implement incrementally. Give Copilot one logical part of the approved plan at a time.
  7. Test continuously. Add and run tests derived from the acceptance criteria.
  8. Perform a final specification review. Check that every requirement has been implemented and verified.

This approach preserves one of the biggest advantages of AI coding assistants—speed—while reducing the risk that speed turns into uncontrolled complexity.

10. The Human Developer Still Matters

SDD should not be interpreted as handing the specification to an AI and stepping away.

The developer remains responsible for deciding what the software should do, evaluating trade-offs, understanding the architecture, reviewing the generated implementation, and determining whether the result is safe and correct.

In fact, AI-assisted SDD can make the developer's role more strategic. Instead of spending all of their time typing implementation details, developers can spend more time defining problems, making design decisions, reviewing results, and validating behavior.

Think of the division of labor this way: The human defines the desired outcome and constraints. The AI helps explore and implement solutions. Tests and reviews provide evidence that the implementation actually satisfies the specification.

11. Final Takeaway

Spec-Driven Development is a natural evolution of software development in an age where AI can generate code much faster than humans can manually write it.

The bottleneck increasingly shifts from "How quickly can we write the code?" to "How clearly have we defined what the code should accomplish?"

SDD answers that question by putting the specification at the center of the workflow:

Define the problem
       ↓
Write the specification
       ↓
Clarify requirements
       ↓
Create an implementation plan
       ↓
Review the plan
       ↓
Implement with AI assistance
       ↓
Test
       ↓
Verify against the specification
       ↓
Iterate

Vibe coding can be excellent for discovering possibilities and quickly creating prototypes. But when correctness, maintainability, security, and predictable behavior matter, relying on an evolving conversation alone can become risky.

Spec-Driven Development does not eliminate the speed of AI-assisted coding; it gives that speed direction.

The One-Sentence Definition

Spec-Driven Development is an AI-assisted development approach in which a clear, explicit specification defines the intended behavior first, and the implementation, tests, and review are driven by that specification.


See All on GenAI    « Previously

No comments:

Post a Comment