River
Y CombinatorBacked by Y Combinator

Software & TechnicalFree

Pull Request Description and Review Order

River reads the diff against the ticket and writes the review order: what to read now, what to confirm, and what to skip.

Start here

River reads the diff and the linked ticket together, then writes the thing a reviewer actually needs, which is an order. Every changed file gets a position, a verdict of read, confirm or skip, a one-line reason, and a minute estimate. The first block is sized to ten minutes and named as such, so a reviewer with ten minutes knows exactly what those ten minutes bought and what they did not cover. Underneath sits a file-by-file register where the counts reconcile against the diff.

Page one for this query is templates: a heading for what, a heading for why, a checklist with a box for tests. None of them changes what the reviewer sees, which is a file list sorted by path. Litchgate, a freight platform, moved rate quoting onto a queue in one pull request: 137 files, 6,087 changed lines. Six of those files, four percent of the progress bar, carried every decision in the change. Seventy-seven of them, fifty-six percent of the bar, came to 26 lines a person has to read.

Built for the author of a change too big to split, and for the reviewer who has been handed one. Run it before you open the pull request, or after, when the first comment asks what all this is. The user-facing version of the same range is a different artifact and belongs in the release notes. Where the reviewer has no context on the module, the codebase documentation is the better first read, and a design choice worth arguing about belongs in an architecture decision record rather than in a comment thread.

Why the file list is the wrong order

Google's own code review guide tells reviewers to find the files that are the main part of the change and look at those first, and it is honest about the fallback. If the change is too large to work out which parts are the major parts, it says to ask the author what to look at first, or ask them to split it up. That is a question with one right answer and only one person who can give it. The change summary answers it before it is asked.

The tooling actively works against this. GitHub's guidance is to review one file at a time, marking each as viewed so the progress bar in the header tracks how far you have got. It is a good mechanism attached to a bad denominator. At Litchgate, 31 regenerated client files were 23 percent of that bar and none of the review. Nothing in that bar distinguished the migration from a regenerated snapshot. Sorting by path is not a ranking, and it is the only sort there is.

Size is not line count either. The same guide counts the deletion of an entire file as one line of change, because it does not take long to review, and puts a reasonable change at around a hundred lines. Applying that discount to Litchgate's 6,087 changed lines leaves 1,091 a person has to read. Generated output goes to zero, and the review says which files to mark with the attribute that hides them from future diffs. That fixes the next diff as well as this one.

How it works

  1. Send the diff

    The full diff or the branch range, with the file paths intact so paths can be grouped.

  2. Add the ticket

    The linked issue with its acceptance criteria, because half the check runs in that direction.

  3. Say who reviews

    Whether they know this module already, since that changes what has to be explained.

  4. Paste the order

    The description goes in the pull request, and the register goes in the sheet beside it.

What you get

  • A ranked review order with a verdict and a reason against every changed file
  • The ten-minute read named explicitly, with what it covers and what it leaves out
  • Changed lines discounted for generated output, pure moves and the files you deleted whole
  • Every acceptance criterion in the ticket matched to the files that implement it
  • The files answering to nothing in the ticket, listed with what they actually do
  • The riskiest changes ranked, each naming the test that covers it or nothing
  • A file-by-file register whose counts reconcile against the diff you started from

Common questions

Isn't this what the reviewer is supposed to work out?

They will, and it costs them the first fifteen minutes and you the first round of comments. You already know which file the decision is in, because you made it. Writing the order down is a two-minute transfer of something you have and they do not, which is the whole of it. The questions a reviewer does ask, over years, are where a docstring pass puts its comments.

Our pull request is 137 files. Should we just split it?

Usually yes, and sometimes the change genuinely does not decompose: a rename that touches everything, a generated client, a migration with its call sites. The review order is for the second case and it will tell you when you are in the first, because a change that splits cleanly shows up as separate blocks with nothing shared between them.

Why does it need the ticket?

Because half the check runs backwards. Forward, every acceptance criterion should have files behind it, and at Litchgate one of five had none, which nobody noticed until the reviewer was forty comments in. Backwards, every file should answer to a criterion, and thirteen answered to nothing: a logging cleanup, an unrelated fix, and call sites a dependency upgrade forced.

Does the AI summarise the diff?

It reads the diff, which is not the same thing. A summary of 137 files is 137 sentences nobody reads. What comes out is a sequence with a stopping point: six files first, then the fifty-four that need real attention, then forty-six to confirm in a glance, then thirty-one to skip and why.

How does it know what is risky?

Irreversibility first, then blast radius, then whether anything tests it. Litchgate's top row was a migration backfilling 2.1 million rows, which no test covers and a dry-run output does. Third was three retries at four-second backoff, where a slow carrier sees four times the traffic, and that one named no test at all.

What about the description itself?

You get one, written to be read in order rather than filled into headings: what changed and why, the order to read it in, the risky parts with their tests, and the open questions. The file-by-file register goes in a sheet beside it, because a hundred rows in a pull request body is where descriptions go to die.

The change touches the API and the schema.

Then two of the six files a reviewer reads first are those, and the summary says what a caller has to change and what the migration does to existing rows. The published contract needs the same edit, which the API documentation pack carries, and the column meanings belong in the schema register.

Pull Request Description and Review Order

Fill in the form and your workspace opens with the work already underway.