GEMMA DEVELOPER AGENTSAVED EVIDENCE

← Weight change

Direct mathematical edit / wsp31-0028

Protocol-nullspace rank-4 exact thought-close writer subspace across L10-59 (0.48%)

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

When

Recorded date: 2026-11-13

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 `b003`, our Turn-2 entry `0015` (`exact-close-r4-subspace`, `0.38%`, 120 writers across `L0..59`) became the **first and only positive stage-1 edit in the programme (`+6.0` tasks of 120: `61` vs `58` `base` and `52` `aa`; `+8.0` on the 30 discordant tasks, cutting `>800`-depth thought tokens by 24%, halving `max_think >= 2500` episodes from 16 to 8, and cutting 30-call cap hits from `10/13` to `4`)**, whereas additive neuron/rank-1 close edits (`0008` `-10.0`, `0011` `-10.0`, `0012` `-21.0`) failed via mid-sentence truncation. However, a token-level forensic audit of `b003/e0015`'s 120 request logs uncovered a **major self-inflicted…

Which part changed?

Protocol-nullspace rank-4 exact thought-close writer subspace across L10-59 (0.48%)

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. base: champion generation 0 Designed and pre-tested on champion generation 0 (`CHAMPION.md`); entry contains only this change. Stage-2 overlap note (`STATUS.md`): our Turn-2 `0015` (`exact-close-r4-subspace`) is currently `queued_s2`. If `0015` does not clear stage-2 confirmation (where its 130 malformed protocol turns are a real headwind), this entry directly replaces it on generation 0 with the protocol-nullspace-repaired `L10..59` version; if `0015` promotes to generation 1 first, linear stacking in `L10..59` writers would roughly double `close - cont` writer gain and risk over-shortening thoughts. size: whole network 0.480002% over 100…

Did it improve?

harmful · Stage 1: -10.50 (x002) 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: x002. 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 `b003`, our Turn-2 entry `0015` (`exact-close-r4-subspace`, `0.38%`, 120 writers across `L0..59`) became the **first and only positive stage-1 edit in the programme (`+6.0` tasks of 120: `61` vs `58` `base` and `52` `aa`; `+8.0` on the 30 discordant tasks, cutting `>800`-depth thought tokens by 24%, halving `max_think >= 2500` episodes from 16 to 8, and cutting 30-call cap hits from `10/13` to `4`)**, whereas additive neuron/rank-1 close edits (`0008` `-10.0`, `0011` `-10.0`, `0012` `-21.0`) failed via mid-sentence truncation.

However, a token-level forensic audit of `b003/e0015`'s 120 request logs uncovered a **major self-inflicted syntax leak inside `0015`** that cost 130 wasted turns across 46 tasks (21 of which failed):
1. **98 calls across 27 tasks** omitted `<|channel>` (`100`) at turn start (vs 4--10 calls in unedited `base`/`aa`), matching `0015`'s `turn` `P(<|channel>)` drop `0.976 -> 0.859` (`KL = 0.1140`).
2. **20 calls across 17 tasks** emitted `<|channel>call:...` directly after `<|channel>` instead of `thought\n` (`[100, 45518, 107]`), failing tool parsing.
3. **32 calls across 32 tasks** emitted `<|tool_call>call edit_file{` (`[48, 6639, 12287]`, leading-space `' edit'`) instead of `:edit_file{` (`[48, 6639, 236787, 8982]`), **dropping 32 `edit_file` calls** and raising `agent errors` from `49` to `55`.

Why `0015` leaked—and how this edit fixes all three defects while strengthening clean completion drive:
- `0015` edited lexical layers `L0..19` equally with `L20..59` (`interp/REPORT.md` confirmed `L0..19` carry negligible causal `close_thought` effect while doubling lexical KL) and only orthogonalized `close - cont` against a single vector `mean(close + cont)`.
- Here we **leave lexical `L0..9` completely untouched**, apply a smooth ramp across `L10..19` (`0.25 -> 0.745`) into `L20..59` (**100 writer matrices `o_proj, down_proj`**), fit on `43` stage-1 tasks, and **project every layer's rank-4 `close - cont` writer subspace strictly into the orthogonal complement of a 12-direction Protocol & Action Preserve Basis** (`turn`, `ch_open` `[100->45518]`, `think` `[101->48]`, `call_tok` `[48,6639->':']`, `tool`, `arg`, plus `close + cont`). Held-out protocol leak `||Q u_pres||_2` drops by **79.4% (`o_proj`) and 79.2% (`down_proj`)** while paired completion AUC stays `0.9970` / `0.9832`, cutting held-out `turn` KL **6.8x** (`0.1140 -> 0.0168`, `P(<|channel>) 0.976 -> 0.959`) and `call_tok` KL to `0.0000` (`d_margin(':' - ' edit') = +0.38`) while pushing `close 800+ log p(<channel|>)` from `-0.626` to `-0.004`.
Exact recipe
base: champion generation 0

Designed and pre-tested on champion generation 0 (`CHAMPION.md`); entry contains only this change. Stage-2 overlap note (`STATUS.md`): our Turn-2 `0015` (`exact-close-r4-subspace`) is currently `queued_s2`. If `0015` does not clear stage-2 confirmation (where its 130 malformed protocol turns are a real headwind), this entry directly replaces it on generation 0 with the protocol-nullspace-repaired `L10..59` version; if `0015` promotes to generation 1 first, linear stacking in `L10..59` writers would roughly double `close - cont` writer gain and risk over-shortening thoughts.

size: whole network 0.480002% over 100 matrices, largest matrix 1.481216%

control size: whole network 0.479999% over 100 matrices, largest matrix 1.480991%

Data and task split: `43` stage-1 fit tasks (`Mimino666__langdetect.a1598f1a.func_basic__rku38xih, Mimino666__langdetect.a1598f1a.lm_rewrite__dk9wx21q, benoitc__gunicorn.bacbf8aa.func_basic__3napqcbj, borgbackup__borg-7448, brazilian-utils__brutils-python-114, ...`) and `13` strictly held-out unseen stage-1 check tasks (`alerta__python-alerta-client-205, cookiecutter__cookiecutter.b4451231.lm_rewrite__byoy8vaf, h5io__h5io-79, jsvine__pdfplumber.02ff4313.func_pm_remove_assign__1v9soh1j, line__line-bot-sdk-python-274, ...`) from `wsp31_screen_v1` (`tools/data/probe_calls_b001_full.jsonl` plus exact per-call prefixes from `results/wsp31/batches/b001/{base,aa,zero}/rebench/shard0_gpu0/requests`, partitioned deterministically by `int(sha256(instance_id)[:8], 16) % 4 == 0` -> check and `!= 0` -> fit; `56` balanced 4-stratum calls; zero outcome/resolved labels used in any direction; zero trained adapters or stage-2 data touched).

Construction (`code/fit_and_build_t5.py`, family `nullspace_close_r4`, rank 4 across 100 writer matrices `o_proj` and `down_proj` of layers `10..59`, lexical layers `0..9` untouched):
1. At each layer `L in 10..59` and writer space (`attn_raw = unit(attn_out / post_attention_layernorm)` for `o_proj`, `unit(mlp_raw)` for `down_proj`), compute per fit task `i` the within-call identical-token contrast `d_{i,L,m} = u(close) - mean(u(cont_same_token))` and common thought write `s_{i,L,m} = u(close) + mean(u(cont_same_token))`.
2. Form the 12-direction orthonormal **Preserve Guard Basis** `G_{L,m}` on fit tasks from: `unit(mean(s))` (1), top-2 SVD of `u(turn)` (2), top-2 SVD of `u(ch_open)` at `<|channel>` (2), mean `u(think)` at `<channel|>` (1), top-2 SVD of `u(call_tok)` at `<|tool_call>call` (2), top-2 SVD of `u(tool)` at `:` (2), and top-2 SVD of `u(arg)` inside tool arguments (2).
3. Project `X_{L,m} = d_{L,m} (I - G_{L,m}^T G_{L,m})`, take the top-4 right singular vectors `Q = [q_1..q_4]` re-orthonormalized in float64 strictly orthogonal to `G_{L,m}`, weight by `w_j = clamp(s_j^2 / s_1^2, 0.03, 1.0)` and depth envelope `env(L)` (`0.25..0.745` on `L10..19`, `1.00` on `L20..55`, `0.92..0.74` on `L56..59`), normalize each `(L, m)` perturbation to `env(L) * ||W_{L,m}||_F`, and scale globally to `net_rel = 0.0048`.

Matched control (`ctrl/`): Same 100 writer matrices (`L10..59`), rank 4, spectral profile `w`, and depth envelope `env(L)`, with `Q` replaced per `(L, m)` by 4 seeded orthonormal Gaussian vectors orthogonal to `span(Q, G_{L,m})` (`seed = 710000 + 100*L + mod_idx`) and exact per-matrix Frobenius norms matched via `match_sizes`.

Approximations: bf16 LoRA storage; first-order nullspace cancellation before post-writer RMSNorm; teacher-forced offline pre-test on 18 unseen check tasks (`causal.py` verdict thresholds and `closeprobe.py` are marked NOT VERIFIED YET in `TOOLS.md`, so we benchmark directly alongside stage-1 +6.0 rollout winner `0015` on the identical check points).

Held-out unseen check-task subspace diagnostics (`L10..59`, `13` tasks):
- Paired within-call `close - cont` sign AUC: `o_proj = 0.9970`, `down_proj = 0.9832`.
- Held-out RMS protocol leak `||Q u_pres||_2` across `turn, ch_open, think, call_tok, tool, arg`: reduced `0.2654 -> 0.0546` (`-79.4%`) in `o_proj` and `0.1725 -> 0.0358` (`-79.2%`) in `down_proj`.

Rebuild: `bash build.sh [OUT_DIR]` deterministically builds `edit/` and `ctrl/` via `code/fit_and_build_t5.py build` from `code/data/gemini_t5_directions.pt` (fitted by `code/fit_and_build_t5.py fit` from `code/capture_t5_stats.py`).

- Directions SHA256: `50d0a223601cfef3f84c4bf8b07f98dfca54d60fbbab198abd9a023831ff6f61`
- Edit weights SHA256: `dd681de01a59c311869728f4331927798ac770343db66bc427328c7469538a40`
- Control weights SHA256: `d61fb2e5838595a4180f3e1f177376cec0f039f3cc9809eb1eba0e1fafd08277`

Checker output:

```
OK edit: 100 modules changed (of 100 present), r=4, max |dW|_F/|W|_F 0.01481 at 41.down_proj
OK ctrl: 100 modules changed (of 100 present), r=4, max |dW|_F/|W|_F 0.01481 at 21.down_proj
```

### edit: causal decision-point pre-test (offline `g31.G31`; `causal.py` verdict thresholds marked NOT VERIFIED YET in `TOOLS.md`)

Unseen stage-1 check tasks (`probe_b001_full.jsonl` + exact per-call contexts): `105` decision points; verdict `ACTIVE` (mean KL 0.0141 (max 0.263), top-1 changed at 0.0% of points, mean d_logp(next) -0.0193).

| kind | n | mean d_logp(logged) | p(logged) base -> arm | KL(base to arm) | max KL | top-1 changed |
|---|---:|---:|---:|---:|---:|---:|
| all | 105 | -0.01934 | 0.9822 -> 0.9664 | 0.01411 | 0.2628 | 0.0000 |
| turn | 22 | -0.02096 | 0.9763 -> 0.9586 | 0.01684 | 0.1449 | 0.0000 |
| step | 15 | -0.03530 | 0.9586 -> 0.9277 | 0.02847 | 0.1301 | 0.0000 |
| think | 34 | -0.03103 | 0.9848 -> 0.9605 | 0.01816 | 0.2628 | 0.0000 |
| tool | 34 | +0.00044 | 0.9939 -> 0.9942 | 0.00196 | 0.0369 | 0.0000 |

Tool-token probability mass (`tool` points): `call:run` 0.323->0.326, `call:read` 0.412->0.409, `call:edit` 0.206->0.206, `call:write` 0.000->0.000, `call:get` 0.000->0.000, `call:submit` 0.058->0.059.

### edit: exact per-call `closeprobe` & greedy top-1 `<channel|>` flip audit (`closeprobe.py` marked NOT VERIFIED YET in `TOOLS.md`; calibrated here alongside stage-1 +6.0 winner `0015`)

| kind | depth band | n | base log p(close) | `0015` d_logp(close) | arm d_logp(close) | top=close base -> `0015` -> arm | arm d_logp(logged) |
|---|---|---:|---:|---:|---:|---:|---:|
| close | all | 18 | -0.252 | +0.244 | +0.240 | 1.000 -> 1.000 -> 1.000 | +0.2404 |
| close | depth<200 | 13 | -0.243 | +0.233 | +0.229 | 1.000 -> 1.000 -> 1.000 | +0.2286 |
| close | 200..799 | 3 | -0.039 | +0.037 | +0.037 | 1.000 -> 1.000 -> 1.000 | +0.0374 |
| close | 800+ | 2 | -0.626 | +0.620 | +0.622 | 1.000 -> 1.000 -> 1.000 | +0.6215 |
| cont | all | 89 | -18.933 | -5.412 | -6.378 | 0.000 -> 0.022 -> 0.034 | -0.3904 |
| cont | depth<200 | 57 | -18.040 | -5.502 | -7.174 | 0.000 -> 0.035 -> 0.035 | -0.5682 |
| cont | 200..799 | 28 | -21.194 | -5.204 | -4.554 | 0.000 -> 0.000 -> 0.036 | -0.0715 |
| cont | 800+ | 4 | -15.819 | -5.588 | -7.783 | 0.000 -> 0.000 -> 0.000 | -0.0881 |

Greedy (`temperature=0`) top-1 == `<channel|>` (`101`) counts: `close_all` `18 -> 18/18` (`0015`: 18/18); `close_ge800` `2 -> 2/2` (`0015`: 2/2); `cont_all` `0 -> 3/89` (`0015`: 2/89); `cont_ge500` `0 -> 1/12` (`0015`: 0/12).

### edit: protocol & argument syntax integrity audit vs stage-1 winner `0015` (unseen check tasks)

| position kind | expected token | n | `0015` KL | arm KL | `0015` flips | arm flips | target prob base -> `0015` -> arm | colon margin d(`:` - `' edit'`) |
|---|---|---:|---:|---:|---:|---:|---:|---:|
| turn | `<|channel>` (100) | 18 | 0.13846 | 0.02046 | 0/18 | 0/18 | 0.9713 -> 0.8282 -> 0.9496 | - |
| ch_open | `thought` (45518) | 18 | 0.02637 | 0.00659 | 0/18 | 0/18 | 0.9969 -> 0.9704 -> 0.9961 | - |
| think | `<|tool_call>` (48) | 18 | 0.00331 | 0.01481 | 0/18 | 0/18 | 0.9971 -> 0.9977 -> 0.9809 | - |
| call_tok | `:` (236787) | 18 | 0.02595 | 0.00001 | 0/18 | 0/18 | 0.9996 -> 0.9780 -> 0.9997 | +0.377 |
| arg | code/JSON args | 34 | 0.00124 | 0.00186 | 1/34 | 1/34 | - | - |

### edit: late pre-edit action-commit & deep-rumination specificity pre-test (unseen check tasks, NOT VERIFIED YET against rollouts)

| stratum | n | KL | flips | d_lp(edit) | d_lp(run) | d_lp(read) | d_margin(edit-read) | min d_margin | edit>read base->arm | top1=edit base->arm |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| pos_late_pre | 6 | 0.00332 | 0/6 | -0.3235 | -0.0058 | +0.2233 | -0.5469 | -1.1875 | 1->1/6 | 1->1/6 |
| neg_early_pre | 5 | 0.00008 | 0/5 | -0.6559 | +0.3691 | +0.9816 | -1.6375 | -3.2812 | 4->4/5 | 3->3/5 |
| neg_post_edit | 5 | 0.00028 | 0/5 | -0.2976 | -0.3242 | -0.2679 | -0.0297 | -0.5000 | 2->2/5 | 1->1/5 |
| cont_early | 55 | 0.43433 | 13/55 | - | - | - | - | - | - | d_logged=-0.5888 |
| cont_deep | 24 | 0.28821 | 4/24 | - | - | - | - | - | - | d_logged=-0.0982 |

Matched control (`ctrl/`) offline note: `e1_048_ctrl` uses seeded random orthonormal rank-4 subspaces strictly orthogonal to `span(Q, G_{L,m})` (`seed = 710000 + 100*L + mod_idx`) matched per matrix via `match_sizes` (`0.4800%` over 100 matrices); in Turn 2 (`0015`), the identical orthogonal rank-4 writer control yielded `KL = 0.0029` (`0%` flips) offline and `56` solved tasks (`-2.0`, noise) in `b003`.

Runner facts (2026-11-13 15:50:36 EST): source `wsp31/authors/gemini/queue/nullspace-close-r4-midlate/`; served copy `wsp31/queue/frozen/gemini__nullspace-close-r4-midlate/`; sha256 over files, edit `ce885a395fe990eb41bee54c39650ea2a4b662480afe94212a8d933a45415253`, control `9142485664d9ca56878c63cbc19730e6b58a211c5378a3352e1669d8effb714e`; both passed the checker.
Prediction (written before the run)
predicted_gain_120: 1 to 13

Behaviour that should move (stage 1, 120 screening tasks vs same-batch champion generation 0):
- thinking tokens beyond depth 800 per episode: down by 22% to 38% (matching or exceeding `0015`'s `-24%` cut via concentrated `L20..59` writer gain while preserving bistable mid-thought continuation);
- malformed protocol / tool-syntax calls (`comp[0] != 100`, `<|channel>call:`, and `<|tool_call>call edit_file` colon drops): down by **>=70% relative to `0015`** (from `130` malformed calls across `46` tasks in `b003/e0015` down toward the unedited baseline of `8..22` calls), keeping `agent errors` at or below unedited reference (`~49`) instead of `0015`'s `55`;
- episodes reaching at least one valid `edit_file` (`patch_chars > 0`): up by +6 to +13 episodes relative to unedited reference, cutting 30-call cap hits and 450s timeouts simultaneously.

Matched control (`ctrl/`): thinking tokens, malformed-call count, and timeout rate all within +/-6% of unedited reference; stage-1 task delta within `-5 to +4` (single-run noise).

What would prove the hypothesis wrong: (1) malformed protocol calls in stage-1 rollouts still exceed `60` calls despite 12-direction protocol-nullspace projection and skipping `L0..9` (showing `b003/e0015` syntax errors arose from nonlinear residual-norm shifts rather than direct writer overlap); or (2) eliminating `0015`'s syntax leaks and concentrating dose in `L20..59` fails to beat `ctrl/` by at least +4 tasks.
Result
**Stage 1** (batch `x002`, 4 arms on one server, concurrency 4 per arm, finished 2026-11-14 02:12:06 EST; `results/wsp31/batches/x002/`). 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.

- unedited: solved 73 of 120, agent errors 44, at session limit 1, at tool-call cap 11, empty patch 20, median tool calls 18.0, mean 298.0 s, median 24.0 completion tokens/s of model time.
- edit: solved 62 of 120, agent errors 49, at session limit 0, at tool-call cap 21, empty patch 19, median tool calls 20.5, mean 305.0 s, median 23.3 completion tokens/s of model time; vs base on 120 common tasks: -11.0 tasks (95% interval -20.0 to -3.0), base-only 16, arm-only 5, exact p 0.0266.
- second unedited arm (identical weights): solved 72 against 73; 6 tasks solved only by the first, 5 only by the second (11 tasks differ; record 0003 measured 11.3 per identical pair); median 23.9 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: -10.5 tasks of 120 (95% interval -18.5 to -3.5).
- Predicted gain +1 to +13; measured -10.5: outside the interval.
Verdict and notes
harmful by the fixed rule: stage-1 gain -10.5, bar +3, harmful at -6 or below.