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

102 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.