- Drew's directive (2026-09-05): nothing but the original hand-asm and the PsyQ libs may remain; hand-crack each row and
name the blocker before spawning Fable agents. CURRENT_PHASE.md T4b row records the pass.
- func_80032A74: the missing 8 frame bytes = §172 producer 3, a TRANSIENT caller-save area — reload1.c's loop runs
setup_save_areas BEFORE spill_hard_reg in the same iteration (source-read), the draft already spills $t0 at iteration 1;
needs a rematerialisable call-crossing pseudo with 4*calls < weighted refs (regs.h:165); the lhu variant is byte-exact in all
422 instructions except the 22 frame-offset rows (HYPOTHESIS.md)
- func_80020DA4 (reuse lo0: 80), func_800CD674 (prim-4 temp forms: 31/44), func_800391D4 (giv / early promotion / order: 11–69),
func_800CD92C (constant birth position: no effect on pinned hard regs), func_80011380 (block-scoped register temp: 193/131),
func_80039308 (the TU's [][1] spelling: 517/81) — each NOTES.md carries the measurement and the next lever
- func_8017DF28: the target's `addiu $s2,$sp,0x10` in the bnez slot is the branch-target's first insn (reorg); the block-move
address pseudo must DIE at the copy. func_801834A4: sign-hoist vs const-hoist thresholds (S71 proof) + the mulsidi3 +2.
func_80039DEC: global.c find_reg's first pass avoids regs used by local pseudos — find the draft's local in $a3.
- .run/P32/t5x/BRIEF.md (the Fable contract: instruments incl. cc1_dumps/gcc source/permuter --j 2, laws, output JSON),
targets.json (15, sub = TU basename), packs regenerated; .gitignore allowlists for .run/P32/t4b and .run/P32/t5x
- every wall's best draft re-run with rtu_match in its CURRENT real TU: func_80011380 DIFF 6 (--o0, §474 PROVED),
func_80020DA4 DIFF 2, func_8017DF28 DIFF 2, func_801834A4 DIFF 6 ×3 variants; leaf match_one re-measured the CC1 rows
(func_80032A74 1, func_80039DEC 2 permuter / 9 sonnet, func_800391D4 3)
- the three CC1-FAIL rows: func_80032A74 = 7 typedefs the TU provides via 800_shared.h + 4 decl spellings → synced copy
(.run/P32/t4/drafts/func_80032A74_tuclean.c) DIFF 1 in the real TU (idx 244 lh vs lhu); func_80039DEC = the TU's narrow
prototype (800_c.c:3496) vs the K&R def → sandbox TU (.run/P32/t4/tu/, no-proto decl) DIFF 2; func_800391D4 = the
load-bearing `D_80073140[][1]` vs the TU's `[]` → sandbox TU DIFF 3 (TU-compatible spellings regress to 65 @ 76)
- config/wave_exclude.txt: each of the 7 lines carries its S83 re-probe verdict; exclude_audit --assert-fresh 7/7
- backlog: rows for all 7 walls (the path-less func_80011380/func_801834A4 given existing drafts, R62; two rows re-logged
after a shell-quoting mangle); docs/backlog.md 16 open
- CURRENT_PHASE.md: T4 row DONE, the wall ledger table (row · ins · class · leaf/real-TU closeness · mechanism+citation ·
attempt record · verdict · best draft; func_800CF3E8 listed as an unpinned candidate), the T4 log entry, 🛑 block → T5
(R27 Max prompt + the gate-2 procedure)
- cookbook §500-I (the sandbox-TU re-probe method + the verdict table); accelerators (8); decision-log P32 S83 (R31)
- CURRENT_PHASE.md: T3 row DONE with the close numbers; the S83 steps 8–9 log entry; the 🛑 SESSION CHECKPOINT rewritten
(T3 CLOSED, T4 NEXT; the 15-row census with draft paths and mechanisms; the T4 procedure incl. the §376 re-probe of the
three CC1-FAIL walls before any verdict; T5 carry)
- step 8 tail: func_8001BC6C BANKED (commit:3948); func_800CD674 plateau ledgered; func_800CF3E8 Opus second look 27 HOLDS —
§500-D1's mechanism corrected to cse.c find_best_addr (fold_rtx MEM, COST pseudo 0 vs hard reg 1), the alias lever refuted
5/5, a new zero-byte pinned-pointer launder found (79 @ 470) — cookbook §500-H, backlog row with cost (245k tokens / 29 min)
- make report: fleet instr 13,484,739 / 13,488,497 = 100.0% · distinct 5,812,831 / 5,816,589 = 99.9% (90,975 / 90,984 unique)
· fn-count 363,199 / 363,214 = 100.00% · INCLUDE_ASM 15; main REAL 783 · LINKED 1,256 · VERBATIM 3 · stubs 6 ·
byte-identical 2,085 / 2,091 = 99.71% · 143dbb89; census .run/P32/frontier_t3_close.json; twin_rescan 0 free
- R22 (clean + extract-all + check-all) after the Makefile guard + the main bank: 218 passed / 0 failed, exits 0/0/0
(.run/P32/t3s3/r22c_full.log) — the third green fleet sweep of the session (10:46, 11:09, 12:00)
- docs/accelerators.md (5)–(7): the build is the batch verdict / read a waypoint's diff both ways / a live probe in src/ is
build input; docs/backlog.md 14 open; verdicts.jsonl 50 rows; the s83 Opus draft + report kept (R20)
- kill gate: 29 banks + 3 new verdicts this session, the three bounded tail attempts spent — T3 closes on the evidence
- phase-ends/DIGEST.md (NEW, Drew-directed 2026-09-05): every phase's synopsis (P1–P32), every rule R1–R64 in full, the
corrections that supersede parts of PROJECT_CONTEXT.md (P8→R19, commit cadence→R42, H1→R1, headless Ghidra, roadmap v2,
effort doctrine, the pinned triple), and the doc map. Maintained at every PhaseEnd (CLAUDE.md Phase Boundary step 3b, P7).
- CLAUDE.md Session Start Protocol rewritten: PROJECT_CONTEXT → DIGEST → the THREE most recent PhaseEnds → CURRENT_PHASE
(+ cookbook head/newest § + SETUP §5.4 for matching phases); rules transcribed in full from the digest; the 🛑 SESSION
CHECKPOINT block reproduced VERBATIM in chat as the session's only in-phase seed. Measured load order ≈55k tokens
(was ~150k reading all 32 PhaseEnds). phase-ends/README.md + SETUP §7 pointer updated (R21).
- CURRENT_PHASE.md: the T3 🛑 block REFRESHED and SUPERSEDING the 09:30 one — written to be replayed: what happened in the
dead session (times, hashes, the overflow, the swept dir), what the successor did, the 44-stub census with every row's
state/draft path, the 10 banked with hashes+shas, the 9-step resume order with exact invocations, the file/tool
inventory and gotchas, carried context for T4/T5, environment, the plain-English recap; Log entry for the protocol change.
- .run/P32/t3/PROMPT_TEMPLATE.md (tracked): the verbatim agent prompts (Haiku / Haiku+twin / Sonnet escalation / Opus /
Sonnet) for launching the 17 queued rows under the amended output contract.
- memories updated outside the repo: checkpoint-current-phase-before-pause (the verbatim-replay contract; a dead session's
checkpoint is written by the successor from the transcripts) and session-start-list-rules-in-full (the ~100k protocol).
- verdict ledger .run/P32/t3/verdicts.jsonl rebuilt from the 31 T3 transcripts (agent_verdicts.py); every unbanked draft
re-verified with rtu_match in its real TU: 10 MATCH awaiting the gate (main func_80015B6C 120 + func_8002FDE8 73;
md_SC03_054 func_801EF6D8 604 + six jtbls; md_SC03_053 func_801EF734 44 + func_801EF7E4 72; md_MAIN_007
func_800CF148/2BC/EEFC/EF94/068) + func_800CF3B0 leaf-exact behind the TU's void/3-arg decl; 9 NEAR at exact length
(2/6/15/17/27/35/46/49/137), each with its class and inert-lever list
- R48 incident: one agent's `find .run/P32/t3/opus -maxdepth 1 -type f ! -name <mine> -exec mv {} _scratch/` swept 11
sibling deliverables (two MATCHes among them); found in _scratch/, restored to the contract paths, byte-verified;
tools/agent_drafts_restore.py (NEW: transcript replay) as the fallback; .gitignore allowlist for .run/P32/** so the
drafts, ledger and census files are committed (R20)
- harvest (R16/R30): cookbook §500 (10 banked closers, 10 MATCH closers, 9 NEAR classes, two NEW mechanisms — the
pinned-base-vs-pseudo-address alias basin and #line-equalised ASM_OPERANDS for cross_jump — and the wave-process
defects); wave-playbook §S80 addendum-2 (per-function work dirs, JSON-only final message, the 20-agent cap, the
recovery tools); accelerators P32 T3; decision-log P32 S82 (R31); SETUP tooling row (R21); cookbook-index
regenerated; .run/P32/t3/BRIEF.md output contract amended for the 17 queued launches
- CURRENT_PHASE: T3 row IN PROGRESS, Log entry, 🛑 SESSION CHECKPOINT (census 44 stubs / 5,313 ins with every row's
state and draft path, the 9-step resume order, the dead session's read-only T4 pre-read); harness task list rebuilt
- no src/ or config/ change in this commit; no fleet R22 has run since the 10 T3 banks — the resume order starts with one
Stubs 32 -> 31 after the func_80015760 bank (commit:3877); R22 fleet 213/213 (.run/S79_check_all_8.log);
main game-code 93.5% (38,854 / 41,534). Permuter ILS plateaus recorded with their residual named:
func_80015608 best 1, func_80039B20 best 7, func_80038698 pinned seed refused (11). The ILS runner
had reported "no waypoint" for 8 cycles in 20 s on a seed the permuter's C parser rejects; it now
prints [permuter] REFUSED and leaves PERMUTER_REFUSED.txt (positive-controlled on func_80038698).
Stubs 35 -> 32 after the #7 banks (commit:3873 commit:3874); R22 fleet 213/213 (.run/S79_check_all_7.log).
ov_SC05_018:func_80180BE0 and ov_SC06_010:func_801809E4 have NO draft: their ledger drafts were other
overlays' same-named functions (.run/backlog_drafts/<fn>.c is keyed by bare fn name) -> drafting pool.
config/wave_exclude.txt: main:func_80011380 pinned WALL with the §474 proof (fold-const split_tree +
stupid.c adjacency), 4 entries.
Stubs 38 -> 35 after the #6 banks (commit:3868 commit:3869 commit:3870 commit:3871); R22 fleet 213/213
(.run/S79_check_all_6.log); frontier_classify 35 rows (main 16, md_MAIN_003 5, resident 2, ov 12).
jtbl_pads_fix's PAD_ERR_MORE regex carried jtbl_rodata_pads' old wording and reported "no
pad-count drift" over a red build; it now accepts both spellings and, positive-controlled with a
deliberately short spec, reports "emits >4 table(s), spec declares 4". The deferred carves and
their blockers are itemised in §491 and in the checkpoint's task #7 brief.
800c3 (0x8005CE18-0x8005FC68, one contiguous run of 33 interleaved Sony objects) is now four
stub rows — libapi1 (21 BIOS trampolines + COUNTER), libpad1 (PADENTRY + PADMAIN 760), libapi2
(L02/L03), libpad2 (PADCMD PADIF PADPORTD PADSEQD WAITRC2) — fed by two WINDOWED psyq_integrate
calls from the raw .run/obj42/{libapi42,libpad421} dirs (integrate tiles each stub with one
library; every boundary checked against .text SECTION sizes). The apicard region's three
"game code" rows were libapi 4.2's C objects to the byte: 800c2 = FIRST.o (firstfile + the
"no jump table wall" stub func_80062144), 800c2_2 = PAD.o, 800c2_3 = PATCH.o + CHCLRPAD.o ->
apicard5/6/7; make_apicard_used.py sources libapi from 4.2 (the EXE's real libapi; libcard
stays 4.0) into .run/obj42/apicard_used, 26 objects / 7 blocks, no game code left in
0x80061F38-0x80062888. src/800c3.c (129 hand-matched "C", 62 verbatim bodies, 19 stubs incl.
the four §332 %lo-in-a-delay-slot "walls"), src/800c2.c, src/800c2_2.c, src/800c2_3.c removed;
REORDER_TUS is empty (mechanism kept). Cookbook §490.
Two stale instruments fixed: exclude_audit let a pinned WALL outrank LINKED (PopMatrix/
PushMatrix had sat as walls since S68 while living in libgte3, linked since Phase 8) — LINKED
dominates now, config/wave_exclude.txt 13 -> 3; frontier_classify carried a hard-coded 49-name
LINKED set (R51) and reported 337 "stubs" — derived from the Makefile now.
Verified: main 143dbb89f34491258bbc27810d0a12ec8b43a8dd WITH all SDK dirs and WITHOUT them from
a fresh extract; make tools-health OK; R22 fleet extract-all 212/212 + check-all 213/213.
Metrics: main REAL 839->773, LINKED 1,150->1,256, VERBATIM 29->3, stubs 29->16, byte-identical
2,075/2,091 = 99.2%; game-code weighted 93.3% (38,748/41,534), remainder 2,786 = the open-stub
sum; fleet stubs 51->38 (frontier_classify: 39 rows incl. the data word). Verbatim manifest
33 -> 6. Docs: worklist rows + "S79 task #5", SETUP (fresh-clone obj42 commands, Makefile
blocks, exclude_audit), decision-log "S79 addendum 2", accelerators "S79 (2)", CURRENT_PHASE
S79 FINAL refreshed (census, metrics, the task #6 brief).
The bounded hunt succeeded on its first lead. archive.org item
`play-station-programmer-tool-runtime-library-version-4.2.7z` (383 KB) is the PsyQ Runtime
Library 4.2 (LIB/*.LIB + INCLUDE, 1998-01-21) plus LIB/42PATCH/J421PD.ZIP — SCE R&D's
1998-02-26 "Libpad.lib version 4.2.1 for the Analog Controller (DUAL SHOCK)" patch, shipping
LIBPAD.LIB 4.2.1 with LIBAPI.LIB 4.2 and LIBPAD.H/LIBAPI.H/KERNEL.H.
Placed and byte-verified against the EXE (psyq_identify 0x8005CE18-0x800629DC, then
psyq_link.py per object): libpad 4.2.1 7/11 — PADENTRY, PADMAIN (760 ins, the 4.2.1 build,
exact), PADCMD, PADIF, PADPORTD, PADSEQD, WAITRC2 — and libapi 4.2 39/88 — the 21 band
trampolines, COUNTER, L02/L03, and the apicard-region C112/A50/A51/A54/A65/A67/A69/FIRST/A66/
PAD/A18-21/PATCH/CHCLRPAD. All 46 PASS. Neighbours for the record: plain libpad 4.2 and the
4.3 disc (DTL-S2340, 1998-05-18; PADMAIN 832 / PADIF 380 / PADSEQD 292) each place only 4;
4.2.1 is the unique exact match, so the game was built between Feb and May 1998.
Banked (R20): the 7z tracked under tools/psyq/ with sha256 + provenance in CHECKSUMS.sha256;
extracted to gitignored tools/psyq/lib42/ and lib421/ (the 4.2.1 headers are the band's
prototype oracle from now on); ELF in .run/obj42/{libpad421,libapi42}. Docs: psyq-worklist
"S79 task #13", SETUP archive table + §5.1 + S79 tool table, CURRENT_PHASE (#13 log; the S79
FINAL block's §5 records the archive and §6 is the re-scoped task #5 brief: link the whole
0x8005CE18-0x8005FC68 band and re-source the apicard region's libapi from 4.2).
The §9.1 "scattered .bss commons" exclusion class (Phase 8 → P31) is closed 3/3. New
tools/psyq_bss_split.py (own ELF32 REL reader/writer) cuts an object's packed .bss into
per-base NOBITS pieces: bases derived from the game bytes per HI16/LO16 pair, references
walked in offset order into single-base runs, cuts snapped to symbol starts (the linker
scattered SYMBOLS), symbols moved, a LOCAL section symbol per piece inserted, relocs
retargeted with the addend rewritten in the immediates, self-diffed. It runs inside the one
prepare step shared by psyq_link.link_object / psyq_link_region.build_region /
psyq_integrate.integrate (prepare_object before classify), re-derived every build.
GS_001.o was certified "5 interleaved bases, NOT splittable" by the S77 probe, which grouped
by BASE; by RUN it is six symbol-aligned pieces. All seven cuts across the three objects are
confirmed by the other objects' by-name recoveries (_que 0x800C5510, _svm_sreg_buf
0x800B9B58, PSDBASEX/CLIP2/PSDBASEY/POSITION/GsDRAWENV). R39 negative control: 235 placed
objects across 9 curated dirs, 0 refusals, exactly 3 splits (a libcd .bss+size end pointer
refused the first build → reference problems are fatal only when a split is needed).
Wiring: yaml 800c→libgpu2, sgap_6→sgap_6+snd12, gsgap3→libgs8 (comments rewritten);
LIBGPU_ELF := .run/obj40/libgpu (curated libgpu_used retired); libgs 34 objs/8 blocks
(make_libgs.sh +GS_001); snd 63/12 (make_snd_used.py exclusions 4→3). src/800c.c and
src/gsgap3.c removed (Sony code hand-matched as REAL/verbatim), sgap_6.c keeps only
func_8003FA54; splat-emitted libgpu2.c/libgs8.c/snd12.c stubs for the no-SDK fallback.
Verified: main 143dbb89f34491258bbc27810d0a12ec8b43a8dd WITH the SDK objects and WITHOUT
them from a fresh extract; make tools-health OK; R22 fleet clean extract-all 212/212 +
check-all 213/213. Metrics: main REAL 886→839, LINKED 1,040→1,150, VERBATIM 85→29, stubs 29
(unchanged); game-code weighted 91.1% (40,895/44,870) — both terms lost the 3,667 SDK ins;
the remainder is still exactly the 3,975-ins open-stub sum. Verbatim manifest --update
200→33 rows (subtractive). Docs: cookbook §489 (+index), psyq-worklist rows + "S78 task #4",
SETUP S79 R21 table, decision-log S79 addendum, accelerators S79, CURRENT_PHASE S79 FINAL 🛑.
- exact tiles, 0 tokens: libgte23-26 (MSC01/02/05/09, SMP_00, FGO_01-06, PATCHGTE), libgte9 re-derived
as SMP_05 NormalClip (SMP_06 NormalClipS = nested sub-pattern; psyq_integrate now drops nested
placements), libgte27-30 (the libgs-gap MTX_05/07/11, REG03+REG11), libgs7 (2D_BG0+2D_BG1), snd10
(VM_NO1), snd11 (VM_NOWON carved off sgap_8). LINKED 959->1040, REAL 912->886 (SDK inline-asm wrappers
re-provenanced), VERBATIM 146->85, 13 TUs deleted; splat re-emits the stub records.
- main 143dbb89 WITH and WITHOUT the SDK objects. The no-SDK fallback had been red since S7x
(CdReadyCallback called by its SDK name while the libcd stub carried func_800435B4) — curated
CdReadyCallback = 0x800435B4, refs unified. R22 clean fleet 213/213; tools-health OK.
- METRIC CORRECTION (R35): progress.py's "MAIN game-code weighted" sig never excluded the LINKED
objects (its comment said it did) — ~31k linked-SDK ins sat in the denominator as unmatched game
code. Exclusion now derived LIVE from the Makefile stub lists + yaml ranges: 91.8% (44,562/48,537),
not 59.8%; the 3,975-ins remainder equals the open-stub sum exactly.
- VM_F.o probed SPLITTABLE at .bss 0x50c (SYS.o's class -> task #4). cookbook §488; worklist S78 #3;
decision-log + accelerators; SETUP rows.
- provenance: the psx loader's per-version PsyQ signature sets place PADENTRY/PADCMD/PADPORTD/
PADSEQD (4.2), WAITRC2 (4.3), COUNTER/C114/FIRST/PAD/PATCH/CHCLRPAD (libapi 4.2) byte-exact in
0x8005CE48-0x8005FC68 / 800c2 -> 12 of main's 29 stubs incl. all four §332 walls are Sony's
DualShock library in reorder mode. 46 names -> symbols.us.txt (count 1081), band TUs, verbatim
manifest, wave_exclude; firstfile/firstfile2 (4.2 naming); CdGetToc @0x800430B8 (was the Phase-21
xdedup mislabel DecDCToutCallback). SETUP §5.1 corrected; psyq-worklist S78; cookbook §487;
decision-log + accelerators S78; CHECKSUMS +Psy-Q_46.zip +PSYQ_SDevTC_v4.5.zip.
- psyq_integrate: --yaml maps stub<->objects by SUBSEG RANGE with an exact-tiling check and PRINTS
the located-but-unwired residue (libgte: 13 objs / 1,264 ins) — main's LINKED build had been RED
at HEAD since the S77 psyq_identify fix (22 libgte blocks merged to 3; gate worktrees take the
stub fallback so it never showed); a library object's exported symbol whose recovered address the
curated file names differently is --redefine-sym'd (R15; A66 firstfile->firstfile2).
- Ghidra: 47 MCP renames did NOT persist through the sentinel stop (R9 caught it) -> NEW
tools/ghidra_scripts/ApplySymbols.java + tools/ghidra_apply_symbols.sh mirror the curated file
headless with a real save: 73 renamed, R9-verified x4. SETUP inventory rows (R21).
- lint_symbol_refs: scans verbatim __asm__ bodies (`.ent\tfunc_X` is invisible to \b and to the
string-masked scan); negative-controlled (red on the pre-fix TUs, green on the passing tree).
- R22: clean extract-all 212/212 + check-all green on the final config; main rebuilt byte-identical
143dbb89 after the last src-only fix -> 213/213; tools-health OK.
Drew ratified in-session after the S77 census: eight instrument defects, all one
shape — a tool asserting about a DRAFT what was true only of the HARNESS.
T11 4/7, T12 13 banked of a 34-draft pool, T13 R22 213/213 twice (a green
baseline before the overlay banks and again after all 17).
main REAL 895 -> 899, stubs 46 -> 42. Fleet stubs 82 -> 65, distinct-code
99.3% -> 99.4%, MAIN game-code 57.1% -> 57.3%.
Written for a fresh session: what banked, what did not and WHY (classified by
compiling each stranded draft in its real TU, not guessed), the five tool
defects and their fixes, the four refuted walls and the one proved, and the
five things I got wrong so the next session does not inherit them.
Headline state: REAL 895 (was 882), main game-code 57.1% instruction-weighted
(was 55.8%), 46 open stubs in main and 82 fleet-wide, 143dbb89 byte-identical.
R22 clean-fleet NOT run since the banks.
Next four tasks are logged with their evidence and their traps.
Verified at close rather than asserted: 25 commits, src/config/tools clean, main
green at 143dbb89..., and HEAD genuinely carries the func_8002B0B4 C (0
INCLUDE_ASM for SaveLoadRoutine, 1 real definition). A 47-minute bisection left
several mid-run readings that looked like regressions and were not, so the
figures are now stated from a settled tree.
Adds START HERE item 0: the UNPLACED parse hole is one line --
config/symbols.us.txt:27 still declares SaveLoadRoutine = 0x8002B154 // func, so
splat keeps emitting a .s for a symbol that is now case 0: inside func_8002B0B4.
Delete, re-extract, rebuild. config/wave_exclude.txt lines 14-15 are stale for
the same reason. Left undone only because a gate held main's tree at close.
T10 checklist now carries the S75 line.
Written for a fresh session. Headline: every codegen wall examined this session
was an instrument defect, and the two largest results came from deleting a
belief rather than writing better C -- SaveLoadRoutine's §434 wall was a splat
symbol boundary (it is case 0 of func_8002B0B4, one function on one frame), and
the '§332/§188 wall' was the reorder island, which banked 20 functions whose
drafts had been on disk since waves m04-m16.
Records what I got wrong so it is not inherited: five regex censuses
(116/112/108/178/199), contiguity mistaken for fragmentation, a build-config gap
called compiler-inexpressible, and two bursts drawn at fragments because the
triage came after the draw instead of before it.
R22 clean-fleet NOT run; the checkpoint says so at the top.
tools/asm_in_c.py finds 199 functions that are assembly posing as C (154 game
code, 171 in main). They were in no progress.py bucket, so main's REAL% was
overstated: 45.88% -> 42.15% once counted. Nothing regressed; the denominator
was missing 173 functions of real remaining work.
Also records the counting cautionary tale (five hand counts, 116->112->108->178
->199, each wrong the same way) and the tool design that answers it. Cookbook
§448.
Full 🛑 block for a fresh session: state, the seven defects (§442-§447), the
measured frontier map, Drew's dedup decision, and the harness lessons.
The headline for whoever picks this up: SaveLoadRoutine (1,165 ins, the §434
wall, 9.2% of all remaining work) has a BYTE-IDENTICAL body and is blocked by a
jump-table carve -- which the verdict tool could not say because that verdict
class was unreachable by construction on main.
R22 clean-fleet is NOT yet run for S75 and the checkpoint says so.
S74 handed this forward as "1,116 instructions behind one question": family_remap
on ov_SC01_004/005/006/008 gated DIFF 4/4 against the banked exemplar
ov_SC01_009:func_8017EB08, and the class had been carried as a codegen wall since
S70. The four bodies were byte-identical to the exemplar the entire time.
Word-level classification vs the exemplar, computed independently twice (a Fable
agent's script, then mine from scratch against the retail images), identical:
nins=279 EQ 213 · RELOC-HI16 23 · RELOC-LO16 24 · INTERNAL-J 19 · CODEGEN 0
Zero register-allocation, instruction-selection or scheduling differences.
ROOT CAUSE — tools/jtbl_carve.py reserved ONE WORD TOO MANY per table:
* spimdisasm runs an island's LAST `jtbl_` dlabel one word into the following
NON-ZERO data (string bytes 0x696F760A / 0x000013FF / 0x62647020), so the
zero-word trim cannot see it; and
* the over-span clamp that would have caught it was guarded by
`len(sltiu_bounds) == 1` -- but `sltiu` is ALSO how gcc emits an unsigned
range check ((u32)(x-lo) < n, I1). These four carry five distinct sltiu
immediates, so the guard silently disabled itself on precisely the functions
that needed it.
0x2C reserved for a 0x28 table => image 4 bytes short => ~850 %lo immediates
shift => whole-binary DIFF about a function whose own bytes are perfect.
Fixed with a PER-TABLE bound: gcc-2.7.2's dispatch is a fixed idiom, so the
`sltiu` nearest ABOVE that table's own %hi(jtbl_X) is unambiguous whatever else
the function tests. Second defect stacked behind it: a carve span whose
JTBL_PADS line lacks a `tables=` comment lost its existing table's start on
merge and refused "table starts do not fit the span" -- which harvest_verify
then "repaired" with a needless jr_isolate_all that walked back into the first.
THE NEGATIVE CONTROL IS THE STORY. Run over every other open table-bearing stub
fleet-wide, the fixed bound changed exactly one more table: ov_SC06_022/
func_80185B80 (185 ins), a FIFTH victim nobody had drafted against. A guard that
disables itself on a common idiom does not fail once -- it fails quietly across
the whole corpus.
Banked, each with its own byte-gate verdict (--no-propagate, clean re-gate):
func_8017EB30 ov_SC01_004 279
func_8017F2D4 ov_SC01_005 279
func_8017F2D4 ov_SC01_006 279
func_8017EC68 ov_SC01_008 279
func_80185B80 ov_SC06_022 185
Also here:
* dedup_propagate: memoize find_site's mask (lru_cache) -- 54 ms of masking
per call over the whole source, recomputed though it depends only on the
text. 2x on that loop (58.3 -> 33.0 ms/call), NC identical on 120 addrs.
Scoped honestly: that loop is ~2.4 min of a 30-min run; the profiler puts
43% in family_remap._alias_decl_for, which is NOT fixed here.
* Makefile: `clean` says out loud that BINARY= is ignored and it is fleet-wide
(cookbook §445) -- it silently deleted asm/ for all 213 binaries this session.
* Cookbook §446 (the carve law: when a standalone-MATCH jtbl draft gates DIFF,
diff the carve extent against 4 x sltiu before touching the body), §445, and
SETUP rows for both tools (R21).
* CURRENT_PHASE: the S75 log, incl. the measured fleet dedup-hygiene census
(~2,073 fns / ~12,116 items, all ALREADY MATCHED -- cleanup, not work) and
Drew's decision to leave it and gate --no-propagate from here.
The S74 checkpoint's "one unfixed defect that is actively costing banks"
(reconcile_tu manufacturing declaration conflicts), run to ground — plus the
harness gap that produced a false carve-corruption verdict.
reconcile_tu.py — three defects, measured against the real gcc-2.7.2 front end
(cdecl._cc1_accepts, the oracle cdecl.compatible was validated with; R33):
* The premise "a decl BELOW still conflicts" is TRUE at file scope and FALSE
at block scope. cc1 ACCEPTS a block-scope extern against a TU decl below it
(pedwarn "type mismatch with previous external decl"); conforming it is
destructive, because the TU's decl names the TU's TYPE and a type declared
below the splice point is not in scope AT it -- the emitted result gets
"syntax error before 'D_x'". Byte-witnessed on resident:func_800D06E8 (344
ins), whose block-scoped `extern Blk80078E78` became `extern
Struct80078E78`, typedef 388 lines lower. That construct is what this
ladder's OWN scope_demote_drafts (§8d) rung emits on purpose, and three
already-banked functions in that TU use it: one rung undoing another.
* The cast pass rewrote COMMENT PROSE -- 8 rewrites inside one header comment,
including inside a quoted cc1 diagnostic. Now matches on cdecl._mask
(length-preserving, so a mask offset is a source offset) and splices into
the original.
* `&sym` emitted `&` applied to a cast: legal for the scalar arm, `invalid
lvalue in unary '&'` (measured) for the array/fnptr/fnptr_array arms. `&`
now selects a pointer form and consumes itself -- but ONLY with no trailing
subscript, because `&sym[i]` is the address of ELEMENT i and the old code
had that case right. That last clause exists because the R39 negative
control caught the fold as a regression in the first cut of this fix.
gate_stage.py — `--skip-stages` / `GATE_SKIP_STAGES` (loud when used). Stage 0
gates raw drafts first, so a broken rung can only cost a RECOVERY, which is
exactly what makes it invisible: the function it destroys was already failing,
so its DIFF reads as a fact about the function.
verify_worktree.py / jr_isolate_all.py / parallel_gate.py — provision() now
symlinks every .run/sig.*.jsonl (main clone 259, provisioned worktree 0), the
third member of the class holding extracted/ and .run/obj40. parallel_gate was
fixed for this identical bug in S69: two provisioners, no shared list, found
twice; they now cross-reference each other. jr_isolate_all no longer swallows
the resulting FileNotFoundError into `except: continue` -- that turned a missing
index into a confident carve-CORRUPTION verdict over 2,603 of 2,603 functions
(R54). Adds _assert_scan_covered: attempted == raised means the scan measured
nothing, so its zero is an artifact, not a finding (R32).
Verification:
* 4 cc1 probes (the table above), each run on the pinned front end.
* R39 negative control over the stored-draft corpus: 661 adjudicated, 652
IDENTICAL, 9 CHANGED and every one an intended class. 4,173 of 4,864 drafts
unadjudicable (filenames that are not func_<ADDR>) -- stated, not hidden.
* jr_isolate_all ov_SC03_105 --dry-run: unchanged in the main tree.
* make clean/extract/build BINARY=resident -> 8e17e02f... BYTE-IDENTICAL.
Docs ship with the change (R21): cookbook §442/§443, index regenerated (1,112
sections), 3 docs/SETUP.md rows, CURRENT_PHASE S75 log.