Operator eyeball: a jolt/pause when the morph ends and the next altitude's loop loads. Root cause: swapping vid.src to the base + seeking to the tail reloaded the ON-SCREEN element (decode + seek stall). Now a dedicated #vid-loop element carries the steady-state base loop; during a scrub it is PRELOADED to the clip we're heading toward, seeked to the tail and paused on that exact frame. The paint shader reads the active source (busy ? morph : loop), so landing is an instant source swap — no reload, no seek. E2E asserts the loop element is armed + playing from ~3s after landing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Simulator E2E (Playwright)
Browser end-to-end tests for the Human Experience Filter simulator. The §9 pipeline requires an E2E browser tier for any UI surface; this is that tier.
What it covers
tests/altitude-lock.spec.ts drives the real simulator and asserts the
altitude-morph behavior:
- Zooming to a new altitude plays the morph that matches the clip it lands on
(forward zoom-in, and
.revzoom-out). - After landing, the clip is locked — it does not change while parked (no secondary swap, no re-roll).
The played morph paths are read from window.__hefMorphs (a diagnostic array
populated by advance() in static/app.js), which is reliable even when a morph
is served from the in-memory blob cache. The locked clip is read from the
Dev-Mode #scale-name readout.
Running
Prerequisites: the project Python venv on PATH (the Playwright webServer boots
uvicorn simulator.app:app from the repo root), Node, and the Chromium browser.
# from this directory (simulator/e2e)
npm install
npx playwright install chromium
npm test
playwright.config.ts starts uvicorn on port 8099 automatically (reuseExistingServer
locally) and points the tests at it.