9 Commits

Author SHA1 Message Date
Drew T 8a1a1a0d79 feat(phase-27 T6): migrate difficulty + exemplar_miner off hand-lists/proxies (R33) — before T7
The 26-A audit named difficulty's 136-entry BINARIES dict as the exact root cause corpus.py:9
describes (a hand-maintained allowlist over a filesystem that already answers the question), and
exemplar_miner's registered_addrs() as a ~60%-wrong proxy for "is this still work?". T7 onboards
new overlays, so these are migrated FIRST or the new binaries silently miss make report.

- exemplar_miner.py: "still a residual?" now = corpus.stubs(source) membership (the INCLUDE_ASM
  invariant, R33), not dp.registered_addrs() (config/dedup.us.yaml — a matched-but-unregistered
  fn, e.g. banked inline or matched-but-local, stayed wrongly in the residual pool).
- difficulty.py: the 136-entry hand-dict -> cfg_for(alias), deriving the mechanical layout
  (src/<a> + asm/<a>/nonmatchings; main/resident the two specials). Validated against the tree
  (src/<a> must exist -> a typo is a clean error, R32), not a hand-list. A newly-onboarded overlay
  now needs zero difficulty registration.
- new_overlay.sh: DROPPED difficulty from the sentinel-insertion set (T6 made it obsolete; leaving
  it would insert a dead dict entry into a file that no longer has a dict). The other 3 tools
  (diff_settings/progress/dup_report) keep their hand-lists — migrated one-at-a-time, byte-gated,
  per the audit's cadence; NOT dup_report.BINARIES, which corpus depends on as the binary list.

VERIFIED:
- difficulty derivation is BYTE-EXACT vs the old dict for all 136 aliases (0 mismatches), and
  old-tool vs new-tool output is byte-identical (.md AND .csv) on the same tree — the diff vs the
  committed docs was pure staleness (committed 2026-06-20, tree at 2026-07-15), NOT my change (R14).
- unknown alias -> clean error, not silent-empty output.
- exemplar_miner runs -> 223 residual stubs (corrected; it's a manual tool, not in make report).
- new_overlay.sh: bash + embedded-python both parse; difficulty absent from the insertion set.
2026-07-15 18:20:55 -06:00
Drew T 87136a024e feat(phase-15): T3 — onboard the remaining 118 overlays; full fleet 136/136 byte-identical
- onboarded all 118 not-yet-onboarded overlays via tools/new_overlay.sh (0 failed)
  -> fleet = 134 location overlays + main + resident = 136 binaries
- R22 CLEAN rebuild (make clean -> extract all 136 -> make check-all):
  136 passed, 0 failed of 136 -- every overlay byte-identical at 100% INCLUDE_ASM
  from a fully clean tree, 0 extract failures
- per-overlay config (splat.ov_*.yaml / check.ov_*.sha / symbols.ov_*.txt) +
  config/overlays.mk var blocks + the 4 report/diff BINARIES dicts auto-registered
  (sentinel-anchored, idempotent); src/ov_*/ stub records committed (harvest_verify
  reverts via git checkout, so the records must be tracked before any harvest)
- ghidra/ churn NOT staged (R23); build/asm/assets/.run gitignored
- report-digest regen (fleet-wide duplicates.cross.md + progress.fleet.md) is T4
2026-06-16 19:41:37 -06:00
Drew T e5a2bd4083 feat(phase-15): T1 — onboard diverse wave-1 (12 overlays); fleet 18/18 byte-identical
- onboarded ov_{SC01_000,SC01_001,SC02_000,SC02_003,SC03_002,SC03_006,
  SC04_000,SC04_018,SC04_019,SC05_000,SC06_000,SC07_000} via tools/new_overlay.sh
  — spans all 7 SC areas + 2 full duplicate pairs (SC02_000≡003, SC04_018≡019)
- each byte-identical at 100% INCLUDE_ASM (non-4-aligned auto-handled); no
  position-lock anomalies — the cross-shape risk is retired before the full onboard
- make check-all = 18/18 passed (main + resident + 4 prior + 12 new)
- config/overlays.mk + 4 report dicts auto-registered (sentinel, idempotent)
- ghidra/ DB churn NOT staged (R23); asm/build/assets/.run gitignored
2026-06-16 19:02:14 -06:00
Drew T 67592993ea feat(phase-13): T3+T4 — new_overlay.sh + dup-pair & free-roam onboarded byte-identical
- tools/new_overlay.sh: one-command overlay onboarding (template instantiate +
  @TRAILING@ carve + overlays.mk + 4-dict sentinel-insert + extract/build/check);
  idempotent (re-run = no-op, no dupe entries)
- T3: ov_SC03_001 (free-roam, 815,887 B) byte-identical f8fd92f5
- T2 (onboard): ov_SC01_005 + ov_SC01_006 (byte-identical pair) both 56760dbe
- template tokens unquoted (correct YAML int types); SETUP §2.8 MCP-reconnect note (R21)
- 6 binaries now build byte-identical (main, resident, 4 overlays)
2026-06-16 16:44:01 -06:00
Drew T 144839f24b feat(phase-13): T1a/T1b — SC01/077 onboarded + all-asm byte-match (d19c9580)
- ov_SC01_077 scaffolded: config/overlays.mk (OVERLAY_BINARIES + var block),
  config/splat.ov_SC01_077.yaml (from template), check.sha, empty symbols, +
  ov_SC01_077 entry & sentinel anchor in the 4 Python BINARIES dicts
- GATE T1b: make check BINARY=ov_SC01_077 -> d19c9580 BYTE-IDENTICAL @ 100%
  INCLUDE_ASM; clean rebuild leaves main 143dbb89 + resident 8e17e02f unregressed
- reusable non-word-aligned-overlay handling (~75% of fleet) added to the
  template + Makefile: (1) [word_floor, bin, trailing] carve for the final 1-3
  bytes spimdisasm drops; (2) build/assets/%.o incbin rule (+ .data align=1) for
  splat bin assets (asset_path scoped per-alias); (3) objcopy end-align TRIM
  (shrink-only, <=3 B) removing the .ld's segment-end ALIGN(.,4) pad
- .gitignore /assets/ (regenerable splat output); clean removes assets/
2026-06-16 15:39:52 -06:00
Drew T cc73951128 feat(phase-10): T3 — per-binary reports/diff/expected for the resident binary
- 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)
2026-06-15 23:06:25 -06:00
Drew T 22b20e8f31 refactor(phase-9): T6 — --binary selector for dup_report + difficulty; report threads BINARY
- dup_report.py + difficulty.py: argparse --binary (default main) + BINARIES table
  (main = current sig/src/asm/md/csv paths); overlay src/asm subtree deferred to P10
- Makefile report target threads --binary $(BINARY) to progress/difficulty/dup_report
- no-op proof: docs/progress.md + docs/duplicates.md UNCHANGED; difficulty.py old-code
  vs new-code output IDENTICAL (pure path-table refactor)
- docs/difficulty.md regenerated (the Phase-8-deferred regen: 9 harvested funcs left
  the unmatched queue — 12/12 row shift); build path untouched (still 143dbb89)
2026-06-15 20:46:48 -06:00
Drew T 8ffb7f0607 feat(phase-7): -O0 split + 4 matches (42 real) + libcd.h — session B checkpoint
- per-file -O0 mechanism: split text c-subseg into boot@-O0 (src/boot.c) + 800@-O2
  via splat resegmentation + Makefile target-specific CC1FLAGS; the boot/main/
  game-mode-dispatch module (0x80010000-0x800123F0) is -O0, not the pinned -O2
  (per-module compiler mixing, SETUP §5.5). Regression-gated byte-identical.
- 4 byte-matches (38->42 real, make check BYTE-IDENTICAL throughout): GameModeDispatch
  (-O0 register-ptr far member), DebugMenuHandler (-O0 reserved-slot local), CdQueueBusy
  (-O2 if/else order + branch polarity), CdReadRequest (-O2 early-return fall-through)
- PsyQ infra: include/psyq/libcd.h (CdlLOC/CdlFILE from the .gdt) + 4 named symbols
  (CdSearchFile/CdPosToInt/CdIntToPos/VSync) in symbols.us.txt; func_* stubs renamed
- loader cluster non-jtbl COMPLETE (6 matched + 2 drafted): NON_MATCHING drafts of
  LoaderInitFileTable + ResourceLoadStateMachine (logically faithful, residuals in-source)
- tooling: progress.py/difficulty.py fixed for the multi-file split (glob src/*.c, all
  asm dirs, skip forward-decls); deterministic; 42 real / 4 NM
- flywheel: matching-cookbook §6 (-O0 detection + idioms), §7 (PsyQ types/symbols), T4
- build byte-identical 143dbb89f34491258bbc27810d0a12ec8b43a8dd from a full clean cycle
2026-06-14 19:37:05 -06:00
Drew T 379185a799 feat(phase-7): matching reports + 24 matches (38 real) — session A checkpoint
Mid-phase checkpoint (Drew-directed; phase NOT closed — R8 exception).

- reports (Task 3): tools/{progress,difficulty,dup_report}.py + `make report`
  (deterministic) + `make sig-refresh`; authoritative baseline 38 real / 2050
  matchable; empties audit 42/42 genuine jr;nop; docs/{progress,difficulty,
  duplicates}.md digests
- matches (Tasks 4-5): +24 byte-identical (22 accessor leaves via the harvest
  pattern + ResourceGetCdLoc + LoaderResetReadState); make check BYTE-IDENTICAL
  throughout (143dbb89...)
- config/symbols.us.txt: declare func_80047CAC (R15) — fixes a latent
  non-reproducibility (spimdisasm 1.41.0 auto-detect of an 8B inter-fn blob was
  unstable across clean extracts; the committed Phase-6 baseline did not
  deterministically rebuild)
- Task 1 rodata-island foundation: investigated (migration co-locates jump
  tables + resolves refs, but byte-identity blocked by splat global-migration +
  contiguous linker placement vs BFM's monolithic segment) -> DEFERRED to Task 2'
  with a candidate fix; full findings in phase-ends/CURRENT_PHASE.md
- phase-ends/CURRENT_PHASE.md: reordered plan, loader-cluster triage, per-session
  green-check log (1 of >=3 needed for the Gen1-exit milestone)
2026-06-14 17:36:12 -06:00