| name | plan-management |
| description | Build and maintain the executable plan as a GitHub issue graph — Epics, just-in-time Task decomposition, blocked-by dependencies, the actionable frontier, and replanning after deviations. Use this whenever creating or splitting issues, deciding what can run in parallel, wiring or changing dependencies, reacting to a task outcome that invalidates later tasks, or asking "what should agents work on next". |
Plan Management
The plan is not a document; it is the issue graph itself. Epics hold the
outline, Task issues hold executable work orders, blocked-by edges hold the
ordering, and the graph's edit history is the plan's change log. A schedule
drawn once never survives contact with reality — so this skill optimizes for
cheap, auditable plan changes, not for a perfect initial plan.
Requires GitHub CLI v2.94.0 or later (native --parent, --blocked-by,
--blocking support). Check with gh --version.
Data model
| Concept | GitHub primitive | Conventions |
|---|
| Outline item / phase | Epic issue | label type:epic; template epic.yml; holds outcome, scope, phase outline |
| Work order | Task issue, sub-issue of an Epic | label type:task; template ai-task.yml; one exec:* label |
| Ordering constraint | Issue dependency (blocked by / blocking) | the only mechanism for sequencing — never encode order in prose only |
| Ready gate | label ai:ready | present only when the brief is complete enough for a context-free agent |
| Plan exceptions | labels needs:replan, needs:human | set by executors; consumed by planner/orchestrator |
| Portfolio view | GitHub Project (optional) | group by Epic, surface Blocked markers; keep Project fields derived from issues, not the reverse |
Rolling-wave decomposition
- Create Epics for the whole outline up front — cheap, low detail, gives the
"what comes next" visibility agents need for preparation.
- Decompose an Epic into Task sub-issues only when its phase is about to
start (or when the frontier is nearly empty). Detail decays; write it late.
- Every Task must clear the planner quality bar
(self-contained, traceable to
REQ-###, bounded, partitioned, routed —
see .github/agents/planner.agent.md). Only then add ai:ready.
- Partition for parallelism: tasks meant to run concurrently must have
disjoint File ownership path sets. If two tasks need the same paths,
add a
blocked-by edge between them — serialization by dependency beats
merge-conflict roulette.
The frontier
Frontier = open Task issues labeled ai:ready whose blocked by issues are
all closed. This is the set an orchestrator may dispatch right now.
- Compute it with
.github/skills/plan-management/scripts/frontier.sh, or manually per issue:
gh issue view <n> shows Blocked by: rows; each listed issue must be
CLOSED. (Dependency data is also exposed as JSON fields in gh ≥ 2.94 — run
gh issue view <n> --json with no field list to see the exact field names
your version supports.)
- Before dispatching two frontier tasks together, re-check ownership
disjointness — the graph guarantees ordering, not file safety.
Command cookbook
Body files start from the canonical templates bundled with this skill:
templates/epic-body.md and templates/task-body.md (issue forms in
.github/ISSUE_TEMPLATE/ mirror the same sections but apply only to the
web UI).
gh issue create --title "Epic: <outcome>" --label "type:epic" --body-file epic-body.md
gh issue create --title "<task title>" --label "type:task,exec:cloud,ai:ready" \
--body-file task-body.md --parent 12 --blocked-by 14,15
gh issue edit 23 --add-blocked-by 22
gh issue edit 23 --remove-blocked-by 14
gh issue view 23
gh issue list --label "ai:ready" --state open --json number,title,labels
Roadmap scheduling
Optional: visualize Epics and Tasks as spans on a Projects v2 roadmap. The
board stays a view of the issue graph — fields are derived from issues,
never the reverse (see the Portfolio view row in the Data model).
Bootstrap the board once per repository (idempotent: reuses the same-title
project, skips existing fields, re-links safely). init creates the DATE
fields Start date / Target date plus a single-select field Kind
(options Epic, Task) so both issue kinds are distinguishable on the
board:
scripts/setup-project.sh init
Projects v2 boards cannot be repo-owned — they always belong to a user or
org, so the board URL is github.com/orgs/<owner>/projects/<n> (or
/users/...). That is normal. init links the board to the repository,
which makes it appear in the repo's Projects tab
(https://github.com/<owner>/<repo>/projects) — look for it there. Pass
--owner <login> only to place the board under a different user/org.
Set an issue's schedule span when the Task is created during decomposition,
and update it whenever replanning moves the schedule (re-running replaces
both dates on the existing item). The same call sets Kind automatically
from the issue's labels — type:epic → Epic, type:task → Task:
scripts/setup-project.sh dates --project <number> \
--issue <n> --start 2026-07-07 --target 2026-07-11
One-time manual steps: in the project UI, add a Roadmap view, pick
Start date / Target date as its date fields, and set Group by to
Kind so Epics and Tasks render as separate swimlanes. View creation and
configuration (including Group by) are not exposed by the GitHub API, so
init cannot script this part; it reminds you on every run.
Replanning procedure
Trigger: a Task closes with recorded deviations; a needs:replan label
appears; an Epic's assumptions are invalidated; or the frontier is empty while
the Epic is unfinished.
- Read the triggering record (issue comment / PR "Deviations" section). The
trigger must already be written down — if someone asks you to replan from a
verbal report, record it on the issue first (persistence rule,
AGENTS.md).
- Walk the downstream graph: the trigger issue's
Blocking: list, its Epic's
remaining sub-issues, and any task whose File ownership or references
mention the changed area.
- For each affected issue decide: keep / modify / split / add / close.
Apply the decisions with
gh issue edit / create / close — edit the
graph, don't just talk about it. Closed-as-obsolete issues get a one-line
reason; never delete issues (history is the audit trail).
- Remove
ai:ready from any task whose brief is no longer accurate; restore
it only after the brief is fixed.
- Post one rationale comment on the Epic: what changed, why, and the list of
added/modified/closed issue numbers. This comment stream is the diff log of
the schedule.
- Clear the
needs:replan label from the trigger issue.
Anti-patterns
- Giant tasks ("implement the whole feature") — undispatchable and
unreviewable; split until each task fits one session/PR.
- Hidden ordering in prose ("do this after the API lands") without a
blocked-by edge — invisible to frontier computation, so it will be
violated by a parallel dispatch.
- Plan-in-a-file drift — maintaining the real plan in a
plan.md while
issues rot. Session-local plan files are caches (see
session-orchestration); the graph is the truth.
- Premature detail — fully decomposing phase 4 while phase 1 is running;
you will rewrite it, and stale
ai:ready tasks are dispatch hazards.