issue-triage · git:20261011.2406fc7 · 2026-10-11 · sha256 497ef1b8d465bd2d
issue-triage git:20261011.2406fc7A
Immutable. This exact content never changes and is served at /api/v1/blob/497ef1b8d465bd2d.
---
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
Story points on the Fibonacci scale: **1, 2, 3, 5, 8, 13, 21**. No intermediate values.
| Label | Duration |
|---|---|
| `effort/1` | < 2 hours — a one-liner, config change, or text correction (1 AC) |
| `effort/2` | 2–4 hours — a small validation, DTO field, or targeted bug fix (2 ACs) |
| `effort/3` | ~1 day — a new use case, new endpoint, or feature with 3–4 ACs |
| `effort/5` | 2 days — a new aggregate, complex business rule, subsystem refactor (4–5 ACs) |
| `effort/8` | 3 days — a large aggregate or cross-cutting change (5–6 ACs). Ceiling of the right-sized 1–3 days band. |
| `effort/13` | > 3 days — a new bounded context or major architectural change (6+ ACs). **Must be split before DISCUSS.** |
| `effort/21` | > 3 days — an epic spanning several subsystems (6+ ACs). **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 = 1, 2 ACs = 2, 3-4 ACs = 3, 4-5 ACs = 5, 5-6 ACs = 8, 6+ ACs = 13 or 21 |
| Number of architecture layers touched | 1 layer = 2 or 3, 2-3 layers = 3 or 5, 4+ layers = 8 or above |
| External dependencies changed | +1 step up the scale per external dependency |
| New concept or aggregate introduced | 5 points minimum |
| Refactoring existing code | Depends on scope — targeted = 2, cross-cutting = 13 or 21 |
### Estimation by Label
| Label | Example tasks in auto-insurance domain |
|---|---|
| `effort/1` | Fix a typo in a validation message, update a config value, add a missing null check |
| `effort/2` | Add a `driverAge` field validation, fix a bug in a single use case, add a DTO property |
| `effort/3` | Implement `CheckEligibilityUseCase`, add a new API endpoint with request/response, fix a multi-step bug |
| `effort/5` | Build the `DriverProfile` aggregate with value objects, refactor the eligibility module, add audit logging across the domain |
| `effort/8` | Extend the driver subsystem end-to-end (domain + API + persistence), migrate a module to a new contract |
| `effort/13` | Introduce a new bounded context (Claims), major architectural change (CQRS migration) |
| `effort/21` | Full subsystem rebuild, multi-context re-platforming |
### Oversize Warning
Any issue estimated **above 8 points** — that is, `effort/13` or `effort/21` — **must be flagged before entering DISCUSS**. Estimates above 8 points are too large to write meaningful ACs for without splitting. The triage report must include a "must split" note for every 13- or 21-point issue.
8 points (3 days) is the ceiling of the right-sized 1–3 days band: anything larger is not an issue, it is a batch of issues.
---
## 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:
1. Lowercase all words
2. Remove stop words: `the`, `a`, `an`, `is`, `in`, `for`, `of`, `to`, `with`, `and`, `or`, `not`, `on`, `at`
3. Remove punctuation
4. Sort remaining words alphabetically
5. 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
```markdown
| # | Title | Type | Priority | Effort | Notes |
|---|---|---|---|---|---|
| 42 | Add eligibility check for young drivers | feature | P1 | 3 | Core feature for v0.2 |
| 43 | Fix validation error on driver age field | bug | P0 | 2 | Blocking form submission — crashes on age < 0 |
| 58 | Driver profile missing secondary driver | feature | P1 | 5 | Required for multi-driver policies |
| 71 | Add pagination to driver list endpoint | feature | P2 | 2 | UX improvement, not blocking |
| 89 | Add tooltip to eligibility form | feature | P3 | 1 | Cosmetic, low priority |
```
### Sprint Proposal Capacity Calculation
Effort-to-days conversion:
- 1 = 0.25 day
- 2 = 0.5 day
- 3 = 0.75 day
- 5 = 1.5 days
- 8 = 3 days
- 13 = excluded (must split)
- 21 = excluded (must split)
Effective capacity = team-days × 0.7 (accounts for meetings, reviews, incidents)
---
## Sprint Proposal Construction
1. **Sort** all triaged issues by priority: P0 first, then P1, then P2, then P3
2. **Apply capacity constraint**: effective capacity = declared team-days × 0.7
3. **Fill greedily**: add issues until effective capacity is reached
4. **Override for P0**: all P0 issues enter the sprint regardless of capacity (mark "over capacity" if needed)
5. **Enforce the above-8 exclusion**: no 13- or 21-point issue enters the sprint — must be split first
6. **Note over-capacity**: if total effort > effective capacity, mark sprint as "over capacity" with explanation
### Sprint Proposal Table
```markdown
| # | Title | Priority | Effort | Days | Justification |
|---|---|---|---|---|---|
| 43 | Fix validation error on driver age field | P0 | 2 | 0.5 | Blocking — must fix |
| 42 | Add eligibility check for young drivers | P1 | 3 | 0.75 | Sprint goal |
| 58 | Driver profile missing secondary driver | P1 | 5 | 1.5 | Sprint goal |
| 71 | Add pagination to driver list endpoint | P2 | 2 | 0.5 | Capacity available |
Total: 3.25 days | Effective capacity: 4.9 days (7 team-days × 0.7)
Status: within capacity
```
---
## References
- [label-taxonomy.md](references/label-taxonomy.md) — full label definitions, color codes, conflict rules
- [priority-criteria.md](references/priority-criteria.md) — P0–P3 decision framework with domain examples
- [triage-template.md](references/triage-template.md) — blank template and filled auto-insurance example