DEF-29: a video export bakes its beacons whatever the author's reduced motion - #42
Open
djDAOjones wants to merge 2 commits into
Open
djDAOjones wants to merge 2 commits into
djDAOjones wants to merge 2 commits into
Conversation
…d motion Under prefers-reduced-motion the pulse, ripple and glow beacons were held still in every host, so an author with the setting on exported videos without them; a video export now draws them as authored, while the editor and the live player keep honouring the setting (§20 Q7b). Verify: 85 test files · 1,192 tests · shell 0 · build:check 0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dV8F9uaxT1v6tu3JFqTkf
The review found export frames, now syncing every beacon, left their last ring or glow drawn and frozen in a reduced-motion editor once the export ended; the hold now resets a held beacon rather than only rescaling it, which also ends an older freeze when the setting is switched on mid-effect. The tests give each style its own fixture, draw the pulse while playing, and check the editor after a finished, cancelled and failed export. Verify: 85 test files · 1,199 tests · shell 0 · build:check 0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dV8F9uaxT1v6tu3JFqTkf
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Post-W2 queue · DEF-29 (plan §12.1 DEF-29, P3; the policy was decided at §20 Q7b and accepted on 2026-09-22). This changes behaviour for an author whose operating system asks for reduced motion. Their video exports now show pulse, ripple and glow beacons as authored. The editor and the exported HTML player still hold those beacons still for them, including right after an export.
The defect
BeaconRenderer.updateholds pulse, ripple and glow beacons still underprefers-reduced-motion. That is right for the editor and the live player. But it held them still in a baked video export too, so an author with the setting on exported videos without them.Stated new behaviour
main.The change
src/main.js: the render state carriesexportingVideo: this._isExportMode. Only the video export sets that flag (_enterExportMode), and it clears it in itsfinally.src/services/RenderingService.js: thebeaconsrender step passes{ ignoreReducedMotion: state.exportingVideo === true }throughrenderBeaconsto the beacons.src/services/BeaconRenderer.js:updateskips the reduced-motion hold when told to. A held beacon is now reset rather than only rescaled, so it is drawn as one that was never synced. That second change came from the review: export frames now sync every beacon, and the hold used to leave whatever they had drawn frozen on screen.Evidence
Tests first. In
tests/goldenDrawLogs.test.js,DEF-29: a video export ignores the author's reduced-motion setting, on Open day. Each style gets its own fixture, so a check can only pass on that style's own drawing. At each beacon's arrival plus 250 ms, the frame drawn with reduced motion is compared with the frame drawn without it. A pulse shows only through its marker's scale, which before DEF-08 only a playing frame draws, so the pulse's frames are drawn playing.main: the reduced frame differs (140 lines for the ripple)The post-export tests run the app's real
exportVideo(), with only the encoder replaced, from preview under reduced motion. They compare frames at four instants before and after the export.Mutations, each against the whole suite (parallel, JSON report, watchdog):
renderBeaconsdrops the option on its way to the beaconsmain.jsand both services as onmainGoldens. None changed.
In a real browser (headless Chromium 141, in this session's cloud container). I built
mainand this branch's head (509fa43) in throwaway clones and served each locally; nothing touched Joe's machine or the live site. The review's own Playwright scripts drove the realexportVideo()with the real WebM encoder (WebCodecs VP9). Chromium's media emulation stood in for the operating-system setting and fired the app's real reduced-motion listener.mainReview
Codex isn't available in this cloud container. Instead, an independent Claude agent attacked five numbered claims. It had a fresh context, its own no-remote clone and the falsification brief Codex would get. It used jsdom probes of the real
exportVideo(), Chromium 141 with the real WebM encoder, and a merge with DEF-08.It confirmed:
authored-extrasfixture. Onmain, 252 of the 371 frames differ with the setting on.exportingVideohas one writer and one reader, the player never sets it, and nothing else renders in export mode.It found real holes, and I reproduced each before acting:
Adopted: a regression in the editor after every export (claim 2 broken). The hold skipped syncing a beacon but kept its old state. Once export frames synced every beacon, a reduced-motion author saw the last ripple ring or glow frozen in the editor after any finished, cancelled or failed export. In Chromium, a real Escape cancel left a ring of r = 31.07, and a finished export left a glow of r = 57.26 round the last waypoint.
mainshows neither.The tests missed it because they reset the beacons before every reduced frame. The hold now resets the beacon. The reviewer verified this fix, and the three post-export tests pin it.
Adopted: the pulse cases were vacuous (claim 5). In the shared fixture, the entrance ripple was still animating at the pulse's instant, so its lines passed the pulse's checks. Each style now has its own fixture, and the pulse is drawn playing. H9 and H10 above are the review's M10 and M11.
Recorded for Joe: a second export started during the first corrupts it.
_isExportModeis a boolean. A secondexportVideo()throws "Export already in progress", but itsfinallystill leaves export mode under the running export. In jsdom the remaining frames lose the flag and the canvas drops from 1920 to 1173 px wide. The likely route is a double click on Export MP4, which couldn't be tried here: headless Chromium has no H.264 encoder. It is older than this PR; the close-out PR proposes it to Joe as DEF-46.If Joe wants Codex's view before merging, the same falsification brief is ready to run against this branch.
Design review gate (
UI-STANDARDS.md)No control, layout or style changes. The reduced-motion contract is unchanged where people are watching live: the editor and the player hold the looping beacons still, and now also right after an export and when the setting is switched on mid-effect. A baked video drops the author's personal setting, as §20 Q7b decided.
Still manual
matchMedialistener.Merging. This PR conflicts, in text only, with two others; whichever merges second needs
mainmerged in, and I'll do that. With #37 (DEF-08), the golden-draw-logs test's imports (both addBeaconRenderer) and its file-map row conflict; I'll combine them. Once both are in, the pulse checks can use paused frames too. With #40 (DEF-30), the plan's DEF-29 and DEF-30 rows are adjacent, so their dated notes conflict.file-map.md: the golden-draw-logs test row describes the new coverage. The plan: a dated note on DEF-29's row.Verify
npm run check: 85 test files · 1,199 tests · 2 todo · shell 0 · build:check 0.main: 85 · 1,190 · 2 todo.Rollback
Revert this PR. Either way, the change reaches users only through a release.
🤖 Generated with Claude Code
https://claude.ai/code/session_013dV8F9uaxT1v6tu3JFqTkf
Generated by Claude Code