Skip to content

build-dev-plan

build-dev-plan

buildwriteshands-off

Use this when: you want to see what to work on next

Build Dev Plan

One live, mobile-readable issue that tells you — at a glance from a phone — what to pick up next: the open work in the earliest milestone, ordered so the top item is the one to start, plus a flag for how much backlog still has no home. The work-in mirror of build-qa-plan (which does the ship-out / open-PR side).

It is a board, not an editor. organise mutates backlog structure (places, re-homes, orders, sets deps); build-dev-plan only reads that structure into a current, ordered, mobile-readable board and flags what organise still needs to fix — it changes nothing. That read-only-board / interactive-editor split is exactly why it earns its own skill rather than folding into organise (mirrors build-qa-plan being a board over the PRs). It is a status board, not a snapshot — every run re-derives the facts from GitHub.

Contract

  • Task class: build — produces/refreshes a tracking artifact.
  • Allowed tools: gh (issue/milestone list+view JSON, native Issue Types, sub-issues; issue create/edit, label create) per docs/agents/issue-tracker.md; Read/codegraph for context. (In the web/remote env the mcp__github__* tools stand in for gh.) Projects v2 Status is NOT on the REST issue / gh issue payload — read it from the board via the GraphQL API (projectItems → fieldValueByName("Status")); in the web env, curl https://api.github.com/graphql with $GH_TOKEN. Area is a label (on the REST payload). Native milestone due_on and the search count no:milestone come from REST/search, not gh issue view.
  • Direct vs fork: direct. Fork a scanner/general-purpose gather only when the issue set is large (≳25) and you want the digest, not the raw JSON, in-thread.
  • Verifiable artifact: exactly one open issue titled "Dev Plan", labelled plan, whose body reflects the current earliest-milestone work + orphan count in the format below.

Fresh data, ordered by readiness — this is the skill

The plan's whole value is that the top line is genuinely the thing to start now — so the heart is re-deriving live state and ordering by readiness, not the formatting (which is mechanical).

Re-derive every fact from GitHub on every run. Never copy a claim from the existing plan body — a milestone may have shipped, an issue's Status may have moved from Needs Info to Ready for Agent, a blocking dependency may have closed, an orphan may have been placed. A stale plan is worse than none, because it's trusted. Per in-scope issue pull live: Issue Type (Epic/Sprint/Task/Bug/Feature), milestone, sub-issue parent (Task→Sprint→Epic), Status (Projects v2 board) + Area (label), and native blocked-by dependencies (open or closed?).

Then order by readiness (the same gate organise applies, here read-only): only Ready for Agent / Ready for Human issues are startable; one at Needs Info (incl. vet-flagged) or with an open blocked-by is listed but marked held, never the next pick. Weigh Status and deps together — a held item never goes to the top. Getting this order right is where the effort goes.

Workflow

  1. Find the earliest open milestone — by the maintainer's fixed order, not by date. The milestone sequence is an explicit, maintained order (currently Foundational → Launch → post-launch buckets). The early ones are dated (Foundational, Launch) and scheduled; the post-launch buckets are deliberately undated ("do this after launch", split into a small number of buckets by urgency). So: dated milestones first in due_on order, then the undated buckets in their maintained manual order (the order on the milestones list / board) — never inferred from creation date (creation order ≠ urgency). The earliest open milestone = the first in that sequence that still has open issues. State the basis in the plan header.
  2. Walk DOWN the tree. Milestone issues are usually Epics, not leaf work — the startable items are their child Sprints/Tasks. Descend each Epic's sub-issue tree and place items under ## Epic #NN — <title> / ### Sprint <n> · <title> (#NN). A milestone issue that's itself a bare Task/Sprint (no parent) goes under **Loose in milestone**; an Epic with no sub-issues yet is listed as an empty epic that needs organise/to-issues to populate it.
  3. Order within a group by readiness then dependency: startable (Ready for Agent/Ready for Human, no open blocker) first — top item = next pick — then held items with the reason. A Sprint with all-ready Tasks is itself startable via build-sprint. If nothing is startable (everything at Needs Triage/Needs Info — common for a fresh milestone), say so plainly at the top and make the next action "triage these to Ready (via triage/organise)" rather than inventing a pick.
  4. Per issue, fill the block (template below) from live data + a one-line read of what it is and whether Claude can build it now.
  5. Compute the orphan flag — a deliberate whole-backlog health signal, kept separate from the milestone plan: count open issues with no home — untyped, OR no milestone, OR no epic/sprint parent. Exception: a Bug-typed issue that is top-level is correctly placed, not an orphan (the bug placement convention — docs/agents/triage-labels.md); never count it. It's a single number + nudge at the top, not part of the ordered plan below (those orphans aren't startable from here). It only counts + nudges organise — it never places them.
  6. Find-or-update the plan. gh issue list --label plan --state open → there may already be a QA Plan on that label; match on title Dev Plan specifically. If a Dev Plan exists, gh issue edit <n> its body; else create it. Title is always exactly Dev Plan. If the plan label is missing, gh label create plan first.
  7. Write the plan automatically — no confirm gate. Create or edit the single Dev Plan issue (and gh label create plan if the label is missing) without pausing for approval. The maintainer has given standing approval for this auto-write: the artifact is one known, in-place tracking issue, the edit is idempotent, and it spawns no work — so the write is low-risk (unlike organise, which mutates backlog structure, or a skill that opens PRs). Still surface the plan in chat so it's reviewable, and report the issue link once written. (This is the deliberate exception to the surface-then-confirm default — every other outward write in the harness still confirms.)

Format

# Dev Plan — <milestone title> (earliest open milestone)

⚠️ **<N> issues have no home yet** (untyped / no milestone / no epic·sprint parent — top-level `Bug`s excluded by convention) → run `organise` to place them.   ← ✅ if zero

## Epic #NN — <title>
### Sprint <n> · <title> (#NN)
<▶ startable | ⏸ held: reason>

- [ ] <🧩> #NN — **<readable title>** · <Status>

_<one concise line: what it is>_

**Claude can:** <build it now / needs info: what's missing / blocked-by #NN>

The sprint's status token sits on its own line (not inline after the title) so it doesn't wrap awkwardly on a narrow phone. End with the legend: ▶ startable now · ⏸ held (needs info / blocked) · 🧩 best next pick. Mark exactly one item — the single best next pick across the whole plan — with 🧩. Every #NN is a clickable Markdown link (mobile-first — see CLAUDE.md). Keep titles bold, one block per issue — no nested bullet trees (they waste horizontal space on a phone).

Failure branch

  • No milestones / none with issues → say so, fall back to listing the highest-readiness open issues regardless of milestone, and flag that milestones need setting up (point at organise).
  • No Projects board configured (Status unavailable) → order by dependencies + Type alone, and note that readiness couldn't be read.
  • An issue's parent can't be resolved → place under **Loose in milestone** and say why; don't guess a parent.

Output / handoff

The single open Dev Plan issue, current. Then offer to hand the top startable sprint to build-sprint (or the milestone's epic to build-epic) to execute, and — if the orphan count is non-zero — organise to place the homeless backlog. Pairs with build-qa-plan for the open-PR side.