Commit Graph
2946 Commits
Author SHA1 Message Date
Miguel Ángel 6458807066 feat(cli): let projects opt out of automatic proxying (#2591)
* feat(studio-server): serve H.264 proxies from the preview route

Wires the codec manifest and the transcoder into the preview surface: the route
negotiates a proxy via a query param and serves it through the existing range
and ETag machinery, composition HTML carries a codec map for the runtime, and
hostile assets pre-warm so a first play does not wait on a cold transcode.
Exposes the three subpath exports the CLI surfaces consume upstack.

Drops the TEMP fallow entry added with the transcoder: it has real importers now.

* fix(studio-server): publish media proxy exports

* fix(parsers): scan HTML comments linearly

* feat(cli): let projects opt out of automatic proxying

Adds media.autoProxy to hyperframes.json plus --proxy/--no-proxy flags, and
forwards the resolved value into the studio and preview servers and the vite
adapter. Lands before the runtime slice that turns auto-proxying on, so the
switch exists before there is any behavior to switch off.

* fix(cli): align media config schema
2026-07-16 23:01:14 -04:00
Miguel Ángel 67eab59f44 feat(studio-server): serve H.264 proxies from the preview route (#2590)
* feat(studio-server): serve H.264 proxies from the preview route

Wires the codec manifest and the transcoder into the preview surface: the route
negotiates a proxy via a query param and serves it through the existing range
and ETag machinery, composition HTML carries a codec map for the runtime, and
hostile assets pre-warm so a first play does not wait on a cold transcode.
Exposes the three subpath exports the CLI surfaces consume upstack.

Drops the TEMP fallow entry added with the transcoder: it has real importers now.

* fix(studio-server): publish media proxy exports

* fix(parsers): scan HTML comments linearly
2026-07-16 23:00:48 -04:00
Miguel Ángel 9d148d288a feat(studio-server): transcode bounded H.264 proxies on demand (#2589)
* feat(studio-server): bound the proxy cache with LRU accounting

Adds cache accounting and bounded cleanup for transcoded proxies, and keeps
.transcode-cache out of git. Standalone: the transcoder consumes it next.

* feat(studio-server): transcode bounded H.264 proxies on demand

Adds the proxy transcoder: a bounded work queue with per-key dedupe, a hard
kill ceiling, TTL'd failure memory so a broken asset is not retried forever,
and pixel/color normalization for browser playback. Writes through a temp name
and renames on success, so a cache entry is never partial.

Carries a TEMP fallow ignoreExports entry: this module lands below its
consumers, so a per-PR audit sees its exports as unused until the preview weld
arrives. The entry is dropped there.
2026-07-16 21:08:03 -04:00
Miguel Ángel 1d3d20450d feat(studio-server): bound the proxy cache with LRU accounting (#2588)
Adds cache accounting and bounded cleanup for transcoded proxies, and keeps
.transcode-cache out of git. Standalone: the transcoder consumes it next.
2026-07-16 21:05:08 -04:00
Miguel Ángel 9ca1e17101 feat(studio-server): probe media codec facts for proxy decisions (#2587)
* feat(studio-server): probe media codec facts for proxy decisions

Adds the codec manifest: one ffprobe-backed answer to what codec an asset
uses, whether a browser can decode it, and whether it carries alpha. Migrates
the existing prober to the shared ff-binaries resolver and to async execFile so
a scan pool runs off the event loop. No consumer yet; the preview weld wires it
up later in the stack.

* fix(studio-server): honor injected ffprobe runners
2026-07-16 20:54:50 -04:00
Miguel Ángel d7b38da19d Merge pull request #2586 from heygen-com/carve/s1-asset-resolution
refactor(parsers): share local-asset resolution across lint and studio-server
2026-07-16 20:07:47 -04:00
Miguel Ángel 817a87056c Merge pull request #2585 from heygen-com/carve/hevc-base-rebased
refactor(parsers): single shared FFmpeg/FFprobe binary resolver
2026-07-16 20:07:14 -04:00
Miguel Ángel d4a29fd0c3 Merge pull request #2597 from heygen-com/carve/hevc-base-docs-lint
feat(lint): warn on HEVC video assets that browsers cannot preview
2026-07-16 20:06:35 -04:00
Miguel Angel Simon Sierra 053e1274b1 refactor(parsers): share local-asset resolution across lint and studio-server
Moves assetResolution.ts from packages/lint into @hyperframes/parsers behind
a ./asset-resolution subpath export, mirroring the ./ff-binaries shape, and
points lint's two importers at it. Pure move: no behavior change. Unblocks
studio-server consuming the same helpers without a dependency cycle (the CLI
already depends on lint, so importing lint from studio-server is not an option).
2026-07-16 19:16:43 -04:00
Miguel Angel Simon Sierra 7980479083 fix: preserve shared FFmpeg resolver behavior 2026-07-16 19:10:04 -04:00
Miguel Angel Simon Sierra 88c049f525 refactor(parsers): single shared FFmpeg/FFprobe binary resolver
The cli, engine, and lint packages each carried their own copy of the
ffmpeg/ffprobe lookup, annotated fallow-ignore code-duplication, and the
copies had drifted: the engine copy handled Windows PATHEXT and executed
which/where without a shell but lacked the Homebrew-dirs fallback for
GUI-spawned processes; the cli copy had the opposite. One resolver in
@hyperframes/parsers (the dependency-graph bottom) now carries the union
of both hardenings, and all three packages delegate to it. Every
consumer gets strictly more robust resolution; env-override semantics
per call site are preserved via configuredMustExist.
2026-07-16 18:36:40 -04:00
Miguel Angel Simon Sierra 247743fcdf refactor(lint): bound concurrent ffprobe processes in HEVC probe 2026-07-16 18:36:12 -04:00
Miguel Angel Simon Sierra 664c39db9e feat(lint): flag HEVC video assets with info-level preview note 2026-07-16 18:36:12 -04:00
Miguel Angel Simon Sierra 5f2819b1e7 docs: document HEVC input support and the preview-only codec caveat 2026-07-16 18:36:12 -04:00
Miguel Ángel 08dbb7db37 fix(engine): ignore benign media request aborts (#2423) 2026-07-16 18:20:25 -04:00
Miguel Ángel f0aee28551 fix(engine): reuse HyperFrames browser cache (#2459)
* fix(engine): reuse HyperFrames browser cache

* test(engine): isolate browser cache home on Windows
2026-07-16 18:20:21 -04:00
Miguel Ángel 428e571914 fix(skills): align TTS docs with CLI contract (#2483) 2026-07-16 18:20:17 -04:00
Miguel Ángel 406894061e fix(core): stop composition variables from shadowing authored CSS custom properties (#2553)
A composition variable mirrored as --<slug> for a mounted sub-composition
(default or an explicit data-variable-values value) previously overrode any
same-named custom property the document already authored elsewhere (e.g. a
:root theme token), since the mirroring had no "already defined" guard —
unlike the two other emission paths, which already skip re-emitting when the
name collides with an authored definition. Extend that guard to the
sub-composition mount path in both the compiler (htmlBundler.ts) and the
runtime loader (compositionLoader.ts / getVariables.ts), so an authored
definition always wins; render-time --variables overrides still always win.
2026-07-16 18:20:13 -04:00
James Russo 065f8c9c8d Revert "docs(changelog): weekly digest 2026-06-29–2026-07-06 (#1995)" (#2571)
This reverts commit 9dc7dcd7fb.
2026-07-16 17:34:47 -04:00
James RussoandClaude Opus 4.8 9dc7dcd7fb docs(changelog): weekly digest 2026-06-29–2026-07-06 (#1995)
Auto-generated weekly digest (bun run changelog:weekly), hand-cleaned to
publish quality. Grouped into Features / Fixes / Performance / Docs &
Examples with readable one-liners and commit + PR links.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 17:32:33 -04:00
James RussoandJake Moran e96ebd74de feat(skills): add changelog-video skill for repo-native CC + Codex discovery (#2552)
Packages Jake Moran's changelog-video pipeline (v1, validated end-to-end
by Home on the Jun 23-29 range) as a repo-native skill set that Claude
Code (.claude/skills/) and Codex CLI (.agents/skills/) auto-discover the
moment the repo is opened. No install step; run the skill against a
changelog markdown for a given git range and it produces a lint-clean,
seam-gate-green 1080x1080 MP4 (~45-60s, Annie VO, mock-UI visualizations,
caption rail) end-to-end.

Six skills added byte-identical in both mirror dirs:
- changelog-video (pipeline entry point)
- motion-doctrine (carries seam-stamp.mjs + seam-gate.mjs)
- cut-the-curve, captions-overlay, seam-craft, oversized-cursor

Layout:
- .claude/skills/  - Claude Code project-local auto-discover
- .agents/skills/  - Codex CLI project-local auto-discover (verified via
                     Magi's clean-home Codex 0.144.3 repro; NOT .codex/skills/)

Fonts, animated background (12 MB), house BGM (5 MB), lexicon, and
align-captions ship inside the skill dirs. .gitattributes routes only
.claude/skills/**/*.{mp4,mp3} + .agents/skills/**/*.{mp4,mp3} through
LFS — narrowly scoped so unrelated Player, Studio, registry, and
marketplace media stay put. HeyGen CLI auth is the one credential the
skill needs; Node >= 22, ffmpeg, and headless Chrome are documented
alongside in both READMEs.

.gitignore: rewrites .claude/ and .agents/ blocks to keep agent-installed
skill hygiene while re-including the six repo-native skill dirs plus
README.md.

CI:
- Extends changes.skills filter to match .claude/skills/**,
  .agents/skills/**, scripts/lint-skills.ts, and scripts/check-skill-mirror.mjs.
- New 'Skills: project-native lint + mirror' job runs the extended
  lint-skills.ts (schema-driven; required { name, description } + optional
  { license, allowed-tools, metadata }, name pattern check, description
  length check) plus a new check-skill-mirror.mjs byte-integrity script
  (24 mirrored files must match; README.md deliberately per-CLI).
- Wired into 'bun run lint' locally.

Frontmatter validator:
- Rejects unsupported top-level keys (catches category:-style drift).
- Requires name + description.
- Validates name pattern (^[a-z][a-z0-9-]{0,63}$) and description shape
  (non-empty, <=1024 chars).
- Missing frontmatter block itself is a first-class error.

Also strips unsupported top-level 'category:' frontmatter from Jake's
motion-doctrine and cut-the-curve SKILL.mds (both mirrors), rewrites the
TTS invocation from ~/.claude/skills/media-use/... to the tracked
skills/hyperframes-media/scripts/heygen-tts.mjs, swaps npx hyperframes@latest
for the repo-local CLI in the gate step, and fixes a lint issue in Jake's
seam-gate.mjs (ternary-for-side-effect -> if/else).

Validated end-to-end by Home on Jun 23-29 (MP4 posted in C0ACCNHLG3U
thread 1784181166.041319). Independently reviewed R1/R2/R3 by Magi.

Co-authored-by: Jake Moran <jake@heygen.com>
2026-07-16 17:29:19 -04:00
James Russo 172f2757f0 feat(studio): clarify storyboard review handoff (#2560)
## What changed

- adds a stage-aware review guide for plan, sketch, animation, and final-review states
- makes the review loop explicit: review frames → save feedback → reply in agent chat
- adds copyable agent handoff and approval messages
- keeps frame status agent-owned and presents planned frames before previews exist
- clarifies voiceover ownership, save state, feedback errors, and preview availability
- improves responsive layout and surfaces storyboard warnings without dominating the board
- adds unit coverage for review-stage and handoff-step derivation

## Why

Storyboard reviewers could leave comments, but the UI did not clearly explain when a pass was ready, what to inspect, or how saved feedback reaches the agent. This makes the human-to-agent iteration loop visible while preserving the existing file-based handoff.

## Impact

Users get a clear next action throughout the storyboard lifecycle and can copy the exact message needed to continue the agent workflow. The underlying storyboard and frame-comment formats are unchanged.

## Validation

- `bun run --filter @hyperframes/studio test --run src/components/storyboard/storyboardReviewStage.test.ts` — 13 tests passed
- `bun run --filter @hyperframes/studio typecheck`
- pre-commit: tracked artifacts, lint, formatting, Fallow audit, typecheck
2026-07-16 16:16:42 -04:00
James 68beec0e76 fix(studio): guard storyboard history navigation 2026-07-16 15:49:40 -04:00
James ded443647d fix(studio): address storyboard review feedback 2026-07-16 14:56:11 -04:00
James 73dd38f93e feat(studio): clarify storyboard review handoff 2026-07-16 14:56:11 -04:00
James Russo 4b9135393e Merge pull request #2159 from heygen-com/07-10-refactor_engine_add_browser_leases
refactor(engine): add fingerprinted browser leases
2026-07-16 14:42:06 -04:00
James d4cfa08cb6 fix(engine): escalate hung browser lease closes 2026-07-16 12:58:10 -04:00
James 9b23c00237 refactor(engine): add fingerprinted browser leases 2026-07-16 12:58:10 -04:00
WaterrrForever 3bb26b0f08 docs(skills): make the core set the default install on every surface (#2554)
* docs(skills): make the core set the default install on every surface

A field test showed an agent with a real 'make videos' intent installing
all 19 skills: at install time, every surface it could read pointed at the
full set, while the core-eager / workflow-on-demand design only exists
inside hyperframes/SKILL.md - unreadable until after the install decision.

Two traps made full-install the documented default:
- The README Quick Start used 'skills add --yes': skills.sh force-detects
  agent environments into non-interactive mode, and a non-interactive run
  without --skill installs all 19. Dropping --yes fixes the human path
  (the picker opens with nothing pre-selected), but not the agent path.
- marketplace.json listed the full 'hyperframes' bundle first, under the
  name an agent installing 'hyperframes' matches; core-skills sat second.

Changes, each behavior verified by an isolated run:
- README Quick Start drops --yes (humans get the picker; verified via a
  pty capture that nothing is pre-selected) and points agents and
  non-interactive runs at 'npx hyperframes skills update', which from a
  clean HOME installs exactly the 8 core skills, refreshes stale ones and
  prunes unpublished ones on an existing machine, and is idempotent.
- CLAUDE.md and the docs install guide lead with the same one-liner;
  --all is reworded to explicit-request-only at every surface.
- marketplace.json puts core-skills first and both descriptions steer the
  default choice; the full entry keeps auto-discovery (no allowlist),
  per the skillsManifest core-pin test (56/56 pass).

* docs(skills): close the same install trap in AGENTS.md

Review follow-up on the core-default change: AGENTS.md still carried a
bare 'npx skills add heygen-com/hyperframes' - no --full-depth, and the
same non-interactive-installs-everything trap the README fix closed.
AGENTS.md is the first file Codex/Cursor-family agents read for repo
intent, so it leaked the full-set default to exactly the readers the
core-default policy targets. It now leads with the same core-set
one-liner and policy line as CLAUDE.md.
2026-07-17 00:49:43 +08:00
Miguel Ángel 771145a5c4 fix(registry): remove invalid media from caption components (#2454)
* fix(registry): remove invalid media from caption components

* test(registry): enforce nested media contracts
2026-07-16 12:16:45 -04:00
Miguel Ángel 55ee559e40 fix(lint): catch cold-seek opacity reveals (#2503)
* fix(lint): catch cold-seek opacity reveals

* fix(lint): resolve hidden selector aliases

* style(lint): format gsap rule
2026-07-16 12:03:25 -04:00
Miguel Ángel 9b17a5ad7e fix(cli): avoid Python whisper CLI collision (#2414) 2026-07-16 12:03:21 -04:00
Miguel Ángel ed1f38124b fix(engine): preserve mono audio level (#2392) 2026-07-16 12:03:17 -04:00
Miguel Ángel e846cd6004 fix(cli): fail clearly on unsupported Node versions (#2388) 2026-07-16 12:03:13 -04:00
Miguel Ángel 584be6d64a fix(transcribe): select multilingual model before download (#2303) 2026-07-16 12:03:09 -04:00
Miguel Ángel 75eedf5cc1 fix(cli): time out stalled model downloads (#2415) 2026-07-16 11:45:49 -04:00
Miguel Ángel 335e7483b5 fix(talking-head): preserve source audio (#2260) 2026-07-16 11:30:49 -04:00
Miguel Ángel b8a44e49c9 fix(lint): ignore !important in font families (#2538) 2026-07-16 10:43:17 -04:00
WaterrrForever f8c33cab72 feat(skills): act on stale CLI pin during project resume (#2540)
* feat(skills): probe and bump stale CLI pins during project resume

The entry skill now keeps a resumed project's pinned CLI current instead of
leaving that to a notice nobody acts on. On resuming a project with pinned
scripts, run the read-only probe 'npx hyperframes@latest upgrade --project
. --check'; when it (or the stale-pin stderr notice, or _meta.updateAvailable
from a pinned run) reports the project behind, apply the bump and verify
with 'hyperframes check'. A failed check reverts the bump and keeps the
project on its pinned version, preserving the reproducibility contract the
pin exists for.

The probe matters because the stale-pin notice only exists in >= 0.7.59:
a pinned run of an older CLI prints no warning at all, so a notice-only
trigger never fires for exactly the projects most behind. The probe runs
unpinned, so its behavior never depends on the project's CLI age.

Telemetry: the fleet converges to new releases within about a week via the
background auto-updater and ephemeral npx, but pinned projects form a
persistent stale tail (~10% of weekly actives, e.g. 6.3k users still on
0.6.x three weeks after 0.7.0).

Both skill surfaces now pass an explicit dir ('--project .') because a bare
'--project' followed by another flag consumes that flag as its directory
value and no-ops; the parsing fix is a separate CLI change.

* fix(cli): stop bare --project from eating the next flag as its directory

citty parses --project as a string option, so 'upgrade --project --check'
arrived with project="--check": the dir resolved to a nonexistent path and
the command no-opd with 'No package.json found' while --check was lost.
The documented default-cwd behavior only worked when --project was the
final token — and the trap-prone form is exactly what the scaffolded
template CLAUDE.md instructs.

A leading dash can never be a real directory argument, so resolveProjectArgs
now reclaims the eaten token as the flag the user wrote (--check / --json),
falls back to the current directory, and drops unrelated eaten flags rather
than treating them as paths. Templates and skill references switch to the
explicit-dir form ('--project .'), which behaves correctly on every release
including ones that predate this fix.

* feat(skills): report a successful pin bump in the run summary

Review follow-up on the stale-pin rule: 'hyperframes check' validates
composition structure, not render-output equivalence, so a check-passing
bump can still shift a project's rendered output. The bump stays the right
default for stale projects, but it must not be silent — the summary now
names the old and new version so the user knows the reproducibility
trade was made.
2026-07-16 22:28:11 +08:00
James Russo 1b4cf12cd3 refactor(cli): add stderr diagnostics logger + oxlint guard (#2551) 2026-07-16 09:35:27 -04:00
James Russo d92d1d4f51 fix(cli): keep diagnostics on stderr for --json commands (#2522) 2026-07-16 09:14:39 -04:00
Somansh ReddyandClaude Opus 4.8 5e78a29af3 docs(guides): add Claude Design → Send to HyperFrames single-file import guide (#2131)
* docs(guides): add Claude Design → Send to HyperFrames single-file import guide

Self-contained authoring guide for the 'Send to HyperFrames' MCP import path
(distinct from the download-ZIP flow): single self-contained HTML wire format,
the composition contract the importer validates, inline-brand-assets fidelity
rules (base64 data: URIs), no bundled/splash artifacts, keep-the-original-as-
reference, a complete worked skeleton, the animation-pattern catalog, and
determinism rules. Reviewed for technical accuracy against a known-good
imported+rendered composition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(send-to guide): assets must be resolvable (inline OR fetchable URL), not inline-only

Large media can exceed the import size cap, so "inline everything" is wrong for it,
and the import tool description now states "resolvable refs." Align the guide: inline
data: URIs preferred (fonts/images/logos — the only fully self-contained form), a
publicly-fetchable absolute URL allowed for large media, and explicitly forbid relative
paths / local-file variables / expiring-or-private hosts (the media-expiry trap).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 04:43:57 -07:00
Vance Ingalls dbb684fa6c Merge pull request #2535 from heygen-com/fix/runtime-partial-timeline-pause-guard
fix(runtime): tolerate registry timelines without pause() in interactive transport
2026-07-16 03:03:22 -07:00
Vance Ingalls 74f52fcd96 Merge pull request #2534 from heygen-com/fix/panel-sections-audio-layout-style-gate
fix(studio): gate Layout and Style panel sections on the element having a rendered box
2026-07-16 02:43:57 -07:00
Vance IngallsandClaude Fable 5 7e0bd401c8 chore(core): regenerate position-edits-render artifact with current esbuild
The committed artifact was generated with an older esbuild than the
current lockfile resolves; CI's check:position-edits-render regen now
produces different (equivalent) minifier variable naming and fails the
diff gate. Regenerate to match — no source change to positionEdits.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 02:17:36 -07:00
Vance Ingalls eb967f1542 Merge pull request #2533 from heygen-com/fix/studio-promotable-badge-overlap
fix(studio): reserve a gutter for the promote-to-variable badge
2026-07-16 02:06:28 -07:00
Vance Ingalls 1a2e7524e2 Merge pull request #2532 from heygen-com/fix/studio-flat-stroke-select
fix(studio): make flat inspector's Stroke width free of style-name typing
2026-07-16 02:06:07 -07:00
Vance Ingalls f96b78165e Merge pull request #2528 from heygen-com/fix/studio-flat-row-values-right-aligned
fix(studio): right-align FlatRow's value input in the flat inspector
2026-07-16 02:05:48 -07:00
James Russo 6a1585df27 refactor(render): centralize execution ownership (#2158) 2026-07-16 05:00:40 -04:00
Vance IngallsandClaude Fable 5 8826d2d71d fix(runtime): tolerate registry timelines without pause() in interactive transport
A window.__timelines entry is authored content and may be a partial
RuntimeTimelineLike (duration/seek only, no pause). Timeline resolution
is deliberately permissive — duration-based — and such compositions
render fine, because the render path only seeks. But every interactive
transport path (play/pause/seek, bind, rebind-tick, boot) called
capturedTimeline.pause() unguarded, crashing studio playback with
'tl.pause is not a function' — the top recurring studio:unhandled_error
in telemetry across versions 0.6.121 through 0.7.59 (~150-175/day).

Guard all pause sites through one helper (typeof check + swallow, plus
a once-per-page timeline_missing_pause analytics event so composition
authors can find the partial timeline), matching the safeVoid pattern
player.ts already uses. In the rebind restore path, pause is guarded
separately so a missing pause() no longer aborts the seek/play restore
behind it in the same try/catch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 01:58:39 -07:00