diff --git a/packages/cli/src/commands/coreSkillContent.test.ts b/packages/cli/src/commands/coreSkillContent.test.ts
new file mode 100644
index 000000000..001eecb1c
--- /dev/null
+++ b/packages/cli/src/commands/coreSkillContent.test.ts
@@ -0,0 +1,26 @@
+// @vitest-environment node
+import { readFileSync } from "node:fs";
+import { join } from "node:path";
+import { fileURLToPath } from "node:url";
+import { describe, expect, it } from "vitest";
+
+const REPO_ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "..", "..", "..", "..");
+const read = (...parts: string[]): string => readFileSync(join(REPO_ROOT, ...parts), "utf8");
+
+describe("hyperframes-core contract docs", () => {
+ it("keeps root data-start in the minimal composition skeleton", () => {
+ const minimal = read("skills", "hyperframes-core", "references", "minimal-composition.md");
+
+ expect(minimal).toMatch(/data-composition-id="main"[\s\S]{0,300}data-start="0"/);
+ expect(minimal).toContain('Root `
` with `data-composition-id`, `data-start="0"`');
+ });
+
+ it("teaches check as the canonical quality gate", () => {
+ const skill = read("skills", "hyperframes-core", "SKILL.md");
+ const brief = read("skills", "hyperframes-core", "references", "brief-contract.md");
+
+ expect(skill).toContain("`npx hyperframes check`");
+ expect(brief).toContain("`hyperframes check`");
+ expect(brief).not.toContain("`lint` / `validate` / `inspect`");
+ });
+});
diff --git a/skills-manifest.json b/skills-manifest.json
index d03c26a01..90856496d 100644
--- a/skills-manifest.json
+++ b/skills-manifest.json
@@ -30,7 +30,7 @@
"files": 7
},
"hyperframes-core": {
- "hash": "507aecd0bb312a94",
+ "hash": "690ebb3ba5420b90",
"files": 14
},
"hyperframes-creative": {
diff --git a/skills/hyperframes-core/SKILL.md b/skills/hyperframes-core/SKILL.md
index 837132c88..253a65b67 100644
--- a/skills/hyperframes-core/SKILL.md
+++ b/skills/hyperframes-core/SKILL.md
@@ -72,9 +72,7 @@ Surfaced here; full rationale in the linked reference. Do not violate:
Use `hyperframes-cli` for command details
-- [ ] `npx hyperframes lint` passes (0 errors)
-- [ ] `npx hyperframes check` passes (0 console errors)
-- [ ] `npx hyperframes check` passes (0 errors)
+- [ ] `npx hyperframes check` passes (0 findings across lint, runtime, layout, motion, and contrast)
- [ ] Projects with sub-compositions: `npx hyperframes snapshot --at
` and eyeball each frame
- [ ] `npx hyperframes preview` for review (the user can edit anything in Studio's timeline)
- [ ] `npx hyperframes render` only after the user approves
diff --git a/skills/hyperframes-core/references/brief-contract.md b/skills/hyperframes-core/references/brief-contract.md
index 5707bc242..5013a29af 100644
--- a/skills/hyperframes-core/references/brief-contract.md
+++ b/skills/hyperframes-core/references/brief-contract.md
@@ -17,7 +17,7 @@ There are two modes. Default: **collaborative**.
1. **Preference gates** (which preset, voice, caption identity, want a preview?) — autonomous: decide yourself and state the decision with a one-line reason. Never stay silent.
2. **Checkpoint gates** (storyboard approval, pre-render review) — autonomous: post the same summary you would have asked about as an inline heads-up, then continue. One exception: before rendering, ask once — preview first, or render (§ 3).
-3. **Quality gates** (`lint` / `validate` / `inspect`, capture completeness, fetch failures, workflow-specific verification checklists) — never skip these in any mode. Errors still stop the run. Reasoning like "autonomous means bias toward action, so I'll skip verification" misuses the mode — bias toward action applies to deciding _what to build_, not _whether to verify_.
+3. **Quality gates** (`hyperframes check`, capture completeness, fetch failures, workflow-specific verification checklists) — never skip these in any mode. Errors still stop the run. Reasoning like "autonomous means bias toward action, so I'll skip verification" misuses the mode — bias toward action applies to deciding _what to build_, not _whether to verify_.
4. **Routing and sign-in decisions** — wrong routing is a quality problem: an ambiguous-intent confirmation, such as `/slideshow`'s "is this a deck?", still happens in autonomous mode. Auth sign-in follows `/media-use` → Preflight: show the status as-is; collaborative waits for the user's choice, while autonomous notes it and continues offline.
**Autonomous is not silent.** Every question absorbed by the mode becomes a decision with a receipt — state the choice and its one-line reason inline as you go. Final delivery always includes the contact sheet, so review happens after the fact instead of not happening at all.
diff --git a/skills/hyperframes-core/references/minimal-composition.md b/skills/hyperframes-core/references/minimal-composition.md
index 4cd7c627d..c38a00ead 100644
--- a/skills/hyperframes-core/references/minimal-composition.md
+++ b/skills/hyperframes-core/references/minimal-composition.md
@@ -39,6 +39,7 @@ The smallest renderable HyperFrames composition — a standalone (top-level) roo
` with `data-composition-id`, `data-width`, `data-height`, `data-duration`
+- Root `
` with `data-composition-id`, `data-start="0"`, `data-width`, `data-height`, `data-duration`
- At least one clip (any element with `data-start`, `data-duration`, `data-track-index`)
- GSAP timeline created paused, registered on `window.__timelines[""]`