A pull request description is a message to a reviewer who has not seen your work and has fifteen minutes to judge it. An AI assistant writes good ones: it has the whole diff and the whole history in front of it, and it does not get bored writing the testing section. It also writes confidently about things that are no longer true. This post covers drafting commits and a pull request with an assistant, and the check that matters most: does the description match the diff?
Commit messages: the why
On the series' feature, the assistant wrote the code and the engineer wrote the commits, one per plan step, after reading each diff. A commit message records what the diff cannot show. Step 2's message is a fair example:
PIZZA-42 step 2: put a saved card on an order's PaymentIntent
The PO wants the card chosen on the payment step and a declined card
swappable on the same order, so the card cannot be fixed when the
order is created. Instead the existing PaymentIntent is UPDATED with
the user's Stripe customer and the saved card; the browser confirms
it with the clientSecret it already holds and never sees the pm_
token.
The update carries no idempotency key on purpose: a key per (order,
card) would make A -> B -> A replay the first response and leave B on
the intent. Setting the same two fields twice is harmless anyway.
Nothing in it restates the diff. It records the product decision that forced the design and the one choice a future reader is most likely to "fix". The assistant's step summaries supplied most of the material, which is a good reason to ask every step to report its decisions and deviations: they are your commit messages, nearly written.
Drafting the description
With ten commits on the branch, a session that had done all the work was asked to draft the pull request for someone who had not:
Draft the pull request: a title and a description for a reviewer who has NOT
seen this conversation.
- Lead with what changed and why, in a few sentences. Then: how it works, the
decisions a reviewer should check, how it was tested (with real numbers),
what is NOT covered, and the follow-ups.
- Every claim must be true of the diff (git diff main...HEAD). Don't describe
anything that isn't in it.
- Keep it to what a reviewer needs; cut anything that only matters to us.
The draft followed that shape: a short summary, a five-step "how it works", nine decisions worth checking (the missing idempotency key, 404 instead of 403, the 403 for a missing token, a database connection held during the Stripe call), a test table with counts per class, a list of failures the reviewer would see that the branch did not cause, and an honest "not covered" section. It also said what it had cut: "the step-by-step history, the reference to the debugging session file, and the manual Playwright checks from step 5".
It could not save the file. The target folder was outside the session's working directory, so the write was denied, and it said so and printed the draft instead. A small thing, but a summary that says "saved" when it was not is precisely what you are reading for.
Check the description against the diff
This is the step that is easiest to skip and most important not to. Every number and every claim in the description was checked against the branch:
git diff --shortstat main...feature/checkout-saved-cards
# 25 files changed, 1601 insertions(+), 21 deletions(-)
grep -c "@Test" UserPaymentMethodTest.java UserPaymentMethodDAOIntegrationTest.java \
CustomerOrderSavedCardTest.java SavedCardPaymentApiIntegrationTest.java
# 4, 4, 15, 8 -> the 31 new tests the description claims
The file count, the line counts, the test counts and a quoted error message were all right. Two things were not. The description said three report tests fail for reasons unrelated to the branch; by then it was two, because test runs had added recent data. And it gave the early, incomplete explanation of those failures, the one a later debugging session had replaced. Neither is the assistant inventing something: both were true when written. Descriptions go stale as the world moves, and the person opening the pull request is the last chance to notice.
The review round later added three commits, so the counts were updated again before the PR went up. Recheck the numbers after every change to the branch.
A big PR made of small commits
Twenty-five files and sixteen hundred lines is a large pull request, and most of it is tests and documentation. It stays reviewable because it is ten commits that each match one plan step or one review fix, each small enough to read alone. Say so in the description: a reviewer who knows they can read it commit by commit, in plan order, will review it properly instead of scrolling the combined diff. If the commits do not tell a story on their own, that is worth fixing before asking anyone else to read them.
Before it goes public
Pushing to a public repository publishes everything in the branch. Before the push, the diff was scanned for anything that should not be there:
git diff main...feature/checkout-saved-cards \
| grep -nE "sk_(test|live)_[A-Za-z0-9]{10}|pk_(test|live)_|whsec_|AKIA[0-9A-Z]{16}|password\s*="
git diff --name-only main...feature/checkout-saved-cards | grep -iE "\.env|properties|\.log$"
Both came back empty. This app's Stripe keys live in a git-ignored properties file, but an assistant that "helpfully" adds a config value for a test is exactly how keys end up in history. Ten seconds of grep is cheap insurance. Then the branch was pushed and the pull request opened with the checked description, on the account owner's explicit instruction. Pushing is a public, hard-to-undo action, and it was not the assistant's call to make.
One more choice was left to the owner: the drafted description ended with a "Generated with Claude Code" line, and the session pointed out that the project's rule against attribution trailers covered commits, not pull requests. Whether to disclose AI assistance in a PR is a team convention. Decide it once and write it down.
Before you accept
- Does each commit message say why, not what?
- Did you check every number in the description against the branch as it is now?
- Does the description describe anything that is not in the diff, or omit anything that is?
- Is there an honest "not covered" section, and a list of failures the reviewer should expect?
- Did you scan the diff for secrets and stray files before pushing?
- Did a person decide to push and open the pull request?