Engineering

How to review a pull request you did not ask for

Editorial · Reveneau · October 11, 2026

How to review a pull request you did not ask for

Open any active repository and look at the pull request list. A growing share of what is there was not requested by anyone.

Dependency version bumps from an update bot. Security patches from a scanning tool. Lint and formatting corrections. Refactors an agent decided were an improvement while working on something adjacent. Suggested fixes from static analysis. They arrive daily, they are usually small, the build is usually green, and they get approved in a few seconds each.

The review habits everybody learned were built for a different situation, and they fail on these in a specific way that is worth naming.

The missing half of a review

Reviewing a human's change is a conversation with one side already written. The diff carries what was done. What is missing, reliably, is why: which approaches were tried and abandoned, what the author knew about the calling code, what they checked before deciding a case could not happen.

So reviewers ask. Why this approach. Did you consider the other thing. What happens when this is null. The question is a request for information that exists, in somebody's head, and can be retrieved.

On an unrequested pull request there is nothing to retrieve. The agent has no retained reasoning. Ask it anyway and you will get a fluent, confident, well-structured answer, reconstructed from the diff in front of it. That answer may be correct. It carries no evidence either way, and it is more dangerous than silence, because it satisfies the reviewer's instinct that a reason was given.

This is the adjustment: the review has to run on evidence inside the change rather than on intent behind it.

Three questions that work without an author

What did this change that I cannot see?

The diff is not the change. This is most obvious on a dependency bump, where the visible edit is one line in a lock file and the actual change is every difference between two versions of somebody else's code.

For a version bump, the artefact to read is the upstream changelog between the two versions, not the diff. You are looking for behavioural changes, deprecations, default value changes, and anything in the "breaking" section that the semantic version number did not warn you about, which happens more often than the convention promises.

For a generated refactor, the invisible part is whether behaviour changed at a boundary. Refactors are defined as behaviour-preserving and generated ones sometimes are not, particularly around null handling, ordering, and error paths that no test exercises.

What does this change claim about the world?

Generated changes constantly encode assumptions about data. This value is never null. This field is unused. This collection is small enough to load at once. This loop runs a handful of times.

Each is a claim about your production system, and your production system is not in the pull request. The reviewer's job on these is to notice the claim and then go and check it against something real: a query, a log, a metric. Not against intuition, because intuition about data distributions is unreliable in exactly the way that produces incidents.

This is the same failure described in why data changes are riskier than code changes, and it shows up wherever generated code meets data nobody measured.

What happens if this is wrong at 3am?

Two properties matter and neither is diff size: blast radius and reversibility.

A change that is small and reversible earns a fast approval, because being wrong costs a rollback. A change that is small and irreversible does not, regardless of how tidy it looks. Dropping a column, altering a permission default, changing a retry policy, modifying something that runs in a scheduled job: all of these can be eleven lines and none of them is cheaply undone.

The reason this question matters most is that approval speed in practice tracks diff size, and diff size is nearly unrelated to consequence. That correlation is the thing to break.

The queue problem

Behind the individual reviews is a volume problem that changes behaviour whether or not anyone decides it should.

A repository generating fifteen automated pull requests a week, each needing a genuine ten minutes of investigation, has created two and a half hours of weekly work that nobody was assigned and nobody scheduled. What happens next is predictable. The queue grows, somebody feels bad about it, and a habit forms of approving anything that looks routine. At that point the review step exists in the process diagram and nowhere else, which is worse than not having it, because it is being counted as a control.

Three things help.

Set a policy per category rather than deciding per pull request. Patch bumps to development-only dependencies behind a suite that would catch a regression: auto-merge is defensible. Anything touching authentication, payments, or data handling: always a human, always the changelog. Major versions: always a human. Write this down so it is a decision made once rather than fifteen times a week under time pressure.

Batch and schedule. Review these in one block on a fixed day rather than reactively as they arrive. Reactive review of low-urgency changes is how the fast-approval habit gets trained.

Name owners. Dependencies, security patches, and generated refactors each get a specific person. Unowned automated changes are reviewed by whoever has a spare moment, which describes no review at all.

What a green build is evidence of

Every one of these arrives with a passing build, and the temptation is to treat that as the answer.

A green build is evidence about exactly the cases the test suite covers, and nothing else. On a dependency bump it proves your tests still pass against the new version, which says nothing about the upstream behaviour your tests never touch. On a refactor it proves the covered paths still work, and refactors go wrong on uncovered paths.

The useful habit, and it takes an afternoon once rather than effort per review, is knowing what your suite actually protects. Break something a check is supposed to catch, on purpose, and confirm the build turns red. A check that cannot fail has been contributing false confidence to every review it appeared in. We made the longer argument in how many tests does AI-generated code need.

Where the actual risk sits

The dangerous unrequested pull request is never the large one. A 600-line generated refactor gets attention automatically, because its size triggers the instinct to slow down.

The one that gets merged is small, green, plausible, and appears among fourteen others exactly like it. It bumps a library that handles session tokens across a minor version where the default expiry changed. It removes a null check that a linter called redundant and that was covering a case the linter could not see. It adjusts a retry count in a job that only runs on the first of the month.

None of those are found by reading harder. They are found by asking what changed outside the diff, what the change assumes about real data, and what being wrong costs, on every change, including the boring ones. Especially the boring ones, since boring is the entire category now.

Sources

Common questions

What is an unrequested pull request?

It is a change opened by automation or an agent rather than assigned to a person: a dependency version bump, a security patch, a lint or formatting fix, a generated refactor, or a suggested improvement from a scanning tool. Nobody wrote a ticket for it, so it arrives with no stated intent and no author who can explain the reasoning behind it.

Why are agent-opened pull requests harder to review?

Because normal review depends on recovering the author's intent, usually by asking. An agent has no retained reasoning to recover, and asking it produces a fluent reconstruction rather than a memory, which sounds like an explanation while carrying no information. The review has to be grounded in evidence inside the change instead.

Should dependency update pull requests be auto-merged?

Patch-level updates to development-only dependencies, behind a test suite that would actually catch a regression, are reasonable candidates. Anything that touches production behaviour, changes a major version, or updates a package involved in authentication, payments, or data handling deserves a human read of the upstream changelog, because the diff shows a version string and hides everything that matters.

How do you review a change when the diff looks trivial?

Read what the diff does not show. For a version bump that means the upstream release notes between the two versions. For a refactor it means whether any behaviour changed at a boundary. For a lint fix it means whether the rule change altered semantics anywhere. The size of the diff is not related to the size of the change.

What is the risk of approving small automated changes quickly?

Approval speed tends to track diff size rather than consequence, and those two come apart badly on automated changes. A one-line dependency bump can pull in thousands of lines of third-party behaviour, and an eleven-line refactor can remove a null check that was load-bearing. The habit of fast-approving small diffs is exactly what makes this category dangerous.

Should you ask an agent why it made a change?

Treat the answer as a hypothesis to check rather than as testimony. A model asked to justify a past change produces a plausible reconstruction from the diff, which may be correct and carries no evidence either way. It is useful as a starting point for your own verification and is not a substitute for it.

How should a team handle a flood of automated pull requests?

Batch them by category and risk, review them on a schedule rather than reactively, and set a policy per category so each one is not an individual decision. The failure mode is an unbounded queue that trains everybody to approve on sight, at which point the review step exists on paper and nowhere else.

What should you check on a generated refactor?

Whether any behaviour changed, particularly at error paths, null handling, ordering, and boundary conditions. Refactors are supposed to preserve behaviour, and a generated one will sometimes improve the code while quietly changing what happens in a case nobody tested. If the test suite passes both before and after, that is evidence only about the cases the suite covers.

Does a green build make an unrequested pull request safe to merge?

Only to the extent the checks can fail. A green build on a dependency bump proves your tests still pass against the new version, which says nothing about the parts of the upstream change your tests never exercise. Knowing what the suite actually protects is what turns a green build into information.

Who should own automated pull requests?

Someone specific, by category, with a named owner for dependencies, for security patches, and for generated refactors. Unowned automated changes accumulate until they are reviewed by whoever has a spare moment, which is a good description of no review at all.