solve-milestone
Skill2 starsChanged 16 days agoMITView on GitHub
This skill should be used when the user invokes "/milestone-driver:solve-milestone <name>", or asks to "solve a milestone", "drive a milestone", or "work the milestone autonomously". Iterates every issue in a GitHub milestone in dependency order via /milestone-driver:solve-issue, integrating per the resolved integrationGranularity. Runs unattended: parks blocked or gapped issues and continues; only a systemic failure ends a run early. Builds mutually-independent issues within a Wave concurrently in git worktrees by default; a run-start barrier check drops to sequential only when a barrier is present.
- Commits and pushes
In this repository3 other files it gives its agents.
- setupSkill
- solve-issueSkill
- triageSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
19 rules. About 0 are common, 3 are distinctive, and 16 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
16
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 7
If ${CLAUDE_PLUGIN_ROOT} appears unexpanded, it is the parent of the skills/ directory that holds this file.
- Distinctive: line 15
Execution mode: parallel by default: No flag, no opt-in. Resolved once at run start by the barrier cascade in the last Before-starting step …
- Very specific: line 23
Auth preflight: Run gh auth status. Non-zero exit, or output containing "not logged in" / "authentication failed" → print Error: gh auth …
- Very specific: line 24
Read the profile (docs/profile-schema.md).
- Very specific: line 59
All downstream steps use the resolved {number, title}.
- Very specific: line 103
Read versioning. versioning: false → skip this step.
- Very specific: line 138
Create one TodoWrite item per issue (Codex: skills/runtime-codex.md).
- Very specific: line 140
(a): every issue in dependencyGraph.edges["<n>"] (those this issue directly DEPENDS_ON) is already merged to integrationBranch, or, under …
- Very specific: line 141
Before (b): where (a) holds and edges["<n>"] is non-empty, read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/blocked-label-clear.md and run …
- Very specific: line 145
If buildable: read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/sequential-loop.md and run its per-issue build steps 1–4 (re-sync the build …
- Very specific: line 196
Never escalate scope to
protectedBranch: No PR, push, or merge targets protectedBranch. - Very specific: line 252
After this update every input the next wave needs is on disk (.milestone-config/.runtime/wave-state.json, …
- Very specific: line 283
Read ${CLAUDE_PLUGIN_ROOT}/skills/citation-format.md - the one format every citation in those slots takes.
- Distinctive: line 291
Use Template 3 as the layout.
- Distinctive: line 299
The run ended because: no buildable issues remain - not because it is waiting on a human.
- Very specific: line 302
Output ordering (clean-completion path only): do not emit Template 3 until ### Simplify pass and step 6 have both completed or skipped …
- Very specific: line 306
Runs on the clean completion path only: When the systemic-halt path reaches the Final summary, skip this step and go straight to ## …
- Very specific: line 321
After Template 3, emit a PushNotification:
- Very specific: line 329
Skip cleanly: No usage file for this milestone (zero dispatches) → --finalize fails open on its own, one log line, no zero-value record.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
If ${CLAUDE_PLUGIN_ROOT} appears unexpanded, it is the parent of the skills/ directory that holds this file.
solve-milestone - autonomous driver
Order a milestone's issues, run /milestone-driver:solve-issue on each, integrate per the resolved integrationGranularity. Owns ordering, the loop, branch re-sync, parking, the final summary; solve-issue owns the per-issue pipeline. Coherence pass (coherenceReviewAgent, read-only, never gates). Runs per-issue in solve-issue section 6, before that issue's /code-review, under issue and wave granularity. Under wave granularity in parallel mode it also runs at the Phase-2 merge-tail re-verify point (skills/solve-milestone/parallel-waves.md § Parallel mode - Phase 2: serial verified merge tail), against the integrated wave. Under milestone granularity it runs once, never per issue, at skills/solve-milestone/milestone-end-gates.md § The ordered sequence step 3, against the whole branch. Absent → skip silently.
Blast radius. Merge only to integrationBranch, never protectedBranch. Release, closing the milestone object, and deploy are human-only. This skill closes the milestone's issues and authors the CHANGELOG; never the milestone.
Execution mode: parallel by default. No flag, no opt-in. Resolved once at run start by the barrier cascade in the last Before-starting step (Resolve execution mode), then held all run. A typed --parallel in $ARGUMENTS is stripped and ignored by step 3's --<token> strip.
Contents
Before starting · The procedure - 1. List the milestone's open issues · 2. Determine the order · 3. Determine the target version · Phase 0 - Triage · 4. Loop over issues in dependency-graph order · Permission pre-flight gate · Simplify pass · 5. Finish · Autonomy · Output spec - Template 1 - Run start / plan board · Template 2 - Status update at each wave boundary · Template 3 - Final results · Output style - Main-thread context · Final summary - 6. Author the CHANGELOG entry · Run-complete notification
Before starting
- Auth preflight. Run
gh auth status. Non-zero exit, or output containing "not logged in" / "authentication failed" → printError: gh auth status failed - authenticate with 'gh auth login' before running solve-milestone.and halt. Read the profile (
docs/profile-schema.md).Decision point Behavior Resolution order (READ only; no migration here) <repo>/.milestone-config/driver.json, else legacy root<repo>/milestone-driver.json. Both present →.milestone-config/driver.jsonwins; no move, no overwrite, no deletion of the leftover.Migration ( git mv) of a legacy layoutNever on this orchestrator's own working tree. The first dispatched solve-issueperforms it on its feature branch at step 3.5. An all-parked milestone defers it to the next building run; the transitional READ covers the gap.Neither file exists, or integrationBranch/protectedBranch/sourceGlobsmissingInvoke milestone-driver:setup, then continue. Do not fail.implementerAgentDefaults to milestone-driver:implementer.Optional keys - unitTestCmd,e2eTestCmd,e2eEnv,domainSkills,nonNegotiablesTheir steps skip cleanly when absent. integrationGranularity(resolve here, once, hold all run)Absent → "milestone". Fail-open, never a hard error: an out-of-enum value degrades to"milestone", loggingintegrationGranularity "<value>" is not one of "issue", "wave", "milestone", degraded to "milestone". A valid value logs nothing; every later read uses it.2.0.5. Self-heal the scratch-ignore, always, before any
.milestone-config/scratch write. That directory also holds tracked config (driver.json,feeder.json): never add a bare*or/rule, which swallows both. The suffix-scoped*-noticedoes not. Ensure a committed.milestone-config/.gitignorecarrying the block below: absent →mkdir -p .milestone-configand write it; present → do nothing. The first dispatchedsolve-issuecommits it alongside the migration.<!-- KEEP THIS BLOCK IN SYNC with the committed .milestone-config/.gitignore in this repo and with solve-issue / scripts/triage-cache.{sh,ps1} / hooks/tests-green.{sh,ps1}, feeder setup / plan. --># milestone-driver / milestone-feeder per-clone scratch - git-invisible by default. # Committed so per-run scratch stays out of `git status` with zero user setup. # Patterns are relative to this .milestone-config/ directory. Tracked config # (driver.json, feeder.json) is intentionally NOT listed, so it stays tracked. *-notice triage-cache.json tests-stamp .runtime/ worktrees/2.0.6. Assemble common.md once; hold its path all run:
mkdir -p <repo-root>/.milestone-config/.runtime/plans, then${CLAUDE_PLUGIN_ROOT}/scripts/assemble-common.{sh,ps1} <repo-root> <repo-root>/.milestone-config/.runtime/plans/common.md [<anchor> ...], one<anchor>perstandingDocsentry, prefixed with the resolvedprojectDocs. A nonzero exit logs its stderr and re-runs with no anchors (fail-open); a second one holds no path. The main thread never readscommon.md.2.1. One-time notices. Immediately after the profile read: read
${CLAUDE_PLUGIN_ROOT}/skills/notices.mdand, in file order (= print order), evaluate each section whoseSkillsfield includessolve-milestone, applying itsTrigger→Text→Marker→Legacy fallbackmechanics exactly as stated there.Resolve the milestone argument. Strip flags from
$ARGUMENTS: a flag is a token starting with--. Remove each--<token>, plus the following token when it does not start with--and the flag is value-bearing (--paralleland--drivenare boolean - strip the flag alone; any other--<token>followed by a non-flag token counts as value-bearing, strip both). Then:- Purely numeric (digits only):
gh api repos/{owner}/{repo}/milestones/<milestone-number> --jq '{number, title}'. Found → record the canonical{number, title}, state"Resolved milestone #<milestone-number> → '<title>'". Not found → print the available-milestones table and stop. - Otherwise (title):
gh api "repos/{owner}/{repo}/milestones?state=all&per_page=100" --paginate --jq '.[] | select(.title=="<name>") | {number, title}'. Found → record it, state"Resolved milestone '<title>'". Not found → stop the same way. - Numeric-title halt. Resolved title purely numeric → halt and prompt the human; do not proceed to Phase 0. Triage reads a bare number as single-issue mode, so a purely-numeric milestone title must be renamed to a non-numeric one before this skill can drive it unattended.
- Available-milestones table (error path):
gh api "repos/{owner}/{repo}/milestones?state=all&per_page=100" --paginate --jq '.[] | [.number, .title] | @tsv'as a Markdown table with columns#andTitle.
All downstream steps use the resolved
{number, title}; do not re-read$ARGUMENTS. 3.5integrations.trellopresent → read${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/trello-sync.mdand run its run-start card resolution (best-effort; a Trello failure never blocks the run). 3.6 Cherry-pick check for a milestone under a parent group. Fires only when--driven(step 5) is absent; when present, none of it runs - not the first-issue query, not the parent lookup. When absent:a. Find the milestone's first issue - lowest issue number,
--state allso a fully-built milestone stays inspectable:gh issue list --milestone "<resolved-title>" --state all --json number --jq 'sort_by(.number) | .[0].number'. Nothing returned → fall through to step 4. b. Read that issue's parent, checkingmd-epicin the same call:gh api repos/{owner}/{repo}/issues/<first-issue>/parent. 404 → no parent. Any other successful response already includes.labels- check those for an exactmd-epicmatch, no second call. A non-404 failure (auth, 5xx, network) is systemic, not "no parent" - surface it and halt per## Autonomy. c. No parent, or a parent withoutmd-epic→ fall through to step 4, no prompt. d. A parent carryingmd-epic→ read${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/md-epic-parent-check.mdand run it: the three-option prompt (build just this milestone · hand off to/milestone-driver:solve-issue <parent-number>· pause), each option's branch, and the reactive-only out-of-order note. Reached on no other path.- Purely numeric (digits only):
- Confirm the working tree is clean and the local
integrationBranchis current (git fetch, fast-forward). Record its tip (git rev-parse <integrationBranch>) asmilestoneBaseCommit, held all run for### Simplify pass. Resolve execution mode (the last Before-starting step). Resolve once, here; hold all run. Evaluate the cascade top-down; first match wins:
The
--driventoken. An interpreted token, not a parsed CLI flag - recognized by string presence in the invocation text, never argument parsing. Only an internal caller dispatching this skill supplies it. It gates only row 4 (the DB-hazard interview): a driven run takes row 4′ instead of prompting. Every other Before-starting prompt is unaffected - step 3's numeric-title halt still halts and prompts on a driven run.# Condition Resolved mode Dispatch Surfacing 1 profile parallel: falsesequential background leaf dispatch ok if the gate passes, else synchronous quiet - standing opt-out 2 permission-allowlist gap ( ### Permission pre-flight gate)sequential synchronous 🔴 gap table + recommend /fewer-permission-prompts3 profile parallel: trueparallel background quiet - asserted safe 4 unitTestCmdset andparallelabsent and interactiveinterview → user's choice, persisted to parallelper choice 🔴 up-front prompt (below) 4′ same as row 4 but ( MILESTONE_DRIVER_NONINTERACTIVE=1OR--drivenpresent)sequential background leaf dispatch ok if the gate passes, else synchronous loud ⚠note + how to setparallel: true; no persist5 otherwise parallel background quiet - default The permission pre-flight gate runs here, once (
### Permission pre-flight gate): a gap → synchronous dispatch + sequential mode (row 2); no gap → background dispatch is available and the cascade continues. The in-loop references (sequential-loop.mdstep 2,parallel-waves.mdPhase 1 step 3) read this decision; the gate never re-fires mid-loop.DB-hazard interview (row 4). Trigger:
unitTestCmdset andparallelabsent - the only trigger. Fire once, before Phase 0: read${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/db-hazard-interview.mdand run it - the prompt, the Yes/No branches writingparallel: true/falseto.milestone-config/driver.json, the persistence rule, and the row-4′ path (MILESTONE_DRIVER_NONINTERACTIVE=1OR--driven), which skips the prompt, falls to sequential with a loud note, and persists nothing.Nothing to decide:
parallelabsent andunitTestCmdabsent → row 5 → parallel, quiet; no interview, no persisted value.Surface the resolved mode and its reason; it drives Template 1's mode line.
5.1 Remediate handoff - the run-start question. Is
/milestone-feeder:remediateresolvable in this session? Not resolvable → no question, one log line, silent degrade; file never read. Resolvable → read${CLAUDE_PLUGIN_ROOT}/skills/remediate-handoff.mdand run## The run-start questionverbatim - asked once, held all run, never re-asked per issue.MILESTONE_DRIVER_NONINTERACTIVE=1→ do not ask: take that file's non-interactive default with a loud⚠note (--drivendoesn't gate this). Never copy its procedure here.
The procedure
1. List the milestone's open issues
gh issue list --milestone "<resolved-title>" --state open, using the title resolved in Before-starting step 3.
2. Determine the order
The milestone description is the ordering source of truth. Read it (gh api "repos/{owner}/{repo}/milestones/<resolved-number>" --jq '.description', else gh api "repos/{owner}/{repo}/milestones?state=all" --jq '.[] | select(.title=="<resolved-title>") | .description') and follow the Wave / dependency sequence it records. No explicit order → fall back to ascending issue number and state that in the run output.
3. Determine the target version
Read versioning. versioning: false → skip this step; record "version-free run - no version determined or bumped" and proceed to Phase 0.
Otherwise (true or absent) → read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/version-target.md and run it: the deterministic extractor ${CLAUDE_PLUGIN_ROOT}/scripts/extract-version.{sh,ps1} (never parse by judgment), its branch table, fail-open behavior, and non-interactive degradation. Hold that target for the loop.
Phase 0 - Triage
Invoke triage across the milestone before the build loop:
/milestone-driver:triage <resolved-title>(Pass the resolved title - triage's bare-number path means single-issue mode.)
- Present triage output. Surface the all-clear or gap table; triage's output carries the Wave-ordered dependency graph either way.
Apply triage-recommended park labels. Triage posts the
🔴 Triagecomment but applies no labels; that is this skill's job. For every issue whereissueStates[n].blockers == true, apply itsissueStates[n].label("needs design"or"needs decision") with the apply-time label helper from${CLAUDE_PLUGIN_ROOT}/skills/setup/SKILL.mdPhase 4, using that taxonomy table's hex color and description. WhereissueStates[n].clearLabel == trueinstead, remove the one park label the issue live-carries and add none (skills/triage/blocker-resolver-dispatch.md (Unparking)):gh label create "<name>" --color <hex> --description "<desc>" --force gh issue edit <n> --add-label "<name>" gh issue edit <n> --remove-label "<name>" # clearLabel == trueUnder a held Auto answer, every issue parked here enters the
## The Auto loopin${CLAUDE_PLUGIN_ROOT}/skills/remediate-handoff.mdbefore step 3 - same gated read-direct, on this main line, cap 1 per issue per run; aNEEDS_HUMANreturn or a still-dirty re-triage parks for good (skills/remediate-handoff.md (Park for good)).
2.5. integrations.trello configured → run trello-sync.md ## Phase 0 hooks (best-effort).
- Seed the build queue. Carry triage's full
dependencyGraphandissueStatesinto the loop; the loop drives from the validated graph, not the raw declared order.
4. Loop over issues in dependency-graph order
Mode branch point. In parallel mode: read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/parallel-waves.md and run its Wave loop - parallel-waves.md § Parallelizable-set selection (parallel mode), then § Parallel mode - Phase 1: concurrent stage dispatch, § Parallel mode - Phase 2: serial verified merge tail, § Integration granularity (issue vs wave) - instead of the sequential build steps below. Never silently degrade to sequential. In sequential mode it is never read.
- Granularity branch point (orthogonal to the mode branch). Under
integrationGranularity: "milestone", read${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/milestone-granularity.md:§ Branch modeland§ Folding an issue into the milestone branchown condition (a) and every re-sync below;§ Creating the milestone branchcutsmilestone-<number>-<slug>fromintegrationBranchhere, before any issue branch. Every issue branch this run is cut from it; nothing reaches origin until milestone end. Under"issue"never read; under"wave"only where cited.
Create one TodoWrite item per issue (Codex: skills/runtime-codex.md). Process issues Wave by Wave; within a Wave, mutually independent issues may be taken in any order. For each issue, determine whether it is buildable this pass - iff all three hold:
- (a) every issue in
dependencyGraph.edges["<n>"](those this issue directly DEPENDS_ON) is already merged tointegrationBranch, or, underintegrationGranularity: "milestone", carries itsIssue: #<n>trailer on the milestone branch (milestone-granularity.md § Resume and buildability from the trailer); and- Before (b): where (a) holds and
edges["<n>"]is non-empty, read${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/blocked-label-clear.mdand run it.
- Before (b): where (a) holds and
- (b) the issue currently carries no blocker label - check live:
gh issue view <n> --json labels --jq '[.labels[].name]', confirming none ofneeds design,needs decision,blockedis present. This live check is the authoritative park-state. A labeled issue must not be rebuilt until a human (or Phase 0's Auto remediate loop) clears the label; and - (c)
issueStates[n].blockers == false.
If buildable: read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/sequential-loop.md and run its per-issue build steps 1–4 (re-sync the build target → run solve-issue <n> in-thread with the held values restated → park-and-continue on STOP/PAUSE → on-success terminal states, trello tick, milestone-granularity fold). In parallel mode it is never read.
If not buildable (triage-parked, live-label park, or dependency not yet merged): read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/not-buildable.md and run it: the park-label back-fill for a triage/prior-run park, and the blocked label, 🔴 Blocked comment, and transitive holds for a dependency hold. Both modes read it when an issue is not buildable.
The loop never waits on a human. Every issue ends merged or parked (label, open branch if applicable, comment), UI included. Park comments: triage parks carry Phase 0's 🔴 Triage comment; build-time parks, the reason posted at sequential-loop.md step 3c; dependency holds, 🔴 Blocked (not-buildable.md).
In versioned mode the first issue's commit sets plugin.json to the target version; every later PR is idempotent.
Permission pre-flight gate
Runs once per run, at run-start mode resolution (row 2 above), before any dispatch - whenever background dispatch is about to be used. The mode cascade and the loop read its result.
Allowlist source. Union permissions.allow from these three settings layers, which the autocompact notice (${CLAUDE_PLUGIN_ROOT}/skills/notices.md) also reads autoCompactWindow from; absent or unreadable layers are skipped in the union, not counted as gaps:
| Priority | File |
| 1 | ~/.claude/settings.json (user global) |
| 2 | .claude/settings.json (project) |
| 3 | .claude/settings.local.json (project local) |
<!-- KEEP THIS BLOCK IN SYNC with skills/solve-issue/permission-preflight.md § Tool surface and response, its second copy. -->Pipeline tool surface. The union must cover at minimum:
| Tool category | Required grants |
| Read-only gh ops | gh pr list, gh issue view, gh issue list |
| Git | git commit, git push |
| PR / issue writes | gh pr create, gh pr merge, gh pr edit, gh pr comment |
| Issue management | gh issue edit, gh issue comment, gh issue close |
| Label management | gh label create |
| Planner leaf | Write to .milestone-config/.runtime/plans/issue-<n>.md, git rev-parse, Skill |
| Profile-defined commands | Each command in unitTestCmd, preflightCmd, e2eTestCmd (skip if absent) |
Gap detection and response. No gaps → proceed with background dispatch. Gap detected (missing surface coverage, or no readable layer) → do not dispatch in the background: (1) surface a 🔴 gap table naming each missing grant and which layer(s) could supply it; (2) fall back to synchronous dispatch for this run; (3) recommend the consumer run /fewer-permission-prompts (see docs/consumer-setup.md). That result holds for the run; do not re-read settings per issue.
Auto-deny handling. A background leaf reporting an auto-deny it could not work around is a park: post a blocked comment naming the denied tool, apply blocked (+ in progress if the branch has commits), preserve the branch, continue.
Simplify pass
Runs once, after step 4's loop exhausts, on the clean-completion path only; a systemic halt skips it. Read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/simplify-pass.md and run it.
5. Finish
The run ends when no buildable issues remain.
integrations.trello present → apply ## Finish hooks from ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/trello-sync.md (best-effort; skipped updates surface in the final summary).
Autonomy
- Unattended between systemic failures. Operate autonomously within an explicit
/milestone-driver:solve-milestonerun. Asolve-issueSTOP or PAUSE parks that issue (label + open branch + comment) and the loop continues. - Systemic failures that halt the run (examples):
gh authfailure, a broken or inaccessibleintegrationBranch, missing required tooling (gh,git), and any reference file this skill read-directs being missing or unreadable once its condition has fired -parallel-waves.md,milestone-granularity.md,blocked-label-clear.md,sequential-loop.md,not-buildable.md,md-epic-parent-check.md,version-target.md,db-hazard-interview.md,changelog-authoring.md,milestone-end-gates.md. Best-effort integrations (trello-sync.md,simplify-pass.md,coherenceReviewAgent) degrade silently instead. These are conditions where no further issue can make progress: surface the failure, leave the tree clean, all in-flight issues parked, present the summary, and stop -## Run-complete notificationemits🚨 Run halted - <reason>. - Architecture is locked per issue at its plan-approval time. A plan proven wrong is a park (STOP → park + continue), not a silent redesign.
- Never escalate scope to
protectedBranch. No PR, push, or merge targetsprotectedBranch.
Output spec
<!-- KEEP THIS ICON LEGEND BYTE-IDENTICAL across solve-issue and solve-milestone. -->Icon legend: ✅ merged · 🔨 building · ⏭️ queued · ⏸️ parked · 👁️ UI surface / visual evidence · ⚖️ judgment call · 🔴 Your move
Template 1 - Run start / plan board
Show after Phase 0 triage completes.
🚀 Milestone v[version] - [N] issues · [W] waves · [resolved mode: parallel | sequential (<reason>)] · ~[T]–[T2] min
develop ← integration PRs · profile: <H> heavy / <L> light
| Wave | Issue | Title | Risk | UI | Status |
|------|-------|--------------------------|-------|----|-------------|
| 1 | #201 | Background wave dispatch | heavy | - | 🔨 building |
| 2 | #203 | Status board templates | light | 👁️ | ⏭️ queued |
⏸️ Parked at triage: #202 - needs design (contradictory grouping spec)
▶ Wave 1 dispatched - the floor is yours.Mode cell: parallel, or sequential (<reason>) where <reason> ∈ { profile parallel:false, permission gap - see 🔴, test-isolation not confirmed }.
Template 2 - Status update at each wave boundary
Show after each Wave completes.
<!-- Structural mirror of solve-issue Template 2; keep column schema (Issue/Result/Gates/PR/Note) in sync. -->🌊 Wave [N] done · [T] min · milestone [done]/[total] ✅
| Issue | Result | Gates | PR | Note |
|-------|-----------|------------------|------|-------------------------|
| #201 | ✅ merged | 🧪✓ 🔍✓(2 fixed) | #301 | ⚖️ quarantined flaky E2E |
| #202 | ⏸️ parked | - | [#pr | -] | needs decision: new dep |
▶ Next: Wave 2 (#203 👁️, #204) - redirect or reprioritize before it lands.PR cell: the PR number if the issue has one, else -.
Note cell: an issue sent through the Auto loop shows remediated, cleared (clean re-triage, label cleared), remediated, still parked (cap spent or still dirty), or NEEDS_HUMAN, parked (skills/remediate-handoff.md (Park for good)). No Auto loop → cell unchanged. A slow first build adds its note per skills/solve-issue/SKILL.md (Slow first build:).
Milestone end row (integrationGranularity: "milestone" only). Once skills/solve-milestone/milestone-end-gates.md's sequence finishes, print one Template-2-shaped table before Template 3:
🏁 Milestone end · [T] min
| Issue | Result | Gates | PR | Note |
|---------------|---------|-------------|----|--------------------|
| milestone end | ✅ done | 🧪✓ 🔍✓ 🌐✓ | - | 2 fix dispatches |Note cell: <F> fix dispatches (0-3); a cap-spent revert appends ; reverted #<n>. No commits on the milestone branch → no row; any other resolved integrationGranularity never prints it. ## The run-scoped handler path prints ⏸️ needs review instead of ✅ done, the Note cell naming the reason (an open finding, or an unattributed red gate).
Gates legend: 🧪 = unit suite · 🔍 = code review · 🌐 = E2E. Milestone end row: 🧪✓ 🔍✓, plus 🌐✓ only with a ui-labeled issue and e2eTestCmd defined; coherence review and preflight get no symbol, as in the per-issue Gates cell.
After this update every input the next wave needs is on disk (.milestone-config/.runtime/wave-state.json, .milestone-config/triage-cache.json, the milestone branch), so compaction here loses nothing; session-resume re-injects the checkpoint.
Template 3 - Final results
The layout for ## Final summary below; fill the metadata lines from that section's requirements.
🏁 v[version] complete · [T] min · ✅ [M] merged · ⏸️ [P] parked
| Issue | Outcome | PR | Follow-up |
|-------|-----------|-------------|--------------------------------------------|
| #201 | ✅ merged | #301 | - |
| #203 | ✅ merged | #303 | 👁️ visual evidence attached |
| #202 | ⏸️ parked | [#pr | -] | clear `needs decision` (new dep) |
Judgment-call PRs: [list or "none"]
PRs missing Code Review section: [list or "none"]
Auto-resolved conflicts: [list or "none"]
Per-wave sizes: Wave 1 · [N] issues · [T] min | Wave 2 · …
🔴 Your move:
1. Sanity-check the ⚖️ judgment-call PRs and any PR listed as missing a Code Review section
2. Clear park labels → re-run
3. All merged → merge `integrationBranch` → `protectedBranch` with `--merge` (not squash), merging the release PR *before* tagging, then **back-merge `protectedBranch` → `integrationBranch`** (history-only, conflict-free) so `integrationBranch` stays tag-current and topologically even, close the milestone (`gh api -X PATCH repos/{owner}/{repo}/milestones/<number> -f state=closed`), deploy - full ordered runbook in `docs/consumer-setup.md` § "Releasing to your protected branch"PR cell: the PR number if the issue has one, else -. Follow-up cell: the same auto-remediate outcome Template 2's Note cell records.
Output style
Read ${CLAUDE_PLUGIN_ROOT}/skills/output-style.md - this plugin's output contract. ## Terminal output governs what this skill prints (including the ## Output spec template rule); ## GitHub-facing prose, ## When prose is the correct form, and ## Evidence slots govern every issue comment, PR body, and CHANGELOG entry it writes. Plain English. Write every response, document, and GitHub issue, milestone, comment, and PR body in plain, concise English. Never include hypothesis, conjecture, or defensive text.
Read ${CLAUDE_PLUGIN_ROOT}/skills/citation-format.md - the one format every citation in those slots takes.
Main-thread context
The orchestrator never Reads a persisted tool-result file (~/.claude/projects/<session>/tool-results/*.txt) whole, never cats a .project/ doc, the consumer brief, or a plugin reference file - it takes a section with ${CLAUDE_PLUGIN_ROOT}/scripts/read-doc-section.{sh,ps1} or sed -n. A truncated tool result is re-run with a narrower command, never re-read. Everything an agent needs travels as a path in its brief, never pasted inline.
Final summary
Use Template 3 as the layout. On completion or systemic-failure halt, report:
- Issues built and merged to
integrationBranch, with PR links. - Issues parked - per issue: number, title, park label, blocker reason, the Auto-loop outcome if attempted, and the open feature branch if applicable. Take the reason from tracked context (triage gap, STOP/PAUSE reason, or unmerged upstream). Not in active context → read
gh issue view <n> --json commentsand use the most recent matching comment: opening🔴 Triage(triage-park),🔴 Blocked(dependency-hold), or🔴 Parked(build-park). gh returns comments oldest-first, so take the LAST match. No anchored match → report "park reason not recorded (pre-1.7.0 park format)". Never invent a reason. - PRs carrying a
judgment calllabel, flagged for post-run review. - PRs missing a
## Code Reviewsection, flagged the same way, for review before theintegrationBranch→protectedBranchmerge. - Auto-resolved-conflict issues (parallel mode) - those whose merge conflict the serial verified merge tail auto-resolved, for a human to sanity-check.
- Per-Wave parallel-set sizes (parallel mode).
- The run ended because no buildable issues remain - not because it is waiting on a human.
- The next human step: review parked issues; clear park labels once their blockers are resolved and re-run for the rest; all work merged → run Template 3's
🔴 Your move:item 3 verbatim, then deploy manually.
Output ordering (clean-completion path only): do not emit Template 3 until ### Simplify pass and step 6 have both completed or skipped cleanly (skills/solve-milestone/changelog-authoring.md § 6.9 Surface in the final summary "Your move" section). On the systemic-halt path both are skipped - emit Template 3 immediately.
6. Author the CHANGELOG entry
Runs on the clean completion path only. When the systemic-halt path reaches the Final summary, skip this step and go straight to ## Run-complete notification.
Guard - skip this step entirely if either holds:
- The parked count for this run is greater than zero, OR
- The run ended via a systemic halt
The parked count comes from this run's in-context tracking - every issue that did not reach "merged": parked at build time, skipped on triage blockers, or excluded by a live blocker label (e.g. blocked from a prior run). It is Template 3's ⏸️ P count. Do not re-derive via a live gh issue list query: it may find labels unrelated to this run.
Either condition holding → post "Skipping CHANGELOG authoring - run did not fully complete (N parked)." and go straight to ## Run-complete notification - except under integrationGranularity: "milestone", where it skips only changelog-authoring.md steps 6.1-6.5: milestone-granularity.md § Milestone end still runs gates, push, and PR for whatever merged (skills/solve-milestone/milestone-granularity.md (Steps 2 to 6 run for whatever did merge.)).
Guard passes → read ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/changelog-authoring.md and run its steps 6.1–6.9 (idempotency check → PR summaries → categorize → theme → author the entry → branch name → doc-only PR → CI result → surface in the final summary).
Run-complete notification
After Template 3, emit a PushNotification:
- Clean completion:
🏁 <milestone-title> · ✅ M merged · ⏸️ P parked, the counts from Template 3. - Systemic halt:
🚨 Run halted - <reason>, where<reason>is the systemic-failure description, e.g. "gh auth failure".
Run-end cost record (additive, never-gating), survives context compaction. No in-context aggregation: each dispatch appends its usage to disk as it returns; the run-end record reads back from that file alone, the last step here on both the clean-completion and systemic-halt paths.
- Append, per dispatch, as it returns. Every Agent-dispatch this run - Phase 0 triage's own dispatches and each per-issue / per-wave
Agent(run_in_background: ...)dispatch - pipes{"agent":"<dispatch label>","tier":"<opus|sonnet>","totalTokens":<subagent_tokens>,"durationMs":<duration_ms>}to${CLAUDE_PLUGIN_ROOT}/scripts/write-cost-record.{sh,ps1} --append <milestone id>as its last step, milestone-wide: one usage file spans every Wave, so Phase 1 needs none of its own (skills/solve-milestone/parallel-waves.md (Hand the green set to Phase 2)). An implementer or planner return carryingoutput_file:merges its measurement perskills/solve-issue/SKILL.md (merges the object); that merge never gates (.project/design-philosophy.md#Error & failure philosophy). - Finalize.
${CLAUDE_PLUGIN_ROOT}/scripts/write-cost-record.{sh,ps1} --finalize <milestone id>sumstotalTokensper tier intoinputTokens(outputTokens/cacheReadTokens/cacheWriteTokensat the 0 sentinel,provenanceNote: "unsplit-total-as-input"marking it a lower-bound), sumsdurationMsintowallClockSeconds, and writes the record to.milestone-config/.runtime/cost-records/with one more field,agents: the raw per-dispatch entries. - Skip cleanly. No usage file for this milestone (zero dispatches) →
--finalizefails open on its own, one log line, no zero-value record. Writer script absent → silent no-op, one log line. Never fails the run.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

