* fix(cli): snapshot rejects a negative --at and builds its sheet from its own frames
* fix(cli): snapshot --at refuses an empty value and trailing junk too
* test(cli): the contact sheet test's fake image reads orientation like the sheet now does
Seeking to a keyframe's own time landed on the one before it, so every candidate failed the
repeat-landing check and the frame was found by decoding from the start of the file. An
accurate seek to the keyframe's time decodes from that earlier keyframe and drops what precedes it.
* fix(studio-server): a history restore refuses to remove every tracked file
* test(studio-server): compare the held clip by bytes so the adopting check stays fast
* fix(studio-server): history's own hidden records do not count as files a restore keeps
* refactor(studio-server): name the restore guard's check instead of commenting it
* chore(studio-server): re-baseline the packed size budget for the restore guard
* test(cli): the lifecycle suite warms the CLI module graph in a hook, not in its first test
* test(studio): the thumbnail suite warms puppeteer in a hook and cancels leftover requests
The chrome-headless-shell that HyperFrames downloads on Windows ships
without dxil.dll and dxcompiler.dll. Dawn's D3D12 backend loads them in
requestDevice, so the adapter is found but device creation fails and
three.js WebGPURenderer silently falls back to WebGL2.
Pass --disable-dawn-features=use_dxc next to --enable-unsafe-webgpu on
win32.
Refs #5775
Co-authored-by: serdarucel <196021214+serdarucel@users.noreply.github.com>
* fix(core): color grading builds a new WebGL context when a lost one is never restored
A context the browser evicts and does not restore left every graded clip hidden for good.
After a grace period the runtime now creates a new shared context and moves each clip onto it.
* refactor(core): split the lost-context rebuild into smaller steps and test its retry
* fix(producer): a render's page-error count includes what the capture workers saw
* fix(producer): a failed parallel capture still carries its workers' page errors
* fix(producer): every capture failure carries the page's errors, in every stage
* chore(engine): drop a comment the capture classifier's name already says
* fix(engine): renames ride out Windows file locks instead of failing the render
* fix(producer): the true-peak and segment-manifest renames ride out Windows file locks too
parseAudioElements now resolves end the way core's compileTimingAttrs does. A clip
with no length at all warns, naming the clip, instead of silently playing to the end of
its source.
* fix(cli): keep beats audio paths inside the project
An encoded ../ in the music src decoded to a path outside the project, so
hyperframes beats read that file and wrote beats/<rel>.json outside the
project too. Fail the command when either path escapes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli): drop added comment in beats containment check
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli): resolve symlinks in beats path containment
The lexical check let a symlinked folder inside the project send the read
or the beat-file write outside it, and refused an in-project file named
..music.wav. Use the realpath-aware resolveWithinProject and isSafePath
from core for both paths.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(core): color grading rebuilds the graded clips when a lost WebGL context is restored
A clip shown while the context was lost never got an entry.
* fix(core): drop the added comment line from the color grading restore fix
* fix(engine): h265 renders no longer fail on hosts with more than 16 cores
libx265 rejects more than 16 frame threads, so the thread count taken from the
CPU quota is now capped at 16 for x265. x264 is unchanged.
* fix(engine): pass the encoder to the thread cap in the CFR re-encode
* fix(core): release decoded preview audio once no clip uses its source
The preview transport cached every decoded audio buffer by source until the player was destroyed. Each scheduling pass now drops cached buffers whose source no clip in the document still uses (scene edits, swapped sources), and keeps the rest so playback never re-decodes a clip still in the film.
* fix(core): drop the comment the comment-share ratchet rejects
* perf(producer): the audio task probes each video for sound instead of extracting its frames
* test(producer): the audio task finds a video's sound from a probe, with no frames extracted
* perf(engine): the audio mix reads clips held at a URL many at a time
* style(engine): format the remote clip slot choice
* fix(producer): the audio task places a video's sound in the window extraction would give it
* style(producer): format the slot cases of the script-src audio test
* fix(studio-server): project history no longer copies video, audio or huge files
* fix(studio-server): clean drops old video and audio copies in every history
* fix(studio-server): TypeScript source is not media, so its history is kept
* fix(studio-server): split the media reclaim and point the slow-copy route test at a non-media file
* fix(studio-server): no unused expression when collecting a history's hashes