The PR title becomes a commit subject the moment it merges. Write it like a commit, because it is one.Pull requests are the unit of change that lands on
main. The title, the description, and the merge strategy together decide what the changelog says and how easily someone six months from now can answer “why did this happen?”.
Title
- Use the same conventional-commit prefix the squash commit will have.
feat: …,fix: …,chore(scope): …. The squash-merge takes the PR title as the commit subject verbatim; if the prefix is wrong,release-pleasecomputes the wrong version bump. - No emoji. Same rule as commit subjects — machine-parsed surface, no decoration.
- Under 70 characters. Lengthy context belongs in the body, not the subject line that GitHub truncates in the merged-PR list.
- Imperative mood, present tense: “add netflow firewall rule”, not “added” or “adding”.
- Scope is optional, lowercase, in parens when used:
feat(api): rate-limit token refresh.
Body
Three sections, in this order:## Summary— 1–3 bullets covering why this change exists. Not the diff (the reader sees that); the motivation. If the PR closes a Linear issue or GitHub issue, say so here (Closes JAC-50,Fixes #127).## Test plan— bulleted markdown checklist. What CI runs automatically (bun run build,pnpm test,tofu fmt -check), and what a reviewer still has to verify by hand (browser smoke test, manualterragrunt plan, anything CI cannot see). Tick the boxes as work completes.- Optional:
## Security notes— when the change touches credentials, IAM scopes, network exposure, secret-store layout, or anything else where the security review is non-obvious from the diff. Empty section = “I considered it and there is nothing to flag” (different from “I did not think about security”).
Merge strategy
- Squash-merge is the default. One PR = one commit on
main. The PR title becomes the commit subject; the PR description becomes the commit body.release-pleasewalks this linear history to compute version bumps. - No merge commits on
main. The Settings → “Allow merge commits” toggle stays off org-wide. - Rebase-merge is allowed for stacked PRs where each constituent commit is itself a clean conventional-commit and worth preserving separately. Rare. Default to squash.
- No force-push to
main. Force-push to your own feature branch is fine while the PR is open.
Review
- CI must be green before merge. CodeQL alerts must be resolved, not dismissed — see Golden laws.
- A reviewer’s
request changesblocks merge until the author addresses every comment, either with a fix or with a written reply explaining why no fix is needed. Silent dismissal is not acceptable. - The author drives the conversation. If a reviewer goes quiet for > 24h on an open PR, the author pings them in the PR thread or on Slack — the PR stops waiting silently.
Voice in the description and review thread
- Tell hard truths directly. Don’t soften with “perhaps” or “maybe consider”. Disagree explicitly when you disagree.
- ALL CAPS from the requester means refocus immediately. A capitalized correction is the highest-priority signal in the conversation; everything else pauses until that direction is followed.
- Explain complex reasoning. A two-line diff with five lines of justification is fine; an ambiguous diff with no rationale is not.
What this connects to
Commit conventions
The vocabulary the PR title uses. Subject rules, voice, autonomy — all the same.
Branch conventions
Branch type predicts the PR title prefix. One decision, made once.
Git transport
Why private-repo PR pushes go over HTTPS even when public repos use SSH.
CI/CD policy
The release-please flow that consumes the squash-commit subject.