From 3daa647bb35b094e35c4b2788e16faebe15cb8dc Mon Sep 17 00:00:00 2001
From: Drew T <50529377+Druthulu@users.noreply.github.com>
Date: Mon, 3 Aug 2026 23:55:53 -0600
Subject: [PATCH] =?UTF-8?q?docs(phase-30=20S11):=20cookbook=20=C2=A7138=20?=
=?UTF-8?q?+=20SESSION-33=20checkpoint?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
§138 — "the propagation lanes: a gate refusal is a DECLARATION, and which lever
you owe depends on blast radius". The durable content of this session:
- the 4-lever triage table ranked by blast radius, and the rule to grep the
fleet's decl shapes BEFORE relaxing to `()` (illegal only against a
default-promotion param — 4,020 decls measured, 8 of 36 banked for one token)
- `volatile` in the host TU is a SCHEDULING BARRIER that masquerades as a codegen
wall; the tell is a positional shift with a `nop` at a delay slot, and the
h_exact contract is confirmed/refuted in ONE command with no build
- the DEFINITION-side asm-label alias as the only zero-radius escape when the
fleet canon disagrees on a promoting param (1,725 in-tree precedents)
- rank a lane by measured concentration, not class count (5 of 45 classes carried
89%), and `--recover` is not a retry (16/16 on drafts, 4/138 on a propagation)
- §134 multi-line blindness recurring in a second tool; decide on `cdecl._mask`
- the waiter rule CORRECTED: `pgrep -x make` is wrong for a campaign of
sequential makes, `pgrep -f` self-matches, `nohup … &` signals the wrapper
Checkpoint refreshed and placed below the task checklist (fresh-session safe):
fleet 96.10 / 93.7 / 88.0, dedup 1908/0, R22 140/140 four times this session,
nothing running, lock free. Three named next items, none yet diagnosed against a
build — the PROPAGATE head remainder (11,147 ins), the 41-class tail (2,316),
and EXTEND's last 5 (the whale needs the §38 -O0 route; dedup_extend should
refuse-and-name that class per R32).
---
docs/cookbook-index.md | 26 ++++++++---
docs/matching-cookbook.md | 93 +++++++++++++++++++++++++++++++++++++
phase-ends/CURRENT_PHASE.md | 78 ++++++++++++++++++++++++++++++-
3 files changed, 189 insertions(+), 8 deletions(-)
diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md
index 671df474d..4906ba081 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 / 382 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 / 387 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.
@@ -108,7 +108,7 @@
- **§66d-1** — What transfers between giants is the LOOP, not the PIN L5273
- **§70** — The giv-init base register: walk the PARAMETER, not a copy of it (Phase 29 SESSION-18, `func_801777BC`) L5612
-### structs, block moves & memcpy (28)
+### structs, block moves & memcpy (29)
- **§3-T2** — Source statement order drives instruction scheduling L78
- **§5** — Known hard-residual classes (instruction-identical, one byte-exact blocker) L199
@@ -138,6 +138,7 @@
- **§3-The** — three-hypothesis trail, because two of them were wrong and the wrongness is instructive L6864
- **§129** — Post-carve, `rtu_match`/`match_one` COUNT THE JUMP TABLE AS INSTRUCTIONS; and a carve must never be committed without its owner (P30 S28, `func_8013BD74`) L8430
- **§129a** — the target instruction count is INFLATED after a carve L8434
+- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9455
### types, signedness & load/store width (29)
@@ -171,7 +172,7 @@
- **§3-Do** — NOT "strip the duplicate typedef" — it breaks the extern that uses it L8030
- **§3-The** — type-form rules L8872
-### declarations, prototypes & K&R (50)
+### declarations, prototypes & K&R (51)
- **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch L90
- **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) L437
@@ -223,6 +224,7 @@
- **§121** — Synthesise externs for macro-DEFINED callees from the macro's own definition head (Phase 29 T95) L8054
- **§3-The** — declaration surface (integration, not codegen) L8931
- **§136f** — Two declaration sub-cases the reconcile lane surfaced (lane now 15/15 lifetime) L9176
+- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405
### jump tables & switches (25)
@@ -267,7 +269,7 @@
- **§127a** — §71 (sibling-first) is the strongest `-O0` lever, and it beats the index L8370
- **§132** — The `JR-PAIR-IN-ONE-O0-OBJECT` "wall" was TWO instrument defects: a merged-double span the carve could not see, and a truncated object no rule deleted (P30 S29, `func_8013B83C` + `func_8013BD74`) L8563
-### family propagation & sweeps (67)
+### family propagation & sweeps (68)
- **§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) L483
- **§11** — Cross-binary dedup & code-sharing (Phase 11 — "one match unlocks many") L908
@@ -336,6 +338,7 @@
- **§124a** — a family sweep's `0 matched-exemplar families` may be a FILTER, not a wall L8191
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) L8704
- **§136c** — SIBLING-FIRST is a DERIVATION shortcut, not just a conflict fix (the fastest route in a family wave) L9059
+- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405
### integration / TU plumbing (34)
@@ -374,7 +377,7 @@
- **§3-The** — integration idioms (these decide whether a byte-correct draft BANKS) L8797
- **§3-The** — declaration surface (integration, not codegen) L8931
-### build graph, splat & the harness (92)
+### build graph, splat & the harness (94)
- **§4** — Flag/toolchain gotchas L190
- **Build** — mechanism — per-file opt override (splat resegmentation) L288
@@ -468,8 +471,10 @@
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) L8704
- **§3-The** — splitting/merging rules (each closed a residual, byte-gated) L8846
- **§137a** — A gate verdict has a TIMESTAMP; re-check it against the draft's mtime L9376
+- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405
+- **§134** — again, in a second tool — and the waiter rule corrected L9472
-### process, measurement & doctrine (52)
+### process, measurement & doctrine (53)
- **§8e** — The jtbl ALIGNMENT LAW + the pad-spec filter — multi-table .rodata spans (Phase 29, byte-proven; `.run/probe_jtbl/verdict.md`) L530
- **§3-The** — mechanism: game-code dedup is SOURCE-LEVEL, not an object swap (R-D1, the key lesson) L926
@@ -523,8 +528,9 @@
- **§136g** — When the index points at the WRONG lever: two byte-refuted routings (func_801863B4) L9201
- **§136h** — CORRECTION: the zero-crack pool does NOT "refill with cheap work" (my error, byte-measured) L9230
- **§136j** — The failure MIX flips with function size (measured across four bands, one session) L9292
+- **Rank** — the lane by measured concentration, not by class count L9463
-### (unbucketed — title matched no symptom vocabulary) (107)
+### (unbucketed — title matched no symptom vocabulary) (108)
- **§3-How** — to use this L30
- **§1** — Idiom catalog (asm pattern → C that produces it) L39
@@ -633,6 +639,7 @@
- **§136d** — Four gcc-2.7.2 levers the redraft lane found (each closed a residual no other lever moved) L9084
- **§136e** — §136c's PRECONDITION, and two more symptom keys (wave 4b batch 3) L9128
- **§136i** — The drafter model LADDER: Haiku → **Sonnet** → Opus → Fable5 (Drew, 2026-08-03) L9260
+- **§3-The** — triage, cheapest first L9411
## All sections, in order
@@ -1019,3 +1026,8 @@
- **§136j** — The failure MIX flips with function size (measured across four bands, one session) L9292
- **§137** — REGALLOC-PERM is a TWO-COMPILE ARITHMETIC PROBLEM, not a permuter job L9334
- **§137a** — A gate verdict has a TIMESTAMP; re-check it against the draft's mtime L9376
+- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405
+- **§3-The** — triage, cheapest first L9411
+- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9455
+- **Rank** — the lane by measured concentration, not by class count L9463
+- **§134** — again, in a second tool — and the waiter rule corrected L9472
diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md
index b0e5b441e..e4f83637c 100644
--- a/docs/matching-cookbook.md
+++ b/docs/matching-cookbook.md
@@ -9399,3 +9399,96 @@ relocation mask leaves open, without running `make`):
Symptom line for the index: **"`match_one`/`rtu_match` say MATCH but the whole-overlay SHA still
DIFFs"** has exactly three causes — a stale verdict, a wrong `jal`/`%hi`/`%lo` target the mask hides,
or collateral from file-scope decls — and the two oracles above discriminate all three offline.
+
+---
+
+## §138 — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius
+
+**Symptom key:** `dedup_extend` or `dedup_propagate` plans N members and banks **0**, or reports
+`PLUMBING: conflicting types for X` / an undiagnosed `DIFF`. Measured this session: a 0/36 lane went
+to **31/36**, and every single blocker was a declaration — not one was compiler codegen.
+
+### The triage, cheapest first
+
+Capture each failure's **own compiler error** (§136a — classify on the build's OUTPUT, never its exit
+status) and bucket by which symbol is named. The named symbols repeat: 9 failures per binary reduced
+to **4 distinct symbols** shared across all four binaries. Then pick the *lowest-blast-radius* lever
+that is byte-neutral **by construction**:
+
+| conflict | lever | radius |
+|---|---|---|
+| macro declares `(void)`, TU declares `(ptr)`, **use is cast** | relax the macro decl to `()` | T2, 1 token |
+| TU decl is unused boilerplate (**zero uncast uses**) | conform the TU decl to the fleet canon | T1 |
+| TU declares the symbol `volatile`, or any type the macro can't match | **asm-label alias on the DATA** | T2 |
+| the fn's own signature (return/arity/param) | **asm-label alias on the DEFINITION** | T2 |
+
+**Before relaxing to `()`, MEASURE the whole fleet's decl shapes for that symbol.** `()` is illegal
+against a prototype carrying a *default-promotion* param (`s8/s16/u8/u16/char/short/float`) — the
+documented gcc-2.7.2 dead-end. It is legal against pointers and `s32`. One `grep -rhoE` over `src/`
+answers it; 4,020 decls of `func_80146C3C` were all `(void)/()/(u8*)`, so the relax was safe and
+bought 8 of 36 for one token.
+
+**One conflict HIDES the next.** A declaration conflict *aborts the compile*, so the error you see
+says nothing about what is behind it (the S29 law). Fixing `func_8012E5CC` immediately revealed
+`func_80147364` at the same site. Re-run after every fix; do not price the lane off the first error.
+
+### `volatile` in the host TU is a SCHEDULING BARRIER — and it looks exactly like a codegen wall
+
+The four "undiagnosed DIFF"s in `dedup_extend`'s own header were this. Its correctness argument says
+an `h_exact` match guarantees byte-identity *including relocs*, so a DIFF should be impossible.
+Both halves resolved against the bytes:
+
+1. **The contract HELD** — `func_80162FF4`'s original bytes are sha1-identical in the failing and the
+ working overlay (`af1aceb2…`). *Check this first: it splits "the registry is lying" from "the TU
+ is different" in one command, with no build.*
+2. **The TU differed** — the host TU declared `extern volatile s32 D_80127090/94/98` at FILE scope,
+ which no working overlay's copy of that TU does. Volatile makes the macro's three stores a
+ barrier, so `addu $a0,$s2,$zero` could not sink into the `jal`'s delay slot: the build emitted it
+ early **plus a `nop`**, one instruction longer.
+
+**The tell:** a diff that is a *positional shift with a `nop` appearing at a delay slot* is an
+ordering constraint, not a wrong body. Look for a qualifier (`volatile`, `const`) on a symbol the
+body touches before reaching for a codegen idiom. The fix is the **data asm-label alias**
+(`extern s32 aD_80127090 __asm__("D_80127090")`): a distinct C identifier is immune to any TU's
+declaration of that symbol, and is byte-neutral wherever the macro already worked.
+
+### The DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param
+
+`func_80147364`'s byte-true definition is `(u16, u16)`; **4,046 fleet decls say `(u16, s32)`**. `()`
+is illegal (u16 promotes) and conforming the decls would change caller codegen. Author the macro as
+`void aF80147364(u16, u16) __asm__("func_80147364");` + a definition of the aliased name: the real
+symbol is emitted, every caller keeps its own declaration, blast radius is zero. In-tree precedent:
+**1,725 files** already use this form. Banked ×137 first try.
+
+### Rank the lane by measured concentration, not by class count
+
+A "45 classes / 20,837 ins" queue was really **5 classes carrying 89% of it**. Re-split the ledger by
+`nins × n_stub` before scheduling anything — and note the per-class outcomes diverge wildly
+(4,110 banked ×137 · 3,288 banked ×138 · 3,973 dropped · 3,886 at 4/138 · 3,288 tool-gapped), so a
+lane average predicts nothing. **`--recover` is not a retry:** the caller-extern reconcile that is
+16/16 lifetime *on drafts* banked 4 of 138 on a *propagation*. Probe one excluded member's build
+output before re-running any lever that already returned a bad number.
+
+### §134 again, in a second tool — and the waiter rule corrected
+
+`dedup_propagate.find_site`'s preamble backscan had the SESSION-18 fix for blank / `//` /
+**single-line** `/* … */` lines, and still halted on a **multi-line block comment** (middle lines
+start `*`; the last ends `*/` without starting `/*`). Same class S6b fixed three times in
+`family_remap`. **Decide skippability on `cdecl._mask`, not on line syntax** — one oracle (R33),
+every comment form, immune to a `/*` inside a string, with an R32 assertion that the mask is
+length-preserving. Also: a body declaring a draft-local `struct Tag {…}` is unextractable by design;
+if the identical layout already exists in `src/shared/engine_types.h`, switching the exemplar to the
+shared tag is byte-neutral and unblocks propagation.
+
+**Waiter rule, corrected (three failures, one mechanism — the signal sampled is not the thing waited
+for):** `pgrep -x make` is right for ONE make and **wrong for a campaign** — `dedup_propagate` runs a
+*sequence* of `make build BINARY=`, so a poll lands in the gap between two and reports a live
+campaign finished. And `pgrep -f ` **self-matches** its own command line, so that waiter can
+never exit. Wait on the campaign process by its real argv (`ps -eo args | grep 'python3 tools/…'`) or
+on **`tools/treelock.sh --status`**, which is a statement of intent spanning the gaps. Likewise never
+wrap a campaign in `nohup … &` inside a backgrounded call: the harness then signals completion of the
+*wrapper* — a fleet check "finished" at 63/140.
+
+Symptom line for the index: **"a propagation/extend lane plans N and banks 0"** — read each failure's
+compiler error, bucket by named symbol, and apply the lowest-radius byte-neutral alias; a `volatile`
+in the host TU and a fleet decl carrying a promoting param are the two that masquerade as codegen.
diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md
index b78d97af5..ca46f63d8 100644
--- a/phase-ends/CURRENT_PHASE.md
+++ b/phase-ends/CURRENT_PHASE.md
@@ -147,7 +147,83 @@ stub on a named wall/behemoth/queue ledger** — 140/140 byte-identical througho
---
-# 🛑 SESSION-31/32 CHECKPOINT (2026-08-03) — FRESH SESSION SAFE HERE
+# 🛑 SESSION-33 CHECKPOINT (2026-08-04) — FRESH SESSION SAFE HERE
+> **Nothing is running. Tree lock FREE. Tree CLEAN** but for the R23 `db.*.gbf` churn — never stage.
+> Effort: **ultracode**. **R22 clean-fleet run FOUR times this session, 140/140 every time.**
+> HEAD `commit:1380`. **Drew's standing decision: NO phase close — keep grinding.**
+
+## FLEET — R22 **140 passed / 0 failed of 140**
+**96.10% fn-count · 93.7% instr-weighted · 88.0% distinct-code** · dedup **1908/0** ·
+C1 240807/240807 · **0 NON_MATCHING** (G4).
+Phase opened 92.00 / 87.5 / 78.0 ⇒ **+4.10pp fn, +6.2pp instr, +10.0pp distinct.**
+
+## WHAT S33 DID — lane 2 of the S10 checkpoint (the propagation lag), taken FIRST on the
+standing "probe the cheap lever before funding the expensive one" doctrine. **~0 agent tokens.**
+- **SC07 EXTEND: 0/36 → 31/36.** Commits `commit:1377` · `commit:1378`.
+- **PROPAGATE head: 7,398 of 18,545 ins banked** — `func_80147364` ×137 (4,110) + `func_8012A598`
+ ×138 (3,288). Commits `commit:1379` · `commit:1380`.
+- **Distilled to cookbook §138** (+ index regenerated) — the full triage is there, not here.
+
+## 🔑 THE FINDING: a gate refusal in these lanes is a DECLARATION, not codegen
+**Not one of the 36 EXTEND blockers was compiler codegen.** Nine failures per binary reduced to
+**4 distinct symbols** repeated across all four. Two masqueraded as walls:
+1. **The 4 "undiagnosed DIFF"s in `dedup_extend`'s own header are a `volatile`.** Its correctness
+ argument says an h_exact match makes a DIFF impossible — and the contract HELD (original bytes
+ sha1-identical across the failing and working overlay, `af1aceb2…`, *checked in one command with
+ no build*). The host TU declared `extern volatile s32 D_80127090/94/98` at FILE scope, which no
+ working overlay's copy does ⇒ the macro's three stores became a scheduling barrier ⇒ `addu`
+ could not sink into the `jal` delay slot ⇒ built body emitted it early **plus a `nop`**, one
+ instruction longer. **Tell: a positional shift with a `nop` at a delay slot is an ORDERING
+ constraint, not a wrong body.** Fixed by the §37/§124 DATA asm-label alias. 16/16 on retry.
+2. **`func_80147364`: definition `(u16,u16)` vs 4,046 fleet decls `(u16,s32)`.** u16 promotes, so
+ the `()` escape is ILLEGAL. The **DEFINITION-side** asm-label alias is the only zero-radius
+ escape (1,725 in-tree precedents). Banked ×137 first try.
+**Before relaxing a decl to `()`, grep the fleet's decl shapes for that symbol** — `()` is illegal
+only against a *default-promotion* param. 4,020 decls of `func_80146C3C` were all `(void)/()/(u8*)`
+⇒ safe ⇒ 8 of 36 for ONE token.
+
+## 🧰 TOOL FIX — §134 multi-line blindness, now in a SECOND tool
+`dedup_propagate.find_site`'s preamble backscan had the SESSION-18 fix for blank/`//`/single-line
+comments and still halted on a **multi-line block comment**. Same class S6b fixed 3× in
+`family_remap`. Now decides on **`cdecl._mask`** (one oracle, R33) with an R32 length-preservation
+assertion. Monotone + byte-gate-fed ⇒ can fail to bank, never falsely bank. Paired with switching
+the `func_8012A598` exemplar off its draft-local `struct BigCopy164` to the shared `struct BigCopy`
+(engine_types.h L312, already used identically at engine_core.h:16158). **Either fix alone leaves
+the function written off.**
+
+## ▶ RESUME HERE — three named items, none diagnosed against a build yet
+1. **The PROPAGATE head remainder — 11,147 ins.** `func_8012f274` (3,973, **dropped**),
+ `func_8016ba68` (3,886, **4 of 138**), `func_801466f0` (3,288, **no source found** — the S6b
+ **D4** gap: its def at `ov_SC01_077_after.c:495` carries a *wrapped* `__asm__` alias decl that
+ `_alias_decl_for`'s single-line `rx.match` cannot see, with a file-scope `typedef struct
+ Rec801466F0` behind it, §100). **`--recover` is NOT a retry** — it banked 4 of 138 here, and the
+ reconcile lane that is 16/16 lifetime *on drafts* does not transfer to *propagation*. **Probe
+ ONE excluded overlay's build output (§136a) before re-running any lever.**
+2. **The 41-class PROPAGATE tail** — 2,316 ins total. Low value; batch it or ledger it.
+3. **EXTEND's last 5:** `func_80144B9C` ×4 — the whale's registry `func` field is a bare name, not
+ a `DEFINE_` macro, so `write_drafts` emits a CALL (hence "undefined reference" in ov_SC07_010);
+ it needs the §38 `-O0` shared-header route, **and `dedup_extend` should refuse-and-name the
+ class per R32** rather than feed the gate a draft that cannot pass. Plus `func_80149954` ×1,
+ blocked behind `func_80147364`'s u16 params.
+Then: **lane 1** (S10's 17 unbanked targets, 26,227 templ ins, Sonnet at ~12-16 concurrency — the
+manifest `.run/s10.json` / script `.run/s10.js` are still valid) and **lane 3** (the ×2-9 grind).
+
+## 🧰 MY PROCESS ERRORS THIS SESSION — all ONE mechanism, all now in §138
+**The signal I sampled was not the thing I was waiting for**, three times:
+1. `nohup CMD &` inside a backgrounded call ⇒ the harness signalled the **wrapper**'s exit; the
+ fleet check stood at **63/140** and I nearly read it as a pass.
+2. **CORRECTION to the S10 checkpoint's own rule.** It says use `pgrep -x make`. Right for ONE
+ make, **wrong for a campaign** of sequential makes — it fired in a gap and called a live
+ campaign done. And **`pgrep -f ` SELF-MATCHES**, so that waiter can never exit (two
+ spinning shells, killed). **Wait on the campaign's real argv or on `treelock.sh --status`.**
+3. A `corpus.stubs` probe run mid-rebuild returned garbage — R32's coverage assertion refused to
+ answer rather than hand me a wrong stub set. *A measurement taken during a rebuild is not a
+ measurement* (S27's law, re-earned).
+No bad bytes from any of them — the byte-gate and R22 caught everything.
+
+---
+
+# 🛑 (superseded) SESSION-31/32 CHECKPOINT (2026-08-03)
> **Nothing is running. Tree lock FREE. Tree CLEAN** but for the R23 `db.*.gbf` churn — never stage.
> Effort: **ultracode**. **R22 clean-fleet run TWELVE times, 140/140 every time.** HEAD `commit:1375`.
> **Drew's standing decision: NO phase close — keep grinding** (task #15).