# CURRENT_PHASE — Phase 24: Fix + evolve the permuter (§31-class-aware) · integration-recovery tool · scale the §31 wave **Started:** 2026-07-02 · **Effort:** Max · **Gen2 phase 16 of the arc (8→…→23→24)** · Open-ended matching phase (checkpoint-close, like 15/20/21/22). **Plan:** approved (Drew, sequencing = permuter-first, staged). Full plan: `/home/musashi/.claude/plans/plan-mode-enabled-max-tender-bengio.md`. **Baseline at phase start:** fleet 64.86% byte-identical-from-source (~30% byte-weighted); 136/136 binaries byte-identical; 0 NON_MATCHING; dedup groups per Phase-23 close. main `143dbb89…`, resident `8e17e02f…`, ov_SC01_077 `d19c9580…`. ## Invariant (every task) Whole-binary byte-gate (`tools/harvest_verify.py`) is the SOLE arbiter (G3/P9). Tools only reshape declarations/plumbing or PROPOSE candidates; nothing banks except a byte-identical SHA1 rebuild, verified CLEAN (R22): `make clean && (extract all 136) && make check-all` → 136/136; `tools/dedup_integrate.py --check` 0-failed; `tools/progress.py --fleet` monotonic up. No Ghidra DB change (R23 restart-noise — do NOT stage `db.*.gbf`). ## Task checklist - [x] T1 — Re-log map-wave results + backlog hygiene *(xHigh)* - [x] T2 — Permuter Stage-0: floor-free masked scorer (-drz) *(Max)* - [x] T3 — Permuter setup fixes: pins · typedefs · -O0 *(xHigh)* - [x] T4 — Probe the flagship func_80132784 (4/400) + count-exact seeds *(Max)* - [x] T5 — Permuter evolve: §31-directed mutation + grinder fixes *(Max)* - [x] T5b — Fable5 §31 map-extension spike: S11 CRACKED (func_8014E048 banked; S12/S13/RC-10 → §31) *(Max; Fable5)* — + found the Phase-21 breakage (overlay GetTPage + main-side 62 refs → both fixed in T5c) - [x] T5c — Fix the Phase-21 main/library clean-rebuild breakage (62 dangling INCLUDE_ASM refs) *(Max)* — renamed to curated names; **true clean 136/136 restored**; added `tools/lint_symbol_refs.py` guard - [x] **T6 — Integration-recovery tool + ×134 propagation-recovery** *(Max)* — flagship `func_80132784` ×134 (`commit:0443`) + `recover_integration.py` (`commit:0445`); **§A propagation-recovery COMPLETE (2026-07-03):** 15 more fns propagated ×134 — the 13 leaf-MATCHes (`commit:0447`) + func_8014E048 (T5b S11 crack) + func_80157580 (`commit:0448`). Fleet 64.90→**65.48%**, **clean fleet 136/136 (R22) after each batch**, dedup 1784→1799/0. Tool fixes: find_site indented-defs + trailing-comment externs, `dedup_propagate --recover` (Part B reconcile / Part A per-overlay exclude), build_engine_types comment-awareness. Broader capped tail (17 skips: 3 pin/asm/SHB stragglers + 14 local-type) → T8 sweep. - [x] T7 — Region-a giants *(Max)* — **✅ GIANT ENDGAME COMPLETE (2026-07-08):** §G batch (6/8 cracked, 4 ×134) + whale ×134 + this session's `func_801770E0` + `func_801372B0` ×134 ⇒ every matched region-a giant is ×134; NO matched giant remains ×1. The 2 remaining reach-134 giants are permanent walls (`func_80178004` biv-init, `func_801412A8` alloc-knot — INCLUDE_ASM, G4). Small ×1 tail (3 stragglers + 17 local-type) → T8. Fleet 66.02%. — giant-crack pipeline PROVEN: `func_80129CF8` Fable5-cracked + §32 idiom + banked ×1 (`commit:0450`) → **NOW ×134** (via T7b/T1: the "×134 wall" was an **R14 MISDIAGNOSIS** — the already-reconciled ×1 bank propagates cleanly via existing `dedup_propagate --recover`; clean fleet 136/136, fleet **65.52%**). 6 sibling giants still stubs (need Fable5/Opus match → then the tool). - [x] **T7b — Canonical-decl reconcile tool** *(Opus, Max — NOT Fable5)* — **COMPLETE** (plan `plan-…mossy-dawn.md`, T1–T6, commits `commit:0452`/`commit:0453`/`commit:0454`/`commit:0455`). **T1 (R14):** the "×134 wall" was a misdiagnosis — `func_80129CF8` banks ×134 FREE. **T2/T3:** `tools/reconcile_decls.py` (fleet-majority oracle + byte-neutral data-cast transform, wired into gate_stage), byte-proven. **T4** no-op (no per-member conflicts). **T5:** 2nd giant `func_80138ED0` MATCHED (Opus+§32→close=21→Fable5 MATCH) + banked ×134 — validates the tool + pipeline on a real un-reconciled sibling; **2 giants ×134 this task**, fleet 65.48→**65.56%**, clean 136/136. **T6:** cookbook §33/§34 (+ the 3-qty sort bug / zero-byte asm toolkit / giv-init fence), §31 map RC-11, SETUP, design-doc RESOLVED. Reframed value: the tool AUTOMATES the manual reconcile for freshly-matched giants + the wave tail (6 sibling giants remain). - [ ] T8 — Scale the §31 wave *(breadth → prompt for /effort toggle, R27)* — §D - [ ] T9 — Distill + PhaseEnd *(Max, Tier-1)* — §E **Current task:** ✅ **T7 §G ×1→×134 GIANT ENDGAME COMPLETE (2026-07-08)** — both remaining ×1 giants (`func_801770E0` 152, `func_801372B0` 207) banked ×134 via the native `dedup_propagate` DEFINE-macro path (R14: the handoff's 3rd "×1 giant" `func_8014E048` was already ×134). Clean fleet **136/136 (R22)**, dedup **1813/0**, fleet **66.02%**; no matched giant remains ×1; cookbook **§39** distilled. **NEXT (Drew's call):** **T8 — scale the §31 wave** over the near-miss / small-tail residuals (breadth-shaped → prompt for `/effort ultracode`, R26/R27; the 3 now-propagatable stragglers + 17 local-type ×1s are cheap fodder), **OR close the phase** (T9 — PhaseEnd, Tier-1 Max). **Rules check ✓ (P6).** main `143dbb89`, resident `8e17e02f`, ov_SC01_077 `d19c9580`; all 134 overlays now carry `func_801770E0` + `func_801372B0` ×134. **Fable5 policy (Drew, 2026-07-02):** Fable5 (`Agent(model:fable)`) is the reserved *discovery / wall-breaker* tier (reads the gcc-2.7.2 source; ~375k tok/giant), NOT the workhorse. Cheap-tier-first: permuter + Opus applying §31 → Fable5 only when they stall. Two uses this phase: (1) **on-demand escalation** on any giant the fixed permuter can't close (T4/T8 — no task); (2) **T5b** proactive spike to test whether S11/RC-6 are truly intrinsic. A Fable5-cracked lever goes into §31 (R16) so Opus applies it thereafter. ## §G — GIANT ENDGAME QUEUE (NEXT SESSION — Drew, 2026-07-04) — start AFTER this session's 3-giant Fable5 batch lands > The remaining **~9 reach-134 giants (≥150 ins)** to harvest next session (12 reach-134 giants were stubbed post-T7; **this session's batch = func_801392FC/8013A530/8013AF20**, banked HERE first). **Strategy: closest-to-completion FIRST + fast-track the whale via a cheap triage** — NOT smallest→largest (closeness = the effort; size = the payoff; a 204-ins giant can be close=10 while a 152-ins one is close=52). **R14: RE-MEASURE closeness first** (`match_one` per giant — the backlog values below are Phase-23-era, likely stale). **Bank this session's Fable5 idioms into §31 BEFORE starting** (compounding). Banking recipe = cookbook **§35**; per-giant integration classes (caller-conflict / callee-proto / local-typedef) in §35. > > **The order:** > 0. **Verify near-free:** `func_80178004` (165, backlog close=**0**, no saved draft) — `match_one` it FIRST; may bank almost free. > 1. **Closeness ladder (drafted/close = fast certain wins):** `func_8014EA4C` (183, ~c6) → `func_801571C4` (198, ~c24) → `func_80176D94` (152, ~c52, drafted) → `func_801770E0` (152, ~c53) → `func_80148094` (213, ~c72, drafted) → `func_801412A8` (198, ~c110, drafted) → `func_801372B0` (207, ~c173). > 2. **THE WHALE — triage EARLY, in parallel:** `func_80144B9C` (**770 ins**, untouched) — a cheap Opus pass (ranking-law triage: param/buffer-based → one-shot ≈ **+1.6% byte-weight free**; global-array-hoister → close-draft + Fable5). Its byte-weight ≈ the next ~8 giants COMBINED — the single biggest lever on the honest byte-weighted % (giants ≈ 35% of remaining byte-weight, Phase 19). Do NOT bury it at the end of the closeness queue. > > **Method per giant:** cheap Opus applying §32/§34/§35 (ranking-law triage) → bank via the §35 recipe if close; if stalled at a genuine global-hoist/regalloc wall → Fable5 (sequential, idiom-banking). ~90 total ≥150-ins stubs exist in ov_SC01_077 but only these ~12 are reach-134 (×134 payoff); the ~78 lower-reach large fns are a separate, lower-value tail. ## R14 corrections carried in (do NOT re-adopt the stale Phase-23 backlog framings) - "split-file-blind glob" is refuted — the real defect is `compile.sh`/`match_one.py` are **-O2 only** (can't match `_o0`). → -O0 compile.sh variant (T3). - "churn-without-blacklist" is refuted — the real churn is **floor-victim idle re-tries** (`grinder.py:120 tried.clear()`). → scorer (T2) + input-changed gating (T5). - `func_80144090` ×1 is a **type-lift** case (`OtBlk` not in `engine_types.h`), NOT a straggler. → `build_engine_types.py` (T6). - `backlog.jsonl` closeness is **stale/regressed** for the wave seeds (true values in `.run/wave/*.c` headers; `func_8014E048` logged `failed` → `wave_targets` skips it). → re-log first (T1). - The "~95/80/31" class counts are aspirational; real canon `SCHEDULE=30/REGALLOC=84/REMAT=3`, steerable near-misses scattered in `OTHER`/`None`. → wave text-scans `where_stuck` (T8). - `gcc-papermario` is gcc **2.8.1**, not 2.7.2; vanilla 2.7.2 at `tools/reference/gcc-2.7.2/` (cite it). `loop.md` on vanilla; sched/regalloc/cse map files still cite 2.8.1 lines. - **No decomp-permuter submodule edit** for the overhaul (scorer rebind + `#pragma _permuter b64literal` pin carrier + `weight_overrides`, all in `tools/`). The pin-scope randomizer pass (only submodule edit) is deferred. ## Progress log *(append one line per task on completion — the crash-recovery trail)* - **✅ T7 §G ×1→×134 GIANT ENDGAME COMPLETE (2026-07-08) — `func_801372B0` (207) banked ×134; BOTH remaining ×1 giants now ×134.** Unique-renamed local `SVEC`/`GLINE` → `Svec_801372B0`/`Gline_801372B0` (a DIFFERENT same-named `SVEC` with u16 fields lives in `_after.c` → a bare-name lift would double-define fleet-wide) + lifted to `engine_types.h`; ov_SC01_077 byte-neutral (`d19c9580`); `dedup_propagate --addr 0x801372B0 --recover` → 134 byte-identical, group `E_func_801372B0`. CLEAN fleet **136/136 (R22)**, dedup **1812→1813/0**, fleet 65.99→**66.02%** (byte-weighted gain larger). **Completeness scan (R14): NO matched giant remains ×1** — the only reach-134 ×1 fns left are SMALL (3 now-propagatable stragglers `0x80174650`/`0x8012A018`/`0x80165CA0` + 17 local-type-blocked) = the **T8 tail** (Drew's focus directive: giants only, no small sweeps; my `overlay_files` fix incidentally unblocked the 3). Distilled → cookbook **§39** (native-DEFINE-path-for-O2-giants · the `overlay_files` post-whale-split gap · `find_site` extern-comment class · unique-rename typedef-lift · R14 handoff-staleness). **The giant endgame is fully banked ×134** (whale + 6 §G cracks + func_801770E0 + func_801372B0). Remaining reach-134 giants = the 2 permanent walls (`func_80178004` biv-init close=7, `func_801412A8` alloc-knot close=29 — INCLUDE_ASM, G4). Commit: (this). - **T7 §G ×134 GIANT ENDGAME (2026-07-08, this session) — `func_801770E0` (152) banked ×134 via the NATIVE DEFINE-macro path; R14: `func_8014E048` was ALREADY ×134 (handoff line-49 stale).** Verified each named ×1 giant against the bytes (R14): `func_8014E048` is a 134-member group + `DEFINE_func_8014E048()` in every overlay (done in T6 §A) — NOT ×1. Only `func_801770E0` + `func_801372B0` actually remained. **Chose the native `dedup_propagate` DEFINE-macro path over the handoff's hand-rolled shared-header** — `func_8014E048` (pins+asm) is ×134 via a DEFINE macro, PROVING that path handles pin/asm -O2 giants (the whale needed a shared header only because it's -O0 → separate object). **Blocker found + fixed (reusable):** `dedup_propagate.overlay_files` scanned `_a`/`_o0` splits but NOT the whale-rollout-created `_o0b`/`_after` — so every post-whale-region fn (func_801770E0 @0x801770E0 lives in `_after.c`) was invisible for BOTH source-def-find and stub-replacement → added `_o0b`/`_after` to the suffix list. Also made func_801770E0's extern block contiguous (a `/* comment */` between externs made `find_site` drop the earlier 5 externs → compiles_standalone fail; byte-neutral relocation). Then `dedup_propagate --addr 0x801770E0 --recover` → **134 overlays byte-identical, 0 stragglers, group E_func_801770E0 registered**. CLEAN fleet (make clean+extract-all-136+check-all) = **136/136 (R22)**, dedup **1811→1812/0**, fleet 65.95→**65.99%** (byte-weighted gain larger — 152-ins giant). **NEXT: `func_801372B0`** (207; blocker = local `SVEC`/`GLINE` typedefs, also used differently in `_after.c` → unique-rename `Svec_801372B0`/`Gline_801372B0` → `engine_types.h`, byte-verify d19c9580, then `--recover`). Commit: (this). - **🔜 NEXT SESSION (2026-07-07, whale done) — the 2-3 ×1-matched giants → ×134 (Drew: "finish the giants").** `func_801372B0` (207) + `func_801770E0` (152) + `func_8014E048` (143, T5b S11 crack) are MATCHED but banked ×1 in ov_SC01_077, STUBBED in the other 133 overlays — blocked from ×134 because `dedup_propagate.compiles_standalone` (tools/dedup_propagate.py:246) REJECTS register-asm-pin / anon-struct / local-typedef bodies (§A). Est. ~+0.4-0.6% byte-weight (already-matched; no new matching). **WHALE-DERIVED LEVER (a promising LEAD — verify, not proven):** the whale propagated ×134 WITHOUT dedup_propagate — via a **shared header** (`src/shared/func_80144B9C.h`) + a **hand-registered** h_exact dedup group (`.run/t7b/register_whale_dedup.py` → E_func_80144B9C, `source=`the header). This pattern **BYPASSES `compiles_standalone` entirely**. The ×1 giants may bank ×134 the same way: extract each matched body → `src/shared/.h`, then in ov_SC01_077 AND each of the 133 overlays replace the `INCLUDE_ASM()` line with `#include "../shared/.h"` **AT THE STUB POSITION** (NOT the file top — the fns are position-locked in the -O2 main subseg, unlike the whale which had its own o0b subseg), and hand-register the group. Sidesteps the pin/asm gate. (Alternative: teach `compiles_standalone` to compile pin/asm bodies WITH the pins.) A `rollout_whale_o0.py`-style tool (but for a mid-file `#include`, no yaml carve since these are -O2) would script it. **Then the giant endgame is fully banked.** Whale commits **commit:0463 (×1) + commit:0464 (×134)** — ready for Drew to push. - **🐋 T7 WHALE ×134 ROLLOUT COMPLETE — clean fleet 136/136 (2026-07-07):** all 134 overlays now carry func_80144B9C as -O0 compiled C (was ×1 in ov_SC01_077) — the single biggest byte-weight lever, banked ×134 (~+1.6% byte-weight). Mechanism (`tools/rollout_whale_o0.py`): per single-file overlay, LINE-split `.c` at the whale (splat emits in vram order → no item-parse hazard), carve the yaml code subseg into before/`_o0b`(-O0)/`_after`, thin `_o0b.c` #includes the shared `src/shared/func_80144B9C.h` (the whale C moved there — DRY, TU-local typedefs, NOT a fragile 200-line DEFINE_ macro). One Makefile `WHALE_O0B_OBJS` wildcard -O0-compiles all `_o0b.o`. Registered dedup group **E_func_80144B9C** (134 members, h_exact 74186b97, source=the header — `group_members` keys on binary+vram, so a header-share validates like a macro-share). **CLEAN fleet check-all 136/136 (R22)**; dedup-check 1810→**1811/0**; FLEET REAL 225816→225949, byte-identical 65.91→**65.95%** function-count (the big gain is byte-weighted). Validated on ov_SC01_000 + spot-checks SC02/SC03/SC07 before the full fleet. Distilled: **cookbook §38** (struct-assign -O0 idiom + the -O0 reach-134 rollout + the memcpy asm-label) + SETUP inventory. **🐋 WHALE DONE.** Commit: (this). - **🐋 T7 WHALE func_80144B9C CRACKED + banked ×1 (-O0), clean fleet 136/136 (2026-07-07):** the 770-ins reach-134 whale — the single biggest byte-weight lever (≈ next ~8 giants combined). **CRACK (cheap Opus, NO Fable5/calls.c — both retired):** the close=2 residual was a STRUCT ASSIGN `D_80078E50 = *ent;` (sizeof(ENT)==0x24), NOT an explicit memcpy() — gcc-2.7.2 -O0 expands a >MOVE_RATIO struct copy via emit_block_move→emit_library_call(memcpy): args go through copy_to_mode_reg (pseudos) then `addu $a0,$v1 ; addu $a1,$v0` = the exact 2 missing moves. **BANK INFRA (byte-neutral, reusable for ×134):** (1) 2nd per-file -O0 split — the whale is a 2nd -O0 region (prologue 21F0A003) in the -O2 "after" segment, carved into its own -O0 object `o0b` (splat.ov_SC01_077.yaml 3-way + Makefile CC1FLAGS=-O0; the file is splat-emitted in vram order → a LINE-based split at the whale preserves all banked C, no item-parsing/DEFINE_ hazard — `.run/t7b/split_whale.py`). (2) `memcpy=0x8005C324` in symbols.resident.txt (overlays+resident ONLY — main defines memcpy via MEMCPY.o, so a shared-symbol add would multiple-def) + `__asm__("memcpy")` on the engine_core.h block-copy macro (keeps the non-builtin C name to avoid gcc's built-in-memcpy codegen, emits the same 0x8005C324 call; benign "conflicting types for built-in memcpy" warning). splat REJECTS two symbols at one addr (tried func_8005C324+memcpy → error) → the asm-label is the fix. ov_SC01_077 == d19c9580; **CLEAN fleet check-all 136/136 (R22)**, dedup 1810/0. **W9 NEXT: script the ×134 -O0 rollout** (per-overlay o0b split via split_whale-style tool + a DEFINE_func_80144B9C() macro w/ TU-local typedefs — no engine_types.h collision; 133 single-file overlays, whale stubbed at file 0x1CA44 in each) → ~+1.6% byte-weight. Commit: (this). - **T7 §G BATCH CLOSE ✅ (2026-07-07, committed; TRUE clean fleet 136/136) — 6/8 reach-134 giants cracked, 4 propagated ×134, fleet 65.75→65.91%:** MATCHED: `func_801571C4` (permuter, after the p16_permute comment-fix), `func_8014EA4C`/`func_801372B0`/`func_801770E0`/`func_80176D94`/`func_80148094` (Fable5, sequential idiom-banking chain). 2 WALLS (stay INCLUDE_ASM, G4): `func_80178004` (biv-init emit-order, close=7), `func_801412A8` (allocation placement-knot, close=29). **Propagated ×134:** 571C4/EA4C/76D94/48094 (134 overlays byte-identical; dedup **1810 groups / 0 failed**; genuinely-clean `make clean`+extract-all-136+check-all = **136/136**). **×1 (×134 follow-up — §A `dedup_propagate.compiles_standalone` gaps):** `func_801372B0` (asm-label-alias bank; blocked by local SVEC/GLINE typedefs — need unique-renamed lift — + register-asm pins), `func_801770E0` (anon-struct'd; blocked by register-asm pins). **NEW TOOLS:** `tools/p16_permute.py` comment-fix (a silent bug that had no-op'd the permuter on EVERY commented draft → immediately cracked 571C4) + `tools/permuter_ils.py` (warm-restart iterated-local-search). **KNOWLEDGE (durable):** cookbook **§37** + `docs/gcc-2.7.2-map/t7g-giant-harvest.md` (sibling-isomorphism law · `/s`-dep-lattice load+store dual · allocno ref-boost · coalescable-copy insn_count bump · RC-6-exemplar downgrade · "RTL dumps NOT stripped" · asm-label-alias/anon-struct banking). **REMAINING:** the WHALE `func_80144B9C` (close=2, DISCOVERED -O0 — needs a 2nd per-file -O0 split + gcc-2.7.2 `calls.c` + Fable5) + the 2 ×1 giants' ×134 (a pin/asm self-containment shim). Commit: (this). - **T7 §G IN PROGRESS — parallel-attack session (2026-07-07, uncommitted; NOT yet clean-verified):** worked the ~9 reach-134 §G giants via 8 parallel Opus draft-agents (draft-only) + directed permuter + Fable5 chain; banking serial in main loop. **R14 re-measure overturned §G's stale closeness** (func_8014EA4C "~c6"→really 128; func_80178004 "close=0"→91; the REAL closest was func_801571C4 @11). **FLYWHEEL FIX:** found+fixed a silent permuter bug — `make_base_c` didn't strip draft header comments → `cpp` "unterminated comment" → decomp-permuter no-op'd `(0s)` on EVERY commented giant draft (`tools/p16_permute.py` `strip_c_comments`). Immediately cracked **func_801571C4 (SCHEDULE, 11→0 in 40s) → banked ×1** (`.run/t7b/matched/`; needed the byte-neutral `extern void`→`u32` caller reconcile at ov_SC01_077.c:4721; propagate ×134 at batch close). Built **`tools/permuter_ils.py`** (warm-restart iterated-local-search; 48094 72→38 where cold plateaus). **7 giants driven count-exact to precise single-class cc1-internal walls → FABLE5 BATCH (Drew authorized full, closest-first sequential + idiom-banking):** EA4C(6,frame-0x60-knife-edge) · 372B0(8,sched1 live-range) · 78004(37,const-hoist⊗regalloc) · 770E0(47,RC-6) · 76D94(52,S3 mutual-excl) · 48094(72,local-vs-global $a0; ILS→38) · 412A8(80,S3; ILS→45). **EA4C Fable5 RUNNING (1st).** 🐋 **WHALE func_80144B9C CLOSE=2 (768/770) — DISCOVERED -O0, not -O2** (prologue `21F0A003`; -O2 reads only 458/770) — a 2nd -O0 region @0x80144B9C stranded in the -O2 segment; needs a **2nd per-file -O0 split** (config) + **gcc-2.7.2 `calls.c`** (not in tools/reference, only 2.8.1) + Fable5 for the memcpy(=func_8005C324) -O0 arg-precompute. All drafts in `.run/t7b/{matched,close}/`; all levers + the -O0 idiom set + banking recipe in **`.run/t7b/LEVERS_HARVEST.md`** (→ cookbook at close). Fleet still 65.75% (571C4 ×1 negligible until ×134). NEXT: bank each Fable5 MATCH ×1 → one `dedup_propagate --auto-from --recover` at close → R22 clean-verify 136/136. **GEN2 RELEASE CANDIDATES (Drew 2026-07-07 → put in PhaseEnd):** (1) upstream an ILS/warm-restart mode to decomp-permuter (it appears to lack one); (2) release our gcc-2.7.2 codegen map §31/§36 + the "shipped cc1 RTL dumps are NOT stripped (`-dr -dj -dc -dl -dg`)" method — high value to any gcc-2.7.x decomp project; (3) the ILS *idea* (not the harness-coupled wrapper). Sequence at the Gen2 public flip. **FOCUS DIRECTIVE (Drew 2026-07-07):** pursue the largest-%-gain giants ONLY — NO small-function backlog sweeps (declined a ~52-candidate sweep); crack ALL giants incl. the WHALE func_80144B9C (the single biggest lever, ≈ next ~8 giants combined in byte-weight), THEN decide what's next. - **T7 Fable5 batch COMPLETE — 3 giants cracked + banked ×134 (2026-07-04, `commit:0460`; clean fleet 136/136):** the 3 residual monsters (close=2/10/15) all → **MATCH** via sequential Fable5 (idiom-banking between): `func_801392FC` (cross-BB combine law + volatile-frame-parity), `func_8013A530` (the RC-6 "reload knot" was the pins → the **$0-add opaque copy** `iVar7=fc+zr` + 3 zero-byte levers; regalloc.md RC-12/13), `func_8013AF20` (the "impossible" const-hoist order was libgpu addPrim's 24-bit **bitfield store** → `store_fixed_bit_field` emits 0x00ffffff first; P_TAG lifted to engine_types.h byte-neutral). Banked via the §35 recipe; cookbook **§36** + loop.md + regalloc.md fed; gcc-2.7.2 reference tree extended (expmed.c/mips.md/…). **SESSION TOTAL: 7 giants ×134** (func_80129CF8 R14-free + func_8012D098/EC04 Opus-solo + func_80138ED0/801392FC/8013A530/8013AF20 Opus→Fable5); **fleet 65.48→65.75%**, 136/136, 0 NON_MATCHING. **NEXT SESSION: the ~9 remaining reach-134 giants per §G** (closest-first + the 770-ins whale func_80144B9C fast-tracked). Bank this session's §36 idioms are already in §31 → next-session Opus starts richer. - **T7 (resumed, Drew's choice) — sibling-giant harvest via parallel Opus-Max agents (2026-07-03, IN PROGRESS):** launched 5 Opus agents (one per remaining region-a giant), each applying §32/§34, escalating to Fable5 only on stall. **KEY FINDING (answers the flywheel Q):** the "3 hardest 8-$s-reg giants" were MIS-RANKED — the 8-$s pressure is param/local/buffer-derived, NOT global-array hoists (only global-array-hoisting giants like func_80129CF8 are genuinely hard), so they **one-shot with Opus alone, no Fable5**. Banked ×134 so far: **func_8012D098** (189, one-shot Opus) + **func_8012EC04** (178, one-shot Opus = sibling func_8012EA90 + GTE tail). Fleet 65.56→**65.64%** (uncommitted, clean-verify running). 3 still iterating: func_8013AF20 (~60), func_8013A530 (~45), func_801392FC. **BANKING RECIPE (established; per-giant integration is mechanical, §30a):** matched draft → `fix_arity_callers --apply --any-proto` (no-proto the engine_core.h/overlay caller extern that conflicts with the matched def-sig — the DEF-side wall) → `sig_unify` (callee no-proto→full-proto) → **strip draft-local typedefs already in engine_types.h + anonymize named local typedefs** (else `conflicting types` in the shared TU) → `harvest_verify --chunk 1` ×1 → `dedup_propagate --recover` ×134. **NOTE: skip `cast_call_sites`** — it mis-casts a no-proto `void f()` to `void(*)(void)` (T6/cookbook fix candidate). **Two-pass verdict (Drew's Q):** Opus-first is right (structure cheap + flywheel; Fable5 only for genuine global-hoist/regalloc walls); parallel Opus is fine, sequence any Fable5 escalations with idiom-banking. **HARVEST COMPLETE (5 giants processed):** **4 banked ×134** (func_80129CF8, func_80138ED0 earlier; **func_8012D098 + func_8012EC04 this batch**, `commit:0457`, clean 136/136, fleet **65.64%**). **3 deferred to a Fable5 batch** — all Opus-driven to a single-class compiler-internal wall: `func_801392FC` **close=2** (count-load pipelining / combine-fold-vs-sched2), `func_8013A530` **close=10** (RC-6 reload-pressure, register-only, contained), `func_8013AF20` **close=15** (loop-invariant constant-hoist order). Residuals in `docs/backlog.md` + cookbook **§35** + `.run/t7/.c` headers. **RANKING LAW (retires "8-$s=hardest"):** difficulty = global-array-hoisting, NOT $s count (param/buffer giants one-shot Opus even at all-8-$s; only global-hoisters need Fable5). **BANKING RECIPE** (§35): fix_arity_callers --any-proto → sig_unify → strip engine_types.h-dup + anonymize local typedefs → harvest_verify → dedup_propagate; NOT cast_call_sites (mis-casts no-proto). **NEXT DECISION (Drew):** Fable5-batch the 3 residuals now (~1.3M tok, ~4.5h, each ×134) vs a fresh focused session vs permuter-first on the contained func_8013A530. - **T7b/T5 — 2nd giant `func_80138ED0` MATCHED + banked ×134; the real un-reconciled-sibling proof + major new §31 idioms (2026-07-03):** Opus applying §32 → **close=21** (159/159 ins; semantics/control-flow/constants exact; found the transferable **giv-init fence** lever) → stalled on pure regalloc/sched. **Fable5Max reading the vanilla gcc-2.7.2 source → MATCH** (every class C-reachable, no permuter). Headline finds (→ cookbook §34, byte-verified + gdb-on-cc1): **gcc-2.7.2's 3-qty local-alloc SORT BUG** (`local-alloc.c:1441` — ≤3 qtys allocate in creation not density order; fixed via a zero-instruction **decoy qty**) + the **zero-byte asm allocation toolkit** (input-only / multi-input / def+use dummies = ref-count / lifetime / sort-path dials that emit nothing, byte-gate-certified). **Banked via the standard pipeline** (validates it on a real giant): `cast_call_sites` reconciled `func_8013914C` `(u8*,u16*)`→canonical `(s32,s32)`+call-site cast; **`reconcile_decls` a NO-OP** (the 2 data bases are giant-local → no fleet conflict — confirms the tool's no-op correctness / no false-positive); `harvest_verify` ×1 (`d19c9580`) → `dedup_propagate --recover` **×134** (134 byte-identical; pins/asm body propagates fine; `func_800599B8`'s lone `(s32,s32)` decl is in `ov_SC01_077.c`, a separate TU from the `_a.c` bank → no per-member conflict). gcc-2.7.2 reference tree **completed** (18 .c). Distilled: cookbook **§34** + SETUP §5.6. **Clean fleet verify running.** T5 satisfied: tool proven on 2 real giants (func_80129CF8 reconcile-path byte-proof + func_80138ED0 no-op + full-pipeline + 2nd giant ×134). **NEXT: T6 finalize** (fold §34 into the §31 map files) **+ PhaseEnd.** Commit: (pending verify). - **T7b/T2+T3 — `tools/reconcile_decls.py` built + BYTE-PROVEN (2026-07-03, `commit:0453` tool + docs commit):** the DATA-symbol analog of `cast_call_sites` (§20). **Oracle** (T2): fleet-majority canonical-type picker — `engine_core.h`-macro type authoritative, else plurality across all overlays+resident (deterministic); reuses `gen_harvest_targets.collect_data_decls`; **8/8 correct** on func_80129CF8's symbols (`--print-canon`). **Transform** (T3): byte-neutral access-cast taxonomy — array `(Ed*)D_x`, struct-base `(Ed*)&D_x`, scalar-signedness `*(Td*)&D_x`, ptr-in-scalar `(*(P**)&D_x)`; ONE single-pass `re.sub` per symbol (a first draft double-wrapped the ptr-store — fixed). Wired into `gate_stage` after `cast_call_sites` (idempotent / no-op without a data conflict → can't regress the wave; byte-gate stays sole arbiter). **BYTE-PROOF (no Fable5):** full *loose* func_80129CF8 (intended decls, un-cast) → `reconcile_decls` (5 reconciled) → swapped into the `DEFINE_` macro → `make build BINARY=ov_SC01_077` = **`d19c9580` BYTE-IDENTICAL**; idempotent (0) on the canonical committed draft. **T4 resolved NO-OP** (T1: zero per-member conflicts — the fleet is decl-consistent). Distilled (R30): cookbook **§33** + §32 R14-correction, SETUP inventory row, design-doc **✅ RESOLVED** banner. **NEXT (T5, on Drew's Fable5 go):** match a sibling giant — `func_80138ED0` (closest, 2 data bases D_80127548/D_80127C0C) — with Fable5Max → `reconcile_decls` its raw draft → bank ×1 → `dedup_propagate --recover` ×134 (the real end-to-end proof + a 2nd giant ×134). Then T6 finalize + PhaseEnd. - **T7b/T1 — R14: the "×134 wall" was a MISDIAGNOSIS; `func_80129CF8` banks ×134 FREE (2026-07-03, this commit):** Diagnosed the prior "×134 BLOCKED / all overlays excluded" claim by RUNNING it (R14/P9). Byte-verified: (a) the giant's ×1 bank extern block is already fleet-canonical (every symbol matches the overlay-majority; the lone `D_801151D4` `s32`-vs-`ptr` conflict is in `resident.c`, NOT an overlay member); (b) `dedup_propagate --addr 0x80129CF8 --check-only` → plan-eligible, **134 members**, passes `compiles_standalone`; (c) a representative member (`ov_SC01_000`) declares NONE of the giant's symbols locally (the macro's externs are the sole declarers); (d) controlled `--no-gate` instantiate + `make build BINARY=ov_SC01_000` = **BYTE-IDENTICAL** `9052dc0e`. Then full `dedup_propagate --addr 0x80129CF8 --recover` → **134 overlays byte-identical, group registered** (exit 0); clean `make clean && extract-all && check-all` → **136/136, 0 failed**, fleet **64.90→65.52%**, dedup **1799→1800/0**. ⇒ the "loose-typing wall" was a **stale-asm / incremental-tree artifact** (the exact T5c/T6-§A trap — a prior run before the reconcile committed, or a dirty asm/). **Consequence:** the reconcile tool is NOT needed to unlock func_80129CF8 (or any *already-reconciled* giant); its real value = **mechanize the manual decl-reconcile** for *freshly-matched* giant drafts (m2c `M2C_UNK` / Fable5 output with loose callee/data types) → canonical decl + byte-neutral access casts → bankable ×1 + propagatable ×134, hands-free. Beneficiaries: the **6 sibling giants** (all still stubs) + the wave tail. **Drew's choice B:** finish the tool + match a sibling giant as the real T5 validation target (Fable5Max on request). Plan `plan-…mossy-dawn.md` (T1–T6); next = T2 oracle + T3 `reconcile_decls.py`. Commit: (this). - **T7 — giant `func_80129CF8` CRACKED (Fable5) + §32 idiom + banked ×1; ×134 WALL found → Drew chose to build the canonical-decl tool (2026-07-03, `commit:0450`):** Fable5Max cracked the 191-ins region-a camera giant (match_one MATCH) — struct-base hoisting via **source-local pointers** (gcc-2.7.2 has no cross-bb CSE → a callee-saved base can only come from a local, **NO pins**), branch-polarity-off-the-opcode, S12 reused-temp fence, `expand_block_move` struct-assignment, dead-local-aggregate frame → **cookbook §32** (transferable to the 6 sibling giants — `.run/t7/GIANTS_SURVEY.md`). Banked **×1** in `ov_SC01_077_a.c` (`d19c9580`, clean fleet 136/136) after reconciling its loose-typed decls (`u8[]`/`s32[]`/`struct BigCopy`/`s8`-vs-`u8`; `func_80012F74` `s16`-vs-`s32`) → canonical + **byte-neutral access casts**; `RView` (GsRVIEW2-shaped) → `engine_types.h`. **FINDING (byte-proven):** ×134 propagation is **BLOCKED by the fleet-wide loose-typing wall** — the giant's shared callees/data are declared incompatibly across overlays, so the macro's externs conflict per-overlay, and `dedup_propagate --recover` only fixes the propagated fn's CALLER extern (not its callee/data). Loose-typed giants bank ×1, NOT ×134 (the flagship `func_80132784` propagated only because its symbols were fleet-compatible). **DREW'S DECISION (A — invest over immediate ROI):** build the fleet-wide **canonical-decl reconcile tool** = the ×134 giant unlock. **Spec + conflict taxonomy + the proven byte-neutral cast patterns → `docs/canonical-decl-reconcile-design.md`.** Build it **Opus, plan-mode, Max — NOT Fable5** (it's tooling; the byte-gate arbitrates; reserve Fable5 for stalled giant MATCHES). Fable5's giant-crack is a *match* tier; this is a *plumbing* tier. - **T6 §A — ×134 propagation-recovery COMPLETE (2026-07-03, `commit:0447`+`commit:0448`):** 🎯 **15 fns propagated ×134** this session (fleet 64.90→**65.48%**; two clean-fleet-verified commits). Fixed FOUR blockers, all whole-binary-byte-gate-validated: **(1) find_site indented defs** — the def regex `^[A-Za-z_]` was column-0-only, silently dropping every recover_integration-banked (indented) def from propagation; unit-tested (indented DEFS match, indented CALL-exprs don't). **(2) find_site trailing-comment externs** — the extern-collection `^\s*extern\b.*;\s*$` stopped at `extern u8 D_x[]; /* comment */`, dropping the earlier externs → THIS (not "pin/asm", R14) was func_8014E048's real self-containment blocker. **(3) dedup_propagate --recover** — on a straggler byte-gate fail: Part B no-protos that overlay's conflicting caller extern + re-gates (byte-neutral, = fix_arity_callers --any-proto); Part A excludes only that overlay (×N-1) vs the historical all-or-nothing drop; wired into gate_stage. **(4) build_engine_types comment-awareness** (`blank_comments`) — its OWN generated "…typedef lift" header comment was captured as a bogus `typedef vec`, self-colliding and blocking every --strip; NOTE full --strip still conflicts with the `_a/_o0` splits, so func_8014F74C's PosT/MoveT were lifted TARGETED (byte-neutral). **Banked:** the 13 leaf-MATCHes + func_8014E048 (T5b S11 crack) + func_80157580. **R14/R22 lesson (cost me a detour):** a stale-`asm/` tree (13 missing `.s`) confounded the FIRST --recover test into a false "byte-diverge everywhere incl. the source overlay" — a re-extract fixed it; the incremental per-overlay byte-gate is only valid on a freshly-extracted tree, so clean-verify (make clean && extract-all && check-all) EVERY batch. **Deferred tail (17 not-self-contained):** the 3 pre-existing --auto-from stragglers (0x80174650/8012A018/80165CA0 — pin/asm + uncaptured local `#define SHB`; moving SHB to a shared header would unblock func_80165CA0) + 14 local-type cases → T8 sweep. **T9 cookbook fodder:** the integration-recovery family (§A) + the stale-asm R22 corollary + the find_site extern-comment/indent classes. - **T6 (tool built + gate-recovery proven; ×134 propagation-recovery deferred) (2026-07-03):** built **`tools/recover_integration.py`** (batch integration-recovery: gather leaf-MATCH candidates → no-proto their conflicting caller decls → gate_stage → 2-pass snapshot/restore so non-banks aren't corrupted) + **extended `tools/fix_arity_callers.py`** with `--binary` (scan the overlay's OWN inline callers, not just engine_core.h — the gap that left the "declaration/TU plumbing" class unrecovered). **Banked 13 leaf-MATCH fns** (func_8014F74C/801542A4/8015BE94/8015F380/80160F00/801653B8/80166244/8016E778/801732C4/8017331C/80173374/80174554/801745AC), **clean-verified together** (ov_SC01_077 `d19c9580`). **R14 lesson (clean-verify caught it):** the first batch's `fix_arity_callers --revert` was LOSSY for `--any-proto` (`()`→`(void)`, not back to the original args) → corrupted non-banks ("too many arguments"); fixed with the 2-pass snapshot. **×134 propagation of the 13 is BLOCKED (3 diagnosed sub-blockers → remaining T6 work):** (1) `dedup_propagate` `find_site` misses **indented** inline defs (7/13 "not inline-def" — Phase-15 class); (2) 1/13 uses overlay-local types (type-lift); (3) the 5 plannable all drop on the **ov_SC01_000 straggler** (conflicting caller externs, same class as the flagship's ov_SC02_005 — needs the auto-reconcile Part B). So the 13 are banked **×1** pending those fixes. Flagship `func_80132784` (`commit:0443`) remains the one ×134 T6 win. - **T6 (partial) ✓ (2026-07-03):** 🎯 **FLAGSHIP `func_80132784` PROPAGATED ×134** (`commit:0443`) — the 400-ins S11 giant (cracked T4, banked ×1) now byte-identical in ALL 134 overlays, **+1.6% byte-weighted** (the single biggest lever; function-count fleet 64.86→64.90%). **The T6 recovery pattern, proven end-to-end:** the T4-deferred ×1 cap was one straggler overlay (ov_SC02_005) declaring a CONFLICTING caller extern `void func_80132784(s32,s32,s32)` vs the def `(s32,s32,u32)` → `conflicting types` → dedup_propagate's all-or-nothing single-`--addr` plan dropped the whole fn. Fix: reconcile the straggler's caller extern to the def's canonical sig (s32→u32, byte-neutral — the call site casts anyway), then propagate → 134 overlays rebuilt byte-identical, group `E_func_80132784` registered, dedup-check 1784/0. **Clean R22 fleet check-all 136/136.** **REMAINING T6 (the tool):** automate this — detect a straggler's conflicting caller decl → reconcile to the def's canonical sig → re-gate → propagate full (vs. all-or-nothing drop); + the other ×1 classes (func_8014E048 pin/asm self-containment — a DIFFERENT blocker: dedup_propagate's `compiles_standalone` rejects pin/asm bodies; func_80144090 OtBlk type-lift; func_8014F4C0/func_80155800 TU-context leaf-MATCHes in `.run/wave/`). - **T5c ✓ (2026-07-03):** 🟢 **TRUE clean fleet 136/136 RESTORED** (first genuinely-clean `make clean`+full-re-extract+check-all green since Phase 21). Fixed the pre-existing Phase-21 (`commit:0292`) rename-propagation breakage: renamed all **62** stale `INCLUDE_ASM(func_)` → curated names across 12 main/library `src/*.c` (800c.c/800c3.c×22/apicard1·2·4/boot.c/libcd1×8/libetc×6/libgpu×3/sgap.c/snd1×7/snd2.c) to match splat's canonical output (proven: splat's fresh stub-regen uses the curated names). **main clean-builds `143dbb89` ✓; fleet 136/136 ✓** (all overlays byte-identical, resident `8e17e02f`). Built **`tools/lint_symbol_refs.py`** (comment/string-aware, func_+D_) — flags any `func_/D_` ref whose addr was renamed (the R22-masked class); caught the T5b macro-call + this INCLUDE_ASM set; now 0 stale. SETUP inventory + CURRENT_PHASE finding updated. Commit: (checkpoint). - **T5b ✓ (2026-07-03):** 🎯 **S11 CRACKED — the class verdict was map-incompleteness, not intrinsic codegen** (Fable5 main-loop spike, Drew switched the session to Fable5 Max). `func_8014E048` (143 ins, reach-134; "S11 LUID⊗alloc intrinsic / not source-steerable" since the map wave; **28-off even after T5's directed permuter**) → **MATCH (143/143) + whole-binary BANKED** (`harvest_verify` 1/0, ov_SC01_077 `d19c9580…`). Derived by reading gcc-2.7.2 source + `-dl -dg -dS` RTL dumps (12 experiments, `.run/gccmap/exp/e1a..e1k.c`): **S12 reused-s32-temp fence** (output/anti deps forbid load batching; **u16 temps DON'T work** — unpromoted HI vars spawn per-use zext temps that combine folds away), **S13 head-skip escape** (body-local param copies keep hard arg regs live into the temp windows → conflict-steer the scratch contest; zero-byte volatile-asm dead-read as a wedge-slot fence; multi-input dead-read to rebalance K2 densities), **cse-opaque asm-copy** (`addu %0,%1,$zero`) for must-materialize pointer copies, **RC-4b pinned store-temp**, **RC-10 preference-cascade mechanics** (set_preference one-level expression unwrap; expand_preferences dying-into-set merge; find_reg pass-0 used-so-far/someone-prefers + pref override). Integration needed 2 hand-reconciles (both T6 classes): engine_core.h:17569 caller-decl `s16*`→`u16*` (ptr param type codegen-neutral) + canonical data decls with `*(u16*)` access casts (D_801152A8 `u8[]` / D_801152AC `s16`). **×134 lift blocked by dedup_propagate self-containment (pins/asm) → T6 target** (joins func_80132784). Distilled (R30): sched.md **§6/S12/S13** + regalloc.md **§F/RC-10** + cookbook §31 triage-table **S11 downgrade**. Backlog re-logged (capped). R22 clean fleet check-all running at close. Commit: (checkpoint). - **T5 ✓ (2026-07-03):** **§31-directed permuter mutation + grinder input-changed gating — built, validated, distilled.** NEW `tools/permuter_weights.py`: `classify(klass,where)` → `regalloc|schedule|cse|None` + `render_settings_toml` emitting the `[weight_overrides]` table decomp-permuter merges over the gcc defaults (`main.py:336` / `helpers.py:merge` — per-key REPLACE; **no submodule edit**, R3/R20). Biases pass-selection toward each class's §31 levers (`perm_reorder_decls` RC-1/3 · `perm_reorder_stmts` RC-2/S1 · `perm_temp_for_expr` S2 · `perm_commutative` cse) and pushes the value/type noise to ~0.1. Wired into `p16_permute.setup(…, klass=, where=)` (+`--klass`, backlog auto-lookup) and `grinder.py` (auto-threads `klass`/`where_stuck`; `klass=None` → gcc defaults = the pre-T5 undirected search, a safe superset). **Grinder fix (R14):** replaced the blind `tried.clear()` idle churn with **input-changed gating** (`draft_sig`=(best_draft mtime, closeness) — re-open a fn only when the worker improved it; the permuter is deterministic given base.c+target.o). **VALIDATED:** the regalloc profile drove `func_8014E048` base masked-36 → **29** (match_one `-drz` **35→28**) where the undirected search stalled — real directed progress; re-logged (closeness 28, improved draft promoted). The 4 flagship count-exact seeds are the project's WORST-CASE intrinsic S11/RC-6 walls ("C-space discontinuous" §31 RC-6) — directed mutation improves but doesn't gate them → T5b/backlog fuel (§31 "two probes, don't grind"). Distilled: cookbook **§3b** + SETUP inventory (R16/R30). **No build-input changed → 136/136 fleet invariant untouched (tools/docs only).** Commit: (checkpoint). - **T4 ✓ (2026-07-02):** 🎯 **FLAGSHIP BANKED** — `func_80132784` (400 ins, "HARD-DEFER/irreducible" for 22 phases) matched whole-binary + committed (`commit:0438`); `make check BINARY=ov_SC01_077` BYTE-IDENTICAL, dedup-check 1783/0. The permuter overhaul (T2+T3) is validated end-to-end by a real bank. **Banked ×1** — the ×134 propagation is capped by per-overlay declaration plumbing (`ov_SC02_005` cross-overlay straggler + an `extern`/type mismatch), NOT codegen → **T6 target** (the +1.6% byte-weight lands when T6's integration-recovery reconciles it). Hand-fix that unblocked the ×1: dropped the draft's redundant `Blk16` typedef (already in engine_types.h:442) — T6 automates this. **Count-exact seeds** (func_8014E048 35 / func_80176D94 52 / func_80148094 72 / func_801412A8 110): permuter setup works (parse/compile/search clean, 0 internal failures), but random mutation didn't close them (func_80148094 only 77→74 in T2) — they're intrinsic residuals (RC-6/S11) → **T5 directed mutation + T5b Fable5**. Fleet 64.86% (×1 negligible). Commit: (checkpoint). - **T3 ✓ (2026-07-02):** permuter setup fixes (all in `tools/`, no submodule edit): `p16_permute.hide_asm` — a b64-pragma carrier for register pins AND GTE `__asm__` blocks (pycparser parses the pragma; decomp-permuter's own `process_pragmas` decodes it back so cc1 sees the real asm); custom-typedef/`#define` preservation (drop only `#include`); `f32` typedef gap fixed; `compile_o0.sh` `-O0` variant auto-selected for `_o0` targets; `run_masked.py` pin-var fallback (`expr_type`→`int` on an unknown/hidden-pin id → 0 "internal permuter failures", was >0). ROOT CAUSE of the GTE fail: `compile.sh` now prepends `.include "macro.inc"` so `mvmva` assembles (the real build gets it via `include_asm.h`, which base.c omits + `-DPERMUTER` disables) — byte-neutral for non-GTE (count-exact scores unchanged). ALL 5 seeds parse+compile (base 4/110/36/52/77). 🎯 **The flagship func_80132784 (4/400) CLOSED** to a masked-0 that `match_one` independently confirms **MATCH (400 ins)** — winner preserved `.run/wave/func_80132784.win.c` for the T4 whole-binary gate → ×134 (≈ +1.6% byte-weight). No build-input changed. Commit: (checkpoint). - **T2 ✓ (2026-07-02):** built the floor-free relocation-masked scorer, ENTIRELY in the `tools/` layer (no decomp-permuter submodule edit): `tools/masked_diff.py` (shared `objdump -drz` oracle + masking), refactored `tools/match_one.py` to use it (`-dr`→`-drz`), `tools/masked_scorer.py` (`MaskedScorer` drop-in), `tools/permuter/run_masked.py` (rebinds `src.main.Scorer`), wired `p16_permute.run_permuter`. VALIDATED: `masked_self=0`; `masked_cand≈match_one` (77~72/36~35/52=52); **STOCK floor 1750–2100 vs masked 36–77** (the wander cause, removed); live permuter base score = masked 77 (not stock 1930), descends to 74. `-drz` also fixed match_one's GTE under-count (regression-clean on count-exact seeds; func_80132784 now true 400 ins / 4-off). match_one output format unchanged → gate_stage/grinder compatible. No build-input changed. Commit: (checkpoint). T3 next handles the 2 compile FAILs surfaced (func_80132784 GTE `mvmva`/common.h; func_801412A8 custom-typedef drop). - **T1 ✓ (2026-07-02):** re-logged 7 map-wave seeds with BYTE-VERIFIED closeness (dropped 19 stale/unreproducible records from `.run/backlog.jsonl`, `.bak` kept; best_draft → `.run/backlog_drafts/`). Ground truth (match_one `-dr`): func_8014E048=**35** (was mis-logged `failed`), func_80176D94=**52**, func_80148094=**72** (best draft = `vG2.c`, NOT the named file), func_801412A8=**110**; T6 leaf-MATCHes func_8014F4C0/func_80155800=**0**. func_80144090 excluded (banked ×1, not a stub → T6 `OtBlk` type-lift). Fixed gate_stage sig_unify/`--src-file` doc-drift. `wave_targets --class REGALLOC` + grinder now surface all 4 count-exact permuter seeds with true closeness; func_80132784 correctly kept out of blind selection. No build-input changed → 136/136 invariant untouched. Commit: (checkpoint). --- # 🔜 CONTINUATION FOR THE FRESH SESSION (2026-07-03 checkpoint) **State (updated 2026-07-03):** all work committed (`…`→`commit:0448`); tree clean (only `db.*.gbf` R23 noise). Fleet 136/136 byte-identical from a genuinely-clean tree, **65.48%** count / ~31.7% byte-weighted, 1799 dedup groups. **§A propagation-recovery is COMPLETE** (15 fns ×134 — see the progress-log T6 §A entry; §A below is kept as the resolved-blocker record). **RESUME AT T7** — region-a giants *(xHigh; Drew: PING to switch effort before starting)*, OR the T8 tail-sweep *(breadth → prompt for ultracode, R26)*. Effort stays **Opus Max** until the T7/T8 toggle. ## §A — T6 propagation-recovery ✅ RESOLVED (2026-07-03, `commit:0447`+`commit:0448`) > DONE: all 3 blockers fixed + a 4th (trailing-comment externs). 15 fns propagated ×134 (the 13 + func_8014E048 + func_80157580); clean fleet 136/136; fleet 65.48%. The blocker-by-blocker plan below is kept as the record of how it was done. Remaining tail (17 not-self-contained) deferred to T8. **Goal (achieved):** take the leaf-MATCH-but-×1 banks to ×134. The **tool** (`recover_integration.py`) already banks the "declaration/TU plumbing" class ×1; what's missing is getting those ×1 banks (and the flagship-class ×1s) propagated ×134. **Reproduce the 13 gate-recovered ×1 banks (clean-verified this session):** ``` .venv/bin/python tools/recover_integration.py --funcs func_8014F74C,func_801542A4,func_8015BE94,func_8015F380,func_80160F00,func_801653B8,func_80166244,func_8016E778,func_801732C4,func_8017331C,func_80173374,func_80174554,func_801745AC --no-propagate # -> banks all 13 ×1 in ov_SC01_077; CLEAN-verify: make clean && make extract BINARY=ov_SC01_077 && make build BINARY=ov_SC01_077 == d19c9580 ``` (Reverted at checkpoint — they re-bank via the tool. Better to fix propagation FIRST, then bank+propagate so they land ×134 directly.) **The 3 propagation blockers (each a concrete fix; the whole-binary byte-gate is the arbiter throughout):** 1. **`dedup_propagate.find_site` misses INDENTED inline defs** (blocked 7/13 → "not inline-def"). The banked defs are indented (` void func_801542A4(s32 *a0, s32 a1) {` at ov_SC01_077.c:4601). `find_site` (tools/dedup_propagate.py ~line 440, `apply_plan`) + its `INLINE_DEF_RE` detect column-0 defs only. **Fix:** allow leading whitespace in the inline-def detection (same Phase-15 `find_site` brace-placement class — a green byte-gate masks under-propagation; verify via `make report` fleet %, not just the gate). Cross-check with `tools/gen_harvest_targets.py:INLINE_DEF_RE` (Phase-19 fixed a similar column-0 issue there). 2. **Overlay-local type lift** (blocked 1/13 → "not self-contained (local types)"). One fn's body uses a type not in `engine_types.h`. **Fix:** `tools/build_engine_types.py --strip` (§28b type-lift), then re-propagate. 3. **Straggler caller-extern reconcile** (blocked the 5 plannable + the flagship + others). A member overlay (e.g. `ov_SC01_000`) declares a CONFLICTING caller extern for the fn vs the def sig → `conflicting types` → `dedup_propagate`'s all-or-nothing drops it. **THE PROVEN FIX (flagship func_80132784 / ov_SC02_005, byte-neutral):** rewrite the straggler overlay's `extern func_X(...)` to the def's canonical sig (width-compatible: `s32↔u32`, `s16↔u16`, ptr types — the call site casts or passes wide args, so codegen is identical), then re-propagate → ×134. Example done by hand: `sed -i 's/extern void func_80132784(s32 a0, s32 a1, s32 a2);/…u32 a2);/' src/ov_SC02_005/ov_SC02_005.c`. **AUTOMATE as `dedup_propagate --recover`:** on a straggler drop, (Part B) reconcile its conflicting caller extern to the def sig → re-gate → keep in members (×N); (Part A fallback) if irreconcilable, EXCLUDE the straggler from the fn's members and propagate to the clean N-1 (×N-1, keep straggler ×1) rather than the current "single-fn plan → all-candidates-dropped → error" (dedup_propagate.py lines 478-511). **NEVER change the matched def; only the caller's extern.** **Also `func_8014E048` ×134 (T5b bank, DIFFERENT blocker, lower priority — 1 fn):** `dedup_propagate.compiles_standalone` (tools/dedup_propagate.py:246) REJECTS pin/asm bodies (`register __asm__`/asm-carrier) → the fn never enters the plan. Needs a self-containment shim (compile with the pins) or an alternate propagation path for pin/asm defs. `func_8014E048` is banked ×1 in ov_SC01_077.c (S12/S13 levers, §31 sched.md §6). **T6 done-criterion:** the 13 (+ flagship-class ×1s) propagate ×134, clean fleet 136/136, dedup-check 0-failed, fleet-% up. Then `dedup_propagate --recover` (or the recover_integration `--auto` path with propagation) can sweep the broader capped tail. ## §B — Tools + knowledge built this session (for T8/T9 reuse) - **`tools/permuter_weights.py`** (T5): §31-directed decomp-permuter weights (`classify(klass,where)→regalloc|schedule|cse` → settings.toml `[weight_overrides]`). Auto-threaded by `p16_permute.setup`/`grinder`. No submodule edit. - **`tools/lint_symbol_refs.py`** (T5c): flags stale `func_/D_` refs after a symbols rename (comment/string-aware). **Run after ANY symbols.us.txt rename**; T9 candidate to wire into `make report`. - **`tools/recover_integration.py`** (T6): batch integration-recovery (`--auto`/`--funcs`/`--from-file`; 2-pass snapshot/restore). Banks the caller-decl-conflict class. - **`tools/fix_arity_callers.py`** — EXTENDED with `--binary` (scans the overlay's own inline callers, not just engine_core.h — the T6 gap) + `--any-proto`. NOTE: `--revert` is LOSSY for `--any-proto` (→ use snapshot/restore, as recover_integration now does). - **§31 map extension (T5b, byte-proven):** `docs/gcc-2.7.2-map/sched.md §6` (S12 reused-s32-temp fence, S13 head-skip escape + case-study ledger `.run/gccmap/exp/e1a..e1k.c`), `regalloc.md §F` (RC-10 preference cascade + RC-6/S11 verdict DOWNGRADE), cookbook §31 triage table updated. **S11 is now steerable** — audit pins + try S12/S13 before any "S11 intrinsic" verdict. - **§31-directed permuter (T5):** `tools/p16_permute.py --funcs --from-drafts .run/backlog_drafts --secs N --j 14` (auto-directed by backlog class). The 4 flagship count-exact seeds (func_8014E048 28 / func_80176D94 52 / func_80148094 72 / func_801412A8 110) are RC-6/S11 walls — permuter improves but doesn't gate; T5b cracked func_8014E048 by hand instead. ## §C — T7: unblock the 8 compile-blocked region-a giants (xHigh; PING Drew first) The 8 (all reach-134, "won't compile standalone (loose-typing / missing decl)"): **`func_80129CF8`(191) `func_8012D098`(189) `func_8012EC04`(178) `func_8013339C`(160) `func_80138ED0`(159) `func_801392FC`(182) `func_8013A530`(204) `func_8013AF20`(185)**. Per the Phase-23 finding they are **mechanically** unblocked (ghidra-type aliases + data externs — NOT struct-walled). A cheap pass (add the missing type aliases/data externs so they compile standalone) makes them draftable → then §31 + Opus + the T6 recovery + permuter. Their Ghidra-C is in `.run/ghidra_c/` (or regen via `DecompileFunctions.java`, R23/R29 `/mcp`). ## §D — T8: scale the §31 wave (breadth → prompt for /effort toggle, R27) With the permuter (T5), integration-recovery (T6), and the §31 map (incl. S12/S13/RC-10), run §31-powered Opus-agent waves over the near-miss backlog. Real canon class counts: `SCHEDULE≈30 / REGALLOC≈84 / REMAT≈3`, steerable near-misses scattered in `OTHER`/`None` (text-scan `where_stuck`). Each match ×134. Batch ~8, triage-first (bail confirmed-intrinsic to permuter). **The ~26 remaining capped candidates** (leaf-MATCH-but-gate-rejected beyond the 13 T6-recovered) are `recover_integration --auto` fodder — the harder multi-arity-caller loose-typing walls need per-fn diagnosis. Breadth-shaped → prompt Drew for `/effort ultracode` (R26/R27). ## §E — T9: distill + PhaseEnd (Tier-1, Max) Distill into the cookbook: the **T6 integration-recovery** (caller-decl no-proto reconcile + the straggler-reconcile + the 2-pass snapshot) + the **incremental-masking lesson** (R22/R14 caught 2 traps this session: the Phase-21 fleet bug AND the tool's lossy-revert — clean-verify EVERY batch) + `lint_symbol_refs.py` + the **Phase-21 rename-propagation post-mortem** (§Blockers). Verify every checkbox (P7), clean fleet 136/136, write `PhaseEnd_Phase24.md`, archive this file → `phase-ends/logs/Phase24.md` (R19). ## §F — discipline reminders (do NOT regress) - **R22/R14 — clean-verify EVERY batch before committing** (`make clean && extract-all && check-all` → 136/136). Incremental masks (proven twice this session). The `harvest_verify`/`dedup_propagate` per-binary gate is incremental — a full clean fleet check-all is the real proof. - **Straggler/caller reconcile is byte-neutral ONLY on the caller's extern** (width-compatible types; the call site casts/passes-wide). NEVER touch the matched def. - **R23:** never stage `db.*.gbf`. **T6 commits:** never stage `symbols.us.txt` (unrelated). - **Commit hygiene:** the tool commits keep source/tool/docs; `git checkout src/ docs/` to revert scratch banks (keeps `tools/`+`phase-ends/`). --- ## T6 targets (the specific ×1 banks awaiting §A propagation-recovery) - **`func_80132784`** (flagship, 400 ins) — **ALREADY ×134** (`commit:0443`, via the ov_SC02_005 straggler reconcile — the template for §A.3). - **The 13 T6 gate-recovered fns** (§A) — banked ×1, awaiting the 3-blocker fix. - **`func_8014E048`** (T5b, S11 crack) — ×1, pin/asm self-containment blocker (§A). - Carried from Phase-23 backlog: `func_8014F4C0` (fwd-decl reconcile + Vec4u lift), `func_80155800` (TU-context), `func_80144090` (OtBlk type-lift). Test cases in `.run/wave/`. ## Blockers / open findings - **✅ RESOLVED (T5b+T5c, 2026-07-03) — Phase-21 latent breakage: a truly-clean rebuild had been broken since Phase-21 close (`commit:0292`), masked by incremental builds. FOUND during T5b's R22 fleet verify; fully fixed, true clean 136/136 restored, `lint_symbol_refs.py` guard added.** (Kept here as the post-mortem for T9's PhaseEnd + cookbook distillation.) - **Symptom:** `make clean` + full re-extract + `make check-all` → main FAILS to build (`can't open asm/nonmatchings/800c3/func_8005CE18.s` … dozens); overlays failed 134× on `undefined reference to func_80058B40`. Only `main`'s failure remains after the overlay fix (135/136). - **Root cause:** Phase-21 xdedup (`commit:0292`, "+62 PsyQ names") renamed 62 PsyQ library functions to their proper names (InitHeap, FlushCache, GetTPage, SysEnqIntRP, SpuWrite, _SpuInit, CdMix, __main …) in `symbols.us.txt`, but did NOT propagate the rename to the committed source that references them by the OLD `func_` name: **(a) 1 shared macro CALL** in `engine_core.h` (`func_80058B40`, overlay-side) and **(b) 62 `INCLUDE_ASM(func_)` stub lines across 12 main/library `src/*.c`** (800c.c, 800c3.c×22, apicard1/2/4, boot.c, libcd1.c×8, libetc.c×6, libgpu.c×3, sgap.c, snd1.c×7, snd2.c). Splat now names/handles those addresses by the curated name (linked-not-stubbed via psyq_integrate, or emitted as `.s`), so the stale `func_` refs dangle. **Incremental builds reused stale pre-rename `.s`/`.o` and masked it** → every "check-all 136/136 / main 143dbb89" in Phases 21/22/23 was incrementally-stale, NEVER a genuinely-clean tree (the exact R22 failure mode). - **FIXED so far (overlay-side, byte-neutral, verified):** the 1 shared-macro call `func_80058B40` → `GetTPage` in engine_core.h (same addr 0x80058b40 → identical `jal`); took the fleet **135→ (134 overlays now pass)**; `ov_SC07_009` byte-identical `2a6499b6`. Static scan of engine_core.h+engine_types.h (func_ AND D_): this was the ONLY shared-header collision. - **FIXED (main/library-side, 62 refs — T5c, Drew: rename to curated names):** the root mechanism, byte-proven: **splat's FRESH regeneration of a stub `.c` uses the CURATED names** (move `src/800c3.c` aside → splat writes `INCLUDE_ASM(InitHeap)` + emits `InitHeap.s`); the committed `src/*.c` were simply STALE (`func_`) — Phase-21 renamed the symbols but never regenerated/renamed the committed stub refs. Fix = rename the 62 `INCLUDE_ASM(func_)` → the curated name (InitHeap, FlushCache, GetTPage, SysEnqIntRP, SpuWrite, CdMix, __main …) across the 12 files (800c.c 1, 800c3.c 22, apicard1/2/4 4/6/2, boot.c 1, libcd1.c 8, libetc.c 6, libgpu.c 3, sgap.c 1, snd1.c 7, snd2.c 1). **main clean-builds `143dbb89` ✓**; full clean fleet check-all confirming 136/136. (NOT hex-case, NOT a proto-dup — only symbols.us.txt is stacked.) - **Lesson (→ cookbook, T9):** a `symbols.us.txt` rename MUST be propagated to (a) shared-macro bodies AND (b) `INCLUDE_ASM` stub refs, AND verified by a genuinely-clean (`make clean` + full re-extract) check-all, never incremental. Add a lint: every `func_` referenced in committed `src/` must have a matching emitted `.s` OR a defined symbol. Also: T5b's interim harvest_verify on func_8014E048 passed on a stale `_a.o` → re-verified clean (ov_SC01_077 was among the 135 that pass). - **RESOLVED in T2 (R14 self-correction):** the T1 finding that "func_80132784 is 204-off / not 4/400" was itself the `-dr` artifact. Once `match_one` uses `-drz` (T2), func_80132784 reads its **true 400 ins and is 4/400 count-exact** — the Phase-23 "4 instructions away" premise is CONFIRMED. Backlog re-logged closeness 4 (source T2-drz). The residual is a **prologue save/init order swap (S7/S11) — a pure register/schedule swap, prime permuter/pin + T4 target.** The realistic count-exact near-permuter seeds are: **func_80132784 (4)**, func_8014E048 (35), func_80176D94 (52), func_80148094/vG2 (72), func_801412A8 (110). S11 blocks func_801412A8 + (partly) func_80132784 → T5b Fable5 spike still well-motivated. Lesson: the `-drz` fix (T2) is load-bearing for measurement honesty, not just the permuter's gradient.