docs(phase-32): session-start protocol → phase-ends/DIGEST.md + last 3 PhaseEnds (~100k tokens), checkpoint replayed VERBATIM (R64 candidate); the T3 checkpoint refreshed to the verbatim-replay standard

- 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).
This commit is contained in:
Drew T
2026-09-05 10:02:04 -06:00
parent 9480c979a0
commit 42ff6116ea
7 changed files with 510 additions and 101 deletions
+1
View File
@@ -252,6 +252,7 @@ unsloth_compiled_cache/
!/.run/P32/t3/verdicts.jsonl
!/.run/P32/t3/pending_launch.txt
!/.run/P32/t3/harvest_notes.md
!/.run/P32/t3/PROMPT_TEMPLATE.md
!/.run/P32/t3/haiku/
/.run/P32/t3/haiku/*
!/.run/P32/t3/haiku/func_*.c
+40
View File
@@ -0,0 +1,40 @@
# T3 agent prompt templates (extracted verbatim from the launching session c6a5fb71 on 2026-09-05 by the successor session)
Use these to launch the 17 queued rows in `pending_launch.txt` (substitute fn / binary / nins / sub / paths; keep the arm).
AMENDED CONTRACT (playbook §S80 addendum-2, already in BRIEF.md): the final message is the JSON line ONLY; scratch only under
`.run/P32/t3/work/<fn>/`; never find/rm/mv in a shared dir. Add one sentence to each prompt saying so.
## Haiku, never-drafted row (func_801F0048, md_SC03_054) — model=haiku — desc: Draft func_801F0048 (md_SC03_054)
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_801F0048 in binary md_SC03_054 (20 instructions, never drafted). Arm: haiku. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_801F0048.md. Target asm (read IN FULL): asm/md_SC03_054/nonmatchings/md_SC03_054/func_801F0048.s. Destination TU: src/md_SC03_054/md_SC03_054.c (read its banked siblings, e.g. func_801F0098, for house style). sub = md_SC03_054. Write your best draft to .run/P32/t3/haiku/func_801F0048.c. Check with `.venv/bin/python tools/match_one.py func_801F0048 --c <draft> --asm-subdir asm/md_SC03_054/nonmatchings/md_SC03_054 --work .run/P32/t3/work/func_801F0048`, then `.venv/bin/python tools/rtu_match.py func_801F0048 --split md_SC03_054 --source md_SC03_054 --c <draft> --asm-subdir asm/md_SC03_054/nonmatchings/md_SC03_054 --work .run/P32/t3/rtu/func_801F0048`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md.
```
## Haiku, row with a twin hint (func_800CF068, md_MAIN_007 ← md_MAIN_008:0x800cee44 d=5) — model=haiku — desc: Draft func_800CF068 (md_MAIN_007)
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_800CF068 in binary md_MAIN_007 (21 instructions). A near twin exists: md_MAIN_008:0x800cee44 (edit distance 5). Start from `.venv/bin/python tools/family_remap.py --addr 0x800cee44 --from md_MAIN_008 --to md_MAIN_007 --to-addr 0x800cf068 --out .run/P32/t3/haiku/func_800CF068.c` (it remaps the per-binary symbols; if it refuses, write the body from the .s using the twin's C in src/md_MAIN_008/md_MAIN_008.c as the shape), then fix the structural differences the real-TU diff shows. Arm: haiku. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_800CF068.md. Target asm (read IN FULL): asm/md_MAIN_007/nonmatchings/md_MAIN_007/func_800CF068.s. Destination TU: src/md_MAIN_007/md_MAIN_007.c. sub = md_MAIN_007. Draft path: .run/P32/t3/haiku/func_800CF068.c. Check with `.venv/bin/python tools/match_one.py func_800CF068 --c <draft> --asm-subdir asm/md_MAIN_007/nonmatchings/md_MAIN_007 --work .run/P32/t3/work/func_800CF068`, then `.venv/bin/python tools/rtu_match.py func_800CF068 --split md_MAIN_007 --source md_MAIN_007 --c <draft> --asm-subdir asm/md_MAIN_007/nonmatchings/md_MAIN_007 --work .run/P32/t3/rtu/func_800CF068`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md.
```
## func_801EF734 (Haiku first launch, then the Sonnet ESCALATION with the shape hint) — model=haiku — desc: Draft func_801EF734 (md_SC03_053)
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_801EF734 in binary md_SC03_053 (44 instructions, never drafted). Arm: haiku. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_801EF734.md. Target asm (read IN FULL): asm/md_SC03_053/nonmatchings/md_SC03_053/func_801EF734.s. Destination TU: src/md_SC03_053/md_SC03_053.c. sub = md_SC03_053. Write your best draft to .run/P32/t3/haiku/func_801EF734.c. Check with `.venv/bin/python tools/match_one.py func_801EF734 --c <draft> --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/work/func_801EF734`, then `.venv/bin/python tools/rtu_match.py func_801EF734 --split md_SC03_053 --source md_SC03_053 --c <draft> --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/rtu/func_801EF734`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md.
```
## func_801EF734 (Haiku first launch, then the Sonnet ESCALATION with the shape hint) — model=haiku — desc: Draft func_801EF734 (md_SC03_053)
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_801EF734 in binary md_SC03_053 (44 instructions, never drafted). Arm: haiku. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_801EF734.md. Target asm (read IN FULL): asm/md_SC03_053/nonmatchings/md_SC03_053/func_801EF734.s. Destination TU: src/md_SC03_053/md_SC03_053.c (read its banked siblings for house style). sub = md_SC03_053. Write your best draft to .run/P32/t3/haiku/func_801EF734.c. Check with `.venv/bin/python tools/match_one.py func_801EF734 --c <draft> --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/work/func_801EF734`, then `.venv/bin/python tools/rtu_match.py func_801EF734 --split md_SC03_053 --source md_SC03_053 --c <draft> --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/rtu/func_801EF734`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md.
```
## func_801EF734 (Haiku first launch, then the Sonnet ESCALATION with the shape hint) — model=sonnet — desc: Escalate func_801EF734 (md_SC03_053) to Sonnet
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_801EF734 in binary md_SC03_053 (44 instructions). ESCALATION: a Haiku drafter plateaued at 47 instructions with its draft at .run/P32/t3/haiku/func_801EF734.c — its three if-arms each emit their OWN `jal` where the target CONVERGES on one shared tail call (44 ins). That is a C structure question, not a compiler wall: make the arms only compute/assign the arguments and FALL THROUGH (or `goto` one shared label) to a SINGLE call site so gcc emits one jal; read the target's branch structure to see which arm is the fall-through and which ones jump to the shared tail. Arm: sonnet. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_801EF734.md, then the Haiku draft above (correct semantics, wrong shape). Target asm (read IN FULL): asm/md_SC03_053/nonmatchings/md_SC03_053/func_801EF734.s. Destination TU: src/md_SC03_053/md_SC03_053.c (read its banked siblings — several are the same script-module shape). sub = md_SC03_053. Write your best draft to .run/P32/t3/sonnet/func_801EF734.c. Check with `.venv/bin/python tools/match_one.py func_801EF734 --c <draft> --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/work/func_801EF734s`, then `.venv/bin/python tools/rtu_match.py func_801EF734 --split md_SC03_053 --source md_SC03_053 --c <draft> --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/rtu/func_801EF734s`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md (arm "sonnet").
```
## Opus, old near/far row (func_800CD92C, md_MAIN_009) — model=opus — desc: Draft func_800CD92C (md_MAIN_009)
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_800CD92C in binary md_MAIN_009 (247 instructions, never drafted before; md_MAIN_009 is a freshly onboarded module at 0x800CD348). Arm: opus. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_800CD92C.md. Target asm (read IN FULL): asm/md_MAIN_009/nonmatchings/md_MAIN_009/func_800CD92C.s. Destination TU: src/md_MAIN_009/md_MAIN_009.c. sub = md_MAIN_009. Write your best draft to .run/P32/t3/opus/func_800CD92C.c. Check with `.venv/bin/python tools/match_one.py func_800CD92C --c <draft> --asm-subdir asm/md_MAIN_009/nonmatchings/md_MAIN_009 --work .run/P32/t3/work/func_800CD92C`, then `.venv/bin/python tools/rtu_match.py func_800CD92C --split md_MAIN_009 --source md_MAIN_009 --c <draft> --asm-subdir asm/md_MAIN_009/nonmatchings/md_MAIN_009 --work .run/P32/t3/rtu/func_800CD92C`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md.
```
## Sonnet, mid-size row (func_800CEE2C, md_MAIN_007) — model=sonnet — desc: Draft func_800CEE2C (md_MAIN_007)
```
Byte-match ONE function for the Brave Fencer Musashi matching decomp. Repo: /home/musashi/bfm-decomp (run every command from there). Target: func_800CEE2C in binary md_MAIN_007 (52 instructions, the module's first function, never drafted). Arm: sonnet. READ FIRST, in order: .run/P32/t3/BRIEF.md, .run/P32/t3/SYS.md, .run/P32/t3/packs/func_800CEE2C.md. Target asm (read IN FULL): asm/md_MAIN_007/nonmatchings/md_MAIN_007/func_800CEE2C.s. Destination TU: src/md_MAIN_007/md_MAIN_007.c (a boot-slot module TU that stacks only config/symbols.us.txt). sub = md_MAIN_007. Write your best draft to .run/P32/t3/sonnet/func_800CEE2C.c. Check with `.venv/bin/python tools/match_one.py func_800CEE2C --c <draft> --asm-subdir asm/md_MAIN_007/nonmatchings/md_MAIN_007 --work .run/P32/t3/work/func_800CEE2C`, then `.venv/bin/python tools/rtu_match.py func_800CEE2C --split md_MAIN_007 --source md_MAIN_007 --c <draft> --asm-subdir asm/md_MAIN_007/nonmatchings/md_MAIN_007 --work .run/P32/t3/rtu/func_800CEE2C`. Do NOT edit anything under src/ or config/. End your final message with the single-line JSON verdict specified in BRIEF.md.
```
+24 -14
View File
@@ -4,24 +4,33 @@ Matching decompilation of **Brave Fencer Musashi** (PS1, SLUS-00726 USA). Goal:
## Session Start Protocol — Do This First, Every Session
Before doing any work, read these files in this order:
**Budget: the whole protocol should cost about 100k tokens plus the verbatim checkpoint block** (Drew, 2026-09-05; R64
candidate). Read these files in this order — nothing else at session start:
1. Read `PROJECT_CONTEXT.md` in full (the permanent constitution: rules, protocols, roadmap).
2. Read every `phase-ends/PhaseEnd_*.md` in numeric order (the build history). **Do NOT read `phase-ends/logs/`** — those are on-demand worklog archives (R19), deliberately out of the load order; consult one only when researching a past mechanism (see the `phase-worklogs-reference-only` memory).
3. Read `phase-ends/CURRENT_PHASE.md` if it exists (the in-phase state).
4. Then follow the **Session Start Protocol** in `PROJECT_CONTEXT.md` — state phase, completed tasks, the single next task, and acknowledge the rules before working.
5. **For matching phases (Phase 6+):** before any function matching, also read `docs/matching-cookbook.md` (reusable compiler idioms asm↔C + techniques) and `docs/SETUP.md` §5.4 (the pinned triple). The matching knowledge base is a **compounding flywheel** — consult it before each match, and after each match (especially a hard-won near-miss) feed the generalizable lesson back into BOTH the cookbook AND the tooling (`tools/permuter/` PERM_ recipes/weights, the m2c `--context`) so future similar functions one-shot.
2. Read `phase-ends/DIGEST.md` in full — every phase's synopsis, every rule's full text (R1–R64), the corrections that
supersede parts of PROJECT_CONTEXT.md, and the doc map. It REPLACES reading every PhaseEnd (the PhaseEnds are still
kept forever — read an older one on demand when a synopsis is not enough; **never** read `phase-ends/logs/` at
session start, R19).
3. Read the **three most recent** `phase-ends/PhaseEnd_*.md` in full, in numeric order.
4. Read `phase-ends/CURRENT_PHASE.md` in full if it exists (the in-phase state).
5. For matching phases (Phase 6+): read `docs/matching-cookbook.md`'s first ~120 lines (the pinned triple + §1–§3) and its
most recent § only, and `docs/SETUP.md` §5.4 (the pinned triple). The cookbook is 3.5 MB and `docs/cookbook-index.md`
is 566 KB: grep them by §/symptom during matching, never read them whole. The knowledge base is a **compounding
flywheel** — consult it before each match, and after each match feed the generalizable lesson back into BOTH the
cookbook AND the tooling (`tools/permuter/` recipes, the m2c `--context`) so future similar functions one-shot.
After reading, state the following and nothing else:
- Current phase number and name
- Which tasks in the current phase are already complete
- Which single task is NEXT
- The recommended **effort level** for that NEXT task per `docs/effort-map.md`, and confirm the developer has it set (Effort-map check)
- Every AI Collaboration Rule from the context file plus every rule added in any PhaseEnd file's "Rules Added This Phase" section
After reading, state the following and nothing else, in this order:
- Current phase number and name; which tasks in the current phase are already complete; which single task is NEXT
- The recommended **effort level** for that NEXT task per `docs/effort-map.md`, and confirm the developer has it set
- Every AI Collaboration Rule from `PROJECT_CONTEXT.md` (P/G/H/X) plus every R-rule, **in full text**, transcribed from
`phase-ends/DIGEST.md` §3
- **The last `## 🛑 SESSION CHECKPOINT` block of `phase-ends/CURRENT_PHASE.md`, reproduced VERBATIM and in full** — not
summarized. That block is written to be replayed: it is the complete seed for this session and it is the ONLY in-phase
context this session inherits from the previous one.
Then wait for the developer to confirm before doing anything.
Do not summarize the project. Do not list all remaining tasks. Do not start working. State what is next, list the rules, and wait.
Then wait for the developer to confirm before doing anything. Do not summarize the project. Do not list all remaining
tasks. Do not start working. State what is next, list the rules, replay the checkpoint, and wait.
---
@@ -119,6 +128,7 @@ When a phase milestone is confirmed complete:
1. State: "🟡 PhaseEnd creation is a Tier 1 task. Confirm when ready."
2. Wait for confirmation.
3. Create the `PhaseEnd_Phase[N].md` file using the Write tool, taking time to reason carefully about the phase as a whole.
3b. Append the phase's synopsis and its ratified rules to `phase-ends/DIGEST.md` (the session-start digest; a P7 checkbox — a PhaseEnd without its digest entry is not closed).
4. Final message: "PhaseEnd file created. Commit the file and start a new Claude Code session for the next phase."
5. HARD STOP. Do not preview the next phase. Do not continue working. Do not suggest what comes next.
+6
View File
@@ -647,6 +647,12 @@ The tooling-inventory rows below are the per-tool REFERENCE; the playbook is the
## §7 Session-start ritual
> **Claude Code load order (2026-09-05, R64 candidate):** `PROJECT_CONTEXT.md` → `phase-ends/DIGEST.md` (all phase synopses + all
> rules in full) → the THREE most recent `phase-ends/PhaseEnd_*.md` → `phase-ends/CURRENT_PHASE.md`, then the 🛑 SESSION
> CHECKPOINT block is replayed VERBATIM into the chat. Budget ≈100k tokens + the checkpoint. Never read all PhaseEnds,
> `phase-ends/logs/`, the whole cookbook or `docs/cookbook-index.md` at session start (CLAUDE.md is the authority).
> The Ghidra steps below apply only to RE sessions (G2) — the MCP server now runs headless via the SessionStart hook.
Order is load-bearing — MCP tools fail (sometimes silently) without an open program.
1. **Start Ghidra** (in WSL, under WSLg): `~/ghidra_12.1_PUBLIC/ghidraRun`.
+202 -86
View File
@@ -120,6 +120,7 @@ cookbook before the next drafting step (R16/R30) · no `Co-Authored-By` trailer
needed for T0–T2b; if T2d needs it: `tools/ghidra_mcp_start.sh` → pause → Drew runs `/mcp` (R29) → G2 ping.
## Log
- 2026-09-05 (successor session, later) — **Session-start protocol rewritten at Drew's direction (R64 candidate):** `phase-ends/DIGEST.md` created (every phase synopsis + every rule in full + the PROJECT_CONTEXT corrections + the doc map); CLAUDE.md load order = PROJECT_CONTEXT → DIGEST → the three most recent PhaseEnds → CURRENT_PHASE, ≈100k tokens, the 🛑 block replayed VERBATIM; Phase Boundary step 3b maintains the digest (P7); `phase-ends/README.md` + SETUP §7 updated; the two memories (`checkpoint-current-phase-before-pause`, `session-start-list-rules-in-full`) + MEMORY.md updated; `.run/P32/t3/PROMPT_TEMPLATE.md` saved (verbatim agent prompts). The 🛑 block below was REFRESHED to the verbatim-replay standard and SUPERSEDES the 09:30 block. Ratify R64 at PhaseEnd_Phase32.
- 2026-09-05 09:30 MDT — **T3 CHECKPOINT by the successor session (Max, Fable 5.1) after the launching session died.** The T3 coordinator (session c6a5fb71) banked 10 functions in 9 commits (T3 (1)–(9), 01:01–01:07 MDT) and then hit "Prompt is too long" at 01:07 MDT; 22 agent completions (07:07Z–08:04Z) arrived into a dead session. Recovered via the recorded route: `agent_verdicts.py` over the 31 task transcripts → `.run/P32/t3/verdicts.jsonl` (20 MATCH / 9 NEAR / 2 FAIL); every unbanked draft re-verified with `rtu_match` in its real TU (10 MATCH confirmed). **Instrument incident (R48 class):** one agent's tidy-up (`find .run/P32/t3/opus -maxdepth 1 -type f ! -name func_800CD674.c -exec mv {} _scratch/`, 07:52Z) had swept 11 sibling Opus deliverables — found in `_scratch/`, moved back, byte-verified at the reported closeness; `tools/agent_drafts_restore.py` (NEW — transcript replay) written as the fallback; `.gitignore` allowlist for `.run/P32/**` so the drafts/ledger/census are committed (R20). Harvest written IN-SESSION (R16/R30): cookbook **§500** (10 banked closers, 10 MATCH closers, 9 NEAR classes, two NEW mechanisms — the pinned-base alias basin and `#line`-equalised ASM_OPERANDS — and the process defects); `docs/wave-playbook.md` §S80 addendum-2 (per-function work dirs, JSON-only final message, the 20-agent cap, the recovery tools); `docs/accelerators.md` P32 T3; `docs/decision-log.md` P32 S82 (R31); SETUP row (R21). Read-only T4 pre-check results from the dead session preserved in the 🛑 block. Effort: this checkpoint at Max; **T3 resumes at xHigh** (R27).
- 2026-09-05 — gate 1 approved; T0 opened at HEAD `commit:3900`.
- 2026-09-05 — **T3 LAUNCHED** (xHigh): 47 targets = census 54 − 7 pinned walls (`.run/P32/t3/targets.json`, 5,288 ins); packs built (`claude_wave_packs`, 47/47 neighbours, 10 journals); brief `.run/P32/t3/BRIEF.md`. **20 Agent-tool drafters running** (16 Opus: the 11 old near/far rows + resident func_800D06E8 + the 4 largest new bodies · 3 Sonnet · 1 Haiku); **27 Haiku queued** behind the harness's 20-concurrent cap (`.run/P32/t3/pending_launch.txt`, launched one per freed slot). Recovery + per-result route: `.run/P32/t3/LAUNCHED.md`.
@@ -129,105 +130,220 @@ cookbook before the next drafting step (R16/R30) · no `Co-Authored-By` trailer
- 2026-09-05 — **T1a DONE — `resident:func_800D128C` BANKED (243 ins, byte-identical 8e17e02f, R22 213/213).** The stored S71 closeness-0 draft was byte-correct all along; the whole task was three instrument defects the resident (the fleet's one `common.h`-only, `--pre`-sandwich binary) exposed in overlay-only assumptions: (1) `jr_isolate_all` dropped a file-local typedef whose name engine_types.h also defines (§496 — fixed: provided types derived from the TU's own includes); (2) `jtbl_carve` regenerated `JTBL_INTERLEAVE` without the `--pre hdr.rodata.o` clause → extract refused → the gate linked a stale script and booked the byte-correct draft as DIFF; `harvest_verify` ignored that extract's rc (§498 — both fixed, R49/R61); (3) `interleave_check` read a `--pre` line as n=0 (false DRIFT; fixed). R38 then found two more stored MATCH bodies for T1b/T1c (see their rows). Effort stayed Max.
- 2026-09-05 — **T0 DONE.** Baseline reads all green (`.run/P32/t0_baseline.log`): `verbatim_check --strict` 5 bodies == 5 rows; `exclude_audit --assert-fresh` 8 entries, 8 WALL, 0 stale; `frontier_classify` → 21 rows = the S80 census exactly; `make tools-health` OK (sigs fresh, corpus(+resident), cdecl, audit-binaries 213/213, report lint+dedup, cookbook-index, split_indicator 213 OK); `make check-all` 213 passed / 0 failed, rc 0. Harness task list #1–#11 built (R28). NEXT = T1a.
## 🛑 SESSION CHECKPOINT — T3 MID-WAVE (2026-09-05 09:30 MDT; written by the successor session after the launching coordinator overflowed)
Written for a FRESH SESSION with none of this context. Phase 32 plan approved (gate 1, Drew, 2026-09-05, Max, Fable 5.1);
rules R44–R63 ratified. **T0–T2d DONE. T3 (task #9) IN PROGRESS — resume it at xHigh (R27; Drew sets the effort).**
Fleet **218/218** byte-identical at the last R22 (T2c close, `.run/P32/t2c/r22.log`); the 10 T3 banks since were each
built byte-identical in their own binary (main `143dbb89…` ×3 via `gate_main`, resident `8e17e02f…`, md_SC03_053
`c0848f30…` ×4, md_SC03_054 `06bd73df…`, md_MAIN_007 `2ff702b6…`) — **no fleet R22 has run since those banks: run one
before the first new bank** (R22/R58; a stale `.o` can false-pass). Non-ghidra `git status` was clean at this checkpoint;
`ghidra/` churn is R23 restart-noise — never stage it.
## 🛑 SESSION CHECKPOINT — T3 MID-WAVE, REFRESHED (2026-09-05 10:01 MDT; written by the successor session e40106e1; SUPERSEDES the 09:30 block)
### What happened in T3 so far (the facts a fresh session needs)
- **The wave:** 47 targets = the T2c census (54) minus the 7 pinned walls; packs `.run/P32/t3/packs/<fn>.md`, brief
`.run/P32/t3/BRIEF.md`, laws `.run/P32/t3/SYS.md`, targets `.run/P32/t3/targets.json`. Model ladder Haiku ≤50 /
Sonnet ≤120 / Opus >120 + the 11 old near/far rows on Opus. One Agent-tool subagent per function; the harness caps
concurrency at 20, so **31 launched, 17 Haiku rows still queued in `.run/P32/t3/pending_launch.txt`** (with their
twin hints; `md_SC03_054:func_801F00C8` needs a hand-adapt — `family_remap` refused, reloc-count 1≠2).
- **The coordinator (session c6a5fb71) banked 10 functions in 9 commits `commit:3923`..`commit:3931` (01:01–01:07 MDT),
then hit "Prompt is too long" at 01:07 MDT.** 22 agent completions (07:07Z–08:04Z) arrived into the dead session.
This checkpoint harvested them: `.run/P32/t3/verdicts.jsonl` (31 rows: **20 MATCH / 9 NEAR / 2 FAIL**), rebuilt with
`tools/agent_verdicts.py /tmp/claude-1000/-home-musashi-bfm-decomp/7beebba8-05e9-4d18-98ea-ce208f45370f/tasks/a*.output`
(the transcripts themselves: `~/.claude/projects/-home-musashi-bfm-decomp/c6a5fb71-f2ae-4846-a4a9-a43a4c1c3496/subagents/`).
- **Every unbanked draft was re-verified by the successor with `rtu_match` in its real TU** (results match the agents'
verdicts exactly). The Opus deliverables had been swept into `.run/P32/t3/opus/_scratch/` by one agent's tidy-up
(07:52Z, `find … -exec mv`) — moved back to `.run/P32/t3/opus/<fn>.c` and byte-verified; `tools/agent_drafts_restore.py`
(NEW) replays a transcript if a deliverable ever goes missing again. The drafts + ledger are git-tracked now.
- **Harvest already written (R16/R30):** cookbook **§500** (every closer, the 9 NEAR classes with their inert-lever
lists, two NEW mechanisms, the process defects) · `docs/wave-playbook.md` §S80 addendum-2 · `docs/accelerators.md`
P32 T3 · `docs/decision-log.md` P32 S82. The 8 orchestrator notes in `.run/P32/t3/harvest_notes.md` are subsumed.
### 0. How to use this block
You are a FRESH SESSION that has read `PROJECT_CONTEXT.md`, `phase-ends/DIGEST.md`, `PhaseEnd_Phase29/30/31.md` and this
file, and nothing else (CLAUDE.md protocol, R64 candidate). Replay this block verbatim into your chat, state phase / done /
NEXT / effort, list the rules from the digest, then WAIT for Drew. When he confirms, follow §5 in order. **Effort: xHigh
for T3 and T4** (R27 — Drew sets it; if the status line does not say xHigh, prompt before the first command); **Max only
for T5.** Drafter ladder Haiku ≤50 ins / Sonnet ≤120 / Opus >120; Fable only if an agent names a wall class the codegen
map lacks — STOP and prompt Drew first. No Workflow / Ultracode in T3: one Agent-tool subagent per function.
### Census — 44 stubs / 5,313 ins (`.run/P32/frontier_t3_checkpoint.json`), every row with its state
| binary | stubs | rows (nins · state) |
### 1. Where we are
**Phase 32 — the last 21 + the parked 5 (short, kill-gated).** Gate 1 approved 2026-09-05 (Drew, plan mode, Max,
Fable 5.1); rules R44–R63 ratified then; R64 is a candidate (DIGEST §3). Tasks: **T0 ✓** `commit:3901` · **T1a ✓**
`commit:3902` `commit:3904` · **T1b ✓** `commit:3903` `commit:3906` `commit:3907` · **T1c ✓** `commit:3908` · **T2a ✓** `commit:3909`
· **T2b ✓** `commit:3911` `commit:3912` `commit:3913` `commit:3914` (fleet 213 → 218) · **T2c ✓** `commit:3917` `commit:3918`
`commit:3919` `commit:3920`, close `commit:3921` · **T2d not needed** · **T3 IN PROGRESS** (launch `commit:3922`; banks
`commit:3923` `commit:3924` `commit:3925` `commit:3926` `commit:3927` `commit:3928` `commit:3929` `commit:3930` `commit:3931`; the
successor's checkpoint `commit:3932` + the protocol commit = HEAD) · **T4, T5 pending.** Harness task list #1–#11 exists
(#9 = T3 in_progress). Fleet **218 binaries** (main + resident + 138 `ov_*` + 78 `md_*`). **Last full R22: 218/218 rc 0
at the T2c close** (`.run/P32/t2c/r22.log`); the 10 T3 banks each built byte-identical in their own binary but **no fleet
R22 has run since — §5 step 0 runs one before any new bank.** Non-ghidra tree clean at HEAD; the `ghidra/` churn
(`db.*.gbf`, `~index.*`, `*.prp`) is R23 restart-noise — never stage it. Unpushed commits at this writing: 32
(Drew pushes, R6).
### 2. What happened in the previous session (c6a5fb71, 2026-09-04 22:39 → 2026-09-05 01:07 MDT)
T0–T2c as logged above. T3: census 54 − 7 pinned walls = **47 targets** (`.run/P32/t3/targets.json`); packs built
(`claude_wave_packs`, 47/47 neighbours, 10 journal notes); brief `.run/P32/t3/BRIEF.md`, laws `.run/P32/t3/SYS.md`.
**20 drafters launched 00:53–00:55 MDT** (16 Opus: the 11 old near/far rows + resident `func_800D06E8` + the 4 largest new
bodies; 3 Sonnet; 1 Haiku), **27 Haiku rows queued** behind the harness's 20-concurrent cap; the launch was checkpointed
(`commit:3922`, 00:59). Ten queued rows were launched as slots freed (01:00–01:07). **Ten functions banked in nine commits
01:01–01:07** (list in §4). **At 01:07:15 MDT the coordinator hit "Prompt is too long"** (its context was ~95% full from
the whole day BEFORE the wave); the other **22 completions (01:07–02:04 MDT) arrived as notifications into a dead
session.** At 01:52 MDT one agent (func_800CD674's) tidied the SHARED `.run/P32/t3/opus/` with
`find .run/P32/t3/opus -maxdepth 1 -type f ! -name 'func_800CD674.c' -exec mv {} .run/P32/t3/opus/_scratch/ \;`, moving
**11 sibling deliverables** (the three agents that finished later wrote their finals afterwards and survived). Drew's last
message (09:04): "97% context. checkpoint for fresh session, have next session analyze the completed subagents results".
### 3. What THIS session did (e40106e1, 2026-09-05 09:12 → 10:01 MDT, Max, Fable 5.1)
(a) Dumped the dead session's transcript (`~/.claude/projects/-home-musashi-bfm-decomp/c6a5fb71-….jsonl` → condensed text:
assistant text + tool calls + truncated results) and summarised all 31 subagent transcripts. (b) **Rebuilt the verdict
ledger by the recorded route:** `.venv/bin/python tools/agent_verdicts.py /tmp/claude-1000/-home-musashi-bfm-decomp/
7beebba8-05e9-4d18-98ea-ce208f45370f/tasks/a*.output --append .run/P32/t3/verdicts.jsonl` → **31 rows: 20 MATCH / 9 NEAR /
2 FAIL** (pass ONLY `a*.output` — the `b*.output` files there are older sessions' tasks). (c) Found the swept deliverables
in `_scratch/`, moved the 9 missing ones back to `.run/P32/t3/opus/<fn>.c`, and **re-verified EVERY unbanked draft with
`rtu_match` in its real TU — every result equals the agent's verdict** (§4). (d) Wrote `tools/agent_drafts_restore.py`
(transcript replay of Write/Edit/cp/mv/heredoc ops; rebuilt 26/30 exactly — the 4 an agent had edited via shell after its
last Write were stale, so an on-disk copy always wins). (e) **Harvest (R16/R30): cookbook §500** (10 banked closers, 10
MATCH closers, the 9 NEAR classes with their inert-lever lists, two NEW mechanisms — the pinned-base-vs-pseudo-address
alias basin, `#line`-equalised ASM_OPERANDS for cross_jump — and the process defects), `docs/wave-playbook.md` §S80
addendum-2, `docs/accelerators.md` P32 T3, `docs/decision-log.md` P32 S82 (R31), `docs/SETUP.md` tool row (R21),
`docs/cookbook-index.md` regenerated (tools-health's `--check` is green), `.run/P32/t3/BRIEF.md` output contract amended
(final message = the JSON line ONLY; scratch only under `.run/P32/t3/work/<fn>/`; never `find`/`rm`/`mv` in a shared
dir). (f) `.gitignore` allowlist for `.run/P32/**` (drafts, ledger, census jsons, BRIEF/SYS/LAUNCHED/targets/pending/
harvest_notes/PROMPT_TEMPLATE, `restored/sweep_*.py`) → committed **`commit:3932`**. (g) **Drew-directed protocol change:**
`phase-ends/DIGEST.md` created (every phase synopsis, every rule in full, the PROJECT_CONTEXT corrections, the doc map);
CLAUDE.md session-start rewritten (≈100k-token budget: PROJECT_CONTEXT → DIGEST → last 3 PhaseEnds → CURRENT_PHASE; rules in
full from the digest; the 🛑 block replayed VERBATIM); Phase Boundary step 3b (append the phase to the digest, P7);
`phase-ends/README.md`; SETUP §7 pointer; the memories `checkpoint-current-phase-before-pause` and
`session-start-list-rules-in-full` + MEMORY.md; **R64 candidate** — ratify at PhaseEnd_Phase32. (h)
`.run/P32/t3/PROMPT_TEMPLATE.md` — the verbatim agent prompts (Haiku plain / Haiku with a twin hint / the Sonnet
escalation / Opus / Sonnet). (i) Rebuilt the harness task list; wrote this block. **Nothing under `src/` or `config/`
changed this session.**
### 4. Census — 44 stubs / 5,313 ins (`.run/P32/frontier_t3_checkpoint.json`), every row with its state and draft path
| binary | stubs · ins | rows |
|---|---|---|
| main | 9 · 1,643 | **MATCH-unbanked:** func_80015B6C 120 (Opus, `.run/P32/t3/opus/func_80015B6C.c`, TU `src/800.c`) · func_8002FDE8 73 (Opus, `…/opus/func_8002FDE8.c`, TU `src/800_b_2.c`) · **NEAR:** func_80039308 518 → 17 (`…/opus/func_80039308.c`) · func_8001BC6C 69 → 6 (`…/opus/func_8001BC6C.c`) · **WALLS (pinned, T4):** func_80011380 192 (boot −O0; best `.run/m3/opus/func_80011380.c` 6-off) · func_80032A74 (800_b_2) · func_80020DA4 100 (800; 2-off) · func_80039DEC (800_c) · func_800391D4 (800_c) |
| main | 9 · 1,643 | **MATCH-unbanked:** func_80015B6C 120 (`.run/P32/t3/opus/func_80015B6C.c`, TU `src/800.c`) · func_8002FDE8 73 (`.run/P32/t3/opus/func_8002FDE8.c`, TU `src/800_b_2.c`) · **NEAR:** func_80039308 518 → 17 (`…/opus/func_80039308.c`, TU `src/800_c.c`) · func_8001BC6C 69 → 6 (`…/opus/func_8001BC6C.c`, TU `src/800.c`) · **WALLS (pinned in `config/wave_exclude.txt`, T4):** func_80011380 192 (boot −O0; `.run/m3/opus/func_80011380.c` 6-off) · func_80032A74 (800_b_2) · func_80020DA4 100 (800; `.run/S79w/sonnet/func_80020DA4.c` 2-off) · func_80039DEC (800_c) · func_800391D4 (800_c) |
| md_MAIN_003 | 1 · 469 | NEAR func_800CF3E8 469 → 27 (`…/opus/func_800CF3E8.c`) |
| md_MAIN_007 | 14 · 701 | **MATCH-unbanked (Haiku):** func_800CF148 33 · func_800CF2BC 32 · func_800CEEFC 25 · func_800CEF94 25 · func_800CF068 21 (`.run/P32/t3/haiku/<fn>.c`) · **leaf-exact behind the TU decl:** func_800CF3B0 22 (`…/haiku/func_800CF3B0.c`; `src/md_MAIN_007/md_MAIN_007.c:91` declares `extern void func_800CF3B0(void*,void*,void*)`, the banked `func_800CF390` at `:94` calls it with 3 args; the real signature is `s32 (void)`) · **NEAR:** func_800CF6D0 249 → 137 · func_800CF408 178 → 49 (`…/opus/`) · **QUEUED Haiku:** func_800CF0F4 21 · func_800CF1CC 21 · func_800CF268 21 · func_800CF33C 21 · func_800CF220 19 (twin ov_SC03_001:0x80182860 d=4) · func_800CEFF8 13 (twin ov_SC02_005:0x801865d0 d=3) |
| md_MAIN_007 | 14 · 701 | **MATCH-unbanked (Haiku, `.run/P32/t3/haiku/<fn>.c`):** func_800CF148 33 · func_800CF2BC 32 · func_800CEEFC 25 · func_800CEF94 25 · func_800CF068 21 · **leaf-exact behind the TU decl:** func_800CF3B0 22 (`src/md_MAIN_007/md_MAIN_007.c:91` = `extern void func_800CF3B0(void *a0, void *a1, void *a2);`, the BANKED `func_800CF390` at `:94` calls it with 3 args; the real signature is `s32 (void)`) · **NEAR:** func_800CF6D0 249 → 137 · func_800CF408 178 → 49 (`…/opus/`) · **QUEUED Haiku:** func_800CF0F4 21 · func_800CF1CC 21 · func_800CF268 21 · func_800CF33C 21 · func_800CF220 19 (twin ov_SC03_001:0x80182860 d=4) · func_800CEFF8 13 (twin ov_SC02_005:0x801865d0 d=3) |
| md_MAIN_009 | 10 · 603 | **NEAR:** func_800CD92C 247 → 15 · func_800CD674 174 → 2 (`…/opus/`) · **QUEUED Haiku:** func_800CD464 25 · func_800CD558 24 · func_800CD408 23 · func_800CD5B8 23 · func_800CD4C8 22 · func_800CD520 22 (twin ov_SC03_011:0x8017dbd8 d=3) · func_800CD614 22 · func_800CD3B8 21 |
| md_SC03_053 | 2 · 116 | **MATCH-unbanked (Sonnet):** func_801EF734 44 (`.run/P32/t3/sonnet/func_801EF734.c`) · func_801EF7E4 72 (`…/sonnet/func_801EF7E4.c`) → the module reaches 100% C |
| md_SC03_054 | 3 · 698 | **MATCH-unbanked:** func_801EF6D8 663-row (604 code ins + six jump tables → B-CARVE; `…/opus/func_801EF6D8.c`) · **QUEUED Haiku:** func_801F0048 20 · func_801F00C8 15 (twin md_SC03_053:0x801ef9dc d=5, hand-adapt) |
| md_SC03_054 | 3 · 698 | **MATCH-unbanked:** func_801EF6D8 — targets.json nins 663 = 604 code ins + six jump tables (B-CARVE; `…/opus/func_801EF6D8.c`) · **QUEUED Haiku:** func_801F0048 20 · func_801F00C8 15 (twin md_SC03_053:0x801ef9dc d=5 — `family_remap` refused, reloc-count 1≠2, hand-adapt) |
| md_SC03_056 | 1 · 23 | QUEUED Haiku func_801CBB80 23 (twin ov_SC06_025:0x8017ded8 d=5) |
| ov_SC03_105 | 2 · 595 | NEAR func_80185810 489 → 35 (`…/opus/func_80185810.c`) · WALL (pinned) func_801834A4 106 (S71_gate14 variants 6-off) |
| ov_SC03_105 | 2 · 595 | NEAR func_80185810 489 → 35 (`…/opus/func_80185810.c`) · WALL (pinned) func_801834A4 106 (`.run/S71_gate14/ov_SC03_105*/func_801834A4.c` 6-off) |
| ov_SC06_022 | 1 · 119 | WALL (pinned) func_8017DF28 119 (`.run/S79w/sonnet/func_8017DF28.c` 2-off) |
| ov_SC07_002 | 1 · 346 | NEAR func_8017DC80 346 → 46 (`…/opus/func_8017DC80.c`) |
**FAIL rows:** haiku func_801EF734 (47 vs 44 — superseded by the Sonnet MATCH), haiku func_800CF3B0 (leaf-exact; the TU decl).
**FAIL rows:** haiku func_801EF734 (47 vs 44 — superseded by the Sonnet MATCH); haiku func_800CF3B0 (leaf-exact 22/22; the
TU decl). **The 10 BANKED in T3 so far (1,063 ins):** md_SC03_054 func_801EF558 96 (`commit:3923`, sha `06bd73df…`) ·
md_SC03_053 func_801EF49C 49 (`commit:3924`), func_801EF6B0 33 + func_801EF95C 20 (`commit:3927`), func_801EF624 35
(`commit:3928`) (all `c0848f30…`) · resident func_800D06E8 344 (`commit:3925`, `8e17e02f…` — the resident is 145/145 C; its
`jtbl_80113FA4` carved by `jtbl_carve --func`) · main func_80039B20 79 (`commit:3926`), func_80023BF0 281 (`commit:3930`),
func_80038698 74 (`commit:3931`) (all `143dbb89…` via `gate_main`) · md_MAIN_007 func_800CEE2C 52 (`commit:3929`, `2ff702b6…`).
### NEXT — the T3 resume order (xHigh; each step's evidence quoted, R42 commit before the next command that can touch src/)
0. **Preflight:** `git status` (only `ghidra/` churn) · `verbatim_check --strict` (5==5) · `make check-all` **218/218 rc 0**
(R22 baseline before any bank; if red, fix the baseline first — R56) · read cookbook §500-B for each MATCH's plumbing note.
1. **md_SC03_053 ×2 (Sonnet MATCH):** for `func_801EF734` then `func_801EF7E4`: `rtu_match <fn> --split md_SC03_053 --source
md_SC03_053 --c .run/P32/t3/sonnet/<fn>.c --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053 --work .run/P32/t3/verify/<fn>`
→ splice over the `INCLUDE_ASM(…, <fn>);` line (the T3 (1)/(2) python one-liner) → `make build BINARY=md_SC03_053 -j8`
(rc via PIPESTATUS, R53) → sha `c0848f30…` == `config/check.md_SC03_053.sha` → commit → **md_SC03_053 is 100% C**.
2. **main ×2 (Opus MATCH):** one slate `[{"fn":"func_80015B6C","draft":"<abs>/.run/P32/t3/opus/func_80015B6C.c"},
{"fn":"func_8002FDE8","draft":"<abs>/.run/P32/t3/opus/func_8002FDE8.c"}]` → `tools/gate_main.py <slate> --apply`
(read the BODY/TABLE/PLUMBING/MIXED line; clean rebuild) → sha `143dbb89…` → commit `src/800.c` + `src/800_b_2.c`.
Keep `func_8002FDE8`'s block-scope `extern s16 D_800A46D2;` (the scalar spelling IS the lever, §500-B).
3. **md_SC03_054 `func_801EF6D8` (604 + six jtbls):** `tools/jtbl_carve.py md_SC03_054 --func func_801EF6D8` (as T3 (3)
did for the resident) → `make extract BINARY=md_SC03_054` (EXIT CODE) → splice → `make build BINARY=md_SC03_054 -j8` →
sha `06bd73df…` → `pads_audit md_SC03_054` + `interleave_check md_SC03_054` (R60) → commit carve state (only this
binary's `overlays.mk`/yaml lines) + the bank. Alternative: `parallel_gate --r22` (it carves). rtu_match MATCH was
re-confirmed against the CURRENT TU (after `func_801EF558` landed).
4. **md_MAIN_007 six:** FIRST the byte-neutral plumbing commit (S77 law): `src/md_MAIN_007/md_MAIN_007.c:91`
`extern void func_800CF3B0(void *a0, void *a1, void *a2);` → `extern s32 func_800CF3B0();` (no-proto, §376 class —
keeps `func_800CF390`'s 3-arg call legal, admits the `s32 (void)` definition) → `make build BINARY=md_MAIN_007 -j8` sha
`2ff702b6…` UNCHANGED → commit. (If the sha moves: keep `void (void*,void*,void*)` and give the definition three unused
pointer params instead — the gate decides.) Then `rtu_match` each of func_800CEEFC, func_800CEF94, func_800CF068,
func_800CF148 (drop its block-scope redeclaration of `func_800CF3B0` only if cc1 objects), func_800CF2BC, func_800CF3B0
→ splice → one build → sha → commit (one commit per bank or per verified same-TU batch).
5. After 1–4: `tools/twin_rescan.py` (a bank changes the twin graph — the queued md_MAIN_009 rows may gain twins) ·
`verbatim_check --strict` · R22 `make clean && make extract-all && make check-all` → quote **218 passed / 0 failed rc 0**
(R58) · `make tools-health` · refresh this block + commit. Expected census after 1–4: **33 stubs / ~4,250 ins**.
6. **Ledger the 9 NEAR** with `tools/backlog.py log` (closeness · class · best draft · cost "1 Opus agent, 30–70 min", R41):
func_800CD674 2 REGALLOC-PERM `$a3↔$t1` · func_8001BC6C 6 REGALLOC-PERM `$v0↔$v1` (qty_compare one span unit; pinned
seed → §494 `permuter_ils … --cycles 8 --secs 150 --j 3`) · func_800CD92C 15 §S7 prologue weave · func_80039308 17
sched2 + cross-block regalloc · func_800CF3E8 27 pinned-base alias basin (§500-D1) · func_80185810 35 [permuter] 4
emission windows · func_8017DC80 46 reload-slot frame + `la $a0` slot · func_800CF408 49 [permuter] 3 hunks ·
func_800CF6D0 137 sched1 rank_for_schedule class tie. `backlog.py render`.
7. **Launch the 17 queued Haiku rows** (one per free slot, ≤20 concurrent, dequeue-then-launch; escalate a structural
FAIL to Sonnet) — but FIRST amend `BRIEF.md`'s output contract per §S80 addendum-2: final message = the JSON line ONLY
(prose → `.run/P32/t3/reports/<fn>.md`); scratch ONLY under `.run/P32/t3/work/<fn>/`; never `find/rm/mv` elsewhere.
Per result: verbatim grep → your own `rtu_match` → splice/build/sha → commit → `twin_rescan`.
### 5. NEXT — the T3 resume order (each step's evidence quoted; R42: commit before the next command that can touch src/)
0. **Preflight:** `git status --short | grep -v ghidra/` (empty) · `.venv/bin/python tools/verbatim_check.py --strict` (5 == 5)
· `make check-all` → **218 passed, 0 failed of 218, exit 0** (R22 baseline before any bank; if any binary is red, fix the
baseline first — R56) · read cookbook §500-B for each MATCH's plumbing note.
1. **md_SC03_053 ×2 (Sonnet MATCH):** for `func_801EF734` then `func_801EF7E4`: `.venv/bin/python tools/rtu_match.py <fn>
--split md_SC03_053 --source md_SC03_053 --c .run/P32/t3/sonnet/<fn>.c --asm-subdir asm/md_SC03_053/nonmatchings/md_SC03_053
--work .run/P32/t3/verify/<fn>` (expect `MATCH (N ins)`) → splice the draft over the one `INCLUDE_ASM("asm/md_SC03_053/
nonmatchings/md_SC03_053", <fn>);` line (python: assert the line occurs once, replace with the draft text) → `make build
BINARY=md_SC03_053 -j8` (read `${PIPESTATUS[0]}`, R53) → `sha1sum build/md_SC03_053/md_SC03_053` == `config/check.md_SC03_053.sha`
(`c0848f30…`) → `git add src/md_SC03_053/md_SC03_053.c` + commit ("T3 (10) …") → **md_SC03_053 is 100% C.**
2. **main ×2 (Opus MATCH):** write `.run/P32/t3/gate/slate_main2.json` = `[{"fn":"func_80015B6C","draft":"/home/musashi/
bfm-decomp/.run/P32/t3/opus/func_80015B6C.c"},{"fn":"func_8002FDE8","draft":"/home/musashi/bfm-decomp/.run/P32/t3/opus/
func_8002FDE8.c"}]` (ABSOLUTE paths) → `.venv/bin/python tools/gate_main.py .run/P32/t3/gate/slate_main2.json --apply`
(a clean main rebuild; read the "slate 2 -> N compatible" and the "BANKED n main functions -- 143dbb89… BYTE-IDENTICAL"
lines; on a drop, read the BODY/TABLE/PLUMBING/MIXED verdict) → `git add src/800.c src/800_b_2.c` + commit. Keep
`func_8002FDE8`'s block-scope `extern s16 D_800A46D2;` — the scalar spelling IS the lever (§500-B).
3. **md_SC03_054 `func_801EF6D8` (604 + six jtbls):** `.venv/bin/python tools/jtbl_carve.py md_SC03_054 --func func_801EF6D8`
(as T3 (3) did for the resident) → `make extract BINARY=md_SC03_054` (EXIT CODE — a failed extract leaves a stale linker
script, §498) → splice → `make build BINARY=md_SC03_054 -j8` → sha `06bd73df…` → `.venv/bin/python tools/pads_audit.py
md_SC03_054` + `tools/interleave_check.py md_SC03_054` (R60) → commit the carve state (ONLY this binary's `config/overlays.mk`
lines + `config/splat.md_SC03_054.yaml`) + the bank. Alternative: `tools/parallel_gate.py … --r22` (it carves). The draft's
rtu_match MATCH was re-confirmed against the CURRENT TU after `func_801EF558` landed.
4. **md_MAIN_007 (six):** FIRST the byte-neutral plumbing commit (the S77 law): `src/md_MAIN_007/md_MAIN_007.c:91`
`extern void func_800CF3B0(void *a0, void *a1, void *a2);` → `extern s32 func_800CF3B0();` (no-proto, the §376
`fix_arity_callers` class — keeps `func_800CF390`'s 3-arg call legal and admits the `s32 (void)` definition) → `make build
BINARY=md_MAIN_007 -j8` → sha `2ff702b6…` UNCHANGED → commit. (If the sha moves, keep the 3-param decl with `s32` return
and define `func_800CF3B0` with three unused pointer params instead — the gate decides.) Then `rtu_match` each of
func_800CEEFC, func_800CEF94, func_800CF068, func_800CF148 (drop its block-scope `s32 func_800CF3B0(void)` redeclaration
only if cc1 objects), func_800CF2BC, func_800CF3B0 → splice → one build → sha → commit (per bank, or per verified same-TU
batch).
5. **After 1–4:** `.venv/bin/python tools/twin_rescan.py` (a bank changes the twin graph — the queued md_MAIN_009 rows may
gain twins; it prints ready `family_remap` command lines) · `verbatim_check --strict` · R22 `make clean && make
extract-all && make check-all` → quote **218 passed / 0 failed, exit 0** (R58) · `make tools-health` → OK · refresh this
block + commit. Expected census after 1–4: **33 stubs / ~4,250 ins.**
6. **Ledger the 9 NEAR** in the backlog (`grep -n add_argument tools/backlog.py` first — the dead session's query on keys
`addr`/`fn` returned nothing for the wall rows, so confirm the row schema; then `tools/backlog.py log …` per row with
closeness · class · best draft · cost "1 Opus agent, 30–70 min" (R41) · `tools/backlog.py render`): func_800CD674 2
REGALLOC-PERM `$a3↔$t1` · func_8001BC6C 6 REGALLOC-PERM `$v0↔$v1` (qty_compare one span unit; pinned seed → §494
`permuter_ils … --cycles 8 --secs 150 --j 3`) · func_800CD92C 15 §S7 prologue weave · func_80039308 17 sched2 +
cross-block regalloc · func_800CF3E8 27 pinned-base alias basin (§500-D1) · func_80185810 35 [permuter] 4 emission
windows · func_8017DC80 46 reload-slot frame + `la $a0` slot · func_800CF408 49 [permuter] 3 hunks · func_800CF6D0 137
sched1 rank_for_schedule class tie.
7. **Launch the 17 queued Haiku rows** from `.run/P32/t3/pending_launch.txt` with the prompts in
`.run/P32/t3/PROMPT_TEMPLATE.md` (substitute fn / binary / nins / sub / asm / tu / twin; keep the arm; the packs are at
`.run/P32/t3/packs/<fn>.md` — regenerate with `claude_wave_packs` if missing): **dequeue the row (`sed -i '/^<binary>
<fn> /d' pending_launch.txt`) BEFORE launching; ≤20 concurrent** ("Concurrent subagent limit reached. … Do not retry" =
wait for a completion); each agent's final message is now the JSON line only (BRIEF amended). Per result, never in bulk:
`grep -c '\.ent\|\.word' <draft>` (0) → your OWN `rtu_match` → splice/build/sha → commit → `twin_rescan`. A Haiku FAIL
whose note names a C-structure residual at near-exact length → escalate to Sonnet with the shape hint (the
PROMPT_TEMPLATE has the escalation prompt); a TU `conflicting types` → the §376 plumbing commit first.
8. **The NEAR tail (bounded):** permuter on the two REGALLOC-PERM seeds (func_800CD674, func_8001BC6C) via the repaired
`permuter_ils`; one Opus second look ONLY where §500 names an untested lever (func_800CF3E8: an unpinned alias of `p6`
`permuter_ils`; ONE Opus second look only where §500 names an untested lever (func_800CF3E8: an unpinned alias of `p6`
for the tag load alone). Plateaus stay in the backlog. **Kill gate stands:** a session with no bank and no new verdict
ends T3.
9. **T3 close:** any new idiom from steps 7–8 → cookbook §500 addendum (R16/R30); `harvest_notes.md` pointer; then **T4**.
9. **T3 close:** any new idiom from steps 7–8 → cookbook §500 addendum (R16/R30) + `harvest_notes.md`; regenerate
`docs/progress.fleet.md` (`make report`); then **T4**.
### T4 pre-read (read-only, run by the dead session at 07:00Z — its ledger repairs are still owed)
`exclude_audit --assert-fresh`: 7 entries, 7 WALL, 0 stale. Best drafts in the REAL TU today: `main:func_80011380`
`.run/m3/opus/func_80011380.c` DIFF 6 (the ledger's `.run/backlog_drafts/func_80011380.c` is MISSING — R62 path fix) ·
`main:func_80032A74` `.run/S79w/opus/…` **CC1 FAIL** (redefinition of `struct Slot`/`Slot`, conflicting `A12`/`B12` vs
`src/800_shared.h:68/95` — a §376 plumbing class, re-probe before calling it a wall, R40) · `main:func_80020DA4`
`.run/S79w/sonnet/…` DIFF 2 · `main:func_80039DEC` both S79w drafts **CC1 FAIL** (`conflicting types for func_80039DEC`
— a def-side declaration wall, §495 class: fix the TU's own decl first) · `main:func_800391D4` **CC1 FAIL** (`D_80073140`
conflicting types) · `ov_SC06_022:func_8017DF28` DIFF 2 · `ov_SC03_105:func_801834A4` S71_gate14 variants DIFF 6 (the
ledger's `.run/backlog_drafts/func_801834A4.c` is MISSING). The backlog query for the seven wall rows returned nothing
under the `addr`/`fn` keys — check `backlog.py`'s row schema before rendering.
### 6. Files, tools, exact invocations, gotchas
- **`.run/P32/t3/` (git-tracked unless noted):** `BRIEF.md` (agent brief, amended) · `SYS.md` (the laws) · `targets.json`
(47 rows: name, binary, nins, sub, asm, tu, klass, closeness, model, twin, twin_d) · `pending_launch.txt` (17 rows
`binary fn nins [twin=…]`) · `verdicts.jsonl` (31) · `LAUNCHED.md` (recovery route + status) · `harvest_notes.md` ·
`PROMPT_TEMPLATE.md` · `{opus,sonnet,haiku}/func_*.c` (the deliverables: 12 + 4 + 11) · `restored/sweep_func_80039308.py`
(the dead-local sweeper an agent wrote — a tool candidate) · untracked: `packs/<fn>.md` (47; regenerable), `verify/` +
`verify_*.txt` + `gate/slate_*.json` (the coordinator's own checks), `work/` `rtu/` (agent scratch), `opus/_scratch/`
`opus/x/` `opus/var/` `opus/_h/` `opus/_wk_8017DC80/` `opus/sweep/` (agent leftovers — ignorable), `restored/*.c`
(transcript replays — inferior to the on-disk finals). Census jsons: `.run/P32/frontier_*.json` (tracked).
- **Transcripts:** `~/.claude/projects/-home-musashi-bfm-decomp/c6a5fb71-f2ae-4846-a4a9-a43a4c1c3496/subagents/agent-<id>.jsonl`
(31; `/tmp/claude-1000/-home-musashi-bfm-decomp/7beebba8-05e9-4d18-98ea-ce208f45370f/tasks/<id>.output` are symlinks to
them; the id→function map is the `file` field of each `verdicts.jsonl` row). Never cat one; use `agent_verdicts.py` /
`agent_drafts_restore.py`.
- **`rtu_match`:** `--split <sub> --source <binary> --c <draft> --asm-subdir <asmdir> --work <dir>`; **main adds `--tu
src/<sub>.c`**; `<sub>`/`<asmdir>`/`<tu>` come from `targets.json` or `corpus.stubs(<binary>)` (`asm_path`, `path`). The
verdict line starts `MATCH`/`DIFF`/`CC1`. It compiles the WHOLE TU with the draft spliced — the gate predictor.
- **Build check:** `make build BINARY=<b> -j8 2>&1 | grep -v "warning\|In function" | tail -2; rc=${PIPESTATUS[0]}` then
`sha1sum build/<b>/<b>` vs `config/check.<b>.sha`. R53: exit code, never the file (a failed build leaves the old binary).
- **`gate_main`:** the ONLY way to gate main (incremental builds false-pass/false-diff on main, R43/§S52); slate = JSON list
of `{fn, draft(ABSOLUTE)}`; `--apply` keeps the splice on success; then `git add` the TU + commit.
- **Carves:** `jtbl_carve.py <b> --func <fn>` → extract (rc) → build; `pads_audit.py <b>`, `interleave_check.py <b>`; a
DIFF that starts at the first code byte is a stale linker script, never the draft (§498).
- **Gotchas that bit this week:** `set -o pipefail` + `grep -c` exits 1 on zero matches (a "no ghidra staged" guard
aborted a good commit) · never `cd` inside a compound command (the cwd persists into later calls) · `masked_diff.py`
leaves `src/.masked_diff_probe.<pid>.c` while running — they are other agents' live probes, never delete them · the
`.run/P32/t3/<arm>/` dirs are SHARED (agents are now told not to touch siblings) · the SessionStart hook launches a
headless Ghidra MCP server (`.run/ghidra-mcp.log`) — T3/T4 never use it · `agent_verdicts.py` over a whole `tasks/` dir
picks up older sessions' outputs — pass `a*.output`.
### Standing reminders
Effort **xHigh** for T3/T4, **Max** for T5 (prompt at each transition, R27) · every bank commits before the next command
that can touch `src/` (R42) · count banks from the SOURCE, quote the fleet's green count at every close (R58) · the
Ghidra MCP is not needed for T3/T4; if a hook started one, do not stage `ghidra/` (R23) · Fable only if an agent names a
wall class the codegen map lacks — STOP and prompt Drew first.
### 7. Carried context for T4 and T5
**T4 (xHigh, no drafting) — the dead session's read-only pre-check (07:00Z):** `exclude_audit --assert-fresh`: 7 entries,
7 WALL, 0 stale. Best drafts re-run in their REAL TU: `main:func_80011380` `.run/m3/opus/func_80011380.c` DIFF 6 (the
ledger's `.run/backlog_drafts/func_80011380.c` is MISSING — R62 path fix) · `main:func_80032A74` `.run/S79w/opus/
func_80032A74.c` **CC1 FAIL** (`redefinition of struct Slot`/`Slot`, `conflicting types for A12`/`B12` vs
`src/800_shared.h:68/95` — §376 plumbing, re-probe before a final verdict, R40) · `main:func_80020DA4` `.run/S79w/sonnet/
func_80020DA4.c` DIFF 2 · `main:func_80039DEC` both `.run/S79w/{permuter,sonnet}/func_80039DEC.c` **CC1 FAIL**
(`conflicting types for func_80039DEC` — a def-side declaration wall, §495: fix the TU's own decl first) ·
`main:func_800391D4` `.run/S79w/sonnet/func_800391D4.c` **CC1 FAIL** (`conflicting types for D_80073140` at t.c:3310 vs
:2622) · `ov_SC06_022:func_8017DF28` DIFF 2 · `ov_SC03_105:func_801834A4` S71_gate14 variants DIFF 6 (the ledger's
`.run/backlog_drafts/func_801834A4.c` is MISSING). Deliverables: each of the 7 rows PROVED vs CANDIDATE with a current
citation + an instrument-exonerated bounded attempt (R40), `exclude_audit --write`, `backlog.py render`, the wall table
into this file, cookbook §501 if a verdict changes, decision-log, accelerators. A T3 idiom naming a wall's mechanism
re-opens that row (one bounded attempt, permuter first).
**T5 (Max, Tier 1 — prompt R27; WAIT for gate 2):** P7 checkbox walk over every task above; milestone demo = R22 fleet
218/218 · `make tools-health` OK · `verbatim_check --strict` 5==5 · the final census (`tools/frontier_classify.py --json`)
· the wall ledger · parked-5 dispositions via `make audit-disc` (UNCLAIMED 0 of 220 at T2c) · `make report` all three
metrics + main `143dbb89…` WITH and WITHOUT the SDK object dirs (`.run/obj40`, `.run/obj42`; fresh-extract fallback) ·
corrected denominators (main game-code 41,556 — the 22-ins Ghidra-boundary gap; the fleet denominator grew by the five
modules' ~2,600 ins at T2b). Then `PhaseEnd_Phase32.md` (+ Roadmap delta: P33 = verify + flip; + Plain-English Recap; +
the rules table incl. R64) → **append the P32 synopsis + rules to `phase-ends/DIGEST.md` (step 3b)** → `git mv
CURRENT_PHASE.md phase-ends/logs/Phase32.md` (R19) → R23 MCP stop if it ran → leave both uncommitted for Drew (R6) → 🛑.
### 8. Environment
Fleet 218; shas of the binaries T3 touches: main `143dbb89f34491258bbc27810d0a12ec8b43a8dd` · resident
`8e17e02ff8954d07c979449198f7e1645046b353` · md_SC03_053 `c0848f308342e499e2bd8c2db86f6225a29e1592` · md_SC03_054
`06bd73dfbdb10748adcbac7093ead5d76131206a` · md_MAIN_007 `2ff702b605ab5cfc18474c464c4c07e5f8ffd48c` · md_MAIN_009
`d270f695…` · md_SC03_056 `bc768a6b…` (`config/check.<b>.sha` is authoritative). Toolchain unchanged (SETUP §5.4). Harness:
20 concurrent Agent-tool subagents max; an Agent call beyond that returns "Concurrent subagent limit reached" (do not
retry — wait). Claude commits, Drew pushes. Last published metrics (P31 close, 213 binaries): instr 100.0% · distinct
99.9% · fn 99.99% — regenerate with `make report` at the T3 close (218 binaries).
### 9. Standing reminders (the rules that bite in T3)
Every bank commits before the next command that can touch `src/` (R42) · count banks from the SOURCE and quote the
fleet's green count at every close (R58) · verify a build from its exit code (R53) · a masked score is not a closeness
until its diff is read (R63) · an `__asm__` body is a verbatim, not a bank (R62) · fix the TU by a byte-neutral plumbing
commit BEFORE any gate (S77 law) · after a carve/merge touching a yaml/`.mk`: `make extract` before building, then
`pads_audit`/`interleave_check` (R60) · rules check every 4 tasks (P6) · harvest idioms into the cookbook before the next
drafting step (R16/R30) · no `Co-Authored-By` (R5) · never stage `ghidra/` (R23).
**Plain-English recap (R18).** Last night thirty-one AI agents were set on the leftover functions; twenty produced exact
matches, but the coordinator ran out of memory after banking the first ten and one agent accidentally swept the others'
finished files into a side folder. This session read the whole record, pulled every result back out, confirmed each one
byte-for-byte, put the swept files back, wrote the lessons into the cookbook and the playbook, and — at Drew's direction —
made session start cheaper (a one-page digest of all 32 phases instead of reading them all) and made this checkpoint the
complete hand-off the next session replays verbatim. The next session's first jobs: re-verify the fleet, bank the ten
ready matches, then launch the seventeen queued small functions.
+234
View File
@@ -0,0 +1,234 @@
# phase-ends/DIGEST.md — the session-start digest (every PhaseEnd in one page + every rule in full)
> **Purpose (R64 candidate, Drew 2026-09-05).** The Session Start Protocol used to read all 32 PhaseEnd files (~510 KB,
> ~150k tokens) before any work. This digest replaces that read: it carries **every rule's full text** (the rules
> acknowledgment is transcribed from here) and a **synopsis of every phase**, so a session reads `PROJECT_CONTEXT.md`
> → this file → the **three most recent** `PhaseEnd_*.md` in full → `CURRENT_PHASE.md` (and replays its 🛑 block
> verbatim into the chat). Budget: the whole protocol ≈ 100k tokens + the verbatim checkpoint. The PhaseEnd files are
> still the durable record (never deleted, R19) — read an older one on demand when a synopsis is not enough.
> **Maintenance:** at every PhaseEnd, append that phase's synopsis and its ratified rules here (a P7 checkbox).
> This file is DERIVED from the PhaseEnds and may be corrected; PROJECT_CONTEXT.md is never edited (P1).
## 0. Where the project stands (at the latest PhaseEnd — the live state is in CURRENT_PHASE.md)
Brave Fencer Musashi (SLUS-00726) matching decomp. **Phase 31 closed 2026-09-05 (v1.30.0):** 213 binaries (main EXE +
resident engine blob + 138 location overlays + 73 `md_*` code modules) rebuild byte-identical from source; fleet
**100.0% instruction-weighted / 99.9% distinct-code / 99.99% fn-count**; 21 open stubs / 4,554 ins; main REAL 777 /
LINKED 1,256 (real PsyQ objects incl. libpad 4.2.1) / 12 stubs (99.43% byte-identical, 95.0% game-code); 5 PERMANENT
verbatim `__asm__` bodies; dedup registry 2,220 groups / 0 failures. **Phase 32 (in progress)** = the last stubs + the
five parked disc payloads, short and kill-gated; then **P33 = verify + public flip**. Roadmap: `docs/roadmap-to-100.md`
v2 (adopted 2026-07-15, rewritten 2026-07-30); jumping-off doc `docs/frontier-p32.md`.
## 1. Corrections and supersessions of PROJECT_CONTEXT.md recorded in PhaseEnds (P1: the constitution is never edited)
- **Session start** reads this digest + the last three PhaseEnds, not every PhaseEnd (R64 candidate, Drew 2026-09-05).
- **P8 "absorb and delete CURRENT_PHASE.md"** → **R19**: `git mv` it to `phase-ends/logs/Phase<N>.md`, out of the load
order; consult a log only when researching a past mechanism.
- **Commit cadence:** P4 per-task → R8 one-commit-at-phase-end (P2) → per-session checkpoint commits (P7) and R20
backups → today: **one commit per completed task after CURRENT_PHASE.md is updated; a bank commits the moment it
exists (R42)**. Claude commits; **Drew pushes** (R6); the PhaseEnd + archived log are left uncommitted for Drew's
milestone-close commit; no `Co-Authored-By` (R5).
- **H1** relaxed while private (R1): ROM-derived content may be committed; the disc dump never.
- **Environment:** all-in-WSL (R2); Ghidra runs **headless** (MCP server via `tools/ghidra_mcp_start.sh` / the
SessionStart hook; symbols persist only via `tools/ghidra_apply_symbols.sh`, MCP renames do not); PCSX-Redux is
Windows-native bridged over the web API (R11); no `/tmp`, scratch under `.run/` (R12).
- **Roadmap:** the constitution's Gen1 roadmap ended at Phase 7 (Gen1 EXIT confirmed 2026-06-15); Gen2 phases 8–32 are
governed by `docs/gen2-roadmap.md` → `docs/roadmap-to-100.md` v2; **Phase 14 (public flip) is deferred to Gen3+** and
becomes P33.
- **Effort doctrine (Drew 2026-07-04, `docs/effort-map.md` governs):** xHigh for most tasks, Max for deep tasks (phase
plans, PhaseEnds, non-obvious debugging), Ultracode for breadth; plan mode always Max; every transition is prompted
(R27). Model ladder for drafters: Haiku ≤~50 ins → Sonnet ~50–120 → Opus ≥120 → Fable only for a NEW wall class.
- **Compiler triple pinned** (P6, SETUP §5.4): `gcc-2.7.2-psx cc1 -O2 -G0 -mips1 -mcpu=3000 -mgas -msoft-float
-fgnu-linker` → `maspsx --aspsx-version=2.56 --expand-div` → `mipsel-as -march=r3000 -mtune=r3000 -no-pad-sections
-O1 -G0`; per-file `-O0` modules exist (boot, the `_o0` splits).
## 2. Phase synopses (what each phase delivered, its key finding, the rules it added)
**P1 (2026-06-13, v1.1.0) Repo governance + WSL RE stack.** Ghidra 12.1 + GhidrAssistMCP + ghidra_psx_ldr installed
headless; `SLUS_007.26` imported (1,726 fns, PsyQ 4.0.0), PsyQ types imported; the LZSS decompressor at 0x80018730
decompiled via MCP. Rules R1–R6.
**P2 (2026-06-13, v1.2.0) Deterministic extraction.** `tools/bfm_extract` walks the disc/.CD/PAC/LZSS into 1,801
manifest-tracked artifacts, byte-validated against CUE's `brave` (138/138 type-4). `docs/effort-map.md`. Rules R7, R8.
**P3 (2026-06-14, v1.3.0) File-loader & overlay map.** The loader is a hand-rolled CdControl reader driven by
`cdFileLocTable` (LIST.CD) + `resourceIdMap`; LZSS staging 0x80079A70; PCSX-Redux runtime oracle; resident blob
@0x800CEDF8 and location overlays @0x80128158 byte-proven against live RAM; 13 area-states; player state verified.
Rules R9–R12.
**P3.5 (2026-06-14, v1.3.1) Prototype spike — NO-GO.** Neither US prototype carries symbols; Sep-8 = retail minus 3
functions; protos kept only as assets. Rules R13, R14.
**P4 (2026-06-14, v1.4.0) Build toolchain.** binutils-mipsel 2.42, splat64 0.41.0, pinned submodules
(maspsx/asm-differ/m2c/decomp-permuter), gcc-2.7.2-psx/cdk cc1 (i386 static); `make check-env`. No rules.
**P5 (2026-06-14, v1.5.0) All-asm byte-identical EXE** (`143dbb89…`) from the splat config; `-G0`; binutils 2.42
byte-clean. Rule R15.
**P6 (2026-06-14, v1.6.0) Compiler pinned + first matches.** The triple above (`--expand-div` required); 14 matches;
`docs/matching-cookbook.md` and the permuter harness created. Rule R16.
**P7 (2026-06-15, v1.7.0) Gen1 EXIT.** Reports (progress/difficulty/dup); the `-O0` boot module; **real PsyQ library
objects linked byte-identical** (libcd + libgs); LZSS matched; 43 REAL. Rules R17–R19.
**P8 (2026-06-15, v1.8.0)** Eight more PsyQ libraries linked; EXE 50.24% byte-identical-from-source. Rule R22.
**P9 (2026-06-15, v1.9.0)** Binary-agnostic toolchain (`make build BINARY=<alias>`, required `--vram-base/--exe`). Rule R23.
**P10 (2026-06-15, v1.10.0)** The resident engine blob is the 2nd byte-identical binary (`8e17e02f…`, flat-blob
recipe); it detects PsyQ 4.7. Rules R24, R25.
**P11 (2026-06-16, v1.11.0)** Cross-binary dedup pipeline (`sig_image.py`, `dup_report --cross`, `config/dedup.us.yaml`,
`src/shared/`); all 134 overlays signed — 9,366 cross-binary groups. No rules.
**P12 (2026-06-16, v1.12.0)** Resident harvest 1.4% → 85.6% via the Ultracode parallel-draft + whole-binary byte-gate
(`harvest_verify.py`, `match_one.py`); the "script VM" is compiled-MIPS dispatch tables; save format documented. Rule R26.
**P13 (2026-06-16, v1.13.0)** Representative overlays; 6 binaries; `tools/new_overlay.sh`; non-4-aligned overlay
handling; dup-pair collapse. Rules R27–R29.
**P15 (2026-06-18, v1.14.0)** All 134 overlays onboarded (136 binaries); `dedup_propagate` + `engine_core.h` (match once
→ ×134); fleet 3.82% → 54.48%; `sig_unify`. No rules. (P14 public flip deferred.)
**P16 (2026-06-19, v1.15.0) PIVOT.** m2c + permuter cannot crack the loose-typed engine core (~3%); `docs/struct-core-pivot.md`.
**P17 (2026-06-20, v1.16.0)** Canonical-sig layer; the wall is the compiler's codegen, not signatures/types; 55.51%.
**P18 (2026-06-20, v1.17.0)** Compiler-quirk research → the register-pin toolkit (cookbook §17); waves 33% → 56% → 90%
close-rate; 56.64%.
**P19 (2026-06-20, v1.18.0)** Scaled waves (88/92% match_one); `canon_resident_calls`, `fix_arity_callers`; propagation
is the cap; 58.00%.
**P20 (2026-06-21, v1.19.0)** `cast_call_sites` cap tool; typedef type-lift; the `%lo`-fold class cracked; 58.82%. Rule R30.
**P21 (2026-06-26, v1.20.0)** The automation manager (`gate_stage`, `worker_wave`, `grinder`, `orchestrator`, backlog
ledger, `idiom_loop`); 63.18%; automated ceiling byte-proven; a 5-scout sweep found no external shortcut.
**P22 (2026-06-29, v1.21.0)** Tractable giants banked ×134; 63.66%; pivot to the local LLM tier.
**P23 (2026-07-02, v1.22.0) THE BREAKTHROUGH.** Local 7B tier saturates ≤15-ins ($0); **Fable reading the gcc-2.7.2
source cracks "unsteerable" classes** → the §31 codegen map (`docs/gcc-2.7.2-map/`); 64.86%; `gcc-papermario` is
gcc 2.8.1 — vanilla 2.7.2 staged under `tools/reference/`.
**P24 (2026-07-08, v1.23.0)** Permuter overhaul (masked scorer, §31 class weights, ILS); integration-recovery tools;
every matched giant ×134 (incl. the 770-ins whale, the 400-ins flagship); 66.02%; the h_norm structural-family reframe.
**P25 (2026-07-11, v1.24.0)** Family engine (`family_remap`/`family_sweep`, `canon_sig_reconcile` v3.2, `rtu_match`);
giant endgame complete; 74.6% fn / 58.2% instr / 30.3% distinct; the h_seq reframe → `family-endgame-megaplan.md`. Rule R31.
**P26 (2026-07-15, v1.25.0)** Family engine + the **26-A tooling-integrity audit** (`corpus.py`, `cdecl.py`,
`audit-corpus` — the tools WERE several walls) + the §52 discovery flywheel; 68.9% instr / 49.2% distinct; mechanical
harvest exhausted. Rules R32–R34.
**P27 (2026-07-15, v1.26.0)** Instruments fixed (fail-closed Makefile, one typedef-strip primitive, second oracle on
resident); disc audit 136 → 140 + 39 type-1 modules found; the pin-crash "wall" was a tool bug; 67.0% (denominator
correction). Rule R35.
**P28 (2026-07-16, v1.27.0)** Instrument repair; B2 LIVES (its 0/8 was a missing carve); SC07 pool wired via
`dedup_extend` (6,174 members); resident 90%; 68.9%. Rule R36.
**P29 (2026-07-30, v1.28.0) THE FAMILY CAMPAIGN.** 25 sessions / 552 commits; 68.9 → 87.5% instr, 49.5 → 78.0% distinct;
`diff_regions.py` resolved the swing number (tooling); integration, not idioms, is the wave bottleneck; roadmap v2.
Rule R37 proposed.
**P30 (2026-08-14, v1.29.0)** Recovery & concentration; 87.5 → 95.3% instr; fleet 140 → 213 (disc audit + module
onboarding); the zero-token mechanical pipeline (`aprop_autodraft`, `symfix`, `prechecks`, `gate_lane`); the §172 wall
model. R37 operated as binding; R38–R39 proposed.
**P31 (2026-09-05, v1.30.0) THE FRONTIER ATLAS & WIDE-TOLERANCE CAMPAIGN.** 30 sessions / ~1,660 commits; the atlas
(`atlas.py`), 6,000-ins waves, autonomous lanes, a completion sprint; stubs 12,059 → 21; fleet 95.3 → 100.0% instr;
main 1,041 → 12 open; libpad 4.2.1 + RTL 4.2 archive linked (twelve "walls" were Sony objects); the verbatim `__asm__`
class censused to 5 PERMANENT rows; `gate_main` (main gates only by clean rebuild). R37–R39 ratified; R40–R43 + R61
accepted; R44–R60, R62–R63 proposed → **all ratified at P32 gate 1 (2026-09-05)**.
**P32 (open 2026-09-05)** The last 21 + the parked 5 (short, kill-gated) — see `CURRENT_PHASE.md`.
## 3. Every rule, in full (transcribe these at session start; P/G/H/X are in PROJECT_CONTEXT.md)
- **R1 — H1 relaxed while private.** ROM-derived content (`asm/`, `assets/`, `extracted/`, decompressed `.CD`) MAY be
committed while the repo is private; accidental inclusion is not a violation. The raw multi-GB disc dump stays ignored
regardless. Compliance before going public = history scrub + a rom→decoder regeneration tool.
- **R2 — All-in-WSL (H2 restatement).** One ext4 clone at `~/bfm-decomp`; no Windows/WSL split, no second clone, no
`/mnt` builds; MCP is loopback `127.0.0.1:8080`.
- **R3 — All tooling under `tools/`.** Including `tools/bin` (compilers), `tools/psyq*`, `tools/ghidra_scripts`.
- **R4 — Plan mode every phase.** Present the task-by-task plan and get approval before executing (the Phase Start gate).
- **R5 — No `Co-Authored-By` trailer on commits.**
- **R6 — Git workflow = Claude commits in WSL, Drew pushes.** Never `git push` from the WSL CLI. Phase-boundary
exception: Claude writes `PhaseEnd_PhaseN.md` and archives `CURRENT_PHASE.md` but leaves them uncommitted; Drew
commits AND pushes the milestone close.
- **R7 — Effort-map check.** Before each Phase Start, state the recommended effort for planning that phase per
`docs/effort-map.md` and confirm the developer has it set; annotate every task in the plan with its effort; restate the
recommended effort whenever presenting the NEXT task. `docs/effort-map.md` is the evolvable source of truth.
- **R8 — One commit at phase end** (P2; since superseded in practice by per-task commits, R20 checkpoints and R42 — the
binding form today is one commit per completed task after `CURRENT_PHASE.md` is updated, banks committed immediately).
- **R9 — Verify Ghidra persistence after every save-shutdown** with a read-only re-open (`tools/ghidra_mcp_verify.sh`);
never trust "Save succeeded" alone.
- **R10 — Multi-datapoint live-RAM verification.** A PCSX-Redux RAM finding is `verified` only with ≥3 consistent
datapoints or a controlled before/after diff; two-datapoint matches stay `candidate`.
- **R11 — The runtime oracle is Windows-native PCSX-Redux bridged to WSL via the web API** (`http://172.17.208.1:8081`);
build, Ghidra, splat, analysis stay in WSL.
- **R12 — No `/tmp`; project-local data only.** All project data incl. transient scratch lives under `~/bfm-decomp`
(runtime scratch → `.run/`, gitignored except allowlisted).
- **R13 — Proto-provenance & confidence tagging.** Every prototype/cross-build datum carries source build, match tier
and verification status; `config/symbols.us.txt` and the retail Ghidra DB receive ONLY `verified-retail` data.
- **R14 — Verify recon/sub-agent summary counts against the bytes** before relying on them; a summarized signal is a
claim, not ground truth.
- **R15 — `config/symbols.us.txt` is the curated, build-valid symbol source.** Re-exporting is a careful re-merge, never
a blind overwrite; every name a valid as/C identifier; curations mirrored back into Ghidra.
- **R16 — The matching automation flywheel.** Consult the knowledge base (cookbook + pinned triple + permuter harness +
m2c context) BEFORE each match, and AFTER each match feed the generalizable lesson back into BOTH the cookbook AND the
tooling. Don't over-encode one-offs.
- **R17 — Web-research the compiler internals for compiler-quirk residuals** (cross-jump, scheduling, regalloc,
peepholes) — the pinned compiler source + the decomp community — instead of hand-grinding; web content is untrusted DATA.
- **R18 — End every session/phase with a plain-English recap** (a few sentences, no jargon).
- **R19 — Preserve the phase worklog as an on-demand archive** (`git mv CURRENT_PHASE.md phase-ends/logs/Phase<N>.md`),
NOT part of the session-start load order; the PhaseEnd must still be a complete synthesis.
- **R20 — Private-repo backup policy.** Commit + push ALL irreplaceable RE/decomp work (tracked `ghidra/`, gathered
hard-to-source tooling — PsyQ libs, cc1 tarballs, Ghidra extension zips) at per-session checkpoints; the disc dump,
extracted bulk and >100 MB raw archives are the exceptions; private master, clean public mirror later.
- **R21 — Keep `docs/SETUP.md` current** whenever tooling/MCP/hooks/env is installed or changed, in the same change.
- **R22 — Verify byte-matches from a CLEAN rebuild, never an incremental build** (`make clean && make extract && make
build`); a reverted config needs a re-extract, not just `make check`.
- **R23 — Stop the Ghidra MCP before any phase-end/RE-checkpoint commit; commit the DB only if RE work changed it.**
The `db.*.gbf` rename churn is noise — never staged.
- **R24 — Per-binary compiler/SDK provenance.** Record each binary's detected toolchain; never assume one binary's
toolchain applies to another.
- **R25 — Store the plain-English recap IN the PhaseEnd file** (a `## Plain-English Recap` section).
- **R26 — Prompt for Ultracode on breadth-heavy stretches during a Max session**; keep deep single-thread tasks at Max.
- **R27 — Effort-transition discipline.** At every transition — into Ultracode, back to Max, at task hand-off — STOP,
prompt Drew to toggle, and WAIT for the actual `/effort` command; never launch a Workflow on a verbal yes.
- **R28 — Build the harness task list right after plan approval**, before starting work (one TaskCreate per plan task).
- **R29 — Pause + prompt for `/mcp` reconnect after any MCP server restart/program switch**, then one cheap
`get_binary_info` (G2) before continuing.
- **R30 — Capture context-dependent knowledge artifacts DURING the producing session**, before any fresh-session handoff;
defer only mechanical/continuable work.
- **R31 — Capture the WHY behind strategic pivots in `docs/decision-log.md` while fresh**: context+belief → what failed →
the pivot → the measurement-grounded why → a hindsight "better path".
- **R32 — Assert your COVERAGE.** A corpus scanner compares what it found against an over-approximating candidate set
and fails on the gap; a silent skip is a defect, and a loud failure nobody counts is exactly as invisible.
- **R33 — Derive, don't re-derive.** Where a proven invariant answers the question, derive from it rather than re-parse
the source; the best outcome is a DELETED scanner.
- **R34 — A second, DISAGREEING oracle — not a better assertion** — when an oracle is structurally blind to an error class.
- **R35 — Fix the measuring instrument before trusting its measurement; a probe from a broken tool is not evidence.**
Tool-integrity is a precondition of a measurement, not a parallel concern.
- **R36 — A newly-discovered binary is not real until every consumer knows it** (sig set, family map, dedup registry,
shared-header include, reports) — asserted by a gate (`make audit-binaries`), not remembered.
- **R37 — Probe before costing.** Ground every estimate/attribution on ONE instance; derive counts from `corpus.stubs`;
diff the artifact to prove an edit actually ran before judging the lever it carried.
- **R38 — Read the recorded failure verdicts before designing an experiment** (`.run/harvest_failed.*.classified.txt`,
gate results, journals) — the answer is frequently already recorded.
- **R39 — Negative-control every new refusal-check against the already-succeeded population**; zero false positives
before it ships.
- **R40 — Exonerate the instrument before attributing a failure to its subject** (truncation, fences, rate limits, tool
faults first; ~a third of P31's "walls" were tooling).
- **R41 — Every cost/rate/yield/effort number ships with its denominator.**
- **R42 — Commit banked work the moment it exists**, before the next command that can touch `src/` (a gate IS one);
never blind-revert a dirty `src/`; count banks from the SOURCE.
- **R43 — A tool must refuse an input it cannot handle, never process it wrongly.**
- **R44 — A card may not name a lever the knowledge base does not contain.**
- **R45 — Draw-time bankability: never draw a card the pipeline cannot bank.**
- **R46 — A budget is part of the harness, not a constant.**
- **R47 — Consume every verdict layer** (a stage reading one bit of one oracle staged garbage forever).
- **R48 — Never key by bare function name** (scratch dirs, ledgers, drafts — collisions destroy work).
- **R49 — A soft error inside a success envelope is still that error** (a 200 carrying code 429; `rc≠0` read as "no binary").
- **R50 — Periodic whole-fleet verification** (a byte gate is silent about every binary it did not build).
- **R51 — A derived property stored as config will go stale and take a binary with it**; derive it or give it a
byte-proven self-repair.
- **R52 — A blanket committer must not adopt a collapsed file** (right for `src/`, wrong for config).
- **R53 — Verify a build from its exit code, not its output file** (a failed build leaves the previous binary in place).
- **R54 — A guard downstream of the failure is not a guard, and a guard that is not running is not a guard.**
- **R55 — A lane that runs unattended must leave evidence** (progress logs; empty log + no ps hits = never started).
- **R56 — A gate verdict measures the draft only while the binary's baseline is green**; check the baseline first.
- **R57 — An instrument's own write path is part of the instrument.**
- **R58 — A session-close "clean" must quote the fleet's green count** (tree-clean ≠ fleet-green).
- **R59 — A blanket commit of another lane's mid-gate tree is a race, not a backup.**
- **R60 — `config/overlays.mk` and the splat yamls are CARVE STATE**: a gate commit carries only its own binary's lines;
any blanket restore/commit is followed by `interleave_check` + `pads_audit` on every touched binary.
- **R61 — A tool must distinguish "judged and failed" from "not judged", and a judging tool must model what the gate
does to the draft** (a loop tool that reports "unchanged" for N cycles must prove it iterated).
- **R62 — A ledger's best draft may never be an `__asm__` body, and a bank whose body is `__asm__` is a verbatim, not a
bank** (`verbatim_check --strict` in the per-bank close).
- **R63 — A permuter/waypoint score is not a closeness until its diff is read.**
- **R64 (CANDIDATE, Drew-directed 2026-09-05; ratify at PhaseEnd_Phase32) — Session start reads PROJECT_CONTEXT.md →
`phase-ends/DIGEST.md` → the three most recent PhaseEnds → `CURRENT_PHASE.md`, then replays the 🛑 SESSION CHECKPOINT
block VERBATIM into the chat; the protocol costs ≈100k tokens + the checkpoint. Every PhaseEnd appends its synopsis
and rules to the digest (P7). A checkpoint is written to be replayed: self-sufficient, verbose, every path/command/hash
explicit (see `checkpoint-current-phase-before-pause` memory).**
(R40–R43 and R61 were accepted mid-P31; their long forms are in `phase-ends/logs/Phase31.md` — the one-liners above are
the binding text. R44–R63 one-liners are the P31 table, ratified at P32 gate 1.)
## 4. Where things live (the doc map a session needs)
`docs/SETUP.md` (environment, every tool's row, commands) · `docs/matching-cookbook.md` §1–§500 (idioms; 3.5 MB —
grep by §, never read whole) + `docs/cookbook-index.md` (symptom-keyed, derived, 566 KB — grep) · `docs/gcc-2.7.2-map/`
(the compiler map) · `docs/wave-playbook.md` (THE wave procedure; `docs/automation-runbook.md` is retired) ·
`docs/effort-map.md` · `docs/roadmap-to-100.md` v2 · `docs/frontier-p32.md` · `docs/decision-log.md` (R31) ·
`docs/accelerators.md` · `docs/memory-map.md` (addresses, provenance) · `docs/formats.md` · `docs/disc-completeness.md` +
`docs/disc-ledger.md` · `docs/backlog.md` (near-miss ledger) · `config/wave_exclude.txt` (pinned walls) ·
`config/verbatim_manifest.json` · `phase-ends/logs/` (on demand only, R19) · `.run/` (scratch; allowlisted subtrees are
tracked — e.g. `.run/P32/t3/` drafts/ledger).
+3 -1
View File
@@ -2,4 +2,6 @@
- `PhaseEnd_Phase[N].md` — written at each phase boundary (format defined in `PROJECT_CONTEXT.md`). Append-only history: build log, deviations, commit message, rules added, changelog. Never deleted.
- `CURRENT_PHASE.md` — the in-phase autonomous log: approved phase plan, per-task checkboxes, current task pointer, blockers. Created at phase start, updated after every task, absorbed into the PhaseEnd file and deleted at phase close. This is the crash/compaction recovery point.
- Sessions read `PROJECT_CONTEXT.md`, then every `PhaseEnd_*.md` in numeric order, then `CURRENT_PHASE.md` (if present) — in that order, every session.
- `DIGEST.md` — the session-start digest: every phase's synopsis + every rule in full + the corrections to PROJECT_CONTEXT.md; appended at every PhaseEnd (P7).
- `logs/Phase<N>.md` — the archived in-phase worklogs (R19): NOT in the load order; consult on demand only.
- Sessions read `PROJECT_CONTEXT.md`, then `DIGEST.md`, then the THREE most recent `PhaseEnd_*.md` in numeric order, then `CURRENT_PHASE.md` (if present), and replay its 🛑 SESSION CHECKPOINT block verbatim into the chat — every session (R64 candidate, 2026-09-05; ≈100k tokens + the checkpoint).