Commit Graph
6329 Commits
Author SHA1 Message Date
James Russo c564daf210 fix(studio): avoid inline style regex backtracking (#3708) 2026-09-05 12:58:26 -04:00
James Russo eec04340b3 fix(core): avoid grade stats regex backtracking (#3706) 2026-09-05 12:28:59 -04:00
James Russo e5d1d9bf0e fix(engine): avoid transform regex backtracking (#3704) 2026-09-05 11:53:43 -04:00
James Russo f13037ecd4 fix(engine): isolate chunked encode temporary files (#3680) 2026-09-05 11:15:46 -04:00
miga-heygen ae3d80c30f chore: release v0.8.29 (#3690) v0.8.29 2026-09-04 21:50:46 -04:00
miga-heygenandClaude Opus 4.6 00c575d23b fix(studio): prevent preview hang on burst external file rewrites (#3648)
* fix(studio): prevent preview hang on burst external file rewrites

Two interacting bugs caused Studio to freeze when multiple processes
(generator, check, snapshot) burst-wrote index.html within seconds:

1. SSE listener leak: the /api/events handler added a watcher listener
   per client connection but never removed it on disconnect. Reconnects
   accumulated dead listeners, each triggering readFileSync on every
   file change and writing to closed streams.

2. Generation starvation: processChange incremented generationRef and
   awaited drainPendingChanges. A second event arriving mid-drain bumped
   the generation, causing the first drain to bail at the generation
   check. With rapid writes, no drain ever completed and Studio stayed
   frozen on stale content.

Fix 1: use stream.onAbort() to remove the watcher listener when the
SSE connection closes.

Fix 2: gate processChange with a draining ref. While a drain is in
progress, stash the latest event. On completion, process the stashed
event — the last write in a burst always completes its reload.

Closes #3646

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

* fix(studio): align coordinator tests with drain serialization

Update existing test to expect the new behavior: when two events
fire in quick succession, the first drain completes and triggers a
reload (previously it was silently discarded). The stashed event
then starts a second drain.

Also fix the burst-write test to use the drains array pattern and
explicit act() flushes for stashed event processing.

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

* fix(studio): stash events with allowDuplicate and harden listener cleanup

Address Rames's review findings:

- Stash with allowDuplicate: true so re-dispatched events are not
  swallowed by the duplicate guard (the identity was already written
  on the way in, so the stashed event matched itself on re-entry).
- Wrap SSE keepalive loop in try/finally so the listener is removed on
  both abort and throw, not just abort.
- Restore stale-completion guard test coverage lost in the rename.
- Use await act(async () => {...}) for burst dispatches so assertions
  depend on the stash guard rather than scheduling.

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

* fix(studio): simplify drain serialization and restore SSE cleanup

Restructure processChange into intake + drain loop:

- processChange is now synchronous — validates, dedupes, checks own
  echoes, enqueues the accepted payload, and starts the drain loop
- startDrainLoop runs while the pending slot is non-null, draining
  one event per iteration via drainOnePending
- No recursive void processChange(...) from finally, so no
  allowDuplicate escape hatch needed — stashed events never re-enter
  intake guards

SSE listener: restore stream.onAbort alongside try/finally. Hono's
sleep() never throws, so finally alone doesn't fire on disconnect.
Both paths call removeListener (Set.delete is idempotent).

Tests: remove stale-drain test that contaminated subsequent tests by
emptying the shared roots array mid-test. Use sync act() for burst
dispatches — the stash decision is synchronous.

All 10 coordinator tests pass locally (NODE_ENV=test).

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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-09-04 21:44:25 -04:00
Miguel Ángel 64ce9fdf1f chore: release v0.8.28 (#3689) v0.8.28 2026-09-04 21:01:08 -04:00
James RussoandXuanru Li 9ed50028c4 fix(capture): sample computed shadows on ordinary boxes (#3686)
Co-authored-by: Xuanru Li <157947275+xuanruli@users.noreply.github.com>
2026-09-04 20:28:17 -04:00
James RussoandXuanru Li a7cdd583e7 fix(capture): retain opaque and glass button styles (#3685)
Refresh the capture fixes proposed in #1880 with browser-backed regression coverage.

Co-authored-by: Xuanru Li <157947275+xuanruli@users.noreply.github.com>
2026-09-04 20:28:07 -04:00
James RussoandThomaswebstich 65cf87de38 fix(core): scope composition root pattern selectors per instance (#3684)
Port the authored-root selector fix from Thomaswebstich in #2262 to current main.

Co-authored-by: Thomaswebstich <thomas.schnerb@gmail.com>
2026-09-04 20:27:56 -04:00
James Russoandvitalii.semianchuk 19dee4cede fix(render): serve media assets with registered content types (#3677)
Port the MIME mappings reported by fix2015 in #1836 to both render file servers.

Co-authored-by: vitalii.semianchuk <fix20152@gmail.com>
2026-09-04 19:54:29 -04:00
James Russoandyoma 7fcb5be6ea docs(registry): clarify catalog preview staging and published URLs (#3676)
Co-authored-by: yoma <yingwaizhiying@gmail.com>
2026-09-04 19:53:18 -04:00
James Russoandyoma 1f9f86c857 docs(studio): align stack note with package dependency contract (#3675)
Co-authored-by: yoma <yingwaizhiying@gmail.com>
2026-09-04 19:53:07 -04:00
James Russoandyoma 44208ceada docs(cli): document current publish workflow (#3674)
Refresh the README guidance from #1950 for current auth, visibility and updates.

Co-authored-by: yoma <yingwaizhiying@gmail.com>
2026-09-04 19:52:54 -04:00
James Russoandyoma 893141413e docs(core): fix published frame adapter reference links (#3667)
Co-authored-by: yoma <yingwaizhiying@gmail.com>
2026-09-04 19:30:59 -04:00
James RussoandDustin Persek 36ec028d5f fix(cli): forward GIF and frame-format options in batch renders (#3666)
Port Dustin Persek’s fix and command regression from #1833 onto current main.

Co-authored-by: Dustin Persek <dustin.persek@protonmail.com>
2026-09-04 19:30:50 -04:00
James Russo 66052255cf fix(producer): isolate font cache temporary writes (#3669) 2026-09-04 19:30:47 -04:00
James Russoandyoma a93106aebf docs(skills): fix creative house style reference links (#3668)
Co-authored-by: yoma <yingwaizhiying@gmail.com>
2026-09-04 19:19:25 -04:00
Miguel Ángel cb44fe1c0b fix(producer): constrain delivered AAC true peak (#3644) 2026-09-04 23:16:07 +00:00
Miguel Ángel 32f9ed9880 fix(producer): preserve nested entry asset base (#3645) 2026-09-04 23:16:03 +00:00
Miguel Ángel 3314168e30 fix(producer): guard disk capture capacity (#3643) 2026-09-04 23:15:53 +00:00
Miguel Ángel c0303fc523 fix(engine): fail closed on blocked SRI scripts (#3664) 2026-09-04 23:15:41 +00:00
Miguel Ángel 50af764b7d fix(producer): scale high-quality encode timeout (#3649) 2026-09-04 23:15:37 +00:00
Miguel Ángel 2ca493094e fix(producer): follow variable audio duration (#3647) 2026-09-04 23:15:33 +00:00
Miguel Ángel 78a28b8942 fix(producer): preserve render warning attribution (#3642) 2026-09-04 23:15:30 +00:00
Miguel Ángel f334b0e735 fix(engine): retry capture screenshot timeouts (#3641) 2026-09-04 23:15:14 +00:00
Miguel Ángel c8ddbe0a4b fix(runtime): align nested activation to export frames (#3640) 2026-09-04 23:14:50 +00:00
James Russo 723cd0d785 fix(studio-server): block dangling symlink upload escapes (#3661)
* fix(studio-server): block dangling symlink upload escapes

* fix(studio-server): contain rename reference updates
2026-09-04 19:03:08 -04:00
James RussoandKamal Kannan 7b772465e3 docs(adopters): add PandaStudio (#3663)
Co-authored-by: Kamal Kannan <kamalkannan.sankarraj@gmail.com>
2026-09-04 18:51:06 -04:00
James Russoanderen-commits f7cac7287a docs(adopters): add Mini Course Generator (#3662)
* Add Mini Course Generator to adopters list

Added a new card for the Mini Course Generator showcasing its AI-powered course generation capabilities.

* docs(adopters): add Mini Course Generator

---------

Co-authored-by: eren-commits <eren@minicoursegenerator.com>
2026-09-04 18:40:10 -04:00
James RussoandCarlos Alcaraz dd06b321cd fix(shader-transitions): preserve gravitational lens start frame (#3660)
Builds on #1579, verified with hardware WebGL endpoint and intermediate pixel comparisons.

Co-authored-by: Carlos Alcaraz <193642530+calcarazgre646@users.noreply.github.com>
2026-09-04 18:40:00 -04:00
James RussoandAGRO-CODEX 0ad9c700ac fix(lint): give randomness guidance for crypto values (#3659)
Builds on #1729 in the extracted lint package.

Co-authored-by: AGRO-CODEX <brstopo@gmail.com>
2026-09-04 18:39:51 -04:00
James RussoandKiyeon Jeon 29efd5dfa8 docs(registry): document installer metadata (#3658)
Co-authored-by: Kiyeon Jeon <kiyeon.jeon.21@gmail.com>
2026-09-04 18:39:41 -04:00
James Russo d2741b3a28 fix(studio-server): preserve binary file writes and versions (#3653)
* fix(studio-server): preserve binary file writes and versions

* fix(studio-server): rely on exclusive file creation for POST

* test(studio-server): create race fixture atomically
2026-09-04 17:44:19 -04:00
James Russo 924b98a0dc fix(captions): preserve zero plate grain in generated postfx (#3656) 2026-09-04 17:38:43 -04:00
James Russo 3bc46a8ade fix(studio-server): cascade GSAP cleanup when deleting subtrees (#3655) 2026-09-04 17:38:33 -04:00
James RussoandAkshay Kumar Sharma ef63e02936 fix(fonts): retain non-Latin subsets for bundled weights (#3652)
Builds on #3086 with canonical alias supplementation and bundled Latin precedence.

Co-authored-by: Akshay Kumar Sharma <25038017+akzarma@users.noreply.github.com>
2026-09-04 17:38:24 -04:00
James Russo bec11b1293 fix(runtime): wait for a finite dotlottie duration (#3651) 2026-09-04 17:37:53 -04:00
heygengenesis[bot]andmiguel.sierra 62d3304caf fix(embedded-captions): support heroless themes (#3632)
Co-authored-by: heygengenesis[bot] <262951085+heygengenesis[bot]@users.noreply.github.com>
Co-authored-by: miguel.sierra <229591595+miguel-heygen@users.noreply.github.com>
2026-09-04 18:27:47 +00:00
Miguel Ángel 19a512c05a fix(cli): count font axes as motion in the sweep fingerprint (#3107)
The layout audit fingerprints each element by rect and opacity, plus an
8x8 pixel hash for canvas and video. A composition whose only change over
the timeline is font-variation-settings touches none of those, so all six
samples hash identically and the audit reports sweep_static on a timeline
that is visibly animating.

Duplexed variable fonts make it unavoidable rather than unlikely. Recursive
holds one advance width across its whole weight axis by design, so even the
element rect stays fixed while the letterforms change.

Fold the computed font-variation-settings into the per-element fingerprint.
It reads normal on every element that does not use the property, so no
existing composition's fingerprint changes.

This is the third instance of this failure class in the same function,
after the canvas-repaint and opacity-reveal cases whose regression tests
already sit alongside these. Two more join them: a scene where only the
axes move must change the fingerprint, and a scene where nothing moves
must hash identically twice. The second is the load-bearing one, since a
fingerprint that varies on its own would make sweep_static unfireable and
every green layout verdict meaningless.
2026-09-04 18:07:32 +00:00
Miguel Ángel e147613542 fix(cli): upgrade project wrapper pins (#3042) 2026-09-04 18:06:51 +00:00
Miguel Ángel 709d70c675 fix(cli): render SVG selector proof strips (#3537) 2026-09-04 18:06:49 +00:00
Miguel Ángel 2dc4bbfa75 feat(cli): forward a reported catalog gap to the feedback channel (#3204)
A search miss already reached PostHog, where nobody was watching it. It now
also goes to the same channel a CLI rating goes to, by the same best-effort
POST, so a move the catalog is missing is read rather than queried.

The forward is bounded and swallowed, and the ack prints before it, so a gap
report can never fail or delay the command that sent it.
2026-09-04 18:06:36 +00:00
Miguel Ángel 353b9eb3da fix(producer): scale frame coverage by playback rate (#3542) 2026-09-04 18:06:34 +00:00
Miguel Ángel ece09d830d fix(studio): drop the resurrected WebMCP polyfill assertion (#3556)
#3516 merged from a branch cut before da6514d45 and brought back
`expect(document).not.toHaveProperty("modelContext")`, along with the old
test title. This re-applies that fix.

The assertion is racy, not merely wrong. The hook awaits a dynamic import
of the `@mcp-b/global` polyfill inside its mount effect, so whether
`document.modelContext` exists when the assertion runs depends only on
whether that import has resolved yet. `await act()` usually returns first,
which is why main went green while another PR's run went red. Inserting a
100ms wait before the assertion on the current tip makes it fail every
time, and the failure dump shows all five tools registered through the
polyfill: the real behaviour is the opposite of what the line asserted.

Installing `document.modelContext` where the browser has none is the
polyfill's job. What the case is really for is that mounting does not
throw, so a browser without native WebMCP still boots Studio.
2026-09-04 18:06:24 +00:00
Miguel Ángel faaafbb251 fix(cli): split Kokoro text on token overflow (#3041) 2026-09-04 18:06:15 +00:00
heygengenesis[bot]andmiguel.sierra 0154b40b65 fix(captions): derive preview GSAP integrity (#3631)
Co-authored-by: heygengenesis[bot] <262951085+heygengenesis[bot]@users.noreply.github.com>
Co-authored-by: miguel.sierra <229591595+miguel-heygen@users.noreply.github.com>
2026-09-04 18:04:26 +00:00
Miguel Ángel a3954aa1cb fix(cli): persist what the server answered for a captured page (#3553)
* fix(cli): persist what the server answered for a captured page

A page that renders is not a page that succeeded. An error page has a title,
a palette, typefaces and a DOM, so every extractor downstream reads it happily
and produces a design system belonging to whoever wrote the error page rather
than to the site's owner.

The status was already read, once, to feed `detectBlockedPage`, and then
dropped. That helper cannot stand in for it: it decides whether the rendered
document LOOKS like a protection wall, over a minimal-DOM heuristic that a
rich error page passes. "Was this blocked?" and "what did the server answer?"
are two questions, and widening the first to carry the second would leave a
heuristic owning a fact.

So the response status is persisted plainly, as its own record, and every
consumer decides for itself what a non-success response means for its product.
Written before the blocked-page check runs, so the record's absence means
"navigation never produced a response" — a third state distinct from a status
of 404 and from a status of null.

* fix(cli): report the response status in the capture command's JSON output

The status reached `CaptureResult` and was then dropped at the CLI boundary,
which is the same read-once-and-discard that made the error page harvestable
in the first place. `--json` is the documented programmatic surface, and an
agent reading `ok: true` off a capture of a 404 has no way to see it there.
2026-09-04 18:03:35 +00:00
WaterrrForever c8300c69a1 fix(cli): install the published skill set, not every SKILL.md in the repo (#3636)
Bare `hyperframes skills` passed `--skill '*'` to the upstream installer, which discovers every SKILL.md in the clone, so a full install put 26 skills on disk against the 20 the manifest publishes (the six repo-internal ones under .claude/skills / .agents/skills). It now resolves the canonical manifest and installs its names, the same path `skills update` uses; offline it warns and degrades to the pinned core set instead of the wildcard. Docs point the full set at `npx hyperframes skills` and say what `skills add --all` really pulls.
2026-09-04 23:25:43 +08:00
WaterrrForever c5224ac7e3 feat(cli): snapshot --against pairs each frame with a reference video (#3637)
Rebuilding footage means checking the render against the source at the same timestamps. `--against <video>` saves the reference frame at every captured time (frame-exact seek: -ss after -i) plus a labelled render|reference pair sheet built with the existing contact-sheet helper. Reference frames and pair sheets are derived artifacts, kept out of the snapshot list like contact-sheet.jpg. No new dependencies.
2026-09-04 23:25:36 +08:00