From d01dd23caf661a52c3ab6c39221b10835b72173c Mon Sep 17 00:00:00 2001 From: BuildTools Date: Mon, 28 Sep 2026 22:23:09 +0800 Subject: [PATCH 1/2] Document illustrated MV motion workflow --- codex-skill/video-autopilot/SKILL.md | 16 ++++-- .../references/music-video-motion.md | 51 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 codex-skill/video-autopilot/references/music-video-motion.md diff --git a/codex-skill/video-autopilot/SKILL.md b/codex-skill/video-autopilot/SKILL.md index fe711c0..7209c20 100644 --- a/codex-skill/video-autopilot/SKILL.md +++ b/codex-skill/video-autopilot/SKILL.md @@ -7,8 +7,9 @@ description: Plan, build, review, package, release, and improve long-form videos Turn a content brief and creator-owned source material into reviewable video artifacts and publishing packages. The workflow supports long-form video, -YouTube Shorts, Instagram Reels, and reusable image or motion assets. It does -not ship a maintainer profile: voice, face policy, captions, palette, outro, +YouTube Shorts, Instagram Reels, illustrated music videos, and reusable image +or motion assets. It does not ship a maintainer profile: voice, face policy, +captions, palette, outro, channel links, performance baselines, and aesthetic choices come from the active creator configuration or an explicit brief. @@ -44,7 +45,8 @@ active creator configuration or an explicit brief. apply it atomically through the workflow contract, and retain immutable receipts. Older plan versions may be imported for migration but not applied as the current workflow. -6. Programmatic motion uses `hao.motion-composition/v1`; Editkin Motion also +6. Programmatic motion uses the registered `hao.motion-composition/v1` or + `hao.motion-composition/v2` contract; Editkin Motion also supports editable 2.5D floating video frames, portrait perspective orbit, and two rear portrait panels through the registered MCP presets. Use the read-only scene compiler and include its commands in the audited v4 plan as @@ -52,6 +54,14 @@ active creator configuration or an explicit brief. Effects, tracking, masks, generated assets, and transitions require a semantic purpose and the evidence needed by their adapters. Missing evidence falls back to a clean cut or clean hold. + For an illustrated music video, use the separate + [illustrated music MV route](references/music-video-motion.md): original + layered character and scene art, verified musical phrases, frame-aligned + kinetic typography, editable silhouettes and foreground accents. Call + `prepare_illustrated_music_video_draft` to create a read-only scene draft, + then bind its commands and text events into the audited v4 plan. The + live-action `prepare_music_video_draft` route is used only when the creator + explicitly requests live-action montage. 7. Render only after prerequisites pass. Run technical QA, content-integrity checks, and a human review bundle. Machine checks may block known failures; they do not certify taste or authorize publication. diff --git a/codex-skill/video-autopilot/references/music-video-motion.md b/codex-skill/video-autopilot/references/music-video-motion.md new file mode 100644 index 0000000..00708a5 --- /dev/null +++ b/codex-skill/video-autopilot/references/music-video-motion.md @@ -0,0 +1,51 @@ +# Illustrated music MV route + +An illustrated music MV uses an original character, layered scenes, graphic +symbols, expressive typography and musical editing. A live-action montage +with lyric cards is a separate route. Existing videos may inform the rhythm +and visual grammar; do not copy their characters, costumes, logos, song, +shots or exact layouts. + +## Required inputs + +- A song the creator may use, with verified duration and musical sections. +- Original or licensed background, character poses and foreground art with + provenance and distribution scope. Character and foreground layers need + usable alpha. Do not substitute unrelated stock footage for missing art. +- Lyrics verified against the audio. A title or graphic word can come from + the creative brief; unverified words cannot be labeled as lyrics. +- A storyboard with section boundaries, framing changes, emotional purpose, + colour progression, text events and cut or transition evidence. + +## Editkin plan + +1. Analyse beat candidates, then listen to confirm downbeats, phrases, + syncopation and holds. Avoid cutting on every beat by default. +2. Make contiguous, frame-aligned sections. Route original background, + character, optional silhouette and transparent foreground accents to + separate editable tracks. Use distinct poses and expressions at musical + turns, with meaningful camera and depth motion. Same-aspect, high-resolution + cels can use evidence-bound `characterFrame` positioning to preserve soft + alpha edges and space for text. +3. Use `prepare_illustrated_music_video_draft` for a read-only command + candidate. The tool requires image rights, alpha, continuous music and + explicit evidence references. Its source project remains unchanged. +4. Bind its flat commands plus title and verified lyric events into one + `hao.video-autopilot.edit-plan/v4`; audit, apply atomically and render. + Preserve the command receipt and re-open the project before export. +5. Animate text at the phrase and syllable level where warranted: staggered + character entrances, brief beat words, `impact` or center-out `ripple` + treatment, exit timing, negative space and contrast that remain legible over + the character. A short `accent_flash` needs evidence on both sides of a + musical cut and frame-by-frame overexposure review. Transitions, silhouette + reveals and foreground effects should accent scene meaning. + +## Acceptance + +Inspect the rendered video and delivered native editor project. Verify every +cut, silhouette edge, text motion, colour handoff, effect and musical accent +against the storyboard; check frame count, audio continuity, decode, preview +responsiveness, render time and memory. Technical success is not art approval. +Keep the result in review until a person assesses character consistency, +posing, compositing, typography and the complete viewing rhythm. A short +engineering sample cannot be reported as a finished MV. From 84bfb62e7410161f8cc8ef180903c6fe96324e16 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Mon, 28 Sep 2026 22:49:14 +0800 Subject: [PATCH 2/2] Sync public illustrated MV route and beat preflight --- AUTOPILOT_MANIFEST.json | 2 + codex-skill/video-autopilot/SKILL.md | 1 + .../knowledge/runtime/aesthetic_standard.json | 29 ++++- .../design_runtime/src/design_system_v6.py | 18 ++- .../references/editkin-workflow-execution.md | 4 + .../references/music-video-motion.md | 6 +- knowledge/runtime/aesthetic_standard.json | 29 ++++- scripts/public_skill_skeleton.py | 18 ++- scripts/public_sync_inventory.py | 13 +- scripts/sync_canonical.py | 12 +- src/design_system_v6.py | 18 ++- src/music_mv_preflight.py | 111 ++++++++++++++++++ sync-receipt.json | 38 +++--- 13 files changed, 265 insertions(+), 34 deletions(-) create mode 100644 src/music_mv_preflight.py diff --git a/AUTOPILOT_MANIFEST.json b/AUTOPILOT_MANIFEST.json index 919106c..9713f89 100644 --- a/AUTOPILOT_MANIFEST.json +++ b/AUTOPILOT_MANIFEST.json @@ -303,6 +303,7 @@ "codex-skill/video-autopilot/references/motion-asset-library.md", "codex-skill/video-autopilot/references/mrbeast-and-yingshi-benchmark.md", "codex-skill/video-autopilot/references/mrbeast-production-source-map.md", + "codex-skill/video-autopilot/references/music-video-motion.md", "codex-skill/video-autopilot/references/niche-editing-grammar.md", "codex-skill/video-autopilot/references/niche-fonts-colors.md", "codex-skill/video-autopilot/references/publish-hub-and-remix.md", @@ -386,6 +387,7 @@ "src/longform_maker/word_captions.py", "src/motion_asset_pack.py", "src/motion_renderers.py", + "src/music_mv_preflight.py", "src/outcome_learning.py", "src/platform_compat.py", "src/project_kernel.py", diff --git a/codex-skill/video-autopilot/SKILL.md b/codex-skill/video-autopilot/SKILL.md index 7209c20..9c50426 100644 --- a/codex-skill/video-autopilot/SKILL.md +++ b/codex-skill/video-autopilot/SKILL.md @@ -113,6 +113,7 @@ require confirmation; unknown files are never deleted implicitly. - [Editorial intelligence contract](references/editorial-intelligence-contract.md) - [Workflow execution](references/editkin-workflow-execution.md) +- [Illustrated music MV route](references/music-video-motion.md) - [Plugin automation](references/editkin-plugin-automation.md) - [Mobile device binding](references/editkin-mobile-device-binding.md) - [Model and context adaptation](references/model-and-context-adaptation.md) diff --git a/codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json b/codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json index 6d16ec6..64cb3a1 100644 --- a/codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json +++ b/codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json @@ -1,7 +1,7 @@ { "schema_version": 1, "standard_id": "public-aesthetic-standard", - "version": "2.2.0", + "version": "2.3.0", "reference_basis": { "dna_file": "knowledge/runtime/design_reference_dna.json", "compiler": "design_system_v6.py", @@ -312,6 +312,20 @@ "music" ] }, + "illustrated_mv": { + "label_zh": "插畫角色節奏敘事", + "templates": [], + "traits": [ + "original illustrated character integrated with layered scenery", + "pose and expression changes across musical sections", + "kinetic spatial type shaped around the character silhouette", + "frame-aligned accents with quiet holds", + "scene colour progression and motivated cuts" + ], + "best_for": [ + "music" + ] + }, "ticket_ribbon": { "label_zh": "票券與緞帶動態排版", "templates": [ @@ -525,6 +539,19 @@ "all beats using the same transition" ] }, + "illustrated_music_mv": { + "primary": "illustrated_mv", + "support": [ + "night_signal", + "arcade_pop", + "brush_culture" + ], + "avoid": [ + "static lyric cards over unrelated footage", + "one pose across every phrase", + "cuts on every beat without phrasing" + ] + }, "culture": { "primary": "brush_culture", "support": [ diff --git a/codex-skill/video-autopilot/design_runtime/src/design_system_v6.py b/codex-skill/video-autopilot/design_runtime/src/design_system_v6.py index 6d28887..198fa91 100644 --- a/codex-skill/video-autopilot/design_runtime/src/design_system_v6.py +++ b/codex-skill/video-autopilot/design_runtime/src/design_system_v6.py @@ -63,11 +63,22 @@ "brush_culture": ["dry brush", "flat colour plane", "stamp accent"], "cobalt_lime_ui": ["clean UI plane", "selection mark", "technical line"], "iridescent_future": ["glass or chrome hero", "spectral light", "clean cyclorama"], + "illustrated_mv": ["painted scene layers", "soft character alpha", "subtle halftone accent"], "ticket_ribbon": ["printed ribbon", "paper curl", "perspective depth"], "arcade_pop": ["sticker edge", "comic halftone", "flat colour burst"], "pixel_terminal": ["one-bit pixel", "bitmap window", "scan texture"], "japanese_lifestyle_calm": ["warm paper", "natural wood", "linen", "soft daylight"], } +ORIGINAL_FAMILY_TOKENS = { + # This new family is authored from the MV brief, not inferred from reference + # images. Explicit defaults keep an empty reference set from yielding an + # arbitrary palette, typography or motion treatment. + "illustrated_mv": { + "palette": ["indigo or dawn base chosen by song section", "one warm character accent", "legible light or ink type"], + "motion": ["character pose or expression change at phrases", "layer parallax with short held frames", "spatial type entry on verified beats", "motivated silhouette or foreground reveal"], + "type": ["one oversized display voice integrated with character negative space", "short secondary voice only when necessary"], + }, +} EXCLUSIVE_DISPLAY_FAMILIES = {"arcade_pop", "pixel_terminal", "iridescent_future"} ROLE_LAYOUT_PREFERENCES = { "first_frame": ["centered", "diagonal", "corner_anchor", "image_bleed"], @@ -210,12 +221,13 @@ def _compile_visual_tokens(examples: list[dict[str, Any]], primary: str, energy: float) -> dict[str, Any]: accent_budget = 1 if energy < .45 else 2 density = "quiet" if energy < .35 else ("controlled" if energy < .78 else "impact") + original = ORIGINAL_FAMILY_TOKENS.get(primary, {}) return { - "palette_candidates": _dimension_candidates(examples, "palette", "palette", 5, art_take=2), + "palette_candidates": _dimension_candidates(examples, "palette", "palette", 5, art_take=2) or original.get("palette", []), "accent_colour_budget": accent_budget, "material_candidates": _dimension_candidates(examples, "material", "material", 4, art_take=2) or MATERIAL_PRESETS[primary], - "motion_candidates": _dimension_candidates(examples, "motion", "motion", 4), - "type_candidates": _dimension_candidates(examples, "type", "type", 3), + "motion_candidates": _dimension_candidates(examples, "motion", "motion", 4) or original.get("motion", []), + "type_candidates": _dimension_candidates(examples, "type", "type", 3) or original.get("type", []), "composition_candidates": _dimension_candidates(composition_examples, "composition", "composition", 3), "hierarchy_candidates": _dimension_candidates(hierarchy_examples, "hierarchy", "hierarchy", 3), "density": density, diff --git a/codex-skill/video-autopilot/references/editkin-workflow-execution.md b/codex-skill/video-autopilot/references/editkin-workflow-execution.md index d810b67..42a65e7 100644 --- a/codex-skill/video-autopilot/references/editkin-workflow-execution.md +++ b/codex-skill/video-autopilot/references/editkin-workflow-execution.md @@ -28,6 +28,10 @@ Skill source precedence 與 Editkin 完全一致:明確 invocation path → `~/.codex/skills/video-autopilot/SKILL.md`;workflow contract 永遠取該 Skill 同層檔案。 workspace `.claude` 相容副本不得自動成為 governance source。 +## Editkin Music MV + +在固定 DAG 的歌曲/素材收據齊全後,依 `references/music-video-motion.md` 預檢節拍,聽歌核對樂段,建立原創角色、背景及畫面文字的分鏡。動畫 MV 先取得有權利的插畫層;輸入同畫幅完整畫布的角色透明 PNG 與背景(可保留高解析原稿),呼叫只讀 `prepare_illustrated_music_video_draft` 編出背景和角色獨立軌、逐格關鍵幀、樂段切鏡及空間字。回傳的 `editorialGraphics`、精確命令順序、來源與 beat/phrase 證據放進同一份 v4 plan,逐項綁 `editorial.motionTreatment` 與 `designEvidence`。先 `audit_autopilot_plan`,再 `apply_autopilot_plan`,最後原生 render、技術 QA、手機及人工美術審片。歌曲或插畫缺失時停在素材製作/缺口,不得改以實拍歌詞卡冒充動畫 MV。只有使用者明確選擇實拍蒙太奇才用 `prepare_music_video_draft`。 + ## 快速與續跑規則 - 建立 run 時直接 hash 真實素材 bytes;同路徑換檔會使來源失效,不能只信舊 metadata。 diff --git a/codex-skill/video-autopilot/references/music-video-motion.md b/codex-skill/video-autopilot/references/music-video-motion.md index 00708a5..bb760e0 100644 --- a/codex-skill/video-autopilot/references/music-video-motion.md +++ b/codex-skill/video-autopilot/references/music-video-motion.md @@ -19,8 +19,10 @@ shots or exact layouts. ## Editkin plan -1. Analyse beat candidates, then listen to confirm downbeats, phrases, - syncopation and holds. Avoid cutting on every beat by default. +1. Run `python src/music_mv_preflight.py --window 45 --output /music-preflight.json` + for beat candidates, then listen to confirm + downbeats, phrases, syncopation and holds. The preflight does not certify + musical structure or lyrics. Avoid cutting on every beat by default. 2. Make contiguous, frame-aligned sections. Route original background, character, optional silhouette and transparent foreground accents to separate editable tracks. Use distinct poses and expressions at musical diff --git a/knowledge/runtime/aesthetic_standard.json b/knowledge/runtime/aesthetic_standard.json index 6d16ec6..64cb3a1 100644 --- a/knowledge/runtime/aesthetic_standard.json +++ b/knowledge/runtime/aesthetic_standard.json @@ -1,7 +1,7 @@ { "schema_version": 1, "standard_id": "public-aesthetic-standard", - "version": "2.2.0", + "version": "2.3.0", "reference_basis": { "dna_file": "knowledge/runtime/design_reference_dna.json", "compiler": "design_system_v6.py", @@ -312,6 +312,20 @@ "music" ] }, + "illustrated_mv": { + "label_zh": "插畫角色節奏敘事", + "templates": [], + "traits": [ + "original illustrated character integrated with layered scenery", + "pose and expression changes across musical sections", + "kinetic spatial type shaped around the character silhouette", + "frame-aligned accents with quiet holds", + "scene colour progression and motivated cuts" + ], + "best_for": [ + "music" + ] + }, "ticket_ribbon": { "label_zh": "票券與緞帶動態排版", "templates": [ @@ -525,6 +539,19 @@ "all beats using the same transition" ] }, + "illustrated_music_mv": { + "primary": "illustrated_mv", + "support": [ + "night_signal", + "arcade_pop", + "brush_culture" + ], + "avoid": [ + "static lyric cards over unrelated footage", + "one pose across every phrase", + "cuts on every beat without phrasing" + ] + }, "culture": { "primary": "brush_culture", "support": [ diff --git a/scripts/public_skill_skeleton.py b/scripts/public_skill_skeleton.py index 099230a..7453b6b 100644 --- a/scripts/public_skill_skeleton.py +++ b/scripts/public_skill_skeleton.py @@ -30,6 +30,7 @@ "editkin-plugin-automation.md", "editkin-workflow-execution.md", "model-and-context-adaptation.md", + "music-video-motion.md", "open-source-release-and-upgrade.md", "publish-hub-and-remix.md", "script-retention-2026.md", @@ -108,8 +109,9 @@ def validate_canonical_frontmatter(canonical_text: str) -> Dict[str, str]: Turn a content brief and creator-owned source material into reviewable video artifacts and publishing packages. The workflow supports long-form video, -YouTube Shorts, Instagram Reels, and reusable image or motion assets. It does -not ship a maintainer profile: voice, face policy, captions, palette, outro, +YouTube Shorts, Instagram Reels, illustrated music videos, and reusable image +or motion assets. It does not ship a maintainer profile: voice, face policy, +captions, palette, outro, channel links, performance baselines, and aesthetic choices come from the active creator configuration or an explicit brief. @@ -145,7 +147,8 @@ def validate_canonical_frontmatter(canonical_text: str) -> Dict[str, str]: apply it atomically through the workflow contract, and retain immutable receipts. Older plan versions may be imported for migration but not applied as the current workflow. -6. Programmatic motion uses `hao.motion-composition/v1`; Editkin Motion also +6. Programmatic motion uses the registered `hao.motion-composition/v1` or + `hao.motion-composition/v2` contract; Editkin Motion also supports editable 2.5D floating video frames, portrait perspective orbit, and two rear portrait panels through the registered MCP presets. Use the read-only scene compiler and include its commands in the audited v4 plan as @@ -153,6 +156,14 @@ def validate_canonical_frontmatter(canonical_text: str) -> Dict[str, str]: Effects, tracking, masks, generated assets, and transitions require a semantic purpose and the evidence needed by their adapters. Missing evidence falls back to a clean cut or clean hold. + For an illustrated music video, use the separate + [illustrated music MV route](references/music-video-motion.md): original + layered character and scene art, verified musical phrases, frame-aligned + kinetic typography, editable silhouettes and foreground accents. Call + `prepare_illustrated_music_video_draft` to create a read-only scene draft, + then bind its commands and text events into the audited v4 plan. The + live-action `prepare_music_video_draft` route is used only when the creator + explicitly requests live-action montage. 7. Render only after prerequisites pass. Run technical QA, content-integrity checks, and a human review bundle. Machine checks may block known failures; they do not certify taste or authorize publication. @@ -204,6 +215,7 @@ def validate_canonical_frontmatter(canonical_text: str) -> Dict[str, str]: - [Editorial intelligence contract](references/editorial-intelligence-contract.md) - [Workflow execution](references/editkin-workflow-execution.md) +- [Illustrated music MV route](references/music-video-motion.md) - [Plugin automation](references/editkin-plugin-automation.md) - [Mobile device binding](references/editkin-mobile-device-binding.md) - [Model and context adaptation](references/model-and-context-adaptation.md) diff --git a/scripts/public_sync_inventory.py b/scripts/public_sync_inventory.py index 23119a3..9d212a6 100644 --- a/scripts/public_sync_inventory.py +++ b/scripts/public_sync_inventory.py @@ -21,7 +21,7 @@ "battle_plan_components.py", "broll_qa.py", "camera_transition_director.py", "caption_director.py", "challenge_hud.py", "channel_tracker.py", "color_calibration_lab.py", "context_router.py", "domain_broll_pack.py", "domain_taxonomy.py", "drama_autopilot.py", "beyblade_x_rules.py", - "design_system_v6.py", "editorial_parity_benchmark.py", "editorial_templates.py", "knowledge_lifecycle.py", "motion_asset_pack.py", + "design_system_v6.py", "editorial_parity_benchmark.py", "editorial_templates.py", "knowledge_lifecycle.py", "motion_asset_pack.py", "music_mv_preflight.py", "mrbeast_editing_system.py", "mrbeast_source_map.py", "three_d_system.py", "motion_renderers.py", "outcome_learning.py", "project_kernel.py", "project_quality_95.py", "media_delivery_qa.py", "delivery_media_ops.py", @@ -214,6 +214,7 @@ # cannot be silently ignored by a false-green public sync. PUBLIC_OWNED_PATHS = ( "codex-skill/video-autopilot/editkin_design_bridge.py", + "codex-skill/video-autopilot/references/music-video-motion.md", "codex-skill/video-autopilot/design_runtime/src/aesthetic_score.py", "codex-skill/video-autopilot/design_runtime/src/design_system_v6.py", "codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json", @@ -253,7 +254,7 @@ "drama_pipeline": 0, "knowledge": 3, "agents": 0, - "references": 7, + "references": 8, } @@ -380,6 +381,10 @@ def public_destination_direct_files() -> dict[str, frozenset[str]]: Path(relative).name for relative in PUBLIC_OWNED_PATHS if Path(relative).parent.as_posix() == "src" } + public_reference_owned = { + Path(relative).name for relative in PUBLIC_OWNED_PATHS + if Path(relative).parent.as_posix() == "codex-skill/video-autopilot/references" + } return { "src": frozenset((*ROOT_MODULES, *public_src_owned)), "src/longform_maker": frozenset((*LONGFORM_MODULES, "__init__.py")), @@ -390,7 +395,7 @@ def public_destination_direct_files() -> dict[str, frozenset[str]]: "codex-skill/video-autopilot/design_runtime/src": frozenset(("aesthetic_score.py", "design_system_v6.py")), "codex-skill/video-autopilot/design_runtime/knowledge/runtime": frozenset(("aesthetic_standard.json", "design_reference_dna.json")), "codex-skill/video-autopilot/agents": frozenset(("openai.yaml",)), - "codex-skill/video-autopilot/references": frozenset(REFERENCE_FILES), + "codex-skill/video-autopilot/references": frozenset((*REFERENCE_FILES, *public_reference_owned)), } @@ -593,5 +598,5 @@ def self_test_public_inventory(repository: Path) -> None: assert "public design runtime mirror drift" in str(exc) else: raise AssertionError("public design runtime accepted a stale mirror") - assert len(sync_expected_output_paths()) == 307 + assert len(sync_expected_output_paths()) == 309 print("public sync inventory negative fixtures GREEN") diff --git a/scripts/sync_canonical.py b/scripts/sync_canonical.py index f480ec3..89891d7 100644 --- a/scripts/sync_canonical.py +++ b/scripts/sync_canonical.py @@ -296,9 +296,17 @@ def _copy_public_owned(distribution_source: Path, repository: Path) -> list[str] keeps the committed sync receipt valid after Git checkout/archive filters on Windows and makes the receipt portable across supported platforms. """ + generated_mirrors = { + "codex-skill/video-autopilot/design_runtime/src/aesthetic_score.py": "src/aesthetic_score.py", + "codex-skill/video-autopilot/design_runtime/src/design_system_v6.py": "src/design_system_v6.py", + "codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json": "knowledge/runtime/aesthetic_standard.json", + "codex-skill/video-autopilot/design_runtime/knowledge/runtime/design_reference_dna.json": "knowledge/runtime/design_reference_dna.json", + } copied: list[str] = [] for relative in PUBLIC_OWNED_PATHS: - source, destination = distribution_source / relative, repository / relative + generated = repository / generated_mirrors[relative] if relative in generated_mirrors else None + source = generated if generated is not None and generated.is_file() else distribution_source / relative + destination = repository / relative if not source.is_file(): raise FileNotFoundError(f"public-kit-owned source missing: {source}") text = source.read_text(encoding="utf-8-sig") @@ -332,6 +340,8 @@ def _unexpected_public_references(repository: Path) -> list[str]: if not reference_root.is_dir(): return [] expected = {Path(name).as_posix() for name in REFERENCE_FILES} + expected.update(Path(name).name for name in PUBLIC_OWNED_PATHS + if Path(name).parent.as_posix() == "codex-skill/video-autopilot/references") actual = { path.relative_to(reference_root).as_posix() for path in reference_root.rglob("*.md") diff --git a/src/design_system_v6.py b/src/design_system_v6.py index 6d28887..198fa91 100644 --- a/src/design_system_v6.py +++ b/src/design_system_v6.py @@ -63,11 +63,22 @@ "brush_culture": ["dry brush", "flat colour plane", "stamp accent"], "cobalt_lime_ui": ["clean UI plane", "selection mark", "technical line"], "iridescent_future": ["glass or chrome hero", "spectral light", "clean cyclorama"], + "illustrated_mv": ["painted scene layers", "soft character alpha", "subtle halftone accent"], "ticket_ribbon": ["printed ribbon", "paper curl", "perspective depth"], "arcade_pop": ["sticker edge", "comic halftone", "flat colour burst"], "pixel_terminal": ["one-bit pixel", "bitmap window", "scan texture"], "japanese_lifestyle_calm": ["warm paper", "natural wood", "linen", "soft daylight"], } +ORIGINAL_FAMILY_TOKENS = { + # This new family is authored from the MV brief, not inferred from reference + # images. Explicit defaults keep an empty reference set from yielding an + # arbitrary palette, typography or motion treatment. + "illustrated_mv": { + "palette": ["indigo or dawn base chosen by song section", "one warm character accent", "legible light or ink type"], + "motion": ["character pose or expression change at phrases", "layer parallax with short held frames", "spatial type entry on verified beats", "motivated silhouette or foreground reveal"], + "type": ["one oversized display voice integrated with character negative space", "short secondary voice only when necessary"], + }, +} EXCLUSIVE_DISPLAY_FAMILIES = {"arcade_pop", "pixel_terminal", "iridescent_future"} ROLE_LAYOUT_PREFERENCES = { "first_frame": ["centered", "diagonal", "corner_anchor", "image_bleed"], @@ -210,12 +221,13 @@ def _compile_visual_tokens(examples: list[dict[str, Any]], primary: str, energy: float) -> dict[str, Any]: accent_budget = 1 if energy < .45 else 2 density = "quiet" if energy < .35 else ("controlled" if energy < .78 else "impact") + original = ORIGINAL_FAMILY_TOKENS.get(primary, {}) return { - "palette_candidates": _dimension_candidates(examples, "palette", "palette", 5, art_take=2), + "palette_candidates": _dimension_candidates(examples, "palette", "palette", 5, art_take=2) or original.get("palette", []), "accent_colour_budget": accent_budget, "material_candidates": _dimension_candidates(examples, "material", "material", 4, art_take=2) or MATERIAL_PRESETS[primary], - "motion_candidates": _dimension_candidates(examples, "motion", "motion", 4), - "type_candidates": _dimension_candidates(examples, "type", "type", 3), + "motion_candidates": _dimension_candidates(examples, "motion", "motion", 4) or original.get("motion", []), + "type_candidates": _dimension_candidates(examples, "type", "type", 3) or original.get("type", []), "composition_candidates": _dimension_candidates(composition_examples, "composition", "composition", 3), "hierarchy_candidates": _dimension_candidates(hierarchy_examples, "hierarchy", "hierarchy", 3), "density": density, diff --git a/src/music_mv_preflight.py b/src/music_mv_preflight.py new file mode 100644 index 0000000..1e6786d --- /dev/null +++ b/src/music_mv_preflight.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Read-only music timing candidates for an Editkin Music MV. + +The result is deliberately a *candidate* grid. It cannot establish the real +downbeat, musical phrase, lyric words, rights, or an aesthetically good cut. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import shutil +import statistics +import subprocess +import tempfile +from pathlib import Path + +from longform_maker.music_engine import _load_pcm, _probe_duration, detect_beats + + +def _sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as source: + for block in iter(lambda: source.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def _extract_window(source: Path, target: Path, start: float, duration: float) -> None: + result = subprocess.run( + ["ffmpeg", "-hide_banner", "-loglevel", "error", "-ss", str(start), + "-i", str(source), "-t", str(duration), "-vn", "-ac", "1", "-ar", "22050", + "-c:a", "pcm_s16le", "-y", str(target)], + capture_output=True, + ) + if result.returncode or not target.is_file() or target.stat().st_size < 1024: + raise RuntimeError("AUDIO_DECODE_FAILED: " + result.stderr.decode("utf-8", "replace")[-350:]) + + +def analyze_song(source: Path, start: float = 0, window: float = 45, + force_fallback: bool = False) -> dict: + source = source.resolve(strict=True) + if not source.is_file() or not math.isfinite(start) or not math.isfinite(window): + raise ValueError("source, start, and window must be valid") + if start < 0 or window < 12 or window > 60: + raise ValueError("start must be nonnegative and window must be 12–60 seconds") + if not shutil.which("ffmpeg") or not shutil.which("ffprobe"): + raise RuntimeError("FFMPEG_REQUIRED") + song_duration = _probe_duration(source) + if song_duration <= 0 or start >= song_duration - 12: + raise ValueError("analysis window has fewer than 12 seconds of audio") + window = min(window, song_duration - start) + with tempfile.TemporaryDirectory(prefix="editkin-music-mv-") as temporary: + excerpt = Path(temporary) / "excerpt.wav" + _extract_window(source, excerpt, start, window) + pcm, _ = _load_pcm(excerpt) + rms = math.sqrt(float((pcm.astype("float64") ** 2).mean())) if pcm.size else 0.0 + if rms < 0.001: + detected = {"bpm": 0.0, "beats": [], "confidence": "none"} + else: + detected = detect_beats(excerpt, force_fallback=force_fallback) + + local_beats = [float(t) for t in detected["beats"] if 0 <= float(t) < window] + beats = [round(start + t, 4) for t in local_beats] + intervals = [b - a for a, b in zip(beats, beats[1:])] + median_interval = statistics.median(intervals) if intervals else 0.0 + regularity = (1 - statistics.median(abs(value - median_interval) for value in intervals) / median_interval + if median_interval > 0 else 0.0) + plausible = 60 <= float(detected["bpm"]) <= 180 and len(beats) >= 8 and regularity >= 0.75 + status = "BEAT_GRID_REVIEW_REQUIRED" if plausible else "BEAT_GRID_UNAVAILABLE" + return { + "schema": "hao.video-autopilot.music-mv-preflight/v1", + "status": status, + "sourceSha256": _sha256(source), + "sourceDurationSec": round(song_duration, 4), + "analysisRangeSec": [round(start, 4), round(start + window, 4)], + "algorithm": detected["confidence"], + "bpmCandidate": float(detected["bpm"]) if plausible else None, + "beatCandidatesSec": beats if plausible else [], + "fourBeatBoundaryCandidatesSec": beats[::4] if plausible else [], + "eightBeatBoundaryCandidatesSec": beats[::8] if plausible else [], + "gridRegularity": round(regularity, 4), + "downbeatVerified": False, + "phraseVerified": False, + "lyricsTranscribed": False, + "next": "Check downbeat/phrase against the actual song and visual story; choose a sparse cut grid. Do not treat every beat as a cut or infer lyrics.", + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("song", type=Path) + parser.add_argument("--start", type=float, default=0) + parser.add_argument("--window", type=float, default=45) + parser.add_argument("--fallback", action="store_true", help="Use deterministic NumPy detector") + parser.add_argument("--output", type=Path) + args = parser.parse_args() + result = analyze_song(args.song, args.start, args.window, args.fallback) + serialized = json.dumps(result, ensure_ascii=False, indent=2) + "\n" + if args.output: + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(serialized, encoding="utf-8") + else: + print(serialized, end="") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/sync-receipt.json b/sync-receipt.json index b8f3035..4c2d6c0 100644 --- a/sync-receipt.json +++ b/sync-receipt.json @@ -2,7 +2,7 @@ "schema": "video-autopilot-public-sync-receipt/v3", "assurance": "Detects stale or accidental public-sync drift. This committed receipt is not an external signature against an attacker who can modify both code and receipt.", "output_hash_semantics": "sha256:utf8-bom-stripped:lf-normalized", - "canonical_inventory_sha256": "adf206bab1302e2270ec4149a8a80aa75b3fc99f8610a10486be535aec0b3aed", + "canonical_inventory_sha256": "33bb6e49eec3678c1c69219b32f3af2e64818b89c64774b903f2d5b30b5a9440", "canonical_inventory": { "root": { "derived": { @@ -33,7 +33,7 @@ "composition_runtime.py": "00dd4c7c4903bdefe4d59f63b39d3afcae911bb7c26e8df0087e5516ef7d5801", "context_router.py": "2182f58b88de0097d49b166cce0b05c5243ca69b54c9d9e05e4bf55e7337565e", "delivery_media_ops.py": "e820077e7208160884e4e2d0280b1788ef0912feeb525b68b50e4ea3f4051f02", - "design_system_v6.py": "b2d7b4c0ba59eff347418b809ea35ac3de9803920c2f103ec82867148b9faab1", + "design_system_v6.py": "3aa2f30c7008a7fb2db3a67362740e1f2bea81f5138210ee1f10e11ee7b929c3", "domain_broll_pack.py": "19e98952f2f6ac57c61c3744c6ded6543a29b1d020af591b7e083d73023a71ec", "domain_taxonomy.py": "35f0237600695fccdc05ad0f5797a8bd08bbf3186e38f983cc7f8e063ab423af", "drama_autopilot.py": "a30ba6fddbd07b778f4425493bb52938270c10242260178924bc3cb0a58d558c", @@ -51,6 +51,7 @@ "motion_renderers.py": "d9fc90733fa702b2b43a3245236ed5f76e3b9191d33adafef9da4c98591dd881", "mrbeast_editing_system.py": "c0c4f70398037ccdc0b5de13e7b6317d19ee4031bbff615dca779588bdf26819", "mrbeast_source_map.py": "95c2ab26621b75303764f4e00b35999d7ef02e9c3a41cb8ba38e2845e1ccefee", + "music_mv_preflight.py": "7f0366d58c230935276195b1d3f35776dbcca8a68d167842b6e704e0f2da560f", "outcome_learning.py": "52a8d7125fe1b90cbd0d911517ccd5210af00447f33cee704158a925d845b91e", "parallax_transition.py": "ed2a4f0a6cdab683096753104eb1c8e51884875a02a445a725b96cd74b5899fa", "project_kernel.py": "75bf5795db429b44841604b361eaffda9a3044f88928389fd7608f2a5a82ed0b", @@ -104,7 +105,7 @@ "workflow_transport.py": "8891d78b1882c4c204f53665eeac3ace568363353577d52da5974749b9e5651e" }, "special": { - "SKILL.md": "4b2627f3bbffe7073f677f5f04c8c1f6baefc6847514d5c7b3478cd768c100cc", + "SKILL.md": "92a54264c8dfd9318616aaf67b23a24b6ce119b557ef40596f9c6d2542ddd7cc", "audit.config.json": "e3d80d325fd4ab4c516ba7507f27dcf9ffa45a720dd157cc68034015cce80456" }, "public_owned_analogue": { @@ -195,7 +196,7 @@ }, "knowledge": { "derived": { - "aesthetic_standard.json": "b5718fad0153cadf9343a9cc699c36c42ea9b2b7efb1c6669d38150119ae96e7", + "aesthetic_standard.json": "8985dac258d1fab378396d8372836e0f95279e3bfad12ee8d74dac5a264b2578", "asset_license_overrides.json": "8b443854fb341ff4ad4658b1e8e688e350d0df81a75168de14754b17556bf13e", "asset_license_policy.json": "a3e7e4df99fd42918ba65e0f506d03f9ede27de3f2aa7f55ad8831d786524872", "beyblade_x_rules.json": "4eed9df62d0bd833846c0805a6fe6a2e080728f91f7377029fa7f0e7341691ff", @@ -254,7 +255,7 @@ "editkin-batch-workflow.md": "90862871cc78b31f28a0d72a1b19add9046f7f72548610cc29a15401b5bc361c", "editkin-mobile-device-binding.md": "41fd756a3a5048b21a38fc80c12d7d7bd36ef637ed27c6189c9428c3858c7108", "editkin-plugin-automation.md": "0d16c004cc89aa8927e791cb73bfd0c375dce3f4c5b3fc156c3613f2de57129d", - "editkin-workflow-execution.md": "e274d1025c0bc38229f3b95d6901dd643dc1c937bc1dd671a5c6ef0272627f34", + "editkin-workflow-execution.md": "296657a72f9bbafc898af82beb040fcd4a1418769ddbba61ed4db1783c349dc3", "editorial-intelligence-contract.md": "74fd64bb3268e47fff26ed9819953eacb1731475f3e5e181b657046740106298", "filter-library.md": "8c7f93740df2fadc6c5a11970d1d16c884cc14c65b7a95fc3f0ff5bc71a98b05", "genre-copy-grammar-2026.md": "ec58fa00ac30fceed4b9cee6b5797dc82ff56947cf1d1830d8df51db8a2860d8", @@ -287,20 +288,20 @@ }, "special": {}, "public_owned_analogue": {}, - "private_count": 7, + "private_count": 8, "private_control_count": 0 } }, - "output_count": 307, + "output_count": 309, "outputs": { - "AUTOPILOT_MANIFEST.json": "9a766e0e4ac3cb363777112a2f7f3c4a9659716a027001663e91fa928ad69f0c", + "AUTOPILOT_MANIFEST.json": "cd4fc77d3f425eae17597759ca7f0eed3adda40044ddd36a1bf03f0a433c1744", "audit.config.json": "493ddb0139a8a3a337c47d6450f8de93fdd5698af20736bb5e468e7395c93c0c", - "codex-skill/video-autopilot/SKILL.md": "64f47ea53128c3afedf41ec5e2c0b17f6b705bac6489c755788a1e22ad157232", + "codex-skill/video-autopilot/SKILL.md": "df1d083c3946b76b109ede561ca82efc20525b5adbbbf69c89d727372efcae16", "codex-skill/video-autopilot/agents/openai.yaml": "0f144cca8ce214d0733f56b8c03d4dec5e1dabce2d1305def3d3f3c3b6c3596b", - "codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json": "3d05d0fe77065f0584c6bcedd190cad4df649187fa8434d3b40407e01f5488f5", + "codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json": "4272cf87b642ae54c6c93bd1c488117440d427077d3ef8e81e708a5c327c8e50", "codex-skill/video-autopilot/design_runtime/knowledge/runtime/design_reference_dna.json": "b65f17f0dda02eddeff1ca3e1e5c62451f02a04923475838a7dc6617fe3a181e", "codex-skill/video-autopilot/design_runtime/src/aesthetic_score.py": "011e65dcd864b955a634b39191622de8dabab43fdc77a681d89f769e6fc41bc9", - "codex-skill/video-autopilot/design_runtime/src/design_system_v6.py": "7ef454ac24fa7846d46796b65422af5e76b679feb6238fe5fe93fdfb4a69b524", + "codex-skill/video-autopilot/design_runtime/src/design_system_v6.py": "d4ce1abf6bb8e4f00932a09d257e34279ceee50beffe418abc911dda321032e4", "codex-skill/video-autopilot/editkin_design_bridge.py": "4dcb2fdad52ae7abc4056e87c112cf24b9e962f3d386bfb737b5959ce281b3b0", "codex-skill/video-autopilot/references/ai-evidence-canvas.md": "00e008517d06aac09284b812973e72184d6f7d2cd8c9de524c47dcaed7722b44", "codex-skill/video-autopilot/references/architecture-foundation-v6-3.md": "d7fbf23da6d6c88c171076f2bee5898fcf9627e99ee92df5658a064f7e4e84fc", @@ -326,7 +327,7 @@ "codex-skill/video-autopilot/references/editkin-batch-workflow.md": "90862871cc78b31f28a0d72a1b19add9046f7f72548610cc29a15401b5bc361c", "codex-skill/video-autopilot/references/editkin-mobile-device-binding.md": "41fd756a3a5048b21a38fc80c12d7d7bd36ef637ed27c6189c9428c3858c7108", "codex-skill/video-autopilot/references/editkin-plugin-automation.md": "0d16c004cc89aa8927e791cb73bfd0c375dce3f4c5b3fc156c3613f2de57129d", - "codex-skill/video-autopilot/references/editkin-workflow-execution.md": "e274d1025c0bc38229f3b95d6901dd643dc1c937bc1dd671a5c6ef0272627f34", + "codex-skill/video-autopilot/references/editkin-workflow-execution.md": "296657a72f9bbafc898af82beb040fcd4a1418769ddbba61ed4db1783c349dc3", "codex-skill/video-autopilot/references/editorial-intelligence-contract.md": "74fd64bb3268e47fff26ed9819953eacb1731475f3e5e181b657046740106298", "codex-skill/video-autopilot/references/filter-library.md": "8c7f93740df2fadc6c5a11970d1d16c884cc14c65b7a95fc3f0ff5bc71a98b05", "codex-skill/video-autopilot/references/genre-copy-grammar-2026.md": "aaed0cc65b6c8155b66e96bf1a9260d2462442dad193160a07d4faf53fe78a00", @@ -338,6 +339,7 @@ "codex-skill/video-autopilot/references/motion-asset-library.md": "8aa00b35c554fd64380e2d7d05b3ed2408786125de1fddd41eed568d7f342c8e", "codex-skill/video-autopilot/references/mrbeast-and-yingshi-benchmark.md": "6be63bf903c1ebd8fd3d2e23fbfde69a0453c23b9b4e417fa5c65c2943a9f080", "codex-skill/video-autopilot/references/mrbeast-production-source-map.md": "465c3350158b30f864c3a402f595c73725b57fdd002216e2e61105e66503d0bd", + "codex-skill/video-autopilot/references/music-video-motion.md": "91a948430e8642881019b87040686f5850b3f27182e1f4467d70119cd745916a", "codex-skill/video-autopilot/references/niche-editing-grammar.md": "f072fe9cd9c525360653724db161bc69cd30618914bcb88691ab430927e0c7c2", "codex-skill/video-autopilot/references/niche-fonts-colors.md": "9a032cee07a4ad60aaf1cfbeb259ead5d4da4d136639513681540bdb0f722664", "codex-skill/video-autopilot/references/open-source-release-and-upgrade.md": "0b04df92034ba1adff0fb6b36542d3b1b0ef16b18eaf8ae3cdd9961be4c07d30", @@ -368,7 +370,7 @@ "codex-skill/video-autopilot/workflow_state.py": "158d6d83dfd3141d6b1d14a0a31dc3382a78689186d1fd36c123f1c35ef229e9", "codex-skill/video-autopilot/workflow_transport.py": "8891d78b1882c4c204f53665eeac3ace568363353577d52da5974749b9e5651e", "docs/AUTOPILOT_ARCHITECTURE_V6.md": "ac5bf534fd255106f95ea41b4f862923b7f061ee9b945ac1287cb3b1dbf24c76", - "knowledge/runtime/aesthetic_standard.json": "3d05d0fe77065f0584c6bcedd190cad4df649187fa8434d3b40407e01f5488f5", + "knowledge/runtime/aesthetic_standard.json": "4272cf87b642ae54c6c93bd1c488117440d427077d3ef8e81e708a5c327c8e50", "knowledge/runtime/asset_license_overrides.json": "8b443854fb341ff4ad4658b1e8e688e350d0df81a75168de14754b17556bf13e", "knowledge/runtime/asset_license_policy.json": "a3e7e4df99fd42918ba65e0f506d03f9ede27de3f2aa7f55ad8831d786524872", "knowledge/runtime/beyblade_x_rules.json": "4eed9df62d0bd833846c0805a6fe6a2e080728f91f7377029fa7f0e7341691ff", @@ -413,7 +415,7 @@ "src/composition_runtime.py": "00dd4c7c4903bdefe4d59f63b39d3afcae911bb7c26e8df0087e5516ef7d5801", "src/context_router.py": "2182f58b88de0097d49b166cce0b05c5243ca69b54c9d9e05e4bf55e7337565e", "src/delivery_media_ops.py": "e820077e7208160884e4e2d0280b1788ef0912feeb525b68b50e4ea3f4051f02", - "src/design_system_v6.py": "7ef454ac24fa7846d46796b65422af5e76b679feb6238fe5fe93fdfb4a69b524", + "src/design_system_v6.py": "d4ce1abf6bb8e4f00932a09d257e34279ceee50beffe418abc911dda321032e4", "src/domain_broll_pack.py": "65169fe6ec4e35325e8f2385051b21627699785f2ee9aa261415e360174578f0", "src/domain_taxonomy.py": "35f0237600695fccdc05ad0f5797a8bd08bbf3186e38f983cc7f8e063ab423af", "src/drama_autopilot.py": "a30ba6fddbd07b778f4425493bb52938270c10242260178924bc3cb0a58d558c", @@ -467,6 +469,7 @@ "src/motion_renderers.py": "d190f28eaa5620c5594bc2ccd9f37ac3171b58b49d1b6f646ea88632a65b1e5f", "src/mrbeast_editing_system.py": "c0c4f70398037ccdc0b5de13e7b6317d19ee4031bbff615dca779588bdf26819", "src/mrbeast_source_map.py": "95c2ab26621b75303764f4e00b35999d7ef02e9c3a41cb8ba38e2845e1ccefee", + "src/music_mv_preflight.py": "7f0366d58c230935276195b1d3f35776dbcca8a68d167842b6e704e0f2da560f", "src/outcome_learning.py": "c0751b9ea3ec88243736c62fc82dac73ce4d1475f6ae7572a524d2f8f55485b8", "src/parallax_transition.py": "ed2a4f0a6cdab683096753104eb1c8e51884875a02a445a725b96cd74b5899fa", "src/platform_compat.py": "331086aa8f8906f7aacbfbfb5d86869451e3c09bdf3208a776fd185acef905c0", @@ -603,9 +606,10 @@ }, "public_owned": { "codex-skill/video-autopilot/editkin_design_bridge.py": "4dcb2fdad52ae7abc4056e87c112cf24b9e962f3d386bfb737b5959ce281b3b0", + "codex-skill/video-autopilot/references/music-video-motion.md": "91a948430e8642881019b87040686f5850b3f27182e1f4467d70119cd745916a", "codex-skill/video-autopilot/design_runtime/src/aesthetic_score.py": "011e65dcd864b955a634b39191622de8dabab43fdc77a681d89f769e6fc41bc9", - "codex-skill/video-autopilot/design_runtime/src/design_system_v6.py": "7ef454ac24fa7846d46796b65422af5e76b679feb6238fe5fe93fdfb4a69b524", - "codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json": "3d05d0fe77065f0584c6bcedd190cad4df649187fa8434d3b40407e01f5488f5", + "codex-skill/video-autopilot/design_runtime/src/design_system_v6.py": "d4ce1abf6bb8e4f00932a09d257e34279ceee50beffe418abc911dda321032e4", + "codex-skill/video-autopilot/design_runtime/knowledge/runtime/aesthetic_standard.json": "4272cf87b642ae54c6c93bd1c488117440d427077d3ef8e81e708a5c327c8e50", "codex-skill/video-autopilot/design_runtime/knowledge/runtime/design_reference_dna.json": "b65f17f0dda02eddeff1ca3e1e5c62451f02a04923475838a7dc6617fe3a181e", "src/editorial_template_fallback.py": "dc37d0d28ffa3819f18f482d6822e3d382cfd205ee882e55b23980299b39b2e6", "src/interview_autopilot.py": "fba92b1da0a14fc72a7c92eadbc085eba8a24d702a54dfe1afd58af32844e1c9", @@ -663,6 +667,7 @@ "codex-skill/video-autopilot/references/motion-asset-library.md", "codex-skill/video-autopilot/references/mrbeast-and-yingshi-benchmark.md", "codex-skill/video-autopilot/references/mrbeast-production-source-map.md", + "codex-skill/video-autopilot/references/music-video-motion.md", "codex-skill/video-autopilot/references/niche-editing-grammar.md", "codex-skill/video-autopilot/references/niche-fonts-colors.md", "codex-skill/video-autopilot/references/open-source-release-and-upgrade.md", @@ -791,6 +796,7 @@ "src/motion_renderers.py", "src/mrbeast_editing_system.py", "src/mrbeast_source_map.py", + "src/music_mv_preflight.py", "src/outcome_learning.py", "src/parallax_transition.py", "src/platform_compat.py",