Files
xenia-rs/audit-runs/phase-c12-NtQueryFullAttributesFile/re-validation.md
MechaCat02 ef93a4fa14 handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes
Source changes (dormant parity infra, retained from iterate 2.AI/2.AO):
- xenia-kernel/exports.rs: nt_create_event manual_reset polarity +
  related event wiring
- xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity

Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the
iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps
(.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as
regenerable local artifacts — see memory + HANDOFF for the running findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 07:19:08 +02:00

5.6 KiB
Raw Blame History

Phase C+12 re-validation (cold-vs-cold)

Cache-wipe protocol (CORRECTED from C+11.1)

The Phase C+11.1 protocol wiped ~/.local/share/Xenia/cache, but the Windows-debug canary running under wine actually stores its cache at xenia-canary/build-cross/bin/Windows/Debug/cache/ (the binary directory; verified by canary's Storage root: Z:\...\build- cross\bin\Windows\Debug startup log). C+12's effective wipe targets the binary directory.

Step-by-step (the protocol used here):

  1. Backup canary's binary-dir cache: tar -czf /tmp/canary-binary-cache-backup.tar.gz -C xenia-canary/build-cross/bin/Windows/Debug cache (4.7 MB, 23 files). Copy to audit-runs/phase-c12-NtQueryFullAttributesFile/ canary-binary-cache-pre-wipe.tar.gz.
  2. Wipe both engines' caches:
    • find xenia-canary/build-cross/bin/Windows/Debug/cache -mindepth 1 -delete
    • find xenia-canary/build-cross/bin/Windows/Debug/cache0 -mindepth 1 -delete
    • find xenia-canary/build-cross/bin/Windows/Debug/cache1 -mindepth 1 -delete
    • find ~/.local/share/xenia-rs/cache -mindepth 1 -delete
  3. Cold ours run: ./xenia-rs/target/release/xrs-c12 exec --phase-a-event-log /tmp/ours-cold-c12-v2.jsonl -n 50000000 "<ISO>" (~3 s wallclock).
  4. Cold canary run (background, killed after 5M+ canary events): cd xenia-canary/build-cross/bin/Windows/Debug && /usr/bin/wine ./xc-c12.exe --mute=true --phase_a_event_log_path=canary-cold-c12-v2.jsonl "<ISO>" Killed via wineserver -k after ~120 s wallclock once the jsonl reached ~6 M lines (250 k tid=6 events buffered).
  5. Truncate canary jsonl per-tid (cap tid=6 at 250 k, other tids at 20 k) to keep the diff tractable. Truncated file is 119 MB / 533 k lines (kept) — the differ runs on this.
  6. Diff: python3 xenia-rs/tools/diff-events/diff_events.py --canary <truncated> --ours /tmp/ours-cold-c12-v2.jsonl --out /tmp/diff-c12-cold-v2.md.
  7. Restore canary's binary-dir cache from backup so future runs keep the oracle intact.

Canonical post-C+12 cold-vs-cold matched-prefix table

canary_tid ours_tid matched canary_total ours_total first_divergence_at notes
6 1 103862 250000 108471 103862 main chain — +1458 events vs C+11.1. New divergence: NtCreateFile game:\dat\files.tbl returns canary=STATUS_OBJECT_NAME_NOT_FOUND (0xC0000034) / ours=STATUS_SUCCESS (synth-empty stub for missing disc files; AUDIT-006 fallback).
4 11 9 20000 9 sister — no divergence within the 9 ours events
7 2 29 29 30 sister — no divergence within the 29 canary events
12 7 2 10532 3 2 sister — pre-existing KeWaitForSingleObject return (TIMEOUT/SUCCESS); NOT regressed
14 9 39 20000 75 39 sister — pre-existing XAudio init divergence; NOT regressed
15 10 15 20000 15 sister — no divergence within the 15 ours events

Gate matrix

gate result notes
Build (cargo build --release) PASS 1 unrelated dead_code warning, no errors
Kernel tests (172 → 177) PASS 5 new C+12 tests, all pass
Full workspace tests PASS 702 tests pass (sum of all crates)
Determinism — 3× cold stable-digest PASS ad4f74ee324fdedb0bfdd4cc4c6468e9 (all 3) — IDENTICAL to C+11.1 baseline
--stable-digest digest unchanged PASS C+12 fix is observation-only on the stable counters
Phase B image_loaded_sha256 PASS ea8d160e9369328a5b922258a92113efb8d7ce3e1a5c12cc521e375985c91c18 unchanged
Cold-vs-cold matched prefix PASS 102404 → 103862 (+1458) on main chain
Sister-chain regression check PASS All 5 sister chains unchanged

Source data

file size notes
canary-cold.jsonl 1.4 GB full canary cold run, 6.0 M lines (post-kill)
canary-cold-tid6-250k.jsonl 119 MB per-tid truncated for diff (tid 6: 250 k, others: 20 k cap)
ours-cold.jsonl 28 MB ours cold run, 121 k tid=1 events
diff-cold-vs-cold.md 8 KB the diff_events.py output
canary-binary-cache-pre-wipe.tar.gz 4.7 MB canary's 23-file oracle preserved before wipe (binary-dir!)
digest-cold-stable-{1,2,3}.json <1 KB each 3 determinism runs, identical hash
phase-b-snap/ours/ ~5 MB Phase B 5-file snapshot with image_loaded_sha256

Notes

  • The +1458-event advance lands at a new tid=6 divergence: NtCreateFile game:\dat\files.tbl returns SUCCESS in ours because the disc dump doesn't ship this file but ours's open_vfs_file fallback synthesizes a 0-byte file (see exports.rs:1399-1422), while canary returns STATUS_OBJECT_NAME_NOT_FOUND since it has no equivalent stub. This is a long-standing intentional fallback (rationale: "synthesize empty file lets the game's existence probe succeed for files the rip lacks") that now becomes the next divergence target.
  • The synth-empty fallback was originally introduced to prevent XamShowDirtyDiscErrorUI on missing disc files — removing it outright might regress past audits. Phase C+13 should investigate whether Sylpheed actually needs the file or whether the dirty-disc path is now correctly gated by other logic.
  • Stable digest unchanged confirms the C+12 fix is a pure observation change: the in-memory entry tree and the nt_query_full_attributes_ file rewrite affect only the kernel's response on cache: lookup probes, not the per-instruction execution path observed by the digest. The 1458-event advance is the kernel-export-side effect.