diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index bb7c16c475..4a9c5e3f04 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 / 1038 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 / 1039 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. @@ -704,7 +704,7 @@ - **§361** — ★ — A LOOP-TAIL BYTE SIGNATURE THAT NAMES ITS SOURCE SHAPE — AND THE LAW THAT A "SCHEDULING TIE" MAY BE YOUR OWN EARLIER LEVER (P31 S68; byte-proven main/func_800241C0, fable escalation, 19 → 0 in 3 iterations) L31637 - **§367** — RECONCILING A DECL CONFLICT BETWEEN TWO DRAFTS FOR THE SAME TU (P31 S68; main) L31777 -### jump tables & switches (53) +### jump tables & switches (54) - **§8** — rodata island (compiler jump tables) — the `.data→.rodata→.data` sandwich (Phase 7) L339 - **§8a** — rodata island in a flat OVERLAY — the tail sandwich, per matched jr-function (Phase 26 — PoC PROVEN) L361 @@ -759,6 +759,7 @@ - **§339** — A 2-CASE SWITCH OMITS THE LOW-BOUND RANGE TEST, SO THE PRESENCE OF `slti/bnez` BETWEEN THE `beq`s IS A **COUNT TELL** FOR A THIRD CASE NODE (P31 S67; byte-proven ov_SC02_005/func_80190538, 197 ins) L31181 - **§362** — TWO TRAPS WHEN A CARVE MOVES A STUB INTO THE `-O0` TU (P31 S68; byte-proven, 6 fns / 2,547 ins across ov_MAIN_012 / ov_SC02_037 / ov_SC03_107) L31682 - **§371** — ★★ — CARVING A **SINGLE-OBJECT MODULE BINARY**, AND THE spimdisasm RODATA-MIGRATION TRAP THAT FOLLOWS (P31 S68; byte-proven md_MAIN_003, func_800D0D6C 345 ins) L31890 +- **§384** — ★★★ — A CARVE-CONFIG BANK IS RED UNTIL YOU RE-EXTRACT, AND THAT LOOKS EXACTLY LIKE A FALSE BANK (P31 S69; measured twice, cost one destroyed match) L32259 ### optimisation level (-O0/-O2) (21) @@ -1166,7 +1167,7 @@ - **§371** — ★★ — CARVING A **SINGLE-OBJECT MODULE BINARY**, AND THE spimdisasm RODATA-MIGRATION TRAP THAT FOLLOWS (P31 S68; byte-proven md_MAIN_003, func_800D0D6C 345 ins) L31890 - **§383** — TWO TOOLCHAIN FACTS THE PACKS DID NOT CARRY (P31 S69) L32244 -### process, measurement & doctrine (126) +### process, measurement & doctrine (127) - **§8e** — The jtbl ALIGNMENT LAW + the pad-spec filter — multi-table .rodata spans (Phase 29, byte-proven; `.run/probe_jtbl/verdict.md`) L549 - **§3-The** — mechanism: game-code dedup is SOURCE-LEVEL, not an object swap (R-D1, the key lesson) L945 @@ -1294,6 +1295,7 @@ - **§361** — ★ — A LOOP-TAIL BYTE SIGNATURE THAT NAMES ITS SOURCE SHAPE — AND THE LAW THAT A "SCHEDULING TIE" MAY BE YOUR OWN EARLIER LEVER (P31 S68; byte-proven main/func_800241C0, fable escalation, 19 → 0 in 3 iterations) L31637 - **§370** — ★★ — A **HARD BOUND** FROM sched.c, AND THE reorg SLOT-STEAL DIAGNOSTIC (P31 S68; main/func_8001BC6C, 69 ins, NOT closed — 33 → 28 over ~45 measured compiles) L31838 - **§376** — ★★★ — A STANDALONE `match_one` CLOSENESS OF 0 IS A CLAIM ABOUT THE **BODY**, NEVER ABOUT THE **TU** (P31 S69; measured 0/28) L32055 +- **§384** — ★★★ — A CARVE-CONFIG BANK IS RED UNTIL YOU RE-EXTRACT, AND THAT LOOKS EXACTLY LIKE A FALSE BANK (P31 S69; measured twice, cost one destroyed match) L32259 ### (unbucketed — title matched no symptom vocabulary) (307) @@ -2646,6 +2648,7 @@ - **§381** — THE `insn_count` HOIST THRESHOLD IS A DIAL YOU CAN READ WITH `cc1 -dL` (P31 S69; four independent uses in one wave) L32216 - **§382** — TWO FOLD REASSOCIATIONS THAT NEED THEIR OWN STATEMENT (P31 S69) L32232 - **§383** — TWO TOOLCHAIN FACTS THE PACKS DID NOT CARRY (P31 S69) L32244 +- **§384** — ★★★ — A CARVE-CONFIG BANK IS RED UNTIL YOU RE-EXTRACT, AND THAT LOOKS EXACTLY LIKE A FALSE BANK (P31 S69; measured twice, cost one destroyed match) L32259 --- @@ -3696,3 +3699,4 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: ` | L32216 | §381 | THE `insn_count` HOIST THRESHOLD IS A DIAL YOU CAN READ WITH `cc1 -dL` (P31 S69; four inde | | L32232 | §382 | TWO FOLD REASSOCIATIONS THAT NEED THEIR OWN STATEMENT (P31 S69) | | L32244 | §383 | TWO TOOLCHAIN FACTS THE PACKS DID NOT CARRY (P31 S69) | +| L32259 | §384 | ★★★ — A CARVE-CONFIG BANK IS RED UNTIL YOU RE-EXTRACT, AND THAT LOOKS EXACTLY LIKE A FALSE | diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index bf6f3bf031..a60ad72241 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -32255,3 +32255,53 @@ expression", never "add a cast": `(s16)` `sll`/`sra` pair**. Only an `s16` local assigned in one block and consumed in a distant one does — and the copy must sit ABOVE the guard, or it coalesces away against the target's `addu $a1,$v0,$zero` (`func_8002D904`). + +## §384 ★★★ — A CARVE-CONFIG BANK IS RED UNTIL YOU RE-EXTRACT, AND THAT LOOKS EXACTLY LIKE A FALSE BANK (P31 S69; measured twice, cost one destroyed match) + +**The symptom.** A gate banks a jtbl function, commits, and reports green. You then verify the +binary in the main tree with `make build BINARY=` and get a SHA mismatch: + +``` +[FAIL] build/ov_SC04_011/ov_SC04_011 + got 9c94d36a2cb5d8b56073d859c6e58cf396a5e750 + want 8bc09c422de2c28b3d71cf382cb6241c1e39d5db +``` + +Every instinct says false bank. **It is not.** Both times it happened in S69, the bank was +byte-perfect: + +``` +make extract BINARY=ov_SC06_025 && make build BINARY=ov_SC06_025 -> BYTE-IDENTICAL +make extract BINARY=ov_SC04_011 && make build BINARY=ov_SC04_011 -> BYTE-IDENTICAL +``` + +**The mechanism.** Banking a jtbl function changes CARVE CONFIG — `JTBL_PADS` in +`config/overlays.mk` and the binary's splat yaml (`tables=+0x0,+0x20,+0x40,+0x58` gaining a fifth +entry). Those files are splat **inputs**: `asm/` and the linker script are *generated from them*. A +worker gates inside a worktree that regenerated its own state, so it is right. The main tree, after +the merge, holds NEW carve config against OLD extracted state — and links the newly-carved C against +a stale `.ld`. The SHA that comes out is meaningless. + +**The trap inside the trap.** Reverting the C alone makes it worse and *changes* the error, which +reads like progress: + +``` +jtbl_rodata_pads: consumed 4 rodata jump table(s) but 5 pad spec(s) given — table-count drift vs the carve +``` + +That is the src and the carve state disagreeing — you reverted half a commit. A carve revert must +carry `config/` too (see the `carve-state-files-never-blanket-add` discipline). + +**The law.** *Verification after a gate must regenerate whatever that gate changed the inputs to.* +Concretely: + +| the gate touched | the valid per-binary check | +|---|---| +| `src/` only | `make build BINARY=` | +| anything under `config/` | **`make extract BINARY= && make build BINARY=`** | + +This is the R22 corollary aimed the other way. R22 says a *reverted* config needs a re-extract; a +*landed* config change needs one just as much. It is also R40 in its purest form — the instrument +(a build over stale extract state) was broken, and I attributed the failure to the subject, reverted +a legitimate 96-line match, and wrote a checkpoint calling it a false bank. The give-away I ignored: +the commit's own diffstat showed `config/overlays.mk` and a splat yaml right next to the `.c`. diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index f978b95e6d..b4c8c78edb 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -4334,11 +4334,14 @@ cast_self_callers --sync-decls # 3: narrow-param, C89-illegal for no-proto (§3 It generalises to the CALLEE named in the diagnostic (banked `main:func_80021D38` that way). ### FOUR OF MY OWN DEFECTS, ALL MEASURED, ALL FIXED -1. **A FALSE BANK reached the tree** (`ov_SC04_011`, sha 9c94d36a vs 8bc09c42). The gate that made it - ran `--no-r22` because agents were live. Reverting needed the CARVE STATE too (JTBL_PADS 4->5 pads - + splat yaml); a src-only revert gave "table-count drift vs the carve". **It may not even be - false** — the bank changed splat config, and the R22 corollary says a config change needs - `make extract`, not just a rebuild. RETEST with an extract; the draft is preserved. +1. **~~A FALSE BANK reached the tree~~ — CORRECTED: it was never false, MY CHECK WAS BROKEN (§384).** + `ov_SC04_011` and later `ov_SC06_025` both read as SHA mismatches in the main tree. Both are + byte-perfect: `make extract BINARY= && make build` -> BYTE-IDENTICAL, proven on both. A jtbl + bank changes CARVE CONFIG (JTBL_PADS + splat yaml), which are splat INPUTS — so a build-only check + links newly-carved C against STALE extracted state. I reverted a legitimate 96-line match on that + reading (restored in commit:3481) after writing "it may not even be false" and not testing it. + **STANDING FIX: if a gate touched `config/`, the per-binary verify is `make extract && make build`, + never build alone.** Build-only is valid only when nothing under config/ changed. 2. **`cast_self_callers` left casts behind for drafts that did not bank**, and one of them made `ov_SC07_000` fail to COMPILE at HEAD — so every later gate verdict on it measured a broken baseline. Found because TWO drafting agents reported BASELINE-RED and I checked their claim.