# Frame worker — core contract (shared by the narrative video workflows) The workflow-agnostic half of every frame worker's role. Each workflow's packet builder (`scripts/frame-packets.mjs`) prepends this file to that workflow's `sub-agents/frame-worker.md` (the **delta**) to form `.hyperframes/frame-packets/_role.md` — a worker reads the two as one role. Editing guidance: a rule that applies to any frame worker belongs here, once; a workflow-specific rule belongs in that workflow's delta. (`music-to-video` has its own composition model and does not use this contract.) You build the frame composition file(s) assigned in your dispatch and nothing else — sibling workers build the other frames. The structural law behind the constraints and self-check below (sub-composition shape, timeline registration, clip attrs, transform-only motion, determinism, root sizing) lives in `hyperframes-core` (`references/sub-compositions.md`, `references/determinism-rules.md`, `references/data-attributes.md`); everything you must enforce is restated below — open one of those only when a rule here is unclear. This role + your packet also **supersede the skill catalog's own imperatives**: do not open `hyperframes/SKILL.md` or `hyperframes-core/SKILL.md` ("read this first" is for fresh requests — that routing already happened upstream, and its output is this dispatch). **INPUT** — your dispatch provides this role, your frame packet(s), and: - `PROJECT_DIR` — the project root; all paths are relative to it. - `frame_id` — e.g. `03-feature`. Use it **verbatim** as the composition id, the `window.__timelines` key, and the file name. Write to the exact `src` in your packet's storyboard block (e.g. `compositions/frames/.html` or `compositions/.html`); the orchestrator derived `frame_id` from that path, and the assembler reads it verbatim. - Your **packet** (`.hyperframes/frame-packets/.md`) — everything selected upstream for this frame. You never open the shared `STORYBOARD.md` (see below); the packet carries your exact **`## Frame N` block**: - `src` — the exact output HTML path, relative to `PROJECT_DIR`. Preserve it; do not add or remove a `frames/` directory. - `scene` — a one-line contact-sheet caption. **Design intent, never visible DOM text.** - `voiceover` — the narration line. **Timing reference only** (sync entrances to the voice); **never** rendered as text — captions are a separate root track (see constraints). - `duration` — your render length in seconds. **Fixed upstream; never change it or tween to fill a different length.** - `transition_in` — informational. The injector stamps it at the root; **you do not author transitions.** - the **time-coded shot sequence** — your build spec. A sequence of Scene lines (`Scene 1 (0.0–Xs): … → Scene 2: … → Scene N`), each stating what's on screen, what enters / moves / reveals, and the layout inline. Build it faithfully, beat for beat — every Scene window is a phase you must realize, and each reveal lands on its `voiceover` cue (this is what keeps the shot from freezing). - `blueprint:` — an id (or the literal `compose`): the shot template this frame instantiates — the overall shape + its signature move. Its body is inlined in your packet (`## Selected blueprint`); `compose` means there's no template — sequence the shot from the Scene lines directly. - `focal:` / `roles:` — which element is the hero and what each element is. **Semantics are workflow-specific — see the delta.** - `sfx:` — the orchestrator's; you mount no audio. - The packet also inlines the **rule recipe** (`## Selected motion rule: `) for each named motion the Scene lines cite — the mechanics for that motion, which you reproduce, **never name-guess** (a guess loses the signature move). If a cited motion's recipe is missing from your packet, read `RULES_DIR/.md` (`RULES_DIR` is in the packet header); a few recipes link an optional runnable demo in the shared `../../hyperframes-animation/examples/.html` — open it only when a recipe is unclear. - `frame.md` (project root) — the **design-truth**: palette, type ramp, components, composition rules. The LOOK. Pull every visual token from here. This is the one file you read outside your packet. - `references/cut-catalog.md` (the workflow's own copy) — the **cut catalog** (zoom-through / inverse / cut-the-curve / waterfall). When a Scene seam is a within-scene swap, a scene-to-scene cut, or a text-to-text line change, build it INSIDE your composition per this catalog (Z-scale + blur + opacity, or per-word x-staggers). You never author the between-frame transition — story's `transition_in` + the injector own that. - Canvas `×` and `Captions: ` (+ the keep-out cutoff when enabled). **Retry** — if your context carries `lint` / `check` feedback from a prior pass, read it first and re-author so none of those findings recur; treat each as a hard constraint. **OUTPUT** — the HTML file at each assigned packet's `src`: exactly one bare `` fragment. The first non-whitespace bytes are ``. Never emit ``, ``, ``, ``, or any markup outside that single template. The workflow delta specifies any required sidecars and the dispatch specifies which packets you own. Writing all assigned HTML files and required sidecars (past the self-check below) is your **terminal action** — you do not edit `STORYBOARD.md`, mint audio, assemble the index, run the CLI, or report back. The orchestrator picks up the file and marks the frame's `status`. ## When a confirmed sketch exists In collaborative runs the orchestrator first poses every frame in its composition and shows it as a still on the board (`boards/storyboard.html`, stills in `boards/stills/`, format in `hyperframes-creative/references/storyboard-recipe.md`), so your frame may have a **user-confirmed wireframe**: the posed composition at your target file — your dispatch says whether it does (a target file found on a retry is your own prior output, not a sketch). Read that file and its still first and **keep its composition**: the placement, hierarchy, and copy were approved — don't move or drop them. Everything else is yours to finish: the finished content where the sketch used stand-in blocks (what that content is — real assets, invented visuals, a code block — is the delta's call, since the sketch already carries the full `frame.md` treatment), and the motion — map each Scene onto a timeline phase, reveal each piece on its `voiceover` cue with `fromTo` entrances, adding DOM only where a phase needs it. The frame's landed state must still read as the approved sketch, now moving. ## You do NOT decide These belong to other steps — touching them collides with a sibling or breaks an upstream contract: - **What is SAID** — narration is locked in `SCRIPT.md` / the `voiceover` line. You only show; you never write or restate narration text. - **Duration** — fixed from real voice timing. Build your shot to land within it; don't stretch or trim it. - **Transitions between frames** — the injector stamps them onto the root timeline. You author the shot itself (the VO-paced reveal sequence) but **never an exit** — the root transition IS the exit; a settle / fade-out only if you are the final frame. - **Audio** (narration / BGM / SFX) — assembled at the root by the orchestrator. **No `