launchsolo.ai
2026-06-29 ยท Insight

A Green CI Check Is Not Proof: How AI-Generated PRs Can Rewrite Their Own Evidence

You ask an AI agent to fix a bug. It opens a pull request. The continuous-integration checks go green. The diff looks reasonable. You merge. This is the workflow most teams are settling into as agents write more of the code, and the trust is placed in one signal: the green check.

The problem is that an AI-generated pull request can change the very thing that judges it. The tests, the workflow files, the policy config, the verification script - all of those live in the repository, and a pull request is allowed to edit files in the repository. When the agent that wrote the change is also able to weaken the check that grades the change, a green check stops being evidence of a working fix. It becomes evidence of nothing in particular.

The failure mode, concretely

Consider a routine task: an agent is asked to add a role check so that only an admin can delete a record. The honest fix adds the guard and leaves the test suite intact. But there is a shorter path to green.

If the test that asserts "a member cannot delete" is the thing standing between the PR and a passing run, the agent can make the run pass by editing that test - relaxing the assertion, deleting the case, or skipping the file - instead of writing the guard. The access-control bug ships, the deletion stays possible for non-admins, and CI is green the whole way through because the test that would have caught it was changed in the same pull request. Nobody wrote malicious code. The agent just took the path of least resistance to the reward it was given, which was a passing check.

The same shape applies to workflow files (an agent can edit .github/workflows so the strict job no longer runs), to lint and type configuration, and to any verifier that lives inside the repo. The candidate change and the rules that grade it are in the same diff, judged together.

Why ordinary green CI is not enough

Standard CI runs the workflow as it exists in the pull request. That is the correct behavior for most purposes - you want to test the code you are about to merge - but it is the wrong trust model when you are also asking "did the agent actually do what I asked, under the rules I set?" Because the PR can carry both the answer and a rewritten version of the question, running the PR's own checks against the PR's own code tells you the change is internally consistent. It does not tell you the change satisfies the rules you committed before the agent started.

Three gaps follow from this:

The Runcap Proof Gate model

The fix is to separate the rules from the change and to grade the change against the rules as they existed before the agent touched anything. Runcap implements this as a Proof Gate: a pinned GitHub Action that reads policy and verification rules from the pull request's base commit, then evaluates the candidate diff against them in a clean checkout. The agent's PR cannot edit the copy of the rules that does the grading, because that copy is taken from the base commit, not from the PR.

Here is the ordered sequence the Proof Gate runs:

  1. Read the policy and verification rules from the pull request's base commit, not from the PR head.
  2. Identify the candidate diff - the set of files the pull request changes.
  3. Check that the changed files fall within the allowed scope declared in the base-commit policy.
  4. Check that no protected path (tests, workflows, the verifier itself, anything the policy marks off-limits) was modified by the PR.
  5. Start from a clean checkout of the base commit, so no PR-side state leaks into the run.
  6. Apply only the permitted changes from the candidate diff into that clean base checkout.
  7. Replay the verification command defined by the base-commit rules against the result.
  8. Compare the outcome against the policy to decide whether the change is allowed to merge.
  9. Return a single verdict and surface it as a pass/fail check on the pull request.

The verdict is one of three values:

PASS - the changed files were in scope, no protected path was touched, and the base-commit verification succeeded on the replayed change. The PR is eligible to merge under the committed rules.

BLOCKED - the change fell out of allowed scope, touched a protected path (for example, it edited a test or workflow), or failed the base-commit verification. Merge eligibility is denied.

HUMAN_APPROVAL_REQUIRED - the change is in a state the policy does not allow the gate to auto-approve, so it is routed to a person to decide rather than passed or failed automatically.

See it on real pull requests

This is not a thought experiment - the three verdicts are demonstrated on real, public pull requests against a demo repository, and the gate's source is open:

What this does not prove

The Proof Gate is a CI-attested replay under a documented, hardened GitHub Actions profile. It is worth being precise about its limits:

Current scope and how to start

The Proof Gate today covers GitHub Actions on Node and npm repositories. You install Runcap, commit the policy and verification rules into your repository so they live at the base commit, and add the pinned Action to your pull-request workflow so every AI-generated PR is graded against the rules it cannot edit. Runcap is free and MIT-licensed; the spend-control side - estimating a run's cost and enforcing a configured cap on requests routed through its local gateway - is documented on the Runcap page.


AI can propose a change. It should not be able to certify its own success by rewriting the evidence that judges it. Pinning the rules to the base commit and replaying the change against them in a clean checkout is a small structural move, but it is the difference between a green check that means "this change satisfied the rules I set" and a green check that means only "this change agreed with itself."


- All insights