diff --git a/AGENTS.md b/AGENTS.md
index 7264b1adb..1c1cd9eff 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -51,7 +51,7 @@ After creating or editing any `.html` composition:
```bash
npx hyperframes lint # Static HTML structure check
-npx hyperframes validate # Runtime check (headless Chrome — catches JS errors, missing assets)
+npx hyperframes check # Browser gate (headless Chrome — runtime errors, layout, motion, WCAG contrast)
```
Both must pass before previewing or considering work complete.
diff --git a/CLAUDE.md b/CLAUDE.md
index 7c895db16..abd8a019f 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -39,7 +39,7 @@ Atomic capabilities the creation workflows compose against — pull one when you
- `/hyperframes-keyframes` — seek-safe keyframe authoring across runtimes: GSAP timelines, CSS keyframes, Anime.js, WAAPI, FLIP, paths, masks, SVG morph/draw, text trails, 3D depth; plus `hyperframes keyframes` diagnostics for surfacing and verifying rendered motion.
- `/hyperframes-creative` — non-animation creative direction: `frame.md` / `design.md` handling, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns.
- `/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-cli` — CLI dev loop: `init`, `add`, `lint`, `validate`, `inspect`, `preview`, `render`, `publish`, `doctor`, `lambda` (AWS Lambda cloud rendering).
+- `/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.
- `/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.
@@ -81,7 +81,7 @@ After creating or editing any `.html` composition:
```bash
npx hyperframes lint # Static HTML structure check
-npx hyperframes validate # Runtime check (headless Chrome — catches JS errors, missing assets)
+npx hyperframes check # Browser gate (headless Chrome — runtime errors, layout, motion, WCAG contrast)
```
Both must pass before previewing or considering work complete.
diff --git a/README.md b/README.md
index e6b2a4a7b..d12516ace 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@ Atomic capabilities the creation workflows compose against — pull one when you
| `/hyperframes-keyframes` | Seek-safe keyframe authoring across runtimes — GSAP timelines, CSS keyframes, Anime.js, WAAPI, FLIP, paths, masks, SVG morph/draw, 3D depth — plus `hyperframes keyframes` diagnostics for rendered motion. |
| `/hyperframes-creative` | Non-animation creative direction — `frame.md` / `design.md`, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns. |
| `/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`, `validate`, `inspect`, `preview`, `render`, `publish`, `doctor`, plus AWS Lambda cloud rendering (`lambda deploy / render / progress`). |
+| `/hyperframes-cli` | CLI dev loop — `init`, `lint`, `check`, `snapshot`, `preview`, `render`, `publish`, `doctor`, plus AWS Lambda cloud rendering (`lambda deploy / render / progress`). |
| `/hyperframes-registry` | Install and wire registry blocks and components into compositions via `hyperframes add`. 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. |
diff --git a/docs/contributing/catalog.mdx b/docs/contributing/catalog.mdx
index a630a41e2..be61d7f57 100644
--- a/docs/contributing/catalog.mdx
+++ b/docs/contributing/catalog.mdx
@@ -141,7 +141,7 @@ Not everything belongs in the registry. The bar is production quality.
```bash
hyperframes lint
- hyperframes validate
+ hyperframes check
npx oxfmt your-block.html
```
diff --git a/docs/guides/pipeline.mdx b/docs/guides/pipeline.mdx
index c701ddb7a..8298adf98 100644
--- a/docs/guides/pipeline.mdx
+++ b/docs/guides/pipeline.mdx
@@ -165,7 +165,7 @@ Three checks before delivery:
```bash
npx hyperframes lint # static HTML structure checks
-npx hyperframes validate # loads in headless Chrome, catches runtime errors
+npx hyperframes check # one browser session: runtime errors, layout, motion, contrast
npx hyperframes snapshot my-video --at 2.9,10.4 # PNGs at beat midpoints
```
diff --git a/docs/guides/prompting.mdx b/docs/guides/prompting.mdx
index 49907ccc6..fe78e6904 100644
--- a/docs/guides/prompting.mdx
+++ b/docs/guides/prompting.mdx
@@ -268,7 +268,7 @@ Things that cause friction (or wrong output):
- **Don't ask for React / Vue components.** Hyperframes compositions are plain HTML with `data-*` attributes and a GSAP timeline. Asking for "a React component for the intro" forces the agent to translate later.
- **Don't ask for 4K or 60fps unless you need it.** Defaults (1920×1080, 30fps) render fast and look great. Higher specs slow rendering meaningfully.
- **Don't skip the slash command.** Without `/hyperframes`, the agent may guess at HTML video conventions instead of using the framework's actual rules (`class="clip"` on timed elements, `window.__timelines` registration, etc.).
-- **Don't paste long error logs into the prompt without context.** Run `npx hyperframes lint` and `npx hyperframes validate` first — lint catches structural issues, validate catches runtime errors (JS exceptions, missing assets, contrast problems).
+- **Don't paste long error logs into the prompt without context.** Run `npx hyperframes check` first — lint catches structural issues, validate catches runtime errors (JS exceptions, missing assets, contrast problems).
- **Don't assume the agent knows your assets.** Mention file paths explicitly (`assets/intro.mp4`, `assets/logo.png`) — the agent will check what's there but a hint speeds it up.
## Recommended workflow
diff --git a/docs/guides/skills.mdx b/docs/guides/skills.mdx
index 9579f7df6..254d85aea 100644
--- a/docs/guides/skills.mdx
+++ b/docs/guides/skills.mdx
@@ -99,7 +99,7 @@ Atomic capabilities the creation workflows compose against — pull one when you
| `/hyperframes-keyframes` | Seek-safe keyframe authoring across runtimes — GSAP timelines, CSS keyframes, Anime.js, WAAPI, FLIP, paths, masks, SVG morph/draw, 3D depth — plus `hyperframes keyframes` diagnostics for rendered motion. |
| `/hyperframes-creative` | Non-animation creative direction — `frame.md` / `design.md`, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns. |
| `/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`, `validate`, `inspect`, `preview`, `render`, `publish`, `doctor`, plus AWS Lambda cloud rendering (`lambda deploy / render / progress / destroy / policies`). |
+| `/hyperframes-cli` | CLI dev loop — `init`, `lint`, `check`, `snapshot`, `preview`, `render`, `publish`, `doctor`, plus AWS Lambda cloud rendering (`lambda deploy / render / progress / destroy / policies`). |
| `/hyperframes-registry` | Install and wire registry blocks and components into compositions via `hyperframes add`. 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. |
diff --git a/docs/guides/video-editor-cheatsheet.mdx b/docs/guides/video-editor-cheatsheet.mdx
index e9216f6bf..16e3431ab 100644
--- a/docs/guides/video-editor-cheatsheet.mdx
+++ b/docs/guides/video-editor-cheatsheet.mdx
@@ -27,7 +27,7 @@ Before showing or rendering a project:
```bash
npx hyperframes lint
-npx hyperframes validate
+npx hyperframes check
npx hyperframes render --quality standard --output review.mp4
```
@@ -174,8 +174,8 @@ I moved the hero title and resized the CTA manually in Studio. Inspect the chang
| `npx hyperframes capture https://example.com` | Capture a website as source material for a video |
| `npx hyperframes preview` | Open the live Studio preview |
| `npx hyperframes lint` | Catch structural mistakes before preview or render |
-| `npx hyperframes validate` | Run the composition in headless Chrome to catch runtime errors |
-| `npx hyperframes inspect` | Find text overflow and layout problems across the timeline |
+| `npx hyperframes check` | Run the composition in headless Chrome to catch runtime errors |
+| `npx hyperframes check` | Find text overflow and layout problems across the timeline |
| `npx hyperframes snapshot --at 1,3,5` | Save PNG checks at exact timestamps |
| `npx hyperframes render --output final.mp4` | Render the video |
| `npx hyperframes publish` | Upload the project and get a shareable HyperFrames URL |
@@ -278,9 +278,9 @@ For editor-facing changes, keep `npx hyperframes preview` running, then have the
| --- | --- |
| Preview will not start | `npx hyperframes doctor` |
| Port already in use | `npx hyperframes preview --port 4567` |
-| Render fails | `npx hyperframes lint` then `npx hyperframes validate` |
+| Render fails | `npx hyperframes lint` then `npx hyperframes check` |
| Need exact frame checks | `npx hyperframes snapshot --at 1,2.5,5` |
-| Text overflows in the frame | `npx hyperframes inspect` |
+| Text overflows in the frame | `npx hyperframes check` |
| Final render is too slow | Try `--quality draft`, reduce image sizes, or lower `--fps` |
| Need to share editable project | `npx hyperframes publish` |
diff --git a/docs/packages/cli.mdx b/docs/packages/cli.mdx
index bd4839625..91094b0ed 100644
--- a/docs/packages/cli.mdx
+++ b/docs/packages/cli.mdx
@@ -520,6 +520,34 @@ Word-level transcripts (whisper output) are grouped into readable caption cues o
The linter detects missing attributes, missing adapter libraries (GSAP, Lottie, Three.js), structural problems, and more. See [Common Mistakes](/guides/common-mistakes) for details on each rule.
+ ### `check`
+
+ The browser verification gate: everything the old `validate` → `inspect` → `snapshot` loop did, in **one** command with one browser session:
+
+ ```bash
+ npx hyperframes check [dir]
+ npx hyperframes check [dir] --json # {ok, lint, runtime, layout, motion, contrast, snapshots}
+ npx hyperframes check [dir] --snapshots # annotated overview frames + per-finding crops
+ npx hyperframes check [dir] --at 1.5,4,7.25
+ npx hyperframes check [dir] --strict # exit non-zero on warnings too
+ ```
+
+ `check` runs the linter first (browser skipped entirely on lint errors), then loads the bundled composition once and sweeps one seek grid running every audit per sample: runtime console errors and failed requests, layout defects (overflow, clipping, held overlaps, occlusion), `*.motion.json` sidecar assertions, and WCAG AA contrast.
+
+ | Flag | Description |
+ |------|-------------|
+ | `--json` | Aggregated machine-readable envelope; every finding carries selector, `data-*` identity, source file, bbox, and sample time |
+ | `--snapshots` | Write overview frames (annotated with labeled finding boxes when there are errors) plus `finding-NN-.png` crops |
+ | `--samples` / `--at` / `--at-transitions` | Control the seek grid (default 9 samples; `--at-transitions` adds tween boundaries) |
+ | `--tolerance` | Allowed overflow in px before reporting (default 2) |
+ | `--timeout` | Initial settle budget in ms (default 3000) |
+ | `--no-contrast` | Skip the WCAG audit while iterating |
+ | `--strict` | Exit non-zero on warnings too (default: only errors) |
+ | `--caption-zone ""` | Opt-in band gate: flags content whose center sits inside the fractional band (optional `severity`, `seek`) |
+ | `--frame-check` | Opt-in media out-of-frame detection (img/svg/video/canvas) |
+
+ Contrast failures are **errors** and include the sampled fg/bg colors, measured vs required ratio, and a suggested compliant color. Severity is persistence-aware: single-sample transients demote to info, held findings gate the exit code, and a frozen timeline on a 3s+ composition fails with `sweep_static`.
+
### `beats`
Detect the beats in a composition's music track and write them to a beat file the Studio uses to draw beat guides on the timeline:
@@ -549,6 +577,8 @@ Word-level transcripts (whisper output) are grouped into readable caption cues o
### `inspect`
+ Deprecated: use [`check`](#check) — it covers this layout sweep plus runtime, motion, and contrast in one browser session. `inspect` keeps working and marks `_meta.deprecated: true` in JSON output.
+
Inspect rendered visual layout across the composition timeline:
```bash
diff --git a/packages/cli/src/commands/init.test.ts b/packages/cli/src/commands/init.test.ts
index e913d6119..ef73b31be 100644
--- a/packages/cli/src/commands/init.test.ts
+++ b/packages/cli/src/commands/init.test.ts
@@ -50,8 +50,7 @@ describe("hyperframes init flag rename", () => {
expect(pkg.type).toBe("module");
expect(pkg.scripts).toMatchObject({
dev: "npx --yes hyperframes preview",
- check:
- "npx --yes hyperframes lint && npx --yes hyperframes validate && npx --yes hyperframes inspect",
+ check: "npx --yes hyperframes check",
render: "npx --yes hyperframes render",
publish: "npx --yes hyperframes publish",
});
@@ -84,8 +83,7 @@ describe("hyperframes init flag rename", () => {
};
expect(pkg.scripts).toMatchObject({
dev: "npx --yes hyperframes preview",
- check:
- "npx --yes hyperframes lint && npx --yes hyperframes validate && npx --yes hyperframes inspect",
+ check: "npx --yes hyperframes check",
render: "npx --yes hyperframes render",
publish: "npx --yes hyperframes publish",
});
diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts
index 3866a4fbc..4bb625c7f 100644
--- a/packages/cli/src/commands/init.ts
+++ b/packages/cli/src/commands/init.ts
@@ -224,9 +224,7 @@ function hyperframesScript(command: string): string {
function buildPackageScripts(): Record {
return {
dev: hyperframesScript("preview"),
- check:
- `${hyperframesScript("lint")} && ${hyperframesScript("validate")} && ` +
- `${hyperframesScript("inspect")}`,
+ check: hyperframesScript("check"),
render: hyperframesScript("render"),
publish: hyperframesScript("publish"),
};
diff --git a/packages/cli/src/templates/_shared/AGENTS.md b/packages/cli/src/templates/_shared/AGENTS.md
index a30e02dbe..3e8a31aba 100644
--- a/packages/cli/src/templates/_shared/AGENTS.md
+++ b/packages/cli/src/templates/_shared/AGENTS.md
@@ -33,7 +33,7 @@ The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-
```bash
npm run dev # start the preview server (long-running — keep it alive in background)
-npm run check # lint + validate + inspect
+npm run check # lint + runtime + layout + motion + contrast (one command)
npm run render # render to MP4
npm run publish # publish and get a shareable link
npx hyperframes lint --verbose # include info-level findings
@@ -76,7 +76,7 @@ After creating or editing any `.html` composition, **always** run the full check
npm run check
```
-Fix all errors before presenting the result. Inspect warnings should be reviewed before rendering.
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
## Key Rules
diff --git a/packages/cli/src/templates/_shared/CLAUDE.md b/packages/cli/src/templates/_shared/CLAUDE.md
index a30e02dbe..3e8a31aba 100644
--- a/packages/cli/src/templates/_shared/CLAUDE.md
+++ b/packages/cli/src/templates/_shared/CLAUDE.md
@@ -33,7 +33,7 @@ The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-
```bash
npm run dev # start the preview server (long-running — keep it alive in background)
-npm run check # lint + validate + inspect
+npm run check # lint + runtime + layout + motion + contrast (one command)
npm run render # render to MP4
npm run publish # publish and get a shareable link
npx hyperframes lint --verbose # include info-level findings
@@ -76,7 +76,7 @@ After creating or editing any `.html` composition, **always** run the full check
npm run check
```
-Fix all errors before presenting the result. Inspect warnings should be reviewed before rendering.
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
## Key Rules
diff --git a/skills-manifest.json b/skills-manifest.json
index e346b5d1c..97daf2d5f 100644
--- a/skills-manifest.json
+++ b/skills-manifest.json
@@ -6,43 +6,43 @@
"files": 144
},
"faceless-explainer": {
- "hash": "09bc257e79dabebc",
+ "hash": "a09191a97564b114",
"files": 18
},
"figma": {
- "hash": "99538ee56a4ca553",
+ "hash": "0e6e96f5a76ff824",
"files": 2
},
"general-video": {
- "hash": "67f3dae100541eed",
+ "hash": "1aed9f4f68414a45",
"files": 1
},
"hyperframes": {
- "hash": "132596767485f923",
+ "hash": "fce43b4c3355cde9",
"files": 1
},
"hyperframes-animation": {
- "hash": "16ecdf00cf5cebf1",
+ "hash": "b982a1af9821e326",
"files": 99
},
"hyperframes-cli": {
- "hash": "9544d2cee786ebaf",
+ "hash": "f1c8c70693101e59",
"files": 7
},
"hyperframes-core": {
- "hash": "511a6283a5dbd7ea",
+ "hash": "507aecd0bb312a94",
"files": 14
},
"hyperframes-creative": {
- "hash": "d60c84ddca9ea6db",
+ "hash": "3e5bcbf46dc14427",
"files": 69
},
"hyperframes-keyframes": {
- "hash": "555c0cd491c40cea",
+ "hash": "040453e302a0e15b",
"files": 3
},
"hyperframes-registry": {
- "hash": "e3b389526834109d",
+ "hash": "5f49178cc43e100b",
"files": 10
},
"media-use": {
@@ -50,19 +50,19 @@
"files": 122
},
"motion-graphics": {
- "hash": "0f1ac928e387a74c",
+ "hash": "dafcdce07d221aa4",
"files": 23
},
"music-to-video": {
- "hash": "5bb405421a7e19ba",
+ "hash": "ccb6181af8bcef09",
"files": 132
},
"pr-to-video": {
- "hash": "a93fde2b33b26e75",
+ "hash": "21dcf8aa94fc1033",
"files": 22
},
"product-launch-video": {
- "hash": "14404973ef5d38a0",
+ "hash": "158398dbfc4ab652",
"files": 20
},
"remotion-to-hyperframes": {
@@ -70,7 +70,7 @@
"files": 70
},
"slideshow": {
- "hash": "114b57cf22b39068",
+ "hash": "0f0364c54f77cb9b",
"files": 2
},
"talking-head-recut": {
@@ -78,7 +78,7 @@
"files": 27
},
"website-to-video": {
- "hash": "79af52a847abaa43",
+ "hash": "e8143700c50b7469",
"files": 32
}
}
diff --git a/skills/faceless-explainer/SKILL.md b/skills/faceless-explainer/SKILL.md
index 2f965990e..a402597b7 100644
--- a/skills/faceless-explainer/SKILL.md
+++ b/skills/faceless-explainer/SKILL.md
@@ -177,9 +177,9 @@ Inject transitions, run checks, pause for review, then render.
`npx hyperframes lint`
-`npx hyperframes validate`
+`npx hyperframes check`
-`npx hyperframes inspect`
+`npx hyperframes check`
`npx hyperframes snapshot --at `
diff --git a/skills/figma/SKILL.md b/skills/figma/SKILL.md
index b08f77174..605cd954d 100644
--- a/skills/figma/SKILL.md
+++ b/skills/figma/SKILL.md
@@ -95,7 +95,7 @@ No REST equivalent exists. You drive the MCP tools, then hand output to the pure
2b. **Validate against ground truth before calling it done — mandatory**: `export_video` on the cohort's `rootNodeId` gives Figma's own render of the timeline. Run `node skills/figma/scripts/verify-motion.mjs --reference --render --crop WxH+X+Y` — it compares motion-energy deltas (static import fidelity cancels out) and fails below 15dB min motion-PSNR (calibrated: faithful ≈ 20+, diverging ≈ 5). Measure `--crop` from the render's actual card edges, don't guess. FAIL means re-check the translation, not the threshold.
3. `motionToGsap(doc)` → `emitTimelineScript(spec)` → inject as a `