5.7 KiB
name, description, user-invocable, args
| name | description | user-invocable | args | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| plan-milestone | Turn a design doc or feature idea into a tracker milestone with a filed, labeled, interdependent issue set — by auditing what already exists, grilling the operator through the open decisions, and drafting the full set for approval before filing. The milestone is the handoff unit: /blitz <milestone> sweeps it, and parallel planning efforts stay distinguishable. Use when the user wants to plan a feature area into issues, e.g. "plan TV tracking" or "/plan-milestone §6 of DESIGN.md". | true |
|
Plan Milestone — Design to Issue Set
Produces a tracker milestone holding a set of issues another session can
land one at a time — /blitz <milestone> is the intended consumer, /yolo
works per issue. The milestone is what keeps two concurrent planning efforts
apart: every issue this skill files belongs to the milestone it creates. The
output is the milestone; this skill never implements anything.
First: read tracker-common/COMMON.md (sibling skill, same skills root)
for project config and tracker API conventions.
1. Ground yourself
- Read the design document end to end if the repo has one (
DESIGN.mdor whatever CLAUDE.md names as the contract). The design doc is authoritative: if planning surfaces a contradiction, the fix is a design-doc amendment issue, never an issue that quietly contradicts it. - Audit what already exists — code, migrations, API surface, closed issues — so the set covers the gap, not what is built. Plan from evidence, not from the doc's table of contents.
- Learn the label taxonomy: the repo's CLAUDE.md, or the tracker's existing
labels. A good taxonomy has one label per axis per issue (e.g.
phase/,area/,difficulty/,type/). If the repo has none, propose one to the operator before drafting.
2. Grill the operator
The operator holds decisions the design doc doesn't. Interview them in batches, one batch at a time — a wall of twenty questions gets skimmed; four pointed ones get answered.
- Ask about behavior, not implementation: semantics, defaults, edge cases, what "done" looks like for the user.
- Challenge vague answers and surface tradeoffs ("per-episode grabbing doubles indexer load — accept that or prefer season packs?").
- Where the design doc is thin or self-contradictory, say so explicitly and get a ruling.
- Record each settled decision in one line; these lines become issue-body context.
Stop interviewing when new questions stop changing the issue set.
3. Draft, then file
Draft the complete set and show it to the operator for approval before filing anything. For each issue:
- Title: imperative, specific, no scope words like "improve" or "handle".
- Body: the settled decisions it depends on, pointers into the design doc
(cite sections, don't restate them), and explicit non-goals when adjacent
scope is likely to creep. Still write
Depends on: #Nlines for a human skimming the body, but they are cosmetic — the tracker's real dependency graph, not prose, drives execution order (see step 2 below). - Labels: exactly one per axis. Difficulty drives model selection downstream, so calibrate it against the work's real shape, not its size — a large mechanical issue is easy; a ten-line scoring change can be hard.
- Scope: one session must be able to land it without widening it. If a draft needs two sessions, split it; if two drafts always land together, merge them.
After approval:
-
Create the milestone (
POST $BASE/api/v1/repos/$REPO/milestones) named for the feature area, with a one-paragraph description linking the design doc section and stating the goal. Reuse an existing open milestone only if the operator says this plan extends it. -
File each issue with the milestone set (
milestone: <id>in the create payload), then its labels. An issue outside the milestone is invisible to/blitz <milestone>— the milestone link is not decoration, it is the execution boundary. Keep theDepends on: #Nbody lines from the draft — don't strip them once real dependencies exist, they're what a human reading the issue sees. -
Wire real dependencies. File issues in dependency order (blockers before dependents) so every
#Nreferenced already has a number. For eachDepends on: #Nline on a just-filed issue#M:curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \ "$BASE/api/v1/repos/$REPO/issues/$M/dependencies" \ -d "$(jq -nc --arg owner "$OWNER" --arg repo "$REPO_NAME" --argjson index $N \ '{owner: $owner, repo: $repo, index: $index}')"ownerandrepoare required even for a same-repo dependency. Gitea resolves the blocker by owner/repo/index, and omitting them returns a bare 404 with no explanation.$REPO_NAMEis the repo name alone, notowner/repo.This is Gitea's actual dependency graph (
GET .../issues/$M/dependencieslists it) —/blitzreads this, not the prose. The body text stays for human readers; the API call is what makes it load-bearing. -
Report the milestone name plus the issue numbers with their dependency edges so the operator can eyeball the DAG, and note the follow-up command:
/blitz <milestone>.
What this skill must not do
- Implement, branch, or push code.
- File before the operator has seen the full set.
- Restate design-doc content in issue bodies — reference it.
- Leave a dependency implied in prose (
Depends on: #N) but missing from the real Gitea dependency graph. - File an issue without the milestone link.