docs+kit(phase-33.5): task 14 — the S91-b types hindsight implemented in the kit + the wiki page Start-a-new-decomp-project.md + the rows

- kit: DK-65 "types are a banking lever and a width lever, not a byte lever" (kernel, when, cost, calibration fence, provenance;
  the kernels file now states its own total "In all: DK-1 … DK-65" and SETUP Step 6 compares grep -c against it instead of a typed
  64); intake row 6's milestone gains the canonical type layer (one definition per shape, widths proven by the bytes at bank time,
  a bank refused for a duplicate definition or a raw address cast) + the type tools moved forward + G62/DK-65 in its columns; row 10
  reads "short if Part C and Phase 6's type layer held"; G62 extended with the bank-time clause (G1–G67 kept); tool_dictionary:
  lift_types + canon_sig_reconcile P10 → P6 and the five type tools' need-keys name the type layer at Phase 6 (the phase column is
  one token — the corpus dir derives from it); the cookbook front page's type-verdict sentence (a NAME never moves a byte, a WIDTH
  or SIGNEDNESS is the one place a type does, the permuter cannot reach it); the methodology's "Types — the two-sided verdict"
  paragraph; the kit README's table + tree now name the two dictionaries and layout-contract.md; make kit-corpus regenerated the
  tool index, the MANIFEST and the corpora (302 copies + 28 pointers)
- wiki: docs/wiki/Start-a-new-decomp-project.md — the three steps, what it installs / does not (the two dictionaries), the ladder
  (11 rows), the five AI-use rules, the six inversions (raw casts → declared symbols; DK-65), the compiler question, the accelerators
  one line each (58 rows), the four dry-runs, how it is kept honest; sidebar + Home rows; Tools-from-this-project rows for the kit
  and the tool index; README bullets for both; SETUP row for decomp-architect/ (R21); Where-the-project-goes-next links the page and
  records the probe PASS (2026-09-07); phase34-seed: task 0 PASSED, the kit carried whole through the flip and split later
- verify: wiki_render --selftest 12/12 + reachability 32 pages / 0 unlisted; doc_links --strict 58 documents / 451 links / 0 pending /
  0 broken / coverage 65 of 65 (one BROKEN on the first draft — a foreign project's docs/ path cited in backticks — reworded);
  kit_lint OK (leak 0 / placeholders 22 == 22 / syntax 0 / gitignore 75 identical); tool_census --check OK; 65 DK ids cited, 0
  dangling; audit_public OK on the touched files; no build input changed
- log + checkpoint (NEXT = task 15, Max, Tier 1 — prompt Drew and wait for gate 2)
This commit is contained in:
Drew T
2026-09-07 22:40:17 -06:00
parent 3c4e185feb
commit 9937fd7e39
22 changed files with 464 additions and 108 deletions
+7
View File
@@ -140,6 +140,13 @@ Things built here that stand on their own, for other decompilation projects:
- [**The drafter write-up**](docs/matching-drafter-pipeline.md) — how a small local model was fine-tuned to draft matches
under the byte gate, every measurement in order, and what it was worth.
- [**How to AI-decomp**](docs/how-to-ai-decomp/00-README.md) — the whole method, for anyone doing this with an agent.
- [**The day-one decomp kit**](decomp-architect/README.md) (`decomp-architect/`) — what this project would hand its own day one,
as a Phase-0.5 overlay on ProjectArchitect 2.0: the order of work, the ROM firewall from commit one, the rules distilled from the
failures, the conduct rules, readability at draft time — and two dictionaries: the tools verbatim, keyed by the need each answers,
and the cookbook with its index and the codegen map behind a page that says what transfers to another compiler. Installed four
times in a throwaway under a judge script ([wiki](docs/wiki/Start-a-new-decomp-project.md)); split out after the flip.
- [**The tool index**](docs/tool-index.md) — every tool in the tree keyed by the need it answers, with what proved it and what it
hard-codes; generated by `tools/tool_census.py` from the tree and an authored dictionary, coverage asserted both ways.
## License
+5 -5
View File
@@ -50,7 +50,7 @@ tools/burndown.py P5 ADAPT track per-session yield and velocity so a diminishing
tools/campaign_status.py P8 ADAPT report every concurrent lane with its own metrics, not only the loud one One status view covering every lane, not only the loud one lane names, repo scratch paths STILL-NEEDED report every concurrent lane with its own metrics, not only the loud one
tools/canon_draft_decls.py P6 ADAPT canonicalize a draft's extern and data declarations to the banked-consistent set Canonicalizes a draft's extern and data declarations to the banked-consistent set repo shared-header paths SUPERSEDED tools/sig_unify.py
tools/canon_resident_calls.py P6 ADAPT rewrite address-named calls in a draft to their curated symbol names Rewrites address-named calls in a draft to the curated symbol name when one exists repo symbol file path LIVE
tools/canon_sig_reconcile.py P10 ADAPT reconcile a definition's typed signature with what its destination unit declares Reconciles a definition's typed signature with what its destination unit already declares repo src layout LIVE
tools/canon_sig_reconcile.py P6 ADAPT reconcile a definition's typed signature with what its destination unit declares — part of banking against a canonical type layer from Phase 6; again at readability (Phase 10) Reconciles a definition's typed signature with what its destination unit already declares repo src layout LIVE
tools/cast_call_sites.py P10 ADAPT add per-site function-pointer casts so a draft can call a differently typed callee Adds per-site function-pointer casts so a draft can call a differently typed callee repo src layout LIVE
tools/cast_self_callers.py P6 ADAPT let a unit keep calling, through per-site casts, the function it now defines Lets a unit keep calling, through a per-site cast, the function it is about to define repo src layout LIVE
tools/cc1_dumps.sh P4 ADAPT dump every compiler pass file for a self-contained draft Dumps every compiler pass file for a self-contained draft into a private directory compiler triple, repo scratch paths LIVE
@@ -59,11 +59,11 @@ tools/cdecl.py P6 PORTABLE parse C declarators once, for every declaration tool
tools/cdtrace.py PROJECT-ONLY PROJECT-ONLY observe a live loader's requests to learn which payload loads where Reads one game's loader request structures at fixed RAM addresses project-only STILL-NEEDED observe a live loader's requests to learn which payload is read to which address
tools/claude_wave_packs.py P8 ADAPT build the per-function prompt packs a drafting agent wave works from Builds the per-function prompt packs an agent wave drafts from repo scratch paths, agent harness LIVE
tools/compile_only.py P9 ADAPT compile every eligible translation unit with the pinned toolchain, using no derived bytes Compiles every eligible translation unit with the pinned toolchain, without any game bytes compiler triple, repo makefile parsing LIVE
tools/conform_decls.py P6 ADAPT conform every declaration of a function fleet-wide to its byte-true definition Conforms every declaration of a function fleet-wide to its byte-true definition repo src/shared-header layout LIVE
tools/conform_decls.py P6 ADAPT conform every declaration of a function fleet-wide to its byte-true definition — width and signedness proven by the bytes at bank time (Phase 6) Conforms every declaration of a function fleet-wide to its byte-true definition repo src/shared-header layout LIVE
tools/cookbook_index.py P9 ADAPT generate a symptom-keyed index of a large technique document Generates a symptom-keyed index of the large technique document repo doc paths LIVE
tools/corpus.py P5 ADAPT answer from one derived model whether each function is open, matched or shared The single derived model of the source tree: open, matched or shared, per function repo src/config layout LIVE
tools/decl_from_use.py P6 ADAPT infer a minimal extern for a data symbol the destination unit does not declare Infers a minimal extern for a data symbol a draft uses but its destination does not declare repo src layout LIVE
tools/decl_prior.py P6 ADAPT compute the fleet's consensus declaration for every symbol, as card fuel Computes the fleet's consensus declaration for every symbol, as card fuel repo src layout LIVE
tools/decl_prior.py P6 ADAPT compute the fleet's consensus declaration for every symbol, as card fuel — the seed of a canonical type layer (Phase 6) Computes the fleet's consensus declaration for every symbol, as card fuel repo src layout LIVE
tools/decompile.py P4 ADAPT turn one function's disassembly into a C scaffold to start a match Wrapper locating a function's disassembly and running the C-scaffold generator on it repo asm paths, decompiler target name STILL-NEEDED turn one function's disassembly into a C scaffold to start a match
tools/decompme_replica.sh P4 ADAPT reproduce an external reference toolchain locally and compare its words to target Runs a function through an external reference toolchain build and compares words against the target pinned toolchain versions, network fetch STILL-NEEDED kept: a public preset request needs the replica of the community toolchain to prove equivalence
tools/dedup_extend.py P6 ADAPT extend an existing code-share registry to newly onboarded binaries Extends the existing share registry to newly onboarded binaries repo config/src layout LIVE
@@ -180,7 +180,7 @@ tools/launch_check.py P8 ADAPT refuse to launch an agent at a target that is alr
tools/ld_interleave.py P3 ADAPT reorder a generated linker script to reproduce the original section interleaving Reorders a generated linker script to reproduce the original section interleaving repo build paths LIVE
tools/len_tells.py P7 ADAPT classify a length-drift near-miss against its own target and build its routing card Classifies a length-drift near-miss against its own target and builds the routing card repo scratch paths LIVE
tools/lenmiss_route.py P7 ADAPT route a length-drift near-miss pile through the documented lenses, re-verified Routes the length-drift near-miss pile through the documented lenses, re-verified against the tree repo scratch paths ONE-OFF the routed outcome of one length-drift near-miss pile (it consumes that audit's classified ledger)
tools/lift_types.py P10 ADAPT lift a named list of types fleet-wide into the shared type header Lifts a named list of types fleet-wide into the shared type header repo shared-header path LIVE
tools/lift_types.py P6 ADAPT lift a named list of types fleet-wide into the shared type header — the canonical type layer from the first bank (Phase 6, the multiplier); again at readability (Phase 10) Lifts a named list of types fleet-wide into the shared type header repo shared-header path LIVE
tools/lint_symbol_refs.py P10 ADAPT flag address-named references whose address now has a curated name Flags address-named references in committed sources whose address now has a curated name repo symbol/src paths LIVE
tools/lora_grind.py P8 ADAPT rotate binaries drafting small stubs with a served model, gating and propagating Mass-run driver rotating binaries, drafting small stubs with a served model, gating, propagating repo scratch paths, model endpoint LIVE
tools/macro_draft.py P6 ADAPT materialize a shared macro body back into a compilable standalone draft Materializes a shared macro body back into a compilable standalone draft repo shared-header layout STILL-NEEDED materialize a shared macro body back into a compilable standalone draft
@@ -283,7 +283,7 @@ tools/stub_invariant_audit.py P5 ADAPT negative-control the comparer: every stub
tools/sweep_citations.py P7 ADAPT localize every compiler-source citation in a document against the pinned sources Deterministically localizes every compiler-source citation in a document against the pinned sources repo reference tree paths SUPERSEDED tools/gccmap_cites.py
tools/sweep_parallel.py P8 ADAPT gate pre-staged draft directories across distinct binaries in parallel Gates pre-staged draft directories across distinct binaries in parallel repo scratch paths LIVE
tools/symcheck.py P5 ADAPT diff the symbol set a draft references against the target's, before gating Pre-gate guard diffing the symbol set a draft references against the target's repo build paths SUPERSEDED tools/reloc_verify.py
tools/sync_tu_decls.py P6 ADAPT bank a refused draft by copying the destination unit's own declarations into it Banks a refused draft by copying the destination unit's own declarations into it repo src layout LIVE
tools/sync_tu_decls.py P6 ADAPT bank a refused draft by copying the destination unit's own declarations into it — the declaration-conflict class a canonical type layer prevents (Phase 6) Banks a refused draft by copying the destination unit's own declarations into it repo src layout LIVE
tools/t5_bank.sh P8 ADAPT judge each arm of a wave and bank the union, refusing if unsafe Post-draft half of an agent wave: refuse if unsafe, judge each arm, bank the union repo paths, lane conventions SUPERSEDED tools/gate_wave.py
tools/t5_cards.py P8 ADAPT build the card fuel for one wave's own targets, keyed per binary Builds the card fuel for one wave's own targets, keyed correctly per binary repo scratch paths LIVE
tools/t5_distill_args.py P8 ADAPT build the post-wave distillation slate from a wave's directories Builds the post-wave distillation slate from a wave's directories repo scratch paths SUPERSEDED tools/distill_scan.py
1 path phase portability need what adapts status successor_or_product
50 tools/campaign_status.py P8 ADAPT report every concurrent lane with its own metrics, not only the loud one One status view covering every lane, not only the loud one lane names, repo scratch paths STILL-NEEDED report every concurrent lane with its own metrics, not only the loud one
51 tools/canon_draft_decls.py P6 ADAPT canonicalize a draft's extern and data declarations to the banked-consistent set Canonicalizes a draft's extern and data declarations to the banked-consistent set repo shared-header paths SUPERSEDED tools/sig_unify.py
52 tools/canon_resident_calls.py P6 ADAPT rewrite address-named calls in a draft to their curated symbol names Rewrites address-named calls in a draft to the curated symbol name when one exists repo symbol file path LIVE
53 tools/canon_sig_reconcile.py P10 P6 ADAPT reconcile a definition's typed signature with what its destination unit declares reconcile a definition's typed signature with what its destination unit declares — part of banking against a canonical type layer from Phase 6; again at readability (Phase 10) Reconciles a definition's typed signature with what its destination unit already declares repo src layout LIVE
54 tools/cast_call_sites.py P10 ADAPT add per-site function-pointer casts so a draft can call a differently typed callee Adds per-site function-pointer casts so a draft can call a differently typed callee repo src layout LIVE
55 tools/cast_self_callers.py P6 ADAPT let a unit keep calling, through per-site casts, the function it now defines Lets a unit keep calling, through a per-site cast, the function it is about to define repo src layout LIVE
56 tools/cc1_dumps.sh P4 ADAPT dump every compiler pass file for a self-contained draft Dumps every compiler pass file for a self-contained draft into a private directory compiler triple, repo scratch paths LIVE
59 tools/cdtrace.py PROJECT-ONLY PROJECT-ONLY observe a live loader's requests to learn which payload loads where Reads one game's loader request structures at fixed RAM addresses project-only STILL-NEEDED observe a live loader's requests to learn which payload is read to which address
60 tools/claude_wave_packs.py P8 ADAPT build the per-function prompt packs a drafting agent wave works from Builds the per-function prompt packs an agent wave drafts from repo scratch paths, agent harness LIVE
61 tools/compile_only.py P9 ADAPT compile every eligible translation unit with the pinned toolchain, using no derived bytes Compiles every eligible translation unit with the pinned toolchain, without any game bytes compiler triple, repo makefile parsing LIVE
62 tools/conform_decls.py P6 ADAPT conform every declaration of a function fleet-wide to its byte-true definition conform every declaration of a function fleet-wide to its byte-true definition — width and signedness proven by the bytes at bank time (Phase 6) Conforms every declaration of a function fleet-wide to its byte-true definition repo src/shared-header layout LIVE
63 tools/cookbook_index.py P9 ADAPT generate a symptom-keyed index of a large technique document Generates a symptom-keyed index of the large technique document repo doc paths LIVE
64 tools/corpus.py P5 ADAPT answer from one derived model whether each function is open, matched or shared The single derived model of the source tree: open, matched or shared, per function repo src/config layout LIVE
65 tools/decl_from_use.py P6 ADAPT infer a minimal extern for a data symbol the destination unit does not declare Infers a minimal extern for a data symbol a draft uses but its destination does not declare repo src layout LIVE
66 tools/decl_prior.py P6 ADAPT compute the fleet's consensus declaration for every symbol, as card fuel compute the fleet's consensus declaration for every symbol, as card fuel — the seed of a canonical type layer (Phase 6) Computes the fleet's consensus declaration for every symbol, as card fuel repo src layout LIVE
67 tools/decompile.py P4 ADAPT turn one function's disassembly into a C scaffold to start a match Wrapper locating a function's disassembly and running the C-scaffold generator on it repo asm paths, decompiler target name STILL-NEEDED turn one function's disassembly into a C scaffold to start a match
68 tools/decompme_replica.sh P4 ADAPT reproduce an external reference toolchain locally and compare its words to target Runs a function through an external reference toolchain build and compares words against the target pinned toolchain versions, network fetch STILL-NEEDED kept: a public preset request needs the replica of the community toolchain to prove equivalence
69 tools/dedup_extend.py P6 ADAPT extend an existing code-share registry to newly onboarded binaries Extends the existing share registry to newly onboarded binaries repo config/src layout LIVE
180 tools/ld_interleave.py P3 ADAPT reorder a generated linker script to reproduce the original section interleaving Reorders a generated linker script to reproduce the original section interleaving repo build paths LIVE
181 tools/len_tells.py P7 ADAPT classify a length-drift near-miss against its own target and build its routing card Classifies a length-drift near-miss against its own target and builds the routing card repo scratch paths LIVE
182 tools/lenmiss_route.py P7 ADAPT route a length-drift near-miss pile through the documented lenses, re-verified Routes the length-drift near-miss pile through the documented lenses, re-verified against the tree repo scratch paths ONE-OFF the routed outcome of one length-drift near-miss pile (it consumes that audit's classified ledger)
183 tools/lift_types.py P10 P6 ADAPT lift a named list of types fleet-wide into the shared type header lift a named list of types fleet-wide into the shared type header — the canonical type layer from the first bank (Phase 6, the multiplier); again at readability (Phase 10) Lifts a named list of types fleet-wide into the shared type header repo shared-header path LIVE
184 tools/lint_symbol_refs.py P10 ADAPT flag address-named references whose address now has a curated name Flags address-named references in committed sources whose address now has a curated name repo symbol/src paths LIVE
185 tools/lora_grind.py P8 ADAPT rotate binaries drafting small stubs with a served model, gating and propagating Mass-run driver rotating binaries, drafting small stubs with a served model, gating, propagating repo scratch paths, model endpoint LIVE
186 tools/macro_draft.py P6 ADAPT materialize a shared macro body back into a compilable standalone draft Materializes a shared macro body back into a compilable standalone draft repo shared-header layout STILL-NEEDED materialize a shared macro body back into a compilable standalone draft
283 tools/sweep_citations.py P7 ADAPT localize every compiler-source citation in a document against the pinned sources Deterministically localizes every compiler-source citation in a document against the pinned sources repo reference tree paths SUPERSEDED tools/gccmap_cites.py
284 tools/sweep_parallel.py P8 ADAPT gate pre-staged draft directories across distinct binaries in parallel Gates pre-staged draft directories across distinct binaries in parallel repo scratch paths LIVE
285 tools/symcheck.py P5 ADAPT diff the symbol set a draft references against the target's, before gating Pre-gate guard diffing the symbol set a draft references against the target's repo build paths SUPERSEDED tools/reloc_verify.py
286 tools/sync_tu_decls.py P6 ADAPT bank a refused draft by copying the destination unit's own declarations into it bank a refused draft by copying the destination unit's own declarations into it — the declaration-conflict class a canonical type layer prevents (Phase 6) Banks a refused draft by copying the destination unit's own declarations into it repo src layout LIVE
287 tools/t5_bank.sh P8 ADAPT judge each arm of a wave and bank the union, refusing if unsafe Post-draft half of an agent wave: refuse if unsafe, judge each arm, bank the union repo paths, lane conventions SUPERSEDED tools/gate_wave.py
288 tools/t5_cards.py P8 ADAPT build the card fuel for one wave's own targets, keyed per binary Builds the card fuel for one wave's own targets, keyed correctly per binary repo scratch paths LIVE
289 tools/t5_distill_args.py P8 ADAPT build the post-wave distillation slate from a wave's directories Builds the post-wave distillation slate from a wave's directories repo scratch paths SUPERSEDED tools/distill_scan.py
+6 -2
View File
@@ -71,7 +71,8 @@ session and say `Begin Phase 1`.
| **The firewall pack** (`templates/gitignore.decomp`, the audit template and its config, a planted fixture, the CI workflow) | no game-derived bytes in git from commit one; an audit that derives its forbidden set, asserts its coverage and fails on the fixture before it is trusted; CI on every push |
| **The layout and its READMEs** (`docs/`, `.run/`, the ops-setup overlay) | where each kind of knowledge goes; scratch under the repository with dated tracked exceptions; the ops reference a fresh machine rebuilds from |
| **The overlays** (`templates/pa-overlays.md`, `templates/CLAUDE.decomp-overlay.md`) | marked-section appends to `CLAUDE.md` (the decomp fail-safes and session-start extras), the effort map (Max on the plan, the PhaseEnd, the compiler pin, the segmentation decision, any wall verdict), the cookbook (the idiom entry shape, the triage table), ops-setup; the digest, the replayable checkpoint block and the PhaseEnd narrative axis |
| **The corpus** (`corpus/decomp-kernels.md`) | DK-1 … DK-64 — what the source project learned late, each with when it applies and what it cost, and the failure museum |
| **The corpus** (`corpus/decomp-kernels.md`) | DK-1 … DK-65 — what the source project learned late, each with when it applies and what it cost, and the failure museum |
| **The two dictionaries** (`corpus/tools/`, `corpus/cookbook/`) | the source project's tools, verbatim, by ladder phase, behind an index keyed by the NEED each answers (what it does, what proved it, what to adapt); and its knowledge base — the cookbook, its symptom index and the codegen map — verbatim, behind a front page that says what transfers to another compiler. Both are regenerated from the source project and asserted equal to it; a new project installs the index and the front page and keeps the folder as its reference shelf |
| **The memory seed** (`memory-seed/`) | working agreements and harness facts learned on the source project, appended to the memory ProjectArchitect configured |
| **The skeletons** | LICENSE, `src/NOTICE.md`, README, CONTRIBUTING (with the AI-conduct section), `.clang-format` and a `make format` snippet |
| **The tools manifest** (`tools/MANIFEST.md`) | the portable tools of the source project by phase — what each does and what it hard-codes — as Phase-1 tasks (see below) |
@@ -124,8 +125,11 @@ decomp-architect/
decomp-architect.md the methodology reference (copied to docs/)
templates/ the firewall pack, the READMEs, the overlays, the registry seed, the skeletons, PLACEHOLDERS.md
corpus/decomp-kernels.md the kernels and the failure museum
corpus/tools/<phase>/ the source project's tools, verbatim, with INDEX.md (the need-keyed dictionary)
corpus/cookbook/ the source project's cookbook, symptom index and codegen map, verbatim, with a front page
memory-seed/ the memory files and their index rows
tools/MANIFEST.md the portable tools by phase, as tasks
templates/layout-contract.md a draft of the layout assumptions the portable tools share (for the split)
tools/MANIFEST.md the portable tools by phase, as tasks and as a dictionary
```
## License
+1 -1
View File
@@ -167,7 +167,7 @@ FAILS (the README is trackable).
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; the manifest's row count equals the total its own header states (`grep -c '^| \`'
docs/decomp-kernels.md` equals the "In all" figure of that file's own Coverage section (both derived, never typed here); the manifest's row count equals the total its own header states (`grep -c '^| \`'
docs/tools-manifest.md` == the "Table rows in all: N" figure in its Coverage line — the live rows plus the superseded pointer
rows, both derived, never typed here); `docs/knowledge-corpus.md` exists.
+5 -2
View File
@@ -26,8 +26,11 @@ re-deriving it. Read this page first; it says what transfers.
- **In both cases** the compiler-agnostic parts apply unchanged and are also distilled elsewhere in the kit: the integration
classes (a byte-correct body that will not bank because of its file), the instrument findings (a tool that reports a true
number about a narrower world), the harvest laws (one credited lever in three is inert — strip and recompile before it enters
the base), the verbatim class (pasted assembly is not C), and the segmentation law (translation-unit boundaries at the build's
forced boundaries).
the base), the verbatim class (pasted assembly is not C), the segmentation law (translation-unit boundaries at the build's
forced boundaries), and the type verdict: a type NAME never moves a byte, but a WIDTH or SIGNEDNESS is the one place a type
does — a halfword load's sign, a pointer arithmetic scale, a narrower accumulator that stops a value being re-read — and the
permuter cannot change a type, so a width near-miss is fixed at the declaration (proven by the bytes at bank time), never by a
dial.
## The vocabulary you will meet
+31 -1
View File
@@ -800,6 +800,35 @@ data symbols; 3,558 of 4,287 C files carve splits; no formatter configuration; a
```
provenance: BFM gen3-standards (2026-09-07) + gen3-handoff §2.2; the sotn-decomp style guide read as data
### DK-65 — Types are a banking lever and a width lever, not a byte lever
- **Kernel:** a type name never moves a byte — the compiler does not care what a field is called — and the source
project measured exactly that early, correctly, and then drew the wrong second conclusion: that types could wait until
after 100%. Read the other way, its record says types are the largest *banking* lever it underweighted. Banking, not
cracking, was the bottleneck, and a large share of gate failures were declaration conflicts — a signed halfword against
an unsigned one, one arity against another, a structure a drafting agent invented in isolation because there was no
registry to draft against — so the tree filled with variants of a few shapes and a whole reconcile ladder was built to
repair what a canonical type file would have prevented. And the one place a type *does* touch bytes is width and
signedness: a halfword load's sign, a pointer arithmetic scale, a narrower accumulator that stops a value being re-read;
the permuter cannot change a type, so every width near-miss was dial work until the declaration was right. The
achievable early form is a discipline, not a census: **a canonical type file from the first bank that grows one proven
field at a time, the width and signedness fixed by the bytes at bank time, with no draft allowed to bank a duplicate
definition of an existing shape or a raw address cast, and names only with evidence.** It costs one duplicate-definition
and raw-cast check per bank; it removes most of the declaration-conflict class before a ladder is needed, lowers the
width class of near-misses on the first pass, and leaves nothing to unify after 100%. It would not have shortened one
compiler-pass crack — do not expect it to.
- **When it applies:** from the first bank (Phase 6, the multipliers) — the type layer is part of what makes drafts bank;
Phase 10 is short when it held.
- **Cost:** a reconcile ladder built reactively; a generation's struct unification and raw-cast removal after 100%.
```calibration
source project: rich decompiler context (the recovered actor structure + the jump tables) scored 0 better / 10 same /
2 worse on a 12-function structural-miss sample, identical bytes (phase 17) — right for cracking; ≈92% of drafts
byte-correct and ≈27% banked at one measurement, declaration conflicts a large share of the gap; 1,232 struct
definitions in the tree at 100%, most of them variants of a few shapes; 143 raw address casts; the width class
(a u16 accumulator as a CSE firewall, an object-table symbol declared u8, the scaffold's ×4 pointer arithmetic) in
the last hand cracks (phase 32).
```
provenance: BFM decision-log "P33.5 S91-b" (the hindsight on types, 2026-09-07); struct-core-pivot.md (2026-06-19); cookbook §501-N/§501-R
---
## 8. The failure museum, condensed — what looked right at the time
@@ -862,7 +891,8 @@ reading, the denominator on every number, and a decision log that records each o
- **Compiler walls:** DK-44 … DK-52 — 9 kernels.
- **The repository and publishing:** DK-53 … DK-58 — 6 kernels.
- **Governance and sessions:** DK-59 … DK-63 — 5 kernels.
- **Readability at day one:** DK-64 — 1 kernel.
- **Readability at day one:** DK-64 … DK-65 — 2 kernels.
- **In all:** DK-1 … DK-65 — 65 kernels (the installer's check compares `grep -c '^### DK-'` against this figure).
- **The failure museum:** 37 exhibits, condensed.
- Conduct rules are not duplicated here; they are the registry seed's E.7 group. The generic engineering kernels of
ProjectArchitect's own corpus apply unchanged and are not repeated.
+6 -6
View File
@@ -9,7 +9,7 @@
> their code does not transfer). *TODO(platform): the MIPS and PlayStation SDK hard-codes are the ones another platform replaces first.*
>
> **Coverage:** 293 tool files in scope (submodules, vendored and downloaded code excluded), of which 293 live rows
> below; per phase: P1 2 · P2 26 · P3 17 · P4 9 · P5 27 · P6 52 · P7 20 · P8 86 · P9 26 · P10 12 · PROJECT-ONLY 16. Superseded tools appear only as pointers to their successor (28 pointer rows); one-offs are omitted. Table rows in all: 321 (the installer checks its copy against this figure).
> below; per phase: P1 2 · P2 26 · P3 17 · P4 9 · P5 27 · P6 54 · P7 20 · P8 86 · P9 26 · P10 10 · PROJECT-ONLY 16. Superseded tools appear only as pointers to their successor (28 pointer rows); one-offs are omitted. Table rows in all: 321 (the installer checks its copy against this figure).
## P1 — extraction + manifest
@@ -125,15 +125,15 @@
| `weave_sweep.py` | apply one proven codegen lever everywhere the bytes say it belongs | Applies one known prologue-scheduling lever everywhere the bytes say it belongs | repo src layout, compiler behaviour |
| `interleave_check.py` | assert a read-only-data carve's interleave order equals the segment sequence | Asserts the carve interleave order equals the segment sequence, position by position | repo config layout |
| `jtbl_family_bank.py` | bank a matched jump-table exemplar across its siblings, reverting on failure | Banks a matched jump-table exemplar across its structural siblings, revert-on-fail | repo config/src layout |
| `sync_tu_decls.py` | bank a refused draft by copying the destination unit's own declarations into it | Banks a refused draft by copying the destination unit's own declarations into it | repo src layout |
| `sync_tu_decls.py` | bank a refused draft by copying the destination unit's own declarations into it — the declaration-conflict class a canonical type layer prevents (Phase 6) | Banks a refused draft by copying the destination unit's own declarations into it | repo src layout |
| `twin_sweep.py` | bank every open stub that already has a banked structural twin | Banks every open stub that has an already-banked structural twin, for near-zero tokens | repo signature files |
| `fix_decl_mirror.py` | bind a void definition to a symbol the destination declares as returning a value | Binds a void definition to its symbol when the destination declares a value return | repo src layout |
| `family_align.py` | classify drifted structural siblings by aligned words and expand their constants | Length-tolerant aligned classifier plus the mechanical constant-expansion engine for drifted members | repo scratch paths |
| `exclude_audit.py` | classify every exclude-list entry by its current blocker and regenerate the list | Classifies every exclude-list entry by its current blocker and regenerates the list | repo config path |
| `family_cousins.py` | cluster the open frontier one tier looser than exact skeleton hashing | Similarity clustering one tier looser than exact skeleton hashing over the open frontier | repo signature files |
| `decl_prior.py` | compute the fleet's consensus declaration for every symbol, as card fuel | Computes the fleet's consensus declaration for every symbol, as card fuel | repo src layout |
| `decl_prior.py` | compute the fleet's consensus declaration for every symbol, as card fuel — the seed of a canonical type layer (Phase 6) | Computes the fleet's consensus declaration for every symbol, as card fuel | repo src layout |
| `reconcile_tu.py` | conform a draft's data declarations to what its destination unit can see | Conforms a draft's data declarations to what the destination translation unit can actually see | repo src layout |
| `conform_decls.py` | conform every declaration of a function fleet-wide to its byte-true definition | Conforms every declaration of a function fleet-wide to its byte-true definition | repo src/shared-header layout |
| `conform_decls.py` | conform every declaration of a function fleet-wide to its byte-true definition — width and signedness proven by the bytes at bank time (Phase 6) | Conforms every declaration of a function fleet-wide to its byte-true definition | repo src/shared-header layout |
| `scope_demote_drafts.py` | demote declaration scope as one rung of the recovery ladder | The scope-demote step, wired as a rung of the recovery ladder | repo src layout |
| `pads_audit.py` | derive an object's inter-table padding spec from the bytes instead of searching | Derives each object's padding spec from the bytes instead of searching for it | repo build/config layout |
| `aprop_autodraft.py` | draft a family member mechanically from a seed body and symbol rebase | Mechanically drafts a family member from the seed body plus a positional symbol rebase | repo scratch paths |
@@ -145,6 +145,7 @@
| `jr_isolate_all.py` | isolate every switch function in a binary in one multi-cut resegment | One-shot multi-cut resegment isolating every switch function in a binary | repo config/src layout |
| `match_protos.py` | join two related builds' signature dumps into a function correspondence | Joins per-function signature dumps of two related builds into a function correspondence | repo signature files |
| `cast_self_callers.py` | let a unit keep calling, through per-site casts, the function it now defines | Lets a unit keep calling, through a per-site cast, the function it is about to define | repo src layout |
| `lift_types.py` | lift a named list of types fleet-wide into the shared type header — the canonical type layer from the first bank (Phase 6, the multiplier); again at readability (Phase 10) | Lifts a named list of types fleet-wide into the shared type header | repo shared-header path |
| `dedup_propagate.py` | lift one matched body into a shared macro and instantiate it everywhere | Lifts one matched body into a shared macro and instantiates it at every duplicate site | repo shared-header/src layout |
| `macro_draft.py` | materialize a shared macro body back into a compilable standalone draft | Materializes a shared macro body back into a compilable standalone draft | repo shared-header layout |
| `scope_tu_externs.py` | move a unit's file-scope data externs down into their consumers | Moves a unit's own file-scope data externs down into their consumers to legalize a block-scope type | repo src layout |
@@ -156,6 +157,7 @@
| `xsig/tests/test_xsig.py` | property-test the signature tool on committed fixtures, needing no compiler | Property tests for the signature tool on committed fixtures, needing no compiler | fixture paths |
| `family_hseq.py` | rank clusters of the unmatched frontier by mnemonic-skeleton hash | Ranked clustering of the unmatched frontier by mnemonic-skeleton hash | repo signature files |
| `aprop_symfix.py` | rebase a remapped draft's stale seed symbols onto the target's own | Rebases stale seed symbols in a mechanically adapted draft onto the target's own symbols | repo symbol/config sources |
| `canon_sig_reconcile.py` | reconcile a definition's typed signature with what its destination unit declares — part of banking against a canonical type layer from Phase 6; again at readability (Phase 10) | Reconciles a definition's typed signature with what its destination unit already declares | repo src layout |
| `xsig/tests/make_fixtures.sh` | regenerate the signature tool's fixtures with the pinned toolchain | Regenerates the signature-tool fixtures with the pinned toolchain | compiler triple, repo tool paths |
| `family_remap.py` | remap a matched exemplar's source onto a structural sibling by positional symbol pairing | Mechanically remaps a matched exemplar's C onto a structural sibling by positional symbol pairing | repo src layout |
| `fix_arity_callers.py` | repair a shared caller's argument-count conflict for the no-prototype failure class | Repairs the shared-caller argument-count conflict for the no-prototype failure class | repo shared-header layout |
@@ -332,9 +334,7 @@
| `lint_symbol_refs.py` | flag address-named references whose address now has a curated name | Flags address-named references in committed sources whose address now has a curated name | repo symbol/src paths |
| `uniquify_type.py` | give each conflicting camp of a same-named type its own name | Gives each conflicting camp of a same-named type its own name so every camp becomes liftable | repo src layout |
| `verbatim_check.py` | guard that every inline-assembly body still reproduces its target bytes | Regression guard that every inline-assembly body still reproduces its target bytes | repo src layout |
| `lift_types.py` | lift a named list of types fleet-wide into the shared type header | Lifts a named list of types fleet-wide into the shared type header | repo shared-header path |
| `ghidra_apply_symbols.sh` | mirror the curated symbol file into the analysis database with a real save | Mirrors the curated symbol file into the analysis program headlessly, with a real save | repo symbol path, project name |
| `canon_sig_reconcile.py` | reconcile a definition's typed signature with what its destination unit declares | Reconciles a definition's typed signature with what its destination unit already declares | repo src layout |
| `verbatim_target_s.py` | regenerate a splitter-format target disassembly for a function no longer stubbed | Regenerates a splitter-format target disassembly for a function that is no longer a stub | repo build/asm layout |
| `verbatim_to_stub.py` | turn an inline-assembly body back into a stub the toolchain can reach | Turns an inline-assembly body back into an include-assembly stub | repo src/asm layout |
+13 -2
View File
@@ -214,10 +214,21 @@ pass-throughs as remaps with an edit. A gate verifies one binary and propagation
follows every propagating gate; carve state belongs to its binary (G43); a newly discovered binary is not real until every
consumer knows it (G7).
**Types — the two-sided verdict.** As a codegen lever, types are inert: the source project measured rich structure context
against a structural-miss sample early and got identical bytes, and every wall after that was a compiler pass — so a type is
never the reason a body will not match. As a banking lever they are the largest one it underweighted: agents drafting in
isolation invent their types, so gate failures arrive as declaration conflicts and the tree fills with variants of one shape;
and width and signedness are the one place a type *does* move bytes, which the permuter cannot reach. Hence the canonical type
file from the first bank, growing one proven field at a time — one definition per shape, widths fixed by the bytes at bank
time, a draft refused for a duplicate definition or a raw address cast (DK-65, G62). It removes most of the declaration-conflict
class before the ladder is needed and leaves nothing to unify after 100%; it shortens no crack.
```calibration
source project: ≈92% of drafts byte-correct and ≈27% banked at one measurement; with the map, 11 of 12 first-pass
drafts matched and every failure was plumbing; one 299-instruction head became 4,485 instructions across 15 siblings
for ≈0 tokens; the exact-hash twin join found 22 of 352 reachable stubs, the band 75.
for ≈0 tokens; the exact-hash twin join found 22 of 352 reachable stubs, the band 75. Types: rich decompiler context
scored 0 better / 10 same / 2 worse on a 12-function structural-miss sample, identical bytes (phase 17); 1,232 struct
definitions and 143 raw address casts in the tree at 100%.
```
## 7. The compiler's source — "unsteerable" means "not yet read"
@@ -344,5 +355,5 @@ harness defects wearing model-failure costumes.
## Coverage
Thirteen sections; every claim outside a calibration fence is stated to transfer. The rules are the registry seed
(`templates/registry-E.decomp.md`, G1–G67); the kernels with their costs are `corpus/decomp-kernels.md` (DK-1 … DK-64 and
(`templates/registry-E.decomp.md`, G1–G67); the kernels with their costs are `corpus/decomp-kernels.md` (DK-1 … DK-65 and
the failure museum); the ladder with its milestones is `intake.decomp.md` Part B; the day-one inversions are its Part C.
+2 -2
View File
@@ -142,11 +142,11 @@ registry seed's, installed at Phase 0.5.*
| 3 | **The all-assembly byte-identical baseline** | `make build` produces every onboarded binary with a hash equal to the original at 100% assembly, with the check inside the build; translation-unit boundaries sit at the forced boundaries found in Phase 2; `make expected` baseline set | the Makefile pipeline, the per-binary contracts, the split configs, the boundary check in the health target | G9 | DK-2, DK-12 |
| 4 | **The compiler pinned by evidence** | Three to five probe functions byte-identical under exactly one candidate triple; the triple recorded with its fingerprint evidence and the assembler version passed explicitly; per-module variation (optimisation levels, mixed compilers) detected and recorded; the first functions matched end to end through the whole workflow | the decompile scaffold wrapper, the differ invocation, the standalone probe, the stub/non-matching headers | G8, G10 | DK-3 |
| 5 | **The honest census and the differential harness — at 0%** | Every scanner asserts its coverage; a second oracle disagrees with the first on nothing (0 phantoms, 0 truncations); the harness runs at least five question pairs on a schedule with 0 disagreements; the census reports duplication, structural families, reach × size and the unique tail, each checked against a known-true case; the progress report derives its denominators from the build | the corpus oracle, the coverage assertions, the second boundary oracle, the differential harness, the census, the progress/difficulty/duplicate reports | G19–G36 | DK-8, DK-9, DK-17, DK-19, DK-30, DK-61 |
| 6 | **The multipliers: propagation, families, twins, the reconcile ladder, the carve chain, the draw filter** | One hand-matched function propagates to every member across the fleet, byte-gated per member, registered fail-closed; the twin band reproduces every exact pair and finds more; a standalone match is banked into its real translation unit by the ladder without a redraft; the opt-level and jump-table carves build; the draw filter refuses what cannot bank and counts what it filtered; all four verdict layers are consumed | signatures (exact, normalised, sequence) + the band, dedup propagation and the registry, the family remap, declaration sync / callee casts / canonical signatures, the carve tools, the wall oracle, the draw filter, the twin rescan | G7, G37, G40–G43, G46 | DK-5, DK-7, DK-10, DK-11, DK-24, DK-36 |
| 6 | **The multipliers: propagation, families, twins, the reconcile ladder, the carve chain, the draw filter** | One hand-matched function propagates to every member across the fleet, byte-gated per member, registered fail-closed; the twin band reproduces every exact pair and finds more; a standalone match is banked into its real translation unit by the ladder without a redraft; the opt-level and jump-table carves build; the draw filter refuses what cannot bank and counts what it filtered; all four verdict layers are consumed; **the canonical type layer** exists from the first bank — one definition per shape, widths and signedness proven by the bytes at bank time, a bank refused for a duplicate definition of an existing shape or a raw address cast | signatures (exact, normalised, sequence) + the band, dedup propagation and the registry, the family remap, declaration sync / callee casts / canonical signatures, the canonical type file with its bank-time duplicate-definition and raw-cast check (the type lifter and the signature reconciler start here, not at Phase 10), the carve tools, the wall oracle, the draw filter, the twin rescan | G7, G37, G40–G43, G46, G62 (its bank-time clause) | DK-5, DK-7, DK-10, DK-11, DK-24, DK-36, DK-65 |
| 7 | **The codegen map and the permuter** | The map holds at least one byte-proven lever per pass group with a symptom-keyed triage table; the compiler's source staged at the pinned version with citations audited; the permuter runs on a stored draft and proves it iterated; the plateau classifier labels a plateau; the cookbook seeded from the source and any sibling project, indexed by symptom with its own coverage assertion | the map, the dump scripts (from the real unit), the allocation-table reader, the reproducer battery harness, the permuter with a masked scorer, the plateau classifier, the cookbook index tool | G51, G52, G55, G57, G60, G66, G67 | DK-6, DK-14, DK-15, DK-52 |
| 8 | **First cracks, the manual wave, the routing cliff — then the campaign, leverage-first** | Bank rate by instruction count measured on a small manual wave and the routing set from it; every wave closes with the harvest gate (idioms in the base, mechanical ones toolified, free banks swept, the widening review asked); the fleet green from a clean rebuild after every banked batch; every remaining function on a named ledger with a class, a closeness, a best draft and a named blocker; the census reads 0 stubs | cards and packs (with the banked twin, past attempts, the lever with where to read it), the lanes, the wave procedure with each guard's measurement, the journal read side, the target validator, the exclude-list audit, the gates in worktrees, the recovery ladder, the harvest tools, the verbatim check | G38, G39, G44, G45, G47–G50, G53, G54, G56 | DK-16, DK-31–DK-35, DK-39–DK-43, DK-44–DK-51 |
| 9 | **Publish** | The contract run recorded (clean rebuild, both with and without the vendor SDK, every oracle green, N of N); a fresh clone rebuilds from the developer's own dump by the README alone; every published number generated with a freshness check; the no-ROM CI green; the releases and outreach written by a person; if the repository was private, the visibility flip gated on the host's object store | the contract script, the bootstrap script, the progress publisher, the badges, the release write-ups | G17, G58, G63, G64 | DK-56, DK-57, DK-58 |
| 10 | **Readability** (short if Part C held from Phase 6) | 0 register pins, or each one marked as forced with its reason; 0 shared bodies as macros; 0 raw address casts (every one a declared, typed symbol; a field of a known structure accessed as a field); one definition per structure; every renamed symbol with a recorded basis; formatting clean; and, unchanged, N of N byte-identical from a clean rebuild | the allocation-order reader on the real unit, the type lifter, the symbol mirror into the database, the rename-coverage scanner | G11, G62 | DK-64, DK-47, DK-12; Part C |
| 10 | **Readability** (short if Part C and Phase 6's type layer held — with one definition per shape and no raw cast banked from the first bank, this phase is names, pins and formatting) | 0 register pins, or each one marked as forced with its reason; 0 shared bodies as macros; 0 raw address casts (every one a declared, typed symbol; a field of a known structure accessed as a field); one definition per structure; every renamed symbol with a recorded basis; formatting clean; and, unchanged, N of N byte-identical from a clean rebuild | the allocation-order reader on the real unit, the type lifter, the symbol mirror into the database, the rename-coverage scanner | G11, G62 | DK-64, DK-65, DK-47, DK-12; Part C |
**Two notes on the order.** Phases 5–7 look like "planning-only" phases and are not: each ends in a running tool with a
verifiable output (M1), and each is the reason the campaign phase banks at the rate it does — the source project built
@@ -411,8 +411,11 @@ provenance: BFM gen3-standards conduct rule 1
A symbol is renamed only on a recorded basis (a string it prints, a cross-reference chain, a debug menu, a live-memory
datapoint, a community label with provenance). No evidence, no name — an address-named placeholder is honest and greppable.
A model may propose a name; it may never assert one. Types come from access patterns locked into the bytes; structure is
unified before any field is named.
provenance: BFM gen3-standards rule 1 + the sotn-decomp style guide ("better to leave it unnamed than name it wrongly")
unified before any field is named. **At bank time:** a canonical type file exists from the first bank and grows one proven
field at a time; a draft may not bank a duplicate definition of a shape the file already has, nor a raw address cast (every
absolute address it touches is a declared, typed symbol); a width or signedness is proven by the bytes, never guessed — the one
place a type moves bytes, and the one the permuter cannot reach.
provenance: BFM gen3-standards rule 1 + the sotn-decomp style guide ("better to leave it unnamed than name it wrongly"); the bank-time clause from BFM decision-log "P33.5 S91-b" (types as a banking and width lever — 1,232 drafter-invented definitions at 100%)
### G63 — Outward text is written by a person
Issues, pull requests, forum posts and outreach are written by the maintainer the way a developer writes — short, plain, few
+6 -6
View File
@@ -9,7 +9,7 @@
> their code does not transfer). *TODO(platform): the MIPS and PlayStation SDK hard-codes are the ones another platform replaces first.*
>
> **Coverage:** 293 tool files in scope (submodules, vendored and downloaded code excluded), of which 293 live rows
> below; per phase: P1 2 · P2 26 · P3 17 · P4 9 · P5 27 · P6 52 · P7 20 · P8 86 · P9 26 · P10 12 · PROJECT-ONLY 16. Superseded tools appear only as pointers to their successor (28 pointer rows); one-offs are omitted. Table rows in all: 321 (the installer checks its copy against this figure).
> below; per phase: P1 2 · P2 26 · P3 17 · P4 9 · P5 27 · P6 54 · P7 20 · P8 86 · P9 26 · P10 10 · PROJECT-ONLY 16. Superseded tools appear only as pointers to their successor (28 pointer rows); one-offs are omitted. Table rows in all: 321 (the installer checks its copy against this figure).
## P1 — extraction + manifest
@@ -125,15 +125,15 @@
| `weave_sweep.py` | apply one proven codegen lever everywhere the bytes say it belongs | Applies one known prologue-scheduling lever everywhere the bytes say it belongs | repo src layout, compiler behaviour |
| `interleave_check.py` | assert a read-only-data carve's interleave order equals the segment sequence | Asserts the carve interleave order equals the segment sequence, position by position | repo config layout |
| `jtbl_family_bank.py` | bank a matched jump-table exemplar across its siblings, reverting on failure | Banks a matched jump-table exemplar across its structural siblings, revert-on-fail | repo config/src layout |
| `sync_tu_decls.py` | bank a refused draft by copying the destination unit's own declarations into it | Banks a refused draft by copying the destination unit's own declarations into it | repo src layout |
| `sync_tu_decls.py` | bank a refused draft by copying the destination unit's own declarations into it — the declaration-conflict class a canonical type layer prevents (Phase 6) | Banks a refused draft by copying the destination unit's own declarations into it | repo src layout |
| `twin_sweep.py` | bank every open stub that already has a banked structural twin | Banks every open stub that has an already-banked structural twin, for near-zero tokens | repo signature files |
| `fix_decl_mirror.py` | bind a void definition to a symbol the destination declares as returning a value | Binds a void definition to its symbol when the destination declares a value return | repo src layout |
| `family_align.py` | classify drifted structural siblings by aligned words and expand their constants | Length-tolerant aligned classifier plus the mechanical constant-expansion engine for drifted members | repo scratch paths |
| `exclude_audit.py` | classify every exclude-list entry by its current blocker and regenerate the list | Classifies every exclude-list entry by its current blocker and regenerates the list | repo config path |
| `family_cousins.py` | cluster the open frontier one tier looser than exact skeleton hashing | Similarity clustering one tier looser than exact skeleton hashing over the open frontier | repo signature files |
| `decl_prior.py` | compute the fleet's consensus declaration for every symbol, as card fuel | Computes the fleet's consensus declaration for every symbol, as card fuel | repo src layout |
| `decl_prior.py` | compute the fleet's consensus declaration for every symbol, as card fuel — the seed of a canonical type layer (Phase 6) | Computes the fleet's consensus declaration for every symbol, as card fuel | repo src layout |
| `reconcile_tu.py` | conform a draft's data declarations to what its destination unit can see | Conforms a draft's data declarations to what the destination translation unit can actually see | repo src layout |
| `conform_decls.py` | conform every declaration of a function fleet-wide to its byte-true definition | Conforms every declaration of a function fleet-wide to its byte-true definition | repo src/shared-header layout |
| `conform_decls.py` | conform every declaration of a function fleet-wide to its byte-true definition — width and signedness proven by the bytes at bank time (Phase 6) | Conforms every declaration of a function fleet-wide to its byte-true definition | repo src/shared-header layout |
| `scope_demote_drafts.py` | demote declaration scope as one rung of the recovery ladder | The scope-demote step, wired as a rung of the recovery ladder | repo src layout |
| `pads_audit.py` | derive an object's inter-table padding spec from the bytes instead of searching | Derives each object's padding spec from the bytes instead of searching for it | repo build/config layout |
| `aprop_autodraft.py` | draft a family member mechanically from a seed body and symbol rebase | Mechanically drafts a family member from the seed body plus a positional symbol rebase | repo scratch paths |
@@ -145,6 +145,7 @@
| `jr_isolate_all.py` | isolate every switch function in a binary in one multi-cut resegment | One-shot multi-cut resegment isolating every switch function in a binary | repo config/src layout |
| `match_protos.py` | join two related builds' signature dumps into a function correspondence | Joins per-function signature dumps of two related builds into a function correspondence | repo signature files |
| `cast_self_callers.py` | let a unit keep calling, through per-site casts, the function it now defines | Lets a unit keep calling, through a per-site cast, the function it is about to define | repo src layout |
| `lift_types.py` | lift a named list of types fleet-wide into the shared type header — the canonical type layer from the first bank (Phase 6, the multiplier); again at readability (Phase 10) | Lifts a named list of types fleet-wide into the shared type header | repo shared-header path |
| `dedup_propagate.py` | lift one matched body into a shared macro and instantiate it everywhere | Lifts one matched body into a shared macro and instantiates it at every duplicate site | repo shared-header/src layout |
| `macro_draft.py` | materialize a shared macro body back into a compilable standalone draft | Materializes a shared macro body back into a compilable standalone draft | repo shared-header layout |
| `scope_tu_externs.py` | move a unit's file-scope data externs down into their consumers | Moves a unit's own file-scope data externs down into their consumers to legalize a block-scope type | repo src layout |
@@ -156,6 +157,7 @@
| `xsig/tests/test_xsig.py` | property-test the signature tool on committed fixtures, needing no compiler | Property tests for the signature tool on committed fixtures, needing no compiler | fixture paths |
| `family_hseq.py` | rank clusters of the unmatched frontier by mnemonic-skeleton hash | Ranked clustering of the unmatched frontier by mnemonic-skeleton hash | repo signature files |
| `aprop_symfix.py` | rebase a remapped draft's stale seed symbols onto the target's own | Rebases stale seed symbols in a mechanically adapted draft onto the target's own symbols | repo symbol/config sources |
| `canon_sig_reconcile.py` | reconcile a definition's typed signature with what its destination unit declares — part of banking against a canonical type layer from Phase 6; again at readability (Phase 10) | Reconciles a definition's typed signature with what its destination unit already declares | repo src layout |
| `xsig/tests/make_fixtures.sh` | regenerate the signature tool's fixtures with the pinned toolchain | Regenerates the signature-tool fixtures with the pinned toolchain | compiler triple, repo tool paths |
| `family_remap.py` | remap a matched exemplar's source onto a structural sibling by positional symbol pairing | Mechanically remaps a matched exemplar's C onto a structural sibling by positional symbol pairing | repo src layout |
| `fix_arity_callers.py` | repair a shared caller's argument-count conflict for the no-prototype failure class | Repairs the shared-caller argument-count conflict for the no-prototype failure class | repo shared-header layout |
@@ -332,9 +334,7 @@
| `lint_symbol_refs.py` | flag address-named references whose address now has a curated name | Flags address-named references in committed sources whose address now has a curated name | repo symbol/src paths |
| `uniquify_type.py` | give each conflicting camp of a same-named type its own name | Gives each conflicting camp of a same-named type its own name so every camp becomes liftable | repo src layout |
| `verbatim_check.py` | guard that every inline-assembly body still reproduces its target bytes | Regression guard that every inline-assembly body still reproduces its target bytes | repo src layout |
| `lift_types.py` | lift a named list of types fleet-wide into the shared type header | Lifts a named list of types fleet-wide into the shared type header | repo shared-header path |
| `ghidra_apply_symbols.sh` | mirror the curated symbol file into the analysis database with a real save | Mirrors the curated symbol file into the analysis program headlessly, with a real save | repo symbol path, project name |
| `canon_sig_reconcile.py` | reconcile a definition's typed signature with what its destination unit declares | Reconciles a definition's typed signature with what its destination unit already declares | repo src layout |
| `verbatim_target_s.py` | regenerate a splitter-format target disassembly for a function no longer stubbed | Regenerates a splitter-format target disassembly for a function that is no longer a stub | repo build/asm layout |
| `verbatim_to_stub.py` | turn an inline-assembly body back into a stub the toolchain can reach | Turns an inline-assembly body back into an include-assembly stub | repo src/asm layout |
+1
View File
@@ -771,6 +771,7 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo
| | `tools/gitignore_template_check.py` | **(P33.5 task 7)** The ```` ```gitignore ```` fence of `docs/wiki/The-ROM-firewall.md` must equal `decomp-architect/templates/gitignore.decomp` byte for byte (one source, two copies; R75-shaped). rc 1 on drift, rc 2 when the template does not exist yet ("nothing to compare" — never a pass, R43); refuses a page with ≠ 1 fence. In `tools-health` behind an existence test that skips loudly until the kit lands (task 11). |
| | `tools/kit_lint.py [--selftest] [--paths …]` | **(P33.5 task 11)** The day-one decomp kit (`decomp-architect/`) stays de-specialised: (1) LEAK — no line outside a ```` ```calibration ```` fence and off a `provenance:` line matches `SLUS|Musashi|BFM|Druthulu|func_80|ov_SC|/home/musashi|/mnt/z|172\.17\.|\bR[0-9]{1,2}\b|§[0-9]+` (fence-aware: `grep -v calibration` would drop only lines containing the word); (2) PLACEHOLDERS — the `{{NAME}}` set used under the package equals the backticked set in `templates/PLACEHOLDERS.md` (the contract); (3) SYNTAX — `bash -n` / `py_compile` (no bytecode written) / JSON+YAML parse; (4) the gitignore template diff (delegated); (5) `TODO(platform)` / `TODO(phase-N)` counts; (6) coverage — zero files is a failure. rc 1 findings, rc 2 package absent (R43). `--selftest` = the R39 control (a planted leak line + a planted unlisted placeholder must be caught, fenced and provenance lines must not). In `tools-health` (selftest, then the real run). |
| | `tools/tool_census.py [--check | --manifest | --corpus | --all | --consumers FILE]` | **(P33.5 task 13.5)** The tools audit as a derived instrument: two independent enumerations of every tool file under `tools/` (`find` vs `git ls-files`, submodules/vendored/downloaded excluded — they must agree, R34); per tool the docstring line, its SETUP row, its CONSUMERS (Makefile/`.mk` targets, CI, the wave playbook, other tools by import or by name) and hence its class (LIVE · REFERENCED · ORPHAN); the AUTHORED facts live in `config/tool_dictionary.tsv` (phase · portability · the NEED the tool answers · what · what it hard-codes · the retirement verdict with its successor or product) with coverage asserted BOTH ways (R32 — a new tool without a row fails `--check`). Generates `docs/tool-index.md` (the need-keyed dictionary; KEEP-GEN), the kit's `tools/MANIFEST.md` (`--manifest`) and the two verbatim corpora `decomp-architect/corpus/tools/<phase>/` + `corpus/cookbook/` (`--corpus`; superseded tools as pointer files; sha1-equal to their sources). `--check` in `tools-health`; `make kit-corpus` = `--all`. `--consumers FILE` is the referrer census before any `git mv` of a tool. |
| | `decomp-architect/` (the day-one decomp kit) | **(P33.5 tasks 9–14)** The package a new matching-decomp project installs as Phase 0.5 on ProjectArchitect 2.0: `README.md` (the three steps), `intake.decomp.md` (ProjectArchitect's twelve items pre-answered + the phase ladder + the six readability inversions), `SETUP.md` (the installer, Step 0 contract … Step 10 verify + hard stop; `answers: <path>` for unattended runs), `decomp-architect.md` (the methodology), `templates/` (the firewall pack — `gitignore.decomp`, `firewall.txt`, `audit_public.template.py`, the planted fixture, `no-rom.template.yml` —, the READMEs, `pa-overlays.md`, `registry-E.decomp.md` G1–G67, the skeletons, `PLACEHOLDERS.md`, `layout-contract.md`), `corpus/decomp-kernels.md` (DK-1 … DK-65), the two dictionaries `corpus/tools/<phase>/` + `corpus/cookbook/` (generated by `make kit-corpus`), `memory-seed/` (18), `tools/MANIFEST.md` (generated). **How it is checked:** `tools/kit_lint.py` (de-specialisation, placeholders, syntax, the gitignore-template diff) + `tools/tool_census.py --check` (the corpora equal their sources) + `tools/gitignore_template_check.py`, all in `tools-health`; the dry-run harness under `.run/P33.5/kit-dryrun/` (`answers.md`, `expected-manifest.txt`, `judge.py`, the install logs and verdicts of runs 1–4 — a kit change is re-verified by a resume on the last throwaway `repo/`, a fresh full run only when SETUP's steps change; the judge compares the real tree's dirty PATH SETS before/after). Wiki page: `docs/wiki/Start-a-new-decomp-project.md`. Split into its own repository after the flip. |
| **Verification** | `tools/verify_contract.sh` | **(P33 A5/C8) THE recorded contract run**: 00 tree · 01 check-env · 02 family_hseq · 03 `make clean && extract-all && check-all` · 04 sdk-dual (or a recorded SKIP) · 05 tools-health (zero `[warn]`) · 06 audit-frontier · 07 audit-disc · 08 report; one log per step ending `EXIT=<rc>`, abort on the first red (R53), every step asserted by its contract line (R49), `SUMMARY.md` generated → `.run/P33/verify/` (tracked evidence, quoted by `docs/verification.md` §2); step 00 ignores its own output dir. ≈14 min on 32 CPUs. |
| **Publishing** | `tools/progress.py --json \| --readme [--check]` | **(P33 D1/D3)** The same numbers as DATA: `--json` → `docs/progress.json` (schema 1: the four metrics with numerator/denominator/pct, the counts, 218 per-binary rows incl. instruction totals; no run date) + `docs/badges/{fleet_instr,fleet_fn,distinct,binaries}.json` (shields endpoint format; the README references `fleet_instr` + `binaries` by name); `--readme` rewrites the README's `<!-- progress:begin/end -->` block (refuses a README without the markers); `--check` asserts JSON + block + badges are fresh (in `make audit-digest`). Run by `make report BINARY=main`. |
| | `tools/wiki_render.py OUT_DIR \| --list \| --selftest` | **(P33 F3)** Render `docs/wiki/*.md` + `docs/how-to-ai-decomp/*.md` into GitHub-wiki page names with every relative link rewritten deterministically (wiki page → its name; a chapter → `How-to-AI-decomp-NN-name`; any other repo path → a `blob/main` / `tree/main` / raw URL; URLs, mailto and anchors untouched; **a dead link is an error**, R43). `--selftest` = the 12-case fixture incl. the dead-link negative control **plus (P33.5 task 7) the reachability assertion: every `docs/wiki/*.md` except `_Sidebar`/`_Footer`/`Home` is linked from `_Sidebar.md`, every chapter from `_Sidebar.md` AND `How-to-AI-decomp.md`** — a published page nobody can navigate to fails here; in `make tools-health`. |
+4 -2
View File
@@ -12,7 +12,7 @@
| # | Task | Actor | Effort | The document that carries it |
|---|---|---|---|---|
| 0 | **Daily probe** until PASS: `tools/public_rewrite/probe_github.sh` (S89 baseline 31 of 33 old hashes still ALIVE). Fallback if Support stalls past ~a week: delete and recreate the repository under the same name and push the same rewritten history (a new object network and a fresh Activity log; nothing else exists to lose). | Claude runs; Drew decides the fallback | Low | `docs/public-flip-runbook.md` §11 (the Activity-view leak, the ticket route, the fallback) |
| 0 | **Daily probe** until PASS: `tools/public_rewrite/probe_github.sh` (S89 baseline 31 of 33 old hashes still ALIVE). **PASSED 2026-09-07 during Phase 33.5** (`.run/P33.5/probe_github_s91.log`: every sampled old hash gone, the live control resolves) — the gate is open; run it once more immediately before task 1. Fallback if Support stalls past ~a week: delete and recreate the repository under the same name and push the same rewritten history (a new object network and a fresh Activity log; nothing else exists to lose). | Claude runs; Drew decides the fallback | Low | `docs/public-flip-runbook.md` §11 (the Activity-view leak, the ticket route, the fallback) |
| 1 | **C10 the flip:** Settings → General → Danger Zone → Change visibility → Public; then `gh api repos/Druthulu/BFM-decomp --jq .private` → `false`; `probe_github.sh --after-flip`; the Actions tab green; enable Settings → Features → Wikis (free plan: wikis need a public repo). | Drew | Max (decision) | runbook §11; checkpoint §0b |
| 2 | **E1 outward — the decomp.me preset:** the six steps (log in; scratch from `.run/decompme/drew_bundle/` → 100%; the preset-request issue on `decompme/decomp.me` in Drew's words; the manual search closing SETUP ledger row 14; report URLs). Regenerate the bundle with `tools/decompme_replica.sh` if `.run/` was pruned. | Drew | xHigh | `docs/decompme-preset.md` §5 |
| 3 | **E2 outward — the Archipelago note:** the GitHub issue on `AegeusEvander/Brave-Fencer-Musashi-AP-World` (or the Discord short form), in Drew's words; on reply, memory-map rows per its §5. | Drew | xHigh | `docs/outreach/archipelago.md` §4–§5 |
@@ -24,7 +24,9 @@
> **Phase 33.5 runs before this phase** (opened 2026-09-07; `phase-ends/CURRENT_PHASE.md`): docs consolidation into the wiki, the
> tracked-`.run/` prune, the memory reconciliation and the day-one decomp kit — v1.32.1. It changes no build input and no flip step;
> task 0's daily probe continues in parallel. Phase 34 opens from this file once 33.5 closes.
> task 0's probe PASSED during it (2026-09-07). Phase 34 opens from this file once 33.5 closes. **The kit `decomp-architect/` is carried
> WHOLE through the flip** (its two corpora are generated in-tree by `make kit-corpus` and asserted equal in tools-health; nothing in it
> refers to this repository's paths) and split into its own repository afterwards, as xsig was — that split is a Phase-35+ task, not this phase's.
Every outward action is done by Drew or **explicitly recorded as pending** in the PhaseEnd (P9 — never claimed). Every outward
text is written by Drew the way a developer writes it (rule candidate (j); `docs/gen3-standards.md` §3).
+5 -5
View File
@@ -121,15 +121,15 @@ then what proved it. The same data generates the day-one kit's manifest and its
| apply one proven codegen lever everywhere the bytes say it belongs | `weave_sweep.py` | Applies one known prologue-scheduling lever everywhere the bytes say it belongs | — | repo src layout, compiler behaviour | REFERENCED |
| assert a read-only-data carve's interleave order equals the segment sequence | `interleave_check.py` | Asserts the carve interleave order equals the segment sequence, position by position | — | repo config layout | REFERENCED |
| bank a matched jump-table exemplar across its siblings, reverting on failure | `jtbl_family_bank.py` | Banks a matched jump-table exemplar across its structural siblings, revert-on-fail | dedup_extend.py, family_sweep.py, reloc_verify.py | repo config/src layout | LIVE |
| bank a refused draft by copying the destination unit's own declarations into it | `sync_tu_decls.py` | Banks a refused draft by copying the destination unit's own declarations into it | docs/wave-playbook.md, recover_route.py | repo src layout | LIVE |
| bank a refused draft by copying the destination unit's own declarations into it — the declaration-conflict class a canonical type layer prevents (Phase 6) | `sync_tu_decls.py` | Banks a refused draft by copying the destination unit's own declarations into it | docs/wave-playbook.md, recover_route.py | repo src layout | LIVE |
| bank every open stub that already has a banked structural twin | `twin_sweep.py` | Banks every open stub that has an already-banked structural twin, for near-zero tokens | docs/wave-playbook.md | repo signature files | LIVE |
| bind a void definition to a symbol the destination declares as returning a value | `fix_decl_mirror.py` | Binds a void definition to its symbol when the destination declares a value return | — | repo src layout | ORPHAN |
| classify drifted structural siblings by aligned words and expand their constants | `family_align.py` | Length-tolerant aligned classifier plus the mechanical constant-expansion engine for drifted members | len_tells.py | repo scratch paths | LIVE |
| classify every exclude-list entry by its current blocker and regenerate the list | `exclude_audit.py` | Classifies every exclude-list entry by its current blocker and regenerates the list | docs/wave-playbook.md, draw_waves.py | repo config path | LIVE |
| cluster the open frontier one tier looser than exact skeleton hashing | `family_cousins.py` | Similarity clustering one tier looser than exact skeleton hashing over the open frontier | Makefile, aprop_autodraft.py, atlas.py, atlas_features.py (+3) | repo signature files | LIVE |
| compute the fleet's consensus declaration for every symbol, as card fuel | `decl_prior.py` | Computes the fleet's consensus declaration for every symbol, as card fuel | build_wave_atlas.py, family_remap.py, t5_cards.py | repo src layout | LIVE |
| compute the fleet's consensus declaration for every symbol, as card fuel — the seed of a canonical type layer (Phase 6) | `decl_prior.py` | Computes the fleet's consensus declaration for every symbol, as card fuel | build_wave_atlas.py, family_remap.py, t5_cards.py | repo src layout | LIVE |
| conform a draft's data declarations to what its destination unit can see | `reconcile_tu.py` | Conforms a draft's data declarations to what the destination translation unit can actually see | gate_stage.py, harvest_verify.py, integration_resolver.py, jtbl_family_bank.py | repo src layout | LIVE |
| conform every declaration of a function fleet-wide to its byte-true definition | `conform_decls.py` | Conforms every declaration of a function fleet-wide to its byte-true definition | family_sweep.py, macro_draft.py | repo src/shared-header layout | LIVE |
| conform every declaration of a function fleet-wide to its byte-true definition — width and signedness proven by the bytes at bank time (Phase 6) | `conform_decls.py` | Conforms every declaration of a function fleet-wide to its byte-true definition | family_sweep.py, macro_draft.py | repo src/shared-header layout | LIVE |
| demote declaration scope as one rung of the recovery ladder | `scope_demote_drafts.py` | The scope-demote step, wired as a rung of the recovery ladder | gate_stage.py, recover_route.py | repo src layout | LIVE |
| derive an object's inter-table padding spec from the bytes instead of searching | `pads_audit.py` | Derives each object's padding spec from the bytes instead of searching for it | — | repo build/config layout | REFERENCED |
| draft a family member mechanically from a seed body and symbol rebase | `aprop_autodraft.py` | Mechanically drafts a family member from the seed body plus a positional symbol rebase | decl_from_use.py, maintenance.sh, sibling_lane.sh | repo scratch paths | LIVE |
@@ -141,6 +141,7 @@ then what proved it. The same data generates the day-one kit's manifest and its
| isolate every switch function in a binary in one multi-cut resegment | `jr_isolate_all.py` | One-shot multi-cut resegment isolating every switch function in a binary | harvest_verify.py, jtbl_carve.py, jtbl_family_bank.py, o0_subsplit.py (+1) | repo config/src layout | LIVE |
| join two related builds' signature dumps into a function correspondence | `match_protos.py` | Joins per-function signature dumps of two related builds into a function correspondence | dup_report.py | repo signature files | LIVE |
| let a unit keep calling, through per-site casts, the function it now defines | `cast_self_callers.py` | Lets a unit keep calling, through a per-site cast, the function it is about to define | docs/wave-playbook.md, recover_integration.py, recover_route.py | repo src layout | LIVE |
| lift a named list of types fleet-wide into the shared type header — the canonical type layer from the first bank (Phase 6, the multiplier); again at readability (Phase 10) | `lift_types.py` | Lifts a named list of types fleet-wide into the shared type header | build_engine_types.py, uniquify_type.py | repo shared-header path | LIVE |
| lift one matched body into a shared macro and instantiate it everywhere | `dedup_propagate.py` | Lifts one matched body into a shared macro and instantiates it at every duplicate site | auto_driver.py, bulk_harvest.py, gate_lane.py, gate_stage.py (+5) | repo shared-header/src layout | LIVE |
| materialize a shared macro body back into a compilable standalone draft | `macro_draft.py` | Materializes a shared macro body back into a compilable standalone draft | — | repo shared-header layout | ORPHAN |
| move a unit's file-scope data externs down into their consumers | `scope_tu_externs.py` | Moves a unit's own file-scope data externs down into their consumers to legalize a block-scope type | family_sweep.py, jtbl_family_bank.py, recover_integration.py | repo src layout | LIVE |
@@ -152,6 +153,7 @@ then what proved it. The same data generates the day-one kit's manifest and its
| property-test the signature tool on committed fixtures, needing no compiler | `xsig/tests/test_xsig.py` | Property tests for the signature tool on committed fixtures, needing no compiler | .github/workflows/no-rom.yml, Makefile | fixture paths | LIVE |
| rank clusters of the unmatched frontier by mnemonic-skeleton hash | `family_hseq.py` | Ranked clustering of the unmatched frontier by mnemonic-skeleton hash | Makefile, audit_binaries.py, audit_frontier.py, build_wave_atlas.py (+6) | repo signature files | LIVE |
| rebase a remapped draft's stale seed symbols onto the target's own | `aprop_symfix.py` | Rebases stale seed symbols in a mechanically adapted draft onto the target's own symbols | aprop_autodraft.py, family_cousins.py, integration_resolver.py, recover_rejects.py | repo symbol/config sources | LIVE |
| reconcile a definition's typed signature with what its destination unit declares — part of banking against a canonical type layer from Phase 6; again at readability (Phase 10) | `canon_sig_reconcile.py` | Reconciles a definition's typed signature with what its destination unit already declares | family_sweep.py, jtbl_family_bank.py | repo src layout | LIVE |
| regenerate the signature tool's fixtures with the pinned toolchain | `xsig/tests/make_fixtures.sh` | Regenerates the signature-tool fixtures with the pinned toolchain | test_xsig.py | compiler triple, repo tool paths | LIVE |
| remap a matched exemplar's source onto a structural sibling by positional symbol pairing | `family_remap.py` | Mechanically remaps a matched exemplar's C onto a structural sibling by positional symbol pairing | aprop_autodraft.py, atlas.py, atlas_features.py, dedup_extend.py (+17) | repo src layout | LIVE |
| repair a shared caller's argument-count conflict for the no-prototype failure class | `fix_arity_callers.py` | Repairs the shared-caller argument-count conflict for the no-prototype failure class | docs/wave-playbook.md, cdecl.py, dedup_propagate.py, gate_stage.py (+2) | repo shared-header layout | LIVE |
@@ -328,9 +330,7 @@ then what proved it. The same data generates the day-one kit's manifest and its
| flag address-named references whose address now has a curated name | `lint_symbol_refs.py` | Flags address-named references in committed sources whose address now has a curated name | .github/workflows/no-rom.yml, Makefile | repo symbol/src paths | LIVE |
| give each conflicting camp of a same-named type its own name | `uniquify_type.py` | Gives each conflicting camp of a same-named type its own name so every camp becomes liftable | — | repo src layout | REFERENCED |
| guard that every inline-assembly body still reproduces its target bytes | `verbatim_check.py` | Regression guard that every inline-assembly body still reproduces its target bytes | .github/workflows/no-rom.yml, verbatim_target_s.py, verbatim_to_stub.py | repo src layout | LIVE |
| lift a named list of types fleet-wide into the shared type header | `lift_types.py` | Lifts a named list of types fleet-wide into the shared type header | build_engine_types.py, uniquify_type.py | repo shared-header path | LIVE |
| mirror the curated symbol file into the analysis database with a real save | `ghidra_apply_symbols.sh` | Mirrors the curated symbol file into the analysis program headlessly, with a real save | — | repo symbol path, project name | REFERENCED |
| reconcile a definition's typed signature with what its destination unit declares | `canon_sig_reconcile.py` | Reconciles a definition's typed signature with what its destination unit already declares | family_sweep.py, jtbl_family_bank.py | repo src layout | LIVE |
| regenerate a splitter-format target disassembly for a function no longer stubbed | `verbatim_target_s.py` | Regenerates a splitter-format target disassembly for a function that is no longer a stub | decompme_replica.sh | repo build/asm layout | LIVE |
| turn an inline-assembly body back into a stub the toolchain can reach | `verbatim_to_stub.py` | Turns an inline-assembly body back into an include-assembly stub | — | repo src/asm layout | REFERENCED |
+1
View File
@@ -34,6 +34,7 @@ log, the memory map, the environment reference) live under `docs/` and are liste
| [Verification and progress](Verification-and-progress.md) | The contract run, the three metrics and how they are computed, what CI proves without a disc, the published numbers |
| [Contributing and the no-ROM policy](Contributing-and-the-no-ROM-policy.md) | What may never enter the repository, what a useful contribution looks like now that the frontier is empty, the AI-use conduct rules, the license split |
| [Tools from this project](Tools-from-this-project.md) | xsig, the permuter driver, the codegen map, the decomp.me replica, the drafter write-up — what stands on its own for other projects |
| [Start a new decomp project](Start-a-new-decomp-project.md) | The day-one kit for the next decompilation: the three install steps, what it installs and does not (the two dictionaries), the phase ladder, the conduct rules, the six inversions, every accelerator in one line, the four dry-runs that prove it |
## Working conventions
+227
View File
@@ -0,0 +1,227 @@
# Start a new decomp project
This project reached 100% and then wrote down, in one place, what it would hand its own day one: the order of work it
would have used from the start, the ROM firewall from the first commit, the rules distilled from its failures, the
knowledge-base flywheel, the model and effort doctrine, the conduct rules for using AI, and the readability standard
applied at draft time instead of after 100%. That package is the **day-one decomp kit**, `decomp-architect/`, at the
repository root. It lives in this tree until the public flip and is split into its own repository afterwards, as xsig was.
It is an overlay, not a system of its own: it installs as **Phase 0.5** of a project governed by
[ProjectArchitect 2.0](https://github.com/Druthulu/ProjectArchitect) (the constitution-and-phase-gates system this project
ran under), and it refuses to run on any other version or on a repository ProjectArchitect has not set up.
## The three steps
From the kit's own README (`decomp-architect/README.md`):
1. **Install ProjectArchitect 2.0.** Copy its `project-architect-2.0/` folder into your new, empty git repository and say, in
Claude Code, `Read SETUP.md and do it.` When its interview starts, hand it the kit's intake:
`My intake answers are in decomp-architect/intake.decomp.md; read it, ask me only the FILL items, and generate from it.`
The intake pre-answers ProjectArchitect's twelve items for a decompilation and carries the phase ladder, so the
constitution ProjectArchitect generates — and then freezes — already contains the decomp roadmap with a
machine-checkable milestone per phase. (Copy `decomp-architect/` in first so the file is there to read.)
2. **Copy `decomp-architect/`** into the repository root, beside `project-architect-2.0/`. Only that folder, not the
repository it ships in.
3. **Run the kit's installer.** In a fresh session: `Read decomp-architect/SETUP.md and do it.` It checks the
ProjectArchitect version, interviews you about the game (title, platform, serial, where your dump lives, the medium's
container layout and SDK evidence, prior community work, goals, the license and disclosure decisions), stamps the
firewall, appends the domain rules and the overlays, seeds the memory and the corpus, verifies every step, commits by
explicit path, and stops. Then delete the folder, start a fresh session and say `Begin Phase 1`.
For an unattended run, the instruction takes an `answers: <path>` clause naming a `KEY: value` file; a missing key stops
the installer, it never defaults. Every git call is by explicit path; the installer never pushes and never runs `git clean`.
## What it installs — and what it deliberately does not
| Piece | What it is |
|---|---|
| The intake (`intake.decomp.md`) | ProjectArchitect's twelve items pre-answered; the phase ladder below; the six readability inversions; what to tell the generation step about the rules registry |
| The methodology (`decomp-architect.md`, copied to `docs/`) | thirteen sections: the ladder and why, the byte gate, cards/lanes/waves, the flywheel laws, the instruments, integration, the compiler's source, models and effort, conduct, readability at day one, what stays hard, publishing, the economics' shape |
| The registry seed (`templates/registry-E.decomp.md`) | rules G1–G67 in seven groups — the oracles and the gate, the ROM firewall, the instruments, the campaign, compiler walls, publishing and the record, the use of AI — each with a `provenance:` line naming the failure that earned it |
| The firewall pack | a copyable `.gitignore` (the same block as [The ROM firewall](The-ROM-firewall.md), asserted identical in this project's health check), an audit that derives its forbidden set from a config and fails on a planted fixture before it is trusted, and a CI workflow — no game-derived bytes in git from commit one |
| The layout, the overlays, the skeletons | the `docs/` and `.run/` conventions from [Docs and scratch conventions](Docs-and-scratch-conventions.md); marked-section appends to `CLAUDE.md`, the effort map, the cookbook, the ops reference; the session-start digest, the replayable checkpoint block and the PhaseEnd narrative axis; LICENSE, NOTICE, README and CONTRIBUTING skeletons, a `.clang-format` and a `make format` snippet |
| The kernels (`corpus/decomp-kernels.md`) | DK-1 … DK-65: what this project learned late, each with when it applies and what it cost, plus the failure museum |
| The memory seed (`memory-seed/`) | eighteen working agreements and harness facts, de-specialised, appended to the memory ProjectArchitect configured |
**It installs no tools.** A byte gate, a splitter config, a permuter harness, a decompiler context, a differential
harness — those are the first phases' work, and the kit says so in its installer's honesty section. What it ships instead
is **two dictionaries**, both generated from this tree and asserted equal to it on every health check:
- **The tool corpus** (`decomp-architect/corpus/tools/<phase>/`): this project's 293 live tools, copied verbatim by ladder
phase, behind an index keyed by the *need* each answers — what it does, what proved it (its consumers), what it
hard-codes. The live counterpart is the [tool index](../tool-index.md). Superseded tools appear as pointers to their
successor; one-offs are left behind. A new project builds each tool for its own target from the description, with the
verbatim copy as the reference implementation and the *adapt* column as the list of what to change — and the kit's rule is
to look a need up in the dictionary before designing or debugging a tool (G66).
- **The inherited knowledge base** (`decomp-architect/corpus/cookbook/`): the matching cookbook, its symptom-keyed index
and the gcc 2.7.2 codegen map, verbatim, behind a front page that states what transfers (see *The compiler question*).
## The phase ladder
The order this project would use if it started again. Each phase ends in something runnable with a machine-checkable
milestone; the last column is the kernel that earned the phase its position — something this project paid to learn late.
The full rows, with the tools built and the rules in force, are the intake's Part B.
| # | Phase | Milestone, in one line | Earned by |
|---|---|---|---|
| 0 | Governance and the firewall | the ROM audit fails on the planted fixture and passes on the tree; CI green on the first push; the constitution carries this ladder | DK-1, DK-53–58 |
| 1 | Deterministic extraction with a committed manifest | one command extracts the whole medium; a second run reproduces the manifest; sampled payloads agree with a reference extractor; nothing ROM-derived staged | DK-2 |
| 2 | The oracles and the load map | the database imported with the era's signatures and exported as text with the rebuild proven; the runtime oracle scripted; load addresses byte-proven against live memory; the forced boundaries recorded | DK-12, DK-13, DK-18 |
| 3 | The all-assembly byte-identical baseline | every onboarded binary rebuilds hash-equal at 100% assembly with the check inside the build; unit boundaries at the forced boundaries | DK-2, DK-12 |
| 4 | The compiler pinned by evidence | three to five probe functions byte-identical under exactly one candidate triple; per-module variation detected; the first functions matched end to end | DK-3 |
| 5 | The honest census and the differential harness, at 0% | every scanner asserts its coverage; a second oracle disagrees on nothing; the census checked against a known-true case; denominators derived from the build | DK-8, 9, 17, 19, 30, 61 |
| 6 | The multipliers | one matched function propagates fleet-wide, gated per member; twins reproduced; a standalone match banked into its real unit without a redraft; the carves build; the draw filter refuses what cannot bank; **the canonical type layer from the first bank** — one definition per shape, widths proven by the bytes, no duplicate definition or raw address cast banked | DK-5, 7, 10, 11, 24, 36, 65 |
| 7 | The codegen map and the permuter | one byte-proven lever per pass group with a symptom-keyed triage table; the compiler's source staged and cited; the permuter proves it iterated; the cookbook seeded and indexed | DK-6, 14, 15, 52 |
| 8 | First cracks, the manual wave, the routing cliff, then the campaign | the bank rate measured on a small manual wave and the routing set from it; every wave closes with the harvest gate; the fleet green from a clean rebuild after every batch; the census reads 0 stubs | DK-16, 31–35, 39–51 |
| 9 | Publish | the contract run recorded; a fresh clone rebuilds from the developer's own dump by the README alone; every published number generated; the flip gated on the host's object store | DK-56–58 |
| 10 | Readability (short if the inversions held) | 0 pins or each marked; 0 shared bodies as macros; 0 raw casts; one definition per structure; every rename with a recorded basis; formatting clean; N of N still byte-identical | DK-64, 65, 47, 12 |
Phases 5–7 look like planning phases and are not: each ends in a running tool, and each is the reason the campaign phase
banks at the rate it does. This project built them reactively, phases later; the bootstrap order is the single largest
lesson of its [retrospective](../retrospective.md) and of the how-to's chapter [03 Bootstrap order](../how-to-ai-decomp/03-bootstrap-order.md).
## The AI-use rules
The five conduct rules from [Contributing](Contributing-and-the-no-ROM-policy.md) are the kit's rules G61–G65, in force
from Phase 0:
1. **The byte gate is the only claim of success.** No match is reported that the gate has not proven; every "done" is
written from a tool's printed success line.
2. **Names and types are evidence-based, never guessed.** No evidence, no name; a model may propose, it may never assert.
3. **Outward text is written by a person**, the way a developer writes, after reading the target project's own AI policy.
4. **No automated traffic against community infrastructure.**
5. **Agents assist; a person owns.** Every change is justifiable by a person from the record.
## Readability at day one — the six inversions
This project reached 100% and then chartered a whole generation to make the code legible
([Where the project goes next](Where-the-project-goes-next.md)). Each item below is something it had to do *after* the
fact that a new project does at draft or bank time, gated the same way a match is (the intake's Part C, kernel DK-64):
1. **Pins are recorded at draft time, not removed later.** A draft carrying a register pin is a near-miss with its
allocation-order reading attached, not a bank; a body that cannot be shaped is banked with a `// !FAKE:` line, and the
count is a published metric from the first bank.
2. **Shared bodies live as C files per system from the first propagation**, not as macro bodies in one header.
3. **Types are canonical at bank time, and no raw address cast is banked.** A canonical type file exists from the first bank
and grows one proven field at a time; a draft may not invent a structure the file already has, every absolute address it
touches is a declared, typed symbol, and a width or signedness is proven by the bytes — the one place a type moves bytes
(DK-65: types are a *banking* lever and a *width* lever, not a codegen lever; this project measured the codegen half
correctly and underweighted the other).
4. **Names carry evidence, recorded per name**, on the same ladder as addresses.
5. **Formatting is installed with the first C file:** the community style guide's formatter and a `make format` target.
6. **File layout follows the game's systems, with unit boundaries decided at segmentation time** from the build's forced
boundaries — not by the carving tool, and not by archaeology about the original file layout.
## The compiler question
The inherited cookbook is one project's knowledge base for one compiler family. Its front page
(`decomp-architect/corpus/cookbook/README.md`) says what transfers:
- **Same family (the gcc 2.7.2 era that shipped with the PlayStation SDK):** the idioms apply directly — look the symptom
up, apply the lever, and still re-prove it on your own bytes before it enters *your* cookbook. An idiom that held on one
game's functions is a hypothesis until it holds on yours.
- **Another compiler:** the levers do not transfer; the *structure* of every entry does. An idiom is a symptom, a named
pass, a lever and a byte proof. Find your tell in the index, read which pass this project attributed it to, read the same
pass in your compiler's source (or probe it), build a five-line reproducer that shows the symptom on your toolchain, find
your lever, write your own entry in the same shape. The inherited idiom tells your agent what to read; it does not tell it
the answer (G67: translate through the pass, never copy the lever).
In both cases the compiler-agnostic parts apply unchanged: the integration classes, the instrument findings, the harvest
laws, the verbatim class, the segmentation law, and the type verdict above.
## The accelerators, one line each
Everything in [`docs/accelerators.md`](../accelerators.md) — what was learned late, when it could have been learned, what it
would have saved — in one line per entry. The kernels distil the same material with their costs; this is the index.
| When | Accelerator |
|---|---|
| Phase 26 | **A1** Instrument integrity before measurement, as a standing habit — fix the tool, then trust the number |
| Phase 12 | **A2** The whole-binary byte gate plus a parallel drafting harness, from the first byte-identical build |
| Phases 11–15 | **A3** Cross-binary dedup propagation: match once, stamp every member, gate each |
| Phase 23 | **A4** Read the compiler's source once, into a codegen map — right after the triple is pinned |
| Phase 30 | **A5** A static scanner must model the compiler's addressing forms, or it under-counts references |
| Phases 24–25 | **A6** Regroup the residue by structure before calling any of it unique |
| Phase 30 | **A7** The load map: derive who loads what from the bytes, with control rows |
| Phase 30 | **A8** Parallelism defaults for fleet-wide tools — processes for CPU work, threads for waits, batch what you already know |
| Phase 30 | **A9** Validate the target list, and let an empty tier terminate the pipeline instead of running on nothing |
| Phase 31 | A `#` comment between backslash-continued argument lines silently drops every argument below it; print the effective config on line one |
| Phase 31 | `pgrep -f <pattern>` matches your own shell; anchor the pattern or kill by pid |
| Phase 31 | `cmd \| tail -N` buffers everything until exit — a background job's progress never shows |
| Phase 31 | Telemetry that exists only in a log line is not telemetry; count it where it is read |
| Phase 31 | A running lane script does not read your edit — bash parsed the loop up front; restart it |
| Phase 31 | A 0% gate yield is a statement about the instrument until a no-input control says otherwise |
| Phase 31 | A mechanical-remap lane needs all four verdict layers wired in from day one |
| Phase 31 | **#12** Byte-locate the residual before blaming the draft |
| Phase 31 | **#13** Census what is already drafted before drawing anything |
| Phase 31 | **#14** Make the cheap probe call the real planner, not a copy of it |
| Phase 31 | **#15** The differential-oracle harness: run every question down two paths and fail on disagreement |
| Phase 31 | **#16** A "verified, just bank it" claim must name the compilation it survived |
| Phase 31 | **#17** A similarity join is probably a point when it should be a band |
| Phase 31 | **#18** A claim derived from bytes is not a claim verified by a compiler |
| Phase 31 | **#19** A verdict recorded inside an isolated environment describes the environment |
| Phase 31 | The agent journals were a labelled corpus written for thirty phases and never read back — feed them into the next card |
| Phase 31 | **#20** Set translation-unit boundaries at the data island's jump-table spans, at segmentation time |
| Phase 31 | A tool that derives a byte-exact fact from a pretty-printer inherits its liberties |
| Phase 31 | A refusal check is measured against what the real pipeline does to the input, not against a clean copy |
| Phase 31 | An exclusion reason is a claim about the tooling on the day it was written — re-probe the list after every tool fix |
| Phase 31 | The loader shipped the answer key: per-version SDK signatures name the library bands you cannot link |
| Phase 31 | Check a percentage against a case you already know the answer to |
| Phase 31 | "No single base" means "partition it", along the producer's structure |
| Phase 31 | Provenance → archive → link → compiler, in that order — a "wall" is a provenance question first |
| Phase 31 | A tool that reports "unchanged" for N cycles must prove it iterated |
| Phase 31 | A byte gate is a null oracle for "is this C?" — pasted assembly is a verbatim, not a bank |
| Phase 31 | A pointer-only callee's `extern` is a guess, not a constraint |
| Phase 31 | "banked 1 / merged 0 / refused 0 / exit 0" can be a failure that prints as success |
| Phase 31 | Agent drafters outlive the session that spawned them; harvest a dead session from its transcripts |
| Phase 32 | A coordinator that reads prose results dies mid-wave; agents return one JSON line |
| Phase 32 | A shared scratch directory is a shared blast radius; one work directory per item |
| Phase 32 | A converged multi-agent plateau is not a mechanism proof |
| Phase 32 | The rematerialisation slider is a computation, not a search — read the dump's counts |
| Phase 32 | The build is the batch verdict; a per-draft oracle is blind to cross-draft integration |
| Phase 32 | Read a permuter waypoint's diff before rejecting or accepting it |
| Phase 32 | A tool's live probe in the source tree is part of the build's input |
| Phase 32 | Re-probe a compile-failure wall in a sandbox unit, not by editing the tree |
| Phase 32 | A lever that measures worse may be a cascade |
| Phase 32 | The strongest model on the compiler-internals class banked where every prior tier had 0 — reserve it for that |
| Phase 32 | Attribute the residual to a pass with a dump line before sweeping levers |
| Phase 32 | Enumerate the artefact's producers from the compiler source before probing a single spelling |
| Phase 32 | When a same-family sibling is banked, port its spelling before touching a dial |
| Phase 32 | A similarity score is not a shape oracle — grep the idiom's constants and read the sibling's objdump window |
| Phase 32 | Re-run the producer census with the combiner's bookkeeping in view before writing "proved" |
| Phase 32 | Read the allocation order before the register; pins are symptoms |
| Phase 33.5 | An ignore file's directory-form rule is a wall no later block can climb — write the by-contents form first |
| Phase 33.5 | A check that compares a typed figure against a derived one is wrong the day the derived side moves |
| Phase 33.5 | A dry-run judge is an instrument; negative-control it before believing its FAILs |
| Phase 33.5 | A tool without a dictionary row is invisible to the project that owns it |
## The proof: four dry-run installs
The kit was installed four times into a throwaway repository by an agent that had never seen it, from an answers file,
under write-scope guardrails (nothing outside the throwaway; the real tree's dirty paths, the memory store and the
settings compared before and after), and judged by a script rather than by the agent's own report
(`.run/P33.5/kit-dryrun/judge.py`, with the answers file, the expected manifest, the install logs and the verdicts beside it).
| Run | Outcome | What it found |
|---|---|---|
| 1 | FAIL at the firewall step | ProjectArchitect's own ignore block writes the directory form `.run/`, and git never descends into an excluded directory, so no re-include beneath it can take effect; and its leftover-placeholder audit was not scoped past the installer packages' own template bodies. Two installer steps rewritten. |
| 2 | PASS 10/10 (resumed from the fixed step) | `py_compile` always writes bytecode (an in-memory compile replaced it); prose that quotes a literal placeholder trips the audit (a documented rule); the judge itself had two false FAILs — the same scoping gap it was judging, and a dirty-tree *count* where a path *set* was needed. |
| 3 | PASS 10/10, 0 defects (fresh throwaway, fresh agent, final kit) | Two honest agents produced two honest manifest sizes from the same words: the manifest is now specified as an exact derivable set. |
| 4 | PASS 10/10 after one resume (after the dictionaries were added) | The installer compared a typed figure against a derived one and stopped the day the derived side moved; both sides are now derived. The one guardrail flag was a generated timeline rewritten by a health check running at the time, not a write by the agent. |
The harness is reusable: a kit change is re-verified by resuming on the last throwaway; a fresh full run only when the
installer's steps change.
## Where it lives, and how it is kept honest
- `decomp-architect/` at the repository root, gitignored by the project it is installed into (the folder is deleted after
Phase 0.5; the methodology survives as a copy in the new project's docs folder).
- `tools/kit_lint.py` keeps it de-specialised: no line outside a calibration fence names this project, its paths, its
rule numbers or its cookbook sections; the placeholder set equals the documented contract; every script parses; the
`.gitignore` template equals the wiki page's block.
- `tools/tool_census.py --check` asserts the two dictionaries equal their sources; `make kit-corpus` regenerates them
(any edit to a tool or to the cookbook makes a copy stale until it is run).
- Both run in `make tools-health`. The split into its own repository happens after the flip; the folder lifts unchanged,
because nothing in it refers to this repository's paths.
Nothing in the kit is derived from any game.
+2
View File
@@ -11,6 +11,8 @@ documentation in the repository; the two with standalone homes are noted.
| **The decomp.me replica** | Rebuilds decomp.me's own PS1 `gcc2.7.2-psx` toolchain locally from its published recipe and runs a function through it, comparing the words to the target — a preset or a scratch is proven before it exists, and a disagreement between decomp.me and a local build names its producer. | [`tools/decompme_replica.sh`](../../tools/decompme_replica.sh), [`docs/decompme-preset.md`](../decompme-preset.md) |
| **The drafter write-up** | How a small local model was fine-tuned to draft matches under the byte gate, every measurement in order, the portable lessons, and what it was worth. The paired dataset is game-derived and not published. | [`docs/matching-drafter-pipeline.md`](../matching-drafter-pipeline.md) |
| **How to AI-decomp** | The whole method as thirteen chapters, for anyone doing this with an agent. | [Index](How-to-AI-decomp.md) |
| **The day-one decomp kit** | The order of work this project would use if it started again, packaged as a Phase-0.5 overlay on ProjectArchitect 2.0: the firewall from commit one, the rules distilled from the failures, the phase ladder with a machine-checkable milestone per phase, the conduct rules, the readability standard at draft time — and the two dictionaries: this project's tools verbatim, keyed by the need each answers, and its cookbook, symptom index and codegen map behind a front page that says what transfers to another compiler. Dry-run installed four times. Split into its own repository after the flip. | in-tree `decomp-architect/`; [Start a new decomp project](Start-a-new-decomp-project.md) |
| **The tool index** | Every tool in the tree keyed by the need it answers, with what proved it (its consumers), what it hard-codes and — for the retired ones — its successor or what it produced. Generated from the tree and an authored dictionary by `tools/tool_census.py`, with coverage asserted both ways; the same data generates the kit's manifest and its tool corpus. | [`docs/tool-index.md`](../tool-index.md) |
What is deliberately **not** offered as a tool: the ROM-derived artifacts (the disc extraction, the dumps, the Ghidra database),
the Sony SDK, and the fine-tuning dataset. See [Contributing and the no-ROM policy](Contributing-and-the-no-ROM-policy.md).
+4 -4
View File
@@ -9,8 +9,9 @@ third generation: making code that *matches* into code a maintainer would call *
The repository's history was rewritten before publication to remove every game-derived byte and force-pushed in
place. The flip itself waits on one thing outside the project's control: GitHub Support purging the old objects, which
the host's Activity view still serves for every pre-force-push tip ([The ROM firewall](The-ROM-firewall.md)). A probe
of the old hashes runs daily; the flip is gated on it printing PASS (or, if the purge stalls, on recreating the
repository under the same name).
of the old hashes runs daily and the flip is gated on it printing PASS (or, if the purge stalls, on recreating the
repository under the same name). **It printed PASS on 2026-09-07** — every sampled old hash gone, the live control still
resolving — so the gate is open and Phase 34 can proceed; the probe is run once more immediately before the flip.
After that, in order: the visibility change and the checks that follow it (the probe after the flip, the Actions tab
green, the wiki enabled — GitHub offers wikis only on public repositories on the free plan); the outward actions the
@@ -93,5 +94,4 @@ wait on a licensing decision), the Japanese release and the prototypes as extra
## What a new project takes from this
The order this project would use if it started again — and the firewall, the conventions and the conduct rules above —
are packaged as a day-one kit for the next decompilation, described on the wiki page *Start a new decomp project* once
Phase 33.5 ships it.
are packaged as a day-one kit for the next decompilation: [Start a new decomp project](Start-a-new-decomp-project.md).
+1
View File
@@ -11,6 +11,7 @@
- [Verification and progress](Verification-and-progress.md)
- [Contributing and the no-ROM policy](Contributing-and-the-no-ROM-policy.md)
- [Tools from this project](Tools-from-this-project.md)
- [Start a new decomp project](Start-a-new-decomp-project.md)
**Working conventions**
- [Docs and scratch conventions](Docs-and-scratch-conventions.md)
+132 -68
View File
@@ -53,7 +53,7 @@ in-tree links to `docs/wiki/<Page>.md`. 8. `.run/`: only what git tracks; no sca
- [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
- [x] **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 — see Log 2026-09-07 Task 13
- [x] **13.5** *(added 2026-09-07 by Drew — plan amendment, P5d; AMENDED the same day after the dry-run: the dictionaries, in-tree)* **Tools audit + the derived tool index + the two corpora as dictionaries:** `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 · REFERENCED · ORPHAN; PORTABLE vs PROJECT-ONLY) and its ladder phase; coverage-asserted against `find` (R32) → the generated `docs/tool-index.md` (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) whose rows are **dictionary entries keyed by the NEED they answer** (what · when the need shows up · why — the SETUP row's incident · what proved it — its consumer/control · what to adapt — the hard-codes); the kit's `tools/MANIFEST.md` RE-DERIVED from the census (`--manifest`, byte-equality asserted); 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), 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 census proves 0 consumers, an archive-index-style row per tool, its SETUP row moved to a retired section; Drew reviews and deletes later. **The dictionaries (Drew, 2026-09-07, confirmed in-tree now):** `tool_census.py --corpus` materialises the tools VERBATIM into `decomp-architect/corpus/tools/<phase>/` (LIVE + REFERENCED portable tools and the project-only shape references; retired one-offs out; superseded ones as a pointer file naming the successor) and the knowledge base VERBATIM into `decomp-architect/corpus/cookbook/` (the cookbook, its symptom index, the codegen map) behind one front page stating what transfers (gcc 2.7.2 family = direct use, re-proven on the new bytes; other compilers = the symptom → the named pass → read the same pass in your compiler → a five-line reproducer → your lever); both copies regenerated by a `make kit-corpus` target and asserted EQUAL to the live files in tools-health (no drift, R51); `kit_lint` exempts `corpus/tools/` and `corpus/cookbook/` from the de-specialisation check (evidence, verbatim) and asserts coverage (every corpus file has an index entry) — the ROM audit covers them like everything else; the new project installs only the index + the front page + an ops-setup row naming the corpus (SETUP Step 6; its row count derived from the manifest header, no typed 325). **Two memory seeds + two registry rules** in the kit: consult-the-tool-dictionary-first (before designing or debugging a tool, look the need up; the proven implementation is the jumping-off point, its incident row the failure mode to avoid) and translate-the-source-idiom (a symptom + a named pass + a lever + a byte proof; translate through the pass, never copy the lever; re-prove on your bytes) — G66/G67 in `registry-E.decomp.md`, cited from the ladder's Phase 7 row and the methodology. **A five-tool layout-contract probe** (the corpus oracle, `match_one`, `rtu_match`, `harvest_verify`, `dedup_propagate`: count the layout assumptions — paths, aliases, config names, make targets) → `decomp-architect/templates/layout-contract.md` (a draft; stamping it at Step 4 is a split-phase decision) — xHigh (the ORPHAN review draft is breadth-shaped: one read-only Explore agent, verified against the consumer list) — verify: rows == `find` count; `tool-index --check` green; every retired tool has 0 consumers AND a named successor or product; MANIFEST regenerated byte-equal; the two corpora equal to their sources; `kit_lint` OK; `doc_links --strict` rc 0; the dry-run's Step 6 re-verified by a resume on the run-3 throwaway; `make tools-health` OK (detached) — see Log 2026-09-07 Task 13.5
- [ ] **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 — **AMENDED S91 (Drew): also implement the types hindsight into the kit per `docs/decision-log.md` "P33.5 S91-b" items (a)–(e): DK-65, the Phase-6 milestone's canonical type layer, G62 extended (or G68), the type tools' need-keys re-pointed at Phase 6, the cookbook front page's width sentence, one paragraph in the methodology; then `make kit-corpus` + `tool_census --check` + `kit_lint`**
- [x] **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 — **AMENDED S91 (Drew): also implement the types hindsight into the kit per `docs/decision-log.md` "P33.5 S91-b" items (a)–(e): DK-65, the Phase-6 milestone's canonical type layer, G62 extended (or G68), the type tools' need-keys re-pointed at Phase 6, the cookbook front page's width sentence, one paragraph in the methodology; then `make kit-corpus` + `tool_census --check` + `kit_lint`** — see Log 2026-09-07 Task 14
- [ ] **15** Close: real render; tools-health foreground; `doc_links --strict`; `audit_public`; `PhaseEnd_Phase33.5.md` + DIGEST §0/§2 + log archive; left for Drew — Max (Tier 1, WAIT for gate 2)
## Blockers
@@ -670,86 +670,150 @@ coordinator's cost was the census tool, the dictionary seed, two derived-check r
verdict overrides (recorded); run 4 needed a resume for a check of my own making; the ORPHAN count moved 91 → 94 → 31 as the
instrument replaced the ad-hoc scan and the retirements landed.
## 🛑 SESSION CHECKPOINT — Tasks 0–13 and 13.5 ✓; NEXT = task 14 (the wiki page `Start-a-new-decomp-project.md` + the README/Tools rows + the kit's SETUP rows; **xHigh**; a FRESH SESSION — S91 ended at 85% context)
### 2026-09-07 — Task 14 — The S91-b kit edits, the wiki page `Start-a-new-decomp-project.md`, the rows (xHigh; S92)
**The kit first (decision-log "P33.5 S91-b" items (a)–(e), implemented, not re-recorded):** (a) `corpus/decomp-kernels.md` **DK-65**
"Types are a banking lever and a width lever, not a byte lever" — the kernel (a type name never moves a byte, measured early and
correctly; banking was the bottleneck and declaration conflicts a large share of it; width/signedness the one place a type does move
bytes and the permuter cannot reach it; the discipline = a canonical type file from the first bank, one proven field at a time,
widths fixed by the bytes at bank time, no duplicate definition or raw address cast banked; it shortens no crack), when it applies
(Phase 6), the cost, the calibration fence (0 better / 10 same / 2 worse on the 12-function sample; ≈92% byte-correct / ≈27% banked;
1,232 definitions; 143 raw casts; the width class of the last hand cracks), provenance; the Coverage section reads "DK-64 … DK-65 —
2 kernels" and gained an **"In all: DK-1 … DK-65 — 65 kernels"** line. (b) `intake.decomp.md` row 6's milestone gains the canonical
type layer (one definition per shape; widths and signedness proven by the bytes at bank time; a bank refused for a duplicate
definition or a raw address cast), its tools column the type file + the bank-time check ("the type lifter and the signature
reconciler start here, not at Phase 10"), its rules G62 (its bank-time clause), its earned-by DK-65; row 10's title now says it is
short when Part C AND Phase 6's type layer held, earned-by gains DK-65. (c) `templates/registry-E.decomp.md` **G62 extended** (kept
G1–G67, no renumber) with the bank-time paragraph and a provenance addendum. (d) `config/tool_dictionary.tsv`: the phase column is
ONE token (`tool_census.PHASES`; the corpus directory derives from it), so `lift_types.py` and `canon_sig_reconcile.py` moved
**P10 → P6** and all five need-keys (`lift_types`, `canon_sig_reconcile`, `sync_tu_decls`, `decl_prior`, `conform_decls`) name the
canonical type layer at Phase 6 ("again at readability (Phase 10)" where true); `corpus/cookbook/README.md`'s "In both cases"
bullet gained the type verdict sentence (a NAME never moves a byte; a WIDTH or SIGNEDNESS is the one place a type does; the permuter
cannot change a type, so a width near-miss is fixed at the declaration, never by a dial). (e) `decomp-architect.md` part 6 gained
the paragraph "Types — the two-sided verdict" (+ two fence lines); its Coverage line and the kit README read DK-1 … DK-65. **Two
findings fixed on the way (R75/accelerator S91-(2) class):** `SETUP.md` Step 6 asserted `grep -c '^### DK-' … = 64` — a TYPED figure —
now "equals the 'In all' figure of that file's own Coverage section (both derived)"; and the kit README's install table and package
tree did not name the two dictionaries or `templates/layout-contract.md` (added — the page describes the final kit, so the README
must too). `make kit-corpus` → 293 tool files, 302 copies + 28 pointers, INDEX.md, MANIFEST + tool-index regenerated (git sees the
two moves as renames under `corpus/tools/P6/`).
**The wiki page** `docs/wiki/Start-a-new-decomp-project.md` (≈230 lines): the three steps from the kit README (+ the `answers:`
clause); what it installs (a 7-row table) and what it does NOT — the two dictionaries in their place (the tool corpus keyed by need,
linking the live tool index; the inherited knowledge base behind its front page; G66 named); the ladder as an 11-row table (phase ·
milestone in one line · earned by, with row 6 carrying the type layer); the five AI-use rules (G61–G65); the six inversions (item 3
carries DK-65 and the raw-cast → declared-symbol step); the compiler question (same family = direct use + re-prove; other = translate
through the pass, G67); **the accelerators as a one-line-per-entry table — 58 rows** (A1–A9, the seven harness wounds, #12–#19, the
journals, #20, the three S77, the two S78, the two S79, the five S80, the sixteen P32 T3/T4, the four P33.5 S91), each with the phase
it was found in; the four dry-runs as a table (run · outcome · what it found); where it lives and how it is kept honest (kit_lint,
tool_census --check, kit-corpus, tools-health, the split). Links: wiki pages relative; `docs/` only at Reference-index targets
(`../tool-index.md`, `../accelerators.md`, `../retrospective.md`, the how-to chapter); the kit by backticked path; ProjectArchitect by
the URL the README already uses; `.run/P33.5/kit-dryrun/judge.py` cited (TRACKED). **The citation trap, re-hit and fixed:** the first
draft cited the NEW project's `docs/decomp-architect.md` and `doc_links` read it as a path in THIS repo → BROKEN (the task-7 lesson:
name a foreign path in prose, never as a backticked `docs/…` path). **The rows:** `_Sidebar.md` (under "Using the project") + `Home.md`
(table row); `Tools-from-this-project.md` two rows (the kit; the tool index → `docs/tool-index.md`); `README.md` two bullets (the kit
→ `decomp-architect/README.md` + the wiki page; the tool index); `docs/SETUP.md` one row for `decomp-architect/` after the
`tool_census` row (what it is, the checks, the dry-run harness, R21); `Where-the-project-goes-next.md` (the probe PASSED 2026-09-07 —
the gate is open, re-run once before the flip; the kit pointer → a link to the new page); `docs/phase34-seed.md` (task 0 PASSED
with the log path — a DEFAULT doc, an untracked citation is allowed there; the 33.5 note: the kit carried WHOLE through the flip,
split later as xsig was). No decision-log/accelerators entry written (both already banked in S91; nothing new was earned that the
S91 entries do not carry).
**Verify (literal):** `wiki_render --selftest`: 12 cases, 0 failed; reachability **32 pages, 0 unlisted** · `doc_links --strict`:
**58 documents, 451 links, 0 pending, 0 broken; citations 564 (439 tracked / 125 untracked); coverage 65 of 65; OK** (2 wiki-first
warnings, unchanged) · `kit_lint`: OK (leak 0 over 379 files; placeholders 22 == 22; syntax 0/284; gitignore 75 identical;
`TODO(platform)` 8, `TODO(phase-N)` 38) · `tool_census --check`: 302 copies + 28 pointers, 0 gaps, OK · every DK id cited in the kit
resolves (65 defined, 65 cited, 0 dangling) · `audit_public --paths` over the four largest touched files: OK · `gitignore_template_check`
OK. `make tools-health` NOT run for this task (docs + kit only; task 15 runs it as the close's gate). No build input changed.
**Session note (S92):** the log entry was dropped once by a stale slice index while rewriting the checkpoint and re-inserted — the
grep for the entry's heading before the commit is what caught it (R66's shape: verify the artefact, not the intent).
## 🛑 SESSION CHECKPOINT — Tasks 0–14 ✓; NEXT = task 15 (the close: real render, tools-health, `doc_links --strict`, `audit_public`, the P7 walk, `PhaseEnd_Phase33.5.md` + DIGEST §0/§2 + the log archive; **Max — Tier 1, prompt Drew (R27) and WAIT for gate 2**)
### 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–13 and 13.5 completed and task 14 in progress.
You are a FRESH SESSION (or this one, continuing) 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–14 completed and task 15
in progress. Task 15 is **Max** — state the Tier 1 prompt and wait for `/effort max` before starting it.
### 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 task 15 — prompt at that transition, R27; task 14 is 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`;
amendment 1 (13.5 added) = `6fb2bc7f8`; task 12 = `4c1d5d9f7`; task 13 = `a291c2b47`; amendment 2 (the dictionaries) = `3307775e5`;
task 13.5 = the commit after this block (S91, 2026-09-07). No build input changed; the fleet is 218/218 at the Phase-33 close;
**`make tools-health` OK on this tree at task 13.5** (`.run/P33.5/tools_health_t135.log`). `doc_links --strict` rc 0; pending list
empty; `kit_lint` OK; `tool_census --check` OK; `audit_public` OK (6,842 paths). **The kit is complete, dry-run-proven four times, and
now carries the two dictionaries in-tree** (Drew, confirmed S91): `corpus/tools/` (302 verbatim copies + 28 pointers + INDEX),
`corpus/cookbook/` (cookbook + index + codegen map + front page), G1–G67, 18 memory seeds, `templates/layout-contract.md` (a draft).
**The tools folder is audited:** 293 live tool files + 34 retired under `tools/sunset/` (README = the ☐ review table; deletion is
Drew's), `config/tool_dictionary.tsv` the authored record, `docs/tool-index.md` the generated need-keyed index. **Phase 34's gate is
OPEN:** the purge probe PASSED on 2026-09-07 (`.run/P33.5/probe_github_s91.log`) — the flip can proceed in Phase 34.
**Already banked — task 14 must NOT write these again:** `docs/decision-log.md` entries "P33.5 S90", "P33.5 S91" AND "P33.5 S91-b" (the types hindsight — task 14 IMPLEMENTS its items (a)–(e) in the kit, it does not re-record them); the
`docs/accelerators.md` "P33.5 S91" entry (four accelerators); the SETUP rows for `kit_lint.py`, `tool_census.py`, the retired-tools
section. 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 below — this file
is the one that counts.
**Phase 33.5** (sub-phase; v1.32.0 → v1.32.1), gate 1 approved 2026-09-07 by Drew in plan mode at Max. 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`; amendment 1 = `6fb2bc7f8`; task 12 = `4c1d5d9f7`; task 13 = `a291c2b47`; amendment 2 = `3307775e5`;
task 13.5 = `827295e24`; S91-b decision-log entry = `3c4e185fe`; **task 14 = the commit after this block (S92, 2026-09-07)**. No build
input has changed in this phase; the fleet is 218/218 at the Phase-33 close; the last `make tools-health` OK on this tree was at
task 13.5 (`.run/P33.5/tools_health_t135.log`) — task 14 changed docs + the kit + `config/tool_dictionary.tsv` + the generated
`docs/tool-index.md` only, every per-tool check green (task-14 log). `doc_links --strict` rc 0; pending list EMPTY; `kit_lint` OK;
`tool_census --check` OK; render selftest 32 pages / 0 unlisted. **Every plan task except the close is done:** the wiki is the
source of truth (five new pages: conventions, firewall, reference index, direction, start-a-new-project; the archive index), 59
docs + 34 tools sunset with indexes, tracked `.run/` 1,086 → 868, the memory store reconciled, the kit complete with the two
dictionaries and DK-65 / the type layer (S91-b) — dry-run-proven four times. **Phase 34's gate is OPEN** (the purge probe PASSED
2026-09-07, `.run/P33.5/probe_github_s91.log`, untracked). 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 below — this file is the one that counts.
### 2. What NEXT does (task 14, **xHigh**) — exact steps (plan D1 "Start a new decomp project" + the task-14 row)
**Read first:** `docs/wiki/_Sidebar.md`, `docs/wiki/Home.md`, `docs/wiki/Tools-from-this-project.md`, `docs/wiki/Where-the-project-goes-next.md`
(its day-one-kit pointer paragraph), `docs/wiki/Docs-and-scratch-conventions.md` §"Links" (the link policy: a wiki page links `docs/`
only at a Reference-index target; forward links via `docs/doc_links_pending.txt`), `decomp-architect/README.md` (the install steps, what
it installs and does NOT, the corpus findings), `decomp-architect/intake.decomp.md` Part B (the ladder table) and Part C (the six
inversions), `decomp-architect/corpus/cookbook/README.md` (what transfers), `docs/accelerators.md` (the entries → a one-line-per-entry
table), `README.md` ("Tools from this project"), `docs/SETUP.md` (the row shape).
**Write, FIRST (the S91-b amendment — the kit edits, so the wiki page describes the final kit):** (0) per `docs/decision-log.md`
"P33.5 S91-b" items (a)–(e): `corpus/decomp-kernels.md` gains **DK-65** (types are a banking lever and a width lever, not a byte lever; the
Phase-17 measurement 0/10/2 and the 1,232-definition cost in its calibration fence; coverage line 64 → 65); `intake.decomp.md` Part B
row 6's milestone gains the canonical type layer (one definition per shape; widths proven at bank time; a bank refused for a duplicate
definition or a raw address cast) and row 10 notes it is short when row 6 held; `templates/registry-E.decomp.md` G62 extended with the
bank-time refusal (keep G1–G67 — extend G62's text rather than renumber); `config/tool_dictionary.tsv`: the need-keys/phases of
`lift_types.py`, `canon_sig_reconcile.py`, `sync_tu_decls.py`, `decl_prior.py`, `conform_decls.py` say Phase 6 (the multiplier) as well as
P10; `corpus/cookbook/README.md` one sentence naming width/signedness as the one place a type moves bytes; `decomp-architect.md` part 6
one paragraph with the two-sided verdict. Then `make kit-corpus`, `tool_census --check`, `kit_lint`, `doc_links --strict`. Then:
**Write:** (1) `docs/wiki/Start-a-new-decomp-project.md` — the three steps verbatim from the kit README (install ProjectArchitect 2.0
handing it `intake.decomp.md`; copy `decomp-architect/`; "Read decomp-architect/SETUP.md and do it"); what it installs / does NOT
(no tools installed — the two DICTIONARIES instead: the verbatim tool corpus keyed by need, the inherited cookbook + index + codegen map
behind its front page; the memory seed; G1–G67); the hindsight ladder as a compact table (phase · milestone · earned by); the AI-use
rules (the five); the Gen3-at-day-one inversions (six, incl. raw casts → declared symbols); the accelerators as a one-line-per-entry
table; the compiler question (same family = direct use + re-prove; other = translate through the pass); the four dry-runs as the
proof (runs 1–4, what each found); links: wiki pages by relative `<Page>.md`, the kit by backticked path (it is not a `docs/` file —
the kit README is in `doc_links`' DEFAULT set; do NOT link `decomp-architect/` files from a wiki page unless the Reference index lists
them — cite paths). Sidebar row under "Using the project" or a new "Start a new decomp project" entry; a Home.md row. (2) README:
a "Tools from this project" row for the kit (`decomp-architect/` — the day-one kit; the two dictionaries; the tool index) and one for
`tools/tool_census.py` if the section lists tools; `docs/wiki/Tools-from-this-project.md`: rows for the kit and for the tool index
(`docs/tool-index.md` is a Reference-index target — linkable). (3) `docs/SETUP.md`: a row for `decomp-architect/` (the package: what
it is, how it is checked — `kit_lint`, `tool_census --check`, `gitignore_template_check`, the dry-run harness under
`.run/P33.5/kit-dryrun/` with `judge.py`), R21. (4) `docs/wiki/Where-the-project-goes-next.md`: the kit pointer paragraph → a link to
the new page; the Phase-34 paragraph notes the probe PASSED 2026-09-07. (5) `docs/phase34-seed.md`: note the probe PASS and that the
split phase carries `decomp-architect/` whole (the corpus is generated in-tree; `make kit-corpus`). **Verify:** `wiki_render --selftest`
(the new page reachable — 32 pages); `doc_links --strict` rc 0 (register any forward link in the pending file in the same commit;
none expected); `kit_lint` OK; `tool_census --check` OK (if any tool moved). Log + checkpoint; commit by explicit path. Then **task 15
is Max — prompt Drew (R27)**; task 15's checklist is the plan's row 15 + the P7 walk of the milestone's six items + the R18/R25 recap
+ the PhaseEnd's rule candidates (this phase produced: the ignore-form wall; a typed figure vs a derived one; the judge as an
instrument; a tool needs a dictionary row; re-run `doc_links --strict` after any untrack; an unattended installer's manifest is a
derivable SET; the class-7 line for a governance system that keeps transcripts in the repo).
### 2. What NEXT does (task 15, **Max**, Tier 1 — the plan's row 15 + the Phase Boundary Protocol) — exact steps
**Prompt first (R27):** "🟡 PhaseEnd creation is a Tier 1 task — confirm **effort: Max** is set." WAIT for `/effort max`.
**Then, in order:**
1. **A real render:** `.venv/bin/python tools/wiki_render.py --out .run/P33.5/wiki-render/` (check `--help` for the exact flag; the
selftest is not the real run) → exit 0, every page rendered, no RenderError; record the page count (32 + 13 chapters).
2. **`make tools-health`** — it runs LONGER than the 10-minute foreground cap: launch DETACHED (`setsid nohup make tools-health >
.run/P33.5/tools_health_t15.log 2>&1 < /dev/null &`), then wait on the pid from a background Bash (never a harness background task,
never sleep-poll). Its report step regenerates `docs/story-timeline.md` (+ `.svg`) — a generated file, commit it (R75). Read the
whole log: sigs fresh · sdk-dual both legs `143dbb89…` · corpus 0 PHANTOM / 0 TRUNCATED · cdecl · audit-binaries 218/218 ·
report + audit-digest (timeline `--check`) · cookbook-index · gccmap_cites · roster · `doc_links` · `wiki_render --selftest`
· `gitignore_template_check` · `kit_lint --selftest` + run · `tool_census --check` · xsig 8/8 · work_evidence · split_indicator
218/218 · the final OK line. (The plan said "foreground, ~15-min timeout"; task 11's log records why it is detached.)
3. `doc_links --strict` rc 0 (0 pending — the list must be EMPTY at a PhaseEnd, R80); `tools/audit_public.py` OK over every tracked
path (the corpus included; ~6,845); `git status --short` clean apart from the deliverables of this task.
4. **The P7 walk of the six milestone items** (top of this file), each with the command and its literal output: (1) coverage ⊆ +
`--strict` + the real render; (2) `comm -3` of the Archive-index paths / `docs/sunset/README.md` / `git ls-files docs/sunset`
(59 = 59) and `tools/sunset/README.md` vs `git ls-files tools/sunset` (34); `git log --follow` on three samples; (3)
`git ls-files -ci --exclude-standard .run | wc -l` = 0; `git status --porcelain .run | grep -c '^??'` = 0; the two listings named
in `tools/public_rewrite/untracked_after_rewrite.txt`; `purge_set.txt` unchanged since `80d45b29b` (`git diff 80d45b29b --
tools/public_rewrite/purge_set.txt` empty); `gate_scan.py --all --worktree` PASS (73 s at task 8 — re-run or cite); (4)
`kit_lint` OK + the run-4 judge verdict (`.run/P33.5/kit-dryrun/verdict.json` PASS 10/10, manifest 56 == 56) — the S91-b kit
edits changed no SETUP step, so NO fresh dry-run is owed (a resume on `repo/` is optional, not required); (5) `ls
~/.claude/projects/-home-musashi-bfm-decomp/memory/*.md | wc -l` == the `MEMORY.md` row count (80 == 80 at task 9; re-count) and
`decomp-architect/memory-seed/` 18 files == its index rows; (6) this item is the PhaseEnd itself.
5. **`phase-ends/PhaseEnd_Phase33.5.md`** — the constitution's format + the narrative axis (Build Log with every file/tool, the
literal verification lines, the milestone; Deviations table; "What we believed, what failed, what we would do sooner";
Commit Message; Rules Added — R74–R83 ratified at gate 1, then the **candidates** this phase produced: (i) an ignore file's
directory-form rule is a wall no later block can climb — write the by-contents form first; (ii) a check that compares a typed
figure against a derived one is wrong the day the derived side moves — derive both sides (`SETUP` Step 6, twice: the manifest
total and the DK total); (iii) a dry-run judge is an instrument — negative-control it before believing its FAILs; (iv) a tool
without a dictionary row is invisible to the project that owns it — a new tool ships with its row (`tool_census --check`);
(v) re-run `doc_links --strict` after ANY untrack or archive move, not only after a docs edit; (vi) an unattended installer's
manifest is specified as a derivable SET, or two honest agents produce two honest sizes; (vii) a governance system that keeps
transcripts in the repository needs the firewall's class-7 line (a decomp's transcripts quote the target); (viii) a foreign
project's path is named in prose, never as a backticked `docs/…` citation (the checker reads every such citation as this repo's) —
plus the S91-b doctrine as a candidate if Drew wants it as a rule: types are a banking and width lever, the canonical type file
from the first bank; PhaseEnd Changelog v1.32.0 → v1.32.1; **the Plain-English Recap (R18/R25)**; 🛑 Stop Here).
6. **DIGEST §0 + §2 append** (the P33.5 synopsis: what it delivered, the key findings, "R74–R83 ratified at gate 1", the candidates);
§0's status paragraph updated (33.5 CLOSED at v1.32.1; Phase 34 next, its gate OPEN); §4 already reflects the wiki.
7. `git mv phase-ends/CURRENT_PHASE.md phase-ends/logs/Phase33.5.md` (R19). **Leave the PhaseEnd + the archived log + the DIGEST edit
+ the tools-health log UNCOMMITTED for Drew's milestone-close commit (R6);** commit nothing else after step 3's generated timeline
(that one goes in the task-15 prep commit BEFORE the PhaseEnd is written, so Drew's close commit carries only the close).
8. Final message: the plain-English recap + "PhaseEnd file created. Commit the file and start a new Claude Code session for the
next phase." HARD STOP — do not preview Phase 34 (its seed is `docs/phase34-seed.md`; plan mode, Max, fresh session).
**P6 count:** rules checks were done after tasks 4, 8 and 12; tasks 13, 13.5 and 14 are three since — task 15 opens with the
fourth check ("Rules check — re-read complete. Continuing with task 15.").
### 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).
- Forward links from any new wiki page go into `docs/doc_links_pending.txt` as `<path>\t<task N>` in the SAME commit; the render
refuses dead relative links (exit 1); `tools/doc_links.py` non-strict is in tools-health; `--strict` at task 15 — **and after
any untrack or archive move** (task 10's finding).
any untrack or archive move** (task 10's finding). **A backticked `docs/…` or `.run/…` path in a wiki page is a citation of THIS
repo and must be TRACKED — name a foreign project's path in prose** (task 7 and task 14 both hit this).
- 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`; for TOOLS the census is `tool_census.py --consumers FILE`.
- `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 task 15; xHigh for task 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);
the two corpus directories are verbatim evidence (lint-exempt, syntax-checked, coverage by `tool_census --check`).
- **Any edit to a tool under `tools/` or to the cookbook/codegen map makes its corpus copy stale: run `make kit-corpus` and re-stage
`decomp-architect/corpus` before committing** (`tool_census --check` in tools-health refuses otherwise).
- Effort transitions are prompted and waited for (R27): Max for task 15.
- The kit's vocabulary (task 10): rules by G-id, kernels by DK-id (DK-1 … DK-65 since task 14; the kernels file states its own
total and SETUP Step 6 compares against it), 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); the two corpus
directories are verbatim evidence (lint-exempt, syntax-checked, coverage by `tool_census --check`); the dictionary's phase column
is ONE token of `tool_census.PHASES` (a tool lives under exactly one `corpus/tools/<phase>/`).
- **Any edit to a tool under `tools/`, to the cookbook/codegen map, or to `config/tool_dictionary.tsv` makes a corpus copy stale: run
`make kit-corpus` and re-stage `decomp-architect/corpus` + `docs/tool-index.md` + `decomp-architect/tools/MANIFEST.md` before
committing** (`tool_census --check` in tools-health refuses otherwise; `write_corpus` rmtree's `corpus/tools/` and rewrites it).
- **`make tools-health` runs longer than the 10-minute foreground cap:** launch it detached (`setsid nohup make tools-health >
.run/P33.5/<log> 2>&1 < /dev/null &`), then wait on the pid from a background Bash; never as a harness background task; never
sleep-poll in the foreground. Its report step regenerates `docs/story-timeline.md` (a generated file — commit it).