Skip to content

triage

triage

standalonewriteshands-off

Use this when: an incoming issue needs a readiness status + area

Problem it solves — An incoming issue with no readiness state or area can't be picked up by an agent. This drives an issue through the triage state machine — readiness Status, Area, category type — so it lands in the right hands ready to work.

Used in workflows: Idea → shipped

Triage

Move an issue through a small readiness state machine and classify it — so the backlog says, for every issue, what it is and how ready it is to be worked.

Task class: classify (a meta action; standalone single-word skill, like vet). Tools: gh (issues + Projects v2), Read/Grep/codegraph for context. Runs in-thread. Artifact: an issue carrying one Status, one Area label, one category Issue Type — plus a recommendation comment / agent brief.

The three axes

  • Status (readiness) — a Projects v2 Status field: Needs Triage → Needs Info → Ready for Agent → Ready for Human → In Progress → Done (+ Wontfix).
  • Area — a label: App, Harness, or App + Harness (set via the labels API; formerly the org Area Issue Field — see docs/agents/triage-labels.md).
  • Category — native Issue Type Bug / Feature.

Every triaged issue carries exactly one of each — and a Bug may carry a fourth: a severity label (sev:high / sev:low; absence = normal, deliberately two values) that orders the exterminate sweep and sets its escalate/auto-merge bar. The canonical vocabulary lives in docs/agents/triage-labels.md. If state signals conflict, flag it and ask first.

Bug intake. A bug filed from the issue template carries a repro stub (What happened / Steps / Expected / Actual / Surface). Read it as the repro source; an unfilled or unusable stub → Needs Info with a comment naming the specific missing fact — never guess a repro. Remember the placement convention: a top-level Bug is correctly placed (no Epic/Sprint parent required).

Setting Status (the board exists — org Project v2 "Tempo"). Apply it, don't just recommend. Locally gh writes it; in the web/remote env (no gh, and the GitHub MCP has no Projects-v2 tool) use the GraphQL updateProjectV2ItemFieldValue mutation authenticated with $GH_TOKEN — board / field / option IDs in docs/learnings/2026-06-06-projects-v2-status-via-graphql.md. No board at all? set Type + area, report the Status recommendation, never invent one.

Split when it's really a sprint

If an issue's body covers several distinct pieces of work, it isn't a Task — it's a Sprint. Recommend splitting its parts into Task sub-issues and typing the parent Sprint (the split runs on confirm, like any triage write; the mechanical creation mirrors to-issues). A childless "Sprint" is just a Task; a Task that's secretly a checklist of many things is a Sprint waiting to be split.

This is the skill — recommend, then apply on confirm

Triage never auto-advances an issue. Gather context, recommend Status / area / category with reasoning, and wait. Apply only what the maintainer confirms. (Surface-then-confirm — state changes, comments and closes are writes.)

Show what needs attention

Query and present three buckets, oldest first: untriaged (no Status/type) · Needs Triage · Needs Info with reporter activity since the last notes. Show counts + a one-line summary each; let the maintainer pick.

Triage one issue

  1. Gather context. Read the issue (body, comments, dates) and any prior triage notes (don't re-ask resolved questions). Explore the code via codegraph, using the domain glossary and respecting ADRs. Read .out-of-scope/*.md and surface any prior rejection that matches.
  2. Recommend, then vet — recommend Status + area + category (short codebase summary), then run vet (inline: worth + placement; blind-review only if consequential/uncertain — mostly Harness-area). vet flags → set Status Needs Info and stop so the maintainer reviews the feedback; vet passes → proceed. Wait.
  3. Reproduce (bugs only) before grilling — trace the code, run the covering test. A confirmed repro makes a stronger brief; insufficient detail is a strong Needs Info signal.
  4. Grill (if needed) via grill-with-docs.
  5. Apply on confirm:
    • Ready for Agent — post an agent brief (the shared convention: docs/agents/agent-brief.md). If the issue is consequential/architectural, flag "needs check-reasoning at build" in the brief so build-sprint's PLAN red-teams it.
    • Ready for Human — same shape, noting why it can't be delegated (judgment, external access, manual testing — e.g. an issue like "run manual testing").
    • Needs Info — post triage notes (template below).
    • Wontfix (Feature) — record in .out-of-scope/ (OUT-OF-SCOPE.md), link it, then close. Wontfix (Bug) — polite explanation, then close.

Quick override

"Move #42 to Ready for Agent" → confirm what you'll do (Status, comment, close), then apply. Skip grilling; offer to write the agent brief.

Needs-info template

markdown
## Triage Notes

**Established so far:**
-

**Still need from you (@reporter):**
- … (specific and actionable — never "please provide more info")

Capture everything resolved during grilling under "established" so it isn't lost.

Resuming

If prior triage notes exist, read them, check whether the reporter has answered, and present an updated picture before continuing. Don't re-ask resolved questions.

At scale — Workflow (when appropriate)

For a backlog sweep (many issues), you may fan out via the Workflow tool — read-only triage-gather sub-agents (one per issue, isolated context), each returning a recommendation; the main thread batches them for confirm + applies, keeping context clean. A vet blind-review can ride the same fan-out. A handful of issues just run inline.

Where it sits

Called by to-issues (classify on creation) and organise (readiness as it places); also standalone. NOT to-issues (creates issues) / organise (places them in the backlog). Attribution is via the acting GitHub account — no "generated by AI" disclaimer needed.