hyper-animator-codex 0.8.0 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/README.md +30 -13
  2. package/bin/hyper-animator-codex.mjs +4 -4
  3. package/lib/install-skill.mjs +49 -20
  4. package/lib/minimax-config.mjs +5 -9
  5. package/package.json +10 -2
  6. package/skills/hyper-animator-codex/SKILL.md +33 -25
  7. package/skills/hyper-animator-codex/agents/openai.yaml +2 -2
  8. package/skills/hyper-animator-codex/contracts/shot-plan.schema.json +113 -7
  9. package/skills/hyper-animator-codex/contracts/workflow-policy.json +21 -3
  10. package/skills/hyper-animator-codex/references/examples/shot-plan-dual-catalog.json +41 -5
  11. package/skills/hyper-animator-codex/references/hyperframes-intent-workflow.md +20 -10
  12. package/skills/hyper-animator-codex/references/minimax-music-workflow.md +5 -7
  13. package/skills/hyper-animator-codex/references/narration-audio-workflow.md +20 -14
  14. package/skills/hyper-animator-codex/references/preview-controls-workflow.md +4 -2
  15. package/skills/hyper-animator-codex/references/shotcraft/motion-pack/README.md +32 -0
  16. package/skills/hyper-animator-codex/references/shotcraft/motion-pack/shotcraft-motion-pack.js +178 -0
  17. package/skills/hyper-animator-codex/scripts/generate_minimax_music.mjs +11 -6
  18. package/skills/hyper-animator-codex/scripts/generate_minimax_tts.mjs +20 -8
  19. package/skills/hyper-animator-codex/scripts/git_checkpoint.mjs +29 -3
  20. package/skills/hyper-animator-codex/scripts/inject_preview_controls.mjs +37 -1
  21. package/skills/hyper-animator-codex/scripts/minimax_runtime_config.mjs +5 -9
  22. package/skills/hyper-animator-codex/scripts/query_shotcraft.mjs +10 -1
  23. package/skills/hyper-animator-codex/scripts/shot_plan_schema_validator.mjs +3 -0
  24. package/skills/hyper-animator-codex/scripts/validate_hyperframes_html.py +122 -36
  25. package/skills/hyper-animator-codex/scripts/validate_shot_plan.mjs +110 -17
package/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  Install the `hyper-animator-codex` Codex skill from npm.
4
4
 
5
5
  The skill guides Codex through a contract-first HyperFrames animation workflow:
6
- natural-language brief, outline/narration detection, dual-catalog shot planning
7
- (HyperFrames + ShotCraft), MiniMax mainland China audio, HTML animation
8
- authoring, validation, user approval, and render handoff.
6
+ natural-language brief, outline/narration detection, visual-first dual-catalog
7
+ shot planning (HyperFrames + ShotCraft), HTML animation authoring, MiniMax
8
+ mainland China audio after visual approval, validation, and render handoff.
9
9
 
10
10
  ## Install
11
11
 
@@ -77,14 +77,13 @@ generate music and voiceover without asking for credentials later:
77
77
  ```bash
78
78
  npx hyper-animator-codex install --force \
79
79
  --minimax-api-key "$MINIMAX_API_KEY" \
80
- --minimax-group-id "$MINIMAX_GROUP_ID" \
81
- --minimax-model music-2.6-free
80
+ --minimax-model music-3.0-free
82
81
  ```
83
82
 
84
83
  Environment fallback is also supported:
85
84
 
86
85
  ```bash
87
- MINIMAX_API_KEY=... MINIMAX_GROUP_ID=... npx hyper-animator-codex install --force
86
+ MINIMAX_API_KEY=... npx hyper-animator-codex install --force
88
87
  ```
89
88
 
90
89
  Or load a JSON config file:
@@ -107,7 +106,8 @@ Preview HTML can include a bottom page indicator and thin draggable progress bar
107
106
 
108
107
  ```bash
109
108
  node skills/hyper-animator-codex/scripts/inject_preview_controls.mjs composition.html -o composition.preview.html --force
110
- python3 skills/hyper-animator-codex/scripts/validate_hyperframes_html.py composition.preview.html --preview-controls
109
+ python3 skills/hyper-animator-codex/scripts/validate_hyperframes_html.py composition.preview.html \
110
+ --preview-controls --shot-plan shot-plan.json
111
111
  ```
112
112
 
113
113
  The injected controls support dragging the progress bar and using ArrowLeft or ArrowRight to move between pages.
@@ -124,6 +124,11 @@ When rendering video, hide preview controls with any one of:
124
124
 
125
125
  ## Narration And Subtitles
126
126
 
127
+ The workflow detects narration needs early, but generated narration and
128
+ subtitles are deferred until the user approves the page, transitions, and
129
+ animation. Visual drafts use `audio.narration.mode: "deferred"` in the shot
130
+ plan.
131
+
127
132
  Detect outline and narration files in a project directory:
128
133
 
129
134
  ```bash
@@ -180,20 +185,29 @@ node skills/hyper-animator-codex/scripts/query_shotcraft.mjs \
180
185
  ```
181
186
 
182
187
  HyperFrames entries remain the renderable catalog; ShotCraft supplies shot
183
- grammar and motion references that are translated into HyperFrames/GSAP HTML.
188
+ grammar and motion references that are translated into `motion_contract`
189
+ commitments and then into HyperFrames/GSAP HTML.
190
+
191
+ For high-impact ShotCraft refs, the validator requires an explicit
192
+ `motion_contract.motion_preset`. The bundled
193
+ `references/shotcraft/motion-pack/` directory contains small GSAP helpers to
194
+ copy before freehanding the animation.
195
+
184
196
  Validate a dual-catalog plan before authoring:
185
197
 
186
198
  ```bash
187
199
  node skills/hyper-animator-codex/scripts/validate_shot_plan.mjs shot-plan.json
200
+ python3 skills/hyper-animator-codex/scripts/validate_hyperframes_html.py composition.html --shot-plan shot-plan.json
188
201
  ```
189
202
 
190
- When model routing is available, `gpt-5.6-sol` is reserved for page generation
191
- and animation authoring. Planning, discovery, audio prompting, validation, and
192
- packaging use a faster cost-efficient model.
203
+ When model routing is available, the client's `high_quality` tier is reserved
204
+ for page generation and animation authoring. Planning, discovery, audio
205
+ prompting, validation, and packaging use its `fast` tier; the shot plan records
206
+ the actual model names.
193
207
 
194
208
  ## Contents
195
209
 
196
- - `skills/hyper-animator-codex/SKILL.md`: Codex skill instructions.
210
+ - `skills/hyper-animator-codex/SKILL.md`: Codex and Claude Code skill instructions.
197
211
  - `skills/hyper-animator-codex/contracts/`: provider/model policy and shot-plan schema.
198
212
  - `skills/hyper-animator-codex/references/`: HyperFrames catalog, ShotCraft knowledge bundle, authoring patterns, workflows, and examples.
199
213
  - `skills/hyper-animator-codex/scripts/query_shotcraft.mjs`: ShotCraft intent/reference search.
@@ -209,7 +223,8 @@ packaging use a faster cost-efficient model.
209
223
 
210
224
  The skill can analyze background music and guide Codex to align HyperFrames/GSAP transitions to beats, bars, energy peaks, and detected music segments.
211
225
 
212
- Install optional Python dependencies:
226
+ Install optional Python dependencies yourself if you want automatic beat
227
+ analysis. The skill will not install them during a run:
213
228
 
214
229
  ```bash
215
230
  python3 -m pip install librosa pydub numpy click
@@ -236,6 +251,8 @@ Then analyze the generated audio with `analyze_music_beats.py` and align animati
236
251
  ## Development
237
252
 
238
253
  ```bash
254
+ npm run preflight
239
255
  npm test
256
+ npm run check
240
257
  npm run pack:check
241
258
  ```
@@ -25,12 +25,12 @@ Options:
25
25
  --quiet Suppress successful install output
26
26
  --target <dir> Install into one specific skills directory
27
27
  --minimax-api-key <key> Save MiniMax API key into installed skill config
28
- --minimax-group-id <group_id> Save MiniMax group_id into installed skill config
29
- --minimax-model <model> MiniMax text music model: music-3.0, music-2.6, or music-2.6-free
30
- --minimax-config <file> Load MiniMax JSON config with api_key, group_id, and model
28
+ --minimax-group-id <group_id> Optional legacy account metadata
29
+ --minimax-model <model> MiniMax text music model; default music-3.0
30
+ --minimax-config <file> Load MiniMax JSON config with api_key and optional model
31
31
 
32
32
  Environment fallback:
33
- MINIMAX_API_KEY, MINIMAX_GROUP_ID, MINIMAX_MODEL
33
+ MINIMAX_API_KEY, MINIMAX_MODEL (MINIMAX_GROUP_ID remains optional)
34
34
  `);
35
35
  }
36
36
 
@@ -1,6 +1,6 @@
1
- import { chmod, cp, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
1
+ import { chmod, cp, mkdir, mkdtemp, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
- import { basename, dirname, join } from "node:path";
3
+ import { basename, dirname, join, resolve, sep } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
 
6
6
  import {
@@ -84,46 +84,75 @@ async function restoreExistingMinimaxConfig(installedPath, existingConfig) {
84
84
 
85
85
  export async function installSkill(options = {}) {
86
86
  const targetRoot = options.targetRoot || resolveCodexSkillsRoot(options.env);
87
- const sourcePath = options.sourcePath || join(packageRoot, "skills", SKILL_NAME);
88
- const installedPath = join(targetRoot, SKILL_NAME);
87
+ const sourcePath = resolve(options.sourcePath || join(packageRoot, "skills", SKILL_NAME));
88
+ const installedPath = resolve(targetRoot, SKILL_NAME);
89
89
  const force = Boolean(options.force);
90
90
 
91
+ if (sourcePath === installedPath
92
+ || sourcePath.startsWith(`${installedPath}${sep}`)
93
+ || installedPath.startsWith(`${sourcePath}${sep}`)) {
94
+ throw new Error(`Source and install paths overlap: ${sourcePath} -> ${installedPath}`);
95
+ }
91
96
  if (!(await pathExists(sourcePath))) {
92
97
  throw new Error(`Packaged skill not found at ${sourcePath}`);
93
98
  }
94
99
 
95
100
  await mkdir(targetRoot, { recursive: true });
96
-
97
- const existingMinimaxConfig = force ? await readExistingMinimaxConfig(installedPath) : null;
98
-
99
- if (await pathExists(installedPath)) {
101
+ const installExists = await pathExists(installedPath);
102
+ if (installExists) {
100
103
  if (!force) {
101
104
  throw new Error(`${SKILL_NAME} already exists at ${installedPath}; rerun with --force to replace it`);
102
105
  }
103
- await rm(installedPath, { recursive: true, force: true });
104
106
  }
105
107
 
106
- await cp(sourcePath, installedPath, {
107
- recursive: true,
108
- filter: shouldCopy,
109
- });
110
-
111
108
  const resolvedMinimaxConfig = await resolveInstallMinimaxConfig({
112
109
  cliConfig: options.minimaxConfig || {},
113
110
  env: options.env || process.env,
114
111
  });
115
- const minimaxWrite = resolvedMinimaxConfig
116
- ? await writeMinimaxConfig(installedPath, resolvedMinimaxConfig)
117
- : null;
118
- const restoredMinimaxConfigPath = minimaxWrite ? null : await restoreExistingMinimaxConfig(installedPath, existingMinimaxConfig);
112
+ const existingMinimaxConfig = force ? await readExistingMinimaxConfig(installedPath) : null;
113
+ const stagingRoot = await mkdtemp(join(resolve(targetRoot), `.${SKILL_NAME}-install-`));
114
+ const stagingPath = join(stagingRoot, SKILL_NAME);
115
+ let backupRoot = null;
116
+ let backupPath = null;
117
+
118
+ try {
119
+ await cp(sourcePath, stagingPath, {
120
+ recursive: true,
121
+ filter: shouldCopy,
122
+ });
123
+ if (resolvedMinimaxConfig) {
124
+ await writeMinimaxConfig(stagingPath, resolvedMinimaxConfig);
125
+ } else {
126
+ await restoreExistingMinimaxConfig(stagingPath, existingMinimaxConfig);
127
+ }
128
+
129
+ if (installExists) {
130
+ backupRoot = await mkdtemp(join(resolve(targetRoot), `.${SKILL_NAME}-backup-`));
131
+ backupPath = join(backupRoot, SKILL_NAME);
132
+ await rename(installedPath, backupPath);
133
+ }
134
+ try {
135
+ await rename(stagingPath, installedPath);
136
+ } catch (error) {
137
+ if (backupPath && await pathExists(backupPath)) {
138
+ await rename(backupPath, installedPath);
139
+ }
140
+ throw error;
141
+ }
142
+ } finally {
143
+ await rm(stagingRoot, { recursive: true, force: true });
144
+ if (backupRoot) await rm(backupRoot, { recursive: true, force: true });
145
+ }
119
146
 
120
147
  return {
121
148
  skillName: SKILL_NAME,
122
149
  tool: options.tool || "codex",
123
150
  sourcePath,
124
151
  installedPath,
125
- minimaxConfigPath: minimaxWrite ? minimaxWrite.configPath : restoredMinimaxConfigPath,
126
- minimaxConfig: minimaxWrite ? redactMinimaxConfig(minimaxWrite.config) : null,
152
+ minimaxConfigPath: resolvedMinimaxConfig || existingMinimaxConfig
153
+ ? join(installedPath, MINIMAX_CONFIG_RELATIVE_PATH)
154
+ : null,
155
+ minimaxConfig: resolvedMinimaxConfig ? redactMinimaxConfig(resolvedMinimaxConfig) : null,
127
156
  };
128
157
  }
129
158
 
@@ -1,8 +1,8 @@
1
1
  import { chmod, mkdir, readFile, stat, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
 
4
- export const DEFAULT_MINIMAX_MODEL = "music-2.6";
5
- export const TEXT_MUSIC_MODELS = new Set(["music-3.0", "music-2.6", "music-2.6-free"]);
4
+ export const DEFAULT_MINIMAX_MODEL = "music-3.0";
5
+ export const TEXT_MUSIC_MODELS = new Set(["music-3.0", "music-3.0-free", "music-2.6", "music-2.6-free"]);
6
6
  export const MINIMAX_CONFIG_RELATIVE_PATH = join("config", "minimax.json");
7
7
 
8
8
  async function pathExists(path) {
@@ -62,19 +62,15 @@ export function validateMinimaxConfig(config = {}) {
62
62
  throw new Error("MiniMax api_key is required when MiniMax config is provided");
63
63
  }
64
64
 
65
- if (!normalized.group_id) {
66
- throw new Error("MiniMax group_id is required when MiniMax config is provided");
67
- }
68
-
69
65
  const model = normalized.model || DEFAULT_MINIMAX_MODEL;
70
66
 
71
67
  if (!TEXT_MUSIC_MODELS.has(model)) {
72
- throw new Error(`Unsupported MiniMax text music model: ${model}. Use music-3.0, music-2.6, or music-2.6-free.`);
68
+ throw new Error(`Unsupported MiniMax text music model: ${model}. Use music-3.0, music-3.0-free, music-2.6, or music-2.6-free.`);
73
69
  }
74
70
 
75
71
  return {
76
72
  api_key: normalized.api_key,
77
- group_id: normalized.group_id,
73
+ ...(normalized.group_id ? { group_id: normalized.group_id } : {}),
78
74
  model,
79
75
  };
80
76
  }
@@ -156,7 +152,7 @@ export function redactMinimaxConfig(config = {}) {
156
152
 
157
153
  return {
158
154
  api_key: normalized.api_key ? "[redacted]" : undefined,
159
- group_id: normalized.group_id,
155
+ ...(normalized.group_id ? { group_id: normalized.group_id } : {}),
160
156
  model: normalized.model || DEFAULT_MINIMAX_MODEL,
161
157
  };
162
158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyper-animator-codex",
3
- "version": "0.8.0",
3
+ "version": "0.8.3",
4
4
  "description": "Install the Hyper Animator skill for Codex and Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,8 +8,13 @@
8
8
  },
9
9
  "scripts": {
10
10
  "postinstall": "node bin/postinstall.mjs",
11
+ "build:contracts": "node tools/build-shot-plan-validator.mjs",
12
+ "preflight": "node tools/verify-governance.mjs",
11
13
  "test": "node --test",
12
- "pack:check": "npm pack --dry-run"
14
+ "test:contracts": "node --test test/shot-plan-contract.test.mjs test/workflow-policy.test.mjs test/provider-policy.test.mjs",
15
+ "check": "npm run preflight && npm test && npm run pack:check",
16
+ "pack:check": "npm pack --dry-run",
17
+ "prepublishOnly": "npm run check"
13
18
  },
14
19
  "files": [
15
20
  "bin/",
@@ -36,5 +41,8 @@
36
41
  },
37
42
  "publishConfig": {
38
43
  "access": "public"
44
+ },
45
+ "devDependencies": {
46
+ "ajv": "^8.17.1"
39
47
  }
40
48
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hyper-animator-codex
3
- description: Use when a user asks Codex to create, plan, author, customize, validate, preview, or render a HyperFrames, HTML, or GSAP animation/video from natural-language requirements, including product demos, code demos, data videos, podcast captions, social shorts, catalog assembly, new HyperFrames HTML, outline/narration detection, voiceover, subtitles, sound effects, background music, rhythm, BPM, final mixing, or beat-synced transitions.
3
+ description: Use when a user asks a coding agent to create, plan, author, customize, validate, preview, or render a HyperFrames, HTML, or GSAP animation/video from natural-language requirements, including product demos, code demos, data videos, podcast captions, social shorts, catalog assembly, new HyperFrames HTML, outline/narration detection, voiceover, subtitles, sound effects, background music, rhythm, BPM, final mixing, or beat-synced transitions.
4
4
  ---
5
5
 
6
6
  # Hyper Animator Codex
@@ -11,41 +11,41 @@ Turn a natural-language animation or video brief into a validated HyperFrames HT
11
11
 
12
12
  ## Required Flow
13
13
 
14
- 1. Read `contracts/workflow-policy.json` before doing any orchestration. Treat it as an executable product contract, not optional guidance. Generated narration and generated BGM must use `minimax_cn` at the declared `minimaxi.com` endpoints.
15
- 2. Enforce the provider boundary. Never run `hyperframes auth login` or `hyperframes tts`. Do not use HeyGen, Kokoro, or MusicGen. Do not install a fallback audio runtime or fallback model. If MiniMax is unavailable or fails, stop that audio stage and ask the user to choose: retry MiniMax CN, provide a local audio file, or skip the track.
14
+ 1. Read `contracts/workflow-policy.json` before doing any orchestration. Treat it as an executable product contract, not optional guidance. Generated narration and generated BGM must use `minimax_cn` at the declared `minimaxi.com` endpoints; generated narration is gated until visual confirmation.
15
+ 2. Enforce the provider boundary. Never run `hyperframes auth login` or `hyperframes tts`. Do not use HeyGen, Kokoro, or MusicGen. Do not install a fallback audio runtime, fallback model, or beat-analysis dependency. If MiniMax or optional beat analysis is unavailable, stop that stage and ask the user to choose: retry MiniMax CN, provide a local audio file/beat map, or skip the track.
16
16
  3. Read `references/git-checkpoint-workflow.md` and run `scripts/git_checkpoint.mjs --phase init --message "chore: initialize hyper animator workspace" --allow-empty` before requirement capture. If the helper reports an existing dirty repository or linked worktree, stop and ask the user to resolve it.
17
- 4. When starting in a new directory, restarting, or handling outline/narration/voiceover/subtitle/full-mix work, read `references/narration-audio-workflow.md` and run `scripts/detect_project_files.mjs --dir . --pretty` before visual planning.
17
+ 4. When starting in a new directory, restarting, or handling outline/narration/voiceover/subtitle/full-mix work, read `references/narration-audio-workflow.md` and run `scripts/detect_project_files.mjs --dir . --pretty` before visual planning. Detect outline/narration inputs only; do not process narration yet.
18
18
  5. Capture the raw request and extract an initial intent profile: purpose, format, duration, content inputs, style tags, motion tags, and needed roles.
19
19
  6. If purpose, format, or core content is unclear, ask the first clarification round before choosing catalog items.
20
20
  7. Query both catalogs:
21
21
  - Read `references/hyperframes-catalog-map.json` and score renderable HyperFrames candidates.
22
22
  - Run `scripts/query_shotcraft.mjs --query "<purpose style motion>" --limit 8 --json` against `references/shotcraft/catalog.json` for shot grammar, pacing, transition, and camera references.
23
- 8. Pick candidate HyperFrames blocks/components plus ShotCraft references for each main scene, caption, effect, transition, and outro. ShotCraft TSX is a design reference; do not introduce Remotion or copy it as the final renderer.
23
+ 8. Pick candidate HyperFrames blocks/components plus ShotCraft references for each main scene, caption, effect, transition, and outro. Open the selected ShotCraft card READMEs and translate their timing, camera, transition, and known pitfalls into explicit `motion_contract.shotcraft_commitments`; ShotCraft TSX is a design reference, not the renderer. If a selected card is covered by `references/shotcraft/motion-pack/README.md`, use its `motion_contract.motion_preset` and GSAP helper before freehanding motion.
24
24
  9. Decide generation mode:
25
25
  - `generate_new_hyperframes_html` when the user asks to write HTML, create a new effect, customize style, match a brand, use complex animation, or when component snippets are only paste placeholders.
26
26
  - `assemble_existing_catalog_items` only when the user asks to use existing catalog items or quickly compose installed blocks/components.
27
- 10. Apply model routing when model selection is available: use `gpt-5.6-sol` for page and animation authoring only; use `gpt-5.6-terra` or another fast cost-efficient model for requirements, discovery, catalog queries, shot planning, audio prompting, validation, and packaging. Do not create an extra agent/entity only to implement this routing.
28
- 11. Write a shot plan that follows `contracts/shot-plan.schema.json`, uses `catalog_strategy: "dual_catalog"`, and gives every shot explicit start/end timing and both catalog reference lists. Run `scripts/validate_shot_plan.mjs shot-plan.json`; fix every error before audio generation or HTML authoring.
29
- 12. Clarify audio: ask whether to use narration, subtitles, animation/transition sound effects, and background music.
30
- 13. If generated narration is used, first run `scripts/validate_provider_policy.mjs --kind narration --provider minimax_cn --endpoint https://api.minimaxi.com/v1/t2a_v2`. Use `scripts/generate_minimax_tts.mjs` for voice listing and TTS; do not construct MiniMax HTTP calls directly. For multi-scene narration, use `--split-scenes` and treat `narration-manifest.json` actual durations as the scene-timing source. Reconcile shot boundaries with those durations and run `scripts/validate_shot_plan.mjs` again. If subtitles are requested, run `scripts/generate_subtitles.mjs --timing-manifest <voice-output>/narration-manifest.json`.
31
- 14. If generated BGM is requested, read `references/minimax-music-workflow.md`, run `scripts/validate_provider_policy.mjs --kind bgm --provider minimax_cn --endpoint https://api.minimaxi.com/v1/music_generation`, and use `scripts/generate_minimax_music.mjs`. Do not construct MiniMax HTTP calls directly.
32
- 15. If background music is used, read `references/beat-sync-workflow.md`, generate or obtain the audio, and run `scripts/analyze_music_beats.py` when the file is available.
33
- 16. Ask the second clarification round with dual-catalog candidate context: visual direction, motion rhythm, generation mode, narration/subtitle/audio choices, music prompt/model when MiniMax is used, and beat-sync assumptions when background music is present.
34
- 17. Write or assemble HTML using `references/HyperFrames-AI-Generation-Patterns-codex.md`. When beat-sync is enabled, align major reveals, cuts, transitions, camera moves, narration beats, subtitle cues, and visual accents to the beat map instead of arbitrary timestamps.
35
- 18. After each file-writing stage, run `scripts/git_checkpoint.mjs` with the phase-specific allowlist from `references/git-checkpoint-workflow.md`. Do not create, switch, or recommend Git branches or worktrees.
36
- 19. Run pre-render quality gates on the base HTML.
37
- 20. Read `references/preview-controls-workflow.md`, run `scripts/inject_preview_controls.mjs` to create a preview HTML copy, and run `scripts/validate_hyperframes_html.py preview.html --preview-controls`.
38
- 21. Show a concise plan summary and preview path or HTML file to the user. Ask for confirmation before video render.
39
- 22. Render only after user confirmation. Prefer rendering the base HTML; if rendering the preview copy, use `?render=1`, `?preview=0`, or `<html data-render-mode="video">` so preview controls are hidden. Then report output path and any caveats.
27
+ 10. Apply capability-based model routing when model selection is available: use the client's `high_quality` model for page and animation authoring only, and a `fast` cost-efficient model for requirements, discovery, catalog queries, shot planning, audio prompting, validation, and packaging. On Codex, prefer `gpt-5.6-sol` and `gpt-5.6-terra` respectively; on Claude Code, record the actual Claude models selected. Do not create an extra agent/entity only to implement this routing.
28
+ 11. Write a visual-first shot plan that follows `contracts/shot-plan.schema.json`, sets workflow_stage: `visual_draft`, `catalog_strategy: "dual_catalog"`, `audio.narration.mode: "deferred"` when narration is requested, provider-neutral model routing tiers plus actual model names, explicit start/end timing, both catalog reference lists, and one `motion_contract` per shot including `motion_preset`. Run `scripts/validate_shot_plan.mjs shot-plan.json`; fix every error before HTML authoring.
29
+ 12. Clarify audio intent only: ask whether the final piece should use narration, subtitles, transition sound effects, and background music. Do not generate narration audio or subtitles before the user confirms the page, transition, and animation. If BGM is the rhythm source, it may be generated or imported before HTML; otherwise defer it with narration.
30
+ 13. If generated BGM is needed as the rhythm source, read `references/minimax-music-workflow.md`, run `scripts/validate_provider_policy.mjs --kind bgm --provider minimax_cn --endpoint https://api.minimaxi.com/v1/music_generation`, and use `scripts/generate_minimax_music.mjs`. Then read `references/beat-sync-workflow.md` and run `scripts/analyze_music_beats.py` when dependencies and the file are already available. Do not install beat-analysis dependencies during the run.
31
+ 14. Ask the second clarification round with dual-catalog candidate context: visual direction, motion rhythm, selected ShotCraft commitments, generation mode, BGM/beat-sync assumptions when present, and the fact that narration is deferred until visual approval.
32
+ 15. Write or assemble the visual HTML using `references/HyperFrames-AI-Generation-Patterns-codex.md`. When beat-sync is enabled, align major reveals, cuts, transitions, camera moves, subtitle placeholders, and visual accents to the beat map instead of arbitrary timestamps.
33
+ 16. After each file-writing stage, run `scripts/git_checkpoint.mjs` with the phase-specific allowlist from `references/git-checkpoint-workflow.md`. Do not create, switch, or recommend Git branches or worktrees.
34
+ 17. Mark every shot root with `data-shot-id` and `data-motion-preset`, then run `scripts/validate_hyperframes_html.py composition.html --shot-plan shot-plan.json` so planned ShotCraft motion is proven in executable HTML.
35
+ 18. Read `references/preview-controls-workflow.md`, run `scripts/inject_preview_controls.mjs` to create a preview HTML copy (with play/pause and interactive autoplay), and run `scripts/validate_hyperframes_html.py preview.html --preview-controls --shot-plan shot-plan.json`.
36
+ 19. Show a concise visual plan summary and preview path. Ask the user to confirm or revise the page, transition, and animation before any generated narration or subtitle work.
37
+ 20. After visual confirmation, handle narration. If generated narration is used, first run `scripts/validate_provider_policy.mjs --kind narration --provider minimax_cn --endpoint https://api.minimaxi.com/v1/t2a_v2`. Use `scripts/generate_minimax_tts.mjs` for voice listing and TTS; do not construct MiniMax HTTP calls directly. For multi-scene narration, use `--split-scenes` and treat `narration-manifest.json` actual durations as the scene-timing source. Generate subtitles only after this with `scripts/generate_subtitles.mjs --timing-manifest <voice-output>/narration-manifest.json`.
38
+ 21. Reconcile shot boundaries with actual narration durations, update the shot plan to `workflow_stage: "audio_integrated"`, re-run `scripts/validate_shot_plan.mjs`, update the HTML/audio preview, and ask for final render confirmation.
39
+ 22. Render only after final user confirmation. Prefer rendering the base HTML; if rendering the preview copy, use `?render=1`, `?preview=0`, or `<html data-render-mode="video">` so preview controls are hidden. Then report output path and any caveats.
40
40
 
41
41
  ## Interactive Questions
42
42
 
43
- Prefer Codex interactive question tools such as `AskUserQuestion` or `request_user_input` when available. If they are unavailable, ask the same questions as ordinary concise text and continue after the user answers.
43
+ Prefer the current client's interactive question tool when available. If unavailable, ask the same questions as ordinary concise text and continue after the user answers.
44
44
 
45
45
  Use two rounds:
46
46
 
47
- - Round 1: purpose, format, duration, platform, required content, outline/narration status, narration/subtitles, brand assets, sound effects, background music, and whether video render is expected in this turn.
48
- - Round 2: after catalog scoring, ask about style, motion, candidate selection, generation mode, voice/emotion/subtitle style, and beat-sync assumptions when background music is present.
47
+ - Round 1: purpose, format, duration, platform, required content, outline/narration status, desired final narration/subtitles, brand assets, sound effects, background music, and whether video render is expected in this turn.
48
+ - Round 2: after catalog scoring, ask about style, motion, candidate selection, generation mode, selected ShotCraft commitments, and beat-sync assumptions when background music is present. Defer voice/emotion/subtitle generation choices until page, transition, and animation approval.
49
49
 
50
50
  Do not ask everything upfront when the brief is already specific. Ask only for missing or decision-changing information.
51
51
 
@@ -57,6 +57,7 @@ Do not ask everything upfront when the brief is already specific. Ask only for m
57
57
  - Read `references/hyperframes-catalog-map.json` whenever selecting catalog candidates or determining visual references.
58
58
  - Read `references/shotcraft/catalog.json` and use `scripts/query_shotcraft.mjs` whenever building or revising a shot plan. Open only the selected cards and source references, not the entire bundle.
59
59
  - Read selected `references/shotcraft/cards/<name>/README.md` files for intent, timing, parameters, and known failure modes. Treat selected `references/shotcraft/source/**/*.tsx` as motion references that must be translated into the HyperFrames/GSAP contract.
60
+ - Read `references/shotcraft/motion-pack/README.md` before HTML authoring when selected ShotCraft refs include a supported preset. Copy only needed helpers from `references/shotcraft/motion-pack/shotcraft-motion-pack.js`.
60
61
  - Read `contracts/shot-plan.schema.json` before writing a shot plan and validate the result with `scripts/validate_shot_plan.mjs`.
61
62
  - Read `references/HyperFrames-AI-Generation-Patterns-codex.md` before generating new HyperFrames HTML.
62
63
  - Read `references/hyperframes-agent-pseudocode.ts` when implementing the end-to-end loop or when the correct sequence is ambiguous.
@@ -71,6 +72,8 @@ Hard constraints beat score:
71
72
 
72
73
  - Use the HyperFrames map and ShotCraft together. HyperFrames answers “what can be rendered”; ShotCraft answers “how the shot should communicate and move.”
73
74
  - Query ShotCraft first, then open only the top relevant cards. By default exclude `reference-only` styles.
75
+ - Every selected ShotCraft reference must become a concrete `motion_contract.shotcraft_commitments` item in the shot plan before HTML authoring.
76
+ - Supported ShotCraft refs must also select the matching `motion_contract.motion_preset`; use the motion pack helper before inventing a new GSAP pattern.
74
77
  - Do not install React, Remotion, or ShotCraft dependencies merely to use a ShotCraft reference.
75
78
  - Portrait requests prioritize portrait items such as `instagram-follow`, `tiktok-follow`, `spotify-card`, and `flowchart-vertical`.
76
79
  - Caption requests prioritize `caption-*` components.
@@ -83,7 +86,7 @@ Hard constraints beat score:
83
86
  Before render, run:
84
87
 
85
88
  ```bash
86
- python3 scripts/validate_hyperframes_html.py path/to/composition.html
89
+ python3 scripts/validate_hyperframes_html.py path/to/composition.html --shot-plan path/to/shot-plan.json
87
90
  ```
88
91
 
89
92
  Generated block HTML must include:
@@ -93,6 +96,8 @@ Generated block HTML must include:
93
96
  - scoped CSS under `[data-composition-id="..."]` or another unique composition selector;
94
97
  - `gsap.timeline({ paused: true })`;
95
98
  - `window.__timelines[id]` registration;
99
+ - one `data-shot-id` and matching `data-motion-preset` per planned shot;
100
+ - a real motion-pack helper call for every supported non-`none` preset;
96
101
  - no unresolved `<!-- paste from ... -->` placeholders;
97
102
  - no wall-clock `Date.now()` or `setInterval()` driving primary timeline progress;
98
103
  - no `Math.random()` for visual generation; use a fixed-seed deterministic PRNG;
@@ -102,7 +107,7 @@ Generated block HTML must include:
102
107
  Preview HTML must pass:
103
108
 
104
109
  ```bash
105
- python3 scripts/validate_hyperframes_html.py path/to/composition.preview.html --preview-controls
110
+ python3 scripts/validate_hyperframes_html.py path/to/composition.preview.html --preview-controls --shot-plan path/to/shot-plan.json
106
111
  ```
107
112
 
108
113
  If the validator fails, fix the HTML before asking the user to approve render.
@@ -113,7 +118,10 @@ Before approval, inspect the preview against the selected ShotCraft cards:
113
118
 
114
119
  - every required product capability has a distinct, readable shot;
115
120
  - every shot adds new information and preserves the selected card's motion
116
- grammar, critical timing, and documented known pitfalls;
121
+ grammar, critical timing, documented known pitfalls, and written
122
+ `motion_contract.shotcraft_commitments`;
123
+ - supported ShotCraft refs use their declared `motion_contract.motion_preset`
124
+ and corresponding motion-pack helper;
117
125
  - real product states/assets are used when supplied, with no invented product
118
126
  claims;
119
127
  - text, masks, media, fonts, and async resources are fully loaded at render
@@ -134,7 +142,7 @@ Before rendering, summarize:
134
142
 
135
143
  - generation mode;
136
144
  - shot-plan validator result and selected HyperFrames/ShotCraft references per shot;
137
- - model routing used, including confirmation that Sol was limited to page/animation authoring;
145
+ - model routing used, including confirmation that the high-quality tier was limited to page/animation authoring;
138
146
  - detected outline/narration paths, ambiguity status, and any outline/narration generation assumptions;
139
147
  - selected or referenced catalog items;
140
148
  - narration usage, selected voice, emotion, voice audio path, subtitle style, subtitle JSON/SRT paths, and voice/BGM/SFX volume values when applicable;
@@ -1,4 +1,4 @@
1
1
  interface:
2
2
  display_name: "Hyper Animator Codex"
3
- short_description: "Plan dual-catalog HyperFrames videos with MiniMax CN audio"
4
- default_prompt: "Use $hyper-animator-codex to plan my shots with HyperFrames and ShotCraft, create validated HyperFrames HTML, and use MiniMax CN for generated narration or BGM."
3
+ short_description: "Plan visual-first HyperFrames videos with ShotCraft"
4
+ default_prompt: "Use $hyper-animator-codex to plan visual-first shots with HyperFrames and ShotCraft, create validated HyperFrames HTML, and add MiniMax CN narration or BGM only at the approved stage."
@@ -6,6 +6,7 @@
6
6
  "additionalProperties": false,
7
7
  "required": [
8
8
  "schema_version",
9
+ "workflow_stage",
9
10
  "generation_mode",
10
11
  "catalog_strategy",
11
12
  "dimensions",
@@ -16,7 +17,14 @@
16
17
  ],
17
18
  "properties": {
18
19
  "schema_version": {
19
- "const": "1.0.0"
20
+ "const": "1.1.0"
21
+ },
22
+ "workflow_stage": {
23
+ "enum": [
24
+ "visual_draft",
25
+ "audio_integrated",
26
+ "render_ready"
27
+ ]
20
28
  },
21
29
  "generation_mode": {
22
30
  "enum": [
@@ -74,12 +82,32 @@
74
82
  ],
75
83
  "properties": {
76
84
  "page_animation_authoring": {
77
- "const": "gpt-5.6-sol"
85
+ "allOf": [
86
+ {
87
+ "$ref": "#/$defs/modelRoute"
88
+ },
89
+ {
90
+ "properties": {
91
+ "tier": {
92
+ "const": "high_quality"
93
+ }
94
+ }
95
+ }
96
+ ]
78
97
  },
79
98
  "planning_and_validation": {
80
- "not": {
81
- "const": "gpt-5.6-sol"
82
- }
99
+ "allOf": [
100
+ {
101
+ "$ref": "#/$defs/modelRoute"
102
+ },
103
+ {
104
+ "properties": {
105
+ "tier": {
106
+ "const": "fast"
107
+ }
108
+ }
109
+ }
110
+ ]
83
111
  }
84
112
  }
85
113
  },
@@ -98,6 +126,26 @@
98
126
  }
99
127
  },
100
128
  "$defs": {
129
+ "modelRoute": {
130
+ "type": "object",
131
+ "additionalProperties": false,
132
+ "required": [
133
+ "tier",
134
+ "actual_model"
135
+ ],
136
+ "properties": {
137
+ "tier": {
138
+ "enum": [
139
+ "high_quality",
140
+ "fast"
141
+ ]
142
+ },
143
+ "actual_model": {
144
+ "type": "string",
145
+ "minLength": 1
146
+ }
147
+ }
148
+ },
101
149
  "audioTrack": {
102
150
  "type": "object",
103
151
  "additionalProperties": false,
@@ -109,7 +157,8 @@
109
157
  "enum": [
110
158
  "generated",
111
159
  "user_local_file",
112
- "none"
160
+ "none",
161
+ "deferred"
113
162
  ]
114
163
  },
115
164
  "provider": {
@@ -167,7 +216,8 @@
167
216
  "end_seconds",
168
217
  "purpose",
169
218
  "hyperframes_refs",
170
- "shotcraft_refs"
219
+ "shotcraft_refs",
220
+ "motion_contract"
171
221
  ],
172
222
  "properties": {
173
223
  "id": {
@@ -188,6 +238,7 @@
188
238
  },
189
239
  "hyperframes_refs": {
190
240
  "type": "array",
241
+ "minItems": 1,
191
242
  "items": {
192
243
  "type": "string",
193
244
  "minLength": 1
@@ -196,6 +247,7 @@
196
247
  },
197
248
  "shotcraft_refs": {
198
249
  "type": "array",
250
+ "minItems": 1,
199
251
  "items": {
200
252
  "type": "string",
201
253
  "minLength": 1
@@ -207,6 +259,60 @@
207
259
  "string",
208
260
  "null"
209
261
  ]
262
+ },
263
+ "motion_contract": {
264
+ "type": "object",
265
+ "additionalProperties": false,
266
+ "required": [
267
+ "motion_preset",
268
+ "energy",
269
+ "camera",
270
+ "transition",
271
+ "shotcraft_commitments",
272
+ "readable_rest_seconds"
273
+ ],
274
+ "properties": {
275
+ "motion_preset": {
276
+ "enum": [
277
+ "none",
278
+ "slam-entrance",
279
+ "whip-transition",
280
+ "crash-zoom",
281
+ "push-stack-wipe",
282
+ "dataviz-landscape-open",
283
+ "panel-grid-reflow",
284
+ "brand-resolve"
285
+ ]
286
+ },
287
+ "energy": {
288
+ "enum": [
289
+ "quiet",
290
+ "balanced",
291
+ "high",
292
+ "cinematic"
293
+ ]
294
+ },
295
+ "camera": {
296
+ "type": "string",
297
+ "minLength": 1
298
+ },
299
+ "transition": {
300
+ "type": "string",
301
+ "minLength": 1
302
+ },
303
+ "shotcraft_commitments": {
304
+ "type": "array",
305
+ "minItems": 1,
306
+ "items": {
307
+ "type": "string",
308
+ "minLength": 1
309
+ }
310
+ },
311
+ "readable_rest_seconds": {
312
+ "type": "number",
313
+ "minimum": 0
314
+ }
315
+ }
210
316
  }
211
317
  }
212
318
  }