Experiments · E152

With everything else matched, does the whole brain search worse than the mushroom body alone?

Yes. The mushroom body found 5.5 alloys per run, the whole brain 0.5, although both read the same 4,064 Kenyon cells.

In the log: the matched control for the whole brain. Take two: the first launch never ran.

supersededDate not stated in the log; it was written between the commit of 2026-09-16 19:06 and the first commit that contains it, 2026-09-19 08:35generator · fly brain0 predictions · 4 result paragraphsEXPERIMENTS.md lines 9213–9220, lines 9254–9286, lines 9288–9290, lines 9292–9323, lines 9325–9369, lines 9371–9405, lines 9407–9414
exp E152 diagram
What E152 did and how it came out, drawn from this record and the files it names (book/assets/diagrams/exp/E152.svg).

Pre-registration

The pre-registration, as written

E152 relaunched against the rebuilt subset, matched to E145 in every other respect: 200 rounds x 4 proposals x 2 seeds, --known-penalty 1.0 --repeat-decay 1.0. The predictions above stand unchanged; only the substrate file they refer to is now real.

E152 gate: 241 passed, 2 skipped (878 s), after the import os move and the new data/malecns_mushroom.* asset. The rules' baseline of 227 is stale by 14 tests added since, 7 of them this session in test_published_odt.py. Nothing red.

One thing worth recording against myself: tests/test_verifier.py:: test_the_expansion_is_exact_at_every_pure_element already asserts the anchored-fit property I spent this hour re-measuring by hand to decide whether ce_8element_anchored was stale. The test was the faster answer and I did not look for it before reaching for the calculation.


Results

EXPERIMENTS.md · line 9254

E152 result, part 1 — the control could not have been a control, and the reason is worse than the bug.

Fixing the NameError was not enough. FORAGER_CIRCUIT=malecns_circuit.json would have loaded the whole brain again:

data/malecns_circuit.json   164,506 nodes   -> malecns_circuit.npz   25,135,527 edges
data/malecns_full.json      164,506 nodes   -> malecns_full.npz      25,135,527 edges

ids, groups, src, dst and contacts are all array_equal between the two, and both carry selection='full_asset_v3', type_regex='.'. When the whole brain was extracted the extractor wrote both names, and the 5,311-neuron mushroom-body circuit stopped existing on disk. Everything before E140 was measured on a file that is no longer there.

So the substrate comparison was not merely unrun — as specified it was unrunnable, and had the import bug not stopped it, E152 would have produced a second whole-brain number and I would have compared the whole brain against itself and reported the difference as a substrate effect.

Rebuilt, and the count is the check. scripts/brain/induce_subcircuit.py applies the original documented selection — type_regex = "^(KC|MBON|PAM|PPL|APL)|PN", whose 20,000 cap never bound — to the full asset's own type annotations:

regex selects                5,311 nodes     (the documented count, exactly)
induced edges            1,066,603           4.243% of the parent's
largest weak component       5,311 of 5,311  nothing disconnected

Recovering 5,311 rather than a number near it is what says this is the same selection and not a new substrate wearing an old name. Written as data/malecns_mushroom.* under its own name; malecns_full.* untouched, and nothing overwrites malecns_circuit.* again.

This does not soften the standing rule that the whole brain is the substrate. The subset exists so the whole brain can be measured against something, which is the only way the rule can be shown to be worth following.

EXPERIMENTS.md · line 9292

E152 result, part 2 — the duplication audit, run immediately because the first one went unnoticed for a week.

Content-hashed all 30 files in data/. Three byte-identical groups:

malecns_circuit.npz  ==  malecns_full.npz          607.2 MB   <- the destructive one
ce_8element.icet     ==  ce_8element_anchored.icet
ce_8element.npz      ==  ce_8element_anchored.npz    2.3 MB

The second pair is benign, and this was checked rather than assumed. E80 refitted the expansion against the eight elemental corners and E82 re-measured the ladder under it, so the two names existing with one content admits two readings: the anchored fit became the default (harmless), or the refit never wrote and "anchored" is a stale copy (which would make E82 a comparison of a file with itself).

The corners decide it. An anchored fit is exact at the pure elements; E72 measured the unanchored fit at 58 meV/atom wrong at pure Mo. ce_8element.npz predicts:

Hf  +0.21   Mo  -4.26   Nb  -0.05   Ta  +0.91
Ti  +1.13   V   -1.41   W   -3.04   Zr  +0.10   meV/atom

All eight within 4.3 meV/atom of zero. ce_8element is the anchored fit, both names point at it, and E80/E82 stand. refit_ce_with_elements.py is the only reader of the _anchored name and it only ever writes it.

The connectome pair is the destructive one and is now repaired by adding a file, not by deleting one. The distinction that matters: the CE case overwrote a superseded artefact with its successor, which loses nothing; the connectome case overwrote a distinct artefact with an unrelated one, which lost the only copy of the substrate five experiments were measured on. Only the second kind can misattribute a result, and only the second kind was silent about it — provenance in both connectome files reads selection='full_asset_v3', so the file itself said what it was and nothing read it.

EXPERIMENTS.md · line 9325

E152 result, part 3 — the measurement. Two of my three predictions are falsified, and the falsified one is the one that matters.

arm                                    AUC_Q        distinct found   best meV
E145  whole brain, 164,506 nodes   0.15 +- 0.15     0.50 +- 0.50        -33
E152  mushroom body, 5,311 nodes   1.48 +- 0.48     5.50 +- 0.50        -94

Matched in every other respect: 200 rounds x 4 proposals x 2 seeds, --known-penalty 1.0 --repeat-decay 1.0, same reward, same verifier, same target.

Prediction 1 FALSIFIED. I said E152 would land in 0.1 to 0.8, on the reasoning that most of E136's 1.00 -> E145's 0.15 was the shorter budget and the reward change. It landed at 1.48, above E136's 1.00 on fewer rounds (200 against 300). So the budget and the reward change did not cost anything — the E133 reward separation helped — and the entire gap is the substrate.

Prediction 2 FALSIFIED. I said the two arms would not be separable at two seeds and that the experiment as specified could not answer its question. The difference is 1.33 against a combined error of 0.63, and the find counts do not overlap at all: 5.50 +- 0.50 against 0.50 +- 0.50. Two seeds were enough because the effect is an order of magnitude, not a margin. I was wrong about the power because I assumed the effect would be small.

Prediction 3 CONFIRMED, and it is now the live branch. E152 landed above 1.00, so on this measurement the whole brain, as currently wired, searches about ten times worse than the mushroom body alone — a tenth the AUC_Q, a ninth the finds, and 61 meV/atom shallower.

What this does and does not say. It is not an argument for going back to a subset. The standing instruction is that the whole brain is the substrate and the design job is the ladder and which parts of the brain each rung connects to. This is a measurement that the mapping is wrong, not that the substrate is — the fly has 164,506 neurons and does not search ten times worse than a fly with 5,311.

The named suspect, from this project's own record. KC sparsity was calibrated when 4,064 Kenyon cells were active; at 0.07% active (3 of 4,064) it starved all learning, and fixing it is what made the fly beat its frozen twin at p = 0.020. MushroomBody takes sparsity_target=0.06 as a fixed fraction and sets the threshold from a quantile of the drive distribution, so the fraction is held while the population grows 31-fold. Whether the populations MushroomBody selects actually grow on the whole brain — the regex is ^KC, and the whole asset carries 11,751 distinct types — is a one-line measurement and is the first task of the next hour.

Task 2 status: one of three runs answered, and it is the one that was worth running. Remaining: 5,311-with-novelty and whole-brain-with-novelty. Both are now less urgent than finding out why the whole brain loses, because a novelty term on a substrate that searches ten times worse is measuring the wrong thing.

EXPERIMENTS.md · line 9371

E152 result, part 4 — the mechanism, measured in the same hour. The readout is byte-identical on both substrates.

malecns_mushroom.json   n=  5,311   KC=4064  MBON=97  PAM=316  PPL=24  APL=2  PN=595
malecns_full.json       n=164,506   KC=4064  MBON=97  PAM=316  PPL=24  APL=2  PN=595
                                    plastic KC->MBON edges = 61,210 in BOTH

Every population MushroomBody uses is the same, and so is the plastic edge set. The whole brain's extra 159,195 neurons are in no population the learner reads, so they cannot carry information into the decision — and yet the whole-brain arm searches ten times worse.

This falsifies the KC-sparsity hypothesis I named an hour ago before it was tested: the KC population does not grow, so sparsity_target=0.06 is being applied to 4,064 cells in both cases and the threshold quantile is taken over the same population. That was the obvious suspect from this project's own record and it is wrong.

What is left is the only path by which those neurons can touch anything: they are in the graph, so they are in input_gain="auto" calibration and in whatever _kc_input propagates through circuit.src/circuit.dst. The extra 159,195 nodes and ~24 million edges change the drive distribution the gain is normalised against, while the cells that decide are unchanged. That is a scaling artefact in the input normalisation, not a property of the substrate.

The honest reading of "use the whole brain". On the current wiring the whole brain is loaded but not used: the readout is the same 4,064 KCs either way, and the other 97% of the brain enters only by perturbing a normalisation constant. Making the whole brain genuinely carry the computation is the mapping work the operator specified — deciding which rung connects to which region — and it has not been done. Nothing in this entry argues for a smaller substrate; it argues that the substrate is currently decorative.

Next hour, first task: instrument input_gain and the KC drive distribution on both assets. Predict before measuring: the auto gain will differ between them by a factor large enough to move the sparsity threshold off its calibrated operating point, and re-deriving the gain on the whole brain — or excluding non-mushroom-body nodes from the gain calibration only, leaving them in the graph — will close most of the 10x. If the gains are the same, that is falsified and the remaining path is _kc_input itself.

The full record

This entry is written in 7 separate places in the log, shown here in log order.

EXPERIMENTS.md · lines 9213–9220

E152 — the matched control for the whole brain. Take two: the first launch never ran.

Withdrawal of a process claim, not a result. Last hour I reported E152 as "launched". It was not. It raised NameError: name 'os' is not defined at stage_b.py:208 within a second of starting and wrote nothing but a traceback. import os sits at line 67, inside build(), so it covers the six os.environ reads in that function and not the seventh, which I added in main() for the FORAGER_CIRCUIT override. I declared a launch without looking at the log it wrote.

EXPERIMENTS.md · lines 9254–9286

E152 result, part 1 — the control could not have been a control, and the reason is worse than the bug.

Fixing the NameError was not enough. FORAGER_CIRCUIT=malecns_circuit.json would have loaded the whole brain again:

data/malecns_circuit.json   164,506 nodes   -> malecns_circuit.npz   25,135,527 edges
data/malecns_full.json      164,506 nodes   -> malecns_full.npz      25,135,527 edges

ids, groups, src, dst and contacts are all array_equal between the two, and both carry selection='full_asset_v3', type_regex='.'. When the whole brain was extracted the extractor wrote both names, and the 5,311-neuron mushroom-body circuit stopped existing on disk. Everything before E140 was measured on a file that is no longer there.

So the substrate comparison was not merely unrun — as specified it was unrunnable, and had the import bug not stopped it, E152 would have produced a second whole-brain number and I would have compared the whole brain against itself and reported the difference as a substrate effect.

Rebuilt, and the count is the check. scripts/brain/induce_subcircuit.py applies the original documented selection — type_regex = "^(KC|MBON|PAM|PPL|APL)|PN", whose 20,000 cap never bound — to the full asset's own type annotations:

regex selects                5,311 nodes     (the documented count, exactly)
induced edges            1,066,603           4.243% of the parent's
largest weak component       5,311 of 5,311  nothing disconnected

Recovering 5,311 rather than a number near it is what says this is the same selection and not a new substrate wearing an old name. Written as data/malecns_mushroom.* under its own name; malecns_full.* untouched, and nothing overwrites malecns_circuit.* again.

This does not soften the standing rule that the whole brain is the substrate. The subset exists so the whole brain can be measured against something, which is the only way the rule can be shown to be worth following.

EXPERIMENTS.md · lines 9288–9290

E152 relaunched against the rebuilt subset, matched to E145 in every other respect: 200 rounds x 4 proposals x 2 seeds, --known-penalty 1.0 --repeat-decay 1.0. The predictions above stand unchanged; only the substrate file they refer to is now real.

EXPERIMENTS.md · lines 9292–9323

E152 result, part 2 — the duplication audit, run immediately because the first one went unnoticed for a week.

Content-hashed all 30 files in data/. Three byte-identical groups:

malecns_circuit.npz  ==  malecns_full.npz          607.2 MB   <- the destructive one
ce_8element.icet     ==  ce_8element_anchored.icet
ce_8element.npz      ==  ce_8element_anchored.npz    2.3 MB

The second pair is benign, and this was checked rather than assumed. E80 refitted the expansion against the eight elemental corners and E82 re-measured the ladder under it, so the two names existing with one content admits two readings: the anchored fit became the default (harmless), or the refit never wrote and "anchored" is a stale copy (which would make E82 a comparison of a file with itself).

The corners decide it. An anchored fit is exact at the pure elements; E72 measured the unanchored fit at 58 meV/atom wrong at pure Mo. ce_8element.npz predicts:

Hf  +0.21   Mo  -4.26   Nb  -0.05   Ta  +0.91
Ti  +1.13   V   -1.41   W   -3.04   Zr  +0.10   meV/atom

All eight within 4.3 meV/atom of zero. ce_8element is the anchored fit, both names point at it, and E80/E82 stand. refit_ce_with_elements.py is the only reader of the _anchored name and it only ever writes it.

The connectome pair is the destructive one and is now repaired by adding a file, not by deleting one. The distinction that matters: the CE case overwrote a superseded artefact with its successor, which loses nothing; the connectome case overwrote a distinct artefact with an unrelated one, which lost the only copy of the substrate five experiments were measured on. Only the second kind can misattribute a result, and only the second kind was silent about it — provenance in both connectome files reads selection='full_asset_v3', so the file itself said what it was and nothing read it.

EXPERIMENTS.md · lines 9325–9369

E152 result, part 3 — the measurement. Two of my three predictions are falsified, and the falsified one is the one that matters.

arm                                    AUC_Q        distinct found   best meV
E145  whole brain, 164,506 nodes   0.15 +- 0.15     0.50 +- 0.50        -33
E152  mushroom body, 5,311 nodes   1.48 +- 0.48     5.50 +- 0.50        -94

Matched in every other respect: 200 rounds x 4 proposals x 2 seeds, --known-penalty 1.0 --repeat-decay 1.0, same reward, same verifier, same target.

Prediction 1 FALSIFIED. I said E152 would land in 0.1 to 0.8, on the reasoning that most of E136's 1.00 -> E145's 0.15 was the shorter budget and the reward change. It landed at 1.48, above E136's 1.00 on fewer rounds (200 against 300). So the budget and the reward change did not cost anything — the E133 reward separation helped — and the entire gap is the substrate.

Prediction 2 FALSIFIED. I said the two arms would not be separable at two seeds and that the experiment as specified could not answer its question. The difference is 1.33 against a combined error of 0.63, and the find counts do not overlap at all: 5.50 +- 0.50 against 0.50 +- 0.50. Two seeds were enough because the effect is an order of magnitude, not a margin. I was wrong about the power because I assumed the effect would be small.

Prediction 3 CONFIRMED, and it is now the live branch. E152 landed above 1.00, so on this measurement the whole brain, as currently wired, searches about ten times worse than the mushroom body alone — a tenth the AUC_Q, a ninth the finds, and 61 meV/atom shallower.

What this does and does not say. It is not an argument for going back to a subset. The standing instruction is that the whole brain is the substrate and the design job is the ladder and which parts of the brain each rung connects to. This is a measurement that the mapping is wrong, not that the substrate is — the fly has 164,506 neurons and does not search ten times worse than a fly with 5,311.

The named suspect, from this project's own record. KC sparsity was calibrated when 4,064 Kenyon cells were active; at 0.07% active (3 of 4,064) it starved all learning, and fixing it is what made the fly beat its frozen twin at p = 0.020. MushroomBody takes sparsity_target=0.06 as a fixed fraction and sets the threshold from a quantile of the drive distribution, so the fraction is held while the population grows 31-fold. Whether the populations MushroomBody selects actually grow on the whole brain — the regex is ^KC, and the whole asset carries 11,751 distinct types — is a one-line measurement and is the first task of the next hour.

Task 2 status: one of three runs answered, and it is the one that was worth running. Remaining: 5,311-with-novelty and whole-brain-with-novelty. Both are now less urgent than finding out why the whole brain loses, because a novelty term on a substrate that searches ten times worse is measuring the wrong thing.

EXPERIMENTS.md · lines 9371–9405

E152 result, part 4 — the mechanism, measured in the same hour. The readout is byte-identical on both substrates.

malecns_mushroom.json   n=  5,311   KC=4064  MBON=97  PAM=316  PPL=24  APL=2  PN=595
malecns_full.json       n=164,506   KC=4064  MBON=97  PAM=316  PPL=24  APL=2  PN=595
                                    plastic KC->MBON edges = 61,210 in BOTH

Every population MushroomBody uses is the same, and so is the plastic edge set. The whole brain's extra 159,195 neurons are in no population the learner reads, so they cannot carry information into the decision — and yet the whole-brain arm searches ten times worse.

This falsifies the KC-sparsity hypothesis I named an hour ago before it was tested: the KC population does not grow, so sparsity_target=0.06 is being applied to 4,064 cells in both cases and the threshold quantile is taken over the same population. That was the obvious suspect from this project's own record and it is wrong.

What is left is the only path by which those neurons can touch anything: they are in the graph, so they are in input_gain="auto" calibration and in whatever _kc_input propagates through circuit.src/circuit.dst. The extra 159,195 nodes and ~24 million edges change the drive distribution the gain is normalised against, while the cells that decide are unchanged. That is a scaling artefact in the input normalisation, not a property of the substrate.

The honest reading of "use the whole brain". On the current wiring the whole brain is loaded but not used: the readout is the same 4,064 KCs either way, and the other 97% of the brain enters only by perturbing a normalisation constant. Making the whole brain genuinely carry the computation is the mapping work the operator specified — deciding which rung connects to which region — and it has not been done. Nothing in this entry argues for a smaller substrate; it argues that the substrate is currently decorative.

Next hour, first task: instrument input_gain and the KC drive distribution on both assets. Predict before measuring: the auto gain will differ between them by a factor large enough to move the sparsity threshold off its calibrated operating point, and re-deriving the gain on the whole brain — or excluding non-mushroom-body nodes from the gain calibration only, leaving them in the graph — will close most of the 10x. If the gains are the same, that is falsified and the remaining path is _kc_input itself.

EXPERIMENTS.md · lines 9407–9414

E152 gate: 241 passed, 2 skipped (878 s), after the import os move and the new data/malecns_mushroom.* asset. The rules' baseline of 227 is stale by 14 tests added since, 7 of them this session in test_published_odt.py. Nothing red.

One thing worth recording against myself: tests/test_verifier.py:: test_the_expansion_is_exact_at_every_pure_element already asserts the anchored-fit property I spent this hour re-measuring by hand to decide whether ce_8element_anchored was stale. The test was the faster answer and I did not look for it before reaching for the calculation.

Related entries

Built with PRISMWebsite and visualizations made using Claude