solve-issue
Skill2 starsChanged 15 days agoMITView on GitHub
This skill should be used when the user invokes "/milestone-driver:solve-issue <n>", or asks to "solve issue <n>", "fix issue <n>", or "drive issue <n>" through the milestone-driver gated procedure. Runs one GitHub issue end-to-end as an orchestrator - triage, dispatch the planner and approve its build packet, dispatch the implementer subagent (TDD, citations), unit + E2E gates, code review, PR to the integration branch, auto-merge on CI green, then close - never authoring application or test code on the main thread.
- Commits and pushes
2 other projects use a version of this.
Adopted by
Most recently taken up by
- edloidas/skillstheir own version, first seen Nov 1, 2026
- ypxing/coding-crewtheir own version, first seen Oct 13, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- edloidas/skills★ 2same name
- ypxing/coding-crew★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository3 other files it gives its agents.
- setupSkill
- solve-milestoneSkill
- triageSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
13 rules. About 0 are common, 0 are distinctive, and 13 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
13
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 5
If ${CLAUDE_PLUGIN_ROOT} appears unexpanded, it is the parent of the skills/ directory that holds this file.
- Very specific: line 17
Every ${CLAUDE_PLUGIN_ROOT}/scripts/*.{sh,ps1} invocation in this skill selects its host the same way: pwsh on Windows, bash elsewhere.
- Very specific: line 19
Read the profile (see the plugin's docs/profile-schema.md).
- Very specific: line 54
(d) runs inline; (a), (b) and (c) are resumes: - read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/resume-paths.md and follow its ### Resume …
- Very specific: line 59
Create one TodoWrite item per numbered step below (on Codex, this and every Agent, Skill-tool and SendMessage use: skills/runtime-codex.md).
- Very specific: line 78
Run gh issue view <n> with comments, redirected to the issue record <repo-root>/.milestone-config/.runtime/triage/issue-<n>.md by the …
- Very specific: line 97
Source the docs root: Use projectDocs already resolved at step 1 (defaults to .project/).
- Very specific: line 100
Pass the common.md path: Put the held common.md path into the ### 2 and ### 3 briefs.
- Very specific: line 162
Act: Run the gate's act per the table row.
- Very specific: line 183
After a fix, before committing: No in-scope findings → commit directly.
- Very specific: line 206
Commit on the feature branch - the tests-green hook (PreToolUse on git commit) re-checks the suite.
- Very specific: line 231
Skip cleanly: No usage file for this runId (e.g.
- Very specific: line 314
Read ${CLAUDE_PLUGIN_ROOT}/skills/citation-format.md - the one format every citation in those slots takes.
≈ “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-issue - gated per-issue procedure
Run exactly one GitHub issue through a fixed, gated pipeline. The main thread acts only as an orchestrator: read, decide, dispatch, review, integrate. It never authors application or test code itself - the force-subagent hook enforces this mechanically. Orchestrate the superpowers:* skills for the inner loop. Before anything else, check #n's labels for md-epic: a parent issue takes ### Parent path (see skills/solve-issue/md-epic-fanout.md) instead of the pipeline below.
Contents
Before starting · The procedure (0 Triage · 1 Read the issue · Build profile resolution · Resolve cited project-docs sections · Resolve cited path (anchor) citations · 2 Evaluate the codebase for root cause · 3 Dispatch the implementer · 4 Verification gates - no step 5, it merged into 4 · 6 Review → integrate → close) · Run-end cost record · Autonomy model · Permission pre-flight gate · Milestone granularity · Wave granularity · Async mode · Parent-issue detection · Output spec (Template 1 · Template 2) · Output style · Non-negotiables
Before starting
Every ${CLAUDE_PLUGIN_ROOT}/scripts/*.{sh,ps1} invocation in this skill selects its host the same way: pwsh on Windows, bash elsewhere.
Read the profile (see the plugin's
docs/profile-schema.md).Profile-resolution decision point Behavior Resolution order (transitional) Read <repo>/.milestone-config/driver.jsonfirst; if absent, fall back to the legacy root<repo>/milestone-driver.json.Both files exist .milestone-config/driver.jsonwins for the read.Migration ( git mv)Deferred to step 3.5, so it rides the feature branch and does not trip the clean-tree precondition (step 2). Do not move here. Neither file exists, or integrationBranch/protectedBranch/sourceGlobsmissingInvoke milestone-driver:setupto bootstrap it, then continue - do not fail.implementerAgentDefaults to milestone-driver:implementerwhen omitted.Optional keys - unitTestCmd,e2eTestCmd,e2eEnv,preflightCmd,domainSkills,nonNegotiables,projectDocsprojectDocsdefaults to.project/; every other step is skipped cleanly when absent.domainSkillsis expanded first (`${CLAUDE_PLUGIN_ROOT}/scripts/expand-domain-skills.<shps1> ~/.claude/plugins/cache <entry>…): its **stdout** is what the ### 2 and ### 3 briefs carry, never the raw profile value, and eachunresolved:<entry>on stderr is named there asdomainSkills unresolved:<entry>. Empty stdout is an absent key: the brief omitsdomainSkills` and still names those entries.1.1. Self-heal the scratch-ignore (always, before any
.milestone-config/scratch write). Ensure a committed.milestone-config/.gitignorecarrying exactly the block below; the directory also holds tracked config (driver.json,feeder.json), so never add a bare*or/rule, which swallows both. The suffix-scoped*-noticedoes not. Absent → create it (mkdir -p .milestone-config, then write the block). Present → do nothing. It rides the feature branch.<!-- Keep this block in sync with the committed .milestone-config/.gitignore in this repo and with solve-milestone / 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/1.1.1. One-time notices. Immediately after the profile read: read
${CLAUDE_PLUGIN_ROOT}/skills/notices.mdand, in file order, evaluate each section whoseSkillsfield includessolve-issue, applying that section'sTrigger→Text→Marker→Legacy fallbackmechanics. Never evaluate a section scoped only tosolve-milestone. 1.1.2. Remediate handoff (feeder only). Probe once: is/milestone-feeder:remediateresolvable in this session? Not resolvable → skip this sub-step: no question, no read, no error. Resolvable, and the caller supplied no answer → read${CLAUDE_PLUGIN_ROOT}/skills/remediate-handoff.mdand follow its## The feeder-installed gateand## The run-start question; hold the answer for the whole run. A caller-supplied answer (asolve-milestonerun's own run-start question) is reused, never re-asked - the held-value shape step 0's Branch A uses for the triage result.- Require a clean working tree (cold-start precondition) and a current local
integrationBranch(git fetch, fast-forward). One exception, never stashed or discarded: step 3's probe finding an existingissue/<n>-*branch (committed or uncommitted prior work) skips this enforcement. Any other dirty state is a cold-start violation. Branch-state probe (resume an interrupted run).
git fetchfirst, then classify prior progress from git + gh before cutting anything; first match wins:- (a) A PR exists for
issue/<n>-*, merged or open (client-side filter:gh pr list --state all --limit 200 --json number,headRefName,state,url --jq '.[] | select(.headRefName | startswith("issue/<n>-"))'). - (b) No PR; branch
issue/<n>-*exists (local or remote) with commits ahead ofintegrationBranch. - (c) No PR; no commits ahead; the issue branch
issue/<n>-*is checked out with uncommitted changes (the normal implementer contract). - (d) Otherwise (no branch, no PR, clean tree): cut a fresh feature branch from
integrationBranch(e.g.issue/<n>-<slug>) - cold start: run ### 2. Evaluate the codebase for root cause, then ### 3. Dispatch the implementer with itsPACKET:.
(d) runs inline; (a), (b) and (c) are resumes - read
${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/resume-paths.mdand follow its### Resume paths.This derives resume-state entirely from git + gh; there is no checkpoint file. Never skip
/code-reviewon a resumed path; a fix it triggers runs step 6's normal re-review and push cycle.3.5. Profile migration (run once, on the feature branch).
.milestone-config/driver.jsonexists → use it. Else a legacy rootmilestone-driver.jsonexists →mkdir -p .milestone-config;git mvit to.milestone-config/driver.json(plainmvwhen untracked). Else: new project - setup creates the canonical file; hooks fail-open. Idempotent; both present →.milestone-config/driver.jsonwins, no move, no deletion. The move rides the issue's PR, not a separate commit.- (a) A PR exists for
- Create one TodoWrite item per numbered step below (on Codex, this and every Agent, Skill-tool and SendMessage use:
skills/runtime-codex.md). Work them in order - do not skip or reorder.
The procedure
The park action, referenced by every park below. Post a comment on the issue in the park-comment shape (skills/output-style.md) opening with 🔴 Parked - and the reason (gh issue comment <n>); apply the named label, plus in progress when the feature branch has commits, via the apply-time helper (idempotent gh label create --force then gh issue edit <n> --add-label); leave the issue open; preserve the branch with any work done; clear the issue's dispatch-cap counters with ${CLAUDE_PLUGIN_ROOT}/scripts/reset-dispatch-cap.{sh,ps1} <repo-root> <n>, so a re-run after the park starts a fresh chain; and return.
0. Triage
Two branches - always run one:
Branch A - Explicit supply (reuse). Fires iff the caller supplied this issue's triage result at invocation time as named fields with actual values (e.g. issueStates["N"] = { blockers: false, label: null, advisories: [...], risk: "light" }, edges["N"] = [...]). Absent, label-only, or partial → Branch B. Use it directly - do not re-invoke milestone-driver:triage <n> - and proceed to the Blocker check.
Branch B - Standalone / fallback (the safe default, never an error). No explicit supply - including a result merely recalled from earlier context → invoke milestone-driver:triage <n> (single-issue mode) and use its return for the Blocker check.
Blocker check (both branches). A Blocker for this issue → park: triage has already posted the 🔴 Triage comment; VERIFY it exists (gh issue view <n> --comments) and post it if missing (idempotent); apply the recommended label from issueStates["<n>"].label - needs design for a design gap, needs decision for a non-design decision; do not proceed to step 1. All-clear or Advisory-only → proceed to step 1.
Held remediate answer is Auto (sub-step 1.1.2) → read ${CLAUDE_PLUGIN_ROOT}/skills/remediate-handoff.md and follow its ## The Auto loop instead of parking now: invoke /milestone-feeder:remediate <n>, re-run triage on the corrected body, and clear the park label when the re-triage comes back clean, then proceed to step 1. Attempt cap: 1 per issue per run. Its ## Park for good branches - remediate returns NEEDS_HUMAN, the re-triage is still dirty, the cap is spent, or the issue has no 🔴 Triage comment - run the park action above unchanged: comment opening 🔴 Parked - , label intact. No held answer, an answer of Leave-them-for-me, or the feeder absent → park immediately, as above.
1. Read the issue
Run gh issue view <n> with comments, redirected to the issue record <repo-root>/.milestone-config/.runtime/triage/issue-<n>.md by the skills/triage/SKILL.md (redirect its full record) command, which refreshes step 0's copy with comments posted since. Restate the acceptance criteria plainly before continuing.
common.md. A caller-supplied common.md path (a solve-milestone run) is reused, never re-assembled - the held-value shape sub-step 1.1.2 uses. None held → run the assembly call and its fail-open rule from skills/solve-milestone/SKILL.md (Assemble common.md) here, and hold its path.
Build profile resolution (resolved after step 0, governs steps 2–6)
Read issueStates["<n>"].risk from the step-0 result (held Phase 0 result in a milestone run, fresh single-issue return standalone): "light" or "heavy", defaulting to "heavy" when absent or inconclusive. That one read sets the brief token and the E2E gate's skip condition. Review effort and the cycle cap come from step 6.1.
| Profile | Planner and implementer brief | E2E gate (step 4, E2E row) |
| Light | Include a risk:light token in the brief | Skip when the issue touches no UI surface |
| Heavy (default) | Standard TDD brief (no risk:light) | Per step 4's E2E row (UI surface + e2eTestCmd) |
The safety floor is unconditional for both profiles: triage (step 0) and the tests-green, force-subagent, and dispatch-cap hooks always run. Light relaxes ceremony only - it never skips verification.
Resolve cited project-docs sections (once, before dispatch)
Name the docs root and pass the common.md path once, here in the orchestrator; the planner quotes the .project/ sections the change depends on into the packet (skills/solve-issue/build-packet.md#Sections), so the implementer reads exactly those sections and never a whole doc. Runs after the build profile resolves, adding inputs to the step-2 and step-3 briefs.
- Source the docs root. Use
projectDocsalready resolved at step 1 (defaults to.project/). Do not re-resolve the profile here. - Leave the anchors to the planner. The planner reads the issue's cited
.project/<doc>#<section>anchors and quotes each sectioncommon.mddoes not carry into the packet's## Rules; the main thread reads no section. - Resolve the repo file index (once). Invoke
${CLAUDE_PLUGIN_ROOT}/scripts/build-file-index.{sh,ps1}once per run, never per-issue inside a milestone loop. Pipe the diff-scoped{"files":[...]}to stdin; it prints one<path> → <purpose>line per file. A ### 3 brief carrying no packet takes it as the resolved file index - thebuild-file-indexoutput format, consumed, not re-derived. - Pass the common.md path. Put the held
common.mdpath into the ### 2 and ### 3 briefs; never paste its contents. Sub-steps 3 and 4 apply under both build profiles, unaltered byrisk:light. The code-comment rule isagents/implementer.mdrule 8; the brief does not restate it.
Degradation (no error, ever):
- Absent
projectDocs→.project/(step 1). - Absent
.project/directory, or no cited anchors → no-op: no project grounding, no error, skipped cleanly likeunitTestCmd/preflightCmd. - Missing/renamed cited anchor → a planner park (
agents/planner.md#Park). - Absent/failed file-index resolver → no-op: no file index, no error.
assemble-commonfails twice → no-op: the brief names nocommon.mdpath, no error; the implementer reads the fourskills/output-style.mdsections andcitationFormatPathdirectly.
Resolve cited path (anchor) citations (once, before dispatch)
Resolve the issue's path (anchor) citations (skills/citation-format.md) once, here in the orchestrator, and thread the resolved table into every subagent brief this run composes - no subagent re-derives it. Runs with the block above, before ### 2. Evaluate the codebase for root cause. Paths are repo-root-relative: an issue has no directory, so there is no multi-base fallback.
- Extract by model judgment over the
path (anchor)shape - never a regex. Applyskills/citation-format.md's span and position tests to the issue body + acceptance criteria. - Resolve each citation once. Invoke
${CLAUDE_PLUGIN_ROOT}/scripts/resolve-citation.{sh,ps1}once per citation:resolve-citation.<sh|ps1> <file-path> <anchor-text>. Exit 0 printsPRIMARY <line> <text>then zero or moreMATCH <line> <text>, TAB-delimited, in file order; matching is literal, case-sensitive, and line-scoped. - Feed the printed rows into the ### 2 and ### 3 briefs as the resolved citations, as printed, unchanged; invent no new format.
Degradation (no error, ever):
- No
path (anchor)citation on the issue → no-op: noresolve-citationinvocation and no error. - A cited anchor not found, or an unreadable file →
resolve-citationfails loud (nonzero exit, naming the anchor and file on stderr, stdout empty). Surface it; never swallow it. Exit 2 is a wrong argument count or an empty anchor.
2. Evaluate the codebase for root cause
Dispatch milestone-driver:planner via the Agent tool, briefed with: the issue record path (step 1), the held step-0 result, the resolved build profile (a risk:light token under light), the profile keys sourceGlobs, the expanded domainSkills, nonNegotiables and projectDocs, the worktree path (the repo root standalone), the common.md path (omit when none is held), the resolved citations (omit any whose resolution was a no-op), citationFormatPath (the absolute path of ${CLAUDE_PLUGIN_ROOT}/skills/citation-format.md, always passed), the packet path <main-repo-root>/.milestone-config/.runtime/plans/issue-<n>.md beside common.md, never inside a worktree, and the packet contract path ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/build-packet.md. Every brief carries resolved absolute paths, never the token. A run may add project facts to the brief, never work. The brief carries step 3's scratch-hygiene and command-shape rules; the planner's park cases are agents/planner.md#Park. Planner dispatches are capped at 2 per issue, enforced by hooks/dispatch-cap.sh; a denied dispatch, or a return that is neither PARK nor PLANNED with a file at PACKET:, runs the park action with blocked, never a retry. A packet failing approval takes the one re-dispatch below.
STATUS: PLANNED→ hold thePACKET:path and approve it with check-packet, never a whole-packet read: run${CLAUDE_PLUGIN_ROOT}/scripts/check-packet.{sh,ps1} <packet> <worktree>, addinglightunder the light profile. Exit 0 → the packet is approved, the locked architecture for this issue. Nonzero → re-dispatch the planner once, same brief plus eachFAILline as one listed approval failure, peragents/planner.md (On a re-dispatch, fold the listed approval failures), and approve its new packet likewise. A second failure → run the park action withblocked, naming the failures; the planner cap of 2 is spent, so no further dispatch. ADOMAIN_SKILLS_INVOKEDmissing an expandeddomainSkillsname takes that same one re-dispatch, each missing name a listed failure; on exit 0, first copy the packet toissue-<n>.approved.md, which a denied or failing re-dispatch restores, approved. A name still missing goes to step 6.2.STATUS: PARK→ run the park action with the returnedLABELandREASON.
Hold the last planner return's DOMAIN_SKILLS_INVOKED line for step 6.2.
3. Dispatch the implementer
Dispatch the profile's implementerAgent (default milestone-driver:implementer; a project-level override uses that agent's own name as-is) via the Agent tool with no model on the first build, so its frontmatter tier applies, orchestrating superpowers:subagent-driven-development + superpowers:test-driven-development. Brief it like a colleague walking in cold: the issue, the approved PACKET: path, the profile, the common.md path (omit when none is held), the resolved citations (omit any whose resolution was a no-op), the repo root (that issue's worktree path in a parallel-mode run), and citationFormatPath; under the light profile the brief must include a risk:light token. Every implementer re-dispatch carries this brief, PACKET: included, plus the failure. Implementer dispatches are capped at 3 per issue (step 4's shared loop), and a non-converging issue parks like any other. The brief must also carry this scratch-hygiene rule: write scratch only under a path named for that issue or that agent, never the shared scratchpad directory, and report what a probe printed rather than writing a probe file to read back later. The brief must also carry this command-shape rule: absolute paths only, and never change directory (cd, pushd, or a subshell); git -C <dir> for git, absolute file paths for grep, cat, sed, and find; a command needing a working directory (unitTestCmd, preflightCmd, npm ci) runs with the absolute worktree path as its cwd.
The implementer is a leaf. It returns an uncommitted diff plus its report and dispatches no subagent of its own (docs/architecture.md → ## Dispatch topology).
Verify the report honors the implementer contract: least-code / reuse-first, TDD red→green observed (or a VERIFICATION (no test layer) section when no test layer exists or under risk:light), verified citations where citable sources exist, a Decision Log, a USER-FACING CHANGES block (with NEW_UI_ELEMENTS: yes|no, DESTRUCTIVE_OPS: yes|no, and POST_REVIEW_CHANGES: yes|no), and changes left uncommitted. The first COMPLETE return whose DOMAIN_SKILLS_INVOKED misses an expanded domainSkills name re-dispatches the implementer once, the re-dispatch brief plus the missing names: invoke them and fix what they contradict in the diff, no new RED run. A second miss or a denied dispatch continues, holding them for step 6.2. With unitTestCmd defined and CLAUDE_HOOK_DISABLE_TESTS_GREEN not 1, the GREEN evidence is a scoped run of only the spec file(s) the implementer added or touched (agents/implementer.md rule 3); the full-suite run is step 4's Unit gate below. Then apply the declaration gates:
NEW_UI_ELEMENTS: yesand the acceptance criteria are silent on the element's visual/UX detail → park withneeds design, documenting the new elements and the direction needed.DESTRUCTIVE_OPS: yesand the confirmation UX is unspecified → park withneeds decision, documenting the missing confirm flow.
🔴 GATE - new dependency: the implementer reports that the optimal solution requires a new library or toolkit → park with needs decision, naming the library and its license / OSS status. Do not ask the operator interactively.
🔴 GATE - implementer STOPPED: STATUS: STOPPED carrying no PACKET_GAP: line (architecture conflict, scope overrun, out-of-scope edit, or missing/ambiguous brief) → park describing the conflict, with needs design for a design/spec conflict, needs decision for an architecture call, or blocked for an otherwise-unresolvable gate. PAUSED-FOR-APPROVAL indicates a new-dependency case and routes to the gate above.
A packet-gap stop re-plans: a stop carrying a PACKET_GAP: line, agents/implementer.md (A fact the packet lacks, or a quoted excerpt that does not match its file), re-dispatches the planner, step 2's brief plus that fact, per agents/planner.md (On a re-dispatch, fold the listed approval failures or the missing fact). Planner dispatches already at 2 (step 2 re-dispatched) → park blocked naming the gap, no dispatch. PLANNED → approve per step 2's check-packet run; approved → re-dispatch the implementer with the new PACKET: path and no model, then apply step 3's checks to its return; a failure parks blocked, no further planner dispatch. PARK → run the park action with its LABEL and REASON, no implementer re-dispatch. A denied planner or implementer dispatch parks blocked, never retried (step 4's shared loop).
4. Verification gates
There is no step 5; the next step is 6, since headings are citation anchors (.project/conventions.md (Keep ## headings stable)).
Unit, E2E, and preflight share one shape - act → verify → retry → park. /code-review is listed for visibility only (always-on, hence no trailing ? in its row): it keeps its own step-6.1 procedure and is not iterated by the shared loop below.
| Gate | Applicability | act | Cap | Park / escape policy |
| Unit? | unitTestCmd defined | Run ${CLAUDE_PLUGIN_ROOT}/scripts/unit-gate.<sh|ps1> <repo-root> (pwsh on Windows, bash elsewhere), never unitTestCmd directly - it stages, runs unitTestCmd, and on green writes the same stamp hooks/tests-green.<sh|ps1> reads, so the commit-time hook does not re-run a suite this gate already proved green on this exact tree. | Shared (below) | Park blocked (or needs design if the plan is wrong). |
| E2E? | Issue touches a UI surface and e2eTestCmd defined | Bug: run a targeted subset that proves the fix. Feature: implementer authors new E2E tests covering reasonable user stories, then runs them. Both against the profile's e2eEnv. | Shared (below) | Verified by other means (a DB assertion + an attached screenshot confirming the feature) → quarantine the flaky test, proceed, log the quarantine in the PR's Code Review section, apply judgment call. Not otherwise verified → park blocked. |
/code-review | Unconditional: always runs, no applicability flag | See step 6.1, its own in-scope-fix / park-trigger classification | Step 6.1's classifier verdict, per skills/review-depth.md § The ladder | Step 6.1's own park-trigger classification (architecture deviation, shared-contract change, new dependency, out-of-scope edit, unmetable gate, material ambiguity), plus its second-cycle park rule |
| Preflight? | preflightCmd defined as a literal command | Run the literal preflightCmd. | Shared (below) | Park blocked (or needs design if the plan is wrong). |
Preflight's "github-ci" sentinel mode. When preflightCmd is the reserved sentinel "github-ci", the Preflight row above does not apply: no local command runs, no cap, no park. The PR's own CI is the preflight, gated by step 6.8's wait-for-green merge under whichever granularity is in effect (the per-issue PR, the wave PR, or the milestone PR), each with its red-CI handling. Read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/preflight-github-ci.md for the record.
🔴 GATE - shared loop (unit, E2E, preflight only):
- Act. Run the gate's
actper the table row. Skip the gate cleanly, no error, when its applicability condition is not met (unitTestCmdabsent;e2eTestCmdabsent or no UI surface touched;preflightCmdabsent). - Verify. Invoke
superpowers:verification-before-completionand report real output, never assertion - for all three gates. - Retry. A failing gate re-dispatches the implementer (step 3's re-dispatch brief) with the failure and
model: "opus"- or parks directly if the failure reveals the plan is wrong (see Autonomy). A preflight fix routes through step 6.1's After a fix, before committing branch set -${CLAUDE_PLUGIN_ROOT}/scripts/classify-delta.{sh,ps1}picks the branch, andcode-changedre-runs the unit gate, neverunitTestCmddirectly (skills/solve-issue/post-fix-commit.md § After a fix), and/code-review. Cap: 3 implementer dispatches per issue in total, however split, shared across every gate and the step-6.1 review loop, enforced byhooks/dispatch-cap.sh. A denied dispatch is the park signal, never a retry. - Park. Still failing when the budget is spent → apply that gate's park/escape policy from the table above; the failed gate and its real output are the park comment's evidence slot. E2E's row is the one exception: verified-by-other-means quarantines and proceeds instead of parking.
Call sites. Unit and E2E run back-to-back immediately after the implementer dispatch (step 3). Preflight fires as the concluding action of step 6.1, after the /code-review loop converges and before version bump/commit.
6. Review → integrate → close
Coherence review (before the final /code-review). An optional read-only pass over the implementer's uncommitted diff. Run the review-depth classifier first (skills/review-depth.md § Running the classifier, <repo-root> as root): a shallow verdict skips this pass. Otherwise run it only when the coherenceReviewAgent - profile key, default-filled to milestone-coherence-reviewer:coherence-reviewer - is both present (dispatchable in this session) and configured (on Codex, present means its file resolves per skills/runtime-codex.md); absent/unavailable OR explicitly unconfigured → silently skip: no error, no prompt, at most one log line. When it runs, read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/coherence-review.md and follow its ### The pass.
Resolve review depth, then review and resolve. Read
${CLAUDE_PLUGIN_ROOT}/skills/review-depth.mdand follow it, passing<repo-root>as the classifier's root: it holds the verdict-to-effort mapping, the per-verdict cycle cap, the classifier's fail-open behavior, the re-classify-before-a-second-cycle rule, and the second-cycle park. Then run/code-review(superpowers:requesting-code-review) at that effort on the implementer's uncommitted changes, resolving findings autonomously per the Autonomy model, never pausing to ask the operator about an in-scope finding:- In-scope (cosmetic, naming, style, local reversible refactor, missing/weak test): take the pre-fix snapshot first -
${CLAUDE_PLUGIN_ROOT}/scripts/classify-delta.<sh|ps1> --snapshot <repo-root>(pwsh on Windows, bash elsewhere), holding the tree hash it prints; on nonzero exit hold nothing and still re-dispatch, the post-fix branch set names the move. Then re-dispatch the implementer (step 3's re-dispatch brief) to fix it withmodel: "opus"(the main thread cannot editsourceGlobs-force-subagent); log it in the Decision Log. That hash is what the post-fix branch set below classifies against. Which findings the build profile fixes, and how a finding carrying no severity is scored, areskills/review-depth.md § Which findings get fixed. - Park trigger (architecture deviation; a shared contract/interface/schema change; a new dependency; edits outside the issue's file scope; an unmetable gate; material ambiguity): park with
needs design,needs decision, orblocked. Do not commit.
The orchestrator runs this review itself, dispatching the reviewers directly as leaves (
docs/architecture.md→## Dispatch topology), and never dispatches an agent that itself runs/code-review. Reviewing several issues concurrently pins the shape to exactly one reviewer leaf per issue (skills/solve-milestone/parallel-waves.md § Parallel mode - Phase 1: concurrent stage dispatch, Stage B). The gate is unconditional: its### 4. Verification gatesrow carries no applicability flag, andhooks/code-review-gate.shdenies agh pr create/gh pr mergewhose PR body carries no## Code Reviewsection. The brief must also carry the step-3 scratch-hygiene and command-shape rules andcitationFormatPath.The brief must also put comment text out of review scope: no finding at any severity about a comment's wording, density, or presence. One carve-out, in these terms and not redefined: a comment change altering a machine-read directive stays in scope,
scripts/classify-delta.sh (is_directive <src>)'s enumeration deciding what counts as one.Omitting
/code-reviewis not permitted. Skipped under any constraint (time, token budget, tool error, self-review substitution) → treat the omission as a park trigger and park withblocked, giving the reason.After a fix, before committing. No in-scope findings → commit directly. Otherwise at least one was fixed: read
${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/post-fix-commit.mdand follow its### After a fix: the document-only andclassify-deltabranches, and thetests-greenbehavior they rely on. The cycle cap that bounds the loop isskills/review-depth.md § The ladder.Preflight gate (concluding action of 6.1). Once the
/code-reviewloop has converged, before version bump/commit, run the preflight gate - its applicability,act, cap, verify step, and park/escape policy are the Preflight row of### 4. Verification gatesand its shared loop.- In-scope (cosmetic, naming, style, local reversible refactor, missing/weak test): take the pre-fix snapshot first -
Assemble the Decision Log from the implementer's report for the PR body. Its slots are the Decision Log entry shape in
skills/output-style.md- choice · rationale · citation · rejected alternatives, one entry per line. Carryplanner DOMAIN_SKILLS_INVOKED: <value>andimplementer DOMAIN_SKILLS_INVOKED: <value>, one line each, plusDomain skills missed: <names>when step 2 or 3 held any.Check every
path (anchor)citation via${CLAUDE_PLUGIN_ROOT}/scripts/resolve-citation.{sh,ps1}before posting. Resolves → post verbatim. Fails → correct that citation from code, or set it tononeif no anchor exists. No other rewriting.Post the block on the issue as the Decision Log comment opening
📋 Decision Log, the implementer's CITATIONS block after it - the record the aggregate PR bodies' choice-only shape cites (skills/output-style.md (Choice-only Decision Log)). Probegh issue view <n> --json commentsfor that opener: found, replace that comment's body (gh api -X PATCH repos/{owner}/{repo}/issues/comments/<id> -F body=@<file>), so a re-drive's entries land on the cited record; absent, create it (gh issue comment <n>). Never a second comment.Assemble the Code Review section for the PR body. Record whether
/code-reviewran, the finding count and severity per run (the 1st, and the 2nd if a re-review ran), and each finding's resolution (re-dispatched and resolved / accepted with rationale / triggered park). Its slots are the## Code Reviewsection shape inskills/output-style.md; the evidence slot is the ref each finding named (perskills/citation-format.md; at zero findings, the effort level used). Template:## Code Review - /code-review run: yes | n/a - <reason> (`n/a` only for a PR carrying no `sourceGlobs` change; omission is a park trigger: a submitted PR always carries a real review; a parked run opens no PR) - Findings, one line per run: <count> in-scope finding(s) at <effort> effort - <finding> - <the ref it named, per skills/citation-format.md> → re-dispatched and resolved | accepted (rationale: <…>) | triggered park - … (one line per finding, or "none" when count is 0) - No park-triggering findings. | Park-triggering findings: <list>The version-bump annotation this section carries is the one step 6.4's resolved mode names.
- Version bump. Read
versioningfrom the profile and select the mode: Version-free mode (versioning: false), Fail-safe degradation (versioned mode -versioningtrueor absent - but.claude-plugin/plugin.jsondoes not exist), or Versioned mode (versioningtrueor absent, and.claude-plugin/plugin.jsonexists). Read${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/version-bump.mdand follow its### Modesfor that mode's mechanics, its Code Review annotation, and - under Versioned mode - the milestone-run vs standalone-run split. - Commit on the feature branch - the
tests-greenhook (PreToolUseongit commit) re-checks the suite. Review-before-commit is enforced by audit trail (the mandatory Code Review section), not by a commit-time hook;hooks/code-review-gate.shgatesgh pr create/gh pr merge, notgit commit. - Push the feature branch and open a PR with
--base <integrationBranch>(neverprotectedBranch- enforced by theno-push/no-pr-to-protectedhooks and GitHub branch protection). Put the Decision Log and the Code Review section in the PR body. Add ajudgment calllabel if any borderline autonomous call was made. Record its number (gh pr view --json number --jq .number) as step 8's<pr-number>. Auto-merge on green. Once CI is green, squash-merge for every issue, no UI/non-UI branch in front of it. This replaces the human-choice step of
superpowers:finishing-a-development-branch.Every squash merge in this plugin passes an explicit subject and body, here and at every squash site citing this section.
body="Decision Log and Code Review: PR #<pr-number>" \ && title="$(gh pr view <pr-number> --json title --jq .title)" && [ -n "$title" ] \ && gh pr merge <pr-number> --squash --delete-branch --subject "$title (#<pr-number>)" --body "$body"One Bash call,
&&-joined - a variable does not survive a call boundary, and an empty title aborts before the merge. The title is read at merge time, never held, and every value these strings interpolate is a variable, so a$, a backtick, or a"in one is safe.$bodyis"Decision Log and Code Review: PR #<pr-number>"where the PR body carries a Decision Log,"Code Review: PR #<pr-number>"where it carries none.<pr-number>is written into the command as literal digits, never a variable. The merge gate'spr_argregex reads the first token aftermergeand runsgh pr viewon it (hooks/code-review-gate.sh (gh pr view "$pr_arg")); on a non-literal token that view fails and the gate falls open.Visual evidence (optional, never-gating), before that merge. Runs only when the PR's diff matches
uiSurfaceGlobs. Then, with avisualCaptureblock carrying all three required keys -serverCmd,readyUrl,signInPath- on a sequential run (a parallel run defers the capture to the serial merge tail:skills/solve-milestone/parallel-waves.md (Deferred to the serial tail)), read${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/visual-capture.mdand follow its### Capture flow. No UI surface,visualCaptureabsent or incomplete, or any failure in it → skip with one log line: no capture, no PR comment, no hold. The merge proceeds regardless.- Confirm the issue is closed (a linked PR auto-closes it; otherwise
gh issue close <n>) - unconditionally.
Run-end cost record (additive, never-gating)
Survives context compaction: an in-context sum is gone the moment compaction runs, so nothing is aggregated in context. Every dispatch's usage is appended to disk as it returns; the run-end record is read back from that disk file alone. Never blocks, parks, or changes any outcome (.project/design-philosophy.md#Error & failure philosophy).
- Append, per dispatch, as it returns. As soon as an Agent-dispatch report lands - planner (tier
opus), implementer (tiersonnet,opuson a fix re-dispatch),/code-review, coherence-reviewer, direct triage; a background completion notification carries the same<usage>block - pipe{"agent":"<dispatch label>","tier":"<opus|sonnet>","totalTokens":<subagent_tokens>,"durationMs":<duration_ms>}to${CLAUDE_PLUGIN_ROOT}/scripts/write-cost-record.{sh,ps1} --append <runId>(<runId>the issue branch / run id, held constant for the whole run). It appends one line to.milestone-config/.runtime/usage/<runId>.jsonl; a dispatch never skips this even mid-run. An implementer or planner return carrying anoutput_file:path first merges the object${CLAUDE_PLUGIN_ROOT}/scripts/measure-dispatch.{sh,ps1} <output_file>prints into the piped one (jq -c -s '.[0] + .[1]'(Bash), or both objects throughConvertFrom-Json -AsHashtable, merged with+, thenConvertTo-Json -Compress(PowerShell)); nooutput_file:, or a nonzero exit, pipes the four-field object unchanged and never gates. - Finalize, last action before returning to the caller at every terminal exit - every park (steps 0, 2, 3, 4, 6.1) and the step-6.9 close. Run
${CLAUDE_PLUGIN_ROOT}/scripts/write-cost-record.{sh,ps1} --finalize <runId>: it reads that.jsonlalone, sumstotalTokensper tier intoinputTokens(an auditable lower bound -outputTokens/cacheReadTokens/cacheWriteTokensat the 0 sentinel,provenanceNote: "unsplit-total-as-input"), sumsdurationMsintowallClockSeconds, and writes the record to.milestone-config/.runtime/cost-records/carrying one more field,agents: the raw per-dispatch entries, for a per-agentdurationMsbreakdown the summed total alone cannot give back. - Skip cleanly. No usage file for this
runId(e.g. a triage-blocker park before any dispatch) →--finalizefails open on its own, one log line, no zero-value record. Writer script absent → silent no-op, one log line.
Autonomy model (Balanced)
Proceed autonomously (log on the PR): implementation choices within the approved architecture; reuse of existing helpers, styles, and conventions; test design; local reversible refactors; resolving in-scope /code-review findings (step 6.1).
PARK & continue (the autonomous runtime parks, never interactively waits): deviation from the approved architecture; any change to a shared contract, interface, base class, or DB schema used beyond this issue; a new dependency; edits outside the issue's expected file scope; a gate that cannot be met without a design change; material ambiguity in the issue's intent; /code-review omission or substitution for any reason (time, token budget, tool error, self-review); budget pressure is not an exception.
The park is ## The procedure's park action, comment opening 🔴 Parked - <reason>; its in progress label is the open-WIP signal the milestone loop reads, and that loop continues with independent, clean issues. Only a systemic failure (auth/gh failure, broken integrationBranch, missing tooling) halts the whole run. A standalone interactive solve-issue still parks durably; it may additionally narrate to the watching operator.
Additional park triggers (each a park, not silent resolution and not an interactive prompt):
- The recorded/locked design is internally contradictory → park with
needs design. - A self-noted risk about the approved design (e.g. "this list could get long at realistic data volumes") → park with
needs design.
Architecture is locked at packet-approval time (step 2). The procedure executes approved architecture. If implementation proves the plan wrong → park, not pivot.
A change is architecture (→ park) if it touches any of: a component or data structure named in the approved packet; a shared contract, interface, base class, DB schema, or public API used by code outside this issue; data ownership or a cross-component boundary; a new external dependency; or any file outside this issue's stated scope. A change is an implementation detail (→ proceed, log in the Decision Log, step 6.2) if it is local to this issue's own files, changes no shared contract, and is reversible - a binding style, a private helper extracted in the same file, a local refactor, or test design. When the distinction is genuinely ambiguous, treat it as architecture and park.
Audit trail (always): a Decision Log on every PR, a Code Review section recording every /code-review run and its findings/resolutions, and a judgment call label on borderline calls.
Permission pre-flight gate
Runs once per run, before the first background dispatch - only when a leaf is about to be dispatched as Agent(run_in_background: true). A fully synchronous run SKIPS it entirely.
Background subagents auto-deny any tool call that would otherwise prompt, and a background leaf hitting an un-allowlisted tool fails outright with no interactive recovery. Before the first background dispatch: union permissions.allow across ~/.claude/settings.json, .claude/settings.json, and .claude/settings.local.json - absent or unreadable layers are skipped in the union, not treated as gaps. Synchronous fallback fires only when the union misses the required tool surface, or no layer is readable. With that union in hand, read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/permission-preflight.md and follow its ### Tool surface and response.
Milestone granularity (integrationGranularity: "milestone")
Resolved from the profile at step 1, not from an invocation token. integrationGranularity resolves to "milestone" (docs/profile-schema.md (How should built issues integrate?)) → read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/milestone-clauses.md and apply its ### Clauses, plus ${CLAUDE_PLUGIN_ROOT}/skills/solve-milestone/milestone-granularity.md for the branch model, integration-commit trailer, and resume query. Absent or invalid, with no milestone run holding a resolved value, resolves to "issue" here: neither read happens and the pipeline runs byte-unchanged. An explicit "issue" resolves the same way.
Wave granularity (integrationGranularity: "wave")
Resolved at the same step-1 profile read, not from an invocation token. integrationGranularity resolves to "wave" (docs/profile-schema.md (How should built issues integrate?)) → read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/wave-clauses.md and apply its ### Clauses. Those clauses apply to every issue in the Wave, UI included.
Async mode (--async): retired
--async is an interpreted token, not a parsed CLI flag - recognized by string presence in the invocation text - and inert: the pipeline runs on the caller's own main line, and the token is a no-op, never an error. No run reads ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/async-mode.md.
Parent-issue detection (md-epic)
Runs before anything else - before ## Before starting step 1 and before ### 0. Triage. Read #n's labels (gh issue view <n> --json labels, exact match against .labels[].name for the literal md-epic). Absent → this section does not apply; the pipeline runs byte-unchanged from ## Before starting step 1. Present → read ${CLAUDE_PLUGIN_ROOT}/skills/solve-issue/md-epic-fanout.md and follow its ### Parent path, which replaces the rest of this pipeline for this invocation.
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 the ### 0. Triage step completes.
🚀 Issue #201 - [title] · [risk: light | heavy] · [UI | non-UI]
| Issue | Title | Risk | UI | Status |
|-------|---------|--------|----|-------------|
| #201 | [title] | [risk] | - | 🔨 building |
▶ Building - the floor is yours.Template 2 - Issue completion (terminal output)
<!-- Structural mirror of solve-milestone Template 2; keep column schema (Issue/Result/Gates/PR/Note) in sync. -->One row per issue; emit only the row matching the actual outcome and suppress the others.
🏁 Issue #[n] · [T] min
| Issue | Result | Gates | PR | Note |
|-------|------------|-------|----|-------------------------|
| #201 | ✅ merged | 🔍✓(0 findings) | #301 | - |
| #202 | ⏸️ parked | - | [#pr | -] | [park label] |
| #204 | ✅ committed | - | - | committed on its branch |PR cell: show the PR number if the issue has one, else -. Gates legend: 🧪 = unit suite · 🔍 = code review · 🌐 = E2E
Note cell: an issue the run sent through the Auto loop records its outcome there - remediated, cleared (re-triage clean, label cleared), remediated, still parked (cap spent or re-triage still dirty), or NEEDS_HUMAN, parked (skills/remediate-handoff.md (Park for good)); Result still shows the state the pipeline reached. No Auto loop → the cell is unchanged. Slow first build: an issue whose first implementer dispatch printed steps over 40 or minutesToFirstEdit over 2 adds <steps> steps, first edit <m> min (no minutesToFirstEdit: steps alone decides, shown as <steps> steps, no edit), joined to any Auto loop outcome by ; . Slow planner: an issue whose first planner dispatch printed steps over 25 adds planner <steps> steps, <minutes> min to the Note cell, joined to any other Note text by ; .
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 comment, Decision Log, and PR body. The two surfaces are distinct - terminal rules never reach GitHub. 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. skills/solve-milestone/SKILL.md § Main-thread context binds this skill too - it runs in-thread.
Non-negotiables
- Gitflow. PRs target
integrationBranchonly - neverprotectedBranch. - Honor the profile's
nonNegotiables(framework versions, platform targets). - The main thread never authors application or test code - always dispatch the implementer.
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.

