### Headline decode tests fail on a missing input instead of passing

- The `int_hyper` tests over the pretrained mbt2018_mean (`int_hyper_synth`,
  `int_video_sota_keyframe`) and the JPEG-AI whole-decoder tests
  (`jpegai_e2e_full`, `jpegai_reconstruction_binding`, `jpegai_live`) read inputs
  from outside the tree, and used to `return` — reported as a pass — when those
  were absent. With
  `WAI_REQUIRE_SOTA_VECTORS=1` a missing input is now a failure that names the
  tool producing it; without it the skip is written to the process's real stderr,
  so it shows in an ordinary `cargo test` run. Either way, a corrupt input file
  fails, and so does a variable that names inputs which are not all there: a
  path that does not exist (`WAI_JPEGAI_CODESTREAM`/`_WEIGHTS_DIR`/`_NORM`, even
  when another of the three is unset), or a directory that does not exist or
  lacks a file the test reads (`WAI_SOTA_INT_DIR`, `WAI_JPEGAI_ASSETS`, the
  JPEG-AI weights directory). So without the switch a test skips only when no
  variable names what is missing: one of the three path variables is unset, or
  `WAI_SOTA_INT_DIR` or `WAI_JPEGAI_ASSETS` is unset or empty and its default
  directory (`/tmp/sota_int`, `../jpegai-vm-assets`) is absent or incomplete.
  The CI jobs always set the switch, so the new test
  `require_vectors_rule` checks this rule without it: it runs the helpers in
  child processes with the switch and the variables set per case, and
  `wai-sota-vectors.yml` runs it.
- New CI job `wai-sota-vectors.yml` regenerates the mbt2018_mean integer vectors
  from pinned inputs (`tools/wai_sota_vectors.sh`, the Python stack in
  `tools/requirements-sota-int.txt`, a public-domain photograph pinned by SHA-256,
  the published checkpoint pinned by its full SHA-256) and runs those tests
  with the switch set. It is triggered by changes to the decode path and by a
  weekly schedule. Besides requiring each test by name, it fails if the test log
  contains a skip banner, since a skipped test also reports `ok`. The export tool
  checks the checkpoint's bytes before loading them (as tensors only), because the
  model zoo's own download path checks no hash. The job checks the Rust decode
  against the Python integer reference on one runner; cross-architecture
  byte-equality remains the committed tiny vector's job in
  `wai-byte-equality.yml`. The regenerated vectors are not portable, and part
  of them is not repeatable run to run on every machine. Between an arm64
  macOS machine [name removed 2026-09-30] and the x86_64 runner, the synthesis-only test's input latent,
  which the float model computes, differed, and with it its expected
  `rgb_hash`; each side wrote the same latent in all of its runs. Two runs on
  the one runner wrote different `cond.json` and `int_synth_sota.json`, most
  likely in the float decode's PSNR, which only the quality test reads, against
  thresholds. The PNG bytes of the source also differed between the Mac and the
  runner; the PNG encoder writes them from the pinned pixels before any model
  runs, and the pixels matched. So no expected hash of the regenerated vectors
  is pinned in the repository (the committed tiny vector's is, in
  `tests/vectors/int_hyper/tiny.json`); each run checks the hashes its own export
  wrote, and a hash from one run's vectors must not be pinned for another run,
  on the same machine or another. The pins that hold across machines are on the
  inputs: the photograph's pixels and the checkpoint's bytes.
- New test `integer_decode_keeps_the_float_codec_quality`: the Rust decoder
  measures its own reconstruction against the source pixels and must stay within
  1 dB of the same model's float decode on the same image. On the pinned
  photograph, measured on an arm64 macOS machine [name removed 2026-09-30]: integer decode 35.985 dB (8-bit
  PSNR of the Rust decode), float decode 36.175 dB (the export tool's PSNR of the
  float reconstruction), a cost of 0.19 dB, from 6328 bytes of rANS payload for
  256×256 pixels. This is a relative bar on one image: nothing here compares
  mbt2018_mean with another codec, and quality is image-dependent — the 42.6 dB
  figure quoted for this codec was measured on a different photograph, which is
  not in the repository.
- New CI job `wai-jpegai-e2e.yml` runs `jpegai_e2e_full` and
  `jpegai_reconstruction_binding` with the switch set, with the same by-name and
  skip-banner checks. Their inputs — the decoder
  weights, normative tables and test codestream, extracted from the JPEG-AI
  reference-software assets (which are not in this repository) — are fetched from
  WAI's versioned models root (`jpegai/v1/`) by
  `tools/wai_jpegai_fetch_e2e_inputs.sh` and checked against the SHA-256 manifest
  `tools/jpegai-e2e-v1.sha256`. The job also pins the SHA-256 of the decoded
  pixels (`WAI_JPEGAI_EXPECT_SHA256`): measured natively on an arm64 macOS machine [name removed 2026-09-30]
  and reproduced by an x86_64 Linux build under QEMU user-mode emulation, and
  required again on the x86_64 runner. That extends a measurement, not a
  registry guarantee: the registry classes `wai.image.jpegai` as
  `NeuralEntropyExact`, a conservative class that guarantees only the entropy
  decode to be byte-identical on every machine, while the exact decoder's pinned
  output for these inputs was measured identical on four platforms
  (determinism-tiers §6).
- `jpegai_live` (the ONNX-runtime `wai.image.jpegai` decode) follows the same
  missing-input rule, but no CI job runs it: its model bundle exists only in the
  local JPEG-AI asset directory, and it needs the `neural` and `codecs` features.
- determinism-tiers §5–§6 record the two jobs. The full-scale `int_hyper` row and
  the JPEG AI whole-decode row (split from the index-derivation row, whose test CI
  still does not run) now name their workflow, state that a missing input fails
  there instead of skipping, and state that neither workflow has run through the
  forge: each passed under `forgejo-runner exec` on the Linux runner's host in an
  earlier form, and its current steps have run on macOS arm64 only. §5 quotes the
  `int_hyper` cost measured on the pinned photograph in place of the 42.6 dB
  figure, and names the bar each job re-checks.

