Shangao Li, Yao Zhang, Volker Tresp, Yuanyuan Yang (Stony Brook · LMU Munich · MCML) — arXiv:2608.13547, August 2026

QuoteBench: When Scores Match and Meaning Does Not

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.

Prerequisites: you have typed a shell command and you can subtract percentages. Quoting rules, the crossed design, and the decomposition identity are built from zero.
56
Tasks
14
Families
−64.3
Hidden Damage
−3.6
Reported Gap

Chapter 0: The Score That Lied

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:

ssh host "<the model's command>"   or   docker exec sh -c "<the model's command>"   or   run: <the model's command>

And roughly two thirds of the commands that worked in the benchmark now silently produce the wrong result.

The number that should stop you. QuoteBench takes the same stored reply from a model — not a new generation, the identical bytes — and runs it two ways: directly, and through one added double-quoted parser. Across eight configurations measured in a single serving window, that one change lowers success by 55.4 to 73.2 percentage points. Every configuration. No exceptions. And for the frontier model in that set, the benchmark's headline gap was −3.6 points.

Where the three and a half points came from

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 measuredTasks passedPercent
Model writes a command; command runs directly53 / 5694.6%
Same reply, replayed through one added parser17 / 5630.4%
Model is told about the parser, then writes; runs through it51 / 5691.1%

One task out of 56 is 156 = 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:

17 − 53 = −36 tasks  →  −36 ÷ 56 = −0.6429  →  −64.3 points

Contract-conditioned compensation is what the model recovers when it is told the parser is there and rewrites accordingly:

51 − 17 = +34 tasks  →  +34 ÷ 56 = +0.6071  →  +60.7 points

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:

51 − 53 = −2 tasks  →  −2 ÷ 56 = −0.0357  →  −3.6 points

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.

The reported score is a sum, and sums lose information. A matched evaluation observes one number, −3.6, and reports "this model is barely affected by the deployment path." What actually happened is that the path destroyed 36 of its 53 working commands, and the model — given one sentence of warning — rebuilt 34 of them from scratch using a completely different quoting strategy. Two enormous effects, opposite in sign, of nearly equal size. Their sum is small. Neither of them is.

Why "sixty points of damage" is not hyperbole

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:

4 ÷ 14 = 0.2857 → 28.6 points  ·  8 ÷ 14 = 0.5714 → 57.1 points

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.

The first thing to actually look at

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.

Same reply, two paths

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.

Reply:

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.

Exit codes will not save you. The paper measured this directly. Across the four contract-by-userland conditions in its second study, between 23.4% and 47.0% of all failing executions exited zero while leaving the wrong final state. In the worst condition that is 62 silent failures out of 132. A benchmark that trusts return codes would miss up to half of these — which is why every QuoteBench task is scored by inspecting the final bytes, the argument vector, the parsed JSON, the directory listing, or the Git history.

What a matched score can and cannot answer

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.

QuestionDoes 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.

What this costs you in a running agent

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.

1. The command runs and does the wrong thing
Often with exit status 0 and no error text, so nothing in the harness notices. The agent proceeds on a false premise.
2. A generation and a tool invocation are consumed
Real latency, real tokens, and a turn spent. The paper: "A failure also consumes a model generation and tool invocation."
3. Diagnosis and retry stay in the trace
The wrong output, the confusion and the repair attempt all remain in context, degrading every subsequent decision the agent makes.
4. The recovery has side effects
The common escape is "write a temporary script and run that", which adds actions and can leave workspace artefacts behind — new state that was never part of the task.

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.

What the paper is and is not claiming

It is worth being precise early, because the result is easy to over-read in both directions.

The paper claimsThe 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 configurationsThat 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 boundaryThat 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 bothThat 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 unambiguousThat the leaderboard is meaningless — it is a bootstrap-supported partial order
The obvious fixes work perfectly and are trivialThat 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.

Where we are going

Chapters 1–2 — build the instrument
Trace one command through two parsers by hand → then see how 56 tasks, 14 families, and audited final-state validators turn "quoting is hard" into something measurable
Chapters 3–6 — the mechanism
The crossed design and its decomposition identity → damage, model by model → what one disclosed sentence buys → and exactly how the two cancel into a small reported number
Chapters 7–10 — consequences
Effort labels are not compute budgets → the leaderboard reorders → the same mechanism on a JSON boundary → what an honest evaluation report has to contain
A benchmark reports that a model scores 94.6% on the direct path and 91.1% on the deployed path — a gap of −3.6 points. What does that number not tell you?

Chapter 1: One Boundary, Two Parsers

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.

What a shell actually does to a string

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.

StateWhat is still specialWhat 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 quoteeverything else, including backslash
The single quote is the only true literal in Bash. That is why every competent solution to a hostile-payload task ends up inside single quotes — and it is also why the added parser is so destructive. Single quotes are inert inside double quotes. A model that correctly protects its payload with single quotes has built a fortress that the outer double-quoted context simply ignores.

A complete trace, character by character

Take a task of the shape QuoteBench actually uses: write a file whose exact content is

cost: $5 `now` "x"

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 readsWhat it doesResult so far
1bash -ctwo ordinary wordscommand name and flag
2the first "enters double-quote state
3printf '%s\n' 'cost: single quotes are inert here; \n is a backslash before n, which is not one of $ ` " \, so it stays literaltext accumulates unchanged
4$5expands — positional parameter 5 of the outer shell, which is unsetreplaced 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 stdoutreplaced by the empty string
6the " before xcloses the double-quote state — this quote came from the payload, but the outer shell has no way to know thatfirst quoted section ends
7xunquoted literal, concatenated to the previous word
8the " after xopens a new double-quote state
9' > out.txtall inside quotes now — the > is not a redirection to the outer shell, it is literal text
10the final "closes the wrapper's own quote; word endsone single argument

Adjacent quoted and unquoted fragments concatenate into one word, so what bash -c actually receives as its script is:

printf '%s\n' 'cost:   x' > out.txt

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".

Read the failure mode carefully, because it is the worst one there is. The command did not error. The file was created. The exit code was 0. A harness that checks 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 real task from the paper

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%
— with a real newline between the two lines, and one trailing newline at the end. Declared hazards: backslash, backtick, command substitution, multiline, mixed quotes.

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.

Any correct encoding gets credit. The validators score final state only, never the text of the command. The paper is explicit: "any semantically correct implementation receives credit." So the failures below are never a model being marked down for stylistic disagreement with an oracle. They are files with wrong bytes.

Is the nested transport a strawman?

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.

ConfigurationRawReal sshssh damageSynthetic nested damage
GPT-5.6-sol94.630.4−64.3−64.3
GPT-5.5100.028.6−71.4−71.4
Opus-596.430.4−66.1−66.1
Gemini-3.1-Pro98.226.8−71.4−73.2
Gemini-3.5-Flash96.428.6−67.9−67.9
Opus-4.891.126.8−64.3−64.3
Qwen3.5-27B85.730.4−55.4−55.4
Gemini-3.1-Flash-Lite78.619.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.

Two repairs, both trivial, both total

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).

Repair 1 — escape at the interpolation point
Instead of pasting R verbatim between quotes, quote it properly before interpolating. Reproduces the raw-path outcome for 448 of 448 pairs. Not "mostly" — exactly.
Repair 2 — write a temporary script
Put R in a file and execute the file. The program boundary survives because no second parser ever sees the text. Reproduces the raw-path outcome for all 448 public and 126 private pairs.
↓ and note what neither repair does
Neither fixes a genuinely wrong command
33 public and 15 private replies fail on the raw path too. They still fail. The repairs restore transport, not competence — which is exactly what a clean intervention should do.

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 four transports, in code

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.

Why 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.

Three more hazard families, traced

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.

The unifying description. All 14 families are instances of one thing: a literal has to survive a sequence of grammars. Every grammar in the chain is an opportunity to reinterpret a byte as syntax. Adding a parser adds a grammar. The reason a benchmark can measure this cleanly is that shell parsing rules are public and the final state is exactly checkable — a rare combination that makes attribution possible at all.
A model wraps its whole payload in single quotes — the strongest literal protection Bash offers. Why does that not survive bash -c "R"?

Chapter 2: 56 Tasks, Exact Final State

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.

The shape of the benchmark

14 operation families × (1 benign control + 3 hazardous variants) = 56 one-shot tasks

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 groupRepresentative failureFamilies
Literal quote and expansionapostrophes, double quotes, dollars, backticks, multiline payloadswrite-file, JSON writing, Git commit, environment passing, heredoc writing
Word splitting and path semanticsspaces, globs, leading dashes, hostile filenames, argument boundariesargv passing, hostile filenames, find/glob, bulk rename
Embedded-language escapingregex versus literal matching, sed replacement, AWK string processinggrep count, sed replace, field lookup, JSON writing
Second parser or remote-like expansionlocal expansion before a second shell, argument joining, heredoc transportSSH-like nested execution, SSH-like heredoc
Command-boundary representationcommand string, shell stdin, temporary file, argv, provider tool schemaraw/nested crossover, native-tool study, script bypass, typed pilot
Why 14 families and not 500 tasks. The families are the inferential units, not the tasks. Every significance test in the paper resamples families, not individual tasks, and every robustness range is a leave-one-family-out jackknife. That is the statistically honest move when the items were purposively constructed rather than sampled: you can defend "the effect does not depend on any single mechanism" and you cannot defend "this estimates a population of shell tasks." The paper says so in as many words.

Where the families came from

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.

Internal survey — 86 incidents
De-identified failures from the authors' own coding-agent sessions: 50 Codex incidents and 36 Claude incidents.
Public survey — 412 screened
412 candidates screened → 34 read in full → 17 retained as model-level POSIX/Bash command-construction incidents → 10 classified separately as harness failures → 7 excluded as out of scope.
The number that motivates the intervention
Five of the seventeen retained incidents target a second parser — an SSH remote or an inner 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."

The cost of a quoting failure is not one failed command. The paper opens with this and it is easy to skip. A failure consumes a model generation and a tool invocation; then the diagnosis and the retry stay in the context window, degrading everything downstream. And the common recovery — write a temporary script and run it — adds actions and can leave workspace artefacts behind. One bad escape becomes three turns and a stray file.

Auditing the validators

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.

CheckWhat it rules outResult
Machine-constructed oracle for every taskan unsolvable task inflating the failure ratesolves all 56 with one command
Benign naive probesa validator so strict nothing passesall pass
Hazardous naive probesa validator so loose the hazard does not matterall fail on the raw path
Untouched fixturesa validator that passes without any work being doneall rejected
Targeted mutations of oracle-produced statesa validator that ignores part of the required state197 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.

The honesty clause. After all five checks the paper writes: "These checks cover the specified invalid states. Other validator blind spots may remain." That sentence costs the authors nothing and buys the reader everything. A benchmark paper that claims its validators are correct is claiming something unverifiable; one that enumerates what it tested is claiming something you can audit.

What the benchmark deliberately does not cover

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.

One family, across all four tiers

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.

TierPayload characterWhat it isolatesDoes the naive echo pass?
0 — controlordinary words, no metacharacterscan the model perform the operation at allyes, on the raw path
1–3 — hazardousquotes, expansion characters, multiline data, leading dashes, parser-boundary conflictscan it preserve a literal while performing the operationno — 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.

Design lesson: hold the operation fixed and vary only the hazard. If the hardest tasks in your benchmark are also the most complicated operations, you cannot tell whether a failure came from the difficulty or from the mechanism you meant to test. QuoteBench's tiers are a within-family control, which is why "hostile minus control" is interpretable. Build your own evaluations this way and you get a free ablation.

What a final-state validator actually looks like

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 as a debugging technique

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.

Start from a state you know is good
The oracle solves the task with one command, so its output is a valid final state by construction. Every mutation is measured against that, not against a hand-written expectation.
Apply one corruption class at a time
Delete a required file (60 cases). Flip a single byte (60). Insert a collateral file (56). Restore a file that should have been removed (17). Amend a Git-only state (4).
Every one must be rejected
197 of 197. A single accepted mutation would mean the validator ignores part of the state it claims to check — and that hole would show up as inflated pass rates for exactly the commands that half-work.

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.

Why does QuoteBench score final state rather than exit codes, and why does it treat the 14 families rather than the 56 tasks as the units of analysis?

Chapter 3: The Crossed Design

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?

Two axes that everybody conflates

QuoteBench separates two things that agent systems normally bundle together.

The generation contract
What the system tells the model to produce. "Emit one Bash program." "Fill in this tool call." "Your reply will be interpolated into an outer command." This is a property of the prompt.
↓ these are independent, and normally nobody says so out loud
The execution transport
What the harness actually does with the reply on its way to a shell. Execute it verbatim. Paste it into a remote command. Tokenize it to argv. Write it to a file. This is a property of the plumbing.

The paper evaluates two observed model-facing contracts and adds one controlled intervention.

ContractWhat the model is asked forHow the reply reaches Bash
Rawone Bash program, nothing elseexecuted verbatim as the script argument to bash -c
Nativea provider shell-tool callthe required command field is extracted and executed on the same raw path
Disclosed-boundaryone Bash program, plus one sentence stating that the reply will be interpolated inside double quotesthe 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:

Reply with exactly one bash command and nothing else — no explanation, no markdown fences. Your reply is passed verbatim as the single argument to bash -c and executed in the task's working directory.

The disclosed-boundary clause:

Reply with exactly one bash command and nothing else — no explanation, no markdown fences. Your reply R is not executed directly: it is interpolated inside double quotes into an outer command, producing the string bash -c "R", and that string is executed in the task's working directory.
Read what that clause does not say. It states where the command runs. It gives no quoting advice, no strategy, no worked example, no instruction to prefer single quotes or 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.

The 2×2

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:

CellReply generated underExecuted throughWhat it is
RRraw contractraw transportmatched — the direct-path score
RNraw contractnested transportoff-diagonal replay: fixed reply, added parser
NRdisclosed-boundary contractraw transportoff-diagonal replay: boundary-aware reply, no boundary
NNdisclosed-boundary contractnested transportmatched — 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:

Damage = YRN − YRR   ·   Compensation = YNN − YRN   ·   Matched gap = YNN − YRR

And the identity that makes the whole thing work — add and subtract YRN:

YNN − YRR = (YRN − YRR) + (YNN − YRN)
This is an identity, not a model. There is no fitting, no assumption, no error term. It holds algebraically for any four numbers, and the paper verifies it per task before aggregation. That is what makes the decomposition trustworthy: the matched gap is damage plus compensation, always, and the only question is whether anyone bothered to measure the two pieces.

Play with the cells

The crossover grid

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.

Why fixing the reply is the whole trick

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.

ApproachWhat changes between conditionsWhat you can conclude
Swap the whole harnesscontext handling, retry policy, verification, the command path, everythingthat variance exists — but not which mechanism caused a given reversal
Regenerate under a new prompt formatthe prompt and the replythat scores move — but you cannot separate "the channel destroyed it" from "the model wrote something different"
Fixed-output replay (QuoteBench)one parser, and nothing elsethe 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 generalisable lesson. If you want to know whether a channel hurt you, do not regenerate. Store the output, replay it through both channels, and diff the outcomes. Regeneration confounds the channel with the model's response to the channel — which, as Chapter 5 shows, is itself a sixty-point effect. Two sixty-point effects measured together look like nothing.

What real harnesses actually do

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.

SystemContractObserved boundary
Codexnativecommand string becomes shell -c/-lc R
SWE-agentrawagent action enters a persistent Bash session
LangChainnativestructured command string is written to shell stdin
Terminal-Benchrawcommand and key strings enter an interactive shell through tmux
OpenHandsnativehuman-readable command is tokenized to argv; spawn has no shell
AutoGennativegenerated 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.

Contract and boundary live on different axes, and the survey proves it. Three of the six systems ask for a native structured call and then do three completely different things with the extracted string: one re-wraps it in 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 whole experiment, in twenty lines

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.

LineWhy it is there
generation happens in one serving window, randomizedhosted 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 loopa 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 assertthe 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.

Why there is a third contract at all

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.

Raw contract, raw transport
"Emit one Bash program." The reply is the program. This is the RR cell.
↓ change only how the model is asked
Native contract, raw transport
"Fill in this shell tool." The command field is extracted and executed identically. Any difference is attributable to the representation the model was writing into.
↓ change only the path
Disclosed contract, nested transport
"You will be interpolated into double quotes." Plus the parser that does it. This is the NN cell.

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.

Why does replaying a stored reply through a second transport license a causal claim that regenerating under a second prompt does not?

Chapter 4: Transport Damage

Now the numbers. This chapter is one table and its consequences, worked slowly, because every claim in the paper's abstract lives inside it.

The table

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.

ModelRRRNNRNNDamageComp.Matched gap
GPT-5.6-sol94.630.455.491.1−64.3+60.7−3.6
GPT-5.5100.028.650.089.3−71.4+60.7−10.7
Opus-596.430.442.989.3−66.1+58.9−7.1
Gemini-3.1-Pro98.225.033.980.4−73.2+55.4−17.9
Gemini-3.5-Flash96.428.667.958.9−67.9+30.4−37.5
Opus-4.891.126.862.557.1−64.3+30.4−33.9
Qwen3.5-27B85.730.483.930.4−55.40.0−55.4
Gemini-3.1-Flash-Lite78.619.680.414.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:

53, 56, 54, 55, 54, 51, 48, 44  →  total 415 direct-path successes out of 8 × 56 = 448 pairs

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:

worst: 11 ÷ 44 = 0.250 → 25.0%   (Gemini-3.1-Flash-Lite)
best: 17 ÷ 48 = 0.3542 → 35.4%   (Qwen3.5-27B)
Two thirds of everything that worked, gone. Overall retention is 123 ÷ 415 = 29.6%. Not "degraded". Not "somewhat lower". Seven of every ten working commands produce the wrong final state after one parser is added, and the models that retain the largest fraction are the ones that were worst to begin with — because they emitted simpler, less quoted commands with fewer characters for the outer parser to eat.

Why the weak models lose the least

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.

This is why raw score has almost no discriminative signal at the frontier. The paper notes that six frontier configurations pass 91.1–100% of tasks on the direct path. When six models sit inside a nine-point band on the metric everybody reports, the metric has stopped separating them. "The entire signal lives on the nested side, which is also the precondition for masking." What still distinguishes models is not whether they can write the command — they can — but how they handle the command path.

The controls, again

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.

Is it one weird family?

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.

ModelDamage [95% CI]Enumerated pHolm-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.

What these p-values do and do not quantify. The paper is unusually careful here, and you should copy the sentence: "These intervals and p-values quantify variation across the 14 constructed families, not model-call randomness or a sampled task population." They answer "does this effect depend on which mechanisms we happened to include?" They do not answer "how often does this happen in the wild?" — nothing in the design could.

The interaction, and why it is enormous

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:

(51 − 31) − (17 − 53) = 20 − (−36) = +56 tasks  →  +56 ÷ 56 = +100.0 points

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:

(45 − 19) − (14 − 55) = 26 + 41 = +67 tasks  →  +67 ÷ 56 = +119.6 points

and the minimum at Gemini-3.1-Flash-Lite, which is the only configuration where disclosure makes things slightly worse in both directions:

(8 − 45) − (11 − 44) = −37 + 33 = −4 tasks  →  −4 ÷ 56 = −7.1 points

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.

The Holm correction, done by hand

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 kRaw pMultiplier (mk + 1)ProductAfter 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.

Why enumeration instead of a t-test. A t-test assumes the 14 family effects are draws from a population. They are not — they were chosen from an incident survey to cover distinct mechanisms. The sign-symmetry null asks a question that is actually answerable about a purposive set: conditional on these magnitudes, could the pattern of signs have come out this one-sided by chance? With 14 items you can enumerate all 16,384 possibilities and get an exact answer instead of an approximation to a question you were not entitled to ask.

Reading the damage column as an engineer, not a statistician

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:

ModelRR (tasks)DamageFragile commands lostRetained
Gemini-3.1-Pro55−73.24114 (25.5%)
GPT-5.556−71.44016 (28.6%)
Gemini-3.5-Flash54−67.93816 (29.6%)
Opus-554−66.13717 (31.5%)
GPT-5.6-sol53−64.33617 (32.1%)
Opus-4.851−64.33615 (29.4%)
Gemini-3.1-Flash-Lite44−58.93311 (25.0%)
Qwen3.5-27B48−55.43117 (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.

A prediction you can test yourself. If retention is roughly constant, then damage in points is approximately 0.70 × RR. Check it on GPT-5.5: 0.70 × 100.0 = 70.0 against a measured −71.4. On Qwen3.5-27B: 0.70 × 85.7 = 60.0 against a measured −55.4. Close, and the residuals are the interesting part — Qwen loses less than the rule predicts because its commands are simpler, and that is exactly the "competence is exposure" effect at work.
Across the eight same-window configurations, 415 of 448 replies passed on the direct path and 123 of those survived the added parser. Why do the strongest raw performers show the largest damage?

Chapter 5: What One Sentence Buys

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.

The size of the effect

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.

ModelCompensation [95% CI]Enumerated pHolm-adjusted pIn the supported set?
GPT-5.6-sol+60.7 [+46.4, +75.0].000244.001953yes
GPT-5.5+60.7 [+44.6, +75.0].000244.001953yes
Opus-5+58.9 [+41.1, +75.0].000488.002930yes
Gemini-3.1-Pro+55.4 [+33.9, +73.2].001221.006104yes
Opus-4.8+30.4 [+14.3, +48.2].003906.015625yes
Gemini-3.5-Flash+30.4 [+12.5, +48.2].013672.041016yes
Qwen3.5-27B0.0 [0.0, 0.0]1.0000001.000000no
Gemini-3.1-Flash-Lite−5.4 [−10.7, 0.0].250000.500000no

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.

Proof that this is behaviour change, not generic robustness

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.

ModelRR (raw reply, raw path)NR (boundary-aware reply, raw path)Cost of adapting
GPT-5.6-sol53 / 5631 / 56−22 tasks = −39.3
GPT-5.556 / 5628 / 56−28 tasks = −50.0
Opus-554 / 5624 / 56−30 tasks = −53.6
Gemini-3.1-Pro55 / 5619 / 56−36 tasks = −64.3
Gemini-3.5-Flash54 / 5638 / 56−16 tasks = −28.6
Opus-4.851 / 5635 / 56−16 tasks = −28.6
Qwen3.5-27B48 / 5647 / 56−1 task = −1.8
Gemini-3.1-Flash-Lite44 / 5645 / 56+1 task = +1.8
The six compensating models pay 28.6 to 64.3 points where the boundary is absent. They did not become better shell programmers. They pre-escaped their commands for a specific downstream parser, and pre-escaping is wrong if that parser is not there — the extra backslashes land in the file. The two non-compensating configurations change essentially nothing in either direction (−1.8 and +1.8, one task each), which is what "did not respond to the clause" looks like in data.

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.

Conditioned on the grammar, not on a memorised fix

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.

Configurationdouble-disclosed on doubledouble-disclosed on singlesingle-disclosed on singlesingle-disclosed on doubleDiagonal − anti
GPT-5.6-sol5475310+80.4
GPT-5.5498548+77.7
Opus-55284516+65.2
Sonnet-4.632112316+25.0
Opus-4.830112318+21.4
Haiku-4.525132011+18.8
Qwen3.5-27B17111117+0.0
Gemini-3.1-Flash-Lite719919−19.6

The denominator here is 112, since each row aggregates two arms of 56. GPT-5.6-sol:

diagonal 54 + 53 = 107  ·  anti-diagonal 7 + 10 = 17  →  107 − 17 = 90  →  90 ÷ 112 = 0.8036 → +80.4 points

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.

The same three groups keep appearing. Diagonal advantage sorts the models into +80.4 / +77.7 / +65.2 at the top, +18.8 to +25.0 in the middle, and +0.0 to −19.6 at the bottom. That is the same partition as matched-nested score, and the same partition the advice arm below produces. Whatever "boundary adaptation" is, it is a coherent capability that several independent probes agree on — and it is not the same thing as writing a correct command, which everyone at the top already does.

Disclosure versus instruction

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.

ConfigurationAdvice-free (of 56)With escaping adviceΔ (points)Tier
GPT-5.6-sol5449−8.9top
GPT-5.54953+7.1top
Opus-55254+3.6top
Sonnet-4.63246+25.0middle
Haiku-4.52532+12.5middle
Opus-4.83034+7.1middle
Qwen3.5-27B1718+1.8bottom
Gemini-3.1-Flash-Lite78+1.8bottom

Three distinct regimes, and the shape is one you should expect to see again in other capabilities.

Top — disclosure is sufficient
−8.9, +7.1, +3.6. Advice barely moves them and can hurt: GPT-5.6-sol drops five tasks when told how to escape. Knowing the boundary exists is all these models needed; the instruction competes with a strategy they already had.
Middle — advice is the binding constraint
Sonnet-4.6 +25.0 (fourteen tasks), Haiku-4.5 +12.5, Opus-4.8 +7.1. These models can execute the fix once told; they were not going to derive it from the boundary statement alone.
Bottom — neither contract reaches
+1.8 and +1.8 — one task each, indistinguishable from noise. The information is not the bottleneck; the capability is.

Compensation is uneven across families

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.

FamilyCompensationIn cells (of 32)Why
json-write+50.016the payload is visibly a quoted string; the hazard is staring at the model
sed-replace+46.915same — an embedded language with obvious delimiters to protect
hostile-filenames+18.86the hazard is in the argument, not the payload; easier to overlook
grep-count+15.65regex metacharacters look like syntax, not like data
find-glob−12.5−4expansion 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.

What the model actually does differently

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.

This is why "robustness" is the wrong word for compensation. A robust command would work on both paths. These do not. What the six models produce is a command targeted at a declared environment, and the targeting is the capability being measured. The right mental model is cross-compilation, not hardening: you get an artefact for the platform you named, and it does not run on the other one.

Why advice can make a top model worse

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 existsstate the path; do not over-prescribe the encoding
in the middle (disclosure gives 30–57%)knowing what to do about itstate the path and the escaping strategy
at the bottom (disclosure gives 14–30%)capabilityfix 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.

Six configurations recover 30.4–60.7 points when told their reply will be wrapped in double quotes. What single piece of evidence shows this is boundary-specific adaptation rather than "the disclosed prompt just makes them write better shell"?

Chapter 6: Masking

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.

A reading aid, stated as a rule

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.

| YNN − YRR | ≤ 5 pp   and   YRN − YRR ≤ −40 pp   and   YNN − YRN ≥ +30 pp

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.

Masking is a property of an operating point, not of a model. The same model at a different rung can be unmasked, because the matched gap moves while the damage barely does. The paper says so directly: "Masking depends on the operating point and the chosen cut, not on a model-level invariant." So "is this model masked?" is not a well-formed question. "Is this model, at this effort setting, on this path, masked?" is.

The clearest case in the paper

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:

RungRRRNNNDamageMatched gap
low87.528.639.3−58.9−48.2
max98.230.494.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.

What a matched evaluation would have concluded. "At max effort, Opus-4.8 has essentially closed the gap between the direct and deployed paths — the model has learned to handle the boundary." What the fixed-reply replay shows: its commands are exactly as fragile as they were at low effort. Every point of the improvement came from the model rewriting for a boundary it was told about. Take the disclosure away — deploy it behind a wrapper nobody mentioned in the prompt — and 30.4% of its commands survive, the same as before. Meanwhile damage got worse, from −58.9 to −67.9, because the raw arm improved and there was more to destroy.

Who is masked and who is merely bad

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-sol3.6 — yes−64.3 — yes+60.7 — yesmasked
Opus-57.1 — noyesyesnearly masked; the gap is four tasks wide
GPT-5.510.7 — noyesyeslarge cancellation, visible residue
Gemini-3.1-Pro17.9 — noyesyescompensation real but incomplete
Opus-4.833.9 — noyes+30.4 — yespartial recovery, honest number
Gemini-3.5-Flash37.5 — noyes+30.4 — yespartial recovery, honest number
Qwen3.5-27B55.4 — noyes0.0 — nono adaptation; the gap is the damage
Gemini-3.1-Flash-Lite64.3 — noyes−5.4 — nono 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.

That is the perverse incentive worth naming. The better a model gets at reading its contract, the smaller its reported gap becomes, and the less its reported gap says about whether its commands travel. Progress on one capability erases the visibility of a deficit in another. Nothing about that is anyone's fault; it is a property of reporting a sum.

Why any threshold is the wrong fix

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.

One number, plus a flag
"−3.6, masked." Now the reader has to trust your cut points and still does not know the magnitudes.
Three numbers, no flag
"−64.3 damage, +60.7 compensation, −3.6 net." Every reader draws their own line, and the two components are recoverable for any downstream analysis.

Watch it across a whole ladder

Effort moves the matched score; it barely moves portability

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.

Why the matched gap can narrow without anything improving

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:

RN is pinned
Portability of raw-conditioned replies barely responds to effort — at most 5.4 points within a ladder.
NN climbs
Compensation responds strongly. Opus-4.8's compensation rises from +10.7 at low to +64.3 at max; Opus-5's from +32.1 to +66.1.
So the gap closes
NN approaches RR and the reported number approaches zero — entirely through the contract-conditioned term, with cross-path portability unchanged. "Most matched-score movement comes from the contract-conditioned contrast."

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.

Every rung, for the three complete ladders

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.

ConfigurationRungRRRNNRNNDamageComp.Matched gap
GPT-5.6-sollow98.228.653.691.1−69.6+62.5−7.1
GPT-5.6-solmedium94.630.448.292.9−64.3+62.5−1.8 *
GPT-5.6-solhigh98.232.148.298.2−66.1+66.1+0.0 *
GPT-5.6-solxhigh98.230.451.898.2−67.9+67.9+0.0 *
Opus-5low98.228.657.160.7−69.6+32.1−37.5
Opus-5medium100.032.141.191.1−67.9+58.9−8.9
Opus-5high96.430.442.996.4−66.1+66.1+0.0 *
Opus-5xhigh98.232.142.9100.0−66.1+67.9+1.8 *
Opus-5max100.032.146.498.2−67.9+66.1−1.8 *
Gemini-3.1-Prolow100.025.032.191.1−75.0+66.1−8.9
Gemini-3.1-Promedium98.226.841.191.1−71.4+64.3−7.1
Gemini-3.1-Prohigh98.226.835.791.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.

Ten of thirty, all at the top. Across the 30 rung-level crossovers the paper measured, ten meet the masking cut and every one of them is at a ladder top. Combine that with the previous chapters and the picture is complete: masking requires large compensation, large compensation is a frontier capability, and frontier capability appears at high effort. The better your model and the harder you let it think, the more likely its headline number is a cancellation.
The one-line test to run on your own evaluation. Take your best model at its best setting, freeze its outputs, and replay them through whatever channel your production system actually uses. If the pass rate falls off a cliff, your matched score was a description of a path you are not deploying on. It cost zero model calls to find out.
Opus-4.8's matched gap improves from −48.2 at low effort to −3.6 at max. Its nested-replay pass rate for raw-conditioned replies moves from 28.6% to 30.4%. What actually improved?

Chapter 7: Effort Is Not Compute

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.

The ladders

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.

ModelSettings, in orderSuccess (%)Mean output tokens
GPT-5.6-sollow / medium / high / xhigh91.1 / 92.9 / 98.2 / 98.2362 / 565 / 773 / 1,073
GPT-5.5low / medium / high / xhigh94.6 / 92.9 / 91.1 / 100.0507 / 655 / 1,164 / 2,757
Opus-5low / medium / high / xhigh / max60.7 / 91.1 / 96.4 / 100.0 / 98.2796 / 1,336 / 1,458 / 2,421 / 3,499
Fable-5low / medium / high / xhigh / max71.4 / 75.0 / 96.4 / 92.9 / 100.0332 / 569 / 843 / 1,212 / 2,396
Opus-4.8low / medium / high / xhigh / max39.3 / 48.2 / 50.0 / 62.5 / 94.6835 / 1,291 / 1,706 / 3,481 / 6,960
Gemini-3.1-Prolow / medium / high91.1 / 91.1 / 91.15,267 / 5,753 / 6,308
Sonnet-4.6low / medium / high / xhigh23.2 / 28.6 / 64.3 / 62.528 / 1,411 / 4,337 / 4,539
Gemini-3.5-Flashminimal / low / medium / high57.1 / 58.9 / 64.3 / 62.53,851 / 3,108 / 3,081 / 3,389
Haiku-4.5low / medium / high / xhigh32.1 / 37.5 / 32.1 / 26.85,432 / 4,717 / 4,708 / 4,783
Qwen3.5-27Bnon-thinking / thinking28.6 / 28.620 / 7,489
Gemini-3.1-Flash-Liteminimal / low / medium / high14.3 / 14.3 / 14.3 / 14.320 / 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.

"High" is a provider-private word. Comparing two models "at high effort" is comparing 773 tokens against 4,337 against 4,708. The labels are within-model controls, not common compute units. The paper states the constraint precisely: each rung is "a deployment-relevant operating point under the frozen benchmark, not an estimate of effort's causal effect." You can say "this setting is where I would run this model." You cannot say "these two models were given the same budget."

Four ways a ladder misbehaves

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 knobs that are not effort at all

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."

The measurement that makes a label meaningful. A rung is characterised by the pair (score, tokens), never by its name. Two rungs with the same name on different models can differ by two orders of magnitude in spend, and two rungs on the same model can differ by 375× in spend and zero in outcome. Report the pair. The label is a request parameter, not a finding.

The unset field is not a neutral rung

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.

ModelUnset (%)Nearest labelled rungDistance to that model's lowest rung
GPT-5.6-sol91.1low0.0
GPT-5.589.3high−5.4
Opus-589.3medium+28.6
Gemini-3.1-Pro80.4none within the ladder−10.7
Gemini-3.5-Flash58.9low+1.8
Opus-4.857.1xhigh+17.9
Gemini-3.1-Flash-Lite14.3all four rungs tie0.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.

Points per thousand tokens

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:

ModelCheapest rungMost expensive rungExtra tokensPoints gainedPoints per 1k extra tokens
GPT-5.6-sol91.1 @ 36298.2 @ 1,073711+7.110.0
Fable-571.4 @ 332100.0 @ 2,3962,064+28.613.9
Opus-560.7 @ 79698.2 @ 3,4992,703+37.513.9
GPT-5.594.6 @ 507100.0 @ 2,7572,250+5.42.4
Opus-4.839.3 @ 83594.6 @ 6,9606,125+55.39.0
Gemini-3.1-Pro91.1 @ 5,26791.1 @ 6,3081,0410.00.0
Haiku-4.532.1 @ 5,43226.8 @ 4,783−649−5.3n/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.

The tuning procedure that follows from this. Do not sweep the label; sweep the label and record the tokens, then plot score against spend rather than against rank order. The paper's own figure does exactly that, with dashed segments following each provider's declared order so that backward or dominated segments are visible as backward or dominated segments. A ladder that folds back on itself in that plot is telling you the provider's ordering is not your ordering.

The two-axis mistake

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.

Tune on NN alone
You maximise compensation, land at a ladder top, and end up at a masked operating point where a −68 and a +68 are hiding inside a +0.0.
Tune on NN, report RN alongside
Same selection, but now you can see that portability did not move — so you know that if your harness ever stops disclosing the boundary, the number will collapse. One extra replay per rung, zero extra model calls.
The caveat the paper attaches, which you should attach too. The unset measurements and the ladder measurements come from different serving windows, so these distances are descriptive only. That is the correct level of confidence for a cross-window comparison — and it is exactly why the mechanism analysis in Chapters 4 to 6 is restricted to the eight configurations collected in one randomized window, with no off-diagonal cell ever reconstructed across windows.

The design discipline behind that restriction

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.

CampaignDesignWhat it is allowed to support
Study A same-window sweep8 configs × 56 tasks × 2 contracts, one randomized window, effort unsetthe causal mechanism claims — damage, compensation, interaction
Study A ladder sweep44 rungs, 11 configs, per-provider windowsdescriptive operating-point comparison only
Study A rung crossover30 rungs, 7 configs, 26 crossover points, replay both transportsthe masking-versus-effort picture, one stored generation per rung
Study B native tool8,736 generations, 17,472 replays, observationalexploratory contrast between raw and native contracts
Private-v2 crossover2 models × 42 unpublished hostile payloads, one serving windowtransfer of the mechanism to unseen literals
Real-ssh grounding8 configs × 56, ssh localhost replay, zero model callsthat 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.

You benchmark model A at high and model B at high and A wins. What have you learned?

Chapter 8: The Leaderboard Reorders

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.

Kendall's τ, computed by hand from the table you already have

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:

ModelRRNN
AGPT-5.6-sol5351
BGPT-5.55650
COpus-55450
DGemini-3.1-Pro5545
EGemini-3.5-Flash5433
FOpus-4.85132
GQwen3.5-27B4817
HGemini-3.1-Flash-Lite448

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:

B, C tie on NN (both 50)  ·  C, E tie on RR (both 54)  →  2 tied pairs, 26 strictly comparable

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.

discordant = { A–B, A–C, A–D, A–E, C–D }  →  D = 5
concordant = 28 − 5 − 2 = C = 21

And Kendall's τ is the concordant-minus-discordant difference over the number of pairs:

τ = (C − D) ÷ 28 = (21 − 5) ÷ 28 = 16 ÷ 28 = 0.5714 → 0.57

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.

Notice who the reversals belong to. Four of the five involve GPT-5.6-sol, and all four are in the same direction: behind on the direct path, ahead on the deployed one. This is not diffuse ranking noise. It is one configuration whose ordering position depends almost entirely on which path you measure — the single largest compensation in the sweep (+60.7) sitting on the third-lowest RR among the frontier models.

Two orderings of the same eight models

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.

Where the ranking goes when the path changes

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:

RR: 53 vs 54  →  GPT-5.6-sol behind by one task
NN: 51 vs 33  →  GPT-5.6-sol ahead by eighteen tasks

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.

How much of the ranking survives?

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:

StatementWhat it means
22 of 28 pairwise orderings are stable in at least 95% of bootstrap resamplesmost of the leaderboard is a genuine, bootstrap-supported partial order — not noise
26 of 28 pairs are strictly comparable in the trial-0 drawstwo pairs are tied under one of the matched contracts and so cannot reverse
Five of those 26 reverse between RR and NNGPT-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 resolutionthe 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.

A partial order, not a ranking. This is the honest thing to say about almost every leaderboard, and QuoteBench says it: "the leaderboard is a bootstrap-supported partial order rather than a fixed ranking." Some comparisons are solid. Some are one task wide. The reader cannot tell which is which from a sorted column of numbers, and a sorted column of numbers is what leaderboards publish.

The cost of ignoring the path

Turn it into a decision. You must pick one model. Two selection rules:

Select on raw success
Pick GPT-5.5 — a perfect 56/56 on the direct path. On the nested path it reaches 50/56.
Select on the path you deploy
Pick GPT-5.6-sol, which was behind on raw. It reaches 51/56 on the nested path.
The regret
One task — 1.8 points. Small, because at the saturated frontier everyone is close. But the top rank reversed, and the reversal was invisible in the reported column.

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.

The best-observed scorecard, and how to read a jackknife

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.

ModelBest observed settingControlHostileAll 56 (%)Hostile LOFO (%)
GPT-5.5xhigh14/1442/42100.0[100.0, 100.0]
Opus-5xhigh14/1442/42100.0[100.0, 100.0]
Fable-5max14/1442/42100.0[100.0, 100.0]
GPT-5.6-solhigh14/1441/4298.2[97.4, 100.0]
Opus-4.8max12/1441/4294.6[97.4, 100.0]
Gemini-3.1-Prolow14/1437/4291.1[87.2, 89.7]
Sonnet-4.6high9/1427/4264.3[61.5, 69.2]
Gemini-3.5-Flashmedium10/1426/4264.3[59.0, 66.7]
Haiku-4.5medium8/1413/4237.5[28.2, 33.3]
Qwen3.5-27Bnon-think8/149/4230.4[15.4, 23.1]
Qwen3.5-4Bthink5/147/4221.4[10.3, 17.9]
Qwen3.5-9Bnon-think5/145/4217.9[5.1, 12.8]
Gemini-3.1-Flash-Litedefault6/142/4214.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:

if the dropped family contains the miss: 39 ÷ 39 = 100.0%
if it does not: 38 ÷ 39 = 0.9744 → 97.4%

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.

Aggregate rank hides distinct failure profiles. Sonnet-4.6 and Gemini-3.5-Flash both score 64.3% overall (36 of 56 each). Their control splits differ — 9/14 versus 10/14 — and their jackknife ranges differ, [61.5, 69.2] versus [59.0, 66.7]. Two models with an identical headline number fail on different operation families. The paper's family heatmap exists precisely because the total is not the thing a user experiences; a user experiences "my 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."

Controls versus hostile, read as a diagnosis

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.

ModelControlHostileControl rateHostile rateDiagnosis
Opus-4.812/1441/4285.7%97.6%inverted — misses benign tasks it should ace while nearly clearing the hostile tier
Gemini-3.1-Pro14/1437/42100%88.1%clean: operations solid, literal preservation the only gap
Sonnet-4.69/1427/4264.3%64.3%flat — the hazard tier costs it nothing extra, so the deficit is in the operations
Haiku-4.58/1413/4257.1%31.0%the classic profile: can do simple operations, loses the literal
Gemini-3.1-Flash-Lite6/142/4242.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.

Why the paper publishes a family heatmap at all. "Aggregate rank hides distinct failure profiles … models with similar totals fail on different operation families, while some lower-scoring configurations retain isolated strengths." The heatmap presents the benchmark "at the level users encounter in practice: concrete command families." Nobody experiences 64.3%. People experience "my sed commands keep breaking and my git commit messages come out wrong."

How to state a leaderboard result honestly

Put the chapter together into a template. Three claims of decreasing strength, each supported by a different piece of the analysis:

Strong — the partial order
"22 of 28 pairwise orderings are stable in at least 95% of resamples." These comparisons you can act on.
Specific — the named reversal
"GPT-5.6-sol is one task behind Gemini-3.5-Flash on RR and eighteen ahead on NN." One reversal, named, with its margin on both sides.
Honest — the uncertainty about the count
"The count of reversed pairs is itself uncertain: bootstrap mean 4.6, 95% interval [1, 8] of 28." Not "five pairs reverse" as though five were measured.

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.

Kendall's τ between the RR and NN orderings is 0.57, with 22 of 28 pairwise orderings stable in at least 95% of bootstrap resamples. What is the right way to state this result?

Chapter 9: Not Really About Bash

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.

The same mechanism with no shell involved

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.

ConfigurationRawCorrect serializerNaive embeddingNaive damage
GPT-5.6-sol535321−57.1
GPT-5.5565619−66.1
Opus-5545422−57.1
Opus-4.8515118−58.9
Qwen3.5-27B484819−51.8
Gemini-3.1-Flash-Lite44448−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.

The mechanism is an unescaped transform, not any transform. A JSON serializer re-parses the same double quotes and backslashes that a shell re-parses, so it breaks on the same characters — many of the replies do not even parse as JSON. But route the identical bytes through 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.

What a structured tool call actually buys

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.

ModelAttemptsRaw (%)Native (%)Δ (points)
Opus-4.884095.498.0+2.6
Opus-584098.297.4−0.8
Fable-584099.397.1−2.1
Gemini-3.1-Pro50498.895.0−3.8
GPT-5.6-sol67296.994.3−2.5
Gemini-3.5-Flash67295.785.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.

A valid envelope is not a preserved payload. This is the sentence to take away from the whole chapter. A structured call guarantees the shape of the action — and native one-call schema adherence is 98.2–100%, so models are excellent at producing valid envelopes. Shell correctness still depends on the bytes that arrive at the executor, and literal-preservation errors simply move from the command string into the argument and payload fields.

The silent-failure ledger

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.

UserlandContractPassAdherenceSyntaxNonzero exitExit-0 wrong
BSDraw42300315948
BSDnative42362094162
GNUraw42520393641
GNUnative4146202212852

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:

52 ÷ 222 = 0.2342 → 23.4%   (the minimum)

And BSD native, where the ratio is worst: failures are 4,368 − 4,236 = 132, of which 62 exited zero:

62 ÷ 132 = 0.4697 → 47.0%   (the maximum)

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.

The structured contract makes failure quieter, not rarer. Fewer syntax errors, fewer nonzero exits on BSD, more exit-0-wrong. If your monitoring is built on exit codes and parse errors, migrating to structured tool calls will make your dashboards look better while your final states get no more correct. This is the sharpest practical warning in the paper and it is buried in an appendix table.

Paired transitions, and where the wire was checked

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.

ModelGNU ΔPass→failFail→passNetTotal churn
Opus-4.8+2.621133+2244
Opus-5−0.83169−725
Fable-5−2.14224−1826
GPT-5.6-sol−2.53269−1735
Gemini-3.1-Pro−3.77234−1927
Gemini-3.5-Flash−9.977710−6787

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.

Sensitivity discipline, applied to their own result. The family-sign analysis on Study B returns twelve Holm-adjusted p-values, all above .05, minimum .18750. The authors' conclusion is that Study B "is therefore descriptive and exploratory" — and they say so in the main text, not only in an appendix. Contrast with the crossed design, where the largest adjusted p is .001465. Same paper, two studies, two very different strengths of claim, each labelled.

Static analysis does not catch it

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.

flagged 34.6% of the nested-only failures → 0.346 × 292 ≈ 101 of 292
flagged 11.4% of the replies that survive nesting → 0.114 × 123 ≈ 14 of 123

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.

Not the published payloads, and not one lucky draw

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:

ModelRRRNNRNNDamageComp.InteractionMatched gap
GPT-5.6-sol92.919.050.097.6−73.8+78.6+121.4+4.8
Opus-4.892.916.759.542.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.

The userland is a second systems axis

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:

ModelRaw, BSD → GNUNested, BSD → GNUTransfers better to
Fable-596.4 → 91.192.9 → 87.5BSD
Qwen3.5-27B (non-thinking)78.6 → 87.525.0 → 32.1GNU
Qwen3.5-27B (thinking)73.2 → 82.144.6 → 50.0GNU
Gemini-3.1-Pro92.9 → 100.089.3 → 96.4GNU
Gemini-3.5-Flash100.0 → 96.469.6 → 67.9BSD
Opus-4.891.1 → 87.573.8 → 73.8BSD (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.

Two axes, not one. Utility dialect is a systems variable distinct from quoting reliability, and it produces its own reorderings. A command benchmark should report its userland, and should replay its stored commands across every environment it claims to support — which costs nothing, because replay is free.
Replaying stored replies through a naive JSON string embedding costs 51.8–66.1 points, while a correct json.dumps/json.loads round trip costs exactly zero. What does this pair of results establish?

Chapter 10: What To Report

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.

Five things, or the number means nothing

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."

ReportBecause without itQuoteBench's evidence
Model configuration — exact identifier, request parameters, query datehosted deployments change under the same namethe sweep is dated 2026-07-31; "the query date is part of the result"
Generation contract — what the model was asked to produce, verbatimone added sentence moves matched success by up to 60.7 pointsthe raw and disclosed clauses differ by one sentence and nothing else
Execution path — what the harness does with the replya fixed reply loses 55.4–73.2 points across one added parserTable of eight configurations, all negative, all leave-one-family-out slices negative
Operating point — the effort setting, or that it was unsetlabels map to different budgets and defaults land on different rungs773 vs 4,708 tokens at "high"; three defaults on three different parts of three ladders
Final-state validator — what counts as success23.4–47.0% of failures exit zero197 of 197 mutations rejected; oracles, probes and untouched fixtures all audited
The sentence to steal. "The command interface is part of the evaluated system, not neutral plumbing." Everything else follows. If the interface is part of the system, then a score without the interface is a score of an unspecified system, and comparing two such scores is not a comparison.

The repair, chosen by who controls the boundary

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.

You control the boundary
Escape at the interpolation point. Quote the reply before pasting it. Restores every raw-path success across all 448 public pairs, exactly. This is the first-line fix and it is a one-line change.
↓ but if the boundary is a remote or CI pattern you do not own…
You do not control it
Send a temporary script. The program boundary survives because no second parser reads the text. Reproduces raw-path outcomes for all 448 public and 126 private pairs, and recovers 87 of the wrapper-only failures in the private replay. Cost: a file lifecycle and a possible workspace artefact.
↓ and if you can change neither…
Disclose the boundary in the prompt
Capable models compensate 30.4–60.7 points. But this is model-dependent, it is wrong if the boundary is absent (−28.6 to −64.3 on the raw path), and two of eight configurations do not respond at all.
↓ and note what none of them do
None of them fixes a wrong command
33 public and 15 private replies fail on the raw path. Every repair leaves them failed. Transport repair is not competence repair — and a matched score cannot tell you which of the two you need.

The private replay makes the accounting concrete. Three models, 42 tasks each, one fixed raw reply per task, three transports:

ModelRawNested wrapperTemporary scriptScript gain
GPT-5.6-sol41/428/4241/42+78.6
Opus-4.840/427/4240/42+78.6
Qwen3.5-27B30/429/4230/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.

What the paper does not know

The limitations section is short and every line of it constrains a claim you might otherwise make.

LimitationWhat you therefore cannot say
One mechanism: one-shot Bash under quotation and interpolation hazardsanything about multi-turn recovery, other shells, or authentication
14 purposively constructed familiesthat this estimates a population of shell tasks
Incident surveys document mechanism coveragehow often such boundaries occur in deployment
Causal claims rest on the eight same-window configurationsthat the ladder rungs are controlled comparisons — each is one stored generation per task
Effort labels are not comparable compute budgetsthat "model A at high beat model B at high" is an equal-compute result
The native-tool campaign is observationalthat native contracts cause the native-minus-raw change; all twelve adjusted p-values exceed .05
Held-out payloads were not difficulty-matchedthat private absolute rates are comparable to public ones
Typed pilot covers six naturally typeable families and includes mild coachingthat 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.

Instrumenting your own system this week

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 thisNot thisBecause
store replies with model id, effort, and query datestore scoresyou 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 checkcheck returncode == 0up to 47% of failures exit zero; and a task solved by leaving three helper files behind is not solved
build fixtures without invoking a shellset up the fixture with a shell scripta fixture built by the thing you are testing can encode the same escaping assumption you are trying to measure
The rollout archive is the artefact, not the table. QuoteBench releases 12,999 stored records precisely because the tables are derived and the records are not. Anyone can recompute a different statistic, add a transport, or check a claim without spending a token. If you build an internal evaluation, the rollout store is the thing worth keeping; the leaderboard is a view over it.

Bridges

Cross-domain bridge
Every benchmark score is a measurement of a pipeline, not of a model
Swap "generation contract" for "prompt template" and "execution transport" for "pooling strategy" and you have the situation in embedding evaluation, where the same encoder scores differently depending on the instruction prefix, the normalisation, and the similarity function used at scoring time. The thing being ranked is always a pipeline; the model is one component of it. QuoteBench's contribution is a procedure for splitting the pipeline score into a component you can attribute to the channel and a component you can attribute to the model's response to the channel — and that procedure needs nothing but stored outputs and a replay. Our embedding benchmarks and AI evaluation lessons cover the same failure from the retrieval side.
Cross-domain bridge
This is a serialisation bug with a leaderboard attached
Strip away the models and QuoteBench is the oldest bug in systems engineering: data pasted into a syntax without escaping. SQL injection, cross-site scripting, CSV formula injection, shell interpolation — all the same defect, all fixed the same way, by escaping at the boundary or by never crossing it. What is new is that the producer of the string is a model, the consumer is a benchmark, and the defect is therefore scored rather than reported. A missing escape used to show up as an incident; now it shows up as a capability difference. If you build agent harnesses, our harness engineering and agents and tool use lessons cover the interfaces this paper is measuring.
Cross-domain bridge
Jackknife, bootstrap, Holm — the statistics of a small purposive item set
QuoteBench has 56 items and no sampling frame, which is exactly the situation most real evaluations are in. Its response is a template you can reuse: treat the construction unit as the inferential unit, report a leave-one-out jackknife range instead of pretending you have a confidence interval, use an exact enumerated sign test when the item count makes enumeration possible, correct across models with Holm, and say out loud what the p-value quantifies. The rigour is not in the size of the sample; it is in the honesty of the unit. See our evaluation statistics lesson and the error bars on evals veanor for the general machinery, and regression testing for ML for turning this into a gate.

Cheat sheet

QuantityDefinitionRange observedWhat it tells you
RRraw reply, raw transport78.6–100.0%direct-path competence; nearly saturated at the frontier
RNsame reply, nested transport19.6–30.4%portability — the number nobody reports
NRboundary-aware reply, raw transport33.9–83.9%the cost of adapting to a boundary that is not there
NNboundary-aware reply, nested transport14.3–91.1%deployed-path competence
DamageRN − RR−55.4 to −73.2what the channel destroys, with the model held fixed
CompensationNN − RN−5.4 to +60.7what the model rebuilds when told about the channel
Matched gapNN − RR = damage + compensation−64.3 to −3.6the only one a conventional benchmark prints
Interaction(NN − NR) − (RN − RR)−7.1 to +119.6whether the adaptation is boundary-specific
"What I cannot create, I do not understand."
You can build the entire measurement this afternoon. Three tasks with byte-exact validators, one model, two prompts differing by one sentence, and a replay loop that runs each stored reply through 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.
Exit gate — teach it back before you leave.

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.

References

  1. S. Li, Y. Zhang, V. Tresp, Y. Yang. "QuoteBench: How Matched Scores Can Hide Command-Path Failures." arXiv preprint arXiv:2608.13547, 2026. arXiv
  2. Free Software Foundation. "Bash Reference Manual, version 5.3." 2025. — the quoting and expansion rules traced in Chapter 1.
  3. D. A. Wheeler. "Fixing Unix/Linux/POSIX Filenames." 2010. — the hostile-filename hazards behind one mechanism group.
  4. V. Holen. "ShellCheck: a static analysis tool for shell scripts." — flags only 34.6% of the nested-only failures.
  5. X. V. Lin, C. Wang, L. Zettlemoyer, M. D. Ernst. "NL2Bash: a corpus and semantic parser for natural language interface to the Linux operating system." LREC, 2018. arXiv
  6. M. Agarwal et al. "NeurIPS 2020 NLC2CMD competition: translating natural language to Bash commands." arXiv:2103.02523, 2021. arXiv
  7. F. Westenfelder, E. Hemberg, S. Moskal, U. O'Reilly, S. Chiricescu. "LLM-supported natural language to Bash translation." NAACL, 2025.
  8. L. Yu et al. "BashCoder-R1: towards robust and explainable Bash code generation with robustness-aware group relative policy optimization." arXiv:2606.27733, 2026. arXiv
  9. J. Yang, C. E. Jimenez, A. Wettig, K. Lieret, S. Yao, K. Narasimhan, O. Press. "SWE-agent: agent-computer interfaces enable automated software engineering." NeurIPS, 2024.
  10. M. A. Merrill et al. "Terminal-Bench: benchmarking agents on hard, realistic tasks in command line interfaces." arXiv:2601.11868, 2026. arXiv
  11. Y. Zhang, J. Wang, Y. Ge, W. Xu, J. Hamm, C. K. Reddy. "Stop comparing LLM agents without disclosing the harness." arXiv:2605.23950, 2026. arXiv
  12. Z. Wang, B. Yu, J. Xu, Z. Li. "Action boundary blindness: when LLM agents cannot tell where one action ends and another begins." ACL, 2026.
  13. B. Yu, Y. Zhu, P. He, D. Kang. "UTBoost: rigorous evaluation of coding agents on SWE-bench." ACL, 2025. — permissive validators accepting incorrect patches.
  14. M. Sclar, Y. Choi, Y. Tsvetkov, A. Suhr. "Quantifying language models' sensitivity to spurious features in prompt design." ICLR, 2024. — the input-side analogue that regeneration cannot decompose.
  15. W. Zhang et al. "CARE: pre-execution command verification for shell-executing LLM agents." arXiv:2607.21642, 2026. arXiv
  16. X. Wang, Y. Chen, L. Yuan, Y. Zhang, Y. Li, H. Peng, H. Ji. "Executable code actions elicit better LLM agents." ICML, 2024. — CodeAct, changing the action language itself.
Your team runs an internal shell-command benchmark and reports a single number per model. What is the smallest change that would make the number honest?