LICENSE
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2026 HeyGen, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
MIRROR.md
# heygen-com/hyperframes Skill Mirror
Mirrored skill: general-video
Published skill: hyperframes-general-video
Source: https://github.com/heygen-com/hyperframes.git
Source path: skills/general-video
Branch: main
Commit: 0d5d3f3eb3aecd9fd64954d2767d3d64e97e58fc
This skill is vendored from heygen-com/hyperframes. Naturally namespaced `hyperframes*` names are preserved; generic names receive a `hyperframes-` prefix to avoid global skill-name collisions. Only frontmatter names and concrete references to renamed skill directories are adapted so sibling scripts and documentation remain resolvable after installation. Product and CLI commands, internal identifiers, scripts, tests, assets, and workflow behavior remain upstream material. Automatic source updates arrive through this mirror workflow. See `LICENSE` for the preserved Apache-2.0 terms.
scripts/frame-packets.mjs
#!/usr/bin/env node
// Thin wrapper over the shared packet builder in hyperframes-core — this file pins
// this workflow's paths plus its one behavioral difference: design truth resolves
// frame.md → design.md → DESIGN.md (general-video § 6 order). Everything else has
// one owner: ../../hyperframes-core/scripts/lib/frame-packets-core.mjs
import { existsSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import * as core from "../../hyperframes-core/scripts/lib/frame-packets-core.mjs";
const SKILL_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..");
function designTruthLine(projectDir) {
for (const name of ["frame.md", "design.md", "DESIGN.md"]) {
const candidate = join(resolve(projectDir), name);
if (existsSync(candidate)) return `- Design truth: ${candidate}`;
}
return `- Design truth: ${join(resolve(projectDir), "frame.md")}`;
}
const CONFIG = {
animationDir: resolve(SKILL_DIR, "../hyperframes-animation"),
corePath: resolve(SKILL_DIR, "../hyperframes-core/references/frame-worker-core.md"),
deltaPath: resolve(SKILL_DIR, "sub-agents/frame-worker.md"),
designTruthLine,
};
export function buildRolePayload({ outDir }) {
return core.buildRolePayload({ ...CONFIG, outDir });
}
export function buildFramePackets(options) {
return core.buildFramePackets({ ...CONFIG, ...options });
}
if (core.isMainModule(import.meta.url)) core.runCli({ buildFramePackets, buildRolePayload });
scripts/frame-packets.test.mjs
import assert from "node:assert/strict";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import test from "node:test";
import { buildFramePackets } from "./frame-packets.mjs";
function write(path, contents) {
mkdirSync(dirname(path), { recursive: true });
writeFileSync(path, contents);
}
test("packets inline the blueprint body and the Scene-cited rule recipes", () => {
const project = mkdtempSync(join(tmpdir(), "gv-packets-"));
write(join(project, "frame.md"), "# tokens\n");
write(
join(project, "STORYBOARD.md"),
`---\nformat: 1920x1080\n---\n\n## Frame 1 — Hook\n\n- duration: 3s\n- src: compositions/01-hook.html\n- blueprint: dataviz-countup\n- scene: hero stat punches in\n\nScene 1 (0.0–1.5s): the stat enters via spring-pop-entrance, then counting-dynamic-scale runs the tally.\n\n## Frame 2 — Freeform\n\n- duration: 4s\n- src: compositions/02-freeform.html\n- blueprint: compose\n\nScene 1 (0.0–4.0s): a quiet hold, no named motion.\n`,
);
const result = buildFramePackets({ projectDir: project });
assert.equal(result.length, 2);
const hook = readFileSync(result[0].path, "utf8");
assert.match(hook, /## Selected blueprint: dataviz-countup/);
assert.match(hook, /## Selected motion rule: spring-pop-entrance/);
assert.match(hook, /## Selected motion rule: counting-dynamic-scale/);
assert.match(hook, /RULES_DIR: /);
const freeform = readFileSync(result[1].path, "utf8");
assert.doesNotMatch(freeform, /## Selected blueprint/);
assert.doesNotMatch(freeform, /## Selected motion rule/);
});
test("design truth resolves frame.md → design.md → DESIGN.md", () => {
const project = mkdtempSync(join(tmpdir(), "gv-design-"));
write(join(project, "design.md"), "# design truth\n");
write(
join(project, "STORYBOARD.md"),
`---\nformat: 1920x1080\n---\n\n## Frame 1 — Hook\n\n- duration: 3s\n- src: compositions/01-hook.html\n`,
);
const result = buildFramePackets({ projectDir: project });
const packet = readFileSync(result[0].path, "utf8");
assert.match(packet, /Design truth: .*design\.md/);
assert.doesNotMatch(packet, /Design truth: .*frame\.md/);
});
test("_role.md is the core contract + this workflow's delta, verbatim", () => {
const project = mkdtempSync(join(tmpdir(), "gv-role-"));
write(join(project, "frame.md"), "# tokens\n");
write(
join(project, "STORYBOARD.md"),
`---\nformat: 1920x1080\n---\n\n## Frame 1 — Hook\n\n- duration: 3s\n- src: compositions/01-hook.html\n`,
);
buildFramePackets({ projectDir: project });
const rolePath = join(project, ".hyperframes", "frame-packets", "_role.md");
assert.ok(existsSync(rolePath));
const role = readFileSync(rolePath, "utf8");
assert.match(role, /# Frame worker — core contract/);
assert.match(role, /# Frame worker — general-video delta/);
});
test("packet validation is atomic and leaves no partial output on overflow", () => {
const project = mkdtempSync(join(tmpdir(), "gv-atomic-"));
const outDir = join(project, ".hyperframes", "frame-packets");
write(join(project, "frame.md"), "# tokens\n");
write(
join(project, "STORYBOARD.md"),
`---\nformat: 1920x1080\n---\n\n## Frame 1 — Big\n\n- duration: 3s\n- src: compositions/01-big.html\n\n${"padding line\n".repeat(300)}`,
);
assert.throws(
() => buildFramePackets({ projectDir: project, outDir, maxPacketBytes: 2_000 }),
/limit 2000/,
);
assert.equal(existsSync(outDir), false);
});
SKILL.md
---
name: hyperframes-general-video
description: "Author or edit a custom HyperFrames composition when no specialized workflow fits, or when BRIEF.md sets flow: companion. Use for longer or multi-scene pieces, brand and sizzle reels, montages, static loops, static title cards, footage remixes, and freeform builds. Use motion-graphics instead for a short unnarrated motion-first unit, including an animated title. Route fresh creation through hyperframes before using this skill."
---
# General video
Before relying on this workflow, run:
```bash
npx hyperframes skills update general-video
```
A successful no-op means the skill is current. Surface an update failure instead of continuing from memory.
## 1. Apply cross-cutting source adapters
- **Media:** For any audio, image, icon, logo, voice, grade, LUT, treatment/effect, caption, or media-operation need, load `/media-use` and follow `../hyperframes-media-use/references/resolve.md` (resolve, adopt, reuse) and `../hyperframes-media-use/references/setup-providers.md` (providers, auth). Vague footage feedback and named styles use `../hyperframes-media-use/references/media-treatments.md` before editing; do not improvise supported media effects with CSS/SVG/opacity. Before the first authenticated provider action, run `npx hyperframes auth status` and relay its output verbatim. If signed out, apply the gate in `../hyperframes-core/references/brief-contract.md`: collaborative waits for sign-in or an explicit offline choice; autonomous states the status and continues through an available offline provider. Surface a blocker when no offline provider can satisfy a required capability. Local adoption alone does not require an auth gate.
- **Figma:** If any input is a `figma.com` URL, run `/figma` first. Build from its exported assets, tokens, components, or storyboard frames. Do not use raw Figma connector calls because they skip SVG sanitization, media provenance, and brand-token binding.
These adapters do not change the workflow selected by `/hyperframes`.
## 2. Start from project state
Apply the first matching row; do not evaluate lower state rows:
| State | Action |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Specific edit | Make the edit, preserve existing project decisions, then rerun affected checks. Do not reopen discovery. |
| `BRIEF.md` exists | Read it. If `workflow` names another workflow and `flow` is not `companion`, hand off. Ask no brief questions. |
| No brief, but `hyperframes.json` or `STORYBOARD.md` exists | Resume from files and recorded preferences. Backfill `BRIEF.md` only from known facts. |
| Fresh creation | Run `/hyperframes` and its intent layer. Return here only for `workflow: general-video` or `flow: companion`. |
For a new project, choose a kebab-case directory name from the brief and scaffold before writing the brief:
```bash
npx hyperframes init "videos/<project>" --non-interactive --example=blank --skill=general-video
```
Then write `BRIEF.md` at the project root using `../hyperframes-core/references/brief-format.md`. In an existing project, the root is the directory containing `hyperframes.json`. Record only the confirmed preference-backed fields named by the brief format, using `node <MEDIA_DIR>/scripts/prefs.mjs record --hyperframes <PROJECT_ROOT>`; never record inferred defaults. Here `<MEDIA_DIR>` is the installed `/media-use` skill directory and `<PROJECT_ROOT>` is the directory containing `hyperframes.json`. If the intent layer adopted a recipe, apply it now with `node <MEDIA_DIR>/scripts/recipe.mjs use --hyperframes <PROJECT_ROOT> --name <name>` and do not ask again.
## 3. Interpret the run shape
Use only the canonical terms from `../hyperframes-core/references/brief-contract.md`:
| Field | Meaning | Effect |
| -------------- | ------------------------------------- | ----------------------------------------------------------------------------------- |
| `flow` | Who drives | `automation`: choose and execute the route. `companion`: co-create in conversation. |
| `storyboard` | Whether the board is a review surface | `yes`: run plan and sketch review. `no`: build without the board. |
| derived `mode` | How checkpoint gates behave | Follow the brief contract. Never ask the user to name a mode. |
Do not invent synonyms for these states. An ongoing “just build it” signal is handled by the intent layer and arrives as `flow: automation`, `storyboard: no`.
- For `flow: automation`, choose the route and state it in one line in the first progress update.
- For a specific edit, make the edit without inventing a new route.
For a hard cut, trim, splice, or reorder of existing footage, duplicate the same
video source into multiple clip elements. On each copy, set the source range
with `data-media-start` plus `data-duration`, then set authored placement/order
with `data-start`. Separately authored audio follows the identical clip ranges
and timing on matching `<audio>` elements. `/hyperframes-core` owns this temporal
edit; use `/hyperframes-keyframes` only for visual-property animation such as
zoom, punch, pan, crop, mask, or `clip-path` on an inner wrapper.
Copy the full contracts from `../hyperframes-core/references/creator-editing-recipes.md`.
### Companion flow
When `flow: companion`:
- Read `BRIEF.md` and reconcile accepted `## Assets` and `## Customizations` with project artifacts. Complete accepted work that is still pending; leave completed work alone; do not offer an accepted capability again as if it were new.
- **Arrive as the director, not the contractor.** A user who chose companion chose involvement and quality; the honest response is the best version you can design, not the smallest one you can defend. The first plan is the ceiling treatment: the story arc (borrow the nearest genre lens — menu § Genre lenses), the design spec, each scene's motion treatment cited by name (§ 5's plan discipline), the transitions, the audio identity — music and sound marks, or deliberate silence — the user's material placed, and a designed open and close. Say what each layer adds in one line; flag the expensive ones (render time, sign-in, billing) as you name them. The user trims a treatment down; they should never have to assemble one approval by approval.
- **The ceiling belongs to the concept, not the toolbox.** Every layer must serve the brief's message — a treatment that would dress any video the same way is decoration. Craft rises to the ceiling; content never grows past what was asked (§ 6).
- Between checkpoints, `../hyperframes/references/capability-menu.md` works two ways. As the trigger list: offer a relevant capability when the user mentions its input or the build reaches its need. As each pass's upgrade channel: a plan, sketch, or build checkpoint may carry one or two traced offers pointed at material the user is looking at ("scene 3's stat wants the count-up treatment"). Read it before offering; never dump the full catalog.
- After the user accepts a capability, produce its artifact and record the decision in the matching `BRIEF.md` body section immediately. Rewrite a frontmatter field and record the confirmed preference only when the user explicitly changes it.
- Keep the same storyboard, validation, final-preview, and render-approval gates. Companion changes who steers, not what quality requires.
## 4. Load required knowledge before each stage
These reads are mandatory when their condition matches:
| Condition | Read before acting |
| ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Any composition HTML or scene layout | `/hyperframes-core`; use `references/determinism-rules.md` for its layout contract |
| Any non-trivial creation or visual treatment | `/hyperframes-creative` → `references/house-style.md` and `references/video-composition.md` |
| Any motion, animation, or scene transition | `/hyperframes-animation`; follow its routing to the matching rules, adapters, blueprints, or transition references |
| `storyboard: yes` | `../hyperframes-core/references/storyboard-format.md` and `../hyperframes-core/references/review-loop.md` |
| Any media asset or operation, including narration, BGM, SFX, captions, grading, or transforms | `/media-use`; for framework playback and placement also read `/hyperframes-core` → `references/variables-and-media.md` |
| Multi-scene assembly | `../hyperframes-core/references/production-loop.md` |
| `flow: companion`, before the first plan | `/hyperframes-creative` → `references/story-spine.md` and `references/house-style.md`; the nearest genre lens and the full `../hyperframes/references/capability-menu.md` — the ceiling treatment is designed from these, not recalled |
| A companion capability offer, capture, beat grid, generative video, map, publishing, or cross-workflow capability | `../hyperframes/references/capability-menu.md` |
| A design spec exists, before final approval | `/hyperframes-creative` → `references/design-adherence.md` |
Do not replace these reads with recollection. Progressive disclosure saves context only when the matching reference is actually loaded.
## 5. Execute the composition
Use this dependency order. Skip a stage only when its input is absent.
1. **Plan.** State the viewer arc, structure, rhythm, and duration driver. Use one file for a short single scene; use sub-compositions for three or more hard scene cuts or any reused scene. Read `/hyperframes-creative` → `references/story-spine.md` for narrated arcs, `references/beat-direction.md` for rhythm, and `/hyperframes-core` → `references/composition-patterns.md` for structure. For an open-ended multi-scene brief, expand the prompt through `/hyperframes-creative` → `references/prompt-expansion.md`. A multi-scene plan cites each scene's shape: a blueprint id from `/hyperframes-animation` → `blueprints-index.md` when one fits, or the named rules it composes from `rules-index.md` when none does — motion names come from those indexes, never invented. Story truth decides which scenes exist; the citation dresses them. A multi-scene plan is also recorded as the dispatch artifact: one `## Frame N` block per scene in `STORYBOARD.md` — `status: outline`, a declared `src:`, the blueprint/rules citation, and the beat text — **even when `storyboard: no`**. The block is the dispatch unit; the board is only the review surface.
2. **Review the plan when requested.** For `storyboard: yes`, run the shared review loop over those blocks. For `storyboard: no`, continue without opening the board. When a plan pause happens anyway, fold the sub-agent delegation grant (needed by codex for step 4's dispatch) into that pause rather than stopping again later.
3. **Resolve dependencies.** Install registry blocks before parallel work. Stage user assets, adopt existing media, and resolve only what the brief requires. Start audio early when its timings drive duration.
4. **Build scenes.** For a short single-scene piece, implement the scene at its most visible moment before adding motion (the confirmed wireframe, when present, is that end state and must not be redrawn), then animate from its cited blueprint or rules — read the full recipe body (`/hyperframes-animation` → `blueprints/<id>.md`, `rules/<id>.md`) before writing motion.
**Dispatch pays for itself only at scale.** Authoring packets and warming fresh worker contexts costs real minutes and tokens: a film of up to ~6 short scenes builds FASTER inline, in this context, one scene after another (measured: 5 short scenes ≈ 9 min inline vs ≈ 21 min packetized). Fan out only when the plan exceeds that — more scenes, or individually heavy ones — and then give each worker **2–3 scenes**, not one, and spawn **all workers in a single wave** (a second wave nearly doubles the window). When dispatching:
`node <SKILL_DIR>/scripts/frame-packets.mjs --project "$PROJECT_DIR" --storyboard "$PROJECT_DIR/STORYBOARD.md"`
The builder writes one bounded packet per scene under `.hyperframes/frame-packets/` (the scene's exact storyboard block + the blueprint body + every cited rule recipe, inlined) and `_role.md` (`../hyperframes-core/references/frame-worker-core.md` + this skill's `sub-agents/frame-worker.md`, concatenated verbatim — the complete worker role). Dispatch the workers — 2–3 scene packets each, all in one wave (`../hyperframes-core/references/subagent-dispatch.md`); each worker's prompt carries `_role.md` and its packets — paste them in full, or hand the file paths for the worker to read first (equivalent either way) — plus a dispatch context with `PROJECT_DIR`, its `frame_id`s, and canvas size. WAIT on every scene's `compositions/<frame_id>.html` + `compositions/<frame_id>.motion.json`. Workers read only their packets and the design truth file; they never open `STORYBOARD.md` or the skill documents. With no delegation channel, fall back serially: process one packet at a time in this context, still working from the packet alone.
5. **Merge motion sidecars.** Collect the workers' `compositions/<frame_id>.motion.json` files and carry their durations and exit/entry vectors into assembly; where the doctrine chain (`/motion-doctrine`) is installed, translate them into the project ledger before stamping seams.
6. **Assemble.** Mount scenes, media, transitions, captions, and audio using the production loop. Real voice duration overrides estimates.
7. **Verify.** Use `npx hyperframes lint` for fast feedback after the first HTML pass and structural changes. For the final gate, run `npx hyperframes check`; it reruns lint internally, so do not run a redundant standalone lint immediately before it. For sub-compositions, inspect midpoint snapshots. For multi-scene work, review the animation map.
8. **Final approval.** Open the final Studio preview only after checks pass. Ask whether to render or revise. Render only after approval.
## 6. Gates that always apply
### Keep scope exact
Build what the user asked for. A title card is not a title card plus three scenes, music, and captions. Offer additions before adding them.
### Establish design before HTML
Resolve the design source in this order: `frame.md` → `design.md` → `DESIGN.md`. Treat the first file found as brand truth.
When no design spec exists, complete all four items before writing composition HTML:
1. Ground the visual identity in `house-style.md` and `video-composition.md`.
2. Write one sentence naming the concept angle for every non-trivial creation.
3. Choose an embeddable font pairing from `/hyperframes-creative` → `references/typography.md`; do not assume an unbundled display font exists in cloud rendering.
4. Define the focal element, edge anchors, supporting detail, and background treatment.
Match density to the requested format and message. Density examples are guidance for produced frames, not permission to invent claims, scenes, or a fixed number of elements.
For a named style or mood, read `/hyperframes-creative` → `references/visual-styles.md`. When the user needs to choose visually and no shipped preset fits, read `/hyperframes-creative` → `references/design-picker.md` and run the interactive design selection there.
### Preserve the composition contract
Timed elements use `class="clip"`; the root and relevant ancestors are sized; each composition registers one paused, seek-safe timeline on `window.__timelines`; rendering is deterministic. Do not use render-time network fetches, clocks, or unseeded randomness.
### Borrow workflows safely
When the piece resembles a shipped workflow, borrow its genre references as examples. First run `npx hyperframes skills update <workflow-name>`. Borrow its story shape and taste, not its private scripts, pipeline state, or directory contract. The generic build remains owned by this skill.
## 7. Done
A run is complete only when:
- requested scope is implemented;
- for `flow: companion`, the treatment is delivered, not just the scope: every scene's cited blueprint or rules realized, the audio identity present (or the silence chosen and said), the open and close designed rather than defaulted;
- `npx hyperframes check` passes, including its built-in lint stage;
- design adherence is reviewed against `/hyperframes-creative` → `references/design-adherence.md` when a design spec exists;
- contrast findings are resolved;
- sub-composition snapshots are inspected when applicable;
- an autonomous handoff includes an inspected contact or snapshot sheet; multi-scene sheets use scene midpoints;
- the handoff names the final preview or rendered artifact as applicable and reports the actual duration for a time-based deliverable;
- `hyperframes-animation/scripts/animation-map.mjs` is reviewed for multi-scene work;
- the user approves the final Studio preview before render;
- the rendered file is verified when a render was requested.
After final approval, offer once to freeze the run as a recipe, following `../hyperframes-core/references/review-loop.md` § 4.
sub-agents/frame-worker.md
# Frame worker — general-video delta
> The shared law is the core contract above (the packet builder prepends `../hyperframes-core/references/frame-worker-core.md` to this file as `_role.md`) — read the two as one role. This file carries only what's specific to a general-video scene; you run N-up, **one scene each** — your dispatch carries exactly one packet. Tempted to add a generic GSAP / timeline rule here? Wrong home — it belongs in the core contract or `hyperframes-core`.
## Your scene is invented, not captured
There is no product capture pipeline: your packet's storyboard block plus the design truth file named in Project inputs are your complete input. Invent elements from those two sources only — use exactly the media paths the block itself names, and never resolve or fetch new media (the orchestrator staged everything your block cites before dispatch).
## Design truth
Project inputs names the design file (resolution order `frame.md` → `design.md` → `DESIGN.md`). It is brand truth for tokens, type, palette, and treatment; the storyboard block owns content. When the block and the design file disagree on content, the block wins; on style, the design file wins.
## Output contract — composition + motion sidecar
Write exactly two files, then stop:
1. `compositions/<frame_id>.html` — the sub-composition, a bare fragment per the core contract.
2. `compositions/<frame_id>.motion.json` — one JSON object the orchestrator merges into the project's motion ledger:
```json
{
"scene": "<frame_id>",
"duration_s": 0.0,
"rules": ["<rule ids you actually used>"],
"exit": { "vector": "<direction + px/s at your last frame>", "still_moving": true },
"entry": { "vector": "<direction + px/s at your first frame>", "from_rest": false }
}
```
Report what you actually authored — measured values from your timeline, not the plan's hopes; where the doctrine chain is installed, a numeric seam gate verifies exits and entries downstream and a wrong sidecar fails loudly there instead of silently here.
## Boundaries
Audio is orchestrator-owned: never author `<audio>` in a scene. Seams between scenes are stamped by the orchestrator from the ledger — author your entry/exit motion inside your own timeline, and never reach into a neighbor scene's file.