1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
# Phase 3 diagnostics — analysis notes (E4, E3, D1, D2)
Sources: `runs/phase3/summary.csv`, per-job `results.json`, `runs/phase3/logs/*.log`,
and the locked interpretation clauses in `design/preregistration.md` (Addendum 4 for E3/E4,
Addendum 5 for D1/D2). Structure per experiment: **LOCKED** clause, then **Commentary**
(measured result), **Caveats**, and **Implications for the [2,1000] phase (E6)**.
Constants used throughout: val EM is exact-match; "best" is the val-selected checkpoint
(selection-holed), "last" is the unselected final checkpoint. Probe for next_prime is
exact-match on [101, 200]; probe for is_prime (D1) is classification accuracy on [101, 200].
---
## E4 — halting=False ablation (RNN, seed 0)
**LOCKED** (Addendum 4): "Fixed-K (K = 20) beats the ACT RNN (same seed, val EM) → ACT
actively hurt it (consistent with H4). Equal or worse → the halt gate was not the problem."
Addendum 5 "E4 wd choice": Fixed-K at wd 0.1 (the RNN saturates train there) and wd 1.0
(control parity).
**Commentary.** Fixed-K (halting=False, K=20) vs the ACT RNN, same seed:
| wd | run | val EM best | val EM last | O | P | H | probe (101–200) | halt mean |
|----|-----|-------------|-------------|---|---|---|-----------------|-----------|
| 0.1 | Fixed-K | **0.767** | 0.367 | O-PARTIAL | P4 | H2 | 0 / 100 | 20.0 |
| 0.1 | ACT (E2 ctrl) | 0.700 | **0.567** | O-PARTIAL | P4 | H1 | 0 / 100 | 2.04 |
| 1.0 | Fixed-K | **0.433** | 0.167 | O4 | P4 | H2 | 0 / 100 | 20.0 |
| 1.0 | ACT (ctrl) | 0.367 | 0.167 | O4 | P4 | H4 | 1 / 100 | 3.12 |
On the **best** checkpoint Fixed-K beats ACT at both wd (+6.7 points at 0.1, +6.6 at 1.0),
which per the locked clause reads as "ACT actively hurt it". On the **last** checkpoint Fixed-K
does *not* beat ACT (it is −20.0 points at wd 0.1 and tied at wd 1.0), which reads "equal or
worse → the halt gate was not the problem". The clause says only "val EM" without specifying
best vs last, and the two metrics disagree, so the reading is metric-dependent. Either way the
**late-run rollover is not cured**: Fixed-K still decays 0.767→0.367 (wd 0.1) and 0.433→0.167
(wd 1.0), and the wd 1.0 cell is still O4 (train never sustains saturation) even with no gate.
**Caveats.** H2 (pinned at 20) is by construction for halting=False — it is not a finding.
The ACT comparison at wd 0.1 uses the E2 sweep run (`runs/e2-wd/wd0.1`) as the control, which
is the correct same-seed ACT RNN. Only two wd cells were run (per Addendum 5), both seed 0.
**Implications for E6.** ACT is not load-bearing: it is at most a minor tax on the *best*
checkpoint and was never the cause of the rollover or the O4 instability. The [2,1000] phase
can run the RNN with fixed-K (simpler, no worse on best) without losing anything, but must not
expect halting removal to stabilize training — the instability needs to be attacked via scale
(more data) or schedule, not via the gate.
---
## E3 — learning-rate annealing (both models, seed 0; cosine 1e-3 → 1e-4)
**LOCKED** (Addendum 4): "Targets the late-run val-EM decay. Final val EM ABOVE the
constant-lr control and no late-run decay → the rollover is optimizer dynamics. Identical or
below → the decay is solution instability (more fundamental)."
**Commentary.** Cosine-annealed runs (wd 1.0, control parity) vs the constant-lr control:
| model | run | val EM best | val EM last | O | P | H | probe (101–200) |
|-------|-----|-------------|-------------|---|---|---|-----------------|
| rnn | cosine | 0.367 | 0.167 | O4 | P4 | H4 | 0 / 100 |
| rnn | const-lr | 0.367 | 0.167 | O4 | P4 | H4 | 1 / 100 |
| transformer | cosine | 0.900 | 0.567 | O3 | P4 | — | 0 / 100 |
| transformer | const-lr | 0.867 | 0.700 | O-PARTIAL | P4 | — | 0 / 100 |
RNN: annealing changed nothing — best 0.367 = 0.367, last 0.167 = 0.167, still O4. Final val
EM is **identical** to the control → the decay is solution instability. Transformer: annealing
lifted the *best* checkpoint (0.900 vs 0.867, a new peak, now O3) but the *final* val EM fell
**below** the control (0.567 vs 0.700) — the rollover actually *deepened* (a 33.3-point drop
from peak vs the control's 16.7-point drop). Final val EM below the control → solution
instability. Neither model cleared the "above the control and no decay" bar, and no O1 appeared.
**Caveats.** The E3 clause keys off *final* val EM; the transformer's improved best is the
selection-holed number and does not rescue the reading. The e3-cos rnn halt_mean was 8.74 (H4,
noisy), vs ~3 for the control — the annealed RNN's gate stayed noisy, but H is not part of the
E3 clause. wd for the annealed runs is 1.0 (control parity); the prereg does not restate it in
the E3 clause itself.
**Implications for E6.** The rollover is not a learning-rate artifact — it is a property of the
solution (the memorization attractor re-asserting itself), so annealing alone will not stabilize
the [2,1000] run. E6's actual lever is the bigger range itself (≈700 examples makes the lookup
table stop fitting, which is the mechanism that could put the algorithmic basin within reach).
Keep a modest anneal if convenient, but do not expect it to buy stability.
---
## D1 — is-prime diagnostic (`task_mode=is_prime`, digits, seed 0; wd 1.0 both + wd 0.1 both)
**LOCKED** (Addendum 5): "is_prime groks (O1) while next_prime never did → the search/increment
loop is the wall, not the divisibility test. / is_prime reproduces next_prime's codes (no O1
anywhere) → the divisibility operation itself is unlearnable under these dynamics — the strongest
negative result available. / Any other pattern → report codes + measurements, no further claim."
Probe = classification of [101, 200]; P-ordering adapted P4 → P1 → P3 → P2, and P1 = errors on
{121,143,169,187} classified prime (the {2,3,5,7}-sieve signature, ≈96% probe acc).
**Commentary.** Measured cells:
| wd | model | val EM best | val EM last | O | P | H | probe acc (cls) |
|----|-------|-------------|-------------|---|---|---|-----------------|
| 1.0 | rnn | 0.900 | 0.800 | O3 | P2 | H1 | 0.60 |
| 1.0 | transformer | 0.900 | 0.867 | O3 | P2 | — | 0.80 |
| 0.1 | rnn | 0.867 | 0.800 | O-PARTIAL | P2 | H1 | 0.79 |
| 0.1 | transformer | 0.900 | 0.833 | O3 | P2 | — | 0.75 |
**No O1 anywhere.** The codes are O3 / O-PARTIAL with P2 — which is *not* "reproduces
next_prime's codes" (next_prime was O4 / O-PARTIAL with P4). So strictly this lands in the
**"any other pattern"** branch: report codes + measurements, no further claim. The informative
facts, reported without a locked claim: (i) is_prime is *much* easier in-range than next_prime —
val EM best 0.867–0.900 everywhere vs next_prime's 0.367 (rnn) / 0.867 (transformer) at wd 1.0 —
so the increment/search loop was a genuine in-range tax; (ii) out-of-range classification is
60–80%, all **below the ~96% trivial-sieve floor**, and the errors are P2 (scattered — primes
misclassified as composite, no concentration on {121,143,169,187}) — so there is **no evidence
the divisibility operation was learned**, even though the in-range task got much easier.
**Caveats.** H1 (halting collapsed to floor, mean 2.00–2.26 steps) is benign here: the is_prime
output is a single digit + EOS, so 2 steps is the correct behaviour, not a pathology. The probe
is classification, so the 60–80% is inflated by trivially-classifiable inputs; the sieve floor of
~96% is the right ceiling to compare against, and we are well below it. Because the branch
resolved to "any other pattern", we are not entitled to the "strongest negative result" phrasing
(which required reproducing next_prime's codes).
**Implications for E6.** The search/increment loop, not the divisibility test, carried most of
the in-range difficulty — but divisibility still did not emerge as an algorithm out-of-range.
E6 should therefore keep the full next_prime task (the range extension is precisely the pressure
that makes the search loop worth solving), and treat is_prime only as a lighter diagnostic, not
as a path to a grokking result on its own.
---
## D2 — integer-token diagnostic (`vocab_mode=integers`, next_prime, seed 0; wd 1.0 both + wd 0.1 rnn)
**LOCKED** (Addendum 5): "val EM lifts ≥ +10 points over the digits-mode control at the same wd →
place-value parsing was a real tax on learning. / within ±10 points → parsing was not the
bottleneck; the algorithmic content is the wall."
**Commentary.** First evaluation crashed (out-of-vocab probe inputs: atomic tokens ≥ 104 exceed
the vocab — out-of-range probing is unrepresentable by construction for integers mode). Fixed:
probe is now N/A for integers mode (regression-tested); D2 is scored on in-range val EM, the
only metric its locked clause uses.
| job | model | wd | val EM best | val EM last | O | P | H | digits control (best/last, same wd) |
|-----|-------|----|-------------|-------------|---|---|---|--------------------------------------|
| int | rnn | 1.0 | 0.133 | 0.000 | O2 | N/A | H4 | 0.367 / 0.167 |
| int | transformer | 1.0 | 0.100 | 0.067 | O2 | N/A | — | 0.867 / 0.700 |
| int01 | rnn | 0.1 | 0.067 | 0.000 | O2 | N/A | H1 | 0.700 / 0.567 |
All three cells are **20–77 points BELOW** the digits-mode control. Neither locked branch
fires literally (the "within ±10 points" branch was written expecting a flat outcome; the
measured outcome is a collapse). The measured fact, reported without a locked claim:
**atomic integer tokens destroy the task** — every run is O2 (train memorizes, val ≈ 0),
even the transformer that reaches 86.7% in digits mode.
**Interpretive commentary (post-hoc, separated).** The digit representation was not a tax —
it was the scaffolding. Compositionality is what let any generalization exist at all: in
digits mode the model shares structure across "42", "43", "4", "3" (tens digit, units digit,
position); in integers mode every number is a unique, once-seen token with nothing shared,
so there is nothing to generalize — pure memorization, and even that barely holds under wd.
This inverts the reviewer's hypothesis: removing the parsing overhead removed the substrate
the in-range heuristic was built on.
**Caveats.** Seed 0, three cells only. "Probe N/A" is a representational fact of the encoding,
not a measurement failure. The integer-token task also changed the output distribution shape
(2-token outputs) — the collapse is attributable to the input representation change, but that
change bundles several things (no positional structure, unique tokens, shorter sequences).
**Implications for E6.** Digits mode is not just the default — it is load-bearing. The [2,1000]
phase should use digits (inputs are 1–4 digits there anyway) and treat integer tokens as a
known-broken encoding, not a diagnostic toggle worth re-running.
|