diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md
index 3b5b6e20c..f6ab8192f 100644
--- a/docs/cookbook-index.md
+++ b/docs/cookbook-index.md
@@ -2,7 +2,7 @@
> **Generated by `tools/cookbook_index.py` — do not hand-edit** (R33). Regenerate after adding a cookbook section.
>
-> `docs/matching-cookbook.md` is ~716 KB / 405 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses.
+> `docs/matching-cookbook.md` is ~716 KB / 406 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses.
**How to use:** name what you SEE in the diff (a stolen delay slot, an extra `la`, a swapped register pair, a `conflicting types` error), find that symptom below, read those sections first. If nothing fits, THEN grind — and add a section when you win.
@@ -548,7 +548,7 @@
- **§3-The** — measurement (do this before any wave; it is ~20 lines and needs no builds) L9780
- **§3-And** — the report-vs-bytes lesson attached to it L9812
-### (unbucketed — title matched no symptom vocabulary) (117)
+### (unbucketed — title matched no symptom vocabulary) (118)
- **§3-How** — to use this L30
- **§1** — Idiom catalog (asm pattern → C that produces it) L39
@@ -667,6 +667,7 @@
- **§3-Two** — wrong mechanisms I chased first, and why they were wrong L9710
- **§3-The** — trap that hid it — SAME FUNCTION, TWO ROUTES, ONLY ONE IS FREE L9795
- **Route** — selection (why `--addr` sometimes says "nothing changed") L9804
+- **§144** — THE LITERAL'S SPELLING PICKS THE IMMEDIATE ENCODING (P30 S40 wave 1, `func_801822E0`) L9878
## All sections, in order
@@ -1076,3 +1077,4 @@
- **Route** — selection (why `--addr` sometimes says "nothing changed") L9804
- **§3-And** — the report-vs-bytes lesson attached to it L9812
- **§143** — `cast_call_sites` read a RETURN STATEMENT as a prototype and deleted it. A 0/39 sweep became 18/39. (P30 S40) L9824
+- **§144** — THE LITERAL'S SPELLING PICKS THE IMMEDIATE ENCODING (P30 S40 wave 1, `func_801822E0`) L9878
diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md
index 766fc49b7..e7130b25c 100644
--- a/docs/matching-cookbook.md
+++ b/docs/matching-cookbook.md
@@ -9872,3 +9872,42 @@ touched every member — and read the per-member payload before believing any wa
**Symptom lines for the index:** **"parse error before `extern'"** · **"a sweep banked 0 of N"** ·
**"a draft lost its return statement"** · **"declaration after statement in a block"**.
+
+---
+
+## §144 — THE LITERAL'S SPELLING PICKS THE IMMEDIATE ENCODING (P30 S40 wave 1, `func_801822E0`)
+
+A new, byte-proven gcc-2.7.2 idiom, found by a wave agent on an 85-ins exemplar.
+
+A byte counter stored through an `sb` was diffing on **one instruction's immediate field only**:
+
+ target : addiu $v0, $v1, 0xFF (imm 0x00FF)
+ ours : addiu $v0, $v1, -1 (imm 0xFFFF)
+
+Both are *arithmetically identical modulo 256* — only the low byte survives the `sb` — and both
+compile to a **single `addiu`**, same instruction count, same registers, same schedule. The compiler
+is not choosing between them on any semantic ground: **it takes the immediate from how the literal
+was SPELLED in the source.**
+
+ cnt = cnt - 1; -> addiu $v0,$v1,-1 (0xFFFF)
+ cnt = cnt + 0xff; -> addiu $v0,$v1,0xFF (0x00FF) <- matches
+
+Signedness of the counter (`s8` vs `u8`) was tested and makes **no** difference; the spelling is the
+whole lever.
+
+**When to reach for it:** your diff is a single instruction, the mnemonic and both registers agree,
+and only the **immediate field** differs — *and* the two immediates are congruent modulo the width of
+the store that consumes the value (`sb` → mod 256, `sh` → mod 65536). Then re-spell the literal to the
+form whose bit-pattern you need. Do NOT reach for pins, scheduling barriers or the permuter: nothing
+about register allocation or ordering is wrong.
+
+**Why it is easy to misread as intrinsic:** the residual is one immediate in one instruction, which
+looks exactly like the tail of a regalloc/scheduling wall. It is not — it is a pure source-text lever,
+and it is free.
+
+**Generalisation to test when it next appears** (not yet byte-proven, so treat as a hypothesis):
+the same should hold for any masked-then-truncated arithmetic where two literals are congruent modulo
+the consuming store width — e.g. `x - 2` vs `x + 0xfe`, or `h - 1` vs `h + 0xffff` ahead of an `sh`.
+
+**Symptom lines for the index:** **"only the immediate field differs"** · **"addiu -1 vs 0xFF"** ·
+**"one instruction off, same registers"**.
diff --git a/docs/wave-metrics.md b/docs/wave-metrics.md
index f76daaf28..f12e127e5 100644
--- a/docs/wave-metrics.md
+++ b/docs/wave-metrics.md
@@ -152,3 +152,44 @@ fixed path — a real match reported as nothing.
**Any row in this table is a coverage claim.** Before recording one, confirm the gate accounted for
every draft (`banked + failed + no-verdict == drafts`, now asserted in `.run/s6f_gate.py`). Full
post-mortem: cookbook **§139**.
+
+---
+
+## Wave S40-1 (2026-08-05) — 8 targets, the first wave ever aimed at the open-only h_norm clusters
+
+**Pool verified BEFORE the wave (R14).** The frontier report's cluster pool was carried with an
+explicit "not verified" caveat, and its *other* headline claim (the whale open in 4 SC07 overlays)
+had already proved 3/4 wrong. Measured from the sigs instead:
+
+| | clusters | fns | ins | multiplier |
+|---|---:|---:|---:|---:|
+| claimed | 1,689 | 5,956 | 326,261 | 2.7× |
+| **measured** | **1,677** | **5,795** | **319,755** | **3.68×** |
+
+Within 2–4% on size, and the multiplier is **better** than claimed. Verify each claim separately: the
+same document was right here and wrong about the whale.
+
+**Result — and the two numbers say different things.**
+
+| stage | result |
+|---|---|
+| `match_one` close=0 | **8 / 8** |
+| whole-binary gate, first pass | **5 / 8** |
+| after deterministic recovery | **8 / 8** — ~0 agent tokens |
+
+**All three first-pass failures were integration plumbing, each a different known lever, ZERO codegen
+walls:**
+
+| fn | gate error | lever |
+|---|---|---|
+| `func_801802EC` | `redefinition of morph_lerp` | strip the **§77 probe layer** — the draft carried types + a `static inline` helper so `match_one` could compile standalone; the real TU already defines them. Scaffolding is not part of the bank. |
+| `func_8018B238` | `conflicting types for D_80115158` | `recover_giant` — the draft declared it file-scope as a struct array while the TU declares `u8[]` **block-scope** inside other functions; block-scoping the draft's externs removes the collision. |
+| `func_8017EF54` | `conflicting types for func_8017EF54` | **§37/§124 def-side asm-label alias** — TU declares `void f(void)` for no-arg callers, byte-true def takes `s32` in `$a0`; no-prototype escape illegal once a param promotes, so the definition takes a private C identifier + `__asm__("func_8017EF54")`. |
+
+**The lesson for reading any future wave row: the gate number is not the close-rate.** 5/8 measured
+integration, not matching. Run the recovery ladder before recording a wave's yield, or the table will
+under-report the drafters and send the next wave hunting compiler walls that are not there.
+
+**Cost:** 1.31M subagent tokens, 8 agents, 0 errors. **Idioms harvested:** cookbook §144 (literal
+spelling picks the immediate encoding). **Defect found:** `.run/ghidra_c/func_8017EF54.c` is a stale
+decompile of the WRONG function — the prefetch cache is not trustworthy per-entry.