Commit Graph
1947 Commits
Author SHA1 Message Date
Miguel Ángel 66f55ffb9b fix(cli): audio describe builds its Apple helper with a module cache an agent's sandbox can write (#6102)
* fix(cli): audio describe builds its Apple helper with a module cache an agent's sandbox can write

* chore(cli): shorten the module cache comment
2026-10-25 23:05:01 +00:00
Miguel Ángel d49e527b32 fix(engine): ffmpeg steps and downloads stop on no progress, not while still advancing (#6258)
* fix(engine): ffmpeg steps and downloads stop on no progress, not while still advancing

* test(cli): an ffmpeg step that stops advancing reports inactivity, not a deadline
2026-10-25 23:04:13 +00:00
Akshar Patel 6a20ec9e9a fix(cli): preserve clip lengths when duplicating media (#6280)
* fix(cli): prevent overlaps when duplicating natural-duration media

* fix(cli): preserve absolute ends when duplicating clips

* fix(cli): keep rippled clip bounds together
2026-10-25 23:01:27 +00:00
Abdullah M. Nazif 707c150cbd fix(cli): include external srcset images in project archives (#6335) 2026-10-25 22:55:35 +00:00
Abdullah M. NazifandMiguel Angel Simon Sierra 3aca8060b8 fix(cli): preserve distinct Lottie animations during capture (#5293)
Co-authored-by: Miguel Angel Simon Sierra <miguel.sierra@heygen.com>
2026-10-25 22:46:44 +00:00
Miguel Ángel 2c10eb0a33 chore: release v0.8.200 (#6337) 2026-10-25 20:50:21 +00:00
Miguel Ángel c50918277a perf(engine): fast capture stays on for frames a shadow, blur or clip effect does not touch (#6318)
* perf(engine): fast capture stays on for frames a shadow, blur or clip effect does not touch

A single drop-shadow, blur, backdrop-filter or blend element, or one clip-path or mask
tween, sent the whole render to screenshot capture, 2-3x slower than drawElement. The two
init gates now name the frames the effect can show on. Only those frames capture by
screenshot, in a second browser opened on the first of them; every other frame keeps
drawElement.

* fix(engine): scan effects in a throwaway session; hand risk frames over only where captured

The effect scan seeked the render's own page to the end, leaving its timeline state ahead of
the render. It now runs in a throwaway session with the render's own seek. A hidden effect
element with a visible descendant counts as shown. Per-frame capture is opt-in per caller
(deFrameFallback), so disk, segmented, chunk and parallel-worker sessions keep the
whole-render fallback, and a route that cannot hand frames over drops drawElement up front.

* fix(engine): a timeline callback keeps the whole-render fallback; trim comment share

A tl.call or onComplete can add an effect's class to any element mid-render, so the elements
found at the start are not the only ones it can reach. Such a timeline is unbounded and keeps
the whole-render screenshot fallback.

* style(engine): shorten the live-frame scan comment

* perf(engine): after a timeline callback, not before, every frame may show the effect

A callback can add an effect's class to any element, so only the frames from the first
callback on lose their element bounds. Frames before it keep the scanned bounds, so a late
callback no longer sends the whole render to screenshot capture.

* perf(engine): open the second screenshot browser only when memory is available for it

Per-frame capture needs a second browser (479 MB measured at 1080p). When the render would
leave less than 1.5 GB available after it, the render keeps the whole-render screenshot
fallback instead. getAvailableMemoryMb moves from the CLI to the engine's system-memory
module, which already owns the host's memory readings; os.freemem() reads 367 MB on this
49 GB Mac, so the guard uses free, inactive, speculative and purgeable pages.

* fix(engine): budget the whole 1 GB per-frame capture adds, not just the second browser

The render's process tree goes from 1002 to 2001 MB at 1080p: the screenshot browser (479 MB)
plus a drawElement browser that is itself about 500 MB larger than a screenshot one. The guard
budgeted 500 MB. It now budgets the 1 GB measured, scaled by output pixels.
2026-10-25 19:15:18 +00:00
Miguel Ángel 42b84632a8 chore: release v0.8.199 (#6328) 2026-10-25 18:13:20 +00:00
Miguel Ángel d4812a0393 test(cli): check the browser that ran the hanging script, and that every browser it started is gone (#6320)
* test(cli): check the browser that ran the hanging script, and that every browser it started is gone

* test(cli): type the launch recorder's pid file and drop the added comment
2026-10-25 16:52:39 +00:00
Miguel Ángel d3a7599c60 fix(cli): a failed frame check no longer switches parallel capture off for good (#6313)
* fix(cli): a failed frame check no longer switches parallel capture off for good

The per-install breaker tripped on the first self-verify fallback and nothing ever cleared it. Now a second fallback within 20 router renders turns the router off, a new CLI version or 20 clean renders turn it back on, and the stored record keeps the rejected frame (reason, frame, dB, threshold, version, time).

* docs(cli): shorten three comments to the line limits

* refactor(cli): keep the breaker record parsing small and the comments within the ratchet
2026-10-25 15:24:47 +00:00
Miguel Ángel ada9932d4e fix(cli): a long video copy reports progress, resumes in 15 s pieces and stops only when stalled (#6307)
* fix(cli): a long video copy reports progress, resumes in 15 s pieces and stops only when stalled

* perf(core): a video copy's size box follows the stage within a fifth, not a half

* docs(cli): shorten two comments to the line limit

* fix(cli): the copy heartbeat drops a finished copy; size budgets follow the stall and progress code

* chore: size budgets rise by this change's measured bytes
2026-10-25 13:53:03 +00:00
Miguel Ángel d7f323d319 chore: release v0.8.198 (#6305) 2026-10-25 12:42:50 +00:00
Miguel Ángel 6b424e02c4 fix(cli): snapshot waits for a slow scene to finish building instead of saving a stale frame (#6290)
* fix(cli): snapshot waits for a slow scene to finish building instead of saving a stale frame

* fix(cli): drop the added comments, the names say it

* test(cli): give the contact-sheet engine mock the render-ready timeout snapshot reads
2026-10-25 10:59:47 +00:00
Miguel Ángel f51650d8a7 chore: release v0.8.197 (#6298) 2026-10-25 09:17:12 +00:00
Miguel Ángel 4d154c6a23 test: two flaky queue tests no longer race real time or the first copy's start (#6283) 2026-10-25 07:13:22 +00:00
Miguel Ángel a7273f7147 fix(cli): snapshot fails with the clip and time instead of a silent black frame (#6274)
* fix(cli): snapshot fails with the clip and time instead of a silent black frame

* fix(cli): one clip timing out in a snapshot no longer loses the other frames

* fix(cli): snapshot fallback seeks to a real frame time so the right frame is picked

* fix(cli): only a frame-extract timeout is recorded as a finding; other errors still stop snapshot
2026-10-25 07:13:16 +00:00
Miguel Ángel 1f740ca21a fix(cli): a check that is stopped by a signal prints the report it has so far (#6282)
* fix(cli): drop added comments, the names carry the meaning

* fix(cli): a check that is stopped by a signal prints the report it has so far

Killed by SIGTERM or SIGINT, check closed Chrome and exited 143 or 130 with
nothing on stdout, so a caller that stops a long check got no result at all.

The signal now ends the check the way an expired deadline does: findings
already made are kept, one finding says the check stopped before finishing,
and the report is printed before the process exits with the signal's code.
2026-10-25 07:13:09 +00:00
Miguel Ángel 45167743a6 chore: release v0.8.196 (#6288) 2026-10-25 06:52:05 +00:00
Miguel Ángel 38afc0b013 fix(deps): update esbuild for the security advisory (#6277) 2026-10-25 04:52:58 +00:00
Miguel Ángel 221f3671f2 fix(cli): stop 'hyperframes add' hanging when a desktop clipboard is available (#6271)
* fix(cli): stop 'hyperframes add' hanging when a desktop clipboard is available

* test(cli): assert the clipboard copy options instead of waiting on real time
2026-10-25 04:44:34 +00:00
Akshar Patel c6c8d81ba3 fix(cli): include encoded external assets in archives (#6266) 2026-10-25 03:45:43 +00:00
Abdullah M. Nazif f5e15b2f77 fix(cli): remove stale briefs when re-freezing recipes (#5324)
* fix(cli): remove stale briefs when re-freezing recipes

* chore: prepare conflict resolution against current main

* chore: preserve reviewed fix on current main

* chore: prepare conflict resolution against current main

* fix(cli): retain recipe brief cleanup with safe directory copies

* chore: prepare conflict resolution against current main

* chore: merge main and refresh recipe skill manifest
2026-10-25 03:45:23 +00:00
Miguel Ángel 37f5f27290 fix(cli): check finishes on long projects with many video clips (#6270)
* fix(cli): check finishes on long projects with many video clips

check loaded every video in the project at once. On a 500 s project with 137
clips of one 1440p source a single renderer reached 6.4 GB, the second sampling
Chrome crashed, and a crashed puppeteer page never settles its calls, so the
run sat until the 120 s deadline.

- Load the check page in Studio's capture mode so only media near the
  playhead loads (peak renderer memory 15.75 GB -> 1.77 GB).
- Read audio durations for the clip-fit audit from a detached element when the
  page has not loaded the one in the composition.
- Settle every driver call with the page's crash or close, so a dead helper
  hands its samples back and a dead main page fails at once.

* fix(cli): shorten a comment to the line limit
2026-10-25 03:32:47 +00:00
Miguel Ángel 1776b42736 chore: release v0.8.195 (#6273) 2026-10-25 03:18:09 +00:00
Miguel Ángel 3eb1aeb0de perf(core): Safari stops re-serializing inline styles on every GSAP write (#5974)
* perf(core): Safari stops re-serializing inline styles on every GSAP write in a playing film

* perf(core): declare the clip-reveal subpath in its descriptor and cut added comment lines

* fix(shader-transitions): shader transitions across a scene boundary keep the scene's contents

Every revealer now goes through one core helper that shows the clip and
lifts the runtime's hidden mark together; the page-side compositor's scene
copies were still carrying the mark. The contents rule keeps its old weight.

* fix(core): films on an older shader-transitions build keep their transition scenes

Published shader builds reveal scenes by inline style without lifting the
hidden mark. When one is on the page, the runtime keeps the inline-style
rules; builds that lift the mark declare it on load and keep the fast rules.

* test(core): pin the hidden-clip contents rule's weight on its selector

* style(core): format the reveal test and move hidden-clip rule notes into names

* test(producer): pin hidden-clip behaviours in real Chrome under the mark-keyed rules

* test(producer): read the forced restyle's result so lint accepts the restyle test
2026-10-25 03:17:39 +00:00
James RussoandClaude Opus 5.5 7f19f2335a feat(studio): load GSAP from the CLI's bundled copy by default (#6256)
* feat(studio): load GSAP from the CLI's bundled copy by default

Studio preview now loads the GSAP, CustomEase and MotionPathPlugin scripts
it adds from files the CLI ships and serves same-origin at /api/vendor/npm,
instead of jsDelivr. HYPERFRAMES_GSAP_BASE_URL still wins when set, and a
composition on another GSAP version gets its plugin from jsDelivr.

Renders now honor HYPERFRAMES_GSAP_BASE_URL when they replace a missing
local GSAP script, and the setting accepts plain http only for loopback
hosts.

Closes #6205

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(studio): keep comment share flat for the GSAP local root

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(cli): find the installed gsap with node resolution when run from source

The Windows CI lane installs with the hoisted linker, so gsap is not under
packages/core/node_modules there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(producer): load a nested composition's missing GSAP from the mirror

A sub-composition's missing local gsap/dist script was hoisted into the
render unchanged, so HYPERFRAMES_GSAP_BASE_URL (and the jsDelivr fallback)
only reached the entry document. Run the same rewrite on every
sub-composition before it is compiled, resolving its path the way the
inliner will hoist it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 03:08:42 +00:00
Miguel Ángel 2e397dba59 chore: release v0.8.194 (#6269) 2026-10-24 22:17:19 -04:00
Abdullah M. Nazif e7169ae85b fix(cli): scope explicit preview port discovery (#6242)
* fix(cli): scope explicit preview port discovery

* fix(cli): scope preview lifecycle discovery

* fix(cli): report the selected preview and its owned log
2026-10-25 01:53:01 +00:00
Akshar Patel 6a917780f5 fix(cli): emit valid JSON for filtered keyframes (#6228) 2026-10-25 00:28:42 +00:00
Abdullah M. Nazif d36797a3b5 fix(cli): report parent motion in template-wrapped keyframes (#5331)
* fix(cli): report parent motion in template-wrapped keyframes

* fix(cli): preserve template ancestor ordering with current keyframes semantics
2026-10-25 00:23:22 +00:00
Abdullah M. Nazif ecd7bf4184 test(cli): cover media URL duration probes (#5330)
* fix(cli): resolve media URLs before timeline duration probes

* chore: prepare conflict resolution against current main

* chore: preserve reviewed fix on current main

* chore: prepare conflict resolution against current main

* fix(cli): keep URL media probes with nested timeline rows

* chore: prepare conflict resolution against current main

* test(cli): cover media URL duration probes
2026-10-25 00:23:02 +00:00
Abdullah M. Nazif ad41745ab1 fix(cli): preserve ducking gain when music starts later (#5318)
* fix(cli): preserve ducking gain when music starts later

* test(cli): keep ducking regressions standalone

* chore: prepare conflict resolution against current main

* chore: preserve reviewed fix on current main

* chore: prepare conflict resolution against current main

* fix(cli): refresh delayed music ducking against main
2026-10-25 00:22:08 +00:00
Abdullah M. Nazif f9d72a3f73 fix(cli): preserve distinct font URLs during capture (#5312)
* fix(cli): preserve distinct font URLs during capture

* fix(cli): preserve distinct font URLs during capture
2026-10-25 00:21:53 +00:00
Abdullah M. Nazif e5e2d6f1df fix(cli): include external video posters in project archives (#5309)
* fix(cli): include external video posters in project archives

* chore: prepare conflict resolution against current main

* fix(cli): retain poster localization with shared archive resolvers
2026-10-25 00:21:39 +00:00
Abdullah M. Nazif bb5e0f0bcf fix(cli): include captured raster formats in contact sheets (#5301)
* fix(cli): include captured raster formats in contact sheets

* test(cli): release cached GIF handles before fixture cleanup

* fix(cli): reconcile contact sheet tests with main
2026-10-25 00:21:26 +00:00
Abdullah M. Nazif 39364ee4fb fix(cli): respect reference image orientation in grade comparisons (#5288)
* fix(cli): respect reference image orientation in grade comparisons

* chore: prepare conflict resolution against current main

* fix(cli): preserve oriented grade references with lazy image loading
2026-10-25 00:21:07 +00:00
Abdullah M. Nazif 9a517560a8 fix(cli): refresh item manifests when bypassing registry cache (#5256)
* fix(cli): refresh item manifests when bypassing registry cache

* chore: prepare conflict resolution against current main

* fix(cli): preserve registry refresh with bounded timeout fallback
2026-10-25 00:20:54 +00:00
James RussoandClaude Opus 5.5 f180ffca64 fix(cli): reap only orphaned browsers HyperFrames launched (#6251)
* fix(cli): reap only orphaned browsers HyperFrames launched

Orphan cleanup on preview and render killed every PPID-1 process of the
current user whose args named chrome-headless-shell or a Puppeteer temp
profile, which included detached browsers started by other tools.

Every HyperFrames Chrome launch now passes an inert
--hyperframes-owned-browser switch, and the reaper only kills PPID-1
processes that carry it as a whole argument.

Fixes #6203

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(core): serve the browser marker from its own subpath

The GCP image's BeginFrame contract step imports the engine's
browserManager straight from source before core's generated runtime
exists, so pulling the marker from the core root entry broke it.
A dependency-free @hyperframes/core/browser-marker subpath keeps that
import chain as light as it was.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(cli): expect the browser marker in the capture fallback launches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs(cli): say orphan cleanup runs before preview and render

The cleanup only stops browsers HyperFrames launched, so the opt-out is
no longer needed to protect other tools' browsers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 23:09:57 +00:00
Dante aefca2144c fix(cli): allow disabling orphan browser cleanup (#6213) 2026-10-24 22:13:25 +00:00
Miguel Ángel fcec26ed5f fix(cli): a Chrome download that stops sending is abandoned, retried, and releases the lock (#6222)
* fix(cli): a Chrome download that stops sending is abandoned, retried, and releases the lock

* fix(cli): a stalled Chrome download is aborted at the socket so the process can exit

* fix(cli): the Chrome download runs in its own process and is killed when it stalls

* test(cli): ignore the expected socket reset in the download stall test on Windows
2026-10-24 17:53:54 +00:00
Miguel Ángel 89081b9197 chore: release v0.8.193 (#6229) 2026-10-24 12:39:08 -04:00
Sergey S 24965372db fix(cli): each start sweeps the running markers of CLIs that are gone (#5790)
A CLI killed by a signal never runs its exit listener, so its file in
~/.hyperframes/running stays. Only the background installer swept those
files, and it never runs for an install layout it skips ("Unknown install
layout", e.g. a CLI bundled inside another tool), so the folder only grew:
185 markers since 2026-10-05 on one machine, none of them a live CLI.

registerRunningCli now removes, besides its own file, every file whose pid
is gone, whose name is not a pid, or whose heartbeat is older than
RUNNING_STALE_MS (a reused pid) — the installer's own criterion. The sweep
never throws, so a failure cannot skip the heartbeat or the exit listener.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

The test reads the running folder's listing instead of checking each path, so no
existence check precedes a write to the same path (CodeQL, file system race).
2026-10-24 15:15:25 +00:00
Miguel Ángel 80be6ff039 fix(cli): snapshot rejects a negative --at and builds its sheet from its own frames (#6179)
* 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
2026-10-24 13:23:36 +00:00
Miguel Ángel 3cbd98890e fix(cli): snapshot seeks into a HEVC cut whose index lands a keyframe early (#6217)
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.
2026-10-24 13:15:11 +00:00
Miguel Ángel 0eae4946d3 fix(studio-server): a history restore refuses to remove every tracked file (#6175)
* 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
2026-10-24 12:51:30 +00:00
Miguel Ángel dd1cba49de test(cli): the lifecycle suite lets background imports settle before it resets modules (#6216) 2026-10-24 12:48:44 +00:00
Miguel Ángel 1a238171ec test: the lifecycle and thumbnail suites load cold modules in a hook, not in their first test (#6212)
* 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
2026-10-24 11:26:33 +00:00
Miguel Ángel c16b783f5e chore: release v0.8.192 (#6206) 2026-10-24 08:51:29 +00:00
James RussoandClaude Opus 5.5 17dd4ee347 fix(cli): keep beats audio paths inside the project (#6188)
* 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>
2026-10-24 08:23:32 +00:00
Miguel Ángel c324a40a87 fix(cli): lint accepts one composition file as well as a project directory (#6202) 2026-10-24 08:22:53 +00:00