Update CURRENT_PHASE: T6 [x] done, next=T7 (xHigh, ping Drew), progress-log T6 §A entry (4 tool fixes + the stale-asm R22 lesson), CONTINUATION §A marked resolved.
32 KiB
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
- T1 — Re-log map-wave results + backlog hygiene (xHigh)
- T2 — Permuter Stage-0: floor-free masked scorer (-drz) (Max)
- T3 — Permuter setup fixes: pins · typedefs · -O0 (xHigh)
- T4 — Probe the flagship func_80132784 (4/400) + count-exact seeds (Max)
- T5 — Permuter evolve: §31-directed mutation + grinder fixes (Max)
- 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)
- 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.pyguard - 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. - T7 — Unblock the 8 compile-blocked region-a giants (xHigh — Drew: PING before starting to switch effort) — §C
- T8 — Scale the §31 wave (breadth → prompt for /effort toggle, R27) — §D
- T9 — Distill + PhaseEnd (Max, Tier-1) — §E
Current task: T6 COMPLETE (§A propagation-recovery done). NEXT: T7 — unblock the 8 compile-blocked region-a giants (xHigh — Drew: PING to switch effort before starting). Rules check ✓ after T4 + after T6.4 (P6); next due after T8. Fleet at last commit commit:0448: 136/136 byte-identical (clean R22 verified), 65.48% count / ~31.7% byte-weighted, 1799 dedup groups, 0 NON_MATCHING. main 143dbb89, resident 8e17e02f, ov_SC01_077 d19c9580.
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.
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.pyare -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 (OtBlknot inengine_types.h), NOT a straggler. →build_engine_types.py(T6).backlog.jsonlcloseness is stale/regressed for the wave seeds (true values in.run/wave/*.cheaders;func_8014E048loggedfailed→wave_targetsskips 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 inOTHER/None. → wave text-scanswhere_stuck(T8). gcc-papermariois gcc 2.8.1, not 2.7.2; vanilla 2.7.2 attools/reference/gcc-2.7.2/(cite it).loop.mdon vanilla; sched/regalloc/cse map files still cite 2.8.1 lines.- No decomp-permuter submodule edit for the overhaul (scorer rebind +
#pragma _permuter b64literalpin carrier +weight_overrides, all intools/). The pin-scope randomizer pass (only submodule edit) is deferred.
Progress log
(append one line per task on completion — the crash-recovery trail)
- 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 atextern 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 bogustypedef vec, self-colliding and blocking every --strip; NOTE full --strip still conflicts with the_a/_o0splits, 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) + extendedtools/fix_arity_callers.pywith--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_077d19c9580). R14 lesson (clean-verify caught it): the first batch'sfix_arity_callers --revertwas 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_propagatefind_sitemisses 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. Flagshipfunc_80132784(commit:0443) remains the one ×134 T6 win. - T6 (partial) ✓ (2026-07-03): 🎯 FLAGSHIP
func_80132784PROPAGATED ×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 externvoid func_80132784(s32,s32,s32)vs the def(s32,s32,u32)→conflicting types→ dedup_propagate's all-or-nothing single---addrplan 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, groupE_func_80132784registered, 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'scompiles_standalonerejects 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 staleINCLUDE_ASM(func_<ADDR>)→ curated names across 12 main/librarysrc/*.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-builds143dbb89✓; fleet 136/136 ✓ (all overlays byte-identical, resident8e17e02f). Builttools/lint_symbol_refs.py(comment/string-aware, func_+D_) — flags anyfunc_/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_verify1/0, ov_SC01_077d19c9580…). Derived by reading gcc-2.7.2 source +-dl -dg -dSRTL 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-decls16*→u16*(ptr param type codegen-neutral) + canonical data decls with*(u16*)access casts (D_801152A8u8[]/ D_801152ACs16). ×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_tomlemitting 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_declsRC-1/3 ·perm_reorder_stmtsRC-2/S1 ·perm_temp_for_exprS2 ·perm_commutativecse) and pushes the value/type noise to ~0.1. Wired intop16_permute.setup(…, klass=, where=)(+--klass, backlog auto-lookup) andgrinder.py(auto-threadsklass/where_stuck;klass=None→ gcc defaults = the pre-T5 undirected search, a safe superset). Grinder fix (R14): replaced the blindtried.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 drovefunc_8014E048base masked-36 → 29 (match_one-drz35→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_077BYTE-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_005cross-overlay straggler + anextern/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 redundantBlk16typedef (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 ownprocess_pragmasdecodes it back so cc1 sees the real asm); custom-typedef/#definepreservation (drop only#include);f32typedef gap fixed;compile_o0.sh-O0variant auto-selected for_o0targets;run_masked.pypin-var fallback (expr_type→inton an unknown/hidden-pin id → 0 "internal permuter failures", was >0). ROOT CAUSE of the GTE fail:compile.shnow prepends.include "macro.inc"somvmvaassembles (the real build gets it viainclude_asm.h, which base.c omits +-DPERMUTERdisables) — 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 thatmatch_oneindependently confirms MATCH (400 ins) — winner preserved.run/wave/func_80132784.win.cfor 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(sharedobjdump -drzoracle + masking), refactoredtools/match_one.pyto use it (-dr→-drz),tools/masked_scorer.py(MaskedScorerdrop-in),tools/permuter/run_masked.py(rebindssrc.main.Scorer), wiredp16_permute.run_permuter. VALIDATED:masked_self=0;masked_cand≈match_one(7772/3635/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.-drzalso 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 GTEmvmva/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,.bakkept; best_draft →.run/backlog_drafts/). Ground truth (match_one-dr): func_8014E048=35 (was mis-loggedfailed), 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 → T6OtBlktype-lift). Fixed gate_stage sig_unify/--src-filedoc-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):
dedup_propagate.find_sitemisses 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) + itsINLINE_DEF_REdetect column-0 defs only. Fix: allow leading whitespace in the inline-def detection (same Phase-15find_sitebrace-placement class — a green byte-gate masks under-propagation; verify viamake reportfleet %, not just the gate). Cross-check withtools/gen_harvest_targets.py:INLINE_DEF_RE(Phase-19 fixed a similar column-0 issue there).- 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. - 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'sextern <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 asdedup_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 byp16_permute.setup/grinder. No submodule edit.tools/lint_symbol_refs.py(T5c): flags stalefunc_/D_<ADDR>refs after a symbols rename (comment/string-aware). Run after ANY symbols.us.txt rename; T9 candidate to wire intomake 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:--revertis 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). Theharvest_verify/dedup_propagateper-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 stagesymbols.us.txt(unrelated). - Commit hygiene: the tool commits keep source/tool/docs;
git checkout src/ docs/to revert scratch banks (keepstools/+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.pyguard 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× onundefined reference to func_80058B40. Onlymain'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 …) insymbols.us.txt, but did NOT propagate the rename to the committed source that references them by the OLDfunc_<ADDR>name: (a) 1 shared macro CALL inengine_core.h(func_80058B40, overlay-side) and (b) 62INCLUDE_ASM(func_<ADDR>)stub lines across 12 main/librarysrc/*.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 stalefunc_<ADDR>refs dangle. Incremental builds reused stale pre-rename.s/.oand 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→GetTPagein engine_core.h (same addr 0x80058b40 → identicaljal); took the fleet 135→ (134 overlays now pass);ov_SC07_009byte-identical2a6499b6. 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
.cuses the CURATED names (movesrc/800c3.caside → splat writesINCLUDE_ASM(InitHeap)+ emitsInitHeap.s); the committedsrc/*.cwere simply STALE (func_<ADDR>) — Phase-21 renamed the symbols but never regenerated/renamed the committed stub refs. Fix = rename the 62INCLUDE_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-builds143dbb89✓; 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.txtrename MUST be propagated to (a) shared-macro bodies AND (b)INCLUDE_ASMstub refs, AND verified by a genuinely-clean (make clean+ full re-extract) check-all, never incremental. Add a lint: everyfunc_<ADDR>referenced in committedsrc/must have a matching emitted.sOR 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).
- Symptom:
- RESOLVED in T2 (R14 self-correction): the T1 finding that "func_80132784 is 204-off / not 4/400" was itself the
-drartifact. Oncematch_oneuses-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-drzfix (T2) is load-bearing for measurement honesty, not just the permuter's gradient.