Rames' second item on #2976, fixed here because this is the line that owns it.
It was the only cols={3} in docs/, and all three cards carry body text — the
case docs/AGENTS.md names as hyphenating titles mid-word at this content width.
The rules file is #2976's deliverable, so it should not ship with the tree
beneath it holding the one counter-example.
Rewrites the pages that survive the restructure so they lead with what a reader
can accomplish, and points them at the sections added in the previous commit.
Page set and navigation are unchanged here; only content moves.
Keeps the skill count in README. CLAUDE.md's catalog-maintenance rule requires
the count to live in README and CLAUDE.md, and both now agree with the 19
directories under skills/.
Removes the thirteen pages the rebuilt sections replaced, and claims a redirect
for each one in the same commit so no published URL starts returning a 404.
Each destination is the page that now answers the question the retired page was
answering — the Studio pages for editor topics, the workflow guides for the
per-source how-tos, Troubleshooting for the mistakes list.
Adds the pages the rebuilt navigation is organised around, and moves the sidebar
onto that structure. Every entry points at a file that exists after this commit;
nothing is rewritten or removed yet, and no redirect is claimed yet.
- Studio (13 pages) — the editor had no section of its own
- One guide per creation workflow, matching the shipped agent skills
- Section hubs: Concepts, Catalog, Developers, Deploy, Workflows, Help,
Go further, Product updates, 30 Days of HyperFrames
Pages a later commit retires drop out of the sidebar here but still exist and
still resolve, so the site stays navigable at this commit.
Incidentally fixes a link to /concepts from the Lambda migration guide that is
broken on main today — the destination did not exist.
Both pages explained intensity's independence by saying details and
effects are applied after the u_intensity mix. The conclusion was right
but the mechanism was wrong for several families.
Verified in the shader: applyCrtWarp runs on the uv before sampling;
sampleMedia itself carries pixelate, chromaBleed and the tape family;
sampleChromaticMedia and applyDigitalGlitch shape sampleColor — all
before the mix at runtime/colorGrading.ts:1234. Only grain,
filmArtifacts, monoScreen, engraving, crosshatch, halftone, twoInkPrint,
bloom, scanlines and vignette run after it.
Pre-mix effects are already present on both sides of
mix(sampleColor.rgb, applyColorGrade(sampleColor.rgb), u_intensity), so
intensity does not scale them either. Both pages now say details and
effects sit outside the mix — some before, some after — without making
the ordering the reason.
Reported by miguel-heygen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both pages said intensity does not scale a grade and that 0.5 renders the
same as 0. That is wrong, and the error was mine: I tested intensity only
against twoInkPrint and tapeDamage, then generalised from an effects-only
result.
The shader mixes ungraded against graded at u_intensity
(runtime/colorGrading.ts:1234), so it does scale adjust, wheels, curves,
hueCurves, secondaries and the LUT. Runtime tests pin 0.25 and 0.75
reaching the uniform. What it does not scale is details and effects —
grain, filmArtifacts, monoScreen, engraving, crosshatch, halftone,
twoInkPrint and the tape/CRT families are all applied after that mix
(:1235-1262), which is exactly what I had measured.
Both pages now say intensity ramps the primary grade only, and to animate
the specific effect when the look is effect-based.
Reported by miguel-heygen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Repoint the generated-artwork exit bridge at color-grading. The nav
inserted the new page between generated-artwork and vfx-and-liquid-glass
but the "Next" link still skipped it (miga-heygen, blocking).
- Correct the LUT custom property name: --hf-color-grading-lut-intensity,
not --hf-color-grading-lut. Real transcription error, surfaced while
checking the CSS-variable review comment against the source table in
packages/core/src/colorGrading.ts:921-931.
- Add #t=0.1 posterframe hints and a contextual italic caption to all ten
videos, matching the sibling prompting chapters.
- Reconcile British spelling to American throughout. The file path, nav
slug, page title and every cross-reference were already "color".
- De-duplicate the animatable-effect caveat list: the chapter now links to
the guide's Animating a Grade section instead of restating which effects
are verified working, so the list is maintained in one place.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The guide covers the contract; the chapter covers the two failures the
contract cannot express — choosing a source that has something for the
treatment to remove, and separating a subject so part of the frame can
be graded while the rest is protected.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ten A/B demos, each with the plain-language prompt that produced it and
the payload it compiled to. Slots into Level 4 — Substance.
The chapter teaches technique and leaves the key/bound reference to the
Colour Grading guide rather than duplicating it.
Also adds two sections to docs/guides/color-grading.mdx:
- Animating a Grade — the nine CSS custom properties, plus driving the
payload from the timeline for effects that have none. Documents that
--hf-color-grading-intensity does not scale a grade at render time,
and that payload-rewrite animation is effect-dependent: verified
working for halftone and twoInkPrint, verified not working for
crtCurvature, scanlines, chromaBleed and chromaticAberration.
- Limiting a Grade to Part of the Frame — grading qualifies by value,
never by screen position, so a region has to become its own layer.
Includes the three layer recipes and a worked face-redaction example.
Previously the support matrix said "not supported" with nowhere to go.
Renders are served from the CDN; docs/images/ is gitignored.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Second half of a review comment I had only half-addressed: the opt-out
behaviour shipped in 4f464dc4, but "should we add this into/connected to
the existing telemetry doc?" did not.
There is no standalone telemetry page — the canonical disclosure is the
`telemetry` command section in packages/cli. Links now run both ways so
neither page describes canaries as a separate system:
- packages/cli #telemetry: telemetry state also controls canary
enrolment, with every opt-out route named.
- contributing/canary-rollouts: a Note at the top, before any of the
how-to, saying canaries sit behind the telemetry switch and why (a
canary is a measured rollout; an install that reports nothing cannot be
compared, so enrolling it buys no signal).
- guides/feedback "Opting Out": disabling telemetry also ends canary
enrolment, alongside the feedback prompt and usage tracking.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(prompting): correct workflow one-liners against skill contracts
general-video leads with its positive identity and companion mode;
faceless-explainer keys on invented visuals instead of TTS;
talking-head-recut uses the 'graphic overlays' trigger term;
motion-graphics gains its input side and overlay output;
music-to-video stops implying images are required.
* docs(prompting): make vocabulary video grids readable
Replace the 4-5 column table hack with a 3-column CSS grid,
switch demo clips to autoplay muted loops (no black poster frame,
no player chrome over tiny videos), and align cells at 16:9.
* docs(prompting): document the opening interview and run-shape questions
The guide taught prompt shapes but never prepared readers for the
conversation that follows: the intent interview, the two run-shape
questions (storyboard, automation vs companion), the just-build-it
skip, and BRIEF.md as the resumable artifact. Add that section to the
overview, a disambiguation note on the storyboards page, and free up
'companion' as a reserved term in media-and-audio.
* docs(guides): make BRIEF.md the pipeline's Step 3 artifact
Step 3 (Strategy & Messaging) listed no output while describing
exactly what BRIEF.md now captures. Name the artifact in the step
table, project tree, step body, gate, and iterating list, and fix
SCRIPT.md's step label in the tree (Step 4, not 3).
* docs(quickstart): realign the setup surface with the skills catalog
The quickstart drifted from docs/guides/skills.mdx, CLAUDE.md, and the
prompting overview — it had never been updated when those surfaces were:
- `--full-depth` on both install commands, with the reason inline. Without
it `skills add` fetches the skills.sh registry blob, which lags `main` by
hours, so a reader following the quickstart installs stale skills.
- `check` in the `/hyperframes-cli` row, and a validate step in the manual
dev loop, which went preview → render with no gate at all. The prompting
overview calls `check` "the step people skip and regret" and states both
`lint` and `check` must pass before rendering.
- `/hyperframes-keyframes` in the core-skills table (8 rows → 9).
- `/figma` in the optional-workflow list (10 → 11).
* docs(skills): close the catalog drift class and complete the music-to-video input
Follow-up on the two review nits from #2872.
`/music-to-video`'s SKILL.md names three inputs — an audio file, a video to
pull audio from, or a track generated from a mood brief. Every compressed copy
of that description carried only the first two, and the third is the one that
makes "a complete video needs zero assets" true. Fixed on all eight surfaces
that state it, so no surface is now more correct than its siblings: the
prompting overview and quickstart setup tables, docs/guides/skills.mdx, the
README catalog, root CLAUDE.md + AGENTS.md, both CLI project templates, and the
router's own routes/music-to-video.md Input line (whose Interview must-haves
already listed all three).
The drift was structural, not accidental: the sync set declared in
docs/guides/skills.mdx and in CLAUDE.md's "Skill catalog maintenance" named
four surfaces and never the two setup tables, so those two were free to rot
while the declared four stayed correct. Both declarations now name them, and
both say the set applies to a *changed contract* — a reworded description —
not only to an added or renamed skill.
skills-manifest.json regenerated for the touched route file.
* docs(claude): point the routing-surface rule at routes/, not the moved stubs
Item 3 of "Skill catalog maintenance" still sent readers to
`references/workflow-catalog.md` for a workflow's input/output/trigger
contract and `references/route-briefs.md` for its interview entry. Both are
now "moved" stubs — the contract and the interview entry live together in
`references/routes/<workflow>.md`, one read per candidate route.
Same failure class the previous commit fixed at item 1: a maintenance rule
outliving the layout it describes. Swept the tree for other pointers at the
two stubs; there are none, so this closes it rather than fixing one instance.
* docs(send-to-guide): enhance turns are free; render is the paid step
The shipped pricing model is import + enhance turns free, only the final
render charged (a monthly free-render credit, then per-minute). The guide
labeled enhance as 'the paid step', which misstates the model to the
authoring agent. Move the paid label to Render.
* docs(send-to-guide): state the tiered render billing contract + pin it in the guide test
Address review: the pricing line must teach Claude the real tiered contract,
not a single universal free render. Per heygen-server usage_limits.py: FREE
accounts get 3 renders/month (then blocked, not billed); paid plans are charged
20 credits per rendered minute at completion. Enhance turns are free.
Also pin the invariant in sendToGuideContract.test.ts: assert Enhance=free /
Render=paid + the tiered figures, and a negative assertion blocking the retired
'Enhance ... paid step' wording from returning.
CLI and Studio feedback were emitted as `survey sent` with `$survey_*`
properties, so every rating was ingested as a PostHog survey response even
though no survey definition, targeting, or popover backs them.
Emit `cli_render_feedback` and `studio_feedback` with plain `rating` /
`comment` properties instead. Same fields, same call sites, same opt-out.
The Claude Design Send-to guide rendered at its URL but was an orphan — absent from the
docs nav and llms.txt, so it never surfaced as a fetchable search RESULT (only as body
text in another page's excerpt, which Claude Design's web_fetch rejects). Add it to the
Guides nav (→ llms.txt index) next to claude-design, and give it frontmatter title +
description for a clean entry. This makes the full guide discoverable + fetchable via
search, the reliable path since a URL named only in a tool description is not fetchable.
* docs(guides): resolve the fidelity contradiction (preserve substance, adapt form)
The guide called the rebuild 'lossy by nature' while the checklist demanded 'content
match the brief exactly', with no rule for what to preserve vs adapt. On a live import
CD kept fonts/palette/hero but genericized the source's real figures (2.4M signals/sec,
+240% spike) into vague phrases. Resolve around one principle: substance (real copy,
exact palette/fonts, distinctive figures/data, product names, signature visuals) is
preserved verbatim; only the form (static page to timed multi-scene motion) adapts.
* test(guides): pin the Send-to fidelity contract against silent regression
Address review on #2620: the resolved 'preserve substance, adapt form' instruction is
load-bearing LLM-facing prompt text, but validate-docs only proves syntax. Add a semantic
pin (mirroring packages/cli figma skillContent.test.ts) asserting the three positive
concepts are present and the two retired contradictory phrases ('lossy by nature',
'content match the brief exactly') cannot silently return.
* style(guides): oxfmt the Send-to fidelity-contract test
Wrap the readFileSync call to oxfmt form (printWidth 100); unblocks required Format + its
preflight/preview-regression cascade on #2620.
* docs(guides): redirect Send-to imports to the Send-to guide
Claude Design's only doc-discovery tool is web search, which ranks this Template-First
(Download-ZIP) guide first; the Send-to guide is not indexed, so Send-to imports get
authored against the wrong flow. A body link here lets CD's fetch of this page unlock a
fetch of the correct guide (its URL now appears in a prior fetch result).
* docs(guides): add Send-to redirect note to the Claude Design landing page
The /guides/claude-design landing page (claude-design.mdx) is the indexed nav page and
points only at the Download-ZIP instruction file; a Send-to author landing here got no
pointer to the Send-to guide. Mirror the redirect from claude-design-hyperframes.md.
* docs(media): document automatic proxying for hostile codecs
Describes the shipped behavior: which input codecs render, that live preview
auto-proxies what the browser cannot decode, where the cache lives, and how to
turn it off. Carries the skills notes and the hardening design documents.
* docs(media): align proxy guidance with runtime
* docs(skills): make the core set the default install on every surface
A field test showed an agent with a real 'make videos' intent installing
all 19 skills: at install time, every surface it could read pointed at the
full set, while the core-eager / workflow-on-demand design only exists
inside hyperframes/SKILL.md - unreadable until after the install decision.
Two traps made full-install the documented default:
- The README Quick Start used 'skills add --yes': skills.sh force-detects
agent environments into non-interactive mode, and a non-interactive run
without --skill installs all 19. Dropping --yes fixes the human path
(the picker opens with nothing pre-selected), but not the agent path.
- marketplace.json listed the full 'hyperframes' bundle first, under the
name an agent installing 'hyperframes' matches; core-skills sat second.
Changes, each behavior verified by an isolated run:
- README Quick Start drops --yes (humans get the picker; verified via a
pty capture that nothing is pre-selected) and points agents and
non-interactive runs at 'npx hyperframes skills update', which from a
clean HOME installs exactly the 8 core skills, refreshes stale ones and
prunes unpublished ones on an existing machine, and is idempotent.
- CLAUDE.md and the docs install guide lead with the same one-liner;
--all is reworded to explicit-request-only at every surface.
- marketplace.json puts core-skills first and both descriptions steer the
default choice; the full entry keeps auto-discovery (no allowlist),
per the skillsManifest core-pin test (56/56 pass).
* docs(skills): close the same install trap in AGENTS.md
Review follow-up on the core-default change: AGENTS.md still carried a
bare 'npx skills add heygen-com/hyperframes' - no --full-depth, and the
same non-interactive-installs-everything trap the README fix closed.
AGENTS.md is the first file Codex/Cursor-family agents read for repo
intent, so it leaked the full-set default to exactly the readers the
core-default policy targets. It now leads with the same core-set
one-liner and policy line as CLAUDE.md.
* docs(guides): add Claude Design → Send to HyperFrames single-file import guide
Self-contained authoring guide for the 'Send to HyperFrames' MCP import path
(distinct from the download-ZIP flow): single self-contained HTML wire format,
the composition contract the importer validates, inline-brand-assets fidelity
rules (base64 data: URIs), no bundled/splash artifacts, keep-the-original-as-
reference, a complete worked skeleton, the animation-pattern catalog, and
determinism rules. Reviewed for technical accuracy against a known-good
imported+rendered composition.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(send-to guide): assets must be resolvable (inline OR fetchable URL), not inline-only
Large media can exceed the import size cap, so "inline everything" is wrong for it,
and the import tool description now states "resolvable refs." Align the guide: inline
data: URIs preferred (fonts/images/logos — the only fully self-contained form), a
publicly-fetchable absolute URL allowed for large media, and explicitly forbid relative
paths / local-file variables / expiring-or-private hosts (the media-expiry trap).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat(studio,cli): per-frame board comments, self-refreshing storyboard, status-aware preview landing
Per-frame comment boxes on the storyboard board batch into
.hyperframes/frame-comments.json (a resubmit wins per frame; unconsumed
comments on other frames are kept). Submitted-but-unconsumed comments
stay visible — a toolbar banner plus a per-tile echo — until the agent
consumes the file; the banner also says what to do next (reply anything
in the agent chat).
The board keeps itself current: GET /projects/:id/signature exposes the
watcher-cached project signature, the storyboard payload carries the
signature it was derived from, and the view polls at 2s (hidden tabs
skipped, re-checked on visibility), refetching in place with no loading
flash. Posters bake the signature into their URL so tiles fill in as
sketches land and a poster that failed mid-write retries on the next
version; the empty state upgrades itself when STORYBOARD.md appears,
and its handoff prompt now points the agent at the review loop and uses
the parser's real status vocabulary (outline, not planned).
preview lands the browser on the storyboard view while the board is the
review surface — any frame built, or pure planning (srcs declared, none
on disk yet) — and on the timeline once the video is assembled.
* feat(skills): the review loop — plan, sketch, build as one shared process
hyperframes-core/references/review-loop.md is the single source for the
three-pass collaborative review: the plan proposed on a live board
(§ 1), wireframe sketches marked built with one layout question (§ 2 —
real words on plain blocks, run no CLI; a confirmed board is itself a
valid deliverable when the user asked for a storyboard, not a video),
the build dressing confirmed layouts (§ 3, worker or inline), and the
final look (§ 4). Autonomous runs skip every gate and keep one question
before render.
The three narrative workflows' Steps 3/4/6 collapse to references plus
their sketch stand-ins (captured-asset blocks for product-launch-video,
plain code panels for pr-to-video); the confirmed-sketch handoff stays
in each frame-worker prompt. general-video plans on a board for
multi-scene narrative pieces in collaborative mode — its sketch pass is
layout-before-animation with the user watching. The router treats
"I want a storyboard" as a process request rather than a route, and
closes exploratory intake by recommending a route plus how the run will
review.
The supporting contracts land next door: the comments channel (silent
submit, one reply picks it up, check the file before the words) in
brief-contract § 1; the sidecar schema and the built status rung in
storyboard-format; the mode question asked first and alone in the three
workflows' Step 0.
* feat(media-use): user memory — remembered preferences and frozen recipes
Two tiers of memory on media-use's existing two-tier storage split.
Preferences (lightweight): confirmed brief answers — destination, aspect,
language, mode, voice, style preset — recorded to the project's
.media/preferences.json (committed, the team inherits it) and promoted
to the personal ~/.media/preferences.json once the same value is
confirmed in two different projects (a sightings ledger accumulates the
cross-project evidence user-side, since project files can't see each
other). prefs.mjs get/record; merge reads project-over-user; a changed
value restarts its provenance.
Recipes (heavyweight): one approved run frozen as a named, versioned
bundle — frame.md, the storyboard skeleton (structure kept: durations,
transitions, srcs, Video direction; statuses reset to outline; content
blanked to per-frame fill-ins naming the beat's role), and the confirmed
brief values. Named folders, not content hashes: re-freezing bumps
version and archives <name>@v<N>; a freeze is already confirmed, so it
promotes to the user tier immediately. recipe.mjs freeze/list/use, plus
resolve --type recipe --entity <name> delegating like grade/lut.
16 new node --test cases; the media-use lib suite is 168/168.
* feat(skills): wire user memory into the brief and the review loop
brief-contract § 2 gains Remembered defaults: read the merged
preferences before Round 2 and let a remembered value become the
recommended option with a receipt naming its source project. Memory
changes the default, never the question — every ask-marked field still
gets asked, and what the request says this time beats what was picked
last time. Record only what the user actually confirmed (a defaulted
voice nobody chose is not an answer; a "go" that accepts the
recommended defaults is). The first record announces itself once;
after that the receipts carry the reminder. In autonomous mode a
remembered value becomes the decided value, receipt included.
The three narrative workflows read the remembered defaults before
Round 2, record the confirmed answers at the Step 0 gate, record the
chosen preset at the Step 2 gate (pr-to-video excepted — its preset is
fixed), and fall back to the remembered voice when the request names
none. general-video's discovery reads the same defaults.
Recipes wire in at both ends: Step 0 checks for a matching recipe
before the mode question — one question, plural-aware, and adopting
one fills the brief, skips the design step, and drafts the storyboard
from the frozen skeleton while every review gate still runs. The
review loop's final look (§ 4) offers the freeze once after approval,
and the confirmation teaches the recall phrase — the name is something
the system reminds the user of, never something they must remember.
The router recognizes a named recipe or "like last time" as a route.
* docs(skills): the sketch pass names check, not the deprecated validate
* feat(skills): intent-layer references — process, route briefs, capability menu, BRIEF.md format
* feat(media-use): brief skeleton as the recipe's fourth artifact; flow/storyboard preference keys
* feat(skills): the intent layer conducts every brief — workflows execute BRIEF.md
* feat(skills): retire the mode preference key; sync catalog surfaces for intent layer
* refactor(skills): dedupe router vs intent-layer guidance — one owner per rule
* feat(skills): the design ask — own spec, pick by eye from showcases, or defer
* docs(skills): the design ask says the honest line on capture routes
* feat(skills): product-launch-video absorbs website-to-video as the tour angle
* refactor(skills): keep product-launch-video pristine — a tour is brief intent, not a pipeline branch
* feat(skills): production loop + genre lenses; general-video goes freeform (route yours, laws hold)
* refactor(skills): /hyperframes is the front door - route tables and scope lists leave the workflows
* docs(skills): review-loop pass across skill catalog
* fix(cli): pass project dir to openStudioBrowser in background-server path
* feat(skills): add pitch-round reference - verbalized sampling concept gate
* feat(skills): wire pitch round into intent layer - completeness triage + route eligibility
* feat(skills): editorial capability recommendations, handoff disciplines, menu-probe split
* feat(skills): pitches carry their machinery; source-only-formed requests pitch the telling
* feat(skills): companion goes director - ceiling treatment plus blueprint/rule citation discipline
* fix(scripts): sandbox npx-leak guard - private npm global prefix keeps npx on the branch CLI
* chore(skills): resync manifest hash after formatter pass reflowed general-video tables
* fix(skills): recipe freeze reads workflow from BRIEF.md; style_preset records require workflow scope
Two holes found by a live companion-run freeze: the agent-supplied --workflow
contradicted the run's actual workflow (recipe.json said faceless-explainer,
brief-skeleton said general-video), and the style_preset lookup missed because
the preference had been recorded under the bare key.
- freezeRecipe resolves the workflow from BRIEF.md frontmatter; the flag is a
fallback for briefless projects and a contradicting flag is ignored (noted).
- recordPreference refuses a bare style_preset — the scoped key is the only
writable shape; freeze tolerates legacy bare records via read fallback.
- review-loop § 4 / media-use SKILL / brief-format wording follow the machinery.
Add a `core-skills` entry to .claude-plugin/marketplace.json declaring
the core skill set (the /hyperframes router, the hyperframes-* domain
skills, and media-use). The upstream vercel-labs/skills CLI reads that
entry's `skills` array for its interactive picker: the core set renders
under a "Core Skills" group and everything else falls into "Other", so
a human running `npx skills add heygen-com/hyperframes --full-depth`
can tell the always-needed core set apart from the on-demand creation
workflows — mirroring the core/on-demand tiers `hyperframes skills
update` already enforces (isCoreSkill in skillsManifest.ts).
The array deliberately lives on a separate marketplace entry, NOT on
plugin.json or the `hyperframes` entry: Claude Code treats a manifest
`skills` array as that plugin's skill allowlist (verified against
claude CLI), so attaching it to the full plugin would narrow it from
all skills to the core 8. As a side effect the new entry is itself a
coherent Claude Code plugin — `core-skills@hyperframes` installs just
the core set — while `hyperframes@hyperframes` keeps auto-discovering
everything.
A new pin test keeps the marketplace list in lockstep with isCoreSkill
and the skills/ tree (alongside the existing FALLBACK_CORE_SKILLS pin),
and asserts the full plugin carries no allowlist. Agent installs are
unaffected — the upstream CLI detects agent environments and installs
non-interactively, and the hyperframes CLI always passes explicit
--skill flags.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* docs(skills): add cloud render + variables to CLI skill, media-use generative use cases
The hyperframes-cli skill only documented self-managed AWS Lambda rendering; the
zero-infra HeyGen-hosted `cloud render` path (a real, shipped command with its
own docs page) was absent from every skill, so agents never surfaced it.
- hyperframes-cli: add `cloud` to the frontmatter verb list + entry point; new
Cloud and Variables sections; new references/cloud.md distilled from
docs/deploy/cloud.mdx; routing + workflow rows.
- media-use: add image-to-video recipe (heygen video create type:image) plus a
table of other HeyGen generative use cases (photo avatar, digital twin, video
translation, lipsync, voice design) in references/operations.md; surface them
in the SKILL coverage/provider rows.
- Sync README + docs/guides/skills.mdx catalog entries to mention cloud render.
* docs(media-use): point HeyGen generative use cases at --request-schema
Verified against the installed heygen CLI (v0.3.0): no capability gap that would
need the raw API. Replace hardcoded body-field lists with a pointer to
`heygen video create --request-schema` (self-documenting, can't rot), correct
the image-to-video motion_prompt/expressiveness support, and add the
cinematic_avatar, ai-clipping, and photo-avatar creation paths.
* fix(skills): correct media-use manifest hash (clean-tree regen)
The prior regen was polluted by the gitignored skills/media-use/eval-report.html
(a suppressed mv error left it present), so the committed media-use hash didn't
match a clean checkout. Regenerate with no untracked artifacts present.
Two real conflicts:
- docs/guides/prompting.mdx: modify/delete. This branch already deleted
it (383dd3568, replaced by the docs/prompting/* multi-page structure);
main separately fixed one line in the old file (cf7c1d760: lint+validate
-> the new consolidated `check` command). Kept the deletion — a
redirect to /prompting/overview already exists in docs.json — and
ported the same check-command fix forward into the two new-structure
pages that still had the stale lint+validate phrasing
(examples.mdx, rules-and-anti-patterns.mdx), so main's fix isn't lost.
- skills-manifest.json: auto-generated, regenerated fresh via
packages/cli/scripts/gen-skills-manifest.ts rather than hand-resolving
the JSON conflict markers.
Everything else auto-merged cleanly (no conflicts) — this pulls in
main's independent work since the branch diverged (media-use v2, the
check command consolidation, studio timeline updates, etc).
Co-Authored-By: Claude Opus <noreply@anthropic.com>
Scaffolded projects' npm run check now invokes the single check command
instead of chaining lint, validate, and inspect (three Chrome boots
become one). The CLI skill, its correctness reference, the entry skill's
capability map, README/docs catalog rows, the Mintlify CLI page (new
check section, deprecation banner on inspect), template CLAUDE/AGENTS
(byte-identical), root CLAUDE/AGENTS, and every creation-workflow skill
that taught the old sequence all point at check. snapshot keeps its
standalone sections; validate/inspect stay documented as deprecated
aliases with their check equivalents.
Splits guides/prompting into a Prompt Guide nav group (overview + Fundamentals
+ Making it look good, 11 pages) with a redirect from the old URL. Applies
research-validated upgrades: beat content formula, before/after prompt rewrites
with engine rationale, single-variable iteration moves, absolute-target
calibration, camera/depth/pacing vocabulary, prerequisites gate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The old setup section was one long token-minting flow with the MCP
connector as an afterthought — but motion/shaders/storyboards need
only the connector (no token at all), and even brand tokens are
easier via MCP on any non-Enterprise plan. A reader wanting only
motion had to wade past REST scope tables meant for a different path.
Restructured into a decision table (what you want → which credential)
followed by two equal, independent steps. Step A's scope list now
states the 3 boxes to check on a normal (non-Enterprise) account
up front, instead of a generic 4-scope table the reader has to
interpret themselves. Step B now states the MCP connector's actual
capability (variable reads work on any plan, rate-limited by tier —
6 calls/month on Starter) instead of "no scopes to configure," which
undersold what it can do.
Co-Authored-By: Claude Opus <noreply@anthropic.com>
Miga's re-review caught it: the new RATE_LIMITED row (client auto-
retries with backoff) landed alongside the old pre-retry row ("wait a
minute and retry; chunk batch renders"), leaving two rows for the same
code — one accurate, one stale. Keep only the current one.
Co-Authored-By: Claude Opus <noreply@anthropic.com>
Addresses @miguel-heygen's review on #2112:
- BLOCKER: docs/guides/figma.mdx now matches the shipped code/skill —
adds the Library content: Read-only scope row (+ corrects the
'falls back, expected' line that was false without it), and the
troubleshooting table now says bad PATs surface as 403 Invalid token
(not 401), names the scope in FORBIDDEN, and documents RATE_LIMITED retry.
- nit: the batch summary line no longer claims '1 figma request' when every
node was a cache hit — says 'all reused from cache — no figma request'.
- nit: index.md regen moved to a finally, so a mid-batch RENDER_FAILED
leaves index.md consistent with the nodes that did freeze.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(media-use): color grading — grade/lut resolve, smart-grade, grade-compare CLI
Add color grading to media-use as first-class resolve types plus a faithful
comparison command. All local, offline, deterministic — no model, no GPU.
- resolve -t grade / -t lut: produce a data-color-grading block (or a frozen
.cube). Look cascade: core preset (no file) -> bundled .cube library ->
parametric buildCube. Emitted .cube is Rec.709 and validated against core's
colorLuts constraints (LUT_3D_SIZE <= 64) before it is frozen.
- smart grade (grade --for <media>): ffmpeg signalstats -> adjust suggestion
(exposure / contrast / white balance), surfaced with the measured evidence on
stderr as a starting point; never auto-applied.
- hyperframes grade-compare: renders N candidate grades onto a reference frame
through the real runtime shader into one labeled comparison PNG, so an agent
picks a look without opening Studio. Prepends an "original" baseline cell by
default (--no-baseline to omit). Shares the headless-capture pipeline with
snapshot via capture/captureCompositionFrame.
- media-use SKILL: proactive "media opportunity pass" guidance (grounded
signal -> offer, ask once, surface don't mutate).
Verified: media-use 116/116, grade-compare 7/7, snapshot 9/9, lint + format
clean, full build green, comparison renders end to end.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* test(cli): narrow grade-compare baseline assertion off unknown-typed grading
Assert the whole cell via toEqual instead of reaching into .grading.preset /
.grading.lut on the unknown-typed field, keeping the test typecheck-clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* feat(media-use): agent-authored LUTs via --params + validate --from cube; never-read-.cube guardrail
- resolve -t lut / -t grade --params '<json>': build a parametric .cube from
explicit params (bypassing the intent cascade), validate, and freeze in one
step. --intent becomes the optional description. Lets an agent commit a look
it computed itself.
- --from <file.cube> now validates the ingested LUT for lut/grade types and
rejects an invalid/oversized cube (no partial write) — the escape hatch for a
LUT the agent generated with its own code.
- SKILL.md: hard rule to never read a .cube body into context (~size^3 lines,
zero legible signal) — inspect via grade-compare (see it) or cube-validate
(ok/size), read the manifest description for meaning; plus both authoring
paths and the parametric-vs-film-stock ceiling note.
Verified: media-use 116/116, lint + format clean; smokes — --params builds a
valid frozen cube, grade --params returns a lut block, bad JSON and an oversized
--from cube are both rejected with no stray file.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* fix(cli): grade-compare validates referenced LUTs, warns on no-op cells, caps candidates
Bug-bash follow-ups — grade-compare silently accepted bad input:
- Validate LUT *content*, not just existence: each referenced .cube is parsed
with core's parseCubeLut (now exported from @hyperframes/core) and rejected
with a per-cell error ("LUT for \"<label>\" is not a valid .cube: ..."). A
file that exists but isn't a valid cube no longer renders a silent no-op cell.
- Warn on inactive cells: a grading that normalizes to inactive (e.g. a
malformed {lut:12345}) emits a stderr warning naming the cell; the
auto-prepended "original" baseline is intentionally inactive and stays silent.
stdout remains valid JSON.
- Cap candidates at 16 (excluding baseline): over-cap input renders the first N
and reports {truncated:true, total:M} on stdout + a stderr note — no silent
drop, no unbounded giant sheet.
Verified: grade-compare 10/10; non-cube LUT → clear error; {lut:12345} → warning
+ ok; 20 cells → cells=17 truncated total=20; valid runs unchanged. Lint/format
clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* feat(cli): general `hyperframes compare` visual-variant primitive
Generalize grade-compare's "render N variants → one labeled sheet → the agent
looks and picks" loop into a standalone command that works on ANY variation
(font, layout, motion, grade, whole compositions) — the tool never needs to
know what differs.
- `hyperframes compare <path...> [--at <sec>] [--labels a,b,c] [--out] [--cols]
[--json]`: renders each agent-authored composition variant through the real
runtime (captureCompositionFrame) and stitches one labeled comparison sheet +
JSON ({ok, sheet, rendered, variants, truncated?/total?}). 2+ paths required;
caps at 16 with loud truncation. It presents, it does not judge — choosing is
the caller's job.
- Factored the shared "render a labeled set → contact sheet" path so compare,
grade-compare, and snapshot all sit on it (no duplication). grade-compare is
now the first color-specific specialization of this primitive.
- New pathArgs util + contactSheet test; hyperframes-cli SKILL documents compare
as the agent's "see your own renders and choose" primitive.
Verified: 26/26 across compare + grade-compare + snapshot + contactSheet (no
regressions); compare renders 3 variants into one visibly-distinct labeled
sheet; 2+-path error path clean; lint/format clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* fix(ci): green the skills CI — skip ffmpeg tests when absent, oxfmt markdown
The "Test: skills" CI job runs bare `node --test` with no ffmpeg on PATH (by
design — skills tests are meant to be node-builtin-only). The grade-analyzer +
smart-grade tests shell to ffmpeg and were failing there with ENOENT. Guard
them to skip when ffmpeg isn't on PATH; they still run locally / where it is.
Also oxfmt README.md + hyperframes/media-use SKILL.md (the whole-repo
`oxfmt --check .` Format job caught markdown left unformatted by the rebase
conflict resolution).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* fix(ci): skip core-conformance test when tsx is unavailable
The "Test: skills" CI job installs no deps, so the normalizeHfColorGrading
conformance test (which imports core's TS via `node --import tsx`) failed there.
Guard it to skip when tsx can't resolve; runs locally / in the deps-installed
Test job. Completes the skills-CI greening (the ffmpeg guards handled the rest).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* fix(cli): escape grade-compare src double-quotes (CodeQL XSS) + Windows-safe compare test
- grade-compare built `<img src="...">` (double-quoted) with the single-quote
escaper, leaving `"` unescaped — a `"` in the frame path could break out
(CodeQL: incomplete HTML attribute sanitization). Use escapeXml for src.
- compare label test hard-coded POSIX paths that can't match on Windows; assert
the derived labels (the subject); path resolution is covered elsewhere.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* refactor(media-use): generate LUT library from params (drop committed .cube files)
The 3 bundled .cube files were 733 lines each (2,199 total) and were themselves
buildCube output — pure repo bloat. Replace with compact per-look params in
luts/index.json, generated on resolve; add an optional `url` for future scanned
LUTs to be CDN-hosted + downloaded on demand (freezeUrl) instead of committed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* feat(media-use): serve library LUTs from CDN on-demand (static.heygen.ai/luts), params fallback
Looks now carry a CDN `url` (hosted at s3://heygen-public/luts → static.heygen.ai/luts/<id>.cube);
resolve downloads + validates + freezes on demand, like bgm/image. `params` stays
as the deterministic offline fallback (--local-only, or if the download fails), so
resolution is never blocked on the network. Provider prefers url, falls back to params.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
* fix(media-use): address #2041 review — atomic LUT writes, compare telemetry, follow-ups
- Atomic .cube writes: library provider (url + params) and the parametric
generator now write to a .tmp path, validate, then rename, so a crash can
never orphan an invalid .cube at the final path (was validate-after-write).
- track("media_use_resolve") now emits provenance.via (url/params-fallback/params).
- grade-compare + compare: --timeout flag (was hardcoded 5000) and a
media_use_compare event (cells, truncated, total, render_ready_timed_out);
openSettledCompositionPage now surfaces the render-ready timeout.
- compare staging skips node_modules/.git; --for gets an upfront existence check.
- Rec.709 luma comment; HYPERFRAMES_ANALYZE_TIMEOUT_MS override; measured note
uses basename; LUT s3 hosting moved from index.json into luts/README.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5k87mPZ4d6yiFwcWSb8Vv
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(cli): fix render examples that pass a file as the project dir
The render command's positional argument is the project directory (default
"."), resolved via resolveProjectOrThrow; a specific composition file is
passed with -c/--composition. Several docs showed `hyperframes render
index.html` / `render ./my-composition.html`, which treats the HTML file as
the project dir and fails with "Not a directory". Correct the guide and the
cli README to render the project's index.html directly (or point at a file
with -c).
* docs: fix render index.html example in the Open Design guide too (R1)
R1 flagged that open-design-hyperframes.md carried the identical
`npx hyperframes render index.html` example this PR fixes in the Claude
guide — same failure vector ("Not a directory" for a file positional).
Corrected to `npx hyperframes render` run from the project directory.
Add Modal as a third official deployment template alongside Vercel and
Cloudflare: comparison-table row, a Modal tab (deploy commands, what-you-get,
performance, pricing, async spawned-function note), architecture/pre-baking
updates, swap-the-composition steps, and a source card. Update the cloud.mdx
cross-reference to include Modal.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cli,skills): install workflow skills on demand instead of re-pulling the full set
Users report every init re-pulls all 21 skills into ~/.agents/skills
whenever anything is stale or missing - heavy, noisy, and it re-expands
deliberate partial installs.
Split the set into two tiers:
- core: the /hyperframes router + hyperframes-* domain skills +
media-use, which every workflow references structurally. init and
bare 'skills update' keep these (plus anything already installed)
fresh, and never expand the install.
- on demand: the end-user workflow skills (and figma). They install at
trigger time via 'skills update <name...>' - positional names are
the only way update expands an install: one targeted
'skills add --skill <name>' covering only stale/missing targets, a
fast no-op when current, presence-verified after install, exit 1 on
unknown names, and a presence-only degrade when GitHub is
unreachable.
The /hyperframes router now runs 'skills update <workflow>' after
routing and before reading the workflow skill, so a routed workflow is
guaranteed present even on a machine that only has the core set. Each
on-demand skill also opens with the same self-maintenance step (run
'npx hyperframes skills update <name>' silently), so a workflow
triggered directly - without the router - still refreshes itself and
restores any missing core skill before relying on it.
When the manifest is unreachable (offline / rate-limited) the engine
degrades honestly instead of claiming success: named runs presence-check
the request plus a pinned fallback core list (unit-pinned to skills/)
and blind-install whatever is absent; a bare strict update fails loudly
so the 'check || update' chain can't pass while everything stays stale;
init reports the skipped freshness check. --json emits structured
errors on failure paths.
skills check still lists every skill, but exits non-zero only for
stale installed skills, an incomplete core set, or removed leftovers -
workflow skills not yet installed are reported as available on demand.
Bare 'hyperframes skills' (and 'skills add --all') remain the explicit
full-set installs.
Verified end-to-end with a sandboxed $HOME: fresh init installs the 9
core skills only; 'skills update slideshow' adds exactly that skill
(no-op on re-run, exit 1 on unknown names); bare update refreshes
without expanding; a live Claude Code run routed PR-to-video, executed
the router's update step, and the workflow skill appeared before use;
and a second live run triggered an installed workflow directly, whose
opening maintenance step restored a deliberately removed core skill.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(skills): clarify update-engine contracts + document lazy-install model
- skills.ts: note the UpdateSkillsResult.unknown strict-mode contract,
verifyInstalled's non-strict (warn-not-throw) intent, and that a
partial install stays "refreshed but never expanded" (review nits).
- docs/guides/skills.mdx: add a "Keeping skills current" section covering
the core-eager / workflow-on-demand model and the skills check|update
commands, per the repo's catalog-maintenance rule.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: kiritowoo <295860553+kiritowoo@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Miao Yang <miao.yang@heygen.com>
* feat(media-use): resolve official brand logos via a four-tier cascade
Third-party brand logos (the meeting's 'credibility signals lost' gap)
had no acquisition path: capture only grabs the product's own site
assets, and HeyGen asset search returns generic look-alike icons for
brand queries (0/3 in testing — an X-in-a-circle for LinkedIn). Workers
could only fake a mark or drop it.
New resolve type 'logo', four tiers verified by a 54-brand stress test
(100% cascade hit across dev tools / big tech / non-tech / CN brands):
- svgl — official full-color vector SVGs + wordmark variants (40/54
first-hits); search is substring-based, so entities pass through
alias normalization (nextjs → 'next.js', aws → 'amazon web services')
- simple-icons (pinned CDN build) — official monochrome glyphs; catches
the long tail (nike, visa, toyota, wechat, bytedance)
- github org avatar — known-org map only; a brand name is not a GitHub
login, guessing risks same-named personal accounts
- domain favicon (DuckDuckGo ip3) — small-raster last resort; sub-500B
responses are DDG's placeholder and rejected; frozen with a low_res
provenance flag (chip-size use only)
logo joins the icon/image equivalence group (typesMatch) and the
images/ subdir, so entity cache hits interop with figma-imported marks.
A total miss falls through resolve's normal failure path — no special
casing. HeyGen search stays the icon provider; it is deliberately
absent from the logo cascade.
Docs: media-use gap/types/providers tables + example; the five
workflow banners now cover logos (catalog claim kept for media, 'from
their official sources' added for logos); product-launch story-design
and motion-graphics logo-reveal point at the new type; catalog
surfaces (CLAUDE.md / README / docs) updated in lockstep.
Verified: 19 unit tests + coverage row green; live smoke across all
four tiers (linkedin→svgl, nike→simple-icons, heygen→github.avatar,
amazon→favicon) plus a fabricated brand exiting 1 on the default miss
path. oxlint + oxfmt clean.
* test(media-use): sanction the four logo providers in the registry allowlist
svgl / simple-icons / github.avatar / favicon.ddg join the sanctioned
list — the logo cascade added in the previous commit. Full lib suite
95/95 green.
* test(media-use): gate the logo cascade behavior in CI + single-fetch favicon tier
Review follow-ups (miga-heygen, jrusso1020 on #2061):
- Eight mocked-network tests pin what the manual 54-brand stress test
only asserted: descriptor shape, alias retry (svgl non-array payload
→ next query, simple-icons 404 → next slug), network-error → null
fallthrough, the sub-500B placeholder rejection, github's
no-guessing (zero fetches for unmapped entities), and the real
cascade order landing tier by tier under a mocked network.
- faviconSearch now hands its verified bytes over as a local file, so
the freeze step copies instead of re-downloading — one round-trip,
and the size check is authoritative over what gets frozen.
- The header's hit counts are labeled as a stress-test snapshot, not a
live invariant.
Full lib suite 103/103; live smoke re-verified (amazon → favicon.ddg,
frozen .ico).
* fix(media-use): codex gate misfires as 'not logged in' when piped
codexUnavailableReason() gated generation on parsing `codex login status`
stdout, but that command prints 'Logged in using ChatGPT' to stderr and
exits 0 — so the piped stdout media-use captures (execFileSync returns
stdout only on success) was empty, and the gate falsely reported 'not
logged in'. Every headless / CI / agent run was blocked from codex image
gen even when fully authed.
Gate on the durable credentials file ($CODEX_HOME/auth.json) instead of
the TTY/stderr-only human text. Token validity is still proven by the
exec, which fails cleanly on a stale login. The stdout `features list`
capability check is unchanged.
Verified: reproduced the false 'not logged in' block, then after the fix
generated end-to-end via `resolve -t image --provider codex` (valid
1254x1254 PNG, source=generated, provider=codex.image_gen).
* fix(media-use): bug-bash fixes — id race, provider/reuse/adopt guards
From the bug-bash against main:
- MU-23 (HIGH): concurrent resolves raced on nextId (read-max-then-append,
non-atomic), so parallel agents got duplicate ids and clobbered each
other's files. Add allocateId(): a coarse per-project lock (.media/.lock,
15s stale-steal) around id allocation that scans the manifest AND the
type dir for reserved ids, then O_EXCL-creates a placeholder file so the
slow download between allocate and append can't collide. 5 parallel
resolves now yield 5 distinct ids + files.
- X4: --reuse imported across a type mismatch (bgm asset under images/).
Apply typesMatch on the --reuse path; reject mismatches (icon<->image
still interchangeable).
- X5: --provider silently overrode --local-only and made a network call.
--local-only is now a hard guard: network providers are skipped even
under a forced provider; the miss message explains the conflict.
- BUG-2: --provider ignored the exact-cache floor and could hand back an
asset from a different provider. A forced --provider now bypasses all
reuse rungs (regenerate with THIS provider); the unforced floor is intact.
- MU-26/X6: 0-byte assets accepted. --adopt skips 0-byte files (loud); ingest
refuses a 0-byte local file (freezeUrl already rejects empty responses).
- BUG-4: unknown/unavailable --provider now errors with the available list
instead of a generic 'no provider could resolve' (typo != catalog miss).
- BUG-5: --reuse "" gave the wrong 'type and intent required' error; it now
routes to a clear empty-sha message.
- BUG-3: voice duration leaked an unrounded float into index.md; round all
durations to 0.1s centrally at record build (matches probe).
- Nits: whitespace-only --intent is rejected; nudge grammar (exists/exist).
Tests: allocateId reservation + registry local-only-wins added; full
media-use suite green. All fixes verified e2e.
* fix(cli): reject unknown flags instead of silently ignoring them
citty is permissive: an unrecognized flag was dropped, not rejected — so
`render . --out x` (the flag is --output/-o) silently ignored --out and
rendered to the default renders/<name>.mp4 path. A mistyped flag read as a
render/catalog miss.
Add assertKnownFlags(): validate every dash-prefixed token against the
command's declared args + aliases + the global set (help/version/json)
before the command runs, in the shared trackCommandFailures run-wrapper so
every leaf command is covered. Handles --flag=value, --no-<bool> negation,
camelCase<->kebab arg names, and combined shorts; stops at --; positionals
and flag values pass through.
Verified: `render . --out x` -> 'Error: Unknown flag: --out'; --output/-o/
--json/--help still accepted. Unit tests added.
* docs(skills): install with --full-depth so agents get current main
The documented `npx skills add heygen-com/hyperframes` fetched the
skills.sh registry blob, which lags GitHub main by hours — so users
following the docs got a stale skill (e.g. media-use v1: no --candidates,
voice stubbed). The CLI's own `hyperframes skills` command already forces
a full clone via --full-depth to bypass this; the docs didn't pass it.
Add --full-depth to every documented install command (README, CLAUDE.md,
docs/guides/skills.mdx) with a one-line note on the lag. Addresses the
user-facing half of the publish/registry lag (#2034).
* chore(media-use): collapse resolve.mjs import to satisfy oxfmt --check
* fix(cli): extract longFlagName to keep flag validator under complexity gate
Also regenerate skills-manifest.json (resolve.mjs formatting change re-hashed
the media-use skill). Fixes the Fallow audit + skills-manifest-in-sync CI gates.
* fix(skills): audit descriptions — trim routing prose, fix stale facts, add missing triggers
Descriptions are the always-loaded routing tier; this audit rebuilds them on
one principle: discriminate by input shape, not pipeline internals.
- Trim creation-workflow descriptions to positive trigger + nearest-neighbor
disambiguation + /hyperframes escape hatch; full routing prose already
lives in each skill body's route-confirm block and the router
- Codify the workflow-vs-domain split as ownership (owns the end-to-end
deliverable vs capability layer pulled in mid-flight) in /hyperframes,
and widen "make me a video" framing to deck / composition port
- Fix stale facts: embedded-captions identity count (desc 32, body 17 →
actual 36 = 10 classic + 26 themed), six→ten visual languages, retired
RVM/Standard wording in router details, figma shader transport
(MCP → MCP source / native export), keyframes "cursor demos" (no backing
content), hyperframes-media scripts/audio.mjs leak
- Register missing capabilities: motion-graphics maps category (was in
categories/ but absent from its own table, description, and router),
asset-fusion + news triggers, slideshow page-to-deck + presenter mode,
general-video editing, talking-head-recut 16:9/9:16/4:5 canvas,
cli feedback + lambda sites, product demos, mood-brief BGM generation
- website-to-video: relabel promo-shaped video types to keep the promo
boundary with /product-launch-video; drop headless-Chrome wording
- music-to-video: lyric timing via /hyperframes-media transcription or
user-supplied lyrics, placed on the beat grid
- Sync catalogs in lockstep (CLAUDE.md, AGENTS.md, README,
docs/guides/skills.mdx, CLI project templates): add music-to-video +
slideshow entries, complete the domain-skill lists, and extend the
catalog-maintenance rule to cover AGENTS.md and the templates
Validated with a 35-case description-only routing eval: 35/35 both before
and after the rewrite (including new maps / asset-fusion / news probes).
* fix(skills): post-media-v2 consistency — stale media ref, router figma wording, catalog rows
- music-to-video: lyric transcription now routes to /media-use (the
retired /hyperframes-media was still referenced)
- router capability map: figma row gains the shaders fact (MCP source /
native export), matching the SKILL.md source of truth
- media-use catalog rows (CLAUDE.md, README, docs/guides/skills.mdx):
add image models + captioning, aligning with the v2 description
- catalog rule #1: root AGENTS.md carries the workflow list only (it
has no domain-skill section) — rule wording now says so
Field feedback from a raw-API agent build (join-the-world-flow): the
catalog blurb's word 'animatics' encodes the PNG-slideshow architecture
the skill body explicitly forbids — an agent routing by the blurb
concludes the shipped behavior is frames-as-pictures. Reworded to
'reconstructed motion (frames read as states, not slides)' across all
catalog surfaces (skill frontmatter, CLAUDE.md, README, skills.mdx,
hyperframes router, figma guide).
Also codifies the stronger doctrine that build demonstrated as
storyboard rule 10: when every frame is the same product UI in
successive states, rebuild the app as live DOM (Phase-3 for stateful
parts, real pixels for static chrome — code what changes state, freeze
what doesn't) and perform frame deltas as interactions instead of
tweens. Spec §5.1 records the escalation + field origin.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>