| name | milestone-plan |
| description | This skill should be used when the user asks to 'plan my project', 'plan milestones', 'break down into tasks', or 'create tasks for milestone'. Plans spec milestones in detail — task groups, tasks, dependencies, and priorities. |
Milestone Planner
The spec already contains a high-level list of milestones. This skill plans one milestone at a time in detail — defining task groups, individual tasks, dependencies, and priorities. Everything is presented to the user for approval before creating anything in the system.
EARS-BDD Mode
Check whether EARS-BDD is enabled for this workspace — the agent's appended system prompt or getWorkspaceDetails will indicate it (earsBdd: true). When enabled, each TG's ### Requirements lists the durable FR-<AREA>-<NNN> ids it delivers (drawn from the SRS, reused verbatim — replacing the FR-TG1.N local numbering); allocate a new durable id only for milestone-level detail the SRS did not capture. Follow the planning augmentations in plugins/engy/skills/implement/references/ears-bdd.md for FR-graph orientation (use the area's existing FRs + trace to find current behaviour, tests, and code before exploring), the id scheme, allocation rule, and funnel discipline. When disabled, use the hierarchical FR-TG1.N scheme below unchanged.
Multi-Repo Task Scoping
When a workspace manages multiple repos, task scoping rules apply:
- Task groups can span multiple repos — set their
repos field to all repos the group's tasks touch.
- Tasks must each target a single repo. Never create a task that requires working across multiple repos simultaneously. Mention the target repo/package in the task title or description (e.g., "Implement auth middleware in
web/").
- Cross-repo dependencies within a group use
blockedBy — upstream repo tasks (e.g., shared types in common/) should be completed before downstream consumers (e.g., web/).
Discovering Repos
Call getProjectDetails(projectId) and inspect workspace.repos (an array of local repo paths). If the array has more than one entry, apply the multi-repo rules above when planning task groups and tasks.
For single-repo workspaces, these rules are effectively no-ops — all tasks naturally target the same repo.
Planning Levels
Level 1: Identify Which Milestone to Plan
- Get the project's
specDir via getProjectDetails (returned at paths.specDir).
- Read
{specDir}/spec.md and extract the existing milestone list.
- Determine which milestone to plan:
- If the user specified a milestone, use that one.
- Otherwise, check for existing milestone plan docs via
Glob("{specDir}/milestones/m*-*.plan.md") or task groups via listTaskGroups. Find the next unplanned milestone in sequence.
- Present the selected milestone and its scope to the user for confirmation before proceeding.
Do NOT create task groups or tasks yet. Level 1 is purely about selecting and confirming which milestone to plan.
One milestone per run. Do not plan multiple milestones unless the user explicitly asks.
Level 1.5: Research Prior Knowledge
Before writing the milestone plan body, dispatch the engy:research subagent to surface relevant prior decisions, patterns, and architectural context from the workspace knowledge graph.
Resolve workspaceId first. If not already known from context, call listWorkspaces (or getWorkspaceDetails) to obtain it before dispatching — engy:research hard-errors without it.
Task({
subagent_type: 'engy:research',
prompt: '<milestone name and domain description> — context: project=<slug>, milestone=<id>, repo=<repo-or-empty> workspaceId=<id>'
})
The subagent returns a digest with 3–8 cited findings. Fold it into the milestone plan document in the Codebase Context section or immediately after the Overview, wrapped in markers:
<!-- engy:research synthesized YYYY-MM-DD -->
<digest content>
<!-- /engy:research -->
The markers let future readers identify LLM-synthesized content and re-run the research step.
If the subagent returns No relevant prior knowledge found for this question. (i.e., Distinct findings: 0 (after dedup) in the footer), omit the marker block entirely — do not write an empty block.
When the milestone is repo-local, mention the repo path in the prompt so the subagent applies filters.repo. This step runs after Level 1 (milestone selection confirmed) and before writing the plan document.
Level 2: Plan Milestone Details (Groups and Tasks)
For the selected milestone:
- Confirm the correct projectId. Use
listProjects to find the project whose specDir matches the spec you're working with. Do NOT assume projectId=1.
- Discover workspace repos. Call
getProjectDetails(projectId) and check workspace.repos. If the workspace has multiple repos, apply the multi-repo task scoping rules (see above) throughout the remaining steps.
- Review the milestone scope against the spec.
- Break the milestone into task groups. Each group is a single deliverable — think one PR. Groups are ordered so they can be reviewed and merged as stacked PRs, making large milestones easier to review incrementally. For multi-repo workspaces, set the
repos field on each group to the repos its tasks touch. For each group, define its functional requirements using hierarchical numbering (e.g., FR-DC.1 for Dev Containers group) — or, in EARS-BDD mode, durable FR-<AREA>-<NNN> ids (see "EARS-BDD Mode" above). FRs live under each TG, not at the top level — this keeps each group self-contained for agent dispatch.
- Within each group, define 1 or more tasks that together produce that deliverable. Follow the vertical slicing and granularity guidelines below. Each task must target a single repo — include the target repo/package in the task title or description (e.g., "Implement auth middleware in
web/"). For cross-repo dependencies, use blockedBy to order upstream tasks before downstream consumers.
- For each task, specify:
- Title and description (including target repo for multi-repo workspaces)
- File ownership — list the files this task creates or modifies. This is critical for parallel execution: agents need to know what they own and what siblings touch.
- Acceptance criteria — derived from the task group's FRs. These are what the implementer tests against.
- FR references — which FRs this task implements (e.g., "Implements FR-TG1.1, FR-TG1.2")
- Type (
ai or human)
- Importance and urgency (using the Eisenhower matrix)
- Dependencies on other tasks (
blockedBy)
- Present the full breakdown to the user and wait for explicit approval.
- Write the milestone plan document (
m{N}-{slug}.plan.md with status: draft) using the template below. This doc the presentation — approval happens on this doc.
Task Group Planning
When the user asks to plan a specific TG:
-
Read the milestone doc's TG section (requirements, task outline, file ownership) as context. Update milestone doc status to planning if still draft.
-
For each task, decide whether /engy:plan is warranted. A separate planning pass is only needed when the milestone doc's task block leaves real ambiguity. Run /engy:plan if any of the following apply:
- The task touches more than 2 files of non-trivial size.
- The task description is vague — contains "TBD", "implementer's choice", "decide between X and Y", or leaves a key design choice open.
- The task spans architectural boundaries (e.g., adds a new layer, changes a cross-cutting protocol, introduces a new pattern other tasks will follow).
Otherwise, the milestone doc's task block (title, file ownership, FR refs, acceptance criteria, brief description) is sufficient — skip /engy:plan.
-
Create the task group and tasks via createTaskGroup / createTask.
- Set
milestoneRef on every task (e.g., "m3") to link it to the milestone.
- Set
specId to the spec directory name so the task resolves to the correct spec path.
- For multi-repo workspaces, pass the
repos array when calling createTaskGroup.
- For tasks that got a
/engy:plan pass: set needsPlan: false and store the plan doc path in the task description.
- For tasks that didn't: set
needsPlan: true and copy the milestone doc's task block (files, FR refs, description, acceptance criteria) into the task description as-is. The implementer agent can still spin up its own plan pass at implementation time if it hits ambiguity.
-
Verify structure via listTasks and listTaskGroups.
-
When all TGs are planned and created, update milestone doc status to complete.
Example: when to plan, when to skip
Both tasks below come from the same TG. The first warrants /engy:plan; the second does not.
- Plan-warranted: "Wire spawn-event replay into mobile terminal sheet." Touches
web/src/components/terminal/*, web/src/server/ws/handlers.ts, and client/src/terminal/session.ts (3 files, 2 layers, cross-cutting protocol change). Run /engy:plan, store the plan path, needsPlan: false.
- Skip: "Add
status: 'planning' to milestone plan doc frontmatter type." Touches one file, the milestone doc's task block already lists the exact field, file, and acceptance criteria. Copy the task block into the description, needsPlan: true as a safety net.
Vertical Slicing
Use vertical slices, not horizontal layers. Each task should deliver a thin, end-to-end slice of functionality that touches all necessary layers (database, service, API, UI). A good slice is small but complete — something that can be tested and verified independently.
Bad (horizontal): "Create all database tables" then "Build all API endpoints" then "Add all UI components"
Good (vertical): "User can create a task and see it in a list" then "User can mark a task complete" then "User can filter tasks by status"
Execution Order Within a Slice
Within each vertical slice, order subtasks as:
- Schema / data model changes
- Data access layer (repositories / queries)
- Service / business logic
- API endpoints
- UI components
- Integration tests
Task Granularity
- Target size: 1-4 hours of work, or 5-8 concrete implementation steps
- Maximum: 6 tasks per feature/story
- Minimum viable: Each task must produce something testable
- Context budget: Tasks should complete within ~10-20 minutes of autonomous agent work
- If a task has more than 8 steps, split it. If it has fewer than 3 steps, combine with related work.
Task Quality Checklist
Each task should be:
- Self-sufficient for simple tasks, plan-ready for complex ones: The milestone task block should be detailed enough that simple, single-file tasks can skip
/engy:plan entirely (see Task Group Planning's conditional flow). For multi-file or architecturally cross-cutting tasks, the block must still be a good launching pad — a /engy:plan pass with the task description + milestone plan context should produce a complete implementation plan. The milestone task always defines what and where; the planning pass (when needed) discovers how.
- Explicit: Reference specific files, functions, and patterns from the existing codebase. Never reference line numbers — they go stale. Reference by function name, class name, or pattern description instead.
- File-owned: List every file the task creates or modifies. This lets parallel agents know what they own and what siblings touch.
- Feature-traced: Reference which FRs this task covers, so nothing is missed and nothing is invented
- Verifiable: Include what shell commands prove the task is done (e.g.,
pnpm test, pnpm lint)
- Repo-scoped: In multi-repo workspaces, each task targets a single repo (mentioned in title or description)
- File-conflict-free: No two parallel tasks modify the same file. Identify shared touchpoint files (routers, protocol types, schema definitions, composition roots) and ensure tasks touching them are serialized via
blockedBy or combined into a single task
- Atomically testable: If you can't test a task independently (e.g., protocol changes without handlers, dispatch without pending maps), it's not a real task — combine it with its dependencies into one task
Anti-Patterns to Flag
When reviewing the breakdown, watch for and restructure:
- Tasks that only touch one layer (pure DB, pure UI) — prefer vertical slices
- Tasks with vague acceptance criteria ("works correctly")
- Tasks with 10+ steps (too large)
- Circular dependencies
- Tasks that span multiple repos — split into separate single-repo tasks with
blockedBy for ordering
- Tasks that require context from many previous tasks (context rot risk)
- Parallel tasks that modify the same file — tasks that create or modify the same file MUST be serialized via
blockedBy, never placed in the same parallel wave. If two tasks both need to add to the same file (e.g., both add routes to a router or message types to a protocol), either combine them into one task or serialize them explicitly via blockedBy.
- Tasks that reference patterns created by siblings — if task B says "follow the pattern in X" and task A creates that pattern, B must
blockedBy A. Pattern-establishing tasks must be identified and serialized before pattern-consuming tasks.
- Untestable splits — protocol changes, dispatch functions, pending maps, and handlers are one atomic unit. If you can't run a test after completing the task alone, it's not a valid split. Combine into one task.
Eisenhower Matrix for Prioritization
Use importance and urgency to classify tasks:
| Urgent | Not Urgent |
|---|
| Important | Critical path, blockers | Architecture, quality |
| Not Important | Quick wins, polish | Nice-to-haves, defer |
- Mark critical-path tasks and blockers as
important + urgent
- Architecture and quality work is
important + not_urgent
- Quick wins and polish are
not_important + urgent
- Nice-to-haves are
not_important + not_urgent (consider deferring)
Milestone Plan Document Template
After the task breakdown is approved and created, produce a m{N}-{slug}.plan.md document at {specDir}/milestones/m{N}-{slug}.plan.md (where specDir is resolved from getProjectDetails's paths.specDir). This is the canonical location where /engy:implement and /engy:implement-milestone look for plan docs.
---
title: {Milestone Name}
status: draft
---
# Plan: M{N} {Milestone Name}
## Overview
{1-2 paragraphs: what this milestone delivers and its boundary. End with an explicit "Boundary: no X, no Y, no Z." sentence listing what is NOT included.}
## Codebase Context
{Key existing files, patterns, and components that this milestone builds on. Reference actual paths and describe what each does — this orients the implementer. Include a note on what previous milestones shipped if relevant.}
## Task Group Sequencing
{Dependency graph between TGs. Which TGs can start immediately, which
depend on others, and what specifically they depend on.}
- **TG1: {Name}** — no dependencies. Can start immediately.
- **TG2: {Name}** — depends on TG1 ({what specifically}).
- ...
## TG1: {Task Group Name}
{One paragraph: what this group delivers and why it's sequenced here.}
### Requirements
<!-- EARS-BDD off: local `FR-TG<N>.<M>` ids as shown below. EARS-BDD on: durable `FR-<AREA>-<NNN>` EARS rows — see "EARS-BDD Mode" above. -->
1. The system shall {concrete, testable behavior}. *(source: user request | inferred | elicited)* (FR-TG1.1)
2. ...
### Tasks
1. **{Task title}**
- Files: `path/to/file.ts` [NEW], `path/to/other.ts` [MODIFY]
- Implements FR-TG1.1, FR-TG1.2
- {Brief description of what to build}
2. **{Task title}** (depends on task 1)
- Files: `path/to/another.ts` [NEW]
- Implements FR-TG1.3
- {Brief description}
**Parallelizable:** Tasks 1, 3 have no dependencies and can run concurrently.
### Completion Summary
{Updated after TG completes — what was actually shipped, key APIs/patterns
created, anything the next TG's agents need to know. Leave blank until done.}
{Repeat structure. Can reference TG1's completion summary for context.}
...
{Feature} (deferred to M{X})
...
Template Notes
- Frontmatter status:
draft → planning → complete
- No top-level Affected Components or FR sections — these live under each TG, making each group self-contained for agent dispatch
- Hierarchical FR numbering:
FR-TG1.1, FR-TG2.1, etc. — scoped to task group number, deletions in one TG don't affect another
- Source attribution on each FR:
(user request), (inferred: reason), or (elicited) — tracks provenance
- Codebase Context prevents the implementer from reimplementing what exists or breaking established patterns
- Completion Summary per TG is updated after implementation — gives the next TG's agents context on what shipped without them having to read the code
- File ownership per task — every task lists its files so parallel agents know boundaries
- Never use line numbers in task descriptions — they go stale. Reference by function/class/pattern name
Key Principles
- Never auto-create. Always present the full breakdown and wait for explicit user approval before calling
createTaskGroup or createTask.
- Ask clarifying questions when scope is ambiguous.
- Keep milestones independent and shippable.
- Set realistic dependencies — avoid over-constraining.
- Plan content should explain the "how" and "why", not just list tasks.
- Milestone-doc detail absorbs
/engy:plan. A well-written milestone task block (file ownership, FR refs, acceptance criteria, concrete step-level intent) IS the plan for 1–4 hr tasks. Reserve /engy:plan for tasks with real ambiguity — multi-file, vague, or architecturally cross-cutting. When in doubt, lean on needsPlan: true so the implementer can plan at execution time if it hits friction.
Flow Position
Previous: write-spec | Next: implement (with plan invoked conditionally per task)
Once the milestone plan doc is written and approved, the user typically asks to plan a specific TG ("plan TG1"). Within that TG planning pass, run /engy:plan only for tasks that warrant it (see the Task Group Planning criteria); simple tasks ship straight to /engy:implement with needsPlan: true as a safety net.