RustyNES v2.3.8 "Parallax" — which pixels differ, not just which frame Parallax is the apparent shift of an object seen from two positions, and the displacement is the measurement. That is what this release adds. `Probe` could already say whether two configurations of the same ROM diverge and AT WHICH FRAME, and could say nothing about where or why. A trial reduces each frame to one u64 — the right shape for detecting a difference and the wrong shape for explaining one. A hash says frame 412 differs and has nothing to hand to Pixel Provenance, which is where an answer actually lives. THE DIVERGENCE LENS `divergence::localise` re-runs both configurations to the detected frame, keeps the full output instead of its hash, and reports the SHAPE of the difference: population count, first pixel in raster order, and the inclusive bounding box. Count and box separate kinds of bug from each other — one pixel is a sprite or a palette entry, 256 in a row is a scanline, tens of thousands is a scroll or a mode change. `is_single_scanline` is offered rather than left to call sites, because it is the distinction a caller acts on and the inclusive comparison is easy to get wrong. It localises on the INDEX framebuffer — 256x240 u16s of `(emphasis << 6) | colour`, the PPU's own per-pixel output before the palette lookup. Half the bytes and at least as sensitive, because the RGBA buffer is a pure function of it given the same palette. That proviso holds because both trials run on the same instance and therefore share whatever palette is loaded; it is written down rather than assumed, because a future two-instance lens would have to revisit it. THREE ANSWERS, AND THE THIRD IS THE POINT `Identical`, `Differs`, and `Inconclusive` — for an exhausted budget, or two trials that cannot be compared. The Latency Oracle's precedent applies directly: `None` and `Some(0)` were never collapsed there, and "I stopped looking" must not arrive wearing the same shape as "they agree". The budget is checked UP FRONT for all four trials, mirroring `atlas::verify_liveness`. Spending two on detection and then finding the localisation pair unaffordable would consume the budget that would have answered the question. Detection disagreeing with the pixel diff also returns `Inconclusive` rather than picking a winner. THE ANSWER IS A CAUSE, NOT A COORDINATE Trial-scoped provenance capture hands a located pixel to the machinery that already answers "what wrote this, and from which instruction", so `localise_explained` returns the diverging pixel's provenance from BOTH configurations: the winning layer, the pattern row, the nametable and attribute addresses, the palette entry, the emphasis mask. That closed the sub-frame item WITHOUT BISECTION, and the plan's framing was wrong rather than merely unresolved. It offered a choice between bisecting the frame and riding the records; proving the cheap option viable produced a third answer that is better rather than cheaper. A cycle index says WHEN. A differing `pattern_addr` says the two runs fetched different tile data, which is a lead. Bisection would have spent about seventeen extra trials to produce the weaker answer, so it is not implemented — as a decision, recorded in `docs/divergence-lens.md` so the question is not rediscovered. It remains the only route in a build without `debug-hooks`. For audio the records ride directly, so `localise_audio` resolves a divergence to the CPU CYCLE. FIXED, INSIDE THE SAME WORK The Lens left the emulator THIRTY FRAMES AHEAD of where it started. A trial restores the anchor on the way in and not on the way out — which is deliberate, and is what lets the Lens read the trial's final frame straight off `nes` — but the outermost caller has to put the timeline back, and did not. Through the panel, asking a question advanced the user's game. Both entry points now restore through one wrapper, and that restore is guarded so it does not clear the caller's provenance, which is the v2.3.7 defect one layer up. TWO NOTES WORTH KEEPING No new engine primitive was needed, and the estimate that one would be was wrong in the cheap direction. The same trial-restore asymmetry that caused the bug above is what makes the diverging frame readable. A documentation claim was retracted mid-implementation. `differing_fields` was documented as possibly empty at a located pixel. It cannot be: an index-framebuffer entry is `(emphasis << 6) | colour`, so a differing entry means colour or the emphasis mask differs. Under the permissive reading an empty result is something to render; under the correct one it means the two records did not come from the two configurations. A mutation reading both from the same trial was caught only once the assertion was tightened to match the stricter claim. WHERE IT LIVES, AND WHAT IT IS CUT FROM Tools -> Analysis -> Divergence Lens, over a headless `rustynes_probe::divergence` core tested independently of it. Spec: `docs/divergence-lens.md`. This tag is cut from v2.3.8's own boundary commit rather than from `main`, which had already advanced six PRs into v2.3.9. Its artifacts therefore contain exactly Parallax and nothing from Crucible. ACCURACY `rustynes-apu`, `rustynes-ppu` and `rustynes-core` all change, so AccuracyCoin is VERIFIED rather than asserted: 141/141 (100.00%) on the authoritative RAM decoder, nestest 0-diff. Also green on this tree: fmt, workspace clippy under -D warnings, the no_std thumbv7em cross-compile, and every workspace suite.