Sprint Orchestrator
A sprint is a batch of independent work items that each land on the
trunk on their own. Use this when the work decomposes into pieces that
don't interleave (no shared runtime contract across siblings, no
half-migrated state if you ship one without the others). If children
do interleave, use an epic / integration-branch flow instead — same
decomposition step, plus a shared branch the children stack on.
Configuration
Reads .rig/config.json (missing keys → defaults):
| Key |
Default |
Used for |
tracker.provider |
none |
linear | github | none. Selects the ticket backend, or ad-hoc mode. |
tracker.team |
— |
Linear team / GitHub org for list/create. |
tracker.project |
— |
Linear project for list/create. |
tracker.ticketPrefix |
— |
Recognize ticket IDs in $ARGUMENTS. |
tracker.githubIntegration |
false |
If true, GitHub drives PR/merge transitions; each /rig-task sets only the start-of-work In Progress. |
tracker.shapeLabels.sprint |
sprint |
GitHub-only label applied to each item at creation so a board/dispatcher can pick up sprint items. Omit shapeLabels to skip. |
vcs.baseRef |
origin/main |
Base each ticket's branch is cut from. |
vcs.branchConvention |
{user}/{ticket}-{slug} |
New-branch template. |
vcs.defaultBranch |
main |
Trunk each PR targets. |
vcs.protectedBranchMergeQueue |
false |
If true, merge via gh pr merge --auto and never pass --rebase/--squash. |
runtime.installCommand / packageManager |
npm |
Install command inside a worktree. |
test.command |
npm test |
Test step in each per-ticket implementation. |
sourceScope[0] |
src |
Default codebase area to explore during decomposition. |
style.guideFile |
.claude/STYLE.md |
Writing style for item titles, bodies, and the hand-off report. |
Tracker modes:
linear — tickets are Linear issues; use the mcp__claude_ai_Linear__* tools.
github — tickets are GitHub issues; use gh issue.
none — ad-hoc mode. There are no ticket IDs. Treat each item in
$ARGUMENTS (or each bullet the user gives) as a task description.
Skip all create/list/move-ticket steps; the sprint operates directly
on the task list, and each task's implementation opens a PR whose title
is the task description. plan <feature> still decomposes into a
numbered task list — it just prints it instead of creating tickets.
Arguments
The user invoked this with: $ARGUMENTS
What to do
If the user said plan <FEATURE-DESCRIPTION> (decompose a feature)
Create independent work items that can each be picked up and landed on
the trunk directly — no parent epic, no integration branch.
Read context.
- Any product/spec docs the project keeps (ask if unsure — don't
assume a fixed path).
- Explore the codebase to understand what already exists. Default the
exploration scope to
sourceScope[0] (fallback src).
- Search before creating to avoid duplicates:
- Linear:
mcp__claude_ai_Linear__list_issues with project =
tracker.project, a query of the feature's key nouns,
limit: 50 — search, don't pull the whole board; page via the
returned cursor only if a likely match looks cut off.
- GitHub:
gh issue list --search "<key nouns>" --state all.
- Ad-hoc (
none): grep the codebase / recent branches for prior art.
Sanity-check it's actually sprint-shaped (independent), not
epic-shaped (interleaved). If at least one child's runtime contract
genuinely depends on another being partially complete (the middle
state would break the trunk), stop and tell the user to use an
epic / integration-branch flow instead.
Break the feature into 3–8 discrete items, ordered by dependency.
No parent ticket.
Materialize the items:
- Linear:
mcp__claude_ai_Linear__save_issue per item — team =
tracker.team, project = tracker.project, short action-oriented
title ("Add X", "Wire up Y", "Implement Z"), state: "Backlog",
priority 2/3/4, a markdown description (Overview, Acceptance
Criteria, dependency references). Set blockedBy for every real
dependency — not optional; the phaser relies on it to group
correctly.
- GitHub:
gh issue create per item with the same title/body, adding
the sprint shape label — --label "<L>" where <L> =
tracker.shapeLabels.sprint (default sprint) — so a Project board /
dispatcher can pick up sprint items directly (skip the label if
tracker.shapeLabels is absent; ensure it exists first with
gh label create "<L>" --force). Encode dependencies as "Blocked by #N"
in the body (GitHub has no native blockedBy).
- Ad-hoc (
none): don't create anything — just produce the
numbered task list with an explicit "depends on #k" note per item.
Show the user a summary table of what was created (or the task
list, in ad-hoc mode):
| ID / # |
Title |
Priority |
Depends On |
Hand off. End with: "Run /rig-sprint <ID1> <ID2> ... (or paste the
task list back) to batch-execute these in phased dependency order."
Don't move tickets to Todo or auto-run — the user picks the entry point.
If the user said plan (no description) — or passed no arguments at all
Preview-mode for the existing sprint queue. Neither launches work; they
show what's ready to run and wait for the user to pick items or kick off
the sprint.
- Fetch ready work:
- Linear:
mcp__claude_ai_Linear__list_issues with project =
tracker.project, state "Todo", limit: 100 (page via cursor if
truncated). Also check "In Progress" for in-flight work.
- GitHub:
gh issue list --state open (optionally filtered by a
"ready" label the repo uses).
- Ad-hoc (
none): there is no queue — say so and ask the user to
supply the task list.
- Show the user: which items are ready, a suggested phase grouping based
on dependencies (
blockedBy/blocks relations, or "Blocked by #N"
text), and estimated scope per phase.
- Ask the user to confirm before launching.
If the user specified ticket identifiers (or a task list)
- Resolve the items.
- Detect ticket IDs by
tracker.ticketPrefix. For Linear, fetch each
with mcp__claude_ai_Linear__get_issue; for GitHub,
gh issue view <number>. In ad-hoc mode, each argument/bullet is a
task description — no fetch.
- Determine phases:
- Group items with no inter-dependencies into the same phase.
- Items that depend on other specified items go in a later phase.
- Use
blockedBy/blocks relations, "Blocked by #N" text, or the
description clues (ad-hoc: the "depends on #k" notes) to order them.
- Show the proposed phases to the user for confirmation.
- Mark items in-flight (tracker only):
- Guard —
tracker.githubIntegration: if true, skip the bulk move
here — each /rig-task sets its own item to "In Progress" at start
(Step 1), and GitHub advances In Review / Done from PR events.
- Otherwise, move every item in the sprint to Todo (Linear:
save_issue with state: "Todo").
- Ad-hoc mode: nothing to move.
- Execute each phase. Within a phase, items are independent and can
run in parallel; whichever PR lands second rebases on the trunk. For
each item in the phase, run
/rig-task (passing the ticket ID,
or the task description in ad-hoc mode) and act on its returned outcome
— only a clean review is merge-green; anything else stops for a human.
Move to the next phase only after every item in the prior phase has
its PR merged.
- Between phases and at the end, run
/rig-tidy to audit the merged
commits for dead code, duplicates, and stale comments before building
on top of them.
Implementing each item
Each item is implemented by the /rig-task skill — a self-contained
spec → worktree → TDD → pre-PR review → open PR → review-bot loop
orchestrator. Sprint does not reimplement that loop; it just sequences the
items and calls /rig-task per item (Step 5 above), reading the config
knobs (tracker.*, vcs.*, test.*, review.*) the same way.
/rig-task never auto-merges and returns an outcome string; sprint uses
it to gate phase progression (merge only on clean, run /rig-tidy
between phases). See the /rig-task skill for the full per-item cadence.
1---2name: rig-sprint3description: Plan or run a sprint of independent tickets (or ad-hoc tasks). Use 'plan <feature>' to decompose a feature into independent tickets (no integration branch — each lands on the trunk on its own). Pass ticket IDs (or task descriptions) to execute them in phased dependency order with cleanup between phases. With no args (or just 'plan'), previews the current sprint-ready queue without launching anything. Triggers on: 'sprint', 'plan sprint', 'plan this as a sprint', 'break this into tickets', 'run tickets', 'execute tickets', 'run these tickets', 'kick off tickets', 'start sprint'.4---56# Sprint Orchestrator78A sprint is a batch of *independent* work items that each land on the9trunk on their own. Use this when the work decomposes into pieces that10don't interleave (no shared runtime contract across siblings, no11half-migrated state if you ship one without the others). If children12do interleave, use an epic / integration-branch flow instead — same13decomposition step, plus a shared branch the children stack on.1415## Configuration1617Reads `.rig/config.json` (missing keys → defaults):1819| Key | Default | Used for |20|---|---|---|21| `tracker.provider` | `none` | `linear` \| `github` \| `none`. Selects the ticket backend, or ad-hoc mode. |22| `tracker.team` | — | Linear team / GitHub org for list/create. |23| `tracker.project` | — | Linear project for list/create. |24| `tracker.ticketPrefix` | — | Recognize ticket IDs in `$ARGUMENTS`. |25| `tracker.githubIntegration` | `false` | If true, GitHub drives PR/merge transitions; each `/rig-task` sets only the start-of-work In Progress. |26| `tracker.shapeLabels.sprint` | `sprint` | GitHub-only label applied to each item at creation so a board/dispatcher can pick up sprint items. Omit `shapeLabels` to skip. |27| `vcs.baseRef` | `origin/main` | Base each ticket's branch is cut from. |28| `vcs.branchConvention` | `{user}/{ticket}-{slug}` | New-branch template. |29| `vcs.defaultBranch` | `main` | Trunk each PR targets. |30| `vcs.protectedBranchMergeQueue` | `false` | If true, merge via `gh pr merge --auto` and never pass `--rebase`/`--squash`. |31| `runtime.installCommand` / `packageManager` | `npm` | Install command inside a worktree. |32| `test.command` | `npm test` | Test step in each per-ticket implementation. |33| `sourceScope[0]` | `src` | Default codebase area to explore during decomposition. |34| `style.guideFile` | `.claude/STYLE.md` | Writing style for item titles, bodies, and the hand-off report. |3536**Tracker modes:**37- `linear` — tickets are Linear issues; use the `mcp__claude_ai_Linear__*` tools.38- `github` — tickets are GitHub issues; use `gh issue`.39- `none` — **ad-hoc mode.** There are no ticket IDs. Treat each item in40 `$ARGUMENTS` (or each bullet the user gives) as a task *description*.41 Skip all create/list/move-ticket steps; the sprint operates directly42 on the task list, and each task's implementation opens a PR whose title43 is the task description. `plan <feature>` still decomposes into a44 numbered task list — it just prints it instead of creating tickets.4546## Arguments4748The user invoked this with: $ARGUMENTS4950## What to do5152### If the user said `plan <FEATURE-DESCRIPTION>` (decompose a feature)5354Create independent work items that can each be picked up and landed on55the trunk directly — no parent epic, no integration branch.56571. **Read context.**58 - Any product/spec docs the project keeps (ask if unsure — don't59 assume a fixed path).60 - Explore the codebase to understand what already exists. Default the61 exploration scope to `sourceScope[0]` (fallback `src`).62 - **Search before creating** to avoid duplicates:63 - Linear: `mcp__claude_ai_Linear__list_issues` with `project` =64 `tracker.project`, a `query` of the feature's key nouns,65 `limit: 50` — search, don't pull the whole board; page via the66 returned cursor only if a likely match looks cut off.67 - GitHub: `gh issue list --search "<key nouns>" --state all`.68 - Ad-hoc (`none`): grep the codebase / recent branches for prior art.692. **Sanity-check it's actually sprint-shaped (independent), not70 epic-shaped (interleaved).** If at least one child's runtime contract71 genuinely depends on another being partially complete (the middle72 state would break the trunk), stop and tell the user to use an73 epic / integration-branch flow instead.743. **Break the feature into 3–8 discrete items,** ordered by dependency.75 No parent ticket.764. **Materialize the items:**77 - **Linear:** `mcp__claude_ai_Linear__save_issue` per item — `team` =78 `tracker.team`, `project` = `tracker.project`, short action-oriented79 `title` ("Add X", "Wire up Y", "Implement Z"), `state: "Backlog"`,80 `priority` 2/3/4, a markdown `description` (Overview, Acceptance81 Criteria, dependency references). **Set `blockedBy` for every real82 dependency** — not optional; the phaser relies on it to group83 correctly.84 - **GitHub:** `gh issue create` per item with the same title/body, adding85 the sprint shape label — `--label "<L>"` where `<L>` =86 `tracker.shapeLabels.sprint` (default `sprint`) — so a Project board /87 dispatcher can pick up sprint items directly (skip the label if88 `tracker.shapeLabels` is absent; ensure it exists first with89 `gh label create "<L>" --force`). Encode dependencies as "Blocked by #N"90 in the body (GitHub has no native blockedBy).91 - **Ad-hoc (`none`):** don't create anything — just produce the92 numbered task list with an explicit "depends on #k" note per item.935. **Show the user a summary table** of what was created (or the task94 list, in ad-hoc mode):9596 | ID / # | Title | Priority | Depends On |97 |--------|-------|----------|------------|98996. **Hand off.** End with: *"Run `/rig-sprint <ID1> <ID2> ...` (or paste the100 task list back) to batch-execute these in phased dependency order."*101 Don't move tickets to Todo or auto-run — the user picks the entry point.102103### If the user said `plan` (no description) — or passed no arguments at all104105Preview-mode for the existing sprint queue. Neither launches work; they106show what's ready to run and wait for the user to pick items or kick off107the sprint.1081091. Fetch ready work:110 - **Linear:** `mcp__claude_ai_Linear__list_issues` with `project` =111 `tracker.project`, state `"Todo"`, `limit: 100` (page via cursor if112 truncated). Also check `"In Progress"` for in-flight work.113 - **GitHub:** `gh issue list --state open` (optionally filtered by a114 "ready" label the repo uses).115 - **Ad-hoc (`none`):** there is no queue — say so and ask the user to116 supply the task list.1172. Show the user: which items are ready, a suggested phase grouping based118 on dependencies (`blockedBy`/`blocks` relations, or "Blocked by #N"119 text), and estimated scope per phase.1203. Ask the user to confirm before launching.121122### If the user specified ticket identifiers (or a task list)1231241. **Resolve the items.**125 - Detect ticket IDs by `tracker.ticketPrefix`. For Linear, fetch each126 with `mcp__claude_ai_Linear__get_issue`; for GitHub,127 `gh issue view <number>`. In ad-hoc mode, each argument/bullet is a128 task description — no fetch.1292. **Determine phases:**130 - Group items with no inter-dependencies into the same phase.131 - Items that depend on other specified items go in a later phase.132 - Use `blockedBy`/`blocks` relations, "Blocked by #N" text, or the133 description clues (ad-hoc: the "depends on #k" notes) to order them.1343. **Show the proposed phases** to the user for confirmation.1354. **Mark items in-flight (tracker only):**136 - **Guard — `tracker.githubIntegration`:** if true, skip the bulk move137 here — each `/rig-task` sets its own item to "In Progress" at start138 (Step 1), and GitHub advances In Review / Done from PR events.139 - Otherwise, move every item in the sprint to Todo (Linear:140 `save_issue` with `state: "Todo"`).141 - Ad-hoc mode: nothing to move.1425. **Execute each phase.** Within a phase, items are independent and can143 run in parallel; whichever PR lands second rebases on the trunk. For144 **each item** in the phase, run **`/rig-task`** (passing the ticket ID,145 or the task description in ad-hoc mode) and act on its returned outcome146 — only a `clean` review is merge-green; anything else stops for a human.147 Move to the next phase only after **every** item in the prior phase has148 its PR merged.1496. **Between phases and at the end,** run `/rig-tidy` to audit the merged150 commits for dead code, duplicates, and stale comments before building151 on top of them.152153## Implementing each item154155Each item is implemented by the **`/rig-task`** skill — a self-contained156`spec → worktree → TDD → pre-PR review → open PR → review-bot loop`157orchestrator. Sprint does not reimplement that loop; it just sequences the158items and calls `/rig-task` per item (Step 5 above), reading the config159knobs (`tracker.*`, `vcs.*`, `test.*`, `review.*`) the same way.160161`/rig-task` never auto-merges and returns an outcome string; sprint uses162it to gate phase progression (merge only on `clean`, run `/rig-tidy`163between phases). See the `/rig-task` skill for the full per-item cadence.