---
name: process-issues
description: "Run one issue-triage tick on the current repo's open issues, then stop. Scan untriaged issues, classify them (type: bug/feature/task), reproduce bugs, and route each through the canonical triage state machine: needs-info / ready-for-agent (with an agent brief) / ready-for-human, or park a wontfix/duplicate/out-of-scope belief in needs-triage for the maintainer. Does one tick then stops, so it composes with /loop for a recurring issue loop (e.g. `/loop /process-issues`, `/loop 1h /process-issues`). Never closes an issue, never applies wontfix; those stay the maintainer's call. GitHub-only (uses `gh`). The autonomous sibling of the interactive /triage skill. Use when the user wants to triage, classify, or process open issues, prepare issues for AFK agents, or set up a recurring issue-triage agent."
---

# Process issues (one tick)

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 in `needs-triage` for the maintainer to
  confirm-and-close. `wontfix` is 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.md` mapping the
    canonical roles `needs-triage` / `needs-info` / `ready-for-agent` /
    `ready-for-human` / `wontfix`, and an issue `type:` axis). If absent, offer
    to run `/setup-github-labels` and 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 the `triage` skill's `OUT-OF-SCOPE.md`); if absent, skip out-of-scope
    matching.

## 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

1. **Build the queue.** Two buckets:
   - Open issues with **no triage state label** (never triaged, this pass's
     turn).
   - `needs-info` issues where the **reporter has replied since the last triage
     note** (re-evaluation needed).

   ```bash
   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-pick `needs-triage` (that is the parking spot,
   not a work queue).

2. **Process up to ~5 issues this tick, oldest-first**, each through the
   pipeline below, then stop. `/loop` drains a larger backlog over later ticks.

3. **Report.** A short dashboard: each issue processed and the state applied,
   recommendations parked for the maintainer, anything needing a human call.
   `/loop` reads this to pace the next run.

## Per-issue pipeline

1. **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 strong `needs-info` signal.

2. **Classify the category** → `type: bug` / `type: feature` / `type: task`.

3. **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 park
     `needs-triage`. Never close.
   - **Underspecified / repro failed / missing information** → `needs-info`,
     using the `triage` skill'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-agent` with an agent brief written
     per the `triage` skill's `AGENT-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-triage` with the
     reasoning.

   **When in doubt, escalate.** Prefer `ready-for-human` or `needs-triage` over
   `ready-for-agent`: handing an AFK agent an underspecified brief is the
   failure mode this gate exists to prevent.

## Composition

Spin-off issues from `/process-prs` land unlabeled, so this pass picks them up
and triages them on its next tick (escalations from `/kaizen-codebase` arrive
already labeled `needs-triage` and are left for the maintainer, not re-picked
here). 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`.
