---
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/`.

## Prerequisites

- Read `./templates/requirements-template.md`, `./templates/design-template.md`, `./templates/tasks-template.md`, and `./templates/contract-template.md` before starting — they define the section structure
- Read `@docs/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`.

1. Ask the developer to describe the feature in 2-5 sentences (or accept what they've already provided)
2. 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.
3. Draft the **Goal & Context** section — focus on the problem, not the solution
4. Draft **Requirements** using EARS notation: `WHEN [condition] THE SYSTEM SHALL [behavior]`. Assign stable IDs (R1, R2, …)
5. Draft **Non-Goals** — ask: "What should this feature explicitly NOT do?"
6. 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`.

1. Propose a **Building Blocks Diff** — list every block that is ADDED, MODIFIED, or DELETED. Use the project's building block taxonomy from `.agents/skills/building-blocks/SKILL.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.
2. **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.
3. **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-template.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:
   1. **Multiple states & transitions** — the block moves through several discrete states with conditional or guarded transitions.
   2. **Structured internal state** — more than a couple of flat fields: derived values, interdependent fields, or normalized collections.
   3. **Branching domain logic** — conditional rules, invariants, or multi-step computation where the rules themselves are the design.
   4. **Cross-slice coordination** — behavior depends on wiring into another feature or sub-feature slice; the seam (callback, slot, render-prop) needs design.
   5. **No canonical pattern** — the block matches no established pattern the agent can look up, so its shape must be designed from scratch.

4. For non-trivial features, propose **two plausible designs** with tradeoffs. Let the developer choose. Capture the winner and rationale in **Design Decisions**
5. 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)
6. 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`.

1. 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)
2. Draft **Error & Edge Cases** using GIVEN/WHEN/THEN — cover failure modes (including fetch errors for data-fetching components), boundary conditions, concurrency
3. Add **Open Questions** for anything unresolved that blocks a specific task
4. Present `tasks.md` for review

### Phase 4 — Review & Finalize

1. 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
2. Fix any issues found in step 1 before proceeding
3. Set status to `review` in each Meta table
4. 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
- 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

```markdown
### Added

- `loginMutation` (mutation) — handles POST /auth/login
- `LoginForm` (component) — email/password form with validation
```

### ❌ Wrong: Building block with implementation details

````markdown
### 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

```markdown
- **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:

- [ ] Every section marked REQUIRED in each template is filled
- [ ] Every requirement has a stable ID and uses EARS notation
- [ ] Every task traces to ≥1 requirement ID
- [ ] Building blocks reference name + type only, no implementation details
- [ ] Boundaries use specific file paths, not vague categories
- [ ] Open questions are either resolved or explicitly block named tasks
- [ ] Developer has approved the final spec (status set to `approved`)
- [ ] Every proposed-and-approved contract is filled and linked from `design.md`
- [ ] File sizes within caps: `requirements.md` ≤50, `design.md` ≤80, `tasks.md` ≤70, combined ≤200 lines; each contract ≤80 lines (excluded from the combined cap)

## References

- `.agents/skills/building-blocks/SKILL.md` — building block type dictionary (names, descriptions, when to use each)
- `./templates/requirements-template.md`, `./templates/design-template.md`, `./templates/tasks-template.md`, `./templates/contract-template.md` — section structure and inline guidance
- `@docs/architecture.md` — project structure, architectural decisions, conventions
