Held movement and keyboard look now run on a 50 ms main-thread timer, independently of animation frames. Key changes still send immediately. The timer advances arrow-key look using elapsed time capped at 100 ms and sends the current input with its monotonic sequence. It does not send input or turn while paused, hidden or disposed. Page teardown clears it. Blur, hidden-page transitions, menus and graphics recovery retain the existing immediate key release and worker pause behavior.
Previously, refresh and keyboard look ran in animate(). The simulation deliberately expires input after 250 ms without an update. When the compositor stopped delivering animation frames, one keydown moved the player briefly and then the worker correctly expired it, even though the physical key remained held. Increasing the expiry would weaken lost-input handling; the correction changes the sender cadence instead.
The browser regression intercepts animation-frame scheduling from startup, observes the real worker messages, and uses actual keyboard events. Before the correction, the player stopped near Z=4.149 after starting at Z=4.8 and failed the required 1.25 m movement. With the correction, the recorded run advances to Z=2.407 with twenty further input messages and zero animation callbacks. It then verifies release, keyboard look, paused position and input-count stability, and successful resumption of animation callbacks. The test does not fabricate simulation positions or expose a production debug endpoint.
This isolates animation-frame starvation. A blocked JavaScript event loop can still delay timers and key events, and the worker should still expire input in that case. The change does not promise responsiveness during a completely stalled page, change the 30 Hz simulation clock, or establish physical-GPU performance.
#Browser acceptance follow-up
The multiplayer pose-stall scenario now maintains real forward/backward keyboard movement while it observes walking, holds pose delivery and verifies stalled idle, then resumes delivery and verifies walking again. This keeps the movement condition present on slow renderers instead of allowing a single walk to end against a wall before observation. The separate delayed-completion scenario uses the same bounded movement helper. Both retain actual relay traffic, timestamps, animation-state checks and departure cleanup.
The controlled GPU hold measures how long its completion notification is withheld. The longest recorded queue wait must be monotonic and cover that measured hold; it does not have to exceed a slower startup submission. CI source 262bb8f failed the old strict-growth assertion with an unchanged 2,622.1 ms historical maximum, not an unchanged last-completion timestamp. The completed-frame and last-completion checks remain in place.
The same source's recovery pixel check spent approximately 107 seconds inside one screenshot call after its fonts had loaded, exceeding the outer 60-second pixel-poll deadline. A late trace screencast contains world geometry. That distinguishes a capture deadline from an observed black-pixel result, but does not establish a cause or fix for the compositor delay. No recovery deadline or pixel threshold is relaxed by this input correction; that CI issue remains open.
#Validation
Recorded acceptance includes 307 passing headless checks, all 30 browser scenarios with no retries or failures, and type/import checks across 68 source files. The evidence retains the failing pre-fix regression, the full passing browser log, exported reports and the historical CI trace analysis. This is local software-rendered acceptance; remote CI and physical-hardware performance remain separate gates.
#Release measurement and remote follow-up
The input-cadence source 3ec899e subsequently completed CI: core, container and probe pass; player passes 13 of 14 and multiplayer passes two of six. The key-release trace shows a 545.559 ms keyboard-up command between the earlier moving snapshot and the stopped snapshot. The old 0.25 m assertion included time before release could be delivered; it cannot establish braking distance. The trace does not locate the actual DOM event.
The browser regression now surrounds the application's trusted key-up event with capture/bubble observations. It requires exactly one immediate neutral send with the next input sequence, then zero horizontal velocity and stable position through at least ten further worker deliveries, with animation callbacks still withheld. A deliberate 650 ms gap between the moving snapshot and the release request exercises the old measurement error. Separate native motor coverage verifies full-speed walking/sprinting release across four tick rates and five headings/directions: stopping within 270 ms, under 0.18 m walking or 0.48 m sprinting, and less than 1 mm subsequent horizontal drift. These are flat-floor motor bounds, not an end-to-end input-latency claim.
The rendered nameplate test now walks toward the far wall instead of sideways out of the observer's camera. It retains the changed screen position, visible nameplate, canonical arrival/departure and removal checks. The remaining CI walking/stall and graphics-loss cases are not claimed fixed. Their browser tests retain bounded real input, worker/peer, timer, animation-callback and device lifecycle observations on failure, alongside the existing renderer report. Neither graphics deadlines nor motion-staleness limits change.
Follow-up acceptance records three passing native motor tests (forty release fixtures), two player browser scenarios, all six multiplayer scenarios and three final diagnostic-instrumentation scenarios, plus type/import checks. The actual release observation retains the trusted event, immediate neutral sequence, and stopped/settled/paused snapshots. This increment changes validation and evidence only; remote failure diagnosis and full engine acceptance remain open.