* feat(skills): add brief contract — interaction modes + shared intake fields across workflows New hyperframes-core/references/brief-contract.md, the shared intake contract every creation workflow now runs its brief against: - §1 interaction mode: collaborative (default) vs autonomous, ongoing vs one-time signals, mode set once and carried forward, and a gate taxonomy (preference / checkpoint / quality / routing) — autonomous skips waiting, never verification - §2 field registry: destination→aspect derivation (feed → 1:1, Shorts/TikTok → 9:16, else 16:9), message, angle, length, audience, language, narration — each workflow binds fields as ask or state - §3 question rules: one round with one question per asked field (native question UI mandatory when available, recommended option first with a receipt), never drop a question as inferable, and a mode legend advertised in the intro text instead of asked Wired into the surfaces: - hyperframes router: detect mode at entry, derive aspect from destination instead of stating 16:9 - product-launch-video / pr-to-video / faceless-explainer: ask/state binding tables at Step 0; Step 3/6 checkpoint-gate branches (autonomous posts a heads-up with a preview hint before render) - website-to-video: local mode definition now defers to the contract - music-to-video, general-video, embedded-captions, talking-head-recut, slideshow, motion-graphics: mode semantics wired per gate type - storyboard-format: new optional 'mode' frontmatter key - pr-to-video: length tier is a ceiling, not a floor — a one-headline PR recommends inside the 30–90s sweet spot regardless of diff size * feat(skills): story spine + mode-first brief across creation workflows Story — the reverse-iceberg feedback: - New hyperframes-creative/references/story-spine.md, three rules for the narrated workflows: the hook speaks the viewer's outcome language, the value claim lands by beat 2 (implementation is the footnote of the story, not the spine), and the storyboard is presented as a proposal — 'This video tells [audience] that [message]' plus a per-frame why: drawn from narrativeRole - pr-to-video: feature-reveal reordered promise-first (impact leads, diff/mechanism follow as evidence); hooks ban file/function names; fix-explainer, refactor-walkthrough, changelog unchanged - product-launch-video / faceless-explainer hook rules aligned to the spine; website-to-video's beat summary gains the echo line + why:; general-video points at the spine from its plan step Brief — hardened after live-test drift: - Mode is now the first question (Collaborative recommended vs Autonomous), its own round, skipped when the request carries a signal; autonomous asks nothing further until one final preview-or-render question before render - Step 0 rewritten as a literal two-round question script in each shot-sequence workflow (website-to-video's editorial register, channel-agnostic); brief-contract.md §3 reduced to invariants so the procedure lives in exactly one place * feat(skills): split type minimums by viewing context typography.md: full-screen viewing keeps body 20px / headline 60px; in-feed destinations (X / LinkedIn / Instagram — brief-contract's destination field) scale to body >=32px, headline >=90px, data labels >=24px. First-pass values, to be calibrated against real renders. * feat(skills): storyboard proposal as a table + credits close by default - story-spine § 3: the proposal presents frames as a markdown table (frame · beat · on screen · why) instead of dense paragraphs; the three shot-sequence workflows and website-to-video's beat summary reference the same shape - pr-to-video: the credits close is now the default ending — every PR video ends on a contributors frame (committers by commit count, 1-6 avatars), with no taste judgment; the only skip is when no avatar was fetched, and the user can cut the frame in the proposal * fix(skills): address review nits on the brief/story contracts - embedded-captions: the identity procedure now states both sides of the preference gate inline (user picks; autonomous picks with a stated why) - website-to-video step-2-brief: note that its mode section is the workflow's application of brief-contract.md, not a second definition - brief-contract: resuming a project reads mode from STORYBOARD.md frontmatter — a recorded mode counts as set, closing the write-only gap * docs(skills): add a non-code receipts example to the brief contract Review nit (jrusso1020, #2058): the receipts example in § 3 was PR-video-shaped only. A destination-shaped example joins it so the rule reads as workflow-neutral.
5.2 KiB
Storyboard format — STORYBOARD.md + parsed manifest
Defines the storyboard's base data format only: the STORYBOARD.md file shape and the StoryboardManifest it parses into. How a workflow generates a storyboard lives in that workflow; the optional narration/TTS file (SCRIPT.md) is a separate concern owned by the TTS step, not here.
A storyboard is the plan layer for a video — an ordered set of frames (key moments) in one markdown file. HyperFrames Studio renders it as a contact sheet (the Storyboard view, available by default in every Studio session). Parser: @hyperframes/core/storyboard → StoryboardManifest; read API: GET /api/projects/<id>/storyboard.
Frontmatter (global direction)
YAML block at the top. Unknown keys are kept under globals.extra.
| Key | Meaning | Example |
|---|---|---|
format |
Canvas size | 1920x1080 |
message |
One-line thesis | Ship a launch video in an afternoon |
arc |
Narrative arc | Hook → Problem → Solution → Proof → CTA |
audience |
Who it's for | indie devs on X |
mode |
Interaction mode (see brief-contract.md; default collaborative) |
autonomous |
Per-frame sections
One ## Frame N — Title heading per frame (Frame / Beat / Scene accepted at H2/H3). Metadata as - key: value bullets; everything below them until the next heading is the free-form narrative.
| Key | Meaning |
|---|---|
status |
outline → built → animated (defaults outline) |
src |
project-relative path to the frame's HTML sub-composition (the tile poster renders from it) |
duration |
e.g. 4s |
transition_in |
crossfade / cut / wipe … (alias transition) |
scene |
one-line contact-sheet caption (aliases description / summary / caption) |
voiceover |
the frame's narration guide (aliases vo / voice_over / narration) |
poster |
seconds to seek for the tile poster (past the intro animation) |
| any other key | kept verbatim under the frame's extra — a workflow carries its own per-frame data (effects, assets, …) here |
Parsed manifest
The parser is lenient: it never throws and records anything surprising as a warning.
StoryboardManifest {
globals: { format?, message?, arc?, audience?, extra: {…} }
frames: Array<{
index, number?, title?,
status, // "outline" | "built" | "animated"
src?, duration? / durationSeconds?, transitionIn?,
scene?, voiceover?, poster?,
narrative, // markdown below the metadata
extra: {…} // unknown keys, preserved
}>
warnings: Array<{ message, line?, frameIndex? }>
}
The read API also adds srcExists per frame and attaches the optional SCRIPT.md payload when present.
SCRIPT.md (out of scope here)
Optional, free-form, not parsed into the manifest — the locked-narration file that drives TTS. Its format is defined in references/script-format.md, and it is absent for videos with no narration/TTS. The per-frame voiceover above is the storyboard's own narration guide.
Example
---
format: 1920x1080
message: "Ship a launch video in an afternoon"
arc: Hook → Problem → Solution → Proof → CTA
audience: indie devs on X
---
## Frame 1 — Hook
- scene: Big type punches in on the beat
- duration: 3s
- poster: 2s
- transition_in: cut
- status: animated
- voiceover: "Ship a launch video in an afternoon."
- src: compositions/frames/01-hook.html
Open cold on the promise. This is the thesis — everything after pays it off.
## Frame 2 — The problem
- scene: A 20-minute timer spins on a stack of rejected takes
- duration: 4s
- transition_in: crossfade
- status: built
- voiceover: "The old way? Prompt, wait twenty minutes, get something that misses."
- src: compositions/frames/02-problem.html
The old way: prompt, wait, get something that misses. Establish the pain we remove.
Notes
- A frame with
status: outlineand no builtsrcrenders as an outline placeholder. - Multi-line
voiceovervalues collapse to one line on save.