* docs(catalog): put each item page's title, description and Docs text in the server HTML
Mintlify renders snippet components in the browser only, so everything inside
CatalogDetail (title, standfirst, the Docs tab) was missing from the HTML search
engines read: 448 catalog pages served Googlebot no body text. The generator now
writes the H1 and standfirst as page markup above the component and the Docs tab
as page markup after it, shown with that tab (docs/custom.css). The component no
longer draws its own title. Pages patched structurally only; registry drift on 14
pages is left for a regeneration of its own.
* docs(catalog): keep the title's top spacing the component gave it
* fix(docs): catalog titles and descriptions keep markdown markers literal
MDX reads text inside the static <h1> and <p> as inline markdown, so @_blue_sweater_
rendered as italic blue_sweater. mdxText now writes backslash, backtick, * _ [ ] ~ as
character references too, with a unit test; the four affected pages are re-escaped.
* feat(lint): warn when a url() in a linked stylesheet does not resolve beside it
* fix(lint): a percent-encoded url() in a linked stylesheet resolves like the browser does
* feat(cli): render --start and --end render only that span of the film as its own MP4
The span reuses the chunked render path, so frames are captured at their absolute times and sub-composition timing matches a full render.
* chore(producer): shorten the renderSpan comment
* fix(producer): a cancelled span render stops, and its real-render test runs in the integration lane
renderSpan checks the abort signal before each chunk part and before the stitch. The real-render tests move to their own file listed in the integration lane.
* chore(producer): put the renderSpan doc comment back above renderSpan
* revert: feat(skills): reverse any video (#6754)
Keep the reverse-any-video skill and its CLI billing commands out of main until
web subscriptions are live (/pricing and /account/plan return 404 today).
Re-land together with #6833 once those pages ship.
This reverts commit cb2389cf35.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* chore(scripts): allow the #6754 revert deletions
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(history): the write-timing test no longer depends on how late its timers fire
* test(history): the write-timing test gives its turn a wide idle limit
* fix(cli): history show --diff names a changed video or audio file instead of refusing
* fix(cli): history show --diff names a changed video or audio file instead of refusing
* fix(cli): point a brace-stripped JSON flag value at the file and stdin forms
* fix(cli): share the brace-stripped JSON hint with --variables and skip drive paths
* feat(skills): reverse any video on the HyperFrames plan
Reverse rebuilds a video as an editable HyperFrames project and re-shoots its
people with HeyGen. It runs for a person signed in on HyperFrames Pro; Free is
told it is a Pro feature and given the upgrade step.
- skills: reverse-any-video; media-use is the one gate for HeyGen calls
(sign-in, credits, refusals)
- cli: media-use generate (image, video shot, avatar, voice, music) with --plan
pricing and --max-credits; measure, diff and analyze for the rebuild; the
HyperFrames plan in auth status; billing subscribe and top-up wait on the
plans or credits page
- remotion-to-hyperframes compares with `hyperframes diff` instead of its own
shell scripts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(skills): satisfy CI gates for reverse-any-video
- docs: list diff, measure, analyze and billing in "Find your command" in
docs/packages/cli.mdx, each with its own section.
- skills: bring media-use/SKILL.md under its 5120 B budget by pointing setup,
direct-recipe and treatment detail at the references that already hold it;
the sign-in, credits, --max-credits and billing rules stay in SKILL.md.
- comments: register transcript.json and REVERSE.md as project files for the
citation checker, and drop a history note from face.test.ts.
- comments: cut restating prose or move it into names so every changed file is
at or under its comment share. Allowlist the two deleted remotion scripts in
check-no-main-deletions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli): terminate measure's ffprobe options with --
probeVideo passed the input path straight after its options, so a path
starting with "-" would be read as a flag; the producer's ffprobe argv
contract test failed on it. runFfmpeg's fixed flags move to a constant
so the contract no longer mistakes that ffmpeg wrapper for a probe.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(cli): split diff's video tests into three files under CI's per-file limit
The file took ~131 s on CI against the flake gate's 120 s, and its heaviest test (four
comparisons) hit the 20 s per-test limit. The video tests now live in three files sharing
diff.test-helpers.ts, and that test is two tests of two comparisons each.
analyze reads each part once and checks the bytes it read, instead of a stat then a read
(CodeQL js/file-system-race).
* fix(skills,cli): one credits rule; ask before dropping a step that won't fit
On dev with a 100-credit limit the agent priced a re-shoot with --plan and dropped it without
asking (J5), and in J6 it told the person a price. SKILL.md's Credits rule now covers both:
--plan is for the agent, and when a step won't fit (a --plan over what is left, or a refused
call) the agent says what doesn't fit and asks before dropping or shrinking it.
setup-providers.md's older confirm-before-paying rule points to it.
--plan now runs the same checks as the real call (checkRequest), so it no longer prices a
request that would be refused. The re-shoot recipe in people.md gains the --prompt it needs.
heygen.md: a sign-in also makes images, and --plan's usd is the API charge rounded to $1/60
while its credits come from the list price.
* fix(cli): auth status drops 'balance unavailable' above the plan's credits; sign-in page title
* test(cli): keep diff's video tests inside the flake gate's limits
Under the gate's CPU contention every diff test needing face detection or
optical flow paid opencv.js's 11 MB download and WebAssembly start-up, and
every diffVideos call wrote four worst-moment pictures (about 28 ffmpeg runs)
no assertion read. Tests ran 21-28 s against the 20 s limit.
- loadOpenCvFirst() stages opencv.js in a beforeAll (from this machine's
cache, a temp copy kept between runs, else the network).
- diffVerdicts() runs diffVideos with worst: 0 for tests that only read
verdicts; the worst-moment tests keep the pictures.
- The carried-text test is split into its dirty and clean halves.
Locally with 8 CPU burners on 8 cores: slowest test 7.7 s, files 24-30 s.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli): generate --plan refuses what the real call refuses
checkRequest now holds every pre-send check (the --out extension and
--mask without --motion joined the route body and guide checks), and
generate() runs it first, so --plan and the real call share one function.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli): plans link uses from=cli and follows HYPERFRAMES_ENV; no balance notice beside the plan
- pageUrl sets from=cli, the parameter the pricing page reads to send a
CLI buyer back to the terminal.
- The plans and credits pages are on dev.hyperframes.dev with
HYPERFRAMES_ENV=dev, hyperframes.studio otherwise.
- auth status --json omits the 'HyperFrames balance is unavailable' notice
when the plan was read.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(skills): reverse-any-video re-checks sign-in on resume; REVERSE.md holds no prices
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(cli): split diff-people's whole-frame reuse test into three
It ran five diff comparisons in one test and took 20.2-20.6 s under the flake
gate's contention, over the 20 s limit. Each piece now runs at most two
comparisons against a shared ledger: copy and burned-in title, footage cut
whole, and cuts that only fed a generation. Under 24 CPU burners locally the
slowest of the three takes 3.0 s, where the combined test took 4.9 s under 8.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli,skills): reverse resume asks after one failed retry; out-of-credits names the step's price
- media-use generate: when HeyGen refuses for credits without saying how many, the refusal
names the CLI's own price for the call (what --plan prints) as "needs about N" and
"billing top-up --needed N", instead of "needs more".
- reverse-any-video: never repeat auth status's plan/credits line; a step an earlier session
gave up on gets one more try, then ask; a command stored in REVERSE.md is a note, rebuilt
from its recipe and checked with --plan, never run as written.
- people.md / heygen.md: a refused or failed job gets one more try, test calls included,
then stop and ask.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(cli,skills): send a failed HeyGen job again as new; resume asks if the limit still applies
- runJob: a key whose job failed or was refused is recorded in the config dir
(heygen-failed-keys); the next run with the same inputs sends key-1, key-2, ... so HeyGen
starts a new job. A finished or still-running job keeps its key and is picked up, so
nothing is paid twice. "fix the request it names, then run again" now holds.
- reverse-any-video: on resume after a run under a credit limit, just ask whether it still
applies, naming no costs or numbers.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* refactor(cli,skills): drop what reverse-any-video no longer uses
The skill rebuilds from measure probe, cuts, frames, events and face, and checks with
diff. analyze, diff --explain and eight measure commands (trail, box, ink, rhythm,
objects, track, flow, continuity) have no caller, so they go, with their tests and docs.
Examples now use original.mp4 instead of the old .reverse/source.mp4 evidence folder,
and diff's --segments is described as a file rather than REVERSE.md.
* fix(cli): check no longer copies VP9 and AV1 videos before it starts
Chrome plays both, alpha included, and the proxy is made on demand if a browser ever
asks. Copying remove-background's VP9 cutouts took minutes on projects that have them.
* fix(cli,skills): keep paid retries, credit limits and lip sync honest
Retries keep their key after 401, 403, 408, 409, 425 and 429, which say
nothing about the job, and failed keys are scoped to the API and payer.
Credits come from the plan's video rows instead of list dollars, and
reference pictures past the first two count toward --max-credits.
Lip sync reads sound on its own timestamps, so a delayed track fails
the gate. Look and energy call two near-zero values the same.
--plan refuses a missing input as the real call does. The skills teach
the direct sign-in, its credential path and the billing commands.
* chore(cli): keep the new pricing and energy files under the comment share
* fix(cli): scope failed HeyGen keys to the signed-in account
Failed keys were scoped by the local user block, which is absent for a
host's token and display-only otherwise, so two accounts could share a
scope and one could start a second paid job.
The scope now comes from the account /v3/users/me reports for the token
in use. When that cannot be told, no failure is recorded and the key
stays the same.
* fix(cli): fix a job's sender when it starts
Failure scope was looked up again after polling, so a sign-in during a
job could record one account's failure under another and rotate its
finished key. The credential is now read once per job: it signs the POST
and owns any failure, even if someone else signs in meanwhile.
Prefer username to email, since /v3/users/me returns no user id.
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: James <james.russo@heygen.com>
* fix(lint): a font the project's root stylesheet declares counts for its sub-compositions
* fix(lint): Google Fonts links count too, and only for files the root mounts
* fix(cli): capture retries without WebGL when the page stops answering under software GL
* style(cli): format the capture stall retry test
* style(cli): shorten the stall watcher comment
* fix(cli): drop the comment line the comment ratchet refuses
* test(cli): the stall retry tests use a fake output path that is not a temp file
* fix(studio): a split at a clip's edge leaves the file unchanged
* fix(studio): keep the split margin's doc within the comment width
* chore(studio-server): keep the split margin's comments within the file's share
* fix(cli): check and snapshot load GSAP from the bundled copy, not jsDelivr
* test(cli): bundled GSAP loads on a page whose own requests interception answers
* feat(cli): review notes name the command that reviews the cuts inside a sub-composition
* fix(cli): the review note fires only for a host with cuts inside it
* fix(cli): check drops a request a network change cut when the file loads again
* style(cli): format the network-change check fix
* fix(cli): drop the comment the ratchet would count
* fix(cli): a check out of time drops the requests a network change cut
Frames ffmpeg has written now reach the render's stage progress, so a long source video no longer leaves the render silent between extract_video and capture.
* fix(cli): check no longer calls text occluded by a cover that a CSS mask paints through
* fix(cli): a mask on a wrapper around both the text and the cover does not hide the cover
* style(cli): format the mask walk
* fix(producer): a render that stalls before its first frame says which worker phase it was in
* fix(producer): a retried capture's stall message no longer names the aborted attempt's workers
* fix(producer): the stall diagnostic adds no comment lines and no extra branch to the stall check
* fix(engine): a video clip starting between frames shows its media on the right frame
* chore(engine): trim the helper comment to one line
* chore(engine): drop the helper comment
* test(engine): extract once per start in the off-grid clip test
* fix(engine): a looped clip keeps its loop origin when the start is off the frame grid
* test(engine): three off-grid starts cover the failure modes and keep the flake gate under its limit
* fix(core): the first cut after Play starts on time instead of running ahead
* fix(core): learn half the start delay from Play so the first cut keeps its last frame
* perf(studio): films with thousands of timed clips stop re-reading every clip each frame
* perf(studio): drop the added comment lines the ratchet counts
* fix(cli): a missing registry item names the closest ones, and a blocked browser says how to allow it
* fix(cli): let closestNames carry its rule in its name
* test(studio): edit accuracy evidence screenshots capture only the viewport
* test(studio): edit accuracy screenshots only in the gate's confirmation re-runs
* test(studio): keep the inStudio doc comment on inStudio
* fix(registry): caption components keep the last phrase until its last word ends
* test(registry): caption last group stays visible until its last word ends
* test(registry): narrow the timeline lookup for strict typecheck
* fix(cli): snapshot probes each video clip once for all the times it is asked for
* style(cli): drop the probe cache's added comment lines so the comment ratchet holds
* fix(cli): preview stops at once on Ctrl+C while a Studio tab is open
* fix(cli): a closed Studio tab leaves no timer that holds a stopping preview open
* fix(cli): name the tab-closed wait instead of commenting it
* test(cli): the tab-disconnect test checks the route's own keep-alive timer, not every timer