* fix(cli): say a font or image URL is a download, not a page, when capture is given one
* fix(cli): word the capture download hint as a likely cause, not a fact
* fix(studio): a preview reload that timed out is tried once more, so an edit is not left unseen
* fix(studio): trim the retry hook's comments to the package's share
* fix(core): accept 65-point .cube LUTs, the size grading apps export
* fix(core): shrink LUTs wider than the GPU texture limit instead of rendering black
* fix(cli): keep browser sign-in open through checkout
The loopback listener timed out after 5 minutes, but plan checkout runs
inside the OAuth flow. A slower purchase ended on ERR_CONNECTION_REFUSED.
Raise the default to 60 minutes, matching pacific's plan-checkout handoff.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(cli): show the sign-in limit and how to recover
The waiting line now states the 60-minute limit and Ctrl+C. After a
timed-out browser login the CLI says to run auth login again.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(cli): drop unverified purchase claim, harden timer test, document limit
Review fixes: the timeout hint no longer says purchases stay on the account
(the CLI cannot observe billing); the no-timer-left test now asserts before
any explicit close() and uses node:http so undici timers cannot pollute the
count; docs mention the 60-minute window and Ctrl+C.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(cli): close the sign-in listener on every path and record Ctrl+C
Ctrl+C is now the advertised exit, but events only flush on exit, which a
default SIGINT skips, so an abandoned login vanished from telemetry. Record
it as aborted and exit 130 through requestCliExit. Close the listener on any
throw, so a failure before the wait can't hold the process for the full
window. Derive the waiting line and timeout message from the listener's own
limit, and name the constant for why it is long, which clears the comment
ratchet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(studio): a clip's thumbnail strip stays put while you trim it
* fix(studio): cover the trim-to-hold link and drop the comment
* refactor(studio): the held trim range lives in its own small hook
* refactor(studio): the thumbnail's held request inputs move into one hook
* chore(studio): drop the hook docstring
* fix(cli): a stale mask takes its frame's colours instead of delogo's streaks
Delogo drew the box's edges across large boxes, and HeyGen painted the streaks into the shot.
Shrink the box to 3x3 and blur it back, so no letter or streak survives.
fails without the fix: leaves no streaks in a box filled while the picture changes
* fix(cli): the stale mask fill drops gblur, which blacked out light boxes
On a 3x3 picture gblur turned light fills black on an FFmpeg 8 build.
Bicubic from 3x3 is already smooth.
* fix(cli): a masked box follows the frame while the camera moves
A temporal median under a moving camera froze older frames in the box, and HeyGen painted them in.
Fill from the box's own edges on each frame when the picture round it changes.
fails without the fix: fills a masked box from the current frame while the picture changes
* fix(cli): the mask scan stops where the guide does, and small boxes still blur
A long guide overflowed the decode buffer.
A narrow box asked for more blur than its chroma plane holds.
* docs(skills): animated films in reverse-any-video decide code or generation per shot
A code-first run scored close to the generated one, except on fine flowing detail.
Build what code can carry, and generate acting, morphs and streamlines.
* docs(skills): clean plates are separate layers, and framing compares a stable shape
Review notes on the animated-film recipe.
A persistent contrast error told the agent to change the original's colours to pass check.
Keep the original's colours and tiny text, and trim two framing lines to stay in budget.
The skill assumed live footage, so an agent on a painted film worked out the path alone.
Says what to tell the person, what stays code, and how to regenerate a shot from its plate.
* fix(engine): GPU renders use the NVENC preset names the host's ffmpeg lists
* fix(engine): one ffmpeg stdout reader for encoder detection and preset listing
* ci(engine): raise the engine unpacked size budget for the NVENC preset reader
* feat(cli): the api exports offloadHeavyMedia and every offloaded file reports its asset_id
* fix(cli): drop the asset_id doc comment that raised the file's comment share
* fix(cli): the cut detector keeps real cuts in live footage
#6894 left held frames out of every baseline and called any run over 3 frames a fast
move. On live footage that raised the baseline past real jump cuts and dropped blur
transitions between shots. Only animation that moves and holds in turn gets the moving
baseline now, and a run stays a cut when its tones change.
* fix(cli): a wipe through black is a cut, and a cut near a guide's edge is refused
A whip keeps its tones through every frame of the run, so that is the test, not only
the two ends: johnny's wipes between two views of one map match at the ends alone.
foldShort folds pieces of a few frames now. At 0.5 s it let a real cut through to a
paid shot, and the classifier already handles the flashes it was there for. --allow-cuts
is in the skills.
* refactor(cli): name the whip check instead of commenting it
* fix(cli): check and snapshot free video clips the playhead left, halving memory on cut films
* fix(core): drop the releaseMedia doc comment that raised the file's comment share
* fix(cli): a shot from --first-frame comes back in that frame's shape
HeyGen can answer 1344x768 for a 16:9 first frame. The crop only ran with --aspect or
with no first frame, so these shots kept its size. Without --aspect the first frame now
sets the shape.
* refactor(cli): drop a comment the function name already says
* fix(cli): the first frame's shape is the one sent, not the one stored
A phone JPEG with Orientation=6 uploads as portrait but stores landscape pixels, so a correct
portrait answer was cropped to 90x50. The shape now comes from the same conversion the upload uses.
fails without the fix: keeps a portrait shot from a phone photo stored sideways
* fix(core): a resized preview video keeps its picture while its new copy loads
Swapping a video to a copy made for its new size emptied it until the copy
decoded, so the preview showed black for a moment. The swap now shows a still
of the frame it had, as the video's poster, until the new copy can draw.
* fix(core): a held preview still is let go when no file loads back
* chore(core): raise the packed size budget for the held preview still
* fix(engine): passthrough output follows the page frames and holds a short video's last frame
* test(engine): a film whose audio outlasts its video still qualifies for passthrough
* test(engine): passthrough encodes one output frame per page frame when the video is shorter
* test(engine): end the ffprobe options before the file in the passthrough frame count test
* fix(studio-server): a copy another process holds without progress ends in a named error
* fix(studio-server): a long source's in-progress piece counts as the owner's progress
* feat(engine): composite a source video inside the streaming encoder
* feat(engine): opt-in flag and rule for compositing a lone full-timeline video
* feat(producer): opt-in video layer passthrough for a lone full-canvas video
* feat(producer): launch the probe, drop its page and capture PNG when passthrough is on
* refactor(engine): trim the passthrough doc comments to one line
* fix(producer): refuse passthrough when a wrapper or sub-composition paints a background
* chore(producer): mark the in-page layout check as one deliberate unit
* fix(engine): a video left out of capture no longer blocks static-frame dedup
* refactor(engine): shorten two long comments in the static-frame eligibility scan
* feat(studio): a host that draws its own loader can turn off both of Studio's preview loaders
Player and NLEPreview take loadingUi: 'none', which hides the composition cover
and the 'Preparing preview assets' wait while still reporting that the preview is
loading. suppressLoadingOverlay keeps its narrower meaning: skip only the
composition cover on a later load.
* refactor(studio): name who draws the loader in the value, loadingUi 'studio' | 'host'
The value says the host draws its own loader, so no doc line has to tell it apart
from suppressLoadingOverlay, and the files' comment share does not rise.
* refactor(studio): the loader choice sits outside Player, the stage size beside NLEPreview
Player's draw decision moves to a small helper so the component's complexity does
not rise, and resolvePreviewStageSize moves to its own file so NLEPreview stays
under the 600-line cap with the new prop.
* refactor(studio): Player reads the host's loader choice without another destructured prop
Destructuring one more prop raised Player's cognitive complexity above main's; the
rest of the props carries loadingUi instead.
* refactor(studio): NLEPreview's stage constants live in one small module
* style(studio): format NLEPreview's stage import
* feat(core): WebKit plays bare audio from a decoded buffer on the audio clock
* fix(core): a handed-over WebKit track goes back to its element when the speed changes
* test(player): play the WebKit audio edits in real Safari on a macOS runner
* fix(core): Safari keeps playing edits' audio without seeks or rate changes
* fix(core): keep the 0.1 s audio sync bound outside WebKit
* fix(core): restore main's audio steering outside WebKit
* fix(core): tell WebKit from the test DOM's user agent
* fix(core): name WebKit's audio start lag instead of commenting it
* fix(core): count embedded WKWebViews as WebKit for audio sync
* fix(cli): snapshot gives a seek that will not settle its own --timeout, not three minutes
* fix(cli): a seek budget never outlives the protocol timeout; say so in --timeout help
* refactor(engine): one builder for the video frame filter chain
* refactor(engine): keep the filter chain builder module-private until it has a caller
* ci: split the cli test job into two shards so each stays well under its limit
* ci: map the sharded cli test run in the reachability audit
* ci: the reachability audit treats --shard as selection-neutral instead of a pinned mapping
* ci: map the sharded cli test run in the reachability audit (pinned), not a blanket --shard rule
* fix(producer): a failed video extraction names which clip files failed
* fix(producer): the extraction source label hides scheme payloads and drive paths
* style(producer): format the extraction source label
* feat(core): the playback health reading says which clock the film followed
* style(core): format the clock's new reading
* refactor(core): let the clock's names say what the comments said
* fix(cli): billing and Desktop handoff read their hosts from settings
* fix(cli): OAuth client and API hosts read from settings
* test(cli): host and client settings tests run the same on any machine
* chore(cli): format and refresh the skills manifest
* chore(cli): trim a comment
* chore(cli): keep the stylesheet as it was
* fix(engine): scale static-frame verification budget with the job
* fix(engine): keep comment share flat
* fix(engine): drop added comment
* fix(engine): time seek in verify budget, state the policy
* feat(cli): measure ink reads text size, --out and --output both work, logo --variant wordmark
measure ink reports the bounds, size and lines of text in a region of one frame, so a rebuild can be sized without a script. measure and snapshot take --out and --output for the same folder. media-use resolve --type logo --variant wordmark returns the brand's wordmark when theSVG has one.
* fix(cli): measure ink stays under the complexity and comment limits, one projectOf
* fix(cli): snapshot and measure also accept --output-dir
* fix(cli): projectOf moves without adding comment lines
* fix(cli): measure output alias list type-checks as an argument
* fix(cli): a logo variant never answers a default logo request; test output flags
* style(cli): format the new tests
* fix(producer): render telemetry reports beyond-viewport capture as the workers used it
* fix(producer): apply the sessions' beyond-viewport value at the summary, on every capture path
* chore(engine): drop a comment so the types file's comment share does not rise
* fix(cli): one cut detector that tells real cuts from flashes and fast moves
* fix(cli): a flash must come back within a few frames; trim comments, format
* test(cli): the cut fixture gets a 60 s timeout; format
* test(cli): drop a history comment
* fix(cli): cloud render uses the composition's data-fps and skips unused heavy files
* fix(cli): satisfy typecheck and comment ratchet for cloud render fps