* 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
* feat(cli): associate signed-in HeyGen account with telemetry
Sign-in telemetry currently attributes everything to the anonymous
install id, so the sign-in funnel can be counted but a completed sign-in
can't be tied to the account it produced. This associates the two.
- On a completed sign-in, emit a PostHog `$identify` alias whose
`$anon_distinct_id` is the install's anonymousId, so events recorded
before sign-in stitch to the same person, and tag `auth_login_completed`
with the account identity (the pre-plumbed `distinctId`).
- `/v3/users/me` exposes no opaque user_id, so the identity key is the
account email, falling back to username (single `identityKey` helper).
- Both no-op under the `telemetry disable` opt-out and only fire after
the user chooses to sign in.
Privacy disclosure updated in lockstep, since this is the first PII the
CLI attaches: the first-run telemetry notice and the telemetry section
of docs/packages/cli.mdx now state that signing in links your account
email to your usage.
Tests: identifyUser payload + no-op, completion attribution incl.
username fallback and no-identity-on-reject/empty. Verified end-to-end
against the built CLI: pre-auth events anonymous, $identify carries
$anon_distinct_id, completion carries the account email.
* docs(cli): disclose the username identity fallback
Review gating item: identityKey is `email ?? username`, but the
first-run notice and cli.mdx said only "email", so an emailless
account's username would reach PostHog undisclosed. `/v3/users/me`
treats email as optional (pickString), so the fallback is live code,
not dead — disclose it rather than assert an unverifiable email
guarantee. Both surfaces now say "email, or username if the account
has no email".
Also soften the identityKey comment: it implied username is "less
identifying", but HeyGen usernames are often email-shaped, so the note
now states username is a fallback, not a privacy win.
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>
Exhaustive audit of every MDX file in docs/ against skill references
and package source code. Every API signature, default value, flag,
and technical claim verified against ground truth.
* fix(sdk): moveElement survives GSAP animation per-axis via runtime delta translate
A committed moveElement wrote data-x/data-y but nothing rendered them:
hosts shimmed CSS translate, which GSAP folds into the cached transform
at first parse and then discards on the animated axis at every seek —
dragging an animated element kept only the un-animated axis.
Spike-proven on GSAP 3.15: a translate set AFTER GSAP's first parse is
never read, folded, or cleared across seeks and composes natively with
the animated transform. So:
- moveElement captures the pre-edit baseline once (data-hf-edit-base-x/y)
- the runtime (new core runtime/positionEdits.ts, applied at timeline
bind — after GSAP parse) renders translate = (data-x − base), a pure
delta that composes with GSAP tweens, tl.set positions, and CSS alike
- applyDraft now drives the drag preview through the same translate
channel (the --hf-studio-dx/dy vars had no consumer outside authored
Studio bridges), and commitPreview mirrors the committed move onto
the live element so it holds without an srcdoc reload
Acceptance: packages/engine/scripts/test-runtime-position-edits-browser.ts
(real Chrome + GSAP + runtime IIFE, no Studio shell) — X-animated,
Y-animated, and static elements hold both edited axes across the full
seek range. New subpath export @hyperframes/core/runtime/position-edits.
Known limitation (documented): a tween created lazily at runtime that
first-parses a marked element after apply folds the edit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sdk): harden position-edit rendering and the drag draft channel
Fixes six issues from adversarial review of the moveElement stack:
- Runtime: apply position edits at init as well as at timeline bind, so
committed moves render in compositions with no usable GSAP timeline
(CSS/WAAPI-animated or fully static) — previously the apply was
unreachable outside the boundDuration > 0 bind branch and the edit
silently vanished from reloads and renders.
- Runtime: guard bind-path re-apply against post-fold double-apply — if
the previously written translate was consumed externally (a lazily
created tween folding it into GSAP's cached transform), skip instead
of re-setting it on top ({force} escape hatch for editor commits).
- Adapter: stop writing the --hf-studio-dx/dy custom properties during
drags — compositions with the documented var-consuming drag-bridge
CSS moved by twice the pointer delta (var transform + new inline
translate). The inline translate is now the only draft channel;
deltas accumulate in adapter fields. Docs updated to match.
- Adapter: switching applyDraft to a new id reverts the abandoned
element's draft translate instead of leaving it displaced with no op.
- Adapter: cancelPreview restores the raw inline translate (removing it
when there was none), so a stylesheet-authored translate is never
promoted to a permanent inline style.
- Adapter: commitPreview reverts the draft and clears state when
dispatch throws, instead of leaving the element shifted by an
uncommitted draft.
Cleanups: reuse readCurrentTranslate from the core module (was a
verbatim copy), drop the dead __hfApplyPositionEdits window hook.
Browser acceptance test now also covers the GSAP-free composition path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(core): prime GSAP transform cache before position-edit apply; add fold-loss telemetry
Addresses PR #1875 review feedback (Rames, Miga):
- Prime the element's GSAP transform parse (gsap.getProperty) before the
first translate apply — positioned tl.set()s and tweens that first
RENDER after the apply now reuse the cache instead of folding the edit.
This closes the lazy-first-parse fold-loss for any page where GSAP is
loaded at apply time; the residual limitation is GSAP itself loading
after the apply. Proven by the extended browser acceptance test.
- Emit position_edit_fold_skipped analytics at the fold-guard skip site
so the residual degradation is observable instead of silent.
- Browser acceptance test: add a both-axis-animated element (the shape
that originated the per-axis loss) and a positioned tl.set() element,
asserted across the full seek range.
- Simplify the num() null guard (review nit).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(skills): reroute /figma by capability - REST/CLI for phases 1-3, MCP for 4-5 (M4)
Rewrites the skill from MCP-first to the spec 2 split: asset/tokens/
component route through the hyperframes figma CLI (FIGMA_TOKEN), motion/
shaders stay agent-driven over MCP (no REST equivalent). Adds two-
credential guidance, Starter rate-limit tactics (recursive:true, raw-
response cache, opt-in screenshots), the 7.1 binding flow (tokens before
components, one ask per unknown library, never value matching), and the
shader manual-export default. Catalog blurbs updated in lockstep.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(cli): register figma component subcommand
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(skills): add storyboard-to-animatic guidance to /figma
Field-tested against a real 26-scene storyboard section: the parsing
grammar (frame-sized nodes incl. loose rectangles = scenes, x-order =
time order, TEXT below the strip = director notes paired by x-overlap),
batched still export (chunk ~4 ids per render call - big frames timeout
past ~12), a note-verb -> transition vocabulary (EXPLOSION/SLIDE/MORPH/
CYCLE), and the stills-vs-component routing rule for within-scene motion
notes. Catalog blurbs updated in lockstep.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(skills): storyboard frames are keyframes, not slides
Field-tested against a second real storyboard section: frames sharing an
element (matched by name, else geometry similarity) define that element's
states through time - tween the element between states, crossfade only
when pixels genuinely differ, enter/exit unmatched children, tween frame
backgrounds as a color track. Stills demoted to fallback for frames that
don't decompose. Validated live: a 4-frame logo-rise reconstructed as one
element with four keyframes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(figma): self-explanatory first-run experience + mintlify guide
- NO_TOKEN/BAD_TOKEN errors now carry the full one-time setup (mint URL,
read-only scope checklist, persist hint) instead of a bare pointer
- figma subcommands print clean guidance on typed client errors, not a
stack trace (shared withFigmaErrors boundary)
- CLI help gains component subcommand, FIRST-TIME SETUP and WHAT TO
EXPECT blocks
- /figma skill: preflight the token before the first CLI call and walk
the user through setup up front; narrate landed-artifact + next action
at every step
- new docs/guides/figma.mdx (setup, per-phase walkthroughs, provenance,
troubleshooting table) wired into docs.json nav
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(figma): review fixes — missing withFigmaErrors imports, 401/403 semantics, docs accuracy
- tokens.ts/component.ts called withFigmaErrors without importing it
(tsup doesn't typecheck, so every invocation shipped as an immediate
ReferenceError); imports added, tsc --noEmit now clean
- error boundary widened to all Errors so bad-ref/bad-format input
errors print their message instead of a stack trace
- 401 no longer claims 'missing scopes' (figma signals that as 403);
new FORBIDDEN code maps non-variables 403 to scope/access guidance
- docs: asset/component refs require a node id (bare fileKey is
tokens-only), example snippet matches real output, FORBIDDEN row
- skill: preflight counts a project-.env token as configured (CLI
auto-loads it); BAD_TOKEN/FORBIDDEN guidance split
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(cli): present figma errors via standard errorBox
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(core): add figma motion easing mapping
* feat(core): translate figma motion doc to gsap timeline spec
* feat(core): emit paused GSAP timeline script from figma motion spec
* fix(core): restore type exports dropped from figma barrel in Task 8
* feat(skills): add /figma import skill + catalog wiring
Add the agent-facing /figma skill (asset + Figma Motion import via the
Figma MCP connector, built on @hyperframes/core/figma) and wire it into
the skill catalog across CLAUDE.md, README.md, docs/guides/skills.mdx,
and the hyperframes router's capability map. Bumps the skill count from
19 to 20 in CLAUDE.md and README.md.
* fix(core): use replaceAll for figma node-id dash-to-colon conversion
* style: format skills catalog tables
oxfmt-align the README and router SKILL.md tables after the /figma +
/hyperframes-keyframes merge left uneven column padding.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(cli): add missing cache fields to telemetry test fixture
ExtractionPhaseBreakdown gained cachePublishFailures/cacheGcEvictions/
cacheGcBytesFreed/cacheAgedPartialsCleared; the studioRenderTelemetry
test fixture was never updated, breaking Typecheck on main and every PR
based on it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Renames the motion-surfacing tool from `hyperframes keyframes` to `hyperframes motion`,
renames the implementation from keyframes*.ts to motion*.ts (keeping the keyframe data
model name where still accurate), and renames the shipped skill from
hyperframes-keyframes to hyperframes-motion. Expands the skill from a command
reference into a full motion-design workflow: reading motion, 3D angle verification,
layered GSAP motion, one-shot reference reproduction, diagnostic checks, and
eval-derived craft guidance.
The #1817 deploy added 15 pages but Mintlify only published changed files
incrementally; the 14 unmodified pages 404'd on production while
editing-affordances (touched in 9140ee51b) deployed fine. Trailing-newline
touch forces Mintlify to re-emit all SDK pages.
Concrete version now that the /editing subpath shipped in v0.7.22 (review
follow-up). Also forces a fresh Mintlify build to register the new SDK tab.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(sdk): comprehensive SDK reference + guides
Adds a dedicated SDK tab to the Mintlify docs documenting the entire
@hyperframes/sdk surface, verified against source:
Reference (6 pages):
- openComposition + OpenCompositionOptions
- Composition (every typed method, query, selection, dispatch/batch/can,
events, serialize, override mode, lifecycle)
- Edit Operations (all 33 EditOp variants for dispatch/can/batch)
- Types (every exported type + constants)
- Adapters (PersistAdapter/PreviewAdapter + memory/fs/headless/iframe factories)
- Utilities & Constants (history, persist-queue, document utils, origins, errors)
Guides (7) + Overview + Quickstart:
- querying-and-editing, timing-and-animation, undo-redo-and-patches,
persistence, embedded-override-mode, canvas-integration, editing-affordances
The existing packages/sdk.mdx stays as the package card and now links the
new SDK tab. editing-affordances documents the @hyperframes/sdk/editing
subpath shipping in #1814 (flagged with a version Note).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(sdk): address PR review feedback
Correctness fixes from PR #1817 review (Miga + Rames):
- types.mdx: FindQuery.text is a substring match (String.includes), not exact
- persistence.mdx: import PersistAdapter/PersistVersionEntry/PersistErrorEvent
from @hyperframes/sdk (no @hyperframes/sdk/adapters/types export exists)
- open-composition.mdx: createHeadlessAdapter is a PreviewAdapter, not a persist
adapter; PersistAdapter is exported from @hyperframes/sdk (no /adapters subpath)
- types.mdx / adapters.mdx: note KeyframeSpec, ElementAtPointResult, DraftProps
are structural shapes, not barrel exports (no import to copy)
- overview.mdx: drop leaked authoring meta-comment
- timing-and-animation.mdx: getElementTimings is keyed by scopedId
- embedded-override-mode.mdx: history is already off by default in embedded mode
- editing-affordances.mdx: /editing subpath is merged; soften the version note
- querying-and-editing.mdx: bare id only resolves top-level; use find() for
sub-composition leaves
- canvas-integration.mdx + persistence.mdx: explain the comp closure forward-ref
and the fs-adapter subpath (tree-shaking) asymmetry
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an opt-in --file-issue flag to hyperframes feedback. When set, after
sending the usual feedback the CLI publishes a minimal repro of the project
to a public URL (consent-gated, mirroring publish --yes) and opens a
pre-filled GitHub bug issue draft containing the rating, comment, public
repro link, and environment summary. The user reviews and submits the issue
under their own account; there is no token, backend, or gh invocation. New
--dir selects the project to publish; --yes skips the consent prompt for
scripts. URL/body building is extracted into pure, unit-tested helpers.