One pass over the repo's open issues per invocation, then stop. Compose with
/loop for recurrence (/loop /process-issues, /loop 1h /process-issues);
/loop owns pacing. Never schedule yourself.
This is the autonomous sibling of the interactive /triage skill: it runs the
same state machine and reuses the triage skill's bundled references (its
AGENT-BRIEF.md template, OUT-OF-SCOPE.md knowledge base, and needs-info
notes template) instead of duplicating them. The difference is that /triage
waits for the maintainer at each step; this pass acts autonomously and parks
anything that needs a human.
State derives entirely from GitHub (labels, comment timestamps), so a tick is
idempotent: an empty queue costs one gh issue list and exits.
Rails
- Never close an issue, never apply
wontfix. Those are the maintainer's call. When this pass believes an issue is wontfix, a duplicate, out of scope, or a "do we even want this" scope question, it does not close it: it leaves a disclaimer-prefixed comment with the reasoning (and any.out-of-scope/match or duplicate link) and parks it inneeds-triagefor the maintainer to confirm-and-close.wontfixis a recommendation, never an action. - Every comment starts with a disclaimer:
> *This was generated by AI during triage.*. - Skip issues owned by another active loop. If another dispatcher already drives an issue (it is in that loop's queue), leave it untouched.
0. Preflight
- Abort if not a git repo, or if there is no GitHub remote. This skill is
GitHub-only (
gh, issues). - Detect optional substrate; use what exists, skip what doesn't:
- Triage labels + wiring (
docs/agents/triage-labels.mdmapping the canonical rolesneeds-triage/needs-info/ready-for-agent/ready-for-human/wontfix, and an issuetype:axis). If absent, offer to run/setup-github-labelsand stop: without state labels the tick can read but cannot record an outcome. .out-of-scope/directory. If present, read it during context-gathering (see thetriageskill'sOUT-OF-SCOPE.md); if absent, skip out-of-scope matching.
- Triage labels + wiring (
States
This pass routes each issue to exactly one canonical state (label strings come
from triage-labels.md). Every triaged issue also carries one category role
(type: bug / type: feature / type: task).
needs-info: underspecified or unreproducible; waiting on the reporter.ready-for-agent: fully specified, behind the strict gate below, with an agent brief. The handoff to an AFK agent (implemented by/implement-issues).ready-for-human: wanted, but a human must implement it (judgment, access, or a design decision).needs-triage: the parking spot for the maintainer. A wontfix / duplicate / out-of-scope / scope-call belief lands here with a comment. This pass never re-picks it.
Tick algorithm
-
Build the queue. Two buckets:
- Open issues with no triage state label (never triaged, this pass's turn).
needs-infoissues where the reporter has replied since the last triage note (re-evaluation needed).
gh issue list --state open --json number,title,labels,author,createdAt,updatedAt \ --jq '[.[] | {number, title, labels: [.labels[].name], author: .author.login, createdAt, updatedAt}]'Skip issues already wearing
ready-for-agent/ready-for-human/wontfix, and do not re-pickneeds-triage(that is the parking spot, not a work queue). -
Process up to ~5 issues this tick, oldest-first, each through the pipeline below, then stop.
/loopdrains a larger backlog over later ticks. -
Report. A short dashboard: each issue processed and the state applied, recommendations parked for the maintainer, anything needing a human call.
/loopreads this to pace the next run.
Per-issue pipeline
-
Gather context in a subagent (keep the main loop context clean): read the issue body, comments, labels, reporter, and dates; parse prior triage notes so resolved questions are not re-asked; read
.out-of-scope/; quick-search open issues for a likely duplicate; explore the codebase. For bugs, attempt reproduction (trace the code, run tests). A confirmed repro makes a far stronger brief; a failed or impossible repro is a strongneeds-infosignal. -
Classify the category →
type: bug/type: feature/type: task. -
Route to a state:
- Out-of-scope match or duplicate of an open issue → comment linking the
prior
.out-of-scope/entry or the original issue, then parkneeds-triage. Never close. - Underspecified / repro failed / missing information →
needs-info, using thetriageskill's needs-info notes template. Capture everything already established so the work is not lost; ask the reporter specific, actionable questions. This is the autonomous substitute for/triage's maintainer-grilling: ask the reporter, do not block on a human. - Passes the strict gate →
ready-for-agentwith an agent brief written per thetriageskill'sAGENT-BRIEF.md. The gate requires all of: one reasonable interpretation, a complete brief with concrete testable acceptance criteria, verifiability by cheap or existing tests, and no product/design decision or human-only access required. - Wanted but a human must build it (judgment, access, design decision) →
ready-for-human, same brief structure, noting why it cannot be delegated. - A "do we even want this" scope call → park
needs-triagewith the reasoning.
When in doubt, escalate. Prefer
ready-for-humanorneeds-triageoverready-for-agent: handing an AFK agent an underspecified brief is the failure mode this gate exists to prevent. - Out-of-scope match or duplicate of an open issue → comment linking the
prior
Composition
Spin-off issues from /process-prs and escalations from /kaizen-codebase
arrive labeled needs-triage and are left for the maintainer, not re-picked
here. Unlabeled external issues remain this pass's intake. An issue this pass
marks ready-for-agent is the handoff to /implement-issues (this pass does not
write code or open PRs itself); the resulting PR is then handled by
/process-prs.