Spec-Driven Development Workflow From Requirements to Code

Five phases from intent to verified code.

Page content

Spec-Driven Development works when the specification is a workflow, not a document you file away after kickoff. The point is not to produce a large product requirements document.

The point is to move through a sequence of reviewable artifacts that each reduce ambiguity before anyone – human or AI agent – changes production code.

If you do not know what SDD is conceptually, start with What Is Spec-Driven Development? for definitions, comparisons with TDD and BDD, and the case for treating the spec as source of truth. This article in the App Architecture documentation cluster is the operational guide. It walks through the five phases, shows what each artifact should contain, explains where AI agents fit, and gives reusable templates you can copy into your repository today.

Spec-driven development workflow – requirements, design, tasks, implementation, validation

SDD Is a Workflow, Not a Document

The most common failure mode in spec-driven development is treating the spec as paperwork. A team writes a long requirements document, stores it in a wiki, and then codes from memory and chat threads. The spec exists, but it does not drive anything. That is documentation theater, and it is worse than no spec because it creates false confidence.

A working SDD workflow produces a chain of artifacts, each reviewed before the next phase begins. Requirements reduce product ambiguity. Design reduces technical ambiguity. Tasks reduce execution ambiguity. Implementation produces code against a known target. Validation proves the chain held. When any phase reveals a mistake, you fix the artifact and re-run from that point – not after three thousand lines of drift have landed in main.

flowchart LR A[Specify] --> B[Plan] B --> C[Tasks] C --> D[Implement] D --> E[Validate] E -->|drift found| A E -->|ship| F[Done]

The workflow is tool-neutral. You can run it with markdown files in Git, with GitHub Spec Kit, with Cursor plans, or with a plain text editor and a disciplined reviewer. What matters is the sequence and the review gates, not the brand on the tooling.

Phase 1 – Specify the Requirements

The specify phase answers what problem you are solving and what done looks like. It deliberately avoids how to build it. The moment your requirements spec says “use Redis sorted sets,” you have stopped specifying and started designing in the wrong document. Keep implementation out of requirements. Put it in the plan.

Problem statement and users

Start with one paragraph that states the problem in plain language. Name the users affected and the situation that makes the problem painful. A good problem statement lets a reviewer who was not in the planning meeting decide whether a proposed solution actually addresses the pain.

Example for an API rate-limiting feature:

API consumers on the free tier can send unlimited requests, which causes cost spikes and noisy-neighbor impact on paid tenants. Platform operators need a enforceable per-key limit without manual intervention.

Goals, non-goals, and acceptance criteria

Goals describe outcomes you will deliver. Non-goals describe tempting adjacent work you will explicitly not do. Together they bound the agent’s creativity, which is essential when AI tools otherwise “helpfully” expand scope.

Section Good example Weak example
Goal Reject requests over the per-key limit with HTTP 429 Make the API faster
Non-goal Per-tenant billing dashboards Improve all API performance
Acceptance criterion Unauthenticated requests receive 401 before rate check runs The endpoint is secure

Acceptance criteria should be precise enough that each one maps to at least one test. “The endpoint is secure” is not an acceptance criterion. “Unauthenticated requests receive HTTP 401” is. If you cannot write a concrete criterion, the requirement is still too vague to implement.

Open questions

List every decision that is not yet settled. Unclear questions are not a sign of failure. They are the specify phase doing its job. Resolve them before you write the design plan, or you will pay for the ambiguity in implementation rework.

A minimal requirements template:

## Problem
[One paragraph: who hurts, why, and what triggers the pain.]

## Users
- [Primary user role]
- [Secondary user role]

## Goals
1. [Measurable outcome]
2. [Measurable outcome]

## Non-goals
- [Explicitly out of scope]
- [Explicitly out of scope]

## Acceptance criteria
- [ ] [Verifiable behavior]
- [ ] [Verifiable behavior]

## Open questions
- [ ] [Question that blocks planning]

Phase 2 – Plan the Design

The plan phase translates intent into technical decisions. This is where Redis sorted sets belong, along with module boundaries, schema changes, API contracts, migration steps, security constraints, and the test strategy. The plan is derived from the requirements spec plus your project’s existing constraints – stack choices, decision records, and conventions stored in files like AGENTS.md or a project constitution.

Architecture and affected modules

Name the modules, services, or packages that will change and summarize the integration pattern. If the feature crosses a service boundary, document the contract on both sides. Agents hallucinate APIs when contracts are implicit. Making them explicit in the plan prevents invented endpoints and wrong response shapes.

Data model, API contracts, and migrations

Document schema changes, new tables or fields, index requirements, and backward-compatibility rules. For HTTP APIs, write method, path, request shape, response shape, and error codes. For events, write topic names, payload schemas, and delivery semantics. Include migration steps and rollback notes when the data model changes.

Security, observability, and test strategy

Security constraints belong in the plan, not as afterthoughts in code review. Note authentication requirements, authorization rules, input validation boundaries, and data that must not appear in logs. Observability should cover metrics, logs, or traces needed to confirm the feature works in production.

The test strategy connects back to acceptance criteria. Identify which criteria need unit tests, which need integration tests, and which need manual verification. If you use unit testing in Go or unit testing in Python, name the packages and test files you expect to add. A plan without a test strategy is a plan that will ship with gaps you discover in production.

flowchart TB subgraph plan [Design plan contents] R[Requirements spec] C[Project constitution / ADRs] R --> D[Architecture decisions] C --> D D --> M[Data model and migrations] D --> A[API contracts] D --> S[Security constraints] D --> T[Test strategy] end

Phase 3 – Break Down Implementation Tasks

The task phase decomposes the plan into slices small enough to implement, review, and validate independently. This is what makes agent-assisted development reviewable. Instead of one enormous diff, you get a sequence of focused changes that each map back to a named requirement.

Task sizing and dependencies

A good task touches a bounded set of files, completes in one agent session, and ends with a verification step. Tasks should declare dependencies explicitly. Migration tasks run before code that reads the new schema. Shared library changes run before consumers. Authentication middleware changes run before endpoints that depend on the new behavior.

flowchart TD T1[Task 1 -- schema migration] --> T2[Task 2 -- repository layer] T2 --> T3[Task 3 -- HTTP handler] T2 --> T4[Task 4 -- metrics instrumentation] T3 --> T5[Task 5 -- integration tests] T4 --> T5

Files, validation, and review checkpoints

Each task should list the files likely to change, the acceptance criteria it satisfies, and how to validate completion. Validation might be a test command, a curl example, or a manual check described in copy-pasteable steps. Every task ends at a human review checkpoint. The reviewer confirms the diff matches the task description before the next task starts.

A minimal task entry:

### Task 3 -- Add rate-limit middleware

**Depends on:** Task 1 (schema), Task 2 (repository)
**Files:** middleware/ratelimit.go, middleware/ratelimit_test.go, server.go
**Satisfies:** AC-2 (429 over limit), AC-3 (limit headers in response)
**Validate:** `go test ./middleware/...` passes; curl over limit returns 429 with Retry-After
**Review checkpoint:** Confirm middleware runs after auth, before handler

Watch for generated task explosions. AI agents can produce fifty-task plans in seconds. Most of those tasks will be redundant or too granular to review efficiently. A useful task list for a medium feature often has five to fifteen items, not fifty.

Phase 4 – Implement One Task at a Time

Implementation is deliberately narrow. Pick one task, give the agent only the context it needs for that task, and stop when validation passes. Context resets between tasks are a feature, not a bug. They prevent earlier assumptions from polluting later work and keep diffs reviewable.

Apply constraints from the spec stack

The implementing agent should read the requirements spec, the design plan, the current task description, and project-level constraints. Constraints are the highest-ROI section most teams skip. They tell the agent what not to do – do not refactor unrelated modules, do not change public API signatures outside this feature, do not introduce new dependencies without updating the plan.

Update the plan when reality differs

Implementation will surface surprises. A library does not support the assumed behavior. A migration takes longer than expected. An edge case was missing from acceptance criteria. When that happens, update the spec before continuing. Fix the requirements or plan, get a quick review, then resume implementation against the corrected artifact. Code that diverges silently from the spec is how drift becomes permanent.

sequenceDiagram participant H as Human reviewer participant A as AI agent participant S as Spec artifacts H->>S: Approve task N A->>S: Read task + plan + constraints A->>A: Implement task N A->>A: Run task validation A->>H: Submit diff for review H->>H: Review diff against task alt drift or surprise H->>S: Update spec/plan H->>A: Re-run with corrected context else approved H->>S: Mark task N complete H->>A: Proceed to task N+1 end

Phase 5 – Validate Against the Spec

Validation is where SDD earns its keep. Without it, the spec is a planning exercise. With it, the spec is a contract you can check against the shipped code.

Automated checks

Run the full test suite, lint, and type checks on CI. Wire these into your pipeline using patterns from the GitHub Actions cheatsheet if you need a practical starting point. Automated checks catch regressions. They do not catch wrong features built correctly, which is why acceptance criteria review still matters.

Acceptance criteria and manual review

Walk through each acceptance criterion from the requirements spec. Mark each as satisfied, failed, or deferred with justification. Manual review catches UX issues, security gaps, and wrong behavior that tests missed because the tests were written to match a flawed spec.

Spec-to-code diff

The final validation step compares the implementation against the design plan. Did the files that changed match the files the plan predicted? Did architectural decisions in the code match the recorded decisions? Unexpected files in the diff are a signal – either the plan was incomplete or the agent wandered. Both deserve attention before merge.

Validation layer Catches
Unit and integration tests Regressions and incorrect logic within scope
Lint and type checks Style issues and type errors
Acceptance criteria walkthrough Wrong behavior built to spec
Spec-to-code diff Architectural drift and scope creep

Where AI Agents Fit in the Workflow

AI agents are accelerators on each phase, not replacements for review. The productive pattern is draft, review, refine, then proceed. Ask an agent to draft the requirements spec from a problem description, then edit intent until goals, non-goals, and acceptance criteria are right. Ask an agent to draft the design plan from the approved requirements, then review architecture decisions before any code exists. Ask an agent to implement one task slice at a time, with you approving each diff before the next task starts.

flowchart LR subgraph human [Human owns] H1[Intent and priorities] H2[Architecture approval] H3[Diff review at checkpoints] H4[Final acceptance] end subgraph agent [Agent accelerates] A1[Draft requirements] A2[Draft design plan] A3[Generate task list] A4[Implement task slices] A5[Draft tests] end H1 --> A1 --> H1 A1 --> A2 --> H2 H2 --> A3 --> A4 --> H3 H3 --> A4 A4 --> A5 --> H4

Agents are especially useful at producing first drafts and boilerplate tests. Humans are especially useful at catching wrong goals, unsafe architecture, and subtle scope creep. The workflow fails when either side is skipped – when agents implement without specs, or when humans write specs without ever validating them against code.

This workflow article stays tool-neutral on purpose. Tool-specific execution guides – editor setup, slash commands, agent configuration – belong under the AI Developer Tools cluster. The process pillar lives here under documentation practices because the artifacts matter more than the vendor.

Common Mistakes That Kill Spec-Driven Development

Huge specs before any validation. A thirty-page requirements document written before a prototype or spike is waterfall paperwork, not SDD. Write the minimum spec that removes ambiguity for the next phase, then validate assumptions early. Not every feature needs the full five-phase loop – Spec-Driven Development vs Vibe Coding explains when lighter structure is enough.

Vague acceptance criteria. Adjectives like “fast,” “clean,” and “user-friendly” are not acceptance criteria. Replace them with measurable behavior. If you cannot test it, you cannot implement it reliably – especially with an AI agent.

Missing non-goals. Without non-goals, agents expand scope by default. They add caching layers, refactor neighboring modules, and introduce dependencies you did not ask for. Non-goals are how you say no in advance.

No test plan in the design phase. Tests written only after implementation tend to confirm what was built, not what was intended. The plan should name which acceptance criteria map to which test types before the first production file changes.

Skipping review at phase boundaries. The spec reviewed before the plan. The plan reviewed before tasks. Tasks reviewed before implementation. Each gate is cheap. Fixing drift after a large merge is expensive.

Letting generated tasks explode. Treat a fifty-item AI-generated task list as a first draft, not a schedule. Merge redundant items, split oversized ones, and delete tasks that do not map to a requirement.

SDD works when each phase reduces ambiguity. It fails when it creates paperwork.

Reusable Templates

Copy these into your repository and adapt them. Store specs alongside the feature branch, review them in pull requests, and keep them in version control so agents and humans read the same source.

Requirements template

# Feature -- [name]

## Problem
## Users
## Goals
## Non-goals
## Acceptance criteria
## Open questions

Design template

# Design -- [feature name]

## Summary
## Affected modules
## Data model changes
## API contracts
## Migrations
## Security
## Observability
## Test strategy
## Risks and mitigations

Task list template

# Tasks -- [feature name]

## Task 1 -- [title]
Depends on:
Files:
Satisfies:
Validate:
Review checkpoint:

## Task 2 -- [title]
...

Validation checklist

# Validation -- [feature name]

## Automated
- [ ] All tests pass
- [ ] Lint clean
- [ ] Type check clean

## Acceptance criteria
- [ ] AC-1 --
- [ ] AC-2 --

## Spec-to-code
- [ ] Changed files match plan
- [ ] No undocumented architectural changes
- [ ] Spec updated if implementation differed

Conclusion

Spec-driven development is not about writing more documents. It is about moving through specify, plan, task, implement, and validate with a review gate at each step. Each phase should leave the next actor – human or agent – with less guesswork than the phase before.

Start small. Run the full workflow on one medium-sized feature. Keep artifacts in markdown in the repository. Update the spec when reality diverges. Validate before merge. When the chain works, you get less drift, smaller reviewable diffs, and a durable record of intent that survives session resets and team handoffs.

When the chain becomes paperwork, cut scope – not review. A two-page spec that was validated beats a thirty-page spec that nobody read.

Subscribe

Get new posts on AI systems, Infrastructure, and AI engineering.