Two models tie on a benchmark. One of them loses sixty-four points of capability the moment you deploy it, and gets sixty-one back by rewriting its own commands. The tie was the sum of those two numbers — and the benchmark reported neither.
You are choosing a model for a coding agent. The agent does one thing over and over: it decides what shell command to run, and something in your stack runs it. You do what everyone does — you find a benchmark that measures exactly that, you read the column, and you pick the top row.
The column says 91.1% for the model you picked. The column says 94.6% for the same model on a slightly different setup. A gap of three and a half points. Rounding error. You ship.
In production, your agent does not talk to a local shell. It talks to a container, or a CI runner, or a remote host, and the command reaches Bash through a wrapper that looks like this:
And roughly two thirds of the commands that worked in the benchmark now silently produce the wrong result.
Here is the entire paper in five numbers, for the configuration the authors call gpt-5.6-sol. Each number is a count out of 56 tasks, which we will convert to percentage points by hand because the conversion is the whole trick.
| What was measured | Tasks passed | Percent |
|---|---|---|
| Model writes a command; command runs directly | 53 / 56 | 94.6% |
| Same reply, replayed through one added parser | 17 / 56 | 30.4% |
| Model is told about the parser, then writes; runs through it | 51 / 56 | 91.1% |
One task out of 56 is 1⁄56 = 0.017857, so one task is 1.79 percentage points. Hold that constant; every number in this lesson is a multiple of it.
Now the three quantities the paper cares about. Transport damage is what the added parser costs a fixed reply:
Contract-conditioned compensation is what the model recovers when it is told the parser is there and rewrites accordingly:
And the matched gap — the only one of the three that a conventional benchmark reports, because it is the only one where both cells were generated and executed under their own declared setup:
Check the arithmetic the other way, because this is an identity and not a coincidence: −64.3 + 60.7 = −3.6. Exactly. In tasks: −36 + 34 = −2.
Sixty-four points sounds like a benchmark artefact until you look at what the tasks are. QuoteBench does not test exotic shell wizardry. It tests things a coding agent does hourly: write a file with exact bytes, pass a literal argument to a program, edit a JSON field, run a sed replacement, commit with a message, handle a filename that contains a space.
And the damage is not confined to the deliberately nasty payloads. The benchmark includes 14 control tasks — one per operation family, deliberately benign, no hostile characters at all. Under the added parser, the eight configurations lose between 28.6 and 57.1 points on the controls alone. In counts, that is 4 to 8 of the 14 benign tasks:
The paper's explanation is one clause long and it is the reason the whole effect exists: models emit double-quote-active characters even for ordinary commands. A quoted string here, a $ there, a backslash in a path. Nothing hostile. All of it explosive on the second pass.
Before any theory, watch it happen. The simulation below holds a model's reply completely fixed and sends it down two paths: straight into bash -c, and into bash -c "…" with the reply pasted inside the double quotes. Nothing about the model changes between the two panels. Only the plumbing does.
Pick a reply, then step through the outer shell's read of it. Characters the outer parser consumes are marked; characters it leaves alone pass through untouched. The final-state check at the bottom is byte-exact, exactly like the benchmark's validators. Watch the exit code while you do it.
Three things worth noticing. First, the raw path is boring — the reply is the program, and it does what it says. Second, the nested path does not crash; on the "printf literal" reply it produces a file, exits zero, and gets the bytes wrong. Third, on the benign control, most of the reply survives — and then one ordinary character does not, and the whole result is wrong anyway.
It is tempting to conclude that the benchmark was simply wrong. It was not. The 91.1% is a completely accurate description of one thing, and useless for another, and the difference between those two things is the subject of this lesson.
| Question | Does a matched score answer it? |
|---|---|
| "How well does this model do the tasks, on the exact setup that was measured?" | Yes. That is precisely what it measures, and the paper says the matched score "accurately describes its declared path." |
| "Will its commands still work if my harness wraps them differently?" | No. That is portability, and it lives in the off-diagonal cell nobody computed. |
| "Did this model get better between two releases, or did it just learn to read the prompt?" | No. Both look identical in the reported number. |
| "Which of two models should I deploy behind a remote wrapper?" | No — and it can invert the answer. Chapter 8 has the case. |
| "Is the failure the model's fault or my harness's?" | No. Both show up as the same missing point. |
Every "no" in that column is answerable, and answerable cheaply, by replaying stored replies through a second path. Nothing about the model needs to be re-run. That is the paper's actual gift: a decomposition you can compute after the fact, for free, from outputs you already have.
The benchmark measures single commands, but the systems that issue them are loops, and a loop amplifies the cost of a failure in ways a pass rate does not show. The paper opens on exactly this and it is worth making concrete.
This is why the incident evidence behind the benchmark is full of phrases like "repeated repair attempts" and "multi-attempt delays". The unit of damage in production is not one failed command. It is a turn, plus a polluted context, plus a file nobody asked for.
It is worth being precise early, because the result is easy to over-read in both directions.
| The paper claims | The paper does not claim |
|---|---|
| A fixed reply loses 55.4–73.2 points when one double-quoted parser is added, in every one of eight same-window configurations | That such parsers are common in deployment — the surveys establish mechanism coverage, not prevalence |
| Six of eight configurations recover 30.4–60.7 points from a one-sentence disclosure of the boundary | That disclosure is a fix — two configurations recover nothing, and one goes slightly backwards |
| The matched score is the sum of those two effects and hides both | That the matched score is wrong — it accurately describes the path it was measured on |
| Deployment configuration reorders models; one reversal among 26 comparable pairs is unambiguous | That the leaderboard is meaningless — it is a bootstrap-supported partial order |
| The obvious fixes work perfectly and are trivial | That the fix is the contribution — the authors say plainly it is the measurement |
That last row deserves emphasis, because it is unusual and it is honest. Two repairs remove the entire effect: escape the reply at the interpolation point, or write it to a temporary script and execute that. Both reproduce the raw-path outcome for all 448 public replay pairs. The authors write that "precisely because the fixes are trivial, the contribution is the measurement, not the repair." A matched score alone cannot tell an evaluator whether the fix is needed — that is the whole problem.
Chapter 0 asserted that adding one parser destroys most working commands. This chapter earns that assertion by hand, on real bytes, because the mechanism is completely mechanical and you should never have to take it on faith.
When Bash reads a command line it performs quote removal and several expansions, and the rules depend on which kind of quoting you are inside. There are exactly three states, and you only need these three.
| State | What is still special | What is inert |
|---|---|---|
| Unquoted | $ ` \ " ' * ? [ whitespace | & ; < > ( ) | almost nothing |
Inside "double quotes" | $ (expansion), ` (command substitution), \ (only before $ ` " \ or newline), " (closes the quote) | spaces, globs, ', ;, |, &, redirections |
Inside 'single quotes' | only ', which closes the quote | everything else, including backslash |
Take a task of the shape QuoteBench actually uses: write a file whose exact content is
followed by one trailing newline. This is a legitimate literal-preservation task — a dollar sign, a backtick pair, a nested double quote. A competent model replies with a single command, and this one is correct:
the model's reply, call it R printf '%s\n' 'cost: $5 `now` "x"' > out.txt
Read it once on the raw path. The outer printf gets format %s\n and one argument. Both are single-quoted, so $5, the backticks and the inner double quotes are all inert. printf's %s conversion does not interpret backslashes in its argument (that is %b), so the payload passes through untouched. The file receives exactly nineteen bytes plus a newline. Pass.
Now the nested path. The harness does not execute R. It builds the string bash -c "R" — R pasted verbatim between two double quotes — and executes that. So an outer Bash reads this line first:
what the outer shell sees
bash -c "printf '%s\n' 'cost: $5 `now` "x"' > out.txt"
Walk it left to right in the outer shell, using only the three-state table above.
| # | Outer shell reads | What it does | Result so far |
|---|---|---|---|
| 1 | bash -c | two ordinary words | command name and flag |
| 2 | the first " | enters double-quote state | — |
| 3 | printf '%s\n' 'cost: | single quotes are inert here; \n is a backslash before n, which is not one of $ ` " \, so it stays literal | text accumulates unchanged |
| 4 | $5 | expands — positional parameter 5 of the outer shell, which is unset | replaced by the empty string |
| 5 | `now` | command substitution — the outer shell runs now, which does not exist, writes an error to stderr, and substitutes its empty stdout | replaced by the empty string |
| 6 | the " before x | closes the double-quote state — this quote came from the payload, but the outer shell has no way to know that | first quoted section ends |
| 7 | x | unquoted literal, concatenated to the previous word | — |
| 8 | the " after x | opens a new double-quote state | — |
| 9 | ' > out.txt | all inside quotes now — the > is not a redirection to the outer shell, it is literal text | — |
| 10 | the final " | closes the wrapper's own quote; word ends | one single argument |
Adjacent quoted and unquoted fragments concatenate into one word, so what bash -c actually receives as its script is:
The inner shell now parses that perfectly happily. It has a valid printf, a valid redirection, and it writes the file. The file contains cost:, three spaces, x, newline. The expected content was cost: $5 backtick now backtick "x".
returncode == 0 records a success. A human skimming the trace sees a printf that ran. Only a byte-exact validator catches it — and that is precisely why the paper reports that 23.4–47.0% of failing executions exit zero.The paper prints one worked task in full — the write-file family, hazard tier 3. The instruction asks for a file out.txt whose content is exactly:
back\slash and `date` here'single' "double" $(pwd) 100%The paper also prints the naive command, the thing a model reaches for without thinking:
naive — fails even on the raw path echo "back\slash and `date` here …" > out.txt
Three separate defects, and the paper names all three: the backticks execute date, $(pwd) expands locally, and the payload's inner double quote terminates the string early. This is the tier-3 variant — the benign tier-0 control of the same family uses ordinary text and the naive command passes. That contrast is deliberate and it is how the benchmark separates "cannot do the operation" from "cannot preserve a literal."
The passing command the paper describes is "a single-quoted printf with an embedded-quote splice." The splice is the standard idiom for putting a single quote inside a single-quoted string, since there is no escape for it:
the machine oracle, structurally printf '%s\n' 'back\slash and `date` here '"'"'single'"'"' "double" $(pwd) 100%' > out.txt # the splice: close single quote, emit a double-quoted apostrophe, reopen # ' "'" ' -> one literal ' with nothing else changed
Now count what the outer double-quoted parser does to that. The splice contains " characters — three of them per apostrophe — and each one flips the outer quote state. The $(pwd) expands in the outer shell. The backticks around date run date in the outer shell. The \s survives, because s is not one of the four characters backslash protects inside double quotes. The model wrote a correct program and the channel shredded it.
This is the obvious objection and the paper answers it with an experiment rather than an argument. The authors took each stored raw reply and replayed it through an actual remote command — ssh localhost "R" inside a container running a real sshd — and compared the loss to the synthetic nested transport. Zero model calls; pure replay.
| Configuration | Raw | Real ssh | ssh damage | Synthetic nested damage |
|---|---|---|---|---|
| GPT-5.6-sol | 94.6 | 30.4 | −64.3 | −64.3 |
| GPT-5.5 | 100.0 | 28.6 | −71.4 | −71.4 |
| Opus-5 | 96.4 | 30.4 | −66.1 | −66.1 |
| Gemini-3.1-Pro | 98.2 | 26.8 | −71.4 | −73.2 |
| Gemini-3.5-Flash | 96.4 | 28.6 | −67.9 | −67.9 |
| Opus-4.8 | 91.1 | 26.8 | −64.3 | −64.3 |
| Qwen3.5-27B | 85.7 | 30.4 | −55.4 | −55.4 |
| Gemini-3.1-Flash-Lite | 78.6 | 19.6 | −58.9 | −58.9 |
Seven of eight match to the decimal. The eighth, Gemini-3.1-Pro, differs by 1.8 points, which is exactly one task: −71.4 is −40 tasks and −73.2 is −41 tasks out of 56. The synthetic condition is not a caricature of a remote command — on this benchmark it is numerically the same thing, because it is the same parser.
If the mechanism is a missing escape, the fix is an escape. The paper measures both obvious repairs on all 448 public replay pairs (8 configurations × 56 tasks).
So why is there a paper? Because both repairs require the caller to control the boundary. The authors surveyed six public agent systems at fixed commits and found the boundary applied downstream of whatever contract the model was given — a command string that later becomes shell -c/-lc R, an action that enters a persistent Bash session, a structured command written to a shell's stdin, key strings pushed through a tmux session. The system that states the contract is frequently not the system that adds the parser.
The abstraction is easier to hold once you have written it. Here are all four ways a harness can get a reply R to a shell, as the paper describes them, with the difference between them reduced to one line each.
python import shlex, subprocess, tempfile, os, pathlib def run_raw(R, cwd): # the raw transport: R IS the program. One parser, and it is Bash's. return subprocess.run(["bash", "-c", R], cwd=cwd) def run_nested(R, cwd): # the nested transport: R is INTERPOLATED into a double-quoted word. # This is the whole intervention. One extra parser, no other change. outer = 'bash -c "' + R + '"' return subprocess.run(["bash", "-c", outer], cwd=cwd) def run_nested_escaped(R, cwd): # REPAIR 1 — quote at the interpolation point. shlex.quote wraps R in # single quotes and splices any embedded apostrophes, so the outer # shell hands the inner one exactly the bytes the model wrote. outer = "bash -c " + shlex.quote(R) return subprocess.run(["bash", "-c", outer], cwd=cwd) def run_script(R, cwd): # REPAIR 2 — never cross the boundary. The program lives in a file, # so no second parser ever reads its text. Costs a file lifecycle. fd, path = tempfile.mkstemp(suffix=".sh") os.write(fd, R.encode()); os.close(fd) try: return subprocess.run(["bash", path], cwd=cwd) finally: os.unlink(path)
Read the diff between run_nested and run_nested_escaped. It is one function call. That single call is worth 292 commands across the eight configurations in Chapter 4, and its absence is what the entire paper measures.
shlex.quote is exactly right and why single quotes are the mechanism. It wraps the whole string in single quotes and replaces every embedded apostrophe with the splice from earlier in this chapter. Since single quotes make everything inert — there is no character with special meaning inside them except the closing quote itself — the outer shell performs no expansion, no substitution, and no word splitting. It hands the inner shell the original bytes. That is why the repair is total rather than partial: it does not enumerate dangerous characters, it removes the entire class of danger.Chapter 2 will list all 14 families. Three of them are worth walking now, because each breaks in a structurally different way and together they explain why the damage is not concentrated in one mechanism.
Expansion timing (the find / glob family). A glob is not a character problem, it is a timing problem: the question is which shell expands it. Consider a reply intended to delete backup files in a subtree:
the reply find . -name '*.bak' -delete
On the raw path, the single quotes stop Bash expanding *.bak and find receives the pattern itself, matching at every depth. Under bash -c "R", single quotes are inert — but so are globs inside double quotes, so this particular reply survives. Now consider the same intent written without quoting, which many models do:
a fragile variant
find . -name *.bak -delete
Unquoted, the pattern expands against the current directory before find ever runs. If there is exactly one matching file at the top level, find silently searches for that one name and misses the rest; if there is none, Bash passes the literal pattern and it works by accident. The outcome depends on the fixture, which is precisely why the benchmark builds fixtures without invoking a shell. This is also why find-glob is the family where disclosure makes things worse — adding escapes changes when expansion happens, and the model is being asked to reason about ordering rather than about characters.
Argument boundaries (the hostile-filename family). A filename can contain a space, a newline, a leading dash, or a glob character — POSIX permits everything except the null byte and the path separator. The classic hazard is the leading dash:
the fixture contains a file literally named -rf rm -- -rf # correct: -- ends option parsing rm ./-rf # also correct: the path is no longer dash-initial rm -rf # catastrophically wrong: parsed as flags
Here the second parser does not change the characters at all — it changes the word splitting, which changes the argument vector, which changes which strings are options and which are operands. That is why the validators inspect the received argv for this family rather than file bytes: the failure is in argument structure, not content.
Embedded languages (the sed, grep and AWK families). These stack a third grammar on top of the two shells. A sed replacement has its own escaping rules for the delimiter, for &, for backreferences and for newlines, and those rules are unrelated to Bash's:
python # the model must satisfy THREE grammars at once: # 1. sed's substitution syntax (delimiter, &, backrefs) # 2. the inner shell's quoting (what the model is thinking about) # 3. the outer shell's quoting (which nobody told it about) sed -i 's|old|new \& co|g' cfg.txt
The paper's family-level compensation numbers say something precise about this stack. sed-replace recovers +46.9 points under disclosure and json-write +50.0, while find-glob recovers −12.5. Explicit payload-quoting hazards, where the model can see a string that needs protecting, are the ones disclosure helps with. Implicit hazards — expansion order, argument structure — are not.
bash -c "R"?You now know the mechanism. Turning it into a measurement is a separate craft, and QuoteBench is a good place to learn it, because almost every design choice exists to close a specific way a benchmark can lie to you.
Each task is a fixture (a directory prepared without ever invoking a shell), an instruction, and a final-state validator. A model returns exactly one Bash program. It runs in a fresh working directory with a trimmed environment and a 15-second timeout. Then the validator looks at what is on disk — and only at what is on disk.
The tier structure is the load-bearing part. Within a family, the operation is held fixed and only the payload changes: the control is ordinary text; the hazardous tiers add quotes, expansion characters, multiline data, leading dashes, or parser-boundary conflicts. So the control answers "can this model do the operation at all?" and the difference between control and hazardous answers "can it preserve a literal while doing it?" Those are different competences and a single aggregate score confuses them.
| Mechanism group | Representative failure | Families |
|---|---|---|
| Literal quote and expansion | apostrophes, double quotes, dollars, backticks, multiline payloads | write-file, JSON writing, Git commit, environment passing, heredoc writing |
| Word splitting and path semantics | spaces, globs, leading dashes, hostile filenames, argument boundaries | argv passing, hostile filenames, find/glob, bulk rename |
| Embedded-language escaping | regex versus literal matching, sed replacement, AWK string processing | grep count, sed replace, field lookup, JSON writing |
| Second parser or remote-like expansion | local expansion before a second shell, argument joining, heredoc transport | SSH-like nested execution, SSH-like heredoc |
| Command-boundary representation | command string, shell stdin, temporary file, argv, provider tool schema | raw/nested crossover, native-tool study, script bypass, typed pilot |
The families were not invented at a whiteboard. Two surveys fed the design, and the counts are worth memorising because they show what the evidence does and does not support.
shell -c. That is why "nested" is the controlled condition and not a hypothetical.Check the public arithmetic: 17 retained + 10 harness + 7 excluded = 34 read in full, out of 412 screened. Retained reports span Claude Code, Codex, Gemini CLI, Warp, and OpenHands — broken heredocs, over-quoted operators, repeated repair attempts. The authors are careful with the inference this licenses: the surveys "document mechanism coverage. Prevalence and complete shell coverage remain outside their purpose."
A benchmark's validators are code, and code has bugs. The failure mode here is well documented in the literature the paper cites: permissive validators that accept incorrect coding-agent patches. So QuoteBench audits every validator in four directions.
| Check | What it rules out | Result |
|---|---|---|
| Machine-constructed oracle for every task | an unsolvable task inflating the failure rate | solves all 56 with one command |
| Benign naive probes | a validator so strict nothing passes | all pass |
| Hazardous naive probes | a validator so loose the hazard does not matter | all fail on the raw path |
| Untouched fixtures | a validator that passes without any work being done | all rejected |
| Targeted mutations of oracle-produced states | a validator that ignores part of the required state | 197 of 197 rejected |
The mutation classes and their counts add up exactly, which is a nice sanity check to run yourself: delete a changed or required file 60/60, flip one byte in a changed file 60/60, insert an unexpected collateral file 56/56, restore a file that should have been removed 17/17, amend a Git-only final state 4/4. Sum: 60 + 60 + 56 + 17 + 4 = 197.
And a solvability control for the nested arm specifically, which matters more than it looks: three configurations pass all 56 tasks under the nested transport. So every task has a feasible nested solution, and the nested arm is not a degenerate condition where the benchmark is simply impossible.
Scope statements are how you avoid being cited for things you did not measure. QuoteBench focuses on POSIX/Bash command construction. Outside the benchmark: PowerShell, Windows CMD, authentication, network failures, interactive terminal state, and multi-turn recovery. The public core also excludes real SSH networking and authentication — the SSH-like families are local two-shell simulations.
Two more design details you should copy if you ever build an evaluation like this.
Contamination handling. Publishing the frozen 56-task core creates a contamination risk. The authors treat it as a versioned audit set (core-v1), hold out regenerated private variants, and embed a fixed canary GUID in every released task file so downstream contamination checks have a known token to grep for.
The query date is part of the result. Hosted deployments can change under the same model identifier. So the paper records that the same-window mechanism sweep was queried on 2026-07-31 and the effort ladders earlier in July 2026. If you ever cite a number from a hosted model without a date, you have cited a moving target.
The tier structure is what turns a pile of shell tasks into an instrument, so it is worth walking one family from the benign control up to the hardest variant. Take write-file, whose tier-3 instance the paper prints in full. The operation is identical at every tier — create out.txt with exactly this content and one trailing newline — and only the payload changes.
| Tier | Payload character | What it isolates | Does the naive echo pass? |
|---|---|---|---|
| 0 — control | ordinary words, no metacharacters | can the model perform the operation at all | yes, on the raw path |
| 1–3 — hazardous | quotes, expansion characters, multiline data, leading dashes, parser-boundary conflicts | can it preserve a literal while performing the operation | no — each hazardous probe fails on the raw path |
That last column is a validated property of the benchmark, not an assumption: the audit confirms benign naive probes pass and their hazardous counterparts fail on the raw path. So a model that scores 14/14 on controls and 13/42 on hostile tasks — Haiku-4.5 at its best observed setting — is not failing at shell. It is failing at literal preservation, and the two-column split makes that legible in a way a single 37.5% cannot.
The phrase "final-state validator" hides some real engineering, so here is its shape for the write-file family. Three checks, and the third is the one people forget.
python import os, pathlib EXPECTED = (b"back\\slash and `date` here\n" b"'single' \"double\" $(pwd) 100%\n") def validate(workdir): # 1. the artefact exists p = pathlib.Path(workdir) / "out.txt" if not p.is_file(): return False # 2. the bytes are EXACT — including the single trailing newline. # Not a substring match, not a strip()ed compare, not a decode. if p.read_bytes() != EXPECTED: return False # 3. no collateral. A command that got the file right by writing # three helper files on the way has not solved the task. if set(os.listdir(workdir)) != {"out.txt"}: return False return True
Every design decision in those fifteen lines answers a way the measurement could have been wrong. Byte comparison rather than text comparison, because an encoding round trip would silently normalise a payload the task exists to preserve. No stripping, because the trailing newline is part of the specification — echo adds one and printf '%s' does not, and the difference is exactly the kind of thing a benchmark should notice. And the collateral check, because the paper's own recovery story is "write a temporary script", which leaves workspace artefacts; a validator blind to collateral would grade that as clean.
Notice also what is not in there: the command text. No regular expression over the reply, no oracle-string comparison, no check that the model used printf. That is what makes "any semantically correct implementation receives credit" true rather than aspirational, and it is what allows the disclosed-boundary arm to rewrite its commands completely and still be scored fairly.
The mutation audit deserves one more paragraph because it is a technique you can lift wholesale. The procedure: run the oracle, capture the resulting valid state, then corrupt it in every way the validator is supposed to catch and confirm each corruption is rejected.
The counts also tell you about the benchmark's shape. Only 17 tasks involve removing a file, and only 4 have Git-only final state — so the Git family is small, and most tasks are about producing bytes rather than deleting them. That is the kind of thing you can read off an audit table if you look.
Everything so far has been setup. This chapter is the paper's actual contribution, and it is a piece of experimental design rather than a piece of engineering. The question is: given that a command can fail either because the model wrote it wrong or because the channel broke it, how do you tell which happened?
QuoteBench separates two things that agent systems normally bundle together.
The paper evaluates two observed model-facing contracts and adds one controlled intervention.
| Contract | What the model is asked for | How the reply reaches Bash |
|---|---|---|
| Raw | one Bash program, nothing else | executed verbatim as the script argument to bash -c |
| Native | a provider shell-tool call | the required command field is extracted and executed on the same raw path |
| Disclosed-boundary | one Bash program, plus one sentence stating that the reply will be interpolated inside double quotes | the nested transport, which adds exactly that parser |
The two Study-A contracts are printed verbatim in the appendix, and the diff between them is the entire experimental manipulation. The raw clause:
The disclosed-boundary clause:
printf or heredocs. The paper confirms with a character-level diff that the sentence beginning "Your reply" is the only text that changes between the two full system prompts. So whatever the model does differently is elicited by the fact of the boundary, not by coaching about it — and Chapter 5 shows the difference between those two things is measurable.Now cross them. Let G be the generation contract and T the execution transport, each taking value R (raw) or N (nested / disclosed-boundary). Four cells, written contract-then-transport:
| Cell | Reply generated under | Executed through | What it is |
|---|---|---|---|
| RR | raw contract | raw transport | matched — the direct-path score |
| RN | raw contract | nested transport | off-diagonal replay: fixed reply, added parser |
| NR | disclosed-boundary contract | raw transport | off-diagonal replay: boundary-aware reply, no boundary |
| NN | disclosed-boundary contract | nested transport | matched — the deployed-path score |
The diagonal cells, RR and NN, are what any normal benchmark reports: each was generated and executed under its own consistent setup. The off-diagonal cells are the new information, and they cost zero model calls — RN is the RR reply replayed through a different transport, NR is the NN reply replayed through a different transport. Same bytes, different plumbing.
From the four cells, three quantities, all in percentage points averaged over the 14 families:
And the identity that makes the whole thing work — add and subtract YRN:
Pick a configuration. The 2×2 fills with its measured pass rates (out of 56 tasks) from the paper's same-window sweep. The bar underneath decomposes the matched gap into damage and compensation — watch how the two arrows can be enormous while the bar that a leaderboard would print stays near zero.
Flip to the second mode on GPT-5.6-sol. Two numbers survive, 94.6 and 91.1, and the story they tell is "robust model." Flip back and the same model has lost 36 tasks and rebuilt 34 different ones. Both descriptions are true. Only one of them predicts what happens when your harness changes.
There is a large literature showing that scores move when you change a nuisance variable — prompt formatting, scaffold choice, harness. The paper is careful about what makes its design different, and the distinction is worth internalising because it applies to any experiment you will ever run on a model.
| Approach | What changes between conditions | What you can conclude |
|---|---|---|
| Swap the whole harness | context handling, retry policy, verification, the command path, everything | that variance exists — but not which mechanism caused a given reversal |
| Regenerate under a new prompt format | the prompt and the reply | that scores move — but you cannot separate "the channel destroyed it" from "the model wrote something different" |
| Fixed-output replay (QuoteBench) | one parser, and nothing else | the change in outcome is attributable to that parser, because the bytes were identical on both sides |
The paper puts it plainly against the closest concurrent work: because that work "replaces the harness wholesale, including context handling, retry, and verification, it measures variance but cannot attribute a reversal to a mechanism; QuoteBench fixes the model output and changes a single parser."
The paper inspected six public agent systems at fixed commits, recording separately what each system asks the model to produce and what it subsequently does with the reply. Both contract styles are in use, and the downstream boundaries vary a lot.
| System | Contract | Observed boundary |
|---|---|---|
| Codex | native | command string becomes shell -c/-lc R |
| SWE-agent | raw | agent action enters a persistent Bash session |
| LangChain | native | structured command string is written to shell stdin |
| Terminal-Bench | raw | command and key strings enter an interactive shell through tmux |
| OpenHands | native | human-readable command is tokenized to argv; spawn has no shell |
| AutoGen | native | generated code is written to a temporary file and invoked by argv |
Notice the bottom two rows. OpenHands tokenizing to argv and AutoGen writing to a temporary file are, structurally, the two repairs from Chapter 1 — those systems have already removed the boundary. Codex's row is the one that matters for this paper: a command string that later becomes shell -c R. And the contract the model was given said nothing about that.
shell -c, one writes it to a shell's stdin, one tokenizes it to argv with no shell at all. Knowing that a system "uses tool calls" tells you nothing about how many parsers the payload crosses. That is why the paper insists on reporting the contract and the path, and why a single word like "native" is not a specification.The design is easier to trust once you see how little code it is. Generation happens once; everything after that is replay.
python CONTRACTS = {"R": RAW_CLAUSE, "N": DISCLOSED_CLAUSE} # differ by ONE sentence TRANSPORTS = {"R": run_raw, "N": run_nested} # differ by ONE parser # ---- phase 1: generate once, in ONE serving window, order randomized ---- replies = {} for task in TASKS: # 56 tasks for g in CONTRACTS: # 2 contracts replies[(task.id, g)] = model(CONTRACTS[g], task.instruction) # ---- phase 2: replay. Zero model calls from here on. ---- Y = {} for task in TASKS: for g in CONTRACTS: R = replies[(task.id, g)] for t in TRANSPORTS: # SAME bytes, two paths work = task.fresh_fixture() # built without a shell TRANSPORTS[t](R, cwd=work, timeout=15) Y[(task.id, g + t)] = task.validate(work) # ---- phase 3: the decomposition, per family, in percentage points ---- def rate(cell, fam): ts = [t for t in TASKS if t.family == fam] return 100 * sum(Y[(t.id, cell)] for t in ts) / len(ts) for fam in FAMILIES: # 14 families = the inferential units damage = rate("RN", fam) - rate("RR", fam) comp = rate("NN", fam) - rate("RN", fam) gap = rate("NN", fam) - rate("RR", fam) assert abs(gap - (damage + comp)) < 1e-9 # the identity, per family
Three details in that loop are the difference between a measurement and an anecdote, and each corresponds to a sentence in the paper.
| Line | Why it is there |
|---|---|
| generation happens in one serving window, randomized | hosted deployments drift; a cell generated on Tuesday and a cell generated on Thursday are not a controlled comparison. The mechanism analysis uses only the same-window configurations, and "no off-diagonal cell is reconstructed across serving windows" |
task.fresh_fixture() inside the innermost loop | a command that leaves a file behind would change the starting state of the next replay. Fresh fixture, trimmed environment, 15-second timeout, collateral checks |
the assert | the identity is verified per task before aggregation, so a bug in the rate function cannot quietly produce a decomposition that does not add up |
And the economics are the reason so many robustness checks exist. Phase 1 is 56 × 2 = 112 model calls per configuration. Phase 2 is free. Every extra transport — escaped, temporary script, real ssh, JSON serializer, single-quote wrapper — is another pass over the stored replies at the cost of container time. That is how one paper affords a real-ssh grounding, a grammar crossover, a JSON boundary study, two userlands, and a script-bypass replication.
The native contract sits slightly outside the 2×2 and it is easy to skip past. Its purpose is to isolate the model-facing representation from the execution path: QuoteBench extracts the command field from the provider's shell-tool call and runs that string on the same raw path as the raw contract. Same transport, different way of asking.
command field is extracted and executed identically. Any difference is attributable to the representation the model was writing into.The paper is upfront that the native comparison is not as clean as the crossed one — the native contract also mentions a Bash script payload, a difference it folds into a declared total-effect estimand rather than pretending the prompts are otherwise identical. Chapter 9 reports what that study found; the point here is that "how you ask" and "how it runs" are two knobs, and this paper turns each one separately.
Now the numbers. This chapter is one table and its consequences, worked slowly, because every claim in the paper's abstract lives inside it.
Eight configurations, collected in one randomized serving window with the effort field omitted, each contributing 56 raw-contract replies and 56 disclosed-boundary replies. Every reply replayed through both transports. Cells are pass rates in percent; effects are percentage points.
| Model | RR | RN | NR | NN | Damage | Comp. | Matched gap |
|---|---|---|---|---|---|---|---|
| GPT-5.6-sol | 94.6 | 30.4 | 55.4 | 91.1 | −64.3 | +60.7 | −3.6 |
| GPT-5.5 | 100.0 | 28.6 | 50.0 | 89.3 | −71.4 | +60.7 | −10.7 |
| Opus-5 | 96.4 | 30.4 | 42.9 | 89.3 | −66.1 | +58.9 | −7.1 |
| Gemini-3.1-Pro | 98.2 | 25.0 | 33.9 | 80.4 | −73.2 | +55.4 | −17.9 |
| Gemini-3.5-Flash | 96.4 | 28.6 | 67.9 | 58.9 | −67.9 | +30.4 | −37.5 |
| Opus-4.8 | 91.1 | 26.8 | 62.5 | 57.1 | −64.3 | +30.4 | −33.9 |
| Qwen3.5-27B | 85.7 | 30.4 | 83.9 | 30.4 | −55.4 | 0.0 | −55.4 |
| Gemini-3.1-Flash-Lite | 78.6 | 19.6 | 80.4 | 14.3 | −58.9 | −5.4 | −64.3 |
Convert the whole RR column back to counts to see what you are looking at. Multiply by 56 and round:
And the RN column: 17, 16, 17, 14, 16, 15, 17, 11, totalling 123. So of 415 commands that worked when executed directly, 123 survived the added parser and 292 did not. The 33 commands that already failed on the raw path (448 − 415) stayed failed — the parser rescues nothing, which is exactly what a clean one-directional intervention should look like.
Per-configuration retention, which the paper reports as 25.0–35.4%, is a division you can do in your head at both ends:
That last observation is worth a paragraph because it is counter-intuitive and it explains the shape of the damage column. Damage ranges from −55.4 (Qwen3.5-27B) to −73.2 (Gemini-3.1-Pro), and it is anti-correlated with raw ability: the highest raw scorers take the biggest hits.
The mechanism is not mysterious. A model that solves hostile payloads correctly does so by quoting them properly — single quotes, splices, printf with a literal format. Those are precisely the constructions that contain $, backticks, backslashes and embedded quotes, which are precisely what the outer double-quoted parser consumes. Competence on the raw path is exposure on the nested path. A model that solves only 48 of 56 tasks had fewer correct-but-fragile commands to lose.
Chapter 0 quoted the control-task loss; here is why it is the most alarming number in the paper. The 14 controls are the benign tier — no hostile characters, ordinary operations. Under the added parser the eight configurations lose 28.6–57.1 points on the controls alone, which in counts is 4 to 8 tasks of 14.
Gemini-3.5-Flash makes it concrete. At the fixed same-window setting used for the crossover it passes 54 of 56 tasks in RR — near perfect — and only 8 of 14 control tasks in NN. Six of fourteen ordinary, hazard-free operations, failed on the deployed path, by a model that had essentially solved the benchmark on the direct path.
The paper's one-line explanation: "models emit double-quote-active characters even for ordinary commands." You do not need a hostile payload to write grep "TODO" src/*.py or echo "done". You just need to write shell.
The obvious worry is that a single pathological family is carrying the entire effect. The paper closes this two ways.
Leave-one-family-out. Drop each of the 14 families in turn and recompute. Every one of the 8 × 14 = 112 leave-one-family-out estimates of transport damage remains negative. There is no family whose removal makes the effect disappear, or even change sign.
An exact enumerated test. Because the families are purposively constructed rather than sampled, the paper uses a family-sign symmetry null: conditional on the observed effect magnitudes, positive and negative signs are exchangeable. With 14 families that is 214 = 16,384 sign assignments, enumerable exactly — note that the smallest reported p-value, .000122, is 2 ÷ 16,384, the two-sided probability of the most extreme assignment. Holm's step-down correction is then applied across the eight models.
| Model | Damage [95% CI] | Enumerated p | Holm-adjusted p |
|---|---|---|---|
| Gemini-3.1-Pro | −73.2 [−87.5, −58.9] | .000122 | .000977 |
| Gemini-3.1-Flash-Lite | −58.9 [−71.4, −48.2] | .000122 | .000977 |
| GPT-5.5 | −71.4 [−85.7, −55.4] | .000244 | .001465 |
| Opus-5 | −66.1 [−82.1, −50.0] | .000244 | .001465 |
| Gemini-3.5-Flash | −67.9 [−82.1, −51.8] | .000244 | .001465 |
| GPT-5.6-sol | −64.3 [−80.4, −46.4] | .000244 | .001465 |
| Opus-4.8 | −64.3 [−80.4, −46.4] | .000244 | .001465 |
| Qwen3.5-27B | −55.4 [−69.6, −41.1] | .000244 | .001465 |
The intervals come from a percentile bootstrap of the mean over families as units, 10,000 replicates. The largest adjusted p is .001465. Every interval excludes zero by a wide margin — the closest, Qwen3.5-27B, still has its upper end at −41.1 points.
There is a fourth quantity you can build from the four cells: the generation-by-transport interaction, (NN − NR) − (RN − RR). It asks whether the disclosed contract helps more on the nested path than on the raw path. Work it for GPT-5.6-sol in tasks first, since the arithmetic is cleaner:
An interaction of a full hundred points. The paper reports the range across the eight configurations as −7.1 to +119.6, with the maximum at Gemini-3.1-Pro:
and the minimum at Gemini-3.1-Flash-Lite, which is the only configuration where disclosure makes things slightly worse in both directions:
A large positive interaction means the boundary-aware contract does not make the model generically better at shell — it makes it better at that boundary specifically, and Chapter 5 shows it makes it measurably worse everywhere else.
Eight models means eight tests, and running eight tests at α = .05 gives you roughly a one-in-three chance of at least one false positive by luck alone. Holm's step-down procedure fixes that, and it is simple enough to do on paper — which is worth doing once, because you will then recognise a Holm-adjusted column forever.
Sort the raw p-values ascending. Multiply the smallest by m = 8, the next by 7, the next by 6, and so on. Then enforce monotonicity by taking a running maximum, so an adjusted value can never be smaller than one before it.
| Rank k | Raw p | Multiplier (m − k + 1) | Product | After running max = reported |
|---|---|---|---|---|
| 1 | .000122 | × 8 | .000977 | .000977 |
| 2 | .000122 | × 7 | .000854 | .000977 |
| 3 | .000244 | × 6 | .001465 | .001465 |
| 4 | .000244 | × 5 | .001221 | .001465 |
| 5–8 | .000244 | × 4 … × 1 | .000977 … .000244 | .001465 (carried by the running max) |
Which reproduces the paper's two distinct reported values exactly: .000977 for the two smallest and .001465 for the rest. The running-max step is doing real work here — without it, rank 2 would report .000854, smaller than rank 1, which is incoherent because a less extreme observation cannot be more significant.
Note also what the raw p-values are made of. With 14 families there are 214 = 16,384 sign assignments, so the finest achievable two-sided p is 2 ÷ 16,384 = .000122 — the case where the observed assignment and its exact mirror are the only ones at least as extreme. The value .000244 is 4 ÷ 16,384, and .000488 is 8 ÷ 16,384. Every p-value in the table is a small integer over 16,384, which is what an exact enumerated test looks like when you meet one.
Statistical significance here is almost beside the point — every effect is 55 points or more, and no reasonable amount of noise produces that. The engineering content is in the ordering and the spread. Sort the eight configurations by damage and put raw score beside it:
| Model | RR (tasks) | Damage | Fragile commands lost | Retained |
|---|---|---|---|---|
| Gemini-3.1-Pro | 55 | −73.2 | 41 | 14 (25.5%) |
| GPT-5.5 | 56 | −71.4 | 40 | 16 (28.6%) |
| Gemini-3.5-Flash | 54 | −67.9 | 38 | 16 (29.6%) |
| Opus-5 | 54 | −66.1 | 37 | 17 (31.5%) |
| GPT-5.6-sol | 53 | −64.3 | 36 | 17 (32.1%) |
| Opus-4.8 | 51 | −64.3 | 36 | 15 (29.4%) |
| Gemini-3.1-Flash-Lite | 44 | −58.9 | 33 | 11 (25.0%) |
| Qwen3.5-27B | 48 | −55.4 | 31 | 17 (35.4%) |
The "fragile commands lost" column is just RR minus RN in tasks, and it tracks RR almost perfectly: the correlation is visible by eye. The retention column, which normalises by how many the model had to lose, is much flatter — 25% to 35% for every configuration in the table, weak and strong alike. That is the honest summary of what the parser does: roughly seven in ten working commands die, regardless of who wrote them.
Damage is the depressing half. This chapter is the surprising half: tell a capable model where its command is going to run — one sentence, no advice — and it rewrites its commands into a form that survives. Sometimes it recovers nearly everything it lost.
Compensation is NN − RN: hold the nested transport fixed and compare replies written under the two contracts. Six of eight configurations recover between 30.4 and 60.7 points, every one with a family-bootstrap interval excluding zero. Two do not: Qwen3.5-27B recovers exactly 0.0, and Gemini-3.1-Flash-Lite goes backwards by 5.4.
| Model | Compensation [95% CI] | Enumerated p | Holm-adjusted p | In the supported set? |
|---|---|---|---|---|
| GPT-5.6-sol | +60.7 [+46.4, +75.0] | .000244 | .001953 | yes |
| GPT-5.5 | +60.7 [+44.6, +75.0] | .000244 | .001953 | yes |
| Opus-5 | +58.9 [+41.1, +75.0] | .000488 | .002930 | yes |
| Gemini-3.1-Pro | +55.4 [+33.9, +73.2] | .001221 | .006104 | yes |
| Opus-4.8 | +30.4 [+14.3, +48.2] | .003906 | .015625 | yes |
| Gemini-3.5-Flash | +30.4 [+12.5, +48.2] | .013672 | .041016 | yes |
| Qwen3.5-27B | 0.0 [0.0, 0.0] | 1.000000 | 1.000000 | no |
| Gemini-3.1-Flash-Lite | −5.4 [−10.7, 0.0] | .250000 | .500000 | no |
A configuration joins the supported positive-compensation set when three things hold at once: the effect is positive, its Holm-adjusted p is at most .05, and every leave-one-family-out estimate stays positive. Six qualify. Gemini-3.5-Flash squeaks in at .041016 — a good reminder that a criterion stated in advance is worth more than a criterion chosen after seeing the numbers.
Note also what a zero-width interval means. Qwen3.5-27B is [0.0, 0.0]: it recovers exactly zero on every family, in every bootstrap resample. It did not partially adapt. It did not adapt at all.
The sceptical reading of compensation is that the disclosed contract simply makes models write more careful shell in general, and the nested arm is where careful shell pays. The off-diagonal NR cell refutes this in one step: take those same boundary-aware replies and run them on the raw path, where there is no boundary at all.
| Model | RR (raw reply, raw path) | NR (boundary-aware reply, raw path) | Cost of adapting |
|---|---|---|---|
| GPT-5.6-sol | 53 / 56 | 31 / 56 | −22 tasks = −39.3 |
| GPT-5.5 | 56 / 56 | 28 / 56 | −28 tasks = −50.0 |
| Opus-5 | 54 / 56 | 24 / 56 | −30 tasks = −53.6 |
| Gemini-3.1-Pro | 55 / 56 | 19 / 56 | −36 tasks = −64.3 |
| Gemini-3.5-Flash | 54 / 56 | 38 / 56 | −16 tasks = −28.6 |
| Opus-4.8 | 51 / 56 | 35 / 56 | −16 tasks = −28.6 |
| Qwen3.5-27B | 48 / 56 | 47 / 56 | −1 task = −1.8 |
| Gemini-3.1-Flash-Lite | 44 / 56 | 45 / 56 | +1 task = +1.8 |
Gemini-3.1-Pro is the sharpest case: it gains 55.4 points on the nested path and loses 64.3 on the raw one. Its behaviour is now strongly conditioned on a claim about the environment. If that claim is wrong, it is worse than a model that ignored it.
Is the model actually reasoning about the stated boundary, or has it learned one reflex — "when someone mentions wrapping, add backslashes before double quotes"? The paper settles this with a second crossover, this time on the grammar.
Disclose either a double-quote wrapper or a single-quote wrapper, then replay every stored reply through both wrappers. A model with a memorised double-quote reflex will do well only on the double-quote wrapper. A model that reasons about the declared grammar will do well on whichever wrapper it was told about — the matched diagonal — and badly on the other.
| Configuration | double-disclosed on double | double-disclosed on single | single-disclosed on single | single-disclosed on double | Diagonal − anti |
|---|---|---|---|---|---|
| GPT-5.6-sol | 54 | 7 | 53 | 10 | +80.4 |
| GPT-5.5 | 49 | 8 | 54 | 8 | +77.7 |
| Opus-5 | 52 | 8 | 45 | 16 | +65.2 |
| Sonnet-4.6 | 32 | 11 | 23 | 16 | +25.0 |
| Opus-4.8 | 30 | 11 | 23 | 18 | +21.4 |
| Haiku-4.5 | 25 | 13 | 20 | 11 | +18.8 |
| Qwen3.5-27B | 17 | 11 | 11 | 17 | +0.0 |
| Gemini-3.1-Flash-Lite | 7 | 19 | 9 | 19 | −19.6 |
The denominator here is 112, since each row aggregates two arms of 56. GPT-5.6-sol:
Look at the single-disclosed column: 53 of 56 on the single-quote wrapper it was told about, 10 of 56 on the double-quote one. Nothing about a memorised double-quote defence explains that. And look at the bottom row: Gemini-3.1-Flash-Lite has a negative diagonal advantage — it does slightly better on the wrapper it was not told about, which is what noise looks like when there is no adaptation to detect.
One more decomposition, and it is the practically useful one. The disclosed contract states the boundary but gives no quoting advice. What happens if you also tell the model how to escape? The paper regenerates both the advice-free and advice-bearing contracts within one serving window, so there is no cross-window drift to confound the comparison.
| Configuration | Advice-free (of 56) | With escaping advice | Δ (points) | Tier |
|---|---|---|---|---|
| GPT-5.6-sol | 54 | 49 | −8.9 | top |
| GPT-5.5 | 49 | 53 | +7.1 | top |
| Opus-5 | 52 | 54 | +3.6 | top |
| Sonnet-4.6 | 32 | 46 | +25.0 | middle |
| Haiku-4.5 | 25 | 32 | +12.5 | middle |
| Opus-4.8 | 30 | 34 | +7.1 | middle |
| Qwen3.5-27B | 17 | 18 | +1.8 | bottom |
| Gemini-3.1-Flash-Lite | 7 | 8 | +1.8 | bottom |
Three distinct regimes, and the shape is one you should expect to see again in other capabilities.
Aggregates hide structure here too. Averaged over the eight configurations — so each family effect is over 4 tasks × 8 configurations = 32 cells, and one cell is 3.125 points — the recovery concentrates where the hazard is explicit and stalls where it is implicit.
| Family | Compensation | In cells (of 32) | Why |
|---|---|---|---|
json-write | +50.0 | 16 | the payload is visibly a quoted string; the hazard is staring at the model |
sed-replace | +46.9 | 15 | same — an embedded language with obvious delimiters to protect |
hostile-filenames | +18.8 | 6 | the hazard is in the argument, not the payload; easier to overlook |
grep-count | +15.6 | 5 | regex metacharacters look like syntax, not like data |
find-glob | −12.5 | −4 | expansion timing — disclosure makes it worse |
Verify one: +46.9 points is 15 ÷ 32 = 0.46875. And find-glob going negative is the instructive one. Glob and expansion-timing hazards are about when something expands rather than what characters are in it, so a model told "you will be wrapped in double quotes" adds escaping that changes expansion timing in the wrong direction. Being told about the boundary is not the same as understanding it.
The families that recover about half their damage are the ones where the model can see the thing that needs protecting: a JSON string literal, a sed replacement between delimiters. The families that stay broken are the ones where the hazard is a property of the evaluation order or the argument vector rather than a visible span of characters. That split is a genuine finding about what disclosure elicits, and it is more informative than the aggregate: a system builder who only writes files and edits JSON gets most of the benefit, and one who does bulk renames and recursive searches gets almost none.
The paper does not publish reply diffs, but the numbers constrain the answer tightly, and it is worth reasoning it through because it explains both the gain and the cost.
On the raw path, the winning strategy is single quotes: they make everything inert in one step, and they are what a correct solution to a hostile payload looks like. Under a disclosed double-quote wrapper that strategy is worthless, because single quotes do not survive the outer context. The model must instead produce a string that, after the outer shell has performed its expansions and quote removal, still constitutes the intended program. Concretely that means pre-escaping every character the outer parser treats as special — $, backtick, backslash, " — so they arrive at the inner shell as literals.
the same intent under two contracts # raw contract — single quotes make everything inert printf '%s\n' 'cost: $5 "x"' > out.txt # disclosed contract — the reply must SURVIVE one round of double-quote # parsing first, so the specials are escaped for the OUTER shell printf '%s\n' 'cost: \$5 \"x\"' > out.txt
Now the NR result is not surprising at all. Run that second command on the raw path and the backslashes never get consumed by anyone: the file receives cost: \$5 \"x\". Wrong bytes. The reply is not a more careful version of the first — it is a different program, correct against a different machine.
GPT-5.6-sol loses 8.9 points — five tasks — when the contract adds escaping advice on top of the boundary disclosure. That is the single most counter-intuitive number in the paper and it has a clean reading.
The advice-free disclosed contract states a fact about the environment and leaves the strategy open. A model that can already reason from "I will be inside double quotes" to a correct encoding chooses whichever encoding fits the payload — and different payloads want different encodings. Adding prescriptive escaping advice narrows that search: the model now follows the recommended pattern even where a different one would have been correct. The paper's framing is exactly this: "Disclosure alone already elicits the adaptation," and at the top of the ladder the added instruction "barely moves matched nested success."
Meanwhile the middle tier gains the most — Sonnet-4.6 +25.0 points, fourteen tasks. Those models can execute a stated procedure but were not deriving it from the environment description alone. And the bottom tier gains 1.8 points, one task, from both contracts, which is the signature of a capability ceiling rather than an information gap.
| If your model is… | Then the binding constraint is… | So the right intervention is… |
|---|---|---|
| at the top (disclosure alone gives 89–91% nested) | knowing the boundary exists | state the path; do not over-prescribe the encoding |
| in the middle (disclosure gives 30–57%) | knowing what to do about it | state the path and the escaping strategy |
| at the bottom (disclosure gives 14–30%) | capability | fix the harness — escape at the boundary or send a script |
That table is the practical distillation of the whole chapter, and note where it lands: for two of the three tiers, the answer involves changing your own code rather than your prompt.
Two large effects with opposite signs. This chapter is about what happens when they are nearly equal, which is where the paper's title comes from and where the practical damage to evaluation happens.
The paper offers a descriptive criterion — explicitly "one illustrative reading aid (not a fitted criterion)" — for calling a configuration masked: the matched gap is small while both components are large.
GPT-5.6-sol at the same-window setting meets all three: |−3.6| ≤ 5, −64.3 ≤ −40, +60.7 ≥ +30. And the identity closes exactly: −3.6 = −64.3 + 60.7.
Across the 30 rung-level crossovers the paper measured, ten meet the same cut — and all ten sit at the tops of their ladders. That is not an accident. Masking requires large compensation, compensation is a frontier capability, and frontier capability shows up at high effort settings.
Opus-4.8's effort ladder is the demonstration, because it is the case where matched success genuinely improves and the improvement means something different from what it looks like. Two rungs, low and max, with the disclosed contract:
| Rung | RR | RN | NN | Damage | Matched gap |
|---|---|---|---|---|---|
| low | 87.5 | 28.6 | 39.3 | −58.9 | −48.2 |
| max | 98.2 | 30.4 | 94.6 | −67.9 | −3.6 |
| change | +10.7 | +1.8 | +55.4 | −9.0 | +44.6 |
Reconstruct those from the identity to convince yourself. At low, matched nested success is 39.3 and the matched gap is −48.2, so RR = 39.3 + 48.2 = 87.5. Damage is −58.9, so RN = 87.5 − 58.9 = 28.6. At max, NN = 94.6 and the gap is −3.6, so RR = 98.2; damage is −67.9, so RN = 98.2 − 67.9 = 30.4.
Now read the RN column. It moved from 28.6 to 30.4 — one task. Turning the effort dial from low to max moved the matched gap by 44.6 points and moved cross-path portability by 1.8.
Run the criterion across all eight same-window configurations and it separates them into three genuinely different situations. This is worth doing explicitly, because "masked" is not a synonym for "has a large damage number" — every configuration has a large damage number.
| Model | |gap| ≤ 5? | damage ≤ −40? | comp ≥ +30? | Verdict |
|---|---|---|---|---|
| GPT-5.6-sol | 3.6 — yes | −64.3 — yes | +60.7 — yes | masked |
| Opus-5 | 7.1 — no | yes | yes | nearly masked; the gap is four tasks wide |
| GPT-5.5 | 10.7 — no | yes | yes | large cancellation, visible residue |
| Gemini-3.1-Pro | 17.9 — no | yes | yes | compensation real but incomplete |
| Opus-4.8 | 33.9 — no | yes | +30.4 — yes | partial recovery, honest number |
| Gemini-3.5-Flash | 37.5 — no | yes | +30.4 — yes | partial recovery, honest number |
| Qwen3.5-27B | 55.4 — no | yes | 0.0 — no | no adaptation; the gap is the damage |
| Gemini-3.1-Flash-Lite | 64.3 — no | yes | −5.4 — no | no adaptation; gap slightly exceeds damage |
Look at the bottom two rows and something clarifying appears: for a model that does not compensate, the matched gap is an honest report of transport damage. Qwen3.5-27B's −55.4 gap is exactly its −55.4 damage, because compensation is precisely zero. The benchmark tells the truth about the weak models and hides the truth about the strong ones. Masking is a frontier phenomenon.
The obvious response is to adopt the criterion as a rule: flag any configuration meeting those three inequalities. The paper deliberately does not do that, and its reason is worth adopting. The cut points — 5, −40, +30 — are arbitrary. Opus-5's gap is 7.1, which is four tasks; is that meaningfully different from GPT-5.6-sol's two tasks? The criterion says yes and reality says barely.
The real fix is not a better threshold. It is to stop reducing three numbers to one. If you report damage, compensation and the matched gap side by side, nobody needs a masking rule, because there is nothing left to mask.
Three configurations with complete rung-level crossovers. RR is direct-path success, RN is the nested-replay pass rate of the same raw-contract replies, NN is matched nested success. The shaded band is the masked region — matched gap within 5 points of zero. Toggle the RN line off and on: it is the flat one, and it is the one nobody reports.
The paper's summary of this figure is one sentence and it is worth memorising: across the observed trial-0 effort rungs, the unconditional nested-replay pass rate stays between 23.2% and 33.9%, and moves by at most 5.4 points within any one ladder. Five point four points is three tasks. That is the entire range of portability improvement available from every effort dial the providers expose.
Check it on GPT-5.6-sol, whose four rungs give RN values of 28.6, 30.4, 32.1, 30.4. Highest minus lowest is 3.6 points, or two tasks. On Opus-5's five rungs: 28.6, 32.1, 30.4, 32.1, 32.1 — again 3.6. On Gemini-3.1-Pro's three: 25.0, 26.8, 26.8 — 1.8 points, one task.
Put the two observations together and the mechanism of masking is fully explained. The matched gap is NN − RR. Damage is roughly constant across a ladder, so RN is roughly constant. Therefore:
And the interior of these ladders is not monotone, which is a separate warning. Opus-5 at low is 60.7, medium 91.1, high 96.4, xhigh 100.0, max 98.2 — the max rung is worse than xhigh by one task. GPT-5.5 runs 94.6, 92.9, 91.1, 100.0: three rungs of decline and then a jump. If you tune effort by picking the highest label you will sometimes be picking a worse operating point.
The claim is easier to believe when you can see all four cells at every rung rather than a summary. Asterisks mark rungs meeting the descriptive masking criterion.
| Configuration | Rung | RR | RN | NR | NN | Damage | Comp. | Matched gap |
|---|---|---|---|---|---|---|---|---|
| GPT-5.6-sol | low | 98.2 | 28.6 | 53.6 | 91.1 | −69.6 | +62.5 | −7.1 |
| GPT-5.6-sol | medium | 94.6 | 30.4 | 48.2 | 92.9 | −64.3 | +62.5 | −1.8 * |
| GPT-5.6-sol | high | 98.2 | 32.1 | 48.2 | 98.2 | −66.1 | +66.1 | +0.0 * |
| GPT-5.6-sol | xhigh | 98.2 | 30.4 | 51.8 | 98.2 | −67.9 | +67.9 | +0.0 * |
| Opus-5 | low | 98.2 | 28.6 | 57.1 | 60.7 | −69.6 | +32.1 | −37.5 |
| Opus-5 | medium | 100.0 | 32.1 | 41.1 | 91.1 | −67.9 | +58.9 | −8.9 |
| Opus-5 | high | 96.4 | 30.4 | 42.9 | 96.4 | −66.1 | +66.1 | +0.0 * |
| Opus-5 | xhigh | 98.2 | 32.1 | 42.9 | 100.0 | −66.1 | +67.9 | +1.8 * |
| Opus-5 | max | 100.0 | 32.1 | 46.4 | 98.2 | −67.9 | +66.1 | −1.8 * |
| Gemini-3.1-Pro | low | 100.0 | 25.0 | 32.1 | 91.1 | −75.0 | +66.1 | −8.9 |
| Gemini-3.1-Pro | medium | 98.2 | 26.8 | 41.1 | 91.1 | −71.4 | +64.3 | −7.1 |
| Gemini-3.1-Pro | high | 98.2 | 26.8 | 35.7 | 91.1 | −71.4 | +64.3 | −7.1 |
Three readings, top to bottom. GPT-5.6-sol is masked at three of its four rungs — its reported gap is −1.8, +0.0, +0.0 while damage sits at −64 to −68 the whole way. Opus-5 is unmasked at its two cheapest rungs and masked at its three most expensive, which is the "masking lives at ladder tops" pattern in a single row group. And Gemini-3.1-Pro is masked at none of them, because its compensation never quite catches its damage — its NN is pinned at exactly 91.1 across all three rungs while RR sits at 98–100.
Now scan the NR column, which is the one nobody would think to look at. For GPT-5.6-sol it runs 53.6, 48.2, 48.2, 51.8 — the model's boundary-aware replies get worse on the raw path as effort rises from low to medium, then recover. Effort makes the targeting sharper, and sharper targeting is more wrong when aimed at the wrong platform.
Every provider now exposes a knob labelled with words like low, medium, high, xhigh, max. It is enormously tempting to treat those labels as a common axis — to compare "model A at high" with "model B at high" as though the two were spending the same budget. QuoteBench measured what the labels actually do, and the answer is: something different for every provider, sometimes non-monotone, sometimes nothing at all.
Matched-nested success on the 56-task core under the disclosed-boundary contract, trial 0, with the provider-reported mean output tokens per task alongside — including reported hidden reasoning.
| Model | Settings, in order | Success (%) | Mean output tokens |
|---|---|---|---|
| GPT-5.6-sol | low / medium / high / xhigh | 91.1 / 92.9 / 98.2 / 98.2 | 362 / 565 / 773 / 1,073 |
| GPT-5.5 | low / medium / high / xhigh | 94.6 / 92.9 / 91.1 / 100.0 | 507 / 655 / 1,164 / 2,757 |
| Opus-5 | low / medium / high / xhigh / max | 60.7 / 91.1 / 96.4 / 100.0 / 98.2 | 796 / 1,336 / 1,458 / 2,421 / 3,499 |
| Fable-5 | low / medium / high / xhigh / max | 71.4 / 75.0 / 96.4 / 92.9 / 100.0 | 332 / 569 / 843 / 1,212 / 2,396 |
| Opus-4.8 | low / medium / high / xhigh / max | 39.3 / 48.2 / 50.0 / 62.5 / 94.6 | 835 / 1,291 / 1,706 / 3,481 / 6,960 |
| Gemini-3.1-Pro | low / medium / high | 91.1 / 91.1 / 91.1 | 5,267 / 5,753 / 6,308 |
| Sonnet-4.6 | low / medium / high / xhigh | 23.2 / 28.6 / 64.3 / 62.5 | 28 / 1,411 / 4,337 / 4,539 |
| Gemini-3.5-Flash | minimal / low / medium / high | 57.1 / 58.9 / 64.3 / 62.5 | 3,851 / 3,108 / 3,081 / 3,389 |
| Haiku-4.5 | low / medium / high / xhigh | 32.1 / 37.5 / 32.1 / 26.8 | 5,432 / 4,717 / 4,708 / 4,783 |
| Qwen3.5-27B | non-thinking / thinking | 28.6 / 28.6 | 20 / 7,489 |
| Gemini-3.1-Flash-Lite | minimal / low / medium / high | 14.3 / 14.3 / 14.3 / 14.3 | 20 / 20 / 20 / 20 |
Read down the token column before the success column, because the token column is the one that destroys cross-model comparison. GPT-5.6-sol at high spends 773 tokens. Gemini-3.1-Pro at low spends 5,267 — nearly seven times more — and Opus-4.8 at max spends 6,960, which is nine times GPT-5.6-sol's high.
1. It goes down. Haiku-4.5: 32.1, 37.5, 32.1, 26.8 across low, medium, high, xhigh. The best setting is medium and the worst is the highest label. Its token means are also non-monotone — 5,432, 4,717, 4,708, 4,783 — and because those means are strongly right-skewed the paper also reports the medians: 1,206, 1,560, 936, 1,283. The non-monotone budget ordering survives the robust summary, so it is not one runaway generation dragging an average.
2. It goes down and then jumps. GPT-5.5 declines through low, medium, high (94.6 → 92.9 → 91.1) and then reaches 100.0 at xhigh. Two of its labelled rungs are worse than its cheapest one. A tuner that tries low and medium and concludes "effort does not help here" would stop one rung before the perfect score.
3. It does nothing. Gemini-3.1-Pro is 91.1 at every one of its three rungs, at 5,267 to 6,308 tokens. You can pay 20% more tokens for identically zero improvement.
4. It is not real. Gemini-3.1-Flash-Lite returns byte-identical replies at all four settings, at 20 tokens each. The paper retains it in the tables "only to document that the provider did not expose a usable ladder." Four labels; one behaviour. Qwen3.5-27B's think toggle is the mirror image: 20 tokens versus 7,489 tokens — a 375× difference in spend — for the same 28.6% score.
Two of the eleven rows in that table do not expose an effort ladder in any meaningful sense, and both are instructive about what the label is hiding.
The think toggle. Qwen exposes a binary rather than a multi-rung parameter, and the measurement is startling: 28.6% non-thinking at 20 mean output tokens, 28.6% thinking at 7,489. Identical score, 375 times the spend. Twenty tokens is barely a command; 7,489 is a long deliberation. Whatever the model does with those 7,469 extra tokens, it does not change how many of the 56 tasks reach the correct final state. And the crossover table backs this up from a different direction — Qwen3.5-27B is one of the two configurations with exactly zero contract-conditioned compensation, so more thinking is not buying boundary reasoning either.
The rung that is barely a generation. Sonnet-4.6's low setting averages 28 output tokens and scores 23.2%. Its high setting averages 4,337 and scores 64.3%. A 28-token mean means most replies are a single short command with no deliberation at all — which is a perfectly legitimate operating point, and one you would never guess from a label that reads "low" rather than "essentially no reasoning budget."
Most production code never sets the effort field at all. So what do you get? The paper calibrated the unset arm against each model's labelled ladder, and the answer is different for every provider.
| Model | Unset (%) | Nearest labelled rung | Distance to that model's lowest rung |
|---|---|---|---|
| GPT-5.6-sol | 91.1 | low | 0.0 |
| GPT-5.5 | 89.3 | high | −5.4 |
| Opus-5 | 89.3 | medium | +28.6 |
| Gemini-3.1-Pro | 80.4 | none within the ladder | −10.7 |
| Gemini-3.5-Flash | 58.9 | low | +1.8 |
| Opus-4.8 | 57.1 | xhigh | +17.9 |
| Gemini-3.1-Flash-Lite | 14.3 | all four rungs tie | 0.0 |
Opus-4.8's default sits near xhigh; Opus-5's sits near medium; Gemini-3.1-Pro's falls below its entire measured ladder, 10.7 points under its own lowest rung. Three defaults, three completely different places on three different ladders. If you compare two models with the effort field omitted, you are comparing two arbitrary and undisclosed operating points.
If the labels are meaningless, the tokens are not. Divide the improvement by the spend and the ladders sort themselves into shapes that are actually decision-relevant. Take each model's cheapest and most expensive measured rungs:
| Model | Cheapest rung | Most expensive rung | Extra tokens | Points gained | Points per 1k extra tokens |
|---|---|---|---|---|---|
| GPT-5.6-sol | 91.1 @ 362 | 98.2 @ 1,073 | 711 | +7.1 | 10.0 |
| Fable-5 | 71.4 @ 332 | 100.0 @ 2,396 | 2,064 | +28.6 | 13.9 |
| Opus-5 | 60.7 @ 796 | 98.2 @ 3,499 | 2,703 | +37.5 | 13.9 |
| GPT-5.5 | 94.6 @ 507 | 100.0 @ 2,757 | 2,250 | +5.4 | 2.4 |
| Opus-4.8 | 39.3 @ 835 | 94.6 @ 6,960 | 6,125 | +55.3 | 9.0 |
| Gemini-3.1-Pro | 91.1 @ 5,267 | 91.1 @ 6,308 | 1,041 | 0.0 | 0.0 |
| Haiku-4.5 | 32.1 @ 5,432 | 26.8 @ 4,783 | −649 | −5.3 | n/a — cheaper and worse |
Two rows are worth staring at. Opus-4.8 gains 55.3 points, the largest movement in the table, and pays 6,125 extra tokens for it — but Chapter 6 already showed that essentially all of that gain is contract-conditioned compensation, not portability. You are buying a number, not a capability, unless your deployment discloses the boundary. And Gemini-3.1-Pro's row is the cleanest waste in the paper: 1,041 extra tokens, zero points, three times over.
There is one more trap, and it combines this chapter with Chapter 6. Suppose you tune effort on the matched nested score, which is the natural thing to do if that is your deployment configuration. You will find a rung that maximises it — and Chapter 6 showed that the maximising rung is very likely the masked one, since masking happens where compensation is largest. So the standard tuning procedure systematically selects operating points whose reported number is the least informative about cross-path behaviour.
It is worth spelling out, because it is the difference between a paper you can trust and one you cannot. QuoteBench runs many campaigns — a same-window sweep, ladder sweeps, three-draw repeats, a native-tool campaign of 8,736 generations, private-payload crossovers, a real-ssh grounding replay, an advice arm, a grammar crossover, a JSON boundary replay. Each has a declared design and a declared role.
| Campaign | Design | What it is allowed to support |
|---|---|---|
| Study A same-window sweep | 8 configs × 56 tasks × 2 contracts, one randomized window, effort unset | the causal mechanism claims — damage, compensation, interaction |
| Study A ladder sweep | 44 rungs, 11 configs, per-provider windows | descriptive operating-point comparison only |
| Study A rung crossover | 30 rungs, 7 configs, 26 crossover points, replay both transports | the masking-versus-effort picture, one stored generation per rung |
| Study B native tool | 8,736 generations, 17,472 replays, observational | exploratory contrast between raw and native contracts |
| Private-v2 crossover | 2 models × 42 unpublished hostile payloads, one serving window | transfer of the mechanism to unseen literals |
Real-ssh grounding | 8 configs × 56, ssh localhost replay, zero model calls | that the synthetic boundary behaves like a real one |
Every replay campaign is a zero-call execution of stored replies in the pinned container. That is what makes so many robustness checks affordable: the expensive part, generation, was paid once.
high and model B at high and A wins. What have you learned?If damage and compensation differed by a constant across models, none of this would matter for model selection — every model would shift by the same amount and the ranking would hold. They do not. Compensation ranges from −5.4 to +60.7. So the ranking moves.
Rank correlations tend to arrive as a number with no visible derivation. This one is small enough to do completely, and doing it recovers every claim the paper makes about the reordering. Label the eight configurations and write down their two scores in tasks:
| Model | RR | NN | |
|---|---|---|---|
| A | GPT-5.6-sol | 53 | 51 |
| B | GPT-5.5 | 56 | 50 |
| C | Opus-5 | 54 | 50 |
| D | Gemini-3.1-Pro | 55 | 45 |
| E | Gemini-3.5-Flash | 54 | 33 |
| F | Opus-4.8 | 51 | 32 |
| G | Qwen3.5-27B | 48 | 17 |
| H | Gemini-3.1-Flash-Lite | 44 | 8 |
A pair is concordant if the two columns order it the same way, discordant if they disagree, and tied if either column gives the pair the same value. Go through all 8 × 7 ÷ 2 = 28 pairs. Ties first, because there are only two:
Now the disagreements. A is behind B, C, D and E on RR and ahead of all four on NN — four discordant pairs. C is behind D on RR (54 versus 55) and ahead on NN (50 versus 45) — one more. Every other pair agrees.
And Kendall's τ is the concordant-minus-discordant difference over the number of pairs:
Which is the paper's reported value, and the five discordant pairs are exactly the five reversals it names: GPT-5.6-sol against Gemini-3.5-Flash, Gemini-3.1-Pro, GPT-5.5 and Opus-5, and Opus-5 against Gemini-3.1-Pro. The "26 of 28 strictly comparable" figure is the two ties removed. Every published number in this analysis falls out of eight pairs of integers.
Take the same-window crossover table and sort it twice: once by RR, the direct-path score, and once by NN, the deployed-path score. Same models, same tasks, same window, same validators.
Left column: models ordered by direct-path success (RR). Right column: the same models ordered by deployed-path success (NN). Ribbons that cross are pairs whose order reversed. Tap a model to trace it.
The headline reversal is GPT-5.6-sol versus Gemini-3.5-Flash, and it is worth doing in counts because the asymmetry is startling:
Eighteen tasks is 32.1 percentage points. A one-task deficit on the path you measured becomes a thirty-two-point lead on the path you deploy. If you selected on RR you did not make a marginal mistake; you inverted a large difference.
The paper quantifies the agreement between the two orderings with Kendall's rank correlation: τ = 0.57, with a task-cluster bootstrap 95% interval of [0.32, 0.82] that excludes perfect agreement. With eight models there are 8 × 7 ÷ 2 = 28 pairs, and τ is the concordant-minus-discordant fraction, so τ = 0.57 corresponds to roughly 22 concordant against 6 discordant pairs.
Two further statements, and the difference between them matters:
| Statement | What it means |
|---|---|
| 22 of 28 pairwise orderings are stable in at least 95% of bootstrap resamples | most of the leaderboard is a genuine, bootstrap-supported partial order — not noise |
| 26 of 28 pairs are strictly comparable in the trial-0 draws | two pairs are tied under one of the matched contracts and so cannot reverse |
| Five of those 26 reverse between RR and NN | GPT-5.6-sol versus Gemini-3.5-Flash, Gemini-3.1-Pro, GPT-5.5 and Opus-5; and Opus-5 versus Gemini-3.1-Pro |
| One reversal is unambiguous at this resolution | the other four rest on a single-task margin on at least one side. The count itself is uncertain: bootstrap mean 4.6, 95% interval [1, 8] of 28 |
You can locate the two tied pairs yourself from the crossover table. Under RR, Opus-5 and Gemini-3.5-Flash both score 54 of 56. Under NN, GPT-5.5 and Opus-5 both score 50 of 56. That is 2 of 28 pairs non-comparable, leaving 26 — the arithmetic closes.
Turn it into a decision. You must pick one model. Two selection rules:
The paper is careful not to oversell this: "The regret is small at the saturated frontier, but the reversed top rank." That is the right size of claim. The point is not that path-blind selection is catastrophic; it is that the number you selected on did not contain the information you needed, and you had no way to know.
Separately from the mechanism analysis, the paper reports each base model at its best measured operating point — a within-model maximum over single-trial rungs. The Hostile LOFO column is a family jackknife, not a confidence interval: the minimum and maximum hostile success across the 14 leave-one-family-out slices.
| Model | Best observed setting | Control | Hostile | All 56 (%) | Hostile LOFO (%) |
|---|---|---|---|---|---|
| GPT-5.5 | xhigh | 14/14 | 42/42 | 100.0 | [100.0, 100.0] |
| Opus-5 | xhigh | 14/14 | 42/42 | 100.0 | [100.0, 100.0] |
| Fable-5 | max | 14/14 | 42/42 | 100.0 | [100.0, 100.0] |
| GPT-5.6-sol | high | 14/14 | 41/42 | 98.2 | [97.4, 100.0] |
| Opus-4.8 | max | 12/14 | 41/42 | 94.6 | [97.4, 100.0] |
| Gemini-3.1-Pro | low | 14/14 | 37/42 | 91.1 | [87.2, 89.7] |
| Sonnet-4.6 | high | 9/14 | 27/42 | 64.3 | [61.5, 69.2] |
| Gemini-3.5-Flash | medium | 10/14 | 26/42 | 64.3 | [59.0, 66.7] |
| Haiku-4.5 | medium | 8/14 | 13/42 | 37.5 | [28.2, 33.3] |
| Qwen3.5-27B | non-think | 8/14 | 9/42 | 30.4 | [15.4, 23.1] |
| Qwen3.5-4B | think | 5/14 | 7/42 | 21.4 | [10.3, 17.9] |
| Qwen3.5-9B | non-think | 5/14 | 5/42 | 17.9 | [5.1, 12.8] |
| Gemini-3.1-Flash-Lite | default | 6/14 | 2/42 | 14.3 | [2.6, 5.1] |
Verify one row and the jackknife stops being mysterious. GPT-5.6-sol misses exactly one hostile task out of 42. Dropping a family removes 3 hostile tasks, leaving 39:
which is exactly the reported [97.4, 100.0]. Now Sonnet-4.6, which passes 27 of 42 hostile tasks and therefore misses 15. If the dropped family had all three of its hostile tasks passing, the slice is 24/39 = 61.5%; if all three failing, 27/39 = 69.2%. Reported: [61.5, 69.2]. So some family fails Sonnet-4.6 completely, and removing it lifts the score by 4.9 points. That is what a jackknife is for — it tells you how concentrated the failures are.
sed commands keep breaking."One more thing worth noticing in that table: Qwen3.5-4B at 21.4% beats Qwen3.5-9B at 17.9%. The smaller model wins. And GPT-5.6-sol at 98.2% is behind three models at 100.0%, which contradicts the same-window crossover where it had the best matched-nested score — because these are different selections from different serving windows. The paper flags this explicitly: the scorecard supports operating-point selection, the crossover diagnoses path sensitivity, and "neither is a controlled compute ranking."
Split every row of the scorecard into its two components and the aggregate stops being a single skill. The control column measures "can you do the operation"; the hostile column measures "can you preserve a literal while doing it". Compute the ratio and models sort into recognisably different failure modes.
| Model | Control | Hostile | Control rate | Hostile rate | Diagnosis |
|---|---|---|---|---|---|
| Opus-4.8 | 12/14 | 41/42 | 85.7% | 97.6% | inverted — misses benign tasks it should ace while nearly clearing the hostile tier |
| Gemini-3.1-Pro | 14/14 | 37/42 | 100% | 88.1% | clean: operations solid, literal preservation the only gap |
| Sonnet-4.6 | 9/14 | 27/42 | 64.3% | 64.3% | flat — the hazard tier costs it nothing extra, so the deficit is in the operations |
| Haiku-4.5 | 8/14 | 13/42 | 57.1% | 31.0% | the classic profile: can do simple operations, loses the literal |
| Gemini-3.1-Flash-Lite | 6/14 | 2/42 | 42.9% | 4.8% | near-total collapse on any hazard at all |
Opus-4.8's row is the strange one and it is a good illustration of why you should always look. It passes 41 of 42 hostile tasks and only 12 of 14 benign ones. A model that can preserve a multiline payload with mixed quotes but drops two ordinary operations is telling you something about its failure distribution that no aggregate can — and its Hostile LOFO of [97.4, 100.0] is identical to GPT-5.6-sol's, despite a 3.6-point difference in the total.
Sonnet-4.6's flat profile is the other instructive one: 64.3% on both halves. The hazard tier is supposed to be harder, and for this configuration it is not, which means its 20 failures are distributed across operations rather than concentrated on literals. Two models at exactly 64.3% overall — Sonnet-4.6 and Gemini-3.5-Flash — and their splits differ, their jackknives differ, and a user would experience them differently.
sed commands keep breaking and my git commit messages come out wrong."Put the chapter together into a template. Three claims of decreasing strength, each supported by a different piece of the analysis:
That third block is the one most papers skip. Reporting "five reversals" invites the reader to treat five as an estimate with negligible error, when the interval spans one to eight. Reporting the interval costs one sentence and prevents a citation chain from hardening a soft number.
Everything so far concerned one shell and one wrapper. If that were the whole story, the fix would be "stop using ssh host quotes" and we could go home. This chapter shows the same four cells appearing on a boundary with no shell anywhere in it, and gathers the robustness checks that say the effect is not an artefact of the published payloads, the userland, or a single sampled reply.
Replace the shell wrapper with a JSON tool call. The paper replays each stored raw reply through a JSON boundary two ways: a correct serializer that round-trips the string, and a naive embedding that pastes the reply into a JSON string field without escaping.
| Configuration | Raw | Correct serializer | Naive embedding | Naive damage |
|---|---|---|---|---|
| GPT-5.6-sol | 53 | 53 | 21 | −57.1 |
| GPT-5.5 | 56 | 56 | 19 | −66.1 |
| Opus-5 | 54 | 54 | 22 | −57.1 |
| Opus-4.8 | 51 | 51 | 18 | −58.9 |
| Qwen3.5-27B | 48 | 48 | 19 | −51.8 |
| Gemini-3.1-Flash-Lite | 44 | 44 | 8 | −64.3 |
Two things to read off. The correct-serializer column is identical to the raw column, every row. Damage exactly zero. And the naive column loses 51.8 to 66.1 points — the same magnitude as the shell nested transport, on a boundary that contains no shell at all.
json.dumps and back through json.loads and the cost is precisely nothing. Any pipeline that transforms generated output before executing it defines the same four cells. The decomposition is not a Bash result.The natural conclusion is "use structured actions instead of shell strings." The paper measures that too, in a separate observational campaign: six provider-hosted models, both the raw contract and the provider's native shell tool, pooled over each model's measured effort ladder and three trials per cell.
| Model | Attempts | Raw (%) | Native (%) | Δ (points) |
|---|---|---|---|---|
| Opus-4.8 | 840 | 95.4 | 98.0 | +2.6 |
| Opus-5 | 840 | 98.2 | 97.4 | −0.8 |
| Fable-5 | 840 | 99.3 | 97.1 | −2.1 |
| Gemini-3.1-Pro | 504 | 98.8 | 95.0 | −3.8 |
| GPT-5.6-sol | 672 | 96.9 | 94.3 | −2.5 |
| Gemini-3.5-Flash | 672 | 95.7 | 85.7 | −10.0 |
The attempt counts are readable if you decompose them: 56 tasks × 3 trials × the number of rungs. Opus models expose 5 rungs, so 56 × 3 × 5 = 840. GPT-5.6-sol and Gemini-3.5-Flash have 4 rungs: 56 × 3 × 4 = 672. Gemini-3.1-Pro has 3: 56 × 3 × 3 = 504. The six sum to 4,368 raw plus 4,368 native = 8,736 generations, each replayed in both userlands for 17,472 execution outcomes.
The native-minus-raw change spans +2.6 to −10.0 points, and the family-sign sensitivity analysis returns twelve Holm-adjusted values all above .05, minimum .18750. So this study is explicitly descriptive and exploratory — the paper says so. But its central comparison is unambiguous: the native effect is smaller than the controlled nested loss for every model. A structured call removes one quoting surface. It does not remove sixty points of anything.
And the typed-operation pilot puts a number on the residual. Replacing shell-string construction with structured operations on 18 private tasks across two models — 36 attempts — passes 25 of 36, or 69.4%, against 35 of 36, or 97.2%, for raw bash -c and temporary scripts. Of the eleven typed failures, ten reach the wrong final state and one fails during execution. The most common cause the paper names: the model copies the instruction's delimiter markers into the payload.
Study B is also where the exit-code claim gets its numbers, and the full table is worth reading because each row partitions exactly 4,368 executions into five outcomes.
| Userland | Contract | Pass | Adherence | Syntax | Nonzero exit | Exit-0 wrong |
|---|---|---|---|---|---|---|
| BSD | raw | 4230 | 0 | 31 | 59 | 48 |
| BSD | native | 4236 | 20 | 9 | 41 | 62 |
| GNU | raw | 4252 | 0 | 39 | 36 | 41 |
| GNU | native | 4146 | 20 | 22 | 128 | 52 |
Check one row, then compute the headline. GNU native: 4146 + 20 + 22 + 128 + 52 = 4,368. Failures on that row are 4,368 − 4,146 = 222, of which 52 exited zero:
And BSD native, where the ratio is worst: failures are 4,368 − 4,236 = 132, of which 62 exited zero:
So the abstract's "23.4–47.0%" is the span across the four conditions, and the extremes are both on the native contract. That is not a coincidence: the adherence column shows why. The native arm has 20 invalid one-call invocations per userland and far fewer syntax errors — 9 versus 31 on BSD, 22 versus 39 on GNU — because a schema-validated tool call rules out malformed shell more often. Removing loud failures does not remove failures. It converts them into quiet ones.
Aggregate deltas hide churn. The paper reports paired pass-to-fail and fail-to-pass transitions for the native-minus-raw comparison, and the pairs are far larger than the nets.
| Model | GNU Δ | Pass→fail | Fail→pass | Net | Total churn |
|---|---|---|---|---|---|
| Opus-4.8 | +2.62 | 11 | 33 | +22 | 44 |
| Opus-5 | −0.83 | 16 | 9 | −7 | 25 |
| Fable-5 | −2.14 | 22 | 4 | −18 | 26 |
| GPT-5.6-sol | −2.53 | 26 | 9 | −17 | 35 |
| Gemini-3.1-Pro | −3.77 | 23 | 4 | −19 | 27 |
| Gemini-3.5-Flash | −9.97 | 77 | 10 | −67 | 87 |
Opus-5's net is −7 executions out of 840, which reads as "no effect" — but 25 individual task outcomes changed. Twenty-five different tasks behaved differently depending on how the model was asked, and the aggregate cancelled most of that. Verify one net against its percentage: Gemini-3.5-Flash loses 67 net of 672 attempts, and 67 ÷ 672 = 9.97% exactly.
The paper also does something rare and worth naming: it checks the wire. For three configurations from two providers, the raw native-tool arguments were retained, allowing byte-level verification between the decoded command field and what actually reached the executor — 660 records for Gemini-3.5-Flash, 497 for Gemini-3.1-Pro, and 672 for GPT-5.6-sol, with 19 adherence failures containing no usable argument. For the other three models the stored artefact begins at the decoded command string, so their analysis starts at that boundary and the paper says so rather than implying the check covered everything.
If the failures were malformed shell, a linter would find them. The authors ran ShellCheck over the replies and the result is a clean demonstration that this is not a syntax problem.
It misses two thirds — 191 of the 292 — and its base rate on working commands is 11.4%, so the signal-to-noise is poor even where it fires. The reason is structural, and the paper states it: "each command is individually well-formed and the fault is in the downstream interpolation." There is nothing wrong with the program. The program never reached the executor.
Two ways the result could be an artefact: the released tasks could be special, or a single sampled reply per cell could be unrepresentative. Both are tested.
Held-out payloads. A private crossover on 42 unpublished hostile payloads — three per family, hostile-only, manifest and sample hash fixed before inference, both contracts interleaved in one serving window:
| Model | RR | RN | NR | NN | Damage | Comp. | Interaction | Matched gap |
|---|---|---|---|---|---|---|---|---|
| GPT-5.6-sol | 92.9 | 19.0 | 50.0 | 97.6 | −73.8 | +78.6 | +121.4 | +4.8 |
| Opus-4.8 | 92.9 | 16.7 | 59.5 | 42.9 | −76.2 | +26.2 | +59.5 | −50.0 |
Denominator 42, so one task is 2.38 points. GPT-5.6-sol: 39 of 42 on the direct path, 8 of 42 through the parser — damage −31 ÷ 42 = −73.8 — and 41 of 42 under disclosure, compensation +33 ÷ 42 = +78.6. The matched gap is positive, +4.8, which would read on a leaderboard as "the deployed path is slightly better for this model." It hides a 73.8-point loss and a 78.6-point recovery. Same story, different payloads, and here the masking is even more complete.
Repeated draws. Three generations per contract for all eight public configurations: damage stays negative for every configuration and every draw, with per-configuration ranges of 1.8–7.1 points. No compensation changes sign; the largest spread is 12.5 points (Opus-4.8), and Qwen3.5-27B realizes exactly zero compensation in every draw. On the private tasks, three extra generations for eight tasks produce different reply text in 9 of 16 task-contract cells for GPT-5.6-sol and 10 of 16 for Opus-4.8 — the models really did write something different — and every draw still shows negative damage and positive compensation. Mean over four draws: GPT-5.6-sol −78.1 damage and +81.3 compensation; Opus-4.8 −84.4 and +46.9.
One more nuisance variable, and it is the one command benchmarks most often leave undeclared: GNU/Linux coreutils versus BSD/macOS coreutils. The primary replay is a pinned, network-disabled GNU container; the analysis is repeated in a BSD userland.
For the crossed design, the userland barely matters: corresponding crossover cells differ by at most 3.6 points for six of the eight configurations and by 7.1–12.5 for the other two, fixed-reply damage stays negative in both, and the masked set is unchanged. But for absolute shell competence it matters a lot. An earlier BSD-elicited campaign, replayed unchanged on GNU, shows model-specific dialect affinity in both directions:
| Model | Raw, BSD → GNU | Nested, BSD → GNU | Transfers better to |
|---|---|---|---|
| Fable-5 | 96.4 → 91.1 | 92.9 → 87.5 | BSD |
| Qwen3.5-27B (non-thinking) | 78.6 → 87.5 | 25.0 → 32.1 | GNU |
| Qwen3.5-27B (thinking) | 73.2 → 82.1 | 44.6 → 50.0 | GNU |
| Gemini-3.1-Pro | 92.9 → 100.0 | 89.3 → 96.4 | GNU |
| Gemini-3.5-Flash | 100.0 → 96.4 | 69.6 → 67.9 | BSD |
| Opus-4.8 | 91.1 → 87.5 | 73.8 → 73.8 | BSD (raw); tie (nested) |
Shifts reach 8.9 points and they reorder models: the raw top three go from Gemini-3.5-Flash / Fable-5 / Gemini-3.1-Pro on BSD to Gemini-3.1-Pro / Gemini-3.5-Flash / Fable-5 on GNU, and the nested ordering likewise swaps Fable-5 and Gemini-3.1-Pro at the top. Note the correct interpretation, which the paper insists on: because every command was elicited in BSD sessions, this measures cross-userland transfer of fixed commands, not what a model would write if told to target GNU.
json.dumps/json.loads round trip costs exactly zero. What does this pair of results establish?The paper ends with a prescription rather than a technique, which is unusual and correct. This chapter is that prescription, the fixes, the limits, and the connections to the rest of what you already know about evaluation.
The abstract's closing sentence is the whole paper compressed: evaluations of command-issuing agents should report the model configuration, generation contract, execution path, operating point, and final-state validator "rather than treat a matched score as an intrinsic model property."
| Report | Because without it | QuoteBench's evidence |
|---|---|---|
| Model configuration — exact identifier, request parameters, query date | hosted deployments change under the same name | the sweep is dated 2026-07-31; "the query date is part of the result" |
| Generation contract — what the model was asked to produce, verbatim | one added sentence moves matched success by up to 60.7 points | the raw and disclosed clauses differ by one sentence and nothing else |
| Execution path — what the harness does with the reply | a fixed reply loses 55.4–73.2 points across one added parser | Table of eight configurations, all negative, all leave-one-family-out slices negative |
| Operating point — the effort setting, or that it was unset | labels map to different budgets and defaults land on different rungs | 773 vs 4,708 tokens at "high"; three defaults on three different parts of three ladders |
| Final-state validator — what counts as success | 23.4–47.0% of failures exit zero | 197 of 197 mutations rejected; oracles, probes and untouched fixtures all audited |
The fixes are boring and total. What is not boring is deciding which one you are allowed to use, and the deciding factor is ownership of the interpolation point.
The private replay makes the accounting concrete. Three models, 42 tasks each, one fixed raw reply per task, three transports:
| Model | Raw | Nested wrapper | Temporary script | Script gain |
|---|---|---|---|---|
| GPT-5.6-sol | 41/42 | 8/42 | 41/42 | +78.6 |
| Opus-4.8 | 40/42 | 7/42 | 40/42 | +78.6 |
| Qwen3.5-27B | 30/42 | 9/42 | 30/42 | +50.0 |
Add the recoveries: (41 − 8) + (40 − 7) + (30 − 9) = 33 + 33 + 21 = 87 commands that fail only under the wrapper. Add the residual raw failures: (42 − 41) + (42 − 40) + (42 − 30) = 1 + 2 + 12 = 15, unresolved by any transport. The script column reproduces the raw column exactly, row by row.
The limitations section is short and every line of it constrains a claim you might otherwise make.
| Limitation | What you therefore cannot say |
|---|---|
| One mechanism: one-shot Bash under quotation and interpolation hazards | anything about multi-turn recovery, other shells, or authentication |
| 14 purposively constructed families | that this estimates a population of shell tasks |
| Incident surveys document mechanism coverage | how often such boundaries occur in deployment |
| Causal claims rest on the eight same-window configurations | that the ladder rungs are controlled comparisons — each is one stored generation per task |
| Effort labels are not comparable compute budgets | that "model A at high beat model B at high" is an equal-compute result |
| The native-tool campaign is observational | that native contracts cause the native-minus-raw change; all twelve adjusted p-values exceed .05 |
| Held-out payloads were not difficulty-matched | that private absolute rates are comparable to public ones |
| Typed pilot covers six naturally typeable families and includes mild coaching | that typed operations are or are not the answer — the authors call it exploratory |
And the artefacts, because a benchmark you cannot rerun is a claim rather than a measurement: the harness, all 56 tasks, validators, contract prompts, and offline verification commands are released, along with a sanitized rollout archive of 12,999 records across 33 arm files carrying each generation with its replays, prompt, reply, identifiers, usage, and final-state outcomes, plus a SHA-256 manifest and a REPRODUCE.md that reconciles campaign-level counts. Private payloads and replies are withheld to preserve held-out evaluation. Every released task file embeds a fixed canary GUID for contamination checks.
One more design detail worth copying: because the harness executes untrusted model output, every attempt runs in a fresh fixture inside a timeout-bounded, network-disabled container, and the incident evidence is released only as de-identified mechanism classifications.
The measurement is cheap enough that there is no reason not to run it on whatever you are building. Here is the whole thing, reduced to the four steps the paper actually performs.
python # STEP 1 — store every reply. Not the score. The BYTES. # This is the only step that costs model calls, and it is the only # step you cannot go back and do later. rollout = [] for task in TASKS: R = model(SYSTEM_PROMPT, task.instruction) rollout.append({"task": task.id, "contract": "raw", "reply": R, "model": MODEL_ID, "queried": TODAY, "effort": EFFORT}) # STEP 2 — replay through every transport you might ever deploy on. # Zero model calls. Add transports freely; each one is just container time. TRANSPORTS = {"direct": run_raw, "nested": run_nested, "escaped": run_nested_escaped, "script": run_script} for rec in rollout: for name, fn in TRANSPORTS.items(): work = fresh_fixture(rec["task"]) fn(rec["reply"], cwd=work) rec[name] = validate(rec["task"], work) # FINAL STATE, not exit code # STEP 3 — the number that tells you whether you have a problem. direct = sum(r["direct"] for r in rollout) deploy = sum(r[DEPLOYED_TRANSPORT] for r in rollout) print(f"portability: {deploy}/{direct} of working commands survive") # STEP 4 — if portability is bad, check whether it is YOUR bug. # If "escaped" reproduces "direct" exactly, the model was never wrong. assert all(r["escaped"] == r["direct"] for r in rollout), \ "escaping does not fully restore — there is a second boundary somewhere"
Step 4 is the diagnostic worth internalising. If escaping at the interpolation point restores every direct-path success, then the model produced correct programs and your harness destroyed them — and that is a one-line fix in your code, not a model-selection problem. In the paper that assertion holds for all 448 public pairs. If it fails in your system, you have more than one boundary, and you have just found the second one.
Three things that make the difference between this being a real measurement and a comforting one:
| Do this | Not this | Because |
|---|---|---|
| store replies with model id, effort, and query date | store scores | you cannot replay a score, and a hosted model under the same name will not reproduce the reply |
| validate final state, byte-exact, with a collateral check | check returncode == 0 | up to 47% of failures exit zero; and a task solved by leaving three helper files behind is not solved |
| build fixtures without invoking a shell | set up the fixture with a shell script | a fixture built by the thing you are testing can encode the same escaping assumption you are trying to measure |
| Quantity | Definition | Range observed | What it tells you |
|---|---|---|---|
| RR | raw reply, raw transport | 78.6–100.0% | direct-path competence; nearly saturated at the frontier |
| RN | same reply, nested transport | 19.6–30.4% | portability — the number nobody reports |
| NR | boundary-aware reply, raw transport | 33.9–83.9% | the cost of adapting to a boundary that is not there |
| NN | boundary-aware reply, nested transport | 14.3–91.1% | deployed-path competence |
| Damage | RN − RR | −55.4 to −73.2 | what the channel destroys, with the model held fixed |
| Compensation | NN − RN | −5.4 to +60.7 | what the model rebuilds when told about the channel |
| Matched gap | NN − RR = damage + compensation | −64.3 to −3.6 | the only one a conventional benchmark prints |
| Interaction | (NN − NR) − (RN − RR) | −7.1 to +119.6 | whether the adaptation is boundary-specific |
bash -c R and bash -c "R". The generation costs a few cents; every number after that is free. The first time you watch a correct command produce a wrong file with exit status zero, the sixty-four points will stop being a statistic.Without scrolling up: (1) trace printf '%s\n' 'cost: $5 `now` "x"' > out.txt through bash -c "R" and say what ends up in the file and what the exit code is; (2) name the four cells of the crossed design and write the decomposition identity; (3) given RR = 53/56 and RN = 17/56 and NN = 51/56, compute damage, compensation and the matched gap in percentage points; (4) explain why the six compensating models lose 28.6–64.3 points on the raw path, and what that proves; (5) explain why Opus-4.8's matched gap improving from −48.2 to −3.6 does not mean its commands became portable. If any of the five stalls, its chapter is one tap away.