Commit Graph

231 Commits

Author SHA1 Message Date
Drew T 60f9ac40f3 feat(phase-29): T64 — func_8014D610 swept 137/137 after the header correction (+10,138 ins)
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).
2026-07-28 22:10:10 -06:00
Drew T a850255572 feat(phase-29): T63 — func_8016163C swept 137/137 after the header correction (+10,686 ins)
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.
2026-07-28 21:50:19 -06:00
Drew T 2d7694ba2d feat(phase-29): T58 — 8-family batch: 1 of 6 banked (func_8012A1BC 137/137, +10,686 ins)
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.
2026-07-28 20:55:35 -06:00
Drew T cbc5665fd8 feat(phase-29): T57 — func_80133AB0 132/132 (+18,084 ins); a SECOND opt-in lever found; fleet 86.0% instr
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.
2026-07-28 20:37:06 -06:00
Drew T 56e2d808ab feat(phase-29): T56 — wire the tu-scope lever into family_sweep; func_80144090 0/136 -> 136/136
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.
2026-07-28 20:15:11 -06:00
Drew T d4dc533f54 feat(phase-29): T52 — func_80135260 swept 132/132 (0 failed); the family goes 4/137 -> 137/137
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.
2026-07-28 17:27:20 -06:00
Drew T 69dee1d429 docs(phase-29): T50 + SESSION-23 REVISED final checkpoint
T50 func_80135260 family: the §53 carve path banked 4/137 (all SC07), 133 gate-fail, tree clean
after every revert. The 3,744-site conform_decls between runs changed NOTHING for this family (99
attempts observed mid-run, 0 banks) — it is byte-neutral and axis-complete so not harmful, but my
inference that this family shared func_80177DA8's blocker was WRONG: same SC07-only signature,
different cause.

THE REAL BLOCKER, LOCATED: staged siblings are correctly remapped (family_remap works). The draft
requires 4-byte POINTER decls for the contested data symbols — the canonical extern u8 +
(*(u16**)&sym) form makes gcc CSE &sym into two callee-saved regs, costing a 7th saved register and
3 extra instructions (the identical +3 measured on the exemplar). And every sibling host TU carries
the same FILE-SCOPE blocker the exemplar did: verified on ov_SC01_000, whose host TU declares the
contested symbols at file scope (lines 3053-3056) alongside 18 block-scope occurrences. A file-scope
decl constrains every later function in that TU — the T48 finding.

So the fix is the T48 lever replicated x137: scope those decls into their consumers per sibling TU.
Byte-neutral on the exemplar (proven in two steps). That is a TOOL, and it is worth ~18,000 ins.

Also: gather_externs' warning naming func_80135D20 is a COMMENT-SCANNING FALSE POSITIVE (the symbol
appears only in header prose and is defined in another split file). Fires on all 137, masks real
causes. Same class as the Phase-19 garbled-hint bug.

CHECKPOINT REVISED (supersedes the earlier SESSION-23 block): 975 functions banked, reconciled
against the metric (fn-count 319,549 -> 320,524) with the per-task recount agreeing exactly. Fleet
85.5% instr / 76.1% distinct / 90.62% fn-count. R22 140/140 run 11x, dedup 1886/0, 0 NON_MATCHING.
Ranked START-HERE (decl-scoping tool first), the four strategic changes, my five recorded errors —
whose common thread is inference from partial output instead of measuring — and the carried defects.
2026-07-28 16:16:42 -06:00
Drew T 6fad5d19c8 feat(phase-29): T43 — func_80140D68 banked + swept 137/137; the §94 extract_unit CARRY GAP characterized
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.
2026-07-28 14:17:50 -06:00
Drew T 59785974f0 feat(phase-29): T41 — §99 conform_decls: func_80177DA8 family 4/137 -> 137/137 (0 failed)
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.
2026-07-28 14:05:42 -06:00
Drew T 37e5a19558 feat(phase-29): T40 — sweep 143/548; the 405 failures are one named class (§99 K&R-vs-prototype)
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.
2026-07-28 13:50:28 -06:00
Drew T 46870139bd feat(phase-29): T33 — 548/548 family members banked (0 failed); fleet 84.8 -> 85.3% instr
- family_sweep --hseq --band all --only <4 cores> -j12 -> BANKED 548 member-matches / 0 failed
  across 137 overlays. Preconditions CHECKED not assumed: map regenerated first (sig-overlays +
  family_hseq) so the exemplars read matched-ov077 not the stale draft-ov077; all 4 families
  has_mid_jr=false (§53 carve law) and diff_class PURE 137/137; --band all because two cores are
  `mid` and the default `substantial` band would have silently dropped them; --reconcile-raw avoided.
- R22 clean-fleet after the sweep: 140 passed, 0 failed of 140. dedup-check 1886 validated / 0
  failed, C1 coverage 239604/239604, 0 NON_MATCHING in any default build (G4).
- SESSION ARC: instr 84.8 -> 85.3%, distinct-code 74.7 -> 75.8%, fn-count 90.34 -> 90.50%.
  552 functions banked (4 exemplars + 548 members) ~= 74,802 templated instructions.
- sched.md SOURCE-VERSION CORRECTION: the map declares its source as gcc-papermario, which Phase 23
  established is gcc 2.8.1 — not our 2.7.2 — and it was never re-derived. Citations are correct for
  the WRONG compiler. One claim is byte-refuted and load-bearing: §1.7/§S12 said the S2 birthing
  boost needs SET(REG_pseudo,...) so pins must be removed ("Unpin first"); real 2.7.2
  birthing_insn_p (sched.c:2469) tests only GET_CODE(SET_DEST)==REG with NO pseudo check and gates on
  reg_n_sets==1 (2490) — hard-reg dests ARE boosted. Corrected in place (old text struck, not
  deleted) + a hand-verified 2.7.2 cross-reference table and a warning block.
  DRIFT IS NOT UNIFORM: ~+27 in sched.c but +103/+377/+611 in local-alloc.c/reload1.c — big enough to
  land inside a different function. ~44 drifted citations across sched/regalloc/loop .md (a screen,
  a lower bound). regalloc.md is worst and is NOT yet re-derived — named as next.
- All line numbers verified by me against tools/reference/gcc-2.7.2, not taken from the agents.
2026-07-28 11:36:33 -06:00
Drew T 75bed15697 feat(phase-29): func_80171B4C family banked 137/137 — wave22 complete (690 functions)
137/137 banked via jtbl_family_bank (jr family, carve-aware path). R22 clean-fleet 140 passed /
0 failed of 140. MEASURED: fn-count 319,412 -> 319,549 (+137); instr-weighted 84.7 -> 84.8%
(+9,590 ins); distinct-code 74.5 -> 74.7% (+130 unique fns).

WAVE22 COMPLETE: 18 targets drafted (12 MATCH / 6 NEAR / 0 FAIL, 2.59M subagent tokens) ->
5 exemplars banked -> 685 members swept -> 690 functions total.

This commit stages config/ EXPLICITLY. Twice today I omitted it and left a carve uncommitted, both
times caught by jtbl_family_bank's dirty-tree precondition rather than by me or any gate.
2026-07-28 01:03:33 -06:00
Drew T 687d761bde feat(phase-29): wave22 families swept 548/548 (R22 140/140) — parallel gating proven at scale
4 families x 137 members: BANKED 548 / 0 failed. R22 clean-fleet 140 passed / 0 failed of 140.
MEASURED: fn-count 318,859 -> 319,412 (+553); instr-weighted 84.4 -> 84.7% (+36,640 ins);
distinct-code 74.4 -> 74.5% (+134 unique fns).

TODAY'S PARALLEL GATE WIRING PROVED AT SCALE: this run reported `gating 411 group(s) across distinct
binaries, -j12`. When I shipped it earlier I could only smoke-test 4 fail-fast groups and said
explicitly that the 1.5x measured there was NOT the 8-16x claim; 411 full build-and-gate cycles is
the shape the claim was about.

A PERFECT 548/548 also says the wave's exemplars were right for the right reasons — a body that
templates across 137 byte-variant siblings with zero rejections is not a marginal match.

BAND NOTE: the first sweep attempt used --band substantial and staged NOTHING; these exemplars are
60-76 ins, i.e. the MID band (substantial is >=80). The tool reported that honestly
("0 matched-exemplar families (band=substantial); 0 candidate members") rather than returning a
clean-looking 0 banked — the skip-vs-result distinction this session kept running into.
2026-07-28 00:22:00 -06:00
Drew T d109f591f9 docs(phase-29): item 1 — grinder 4 wins/2 banked (reach-1, R22 140/140); its targeting census is the real result 2026-07-27 22:39:34 -06:00
Drew T 2863acb83c feat(phase-29): func_80175DA8 0/137 -> 137/137 by moving ONE typedef into the body (§100)
Its 0/137 was the §94 TYPE-CARRY signature: the draft defines `typedef struct {…} Sp_80175DA8;` at
FILE scope, and remap_hseq templates the BODY but not the type, so every sibling compiled without it.

§94's remedy is the shared engine_types.h lift (right for func_8016B6BC, whose four types were
transitively referenced). But the cheap remedy was already in the same draft: it carries S_AF634 at
BLOCK scope and that templates fine, because a type declared in the body travels WITH the body.
Sp_80175DA8 is used by that function ONLY (7 mentions, 6 inside the body, 0 elsewhere), so moving it
into the body is byte-neutral (d19c9580 unchanged), T0, zero blast radius — versus editing a header
included by 140 binaries with uniquify/collision care and an R22.

Re-swept: 137/137, 0 failed. R22 clean-fleet 140 passed / 0 failed of 140.
MEASURED: fn-count 318,720 -> 318,857 (+137); instr 84.2 -> 84.4% (+31,647 ins); distinct-code
73.9 -> 74.4% (+129 unique fns).

§99 AND §100, AN HOUR APART, ARE THE SAME LESSON: both times the cookbook's named remedy was the
expensive fleet-wide one (524-site decl conform / shared-header lift) and the correct fix was
DRAFT-LOCAL (K&R definition / block-scope typedef). Before editing anything shared, ask what the
smallest scope is that still travels with the body.
2026-07-27 21:43:20 -06:00
Drew T a884d5f5d6 feat(phase-29): func_80175AB8 swept 133/137 via --allow-pins — a STALE GUARD was skipping them
The first sweep returned "banked 0 / skipped {'pinned-exemplar': 137}" — a SKIP, not a failure. The
§42e guard refuses pinned exemplars to avoid a cc1 SIGABRT, but Phase 27 BYTE-PROVED that crash was
extract_unit dropping file-scope macros (a TOOL bug, fixed by _carry_macros), not a compiler limit.
Re-run with --allow-pins: 133/137 BANKED. R22 clean-fleet 140 passed / 0 failed of 140.

MEASURED: fn-count 318,585 -> 318,720 (+135); instr 84.0 -> 84.2% (+25,423 ins); distinct-code
73.4 -> 73.9% (+127 unique fns).

THE GUARD IS NOW COSTING BANKS — the same shape as sweep_parallel being opt-in: a protection that was
correct when written, whose cause was later removed, still defaults ON. Measured cost on ONE family:
137 skipped, 133 bank fine. Phase 27's roadmap delta already said the PINS class was back on the
table; nothing changed the default. Flipping it is a one-line change, deliberately deferred to a
fresh session — that is exactly how family_sweep got broken twice today.

SC07 QUARTET, third occurrence today, now named: ov_SC07_006/007/010/011 refused again (same four as
func_80176218). NOT broken — func_8014CF04, func_8015D1B8 and func_801789AC all swept them cleanly.
The correlation is the sibling TU (_jr_8016AE5C.c, a different carve layout; these 4 were onboarded
in Phase 27 with code at PAC entry 1). §59: read ONE sibling's real gate result before concluding.

func_80175DA8 0/137 is the §94 TYPE-CARRY signature (local typedef Sp_80175DA8 templated as a body
but not as a type) — the same shape that took func_8016B6BC 0/137 -> 137/137 today. Named next step,
31,878 templated instructions.
2026-07-27 21:35:11 -06:00
Drew T 3d01aaea8c feat(phase-29): func_801789AC family banked 137/137 — fleet crosses 84% instr
137/137 banked, 0 failed via jtbl_family_bank. R22 clean-fleet 140 passed / 0 failed of 140; report
fail-closed green (dedup 1886/0, C1 coverage 239604/239604, 0 NON_MATCHING).

MEASURED: fn-count 318,447 -> 318,585 (+138); instr-weighted 83.9 -> 84.0% (+12,558 ins);
distinct-code 73.2 -> 73.4% (+131 unique fns — byte-VARIANT members, so unlike func_801330E0's
byte-identical family this one moves the distinct number too).

Closes the function REFUSED since SESSION-21 — correctly refused, since conforming its 660
declarations without first casting its 138 zero-arg call sites would have broken 138 binaries.

Also logged (T21): the sweep-throughput measurement. Drew was right that parallelism was proven and
adopted (Makefile JOBS=16; sweep_parallel.py -j12 built SESSION-20 after measuring an 8-16x loss),
but NEITHER sweep tool calls it — the adapter is reachable only via a manual --stage-only two-step,
so three sweeps today ran serially for no reason. The -j theory was wrong and measurement said so:
make is ~5s of the 16s per sibling (the loop runs up to FOUR builds per sibling), so -j16 is a 12%
win, kept but minor. The real 8-16x lever is blocked on revert() restoring the SHARED
config/overlays.mk from git — designed, not built. An attempt to wire family_sweep's parallel default
broke it twice and was reverted rather than committed.
2026-07-27 21:16:39 -06:00
Drew T 8f85c5b967 feat(phase-29): func_801330E0 family swept 137/137 (R22 140/140) — fn-count crosses 90%
137/137 banked, 0 failed. R22 clean-fleet 140 passed / 0 failed of 140.
MEASURED: fn-count 318,309 -> 318,447 (+138), crossing 90.03%; instr-weighted 83.8 -> 83.9%
(+15,180 ins); distinct-code +1 unique fn.

AN HONEST NUANCE: distinct-code moved only +1 here vs +126 for func_80176218's family, because these
137 members are byte-IDENTICAL (h_exact) and collapse to one distinct function, while func_80176218's
were genuine byte-VARIANTS. Both are real work; they move different metrics. The 3-metric dashboard
exists so one number cannot flatter the other.

This family banked only because conform_decls learned to read K&R definitions an hour ago: one tool
gap, unblocked, became 138 functions.

SESSION-22 TOTAL: 6 exemplars + 680 members = 686 functions.
2026-07-27 19:20:21 -06:00
Drew T e47d68c075 feat(phase-29): func_80135EB0 family banked 137/137 via jtbl_family_bank (R22 140/140)
The largest single family on the census: 137 siblings x 289 ins. Per sibling — jtbl_carve -> make
extract -> remap_hseq + canon_sig_reconcile -> whole-binary gate, revert-on-fail. 137/137 BANKED,
0 failed. R22 clean-fleet 140 passed / 0 failed of 140; report fail-closed green (dedup 1886/0,
C1 coverage 239604/239604, 0 NON_MATCHING).

MEASURED: fn-count 318,171 -> 318,309 (+138); instr-weighted 83.4 -> 83.8% (+39,882 ins);
distinct-code 72.5 -> 73.2% (+131 unique fns).

TWO TOOL REFUSALS MADE THIS BANK POSSIBLE, and both deserve recording:
- family_sweep REFUSED the family (has_mid_jr): §53's carve law says a carve-less sweep there returns
  "a 0% that is a TOOL artifact, not a wall". Overriding with --allow-jr would have yielded 0/137 and
  plausibly filed the highest-value family on the board as a wall.
- jtbl_family_bank REFUSED a dirty tree: its per-sibling revert restores from HEAD, so the
  uncommitted 414-file decl axis would have been destroyed. H4 enforced in code.
This is the inverse of the session's earlier failures, which all came from tools that ANSWERED
instead of refusing.

SESSION-22 TOTAL: 5 exemplars + 543 members = 548 functions.
Fleet: 82.9 -> 83.8% instr, 71.5 -> 73.2% distinct-code.
2026-07-27 18:59:58 -06:00
Drew T a776d3248b feat(phase-29): func_8014CF04 + func_8015D1B8 families swept 273/273 (R22 140/140)
BANKED 273 member-matches / 0 failed across 137 overlays (func_8014CF04 136 + func_8015D1B8 137).
R22 clean-fleet 140 passed / 0 failed of 140; report fail-closed green (dedup 1886/0, C1 coverage
239604/239604, 0 NON_MATCHING).

MEASURED from the committed digests, not projected: fn-count 317,898 -> 318,171 (+273);
instr-weighted 83.2 -> 83.4% (+26,770 ins); distinct-code 72.3 -> 72.5% (+129 unique fns).

A USEFUL NEGATIVE RESULT: both families swept cleanly across ov_SC07_006/007/010/011 — the same four
overlays that refused func_80176218's sweep earlier today. So that set is not broken; the 4/137
refusal is family-specific (the _jr_8016AE5C.c carve), which is the per-sibling INTEGRATION signal
§59 describes rather than a codegen or overlay-level wall. Carried, still not concluded.

SESSION-22 total: 3 exemplars + 406 members = 409 functions.
2026-07-27 17:56:18 -06:00
Drew T 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.
2026-07-27 17:47:57 -06:00
Drew T ea1d6587d6 feat(phase-29): func_80176218 family swept 133/137 (R22 140/140)
+134 functions banked total for this exemplar (1 + 133 members). Measured from the committed
progress.fleet.md, not projected: fn-count 317,762 -> 317,896; instr-weighted 82.9 -> 83.2%
(+43,818 ins); distinct-code 71.5 -> 72.3% (+126 unique fns — these members are genuine byte-
VARIANTS that each count distinctly, not free dedup).

VERIFY: R22 clean-fleet (make clean && extract-all && check-all) -> 140 passed, 0 failed of 140.
make report fail-closed green: dedup-check 1886 validated / 0 failed, C1 coverage 239604/239604,
0 NON_MATCHING in any default build (G4).

THE 4 FAILURES ARE CARRIED, NOT CONCLUDED. All four are ov_SC07_006/007/010/011 and all four differ
from the other 133 in exactly one way: their sibling TU is _jr_8016AE5C.c, not _jr_801734BC.c —
carved under func_8016AE5C, which was banked and swept in SESSION-21. That is the SAME four overlays
and the SAME carve the SESSION-21 checkpoint flagged as "worth checking first" for func_8016B6BC's
0/137, which turned out to be a transitive type-carry (§94) rather than a wall. Each sibling reverted
its byte-neutral self-decl edit cleanly, so no dead diff is left behind. Per §59 a sweep failure is a
per-sibling INTEGRATION signal, not a codegen verdict — read one sibling's real gate result
(COMPILE-fail vs byte-DIFF) before concluding.
2026-07-27 17:07:03 -06:00
Drew T 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.
2026-07-27 16:26:26 -06:00
Drew T 553949d157 docs(phase-29): SESSION-21 final checkpoint + cookbook §92/§93 (the doc gap Drew caught)
CHECKPOINT HYGIENE: between T11 and T12, wave 2 + a bank + a new tool guard were recorded ONLY in
commit messages — CURRENT_PHASE.md and the cookbook were stale for that stretch. The quiet periods
were background sweeps/R22 (~2h each) during which the tree cannot be touched, but that does not
excuse leaving the durable record behind: a stale checkpoint is worse than an absent one. Closed.

cookbook §92 — conforming a DECLARATION: pointer changes are caller-neutral, scalar-WIDTH changes
are NOT. Byte-proven both ways (func_80179B74: 1,600 sites / 523 files / 3 forms, banked, R22
140/140; func_80175DA8: PLUMBING before the conform, DIFF after — the conform did not fix the draft,
it changed the callers). Plus the arity case that broke 138/140, and the counting lesson:
func_8015B950 looked like ~926 call-site casts and needed ONE — its only 0-arg call sits in an
engine_core.h DEFINE macro the preprocessor expands 926 times. Count SITES, not expansions.

cookbook §93 — `set -o pipefail` attributes a pipeline failure to the LAST stage, not the failing
one: cc1 exit 33 reads as an assembler error because `as` ends the recipe. The 2-minute fix is to run
the stages by hand printing each rc, then re-run the failing one with stderr visible. Turned an
opaque Error 33 into a one-line fix twice today. Corollary (§88e, earned): hand a stuck function over
as an UNDIAGNOSED observation, never as a named cause — flagged that way, the agent found the true
cause (cc1 `conflicting types for 'Ent'`) immediately.

func_8014D820 family swept 137/137. func_8016B6BC 0/137 reproducibly — recorded as a DIAGNOSIS task
per §59 (a sweep 0/N is a per-sibling integration signal, not a codegen verdict), never as a wall.
Checkpoint fn-count corrected 89.88 -> 89.80 against the measured report; stray a.out removed (R12).
2026-07-27 16:03:14 -06:00
Drew T 7d9dd6deca feat(phase-29): func_8014D820 banked (41,952 ins) + conform_decls scalar-narrowing guard
WAVE 2 (9 never-drafted exemplars, ultracode): 9/9 returned, 5 MATCH / 4 near, 2.25M tokens.

BANKED: func_8014D820 (304 ins ×138) — and its agent ROOT-CAUSED the failure I left undiagnosed.
It was never an assembler problem: cc1 exit 33, `conflicting types for 'Ent'` vs
engine_types.h:434, surfaced by the recipe's `set -o pipefail` and MISATTRIBUTED to `as` because
`as` is the last stage in the pipe (Makefile:560). Fixed by moving V4/Desc/Ent to BLOCK scope —
byte-neutral and collision-proof across all 138 member TUs. Vindicates flagging it to the agent as
UNVERIFIED rather than passing my own guess forward as fact (§88e).
R22 clean-fleet 140/140.

NEW GUARD — SCALAR NARROWING IS NOT CALLER-NEUTRAL (byte-proven, and it cost 3 gate cycles):
conform_decls treated all decl type changes alike. A POINTER change is caller-neutral (func_80179B74
conformed 1,600 sites s16*/short* -> u16* and stayed byte-identical fleet-wide). A SCALAR WIDTH
change is NOT: narrowing `s32 a0` -> `u16 param_1` changes argument promotion at every call site.
MEASURED on func_80175DA8: decls reverted -> gate says PLUMBING; conform applied -> gate says DIFF.
The conform did not fix the draft, it changed the CALLERS. Now warned explicitly (not refused — the
draft's sig is still byte-truth for the callee and the gate arbitrates), with the instruction that a
DIFF after this conform means examine the callers (§17a-1 pair), not the body.
Verified the guard discriminates: fires on func_80175DA8 (s32->u16), silent on func_80179B74.

STILL OPEN from wave 2: func_80176218 + func_80175AB8 (DATA-symbol conflicts, D_80078EB4 /
D_8011F7BC -> reconcile_decls) · func_80175DA8 + func_80135EB0 (need the §17a-1 caller pair, not a
bare conform) · 4 near-misses with precise residuals recorded (func_80176734 129 length-drift,
func_80140958 49 inverted-hoist, func_80177B5C 19 sched tie, func_8017C974 83 -> permuter).
2026-07-27 15:38:15 -06:00
Drew T acc8d762a0 feat(phase-29): func_80179B74 family swept 137/137 (R22 140/140)
134/134 BANKED on the remainder after 3/3 on the probe — the FOURTH full-family sweep this session,
all four unblocked by the --like role guard, three of them 100%.
R22 clean-fleet: extract-all 139/139, check-all 140 passed / 0 failed.
2026-07-27 14:02:30 -06:00
Drew T 6b9e2b7f33 feat(phase-29): func_8016AE5C family swept 136/137 (R22 140/140)
133/134 BANKED on the remainder after 3/3 on the probe. ONE sibling refused (ov_SC03_108,
gate-fail) and is left as a stub rather than forced — a 136/137 recorded honestly beats a 137/137
that needed a shortcut. Third full-family sweep this session, all three unblocked by the --like
role guard.

R22 clean-fleet: extract-all 139/139, check-all 140 passed / 0 failed.
2026-07-27 12:45:20 -06:00
Drew T d4c4a4d563 feat(phase-29): func_8015B950 family swept 137/137 (R22 140/140)
134/134 BANKED on the remainder after 3/3 on the probe — the second clean full-family sweep this
session, both unblocked by the --like role guard. func_8015B950 is stubbed in NO overlay.
R22 clean-fleet: extract-all 139/139, check-all 140 passed / 0 failed.

At 271 ins x 137 members this is the session's largest single family by instruction weight.
2026-07-27 12:21:07 -06:00
Drew T 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.
2026-07-27 11:56:23 -06:00
Drew T ab3ac83a41 feat(phase-29): func_8012AAAC family swept 137/137 — the --like guard unblocked the whole class
- 134/134 BANKED on the remainder (after 3/3 on the probe) => the family is 137/137, ZERO failures.
  func_8012AAAC is now stubbed in NO overlay. R22 clean-fleet: extract-all 139/139, check-all
  140 passed / 0 failed.
- FLEET 81.9 -> 82.0% instr · 89.60 -> 89.64% fn-count · distinct-code 69.3 -> 69.5%.
- THE METRIC POINT, reproduced twice in one session and in BOTH directions: this jtbl family is
  byte-VARIANT (each overlay's table holds its own addresses), so every member is a genuinely new
  unique function and distinct-code MOVED. The h_seq PURE families swept earlier added 274 members
  and moved distinct-code by +0.0, because those members were already counted via their shared
  exemplar. SESSION-20's routing rule, now byte-demonstrated: target byte-VARIANT families to move
  RE-completeness; high-reach h_exact families move only the display number.
- cookbook §91 — "a structure-TRANSFER is only valid where the structure corresponds": the --like
  role trap, plus the three-hypothesis trail (two wrong, and instructive: the sibling call-site casts
  were a real defect that fixed nothing, and my own carve-alone test was a false lead that departed
  from the tool's real sequence). The law: any "same family => same structure" transfer must state
  which structural fact it assumes and CHECK it on both sides — and a tool that drops an error class
  it cannot act on should still SURFACE it, because a bare `gate-fail` repeated 137 times cost far
  more than printing one line would have.
2026-07-27 11:25:42 -06:00
Drew T 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.
2026-07-27 10:38:10 -06:00
Drew T 5be4c21480 feat(phase-29): SESSION-21 — the ×138 member sweep: 274 members from 3 exemplar cracks (R22 140/140)
- family_sweep --hseq over the 3 newly-banked exemplars: BANKED 274 member-matches / 137 failed
  across 137 overlays, for ~0 agent tokens. Session total: 3 exemplars + 274 members = 277 fns.
- THE STALE-MAP STEP, hit and handled: the first sweep returned "0 matched-exemplar families"
  because .run/family_hseq.json still listed the fresh cracks as draft-ov077. Regenerated
  (matched-sib families 60 -> 63) and the sweep found them — the documented bank-x1 -> regen ->
  sweep path (memory crack-wave-sweep-map-regen).
- §86 REPRODUCED CLEANLY: 2 of 3 families templated ~137/137; the third failed ~137/137. Not a
  rate — a BIMODALITY. One probe per family, then sweep or skip; never a blended pool average.
- R22 clean-fleet: extract-all 139/139, check-all 140 passed / 0 failed (second clean-tree
  verification this session). dedup 1886/0, C1 coverage 239,604/239,604, 0 NON_MATCHING (G4).
- FLEET 81.7 -> 81.9% instr · 89.52 -> 89.60% fn-count · distinct-code 69.3% UNCHANGED — correct
  and expected: these are h_seq PURE propagation-class families, and SESSION-20's routing rule says
  propagation moves only the DISPLAY metric (members were already counted once via their exemplar).
  To move RE-completeness, target byte-VARIANT families. Stated plainly so the next session picks
  targets by the metric it means to move.
- drive-by: family_sweep --help crashed (argparse %-expands help text; a literal "0%" needed "0%%").
2026-07-27 10:08:19 -06:00
Drew T 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.
2026-07-27 09:58:17 -06:00
Drew T d2a79deff2 feat(phase-29): ALL THREE BEHEMOTHS BANKED — func_80183814 (5,122), func_8017DC1C (1,518), func_8017D2DC (1,586)
Zero functions >1000 ins remain unmatched anywhere in the fleet.

func_80183814 (5,122 ins — the LARGEST function in the game) — round 2 closed it: length 5127->5122
exact, structural residual 36->0, register-sensitive 1201->0, frame -256 -> -0xF8 exact, saves
10 -> .mask 0x807f0000 exact. Verified independently (R14): match_one MATCH (5122 ins).
  ROUND 1's DIAGNOSIS WAS WRONG and the agent refuted it properly: the +5 length was a SYMPTOM, not
  the lever, and the §83d max_reg/cse.c:8340 story does not hold — a 15-line reproducer reproduced the
  case-0/3 CSE exactly (so it cannot be max_reg-gated), max_qty only gates extension ACROSS blocks,
  and the target leaves $s7/$fp unused (no pressure story). Confirmed from a second direction: C01 has
  the identical two groups over the identical symbols with ZERO residual, because a `break` puts a
  CODE_LABEL between them. The two biggest levers were pure DECLARATION SCOPE (§45/§76), not pins.
func_8017DC1C (1,518) — MATCH first round, pin-free, zero __asm__ dials. NOT a jr fn (0 mid-fn jr).
func_8017D2DC (1,586) — MATCH first round (banked in the previous commit).

BANKING ORDER MATTERS — a new failure mode found and worked around: banking func_8017DC1C BEFORE the
carve chain broke the build. Its draft establishes the canon for 39 previously-undeclared externs;
jr_isolate_all's re-partition (overlay_src_split) then DROPPED ALL 39 across the new split boundary
(`D_801C1EB0 undeclared`), leaving them in NEITHER file. The §77 preamble-drop class, in a third tool.
FIX = ordering, not patching: run the §81 carve chain FIRST on a clean tree (gated BYTE-IDENTICAL),
then bank. Reverted, re-sequenced, both banked clean.

R22 clean-fleet 140/140 BYTE-IDENTICAL; tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4).
Fleet: instr 81.6 -> 81.7% · distinct-code 69.1 -> 69.3% · fn-count 89.52%.
2026-07-26 22:16:48 -06:00
Drew T 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%.
2026-07-26 22:02:37 -06:00
Drew T c2566010f2 feat(phase-29): --allow-pins sweep — 268 banked; pin templatability is PER-FAMILY (cookbook §86)
The §42e pin guard refuses any family whose exemplar carries `register __asm__` pins: 680 of the top
8 FREE families' 1,083 members (63%) were skipped BEFORE any gate ran. Re-run with --allow-pins,
letting the byte-gate arbitrate (G3/P9): 268 banked, and ZERO cc1 crashes across hundreds of pinned
compiles — confirming the SIGABRT the guard was written against was Phase 27's extract_unit
macro-drop, NOT a compiler limit. The guard is protecting against a bug that no longer exists.

THE LAW (§86): templatability is a PER-FAMILY property, not a per-member rate.
  func_801749C8  137/137 = 100%      func_80133AB0    4/136
  func_8014C6F4  137/137 = 100%      func_8014CF04    0/137
                                     func_80143D28    0/136
Two families at 100%, three at ~1%. MY REPORTED "37%" WAS AN ARTEFACT: a 19-member sample that
straddled families reported their AVERAGE and hid the bimodality. Sample PER-FAMILY, never per-pool.

=> PROCEDURE, now the default: probe ONE member per pinned family; bank -> sweep the family; fail ->
skip entirely. The blanket sweep spent ~412 futile gate cycles (60% of the run) on three families
that were never going to bank; the 1-member probe reduces that to 5 probes + 2 sweeps.

Left explicitly UNDIAGNOSED (do not guess): why two families template and three do not. Likely axis
is caller-saved pins spanning a `jal` (§74's corrupting form) vs pins fixing only a local allocno.
Diagnose BEFORE extending --allow-pins fleet-wide — the byte-gate makes a wrong guess free, but a
wrong PROCEDURE costs a sweep.

R22 clean-fleet 140/140 BYTE-IDENTICAL; tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4).
Fleet: instr 81.3 -> 81.5% · distinct-code 69.0% · fn-count 89.41 -> 89.49%.
2026-07-26 20:23:28 -06:00
Drew T 52e6522f1b feat(phase-29): T0.5 — FREE-subset sweep, 3 families fully banked (389 members, +37,713 ins)
Re-derived the T0.1 decomposition post-harvest (it was stale by 395 banked members):
  zero-crack pool 76 fams / 347,892 ins  ->  73 fams / 290,850 ins   (the harvest came out of it)
  FREE (sweepable, non-jr, non-O0)       ->  58 fams / 167,368 ins

Swept the top FREE families through the gate_stage ladder (sample 8/8 first, then the rest):
389 banked; func_801463A0 / func_8017B490 / func_80156670 now stubbed in ZERO overlays.
R22 clean-fleet 140/140 BYTE-IDENTICAL; tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4).
Fleet: instr 81.0 -> 81.3% (10,645,711 -> 10,683,424) · distinct-code 68.8 -> 69.0% ·
fn-count 89.30 -> 89.41%.

THE BLOCKER HAS MOVED — it is now OUR OWN PIN GUARD, not gcc and not declarations. Of the 1,083
candidate members in the top 8 FREE families, 680 (63%) were refused by the §42e pinned-exemplar
guard BEFORE any gate ran; only 403 reached staging. Two pieces of evidence say the guard may now be
over-conservative: SESSION-19 banked func_8017A4AC x134 WITH pins once the byte-gate arbitrated, and
Phase 27 dissolved the cc1 SIGABRT that motivated it (it was the extract_unit macro-drop, not a
compiler limit). Next probe: --allow-pins on a sample of 8, byte-gated.

MY OWN SCRIPT BUG, fixed + negative-controlled: the sweep loop globbed `.run/sweep/*/`, which also
matches gate_stage's INTERMEDIATE ladder dirs (-cn, -cn-cast, -cn-cast-rc, -s2in, -s2in-uni). Those
were called as if they were binaries -> 24 phantom "PARTIAL 0/1" lines inflating notbanked to 56 when
the true failure count was ZERO (stub counts 0/0/0 are the ground truth). Fixed by requiring
config/splat.<ov>.yaml to exist; negative control confirms phantoms are skipped and real binaries kept.
2026-07-26 18:32:09 -06:00
Drew T 015ebff536 feat(phase-29): §84 family fully harvested — 123/123 members, 0 failed (+29,280 ins, +27,840 distinct)
The derived-offset recompute swept the whole func_8013D53C family: 119 banked / 0 failed on top of
the 4 earlier; func_8013D53C is now stubbed in ZERO overlays. R22 clean-fleet 140/140 BYTE-IDENTICAL;
tools-health OK; dedup 1886/0; 0 NON_MATCHING (G4).

RECIPE (and it is NOT the return-axis recipe — sampling caught this):
  §84 derived-offset -> per-member literal recompute AND the gate_stage ladder.
  With the recompute alone the sample was 0/8; through the ladder it was 3/3, then 119/119.
  Had I reused the return-axis recipe (plain harvest_verify, which banked 272/272 there) I would
  have swept 123 members to zero banks and mis-concluded the fix was wrong. Probe-before-scale.

METRIC FINDING worth carrying: this harvest moved instr +29,280 AND distinct-code +27,840, while the
return-axis harvest moved instr +26,928 and distinct-code +0. §84-class members are byte-VARIANTS so
each is a new unique function; propagation-class members were already counted once via their shared
exemplar. => §84-class work moves the RE-COMPLETENESS number; propagation moves only the DISPLAY one.

Session fleet: 80.6 -> 81.0% instr · 68.2 -> 68.8% distinct-code · 89.18 -> 89.30% fn-count.
2026-07-26 16:48:56 -06:00
Drew T 9d9cd58028 feat(phase-29): T0.4 harvest — 272 return-axis members banked (+26,928 ins) + the §84 recompute in family_remap
THE §85 WIDEN PAID OFF AS PREDICTED. It is a ONE-TIME fleet edit, so once committed the
`conflicting types` blocker was gone for EVERY member of both families at once:
  - sample 8 first (probe-before-scale): 8/8 banked with PLAIN harvest_verify, no ladder needed
  - full sweep: 264 banked / 0 failed across 132 overlays; 10 skipped as not-stub
  - total 272 members ~= 27k ins, ZERO agent tokens
R22 clean-fleet 140/140 BYTE-IDENTICAL; dedup 1886/0; 0 NON_MATCHING (G4).
Fleet: instr 80.6 -> 80.8% (10,589,503 -> 10,616,431, +26,928) · fn-count 89.19 -> 89.26%.
distinct-code UNCHANGED at 68.3% — propagation moves the DISPLAY metric, not the RE-completeness
one (the SESSION-19 split, reconfirmed).

§84 RECOMPUTE now implemented in tools/family_remap.py (fix_derived_offsets), wired into all three
apply_remap call sites as a PRE-pass on the exemplar body (the literal is ambiguous as a substitution
token, so it cannot be a table entry):
    correct_literal = mapped(aliased_sym) - mapped(base_sym)
Verified by negative control: the hand-solved case recomputes 0x20 -> 0x18 exactly, and a site whose
target endpoint is NOT a mapped symbol is left byte-for-byte alone AND REPORTED in info
["derived_offsets"] (R32 — a silent skip is a defect, and a silent skip is how this bug survived).
2026-07-26 15:36:06 -06:00
Drew T 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%.
2026-07-26 15:22:21 -06:00
Drew T b6bb04ecff feat(phase-29): CRACK THE PLUMBING FAILURE — the derived-offset remap bug (cookbook §84); func_8013D53C banked
Drew: "if it fails, see why and try again with new knowledge." It failed twice, then banked.

ROOT CAUSE, byte-proven: a family_remap member reached match_one MATCH (240 ins) and failed the
whole-binary gate by ONE BYTE. The exemplar carries a deliberate matching idiom — reach a symbol via
a DIFFERENT symbol plus a literal offset, so gcc cannot CSE the two %hi/%lo pairs:
    (*(S9*)&D_801DAA78) = *(S9*)(&D_801DA998 + 0x20);  /* same addr as &D_801DA9B8 */
family_remap substitutes the symbol NAMES correctly and leaves the literal 0x20 — but 0x20 is not a
constant of the algorithm, it is the DISTANCE BETWEEN TWO PER-OVERLAY SYMBOLS:
    exemplar 0x801DA998 + 0x20 = 0x801DA9B8  OK
    member   0x801A5778 + 0x20 = 0x801A5798  WRONG (real symbol 0x801A5790)
    member   0x801A5778 + 0x18 = 0x801A5790  correct
match_one MASKS HI16/LO16 so it is STRUCTURALLY BLIND to this — the §81 blindness in its DATA form.

TWO FIXES WERE EACH INDIVIDUALLY INSUFFICIENT: the byte fix alone re-failed as PLUMBING; the ladder
alone re-failed as DIFF. Together -> BANKED, R22 clean-fleet 140/140.

TWO LADDER CORRECTIONS (my own T0.2 error): bare harvest_verify is the LAST RUNG, not the ladder —
gate_stage runs canon_resident_calls -> cast_call_sites -> reconcile_tu -> ARITY -> sig_unify ->
harvest_verify, so T0.2's "8/8 PLUMBING" measured the UN-RECOVERED rate. And reconcile_decls.py is
RETIRED (R33, superseded by reconcile_tu): asking "what does the FLEET call this symbol?" is wrong by
construction in a loosely-typed engine (548 of its answers conflicted, rewriting 60 of 196 drafts) —
so Drew's suggested tool would have made it worse.

SCOPE, MEASURED (not over-generalised, §80): the idiom appears at only 5 sites corpus-wide — BUT one
gates a 123-member family (133 staged drafts all carry the un-recomputed +0x20 with different
per-overlay bases), so the mechanical fix is worth ~240 ins x 123 ~= 29,520 ins. It does NOT explain
the pool generally: func_80144090 / func_8012CC88 / func_8014D12C have ZERO derived-offset sites and
fail for a different, still-undiagnosed cause.

THE FIX IS MECHANICAL: correct_literal = mapped(aliased_sym) - mapped(base_sym). The remap already
holds both mappings, and the exemplar's own comment names the aliased symbol.

Also observed: the ARITY pre-pass left 40 TUs of caller-decl edits after a 0-bank run (same hygiene
bug as --normalize-self-decls, twice in one session) — reverted, both binaries byte-identical.
2026-07-26 13:47:06 -06:00
Drew T d3e6d6a702 feat(phase-29): T0.2 gate probe — the FREE pool is PLUMBING-blocked, not wall-blocked (4 banked)
MEASURED, not projected (R14): 12 gate attempts across ov_SC01_000 + ov_SC01_001, one draft per
build for clean attribution.

- 4 BANKED (func_8017B490 x2, func_801463A0 x2); 8 failed; **0 DIFF — zero compiler walls**
- all 8 failures are the §75a/def-side declaration class: `conflicting types for 'D_800A651C'`
  (DATA sym) and `conflicting types for 'func_8013D53C'` (the member's OWN def-side decl)
- => raw conversion 33%, but the ceiling is NOT 33%: the blocker is declaration plumbing, which
  this project has named tools for. Plumbing recovery has out-earned drafting in every phase that
  measured both (P19 fix_arity_callers, P28 dedup_extend 6,174 members / 95.6% from one new mode)

TWO CORRECTIONS TO MY OWN T0.1 POOL MATH, both downward:
- 2 of the 8 top "FREE" families were refused outright by the §42e pinned-exemplar guard (the 270
  skips) => "FREE" does NOT imply sweepable; pins are a third blocker the decomposition missed.
  Recoverable (--allow-pins; SESSION-19 banked pinned families x134), but I mis-labelled them
- n_templatable counts the matched exemplar, so every T0.1 family figure is ~1 member (~0.7%) high

NEGATIVE RESULT (§80, scoped to this base): --fix-def-sig REGRESSES this class — 0 banked and 2
PLUMBING became CC1-FAIL despite targeting the same error text. Do not re-buy without re-testing.

NAMED NEXT LEVER: family_sweep --normalize-self-decls, whose help text cites fixing "the conflicting
types for func_X that blocked 133/137 of func_801670E4" — exactly this failure. Gate-phase transform,
so it cannot run under --stage-only, and --limit caps FAMILIES not MEMBERS => needs a full ~123-member
family run. Highest-value outstanding probe, zero agent tokens.

R22 clean-fleet 140/140 BYTE-IDENTICAL; tools-health/dedup 1886/0; 0 NON_MATCHING (G4).
Fleet: instr 80.6% (10,589,065) · distinct-code 68.3% (3,846,416) · fn-count 89.19%.
2026-07-26 13:12:09 -06:00
Drew T 661f5aa751 feat(phase-29): bank func_8017C730 x ov_SC03_013 (+1,061 ins) via the §81 carve chain
The SESSION-19 handoff's item 1, closed as specified — no drafting, no agent.

- §77 MINIMAL CLOSURE (519 lines, not the 2,993-line whole-file carry): 18 gte_* macros
  + 5 externs + the bandsetup static-inline helper -> match_one MATCH (1061 ins)
- §81 chain, each step byte-gated before the next: jr_isolate_all --only (2 fns/1 object)
  -> BYTE-IDENTICAL; jtbl_carve --func (single-table, 44-piece interleave) -> BYTE-IDENTICAL;
  harvest_verify --chunk 1 -> verified 1 / failed 0, 7042bc71 BYTE-IDENTICAL
- R22 clean-fleet 140/140 from a genuinely clean tree; tools-health OK; dedup 1886/0;
  0 NON_MATCHING (G4). FLEET distinct-code 3,845,161 -> 3,846,222 = 68.3% (+1,061, all
  distinct — a behemoth-class bank, not a propagation); instr-weighted 80.6%
- No §75a class spoke: the exemplar's ApplyMatrixSV(void*,void*,void*) canon fix was
  already carried, so the declarations were clean and it banked first try
- cookbook §77: the ladder CLOSED with all four rungs measured (-56 -> -34 ->
  MATCH-but-uncommittable -> MATCH+BANKED), plus a NEW subsection — the CANDIDATE gate
  and the REAL gate need DIFFERENT preambles (match_one compiles standalone, so a
  shared-type body's CC1-FAIL is a report about the PROBE, not the draft; the types
  header goes in a throwaway probe copy, never in the banked draft)
- FINDING, flagged not acted on (P5d): that shortcut already leaked an ABSOLUTE include
  path into 21 git-tracked files / 23 lines. All 21 verified semantically no-op (guarded
  engine_types.h via engine_core.h at line 2) => removal is byte-neutral, but cpp must
  still find the literal path, so those TUs cannot preprocess on any clone not at
  /home/musashi/bfm-decomp. Invisible to every byte-gate (R34's null-oracle shape, aimed
  at portability). Proposed as the next task.
2026-07-26 11:57:17 -06:00
Drew T 109ce6a2c3 feat(phase-29): BEHEMOTH #6 func_8017C730 BANKED (1,061 ins) + §82 two source-shape oracles
- CRACKED at xHigh and VERIFIED INDEPENDENTLY: match_one MATCH (1061 ins); agent re-matched 3x
  from clean runs (100% register-masked AND register-kept, all 10 regions, frame 0x270 exact).
  §81 carve chain clean first try: jr_isolate_all --only -> byte-identical cacaf7c2 -> jtbl_carve
  (43-piece set) -> byte-identical -> bank -> R22 clean-fleet 140/140, tools-health OK.
  instr 80.6%; distinct-code 3,844,100 -> 3,845,161.
- WHAT IT IS: the matched base func_8017CA80 + camera height-band cull + distance-driven CLUT
  fade. func_8004974C (TransposeMatrix) sits in a 36-ins prologue deriving a Y band; the
  part-level `lim >= g.otz` cull is GONE; flat arms gain an `sz < lim` near-plane cull. The
  base+one-extra-callee fingerprint predicted this exactly.
- §82 ORACLE 1 -- A DUPLICATED `addiu $aN,$sp,K` ACROSS A `jal` MEANS THE BLOCK WAS INLINED.
  `&X` on any non-first local always creates a pseudo and CSE always merges two of them
  (expr.c:6260 ADDR_EXPR -> force_operand(..., NULL); exception: virtual-stack-vars offset 0).
  So the same stack address re-materialised at two sites separated by a jal means CSE was
  PREVENTED from merging => not the same function body. 17 non-inline spellings failed; a
  `static inline` helper reproduced the prologue BYTE-FOR-BYTE first try. Reusable probe: scan
  the ~1,200 built objects for that signature in NON-INCLUDE_ASM functions.
- §82 ORACLE 2 -- SCALAR vs AGGREGATE DECIDES *WHEN* A STACK SLOT IS ALLOCATED: lazily at first
  `&` for a scalar, AT DECLARATION for an aggregate. Six GTE result words had to be six separate
  longs, not a struct, or they don't land after the inlined helper's temps and the frame isn't
  0x270. Second-order: it also flips MEM_IN_STRUCT_P (§30's /s) -- with one word a fixed-address
  scalar, ((PolyF3*)pkt)->rgbc stops aliasing it, so a store needed respelling to keep the
  target's nop. A scalar-vs-struct choice is simultaneously a frame-layout AND an aliasing
  decision.
- BANKING FOOTNOTE (§75a class A): first bank rejected `conflicting types for ApplyMatrixSV` --
  draft (MATRIX2*, SVECTOR2*, SVECTOR2*) vs the TU/fleet canon (void*, void*, void*), 2,286 of
  2,835 sites. Conforming the decl is byte-neutral and banked first try. On a jr function expect
  BOTH gates to speak: the carve chain answers the jump table, §75a answers the declarations.
- Also reproduced: §78 (reuse a busy variable), §80(i) (a lever went -8 -> exactly neutral as the
  base moved), §72 (a register pin made it worse).
- AGENT'S OWN CAVEAT, recorded not hidden: one zero-byte __asm__ keeps a vestigial `mnc = hmid`
  alive that flow.c would delete (costing 10 ins + the 0x130 spill slot). Emits nothing, compile
  is 1061 exact, but it is a documented stand-in -- 12 natural spellings measured, all DCE'd.
2026-07-25 23:24:11 -06:00
Drew T faf4547345 feat(phase-29): func_8017C954 BANKED — jr carve chain cleared; a shared type was PRESENT but INVISIBLE
- BANKED (1,194 ins, ×1 distinct-code). Chain cleared, each step byte-gated before the next was
  built on it: one-line fix to jr_isolate_all._engine_types() -> jr_isolate_all --only
  func_8017C954 (2 fns / 1 object, NOT the bare 47-fn / 21-object resegment) -> BYTE-IDENTICAL
  b7b0d4ae -> jtbl_carve --func func_8017C954 (44-piece carve set + interleave order) ->
  BYTE-IDENTICAL -> harvest_verify VERIFIED BYTE-IDENTICAL -> R22 clean-fleet 140/140,
  tools-health OK. instr 80.5 -> 80.6%; distinct-code 3,842,906 -> 3,844,100.
- THE DEFECT (tools/jr_isolate_all.py): _engine_types() harvested shared type names with four
  patterns -- `typedef ... X;`, `} X;`, forward-decl `struct X;`, fn-ptr typedef -- and a TAGGED
  DEFINITION WITH A BODY matches NONE of them. So `struct PW8017E6D8 { int w; }
  __attribute__((packed));` at engine_types.h:658 was present in the shared header yet invisible
  to the carried-type check, and `extern struct PW8017E6D8 D_801E1EC4;` could not be placed.
  MEASURED BLAST RADIUS: 77 such tags in engine_types.h were invisible. One added pattern fixes
  all 77.
- WHY THIS COST 20 MINUTES INSTEAD OF A MYSTERY BYTE-DIFF THREE PHASES LATER: the Phase-26 audit
  had already turned this predicate's SILENT DROP into a LOUD REFUSAL. The original bug dropped
  4,040 col-0 decls, 683 of them function PROTOTYPES -- and a dropped prototype is a SILENT
  BYTE-CHANGER (C89 implicit `int f()`; return type drives delay-slot fill in this codebase). The
  refusal named the exact symbols and the exact remedy. A loud "I cannot place this" is worth far
  more than a green build -- the audit paying for itself, live.
- §81: the 3-step jr-carve chain + why match_one CANNOT see the problem (it masks jal/HI16/LO16,
  so a jump-table function reports MATCH while the whole-binary gate reports DIFF, correctly).
  Detect with `grep -cE 'jr \$(v0|v1|a0|t[0-9])'` on the target .s + a jtbl_ in asm/<ov>/data/.
  ALWAYS use --only: bare would have resegmented 47 jr-functions across 21 objects.
2026-07-25 21:58:04 -06:00
Drew T 8b828f1ea6 feat(phase-29): BEHEMOTH func_8017BF14 CLOSED — 45 -> 0 (4,763 ins, the largest match yet)
- 45 -> 37 -> 33 -> 21 -> 11 -> 3 -> 2 -> 0, reproduced 3x from independent work dirs. Verified
  independently before believing it (R14): match_one MATCH (4763 ins), then harvest_verify
  --binary ov_SC03_116 BYTE-IDENTICAL, then R22 clean-fleet 140 passed, 0 failed of 140.
  distinct-code 3,838,143 -> 3,842,906 = 68.1% -> 68.2%. instr 80.5%. Agent was interrupted by a
  weekly API limit and RESUMED FROM ITS TRANSCRIPT -- its round-2 harness survived, nothing was
  re-derived.
- §80 THE PROCESS CORRECTION, worth more than the match: A DO-NOT-RE-BUY ENTRY IS SCOPED TO ITS
  BASE, NOT TO THE FUNCTION. Three of round 1's ~40 measured negatives INVERTED on round 2's
  base -- the same edit (qsingle23) measured 1,040 mismatched on the 45-base and 11 on the
  21-base. Re-testing the round-1 negative list cost ~20s and produced THREE of the seven winning
  levers. Such a table records (edit, base) -> result, NOT edit -> useless; after any lever that
  moves the base materially, RE-RUN THE NEGATIVE LIST. This retroactively qualifies every
  do-not-re-buy table in the cookbook (§45, §60b, §75a, §76, §78, §79). Concrete: round 1 measured
  "removing the va->$t2 pin costs 4% elsewhere" => keep the pin; on a base with c0..c3 at function
  scope, removing those pins is worth 21->13. Same experiment, opposite conclusion.
- MY FLAGGED "#1 MOVE" LOST, and the failure is the finding. I briefed variable REUSE (§45-A /
  RC-14) as the top lever because it took func_8017F510 from 97->10. Swept in full here: EVERY
  merge lost, 43-3294 across 8 merges. Reason: the TRI and QUAD grants did not differ by RANK but
  by IDENTITY -- two independent allocno sets, and re-ranking inside one set cannot fix a two-set
  problem. Diagnose ranking-vs-identity before reaching for a merge. The actual fix (c0..c3 at
  FUNCTION scope, 33->21) was read off the two matched relatives (b5:310, b4:338) and confirmed
  against the target -- the 4th time today that reading a matched relative beat the clever lever.
- PIN'S HIDDEN COST, cited: combine_regs' hard-register branch (local-alloc.c:1795, reached from
  :1295 with already_dead==0) records the pinned reg in qty_phys_sugg UNCONDITIONALLY -- no death
  guard. A pin invites local-alloc to tie producer chains into it. New cure R7: a zero-byte
  __asm__ ref keeping the pinned value live past the temp so find_free_reg can't honour the
  suggestion -- closed the last 2 ins (c1->$a0 is uniquely load-bearing; every alternative pin
  lost 64 ins).
- §78's attribution primitive RUN and REPRODUCED: under -fno-schedule-insns, -fno-schedule-insns2
  and both, order unchanged => the rgb transposition was never a sched.c decision.
- Cold-start economics complete: round 1 = decode + exact length + exact frame + 99.06%; round 2 =
  the last 45, and cheaper. Budget TWO passes at this size. 5th source copy-paste artefact found.
2026-07-25 20:29:10 -06:00
Drew T a1f1a948af feat(phase-29): h_norm-remappable pool — +4,919 ins banked, no cracking, no agent
- BANKED (each whole-binary byte-gated; make check-all -> 140 passed, 0 failed of 140):
  func_80130D48 ×4 (1,064) · func_8018F3E4 (478) · func_8018B3D0 (478) · 13 × 223-ins siblings
  of func_8017E6D8 (2,899). distinct-code 3,833,224 -> 3,838,143 = 68.0% -> 68.1%.
- TWO OF MY OWN COUNTS COLLAPSED UNDER SCRUTINY BEFORE I ACTED ON EITHER (R14/R35):
  "func_8017CA80's family = 102 unmatched" was really 13 -- my count tallied family members whose
  NAME appears as a stub anywhere in the fleet, not instances actually unmatched (a semantics
  error, not arithmetic). "56,267 ins remappable" was really 8,114 -- 86% was the known -O0 /
  deferred set (the func_80144B9C whale, the func_8013C414 cluster). I nearly recommended a
  target on the first number.
- THE §77 CARRY GAP IS THE DOMINANT COST OF MECHANICAL REMAP: 23 of 27 first-pass CC1-FAILs.
  NEW .run/giants/s19_remap_tu.py sources the preamble from the exemplar's OVERLAY TU (the block
  between the previous top-level `}` and the def), applies family_remap's own substitution map,
  and adds the two includes match_one never adds -> 21 drafts went 0 MATCH -> 14 MATCH. The 13
  223-ins siblings share ONE exemplar, so a single preamble fix cleared all 13.
- USEFUL ASYMMETRY: func_8018F3E4/func_8018B3D0 FAILED match_one but BANKED in the whole-binary
  gate -- the real TU supplies decls the standalone compile lacks. A match_one CC1 FAIL is not a
  reason to skip the real gate on a remapped sibling.
- RESIDUAL 3,195 ins, causes NAMED not guessed: func_8017D5C0 (952) matches standalone, gate
  reports `conflicting types for memcpy` = the §58 red-herring (a warning from an unrelated TU
  position; SESSION-14 hit the same label and the true cause needed a hand-splice + real cc1
  stderr). func_80166994 ×3 + func_8016A290 ×4 still CC1-FAIL after the TU carry.
- FULL R22 DEFERRED DELIBERATELY: make clean wipes asm/, which the concurrently-running BF14
  agent reads on every probe. This batch changed only src/*.c (no config), so check-all is sound;
  the clean R22 must still run once the agent finishes.
2026-07-25 16:11:38 -06:00
Drew T f9a2de3edd feat(phase-29): BEHEMOTH #2 func_8017D960 CRACKED (1806 -> 0) + its 5-member family = 16,690 ins
- CRACKED pin-free at xHigh (Opus 5 agent), then ALL FOUR family siblings banked via §40 remap,
  each MATCHING FIRST TRY: ov_SC03_090 (the crack) · ov_SC03_089 · ov_SC03_104 ·
  func_8017E778 @ ov_SC03_091 · func_8017CD9C @ ov_SC03_102 (the last two cross-address).
  Verified independently before believing the report (R14): match_one MATCH (3338 ins), then
  harvest_verify BYTE-IDENTICAL on all five binaries, then R22 clean-fleet 140/140.
- METRICS: distinct-code 3,816,534 -> 3,833,224 (+16,690) = 67.7% -> 68.0%, the first
  percentage-point movement in that metric all session. instr-weighted 80.3% -> 80.5%.
  Session distinct-code total +19,712 ins, ALL from the three behemoths; propagation gave +0.
- MY BRIEF WAS WRONG IN AN INSTRUCTIVE WAY -> §78. I said a negative length drift means "missing
  instructions". The 4 absent instructions were 4 emit tails × 1 nop -- delay slots the target
  could NOT FILL because the register it wanted was still live. otp at function scope has 4
  deaths -> fails local-alloc.c:472 -> global allocno in $a2 -> via global.c:668-671 pushes tp
  off $a1 -> the 0xFFFFFF mask is free early -> maspsx hoists it into the slot. Declaring otp
  PER EMIT ARM fixed the whole drift in one edit (3334->3338, 1806->333).
  SECOND TIME IN ONE SESSION a "structural"-looking residual was an allocno-class choice (the
  first: F510's "scheduling" transposition, §76). A nop present in the target but absent from the
  draft is usually a register-liveness fact, not missing code.
- TWO MORE REUSABLE FINDINGS (§78): gcc-2.7.2 fold NEVER leaves a literal first in an `|` chain
  (7 parenthesisations, all reassociate) -- so `or acc, var, K` first in the target means K was a
  VARIABLE in the source, an asm->source read that retires a whole sweep family. And "make it a
  variable" has TWO separable effects (fold-opacity vs a new allocno): a fresh short-lived local
  fixes structure and wrecks allocation (690 mismatched, damage ~300 ins away); reuse a busy one.
- ECONOMICS: 9 levers, each necessary by drop-one ablation, and 5 of the 9 were read straight off
  the MATCHED relatives func_8017F510 (cracked earlier today) and func_8017CA80. Crack the
  smaller family member first -- it is a lever library for the larger one.
- NEW TOOL .run/giants/s19_remap_family.py: family_remap + the §77 preamble carry in one step
  (reproduces the exemplar's FULL file-scope preamble with the tool's own substitution map
  applied). Took the 4 siblings from "4 rounds of CC1 FAIL each" to MATCH first try, ×4.
2026-07-25 15:48:54 -06:00
Drew T 130b9407b1 feat(phase-29): func_8017F5B4 (1,511 ins) banked MECHANICALLY off behemoth #3 — ~0 agent tokens
- func_8017F5B4 @ ov_SC02_031 shares behemoth #3's h_norm AND h_seq (96fe0455c344 /
  9a6bd2b91fd4) with a different h_exact = the same instruction stream differing only in masked
  reloc fields. The §40 family_remap case exactly, so NO agent was spent: family_remap
  --addr 0x8017F510 --from ov_SC03_006 --to ov_SC02_031 --to-addr 0x8017F5B4 substituted 52
  per-overlay symbols correctly on the FIRST invocation.
- match_one -> MATCH (1511 ins); harvest_verify --binary ov_SC02_031 -> BYTE-IDENTICAL;
  R22 clean-fleet 140 passed, 0 failed of 140.
- DISTINCT-CODE 3,815,023 -> 3,816,534 (+1,511). With behemoth #3 that is +3,022 distinct-code
  instructions from the two behemoths, versus +0 from every propagation win this session.
- ALL the work was PREAMBLE, none of it the body -> cookbook §77. Four CC1 FAIL rounds, each
  naming one construct the extractor drops: (1) multi-line `typedef struct {...} PolyGT4;` --
  family_remap's backward walk accepts a line only if it STARTS with extern/typedef/comment, and
  a multi-line typedef ENDS with `} PolyGT4;`, so the walk halts there AND LOSES EVERYTHING ABOVE
  IT; (2) hence the file-scope extern block above the #define BOXTEST/ATTEN block; (3) the
  exemplar's own #include lines (PolyFT3/PolyFT4 live in engine_types.h).
- THIRD CONFIRMATION TODAY OF ONE DEFECT CLASS, NOW ACROSS TWO TOOLS. §75b found
  dedup_propagate dropping a file-scope #define and PREDICTED the generalisation; family_remap
  then dropped a typedef, an extern block, and the includes. RULE (§77): after any mechanical
  template/propagate step, diff the exemplar's full file-scope preamble against what the tool
  emitted. A CC1 FAIL on a remapped sibling is a PREAMBLE report until proven otherwise -- it
  says nothing about whether the remap was right.
- Artifact preserved: .run/giants/s19_func_8017F5B4_remap.c
2026-07-25 15:02:37 -06:00
Drew T 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.
2026-07-25 14:41:08 -06:00