- 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.
- The draft calls ((void(*)(void))func_80142C84)() but nothing declares that symbol above the
splice: it is DEFINED by DEFINE_func_80142C84() in engine_core.h, so gather_externs has no
extern line to harvest, and the member TU instantiates the macro BELOW our function.
- The wrong guess was the useful step: a no-prototype `extern s32 func_80142C84();` turned
`undeclared` into `conflicting types` — a DIFFERENT error, proving the diagnosis right and the
type wrong. Synthesised from the macro's own definition head -> MATCH (34 ins) -> 136/136.
- NEW macro_def_sig_map() (1,878 signatures): the complement of header_sig_map(), which reads the
externs a macro emits FOR ITS CALLEES; this reads the signature a macro DEFINES. Cookbook §121.
- ALL THREE byte-identical stragglers carried since SESSION-24 are now closed: func_80146750
137/137 (T84), func_801759D8 137/137 (T93), func_80142B2C 136/136 (T95) = 410 members, and not
one was a compiler wall (a signedness-wrong header decl, a type-name collision, a missing extern).
- Blast radius 0 (74 further families re-swept). FOUR data points now: only §117 (wrong LOGIC)
generalised at 1,209 members; §118/§120/§121 are path-reachability gaps worth ~one family each.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.88 -> 91.96% (+273, exact) · instr 87.3 -> 87.4% (+12,296) · distinct +0
(both byte-identical families — §111 predicted exactly that).
- CORRECTION 1 (R14/P9): T92's "strip-if-ambient" recipe was WRONG. Stripping the draft's duplicate
typedef breaks the extern that USES it (the TU's own copy sits below the spliced function), so the
"second stacked blocker" T92 recorded (D_800AF634 used prior to declaration) was my own fix
misfiring, not a real blocker. RENAME, don't remove: rtu_match CC1 FAIL -> MATCH (56 ins).
- CORRECTION 2: T91's wiring never RAN. family_sweep has THREE staging sites sharing the identical
two lines (edit-remap / hseq / plain h_norm); I patched by rindex twice, which lands on the PLAIN
site, so --hseq staged the draft unchanged and the lever looked ineffective. Re-anchored on the
hseq site's unique write (func_{to_addr:08X}.c) and the draft came out renamed. T91's revert was
right discipline on a false premise.
- RESULT: _uniquify_draft_types wired into the hseq path (byte-neutral — C type names never reach
codegen). func_801759D8, one of the three long-standing byte-identical stragglers: 0 -> 137/137,
0 failed. Blast radius 0 (74 further families re-swept, none moved) => TARGETED lever, like §118
and unlike §117.
- Cookbook §120, incl. the law: before concluding a lever does not work, prove it RAN — diff the
staged artifact for the change it is supposed to make.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.88 -> 91.92% (+137, exact) · instr 87.3 -> 87.4% (+7,672) · distinct +0
(byte-identical family — §111 predicted exactly that).
- CORRECTION (R14/P9): T84's '137 banked = all of 0x80161c98' is WRONG and committed wrong in
commit:1193. The 137 were func_80146750 (a byte-identical straggler), banked 1-per-overlay in
<ov>_after.c; 0x80161c98's members were still stubs. I assigned a count to the family I had
been looking at without deriving it — third instance today of that error class. The
--fix-def-sig-is-harmful finding itself stands (it unblocked func_80146750 x137).
- THE REAL BLOCKER was a flag OFF-DIAGONAL, not a defect. 0x80161c98's byte truth is (int,u32)
-> sltiu; engine_core.h says (s32,s32); and an in-TU decl disagrees with the def. The levers
pull opposite ways: --fix-def-sig bends the DEFINITION to the header; --normalize-self-decls
bends the DECLARATIONS to the definition. both-on -> slti DIFF (T79). both-off -> correct
sltiu but 'conflicting types' (T84/T88). NSD-only -> 138/138 (T89). Three sweeps across three
sessions tested only the diagonal of the 2x2. Cookbook §119.
- T90 blast radius: 23 more (NSD-only) across the remaining still-zero families — targeted, not
general; recorded so it is not over-projected.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.84 -> 91.88% (+161, exact) · distinct-code 69,593 -> 69,744 (+151).
- The T86 asm-ambiguous refusal was CORRECT (a by-value swap would corrupt the non-differing
occurrence); the safety TEST was too strict. It compared the C literal's occurrences against
EVERY asm use of that value, but gcc synthesises uses no C token names — e.g.
D_80187044[*(u16 *)((s32)a0 + 0x2)]() has one C literal 0x2 and TWO asm uses of 2 (the
per-member offset + a fixed sll ..,2 for the 4-byte stride). Unsatisfiable by construction.
- FIX (_ordinal_edits, §118): pair C occurrences to asm positions IN ORDER, accepting either
len(spans)==len(asm_pos) (every use named) or len(spans)==len(diff_pos) (extras are implicit).
Rewrite only occurrences whose instruction is in diff_idx. Order is a heuristic, so the
whole-binary byte-gate stays the sole arbiter — a wrong pairing is rejected, never banked.
- T87: func_801599A4 0 -> 137 drafts, 137 banked; +12 singletons = 149 (family 0x80131eec).
- T88 blast radius: only 9 of the other 144 immediate-refusals converted (refusals 67 -> 34).
A TARGETED lever, not a second §117 — recorded so it is not over-projected.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.79 -> 91.84% (+158, exact) · distinct-code 69,450 -> 69,593 (+143).
- T84 (item 1): the top still-zero family's whole diff was ONE instruction — slti (signed) vs the
target's sltiu. --fix-def-sig was conforming a byte-correct draft to engine_core.h's
signedness-wrong decl (extern void func_80161D20(s32,s32)) while the exemplar's own def is
(int, u32). Re-swept the 92 still-zero families WITHOUT the flag: 137 banked (all of
0x80161c98), other 91 unmoved => family-specific, NOT a second §117. Recorded as such.
- T85 (item 2): rewrote tools/rollout_801457a4_o0.py as the two-file ATOMIC driver §116 called for
(remapped body -> <ov>_o0b.c AND drop the INCLUDE_ASM from <ov>_after.c in one edit; build vs
config/check.<ov>.sha; restore BOTH files on mismatch, §61). Validated on 3, then 130/130.
No splat change — the Arm-A re-carve wall never touched.
- Item 4 PRICED AND DROPPED: STRUCT residue = 34 families / 166 members / 0.02pp.
- R14: my new_distinct estimator over-projects ~2x (priced 259, measured 125) — it counts classes
unmatched at run time, so concurrent sweeps double-count. Ranks correctly, overstates absolutely.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.72 -> 91.79% (+270, exact) · instr 87.2 -> 87.3% (+16,946) ·
distinct-code 69,325 -> 69,450 (+125).
- Re-swept the 229 eligible non-jr families (2,575 candidate members) that had never seen a
correct target spelling. 821 banked / 1,538 failed; 138 families went zero -> COMPLETE (732
members), 14 partial, 92 still zero. Top: 0x80172780 +135, 0x80128158 +31, 0x80187318 +28,
0x8016f540 +27, 0x8017bef8 +20.
- Every one of those 138 families had been swept before and booked as a failure. None was a
compiler problem — all were downstream of the one positional-map defect fixed in T82.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.48 -> 91.72% (+821, exact) · instr 86.9 -> 87.2% (+33,670) ·
distinct-code 69,024 -> 69,325 unique fns (+301).
- The 92 still-zero families are the honest residue: swept with every lever this phase built
(§114 callee, §115 named-symbol, §117 symbol-kind, def-sig, self-decl normalization), so no
known harness defect applies to them. Correct starting population for the next diagnosis round.
- CAUSE: family_remap.symbol_map zips exemplar/sibling reloc slots positionally and spelled the
SIBLING's symbol from the EXEMPLAR's kind. Same-address families always agree, so it was
invisible for 20+ phases; cross-address families need not agree — func_80174784's callback slot
is the FUNCTION func_801747CC while member func_8017CFD4's same slot is the DATA symbol
D_80182688. The map emitted func_80182688, the body materialized a name for an address that is
not a function, and the fleet gate refused all 251 members.
- FIX: spell the target by what the target address IS in the SIBLING's overlay (func_ iff in that
overlay's sig set — the same boundary oracle nins_of trusts, R33; memoized). Phase 26-A had
already established this rule and applied it only to the exemplar side.
- WHY IT HID: rtu_match/match_one MASK HI16/LO16, so a wrong %hi/%lo symbol still reports a clean
MATCH (measured: "MATCH (10 ins)" on a member the fleet gate rejected). masked-MATCH +
whole-binary DIFF is the exact signature of a compiler wall. Cookbook §117 carries the law.
- Also refuted en route (cheaply): --normalize-self-decls was NOT the cause — re-swept without it,
still 0/251.
- GATES: R22 clean-fleet 140/140; dedup 1886/0; 0 NON_MATCHING (G4).
- METRICS: fn-count 91.41 -> 91.48% (+251, exact) · distinct-code 68,782 -> 69,024 unique fns
(+242, projected 246) · instr +2,510.
- BLAST RADIUS UNMEASURED: symbol_map serves every family sweep; 229 eligible non-jr families /
2,575 members have never been swept with a correct target spelling, incl. the byte-identical
families T76 measured at 0/682 (same failure shape).
- VALIDATED FIRST, then batched: 0x80143d28 (T66's #1, T76's ApplyMatrixSV callee diagnosis)
banked 136/136 under the §114 callee axis + §115 named-symbol widening. Batch of 8 followed:
505/1039. Totals: 5 families outright + 1 partial of 9; 641 members ×N.
- Attribution DERIVED (R33), not parsed from the sweep log: live stubs recomputed per family from
corpus.stubs before/after. Reconciles exactly against the metric (fn-count +641).
- §116 (NEW): optimization level is a property of the FILE, not the function. 0x801457a4 swept
0/137 because its exemplar lives in ov_SC01_077_o0b.c (-O0 via WHALE_O0B_OBJS) while all 137
members' stubs live in <ov>_after.c (-O2). The fix moves the STUB line, not the def: <ov>_o0b's
.text ends exactly at 0x801457A4, so the relocation is byte-neutral by construction and needs no
splat re-carve (which is the Arm-A +0x20 wall). 13th time a family-wide 0/N was the harness.
- R14 CORRECTION to the handoff arithmetic: the tier is 123 families / 3,100 distinct on fresh
sigs, but 1,287 of that distinct is the -O0 cluster behind the Arm-A splat wall. Honest
addressable tier = 113 families / 85,360 ins / 1,813 distinct. Billing the walled 1,287 as sweep
yield would have repeated the T76 error.
- 0x80131eec (214 distinct, the biggest item left) diagnosed precisely: header macro decl +
§20 call-site cast + a scripted §99 pass over 2,022 overlay-local decls; param is void*, so the
T75 narrow-param refusal does not apply.
- GATES: R22 clean-fleet 140/140 from make clean + extract-all + check-all; tools-health RC=0
(corpus 0 PHANTOM/0 TRUNCATED, cdecl, audit-binaries, dedup 1886/0, C1 239604/239604);
report RC=0; 0 NON_MATCHING (G4).
- METRICS: instr 86.7 -> 86.9% (+28,205 ins) · distinct-code 76.9 -> 77.4% (68,196 -> 68,782
unique fns) · fn-count 91.23 -> 91.41% (+641). The distinct-code move is the point of this tier.
I called this "a one-line predicate widening". It was THREE, and fixing the first two changed nothing
— the sweep still reported 0/547 (cookbook §115):
1. canonical_map : re.fullmatch(r'func_[0-9A-Fa-f]{8}') + keyed by parsed ADDRESS
2. DECL_LINE_RE : (func_[0-9A-Fa-f]+) as the name group
3. split_sig_string : \bfunc_[0-9A-Fa-f]+\s*\(
Each is a SILENT SKIP indistinguishable from "no conflict found". With 1+2 done the symbol reached 3
and died there; only tracing transform's internals (`callees cast: 0` while the canonical map plainly
held `s32 RotTransPers(s32, s32, s32*, s32*)`) located it. THE TRAP WORTH REMEMBERING: a partial fix
to a name-form assumption produces the exact symptom of no fix at all, so a correct hypothesis looks
refuted. Curated naming increases as RE quality improves, so any func_-only predicate is
rot-by-design — the same shape as stub_map's (Phase 26-A).
RESULT: func_8012F40C 0/137 -> 137/137. The other three families (801759D8, 80146750, 80142B2C) still
fail on different causes.
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK; dedup 1886/0; 0 NON_MATCHING.
METRICS: instr 86.7% (+4,932 ins); fn-count 91.19% -> 91.23% (+137); distinct +0 (byte-identical).
NEXT: the byte-VARIANT tier is worth re-sweeping — T70 banked 1/10 BEFORE the callee axis existed, and
26 families remain unswept by the two levers added since.
Item 1. The T76 diagnosis was right and the fix was a lever we already owned. cast_call_sites
(§17a-1/§20) handles the callee-conflict class and lived ONLY in gate_stage, which the family sweep
deliberately does not use — the THIRD instance this session of a lever unreachable from the path that
needs it (T56 data-decl unreachable, T57 function-decl off-by-default, now T77 callee).
the 5 byte-identical families : 0/682 -> 135/682
func_80173A60 specifically : 0/135 -> 135/135
Wired after scope_data_fix (orthogonal axes: data vs callee), default ON with --no-cast-callees. Two
details that matter: the canonical map is built from the TARGET sibling's TU via cpp
(canonical_map(ov, src_file=tu) -> cdecl.tu_scope) so it sees MACRO-INJECTED declarations — a
raw-text scan returns nothing for exactly the callees that conflict (§51g LAW 7) — and it is read
AFTER any tu-scope edit is on disk.
THE OTHER FOUR STILL FAIL, different causes. And the next finding is already visible:
func_8012F40C's blocker is RotTransPers, a PsyQ LIBRARY symbol — a callee conflict the cast should
have handled. It did not, because cast_call_sites' canonical map keys on
re.fullmatch(r'func_[0-9A-Fa-f]{8}'), so NAMED PsyQ callees are structurally invisible to it. That is
a one-line predicate widening with ~270 members behind it (RotTransPers + ApplyMatrixSV families).
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK; dedup 1886/0; 0 NON_MATCHING.
METRICS: instr 86.6% -> 86.7% (+7,965 ins); fn-count 91.15% -> 91.19% (+135); distinct +0
(byte-identical — §111 predicted it).
cookbook §114 — the three decl axes, and "conflicting types for X: READ X".
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.
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.
Probe target switched from func_8013BD34 on measured evidence (its def is in ov_SC07_010_o0.c and
_o0 families sweep ~1/137 — a poor test of an unproven technique). func_80144B14: same class, 137
stubs, not -O0, real 34x137 family, tests both axes (void(void) -> int(int)).
THE PROBE FOUND THE PRECONDITION OVER-FIRING. The ARITY blocker exists because the macro's own CALL
SITE passes the header's arity. But DEFINE_func_* does not call func_80144B14 — it takes its ADDRESS:
*(s32 *)((s32)a0 + 0xDC) = (s32)&func_80144B14;
No call site => no arity constraint => the FULL correction is available, not the §99 no-prototype
workaround. Applied `extern int func_80144B14(int param_1);`.
RESULT: header change ALONE -> R22 clean-fleet 140 passed, 0 failed of 140 (byte-neutral); family
sweep -> 137/137, 0 failed.
METRICS: instr 86.6% (+4,658 ins); fn-count 91.12% -> 91.15% (+137); distinct-code +0 (byte-identical
family — §111 predicted it).
THE REFINEMENT (cookbook §113): the precondition must ask what the macro DOES with the symbol — a
call constrains arity, an address-taken or unused decl does not. Blocking on "both names appear"
over-fires, and it had 137 members behind it. The remaining ARITY findings should each be re-checked
for call-vs-address before assuming §99 is needed.
GATES: R22 140/140 twice; tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4).
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.
Item 5, first batch. Swept 10 byte-VARIANT non-jr non-O0 families (42,235 ins / 1,552 distinct
projected): 138 BANKED / 1,346 failed — ONE family of ten (func_801627E8 137/137), plus 152 members
skipped as "unresolved immediates (T2a)".
THE FINDING: that is a ~10x worse rate than the byte-IDENTICAL families, which banked 137/137 apiece
all session. It follows from what §111 established — a byte-variant member differs in more than
relocations, so the template must adapt immediates too, and family_remap's T2a engine refuses what it
cannot resolve. The distinct-code lever is real but it is NOT the same cheap sweep, and the projected
"2,962 distinct across 36 families" should be discounted until the immediate-resolution rate is
measured. That measurement is now item 1 of the next list, ahead of sweeping the other 26.
§111 PASSED A SECOND PREDICTIVE TEST: projected +129 distinct for func_801627E8; observed +130 (the
extra from an unrelated 2-member bank).
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK; 0 NON_MATCHING (G4).
METRICS: instr 86.5% -> 86.6% (+2,618 ins); fn-count 91.08% -> 91.12% (+138); distinct-code
68,066 -> 68,196 = +130 — the first real distinct-code movement of the session.
The audit was the right precondition: THREE of the six corrected functions were families already
queued for the item-3 sweep, and each would have failed 0/137 exactly the way five families did
earlier today.
SWEEP: 6 corrected functions, all non-jr families with 137 live stubs -> 685 BANKED / 137 failed.
Five families landed 137/137; func_80146750 failed on its own residual (undiagnosed).
GATES: R22 clean-fleet 140 passed, 0 failed of 140 — after the header batch alone AND after the
banks; tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED, cdecl, audit-binaries, dedup 1886/0);
0 NON_MATCHING (G4).
METRICS: instr 86.3% -> 86.5% (11338739 -> 11372304 = +33,565 ins); fn-count 90.88% -> 91.08%
(321472 -> 322157 = +685); distinct-code 76.9% -> 76.9% (+0).
§111 GOT ITS FIRST PREDICTIVE TEST AND PASSED: all six families have a single h_exact class, so the
model predicted +0 distinct BEFORE the sweep ran, and +0 is what happened. The metric is modelled,
not mysterious.
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).
Item 3, and it banked the third family. extract_unit located a definition with "the line matches
<type> func_<addr>( and does not end in `;`" — wrong whenever ONE LINE holds both a declaration and a
definition, which the handwritten inline-asm wrappers do:
extern void func_80156044(int, int); int func_80155FF8(int, int) { __asm__ … }
The line does not end in `;`, so func_80156044 — appearing there only in the DECLARATION — was taken
as a definition head. extract_unit lifted the neighbouring WRAPPER instead of the real definition
seven lines below; every sibling already defines that wrapper via its shared DEFINE_ macro, so all
137 failed with `redefinition of func_80155FF8` and it read as a compiler wall.
FIX: ask what follows the PARAMETER LIST, not what ends the line (`_def_head_at`) — `;` is a
declaration, `{` or end-of-line is a definition. Plus the R32 assertion: a unit that defines a
function other than its target cannot template, so refuse LOUDLY (`_foreign_defs`).
TWO TRAPS HIT WHILE WRITING THAT ASSERTION, both caught by regression-checking against families known
to bank: (1) _def_head_at ALONE over-fires — a call whose args wrap has nothing after the `(` on its
line, which "end of line => definition" reads as a definition; it refused THREE families that had
just banked 137/137. (2) The type-prefix test ALONE under-fires — it is what missed the wrapper
originally. The predicate needs both: split the prefix on its last `;`, require the remainder to look
like a return type, then check what follows the parameter list. All five known-banking families
extract byte-identically before and after.
RESULT: func_80156044 0/137 -> 137/137, 0 failed.
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, dedup 1886/0); 0 NON_MATCHING (G4).
METRICS: instr 86.2% -> 86.3% (11328601 -> 11338739 = +10,138 ins); fn-count 90.84% -> 90.88%
(321335 -> 321472 = +137); distinct-code 76.7% -> 76.9% (67937 -> 68066 = +129).
cookbook §110.
Item 2, and the same story as item 1: the header correction WAS the fix. With engine_core.h
declaring the byte truth, the family swept 137/137 with zero failures — no draft change.
before (header wrong) 0/137 `conflicting types` / a param-retyped body that could not compile
after (header right) 137/137, 0 failed
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, dedup 1886/0); 0 NON_MATCHING (G4).
METRICS: instr 86.1% -> 86.2% (11318463 -> 11328601 = +10,138 ins); fn-count 90.81% -> 90.84%
(321198 -> 321335 = +137); distinct-code 76.7% -> 76.7% (+0 — a SIXTH data point for the anomaly).
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.
Item 1. The header flip (commit:1163's sibling, committed just before) was the whole blocker: with
engine_core.h declaring the byte truth, the family swept 137/137 with ZERO failures — no draft
change, no new lever.
before (header wrong) 0/137 `conflicting types` / a --fix-def-sig-truncated draft
after (header right) 137/137, 0 failed
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, dedup 1886/0); 0 NON_MATCHING (G4).
METRICS: instr 86.0% -> 86.1% (11307777 -> 11318463 = +10,686 ins, exactly 137 x 78);
fn-count 90.77% -> 90.81% (321061 -> 321198 = +137); distinct-code 76.7% -> 76.7% (+0).
The distinct-code anomaly now has FIVE data points (T52 +125, T57 +125, T56 +0, T58 +0, T63 +0) and
still no identified variable. Unchanged as the queued probe.
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).
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).
Ran the batch with the T57 recipe (--band all --normalize-self-decls, live stubs derived from src/
not the stale map). 6 of 8 selected (two still filtered — selection line read this time).
821 candidate members across 6 families
BANKED 137 — func_8012A1BC (78 ins) 137/137
failed 684 — the other FIVE families banked 0 each
Attribution from git diff (137 x func_8012A1BC), not the per-group log lines whose split-name field
my first aggregation mangled.
THE SHAPE OF THE REMAINING FRONTIER — the finding. Across T56->T58 the per-family outcome is BINARY
and near-total: a family banks ~137/137 or ~0/137, nothing in between. And each 0/N so far has had
its OWN distinct cause — DATA decl scope (T56), FUNCTION decl scope (T57), jtbl table-count drift
(func_8014032C), plus five more undiagnosed here. The mechanical lever is done pulling by itself:
from here each family costs one diagnosis. A batch is now a DIAGNOSIS QUEUE, not a harvest, and the
next phase of this work should be planned on that economics.
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, dedup 1886/0); 0 NON_MATCHING (G4).
METRICS: instr 86.0% (11297091 -> 11307777 = +10,686 ins); fn-count 90.73% -> 90.77% (+137);
distinct-code 76.7% -> 76.7% (+0).
The distinct-code anomaly now has FOUR data points and still no explanation: T52 +125, T57 +125,
T56 +0, T58 +0. All four families are PURE; the exemplar overlay does not separate them either (T56
and T57 both templated from ov_SC01_077 and disagree). Two behaviours, no identified variable.
Still not guessed at — it stays the queued probe.
First batch off the 64-family list. Fleet crosses 86.0% instr-weighted.
TWO OF MY OWN ERRORS, both caught by measuring:
1. Three of five targets never ran — --band defaults to `substantial` (nins>=80) and I picked three
at 79/78/78. The tool printed "2 matched-exemplar families" and I nearly read that as "5
attempted, 3 refused". Read the SELECTION line, not the intent.
2. Stale map: .run/family_hseq.json was regenerated in T55, BEFORE T56 banked func_80144090, so it
still listed 134 live stubs for a now-complete family. Membership is stable (h_seq over original
bytes); only the matched/unmatched split rots. Filter live stubs from src/, not from n_matched.
THE FIRST RUN WAS 0/268 — AND IT WAS A SECOND OPT-IN LEVER, NOT A WALL. Diagnosed one sibling past
the -j16 interleave and the §58 warning noise: `conflicting types for func_80133AB0` (spliced def at
2688 vs a decl at 2429) — the FUNCTION decl-conflict class, not the DATA one T56 fixed. That is
exactly what --normalize-self-decls exists for (the sibling's own caller declares the member in a
different C form than the exemplar's, which used a fn-ptr cast) — and it is OPT-IN, so it never ran.
Re-ran the identical two families with it: 0 -> 132 banked.
0x80133ab0 (137 ins, jr_8012ACE0) 132/132 BANKED
0x80143d28 (80 ins, jr_80140608) 0/136 — a different, undiagnosed blocker
THE PATTERN, TWICE IN A ROW: T56 the DATA decl lever was unreachable from the sweep path; T57 the
FUNCTION decl lever is reachable but OFF BY DEFAULT. Both present as a flat 0/N that reads exactly
like a compiler wall. A 0/N from a sweep is a statement about which levers were enabled, not about
the code.
GATES: R22 clean-fleet 140 passed, 0 failed of 140; tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, dedup 1886/0); 0 NON_MATCHING (G4).
METRICS: instr 85.8% -> 86.0% (11279007 -> 11297091 = +18,084 ins); fn-count 90.69% -> 90.73% (+132);
distinct-code 76.4% -> 76.7% (67812 -> 67937 = +125).
SHARPENS the T56 anomaly rather than resolving it: 132 banked here moved distinct-code +125, and
T52's 132 also moved it +125 — but T56's 136 moved it +0. Three PURE families, two behave one way
and one the other. Still unexplained, still not guessed at.
T55's two-part next step as one job. +20,944 instructions banked.
1. THE LEVER WAS UNREACHABLE FROM THE PATH MOST FAMILIES USE (cookbook §107)
§103 was wired into jtbl_family_bank only (T53), and that tool runs for has_mid_jr families.
Everything else sweeps through family_sweep, which gates via PLAIN harvest_verify by design — so
the lever existed, was byte-proven, and most families could not reach it. The symptom was
indistinguishable from a compiler wall: func_80144090 swept 0/136 with `conflicting types for
D_800A651C`.
Why it does not violate the plain-harvest_verify rule: that rule exists because gate_stage's
transforms PERTURB A CORRECT DRAFT (§19/T3). The tu-scope never touches the draft — it moves a
DECLARATION IN THE TARGET TU. The test is not "is it a transform" but "does it change the draft?"
Reused the existing undo instead of inventing one: family_sweep already snapshots TUs it edits at
staging time (--normalize-self-decls) and reverts on a final MISMATCH (not byte-neutral) AND on a
zero-bank group (§61 undo law — no dead diff). The tu-scope shares that dict and inherits both
backstops; renamed nsd_snapshots -> tu_snapshots. Default ON with --no-tu-scope to A/B it (the T24
--allow-pins precedent): byte-neutral by construction, a no-op when nothing collides, auto-reverted
when it buys nothing.
2. THE DUPLICATE-DECL REFUSAL RELAXED — AND IT DID NOT MATTER
scope_tu_externs refused N>1 file-scope decls as "ambiguous"; duplicate-IDENTICAL externs are legal
C, so N identical decls are one decl written N times. Now compares whitespace-collapsed forms and
refuses only on genuine disagreement. MEASURED, and my hypothesis was WRONG: D_800B9A02 is 3 decls
in 2 DIFFERENT forms, so it was correctly refused all along — the family banked 136/136 without it.
RESULT: func_80144090 0/136 -> 136/136, 0 failed, with NO change to any draft.
GATES: R22 clean-fleet 140 passed, 0 failed of 140. tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, report/lint/dedup 1886/0). 0 NON_MATCHING (G4).
METRICS (reconciled against make report):
instr-weighted 85.7% -> 85.8% 11258063 -> 11279007 = +20,944 ins
fn-count 90.65% -> 90.69% 320656 -> 320792 = +136
distinct-code 76.4% -> 76.4% +0 (67812 unique, UNCHANGED)
FLAGGING the third row rather than explaining it away: 136 banked functions moved distinct-code by
ZERO, where T52's 132 moved it by +125, and both families are classed PURE. I do not have a verified
cause and will not invent one — either a real property of this family or a gap in the metric. Worth
one probe before that number is quoted again.
T51's payoff. The invocation is IDENTICAL to the T49/T50 runs; the only variable is T51's decl
scoping.
T49/T50 (pre-T51) 4 banked / 133 gate-fail (and all 4 were SC07 — a different cause)
T52 sample (8) 8 BANKED / 8 52s
T52 rest (124) 124 BANKED / 124 13m04s
TOTAL 132 / 132, ZERO failures
So the 133 "gate-fails" were never a codegen wall — they were one file-scope declaration per sibling
TU. Fifth time this phase a wall has resolved to tooling/plumbing.
GATES (from a genuinely clean tree): R22 clean-fleet `make clean && extract-all && check-all` ->
140 passed, 0 failed of 140. `make tools-health` OK — corpus 0 PHANTOM + 0 TRUNCATED, cdecl,
audit-binaries, report/lint/dedup 1886 validated / 0 failed (C1 239604/239604). 0 NON_MATCHING (G4).
METRICS (reconciled against make report, not asserted):
instr-weighted 85.5% -> 85.7% 11240111 -> 11258063 = +17,952 ins
distinct-code 76.1% -> 76.4% 67687 -> 67812 unique fns (+125)
fn-count 90.62% -> 90.65% 320524 -> 320656 = +132 functions
INCLUDE_ASM stubs 33189 -> 33057 = -132
+17,952 templated instructions against T50's ~18,000 estimate. distinct-code gains 125 not 132
because seven siblings are byte-identical to code already counted unique.
ALSO SETTLED:
- item 3 is now byte-confirmed, not just inspected: [gather_externs] warned "func_80135D20 ... the
sibling will not compile" on ALL 132, and all 132 BANKED. A 100% false-alarm rate on this family,
actively masking real causes. cdecl._mask is the fix (T51 used exactly that).
- the T51 pre-pass is now worth folding into jtbl_family_bank; T51 withheld that pending a measured
payoff, and 4/137 -> 137/137 is it. Next task.
config/ (per-overlay splat.*.yaml + overlays.mk, written by the carve) is staged alongside src/ —
the `git add -A src/` omission this phase already recorded once.
Bounded sample before scaling (the standing validate-on-a-sample invariant). The ONLY variable vs
the T49/T50 runs is T51's decl scoping; the invocation is identical.
T49/T50 (pre-T51): 4 banked / 133 gate-fail (and all 4 were SC07, a different cause)
T52 sample: 8 BANKED / 8 in 52s
Committed here only because jtbl_family_bank's precondition refuses to run on a dirty config//src/
(its per-sibling revert restores from HEAD, so uncommitted banks would be silently wiped). The
remaining 124 follow in the next commit; R22 clean-fleet gates the whole task at the end.
Both config/ (the jtbl carve + overlays.mk) and src/ are staged — the omission this file already
warned about after a prior `git add -A src/`.
Also confirms item 3 empirically: [gather_externs] warned "func_80135D20 ... the sibling will not
compile" on every one of the 8, and every one BANKED. Comment-scanning false positive, as T50 said.
Item 1 off the SESSION-23 list. T48 proved the lever by hand on the exemplar, T50 located the same
blocker in every sibling; this builds the tool, measures the population, applies it fleet-wide, and
gates it. It BANKS NOTHING — it removes the blocker. The sweep is the next task.
MEASURED BEFORE BUILDING (R35). The blocker census over all 132 still-stubbed siblings is perfectly
uniform: 132/132 carry it, 3 contested symbols each, EXACTLY ONE file-scope decl statement per
(TU, sym), ZERO file-scope references below the decl (so the deletion is always safe), 660
block-scope re-declarations needed.
THE TOOL: tools/scope_tu_externs.py — the TU-side complement of scope_data_externs.py (§8d). §8d
fixes the incoming DRAFT and has a give-up branch that DROPS the draft's own decl when the TU already
declares the symbol at file scope. Right when the types agree; fatal when the byte-true draft needs a
different one — which is exactly how 132 byte-true siblings gate-failed wearing a codegen wall's
costume. This moves the TU's OWN file-scope decl down into every later function that references the
symbol and lacks its own block-scope decl, then deletes the file-scope line.
FILE(u8 D_x) ... then BLOCK(u16 *D_x) below it -> conflicting types (the 132 failures)
(no file-scope decl) ... BLOCK(u8) ... BLOCK(u16 *) -> builds; each fn owns its own view
- contested set DERIVED, never hand-listed (R33): the remapped draft's block-scope D_ externs
intersected with the TU's file-scope decls above the splice point; --family does it per sibling
- built on cdecl.split_statements/_mask (R33), not a 7th regex: depth-0 spans (a fn definition
flushes at its closing '}' — a column-0 test is NOT a file-scope test, m2c emits goto labels at
column 0 inside bodies) + length-preserving comment/string masking. That masking is what kills the
comment-scanning false-positive class still open as item 3.
- REFUSES LOUDLY, never skips silently (R32): >1 file-scope decl above the splice point; a
file-scope statement below the decl referencing the symbol; an unlocatable body brace
- coverage asserted as a DELTA (R32): file-scope -1, block-scope +len(consumers). An absolute
"a block-scope decl exists" check would have passed VACUOUSLY — these TUs already carry ~18
legitimate block-scope decls of the same symbols
VERIFIED IN TWO STEPS (T48's structure — why a 132-file edit was safe to make):
1. the move ALONE on ov_SC01_000 -> make build -> 9052dc0e BYTE-IDENTICAL, then reverted
2. fleet-wide -> R22 clean-fleet (make clean && extract-all && check-all) -> 140 passed, 0 failed
of 140; make tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED, cdecl, audit-binaries,
report/lint/dedup 1886/0). Metrics UNCHANGED at 85.5% instr / 76.1% distinct / 90.62% fn-count
— the correct result for a declaration-only change.
The diff is uniform to the line: all 132 files +11/-3. A second --family run reports 132
nothing-to-do, 0 refused (idempotent).
Deliberately NOT done: wiring this as an automatic jtbl_family_bank stage. That waits until the
sweep measures the payoff — folding an unproven pre-pass into the gate is the same unmeasured
premise this phase keeps catching.
Also preserves .run/near6/g5260_a.c (the T48 raw crack body, allowlisted) — the sweep may need it
for --raw.
cookbook §103 + SETUP tool-inventory row (R21).
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.
The T45 probe re-filed this as a crack target; it turned out to be a SCOPE problem, and the fix is a
new reusable lever.
DIAGNOSIS. The draft MATCHes standalone (136 ins) with block-scope `extern u16 *D_801870AC/B0/B8`,
which are byte-TRUE (they produce the target's 4-byte pointer loads). The TU carries FILE-scope
`extern u8 D_801870B0/AC/B8; extern s16 *D_801870B4;` at lines 3433-3436 — the preamble of the
already-banked func_80135168 — and a file-scope decl constrains EVERY LATER function in the TU, so
the draft's pointer decls became "conflicting types". Ordering is what makes this asymmetric: the
TU's own block-scope `extern u16 *D_801870B0;` at L2829 precedes the file-scope u8 decl and only
WARNS; a block-scope decl AFTER it is an ERROR.
TWO WORKAROUNDS MEASURED AND REJECTED, both +3 instructions with a rotated callee-saved bank:
reconcile_tu (conform to the TU) -> 139 ins vs 136, 123 mismatched
cast-at-use (*(u16 **)&D_x) -> 139 ins vs 136, 123 mismatched
So the byte-true code genuinely REQUIRES the pointer-typed declaration; the decls had to move.
THE FIX (move the decls, never the draft — §85 applied to DATA): scoped those four file-scope externs
into their only two consumers (func_80135168 and func_80135480, both of which already use the
cast-at-use idiom). Verified in two steps: (1) the decl move ALONE rebuilds ov_SC01_077 byte-identical
d19c9580 — declaration-only, no codegen change; (2) the original byte-true draft then banks clean,
verified 1 / failed 0. R22 clean-fleet 140 passed, 0 failed of 140.
THE REUSABLE LEVER: a FILE-scope extern in a shared overlay TU is a global constraint on every later
function in that TU. When a byte-true draft needs an incompatible type for the same symbol, scope the
existing decl to its consumers rather than bending the draft — bending it cost +3 here, twice.
Family sweep is NEXT and needs the §53 carve path (has_mid_jr: true, 137 siblings, PURE) —
family_sweep correctly refused it.
The §99 conform_decls pass REFUSED this one (§85: 414 callers consume the return), so it was solved
from the DRAFT side. Three blockers, each measured:
1. §94 type-carry, and the draft's own header asserted something FALSE — it claimed both typedefs
already exist in engine_types.h. Measured: Hw4 1 hit, Prim4 1 hit, Env_800D29F8 ZERO. So in the
real TU the #ifndef guard is DEFINED and the typedef vanished -> "parse error before D_800AE7BC".
2. Signature axis: conformed the DRAFT to the fleet's declared `s32 *` return, then param 2
(s16 * -> Prim4 *). Byte-neutral because `src` is used EXACTLY once, as (s32)src. The error
("argument `src' doesn't match prototype") is again printed with NO "error:" prefix.
3. The family sweep went 0/137 TWICE before 137/137.
THE REUSABLE FINDING — a 0/N sweep whose exemplar banks cleanly is the signature of an extract_unit
carry gap. Measured on the staged member drafts:
file-scope extern -> CARRIED
file-scope #define -> CARRIED, but only while its expansion's deps stay file-scope
file-scope typedef -> NOT carried (silently dropped)
#define whose expansion references a BODY-LOCAL extern -> NOT carried
RECIPE: make the draft SELF-CONTAINED — body-local typedefs survive (PTag_80140D68 in this same
draft was the proof all along), and if that pushes a macro's dependency body-local, inline the macro
at its use sites. 0/137 -> 0/137 -> 137/137, 0 failed, each step byte-measured.
R22 clean-fleet 140 passed / 0 failed of 140; dedup-check 1886/0.
Fleet 85.5% instr, 76.1% distinct, 90.57 -> 90.61% fn-count.
§99 arc total (T41-T43): 133 + 1 + 137 = 271 functions. Both blockers Drew green-lit are CLOSED.
Drew green-lit the fleet-shared change. One function at a time from a committed-clean baseline, dry
run first, R22 after each step — the discipline the T39 shared-state hazard earned.
- conform_decls --fn func_80177DA8 --apply: byte-true def `void func_80177DA8(u8 *p, u32 v, s32 idx)`;
268 declaration sites rewritten across 268 files; the tool's own R32 completion assertion reports
"non-canonical declarations remaining: 0 OK (axis complete)" (§85 all-or-nothing as a COUNT, not a
hope). Nothing under src/shared, config or include. R22 -> 140/140: the decl axis is byte-neutral.
- Re-sweep: BANKED 133 / 0 failed, skipped {not-stub: 4} => the family went 4/137 -> 137/137, exactly
reversing T40's failure. R22 -> 140/140. dedup-check 1886/0.
- Fleet 85.4 -> 85.5% instr, 76.0 -> 76.1% distinct, 90.54 -> 90.57% fn-count.
T42 func_80140D68 — the pass correctly REFUSED it (414 callers consume the return, so widening the
return type is not byte-neutral, §85). Diagnosed in the real TU instead (rtu_match + reading ALL
stderr per §95 — gcc-2.7.2 prints hard errors with NO "error:" prefix, so grepping for "error" finds
nothing):
1. parse error before D_800AE7BC = a §94 TYPE-CARRY defect, and the draft's header asserts something
FALSE: it claims Hw4 AND Env_800D29F8 both already exist in engine_types.h. Measured: Hw4 1 hit,
Prim4 1 hit, Env_800D29F8 ZERO. FIXED by keeping Hw4 guarded (it does exist) and moving
Env_800D29F8 outside the guard, draft-local per §100. Still MATCH (65 ins).
2. conflicting types — conformed the DRAFT's return to the fleet's declared s32 * (still MATCH).
Only remaining delta: param 2 byte-true `s16 *` vs declared `Prim4 *`. conform_decls still refuses
(its return-axis precondition fires regardless). OPEN, with the next probe named.
family_sweep --hseq --band all --only <4 cores> -j12 -> 143 banked / 405 failed. R22 clean-fleet
140 passed, 0 failed of 140; dedup-check 1886/0. Fleet 85.3 -> 85.4% instr, 75.8 -> 76.0% distinct,
90.50 -> 90.54% fn-count.
Unlike T33's 548/548, this sweep mostly failed — so the failures were DIAGNOSED, not accepted:
- func_80138C60 swept 137/137 clean.
- func_8013B6A0 / func_8013B598 swept 1/137 each — EXPECTED, not a regression: Phase 20 byte-proved
the -O0 cluster is OVERLAY-LOCAL, so their siblings need per-overlay _o0 carves that do not exist.
- func_80177DA8 swept 4/137 — ROOT CAUSED: its banked def is K&R and its own TU declares it no-proto,
but NON-SC07 overlays declare a PROTOTYPE (extern void func_80177DA8(s32,s32,s32)), so the remap
conflicts. The 4 successes are SC07 overlays, which declare it not at all.
THE SYNTHESIS: that is the SAME §99 K&R-vs-prototype class as item 3's func_80140D68 (K&R def vs 138
prototype callers). ONE conform_decls pass unlocks both — ~17,000 instructions. conform_decls exists
for exactly this ("the draft's signature is byte-TRUTH; move the DECLS, never the draft"). NOT run:
it is a fleet-shared 138+-declaration change and this session already tripped one shared-state
hazard, so it wants an explicit go-ahead (P5).
MY ERROR, recorded: I read a `head -6` list of modified dirs as the complete set and briefly thought
the sweep's count did not reconcile. Measured properly it does — 143 stubs removed across 142 files.
Same class as grepping the wrong field earlier today: truncated output is not exhaustive output.
Worked Drew's order 1->2->3->4 at xHigh (no fan-out).
ITEM 1 func_80176734: permuter COMPLETELY FLAT at 13 (8 cycles x 240s, regalloc profile chosen over
the classifier's cse because the residual is 3 register 2-swaps). Not one improving waypoint in 32
min. THIRD ADDRESSING-bucketed target in a row where the permuter under-delivers (11->7, 10->6,
now 13->13 flat) — the T31 routing finding is now well evidenced. Remaining: the reg_renumber-swap
gdb oracle; feasibility confirmed (cc1 unstripped, reg_renumber @0x82d4330, prior-art .gdb exists)
but it needs a .greg pseudo-identification pass, so not started.
ITEM 2: 4 of 7 banked — func_80177DA8, func_8013B6A0, func_8013B598, func_80138C60. THE BARE GATE
WAS THE UNLOCK: gate_stage reported failed:2 on the _o0 pair while bare harvest_verify reported
verified 2/failed 0 on the SAME drafts, and rtu_match independently confirms func_8013B6A0 matches
in the real TU. That gives the carried "ladder-vs-bare-gate asymmetry" defect a REPRODUCTION — the
ladder is destroying good drafts, not diagnosing them. All 4 are reach-138 PURE families =
35,604 templatable instructions.
SHARED-STATE HAZARD hit and repaired: the failed func_80135260 attempt left fix_arity_callers
--any-proto edits in 17 TUs holding none of my banks (the bare gate has no snapshot/restore, unlike
the ladder after the Task-14 incident). Caught by diffing the tree, not by the tool's report.
Reverted the 17, kept the 3 bank-bearing files, re-verified R22 clean-fleet 140/140. Nothing under
src/shared, config or include was touched, so blast radius was ov_SC01_077-local (§63).
ITEM 3 func_80140D68: fails even bare-gated, and the PREDICTED CAUSE WAS WRONG — there is no
DEFINE_func_80140D68 macro. Real conflict is §99 K&R-vs-prototype: draft is K&R `u32 *`, 138 callers
declare `extern s32 *func_80140D68(s32 *, Prim4 *, s32, s32, s32);`. Lever exists (§99 did this at
1,072-decl scale today) but it is a fleet-shared 138-decl change. Scoped, not attempted.
ITEM 4 func_80178004 biv-init wall: RE-PROBED and UPHELD — my own hypothesis refuted. The cited
mechanism (loop.c:3803/3823, benefit->0 eliminates emit_iv_add_mult) is verbatim present in real
2.7.2 inside strength_reduce (3214); loop.md's flagged version difference is in combine_givs, which
this verdict does not rest on. The wall stands.