Cutting func_80178D40 out of ov_SC01_000_jr_801734BC adds the region's banked LEADER (0x801734BC)
as a cut too (the one-carve-per-object rule), making region 0 EMPTY (the object's first item IS the
first cut) — and region 1's derived name equals the object name, so emitting region 0 duplicated the
line exactly -> splat "segments out of order". Skip an empty region 0; region 1 rightly claims the
object's offset and name. First sibling then banks through the full chain (isolation validation
green -> carve -> --raw remap -> stage ladder -> whole-binary gate): ov_SC01_000 BANKED, included
here. The remaining 132 siblings sweep next.
Three-layer fix for the func_80178D40 ×133 sweep failures:
- LAYER 1 (the residue): jtbl_family_bank.revert() restored carve pieces + src/ but NOT the
isolation's CODE-subseg lines in the splat config. A failed bank attempt (BEBC's first try)
left its isolation config in place; the successful retry re-isolated on top and a DUPLICATE
`- [0x4b364, c, ov_SC01_000_jr_801734BC]` line rode into the commit (harmless to splat —
zero-length — so R22 stayed green). revert() now also restores config/splat.<ov>.yaml.
The committed duplicate is removed (ov_SC01_000 rebuilt BYTE-IDENTICAL 9052dc0e).
- LAYER 2 (the detonation): jr_isolate_all walked the duplicated object TWICE -> two
replacements -> a reversed duplicate block -> splat "segments out of order". It now VALIDATES
the generated config (code subsegs strictly ascending, names unique) and refuses to write on
violation, naming the likely cause — a corrupt input dies at the tool, not three tools later.
- LAYER 3 (the sweep template): jtbl_family_bank gains --raw <crack.c> — template from the RAW
crack via remap_hseq_body instead of the exemplar's banked source unit. REQUIRED when the
exemplar banked at the `reconciled` stage: a reconciled body is TU-SPECIFIC (§41c — uniquified
type names, TU-targeted casts), so extract_unit hands the sweep a polluted template and every
sibling gate-fails (byte-proven: 178D40 banked reconciled -> sweep 0/4; 8015AE2C banked raw ->
sweep 133/133). Same law as family_sweep --reconcile-raw.
Exemplar banked byte-identical (d19c9580); R22 clean-fleet 136/136.
Fable5 crack: MATCH 562/562, pin-free, jump table verified.
THREE REAL BUGS the bank exposed in jr_isolate_all (each byte-proven; each would have
silently corrupted every future heavy-core bank):
1. --only filtered `banked` as well as the cut set, so already-banked jr went untracked
and their carves were never followed. --only selects what to CUT; it must not erase
the record of what is already banked.
2. carve ownership was read from splat .s — but splat emits NO .s for a MATCHED function
(its .c holds real C), so the lookup found nothing. Now resolved from the extracted
IMAGE via family_remap.reloc_targets (byte-exact: func_801734BC -> 0x801d8c68 etc).
3. THE STRUCTURAL ONE: a region may host at most ONE .rodata carve, because an object's
.rodata is a single CONTIGUOUS section. Cutting at func_8015AE2C (jtbl 0x801D8B54)
left the banked func_801734BC (jtbl 0x801D8C68) inside the same region, so the object
emitted a 0x34 .rodata spanning BOTH tables (image +33 B). Every already-banked jr in
a cut object is now cut too -> exactly one carve per object. Cookbook 8b's "bank
same-subseg families ASCENDING" note warned about this; it is now enforced by
construction instead of left to discipline.
Also required (per the crack's own analysis, all byte-verified):
- engine_core.h: DEFINE_func_8015BEC4's zero-arg thunk returns func_8015AE2C(), so the
extern must drop its (void) prototype and the def must stay K&R/unprototyped.
Byte-neutral across all 136 (R22 green).
- recovery chain: cast_call_sites (27 callees) + reconcile_decls (3 data syms). The raw
body declares callees with types that conflict with their real engine_core.h defs; the
original never redeclares them, it CASTS at the call site (cookbook 20).
Layout now exact: .rodata 0x801d8b54/0x1c (7 entries, pad trimmed) + 0x801d8c68/0x14 +
0x801d92a0/0x20 — one table per object, each at its true address.
Two bugs the func_80182268 sibling sweep exposed (both would have silently capped
every future jr family bank):
- extract_unit walks BACKWARD from a definition absorbing preceding extern/comment
lines as the fn's preamble. The §8b carried decl layer sits directly above the
FIRST item of an isolated region, so the unit swallowed the whole layer -> the
template dragged ~140 unrelated externs into each sibling (some naming types the
sibling TU lacks) -> gate-fail. jr_isolate_all now emits an explicit end-marker and
extract_unit stops at it (also guards the Phase-17 canonical-sig layer).
- jtbl_family_bank passed the EXEMPLAR's name to the sibling's carve/isolate/stub
lookup. Cross-address families (same engine fn at a different vram per overlay)
therefore never resolved: ov_SC01_077 @0x80182268 -> ov_SC02_000/003 @0x8017FCB0.
The sibling's name is now derived from to_addr. The first two banked jr families
were same-address, so this had never surfaced.
ov_SC01_077 d19c9580 byte-identical; R22 clean-fleet 136/136.
The full 54-jr isolate-all on ov_SC01_077 now builds d19c9580 BYTE-IDENTICAL
(R22 clean-fleet 136/136) — the configuration session 5 could not build. The
heavy-jr harvest (191 cores / 5.53M templatable ins) is unblocked.
- R14 CORRECTION: session-5's "gcc-2.7.2 block-scope-extern TU-persistence" root
cause was WRONG. There is no gcc quirk — DEFINE_func_* macros expand at FILE
scope, so their leading externs are genuine file-scope decls that merely live in
engine_core.h, invisible to any col-0 .c scan (1377 macros / 3929 lines / 1462 syms).
- REJECTED the approved "global symbol->type map + shadow set" design: the engine is
loosely typed (func_80173544 is DEFINED `s32 f(void*)` yet declared `extern void
f(void);` inside func_801734BC's body), so declaring every USED symbol hoists that
block-scope shadow to file scope and CREATES the conflict a shadow-set then dodges.
Instead reconstruct the original TU's file-scope decl environment and carry it
strictly FORWARD — conflict-free by construction (every carried decl already
coexisted with every definition in the one original TU; compatibility is
order-symmetric; shadows stay in bodies and travel with their item).
- The byte-gate found two MORE lost decl sources, not predicted: (a) a definition is
itself a declaration for everything below it in its TU (func_8012B2CC undeclared);
(b) file-local typedefs used by a carried prototype (parse error, Vec3s). K&R defs
must render `extern T f();` (unprototyped), never f(void).
- LAZY per-core isolation wired into jtbl_family_bank (Drew's call — upfront-x134 =
~7,200 region files): jtbl_carve NON-CONTIGUOUS fail-loud -> jr_isolate_all --only
<core> -> re-extract -> re-carve. Proven on func_80178D40 (890x134, heaviest core):
carve blocked -> isolated (byte-neutral d19c9580) -> carve in its own subseg.
- TWO LATENT BUGS fixed (both would have corrupted the heavy sweeps):
* jtbl_carve.func_subseg derived the owning subseg from the ASM TREE, which `make
extract` never prunes -> after an isolation it returned the STALE owner and
silently re-created the very collision the isolation removed. Now config-derived.
* jtbl_family_bank/jtbl_carve revert() DELETED the shared overlays.mk carve var
unconditionally -> would destroy a COMMITTED carve (all 134 overlays have one) on
any failed sibling. Now restored to its committed value; only region files created
by this attempt are removed; dirty-tree preflight refuses to start a sweep.
- docs: cookbook §8b RESOLVED + new §8c "splitting a TU means rebuilding its
DECLARATION ENVIRONMENT, not moving text"; decision-log 2026-07-13 (R30/R31).
- parser selftest 404/404; R22 clean-fleet 136/136; 0 NON_MATCHING (G4).