Commit Graph

435 Commits

Author SHA1 Message Date
Drew T 8e18bb3df6 chore(phase-29): preserve the remaining behemoth-2 analysis tools (b2_cmp/dump/map/marks/side) 2026-07-25 01:22:36 -06:00
Drew T 28d10601ae docs(phase-29): cookbook §71 — behemoth #2 to 3334/3338; the adjacent-sibling lever; §69 partly REFUTED
func_8017D960 (3,338 ins): 3,334 ins drafted, 98.8% register-masked-identical, 88.3% byte-aligned,
byte-exact prologue AND epilogue, exact 0x320 frame, same 10 saved regs, identical ~110 stack slots,
SYMS-OK. NOT a match (G3) -- but an order of magnitude closer than behemoth #1.

- THE LEVER: it is the LIT VARIANT of func_8017CA80, the 952-ins renderer immediately above it in the
  same file (already matched). Diffing the sibling gave ~90% of the C free and a 3334/3338 draft on
  the FIRST compile. GENERALISED: before mapping any giant, grep for an already-matched adjacent
  function that is the same routine. One grep can replace days of analysis.
- §69 PARTLY REFUTED: its law 1 (write whole body coarsely -> correct frame/saved-reg set) CONFIRMED
  and decisive; law 2 (measure region-aligned) confirmed but its TOOL did not transfer (per-switch-
  case); its HEADLINE ("the deliverable is the map, not a match") is refuted for non-dispatchers --
  §69 was derived from a 359-call dispatcher with no sibling.
- TOOL SUPERSESSION: .run/giants/b2_mask.py + b2_full.py = shape-agnostic masked sequence aligner
  (structural AND byte numbers). Replaces s18_regions_comparator.py for all giants.
- FAMILY: func_8017CD9C + func_8017E778 are the same 3,338-ins fn with only 3 light-descriptor
  symbols changed -> one crack templates x3.
- MY OWN PROFILING ERROR, recorded (R14/R35): I briefed "no switch" from a sltiu jump-table grep; the
  switch is a COMPARISON TREE (23 slti). A jtbl grep is not a switch detector.
2026-07-25 01:18:00 -06:00
Drew T ba35785ec4 feat(phase-29): bank func_801777BC (59 ins) x138 — the giv-init base-register lever (§70)
- MATCH (59 ins), real-TU verified by the agent before handing back (cc1 rc=0, 59/59, 0 diffs).
- Propagated x138 with ZERO exclusions -> confirms the ×3 cap on func_80174CB0 was purely the
  carried-extern collision: a body with no externs propagates clean.
- R22 clean-fleet 140/140, 0 failed. dedup-check 1884 validated / 0 failed, C1 coverage complete.
- FLEET CROSSES 80.0% instr-weighted (10,509,526 / 13,141,652); fn-count 89.02%; distinct 67.7%.
- THE LEVER (cookbook §70): residual was ONE instruction, addiu $t0,$t1,0xC vs $t0,$a0,0xC -- a giv
  based on a copy of the param. Reading gcc-2.7.2 loop.c/cse.c proved the natural form can never
  emit the target: cse.c:make_regs_eqv makes the copy canonical (it out-lives a0) and
  loop.c:update_reg_last_use won't extend a0's last-use (giv-init UID >= max_uid_for_loop). Fix:
  walk the PARAMETER itself, so record_initial sees the biv init as hard reg (reg:SI 4),
  valid_initial_value_p accepts it (precondition: no calls), and emit_iv_add_mult bases the giv on
  $a0 -- yielding both required instructions free.
- META: this compiler-source reasoning was done by an ORDINARY Opus 5 drafting agent, unprompted --
  the tier Phase 23 reserved for Fable5. One data point, recorded as such; the cheap action is to
  give routine drafting agents the gcc source path.
2026-07-25 00:49:04 -06:00
Drew T c31b1ad0b3 docs(phase-29): cookbook §70 — the giv-init base register lever (walk the param, not a copy) 2026-07-25 00:39:58 -06:00
Drew T a8872fa169 docs(phase-29): cookbook §69 — behemoth recon (func_80183814, 5122 ins): map it, don't draft it
First attempt on the game's largest unmatched function. No match (never the goal); the deliverable
is the map, and every claim is byte-verified against the target .s.

- STRUCTURE: an actor state machine, not a straight-line giant. 21-case switch via jtbl_801F4CE4
  (sltiu 0x15); 359 jals to only 37 DISTINCT callees (verified); 48-ins preamble + 19-ins shared tail.
- THE FINDING: it decomposes into repeated templates, not 5122 unique instructions —
  35 instances of one "spawn-effect" packet (~1400 ins, crack one -> 34 free),
  7 "wait/countdown" (already reproduced at 0 skeleton diffs), 12 "HUD/text",
  plus twin cases (0≈3, 1≈4). Only 3 cross-jump edges couple anything.
- TWO GENERAL LAWS FOR GIANTS, measured: (1) register pressure is GLOBAL, so a partial draft gets
  10 callee-saved regs instead of 8 and a matching PREFIX is structurally unavailable — write all
  cases coarsely first, then refine; (2) match_one's global number is meaningless on a partial giant
  (666 vs 5122) — measure REGION-ALIGNED instead.
- NEW REUSABLE TOOL: .run/giants/s18_regions_comparator.py (region-aligned skeleton comparator, works
  on any giant). Caveat travels with it: masks register numbers + jal targets, so it proves STRUCTURE,
  never closeness; finish on the whole-binary gate (G3/P9).
- 2 idioms cracked in passing (the D_x[t+K] constant-fold needing a separate index statement; the
  (s16)*(u16*)p + /455 magic-0x90090091 form).
- VERDICT: tractable but a ~2000-line WRITE, not a hard puzzle — no scheduler wall, no unsteerable
  regalloc. Recipe for the next attempt recorded.
- artifacts preserved under the tracked .run/giants/ path (.gitignore now allowlists *.py there).
2026-07-25 00:33:06 -06:00
Drew T e112eff601 fix(phase-29): find_site — a comment-only line halted the extern scan (§68); func_80174CB0 x1 -> x3
TWO mislabels in one tool, both found by making it print what the compiler actually said.

1) compiles_standalone() returned a bare False and the caller filed EVERY failure under
   "overlay-local TYPE (the real cap)". The dominant real cause is undeclared FILE-SCOPE EXTERNS.
   Now returns (ok, stderr) and the skip is classified by actual cc1 output.
2) find_site()'s backward walk over "preceding contiguous externs" skipped BLANK lines but not
   COMMENT-ONLY lines, so a full-line /* ---- */ between two extern groups dropped every extern
   above it. Comment lines are now skipped like blanks and filtered out of the emitted body so
   make_macro never meets a `//`.

RESULT, measured honestly: func_80174CB0 went from "not self-contained" to a 138-member PLAN, but
--recover banked only x3 (ov_SC07_006/007/011); 135 overlays excluded. Those exclusions are NOT
byte divergence (all 138 share h_exact) -- they are the CARRIED EXTERNS colliding with each target
overlay's own decls. The carry is necessary but not sufficient: it must reconcile per-target-TU
(cdecl.compatible(), the shape reconcile_tu already uses). Spec updated in CURRENT_PHASE.md.

- R22 clean-fleet 140/140, 0 failed. dedup-check 1883 validated / 0 failed, C1 coverage complete.
- fleet instr 79.9% (10,501,384 / 13,141,652); +246 ins from the x3.
- WHY THIS MATTERS beyond the numbers: the Phase-21 backlog already prescribed "macro-extern-
  injection frees them x134 (~+0.3%)" and it was never built, because the mislabel told every later
  session these were the known-hard type wall. A wrong diagnostic label cost ~4 phases.
- cookbook §68. NOTE the exclusion message is ALSO mislabelled ("byte-diverge / irreconcilable"
  conflates differing bytes with a non-compiling instantiation) -- logged to fix.
2026-07-25 00:17:08 -06:00
Drew T e6053357b8 docs(phase-29): cookbook §68 — the comment-halted extern scan + the mislabel that hid it for 4 phases 2026-07-25 00:00:41 -06:00
Drew T af59d8a630 feat(phase-29): bank func_80174CB0 (123 ins) — the §65g verdict was a wrong SIGNATURE
SESSION-17 filed this as §65g-class: "not 'run one more tool', but 'needs a transform that does
not exist yet'". Refuted. It needed the correct self-declaration.

- The TU expands DEFINE_func_80174C80() carrying `extern s32 func_80174CB0(s32, s32);`, while all
  ~100 prior drafts defined `void func_80174CB0(s32, s16)` — matches perfectly STANDALONE, dies in
  the real TU with `conflicting types`. Defining it `s32 (s32, s32)` and recovering param_2's
  s16-ness with an explicit (s16) cast at the func_80012558 use site is byte-identical.
- Drafted by an isolated agent (Opus 5 @ High, 65k tok) pointed at the NAMED blocker with the
  canonical callee sigs supplied — not asked to re-derive the C. It self-verified through the real
  cpp->cc1->maspsx->as chain (cc1 rc=0, 123/123 ins, 0 diffs) before reporting, so the bank was
  first-try clean.
- make check BINARY=ov_SC07_006 BYTE-IDENTICAL (7ca772be); R22 clean-fleet 140/140, 0 failed.
- Propagation ×138 follows as a separate targeted step (§55b: bank -> commit -> dedup_propagate --addr).
- FOLLOW-UP LOGGED: the recovery ladder also relaxed `extern s32 func_80174CB0(s32,s32)` -> `()` in
  src/shared/engine_core.h (+2 overlay files), escalating a binary-local bank to FLEET tier. The
  banked def AGREES with the original prototype, so that edit looks unnecessary — to be tested.
2026-07-24 23:43:15 -06:00
Drew T 16089c7659 docs(phase-29): wave batch 1 — sig-targeted drafting works (MATCH in 55s/32k); blocker walked to the §30#2 macro-widen 2026-07-24 23:38:41 -06:00
Drew T c937f494c6 docs(phase-29): qualify §66d-4 — profile diversity is a lottery ticket (0-for-1 on func_80140958) 2026-07-24 22:06:56 -06:00
Drew T 8399599dba docs(phase-29): func_8014D820 close=9 is a 3-profile MEASURED floor; backlog updated 25->9 2026-07-24 21:50:30 -06:00
Drew T 686aec359c docs(phase-29): cookbook §66d-5 — 'structural' is not a permuter veto (measured counterexample) 2026-07-24 21:46:40 -06:00
Drew T edc9ae92e1 docs(phase-29): §66d-4 — measured, a REPEATED profile yields nothing (lever is profile diversity) 2026-07-24 21:41:29 -06:00
Drew T 16cfc33839 docs(phase-29): cookbook §66d-4 — amend the 'permuter floor' rule (profile-relative, not absolute) 2026-07-24 21:41:02 -06:00
Drew T e9f27c0987 docs(phase-29): correct §67 — the a2 $7 pin is still load-bearing, not pin-free 2026-07-24 21:39:12 -06:00
Drew T b5a5186361 docs(phase-29): §67 — stale pins are dead weight; the func_8014D820 seed is now pin-free 2026-07-24 21:39:01 -06:00
Drew T b8e7250c78 feat(phase-29): tools/symcheck.py — the pre-gate symbol-set guard (§67a)
Builds the guard SESSION-17 left as a TODO after the func_801463A0 `_s`-alias trap, where a draft
invented extern aliases no symbol table defines, read MATCH under rtu_match, and could never bank.

- diffs the symbols a draft's object references (reloc records) against the target .s's
  %hi/%lo/jal set; reports MISSING (invented-alias signature) and INVENTED separately.
- fills a real hole: match_one/masked_diff compare relocation-MASKED words (object-vs-.s is
  symbol-agnostic BY CONSTRUCTION) and rtu_match COMPILES WITHOUT LINKING -- so both are
  structurally blind to this class. R34: a second oracle that can disagree with the first.
- NEGATIVE-CONTROL PROVEN: with one data extern renamed to an invented alias, match_one reports
  the SAME 14 mismatched as the correct draft; symcheck exits 1 naming both symbols.
- --c compiles via match_one so the pinned triple/flags can never drift (R33); or --obj.
- applied to the live func_8014D820 close=14 draft: 12/12 symbols agree, so a match there will
  link cleanly -- the §65c class is ruled out for it in advance.
- cookbook §67a + SETUP tooling-inventory row (R21). Necessary condition, NOT a match oracle:
  still finish on the whole-binary byte-gate (G3/P9).
2026-07-24 21:30:08 -06:00
Drew T 34417179df docs(phase-29): func_8014D820 25->14 by reading — the §67 arg-copy PLACEMENT lever
- PROBE ANSWERED (the SESSION-17 open item): a0's first use is body-line 41, a1's is 28
  -> use order ALREADY matched the target's birth order while birth order was inverted.
  The §31 RC-1/RC-2/RC-3 first-use-order hypothesis is REFUTED for this class; decl order
  is inert too. Both retired, do not re-buy.
- ROOT CAUSE (byte-read): gcc schedules the arg->pseudo entry copies as ordinary in-block
  insns and hoists an unconstrained one to the earliest slot. Mine raced `move $s4,$a0` to
  idx 2, which freed $a0 to become the early load temp (target: $v1) and left the target's
  idx-12 load-delay slot unfilled. The "wrong temp reg", the mirrored `sw $sN`/`move $sN`
  prologue and the +1 instruction were ONE defect in three costumes.
- THE LEVER (cookbook §67, written in-session per R30): an UNPINNED launder
  `__asm__ __volatile__("" : "=r"(pv) : "0"(p));` placed at the statement where the target's
  copy lands, later uses rewritten to pv. Zero instructions. Prerequisite: collapse redundant
  pointer aliases first (the two-pseudo split made gcc serve the first use from the incoming
  arg reg). Placement is the knob and is NOT linear -- sweep 3-4 anchors (3-statement plateau).
- 25 -> 16 by reading; permuter_ils (REGALLOC, 10x180s) 16 -> 14 in cycle 1 then x9 unchanged
  (§66d-3: a repeat means stop). Its edit is semantics-preserving (hoists desc.y+0x10) and
  cleared the idx 271/272 cluster. Seeds tracked: s18_func_8014D820_close{16,14}.c.
- MEASURED NEGATIVES recorded so they are never re-bought: pinning the laundered var to $s4
  (pre-stages via $t0, 305 ins); pinning the reused temp t to $3 (287/303); an artificial
  "r"(t) dependency (inert -- gcc still hoists); laundering after the beqz (305); dropping the
  a2 pin (29); wholesale pos/desc reorder or sinking z0=ent->z (+1 ins).
- NOT banked (G3) -- residual 14 in 2 clusters: idx 21/22 scratch $v1 vs $a0, idx 84-98 the
  desc.y/currentLocationId schedule. SCHEDULE-weighted ILS running from the close=14 seed.
- Also measured: func_80140958 260/260 54 - func_80176734 371/371 56 - func_80176218 328 vs
  327, whose +1 is NOT §67 (it hoists a global address into an extra callee-saved $s6 that the
  target rematerializes -> the §17 array-decay lever).
2026-07-24 21:27:14 -06:00
Drew T 25a02d6940 feat(phase-29): propagate 2 integration banks ×138 — fleet 79.7 -> 79.9% instr, R22 140/140
- func_8012B4B8 (84) + func_80169228 (105) propagated via targeted --addr (--check-only first,
  never --auto-from): 138 overlays byte-identical, 2 new dedup groups, ~+26,082 ins.
- R22 clean-fleet: check-all 140 passed, 0 failed of 140. Fleet fn-count 88.90 -> 88.98%.
- The 3 non-banks are diagnosed, not guessed (blocker_probe, both oracles agree): func_801463A0 is
  a real-cc1 MATCH in its own TU that the gate still rejects (§65c rtu-vs-gate divergence, link-level);
  func_80156670/func_80174CB0 carry "drop when banking" typedefs textually identical to the canonical
  ones. Blockers STACK — stripping the cc1-named typedef exposed the next (S8->B8; MATRIX->a callee
  conflict). Remedy named: strip ALL shared-provided typedefs, then run the DRIVER's ladder.
2026-07-24 20:01:31 -06:00
Drew T 1d225747ba feat(phase-29): 2 stranded reach-138 drafts banked from the refreshed spine — R22 140/140
- Ladder-only recovery (no demacroize, so these are NORMAL banks that can propagate x138):
  func_8012B4B8 (84 ins) + func_80169228 (105 ins), both confirmed gone from src, not read off
  the report (§55b trap 4). 2 of 5 candidates.
- DRIFT-CHECK EARNED ITS KEEP (R14): the backlog's close=0 was wrong for 2 of the 7 spine entries —
  func_8012CC88's draft is for ov_SC07_006 and is 13 off in ov_SC01_077 (the documented
  'backlog drafts are overlay-specific' caveat, now confirmed), func_80158638 is 2 off, not 0.
- The cross-file churn is gate_stage's own fix_arity_callers --any-proto pass on the banked fns'
  caller decls (byte-neutral no-proto widening; comments preserved, H5). R22 clean-fleet 140/140.
- Diagnosed the 3 non-banks with blocker_probe (both oracles agree 3/3): func_801463A0 = real-cc1
  MATCH in its own TU yet gate-rejected (the §65c rtu-vs-gate divergence); func_80156670 and
  func_80174CB0 = local_type collisions on 'S8' and 'MATRIX' -> uniquify (T0, draft-only).
2026-07-24 19:52:58 -06:00
Drew T 1004668405 chore(phase-29): regenerate the fuel manifest + worklist — the decision spine was 9 days stale
- Stale spine claimed 223 live stubs / 870,668 ins and ranked 3 already-banked fns in its top 7
  (func_801325B8, func_8014ADE0, func_8012CC88-in-077 verified 0-live in src).
- TRUE state: 160 live stubs / 583,077 ins remaining gain.
- SHARP EDGE (R35): worklist.py --assert-partition exits at the assertion and does NOT rewrite the
  doc, so 'regenerating' with it leaves the stale file in place and still exits 0. Run it bare to write.
2026-07-24 19:38:31 -06:00
Drew T ff19fdec5e docs(cookbook): §66d-3 — read the ILS per-cycle series, not its final best 2026-07-24 17:18:09 -06:00
Drew T e6354ae82d docs(cookbook): §66d correction — [structural] is a hint, not a veto
func_80177940 was structural(OPCODE-MIXED) at close=5 and the permuter still took it 5->1: the class
names only the DOMINANT residual. Policy: at low closeness run the search anyway (CPU, not tokens);
at high closeness read first.
2026-07-24 16:45:55 -06:00
Drew T cfa421eef2 docs(cookbook): §66d — the permuter/reader loop, and what transfers between giants
- The two halves of a 'not steerable from source order' note belong to different tools: the permuter
  closes INSN_LUID scheduler ties a hand sweep provably cannot enumerate; the reader closes semantic
  fixes the mutation set cannot invent. residual_class's bucket ([permuter] vs [structural]), already
  printed by match_one, is the free handoff signal; its profile feeds p16_permute --klass verbatim.
- Diagnose from a byte-verified SIBLING, and test the naive reading first: deleting the redundant mask
  alone COLLAPSED the copy (100 vs 101 ins), which is what proved a distinct PINNED register was needed.
- §66d-1: the LOOP transfers between giants, the PIN does not (the same move cost func_8014D820
  285 mismatched). §66d-2: setup() wipes the scratch dir; the cleanup pkill was global.
2026-07-24 16:42:20 -06:00
Drew T 32de37fff4 feat(phase-29): propagate func_80177940 x137 — 138 overlays byte-identical, R22 140/140
- Targeted `dedup_propagate --addr 0x80177940 --recover` (NEVER --auto-from; --check-only first
  confirmed the plan held exactly this one address, so the de-macroize hazard could not apply).
- 138 overlays rebuilt byte-identical; 0 stubs remain for the address; 1 new dedup group registered.
- R22 clean-fleet: check-all 140 passed, 0 failed of 140.
- Fleet: fn-count 88.86 -> 88.90%, instr-weighted 79.6 -> 79.7% (+13,938 ins = 101 x 138),
  distinct-code 64,874 -> 64,875 unique fns.
2026-07-24 16:41:44 -06:00
Drew T 465f73ad8b docs(cookbook): §66c — verify wave FUEL before a wave; an attempted-set from the wrong dir lies both ways
The exclusion set built from the backlog alone missed .run/giants/ (false work: ~2.6M tokens of
characterized permuter-only drafts would have been re-bought); corrected to scan .run/**/func_*.c it
swept in the Ghidra-C INPUT cache (false exhaustion: 5,488 phantom attempts). Records the query that
actually answers 'is there fuel' and the structural point that high-reach fuel is CREATED by a
per-overlay Ghidra-C prefetch, not found.
2026-07-24 15:40:08 -06:00
Drew T ffca2e4803 feat(phase-29): T16.10 — the driver's SUCCESS path verified (free re-bank test); 2 defects fixed
- THE FREE TEST (cookbook §66): reverted func_801778A8's bank to its INCLUDE_ASM stub (stub state
  rebuilds BYTE-IDENTICAL 7ca772be — a faithful revert proves itself; needs `make extract` first,
  the R22 corollary) and re-banked it THROUGH recover_integration.py --commit --r22.
  pass1 1/1 -> exact restore -> pass2 1/1 -> commit commit:0928 -> R22 140/140 -> report.json.
  Bank confirmed from SOURCE (stub gone), never the report (§55b trap 4). EQUIVALENCE: git diff vs
  the pre-revert commit = ONE blank line (mine) -> the driver reproduced SESSION-16's state exactly.
- DEFECT 1 (SAFETY, found by reading before firing): PROPAGATION is a fleet-tier write
  (dedup_propagate --auto-from -> src/shared/engine_core.h + up to 138 overlay .c) that was both
  UNDECLARED and the DEFAULT, so --max-tier binary still permitted the widest write in the toolchain.
  assert_write_set cannot catch it (it runs before the gate; under --commit git status is clean).
  FIXED up front: propagate now requires --max-tier fleet AND --r22, and is REFUSED after a
  demacroize stage (those banks are x1 by construction; --auto-from would re-macroize and undo them).
  Both refusals negative-control-tested, exit 1. The "standing hazard" is now a refusal.
- DEFECT 2 (METRIC): gate_stage scraped the fleet % via a progress.py label that no longer exists ->
  fp=None -> 50 gate commits recorded "fleet None%". Now reads FLEET instr-weighted (legacy fallback
  + loud stderr warning if neither matches); parses 79.6.
- STALE DIGEST (R14): docs/progress.fleet.md at HEAD disagreed with HEAD's own source by 45 in the
  dedup-shared column — generated during the §65g local_type trial whose edits were then reverted.
  Regenerated (reproduced identically in-gate + standalone); headline %s unaffected.
- cookbook §66/§66a/§66b distilled in-session (R30); SETUP.md gains the missing recover_integration
  row (R21 debt). tools-health OK: corpus 0/0, cdecl green, audit-binaries 140 citizens, lint OK,
  dedup-check 1879/0. Fleet unchanged 79.6% instr / 67.7% distinct / 88.86% fn-count.
2026-07-24 15:33:25 -06:00
Drew T 1b9ffe1fbb docs(phase-29): T16.9 — the local_type class does NOT recover either (0/4, reverted); §65f/§65g distilled
- 0 of 4 banked; reverted; make check BYTE-IDENTICAL; nothing landed.
- Ordering bug found+fixed: uniquifying the draft's type also renames it inside the draft's own
  `extern <T> D_x;` decls, trading `redefinition of struct T` for `conflicting types for D_x`. With
  uniquify moved BEFORE the reconcile one compiles -- and then DIFFs 48/53, because the data
  reconcile's cast-at-use changes real codegen when the body depends on its own struct layout.
- func_8014C4AC: rtu MATCH but the gate returned a REAL final SHA != locked, i.e. the de-macroize edit
  itself shifted a macro's OWN already-matched function. The §63 failure mode relocated somewhere the
  per-binary gate catches it for free. MEASURED BOUNDARY: de-macroize is byte-neutral 14 of 15.
- Rule recorded: read the FINAL SHA, not the verified count -- `None` = no image (compile/link break),
  a real hash != locked = the TU edit moved bytes. Different faults, different fixes.
- Two consecutive honest negatives (T8, T9): the EXISTING transforms stop at 14/36 (39%). §65f/§65g so
  the next session does not re-buy this.
2026-07-24 14:52:28 -06:00
Drew T 8d198a33c0 chore(phase-29): regenerated digests after the SESSION-16 recovery batch 2026-07-24 14:40:34 -06:00
Drew T f1f6238251 feat(phase-29): T16.6/T16.7 — 14th bank via the generalized de-macroize; §65 distilled; R21 inventory debt cleared
- 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.
2026-07-24 14:25:28 -06:00
Drew T 732128b1f4 feat(phase-29): T16.5 — 13 stranded reach-138 drafts recovered and banked via the per-overlay de-macroize (x1)
Every real-TU rtu_match MATCH converted to a whole-binary bank: 13/13, 0 failed.

- BANKED (all BYTE-IDENTICAL, whole-binary gate, stub-gone confirmed by grep not by report):
  func_8012CC88 func_80138DE0 func_80144B14 func_80146750 func_80147364 func_8014CF04
  func_8014D12C func_8014D610 func_80161374 func_8016163C func_80161774 func_80161888 func_801778A8
- Mechanism: existing draft-side transforms (cast_call_sites + reconcile_tu) then tools/demacroize.py
  expands the conflicting DEFINE_func_* instantiations in the overlay's OWN TU with the self-decl
  corrected to the draft's byte-true signature. Writes confined to src/ov_SC07_006/**.
- R22 clean-fleet after the batch: 140 passed, 0 failed of 140. Write-set asserted T1 (3 TU files).
- METRICS, honest: distinct-code 64,860 -> 64,873 unique fns (+13) -- the FULL credit, since
  progress.py marks an h_exact class matched if ANY instance is. instr-weighted 79.6% and fn-count
  88.86% are ~flat, because a de-macroized bank is x1 and cannot propagate x138. That price was
  stated before the work, not after it.
- dedup-check 1879 validated / 0 failed; 0 NON_MATCHING in any default build (G4).
2026-07-24 14:17:20 -06:00
Drew T ef85803b1f feat(phase-29): backlog prune — compact the append-only near-miss log + wire into make report
The near-miss ledger (.run/backlog.jsonl) is append-only, so it filled with already-banked noise:
6,867 rows, ~98% banked. load_best()/render() already filtered on READ (docs/backlog.md was correct),
but the raw log drifted stale and every render re-scanned all 6,867 rows against the stub oracle.

- backlog.py: new `prune` subcommand — atomic rewrite (temp + os.replace) to load_best()'s output
  (drop-now-matched P9 + best-per-addr collapse). Idempotent. 6,867 -> 1,704 open near-misses.
- Makefile: `backlog.py prune` wired into `make report` (BINARY=main block) so the ledger tracks
  reality every cycle instead of drifting.
- Finding (Drew's question): crack waves DO log every non-byte-match to the backlog durably
  (gate_stage copies best_draft -> .run/backlog_drafts/). BUT the `closeness` field is UNRELIABLE —
  byte-correct drafts (match_one MATCH) are logged with closeness>0 (e.g. func_8012F49C logged 29,
  actually MATCH). And a reach-N function's draft is overlay-SPECIFIC (per-location symbols), so the
  backlog is a messy recovery source vs the fresh per-wave stranded drafts. Integration-recovery
  should consume the fresh wave-dir strandeds, not re-derive from the backlog.
2026-07-24 11:36:54 -06:00
Drew T bf307f2827 feat(phase-29): s15 propagation (5 cores ×138) + crack-wave efficiency audit
- 5 of the 6 s15 fresh cores propagated ×138 (func_801483E8/8014680C/8017129C/80177AD4/801759D8;
  func_8014A51C §20-capped). R22 clean-fleet 140/140. fn-count 88.66->88.86%, instr 79.4->79.6%,
  distinct-code count 64854->64860, dedup 1879/0.
- EFFICIENCY AUDIT (decision-log): the 2 LLM waves ran 92% match_one MATCH but only ~27% whole-binary
  bank; 6 spot-checked non-banks are ALL match_one MATCH (byte-correct bodies). NOT a missing idiom —
  an INTEGRATION wall (def-side sig / data-extern / unshared struct). We strand ~16 paid-for correct
  functions per wave; a fleet-safe integration-recovery pass would ~3.7× yield for 0 new drafting
  tokens. Next investment = integration tooling, not more drafting. Waves held per Drew.
2026-07-24 11:17:05 -06:00
Drew T f1fd8993bf feat(phase-29): permuter overnight harvest — 29 fresh cores banked + distinct-code 64837->64854
The grinder ran the targeted permuter sweep to EXHAUSTION (all 75 permuter-shaped candidates;
correctly skipped 1575 redraft/structural/integration). It banked 29 distinct functions autonomously
(gate_stage commit=True, byte-gated, fail-closed, §55b un-propagated), 39% conversion.

- All 29 are LOW-REACH (1-5) overlay-unique code in the 0x8017-0x8018 range — confirming the map's
  finding that the permuter-admissible set is the low-leverage tail (the high-reach near-misses like
  func_8014F3E8 close=1 reach=134 are redraft/structural, NOT permuter-shaped).
- Propagation of the 22 reach>1 banks filled only 1 (0x80180710 ×2); the rest are genuinely
  overlay-unique (siblings byte-diverge) — as predicted.
- R22 clean-fleet 140/140 (the 27 overnight per-binary-gated commits verified fleet-wide, §61).
- distinct-code 64837 -> 64854 (+17 unique fns); session total +22 unique (wave +5, permuter +17) —
  the first real distinct-code progress in many sessions. instr 79.4%, fn-count 88.66%, dedup 1874/0.
2026-07-24 09:39:07 -06:00
Drew T af8ec58288 docs(phase-29): grinder overnight harvest — backlog/progress digests 2026-07-24 09:28:26 -06:00
Drew T daba4bd5b4 docs(phase-29): wave s14 close — 6 fresh cores (first distinct-code gain); §63 fix_header_decl is fleet-blind (recovery pass reverted, byte-gate saved it) 2026-07-23 23:10:00 -06:00
Drew T 22af9ab2c5 feat(phase-29): 3 Vec8-freed cores ×138, R22 140/140 — and the honest ROI verdict on the cap
- 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.
2026-07-23 21:25:39 -06:00
Drew T f9ad13e031 docs(phase-29): record the types-first verdict for the PhaseEnd (byte-neutral for matching; the win is a naming convention) 2026-07-23 21:21:36 -06:00
Drew T 43041f7fa9 docs(phase-29): SESSION-14 final checkpoint + burn-down session-close (+0.60pp instr) 2026-07-23 20:52:37 -06:00
Drew T e393c320e6 feat(phase-29): VARIANT camps -> UNIQUIFY (not reconcile); validated on Buf, R22 140/140 (§64a)
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).
2026-07-23 20:51:42 -06:00
Drew T 3642b5458a feat(phase-29): the type-lift's payoff — 13 cores propagated ×138, −831 stubs, R22 140/140
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).
2026-07-23 20:18:50 -06:00
Drew T 5ab80517de feat(phase-29): broad §20 type-lift lands — 154 types fleet-wide, R22 140/140 (§64)
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.
2026-07-23 19:54:19 -06:00
Drew T f62d3bcf37 feat(phase-29): lift_types.py topo-sort (dep ordering) + broad-lift finding (needs collision-vet + -O0 strip precision; clean 2-type lift stands) 2026-07-23 18:38:41 -06:00
Drew T 0eb22e10ae docs(phase-29): SESSION-13 type-lift addendum — §20 cap partially cracked (+276), lift_types.py doctrine; fleet 79.0% instr 2026-07-23 18:19:41 -06:00
Drew T b3597c08e0 feat(phase-29): 2 §20-unblocked cores propagated x138 (+276) via the type-lift
func_8012B4B8 + func_8012E138 — freed by the Mat32/Cam8012E138 fleet lift
(commit:0859) — propagated x138 (live 138->0 each, +276 stubs). R22 clean-fleet
140/140. No --recover needed (clean h_exact).

decision-log: the §20 type-lift is safely executable when SCOPED to clean types
(lift_types.py + R22); classify-first, lift the 1-def/copy-only-variant types now,
defer the fleet-split variants (MATRIX/Vec8/Buf/M8) to a per-camp reconcile pass.
2026-07-23 18:04:44 -06:00
Drew T b48455d586 docs(phase-29): §20 type-lift is a fleet-wide collision-resolution op, not a tool-run (R32/R35 — 2 broken-instrument catches); concrete plan for a dedicated pass 2026-07-23 17:39:29 -06:00
Drew T 09bc2c7b72 docs(phase-29): SESSION-13 CHECKPOINT — 15 reach-138 cores banked + 2×138; integration-wall finding + build_engine_types as next lever; fleet 78.9% instr 2026-07-23 17:17:18 -06:00
Drew T 1dd80e9287 feat(phase-29): ov_SC07_006 fresh-138 — 2 cores propagated x138 (+274) + integration-wall finding
Propagation of the 7 fresh-138 cores banked in commit:0855. Only the 2 self-contained
ones cleared all three integration walls:
- func_80130C08 x138, func_80137178 x138 (+274 stubs). R22 clean-fleet 140/140.

The other 5 are blocked, each by a different integration wall (drafting was solved —
all 7 bodies byte-matched; INTEGRATION is the bottleneck):
- func_8012B4B8/func_80175308/func_8012E138/func_8012A1BC: §20 local-type
  propagation cap ("not self-contained") — need build_engine_types type-lift to
  propagate x138 (roadmap B4; ~+552 stubs when unblocked). Stay x1.
- func_80169228: per-member divergence (whole SC03 cluster byte-diverges) — a
  genuine partial family; --recover thrashes it (killed + reverted). Stays x1.

decision-log: fix_header_decl fragility correction (shared multi-caller decls break;
gate_stage's call-site-cast is the integration spine, not header-decl rewriting).
2026-07-23 17:07:29 -06:00
Drew T 3c8fd8a0b0 feat(phase-29): ov_SC07_006 fresh-138 wave — 7 x1 core banks (gate_stage reconcile)
Crack wave w9lidyi5b (24 fresh LIVE=138 families): 20 self-assessed MATCH, 3 near.
Banked x1 (R22 clean-fleet 140/140):
- 2 self-contained via plain harvest_verify: func_8012B4B8 (§52b-wall crack),
  func_80169228.
- 5 via gate_stage's reconcile ladder (cast_call_sites in the draft's own TU):
  func_80175308, func_8012E138, func_80130C08, func_8012A1BC, func_80137178.

Correction (decision-log follow-up): fix_header_decl v1/v2 is FRAGILE for shared
multi-caller decls — rewriting an engine_core.h decl breaks callers that use the
return differently (CC1-FAIL). func_8014CD80 was a lucky single-caller/ignored-return
case. gate_stage's call-site-cast is the right tool for multi-caller plumbing (banked
5 where fix_header_decl broke the build). Remaining ~13 near/deeper-plumbing drafts
staged in .run/drafts-sc07006-fresh/. Propagation x138 next.
2026-07-23 13:55:29 -06:00
Drew T 3814de9817 docs(phase-29): SESSION-13 remaining-work re-derivation + roadmap deltas (B1 reversal, B7 behemoth correction, prefetch gap) 2026-07-23 13:27:55 -06:00