feat(phase-30 S46-6): recovery ladder banks +6; wire gate_stage into dedup_extend

- RECOVERY PASS A (wave residue): gate_stage over the 3 big-3 draft dirs recovered
  6 sites the bare gate rejected — func_80168664 x3, func_80168F40 x2, func_8012B77C
  x1. That is 6 of 19 PLUMBING = ~32%, matching the 16-39% range P29 measured. Batch 1
  goes 27 -> 33 of 60. R22 213/213 + tools-health green.
- HONEST SIZING (correcting my own claim): ~32% is NOT "a one-time fix for a ~50% draft
  loss". It moves the batch loss from 55% to 45%. Real and free; not transformative.
- WIRED (task 9): dedup_extend now gates through gate_stage (the ladder:
  canon_resident_calls -> cast_call_sites -> sig_unify -> harvest_verify) instead of
  harvest_verify verbatim. Its 142 candidates failed 0/142 with reasons 118 PLUMBING /
  21 CC1-FAIL / 3 DIFF — ~1 in 50 a real byte divergence, the rest declaration conflicts
  in the TARGET TU, which is exactly what the ladder reconciles.
  GATE_NO_ARITY=1 is forced for the child: gate_stage's arity pre-pass writes the
  fleet-shared engine_core.h BEFORE the gate and a failing draft can leave that edit
  behind — the F1 defect that broke 141 of 213 binaries in S45. The ladder's other rungs
  are draft-local. --ladder can be disabled to restore the old path.
- DOCTRINE (step 3): gate every wave with gate_stage, not bare harvest_verify. Batch 1
  needed a second manual pass only because I used the bare gate first.
- LEVERAGE METRIC CORRECTED (R14/R35): the behemoth ranking must use LIVE reach
  (unmatched sharers), not total sharers. func_80144B9C reads 770 ins x 141 = 108,570
  by total, but 138 of those are already banked — its true weight is 770 x 3 = 2,310.
  Same x134 over-count the cookbook records in §25; build_wave_args --rank live exists
  precisely for this and I used the wrong ranking. Remaining >=400 ins: 57 distinct
  functions / 77 live instances / 38,968 ins, reach ~1.35 => ~0.3% instr-weighted.
This commit is contained in:
Drew T
2026-08-10 10:43:44 -06:00
parent 0b303f7fe8
commit d54d0a899e
4 changed files with 233 additions and 13 deletions
+71 -2
View File
@@ -10495,7 +10495,29 @@ DEFINE_func_801685EC() /* dedup: shared engine-core @0x801685ec (src/shared) */
DEFINE_func_80168640() /* dedup: shared engine-core @0x80168640 (src/shared) */
INCLUDE_ASM("asm/ov_MAIN_012/nonmatchings/ov_MAIN_012", func_80168664);
extern Mat32 D_800AE620;
extern void RotMatrixX(int, void*);
extern void func_80048EAC(void *a0, void *a1);
extern s32 func_801670E4(s32 a0, s32 a1, s32 a2, s32 a3);
void func_80168664(void *arg0) {
s32 iVar3;
void *blk;
iVar3 = *(s32 *)((u8 *)arg0 + 0x34);
*(s32 *)((u8 *)arg0 + 0x1c) = 0x20;
*(s16 *)((u8 *)arg0 + 0x10) = 0x80;
*(s16 *)((u8 *)arg0 + 0x12) = 0;
*(s32 *)((u8 *)arg0 + 0x30) = 0x1800;
*(Blk20 *)((u8 *)arg0 + 0x38) = (*(Blk20 *)&D_800AE620);
blk = (u8 *)arg0 + 0x38;
((s32 (*)(s32, void *))RotMatrixX)(0x400, blk);
func_80048EAC((void *)(*(s32 *)((u8 *)iVar3 + 0x20) + 0x34), blk);
func_801670E4((s32)arg0, -6, -0x44, -0x18);
*(s16 *)((u8 *)arg0 + 2) = *(s16 *)((u8 *)arg0 + 2) + 1;
}
@@ -10677,7 +10699,54 @@ INCLUDE_ASM("asm/ov_MAIN_012/nonmatchings/ov_MAIN_012", func_80168D94);
DEFINE_func_80168EC4() /* dedup: shared engine-core @0x80168ec4 (src/shared) */
INCLUDE_ASM("asm/ov_MAIN_012/nonmatchings/ov_MAIN_012", func_80168F40);
typedef struct {
u16 f00;
u16 f02;
u16 f04;
u16 pad06;
u16 f08;
u16 f0A;
u16 f0C;
u16 pad0E;
u8 f10;
u8 f11;
u8 f12;
u8 pad13;
u8 f14;
u8 f15;
u8 f16;
u8 pad17;
u32 f18;
} S1_80168F40;
extern s32 func_80016A5C();
extern Mat32 D_800AE620;
void func_80168F40(void *a0)
{
S1_80168F40 s1;
Blk20 s2;
s32 pad[2];
s1.f00 = *(u16 *)((s32)a0 + 0x10);
s1.f02 = *(u16 *)((s32)a0 + 0x14);
s1.f04 = *(u16 *)((s32)a0 + 0x18);
s1.f08 = *(u16 *)((s32)a0 + 0x6);
s1.f0A = *(u16 *)((s32)a0 + 0xA);
s1.f0C = *(u16 *)((s32)a0 + 0xE);
s1.f10 = 8;
s1.f14 = 0xC0;
s1.f12 = 0;
s1.f11 = 0;
s1.f16 = 0x80;
s1.f15 = 0x80;
s2 = (*(Blk20 *)&D_800AE620);
s1.f18 = 0x50000000;
func_80016A5C(&s1, &s2);
}
+64 -2
View File
@@ -461,7 +461,47 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012b70c (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012b744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0);
extern s32 func_8004787C(s32 a0);
s32 func_8012B77C(s32 out, s32 a1, s32 a2)
{
register u32 packed __asm__("$20");
s32 dz;
s32 dx;
s32 dy;
register s32 t __asm__("$16");
s32 sn;
s32 cs;
s32 ang;
packed &= 0xFFFF;
dz = *(s16 *)((s32)a2 + 0xA) - *(s16 *)((s32)a1 + 0xA);
dx = *(s16 *)((s32)a2 + 0x2) - *(s16 *)((s32)a1 + 0x2);
dy = *(s16 *)((s32)a2 + 0x6) - *(s16 *)((s32)a1 + 0x6);
ang = ratan2(-dz, dx);
t = ang - 0x400;
t &= 0xFFF;
packed |= (u32)(t << 16);
sn = func_80047948(t);
cs = func_8004787C(t);
dz = (dz * sn + dx * cs) >> 12;
ang = ratan2(dy, -dz);
packed &= 0xFFFF0000;
packed |= (u32)(ang & 0xFFFF);
{
u32 addr;
__asm__("addu %0,%1,$zero" : "=r"(addr) : "r"(out));
*(u32 *)addr = packed;
}
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012b864 (src/shared) */
@@ -10829,7 +10869,29 @@ DEFINE_func_801685EC() /* dedup: shared engine-core @0x801685ec (src/shared) */
DEFINE_func_80168640() /* dedup: shared engine-core @0x80168640 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037", func_80168664);
extern void func_80048EAC(void *a0, void *a1);
extern s32 func_801670E4(s32 arg0, s32 arg1, s32 arg2, s32 arg3);
extern void RotMatrixX(int, void*);
extern Mat32 D_800AE620;
void func_80168664(s32 param_1)
{
s32 node;
node = *(s32 *)(param_1 + 0x34);
*(s32 *)(param_1 + 0x1c) = 0x20;
*(u16 *)(param_1 + 0x10) = 0x80;
*(u16 *)(param_1 + 0x12) = 0;
*(s32 *)(param_1 + 0x30) = 0x1800;
*(Blk20 *)(param_1 + 0x38) = (*(Blk20 *)&D_800AE620);
((s32 (*)(s32, void *))RotMatrixX)(0x400, (void *)(param_1 + 0x38));
func_80048EAC((void *)(*(s32 *)(node + 0x20) + 0x34), (void *)(param_1 + 0x38));
func_801670E4(param_1, -6, -0x44, -0x18);
*(s16 *)(param_1 + 2) = *(s16 *)(param_1 + 2) + 1;
}
+70 -2
View File
@@ -10491,7 +10491,28 @@ DEFINE_func_801685EC() /* dedup: shared engine-core @0x801685ec (src/shared) */
DEFINE_func_80168640() /* dedup: shared engine-core @0x80168640 (src/shared) */
INCLUDE_ASM("asm/ov_SC03_107/nonmatchings/ov_SC03_107", func_80168664);
extern void RotMatrixX(int, void*);
extern void func_80048EAC(void *a0, void *a1);
extern s32 func_801670E4(s32 arg0, s32 arg1, s32 arg2, s32 arg3);
extern Mat32 D_800AE620;
void func_80168664(s32 a0) {
s32 p;
p = *(s32 *)(a0 + 0x34);
*(s32 *)(a0 + 0x1C) = 0x20;
*(u16 *)(a0 + 0x10) = 0x80;
*(u16 *)(a0 + 0x12) = 0;
*(s32 *)(a0 + 0x30) = 0x1800;
*(Blk20 *)(a0 + 0x38) = (*(Blk20 *)&D_800AE620);
((s32 (*)(s32, void *))RotMatrixX)(0x400, (void *)(a0 + 0x38));
func_80048EAC((void *)(*(s32 *)(p + 0x20) + 0x34), (void *)(a0 + 0x38));
func_801670E4(a0, -6, -0x44, -0x18);
*(u16 *)(a0 + 2) = *(u16 *)(a0 + 2) + 1;
}
@@ -10673,7 +10694,54 @@ INCLUDE_ASM("asm/ov_SC03_107/nonmatchings/ov_SC03_107", func_80168D94);
DEFINE_func_80168EC4() /* dedup: shared engine-core @0x80168ec4 (src/shared) */
INCLUDE_ASM("asm/ov_SC03_107/nonmatchings/ov_SC03_107", func_80168F40);
typedef struct {
u16 f00;
u16 f02;
u16 f04;
u16 pad06;
u16 f08;
u16 f0A;
u16 f0C;
u16 pad0E;
u8 f10;
u8 f11;
u8 f12;
u8 pad13;
u8 f14;
u8 f15;
u8 f16;
u8 pad17;
u32 f18;
} S1_80168F40;
extern s32 func_80016A5C();
extern Mat32 D_800AE620;
void func_80168F40(void *a0)
{
S1_80168F40 s1;
Blk20 s2;
s32 pad[2];
s1.f00 = *(u16 *)((s32)a0 + 0x10);
s1.f02 = *(u16 *)((s32)a0 + 0x14);
s1.f04 = *(u16 *)((s32)a0 + 0x18);
s1.f08 = *(u16 *)((s32)a0 + 0x6);
s1.f0A = *(u16 *)((s32)a0 + 0xA);
s1.f0C = *(u16 *)((s32)a0 + 0xE);
s1.f10 = 8;
s1.f14 = 0xC0;
s1.f12 = 0;
s1.f11 = 0;
s1.f16 = 0x80;
s1.f15 = 0x80;
s2 = (*(Blk20 *)&D_800AE620);
s1.f18 = 0x50000000;
func_80016A5C(&s1, &s2);
}
+28 -7
View File
@@ -188,16 +188,37 @@ def write_drafts(binary, plan):
return d
def gate(binary, drafts_dir, chunk):
"""The EXISTING whole-binary byte-gate is the sole arbiter (G3/P9). Returns the banked fn set."""
def gate(binary, drafts_dir, chunk, ladder=True):
"""The whole-binary byte-gate is the sole arbiter (G3/P9). Returns the banked fn set.
LADDER (S46): this called `harvest_verify` VERBATIM, which is the bare gate with no recovery.
Measured cost of that: 0 of 142 extendable groups banked, and the classified reasons were 118
PLUMBING / 21 CC1-FAIL / 3 DIFF — i.e. ~1 in 50 was a real byte divergence and everything else
was a declaration conflict in the TARGET TU (`conflicting types for memcpy / ApplyMatrixSV /
D_800AE620 / func_8014C568`). `gate_stage` wraps the same gate in exactly the reconcile ladder
those need (canon_resident_calls -> cast_call_sites -> sig_unify -> harvest_verify), and it
carries the §156 reconcile LEDGER so a failed candidate cannot leave a fleet-shared edit behind.
Measured on the same failure class in the S46 wave residue: 6 of 19 PLUMBING recovered (~32%).
GATE_NO_ARITY=1 is set for the child: gate_stage's arity pre-pass writes the fleet-shared
engine_core.h BEFORE the gate, and on a failing draft that edit can survive — the F1 defect that
broke 141 of 213 binaries in S45 and made every later gate report `near`. The ladder's other
rungs are draft-local and safe.
"""
good = open(os.path.join(REPO, f"config/check.{binary}.sha")).read().split()[0]
vout = f".run/extend_verified.{binary}.txt"
fout = f".run/extend_failed.{binary}.txt"
cmd = [PY, "tools/harvest_verify.py", "--binary", binary,
"--out", f"build/{binary}/{binary}", "--good-sha", good,
"--drafts", os.path.relpath(drafts_dir, REPO), "--chunk", str(chunk),
"--verified-out", vout, "--failed-out", fout]
subprocess.run(cmd, cwd=REPO, timeout=7200)
if ladder:
cmd = [PY, "tools/gate_stage.py", "--binary", binary,
"--drafts", os.path.relpath(drafts_dir, REPO), "--no-propagate",
"--verified-out", vout, "--failed-out", fout]
else:
cmd = [PY, "tools/harvest_verify.py", "--binary", binary,
"--out", f"build/{binary}/{binary}", "--good-sha", good,
"--drafts", os.path.relpath(drafts_dir, REPO), "--chunk", str(chunk),
"--verified-out", vout, "--failed-out", fout]
env = dict(os.environ, GATE_NO_ARITY="1")
subprocess.run(cmd, cwd=REPO, timeout=7200, env=env)
p = os.path.join(REPO, vout)
return set(open(p).read().split()) if os.path.exists(p) else set()