Ultracode wave: 16 isolated drafters over the resident's non-jtbl stubs (the 5 jtbl deferred —
they need the rodata-island carve, §53). Drafts only; the whole-binary byte-gate arbitrated after.
- BANKED 7/16, byte-gated: func_800CEFD0(77) func_800D0D7C(45) func_800D1B80(22) func_800D1E28(37)
func_800D1FC8(62) func_800D29F8(172) func_800D2D10(39).
Resident REAL 122 -> 129, stubs 21 -> 14, byte-ident 124/145 (85.52%) -> 131/145 (90.34%).
FLEET instr 9017152 -> 9017606 (+454 ins). R22 make clean && extract-all && check-all ->
140 passed, 0 failed of 140 (the first R22 was killed by a terminal crash and RE-RUN, not assumed).
Ground truth on 14 agrees 3 ways: source grep, splat-emitted stub .s count, progress.py.
- §52b's LAW, MEASURED AGAIN INDEPENDENTLY: the agents self-reported 11 match_one MATCH; the
whole-binary gate banked 7 (64%). All 4 blocked MATCHes died on `conflicting types`
(D_8010EDEC / D_80115110 / func_800D1984 / cdFileLocTable) — the loose-typing def-side wall, NOT
codegen. gate_stage's recovery banked 0/5 on them. A match_one MATCH is a CANDIDATE (G3/P9).
- FIX — match_one's isolation was FAKE, and its own docstring was the false spec. It promises
"Fully isolated (own temp dir) so many run in PARALLEL with no shared build -- a real asm-differ
loop for an agent to iterate against", while `--work` defaulted to the SHARED '.run/match': every
concurrent caller compiled into the same t.c/t.o. FOUND BY AN AGENT MID-WAVE, the only way it can
be found — it read another agent's function out of its own scratch ("found another agent's
func_800D2650 in my t.c") and reported it. Every other agent steered by a loop that could hand it
someone else's compile: a CONFIDENT WRONG verdict, worse than a crash. Default is now a private
.run/match/<fn>.<pid>; the default IS the promise. (Some agents had already worked around it by
passing --work themselves.) The byte-gate was never at risk — it is the sole arbiter — but the
iteration loop the agents steer by absolutely was.
- The 14 remaining: 5 PLUMBING (loose-typing) + 4 DIFF (genuine codegen: func_800D2650 close=4,
func_800CFAD0 close=5, func_800D0E30 close=12, func_800D27DC close=48) + 5 jtbl deferred.
Dossier next (T5b) — the agents' per-function residual analyses are the durable asset (R30).
R35: fix the instrument before planting a flag on its denominator.
- #if 0 BLINDNESS: classify() knew `#ifdef NON_MATCHING` (:425) but not `#if 0`, so a dead
analysis body was read as a live definition AND its real INCLUDE_ASM stub counted separately —
the SAME function in BOTH `real` and `stubs`. Live case: resident.c:868-925 wraps a full
void func_800D00E4(s32){...} in #if 0 (its jtbl dossier) and re-declares the stub at :926.
Now the block is skipped entirely: dead code is neither matched nor stubbed.
- THE len()-SUM (the dual defect): `placed` was a set union, so it caught a function in NO bucket
— but `matchable` SUMMED len()s, so a function in TWO buckets counted twice and nothing
complained. matchable/byteident are now SET unions, plus a new OVER-coverage assertion that
fails loudly if any fn lands in multiple buckets. R32 means both directions: nothing missing,
nothing double-counted.
- NEGATIVE CONTROL (the fix must change an answer the old tool gave):
resident REAL 123 -> 122 | matchable 146 -> 145 | 85.62% -> 85.52% | func_800D00E4 no longer
double-counted. FLEET instr 68.9% UNCHANGED (no #if 0 in the overlays) — the fix is scoped.
- FINDING (logged for T7's audit-binaries, does NOT block the flag-plant): the two INDEPENDENT
oracles now agree exactly at 144 — corpus (21 stubs + 123 matched, derived from the tree) and
sig_image (the 2nd oracle) — with EMPTY set difference both ways. progress.py still reports 145
because it counts func_800CEDFC and func_800D33E0, which are DEFINED in resident.c but absent
from sig_image. 0x800CEDFC is the resident's vram base +4 (the first function, code starts at
file offset 0x4 after the leading data word), yet make audit-corpus reports 0 PHANTOM +
0 TRUNCATED. Either sig_image has a boundary blind spot or those defs are not image functions.
progress.py's text-scanning classify() is exactly the re-parsing R33 says should be DERIVED from
corpus instead — a real refactor, logged not rushed.
The flag-plant claim is unaffected: it rests on corpus.stubs('resident') == 21 (tree-derived,
verified 5 ways), not on the contested denominator.
The pass-4 functions that match_one matched standalone but the single-TU build rejected
on conflicting shared-symbol extern types are recovered by UNIFYING those types in
resident.c (widening definitions' return types where byte-identical — u16 f(){return
u16g} ≡ s32 f(){...} both lhu;jr; choosing asm-correct widths for globals; per-site
*(u16*)&g tricks where a neighbor pins the type). ~20 symbols reconciled
(func_800291B4/CFD68/D1714/D1078/801465C0/... + D_800AE6A8/80078E50/...).
20 of 21 recovered; func_800D00E4 stays an honest INCLUDE_ASM stub (its switch needs the
external jtbl_80113ED8 relocation, not a C-source fix — analysis preserved under #if 0).
REAL 102 -> 123 (85.62% byte-identical); resident 8e17e02f, main 143dbb89 (R22 clean).
22 stubs remain: ~20 documented compiler-internal residuals (permuter/§3a) + D00E4 + dedup.
- tools/match_one.py (new): compile ONE function's C standalone (pinned triple), mask
relocations (jal/HI16/LO16 like psyq_identify), compare to the target bytes in its .s.
Isolated temp dir -> parallelizable; a real per-function asm-differ loop for agents to
iterate against without a shared build. Validated: a matched fn -> MATCH, residuals ->
informative diffs.
- harvest_verify.py + match_one.py: strip inline scalar-typedef redefinitions (some drafts
inlined `typedef unsigned char u8;` -> C89 redefinition error vs common.h = a COMPILE
fail, not a byte mismatch). Re-gate recovered func_800CFBCC + func_800D1938.
- REAL 89 (62.76% byte-identical); resident 8e17e02f, main 143dbb89 (R22 clean).
- 54 stubs remain (scheduling/regalloc residuals + big GPU/dispatch fns) -> match_one-driven
iteration pass next.
Ultracode harvest: a 16-agent workflow (resident-harvest-draft) drafted matching C for
the 135 unmatched resident functions (each agent: asm + cookbook + the 8 worked examples,
writing .run/drafts/<fn>.c, no builds/no Ghidra). Then tools/harvest_verify.py (new) byte-
gated every draft against 8e17e02f one at a time (chunk+bisect), keeping only the byte-
perfect ones and reverting the rest -- the build is the sole arbiter (G3/P9).
- 62 / 127 drafts verified byte-identical in one pass; 65 near/hard misses reverted to stubs.
- REAL 8 -> 70 (48.28%); byte-identical 49.66%. resident 8e17e02f, main 143dbb89 (R22 clean).
- cleaned 35 redundant '#include "common.h"' lines the drafts inlined (still byte-identical).
- remaining: 65 failed drafts (close-misses + the hard dispatch/GPU/big-fn tail) + 8 undrafted
(2 agent batches hit transient API 500s) -> second-pass workflow + manual hard tail.
- opt level: resident is -O2 (0x21f0a003 frame-ptr sig count = 0, vs the EXE's 54;
the EXE's 800 game module is also -O2). No per-file override needed.
- triple (Makefile default, no override): gcc-2.7.2-psx -O2 -G0 -mips1 -mcpu=3000
-mgas -msoft-float -fgnu-linker + maspsx --aspsx-version=2.56 --expand-div.
- 2 byte-exact resident matches confirm it across idiom classes:
* func_800CF854 — lbu D_800AE6BF; sltu $zero (unsigned-!=0 accessor)
* func_800CEE84 — 8-call init: branch-store (D_80127084=0; if(D_800B9A00) =1),
delay-slot-filled func_80010AE0(0x3E0), early-scheduled load
- R22 clean rebuild: resident 8e17e02f, main 143dbb89 — both byte-identical.
make report BINARY=resident: REAL 0 -> 2.
- R24: the "resident is 4.7" DetectPsyQ hit was a coincidental DsMix signature; the
resident's actual game-code triple == the EXE's (byte-confirmed). No candidate
ladder; the STOP-condition did not fire. Harvest (T3) de-risked.
- diff_settings.py + progress.py/difficulty.py/dup_report.py: add the `resident` BINARIES entry
(build/resident/, config/check.resident.sha, src/resident, asm/resident/nonmatchings, per-binary docs)
- dup_report.py: degrade gracefully when the Ghidra sig (.run/sig.resident.jsonl) is absent —
write a placeholder + exit 0 instead of crashing the whole `make report` (sig is a T4 export)
- progress.py: scope linked_subsegs() to BINARY==main — PsyQ library linking is the EXE's layout
(Phase 8, gated ifeq BINARY,main), so a second binary has 0 LINKED (was: listed main's libs)
- Makefile expected: per-binary-safe — drop `rm -rf expected/build` (clobbered every sibling
baseline); refresh only the active binary's image dir + merge-copy (cp never deletes siblings)
- reports: resident = 0 REAL / 143 INCLUDE_ASM stubs / 100% stub (correct); main UNCHANGED
(52 REAL / 959 LINKED / 50.24%); both expected/ baselines coexist (verified)