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>
4.1 KiB
Phase C+6 — re-validation
Gate 1 — Determinism (cvar-OFF, ours)
3 fresh runs of check -n 50000000 --stable-digest:
| run | digest md5 |
|---|---|
| 1 | c6d895829b4611964978990ae1cb8a6a |
| 2 | c6d895829b4611964978990ae1cb8a6a |
| 3 | c6d895829b4611964978990ae1cb8a6a |
| C+5 baseline (cvar-OFF) | c6d895829b4611964978990ae1cb8a6a |
Result: ✅ byte-identical across 3 runs and SAME as the C+5
baseline. The Phase C+6 fix is purely an emitter-framing change (cvar
phase_a_event_log OFF path): the unimplemented_exports HashSet is
consulted only inside the phase_a_on guard in call_export. The
stub body (stub_success, which sets r3 = 0) still runs unchanged.
Therefore the cvar-OFF deterministic boot trajectory is unchanged.
Baseline digest preserved.
Gate 2 — Phase B image_canonical_sha256
Phase B snapshot captured to snap/ours/.
image_loaded_sha256 = ea8d160e9369328a5b922258a92113efb8d7ce3e1a5c12cc521e375985c91c18
matches the Phase-A/B verify baseline. The fix touches only the
kernel-export shim/emitter layer — no PE image bytes modified.
Gate 3 — Phase A matched-prefix extension (KEY METRIC)
Diffed audit-runs/phase-c6-call-name-divergence/ours.jsonl against
the existing phase-c-first-divergence/phase-a/canary.jsonl.
| chain | C+5 (pre-C+6) | C+6 (post) | Δ |
|---|---|---|---|
| canary tid=6 → ours tid=1 (main) | 102132 | 102158 | +26 |
| canary tid=4 → ours tid=11 | 5 | 5 | 0 |
| canary tid=7 → ours tid=2 | 15 | 15 | 0 |
| canary tid=12 → ours tid=7 | 2 | 2 | 0 |
| canary tid=14 → ours tid=9 | 39 | 39 | 0 |
| canary tid=15 → ours tid=10 | (no div) | (no div) | 0 |
Main thread matched prefix grew from 102132 to 102158. Gate 3 ✅.
The new first-divergence at idx=102158 is XamTaskCloseHandle
return_value: canary=1, ours=0 — value divergence, NOT a call-name
divergence. That's the next Phase C+N target.
Gate 4 — Build
$ cargo build --release
Compiling xenia-kernel v0.1.0
Compiling xenia-app v0.1.0
Finished `release` profile [optimized] target(s) in 6.22s
One pre-existing dead-code warning (walk_committed_regions); not
introduced by this fix. Canary untouched.
Gate 5 — Phase A determinism (emitter)
Two cvar-ON captures of the same engine binary on the same ISO,
md5-summing only deterministic fields (excluding host_ns AND
guest_cycle — both are timing-sensitive, see Stage 2's
established practice):
ours.jsonl (run 1, det-fields-only) 7312446e49fa3c3149d26424832cabf4
/tmp/c6_pa_run2.jsonl (run 2, det-fields-only) 7312446e49fa3c3149d26424832cabf4
Byte-identical. ✅
Note: digest changes from C+5's 388d394a… because the suppression
flips 3 events on/off in the deterministic-fields stream. Expected.
Gate 6 — Kernel unit tests
$ cargo test --release -p xenia-kernel --lib
test result: ok. 145 passed; 0 failed; 0 ignored; 0 measured;
0 filtered out
1 new test added (144 → 145):
register_unimplemented_export_marks_set_membership— verifies the newregister_unimplemented_exportAPI both installs the export func (socall_exportfinds and runs the stub) AND inserts the(module, ord)pair intounimplemented_exports(so the Phase A emitter guard suppresses events). Cross-checks the negative case: a normalregister_exportdoes NOT mark unimplemented.
Full workspace test suite (cargo test --release --workspace):
no regressions.
Summary
All 6 gates pass. Phase A main matched prefix grew from 102132 to
102158 (+26 events). One class-E (Phase A coverage gap) engine bug
fixed: ours's emitter injected 3 spurious events
(import.call/kernel.call/kernel.return) for
IoDismountVolumeByFileHandle because canary's syscall-thunk path
for table-entry-only exports never reaches Trampoline and emits
nothing. New register_unimplemented_export API in state.rs lets
us mark such exports for Phase A suppression while keeping their
stub body execution intact. Cvar-OFF inert.
Diff-tool unchanged. Canary unchanged.
Next divergence: XamTaskCloseHandle return value at tid_event_idx=102158 (canary=1, ours=0 — value divergence). Phase C+7 target.