Skip to main content
Version: main

Issue triage

Triage turns a newly filed issue into prioritized, ready-for-work (or correctly closed) state. The process exists so priority reflects a repeatable rubric, not gut feeling:

  • Every issue gets a priority label during triage.
  • Status labels track workflow state; priority labels track importance.
  • Milestone membership is a priority signal, not a duplicate taxonomy.

Contributors mostly need the label taxonomy — it's what you see on issues. Maintainers follow the full workflow.

Issue lifecycle

Label taxonomy

Priority labels (scoring rubric)

LabelScoreDescription
priority: urgent6Blocks a release or active work
priority: high5Should be picked up soon
priority: medium4Worth doing, no rush
priority: low2-3Nice to have, no urgency

Status labels (workflow state)

LabelMeaning
status: newNewly filed, not yet triaged
status: reviewedTriaged, ready for work
status: in progressActively being worked on (auto set when a PR is linked)
status: blockedBlocked on another issue, decision, or external dependency
status: duplicateAlready exists
status: invalidDoesn't seem right
status: wontfixWon't be worked on

Type labels

LabelWhen to use
type: bugSomething is broken or behaving unexpectedly
type: featureNew capability or enhancement
type: refactorCode quality improvement, no behavior change
type: documentationDocs, README, comments
type: devopsCI/CD, workflows, scripts, tooling
type: epicLarge body of work tracked via linked stories
type: testTest infrastructure or coverage improvements

Module labels

Auto applied to PRs based on changed files. For issues, select from the "Affected Module / API" dropdown in the issue template.

Priority scoring rubric

Score = Impact + Risk-of-delay, giving a 2–6 range.

Impact (1–3)

How many consumers are affected, and how badly?

ScoreDescription
1Cosmetic, docs-only, or affects an edge case / rarely-used module
2Affects a commonly-used module (tableapi, core, credentials) or degrades DX without breaking correctness
3Silent-failure / incorrect-behavior risk, a breaking change forced onto consumers, or blocks a milestone

Risk-of-delay (1–3)

What gets worse the longer this sits?

ScoreDescription
1Nothing; can sit indefinitely with no compounding cost
2Accumulates tech debt or blocks a handful of other open issues
3Free now and expensive forever after (breaking changes, naming decisions) or already in a milestone

Score-to-priority mapping

ScorePriorityRationale
6priority: urgentBoth dimensions maxed
5priority: highOne dimension maxed, the other at 2
4priority: mediumBoth dimensions at 2, or a 3+1 split
2-3priority: lowBoth dimensions minimal, or only one mildly elevated

Effort as tie-breaker

Effort (1–3) isn't an input to the score. Use it only to order issues within the same priority tier (cheaper first).

ScoreDescription
1Small, contained to one file/package, no design questions
2Spans a few packages or needs a design decision but not an ADR
3Cross-cutting, ADR-shaped, or touches request-builder/model conventions

Milestone floor rule

If an issue is in a milestone, its priority is floored at high, regardless of the raw score, so milestone work is never buried under non-milestone noise:

  • Milestone issue with score 4 → priority: high (floored up)
  • Milestone issue with score 5 → priority: high (already at tier)
  • Milestone issue with score 6 → priority: urgent (stays at tier)

Triage workflow

Steps

  1. Check the issue is complete. Required fields filled (version, reproduction, expected behavior)? If incomplete: comment requesting the missing info, leave status: new, set no priority yet.
  2. Classify. Set the type: label; set the module: label if the template dropdown didn't already make it clear.
  3. Score. Assess Impact (1–3) and Risk-of-delay (1–3), sum them, apply the milestone floor rule if applicable, set the priority: label.
  4. Set status: status: reviewed when ready for work; status: blocked plus a comment explaining the blocker; or duplicate / invalid / wontfix each with a comment linking the original or explaining why.
  5. Optionally set effort using the Size field on the project board: rubric effort 1 → S, 2 → M, 3 → L.

Re-scoring triggers

Revisit an issue's priority when:

  • New comments change its scope.
  • A PR references it and the actual work differs from the estimate.
  • It's reopened after being closed.
  • A milestone's scope changes.

Planning hierarchy

Large bodies of work are planned through an Epic → Story → Task hierarchy. Each level is a GitHub issue:

  • An epic tracks a large body of work via its linked stories. It carries the type: epic label.
  • A story delivers one slice of user-visible value toward an epic.
  • A task is a single unit of implementable work inside a story.

Templates

Epics, stories, and tasks are maintainer-only planning artifacts. Maintainers file them from the templates in .github/templates/ — one template per level:

TemplateContents
EPIC_TEMPLATE.mdOverview, user personas, success criteria, linked stories
USER_STORY_TEMPLATE.mdAs-a/I-want/so-that statement, acceptance criteria, linked tasks
TASK_TEMPLATE.mdDescription, task type, sub-tasks, deliverables, parent story

You won't find these levels in the public issue chooser. It exposes only two forms: Bug report and Feature request — a feature request becomes a story once planning starts. Blank issues are disabled, and questions go to Discussions, not issues.

Backlog hygiene

A hierarchy is only useful while it reflects reality:

  • Keep status: labels current as work moves — see status labels.
  • Review epics during triage. Close epics whose success criteria are met, and split stale ones into smaller, actionable stories.

Quick reference

Worked examples

Bug in tableapi pagination returns wrong cursor

  • Impact: 3 (commonly-used module, incorrect behavior)
  • Risk-of-delay: 2 (accumulates tech debt, blocks users)
  • Score: 5 → priority: high

Add license headers to Go files

  • Impact: 1 (cosmetic, no behavior change)
  • Risk-of-delay: 1 (can sit indefinitely)
  • Score: 2 → priority: low

Error types should be in errors/ package (in a release milestone)

  • Impact: 2 (affects DX, not correctness)
  • Risk-of-delay: 3 (breaking change, free now, expensive after release)
  • Score: 5 → priority: high
  • Milestone floor: no change (5 ≥ high threshold)

Common mistakes

  1. Don't use Effort as an input to priority. A cheap fix isn't automatically high priority.
  2. Don't force all milestone issues to urgent. Use the floor rule to differentiate.
  3. Don't skip scoring because "it's obviously important." The rubric exists for consistency.
  4. Don't leave issues without a priority label after triage. Every issue needs one.

Where this fits

The conventions reference summarizes these labels alongside everything else reviewers and contributors touch daily. PR-linked status automation (Closes #N moving an issue to status: in progress) is described there too.

Was this page helpful?