mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 05:56:00 -04:00
eb2e72328bbbab3187eb55336d9a2d989504ff31
204 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
eb2e72328b |
fix(phase-30 T6): byte-neutral decl conforms unblock the SC07 EXTEND lane
The dedup_extend SC07 lane banked 0/36. Captured every failure's own compiler error rather than guessing: 5 PLUMBING (declaration conflicts) + 4 DIFF per binary, and the PLUMBING set reduces to 4 distinct symbols repeated across all four binaries. Fixed at the lowest available blast radius, each byte-neutral BY CONSTRUCTION and proven by R22: - func_80146C3C (8 of 36): T2, but 1 token. DEFINE_func_8016A08C / DEFINE_func_8016A1CC declared it `(void)` while the SC07 TUs declare `(u8 *a0)`. Both macros already CAST at the call site, so the prototype is codegen-irrelevant -> relax to `()` (no-prototype). Measured first: all 4,020 fleet decls are (void)/()/(u8*)/(u8 *a0) — no default-promotion param anywhere, so `()` is compatible with every one of them (the gcc-2.7.2 `()` dead-end needs a promoting param; there is none). - func_8014F4C0 (4 of 36, self-axis), D_80126CC4 (3), func_8012E5CC (1): T1 binary-local. Conformed the SC07 decls to the fleet-canonical form. Every one has ZERO uncast uses in its TU (verified per file), so the decls were pure splat boilerplate with no codegen effect. Deliberately NOT touched: engine_core.h beyond those 2 lines. The §29 law is about BULK header edits (the 2,046-file sed that still didn't build); 2 targeted macro lines with a measured compatibility argument is not that. R22 clean-fleet: make clean && extract-all && check-all -> 140 passed, 0 failed of 140. Enabling change only; no function banked in this commit. Method note (mine, recorded): I read `corpus.stubs` while `make extract-all` was mid-flight and got garbage — R32's coverage assertion refused to answer instead of returning a wrong stub set. A measurement taken during a rebuild is not a measurement (S27's law, re-earned). Also: `nohup CMD &` inside a backgrounded Bash call makes the harness signal completion of the WRAPPER, not the campaign — the R22 "finished" at 63/140. Waited on `pgrep -x make` instead. |
||
|
|
6dab5a446b | feat(phase-30 UC): func_80159A20 + func_80139BE0 banked via gate_stage ladder (13,386 ins) | ||
|
|
3b3accd5a2 | feat(phase-30 UC): func_80163764 banked via targeted decl reconcile (compiler-named edits only) | ||
|
|
b5362c7b7f |
feat(phase-30): the -O0 cluster HARVEST — 1,364 banks for ZERO agent tokens; fleet 92.71->93.09% fn / 88.3->88.6% instr / 78.7->79.3% distinct
The payoff of routing the cluster to -O0 (commit:1270). These functions were ALREADY
CRACKED in ov_SC01_077 and could not be banked anywhere else purely because every
destination file compiled -O2. With the destinations now -O0, they template in
deterministically -- no drafting, no agents.
dedup_propagate --recover 0x8013C360 (h_exact x138) -> 137 overlays byte-identical
family_sweep --hseq 10 variant families -> 1,227 banked / 133 failed (90%)
1360 staged across 136 groups
------------------------------------------------------------------------------------
1,364 new banks
FLEET: fn-count 92.71 -> 93.09% · instr 88.3 -> 88.6% · distinct-code 78.7 -> 79.3%
(71,756 / 87,459 unique fns; +1,162 unique). dedup 1904 -> 1905 groups, 0 failed;
C1 coverage 240496/240496. 0 NON_MATCHING in any default build (G4).
R22 CLEAN-FLEET: extract-all 139/139 (+main); check-all 140 passed, 0 failed of 140.
--recover WAS LOAD-BEARING (SS75): without it dedup_propagate took its historical
all-or-nothing branch -- one failing overlay (the SOURCE, ov_SC01_077) dropped the whole
function and it printed "all candidates dropped", which reads exactly like a wall. Reading
the exclusion code instead of believing the message showed the remedy: --recover excludes
only that overlay (kept x1 with its own inline match) and propagates to the other 137.
The two has_mid_jr families in the cluster were REFUSED BY DESIGN, not attempted (SS53
interlock): 0x8013C0F8 (154 ins) and 0x8013C414 (329 ins), ~137 members each = ~466
members queued behind the jtbl carve path they actually need, rather than a fake 0% from
the wrong tool.
REMAINING in the cluster: the 133 sweep failures + the 2 jr families + the 3 addresses
never cracked anywhere (0x8013B83C, 0x8013BD74, 0x8013C08C) -- the last are genuine
drafting work, now finally possible since their TU is -O0.
|
||
|
|
0130fb340a |
feat(phase-30): wave-4 resumed 10/10 MATCH banked + h_exact leg (14 propagated); R22 140/140
The 12 agents killed by the usage-limit pause were resumed and ALL returned MATCH (2 had already banked from their partial drafts, so 10 ran). h_exact propagation leg completed over all 112 banked exemplars: 14 propagated, 42 benign skips (h_seq tier, correctly routed away per §123), 0 failures — the 0x801466F0 'halt' was a third benign-refusal phrase, not a partial write. fn-count 92.61 -> 92.67% | instr 88.2 -> 88.3% | distinct 70,581 -> 70,590 unique fns. |
||
|
|
159317d3fe |
feat(phase-30): T3 wave-1 — 8 cores banked + 4 propagated fleet-wide; R22 140/140 (fn-count 92.00 -> 92.16%)
Ultracode wave of 14 agents over fresh reach-138 cores: 14/14 match_one MATCH, 8 accepted by the whole-binary gate (the §52b law reproduced exactly). Propagated per-function (the incident fix): 0x8012E014, 0x80151C54, 0x8012F49C, 0x80151B98 -> +573 instances. R22 clean-fleet 140/140; instr 87.5 -> 87.7%, fn-count 92.00 -> 92.16%, distinct 69,828 -> 69,836. The other 4 banked cores are h_seq (PURE/IMM) families: dedup_propagate is h_exact-only, so its 'reach<2' / 'not self-contained' refusals were statements about the TOOL's tier, not the functions -> cookbook §123 (the §53 carve-law generalized to the propagation-tier axis) + a routing table. They bank via family_sweep --hseq next. |
||
|
|
ceae8bb4cd |
feat(phase-29): T97 — func_80151944 138/138; the "three-edit job" was ONE edit
- The last big NAMED blocker, costed across four checkpoints as §112 header + §20 call-site cast + a scripted §99 pass over 2,022 overlay-local decls. Probing first showed two of the three were unnecessary: the conflict is entirely between DEFINE_func_80151924()'s own forward-decl (extern s32 func_80151944(void)) and the byte-true definition (void f(void *a0)), four lines apart in the assembled TU. The 2,022 decls live in OTHER TUs and never entered it. - ONE 4-line edit in engine_core.h: decl -> byte-true, call site -> ((s32 (*)(void))f)() so the caller's codegen is unchanged. rtu_match: conflicting types -> MATCH (15 ins). Sweep 138/138. - Family 0x80131eec fully closed: 149 (T87) + 138 (T97) + 1 immediate-refusal = all 288 members. - SHARED-HEADER RISK VERIFIED, NOT ARGUED: engine_core.h is included by all 138 overlays, so §20 cast-folding is a hypothesis. Per-binary gates 138/138 are necessary but not sufficient; the fleet check is the one that counts. R22 clean-fleet 140/140 + tools-health RC=0 (corpus 0 PHANTOM/0 TRUNCATED, cdecl, audit-binaries, dedup 1886/0, C1 239604/239604). - METRICS: fn-count 91.96 -> 92.00% (+138, exact) · instr 87.4 -> 87.5% (+2,070) · distinct +72. - COSTING LESSON: the estimate came from reading the symptom (2,022 decls of this name exist) instead of probing the failure (which decl actually conflicts). Probe before COSTING, not just before scaling. |
||
|
|
14bc520c96 |
fix(phase-29): engine_core.h — §99 no-prototype for func_80147364 (sidesteps a 4,021-site conform)
Item 3, and the cheap route won. conform_decls' dry run priced the direct fix and warned it off:
byte-true def : void func_80147364(u16 param_1, u16 param_2)
4,021 decl sites: 2,030 (u16,s32) + 1,983 (u16 a0,s32 a1) + 4 byte-true + 4 (u16,u16)
⚠ SCALAR-NARROWING (s32 -> u16) — NOT caller-neutral; argument promotion changes at every call
site, so callers emit different code (byte-proven on func_80175DA8)
So conforming 4,021 sites would likely trade a PLUMBING failure for a BYTE failure. The §99
no-prototype form on the HEADER is compatible with both the byte-true definition and the existing
(u16, s32) prototypes, and touches 9 sites instead of 4,021:
extern void func_80147364(u16, s32); -> extern void func_80147364();
Verified: header change ALONE, no src change, R22 clean-fleet 140 passed, 0 failed of 140.
This is the T67 failure resolved — that batch failed 2/140 with because it corrected the header's TYPES while 272 TUs disagreed. Dropping the
prototype instead disagrees with nobody.
|
||
|
|
86c315ec08 |
fix(phase-29): engine_core.h — §99 no-prototype for the three CALLED ARITY functions
Item 1's payoff. §113's call-vs-address re-check found func_80144B14 was the ONLY address-taken one (already fully retyped, T72); func_8013BD34 / func_8014358C / func_8017D808 are genuinely CALLED, so their arity IS constrained by the macro's own call site and the full retype is unavailable. §99 no-prototype is the fix: `extern void func_X();` accepts the macro's fixed-arity call AND the definition's differing arity, and a no-prototype call passing the same arguments generates the same code. extern void func_8013BD34(void); -> extern void func_8013BD34(); (def takes s32 a0) extern void func_8014358C(void); -> extern void func_8014358C(); (def takes s32 param_1) extern void func_8017D808(s32, s32); -> extern void func_8017D808(); (def takes void *a0) Verified in one step per the T48 discipline: the header change ALONE, no src change, R22 clean-fleet 140 passed, 0 failed of 140. Batched three because the technique was the variable, not the targets — a bisect over three is cheap if it fails. |
||
|
|
df86fcce50 |
fix(phase-29): engine_core.h — func_80144B14 declared int(int), not void(void)
The ARITY blocker did not apply: DEFINE_func_* does not CALL func_80144B14, it takes its ADDRESS (`*(s32 *)((s32)a0 + 0xDC) = (s32)&func_80144B14;`). There is no call site to break, so the FULL correction is available rather than the §99 no-prototype workaround. That is a refinement the audit needs: the ARITY precondition asks whether the macro's own call site would break, but an address-taken use has no call site. Over-fires on that shape. §85: 0 consumers, so the void->int return widening is byte-neutral. Verified in two steps (T48 discipline): header change ALONE, no src change, R22 clean-fleet 140 passed, 0 failed of 140. Fleet-shared (§61/§63), R22 mandatory. Probe target switched from func_8013BD34 on measured evidence: that one's definition lives in ov_SC07_010_o0.c, and _o0 families sweep ~1/137, making it a poor test of an unproven technique. func_80144B14 is the same class, 137 stubs, not -O0, with a real 34x137 family. |
||
|
|
0c5df25faf |
feat(phase-29): T67 — audit_header_sigs.py; 61 header decls contradict byte truth, 6 corrected
THE TOOL (tools/audit_header_sigs.py, cookbook §112). A DEFINE_func_*() macro forward-declares the
functions its body calls, and that decl is visible in EVERY overlay instantiating the macro — so when
it disagrees with the byte-true definition the whole family becomes untemplatable and the failure
wears a compiler wall's clothes. Three such were found ONE AT A TIME earlier this phase
(func_80156044, func_8016163C, func_8014D610), each worth ~137 members, each costing a
diagnose/fix/re-sweep cycle. This audits all of them in one pass: parse every `extern func_X(...)` in
src/shared/*.h, find every DEFINITION in src/**/*.c (via §110's _def_head_at, not "ends in ;"),
compare with cdecl, and report only where NO definition agrees — one overlay disagreeing is loose
typing (§16/T49), all of them disagreeing means the header is the outlier.
RESULT: 3,043 decls across 1,023 functions; 265 have definitions; 61 contradict every one. The top 10
are full-fleet families (137/136/134 live stubs, 1,366 total), all with an unambiguous byte truth.
APPLIED: 6 functions / 11 decl sites, R22 clean-fleet 140 passed, 0 failed of 140 —
func_80138DE0, func_80146750, func_80161374, func_80161774, func_80161888, func_801778A8.
TWO PRECONDITIONS THE AUDIT DOES NOT YET CHECK, both found by gating rather than by reasoning:
1. ARITY. func_80144B14 / func_8013BD34 / func_8014358C declare (void) but are DEFINED with one
parameter. Correcting the header would break the macro's OWN call site (too few arguments), so
they need the §99 no-prototype treatment instead. Excluded before the batch, by measurement.
2. OTHER IN-SCOPE DECLS. The first batch of 7 FAILED the gate 2/140 with `conflicting types for
func_80147364` — the overlays' own TUs declare it the old way (9 header sites rewritten, but
src/ov_*/…:347 disagrees). A header correction is only safe when no other in-scope declaration
disagrees; that one additionally needs a conform_decls pass. Excluded; the other 6 then gated
140/140 clean.
The gate caught the bad batch immediately and the culprit was found by reading one object's real cc1
output rather than by a 7-way bisect (7 fleet gates = ~2.5h; one serial compile = seconds).
|
||
|
|
3c380fec83 |
fix(phase-29): engine_core.h — func_8014D610 declared s32(s32,s32,u16*), not void(s32,void*,void*)
Same class as func_80156044 and func_8016163C: the shared header contradicted the byte truth. The
exemplar's banked definition is `s32 func_8014D610(s32 param_1, s32 param_2, u16 *param_3)`
(ov_SC07_006_jr_80140608.c:4576); DEFINE_func_8014D438 declared
`void func_8014D610(s32 a0, void *a1, void *a2)`.
That mismatch is what made --fix-def-sig retype param_3 to `void *` while the body does
`param_3[0]` -> `void value not ignored as it ought to be` (T61's param-use guard now refuses it,
naming the header as the real fix — this is that fix).
§85 sized first: 0 callers consume the return. The macro's call site passes `s16 buf1[4]`/`buf2`
into the s32/u16* params — same 4-byte values in $a1/$a2, so the retype is a warning, not a codegen
change.
Verified in two steps (T48 discipline): the header change ALONE, no src change, R22 clean-fleet ->
140 passed, 0 failed of 140. Fleet-shared (§61/§63), so R22 was mandatory.
NOTE: ov_SC07_006_jr_80140608.c:4529 records an earlier, DIFFERENT resolution of the same conflict —
a per-overlay de-macroized local decl ("do NOT re-macroize"). That remains correct and untouched;
this fixes the shared decl the other 137 overlays see.
|
||
|
|
2d91ed54fb |
fix(phase-29): engine_core.h — func_8016163C declared s32(s32,u32), not void(void*,s32)
The shared header contradicted the byte truth. The exemplar's banked definition is `s32 func_8016163C(s32 arg0, u32 arg1)`; both DEFINE_ macro decl sites said `void func_8016163C(void *a0, s32 a1)`. That mismatch is why the family could not template, and it is what made --fix-def-sig DEMOTE the return to void — gcc then deleted the computation feeding it and the draft compiled to 58 instructions against a 78-instruction target (T62's self-inflicted SIZE-MISMATCH). §85 sized first: conform_decls.consumers(func_8016163C) = 0 — both macro call sites discard the return (`func_8016163C(a0, func_801615C4(a0, 0));`), so the return-axis flip is byte-neutral. Verified in two steps (T48 discipline): the header change ALONE, no src change, R22 clean-fleet `make clean && extract-all && check-all` -> 140 passed, 0 failed of 140. Fleet-shared edit (engine_core.h reaches all 138 overlays), so R22 was mandatory (§61/§63). |
||
|
|
51bac9f3e6 |
fix(phase-29): engine_core.h — DEFINE_func_80155FF8 declares func_80156044 void, not int
The exemplar's own @stuck note asked for this (ov_SC01_077_jr_80154C24.c L1349-1350): the handwritten func_80155FF8 wrapper calls func_80156044 via inline-asm `jal`, so nothing consumes the return, and ov_SC01_077 already declares it `void` inline — the MACRO was the outlier. §85 precondition measured before touching it: conform_decls.consumers(func_80156044) = 0 callers consume the return, so the return-axis flip is byte-neutral. Verified in two steps (T48 discipline): the header change ALONE, with no src change, R22 clean-fleet `make clean && extract-all && check-all` -> 140 passed, 0 failed of 140. Fleet-shared edit (engine_core.h reaches all 138 overlays), so R22 was mandatory (§61/§63). |
||
|
|
f3e8317bd1 |
feat(phase-29): T49 — func_80135260 x4 siblings + the 3,744-site decl conform
The §53 carve path banked only 4 of 137 siblings, ALL of them SC07 — the exact signature func_80177DA8 showed before its §99 fix, so the same lever applies. - jtbl_family_bank func_80135260: 4 BANKED / 133 gate-fail. The 4 are SC07 overlays. - conform_decls dry run confirmed the class: byte-true def is `s32 func_80135260(s32, s32, s16 *, s16 *)` but 3,744 declaration sites say `(s32, s32, s32, s32)` — params 3 and 4 declared s32 where the byte truth is s16 *. Return type agrees, so the §85 return-axis precondition does not fire. - Applied: 3,744 sites rewritten across 2,021 files; the tool's R32 assertion reports "non-canonical declarations remaining: 0 OK (axis complete)". It correctly SKIPPED the 5 DEFINING TUs (the 4 SC07 banks + ov_SC01_077) — a defining TU owns its own declarations, since per-overlay byte-true signatures legitimately differ under §16 loose typing. - This touches src/shared/engine_core.h, so it is FLEET-SHARED and R22 was mandatory (§61/§63): R22 clean-fleet 140 passed, 0 failed of 140. Also recorded: jtbl_family_bank's [gather_externs] warning named func_80135D20 as an undeclared referenced symbol, but that symbol appears ONLY in the draft's header COMMENTS (lines 3 and 29) — a comment-scanning false positive, same class as the Phase-19 gen_harvest_targets garbled-hint bug. It was not the cause of the 133 failures. Next: re-run the carve path for the remaining 133 siblings now that the decl axis is conformed. |
||
|
|
05430eb26e |
feat(phase-29): T32 — NEAR-6 crack wave banks 4 reach-138 cores ×1; R22 140/140
Ultracode fan-out (12 agents, 1.70M subagent tokens): 6 crack agents, one per NEAR target, each carrying its byte-measured residual + T31's disproved routes, then a distill agent per target that adversarially re-checks the claim. - BANKED ×1 (whole-binary gate, gate_stage --no-propagate per §55b law 1): func_80140958 (260 ins), func_80177B5C (147), func_80132F40 (72), func_8012E364 (67). Every agent MATCH claim was RE-MEASURED BY ME with match_one before it was believed (G3/P9: match_one is a candidate, a bank is the whole-binary gate), and verified against the SOURCE not gate_stage's accumulating verified-list (§55b trap 4). R22 clean-fleet: 140 passed, 0 failed of 140. - engine_core.h moved by exactly one byte-neutral arity fix (void -> no-proto) = fleet-shared, so R22 was mandatory (§61/§63), not the per-binary gate. - func_80140D68 MATCHes standalone but NOT whole-binary — the §30a integration class; its distill agent named the likely cause in advance (DEFINE_func_* extern must return u32*, not void). - func_80176734 217 -> 13 with the instruction count now EXACT (371/371). cse_expr.md §H's "no bank, 5 permuter-shaped clusters" is BYTE-REFUTED: 4 of 5 were steerable from C; the -1 length delta was a combine/LOG_LINK effect (flow.c links a SET only to the next use in the SAME bb), not frame pressure. Two coupled allocator/sched ties survive. - FOUND: docs/gcc-2.7.2-map/sched.md cites gcc-2.8.1 line numbers (birthing_insn_p 2498->2469, adjust_priority 2534->2507, potential_hazard 1345->1318, schedule_select 2646->2616) — surviving papermario numbers Phase 23's source-version correction never swept. One is LOAD-BEARING: §1.7 and §S12 claim the S2 boost needs SET(REG_pseudo,...) so pins must be removed; sched.c:2477 tests only GET_CODE(SET_DEST)==REG with NO pseudo check, discriminator is reg_n_sets==1 (2490). Verified by me against tools/reference/gcc-2.7.2, not taken from the agents. Map edits owed (next task). - MY DEFECT: all 6 agents shared one scratch dir (1,452 files); deliverables are uniquely named and verified intact, but short-named scratch could collide. Per-agent subdirs next wave. |
||
|
|
599a33c056 |
feat(phase-29): wave22 — 5 exemplars banked from an 18-target Ultracode wave (R22 140/140)
THE WAVE: 18 h_seq family exemplars (~255k templated instructions), one agent each, drafting from
cached Ghidra-C + the target .s with canonical callee/data decls resolved from the real TU scope.
Result 12 MATCH / 6 NEAR / 0 FAIL (2.59M subagent tokens). No agent touched the tree — the
draft-only constraint held (verified: git status clean across src/config/tools/include).
BANKED 5: func_80148E54, func_80171B4C, func_8014A738, func_8012A328, func_80163534.
R22 clean-fleet 140 passed / 0 failed of 140.
A BUG I INTRODUCED EARLIER TODAY, FOUND BY WORKING THE 12->5 GAP. My block-scope descent in
reconcile_tu fed ordinary STATEMENTS to cdecl.parse; some parse without raising into a declarator
with an EMPTY base type and the statement's symbol as its name. That fake row overwrote the genuine
plan entry for the same symbol, so the span rewrite landed on a statement instead of the declaration
— and my own R32 completion assertion still PASSED, because the conformed text appeared somewhere.
Byte-witnessed on D_80126B5C: planned twice ("draft 's32'" and "draft ''"), output unchanged, gate
PLUMBING. Now block-scope rows are accepted only from a real `extern` with a non-empty base type.
TWO BANKS CAME FROM TODAY'S OWN FINDINGS:
- func_8012E014's single 0-arg call site took --cast-zero-arg-calls (built this morning for
func_801789AC's 138 sites).
- §99 HELD A THIRD TIME: K&R conversion dissolved func_80163534's s32->u16 narrowing across 1,072
declarations, leaving only a caller-neutral pointer change on the last param.
STILL UNBANKED (measured blockers, not guesses): func_8013B6A0 + func_8013B598 CC1-FAIL in the _o0
split; func_80133298 + func_80135260 + func_8012E014 genuine DIFF (match_one MATCH did not hold
whole-binary = TU-context); func_80138C60 parse-order (an extern referencing a body-local typedef
declared after it); func_80177DA8 prototype-vs-K&R mismatch.
|
||
|
|
ee55bd5cae |
feat(phase-29): func_801330E0 banked — conform_decls taught to read K&R definitions
THE GAP: conform_decls could not parse a K&R definition at all — it exited "no DEFINITION found, refusing to guess". Honest, but §43 (a narrow param declared K&R-style, producing the in-place `sll $a2,$a2,16` tell) is a documented, load-bearing idiom here for exactly the narrow-param class. So the tool was silently refusing the drafts that most need it: a whole idiom family read as "nothing to conform" (R32 coverage). THE SUBTLE PART IS PROMOTION (C89 6.3.2.2). A K&R definition promotes each narrow parameter, so a prototype in scope must declare the PROMOTED type or gcc rejects the pair with `argument 'x' doesn't match prototype`. That is why the fleet prototype reads `s32 a2` for a parameter the definition declares `s16` — and why emitting the declared (unpromoted) type would RE-CREATE the narrow-param conflict this tool exists to remove. The parser now promotes s8/u8/char/s16/u16/short -> s32 and float -> f64, pointers untouched, and reports (R32) any K&R param with no declaration. RESULT: byte-true signature read as `void func_801330E0(void *, s16 *, s32)`; the only real change vs the fleet's 973 declarations was param_1 `s16 *` -> `void *` (a pointer shape, caller-neutral). 973 sites / 973 files rewritten, axis complete. Gate: verified 1 / failed 0, d19c9580 BYTE-IDENTICAL. R22 clean-fleet 140 passed / 0 failed of 140. Reach 138 x 110 ins = 15,180 templated instructions unlocked for the family sweep. |
||
|
|
ad57c16e61 |
feat(phase-29): func_8014CF04 + func_8015D1B8 banked; conform_decls had 3 defects R22 caught (§98)
THE BANK: the T14 PLUMBING census showed func_8014CF04 blocking THREE drafts at once. Conforming its
decl axis banked func_8014CF04 + func_8015D1B8 (func_80135260 is a genuine DIFF, agreeing with its
independent SESSION-21 diagnosis). R22 clean-fleet 140/140; report fail-closed green (dedup 1886/0,
0 NON_MATCHING). fn-count 317,896 -> 317,898; distinct 66,110 -> 66,111.
BUT THE AXIS WAS A 1,748-FILE T2 WRITE SET (the --check per-form counts read "1"), and R22 came back
139/140 -- TWICE -- on a change the per-binary gate called BYTE-IDENTICAL. Three defects (§98):
1. THE REGEX CROSSED NEWLINES. `[^;]*` matches '\n', so a match starting at a DEFINITION line ran
past the `{` to the first `;`, swallowing `s32 func_8014CF04(...) {` PLUS the register pin on the
next line and replacing both with a prototype -> undefined reference. Fixed to `[^;{\n]*`: a
definition is now unmatchable by construction.
2. IT REWROTE INSIDE COMMENTS (H5, 3 lines). Now scans cdecl._mask() and rewrites by SPAN (R33 --
that length-preserving primitive already existed for exactly this).
3. THE REAL CAUSE -- IT ASSUMED ONE SIGNATURE FITS THE FLEET. ov_SC07_006 carries its own banked
definition with a DIFFERENT byte-true signature ((s32,s32,void*) vs (s32,void*,void*)), under a
decl marked "per-overlay-local decl (byte-true sig); do NOT re-macroize". That is the Phase-16
loose-typing wall inside a tool that structurally assumes it away. NEW RULE: a TU that DEFINES the
function owns its own declarations; a fleet axis is meaningful only for CONSUMING TUs. This grows
more common as banking proceeds -- every overlay that banks a function becomes an exception.
Then the R32 completion assertion cried wolf on its own by-design skip ("HALF-AXIS -- DO NOT BUILD"
for a complete rewrite): an assertion must be exact about its DOMAIN, not just its condition. Scoped
to consuming TUs -> 1,747 sites, 1 excluded by design. Also hardened to PLAN -> VALIDATE -> WRITE;
the refusal path had aborted mid-write while claiming nothing was modified, creating the very
half-axis §85 calls a guaranteed break.
META (R22's premise, re-earned): after fixing defect 1 I EXPECTED R22 to pass; it failed again for an
unrelated reason, and an individual `make build` of the failing binary SUCCEEDED by reusing objects
the clean run rebuilds. An incremental pass does not refute a clean-tree failure.
|
||
|
|
1670fe293c |
feat(phase-29): func_8016B6BC 0/137 -> 137/137 — it was a TYPE-CARRY failure, not a wall
The family that failed its sweep twice (once in the 274-member batch, once after the §91 guard) and looked like the §86 bimodal 'some families just don't template' case. It was not. DIAGNOSIS (§59 + §93): spliced ONE sibling and read cc1 directly. It reported `c`, `v`, `off` undeclared — ordinary locals that ARE declared in the remapped body. cc1 says 'undeclared' because it aborted the declaration block at an unknown TYPE and every later declaration fell out with it. Read the FIRST error, not the loudest: a visibly-declared variable reported undeclared means suspect its type. THE LIFT MUST BE TRANSITIVE. Lifting the type the body names directly (M8_8016B6BC) changed nothing — still 0/137. The real set was four, found by following each definition's own references: M8_8016B6BC -> Prim_8016B6BC -> Vtx_8016B6BC (named only inside Prim's body) -> DVec_8016B6BC. lift_types.py --apply, byte-gated ALONE first (neutral, d19c9580 unchanged), then swept. RESULT 0/137 -> 137/137, zero failures. R22 clean-fleet 140/140. cookbook §94. Cost of not diagnosing: this family sat recorded as 'doesn't template' across two sessions. Pointed at one sibling's real stderr it took under an hour and was worth 137 members. |
||
|
|
2985f306d9 |
feat(phase-29): func_80179B74 banked — conform_decls cleared it as pointer-type-only (R22 140/140)
1,600 decl sites across 523 files, in THREE different forms (s16 *a0 / short * / short *p), conformed to the byte-true 'void func_80179B74(u16 *p)'. conform_decls ALLOWED this one: the arity is unchanged, so no 0-arg call site can break, and the return is unchanged, so §85's precondition does not apply. Gated BYTE-IDENTICAL; R22 clean-fleet 140/140. The tool has now refused one axis (func_8015B950, correctly — it would have broken 138 binaries) and cleared another (this one, correctly). Both verdicts held under R22. |
||
|
|
f459f53083 |
feat(phase-29): func_8015B950 banked — ONE cast unlocked the 925-site axis that broke 138 binaries
The same axis that broke 138 of 140 binaries an hour ago now lands clean, because conform_decls' NEW arity guard located the actual obstruction instead of leaving me to absorb it by hand. THE OBSTRUCTION WAS ONE LINE. Conforming `extern s32 func_8015B950(void)` -> `(s32 arg0)` turns every 0-arg CALL SITE into `too few arguments`. My hand attempt assumed those were spread across the 926 TUs and would need 926 casts (the func_8012AAAC precedent, where it really was 137 separate sites). They are not: there is exactly ONE call, in `src/shared/engine_core.h`'s `DEFINE_func_8015BEE4()` macro body — expanded into all 926 TUs by the preprocessor. func_8015BEE4 is a THUNK: `return func_8015B950();` with $a0 passing straight through from its own caller. So the 0-arg call shape is byte-CORRECT and must be preserved, not fixed — `return ((s32 (*)(void))func_8015B950)();` keeps it exactly (§17a-1; gcc folds the cast of a known symbol to a direct jal, and the s32 return is unchanged so the thunk's value still flows). Sequence: 1 cast -> conform_decls --apply (925 sites, R32 completion assertion: 0 remaining) -> gate BANKED byte-identical -> R22 clean-fleet extract-all 139/139, check-all 140 passed / 0 failed. The draft's 2 callee-decl conflicts (func_801725A4, func_80147078) dissolved with the axis. Worth 37,398 templatable ins; the ×137 family sweep is next. |
||
|
|
2cc49d0310 |
feat(phase-29): SESSION-21 — func_8012AAAC banked via the §81 carve chain (R22 140/140)
The first jtbl-routed bank of the session, and it validates the whole chain end-to-end:
1. jtbl_carve SPLIT-TABLE repair (this session): jtbl_801D7FB0 28 -> 50 words (112 -> 200 B),
authorized by func_8012AAAC's own `sltiu 0x32`.
2. NEW FIX — SINGLE-TABLE PREDECESSOR: adding a second table to a subseg whose existing carve was
single-table lost the FIRST table's start entirely (new_offs has only the new one;
overlay_jtbl_addrs cannot see the old one because its owner is banked and extract PRUNED the
stub .s; and single-table carves persist no tables= to rebase). The span then failed its own
validator with "first must equal the span start" — the invariant naming the missing entry.
A single-table carve spans exactly its one table, so ITS SPAN START *IS* THAT TABLE'S START:
inference, not persistence, so it also works for spans carved before tables= existed. This is
the RECOVERABLE half of the documented func_8013F350 lesson (that one was a pre-§8e merged
DOUBLE — two tables, no record, genuinely unrecoverable).
Result: ov_SC01_077_a JTBL_PADS := 0,0 tables=+0x0,+0x14. Carve alone byte-gated BYTE-IDENTICAL
BEFORE the bank was attempted (§81 step 2).
3. ARITY axis, all-or-nothing: 1,244 decl sites / 1,240 files `(void)` -> `()` + an R32 completion
assertion (old-form remaining: 0).
4. ONE call-site cast: the definition lands at line 811 and a 0-arg call sits at 822, so gcc sees
the prototype and rejects it — `((void (*)(void))func_8012AAAC)()` (§17a-1; gcc folds the cast
of a known symbol to a direct jal). Only 1 of the 1,386 fleet-wide 0-arg call sites needed it:
the others see only the `extern ()` decl, which permits a 0-arg call.
DIAGNOSIS NOTE: the failure read CC1-FAIL with only a warning visible under make. Running the
pipeline stage-by-stage (cpp | cc1 | maspsx | jtbl_rodata_pads | as) put it on cc1 rc=33, and cc1's
own stderr named it exactly: "too few arguments to function func_8012AAAC" at line 994. Isolating
the stage was what turned an opaque Error 33 into a one-line fix.
R22 clean-fleet: extract-all 139/139, check-all 140 passed / 0 failed.
family_sweep correctly REFUSED this exemplar (§53: a jr-family must route through
jtbl_family_bank.py; "a 0% from this path would be a TOOL artifact, not a wall") — the ×137 member
sweep is the next step and needs a clean tree, which this commit provides.
|
||
|
|
2ce6c5fade |
feat(phase-29): SESSION-21 — 3 family exemplars banked + the §85 return-axis widen (R22 140/140)
BANKED (whole-binary byte-gate, the sole arbiter): func_8014D2A0 (80 ins ×138) · func_80158638
(87 ×138) · func_8016B6BC (94 ×138). Stubs in ov_SC01_077: 150 -> 147, 0 new stubs.
R22 CLEAN-FLEET: extract-all 139/139, check-all 140 passed / 0 failed. dedup 1886/0,
0 NON_MATCHING (G4). Fleet 81.7% instr / 69.3% distinct-code / 89.52% fn-count.
- WAVE STOPPED at Drew's request with 15/24 agents returned, ALL 15 status=match. Only the
completed drafts were gated; in-flight ones are still being written (§90d).
- PRE-GATE, both oracles, all 15: match_one MATCH + reloc_verify ALL RESOLVED. Routed 7 plain /
8 to the §81 jtbl carve chain.
- THE BLOCKER, MEASURED: 7 of 7 plain drafts failed PLUMBING, 0 DIFF, 0 compiler walls — the same
shape as SESSION-20's T0.2. §58b applies: the draft sig is byte-TRUTH (it MATCHed), the header
decl is the stale stub-era guess, so conform the DECLS.
- §85 RETURN-AXIS WIDEN, all-or-nothing: 3,471 decl sites / 1,736 files, precondition verified
(ZERO callers consume the return => byte-neutral by construction) + an R32 completion assertion
(old-form decls remaining: 0). func_8014D820's s32 return is load-bearing — forcing `void` costs
2 instructions (302 vs 304), so the decls had to move, not the draft.
TWO HONESTY ITEMS:
1. I REPORTED "0 of 7 banked"; the true number was already 2. My diagnostic pass printed only
lines starting with "- func_" (the failures) and hid its own successes while I read it for
error text. A script that prints only failures cannot tell you it succeeded — the R32
silent-skip shape aimed at my own instrumentation. Ground truth is the stub count (§55b(3)).
2. A REAL FINDING fell out of that mistake: same drafts, same tree, minutes apart — gate_stage's
full ladder banked 0/7 while bare harvest_verify banked 2/7. The LADDER REGRESSED two drafts
the bare gate accepts (§19's "sig_unify regresses already-canonical drafts", one level up, and
the exact mirror of SESSION-20's missing-ladder false 33%). Neither "always ladder" nor "never
ladder" is right — run both, let the byte-gate arbitrate. One build per draft.
OPEN: func_8014D820 still a stub — after the widen its error moved from `conflicting types` to an
assembler-stage failure, not finished diagnosing. Recorded as open, NOT as a wall.
|
||
|
|
09b1993059 |
feat(phase-29): T0.7 sweep (104 members) + BEHEMOTH func_8017D2DC banked (1,586 ins)
T0.7 — the §86 one-member probe applied to the remaining FREE families: 9 LIVE / 6 DEAD / 5 unstaged. The three highest-value families by raw size (18,084 / 11,234 / 10,880 ins) all probed DEAD — the probe skipped them instead of burning ~400 gate cycles rediscovering it. Swept the 9 live: 104 banked, 8 of 9 families fully cleared (func_8017BEF8 has 8 stragglers). BEHEMOTH 2 of 3: func_8017D2DC (1,586 ins, ov_SC01_001) MATCHED and BANKED — closed in ONE agent round, pin-free. Verified independently (R14): match_one MATCH (1586 ins). §81 carve chain: the agent predicted step 1 unnecessary; jtbl_carve REFUSED (the subseg already hosts a .rodata carve and the new table's start != span start). The refusal was RIGHT and is the instruction to run step 1 — jr_isolate_all --only (2 fns/1 object) -> BYTE-IDENTICAL, then jtbl_carve -> BYTE-IDENTICAL, then the ladder banked it. R22 clean-fleet 140/140 BYTE-IDENTICAL; tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4). Fleet: instr 81.5 -> 81.6% · distinct-code 69.0 -> 69.1% · fn-count 89.49 -> 89.52%. |
||
|
|
772b5c4e02 |
feat(phase-29): the RETURN-axis fleet widen — 2 more families unlocked (cookbook §85); 140/140
Continues the "see why and try again" chain. Diagnosed all 4 T0.2 failures to 4 DISTINCT causes: func_8013D53C 240x123 §84 derived-offset remap bug -> BANKED (previous commit) func_8012CC88 105x137 §73/§30#2 RETURN-axis conflict -> BANKED here func_8014D12C 93x137 §73/§30#2 RETURN-axis conflict -> BANKED here func_80144090 154x136 LENGTH-DRIFT (+13 B, ~3 ins long) -> genuine codegen, real work THE FAILURE THAT TAUGHT THE FIX: widening only src/shared/engine_core.h banked the member in the TARGET overlay and BROKE ov_SC01_077 (R22 139/140) — the source overlay carries its OWN local `extern void func_X(...)` decls, so a shared-header-only widen puts them in direct conflict. The per-binary gate passed while breaking a binary it never built (§63/§61: a T2 write set is only provable by R22). A half-done axis is a guaranteed break, not a smaller win. THE FIX: do the WHOLE axis — 3,668 `extern void` decl sites across 2,688 files widened to `s32`, 0 remaining (R32 completion assertion). Precondition verified first: 0 callers consume the return value, so the widen is byte-neutral by construction. R22 clean-fleet 140/140 BYTE-IDENTICAL; tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4). MY OWN ERROR, recorded (§85 trap): I first spot-checked ov_SC01_077 with `make build | grep | head; echo rc=$?` and read rc=0 as success — that is the exit status of `head`, not make, and the output had no BYTE-IDENTICAL line. I reported a false BYTE-IDENTICAL in the interim. Assert on the SUCCESS STRING, never on $? after a pipe. Fleet: instr 80.6% (10,589,503) · distinct-code 68.3% (3,846,656) · fn-count 89.19%. |
||
|
|
3ffff74f5b |
feat(phase-29): BEHEMOTH #3 func_8017F510 CRACKED — 97 -> MATCH (1,511 ins), pin-free
- BANKED into ov_SC03_006 through the whole-binary byte-gate (G3/P9); R22 clean-fleet 140 passed, 0 failed of 140. Verified independently before believing the agent's report (R14): match_one -> MATCH (1511 ins), then harvest_verify -> BYTE-IDENTICAL. - DISTINCT-CODE 3,813,512 -> 3,815,023 = +1,511, EXACTLY the function's instruction count and the ONLY distinct-code movement of the entire session. Reach is ×1 by sig, no propagation -- which is precisely why it moves the metric propagation cannot touch. instr 80.3%, fn 89.18%. - EFFORT EXPERIMENT (Drew): behemoths #1-#3 were worked at High; this is the first at xHigh (Opus 5 agent). It closed a residual the lower tier had fully localized but could not move, and that 3,663 permuter candidates at base 97 had failed to improve by even 1. - MECHANISM -> cookbook §76: the allocno CLASS (local vs global) is the dominant regalloc lever and C reaches it ONLY through declaration scope and variable reuse -- unreachable by statement order, expression shape, pins, or random search, which is exactly why the permuter was spent. (1) `otp` per emit ARM: 4 deaths -> four 1-death local pseudos (local-alloc.c:472); its second-order effect via global.c:668-671 (local placements re-marked as HARD regs for global-alloc) had made the target's otp=$a0 STRUCTURALLY IMPOSSIBLE, visible as hard-reg 4 in the `;; N conflicts:` tail of the .greg dump. (2) `cb` reused as the unlit rgbc temp: refs 27->39 lifts its global.c:594 allocno_compare priority past `tp`, flipping the 3-colouring -> 97 -> 10. (3) one shared `rgbw` temp -> 10 -> 2. (4) mny-before-my + one zero-byte __asm__ at the head of the tri cull block -> MATCH. - THREE CORRECTIONS TO MY OWN BRIEF, all byte-evidenced: residual B was never a scheduling residual (it fell out free with lever 2 -- a register grant seen as a schedule diff); residual A is RTL EXPANSION order, proven with -fno-schedule-insns AND -fno-schedule-insns2 (source order survives both -- that attribution primitive is the reusable bit); residual C had no single c3 seed (c3 has no lever of its own, it moves only when cb out-ranks tp). - FIXED a latent SHARED-HEADER defect, pre-existing and unrelated to the draft: src/shared/engine_types.h closed its include guard at line 1174 of 1259, leaving 11 typedefs / 85 lines OUTSIDE the guard since the crack-wave lift. A TU including it twice re-declares them and gcc-2.7.2 rejects a repeated typedef even when identical -> `conflicting types for Blk16_956C`. Guard moved to EOF; byte-neutral. - ARTIFACTS TRACKED (R20): .run/giants/s19_func_8017F510_b4.c (130-line dossier) + s19_f510_report.md, whose ~50-row do-not-re-buy table is arguably worth more than the match, + the s19_* analysis tooling. - STRETCH, MEASURED: func_8017F5B4 (1,511 ins, ov_SC02_031) has a DIFFERENT h_exact -- not a dedup sibling, a family_remap TEMPLATE candidate off the b4 source. |
||
|
|
398e653c92 |
fix(phase-29): §75a class-B remedy is the FULL §17a-1 pair — decl AND call-site cast
- The K&R-decl-only probe was HALF the fix, and cc1 said so exactly:
ov_SC01_001_jr_801734BC.c:2616: too many arguments to function `func_8012F14C'
`()` dissolves the DECLARATION conflict (the failure class moved PLUMBING -> CC1-FAIL), but the
composite type after the TU's earlier `void func_8012F14C(s32);` prototype is still 1-param, so
the macro's 3-arg CALL is a hard error. Reproduced by hand-splicing the macro into
ov_SC01_001 and reading real cc1 stderr rather than trusting the classifier's `Error 33`.
- FIX = the other half of §17a-1 (what cast_call_sites.py does, and what §20 established): cast
the call site so it does not depend on the TU's prototype at all —
((void (*)(s32, s32, s32))func_8012F14C)((s32)&mtx, (s32)&vec, (s32)&out)
gcc-2.7.2 folds a cast of a KNOWN function symbol back to a direct `jal`, so the bytes are
unchanged. Decl stays `()` so it cannot conflict in either declaration order.
- BYTE-GATED on the full existing radius: ov_SC07_006 7ca772be · 007 b3b95547 · 011 9885af74 —
all BYTE-IDENTICAL.
- LESSON for §75a class B: the remedy is the PAIR, never the decl alone. A decl-only change moves
the error from `conflicting types` to `too many arguments` and looks like a new wall.
|
||
|
|
8f63c1a8e0 |
probe(phase-29): §75a class-B — K&R () for the carried func_8012F14C decl (func_80174CB0)
- The class-B arity split (1944 `(s32)` vs 968 `(s32,s32,s32)`) blocked func_80174CB0 in 131 of 134 overlays: the macro carried the 3-param prototype, the failing TU declares the 1-param one FIRST (ov_SC01_001: TU@328 vs instantiation@2616), so cc1 sees two prototypes of different arity and rejects. - Per cdecl.compatible's MEASURED gcc-2.7.2 behaviour a no-prototype `()` is accepted in BOTH orders here: prototype-first + ()-second always; ()-first + prototype-second when no parameter is altered by default promotion -- and all three args are s32, which does not promote. So one K&R decl should satisfy both populations regardless of where each TU declares it. - Call site UNCHANGED (`func_8012F14C((s32)&mtx, (s32)&vec, (s32)&out)`): with a K&R decl the args pass under default promotions, and s32 args are unaffected -> same codegen. - BYTE-GATED on the full existing radius before extending: ov_SC07_006 7ca772be · 007 b3b95547 · 011 9885af74 -- all BYTE-IDENTICAL. The extend result is the real test of the prediction. |
||
|
|
364ddd7055 |
fix(phase-29): ENGINE_SHB — the carried-#define gap that capped func_80165CA0 at ×3
- CAUSE (measured, not guessed): the 132 extend failures were `undefined reference to 'SHB'` --
a LINK error, not a type conflict. SHB is not a symbol; it is a file-scope
`#define SHB(x) __asm__(...)` sign-extension barrier. A body's preamble can carry `#define`s
as well as `extern`s, but extraction lifts only the externs -- so the `#define` was left behind
in the source overlay. In ov_SC01_077 it sits literally BETWEEN the two carried externs and the
instantiation:
extern s32 D_8011D030;
extern s32 D_80126728;
#define SHB(x) __asm__ __volatile__("" : "=r"(x) : "0"(x))
DEFINE_func_80165CA0()
The other 132 overlays DO define SHB -- ~300 lines further down the file (stub @4462 vs
#define @4781 in ov_SC01_001), i.e. BELOW the splice point, so the preprocessor never expands
it and cc1 emits a call to an undeclared `SHB`. Pure ORDERING; nothing was missing.
- Also explains why the 3 current members are EXACTLY the 3 files carrying the __volatile__ SHB
spelling: that define is the function's own preamble, still sitting above its instantiation.
- FIX: engine_core.h owns the barrier as ENGINE_SHB (distinct name, so the overlays' own SHB --
which exists in BOTH a volatile and a non-volatile spelling -- can never collide), and
DEFINE_func_80165CA0's 7 uses now call it. Volatile form: what the 3 banked members compile
with today. The body is now self-contained wherever it is instantiated.
- BYTE-GATED the full existing blast radius: ov_SC01_077 d19c9580 · ov_SC01_000 9052dc0e ·
ov_SC07_006 7ca772be -- all BYTE-IDENTICAL.
- This is the dedup_propagate counterpart of Phase-27's family_remap._carry_macros (§75b).
|
||
|
|
2fcb8de6bf |
fix(phase-29): normalize func_8014F468 to the fleet-canonical s32 (unblocks the ×138 reach) + §75
- THE PROPAGATION CAP WAS A MINORITY-SPELLING SOURCE OVERLAY, byte-censused:
extern s32 func_8014F468(void); 1710 | s32 func_8014F468(void) 134 <- fleet canon
extern void func_8014F468(void); 20 | void func_8014F468(void) 4 <- the outlier
and ALL 4 `void` definitions are ov_SC07_{006,007,010,011} — the overlay the F3E8 body was
banked from. dedup_propagate carries the source overlay's file-scope externs into the shared
macro VERBATIM, so the macro inherited `extern void` and the 134 overlays that define the
symbol `s32` rejected it. Propagation landed on exactly that 4-overlay island.
- The exclusion message ("byte-diverge / irreconcilable") is provably the wrong cause: members
are selected BY h_exact, so all 138 are byte-identical by construction. It is a COMPILE
conflict, never a byte one (same defect family as §68's mislabel, same tool).
- NORMALIZED the 24 minority occurrences to s32 (4 definitions + 19 overlay externs + the 1
line in the freshly-authored macro). func_8014F468 is a pure inline-asm $sp-switch trampoline
— no C-level value flow — and 134 overlays already PROVED s32 is byte-correct for the
identical function. Fleet is now uniform: 1730 extern s32 + 138 s32 defs, 0 `void`.
- BYTE-GATED the complete blast radius (the 4 instantiators of DEFINE_func_8014F3E8):
ov_SC07_006 7ca772be · 007 b3b95547 · 010 d7b5875d · 011 9885af74 — all BYTE-IDENTICAL.
- cookbook §75: census the carried extern before believing an exclusion message; prefer a
majority-spelling source overlay; always pass --recover; after normalizing use dedup_extend
(the body is already a macro) not dedup_propagate --addr.
|
||
|
|
10ea5ff653 |
feat(phase-29): propagate the widen batch — func_8014D4C0 ×138; func_8014F3E8 ×4 (cause measured)
- func_8014D4C0 (84 ins) PROPAGATED ×138: all 138 overlays rebuilt byte-identical, group
E_func_8014D4C0 registered. 84×138 = 11,592 ins.
- func_8014F3E8 (32 ins) propagated ×4 only (the ov_SC07_{006,007,010,011} island), 134
overlays excluded one at a time.
- TWO FINDINGS, both measured:
(1) THE FIRST RUN'S "drop" WAS A FLAG OMISSION, NOT A WALL. Without --recover,
dedup_propagate takes the historical all-or-nothing path on the first culprit overlay,
so ONE divergent member cost the whole group (×0). With --recover, Part A excludes just
the culprit -> ×4 instead of dropped. Always pass --recover on a targeted --addr run.
(2) THE EXCLUSION CAUSE IS A MINORITY-SPELLING SOURCE OVERLAY, not byte divergence. The
sigs prove all 138 members share ONE h_exact (2ccf344d), so nothing diverges in bytes.
The macro carries the source overlay's `extern void func_8014F468(void);` while the
fleet census is 1,710 `extern s32` + 134 `s32` definitions vs 20 `extern void` + 4
`void` definitions -- and all 4 `void` definitions are ov_SC07_{006,007,010,011}, i.e.
the source overlay I banked from is the OUTLIER. The macro inherited the minority
spelling and silently capped its own reach at that island.
- => the fix is NORMALIZATION (24 occurrences), not a reconciliation engine; the follow-up
commit flips the SC07 minority to the fleet-canonical s32 and re-propagates.
- R22 clean-fleet: make clean && extract-all && check-all -> 140 passed, 0 failed of 140.
|
||
|
|
1c0d29d91d |
feat(phase-29): §30#2 widen batch — func_8014F3E8 + func_8014D4C0 banked; §73 (the two axes)
- FLEET WIDEN (T2, one edit): extern void -> extern s32 for func_8014F3E8 + func_8014D4C0 across src/** (16 decls in engine_core.h + 5,079 in 3,459 overlay .c; 0 `extern void` left, 0 pre-existing `extern s32`). Scope re-verified against the tree first (R14/R35): the SESSION-18 counts reproduce exactly and no decl exists outside the `extern void <name>` shape in any .c/.h under src/. - BYTE-NEUTRALITY OF THE WIDEN ISOLATED FIRST: ov_SC07_006 7ca772be + ov_SC01_000 9052dc0e BYTE-IDENTICAL before splicing any draft (ov_SC01_000 chosen because it instantiates the two return-CASTING macros — the only sites a decl's return type could touch codegen). - BANKED into ov_SC07_006 (both ×1, both reach ×138 by sig: single h_exact across 138/138): func_8014F3E8 (32 ins) on gate 1; func_8014D4C0 (84 ins) on gate 2. - FINDING -> cookbook §73: the widen fixed only HALF the conflict. A def-side self-decl conflict has TWO independent axes — RETURN (fleet macro-widen, T2, R22-mandatory) and PARAMS (canonical param types + casts at each USE, T0, no fleet edit). func_8014D4C0 failed the first gate on the PARAM axis (canon `void*` vs draft `u16*`); the §17a-1 move applied to the def's own signature banked it with nothing outside the draft touched. Diagnose the axis before reaching for the expensive fix. - R22 clean-fleet: make clean && extract-all && check-all -> 140 passed, 0 failed of 140. make report: dedup 1884 validated / 0 failed, C1 coverage 239039/239039, 0 NON_MATCHING (G4). Fleet 80.0% instr / 67.7% distinct / 89.02% fn-count (the ×138 propagation is the value). |
||
|
|
ba35785ec4 |
feat(phase-29): bank func_801777BC (59 ins) x138 — the giv-init base-register lever (§70)
- MATCH (59 ins), real-TU verified by the agent before handing back (cc1 rc=0, 59/59, 0 diffs). - Propagated x138 with ZERO exclusions -> confirms the ×3 cap on func_80174CB0 was purely the carried-extern collision: a body with no externs propagates clean. - R22 clean-fleet 140/140, 0 failed. dedup-check 1884 validated / 0 failed, C1 coverage complete. - FLEET CROSSES 80.0% instr-weighted (10,509,526 / 13,141,652); fn-count 89.02%; distinct 67.7%. - THE LEVER (cookbook §70): residual was ONE instruction, addiu $t0,$t1,0xC vs $t0,$a0,0xC -- a giv based on a copy of the param. Reading gcc-2.7.2 loop.c/cse.c proved the natural form can never emit the target: cse.c:make_regs_eqv makes the copy canonical (it out-lives a0) and loop.c:update_reg_last_use won't extend a0's last-use (giv-init UID >= max_uid_for_loop). Fix: walk the PARAMETER itself, so record_initial sees the biv init as hard reg (reg:SI 4), valid_initial_value_p accepts it (precondition: no calls), and emit_iv_add_mult bases the giv on $a0 -- yielding both required instructions free. - META: this compiler-source reasoning was done by an ORDINARY Opus 5 drafting agent, unprompted -- the tier Phase 23 reserved for Fable5. One data point, recorded as such; the cheap action is to give routine drafting agents the gcc source path. |
||
|
|
e112eff601 |
fix(phase-29): find_site — a comment-only line halted the extern scan (§68); func_80174CB0 x1 -> x3
TWO mislabels in one tool, both found by making it print what the compiler actually said.
1) compiles_standalone() returned a bare False and the caller filed EVERY failure under
"overlay-local TYPE (the real cap)". The dominant real cause is undeclared FILE-SCOPE EXTERNS.
Now returns (ok, stderr) and the skip is classified by actual cc1 output.
2) find_site()'s backward walk over "preceding contiguous externs" skipped BLANK lines but not
COMMENT-ONLY lines, so a full-line /* ---- */ between two extern groups dropped every extern
above it. Comment lines are now skipped like blanks and filtered out of the emitted body so
make_macro never meets a `//`.
RESULT, measured honestly: func_80174CB0 went from "not self-contained" to a 138-member PLAN, but
--recover banked only x3 (ov_SC07_006/007/011); 135 overlays excluded. Those exclusions are NOT
byte divergence (all 138 share h_exact) -- they are the CARRIED EXTERNS colliding with each target
overlay's own decls. The carry is necessary but not sufficient: it must reconcile per-target-TU
(cdecl.compatible(), the shape reconcile_tu already uses). Spec updated in CURRENT_PHASE.md.
- R22 clean-fleet 140/140, 0 failed. dedup-check 1883 validated / 0 failed, C1 coverage complete.
- fleet instr 79.9% (10,501,384 / 13,141,652); +246 ins from the x3.
- WHY THIS MATTERS beyond the numbers: the Phase-21 backlog already prescribed "macro-extern-
injection frees them x134 (~+0.3%)" and it was never built, because the mislabel told every later
session these were the known-hard type wall. A wrong diagnostic label cost ~4 phases.
- cookbook §68. NOTE the exclusion message is ALSO mislabelled ("byte-diverge / irreconcilable"
conflates differing bytes with a non-compiling instantiation) -- logged to fix.
|
||
|
|
af59d8a630 |
feat(phase-29): bank func_80174CB0 (123 ins) — the §65g verdict was a wrong SIGNATURE
SESSION-17 filed this as §65g-class: "not 'run one more tool', but 'needs a transform that does not exist yet'". Refuted. It needed the correct self-declaration. - The TU expands DEFINE_func_80174C80() carrying `extern s32 func_80174CB0(s32, s32);`, while all ~100 prior drafts defined `void func_80174CB0(s32, s16)` — matches perfectly STANDALONE, dies in the real TU with `conflicting types`. Defining it `s32 (s32, s32)` and recovering param_2's s16-ness with an explicit (s16) cast at the func_80012558 use site is byte-identical. - Drafted by an isolated agent (Opus 5 @ High, 65k tok) pointed at the NAMED blocker with the canonical callee sigs supplied — not asked to re-derive the C. It self-verified through the real cpp->cc1->maspsx->as chain (cc1 rc=0, 123/123 ins, 0 diffs) before reporting, so the bank was first-try clean. - make check BINARY=ov_SC07_006 BYTE-IDENTICAL (7ca772be); R22 clean-fleet 140/140, 0 failed. - Propagation ×138 follows as a separate targeted step (§55b: bank -> commit -> dedup_propagate --addr). - FOLLOW-UP LOGGED: the recovery ladder also relaxed `extern s32 func_80174CB0(s32,s32)` -> `()` in src/shared/engine_core.h (+2 overlay files), escalating a binary-local bank to FLEET tier. The banked def AGREES with the original prototype, so that edit looks unnecessary — to be tested. |
||
|
|
25a02d6940 |
feat(phase-29): propagate 2 integration banks ×138 — fleet 79.7 -> 79.9% instr, R22 140/140
- func_8012B4B8 (84) + func_80169228 (105) propagated via targeted --addr (--check-only first, never --auto-from): 138 overlays byte-identical, 2 new dedup groups, ~+26,082 ins. - R22 clean-fleet: check-all 140 passed, 0 failed of 140. Fleet fn-count 88.90 -> 88.98%. - The 3 non-banks are diagnosed, not guessed (blocker_probe, both oracles agree): func_801463A0 is a real-cc1 MATCH in its own TU that the gate still rejects (§65c rtu-vs-gate divergence, link-level); func_80156670/func_80174CB0 carry "drop when banking" typedefs textually identical to the canonical ones. Blockers STACK — stripping the cc1-named typedef exposed the next (S8->B8; MATRIX->a callee conflict). Remedy named: strip ALL shared-provided typedefs, then run the DRIVER's ladder. |
||
|
|
32de37fff4 |
feat(phase-29): propagate func_80177940 x137 — 138 overlays byte-identical, R22 140/140
- Targeted `dedup_propagate --addr 0x80177940 --recover` (NEVER --auto-from; --check-only first confirmed the plan held exactly this one address, so the de-macroize hazard could not apply). - 138 overlays rebuilt byte-identical; 0 stubs remain for the address; 1 new dedup group registered. - R22 clean-fleet: check-all 140 passed, 0 failed of 140. - Fleet: fn-count 88.86 -> 88.90%, instr-weighted 79.6 -> 79.7% (+13,938 ins = 101 x 138), distinct-code 64,874 -> 64,875 unique fns. |
||
|
|
bf307f2827 |
feat(phase-29): s15 propagation (5 cores ×138) + crack-wave efficiency audit
- 5 of the 6 s15 fresh cores propagated ×138 (func_801483E8/8014680C/8017129C/80177AD4/801759D8; func_8014A51C §20-capped). R22 clean-fleet 140/140. fn-count 88.66->88.86%, instr 79.4->79.6%, distinct-code count 64854->64860, dedup 1879/0. - EFFICIENCY AUDIT (decision-log): the 2 LLM waves ran 92% match_one MATCH but only ~27% whole-binary bank; 6 spot-checked non-banks are ALL match_one MATCH (byte-correct bodies). NOT a missing idiom — an INTEGRATION wall (def-side sig / data-extern / unshared struct). We strand ~16 paid-for correct functions per wave; a fleet-safe integration-recovery pass would ~3.7× yield for 0 new drafting tokens. Next investment = integration tooling, not more drafting. Waves held per Drew. |
||
|
|
6253238c43 |
feat(phase-29): s15 fresh-crack wave — 6 more reach-138 cores banked (R22 140/140)
wave_binary over 24 fresh reach-138 ov_SC07_006 families -> 22 match_one MATCH / 2 near. Whole-binary byte-gate banked 6: func_8014A51C func_801483E8 func_8014680C func_8017129C func_80177AD4 func_801759D8. R22 clean-fleet 140/140 (engine_core.h reconcile edits verified fleet-wide, §61). - The s15 drafter-prompt fix HELD AT SCALE: all 24 winners persisted to the canonical path (vs s14's 3/24, recovered from transcripts). match_one isolation (per-pid --work) confirmed. - Consistent integration ceiling: ~22 match_one MATCH -> 6 whole-binary banks (27%), same as s14. The 16 nears are def-side plumbing / data-extern / struct-def reconcile the gate ladder doesn't clear; fix_header_decl is off-limits (fleet-blind, §63 UPDATE). Integration recovery is the lever to improve before the next batch, NOT the drafter prompt. - 6 genuinely-unmatched cores -> distinct-code movers (propagation follows). |
||
|
|
f1fd8993bf |
feat(phase-29): permuter overnight harvest — 29 fresh cores banked + distinct-code 64837->64854
The grinder ran the targeted permuter sweep to EXHAUSTION (all 75 permuter-shaped candidates; correctly skipped 1575 redraft/structural/integration). It banked 29 distinct functions autonomously (gate_stage commit=True, byte-gated, fail-closed, §55b un-propagated), 39% conversion. - All 29 are LOW-REACH (1-5) overlay-unique code in the 0x8017-0x8018 range — confirming the map's finding that the permuter-admissible set is the low-leverage tail (the high-reach near-misses like func_8014F3E8 close=1 reach=134 are redraft/structural, NOT permuter-shaped). - Propagation of the 22 reach>1 banks filled only 1 (0x80180710 ×2); the rest are genuinely overlay-unique (siblings byte-diverge) — as predicted. - R22 clean-fleet 140/140 (the 27 overnight per-binary-gated commits verified fleet-wide, §61). - distinct-code 64837 -> 64854 (+17 unique fns); session total +22 unique (wave +5, permuter +17) — the first real distinct-code progress in many sessions. instr 79.4%, fn-count 88.66%, dedup 1874/0. |
||
|
|
8ea5202135 |
feat(phase-29): propagate 1 fresh core ×138 + the session's FIRST distinct-code gain
Of the 6 s14 fresh cracks, func_80136F3C propagated ×138 (func_801749C8 dropped as an ov_SC07_006 straggler; 4 are §20 local-type-capped — future uniquify fodder, low-value de-duplication per the SESSION-14 finding). THE POINT (byte-verified): distinct-code UNIQUE count rose 64832 -> 64837 (+5) — the FIRST distinct-code movement all session. Every other lever today (154-type lift, 6 uniquify cores, MATRIX rename) was de-duplication and moved distinct-code by 0. These 6 are genuinely UNMATCHED cores, so banking them ×1 is real new coverage. Percentage is flat (67.6%, denom 87459) but the direction and the count are the validation the pivot to fresh cracks was correct. Fleet: instr 79.3 -> 79.4% | fn-count 88.61 -> 88.65% | distinct-code count +5 | dedup 1873/0. R22 clean-fleet 140/140 BYTE-IDENTICAL. |
||
|
|
e9c950a30c |
feat(phase-29): fresh-crack wave s14 — 6 reach-138 cores banked ×1 in ov_SC07_006 (R22 140/140)
Ultracode wave_binary over 24 FRESH (unmatched, live=138) ov_SC07_006 families -> 20 self-reported
match_one MATCH. The whole-binary byte-gate (sole arbiter, R14/G3) banked 6:
func_8014C6F4 func_801463A0 func_8012B77C func_80136F3C func_80156670 func_801749C8
The gap (20 claimed -> 6 banked) is the integration wall the drafters named: §63 header-decl
(void->s32), data-extern reconcile, struct-guard — a recovery pass follows. R22 clean-fleet 140/140
(the gate_stage ladder's engine_core.h reconcile edits verified fleet-wide, not just per-binary).
These are GENUINELY UNMATCHED cores (unlike the session's earlier propagation work), so once
propagated ×138 they move distinct-code — the metric that sat flat at 67.6% all session.
⚠️ WORKFLOW RECOVERY: the 24 drafters reported MATCH but wrote winners under scratch filenames;
only 3 func_<name>.c persisted. All 24 were recovered from the per-agent transcripts (Write calls
+ Bash heredocs) -> .run/drafts-s14r/. wave_binary.js drafter prompt hardened to force a copy-back
+ existence check as the mandatory final step so a future wave can't lose its winners this way.
|
||
|
|
d1a1d756e0 |
fix(phase-29): PsyQ MATRIX name hazard — the true 32B layout now owns the canonical name (R22 140/140)
Oracle (G1, Ghidra types get, /LIBGTE.H, psyq400.gdt): MATRIX = 32 bytes (short m[3][3] @+0x00,
long t[3] @+0x14, 2B pad after m); SVECTOR = 8B; VECTOR = 16B (long vx,vy,vz,pad).
- HAZARD CONFIRMED: the fleet-wide name `MATRIX` held {s32 m[3][3]; s32 t[3]} = 48 BYTES, not a PsyQ
type at all, while THREE other names (MATRIX_c1, MATRIX_c2, MATRIX2) held the true 32B layout. The
canonical name carried an invention; any future reader assuming PsyQ semantics would be misled.
- FIXED by pure consistent rename across 205 files: 48B invention -> MATRIX_L48 (KEPT — ~131 files are
byte-correct against it, and "fixing" it to 32B would change sizeof/array stride hence codegen);
the true 32B layout now owns MATRIX. R22 clean-fleet 140/140 BYTE-IDENTICAL.
- VECTOR left UNCHANGED on purpose: ours is 12B vs PsyQ 16B (missing trailing pad). I first called it
dead — wrong, it has 1 live use (engine_core.h gte_ldlv0((VECTOR*)sp)). Offsets already agree so a
fix is likely byte-neutral, but it is a LAYOUT change and bundling it with a rename would make an
R22 failure ambiguous. Own R22-gated commit, later.
- engine_types.h gains an oracle-sourced GROUND-TRUTH block: real PsyQ layouts, which of our names are
true vs invented, why MATRIX_L48 must not be "corrected", and the draft-time rule (address-suffix
anything you invent — 7 of the 8 collisions this fleet accumulated were bare generic names).
- SCOPE HELD: renamed + documented; did NOT force existing code onto real PsyQ definitions.
|
||
|
|
22af9ab2c5 |
feat(phase-29): 3 Vec8-freed cores ×138, R22 140/140 — and the honest ROI verdict on the cap
- Propagated 0x8012A464 / 0x8014FFDC / 0x801502EC -> 138/138 byte-identical, 0 stragglers, 3 new groups. R22 clean-fleet 140/140; dedup 1872/0; C1 237654/237654. - FINDING (R14/R31): the §20 propagation cap was gating source-level DE-DUPLICATION, not coverage. The whole uniquify campaign (Buf+MATRIX+Vec8, 223 files renamed, ~1559 copies stripped, 5 propagations, 4 R22 cycles) moved the fleet by +6 functions / +558 ins / -6 stubs and 0.00pp on all three headline metrics. The freed cores' members were ALREADY matched individually; propagation just consolidated them into shared macros. "Unblocked" != "unmatched". - SESSION ATTRIBUTION: of -837 stubs / +0.3pp instr / +0.23pp fn-count, -831 stubs came from the FIRST batch (broad lift -> 13 cores). The uniquify campaign contributed -6. - Roadmap B4 re-labelled: a maintainability item, not a coverage lever. Remaining camps (Handler/Blk8/V8/Prim/Prim_8016E7C8) are small and now known low-yield — opportunistic only. - distinct-code sat at EXACTLY 3811442/5634875 = 67.6% at open and close. Fresh cracks are the sole mover of that number; point the next session there. |
||
|
|
23b9b57505 |
feat(phase-29): uniquify+lift Vec8 camps + propagate 0x8012E778 ×138; blocked queue 10 -> 7
Two units, committed together because they touch overlapping overlay .c files.
- PROPAGATE: 0x8012E778 (freed by the MATRIX uniquify) -> 138/138 byte-identical, 0 stragglers,
1 new dedup group.
- Vec8 UNIQUIFY+LIFT: camp1 {s16 unk0,unk2,unk4,unk6} (8 bytes) x139 files -> Vec8_c1; the 180-file
{s32 w[8]} (32 bytes) majority keeps the name. These are two genuinely DIFFERENT types that had
been sharing one identifier across TUs of the same overlay — the case §64a exists for; reconciling
them to one layout would have merged a 32-byte and an 8-byte struct. Both camps lifted, 319 local
copies stripped.
- Pre-filtered on an overlay from each camp, then R22 clean-fleet 140/140 BYTE-IDENTICAL.
- Blocked core queue 10 -> 7 (0x8012a464, 0x8014ffdc, 0x801502ec freed). Session arc 13 -> 7 via
uniquify (Buf -> MATRIX -> Vec8). Remaining camps all small: Handler, Blk8, V8, Prim, Prim_8016E7C8.
|
||
|
|
72b7a7227a |
feat(phase-29): uniquify+lift the MATRIX camps — 77 files renamed, 655 stripped, R22 140/140
- uniquify_type --type MATRIX: camp1 {short m[3][3]; long t[3]} x71 jr-split TUs -> MATRIX_c1;
camp2 {short m[3][3]; short pad; s32 t[3]} x6 -> MATRIX_c2; the 578-file {s32 m[3][3]; s32 t[3]}
majority keeps the name. All three camps then single-def -> LIFTABLE -> lifted (655 local copies
stripped).
- Pre-filtered on one overlay from EACH camp (ov_SC01_000 / ov_SC01_077 / ov_SC06_033) — a
pre-filter is evidence only about what it filtered — then R22 clean-fleet 140/140 BYTE-IDENTICAL.
- Blocked core queue 11 -> 10 (0x8012e778 freed; propagation follows separately per §55b).
- NB: the R22 job was reported by the harness as exit -1 (session fork killed the shell wrapper
after make completed). Verdict taken from the log's terminal "check-all: 140 passed, 0 failed of
140", which is only emitted on completion. Read the gate's output, not the wrapper's exit code.
|
||
|
|
e393c320e6 |
feat(phase-29): VARIANT camps -> UNIQUIFY (not reconcile); validated on Buf, R22 140/140 (§64a)
MEASUREMENT CORRECTED THE PLAN. The checkpoint called for a "per-camp field-access reconcile";
measuring the camps refutes that: Vec8 = {s32 w[8]} (32B) in 180 files AND {s16 unk0..} (8B) in
139 files; MATRIX 48B/32B/32B; Buf 16B / 0x20+ / DrawEnv. These are DIFFERENT types sharing an
identifier across TUs of the same overlay — reconciling to a canonical layout MERGES them, the
same failure that broke 103 binaries on Prim. The right op is UNIQUIFY: rename the non-majority
camp (byte-neutral — a type name emits no code; TU-local by construction), which makes every camp
single-def and liftable by the existing lift_types rules.
- NEW tools/uniquify_type.py: deterministic camp ordering (file-count desc, then normalized text,
so re-runs assign the same suffixes); majority keeps the name, camp n -> <T>_c<n>; rewrites ONLY
files that DEFINE that camp (a file that merely USES the name gets it elsewhere and is untouched);
\bT\b word boundaries so `Buf` never matches `Buf80153978`.
- VALIDATED on Buf (578/6/1 files): 11 identifiers across 7 files -> 3 camps LIFTABLE -> lifted
(585 local copies stripped) -> R22 140/140 -> blocked core queue 13 -> 11 (0x8012ea90, 0x801749c8
freed). Propagated 0x8012EA90 ×138; 0x801749C8 dropped (straggler in ov_SC07_006).
- YIELD, HONESTLY (P9): ZERO new matched functions. fn-count 88.61% / instr 79.3% / stubs 40281 all
UNCHANGED; dedup 1867->1868, C1 +138. 0x8012EA90's members were ALREADY matched in all 138
overlays — the propagation consolidated duplication into one shared macro (DRY), not coverage.
The value is the PROVEN RECIPE + the queue moving 13->11, not the numbers.
- dedup_propagate (R32): the skip line printed a COUNT and no names, and aggregated three unrelated
causes into n_local — a body skipped merely for a `//` comment (macro-unsafe, 1-line fix) read
identically to one genuinely using an overlay-local type. Now named and split by cause.
- cookbook §64a (uniquify-vs-reconcile + the validated recipe + remaining camps by cost).
|
||
|
|
3642b5458a |
feat(phase-29): the type-lift's payoff — 13 cores propagated ×138, −831 stubs, R22 140/140
With the §20 local-type cap lifted (commit:0863), dedup_propagate --auto-from planned 17 self-contained cores that were previously skipped "not self-contained (local types)". - BANKED: 12 cores via --auto-from + func_80175308 (propagated separately, 138/138) = 13 ×138. func_80175308 is the PROVABLE unblock — the core the SESSION-13 checkpoint named as local-type-blocked. No claim is made that all 17 were unblocked by the lift; measuring that needs a pre-lift re-scan I did not run (P9). - 5 correctly DROPPED as cross-overlay stragglers (0x8012A018, 0x80172C50, 0x80173A60, 0x80144090 in ov_SC01_000; 0x801495C4 in ov_SC07_006): h_exact sharing is all-or-nothing and those overlays' bytes diverge. --recover NOT used (the documented quadratic thrash hazard). - GATES: R22 clean-fleet 140/140 BYTE-IDENTICAL (2nd full cycle this session); make report green; dedup-check 1854 -> 1867 validated / 0 failed, C1 236964/236964; 0 NON_MATCHING (G4). - FLEET: instr 79.0 -> 79.3% | fn-count 88.38 -> 88.61% | INCLUDE_ASM stubs 41112 -> 40281 (-831). distinct-code stays 67.6% — correct: propagation replicates already-distinct-matched code; only a fresh crack moves that number. - STILL BLOCKED: 13 cores "not self-contained (local types)", blocked by exactly the 8 deferred VARIANT entities (MATRIX 3-def, Buf 3-def, Vec8, Prim, Handler, Blk8, V8, Prim_8016E7C8). Next lever = a per-camp FIELD-ACCESS RECONCILE, not a lift (lifting them blindly is what broke 103 overlays earlier this session). |
||
|
|
5ab80517de |
feat(phase-29): broad §20 type-lift lands — 154 types fleet-wide, R22 140/140 (§64)
The 3-session-carried blocker ("needs collision-vetting + -O0 strip precision") was
misdiagnosed on all three counts; fixing the instruments first (R35) changed every answer.
- (1) the "case-variant collision" is a TAGGED TYPEDEF counted twice with OVERLAPPING spans:
the inner span starts at `struct` so it emits a VARIABLE definition, the alias is redeclared,
and the highest-first strip leaves the outer end offset STALE -> over-deletes past the span.
MEASURED 13 pairs / 6142 occurrences / 0 standalone tags. build_engine_types.resolve_type_defs()
is now the ONE shared model (R33) + assert_disjoint() enforces span disjointness (R32).
The case-insensitive exclude was a heuristic over a structural fact — it would also have
wrongly dropped the legitimate Obj/obj + Vec/vec pairs. Key by (kind, name) — the C namespace.
- (2) the "-O0 strip precision" bug is a VISIBILITY bug: ov_SC01_077_o0.c is the 1 TU of 3226
that deliberately omits engine_core.h, so the strip DELETED its types; `multiple definition of
D_801DAA08` was 3 steps downstream (undeclared -> parse error -> implicit int -> tentative def
-> link collision) and named a symbol no diff touched. bet.type_visible() derives the visible-
header set from the include graph and keeps such defs local, named.
- (3) a third blocker, introduced this session and caught by R22: --candidates classifies per
ENTITY but emits per NAME, so passing `Prim` dragged in the deferred VARIANT `typedef Prim` and
repointed 103 overlays at the header's different layout. Compiled clean, per-binary pre-filter
green, R22 37/140 — the 103 failures were EXACTLY the 103 Prim-stripped overlays (set equality).
Fixed by the strip invariant "remove a local def only if what becomes visible is TEXTUALLY
IDENTICAL", placed at the MUTATION so a selector bug cannot reach the source.
- lift_types.py: (kind,name) entity keying, --candidates derived selector (retires the ad-hoc
102-type pipeline), divergence + visibility reports, whole-line strip (411 whitespace-churn
lines -> 0), complement-based single-pass rewrite (no mid-loop offset mutation).
- RESULT: 154 types lifted, 2958 files stripped, engine_types.h +510 lines. R22 clean-fleet
140/140 BYTE-IDENTICAL; tools-health OK (corpus 0/0, cdecl ALL GREEN, audit-binaries 140,
dedup-check 1854/0, C1 235170/235170); 0 NON_MATCHING (G4). Metrics unchanged 79.0/67.6/88.38
— honest: a type-lift banks no functions, it unblocks the NEXT propagate.
- DEFERRED + NAMED: 8 VARIANT entities (MATRIX 3-def, Buf 3-def, Vec8, Prim, Handler, Blk8, V8,
Prim_8016E7C8) = the per-camp field-access reconcile, the remaining hard part of roadmap B4;
14 carried tags; 5 types kept local in the -O0 TU.
- cookbook §64 (the three laws + the pre-filter lesson: a pre-filter is evidence ONLY about what
it filtered — ov_SC01_077 passed the Prim-broken run too; pre-filter on a binary that FAILED),
decision-log (R31), CURRENT_PHASE.md log.
|