<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[The grader said yes: auditing Terminal-Bench 2.0 with near-miss solutions]]></title><description><![CDATA[The grader said yes: auditing Terminal-Bench 2.0 with near-miss solutions]]></description><link>https://thegradersaidyes.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 10:48:54 GMT</lastBuildDate><atom:link href="https://thegradersaidyes.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The grader said yes: auditing Terminal-Bench 2.0 with near-miss solutions]]></title><description><![CDATA[Auditing Terminal-Bench 2.0 graders for being too lenient]]></description><link>https://thegradersaidyes.hashnode.dev/the-grader-said-yes-auditing-terminal-bench-2-0-with-near-miss-solutions</link><guid isPermaLink="true">https://thegradersaidyes.hashnode.dev/the-grader-said-yes-auditing-terminal-bench-2-0-with-near-miss-solutions</guid><category><![CDATA[systems-engineering]]></category><category><![CDATA[Systems Programming]]></category><category><![CDATA[Kernel]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[terminal-bench]]></category><category><![CDATA[harbor]]></category><category><![CDATA[Benchmark]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Ishan Nerlekar]]></dc:creator><pubDate>Fri, 06 Nov 2026 13:25:08 GMT</pubDate><content:encoded><![CDATA[<p>Nov 6, 2026 · Ishan Nerlekar</p>
<h2><strong>A proof that proves nothing</strong></h2>
<p>One Terminal-Bench 2.0 task asks the agent to finish a Coq proof that addition is commutative. I handed its grader a file that declares n + m = m + n as an axiom and then "proves" it by citing that axiom. The grader gave it full marks.</p>
<p>That is one of 16 wrong solutions I found accepted across 8 of the 26 Terminal-Bench 2.0 tasks I audited. All 16 pass under the benchmark's own harness, and all 8 tasks are now reported upstream with test fixes (<a href="https://github.com/harbor-framework/terminal-bench-2/issues/92"><u>#92–#99</u></a>).</p>
<p>Why this matters: a benchmark score is only as good as its verifier. A verifier that accepts wrong work inflates scores, and if the same tasks are used as RL environments, it rewards the wrong behavior. You can't see these gaps by reading the tests or by looking at the reference solution, because both are correct. You see them when you grade solutions that are <em>almost</em> right.</p>
<h2><strong>How I got here: a benchmark the cheapest models solved</strong></h2>
<p>I started out building KernelMind, a benchmark for debugging networked systems, the kind of work I did on network operating systems. It has 20 tasks in a small Wi-Fi control plane and in GoBGP (95k lines of Go). Many transplant the causal chain of a real production incident into new code, so the buggy code was never public.</p>
<p>I spent most of my effort on the graders. Each one is validated three ways: the untouched starter fails, alternative correct fixes pass, and at least three plausible wrong fixes each fail the specific check aimed at them. If a wrong fix passed, the grader was fixed before the task shipped.</p>
<p>Then I tried to make the tasks hard, and couldn't. Over 8 rounds and 122 attempts (about $1.10), the cheapest current models, Claude Haiku 5.5 and GPT-6 Luna, solved every design I tried:</p>
<ul>
<li>bigger codebases and code no model has seen</li>
<li>evidence with no textual clues, and decoys</li>
<li>two interacting faults behind a live reproduction</li>
<li>a regression introduced by an earlier fix, with git history to dig through</li>
</ul>
<p>The trajectories showed why. These models search for every term in the evidence at once, re-run the reproduction after every change, and read the commit message before reverting anything. My working hypothesis is that they fail when information is <em>missing</em>, not when it is spread out or disguised. I haven't tested that yet.</p>
<p>So the difficulty study was a negative result. But the part I trusted most, grading against wrong fixes, looked useful on its own. Did other benchmarks do it?</p>
<h2><strong>The idea: grade solutions that are almost right</strong></h2>
<p>A verifier is a classifier with two kinds of error: it can accept wrong work (lenient) or reject correct work (strict). To measure either, you need solutions whose correct verdict you already know. The reference solution only tells you the grader says yes to one right answer.</p>
<p>So KernelMind audit writes three kinds of candidate for each task and runs the task's own tests on each, in a fresh container:</p>
<table>
<thead>
<tr>
<th><strong>Candidate</strong></th>
<th><strong>How it's made</strong></th>
<th><strong>Should</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Mutant</td>
<td>one number, comparison or boolean changed in the reference solution, or one shell step deleted</td>
<td>fail</td>
</tr>
<tr>
<td>Near miss</td>
<td>a model breaks exactly one sentence of the instruction and quotes it</td>
<td>fail</td>
</tr>
<tr>
<td>Alternative</td>
<td>a model meets every requirement a different way</td>
<td>pass</td>
</tr>
</tbody></table>
<p>Near misses come in six categories taken from KernelMind's wrong-fix controls: partial fix, missed edge case, symptom-only fix, over-broad change, hardcoded output, wrong format. The model sees the instruction and the reference solution but never the tests, so near misses are plausible mistakes, not test-gaming.</p>
<p>A passing near miss is only a <em>suspect</em>. Models often claim a flaw their code doesn't have. Every suspect was checked by hand against the instruction's exact words, and where possible with a differential probe: an input the instruction decides, on which the reference and the candidate disagree. Confirmed findings were then rerun under Harbor, Terminal-Bench's own harness, with the wrong solution swapped in for the reference.</p>
<h2><strong>What it found: 8 of 26 Terminal-Bench 2.0 tasks accept wrong work</strong></h2>
<p>I audited 30 tasks (a 5-task pilot plus 25 sampled with a fixed seed under rules written before any results) and graded 26; four needed hardware or parts of Harbor's runtime I didn't reproduce, or had a broken reference. Eight tasks, 31%, accepted at least one solution that is wrong by the instruction's own words. Harbor gave all 21 reproduction trials (8 references, 13 wrong solutions) reward 1.0.</p>
<table>
<thead>
<tr>
<th><strong>Task</strong></th>
<th><strong>Wrong solution that passes</strong></th>
<th><strong>Issue</strong></th>
</tr>
</thead>
<tbody><tr>
<td>prove-plus-comm</td>
<td>assumes the theorem as an Axiom; also Admitted. with Qed. in a comment</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/94"><u>#94</u></a></td>
</tr>
<tr>
<td>git-leak-recovery</td>
<td>the secret is still readable with git show on a dangling commit; every commit message rewritten</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/93"><u>#93</u></a></td>
</tr>
<tr>
<td>configure-git-webserver</td>
<td>the deploy hook ignores the push and writes a literal hello world</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/95"><u>#95</u></a></td>
</tr>
<tr>
<td>modernize-scientific-stack</td>
<td>edits the script marked DO NOT MODIFY; omits the required version pins</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/97"><u>#97</u></a></td>
</tr>
<tr>
<td>db-wal-recovery</td>
<td>writes the right JSON but never fixes the WAL file, step 1 of the task</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/96"><u>#96</u></a></td>
</tr>
<tr>
<td>cobol-modernization</td>
<td>a Python port that drops the seller-owns-book check</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/98"><u>#98</u></a></td>
</tr>
<tr>
<td>regex-log</td>
<td>rejects Feb 29 (explicitly allowed), accepts April 31, rejects octet 250</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/92"><u>#92</u></a></td>
</tr>
<tr>
<td>sparql-university</td>
<td>counts the UK as an EU member; reads "more than 10" as &gt;= 10</td>
<td><a href="https://github.com/harbor-framework/terminal-bench-2/issues/99"><u>#99</u></a></td>
</tr>
</tbody></table>
<p>Severity varies. The axiom proof, the recoverable secret and the hardcoded deploy are serious: an agent that does them has not done the task. The SPARQL boundary cases are minor. Fifteen of the 16 wrong solutions came from the auditor (12 near misses, 3 mutants); I found the Admitted. variant by hand while testing the fix for the axiom case.</p>
<p>Each issue includes a test change. I validated 7 of the 8 locally: the reference still passes and every wrong solution now fails. Before filing, I searched the tracker; none of the eight had been reported.</p>
<h2><strong>Five ways verifiers go wrong</strong></h2>
<p>The eight findings share five causes. None is exotic, and each has a cheap fix.</p>
<ol>
<li><strong>A stated requirement is never tested.</strong> "DO NOT MODIFY", the version pins, "fix the WAL file", "commit messages remain untouched". If the instruction says it and no test checks it, it's optional.</li>
<li><strong>The one fixed input lacks the deciding case.</strong> The COBOL test data has no invalid sale, the SPARQL graph has no non-EU country and no department with exactly 10 students, and no log line is dated Feb 29.</li>
<li><strong>The test input is the instruction's own example.</strong> The webserver test pushes exactly the hello world the instruction shows, so writing that string passes.</li>
<li><strong>Negative samples are confounded.</strong> In regex-log, every line with an invalid date also has an invalid IP. Those samples test the IP rule, so a broken date rule never gets caught.</li>
<li><strong>The test checks the wrong object, or text instead of meaning.</strong> The leak test lists dangling commit headers, not the blob that holds the secret. The proof test looks for the string Qed. instead of asking Coq which assumptions the proof uses (Print Assumptions does that).</li>
</ol>
<p>All five are invisible if the only solutions ever graded are the reference and a few agent runs. They show up as soon as you grade solutions that are wrong in one specific way.</p>
<h2><strong>How good is the auditor?</strong></h2>
<p>It catches gross verifier flaws every time and misses most subtle ones, so 31% is a floor, not an estimate.</p>
<p>To measure recall, I planted flaws in copies of 11 KernelMind tasks, whose graders I know are sound: I disabled the tests that catch one known wrong fix, audited the weakened task, and regraded the same candidates against the original tests.</p>
<table>
<thead>
<tr>
<th><strong>Planted flaw</strong></th>
<th><strong>Detected</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Gross: the weakened verifier also accepts the untouched starter</td>
<td>4 of 4</td>
</tr>
<tr>
<td>Subtle: only one specific wrong fix gets through</td>
<td>2 of 7</td>
</tr>
</tbody></table>
<p>With four near misses per task, the model rarely makes the one mistake a subtle gap lets through. More near misses, or one per instruction sentence, is the obvious next experiment.</p>
<p>Precision depends on the target. On Terminal-Bench, 12 of 18 model-written lenient suspects were real. On KernelMind's validated graders, only 3 of 18 deserved attention (two small real gaps in my own tests and one open question); the rest were equivalent mutants and near misses whose claimed flaw wasn't in their code. The auditor ranks where to look; a person still decides.</p>
<p>Strictness is a blind spot. None of the 9 failing alternatives turned out to be a correct solution the verifier wrongly rejects, while other people reported strictness and crash issues on two tasks I audited (<a href="https://github.com/harbor-framework/terminal-bench-2/issues/84"><u>#84</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/85"><u>#85</u></a>). Writing a correct alternative is much harder for a model than writing a near miss.</p>
<p>Cost: under $0.25 of model calls for everything ($0.16 for the Terminal-Bench candidates, $0.05 for the planted-flaw study). The real cost is container time, roughly 10–15 minutes per task on a laptop.</p>
<h2><strong>Takeaways for benchmark builders</strong></h2>
<p>Grade wrong answers before you trust a grader. Concretely:</p>
<ul>
<li>For every sentence in the instruction that states a requirement, point to the test that fails without it. If there isn't one, write it or cut the sentence.</li>
<li>Never test with the instruction's own example. Use a second input the agent hasn't seen.</li>
<li>Give each negative sample exactly one defect, so it tests the rule you meant.</li>
<li>Check meaning, not text: ask the tool (Coq, git, the database) rather than grepping its output.</li>
<li>Before shipping a task, run a handful of near misses through its tests. It costs cents.</li>
</ul>
<p>The same lesson held for my own benchmark. KernelMind's graders survived the audit because each had been checked against wrong fixes from the start, and the audit still found two small gaps in them.</p>
<h2><strong>Links</strong></h2>
<ul>
<li>Issues filed on Terminal-Bench 2.0: <a href="https://github.com/harbor-framework/terminal-bench-2/issues/92"><u>#92</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/93"><u>#93</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/94"><u>#94</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/95"><u>#95</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/96"><u>#96</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/97"><u>#97</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/98"><u>#98</u></a>, <a href="https://github.com/harbor-framework/terminal-bench-2/issues/99"><u>#99</u></a></li>
<li><a href="https://github.com/harbor-framework/terminal-bench-2"><u>Terminal-Bench 2.0</u></a>, audited at commit 2fd12b8</li>
<li>Code, full technical report and audit log: the KernelMind repository (link to add when it goes public)</li>
</ul>
<p>Thanks to the Terminal-Bench maintainers for an open, well-documented benchmark; making it easy to audit is what made this possible.</p>
<p><strong>Update (Nov 7):</strong> A strong model read each task’s tests and wrote solutions designed to pass while violating the instruction, and every one was run against the real tests. Reading alone, it found 12 of the 14 gaps above, for about $2 across 26 tasks. It also found four more tasks, including a pipeline-parallel training step that never runs the backward pass and a terminal that ignores Ctrl-C. All four are confirmed under Harbor and filed with fixes (<a href="https://github.com/harbor-framework/terminal-bench-2/issues/100">#100</a>–<a href="https://github.com/harbor-framework/terminal-bench-2/issues/103">#103</a>), bringing the total to 12 of 26 tasks. One task’s own reference solution turned out to be wrong too. These gaps aren’t hard to see if you ask a model to construct a wrong solution that passes, and then run it. Related work, Terminal Wrench (Zhong et al., 2026), found 13 of 89 Terminal-Bench 2.0 tasks hackable by prompting models to hack; only 2 overlap with mine.</p>
]]></content:encoded></item></channel></rss>