@oh-story/dsh 0.1.7 → 0.1.9
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.
- package/README.md +30 -15
- package/lib/client.js +93 -16
- package/lib/client.js.map +2 -2
- package/lib/drama/manifest.json +165 -69
- package/lib/drama/skills/short-drama/SKILL.md +5 -1
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +126 -9
- package/lib/drama/skills/short-drama/scripts/project_tool.py +11 -0
- package/lib/drama/skills/short-drama-assets/references/character-and-look.md +18 -0
- package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +10 -1
- package/lib/drama/skills/short-drama-edit/SKILL.md +148 -0
- package/lib/drama/skills/short-drama-edit/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +60 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +15 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/remotion.config.ts +6 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +26 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +88 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +46 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/index.ts +4 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +32 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +13 -0
- package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +43 -0
- package/lib/drama/skills/short-drama-edit/references/cut-craft.md +81 -0
- package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +58 -0
- package/lib/drama/skills/short-drama-edit/references/generated-footage.md +96 -0
- package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +113 -0
- package/lib/drama/skills/short-drama-edit/references/stage-contract.md +55 -0
- package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1041 -0
- package/lib/drama/skills/short-drama-edit/scripts/selftest.py +456 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/image-prompts.md +5 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-prompts.md +3 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +2 -2
- package/lib/drama/skills/short-drama-novel-analyze/references/chapter-extraction.md +4 -1
- package/lib/drama/skills/short-drama-produce/SKILL.md +24 -3
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +28 -0
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +24 -5
- package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +7 -0
- package/lib/drama/skills/short-drama-produce/scripts/fixture_adapter.py +18 -1
- package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +181 -2
- package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +57 -2
- package/lib/drama/skills/short-drama-review/SKILL.md +3 -0
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +20 -0
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +36 -0
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +7 -0
- package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +4 -0
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +2 -0
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +7 -1
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +101 -6
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +7 -1
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +35 -0
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +3 -1
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +13 -3
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +35 -4
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +1 -1
- package/lib/drama/skills/short-drama-write/SKILL.md +13 -2
- package/lib/drama/skills/short-drama-write/references/screenplay-format.md +6 -0
- package/lib/drama/skills/short-drama-write/references/stage-contract.md +1 -0
- package/lib/index.js +4 -2
- package/lib/index.js.map +2 -2
- package/lib/novel-to-game/VERSION +1 -1
- package/lib/novel-to-game/manifest.json +28 -28
- package/lib/novel-to-game/skills/game-art-direction/SKILL.md +6 -27
- package/lib/novel-to-game/skills/game-build/SKILL.md +12 -29
- package/lib/novel-to-game/skills/game-concept/SKILL.md +10 -26
- package/lib/novel-to-game/skills/game-qa/SKILL.md +5 -15
- package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +1 -1
- package/lib/novel-to-game/skills/game-world-design/SKILL.md +19 -28
- package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +1 -2
- package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +6 -9
- package/lib/novel-to-game/skills/novel-to-game/SKILL.md +6 -11
- package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -4
- package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +1 -3
- package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +3 -5
- package/lib/oh-story/manifest.json +292 -172
- package/lib/oh-story/roles/character-designer.md +1 -1
- package/lib/oh-story/roles/narrative-writer.md +56 -242
- package/lib/oh-story/roles/story-architect.md +1 -1
- package/lib/oh-story/skills/story/SKILL.md +1 -1
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-deslop/SKILL.md +20 -182
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-deslop/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +154 -0
- package/lib/oh-story/skills/story-deslop/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-deslop/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-deslop/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-deslop/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-import/SKILL.md +2 -2
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +2 -2
- package/lib/oh-story/skills/story-import/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +2 -29
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +176 -12
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +1 -1
- package/lib/oh-story/skills/story-long-write/SKILL.md +20 -193
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +62 -7
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-long-write/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +20 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/long-format.md +2 -0
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +2 -0
- package/lib/oh-story/skills/story-long-write/references/project-files.md +108 -0
- package/lib/oh-story/skills/story-long-write/references/reference-index.md +87 -0
- package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/style-craft.md +9 -29
- package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +2 -29
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +51 -52
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +8 -7
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +36 -15
- package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +22 -0
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +69 -2
- package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +410 -0
- package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-long-write/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +176 -12
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +90 -23
- package/lib/oh-story/skills/story-long-write/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +283 -0
- package/lib/oh-story/skills/story-long-write/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-review/SKILL.md +13 -3
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-review/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-review/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-review/references/review-quality.md +2 -2
- package/lib/oh-story/skills/story-review/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-review/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +2 -29
- package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-review/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-review/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-review/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-setup/SKILL.md +17 -10
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +154 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +69 -2
- package/lib/oh-story/skills/story-setup/references/diagnostics.md +38 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-writing-techniques.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +2 -2
- package/lib/oh-story/skills/story-short-write/SKILL.md +18 -186
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-short-write/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +60 -0
- package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//344/270/226/346/203/205/346/211/223/350/204/270.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/244/215/344/273/207/346/211/223/350/204/270.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/256/205/346/226/227/345/256/253/346/226/227.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/200/273/350/243/201/350/261/252/351/227/250.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +5 -5
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/260/221/344/277/227/346/200/252/350/260/210.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +5 -5
- package/lib/oh-story/skills/story-short-write/references/genre-styles//350/277/275/345/246/273/347/201/253/350/221/254/345/234/272.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/reference-index.md +53 -0
- package/lib/oh-story/skills/story-short-write/references/short-craft.md +12 -14
- package/lib/oh-story/skills/story-short-write/references/short-deslop.md +10 -10
- package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -1
- package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-design.md +77 -0
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +5 -5
- package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-short-write/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +34 -5
- package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +90 -23
- package/lib/oh-story/skills/story-short-write/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-short-write/scripts/style-whitelist.js +39 -0
- package/lib/types/client/drama-production-view.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/production-prompts.d.ts.map +1 -1
- package/lib/types/client/production-runtime.d.ts +17 -0
- package/lib/types/client/production-runtime.d.ts.map +1 -1
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/lib/video-recap/CHANGELOG.md +31 -1
- package/lib/video-recap/manifest.json +162 -162
- package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +4 -9
- package/lib/video-recap/skills/video-assemble/scripts/assemble.py +47 -60
- package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +77 -115
- package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +41 -40
- package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +22 -32
- package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +102 -192
- package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +14 -35
- package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +14 -12
- package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +8 -9
- package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +3 -14
- package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +23 -12
- package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +1 -4
- package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +24 -25
- package/lib/video-recap/skills/video-assemble/scripts/lib.py +31 -85
- package/lib/video-recap/skills/video-assemble/scripts/media.py +100 -144
- package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +101 -195
- package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +10 -21
- package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +90 -169
- package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +69 -122
- package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +10 -17
- package/lib/video-recap/skills/video-assemble/scripts/timeline.py +33 -48
- package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +14 -20
- package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +135 -213
- package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +49 -57
- package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +38 -74
- package/lib/video-recap/skills/video-cut/scripts/cut_render.py +46 -95
- package/lib/video-recap/skills/video-cut/scripts/lib.py +23 -25
- package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +70 -173
- package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +28 -53
- package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +162 -322
- package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +6 -7
- package/lib/video-recap/skills/video-recap/scripts/doctor.py +104 -124
- package/lib/video-recap/skills/video-recap/scripts/final_qc.py +255 -412
- package/lib/video-recap/skills/video-recap/scripts/lib.py +30 -52
- package/lib/video-recap/skills/video-recap/scripts/materials.py +97 -120
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +7 -12
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +46 -97
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +18 -36
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +29 -47
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +43 -76
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +2 -1
- package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +2 -1
- package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +2 -2
- package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +129 -145
- package/lib/video-recap/skills/video-recap/scripts/recap_review.py +27 -20
- package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +20 -31
- package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +31 -106
- package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +43 -113
- package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +196 -377
- package/lib/video-recap/skills/video-script/scripts/agent_brief.py +1 -1
- package/lib/video-recap/skills/video-script/scripts/agent_text.py +63 -172
- package/lib/video-recap/skills/video-script/scripts/brief_context.py +80 -135
- package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +125 -167
- package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +93 -208
- package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +20 -46
- package/lib/video-recap/skills/video-script/scripts/lib.py +30 -26
- package/lib/video-recap/skills/video-script/scripts/narration_lint.py +145 -140
- package/lib/video-recap/skills/video-script/scripts/review_response.py +12 -42
- package/lib/video-recap/skills/video-script/scripts/review_runner.py +0 -6
- package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +39 -100
- package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +33 -124
- package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +1 -1
- package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +63 -172
- package/lib/video-recap/skills/video-understanding/scripts/asr.py +1 -2
- package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +80 -135
- package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +125 -167
- package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +93 -208
- package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +1 -1
- package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +20 -46
- package/lib/video-recap/skills/video-understanding/scripts/lib.py +31 -26
- package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +145 -140
- package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +39 -100
- package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +33 -124
- package/lib/video-recap/skills/video-understanding/scripts/vlm.py +1 -4
- package/lib/video-recap/skills/video-voiceover/scripts/dub.py +7 -13
- package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +12 -30
- package/lib/video-recap/skills/video-voiceover/scripts/lib.py +98 -131
- package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +17 -28
- package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +151 -240
- package/package.json +41 -41
|
@@ -1,33 +1,14 @@
|
|
|
1
1
|
"""Validate optional ASR, MiMo, and stage-status inputs for the brief."""
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
|
-
|
|
5
|
-
import importlib.util
|
|
6
|
-
|
|
7
|
-
|
|
8
4
|
import json
|
|
9
|
-
|
|
10
|
-
|
|
11
5
|
from pathlib import Path
|
|
12
6
|
|
|
13
7
|
from lib import CONFIG, file_fingerprint, stable_hash
|
|
14
|
-
|
|
15
|
-
|
|
16
8
|
from brief_context import _clean_asr_prompt_fingerprint, _consolidation_model
|
|
17
9
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
except ModuleNotFoundError:
|
|
21
|
-
_deslop_qc_path = Path(__file__).with_name("deslop_qc.py")
|
|
22
|
-
_deslop_qc_spec = importlib.util.spec_from_file_location(
|
|
23
|
-
"deslop_qc", _deslop_qc_path
|
|
24
|
-
)
|
|
25
|
-
if _deslop_qc_spec is None or _deslop_qc_spec.loader is None:
|
|
26
|
-
raise
|
|
27
|
-
_deslop_qc_module = importlib.util.module_from_spec(_deslop_qc_spec)
|
|
28
|
-
_deslop_qc_spec.loader.exec_module(_deslop_qc_module)
|
|
29
|
-
analyze_deslop_qc = _deslop_qc_module.analyze_deslop_qc
|
|
30
|
-
|
|
10
|
+
# Shared with consolidate.py, which this byte-identical copy cannot import (the sibling
|
|
11
|
+
# skill ships no consolidate.py). Keep both literals in sync.
|
|
31
12
|
_ASR_SPAN_TOL = 0.05
|
|
32
13
|
|
|
33
14
|
_MIMO_REJECTION_MARKERS = (
|
|
@@ -42,67 +23,61 @@ _MIMO_REJECTION_MARKERS = (
|
|
|
42
23
|
)
|
|
43
24
|
|
|
44
25
|
|
|
45
|
-
def _clean_asr_fresh(out_path, source_path):
|
|
46
|
-
# Local freshness check kept inline so the separately shipped byte-identical copy
|
|
47
|
-
# stays self-contained and in lockstep.
|
|
48
|
-
try:
|
|
49
|
-
return (
|
|
50
|
-
out_path.exists()
|
|
51
|
-
and source_path.exists()
|
|
52
|
-
and (out_path.stat().st_mtime >= source_path.stat().st_mtime)
|
|
53
|
-
)
|
|
54
|
-
except OSError:
|
|
55
|
-
return False
|
|
56
|
-
|
|
57
|
-
|
|
58
26
|
def _load_clean_asr(work_dir, asr_result):
|
|
59
27
|
"""Return consolidate.py's cleaned ASR segments, or None to fall back to raw asr_result.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
28
|
+
|
|
29
|
+
Accepted only when the file is at least as fresh as asr_result.json, its provenance
|
|
30
|
+
(source_md5 / model / prompt_md5) matches, and every segment keeps its original span
|
|
31
|
+
within _ASR_SPAN_TOL."""
|
|
32
|
+
if not asr_result:
|
|
64
33
|
return None
|
|
65
34
|
work_dir = Path(work_dir)
|
|
66
35
|
clean_path = work_dir / "asr_clean.json"
|
|
67
36
|
src_path = work_dir / "asr_result.json"
|
|
68
|
-
|
|
37
|
+
try:
|
|
38
|
+
fresh = (
|
|
39
|
+
clean_path.exists()
|
|
40
|
+
and clean_path.stat().st_mtime >= src_path.stat().st_mtime
|
|
41
|
+
)
|
|
42
|
+
except OSError:
|
|
43
|
+
return None
|
|
44
|
+
if not fresh:
|
|
69
45
|
return None
|
|
70
46
|
try:
|
|
71
47
|
payload = json.loads(clean_path.read_text(encoding="utf-8"))
|
|
72
|
-
|
|
48
|
+
source_md5 = hashlib.md5(src_path.read_bytes()).hexdigest()
|
|
49
|
+
except (OSError, json.JSONDecodeError):
|
|
73
50
|
return None
|
|
74
51
|
if not isinstance(payload, dict):
|
|
75
52
|
return None
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
except OSError:
|
|
83
|
-
return None
|
|
84
|
-
if payload.get("model") != _consolidation_model():
|
|
53
|
+
provenance = {
|
|
54
|
+
"source_md5": source_md5,
|
|
55
|
+
"model": _consolidation_model(),
|
|
56
|
+
"prompt_md5": _clean_asr_prompt_fingerprint(),
|
|
57
|
+
}
|
|
58
|
+
if not payload.items() >= provenance.items():
|
|
85
59
|
return None
|
|
86
|
-
|
|
60
|
+
segments = payload.get("segments")
|
|
61
|
+
if not isinstance(segments, list) or len(segments) != len(asr_result):
|
|
87
62
|
return None
|
|
88
|
-
for orig, clean in zip(
|
|
89
|
-
if
|
|
63
|
+
for orig, clean in zip(asr_result, segments):
|
|
64
|
+
if (
|
|
65
|
+
not isinstance(clean, dict)
|
|
66
|
+
or not isinstance(clean.get("start"), (int, float))
|
|
67
|
+
or not isinstance(clean.get("end"), (int, float))
|
|
68
|
+
):
|
|
90
69
|
return None
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
):
|
|
96
|
-
return None
|
|
97
|
-
if abs(float(clean.get("end")) - float(orig.get("end"))) > _ASR_SPAN_TOL:
|
|
98
|
-
return None
|
|
99
|
-
except (TypeError, ValueError):
|
|
70
|
+
if (
|
|
71
|
+
abs(clean["start"] - orig["start"]) > _ASR_SPAN_TOL
|
|
72
|
+
or abs(clean["end"] - orig["end"]) > _ASR_SPAN_TOL
|
|
73
|
+
):
|
|
100
74
|
return None
|
|
101
75
|
return segments
|
|
102
76
|
|
|
103
77
|
|
|
104
78
|
def _is_mimo_chunk_usable(content):
|
|
105
|
-
|
|
79
|
+
"""A chunk is usable only if MiMo returned real analysis (not empty / a moderation refusal)."""
|
|
80
|
+
text = (content or "").strip()
|
|
106
81
|
if not text:
|
|
107
82
|
return False
|
|
108
83
|
low = text.lower()
|
|
@@ -110,28 +85,23 @@ def _is_mimo_chunk_usable(content):
|
|
|
110
85
|
|
|
111
86
|
|
|
112
87
|
def _mimo_video_settings_fingerprint():
|
|
88
|
+
"""Non-secret MiMo video-overview settings that affect generated content."""
|
|
113
89
|
return {
|
|
114
|
-
"model": CONFIG
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
"mimo_video_chunk_min_seconds": CONFIG.get("mimo_video_chunk_min_seconds", 1.0),
|
|
124
|
-
"mimo_video_base64_max_mb": CONFIG.get("mimo_video_base64_max_mb", 45.0),
|
|
125
|
-
"mimo_video_prompt": CONFIG.get("mimo_video_prompt", ""),
|
|
126
|
-
"mimo_disable_thinking": CONFIG.get("mimo_disable_thinking", True),
|
|
90
|
+
"model": CONFIG["mimo_video_model"],
|
|
91
|
+
"mimo_video_api_url": CONFIG["mimo_video_api_url"],
|
|
92
|
+
"mimo_video_fps": CONFIG["mimo_video_fps"],
|
|
93
|
+
"mimo_media_resolution": CONFIG["mimo_media_resolution"],
|
|
94
|
+
"mimo_video_chunk_max_seconds": CONFIG["mimo_video_chunk_max_seconds"],
|
|
95
|
+
"mimo_video_chunk_min_seconds": CONFIG["mimo_video_chunk_min_seconds"],
|
|
96
|
+
"mimo_video_base64_max_mb": CONFIG["mimo_video_base64_max_mb"],
|
|
97
|
+
"mimo_video_prompt": CONFIG["mimo_video_prompt"],
|
|
98
|
+
"mimo_disable_thinking": CONFIG["mimo_disable_thinking"],
|
|
127
99
|
}
|
|
128
100
|
|
|
129
101
|
|
|
130
102
|
def _mimo_chunk_cache_key(chunk):
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
f"{float(chunk['start']):.3f}-{float(chunk['end']):.3f}"
|
|
134
|
-
)
|
|
103
|
+
"""Stable identifier for a MiMo chunk (index + scene span) for partial-cache reuse."""
|
|
104
|
+
return f"{chunk['chunk_id']}|{chunk['scene_id']}|{chunk['start']:.3f}-{chunk['end']:.3f}"
|
|
135
105
|
|
|
136
106
|
|
|
137
107
|
def _mimo_cached_chunks_fingerprint(done):
|
|
@@ -144,48 +114,48 @@ def _mimo_overview_payload_fingerprint(overview):
|
|
|
144
114
|
return stable_hash(payload)
|
|
145
115
|
|
|
146
116
|
|
|
147
|
-
def
|
|
148
|
-
|
|
149
|
-
|
|
117
|
+
def _mimo_video_chunks(scenes):
|
|
118
|
+
"""Split scene spans into MiMo video chunks. scenes.json rows carry no scene_id, so the
|
|
119
|
+
row index stands in for it there."""
|
|
120
|
+
max_seconds = CONFIG["mimo_video_chunk_max_seconds"]
|
|
121
|
+
min_seconds = CONFIG["mimo_video_chunk_min_seconds"]
|
|
150
122
|
chunks = []
|
|
151
|
-
for scene_index, scene in enumerate(scenes
|
|
152
|
-
|
|
153
|
-
continue
|
|
154
|
-
try:
|
|
155
|
-
start = float(scene.get("start", 0.0))
|
|
156
|
-
end = float(scene.get("end", start))
|
|
157
|
-
except (TypeError, ValueError):
|
|
158
|
-
continue
|
|
159
|
-
if end <= start:
|
|
160
|
-
continue
|
|
123
|
+
for scene_index, scene in enumerate(scenes):
|
|
124
|
+
start, end = scene["start"], scene["end"]
|
|
161
125
|
scene_id = scene.get("scene_id", scene_index)
|
|
162
126
|
cursor = start
|
|
163
127
|
while cursor < end:
|
|
164
128
|
chunk_end = min(end, cursor + max_seconds)
|
|
165
129
|
if end - chunk_end < min_seconds and chunk_end < end:
|
|
166
130
|
chunk_end = end
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
131
|
+
chunks.append(
|
|
132
|
+
{
|
|
133
|
+
"chunk_id": len(chunks),
|
|
134
|
+
"scene_id": scene_id,
|
|
135
|
+
"start": round(cursor, 3),
|
|
136
|
+
"end": round(chunk_end, 3),
|
|
137
|
+
}
|
|
138
|
+
)
|
|
176
139
|
cursor = chunk_end
|
|
177
140
|
return chunks
|
|
178
141
|
|
|
179
142
|
|
|
180
|
-
def _mimo_overview_matches_current_inputs(overview,
|
|
143
|
+
def _mimo_overview_matches_current_inputs(overview, scenes, video_path=None):
|
|
144
|
+
"""True only when mimo_video_overview.json was produced from the current settings,
|
|
145
|
+
source video and scene plan, and none of its chunks was moderation-rejected.
|
|
146
|
+
Provenance keys are read with .get: a stale or partial file simply does not match."""
|
|
181
147
|
if not isinstance(overview, dict) or overview.get("input") != "scene_chunks":
|
|
182
148
|
return False
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
149
|
+
settings = _mimo_video_settings_fingerprint()
|
|
150
|
+
expected_keys = [
|
|
151
|
+
_mimo_chunk_cache_key(chunk) for chunk in _mimo_video_chunks(scenes)
|
|
152
|
+
]
|
|
153
|
+
chunks = overview.get("chunks")
|
|
154
|
+
if not isinstance(chunks, list) or not all(
|
|
155
|
+
isinstance(chunk, dict)
|
|
156
|
+
and isinstance(chunk.get("content"), str)
|
|
157
|
+
and _is_mimo_chunk_usable(chunk["content"])
|
|
158
|
+
for chunk in chunks
|
|
189
159
|
):
|
|
190
160
|
return False
|
|
191
161
|
if video_path is not None:
|
|
@@ -194,73 +164,60 @@ def _mimo_overview_matches_current_inputs(overview, scenes_analysis, video_path=
|
|
|
194
164
|
return False
|
|
195
165
|
except OSError:
|
|
196
166
|
return False
|
|
197
|
-
chunks = overview.get("chunks")
|
|
198
|
-
if not isinstance(chunks, list) or not all(
|
|
199
|
-
isinstance(chunk, dict) and _is_mimo_chunk_usable(chunk.get("content"))
|
|
200
|
-
for chunk in chunks
|
|
201
|
-
):
|
|
202
|
-
return False
|
|
203
|
-
chunks_fingerprint = overview.get("chunks_fingerprint")
|
|
204
|
-
if not chunks_fingerprint or chunks_fingerprint != _mimo_cached_chunks_fingerprint(
|
|
205
|
-
chunks
|
|
206
|
-
):
|
|
207
|
-
return False
|
|
208
|
-
expected_chunks = _mimo_video_chunks_for_brief(scenes_analysis)
|
|
209
|
-
if not expected_chunks or len(chunks) != len(expected_chunks):
|
|
210
|
-
return False
|
|
211
167
|
try:
|
|
212
168
|
cached_keys = [_mimo_chunk_cache_key(chunk) for chunk in chunks]
|
|
213
|
-
expected_keys = [_mimo_chunk_cache_key(chunk) for chunk in expected_chunks]
|
|
214
169
|
except (KeyError, TypeError, ValueError):
|
|
215
170
|
return False
|
|
216
|
-
return
|
|
171
|
+
return (
|
|
172
|
+
overview.get("settings") == settings
|
|
173
|
+
and overview.get("overview_fingerprint")
|
|
174
|
+
== _mimo_overview_payload_fingerprint(overview)
|
|
175
|
+
and overview.get("chunks_fingerprint")
|
|
176
|
+
== _mimo_cached_chunks_fingerprint(chunks)
|
|
177
|
+
and cached_keys == expected_keys
|
|
178
|
+
)
|
|
217
179
|
|
|
218
180
|
|
|
219
|
-
def _load_mimo_overview_for_brief(
|
|
220
|
-
|
|
221
|
-
):
|
|
222
|
-
|
|
223
|
-
CONFIG.get("mimo_video_overview", False) if enabled is None else enabled
|
|
224
|
-
)
|
|
225
|
-
if not overview_enabled:
|
|
226
|
-
return {}
|
|
181
|
+
def _load_mimo_overview_for_brief(work_dir, scenes, enabled=None, video_path=None):
|
|
182
|
+
"""The current MiMo overview for the brief, or None when disabled, absent or stale."""
|
|
183
|
+
if not (CONFIG["mimo_video_overview"] if enabled is None else enabled):
|
|
184
|
+
return None
|
|
227
185
|
path = Path(work_dir) / "mimo_video_overview.json"
|
|
228
186
|
if not path.exists():
|
|
229
|
-
return
|
|
187
|
+
return None
|
|
230
188
|
try:
|
|
231
189
|
overview = json.loads(path.read_text(encoding="utf-8"))
|
|
232
|
-
except (json.JSONDecodeError
|
|
233
|
-
return
|
|
234
|
-
|
|
235
|
-
overview
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
else {}
|
|
240
|
-
)
|
|
190
|
+
except (OSError, json.JSONDecodeError):
|
|
191
|
+
return None
|
|
192
|
+
if not _mimo_overview_matches_current_inputs(
|
|
193
|
+
overview, scenes, video_path=video_path
|
|
194
|
+
):
|
|
195
|
+
return None
|
|
196
|
+
return overview
|
|
241
197
|
|
|
242
198
|
|
|
243
199
|
def _load_optional_stage_status(work_dir, filename):
|
|
244
|
-
"""
|
|
200
|
+
"""Optional-stage status sidecar, or None when the stage never ran."""
|
|
245
201
|
path = Path(work_dir) / filename
|
|
246
202
|
if not path.exists():
|
|
247
|
-
return
|
|
203
|
+
return None
|
|
248
204
|
try:
|
|
249
|
-
|
|
250
|
-
except (json.JSONDecodeError
|
|
251
|
-
return
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
205
|
+
status = json.loads(path.read_text(encoding="utf-8"))
|
|
206
|
+
except (OSError, json.JSONDecodeError):
|
|
207
|
+
return None
|
|
208
|
+
if not (
|
|
209
|
+
isinstance(status, dict)
|
|
210
|
+
and isinstance(status.get("enabled"), bool)
|
|
211
|
+
and isinstance(status.get("status"), str)
|
|
212
|
+
and isinstance(status.get("message"), str)
|
|
213
|
+
):
|
|
214
|
+
return None
|
|
215
|
+
return status
|
|
258
216
|
|
|
259
217
|
|
|
260
218
|
def _optional_stage_warning(stage, status, message):
|
|
261
219
|
line = f"- {stage}: {status}"
|
|
262
|
-
|
|
263
|
-
return f"{line} — {msg}" if msg else line
|
|
220
|
+
return f"{line} — {message[:180]}" if message else line
|
|
264
221
|
|
|
265
222
|
|
|
266
223
|
def _format_optional_stage_warnings(
|
|
@@ -275,22 +232,23 @@ def _format_optional_stage_warnings(
|
|
|
275
232
|
warnings = []
|
|
276
233
|
|
|
277
234
|
overview_enabled = (
|
|
278
|
-
|
|
235
|
+
CONFIG["mimo_video_overview"]
|
|
279
236
|
if mimo_overview_enabled is None
|
|
280
|
-
else
|
|
237
|
+
else mimo_overview_enabled
|
|
281
238
|
)
|
|
282
239
|
overview_status = _load_optional_stage_status(
|
|
283
240
|
work_dir, "mimo_video_overview.status.json"
|
|
284
241
|
)
|
|
285
|
-
if
|
|
286
|
-
|
|
287
|
-
"
|
|
288
|
-
|
|
242
|
+
if (
|
|
243
|
+
overview_status is not None
|
|
244
|
+
and overview_status["enabled"]
|
|
245
|
+
and overview_status["status"] in {"failed", "skipped_no_key"}
|
|
246
|
+
):
|
|
289
247
|
warnings.append(
|
|
290
248
|
_optional_stage_warning(
|
|
291
249
|
"mimo_video_overview",
|
|
292
|
-
overview_status
|
|
293
|
-
overview_status
|
|
250
|
+
overview_status["status"],
|
|
251
|
+
overview_status["message"],
|
|
294
252
|
)
|
|
295
253
|
)
|
|
296
254
|
elif overview_enabled and not mimo_overview:
|
|
@@ -305,14 +263,14 @@ def _format_optional_stage_warnings(
|
|
|
305
263
|
consolidation_status = _load_optional_stage_status(
|
|
306
264
|
work_dir, "consolidation.status.json"
|
|
307
265
|
)
|
|
308
|
-
if consolidation_status
|
|
309
|
-
if consolidation_status
|
|
266
|
+
if consolidation_status is not None and consolidation_status["enabled"]:
|
|
267
|
+
if consolidation_status["status"] == "failed":
|
|
310
268
|
warnings.append(
|
|
311
269
|
_optional_stage_warning(
|
|
312
|
-
"consolidation", "failed", consolidation_status
|
|
270
|
+
"consolidation", "failed", consolidation_status["message"]
|
|
313
271
|
)
|
|
314
272
|
)
|
|
315
|
-
elif consolidation_status.get("do_index") and not consolidation_index:
|
|
273
|
+
elif consolidation_status.get("do_index") is True and not consolidation_index:
|
|
316
274
|
warnings.append(
|
|
317
275
|
_optional_stage_warning(
|
|
318
276
|
"consolidation",
|