6644 Commits
Author SHA1 Message Date
Miguel Ángel 34a8d48160 chore: release v0.9.4 (#7018) v0.9.4 2026-11-02 14:33:44 +00:00
Miguel Ángel b23b51f4f0 fix(cli): snapshot fails when an on-screen video frame cannot be read (#7011)
* fix(cli): snapshot reads video frames through any ffprobe and fails on an unreadable one

* fix(cli): snapshot reads video frames through any ffprobe and fails on an unreadable one

* fix(cli): snapshot counts only a failed frame read as unreadable

* fix(cli): snapshot fails when an on-screen video frame cannot be read
2026-11-02 13:48:20 +00:00
Miguel Ángel 036e41fa09 fix(core): iPhone Safari keeps one connection per file for the take on screen and the next (#7012)
* fix(core): iPhone Safari keeps one connection per file for the take on screen and the next

* fix(core): drop the doc comments the comment ratchet counts in studioPreviewMark
2026-11-02 13:15:47 +00:00
Miguel Ángel cd5984261a fix(studio): an undo that drops the keyframes clears the transform the old preview still shows (#7005)
A restore that removes the GSAP script cannot be patched in place, so the preview reloads - and until it lands it keeps the transform the timeline composed, though the file it is going back to places the box with CSS alone. Only the elements the restored script stops animating are repainted; anything it still animates keeps what the timeline gave it.
2026-11-02 12:29:46 +00:00
Miguel Ángel 8891449401 fix(cli): exit-time telemetry stays silent when the temp folder cannot be written (#6925) 2026-11-02 12:18:46 +00:00
Miguel Ángel f6536e9f5d chore: release v0.9.3 (#7010) v0.9.3 2026-11-02 12:04:35 +00:00
WaterrrForever 8089f0049c feat(skills): soft-launch reverse-any-video, and fix what Wanbi's Pro test found (#7006)
* feat(skills): publish reverse-any-video, render it at high quality, and stop on a stuck shot

From Wanbi's Pro test of reverse-any-video (11-01, checked against 0.9.2):

- A standard install never found the skill: it was internal, and /hyperframes did not route to
  it. It is now an on-demand skill on every catalog surface, and the routing line names it.
- The cloud render in SKILL.md had no --quality high, so the final rendered at standard.
- A re-shoot that stayed pending had no rule; the run waited four hours. people.md now runs the
  command once more after generate's 30-minute stop, then treats the shot as failed.

* feat(cli): generate takes a language for --voice, so a Pro sign-in gets a HeyGen voice

Wanbi's Pro run fell back to Kokoro: --voice needed an id, and the only way to list ids was the
separate heygen CLI and its own login. /v3/voices answers on the HyperFrames sign-in, so:

- --voice <language> picks HeyGen's first public voice in it and names it in the output.
- A missing --voice lists six English voices to pick from instead of a bare error.
- A voice id still goes straight through, with no extra call.

* fix(cli): a voice picked by language stays with its request across re-runs

Rames: `--voice Chinese` re-picked HeyGen's first voice on every run, and the voice is part of the
body and the idempotency key. If the catalog reordered while a job was pending, the same command
could start a second paid job instead of resuming the first.

The pick is now bound to the request (every field, plus the account scope a job bills) in the
project's heygen-jobs.jsonl, or the CLI config dir outside a project, and a re-run reuses it.
Regression: a pending timeout, a reordered catalog, the same command, for voice and avatar; the
second POST keeps the voice, body and key.

* fix(cli): a voice pick waits for a known account instead of binding to none

Rames: when /v3/users/me failed, senderScope() was null and the pick was bound to an empty
scope; once the account came back, the same command missed that binding and could pick another
voice and paid key. pickVoice now stops before picking or posting while the account is unknown,
and never reads or writes a blank-account binding.

Regressions, both directions: unknown then known refuses with no POST, then picks once; known
then unknown refuses the re-run with no second POST, then resumes with the same body and key.
Also README: a non-interactive install gets all 8 skills, not 7.
2026-11-02 11:48:55 +00:00
Miguel Ángel d17b958318 feat(studio-server): stamp a project hf-ids without holding the event loop (#7004) 2026-11-02 11:15:42 +00:00
Miguel ÁngelandHuntsDesk c54f84859d fix(studio-server): long media clips no longer leave the host unanswered (#7002)
* fix(studio-server): more than six clips on one media file no longer starve check and preview of connections

Every file server answered `Range: bytes=N-` with the rest of the file. A
media element reads that until its buffer is full, then stops reading but
keeps the response open, so each <video> held one of Chrome's six HTTP/1.1
connections to the host. With seven or more <video> clips on the server's
host, every other request queued behind them and `hyperframes check`
stalled at 0% CPU. A long recording cut into trimmed segments, each its own
<video> on the same file, is enough.

An open-ended range of audio or video now gets at most 4 MiB
(OPEN_MEDIA_RANGE_BYTES), as a normal 206 with an exact Content-Range. The
element asks for the next range as it plays or seeks. Bounded and suffix
ranges, and files that aren't media, are served as before. The helper lives
in studio-server; its preview route and the CLI's static project server and
composition server use it.

Fixes #6029

Claude-Session: https://claude.ai/code/session_014aw1z3VrTNenka3LGDBBLa

* fix(studio-server): carry the range cap's reason in names and tests, not comments

The comment ratchet doesn't let a file's comment share rise: mediaRange.ts
was 48% comments against the package's 7%, and staticProjectServer.ts gained
a line. The cap is now MAX_OPEN_MEDIA_RANGE_BYTES, and the why and the
repro stay in the three tests and #6029.

Claude-Session: https://claude.ai/code/session_014aw1z3VrTNenka3LGDBBLa

* fix(producer): the render file server bounds open-ended media ranges too

parseRangeHeader takes the response's content type and caps an open-ended
`bytes=N-` on audio or video with openRangeEnd, like the CLI and Studio
servers. The producer imports it from a new `media-range` subpath of
@hyperframes/studio-server, as it does `encoder-options`, so a render
doesn't load the rest of the package.

Claude-Session: https://claude.ai/code/session_01DW4V8HZZx5JUgMffb3juVV

* test(cli): eight clips on one file no longer leave the host unanswered

A real Chromium page buffers eight long video clips of one file from the project server and then asks the same host for another file; with open-ended ranges unbounded the request stays unanswered, with the bounded piece it is answered at once.

* docs(producer): range comments name the open-ended form in lowercase

* docs(cli): the range test's comment says what holds now

---------

Co-authored-by: HuntsDesk <hunter@talloak.com>
2026-11-02 11:03:55 +00:00
WaterrrForever 618c486734 fix(cli): measure and diff report why they failed, and reverse reports its runs (#6997)
* fix(cli): measure and diff report why they failed, and reverse reports its runs

Since launch, 97 people saw a bare "Command failed" from measure: runMeasure
and diff called failCommand() without the error, so telemetry kept only the
wrapper. 59 agents ran `measure <file>` with no op and got no hint. Reverse
runs had no skill tag, so nobody could count how many finished.

- runMeasure and diff pass the error to failCommand.
- An unknown word that is an existing file names the commands to put first.
- references/start.md sends skill_invoked and skill_completed beacons.

* fix(cli): the file hint stays out of the root command list

Jerrai: `hyperframes index.html` would list every top-level command. fileHint moves to
didYouMean.ts, answers only inside a command group, and has tests for the root, a missing
file and a group with no commands.
2026-11-02 10:03:08 +00:00
Miguel Ángel a46412ee07 fix(studio): a preview reload writes the composition as it is now, not as it was when it asked (#6998)
* fix(studio): a preview swap writes the composition as it is now, not as it was when it asked

Claude-Session: https://claude.ai/code/session_01BzWPCkrNkiYrpRYeqVmKyK

* fix(studio): a shadow reload that a write outran loads the file again

Claude-Session: https://claude.ai/code/session_01BzWPCkrNkiYrpRYeqVmKyK

* fix(studio): count the project's revision once per write, not again on its echo

Claude-Session: https://claude.ai/code/session_01BzWPCkrNkiYrpRYeqVmKyK

* refactor(studio): move the swap freshness check next to the swap it guards

* refactor(studio): name the refetch bound instead of explaining it
2026-11-02 09:52:07 +00:00
Miguel Ángel aaa5b63f55 fix(core): keep media prefetch queue ordered (#6996)
* fix(core): keep media prefetch queue ordered

* fix(core): refresh queued prefetch priorities on timing edits
2026-11-02 09:24:45 +00:00
Miguel Ángel 43f8b1a3fc fix(lint): a helper script's timeline nested by the page is not reported as unregistered (#6999) 2026-11-02 09:20:46 +00:00
Miguel Ángel 5e50ac1c47 chore: release v0.9.2 (#6994)
* chore: release v0.9.2

* chore: release v0.9.2
v0.9.2
2026-11-02 08:42:46 +00:00
Miguel Ángel 26d6e3eef1 fix(engine): a scene that has ended gives up its WebGL context so the next scene is not slowed (#6984)
* fix(engine): a scene that has ended gives up its WebGL context so the next scene is not slowed

* build(engine): raise the engine package size budget for the WebGL release module

* chore(engine): shorten the WebGL release comment

* fix(engine): a scene gives up its WebGL context only when the runtime says its window ended

* chore(engine): drop a comment the type already says

* chore(engine): shorten a comment line
2026-11-02 07:50:16 +00:00
Miguel Ángel 5fca435623 feat(studio): hosts can ask which action holds a key combination (#6979)
* feat(studio): hosts can ask which Studio action holds a key combination

* fix(studio): the clash check skips a key map entry that is not a combo

* refactor(studio): studioKeyClash in fewer lines
2026-11-02 07:42:18 +00:00
Miguel Ángel e5b10f8bc2 feat(core): a heavy clip's lighter copy can be made ahead of time (#6982)
* feat(core): make a heavy clip's lighter copy ahead of time when the host asks

* feat(core): keep the comment share of the proxy transcoder where it was

* feat(core): split the copy-ahead choice so each part stays simple

* feat(core): the preview route passes the copy's urgency as the proxy options expect
2026-11-02 07:15:45 +00:00
James RussoandClaude Opus 5.5 870569a431 chore: release v0.9.1 (#6987)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
v0.9.1
2026-11-02 07:14:25 +00:00
James RussoandClaude Opus 5.5 a17af79ab0 docs(changelog): complete the v0.9.0 notes (#6986)
Add #6973 and #6978, which merged ahead of the release PR and shipped in
v0.9.0 without an entry. Correct the PLAN_TOO_LARGE upgrade note: the
plan-size cap only applied to Plan v1, and Plan v2 never raises it.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-02 06:37:41 +00:00
James RussoandClaude Opus 5.5 758759673b fix(aws-lambda): route an omitted PlanProtocol before comparing it (#6985)
Step Functions raises States.Runtime for a StringEquals on a missing path
instead of treating it as a non-match, so a state machine input without
PlanProtocol failed at SelectPlanProtocol and never reached the Default
branch. Check presence first in both the SAM template and the CDK stack.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-02 06:37:39 +00:00
James RussoandClaude Opus 5.5 f1391156e0 chore: release v0.9.0 (#6980)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
v0.9.0
2026-11-02 05:14:22 +00:00
WaterrrForever b1316e61d1 fix(cli): diff stops counting a fast move as an extra cut (#6978)
A regenerated shot never lines up with a whip frame by frame, so diff listed every fast move.

A jump now counts only above the original's own motion around it.

fails without the fix: reads a change no stronger than the original's motion as the same fast move
2026-11-02 04:50:16 +00:00
Miguel Ángel 6bbda219bb fix(core): a smaller preview copy nobody wants any more no longer swaps in (#6973)
* fix(core): a smaller preview copy nobody wants any more no longer swaps in

* refactor(core): name the dropped copy instead of commenting it
2026-11-02 04:41:07 +00:00
Miguel Ángel 8519f28363 fix(core): a preview video short of data holds the film instead of looping snippets (#6974)
* fix(core): a preview video short of data holds the film instead of looping snippets

* fix(core): keep the comment share of the runtime files where it was
2026-11-02 04:14:40 +00:00
James Russo 7f48a6894c feat!: remove Plan v1 distributed transport (#6970)
* feat!: remove Plan v1 distributed transport

BREAKING CHANGE: Cloud adapters accept only Plan v2; producer v1 exports are removed.

* ci: authorize Plan v1 cleanup deletions

* docs: avoid citing generated smoke result file

* fix(gcp): reject unsupported plan protocols in workflow

* ci: preserve gcp package size reduction

* fix: reject stale Plan v1 SDK options

* chore: remove retired Plan parity scripts
2026-11-02 04:13:57 +00:00
WaterrrForever 99223d993c fix(cli): diff warns when yours runs at another frame rate (#6976)
A root without data-fps on a 24 fps film rendered at 30 fps, and nothing said so.

fails without the fix: warns about a render at another frame rate
2026-11-02 04:09:30 +00:00
Miguel Ángel f0b2dd0cdb chore: release v0.8.231 (#6971) v0.8.231 2026-11-02 03:34:08 +00:00
Miguel Ángel 9fa02badfc feat(studio): every editor and player shortcut is remappable (#6966)
* feat(studio): shortcut combos in the key resolver

* feat(studio): every editor shortcut is a remappable combo

* refactor(studio): playback keys dispatch through one table

* fix(studio): combo parsing without backtracking, symbol keys match, fewer comments

* style(studio): format the shortcut files

* chore(studio): drop a doc comment the ratchet counts

* chore(studio): drop a doc comment the ratchet counts

* fix(studio): modifier combos fire for playback keys, caption guard and held stop key follow the map
2026-11-02 02:38:23 +00:00
Miguel Ángel c06427b063 test(cli): run the real npx shim check only in its own CI job (#6969)
* test(cli): the npx command test builds the command instead of running a real npx

* test(cli): run the real npx shim check only in its own CI job
2026-11-02 02:18:03 +00:00
Miguel Ángel f8309b356e fix(cli): media-treatment reads a relative --grading file from the project folder (#6964) 2026-11-02 01:47:06 +00:00
Miguel Ángel 7c5c1ce849 fix(cli): the browser install hint names only a Chrome that exists (#6954) 2026-11-01 23:54:29 +00:00
Miguel Ángel 6b008cbc2c fix(lint): a scene may use Three.js or Lottie loaded by the parent document (#6961) 2026-11-01 23:53:40 +00:00
Miguel Ángel fb2c28e8aa chore: release v0.8.230 (#6962) v0.8.230 2026-11-01 23:52:11 +00:00
Miguel Ángel 53c93ba68e fix(cli): snapshot shoots a frame again when Chrome drops the screenshot mid-paint (#6941)
* fix(cli): snapshot shoots a frame again when Chrome drops the screenshot mid-paint

* fix(cli): keep the first screenshot error when the retry fails differently
2026-11-01 23:19:16 +00:00
Miguel Ángel 2bce65ee1b fix(cli): add the audio and transcribe topics to hyperframes docs (#6960) 2026-11-01 23:16:56 +00:00
Miguel Ángel 13b42bec3c fix(shader-transitions): keep the loading panel out of snapshot and check captures (#6959) 2026-11-01 22:46:34 +00:00
Miguel Ángel de6ec3811e fix: cache paths follow HYPERFRAMES_CACHE_DIR (#6716)
* fix: cache paths follow HYPERFRAMES_CACHE_DIR

Every place HyperFrames keeps downloaded or built files now takes its
folder from one helper, hyperframesCacheDir() in @hyperframes/core. The
default stays ~/.cache/hyperframes; HYPERFRAMES_CACHE_DIR moves it.

* fix: register the cache-dir subpath for bun and node, and build inspector from core source

* test: the cache-dir override test uses a folder that is absolute on every platform

* fix: the opencv cache follows HYPERFRAMES_CACHE_DIR

* fix(cli): npm installs run in their staging dir, so no cache path reaches a command line

* fix(cli): whisper.cpp is cloned inside its build dir, so no cache path is a git argument

* test(cli): the whisper clone test finds no system whisper on Windows either
2026-11-01 22:44:11 +00:00
Miguel Ángel 57d23598a7 feat(studio): hosts can remap Studio's single-key shortcuts (#6957)
* feat(studio): hosts can remap Studio's single-key shortcuts

* fix(studio): razor exit key and jump-to-in stay live when remapped
2026-11-01 22:40:12 +00:00
Miguel Ángel 8b029f4fb0 fix(parsers): resolve file URLs and Git Bash paths in media sources (#6956)
* fix(parsers): resolve file URLs and Git Bash paths in media sources

* fix(parsers): return a native path for a Git Bash media source
2026-11-01 22:22:54 +00:00
Miguel Ángel 465128d002 fix(cli): media-treatment says which media the file has when the selector matches none (#6958) 2026-11-01 22:22:18 +00:00
Miguel Ángel 5c5794287b fix(cli): say a font or image URL is a download, not a page, when capture is given one (#6952)
* 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
2026-11-01 21:52:04 +00:00
Miguel Ángel 7d8cdfbb8b fix(studio): a preview reload that timed out is tried once more, so an edit is not left unseen (#6953)
* 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
2026-11-01 21:50:31 +00:00
Miguel Ángel 9284e69fff fix(core): accept 65-point .cube LUTs, the size grading apps export (#6921)
* 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
2026-11-01 20:46:08 +00:00
Vance Ingalls 5540f49121 chore: release v0.8.229 (#6951) v0.8.229 2026-11-01 12:42:11 -08:00
Vance IngallsandClaude Opus 5.5 34ddced2d0 fix(cli): keep browser sign-in open through checkout (#6879)
* 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>
2026-11-01 12:29:35 -08:00
Miguel Ángel 0ab4931159 fix(studio): a clip's thumbnail strip stays put while you trim it (#6942)
* 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
2026-11-01 20:16:52 +00:00
WaterrrForever 6b0abb4eb5 fix(cli): a stale mask takes its frame's colours instead of delogo's streaks (#6950)
* 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.
2026-11-01 19:41:17 +00:00
WaterrrForever 7f8ae5b4b6 fix(cli): a masked box follows the frame while the camera moves (#6948)
* 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.
2026-11-01 18:52:06 +00:00
WaterrrForever 0f76a7d01e docs(skills): animated films in reverse-any-video decide code or generation per shot (#6946)
* 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.
2026-11-01 18:28:10 +00:00
Miguel Ángel 3179348d9a chore: release v0.8.228 (#6943)
* chore: release v0.8.228

* docs(release): the v0.8.228 notes say what limiting a mix far over the ceiling costs
v0.8.228
2026-11-01 18:14:51 +00:00