diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md
index b2dcba550..02d05352d 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 / 1089 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 / 1091 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.
@@ -513,7 +513,7 @@
- **§395** — ★★★ — FIVE NARROWING/PLACEMENT LEVERS FROM ONE 91-INSTRUCTION CRACK (P31 S69; byte-proven ov_SC06_018/func_80189E60, warm start 32 off → MATCH 91/91) L32611
- **§418** — ★★★ — TWO LOOP-STRUCTURE LEVERS: MAKE THE SECOND INDEX A GIV, AND KEEP A TABLE ADDRESS UNFOLDED (P31 S71; byte-proven `ov_SC04_016/func_8017DF8C`, 184 ins, 32 → 0 in seven compiles) L33632
-### types, signedness & load/store width (93)
+### types, signedness & load/store width (95)
- **§3-I1** — Unsigned range check: `(x - lo) < (hi-lo)` → `addiu`+`sltiu` L41
- **§3-I2** — Byte mask forces `andi` even after `lbu` L47
@@ -608,6 +608,8 @@
- **§378** — ★★★ — THE **SELF-CALLER CAST**: LET A TU KEEP CALLING THE FUNCTION IT IS ABOUT TO DEFINE (P31 S69; byte-proven ov_SC04_010/func_8017D6CC) L32114
- **§379** — ★★★ — **MEM_IN_STRUCT_P**: THE SAME LOAD, WRITTEN AS A STRUCT MEMBER, SCHEDULES WHERE A CAST CANNOT (P31 S69; byte-proven main/func_80021284 220 ins and main/func_8002D904 217 ins, found INDEPENDENTLY by two agents) L32164
- **§392** — ★★★ — THE SONNET-WAVE HARVEST (P31 S69): SEVEN TYPE/ORDER LEVERS THAT EACH CLOSED A MATCH L32502
+- **§422** — ★★ — QImode ARITHMETIC VIA `(u8)(x - K)`, AND `flag ^ 1` NEEDS ITS OWN TEMP (P31 S71; byte-proven `resident/func_800D06E8`, 344 ins) L33760
+- **§423** — ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`) L33780
### declarations, prototypes & K&R (114)
@@ -937,7 +939,7 @@
- **§420** — ★★★ — A MULTI-CLUSTER SYMBOL REBASE, AND THE BARE-NAME DEDUP THAT HID THREE QUARTERS OF IT (P31 S71; 4 banked in 57 s) L33692
- **§421** — ★★★ — A `la $tN` + `addiu` PAIR CAN BE A **RELOAD** ARTIFACT THAT NO C SPELLING REACHES (P31 S71; byte-proven `md_SC07_003/func_801A293C`, 313 ins, 6 → 0) L33729
-### integration / TU plumbing (76)
+### integration / TU plumbing (77)
- **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) L456
- **§8d** — Templating a body INTO a TU must not CHANGE its declaration environment — demote the carried data externs (Phase 26 session 8, byte-proven on `func_8015AE2C` ×133) L502
@@ -1015,8 +1017,9 @@
- **§398** — ★★★ — `family_remap` CARRIES THE **SOURCE** TU's DECL ENVIRONMENT INTO A DESTINATION THAT ALREADY OWNS THOSE NAMES (P31 S69; measured 3 banked of 22) L32835
- **§3-D.** — INTEGRATION IS STILL THE BOTTLENECK, AND THE TU IS THE AUTHORITY L33140
- **§415** — ★★ — A FILE-SCOPE DECL MAKES gcc-2.7.2 MERGE THE TU'S LATER *BLOCK-SCOPE* EXTERNS INTO IT (P31 S71; byte-proven `ov_SC04_011/func_80180B24`, 215 ins) L33547
+- **§423** — ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`) L33780
-### build graph, splat & the harness (192)
+### build graph, splat & the harness (193)
- **§4** — Flag/toolchain gotchas L190
- **Build** — mechanism — per-file opt override (splat resegmentation) L307
@@ -1210,6 +1213,7 @@
- **§405** — ★★★ — THE S70 WAVE HARVEST: 130 agents, 113 MATCH, and the laws they brought back L33092
- **§3-A.** — THE ORACLE HAS A HOLE: match_one cannot see a jump table (§405-A) L33098
- **§414** — ★★★ — `parallel_gate` ON `main` IS A FALSE PASS, AND THE RULE WAS ALREADY WRITTEN DOWN (P31 S71) L33510
+- **§423** — ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`) L33780
### process, measurement & doctrine (132)
@@ -2766,6 +2770,8 @@
- **§419** — ★★★ — WHEN A PIN IS IMPOSSIBLE, WIN THE local-alloc DENSITY CONTEST INSTEAD (P31 S71; byte-proven `ov_SC01_000/func_8017DD04`, 297 ins) L33658
- **§420** — ★★★ — A MULTI-CLUSTER SYMBOL REBASE, AND THE BARE-NAME DEDUP THAT HID THREE QUARTERS OF IT (P31 S71; 4 banked in 57 s) L33692
- **§421** — ★★★ — A `la $tN` + `addiu` PAIR CAN BE A **RELOAD** ARTIFACT THAT NO C SPELLING REACHES (P31 S71; byte-proven `md_SC07_003/func_801A293C`, 313 ins, 6 → 0) L33729
+- **§422** — ★★ — QImode ARITHMETIC VIA `(u8)(x - K)`, AND `flag ^ 1` NEEDS ITS OWN TEMP (P31 S71; byte-proven `resident/func_800D06E8`, 344 ins) L33760
+- **§423** — ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`) L33780
---
@@ -3867,3 +3873,5 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: `
| L33658 | §419 | ★★★ — WHEN A PIN IS IMPOSSIBLE, WIN THE local-alloc DENSITY CONTEST INSTEAD (P31 S71; byte |
| L33692 | §420 | ★★★ — A MULTI-CLUSTER SYMBOL REBASE, AND THE BARE-NAME DEDUP THAT HID THREE QUARTERS OF IT |
| L33729 | §421 | ★★★ — A `la $tN` + `addiu` PAIR CAN BE A **RELOAD** ARTIFACT THAT NO C SPELLING REACHES (P |
+| L33760 | §422 | ★★ — QImode ARITHMETIC VIA `(u8)(x - K)`, AND `flag ^ 1` NEEDS ITS OWN TEMP (P31 S71; byte |
+| L33780 | §423 | ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE- |
diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md
index 490318493..af3cf880d 100644
--- a/docs/matching-cookbook.md
+++ b/docs/matching-cookbook.md
@@ -33756,3 +33756,50 @@ had moved it.
register belongs to REGALLOC at all.* `$t`-register appearances next to a `la` are the signature of
reload scratch, and reload runs after every dial C gives you — the only reach is an asm that puts the
instruction there directly.
+
+## §422 ★★ — QImode ARITHMETIC VIA `(u8)(x - K)`, AND `flag ^ 1` NEEDS ITS OWN TEMP (P31 S71; byte-proven `resident/func_800D06E8`, 344 ins)
+
+**1. A raw-`$a0` `addiu` on a byte value comes from doing the arithmetic in QImode.**
+mips.h defines no `PROMOTE_MODE`, so a `u8` local really is QImode. Write the range test in QImode —
+`(u8)(c - 3) < 2` — and `widen_operand` hands the subtraction a **paradoxical subreg** (the raw
+`$a0`), after which `combine.c:9246`'s `A - C1` vs `C2` rule drops the truncation before the `sltiu`.
+Every earlier probe on this function used `(u32)(c - 3)`, which **re-widens** and loses it. The cast
+is not cosmetic: it selects the mode the arithmetic happens in.
+
+**2. `s1 = (cmp) ^ 1` puts the comparison in the DESTINATION pseudo.** That is expand-time subtarget
+reuse, and it produces a `$s1`/`$v0` pair the target does not have. Give the flag its own temp:
+
+```c
+t = (u32)(r - 0x64) < 0x1E;
+s1 = t ^ 1;
+```
+
+**Both are one-line respellings that no permuter reaches**, because both change which RTL the
+expander builds rather than the order of anything.
+
+## §423 ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`)
+
+**The signature.** `match_one` closeness 0, the whole-binary gate rejects, and the classifier records
+`CAUSE NOT DETERMINED`. That combination has a specific, checkable cause.
+
+**The mechanism.** `harvest_verify.py:490` splices by `txt.replace(stub, draft, 1)` — the draft lands
+exactly where the `INCLUDE_ASM` stub was. If the draft carries a FILE-SCOPE typedef that the TU also
+defines (here `typedef struct { s32 unk00; s32 unk04; } Tbl8_8017FC44;`, defined **five lines below**
+the stub), gcc-2.7.2 exits **33** on a C89 typedef redefinition. The whole TU fails, the gate reverts,
+and nothing in the verdict names the typedef — hence "cause not determined".
+
+**The check, and the fix.** Grep the destination TU for every file-scope `typedef`/`struct`/`union`
+name the draft declares. Move the draft's copy to **BLOCK scope**; it is codegen-neutral (a
+label-normalised diff proves the declaration context changes nothing). Proven three ways here:
+spliced TU with the old draft = exit 33 `conflicting types for 'Tbl8_8017FC44'`, with the new draft =
+exit 0, and an unmodified-TU negative control = exit 0.
+
+**This is the mirror of §409 law 2.** There the collision was with a typedef defined LATER in the TU
+and the fix was also block scope; here it is with one just below the splice point. Same rule, and
+between them they cover both directions: **a draft's file-scope type declaration is a hazard wherever
+the TU defines that name.**
+
+**TOOL TRAP recorded by the same agent.** A scratch copy of a TU needs `-Isrc/` or `cpp`
+exits 1 on its relative `"../shared/engine_core.h"` — and then **every variant "passes" identically**,
+which is a silent all-green instrument. Negative-control any TU-splice harness against an unmodified
+copy before believing a single verdict from it.