Overview
Before writing any code, write a structured specification. The spec is the shared source of truth between you and the human engineer; it defines what we are building, why we are building it, and how we know it is done. Code without a spec is guessing.
When to use
- Starting a new project or feature
- Requirements are ambiguous or incomplete
- The change touches multiple files or modules
- You are about to make an architectural decision
- The task implementation will take more than 30 minutes
When not to use: One-line fixes, spelling corrections, or changes whose requirements are clear and self-contained.
Gated workflow
Spec-driven development has four phases, preceded by a scope check (Phase 0) that activates only when a request packages multiple independently testable capabilities. Do not proceed to the next phase until the current phase has been validated.
SPECIFY ──→ PLAN ──→ TASKS ──→ IMPLEMENT
│ │ │ │
▼ ▼ ▼ ▼
Human Human Human Human
reviews reviews reviews reviews
Phase 0: Scope Check
Most requests describe only one capability. If the current request is like that too, skip this phase and go directly to Specify. Phase 0 exists for the exception, not the norm; it does not impose hierarchy on single-capability features.
Detection. When a requirement packages multiple independently testable capabilities, decompose first, then specify:
- The requirement names multiple independent capabilities that each have their own consumers or data (for example identity, billing, notifications, reporting)
- Acceptance criteria cluster into groups that can be delivered and verified separately
- Cutting or replacing one capability does not require rewriting the requirements of the other capabilities
Before writing any spec, propose a capability map. Keep it small and reviewable: a module table plus a build order, not a project plan:
# Capability Map: [Initiative Name]
| Module id | Responsibility | Depends on |
|---|---|---|
| identity | Accounts, sessions, SSO | — |
| billing | Plans, invoices, payments | identity |
| notifications | Email and webhook fan-out | identity |
| reporting | Usage dashboards | billing, notifications |
Build order: identity → billing, notifications → reporting
- Stable module ids. kebab-case, chosen once, never renamed while the initiative is in progress. Specs, plans, and downstream commands all select work through these ids, rather than guessing which spec is currently in effect.
- Dependencies have direction, no cycles. Arrows point in only one direction. If two modules depend on each other, they are actually one module.
- Interfaces live at the boundaries. The map records
billingdependenciesidentity; the contract between them belongs to the spec of the provider module (for the design approach seeapi-and-interface-design)。
The map is gated like every other phase. Before writing any module spec, a human reviews the module boundaries, dependency direction, and build order. Getting the map wrong is expensive; reviewing ten lines is not.
Then recurse by module. In dependency order, run Specify → Plan → Tasks → Implement for each module. Each module has its own spec, scoped to that module's goals, boundaries, and success criteria. Keep the approved map at the project root, with the module specs alongside it, named by module id (SPEC-identity.md、SPEC-billing.md). The index that exists is this map, not guessing filenames.
Phase 1: Specify
Start from the high-level vision. Ask the human clarifying questions until the requirements are concrete.
Surface assumptions immediately. Before writing any spec content, list your assumptions:
ASSUMPTIONS I'M MAKING:
1. This is a web application (not native mobile)
2. Authentication uses session-based cookies (not JWT)
3. The database is PostgreSQL (based on existing Prisma schema)
4. We're targeting modern browsers only (no IE11)
→ Correct me now or I'll proceed with these.
Do not silently fill in ambiguous requirements. The entire purpose of a spec is, before the code is writtenbeforeexpose misunderstandings; assumptions are the most dangerous kind of misunderstanding.
Write a spec document covering these six core areas:
-
Objective: What are we building, and why? Who are the users? What does success look like?
-
Commands: Complete runnable commands, including flags, not just tool names.
Build: npm run build Test: npm test -- --coverage Lint: npm run lint --fix Dev: npm run dev -
Project Structure: Where does source code live, where do tests go, where does documentation belong.
src/ → Application source code src/components → React components src/lib → Shared utilities tests/ → Unit and integration tests e2e/ → End-to-end tests docs/ → Documentation -
Code Style: One real code snippet showing the style is worth three paragraphs of description. Include naming conventions, formatting rules, and examples of excellent output.
-
Testing Strategy: What framework to use, where tests go, coverage expectations, which concerns map to which test levels.
-
Boundaries: Three-tier system:
- Always do: Run tests before committing, follow naming conventions, validate input
- Ask first: Database schema changes, adding dependencies, modifying CI configuration
- Never do: Committing secrets, editing the vendor directory, removing failing tests without approval
Spec template:
# Spec: [Project/Feature Name]
## Objective
[What we're building and why. User stories or acceptance criteria.]
## Tech Stack
[Framework, language, key dependencies with versions]
## Commands
[Build, test, lint, dev — full commands]
## Project Structure
[Directory layout with descriptions]
## Code Style
[Example snippet + key conventions]
## Testing Strategy
[Framework, test locations, coverage requirements, test levels]
## Boundaries
- Always: [...]
- Ask first: [...]
- Never: [...]
## Success Criteria
[How we'll know this is done — specific, testable conditions]
## Open Questions
[Anything unresolved that needs human input]
External spec tools: This workflow is format-agnostic. If the project already uses OpenSpec or another spec system, keep that system's artifact format and storage conventions, and do not create another duplicate SPEC.md. This skill handles clarification, content, and approval gates; external tools handle the representation of approved specs.
Reframe instructions as success criteria. When you receive ambiguous requirements, translate them into concrete conditions:
REQUIREMENT: "Make the dashboard faster"
REFRAMED SUCCESS CRITERIA:
- Dashboard LCP < 2.5s on 4G connection
- Initial data load completes in < 500ms
- No layout shift during load (CLS < 0.1)
→ Are these the right targets?
This way you can loop, retry, and problem-solve around clear goals instead of guessing what "faster" means.
Phase 2: Plan
After the spec has been verified, generate a technical implementation plan:
- Identify the main components and their dependencies
- Determine the implementation order (what must be built first)
- Document risks and mitigation strategies
- Identify what can be built in parallel and what must be done sequentially
- Define validation checkpoints between phases
For the dependency graph mapping and vertical slicing mechanics behind these steps, follow
planning-and-task-breakdown; it is the authoritative source. The bullet points above are only a lightweight summary; if the two diverge,planning-and-task-breakdowntakes precedence.Output conventions: Save the plan to
tasks/plan.md, and record the task list toplanning-and-task-breakdownthe task list target defined by (defaulttasks/todo.md; projects can also specify an external tracker). Iftasks/does not exist, create it. Downstream commands (/build, etc.) depend on these defaults.
The plan should be reviewable: a human should be able to read it and say "yes, this is the right approach" or "no, change X".
Phase 3: Tasks
Break the plan down into discrete, actionable tasks:
- Each task should be completable in one focused session
- Each task has clear acceptance criteria
- Each task includes verification steps (tests, build, manual checks)
- Tasks are ordered by dependency, not by perceived importance
- No task should require modifying more than about 5 files
The complete task sizing and dependency ordering mechanism follows
planning-and-task-breakdown; it is the authoritative source. The template below is only a lightweight inline form; if the two diverge,planning-and-task-breakdownprevails.
Task template:
- [ ] Task: [Description]
- Acceptance: [What must be true when done]
- Verify: [How to confirm — test command, build, manual check]
- Files: [Which files will be touched]
Phase 4: Implement
Execute one task at a time, and follow skills/incremental-implementation/SKILL.md(incremental-implementation) and skills/test-driven-development/SKILL.md(test-driven-development). Use skills/context-engineering/SKILL.md(context-engineering) to load the correct spec sections and source files at each step, instead of stuffing the entire spec into the agent.
Keep the Spec Alive
The spec is a living document, not a one-time artifact:
- Update when decisions change: if you discover the data model needs to change, update the spec first, then implement.
- Update when scope changes: features added or cut should be reflected in the spec.
- Commit the spec: the spec should go into version control alongside the code.
- Reference the spec in PRs: link back to the spec section implemented by each PR.
Common Rationalizations
| Rationalization | Reality |
|---|---|
| "This is simple, I don't need a spec" | Simple tasks don't need along spec, but they still need acceptance criteria. A two-line spec is fine. |
| "I'll add the spec after I write the code" | That's documentation, not a specification. The value of a spec is forcing clarification before the code. |
| "Specs slow us down" | A 15-minute spec can avoid hours of rework. 15 minutes of waterfall beats 15 hours of debugging. |
| "Requirements will change anyway" | That's exactly why the spec is a living document. An outdated spec is still better than no spec. |
| "Users know what they want" | Even clear requests have implicit assumptions. A spec exposes those assumptions. |
| "This is a big feature, splitting it up is extra overhead" | If acceptance criteria can be grouped into independently testable sets, a monolithic spec forces every downstream task to reason over the full contract. A ten-line capability map is the cheaper alternative. |
| "I'll break it down during planning" | Planning is about splitting tasks within a single spec. By then the oversized artifact already exists—module boundaries and dependency direction must be decided before writing the spec, not after. |
Red Flags
- Starting to write code without any written requirements
- Asking "Should I just start building?" before clarifying what "done" means
- Implementing any feature not mentioned in the spec or task list
- Making architectural decisions without recording them
- Skipping the spec because "it's obvious what to build"
- A single spec whose requirements span multiple independently testable capabilities
- Module boundaries or build order being decided implicitly during implementation because there was no pre-approved capability map
Verification
Before entering implementation, confirm:
- The spec covers all six core areas
- A human has reviewed and approved the spec
- Success criteria are specific and testable
- Boundaries (Always/Ask First/Never) defined
- spec saved to a file in the repository
- If the request bundles multiple independently testable capabilities, the capability map (module id, dependency direction, build order) has been approved before writing any module spec
- Each module spec is traceable to a module id in the approved map