The 0.70 points are not the result in this experiment. The KV cache is.
You handed it Mini, so the architecture was never the AI's to invent. Nano's config is Mini's: QK norm, head_dim 64, 2 KV heads, rope theta 100,000, 4,096 context, rms eps 1e-6, SwiGLU, tied embeddings, byte-identical tokenizer.json (same oid, 552,335 bytes). Both cards carry the same 30B mix, same effective batch of 132, same 1,750 warmup, same WSD schedule, same z-loss 1e-4 until 12B then off, same seed 1337. And both land on step 55,485 with 29,999,726,592 tokens seen. To the token.
So two things here were actually the AI's.
Peak LR 3.0e-3 against Mini's 2.3e-3. Right direction for a narrower model.
And this one, which I think is the find. Mini cannot decode incrementally. Its prepare_inputs_for_generation hardcodes use_cache: False, its forward accepts past_key_values and never reads it, and it returns past_key_values=None. Every generated token recomputes the whole prefix. Nano wires up DynamicCache with per-layer layer_idx, shifts the causal mask by past_length, left-pads the key mask out to kv_len, and drops the override so GenerationMixin threads the cache. It also refuses past 4,096 instead of quietly extrapolating rope.
That is a latency fix sitting in your own family, and it is a bigger deal than 0.70 on a four-task mean.
On the score, the arithmetic does reconcile off both configs:
+1,083,136 params = 787,072 the 10th block 72.7%
+ 294,912 heads 8x32 -> 4x64 27.2%
+ 1,152 QK norm 0.1%
QK norm is 1,280 weights, 0.013% of Nano. So the clean run is cheaper than what I asked for last time. Not equal budget. Just v4's config plus QK norm, at 1,024 context and 16.6B tokens, seed 1337.
One more, on data rather than code. v4's line has never seen DCLM. V1 and v2 are FineWeb-Edu, v3 adds FineMath, v4 continues on Cosmopedia. 9.0B of Nano's tokens, 30% of the run, come from a corpus the other arm has never touched. A human picked that.
Did the AI find the cache gap on its own, or did you point it there?