Skip to content

docs(skills): document mounting one composition file several times - #6208

Open
OldSlowDog wants to merge 1 commit into
heygen-com:mainfrom
OldSlowDog:docs/6139-multi-mount-format-v2
Open

OldSlowDog wants to merge 1 commit into
heygen-com:mainfrom
OldSlowDog:docs/6139-multi-mount-format-v2

Conversation

@OldSlowDog

@OldSlowDog OldSlowDog commented Oct 24, 2026 •

Copy link
Copy Markdown

What changed

Added a short "Mounting one composition file several times" section to skills/hyperframes/references/format.md, just below the existing "host id = scene id = timeline key" rule.

Why

Issue #6139's failing case is real: [data-composition-id="step"] .sc throws once per mount. The shared id is not the cause — mounting one file several times with the same data-composition-id on every host is supported:

  • compositionLoader.ts detects the duplicate and rewrites the repeated hosts to <id>__hf1, <id>__hf2 (uniqueCompositionId), keeping the authored id on data-hf-original-composition-id and scoping that mount's document.querySelector, GSAP targets and window.__timelines entry to it.
  • Lint's duplicate_composition_id skips data-composition-src hosts for the same reason: they are mounts, not composition roots.

What breaks is targeting from inside the scene by that id. After the rename no host carries step any more, so the prefixed selector matches nothing.

The section therefore says that mounts share data-composition-id and differ by their own element id and data-variable-values, and that in-file selectors should use a class — an element id still has to satisfy the page-wide uniqueness rule on that page — never [data-composition-id="..."].

Related work

How

Documentation only: six added lines to one existing file. Rewritten after review — the earlier revision described the shared id itself as the failure and gave the hosts distinct ids in an example, which contradicted the "same id" rule on the same page.

Test plan

  • Docs-only; no unit or integration tests apply.
  • The diff is +6/−0 on format.md, so the surrounding rules — including the Google Fonts caching line — are untouched.
  • No packages/studio / packages/player changes, so the PR-captures (scripts/check-pr-captures.mjs) requirement does not apply.

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for picking up #6139. The failing case in that issue is real and worth documenting, but I think this section describes a different cause than the one the engine has.

  • Mounting one file several times with the same data-composition-id on every host is supported. The runtime renames repeated hosts to step__hf1, step__hf2, and so on (packages/core/src/runtime/compositionLoader.ts, around lines 385-404), and the scene script's document.querySelector, GSAP targets and window.__timelines["step"] are all redirected to that mount (packages/core/src/compiler/compositionScoping.ts). That's also why the duplicate_composition_id lint rule skips data-composition-src hosts on purpose (packages/lint/src/rules/composition.ts, the comment above the data-composition-src check). It matches the issue's own observation that shared ids work with a plain .sc selector.
  • What breaks in the issue is the selector [data-composition-id="step"] .sc. After the rename, no host carries step any more, so it matches nothing and the script throws once per mount. Your second bullet ("don't prefix in-file selectors with the composition id") is the right advice. It's the reason that's off: the prefixed selector matches none of the mounts, not all of them.
  • The example gives hosts step-1..step-7 while the scene root stays step. That contradicts the rule a few lines above it on the same page ("Give the host, the scene root and the timeline key the same id ..."), so a reader would get two opposite instructions.

Suggested direction: keep the section short. Say that one file can be mounted several times with the same id, that the runtime gives each mount its own id behind the scenes, and that scene scripts should target elements by class or local id, never by [data-composition-id="..."], because that id is rewritten per mount.

Separately, the branch is based on a much older main and adds format.md as a new file, so it conflicts with the current one. Taking this branch's copy would also drop a fonts line that was added on main since. A rebase onto current main, so that the diff is only the new section, will fix both.

Verdict: REQUEST_CHANGES
Reasoning: The new guidance contradicts how the runtime and lint handle repeated mounts and conflicts with an existing rule on the same page, and the branch has merge conflicts that would drop current content.

@OldSlowDog
OldSlowDog force-pushed the docs/6139-multi-mount-format-v2 branch from bdabf65 to 139e012 Compare October 25, 2026 05:00
@OldSlowDog OldSlowDog changed the title docs(skills): clarify unique data-composition-id per host for multi-mount docs(skills): document mounting one composition file several times Oct 25, 2026
@OldSlowDog

Copy link
Copy Markdown
Author

Thanks for the detailed correction — both points are fixed in 139e012c.

You're right about the cause. I rewrote the section around it: repeated mounts sharing an id are supported (the runtime rewrites them to <id>__hf1 / <id>__hf2 and keeps the authored id on data-hf-original-composition-id), and what breaks is targeting by [data-composition-id="…"] from inside the scene — after the rename it matches nothing, not everything. I also dropped the step-1 … step-7 example, which contradicted the same-id rule a few lines above it, and cut the section down to two paragraphs.

The branch is rebased onto current main, so the diff is now just those six added lines: format.md shows as modified rather than added, and the fonts caching line is back.

@OldSlowDog
OldSlowDog force-pushed the docs/6139-multi-mount-format-v2 branch 3 times, most recently from bfc3786 to 83026b1 Compare October 25, 2026 05:26
@OldSlowDog

Copy link
Copy Markdown
Author

Two refinements after that — head is now 83026b1.

  • Which id is shared. Re-reading format.md:66 host-id rule is ambiguous for multi-mount sub-compositions; scoped selector silently yields static frames #6139, the working setup there is distinct element ids (id="s1" … s7) with data-composition-id="step" on every host. So the shared thing is the composition id, not the host element id. The section now says that explicitly — one id per host is what my first draft did, and it is an easy reading to take from the issue.
  • The #headline example was misleading. Pairing it with .sc implied that reusing an element id across mounts was equally fine, while the rule three bullets above requires ids to stay unique across the assembled page. The advice now prefers a class, and says that an element id still has to satisfy that rule.

Still six added lines on format.md, rebased on current main.

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the rework. Everything from my last review is addressed: the section now says repeated mounts can share a data-composition-id, explains that the prefixed selector matches nothing after the rename, drops the step-1..step-7 example, and the branch is rebased so the diff is just the new section. I checked the new wording against the rename in compositionLoader.ts, the per-mount query, GSAP and timeline scoping in compositionScoping.ts, and the lint rule, and it matches.

One thing before this can merge: changing format.md changes the hyperframes hash in skills-manifest.json, so the required "Skills: manifest in sync" check will fail once CI runs on this branch. Running bun run --cwd packages/cli gen:skills-manifest and committing the updated skills-manifest.json fixes it.

Two optional wording nits:

  • The section uses step without saying where it comes from (the example just above uses intro). Something like "an id such as step" on first use would help.
  • "An element id works too, but it still has to keep the page-wide uniqueness rule above": an id inside a file mounted several times appears once per mount, so it can never meet that rule. "Use a class for anything inside a file you mount more than once" would say it more directly.

Verdict: APPROVE
Reasoning: The guidance now matches how the runtime and lint handle repeated mounts and all earlier points are fixed; the manifest regeneration is mechanical and enforced by a required check.

Two wording fixes from review:

- `step` now arrives with "(an id such as `step`)" on first use: the example
  above uses `intro`, so the bare id read as coming from nowhere.
- Dropped "an element id works too, but it still has to keep the page-wide
  uniqueness rule above": an id inside a file mounted N times appears once per
  mount, so it can never satisfy that rule. It now says to use a class for
  anything inside a file mounted more than once, which is the only thing that
  actually holds.

`format.md` is part of the `hyperframes` bundle, so its content hash in
`skills-manifest.json` changed (77 files, 76c914f4... -> 5ddcce65...);
regenerated so the "Skills: manifest in sync" check passes.
@OldSlowDog
OldSlowDog force-pushed the docs/6139-multi-mount-format-v2 branch from 83026b1 to cf82bac Compare October 25, 2026 10:47
@OldSlowDog

Copy link
Copy Markdown
Author

Done in cf82bac — skills-manifest.json regenerated: hyperframes 76c914f4… → 5ddcce65…, still 77 files, and nothing else in the manifest moved.

Both nits taken as well:

  • step now arrives as "(an id such as step)" on first use.
  • The id advice is replaced with "use a class for anything inside a file you mount more than once". You're right that the old sentence was self-defeating: an id inside a file mounted N times appears once per mount, so it can never satisfy the page-wide rule.

One note on the manifest, so you know what you're reviewing: this checkout is a partial clone, so I couldn't run bun run --cwd packages/cli gen:skills-manifest directly. I reproduced hashSkillBundle from packages/cli/src/utils/skillsManifest.ts and checked it against unchanged content first — it reproduces all seven committed hashes exactly — then applied it to the changed bundle. If CI disagrees, tell me and I'll redo it with the real script.

@OldSlowDog

Copy link
Copy Markdown
Author

Correction to the note above: I did end up running the real generator, and it agrees.

bun run --cwd packages/cli gen:skills-manifest does fail in this checkout — it shells out to tsx, which isn't installed. But bun executes TS directly, so the script runs as-is:

$ bun packages/cli/scripts/gen-skills-manifest.ts
Wrote …/skills-manifest.json (7 skills)
  ~ hyperframes (76c914f47480032c → 5ddcce65cb21e3e3)

Against a full tree with this branch's format.md in place, the output is byte-identical to what is committed here (633 bytes, same sha256), and --check exits 0:

$ bun packages/cli/scripts/gen-skills-manifest.ts --check
✓ skills-manifest.json is in sync (7 skills)

So the committed manifest is not a hand-computed approximation — it is what the generator writes, diff hyperframes only.

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks, this looks good. Both wording changes read well, and the "use a class" line is clearer than the old id sentence.

I checked the manifest update by running bun packages/cli/scripts/gen-skills-manifest.ts --check at this commit, and it reports the manifest in sync, so your reimplementation of the hash matches the real script.

The repository's CI workflows haven't run on this branch yet, so I'm leaving this as a comment for now. Once a maintainer approves the workflow run and the checks are green, this is ready from my side.

Verdict: COMMENT
Reasoning: All earlier points are fixed and the manifest check passes when run locally, but CI has not run on the fork head yet.

This branch has not been deployed

No deployments
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