| name | writing-spec |
| description | Collaboratively write a feature spec with the developer. Trigger when a task involves 5+ unconstrained decisions, spans 10+ files, or the developer explicitly asks for a spec. Do NOT trigger for config edits, CSS fixes, helper functions, exploratory prototyping, presentation-only changes, or when the developer explicitly opts out. |
Purpose
Guide the developer through writing a feature spec before any code is written. The spec constrains intent and approach so implementation decisions are explicit, reviewed, and traceable. This skill produces three files in specs/NNN-feature-name/ — requirements.md, design.md, tasks.md — using the templates in ./templates/, plus an optional contracts/ directory of design fragments for individually complex building blocks.
Prerequisites
- Read
./templates/requirements.md, ./templates/design.md, ./templates/tasks.md, and ./templates/contract.md before starting — they define the section structure
- Read
@.spec-kit/architecture.md to understand current building block types and project structure
- Determine the next available sequence number by checking both
specs/ directory listings AND git log for prior spec-related commits — use the higher of the two
Workflow: Four Phases with Gates
Each phase ends with a human review gate. Do NOT advance to the next phase without explicit developer approval ("continue", "ok", "next", "looks good", or similar). If something goes wrong, STOP and re-plan — do not push forward.
Phase 1 — Goal & Scope (Intent)
Collaborate with the developer to fill requirements.md.
- Ask the developer to describe the feature in 2-5 sentences (or accept what they've already provided)
- Before drafting, ask 3-5 clarifying questions about scope boundaries, error scenarios, and unstated assumptions — only where the answer would change the spec. Skip obvious ones.
- If the feature introduces new API calls (queries or mutations): explicitly ask which server-side error responses each call must handle, and how the UI should react to each.
- Draft the Goal & Context section — focus on the problem, not the solution
- Draft Requirements using EARS notation:
WHEN [condition] THE SYSTEM SHALL [behavior]. Assign stable IDs (R1, R2, …)
- Draft Non-Goals — ask: "What should this feature explicitly NOT do?"
- Present
requirements.md for review
What to ask if unclear: "What's the observable user behavior when this works correctly?" Never invent requirements — if the developer hasn't specified a behavior, ask about it.
Phase 2 — Design (Approach)
Collaborate on design.md.
-
Propose a Building Blocks Diff — list every block that is ADDED, MODIFIED, or DELETED. Use the project's building block taxonomy from ./building-blocks/catalog.md. Reference by name and type only — do not define internals. Implementation details belong in coding standards and per-type skills, not specs. For changes that don't map to a typed building block, use the target file path + a short description instead.
-
Cross-slice concerns — ask whether any new block needs to interact with another feature or sub-feature slice. If yes, decide the wiring point (parent feature or page) and injection mechanism (callback, render prop, slot) in the design — don't defer to implementation.
-
Identify contract candidates. For each block in the diff, check the signal checklist below. For every block hitting ≥1 signal, present an inline proposal — one line each: `blockName` (type) — <signal(s) hit>; design problem: <one phrase>. The developer approves/rejects each. For approved blocks, create specs/NNN-feature-name/contracts/{block-slug}.md (slug = block name kebab-cased per code-style.md; on a slug collision, suffix the type, e.g. review-form-store.md) from ./templates/contract.md, and add a contract link to that block's design.md Building Blocks Diff entry. Contracts are signal-driven, not type-driven — most blocks hit zero signals and get nothing. If no block hits a signal, skip this step entirely: no contracts/ directory, no proposals. When a block hits a signal but the developer rejects the proposal (or you judge it trivial), record the skip reason inline in that block's design.md entry — e.g. `fooStore` (store) — contract skipped: shape is flat.
Signals — a block warrants a contract proposal if ≥1 holds. Signals describe properties of the design problem, not block types:
- Multiple states & transitions — the block moves through several discrete states with conditional or guarded transitions.
- Structured internal state — more than a couple of flat fields: derived values, interdependent fields, or normalized collections.
- Branching domain logic — conditional rules, invariants, or multi-step computation where the rules themselves are the design.
- Cross-slice coordination — behavior depends on wiring into another feature or sub-feature slice; the seam (callback, slot, render-prop) needs design.
- No canonical pattern — the block matches no established pattern the agent can look up, so its shape must be designed from scratch.
-
For non-trivial features, propose two plausible designs with tradeoffs. Let the developer choose. Capture the winner and rationale in Design Decisions
-
Draft the Boundaries section using the three-tier system:
- ✅ Always — proceed without asking (e.g., create files in the feature directory)
- ⚠️ Ask first — needs approval (e.g., modify API contracts, change schema, create shared utilities)
- 🚫 Never — hard stops (e.g., modify core auth, remove tests, commit secrets)
-
Present design.md for review
Critical rule for building blocks: Reference names and types. Do NOT define contracts, interfaces, or implementation — those live in separate coding-standards skills and existing code. The spec describes a CHANGE to the status quo. The agent reads relevant code to see the current status quo.
Phase 3 — Spec (Sequencing)
Fill tasks.md.
- Break work into a Task Breakdown — ordered, independently testable tasks. Each task:
- References building blocks from
design.md if any are involved
- Traces to requirement IDs (R1, R2, …)
- Includes target file paths
- Is marked
[P] (parallelizable) or [S] (sequential)
- Draft Error & Edge Cases using GIVEN/WHEN/THEN — cover failure modes (including fetch errors for data-fetching components), boundary conditions, concurrency
- Add Open Questions for anything unresolved that blocks a specific task
- Present
tasks.md for review
Phase 4 — Review & Finalize
- Run a structured self-audit and present findings to the developer (don't silently verify — show the results):
- Coverage matrix: for each requirement ID, list which task(s) implement it. Flag any requirement with zero tasks
- Orphan tasks: flag any task that doesn't trace back to a requirement ID
- EARS compliance: flag any requirement missing WHEN/THE SYSTEM SHALL or using vague language ("handle properly", "work correctly")
- Boundary specificity: flag any boundary item (✅/⚠️/🚫) that references a vague category instead of a file path or module name
- Building block references: flag any block in
design.md that doesn't exist in the building-blocks catalog — acceptable without a catalog match if the block has a contract (signal 5, no canonical pattern); flag it only if it lacks both
- Contract coverage: every contract file links back from a
design.md block entry; every design.md block that hits a signal either has a contract or an inline skip reason in its entry
- Line count: report each file's count and the combined total. Caps:
requirements.md ≤50, design.md ≤80, tasks.md ≤70, combined ≤200. Contracts are excluded from the combined cap — report each contract's count separately, ≤80 each. If any cap is exceeded, identify which section to compress or extract
- Contract count: no hard cap — report the count. A high count (e.g. >3) signals the feature should be split into separate specs; surface it, don't enforce it
- Fix any issues found in step 1 before proceeding
- Set status to
review in each Meta table
- Present the audit results and the final spec for developer sign-off
Rules & Constraints
What the agent MUST do
- ALWAYS read the three template files in
./templates/ before drafting
- For building-block decisions, route through
./building-blocks/catalog.md; for test decisions, route through ./test-building-blocks/catalog.md
- ALWAYS use EARS notation for requirements and GIVEN/WHEN/THEN for edge cases
- ALWAYS assign stable IDs to requirements (R1, R2, …) — tasks reference these for traceability
- ALWAYS include the three-tier boundary system (✅ / ⚠️ / 🚫) with specific paths
What the agent MUST NOT do
- NEVER invent requirements the developer hasn't stated or confirmed — ask instead
- NEVER define building block internals (interfaces, schemas, implementation) in
design.md — reference name + type only. Internals/pseudocode for complex blocks belong in contracts/; contracts are the one sanctioned place for block-shape detail in a spec
- NEVER duplicate a decision across
design.md and a contract — cross-block decisions go in design.md Design Decisions; intra-block shape rationale goes in the contract
- NEVER skip a review gate — each phase needs explicit developer approval
- NEVER conflate spec layers: requirements constrain intent, design constrains approach, tasks constrain sequencing. Keep them separate
- NEVER add boilerplate boundaries — every item in ✅/⚠️/🚫 must be reachable during implementation of this specific feature
Prefer
- Prefer concise specs (combined ~200 lines: requirements ≤50, design ≤80, tasks ≤70) over exhaustive ones — the curse of instructions means longer specs get followed less reliably. Contracts are excluded from the ~200 combined cap and capped individually at ≤80 lines
- Prefer mechanical enforcement (lint, tests, schemas) over prose rules — if a constraint can be a linter rule, it doesn't belong in the spec
- Prefer two design options with tradeoffs over a single "obvious" choice — this surfaces assumptions
- Prefer specific file paths in boundaries over vague module names
Anti-Patterns
- Spec that's actually a task list — "first create the model, then add the service" constrains sequencing but not intent. The agent follows every step and still builds the wrong thing. Fix: write requirements first, derive tasks from them
- Over-specification that becomes code — if the spec includes TypeScript interfaces, database DDL, or code snippets, it has crossed from "what" into "how." Move those to design docs or coding standards
- Under-specification that forces guessing — if a requirement says "handle errors gracefully" without specifying which errors and what "gracefully" means, the agent will guess. Fix: use GIVEN/WHEN/THEN for every error scenario
- Auto-generated specs — LLM-generated context files have been shown to reduce task success rates. The developer drives content; the agent structures and challenges it
- Markdown review trap — if any file exceeds its cap (requirements 50 / design 80 / tasks 70) or the combined spec exceeds ~200 lines, the review cost may exceed the value. Split the feature or compress the spec
Examples
✅ Correct: Building block reference
### Added
- `loginMutation` (mutation) — handles POST /auth/login
- `LoginForm` (component) — email/password form with validation
❌ Wrong: Building block with implementation details
### Added
- `loginMutation` (mutation):
```typescript
export const loginMutation = {
mutationFn: (data: LoginData) => api.post("/auth/login", data),
onSuccess: (response) => {
authStore.setToken(response.token);
},
};
```
Why wrong: the spec now contains code. The mutation's internals are governed by coding standards, not the feature spec.
### ✅ Correct: EARS requirement
```markdown
- **R3**: WHEN the login form is submitted with an empty email field, THE SYSTEM SHALL display an inline validation error without making an API call.
❌ Wrong: Vague requirement
- **R3**: The form should validate inputs properly.
Why wrong: "properly" is undefined — the agent will guess what validations to apply and what "proper" error display looks like.
Exit Criteria
The spec is ready for implementation when:
References
./building-blocks/catalog.md — building block type dictionary (names, descriptions, when to use each); rule files under ./building-blocks/blocks/
./test-building-blocks/catalog.md — test block dictionary; rule files under ./test-building-blocks/blocks/
./templates/requirements.md, ./templates/design.md, ./templates/tasks.md, ./templates/contract.md — section structure and inline guidance
@.spec-kit/architecture.md — project structure, architectural decisions, conventions