From 00b6448f4ecc135a57ab787d2c7a0bdf51dbb10b Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Fri, 24 Jul 2026 23:50:38 -0600 Subject: [PATCH] =?UTF-8?q?fix(phase-29):=20dedup=5Fpropagate=20=E2=80=94?= =?UTF-8?q?=20the=20"overlay-local=20TYPE=20(the=20real=20cap)"=20skip=20w?= =?UTF-8?q?as=20a=20MISLABEL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compiles_standalone() returned a bare False and the caller attributed EVERY failure to the overlay-local type cap. The dominant real cause is undeclared FILE-SCOPE EXTERNS: the body references extern decls living outside the extracted def block (func_80174CB0: 22 of them; carrying them makes it compile cc1 rc=0). - compiles_standalone now returns (ok, stderr); the skip is classified by actual cause: "missing file-scope extern (CARRY-FIXABLE): " vs "overlay-local TYPE (the real cap)". - FLEET SIZING (--auto-from ov_SC01_077 --check-only): 7 skipped, ALL 7 carry-fixable, 0 genuine type-cap. Three of them (0x80142B2C/0x801535F4/0x80155800) are on the Phase-21 backlog list whose note ALREADY said "macro-extern-injection frees them x134 (~+0.3%)" -- never built, because the mislabel told every later session they were the type wall. A wrong label cost ~4 phases. - also: func_80174CB0's local Mtx_/Svec_ typedefs swapped for the canonical shared MATRIX/SVECTOR (byte-identical layouts); ov_SC07_006 still BYTE-IDENTICAL 7ca772be. - value behind the real fix: the 7 (~+0.3pp) + func_80174CB0 x138 (16,974 ins, ~+0.13pp), ~0 tokens. - _carry_externs itself is SPEC'd but NOT built here: it writes 138 overlay files (§63 class) and wants a fresh session with an R22 budget. func_80174CB0 (banked x1) is the test case. --- phase-ends/CURRENT_PHASE.md | 37 +++++++++++++++++++++++ src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c | 10 +++--- tools/dedup_propagate.py | 20 +++++++++--- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index fecff85675..b35ffc0607 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -3386,3 +3386,40 @@ conditional) · main-EXE/B9 + GLM/B6 + resident's 14 walls (P30) · behemoths B7 **Test: revert the 4 decl lines, re-gate. If it still banks, `recover_integration` should probe whether a stage is NEEDED before applying it** — an unrequested tier escalation is exactly the class R32–R35 exist to catch. + +- **🚨 2026-07-24 (SESSION-18) — THE PROPAGATION "TYPE CAP" IS A MISLABEL. Measured 7/7 CARRY-FIXABLE, + 0/7 actual type problems. This is why a fix Phase 21 already specified was never built.** + `dedup_propagate.compiles_standalone()` returned a bare `False` and the caller filed EVERY failure + under `"overlay-local TYPE (the real cap)"`. Reproducing the compile by hand shows the real cc1 + errors are **undeclared file-scope externs** — the body references `extern` decls that live OUTSIDE + the extracted def block. For `func_80174CB0`: 22 carried externs make it compile **clean** (verified: + cc1 rc=0). It is not a type problem at all; it is the exact gap Phase-27's + `family_remap._carry_macros` closed for file-scope `#define`s, one level over — **extern decls**. + **FIXED (safe, read-only classification):** `compiles_standalone` now returns `(ok, stderr)` and the + skip is classified by ACTUAL cause — `missing file-scope extern (CARRY-FIXABLE): ` vs + `overlay-local TYPE (the real cap)`. R32/R33/R34: a skip that discards its own diagnosis is invisible + work; one that ASSERTS the wrong cause is worse — it redirects every later session. + **FLEET SIZING (`--auto-from ov_SC01_077 --check-only`, touches nothing): 7 skipped, ALL 7 + CARRY-FIXABLE, ZERO genuine type-cap.** + | addr | missing externs | + |---|---| + | 0x8016A73C | ApplyMatrixSV, D_800AE620, RotMatrixYXZ, func_80048EAC | + | 0x80155800 | D_8011F730, func_8001382C, func_80146DB8, func_80146E98 | + | 0x80167540 | func_80146A6C, func_80146C3C, func_801670E4, rand | + | 0x801535F4 | func_8014CC28, func_8014ED28, func_8014FA04 | + | 0x8016F0AC | D_80126B58, func_80165770 | + | 0x80142B2C | func_80142C84, func_80143994 | + | 0x8014FE60 | D_801152A8 | + **⚠️ THE HISTORY MATTERS:** `0x80142B2C`, `0x801535F4`, `0x80155800` are on the **Phase-21 backlog's + "7 callee/data-plumbing capped fns"** list, whose note already read *"a macro-extern-injection (or + canonical-callee-sig embed) frees them ×134 (~+0.3%)"*. **Phase 21 diagnosed it correctly and it was + never built** — and in the meantime the mislabel told every subsequent session these were the type + wall. A wrong diagnostic label cost this project ~4 phases of a known, mechanical win. + **VALUE LOCKED BEHIND THE CARRY FIX:** these 7 (Phase-21 estimated ~+0.3pp) **plus `func_80174CB0` + itself** (123 ins × 138 = 16,974 ins ≈ **+0.13pp**), so ≈ **+0.4pp mechanical, ~0 agent tokens**. + **NEXT (spec, deliberately NOT built in this long session — it writes 138 overlay files, the §63 + disaster class):** add `_carry_externs` to `dedup_propagate` mirroring `family_remap._carry_macros` — + collect the file-scope `extern` lines matching the identifiers the body references, emit them INSIDE + the lifted `DEFINE_func_*` body (existing macros already carry externs, e.g. `DEFINE_func_80174C60`, + so the shape is established), dedupe against decls the target TU already has, then `--check-only` → + one gate → **R22 mandatory**. `func_80174CB0` is banked ×1 today and is the ready-made test case. diff --git a/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c b/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c index c19099729c..2132418ba2 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c @@ -8728,7 +8728,7 @@ DEFINE_func_80174C80() /* dedup: shared engine-core @0x80174c80 (src/shared) */ // `((s16 (*)(s32,s32,s32))f)(...)` func-ptr cast idiom already used by func_801749C8, // so the canonical s32 prototypes are kept and NEVER redeclared. // * D_80126940/42/44 are already `extern s16` at TU:160-162 — drop the three externs below. -// * Mtx_80174CB0 / Svec_80174CB0 are locally-unique names (== MATRIX / SVECTOR layouts) so +// * MATRIX / SVECTOR are locally-unique names (== MATRIX / SVECTOR layouts) so // they cannot collide with engine_types.h; they may be kept as-is or swapped for // MATRIX / SVECTOR when banking. // * THE OWN-SIGNATURE BLOCKER (the layer under the func_80012ABC one): the TU expands @@ -8745,8 +8745,6 @@ DEFINE_func_80174C80() /* dedup: shared engine-core @0x80174c80 (src/shared) */ #include "common.h" /* --- standalone-only scaffolding (bank-safe: names are unique to this function) --- */ -typedef struct { short m[3][3]; long t[3]; } Mtx_80174CB0; /* == MATRIX, 0x20 bytes */ -typedef struct { short vx, vy, vz, pad; } Svec_80174CB0; /* == SVECTOR, 0x08 bytes */ extern s16 D_80126940; extern s16 D_80126942; @@ -8764,9 +8762,9 @@ extern void func_8012F14C(s32 a0, s32 a1, s32 a2); s32 func_80174CB0(s32 param_1, s32 param_2) { s16 *pv = &D_80126940; - Mtx_80174CB0 mtx; - Svec_80174CB0 vec; - Svec_80174CB0 out; + MATRIX mtx; + SVECTOR vec; + SVECTOR out; *(s32 *)(param_1 + 8) = (s16)((s16 (*)(s32, s32, s32))func_80012C6C)((s32)*(s16 *)(param_1 + 8), (s32)*(s16 *)(param_1 + 0xc), 4); *(s32 *)(param_1 + 0x10) = (s16)((s16 (*)(s32, s32, s32))func_80012C6C)((s32)*(s16 *)(param_1 + 0x10), (s32)*(s16 *)(param_1 + 0x14), 4); diff --git a/tools/dedup_propagate.py b/tools/dedup_propagate.py index 542ce10578..579ee93463 100644 --- a/tools/dedup_propagate.py +++ b/tools/dedup_propagate.py @@ -345,11 +345,11 @@ def compiles_standalone(body_lines): "-fno-builtin", "-Dmips", "-D__GNUC__=2", "-D__OPTIMIZE__", "-Dpsx", "-D_PSYQ", "-D_MIPSEL", "-D_LANGUAGE_C", str(f)], capture_output=True, text=True) if cpp.returncode != 0: - return False + return False, (cpp.stderr or "cpp failed") cc1 = subprocess.run([str(CC1), "-quiet", "-O2", "-G0", "-mips1", "-mcpu=3000", "-mgas", "-msoft-float", "-fgnu-linker", "-o", "/dev/null"], input=cpp.stdout, capture_output=True, text=True) - return cc1.returncode == 0 + return cc1.returncode == 0, (cc1.stderr or "") # ---------------------------------------------------------------- main @@ -462,8 +462,20 @@ def main(): # then rejects any body using an overlay-local type NOT yet promoted to the header. if re.search(r'(\b(struct|union)\s+\w+\s*\{)|(\btypedef\b)', "\n".join(body)): n_local += 1; skipped["inline type def in body"].append(addr); continue - if not compiles_standalone(body): # uses overlay-local types -> can't lift mechanically - n_local += 1; skipped["overlay-local TYPE (the real cap)"].append(addr); continue + ok, why = compiles_standalone(body) + if not ok: + # SESSION-18: this bucket asserted "overlay-local TYPE" for EVERY failure, which is a + # mislabel — the dominant real cause is that the body references file-scope `extern` + # decls that live OUTSIDE the extracted block (func_80174CB0: 22 of them), exactly the + # gap Phase-27's family_remap._carry_macros closed for file-scope #defines. Name the + # causes apart so the queue can be sized honestly (R32/R33). + undecl = sorted(set(re.findall(r"`([A-Za-z_]\w*)' undeclared", why))) + if undecl: + n_local += 1 + skipped["missing file-scope extern (CARRY-FIXABLE): " + ",".join(undecl[:4])].append(addr) + else: + n_local += 1; skipped["overlay-local TYPE (the real cap)"].append(addr) + continue plan.append(dict(addr=addr, src=src, hash=h, body=body, members=members)) if n_local or n_nondef or n_lowreach: