* fix(cli): capture images declared only through srcset
* chore: prepare conflict resolution against current main
* fix(capture): retain srcset coverage with validated GIF redirects
* fix(cli): close asset streams when clients disconnect
* chore: prepare conflict resolution against current main
* fix(cli): retain asset disconnect cleanup with current main
* fix(cli): honor HTML attribute casing in frame-rate defaults
* chore: prepare conflict resolution against current main
* fix(cli): preserve HTML fps casing with shared cloud defaults
* fix(core): preserve literal percent in beat source paths
* chore: prepare conflict resolution against current main
* fix(core): retain beat path handling with current main
* fix(cli): preserve stylesheet order during website capture
* chore: prepare conflict resolution against current main
* fix(cli): retain captured stylesheet order with current main
* chore: prepare conflict resolution against current main
* fix(capture): retain cascade coverage with validated redirects
* fix(cli): detect beats from child media sources
* chore: prepare conflict resolution against current main
* fix(cli): integrate child beat sources with native decoding
* fix(cli): init and skills update only touch HyperFrames skills; --skip-skills works
* fix(cli): init never touches installed skills and no command removes one
* fix(cli): shorten the init skills comment
* fix(cli): shorten the init skills comment
* fix(cli): the stale-skills notice reaches agents that run without a terminal
* test(cli): a run without a terminal now checks skills in the background
* fix(cli): the stale-skills notice also prints on --json runs
* perf(engine): remote sources of a site keep their probe results for the whole render
* test(engine): probe a content-addressed URL once per render
* style(engine): format the audio probe split
* fix(sdk): a delete is kept hidden when any script lookup could reach it, not only an id
* fix(sdk): a lookup argument that is not one closed literal keeps the delete hidden
A `<canvas layoutsubtree class="hf-vfx-src">` nested inside another capture
canvas blocks the renderer main thread in drawElementImage, so `check` and
`snapshot` time out with no output. Refuse either direction of the nest with a
reportVfxError and leave the chain unregistered.
Also scope the two host lookups to immediate children (`:scope >`) so a nested
host's src/out canvas is never bound to the outer host, and read the
`data-vfx-ref-visible` flag in resolveCaptureSource so a canvas reached as both
a host's own source and as a ref gets one consistent `visible`/keepBitmap.
Refs #4405
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(cli): recognize painted gradient children on older Chrome
* fix(cli): recognize ancestor image text masks
* fix(cli): report clipped ancestor text on older Chrome
The media_src_kind_mismatch rule classified .mp3 and .jpeg but not .m4a or
.avif, so an <img> pointed at an audio file or a <video> at a still slipped
through for those two formats. Add .avif to IMAGE_SRC_EXT and .m4a to
AUDIO_SRC_EXT.
.ogg stays out: its container can carry Theora video as well as Vorbis or
Opus, so the extension does not name the kind. .m4a is the opposite case --
it is audio-only, and video in the same MP4 container is .m4v, which
VIDEO_SRC_EXT already lists. The .ogg case keeps its existing coverage and
gains an explicit unknown-extension case alongside it.
Refs #4382
Co-authored-by: Yi-111-a <Yi-111-a@users.noreply.github.com>
* docs: align render, fps and transcribe docs with the CLI
- docs/guides/rendering.mdx: default render quality is `looks` (CRF 16),
not `standard`.
- docs/packages/cli.mdx, render --help (render.ts): default --output is the
timestamped `renders/<project>_<YYYY-MM-DD>_<HH-MM-SS>.<ext>`.
- skills/hyperframes-cli/references/preview-render.md: local --fps accepts
1-240 or a rational and defaults to the root data-fps, else 30; only
lambda and cloudrun are limited to 24, 30, 60.
- skills/hyperframes-cli/references/lint-validate-inspect.md: snapshot
--range is documented as START,END like every other reference.
- skills/media-use/references/audio.md, skills/media-use/audio/references/
transcribe.md, skills/hyperframes/references/captions.md: name the entry
point for each transcription default (transcribe.mjs prefers Parakeet;
`hyperframes transcribe` uses Parakeet when installed, else the small.en
whisper model).
- transcribe --model help text and docs/packages/cli.mdx: list `small` and
`medium`, which the CLI already accepts.
- skills-manifest.json: regenerated hashes for the three skills touched.
— Jerrai
* docs: lambda and cloud run also accept 25 fps
Distributed renders accept 24, 25, 30 and 60 fps (DISTRIBUTED_FPS in
packages/core/src/distributedFps.ts).
- skills/hyperframes-cli/references/preview-render.md: the --fps note
lists 24, 25, 30, 60 for lambda and cloudrun.
- skills/hyperframes-cli/references/lambda.md, cloudrun.md: --fps lists
include 25.
- packages/cli/src/docs/rendering.md (`hyperframes docs rendering`): --fps
said 24, 30 or 60 and --quality defaulted to standard; local render takes
1-240 or a rational, default root data-fps else 30, and the default
quality is looks.
- skills-manifest.json: regenerated hyperframes-cli hash.
— Jerrai
* chore(skills): regenerate skills manifest after formatting
The format hook rewrote skill markdown after the manifest hook had hashed
it, leaving the hyperframes-cli hash stale.
— Jerrai
duplicate_media_discovery_risk, self_closing_media_tag and
placeholder_media_url were defined in media.ts but no test in
media.test.ts mentioned any of their codes.
Adds a trigger case per rule (asserting code and severity) plus
negative cases that pin the boundary each rule actually keys on:
one fingerprint field differing for duplicate discovery, an
explicitly closed tag, and a real src.
Each new test was checked to fail against a disabled rule.
The serial guard in captureFrameSurface, which segmented capture reaches, threw on any frame under the
size floor. It now draws the frame once more and keeps a byte-identical redraw, as the streaming drain
guard does, so a flat frame no longer fails a segmented render.
Fixes#5685
* fix(core): preview fetches only the clips due next, and drops passed clips still downloading
A fast-cut film started a fetch per clip inside the look-ahead and let passed clips finish.
* fix(core): a passed clip stays released for the rest of the play
It was refetched each pass inside the look-back window.
The isolation CSS re-showed every descendant of a mover, so a child the
author hid with visibility:hidden was cropped and smeared into the trail
(240 green px in the repro; 0 in the sharp frame). The hide rule now skips
the mover subtree and the mover alone is made visible, so its descendants
inherit and keep their own visibility.
Found by review of #6106.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* feat(studio): motion blur panel with Off / Subtle / Strong
One three-way control in the right dock. Subtle is the default blur
(240 deg shutter, samples sized to the smear); Strong is 720 deg and 64
samples. Writes the root data-motion-blur attributes through the SDK so
renders match and undo works; reads live attributes from the preview.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(studio): motion blur panel edits the file's own root
The edits were worked out against the preview DOM but written to the file,
so a stale preview (undo inside the hold, a slow reload) could save a level
other than the one picked. They are now computed inside the mutation from
the candidate's root. While locked to a sub-composition no level is shown.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(studio): shorten the motion blur tab so the dock strip fits
Five tabs overflowed the default dock width by 10px and clipped a label
(Studio: load smoke). The tab is now titled Blur.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* perf(aws-lambda): a render reads a video's audio from a small file stored beside it
A video's audio is interleaved with its pictures, so mixing it from the cloud read the whole video (2.5 GB for a 20-minute 4K film) at the Lambda's network speed. lambda sites create now stores each large video's audio packets as a separate object keyed by the video's hash; the audio task reads that when it exists.
* chore(producer): shorten the audio sidecar header comment
* fix(aws-lambda): no audio sidecar for a video whose audio starts late or that has several tracks
* test(producer): format the audio sidecar tests and end their ffprobe options with --
* fix(cli): snapshot waits for the image layers a seek reveals before capturing
x
* style(cli): shorten the late-image test comment
* style(cli): trim three comments so the comment share of the capture file goes down
* fix(engine): a composition whose script throws is skipped with a warning, not waited on and refused
A script that threw before registering its timeline kept the capture waiting the full 45 s readiness timeout, then the render was refused. After a page error with timelines still missing the wait now ends after a short grace, each such composition gets an empty paused timeline of its authored length, and a script_error_isolated warning names the element. The render goes on without that animation.
* test(engine): memo test expects a script failure, format the browser test
* style(engine): shorten a doc comment to the line limit
* fix(engine): isolate only nested compositions that threw, never load failures or a root
* fix(engine): a thrown composition script fails fast and names the composition, not a load error
* fix(engine): the page-error grace starts at the first error, not at the start of the wait
* fix(engine): a nested throw is skipped only while another nested timeline is live
* feat(cli): check writes a progress line to stderr per sample, overlap batch and craft frame
* fix(cli): the check progress lines are written by the CLI, not by the pipeline tests call
* fix(sdk): a stored delete a script still looks up is hidden when overrides replay, not removed
* fix(sdk): shorten the script lookup comment
* fix(sdk): a replayed delete a script looks up leaves the model and serializes back hidden
* fix(sdk): shorten a comment line
* fix(sdk): a kept delete is marked hidden so the audio mixer drops it