Skip to content

fix(producer): resolve template sub-composition entries in the shared compile stage - #7217

Merged
jerrai-bot-heygen merged 1 commit into
mainfrom
jerrai/hf_distributed_template_entry-11052026
Nov 5, 2026
Merged

jerrai-bot-heygen merged 1 commit into
mainfrom
jerrai/hf_distributed_template_entry-11052026

Conversation

@jerrai-bot-heygen

Copy link
Copy Markdown
Contributor

What

Rendering a <template>-wrapped sub-composition alone (entry file such as compositions/sting.html) through the distributed planner now works. The mounted-shell extraction moves from renderOrchestrator.ts into runCompileStage, which both the in-process renderer and plan() already call.

Why

plan() set htmlPath = join(projectDir, entryFile) and compiled the raw file. A template entry has no live root, its script never runs, so the probe found no timeline and no duration. Production symptom (render service, /v2/distributed/plan-s3, 500 INTERNAL_ERROR, found by Cut Room's hf_render composition= "render alone" preview):

[FrameCapture] Composition has zero duration.
  Runtime ready: true, __player: true, __hf.seek: true, GSAP timeline: false, data-duration: not set

Only the in-process path handled this (extractStandaloneEntryFromIndex in renderOrchestrator.ts), so the two lanes had diverged. Before the fix, the new plan test reproduces exactly this error (browser probe, "root duration unknown").

Related work

None linked (found from a Cut Room walk, not a filed issue).

How

  • resolveEntryHtmlPath (new, exported from compileStage.ts): index entries and non-template files return join(projectDir, entryFile) unchanged; a template entry is isolated inside the project's index.html shell via extractStandaloneEntryFromIndex, written to <workDir>/standalone-entry.html, with the same two errors as before (no index.html; not mounted by a data-composition-src host). Nothing is keyed to one file name or tag shape; it derives from isTemplateEntry and the mount host.
  • runCompileStage derives the path itself, so htmlPath is removed from CompileStageInput: a caller can no longer skip the resolution. The orchestrator block is deleted and plan.ts drops the argument. Both callers keep their own entry-file-exists checks and error text.
  • Money/DB: none.

Test plan

Run from packages/producer:

  • bun test src/services/distributed/plan.test.ts — 73 pass, 1 fail. The failure is stitched mp4 plans > locks each ProRes profile's preset and pixel format into a mov plan, a 120 s timeout in a mov/ProRes plan test that does not touch entry resolution; I did not confirm it on origin/main, CI will show.
    • New: plans a template-wrapped sub-composition alone and gets totalFrames 90 (3 s at 30 fps); rejects a template entry that index.html does not mount. Both fail before the fix with the zero-duration error above.
  • bunx vitest run src/services/render/stages/compileStage.test.ts src/services/render/stages/compileStage.mediaType.test.ts — 21 pass, including new resolveEntryHtmlPath cases (plain entry untouched and no wrapper written, non-template sub-composition untouched, template isolated in the index shell, unmounted refused, no index.html refused).
  • bun run typecheck in packages/producer — clean. oxlint and oxfmt on the 6 changed files — clean.
  • Index entry unchanged: planning an index.html project before and after gives identical planHash (daa0ae639e3e8518656c0d1f8d9bc9d2ef904229ae2715cd0dcbdd258e593fea) and identical compiled/index.html sha256 (209fe53bd0180ccc4936eec2874d7d492f503f9104dcab990b5e61154ebf85ad).
  • The in-process path is the same code moved verbatim (same messages and log line); there was no in-process template-entry test in the producer, so the new resolveEntryHtmlPath tests now cover it for both lanes.

Not exercised:

  • No render of a real DEV project and no chunk-worker or Lambda run; only plan-time compile.

  • scripts/check-comment-citations.mjs and scripts/comment-ratchet.mjs could not run locally (this box's git lacks check-attr --source); CI runs them.

  • Template entry with a probe-time (non-static) duration was not exercised; the fixture declares data-duration.

  • The published @hyperframes/producer version the render service pins needs a release before consumers see the fix.

  • Unit tests added/updated

  • Manual testing performed

  • Documentation updated (if applicable): no user-visible CLI flag or command change

  • Comments follow CONTRIBUTING.md "Comments"

— Jerrai

… compile stage

The distributed planner compiled the raw entry file, so a <template>-wrapped
sub-composition rendered alone had no live root, timeline or duration and failed
with "Composition has zero duration". Entry resolution now lives in
runCompileStage, which both the in-process renderer and plan() call.

— Jerrai
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 103 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (8)

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head b9ce940

This moves the code without changing its behavior. runCompileStage now resolves the entry itself, and htmlPath is gone from CompileStageInput. plan.ts and renderOrchestrator.ts are its only two callers, so neither can skip the template isolation.

Scope
  • Read all 6 files. The orchestrator never used htmlPath after the compile step, so leaving it as the raw entry path changes nothing downstream.
  • Plan lane: the wrapper is written to <planDir>/.plan-work/standalone-entry.html. That directory is removed before freezePlan, so the wrapper does not enter the planHash or the planDir sent to workers. This matches the unchanged index.html planHash in the description.
  • No other code or test mocks extractStandaloneEntryFromIndex/isTemplateEntry, so the removed import in the orchestrator breaks nothing.
  • CI on this head passed, including Producer unit and integration tests, regression, and Windows render verification. The local ProRes mov plan timeout did not show up in CI.
  • Not covered here: a real DEV distributed render. It needs a producer release first, as the description says.

@jerrai-bot-heygen
jerrai-bot-heygen added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit 0180c60 Nov 5, 2026
91 checks passed
@jerrai-bot-heygen
jerrai-bot-heygen deleted the jerrai/hf_distributed_template_entry-11052026 branch November 5, 2026 10:04
@heygengenesis heygengenesis Bot mentioned this pull request Nov 5, 2026
mitanshu450 pushed a commit to mitanshu450/hyperframes-video-generation that referenced this pull request Nov 5, 2026
* chore: release v0.9.16

* chore: format v0.9.16 release notes

* chore: add heygen-com#7228 and heygen-com#7231 to v0.9.16 notes

* chore: add heygen-com#7217 heygen-com#7224 heygen-com#7225 heygen-com#7226 heygen-com#7229 heygen-com#7233 to v0.9.16 notes
SanHsien added a commit to SanHsien/hyperframes that referenced this pull request Nov 6, 2026
…eview

Adopts or partially adopts 11 groups: multi-worker tween replay behind
the timeline stand-in (heygen-com#7231), template entries in the shared compile
stage (heygen-com#7217), HYPERFRAMES_CACHE_DIR and HYPERFRAMES_CONFIG_DIR for
every per-user cache and settings file (heygen-com#7224, heygen-com#7229; HeyGen
credentials stay under HEYGEN_CONFIG_DIR), WebKit audio clock (heygen-com#7225),
packet-based video length (heygen-com#7233), HLG tone mapping (heygen-com#7234), fetch
network cause (heygen-com#7236), .hyperframesignore in lint (heygen-com#7239), info
--media (heygen-com#7235), lint priority (heygen-com#7244), check --budget (heygen-com#7245) and the
unknown-command answer (heygen-com#7247). bun.lock gains only the lint `ignore`
edge from heygen-com#7239, already resolved. Watermark advances to 0a6746e.

Co-authored-by: Jerrai <[email protected]>
Co-authored-by: Miguel Ángel <[email protected]>
Co-authored-by: WaterrrForever <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.

1 participant