Mutation check for pull requests

Can this pull request’s own tests actually fail?

A pull request says it fixes a bug and adds tests. Coretexa puts the source code back the way it was, leaves the new tests exactly where they are, and runs them again. If they still pass, the tests do not touch the thing the pull request changed — and you know that before you merge, not six months later.

runs on your runner — nothing executes on our infrastructure · no runtime dependencies of its own · no telemetry · MIT

real output · ioi-isr/cms #174
[!!] NO_GATE 3 of 5 behavioural changes in this PR can be reverted with all 5 of its tests still passing. run at head PASS — 5 passed run w/ source reverted PASS — 5 passed ← the finding

a live, unmodified verdict — not a mock-up

the same discipline, applied to our own work:
7 fixes merged upstreamgson, buildtools, fastmcp, git-machete, szio, croniter, superfile

01 The problem

Agent-written pull requests arrive green. Green is not evidence.

A passing suite tells you the tests passed. It does not tell you the tests would have failed without the fix — and that is the only property that makes a test a gate.

BEAT 01

The test covers the wrong thing

The new test exercises the tidy helper function the change added, not the one line that wires it into the program. Delete the wiring and the test is still green.

BEAT 02

The suite was quietly weakened

An assertion loosened, a case skipped, a threshold widened. CI goes green because the bar moved, not because the bug went away.

BEAT 03

The author graded the work

The thing that wrote the fix also wrote the test that proves the fix. That is not review — it is a rubber stamp with extra steps.

02 How it works

One experiment, run on every pull request.

There is no model in it, and on a standard project there is nothing to configure. It answers one question by running something, and everything it reports it established by observation.

  1. Split the diff

    Source changes on one side, new and modified tests on the other. Renames, docs, lockfiles and assets are classified and set aside.

  2. Put the source back

    Every behavioural hunk is reverted to the merge base at once. That is two test runs and usually the whole story. Only when the revert fails to compile — common in Go, Rust and Java — does it fall back to reverting each hunk on its own, so the verdict still points at a line rather than a pull request. That second stage is bounded by a time budget you control.

  3. Run the pull request’s own tests

    Unchanged, exactly as the author wrote them. If they fail, the tests genuinely gate the change. If they pass, they never did.

per-hunk localisation
per-hunk localisation (each hunk reverted on its own) GATED config/web/web.go hunk 4 ASSERT_FAIL: 62 passed, 1 failed -> TestGetDefaultConfig UNGATED config/config.go hunk 1 PASS: 63 passed ← nothing noticed UNREACHED web/app/src/App.vue hunk 1 not run — the Go runner cannot observe this file
03 The verdicts

Five answers. It refuses to guess between them.

A finding is only reported when the mapping from test to code was proved, not inferred. When it cannot prove one, it says so instead of picking the interesting answer.

[!!]

NO_GATE

A behavioural change can be reverted with the pull request’s own tests still passing. The tests do not detect the fix.

[ok]

GATE_HOLDS

Reverting the source makes the new tests fail. They really do gate the change. This is the good case, and the common one.

[ok]

GATE_HOLDS_BUILD

The revert does not compile, so the change is load-bearing at build time. Weaker evidence than a failing assertion, and labelled as such.

[--]

NO_NEW_TESTS

There is nothing to run. The pull request changes behaviour and adds no test that could observe it.

[??]

INCONCLUSIVE

The experiment could not be run cleanly. Reported honestly, with the reason, rather than dressed up as a pass.

PythonJavaScript / TypeScriptGoRustJava (experimental)anything else via test-command
04 Quick start

Paste one file. There is no step two.

No account, no API key, no service to sign up for. Coretexa itself is pure Python standard library and pulls in nothing of its own — it detects and installs your project’s declared test dependencies on your runner, because it has to run your tests.

.github/workflows/coretexa-verify.yml
name: coretexa-verify on: pull_request permissions: contents: read jobs: verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # we need the merge base - uses: earfman/coretexa-verify@v1

Read-only. The verdict goes to the job summary, so nothing needs write access — the safest thing to run on a public repo that takes fork pull requests. Want it as a PR comment instead? Add pull-requests: write and pass github-token. Non-blocking by default — it only fails the job if you opt in with fail-on.

05 A real catch

Three rounds of AI review. No test touched the new code.

NO_GATE · reproduced yorukot/superfile #1545 “feat(metadata): cache directory size calculations”

The pull request did two things: it added a directory-size cache, and it added request tracking to keep stale results from being applied to the wrong path. The cache was well tested. The request tracking was not tested at all — and nothing in the review caught it, because a passing suite looks the same either way.

# put the request-tracking hunks back the way they were, keep every new test reverted: model.go L148-155, L162-174 · model_msg.go L172-182 tests: 67 passed, 0 failed grep across *_test.go: no match for IsPending, IsFresh, SetPendingRequest, MatchPendingRequest, ClearPendingRequest NO_GATE — the new tests do not detect the new code

Five new symbols, none of them named in a single test file. Revert all three hunks and the suite is still green, so the change could break in any future edit and nothing would say so.

CodeRabbit had reviewed this pull request three times and posted rounds of design opinions on exactly that code. It never mentioned that the code had no tests. That is the gap this check is for: not whether the code is good, but whether anything would notice if it stopped working.

The contributor added request_tracking_test.go plus integration tests the next day — and while writing them, found and fixed a stale-response bug on the same path that our report had not named. That is the intended shape of this: the check points at an untested change, and the person who wrote it does the rest.

06 What it cannot tell you

The limits, up front.

A tool that claims to catch everything is a tool you cannot trust on anything. This one answers a single narrow question, and these are the questions it does not answer.

Open source

Everything it says, it established by running something.

0
dependencies — pure stdlib
513
unit tests, no network needed
5
languages supported

MIT licensed. Runs entirely on your runner — no telemetry and no analytics, and nothing is sent anywhere. It touches the network only for git and, unless you set install-deps: false, to install your project’s own declared test dependencies. Secrets are stripped from the environment of every subprocess that runs your repository’s code, so a pull request cannot read your workflow token out of a test.

★ Star on GitHub Read the docs

Find out before you merge.

One file in .github/workflows. It is free and MIT, it runs on your own runner — usually two extra test runs per pull request, and Actions is free on public repos — and it tells you the one thing a green check never will.

Get it on the Marketplace See what it caught

early, solo, and MIT — issues and pull requests welcome

Want this run across pull requests you have already merged?
We do that by hand — the check first, a person reading every finding, then a short write-up of the ones worth acting on. Ask →