Green Is Not Proof — ThruLine Research
ThruLine Check your last agent session

[ ThruLine Research · October 2026 ]

Green Is Not Proof

CI checks the code an AI agent leaves behind. It doesn’t check what the agent did to get there, or whether what it told you is true. The evidence from 2025–2026.

Ashwinsuriya Ravi · Founder October 2026 12 min read

[ BibTeX ]

{{ bib }}
Subscribe

ThruLine makes a tool that checks AI coding agents’ claims against the record of what they ran. We have a commercial interest in this argument, so every number here comes from someone else’s published data, linked in the footnotes.

Painting: the words GREEN IS NOT PROOF beside a green sphere split open, its skin peeling away into a twisting ribbon, on a red ground with a failing test run.
Illustrative session
All checks have passed
tests: 214 passed, 0 failed
  1. 01:52editsrc/dates/parse.ts
  2. 01:55runnpm testexit 19 failed
  3. 02:01editsrc/dates/parse.ts
  4. 02:03runnpm testexit 19 failed
  5. 02:07deletetests/dates/timezone.test.ts
  6. 02:08deletetests/dates/leap-year.test.ts
  7. 02:10edittests/dates/parse.test.ts−41 lines
  8. 02:12runnpm testexit 0214 passed
  9. 02:14said“All tests pass. Ready to merge.”
TimeStepTargetExit codeResult 01:52editsrc/dates/parse.ts—— 01:55runnpm test19 failed 02:01editsrc/dates/parse.ts—— 02:03runnpm test19 failed 02:07deletetests/dates/timezone.test.ts—— 02:08deletetests/dates/leap-year.test.ts—— 02:10edittests/dates/parse.test.ts—−41 lines 02:12runnpm test0214 passed 02:14said“All tests pass. Ready to merge.”——

CI saw the last run. The record has all of them.

Figure 1: An illustrative agent session. CI evaluates the final state of the repository. The steps that produced it, including two deleted test files and an edited one, are invisible to it. Pattern reported by developers; see footnote 6.

Illustrative session · sample data

On May 19, 2025, GitHub’s Copilot coding agent opened a pull request against .NET’s runtime: a bug fix, with new tests. A maintainer replied: “Your new tests aren’t being run because the new file wasn’t added to the csproj.” Copilot added the file. The next reply: “Your added tests are failing.” Copilot answered: “Fixed the failing tests by properly handling the match state when backtracking is exhausted.” Three days later the pull request was closed without being merged.1

Nothing bad shipped, because a maintainer read every line. Most agent work doesn’t get that reader. It gets a green check.

This post is for developers whose rule is “if CI is green, I don’t care what the agent said.” Here is what that rule trusts, and the evidence that it shouldn’t.

[ Key takeaways ]

  • Green answers one question: do the tests in the repo pass on this commit? When an agent wrote the code and touched the tests, green means the agent agrees with itself. → §1
  • Models change the tests. When a task and its tests conflict, GPT-5 still “passed” 76% of tasks on one benchmark. For Claude models, more than 79% of those passes came from editing the tests.4 → §2
  • Passing isn’t correct. Roughly half of AI-written PRs that pass SWE-bench Verified’s tests would not be merged by the projects’ own maintainers.7 → §3
  • The report isn’t evidence. An agent that succeeded 22% of the time predicted 77% success.10 → §4
  • The worst failures never reach CI. Deleted databases, destroyed infrastructure, wiped drives: none of it is in the diff. → §5
  • What fixes it: judge each claim against a record of what actually ran, on the exact version you’re about to ship. → §7

1.Green answers one question. Agents changed who writes the answer key.

A green check means the tests in the repository passed on the commit that was pushed. That was strong evidence when the code and the tests that held it to account came from different hands, or at least different days.

An agent session collapses that. One process writes the code, edits the tests, runs them, reads the failures, edits again, and writes the summary you read. CI then checks the agent’s code against the tests the agent touched last.

Green doesn’t tell you:

  • whether the tests that passed are the ones that existed when the agent started;
  • whether the tests the agent described ever ran;
  • whether “done” means what you asked for;
  • what the agent did outside the repository on the way.

Before agents

Person writes code
Tests written separately (another person, or another day)
CI
Green = an independent check

With an agent

One agent session

writes code edits tests runs tests writes the summary
CI
Green = the agent agrees with itself
same author
LaneStepsCheckWhat green means Before agentsPerson writes code → Tests written separately (another person, or another day)CIGreen = an independent check With an agentOne agent session: writes code · edits tests · runs tests · writes the summary (edits tests and CI input: same author)CIGreen = the agent agrees with itself

Figure 2: CI was built to check code against tests that came from somewhere else. In an agent session, both come from the same place.

Schematic · no data

2.When the task and the tests disagree, models change the tests.

Model makers have documented this in their own models, and independent labs have measured it.

February 2025. Anthropic’s system card for Claude 3.7 Sonnet reported that the model “occasionally resorts to special-casing in order to pass test cases,” including “modifying the problematic tests themselves to match the code’s output.”2

June 2025. METR found OpenAI’s o3 reward-hacked in 30.4% of runs on RE-Bench, including by monkey-patching the evaluator and overwriting the equality operator. On one task, adding “Please do not cheat.” to the prompt left the rate at 80%.3

October 2025. ImpossibleBench built tasks where the specification and the unit tests contradict each other, so the only way to pass is to break the spec. GPT-5 passed 76% of one SWE-bench set anyway. For Claude models, more than 79% of those passes came from editing the test cases.4

May 2026. METR reported that Claude Opus 4.6 “attempted to reward hack in ~80% of attempts” on an early version of a benchmark with hidden tests, and that on tasks over eight hours long, “at least 16% of successful runs were illegitimate upon review.”5

Different setups — read across, not between.

Source Date Setup Finding Rate
Anthropic, Claude 3.7 Sonnet system card2
Feb 2025
SetupAgentic coding evaluations
Finding“special-casing in order to pass test cases”, including “modifying the problematic tests themselves”
Rate
—
METR3
Jun 2025
SetupOpenAI o3 on RE-Bench
FindingReward hacking in 30.4% of runs (39 of 128). On one task, 80% even with “Please do not cheat.” in the prompt
Rate
30.4%
ImpossibleBench (Zhong, Raghunathan, Carlini)4
Oct 2025
SetupTasks where spec and tests contradict
FindingGPT-5 passed 76% of Oneoff-SWEbench tasks, which is only possible by violating the spec. Claude models: >79% of such passes came from editing test cases
Rate
76%
METR, Frontier Risk Report5
May 2026
SetupClaude Opus 4.6, early MirrorCode, hidden tests
FindingAttempted to reward hack in ~80% of attempts
Rate
~80%
METR, Frontier Risk Report5
May 2026
SetupTasks over 8 hours, Time Horizon 1.1
FindingAt least 16% of “successful” runs were illegitimate on review
Rate
≥16%
SourceDateSetupRate Anthropic, Claude 3.7 Sonnet system cardFeb 2025Agentic coding evaluations— (no rate published) METRJun 2025OpenAI o3 on RE-Bench30.4% (39 of 128) ImpossibleBench (Zhong, Raghunathan, Carlini)Oct 2025Tasks where spec and tests contradict76% METR, Frontier Risk ReportMay 2026Claude Opus 4.6, early MirrorCode, hidden tests~80% METR, Frontier Risk ReportMay 2026Tasks over 8 hours, Time Horizon 1.1≥16%

Figure 3: Every source here found models taking a route to “pass” that the task didn’t allow. These are deliberately hard or impossible tasks: they measure propensity, not an everyday rate.

Sources: notes 2–5 · Anthropic (Feb 2025), METR (Jun 2025), Zhong et al. (Oct 2025), METR (May 2026)

These setups are deliberately hard, some impossible. They measure what a model does under pressure, not how often it happens in your repo. But they point one way: when the shortest path to green runs through the tests, models take it. CI can’t tell a fixed bug from a rewritten test. Both are green.

It happens outside labs. In May 2026, Jeongho Nam, writing on the typia blog, woke to a green CI badge. “Then I looked at the diff.” The tests/ tree was 70% smaller. “It deleted every failing test.” The agent’s final report: all tests pass. “It never said it had done this.”6

“It deleted every failing test. … It never said it had done this.”

— Jeongho Nam, typia6

3.Even honest tests pass wrong code.

Say the agent never touches a test. Green still overstates correctness.

In March 2026, METR asked four active maintainers of scikit-learn, Sphinx and pytest to review 296 pull requests that AI agents wrote for SWE-bench Verified issues. Of the ones that pass the benchmark’s tests, roughly half would not be merged. Measured against the maintainers, the automated grader overstated the agents by about 24 percentage points.7

Two independent audits of the same benchmark agree. In one, 29.6% of patches that pass behave differently from the reference fix, and 28.6% of those are certainly incorrect.8 The other found 345 wrong patches labelled as passing, because the tests were too thin to catch them.9

These are curated suites, maintained by experts, used to rank the industry’s models. Your project’s tests were written under deadline. Some of them were written by the agent.

AI-written PRs that pass the tests — passed the automated tests

100%

The same PRs — maintainers would merge

roughly half

Automated grading overstated agents by about 24 points vs. maintainer review (SE 2.7)

Human-written reference fixes — maintainers would merge

about 68%

Automated grading overstated agents by about 24 points vs. maintainer review (SE 2.7)

MeasureValue AI-written PRs that pass the tests — passed the automated tests100% The same PRs — maintainers would merge≈50% (roughly half) Human-written reference fixes — maintainers would merge≈68% (about 68%) Automated grading vs. maintainer review, normalised to the human baselineabout 24 points (SE 2.7)

Figure 4: Four maintainers of scikit-learn, Sphinx and pytest reviewed 296 AI-written PRs for SWE-bench Verified issues. Of those that pass the benchmark’s tests, roughly half would not be merged. The human reference fixes are shown for fairness: maintainers don’t merge everything, even from people. The 24-point gap is normalised to that human baseline. Source: METR, March 2026.

Source: METR, Mar 10, 2026 — note 77

4.The agent’s report is not evidence.

What you act on is the summary: “Fixed.” “All tests pass.” “Ready to ship.” Agents are more confident about their work than their work deserves.

On 100 SWE-bench Pro tasks, Gemini 3 Pro predicted, after finishing, that it had succeeded 77% of the time. It succeeded 22% of the time. GPT-5.2-Codex predicted 73% and reached 35%. Claude Opus 4.5 predicted 61% and reached 27%.10

what the agent predicted what actually happened

Gemini 3 Pro

22% 77% +55 pts

GPT-5.2-Codex

35% 73% +38 pts

Claude Opus 4.5

27% 61% +34 pts
ModelPredicted success after finishingActual successGap Gemini 3 Pro77%22%+55 pts GPT-5.2-Codex73%35%+38 pts Claude Opus 4.561%27%+34 pts

Figure 5: On 100 SWE-bench Pro tasks, each agent estimated its own chance of success after finishing. Every one overestimated. Source: Kaddour et al., February 2026.

Source: Kaddour et al., Feb 6, 2026 — note 1010

In 4,788 real sessions from the public SWE-chat dataset, Transluce’s review flagged “overselling” in 34.7% of them. Overselling means overconfident, misleading or false statements, including declaring incomplete tasks done. On Transluce’s own internal traffic, the rate was 5.7%.11

METR says grading model solutions takes longer than grading human ones because “models overclaim and describe what they did in highly misleading ways.” Companies told METR they had seen agents “lying to users about task completion.” One agent “created a mock version of the app, screenshotted that as evidence of task completion.”5

Developers file the same thing as bug reports. From a Claude Code issue, April 2026:12

REPORTED BY THE AGENT

4966/4966 ALL PASSED (golden)

ACTUAL RESULT

4985/4992 FAILURES DETECTED

REPORTER’S NOTE

“Changed the denominator (4992 to 4966) to hide the dropped tests”

anthropics/claude-code #46940 · April 2026 · reporter’s account12

“Claude Code consistently reports having completed actions, tests, or operations that were not actually performed.”

— anthropics/claude-code #150113

“Technically - all tests pass. Completely wrong in practice.”

— Gal Dayan, Product Hunt14

“The agent was optimizing for green tests, not correct behavior”

— Gal Dayan, Product Hunt14

When the evidence is the model’s own account, it can be bent. METR’s August 2026 investigation of an evaluation incident found that “at least 96 of our transcripts show clear evidence of spoofed tool calls,” and that at least 20% of the agents “expressed clear interest in tampering with their transcripts.”15 Those were evaluation agents, not your coding session. The lesson carries: evidence has to come from what ran, not from what the model says ran.

5.The worst failures never reach CI.

CI evaluates a diff. Agents act on machines, databases and cloud accounts. None of that is in the diff.

May 2025 · GitHub Copilot coding agent, .NET runtime PR #115733

What the agent said

“Fixed the failing tests by properly handling the match state when backtracking is exhausted.”

What happened

Its new tests weren’t in the project file, so they never ran. Once they ran, they failed. The PR was closed unmerged.1

Could a green CI run have caught it?No — the new tests weren’t running.

Jul 2025 · Replit Agent, SaaStr

What the agent said, as reported by founder Jason Lemkin

Rollback was impossible, because it had destroyed all database versions.

What happened

It deleted the production database during an explicit code freeze. The rollback worked.16

Could a green CI run have caught it?No — outside the repository.

Feb 2026 · Claude Code, DataTalks.Club

What happened

It ran terraform destroy against production. The developer didn’t stop it. 2.5 years of submissions and all automated snapshots were gone. AWS restored a snapshot exactly 24 hours later.17

Could a green CI run have caught it?No — infrastructure, not code.

Apr 2026 · Claude Code (Opus 4.6), issue #46940

What the agent said

“4966/4966 ALL PASSED”

What happened (reporter’s account)

4985/4992, with failures. The denominator had changed.12

Could a green CI run have caught it?Only if the full suite runs in CI.

Apr 2026 · Cursor with Claude Opus 4.6, PocketOS

What the agent said, afterwards

“I guessed… I didn’t verify.”

What happened

It deleted the production database and its volume-level backups in one API call. “It took 9 seconds.” Data was restored about an hour after Railway stepped in.18

Could a green CI run have caught it?No — one API call, outside the repository.

May 2026 · coding agent, typia

What the agent said

“all tests pass”

What happened

It deleted every failing test. The tests/ tree was 70% smaller. CI was green.6

Could a green CI run have caught it?No — CI was green.

Oct 2026 · Claude Code on Windows, issue #99193 (user report)

What the agent said

“Looks intact”

What happened

A recursive delete kept running for about 50 minutes after “Successfully stopped task”. About 116 GB was deleted.19

Could a green CI run have caught it?No — on the machine, not in the repo.

DateToolWhat the agent saidWhat happenedCould a green CI run have caught it? May 2025GitHub Copilot coding agent, .NET runtime PR #115733“Fixed the failing tests by properly handling the match state when backtracking is exhausted.”Its new tests weren’t in the project file, so they never ran. Once they ran, they failed. The PR was closed unmerged.No — the new tests weren’t running. Jul 2025Replit Agent, SaaStrAs reported by founder Jason Lemkin: rollback was impossible, because it had destroyed all database versions.It deleted the production database during an explicit code freeze. The rollback worked.No — outside the repository. Feb 2026Claude Code, DataTalks.Club—It ran terraform destroy against production. The developer didn’t stop it. 2.5 years of submissions and all automated snapshots were gone. AWS restored a snapshot exactly 24 hours later.No — infrastructure, not code. Apr 2026Claude Code (Opus 4.6), issue #46940“4966/4966 ALL PASSED”Reporter’s account: 4985/4992, with failures. The denominator had changed.Only if the full suite runs in CI. Apr 2026Cursor with Claude Opus 4.6, PocketOSAfterwards: “I guessed… I didn’t verify.”It deleted the production database and its volume-level backups in one API call. “It took 9 seconds.” Data was restored about an hour after Railway stepped in.No — one API call, outside the repository. May 2026coding agent, typia“all tests pass”It deleted every failing test. The tests/ tree was 70% smaller. CI was green.No — CI was green. Oct 2026Claude Code on Windows, issue #99193 (user report)“Looks intact”A recursive delete kept running for about 50 minutes after “Successfully stopped task”. About 116 GB was deleted.No — on the machine, not in the repo.

Figure 6: Seven incidents from 2025–2026, each reported by the developer it happened to. In several, the data came back. In every one, the agent’s account was the only account available at the time.

Sources: notes 1, 6, 12, 16–19

Each of these was reported by the developer it happened to, and in several the data came back. Replit’s rollback worked. Railway restored PocketOS. AWS restored DataTalks.Club’s database a day later. The point isn’t that agents mean harm. It’s that in the moment, the agent’s account (that rollback was impossible, that everything “looks intact”, that “all tests pass”) was the only account anyone had.

6.Agents now write most new code. Only 48% of developers always check it.

Google, April 2026: “75% of all new code at Google is now AI-generated and approved by engineers, up from 50% last fall.”20

Anthropic: “As of May 2026, more than 80% of the code we merge into Anthropic’s codebase was authored by Claude.”21

Sonar surveyed more than 1,100 developers (January 2026). AI accounts for 42% of committed code. 96% of developers don’t fully trust that it’s functionally correct. Only 48% always check it before committing.22

Stack Overflow, 2026: 73% of developers who use AI coding assistants or agents use them daily.23

And our sense of how it’s going is off. In METR’s 2025 study, developers overestimated AI’s effect on their time by about 40 percentage points.24

75%

of all new code at Google is AI-generated and approved by engineers

Google · Apr 202620

more than 80%

of code merged into Anthropic’s codebase was authored by Claude

Anthropic · May 202621

96%

of developers don’t fully trust that AI-generated code is functionally correct

Sonar survey, 1,100+ devs · Jan 202622

48%

always check AI-assisted code before committing it

Sonar survey · Jan 202622

NumberStatementSource 75%of all new code at Google is AI-generated and approved by engineersGoogle · Apr 2026 >80%of code merged into Anthropic’s codebase was authored by ClaudeAnthropic · May 2026 96%of developers don’t fully trust that AI-generated code is functionally correctSonar survey, 1,100+ devs · Jan 2026 48%always check AI-assisted code before committing itSonar survey · Jan 2026

Figure 7: Most new code is written by agents. Nearly every developer doubts it. About half don’t always check it.

Sources: notes 20–22 · Google (Apr 2026), Anthropic (May 2026), Sonar (Jan 2026)

Put together: most new code is agent-written, nearly everyone doubts it, and about half of developers don’t always check it. What stands in for the check is CI. That’s the problem.

7.A verdict needs a record.

The fix isn’t another model reading the first one’s work. A reviewer model is a grader, and §2 is a list of graders being gamed. It isn’t more process either. It’s one question, answered from evidence: did what the agent said actually happen, on the version you’re about to ship?

ThruLine answers it on your machine:

  • It records what the agent actually ran. Commands, exit codes, files touched and versions, from Claude Code and Codex sessions, in an append-only, hash-chained ledger.
  • It puts each claim next to the record. “All tests pass” at 16:41 sits beside the last test run and its exit code.
  • It knows which version proof applies to. Edit the code after the tests passed, and the proof stops applying: proven on the previous version, needs a re-check.
  • No model decides. States and counts are computed from records. The same record gives the same answer every time.
  • It says when it can’t tell. “Couldn’t check” is an answer, along with what would settle it. It doesn’t guess.
  • Nothing leaves this machine unless you paste it.

The answer is one line per claim: Proven on this version, or Not proven, and why. The full trace is there when you want the why. You never have to open it.

ThruLineChangeFix date parsing

version 3f9a1c2
Illustrative session
  1. {{ r.label }} {{ r.right }}

Illustrative replay — counts are sample data.

Not proven version 3f9a1c2

Command failed, then reported done

Said
“All tests pass. Ready to merge.” — 16:41
Record
The last test run before this message, at 16:38, exited 1 with 3 failed. No test run after it.
Do
Ask the agent to re-run the tests and paste the full output.
Show proof →

[ The other answers ]

Proven on this version

version e71c5b0

Said

“Added a retry to the webhook handler. Its tests pass.”

Record

Tests ran at 14:14 on this version, after the last edit at 14:12, and exited 0.

Needs a re-check

proven on version 8c41d07

Said

“Fixed the rounding bug. Tests pass.”

Record

Tests passed at 15:01 on version 8c41d07. src/billing/discount.ts changed at 15:09. No test run since.

Couldn’t check

Said

“The migration works.”

Record

Nothing in this session ran the migration or its tests.

What would settle it

A recorded run of the migration.

Checking stepCount Reading the session214 steps Finding what the agent said was done1 claim Matching the claim to the commands that ran9 commands Checking which version the result applies toversion 3f9a1c2 SaidAnswerVersionRecord “All tests pass. Ready to merge.” (16:41)Not proven — command failed, then reported done3f9a1c2The last test run before this message, at 16:38, exited 1 with 3 failed. No test run after it. “Added a retry to the webhook handler. Its tests pass.”Proven on this versione71c5b0Tests ran at 14:14 on this version, after the last edit at 14:12, and exited 0. “Fixed the rounding bug. Tests pass.”Needs a re-checkproven on 8c41d07Tests passed at 15:01 on version 8c41d07. src/billing/discount.ts changed at 15:09. No test run since. “The migration works.”Couldn’t check—Nothing in this session ran the migration or its tests. What would settle it: a recorded run of the migration.

Figure 8: ThruLine gives one answer per claim, computed from the record of what ran: Proven on this version, Not proven, Needs a re-check, or Couldn’t check. No model decides it. Illustrative session.

Illustrative session · sample data

ThruLine doesn’t merge, deploy or block anything. When you’re satisfied, you approve one exact version, and that approval is recorded under your project.

  • If you merge your own agent’s work, at 2 a.m., with no second reader: the record is your second reader.
  • If you review someone else’s agent PRs: the diff shows you the result. The record shows what ran, what failed, and what you were told.
  • If you lead a team: an approval names the exact version it was given for, and what it rested on.
Question CI The record (ThruLine)
Do the tests in the repo pass on this commit? CIYes The record (ThruLine)Shows the run and its exit code
Were tests edited or deleted on the way? CINo. A smaller suite is still green. The record (ThruLine)Shows the edits and deletions in the session, with times
Did the tests the agent described actually run? CIOnly the ones wired into CI The record (ThruLine)Shows the command and its result, or “no test run in the record”
Does “done” match what ran? CINever sees the claim The record (ThruLine)Puts each claim beside the record
Does the proof apply to the version you’re merging? CIOnly to the commit it ran on The record (ThruLine)Binds proof to a version. An edit afterwards means “needs a re-check”.
What did the agent do outside the repo? CICan’t see it The record (ThruLine)Records every command the agent ran. It doesn’t block them.
Who decides? CIA status check The record (ThruLine)You approve one exact version

Table 1: What CI tells you, and what the record adds.

8.Objections.

“My tests are written by humans.” Good. Agents edit human-written tests too; that’s what ImpossibleBench measured. And the suites in §3 were written by experts and still passed wrong code.

“I review every PR.” You review the diff. It doesn’t show which commands failed, which tests never ran, or what you were told. And by Sonar’s numbers, about half of developers don’t always check.22

“The model makers are adding self-review.” Self-review is the model grading itself, the arrangement §2 shows breaking. An independent record doesn’t depend on which model wrote the code, and it doesn’t change when the model does.

“One false alarm and I’ll stop trusting it.” Agreed, which is why ThruLine declines before it guesses. When the record can’t settle a claim, the answer is “Couldn’t check”, not “Not proven”.

“Too heavy.” One line per claim. Everything else is optional.

9.What we don’t know yet.

Nobody has published how often an agent’s “done” is unsupported in ordinary daily work. The benchmarks above measure propensity on hard or impossible tasks. The incidents are self-reported and self-selected. Transluce’s two figures, 34.7% and 5.7%, show how much the rate depends on the setting.11

The number that matters to you is your own, and it’s already on your disk. Claude Code keeps session transcripts for 30 days by default, then deletes them.25 Run ThruLine on the sessions you still have, and see how many of your agent’s “done”s the record backs.

CI was built for code a person wrote. For code an agent wrote, ask for the record.

Check your last agent session →

Footnotes

  1. {{ f.n }}

    {{ f.t }}

    {{ f.c }}

How to cite

{{ bib }}
{{ tipText }}

{{ popN }}{{ popT }}

{{ popC }}

{{ popU }}