The () skip is confirmed blind to RETURN-type conflicts (func_801376E8 normalizes 0). The other two
targets produced edits that broke the build outright (final SHA None, not a byte-DIFF) -- consistent
with §57a's SURGICAL-ONLY classification: NSD edits the TU file, so a bad edit poisons the group and
cannot be bisected per-member. Reverted; make check BYTE-IDENTICAL; tree clean; nothing landed.
The self_decl_tu class stays OPEN and needs its own diagnosis session. Measured recovery holds at 14/36.
Extended, not replaced: it already owned exact snapshot/restore, split-aware grouping and the two-pass
gate-all -> restore -> re-stage-winners protocol. A new driver would be a 7th snapshot impl (R33).
- --draft-dir (repeatable): consume a WAVE dir instead of the backlog (unreliable closeness,
overlay-specific drafts). Strict ^func_[0-9A-Fa-f]{8}\.c$ filter -- the wave dirs carry scratch
(_b.c, try2.c, scratch/) and run_gate globs *.c blindly.
- --run-id: all scratch under .run/recover/<id>/, and run-local verified_out/failed_out passed into
run_gate -- closes §55b trap 4 (the accumulating .run/harvest_verified.txt phantom bank), which the
cookbook still lists as "still armed".
- --stages with the new demacroize stage; --max-tier; --r22; --probe-only; --report.
- TIERS ENFORCED not documented: stages declare T0/T1/T2, the driver MEASURES the write set
(git status before/after) and ABORTS if a stage writes outside its blast radius (§61d). A fleet-tier
stage is refused without --max-tier fleet AND --r22. Both refusals negative-control-tested.
- stub_map now derives from corpus.stubs (R33, coverage-asserting) instead of a private regex that
could silently return a short map; banked_from_source() is the sole bank oracle for reporting.
- End-to-end on the remaining 22: excluded 26 already-banked by name, demacroize ran on 12, banked 0,
restored exactly (src/ clean), 14/14 prior banks intact. A clean negative -- it does not manufacture
banks. Those 22 need normalize_self_decls / draft type-uniquify wired next.
- func_8012F40C banked (the callee-conflict variant): relaxing demacroize from "the draft's own
function" to "any decl the DRAFT declares incompatibly" reaches macros that declare a CALLEE
differently than the draft does (RotTransPers/RotTransSV). 14 banks total, R22 140/140.
- THE ONE FAILURE, kept honest: func_8012F49C was rtu-MATCH but the whole-binary gate REJECTED it.
rtu_match is relocation-masked, so a wrong call TARGET is invisible to it -- and this was a callee
case, exactly where the mask hides the error. Trust rtu MATCH for self-decl corrections, distrust it
for callee ones (§65c). Reverted its edits and re-banked only the winner rather than leave
byte-neutral churn on matched code (§57a-4).
- DISTILLED IN-SESSION (R30/R16/R31/R21): cookbook §65 + §65a-§65e (blast-radius tiers; the
de-macroize escape and the §20 refutation; the rtu-vs-gate divergence; the existing-ladder baseline;
two-oracle practice); decision-log entry with the HONEST multiple (~2.3x, not the projected 3.7x,
and it lands on distinct-code not the display number); calibration.md measured table; SETUP.md rows
for blocker_probe + demacroize PLUS the three the inventory was missing (lift_types, uniquify_type,
fix_header_decl-as-retired).
- Carried and NAMED, not dropped: 10 match_one-MATCH drafts still blocked by stacked classes, and the
11 `near` drafts which are unfinished drafts, not recovery fuel.
S0 measured all 36 stranded drafts in 9.2s, two oracles agreeing 36/36.
- POPULATION CORRECTED (R14): the audit's "~92% byte-correct" is a whole-wave figure; among the
STRANDED residue match_one says 24/36 MATCH / 11 near / 1 ERR = 67%. The 11 near are unfinished
drafts, not integration problems -- and they are exactly the ones that compile and DIFF.
- BLOCKERS (they STACK; cc1 reveals only the first): self_decl_hdr=21, callee_decl=19, data_decl=16,
self_decl_tu=5, local_type=5. Per function by MAX tier: T0=6, T1=26, not-integration=4.
- T3 BASELINE, measured free: the existing draft-side ladder clears callee_decl 19->3 and data_decl
16->0 yet converts 1 of 36 to compiling, which then DIFFs -- §61d verbatim. The wave's gate
orchestration was NOT broken; the ladder simply cannot reach this population.
- NEW tools/demacroize.py: the conflicting extern lives INSIDE a DEFINE_func_* macro BODY, so it
exists only where instantiated. Expanding those instantiations in the overlay's OWN TU, correcting
only the conflicting decl to the draft's byte-true sig (never dropping it, §57a-1), dissolves the
conflict with nothing written outside src/ov_SC07_006/. This is §63's own unexplored
"per-overlay-local decl" -- and it refutes §20's "the DEF-conflict class is byte-proven
unrecoverable by text transform" for the per-overlay case.
- MEASURED on the 14 clean candidates: 13 MATCH / 1 DIFF in the real TU.
- END-TO-END: func_8012CC88 banked whole-binary BYTE-IDENTICAL (stub gone per grep, not per report);
R22 clean-fleet 140 passed / 0 failed of 140 -> the T1 blast-radius claim validated empirically
(the difference from fix_header_decl, which broke 139/140 from the same per-binary green light).
- GATE A: 32/36 real decl errors (>=12) and 13/36 rtu-MATCH simulated (>=12). PASS.
Price stated honestly: a de-macroized bank is x1 -- full distinct-code credit, ~1/138 of instr.
Task 16 (the integration-recovery pass) T1. The SESSION-15 audit measured the wave bottleneck as
INTEGRATION (~92% of drafts byte-correct, ~27% bank); 36 stranded byte-correct reach-138 drafts are
the fuel. Before building any recovery, measure the REAL blocker per draft.
- tools/rtu_match.py: --stderr-out (atexit flush, covers every sys.exit path) + \n in //@EDIT
replacements (T6 needs a multi-line macro expansion). The inline tail is truncated and these TUs
emit hundreds of benign warnings -- on the first real run it was 100% warnings while the actual
errors sat ~180 lines earlier (the §58 red-herring, one level down).
- tools/blocker_probe.py (NEW, read-only, two oracles R34): static (cdecl.compatible -- never text
equality, which is what made the deleted scanner report u8-vs-unsigned-char as a conflict) and
real cc1 via rtu_match (ONE compile implementation, R33). Leads with the DISAGREEMENT table.
- DELETED .run/diag_plumbing.py (R3 tooling under tools/; R33 net -1 scanner).
- Two build-forced corrections: (1) cdecl.tu_scope runs real cpp, so it already expands instantiated
DEFINE_func_* macros -- the macro scan's job is ATTRIBUTION (tu-text vs shared-header macro body:
different transforms, same T1 tier), byte-checked against engine_core.h:7533 for func_80161374;
(2) blockers STACK and cc1 reveals only the first, so a function's tier is the MAX over blockers.
- Smoke test 3 fns: oracles agree 3/3. src/ untouched (write-set asserted). Not yet population
evidence -- that is T2 / KILL GATE A.
Oracle (G1, Ghidra types get, /LIBGTE.H, psyq400.gdt): MATRIX = 32 bytes (short m[3][3] @+0x00,
long t[3] @+0x14, 2B pad after m); SVECTOR = 8B; VECTOR = 16B (long vx,vy,vz,pad).
- HAZARD CONFIRMED: the fleet-wide name `MATRIX` held {s32 m[3][3]; s32 t[3]} = 48 BYTES, not a PsyQ
type at all, while THREE other names (MATRIX_c1, MATRIX_c2, MATRIX2) held the true 32B layout. The
canonical name carried an invention; any future reader assuming PsyQ semantics would be misled.
- FIXED by pure consistent rename across 205 files: 48B invention -> MATRIX_L48 (KEPT — ~131 files are
byte-correct against it, and "fixing" it to 32B would change sizeof/array stride hence codegen);
the true 32B layout now owns MATRIX. R22 clean-fleet 140/140 BYTE-IDENTICAL.
- VECTOR left UNCHANGED on purpose: ours is 12B vs PsyQ 16B (missing trailing pad). I first called it
dead — wrong, it has 1 live use (engine_core.h gte_ldlv0((VECTOR*)sp)). Offsets already agree so a
fix is likely byte-neutral, but it is a LAYOUT change and bundling it with a rename would make an
R22 failure ambiguous. Own R22-gated commit, later.
- engine_types.h gains an oracle-sourced GROUND-TRUTH block: real PsyQ layouts, which of our names are
true vs invented, why MATRIX_L48 must not be "corrected", and the draft-time rule (address-suffix
anything you invent — 7 of the 8 collisions this fleet accumulated were bare generic names).
- SCOPE HELD: renamed + documented; did NOT force existing code onto real PsyQ definitions.
- Propagated 0x8012A464 / 0x8014FFDC / 0x801502EC -> 138/138 byte-identical, 0 stragglers, 3 new
groups. R22 clean-fleet 140/140; dedup 1872/0; C1 237654/237654.
- FINDING (R14/R31): the §20 propagation cap was gating source-level DE-DUPLICATION, not coverage.
The whole uniquify campaign (Buf+MATRIX+Vec8, 223 files renamed, ~1559 copies stripped, 5
propagations, 4 R22 cycles) moved the fleet by +6 functions / +558 ins / -6 stubs and 0.00pp on
all three headline metrics. The freed cores' members were ALREADY matched individually;
propagation just consolidated them into shared macros. "Unblocked" != "unmatched".
- SESSION ATTRIBUTION: of -837 stubs / +0.3pp instr / +0.23pp fn-count, -831 stubs came from the
FIRST batch (broad lift -> 13 cores). The uniquify campaign contributed -6.
- Roadmap B4 re-labelled: a maintainability item, not a coverage lever. Remaining camps
(Handler/Blk8/V8/Prim/Prim_8016E7C8) are small and now known low-yield — opportunistic only.
- distinct-code sat at EXACTLY 3811442/5634875 = 67.6% at open and close. Fresh cracks are the sole
mover of that number; point the next session there.
Two units, committed together because they touch overlapping overlay .c files.
- PROPAGATE: 0x8012E778 (freed by the MATRIX uniquify) -> 138/138 byte-identical, 0 stragglers,
1 new dedup group.
- Vec8 UNIQUIFY+LIFT: camp1 {s16 unk0,unk2,unk4,unk6} (8 bytes) x139 files -> Vec8_c1; the 180-file
{s32 w[8]} (32 bytes) majority keeps the name. These are two genuinely DIFFERENT types that had
been sharing one identifier across TUs of the same overlay — the case §64a exists for; reconciling
them to one layout would have merged a 32-byte and an 8-byte struct. Both camps lifted, 319 local
copies stripped.
- Pre-filtered on an overlay from each camp, then R22 clean-fleet 140/140 BYTE-IDENTICAL.
- Blocked core queue 10 -> 7 (0x8012a464, 0x8014ffdc, 0x801502ec freed). Session arc 13 -> 7 via
uniquify (Buf -> MATRIX -> Vec8). Remaining camps all small: Handler, Blk8, V8, Prim, Prim_8016E7C8.
- uniquify_type --type MATRIX: camp1 {short m[3][3]; long t[3]} x71 jr-split TUs -> MATRIX_c1;
camp2 {short m[3][3]; short pad; s32 t[3]} x6 -> MATRIX_c2; the 578-file {s32 m[3][3]; s32 t[3]}
majority keeps the name. All three camps then single-def -> LIFTABLE -> lifted (655 local copies
stripped).
- Pre-filtered on one overlay from EACH camp (ov_SC01_000 / ov_SC01_077 / ov_SC06_033) — a
pre-filter is evidence only about what it filtered — then R22 clean-fleet 140/140 BYTE-IDENTICAL.
- Blocked core queue 11 -> 10 (0x8012e778 freed; propagation follows separately per §55b).
- NB: the R22 job was reported by the harness as exit -1 (session fork killed the shell wrapper
after make completed). Verdict taken from the log's terminal "check-all: 140 passed, 0 failed of
140", which is only emitted on completion. Read the gate's output, not the wrapper's exit code.
MEASUREMENT CORRECTED THE PLAN. The checkpoint called for a "per-camp field-access reconcile";
measuring the camps refutes that: Vec8 = {s32 w[8]} (32B) in 180 files AND {s16 unk0..} (8B) in
139 files; MATRIX 48B/32B/32B; Buf 16B / 0x20+ / DrawEnv. These are DIFFERENT types sharing an
identifier across TUs of the same overlay — reconciling to a canonical layout MERGES them, the
same failure that broke 103 binaries on Prim. The right op is UNIQUIFY: rename the non-majority
camp (byte-neutral — a type name emits no code; TU-local by construction), which makes every camp
single-def and liftable by the existing lift_types rules.
- NEW tools/uniquify_type.py: deterministic camp ordering (file-count desc, then normalized text,
so re-runs assign the same suffixes); majority keeps the name, camp n -> <T>_c<n>; rewrites ONLY
files that DEFINE that camp (a file that merely USES the name gets it elsewhere and is untouched);
\bT\b word boundaries so `Buf` never matches `Buf80153978`.
- VALIDATED on Buf (578/6/1 files): 11 identifiers across 7 files -> 3 camps LIFTABLE -> lifted
(585 local copies stripped) -> R22 140/140 -> blocked core queue 13 -> 11 (0x8012ea90, 0x801749c8
freed). Propagated 0x8012EA90 ×138; 0x801749C8 dropped (straggler in ov_SC07_006).
- YIELD, HONESTLY (P9): ZERO new matched functions. fn-count 88.61% / instr 79.3% / stubs 40281 all
UNCHANGED; dedup 1867->1868, C1 +138. 0x8012EA90's members were ALREADY matched in all 138
overlays — the propagation consolidated duplication into one shared macro (DRY), not coverage.
The value is the PROVEN RECIPE + the queue moving 13->11, not the numbers.
- dedup_propagate (R32): the skip line printed a COUNT and no names, and aggregated three unrelated
causes into n_local — a body skipped merely for a `//` comment (macro-unsafe, 1-line fix) read
identically to one genuinely using an overlay-local type. Now named and split by cause.
- cookbook §64a (uniquify-vs-reconcile + the validated recipe + remaining camps by cost).
With the §20 local-type cap lifted (commit:0863), dedup_propagate --auto-from planned 17
self-contained cores that were previously skipped "not self-contained (local types)".
- BANKED: 12 cores via --auto-from + func_80175308 (propagated separately, 138/138) = 13 ×138.
func_80175308 is the PROVABLE unblock — the core the SESSION-13 checkpoint named as
local-type-blocked. No claim is made that all 17 were unblocked by the lift; measuring that
needs a pre-lift re-scan I did not run (P9).
- 5 correctly DROPPED as cross-overlay stragglers (0x8012A018, 0x80172C50, 0x80173A60,
0x80144090 in ov_SC01_000; 0x801495C4 in ov_SC07_006): h_exact sharing is all-or-nothing and
those overlays' bytes diverge. --recover NOT used (the documented quadratic thrash hazard).
- GATES: R22 clean-fleet 140/140 BYTE-IDENTICAL (2nd full cycle this session); make report green;
dedup-check 1854 -> 1867 validated / 0 failed, C1 236964/236964; 0 NON_MATCHING (G4).
- FLEET: instr 79.0 -> 79.3% | fn-count 88.38 -> 88.61% | INCLUDE_ASM stubs 41112 -> 40281 (-831).
distinct-code stays 67.6% — correct: propagation replicates already-distinct-matched code;
only a fresh crack moves that number.
- STILL BLOCKED: 13 cores "not self-contained (local types)", blocked by exactly the 8 deferred
VARIANT entities (MATRIX 3-def, Buf 3-def, Vec8, Prim, Handler, Blk8, V8, Prim_8016E7C8).
Next lever = a per-camp FIELD-ACCESS RECONCILE, not a lift (lifting them blindly is what broke
103 overlays earlier this session).
The 3-session-carried blocker ("needs collision-vetting + -O0 strip precision") was
misdiagnosed on all three counts; fixing the instruments first (R35) changed every answer.
- (1) the "case-variant collision" is a TAGGED TYPEDEF counted twice with OVERLAPPING spans:
the inner span starts at `struct` so it emits a VARIABLE definition, the alias is redeclared,
and the highest-first strip leaves the outer end offset STALE -> over-deletes past the span.
MEASURED 13 pairs / 6142 occurrences / 0 standalone tags. build_engine_types.resolve_type_defs()
is now the ONE shared model (R33) + assert_disjoint() enforces span disjointness (R32).
The case-insensitive exclude was a heuristic over a structural fact — it would also have
wrongly dropped the legitimate Obj/obj + Vec/vec pairs. Key by (kind, name) — the C namespace.
- (2) the "-O0 strip precision" bug is a VISIBILITY bug: ov_SC01_077_o0.c is the 1 TU of 3226
that deliberately omits engine_core.h, so the strip DELETED its types; `multiple definition of
D_801DAA08` was 3 steps downstream (undeclared -> parse error -> implicit int -> tentative def
-> link collision) and named a symbol no diff touched. bet.type_visible() derives the visible-
header set from the include graph and keeps such defs local, named.
- (3) a third blocker, introduced this session and caught by R22: --candidates classifies per
ENTITY but emits per NAME, so passing `Prim` dragged in the deferred VARIANT `typedef Prim` and
repointed 103 overlays at the header's different layout. Compiled clean, per-binary pre-filter
green, R22 37/140 — the 103 failures were EXACTLY the 103 Prim-stripped overlays (set equality).
Fixed by the strip invariant "remove a local def only if what becomes visible is TEXTUALLY
IDENTICAL", placed at the MUTATION so a selector bug cannot reach the source.
- lift_types.py: (kind,name) entity keying, --candidates derived selector (retires the ad-hoc
102-type pipeline), divergence + visibility reports, whole-line strip (411 whitespace-churn
lines -> 0), complement-based single-pass rewrite (no mid-loop offset mutation).
- RESULT: 154 types lifted, 2958 files stripped, engine_types.h +510 lines. R22 clean-fleet
140/140 BYTE-IDENTICAL; tools-health OK (corpus 0/0, cdecl ALL GREEN, audit-binaries 140,
dedup-check 1854/0, C1 235170/235170); 0 NON_MATCHING (G4). Metrics unchanged 79.0/67.6/88.38
— honest: a type-lift banks no functions, it unblocks the NEXT propagate.
- DEFERRED + NAMED: 8 VARIANT entities (MATRIX 3-def, Buf 3-def, Vec8, Prim, Handler, Blk8, V8,
Prim_8016E7C8) = the per-camp field-access reconcile, the remaining hard part of roadmap B4;
14 carried tags; 5 types kept local in the -O0 TU.
- cookbook §64 (the three laws + the pre-filter lesson: a pre-filter is evidence ONLY about what
it filtered — ov_SC01_077 passed the Prim-broken run too; pre-filter on a binary that FAILED),
decision-log (R31), CURRENT_PHASE.md log.
v2 generalizes v1: also reconciles CALLEE decls in shared headers that a
byte-perfect draft declares differently than engine_core.h (sources the byte-true
sig from the draft's `extern` line; reuses v1's compatible/build_decl machinery).
--check validated: func_80174CB0 -> func_80012C6C s32->s16 (all SAFE); v1 unbroken
(func_8014CD80 ALREADY-OK). The byte-gate + R22 arbitrate scalar-width changes.
Known limitation (byte-gate caught it, fail-closed, nothing banked): v2 fixes only
src/shared/*.h, not per-overlay-local decls — func_80174CB0 stays blocked by a local
decl of func_80012C6C in ov_SC07_006_jr_8015C32C.c:8523. v3 = extend to the overlay
split .c (carried in the checkpoint).
Also in flight (checkpoint): crack wave w9lidyi5b (24 fresh LIVE=138 families,
running) + permuter winner func_8014D12C (score-0, staged) — both gate-on-completion.
Builds + self-tests the tool that reconciles a shared-header forward-decl to a
function's byte-true signature — the integration half of the proven func_8014CD80
x138 pipeline.
- tools/fix_header_decl.py: --fn --draft [--check|--apply]. Parses the byte-true
def sig, canon-compares (typedef-aware int==s32, unsigned short*==u16* -> skip
ALREADY-OK), REFUSES ABI-changing rewrites (param-count / ptr<->scalar / scalar
class), preserves the macro `\` continuation, snapshots + prints the git-restore
(§61: undo = restore, validate fleet-wide by R22).
- 4 self-tests pass: (1) idempotent on the already-fixed func_8014CD80; (2) correct
rewrite + `\` preserved; (3) REFUSE on a 2-vs-3-param ABI mismatch; (4) end-to-end
--apply on func_8014D12C turned the `conflicting types` PLUMBING into a clean
codegen DIFF (plumbing dissolved; its body is a near-miss so no bank), reverted
clean. The self-test CAUGHT two fleet-corrupting bugs before any apply (a dropped
macro `\`, and non-idempotent int/s32).
- cookbook §63 + CURRENT_PHASE. NEXT: fresh-family wave over the 38-family market
-> fix_header_decl --apply -> harvest_verify -> dedup_propagate -> R22.
Bounded probe (SESSION-13, token-free) that REVERSED the same-session "fresh
reach-138 well is spent" verdict. Target func_8014CD80: 138 live, 0 matched, NO
DEFINE macro, a universal body (only universal callees + param offsets, zero
overlay-local D_* refs), clean MATCH draft from batch-1.
- Blocker was a def-side header decl: engine_core.h DEFINE_func_8014CD0C()
forward-declares it `void func_8014CD80(s32,void*,void*)` while the byte-true
def is `int func_8014CD80(s32,u16*,u16*)`. gate_stage's arity pre-pass is
param-COUNT-only (misses return/ptr-type); §54 reconcile_def_sig fixes the
wrong direction.
- One byte-neutral header edit (void->int, void*->u16*; call site passes u16[3]
arrays + ignores the return -> codegen unchanged) -> harvest_verify banked x1
BYTE-IDENTICAL -> dedup_propagate --addr propagated 138/138 overlays
byte-identical (live 138->0) -> R22 clean-fleet 140/140.
- Fleet 78.7->78.8% instr, 88.22->88.26% fn-count from this one family;
tools-health green (dedup 1851/0).
Quantified market (decision-log 2026-07-23): of the 75 fresh (>=100-live)
families, 46 carry an engine_core.h caller forward-decl, 38 SIMPLIFIED = the
func_8014CD80 pattern -> each a candidate x138 (~+1.5-2.8pp instr). NEXT: build
tools/fix_header_decl.py + a fresh-family wave. func_80165CA0's 0/135 was a
non-universal BODY (different failure mode), not this blocker.
Propagation of the 6 batch-1 x1 banks (§55b: banks committed first in commit:0848,
then targeted propagate as a standalone step):
- dedup_propagate --addr: func_801325B8 -> +3 onboarded-tail siblings
(ov_SC07_007/010/011). func_8014A048/func_801678F0 byte-diverge in the SC07
cluster (kept x1); func_8014FE60/func_80167540 local-type-blocked §20 (x1).
- func_80165CA0: consolidated its h_exact subgroup (dedup group registered, +0
new), then family_sweep --hseq 0/135 — a PER-MEMBER WALL (cf func_80133AB0
0/136). The x135 "fresh family" prize does not exist here.
- Net batch-1 yield ~9 newly-matched functions; fleet 78.6->78.7% instr, distinct
flat; ov_SC07_006 84.6->84.8%. R22 clean-fleet 140/140; tools-health 1850/0.
The finding (R14/R35, decision-log 2026-07-23): nins*reach leverage over-counts —
rank by LIVE-siblings. build_wave_args.py --rank live now ranks by the true lever
and reports the fresh(76)/onboarded-tail(44) split. The reach-138 family well is
largely SPENT via wave+gate; the fresh families are the hard tail (def-side
plumbing/DIFF/per-member walls), not free x138 fuel.
- ROOT CAUSE: the jtbl carve's s8b carried-decl layer conflicts with each draft's
externs; the reconcile chain (cast_call_sites+reconcile_tu, --src-file-aware) exists
but gate_stage runs it PRE-carve against the wrong TU (a jtbl fn's real TU is the
split file, which doesn't exist until harvest_verify carves).
- FIX (cookbook s62): harvest_verify._jtbl_reconcile runs the chain POST-carve against
the CARVED TU, draft-only rewrite, guarded by _jsnap is not None. Validated:
func_80135260 (callee) + func_80191C50 (data) both conflicting-types -> genuine DIFF.
- FINDING (R14/R31 -> decision-log): dissolving the plumbing REVEALED all 4 jtbl drafts
have a deeper issue -- func_80135260/80191C50 real %hi-share regalloc residual (agents'
reloc-masked match_one MATCH over-claimed it); func_8012AAAC def-side-arity + FLEET-
SHARED + still DIFFs after arity fix (def-side wall); func_80135EB0 isolate FAILED.
The '+0.58pp from 3 reach-138 jtbl families' is REFUTED -- near-misses/walls, not
plumbing. The fix banks any plumbing-ONLY jtbl fn + makes the jtbl gate honest.
- s61 traps re-confirmed (s62): gate jtbl ONE-AT-A-TIME (mid-batch isolate-FAIL corrupts
the batch); fix_arity on an engine_core.h fn leaks fleet-wide (restore src/shared/ too).
- R22 clean-fleet 140/140; tool change only (no committed-byte change).
- binary-aware crack wave (new tools/workflows/wave_binary.js): 8-target calibration
over ov_SC06_018 substantial stubs, 7/8 match_one MATCH
- func_801365B8 (155, reach 133): cracked FRESH in ov_SC06_018, swept 132/132 siblings
via family_sweep --hseq --source ov_SC06_018 --allow-pins -- SESSION-10 refused this
family 0/133 from an ov077 exemplar. THESIS CONFIRMED (fresh exemplar unlocks it).
- func_80133AB0 (137, reach 137): cracked fresh + banked x1 (+ a byte-neutral s17a-1
cast reconcile of banked caller func_801343C4), but the family sweep FAILED 0/136 even
from the fresh exemplar (reverted clean) -- THESIS REFUTED for this family.
- FINDING (R14/R31 -> decision-log): the fresh-exemplar sweep is FAMILY-SPECIFIC, not a
blanket mechanical x137. A fresh crack is necessary but not sufficient; the byte-gate
arbitrates each family (~50% on this 2-family sample -> discount the ~1.5pp estimate).
- tooling (R33): family_sweep --source override now searches matched_members (a fresh
member leaves 'members' after a sig-regen); cdecl._depth0_spans consumes backslash
line-continuations so a raw-draft #define macro no longer trips audit-cdecl.
- R22 clean-fleet 140/140 byte-identical; tools-health green (dedup 1849/0, C1 234615);
0 NON_MATCHING. fleet 78.4->78.5% instr / 67.1->67.5% distinct / 88.14->88.18% fn-count.
gate_stage._jtbl_prepare carried the SAME config-only undo as harvest_verify's did,
and ate the tree again on the first ladder run: 5 orphan region files, truncated
TUs, `undefined reference to func_80192F64`. That INVALIDATED the run's 0/10, so it
was re-measured rather than reported (R35 — a probe from a broken tool is not
evidence). Tree restored from HEAD and re-verified byte-identical first.
DELETED, not patched (R33 — the best outcome is a deleted stage). It was wrong on
two independent axes:
1. §61b already byte-proved THE CARVE MUST FOLLOW THE SPLICE. A batch pre-pass
carving unspliced functions reports "prepared" and yields a spec that fails
once the body lands — which is why it banked nothing.
2. Its undo snapshotted only config/, while jr_isolate_all rewrites region 0 back
over the ORIGINAL src/<ov>/<nm>.c truncated.
harvest_verify's per-draft prep is the correct mechanism, snapshots the full source
set, and undoes per function. Two implementations of one capability, the outer one
ineffective AND destructive.
THE HONEST RE-MEASUREMENT (clean tree; tree verified clean after):
- 0/10 bank, but 9/10 now COMPILE and land as whole-binary byte-DIFF; 1/10 plumbing.
- match_one close=0 on several (the function's own bytes exact) and rtu_match says
MATCH-in-real-TU for func_80135888 — while func_801299C8's transformed draft does
not compile in its real TU at all. The residual is MIXED, not uniform; at least one
is an IMAGE-level effect rather than the draft or its TU decl context (prime
suspect: jtbl/rodata carve placement). NOT generalized from one data point.
- This PRICES Task 14 stages 2-3 by measurement: the existing ladder converts 0 of
10, so they are not "wire in normalize_self_decls + the type-lift and collect ten
banks" — the projection error §57a already caught once this phase.
- R22 clean-fleet 140/140 BYTE-IDENTICAL with the giant func_8018F694 banked and the
func_80135A4C family swept 138/138
- cookbook §61d (the tree-eating undo in two tools; the constant-label defect; the
re-probe + ladder measurements; the general rule: an undo whose scope is narrower
than its write scope destroys work no byte-gate can see)
- decision-log + CURRENT_PHASE updated (R30/R31)
The session-7 checkpoint gated the entire jtbl track behind one finding: the
carve+isolation path yields a bank that is incrementally valid and clean-invalid
(139/140, [FAIL] ov_SC06_018, "twice, identically"). The prescribed diagnosis
(diff the incremental vs clean object set) never ran, because the failure does
not reproduce.
MEASURED, with the bank applied through the single-function automated path
(harvest_verify --chunk 1 -> [jtbl] carved -> + chunk(1) -> BYTE-IDENTICAL):
per-binary clean (rm asm+build; extract; build) -> BYTE-IDENTICAL cbbc4f44
make clean && extract-all && check-all (run 1) -> 140 passed, 0 failed of 140
make clean && extract-all && check-all (run 2) -> 140 passed, 0 failed of 140
ATTRIBUTION (best-supported; the failing tree is gone): the 139/140 runs were
taken on the tree left by the BATCH _jtbl_prep (6 table-bearing -> 1 carved,
4 isolate-FAILED, 1 stale-asm carve fail) — five failed preps' residue of
stranded carves + half-applied isolations. The per-function snapshot-restore
that removes exactly that residue landed AFTER those runs, in commit:0803, the
same commit that named the blocker.
THE LESSON (R35 on ourselves, -> decision-log): "twice, identically" was not a
replication — two reads of the SAME contaminated state is one observation. A
replication must RE-CREATE the state, not re-run the check. Standing guard:
re-apply a fault from a known-clean tree before writing it down as a property
of the mechanism. Sixth "structural wall" to resolve to our own tree/tooling.
- BANKED: func_80135A4C (181 ins) x1 in ov_SC06_018 — isolated into its own
code subseg + .rodata carve (single-table, no JTBL_PADS; tail3..tail18 renumber)
- §61c faults 1-2 STAND: a stranded carve poisons the overlay; per-function undo
is unsound in a batch -> ONE jtbl draft per harvest_verify invocation.
jr_inventory's 1:1 ownership assertion was right and is unchanged.
- UNFROZEN: this family = 138 members / PURE / 24,978 ins ~ +0.19pp (jtbl_family_bank,
§53 carve law); the 9 preserved t5wave cracks (Task 14 stages 2-3, §57 plumbing)
- R22 clean-fleet 140/140 x2; tools-health OK (dedup 1848/0, C1 234481/234481,
cdecl 53189/53189, audit-binaries 140); 0 NON_MATCHING (G4)
- fleet 78.0% instr / 66.5% distinct / 87.95% fn-count
- also: preserve the 4 untracked wave-4 .o0 drafts (R20); killed an orphaned cc1
from the Jul-21 session burning a full core for 13h23m
DIAGNOSIS CORRECTED: the wave's 10/12 blocker is NOT "§8e-2 table-count drift" (the symptom
the filter reports) but a NON-CONTIGUOUS .rodata carve — the new function's table is separated
from the TU's existing carve by an UNMATCHED function's table, and one object cannot straddle
that gap. jtbl_carve names its own remedy in the refusal message.
RECIPE BYTE-PROVEN (func_80135A4C, 181 ins / 138 members):
jr_isolate_all --only <fn> ; make extract ; <splice> ; jtbl_carve --func <fn> ;
make extract ; make build -> BYTE-IDENTICAL
(isolation verified byte-neutral on its own first; a config change needs extract, not just build.)
BUILT: gate_stage._jtbl_prepare — per-draft carve + auto-isolate on the §8b walls, logic LIFTED
from jtbl_family_bank (R33: one implementation, two callers — their divergence IS this bug),
snapshot-restore undo, GATE_NO_ARITY A/B guard. Ladder: canon -> cast -> reconcile_tu -> jtbl
-> arity -> gate -> sig_unify -> gate.
IT DOES NOT YET BANK, and that is the finding: THE CARVE MUST FOLLOW THE SPLICE. The
non-contiguity is only DETECTABLE once the body is in the object; while the fn is still
INCLUDE_ASM, jtbl_carve reports SUCCESS and produces a spec that fails when the body lands.
Byte-witnessed both ways (spliced -> NON-CONTIGUOUS 0xaa810/0xaa920; unspliced -> "prepared 1/1"
then byte-DIFF). Innocent suspects A/B'd out: the draft is IDENTICAL through canon/cast/
reconcile_tu, and GATE_NO_ARITY=1 changes nothing. FIX = per-draft prep inside harvest_verify's
splice loop (it owns the splice), not a batch pre-pass in gate_stage.
SUB-FINDINGS: (a) a wholesale `git checkout -- config/` undo is WRONG in a batch gate — it
discarded a previously-banked-but-UNCOMMITTED carve, leaving that bank's source with no subseg
(undefined reference to func_80136C90 at link). Now snapshot-restore + drop only this run's
region files (§61's constraint, which I had written and then not applied here). (b) being in a
_jr_* TU != having a table: only 4 of 8 wave drafts reference a jtbl_.
Tree restored byte-identical; nothing banked. cookbook §61a corrected + §61b.
Ultracode wave, 12 agents (~2M tokens), over freshly-prefetched ov_SC06_018 exemplars.
11 MATCH / 1 near, INCLUDING ALL THREE GIANTS (710/673/478 ins). Whole-binary gate: ZERO.
Splicing each failure individually (the gate's own label is §58's memcpy red-herring) gave
THREE DISTINCT blockers, none of which the ladder clears:
(1) §8e-2 jtbl table-count drift -- 10 of 12. "more rodata .align directives than pad specs".
STRUCTURAL FINDING: fresh crack fuel in a well-matched overlay CONCENTRATES in jtbl-carved
TUs (the non-carved ones were harvested first), so §8e-2 GATES the next tranche of
substantial cracking rather than being a straggler.
(2) §57 self-decl conflict -- the 2 plain-TU drafts ("argument 'arg2' doesn't match prototype").
normalize_self_decls exists, is wired into family_sweep, and is NOT in gate_stage -- the
same gap the arity pre-pass had.
(3) local-type redefinition (from the Task-14 diagnosis set) -- wants the type-lift.
So gate_stage needs THREE stages; only the arity pre-pass landed today.
All 12 drafts PRESERVED at .run/giants/t5wave_* (R20): genuine cracks with per-function lever
notes (cross-jump barrier placement, MEM_IN_STRUCT_P store/load ordering, §43 K&R s16 params,
$s-pins, CSE-break barriers). Do NOT re-draft -- they bank the moment the stages exist.
METHOD NOTE: `make build | grep -i error` missed the real failure TWICE (the jtbl_rodata_pads
line contains no "error" token; and the build failed at a later stage than the warnings I read).
Check rc, read the tail unfiltered -- a filtered build log is a selection tool, and every
selection tool here has eventually lied (R32/R35).
Tree reverted clean; nothing banked. cookbook §61a.
SCOPING (it corrected my own claim twice — the durable part of this task):
Remaining frontier = 2,873,658 stub ins = 22.0pp (resident+138 overlays; main excluded).
Substantial 80-1000 ins = 10,934 fns / 12.84pp across 1,398 distinct h_seq families.
I claimed "Task 5 gates 12.84pp". It does not:
340 families / 7.72pp exemplar ALREADY ATTEMPTED or WALLED — the top-12 by value are our
known set (func_801412A8 permanent wall, func_8013C414 -O0-blocked,
func_8014D820 close-11, func_8015B950/func_8013B83C cracked-but-
deferred, func_8013D53C 14/137, func_8013BD74 §8e-2). These need the
DEFERRED TOOLING fixes, not fresh drafting.
1058 families / 5.40pp exemplar NEVER attempted — the true fresh fuel, of which
48 fams / 0.62pp already have a cached member (draftable now, no MCP)
877 fams / 3.10pp have none — median 1 MEMBER, i.e. overlay-UNIQUE code (every big
138-member family lives in ov_SC01_077 and was cached+drained by
waves 1-4). So the prefetch is PER-OVERLAY, never fleet-wide.
Greedy overlay cover: ONE import (ov_SC06_018) unlocks 54 fresh families = 1.59pp; imports
2-8 add only +0.59pp combined, leaving a 632-family long tail. Ranked list:
.run/autopsy/t5_ready.json.
EXECUTED (R23 lock dance): MCP stopped (save succeeded) -> ghidra_import_raw.sh
extracted/retail/SC06.CD.dir/FILE_018.dir/0.4.dec @0x80128158 -> DefineFunctions
(created=72 existed=29 failed=0) -> DecompileFunctions over the 101 uncached substantial
stubs -> 101 ok / 0 fail. Ghidra-C cache 882 -> 983; ov_SC06_018 now 149 substantial stubs
cached. MCP restarted (41 tools, serving).
Overlay Ghidra program NOT committed (Phase-13/15 precedent: script-reproducible from
ghidra_import_raw.sh + DefineFunctions, no manual RE on it; avoids ~14MB/overlay .git bloat).
CAVEAT on the ready-list: attempted-detection matches backlog entries + preserved-draft
filenames, so it carries false-fresh entries (func_8014032C is jtbl-table-count-drift blocked;
func_8017A4AC is already banked). The 48 figure is an UPPER BOUND — verify per family.