Files
BFM-decomp/phase-ends/logs/Phase24.md
T
Drew T 9194d27760 feat(phase-24): permuter overhaul + integration-recovery + the giant endgame (all giants ×134); fleet 64.86->66.02% (v1.23.0)
- PERMUTER OVERHAUL (tools/, no submodule edit): masked_diff.py floor-free relocation-masked
  scorer (killed the ~1750-2100 stock floor -> true closeness); permuter_weights.py §31-class-
  directed mutation; permuter_ils.py warm-restart ILS; p16_permute pin/typedef/-O0/comment fixes.
- GIANT ENDGAME COMPLETE: every matched region-a giant banked ×134 — the whale func_80144B9C
  (770, -O0 struct-assign memcpy §38), the flagship func_80132784 (400, "irreducible 22 phases"),
  the §G batch (6/8 cracked), + this close's func_801770E0 (152) + func_801372B0 (207). 2 permanent
  walls remain (func_801412A8, func_80178004 — G4). NO matched giant remains ×1.
- INTEGRATION/PROPAGATION TOOLING: recover_integration.py, reconcile_decls.py, dedup_propagate
  --recover + find_site fixes + overlay_files _o0b/_after (post-whale gap), lint_symbol_refs.py.
  Fixed the Phase-21 latent clean-rebuild breakage (62 stale INCLUDE_ASM refs) -> true clean 136/136.
- TOOLKIT MATURED: cookbook §18-§39 + gcc-2.7.2-map (S11/S12/S13, RC-6..RC-13, giant idioms).
- STRATEGIC REFRAME (R14): the frontier grouped by STRUCTURE (h_norm) reveals 2764 families /
  11.1 MB hidden by byte-grouping; 46% of large "solo monsters" are family members -> the idiom-
  curriculum endgame (Phase 25). Survey scripts .run/analyze_frontier.py + probe_hnorm.py.
- check-all 136/136 BYTE-IDENTICAL (R22), dedup 1783->1813/0, 0 NON_MATCHING (G4). No new rules
  (techniques -> cookbook; the reframe -> Phase-25 backlog). worklog -> logs/Phase24.md (R19).
2026-07-08 00:14:40 -06:00

139 lines
59 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/<fn>.h`, then in ov_SC01_077 AND each of the 133 overlays replace the `INCLUDE_ASM(<fn>)` line with `#include "../shared/<fn>.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 `<ov>.c` at the whale (splat emits in vram order → no item-parse hazard), carve the yaml code subseg into before/`_o0b`(-O0)/`_after`, thin `<ov>_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/<fn>.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_<ADDR>)` → 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_<ADDR>` 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 <ret> 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_<ADDR>` 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 <fn> --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_<ADDR>` name: **(a) 1 shared macro CALL** in `engine_core.h` (`func_80058B40`, overlay-side) and **(b) 62 `INCLUDE_ASM(func_<ADDR>)` 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 `<curated>.s`), so the stale `func_<ADDR>` 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_<ADDR>`) — Phase-21 renamed the symbols but never regenerated/renamed the committed stub refs. Fix = rename the 62 `INCLUDE_ASM(func_<ADDR>)` → 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_<ADDR>` 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.