Commit Graph

6 Commits

Author SHA1 Message Date
Drew T 07ebb5658d fix(phase-26): jr_isolate_all empty-region0 skip — cutting an already-isolated region's non-leader works
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.
2026-07-13 22:14:57 -06:00
Drew T 7e4165676d fix(phase-26): isolation-residue corruption chain — config cleanup + revert() restores config + fail-loud validation + --raw sweep mode
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.
2026-07-13 22:13:11 -06:00
Drew T 9b93c254c2 feat(phase-26): func_8015AE2C (562 ins, x134) banked — Fable5 MATCH + 3 isolation bugs fixed
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.
2026-07-13 18:26:32 -06:00
Drew T c66b530f71 fix(phase-26): bound the §8b carried decl layer + cross-address sibling naming
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.
2026-07-13 14:41:53 -06:00
Drew T 38ac5659aa feat(phase-26): §8b scoping wall BROKEN — decl-environment reconstruction + lazy per-core isolation
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).
2026-07-13 13:25:39 -06:00
Drew T 234788dfc4 feat(phase-26): §8b overlay-src parser (404/404) + jr isolation tool + the gcc-scoping wall finding
- tools/overlay_src_split.py: overlay-.c-aware partition (header = includes + Phase-17
  canonical-sig layer; per-address items = preamble + body; robust def/decl/K&R/DEFINE_func/
  SETTER/RETCONST classification). Fleet-validated 404/404 overlay .c, 341,902 items —
  round-trip exact / 0 unresolved / 0 non-monotonic. The Stage-2 isolation unblock.
- tools/jr_isolate_all.py: multi-cut jr resegment (config split at jr boundaries, source
  repartition + INCLUDE_ASM path repoint, banked-jr carve repoint, -O0 skip, ambient decl
  carry). SINGLE-cut isolation byte-identical (func_8013FFD8 -> d19c9580, R22).
- FINDING (decision-log 2026-07-13): full 54-jr isolation of the dense _after object hits
  gcc-2.7.2 block-scope-extern TU-persistence (func_801734BC/D_80126B3E declared only in
  engine_core.h DEFINE_func macros); mechanical TU-split breaks it. Fix = declaration-
  completion from a global symbol->type map (Drew-approved next step; lazy per-core).
- baseline intact (ov_SC01_077 rebuilds d19c9580); no config/src/binary change committed.
  CURRENT_PHASE session-5 checkpoint + decision-log R31. db.*.gbf = R23 noise, not staged.
2026-07-13 12:00:26 -06:00