# Pull Request Guidelines

## Terminology

PR and MR are interchangeable. This project is hosted on Forgejo, which uses the term **Pull Request (PR)**.

---

## PR Submission Checklist

All 13 requirements must be satisfied before requesting review:

1. **Detailed description** — summary of what was done and motivation for the change
2. **Closing keyword** — `Closes #N` or `Fixes #N` for each linked issue (one keyword per issue)
3. **Dependency direction** — PR blocks the issue; issue depends on the PR (see [PR Dependency Direction](#pr-dependency-direction-critical) below)
4. **One Epic scope per PR** — PRs that span multiple Epics must be split
5. **Atomic, well-scoped commits** — each commit follows the [commit guidelines](../commits/README.md)
6. **Commit messages reference tickets** — every commit includes `ISSUES CLOSED: #N`
7. **Conventional Changelog format** — all commits use the correct type/scope/description format
8. **Changelog updated** — one entry per commit
9. **No build or install artifacts** in any commit
10. **CONTRIBUTORS.md updated** if this is your first contribution to the project
11. **Version bump** if applicable (see [Versioning](#versioning-clever-semantic-versioning) below)
12. **All automated checks pass** — task runner full suite passes (see [Automated Checks](#automated-checks-required) below)
13. **Correct milestone assigned** and **exactly one `Type/` label applied**

---

## Automated Checks Required

All of the following must pass before a PR can be merged. Commands shown are
Python/nox examples — replace with your ecosystem's task runner equivalent:

| Check                | Example command (Python/nox)  | Requirement          |
|----------------------|-------------------------------|----------------------|
| Unit tests           | `nox -s unit_tests`           | All pass             |
| Integration tests    | `nox -s integration_tests`    | All pass             |
| Linting & formatting | `nox -s lint`                 | Clean                |
| Static type checking | `nox -s typecheck`            | Clean, no suppressions |
| Security scanning    | `nox -s security_scan`        | Clean                |
| Coverage             | `nox -s coverage_report`      | ≥ 97% — blocks merge |

Coverage below 97% **blocks merge**. This is a hard project requirement.

---

## Peer Review Requirements

- **Minimum 1 approving review** required (project-specific rule; C.O.C. baseline is 2)
- **Self-approval is permitted**, including for automated bot PRs
- Approval can be a formal "APPROVED" review or a comment with explicit approval (e.g. LGTM, ✅)
- **No open "Request Changes" or "Rejected" reviews** at merge time — all must be resolved or dismissed
- The **project owner may override** and merge in exceptional circumstances (documented)

### What Reviewers Evaluate

- **Correctness** — satisfies the acceptance criteria of all linked issues
- **Readability** — clear names, easy to follow logic
- **Performance** — no unnecessary inefficiencies introduced
- **Security** — no vulnerabilities or unsafe patterns
- **Style** — follows project coding standards
- **Test coverage** — adequate tests, including edge cases and failure modes

---

## PR Dependency Direction (Critical)

```
PR  →  blocks  →  Issue
Issue  →  depends on  →  PR
```

To configure in Forgejo: open the PR, then add the linked issue under **"blocks"**.

**NEVER set it the other way around.** If the issue blocks the PR, neither can be closed without the other — an unresolvable deadlock.

---

## After Submission

1. Move linked issue(s) to **State/In review**
2. **Watch CI** — fix any failures immediately; do not leave a broken PR waiting
3. **Address all review comments**, then re-request review from each reviewer
4. After merge: move linked issue(s) to **State/Completed**

---

## Merge Requirements Summary

- [ ] PR description is detailed and includes `Closes #N` / `Fixes #N` keywords
- [ ] Dependency direction is correct: PR blocks issue (not the reverse)
- [ ] All CI checks pass
- [ ] Coverage ≥ 97%
- [ ] At least 1 approval; no open "Request Changes" or "Rejected" reviews
- [ ] All commits follow Conventional Changelog format
- [ ] Every commit references the associated issue (`ISSUES CLOSED: #N`)
- [ ] Changelog updated
- [ ] CONTRIBUTORS.md updated (if first contribution)
- [ ] Version number updated (if applicable)
- [ ] Correct milestone assigned
- [ ] Exactly one `Type/` label applied
- [ ] Linked issues are in **State/In review** or **State/Completed**

---

## Versioning (Clever Semantic Versioning)

| Change Type                                      | Version Bump |
|--------------------------------------------------|--------------|
| Incompatible API changes (breaking changes)      | **MAJOR**    |
| Backwards-compatible new functionality           | **MINOR**    |
| Backwards-compatible bug fixes                   | **PATCH**    |
| Refactoring, documentation, tests, unreleased changes | **none** |

Breaking changes must also be marked in the commit message with `!` after the type/scope (e.g. `feat!:`) or a `BREAKING CHANGE:` footer.
