* 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
* 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.