spec-plan
Spec Plan — Implementation Planning for Hexagonal Core
Creates structured, ephemeral plan files inside todo/ that track the gap between
current code and the desired spec state. Plans are living documents — updated during
implementation, then deleted when work is complete.
Important: Plans are ephemeral. Nothing in a plan file should be the only place
important decisions are recorded. Decisions belong in specs/. Plans only track
the path to get there.
Folder structure
todo/
├── plan.md ← project-level index + cross-cutting refactors
├── entities/
│ ├── plan.md ← multi-entity work
│ └── <entity-name>/
│ └── plan.md ← single entity changes
└── use-cases/
├── plan.md ← cross-module work (rare)
└── <module-name>/ ← e.g. orders/, invoices/
├── plan.md ← module-level sequencing
└── <use-case-name>/
└── plan.md ← single use case task list
Step 0 — Determine plan scope
Extract from context or ask:
- What is the scope? (single use case / single entity / module / cross-cutting)
- Which spec file(s) does this plan target? (get the exact path)
- What is the current state of the code? (not started / partial / needs refactor)
- Are there known blockers or prerequisites from other plans?
Map scope → file location:
- Single use case →
todo/use-cases/<module>/<use-case>/plan.md - Entity change →
todo/entities/<entity>/plan.md - Multiple entities →
todo/entities/plan.md - Module sequencing →
todo/use-cases/<module>/plan.md - Refactoring / cross-cutting →
todo/plan.md
Step 1 — Gap analysis
Before writing tasks, identify the gap between spec and code.
Read the target spec file(s). Then either:
- Read the actual source files if available in context or filesystem
- Ask the user to describe current state if code is not accessible
Produce a gap summary — not the plan yet, just the delta:
## Gap: CreateOrderUseCase
Missing entirely:
- CreateOrderUseCase class does not exist
Partially implemented:
- Order entity exists but missing `discount` field
- IOrderRepository interface exists but missing `findByCustomerId` method
Needs refactor:
- OrderService contains business logic that should move to CreateOrderUseCase
Show the gap summary to the user and confirm before writing the plan.
Step 2 — Write the plan file
Read
references/plan-template.mdfor the full frontmatter schema and task format.
Frontmatter fields (all required):
---
scope: use-case | entity | module | project
status: not-started | in-progress | blocked | done
spec: <path to the spec file this plan targets>
blocked-by: <path to another plan file, or null>
unblocks: <list of plan paths this plan unblocks, or null>
created: YYYY-MM-DD
updated: YYYY-MM-DD
---
Task format — every task must have:
- A checkbox
- [ ]or- [x] - A short imperative label (verb first)
- A reference to the spec section it satisfies (in parentheses)
- Optional: a
> note:line for context or decisions made during implementation
- [ ] Add `discount` field to Order entity (`specs/entities/order.md#fields`)
- [ ] Add `findByCustomerId` method to IOrderRepository (`specs/use-cases/orders/create-order.md#repository-interface-hints`)
- [x] Create CreateOrderUseCase class skeleton (`specs/use-cases/orders/create-order.md#intent`)
> note: placed in src/use-cases/orders/ — matches module folder structure
Task grouping — group tasks under ## headers:
For use case plans: ## Prerequisites, ## Entity changes, ## Use case implementation, ## Tests
For entity plans: ## Field changes, ## Invariant changes, ## DTO changes, ## Cascading use case updates
For module plans: list use cases as ## sections with their status and link to their plan
For project plan: list active plans as ## sections with their status pulled from frontmatter
Step 3 — Update the project index
After writing any plan file, update todo/plan.md to include a reference to the new plan.
The project index is a dashboard — one line per active plan:
## Active plans
| Plan | Scope | Status | Blocked by |
|------|-------|--------|------------|
| [Create Order](use-cases/orders/create-order/plan.md) | use-case | in-progress | — |
| [Order entity: add discount](entities/order/plan.md) | entity | done | — |
| [Orders module sequencing](use-cases/orders/plan.md) | module | not-started | entities/order/plan.md |
Step 4 — Updating tasks during implementation
When the user says a task is done, blocked, or needs a note:
- Check the
- [ ]→- [x]for completed tasks - Add a
> note:line under the task if a decision was made - Update
updated:in frontmatter to today's date - Update
status:in frontmatter if overall plan status changed - Re-run the linter:
python scripts/lint_plans.py <path-to-plan> - If plan is fully
done: remind the user to delete the file and remove from index
Never leave a completed plan file in place. Done means deleted.
Step 5 — Linting and maintenance
Run linting at any time:
# Lint all plans
python scripts/lint_plans.py
# Lint a specific plan
python scripts/lint_plans.py todo/use-cases/orders/create-order/plan.md
# Check for broken spec links across all plans
python scripts/lint_plans.py --check-links
# Show dashboard of all plan statuses
python scripts/plan_status.py
See
scripts/lint_plans.pyandscripts/plan_status.pyfor what each check covers.
Hard rules
- Plans reference specs — specs never reference plans. The spec is timeless; the plan is not.
- No decisions in plans. If a decision was made during implementation, it goes in the spec (via spec-sync) or the constitution. The plan's
> note:is a breadcrumb, not a record. - One plan per scope unit. Don't create a use-case plan that also covers entity changes — split them and link with
blocked-by. - Done means deleted. A completed plan file is noise. Archive nothing — delete.
- Update
updated:every session. Staleupdated:dates are a linter error.
More from efesto-cloud/skills
persistence
>
18population
>
17type-enum-dict
|
17value-object
|
17usecase
>
16entity
Create or modify domain entities using the @efesto-cloud/entity package. Use this skill whenever the user asks to add a new entity, update an existing entity, add properties or methods to an entity, or work on the entity/dto layer. Trigger when the user says things like "create a Foo entity", "add a field to Bar", "I need a new domain object", or "add entity X". Also trigger for DTO creation or modification.
16