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>
5.6 KiB
5.6 KiB
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):
- 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 toaudit-runs/phase-c12-NtQueryFullAttributesFile/ canary-binary-cache-pre-wipe.tar.gz. - Wipe both engines' caches:
find xenia-canary/build-cross/bin/Windows/Debug/cache -mindepth 1 -deletefind xenia-canary/build-cross/bin/Windows/Debug/cache0 -mindepth 1 -deletefind xenia-canary/build-cross/bin/Windows/Debug/cache1 -mindepth 1 -deletefind ~/.local/share/xenia-rs/cache -mindepth 1 -delete
- 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). - 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 viawineserver -kafter ~120 s wallclock once the jsonl reached ~6 M lines (250 k tid=6 events buffered). - 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.
- 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. - 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.tblreturns SUCCESS in ours because the disc dump doesn't ship this file but ours'sopen_vfs_filefallback synthesizes a 0-byte file (seeexports.rs:1399-1422), while canary returnsSTATUS_OBJECT_NAME_NOT_FOUNDsince 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
XamShowDirtyDiscErrorUIon 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_ filerewrite affect only the kernel's response oncache:lookup probes, not the per-instruction execution path observed by the digest. The 1458-event advance is the kernel-export-side effect.