GEMMA DEVELOPER AGENTSAVED EVIDENCE

← Weight change

Direct mathematical edit / wsp31-0009

Own end-of-thought neurons x25: scale the write of the 20 late-layer MLP neurons whose write lens is the end-of-thought token (weights only)

Gemma 4 31B, frozen four-bit baseAuthor: claudeState: doneVerdict: harmful

When

Recorded date: 2026-11-12

Ledger date only; exact weight-build/change timestamp is not recorded here. Not a live training event.

Exact tensor-change timestamp: unavailable.

Why change it?

In the unedited batch b001 (three identical arms, 61 episodes finished when read) 14 of the 28 failures end at the 7.5-minute session limit, at least 10 of them with an empty patch and 8 of those without a single file edit (at 110 episodes, 9:40 PM ET: solved 44%, at the limit 35%, empty patch 25%). At about 25 generated tokens per second per stream the limit is a budget of about 11,300 generated tokens. Limit episodes generate 11,341 tokens, 9,149 of them thinking, and 48% of everything they generate lies beyond token 400 of a thought (solved episodes: 24%, 1,631 tokens per episode; `code/cf_budget.py`). The deep parts are re-readings of…

Which part changed?

Own end-of-thought neurons x25: scale the write of the 20 late-layer MLP neurons whose write lens is the end-of-thought token (weights only)

The source describes adapter targets and mathematical changes. No before/after tensor comparison is available in this viewer.

How was it changed?

Computed directly by author-written code and packaged as a low-rank adapter over the frozen base; not gradient-trained. Spec `N:24` of `code/build_think.py` (families in `code/thinklib.py`; rebuild with `build.sh`). No activation statistics enter this edit: it is built from the checkpoint alone (`code/end_neurons.py`, CPU). The pre-test below ran in one GPU-0 hold with `tools/g31.py` (the tools lane's forward pass, whose agreement with the served model is NOT VERIFIED YET in TOOLS.md) on 5 held-out episodes of `tools/data/probe_screen.jsonl` (unedited run s1_base, every fourth instance, one rollout each, truncated to 8,000 tokens). E = last token of a thought (the model's next token was `<channel|>`); depth = tokens since `<|channel>`. Family N (weights only,…

Did it improve?

harmful · Stage 1: -71.00 (x005) tasks against reference arms. Stage 2: not yet measured. Matched control, stage 2: not yet measured. Verdict: harmful.

Measured regression in the recorded screen.

Evaluation set: wsp31_screen_v1 · Batch: x005. Local screening and historical task scores are not competition scores unless explicitly identified in the source. Different evaluation sets cannot be compared as a gain.

Original evidence

Literal source excerpts follow. They may contain original predictions and superseded counts; use the measured-outcome summary and corrections above for the current result.

Hypothesis
In the unedited batch b001 (three identical arms, 61 episodes finished when read) 14 of the 28 failures end at the
7.5-minute session limit, at least 10 of them with an empty patch and 8 of those without a single file edit (at 110
episodes, 9:40 PM ET: solved 44%, at the limit 35%, empty patch 25%). At about
25 generated tokens per second per stream the limit is a budget of about 11,300 generated tokens. Limit episodes
generate 11,341 tokens, 9,149 of them thinking, and 48% of everything they generate lies beyond token 400 of a thought
(solved episodes: 24%, 1,631 tokens per episode; `code/cf_budget.py`). The deep parts are re-readings of code with
"Wait, ..." restarts. Making long thoughts end sooner should return that wall-clock to tool calls, so that episodes
which now time out without a patch get to edit, test and submit.

Different from the E4B "think briefly" edits (28 / 28 / 25 vs 29, PRIOR_E4B.md): there the session limit was not
reported as binding; here it ends 23% to 35% of unedited episodes, and the edit is built from the state at the logged ends of
thoughts (and, in families B and C, acts only deep inside a long thought), not from a short-vs-long contrast.
Exact recipe
Spec `N:24` of `code/build_think.py` (families in `code/thinklib.py`; rebuild with `build.sh`).

No activation statistics enter this edit: it is built from the checkpoint alone (`code/end_neurons.py`, CPU).
The pre-test below ran in one GPU-0 hold with `tools/g31.py` (the tools lane's forward pass, whose agreement with
the served model is NOT VERIFIED YET in TOOLS.md) on 5 held-out episodes of `tools/data/probe_screen.jsonl`
(unedited run s1_base, every fourth instance, one rollout each, truncated to 8,000 tokens). E = last token of a
thought (the model's next token was `<channel|>`); depth = tokens since `<|channel>`.

Family N (weights only, the model's own end-of-thought neurons): the down_proj columns of the MLP neurons of
layers 57, 58, 59 whose direct write lens is dedicated to token 101 `<channel|>` are multiplied by `1 + dose`. Selection
(`code/end_neurons.py`, CPU, no activations): for neuron j, `x_j = final_norm_w * post_ff_norm_w * down[:, j]`,
`z_j = ((E[101] - mean_vocab E) . x_j) / sqrt(x_j^T Cov_vocab(E) x_j)` (the z-score of `<channel|>` in the neuron's
write lens over the 262,144-token vocabulary, exact); selected `z_j >= 6`, at most 16 per layer, layers 48..59
searched: 2 neurons in layer 57 (4238 z 16.9, 18123 z 11.8), 2 in layer 58 (1622 z 10.9, 15419 z 6.5), 16 in layer
59 (14974 z 22.7, 6539 z 18.6, 3378 z 12.0, 18515 z 11.2, ...); none in layers 48..56. Lists and columns:
`code/data/end_neurons.pt`. Control for this family: for each selected neuron, a neuron of the same layer with
`|z| < 1` nearest in column norm (pool of 4000, seed 4242), scaled by the same factor.

Control (`ctrl/`): same code path (`build_think.py N:24 --ctrl`): the same factor 25 applied to the down columns of
20 other neurons, one per selected neuron, same layer, `|z| < 1` for `<channel|>`, nearest in column norm. Same
layers, modules, rank (16) and |dW|_F (0.5996 against 0.5997 of |W|_F at 59.down_proj). It is the right control for
"these neurons, not any 20 late-layer neurons made 25 times louder".

Built as intended; the only approximation is bf16 storage of the added columns (8 significant bits).

Checker:

```
saved queue/end-neurons-x25/edit r 16 modules 3 max rel_fro 0.59969
saved queue/end-neurons-x25/ctrl r 16 modules 3 max rel_fro 0.59963
OK edit: 3 modules changed (of 3 present), r=16, max |dW|_F/|W|_F 0.5997 at 59.down_proj
OK ctrl: 3 modules changed (of 3 present), r=16, max |dW|_F/|W|_F 0.5996 at 59.down_proj
```

Pre-test (teacher-forced on the held-out episodes, truncated to 8,000 tokens, `code/think_report.py`; forward pass
NOT VERIFIED YET against the server; arms named family+dose, a trailing `c` is the control). `dlp101` = change of
log p(`<channel|>`) at thought positions by depth class and at E; `explen ratio` = expected thought tokens under the
arm's end hazard along the logged thoughts, relative to the unedited model, for thoughts logged shorter / longer
than 400 tokens; `dlpnext` = change of the log-prob of the logged token (collateral); `top1 agree` = share of
positions whose top token is unchanged (`think` = first token after a thought, `tool` = tool name); `p101 non` =
mean p(`<channel|>`) outside thoughts.

```
episodes 5 ['PyCQA__flake8.cf15', 'Mimino666__langdet', 'Delgan__loguru-130', 'PyCQA__pyflakes-27', 'HIPS__autograd.ac0'] arms per episode [11, 11, 11, 11, 11]
n by class {'E': 29, 'early': 2051, 'mid': 3020, 'late': 3870, 'non': 750, 'think_pt': 29, 'tool_pt': 29}
base expected/logged thought tokens: short 2708/2712 (23 thoughts)  long 6227/6258 (6 thoughts)
base mean lp101: early -24.99 mid -25.83 late -24.72 E -0.79 non -20.54
arm      | dlp101 early  mid  late     E | explen ratio short long | dlpnext early  late   non think  tool | top1 agree early late think tool | p101 non
N24p0    |   1.93   1.83   2.25   0.58 |     0.81  0.35        |  -0.01  -0.01  -0.21  -0.07  -0.02 |  0.98  0.98  1.00  1.00 | 0.0114 (base 0.0001)
```

Greedy reading of the same passes (the harness decodes at temperature 0): along each logged thought, the first
position where `<channel|>` is the arm's top token. `cut<end` = share of thoughts that would end before their
logged end, `extends` = share where `<channel|>` is not the top token even at the logged end, `tokens kept` =
tokens up to the first cut / logged tokens, `E top=101` = share of logged thought ends where `<channel|>` is top
(the unedited forward pass itself reproduces only this share of the logged ends, see `base`).

```
arm      | short thoughts: n  cut<end  extends  tokens kept | long (>=400): n  cut<end  extends  tokens kept  median cut depth | E top=101 | thought positions (not E) with top=101
base     |  23    0.00     0.13       1.00 |   6    0.17     0.17       0.99     1284 | 0.83 (29) | 0.0001 | outside thoughts (non, think, tool points): n 808, top=101 0, top unchanged 1.000
N24p0    |  23    0.39     0.04       0.86 |   6    0.83     0.00       0.34       98 | 0.93 (29) | 0.0030 | outside thoughts (non, think, tool points): n 808, top=101 8, top unchanged 0.918
```

Not tested: free-running generation under the edit (no rollouts, no served probe in this turn), so whether a thought
that is ended early is followed by a sensible tool call is only covered by the `think` / `tool` columns above.

Runner facts (2026-11-12 21:41:08 EST): source `wsp31/authors/claude/queue/end-neurons-x25/`; served copy `wsp31/queue/frozen/claude__end-neurons-x25/`; sha256 over files, edit `ffa38a920a82cab8a70e2c0946ad0855d4889bafa193d2a8f7d7a691d7763b9b`, control `5d7ab1cf6265720646bb182c8998f79f6d36507357a09c71f15f830e7c4f5cc8`; both passed the checker.
Prediction (written before the run)
predicted_gain_120: -8 to 9

Behaviour that should move: every thought ends at the first place where the model itself already gives `<channel|>`
some weight; short and long thoughts both get shorter (pre-test: 39% of short thoughts cut before their logged end with
86% of their tokens kept; long thoughts keep about a third of their tokens), and logged ends become more decisive
(`E top=101` 0.93 against 0.83 unedited). This is the "think briefly" kind of edit that was neutral to harmful on E4B;
it is queued because here the session limit binds, because it is built from weights alone (the model's own 20
end-of-thought neurons, found by their write lens), and because its collateral in the pre-test is the smallest of all
arms (log-prob of logged tokens inside thoughts -0.01, tool-name top token unchanged at every point).
- thinking tokens per episode: down 30% to 55% (5,700 to between 2,600 and 4,000);
- episodes ending at the 7.5-minute limit: down by a third to two thirds of the unedited arm's rate (35% at 110 episodes: to 12-24%); empty patches down in the same proportion (25%: to 9-17%);
- tool calls per episode: up by 2 to 5; episodes at the 30-call cap up by at most 8 points (unedited 17%);
- risk I can name: p(`<channel|>`) outside thoughts rises from 0.0001 to 0.011 on average. Split by
  `code/non_split.py`: of 152 sampled tokens the model generated outside thoughts (tool-call tokens, answers) the top
  token changes at 1 and is never `<channel|>`; of 598 tokens it only read (tool results) the top token changes at 65
  and is `<channel|>` at 8. A stray `<channel|>` inside a tool call would show up as malformed calls (predicted: under
  2% of calls).
- dose series of this family in the first pre-test pass (same 5 episodes; factor, short tokens kept, long tokens kept,
  `E top=101`): x2 1.00 / 0.99 / 0.83; x4 1.00 / 0.99 / 0.86; x9 0.95 / 0.90 / 0.93; x25 (this entry) 0.86 / 0.34 /
  0.93; norm-matched control neurons x4: 1.00 / 0.99 / 0.83 (= unedited). The control of this entry (x25 on the
  control neurons) was not pre-tested.
Control (`ctrl/`): thinking tokens per episode within 8% of the unedited arm, session-limit rate within 6 points,
gain between -4 and +4 (identical unedited arms already differ by a few tasks).

The hypothesis is wrong if (a) thinking tokens per episode fall by less than 10%: the teacher-forced cut does not
transfer to free-running episodes (the model re-opens the thought it was made to close); or (b) thinking falls by
20% or more and the limit rate falls, but the edit does not gain tasks: long thoughts are then a symptom of hard
tasks and not the cause of the failures; or (c) the control shows the same fall in thinking tokens: then it is not
this direction. A rise of episodes that stop at the 30-tool-call cap by more than 8 points over the unedited arm would mean the saved time went into
more calls and not into finishing.

Caveats written before the run: the pre-test has only 5 held-out episodes (6 long thoughts); the lane's forward pass
reproduces only 83% of the logged thought ends on the unedited model (agreement with the server NOT VERIFIED YET);
nothing was generated under the edit, so the first tool call after a thought that was cut short is untested.
Unedited reference (b001): at 61 episodes solved 54%, at the session limit 23%, thinking tokens per episode 5,700
(solved 4,637, limit 9,149). At 110 episodes (9:40 PM ET): solved 44%, at the session limit 35%, empty patch 25%, at
the 30-tool-call cap 17%; 8.6% of calls think 800 tokens or more, 17.6% think 400 or more. The percentages predicted
above are relative to whatever the unedited arm of the same batch shows.
Result
**Stage 1** (batch `x005`, 4 arms on one server, concurrency 4 per arm, finished 2026-11-14 08:49:03 EST; `results/wsp31/batches/x005/`). Reference arm: unedited. Both reference arms are the unedited model served through an all-zero adapter, the same serving path as an edit (ledger record 0033). Box batch: run on rented boxes as 4 shards by task, every arm of a shard on one server; its edits are compared only with its own reference arms. Episode budget of every arm: 20,000 generated tokens, 60 tool calls, 80 turns (budget `x2`, harness `harness_x2`).

- unedited: solved 75 of 120, agent errors 23, at session limit 23, at tool-call cap 7, empty patch 9, median tool calls 24.0, mean 405.7 s, median 24.9 completion tokens/s of model time.
- edit: solved 3 of 120, agent errors 116, at session limit 116, at tool-call cap 0, empty patch 115, median tool calls 2.0, mean 374.6 s, median 55.9 completion tokens/s of model time; vs base on 120 common tasks: -72.0 tasks (95% interval -82.0 to -62.0), base-only 72, arm-only 0, exact p 0.0.
- second unedited arm (identical weights): solved 73 against 75; 7 tasks solved only by the first, 5 only by the second (12 tasks differ; record 0003 measured 11.3 per identical pair); median 25.0 completion tokens/s. The gain used by the rule is against the mean of the two reference arms per task.
- edit against the mean of the two reference arms: -71.0 tasks of 120 (95% interval -80.5 to -61.0).
- Predicted gain -8 to +9; measured -71.0: outside the interval.
Verdict and notes
Parked 2026-11-13 09:12:02 EST, not screened: rounds began on 13 Nov 2026 and each author keeps two waiting entries. The author can put it back in a later round (an empty file `RESUBMIT` in `wsp31/authors/claude/queue/end-neurons-x25/`); it then counts as one of that round's entries and is served from the frozen copy, unchanged.

Put back by its author 2026-11-14 07:13:46 EST: waits for stage 1 again, served from the frozen copy, unchanged.

harmful by the fixed rule: stage-1 gain -71.0, bar +3, harmful at -6 or below.