Reconcile an open PR's title and body against the current diff, so the body describes what the branch actually ships now — not what it shipped when it was opened. Run when the body has drifted: more commits landed, scope grew or shifted, the title still reads docs: but the PR now ships a feature.
-
Resolve the PR. gh pr view <PR> --json number,title,body,headRefName,baseRefName. Hold the current title and body.
-
Gather the fresh shape. git fetch origin <baseRefName>, then cargo xtask pr body --base origin/<baseRefName> > /tmp/pr-body.fresh.md. Read the change digest on stderr (the rust/docs/capsule/schema categories + file list) — that is what the change is now. Read the fresh skeleton on stdout — its set of ### blocks under ## Verify locally is the selection the current diff requires.
-
Reconcile the Verify-locally blocks. Diff the fresh skeleton's block set against the live body's:
- In the fresh selection but missing from the body → add it (structure from the template, filled for this PR).
- In the body but dropped by the fresh selection → remove it.
- In both → keep the operator's fill verbatim. The Checkout block carries the real PR number; Rust tests carry the scoped filter; User smoke carries PR-specific steps. Never overwrite a kept block with the placeholder.
Done when every ### block under ## Verify locally matches the binary's selection for the current diff, and every kept block retains its authored content.
-
Reconcile the prose. Read gh pr diff <PR> and git log origin/<baseRefName>..HEAD --oneline. For each prose section the body carries (Summary, What ships, Behavior changes, What this addresses, Hard rule, Not included, Migration notes):
- Still matches what shipped → leave untouched. Refresh is anti-churn; do not rewrite what is right.
- Drifted → rewrite to match the current diff. Section no longer earned → drop it. New outcome shipped with no section → add it.
Done when every prose section reflects the current diff, and no section restates the diff file-by-file.
-
Reconcile the title. Does the Conventional Commits subject still describe the shipped scope? If the PR grew — a fix(typo) that now ships a feature, a docs: that now contains code — update type and scope via gh pr edit <PR> --title. Pause for confirmation only if the scope shift is meaningful enough that the operator might not have noticed (.github/AGENTS.md title/description rule).
-
Write the body. Build the reconciled body in a temp file — kept prose, rewritten prose, reconciled blocks — then gh pr edit <PR> --body-file /tmp/pr-body.md. Never --body "..."; the body-construction rule in .github/AGENTS.md mandates --body-file to survive code fences and $.
-
Verify the render. gh pr view <PR> --json body -q .body — confirm no stray \` or \$ from hand-editing. Fix with --body-file if broken.
-
Report. Name what moved: blocks added/dropped, prose sections rewritten, the title change (old → new) and why. Do not ask permission to refresh — the operator asked. Do surface a scope-shifting title change before it sticks if the operator might disagree.