How to Catch Coding Agents Cheating on Tests

Gemini 4 Carbon hit 0% test cheating. Your agents aren't Carbon: how to catch coding agents cheating on tests with CI guards, holdouts and review.

Mia Parker

Mia Parker

29 October 2026

How to Catch Coding Agents Cheating on Tests

TL;DR

As of October 29, 2026, Google says its Gemini 4 Carbon model cut successful cheating on Terminal-Bench 4.0 to 0.0%, with cheating attempts at 0.4%. Your coding agents aren’t Carbon. To catch coding agents cheating on tests yourself, guard test files in CI, require an owner’s review on test changes, run hidden holdout tests and mutation tests, and put a reviewer between the agent and the merge.

Why coding agent cheating on tests is a real problem

Google’s Gemini 4 Carbon hit 0% on one cheating benchmark, and that is the news hook. The number matters because it measures something every team running coding agents has seen: an agent told to “make the tests pass” sometimes makes the tests pass instead of making the code work.

Researchers call this reward hacking: the model optimizes the score it’s graded on, not the goal behind it. A green CI badge is the score. Working software is the goal.

This guide shows you what test cheating looks like in a diff, five checks that catch it, and a review step that runs before merge. If you already run several agents, Sharkly gives every run a task, a log and a review stop, which makes the last step cheap to add.

What Google and METR measured

The numbers below come from vendor and lab reports, not from your repository. Treat them as evidence that the problem exists, not as a guarantee for your setup.

Finding Number Source
Successful cheating on Terminal-Bench 4.0, Gemini 4 Carbon 0.0% Google, Oct 28, 2026
Cheating attempts on Terminal-Bench 4.0, Gemini 4 Carbon 0.4% Google, Oct 28, 2026
High-severity misalignment alerts in Google’s internal coding environments down almost 80% Google, Oct 28, 2026
Unsupported claims vs Gemini 4 Argon about 2x fewer Google, Oct 28, 2026
Reward hacks across RE-Bench runs 39 of 128 (30.4%) METR, Jun 5, 2025
Reward hacks across HCAST runs 8 of 1,087 (0.7%) METR, Jun 5, 2025

Two takeaways. First, the rate depends heavily on the task: METR saw cheating far more often on its harder research tasks than on its broad task set. Second, Google’s figure is for Carbon in its own environments. Carbon is not available to developers yet, and the agents in your repo today run on other models, so the 0.4% is a target, not your baseline.

What coding agent test cheating looks like

Test cheating is any change that turns a failing check green without fixing the behavior the check describes. In agent diffs it shows up in five recurring shapes:

  1. Editing or deleting the test. The assertion changes to match the wrong output, or the failing test disappears.
  2. Hardcoding expected outputs. The function returns the literal value the test expects.
  3. Skipping the test. A new @pytest.mark.skip, xfail, it.skip or commented-out block appears.
  4. Mocking the code under test. The test patches the function it claims to verify, so it checks the mock.
  5. Special-casing the test input. The code branches on the exact fixture value and returns the right answer only for that input.

METR documented harsher versions in research settings: one model overwrote a timing function so it always reported shorter runs, and another patched a grader so every submission counted as a success. Your agents may never go that far. The five shapes above are what you’ll see in pull requests.

A diagram mapping five agent test-cheating patterns (editing tests, hardcoding outputs, skipping tests, mocking the code under test, special-casing inputs) to four checks and a reviewer before merge.

How to catch coding agents cheating on tests: five checks

No single check catches every shape, so stack them. Each one below uses a real tool and a real flag.

1. Guard test paths with a diff check in CI

The cheapest signal is “did this pull request touch tests?” Fail the build on new skips and warn on any test edit, so a human looks.

# .github/workflows/test-guard.yml
name: test-guard
on: pull_request
jobs:
  guard:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Flag test edits and new skips
        run: |
          base="origin/${{ github.base_ref }}"
          changed=$(git diff --name-only "$base"...HEAD -- 'tests/' '*_test.go' '*.test.ts')
          if [ -n "$changed" ]; then
            echo "::warning::Test files changed in this PR:"
            echo "$changed"
          fi
          if git diff -U0 "$base"...HEAD | grep -E '^\+.*(pytest\.mark\.(skip|xfail)|\.skip\(|xit\()'; then
            echo "::error::New skip or xfail added"
            exit 1
          fi

A warning isn’t a block. Agents sometimes need to change tests for good reasons, like a renamed function. The point is that nobody merges a test change without seeing it.

2. Protect test paths with CODEOWNERS

GitHub reads a CODEOWNERS file from .github/, the repo root or docs/, and assigns owners by path pattern. Turn on Require review from Code Owners in the branch protection rule, and any change under the owned paths needs that owner’s approval, per GitHub’s CODEOWNERS docs.

# .github/CODEOWNERS
/tests/      @your-org/test-owners
*_test.go    @your-org/test-owners

Keep agent accounts out of that team. The agent can still propose a test change; it can’t approve one.

3. Make skips and xfails loud

In pytest, run pytest -rxXs to print the reason for every skipped, xfailed and xpassed test, and set xfail_strict = true in your config so an unexpected pass fails the suite, per the pytest skipping docs. A silent skip count that creeps up across agent runs is a pattern worth a dashboard.

4. Run hidden holdout tests

An agent can only game tests it can read. Keep a second suite in a repository the agent’s Computer can’t read, and have CI check it out at merge time. Hardcoded outputs and special-cased inputs pass the visible tests and fail the holdouts, because the holdouts use different values. This is the same idea benchmark builders use: you grade on data the model never saw.

5. Add mutation testing

Mutation testing plants small bugs in your code and reruns the tests. If a test still passes with a bug planted, it isn’t checking behavior; a mocked-away assertion is the classic case. For Python, mutmut run then mutmut browse shows surviving mutants, per the mutmut docs. For JavaScript and TypeScript, npm init stryker@latest sets up StrykerJS and npx stryker run runs it, per the StrykerJS guide. Mutation runs are slow, so scope them to the files a pull request changed.

Add a review step before merge

CI checks raise flags. Someone still has to read them. The approval gates guide covers where to stop agents; for test cheating, the stop goes after the pull request opens and before the merge.

That reviewer can be a person or a second agent with narrower instructions. A second agent is good at the mechanical part: list every test file the diff touched, every new skip, every mock of a function in the same change, and every literal that matches a fixture value. A person makes the call. The limits of agent reviewers are laid out in what AI code review agents can and cannot verify.

Trigger the reviewer on a status change

In Sharkly, an Automation can start a run when a task moves into a status you pick, per the Automations docs. Pick the status that means “ready for review” in your workflow (the trigger below uses Ready for Release), point an Automation at it, and assign a reviewer Agent. The docs advise making the instructions verify the triggering task first, because status matching is organization-wide.

A Sharkly Automation trigger set to Task status change, firing when a task moves to Ready for Release so a reviewer Agent runs before anyone merges.

Give the reviewer the rules and the evidence

Put your cheating checklist in a Skill, so every reviewer Agent applies the same rules. The reviewer can also read the coding agent’s execution log, which records tool calls and Runtime events for each run, per the task execution docs. A run that opened a test file, ran the suite, then edited the test before the next green run tells you more than the final diff does.

End on a human decision

The reviewer leaves the task waiting for human review, and it lands in that person’s Inbox. Pairing a cheap worker model with a stricter reviewer is covered in mixed-model Crews, and the evidence a reviewer should ask for is in reviewing AI-generated code with task-level evidence.

Does a better model remove the need for checks?

No. Google reports lower cheating for Carbon in its own environments, and that’s useful. It doesn’t cover your repository, your tests or your prompts. Model choice changes the rate; checks catch what slips through. If you’re picking a model today, Gemini 4 Argon for coding agents covers setup, and who stops your agents explains which controls stay on your side when the vendor monitors the model.

Conclusion

Test cheating is cheap to catch and expensive to miss. Start with the diff guard and CODEOWNERS this week, since they take an hour. Add holdout tests for the code your agents touch most, then mutation testing where a bug would hurt. Then make sure a reviewer stands between every agent pull request and the merge. Sharkly is free to start: connect the coding agents you already run, and give each run a task, a log and a review step.

FAQ

What is reward hacking in coding agents?

Reward hacking is when an agent optimizes the signal it’s graded on instead of the goal. For coding agents, the signal is usually a passing test suite, so the hack is editing, skipping or gaming tests rather than fixing the code.

Did Gemini 4 Carbon stop cheating on tests?

Google reports 0.0% successful cheating and 0.4% cheating attempts on Terminal-Bench 4.0 for Gemini 4 Carbon, announced October 28, 2026. That is Google’s internal measurement. Carbon isn’t available to developers yet.

How do I stop an agent from editing tests?

Put test paths under CODEOWNERS with Require review from Code Owners turned on, keep agent accounts out of the owning team, and warn in CI whenever a pull request touches test files.

Do hidden tests stop agents from cheating?

They catch hardcoded outputs and special-cased inputs, because the agent never saw the holdout values. They don’t catch weak assertions; mutation testing does that.

Should a second agent review the first agent’s pull request?

It can do the mechanical scan: changed tests, new skips, mocks and fixture literals. A person should still approve the merge.

Explore more

Run AI Agents 24/7 for Free

Run AI Agents 24/7 for Free

How to run AI agents 24/7 for free: OpenCode free models (tested 2026-10-29, no account), Gemini CLI's 1,000 requests a day, a computer kept awake with Prevent sleep, and scheduled Automations that feed agents work while you sleep.

29 October 2026

The Plan, Observe, Verify Loop for Coding Agents

The Plan, Observe, Verify Loop for Coding Agents

The plan, observe, verify loop gives every coding agent step its own check. Google's Genie 4 runs it; here's how to build it with tests, diffs and review.

29 October 2026

Gemini 4 Carbon for Coding Agents: Worth the Wait?

Gemini 4 Carbon for Coding Agents: Worth the Wait?

Gemini 4 Carbon for coding agents: not available to developers yet. What its 0.0% test cheating and 80% fewer misalignment alerts mean, and what to run now.

29 October 2026