Risk-Weighted Merge Gates: From All Checks Green to Blast Radius
A decision matrix for sizing merge checks by ownership, service boundaries, shared contracts, reversibility, and change scope, with a worked example you can recalculate.
It is Tuesday afternoon. Two pull requests sit in your queue, both green. The first corrects a typo in a README. The second adds an optional field to a shared event payload, updates two consuming services, and ships a database migration. Same checks, same approval requirement, same merge button.
Risk-weighted merge gates fix that. Instead of applying one uniform check set to every change, you score the change on five inputs you can read from the diff and repository metadata (ownership clarity, service boundary crossing, shared contract surface, reversibility, and change scope), map the score to a tier, and attach controls to the tier. Routine changes merge with deterministic checks only. Changes that can break other teams get Code Owner review, a named human approver, and a recorded rationale.
I have watched flat gates fail in both directions. They tax the harmless majority with ceremony nobody reads, and they under-protect the small tail of changes that actually cause incidents. Now that a large share of pull requests arrive from coding agents, that tail arrives faster and the ceremony gets bypassed. The gate has to be sized to what breaks if the change is wrong, and to who can undo it.
The Green Checkmark That Told You Nothing
A uniform gate optimizes for the median change. That is the wrong target. The median change is a copy edit, a log line, a test fixture. The changes that wake people up are schema defaults, auth claim shapes, feature flag initial values, and retry policies.
When agents open pull requests, volume stops being the exception. A flat gate then has two outcomes, both bad. Either the required human approval becomes the bottleneck for the entire repository, or someone gets bypass permission "temporarily" and it becomes permanent.
Define blast radius in operational terms before you design any policy. I use four questions: how many consumers see the behavior change, whether persistent data is mutated, how long the reversibility window is, and whether a named team owns every touched path. If you cannot answer the fourth question, that is itself a finding.
Five Inputs That Actually Predict Damage
Ownership clarity. Does a CODEOWNERS path pattern map every touched file to a team? CODEOWNERS assigns ownership by path pattern, and when it is combined with a required review rule, the owning team's approval becomes a merge precondition instead of a notification [4]. Unowned paths are the highest-risk condition in most repositories, because nobody is accountable for the review and nobody is accountable for the rollback.
Service boundary crossing. A diff contained inside one deployable has a rollback you control. A diff that changes behavior other services call has a rollback that depends on someone else's deploy schedule.
Shared contract surface. Public API schemas, event payloads, database migrations, feature flag defaults, and auth token claims. These are the places where a one-line change has a wide reach.
Reversibility. Can this be undone with a revert commit, or does it need a data backfill, a coordinated client release, or a vendor support ticket? This is the input teams score most generously and regret most often.
Change scope. Files touched, handwritten versus generated code, and whether the diff includes CI workflow definitions or the committed agent instruction files your coding tools read on every task [1]. A change to repository instructions changes how future agent work behaves, which makes it policy, not code.
Turning Five Inputs Into One Tier
Score each input 0, 1, or 2 from the diff, then double the shared contract and reversibility scores. Those two inputs predict damage better than raw file count. A 400-file mechanical rename is usually safer than a one-line change to a column default.
| Input | Low (0) | Medium (1) | High (2) | Read this in the diff |
|---|---|---|---|---|
| Ownership clarity | All paths owned by one team | Co-owned or multi-team paths | Any unowned path | CODEOWNERS match for every file |
| Service boundary | Single deployable | Two deployables | Three or more, or shared library | Directory and package ownership |
| Shared contract (×2) | No contract files | Internal interface only | Schema, event, migration, auth claim, flag default | API specs, migration dirs, flag config |
| Reversibility (×2) | Revert commit is sufficient | Revert plus config change | Backfill, client release, or vendor action | Migration type, data writes, client SDK pins |
| Change scope (×2 only if CI or instructions) | Single file, handwritten | Multi-file or generated code | CI workflows or agent instruction files | .github/workflows, AGENTS.md, instruction files |
Maximum score is 14. Map it to four tiers: Routine (0 to 2), Standard (3 to 5), Elevated (6 to 9), Restricted (10 to 14). Treat those boundaries as editable numbers owned by a named person, not constants.
Publish the thresholds. A developer who can predict the tier before opening the pull request will split the migration out of the feature change to stay in Standard, which is exactly the behavior you want. Score from the diff and repository metadata, never from an author self-declaration, or every change becomes Routine by assertion.
What Each Tier Should Require at Merge
Keep the deterministic checks mandatory at every tier, including Routine: dependency scanning, secret scanning, static analysis, and passing tests, independent of who or what authored the change. NIST's secure software development practices give you the control vocabulary to map these to [6], and the generative AI community profile extends that vocabulary to development where models produce code [5].
Then layer the human controls by tier:
- Routine: pull request required, deterministic checks pass, one approval from any maintainer, self-approval blocked.
- Standard: add required review from Code Owners for every touched path and dismissal of stale approvals on new pushes [3].
- Elevated: add a named human approver on the owning team, a recorded rationale for the contract change, and verified build provenance before deploy.
- Restricted: add a second human approver, security review for authentication, authorization, cryptography, or deserialization surfaces, and a staged rollout with a documented rollback owner.
Close self-approval and self-merge on protected paths regardless of whether the author is a person or an automation account. An agent account with write access and no approval requirement is a gate that exists only in documentation.
Keep the required status check set small and reliable [3]. Flaky mandatory checks are the single most effective way to train your team to ask for bypass, and once bypass is normal the tier model is decoration.
A Worked Example You Can Recalculate
An agent opens a pull request that adds an optional field to a shared order event payload, updates two consuming services to read it, and includes an additive nullable column migration. Nine files, all handwritten, no CI changes.
Score it:
- Ownership clarity: every touched path matches a CODEOWNERS entry. 0
- Service boundary: three deployables. 2
- Shared contract: event payload plus migration. 2 × 2 = 4
- Reversibility: migration is additive and nullable, but reverting the field requires coordinated consumer deploys. 1 × 2 = 2
- Change scope: multi-file, handwritten, no CI or instruction files. 1
Total: 9. That lands at the top of Elevated. Code Owner review on all three services, a named human approver, recorded rationale, provenance verified at deploy. Note how close it sits to Restricted: if the event schema directory had no owner, ownership clarity moves to 2 and the change crosses into Restricted with a second approver required.
The sibling change in the same hour: a copy fix in one service's error message. Single file, owned, no contract surface, revert commit is sufficient. Total: 0. Routine. Deterministic checks, one approval, merged in minutes.
Recalculate with your own weights. If your rollback path depends on a mobile client release cycle, reversibility deserves a ×3 multiplier, and changes to client-facing contracts will correctly land in Restricted more often.
Encoding the Matrix as Enforced Policy
Express tiers as layered rulesets rather than per-branch settings edited by hand. Rulesets can be defined at repository or organization level, layered, and evaluated together, so a merge requirement written once applies across many repositories [2]. That matters because a tier model maintained by hand in forty repositories is a tier model that drifts.
Use path-scoped rules so the strict tier attaches automatically to the directories that carry contract risk:
# organization ruleset: contract and policy paths
target: branch
conditions:
include: ["~DEFAULT_BRANCH"]
rules:
- pull_request:
required_approving_review_count: 2
require_code_owner_review: true
dismiss_stale_reviews_on_push: true
- required_status_checks:
checks: [unit-tests, secret-scan, dependency-scan, sast]
# paths that inherit the stricter tier
# api/schemas/** events/** db/migrations/**
# .github/workflows/** AGENTS.md .github/*instructions*Run every new ruleset in evaluate mode first and read the insights view before enforcing [2]. You will find in-flight branches that would have been blocked, and you will find paths nobody owns.
This is where a scoring layer sits alongside platform enforcement rather than replacing it. GitHub rulesets enforce the requirement; something has to decide which tier a given pull request belongs to and record why. Guardian merge gates hold the tier decision, the exception record, and the named owner, while the ruleset remains the mechanism that blocks the merge. For review quality, point automated review at the same committed instruction files your agents read [1][11], so comments enforce your stated conventions instead of generic style. Our notes on how context-aware review differs from rule-based linting go into that configuration in more detail.
The Exception Policy Is the Real Control
Restrict bypass to a short named list and treat each use as an exception with a recorded reason [2]. Not a role, not a standing permission for the platform team. If bypass is the fast path, it becomes the only path.
Stream audit log events to your own storage so bypass records and policy changes outlive the default in-product retention window [7]. The question you will eventually be asked is about a commit from eight months ago.
Pair the approval record with build provenance. GitHub Actions artifact attestations produce signed provenance linking a deployed artifact to the workflow and source commit that built it, with a CLI verification path [8], and SLSA gives you concrete level definitions to target instead of a general intention [9]. Record automation identity separately from human identity so the trail shows what was machine-authored and which person approved it. We cover that separation further in building an AI code authorship provenance chain.
Tuning the Thresholds Without Breaking Flow
Track two signals weekly: bypass count by tier, and review wait time for Elevated changes. DORA's change approval guidance treats approval latency as a measurable constraint on delivery performance, which makes wait time a policy metric rather than a team complaint [10].
If Restricted fires on more than a handful of changes a week, one of two things is true: your thresholds are mis-set, or your services share too many contracts. Both are real findings. Do not fix a coupling problem by loosening the gate.
Treat persistent reviewer complaints about a tier as a scoring defect. Change the weights in a reviewed pull request with the reasoning recorded, the same way you would change any other production configuration. Keep change sizes small so both automated and human review stay fast, and name the person who owns threshold changes before you need them.
Frequently Asked Questions
Does this replace branch protection or required status checks?
No. Rulesets and required checks remain the enforcement mechanism [2][3]. Risk weighting decides which requirement set applies to a given change and records why.
Who computes the score?
It should come from the diff plus repository metadata: CODEOWNERS matches, touched path patterns, migration directories, and CI or instruction file changes [1][4]. Author self-declaration defeats the model.
What about agent-opened pull requests specifically?
Same scoring, same tiers. The differences are that self-approval must be closed for automation accounts and that automation identity should be recorded separately from the approving human [7].
How many tiers should we have?
Four is enough for most organizations. Two cannot distinguish a contract change from an incident-prone migration. Six becomes unpredictable, and predictability is the point.
What if a path has no owner?
Score it High on ownership clarity and route it to the strict tier until ownership is assigned. Unowned code with a permissive gate is the combination that produces the longest incidents.
What to Do This Week
Pick your busiest repository and score the last twenty merged pull requests against the five-input matrix. It takes about an hour. You are looking for two things: how many scored Elevated or higher, and how many of those merged with only one approval.
Then do one concrete thing. Write a path-scoped ruleset covering your schema, migration, CI workflow, and agent instruction directories, requiring Code Owner review and the deterministic check set. Run it in evaluate mode and read the insights view before you enforce it [2].
Start tracking one signal: bypass count by tier, reviewed every Monday with a named owner. If you work in a regulated environment, our DevSecOps control guidance maps these gates to the evidence auditors ask for.
Go back to those two Tuesday pull requests. After you do this, the README fix still merges in minutes, and the event payload change gets the owning teams, the recorded rationale, and the rollback owner it always needed. The checkmark finally means something different on each one.
References
[1] GitHub Docs, "Adding repository custom instructions for GitHub Copilot," 2025. https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions
[2] GitHub Docs, "About rulesets," 2025. https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets
[3] GitHub Docs, "Available rules for rulesets," 2025. https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets
[4] GitHub Docs, "About code owners," 2025. https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
[5] NIST, "SP 800-218A: Secure Software Development Practices for Generative AI and Dual-Use Foundation Models," 2024. https://csrc.nist.gov/pubs/sp/800/218/a/final
[6] NIST, "SP 800-218: Secure Software Development Framework (SSDF) Version 1.1," 2022. https://csrc.nist.gov/pubs/sp/800/218/final
[7] GitHub Docs, "Audit log events for your organization," 2025. https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-your-organizations-audit-logs/audit-log-events-for-your-organization
[8] GitHub Docs, "Using artifact attestations to establish provenance for builds," 2025. https://docs.github.com/en/actions/concepts/security/artifact-attestations
[9] SLSA, "Security levels specification v1.0," 2025. https://slsa.dev/spec/v1.0/levels
[10] DORA, "Change approval capability," 2025. https://dora.dev/capabilities/streamlining-change-approval/
[11] AGENTS.md, "Open format for guiding coding agents," 2025. https://agents.md/