| name | issue-triage |
| description | Use when triaging GitHub issues by assigning labels, priority, effort estimates, or detecting duplicates. Covers triage methodology, label taxonomy, priority frameworks, effort sizing, and sprint proposal construction. |
Issue Triage
Overview
Triage assigns structured metadata to issues so DISCUSS can refine them in priority order. Every triaged issue must have a type, priority, and effort estimate before it is eligible for DISCUSS.
Core principle: triage is classification, not refinement. You are not writing acceptance criteria here — you are labeling, prioritizing, and estimating to enable the next phase.
Label Taxonomy
All GitHub issues passing through DISCOVER must receive labels from the following taxonomy.
Type Labels
| Label | When to Apply |
|---|
type/feature | New user-facing capability that does not currently exist |
type/bug | Behavior that is incorrect relative to expected behavior |
type/tech-debt | Internal quality improvement — no change in user-facing behavior |
type/docs | Documentation — README, API docs, in-code comments |
type/question | Needs clarification before it can be triaged properly |
Priority Labels
| Label | Definition |
|---|
priority/P0 | Blocking users or a legal/compliance/data-loss risk. Must be addressed immediately. Requires written justification. |
priority/P1 | High business value. Should be in the next sprint. |
priority/P2 | Medium value. Target the next 2–3 sprints. |
priority/P3 | Nice-to-have. Not in the current roadmap. Backlog item. |
Effort Labels
| Label | Duration |
|---|
effort/XS | < 2 hours — a one-liner, config change, or text correction |
effort/S | 2–4 hours — a small validation, DTO field, or targeted bug fix |
effort/M | ~1 day — a new use case, new endpoint, or feature with 2–3 ACs |
effort/L | 2–3 days — a new aggregate, complex business rule, subsystem refactor |
effort/XL | > 3 days — a new bounded context or major architectural change. Must be split before DISCUSS. |
Status Labels
| Label | Meaning |
|---|
status/needs-triage | Newly created, not yet classified |
status/ready | Triaged — has type, priority, and effort. Ready for DISCUSS. |
status/duplicate | Confirmed duplicate of another issue. Original linked in comment. |
status/wontfix | Explicitly out of scope. Decision documented. |
Area Labels (Optional)
| Label | Coverage |
|---|
area/domain | Domain logic — entities, value objects, domain services |
area/api | API layer — controllers, DTOs, request/response contracts |
area/infra | Infrastructure — persistence, external integrations |
area/ui | Frontend / client-facing surfaces |
Priority Framework (P0–P3)
P0 — Critical
Definition: The system is broken in a way that blocks users from completing a core flow, or there is a legal, compliance, or data-loss risk.
Qualifying criteria:
- A user cannot complete their primary job-to-be-done (e.g., cannot submit an insurance application)
- Data loss or data corruption is occurring or imminent
- Legal or regulatory compliance is violated (e.g., GDPR, IFRS, provincial insurance regulations)
- Security vulnerability that exposes user data
Auto-insurance examples:
- Driver age validation is throwing an unhandled exception → application submission blocked → P0
- Eligibility calculation overcharging a protected category due to a bug → P0 (compliance)
- User session tokens not expiring → P0 (security)
Disqualifying criteria (NOT P0):
- Feature is missing but users can work around it
- Performance degradation (unless causing timeouts that block submission)
- A P1 feature is incomplete
Mandatory: Every P0 label must include a written justification in the "Notes" field:
"P0: Driver age validation crashes — blocks all application submissions (reported by 3 users, 2026-05-14)"
P1 — High Value
Definition: High business value. Should be in the next sprint. Does not block today's users but is on the critical path for the next release.
Qualifying criteria:
- Core feature required for the next milestone or sprint goal
- Bug that significantly degrades user experience without fully blocking them
- Required for a near-term compliance deadline (> 1 week away)
Auto-insurance examples:
- Add eligibility check for young drivers (core flow, next sprint goal)
- Fix incorrect premium calculation for multi-vehicle policies (wrong output, not crash)
- Implement secondary driver support (needed for v0.2 milestone)
Disqualifying criteria:
- The feature has no defined delivery target
- "Would be nice" but not on the product roadmap
P2 — Medium Value
Definition: Meaningful improvement, but not urgent. Target the next 2–3 sprints.
Qualifying criteria:
- Enhances an existing feature without it being broken
- Performance improvement that is noticeable but not blocking
- Developer experience improvement
Auto-insurance examples:
- Add eligibility reason codes to the API response (enhancement)
- Improve error messages in the eligibility check (UX improvement)
- Add pagination to the driver list endpoint (performance improvement)
P3 — Nice-to-Have
Definition: Low business value or unclear ROI. Not in the current product roadmap.
Qualifying criteria:
- Cosmetic, aesthetic, or minor convenience
- Feature requested once with no validation
- Already has an acceptable workaround
Auto-insurance examples:
- Add tooltips to the eligibility form
- Support dark mode in the customer portal
- Add CSV export of audit logs
Disqualifying criteria:
- Do NOT use P3 for things that are genuinely not worth doing — use
status/wontfix instead
Priority Decision Tree
Q1: Is a user completely blocked from completing a core flow right now?
YES → P0
Q2: Is there a legal, compliance, or data-loss risk?
YES → P0
Q3: Is this in the sprint goal or next milestone?
YES → P1
Q4: Is this a significant UX improvement or important enhancement?
YES → P2
Default → P3
Effort Estimation Heuristics
Signals That Affect Estimation
| Signal | Implication |
|---|
| Number of acceptance criteria (ACs) | 1 AC = XS/S, 2-3 ACs = M, 4+ ACs = L or XL |
| Number of architecture layers touched | 1 layer = S/M, 2-3 layers = M/L, 4+ layers = L/XL |
| External dependencies changed | +1 size level per external dependency |
| New concept or aggregate introduced | +L minimum |
| Refactoring existing code | Depends on scope — targeted = S, cross-cutting = XL |
Estimation by Label
| Label | Example tasks in auto-insurance domain |
|---|
effort/XS | Fix a typo in a validation message, update a config value, add a missing null check |
effort/S | Add a driverAge field validation, fix a bug in a single use case, add a DTO property |
effort/M | Implement CheckEligibilityUseCase, add a new API endpoint with request/response, fix a multi-step bug |
effort/L | Build the DriverProfile aggregate with value objects, refactor the eligibility module, add audit logging across the domain |
effort/XL | Introduce a new bounded context (Claims), major architectural change (CQRS migration), full subsystem rebuild |
XL Warning
Any issue estimated as effort/XL must be flagged before entering DISCUSS. XL issues are too large to write meaningful ACs for without splitting. The triage report must include a "must split" note for every XL issue.
Duplicate Detection
Similarity Levels
| Level | Title Similarity | Action |
|---|
| EXACT | > 95% | Mark the newer issue as status/duplicate. Add comment linking to the original. |
| NEAR | 80–95% | Recommend merge. Add related-to:#{original} comment on both. Flag in triage report. |
| RELATED | 40–80% | Note as related. No merge. Add in the "Duplicates" section of the triage report. |
| DIFFERENT | < 40% | Separate issues. No action needed. |
Normalization for Comparison
Before comparing titles:
- Lowercase all words
- Remove stop words:
the, a, an, is, in, for, of, to, with, and, or, not, on, at
- Remove punctuation
- Sort remaining words alphabetically
- Compare using word overlap ratio:
|intersection| / |union|
Example:
- Issue A: "Fix validation error on driver age field"
- Issue B: "Driver age field validation fails"
- Normalized A:
[age, driver, error, field, fix, validation]
- Normalized B:
[age, driver, fail, field, validation]
- Overlap:
{age, driver, field, validation} = 4 words
- Union: 7 words
- Similarity: 4/7 = 57% → RELATED
When in Doubt
Link rather than merge. Merging issues loses context. If similarity is ambiguous (50–70%), add a related-to comment and flag in the report — let the team decide.
Triage Output Format
Issue Triage Table
| # | Title | Type | Priority | Effort | Notes |
|---|---|---|---|---|---|
| 42 | Add eligibility check for young drivers | feature | P1 | M | Core feature for v0.2 |
| 43 | Fix validation error on driver age field | bug | P0 | S | Blocking form submission — crashes on age < 0 |
| 58 | Driver profile missing secondary driver | feature | P1 | L | Required for multi-driver policies |
| 71 | Add pagination to driver list endpoint | feature | P2 | S | UX improvement, not blocking |
| 89 | Add tooltip to eligibility form | feature | P3 | XS | Cosmetic, low priority |
Sprint Proposal Capacity Calculation
Effort-to-days conversion:
- XS = 0.25 day
- S = 0.5 day
- M = 1 day
- L = 2.5 days
- XL = excluded (must split)
Effective capacity = team-days × 0.7 (accounts for meetings, reviews, incidents)
Sprint Proposal Construction
- Sort all triaged issues by priority: P0 first, then P1, then P2, then P3
- Apply capacity constraint: effective capacity = declared team-days × 0.7
- Fill greedily: add issues until effective capacity is reached
- Override for P0: all P0 issues enter the sprint regardless of capacity (mark "over capacity" if needed)
- Enforce XL exclusion: no XL issue enters the sprint — must be split first
- Note over-capacity: if total effort > effective capacity, mark sprint as "over capacity" with explanation
Sprint Proposal Table
| # | Title | Priority | Effort | Days | Justification |
|---|---|---|---|---|---|
| 43 | Fix validation error on driver age field | P0 | S | 0.5 | Blocking — must fix |
| 42 | Add eligibility check for young drivers | P1 | M | 1.0 | Sprint goal |
| 58 | Driver profile missing secondary driver | P1 | L | 2.5 | Sprint goal |
| 71 | Add pagination to driver list endpoint | P2 | S | 0.5 | Capacity available |
Total: 4.5 days | Effective capacity: 5.0 days (7 team-days × 0.7)
Status: within capacity
References