# 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 **`tools/test_assets.py`, unfiltered — the same tool that produced the existing 14/14.** Using anything else would make the gate results not directly comparable to the baseline they're being measured against. An unfiltered run is a genuine full-tree, both-directions comparison: - `list_assets` with no `--category/--file/--type` returns **every** key in `manifests/.json` — all 35,386 for `pal_gc`. - `collect_yaml_files` reverse-maps those asset paths to yml files (1,320), then `setup_scratch`'s `copy_yaml_with_externals` recursion follows `external_files:` and pulls in the remaining 130 — **all 1,450 land in the scratch dir.** Verified by replaying the logic: `copied == on-disk`, zero yml files omitted. - It hashes what Torch produced and diffs it against the manifest in *both* directions — `not generated` (in the reference, missing from ours) and `not in reference` (extras, computed over the whole zip, not just the filtered set). - The destdir is a fresh `mkdtemp` per run, which matters: `Process()` writes `destdir/torch.hash.yml` and reads it back next run to skip unchanged files. Reuse a destdir and the second run silently produces a partial archive. (Same constraint that forces Phase 3's `Mkdtemp()`.) > The `Copying 1320 YAMLs to scratch dir` line in the logs is printed *before* the `external_files` > recursion runs — it's the pre-recursion count, not what actually gets copied. Easy to misread as > a filtered subset. It isn't one. **One harness patch is needed:** the torch binary path is hardcoded in two places — `tools/test_assets.py:34` and `lib.sh:12`. Make both honour a `TORCH_BIN` environment override so Gate A's driver can be dropped in without editing files between runs: ```python TORCH = os.environ.get("TORCH_BIN") or os.path.join(SOH_DIR, "torch", "build", "torch") ``` `./check.sh` stays as the secondary whole-archive check — it compares two extracted `.o2r` directly, so it's the tool to reach for if a gate fails and you want the raw file-list diff rather than a per-asset table. ### New: `tools/matrix.sh` There's no 19-ROM loop script today; every gate needs one. It's a thin wrapper, not new comparison logic: ```sh TORCH_BIN= tools/matrix.sh