Skip to content

fix: alpha preview e2e fixes — exports, init templates, EPIPE crash#693

Merged
miguel-heygen merged 2 commits into
nextfrom
fix/alpha-e2e-fixes
May 9, 2026
Merged

fix: alpha preview e2e fixes — exports, init templates, EPIPE crash#693
miguel-heygen merged 2 commits into
nextfrom
fix/alpha-e2e-fixes

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen commented May 9, 2026

Summary

Bugs and UX gaps found via automated e2e testing (8 iterations, 424 assertions) and manual power-user audit of the v0.6.0-alpha studio.

E2e fixes (commit 1)

  • core: missing export specifiers@hyperframes/core was missing ./studio-api/manual-edits-render-script and ./studio-api/studio-motion-render-script in its exports map. The alpha.3 npm publish failed because the studio vite build couldn't resolve these sub-paths.

  • cli: init --example creates empty projects — All 7 example templates produced projects with no HTML files. Root cause: tsup leaves empty template directories in dist/, causing existsSync(templateDir) to return true and skip the remote registry fetch fallback. Fixed to check for index.html inside the directory instead.

  • engine: unhandled EPIPE crash in streaming encoderffmpeg.stdin had no error handler, so a write after the ffmpeg process exits throws an uncaught Error: write EPIPE that crashes the Node process.

Studio power-user audit fixes (commit 2)

  • Thumbnail crash kills entire studio — A single thumbnail request can take down the whole vite dev server. Puppeteer's TimeoutError propagates as an uncaught rejection. Wrapped the thumbnail promise chain in try/catch with proper page cleanup.

  • Motion panel and manual editing OFF by defaultSTUDIO_MOTION_PANEL_ENABLED and STUDIO_PREVIEW_MANUAL_EDITING_ENABLED both defaulted to false, undiscoverable without knowing the env vars. Changed defaults to true.

  • Multi-selection shows empty design panel — When multiple elements are selected, the PropertyPanel showed "Select an element" with no indication that multiple were selected. Now shows "N elements selected" with guidance.

  • Render hardcodes 30fps — The export bar had no FPS selector; all renders were forced to 30fps regardless of composition. Added a 24/30/60 FPS dropdown.

Test plan

  • Full monorepo build passes (bun run build)
  • All 785 core unit tests pass
  • Studio typecheck clean
  • Pre-commit hooks (lint + format + typecheck) pass
  • 8 consecutive e2e iterations with zero flakiness
  • init --example warm-grain creates project with index.html
  • 4K render produces 3840x2160 output

🤖 Generated with Claude Code

miguel-heygen and others added 2 commits May 9, 2026 07:21
Three bugs found via automated e2e testing of the v0.6.0-alpha preview:

1. core: add missing package.json export specifiers for
   studio-api/manual-edits-render-script and
   studio-api/studio-motion-render-script — the alpha.3 npm publish
   failed because the studio build could not resolve these sub-paths.

2. cli: fix init --example creating empty projects — tsup leaves empty
   template directories in dist/ during the build, causing
   existsSync(templateDir) to return true and skip the remote fetch
   fallback. Now checks for index.html inside the dir instead.

3. engine: fix unhandled EPIPE crash in streaming encoder — ffmpeg
   stdin/stdout had no error handlers, so a write after the ffmpeg
   process exits throws an uncaught error that crashes the process.

Verified with 8 consecutive e2e iterations (424 test runs, 0 flaky).

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

Power-user audit fixes for the alpha studio:

- vite.config.ts: wrap thumbnail generation in try/catch so Puppeteer
  TimeoutError doesn't crash the entire vite dev server as an uncaught
  rejection. Close the page on error to prevent browser session leaks.

- manualEditingAvailability.ts: enable motion panel and manual canvas
  drag editing by default (were both false, undiscoverable without
  knowing the env vars).

- PropertyPanel.tsx: show "N elements selected" feedback when multiple
  elements are selected instead of the generic "Select an element"
  empty state.

- RenderQueue.tsx + App.tsx: add FPS selector (24/30/60) to the render
  export bar instead of hardcoding 30fps. Pass the user's choice
  through to startRender.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@miguel-heygen miguel-heygen merged commit 513deb4 into next May 9, 2026
24 checks passed
@miguel-heygen miguel-heygen deleted the fix/alpha-e2e-fixes branch May 9, 2026 20:04
miguel-heygen added a commit that referenced this pull request May 10, 2026
Prevent users from selecting elements in the preview while the
composition is still loading (showing "Loading composition" overlay).
Selection and hover highlighting are suppressed until the player fires
the ready event.

Also reverts motion panel and manual drag editing defaults to false —
these were accidentally set to true during the PR #693 merge.

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

@vanceingalls vanceingalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post-merge advisory review (this PR is already merged into next). Findings flagged for follow-up, not gating.

Verdict — Approve, 3 follow-ups

Solid bundle of three real bug fixes (missing exports, init template detection, EPIPE crash) plus power-user audit fixes. The export-specifier fix unblocked the alpha.3 npm publish — that's a real ship-blocker resolution. EPIPE handler is overdue.

Follow-ups

  1. The "feature defaults" commit in this PR set Motion + manual drag to true — then got reverted in PR #695. Commit 2 of this PR flipped STUDIO_MOTION_PANEL_ENABLED and STUDIO_PREVIEW_MANUAL_EDITING_ENABLED defaults to true, then PR #695 (~2h later) reverted them as "accidentally set to true during the PR #693 merge conflict resolution." This is a pattern worth flagging — defaults for alpha-gated features should not change in PRs whose title is "alpha preview e2e fixes — exports, init templates, EPIPE crash." The defaults change is a product decision, not a fix. Reason: hard to audit. The reviewer who looked at the title would not have caught a defaults flip buried in the diff.

  2. EPIPE fix doesn't have a regression test. ffmpeg.stdin got an error handler — good. But there's no test that asserts: "if ffmpeg exits mid-stream, the Node process doesn't crash." Reason: this exact bug pattern (uncaught rejection on a stream error) is easy to reintroduce in future streamingEncoder edits. A test using a mocked ffmpeg that exits early would catch it.

  3. init --example template-detection fix uses index.html as the sentinel. The fix: check for index.html inside the dir instead of just existsSync(templateDir). Reason: this hardcodes the assumption that every template has an index.html at its root. If a future template uses a different entry file (e.g. main.tsx for a React-only template), the fallback fetch will incorrectly fire. Worth either: documenting the assumption, or using a manifest-based check (e.g. templateDir/template.json).

Important

  • Thumbnail crash fix wraps Puppeteer in try/catch — good, but doesn't address the root cause of the timeout. Why was Puppeteer taking >30s? Is the browser pool over-saturated? A graceful-degrade is the right immediate fix, but the underlying capacity question is unanswered. Reason: thumbnails silently failing means renders queue without preview cards, and users lose state visibility.

  • FPS selector hardcodes [24, 30, 60]. What about 25 (PAL) or 23.976/29.97 (NTSC drop-frame)? Not blocking for alpha, but the comment-only menu suggests this wasn't considered.

Nits

  • 8 consecutive e2e iterations / 424 assertions is a strong verification claim — would be even stronger as a recorded CI artifact rather than a local-run citation.

Praise

  • The detective work on the init --example bug (tsup leaves empty template dirs in dist/ → existsSync returns true → skip fallback) is exactly the kind of root-cause-vs-symptom diagnosis the debugging principles ask for.
  • The export-specifier fix turning a failed npm publish into a successful one is a critical-path unblock.

— Vai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants