Triage
Manage issues through a structured state machine. Classify, investigate, and route work to the right place.
Arguments: $ARGUMENTS - issue number, issue URL, or blank to triage the oldest needs-triage issue
State Machine
Categories (apply one):
bug— unintended behavior, regression, or crashenhancement— new capability or improvement request
States (apply one):
| State | Meaning |
|---|---|
needs-triage |
Not yet reviewed — default for new issues |
needs-info |
Blocked on more detail from the reporter |
ready-for-agent |
Well-specified enough for an AI agent to implement |
ready-for-human |
Requires human judgment, architecture decision, or context |
wontfix |
Out of scope — will not be addressed |
Behavior
1. Gather Context
# List open issues needing triage (GitHub CLI)
gh issue list --label "needs-triage" --state open --limit 10 2>/dev/null
# Fetch specific issue if number given
gh issue view "$ARGUMENTS" 2>/dev/null
Read the full issue history. Read relevant code before forming an opinion.
2. Reproduce (for bugs)
Before classifying as a bug, attempt to reproduce:
- Find the code path described
- Identify whether this is a real regression or expected behavior
- Check if a test already covers this case
grep -rn "relevant function or error message" . \
--include="*.ts" --include="*.py" --include="*.js" \
-l 2>/dev/null | grep -v node_modules | head -10
3. Recommend Category + State
Output:
Issue #42: "Login fails when email has uppercase letters"
Category: bug
Recommended state: ready-for-agent
Reasoning: Reproduced. Email comparison uses strict equality instead of
case-insensitive match. One-line fix in src/auth/validator.ts:47.
No architectural decisions required.
For needs-info, specify exactly what information is missing:
State: needs-info
Missing: steps to reproduce, browser/OS version, whether this is
regression (worked before) or has never worked
4. Apply Labels + Comment
# Apply labels via GitHub CLI
gh issue edit "$ISSUE_NUMBER" --add-label "bug,ready-for-agent" \
--remove-label "needs-triage"
# Add triage comment
gh issue comment "$ISSUE_NUMBER" --body "$(cat <<'EOF'
> *This was generated by AI during triage.*
**Category**: bug
**State**: ready-for-agent
Reproduced: email comparison at `src/auth/validator.ts:47` uses `===` instead of `.toLowerCase()` comparison.
Next step: fix comparison to be case-insensitive. Existing test at `src/auth/validator.test.ts` can be extended with an uppercase email case.
EOF
)"
Every AI-generated comment must begin with the disclaimer:
> *This was generated by AI during triage.*
5. Out-of-Scope Tracking
When state is wontfix, document the rejection:
mkdir -p .out-of-scope
# Create rejection record
cat > ".out-of-scope/$(date +%Y-%m-%d)-issue-$ISSUE_NUMBER.md" << EOF
# Issue #$ISSUE_NUMBER — [Title]
**Date**: $(date +%Y-%m-%d)
**Request**: [summary of what was asked]
**Reason rejected**: [why it's out of scope]
**Prior requests**: [link any related issues]
EOF
This prevents the same request being filed repeatedly and documents the reasoning.
6. Bulk Triage Mode
When no argument is given, process needs-triage issues oldest-first:
gh issue list --label "needs-triage" --state open \
--json number,title,createdAt --jq 'sort_by(.createdAt) | .[0]'
Triage one issue, then ask: "Triage next?"
Examples
/triage 42
/triage https://github.com/owner/repo/issues/42
/triage ← oldest needs-triage issue
Token Optimization
Expected range: 400–1,500 tokens (single issue), 200–400 tokens (bulk, per issue)
Grep-before-Read: Finds relevant code paths via grep before reading full files for reproduction.
Early exit: If issue is already fully labeled (has category + terminal state), reports current state without re-triaging.
Patterns used: Grep-before-Read, early exit, Bash for system queries (gh CLI)