[#388 follow-up] Deterministic cross-backend capture of animated snippets (virtual-clock stepping on web) #393

Open
opened 2026-07-20 02:01:48 +00:00 by john · 0 comments
Owner

Part of #387. Follow-up spun out of #388 (cross-backend screenshot diff harness).

Context

The #388 harness diffs the snippet corpus web (SDL2/WebGL) vs the desktop-headless oracle. It currently diffs static snippets only. The desktop oracle is captured on a virtual clock (seed 42, fixed step count via _screenshot.py's resolve_steps()MCRF_SHOT_AT → 0.6×longest-animation → 3 static steps). The web build advances on the browser's requestAnimationFrame wall clock, so a frame mid-animation is not reproducible cross-backend. Per Fail-Early, snippet_diff.py explicitly skips any snippet with still-active mcrfpy.animations (reported, never silent) — roughly the ~61 .animate() + timer-driven snippets.

Goal

Make animated/timer-driven snippets deterministically capturable on web so they can be diffed too:

  1. Pause the web main loop (Module.pauseMainLoop) after the snippet's scene is set.
  2. Advance a virtual clock by stepping deterministically — mirror _screenshot.py: seed, then step mcrfpy.step(0.016) for the same resolved count (honor MCRF_SHOT_AT / 0.6×longest-animation / static-steps and the per-number OVERRIDES from tools/generate_snippet_shots.py).
  3. Verify mcrfpy.step() is exposed and behaves identically to the headless clock on the web build (it may need wiring through the JS interop surface in EmscriptenStubs.cpp).
  4. Capture and diff as the static path already does.

Acceptance

The ~61 animated snippets diff green (within the AA tolerance) against their oracle, or flag genuine divergences — no snippet excluded solely for being animated.

Depends on #388 (landed).

Part of #387. Follow-up spun out of #388 (cross-backend screenshot diff harness). ## Context The #388 harness diffs the snippet corpus web (SDL2/WebGL) vs the desktop-headless oracle. It currently diffs **static** snippets only. The desktop oracle is captured on a *virtual* clock (seed 42, fixed step count via `_screenshot.py`'s `resolve_steps()` — `MCRF_SHOT_AT` → 0.6×longest-animation → 3 static steps). The web build advances on the browser's `requestAnimationFrame` **wall clock**, so a frame mid-animation is not reproducible cross-backend. Per Fail-Early, `snippet_diff.py` **explicitly skips** any snippet with still-active `mcrfpy.animations` (reported, never silent) — roughly the ~61 `.animate()` + timer-driven snippets. ## Goal Make animated/timer-driven snippets deterministically capturable on web so they can be diffed too: 1. Pause the web main loop (`Module.pauseMainLoop`) after the snippet's scene is set. 2. Advance a **virtual** clock by stepping deterministically — mirror `_screenshot.py`: seed, then step `mcrfpy.step(0.016)` for the same resolved count (honor `MCRF_SHOT_AT` / 0.6×longest-animation / static-steps and the per-number OVERRIDES from `tools/generate_snippet_shots.py`). 3. Verify `mcrfpy.step()` is exposed and behaves identically to the headless clock on the web build (it may need wiring through the JS interop surface in `EmscriptenStubs.cpp`). 4. Capture and diff as the static path already does. ## Acceptance The ~61 animated snippets diff green (within the AA tolerance) against their oracle, or flag genuine divergences — no snippet excluded solely for being animated. Depends on #388 (landed).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
john/McRogueFace#393
No description provided.