devlog.

AgentGB · Measurement

Every failure was the same starter

A twenty-six agent swarm completed the whole sixteen-link chain 88.5% of the time. That is a good number, it was correctly computed, and it was hiding something a table structurally cannot show: all three failures were the same starter Pokémon. Not most. All. One chance in 2,600.

88.5%
What the table said
0 / 3
Squirtle runs that finished
0.00038
p, under a no-species-effect null
26 / 26
After three fixes

The number was fine. That was the problem.

Twenty-three of twenty-six agents completed every milestone from a cold boot: out of the bedroom, up Route 1, into the Mart, back down again, and the Pokédex in hand. The confidence interval was reported, the failures were located to a tile, and the three that stopped were noted as stopping in Oak's Lab and on Route 1.

Everything about that report was true. Nothing about it said that one entire third of the population failed every single time it was drawn.

The reason it was caught at all is that the captain watched the film rather than reading the table. Twenty-six agents on screen at once, each in its own cell, each playing its own run — and the eye does something a summary statistic does not. It groups. Three agents stuck in the same room, and all three had the same Pokémon.

BEFORE — 23 / 26 = 88.5% BULBASAUR 21/21 · CHARMANDER 2/2 · SQUIRTLE 0/3 B B B B B B B B B B B B B B B B B B B B B C C S S S AFTER THREE FIXES — 26 / 26 = 100.0% BULBASAUR 21/21 · CHARMANDER 2/2 · SQUIRTLE 3/3 B B B B B B B B B B B B B B B B B B B B B C C S S S
The same twenty-six runs, before and after. B, C and S are the starter each agent chose for itself — the harness reads it back off the cartridge, and the network never sees it. Every dashed cell is a run that did not finish. The aggregate moved from 88.5% to 100.0%, but the aggregate is not the finding. The shape is.

One in two thousand six hundred

"All three failures were the same thing" is exactly the sort of pattern a human finds in noise, so: with 21 Bulbasaur, 2 Charmander and 3 Squirtle runs and no species effect at all, the probability that the three failures land on the three Squirtle runs is about 1 in 2,600. p ≈ 0.00038.

That is not a coincidence you shrug at. And it was the second time this exact shape of bug had appeared in this project, which is what turned it from an incident into a rule.

The standing order that came out of it

Report per starter on every certification and every swarm. Not when it looks relevant. Every time. An aggregate over a population with a structural split in it is a number that is simultaneously correct and useless.

Why the film sees what the table cannot

Not because a film is nicer to look at. Because of what each representation can carry.

A completion table has one row per milestone and one rate per row. It is a marginal — it has already summed over the population, and a correlation between a run's hidden attribute and its outcome is exactly the information summing destroys. You cannot recover it from the table no matter how carefully you read, because it is not in the table.

The film has not summed over anything yet. Every agent is still a separate object on screen, carrying everything about itself, and the failures are visible as a group — three cells stuck in the same room at the same time is a thing you see rather than compute.

The swarm film is not a nicer way of showing the number. It is the only artefact in the pipeline where the population has not been collapsed yet.

What this cost, and what it bought

It is not free. The film that showed this takes roughly twenty-four screenshots per decision per agent — gigabytes — where the table costs nothing but the emulation. It is the expensive artefact, and this is what it is for.

Three separate causes, none of them the one first suspected

The obvious hypothesis was that the training corpus was biased toward one starter, so the student was simply worse with the others. That was checked, and it is not what was happening.

The starter choice is genuinely balanced. At the chain's own entry state the first decision carries 0.992 bits of entropy, and over 500 sampled attempts the committed student takes Bulbasaur 254 times, Squirtle 127 and Charmander 118, reaching the goal in 499 of 500. That is a real three-way split, not a collapse.

What was true, and actionable, is narrower and less obvious: two of the links on the return leg have exactly one recorded start state each, so their corpora contained zero species variation — regardless of how balanced the entry choice was. The student had simply never been shown those rooms with a Squirtle in the party.

Pulling the three failures apart gave three unrelated causes:

Two agents

Reached Oak and never spoke to him

They walked into him, forever. At the four interaction tiles, facing correctly, the base policy's own prediction is the right button only 4.55% of the time — the corpus mostly demonstrates the dialogue that follows the first press, not the press that starts it.

Fixed with a dedicated goal whose positives were harvested structurally from the link's own existing corpora at the four declared tile-and-facing spots.

One agent

Deadlocked in a battle menu for 3,600 decisions

Traced directly on a real seed: a wild Rattata at 8/23 HP, and the agent pressed right forever with the HP never once changing. The return crossing of Route 1 was still set to flee-only — the exact state the outbound crossing had been in before its own upgrade.

It was also explicitly ruled out that the trainer-battle goal was false-firing here: its own history had stopped growing well before the deadlock began.

One agent

Whited out and never recovered

The rule that a whiteout must not end a run was already active. The real gap was that nothing had ever taught the student what to do once it wakes up at home.

Fixed for free: a whiteout this early teleports the party to the player's own house, and the link's goal is simply "be outdoors in Pallet Town" — so walking out of the house satisfies it, and two existing links already do exactly that at 100%. No new data was collected at all.

The fix that broke everything, and what it taught

The first wiring of the Oak-interaction goal took the whole chain from 88.5% to 0 of 150.

The trigger tile it had been trained on — one specific tile, facing one specific direction — is, independently, the chain's own entry tile for taking a starter six links earlier. Same physical room, visited three times by this chain for three different reasons. An ungated goal that fires whenever it recognises its screen fired on the very first approach to the Poké Balls and broke every single run.

The fix was structural rather than a heuristic: the late-chain goals are now only ever consulted once a return-leg stage has already latched. Not by convention — by construction. A screen that a return-leg goal happens to recognise can no longer hijack the outward leg, however visually identical it is to something further down the chain.

There is a general shape here worth naming. In a route that revisits the same rooms, a recogniser's precision is not a property of the recogniser. It is a property of the recogniser and the window of the episode it is allowed to look in. Ours was excellent at its job and catastrophic without a gate.

Where it landed

After the three fixes, an eight-agent smoke test first — 8/8 — before committing to the long run. Then a cold-boot certification at N=150:

Starter Completed the whole chain Rate 95% interval
BULBASAUR87 / 9096.7%90.7–98.9%
CHARMANDER13 / 13100.0%77.2–100.0%
SQUIRTLE45 / 4795.7%85.8–98.8%
All sixteen links145 / 15096.67%92.4–98.6%

No starter anywhere near zero, all three intervals overlapping heavily. The filmed swarm at N=26 came back 26/26 — the first time this chain's film has shown every starter completing at 100%, where the previous one showed a third of them at zero.

N=150 is not the project's 3,000-attempt convention, and bounds failure near 2%, not 0.1%. And Charmander's 13/13 has a lower interval bound of 77.2%: thirteen runs is evidence of not-obviously-broken, not of perfection.

What this actually generalises to

Very little of the above is about Pokémon.

An agent population with a self-selected hidden attribute — which tool it picked, which branch it took, which variant it was served — will produce an aggregate success rate that is arithmetically correct and behaviourally meaningless the moment that attribute correlates with outcome. The failure mode is not a wrong number. It is a right number answering a question nobody asked.

Two cheap defences came out of this. Break every rate down by the attribute, whether or not you expect it to matter. And keep one artefact in the pipeline where the population has not been collapsed yet — expensive, rarely looked at, and the only place a structural split is visible before it becomes a mystery.


Every figure here comes from this project's own swarm and certification tooling against one named weights file, recorded with its sample size, its temperature and its confidence interval. The starter each agent chose is read off the cartridge by the harness and is never visible to the policy. The mechanism the chain is built on has its own write-up: the wall you hit walking home. The wider arc is on the AgentGB progress page.

← Back to devlog