agentsclimarketplace

Milestone workflow

Skill richkuo/rk-skills/skills/milestone-workflow

Use when the user wants a milestone of Execution-block-stamped GitHub issues implemented via a multi-agent dynamic workflow — "create the workflow for v0", "run v0 continuously", "/milestone-workflow v0". Builds dependency tracks, presents the run plan for approval, then runs the milestone-pipeline workflow: per-issue model/effort from the Execution blocks, optional fableplan stage, PRs, optional review loops until LGTM — the repo's @claude Action by default, or in-session subagent reviewers in subagent mode — then pauses at each LGTM so the orchestrating session merges the PR in-session (no merge subagents) and resumes, and, when every issue merges, the orchestrator syncs docs and publishes a release. Stage 7 of the new-app-pipeline.From its SKILL.md

Install
npx -y skills add richkuo/rk-skills --skill milestone-workflow

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

27.8 KB, as published. Nobody here has run it

milestone-workflow

Turn a reviewed milestone into a running multi-agent pipeline. Static plan, dependency-aware dispatch: the dependency graph is decided here with the user; execution waits for stable predecessor results and builds hard-dependent work from their reviewed code. With merging on (the default when review loops run), no subagent ever merges: at each LGTM the run pauses as awaiting_merge, the orchestrating session merges that PR in-session (step 5 owns the procedure), then resumes the run with the merge recorded in args.merged — successors build from the updated base branch. When every issue merges, the orchestrator syncs docs and publishes the release (phase 7).

For a read-only look at the milestone before committing to a run — a single table of what routing is stamped on each issue (complexity, dependencies, validate/build model and effort, fableplan, plan effort, first review) — use milestoneplan first. It reads without editing anything, then hands off here.

Steps

1. Build the dependency tracks

Fetch the milestone's issues and build a typed dependency graph before grouping them into tracks.

  • Filter for idempotency first: list the milestone's issues with --state all and search for open PRs that close each one. Drop closed issues from the plan. An open issue with an existing open PR is planned as a resume — run fix-pr-review-loop on that PR instead of dispatching it through the pipeline — never a fresh build, which would open a duplicate PR. Show three buckets in the run plan: build, resume, skip (closed).
  • Resolve cross-bucket dependency edges before building tracks — after/runsAfter can only reference tracks in this run, so an edge from a build-bucket issue to a resume- or skip-bucket issue must be settled here, never silently dropped (the implement agent would otherwise build from the default branch and miss the predecessor's unmerged code). A predecessor whose PR merged: the edge is satisfied — drop it, the base branch has the code. A predecessor in the resume bucket: run its fix-pr-review-loop to completion before invoking the pipeline — that satisfies ordering-only edges; when the run will merge (the default), also merge that PR once its loop reaches LGTM and CI is green (the approved run plan covers this merge), which satisfies hard edges through the base branch. With merging off, a hard edge still needs the predecessor's code, so exclude the dependent issue and its hard descendants from this run's tracks, report them as blocked pending merge of PR #X in the run plan, and offer to re-run the milestone once it merges. A predecessor closed without a merged PR: the dependency is unsatisfiable as filed — exclude the dependent and its hard descendants, report them as blocked pending decision, and ask the user whether to reopen the predecessor or re-scope the dependent.
  • Read **Depends on:** first for hard code/product prerequisites and **Runs after:** for ordering-only constraints. An explicit none is authoritative: never infer an edge for a field that is present. For an older issue missing either field, infer only that missing edge kind from Approach/Problem prose and label every inferred edge in the plan.
  • Classify an inferred code/product prerequisite as a hard edge and an inferred same-package or no-overlap constraint as an ordering edge. If the prose does not establish the edge kind, flag it for the mandatory plan review instead of guessing.
  • Reject references to issues outside the milestone, and cycles across the union of both edge kinds (edges to resume/skip-bucket issues inside the milestone are resolved by the cross-bucket rules above, not rejected). A hard edge means the successor needs predecessor code; an ordering edge only prevents overlapping work.
  • Express each track as { issues: [...], after: [<track index>...], runsAfter: [<track index>...] }. Dependency-free islands have neither predecessor list. Combine issues into one issues array only when every serial edge is truly hard; untyped serial edges are treated as hard by the workflow, so ordering-only chains must remain separate tracks joined by runsAfter.
  • Preserve concurrency: unrelated tracks start together. Multiple hard predecessors remain separate after entries so the runtime can create and verify one integration base containing every head.
  • With merging on (the default), prerequisites merge to the default branch before successors start inside one invocation — the policy that used to require separate invocations. Use separate workflow invocations for that policy only when merging is off.

2. Present the run plan — review before beginning (mandatory)

Show: numbered tracks with issue titles; hard after edges separately from ordering-only runsAfter edges; which edges were inferred; each issue's model/effort/fableplan, plus the Plan effort on every fableplan: Yes issue; the stable readiness boundary; and merge-order expectations. Do not invoke the Workflow tool until the user approves this plan — the approval is both the safety checkpoint and the explicit multi-agent opt-in the Workflow tool requires.

State the GitHub writes the run performs, so the approval covers them explicitly: agents apply validation corrections to issue bodies, post each fableplan: Yes issue's implementation plan as a comment on that issue, open PRs, (with review loops on) post review-trigger and disposition comments, and — with merging on, the default — the orchestrating session itself squash-merges each PR at LGTM plus green CI, deletes its branch, closes its issue, and, when every issue merges, lands a docs-sync change and publishes a GitHub release. Every merge is an in-session gh pr merge by the orchestrator, run under the session's own permission mode — no background subagent ever holds merge authority. Approving the plan authorizes those merges and the release; run with merge: false to keep merging fully manual.

Add a Run size line before asking for approval:

  • Compute the planned direct-agent baseline, assuming every issue reaches each enabled phase, as 1 prep + sum over issues of (1 validate + (fableplan ? 1 plan : 0) + 1 implement + (reviewLoop && reviewMode === 'subagent' ? 1 review-loop : 0)). Merging and the release dispatch no agents — the orchestrator does both in-session. In subagent mode, the review-loop term is the happy-path first reviewer. Each additional cycle dispatches a fixer and re-reviewer pair, except the unresolved final cycle dispatches no fixer, so the worst case is 2×maxReviewCycles − 1 review-phase agents per issue. In default github mode, the implement agent handles cycle 1. Each later fix agent handles up to two cycles, so the worst case adds ceil((maxReviewCycles − 1) / 2) review-phase agents per issue. All loop state lives on the PR, so agent rotation loses no history.
  • Also compute the retry-aware direct ceiling as planned direct-agent count + 3 × number of issues, because each issue's validation can dispatch one retry, plus one band-escalation re-validation with its own retry. Show both numbers.
  • Label them as planning bounds, not a total-agent guarantee: invalid issues or failures can reduce the count, while review loops can dispatch nested fix agents beyond the retry-aware ceiling. The warning counts all scheduled agents, so never label a plan safe merely because either direct count is below the threshold. maxReviewCycles changes the stopping rule after an LGTM; it is not a guaranteed cap while reviews keep returning Needs Updates.
  • Compare both direct counts with the effective Dynamic workflow size guideline when one is present in session context; otherwise use Claude Code's documented default threshold of more than 25 scheduled agents. Name the threshold source in the plan so the comparison is inspectable. If the baseline crosses it, mark the warning expected; if only the retry-aware ceiling crosses it, mark the run retry-sensitive; if both stay under and review loops are enabled, state that nested fixes can still trigger the warning. The Claude Code workflow cost documentation is authoritative.
  • State that Claude Code can also trigger Large workflow when its projected token total exceeds 1.5 million. In an ultracode session, label both comparisons informational because the warning is suppressed.
  • When either risk is apparent, call it out before approval and recommend splitting the milestone into separate tracked Workflow invocations. Disabling reviewLoop reduces the direct count but forfeits automatic review readiness. Lowering maxReviewCycles may reduce repeat work after non-blocking LGTM reviews, but never present it as a guaranteed cap.
  • When the user set a token target (a "+500k"-style directive), state that the workflow enforces a floor: before each issue starts, if fewer than 80k tokens remain (override with budgetFloor), that issue and the rest of its track are deferred as budget_deferred and the run returns partial results cleanly instead of an agent dying at the hard ceiling. Without a target, no floor applies. The floor is best-effort, not a guarantee: it is checked only when an issue starts, so an in-flight issue's agents can still hit the hard ceiling, and concurrent tracks can each pass the check before spending. Size budgetFloor to roughly one issue's worst-case cost — implement plus a full review loop — which is typically well above the 80k default when review loops are on.

3. Preflight the repo

  • gh auth status succeeds and gh api repos/<owner>/<repo> --jq .permissions.push returns true. A bad token or read-only access must stop the run here — otherwise it surfaces as confusing per-agent failures mid-run.
  • Review-mode dependencies: the default reviewMode: 'github' requires .github/workflows/claude.yml (the @claude review bot — copy from rk-skills templates/claude-review.yml and confirm the API-key secret if missing) plus working GitHub Actions. With reviewBot: 'codex' the same dependency reads .github/workflows/codex.yml (copy from rk-skills templates/codex-review.yml, or install the full templates/codex-workflow/ bundle) plus the Codex secrets and repository variable that the fix-pr-review-loop review-bot preflight lists (the fix cycles push, so the write-route items are required here too). Without that bot, pass reviewMode: 'subagent' — reviews then run in-session (a reviewer agent posts a pr-review comment, a fixer agent resolves it) with no Actions dependency — or set reviewLoop: false to skip reviews entirely (phase 5 states the readiness effect). Note CI checks that run on Actions are an independent dependency either way — subagent mode removes the review's Actions dependency, not CI's.
  • Base branch protection / merge expectations understood: with merging on (the default), the authenticated account must be allowed to squash-merge and delete branches on the base branch — protection rules that require human approvals or block squash merges must be relaxed first, or the run switched to merge: false (merging then stays with the user and successors stack on unmerged heads).
  • CLAUDE.md in the target repo covers conventions the agents must follow (package manager, test commands).

4. Run

Invoke the Workflow tool with {name: 'milestone-pipeline', args: {tracks: [{issues:[2,3]}, {issues:[9], after:[0]}, {issues:[12], runsAfter:[0]}], reviewLoop: true, maxReviewCycles: 5}}. Legacy issue-array tracks remain accepted, but use typed objects for new plans. budgetFloor (tokens, default 80000) is accepted when a token target is set. reviewMode defaults to 'github' — reviews route through the repo's @claude Action; pass 'subagent' to review with in-session agents instead. reviewBot defaults to 'claude' and only applies in github review mode; pass 'codex' to route every trigger and re-trigger to @codex — never infer it from a codex.yml existing in the repo, only from the user naming Codex. merge defaults to reviewLoop — on unless review loops are off; merge: true with reviewLoop: false is rejected because LGTM readiness is the merge criterion. merged carries the PRs the orchestrator has already merged in-session, as [{issue, pr, merge_sha, issue_state}] records — empty on the first invocation, appended to on every merge-resume; step 5 sub-step 7 owns the record format and its validation. release defaults to merge; release: true with merge: false is rejected; phase 7 owns the deferred-release behavior.

Immediately after the invocation returns, post its runId and persisted script path as a comment on the milestone's first issue (footer: Created with LLM: <current model> | high | Harness: milestone-workflow), so run state survives losing the conversation — resumeFromRunId resumes same-session; cross-session the record enables a hand-authored continuation from the persisted script.

The workflow validates all assignments, predecessor indices, duplicates, and cycles before prep, then:

  1. Prep — one agent reads every issue's [C..] score and Execution block → per-issue model/effort/fableplan/plan effort.
  2. Validate — immediately before each issue starts, a validation agent runs the validate-issue procedure against the current dependency base, with deduplicated predecessor PRs/skips and hard base refs. Model and effort are both derived from the [C..] score band, never from a stamp (the validate-issue step 6 band table owns the mapping; a missing prefix routes as band 5). The validator also returns its own score; when it lands in a higher band than the prefix, the pipeline re-validates once on the stronger route (upward only) and re-routes the whole issue from the higher score: build model, build effort and fableplan always move to the escalated band's defaults, replacing the stale stamps. A stamped PR review: reviewer is treated separately — it moves to the escalated review band's default only when that default outranks the stamp, so an operator who named a stronger reviewer keeps it, and a rescore never lowers review routing. Each rescored issue carries a rescore record in the run results; the post-run report below acts on it. INVALID issues are skipped and reported, never built.
  3. Plan — issues flagged fableplan: Yes get a Fable 5 planning agent (validation-aware) whose plan is posted to the issue, at the issue's Plan effort (default high; every tier is legal because the planner is always Fable). The builder implements against it.
  4. Implement — per-issue agent on its assigned model/effort applies validation corrections, invokes work-on-issue with the verified hard baseRefs, creates a deterministic integration base for multiple heads, and opens the PR. In default github review mode, the same agent also handles review cycle 1: it posts the band-derived trigger (@claude sonnet review at 0–10, @claude review at 11–40, @claude opus review at 41–80, @claude fable review effort:high at 81+, or the issue's stamped trigger), waits, fixes or refutes, re-triggers when needed (a fable first review never repeats: the blocking re-triggers after it step down one rung each, @claude opus review then @claude review), and waits for the standing verdict. With reviewBot: 'codex' the heavier bands collapse onto Codex's single flagship — C11 and above posts a bare @codex review, while the cheap tier keeps a shorthand (@codex luna review) for both the C0–C10 first review and the non-blocking re-review.
  5. Review readiness — the review loop runs until LGTM before any hard or ordering successor starts, preventing review fixes from racing same-package work. In subagent mode the script alternates an independent reviewer agent (first review on the issue's stamped PR review: model/effort when one is named, else the review-band default — sonnet/high at 0–10, the session default model at 11–40 (the bare-@claude equivalent), opus/high at 41–80, fable/high at 81+; posts a pr-review comment) with a fix-pr-review fixer agent on the build model/effort — a re-review after only non-blocking fixes drops to sonnet/high, and a fable first review never repeats — its blocking re-reviews step down one rung each, opus/high for the first and the session-default reviewer for every one after that. In default github mode, each fresh fix agent after the implement agent handles up to two review-bot Action cycles before it exits, on whichever bot reviewBot selected. Unrelated tracks and their review loops stay concurrent. With reviewLoop: false, implementation completion is the readiness boundary.
  6. Merge — with merging on, no merge subagent runs. A PR whose merge the orchestrator already recorded in args.merged counts as merged and its successors build from the updated base branch with no baseRefs. The run accepts a record only when it passes step 5 sub-step 7's validation; a rejected record returns merge_record_mismatch and blocks the track instead of counting as a merge. A PR at LGTM without a record pauses its track: the issue returns awaiting_merge (also listed in the run's top-level awaiting_merge array), in-track successors return merge_pending, and descendants in other tracks return dependency_blocked; the run then ends so the orchestrator can merge in-session and resume (step 5).
  7. Release — when every issue in the run reached merged, the run returns release.deferred: true and the orchestrator runs the sync-docs-release skill in-session: sync the docs to the merged PRs, land that change (merging its doc PR after checks pass), then create-release. Any non-merged issue skips the release; a partial milestone never publishes.
  8. Failure propagation — failed, blocked, non-LGTM, or unmerged (with merging on) hard predecessors block descendants. Ordering-only skips without a PR do not; an unresolved predecessor PR does. Integration conflicts block before product changes.

5. Merge-resume loop, monitor, close out

With merging on, the run pauses every time a PR reaches LGTM without a recorded merge. On each awaiting_merge return, the orchestrator merges that PR in-session, then resumes:

  1. Verify the PR: gh pr view <num> --json state,headRefName,headRefOid,mergeStateStatus — OPEN, and headRefOid exactly the reviewed readiness SHA the run returned for it. A different head here means somebody pushed commits after the review: send the PR back through the review loop instead of merging. This check is against the head before any catch-up this procedure performs; the catch-up in sub-step 2 is expected to move the head, and sub-step 3 states which commit that leaves as the merge target.
  2. CI gate: gh pr checks <num> --watch; any failed check blocks the merge. No checks configured counts as passing. If the branch is behind the base, run gh pr update-branch <num> only when it merges cleanly, re-capture the head (gh pr view <num> --json headRefOid), and repeat the CI gate on that new head — the reviewed code must prove itself against the base it actually lands on. If gh pr update-branch reports conflicts, stop; never resolve conflicts yourself.
  3. Fix <verified-sha> — the exact commit sub-step 4 pins. It depends on the review mode, because the two modes bind the LGTM to the code differently:
    • Subagent review mode: <verified-sha> is the reviewed readiness SHA when sub-step 2 did not update the branch, or the head you re-captured after gh pr update-branch when it did. A catch-up that only adds base commits keeps the reviewed product diff, so it does not restart the review loop.
    • Github review mode: <verified-sha> is the reviewed readiness SHA only. If sub-step 2 changed the head, the standing review-bot LGTM now predates the commit you would merge: stop and send the PR back through the review loop until a fresh LGTM lands on the new head. Never merge a caught-up head on an older verdict.
    • Either way, if a concurrent track merges first and forces a second gh pr update-branch, re-apply this same rule to the newest head — subagent mode re-pins and re-gates CI, github mode requires another fresh review.
  4. Github review mode only — the LGTM recency gate. Run it as the final read before the merge, and re-run it after every CI wait and every branch update. Its job is to prove the standing verdict reviewed the exact code you are about to land.
    • Re-fetch the live PR head and the PR's full issue-comment history.
    • Find the newest exact one-line @<review bot> [model] review [effort] trigger comment, and the newest github-actions[bot] output whose body links /actions/runs/<run-id>.
    • Resolve that linked run and require status == completed and conclusion == success. A newer trigger, or a run-linked bot comment without a completed matching output, blocks the merge. Never fall back to an older LGTM.
    • Require the output's created_at to be later than the trigger's created_at, and require its body to carry exactly one standalone verdict line reading LGTM (never Needs Updates).
    • Do not compare the Actions run's head_sha to the PR head. An issue_comment run reports the last commit on the default branch, so that field never equals the PR head and the comparison rejects every valid verdict. Bind the verdict to the code by time instead.
    • Resolve when the head became visible on GitHub — the earliest created_at among gh api repos/{owner}/{repo}/commits/<verified-sha>/check-suites, or that commit's .commit.committer.date when it has no check suite — and require the LGTM output's created_at to be strictly later. An LGTM that predates its head reviewed older code: stop.
    • Once this gate passes, run sub-step 5 immediately. No other command may run between the gate and the pinned merge.
  5. Merge pinned: gh pr merge <num> --squash --delete-branch --match-head-commit <verified-sha> — never unpinned. If GitHub rejects the merge because the head no longer matches, a commit landed after your CI gate: do not retry with a fresh SHA, and restart this procedure from sub-step 1.
  6. Confirm the linked issue closed (gh issue view <n> --json state; close it explicitly if the closes link did not fire), and capture the merge SHA (gh pr view <num> --json mergeCommit).
  7. Resume: re-invoke Workflow with the same scriptPath and resumeFromRunId, passing the complete original args — every field the first invocation carried, including tracks, reviewMode, maxReviewCycles, budgetFloor, merge, and release — with only args.merged extended by {issue, pr, merge_sha, issue_state} for every PR merged so far. args.tracks is required, so a resume that carries merged alone throws immediately; re-running fresh instead would re-validate and re-implement merged issues and open duplicate PRs. Each record names both the issue and the PR that closes it: the run rejects an issue outside the run, a repeated issue or PR, and a record whose PR does not match the PR the run opened for that issue (merge_record_mismatch), and it reports any record it never used in unmatched_merged_records. Cached agents replay instantly; the run proceeds past the recorded merge. Repeat until no awaiting_merge remains.

Concurrent tracks pause together at each return, so serial milestones lose little and wide ones trade some concurrency for in-session merge control.

When the run returns release.deferred: true, run the sync-docs-release skill in-session per phase 7 and report the tag and URL.

Relay meaningful progress (PRs opened, review loops finishing, merges, blockers) — not raw logs. On completion, report a results table: issue → PR → review status → merge status, plus flags the agents raised and the release outcome (tag and URL, or why the release was skipped). For every result that carries a rescore record, do two things: (1) restamp the issue — load the github-issue-format skill first, update the [C..] title prefix to the rescored score, and update the Execution block's Build model / Effort / fableplan lines to the values the run actually used (footer verb Updated); (2) tell the user which issues were rescored, from what to what, and how the routing changed — never let a rescore pass silently. With merging off, recommend dependency merge order, with every hard prerequisite before its descendants, and if a later phase was deferred pending merges, offer to chain the next invocation.

Context discipline

The orchestrating session holds no implementation detail — issues and PRs are the memory. Between phases (or after compaction), everything needed to resume lives in: the milestone's issues, their Execution blocks, the open PRs, and the runId comment posted in step 4. Losing the conversation must never lose state.

Failure modes

SituationDo this
An issue lacks an Execution block at run timeStop before running; send it through execution-plan-review
The user wants the milestone checked before committing to a runRun milestoneplan — the read-only single-table plan, without touching an issue
No review-bot workflow in the repoInstall the template for the selected bot (templates/claude-review.yml, or templates/codex-review.yml with reviewBot: 'codex') for the default github mode, or pass reviewMode: 'subagent' (no Actions dependency); reviewLoop: false remains the no-review fallback
GitHub Actions billing or a self-hosted runner outage stalls reviewsSwitch the next invocation to reviewMode: 'subagent' (github is the default); already-running github-mode loops stay blocked until Actions recovers
A successor hard-depends on unmerged predecessor PRs (merging off)Use after; the workflow waits for stable heads and work-on-issue verifies/integrates every base before implementation. With merging on, the predecessor merges first and the successor builds from the base branch
A PR reaches LGTM but CI fails, the head moved, or the base conflicts before mergingThe orchestrator refuses the in-session merge (step 5 gates); the track pauses per phase 6 — fix the cause, merge, then resume with the record
A resume's args.merged record names the wrong PR for an issueThe run rejects it per step 5 sub-step 7 and blocks that issue's descendants. Correct the record against gh pr view <num> --json number,state,mergeCommit, then resume
Branch protection requires human approvals or blocks squash mergesRun with merge: false; merging returns fully to the user and successors stack on unmerged heads
Some issues did not reach merged at run endThe release is skipped; merge the stragglers in-session, then resume (or run sync-docs-release yourself)
A same-package predecessor is ordering-onlyUse runsAfter; the successor waits but does not inherit code
A build-bucket issue hard-depends on a resume- or skip-bucket issueApply the step 1 cross-bucket rules; step 1 owns the full resolution for merged, resume-bucket, and closed predecessors
A dependency integration conflictsThe affected track and hard descendants stop blocked before product changes; report the conflicting heads
Workflow returns empty/odd resultsRead the run's journal.jsonl before re-running; resume with resumeFromRunId rather than restarting
User asks to start without reviewing the planPresent the plan anyway — step 2 is not skippable

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.