docs(phase-30 S11): cookbook §138 + SESSION-33 checkpoint

§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).
This commit is contained in:
Drew T
2026-08-03 23:55:53 -06:00
parent 62042f65ca
commit 3daa647bb3
3 changed files with 189 additions and 8 deletions
+19 -7
View File
@@ -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 <sub>L5273</sub>
- **§70** — The giv-init base register: walk the PARAMETER, not a copy of it (Phase 29 SESSION-18, `func_801777BC`) <sub>L5612</sub>
### structs, block moves & memcpy (28)
### structs, block moves & memcpy (29)
- **§3-T2** — Source statement order drives instruction scheduling <sub>L78</sub>
- **§5** — Known hard-residual classes (instruction-identical, one byte-exact blocker) <sub>L199</sub>
@@ -138,6 +138,7 @@
- **§3-The** — three-hypothesis trail, because two of them were wrong and the wrongness is instructive <sub>L6864</sub>
- **§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`) <sub>L8430</sub>
- **§129a** — the target instruction count is INFLATED after a carve <sub>L8434</sub>
- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param <sub>L9455</sub>
### types, signedness & load/store width (29)
@@ -171,7 +172,7 @@
- **§3-Do** — NOT "strip the duplicate typedef" — it breaks the extern that uses it <sub>L8030</sub>
- **§3-The** — type-form rules <sub>L8872</sub>
### declarations, prototypes & K&R (50)
### declarations, prototypes & K&R (51)
- **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch <sub>L90</sub>
- **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) <sub>L437</sub>
@@ -223,6 +224,7 @@
- **§121** — Synthesise externs for macro-DEFINED callees from the macro's own definition head (Phase 29 T95) <sub>L8054</sub>
- **§3-The** — declaration surface (integration, not codegen) <sub>L8931</sub>
- **§136f** — Two declaration sub-cases the reconcile lane surfaced (lane now 15/15 lifetime) <sub>L9176</sub>
- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius <sub>L9405</sub>
### jump tables & switches (25)
@@ -267,7 +269,7 @@
- **§127a** — §71 (sibling-first) is the strongest `-O0` lever, and it beats the index <sub>L8370</sub>
- **§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`) <sub>L8563</sub>
### 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) <sub>L483</sub>
- **§11** — Cross-binary dedup & code-sharing (Phase 11 — "one match unlocks many") <sub>L908</sub>
@@ -336,6 +338,7 @@
- **§124a** — a family sweep's `0 matched-exemplar families` may be a FILTER, not a wall <sub>L8191</sub>
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) <sub>L8704</sub>
- **§136c** — SIBLING-FIRST is a DERIVATION shortcut, not just a conflict fix (the fastest route in a family wave) <sub>L9059</sub>
- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius <sub>L9405</sub>
### integration / TU plumbing (34)
@@ -374,7 +377,7 @@
- **§3-The** — integration idioms (these decide whether a byte-correct draft BANKS) <sub>L8797</sub>
- **§3-The** — declaration surface (integration, not codegen) <sub>L8931</sub>
### build graph, splat & the harness (92)
### build graph, splat & the harness (94)
- **§4** — Flag/toolchain gotchas <sub>L190</sub>
- **Build** — mechanism — per-file opt override (splat resegmentation) <sub>L288</sub>
@@ -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) <sub>L8704</sub>
- **§3-The** — splitting/merging rules (each closed a residual, byte-gated) <sub>L8846</sub>
- **§137a** — A gate verdict has a TIMESTAMP; re-check it against the draft's mtime <sub>L9376</sub>
- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius <sub>L9405</sub>
- **§134** — again, in a second tool — and the waiter rule corrected <sub>L9472</sub>
### 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`) <sub>L530</sub>
- **§3-The** — mechanism: game-code dedup is SOURCE-LEVEL, not an object swap (R-D1, the key lesson) <sub>L926</sub>
@@ -523,8 +528,9 @@
- **§136g** — When the index points at the WRONG lever: two byte-refuted routings (func_801863B4) <sub>L9201</sub>
- **§136h** — CORRECTION: the zero-crack pool does NOT "refill with cheap work" (my error, byte-measured) <sub>L9230</sub>
- **§136j** — The failure MIX flips with function size (measured across four bands, one session) <sub>L9292</sub>
- **Rank** — the lane by measured concentration, not by class count <sub>L9463</sub>
### (unbucketed — title matched no symptom vocabulary) (107)
### (unbucketed — title matched no symptom vocabulary) (108)
- **§3-How** — to use this <sub>L30</sub>
- **§1** — Idiom catalog (asm pattern → C that produces it) <sub>L39</sub>
@@ -633,6 +639,7 @@
- **§136d** — Four gcc-2.7.2 levers the redraft lane found (each closed a residual no other lever moved) <sub>L9084</sub>
- **§136e** — §136c's PRECONDITION, and two more symptom keys (wave 4b batch 3) <sub>L9128</sub>
- **§136i** — The drafter model LADDER: Haiku → **Sonnet** → Opus → Fable5 (Drew, 2026-08-03) <sub>L9260</sub>
- **§3-The** — triage, cheapest first <sub>L9411</sub>
## All sections, in order
@@ -1019,3 +1026,8 @@
- **§136j** — The failure MIX flips with function size (measured across four bands, one session) <sub>L9292</sub>
- **§137** — REGALLOC-PERM is a TWO-COMPILE ARITHMETIC PROBLEM, not a permuter job <sub>L9334</sub>
- **§137a** — A gate verdict has a TIMESTAMP; re-check it against the draft's mtime <sub>L9376</sub>
- **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius <sub>L9405</sub>
- **§3-The** — triage, cheapest first <sub>L9411</sub>
- **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param <sub>L9455</sub>
- **Rank** — the lane by measured concentration, not by class count <sub>L9463</sub>
- **§134** — again, in a second tool — and the waiter rule corrected <sub>L9472</sub>
+93
View File
@@ -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=<ov>`, so a poll lands in the gap between two and reports a live
campaign finished. And `pgrep -f <pattern>` **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.
+77 -1
View File
@@ -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 <pattern>` 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).