Auto-approve low-risk pull requests
When AI writes and reviews most of the code, waiting for a person to approve every pull request becomes the slowest step. Most PRs are low risk, and a few cause most incidents. This guide sets up a gate that approves the low-risk ones on its own and sends everything else to a human:
A PR whose risk score is below 0.3, that changes nothing on a blocked path, and whose AI review passed is approved and goes to the merge queue. Everything else waits for a reviewer.
The score comes from opendrs, which measures each PR’s blast radius, file history, author experience, size and tests.
1. Score every PR without approving anything
Add .github/workflows/opendrs.yml. It comments a risk report on each PR and sets a
risk:green, risk:yellow or risk:red label. It approves nothing yet.
name: opendrs
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
concurrency:
group: opendrs-$
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
checks: read
jobs:
opendrs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0 # the score reads past commits and authors
- uses: error-path/opendrs@v0
Leave it like this for two to four weeks and compare the scores with what reviewers found and what was reverted.
2. Check the threshold against your own history
npx @error-path/opendrs backtest # how well the default weights rank your past commits
npx @error-path/opendrs calibrate # fit the weights to your repository
npx @error-path/opendrs backtest # compare default and calibrated
The backtest reports what share of bug-introducing commits the score would have flagged at each threshold. Commit the calibrated model through a normal reviewed PR. See Calibration and backtesting for how to read the numbers.
3. Turn on the branch rules approval depends on
- Settings > Actions > General: allow GitHub Actions to create and approve pull requests.
- Settings > General > Pull Requests: allow auto-merge, if you will use it.
- A ruleset on the default branch that requires one approval and dismisses stale approvals on push. opendrs checks for it before every approval and does not approve without it, so a later push can never merge on an earlier approval.
- Require your tests, your AI review and the opendrs job as status checks.
4. Approve, but let people press merge
In .opendrs.yml on the default branch:
autoApprove:
enabled: true
requireAiReview:
checks: [{ name: "claude-review", app: "github-actions" }] # your AI review's check run
mergeMethod: none
sampleRate: 0.2 # one in five eligible PRs still goes to a human
maxChangedLines: 400
Pass a secret as the Action’s sample-salt input, so nobody can predict which PRs get sampled. Any AI reviewer works if it publishes a check run that fails on a blocking
finding: Claude Code, CodeRabbit, Copilot or your own.
5. Merge automatically
Switch mergeMethod to queue (or auto-merge), give the workflow contents: write, and lower
sampleRate, but keep it above zero, so you keep measuring what the gate lets through. To roll
back, set enabled: false on the default branch. On the next run, opendrs withdraws its own
approvals.
What is never auto-approved
Whatever the score:
- changes to CI workflows, CODEOWNERS, migrations, Terraform, build and install scripts, and the opendrs config or model;
- binary files, submodule pointer changes, lockfiles and other ignored files;
- PRs that delete tests or add a line matching a
content.blockpattern; - PRs from forks, drafts, and PRs where a reviewer requested changes;
- PRs where a signal could not be computed and that unknown could have changed the tier.
The full rule order and every option are in the GitHub Action guide.