milestoneplan · git:20261022.bc1e35d · 2026-10-22 · sha256 488ef025017c80d8

milestoneplan git:20261022.bc1e35dA

Immutable. This exact content never changes and is served at /api/v1/blob/488ef025017c80d8.

---
name: milestoneplan
description: Use when the user wants a milestone's execution plan shown as a table — "milestoneplan v1", "/milestoneplan", "show the plan for v1". Read-only - reads every issue in the milestone and renders one table of issue number, description, complexity, dependencies, validate/build model and effort, plan, plan effort, and first-review trigger. Never edits an issue and never launches a run. Stage 6 of the new-app-pipeline.
---

# milestoneplan

Show a milestone's execution plan as one table. **This skill never writes**: no issue edits, comments, PRs, or Workflow runs. Fixes belong to `execution-plan-review`; the run belongs to `milestone-workflow`.

## Input

A milestone title (`v1`, `v1-Desktop-core-call-loop`), matched loosely on prefix, and an optional skip list: issue numbers the user plans to pass to `milestone-workflow` as `skipValidate` (or "all"). Existing titles with spaces still match; quote them in every `gh` call and in any `milestone:` filter link, and when you name a milestone filter to the user, quote a title that has spaces. With no input, or when two titles match, list the open milestones with open/closed counts and ask which.

## Steps

### 1. Read the milestone

```
gh api "repos/{owner}/{repo}/milestones?state=all&per_page=100" --paginate --jq '.[] | "\(.title) [\(.state)] — open:\(.open_issues) closed:\(.closed_issues)"'
gh issue list --milestone "<title>" --state all --limit 500 --json number,title,state,body
```

`state=all` and `--paginate` with `per_page=100` are required. If the issue count equals `--limit`, re-fetch at a higher limit until a fetch returns strictly below its own limit. Strip `\r` from bodies, then parse the `[C<score>]` title prefix and the `## Execution` block: `Depends on`, `Runs after`, build model, effort, `plan first:` (also read the legacy `fableplan first:`), `PR review:`, and the optional `Validate model:`, `Validate effort:`, `Plan model:`, and `Plan effort:` lines.

### 2. Render the table

Output is **exactly one pipe-delimited markdown table**, one row per issue ordered by number, capped at these 8 columns:

| # | Description | C | Deps/After | Validate | Build | Plan | Review |
|---|---|---|---|---|---|---|---|

- **Description** — the title with the `[C<score>]` prefix stripped, truncated to ~30 characters.
- **C** — the score from the title prefix.
- **Deps/After** — `<depends> / <after>`, issue numbers without `#`, `none` rendered as `—` (e.g. `12, 13 / —`); never infer edges from prose. When every `Runs after` is `none`, drop the ` / —` suffix and say so in the note.
- **Validate** — `<model> · <effort>`. The model comes from the score band unless a `Validate model:` line stamps `Fable 5.1`, `Opus 5.5`, or a Codex CLI harness; the effort is the band default unless a `Validate effort:` line stamps one. A Codex CLI validate renders like a CLI build, e.g. `Astra · low (Codex CLI, gpt-6-astra)`; a Cursor CLI validate stamp renders `blocked (validate runs only on the Codex CLI)`. Band defaults: `Opus 5.5 · medium` at `[C0]`–`[C24]`, `Opus 5.5 · high` at `[C25]` and above (`validate-issue` step 6 is the authority; a missing prefix routes as Opus high). A stamped model or tier renders as the effective value plus `(stamped)`, e.g. `Fable 5.1 · low (stamped)`; the clamp follows the effective model and `validate-issue` step 6, so the pipeline clamps an Opus validate at `low` to `Opus 5.5 · high (stamped low → high: Fable-only tier)`, runs an Opus validate at `medium`, `high`, or `xhigh` as stamped or as the band default, and applies no clamp to a Fable validate at any tier. With a skip list, a listed issue renders `skipped (run arg)` when no open in-milestone predecessor (`Depends on` or `Runs after`), missing `[C..]` prefix, or missing Execution block predicts a fallback; otherwise it keeps the route with `(listed; validates: <reason>)`.
- **Build** — the stamped `<model> · <effort>`, e.g. `Opus 5.5 · high`. An external harness renders as `<Name> · <effort> (<harness>)`, e.g. `Luna · max (Codex CLI)` or `Grok · high (Cursor CLI, cursor-grok-4.6-high)` when the stamp carries a model id. `max` is Codex CLI-only, so a Cursor row stamped `max` renders the clamp the pipeline applies, e.g. `Grok · xhigh (Cursor CLI, stamped max → xhigh)`. A Claude build runs only at `high`, so a Claude row stamped any other tier renders the clamp, e.g. `Opus 5.5 · high (stamped xhigh → high: Claude builds run at high only)`.
- **Plan** — `Yes · <model> · <effort>` when `plan first:` is `Yes`: the model is the stamped `Plan model:` with ` (stamped)`, else `Opus 5.5`; the effort is the stamped `Plan effort:` tier with ` (stamped)`, else the default: `xhigh` on Opus 5.5 when the score is 85 or higher (or the title has no score) and `high` below 85. A Fable plan always renders `high`; a Fable plan stamped another tier renders `high (stamped <tier> → high: a Fable plan runs only at high)`. An Opus plan stamped `low` renders the clamp the pipeline applies, `high (stamped low → high: Fable-only tier)`. Plain `No` when stamped `No`; a `Plan model:` or `Plan effort:` line on a `No` issue renders `No · <stamp> (inert — no plan stage runs)`.
- **Review** — the first-review trigger from the `validate-issue` step 6 first-review table (a missing prefix takes its heaviest row), unless `PR review:` stamps an explicit `@claude <model> review effort:<tier>` trigger. Render a stamped bare `@claude review effort:<tier>` as `@claude opus review effort:<tier>`; a stamped bare `@claude review` with no tier, and a stamped `@claude opus review` with no tier, render as `@claude review (stamped)`; a line that names the standard `@claude` trigger in prose takes the band. Render a stamped `haiku` as `@claude sonnet review`. A stamp that matches no admitted row of `fix-pr-review-loop` step 1 renders as the band trigger with `(ignored stamp: <stamp>)`. Append a parenthetical only for a real caveat (e.g. `may close with no PR`).

Every absent field renders *missing*, never blank or a guessed default. An issue with no `## Execution` block is *missing* across the Execution-derived cells, with a note line that the pipeline builds it from the validated score band's defaults (no prefix routes as band 3).

After the table, print **one note line** covering: the Validate factoring above (`validate-issue` step 6 is the authority); rows whose stamped `Validate effort` or `Plan effort` was clamped; a run started with `keepStamps: true` keeps every stamp and skips the rescore raise below; with a skip list, that `skipped (run arg)` is a prediction: the run's skip-check still checks the evidence, the edit history, and the base branch at run time, and validates the issue normally when any check fails; rows built on an external CLI harness (the pipeline drives them through `cli-dispatch` under an Opus driver, and a rescore keeps the harness); rows whose stamped Build model or Effort diverges from the band default, naming the band value (informational: when validation confirms a higher score at run time, the pipeline raises each line below the new band default, keeps every stamp at or above it (a Fable 5.1 build or a CLI harness keeps model and effort) per `validate-issue/issue-editing.md`, and the orchestrating session restamps those merged values); and anything uniform that was dropped.

Print nothing else: no verdict, findings, wave plan, or cost projection.

### 3. Hand off

After the table, offer in one line each only the actions that apply, and launch neither unprompted:

- Stamps missing or wrong → `execution-plan-review` (it owns Execution-block edits).
- Ready to run → `milestone-workflow` (it presents its own run plan before dispatching).

## Failure modes

| Situation | Do this |
|---|---|
| Milestone has no issues | Say so; there is nothing to tabulate |
| Milestone is closed | Still render |