Godfrey Osagiede · Lab Notes raw receipts: github.com/godfreystorm/ratchet-lab
Ratchet Lab · Run 10 · gpt-oss-20b via Groq, 14 colonies, the replication that failed — and the last run of the series

The Receiver Problem

Two dark ledger pages side by side carrying the same handwritten rules in the same hand. The left page's result reads minus 5.9 in warm amber; the right page's reads minus 0.3 in faint blue-grey, almost illegible.
Why this run exists

Run 9 established that injected lessons cut the child crash rate by about six points. Every number in it is a statement about one model. The honest form of that headline was always "lessons work — in gpt-oss-120b."

So this run decides which sentence the series is entitled to publish. If the effect survives on a weaker model it is a property of the method. If it disappears it was a property of that model, and Run 9 needs the caveat in its first paragraph rather than buried in a footnote. Registered in advance, exactly as Run 9 was, with the clustered analysis declared up front this time instead of run afterwards.

One rule was written into the script rather than into a note: 20b data is never pooled with 120b data. Different model, different crash profile, different baseline. The cross-model analysis block was physically deleted from run10-20b.sh, because a script that cannot make the mistake beats a comment asking nobody to.

Result — it does not replicate
Nothing. Not a smaller effect — nothing.
Run 9 · gpt-oss-120bRun 10 · gpt-oss-20b
trials174182
children per arm3,4803,640
baseline crash rate59.7%62.0%
with a lesson injected53.8%62.3%
difference+5.89 pts−0.30 pts
95% CI[+3.57, +8.21][−2.53, +1.93]
one-sided Fisher exactp < 0.0001p = 0.6141
clustered mean (n=14)+7.05−0.25
colonies positive13 / 147 / 14
The same lessons, two models — crash-rate reduction per colony (percentage points) gpt-oss-120b (Run 9) — 13 of 14 positive gpt-oss-20b (Run 10) — 7 of 14, i.e. a coin -8 -4 0 4 8 12 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 mean +7.05 mean -0.25 colony (paired: same protocol, same arena, same lessons pipeline — only the model differs)

Twenty-eight colonies, one protocol, one arena, one lessons pipeline. The only thing that changes between the amber bars and the blue ones is which model wrote the bots.

This is a strong null, not a failed search

Two alternative explanations were named in the pre-registration before the data existed, so that neither could be reached for afterwards. Both are ruled out.

It is not underpowered. Run 10's confidence interval is tighter than Run 9's, on slightly more data — and the two intervals do not overlap. Run 9's lower bound of +3.57 sits above Run 10's upper bound of +1.93. This run does not merely fail to find the effect; it excludes an effect the size Run 9 measured.

It is not a ceiling artifact. The obvious objection to a null on a weaker model is that its crash rate is already so high there is no room to improve. The 20b baseline is 62.0% against 120b's 59.7% — 2.3 points apart. There is no ceiling. Seven of fourteen colonies positive is precisely what a coin produces.

What it means

The lessons are the same text. Distilled by the same code, injected into the same prompts, judged by the same gate, in the same arena. gpt-oss-120b can comply with "never reference lib outside act" when reminded. gpt-oss-20b cannot — its crashes are capability failures rather than attention failures, and no standing instruction reaches those.

Transmitted knowledge is worth nothing to a receiver who cannot act on it.

Put beside Run 9, the series closes on a matched pair rather than a single result. Run 9: a culture that only adopts what one member can personally prove will correctly reject nearly everything true. Run 10: even perfectly transmitted truth is inert if the members cannot execute it. Culture needs both — a mechanism able to accept small-effect truths, and members able to run them. Each failure was produced separately here, under identical protocol, for about twenty-three dollars.

It also retroactively vindicates the series' most-repeated tic. Every conclusion in these notes was written "for this model." Run 7's "largely placebo" was wrong for 120b — and, it turns out, literally correct for 20b.

The prediction, scored — wrong twice, the same way

The registration predicted 50% that the effect would replicate smaller, 25% that it would hold at full size, 20% null, 5% reversal. The 20% branch landed.

That is two for two on getting magnitude wrong. In Run 9 the argument was that a noisy estimate would regress, and it grew. Here the argument was that a weaker model would comply less but still comply somewhat, and it complied not at all. The error is identical both times: a confident mechanistic story about what ought to happen, allowed to set the estimate. The lab's own lesson applies to the person running it — a plausible mechanism is not evidence. Recorded because a prediction that only gets graded when it is right is not a prediction.

The ending: the loss is not in rejecting, it is in forgetting

Run 9's finding — that individually-correct skepticism discards collectively-true knowledge — reads like a tragedy with no way out. It is not, and the way out was obvious to the first person who looked at it without the statistics in the way. Why does the colony delete what it rejects?

Because it did. A rejected lesson left behind exactly this:

rejected: { "lib is not defined": 96 }

A signature and a counter. The distilled knowledge itself — the sentence a bot had died to produce — was erased. Agent one finds something. Agent two tries it, it does not work for them, and agent two burns the note rather than writing "did not work for me" underneath it.

The half of Run 9's finding that is genuinely structural is small: one agent holding twenty samples cannot resolve a six-point effect. That is arithmetic, and no design fixes it. But "therefore the knowledge is lost" does not follow from it. That part is a choice, and this lab made the wrong one for nine runs.

The proof is embarrassing and sits in this repository. Run 9's entire finding was recoverable only because trial records started being kept partway through — a change made for statistical bookkeeping, not for this reason. Under the original design those verdicts were unrecoverable and the six-point effect would have been reported as non-existent. And Run 10 is the same argument in data: one lesson, two models, two opposite verdicts. Under delete-on-failure that is a contradiction and one verdict gets erased. Under keep-with-context it is the most interesting result in the series.

So the gate does not disappear. It moves.

  • "Should I remember this?" — always yes. Storage is cheap; deletion is irreversible; a rejection carries as much information as an acceptance.
  • "Should I act on this yet?" — gated, revisable, and the answer changes as evidence accumulates across agents who each could not see it alone.

Run 5 is why the second question still needs asking: a colony that keeps everything and obeys it canonized a law about state.arena.walls, a field which does not exist, and its bots died with "safety guard" comments in their source. Keeping is not believing.

The loss is not in rejecting. It is in forgetting. Keep every verdict with its context attached, gate action rather than memory, and the pooled truth reassembles itself for free.

Which is the practical finding for anyone building agent memory, and the note this series ends on. A self-validating memory that checks each entry on its own and deletes what fails will be honest, well-engineered, and will converge on an empty store — while the aggregate of what it discarded would have helped. Do not validate memories one at a time. Keep the rejections, keep who rejected them and under what conditions, and gate what you act on rather than what you retain.

What this run cost

14,047 API calls · $5.08–$6.43 (gpt-oss-20b via Groq — half the per-token rate of every earlier run, and twice the speed).

Series total, all ten runs: 30,726 calls · $25.21–$31.45. Call counts are exact, straight from each run's metrics file. Costs are a range because the provider bills cached input tokens at half price and does not report the cached fraction in the API response, only in the console dashboard, so the upper bound prices every input token as uncached and the lower bound prices all of them as cache hits. Runs before Run 8 additionally reconstruct tokens from a measured per-call profile, because the usage field was discarded before it was ever written down. A bound is not a measurement and a reconstruction is neither, so both are labelled.

Raw receipts — every archive, lessons ledger, metrics file, and match replay: github.com/godfreystorm/ratchet-lab