Triage states
Last updated
May be stale
This page was last updated ago, on 5 October 2026. Check what it says against the code before relying on it.
Triage works in the org's exclusive status/ and resolution/ labels
(issue-tracker.md). Because each scope is exclusive, an issue is in
exactly one state at a time, and adding a new status/ label replaces the old one.
| State | Meaning |
|---|---|
status/new |
Filed; nobody has evaluated it yet |
status/needs-info |
Waiting on the reporter |
status/awaiting-review |
Evaluated, and now waiting on a staff or maintainer decision before it can be triaged, such as sign-off on a suggestion. Every type/spec sits here: the decision it waits on is the breakdown, which /to-tickets makes. So does every type/stub, and every type/suggestion that passes triage: the decision each waits on is the grilling, which /grill-to-spec runs |
status/triaged |
Ready to pick up (see below) |
Closed, with a resolution/ label |
Won't be actioned (see Closing) |
Transitions: status/new → status/awaiting-review (when a decision is needed) → status/triaged.
Any state can move to status/needs-info, and it returns to status/new once the reporter
replies, so the issue resurfaces for triage.
GitHub's review-required label, which stood in for status/new before the migration, did not
come across.
The triaged state
An issue is status/triaged when it carries exactly one type/ label, status/triaged, and
everything its type needs below.
| Type | Priority | Effort | Also needs |
|---|---|---|---|
bug |
required | required | The claim verified: reproduced, or the faulty code path found. A brief: expected against actual behaviour, and acceptance criteria that prove the fix |
task |
required | required | A brief, or a body that works as one: what to build and how to tell it is done. Blockers wired as native dependencies, and Part of #<parent> when it has one |
epic |
required | none | A ## Tickets checklist of its children, each opening Part of #<epic>. No brief of its own: its children carry them |
initiative |
required | none | A body that states the goal, and a ## Tickets checklist of its epics and tasks, each opening Part of #<initiative>. No brief of its own |
research |
required | required | The question, and what an answer has to cover |
wayfinder |
required | none | The map, as /wayfinder leaves it |
discussion, feedback, pull-request |
none | none | Nothing further |
A type/spec never reaches status/triaged. It has the problem and the decisions but no
acceptance criteria, so it is not a brief; /to-tickets turns it into issues that are. Nor does a
type/stub, which has less still: an idea and its open questions. It carries a priority and no
effort, and /grill-to-spec rewrites it in place as a spec.
Migrated issues were backfilled as triaged from their labels alone, before the brief requirement existed. They stay triaged; add the brief when one is picked up.
Triage's terminal move is: set the type, set priority and effort as far as the type needs them,
post the brief where the type needs one, then add status/triaged.
Some issues are born triaged rather than passing through status/new. /to-tickets creates its
tickets and its epic at status/triaged, and an initiative, which is set up by hand as planning,
starts there too. A spec does not: whether it came from /to-spec or /grill-to-spec, it is born
status/awaiting-review, and becomes triaged only once /to-tickets has broken it down. A stub is
born status/awaiting-review as well, and keeps that status when /grill-to-spec re-types it as a
spec.
A type/suggestion never reaches status/triaged either. One that passes triage's checks (the
feature rules, the codebase for an existing implementation,
.out-of-scope/ for a prior rejection, and the pillars
for the one it serves) gets a priority and a condensed brief, and moves to status/awaiting-review
for /grill-to-spec, which re-types it as a spec in place. It takes no effort: the spec's breakdown
sizes the work. Suggestions triaged
with a full brief before this rule stay status/triaged, and /wave grills them all the same.
Finding each bucket
.claude/skills/triage/scripts/buckets.sh
prints every bucket, oldest first, and dates a migrated issue by its original GitHub filing rather
than the migration. It wraps the queries in
the gitea-issues skill, so it never uses
tea issues list --labels, which silently ignores org labels.
/triage bucket |
buckets.sh argument |
What it selects |
|---|---|---|
| Unlabeled, never triaged | unlabelled |
Open issues with no status/ label |
| New | new |
status/new |
| Needs info, with reporter activity | needs-info |
status/needs-info issues the reporter has commented on since the label was applied |
| Waiting on the maintainer | awaiting-review |
status/awaiting-review. Show it when the maintainer asks what needs their attention |
| Specs waiting for a breakdown | specs |
type/spec. These are for /to-tickets, not /triage: don't write a brief for one |
| Ready to pick up | triaged |
Unassigned status/triaged issues with no open blocker and no state/blocked, other than epics, initiatives and wayfinders, highest priority first. Prints the first 20, since blockers cost a call per issue |
With no argument it prints the first three; all prints all five.
Two sources feed the unlabeled bucket:
- Blank issues.
.gitea/ISSUE_TEMPLATE/config.ymlleaves blank issues enabled, and a blank issue carries no labels. - The website's feedback sync. Some player bug reports arrive with only the repo
buglabel. Leave that label where the sync put it, and add thetype/label at triage.
Issues filed by renovate-bot are left out of the bucket. Its Dependency Dashboard is a standing
report, not a ticket, and carries no labels on purpose
(dependencies.md).
Migrated issues. The issues migrated from GitHub were backfilled from GitHub's own type,
priority and effort data. An open one that had everything its type needs is status/triaged; the
rest are status/new and sit in the triage queue like any other new issue.
Closing
Close reasons are resolution/ labels, applied before closing. See
issue-tracker.md. A closed issue with no resolution/ label
counts as completed. Always comment the reasoning before closing, and apply the label before the
close: the feedback sync shows players the status it implies, and a late label notifies the post's
author a second time.