| name | writing-plans |
| description | Use when you have a spec or requirements for a multi-step task, before touching code |
Writing Plans
Overview
Write comprehensive plans for skilled engineers unfamiliar with your codebase and domain. Every detail explicit — no placeholders, no "TBD". Bite-sized tasks with exact file paths, code, and test code. DRY. YAGNI. TDD. Frequent commits.
Announce at start: "I'm using the writing-plans skill to create the implementation plan."
Context: This should be run in a dedicated worktree (created by brainstorming skill).
Save plans to: docs/plans/<feature-slug>/ (see Output Structure below)
- (User preferences for plan location override this default)
Complexity Gate
Before doing anything else, assess plan complexity:
Simple — all of the following are true:
- ≤ 3 features or independent units of work
- Single session (estimably < 2 hours)
- Single contributor
Complex — anything else.
If Simple: Skip wave folders, skip status.yaml, skip plan review subagent, skip cost estimation. Output a single flat plan.md with tasks as numbered sections. Still do the architecture artifact, TDD mode decision, and spec alignment check — those pay off at any scale.
If Complex: Full structure — wave folders, task files, status.yaml, plan review subagent.
Record the assessment in the plan header: **Complexity:** Simple | Complex
Scope Check
If the spec covers multiple independent subsystems, it should have been broken into sub-project specs during brainstorming. If it wasn't, suggest breaking this into separate plans — one per subsystem. Each plan should produce working, testable software on its own.
TDD Mode
Before defining tasks, establish the testing discipline for this plan. Ask the user:
"Do you want strict TDD (tests written before implementation, RED confirmed before GREEN per task), or should I decide based on task type?"
If the user says decide: Apply this heuristic per task:
| Task type | Default mode | Reason |
|---|
| API routes, business logic, data access | Strict TDD | Clear inputs/outputs; RED phase catches wrong assumptions before code is written |
| UI components with user interaction | Strict TDD | Ctrl+Enter, form submit, dialog confirm — all testable and benefit from spec-first |
| Pure UI layout / styling | Test-after | No meaningful unit test to write first; visual output isn't testable this way |
| Scaffolding, config, migrations | Test-after | Setup code with no inputs/outputs to specify upfront |
| One-off scripts | Test-after | Friction without benefit |
Record the decision in the plan header:
**TDD Mode:** Strict (all tasks) | Mixed (strict for API/logic, test-after for UI layout) | Test-after (all tasks)
Tasks using strict TDD must include the RED step (write failing test, run it, confirm FAIL) before the GREEN step (implement, run, confirm PASS). Tasks using test-after write tests after implementation and verify PASS only.
Why this matters: Strict TDD takes longer wall-clock time but catches design errors before implementation. Test-after is faster but tests are written to match existing behavior, not to specify intended behavior. Make the trade-off explicit so the executing agent applies it consistently rather than guessing per task.
File Structure
Map all files to create/modify. Design units with clear boundaries, one responsibility per file. Files that change together live together. Follow existing codebase patterns.
This structure informs the wave decomposition. Tasks that touch the same files CANNOT be in the same wave.
Architecture Artifact (mandatory before tasks)
Before defining any waves or tasks, write a short architecture note. This is not a design document — it's a decision lock that prevents schema drift and API surface mismatches during implementation.
Save it to: docs/plans/<feature-slug>/architecture.md
Required sections (keep it short — the goal is precision, not length):
# Architecture: <Feature Name>
## DB Schema
<!-- Exact table/column names, types, constraints. Copy from spec if provided. -->
## API Surface
<!-- Exact method, path, request shape, response shape for every endpoint. -->
## Component Tree
<!-- List every file to be created: page, layout, component, lib, API route. -->
<!-- One line per file: `src/app/api/complete/route.ts` — streaming AI completion, enforces usage limit -->
## Data Flow (per feature)
<!-- One bullet per feature: "F3: Ctrl+Enter → POST /api/complete → streamText → usage_logs insert → stream response" -->
## Dependency Mock Plan
<!-- For each external dependency: "Clerk auth → mock via vi.mock('@clerk/nextjs/server')" -->
<!-- See TDD skill for the full mock strategy. -->
## Library Integration Notes
<!-- One line per known quirk. Record BEFORE coding to avoid mid-build surprises. -->
Why this matters: Architecture notes prevent schema drift and API mismatches during implementation. Write this before any task definitions. If it surfaces design questions, resolve them here — not during implementation.
Turn efficiency tip: Combine architecture + test skeleton (file paths, mock setup, describe/it names) in one turn under a "Test Skeleton" section in architecture.md.
Spec Alignment Check (after architecture, before first task)
One-pass check before writing tasks — flag and resolve discrepancies now (mid-implementation corrections cost 2–3 turns):
Wave-Based Plan Structure
ALL plans MUST be organized into waves. A wave is a group of tasks that share the same dependency level — they depend on the same set of prior tasks being done. Tasks within a wave MAY be independent (and thus parallelizable), or they may need sequential execution if they touch shared files or have subtle ordering requirements.
Not every wave has parallel tasks. A wave with a single task is perfectly normal. A plan that is entirely sequential (5 waves of 1 task each) is also fine. The wave structure provides checkpoints and clear dependency ordering regardless of parallelism.
How to Decompose into Waves
- Identify all tasks from the spec/requirements
- Build a dependency graph: which tasks depend on which? A task depends on another if it needs the other's output (file created, API defined, interface established)
- Group into waves by dependency level:
- Wave 1: Tasks with NO dependencies (foundations, interfaces, schemas, types)
- Wave 2: Tasks that depend only on Wave 1 outputs
- Wave 3: Tasks that depend on Wave 2 outputs
- Continue until all tasks are placed
- Within each wave, check for independence: Tasks that touch different files and have no data dependencies on each other are independent and can run in parallel. Tasks that touch the same file or have ordering requirements must either be in the same wave (executed sequentially) or split across waves.
- Maximize parallelism where possible: The goal is to have as many independent tasks per wave as possible. But don't force parallelism — a sequential wave is better than a broken parallel one.
Wave parallelism assessment
For each wave, mark whether it's parallel, sequential, or mixed:
| Wave Pattern | When | Execution |
|---|
| All independent | Tasks touch different files, no shared state | Dispatch all as parallel subagents |
| All sequential | Tasks touch the same files or must run in order | Execute one at a time |
| Mixed | Some independent, some dependent | Dispatch independent ones in parallel, then run dependent ones after |
| Single task | Only one task in the wave | Just run it |
Wave Rules
- Each wave is a synchronization point — all tasks must complete before next wave starts
- After each wave: run full test suite to catch integration issues
- Tasks marked as parallel MUST touch different files and have no data dependencies on each other
- Tasks that are sequential within a wave are executed in order
- Commit after each wave (not after each task)
- A wave with a single task is perfectly fine — it still provides a checkpoint
Output Structure
Choose the output format based on plan complexity:
Medium+ plans (3+ waves, or multi-session work)
Create a folder with a wave subfolder per wave. Each wave folder always has an index file (wave.md). Whether tasks get separate files depends on how many tasks the wave contains:
- ≤ 5 tasks in a wave: Tasks are written inline in the wave's
wave.md index file.
- > 5 tasks in a wave: Each task gets its own markdown file (
task-N.M.md) alongside wave.md.
docs/plans/<feature-slug>/
├── plan.md # Overview: goal, architecture, wave summary, dependency graph
├── status.yaml # Execution state — THE resume file (see mp:resume)
├── wave-1/ # 3 tasks → inline in wave.md
│ └── wave.md # Wave overview + entry/checkpoint criteria + all task definitions
├── wave-2/ # 7 tasks → separate task files
│ ├── wave.md # Wave overview + entry/checkpoint criteria + task index (names + links)
│ ├── task-2.1.md
│ ├── task-2.2.md
│ ├── task-2.3.md
│ ├── task-2.4.md
│ ├── task-2.5.md
│ ├── task-2.6.md
│ └── task-2.7.md
└── wave-3/ # 1 task → inline in wave.md
└── wave.md
Wave index file format (wave.md)
The wave index always starts with the wave header:
# Wave 2: Core Logic
**Depends on:** Wave 1 (all tasks must be completed)
**Tasks:** 2.1, 2.2, 2.3
**Execution:** Parallel (tasks are independent — different files, no shared state)
**Entry criteria:** Wave 1 checkpoint passed (all tests green)
**Checkpoint criteria:** Run `npm test` — all tests must pass
When tasks are inline (≤ 5 tasks): the wave index continues with full task definitions directly after the header, using the same Task Structure format documented below. Each task uses an ### Task N.M: heading.
When tasks are in separate files (> 5 tasks): the wave index adds a task index table after the header:
| Task | Name | Status | Files |
|------|------|--------|-------|
| 2.1 | [Retry Queue](task-2.1.md) | pending | `src/services/retry-queue.ts` |
| 2.2 | [Dead Letter Store](task-2.2.md) | pending | `src/services/dead-letter.ts` |
...
Separate task file format (when > 5 tasks)
Each task file is self-contained — a subagent reading ONLY that file has everything it needs:
- Project context (goal, architecture, tech stack)
- What was built in previous waves that this task depends on
- Exact file paths, code, test code, verification commands
- Which files to read for additional context
---
task: "2.2"
wave: 2
status: pending
depends_on: ["1.1", "1.3"]
files_to_create:
- src/services/retry-queue.ts
- tests/retry-queue.test.ts
files_to_read:
- src/services/webhook.ts
- src/types/webhook.ts
---
# Task 2.2: Implement Retry Queue
## Context
Goal: [from plan.md]
Architecture: [from plan.md]
This task implements the retry queue that uses the webhook types (Wave 1, Task 1.1)
and the config schema (Wave 1, Task 1.3).
## Steps
[Full task steps with code, file paths, verification commands]
Small plans (1-2 waves, single session)
Everything in one plan file + a status.yaml:
docs/plans/<feature-slug>/
├── plan.md # Full plan with waves as sections, tasks inline
└── status.yaml # Execution state
Status File (always created)
Create status.yaml alongside plan.md. It enables /resume to pick up where execution stopped. See mp:resume for the full YAML format.
Initialize with: feature, created, plan_file, plan_type (small|medium), current_wave: 0, status: pending, and a waves map with every task set to { status: pending }.
Plan Document Format
Every plan.md starts with this header:
# [Feature Name] Implementation Plan
> **For agentic workers:** Execute wave-by-wave using mp:subagent-driven-development.
> **MANDATORY:** Update `status.yaml` IMMEDIATELY after every task completes.
**Goal:** [One sentence]
**Architecture:** [2-3 sentences]
**Tech Stack:** [Key technologies/libraries]
**Complexity:** Simple | Complex
**TDD Mode:** Strict | Mixed | Test-after
**Wave Summary:**
| Wave | Tasks | Focus | Execution |
|------|-------|-------|-----------|
| 1 | 1.1, 1.2, 1.3 | Foundation | Parallel |
| 2 | 2.1, 2.2 | Core logic | Sequential |
Then wave sections with tasks (using the Task Structure format below), each ending with: **Wave N checkpoint:** Run full test suite. All tests must pass.
Task Structure
Each step is one action (2-5 minutes): write test → verify fail → implement → verify pass → commit.
### Task N.M: [Component Name]
**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`
- [ ] **Step 1: Write the failing test**
```python
def test_specific_behavior():
result = function(input)
assert result == expected
```
- [ ] **Step 2: Run test to verify it fails**
Run: `pytest tests/path/test.py::test_name -v`
Expected: FAIL with "function not defined"
- [ ] **Step 3: Write minimal implementation**
```python
def function(input):
return expected
```
- [ ] **Step 4: Run test to verify it passes**
Run: `pytest tests/path/test.py::test_name -v`
Expected: PASS
No Placeholders
Every step must contain the actual content an engineer needs. These are plan failures — never write them:
- "TBD", "TODO", "implement later", "fill in details"
- "Add appropriate error handling" / "add validation" / "handle edge cases"
- "Write tests for the above" (without actual test code)
- "Similar to Task N" (repeat the code — the engineer may be reading tasks out of order)
- Steps that describe what to do without showing how (code blocks required for code steps)
- References to types, functions, or methods not defined in any task
Remember
- Exact file paths always
- Complete code in every step — if a step changes code, show the code
- Exact commands with expected output
- DRY, YAGNI, TDD, frequent commits
- Wave numbering: Task 1.1, 1.2 (wave 1), Task 2.1, 2.2 (wave 2), etc.
- Dependency annotations: Each wave header states what it depends on
Plan Review Agent
Skip if Simple plan (see Complexity Gate).
Dispatch a review subagent for a second opinion:
Agent tool:
description: "Plan review"
model: sonnet
prompt: |
[Include content of ./plan-document-reviewer-prompt.md]
Review the implementation plan at: {PLAN_PATH}
The original spec/design is at: {SPEC_PATH}
Check for: spec coverage gaps, placeholder/vague tasks, wave integrity
(no shared files within a wave), dependency ordering, missing verification
steps, parallelism opportunities missed.
If the reviewer finds issues, fix them before presenting execution options.
Execution Handoff
After saving, announce: "Plan saved to docs/plans/<slug>/. N waves, M tasks." Then offer:
- Subagent-Driven (recommended) → use
mp:subagent-driven-development
- Inline Execution → use
mp:executing-plans