Commit Graph

2395 Commits

Author SHA1 Message Date
Drew T fa7204e531 feat(phase-31): worker gate — +1 fns x0 propagated (fleet 95.4%) 2026-08-15 09:46:12 -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 594a87e173 feat(phase-31): reloc_identity.py — the oracle that disagrees with match_one about SYMBOL IDENTITY (S52)
match_one masks relocations (26-bit jal field, HI16/LO16 immediates), so it verifies instruction
SHAPE and is structurally blind to WHICH symbol each relocation names: a draft calling the wrong
function or touching the wrong global reports a clean MATCH (§174 law 1c; wave K burned 5 gate
attempts on two swapped globals). Until now only the whole-binary gate caught it, and it reports a
hash, not a cause.

But the target .s comment column carries the FINAL LINKED WORD, so the true address behind every
masked field is recoverable arithmetically, and config/symbols*.txt maps it back to a name. This
tool resolves what the DRAFT names, computes what the TARGET references, and compares -- /bin/bash, no
rebuild, and it names the fix instead of reporting a mismatch.

match_one --emit-streams additionally carries mine_relocs (kind/operand per index); existing
consumers read mine/tgt only.

THREE INSTRUMENT BUGS FOUND BY ITS OWN NEGATIVE CONTROLS, each fixed before any verdict was
believed (R35/R39):
- splat-derived func_/D_/jtbl_ names are not in the symbol FILES (their address IS their name), so
  the first run checked ZERO relocations on a draft whose every callee was correct -- a checker
  that looks clean while checking nothing (R32).
- the nearest-symbol fallback used a 0x4000 window and labelled func_8001C9D0 as 'SsGetMute+0xC50';
  a wrong label is worse than none. Tightened to 0x200 with an explicit splat-derived fallback.
- MIPS o32 uses REL relocations: THE ADDEND IS IN THE INSTRUCTION, not the reloc entry. Reading it
  off the operand string reported 0 for every struct-field/array access and fabricated mismatches
  (the +1/+2/+3 signature on func_801F0734 was a byte-array walk, not three symbol errors).
Also refuses to answer confidently when the streams are not index-aligned (shape differs), since a
single inserted instruction shifts every later index -- my own NC produced exactly that phantom.

NC: known-good drafts AGREE (3 and 5 relocs actually checked); a synthetic callee 4 bytes off is
caught while match_one still says MATCH; a misaligned mutant is downgraded to advisory.
2026-08-15 09:42:58 -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 02edb37265 fix(phase-31): gate_main conflict check reads the destination TU + is per-file (S52-7)
resolve_conflicts() had two defects, both found by the wave-J/K/L draft recovery:

(a) THE SYMBOL TABLE STARTED EMPTY -- only draft-vs-draft was compared, so a draft contradicting
    a declaration ALREADY IN the .c reached the rebuild and surfaced only as a compile error and
    a bisect. src/800.c carries 'extern void func_8001C9D0(void);' (from banked func_8001C2C4)
    while three wave-J drafts declared it (s32)/(void *). The TU now seeds the table, and the
    drop report names whether the clash is with the TU itself or an earlier draft.
(b) ONE NAMESPACE FOR ALL FILES -- 'seen' was global across the slate, so two drafts landing in
    DIFFERENT .c files could not legally disagree about a symbol. Separate TUs are separate
    namespaces; the table is now keyed per destination file (R39: over-refusal discards good work).

On the 11 recovered drafts the new check named 7 real TU conflicts that the old one missed
entirely. All 7 were repaired by adopting the TU's declaration verbatim and casting at the use
site -- including a NEW variant: when the TU's prototype takes no argument and the call must pass
one, cast through a function pointer, ((void (*)(s32))func_8001C9D0)(a0). All 11 re-verified
MATCH afterwards, so the cast is byte-identical in every case.

R39 NC: a synthetic draft re-contradicting the TU is still dropped; the repaired slate is 11/11.
2026-08-15 09:35:26 -06:00
Drew T fb4c1f03a1 fix(phase-31): wave-selector coverage + gate_lane crash-vs-empty (S52-1, S52-8)
build_wave_atlas.py:
- taken-set was a hardcoded 'abcdefghijkl' wave-letter literal -> glob('.run/wave_*_cards.json')
  (R33 derive, don't re-derive). NC: 634 -> 726 taken, strict superset, +92 cards from waves m/n
  that the literal would have silently re-issued.
- --exclude-bins defaulted to 'main' on the REFUTED link-defect rationale; default now empty and
  the help states the real reason (main cannot be gated incrementally; use tools/gate_main.py).
- new --only-bins allow-list: main waves need it, since gate_main rebuilds once per SLATE.

gate_lane.py: an unhandled gate_stage exception produced no JSON line -> v={} -> '0 banked',
indistinguishable from an honest empty gate (cost 2 cycles in P31). Now a non-zero rc or a missing
JSON line is labelled CRASH with the stderr tail, recorded in the results JSON, listed in the
summary as NEVER GATED, and exits non-zero. R39 NC both directions.
2026-08-15 09:31:10 -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 1a36531eff chore(phase-31): checkpoint records the banked idioms (§174-176) — nothing left only in commit text 2026-08-15 09:09:32 -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 b9f2540aa7 feat(phase-31): propagate func_80181B4C (gate lane) 2026-08-15 08:08:34 -06:00
Drew T cb93147138 feat(phase-31): propagate func_80186764 (gate lane) 2026-08-15 08:08:24 -06:00
Drew T 6634db313d feat(phase-31): propagate func_80187738 (gate lane) 2026-08-15 08:08:14 -06:00
Drew T 0b838da46c feat(phase-31): propagate func_80187DB8 (gate lane) 2026-08-15 08:08:00 -06:00
Drew T f59b0fdc75 feat(phase-31): propagate func_801884FC (gate lane) 2026-08-15 08:07:50 -06:00
Drew T 308e59d995 feat(phase-31): propagate func_80186E6C (gate lane) 2026-08-15 08:07:40 -06:00
Drew T 1919009dc4 feat(phase-31): propagate func_80184A08 (gate lane) 2026-08-15 08:07:30 -06:00
Drew T 9f69581941 feat(phase-31): propagate func_80183754 (gate lane) 2026-08-15 08:07:17 -06:00
Drew T 3a708363b5 feat(phase-31): propagate func_801860E4 (gate lane) 2026-08-15 08:07:03 -06:00
Drew T 133e3c4e4c feat(phase-31): propagate func_80181934 (gate lane) 2026-08-15 08:06:54 -06:00
Drew T c2cf9f226c feat(phase-31): propagate func_80181820 (gate lane) 2026-08-15 08:06:40 -06:00
Drew T ccf48cf090 feat(phase-31): propagate func_80188790 (gate lane) 2026-08-15 08:06:22 -06:00
Drew T 3f31273793 feat(phase-31): propagate func_8018825C (gate lane) 2026-08-15 08:06:12 -06:00
Drew T 303e1ffc4b feat(phase-31): propagate func_8018512C (gate lane) 2026-08-15 08:05:58 -06:00
Drew T 62bda0dc38 feat(phase-31): propagate func_80183814 (gate lane) 2026-08-15 08:05:40 -06:00
Drew T 58b0547859 feat(phase-31): propagate func_80186424 (gate lane) 2026-08-15 08:05:26 -06:00
Drew T 3344015a12 feat(phase-31): propagate func_80188134 (gate lane) 2026-08-15 08:05:15 -06:00
Drew T 82744a4f85 feat(phase-31): propagate func_80188028 (gate lane) 2026-08-15 08:05:05 -06:00
Drew T 22878beeeb feat(phase-31): propagate func_801854CC (gate lane) 2026-08-15 08:04:52 -06:00
Drew T ec4c02b1d2 feat(phase-31): propagate func_80184250 (gate lane) 2026-08-15 08:04:42 -06:00
Drew T 90eb6204d6 feat(phase-31): propagate func_80186CE8 (gate lane) 2026-08-15 08:04:32 -06:00
Drew T 597a1a2f48 feat(phase-31): propagate func_80186D88 (gate lane) 2026-08-15 08:04:18 -06:00
Drew T 84753840a5 feat(phase-31): propagate func_801829F8 (gate lane) 2026-08-15 08:04:08 -06:00
Drew T 46cc75a5ce feat(phase-31): propagate func_80184B14 (gate lane) 2026-08-15 08:03:57 -06:00
Drew T 229c6fa8df feat(phase-31): propagate func_80182894 (gate lane) 2026-08-15 08:03:47 -06:00
Drew T 910950423a feat(phase-31): propagate func_801819F4 (gate lane) 2026-08-15 08:03:37 -06:00
Drew T 0e1aa40609 feat(phase-31): propagate func_80181C10 (gate lane) 2026-08-15 08:03:27 -06:00
Drew T dac6fd016e feat(phase-31): propagate func_8018419C (gate lane) 2026-08-15 08:03:16 -06:00
Drew T b5b3072d88 feat(phase-31): propagate func_80187F30 (gate lane) 2026-08-15 08:03:06 -06:00
Drew T c0c19b5c00 feat(phase-31): propagate func_80187354 (gate lane) 2026-08-15 08:02:56 -06:00
Drew T f55032ea56 feat(phase-31): worker gate — +42 fns x0 propagated (fleet 95.4%) 2026-08-15 08:02:45 -06:00
Drew T 6c12790719 chore(phase-31): SESSION CHECKPOINT — overnight campaign closed; cron cancelled; full handoff
- waves C-N: ~448 banked, stubs 12,059 -> 11,549, fleet 95.4% instr, 213/213 after every
  batch, main 0 -> 175 matched.
- records the three campaign-changing findings (main is open and was never hard; gate-group
  packing is the throughput lever; match_one verifies SHAPE not SYMBOL IDENTITY), the tools
  built/fixed, the prioritized open work, and the methodological lesson.
- cron be8fb48c cancelled; nothing in flight at handoff.
2026-08-15 07:30:48 -06:00
Drew T db8deb3558 chore(phase-31): velocity ledger — waves L and M rows (band test + law 1c) 2026-08-15 07:09:04 -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 8225ba9d8a feat(phase-31): propagate func_8018AD3C (gate lane) 2026-08-15 06:41:54 -06:00
Drew T 69b1ef8606 feat(phase-31): worker gate — +40 fns x0 propagated (fleet 95.4%) 2026-08-15 06:38:07 -06:00
Drew T 093a05ab36 feat(phase-31): gate_main strips duplicate typedefs on substitution (the wave-L loss)
- each draft compiles STANDALONE so it carries its own 'typedef struct {...} SVECTOR;'. Once
  one such function banks, that typedef lives in src/800.c forever and every later draft
  defining its own collides — a C89 duplicate-typedef error, not a byte miss. harvest_verify
  already handles this; gate_main did not, and wave L lost a verified-correct draft to it.
- strip_dup_typedefs() drops typedefs the destination file (or an earlier body in the same
  batch) already defines, and keeps novel ones.
- R39 NC: drops the duplicate, keeps the novel one, leaves the function body untouched, and is
  a strict no-op when there are no duplicates.
2026-08-15 06:32:30 -06:00
Drew T 00e018ee41 chore(phase-31): checkpoint — overnight result (~408 banked, main 0->175) + the main-lane runbook
- records the night's totals and, more importantly, HOW to run the main lane: gate_main.py
  batch clean-rebuild, never gate_lane/gate_stage (incremental + .ld rewrite = false diff).
- notes the one mechanical improvement left (strip duplicate typedefs on substitution) and
  that the ~10 conflict-dropped main drafts are verified-correct and recoverable.
2026-08-15 06:10:09 -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