mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 22:45:39 -04:00
a741d2b6b5
- RESEARCH (T0-T7): read gcc-2.7.2 source (gcc-papermario) + mined Xenogears (our exact compiler) -> per-class byte-gated verdicts. VERDICT REVERSAL (Drew "hand-match everything"): the call-crossing register-ORDER class is STEERABLE via `register __asm__` pins + a scheduling barrier (func_8012B8E4, the flagship "unsteerable" fn, byte-gated) -- not unsteerable. - TOOLKIT (cookbook §17): pins+barrier (register swap), array-decay (hoist-vs-remat), for-loop/statement-order (structural), sig_unify-mandatory; narrow-param = honest stub. §16 reconciled (§10-vs-§16). - TAUGHT TO WAVES (§17a): calibration 9/16=56% whole-binary (vs 33%); Step-1 (embedded canonical callee sigs + call-site-cast/re-validate) 28/31=90% match_one, 22 verified. ~31 reach-134 matches banked, each propagated x134. fleet 55.51 -> 56.64% (+1.13%). - FINDING: the match_one->gate gap is declaration plumbing (call-site casts not redeclaration; stale M2C_UNK sibling-decl reconcile; implicit-int caller class) -- recovered deterministically. - NEW residual classes: per-file -O0 (~18 fns, needs an -O0 split file like src/boot.c -> high ROI) + gcc loop-guard operand-order (irreducible). W1: build-divergence ruled out by proxy. - make check-all 136/136 byte-identical (R22); dedup 1450 validated/0 failed; 0 NON_MATCHING (G4). - worklog -> phase-ends/logs/Phase18.md (R19); bumps 1.16.0 -> 1.17.0
224 lines
21 KiB
Markdown
224 lines
21 KiB
Markdown
# PhaseEnd — Phase 18: Compiler-quirk research → the matching TOOLKIT, taught to waves at scale
|
||
**Date:** 2026-06-20 · **Project Version:** 1.17.0 · **Phase Status:** Complete (milestone confirmed by Drew, gate 2) · **Generation:** Gen2 (10th phase)
|
||
|
||
> Gen2 phase 10 of the arc (8→9→10→11→12→13→15→16→17→**18**; 14 deferred to Gen3+). Ran across **multiple
|
||
> sessions**; the granular per-task/per-session trail (T0–T7, the verdict reversal, the 5-avenue ceiling test,
|
||
> the Step-3b calibration, the Step-1 wave + recovery diagnostics) is preserved on-demand at
|
||
> **`phase-ends/logs/Phase18.md`** (R19 — NOT auto-loaded; consult only when researching a mechanism). This
|
||
> file is the synthesis. Owner decisions (Drew): pursue the research → on the "unsteerable" finding, **hand-match
|
||
> everything** (verdict reversal) → teach the toolkit to a calibration wave → **bounded ~40 Step-1 wave**
|
||
> (full tractable-247 sweep deferred to Phase 19) → close with a full Phase-19 backlog.
|
||
|
||
## Build Log
|
||
|
||
**Files created/changed and complete — do not recreate:**
|
||
|
||
*The research + the matching TOOLKIT (T0–T7 + verdict reversal):*
|
||
- `tools/reference/` (gitignored, SETUP §5.6) — cloned **gcc-papermario** (`a6afc2af`, the PSX gcc-2.7.2 lineage
|
||
source) + **xenogears-decomp** (`f27c0768`, Square Oct-1998, our EXACT compiler). The primary-source corpus.
|
||
- `tools/wall_taxonomy.py` + `docs/wall-taxonomy.md` — census/size every residual class (carried from P17 T1).
|
||
- `tools/ram_probe.py` + `docs/actor-struct.md` — the actor/arg0 struct, recovered + live-verified (R10).
|
||
**Re-confirmed byte-NEUTRAL for matching** (matching reads access width off the asm opcode, not a struct def).
|
||
- `tools/ghidra_scripts/DecompileFunctions.java` — headless Ghidra-C batch pre-pass (no /mcp); feeds the
|
||
`.run/ghidra_c/` cache (300 fns) the waves draft from.
|
||
- `tools/census_conflict_callees.py` + `tools/derive_canonical_sigs.py` — the **canonical-sig layer** builders
|
||
(one byte-neutral `s32 func_X(s32…)` per conflict callee; arity from Ghidra-C + asm read-before-write $a0–$a3).
|
||
The 20-extern block at the top of `src/ov_SC01_077/ov_SC01_077.c` (LOCAL; reach-1 names differ per overlay).
|
||
- `docs/hand-matching-process.md` — §1 loop / §2 idioms / §3a 5-move signature playbook / §7 wave / §8 the
|
||
canonical-sig-layer finding / §8e Phase-18 outcome (corrected to the register-pinning toolkit).
|
||
- `docs/matching-cookbook.md` **§17** — **the matching TOOLKIT** (the phase's durable deliverable): the
|
||
call-crossing register-ORDER class is **STEERABLE with `register __asm__` PINS + a scheduling barrier**
|
||
(corrected from a wrong mid-phase "unsteerable" verdict); **array-decay** forces rematerialization;
|
||
**for-loop / statement-order** control scheduling; the **`sig_unify`-MANDATORY** gate gotcha; the
|
||
**narrow-param loose-typing** wall (stub). §16 reconciled (§10-vs-§16 tension resolved).
|
||
- `docs/matching-cookbook.md` **§17a (THIS SESSION)** — the toolkit **at wave scale** (measured close-rates) +
|
||
the **pipeline-integration recovery** techniques (call-site casts not redeclaration + re-validate; stale
|
||
sibling `M2C_UNK` decl reconcile; the implicit-int caller class) + **two NEW residual classes** (per-file
|
||
`-O0`; gcc loop-guard operand-order).
|
||
- `src/shared/engine_core.h` — the worked-example macros `DEFINE_func_8012B8E4` (pins + barrier) and
|
||
`DEFINE_func_801399A8` (for-loop/structural) + **~33 new Phase-18 reach-134 macros** (the wave harvest).
|
||
- `config/dedup.us.yaml` — **1450 validated cross-binary groups** (was ~1424 at phase start; +the Phase-18
|
||
propagations). 0 failed.
|
||
- `src/ov_SC01_077/ov_SC01_077.c` + the **134 overlay `.c` files** — the harvest source + the ×134
|
||
propagations; 2 recovery reconciles (func_8012A418 stale-sibling-decl; func_8012F68C parse-fix).
|
||
|
||
*The Step-3b/Step-1 wave harness (gitignored under `.run/`, regenerable; the recipe is cookbook §17/§17a):*
|
||
- `.run/harvest_wave_3b.js` (calibration, 16 targets) + `.run/harvest_wave_p18s1.js` (Step-1, 31 targets,
|
||
+embedded canonical callee sigs +call-site-cast/re-validate). `tools/gen_harvest_targets.py` generates the
|
||
per-target callee-sig/data-decl manifest the Step-1 prompt embeds.
|
||
- `phase-ends/CURRENT_PHASE.md` → **`phase-ends/logs/Phase18.md`** (R19 archive). `phase-ends/PhaseEnd_Phase18.md` — this file.
|
||
|
||
**Local artifacts (gitignored / regenerable):** `.run/ghidra_c/*` (300 cached Ghidra-C), `.run/drafts-*`
|
||
(wave drafts + gate-staging dirs), `.run/p18/*` (T1/T2-T3 analyses, exemplar scratch), `.run/harvest_*.js`,
|
||
`.run/*_targets*.json`, `build/`, `expected/`, `asm/`, `assets/`. `tools/reference/` (the cloned gcc/Xenogears
|
||
source). The 134 overlay Ghidra programs are script-reproducible (DB-commit deferred as regenerable).
|
||
|
||
**Tools/packages installed:** None — the whole phase used the existing Phase-4/6/10/11/12/13 toolchain + venv.
|
||
(Wine deliberately NOT installed — W1 ruled build-divergence out by proxy; SETUP §4.8 unchanged.)
|
||
|
||
**Verification results (literal) — the milestone proof:**
|
||
- **`make check-all` → 136 passed, 0 failed of 136** (main `143dbb89…`, resident `8e17e02f…`, all 134 overlays
|
||
byte-identical; ov_SC01_077 `d19c9580…`), reproduced from clean after every step (R22).
|
||
- **`make report`:** FLEET byte-identical **194,839 / 344,010 = 56.64%** (phase start 55.51%); **dedup-check
|
||
1450 validated, 0 failed**; **0 NON_MATCHING** in any default build (G4).
|
||
- **The TOOLKIT, byte-gated per class:** register-ORDER → `func_8012B8E4` MATCH via pins+barrier (the flagship
|
||
"unsteerable" fn); array-decay → `func_8012B4B8` 88→52, `func_80149544/584` MATCH; structural/for-loop →
|
||
`func_801399A8` MATCH. Honest stubs: narrow-param (`func_80146A6C`), loop-guard order (`func_8012C2D0`),
|
||
§10 sched (`func_8014F2E0`), per-file -O0 (`func_8013C360`+~17).
|
||
- **The toolkit at WAVE scale (the bounded demonstration):** Step-3b calibration **9/16 = 56% whole-binary**
|
||
(vs the Phase-17 prompt's 33%); Step-1 (prompt v2: +embedded sigs +call-site-cast) **28/31 = 90% `match_one`,
|
||
22 verified**. **Session fleet arc 55.58% → 56.64% (+1.06%, ~31 reach-134 matches; phase total 55.51→56.64 =
|
||
+1.13%).**
|
||
- `git status`: only `config/`/`tools/`/`src/`/`docs/`/`phase-ends/` tracked; **zero ROM-derived/generated bulk
|
||
staged**. **No Ghidra DB change** this phase (matching used cached Ghidra-C + asm; the `db.*.gbf` churn is
|
||
SessionStart-restart noise — R23 no-op, do NOT stage).
|
||
|
||
**Milestone achieved (confirmed by Drew, gate 2):** the knowledge-gated milestone — a per-class byte-gated
|
||
verdict (validated C idiom OR honest "unsteerable" verdict naming the exact gcc pass), §10-vs-§16 reconciled,
|
||
≥1 quirk-tail function newly matched, 136 binaries byte-identical throughout — is **met and exceeded**. The
|
||
phase's headline reversal: the highest-reach **call-crossing register-ORDER class is STEERABLE** (`register
|
||
__asm__` pins + a scheduling barrier), not "unsteerable" as a mid-phase draft wrongly concluded. The toolkit
|
||
was then **taught to a parallel Ultracode wave** and demonstrated at scale (close-rate 33% → 56% → 90%
|
||
`match_one`), banking ~31 reach-134 matches (fleet +1.13%).
|
||
|
||
**Next:** **Phase 19 — Scale the toolkit (the wave-harvest at scale) + the cheap front-loaded levers.** A fresh
|
||
session, **plan mode** (Tier-1 Phase-Start). See the **Phase-19 Backlog** below for the full prioritized brief
|
||
(the -O0 split-file fix first, recovery-tooling, then 50-target waves scaling to 100+, with an optional bounded
|
||
gcc-research spike on the last residual classes). The infra is BUILT and staged.
|
||
|
||
## Deviations
|
||
| Item | Plan | Actual | Reason |
|
||
|---|---|---|---|
|
||
| Register-ORDER verdict | T1–T5 concluded "UNSTEERABLE from C" | **REVERSED — STEERABLE via `register __asm__` pins** | I'd skipped the most direct lever; Drew's "we hand-match everything" pushed it; `func_8012B8E4` byte-gated (P9/R14 self-correction). The "brute waves won't help" point stood; the HAND pin lever does. |
|
||
| Phase scope | research + a bounded quirk-tail demo (gate-1) | research **+ a calibration wave + a bounded Step-1 wave** | the reversal made the toolkit teachable to waves; demonstrating it at scale (33%→56%→90%) is the real proof it raises the ceiling |
|
||
| Step-1 size | "scale the wave on the tail" | **bounded 31 targets** (Drew chose ~40; full tractable-247 → Phase 19) | gate-1 deferred the full sweep to Phase 19; Step 1 = a bounded demonstration of the taught wave |
|
||
| Wave close-rate gap | (not anticipated) | `match_one` MATCH ≫ whole-binary verified (12→9, 28→22) | the gap is **declaration plumbing** (call-site casts the agents skip + `sig_unify` narrowing the extern), NOT codegen — recovered deterministically (cookbook §17a) |
|
||
| W1 Wine native-compiler check | bounded Wine run | **ruled out by proxy, Wine dropped** | 700+ matches prove our cc1's regalloc is faithful; the real compiler emits the same bytes → confirms, doesn't crack; heavy install not worth it (plan escape clause) |
|
||
| Effort | Max planning, xHigh/Ultracode execution | Max/xHigh research + debugging; **Ultracode for the waves** (Drew toggled); xHigh for this close | breadth-shaped waves under Ultracode (R26/R27); deep synthesis at xHigh (Drew's saved default) |
|
||
| New residual classes | (not anticipated) | **per-file -O0** + **gcc loop-guard operand-order** surfaced at scale | the waves exposed classes the single-function research hadn't; the -O0 one is build-infra (high ROI), not a wall |
|
||
|
||
## Commit Message
|
||
```
|
||
(Phase 18 landed as 16 commits commit:0141..commit:0156 + this PhaseEnd.)
|
||
|
||
feat(phase-18): compiler-quirk research -> the matching TOOLKIT, taught to waves (v1.17.0)
|
||
|
||
- RESEARCH (T0-T7): read gcc-2.7.2 source (gcc-papermario) + mined Xenogears (our exact
|
||
compiler) -> per-class byte-gated verdicts. VERDICT REVERSAL (Drew "hand-match everything"):
|
||
the call-crossing register-ORDER class is STEERABLE via `register __asm__` pins + a scheduling
|
||
barrier (func_8012B8E4, the flagship "unsteerable" fn, byte-gated) -- not unsteerable.
|
||
- TOOLKIT (cookbook §17): pins+barrier (register swap), array-decay (hoist-vs-remat),
|
||
for-loop/statement-order (structural), sig_unify-mandatory; narrow-param = honest stub.
|
||
§16 reconciled (§10-vs-§16).
|
||
- TAUGHT TO WAVES (§17a): calibration 9/16=56% whole-binary (vs 33%); Step-1 (embedded
|
||
canonical callee sigs + call-site-cast/re-validate) 28/31=90% match_one, 22 verified.
|
||
~31 reach-134 matches banked, each propagated x134. fleet 55.51 -> 56.64% (+1.13%).
|
||
- FINDING: the match_one->gate gap is declaration plumbing (call-site casts not redeclaration;
|
||
stale M2C_UNK sibling-decl reconcile; implicit-int caller class) -- recovered deterministically.
|
||
- NEW residual classes: per-file -O0 (~18 fns, needs an -O0 split file like src/boot.c -> high
|
||
ROI) + gcc loop-guard operand-order (irreducible). W1: build-divergence ruled out by proxy.
|
||
- make check-all 136/136 byte-identical (R22); dedup 1450 validated/0 failed; 0 NON_MATCHING (G4).
|
||
- worklog -> phase-ends/logs/Phase18.md (R19); bumps 1.16.0 -> 1.17.0
|
||
```
|
||
|
||
## Rules Added This Phase
|
||
| Rule | Reason |
|
||
|---|---|
|
||
| **None (governance).** Phase 18's lessons are *findings + techniques*, recorded where the Phase-8/11/13/15/16/17 precedent puts them (cookbook, not rules): the **register-pinning toolkit** + the **call-site-cast/re-validate** + the **sibling-decl/implicit-int recovery** + the **per-file -O0 and loop-guard residual classes** → cookbook §17/§17a + hand-matching §8e. The **verdict-reversal lesson** ("never conclude *unsteerable* before trying `register __asm__` pins; an intermediate metric is not the gate") is already governed by **G3/P9/R14** and the `dont-conclude-unsteerable-try-register-pins` memory. The **probe-before-investing / bounded-calibration-before-scale** discipline is already cookbook (Phase 15) + effort-map. No new norm of conduct emerged. | A research→toolkit→demonstrate phase produces knowledge, not governance. Existing rules covered the ground and the phase reinforced them (esp. R14: the "unsteerable" over-claim was an R14 failure mode, self-corrected). |
|
||
|
||
## PhaseEnd Changelog
|
||
**v1.16.0 → v1.17.0 — Phase 18 complete (Gen2 phase 10).** Set out to "understand gcc-2.7.2 to raise the
|
||
match-% ceiling," and delivered a **matching TOOLKIT** that does exactly that. Reading the real gcc-2.7.2 source
|
||
+ mining Xenogears (our exact compiler) produced per-class byte-gated verdicts — and a **decisive reversal**
|
||
(Drew's "hand-match everything"): the highest-reach **call-crossing register-allocation-ORDER class is
|
||
STEERABLE** with `register __asm__` pins + a scheduling barrier (the flagship `func_8012B8E4`, byte-gated),
|
||
*not* "unsteerable" as a mid-phase draft wrongly concluded (a clean R14 self-correction). The toolkit
|
||
(pins+barrier · array-decay · for-loop/statement-order · sig_unify-mandatory; narrow-param = honest stub) was
|
||
then **taught to a parallel Ultracode harvest wave** and demonstrated at scale: whole-binary close-rate **33% →
|
||
56%** (Step-3b calibration) **→ 90% `match_one`** (Step-1, after embedding each callee's canonical signature
|
||
and teaching call-site casts). **~31 reach-134 functions matched** (each propagated ×134), driving the fleet
|
||
**55.51% → 56.64%**, all 136 binaries byte-identical, 0 NON_MATCHING. The phase's reusable yield: the toolkit
|
||
itself (cookbook §17), and the **pipeline-integration recovery** insight (§17a) — the `match_one`→gate gap is
|
||
**declaration plumbing** (call-site casts, stale-sibling-decl reconcile, implicit-int callers), recoverable for
|
||
~0 agent tokens, not a codegen wall. Two new residual classes surfaced at scale: the **per-file -O0 class**
|
||
(~18 byte-exact-at-O0 functions needing their own -O0 split file — a high-ROI build-infra fix, not a wall) and
|
||
the **gcc loop-guard operand-order** residual (irreducible). W1 ruled build-divergence out by proxy (Wine
|
||
dropped). No new governance rules (techniques → cookbook). The harvest infra is BUILT and staged for Phase 19's
|
||
scale-up.
|
||
|
||
## Phase-19 Backlog — "Scale the toolkit" (Drew's research + wave recommendations, full context)
|
||
|
||
> Phase 19 = **scale the proven toolkit over the tractable reach-134 tail**, front-loaded with two cheaper
|
||
> levers, run as a flywheel. Detailed plan is a fresh-session Tier-1 Phase-Start task; this is the prioritized
|
||
> brief, by ROI. (Decided with Drew at the Phase-18 close.)
|
||
|
||
1. **[HIGHEST ROI — DO FIRST] The per-file `-O0` split-file fix (build-infra, no research, no agents).** ~18
|
||
functions in ov_SC01_077 were built **-O0** (prologue sig `21F0A003` = `addu $fp,$sp,$zero`; args spilled to
|
||
frame; load-delay nops; redundant `addu rd,rs,$zero`). Their correct C is **byte-exact at -O0** but the
|
||
overlay TU compiles `-O2`, and **gcc-2.7.2 has no per-function optimize pragma** (opt is per-file, Makefile).
|
||
Fix = give them their own `-O0`-compiled split file with a target-specific `CC1FLAGS := -O0 …` (the
|
||
**`src/boot.c` precedent**, Phase 7). ~18 fns × reach-134 for an afternoon of Makefile work. Members:
|
||
func_8013C360 + func_8013B568/B598/B6A0/B7AC/B7F4/B83C/BC7C/BCDC/BD34/BD74, func_8013C08C/C0F8/C414/C938/C964,
|
||
func_80144B9C, func_801457A4. (One agent already produced verified-correct -O0 C for func_8013C360 — see logs.)
|
||
2. **[COMPOUNDING — DO SECOND] Recovery-tooling investment between batches.** This session's deterministic
|
||
recoveries (call-site arity/void casts; stale `M2C_UNK` sibling-decl reconcile) banked matches for **~0 agent
|
||
tokens**. Fold them into the gate so the close-rate rises mechanically: teach `sig_unify` (or a post-pass) to
|
||
**auto-apply call-site arity/void casts** when a draft's call disagrees with the canonical extern, and to
|
||
**auto-reconcile stale sibling `M2C_UNK func_X();` decls** to the real sig. Also solve the **implicit-int
|
||
caller class** (3 deferred fns: func_80147514/8017209C/80168F40) — the clean path is **propagate-first**
|
||
(the def lands in `engine_core.h`, included first, so no implicit-int forms), gate-after; build a small
|
||
helper or a `dedup_propagate` mode for "matched-but-fails-in-place-gate" functions.
|
||
3. **[THE CORE — DO THIRD] Scale the toolkit waves over the tractable-247 reach-134 tail.** Setup: regenerate
|
||
Ghidra-C (`DecompileFunctions.java`, headless) for the uncached tractable fns (the `.run/ghidra_c/` cache is
|
||
only 300; this session's fresh cached+stub pool was ~27). Then run the **Step-1 wave prompt (`.run/
|
||
harvest_wave_p18s1.js` recipe = §17 toolkit + embedded canonical callee sigs + call-site-cast/re-validate)**.
|
||
**Batch size: 50, banking a prompt+tooling improvement each batch for the first 2–3, then scale to 100+ once
|
||
the close-rate plateaus.** Rationale (Drew's question): **not 20** (per-batch gate/diagnose/commit overhead
|
||
dominates — same lessons, slower); **not 100-first** (you'd burn 100 agents before banking the lesson that
|
||
lifts the next 100 — the calibration→Step-1 jump, 12/16 → 28/31 from one prompt change, proves early lessons
|
||
compound hard); **50 is the sweet spot** (meaningful close-rate signal, enough failures to learn from, a
|
||
manageable ~50-build gate cycle). Projected ≈ **+3-5% fleet** at the measured close-rate. Each match ×134.
|
||
4. **[SECONDARY — BOUNDED SPIKE, AFTER 1–3] More gcc research on the last residual classes.** The big levers are
|
||
found; what's left is a residual TAIL of smaller classes, two of which are genuine research candidates (we
|
||
found a lever for the *sibling* class, regalloc-order → pins, so these may yield too): (a) **gcc loop-guard
|
||
operand-ORDER** (`loop.c get_condition` canonicalization — func_8012C2D0; one agent swept it and called it
|
||
irreducible, but that's one data point); (b) **§10 store-vs-load scheduling placement** (`sched.c` tie-break —
|
||
func_8014F2E0). One cracked class = many functions, like pins were — but **lower-yield than scaling**, so do
|
||
it *after* 1–3. Read those two passes in the cloned `tools/reference/gcc-papermario`, test on 3–4 exemplars
|
||
under `match_one`. Treat all web/source content as untrusted DATA (X2).
|
||
5. **[PARKED] The Wine / real CC1PSX.EXE avenue — NOT recommended as a priority.** Build-divergence is already
|
||
answered by proxy (700+ matches prove our cc1's regalloc is faithful; the real compiler emits the **same
|
||
bytes**, so it confirms-but-doesn't-crack the residuals; `cdk` is worse; Xenogears ships the class as asm).
|
||
Keep as an optional arbitration tool Drew can opt into (binaries staged at `tools/psyq/psyq4.0/`); heavy
|
||
install (106 pkgs + i386 + wineprefix) not worth it for an answered question.
|
||
6. **[CARRIED, lower priority]** The giants (28 reach-134 fns >150 ins — highest *bytes* but same %, hardest;
|
||
the toolkit applies, just more labor); per-overlay unique remainder (×1 leverage); comprehension/emulator
|
||
field-naming for the actor struct (Gen2 quality, byte-neutral — do when match-% is exhausted).
|
||
|
||
## Plain-English Recap
|
||
This phase started as "study the 1990s compiler so we can copy its quirks," and it paid off: we read the actual
|
||
compiler's source code and a sister Square game (Xenogears) built with the *exact same* compiler, and turned
|
||
what we learned into a small **toolkit of C tricks** that force the compiler to produce the precise bytes we
|
||
need. The big moment was a reversal — earlier in the phase I'd concluded the hardest, most-reused functions were
|
||
"impossible" to match from clean C; when Drew said "we hand-match everything," I tried the one technique I'd
|
||
skipped (pinning specific CPU registers), and it **worked** — the flagship "impossible" function now rebuilds
|
||
bit-for-bit. Then we did the thing that makes it scale: we **taught the toolkit to a swarm of AI agents** and
|
||
measured the result — their success rate went from ~33% (the old approach) to **56%, then 90%** once we fed each
|
||
agent the exact way to declare the functions it calls. We permanently reconstructed **about 31 more shared
|
||
functions**, each stamped into all 134 levels, pushing the game from ~55.5% to **~56.6%** rebuilt bit-for-bit.
|
||
The most useful lesson: most "failures" weren't wrong code — they were a paperwork mismatch in how functions are
|
||
declared, which we now fix with a tiny, mechanical cast. We also found ~18 functions the original team compiled
|
||
with optimizations *off*; their code is already correct and just needs its own build setting — a quick job for
|
||
next phase that unlocks all 18 at once. Everything still rebuilds perfectly; nothing broke. **Next phase scales
|
||
this up:** do the quick -O0 fix, make the gate auto-fix the paperwork, then run the agent waves in batches of 50
|
||
(learning between each), with optional deeper compiler research only for the last stubborn cases. The Wine
|
||
route stays parked — we already have the answer it would give.
|
||
|
||
## 🛑 Stop Here
|
||
PhaseEnd written; `CURRENT_PHASE.md` archived → `phase-ends/logs/Phase18.md` (R19). **Drew commits AND pushes**
|
||
this PhaseEnd + any uncommitted Phase-18 work (R6/R8 — the matching commits `commit:0152`..`commit:0156` are already
|
||
landed; this PhaseEnd + the archived log are the close). No Ghidra DB change this phase (R23 no-op — the
|
||
`db.*.gbf` churn is restart-noise, do NOT stage it). Gen2 continues — do **NOT** start Phase 19 here. Start a
|
||
**fresh session** (plan mode) for **Phase 19 — Scale the toolkit** (the backlog above; -O0 fix first, then
|
||
recovery-tooling, then the 50-target waves). Keep this file forever.
|