Commit Graph

786 Commits

Author SHA1 Message Date
Drew T 001d8e2127 docs(phase-31): cookbook §186 — cross-jumping runs after sched2 (no barrier reaches it); s16-locals frame signal; local_alloc-vs-global_alloc as a placement lever 2026-08-17 01:02:31 -06:00
Drew T a670f9d24d docs(phase-31): cookbook §184 (comment-blindness as a defect class) + §185 (verify-cheap-side; check a TU retype at its use sites) 2026-08-16 22:54:35 -06:00
Drew T bbd8a6c8e4 feat(phase-31): pregate_check sees brace-bodied externs (the D_80072780 clash that cost a rebuild); §183 addendum 2026-08-16 22:41:01 -06:00
Drew T b15d195cc0 docs(phase-31): cookbook §183 — the declaration-reconciliation playbook, the name/shape trap, and why &D_x defeats the cast escape hatch 2026-08-16 22:39:34 -06:00
Drew T 0ceba4f8ee chore(phase-31): fleet progress report after S53 banks 2026-08-16 21:08:05 -06:00
Drew T fdbc522cf2 chore(phase-31): regenerated family/backlog reports after the S53 atlas + banks 2026-08-16 21:08:00 -06:00
Drew T adfa7185c9 docs+tools(phase-31): cookbook §180d/§181/§182; fragment_check gains the mirror test (5.7% of main stubs); pregate_check scans masked text 2026-08-16 21:07:03 -06:00
Drew T 472ff5806a feat(phase-31): tools/scan_leftovers.py — re-verify unbanked drafts (found 37 free MATCHes / 3,240 ins); cookbook §180 2026-08-16 18:11:32 -06:00
Drew T bc669d5407 chore(phase-31): S53 preflight — atlas regen, leftover-draft harvest (34 free MATCHes found), wave R launched 2026-08-16 18:08:46 -06:00
Drew T f8bf50d8c0 docs(phase-31): cookbook §179 — eight idioms mined from the wave P/Q journals (S52 harvest)
12 reader agents over 172 substantial agent findings from waves P and Q; 16 survived their novelty
filter; merging duplicates and dropping what §174-§178 already own left EIGHT levers. The
synthesizer re-read every gcc/maspsx/masked_diff citation and corrected three wrong line numbers
inline; I independently re-verified two of them (loop.c:3500 `src = SET_SRC (bl->init_set)`,
valid_initial_value_p at :3509, bl->initial_value at :3511; and maspsx's tab-literal `.set\t` test
at __init__.py:844-848) -- both exact.

  A. A loop-walked pointer PARAMETER hands its argument register to the giv (9 byte-proofs).
     record_initial records assign_parms' own incoming-argument copy as the biv's init_set, so
     emit_iv_add_mult re-references the HARD register in the preheader, extending $aN's live range
     and costing the parameter its hard-reg tie. Fix: body-local copy, or an identity re-tie whose
     ASM_OPERANDS SET_SRC makes valid_initial_value_p refuse. Explicitly paired with §70, which
     documents the SAME chain used in the opposite direction.
  B. The hand-written-asm transcription checklist (10 byte-proofs): `.set` needs a literal TAB or
     maspsx never updates is_reorder and re-nops every branch; `.ent` does not update it either;
     displacements must be DECIMAL (bare int() before the range check); maspsx's LOAD-delay nop is
     UNCONDITIONAL, so you manage branch-delay nops and must NOT manage load-delay ones; internal
     labels need a `.L` prefix or masked_diff truncates the function at the stray symtab entry.
     Also flags a real CONFLICT with the banked trampoline rules and gives the A/B to resolve it.
  C-H. No-epilogue functions must be file-scope __asm__; gte_stflg must clobber $12; a
     >2*MAX_MOVE_BYTES copy is a struct assignment; pinning a walked pointer disables strength
     reduction entirely; a pin can CREATE a combine LOG_LINK (n=1, marked as such); a mid-body
     .global pair slices a byte-comparable fragment.

Ends with a "considered and NOT banked" list -- including a softened claim where the reader's
derivation was not traced line-by-line, and a corrected symbol typo. Nothing silently dropped.
Cookbook 554 -> 564 sections.
2026-08-16 17:40:06 -06:00
Drew T 49fc465a51 docs(phase-31): cookbook §178 + §176j-2 + §176k — mine the wave-P journals, the repair-pass yield, two selector bugs
§178 — SIX LEVERS FROM THE WAVE-P JOURNALS, each byte-proven and source-cited. Four wave-P repair
agents REFUTED the first pass's own diagnosis by dumping cc1 -dS/-da and reading gcc-2.7.2. The
meta-finding leads the section: "REGALLOC-PERM" is this project's most over-diagnosed class -- in
four functions the symptom was a register swap and the cause was in cse.c or sched.c, decided
BEFORE allocation, which is exactly why pins and statement order all failed.
  A. The $0-add OPAQUE COPY defeats cse.c:826 make_regs_eqv (a PLUS is not a (set reg reg)), so the
     parm pseudo keeps its register. MATCH on first compile; 3 of 5 pins then became dead weight.
  B. A `return <const>` is a priority-1 hard-reg set that the BACKWARD list scheduler places FIRST
     in the block, making hard $v0 live across a temp's range. Lever: goto a shared return tail.
  C. birthing_insn_p (sched.c:2469) boosts only single-set destinations; splitting a 3-set temp
     boosts the insn and drags its feeder chain down.
  D. NEW IDIOM: a NARROW destination type blocks copy elision (SI->HI cannot be coalesced), so the
     copy survives at its source position -- one type change worth ~20 instructions.
  E. The ZERO-OFFSET ALIAS HOLE: memrefs_conflict_p's find_symbolic_term path is only reachable for
     offset-0 fields, so an offset-0 store silently loses its dependence and floats.
  F. MEM_IN_STRUCT_P asymmetry in true_dependence (sched.c:817): struct-varying vs scalar-fixed do
     not depend. Struct-vs-scalar externs are a scheduling decision, not cosmetics.
  G. Two modelling traps: `sw $a1,SYM($a0)` is ONE cc1 insn (the lui/addu/store triple is gas -G0
     macro expansion, not cc1 output); and __asm__ __volatile__ with a memory clobber is a FULL
     barrier that also sinks address chains.
Plus the exhaustion result: 2,240- and 5,040-variant statement-order sweeps moved nothing, because
the schedule was DAG-determined. When order does not matter, look for an alias or set-count
property, not a permutation.

§176j-2 — THE REPAIR PASS, MEASURED: 12 of 39 recovered / 579 ins, taking wave Q from 51 matches
(3,631 ins) to 64 (4,245). Closeness must be COUNTED, not read off the first differing index (my
first measurement reported six "closeness 0" drafts that were actually truncated).

§176k — two silent selector bugs: ranking gate groups by MEMBER COUNT collapses a wide band to the
smallest functions when the gate cost is per-slate (60 cards/2,604 ins chosen where 46/4,829 were
available); and a selector that globs its own output counts the previous attempt as spent (pool
106 -> 46). Any derive-from-disk rule must exclude the artifact it is about to produce.
2026-08-16 14:23:19 -06:00
Drew T 4adb559a29 docs(phase-31): cookbook §177 — the epilogue return-delay slot is decided by the SAVED-REGISTER SET
Eleven wave-Q functions in 800c/800c3 sat at closeness 1-3 with the same epilogue residual, and
every agent independently filed it as intrinsic ("epilogue-delay-slot-unfillable", "gcc/maspsx
structural wall"). It is neither intrinsic nor a scheduling problem.

Source-confirmed at gcc-2.7.2/config/mips/mips.c:5376 --

  int mips_epilogue_delay_slots () {
    if (current_frame_info.total_size == 0) return 1;                        /* no frame  */
    if (current_frame_info.mask == RA_MASK && current_frame_info.fmask == 0) return 1;  /* only $ra */
    return 0;
  }

gcc offers the epilogue a delay slot ONLY when the function allocates no stack, or saves nothing
but $ra. Otherwise the slot is never offered to the scheduler and the emitter puts the stack
restore there instead (mips.c:5276, the tsize > 0 path).

So the lever is the CALLEE-SAVED SET, steerable from C: the first value whose live range spans a
jal costs an $s register and flips the switch. To gain a filled slot, hold nothing across a call
(recompute or re-read after it); to lose one, hoist a load above the call. Register pins are the
WRONG tool here -- §176-C already established a pin cannot schedule across a call.

~600 instructions were three instructions from banked and about to be written off. The meta-lesson
(R17): when N independent agents call one residual "structural", read the compiler -- the answer
was forty lines of mips.c already sitting in tools/reference/gcc-2.7.2/.
2026-08-16 14:17:09 -06:00
Drew T b021812c17 docs(phase-31): cookbook §176i/§176j — the pre-gate check's real boundary, and the cost of stopping a wave
§176i — WHAT A STATIC PRE-GATE CHECK CAN AND CANNOT PROVE. pregate_check validated wave Q's slate
as clean in 0.7s (the first slate all session to reach the gate pre-validated) and the build then
failed twice, both times outside what any text-only check can see:
  1. LINK-time undefined reference: `.L80050F24` lives INSIDE gfx2D_BG0_OBJ_698 and another
     function's .s branches to it -- converting a function to C deletes the local labels its
     neighbours jump to. Statically checkable, but from the .s files, not the .c: scan every other
     .s for label references landing inside a candidate's address range. Worth building.
  2. BYTE mismatch: with the link fixed the binary BUILT and the SHA differed -- the §174 law 1c
     class, which reloc_identity had already named six suspects for.
The division of labour to rely on: text checker for SHAPE, reloc oracle for IDENTITY, gate for
TRUTH. A clean pre-gate is a licence to build, not a prediction of success -- and when the binary
builds but the hash differs, BISECT, because it costs wall-clock and zero tokens.

§176j — STOPPING A WAVE MID-FLIGHT COSTS THE IN-FLIGHT TAIL. Wave Q stopped early: 51/90 verified
(3,631 of 6,249 ins) versus the 96-97% the same pipeline yields when allowed to finish. The loss is
SUSPENDED, not destroyed -- every draft persists on disk, 15 of the 39 unfinished sit at closeness
<=10. Do NOT resume the workflow to recover it (resume re-runs unfinished agents from scratch at
full cost); use a REPAIR-ONLY pass over the <=30 band instead. Decision rule: before killing a long
agent run, price the tail -- stopping converts near-matches into "needs a cheaper second pass",
which is a deferral, not a saving.
2026-08-16 10:02:22 -06:00
Drew T 74a95af4c1 docs+fix(phase-31): reconcile BEFORE the first gate (§176h.C2); pregate duplicate-typedef fix
MEASURED, and it inverts the obvious plan. "Bank the clean drafts now, recover the conflicted ones
later" is backwards: of 18 wave-O/P drafts parked and re-verified still MATCH, only 1 survived
resolve_conflicts once their wave had banked -- versus 5 before it.

The mechanism: a banked draft's declarations BECOME the TU's, so every parked draft that merely
disagreed with a SIBLING now disagrees with the FILE, which is the stricter arbiter (a sibling
clash can be settled by editing either side; a file clash only by editing the draft, and some
cannot be settled at all because gate_main reverts src/ before every build). Worse, the auto-rename
that reconciles a cosmetic clash pre-bank becomes a DUPLICATE TYPEDEF post-bank, because the name
it renames to is now defined in the file.

So iterate the dry run to `N -> N compatible, 0 dropped` BEFORE spending the first rebuild, and
budget reconciliation into the wave rather than after it.

pregate_check: DUPLICATE-TYPEDEF now fires on ANY redefinition, not only differing bodies. C89 has
no compatible-redefinition allowance for typedefs, and my first version missed exactly the case the
tool exists for -- two identical `OtBlk_80016450` definitions, which the compiler rejected on the
next rebuild. Measured, not reasoned.

Also banks the auto-reconciler's rule: tell a COSMETIC clash from a REAL one by comparing struct
BODIES, not names. OtBlk_80015498 vs OtBlk_80016450 are the same {s32 a; s32 b[4];} and rename
byte-identically (both re-verified MATCH); Elem12 vs B12 genuinely differ and were refused.
2026-08-15 22:11:06 -06:00
Drew T 071ce43e1c docs(phase-31): cookbook §176h — the batch-substitution hazard map (S52)
Wave P drafted at 97% and then cost a dozen clean rebuilds to bank, and not one of those rebuilds
failed on a matching problem. Banks the whole failure surface:

A. The SEVEN under-reporting holes in gate_main, all the same shape (R32): the checker never read
   the destination TU, shared headers, a draft's own definition, lines with trailing comments,
   typedef aliases, the build's own error text, or file order. Law: audit a batch-integration tool
   for what it DOESN'T look at -- its verdicts can be correct on the inputs it reads and still be
   worthless, because the compiler reads more.

B. Typedef handling, with the two wrong strategies that both look right: blanket STRIP (assumes
   the surviving definition sits above the insertion point -- src/800.c defines Rec14 at 7336
   while stubs wanting it sit at 7272), blanket RENAME (breaks drafts sharing an identical
   typedef, because their externs stop agreeing -- my regression, three drafts at once), and the
   rescan loop that deletes the definition it just renamed. The survivor is body-aware +
   position-aware in a single pass over a snapshot.

C. The remaining limit: conflict detection compares spelled type NAMES, so three drafts each
   defining their own Slot54 with different layouts all declare func_80032A74(Slot54*) and compare
   equal. Comparing struct LAYOUTS is the real fix.

D. The measured cost shape -- drafting cheap and solved, integration expensive -- and therefore the
   next lever: a STATIC pre-gate check over the substituted text, no make at all. Plus the R39
   lesson that negative controls apply to the tool you are FIXING, not just the one you ship.
2026-08-15 21:59:52 -06:00
Drew T 0753641d4b feat(phase-31): adopt the 6k-instruction wave doctrine + --target-ins (Drew, 2026-08-15)
A wave is now sized by INSTRUCTION MASS, not card count. The metric is instruction-weighted, so a
wave is worth what its instructions are worth: the 12-42-ins card lanes carried ~1,400 ins/wave
(~0.011pp, ~440 waves to finish) while wave O carried 6,266 ins at the same gate cost and the same
draft rate.

build_wave_atlas --target-ins draws cards until the instruction budget is met (still capped by n)
and refuses to under-fill silently. Standard recipe: --target-ins 6500 --min-ins 60 --max-ins 200
--max-bins 4, levers now including UNKNOWN.

THE MEASUREMENT BEHIND IT: draft rate barely decays with size -- wave M 98% at avg 51 ins, wave N
92% at avg 65, wave O 96% at avg 128. Mass is nearly free.

THE UNKNOWN UNLOCK: UNKNOWN is not a difficulty label, it means the atlas could not name a lever,
and it had been routed as needing its own bespoke lane. Wave O's 22-card R37 probe drafted it like
any other lane -- reclassifying ~138k ins (a quarter of everything open) as ordinary wave fuel.
With UNKNOWN in, 9,224 fns / 417,325 ins = 70% of all open instructions are agent-draftable; the
60-200-ins mass band alone is 164,357 ins ~= 27 waves, and is the band to work first.

Also banks the five-step PRE-GATE PROTOCOL (independent re-verify -> reloc_identity -> dry-run to
0-dropped -> reconcile declarations toward the form the match needs -> gate), cookbook §176g.
2026-08-15 14:05:15 -06:00
Drew T 279037ece6 docs(phase-31): cookbook §176f — the declaration FORM is a matching lever; reconcile toward the form the match needs (S52)
Wave O: six drafts in one TU referenced D_80078D88, three declaring it scalar and three as an
array. One draft's own comment explained why the array form is load-bearing: with a scalar decl the
global load is a plain symbol_ref and sched1 HOISTS the lui/lw above a store; declaring it as an
array makes gcc-2.7.2 alias.c treat the access as possibly-aliasing and the hoist stops.

So §176b/§176d's 'pick one form and cast at the use site' is wrong for a scalar/array clash. Array
is the STRONGER form -- scalar users adopt it for free by indexing [0] (byte-verified on all three)
-- while forcing an array user to scalar can re-enable the hoist and break the match. Reconciling
toward the array form took the slate from 42 -> 37 compatible (5 dropped) to 42/42, every converted
draft re-verified MATCH. Waves J/K/L each lost 5-10 drafts to the greedy keep-first rule.
2026-08-15 11:16:43 -06:00
Drew T 965ae3902e measure(phase-31): the AGREE re-gate lane is a 5% null — symbol verification does not rescue stored drafts (S52-12)
R37 probe: 20 shape-verified AND symbol-verified stored drafts, 5 gate groups -> 1 banked (5%),
statistically the same as the project's A10 stored-verdict law (~0-8%; T1 measured 0/23 on the same
kind of pile earlier this phase). The null is the finding: a stored draft's rejection is almost
never symbol identity, it is TU plumbing (§176d) or staleness. reloc_identity's real home is a
PRE-GATE check on FRESH drafts, not a backlog resurrection tool. The remaining 30 groups are not
worth 30 rebuilds -- lane closed rather than pursued because the tooling was new and interesting.

Also names the SYMBOL-COLLAPSE class in the fixer's refusal (one draft extern standing in for N
distinct globals; a textual rename moves every occurrence together, so it needs one extern per
site) and records the R38 self-note: the 0/23 prior was already in the phase log.
2026-08-15 09:50:48 -06:00
Drew T 0487c0c627 docs(phase-31): cookbook §176e — symbol identity is COMPUTABLE offline, plus reloc_identity --fix (S52)
§174 law 1c recorded match_one's relocation blindness as a caution to the reader ('check every
symbol by hand after MATCH'). It is a computation, not a human's job. Banks the arithmetic, the two
failure shapes it separates (uniform-delta stale seed symbols vs wrong field offset), the four
traps that bit me building it (splat-derived names absent from the symbol files; MIPS o32 REL keeps
the addend in the instruction; index alignment is a precondition; a nearest-symbol label needs a
tight window), and the honest limit measured the same session: symbol-verified + shape-verified is
still NOT sufficient for a bank -- the first re-gate group of five such drafts banked 0/5, because
what remains is TU plumbing (§176d), not identity.

--fix rewrites only unambiguously-wrong symbols (every mismatch naming a symbol must imply the SAME
corrected base) and refuses otherwise: 10 of 12 repaired, 2 correctly refused.
2026-08-15 09:46:10 -06:00
Drew T 7cbaf1ce97 docs(phase-31): cookbook §176d — seed the conflict table from the TU, key it per file, and cast the callee through a function pointer
The wave-J/K/L draft recovery (S52) showed §176b was under-scoped: it made batched drafts agree
with each other and forgot the file they land in. Banks (a) TU-seeded conflict detection and its
iterative behaviour, (b) per-destination-file keying, and (c) the new recovery variant for a callee
the TU prototypes as (void) while your call must pass an argument. All 11 recovered drafts
re-verified MATCH after repair; none needed a codegen change.
2026-08-15 09:36:12 -06:00
Drew T 683c44e15b chore(phase-31): regenerate docs/progress.md digest; move a stray 89KB agent-notes dump out of the repo root into .run/ (R12) 2026-08-15 09:09:50 -06:00
Drew T e0dee637b1 docs(phase-31): cookbook §176 — 7 levers mined from all 14 overnight wave journals (26 novel of 81)
Harvested by a 15-agent workflow over every wave's journal.jsonl (where the long analyses live —
notifications truncate them), each cross-checked against the existing cookbook + gcc-2.7.2-map
before being called novel, then synthesized by residual CLASS rather than by function.

- §176-A STATEMENT ORDER AROUND A CALL is the first thing to check for any schedule/delay-slot/
  ±1-length residual. fill_simple_delay_slots backward-scans and never hoists an instruction
  emitted AFTER a call into that call's slot. The arg-register tell: a delay-slot store whose
  address goes through that call's own arg reg PROVES the statement sits before the call.
  func_80186764 7/92-off + pins -> MATCH 92/92 by moving one statement (no pin needed);
  func_80188528 41/102-off, filed 'irreducible tie-break, permuter fuel' -> MATCH 102/102.
- §176-B a small REGALLOC-PERM is usually NOT allocation. B1: a narrow global that is really
  wide_sym+2 must be expressed through the wide object (asm-label alias) or the disambiguator
  sees no dependency; func_80185548 MATCH 77, verified with a full HI16/LO16+R_MIPS_26 resolve
  oracle. B2: pin the short-lived INTERLOPER out of the way, not the contested value;
  func_8018CA74 MATCH 63/63 with a register-choice sweep confirming the mechanism.
- §176-C 🔴 WALL REFUTATION, and I verified the source myself: gcc-2.7.2 sched.c:1704 tests
  call_used_regs[i] where every neighbouring line uses regno+i, so for any 1-word register the
  test is always call_used_regs[0] (, call-used on MIPS). EVERY hard-reg SET in a block
  therefore gets a REG_DEP_ANTI on the last call, while the pseudo arm (sched.c:1732) is guarded
  by reg_n_calls_crossed. A PIN CANNOT SCHEDULE AROUND A CALL — sometimes the correct move is to
  UNPIN. Refutes the universality of sched.md S11 step 1 and the 'always try pins' reflex.
- plus §176-D (CSE levers in reverse), §176-E (two cc1-probed spellings), §176-F (four residual
  verdicts that were lying).
- the section ends with an explicit 'What is NOT banked here' listing 7 mined items judged too
  thin — including two whose functions are still INCLUDE_ASM (lever unverifiable) and one whose
  narrative CONTRADICTS the banked C. Recorded so they are not silently lost.
2026-08-15 09:09:09 -06:00
Drew T a0296c262e docs(phase-31): cookbook §176a/b/c — the verification-layer laws, batch-gating mechanics, main clean-rebuild
Banking the PROCESS idioms this session produced, which were sitting only in commit messages,
tool docstrings and the wave prompt — none of which a future session reads.

- §176a VERIFICATION-LAYER LAWS: match_one verifies SHAPE not SYMBOL IDENTITY (masks
  jal/HI16/LO16 — a wrong callee or wrong global reports MATCH; func_8002A234 cost 5 gate
  attempts); a detector is ADVISORY and the gate is the ARBITER (3 wave-G drafts withheld on
  symfix flags all banked unchanged); a verifier that can pass WITHOUT BUILDING is worse than
  none (stale-binary false pass); an all-zeros gate result is a NULL not a finding; and the
  general rule — before believing a measurement, run the control that would make it FAIL.
- §176b BATCH-GATING MECHANICS: gate cost scales with (binary,TU) GROUPS not drafts; batched
  drafts must agree with EACH OTHER (type conflicts, duplicate typedefs); compatibility compares
  TYPE SIGNATURES ONLY but the declarator suffix matters (too-strict and too-coarse both bit me);
  conflict-dropped drafts are recoverable via cast-at-use; a COMPILE error names its own culprit
  so only a BYTE mismatch needs bisection.
- §176c MAIN CANNOT BE GATED INCREMENTALLY — psyq_integrate/ld_interleave rewrite the .ld;
  byte-proven both ways including with NO draft substituted. Use tools/gate_main.py.

Agent-discovered matching idioms are being mined from all 14 wave journals in parallel and land
next as §176.
2026-08-15 08:53:52 -06:00
Drew T 56fafb0234 feat(phase-31): wave N — 42 banked (largest band, avg 65 ins), R22 213/213; overnight campaign closed
- 48 atlas mass cards on ov_SC02_000 with --min-ins 40: 45/48 shape-verified, 42 banked,
  ONE gate group. stubs 11,549 -> 11,477. distinct-code 90.4%.
- the band question is answered: 94% draft at avg 65 ins (up to 119), after 98% at avg 51 in
  wave M. The mass lane is NOT size-limited in the band the instruction-weighted metric tracks.
- 2 NEARs enqueued with unusually deep analyses, both reusable beyond their own functions:
  * func_80189C6C (close=2): magic 0x66666667 + mfhi-shift 5 DECODES to a plain /80 — write
    '(x<<12)/80' and let gcc synthesize its own magic multiply. Residual root-caused against
    REAL cc1 -da RTL dumps to loop.c move_movables desirability (threshold 29 vs measured
    insn_count 24-26). Matches the func_80015A74 hard-tail class.
  * func_80185840 (close=3): 'register u32 zr __asm__("$0"); c = val + zr;' reproduces the
    non-coalescing addu-zero copy that cookbook §52a had classified as a WALL; plus 'r = K;'
    before a SINGLE-armed if is what lets reorg's backward scan steal the li into the delay
    slot (any two-arm spelling needs the eager target-thread steal, which never fires).
2026-08-15 08:12:28 -06:00
Drew T 40ee96738d feat(phase-31): wave M — 40 banked (overlay mass lane, larger band), R22 213/213
- 44 atlas mass cards on ov_SC04_011, avg 51 ins (up to 112) -> 43/44 shape-verified,
  40 banked, ONE gate group. stubs 11,589 -> 11,549.
- data point that matters for the endgame: the mass lane holds at ~98% draft on the LARGER
  band (51 avg vs the 12-42 cousins the night started with). Since the public metric is
  instruction-weighted, that is the band that moves it — and it is in reach of haiku/sonnet,
  not only the frontier tier.
- 1 near enqueued (func_80188A30, close=9: gcc reorders a beqz + delay-slot nop; core logic
  verified correct) as grinder fuel.
2026-08-15 06:51:03 -06:00
Drew T a852982105 feat(phase-31): wave L — 42 MAIN functions banked, R22 213/213 (main 133 -> 175)
- 44 atlas mass cards -> 44/44 shape-verified, 42 banked (2 dropped: a duplicate SVECTOR
  typedef and a u8[] vs char[] decl conflict). main stubs 955 -> 913. fleet stubs -> 11,589.
- first wave carrying law 1c (match_one masks relocations => verifies SHAPE not SYMBOL
  IDENTITY; re-check every symbol against the target .s relocation lines after MATCH).
- the compile-error shortcut paid for itself: named 'SVECTOR at src/800.c:94' and the exact
  draft in seconds, where the old bisect path burned 28 minutes producing nothing.
- KNOWN NEXT IMPROVEMENT: gate_main should strip duplicate typedefs on substitution the way
  harvest_verify already does — src/800.c carries a local SVECTOR from a previously banked
  function, so any later draft defining its own collides. Mechanical, recurring, cheap.
2026-08-15 06:02:18 -06:00
Drew T cf36cf6f21 feat(phase-31): wave K — 41 MAIN functions banked, R22 213/213 (main 38 -> 79)
- 44 atlas mass cards on main -> 44/44 standalone, 41 banked after 3 in-TU decl-conflict drops.
  gate_main clean rebuild -> 143dbb89 BYTE-IDENTICAL, then full-fleet R22 213/213.
  main stubs 996 -> 955; main REAL 92 -> 133 (incl. propagated/dedup credit).
- took 5 attempts; each exposed a real defect, the last one substantive:
  * conflict checker too coarse (u8 D_x == u8 D_x[])            -> fixed + NC'd
  * my pkill pattern matched its own shell                       -> stop shell process-matching
  * FALSE PASS: sha() read a stale binary when the build failed  -> rm output + check returncode
  * bisect burned clean rebuilds; the compiler names the culprit -> read the error instead
  * THE REAL BUG: func_8002A234 stored to the WRONG GLOBALS (v1->D_80078EE8/0->D_80078EE4,
    target is the reverse). 2 bytes, both at %lo relocation offsets.
- STANDING CAVEAT (write this into the wave prompt): match_one MASKS jal/HI16/LO16, so it
  verifies INSTRUCTION SHAPE, NOT SYMBOL IDENTITY. A draft that calls the wrong function or
  stores to the wrong global passes standalone every time. Only the whole-binary gate sees it
  — same class as the PsyQ symbol-name errors in waves F/G.
2026-08-15 05:35:59 -06:00
Drew T b8dbf6f6a7 feat(phase-31): wave J — 34 MAIN functions banked (main 4 -> 38), R22 213/213
- first full wave against the main EXE: 40 atlas mass cards -> 39/40 standalone (98%), ALL haiku.
  main drafts exactly like an overlay; the only special handling is the gate path.
- gated via the clean-rebuild batch path: substitute -> make extract BINARY=main -> make build
  BINARY=main -> 143dbb89 BYTE-IDENTICAL; then full-fleet R22 213/213. main stubs 1030 -> 996.
- NEW CLASS: in-TU cross-draft declaration conflicts. Batching N drafts into ONE .c means their
  externs must agree with EACH OTHER (D_800A4ED4 s16-vs-u16; func_8001C9D0 void/void*/s32).
  Resolved greedily (keep-in-order, drop incompatible) at a cost of 5 recoverable drafts.
- the recovery lever, proven on func_80037368: adopt the shared header's decl VERBATIM
  (extern u8 D_80076251;) and adapt at the USE site ((&D_80076251)[i]) instead of redeclaring.
- NOTE on my own tooling: my first conflict detector compared parameter NAMES and wrongly
  dropped 2 good drafts ((s32 *_) vs (s32 *)); comparing type signatures only recovered them.
  Second time tonight a refusal check of mine discarded good work (R39).
2026-08-15 03:57:50 -06:00
Drew T 61806c8a31 chore(phase-31): checkpoint — main open (4 banked), wave I 44/44, tooling debt logged; wave J (main) in flight 2026-08-15 03:33:16 -06:00
Drew T 6d09d35b6d feat(phase-31): wave H — 34 banked (1 gate group); cookbook §175 caller-saved pin hazard
- wave H: 40 atlas mass cards on ov_SC02_005 -> 38/40 standalone (95%), 34 banked, ONE gate
  group. R22 213/213. stubs 11,788 -> 11,751. fleet 95.4%.
- §175 (NEW): a register pin to a CALLER-SAVED reg is not a scheduling hint, it changes program
  meaning. func_80182EB0: value written before a jal and read after it; the $2 pin let gcc treat
  the pre-call store as dead across the call and SILENTLY DELETE addiu v0,zero,-1 (49 vs 50 ins),
  post-call read = garbage. Fix was to DROP the pin and kill the cross-call live range in C.
  Rule: never pin a caller-saved reg to a value whose live range crosses a jal — use a
  callee-saved $s0-$s7 (safe by ABI, the §17 lever) or restructure. A one-instruction count
  mismatch on a caller-saved-pinned draft is this bug until proven otherwise.
- 2 NEARs enqueued with full diagnoses (prologue $ra-save scheduling; S3 chain-priority).
2026-08-15 02:50:57 -06:00
Drew T efd0dd4ee1 feat(phase-31): wave G — 36/36 drafted, 32 banked, fleet 95.4%; §174 law 1b (PsyQ symbol names)
- wave G: 36 atlas mass cards on ov_SC03_006 -> 36/36 standalone (100%, independently
  re-verified), 32 banked of 33 gated, ONE gate group. R22 213/213. stubs -> 11,788.
- two TU-packed waves now confirm the shape: ~1 rebuild per wave instead of 23.
- law 1b added to the wave prompt: agents reconstruct CODE at 91-100% but INVENT PsyQ symbol
  names (S80131E00->Square0, Blk20_...->RotMatrixY, SRM_...->RotTransSV). Dangerous because
  match_one MASKS relocations -> a wrong callee name still reports MATCH; only the
  whole-binary gate + symbol audit catch it, after a wasted rebuild.
- 3 wave-G drafts held by that audit (would previously have crashed it pre-commit:2330).
2026-08-15 01:54:31 -06:00
Drew T ab649794ca feat(phase-31): wave F — 50 banked from ONE gate group; the TU-packed mass lane is the campaign shape
- wave F: 60 atlas 'mass' cards (fresh crack, NO seed body) -> 55/60 standalone pre-repair
  (59/60 post-repair), 50 BANKED of 53 gated, in a SINGLE gate group. R22 213/213.
- the throughput thesis is confirmed: wave D banked 45 across 23 whole-binary rebuilds;
  wave F banked 50 across 1. gate cost scales with (binary,TU) groups, not drafts.
- the fresh-crack lane converts like the seeded lanes (~91%) => the atlas's ~7k draftable
  candidates are all reachable, not just those resembling a prior match.
- grinder: 0 banked across 8 seeds / 11 ILS cycles (band exhausted); re-exposed the Phase-22
  split-file blindness (no .s under md_MAIN_027).
- KNOWN DEFECT logged: aprop_symfix crashes on non-hex symbols (int('Square0',16)) — one
  PsyQ-named callee aborts the whole audit; needs 1:1-rename handling + per-pair isolation.
- stubs 11,876 -> 11,826
2026-08-15 01:23:33 -06:00
Drew T 1a23d90b31 chore(phase-31): R22 213/213 after wave D; wave F launched (first TU-packed wave, 60 drafts/1 gate group) 2026-08-15 00:35:03 -06:00
Drew T dde7a35ca3 feat(phase-31): wave D banked 45/48 + main link-blocker diagnosed; selector packs by gate group
- wave D (48 adapt cards): 47/48 standalone, 45 BANKED across two gates (40 + 5 late-repair).
  Operational lesson: build the gate slate AFTER the repair stage lands — the first slate was
  built early and 5 rescued drafts needed a second gate.
- wave C (35: 11 tell + 24 weak): 32 banked, 91% gate. Weak lane proven 24/24 on haiku.
- MAIN BLOCKER DIAGNOSED (the night's most valuable finding): main drafts are byte-correct yet
  gate 0/4. Byte-diff of the built EXE = exactly 2 bytes in 413,696, NOT in the drafted fn: a
  jal at 0x80060E74 retargets func_80061FA8 (game code, 800c2.o) -> firstfile (PsyQ libapi
  A66.o). Adding one C fn perturbs symbol resolution between game code and the LINKED PsyQ
  archives. main is an INTEGRATION wall, not a matching wall -> its own lane; excluded from
  build_wave_atlas by default.
- build_wave_atlas.py now packs by (binary, TU) — the REAL gate-group key, since each group is
  one whole-binary rebuild (wave D: 42 drafts / 23 groups = the throughput ceiling).
- 3 NEARs enqueued as grinder fuel incl. func_80183578 at close=1 DELAY-SLOT (§60a precedent).
2026-08-15 00:32:03 -06:00
Drew T 540d2cefaa feat(phase-31): wave C banked 32 (R22 213/213) + tools/build_wave.py; 3 instrument defects fixed
- wave C: 35 cards (11 tell + 24 weak) -> 35/35 standalone (re-verified independently, R14)
  -> 32 banked / 3 near, 91% gate, 0 symbol failures (Law 4 prevention worked)
- weak lane proven for the first time: 24/24 on haiku; 890 candidates remain
- reach measured: 32 exemplars, 8 with sharers, x2 each => ~1.25x effective (the x134
  era ended in P25/29/30) -> throughput, not leverage, is now the lever
- tools/build_wave.py (pool=adapt|weak, corpus-derived open-stub filter, R35 gate guard)
- 3 self-inflicted instrument defects found+fixed+NC'd (P9, recorded not buried):
  pgrep self-match via shell=True; corpus.stubs() is addr->Stub not names (nearly
  declared both card pools spent); a wave fired on hand-typed placeholder cards (stopped)
- STRATEGIC: card lanes are ~0.23% of open ins/wave; the Atlas's head-crack bucket is
  1,276 groups / 186k ins with high-reach groups up to 265 instances -> retarget waves
  at atlas groups next
2026-08-14 23:44:03 -06:00
Drew T 6afca3d47e feat(phase-31): wave-C probe — bank func_80181724 + §174 Law 4 (the DEF-side prototype is a wave-prompt law)
- probe 3 tell-cards: 1 MATCH, 2 NEAR (both genuine compiler residuals -> grinder)
- func_80181724 gated 0/1 at standalone MATCH: the TU already declared it (s32,s32) while
  the matching def wanted s16 -> conflicting prototype. Canonical sig + cast-at-use
  ((s16)a0) = identical 13 bytes, re-gated 1/1
- cookbook §174 Law 4 + measured lane economics (tell ~100k tok/card @33% vs adapt
  64-88k/bank @95% gate) + 'a standalone MATCH that gates 0 is a declaration fact'
- 2 NEARs enqueued as permuter fuel (func_8017DAEC count-exact 113=113, role swap)
2026-08-14 22:53:40 -06:00
Drew T 9d1e8e8c38 chore(phase-31): resume — owed R22 banked (213/213) + atlas regen at HEAD (11,994 open); wave-C fuel verified 2026-08-14 22:26:33 -06:00
Drew T 496e3757f2 docs(phase-31): cookbook §174 — the adapt-card wave recipe + 3 laws (R30, in-session) 2026-08-14 22:04:42 -06:00
Drew T e9e3db88de chore(phase-31): SESSION CHECKPOINT — campaign mid-flight; 65 banked this session; wave-B 35/37 (95%); resume steps + fuel inventory 2026-08-14 22:03:10 -06:00
Drew T 2655585c45 feat(phase-31 T10 wave-A): adapt lane opens — 12 banked +1 prop (75% draft / 67% gate, ~117k tok/bank); ledger + lessons 2026-08-14 21:12:28 -06:00
Drew T 682d0fa1fd feat(phase-31 T7): family_align — aligned classifier + imm engine, NC'd; mechanical-cousin lane refuted by probe
- tools/family_align.py (NEW module — classify_member's return contract untouched,
  the remap_hseq silent-pass trap avoided by design): SequenceMatcher alignment
  over FC.tok streams; li-cluster reconstructor (lui/lui+addiu/lui+ori/li-from-$0
  chains, split-cluster absorb for the rs-changed addiu partner); verdicts
  LEN-LI/LEN-NOP/LEN-JTBL/LEN-STRUCT/STRUCT-ALIGNED/PURE/IMM; aligned imm engine
  mirroring imm_map_tier1 (ordinal deliberately out in v1)
- NC-1 verdict-equivalence 157/157 banked pairs — the NC caught two real gaps:
  R-type non-shift sa diffs are STRUCT; registers tested BEFORE the reloc skip
  (a reloc-slot word with a different register is STRUCT). NC-2 parity 21/21
- R37 PROBE REFUTED the planned mechanical driver before it was built: 0/26
  LI-ONLY cards classify mechanically (regfields x19) — cousins are 0.85-similar
  DIFFERENT functions; §168 law 1 re-derived by measurement; no driver written
- family_align re-scoped: its consumer is T8's LEN+N near-miss pile (draft vs
  its OWN target = same function); reloc-vs-constant range discriminator parked
  for T8. decision-log entry (R31)
2026-08-14 19:49:22 -06:00
Drew T 1a8cda6c54 feat(phase-31 T6): PLUMBING campaign — +9 banked (64% probe); recipe + 3 laws (§173)
- tools/plumbing_groups.py: derives the honest still-open pool from the classified
  ledgers (R38) — '1,217 PLUMBING' collapsed to 237 (SELF 109 / CALLEE 48 / OTHER
  48 / DATA 32)
- recover_integration: PER-GROUP ISOLATION (git-checkout binary TUs between groups
  — one TU-stage edit was poisoning every other group's whole-binary gate with a
  phantom shared error; per-group banked_from_source capture) + new stages
  'macro-externs' (§121 draft-tier, via family_sweep.macro_def_sig_map, R33) and
  'tu-scope' (§103 STU binary-tier, the sweep-only lever)
- the probe (ov_SC03_107): raw 0/14 -> root-caused (poisoning + stale seed
  symbols; rtu_match MATCHes them — blind to reloc names, R34) -> symfix-first
  -> 9/14 BANKED (64%)
- sweep finding (Law 3): the no-draft majority (ov_SC02_037 44/44, most of
  ov_MAIN_012) had verdicts from transient sweep remaps never persisted — family-
  lane fuel, not recovery fuel; the stored-draft class is consumed
- cookbook §173 (symfix-first / per-group isolation / verdicts-without-drafts);
  index 518 green; R22 clean fleet 213/213; phase total 17 banked @ 0 agent tokens
2026-08-14 19:42:55 -06:00
Drew T e18738c48e feat(phase-31 T5): THE FRONTIER ATLAS — 5,139 lever-labeled crack groups over all 12,058 open fns
- tools/atlas.py: cousin units baseline + T1.5 h_seqn merges + CALIBRATED warm
  tier (measured: li-norm metric holds ~99% recall to 0.55; rule = smallest t
  with neg-accept<=0.2% AND recall>=95% -> THRESH_WARM=0.70 @ 99.1%/0.18% —
  false merges waste exemplar cracks, misses only route cheaper) + seed sweep
  (65% of open skeletons carry a >=0.55 matched seed) + kNN graph + tiny-direct
  + evidence joins (audit/backlog/ledgers/cards; unparsable=fatal) + lever
  labels with confidence measured>ledger>tell>default>UNKNOWN
- partition ASSERTED: 12,058 = progress stubs 12,051 + NM 7 EXACTLY (chased the
  +1: data blobs now excluded, reconciled against classify() buckets; T1 banks
  confirmed absent); every instance in exactly one group; main joins at the
  atlas layer only (family maps stay non-main — 4 silent-skip hazards)
- warm tier merged 1,019; top group unifies 268 drifted per-location skeletons
- lever table: head-crack 186.9k ins / UNKNOWN 138.6k (honest) / extend-tell
  76.7k / redraft 46.8k / jtbl-carve 45.7k / integration 23.4k / seeded 23.4k /
  len-vein 16.8k / swaprepeat 9.2k / plumbing 8.1k / o0 6.6k / cc1 6.4k
- atlas_features: li_norm_toks exported (shared with atlas, R33; hash-stable);
  mid_jr verifier fixed (compared ZERO rows — R32 silent no-op; now 6,444/6,444)
- make atlas = full regen chain (~10-15 min, zero tokens); --targets emits
  crack slates (12/12 .s resolved); survey 92 s
- SETUP rows (R21); docs/frontier-atlas.md committed
2026-08-14 18:06:46 -06:00
Drew T 22eed7d78a feat(phase-31 T3): main enablement — sig-main at splat-true lengths + main streams
- sig_image: --seeds accepts '0xADDR NINS' (and jsonl nins); a seeded nins is
  authoritative ([addr, addr+4*nins), bypasses func_end whose heuristic mis-sliced
  3/40 main samples); R32 guard on seeded end > hi
- corpus: s_ins_count() factored from audit() (R33, one counter) + '--seed-ends'
  CLI emitting per-stub splat-true lengths
- make sig-main: 2,002 main stubs signed -> .run/sig.main.jsonl; FULL word
  cross-check 2,002/2,002 EXE slices == .s words (0 SLICE-SUSPECT; .s word field
  is byte-order hex, not LE — first checker draft misread 1,999 false suspects).
  Deliberately splat-SEEDED; main's independent second oracle stays deferred
  (second-oracle.md; sig_is_independent(main) stays False)
- family_remap: vram_of/img_path special-case 'main' derived from splat.us.exe.yaml
  (file0-vram = code-seg vram - start = 0x8000F800; target_path); stream_words
  ('main') verified 25/25 vs .s
- regression: sig-resident re-run byte-identical after the shared read_seeds change
- SETUP §6.3 rows (R21)
2026-08-14 17:48:51 -06:00
Drew T fa425f89a5 feat(phase-31 T2): reference expansion — PsyQ SDK sample source extracted + gcc-2.7.2 completed
- PsyQ 4.0 dev-CD Track-1 walked with the frozen iso9660.py (R33): 2,374 files /
  231.6 MB -> tools/reference/psyq-sdk/ (gitignored); 400 C sources incl. the full
  PSX/SAMPLE tree (373) — drafting-agent style priors, esp. for main
- provenance find: GNU/SNGNUVER.TXT = SN's gcc build history (2.7.2.SN32.3.7.0002)
  naming SN's exact patches vs vanilla; only UNROLL.C codegen-relevant
- gcc-2.7.2 reference +6 files (calls.c + caller-save.c — §172-cited, previously
  missing — + integrate/optabs/varasm/recog), tarball sha256 recorded
- docs/psyq-sample-idioms.md seeded; SETUP §5.6 rows (R21)
2026-08-14 17:44:32 -06:00
Drew T 2a0ac5ab8d feat(phase-31 T1): integration quick-bank sweep — 8 banked, 0 agent tokens; symfix STALE-DELTA
- aprop_symfix: STALE-DELTA class — the S50 1:1 stale-seed-symbol rule generalized
  to n:n (sorted-by-address zip, ONE uniform target-draft delta required; refuses
  count mismatch / non-addressed names / disagreeing deltas). R39 negative controls
  (synthetic + S50-snapshot equality over still-stub rows, zero false positives);
  first live batch 4 rebased -> 4/4 BANKED (func_8016BCC0, func_8017F1C8,
  func_80186BD8, func_80186BF8). The delta test refused func_80186C1C whose deltas
  differ by 4 — a hand-check had wrongly accepted it. cookbook §171-D
- recover_integration demacroize (SELF-decl class): 4/7 banked (func_80139BE0,
  func_8014ED28, func_80161D88, func_801659DC)
- R38-first partition of the MATCH-108 pile: 75 still-stub = 13 never-gated +
  62 verdictted (31 PLUMBING = 7 SELF + 15 CALLEE->T6 + 3 UNDEF-DATA + 6 OTHER;
  14 CC1->T6; 8 md CARVE-REFUSED->ledger; 1 DIFF); immfix pile fully consumed
- stored-draft re-gates 0/23 (the ~8% A10 law held); 9 STALE->clean world-motion
  drafts identified (siblings' banks defined their missing symbols)
- gate_lane: propagate-commit tag derives from GATE_PHASE (was hardcoded)
- R22 clean fleet: extract-all 212/212 + main; check-all 213/213 BYTE-IDENTICAL
2026-08-14 17:40:38 -06:00
Drew T d6ade08f3a feat(phase-31 T0): pivot log + instrument freshness + hygiene
- decision-log: the P31 re-charter entry (organize-before-grind; R37/R38/R39
  ratified at gate-1) per R31
- harvest_verify.py: import guard — a bare import now RAISES loud instead of
  running a full gate (CLI unchanged, verified both directions)
- sig-resident: bootstrap boundary artifacts fixed (fused +0 data word with
  func_800CEDFC; func_800D33E0 dropped past a glued tail) -> ELF-seeded per the
  S45 pattern, exactly 145 fns; true denominator confirmed 145 (progress was
  right); audit-corpus 0 PHANTOM + 0 TRUNCATED; all three oracles agree
- family maps regenerated at HEAD commit:2161: 11,025 open non-main members
  reconciles EXACTLY with 12,059 - main 1,034 (102 stale phantoms cleared);
  adapt cards 704, aprop cards 204 (full emission)
- main fuel-gap finding: 2,001/2,002 main stubs already have cached Ghidra-C
  (only func_80049600 missing) — the roadmap '0/2,096' note was stale
- tools-health OK (dedup 2,063/0; C1 254,521/254,521; audit-digest green)
2026-08-14 16:40:43 -06:00
Drew T 1c631ff39f feat(phase-30 S50-Max): the gcc-read audit — +52 banked, R22 213/213 (S50 FINAL v2 checkpoint)
The §172a/§172b tells + repaired instruments swept over all 892 open near-misses:
- 33/95 stored drafts re-verified MATCH and banked through the whole-binary gate
  (aprop_symfix caught 40/108 carrying stale seed symbols before gating — §171 at scale)
- 19/20 hand/mech fixes banked: four pure lhu<->lh s16 flips; the lhu+sltiu->lh+slti
  shared-global quadruplet (D_80126B5E/B66/CB0, D_80126CB0 are s16 FLEET-WIDE); one xor-eq
  rewrite; 11 per-location literal swaps (mask/threshold constants from sibling binaries)
- 1 refusal (func_8017EE78) stays as redraft fuel
Stubs 12,111 -> 12,059. Fleet 95.3% instr / 90.0% distinct / 96.68% fn-count.
Veins mapped for next waves: ~400 LEN+N drafts, 13 ambiguous-symbol, 7 multi-literal.
Audit ledger: .run/c294/audit_results.json (classifier derives from match_one's own sig).
2026-08-14 14:32:48 -06:00
Drew T fe1a0730e1 docs(phase-30 S50-Max): §172b — three more tells banked from the gcc read (sll/sra-16 register-promotion tell; swapped-arm select tell; ?: accumulator-order tell; div sign-correction reuse) 2026-08-14 12:44:25 -06:00
Drew T 4fbe768798 docs(phase-30 S50-Max): func_8017C294 — the ordered Max finish: five new axes opened, all byte-refuted; §172 rewritten v2 + §172a tells (the idiom deliverable)
The crack was NOT achieved; the wall is now mechanism-complete instead of inferred:

- caller-save.c setup_save_areas DISCOVERED as a second never-referenced-slot producer:
  eager 4-byte areas per call-clobbered hard reg carrying a call-crossing pseudo at ANY
  reload iteration (-fcaller-saves is on at -O2), emitted code or not.
- Alignment math corrected: alter_reg slots 8B (align -1), save areas 4B (align 0).
- The whole-binary gate run on v_best/v_dialfree for the FIRST time: both rejected —
  the standalone NEAR-2/NEAR-25 verdicts are faithful, no TU-state leak.
- 200-variant randomized structural sweep: swapped-arm recomputes are the ONE dimension
  that moves vars upward (cse does not merge the swapped select) at ~1:1 real-code cost;
  four coincidental vars=256 hits, all heavy-drift.
- Proof: cross-jump cannot delete slot-bearing code (identical-offset requirement) —
  the last no-residue mechanism branch closed by argument, not probe.
- Inline forms collapse the chain 246->209 ins: the bytes REQUIRE textual macro repeats.
- cc1 flag axis (-fforce-addr/-fno-force-mem/-fno-caller-saves/-fno-schedule-insns):
  vars=224 invariant.

Idioms delivered (Drew's second ask): §172 v2 (complete frame-residue model: producers,
alignment, orphan rule, the three-layer canonicalization wall with its honest bound) +
§172a (the lhu/lh typing tell: movhi=lhu copy vs extendhisi2=lh promotion, the double-load
signature; the macro-vs-inline tell: re-evaluated compares in arms = textually repeating
macros, load-bearing redundancy). The 0x801F1CD8/0x8017D290 family idioms were §171a/b.

Floor stays NEAR 2/246. Parked for P32 with the siege kit: tools/cc1_dumps.sh, the §172-v2
model, sweep_gen.py, the swaprepeat lead. ~240 cumulative refutations, each byte-grounded.
2026-08-14 12:38:14 -06:00