From 4c1d5d9f7cfcd36729255adfb3f832a72bb2c8fe Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:42:41 -0600 Subject: [PATCH] =?UTF-8?q?docs(phase-33.5):=20task=2012=20=E2=80=94=20kit?= =?UTF-8?q?=20part=203:=20decomp-architect/SETUP.md=20(Step=200=20contract?= =?UTF-8?q?=20with=20the=20write-scope=20guardrails;=20Step=201=20the=20PA?= =?UTF-8?q?-2.0=20pin,=20the=20ladder-in-constitution=20check,=20the=20?= =?UTF-8?q?=C2=A7E=20precondition,=20Path=20A=20only,=20the=20Phase-0.5=20?= =?UTF-8?q?phase=20file;=20Step=202=20the=20interview=20+=20the=20`answers?= =?UTF-8?q?:`=20file=20contract;=20Step=203=20the=20firewall=20with=20the?= =?UTF-8?q?=20planted-fixture=20negative=20control=20and=20the=20check-ign?= =?UTF-8?q?ore=20probes;=20Step=204=20layout;=20Step=205=20bootstrap=20+?= =?UTF-8?q?=20the=20checkpoint=20commit;=20Step=206=20the=20flywheel=20doc?= =?UTF-8?q?uments=20that=20outlive=20the=20package;=20Step=207=20the=20reg?= =?UTF-8?q?istry=20seed=20inserted=20before=20=C2=A7E=E2=80=B2=20with=20th?= =?UTF-8?q?e=20renumber=20fallback;=20Step=208=20the=20overlays=20by=20mar?= =?UTF-8?q?ker=20+=20config=20templates=20instead=20of=20a=20live=20settin?= =?UTF-8?q?gs/mcp=20merge=20+=20the=20skeletons;=20Step=209=20the=20memory?= =?UTF-8?q?=20seed;=20Step=2010=20the=20leftover-placeholder=20audit,=20th?= =?UTF-8?q?e=20sorted=20install=20manifest,=20PhaseEnd=5FPhase0.5,=20the?= =?UTF-8?q?=20close=20commit,=20the=20five-part=20final=20message,=20hard?= =?UTF-8?q?=20stop;=20install=20manifest;=20troubleshooting);=20class=207?= =?UTF-8?q?=20of=20the=20firewall=20gains=20/.claude-state/transcripts/=20?= =?UTF-8?q?(a=20decomp's=20transcripts=20quote=20the=20target)=20and=20the?= =?UTF-8?q?=20scratch=20block=20re-includes=20.run/README.md=20=E2=80=94?= =?UTF-8?q?=20wiki=20fence=20+=20template=20re-extracted=20(75=20lines=20i?= =?UTF-8?q?dentical);=20pa-overlays=20Block=207=20=E2=86=92=20config/decom?= =?UTF-8?q?p-hooks.snippet.json=20+=20config/mcp.json.template=20(no=20com?= =?UTF-8?q?ment=20keys=20in=20JSON);=20PLACEHOLDERS=20"Filled"=20wording?= =?UTF-8?q?=20aligned=20with=20the=20steps;=20verify:=20kit=5Flint=20OK=20?= =?UTF-8?q?over=2044=20files,=20doc=5Flinks=20--strict=20rc=200,=2019/19?= =?UTF-8?q?=20PA=20installer=20mechanisms=20with=20counterparts,=2012/12?= =?UTF-8?q?=20markers=20present=20in=20their=20templates,=20all=20placehol?= =?UTF-8?q?ders=20named,=20every=20Step=20reference=20resolves;=20log=20+?= =?UTF-8?q?=20checkpoint=20(NEXT=20=3D=20task=2013,=20the=20dry-run,=20xHi?= =?UTF-8?q?gh)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- decomp-architect/SETUP.md | 291 ++++++++++++++++++++ decomp-architect/templates/PLACEHOLDERS.md | 22 +- decomp-architect/templates/gitignore.decomp | 4 + decomp-architect/templates/pa-overlays.md | 16 +- docs/wiki/The-ROM-firewall.md | 4 + phase-ends/CURRENT_PHASE.md | 192 +++++++------ 6 files changed, 432 insertions(+), 97 deletions(-) create mode 100644 decomp-architect/SETUP.md diff --git a/decomp-architect/SETUP.md b/decomp-architect/SETUP.md new file mode 100644 index 000000000..de23e235d --- /dev/null +++ b/decomp-architect/SETUP.md @@ -0,0 +1,291 @@ +# SETUP.md — decomp-architect installer (Phase 0.5 of a ProjectArchitect 2.0 project) + +> **For the human:** install ProjectArchitect 2.0 first, handing its interview `decomp-architect/intake.decomp.md` (the kit's +> `README.md`, step 1). Then, with this folder at your project root and a **fresh** Claude Code session, say: +> **"Read decomp-architect/SETUP.md and do it."** For an unattended run say instead **"Read decomp-architect/SETUP.md and do +> it; answers: "** (Step 2 describes the file). Expect file-write permission prompts; nothing here writes outside the +> repository. Everything below is for the agent. + +## Honesty — what this installs, and what it does not + +This installer stamps **documents, configuration and one script**: the ROM firewall (the ignore file, the audit with its config +and its negative control, the CI workflow), the layout and its READMEs, the decomp rules into the registry, the overlays on the +entry-point file, the digest, the phase templates, the effort map, the cookbook and the ops reference, the methodology and the +kernels into `docs/`, the tools manifest as a task list, the memory seed, and the license/notice/README/contributing skeletons. +It does **not** install a byte gate, a splitter configuration, a compiler, a disassembler, an emulator, a permuter harness, a +decompiler context or a differential harness — those are the first phases' work, listed in `docs/tools-manifest.md` as tasks +with the source project's tool named beside each. The generation-time values (the toolchain triple, the extract and fleet-check +commands, the oracle endpoints) are written as `TODO(phase-N)` lines that the named phase replaces. The one decision it cannot +make is whether the repository starts public or private; the firewall applies either way. + +--- + +## Step 0 — Execution contract (agent: read this first, follow it exactly) + +1. **You are Claude Code, running from the project's root**, with this package at `./decomp-architect/`. Resolve two + variables once and use them throughout: `KIT="./decomp-architect"` (if the folder is elsewhere, resolve its path) and + `ROOT="$(git rev-parse --show-toplevel)"`. Every git command is `git -C "$ROOT" …`. Quote every path. +2. **If you are in plan mode:** your plan is exactly *"execute SETUP.md Steps 1–10 in order."* Present that, get approval, + execute. Do not redesign, reorder or "improve" these steps. +3. **Copy templates verbatim.** Files are materialised with `cp`, then placeholders are filled with the Edit tool. **Never + retype a template's body from memory.** Placeholders come in two classes (`templates/PLACEHOLDERS.md` is the contract): + **copy-time** — answered once at Step 2 and filled wherever a template is copied in; **generation-time** — written as a + literal `TODO(phase-N)` line at Step 8 (`{{TOOLCHAIN_TRIPLE}}` → `TODO(phase-4)`, `{{EXTRACT_CMD}}` → `TODO(phase-1)`, + `{{FLEET_CHECK_CMD}}` → `TODO(phase-3)`, `{{DISASSEMBLER_MCP}}` and `{{EMULATOR_BRIDGE}}` → `TODO(phase-2)`). Step 10's + audit catches any leftover. +4. **Marked sections, never edits.** Every append lands under the block's own heading — its **marker** — at the END of the + target, or at the one insertion point a step names. A target that already contains the marker is SKIPPED. Nothing above + a marker is ever edited: ProjectArchitect's stamped content stays byte-identical. +5. **Every step self-verifies** (the ✓ line). If a verification fails: STOP, report exactly what failed, and wait — do not + improvise around it. +6. **Idempotent:** every step begins with an existence or marker check and a SKIP branch. Re-running this file after a crash + resumes at the first unticked checkbox of the Phase-0.5 `CURRENT_PHASE.md` (Step 1 creates it). +7. **Git and write scope:** commits add only the files this installer created or appended, **by explicit path** (never + `git add -A`); no attribution trailers; **never push**; never `git clean` (in a decomp the game-derived data is + ignored-but-present); never remove a directory with a relative `rm -rf` — the one deletion below is one explicit file; + **never write under the home directory** (`~/.claude` is ProjectArchitect's; the project's memory lives at the + repository's `.claude-state/memory/`). +8. **Interaction:** the developer answers once, at Step 2 — or the `answers:` file answers for them. An unanswered question + STOPs; nothing is defaulted silently. + +## Step 1 — Prerequisites: the version pin, the path, the registry precondition, the phase file + +1. `git -C "$ROOT" rev-parse --show-toplevel` succeeds (ProjectArchitect requires a git repository too). +2. **The version pin.** All of these must hold, else STOP with *"Install ProjectArchitect 2.0 first (its Path A), handing its + interview decomp-architect/intake.decomp.md; this kit overlays version 2.0 exactly"*: + `grep -q '^> \*\*Version:\*\* 2\.0' docs/project-architect.md` · `test -f RULES_REGISTRY.md` · `test -d phase-ends` · + `test -f PROJECT_CONTEXT.md` · `test -f CLAUDE.md` · `test -f phase-ends/PhaseEnd_Phase0.md` (the ProjectArchitect install + phase is closed) · `test -f phase-ends/CURRENT_PHASE.template.md` · `test -f phase-ends/PhaseEnd.template.md` · + `test -f docs/effort-map.md` · `test -f docs/ops-setup.md` · `ls docs/*cookbook*.md` lists exactly one file · + `test -d .claude-state/memory`. +3. **The ladder is in the constitution.** `grep -q 'Governance and the firewall' PROJECT_CONTEXT.md` (the Phase-0 name from + the intake's ladder). If it fails, the intake was not handed to the generation step. STOP and give the developer the two + options: re-run ProjectArchitect's install on a fresh repository with the intake, or proceed and record, in this phase's + PhaseEnd, the constitution correction that the roadmap of record is the intake's Part B (copied to `docs/decomp-ladder.md` + at Step 6 in that case) — the constitution itself is never edited (ProjectArchitect P1). Record the choice in the log. +4. **The registry precondition.** Between the `## §E` heading and the `## §E′` heading of `RULES_REGISTRY.md` there must be no + `### G` heading (the intake's Part D asked the generation step to leave only a one-line pointer). If rules G1…Gk already + exist there, Step 7 uses its renumber-by-offset fallback; note k now in the log. +5. **Path A only.** A repository that already holds a decompilation — any `src/*.c`, a splitter configuration under + `config/`, a `Makefile` with a build target — is an explicit STOP: *"an existing decompilation repository is out of this + version's scope; the kit installs into a fresh ProjectArchitect 2.0 project only."* +6. **The phase file.** If `phase-ends/CURRENT_PHASE.md` exists and names Phase 0.5 → resume from its first unticked step. + Else `cp phase-ends/CURRENT_PHASE.template.md phase-ends/CURRENT_PHASE.md` and fill it: *"Phase 0.5 — decomp-architect: + the decomp overlay"*, started today, the milestone = Step 10's verify list, the checklist = Steps 2–10 as checkboxes. + +✓ *Verify:* every test in 2 passes; 3 and 5 hold; the §E state is recorded; `CURRENT_PHASE.md` names Phase 0.5 and lists +Steps 2–10. + +## Step 2 — The game interview (the copy-time answers; `answers:` for unattended runs) + +1. **Read back from ProjectArchitect** (never re-ask): `{{PROJECT_NAME}}` = the title on `CLAUDE.md`'s first line (after the + dash); `{{COOKBOOK_NAME}}` = the file name of the one `docs/*cookbook*.md`; `{{INSTALL_DATE}}` = today in the format + ProjectArchitect used (an `answers:` file may pin it). +2. **Ask the developer, in ONE compact round**, offering a default where one is sane, the thirteen copy-time values: + `{{GAME_TITLE}}`, `{{PLATFORM}}`, `{{GAME_SERIAL}}`, `{{TARGET_BINARY}}` (the main executable's file name on the medium), + `{{DUMP_PATH}}` (an ABSOLUTE path to the developer's own dump; it must lie OUTSIDE the repository, and it is never copied + by this installer), `{{CONTAINER_LAYOUT}}`, `{{SDK_EVIDENCE}}`, `{{COMPILER_FAMILY}}` (a candidate set, not the pin), + `{{COMMUNITY_WORK}}` ("none found on " is an answer), `{{PROJECT_GOALS}}`, `{{LICENSE_CHOICE}}` (for the project's own + work; no license is asserted over the decompiled source), `{{AI_DISCLOSURE}}` (one project-level sentence), + `{{PUBLIC_OR_PRIVATE}}` (the day-one visibility; the firewall applies either way). +3. **Unattended mode.** If the developer's instruction carried `answers: `, read that file: one `KEY: value` line per + key (the placeholder name without braces; `#` starts a comment), the thirteen keys above plus the optional + `INSTALL_DATE`. Every question is answered from the file; **a missing or empty key STOPs, naming the key** — it is never + defaulted. +4. Record every answer in the Phase-0.5 log (`CURRENT_PHASE.md`), so the PhaseEnd can carry them. + +✓ *Verify:* all sixteen values are non-empty; `{{DUMP_PATH}}` is absolute and not under `$ROOT`; `{{COOKBOOK_NAME}}` resolves +to an existing file; in unattended mode, the file supplied every key. + +## Step 3 — The ROM firewall, in force from this commit + +1. **The ignore file.** If `.gitignore` does not contain the marker line `# ROM firewall — in force from the FIRST commit`: + append one dated comment line `# ---- decomp-architect Phase 0.5, installed {{INSTALL_DATE}} ----` and then the whole of + `$KIT/templates/gitignore.decomp`. Never remove or reorder ProjectArchitect's block above it. +2. `cp "$KIT/templates/firewall.txt" config/firewall.txt`; fill `{{TARGET_BINARY}}`. +3. `cp "$KIT/templates/firewall-fixture/blob.sha1" config/firewall-fixture.sha1` (the hash only — the blob itself is never + tracked; `templates/firewall-fixture/README.md` says why). +4. `cp "$KIT/templates/audit_public.template.py" tools/audit_public.py && chmod +x tools/audit_public.py`. +5. `mkdir -p .github/workflows && cp "$KIT/templates/no-rom.template.yml" .github/workflows/no-rom.yml`. +6. **The negative control — an audit that has not failed on its fixture is not trusted to pass:** + `mkdir -p .run/firewall-control && cp "$KIT/templates/firewall-fixture/blob.bin" .run/firewall-control/planted.bin`, then + `python3 tools/audit_public.py --paths .run/firewall-control/planted.bin` **must exit 1** and print + `OFFENDER .run/firewall-control/planted.bin`. Then `rm -f .run/firewall-control/planted.bin` (the one deletion in this + installer: an explicit file), and `python3 tools/audit_public.py` (the tracked tree) **must exit 0**. If the control passes + the planted blob, STOP: the fixture hash or the config is wrong; never proceed with an audit that cannot fail. +7. **The ignore probes.** Positive — each must succeed: `git -C "$ROOT" check-ignore -q disks/x.bin`, `… asm/x.s`, + `… extracted/x`, `… dumps/x.bin`, `… ghidra/x`, `… tools/psyq/x`, `… .claude-state/transcripts/x`, `… .run/scratch/x`. + Negative — each must FAIL (exit 1): `git -C "$ROOT" check-ignore -q src/main.c`, `… config/x.yaml`, + `… extracted/retail/manifest.jsonl`, `… .run/README.md`, `… .claude-state/memory/MEMORY.md`. + +✓ *Verify:* the marker is in `.gitignore` exactly once; the five files exist; the control failed then passed; every probe +behaved as listed. + +## Step 4 — The layout and its two READMEs + +1. `mkdir -p src config tools docs .run disks extracted/retail dumps` (the ignored ones exist so the probes above are real + directories; nothing is put in them). +2. `cp "$KIT/templates/docs-README.md" docs/README.md`; fill `{{PROJECT_NAME}}`, `{{INSTALL_DATE}}`, `{{CONTAINER_LAYOUT}}`. +3. `cp "$KIT/templates/run-README.md" .run/README.md`; fill `{{PROJECT_NAME}}`, `{{INSTALL_DATE}}` (the ignore file re-includes + exactly this one file under `.run/`). + +✓ *Verify:* the directories exist; both READMEs exist and contain no `{{`; `git -C "$ROOT" check-ignore -q .run/README.md` +FAILS (the README is trackable). + +## Step 5 — The bootstrap skeleton, and the checkpoint commit + +1. `cp "$KIT/templates/bootstrap.template.sh" tools/bootstrap.sh && chmod +x tools/bootstrap.sh && bash -n tools/bootstrap.sh`. +2. Tick Steps 2–5 in `CURRENT_PHASE.md`; write the Step-2 answers into its log if not yet done. +3. **Checkpoint commit, by explicit path:** `.gitignore config/firewall.txt config/firewall-fixture.sha1 tools/audit_public.py + .github/workflows/no-rom.yml docs/README.md .run/README.md tools/bootstrap.sh phase-ends/CURRENT_PHASE.md` — message + `chore: decomp-architect Phase 0.5 — firewall, layout, bootstrap` (no trailer). Do not push. + +✓ *Verify:* `bash -n` clean; the commit exists; `git -C "$ROOT" status --porcelain` lists none of those paths; +`git -C "$ROOT" log -1 --format=%B` contains no attribution trailer. + +## Step 6 — The flywheel skeleton (documents that outlive the package) + +1. `docs/wave-playbook.md` — CREATE from `pa-overlays.md` **Block 6** (the fenced body under that heading, copied verbatim); + fill `{{INSTALL_DATE}}`. SKIP if the file exists. +2. `docs/tools-manifest.md` — `cp "$KIT/tools/MANIFEST.md"` and prepend one line: *"Installed by decomp-architect on + {{INSTALL_DATE}}; every row is a Phase-N task until the tools are ported."* +3. `docs/decomp-kernels.md` — `cp "$KIT/corpus/decomp-kernels.md"` (the constitution's ladder cites kernels by id; they must + survive the package's deletion). +4. If Step 1.3 chose "proceed": `docs/decomp-ladder.md` — `cp "$KIT/intake.decomp.md"` with a banner naming it the roadmap of + record for this project. + +✓ *Verify:* the files exist; `grep -c '^| [0-9]' docs/wave-playbook.md` ≥ 11 (the step table); `grep -c '^### DK-' +docs/decomp-kernels.md` = 64; `grep -c '^| \`' docs/tools-manifest.md` = 325. + +## Step 7 — The registry: the decomp rules into §E + +1. Marker: the seed's own heading line `## §E — Project-specific rules (a matching decompilation)`. If `RULES_REGISTRY.md` + contains it → SKIP. +2. Re-assert the precondition of Step 1.4 (no `### G` heading between `## §E` and `## §E′`). +3. Take the seed body: from the line of `$KIT/templates/registry-E.decomp.md` that starts `## §E —` to its end (the leading + HTML comment is dropped). **Insert it immediately BEFORE the `## §E′` heading line** (ProjectArchitect's own `## §E` + heading, its italic paragraph and the pointer line stay above; the registry then reads: the §E heading, the pointer, the + installed block G1–G65, then §E′ and §F). +4. **Fallback** (only if Step 1.4 found rules G1…Gk in §E): renumber the seed body — every `G` token inside the body, + headings and cross-references alike — by `+k` with one scripted pass, change its heading to end `— installed as + G–G`, then insert as in 3. Record the offset in the log and the PhaseEnd. + +✓ *Verify:* `grep -c '^### G' RULES_REGISTRY.md` = 65 (or 65 + k); the marker appears exactly once; `## §E′` still follows the +block; the session-start recitation in `CLAUDE.md` already covers "every §E project rule" — nothing to change there. + +## Step 8 — The overlays and the skeletons + +*For each append: grep the target for the marker first; SKIP if present. Fill copy-time placeholders; write generation-time +ones as the `TODO(phase-N)` literals of Step 0.3.* + +1. **`CLAUDE.md`** ← `$KIT/templates/CLAUDE.decomp-overlay.md` from its `## Decomp fail-safes` line to the end (the leading HTML + comment dropped), APPENDED. Marker `## Decomp fail-safes`. Fill `{{INSTALL_DATE}}`, `{{COOKBOOK_NAME}}`; `{{FLEET_CHECK_CMD}}` + → `TODO(phase-3)`. +2. **`phase-ends/DIGEST.md`** ← `pa-overlays.md` **Block 1**, CREATE if absent. Fill `{{INSTALL_DATE}}`. Then write its part 2's + first synopsis line for Phase 0 (ProjectArchitect's install, from `PhaseEnd_Phase0.md`'s recap) — one sentence. +3. **`phase-ends/CURRENT_PHASE.template.md`** ← **Block 2** APPENDED at the end. Marker `## 🛑 SESSION CHECKPOINT`. (Every phase + from 1 on inherits the replayable block; the Phase-0.5 file, already created, keeps ProjectArchitect's shape.) +4. **`phase-ends/PhaseEnd.template.md`** ← **Block 3** INSERTED immediately before the `## PhaseEnd Changelog` line. Marker = + the block's heading. +5. **`docs/effort-map.md`** ← **Block 4** APPENDED. Marker `## Per-phase effort map (decomp ladder`. Fill `{{INSTALL_DATE}}`. +6. **`docs/{{COOKBOOK_NAME}}`** ← **Block 5** APPENDED. Marker `## The decomp entry shape`. Fill `{{INSTALL_DATE}}`, + `{{SDK_EVIDENCE}}`; `{{TOOLCHAIN_TRIPLE}}` → `TODO(phase-4)`. +7. **`docs/ops-setup.md`** ← `$KIT/templates/ops-setup.decomp.md` from its `## Decomp environment` line (the HTML comment + dropped), APPENDED. Marker `## Decomp environment`. Fill every copy-time placeholder it names; the five generation-time + ones as their `TODO(phase-N)` literals. +8. **`config/decomp-hooks.snippet.json`** and **`config/mcp.json.template`** ← **Block 7**'s two JSON bodies, CREATE each if + absent; `{{DISASSEMBLER_MCP}}` → `TODO(phase-2)`. `.claude/settings.json` and `.mcp.json` are NOT touched (Phase 2 merges and + copies them when the server exists). Validate both files parse as JSON. +9. **`docs/decomp-architect.md`** ← `cp "$KIT/decomp-architect.md"` (the methodology survives the package's deletion). +10. **The skeletons.** `LICENSE`: if absent, `cp "$KIT/templates/LICENSE.skeleton.md" LICENSE` and fill `{{LICENSE_CHOICE}}`, + and flag in the final message that it must be replaced by the license's verbatim text before the first push; if present, + leave it and note it. `src/NOTICE.md` ← `templates/NOTICE.src.md` (fill `{{GAME_TITLE}}`, `{{PLATFORM}}`, `{{GAME_SERIAL}}`, + `{{LICENSE_CHOICE}}`). `README.md` and `CONTRIBUTING.md`: if absent, create from the skeletons (fill `{{PROJECT_NAME}}`, + `{{GAME_TITLE}}`, `{{PLATFORM}}`, `{{GAME_SERIAL}}`, `{{PROJECT_GOALS}}`, `{{AI_DISCLOSURE}}`, `{{PUBLIC_OR_PRIVATE}}`, + `{{COMMUNITY_WORK}}`, `{{LICENSE_CHOICE}}`); if present, write the filled skeleton beside it as `README.decomp-skeleton.md` / + `CONTRIBUTING.decomp-skeleton.md` and tell the developer to merge by hand. `.clang-format`: `cp` if absent, else SKIP with + a note. `Makefile`: if absent, create it with the content of `templates/make-format.snippet.mk`; if present, APPEND the + snippet under its marker `.PHONY: format format-check`. + +✓ *Verify:* each marker appears exactly once in its target; `grep -c '{{' CLAUDE.md docs/ops-setup.md docs/effort-map.md +docs/{{COOKBOOK_NAME}} phase-ends/DIGEST.md src/NOTICE.md` = 0 for each; `grep -c 'TODO(phase-' docs/ops-setup.md` ≥ 5; both +JSON files parse; `docs/decomp-architect.md` exists. + +## Step 9 — The memory seed + +1. Assert the memory directory is the one ProjectArchitect configured: the `autoMemoryDirectory` value in + `.claude/settings.local.json` ends with `/.claude-state/memory`; the directory exists. **Nothing is written under the home + directory.** +2. `cp "$KIT/memory-seed/"*.md .claude-state/memory/` — every file EXCEPT `MEMORY.md`. +3. APPEND the kit's index rows to `.claude-state/memory/MEMORY.md`: a heading `## decomp-architect seed` (the marker; SKIP if + present), then every `- [` line of `$KIT/memory-seed/MEMORY.md` in order. +4. State plainly: **seeded memories activate from the NEXT session.** + +✓ *Verify:* `ls .claude-state/memory/*.md | grep -vc MEMORY.md` = 32 (ProjectArchitect's 16 + the kit's 16); every link in +the appended rows resolves to a file; the marker appears once. + +## Step 10 — Verify, the manifest, gitignore the package, close Phase 0.5, hard stop + +1. **The leftover-placeholder audit:** `grep -rln '{{' --include='*.md' --include='*.txt' --include='*.sh' --include='*.py' + --include='*.yml' --include='*.json' --include='*.mk' --include='Makefile' . | grep -v '^./decomp-architect/'` may list + ONLY `./docs/project-architect.md`, `./phase-ends/CURRENT_PHASE.template.md` and `./phase-ends/PhaseEnd.template.md` + (ProjectArchitect's own reference spec and templates). Anything else = an unfilled placeholder → fill it, then re-run. +2. `python3 tools/audit_public.py` → exit 0. `bash -n tools/bootstrap.sh`. `python3 -m py_compile tools/audit_public.py` + (then remove the `__pycache__` it makes, or run it with `PYTHONDONTWRITEBYTECODE=1`). +3. `grep -c '^### G' RULES_REGISTRY.md` = 65 (+ the offset, if any). +4. **Gitignore the package:** append to `.gitignore` under the comment `# decomp-architect (the day-one kit's package folder — + safe to delete after install)` the line `decomp-architect/` (SKIP if present). +5. **The install manifest:** write `.run/decomp-architect-install-manifest.txt` — one line per touched path, sorted, in the + form `CREATED ` / `APPENDED ()` / `SKIPPED ()` — and print it. (An unattended run diffs it + against an expected manifest.) +6. **Close the phase.** Tick Steps 6–10. Write `phase-ends/PhaseEnd_Phase0.5.md` from `phase-ends/PhaseEnd.template.md` (which + now carries the narrative axis): the Build Log = the manifest; Deviations (an existing README/LICENSE left beside a + skeleton, a registry offset, the Step-1.3 choice); Rules Added = *"G1–G65 installed into §E — the kit's seed; the origin + of each is its provenance line"*; the narrative axis filled honestly (what the install assumed, what it found); the + Plain-English Recap last. Run `bash tools/backup-claude-state.sh` (ProjectArchitect's state sweep; the transcripts it + copies are ignored by the class-7 line, the memory files are tracked). Then `git -C "$ROOT" mv phase-ends/CURRENT_PHASE.md + phase-ends/logs/PhaseLog_0.5.md`. +7. **The close commit, by explicit path:** every path in the manifest that this step or Steps 6–9 created or appended, plus + `.gitignore`, `phase-ends/PhaseEnd_Phase0.5.md`, `phase-ends/logs/PhaseLog_0.5.md`, `.claude-state/memory/…`. Message + `chore: decomp-architect Phase 0.5 — the decomp overlay installed` (no trailer). Do not push — tell the developer to review + and push. +8. **Final message, in order:** (a) the install manifest; (b) *"You may delete `decomp-architect/` from this repository (it is + gitignored; keep the master copy elsewhere) — `docs/decomp-architect.md`, `docs/decomp-kernels.md`, `docs/tools-manifest.md` + and the registry carry what matters"*; (c) if `LICENSE` was written from the skeleton: *"Replace `LICENSE` with the license's + verbatim text before the first push"*; (d) *"Start a **fresh session** (the seeded memories activate at startup) and say + **'Begin Phase 1'**"*; (e) the plain-English recap, last. Then **🛑 HARD STOP** — no previewing Phase 1, no continuing. + +✓ *Verify (before the final message):* the PhaseEnd exists; `CURRENT_PHASE.md` is archived, not deleted; both commits are +present and trailer-free; `git -C "$ROOT" status --porcelain` is empty apart from intentionally uncommitted items (none). + +--- + +## Install manifest (what exists after a completed install) + +``` +.gitignore (+ the firewall block, + decomp-architect/) config/firewall.txt config/firewall-fixture.sha1 +tools/audit_public.py .github/workflows/no-rom.yml tools/bootstrap.sh docs/README.md .run/README.md +docs/wave-playbook.md docs/tools-manifest.md docs/decomp-kernels.md docs/decomp-architect.md +RULES_REGISTRY.md (+ §E G1–G65) CLAUDE.md (+ Decomp fail-safes, Session-start extras) +phase-ends/DIGEST.md phase-ends/CURRENT_PHASE.template.md (+ the checkpoint block) +phase-ends/PhaseEnd.template.md (+ the narrative axis) docs/effort-map.md (+ the decomp rows) +docs/ (+ the entry shape and the triage table) docs/ops-setup.md (+ Decomp environment) +config/decomp-hooks.snippet.json config/mcp.json.template LICENSE (skeleton, or untouched) src/NOTICE.md +README.md, CONTRIBUTING.md (created, or *.decomp-skeleton.md beside the existing ones) .clang-format Makefile (+ format) +.claude-state/memory/ (+ 16 seeds, + the index rows) phase-ends/PhaseEnd_Phase0.5.md phase-ends/logs/PhaseLog_0.5.md +``` + +## Troubleshooting + +- **The version line is not found** → the project is not a ProjectArchitect 2.0 install; install it first (its Path A) with the + intake, then re-run this file. +- **§E already holds rules** → Step 7's renumber-by-offset fallback; the offset goes in the log and the PhaseEnd. +- **A README, LICENSE, CONTRIBUTING or `.clang-format` already exists** → the skeleton is written beside it (or skipped) and + named in the final message; merging is the developer's. +- **The control passes the planted blob** → STOP; `config/firewall-fixture.sha1` or `config/firewall.txt` is wrong. An audit + that cannot fail proves nothing. +- **The `answers:` file lacks a key** → STOP, naming the key; unattended runs never default. +- **Interrupted mid-install** → say "Read decomp-architect/SETUP.md and do it" again; Step 1.6 resumes at the first unticked + checkbox of the Phase-0.5 `CURRENT_PHASE.md`. +- **The disassembler or emulator is not reachable** → not an install concern; Phase 2 sets them up, and `docs/ops-setup.md` + carries their `TODO(phase-2)` rows until then. diff --git a/decomp-architect/templates/PLACEHOLDERS.md b/decomp-architect/templates/PLACEHOLDERS.md index 499213fe4..6c60c9178 100644 --- a/decomp-architect/templates/PLACEHOLDERS.md +++ b/decomp-architect/templates/PLACEHOLDERS.md @@ -7,10 +7,10 @@ > the kit's Step 10) must find none of these anywhere in the project outside the kit's own package folder and the > reference copy of the methodology. > -> **Two classes**, following ProjectArchitect: **copy-time** placeholders are filled while the templates are copied in -> (the kit's SETUP Steps 2–5, from the game interview and from values ProjectArchitect already stamped); **generation-time** -> placeholders are filled when the overlays are generated (Steps 7–9), and some legitimately stay a `TODO` until the phase -> that produces their value — those say so. +> **Two classes**, following ProjectArchitect: **copy-time** placeholders are answered at the game interview (the kit's +> SETUP Step 2, plus three values read back from what ProjectArchitect already stamped) and filled wherever a template is copied +> in (Steps 3–9); **generation-time** placeholders have no value at Phase 0.5 — the installer writes each as a literal +> `TODO(phase-N)` line at Step 8, and the phase that produces the value replaces the line. ## Shared with ProjectArchitect (read back from the files it already stamped; never re-asked) @@ -21,7 +21,7 @@ | `{{COOKBOOK_NAME}}` | the cookbook file ProjectArchitect created under `docs/` | the CLAUDE overlay's flywheel line, the cookbook overlay | | `{{DOMAIN_FAILSAFES}}` | **referenced only, never filled by the kit** — ProjectArchitect's own CLAUDE.md placeholder, which its generation step fills from the intake's Part D | `intake.decomp.md` Part D names it so the generation step knows which four fail-safes to write | -## Copy-time (the game interview — SETUP Step 2) +## Copy-time (answered at SETUP Step 2; filled at Steps 3–9) | Placeholder | What it is | Used in | |---|---|---| @@ -39,15 +39,15 @@ | `{{AI_DISCLOSURE}}` | the project-level sentence disclosing how AI is used | the README skeleton, CONTRIBUTING | | `{{PUBLIC_OR_PRIVATE}}` | the day-one visibility decision (the firewall applies either way) | the README skeleton, the ops-setup git posture | -## Generation-time (the overlays — SETUP Steps 7–9) +## Generation-time (written as `TODO(phase-N)` at SETUP Step 8; replaced by the phase that produces the value) | Placeholder | What it is | Filled when | Used in | |---|---|---|---| -| `{{TOOLCHAIN_TRIPLE}}` | the pinned compiler → assembler shim → binutils triple with flags | **Phase 4** — installed as a literal `TODO(phase-4)` line that the pin task replaces | the ops-setup version pins, the cookbook overlay's pinned context | -| `{{EXTRACT_CMD}}` | the one command that extracts the medium and verifies the manifest | Step 9 (as `TODO(phase-1)` until the extractor exists) | the ops-setup build/run/test block | -| `{{FLEET_CHECK_CMD}}` | the clean fleet verification (`clean → extract → build` over every binary, exit code read) | Step 9 (`TODO(phase-3)` until the baseline exists) | the ops-setup gate line, the CLAUDE overlay's fail-safe wording | -| `{{DISASSEMBLER_MCP}}` | the disassembler server's endpoint and the command that starts it | Step 9 (`TODO(phase-2)`) | the ops-setup MCP/hooks row | -| `{{EMULATOR_BRIDGE}}` | the runtime oracle's scripting interface or bridge endpoint | Step 9 (`TODO(phase-2)`) | the ops-setup MCP/hooks row | +| `{{TOOLCHAIN_TRIPLE}}` | the pinned compiler → assembler shim → binutils triple with flags | Step 8 as `TODO(phase-4)`; Phase 4's pin task replaces it | the ops-setup version pins, the cookbook overlay's pinned context | +| `{{EXTRACT_CMD}}` | the one command that extracts the medium and verifies the manifest | Step 8 as `TODO(phase-1)` | the ops-setup build/run/test block | +| `{{FLEET_CHECK_CMD}}` | the clean fleet verification (`clean → extract → build` over every binary, exit code read) | Step 8 as `TODO(phase-3)` | the ops-setup gate line, the CLAUDE overlay's fail-safe wording | +| `{{DISASSEMBLER_MCP}}` | the disassembler server's endpoint and the command that starts it | Step 8 as `TODO(phase-2)` | the ops-setup MCP/hooks row, `config/mcp.json.template` | +| `{{EMULATOR_BRIDGE}}` | the runtime oracle's scripting interface or bridge endpoint | Step 8 as `TODO(phase-2)` | the ops-setup MCP/hooks row | ## Not placeholders (by design) diff --git a/decomp-architect/templates/gitignore.decomp b/decomp-architect/templates/gitignore.decomp index d8e973b80..900c121c7 100644 --- a/decomp-architect/templates/gitignore.decomp +++ b/decomp-architect/templates/gitignore.decomp @@ -35,7 +35,10 @@ /tools/psyq/ # 7. Session transcripts — they quote the target's disassembly; keep them out of any public tree +# (a governance system that keeps the agent's transcripts inside the repository writes them under +# .claude-state/transcripts/ — ignored here; the memory files beside them stay tracked) /session-archive/ +/.claude-state/transcripts/ # 8. Training data and weights derived from the target /datasets/ @@ -54,6 +57,7 @@ # ---- irreplaceable work. Rule of thumb: commit what a rerun CANNOT reproduce (hand analysis, ---- # ---- harnesses, ledgers, the recorded contract run); leave what a script regenerates ignored. ---- /.run/* +!/.run/README.md # One dated block per exception — re-include the directory, re-exclude its contents, re-include # the wanted files — under a comment naming the phase, the session and the rule. For example: # # P (, ): the recorded contract run's per-step logs. Evidence, tracked. diff --git a/decomp-architect/templates/pa-overlays.md b/decomp-architect/templates/pa-overlays.md index f828ca683..cddf4021a 100644 --- a/decomp-architect/templates/pa-overlays.md +++ b/decomp-architect/templates/pa-overlays.md @@ -198,11 +198,13 @@ the reconcile ladder without a redraft; the gate number is not the close rate un --- -## Block 7 — `.claude/settings.json` (MERGE at Step 8; add only absent keys) and `.mcp.json` (CREATE at Step 8) +## Block 7 — `config/decomp-hooks.snippet.json` and `config/mcp.json.template` (CREATE at Step 8; activated at Phase 2) -*ProjectArchitect already wrote the `SessionEnd` backup hook; the kit adds a `SessionStart` slot for the disassembler -server (filled at Phase 2) and the MCP client entry. Merge rule: add a key only if absent; never overwrite; validate -the JSON afterwards.* +*ProjectArchitect already wrote the `SessionEnd` backup hook into `.claude/settings.json`. The kit does NOT merge a hook or an +MCP entry at Phase 0.5 — a hook that runs a stub every session and an MCP client entry pointing at nothing would only add +noise and prompts. It installs the two snippets below as config templates; Phase 2 (the oracles) writes the server-start +script, merges the hook (add only absent keys, validate the JSON afterwards) and copies the MCP template to `.mcp.json` with +the real loopback endpoint. Generation-time values are written as `TODO(phase-2)` at install.* ````json { @@ -212,8 +214,7 @@ the JSON afterwards.* "hooks": [ { "type": "command", - "command": "bash \"$CLAUDE_PROJECT_DIR\"/tools/disassembler_mcp_start.sh", - "_comment": "TODO(phase-2): the script that starts the disassembler's headless server and prints 'serving'; until it exists this hook is a no-op stub the kit installs" + "command": "bash \"$CLAUDE_PROJECT_DIR\"/tools/disassembler_mcp_start.sh" } ] } @@ -227,8 +228,7 @@ the JSON afterwards.* "mcpServers": { "disassembler": { "type": "sse", - "url": "{{DISASSEMBLER_MCP}}", - "_comment": "TODO(phase-2): the loopback SSE endpoint of the disassembler's MCP server; after any restart, the developer reconnects the client" + "url": "{{DISASSEMBLER_MCP}}" } } } diff --git a/docs/wiki/The-ROM-firewall.md b/docs/wiki/The-ROM-firewall.md index 1ac847129..ad407d375 100644 --- a/docs/wiki/The-ROM-firewall.md +++ b/docs/wiki/The-ROM-firewall.md @@ -83,7 +83,10 @@ copies are identical). Adjust the path names to your layout; do not delete a cla /tools/psyq/ # 7. Session transcripts — they quote the target's disassembly; keep them out of any public tree +# (a governance system that keeps the agent's transcripts inside the repository writes them under +# .claude-state/transcripts/ — ignored here; the memory files beside them stay tracked) /session-archive/ +/.claude-state/transcripts/ # 8. Training data and weights derived from the target /datasets/ @@ -102,6 +105,7 @@ copies are identical). Adjust the path names to your layout; do not delete a cla # ---- irreplaceable work. Rule of thumb: commit what a rerun CANNOT reproduce (hand analysis, ---- # ---- harnesses, ledgers, the recorded contract run); leave what a script regenerates ignored. ---- /.run/* +!/.run/README.md # One dated block per exception — re-include the directory, re-exclude its contents, re-include # the wanted files — under a comment naming the phase, the session and the rule. For example: # # P (, ): the recorded contract run's per-step logs. Evidence, tracked. diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index d003c6644..9ea9e577b 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -50,7 +50,7 @@ in-tree links to `docs/wiki/.md`. 8. `.run/`: only what git tracks; no sca - [x] **9** Memory reconciliation (the off-project file parked; the 7 stale updated in place; `bfm-decomp-context-system` refreshed; the seed set — 16 files — under `decomp-architect/memory-seed/` with `upstream: PA` tags) — xHigh — see Log 2026-09-07 Task 9 - [x] **10** Kit part 1: `README.md`, `intake.decomp.md`, `decomp-architect.md`, `templates/registry-E.decomp.md`, `corpus/decomp-kernels.md`, `templates/PLACEHOLDERS.md` — Max — see Log 2026-09-07 Task 10 - [x] **11** Kit part 2: the firewall pack, docs/run READMEs, ops-setup, bootstrap, CLAUDE overlay, `pa-overlays.md`, LICENSE/NOTICE/README/CONTRIBUTING skeletons, `.clang-format` + format snippet, `tools/MANIFEST.md`; `tools/kit_lint.py` in tools-health — xHigh — see Log 2026-09-07 Task 11 -- [ ] **12** Kit part 3: `SETUP.md` (§0–§10, `--answers`, the PA-2.0 version pin, the honesty section, Path A only) — Max — **then P6 rules check** +- [x] **12** Kit part 3: `SETUP.md` (Step 0–Step 10, `answers:`, the PA-2.0 version pin, the honesty section, Path A only) — Max — **then P6 rules check** — see Log 2026-09-07 Task 12 - [ ] **13** Dry-run install under D6's guardrails; fix; re-run to green; fixture + expected manifest + logs tracked under `.run/P33.5/kit-dryrun/` — xHigh - [ ] **13.5** *(added 2026-09-07 by Drew — plan amendment, P5d)* **Tools audit + the derived tool index:** `tools/tool_census.py` — for every file under `tools/` outside submodules/vendored code: the docstring line, its consumers (Makefile/`.mk` targets, CI, the wave playbook, its SETUP row, other tools by import or subprocess), its class (LIVE · RETIRED-CAMPAIGN · ONE-OFF · PORTABLE vs PROJECT-ONLY) and its ladder phase; coverage-asserted against `find` (R32) → the generated `docs/tool-index.md` keyed by workflow step (KEEP-GEN, `--check` in tools-health, a Reference-index row, linked from The-matching-workflow + Toolchain-setup, one pointer line in how-to ch.04/05/10); the kit's `tools/MANIFEST.md` RE-DERIVED from the census (`--manifest`, freshness asserted) instead of transcribed; the hand review of the no-consumer class (91 of 326 at S91) under **Drew's criterion: a tool that served a purpose and was REQUIRED to complete the decomp is judged on its value to a FUTURE decomp — still needed (stays live and/or becomes a port task in the kit manifest), superseded by a better tool (retired, the row NAMING the successor), or a one-off (retired, the row naming what it produced)**; retirement = `git mv` → `tools/sunset/` only after the consumer census proves nothing imports it, an archive-index-style row per tool, its SETUP row moved to a retired section; Drew reviews and deletes later, as with `docs/sunset/` — xHigh (the classification draft is breadth-shaped: one read-only Explore agent, verified against the consumer list) — verify: rows == `find` count (326/326 at S91); `tool-index --check` green; every retired tool has 0 consumers AND a named successor or product; the MANIFEST regenerated byte-equal; `kit_lint` OK; `doc_links --strict` rc 0 - [ ] **14** Wiki `Start-a-new-decomp-project.md` + README/`Tools-from-this-project.md` rows + SETUP rows (R21) + decision-log entry (R31) + accelerators entry if earned — xHigh @@ -530,91 +530,125 @@ config separate from the code so a project edits the config only). ### 2026-09-07 — Plan amendment (Drew, S91): task 13.5 added Asked whether `tools/` had been audited the way `docs/`, `.run/` and the memory store were, the measured answer was no: of 326 tool files (submodules/vendored excluded) 224 have a SETUP row, 54 a Makefile consumer, 14 CI, 34 the playbook, 4 the how-to chapters, 58 a wiki page, 210 another tool; **91 have no runtime consumer at all**; `tools/README.md` is 1 KB; the kit's MANIFEST is an agent-transcribed table. Drew: add task 13.5 (the audit + a derived tool index + the MANIFEST re-derived), and retire only on his criterion — a tool that was required to finish the decomp is judged on its value to a future decomp: still needed, superseded (name the successor), or one-off (name what it produced). Inserted after the dry-run and before the wiki page so task 14 can link the index. -## 🛑 SESSION CHECKPOINT — Tasks 0–11 ✓; NEXT = task 12 (kit part 3: `decomp-architect/SETUP.md`; **Max** — prompt Drew, R27; then the P6 rules check) +### 2026-09-07 — Task 12 — Kit part 3: `decomp-architect/SETUP.md` (Max; S91) +**Written:** `SETUP.md` (25 KB): the human header (the exact instruction; `answers: ` for unattended runs); the **honesty +section** near the top (documents, configuration and one script; no gate/splitter/compiler/disassembler/emulator/permuter/context/ +harness — those are `docs/tools-manifest.md`'s tasks; the generation-time values as `TODO(phase-N)` lines; the visibility decision is +the developer's); **Step 0** the execution contract (`KIT`/`ROOT`, `git -C "$ROOT"`; plan mode = "execute Steps 1–10"; copy verbatim + +Edit-tool fills, the two placeholder classes with the five generation-time literals; marked sections never edits; per-step ✓; +idempotent via the Phase-0.5 `CURRENT_PHASE.md`; explicit-path commits, no trailers, never push, never `git clean`, no relative +`rm -rf`, **never under the home directory**; the interview once or the answers file — a missing key STOPs, never defaults); **Step 1** +the PA-2.0 pin (twelve assertions incl. `PhaseEnd_Phase0.md` closed and exactly one cookbook), the ladder-in-constitution check with +the two owner options if absent (the constitution is never edited), the §E precondition (record k), Path A only (an existing decomp +repo is a STOP), the Phase-0.5 phase file from PA's template; **Step 2** the interview: 3 read-backs (PROJECT_NAME from CLAUDE.md's +title, COOKBOOK_NAME from the one `docs/*cookbook*.md`, INSTALL_DATE) + the 13 copy-time answers in one round (DUMP_PATH absolute and +outside the repo, never copied) + the `KEY: value` answers-file contract; **Step 3** the firewall (the ignore block APPENDED under a +dated line, never replacing PA's; `config/firewall.txt`, `config/firewall-fixture.sha1`, `tools/audit_public.py`, the CI workflow; **the +negative control** — plant the blob under scratch, the audit MUST exit 1 naming it, remove the one explicit file, the audit MUST exit 0; +eight positive and five negative `check-ignore` probes); **Step 4** layout + the two READMEs; **Step 5** the bootstrap skeleton + **the +checkpoint commit** (PA's own mid-install precedent); **Step 6** the flywheel documents that outlive the package (the wave playbook from +Block 6, `docs/tools-manifest.md`, `docs/decomp-kernels.md`, optionally `docs/decomp-ladder.md`); **Step 7** the registry: the seed body +from its `## §E —` line INSERTED before `## §E′` (PA's heading + pointer stay above), the renumber-by-offset fallback; **Step 8** the +overlays by marker (CLAUDE, DIGEST create, the CURRENT_PHASE template append, the PhaseEnd template INSERT before "PhaseEnd Changelog", +effort map, cookbook, ops-setup), `config/decomp-hooks.snippet.json` + `config/mcp.json.template` (Block 7 — **not** a live merge), the +methodology copy, the skeletons with the present/absent rules (`*.decomp-skeleton.md` beside an existing file; LICENSE flagged for the +verbatim text), `.clang-format`, the Makefile snippet; **Step 9** the memory seed (16 files + the index rows under a marker; the +memory dir asserted to be PA's `.claude-state/memory`; nothing under `~/.claude`); **Step 10** the leftover-placeholder audit (allowed +hits = PA's three), the audit/bash -n/py_compile checks, G-count, gitignore the package, the sorted `CREATED/APPENDED/SKIPPED` manifest +to `.run/decomp-architect-install-manifest.txt`, PhaseEnd_Phase0.5 from the template with the narrative axis, the state sweep, the +`git mv` to `logs/PhaseLog_0.5.md`, the close commit by explicit path, the five-part final message, 🛑; the install manifest; +troubleshooting (seven rows). +**Three supporting changes (X1, each a correctness fix):** (1) **class 7 of the firewall** — ProjectArchitect keeps the agent's +transcripts INSIDE the repository (`.claude-state/transcripts/`, committed while private under its H8) and a decomp's transcripts quote +the target's disassembly (the source project purged ~260,000 lines of `.s` from its session archive): `/.claude-state/transcripts/` +added under class 7 in the wiki page's fence AND the template (re-extracted, 71 → 75 lines, `gitignore_template_check` OK), with +`!/.run/README.md` under the scratch block so Step 4's README is trackable; (2) **Block 7 is no longer a live merge** — a SessionStart +hook running a stub every session and an MCP entry pointing at nothing would only add noise/prompts, and `_comment` keys inside the +hook/MCP objects risk the harness's schema; the block now installs `config/decomp-hooks.snippet.json` + `config/mcp.json.template`, +activated at Phase 2 (the JSON bodies carry no comment keys); (3) `PLACEHOLDERS.md`'s "Filled" wording aligned with the steps (answered +at Step 2, filled at Steps 3–9; generation-time as `TODO(phase-N)` at Step 8). +**Verify:** `kit_lint` OK over 44 files (leak 0; placeholders 22 == 22; syntax 0/3; gitignore 75 identical; `TODO(platform)` 7, +`TODO(phase-N)` 38); `doc_links --strict` rc 0; the structural read-through as a script — 19/19 PA installer mechanisms have a +counterpart (contract, plan-mode line, verbatim copy, per-step ✓, idempotent resume, explicit-path commits, no trailers, never push, one +interview round, the phase file, the placeholder audit, the manifest, troubleshooting, hard stop, the delete note, the fresh session, +the version pin, the write-scope guardrails, the negative control); 12/12 markers SETUP greps for exist verbatim in their templates; +SETUP names all 21 non-PA placeholders and no unlisted one; every `Step N` reference resolves (0–10); PLACEHOLDERS' step refs (2, 8, +10) exist; 0 `§`+digit. **Deviation from the plan's wording:** `§0–§10` → `Step 0 … Step 10` (the lint), `--answers` → the +`answers: ` clause of the instruction (a Claude Code prompt has no flags). No build input changed. + +## 🛑 SESSION CHECKPOINT — Tasks 0–12 ✓; NEXT = task 13 (the dry-run install under D6's guardrails; **xHigh** — prompt Drew, R27) ### 0. How to use this block You are a FRESH SESSION that has read `PROJECT_CONTEXT.md`, `phase-ends/DIGEST.md`, `PhaseEnd_Phase31/32/33.md` and this file, and nothing else (R64). Replay this block verbatim, state phase / done / NEXT / effort, list the rules from the digest (R1–R83), then -WAIT for Drew. Rebuild the harness task list (17 rows incl. task 13.5, R28) marking tasks 0–11 completed and task 12 in progress. +WAIT for Drew. Rebuild the harness task list (17 rows incl. task 13.5, R28) marking tasks 0–12 completed and task 13 in progress. ### 1. Where we are **Phase 33.5** (sub-phase; v1.32.0 → v1.32.1), gate 1 approved 2026-09-07 by Drew in plan mode at Max; effort follows the plan's -column (Max for tasks 12 and 15 — prompt at each transition, R27). Baseline HEAD `80d45b29b`; task 0 = `39d524991`; task 1 = -`a0cf302e5`; task 2 = `d06923a06`; task 3 = `5d10a0d12`; task 4 = `9970f1e62`; task 5 = `a0d4ae836`; task 6 = `6ec4786bd`; task 7 = -`21c98ed5a`; task 8 = `ae71efe56`; task 9 = `caefe9872`; S90 checkpoint = `e1463d430`; task 10 = `83de29c02`; task 11 = the commit -after this block (session S91, 2026-09-07). No build input changed; the fleet is 218/218 at the Phase-33 close and -**`make tools-health` is OK on this tree (S91, `.run/P33.5/tools_health_t11.log`)**. Tracked `.run/` = 868; `audit_public` OK; -`gate_scan` PASS; `doc_links --strict` rc 0; pending list empty. **The kit directory holds everything except `SETUP.md`:** `README.md`, -`intake.decomp.md`, `decomp-architect.md`, `corpus/decomp-kernels.md` (DK-1…DK-64), `memory-seed/` (16 + MEMORY.md), -`tools/MANIFEST.md` (325 rows by phase), and `templates/` — `registry-E.decomp.md` (G1–G65), `PLACEHOLDERS.md` (the 22-set), -`gitignore.decomp`, `firewall.txt`, `audit_public.template.py`, `firewall-fixture/{blob.bin,blob.sha1,README.md}`, -`no-rom.template.yml`, `docs-README.md`, `run-README.md`, `ops-setup.decomp.md`, `bootstrap.template.sh`, `CLAUDE.decomp-overlay.md`, -`pa-overlays.md` (7 blocks), `LICENSE.skeleton.md`, `NOTICE.src.md`, `README.skeleton.md`, `CONTRIBUTING.skeleton.md`, `.clang-format`, -`make-format.snippet.mk`. `tools/kit_lint.py` runs in tools-health (selftest + real). Tasks 12–13 finish the kit; 14–15 close. +column (Max for task 15 — prompt at each transition, R27; tasks 13, 13.5 and 14 are xHigh). Baseline HEAD `80d45b29b`; task 0 = +`39d524991`; task 1 = `a0cf302e5`; task 2 = `d06923a06`; task 3 = `5d10a0d12`; task 4 = `9970f1e62`; task 5 = `a0d4ae836`; task 6 = +`6ec4786bd`; task 7 = `21c98ed5a`; task 8 = `ae71efe56`; task 9 = `caefe9872`; S90 checkpoint = `e1463d430`; task 10 = `83de29c02`; +task 11 = `9235800fb`; the plan amendment (task 13.5 added by Drew) = `6fb2bc7f8`; task 12 = the commit after this block (session S91, +2026-09-07). No build input changed; the fleet is 218/218 at the Phase-33 close and `make tools-health` was OK at task 11 on this tree +(`.run/P33.5/tools_health_t11.log`); since then only kit files, the wiki fence (class 7) and this file changed. Tracked `.run/` = 868; +`audit_public` OK; `gate_scan` PASS; `doc_links --strict` rc 0; pending list empty. **The kit is complete on paper:** `README.md`, +`intake.decomp.md`, `SETUP.md`, `decomp-architect.md`, `corpus/decomp-kernels.md`, `memory-seed/`, `tools/MANIFEST.md`, `templates/` +(22 files incl. `firewall-fixture/`). `tools/kit_lint.py` is in tools-health. **The P6 rules check was done after task 12 (S91).** **Already banked for task 14 (R31):** the `docs/decision-log.md` entry "P33.5 S90" — task 14 must NOT write a second one; it still owes -the wiki page `Start-a-new-decomp-project.md`, the README/`Tools-from-this-project.md` rows, the SETUP rows for the kit (the kit_lint -row exists), and an accelerators entry if the dry-run earns one. Nothing runs in the background; the headless Ghidra MCP was never -used (no RE work; nothing under `ghidra/` is tracked). The plan file `~/.claude/plans/max-effort-set-plan-encapsulated-muffin.md` is a -copy of the "Approved plan" section at the end of this file — this file is the one that counts. +the wiki page `Start-a-new-decomp-project.md`, the README/`Tools-from-this-project.md` rows, the SETUP rows for the kit, and an +accelerators entry if the dry-run earns one. **Task 13.5 (added 2026-09-07 by Drew)** follows task 13: the tools audit + the derived +tool index, the kit MANIFEST re-derived, retirement only under his criterion (still needed for a future decomp / superseded by a named +successor / one-off) — its row in the Tasks list carries the full spec. Nothing runs in the background; the headless Ghidra MCP was +never used (no RE work; nothing under `ghidra/` is tracked). The plan file `~/.claude/plans/max-effort-set-plan-encapsulated-muffin.md` +is a copy of the "Approved plan" section at the end of this file — this file is the one that counts. -### 2. What NEXT does (task 12, **Max**) — exact steps (plan D5, "Kit part 3 — SETUP.md") -**Read first:** `/mnt/z/Storage/git/ProjectArchitect/project-architect-2.0/SETUP.md` in full (THE SHAPE TO MIRROR: the execution -contract, `✓ Verify` per step, idempotent via CURRENT_PHASE.md checkboxes, commit by explicit path, never push, the install run as a -phase, the hard stop) and its `templates/CURRENT_PHASE.template.md` + `PhaseEnd.template.md` (the kit's Phase 0.5 uses them); -`decomp-architect/README.md` (the promises SETUP must keep: what it installs / does NOT, the version pin, Path A only); -`decomp-architect/templates/PLACEHOLDERS.md` (which step fills which placeholder — SETUP's steps must match its "Filled" column); -`decomp-architect/templates/pa-overlays.md` (each block's target/marker/step — SETUP applies them by marker, idempotently); -`decomp-architect/templates/firewall-fixture/README.md` (the control's exact procedure); `decomp-architect/intake.decomp.md` Part D -(the §E-empty precondition SETUP Step 7 asserts) and Part C; the plan's D5 + D6 in the "Approved plan" section below (the dry-run's -guardrails shape what SETUP may write: never under `~/.claude`, every git call `git -C `, no `git clean`, no relative `rm -rf`). -**Write `decomp-architect/SETUP.md`** — headings `## Step 0` … `## Step 10` (NOT `§N`: the lint bans `§`+digit; refer to PA's sections as -"step N" too). Contents per step: **Step 0** the execution contract (Claude Code from the project root with `KIT=./decomp-architect`; -in plan mode the plan is "execute Steps 1–10 in order", no redesign; templates copied verbatim with `cp`, placeholders filled with the -Edit tool, never retyped; every step self-verifies, STOP on a failed verify; idempotent — re-run resumes from the first unticked -checkbox of the Phase-0.5 CURRENT_PHASE; commits by explicit path, no trailers, never push; the developer answers Step 2 once — or -`--answers `: "if the file exists every question is answered from it; an unanswered question STOPs, never defaults"); -**Step 1** prerequisites — assert `grep -q '^> \*\*Version:\*\* 2\.0' docs/project-architect.md`, `RULES_REGISTRY.md` and -`phase-ends/` exist, `PROJECT_CONTEXT.md` exists and carries the ladder (grep "Phase 0.5" or the intake's phase names), the PA install -phase is closed (a `PhaseEnd_Phase0.md`), registry §E holds only the one-line pointer (else STOP with the renumber-by-offset fallback -spelled out), and the repo is a PA Path-A project — an existing decomp repository (any `src/*.c`, a splitter config, a `Makefile` with a -build) is an explicit STOP; then create the Phase-0.5 `CURRENT_PHASE.md` from PA's template with Steps 2–10 as checkboxes; -**Step 2** the game interview → the 13 copy-time placeholders (one compact round; `--answers` unattended; record the answers into the -Phase-0.5 log); **Step 3** the firewall — append `templates/gitignore.decomp` to `.gitignore` under a dated marker (NEVER replace PA's -block), copy `firewall.txt` → `config/firewall.txt` (fill `{{TARGET_BINARY}}`), copy `firewall-fixture/blob.sha1` → -`config/firewall-fixture.sha1`, copy `audit_public.template.py` → `tools/audit_public.py` (+x), copy `no-rom.template.yml` → -`.github/workflows/no-rom.yml`; **the control**: `mkdir -p .run/firewall-control && cp $KIT/templates/firewall-fixture/blob.bin -.run/firewall-control/planted.bin && python3 tools/audit_public.py --paths .run/firewall-control/planted.bin` must exit 1 naming the -planted file; `rm` it; `python3 tools/audit_public.py` must exit 0 (`git check-ignore` positive probes `disks/x.bin asm/x.s -extracted/x` and negative probes `src/main.c config/x.yaml`); **Step 4** layout — `mkdir -p src config tools docs .run disks -extracted dumps` + `docs/README.md` from `docs-README.md`, `.run/README.md` from `run-README.md` (fill PROJECT_NAME/INSTALL_DATE/ -CONTAINER_LAYOUT); **Step 5** `bootstrap.template.sh` → `tools/bootstrap.sh` (+x, `bash -n`); **Step 6** the flywheel skeleton — -`pa-overlays.md` block 6 → `docs/wave-playbook.md` (CREATE), `tools/MANIFEST.md` → `docs/tools-manifest.md` (the Phase-1 task list), -`corpus/decomp-kernels.md` → `docs/decomp-kernels.md` (the intake's ladder cites DK ids — they must survive package deletion); -**Step 7** registry — append `registry-E.decomp.md`'s body under §E after asserting the pointer line (marker = the seed's `## §E —` line; -idempotent); **Step 8** overlays + skeletons — `CLAUDE.decomp-overlay.md` appended to `CLAUDE.md` (marker `## Decomp fail-safes`); -`pa-overlays.md` blocks 1 (CREATE `phase-ends/DIGEST.md`), 2 (APPEND to `phase-ends/CURRENT_PHASE.template.md`), 3 (APPEND to -`phase-ends/PhaseEnd.template.md`), 4 (APPEND to `docs/effort-map.md`), 5 (APPEND to `docs/`), 7 (MERGE `.claude/settings.json` -adding only absent keys, CREATE `.mcp.json`); `ops-setup.decomp.md` appended to `docs/ops-setup.md`; `decomp-architect.md` → -`docs/decomp-architect.md`; the skeletons → `LICENSE` (only if absent — PA does not create one; else a `LICENSE.decomp-note.md`?) NO: -write `LICENSE` from the skeleton only when no LICENSE exists, otherwise STOP and ask; `src/NOTICE.md`, `README.md` (PA creates none — -create; if one exists, append under a marker), `CONTRIBUTING.md`, `.clang-format`, `make-format.snippet.mk` appended to `Makefile` -(create a minimal Makefile if absent); generation-time placeholders written as literal `TODO(phase-N)` lines; **Step 9** memory seed -(`memory-seed/*.md` → `.claude-state/memory/`, MEMORY.md rows APPENDED — PA's 16 + the kit's 16; the `upstream: PA` files included) + -"seeded memories activate from the NEXT session"; **Step 10** verify — the leftover-placeholder audit `grep -rn "{{" --include="*.md" ---include="*.txt" --include="*.json" --include="*.sh" --include="*.py" .` must hit ONLY `decomp-architect/` and `docs/decomp-architect.md`; -`tools/audit_public.py` OK; `bash -n tools/bootstrap.sh`; JSON parses; the registry recites G1–G65; the install MANIFEST (the file list) -printed and written to `.run/decomp-architect-install-manifest.txt`; append `decomp-architect/` to `.gitignore`; write -`phase-ends/PhaseEnd_Phase0.5.md` (PA's template + the narrative axis) and `git mv` the Phase-0.5 CURRENT_PHASE to -`phase-ends/logs/PhaseLog_0.5.md`; commit by explicit path (`chore: decomp-architect Phase 0.5 — the decomp overlay installed`); the -final message: the manifest, "you may delete decomp-architect/", "start a fresh session and say Begin Phase 1", the plain-English -recap; **🛑 HARD STOP**. **The honesty section** (near the top): the installer verifies documents, configuration and the firewall audit; -it does not install a byte gate, a splitter config, a permuter harness, a decompiler context or a differential harness — those are -`docs/tools-manifest.md`'s Phase-N tasks. **Verify (task 12):** `kit_lint` clean (SETUP.md is in the package — the lint runs over it: -no `§`+digit, no `R`+digits, no source-project literals; every `{{…}}` it names is in the 22-set); a structural read-through against -PA's SETUP.md (every PA mechanism has its counterpart: contract, verify lines, idempotence, explicit-path commits, the phase file, -the hard stop); every "Filled" column of PLACEHOLDERS.md names a step that exists. Log + checkpoint; commit by explicit path. -**Then the P6 rules check** (re-read CLAUDE.md's Mandatory Behavior + the fail-safes + DIGEST §3, state "Rules check — re-read -complete. Continuing with task 13"). Task 13 is xHigh — prompt Drew to drop back (R27). +### 2. What NEXT does (task 13, **xHigh**) — exact steps (plan D6) +**Read first:** the plan's D6 in the "Approved plan" section below (the guardrails are binding); `decomp-architect/SETUP.md` in full +(the thing under test — Step 2's answers-file contract, Step 10's manifest format); `decomp-architect/README.md` step 1 (the PA +install is handed the intake); `/mnt/z/Storage/git/ProjectArchitect/project-architect-2.0/SETUP.md` (PA's own steps the subagent +must drive: its Path question, its dev interview, its Mode-1 intake + Gate 1 review + Gate 2 effort prompt, its home-directory step, +its Phase-0 close); `docs/wave-playbook.md`'s S80 addendum-2 (per-agent work dirs; the final message is one JSON line). +**Do, in this order:** +1. **Record the BEFORE values** (R57 — the dry-run must not touch the real tree or the home directory): + `sha1sum ~/.claude/settings.json ~/.claude/statusline.sh`; `ls ~/.claude/projects/-home-musashi-bfm-decomp/memory | wc -l`; + `git -C ~/bfm-decomp status --porcelain | wc -l` (0); `ls ghidra | wc -l`; `ls dumps/*.bin | wc -l` (28). Save them to + `.run/P33.5/kit-dryrun/before.txt`. +2. **The fixture** under `.run/P33.5/kit-dryrun/` (create the dir): `answers.md` — the kit's 13 keys + `INSTALL_DATE: 2026-09-07` + (fictional title, a fictional serial in the platform's format, a `DUMP_PATH` that does not exist e.g. `/nonexistent/dryrun.bin` + — SETUP only asserts it is absolute and outside the repo, container/SDK-evidence strings, goals, a license choice, a disclosure + sentence, `PUBLIC_OR_PRIVATE: private until the contract run`) PLUS a section `## For ProjectArchitect's own installer` with PA's + answers (Path A; the dev interview: advanced / decompilation / autonomous, recommendation-first, breadth welcome; the Mode-1 + intake = "read decomp-architect/intake.decomp.md; the game values are above"; Gate 2: "effort Max is already set — proceed, log it + as a deviation"; **"skip PA's home-directory step entirely (no writes under ~/.claude)"**; PA's §E: the one-line pointer per the + intake's Part D); `expected-manifest.txt` — the `CREATED/APPENDED/SKIPPED` lines you expect from SETUP Step 10's format + (derive it from SETUP's install manifest section; sorted); a `.gitignore` block in the REPO's `.gitignore` under a dated comment: + `!/.run/P33.5/` `/.run/P33.5/*` `!/.run/P33.5/kit-dryrun/` `/.run/P33.5/kit-dryrun/*` `!/.run/P33.5/kit-dryrun/answers.md` + `!/.run/P33.5/kit-dryrun/expected-manifest.txt` `!/.run/P33.5/kit-dryrun/*.log` `!/.run/P33.5/kit-dryrun/*.txt` (the nested + `repo/` stays ignored). +3. **The throwaway repo:** `R=$HOME/bfm-decomp/.run/P33.5/kit-dryrun/repo` — `git -C ... init` a fresh dir; `cp -r + /mnt/z/Storage/git/ProjectArchitect/project-architect-2.0 "$R/"`; `cp -r ~/bfm-decomp/decomp-architect "$R/"` (the committed + kit); `git -C "$R" config user.name/user.email` (local). Re-runs: remove ONLY `"$R"` by its ABSOLUTE path (log it), recreate. +4. **ONE subagent** (general-purpose) with a brief that: gives `$R` as its working directory and forbids any write outside it and + any write under the home directory; requires every git call to be `git -C "$R" …`; forbids `git clean` and relative `rm -rf`; + says to run PA's `SETUP.md` first (as the installing agent, answering every question from `answers.md` — never wait for a + human; skip its home-directory step; hand its intake the kit's `intake.decomp.md`), then the kit's SETUP with `answers: `; writes deliverables EARLY into `.run/P33.5/kit-dryrun/`: `install.log` (its narration, appended as it goes), + `manifest.txt` (a copy of the produced install manifest), then `verdict.json` LAST and as its ONLY final message — one JSON line + `{"status": "PASS|FAIL", "pa_install": "...", "kit_steps_completed": N, "defects": [{"step": "...", "what": "...", "fix": "..."}]}`. + Model: the session default; budget: one attempt per run; if it dies, recover its verdict from the transcript by + `tools/agent_verdicts.py`. +5. **Judge the run yourself (R14):** `diff "$R"/../manifest.txt expected-manifest.txt`; the placeholder grep of SETUP Step 10.1 run + BY YOU in `$R`; the check-ignore probes in `$R`; `grep -c '^### G' "$R"/RULES_REGISTRY.md` = 65; `ls "$R"/.claude-state/memory/*.md + | grep -vc MEMORY.md` = 32; `git -C "$R" log --format=%B | grep -ci 'co-authored'` = 0; the two commits present; **the AFTER + values equal the BEFORE values** (re-run step 1's commands; any difference = the run wrote where it must not — a defect of the + brief or the kit, fixed before anything else). +6. **Fix defects in the KIT** (SETUP/templates — never in the throwaway), re-run from step 3 to green; each re-run appends to + `install.log`'s successor (`install.2.log`, …). Every kit fix re-runs `kit_lint`. +7. Log + checkpoint (the defects found and fixed, with the step that caught each; the run count; the final diff empty); commit by + explicit path: the kit fixes, `.gitignore`, `.run/P33.5/kit-dryrun/{answers.md,expected-manifest.txt,before.txt,after.txt,*.log, + manifest.txt}`, this file. **Cut line (D6):** if still red at the end of session 3 of the phase, ship + `decomp-architect/KNOWN-DEFECTS.md` naming exactly what did not, make the re-run the split phase's first task, and the PhaseEnd + says so (R66). Task 13.5 is xHigh — no effort prompt needed after this task. ### 3. Standing facts for every task of this phase - One commit per task, after this file's log line (R8/R42 form); commit by explicit path; no trailers (R5); Drew pushes (R6). @@ -624,12 +658,14 @@ complete. Continuing with task 13"). Task 13 is xHigh — prompt Drew to drop ba - Nothing moves while a wiki page / how-to chapter / `doc_links` DEFAULT document / tool docstring cites it — the referrer census command in the plan's D3 runs before every `git mv`. - `purge_set.txt` is never edited in this phase. Never `git clean -x`. The untracked 29 GB of `.run/` is out of scope. -- Effort transitions are prompted and waited for (R27): Max for tasks 12 and 15; xHigh otherwise. +- Effort transitions are prompted and waited for (R27): Max for task 15; xHigh otherwise (13, 13.5, 14). - The kit's vocabulary (task 10): rules by G-id, kernels by DK-id, PA's sections as "step N", the kit's SETUP as "Step N"; source numbers only in ```` ```calibration ```` fences; the placeholder set is `PLACEHOLDERS.md`'s 22 and nothing else (`kit_lint` enforces). - **`make tools-health` runs longer than the 10-minute foreground cap:** launch it detached (`setsid nohup make tools-health > .run/P33.5/ 2>&1 < /dev/null &`), then wait on the pid from a background Bash (`while kill -0 ; do sleep 10; done`); never as a harness background task (the memory guard killed one in S88), never sleep-poll in the foreground. +- The wiki fence and `templates/gitignore.decomp` are ONE source in two copies: edit the page, re-extract the template by script, + `gitignore_template_check` must read OK (75 lines since task 12). ---