Files
xenia-rs/crates/xenia-app/tests/golden
MechaCat02 77034b6cbf audit-038: persistent cache:/* VFS via host-FS backing
Replaces the "Synthesized empty file" stub for cache:/* paths with a
real host-FS HostPathDevice-style mount. Each KernelState gets a fresh
per-process tmpdir under /tmp/xenia-rs-cache-<pid>-<id>/ which is
cleared on init for lockstep determinism (mirrors canary's
xenia_main.cc:649 RegisterSymbolicLink("cache:", "\\CACHE") +
HostPathDevice in xenia-canary/src/xenia/vfs/devices/host_path_device.cc).

NtCreateFile now honours create_disposition for cache: paths:
  FILE_OPEN          -> NOT_FOUND if missing
  FILE_CREATE        -> NAME_COLLISION if present
  FILE_OPEN_IF       -> open or create
  FILE_OVERWRITE_IF  -> create or truncate
  FILE_OVERWRITE     -> NOT_FOUND if missing, else truncate
  FILE_SUPERSEDE     -> create or truncate

NtReadFile / NtWriteFile / NtSetInformationFile (XFileEndOfFileInformation)
/ NtQueryInformationFile / NtQueryFullAttributesFile route through
std::fs against the per-handle host_path; non-cache paths keep their
legacy semantics (read-only disc image, synth-empty stubs).

Verified by audit-037 cascade:
- sub_82459D18 (cache-miss restore): 0 fires (was firing constantly)
- sub_8245D230 (resize/zero-fill):  0 fires (was firing constantly)
- 105+ real cache-file writes per 500M run; 4+ MB of game data persisting
  to disk per boot; cache:/recent, cache:/access, cache:/d4ea*.tmp, etc.
- Lockstep deterministic at instructions=100000004 / imports=987485
  across 3+ reruns (digest shifted as expected; goldens re-baselined).
- swaps=2 plateau still in place; cluster L1 unactivated. Cascade
  dimension D (cluster activation) — UNKNOWN, no L1 fires.

Tests 640 -> 645 (+5 cache-specific unit tests; full workspace green).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:34:27 +02:00
..

Sylpheed regression goldens

These JSON files anchor xenia-rs check digest output for Project Sylpheed.

Files

File -n Mode Captures
sylpheed_n2m.json 2_000_000 full digest early boot (swaps=0, no rendering)
sylpheed_n50m.json 50_000_000 stable-digest first VdSwap pair (swaps=2 post-Phase-A)

Stable-digest mode

sylpheed_n50m.json is captured with --stable-digest, which omits timing-sensitive counters: packets (±28% lockstep noise from a GPU thread race), resolves, interrupts_delivered, interrupts_dropped, texture_decodes. The remaining fields are byte-identical across repeated lockstep runs at a fixed -n.

sylpheed_n2m.json predates the stable-digest flag and uses full-digest compare. It still works because at -n 2M the GPU pipeline has not produced any packets yet — packets=0 is trivially deterministic.

Circularity hazard

Per ORACBUG-001/002/003, these goldens were captured by running the same code they validate. They detect regression from a known-good snapshot, not correctness. When a planned fix intentionally moves the digest (e.g. a shader fix landing draws > 0 for the first time), re-baseline the golden as a separate commit and reference the audit ID in the message.

Re-baselining

cargo build --release -p xenia-app
target/release/xenia-rs check \
    "$SYLPHEED_ISO" \
    -n 50000000 \
    --stable-digest \
    --out crates/xenia-app/tests/golden/sylpheed_n50m.json

Running the goldens

cargo test --release -p xenia-app --test sylpheed_oracles -- --ignored --nocapture

The tests are #[ignore]-gated because each run takes a few seconds, which is unacceptable in the default cargo test cycle. The ISO path defaults to the contributor's local ~/RE Project Sylpheed/Project Sylpheed*.iso and can be overridden via SYLPHEED_ISO=/path/to/sylpheed.iso.

n4b canonical-invocation regression anchor (deferred)

The audit's recommended next sprint also called for a sylpheed_n4b.json golden capturing the canonical reference invocation xenia-rs check sylpheed.iso -n 4_000_000_000 --parallel --reservations-table. This is deferred because:

  1. The --parallel --reservations-table combination is empirically pathologically slow at -n 100M (>32 min per run per the audit memory). At -n 4B the run cost is many hours, not the single-session-friendly 515 min the original plan estimated.
  2. Each phase that intentionally moves rendering counters (C, D, E, F) would need a re-baseline of n4b — a significant time cost compounding over the sprint.

Once the renderer-unblock phases (C+D+E) land and draws > 0 is confirmed at -n 100M lockstep, an n4b artifact may be captured one-shot and stored under audit-runs/post-fix/ (not as a test golden) as a manual regression anchor for the canonical invocation.