mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(skills): search the component catalog before hand-building a look (#3829)
* fix(motion-graphics): make the catalog search fire before hand-authoring
The workflow's only reuse instruction pointed at catalog-map.md, a
hand-maintained snapshot of ~60 registry items, and no file in the skill
ever named `hyperframes catalog --query`. An agent asked mid-build for
CRT scanlines and a glitch effect had no instruction to search, so it
hand-authored both while caption-glitch-rgb ("RGB chromatic aberration
with CRT scanline overlay") ranks first for that query on either tier.
The search reads the hosted registry and needs nothing installed, from
any directory with no project, so "the components were not installed"
was never the cause. Say that where the reader is, since the wrong
diagnosis is the intuitive one.
Director Part 2 and the Builder now run the search before naming a
block, and catalog-map.md is labelled a partial snapshot whose misses
prove nothing. Pinned by a content test in coreSkillContent.test.ts.
* fix(skills): search the component catalog before hand-building a look
Authoring workflows never told the agent to search the component library,
so agents rebuilt effects the registry already shipped. A user reported
building an effect from scratch that the registry already contained; the
search that would have found it needs nothing installed, which is why the
usual self-diagnosis ("I forgot to install the components") is wrong.
All ten workflow skills carried zero mentions of `hyperframes catalog`.
The instruction lived only in hyperframes-cli and hyperframes-registry,
both loaded on demand, and the registry skill's own trigger named the
command rather than the symptom - circular, because an agent that never
thought to search could not reach the doc telling it to search.
- Eight workflows now run the search at the point they decide what to
build, before authoring. The two that compile through a closed
authoring vocabulary (embedded-captions, talking-head-recut) document
why they deliberately do not.
- hyperframes-registry triggers on the symptom (a named look, effect,
treatment or transition) instead of the command name; the router table
and the catalog surfaces carry the same framing.
- Fixes hand-maintained lists that had drifted: bar-chart-race was listed
as a hand-author gap in two files while shipping in the registry;
stat-motion was named as an installable block and is not one; the
caption-* family count was one high; the registry discovery tables
claimed to be the block list while covering 97 of 180.
- bun run lint:skills now fails when a doc marked as a registry snapshot
names an item the registry does not have.
* refactor(scripts): reuse native recursive readdir and the shared registry type
Simplify pass on the new registry-snapshot check, behaviour identical:
- collectMarkdownFiles uses readdirSync({ recursive: true }) instead of
hand-rolled recursion, matching scripts/generate-template-previews.ts.
- registryItemNames types registry.json with the exported RegistryManifest
instead of an ad hoc inline shape, matching scripts/catalog/build-local-vectors.ts.
The runtime guard stays: a cast describes the file, it does not validate it.
- One report() helper replaces the duplicated print-and-count block in both
lint passes.
* refactor(scripts): name the registry check's blind spots and stop self-arming
Applies the review findings on the new check, behaviour identical except
where noted:
- lintRegistryItemRefs returns null for an unmarked file instead of an
empty array, so "not a snapshot" and "a clean snapshot" have one owner
and the marker is matched once rather than twice.
- Marker detection ignores fenced blocks, so a doc that documents the
marker syntax in an example no longer arms the check on itself. The id
scan still reads full content, so fenced examples stay covered.
- The header comment and two tests now pin both known false negatives:
identifiers outside backticks, and single-word item names. Measured on
the six marked files, dropping the hyphen requirement would monitor 3
more items and force 46 allow= entries for ordinary prose words, so the
requirement stays and the gap is stated instead of silent.
* chore(skills): regenerate skills manifest after catalog-search edits
This commit is contained in:
@@ -41,7 +41,7 @@ Atomic capabilities the creation workflows compose against — pull one when you
|
||||
- `/media-use` — the media OS: resolve any media need (BGM, SFX, image, icon, logo, voice, color grade, LUT) into a frozen local file or paste-ready block + ledger record; generate via TTS / music / image models when the catalog misses; transcribe, caption, remove backgrounds, and reuse assets across projects. One shared `scripts/audio.mjs` engine + manifest tracking; keeps search noise on disk.
|
||||
- `/hyperframes-audio` — mix the audio already placed in a composition: voiceover carve (dip a music bed only in the bands the voice occupies, static or dynamic, level match included), the effect chain (EQ, compressor, limiter, gate, saturation, delay, reverb, chorus, phaser, bitcrush), automation envelopes on volume or any effect parameter, and submix buses (`<hf-audio-group>`) that carry one chain, fader and automation clock for several tracks at once. Sourcing the audio is `/media-use`; this is what happens to it afterwards.
|
||||
- `/hyperframes-cli` — CLI dev loop: `init`, `add`, `lint`, `check`, `snapshot`, `preview`, `render`, `publish`, `doctor`, `lambda` (AWS Lambda cloud rendering).
|
||||
- `/hyperframes-registry` — install and wire registry blocks and components into compositions via `hyperframes add`. Covers authoring a new block or component to contribute upstream.
|
||||
- `/hyperframes-registry` — search, install and wire registry blocks and components into compositions via `hyperframes catalog` / `hyperframes add`. Load it before hand-building any named look, effect, treatment or transition: the search ranks the whole hosted registry with nothing installed. Covers authoring a new block or component to contribute upstream.
|
||||
- `/figma` — import Figma assets, tokens, components, and storyboard sections → reconstructed motion (frames read as states, not slides) (REST/CLI) plus Motion animations (MCP) and shaders (MCP source / native export) into a composition.
|
||||
|
||||
## Skill catalog maintenance
|
||||
|
||||
@@ -103,7 +103,7 @@ Atomic capabilities the creation workflows compose against — pull one when you
|
||||
| `/media-use` | The media OS — resolve any media need (BGM, SFX, image, icon, logo, voice, color grade, LUT) into a frozen local file or paste-ready block + ledger record, generate via TTS/music/image models when the catalog misses, transcribe, caption, remove backgrounds, and reuse assets across projects. One shared audio engine + manifest tracking. |
|
||||
| `/hyperframes-cli` | CLI dev loop — `init`, `lint`, `check`, `snapshot`, `preview`, `render`, `publish`, `doctor`, plus HeyGen-hosted cloud rendering (`cloud render`) and AWS Lambda rendering (`lambda deploy / render / progress`). |
|
||||
| `/hyperframes-audio` | Mix the audio already placed in a composition — voiceover carve (dip a music bed only in the bands the voice occupies, static or dynamic, level match included), the effect chain (EQ, compressor, limiter, gate, saturation, delay, reverb, chorus, phaser, bitcrush), automation envelopes on volume or any effect parameter, and submix buses (`<hf-audio-group>`) carrying one chain, fader and automation clock for several tracks at once. Sourcing the audio is `/media-use`. |
|
||||
| `/hyperframes-registry` | Install and wire registry blocks and components into compositions via `hyperframes add`. Authoring a new block or component to contribute upstream. |
|
||||
| `/hyperframes-registry` | Search, install and wire registry blocks and components into compositions via `hyperframes catalog` / `hyperframes add`. Load before hand-building any named look, effect, treatment or transition. Authoring a new block or component to contribute upstream. |
|
||||
| `/figma` | Import Figma assets, tokens, components, and storyboard sections → reconstructed motion (frames read as states, not slides) (REST/CLI) plus Motion animations (MCP) and shaders (MCP source / native export) into a composition. |
|
||||
|
||||
For visual design handoff workflows, see the [Claude Design guide](https://hyperframes.heygen.com/guides/claude-design) and [Open Design guide](https://hyperframes.heygen.com/guides/open-design).
|
||||
|
||||
@@ -52,7 +52,7 @@ The installer shows a picker. Select the **core skills** below — every project
|
||||
| `/hyperframes-creative` | Creative direction — design spec, palettes, typography, narration, beats |
|
||||
| `/hyperframes-cli` | Dev-loop CLI — `init`, `lint`, `check`, `preview`, `render`, `doctor` |
|
||||
| `/media-use` | Media OS — TTS voiceover (`tts`), `transcribe`, `remove-background`, plus BGM / SFX / image resolution |
|
||||
| `/hyperframes-registry` | Block and component installation via `hyperframes add` |
|
||||
| `/hyperframes-registry` | Search the catalog before hand-building a look; install via `hyperframes add` |
|
||||
| `/hyperframes-keyframes`| Seek-safe keyframe authoring across runtimes, plus `hyperframes keyframes` diagnostics |
|
||||
| `/general-video` | The general authoring workflow — multi-scene pieces, reels, montages, remixes, and the home of **companion mode**; the fallback when no workflow below fits |
|
||||
|
||||
|
||||
@@ -132,6 +132,73 @@ describe("media treatment routing documentation", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("makes the motion-graphics build path run a live catalog search, not read a snapshot", () => {
|
||||
// The failure this pins: a user inside /motion-graphics asked for "CRT scanlines
|
||||
// and glitch effects" and the agent hand-authored both, while `caption-glitch-rgb`
|
||||
// ("RGB chromatic aberration with CRT scanline overlay") ranks first for that exact
|
||||
// query on either tier. Every reuse instruction in the workflow pointed at
|
||||
// catalog-map.md, a hand-maintained snapshot, and none named the search. The search
|
||||
// needs nothing installed, so "I forgot to install the components" was never the cause.
|
||||
for (const file of [
|
||||
["skills", "motion-graphics", "catalog-map.md"],
|
||||
["skills", "motion-graphics", "agents", "director.md"],
|
||||
["skills", "motion-graphics", "agents", "builder.md"],
|
||||
]) {
|
||||
expect(read(...file)).toContain("npx hyperframes catalog --query");
|
||||
}
|
||||
// And it must say the search stands alone, or the next reader re-derives the
|
||||
// creator's wrong diagnosis: that a catalog you have not installed cannot be searched.
|
||||
expect(read("skills", "motion-graphics", "catalog-map.md")).toContain(
|
||||
"needs nothing installed",
|
||||
);
|
||||
});
|
||||
|
||||
it("routes every authoring workflow through the live catalog search, or documents why not", () => {
|
||||
// The same failure one layer up. The search instruction lived only in
|
||||
// hyperframes-cli and hyperframes-registry, both loaded on demand, and the
|
||||
// registry skill's own trigger named the command ("use when running
|
||||
// hyperframes catalog") — circular, because the agent that never thought to
|
||||
// search could not reach the doc telling it to search. All ten workflow
|
||||
// skills carried zero mentions of the command.
|
||||
for (const file of [
|
||||
["skills", "motion-graphics", "agents", "director.md"],
|
||||
["skills", "product-launch-video", "SKILL.md"],
|
||||
["skills", "faceless-explainer", "SKILL.md"],
|
||||
["skills", "pr-to-video", "SKILL.md"],
|
||||
["skills", "music-to-video", "SKILL.md"],
|
||||
["skills", "general-video", "SKILL.md"],
|
||||
["skills", "slideshow", "SKILL.md"],
|
||||
["skills", "remotion-to-hyperframes", "SKILL.md"],
|
||||
]) {
|
||||
const doc = read(...file);
|
||||
expect(doc, file.join("/")).toContain("npx hyperframes catalog --query");
|
||||
// "I forgot to install the components" was the wrong self-diagnosis that
|
||||
// hid this bug. Every copy of the instruction has to kill it on the spot.
|
||||
expect(doc, file.join("/")).toContain("nothing installed");
|
||||
}
|
||||
|
||||
// The two workflows that deliberately do NOT search. Both compile their
|
||||
// output through a closed authoring vocabulary (embedded-captions' locked
|
||||
// caption engines, talking-head-recut's `data-anim` card kinds), and a
|
||||
// registry item is a standalone composition with no place to mount. The
|
||||
// exemption is written into each skill so the next reader does not close
|
||||
// the gap with an instruction that would be false there.
|
||||
for (const file of [
|
||||
["skills", "embedded-captions", "SKILL.md"],
|
||||
["skills", "talking-head-recut", "SKILL.md"],
|
||||
]) {
|
||||
expect(read(...file), file.join("/")).toContain(
|
||||
"does not search the HyperFrames component registry",
|
||||
);
|
||||
}
|
||||
|
||||
// The symptom-triggered description is the other half of the fix: the skill
|
||||
// has to be reachable from the user naming an effect, not from the command.
|
||||
const registrySkill = read("skills", "hyperframes-registry", "SKILL.md");
|
||||
expect(registrySkill).toContain("Use BEFORE hand-building any named visual");
|
||||
expect(registrySkill).toContain("CRT scanlines");
|
||||
});
|
||||
|
||||
it("gives agents a process-owned preview lifecycle in new project instructions", () => {
|
||||
for (const file of ["AGENTS.md", "CLAUDE.md"]) {
|
||||
const template = read("packages", "cli", "src", "templates", "_shared", file);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { lintFrontmatter } from "./lint-skills.ts";
|
||||
import { lintFrontmatter, lintRegistryItemRefs } from "./lint-skills.ts";
|
||||
|
||||
const wrap = (frontmatter) => `---\n${frontmatter}\n---\n\n# body\n`;
|
||||
|
||||
@@ -125,3 +125,58 @@ test("invalid: top-level scalar (frontmatter is not a mapping)", () => {
|
||||
// be non-empty.
|
||||
assert.ok(violations.length > 0);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registry-snapshot drift guard
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const KNOWN = new Set(["caption-glitch-rgb", "code-diff", "data-chart"]);
|
||||
const MARKER = "<!-- registry-items: -->";
|
||||
|
||||
test("registry refs: unmarked file is never checked", () => {
|
||||
// Opt-in is the whole design. Most kebab-case backticks in skill docs are CSS
|
||||
// properties, data-* attributes or skill directory names, and a check that
|
||||
// flags those gets switched off. null (not []) distinguishes "not a snapshot"
|
||||
// from "a snapshot with nothing wrong", which is what the counter reports.
|
||||
assert.equal(lintRegistryItemRefs("Use `not-a-real-item` here.\n", KNOWN), null);
|
||||
});
|
||||
|
||||
test("registry refs: a marker inside a fenced block does not arm the check", () => {
|
||||
// Otherwise a doc that documents this marker's own syntax arms the check on
|
||||
// itself, and every identifier in it starts failing for no stated reason.
|
||||
const doc = ["# Doc", "", "```md", MARKER, "```", "", "Use `not-a-real-item`."].join("\n");
|
||||
assert.equal(lintRegistryItemRefs(doc, KNOWN), null);
|
||||
});
|
||||
|
||||
test("registry refs: marked file passes when every id is real", () => {
|
||||
const doc = `${MARKER}\n\nUse \`caption-glitch-rgb\` or \`code-diff\`.\n`;
|
||||
assert.deepEqual(lintRegistryItemRefs(doc, KNOWN), []);
|
||||
});
|
||||
|
||||
test("registry refs: marked file flags an id the registry does not have", () => {
|
||||
const doc = `${MARKER}\n\nInstall \`text-wave-distort\` for the wobble.\n`;
|
||||
const violations = lintRegistryItemRefs(doc, KNOWN);
|
||||
assert.equal(violations.length, 1);
|
||||
assert.equal(violations[0].line, 3);
|
||||
assert.ok(violations[0].message.includes("text-wave-distort"));
|
||||
});
|
||||
|
||||
test("registry refs: allow= exempts a legitimately non-item identifier", () => {
|
||||
const doc = `<!-- registry-items: allow=dark-plus,pin-rollout -->\n\n\`dark-plus\` and \`pin-rollout\`.\n`;
|
||||
assert.deepEqual(lintRegistryItemRefs(doc, KNOWN), []);
|
||||
});
|
||||
|
||||
test("registry refs: non-id backticks are ignored", () => {
|
||||
const doc = `${MARKER}\n\n\`--json\`, \`Foo-Bar\`, \`a b-c\`, \`UPPER-CASE\`.\n`;
|
||||
assert.deepEqual(lintRegistryItemRefs(doc, KNOWN), []);
|
||||
});
|
||||
|
||||
test("registry refs: single-word ids are a KNOWN blind spot, not an accident", () => {
|
||||
// The pattern requires a hyphen, so real single-word registry items (glitch,
|
||||
// flowchart, typewriter, confetti, separator, vignette, vignelli) are never
|
||||
// checked. Pinned here so the tradeoff is visible in code, not just in a
|
||||
// comment: dropping the hyphen would cost 46 allow= entries of prose nouns
|
||||
// across the marked files to monitor 3 more items. See lint-skills.ts header.
|
||||
const doc = `${MARKER}\n\n\`glitch\` was renamed and this doc was not updated.\n`;
|
||||
assert.deepEqual(lintRegistryItemRefs(doc, KNOWN), []);
|
||||
});
|
||||
|
||||
+95
-4
@@ -12,6 +12,7 @@
|
||||
import { readFileSync, readdirSync, statSync } from "node:fs";
|
||||
import { join, relative } from "node:path";
|
||||
import { parse as parseYaml, YAMLParseError } from "yaml";
|
||||
import type { RegistryManifest } from "../packages/core/src/index.js";
|
||||
|
||||
const REPO_ROOT = join(import.meta.dirname, "..");
|
||||
// Every location that ships SKILL.md files gets linted. `skills/` is the
|
||||
@@ -256,6 +257,79 @@ function lintInlinePatterns(file: string, stripped: string): Violation[] {
|
||||
.flatMap((line, i) => (line ? matchDangerousPatterns(file, line, i + 1) : []));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registry-item references in hand-maintained snapshots
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// A skill doc that snapshots part of the component registry rots in silence:
|
||||
// nothing fails when an item is renamed or dropped, and the agent that follows
|
||||
// the doc runs `hyperframes add <gone>` and dies. A doc opts into this check
|
||||
// with a marker line, after which every registry-item-shaped identifier in a
|
||||
// backtick span must name a real item in registry/registry.json:
|
||||
//
|
||||
// <!-- registry-items: allow=some-suffix,another-suffix -->
|
||||
//
|
||||
// Opt-in rather than repo-wide on purpose. Kebab-case backticks are also CSS
|
||||
// properties, `data-*` attributes, skill directory names, script names, and
|
||||
// motion-graphics category names, and a check that flags those is a check
|
||||
// people turn off. `allow=` carries the few non-item identifiers a snapshot
|
||||
// legitimately names (bare suffixes under a spelled-out prefix, ids the doc
|
||||
// itself marks as hand-authored).
|
||||
//
|
||||
// TWO KNOWN BLIND SPOTS, both deliberate, both false NEGATIVES (this check
|
||||
// never invents a violation, it only misses some):
|
||||
//
|
||||
// 1. Identifiers outside a backtick span are not seen. A bare `bar-chart-race`
|
||||
// in prose slipped past this check while it was a live defect elsewhere.
|
||||
// 2. Single-word item names are not seen, because the pattern below requires a
|
||||
// hyphen. Measured on the six currently-marked files: dropping the hyphen
|
||||
// requirement would monitor 3 more real items (`glitch`, `flowchart`,
|
||||
// `typewriter`) and force 46 new allow= entries for ordinary prose words
|
||||
// ("add", "line", "name", "height", "text"). A 15:1 noise ratio is how a
|
||||
// check gets switched off, so the hyphen requirement stays.
|
||||
const REGISTRY_MARKER = /<!--\s*registry-items:\s*(?:allow=([^\s]*))?\s*-->/;
|
||||
const REGISTRY_ITEM_ID = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)+$/;
|
||||
|
||||
function registryItemNames(): Set<string> {
|
||||
const raw = readFileSync(join(REPO_ROOT, "registry", "registry.json"), "utf-8");
|
||||
// The cast describes the file; it does not validate it. The runtime filter and
|
||||
// the throw below are what actually stop us linting against an empty set.
|
||||
const parsed = JSON.parse(raw) as RegistryManifest;
|
||||
const names = (parsed.items ?? []).map((item) => item.name).filter((name) => Boolean(name));
|
||||
if (names.length === 0) {
|
||||
throw new Error("registry/registry.json parsed to zero item names — refusing to lint blind.");
|
||||
}
|
||||
return new Set(names);
|
||||
}
|
||||
|
||||
/** `null` when the file is not marked as a registry snapshot; otherwise its violations. */
|
||||
export function lintRegistryItemRefs(content: string, known: Set<string>): LineViolation[] | null {
|
||||
// Marker detection ignores fenced blocks so a doc that *documents* the marker
|
||||
// syntax in an example does not arm the check on itself. The scan below still
|
||||
// reads full content, so ids inside fenced examples stay covered.
|
||||
const marker = stripFencedBlocks(content).match(REGISTRY_MARKER);
|
||||
if (!marker) return null;
|
||||
const allowed = new Set((marker[1] ?? "").split(",").filter(Boolean));
|
||||
return content.split("\n").flatMap((line, index) => {
|
||||
const dead = [...new Set([...line.matchAll(/`([^`\n]+)`/g)].map((m) => (m[1] ?? "").trim()))]
|
||||
.filter((token) => REGISTRY_ITEM_ID.test(token))
|
||||
.filter((token) => !known.has(token) && !allowed.has(token));
|
||||
return dead.map((token) =>
|
||||
violation(
|
||||
index + 1,
|
||||
`"${token}" is not an item in registry/registry.json, but this file is marked as a registry snapshot. Correct the name, remove it, or add it to the marker's allow= list if it is legitimately not an item.`,
|
||||
line.trim(),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function collectMarkdownFiles(dir: string): string[] {
|
||||
return readdirSync(dir, { withFileTypes: true, recursive: true })
|
||||
.filter((entry) => entry.isFile() && entry.name.endsWith(".md"))
|
||||
.map((entry) => join(entry.parentPath, entry.name));
|
||||
}
|
||||
|
||||
function lintFile(filePath: string): Violation[] {
|
||||
const raw = readFileSync(filePath, "utf-8");
|
||||
const file = relative(process.cwd(), filePath);
|
||||
@@ -281,18 +355,35 @@ if (files.length === 0) {
|
||||
|
||||
let totalViolations = 0;
|
||||
|
||||
for (const file of files) {
|
||||
const violations = lintFile(file);
|
||||
function report(file: string, violations: LineViolation[]): void {
|
||||
for (const v of violations) {
|
||||
console.error(`${v.file}:${v.line}: ${v.message}`);
|
||||
console.error(`${file}:${v.line}: ${v.message}`);
|
||||
console.error(` ${v.text}\n`);
|
||||
totalViolations++;
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of files) {
|
||||
report(relative(process.cwd(), file), lintFile(file));
|
||||
}
|
||||
|
||||
const knownItems = registryItemNames();
|
||||
let snapshotsChecked = 0;
|
||||
for (const dir of SKILLS_DIRS) {
|
||||
if (!statSync(dir, { throwIfNoEntry: false })?.isDirectory()) continue;
|
||||
for (const path of collectMarkdownFiles(dir)) {
|
||||
const found = lintRegistryItemRefs(readFileSync(path, "utf-8"), knownItems);
|
||||
if (found === null) continue;
|
||||
snapshotsChecked++;
|
||||
report(relative(process.cwd(), path), found);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalViolations > 0) {
|
||||
console.error(`\n${totalViolations} skill lint error(s) found.`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`Checked ${files.length} skill file(s) — no issues found.`);
|
||||
console.log(
|
||||
`Checked ${files.length} skill file(s) and ${snapshotsChecked} registry snapshot(s) against ${knownItems.size} registry items — no issues found.`,
|
||||
);
|
||||
}
|
||||
|
||||
+14
-14
@@ -2,11 +2,11 @@
|
||||
"source": "heygen-com/hyperframes",
|
||||
"skills": {
|
||||
"embedded-captions": {
|
||||
"hash": "1677ab00946eb80c",
|
||||
"hash": "57a5caaa35ff79c8",
|
||||
"files": 142
|
||||
},
|
||||
"faceless-explainer": {
|
||||
"hash": "a7080101c30ceeb7",
|
||||
"hash": "986ee23676272292",
|
||||
"files": 24
|
||||
},
|
||||
"figma": {
|
||||
@@ -14,11 +14,11 @@
|
||||
"files": 2
|
||||
},
|
||||
"general-video": {
|
||||
"hash": "16898c02677d09bc",
|
||||
"hash": "ced729740550f414",
|
||||
"files": 4
|
||||
},
|
||||
"hyperframes": {
|
||||
"hash": "f09636f3307817ab",
|
||||
"hash": "e77a36c488b4f80c",
|
||||
"files": 17
|
||||
},
|
||||
"hyperframes-animation": {
|
||||
@@ -30,7 +30,7 @@
|
||||
"files": 7
|
||||
},
|
||||
"hyperframes-cli": {
|
||||
"hash": "1a691d7069bc158e",
|
||||
"hash": "03b1b65f35a1be63",
|
||||
"files": 11
|
||||
},
|
||||
"hyperframes-core": {
|
||||
@@ -46,39 +46,39 @@
|
||||
"files": 3
|
||||
},
|
||||
"hyperframes-registry": {
|
||||
"hash": "0142a8e09bbe7e2c",
|
||||
"hash": "51e6dba95a8dfb45",
|
||||
"files": 12
|
||||
},
|
||||
"media-use": {
|
||||
"hash": "591daf2adb78e1cd",
|
||||
"hash": "332f69eaeabc945f",
|
||||
"files": 156
|
||||
},
|
||||
"motion-graphics": {
|
||||
"hash": "853ac75cbab69036",
|
||||
"hash": "de8ec5464028ec67",
|
||||
"files": 23
|
||||
},
|
||||
"music-to-video": {
|
||||
"hash": "39282be90a90f89f",
|
||||
"hash": "be70b499dd72169b",
|
||||
"files": 132
|
||||
},
|
||||
"pr-to-video": {
|
||||
"hash": "e3c6d1527c04a804",
|
||||
"hash": "4905e50c64aab195",
|
||||
"files": 30
|
||||
},
|
||||
"product-launch-video": {
|
||||
"hash": "71226b200d8adae3",
|
||||
"hash": "960e964f32dcb4fa",
|
||||
"files": 30
|
||||
},
|
||||
"remotion-to-hyperframes": {
|
||||
"hash": "79fcf8e9641d126e",
|
||||
"hash": "13ade041e6416e5b",
|
||||
"files": 70
|
||||
},
|
||||
"slideshow": {
|
||||
"hash": "c68fb51d48b80802",
|
||||
"hash": "3d03ada897faebd2",
|
||||
"files": 2
|
||||
},
|
||||
"talking-head-recut": {
|
||||
"hash": "2eaa83d6889537a5",
|
||||
"hash": "50d1f9c928514826",
|
||||
"files": 28
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ Procedure: probe the clip → shortlist 2–3 identities from the catalog → re
|
||||
|
||||
(The full identity table lives in [CATALOG.md](CATALOG.md) — single source of truth for routing. The engine docs below describe each backend's authoring contract.)
|
||||
|
||||
**CATALOG.md is the whole answer space here: this workflow does not search the HyperFrames component registry.** The composition workflows run `npx hyperframes catalog` before authoring a named look; this one must not. Its engines are locked compilers that consume `cinematic.json` / `theme.json` and emit the composition themselves, so a registry item — the `caption-*` blocks included — has nothing to mount into. A registry block styles text on a designed canvas; this skill burns captions into somebody's footage through a matte. When no identity fits the ask, say so and pick the nearest, rather than reaching outside the catalog.
|
||||
|
||||
**Recommendation heuristic**: use the "Shortlisting heuristics" in [CATALOG.md](CATALOG.md) — they are identity-level (e.g. "炸" shortlists ordnance/stomp/terminal/loud and picks by WHAT should explode), never category-level. Unsure → `anchor`.
|
||||
|
||||
- **Cinematic** → write `plan.json` for a locked template, compiled by `make-composition.cjs`.
|
||||
|
||||
@@ -123,6 +123,8 @@ Edit `STORYBOARD.md` in place. Do not create another storyboard. Use `frame.md`
|
||||
|
||||
Read `references/visual-design.md`, `../hyperframes-animation/blueprints-index.md`, `references/motion-language.md`, and `../hyperframes-animation/rules-index.md`. Use `visual-design.md` for the method (the time-coded shot sequence, the inline Layout vocabulary, and the invented-visual treatment), plus the required `## Video direction` block. Use `../hyperframes-animation/blueprints-index.md` to pick each frame's shot shape. Use `motion-language.md` (the motion vocabulary + the motion doctrine) and `../hyperframes-animation/rules-index.md` (valid rule names) for motion — do not invent motion names.
|
||||
|
||||
**Search the live catalog before you invent any named look.** A faceless explainer invents every visual, which is exactly when a hand-authored rebuild of an existing block is most likely. For every look, effect, treatment or transition the brief names — "CRT scanlines", "glitch", "film grain", "shimmer sweep", "confetti burst" — run `npx hyperframes catalog --query "<the look, in plain English>" --json` and read the top results BEFORE you write that look into `STORYBOARD.md`. The search needs **nothing installed**: no project, no prior `add`, no account. It ranks the whole hosted registry (~400 blocks and components) from any directory. A block that already does the job becomes the frame's `focal` — name it here so Step 5's workers install and customize it. Invent a visual only after a search for it came back with nothing that fits.
|
||||
|
||||
For every frame, write a **time-coded shot sequence** into `STORYBOARD.md` per `visual-design.md`'s method: pick the frame's blueprint (or compose), instantiate it with THIS frame's **invented** content, and pace each Scene's reveal to the voiceover so the frame develops across its full duration instead of front-loading then freezing. Because the explainer is faceless, `focal`/`roles` name the **invented visual elements** (a hero word, a diagram node, a data-viz series) — you are designing them, not selecting captured assets. State layout and motion **inline** per Scene (vocabularies in `visual-design.md` and `motion-language.md`). Add one video-wide `## Video direction` block.
|
||||
|
||||
Do not change story, script, `transition_in`, or the source text. Do not write HTML in this step. There is **no asset-staging step** — faceless visuals are built by the workers in Step 5. If the user supplied a real `public/<basename>` image, reference it by path in the relevant frame's `focal`/`roles`; otherwise nothing to stage.
|
||||
|
||||
@@ -101,7 +101,7 @@ Do not replace these reads with recollection. Progressive disclosure saves conte
|
||||
|
||||
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.
|
||||
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. **Search the live catalog before you plan to build any named look yourself**: for every look, effect, treatment or transition the brief names — "CRT scanlines", "glitch", "film grain", "shimmer sweep", "confetti burst" — run `npx hyperframes catalog --query "<the look, in plain English>" --json` and read the top results before the plan names how that look gets built. The search needs **nothing installed**: no project, no prior `add`, no account. It ranks the whole hosted registry (~400 blocks and components) from any directory, so it also applies to a look the user asks for mid-build. Blocks the plan names are installed at stage 3; hand-author a look only after a search for it came back with nothing that fits. 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.
|
||||
|
||||
@@ -16,7 +16,7 @@ npx hyperframes init my-video --non-interactive --example blank # CI/agents —
|
||||
|
||||
**Default depends on TTY**: in a terminal, the CLI prompts for example/options. Outside a TTY (CI, agents, piped output) it auto-switches to non-interactive and **requires `--example`** (the CLI errors with a usage example if missing). Pass `--non-interactive` to force flag-only mode even on a TTY.
|
||||
|
||||
Templates: `blank`, `warm-grain`, `play-mode`, `swiss-grid`, `vignelli`, `decision-tree`, `kinetic-type`, `product-promo`, `nyt-graph`.
|
||||
Templates: `blank`, `warm-grain`, `play-mode`, `swiss-grid`, `vignelli`, `decision-tree`, `kinetic-type`, `product-promo`, `nyt-graph`, `vscode-theme-visualizer`. (The closed set of `hyperframes:example` items in `registry/registry.json`. `hyperframes catalog` does not list examples — its `--type` takes only `block` or `component` — so this list has no live equivalent and is checked by `bun run lint:skills`.)
|
||||
|
||||
Other useful flags:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: hyperframes-registry
|
||||
description: Install, discover, and wire registry blocks and components into HyperFrames compositions. Use when running hyperframes add or hyperframes catalog, installing one item or every block matching a tag, wiring an installed item into index.html, or working with hyperframes.json. Covers discovery, install locations, block sub-composition wiring, component snippet merging, and authoring a new block or component to contribute upstream (idea → scaffold → validate → PR).
|
||||
description: Search, install, and wire registry blocks and components into HyperFrames compositions. Use BEFORE hand-building any named visual — whenever a brief, a user, or a storyboard names a look, effect, treatment, or transition such as CRT scanlines, glitch, chromatic aberration, film grain, a shimmer sweep, a chart, a code or terminal window, a map, or a confetti burst — because roughly 400 hosted items already cover many of them and the search ranks all of them with nothing installed, no project, and no account. Also use when running hyperframes add or hyperframes catalog, installing one item or every block matching a tag, wiring an installed item into index.html, or working with hyperframes.json. Covers discovery, install locations, block sub-composition wiring, component snippet merging, and authoring a new block or component to contribute upstream (idea → scaffold → validate → PR).
|
||||
---
|
||||
|
||||
# HyperFrames Registry
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Registry discovery
|
||||
|
||||
<!-- registry-items: allow=data-composition-id,data-start,data-track-index -->
|
||||
|
||||
## Use the catalog command first
|
||||
|
||||
```bash
|
||||
@@ -54,7 +56,7 @@ Where `<type-dir>` is `examples`, `blocks`, or `components`.
|
||||
|
||||
### Blocks
|
||||
|
||||
For an always-current list run `npx hyperframes catalog --type block`. The tables below group the 97 blocks by category. **Block name ≠ shader name**: shader-transition blocks (e.g. `domain-warp-dissolve`) wrap a HyperShader runtime whose internal name omits the `-dissolve`/`-warp` suffix — see the showcase HTML installed alongside the block for the canonical name.
|
||||
For an always-current list run `npx hyperframes catalog --type block`. **The search is the source of truth; the tables below are a hand-maintained sample and under-cover by design** — they group 97 of the registry's 180 blocks by category, so a block missing from them is not evidence the registry lacks it. Only an empty `npx hyperframes catalog --query "<what you want>" --json` is that evidence. Do not grow these tables toward the full set; search instead. **Block name ≠ shader name**: shader-transition blocks (e.g. `domain-warp-dissolve`) wrap a HyperShader runtime whose internal name omits the `-dissolve`/`-warp` suffix — see the showcase HTML installed alongside the block for the canonical name.
|
||||
|
||||
#### Shader transitions (14)
|
||||
|
||||
|
||||
+12
-11
@@ -85,17 +85,18 @@ Use the bare name without `/`. If the command fails, surface the error; do not r
|
||||
|
||||
## 5. Load domain skills on demand
|
||||
|
||||
| Need | Skill |
|
||||
| ------------------------------------------------------------------------------------------------------------------- | ------------------------ |
|
||||
| Composition structure, timing attributes, tracks, variables, determinism | `/hyperframes-core` |
|
||||
| Motion rules, scene blueprints, transitions, runtime adapters | `/hyperframes-animation` |
|
||||
| Seek-safe GSAP, CSS, Anime.js, WAAPI, FLIP, paths, masks, SVG, 3D keyframes, or `hyperframes keyframes` diagnostics | `/hyperframes-keyframes` |
|
||||
| Design specs, concept, palette, typography, narration, beat planning | `/hyperframes-creative` |
|
||||
| Images, icons, logos, audio, captions, grades, LUTs, reusable media | `/media-use` |
|
||||
| Voiceover carve, audio effect chains, automation envelopes, or one chain/fader across several tracks (submix bus) | `/hyperframes-audio` |
|
||||
| Init, lint, check, snapshots, compare, batch render, Studio, render, publish, or diagnostics | `/hyperframes-cli` |
|
||||
| Registry blocks and components | `/hyperframes-registry` |
|
||||
| Figma assets, tokens, components, or storyboard frames as reconstructed motion | `/figma` |
|
||||
| Need | Skill |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
|
||||
| Composition structure, timing attributes, tracks, variables, determinism | `/hyperframes-core` |
|
||||
| Motion rules, scene blueprints, transitions, runtime adapters | `/hyperframes-animation` |
|
||||
| Seek-safe GSAP, CSS, Anime.js, WAAPI, FLIP, paths, masks, SVG, 3D keyframes, or `hyperframes keyframes` diagnostics | `/hyperframes-keyframes` |
|
||||
| Design specs, concept, palette, typography, narration, beat planning | `/hyperframes-creative` |
|
||||
| Images, icons, logos, audio, captions, grades, LUTs, reusable media | `/media-use` |
|
||||
| Voiceover carve, audio effect chains, automation envelopes, or one chain/fader across several tracks (submix bus) | `/hyperframes-audio` |
|
||||
| Init, lint, check, snapshots, compare, batch render, Studio, render, publish, or diagnostics | `/hyperframes-cli` |
|
||||
| Registry blocks and components | `/hyperframes-registry` |
|
||||
| A named look, effect, treatment, or transition — CRT scanlines, glitch, film grain, shimmer sweep, confetti burst — BEFORE hand-building it | `/hyperframes-registry` |
|
||||
| Figma assets, tokens, components, or storyboard frames as reconstructed motion | `/figma` |
|
||||
|
||||
Creator edit phrases are cross-domain requests. Load every skill named in the matching row:
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Captions
|
||||
|
||||
<!-- registry-items: allow=max-width,data-composition-src,hyperframes-registry,blend-mode,caption-style,font-family -->
|
||||
|
||||
**The live search is the source of truth for what the registry has.** The table(s) below are a hand-maintained sample and under-cover by design: run `npx hyperframes catalog --query "<what you want>" --json` — it needs nothing installed — before concluding the registry lacks something. Item names here are checked against `registry/registry.json` by `bun run lint:skills`.
|
||||
|
||||
Before authoring: confirm the transcript came from the right Whisper model. CLI default `small.en` silently translates non-English audio — see [`../transcribe.md`](../transcribe.md) → "Language Rule" and [`transcript-handling.md`](transcript-handling.md) for the mandatory quality check.
|
||||
|
||||
Analyze spoken content to determine caption style. If user specifies a style, use that. Otherwise, detect tone from the transcript.
|
||||
|
||||
@@ -6,6 +6,7 @@ Turn `shot-plan.json` into one renderable HyperFrames composition (`compositions
|
||||
|
||||
Default = **compose existing catalog capabilities, not hand-author**:
|
||||
|
||||
- **Search first, for every named effect** — `npx hyperframes catalog --query "<the move, in plain English>" --json`, including an effect the user names after the plan is written. It needs nothing installed and no project. Author by hand only after a search came back with nothing that does the job, and report that miss with `npx hyperframes feedback --search-miss`.
|
||||
- `npx hyperframes add <block>` (registry) → customize in place. Most blocks bake content/data into their own script (only a few expose CSS-var params), so reuse = **add + edit**.
|
||||
- `hyperframes-animation` rules / blueprints / transitions for motion; runtime adapters (GSAP default).
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ Emit a DRAFT `shot-plan.json`.
|
||||
|
||||
Given the draft + resolved `assets/index.md` (if Step 2 ran) + `catalog-map.md`, design the shot **around the assets**:
|
||||
|
||||
- Pick the **catalog block(s)** + the `hyperframes-animation` rules / blueprints (catalog-aware — see `catalog-map.md`).
|
||||
- **Run `npx hyperframes catalog --query "<the move, in plain English>" --json` for every look or effect the brief names**, before naming any block. It ranks the whole hosted registry and needs nothing installed. `catalog-map.md` is a partial snapshot; the search is the source of truth.
|
||||
- Pick the **catalog block(s)** from those results + the `hyperframes-animation` rules / blueprints (see `catalog-map.md` for how each category customizes).
|
||||
- Layout (hero-frame), motion (per `references/motion-vocabulary.md`), beats, pacing, exits.
|
||||
- `asset-fusion`: read the asset's **geometric affordance** → `element_positions` (center / extent / safe-zones / avoid-zones) + **eyedropper palette** from the asset.
|
||||
- Finalize `shot-plan.json`: `content.block` + `content.customize` + the per-category `content`.
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# Director → catalog block map (reuse-first)
|
||||
|
||||
<!-- registry-items: allow=geo-highlight,geo-flow,flag-borders,pin-rollout,stat-motion,data-composition-src -->
|
||||
<!-- allow= entries above are deliberately NOT registry items: geo-*/flag-borders/pin-rollout and stat-motion are hand-authored gaps this file names in order to say they are gaps. -->
|
||||
|
||||
**Search the live catalog before you use this table, and again before any hand-authored effect.** Run
|
||||
`npx hyperframes catalog --query "<the move, in plain English>" --json` — once per named look or effect the
|
||||
user asks for ("CRT scanlines", "glitch", "film grain", "shimmer sweep"), including effects asked for
|
||||
mid-build. **The search needs nothing installed**: it ranks the whole hosted registry (~400 items) from any
|
||||
directory, with no project, no prior `add`, and no account. The table below is a hand-maintained snapshot of
|
||||
part of that registry and it under-covers by design — treat a miss here as unproven, and only the search's
|
||||
own empty result as evidence the catalog lacks the move. When it does, say so with
|
||||
`npx hyperframes feedback --search-miss "<query>" --wanted "<the move>" --tier <tier from the envelope>`
|
||||
before hand-authoring. Full flags and tiers: `/hyperframes-registry` → § Discovery.
|
||||
|
||||
The Builder's **default is to compose existing HF catalog blocks, not hand-author.** `npx hyperframes add <block>` drops a block's source into `compositions/`; the Builder then **customizes in place** — most blocks bake their content/data into their own script (only a few expose CSS-var `params`), so reuse = **add + edit**, not pure variable injection. Hand-author only (a) gaps no block covers and (b) the asset-fusion affordance binding.
|
||||
|
||||
After classifying intent → category, the **Director names the block(s) + what to customize** in the shot-plan IR:
|
||||
@@ -12,9 +25,9 @@ After classifying intent → category, the **Director names the block(s) + what
|
||||
|
||||
| Category | Borrow from catalog | Customize | Gaps → hand-author |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
|
||||
| **kinetic-typo** | one of **18 `caption-*`** (kinetic-slam, editorial-emphasis, clip-wipe, gradient-fill, neon-glow, glitch-rgb, matrix-decode, particle-burst, weight-shift, pill-karaoke, highlight, blend-difference…) | words; `emphasis_words` → `word--emphasis`; palette; font; timing | a motif none of the 18 cover |
|
||||
| **charts** | `data-chart` (bar+line, staggered, value labels) | edit the data array + headline/subtitle; `--bg`/`--text` | pie/donut, bar-chart-race, ring/% |
|
||||
| **stat** | `apple-money-count` (finance: $ counter + burst + SFX) **or** our generic `stat-motion` (any %/number + ring) | target, prefix/suffix, label, palette | — |
|
||||
| **kinetic-typo** | one of **17 `caption-*`** (kinetic-slam, editorial-emphasis, clip-wipe, gradient-fill, neon-glow, glitch-rgb, matrix-decode, particle-burst, weight-shift, pill-karaoke, highlight, blend-difference…) | words; `emphasis_words` → `word--emphasis`; palette; font; timing | a motif none of the 17 cover |
|
||||
| **charts** | `data-chart` (bar+line, staggered, value labels), `bar-chart-race` (a race) | edit the data array + headline/subtitle; `--bg`/`--text` | pie/donut, ring/% |
|
||||
| **stat** | `apple-money-count` (finance: $ counter + burst + SFX) **or** hand-author a generic %/number + ring per `categories/stat/module.md` (there is no `stat-motion` block) | target, prefix/suffix, label, palette | — |
|
||||
| maps/geo | **vector lane**: `us-map` (+bubble/hex/flow), `world-map`, `spain-map` + **hand-author** `geo-highlight`/`geo-flow`/`flag-borders`/`pin-rollout` (NOT in registry — build per `categories/maps/module.md`). **basemap lane** (real satellite/dark / zoom-to-place): bake via `categories/maps/bake-basemap.mjs` → `<video>` + geo-aligned SVG overlay (border draw-on + colour-block fills) | regions/data, palette, callouts/connectors, basemap style | (basemap lane now covers real imagery + zoom-to-address — was the gap) |
|
||||
| diagram | `flowchart` (SVG connectors + nodes) | nodes, edges, labels | — |
|
||||
| **code / code-reveal** | one of the **9 Code Animations** blocks: `code-typing` (live typing), `code-diff` (a change), `code-morph` (a refactor), `code-highlight` (spotlight a line; `line` is 0-based), `code-scroll` (walk a file), `code-snippet-flight` (assemble); GPU hero reveals `code-3d-extrude` / `code-shader-dissolve` / `code-particle-assemble` for a title-card moment; for a static themed code/terminal window use a `code-snippet-*` block | the baked code string / diff / theme | a code motion none cover |
|
||||
|
||||
@@ -9,7 +9,8 @@ Animated **data-viz** from data. Asset-free (the "input" is the data). "One char
|
||||
## Vocabulary / leans on
|
||||
|
||||
- Block: **`data-chart`** (animated **bar + line**, staggered reveal, value labels — proven: borrowed + customized + rendered to MP4 in the prototype `charts-demo`).
|
||||
- Gaps (hand-author): **pie / donut, bar-chart-race, ring/%** — `data-chart` doesn't cover these. Use D3/visx for data→geometry + GSAP for motion.
|
||||
- Also in the registry: **`bar-chart-race`** — install it rather than hand-authoring a race.
|
||||
- Gaps (hand-author): **pie / donut, ring/%** — no registry block covers these. Search first (`npx hyperframes catalog --query "pie chart reveal" --json`), then use D3/visx for data→geometry + GSAP for motion.
|
||||
- Signature animations: bar stagger-grow · line `stroke-dashoffset` draw-on · pie radial sweep · ring fill · KPI count-up · race reorder.
|
||||
|
||||
## Build (reuse-first)
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# lower-thirds — category module
|
||||
|
||||
<!-- registry-items: allow= -->
|
||||
|
||||
**The live search is the source of truth for what the registry has.** The table(s) below are a hand-maintained sample and under-cover by design: run `npx hyperframes catalog --query "<what you want>" --json` — it needs nothing installed — before concluding the registry lacks something. Item names here are checked against `registry/registry.json` by `bun run lint:skills`.
|
||||
|
||||
**Name/title bars, callouts, social overlays** — graphics meant to sit over other footage. Asset-free (+ optional logo). Usually `export: alpha-overlay` (transparent). ~3–6s (or loop/hold).
|
||||
|
||||
## Plan (Director)
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# text module · motion vocabulary (primitive → GSAP)
|
||||
|
||||
<!-- registry-items: allow= -->
|
||||
|
||||
**The live search is the source of truth for what the registry has.** The table(s) below are a hand-maintained sample and under-cover by design: run `npx hyperframes catalog --query "<what you want>" --json` — it needs nothing installed — before concluding the registry lacks something. Item names here are checked against `registry/registry.json` by `bun run lint:skills`.
|
||||
|
||||
Named primitives the Director references in `motion` strings and the Builder implements. `code_hint`s are framework-neutral physics; the GSAP recipe is the HF implementation. Prefer an HF **registry component** (bottom) when one fits — don't reinvent.
|
||||
|
||||
## Entry
|
||||
|
||||
@@ -91,7 +91,7 @@ Goal: Turn the skeleton into an approved, complete `STORYBOARD.md`.
|
||||
Read [`references/planning.md`](references/planning.md), [`storyboard-format.md`](references/storyboard-format.md), [`template-catalog.md`](references/template-catalog.md), [`motion-primitive-catalog.md`](references/motion-primitive-catalog.md), and [`montage.md`](references/montage.md) (only if the user supplied assets). Editing the same file in place, do two things:
|
||||
|
||||
1. **Pick the brand.** Choose one preset from `../hyperframes-creative/frame-presets/` using the table in `../hyperframes-creative/references/design-spec.md` (match the track's mood; **only its fonts and colors matter** — templates own composition). Copy it into `frame.md` **unmodified** and fill the frontmatter `style` (font + a ≤4–6 swatch palette) from it.
|
||||
2. **Fill every frame.** Decide its groups and give each a treatment: a matched template from the catalog (with bound params and real audiomap anchors), a free-compose from the primitive catalog, or an asset treatment that **obeys `pacing`**. Write the copy. You own WHAT (template / primitives + content + anchors); the frame-worker owns HOW — **never write millisecond tweens into the storyboard**.
|
||||
2. **Fill every frame.** Decide its groups and give each a treatment: a matched template from the catalog (with bound params and real audiomap anchors), a free-compose from the primitive catalog, or an asset treatment that **obeys `pacing`**. **Before you free-compose a named look, search the live catalog for it**: for every look, effect, treatment or transition the user asked for — "CRT scanlines", "glitch", "film grain", "shimmer sweep" — run `npx hyperframes catalog --query "<the look, in plain English>" --json` and read the top results. `template-catalog.md` and `motion-primitive-catalog.md` list only this skill's own local materials; the search ranks the whole hosted registry (~400 blocks and components) and needs **nothing installed** — no project, no prior `add`, no account. Free-compose a look only after a search for it came back with nothing that fits. Write the copy. You own WHAT (template / primitives + content + anchors); the frame-worker owns HOW — **never write millisecond tweens into the storyboard**.
|
||||
|
||||
```bash
|
||||
node <SKILL_DIR>/scripts/validate-plan.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \
|
||||
|
||||
@@ -151,6 +151,8 @@ Edit `STORYBOARD.md` in place. Do not create another storyboard. Use `frame.md`
|
||||
|
||||
Read `references/visual-design.md`, `../hyperframes-animation/blueprints-index.md`, `references/motion-language.md`, `references/code-vocabulary.md`, and `../hyperframes-animation/rules-index.md`. Use `visual-design.md` for the method (the time-coded shot sequence, the inline Layout vocabulary, and the code-beat treatment), plus the required `## Video direction` block. Use `../hyperframes-animation/blueprints-index.md` to pick each frame's shot shape. Use `code-vocabulary.md` to pick the right `code-*` block per code beat (diff = `code-diff`, refactor = `code-morph`, new code = `code-typing`, …). Use `motion-language.md` (the motion vocabulary + the motion doctrine) and `../hyperframes-animation/rules-index.md` (valid rule names) for motion — do not invent motion or block/blueprint names.
|
||||
|
||||
**Search the live catalog before you design any named look.** `code-vocabulary.md` covers the code beats; it does not cover the rest. For every other look, effect, treatment or transition the brief names — "CRT scanlines", "glitch", "film grain", "shimmer sweep", "confetti burst" — run `npx hyperframes catalog --query "<the look, in plain English>" --json` and read the top results BEFORE you write that look into `STORYBOARD.md`. The search needs **nothing installed**: no project, no prior `add`, no account. It ranks the whole hosted registry (~400 blocks and components) from any directory. Name the block you found here; Step 5 pre-installs every block the storyboard names. Hand-author a look only after a search for it came back with nothing that fits.
|
||||
|
||||
For every frame, write a **time-coded shot sequence** into `STORYBOARD.md` per `visual-design.md`'s method: pick the frame's blueprint (or compose), instantiate it with THIS frame's content, and pace each Scene's reveal to the voiceover so the frame develops across its full duration instead of front-loading then freezing. **For a code beat, the `code-*` block is the frame's `focal`** and the Scenes choreograph the surrounding code-editorial Code Surface (the entry of the file/header, the camera onto the hunk, the landing line) — **not** the code animation itself, which the block owns. Immediately after each code frame's fields, add a `### Source excerpt` fenced `diff` block containing only the exact real hunk the worker must render (12 lines maximum). Select it here from `capture/diff.patch`; workers are forbidden from reopening that full diff. State layout and motion **inline** per Scene (vocabularies in `visual-design.md` and `motion-language.md`). Add one video-wide `## Video direction` block.
|
||||
|
||||
Do not change story, script, `transition_in`, `asset_candidates`, or the PR source. Do not write HTML in this step. There is **no asset-staging step** — the only real assets are the credits avatars, already in `assets/`.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Code vocabulary — the `code-*` animation blocks
|
||||
|
||||
<!-- registry-items: allow=data-duration,number-lockup,dark-plus,light-plus,dark-modern,light-modern,dark-2026,light-2026,solarized-light,visual-studio-dark,visual-studio-light,high-contrast,high-contrast-light,clear-dark,clear-light,man-page,red-sands,silver-aerogel,solid-colors -->
|
||||
|
||||
**The live search is the source of truth for what the registry has.** The table(s) below are a hand-maintained sample and under-cover by design: run `npx hyperframes catalog --query "<what you want>" --json` — it needs nothing installed — before concluding the registry lacks something. Item names here are checked against `registry/registry.json` by `bun run lint:skills`.
|
||||
|
||||
PR videos run on two kinds of moving picture: **code** (the lines that changed) and **behavior** (what the change _does_ at runtime). This file is the vocabulary for both — the `code-*` blocks for code beats, and the **mechanism beat** (an invented animated diagram, or a `flowchart` / `data-chart`) for behavior beats. A video that is _all_ code reads flat; **alternate the two** (story-design plans the rhythm; see "Showing behavior" below).
|
||||
|
||||
For code beats the registry ships purpose-built **code animation blocks** that render a diff, a typed-on snippet, a morph, a highlight, a scroll, or a 3D/particle/dissolve reveal — far better than hand-built motion. **Reach for one of these first** for any code beat; fall back to hand-authored composition only when none fits.
|
||||
|
||||
@@ -146,6 +146,8 @@ Edit `STORYBOARD.md` in place. Do not create another storyboard. Use `frame.md`
|
||||
|
||||
Read `references/visual-design.md`, `../hyperframes-animation/blueprints-index.md`, `references/motion-language.md`, and `../hyperframes-animation/rules-index.md`. Use `visual-design.md` for the method (the time-coded shot sequence, the inline Layout vocabulary, and the required `## Video direction` block). Use `../hyperframes-animation/blueprints-index.md` to pick each frame's shot shape. Use `motion-language.md` (the motion vocabulary + the motion doctrine) and `../hyperframes-animation/rules-index.md` (valid rule names) for motion — do not invent motion names.
|
||||
|
||||
**Search the live catalog before you design any named look.** For every look, effect, treatment or transition the brief names — "CRT scanlines", "glitch", "film grain", "shimmer sweep", "confetti burst" — run `npx hyperframes catalog --query "<the look, in plain English>" --json` and read the top results BEFORE you write that look into `STORYBOARD.md`. The search needs **nothing installed**: no project, no prior `add`, no account. It ranks the whole hosted registry (~400 blocks and components) from any directory. A block that already does the job becomes the frame's `focal` — name it here, so Step 5's workers install and customize it instead of rebuilding it. Hand-author a look only after a search for it came back with nothing that fits.
|
||||
|
||||
For every visual frame, write a **time-coded shot sequence** into `STORYBOARD.md` per `visual-design.md`'s method: pick the frame's blueprint (or compose), instantiate it with THIS product's content, and pace each Scene's reveal to the voiceover so the frame develops across its full duration instead of front-loading then freezing. State layout and motion **inline** per Scene (vocabularies in `visual-design.md` and `motion-language.md`). Add one video-wide `## Video direction` block.
|
||||
|
||||
When an element visibly continues across a frame boundary, give both workers the same numerical handoff in `STORYBOARD.md`: add `handoff_out:` to the outgoing frame and a matching `handoff_in:` to the incoming frame. Name the element and its exact x/y position, scale, opacity, and motion direction/speed at the cut — state every field even when it does not change, because a constant is `opacity: 1`, not an omission. Omit the whole block only for a deliberate clean cut. The goal is simple: parallel workers must not invent two different versions of the same seam.
|
||||
|
||||
@@ -67,6 +67,8 @@ Read [`references/api-map.md`](references/api-map.md) — the index of every Rem
|
||||
|
||||
Don't load all of them — load only what the specific source needs.
|
||||
|
||||
**Search the live catalog for any visual effect the table does not map.** When the source paints a look with no HF API equivalent — a scanline/CRT overlay, a glitch or chromatic-aberration pass, a shader wipe, a film-grain treatment — run `npx hyperframes catalog --query "<the effect, in plain English>" --json` before hand-writing it in GSAP. The search needs **nothing installed**: no project, no prior `add`, no account. It ranks the whole hosted registry (~400 blocks and components) from any directory, and `transitions.md` already takes this route for `clockWipe()` / `iris()` via `npx hyperframes add sdf-iris`. A real component is closer to the source than a hand-approximation, so it usually raises the SSIM rather than lowering it — but the render diff in Step 4 is still the arbiter. Hand-write the effect when a search returns nothing that fits, and record the substitution in `TRANSLATION_NOTES.md` either way.
|
||||
|
||||
### Step 3: Generate the HF composition
|
||||
|
||||
Emit `index.html` with:
|
||||
|
||||
@@ -164,6 +164,7 @@ These are hard constraints, not suggestions. A slide that violates them will be
|
||||
- **Lead with the punchline.** The strongest point goes first — on the slide and in the deck order. Investors read left-to-right, top-to-bottom, and they stop.
|
||||
- **Bottom-up market sizing only.** Never write "$50B TAM" without showing the math. Build from unit economics up: accounts × ACV, or transactions × take-rate.
|
||||
- **Font minimum 30pt equivalent.** At 1920×1080, a headline is 72–96px; body copy is 48px. Never go below 40px for any text the audience must read.
|
||||
- **Search the live catalog before hand-building any named visual.** For every look, effect, chart, treatment or transition a slide needs — "CRT scanlines", "glitch", "bar chart race", "shimmer sweep", "terminal window" — run `npx hyperframes catalog --query "<the visual, in plain English>" --json` and read the top results before you author the slide's clips. The search needs **nothing installed**: no project, no prior `add`, no account. It ranks the whole hosted registry (~400 blocks and components) from any directory. `npx hyperframes add <name>` drops the block's source into the deck, where you customize it in place. This applies with extra force when porting a source page: a real block beats the simplified approximation the porting rules below forbid.
|
||||
|
||||
## Porting source pages
|
||||
|
||||
|
||||
@@ -755,6 +755,13 @@ table column that matches the storyboard's `layout` field.
|
||||
|
||||
#### Available `data-anim` Kinds
|
||||
|
||||
This list is closed, and deliberately so: a card is an HTML fragment whose motion this
|
||||
skill compiles into the shared overlay timeline in Step 9 (see the GSAP mapping table
|
||||
there). That is why this workflow does not search the HyperFrames component registry the
|
||||
way the composition workflows do — `npx hyperframes catalog` returns standalone
|
||||
compositions that carry their own timeline, and a card has no place to mount one. Reach a
|
||||
look the kinds below cannot express with plain CSS inside the card's scoped `<style>`.
|
||||
|
||||
| kind | use for | key params |
|
||||
| --------------- | ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `fade-in` | enter | `at`, `duration`, `ease?` |
|
||||
|
||||
Reference in New Issue
Block a user