# Triage

> Automatically triage a newly opened GitHub issue — categorise it, verify the claim, and apply the right category and state so a maintainer or agent can pick it up. Runs unattended in the triage GitHub Action.

- Skill: `flowershow/triage` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add flowershow/triage`
- Raw SKILL.md: https://api.skillmd.com/api/skills/flowershow/triage/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: flowershow (https://skillmd.com/u/flowershow)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/flowershow/triage

---


# Triage

Triage a newly opened issue on the project issue tracker, unattended. This skill runs
inside the triage GitHub Action (triggered by `issues: opened`) — **there is no human
in the loop and no interactive turn.** You act on exactly one issue, decide, apply the
issue type and one state label with `gh`, and write a single comment. You never wait for
or ask a maintainer: if a human is needed, mark the issue appropriately
(`ready-for-human`, `needs-info`, or `needs-triage`) and stop — a maintainer will take
it from there.

**Applying the decision is mandatory and verified.** After this skill runs, the Action
checks that the issue ends up with an issue type set *and* exactly one state label. If
either is missing, the triage job **fails** — so you must run the `gh` commands below,
not just describe your decision in the comment. See [Applying the
decision](#applying-the-decision) for the exact commands.

Your final assistant message **is** the issue comment — the Action posts it as-is. It
**must** start with this exact disclaimer line:

```
> *This was generated by AI during triage.*
```

and contain only the comment — no preamble, no "done" summary, no narration of the
steps you took. Do **not** post it yourself with `gh issue comment` (that duplicates
it). A follow-up step strips any stray text before the disclaimer as a safety net, but
do not rely on that — write it clean.

## Reference docs

- [AGENT-BRIEF.md](AGENT-BRIEF.md) — how to write durable agent briefs
- [OUT-OF-SCOPE.md](OUT-OF-SCOPE.md) — how the `.out-of-scope/` knowledge base works

## Roles

Set the **category** as the GitHub **issue type** (not a label). The org has exactly
these issue types — use one of these names exactly:

- `Bug` — something is broken
- `Feature` — a new feature or improvement
- `Task` — chore/maintenance work that is neither a bug nor a user-facing feature

Apply exactly one **state** label:

- `needs-triage` — a maintainer needs to evaluate (use when genuinely ambiguous)
- `needs-info` — waiting on the reporter for more information
- `ready-for-agent` — fully specified, ready for an AFK agent
- `ready-for-human` — needs human implementation (judgment calls, external access, design decisions, manual testing)
- `wontfix` — will not be actioned (only for obvious, clear-cut cases; see below)

Every issue you triage must end up with exactly one category (issue type) and one state
label. The state names above are the actual label strings used on the tracker.

## Applying the decision

Run these before (or after) writing your comment. The Action verifies the result and
fails the job if the type or state label is missing.

**Issue type** — issue types are *not* labels, so set the type via the REST API (this
works regardless of the runner's `gh` version):

```bash
gh api --method PATCH "repos/$GITHUB_REPOSITORY/issues/<number>" -f type='Bug'
```

Use `Bug`, `Feature`, or `Task` for `type`. The `<number>` is this issue's number.

**State label** — apply exactly one:

```bash
gh issue edit <number> --add-label "ready-for-agent"
```

A freshly opened issue has no state label, so `--add-label` alone is correct. Only on a
manual re-triage of an issue that already carries a *different* state label, remove the
old one in the same command, e.g. `--remove-label "needs-triage"`. Never leave two
state labels on an issue.

## Procedure

1. **Gather context.** Read the full issue (body, comments, labels, author, dates).
   Explore the codebase using the project's domain glossary, respecting ADRs in the
   area. Run two checks: (a) **redundancy** — search for an existing implementation of
   the requested behavior by domain concept (not just the request's wording). (b)
   **prior rejection** — read `.out-of-scope/*.md` and note any that resembles this
   request.

2. **Verify the claim.** For a bug, reproduce it from the reporter's steps where
   cheap. Report what happened: confirmed (with code path), failed to reproduce, or
   insufficient detail (a strong `needs-info` signal). A confirmed verification makes a
   much stronger agent brief.

3. **Decide, apply, and comment.** Pick the category and state, apply them with the
   `gh` commands from [Applying the decision](#applying-the-decision), then write your
   triage comment as your **final assistant message** — the triage action posts that
   message as the single issue comment. Do **not** call `gh issue comment` yourself
   (that duplicates it). Your final message must start with the AI disclaimer and
   contain only the comment — no preamble, no "I've completed triage" summary, no
   restating the steps you took. Pick the safest defensible outcome:

   - **Well-specified and actionable** → `ready-for-agent`; the comment **must**
     contain a `## Agent Brief` section built from the template in
     [AGENT-BRIEF.md](AGENT-BRIEF.md) (Category, Summary, Current behavior, Desired
     behavior, Key interfaces, Acceptance criteria, Out of scope). Describe behavior
     and interfaces — **never cite file paths or line numbers inside the brief**; they
     go stale before an agent picks the issue up. You may cite one code location in a
     separate verification note (step 2) to prove the repro, but the brief itself
     stays behavioral.
   - **Actionable but needs human judgment** → `ready-for-human`; write the same
     `## Agent Brief` structure and note why it can't be delegated.
   - **Underspecified** → `needs-info`; post the Needs-info template with specific,
     answerable questions. This is the terminal action — do not attempt a back-and-forth.
   - **Obviously won't be actioned** → `wontfix`; post your reasoning but **do not
     close the issue** — a maintainer reviews and closes. Only use this for clear-cut
     cases: the behavior already exists in the codebase (point to where it lives), the
     request matches a documented prior rejection in `.out-of-scope/`, or it's plainly
     out of scope / spam. If there's any real doubt, use `needs-triage` instead.
   - **Genuinely ambiguous** → `needs-triage`, and explain what you were unsure about.

## Hard limits

- **Never wait for or ask a human.** Decide from what's in front of you.
- **Always apply the issue type and exactly one state label** with the `gh` commands in
  [Applying the decision](#applying-the-decision). The Action verifies this and fails
  the job if either is missing — describing the decision only in the comment is not
  enough.
- **One comment only, and it is your final assistant message.** Never call
  `gh issue comment` — the action posts your final message as the comment, so posting
  it yourself creates a duplicate. No multi-comment threads, and no chatter wrapped
  around the comment (the whole final message is the comment). The message must start
  with the disclaimer line.
- **Never write repo files.** Do not modify `CONTEXT.md`, ADRs, or `.out-of-scope/`
  from the action — those need a human-reviewed commit/PR. Put recommendations in the
  comment instead.
- **Never close issues.** Closing is always left to a maintainer.

## Needs-info template

```markdown
## Triage Notes

**What we've established so far:**

- point 1
- point 2

**What we still need from you (@reporter):**

- question 1
- question 2
```

Questions must be specific and actionable, not "please provide more info".

