# Phase 0 — Verification gates Detail for [`PLAN.md`](PLAN.md) Phase 0. **Nothing in Shipwright changes until every gate here is green.** All work happens in [`briaguya0/zapd-to-torch-test-harness`](https://github.com/briaguya0/zapd-to-torch-test-harness). --- ## Why there are gates at all The harness proves 14/14 byte-for-byte parity — but for exactly **one** build of Torch, driven exactly **one** way: | | Harness measured | Shipwright will use | |---|---|---| | Build kind | executable (`USE_STANDALONE=ON`) | static lib (`OFF`) | | Games compiled in | all 9 (defaults) | OoT only | | Build type | `Debug` (`-g`) | `Release` (`-O3`) | | Driver | `main.cpp` + CLI11 | our own `Companion` calls | | Extractions per process | one | up to two (vanilla, then MQ) | | `soh.o2r` | n/a (OTRExporter makes it) | a new in-tree packer | Every row is an unproven variable. Each gate closes exactly one of them, **one at a time**, so a failure names its own cause. Running only the final combination would tell us "something broke" without saying what. Reading the source says all six should be fine. Reading is how we got here; running is how we know. --- ## Preconditions - Everything builds inside the **`soh` distrobox** (`distrobox enter soh`) — `cmake`, `ninja`, and the compilers are not on the host `PATH`. - Harness at `~/code/zapd-to-torch-test-harness`, submodules initialised. - `roms/` populated: **19 ROM dumps → 14 version directories** (`ntsc_1-0`, `ntsc_1-1` and `ntsc_1-2` have two dumps each; `pal_mq_dbg` has three). *(`PLAN.md` says 17 hashes in a couple of places — it's 19. Corrected there.)* - `assets/yml/` generated: 20,353 `.yml` / 119 MB across the 14 version dirs, plus the committed `config.yml`. Gitignored — regenerate with `zapd_to_torch.py` if absent. - `o2r/` holds all 19 OTRExporter reference archives (one per ROM dump, from Shipwright `95d8f7e`). - Existing baseline build at `torch/build/` (`USE_STANDALONE=ON`, all games ON, `Debug`, `PORT_VERSION_ENDIANNESS=ON`) — leave it alone; it *is* the control. --- ## How the gates are actually run **Do not use `tools/test_assets.py` for these gates.** It hardcodes `TORCH` to `torch/build/torch`, and it copies a *filtered subset* of the yml into a scratch dir (1,320 of 1,450 files for `pal_gc`) — which is not the invocation SoH will make. It's the right tool for bisecting a single failing asset, not for proving a configuration. Use the **full-tree + `check.sh`** path instead. It points Torch at the entire yml tree — the same shape as Phase 1's `srcdir = assets/` — and diffs the two archives file-by-file: ```sh OUT=$(mktemp -d) # fresh every run — see below "$TORCH_BIN" o2r -s assets/yml -d "$OUT" -u 9.2.3 roms/.z64 cp "$OUT/oot.o2r" o2r/torch.o2r cp "o2r/.o2r" o2r/reference.o2r ./check.sh # missing / extra / mismatched, all three ``` `check.sh` never invokes Torch, so it takes any binary — Gate A's driver drops straight in with no harness patching. > **The fresh destdir is mandatory, not hygiene.** `Process()` writes `destdir/torch.hash.yml` and > reads it back on the next run to skip unchanged files. Reuse a destdir and the second run > silently produces a partial archive. (This is the same constraint that forces Phase 3's > `Mkdtemp()`.) ### New: `tools/matrix.sh` One script, used by every gate: ```sh tools/matrix.sh