# The story — how Brave Fencer Musashi was decompiled in twelve weeks, by an AI agent under a written constitution > **What this is.** The narrative of the project from its first commit (2026-06-10) to the public flip (Phase 33, > September 2026), written for someone who wants to know what happened and why, in order. Every section names the record it > was written from — a PhaseEnd (`phase-ends/`), a decision-log entry (`docs/decision-log.md`, cited by its dated heading), > a digest row (`docs/story-timeline.md`). The numbers are the repository's own (`docs/progress.json`, the timeline). The > analytical companion — what we believed, what failed, what it cost, what we would do sooner — is > [`docs/retrospective.md`](retrospective.md). The chart: [`docs/story-timeline.svg`](story-timeline.svg). > > **A note on the record.** Transcripts of the first month were lost; the phases up to Gen1 exit are reconstructed from > the PhaseEnds, the git history and `docs/history/` (the original brief, the methodology template, the research dump). > Everything after that is written from files that were kept as it happened. ## 0. The premise *Brave Fencer Musashi* (Square, PlayStation, 1998) had no public decompilation, no disassembly, no symbol list — a verified greenfield in June 2026. The owner's original brief (`docs/history/claude-bfm-starting-point.md`) imagined a recompilation first, to get the game running natively and force the memory map into the open. The plan that actually ran inverted that: **decompile first, match byte for byte, defer everything else** — because a matching decompilation needs no recompiler, and the one recomp precedent for a PS1 game had shown that its output does not feed matching work. Two ideas set the project apart from the start. First, a **constitution**: `PROJECT_CONTEXT.md`, generated from the ProjectArchitect template (`docs/history/project_architect_v1.3.0.md`), never edited afterwards, with the rules that kill AI-driven decompilations written down as rules — *bytes are the only truth*, *a match is byte-for-byte or it is not a match*, *the Ghidra program and the emulator are the oracles, never general knowledge*, *no ROM bytes in git*. Second, a **cadence**: phases with two human gates each (the plan, the milestone), autonomous execution between them, a PhaseEnd file at every close, and a session protocol that starts every session by re-reading the rules. The agent — Claude Code, driving Ghidra over an MCP server — did the work; the owner approved plans and milestones, pushed, and decided. ## 1. Gen1 — the foundation, in five days (Phases 1–7, 2026-06-10 → 06-15) *From `phase-ends/PhaseEnd_Phase1.md` … `PhaseEnd_Phase7.md`, `phase-ends/DIGEST.md` §2.* The first week built the ground everything else stood on. Ghidra 12.1 with the PlayStation loader and the MCP server; a deterministic extractor for the disc (`tools/bfm_extract/`) that walks the ISO, the `.CD` containers, the PAC archives and the LZSS streams into 1,801 manifest-tracked files, byte-validated against the community's reference extractor; the file loader reverse-engineered — a hand-rolled CD reader driven by a location table, the LZSS staging buffer, the resident engine blob at `0x800CEDF8` and the location overlays at `0x80128158`, every load address **proven byte-identical against a live PCSX-Redux RAM dump** (`docs/memory-map.md`); a half-phase spike on the two prototype builds that returned a clean NO-GO (no symbols, three functions' difference — kept as assets, not leads). Then the build: splat, the era's GCC 2.7.2 `cc1`, maspsx to reproduce Sony's assembler, GNU binutils — and on 2026-06-14 the first byte-identical `SLUS_007.26` from disassembly alone, SHA1 `143dbb89…`. The compiler triple was **pinned by fingerprint evidence** the same day (`-O2 -G0 -mips1 -mcpu=3000 …`, `--aspsx-version=2.56 --expand-div` — the last flag turned out to be mandatory), fourteen functions matched, the LZSS decompressor among them, and the matching cookbook opened its first page. Phase 7 industrialised the loop (difficulty ranking, duplicate reports, progress scripts), linked the first real PsyQ library objects byte-identical, and declared **Gen1 EXIT** on 2026-06-15 with 43 matched functions. ## 2. The fleet, and the first ceiling (Phases 8–20, 2026-06-15 → 06-21) *From `PhaseEnd_Phase8.md` … `PhaseEnd_Phase20.md`; timeline rows 06-15 → 06-21.* The game's code is not in the executable. It is in the resident engine blob and in 134 location overlays streamed from the disc — so the toolchain became binary-agnostic (one parameterized pipeline builds any binary), the resident blob became the second byte-identical binary, and within four days **all 134 overlays were onboarded as byte-identical build targets**, 136 binaries in all. The single most consequential discovery of the month followed: the overlays share enormous amounts of code. A cross-binary deduplication pipeline (`tools/sig_image.py`, `config/dedup.us.yaml`, `src/shared/`) found some 9,000 byte-identical function groups; **match once, share everywhere** took the fleet from 3.8% to 54% of functions in a single phase (Phase 15, `PhaseEnd_Phase15.md`). Then the wall. Phase 16 is a PIVOT in the record: the decompiler-and-permuter loop could not crack the loose-typed engine core — about 3% of it. Phase 17 showed the obstacle was not signatures or types but the compiler's own code generation. Phase 18 answered with research into the compiler's quirks and the register-pin toolkit (cookbook §17); wave close rates went from a third to nine in ten. Phases 19–20 scaled the waves and found the next limit: **propagation** — getting a matched body accepted by 134 translation units was harder than matching it (`PhaseEnd_Phase19.md`, `PhaseEnd_Phase20.md`). By 06-21 the fleet stood at 58.8% of functions. ## 3. The breakthrough: reading the compiler (Phases 21–24, 2026-06-26 → 07-08) *From `PhaseEnd_Phase21.md` … `PhaseEnd_Phase24.md`; `docs/gcc-2.7.2-map/`; cookbook §31.* Phase 21 built the automation manager (gates, worker waves, a grinder, an orchestrator, a backlog ledger) and measured the automated ceiling honestly; a five-scout sweep found no external shortcut. Phase 22 tried a local-model tier and banked the tractable giants. Phase 23 is the one the project calls **THE BREAKTHROUGH**: the local 7B tier saturated the small functions for free, and — decisively — a Fable-class agent **reading the gcc 2.7.2 source** explained the residuals that had been called "unsteerable": which pass emitted which odd instruction and why. The result is the codegen map (`docs/gcc-2.7.2-map/`), organised by compiler pass, and the discovery that a "reference" compiler the community used was actually gcc 2.8.1 — the vanilla 2.7.2 source was staged instead. Phase 24 overhauled the permuter (a masked scorer, class weights, warm restarts), built the integration-recovery tools, and matched every giant, including a 770-instruction whale, across all 134 overlays. 66% of functions. ## 4. Families, and the instruments (Phases 25–28, 2026-07-11 → 07-16) *From `PhaseEnd_Phase25.md` … `PhaseEnd_Phase28.md`; decision log 2026-07-08 → 2026-07-16 (the Phase-25/26/27/28 entries); timeline rows 07-11 → 07-16.* Phase 25 built the family engine: functions that are the same shape across overlays remap mechanically once one exemplar is cracked. It also changed how progress is measured — from 07-11 the digest carries three metrics (function count, instruction-weighted, distinct code) because the function count, inflated ×134 by the shared engine, flattered the work. Then the project turned its instruments on themselves. Phase 26's **tooling-integrity audit** (`decision-log`, "2026-07-14 (session 9, A2) — The audit found the endgame plan was majority-fiction"; "2026-07-15 (session 13, A10) — the wall re-test verdict: the broken tools WERE the walls") found that several "compiler walls" were defects in the project's own scanners, gates and declaration tools, and that a corpus scanner had been silently skipping work. The rules that came out of it — assert your coverage (R32), derive rather than re-parse (R33), a second disagreeing oracle (R34), fix the instrument before trusting its measurement (R35) — reshaped every phase after. Phase 27 audited the disc and found it held **more code than anyone had counted** (140 binaries, plus 39 modules); Phase 28 repaired more instruments and wired the SC07 pool. On 07-22 the main executable, until then reported separately at under 1%, entered the fleet denominators — the honest contract, adopted by the owner (`docs/roadmap-to-100.md` §1). ## 5. The family campaign (Phase 29, 2026-07-16 → 07-30) *From `PhaseEnd_Phase29.md`; decision log 2026-07-16 → 2026-07-27.* Twenty-five sessions and 552 commits: instruction-weighted 68.9% → 87.5%, distinct code 49.5% → 78.0%. The campaign ran as waves of drafters over family exemplars, with the whole-binary byte gate as the referee. Its lessons are the decision log's densest stretch: the swing number that had haunted three phases was an `-O0` compile-flag artifact ("2026-07-16 (Phase 29 Task 1)"); the permuter's problem was targeting, not a missing transform ("2026-07-21"); the shared byte gate had compared one binary against another binary's hash for a month ("2026-07-22"); a fleet-wide type lift landed across 154 types with the fleet still 140/140 ("2026-07-23, SESSION-14"); and the efficiency audit's verdict that became the project's thesis for the rest of the year — **the bottleneck is integration, not idioms** ("2026-07-24, SESSION-15"). Roadmap v2 (`docs/roadmap-to-100.md`) was adopted at the close. ## 6. Recovery and concentration (Phase 30, 2026-07-30 → 08-14) *From `PhaseEnd_Phase30.md`; decision log 2026-08-04 → 2026-08-14; timeline rows 08-05, 08-06, 08-14.* The overlay fleet went from 87.5% to 95.3% instruction-weighted while the denominator itself grew: the definitive disc audit asserted a *partition* of the disc rather than extending a list ("2026-08-05 (P30 S6/S41)"), and 73 more code-bearing payloads were onboarded **without an emulator**, their load addresses derived statically from their own bytes ("2026-08-06 (P30 S44/S45)") — 213 byte-identical binaries by the close. The way work got done changed: the zero-token mechanical pipeline (auto-drafts, symbol fixes, pre-checks, a lane gate) banked most of the remaining functions with no agent at all; open stubs fell from 28,296 to 12,059. The one function that refused, `func_8017C294`, got a mechanism-complete wall dossier instead of another wave ("2026-08-14 (P30 S50-Max)"). ## 7. The atlas, the lanes, and the last twenty-one (Phase 31, 2026-08-14 → 09-05) *From `PhaseEnd_Phase31.md` (and its 8,700-line log, `phase-ends/logs/Phase31.md`); decision log 2026-08-14 → 2026-09-04 (S59–S78); timeline rows 08-14 → 09-05.* The longest phase: thirty sessions, about 1,660 commits, stubs 12,059 → 21, the fleet to 100.0% instruction-weighted, the main executable from 1,041 open functions to 12. It was re-chartered at its first gate around a **frontier atlas** — a per-function feature layer and similarity groups over every open stub, each labelled with the lever it would need — then run in three shapes: orchestrated waves of six thousand instructions each, **autonomous lanes** (drafter, gater, maintenance, stall-guard) under a two-workflow budget that banked while nobody watched, and finally a hand-run completion sprint once the census fit on one page. Its defining discovery is recorded under the heading "EVERY WALL EXAMINED WAS THE INSTRUMENT" ("S76 (2026-09-03)"): a band of the main executable labelled compiler walls turned out to be Sony's controller library — the exact February-1998 version was found on the internet and linked in, twelve "walls" at once ("S78 (2026-09-04)"); a wall was a mislabelled symbol boundary; the permuter had silently never run on a whole class of drafts; one "finished" function was the original assembly pasted back in — the verbatim class, censused from the archive tables and reduced to the five genuine hand-written routines. Each repair got a control and a rule. ## 8. The frontier emptied (Phase 32, 2026-09-05 → 09-06) *From `PhaseEnd_Phase32.md`; decision log P32 S81 → S85; cookbook §501-Q/§501-R.* Twenty-one functions and five disc files nobody had seen the game load. The five were real code modules, placed from their own bytes (fleet 213 → 218; disc unclaimed 0 of 220) and adding 33 functions to the list. A one-agent-per-function pass banked 39; then, on the owner's directive that nothing but Sony's code and the original hand-written assembly may remain untranslated, the last fifteen: eleven by a Fable pass reading compiler dumps against the gcc source, four by hand. Two of those four carried formal *proofs* that they could not be matched. Both proofs were right about the mechanism and wrong about the list — each named every way the compiler could produce the odd byte, and each list was one producer short (combine's self-update bookkeeping gap, §501-Q; loop.c's user-variable rule with cse's later-mention canonicalization, §501-R). Five-line reproducers found the missing behaviours in minutes; the last two functions then matched with no register pins at all. On 2026-09-06 the census read **0 stubs**: every game-code function in all 218 binaries is C, 218/218 byte-identical from a clean rebuild. ## 9. Making it public (Phase 33, 2026-09-06 →) *From `phase-ends/CURRENT_PHASE.md` (Phase 33), `docs/public-flip-runbook.md`, decision log "P33 S86" and "P33 S87".* What remained was not matching. The contract was proven once more as one recorded run ([`docs/verification.md`](verification.md)); the build was made a stranger's build (a bootstrap script, disc extraction verified against the manifest, the optional Sony SDK user-supplied and checksummed, a fresh-clone proof of 218/218 with no SDK); the reverse-engineering database was made regenerable from text; CI was written to keep the tree ROM-free and compiling. Then the history: the repository had carried game-derived files while private, so its entire history was rewritten in place — every commit, date and message preserved, the purged paths removed from every revision, old hashes in historical documents replaced by inert tokens and mapped back at the tip ([`docs/commit-map.tsv`](commit-map.tsv)) — rehearsed twice on a scratch copy (the rehearsal caught two defects that would have corrupted history), proven pair by pair, and force-pushed. This document, the retrospective, the wiki and the tooling releases are the last block; the visibility flip waits for GitHub to purge the old objects. ## 10. By the numbers | | | |---|---| | Duration | 2026-06-10 → 2026-09-07: 12 weeks; 33 phases (+ a spike and an inserted audit half-phase); 32 PhaseEnds; ~87 sessions | | Commits | ≈4,040 on `main` (78 distinct days) | | Binaries byte-identical | 218 / 218 — the EXE, the resident engine, 138 location overlays, 78 code modules | | Functions | 363,214 / 363,214 byte-identical; 360,737 in C (255,632 of them shared bodies via 2,220 dedup groups); 1,256 Sony library functions linked; 5 hand-written-assembly bodies kept verbatim; 0 stubs | | Instructions | 13,492,113 / 13,492,113 (100.0%); distinct code 5,820,205 / 5,820,205; main game code 45,150 / 45,150 | | Knowledge base | the matching cookbook (§1–§501 and sub-sections, 3.5 MB), the gcc-2.7.2 codegen map, 79 decision-log entries, 73 numbered rules (+ the constitution's 25) | | Tooling | ≈235 Python tools, 25 shell tools, 12 Ghidra scripts — the extractor, the byte gate, the dedup engine, the family engine, the atlas, the lanes, the rewrite package | *Every number above is generated or counted from the repository; the timeline behind the chart is [`docs/story-timeline.md`](story-timeline.md).*