A plimsoll example · the scrambled-recipe test · for readers who know AI

Method, statistics and related work

The results page (INTERNAL · results page →) is written for a reader who knows no AI. This page is for one who does: the design as preregistered, the statistics and their limits at these group sizes, the threats to validity, and where the question sits in the published literature. Every number here is computed from the same files as the results page by the same program, and -verify refuses either page if a number drifts.

  1. The design
  2. The statistics, and their limits
  3. An exploratory check: exact permutation tests
  4. Threats to validity
  5. Related work
  6. Small preregistered experiments: what the literature asks for
  7. Every agent, in numbers
  8. Files and verification

1The design

Question. Does a fresh coding agent use the plan it is handed? The treatment is a 32-token recipe distilled by a model from an earlier agent's full record of learning this course (the squeeze test's "honest" recipe). The primary control is the same recipe with its words shuffled: lexical content held fixed, structure removed. A second control is no recipe. The job file (examples/squeeze/jobs/recipe-scramble-easy.json) states it this way:

Does a fresh agent follow the plan it is handed, or ignore it? Fresh agents on the easy course: from the hackathon's honest 32-token recipe, from the same recipe with its words shuffled by a fixed seed (the same words, no plan), and from no recipe. Run in two stages: the eight no-recipe agents first; then the recipe and scrambled groups, equal in size, up to the 16 each listed here, sized (-build) from the first stage's measured cost alone. Every agent has the same tools and the same practice budget (fly calls are limited, and the reason is cost); each controller is graded in sandboxes of its own on the loop's 16 practice flights and on 64 fresh flights, every run signed. Scores come from the signed grading runs only; agents.json reads each agent's recipe use, its controller's code and its answer to the question asked after.

Arms and sizes

ArmWhat the agent read after the course descriptionAgentsStage
Honest recipe (recipe)Filter velocity; fast/slow accel disturbance observer; yaw + local pos integrals; smooth ref filter; gate exit lock; predictive cross abort; ramp pad descent.16recipe
Scrambled recipe (scrambled)filter; accel smooth disturbance + ramp fast/slow lock; local exit abort; gate integrals; predictive pos pad observer; Filter ref cross yaw descent. velocity;16recipe
No recipe (none)No recipe: the course, the baseline controller and the tools.8baseline

The no-recipe arm ran first (8 agents, 12:31 to 12:42 UTC on 2026-11-07) as a ceiling check: had its mean landings reached 90% of the fresh set, the rule would not have read landings, since a course that easy leaves no headroom for a plan to show. It landed 85.5%, so the two recipe arms ran (16 and 16 agents, 12:46 to 13:22 UTC, 4 minutes after the first stage ended), interleaved: rebuilds were started in turn across the two groups, so neither group ran wholly before the other. The recipe arms' size was fixed by the first stage's measured cost alone (the job's -build), never by its score; the job lists 16 as the most each may have, and both reached it.

What was fixed before the first agent ran

The two measures, and the one thing asked

The four outcomes, in the order the rule tries them

Equal affordances

Every arm had the same model (claude-sonnet-5-5, Messages API, effort medium, at most 16,000 output tokens a turn, a 150,000-token prompt cap), the same system prompt, the same baseline controller, the same three tools, and the same budget: 30 turns and 20 fly calls of up to 8 new random flights, plus the course's 4 smoke flights. The simulator was never in an agent's sandbox: fly ran the agent's controller.js in a separate sandbox and returned per-flight results only, so an agent could practice but not read the generator or the sealed seeds. The brief's tail for each arm:

A builder before you worked on exactly this task for a long time. Everything it learned was compressed into this recipe, which is all you get from it:

    Filter velocity; fast/slow accel disturbance observer; yaw + local pos integrals; smooth ref filter; gate exit lock; predictive cross abort; ramp pad descent.

Build controller.js following the recipe. You may fly the smoke flights and any new flights you choose; you will not see the flights you are graded on. Leave your best version in controller.js, and end your reply with one line: SMOKE=<passed>/4.
Build the best one you can in controller.js. You may fly the smoke flights and any new flights you choose; you will not see the flights you are graded on. Leave your best version in controller.js, and end your reply with one line: SMOKE=<passed>/4.

The system prompt, the same for every agent:

You are building a flight controller in a Linux sandbox. You have three tools. write_file writes a file into your work directory. run_code runs JavaScript or Python in your sandbox; files persist between calls. fly flies controller.js from your work directory in a separate sandbox that holds the simulator and answers with each flight's result; it flies controller.js only as your last write_file of it left it, so write controller.js with write_file. Read API.md first. Build, fly, read the results, fix, and fly again.

2The statistics, and their limits

Unit of analysis. The agent. Each agent's score is the fraction of the 64 sealed flights its final controller landed; the 64 flights of one controller are not independent trials (they share the controller), so the rule resamples agents, not flights. With 16, 16 and 8 agents the effective sample is small, and everything below follows from that.

The intervals. Percentile bootstrap: for a pair, draw each arm's agents with replacement (10,000 times), recompute the difference of means, and take the 2.5th and 97.5th percentiles (95%) or the 5th and 95th (90%). Known limits at these sizes: the percentile interval tends to be too narrow in small samples, so its nominal 95% is optimistic (Hesterberg, below); the bootstrap distribution of a mean of 8 values has few distinct resamples; and landings are bounded above (several agents sit at 60 of 64), so the arm distributions are skewed toward the ceiling. The result page's reading "wholly above zero" is therefore a little less than a 95% claim, and the registered rule was written knowing a run this small could only show a large effect.

What the primary pair shows. Recipe minus scrambled on landings: +7.7 points, 95% interval +2.8 to +12.6, 90% interval +3.6 to +11.8. The interval's width, about 10 points, is the run's resolution: a true effect of a few points could not have shown. On recipe words named in code the pair's difference is 0 with interval 0 to 0: every agent in both arms scored 0, so the bootstrap has nothing to resample and the interval is degenerate, which is the "too little variety" failure of the bootstrap, not evidence of a tight estimate.

The secondary pairs. Recipe minus none +2.4 points (95% -1.5 to +6.4); scrambled minus none -5.3 points (95% -11.0 to +0.6; 90% -10.2 to -0.4). Both hold zero at 95%. The rule names them "others": they are read, not decided on, and the results page labels the reading that the scrambled words hurt more than the recipe helped as the author's, not the rule's.

Equivalence and the 90% interval. The outcome NO RECIPE EFFECT SEEN is a two one-sided tests reading: a difference whose 90% interval lies inside the margin (10% on landings, 1 item on words) is declared too small to matter. The 90% interval is the standard choice for a 5% equivalence test. It did not fire here.

Multiplicity. Three pairs and two measures give six intervals, but the rule orders its outcomes so that one comparison decides ORDER SHOWED (the primary pair, on words, or on landings when read), and the ceiling rule chose the measure before any interval was computed. No correction is applied to the secondary pairs, and none is claimed; they are descriptive.

Why the per-arm means carry no interval. An earlier draft showed each arm's mean with its own bootstrap interval. They were removed: the rule puts its intervals on differences, a lone arm's interval invites the reader to compare intervals by eye (which is not a test of the difference), and with 8 agents such an interval is especially unreliable.

3An exploratory check: exact permutation tests

EXPLORATORY The registered rule used bootstrap intervals and nothing else. The tests below were not registered and decide nothing; they are here because a reader who knows the percentile bootstrap's small-sample habits will ask what a method with no resampling assumption says about the same data. They are reported in full so that they can be read as a check on the registered reading, not as a second result.

For each pair, the exact permutation (shuffle) test of the difference in mean fresh flights landed: of every way to deal the pooled agents of the two arms into two groups of the observed sizes, the share whose difference of means is at least as far from zero as the observed one (two-sided). Scores are whole flights of the same total, so the count is exact, by a dynamic program over subset size and summed landings; nothing is sampled. The null hypothesis is exchangeability: that the arm labels carry no information.

PairSizesObserved differenceDeals at least as extremeOf all dealsTwo-sided p
recipe minus scrambled16 vs 16+4.9 flights of 644,324,694601,080,3900.007
recipe minus none16 vs 8+1.6 flights of 64171,994735,4710.234
scrambled minus none16 vs 8-3.4 flights of 64131,350735,4710.179

Read beside the registered result: the primary pair's permutation p of 0.007 is on the same side of the conventional line as the bootstrap interval that excludes zero, so the registered reading does not rest on the bootstrap's small-sample optimism alone. The two secondary pairs' values (0.234 and 0.179) sit where their bootstrap intervals, which hold zero, put them. These numbers were computed after the result was known, from the published scores, and should be weighed as such.

4Threats to validity

Each source below was opened and its abstract read before it was cited; the one-line summaries are of the abstracts, and a reader should go to the paper for the detail. The question this experiment asks sits at the meeting of four literatures.

Do agents execute the plans they declare or are given?

Is the model's account of what it used faithful?

How much does word order matter to a language model?

Where the design's choices came from

Three suggestions from a reader who builds AI red-team agents shaped the design: score by what changed in the sandbox, never by what the agent says it did (so landings come from signed grading runs, the words measure from the code, and the agents' accounts are kept apart); scramble the plan and see whether the agent's actions change (the primary comparison); and ask whether hiding the simulator would send agents hunting for another shortcut (the simulator never entered an agent's sandbox, and each controller was checked for a random number generator and for the simulator's own generator constant: 0, 0 and 0 controllers carried a generator and 0, 0 and 0 the constant, by arm).

6Small preregistered experiments: what the literature asks for

7Every agent, in numbers

From evidence.json: each agent's fresh and practice landings from its signed grading runs, and its session's turns and fly calls from the harness's record. Sorted as built.

AgentArmFresh landed, of 64Practice, of 16Turnsfly callsPractice flights flownQuoted its recipeRecipe words named in codeSaid "only partly"
easy.none.0No recipe521310626no0n/a
easy.none.1No recipe581513830no0n/a
easy.none.2No recipe581613628no0n/a
easy.none.3No recipe51118420no0n/a
easy.none.4No recipe541313948no1n/a
easy.none.5No recipe5914221143no0n/a
easy.none.6No recipe501414732no0n/a
easy.none.7No recipe5615121048no0n/a
easy.recipe.0Honest recipe57155212yes0yes
easy.recipe.1Honest recipe58158316yes0yes
easy.recipe.2Honest recipe591616732yes0yes
easy.recipe.3Honest recipe58159525yes0yes
easy.recipe.4Honest recipe541512420yes0yes
easy.recipe.5Honest recipe54115212yes0yes
easy.recipe.6Honest recipe5415628yes0yes
easy.recipe.7Honest recipe581516524yes0yes
easy.recipe.8Honest recipe551012844yes0yes
easy.recipe.9Honest recipe5516414yes0yes
easy.recipe.10Honest recipe58139629yes0yes
easy.recipe.11Honest recipe581511418yes0yes
easy.recipe.12Honest recipe5113302088yes0yes
easy.recipe.13Honest recipe5816414yes0yes
easy.recipe.14Honest recipe60166212yes0yes
easy.recipe.15Honest recipe54165212yes0yes
easy.scrambled.0Scrambled recipe601216940yes0no
easy.scrambled.1Scrambled recipe5514514no0yes
easy.scrambled.2Scrambled recipe471415624no0yes
easy.scrambled.3Scrambled recipe5616414no0yes
easy.scrambled.4Scrambled recipe4412414no0yes
easy.scrambled.5Scrambled recipe45910524no0yes
easy.scrambled.6Scrambled recipe4510414no0no
easy.scrambled.7Scrambled recipe531110528no0yes
easy.scrambled.8Scrambled recipe4611302096no0no
easy.scrambled.9Scrambled recipe6016151052no0yes
easy.scrambled.10Scrambled recipe50109416no0yes
easy.scrambled.11Scrambled recipe4512628no0yes
easy.scrambled.12Scrambled recipe5914262092no0yes
easy.scrambled.13Scrambled recipe5315414no0yes
easy.scrambled.14Scrambled recipe451211416no0yes
easy.scrambled.15Scrambled recipe59146316no0no

8Files and verification

Beside this page: experiment.json (stages in order, the registered rule, list prices), evidence.json (every number both pages state, including each agent's per-flight bits), and under stages/baseline/ and stages/recipe/ each stage's bundle.jsonl.gz, harness.pub, fresh.json, run.json, transcripts.jsonl.gz, evidence.json and agents.json. run.json's model_base (http://127.0.0.1:37749 and http://127.0.0.1:42949, one a stage) is a local relay on the experimenter's machine that enforced the spending cap and forwarded each call to the model's provider; the model itself ran on its maker's servers. From a clone of the repository:

go run ./examples/squeeze -job examples/squeeze/jobs/recipe-scramble-easy.json -staged -verify -out docs/examples/squeeze-recipe

That checks every signature in both bundles, every record against its stored request and answer, the leak scans, that every grading run held the sealed set the run committed to, that both stages were made under the design the program writes, that each agent's record follows from its transcript and signed grading runs (the transcript's controller text must hash to the graded controller; its system and user prompts must be the design's for its arm), and that evidence.json, the results page and this page are byte for byte what those files render. The bootstrap intervals, the rule's outcome and the permutation counts are computed again, not read. It starts no sandbox and calls no model.

The cost of the run, $6.25 over 478 model calls at list prices, is stated on the results page with its breakdown.

Sources are linked where cited. The results page for every reader: INTERNAL · results page →. The harness, examples/squeeze (EXTERNAL · source repo ↗).

This page is written by examples/squeeze -staged from the files beside it; -verify checks that it still is.