| 1 | # Release queue and PR integration |
| 2 | |
| 3 | Procedure for triaging a crowded release queue. Consult this when you are |
| 4 | actually working the queue; it is not a rule you break by not having memorized |
| 5 | it. |
| 6 | |
| 7 | This guidance is for **live** work — open PRs and branches close enough to |
| 8 | `main` to reconcile honestly. For work that has drifted far enough that the |
| 9 | merge is an excavation, see "Intent is the artifact" in `AGENTS.md`: capture the |
| 10 | intent as an issue, drop the branch, rebuild from current `main`. A useful rule |
| 11 | of thumb — if the conflicts are in the files the branch most wanted to change, |
| 12 | you are reconstructing intent anyway; do it in the editor, not the merge tool. |
| 13 | |
| 14 | ## Working the queue |
| 15 | |
| 16 | Order of attack: release blockers, recently approved PRs, clean PRs with small |
| 17 | scope, blocked PRs with obvious fixes, dirty PRs that can be harvested safely, |
| 18 | then larger architecture issues. |
| 19 | |
| 20 | Start from the current GitHub release milestone named in `docs/ops/CURRENT.md` |
| 21 | and refresh state before acting: |
| 22 | |
| 23 | ```sh |
| 24 | gh issue list --repo Hmbown/CodeWhale --milestone "<current milestone>" --state open |
| 25 | ``` |
| 26 | |
| 27 | Older per-version triage docs under `docs/` are historical reference only. |
| 28 | |
| 29 | ## Scratch integration branches |
| 30 | |
| 31 | - Use scratch integration branches to expose conflicts, missing tests, |
| 32 | duplicate work, and hidden coupling quickly. Name them like |
| 33 | `scratch/vX.Y.Z-pr-train-YYYYMMDD` and create them from the real landing |
| 34 | branch. |
| 35 | - Treat scratch branches as evidence, not as the artifact to ship. Land work by |
| 36 | harvesting the safe resolved hunks or commits back into the release branch in |
| 37 | narrow, reviewable commits — keep tags, releases, and fast-forwards off the |
| 38 | scratch train. |
| 39 | - A PR that is clean against `main` can still conflict with a release branch. |
| 40 | Test against the actual release head before calling it merge-ready. |
| 41 | |
| 42 | ## Merging and harvesting |
| 43 | |
| 44 | - Prefer direct GitHub merge only when the PR is clean against the real landing |
| 45 | branch, has acceptable checks, and does not cross trust-boundary surfaces. |
| 46 | - For already approved PRs, start with a scratch merge against the release |
| 47 | branch, then decide between direct merge, cherry-pick with conflict |
| 48 | resolution, or credited harvest. Maintainer approval is a priority signal, |
| 49 | not permission to skip review or tests. |
| 50 | - Review PRs from code, tests, linked issues, comments, and check results — let |
| 51 | those, rather than the title or labels alone, drive every merge, close, |
| 52 | harvest, or defer decision. |
| 53 | - Close or update issues and PRs only after verifying the landed commit on the |
| 54 | relevant branch. If the release branch already contains equivalent behavior, |
| 55 | leave a clear note linking the commit and describing any remaining delta. |
| 56 | |
| 57 | ## Credit (CI-enforced) |
| 58 | |
| 59 | - When harvesting, preserve or add machine-readable credit: keep the original |
| 60 | author where possible, add `Co-authored-by` using `.github/AUTHOR_MAP` or the |
| 61 | GitHub numeric noreply identity, and include `Harvested from PR #N by @handle` |
| 62 | in the commit body so the auto-close workflow can close the PR with credit |
| 63 | after it reaches `main`. |
| 64 | - Merge a PR whose commit carries that line with **rebase or a merge commit** so |
| 65 | the body survives intact — a squash can rewrite it, drop the |
| 66 | `Harvested from PR` line, and silently lose both the machine-readable credit |
| 67 | and the auto-close. |
| 68 | - Keep `Co-authored-by` trailers to human contributors. |
| 69 | `scripts/check-coauthor-trailers.py` rejects bot/tool ones (Claude, codex, |
| 70 | cursor, `noreply@anthropic.com`) on harvest commits. |
| 71 | - Refresh the manual credit surfaces that do not auto-populate from trailers: |
| 72 | `docs/CONTRIBUTORS.md` and `CHANGELOG.md`. |
| 73 |