# Issue Tracking Guidelines

## Ticket Hierarchy

```
Issue (atomic work unit)
  └─ Epic (capability unit, groups issues)
       └─ Legendary (strategic pillar, groups epics)
```

- One issue = one commit (atomic)
- No skip-level parenting (issue cannot be direct child of Legendary)
- No orphan issues (every issue must belong to at least one Epic)
- Epics: no parent → Legendary; Issues: parent → Epic
- Legendaries: no parent (root nodes)

---

## Issue Quality Criteria (all must be met)

1. **Atomicity**: smallest meaningful unit of work
2. **Single Commit**: one issue = one commit
3. **Single Responsibility**: one concern only
4. **Assignability**: one developer, no synchronization needed
5. **Verifiability**: clear binary verification criterion
6. **Self-Containment**: all context present in issue + parent Epic
7. **Implementation Independence**: ideally no blocking on sibling issues
8. **Subtask Decomposition**: checkbox list (unless trivially simple)
9. **Leaf Node**: no child tickets (promote to Epic if decomposition needed)
10. **Mandatory Parent**: belongs to at least one Epic

---

## Epic Quality Criteria (all must be met)

1. **Demonstrable Outcome**: can show to stakeholder when complete
2. **Thematic Coherence**: all child issues share unified goal
3. **Own Acceptance Criteria**: beyond "all children closed"
4. **Full Decomposability**: can be broken into issues at planning time
5. **Bounded Scope**: clear finite endpoint
6. **Minimum Composition**: at least 2 child issues
7. **Coordination Boundary**: where cross-developer dependencies are managed
8. **Milestone Affinity**: typically aligns with single milestone
9. **Mandatory Parent**: must belong to at least one Legendary
10. **Finite Completion**: closed permanently when done

---

## Legendary Quality Criteria (all must be met)

1. **Strategic Alignment**: major architectural/business pillar
2. **Articulated End State**: concrete verifiable terminal condition
3. **Multi-Milestone Span**: naturally spans multiple milestones
4. **Epic Grouping**: groups Epics by strategic theme
5. **Minimum Composition**: at least 2 child Epics
6. **Relative Independence**: minimal cross-Legendary blocking
7. **Progress Measurability**: measured by Epic completion
8. **Owner Accountability**: project owner level concern
9. **No Parent**: root of hierarchy
10. **Finite Completion**: closed permanently when done

---

## Mandatory Issue Sections

```markdown
## Metadata
- **Commit Message**: `feat(scope): exact commit message`
- **Branch**: `feature/m3-feature-name`

[Background and context]

[Current behavior (bugs: repro steps, errors, logs)]

[Expected behavior]

[Acceptance criteria (testable binary conditions)]

[Supporting information]

## Subtasks
- [ ] Implement input validation
- [ ] Write BDD scenarios (project: Behave)
- [ ] Run task runner full suite, fix any errors (project: `nox`)
- [ ] Verify coverage ≥ 97% via coverage session (project: `nox -s coverage_report`)

## Definition of Done
This issue is complete when:
- All subtasks completed and checked off
- Git commit created with first line matching Commit Message in Metadata
- Commit pushed to branch matching Branch in Metadata
- Pull request submitted, reviewed, and merged
```

---

## Label System

### State/ labels (exactly one always required)

| Label | Meaning |
|-------|---------|
| State/Unverified | Just created, not yet reviewed (initial state for ALL new issues) |
| State/Verified | Maintainer confirmed valid, ready to work |
| State/In progress | Someone actively working on it |
| State/Paused | Work stopped, usually blocked (add Blocked label too) |
| State/In review | PR submitted, awaiting peer review |
| State/Completed | PR merged, all work done |
| State/Wont Do | Won't be addressed (comment explaining reason required) |
| Duplicate | Duplicate issue (link to original, close) |

### Type/ labels (exactly one required)

| Label | Meaning |
|-------|---------|
| Type/Bug | Defect in existing functionality |
| Type/Feature | New capability or user story |
| Type/Task | Technical/admin work (refactor, deps, docs, infra) |
| Type/Testing | TDD issue-capture test or standalone test work |
| Type/Epic | Large body of work composed of multiple issues |
| Type/Legendary | Strategic pillar composed of multiple Epics |

### Priority/ labels (required for non-Epic, non-Legendary)

| Label | Meaning |
|-------|---------|
| Priority/Critical | Immediate; outages, data loss, security vulnerabilities |
| Priority/High | Current or next development cycle |
| Priority/Medium | Valid, not urgent |
| Priority/Low | Nice to have, time-insensitive |
| Priority/Backlog | Default; not yet pulled into sprint |

Note: Bug issues are ALWAYS Priority/Critical

### MoSCoW/ labels (project owner only — contributors must NOT set these)

| Label | Meaning |
|-------|---------|
| MoSCoW/Must Have | Milestone cannot complete without it |
| MoSCoW/Should Have | Important but not blocking milestone |
| MoSCoW/Could Have | Nice to have if time permits |

No "Won't Have" label — use State/Wont Do instead

### Special labels

| Label | Meaning |
|-------|---------|
| Blocked | Cannot proceed (must link blocking issue in comment) |
| Signed-off:Owner | Project owner sign-off on Epic/Legendary |
| Signed-off:scrum master | Scrum master sign-off on Epic/Legendary |
| Signed-off:Tech Lead | Tech lead sign-off on Epic/Legendary |

---

## Linking and Dependencies (CRITICAL)

### Direction rule

- Ticket that must complete FIRST = the BLOCKER
- Ticket that cannot proceed until blocker resolves = the DEPENDENT
- BLOCKER "blocks" DEPENDENT
- DEPENDENT "depends on" BLOCKER

### PR to Issue (most critical case)

- PR → blocks → Issue (PR must complete before issue can close)
- Issue → depends on → PR
- **WRONG DIRECTION**: Issue blocks PR → creates unresolvable deadlock in Forgejo
  (Issue can't close until PR merges; PR can't merge until issue closes)

### Parent-child hierarchy

- Child issue → blocks → parent Epic (child must complete for parent to complete)
- Parent Epic → depends on → child issue
- Set by: open child, add parent under "blocks" (OR open parent, add child under "depends on")
- NEVER reference parent by number in description body text

### Blocked issues

1. Add Blocked label
2. Link to blocking issue in a comment
3. Add Forgejo dependency (blocking issue blocks dependent; dependent depends on blocking)
4. If no ticket for blocker → create one immediately
5. Move blocked issue to State/Paused

---

## Ticket Lifecycle Flow

```
Created → State/Unverified (Priority/Backlog)
         ↓ (maintainer triage)
State/Verified (Priority/Backlog) OR State/Wont Do OR Duplicate
         ↓ (sprint planning: contributor starts work)
State/In progress (Priority updated: Critical/High/Medium/Low)
         ↓ (optional: if blocked)
State/Paused (+ Blocked label)
         ↓ (blocker resolved)
State/In progress
         ↓ (PR submitted)
State/In review
         ↓ (PR merged)
State/Completed → close ticket

At any point: → State/Wont Do (maintainer decision, comment required)
```
