Files
BFM-decomp/phase-ends/logs/Phase22.md
T
Drew T 64cc91ee83 feat(phase-22): close — tractable giants banked ×134 (fleet 63.18->63.66%), irreducible tail byte-deferred; pivot to the LLM tier (v1.21.0)
- BANKED ×134 (~17 fns): func_8015126C (canonical-extern recovery) + func_80156B74/func_80163C2C
  (struct type-lift -> engine_types.h) + the 14-fn close=0 recovery batch (recover_giant.py). 136/136
  byte-identical, dedup-check 1633/0, 0 NON_MATCHING throughout.
- IRREDUCIBLE GIANTS byte-deferred w/ evidence: func_80132784 (hoist-vs-remat + reg-lifetime),
  func_801372B0 (scheduler last-mile, structural draft banked), func_8014F74C (masked). gcc-2.7.2
  intrinsic walls -> backlog, not effort gaps. Grinder ROI audit: 7 all-time banks (all Phase 21), 0 since.
- TOOLKIT: recover_giant.py + the engine_types.h type-lift lever; cookbook §28/§28a/§28b/§28c.
  gate_stage commit tag made phase-agnostic (GATE_PHASE).
- PIVOT: Phase 23 = the offline LLM matching tier (built this session; see CURRENT_PHASE.md).
- worklog -> phase-ends/logs/Phase22.md (R19); bumps project version 1.20.0 -> 1.21.0
2026-06-30 00:26:49 -06:00

75 lines
16 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 22: Hand-grind the giants (×134) + idiom-distill-then-fan-out flywheel
**Generation:** Gen2 (14th phase of the arc; Phase 14 deferred to Gen3+) · **Started:** 2026-06-26 · **Effort:** Max (giants/synthesis) ↔ Ultracode (idiom waves, prompt per R27) · **Plan approved:** gate 1 ✅ (Drew)
> Per-task crash-recovery log (P3). The full approved plan is at `~/.claude/plans/plan-mode-enabled-max-shimmering-thimble.md`. This file is the committable state a fresh session resumes from.
## Goal
Drive the **byte-weighted** progress number (~30% decomp.dev-comparable; the function-count metric is at 63.18%) by **hand-grinding the giants** (reach-134, >150 ins — each banks ×134), distilling each crack into a reusable idiom, then fanning that idiom out across its class via the existing wave harness. Open-ended; monotonic; zero regressions; close at a clean checkpoint when giant ROI drops.
## Decisions (Drew, gate 1)
- **Calibrate on a mid-giant first:** `func_8015126C` (254 ins / 135K, already a **close=2** backlog near-miss) → `func_8014EE14` (248 / 131K, close=6) → escalate toward `func_80144B9C` (770 / 410K).
- **Background grinder ON:** token-free permuter daemon on the regalloc/coalescing residual, alongside the hand-loop.
## The operating loop
A. Hand-decomp next giant (Max) → §27 recipe → match_one → harvest_verify byte-gate → dedup_propagate ×134 → commit. ROI-gate: irreducible class → bank closest draft to backlog (P9), move on.
B. Distill the last-mile idiom → cookbook (R16/R30).
C. If general → fan out a few waves (Ultracode, prompt R26/R27) applying it → gate_stage → distill.js → backlog.
D. Rinse and repeat (next giant, highest byte-weight first).
## Tasks
- [x] **T0 — Unified byte-weighted ranked worklist** *(done — `commit:0296`)* — `tools/worklist.py` → `docs/worklist.md` + `.run/worklist.json`.
- [x] **T1 — Calibrate on func_8015126C** *(done — banked ×134, fleet 63.18→63.22%, check-all 136/136)* — pin idiom + canonical-extern/block-scope recovery cracked it; all 23 giants confirmed Ghidra-C-cached (no prefetch needed).
- [ ] **T2 — Hand-decomp giants by byte-weight (loop)** — func_8014EE14 → … → func_80144B9C; one at a time, byte-gated, propagated ×134, committed. Report each (P3).
- [x] **T3 — Distill idioms → cookbook** *(done for func_8015126C — cookbook §28/§28a + `tools/recover_giant.py`, `commit:0298`)* — recurring per future crack.
- [ ] **T4 — Idiom fan-out waves (Ultracode)** — a few waves per learned idiom over its class (prompt R27). *(close=0 canonical-extern "wave" was probed → R14 refuted near-free; only func_8015126C banked.)*
- [x] **T5 — Background grinder** *(started + STOPPED for handoff; STOP sentinel set; banked 0 on the hard giants it sampled)* — RESUME: `rm .run/auto/STOP` then `DRIVER=tools/grinder.py setsid nohup bash tools/auto_supervisor.sh --permute-secs 120 -j 14 >/dev/null 2>&1 & disown`; monitor `bash tools/auto_status.sh`.
- [ ] **T6 — Progress honesty + PhaseEnd** — keep worklist/backlog/progress.fleet.md fresh; track both %s; PhaseEnd_Phase22.md at close (Tier-1 Max).
## ▶ RESUME HERE (fresh session)
**State:** Phase 22 in progress (NOT a phase end — no PhaseEnd file). 3 commits this session on top of Phase-21 close `commit:0295`: `commit:0296` (T0 worklist) · `commit:0297` (T1 func_8015126C ×134) · `commit:0298` (T3 cookbook §28 + recover_giant.py) + a reports-regen checkpoint commit. All 136 binaries byte-identical (`make check-all` 136/136); fleet **63.22%** function-count; dedup-check 1617/0. Working tree clean except the R23 `db.*.gbf` churn (do NOT stage). **Drew commits AND pushes the session work (R6/R8).** Grinder STOPPED (STOP sentinel set).
**NEXT TASK — T2: hand-decomp the next giants by byte-weight** (effort **Max**; the loop is A hand-crack → B distill → C fan-out). Use `docs/worklist.md` (the GIANT queue, refreshed) as the decision spine. Concrete queue:
1. **func_80132784** (400 ins, #2 byte-weight giant; backlog close=240: prologue+GTE pipelines match, residual = else-branch `$s0` pointer regalloc + GTE-section stack-ptr allocation → §17 pins). The biggest reachable hand target.
2. **The struct-walled close=0 trio** `func_80156B74` (214), `func_8014F74C` (174), `func_80163C2C` (167): match_one MATCH but blocked by a local `struct S8`/`B8` colliding with the TU (§28 case 3). Lever: lift `S8`/`B8` to `src/shared/engine_types.h` (or reuse the existing def / rename), then `tools/recover_giant.py` + gate. Could bank ~3 giants if the type-lift resolves it.
3. **func_80178004** (165): saved draft regressed (DIFF 91) — re-derive from cached Ghidra-C (it had register-pins-per-sibling-func_80177EA4 keys).
4. **decomp.wiki levers to try** (§28a): `func_801412A8` (198, offset-fold-vs-advance residual) → the **negative-struct-offset-in-loop** idiom (`for(...; p++)`); the **branch-duplication** lever for call-crossing regalloc swaps.
5. After each bank: `dedup_propagate` ×134 (BACKGROUND), `make check-all`, commit, distill any new idiom (T3), then optionally a fan-out wave (T4, prompt for Ultracode R27).
**Reusable this session:** `tools/recover_giant.py` (canonical-extern recovery for pure-extern close=0 giants); `tools/worklist.py --refresh` (the ranked decision table); calib drafts in `.run/drafts-t1-calib6/`. **Op gotchas (cookbook §28):** run `dedup_propagate` in BACKGROUND; `git checkout src/` does NOT revert `config/dedup.us.yaml` (reset both on a redo). **Pending tooling polish:** `gate_stage.py` commit message hardcodes "phase-21" → make phase-agnostic before the T4 worker waves.
## Verification invariant (every bank)
`make check-all` → 136/136 byte-identical from a CLEAN tree (R22); `dedup-check` validated, 0 failed; 0 NON_MATCHING (G4); byte-gate (harvest_verify) is the sole arbiter (G3/P9); each bank = checkpoint commit; the `db.*.gbf` churn is R23 restart-noise (do NOT stage).
## Reuse (no rewrites)
orchestrator / wave_targets / worker_wave.js / distill.js / gate_stage / idiom_loop / grinder + supervisor / harvest_verify / match_one / dedup_propagate / build_fuel_manifest / backlog; cookbook §17–§27 + hand-matching-process.md + automation-runbook.md.
## Guardrails
- Don't grind confirmed-irreducible classes (store-vs-load sched, hoist-vs-remat, IV-combine, hoisted-invariant order, narrow-param loose-typing, cross-jump merge) — ROI-gate, bank closest, move on.
- Actor struct is byte-NEUTRAL for matching (comprehension only).
- R27 effort transitions: prompt Drew to toggle Max↔Ultracode at every A/B↔C boundary; never launch a Workflow on a verbal yes.
## Blockers
(none)
## Progress log
- 2026-06-26: Phase plan approved (gate 1). Task list built (R28). CURRENT_PHASE.md written. Starting T0.
- 2026-06-26: **T0 done** (commit `commit:0296`) — `tools/worklist.py` + `docs/worklist.md` + `.run/worklist.json`. 451 live stubs / 1.85M ins remaining gain; GIANT queue = 23 fns = 37.2% of remaining gain; top = func_80144B9C (770 ins, 5.58%).
- 2026-06-26: **T1 calibration on func_8015126C (254 ins, top-5 giant) — CRACKED, byte-identical in ov_SC01_077; ×134 propagation running (bg bl73feigi).** Key findings (→ T3 distill):
- **(idiom) §17 pin for the coalescing residual:** the `(s16)p[0x79]!=1000` compare wanted `$a0` (coalesced) not `$v1`. Lever: `register s32 cmp79 __asm__("$4")` + assign **inside** the `&&` (lazy, not hoisted) → MATCH. Reusable for the regalloc-coalescing giant group.
- **(THE close=0 wall, byte-proven) why match_one MATCH ≠ whole-binary bank:** the saved draft's *self-contained file-scope externs* conflict with engine_core.h's canonical sigs (e.g. my `extern void func_8015173C(void*)` vs canonical `void func_8015173C(s32*)`). `cast_call_sites`/`sig_unify` do NOT canonicalize these → the close=0 giants sit unbanked. **Fix (deterministic):** rewrite each engine_core.h-callee extern to its canonical def-sig AND move ALL externs **block-scope** (inside the body) so `find_site`/`compiles_standalone`/`dedup_propagate` accept them (file-scope externs are excluded from the lifted body → "not self-contained"). This is a missing gate-stage recovery step.
- **(gotcha) saved best_drafts get clobbered** by later worse attempts (func_8015126C's close=0 winner was overwritten by a close=2/case-broken copy). Trust the gate, re-derive from match_one.
- **(gotcha) propagation is slow** (134 overlay builds) — run dedup_propagate in the background, not a 2-min foreground (a SIGTERM leaves a partial non-atomic state: macro + instantiations applied, registry unwritten).
- **(T4 hypothesis)** the other close=0 giants (func_80156B74 214, func_8014F74C 174, func_80163C2C 167, func_80178004 165) likely unblock with the SAME canonical-extern + block-scope recovery → a deterministic near-free wave.
- 2026-06-26: **T1 CLOSED — func_8015126C banked ×134, fleet 63.18%→63.22%, `make check-all` 136/136 byte-identical, dedup-check 1617 validated/0 failed.** The full loop is proven end-to-end (hand-crack → bank → ×134 propagate → fleet-verify). Calib draft saved at `.run/drafts-t1-calib6/`. Reusable canonical-extern recovery: extract each engine_core.h callee's def-sig, rewrite the draft's extern to it, move ALL externs block-scope; then harvest_verify + dedup_propagate (run propagate in BACKGROUND — foreground gets killed; and `git checkout src/` does NOT revert `config/dedup.us.yaml`, so reset BOTH on a redo).
- 2026-06-26: Drew Q — decomp.wiki/compilers/GCC patterns: ~6 useful for us (PS1 gcc-2.7.2-psx). Top for giants: **negative-struct-offset-in-loops** (`for(...;ptr++)` → directly addresses func_801412A8's offset-fold residual), **branch-invariant code duplication** (alt to §17 pins for call-crossing regalloc swaps), **load-coalescing** (`if(t->a||t->b)`→`lw`). Also: div magic-constant table, s16/s8 div-by-2, gcc-2.7.2.x `slti …,0`. N/A to PS1: `bnel`-likely (MIPS II+), `.lit4` NOPs (PS2), C++ bool (C only). → fold the 3 top into cookbook in T3.
- 2026-06-26: **close=0-giant fan-out probed — R14 REFUTES "near-free" (only func_8015126C was pure-extern).** Of the 5 close=0 giants: func_8015126C #1 pure-extern (BANKED); func_80156B74/func_8014F74C/func_80163C2C #3 STRUCT-walled (local `struct S8`/`B8` collide w/ TU — need type-lift); func_8014F74C also #2 masked-residual (§27, permuter); func_80178004 #4 regressed draft (DIFF 91, re-derive). The canonical-extern lever is real but the group is NOT uniformly near-free. **T3 captured:** cookbook §28 (the 4-way close=0 triage + the canonical-extern recovery + the coalescing pin) + §28a (decomp.wiki PS1 patterns) + `tools/recover_giant.py` (promoted). Net giant strategy unchanged: genuine per-giant hand-work (T2), grinder for the masked/coalescing tail (T5).
- 2026-06-26: **Session paused at a clean checkpoint (Drew).** T0/T1/T3 committed; T5 grinder started then STOPPED for handoff (banked 0). Reports regenerated. Tree clean (only R23 db churn). Resume from the ▶ RESUME HERE block → T2 giants. Grinder is OFF (STOP sentinel) until a fresh session restarts it.
- 2026-06-26 (new session, effort **xHigh** — Drew testing xHigh vs Max on giants): tasklist rebuilt (R28); T2/T3/T4 reframed as a recurring cycle (Drew). **T2 giant #1 BANKED: func_80156B74 (214 ins) ×134** — the struct-walled close=0 trio's lever proven. Method (→ cookbook §28b): lifted the `S8`/`B8` typedefs from ov_SC01_077.c's prelude block to `src/shared/engine_types.h` (shared fleet-wide; byte-neutral verified on resident + 2 overlays), removed the dup typedefs, `recover_giant.py` (block-scope externs) → whole-binary `harvest_verify` MATCH → `dedup_propagate` ×134. **Fleet 63.22% → 63.25%** (function-count; +28,676 ins byte-weighted), `make check-all` **136/136**, dedup-check **1618**/0 failed, 0 NON_MATCHING. Gotcha hit + fixed: a concurrent `make` job (check-all racing dedup_propagate) corrupted an `.o` AND dropped the propagation's registry write — re-ran dedup_propagate (idempotent) to register; **lesson: serialize all make jobs** (cookbook §28b-6). NEXT: func_80163C2C (167, Blk16/Buf32 — same type-lift lever; recovered draft staged in `.run/drafts-t2/`).
- 2026-06-26 (xHigh): **T2 giant #2 BANKED: func_80163C2C (167 ins) ×134** — same type-lift lever. Lifted `Blk16`(u32×4) + `Buf32`(2×Blk16) to engine_types.h, removed the Blk16 dupes from ov_SC01_077.c AND ov_SC01_077_a.c (the -O0 split), byte-neutral verified → recover_giant → harvest_verify MATCH → dedup_propagate ×134. **Fleet 63.25% → 63.29%** (+22,378 ins byte-weighted), `make check-all` **136/136**, dedup-check **1619**/0 failed. Struct-walled close=0 trio DONE (func_80156B74 ✓, func_80163C2C ✓; func_8014F74C is masked-residual → grinder fuel, not type-liftable). **Tool quirk (recurring, benign):** dedup_propagate's first full run applies source + registers but its per-overlay byte-gate output didn't appear in-log; the authoritative gate is the post-bank `make check-all` (136/136). NEXT: restart grinder (T5) on permuter-class giants; hand-decomp func_80132784 (400, close=240, §17 pins GTE-section regalloc — the big one).
- 2026-06-26 (xHigh): **func_80132784 HARD-DEFER** (R14, byte-evidenced) — residual = hoist-vs-remat (irreducible §10) + register-LIFETIME-reuse (target reuses $s0/$s2 for GTE pointers after s0p/s2v die; function-scoped `register __asm__` pins can't express this). Too big (400) + far for the grinder. Logged to backlog. Grinder restarted (T5, permuting) then PAUSED for the batch below.
- 2026-06-26 (xHigh): **T2 close=0 RECOVERY BATCH — 14 functions ×134 (R14 corrects §26 "exhausted").** Surveyed the 43 still-live close=0 reach-134 fns; `recover_giant` + whole-binary gate banked **7** (func_80156ECC, func_80147E44, func_8015ADB0, func_801661CC, func_80166054, func_8012CFA8, func_8012A62C); `dedup_propagate --auto-from` propagated those + **7 pre-existing inline-matched bonus** (func_8012C098/F14C/F038/C0EC/E5CC/C750, func_80128ED8) ×134. The other ~33 are the genuine DEF-side/masked wall. **Fleet 63.29% → 63.66%**, `make check-all` **136/136 byte-identical**, dedup-check **1633**/0 failed. Hit the recurring dedup_propagate registry-skip (source propagated, registry partial) → recovered by direct `append_groups` registration (cookbook §28c; bytes were already correct per check-all). Distilled §28c (close=0 not exhausted + the registry-skip recovery).
- 2026-06-26 (xHigh): **from-scratch giant test — func_801372B0 (207) STRUCTURALLY CRACKED but scheduler-walled (Drew chose 'keep hand-decomp at xHigh').** Decompiled from raw Ghidra-C: a 3D-gizmo/compass HUD drawer (SVEC in/out + GsLINE prim, 4 axis projections via ApplyMatrixSV → GsSortLine + func_80137030/178). First draft was structurally PERFECT (206/207 ins, logic 100%); 4 pin iterations placed the regs but the residual is the **giant scheduler/regalloc last-mile** (10 held callee-saved regs; gcc's list-scheduler orders prologue-saves+materializations differently → pervasive positional diff, ~173). NOT C-steerable to byte-exact; too far for the grinder (173>30). Banked the structural draft to backlog (high-value head-start). **xHigh finding (Drew's test):** xHigh reached structural match FAST on giants — the wall is gcc determinism (§27/§17), not reasoning depth, so xHigh appears sufficient for this work (the bottleneck isn't depth). Grinder running on the permuter tail. SESSION DELIVERED: **16 functions banked ×134** (2 giants + 14 close=0), fleet 63.22%→63.66%, §28b/§28c, 2 hard giants diagnosed+logged.
- 2026-06-27: **Grinder STOPPED (clean, rc=0) + ROI audited (Drew asked for the total).** All-time grinder banks across 11 runs = **7 functions** — ALL during Phase 21 (~06-22, fleet 61-62% when tractable close≤30 fuel existed); **0 banks since** (late Phase 21 + all of Phase 22). Efficiency: 62 "permuter WON" events but only 7 banks (~11%) — the rest were gate-rejected (masked-residual §25) or pure CHURN (func_8014F3E8 won ~22×, func_8014FE60 ~18× across runs, never banked AND never blacklisted). **Two grinder BUGS found (fix before next use):** (1) split-file-blind — it looks for `.s` only in `asm/ov_SC01_077/nonmatchings/ov_SC01_077/`, NOT the `_a`/`_o0` split subdirs → this session it errored on 100% of targets (all `_a`-region); (2) churn-without-blacklist on permuter-won-but-gate-rejected-for-non-plumbing fns. Net: the grinder is a real-but-modest token-free contributor (7 all-time), now exhausted on the hard tail — keep for future fresh tractable fuel only after the 2 fixes. T5 is OFF (STOP sentinel set).