| name | implement-queue |
| description | Work the Butler ready-for-agent issue queue in priority order — select the highest-priority unblocked issue (P0 > P1 > P2) and run /implement-issue on it, looping up to a per-run cap. Use ONLY when explicitly asked to "work the queue" / "implement the next issue(s)", or when fired by the scheduled routine. Do not auto-run. |
Implement Queue
Autonomously works the Butler ready-for-agent issue queue in priority order, one issue at a time, by delegating each to the implement-issue skill. Designed to be run on demand (/implement-queue) or fired by the every-5-hours scheduled routine.
This skill selects and sequences work; implement-issue does the actual implementation. It never assigns priority labels itself — triage is a human decision; this skill only consumes priority labels.
When to run
- An explicit request to "work the queue" / "implement the next issue(s)".
- The scheduled routine (every 5 hours).
Do NOT run this spontaneously. It branches, commits, pushes, and merges PRs. It runs only on explicit invocation.
Per-run budget
Implement at most 3 issues per invocation (MAX_ISSUES = 3), then stop and report. The schedule re-fires every 5 hours to continue from where it left off. This bounds token spend per usage window and prevents runaway loops. The skill is otherwise stateless across runs — each run re-queries the live queue.
Effort & cost: Reserve high reasoning effort for the parts that need it — the adversarial Phase-7 review (xhigh) and any non-trivial TDD. The mechanical loop steps (selecting the next issue, branching, committing, opening the PR, polling CI, squash-merging, branch hygiene) do not need elevated effort and shouldn't run on the most expensive tier. budget_tokens is deprecated on Opus 4.8+; use thinking: { type: "adaptive" } with an effort level instead. Cost rationale and the full optimization plan live in docs/usage-cost.md.
Context hygiene: This loop can run up to 3 issues; context accumulates across them and long context is expensive even when cached. After each issue merges, /clear (or /handoff) before starting the next — each issue is independent and re-queries the live queue, so nothing is lost. Keep per-issue context inside CLAUDE.md's <100k smart zone.
Step 0 — Finish open PRs first
Open PRs are unfinished value; merging them outranks starting new work.
gh pr list --state open
For each open PR: CI green → gh pr merge <PR#> --squash --delete-branch; CI pending → monitor to completion, then merge; CI failing → fix, push, re-check. Only proceed once no PRs are open.
Step 1 — Select the highest-priority eligible issue
An issue is eligible only if ALL hold:
state is open
- has the
ready-for-agent label
- has a priority label —
P0, P1, or P2. A priority label is the opt-in: un-prioritized issues are NEVER auto-picked, which keeps blocked/fuzzy/untriaged work out of the loop until a human triages it.
- not blocked: every issue referenced in its "Blocked by" section is closed/merged.
- not already claimed: the issue has no assignee — another runner is working it (see Work-claiming in
CLAUDE.md / ADR-0007). Exception — stale claim: treat it as eligible anyway if it was assigned >2h ago AND has no open PR referencing it AND no branch pushed for it recently (a crashed session; reclaim it). Read assignees with gh issue list --label ready-for-agent --state open --json number,labels,assignees.
Ranking: P0 before P1 before P2; within the same priority, lowest issue number first.
gh issue list --label ready-for-agent --state open --json number,labels,body
For each candidate, read its "Blocked by" section and confirm each referenced issue is closed (gh issue view <n> --json state). Pick the top-ranked eligible issue.
If no eligible issue exists → stop and report "queue empty (no prioritized, unblocked ready-for-agent issues)".
Step 1.5 — Claim the selected issue
Before any branch or code, claim the issue so a concurrent runner picks a different one (full rules in CLAUDE.md → Work-claiming, and ADR-0007):
gh issue edit <n> --add-assignee @me
Then confirm — re-read the assignee and check no competitor started in the same window:
gh issue view <n> --json assignees --jq '.assignees|map(.login)'
gh pr list --search "<n> in:title" --state all
git ls-remote --heads origin | grep -i "<n>" || true
If a competing claim, open PR, or recently-pushed branch for this issue appears, yield: release (gh issue edit <n> --remove-assignee @me) and return to Step 1 for the next eligible issue. Otherwise proceed to Step 2.
Step 2 — Implement it
Invoke the implement-issue skill with the selected issue number (/implement-issue <n>). That skill owns the full pipeline: branch → TDD → quality gates → dual-axis review → commit → PR → CI-green → squash-merge. Let it run end-to-end.
Step 3 — Loop or stop
After the issue merges, evaluate the stop conditions. If none apply, increment the run counter and, while it is < MAX_ISSUES, return to Step 1 for the next eligible issue.
On a successful merge the squash-merge closes the issue, so the claim needs no explicit release. On any skip or unrecoverable failure below, release the claim first so the issue is immediately reclaimable: gh issue edit <n> --remove-assignee @me.
Stop conditions (report and halt — do not keep looping):
- Run counter reached
MAX_ISSUES (3).
- No eligible issue remains.
implement-issue failed CI unrecoverably, or a guardrail/permission blocked it. (Release the claim before halting.)
Skip (don't halt) conditions — release the claim, comment on the issue explaining why, then move to the next eligible issue:
- The issue genuinely needs HITL (an architectural decision, secrets/credentials, or a design review), or its acceptance criteria cannot be met truthfully without fabrication. Never fabricate results to "complete" an issue — leave it for a human and skip.
- If two issues in a row are skipped, stop and report (the queue likely needs human triage).
Step 4 — Trigger Phase 9 retrospective
After the batch finishes (all issues processed or a stop condition hit), invoke /retrospective. Fire the retrospective even when the batch produced no merged PRs — batches that end with skips, unrecoverable failures, or duplicate-PR collisions often surface the most actionable lessons and should not be silently dropped.
Pass whatever references the batch produced, and briefly describe what happened so the retrospective has context:
- Batch with merged PRs: pass the PR numbers explicitly.
/retrospective <PR#1> <PR#2> ...
- Batch with skips / failures / duplicate collisions: invoke without explicit PR numbers and describe the batch in prose — skipped issue numbers, failed or duplicate PR numbers, and why they were skipped. The retrospective defaults to the window since the last run, which covers this session's git and CI activity, and uses your description as context.
/retrospective
# In the invocation, describe: "batch skipped #N (needs HITL), PR #M failed CI (lint error)"
Only omit this step if the batch was a true no-op (nothing was attempted — no issues selected, no branches created, no PRs opened).
The auto-trigger reuses the same /retrospective skill as the manual path — there is no second implementation. Retrospective findings follow the same propose-only guardrail (ADR-0005): the skill writes only under docs/retro/ and never edits CLAUDE.md, a skill, or .claude/settings.json directly.
Step 5 — Report
Summarize the run: issues implemented (with PR links), issues skipped (with reasons), and what remains eligible in the queue.
Guardrails
- Respect all repo guardrails — never
git push --force, git reset --hard, git clean -f, or git branch -D.
- One issue → one PR. Never bundle multiple issues into one PR.
- Honesty over completion: report failures and skips faithfully; do not claim an issue is done unless its PR merged green.