Commit Graph

773 Commits

Author SHA1 Message Date
Drew T d6194365a2 docs(phase-29): T16.8 — normalize_self_decls does NOT recover the self_decl_tu class as-is (reverted, honest negative)
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.
2026-07-24 14:40:05 -06:00
Drew T 9137d3b784 feat(phase-29): T16.4 — encode the recovery recipe in recover_integration.py (tiers ENFORCED, §55b trap 4 closed)
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.
2026-07-24 14:37:59 -06:00
Drew T f4f0706832 docs(phase-29): SESSION-16 checkpoint — integration-recovery measured (14 banks, ~2.3x not 3.7x); §20 DEF-conflict wall refuted per-overlay; next = the driver (T4) 2026-07-24 14:26:00 -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 09fb069cf2 feat(phase-29): T16.2 — GATE A passed on measured numbers; the §20 DEF-conflict doctrine refuted per-overlay; func_8012CC88 banked
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.
2026-07-24 14:11:58 -06:00
Drew T 1ea54fa594 feat(phase-29): T16.1 — the two-oracle blocker probe (read-only); rtu_match full-stderr + multi-line //@EDIT
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.
2026-07-24 14:01:57 -06:00
Drew T bb6268d9de docs(phase-29): SESSION-15 checkpoint — waves+permuter (+28 distinct-code), backlog pruned, efficiency audit; next = integration-recovery tool 2026-07-24 11:40:04 -06:00
Drew T be89c4536c docs(phase-29): remaining-work map + reach-based targeting (153 shared cores left, then a 9,084-fn unique tail); grinder running 2026-07-23 23:20:04 -06:00
Drew T e9c533b2dc docs(phase-29): SESSION-14 ultracode checkpoint — first distinct-code gain via fresh cracks; next = more waves 2026-07-23 23:10:39 -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 d1a1d756e0 fix(phase-29): PsyQ MATRIX name hazard — the true 32B layout now owns the canonical name (R22 140/140)
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.
2026-07-23 21:35:07 -06:00
Drew T 8223bfc3a4 docs(phase-29): reconcile the task checklist with the per-task log (4 stale boxes) + a truthful open-work header 2026-07-23 21:30:25 -06:00
Drew T 514e90d780 docs(phase-29): SESSION-14 closing checkpoint — cap gated de-duplication not coverage; next lever is fresh cracks 2026-07-23 21:26:09 -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 0d60e53db2 docs(phase-29): PsyQ primitive types — consistency done, correctness NOT (27 lookalikes; MATRIX name/layout hazard) 2026-07-23 21:24:14 -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 23b9b57505 feat(phase-29): uniquify+lift Vec8 camps + propagate 0x8012E778 ×138; blocked queue 10 -> 7
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.
2026-07-23 21:15:58 -06:00
Drew T 72b7a7227a feat(phase-29): uniquify+lift the MATRIX camps — 77 files renamed, 655 stripped, R22 140/140
- 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.
2026-07-23 21:05:35 -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 5c3a2bb69d docs(phase-29): SESSION-14 checkpoint — broad §20 lift + 13 cores ×138; fleet 79.3% instr 2026-07-23 20:19:25 -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 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 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 f8d8f13b98 feat(phase-29): fix_header_decl v2 (--reconcile-externs) + SESSION-13 cont checkpoint
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.
2026-07-23 12:42:43 -06:00
Drew T cbb52ebce1 feat(phase-29): fix_header_decl.py — automate the fresh-138 def-side header reconcile (§63)
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.
2026-07-23 12:15:49 -06:00
Drew T 7f18dbad2f feat(phase-29): func_8014CD80 x138 — the fresh-138 def-side blocker is RECOVERABLE (R35 reversal)
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.
2026-07-23 12:06:26 -06:00
Drew T 5760b39a1a docs(phase-29): SESSION-13 — diagnose the fresh-138 def-side blocker (header-decl reconcile is the missing tool) 2026-07-23 11:46:35 -06:00
Drew T 57ef4ebcb5 feat(phase-29): ov_SC07_006 reach-138 batch-1 propagation + live-count re-scope (SESSION-13)
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.
2026-07-23 11:43:28 -06:00
Drew T 14166b8c47 docs(phase-29): SESSION-12 CHECKPOINT — non-jtbl wave 64 instances + gate_stage arity-undo fix + jtbl §62; fleet 78.6% instr / 67.6% distinct 2026-07-22 22:58:13 -06:00
Drew T 0aae4b2ce5 docs(phase-29): checkpoint non-jtbl wave batch-1 + gate_stage arity-undo fix (resume aids for batch 2/3) 2026-07-22 21:48:59 -06:00
Drew T 3ebdd91fc6 feat(phase-29): jtbl post-carve reconcile (harvest_verify._jtbl_reconcile) + REFUTE the reach-138 jtbl families as plumbing wins
- 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).
2026-07-22 20:01:10 -06:00
Drew T 7e3a234985 docs(phase-29): SESSION-11 CHECKPOINT — fresh-exemplar sweep is family-specific (100/85/0% across 3), fleet 78.4->78.6% instr 2026-07-22 18:24:48 -06:00
Drew T f142a6858f feat(phase-29): ov_SC06_018 crack-wave — func_801365B8 x138 (fresh-exemplar sweep CONFIRMED), thesis is family-specific
- 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.
2026-07-22 18:12:09 -06:00
Drew T d53a33eb06 docs(phase-29): SESSION-10 CHECKPOINT — five tooling walls, the gate SHA bug, main in the denominators 2026-07-22 16:25:50 -06:00
Drew T 124ada384b docs(phase-29): zero-crack vein tapped (exemplar provenance is the discriminator); metrics contract met 2026-07-22 16:23:30 -06:00
Drew T b1d8c0cf39 docs(phase-29): zero-crack sweep track, revert fix, floor-verdict artifact corrected 2026-07-22 15:25:20 -06:00
Drew T a609f43338 docs(phase-29): Task-7 burn-down live (floor NOT yet determinable), zero-crack track, jtbl_family_bank revert defect 2026-07-22 14:45:59 -06:00
Drew T 8016c172f9 docs(phase-29): SESSION-9 CHECKPOINT — sweep 274 siblings, the PURE≠templatable finding, the tooling answer 2026-07-22 13:47:14 -06:00
Drew T 84fd6c785a docs(phase-29): the isolation-must-follow-the-splice finding, 5/11 cracks banked, and the retraction 2026-07-22 11:24:36 -06:00
Drew T 7529ee3d86 docs(phase-29): SESSION-8 CHECKPOINT — §61c refuted, the tree-eating undo fixed, family ×138 + a giant banked 2026-07-22 01:57:04 -06:00
Drew T 02b16fa7a7 refactor(phase-29): DELETE gate_stage's jtbl pre-pass (R33) + the honest ladder measurement
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)
2026-07-22 01:55:47 -06:00
Drew T 12a14410f9 fix(phase-29): §61c REFUTED — the jtbl bank IS clean-reproducible; func_80135A4C banked ×1
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
2026-07-22 00:40:26 -06:00
Drew T e1e77c7482 docs(phase-29): SESSION-7 CHECKPOINT — full fresh-session block (§61c is the single next task) 2026-07-22 00:12:04 -06:00
Drew T 0cf6356ffd docs(phase-29): jr_inventory was right; the clean-rebuild blocker stops jtbl banking 2026-07-21 23:51:38 -06:00
Drew T 86e262e844 docs(phase-29): jtbl-in-harvest_verify result + the jr_inventory ownership blocker 2026-07-21 22:13:50 -06:00
Drew T 96d1324acd feat(phase-29 T14 stage 4): jtbl isolate+carve stage built; the CARVE-MUST-FOLLOW-SPLICE law
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.
2026-07-21 21:07:50 -06:00
Drew T a7f3fce4cf feat(phase-29 T5 wave): 11/12 MATCH, 0 banked — three integration walls named + 12 cracks preserved
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.
2026-07-21 19:47:05 -06:00
Drew T be43af8b59 feat(phase-29 Task-5): Ghidra-C prefetch — scoped by measurement, one overlay imported (+101 exemplars)
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.
2026-07-21 18:41:04 -06:00