ticket-swarm
Skill3 starsChanged 11 days agoMITView on GitHub
Batch-process Jira tickets with parallel agent pipelines. Use when the user types /ticket-swarm, starts a prompt with 'Swarm', or asks to 'fix my bugs', 'swarm my tickets', 'batch fix bugs', 'process my bug queue', or 'swarm this story'. Harvests tickets from Jira (or receives child tickets from ticket-pickup), triages in parallel, groups by domain with team leads, spawns isolated pipelines per ticket, and gates on PR creation only.
- Commits and pushes
In this repository36 other files it gives its agents.
- agent-statsSkill
- aristotle-deconstructorSkill
- babysit-prsSkill
- briefingSkill
- code-auditorSkill
- core-editSkill
- create-jira-ticketSkill
- create-tech-specSkill
- cyrus-tdd-engineerSkill
- doctorSkill
- dotfiles-syncSkill
- forgeSkill
- google-docsSkill
- google-driveSkill
- grill-meSkill
- handoffSkill
- lessons-reviewSkill
- mermaid-diagramsSkill
- metrics-emitSkill
- obligationsSkill
- optimus-plannerSkill
- overlay-initSkill
- performance-reviewSkill
- pr-create-from-commitsSkill
- ranger-reviewerSkill
- record-demoSkill
- review-contextSkill
- review-respondSkill
- scout-reviewerSkill
- self-evaluateSkill
- smart-compactSkill
- smart-statuslineSkill
- swarm-retroSkill
- team-leadSkill
- ticket-pickupSkill
- to-prdSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
46 rules. About 0 are common, 29 are distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈29
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 78
If child_tickets is provided by the caller (e.g., ticket-pickup detected a Story and delegated its sub-tasks), skip JQL harvest entirely.
- Very specific: line 86
If mock_tickets is provided alongside dry_run: true, skip all Jira operations.
- Distinctive: line 102
Custom JQL: If the user provides JQL, use it directly.
- Distinctive: line 107
Limit: Default to 10 tickets max.
- Distinctive: line 124
If no tickets are found, inform the user and suggest broadening the query.
- Very specific: line 126
If Jira is unavailable, show ⚠️ Jira unavailable — provide ticket keys manually (comma-separated) and wait for input.
- Distinctive: line 150
Subagent failure handling: If a triage subagent fails or returns empty, log the failure and continue with remaining tickets.
- Distinctive: line 191
After the user approves the triage table, group the approved tickets by domain based on their codebase references from enrichment:
- Distinctive: line 199
Unknown: No codebase references found — falls back to Jira component field, or groups with the largest existing cluster
- Distinctive: line 202
If a ticket touches both backend and frontend, it goes to Infra.
- Distinctive: line 228
Before dispatching to team leads, scan across all domain clusters for shared file references:
- Distinctive: line 232
If any file appears in tickets assigned to different domain clusters:
- Very specific: line 258
If dry_run: true, stop here.
- Distinctive: line 259
Instead, present the full analysis:
- Distinctive: line 286
No Jira transitions, no branches, no code changes.
- Very specific: line 302
Resolve the target repo: if the ticket's labels include repo:<name>.
- Very specific: line 320
Check for a pre-existing branch: Run git branch --list "*{ticket-key}*".
- Distinctive: line 323
Ensure it is up to date with the default branch.
- Distinctive: line 325
Create the branch: if no match found.
- Very specific: line 344
Fallback: if newbranch is not available: detect the default branch via git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed …
- Very specific: line 349
If using best-of-n-runner subagent type, the worktree isolation is handled automatically by the runner.
- Distinctive: line 393
All tests pass (hard requirement)
- Very specific: line 433
Call getTransitionsForJiraIssue to find the "In Progress" transition ID
- Very specific: line 434
Call transitionJiraIssue with the transition ID
- Very specific: line 435
Add a comment: 🤖 Picked this one up.
- Distinctive: line 437
Verify: After all transitions, confirm each ticket's status changed by checking the response.
- Distinctive: line 474
Do not retry, do not run smart failure analysis, do not escalate.
- Distinctive: line 485
When a pipeline reports a blocker:
- Distinctive: line 494
When both attempts complete:
- Distinctive: line 495
Run Ranger review on each attempt's branch (complex tickets always use Ranger for staff-level analysis).
- Distinctive: line 511
Wait for user choice on complex tickets.
- Distinctive: line 522
If the reviewer passes (no blocking issues): the ticket is approved for PR creation.
- Distinctive: line 523
If the reviewer finds blocking issues: the ticket is held for resolution.
- Very specific: line 564
NEVER use raw gh pr create, gh api, or manual PR construction.
- Distinctive: line 581
After all pipelines complete (or are aborted):
- Distinctive: line 589
Leave status unchanged. There is no PR to review.
- Distinctive: line 599
When the swarm is complete, present a final report:
- Very specific: line 627
After the final summary is presented, write a structured run log to ~/.claude/tasks/<project>/swarm-runs/{timestamp}-{run-id}.md for …
- Very specific: line 632
Create ~/.claude/tasks/<project>/swarm-runs/ if it does not exist.
- Very specific: line 671
After writing the swarm run log to ~/.claude/tasks/<project>/swarm-runs/, emit a swarm_complete event.
- Distinctive: line 685
If emit fails, log and continue.
- Very specific: line 693
Autonomous mode relaxes Gate 2: When execution_mode: autonomous, auto-create draft PRs for tickets where the reviewer passed with no …
- Distinctive: line 696
Always show the summary of what was created after the fact.
- Very specific: line 707
NEVER create PRs manually: Always delegate to /pr-create-from-commits.
- Distinctive: line 716
Jira is always best-effort: Never block pipeline execution on Jira failures — but always attempt the transition.
- Distinctive: line 721
If you discover something during this task that would improve this skill, propose the change and ask me to confirm before saving it.
≈ “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
Audience for Jira comments
Jira comments posted by this skill are read by everyone on the ticket — PMs, designers, QA engineers, junior engineers, and the engineer who's actually doing the work. Write them in plain language. Avoid agent-internal vocabulary (no "Optimus", "Cyrus", "Ranger", "Scout", "pipeline", "team-lead", "sentinel", "max turns", "cap hit"). Describe what just happened and what comes next in concrete actions, not labels. Keep them short — these are Jira comments, not status pages.
Voice: write the assistant's comments in first person (e.g., "Picked this one up.",
"Had to stop on this one.") — not third person ("Automated assistant has…"). The 🤖
prefix is the machine-marker; the first-person voice keeps the comments readable as a
brief status update rather than a system notification. The 🤖 prefix on every comment is
required by the canonical rule in ~/.claude/AGENTS.md § "Automated Comment Marker — 🤖
prefix" (applies to all agent-posted Jira and GitHub comments); the example strings below
already carry it.
Ticket Swarm
Harvest a batch of Jira tickets, triage them in parallel, group by domain with team leads, spawn isolated pipelines per ticket, and produce PRs with minimal human gating.
This skill orchestrates: Jira -> Ticket Pickup (batch) -> Parallel Pipelines -> Code Auditor/Scout/Ranger Review -> PR Creation with two human gates: triage approval and PR approval.
Responsibility boundaries
Ticket Swarm is a batch orchestrator. It composes existing skills — it never does their jobs.
<!-- BEGIN RESPONSIBILITY BOUNDARIES --><!-- EXTRA_ROWS: ticket-swarm,ticket-pickup -->| Agent | Sole responsibility | NEVER does |
| Ticket Swarm | Batch harvest, triage, domain grouping, team-lead dispatch, progress monitoring, PR gating | Write code, produce plans, perform strategic analysis, review PRs, enrich individual tickets |
| Ticket Pickup | Fetch ticket, enrich with codebase context, classify complexity, route to pipeline | Write code, produce plans, perform strategic analysis, review PRs |
| Aristotle | Strategic analysis — assumptions, first principles, highest-leverage direction | Name file paths, produce code, plan execution, review PRs |
| Optimus | Execution planning — file paths, step sequencing, risk assessment, architecture | Write code, make file edits, run commands, re-litigate upstream strategic decisions, review PRs |
| Cyrus | TDD implementation — write tests first, then code, hit 80%+ coverage | Redesign architecture, question strategic direction, skip tests, review PRs |
| Ranger | Staff-level PR review — analyze diffs, score issues, report findings | Write code, make edits, implement fixes, plan architecture, perform strategic analysis |
| Scout | PR review — analyze diffs, score issues, report findings | Write code, make edits, implement fixes, plan architecture, perform strategic analysis |
| Auditor | Code complexity analysis, reviewer routing | Write code, review code, post to GitHub, implement fixes |
<!-- END RESPONSIBILITY BOUNDARIES -->Execution modes
Ticket Swarm supports two special modes in addition to the standard flow:
dry_run— run harvest, triage, and domain grouping but stop before launching any pipelines. Presents the full analysis of what would happen. Triggered by "Swarm, dry-run my bugs" ordry_run: true.mock_tickets— when combined withdry_run: true, accepts a list of mock ticket data instead of querying Jira. Useful for testing classification heuristics and domain grouping without MCP dependencies. Format:[{key, summary, type, description, files_hint}, ...]wherefiles_hintis a list of file paths that replaces codebase search.
Step 1: Harvest tickets
Ticket Swarm accepts tickets from three sources:
Source A: Child tickets from ticket-pickup (Story decomposition)
If child_tickets is provided by the caller (e.g., ticket-pickup detected
a Story and delegated its sub-tasks), skip JQL harvest entirely. Use the
provided ticket list directly and proceed to Step 2.
The parent_story_key is also passed for Jira comment context.
Source C: Mock tickets (dry-run testing only)
If mock_tickets is provided alongside dry_run: true, skip all Jira
operations. Use the mock data directly:
keyandsummarypopulate the triage tabletypedetermines issue type handlingdescriptionis used for classificationfiles_hintreplaces codebase search in enrichment (list of file paths the ticket is expected to touch)
Proceed to Step 2 with mock data.
Source B: JQL harvest from Jira (default)
Parse the user's input to build a JQL query:
- Default ("Swarm, fix my bugs" or similar): Use
assignee = currentUser() AND type in (Bug, Task, Sub-task) AND status in ("To Do", "Open") ORDER BY priority ASC, created ASC - Custom JQL: If the user provides JQL, use it directly.
- Project filter: "Swarm PROJ bugs" ->
project = "PROJ" AND assignee = currentUser() AND type in (Bug, Task) AND status in ("To Do", "Open") ORDER BY priority ASC - Priority filter: "Swarm P1 bugs" ->
assignee = currentUser() AND type = Bug AND priority = "Highest" AND status in ("To Do", "Open") - Limit: Default to 10 tickets max. User can override ("Swarm, fix my top 5 bugs").
Primary: Atlassian MCP plugin (plugin-atlassian-atlassian):
searchJiraIssuesUsingJql(
jql=<constructed_query>,
fields=["summary", "description", "status", "priority", "components", "labels", "assignee", "issuetype"],
maxResults=<limit>
)For company-specific Jira fallback, consult ## Jira fallback in ~/.claude/overlay-context.md. If that file is absent, proceed with the primary tool only.
<!-- BEGIN OVERLAY-FRAGMENT: ticket-swarm-jira-fallback --><!-- END OVERLAY-FRAGMENT: ticket-swarm-jira-fallback -->If no tickets are found, inform the user and suggest broadening the query.
If Jira is unavailable, show ⚠️ Jira unavailable — provide ticket keys
manually (comma-separated) and wait for input.
Assignee target
Step 4.5 assigns each launched ticket to the assignee target: the assignee
input when the caller passes one (ticket-pickup does, from its own Step 1),
otherwise parsed from the user's swarm request the way ticket-pickup Step 1
does: default the user, a named person, or no change.
Step 2: Parallel triage
For each harvested ticket, run the ticket-pickup skill's enrichment and
classification steps (Steps 2-4) in parallel using explore subagents.
Launch one explore subagent per ticket (up to 5 concurrent). Each subagent:
- Fetches full ticket context via
getJiraIssue - Searches the codebase for references (stack traces, error messages, classes)
- Classifies complexity (Simple / Medium / Complex)
- Looks up the story points field and, if the ticket has none, estimates them (ticket-pickup Step 2.2 and Step 4's story point estimate)
Subagent failure handling: If a triage subagent fails or returns empty, log the failure and continue with remaining tickets. If >50% of triage agents fail, abort triage and report. Follow CLAUDE.md error handling defaults.
Aggregate results into a ranked table.
Step 3: Present triage table and gate
Present the batch to the user:
Ticket Swarm: N tickets ready
# Ticket Priority Complexity Points Summary Pipeline
1 PROJ-1001 P1 Simple 1* NPE in RefundProcessor Cyrus direct
2 PROJ-998 P2 Medium 3 Campaign preview 404s Optimus -> Cyrus
3 PROJ-1015 P1 Complex 8* Auth token race condition Aristotle -> Optimus -> Cyrus
4 PROJ-1020 P3 Simple - Typo in error message Cyrus direct
5 PROJ-1003 P2 Medium 3* Flag check missing Optimus -> Cyrus
* = estimated, will be set on launch - = no points field
-> all = Launch all pipelines
-> 1,3 = Launch specific tickets (comma-separated)
-> r = Re-triage with additional context
-> e N = Escalate ticket N (bump complexity one level)
-> s N = Simplify ticket N (drop complexity one level)
-> p N M = Use M story points for ticket N (1, 2, 3, 5, or 8)
-> x = CancelThis is Gate 1 — the user must approve which tickets to swarm. Wait for explicit input. Do not proceed without approval.
Step 3.5: Group into domains and assign team leads
After the user approves the triage table, group the approved tickets by domain based on their codebase references from enrichment:
- Backend: References in
app/controllers/,app/lib/,app/models/,tests_phpunit/ - Frontend: References in
web/js/src/,web/css/, frontend test files - Infra/Cross-Boundary: References span both backend and frontend, or
touch
proto/,config/,data/schemas/, or cross-service boundaries - Unknown: No codebase references found — falls back to Jira component field, or groups with the largest existing cluster
If a ticket touches both backend and frontend, it goes to Infra.
Present the grouping:
Domain Assignments:
Backend Lead (3 tickets):
PROJ-1001 (Simple) -> PROJ-1003 (Medium) [sequenced: shared file]
PROJ-1007 (Simple) [independent]
Frontend Lead (2 tickets):
PROJ-998 (Medium), PROJ-1020 (Simple) [independent, parallel]
Infra Lead (1 ticket):
PROJ-1015 (Complex) [best-of-N]In gated mode: Show the grouping and let the user adjust (move tickets between domains, override sequencing).
In autonomous mode: Auto-approve the grouping. If domain classification is ambiguous for a ticket, assign it to Infra (the most cautious domain).
Cross-domain overlap check
Before dispatching to team leads, scan across all domain clusters for shared file references:
- Collect all codebase reference paths from every enriched ticket
- If any file appears in tickets assigned to different domain clusters:
- Move the dependent tickets into the same cluster as the ticket that owns the primary file (prefer the cluster with more tickets touching it)
- Or flag the overlap to the user and ask which cluster should own it
- This prevents parallel team leads from producing conflicting changes to the same file
Launch team leads
Launch one team-lead subagent per domain cluster. Each receives:
- The cluster of enriched tickets with their classifications
- The domain tag
swarm_mode: true,execution_mode: autonomousunbounded: trueif the swarm was invoked with itparent_story_keyif this swarm originated from a Story decomposition
Team leads handle dependency detection, domain context injection, and within-cluster sequencing internally. They report progress back to this orchestrator.
If a team-lead subagent fails: Log the failure, mark that domain cluster as blocked, and continue with other clusters. Surface the failure to the user.
Dry-run stop point
If dry_run: true, stop here. Do not launch team leads or pipelines.
Instead, present the full analysis:
Dry Run Complete: N tickets analyzed
Domain Assignments:
Backend Lead (3 tickets):
PROJ-1001 (Simple) -> PROJ-1003 (Medium) [sequenced: shared file]
PROJ-1007 (Simple) [independent]
Frontend Lead (1 ticket):
PROJ-1020 (Simple) [independent]
Infra Lead (1 ticket):
PROJ-1015 (Complex, best-of-2) [Ranger review]
Estimated pipelines: 6 (5 tickets + 1 best-of-N extra)
Estimated agents: ~11
Reviewer breakdown: 2 Scout, 2 Auditor, 2 Ranger
Repo roots: PROJ-1015 (repo:billing-service) -> /Users/me/dev/billing-service [labeled tickets only]
No pipelines launched. Use "Swarm, fix my bugs" to execute.For each ticket carrying a repo:<name> label, resolve it via
repo-registry.sh resolve <name> and show the result (or the failure) on
the Repo roots: line — the lookup is a read, so it stays within the
dry-run contract below.
No Jira transitions, no branches, no code changes. Pure analysis. Return without proceeding to Step 4.
Step 4: Monitor team-lead pipelines
Team leads manage the actual pipeline dispatch within their clusters. Ticket Swarm monitors their progress and aggregates results.
For each approved ticket, the team lead spawns an isolated pipeline:
Branch and worktree setup
Each ticket gets its own branch. Before launching any pipeline:
- Resolve the target repo if the ticket's labels include
repo:<name>. Runbash ~/.claude/skills/ticket-pickup/scripts/repo-registry.sh resolve <name>. On success (exit 0, absolute path on stdout), run all subsequent branch commands in this block against that repo viagit -C /abs/path ..., and include aRepo root: /abs/pathline in the pipeline agent's prompt. On any non-zero exit (1 not found, 2 invalid, 3 no registry, 4 malformed), log the failure, mark the ticket blocked, and continue with the other tickets — surface the failure to the user. Never prompt through a bad registry entry: the swarm runs autonomously, so a lookup failure blocks that ticket rather than pausing the batch. Norepo:<name>label → today's behavior exactly: commands run in the current working directory and noRepo root:line is passed. - Determine the branch name:
{ticket-key}-{slug}(e.g.,PROJ-1001-fix-refund-npe). Slugify from the ticket summary. - Check for a pre-existing branch: Run
git branch --list "*{ticket-key}*". If a matching branch already exists (user pre-created it), use it instead of creating a new one. Ensure it is up to date with the default branch. Create the branch if no match found.
If step 1 resolved a repo root (path differs from the current working directory): do NOT use the
newbranchalias — it is an optional user-overlay alias (from.aliases.local, not part of core) and is cwd-bound, so it would act on the wrong repo. Use the plain-git commands with every command run viagit -C /abs/path: detect the default branch viagit -C /abs/path symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'(fall back tomainthenmasterviagit -C /abs/path show-ref), then:git -C /abs/path checkout {default} && git -C /abs/path pull origin {default} && git -C /abs/path checkout -b {ticket-key}-{slug}Otherwise (unlabeled ticket, running in the current working directory): use the
newbranchshell alias if available (from.aliases.local):newbranch {ticket-key}-{slug}. This handles default branch detection (queriesorigin/HEAD, supports any branch name), checkout,git pull origin, and new branch creation automatically.Fallback if
newbranchis not available: detect the default branch viagit symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'(fall back tomainthenmasterviagit show-ref), then:git checkout {default} && git pull origin {default} && git checkout -b {ticket-key}-{slug}- If using
best-of-n-runnersubagent type, the worktree isolation is handled automatically by the runner. Each attempt still gets its own branch suffix (-attempt-1,-attempt-2).
Dispatch by complexity
Simple tickets (Cyrus direct):
Launch one cyrus-tdd-engineer subagent per ticket. Pass:
- The enriched ticket brief
- Jira ticket key
- Branch name
- Repo root (absolute path — only when the ticket carries a
repo:<name>label; omit otherwise) swarm_mode: trueexecution_mode: autonomousunbounded: trueif the swarm was invoked with itticket_complexity: simple
Medium tickets (Optimus -> Cyrus):
Launch one optimus-planner subagent per ticket. Pass:
- The enriched ticket brief as the problem statement
- Jira ticket key
- Branch name
- Repo root (absolute path — only when the ticket carries a
repo:<name>label; omit otherwise) swarm_mode: trueexecution_mode: autonomousunbounded: trueif the swarm was invoked with itticket_complexity: medium
The Optimus skill auto-approves the Cyrus handoff in autonomous mode.
Forwards ticket_complexity to Cyrus.
Complex tickets (Aristotle -> Optimus -> Cyrus):
Launch using best-of-n-runner subagent type with 2 parallel attempts.
Each attempt runs the full aristotle-deconstructor pipeline. Pass:
- The enriched ticket brief
- Jira ticket key
- Branch name (each attempt gets a suffix:
-attempt-1,-attempt-2) - Repo root (absolute path — only when the ticket carries a
repo:<name>label; omit otherwise) swarm_mode: trueexecution_mode: autonomousunbounded: trueif the swarm was invoked with itticket_complexity: complex
The best attempt is selected based on:
- All tests pass (hard requirement)
- Fewer files changed (prefer minimal fix)
- Higher test coverage
- Cleaner Ranger review (fewer issues flagged)
Note: Complex tickets use Ranger (Opus) for review instead of Scout.
The ticket_complexity: complex flag is passed through to Cyrus, which
auto-triggers Ranger on completion. Best-of-N comparison also uses Ranger
to evaluate trade-offs between attempts.
Parallelism limits
- Launch up to 3 pipelines concurrently to avoid overwhelming resources.
- Queue remaining tickets and launch as slots free up.
- Simple tickets are fastest — prioritize launching them first to free slots.
Note: These concurrency limits are guidelines for the orchestrator, not hard enforcement. The actual parallelism depends on the Agent/Task tool's behavior in the current environment. The orchestrator should respect these as targets and adjust based on observed performance.
Step 4.5: Transition Jira tickets (MANDATORY)
You MUST transition each launched ticket to "In Progress" IMMEDIATELY after pipeline launch. Do not defer this to later steps. Do not skip it.
In swarm mode ticket-pickup skips its Step 7, so this step is the only writer of assignment, story points, the transition and the comment.
For each ticket:
- Assign it to the
assigneetarget, following ticket-pickup Step 7.1's autonomous rules; with no change, skip assignment. Unassigned tickets (common for Story sub-tickets) are assigned to the target. A teammate's ticket is reassigned only when an assignee was named; otherwise it is left in place and listed in the final summary. - Set story points if the ticket has none and its issue type has a points
field, following ticket-pickup Step 7.2. Use the estimate approved at
Gate 1, including any
p N Mchange. - Call
getTransitionsForJiraIssueto find the "In Progress" transition ID - Call
transitionJiraIssuewith the transition ID - Add a comment:
🤖 Picked this one up. {action_phrase}— use the same{action_phrase}mapping as ticket-pickup Step 7.5 (Simple → going straight to implementing, Medium → planning then implementing, Complex → strategic analysis then planning then implementing). Branch detail is omitted here; it appears on the PR link when work is submitted.
Verify: After all transitions, confirm each ticket's status changed by checking the response. If a transition fails (no valid transition, Jira unavailable), log the failure but do not block the pipeline.
This step is not optional. The user expects ticket status to reflect pipeline activity in real time.
Step 5: Monitor and report progress
As team leads report wave completions, maintain a live progress dashboard:
Swarm Progress: 3/5 complete
PROJ-1001 [DONE] PR #482 — Scout: approved, awaiting user review
PROJ-998 [DONE] PR #483 — Auditor->Scout: 1 issue, awaiting resolution
PROJ-1015 [RUNNING] Aristotle complete, Optimus planning... (attempt 1/2, Ranger review)
PROJ-1020 [DONE] PR #484 — Scout: approved, awaiting user review
PROJ-1003 [BLOCKED] Cyrus hit a test failure — needs input
-> review N = Review PR for ticket N
-> retry N = Re-run pipeline for ticket N
-> abort N = Cancel pipeline for ticket N
-> status = Refresh progressHandling an advisory outcome
A pipeline can end with a correct answer that is not a code change: the
Complex route's Aristotle stage judges first principles the wrong tool
(Phase 0 stop) or concludes no code changes are needed. ticket-pickup
returns this as outcome: advisory with a one-line verdict. It is the
swarm's third terminal outcome — a success, not a blocker:
- Show it as
[ADVISORY]on the dashboard with the verdict, not[BLOCKED]. - Do not retry, do not run smart failure analysis, do not escalate.
- Count it under
Advisoryin the summary, run log, andswarm_complete. - Best-of-N: if every attempt returns advisory, the ticket is advisory (take the clearest verdict). If one attempt implements and another returns advisory, the attempts disagree on whether this is a code change at all; surface both to the user with the verdict alongside the implementation's test result. Do not auto-select — the existing best-of-N gate ("wait for user choice on complex tickets") applies.
Handling blockers
When a pipeline reports a blocker:
- Surface the blocker immediately with context (error message, failing test, file conflict).
- Offer options: retry, provide context, skip, or abort.
- Other pipelines continue independently — a blocker on one ticket does not hold the rest.
Handling best-of-N completion (complex tickets)
When both attempts complete:
- Run Ranger review on each attempt's branch (complex tickets always use Ranger for staff-level analysis).
- Compare: test results, files changed, Ranger findings, merge readiness.
- Recommend the better attempt. Present comparison:
PROJ-1015: Best-of-2 complete (reviewed by Ranger) Attempt 1: 4 files changed, 12 tests, coverage 87%, Ranger: READY, 0 issues Attempt 2: 6 files changed, 15 tests, coverage 91%, Ranger: NEEDS CHANGES, 1 issue Recommendation: Attempt 1 (fewer changes, clean staff-level review) -> 1 = Use attempt 1 -> 2 = Use attempt 2 -> x = Discard both - Wait for user choice on complex tickets. This is not auto-approved.
Step 6: PR creation gate
This is Gate 2 — the final checkpoint before PRs are created.
For each completed pipeline:
- The appropriate reviewer runs automatically (Scout for simple, code auditor for medium, Ranger for complex — triggered by Cyrus completion in autonomous mode).
- If the reviewer passes (no blocking issues): the ticket is approved for PR creation.
- If the reviewer finds blocking issues: the ticket is held for resolution.
In autonomous mode: Auto-create draft PRs for all approved tickets (reviewer passed with no blocking issues). Do NOT wait for user input on approved tickets. For held tickets (reviewer found blocking issues), surface the issues and wait for user direction. After all auto-created PRs complete, show the summary:
PR creation complete (autonomous): 3 created, 1 held
# Ticket Branch PR Status
1 PROJ-1001 PROJ-1001-fix-refund-npe #201 Draft created
2 PROJ-1020 PROJ-1020-fix-error-typo #202 Draft created
3 PROJ-1015 PROJ-1015-fix-race-cond #203 Draft created
4 PROJ-998 PROJ-998-fix-preview-404 — HELD: 1 blocking issue
Held tickets:
PROJ-998: Scout found 1 blocking issue — potential SQL injection in query builder
-> fix 4 = Address reviewer issues and retry
-> skip 4 = Skip PR creation for this ticketIn gated mode: Present completed tickets for batch PR approval and wait for user input before creating any PRs:
Ready for PR creation: 3 tickets
# Ticket Branch Reviewer Status Files
1 PROJ-1001 PROJ-1001-fix-refund-npe Scout Approved 2
2 PROJ-1020 PROJ-1020-fix-error-typo Scout Approved 1
3 PROJ-1015 PROJ-1015-fix-race-cond Ranger READY 4
4 PROJ-998 PROJ-998-fix-preview-404 Auditor->Scout 1 minor issue 3
-> all = Create PRs for all approved tickets
-> 1,2,3 = Create PRs for specific tickets (comma-separated)
-> fix 4 = Address reviewer issues on ticket 4 first
-> x = Skip PR creationMANDATORY: Use /pr-create-from-commits for ALL PR creation.
NEVER use raw gh pr create, gh api, or manual PR construction.
For each approved ticket, invoke the /pr-create-from-commits skill.
PRs are created as drafts by default. Only create non-draft PRs if the
user explicitly says "open for review" or "create ready PRs".
The skill handles:
- Draft PR creation (
gh pr create --draft) - PR template detection (repo-specific templates)
- Jira status transition
- PR body population from code analysis
Invoke the skill once per ticket. Do not batch — each ticket's PR needs its own skill invocation with the correct branch checked out.
Step 7: Jira cleanup
After all pipelines complete (or are aborted):
For each ticket with a created PR:
- Transition to "In Review" if available.
- Add comment:
🤖 Submitted PR #{number} for review. The ticket's in In Review — it's yours from here.
For advisory tickets (correct no-code answer):
- Add comment:
🤖 Looked into this one and the answer isn't a code change. {verdict}. Leaving the ticket as-is for a human to decide what to do with it. - Leave status unchanged. There is no PR to review.
For blocked/aborted tickets:
- Add comment:
🤖 Had to stop on this one. What happened: {reason}. I've left the ticket in its current state — worth a human look to decide what's next. - Leave status unchanged.
Final summary
When the swarm is complete, present a final report:
Ticket Swarm Complete
Launched: 5 tickets
Completed: 3 (3 PRs created)
Advisory: 1 (PROJ-1030 — first principles says this is a vendor-config change, not code)
Blocked: 1 (PROJ-1003 — test failure, needs manual fix)
PRs created:
- PROJ-1001: PR #482 (approved)
- PROJ-998: PR #483 (approved)
- PROJ-1020: PR #484 (approved)
Left with their assignee:
- PROJ-1004: assigned to Alex Kim, not reassigned
Time: ~12 minutes | Agents spawned: 9Include the "Left with their assignee" block only when Step 4.5 skipped reassigning a teammate's ticket.
Step 8: Write run log
After the final summary is presented, write a structured run log to
~/.claude/tasks/<project>/swarm-runs/{timestamp}-{run-id}.md for post-mortem
analysis by /swarm-retro (see CLAUDE.md § Task Artifact Location for
how to resolve <project>).
Create ~/.claude/tasks/<project>/swarm-runs/ if it does not exist.
# Swarm Run: {timestamp}-{run-id}
## Config
- Source: JQL harvest | child_tickets ({parent-key}) | mock_tickets
- Tickets: {N}
- Domains: Backend ({N}), Frontend ({N}), Infra ({N})
- Dry run: {yes/no}
## Tickets
| Key | Classification | Pipeline | Domain | Reviewer | Status | Duration | Retries |
|-----|---------------|----------|--------|----------|--------|----------|---------|
| {for each ticket...} |
## Blockers
- {ticket}: {description} (retry {N}: {outcome})
## Smart Recovery Actions
- {ticket}: {action} (outcome: {result})
## Sequencing
- {domain}: {sequence description}
## Advisory
- {ticket}: {verdict}
## Summary
- Launched: {N} | Completed: {N} | Advisory: {N} | Blocked: {N}
- PRs: {N} | Time: {duration} | Agents: {N}The run log captures everything the swarm-retro skill needs for analysis.
Dry runs also write a log (with Dry run: yes and no pipeline results)
so classification accuracy can be reviewed before committing resources.
Metrics emit (after run log)
After writing the swarm run log to ~/.claude/tasks/<project>/swarm-runs/,
emit a swarm_complete event. See the metrics-emit library skill for
format and emit instructions.
Data to capture:
tickets_total: total tickets in the swarmcompleted: tickets that produced a PRadvisory: tickets whose pipeline ended with a correct no-code answerblocked: tickets that hit unresolvable blockersprs_created: number of draft PRs createdduration_seconds: wall-clock from swarm start to summaryfirst_pass_rate: (completed on first attempt) / (tickets_total − advisory)agents_spawned: total subagents launched across all pipelines
If emit fails, log and continue.
Gate rules
- Two gates only. Gate 1: triage approval (which tickets to swarm). Gate 2: PR creation (which PRs to submit). Everything between auto-chains.
- Autonomous mode relaxes Gate 2. When
execution_mode: autonomous, auto-create draft PRs for tickets where the reviewer passed with no blocking issues. Only gate on tickets with blocking reviewer findings. Always show the summary of what was created after the fact. - Best-of-N selection is a third mini-gate for complex tickets only. The user picks which attempt wins.
- Blockers surface immediately but don't block other pipelines.
- Ticket Swarm never writes code. It orchestrates team leads, which orchestrate ticket-pickup, which orchestrates the pipeline agents. Composition all the way down.
- Autonomous mode flows downstream. Ticket Swarm passes
execution_mode: autonomousandswarm_mode: true(plusunbounded: truewhen the swarm was invoked with it) to all downstream skills, which pass them to their downstream agents. - NEVER create PRs manually. Always delegate to
/pr-create-from-commits. No rawgh pr create, nogh api, no manual PR body construction. The skill handles templates, Jira, and proper formatting. - NEVER skip Jira transitions. They happen at pipeline launch (Step 4.5), not later. The user expects ticket status to reflect pipeline activity in real time.
- Each pipeline runs as a subagent (or
best-of-n-runnerfor complex tickets) to keep the main context clean. - Jira is always best-effort. Never block pipeline execution on Jira failures — but always attempt the transition.
Maintenance
If you discover something during this task that would improve this skill, propose the change and ask me to confirm before saving it.
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.

