Tutorial Overview
Series index: Superpowers Tutorial Series
writing-plans is Superpowers’ second core skill. Its job is to turn the design document produced by brainstorming into an implementation plan you can actually execute.
What you will learn
- ✅ When
writing-planstriggers - ✅ What makes a task atomic
- ✅ The right granularity for task decomposition
- ✅ The structure of a task template
- ✅ How to move from plan to execution
Why Do We Need writing-plans?
Problems without a plan
flowchart LR
A[Design document] --> B[AI starts implementing]
B --> C[Discovers something was missed]
C --> D[Rework]
D --> E[Task switching]
E --> F[Context loss]
F --> G[Quality drops]
style B fill:#ffcccc
style C fill:#ffcccc
style F fill:#ffcccc
Benefits of having a plan
flowchart TD
A[Design document] --> B[`writing-plans`]
B --> C[Atomic task list]
C --> D[Execute task by task]
D --> E[Completion check]
E --> F[Context preserved]
F --> G[High-quality delivery]
style B fill:#e1f5ff
style C fill:#e1f5ff
style E fill:#e1f5ff
Comparison
| Metric | No plan | With plan |
|---|---|---|
| Task switches | 10+ | 0-2 |
| Context loss | Frequent | Rare |
| Missed functionality | Common | Rare |
| Average task duration | 15-30 minutes | 2-5 minutes |
| Code quality | Unstable | Stable |
writing-plans Skill Explained
When it triggers
The writing-plans skill triggers automatically in these scenarios:
- After
brainstormingcompletes - the design document has been approved - Multi-step tasks - changes that touch multiple files or components
- Complex features - work that spans data models, APIs, frontends, and more
Core principles
1. YAGNI (You Aren’t Gonna Need It)
✅ Only build what is needed now
❌ Do not build "might be useful later" extensions
Example:
❌ "Create a generic BaseComponent with hooks for every future extension"
✅ "Create a CommentComponent that only implements the current requirements"
2. Atomic tasks
✅ Good task: create the tags table migration file
❌ Bad task: implement the entire tagging system
Atomic task characteristics:
- Can be completed in 2-5 minutes
- Has a clear definition of done
- Can be verified independently
- Does not depend on other tasks, or has explicit dependencies
3. Complete code, not pseudocode
✅ Good plan: includes complete code examples
❌ Bad plan: "Create a model, add fields"
Example:
✅ "Create a tags table with the following fields:
- id: BIGINT PRIMARY KEY AUTO_INCREMENT
- name: VARCHAR(50) UNIQUE NOT NULL
- slug: VARCHAR(50) UNIQUE NOT NULL
- description: TEXT NULL
- created_at: TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
Task List Structure
Standard task template
Each task includes the following fields:
## Task 1: [Task Name]
**Estimated time**: 3 minutes
**Goal**: [One-sentence description of the task goal]
**File paths**:
- `path/to/file1.ext` (new or modified)
- `path/to/file2.ext` (new or modified)
**Implementation steps**:
1. [Step 1 - concrete action]
2. [Step 2 - concrete action]
3. [Step 3 - concrete action]
**Code example**:
```language
[complete code example, not pseudocode]
Verification command:
[command you can actually run to verify]
Acceptance criteria:
- File created successfully
- Code passes lint
- Unit tests pass
- Feature verified manually
Dependencies: [Task 0 or None]
### Complete plan example
Here is a complete plan generated for the "tagging system":
```markdown
# Tagging System Implementation Plan
**Design document**: `.project/designs/feature-tag-system-2026-02-28.md`
**Estimated total time**: 45 minutes
**Task count**: 12
---
## Phase 1: Database Migration
### Task 1: Create the tags table migration file
**Estimated time**: 2 minutes
**Goal**: Create the database migration script for the tags table
**File paths**:
- `database/migrations/20260228_create_tags_table.sql` (new)
**Implementation**:
```sql
CREATE TABLE tags (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) UNIQUE NOT NULL COMMENT 'Tag name',
slug VARCHAR(50) UNIQUE NOT NULL COMMENT 'URL-friendly name',
description TEXT NULL COMMENT 'Tag description',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_slug (slug)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Tags table';
Verification command:
# Check that the migration file exists
ls -la database/migrations/20260228_create_tags_table.sql
# Syntax check if you have an SQL linting tool
sqlint database/migrations/20260228_create_tags_table.sql
Acceptance criteria:
- Migration file created successfully
- SQL syntax is correct
- All required fields are included
Dependencies: None
Task 2: Create the article_tags join table migration
Estimated time: 2 minutes
Goal: Create the many-to-many join table between articles and tags
File paths:
database/migrations/20260228_create_article_tags_table.sql(new)
Implementation:
CREATE TABLE article_tags (
article_id BIGINT NOT NULL COMMENT 'Article ID',
tag_id BIGINT NOT NULL COMMENT 'Tag ID',
PRIMARY KEY (article_id, tag_id),
FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE,
INDEX idx_tag_id (tag_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Article-tag join table';
Verification command:
ls -la database/migrations/20260228_create_article_tags_table.sql
Acceptance criteria:
- Join table structure is correct
- Foreign key constraints are correct
- Indexes are reasonable
Dependencies: Task 1
Task 3: Run the database migrations
Estimated time: 3 minutes
Goal: Execute the migration scripts and create the actual tables
File paths:
- None (execution only)
Implementation steps:
- Back up the current database
- Run the migration scripts
- Verify the table structure
Verification command:
# Back up the database
mysqldump -u root -p blog_db > backup_$(date +%Y%m%d_%H%M%S).sql
# Run the migrations
mysql -u root -p blog_db < database/migrations/20260228_create_tags_table.sql
mysql -u root -p blog_db < database/migrations/20260228_create_article_tags_table.sql
# Verify table creation
mysql -u root -p blog_db -e "SHOW TABLES LIKE 'tags';"
mysql -u root -p blog_db -e "DESCRIBE tags;"
mysql -u root -p blog_db -e "DESCRIBE article_tags;"
Acceptance criteria:
- Migrations complete without errors
-
tagstable is created successfully -
article_tagstable is created successfully - Foreign key constraints are active
Dependencies: Task 1, Task 2
Phase 2: Backend Model
Task 4: Create the Tag model class
Estimated time: 3 minutes
Goal: Create the ORM model for tags
File paths:
app/Models/Tag.php(new)
Implementation:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Tag extends Model
{
protected $fillable = [
'name',
'slug',
'description',
];
/**
* Get all related articles
*/
public function articles(): BelongsToMany
{
return $this->belongsToMany(Article::class, 'article_tags')
->withTimestamps();
}
/**
* Generate a URL-friendly slug
*/
public static function createWithSlug(string $name): self
{
$slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $name)));
return self::create([
'name' => $name,
'slug' => $slug,
]);
}
}
Verification command:
# Syntax check
php -l app/Models/Tag.php
# Run the model test
php artisan test --filter=TagTest
Acceptance criteria:
- Model class created successfully
-
fillablefields are correct - Relationship definition is correct
- Helper method works correctly
Dependencies: Task 3
Task 5: Create the TagRepository
Estimated time: 4 minutes
Goal: Implement the tag data access layer
File paths:
app/Repositories/TagRepository.php(new)
Implementation:
<?php
namespace App\Repositories;
use App\Models\Tag;
use Illuminate\Database\Eloquent\Collection;
class TagRepository
{
public function __construct(
private Tag $model
) {}
/**
* Get all tags
*/
public function getAll(): Collection
{
return $this->model->withCount('articles')->get();
}
/**
* Find a tag by slug
*/
public function findBySlug(string $slug): ?Tag
{
return $this->model->where('slug', $slug)->first();
}
/**
* Create or fetch a tag
*/
public function findOrCreate(string $name): Tag
{
$tag = $this->model->where('name', $name)->first();
if (!$tag) {
$tag = Tag::createWithSlug($name);
}
return $tag;
}
/**
* Sync tags for an article
*/
public function syncTags(int $articleId, array $tagNames): void
{
$tagIds = collect($tagNames)
->map(fn($name) => $this->findOrCreate($name)->id)
->all();
$this->model->newModelQuery()
->find($tagIds)
->first()
?->articles()
->sync($articleId);
}
}
Verification command:
php -l app/Repositories/TagRepository.php
Acceptance criteria:
- Repository methods are complete
- Type hints are correct
- Documentation comments are included
Dependencies: Task 4
[Continue with Tasks 6-12…]
## Task Decomposition Strategy
### Decompose by layer
Feature implementation ├── Database layer │ ├── Create migration files │ └── Run migrations ├── Model layer │ ├── Create model classes │ └── Create repositories ├── Service layer │ ├── Create services │ └── Implement business logic ├── API layer │ ├── Create controllers │ └── Define routes └── Frontend layer ├── Create components └── Write styles
### Decompose by CRUD
Resource management ├── Create │ ├── Create form components │ ├── Implement validation logic │ └── Write create API ├── Read │ ├── Create list components │ ├── Create detail components │ └── Write query API ├── Update │ ├── Create edit forms │ ├── Implement update logic │ └── Write update API └── Delete ├── Implement delete confirmation ├── Write delete API └── Handle cascade deletion
### Decompose by testing
Test-driven development ├── Unit tests │ ├── Model tests │ ├── Repository tests │ └── Service tests ├── Integration tests │ ├── API tests │ └── Database tests └── E2E tests ├── User flow tests └── Performance tests
## Best Practices
### 1. Control task granularity
✅ Good: create a single function/class/component ❌ Bad: implement the entire module
Decision criteria:
- Can it be completed in 2-5 minutes?
- Can you write a concrete verification command?
- Does it have a clear definition of done?
### 2. Make dependencies explicit
```markdown
**Dependencies**: Task 1, Task 2
Execution order:
Task 1 → Task 2 → Task 3
↓
Task 4 (depends on Task 2)
3. Make verification commands concrete
✅ Good: php artisan test --filter=TagTest
❌ Bad: run tests
✅ Good: curl http://localhost:8000/api/tags | jq
❌ Bad: test the API
4. Use complete code examples
✅ Good: complete function/class implementation
❌ Bad: pseudocode or comments
Reason:
- AI can implement directly
- Users can see the expected result
- Reduces interpretation errors
Common Questions
Q1: What if the task breakdown is too fine-grained?
Answer: Merge related tasks:
Original plan:
Task 1: Create Tag model
Task 2: Create TagRequest validation class
Task 3: Create TagResource resource class
Merged plan:
Task 1: Create tag-related classes (model, validation, resource)
Q2: What if I discover something was missed during execution?
Answer: Pause the current task and update the plan:
1. Mark the current task as "blocked"
2. Add the missing task
3. Reorder the plan
4. Continue execution
Q3: What if the plan is too long to read?
Answer: Ask the AI to show it in phases:
Please show only the tasks for Phase 1 first. After that is complete, show the remaining phases.
Where Plans Are Saved
.project/plans/
└── plan-<feature>-<date>.md
For example:
.project/plans/
└── plan-tag-system-2026-02-28.md
How This Works With Other Skills
writing-plans -> subagent-driven-development
Plan complete
↓
subagent-driven-development triggers automatically
↓
Tasks are assigned to subagents
writing-plans -> test-driven-development
Each task begins
↓
test-driven-development triggers automatically
↓
Write tests before implementation
Summary
The core value of writing-plans is:
- Executability - a plan is an execution guide, not just documentation
- Atomicity - tasks should be small enough to finish in 2-5 minutes
- Completeness - include code examples and verification commands
- Traceability - every task has a clear acceptance standard
Key takeaways
- ✅ YAGNI principle - do not add unnecessary scope
- ✅ Atomic tasks - move in small steps
- ✅ Complete code - not pseudocode
- ✅ Clear verification - use concrete commands
Series navigation: