Drew's call (2026-08-01, P5d in-phase re-plan): gate 2 was reached and deliberately NOT taken —
closing now would strand roadmap-v2 bucket W3 (the overlay family mass) with no owner phase
(P31 = scope-complete/main/resident, P32 = walls/behemoths).
Order derived from the S29 frontier regen, ranked by TEMPLATABLE weight:
S1 zero-crack propagation (29 families / 67,470 ins, ~0 agent tokens)
S2 the LAST two reach-138 fresh cracks (func_80176734 51,198 + func_8016EC0C 12,144)
S3 close=0 stored drafts as a DIAGNOSTIC pass (not a blind re-sweep)
S4 PINS bounded wave (14 fns / 44,279 ins)
S5 the x10-133 mid-multiplicity families (142,527 ins)
Excluded: the 2 GIANT walls (P32), the x2-9 mass, the x1 singleton residue.
THE PRICING FINDING (R14/R35): worklist.md ranks by h_exact reach, so a per-location PURE family
is priced x1 — under-pricing the frontier head by up to 138x. Byte-proof: S29's pair was priced
272 and 198 ins and delivered 37,536 + 27,324. func_80176734 (the single largest item on the
board) sits at rank ~50 in worklist.md. Rank family work by .run/family_hseq.json.
THE STRUCTURAL SIGNAL: after S2 the x138 era ENDS (last two crackable fleet-wide families);
everything after is <=133 members and mostly <=9. That cost-per-point rise, not a session count,
is P30's honest ROI floor and T5's trigger.
- tools-health OK: sigs regenerated post-bank; corpus(+resident) 0 PHANTOM/0 TRUNCATED; cdecl;
audit-binaries 140/140 citizens (R36); report(lint+dedup) 1905/0; cookbook-index 357 sections.
- Fresh overlay frontier at HEAD: 93.6% fn / 90.1% instr / 82.5% distinct; unmatched 22,550
instances / 1,298,980 ins / 15,029 distinct classes -> 2,414 families + 3,767 singletons
(472 substantial / 543,901 templatable ins; 29 zero-crack).
- T1 ticked with its honest scope: delivered as T1a (+18 banked, 16% vs the S16 39% prior which did
NOT generalize); the ~90 integration-decayed drafts route to T3 redraft lanes (A10).
- T3 ticked with a PER-LANE verdict: Lane B (top-mass) pays and is not exhausted; Lane C (x2-reach
cached tail) is at the floor (1.33M tokens -> 12 banks -> +0.00pp). The ROI floor is a lane
property, not a phase property.
- 2 × 138 = 276 function-instances banked (exemplar + 137 siblings each); the -O0 cluster is now
COMPLETE fleet-wide (these were the last open stubs in every overlay's _o0* region)
- §132a: --like matches by subseg ROLE NAME; ov_SC07_010 shares the exemplar's _o0 role (the only
other overlay so named — the other 136 are _o0c, whose role never matched, which is the only
reason the sweep worked at all). Six derived starts for three emitted tables; guard shipped.
- R22 clean-fleet 140/140. Fleet 93.33% fn-count / 89.6% instr / 81.6% distinct (+260 unique fns);
dedup 1905/0; 0 NON_MATCHING (G4). Phase arc: 92.00->93.33 / 87.5->89.6 / 78.0->81.6.
The 1-sibling probe (R37) gate-failed: ov_SC01_000's object emitted only func_8013C0F8 +
func_8013C414 tables, because BD74's body never compiled — `E_13BD74' undeclared. The draft
declared E_13BD74/P_13BD74 at FILE scope and extract_unit/remap_hseq carry only the BODY, so
the types stay behind in the exemplar. Same §94 class that held func_8013C08C at 0/137 earlier
this phase; fix is §100 (block-scope types travel with the body, byte-neutral — a type emits no
code). Exemplar re-gated: ov_SC01_077 d19c9580 BYTE-IDENTICAL. B83C's draft was already
draft-local. Named in one command by the §132 ladder.
S28 ledgered `JR-PAIR-IN-ONE-O0-OBJECT` (two jr fns matched in one -O0 object => a clean
build that cannot link: `undefined reference to $L105` + `func_8013C938`) with §81 step 1
(isolate one into its own code subseg) as the untested escape. BOTH the class and the escape
are REFUTED — no isolation, no compiler wall, both fns banked from a genuinely clean fleet.
The 4th consecutive "structural wall" to resolve to our own tooling (§124/§125/§126/§131).
- DEFECT 1 (tools/jtbl_carve.py): ov_SC01_077_o0's carve at 0xb01a4 predates the §8e
`tables=` persistence and is a MERGED DOUBLE (func_8013C0F8 $L75 + func_8013C414 $L105);
the 2nd owner is MATCHED so extract pruned the stub .s naming its table. The single-table-
predecessor inference derived 3 starts where the object emits 4 tables -> JTBL_PADS 0,4,4
-> jtbl_rodata_pads refused mid-stream, correctly. FIX: R32 coverage assertion + payload
recovery at the single choke point (spec_from_starts) — every zero word inside a span is an
original `.align 3` pad (the tool's own axiom), so the word after it STARTS a table;
recovered starts are logged. No-op where structure is known (the 134 sibling _o0c spans
carry tables=+0x0,+0x70). Honest limit: tight (0-pad) boundaries stay unrecoverable but
fail LOUD via the filter's count guard — never silent.
- DEFECT 2 (Makefile): no .DELETE_ON_ERROR, so `as` (a pipeline consumer) left a TRUNCATED .o
on disk — 12 of 16 T func_, undefined $L57/$L59/$L63/$L75/$L76 — newer than its .c, and the
NEXT build linked the corpse. That IS the S28 link error, one build downstream of a loud,
correct compile error. Negative-control-proven on a scratch invocation.
- BANKED: func_8013B83C (272 ins) + func_8013BD74 (198 ins) in ov_SC01_077 (d19c9580).
Byte proof: 4 tables 0x801D8254/828C/82FC/836C (13/27/27/27 entries, each zero-pad
separated); span 0xb00fc..0xb0280 = 388 B = 52+4+108+4+108+4+108 exactly; spec 0,4,4,4.
- R22 clean-fleet (make clean + extract-all + check-all): 140 passed, 0 failed of 140.
The incremental result was NOT trusted (§130). Fleet 93.25% fn-count / 89.2% instr /
80.5% distinct; dedup 1905/0; 0 NON_MATCHING (G4).
- cookbook §132 + index (356 sections): the mechanism, the fingerprint (an undefined $L<n> in
a LINK error is a truncated object, never codegen), the 30-second standalone-TU ladder that
named the 4th table owner before any build, and the transferable rule — a fail-loud guard is
only as trustworthy as the artifact hygiene around it.
SS131: `sltiu N` is ground truth in BOTH directions. jtbl_range already EXTENDS a span the
dlabel cut short and WARNS when a span is shorter than the bound, but had no clamp for a
span too LONG for a NON-ZERO reason — and the trailing trim only removes ZERO words, so
ordinary data that spimdisasm ran into the dlabel slipped through and under-filled the piece.
Records the reusable FINGERPRINT of an under-fill, because it does not look like codegen:
hundreds of 1-byte diffs spread over most of the overlay, ~95% at byte 0 (mod 4) = the low
byte of a 16-bit immediate, every one changing by exactly -4. Bucket differing bytes by
offset%4 and decode a few words; uniform small deltas in the immediate field mean LAYOUT,
not codegen. (Measured: 812 of 853 at pos 0 mod 4, all -4.)
The clamp's authorization matches the extension path exactly: unambiguous sltiu bound only,
and REFUSE LOUDLY if any surplus word is a plausible code address.
This was the single instrument failure that survived SS125's retraction round — the one case
where "the tool is broken" was actually true. Now fixed, with the 710-ins behemoth banked.
Fleet 93.25% fn-count / 89.2% instr / 80.5% distinct; R22 140/140 (thirteen runs).
Nothing running, tree clean, lock FREE.
Records for the fresh session: the ordered resume list (T1 + T3 need /effort ultracode and a
WAIT for the toggle; #9 and T5 need Max), the JR-PAIR-IN-ONE-O0-OBJECT wall with its untested
SS81-step-1 escape, and the S28 ROI evidence that a 15-target wave bought 12 banks and +0.00pp
headline — so waves are only worth resuming against HIGH-REACH targets.
Flags the milestone reality plainly rather than leaving it for T5 to discover: 89.2% instr
against a >=95% bar, with the remaining volume in main + the 39 type-1 modules (P31 scope).
P30 realistically closes on the milestone's LEDGER branch, which is an explicit either/or in
the approved milestone — Drew's call, deliberately.
Adds the S28 HONESTY LEDGER: five wrong calls this session, each caught by an oracle, none
committed. The standing consequence is stated once, at the top of the handoff: only a full
clean-fleet R22 counts, and a tool's exit status is never the oracle.
Also removes a duplicated results section left by my own earlier checkpoint edit.
SS129a: post-carve, rtu_match/match_one COUNT THE JUMP TABLE AS INSTRUCTIONS. For
func_8013BD74 it reported `mine=198, target=226, 206 mismatched` — and 226-198=28 is
exactly the table's entry count. A draft that verified cleanly BEFORE the carve reads as a
total mismatch AFTER it, and the number looks like deep codegen trouble. SS81 says a jr fn's
match_one MATCH is not a bank; SS129a says its post-carve DIFF is not a diff either. Let the
whole-binary gate arbitrate.
SS129b: NEVER commit a carve whose owner is still a stub. harvest_verify refuses a dirty
tree (SS97) and the carve dirties config/, so committing the carve to get a clean tree is
tempting — and it STRANDS the carve. jr_inventory refused instantly (R32: "carve ownership
is not 1:1 ... UNOWNED 0x801d828c"), blocking every later jr operation on that overlay.
Reverted; R22 140/140. The route for a jr fn is the INTEGRATED jtbl_family_bank (carve ->
extract -> remap -> gate per sibling in ONE uncommitted transaction). The SS81 hand-chain is
for diagnosis; as a banking path its two constraints contradict each other.
Both were mine, both caught by oracles before any lasting damage, both now documented.
Ledger: JTBL-PAD-SPEC-DRIFT (func_8013BD74, with the exact SS8e error) and CC1-FAIL-UNREAD
(func_8013B83C — the diagnostic is genuinely unread; say so rather than guess).
Fleet 93.21% fn-count / 89.1% instr / 80.4% distinct.
SS127/SS127a/SS127b distil what the wave's agents kept re-deriving, because the index
fired on only 3 of 15 targets:
- the -O0 CONSTANT-OFFSET FOLD: `p->f` folds to `lbu 3(r)`, `p[i]` does NOT (addiu +
0-displacement load). At -O2 these converge, which is why nothing in SS1-SS126 covers it.
- the -O0 regime generally: spill/reload pairs are REAL named locals; load-delay nops and
redundant copies are normal; write plain C, the -O2 steering levers are inert here.
- SS127a: SS71 sibling-first is the STRONGEST -O0 lever — an -O0 TU is a near-uniform code
regime, so a banked sibling's shape transfers far better than at -O2.
- SS127b: two agents' decisive levers came from a SOURCE COMMENT in ov_SC01_077_o0.c, not
from docs/. Promote levers out of source comments or every future agent re-buys them.
Checkpoint records the wave AND its honest ROI: 1.33M tokens for 12 banks and +0.00pp
headline. The value is contingent on three reach-138 functions, and all three are
currently unpropagated (func_8013C08C 0/137, SS94 type-carry) or gate-failed
(func_8013BD74 CARVE-REFUSED, func_8013B83C CC1-FAIL). Fix propagation before wave 2 —
drafting more x2-reach targets is not where the leverage is.
I under-counted this cluster 8x (reported 275 stubs/18 overlays; truth 2,184/138). The
scan ran during a background rebuild AND wrapped corpus.stubs() in `except: continue`,
so every R32 coverage refusal became a silent skip and the total was taken over the few
overlays that happened to be re-extracted already.
Two of our own rules broken at once: a measurement taken during a rebuild is not a
measurement (caught EARLIER the same session, by the same assertion I then suppressed),
and R32 lives in the CALLER — an oracle only asserts coverage if the caller lets it raise.
It also cost credibility the other way: I used the bad number to declare the T0(f)
"2,192 open members" pin STALE. The pin was right. R35 applies to a re-measurement as
much as to the original measurement.
Checkpoint updated with the corrected population and the completed fleet-wide sweep.
- T0.5 was COMPLETE in SESSION-27 (124/124 programs, 7,716 files) but left unticked;
corrected, with the omission noted rather than silently fixed.
- T2 marked [~] part-done and its DEVIATION recorded against the phase-start plan:
the PRIMARY (two-file atomic o0b append) was byte-refuted, and the FALLBACK premise
was ALSO wrong — Arm-A does not bite. What actually blocked it is §126. Route proven,
tool shipped, 6 banked; the 18-overlay sweep of the 0x8013B568 cluster remains, sized
at 275 open stubs (re-derived; the T0(f) "2,192" pin is stale).
Records the T2 result as the phase's biggest unblock: the carve-within-a-carve is
byte-neutral (Arm-A does NOT bite), the real constraint is that an address range is
not an optimization region (SS126), and tools/o0_subsplit.py implements the correct
bound. Measured, not assumed, what it unblocks: 275 open stub instances across 18
overlays in the 0x8013B568..0x8013C98C cluster, homed in an -O2 jr split — plus a
note that the T0(f) "2,192 open members" pin is STALE and must be re-derived before
costing (R37).
Also flags my own under-count: the "15 contiguous -O0 fns" came from an asm scan that
cannot see matched functions.
Max-effort re-measurement of the three jr refusals I ledgered earlier this session.
Two of the three verdicts were FALSE. Every number below is SHA vs config/check.<ov>.sha
from a clean tree, with the restore re-verified.
func_8018057C / ov_SC01_009 : jr_isolate_all is BYTE-NEUTRAL
-> "JR-ISOLATE-BREAKS-BYTES" RETRACTED; original failure not reproducible.
func_80191C50 / ov_SC06_018 : isolate NEUTRAL -> carve DIVERGED
(got 1b1667ea, want cbbc4f44) -> the ONE real instrument failure. CONFIRMED.
func_8017BEBC / ov_SC04_004 : carve is BYTE-NEUTRAL (body-free)
-> failure is the TEMPLATED BODY, the OPPOSITE of what SS125 first claimed.
Re-probed once more from a verified-clean tree: still gate-fail. Reclassified
BODY-TEMPLATE-GATE-FAIL.
So the tidy "two apparent walls are ONE tooling problem" conclusion was wrong: they
are two different problems, and the third target has no demonstrated problem at all.
ROOT CAUSE, and it is mine not the tools': a grep-of-the-build-log gate inside a driver
that did not revert on abort. config/overlays.mk is SHARED, so target 1's half-applied
isolate was still in the tree while target 3 was measured. Separately reproduced the
SS42b stale-object trap head-on: `git checkout -- config/` WITHOUT a re-extract turned a
byte-identical overlay into [FAIL] got 8f28aa77 / want 38a3d919 (Phase-20's R22
corollary, live).
SS125 rewritten. The METHOD (split the carve from the body, one build) is kept and is
what refuted this section's own first conclusion; what is added is the instrument rules
that make its answer trustworthy: compare the SHA against config/check, never grep the
log; re-extract after every config change AND every revert; a driver that aborts a
target must revert it before the next; verify the BASELINE against canonical too.
Meta-lesson recorded: SS53 says a 0% from the wrong TOOL manufactures a doctrine — this
is the same failure one level up, a verdict from the wrong MEASUREMENT, and my own
diagnostic script is an instrument subject to R35 like any other.
Ledger corrected in place (3 entries, superseding the earlier misattributions), so the
scheduled repair is the right one. No source/config change; no bank affected; the fleet
is untouched at 140/140 (last full R22 this session, HEAD commit:1263).
The session's most useful finding is an instrument ticket, not a match.
SS125 (new): before ledgering any jr residue, run jtbl_carve with NO body spliced
and rebuild. Byte-identical => the carve is neutral and the failure is the template;
NOT identical => the failure is the carve and the body was never fairly tested.
One build, and it collapses ambiguity that SS53 warns has twice steered strategy.
MEASURED: group B func_8017BEBC had gate-failed 3 probes in a row (default AND
--raw, cross-address ov_SC02_015 AND same-address ov_SC04_004). Carve-only on
ov_SC04_004 broke the bytes with nothing spliced — so all 3 probes were testing a
body that never got a fair run. The SAME stage had already refused behemoth
func_80191C50/ov_SC06_018. Two "unrelated walls" = ONE tooling problem.
func_8018057C/ov_SC01_009 fails at a DIFFERENT stage (jr_isolate_all, step 1) and
is deliberately NOT grouped with them.
Both tools reported SUCCESS on every failing target; only the whole-binary gate
refused (G3/P9). A tool's exit code is not the oracle.
Ledger: the three logged by STAGE (JTBL-CARVE-BREAKS-BYTES / JR-ISOLATE-BREAKS-
BYTES), not by function, so a carve fix auto-reopens every target it should.
None is diagnosed, so none is called a compiler wall — that guess has been wrong
four times running on this project (R35).
CURRENT_PHASE: SESSION-28 checkpoint refreshed; the carve diagnosis is now resume
item 1 (it gates 13 members + a 710-ins behemoth and every future jr family).
- §124: a "not matched" verdict can mean the definition is there under a DIFFERENT
C NAME (the §37/§73 asm-label alias). The whole "no matched unit" skip class was
one exemplar x 137 members. Includes the two traps in the fix (re-derive the
pattern PER FILE; CARRY the alias declaration or the sibling emits the wrong
symbol and still links) and the law: when corpus.stubs and a source scanner
disagree, the SCANNER is wrong.
- §124a: `0 matched-exemplar families` from family_sweep may be the --band FILTER
(defaults to `substantial`), not a wall — same shape as §53 / §116.
- cookbook-index regenerated (tools/cookbook_index.py, R33).
- CURRENT_PHASE: SESSION-28 checkpoint. Fleet 92.70 fn-count / 88.3 instr / 78.7
distinct, R22 140/140. Records the 4th -O0 region VERIFIED + SIZED (30 instances
/ 1,504 ins, ov_SC03_014+015 only) and correctly BLOCKED on the T2 re-carve, and
two R14 corrections to my own SESSION-27 checkpoint (the 137 were skips not
failures; the cause was not "banked in the wrong binary").
I gated 8 binaries in parallel while wave-2's propagation loop was still running, then ran
'make clean' on top. check-all 77/140; the corpus denominator moved, so the apparent 91.4% instr
was a half-written tree, not a gain. Reverted to commit:1245 (last R22-verified) — 140/140 restored,
all 58 drafts survived because agents only ever write .run/.
ROOT CAUSE, and it was structural not unlucky: my guard was
while pgrep -f dedup_propagate; do sleep; done
A CAMPAIGN is a LOOP of short-lived processes (15 sequential invocations), so it has gaps where no
process matches. The poll sampled a gap and started. Presence-of-a-process cannot express 'a
campaign owns the tree'.
treelock.sh holds one flock for the WHOLE campaign, released by the kernel on exit OR kill, with
--status; both drivers refuse to run unlocked. LAW: guard the CAMPAIGN, not the process.
Corollary (twice today): a killed process performs no undo — a fleet-tier write needs a lock ABOVE
it, not cleanup inside it.
Verified against code rather than the ledger: the split-blind lookup globs */ correctly, and the
churn was fixed by T5's input-signature gating. Both struck. asm_subdir_for was still a parallel
oracle (silent g[0] on multi-match) -> now corpus.asm_path. --fix-def-sig defaults off correctly
but advertised 'Byte-neutral; gate arbitrates' — the claim T84 refuted (signedness-wrong header
decl over a byte-correct draft; 137 members held at 0 until the flag was dropped).
A defect ledger nobody re-verifies decays into busywork — verify before scheduling.
A killed process performs no undo, so a fixed timeout on a fleet-tier write is a tree-corruption
mechanism, not just a delay. Now: timeout = min(6h, 1800+1800*banks); on expiry the driver reports
TREE DIRTY, REVERT REQUIRED and returns cleanly. Standing practice for multi-bank waves: re-gate
--no-propagate, then propagate PER FUNCTION (dedup_propagate --addr) — bounded and resumable.
Wave-1 result recorded: 14/14 match_one MATCH -> 8/14 banked (the §52b law); 3 new idioms owed.
39% prior did not generalize (S16 measured FRESH wave drafts; this is A10's stored-backlog class,
0/958 by plain re-gate) — the driver lifted ~16% over that 0%. Residue routed to T3 redraft lanes.
§61 orphan-carve residue reverted; two T3 pre-work gaps recorded (gate_stage commit add-scope for
new carve files; no tracked writes during tree-writing campaigns). Ledger pruned: 1,350 -> 1,332.
o0b-bearing != o0b-adjacent: T85's 0x801457A4 banked by append only because it abuts the o0b
object's END; the 0x8013Bxxx-0x8013Cxxx families mis-place by construction (probe 1/1 gate-reject)
and per-fn isolation IS the Arm-A re-carve. Frontier report corrected; T2 pivots to the Arm-A
+0x20 defect itself (symbol-pin hypothesis first). Driver stands as the post-fix sweep harness.
- Filter + prune existed since 07-24; jsonl already compacted (the tree's uncommitted edit was
S25's un-committed prune output; prune today 1350->1350/0 dropped). Stale rows were worklist.md's.
- Oracle agreement: 0 divergence across 131 ledger binaries (my first probe compared names vs int
addrs — R35 on my own instrument). Hex-case canonicalized in the membership test (R32).
- Parity proven post-change: load_best 1350 == 1350. §83 doctrinal caveat stands.
The SESSION-25 recipe (grep -v warnings from --stderr-out) applied in-tool across all 4 stages;
gcc-2.7.2 hard errors have no 'error:' prefix so the old tail-truncation drowned them (cost 3
probes). Raw-tail fallback if the filter empties. Verified on a real deliberate CC1 failure.
- STAGE 0: gate the RAW drafts before any transform (GATE_NO_STAGE0 escape) — the carried
'ladder destroys good drafts' defect (SESSION-22 reproduction: _o0 pair + func_80138C60,
ladder-FAILED/bare-VERIFIED) is impossible by construction; ladder+arity now touch only
stage-0 failures. TU-blind-transform root-cause hypothesis recorded in-code, open.
- fix_arity_callers --journal/--undo-journal --keep: exact per-edit undo in the WRITER,
shared by ladder AND bare workflows (the 17-TU residue class); replaces the two-special-case
file snapshot; undo moved after stage 2 (closes the stage-2 arity parity gap); stale-journal
guard. Negative-control: apply->undo byte-identical; --keep exact.
- Flow test .run/t0a_flowtest/driver.py 7/7 PASS. Cookbook §122. CURRENT_PHASE T0(a) logged.
- Re-ranked after T97: 80 families / 960 members / 173 new distinct, top family worth 20.
- Probed the top (0x8017d840): stages 0 drafts, skipped {'member class STRUCT': 21} — every member
is register-drift class, refused by remap_hseq for a REAL structural reason. First still-zero
family this session whose blocker is not our own tooling.
- Clean split measured: 29 all-STRUCT families (86 members, refused by design, per-member drafting
only) vs 51 no-STRUCT families (874 members, ~150 distinct, stage fine but fail the gate) — no
mixed families at all.
- HONEST ROI: the 51 are ~51 independent diagnoses at ~3 distinct each, and the last THREE blast
sweeps over them returned 0 with every lever this phase built applied. Residue total is 173
distinct vs 2,713 members banked today. The mechanical family engine is SPENT — this is the ROI
conversation SESSION-24 deferred, now supported by data (Drew's gate-2 call).
- No banks; tree clean; src/ untouched.
- 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).
- Read the colliding decls out of the ASSEMBLED t.c (the step T91 named): the draft's file-scope
typedef S_AF634 (line 2885) vs the TU's OWN file-scope S_AF634 (line 3016), character-identical,
with the draft landing above. Stripping the draft's duplicate CLEARS the error — by experiment,
not inference.
- SECOND BLOCKER revealed behind it: "D_800AF634 used prior to declaration" — the draft's
extern S_AF634 D_800AF634[] sits at BLOCK scope below its first use (the §8d demotion). So
func_801759D8 is two STACKED blockers; a typedef-only fix will still gate-fail. Recorded so the
strip is not billed as the family's answer.
- tu_ambient DOES scan the whole file, so _uniquify_draft_types should have handled #1 and did not.
Left unresolved rather than spend budget reconstructing a patch I had already reverted — but
func_801759D8 is now a reproducible test case to gate any re-wiring against.
- Ordered recipe recorded: strip ambient-duplicate typedefs -> fix the §8d demotion (hoist the data
extern above first use) -> re-probe with rtu_match -> only then sweep. 137 members / ~130 distinct,
and the auto-named S_* typedefs recur across the byte-identical stragglers.
- No banks; tree clean; src/ untouched (the probe ran in .run/ and a scratch copy).