Commit Graph

733 Commits

Author SHA1 Message Date
Drew T e903713b71 feat(phase-30 S50): the mechanical A-prop draft — 256 members banked with no agent in the loop
Final S50 state: 307 instances banked, stubs 12,468 -> 12,161, fleet 95.3% instr / 90.0%
distinct / 96.65% fn-count. R22 clean rebuild 4x, check-all 213/213 every time.

- tools/aprop_autodraft.py + tools/draft_prechecks.py: seed body + symbol_map + a MINIMAL
  synthesized preamble. The seed's decl layer never travels — that layer is family_sweep's
  dominant failure (331 of 458 S49 verdicts). 256 banked at zero agent tokens, against the
  ~20M the same work would have cost as a wave.
- Macro seeds (567 of 1196 members, all 3737 de-macroize) take the DEFINITION only; the block
  stays the decl source. Pasting it whole measured 28% vs inline's 68% — func_8016AB6C's macro
  is 1,891 lines of which 108 are the function.
- IMM is a second engine, not a wall: T2a's imm_map_tier1 resolves a per-location LITERAL like
  symbol_map resolves a per-location SYMBOL. 131 of 275 IMM members resolve.
- draft_prechecks negative-controlled against ALL 205 banked drafts: zero false positives,
  catches 39 of 67 known failures. That control found two bugs in the checks themselves —
  C89 `f()` declares UNSPECIFIED parameters (not zero), and a member's own definition read as
  a call to itself. Conservative by design: a pre-check that discards good drafts is worse
  than one that lets a few builds fail.
- The A-prop pool is now priced exactly: PURE 437/37,376 ins, IMM 275/8,849, STRUCT 238/4,259.
- Cookbook §171a; SETUP rows; CURRENT_PHASE S50 FINAL checkpoint.
2026-08-14 07:42:19 -06:00
Drew T 895bb6a239 feat(phase-30 S50): clear the func_801EDC18 carry blocker — 4/4 banked, and re-priced
- The blocker was carried as "one missing file-scope extern gates 83 PURE members". Both
  halves were wrong (R14): corpus.stubs says 4 open members, and D_801ED98C is a DEFINED
  const Blk8 whose rodata lives inside the member's own nonmatchings .s — replacing the stub
  deletes the data with it. gather_externs can carry an extern DECL, never a DEFINITION,
  which is why it reported "no file-scope decl" for a symbol md_SC05_023 defines on line 114.
- Fix: paste typedef + const definition + body per sibling (data bytes verified identical
  across md_SC05_024/025/028/029). 4/4 banked.
- aprop_symfix: new `local-only` class — draft-DEFINED identifiers that merely carry a
  vram-looking suffix (Blk8_…, S8_…, L_call_…) are not stale symbols. Measured: that is every
  non-clean case in the whole wave-7a/7b stored-draft residue, which holds ZERO stale-symbol
  recoveries (a clean negative result — the defect was A-prop-specific).
- cookbook index regenerated (tools-health fails closed on a stale index — it caught §171).
- R22 clean rebuild: check-all 213 passed, 0 failed of 213. Stubs 12,445 -> 12,441.
2026-08-14 00:23:32 -06:00
Drew T 2f7e06564b feat(phase-30 S50): the stale seed symbol — A-prop's 57% was ours, not the lane's (§171)
- REFUTES §170's open hypothesis (batched cards concentrate members into one TU ⇒ §169
  collision): 5-draft groups banked 5/5; 11 of 35 unbanked drafts were already one-per-TU;
  and the two "concentrated" groups banked 12/12 and 10/10 once the real defect was fixed.
- The cause: a per-location data symbol carried out of the seed body unrebased. match_one
  compares instruction ENCODINGS and is blind to a relocation's target NAME, so it scores
  MATCH standalone and dies at link in the host TU. 24 of 24 concentrated failures, all 1:1
  rewritable at one constant vram delta (0x4128).
- tools/aprop_symfix.py: audit + --fix, emits a gate_lane-shaped slate; deterministic and
  build-free, so it runs BEFORE the gate. The R34 second oracle for the class match_one
  cannot see.
- family_cousins.py --aprop-cards: members now carry sym_map, the explicit {seed -> member}
  renames, read from the seed's C BODY (a matched seed has no .s of its own) vs the member's
  .s. Two case-mismatch defects fixed while wiring it (sig lowercase vs splat uppercase).
- 23/24 banked. Stubs 12,468 -> 12,445. Fleet 95.2% instr / 89.9% distinct / 96.57% fn.
  R22 clean rebuild: check-all 213 passed, 0 failed of 213. dedup 2,043/0.
- A-prop's true conversion is 87% (79/91); the 320 batched members are unblocked.
- Cookbook §171 + §170 struck in place; SETUP row; decision-log (R31).
2026-08-13 23:41:36 -06:00
Drew T bcc3130eb4 feat(phase-30 S49): the A-prop word-diff card + aprop_wave — 56 banked from the >=16 head (§170)
- NEW family_cousins.py --aprop-cards + tools/wave/aprop_wave.js: lane A (1,700 open fns /
  76,419 ins) had NO card type — cousin diffs are empty for h_seq-identical members, so the card
  is a positional WORD diff vs the matched sibling, grouped BY FAMILY (one agent, N drafts).
  Head cards: 13 families / 433 members, median TWO differing words each.
- calibration 9 batches / 108 members: 98 agent-MATCH (91%, best of any wave) -> 56 BANKED (57%),
  ~80k tok/banked fn vs 157k (cousin card) vs 400k+ (crack wave). R22 213/213 BYTE-IDENTICAL.
- HONEST GAP (R14): 91% agent -> 57% gate is the worst conversion measured; 14 groups banked 0.
  Hypothesis TESTABLE not proven — family batching concentrates members per destination TU, the
  §169 collision. Re-gate unbanked ONE PER TU before scaling the remaining 320.
- >=16 head diagnosed: 3 of 4 blockers are plumbing — the --band substantial default hid 5 of 13
  families from every prior sweep; one missing file-scope extern (D_801ED98C) gates 56 PURE
  members; dedup_extend is macro-only. Only func_8017C294 is a genuine crack.
- fleet 96.56% fn / 95.2% instr / 89.9% distinct; stubs 12,535 -> 12,468; dedup 2,043/0.
- cookbook §170.
2026-08-13 17:44:20 -06:00
Drew T 79b7ff2cbf chore(phase-30 S49): wave 7b — adapt lane scaled, 44 banked (92% MATCH->bank); the TU-spread law
- thresholds relaxed to <=6 blocks/<=16 tokens UNION edit-fraction <=0.20: cards 518 -> 721,
  MIXED 310 -> 50 skeletons; the 753-ins func_8017BEBC (0.987 sim) became reachable.
- 59 cards -> 48 agent-MATCH (81%) -> 44 BANKED (92% MATCH->bank, 75% end-to-end), 6.9M tok.
- FINDING (the actionable one): 7b's bank rate crushed 7a's because it SPREAD 48 drafts over 35
  destination TUs; 7a's failures were per-TU declaration collisions between sibling drafts.
  Cookbook §169 updated with the spread law.
- R22 213/213 BYTE-IDENTICAL from clean; fleet 96.55% fn / 95.2% instr / 89.9% distinct;
  stubs 12,584 -> 12,535; dedup 2,035/0.
- incidents 3 & 4 recorded: an agent wrote a TRACKED header (guard caught it, prose is not
  enforcement); my own gate_lane filtered on the wrong key and printed 'gating 0 drafts' as a
  result (R32 silent skip) — fixed with a coverage assertion that refuses to report 0.
2026-08-13 11:50:04 -06:00
Drew T 44b49ed715 chore(phase-30 S49): wave 7a checkpoint — micro-adapt lane measured (83% MATCH / 64% bank), §169
- pilot 30 cards -> 25 agent-MATCH (0 refuted) -> 16 banked; 29 instances banked tonight
  (89 incl. propagation); 2.7M tokens haiku-tier ~= 30k/banked instance vs a crack wave's ~75k.
- R22 213/213 BYTE-IDENTICAL from clean; fleet 96.53% fn / 95.1% instr / 89.8% distinct;
  stubs 12,613 -> 12,584; dedup 2,029/0.
- R14 CORRECTION: a banked cousin usually does NOT propagate (2 of 8; cousins are byte-variant).
  The card 'reach' column is cousin fuel, not dedup copies — priced wrong in my earlier framing.
- FINDING: the 9 gate failures are per-TU INTEGRATION (standalone-MATCH, host-TU-rejected),
  clustered 5+2 in two binaries — the reconcile-ladder class, not codegen.
- TWO INCIDENTS (mine): an outer timeout tighter than gate_stage's own scaled timeout killed a
  healthy 5-bank group mid-write AND orphaned its dedup_propagate child, which kept rewriting
  src/ through a git checkout. Killed, inspected, reverted; the same 5 drafts banked 5/5 untimed.
  Law: never wrap a self-timing tool in a tighter cap; kill process GROUPS, not pids.
- cookbook §169 (the lane + the three laws + the threshold sizing table).
2026-08-13 06:59:46 -06:00
Drew T dcba5d0f4f feat(phase-30 S49): the micro-adapt lane — adapt cards + adapt_wave.js (wave 7a)
- family_cousins.py --adapt-cards: per seeded-unit member, drift classified vs the seed
  (LI-ONLY 27 / SMALL-EDIT 491 / MIXED 310 excluded); cards carry the seed C location + the
  aligned diff blocks with the member's raw words + disasm (the new constant is readable in
  the card). 518 cards / 1,101 instances / 23,820 ins; 514 haiku-band.
- tools/wave/adapt_wave.js: the EDIT-contract wave (crack_wave contracts preserved: per-agent
  dirs, sha1-last, UNVERIFIED != refuted); symbol surface from the TARGET .s; haiku<=60/sonnet.
- regen chain absorbed the 48 lane-A banks (A-prop open ins -6,475 == the report's instr
  delta exactly — two independent derivations agree); pilot slate .run/wave7a_pilot.json (30).
- R37: pilot before scaling to the 518-card pool.
2026-08-12 22:03:04 -06:00
Drew T ea94fece6f chore(phase-30 S49): checkpoint — lane-A re-sweep 48 banked, R22 213/213, fresh honest ledger
- 48 lane-A members banked (30 non-jr family_sweep + 18 jr jtbl_family_bank); fleet
  96.53% fn / 95.1% instr / 89.8% distinct; stubs 12,661 -> 12,613; dedup 1,949/0.
- R37 probe: PLUMBING-retry 0/4 -> 4/4 on repaired instruments (pre-repair ledger partly
  fiction); bulk re-measure: 458 fresh verdicts, ~331 decl-agreement / 28 genuine DIFF /
  89 md typedef-gather; 264 STRUCT by design -> cousin fuel; 122 unresolved-IMM (T2a).
- named tool findings: reconcile 'syntax before *' defect (80189540 x4); §154-A fresh
  refusal message (20 md jr ledgered); family_sweep phase-26 commit tag; jtbl needs
  operator per-family commits (driver v2).
- next: wave 7 off the cousin slate (regen chain + ultracode toggle), or T5 close.
2026-08-12 21:30:51 -06:00
Drew T b3713cc3ca feat(phase-30 S49): the cousin tier — family_cousins.py similarity map + seeded wave-7 slate (§168)
- FINDING (Drew's smell, byte-verified): the '4,513 unique singletons' picture is substantially
  an h_seq exact-hash artifact — 86/120 near-pairs in the 0.85-0.99 band differ by PURE
  insertion/deletion (li-expansion tell in 25). Specimen: ov_SC06_010:0x8017bebc (753 ins,
  'singleton') is 0.987-similar to a MATCHED fn in the same binary.
- NEW tools/family_cousins.py: distinct open skeletons -> shingle index -> >=0.85 union-find ->
  matched-seed attachment -> .run/family_cousins.json + docs/family-cousins.md. R32 BOTH ways
  (independent stub recount fails loud on a stale map — negative-control-proven; partition
  assert). Reproduced the probe within +-1%; totals EXACT (11,627 inst / 584,448 ins).
- Unit table: A-prop 197u/68,729ins · seeded 418u/50,422 · cousin-multi 1,552u/249,799 ·
  cold 3,240u/215,498 — the genuinely-unique tail is 37% of the remainder, not 90%.
  Main's 'structurally barren' HOLDS at the similarity tier (94% mass <0.70).
- --targets wave slate: .run/wave7_targets.json = 40 targets / 33,304 unit ins (+33% vs
  family-ranked), 9 resolved seed C paths, size-routed 2 haiku/20 sonnet/18 opus.
- LAWS (§168): a cousin is a SEEDED CRACK never a remap; rank waves by UNIT weight; discount
  short-fn similarity. Byte-gate stays the sole arbiter (G3/P9).
- docs/family-hseq.md: this session's frontier regen (post-S48 propagations) rides along.
- cookbook §168 + SETUP inventory row (R16/R21/R30); CURRENT_PHASE S49 entry.
2026-08-12 20:53:40 -06:00
Drew T 57ff04c1ac docs(phase-30 S48): §167 — wave-5/6 harvest, and the saturation signal
27 note-sets, 197 claims, one skeptic each, against a cookbook already holding
§162-§166 from this campaign:

  NEW 5 · SHARPENS 43 · COVERED 126 · UNSOUND 23
  byte-probed 92 · single-instance 75 · asserted 30

COVERED+UNSOUND: 57% (§164) -> 64% (§165) -> 76% (here). The duplicate rate
rises monotonically as the base grows. FIVE genuinely new laws out of 197
claims is the signal that the idiom well for this class of function is
approaching dry — future waves should spend tokens on cracks, not on mining
notes for idioms, and harvest only what a skeptic grades byte-probed.

The skeptics ran their own A/Bs this round. Best example: a crack agent claimed
"the source STATEMENT BOUNDARY decides whether the scheduler hoists a
far-consumed load". The vetter built that spelling and got .text BYTE-IDENTICAL
to the inline form, then swept eight POSITIONS and got five distinct objects —
showing the lever is statement position (the already-banked INSN_LUID
tie-break), not the boundary. Plausible mechanism, refuted by measurement, true
lever named in its place.

46 entries banked as §167-01..46; §167z records the 23 refutations.
cookbook_index.py: 508 sections.
2026-08-12 18:55:05 -06:00
Drew T 0fc297184c fix(phase-30 S48): §166a — strike the causal claim I did not verify (R14)
I banked the crack agent's story that a wrong-TU citation CAUSED
func_8017F2D4's seven gate refusals, and relayed it to Drew, without checking
it. corpus.stubs() derives each stub's TU from the actual INCLUDE_ASM site and
gate_stage splices via corpus — the harness was always editing the right file.
Only the PROSE was wrong.

Measured: func_8017F2D4 is still a stub, still classifies DIFF, and is a
has_mid_jr function referencing jtbl_801CC504 — so it carries a jump table the
standalone gate cannot see. The real residual is CAUSE NOT DETERMINED.

The ORACLE stands on its own evidence (the asm subdir's third component IS the
TU stem, by construction from the split config). The causal story does not, and
is now marked as such. This entry was written to stop a tool printing an
unmeasured cause and its first draft printed one.
2026-08-12 18:34:40 -06:00
Drew T 4144eabc74 chore(phase-30 S48): checkpoint — 684 banked (13,345 -> 12,661), R22 213/213
Wave 6 added 110 (24 cracks + 23/24 families propagated). Fleet 95.1% instr /
89.7% distinct / 96.51% fn-count. R22 clean-fleet run 9x this session, 213/213
every time. Bank rate across six waves: 67/79/69/68/73/60%.

Records §166a (the destination-TU oracle) and the four-instance pattern it
completes: a tool asserting a conclusion it never reached. A confident wrong
label costs more than a missing one.
2026-08-12 18:31:30 -06:00
Drew T 80f3ee7397 fix(phase-30 S48): §166 — the destination-TU oracle, and stop printing a guess as a finding
gate_stage labelled every "standalone MATCH / whole-binary DIFF" with
"(declaration/TU plumbing)". The tool never checked for a declaration conflict —
that was a GUESS printed as a diagnosis, and func_8017F2D4 carried it through
SEVEN attempts across five waves while every agent hunted codegen. The body was
byte-correct from the first attempt; the notes had simply named the wrong
destination TU (a file holding only a caller + prototype), and splicing there is
a no-op that leaves the INCLUDE_ASM bytes in place.

- gate_stage now says only what is true (the two oracles disagree) and hands
  over the check that resolves it, instead of naming a cause it did not measure.
- §166a banks the oracle: asm/<ov>/nonmatchings/<TU_stem>/<fn>.s => the
  INCLUDE_ASM is in src/<ov>/<TU_stem>.c. The third path component IS the TU
  stem, derived from the split config, and it beats any prose citation — a grep
  for the function name also hits callers and prototypes in OTHER TUs and reads
  exactly like a destination hit.
- Plus the two probe gotchas that cost wave-5/6 agents real time: the wrong
  --aspsx-version fakes ~32 ori-vs-addiu mismatches, and a collateral-drift
  check must filter to sized symbols (nm -S) or the zero-size .NON_MATCHING
  aliases all report false drift.

cookbook_index.py: 506 sections.
2026-08-12 18:14:21 -06:00
Drew T 4181b865f2 chore(phase-30 S48): checkpoint — 574 banked, FLEET CROSSED 95% instr, R22 213/213
Wave 5 added 152 (29 cracks + 28/29 families propagated) — the session's
largest. Fleet 95.0% instr / 89.6% distinct / 96.48% fn-count; stubs
13,345 -> 12,771. R22 clean-fleet run 8x this session, 213/213 every time.

P30's milestone is '>=95% instr fleet, or every remaining overlay stub on a
named ledger'. THE FIRST HALF IS NOW MET — T5 (phase close) is a live option.

Bank rate across five waves: 67% -> 79% -> 69% -> 68% -> 73%.
2026-08-12 16:23:37 -06:00
Drew T a2362e6711 docs(phase-30 S48): §165 — wave-4 harvest banked the same day the wave landed
19 note-sets, 131 claims, one skeptic each, vetted against a cookbook that
already held §162/§163/§164 from this same campaign:

  NEW 8 · SHARPENS 39 · COVERED 64 · UNSOUND 20
  byte-probed 61 · single-instance 43 · asserted 27

COVERED+UNSOUND is 64%, up from §164's 57% — the duplicate rate RISES as the
knowledge base grows. That is the argument for harvesting after EVERY wave: a
wave launched before its predecessor's harvest lands re-derives laws already on
disk. This one was banked while wave-4 propagation was still committing.

THE PASS CORRECTED ITS OWN PREDECESSOR. §165-01 BOUNDS §163a, banked hours
earlier today. §163a says "block scope is a conflict SOLVENT" — byte-proven,
but on a DATA symbol. It does NOT reach an ARITY conflict: there the two decls
are COMPATIBLE (cc1 emits no `conflicting types` for scope to downgrade) and
the failure is call-vs-composite in convert_arguments (c-typeck.c:1623), which
a `()` declaration cannot defuse at ANY scope. The diagnostic word picks the
lever: `conflicting types` -> §163a's solvent; `too many arguments` -> cast the
call site (§17a-1/§161c) or replace the host prototype.

§165z records the 20 refuted claims. cookbook_index.py: 505 sections.
2026-08-12 13:21:58 -06:00
Drew T 19a138c318 chore(phase-30 S48): checkpoint — 422 banked (13,345 -> 12,923), R22 213/213
Wave 4 added 105 (27 cracks + 27/27 families propagated). Fleet 94.9% instr /
89.4% distinct / 96.44% fn-count. R22 clean-fleet run 7x this session, 213/213
every time.

Bank rate now measured four times: 67% -> 79% -> 69% -> 68%. Prior-notes
seeding 10/12 (was 7/9). func_8017C294 — the x16 family, largest item on the
board — is NEAR at 2 ins after three seeded attempts (18 -> 11 -> 2).

Also records the 4th comment-blindness defect and its blast radius (one draft
comment refused a binary's stub oracle, failed 5 later binaries, and left
drafts spliced in src/ so 17 re-gates read a poisoned tree as 0/17), and that
the wave harness now lives in tools/wave/ with its contracts written down.
2026-08-12 13:05:21 -06:00
Drew T 137a8540b5 docs(phase-30 S48): §164 — 190 claims vetted by 34 skeptics, 82 banked, 28 refuted
The §163z catalogue was 34 crack-agent note-sets claiming 190 distinct laws.
One independent skeptic per function, each required to read the full notes,
grep the whole cookbook, classify, and GRADE THE EVIDENCE:

  NEW 20 · SHARPENS 62 · COVERED 80 · UNSOUND 28
  byte-probed 114 · single-instance 51 · asserted 25

57% of what the crack agents flagged as novel was already in the cookbook or
does not survive scrutiny. That ratio is the lesson: a crack agent is the right
instrument for FINDING a lever and the wrong one for judging its novelty — it
has just spent hours in one function and has not read the other 497 sections.
Never bank a wave's flags directly.

Banked as §164-01..82, each carrying its verdict, what it sharpens, and its
evidence grade (70 byte-probed, 12 single-instance). Several skeptics CORRECTED
the mechanism the crack agent proposed while confirming its effect — e.g. the
"fold distributes the constant out of an index" claim, where the skeptic traced
the real site to expand_expr's MULT_EXPR EXPAND_SUM case (expr.c:5359-5375)
after showing pointer_int_sum's distributive law cannot fire on that tree.

§164z records the 28 REFUTED claims with the reason, so no future wave spends
tokens rediscovering them.

cookbook_index.py: 501 sections.
2026-08-12 10:40:28 -06:00
Drew T 57cef6325a docs(phase-30 S48): §163 — the five vetted laws from waves 2-3
The waves flagged ~40 candidate laws. Five were byte-probed, generalizable and
actionable enough to bank; they were deduped by hand against the file (no
skeptic-agent pass this time, so each says what it sharpens and why that
section is insufficient):

- §163a decl-conflict severity is SCOPE-DEPENDENT — hard error if either decl
  is at file scope, warning only if BOTH are at block scope. §8d proves the
  phenomenon on D_801812A4 but never states the rule or its LEVER half: block
  scope is a deliberate conflict SOLVENT, so a struct-typed draft can be banked
  into a scalar-typed TU by moving the typedef AND the extern into the block.
- §163b the switch-index parameter-WIDTH oracle: sll/sra straddling the minval
  subtract is a 2-insn signature of a short parameter. Read the extension, not
  just the bound.
- §163c case_values_threshold is 5 — an empty `case k:` glued to default can be
  the only thing that emits a table at all; jtbl[k]==default label is the tell.
- §163d cse deletes a reg-reg copy by rewriting the PREVIOUS insn's SET_DEST
  (cse.c:7440-7477). This is §162j's symptom in a DIFFERENT PASS and needs a
  different lever; the residual it explains had been declared "unsteerable, 30
  variants all >=17" and fell to source-shape edits alone, no pins.
- §163e the frame is a PSEUDO-NUMBER oracle (reload1.c:658 alter_reg in NUMBER
  order); dead-local slot order is not declaration order, and a BLKmode local
  is 8-aligned while a scalar s32 is not. Sharpens §162i, which gets the pad's
  SIZE right and its PLACEMENT wrong.

§163z catalogues the ~35 unvetted claims by function so a future harvest can go
straight to them, explicitly marked "one agent's reconstruction until
re-measured" (R14).

cookbook_index.py: 497 sections.
2026-08-12 10:03:31 -06:00
Drew T 72932899d5 chore(phase-30 S48): checkpoint — 317 banked (13,345 -> 13,028), R22 213/213
Wave 3 added 84 (27 cracks + 21 propagated families). Fleet 94.8% instr /
89.2% distinct / 96.41% fn-count. R22 clean-fleet run 6x this session, 213/213
every time. 96 commits.

Bank rate measured three times: 67% -> 79% -> 69%. The dip is the cost curve
(wave 3's tier was 29 Opus-band / 14 jr vs wave 2's 8 / 5, median reach x6 ->
x3-4), not a regression.

Two levers proved out and belong in every future wave: the hardened harness
contract (0 drafts lost vs 21) and prior-notes seeding (7 of 9 previously
failed targets converted, incl. both long-standing NEARs and all three wave-2
gate misses). NEAR is a resumable state, not a write-off.
2026-08-11 23:04:08 -06:00
Drew T 35d7b11d03 chore(phase-30 S48): checkpoint — 233 banked (13,345 -> 13,112), R22 213/213
Session close state. Three parts: stage 0b (91, zero decompilation), wave 1
(26), wave 2 (116). Fleet 94.4% -> 94.7% instr, 88.3% -> 88.9% distinct,
13,345 -> 13,112 stubs. R22 clean-fleet run 5x, 213/213 every time.

The campaign now has a MEASURED rate, twice: 67% (wave 1, all-Opus) then 79%
(wave 2, 20 of 28 Sonnet) of cracks survive the whole-binary gate. The Sonnet
band beating the all-Opus wave is the session's most useful economic finding
and sets wave 3's routing.

Resume order changed on evidence, twice over:
- harden the wave harness FIRST (per-agent dirs, sha1-last verifier, and a
  tools/recover_drafts.py built from the transcript-replay method that
  recovered 21/21 today);
- then wave 3, sized on 79%, not on the reach-15 prior.

Error ledger grew to 6. The two that matter: I wrote off 21 verified cracks as
lost when the run transcripts held every one of them, and my first two
recovery passes both failed by reading a single tool record instead of
replaying the file's mutation history.
2026-08-11 21:08:06 -06:00
Drew T 551239bd3c chore(phase-30 S48): checkpoint — 117 banked (13,345 -> 13,228), R22 213/213
Stage 0b closed (91, zero decompilation) + Stage-1 wave 1 (8 cracks -> 26
instances). Fleet 94.6% instr / 88.8% distinct / 96.36% fn-count.

Resume order changed on measured evidence: FIX THE md_ MODULE LANE FIRST.
16 of the wave's 42 member slots were unreachable for tooling reasons, not
matching reasons — 12 on a carve that assumes raw data lives in
<binary>/data/*.data.s (modules do not), 4 on an uncarried extern
(`D_8011511A' undeclared). Both are named with verbatim errors; probe one of
each before pricing (R37). Precedent: 0b's three repairs banked 91 for ~0
agent tokens; the wave spent 3.36M for 26.

Also recorded: the frontier re-derivation (1,955 zero-crack families /
330,622 templatable ins), the tier-ordering correction (ins-per-crack is flat
across x5-x8, so rank by templatable weight, not by tier), and the §162
harvest with its two in-place cookbook corrections.
2026-08-11 18:42:30 -06:00
Drew T 0c5d6fa909 docs(phase-30 S48): §162 — the wave-1 idiom harvest, deduped by a skeptic pass
17 candidates from the 12 crack agents, each audited against the whole
cookbook by an independent agent before being written: NEW 3, SHARPENS 13,
COVERED 0 (one agent died mid-response — its entry, §162c, is written by the
orchestrator and labelled as the least-audited one).

The three genuinely new laws:
- §162e  LICM: uniform loop-variable indexing is what makes a symbol address a
         MOVABLE at all (a literal index leaves a constant, no base pseudo, no
         hoist), and preheader order is body order.
- §162g  cross-jump DIRECTION is a source-shape oracle: do_cross_jump always
         keeps the LATER copy, so a BACKWARD jump into an earlier block can
         never be cross-jumping — it is a source `goto`.
- §162n  a conditionally-assigned alias pointer kills a spurious giv
         (loop.c cant_derive).

Two in-place CORRECTIONS, because a reader who lands there first must not be
taught the superseded rule:
- §161a's "diagnostic tell (family-wide)" reads as a complete test on entry[0]
  and actively teaches skipping the upper edge. Amended: check BOTH edges.
  The maxval symptom is the OPPOSITE of the minval one — it shifts nothing and
  costs two bytes, so it is functionally invisible.
- §25's triage rule prescribes pins for a symptom whose sibling mechanism
  (local-alloc optimize_reg_copy_1) pins provably cannot reach, because
  SMALL_REGISTER_CLASSES is never defined in config/mips/mips.h. Amended to
  point at §162j.

The skeptic pass also caught two errors in MY submitted evidence: I had copied
§161a's minval symptom onto the maxval case, and I described func_8017F2D4 as
a verified MATCH when the whole-binary gate had refused it (it is still
INCLUDE_ASM). Both corrected in the entries.

cookbook_index.py: 495 sections, 14 symptom buckets.
2026-08-11 18:31:18 -06:00
Drew T 0498fc3627 chore(phase-30 S48): stage 0b closed — 91 banked (stub oracle 13,345 -> 13,254), R22 213/213 clean 2026-08-11 16:13:31 -06:00
Drew T fd80bd7007 feat(phase-30 S47-0a.1): the symbol-KIND fix banks 205 members; the residue crosses over to DIFF
Stage 0a's first defect, and the largest single zero-token bank of the session.

family_remap's kind test asked ONE question — is this address a function in the SIBLING'S OWN sig?
— and defaulted to `D_` on "no". But a body calls outside its image constantly: an overlay calls
resident helpers, an md_* module calls the overlay-range engine. Those addresses are absent from
the sibling's sig, so the test fell through and emitted a DATA NAME FOR A FUNCTION —
`D_800183E0`, `D_800D1EBC`, `D_80171A1C`. None exist anywhere in src/ or config/symbols.us.txt,
while `func_80171A1C` alone has 1,061 references. Measured: 611 member-rows across 45 symbols,
the largest named residue class. "Not in MY sig" means "not mine", not "is data".

Fix — three oracles, strongest first, never a blanket fallback:
 1. the sibling's own sig (authoritative for its image; this is what preserves the Phase-29 T82
    case where a slot is a function in the exemplar and DATA in the member — unioning every sig
    would have re-broken the 251 members T82 fixed),
 2. the always-linked images via extern_fn_addrs() — resident + main, 2,146 addresses whose ranges
    cannot collide with an overlay's,
 3. the exemplar reached it by `jal` — a call target is a function BY DEFINITION, which covers an
    external address neither sig claims (0x80171A1C from an md_* module, 112 rows).
Only a non-call reloc no oracle claims still falls to `D_`.

Result: BANKED 205 member-matches, failures 670 -> 575, derived net = report = 205.
R22 clean-fleet 213 passed / 0 failed of 213.
Fleet 94.4% instr / 88.3% distinct / 96.27 -> 96.33% fn-count; stubs 13,563 -> 13,345.

THE RESIDUE HAS CROSSED OVER: DIFF is now the LARGEST class at 143 of 575 — real byte divergence
outranks plumbing for the first time this session (undefined-ref 611 -> ~8, PLUMBING-other
231 -> 81). The ~5:1 plumbing:DIFF ratio that justified "tooling beats volume" has inverted in this
queue, exactly as the frontier analysis predicted: the declaration-axis vein was one-time.
The new head class is `conflicting types for func_80175414` (27) — the same addresses this fix
started naming correctly, now surfacing the NEXT layer (the symbol resolves; its declared signature
disagrees). That is the conform axis, not the remap axis.

Note for anyone auditing this class: rtu_match MASKS HI16/LO16, so a wrong %hi/%lo symbol still
reports MATCH (the T82 comment records `MATCH (10 ins)` on a member the fleet gate refused). This
defect is invisible to the per-function tool by construction — only the whole-binary gate sees it.
2026-08-11 14:02:38 -06:00
Drew T d5fbd2630f fix(phase-30 S47): family_hseq derives its own SCOPE, not just its own count; + a zero-crack glossary
The targeting oracle stamped its scope as "the N OVERLAYS only (no main, no resident)" while
load() has scanned the md_* modules and the resident since S44. Measured at this HEAD: 141 location
overlays + 70 md_* modules + the resident = 212 binaries. That is the §159 coverage law broken by
the file that documents coverage, on the repo's most load-bearing targeting instrument — and it is
how "main is structurally barren" survived two phases unexamined.

The COUNT beside it was already derived, with a comment saying "report the scope we ACTUALLY
scanned, never a hardcoded count". The PROSE describing what the count meant was hardcoded and
rotted. Both are derived now.

Caught while fixing it: my first cut read glob(".run/sig.main.jsonl") and stamped "main INCLUDED"
the moment that file existed — while load() still did not glob it. Same defect one layer down: a
stamp describing the filesystem instead of the run. Now derived from the loaded instances.

Also added a glossary line: "zero-crack" means n_matched == 0 (needs its FIRST crack) in this map,
and the OPPOSITE (a matched exemplar awaiting propagation) in roadmap §3 T3 — a ~30x mis-scope risk
for any session reading one against the other.

NOT DONE — main inclusion (0c) is still blocked on settling the attribution. Confirmed the
mechanism: main has 49 LINKED PsyQ subsegs, corpus.stubs('main') returns 2,002 INCLUDING them,
progress.py correctly excludes them and reports 1,034 game-code stubs. progress.linked_subsegs'
own docstring records this exact trap ("an importer then classifies ~1,300 already-byte-identical
LINKED library stubs as outstanding game-code work") — and my sig-main seeded from corpus.stubs,
so it inherited the LINKED rows, which is why G2's 207-family finding was inflated.
My partition probe is NOT trustworthy: 954 of 2,002 stubs returned no asm path from
corpus.asm_path, so 199 LINKED / 849 game / 954 unresolved does not reconcile with 1,034. Fix the
probe before trusting any main-scope number.
2026-08-11 13:42:40 -06:00
Drew T d3f3d8ba22 feat(phase-30 S47-W1b/G2): 3 retries banked, 2 new rules; main signed for the first time
W1b — the 3 targets whose agents died on API rate limiting, retried with cookbook §160 in the
prompt: func_801EFBF4 (reach 12), func_801EFDC8 (12), func_8018CC40 (10, jr). 3/3 confirmed by an
independent verifier, all banked, R22 clean-fleet 213 passed / 0 failed of 213.

func_8018CC40 failed the first gate with `too many arguments to function func_80178970` — which its
own crack agent had PREDICTED in its report, naming the §17a-1 remedy. Dropped the draft's
empty-paren externs and cast 6 call sites instead; banked. Read the agent's integration notes
before diagnosing a gate failure — it has already seen the TU.

Cookbook §161a-c (index 469 sections):
 §161a case 0: break; is LOAD-BEARING when a jump table is indexed from zero. The natural
   case 1..5 makes gcc-2.7.2 pick minval=1, emit `addiu $v1,-1`, and shift every table index —
   58 of 77 mismatched on a byte-perfect body. Tell: the table's FIRST entry points at the
   function's own end address. Family-wide (10 members).
 §161b aliasing a parameter into a local can force a SECOND callee-saved register (+8 frame,
   +3 ins) even when uses are mutually exclusive. Suspect it before reaching for register pins.
 §161c loose-prototype engine helpers: don't fight the TU's (void) decl, cast at the call site.

G2 — THE MAIN EXPERIMENT. family_hseq excludes main as "structurally barren — zero h_exact
overlap". True and irrelevant: an h_exact claim guarding an h_seq tool. There is not even a
sig-main target — main had never been signed for this pipeline. Signed it (2,002 fns, seeded from
splat boundaries via corpus.stubs rather than --bootstrap, which glues functions around jtbl
dispatch and would have corrupted the hashes under test).

Result: main is ~85% singleton work, not 100%.
  internal h_seq families (>=2):  207 families / 748 fns / 11,537 ins (13.7%)
  shapes shared with the fleet:   161 fns / 1,346 ins (1.6%)
  genuine x1 remainder:           ~71,034 ins (84.6%)
IMMEDIATELY ACTIONABLE: 44 classes / 151 main functions / 1,239 ins already have a matched exemplar
in the fleet — free propagation, invisible only because main is not in the map.
Long-term: 748 of main's 2,002 functions (37%) are templatable once one exemplar per family is
cracked, which refutes "2,002 independent cracks" as the planning assumption for the 79k-ins tail.

OPEN, deliberately not done unilaterally: adding a sig-main target and dropping main's exclusion
from family_hseq.load() changes a fleet-shared oracle every targeting tool reads. Needs Drew's call.
2026-08-11 12:31:16 -06:00
Drew T d806766eef feat(phase-30 S47-W1c): crack the reach-57 exemplar; fix the instrument that called it a wall
func_801EDC18 (md_SC05_023) is the largest multiplier remaining — 57 members. The wave agent
abandoned it at "closeness 6" with class SIZE-MISMATCH [redraft]. It was two lines from correct.

THE CODE (cookbook §160a): the target copies 8 bytes with lwl/lwr + swl/swr — gcc-2.7.2's
emit_block_move for a type with ALIGNMENT 1. The draft used a u32 copy (aligned lw/sw), which is
wrong by construction. `typedef struct { char c[8]; } Blk8; buffer = D_801ED98C;` reproduces it.
Six spellings were tried in parallel; two independent agents converged on the same one.

THE INSTRUMENT (§160b) — this is the part worth more than the function. The target .s bundles a
leading `.section .rodata` block (D_801ED98C as two .word) ahead of .text. Those lines carry the
same `/* off vaddr HEX */` shape as instructions, so masked_diff.insns_from_s counted them as TARGET
instructions, while insns_from_object (objdump -j .text) can never emit them. A byte-perfect draft
therefore read `mine=26, target=28, 26 mismatched` — every position shifted by a constant +2 — and
got classified as needing a redraft. 116 of 12,583 .s files in the corpus have this shape, one at
-29 instructions. Every one of them would report a false wall to any agent that tried it.
Fixed: insns_from_s tracks .section and counts only .text. Full-corpus control: 12,467 unchanged,
116 corrected, 0 regressions. Same artifact class as §129a (post-carve jtbl inflation).

THE OWNERSHIP LAW (§160c) — my own error, corrected by the gate. Four sites declare
`extern short D_801ED98C;` and nothing in src/ defines it, so I shipped an extern-only draft. The
gate refuted it: `undefined reference`. The .s block the draft REPLACED was the definition. The
variant emitting `const Blk8 D_801ED98C = {{...}}` banks clean. Never infer ownership from externs.

R22 clean-fleet: check-all 213 passed / 0 failed of 213.

ALSO BANKED — the wave's idiom harvest, which had been sitting unwritten in workflow transcripts
(R16/R30 debt): §160d the ASYMMETRIC INDEX RELOAD (a just-stored narrow field read twice emits
reuse-then-reload; the C is deliberately asymmetric), §160e a stack-layout scheduling rule now
byte-proven on a SECOND independent function (promoting it from coincidence to rule), §160f the
address-only global store via array decl, §160g sibling-search keyed on the CALLEE SET as step 0 of
every wave prompt (one grep turned a 126-instruction crack into a copy-edit).
Cookbook index regenerated: 468 sections.
2026-08-11 12:05:24 -06:00
Drew T ff11fc556c feat(phase-30 S47-W1s): the reach-15 wave templates to 140 members (81% conversion)
The 10 exemplars from W1 flipped modal -> matched in the regenerated map, so family_sweep could
template them. 9 non-jr families swept: BANKED 140 member-matches / 32 failed across 50 overlays.
Derived net = report = 140 (no untracked carve files this time, so the two counts agree).
R22 clean-fleet: check-all 213 passed / 0 failed of 213.

Fleet 94.3 -> 94.4% instr / 88.2 -> 88.3% distinct / 96.22 -> 96.27% fn-count; stubs 13,713 -> 13,563.

WAVE ONE, FULLY ACCOUNTED: 10 agent cracks + 140 templated members = 150 functions for 1.36M
tokens (~9k tokens/function). Still owed from this wave: 73 member-slots in 2 NEAR families,
34 in 3 rate-limited targets, 9 in the jr family (routes to jtbl_family_bank, §53).

TWO MEASUREMENTS THAT CORRECT MY OWN FORECASTS (R14):
 1. Conversion was 81%, not the 58% I projected from this morning's propagation run. Today's
    plumbing fixes (alias-drop, cpp-derived TU type map, group-level draft-vs-draft aliasing) are
    paying off in a population they were not tuned for.
 2. The effective multiplier was 15x, not the 2-3.5x I predicted. That estimate used the MEAN
    family size across the whole zero-crack pool (3.55); this wave deliberately targeted the TOP of
    the reach distribution, where families run 10-28 members. Ordering waves by reach is what
    produced the difference — the mean was the wrong statistic for a wave that selects on the tail.

The regen step is load-bearing and now byte-proven twice: a fresh crack reads as `modal` until sigs
+ family_hseq are rebuilt, and family_sweep templates only from `matched`. Skipping it sweeps a
stale map and the multiplier evaporates (the Phase-26 finding, whose surviving qualifier is that
remap works BEHIND a fresh crack).
2026-08-11 11:41:13 -06:00
Drew T f212ebcc28 chore(phase-30 S47): refresh frontier docs at HEAD commit:1565
Fleet 94.3% instr / 88.2% distinct / 96.22% fn-count; INCLUDE_ASM stubs 13,713.
Frontier (overlays): 6,701 families / 12,679 instances / 685,757 ins.
  siblings + matched exemplar (propagate): 166 fams / 1,122 members / 61,466 ins
  siblings + zero-crack:                 1,969 fams / 6,991 members / 342,004 ins
  singleton + matched exemplar:              53 / 53 / 4,451
  singleton + zero-crack:                 4,513 / 4,513 / 277,836
Zero-crack by size band: <30 ins 2,184 fams/89,785 ins - 30-49 1,738/118,104 -
50-199 2,353 fams/3,800 members/325,223 ins - 200-399 179/67,115 - 400+ 28/19,613.
2026-08-10 22:55:36 -06:00
Drew T dbed0942b1 feat(phase-30 S47-A4): cdFileLocTable typedef alias banks 138 members; R22 213/213
The one-line fix committed ahead of this run (CdFileLoc_80128C98 aliasing CdFileLoc) cleared the
largest remaining propagation-sweep class. Re-sweep: 138 member-matches banked, failures 875 -> 737,
`conflicting types for cdFileLocTable` gone entirely (136 -> 0).

Derived net (138 INCLUDE_ASM removed, 0 re-added) equals the report's 138 — they agree.
R22 clean-fleet: check-all 213 passed / 0 failed of 213.
Fleet 94.2 -> 94.3% instr / 87.9 -> 88.1% distinct / 96.15 -> 96.21% fn-count; stubs 13,780.

Residue reclassified — no symbol dominates any more: 227 PLUMBING-other, 125 DIFF (real byte
divergence, 17%), 93 CC1-FAIL(no-diagnostic), 26 memcpy, then a tail of small data-symbol
conflicts (D_80114F24 12, D_800AE620 11, D_800183E0 9, D_80126B58 6, D_80078EB4 6).

CC1-FAIL rose 77 -> 93 and that is NOT a regression: members that previously died earlier on the
cdFileLocTable conflict now reach a different compile error. Those 93 are hard gcc errors whose
text the sweep's classifier discards because it greps for `error:`, which gcc-2.7.2 never emits on
hard errors. That classifier is now the highest-value instrument fix left — three times today a
no-diagnostic verdict concealed something cheap.
2026-08-10 20:59:06 -06:00
Drew T efec1b9b71 fix(phase-30 S47-A1): asm-label aliases must never be dropped by §8d; +148 members
scope_data_externs §8d drops the draft's decl of any symbol the TU already declares at file scope.
It keys on the SYMBOL, but a §37 asm-label ALIAS binds a DIFFERENT C identifier to that symbol:
the TU declares `D_801851BC`, it does NOT declare `tbl_D_80187044`. Dropping the alias left the
body referencing an undeclared name, which cc1 reports with no `error:` prefix — so the sweep
classified all 132 siblings as CC1-FAIL(no-diagnostic), i.e. as a codegen wall.

The bitter part: the alias exists PRECISELY BECAUSE the TU declares that symbol with a conflicting
type (a `void (*[])(void)` dispatch table vs this function's 20-byte-stride view). The drop rule
fired on exactly the declarations written to survive it. Why 1 of 2 died was fully determined:
tbl_D_80187048's symbol is not in the TU, so it demoted normally.

Fix: is_asm_alias() — an alias is demoted into the body, never dropped (the identifiers differ, so
it cannot collide with the TU's decl). Control-tested 6 ways incl. self-labels and plain externs.

Measured: func_80132018 3/135 -> 135/135; full re-sweep +16 more. Total +148 members.
R22 clean-fleet 213 passed / 0 failed of 213. tools-health OK, dedup-check 1949/0.
Fleet 96.11 -> 96.15% fn-count, 87.8 -> 87.9% distinct; stubs 14,120 -> 13,972 = -148 (2nd oracle).

CORRECTION TO MY OWN CLAIM (R14): after the probe I said the 58% aggregate was concealing a broad
problem. The re-sweep refuted it — only 16 more banks fleet-wide. The alias class really was one
family; the first read ("outlier") was right and the correction was wrong.

875 sweep failures classified: 231 PLUMBING-other, 141 DIFF (real divergence, only 16%),
136 `conflicting types for cdFileLocTable` (ONE symbol — biggest single class left),
77 CC1-FAIL(no-diagnostic), 26 memcpy, 12 D_80114F24, 11 D_800AE620, 9 D_800183E0.

STILL UNFIXED, and the most dangerous instrument left: the sweep's failure classifier greps for
`error:`, which gcc-2.7.2 never emits on hard errors. Every hard error therefore reads
CC1-FAIL(no-diagnostic). That is how a missing declaration looked like a codegen wall across 132
functions. rtu_match was fixed for this at T0(b); this classifier was not.
2026-08-10 18:50:48 -06:00
Drew T 57e345fcce feat(phase-30 S47-P): propagation sweep banks 1,419 member-matches for ~0 agent tokens
family_sweep --hseq --band all -j 8 over every matched-exemplar family: 553 families /
203 overlays / 1,419 banked / 1,023 failed (58%). R22 clean-fleet 213 passed / 0 failed of 213.
tools-health OK, dedup-check 1949 validated / 0 failed.

Fleet: 93.9 -> 94.2% instr / 87.2 -> 87.8% distinct / 95.72 -> 96.11% fn-count.
Second oracle (R34): INCLUDE_ASM stubs 15,542 -> 14,120 = -1,422, equal to the diff-derived net
(1,451 removed - 29 re-added = 1,422 = 1,419 sweep + 3 probe). Three independent counts agree.

B -> C -> P IS ONE CHAIN, NOT THREE WINS. 1,102 of the 1,422 landed in ov_SC02_037 (409),
ov_SC03_107 (364), ov_MAIN_012 (329) — the three newly-onboarded binaries from C, which had never
been wired into the shared-body ecosystem, so every matched exemplar was unreachable from them.
B fixed the declarations, C wired the include, P poured through the opening. A repeat sweep will
NOT pay like this; the opening was one-time.

S47 total: 1,481 functions banked with zero agent drafting, all from removing plumbing.

Two findings recorded, neither fixed (deliberate, costed):
- --band defaults to `substantial`: the first probe returned a confident {"families": 0,
  "banked": 0} on a real 135-member `mid` family. Always pass --band all.
- The alias-gather defect: probe on 0x80132018 banked 3/135, all 132 failures classified
  CC1-FAIL(no-diagnostic) because gcc-2.7.2 emits no `error:` prefix. Real error is
  `tbl_D_80187044' undeclared` — the exemplar declares TWO §37 asm-label aliases and uses both,
  family_remap carried one. T7-S1's "gather" class. Measured as an OUTLIER (aggregate 58%),
  which is why the sweep ran before the fix.

Refused by design, all named: 50 jr families / 183 member-slots (§53 interlock — it printed its
own coverage and reason), 264 STRUCT, 112 unresolved immediates, 3 not-stub.
2026-08-10 17:59:35 -06:00
Drew T 5f001a9392 chore(phase-30 S47): refresh derived frontier docs at HEAD commit:1543
Regenerated after the S47-B/C banks (family_hseq.py + report): docs/family-hseq.md,
docs/progress.fleet.md, docs/backlog.md. Numbers only — no analysis change.

Frontier at this HEAD (overlays only): 7,085 families / 14,508 instances / 752,073 ins.
  with siblings (>=2): 2,429 fams / 9,852 members / 467,634 ins (62.2%)
    - matched exemplar (propagate, ~0 tok): 460 fams / 2,861 members / 125,630 ins
    - zero-crack (crack 1 -> templates to N): 1,969 fams / 6,991 members / 342,004 ins
  singletons: 4,656 fams / 4,656 members / 284,439 ins (37.8%)
    - matched exemplar: 143 / 6,603 ins   - zero-crack (pays x1): 4,513 / 277,836 ins

Structural: the x138 era is over — 3 fleet-wide families remain and ALL 3 already have matched
exemplars, so no fleet-wide CRACK is left, only propagation. 82% of remaining code now sits in
the two worst cost profiles (x2-9 zero-crack 45.5%, singleton zero-crack 36.9%).
2026-08-10 16:48:49 -06:00
Drew T 9ab9120e04 feat(phase-30 S47-B): conform 8 declaration axes (~10,930 sites); 3 guard defects fixed; 213/213
Task B, re-scoped from evidence. The 129 dedup_extend failures are 106 conflicting-types /
21 CC1-FAIL / 4 undefined-ref / 3 DIFF — real byte divergence is 2%, and memcpy is 17 of 106,
not the story. Direction reversed too: the byte-true DEF of func_80128ED8 is what the target
.c files already declare; engine_core.h's macro-local extern was the stub-era guess.

Conformed 8 axes to byte-truth (func_8012F14C 2843, func_8012E5CC 2052, func_8012F038 2214,
func_8014C568 1816, func_80128ED8 1524, func_8012C750 406, func_8012C0EC 50, func_80144A04 25).
R22 clean-fleet: check-all 213 passed / 0 failed of 213. Zero functions banked by design.

Tooling (R33/R35) — three guards that asserted completeness over a narrowed population:
- NEW tools/macro_draft.py: a deduped fn has no definition in any .c (body lives in a DEFINE_
  macro), so conform_decls had been refusing the largest class it was built for.
- conform_decls skipped engine_core.h wholesale as "a defining TU": 10 stale externs survived
  while 1,514 fleet sites moved, and it still printed "axis complete". Skip now scoped to the
  defining macro's span.
- Return-axis compare was literal: typedef int/s32 and a missing `extern` faked a return change.
  Now compares normalized types.
- §85 consumer scan under-reported (the dangerous direction): a cast between `=` and the call
  hid `s0 = (s32 *)func_80144A04(...)`. Now classified by position, validated both ways.

Corrections to my own predictions (R14): the documented scalar-narrowing hazard was benign
across 2,052 sites; the breaks were arity (6 call sites, fixed with §17a-1 fn-ptr casts) and
the consumer-guard gap. A header-only first probe broke ov_SC01_000 — §85 is literal.

Not done, named: memcpy (builtin codegen), ApplyMatrixSV (no DEF), gte_SetRotMatrix (link bug),
func_80147364 (unparseable macro), D_800AE620/D_80126CC4 (data axis). Cookbook §159.
2026-08-10 16:01:49 -06:00
Drew T b0c1e14fda feat(phase-30 S46-final): 400+ cascade banked (11) + waste-prevention gate; B re-scoped, C blocked
- BANKED: 11 functions at 400-952 ins from the cascade (func_8017D898 952, func_8017CE58 733,
  func_801902EC 673, func_8018C2D8 673, func_8018A8D4, func_8017C6F4, func_800CBB38,
  func_800CF3A4, +3). check-all 213/213 from a clean tree. 6 near = jr/switch (§53 separate
  banking step), 1 failed. The cascade agents wrote 6 new cookbook sections incl. §158.
  ⚠️ tools-health UNVERIFIED at commit (stale cookbook index fixed, confirming re-run
  interrupted) — run it first next session. check-all is the byte oracle and it is green.
- WASTE PREVENTION (Drew: "prevent this from ever happening again, however you need to"):
  * tools/validate_targets.py (NEW) — names 5 defect classes (NO-ASM / MID-BODY /
    OUT-OF-RANGE / ALREADY-DONE / NO-BOUNDARY), exits non-zero.
  * WIRED INTO wave_snapshot so it fails closed — every wave passes through there for its .s
    files, so no path from target list to spawned agents bypasses validation. Negative-control:
    a 3-target bad list is refused with the exact mid-body offset (+72 bytes of 100).
  * The cascade `done()` predicate now short-circuits on SKIPPED as well as MATCH. It tested
    only MATCH, so a non-existent target fell Sonnet -> Opus -> Fable and three agents each
    proved the same phantom absent: ~29 invalid targets x 3 tiers = 87 of 119 agents, ~9.7M
    tokens. A tier that cannot act must END the pipeline, not escalate emptiness.
  * docs/accelerators.md A9, including that wave_snapshot's own R32 assertion REFUSED that list
    (24 of 57 found) and was routed around — the one instrument warning that was right and ignored.
- B RE-SCOPED (S46-10) and deliberately NOT done: the extend blocker is INTRA-HEADER, not
  target-side. engine_core.h declares memcpy FOUR incompatible ways across its DEFINE_ macros;
  two in one TU collide. NOT a safe cleanup — the in-tree note at ov_MAIN_012.c:14333 records
  that `extern memcpy` disables gcc's builtin and turns an inlined block-move into a CALL, so the
  declaration CHANGES CODEGEN. Probe one macro in one binary and byte-gate before any sweep.
- C (dedup_extend over the 129) stays blocked on B. Full context for both in the checkpoint.
2026-08-10 14:16:19 -06:00
Drew T f6e48b60c5 perf(phase-30 S46-4): parallelise the propagation — 24min -> 11.4min, and +62 MORE instances
Drew: "make it more multi-threaded... I still see my cpu idle for far too long."
Measured, fixed, and regression-tested against the S46-3 bank as a KNOWN ANSWER.

- THE MEASUREMENT: 31s saturated (33 makes/48 cc1/load 27) then ~25s with ONE build alive
  while 31 cores idled, repeating. Causes: ex.map starts in list order so the giants land
  last, and apply/restore is single-threaded.
- gate_all -> gate_failures: return EVERY failure the sweep already computed (~138 rounds -> 1).
- Longest-first gate scheduling; results re-sorted into `changed` order so the verdict stays
  bit-identical to the serial loop's.
- PER-OVERLAY INDEPENDENT SEARCH, IN PROCESSES. My first cut used threads and the box refuted
  it: 0-4 builds alive at load 3, because the work is regex over 15k-line files and 138
  "parallel" searches all queued on the GIL. Same logic in a ProcessPoolExecutor: 14-29 builds,
  load 34.75, search phase ~100s. Safe because the shared header is written ONCE by the parent
  and each overlay owns its own .c files + build/<bin>/. Seeded with one in-process search
  first — a pool submitted at once gives every worker an empty suspect list and makes all 138
  pay a full bisection. place_in_overlay extracted to module level so the worker and the
  in-process apply cannot drift (R33); compiles_standalone's fixed t.c is per-call now.
- THE REGRESSION (the point, not the stopwatch): revert src/+config to pre-bank, re-run the
  identical command -> 29 functions (same), 141 overlays byte-identical, 682s vs ~1440s, and
  285 exclusions vs ~350 => +62 MORE member instances (249,161). The old prefix-based
  necessity probe was OVER-EXCLUDING (charging 4 fns to 9 overlays that did not all need
  them); the per-overlay shrink minimises per overlay. The faster path is also more correct —
  a timing comparison would never have shown it. R22 213/213 + tools-health green.
- STILL SERIAL, now the actual wall-clock (neither is a build): ~3min setup before the first
  gate (registered_addrs() yaml-parsing a 1949-group/249k-instance registry + 213 sig loads)
  and ~2.5min of sequential reconcile_caller_extern after the search.
- Captured as defaults: docs/accelerators.md A8 + memory fleet-tool-parallelism-defaults.
  cookbook index regenerated (my §155c append left it stale — the gate caught it, exit 1).
2026-08-07 23:14:15 -06:00
Drew T b005312127 feat(phase-30 S46-3): propagation banked — 29 fns / +2,815 member-instances; R22 213/213
The S45p9 blocker is closed, and the recovery loop that kept it from finishing is rewritten.

- BANKED: dedup_propagate --auto-from ov_SC02_037 --recover -> 29 functions propagated,
  141 overlays byte-identical, dedup 1920 -> 1949 groups, member instances 246,284 ->
  249,099 (+2,815). make clean && extract-all && check-all -> 213 passed / 0 failed (R22).
- WHY IT FINISHED THIS TIME: gate_all -> gate_failures returns EVERY failure from the sweep
  that already computed them, and the recovery loop resolves them all per round. Converged in
  3 rounds; the old one-overlay-per-sweep design needed ~138. That reframes the S45 run — it
  was not nearly done when it died, it had barely started.
- Batching did NOT cost capability: per-overlay necessity probes excluded four of the nine
  culprits from only the 9 overlays that needed it (not all 138), and ov_SC07_006 was
  RECOVERED by the Part-B caller-extern reconcile instead of excluded.
- Plan phase parallelised: 5 min -> 26 s, plan + skip classification byte-identical. Its
  compiles_standalone temp file is per-call now — the fixed `t.c` was the same fake-isolation
  class as match_one's shared --work dir (P28 T5), latent until something ran it in parallel.
- docs/accelerators.md (NEW, Drew 2026-08-07): the reusable-workflow ledger — what we learned
  late that a future decomp should know on day one, each entry with when we found it, when it
  WAS findable, what it cost, and the honest prerequisite where one exists.
2026-08-07 22:24:35 -06:00
Drew T 9351b17f48 feat(phase-30 S46-2): the master IDXTAB/DESTPTR load map — and the tracker blind spot that hid it
Drew's S45 idea, delivered fleet-wide + wired into the permanent references.

- THE BLOCKER WAS OUR INSTRUMENT (R35, the 3rd time): the S45 plan ("require a
  register-verified reference to the run's address") returns ZERO for both byte-proved
  tables. They are read by gcc's indexed global-array form —
      lui $at,0x8019 ; addu $at,$at,$a0 ; lh $v0,-0x2844($at)  -> 0x8018D7BC
  — where the address exists only as (lui imm, LOAD offset) with the index add between.
  find_addr_refs killed the lui register at the addu, so the halves never rejoined and
  the tables looked unreachable. Now it carries the hi half through the index add (still
  strictly register-tracked, never window-paired) and labels those hits `-indexed`.
- tools/idxtab_map.py (NEW): fleet-wide payload -> owning binary -> load address.
  Controls-gated (refuses to emit unless ov_SC01_000 0x8017EEC8/37 + *0x801A3234, and
  ov_SC03_001 0x8018D7BC/5 + *0x801EBC68 reproduce from the images alone). Index space
  DERIVED from the extracted tree (reproduces §S44's table independently). Process-pooled.
  Rejects all-zero and majority-zero runs (132 of the first pass's 452 "tables" were that).
- RESULT: 213 binaries -> 143 with a referenced table (294), 141 with a DESTPTR (141/141
  resolved from the binary's OWN image), 61 payloads. The two dominant tables are
  fleet-wide CONSTANTS (5-entry and 37-entry, identical in all 141 overlays); the
  per-binary variable is the destination (134 distinct).
- CORRECTION 1 (R14): §S45 p6's "the SC03 trio are owned by ov_SC03_001" is refuted —
  that 5-entry table is identical in ALL 141 overlays. The byte-observed parts stand.
- CORRECTION 2 (P9): this route CANNOT settle MAIN/7+9. They are absent from all 294
  tables — but so are MAIN/13/20/34/42/44, which are byte-proved to load. Absence here
  means "not on this route", nothing more. Recorded so it is not re-derived as a finding.
- Confidence is stated per-claim in docs/idxtab-map.md: proven (controls) / high (283
  fleet-wide-class tables) / low (3 named rare rows) / UNMEASURED (recall — no oracle
  for "all tables" exists beyond the 2 controls).
- Wired in permanently: docs/idxtab-map.md (the how/when/limits), memory-map.md §S46,
  cookbook §155c (the generalizable law: "no code references X" is a claim about your
  DECODER until it is shown to recognise the forms the compiler emits), SETUP.md
  tooling inventory (R21).
2026-08-07 22:09:05 -06:00
Drew T 537bd90a9a feat(phase-30 S45p6): SOLVED — the SC03 trio are ov_SC03_001's script modules (static decode)
Found the IDXTAB: ov_SC03_001 @0x8018D7BC holds 5 s16 entries, -1 terminated:
224, 231, 232, 234, 233 — i.e. the ENTIRE parked trio (SC03/53/54/56) plus its DATA
companion (SC03/55 = 233), in one table, in the binary whose *DESTPTR points at the
script-module slot the tracer watched load live an hour earlier.

THE CHAIN (every link register-verified or byte-observed):
  ov_SC03_001 IDXTAB @0x8018D7BC  -> indices 231/232/234 (+233 data, +224)
  func_80128CFC (the S44 wrapper) -> cdFileLocTable[idx] -> {loc,size}
      register-tracked: addiu->0x800AE830, lw[0x800AE834] size, lw[0x800AE830] loc
  *DESTPTR @0x801EBC68 = 0x801EF468 -> the script slot
      the ONLY occurrence of that word fleet-wide; read 8x by code, 2x from inside func_80128CFC
  slot confirmed LIVE by tools/cdtrace.py: SC03/76 and SC03/34 both loaded there
  and 0x801EF468 lies inside SC03/54's independently-derived base window [0x801EDED0..0x801EF6C8]

VERDICT: LIVE script modules owned by ov_SC03_001. Not dead code, not boss-gated, not
chapter-gated (that framing retired — scripts swap per SCENE). Every sweep missed them
because the SC03 scenes we visited run DIFFERENT overlays (124/125/051).

WHY THE EARLIER HUNTS COULD NOT WORK: the index never appears in CODE — it lives in a
per-overlay DATA table, and so does the destination. Both invisible to fleet-wide code
scans. That is the structural reason four value-scans and three payload-side oracles failed.

NOT PROVED: the exact load BASE within the slot (the three differ in size; none observed
loading). The byte-gate arbitrates — onboard at 0x801EF468 and let the first build decide.

New tool: tools/find_addr_refs.py — register-tracked absolute-address search (cookbook 155:
no window-pairing), self-tested against cdFileLocTable, with a STRICT addu-index rule
(full-address match, not page match — 342 loose hits -> 7 real ones).

METHOD: a runtime observation supplied ONE constant, and that made a previously-impossible
static decode trivial. Neither alone sufficed. Pair the oracles, don't choose between them.
2026-08-07 20:41:18 -06:00
Drew T de02dc750c feat(phase-30 S45p6): tools/cdtrace.py — a runtime CD-load oracle; 7 routing-table addresses confirmed live
Three static oracles failed to derive the parked payloads' load addresses this session. The
runtime answer needed NO breakpoints, no Lua (no pcsx.lua wedge hazard) and no GDB stub: the
loader mirrors its whole request in RAM (cdReq_curSector / cdReq_dest), and CdReadRequest's
own MATCHED signature says cdlFile points INTO cdFileLocTable -- so (ptr-0x800AE830)/8 is the
global file index and cdReq_dest is the destination. Both readable from the RAM-dump API we
already had working.

VALIDATED FIRST (R35): cdFileLocTable's live sizes reproduce our extractor's file sizes exactly
for all five parked payloads. Then confirmed 7x against independently byte-proved addresses --
loadDestPtrTable slots [0]/[1]/[3], MAIN/10 (Phase-3 resident), MAIN/3 (S45-p2 md_MAIN_003),
MAIN/12 (the resident's func_800CF94C row), and the LIST.CD bootstrap read from matched C.
This is the R34 second oracle for the whole S44 routing table, which was static-only until now.

FINDING: the script-module slot 0x801EF468 is live and GENERAL. SC03/76 AND SC03/34 both load
there; 34 is outside the SC03/73-79 block, so S45's "chapter-2 period" label described one
tenant, not the slot -- scripts swap PER SCENE.

PRE-REGISTERED HYPOTHESIS (written before the test, kept honest): slot CONFIRMED (it lies inside
SC03/54's independently-derived base window); "chapter-gated" WEAKENED (per-scene, not per-chapter);
trio 0 sightings across 38 load events, 2 saves, multiple SC03 scenes.

NEXT (static, no emulator): 0x801EF468 is now a concrete anchor. Register-track the code that
loads into it and decode its scene->script-index SELECTOR -- answers all three at once instead
of sweeping rooms. The correctly-scoped successor to the four refuted value-scans.

Also lands the attract-cycle load map (.run/attract_loadmap.jsonl): MAIN/7 + MAIN/9 absent
across a complete 304s cycle.
2026-08-07 20:36:04 -06:00
Drew T a0236b2220 docs(phase-30 S45p7): correct the F1 misattribution — the cause was an orphaned reconcile
R14 correction to cookbook 156 + checkpoint p7. I blamed gate_stage's arity pre-pass (F1)
for the 141/213 breakage. That was wrong: no arity journal from the session mentions
func_80146A6C (74/26/4 entries checked) and the arity undo reported success in every log.

The real cause was dedup_propagate --recover leaving an orphaned caller-extern reconcile
(now fixed + proven, commit:1521 / commit:1522). F1 remains real, unguarded, and part of the
remaining Stage-1 work -- it simply did not cause this incident.

Generalizable law added to 156: a tool that deliberately leaves an edit on disk pending an
outcome owes a LEDGER for it. 'Keep it if this succeeds' is half a transaction; the other
half is undoing it on every path that can later invalidate the success, exit paths included.

commit:1519's commit message keeps the wrong attribution (history not rewritten, corrected forward).
2026-08-07 18:51:10 -06:00
Drew T 0d05d91293 docs(phase-30 S45 p7): F1 confirmed live (cookbook 156) + the cheap-tier size cliff (157) + wave_snapshot
- cookbook 156: a FAILED draft can poison the fleet. gate_stage's arity pre-pass writes
  the shared engine_core.h before the gate; a rejected draft's caller-signature edit
  survived and broke 141/213 binaries. Byte-gate held (fail-closed). The trap: a broken
  tree makes every later gate report 'near' -- two batches of verdicts were void, not
  evidence. Standing practice: GATE_NO_ARITY=1, assert 'git status --porcelain
  src/shared config' empty after every batch, recover by revert+replay (deterministic).
- cookbook 157: the cheap-tier size cliff, measured over two controlled waves.
  Haiku 4-27 ins 86% (~44k tok/match); >=50 ins 20% (~177k, 4x worse). The documented
  '<=50' band was optimistic. Agent honesty 63/63 claims true across 100 drafters.
- tools/wave_snapshot.py: immutable sha1-manifested per-wave .s copy, so a running wave
  can no longer block R22's 'make clean'. Coverage-asserting (exit 2 on a missing target),
  negative-control proven.
- docs/concurrency-design.md (Fable5): the lane contract, the false-bank correctness
  argument, and the finding that a worktree verify certifies the COMMIT -- strictly
  stronger than our main-tree R22, which also compiles untracked strays.
- checkpoint p7.
2026-08-07 18:04:26 -06:00
Drew T 0f409249ba chore(phase-30 S45 p6): wave-1 banked 0 — the frontier DEFINITION was the bug; cookbook 155b
HONESTY LEDGER (the wave cost 2.5M tokens and banked nothing; root cause mine):
- I FABRICATED the workflow args: after generating the real target list to
  args_light.json I hand-typed the array instead of reading it, inventing names
  and a descending nins run. ~40 of 50 agents got nonexistent targets. The agents
  refused to fabricate and returned accurate diagnoses -- the prompt's honesty
  rules held perfectly under a bad input.
- I then misdiagnosed it twice with a broken check: corpus.stubs() is keyed by
  INTEGER ADDRESS and I compared string names (always False), producing two
  confident wrong claims. Pool was in fact 160/160 + 166/166 valid. -> cookbook
  155b: check the TYPE your oracle returns; an exactly-0/N result is more often
  a type error than a discovery. R32/R35 assert coverage+correctness of a tool,
  but neither catches an INTERFACE mismatch at the call site.

SOLID: 9 drafts independently re-verified MATCH by re-running match_one myself
(not agent claims); all 9 are genuine INCLUDE_ASM stubs; kept at .run/s45p5/gate1.
They did not bank (0/8 near/1 failed) -- but see the open instrument question.

OPEN (do first): harvest_verify reports 619 live stubs where the single source .c
holds 626 INCLUDE_ASM, and skipped a valid stub. Until explained, the 0-banked
verdict is not evidence about the drafts (R35).

CORRECTED FRONTIER: reach-141 identifies the most-DONE work (shared core, already
DEFINE_ macros ~1,614/binary), not the most valuable. Derive targets from the build
invariant (R33): INCLUDE_ASM in committed source. Big-3 = 1,799 draftable, 1,168
already seeded -- the real II.5 fuel.

Tree restored: gate_stage left 659 files dirty; git checkout -- src/ config/ verified clean.
2026-08-07 16:33:39 -06:00
Drew T 0499c1ec88 docs(phase-30 S45 p5): exclusion proof needs a consumer-side instrument; 4th value-scan refuted
- exclusion_proof.py tried the proven S44 {u32 idx,u32 param} table shape; its R32
  control FAILED (neither known resident table re-found) -> output void per R35.
- STANDING VERDICT: no value/shape-based scan can establish the exclusion. Small
  indices (7,9) are indistinguishable from ordinary data; 4/4 attempts refuted.
  Do not attempt a 5th (cookbook 155a).
- The sound instrument is CONSUMER-side: enumerate every register-tracked reference
  to cdFileLocTable across all 213 binaries, resolve each index source, collect the
  reachable index set. Bounded, but real work.
- Partial: the discriminating indices 231/234 appear in no pair-shaped table fleet-wide.
2026-08-07 16:08:08 -06:00
Drew T 0bd334c30d docs(phase-30 S45 p5): MAIN/7+9 identified as the OPDEMO modules; 3 base oracles refuted; the event-module region is runtime-allocated
- MAIN/7 (id 0x3A) and MAIN/9 (id 0x2D) carry 'C:\TIMPACK\OPDEMO0.PAT' /
  'OPDEMO1.PAT' path strings -> they are the OPENING/ATTRACT-DEMO modules. S45 p2
  checked 'OPENING' negative, so the live target is attract-mode (idle at title),
  a different state. Turns a blind search into a targeted capture.
- THREE payload-side base oracles built and ALL refuted by their own controls
  (R32/R35 assertions did their job; none of their answers were used):
    derive_base  0/4  -- 'code follows the table' is false (MAIN/34: 0x208 gap)
    vote_base    4/12 -- calls are outward + MIPS leaf fns have no prologue
    vote_base2   0/4  -- self-jals 0/N: there are NO internal jal calls at all
  The third is structural: a module's bytes do NOT encode its base, because its
  functions are reached indirectly via the header pointer table (jalr), not jal.
- The one real constraint: SC03/54's 19 header pointers (0x801EF718..0x801EFEE8)
  confine its base to [0x801EDED0..0x801EF6C8]. That window lies INSIDE SC02/9's
  span (0x801E4C60+70784=0x801F60E0) -> SC02/9 + the SC03 trio are mutually
  exclusive event modules sharing a ~0x801Exxxx region at DIFFERENT bases.
- => event-module destinations are per-scene/runtime-allocated, not a static slot.
  This explains the empty resourceIdMap branch and why the emulator resolved SC02/9.
  The CD-read tracer stays the correct instrument (R11 + Drew).
2026-08-07 15:45:56 -06:00
Drew T a3976d73e5 docs(phase-30 S45 p5): the resourceIdMap branch is REFUTED for all 5 parked payloads
- resourceIdMap @0x80063138 decoded from the EXE using the index math in our OWN
  matched C (ResourceGetCdLoc is byte-exact): exactly 162 6-byte records, 2 negative
  non-CD sentinels, streamIds >=0x100 -- self-consistent with the C in every field.
- FINDING: its 98 distinct global indices include NONE of gi 7/9/231/232/234, so the
  five parked payloads cannot reach ResourceGetCdLoc/StreamLoadStateMachine/D_80068B60.
  The S44 'descriptor path' branch of the parked-dest disjunction is refuted; only the
  per-overlay IDXTAB/DESTPTR route survives.
- R34 corroboration: loadDestPtrTable's 5 u32s re-derived independently and reproduce
  the S44 table exactly (0x800CEDF8/0x80128158/0x800CAE08/0x800CCB1C/0x800C7F08).
- R14 CORRECTION to S44: 'IDXTAB ... same list fleet-wide' is wrong. The 37-entry list
  at 0x8017EEC8 is real for ov_SC01_000 only; 140 of 141 overlays hold unrelated bytes
  there. IDXTAB is per-overlay data at a per-overlay address; only the mechanism is shared.
- NEGATIVE TOOLING RESULT (cookbook 155a): a shape-only IDXTAB scan passes its R32
  coverage assertion and is still non-discriminating (664 'tables'; hits are (offset,count)
  pair data). Coverage != discrimination -- two different oracles (R34). Recorded so it
  is not repeated; next instrument is a register-tracked decode of func_80128CFC (155).
2026-08-07 15:34:13 -06:00
Drew T 7e9394f691 fix(phase-30 S45 p4): R14 correction — the MAIN/7/SC03-trio 'loader fn' leads were scanner phantoms
- the quick hi/lo sweep paired lui/lo16 WITHOUT tracking base registers -> phantom refs
  (0x800AE868 read where the true target was 0x8018E868); register-tracked rescan: the ONLY
  literal loc-table ref fleet-wide is SC02/9's (solved)
- standing truth: MAIN/7, MAIN/9, SC03/53/54/56 all load via table-INDEXED paths; homework
  respecified (descriptor-data hunt + ResourceGetCdLoc/StreamLoad index math)
- fn 0x80161E08's real gate: currentLocationId vs {0x3012,0x3054,0x3079,0x3096} — the
  'variable 0x800C3054' never existed; cookbook §155 (track the register)
2026-08-07 15:13:50 -06:00
Drew T 788f33d523 feat(phase-30 S45 L3-p3): SC02/9 = the Steam Knight boss module — decoded, captured, retro-verified, onboarded; parked = 5
- the gate DECODED from matched C (func_8012832C case 0x300E -> func_80128998 -> streaming
  API with &cdFileLocTable[144]) -> scene arithmetic named the 1ST-BOSS arena -> ONE targeted
  load captured it at 0x801E4C60
- RETRO-VERIFIED: Phase-3's dumps/ram_castle.bin (2026-06-14) holds it at the SAME address,
  same 6,764-B exact prefix — R10 two independent datapoints two months apart;
  bossHp_SteamKnight (0x801E4398) lives inside this module's image
- onboarded md_SC02_009 (id 0x3E, TLO 0x4): BYTE-IDENTICAL first build; fleet 213;
  R22 213/213; tools-health OK; audit-disc UNCLAIMED 6 -> 5, residue 0
- the last 5 (MAIN/7, MAIN/9, SC03/53/54/56) reclassified emulator->STATIC-RE targets with
  decoded leads (memory-map §S45 p3); loc-id map appended to docs/debug-menu-list.txt
- negatives banked: pause menu, memory-box prompt, new-game intro, high/low game, Minku
  spawn (slot-A actor 0x15 = md_MAIN_015 candidate naming)
2026-08-07 15:07:55 -06:00
Drew T fa7b9d4c71 feat(phase-30 S45 L3): the emulator tour — all 28 script modules + MAIN/3 onboarded; fleet 212, R22 212/212
- THE TOUR (Drew driving the retail debug menu; mode-7 hammer over the Redux web API):
  all 28 script modules captured live at four byte-verified per-chapter slots
  (SC03/73-79 @0x801EF468 ch2-period, SC03/132-138 @0x801E25E8 ch3, SC04/24-30
  @0x801E7B28, SC05/23-29 @0x801ED988); the routing law: debug-menu AREA selects the
  chapter, each CITY interior streams its own module (member k <-> interior k).
  md_MAIN_011/DISELECT byte-proven 24,236/24,240 in RAM; slots A/B/boot R34-verified live.
- MAIN/3 DISCOVERED: the main-menu module (id 0x39, 121,884 B), mis-bucketed as data by
  BOTH audit oracles; live byte-proven @0x800CEDF8 (42,632-B exact prefix); onboarded.
- 29 onboardings BYTE-IDENTICAL on first build -> fleet 212; R22 212/212 after three
  md_MAIN_003 catches: the A4 DsMix leak; an extract-order-sensitive splat boundary
  (bytes: a 1-word data sentinel in .text + fn at +4 -> pinned in symbols file);
  corpus.stubs now treats D_*/jtbl_* INCLUDE_ASM as blob includes (mirrors progress.py)
- module-id census (offline, disc-wide): 77 id-law code payloads, 0 further misses;
  SC03/55 = confirmed DATA. audit-disc: UNCLAIMED 34 -> 6, residue 0 — the 6 carry
  byte-checked negative evidence; next tier = the CD-read tracer
- docs: memory-map §S45 (slots + routing + debug-menu ops), disc-completeness S45
  addendum, decision-log R31 entry, docs/debug-menu-list.txt (Drew's transcription)
- .run/s45 evidence allowlisted (tour logs/scripts/rosters); 104 ram dumps LOCAL-ONLY
- new baseline: 93.8% instr / 95.68% fn / 87.2% distinct over 212
2026-08-07 14:03:51 -06:00
Drew T 14b115d8ba docs(phase-30 S45 II.3): metrics re-baseline + roadmap contract delta + decision-log (R31)
- roadmap §1.1: 183 onboarded binaries; the 100% claim's exclusion list = the 34-row
  parked-for-L3 ledger (28 script + SC02/9 + MAIN/7/9 + SC03/53/54/56 — 3 rows S44 never
  tiered); supersedes the '39 type-1 backlog' framing (43 of them now build byte-identical)
- disc-completeness.md S45 section: what landed, the full parked list, the L3 resolution path
- decision-log: the S45 entry — five instrument findings a 'mechanical' batch surfaced, each
  negative-control-proven; honest baseline 94.0% instr / 95.96% fn / 87.6% distinct over 183
2026-08-06 13:36:34 -06:00