@oh-story/dsh 0.1.9 → 0.1.11
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 +14 -14
- package/lib/client.js +209 -73
- package/lib/client.js.map +3 -3
- package/lib/drama/manifest.json +248 -168
- package/lib/drama/skills/short-drama/SKILL.md +16 -4
- package/lib/drama/skills/short-drama/assets/project-template/short-drama.json +3 -0
- package/lib/drama/skills/short-drama/references/creator-documents.md +3 -0
- package/lib/drama/skills/short-drama/references/knowhow-index.md +15 -0
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +14 -0
- package/lib/drama/skills/short-drama/scripts/project_tool.py +131 -0
- package/lib/drama/skills/short-drama-assets/SKILL.md +2 -1
- package/lib/drama/skills/short-drama-assets/references/asset-review-checklist.md +2 -0
- package/lib/drama/skills/short-drama-assets/references/character-and-look.md +10 -0
- package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +6 -9
- package/lib/drama/skills/short-drama-assets/references/era-anchors.md +37 -0
- package/lib/drama/skills/short-drama-assets/references/stage-contract.md +2 -0
- package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
- package/lib/drama/skills/short-drama-develop/SKILL.md +10 -4
- package/lib/drama/skills/short-drama-develop/assets/adaptation-map.example.jsonl +1 -1
- package/lib/drama/skills/short-drama-develop/assets/creative-brief.md +8 -0
- package/lib/drama/skills/short-drama-develop/references/adaptation-craft.md +80 -13
- package/lib/drama/skills/short-drama-develop/references/episode-design.md +95 -12
- package/lib/drama/skills/short-drama-develop/references/genre-and-hook-playbook.md +9 -5
- package/lib/drama/skills/short-drama-develop/references/genre-cards//345/244/215/344/273/207/346/211/223/350/204/270.md +1 -1
- package/lib/drama/skills/short-drama-develop/references/genre-cards//347/263/273/347/273/237/346/265/201.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//351/200/206/350/242/255.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//351/207/215/347/224/237/347/251/277/350/266/212.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards.md +10 -7
- package/lib/drama/skills/short-drama-develop/references/premise-devices.md +15 -9
- package/lib/drama/skills/short-drama-develop/references/serial-character-and-memory.md +3 -2
- package/lib/drama/skills/short-drama-develop/references/stage-contract.md +14 -7
- package/lib/drama/skills/short-drama-develop/references/story-craft.md +7 -3
- package/lib/drama/skills/short-drama-edit/SKILL.md +65 -44
- package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +49 -13
- package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +4 -2
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Overlay.tsx +31 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +5 -5
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +68 -69
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +39 -29
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/rules.mjs +188 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +26 -13
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/Card.tsx +72 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/CornerChip.tsx +39 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/ScreenText.tsx +36 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/SystemPanel.tsx +44 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/TaskPanel.tsx +100 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/chrome.tsx +197 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/tokens.ts +62 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +1 -0
- package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +6 -4
- package/lib/drama/skills/short-drama-edit/references/cut-craft.md +26 -67
- package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +31 -56
- package/lib/drama/skills/short-drama-edit/references/generated-footage.md +42 -78
- package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +44 -92
- package/lib/drama/skills/short-drama-edit/references/stage-contract.md +14 -16
- package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1272 -125
- package/lib/drama/skills/short-drama-edit/scripts/selftest.py +113 -9
- package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -0
- package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +11 -0
- package/lib/drama/skills/short-drama-novel-analyze/SKILL.md +3 -3
- package/lib/drama/skills/short-drama-novel-analyze/assets/episode-candidate.example.jsonl +2 -2
- package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-triage.md +8 -4
- package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-value.md +10 -3
- package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +25 -1
- package/lib/drama/skills/short-drama-novel-analyze/references/stage-contract.md +1 -0
- package/lib/drama/skills/short-drama-produce/SKILL.md +5 -1
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +14 -20
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +8 -26
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
- package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +142 -1
- package/lib/drama/skills/short-drama-review/SKILL.md +4 -5
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +6 -19
- package/lib/drama/skills/short-drama-review/references/review-method.md +6 -1
- package/lib/drama/skills/short-drama-review/references/rubric-assets-prompts.md +11 -0
- package/lib/drama/skills/short-drama-review/references/rubric-story-script.md +77 -3
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +24 -35
- package/lib/drama/skills/short-drama-review/references/stage-contract.md +3 -0
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +23 -11
- package/lib/drama/skills/short-drama-storyboard/references/blocking-playbooks.md +1 -1
- package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +2 -2
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +139 -34
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +5 -3
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +15 -12
- package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +29 -0
- package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +4 -5
- package/lib/drama/skills/short-drama-video-prompts/references/generability.md +4 -2
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +52 -39
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +24 -21
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +9 -23
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +14 -26
- package/lib/drama/skills/short-drama-video-prompts/references/review-and-fixtures.md +1 -1
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +2 -3
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +34 -9
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +3 -2
- package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +8 -1
- package/lib/drama/skills/short-drama-video-prompts/references/wan-3.0.md +103 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/motion_timing_check.py +8 -7
- package/lib/drama/skills/short-drama-write/SKILL.md +10 -7
- package/lib/drama/skills/short-drama-write/references/dialogue-craft.md +1 -1
- package/lib/drama/skills/short-drama-write/references/script-craft.md +56 -3
- package/lib/drama/skills/short-drama-write/references/stage-contract.md +4 -0
- package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +48 -2
- package/lib/index.js +346 -98
- package/lib/index.js.map +4 -4
- package/lib/novel-to-game/README.md +299 -59
- package/lib/novel-to-game/README_ZH.md +299 -56
- package/lib/novel-to-game/VERSION +1 -1
- package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +3 -1
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +11 -3
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +397 -8
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +0 -31
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +71 -73
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +78 -89
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +37 -14
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +5 -5
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -1
- package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +11 -16
- package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +11 -11
- package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +23 -0
- package/lib/novel-to-game/manifest.json +77 -87
- package/lib/novel-to-game/skills/game-art-direction/SKILL.md +7 -12
- package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +27 -106
- package/lib/novel-to-game/skills/game-build/SKILL.md +13 -14
- package/lib/novel-to-game/skills/game-build/references/blender-asset-workflow.md +24 -0
- package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +45 -82
- package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +14 -45
- package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +30 -65
- package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +13 -27
- package/lib/novel-to-game/skills/game-concept/SKILL.md +13 -15
- package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
- package/lib/novel-to-game/skills/game-qa/SKILL.md +6 -7
- package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +9 -5
- package/lib/novel-to-game/skills/game-world-design/SKILL.md +12 -16
- package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +23 -72
- package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +14 -48
- package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +36 -103
- package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +4 -10
- package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +4 -4
- package/lib/novel-to-game/skills/novel-to-game/SKILL.md +9 -21
- package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -4
- package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +5 -8
- package/lib/oh-story/manifest.json +607 -327
- package/lib/oh-story/roles/chapter-extractor.md +177 -237
- package/lib/oh-story/roles/character-designer.md +1 -2
- package/lib/oh-story/roles/consistency-checker.md +15 -13
- package/lib/oh-story/roles/narrative-writer.md +36 -38
- package/lib/oh-story/roles/story-architect.md +9 -61
- package/lib/oh-story/roles/story-explorer.md +20 -125
- package/lib/oh-story/roles/story-researcher.md +0 -1
- package/lib/oh-story/skills/story/SKILL.md +15 -9
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-cover/SKILL.md +10 -1
- package/lib/oh-story/skills/story-deslop/SKILL.md +59 -73
- package/lib/oh-story/skills/story-deslop/references/agent-calls.md +5 -0
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-deslop/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-deslop/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +22 -5
- package/lib/oh-story/skills/story-deslop/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-import/SKILL.md +64 -584
- package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
- package/lib/oh-story/skills/story-import/references/deep-analysis.md +47 -0
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +1 -1
- package/lib/oh-story/skills/story-import/references/import-report.md +64 -0
- package/lib/oh-story/skills/story-import/references/import-special-cases.md +34 -0
- package/lib/oh-story/skills/story-import/references/import-tracking.md +95 -0
- package/lib/oh-story/skills/story-import/references/length-routing.md +1 -1
- package/lib/oh-story/skills/story-import/references/outline-reverse-rules.md +79 -0
- package/lib/oh-story/skills/story-import/references/outline-reverse.md +24 -0
- package/lib/oh-story/skills/story-import/references/state-tracking.md +4 -69
- package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +98 -92
- package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +24 -12
- package/lib/oh-story/skills/story-import/references/tracking-initialization.md +1 -1
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +15 -11
- package/lib/oh-story/skills/story-import/scripts/build_outline_brief.py +332 -0
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +132 -27
- package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +478 -15
- package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +182 -23
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +81 -270
- package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +252 -0
- package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +3 -3
- package/lib/oh-story/skills/story-long-analyze/references/final-checks.md +19 -0
- package/lib/oh-story/skills/story-long-analyze/references/index-rebuild.md +11 -0
- package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
- package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +138 -64
- package/lib/oh-story/skills/story-long-analyze/references/semantic-acceptance-fixtures.md +84 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage1-golden-chapters.md +128 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage2-extraction.md +229 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage3-plot-rhythm.md +480 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage4-characters-settings.md +195 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage5-report.md +33 -0
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +55 -128
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +6 -6
- package/lib/oh-story/skills/story-long-analyze/references/synthesis-inputs.md +39 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/build_chapter_index.py +466 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/inspect_existing_assets.py +702 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/inspiration_index.py +864 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +1145 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/render_relation_chart.py +425 -0
- package/lib/oh-story/skills/story-long-scan/SKILL.md +45 -194
- package/lib/oh-story/skills/story-long-scan/references/platform-ciweimao.md +19 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-fanqie.md +45 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-jjwxc.md +28 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-qidian.md +35 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-qimao.md +27 -0
- package/lib/oh-story/skills/story-long-scan/references/topic-decision.md +6 -2
- package/lib/oh-story/skills/story-long-write/SKILL.md +49 -81
- package/lib/oh-story/skills/story-long-write/references/agent-calls.md +47 -0
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +24 -202
- package/lib/oh-story/skills/story-long-write/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-long-write/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +7 -11
- package/lib/oh-story/skills/story-long-write/references/character-relations.md +49 -1
- package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
- package/lib/oh-story/skills/story-long-write/references/deslop-gates.md +171 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-long-write/references/emotion-on-page.md +116 -0
- package/lib/oh-story/skills/story-long-write/references/emotional-arc-design.md +1 -114
- package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +7 -15
- package/lib/oh-story/skills/story-long-write/references/long-format.md +0 -8
- package/lib/oh-story/skills/story-long-write/references/long-genre-catalog.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/long-genre-mechanics.md +3 -3
- package/lib/oh-story/skills/story-long-write/references/opening-design.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/outline-conflict.md +4 -4
- package/lib/oh-story/skills/story-long-write/references/outline-methods.md +7 -7
- package/lib/oh-story/skills/story-long-write/references/outline-rhythm.md +3 -3
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +14 -69
- package/lib/oh-story/skills/story-long-write/references/plot-frameworks.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/plot-special-topics.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/project-files.md +19 -13
- package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +13 -5
- package/lib/oh-story/skills/story-long-write/references/reference-index.md +5 -6
- package/lib/oh-story/skills/story-long-write/references/stop-and-fix.md +9 -0
- package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -58
- 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 +4 -4
- package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +15 -11
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +81 -121
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +41 -139
- package/lib/oh-story/skills/story-long-write/references/workflow-outline.md +157 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +57 -67
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +112 -253
- package/lib/oh-story/skills/story-long-write/references/workflow-volume.md +142 -0
- package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +6 -4
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +19 -65
- package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-long-write/scripts/build_architect_brief.py +260 -0
- package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +226 -25
- package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +132 -27
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +7 -2
- package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +7 -4
- package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +304 -46
- package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +478 -15
- package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +182 -23
- package/lib/oh-story/skills/story-review/SKILL.md +31 -302
- package/lib/oh-story/skills/story-review/references/agent-prompts.md +184 -0
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-review/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-review/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-review/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-review/references/batch-review.md +19 -0
- package/lib/oh-story/skills/story-review/references/character-relations.md +49 -1
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-review/references/review-quality.md +6 -11
- package/lib/oh-story/skills/story-review/references/review-tracking.md +10 -0
- package/lib/oh-story/skills/story-review/references/solo.md +52 -0
- package/lib/oh-story/skills/story-review/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-review/references/tracking-initialization.md +1 -1
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +15 -11
- package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +478 -15
- package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +182 -23
- package/lib/oh-story/skills/story-setup/SKILL.md +71 -452
- package/lib/oh-story/skills/story-setup/references/agent-references/agent-quality.md +4 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/benchmark-style-load.md +107 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/character-relations.md +49 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +22 -5
- package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/emotion-on-page.md +116 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/emotional-arc-design.md +1 -114
- package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-catalog.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-mechanics.md +3 -3
- package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +7 -5
- package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-conflict.md +4 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-methods.md +7 -7
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-rhythm.md +3 -3
- package/lib/oh-story/skills/story-setup/references/agent-references/short-emotional-methods.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +0 -15
- package/lib/oh-story/skills/story-setup/references/agent-references/short-reversal.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -58
- 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 +4 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +19 -65
- package/lib/oh-story/skills/story-setup/references/diagnostics.md +4 -4
- package/lib/oh-story/skills/story-short-analyze/SKILL.md +56 -110
- package/lib/oh-story/skills/story-short-analyze/references/analysis-character-relations.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/analysis-method.md +42 -0
- package/lib/oh-story/skills/story-short-analyze/references/optional-modules.md +97 -0
- package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +9 -47
- package/lib/oh-story/skills/story-short-analyze/references/quality-checklist.md +80 -0
- package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +4 -4
- package/lib/oh-story/skills/story-short-analyze/references/stage2-3-structure-emotion.md +308 -0
- package/lib/oh-story/skills/story-short-analyze/references/stage4-6-reversal-summary.md +611 -0
- package/lib/oh-story/skills/story-short-scan/SKILL.md +35 -65
- package/lib/oh-story/skills/story-short-scan/references/manual-rank-input.md +36 -0
- package/lib/oh-story/skills/story-short-scan/references/platform-dianzhong.md +24 -0
- package/lib/oh-story/skills/story-short-scan/references/platform-heiyan.md +21 -0
- package/lib/oh-story/skills/story-short-scan/references/topic-match.md +38 -0
- package/lib/oh-story/skills/story-short-write/SKILL.md +23 -175
- package/lib/oh-story/skills/story-short-write/references/agent-calls.md +13 -0
- package/lib/oh-story/skills/story-short-write/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-short-write/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +1 -21
- package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +0 -15
- package/lib/oh-story/skills/story-short-write/references/output-contract.md +9 -47
- package/lib/oh-story/skills/story-short-write/references/reference-index.md +17 -47
- package/lib/oh-story/skills/story-short-write/references/scene-craft.md +40 -0
- package/lib/oh-story/skills/story-short-write/references/short-craft.md +7 -43
- package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -1
- package/lib/oh-story/skills/story-short-write/references/short-reversal.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/submission-craft.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/villain-and-reveal.md +5 -10
- package/lib/oh-story/skills/story-short-write/references/workflow-design.md +21 -13
- package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +116 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +99 -0
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +7 -119
- package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +7 -2
- package/lib/types/client/drama-production-view.d.ts.map +1 -1
- package/lib/types/client/file-activity.d.ts +19 -1
- package/lib/types/client/file-activity.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/production-prompts.d.ts +7 -0
- package/lib/types/client/production-prompts.d.ts.map +1 -1
- package/lib/types/client/production-runtime.d.ts +16 -0
- package/lib/types/client/production-runtime.d.ts.map +1 -1
- package/lib/types/client/video-studio.d.ts.map +1 -1
- package/lib/types/drama-adapters.d.ts +5 -3
- package/lib/types/drama-adapters.d.ts.map +1 -1
- package/lib/types/native-hooks.d.ts +53 -1
- package/lib/types/native-hooks.d.ts.map +1 -1
- package/lib/types/role-identity.d.ts +17 -0
- package/lib/types/role-identity.d.ts.map +1 -0
- package/lib/types/role-tool.d.ts.map +1 -1
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/lib/types/video-project.d.ts.map +1 -1
- package/lib/types/workspace-route.d.ts.map +1 -1
- package/lib/video-recap/CHANGELOG.md +60 -1
- package/lib/video-recap/README.en.md +348 -137
- package/lib/video-recap/README.md +340 -136
- package/lib/video-recap/manifest.json +406 -251
- package/lib/video-recap/skills/video-assemble/SKILL.md +30 -15
- package/lib/video-recap/skills/video-assemble/references/audio-modes.md +63 -0
- package/lib/video-recap/skills/video-assemble/references/explicit-audio-mix.md +75 -0
- package/lib/video-recap/skills/video-assemble/references/foreground-compose.md +118 -0
- package/lib/video-recap/skills/video-assemble/references/narration-adoption.md +103 -0
- package/lib/video-recap/skills/video-assemble/references/packaging.md +45 -0
- package/lib/video-recap/skills/video-assemble/references/pair-media.md +74 -0
- package/lib/video-recap/skills/video-assemble/references/source-score.md +147 -0
- package/lib/video-recap/skills/video-assemble/references/subtitle-track.md +202 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/__init__.py +1 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/audio_mix_binding.py +279 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/frozen_audio.py +187 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/narration_binding.py +323 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_inputs.py +109 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_publish.py +130 -0
- package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +10 -46
- package/lib/video-recap/skills/video-assemble/scripts/assemble.py +378 -119
- package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +29 -12
- package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +95 -44
- package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +75 -32
- package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +11 -11
- package/lib/video-recap/skills/video-assemble/scripts/compose_foreground.py +293 -0
- package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +71 -78
- package/lib/video-recap/skills/video-assemble/scripts/jianying/__init__.py +1 -0
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_builders.py → jianying/builders.py} +39 -67
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_model.py → jianying/model.py} +3 -11
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_optional.py → jianying/optional.py} +1 -1
- package/lib/video-recap/skills/video-assemble/scripts/jianying/schema.py +53 -0
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_templates.py → jianying/templates.py} +1 -1
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_timeline_contract.py → jianying/timeline_contract.py} +34 -13
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_writer.py → jianying/writer.py} +7 -17
- package/lib/video-recap/skills/video-assemble/scripts/lib.py +37 -4
- package/lib/video-recap/skills/video-assemble/scripts/media.py +12 -21
- package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +64 -34
- package/lib/video-recap/skills/video-assemble/scripts/packaging.py +122 -0
- package/lib/video-recap/skills/video-assemble/scripts/pair_media.py +216 -0
- package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +1 -3
- package/lib/video-recap/skills/video-assemble/scripts/source_score.py +469 -0
- package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +25 -9
- package/lib/video-recap/skills/video-assemble/scripts/subtitles/__init__.py +1 -0
- package/lib/video-recap/skills/video-assemble/scripts/{subtitle_core.py → subtitles/core.py} +13 -6
- package/lib/video-recap/skills/video-assemble/scripts/{subtitle_render.py → subtitles/render.py} +5 -4
- package/lib/video-recap/skills/video-assemble/scripts/subtitles/track.py +324 -0
- package/lib/video-recap/skills/video-assemble/scripts/subtitles/track_binding.py +200 -0
- package/lib/video-recap/skills/video-assemble/scripts/timeline.py +30 -46
- package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +91 -7
- package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +22 -8
- package/lib/video-recap/skills/video-cut/SKILL.md +34 -16
- package/lib/video-recap/skills/video-cut/references/shot-review.md +50 -0
- package/lib/video-recap/skills/video-cut/scripts/cut.py +2 -28
- package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +58 -62
- package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +21 -106
- package/lib/video-recap/skills/video-cut/scripts/cut_render.py +14 -9
- package/lib/video-recap/skills/video-cut/scripts/lib.py +39 -0
- package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +2 -155
- package/lib/video-recap/skills/video-cut/scripts/narrative_selection.py +244 -0
- package/lib/video-recap/skills/video-cut/scripts/shot_review.py +357 -0
- package/lib/video-recap/skills/video-recap/SKILL.md +86 -42
- package/lib/video-recap/skills/video-recap/references/audio-routing.md +126 -0
- package/lib/video-recap/skills/video-recap/references/config-playbook.md +12 -8
- package/lib/video-recap/skills/video-recap/references/data-schema.md +44 -33
- package/lib/video-recap/skills/video-recap/references/resource-library.md +151 -0
- package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +1 -1
- package/lib/video-recap/skills/video-recap/scripts/doctor.py +123 -30
- package/lib/video-recap/skills/video-recap/scripts/final_qc.py +22 -75
- package/lib/video-recap/skills/video-recap/scripts/lib.py +3 -3
- package/lib/video-recap/skills/video-recap/scripts/library.py +509 -0
- package/lib/video-recap/skills/video-recap/scripts/materials.py +63 -91
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +8 -70
- package/lib/video-recap/skills/video-recap/scripts/project_binding.py +286 -0
- package/lib/video-recap/skills/video-recap/scripts/qc/__init__.py +1 -0
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_client.py → qc/mimo_client.py} +1 -1
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_evidence.py → qc/mimo_evidence.py} +33 -66
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_observations.py → qc/mimo_observations.py} +3 -11
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_payload.py → qc/mimo_payload.py} +4 -7
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_report.py → qc/mimo_report.py} +17 -28
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_runner.py → qc/mimo_runner.py} +2 -2
- package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +0 -19
- package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +119 -50
- package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +32 -114
- package/lib/video-recap/skills/video-recap/scripts/recap_review.py +9 -23
- package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +387 -334
- package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +23 -23
- package/lib/video-recap/skills/video-recap/scripts/recap_source.py +278 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +25 -12
- package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +59 -52
- package/lib/video-recap/skills/video-recap/scripts/resource_lock.py +162 -0
- package/lib/video-recap/skills/video-script/SKILL.md +16 -13
- package/lib/video-recap/skills/video-script/references/creative-editing-playbook.md +9 -5
- package/lib/video-recap/skills/video-script/references/promotional-copy.md +68 -0
- package/lib/video-recap/skills/video-script/references/research-guide.md +1 -1
- package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +24 -76
- package/lib/video-recap/skills/video-script/scripts/lib.py +10 -87
- package/lib/video-recap/skills/video-script/scripts/narration_lint.py +63 -39
- package/lib/video-recap/skills/video-script/scripts/review.py +0 -2
- package/lib/video-recap/skills/video-script/scripts/review_grounding.py +35 -59
- package/lib/video-recap/skills/video-script/scripts/review_response.py +66 -128
- package/lib/video-recap/skills/video-script/scripts/review_runner.py +12 -20
- package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +4 -4
- package/lib/video-recap/skills/video-script/scripts/validate.py +53 -42
- package/lib/video-recap/skills/video-understanding/SKILL.md +6 -4
- package/lib/video-recap/skills/video-understanding/references/data-schema.md +50 -156
- package/lib/video-recap/skills/video-understanding/references/research-guide.md +4 -4
- package/lib/video-recap/skills/video-understanding/scripts/asr.py +85 -65
- package/lib/video-recap/skills/video-understanding/scripts/asr_timing_evidence.py +270 -0
- package/lib/video-recap/skills/video-understanding/scripts/brief.py +2 -5
- package/lib/video-recap/skills/video-understanding/scripts/briefing/__init__.py +1 -0
- package/lib/video-recap/skills/{video-script/scripts/agent_brief.py → video-understanding/scripts/briefing/builder.py} +38 -35
- package/lib/video-recap/skills/video-understanding/scripts/{brief_context.py → briefing/context.py} +4 -35
- package/lib/video-recap/skills/{video-script/scripts/brief_inputs.py → video-understanding/scripts/briefing/inputs.py} +9 -31
- package/lib/video-recap/skills/{video-script/scripts/brief_timeline.py → video-understanding/scripts/briefing/timeline.py} +5 -6
- package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +65 -116
- package/lib/video-recap/skills/video-understanding/scripts/detect.py +31 -40
- package/lib/video-recap/skills/video-understanding/scripts/lib.py +30 -86
- package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +63 -39
- package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +4 -4
- package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +17 -79
- package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +14 -40
- package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +64 -46
- package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +31 -11
- package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +19 -14
- package/lib/video-recap/skills/video-understanding/scripts/vlm.py +80 -108
- package/lib/video-recap/skills/video-voiceover/SKILL.md +29 -19
- package/lib/video-recap/skills/video-voiceover/references/index-tts.md +31 -0
- package/lib/video-recap/skills/video-voiceover/scripts/approved_text_policy.py +123 -0
- package/lib/video-recap/skills/video-voiceover/scripts/dub.py +51 -59
- package/lib/video-recap/skills/video-voiceover/scripts/lib.py +8 -44
- package/lib/video-recap/skills/video-voiceover/scripts/providers/__init__.py +1 -0
- package/lib/video-recap/skills/video-voiceover/scripts/providers/index_tts.py +184 -0
- package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +212 -134
- package/package.json +45 -45
- package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -58
- package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +0 -53
- package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -38
- package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +0 -530
- package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +0 -559
- package/lib/oh-story/skills/story-long-scan/references/scan-output-format.md +0 -207
- package/lib/oh-story/skills/story-long-write/references/state-tracking.md +0 -108
- package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +0 -678
- package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +0 -561
- package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +0 -98
- package/lib/video-recap/skills/video-recap/references/creative-editing-playbook.md +0 -225
- package/lib/video-recap/skills/video-recap/references/research-guide.md +0 -74
- package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +0 -250
- package/lib/video-recap/skills/video-script/scripts/brief_context.py +0 -348
- package/lib/video-recap/skills/video-script/scripts/narration.py +0 -12
- package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +0 -399
- package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +0 -290
- package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +0 -327
- /package/lib/video-recap/skills/video-assemble/scripts/{jianying_tracks.py → jianying/tracks.py} +0 -0
- /package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_contract.py → qc/mimo_contract.py} +0 -0
- /package/lib/video-recap/skills/video-voiceover/scripts/{fish_audio.py → providers/fish_audio.py} +0 -0
|
@@ -7,7 +7,6 @@ import re
|
|
|
7
7
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
-
from lib import stable_hash
|
|
11
10
|
|
|
12
11
|
from evidence_bundle import (
|
|
13
12
|
_clip_text,
|
|
@@ -16,9 +15,8 @@ from evidence_bundle import (
|
|
|
16
15
|
build_evidence_bundle,
|
|
17
16
|
build_review_coverage_metadata,
|
|
18
17
|
render_evidence_bundle,
|
|
19
|
-
validate_public_evidence_contract,
|
|
20
18
|
)
|
|
21
|
-
from review_grounding import
|
|
19
|
+
from review_grounding import _load_agent_optional
|
|
22
20
|
|
|
23
21
|
CATEGORIES = [
|
|
24
22
|
"hallucination",
|
|
@@ -70,17 +68,17 @@ COVERAGE_POLICY_VERSION = "coverage_policy_v1"
|
|
|
70
68
|
RUBRIC = """你是中文视频解说的创作复核编辑。依据素材证据和已有创作计划审阅草稿,只指出真实问题,宁缺毋滥:
|
|
71
69
|
1. 反幻觉(最重要):解说里的人物、动作、因果、关系必须由带标签的 evidence 支撑。画面/对白是 timeline evidence(clock=SOURCE 或 OUTPUT);背景资料/user_context 只能作为 context-only(clock=null)辅助识别/消歧。research-only 不能升级成当前画面强事实;若与 research 一致但画面/对白里看不到,最多 severity=suggestion/category=grounding_risk,不要判 error;只有与全部可得证据矛盾才是 severity=error, category=hallucination,并指出冲突证据。
|
|
72
70
|
2. 导演意图:若提供 recap_story_plan.json,检查草稿是否兑现 viewer promise、POV、dramatic question、情绪路径和 chosen_hypothesis;不要另起一条更“吸睛”但不属于该计划的故事。偏离主线 → no_throughline;承诺不兑现 → promise_mismatch/weak_payoff。
|
|
73
|
-
3. change-based beats:每个 beat
|
|
71
|
+
3. change-based beats:每个 beat 应改变知识、权力、目标、关系、情绪或风险。精简时不能只留下“发生了什么”,还要保住人物动机、接受条件及随后犹豫/行动的必要前提。若一段只重复上一段、删除后什么都不损失,可报 low_information_gain/pacing;不要用固定段数或秒数代替判断。
|
|
74
72
|
4. 钩子:开头要提出正文真实兑现的戏剧问题/利害,不是交代场景,也不是无关的留存话术。弱钩子 → weak_hook。
|
|
75
73
|
5. 给信息而非念画面:观众看得见动作表情;解说只增加上下文、因果、预期、证据支持的解释或跨越。复述画面 → narrating_picture。
|
|
76
74
|
6. 视听分工:若提供 visual_audio_board.json,检查 narration_job=none 或 audio_owner=original_dialogue/action_sound/ambience/music/silence 的拍是否被旁白无故覆盖;必须听见的原声被盖住 → original_audio_conflict。沉默和低旁白覆盖本身不是问题。
|
|
77
|
-
7.
|
|
78
|
-
8.
|
|
75
|
+
7. 人物、反应与动作兑现:不要用旁白解释掉素材中已经能成立的表演、停顿或反应。有情感回应或知情变化的反应镜不可机械删;反打是否保留取决于它是否提供新增信息,而非是否达到统一时长。以某个可见结果为看点时,只写 evidence 已呈现的结果,不推断更强的结果(例:证据只到受击,就不能写成倒地或胜负)。当前评审只能检查计划/稿件一致性,不能凭少量帧声称最终剪点一定好坏。
|
|
76
|
+
8. 密度/节奏与因果边界:7:3 不是配额。只在旁白没有任务、墙到墙压住原声、碎成一句一停,或无意长空档导致因果断裂时,报 density/pacing。不得把跨场镜头拼成同场动作/反应的虚假因果,也不用花字替补源证据或提前宣布结果。
|
|
79
77
|
9. 去废词:删空泛形容("危机四伏""震撼人心")→ cliche。
|
|
80
78
|
10. 完整句子:半句话/未收尾 → incomplete。
|
|
81
79
|
11. 段落衔接:解说块要为随后的原声留白铺垫,下一块要承接原声刚呈现的变化;若两块各说各的、原声进来接不上 → disjoint_handoff。
|
|
82
80
|
12. 结尾回收:结尾要兑现开头承诺/主线情绪,不要突然停、只复述最后画面、没有情绪/信息回报;弱回收 → weak_payoff。
|
|
83
|
-
13.
|
|
81
|
+
13. 风格一致性与修改范围:若提供 style_card.json,把它当作表达意图/语气/节奏边界;不符合意图 → style_mismatch。不要把 style_card 当标题/封面/首句包装计划。只提能定位到具体段落、beat 或镜头边界的具体局部修法;REVISION 未点名层默认冻结,不借局部问题重做故事、声音或包装。
|
|
84
82
|
14. 包装一致性:只有提供 packaging_plan.json 时才评估标题/封面/首句/卖点承诺与正文兑现;缺失不扣分。不一致 → packaging_mismatch。不要让包装反过来改写故事判断。
|
|
85
83
|
15. 去AI味:若出现模板化、空泛拔高、过度对仗、机械转折、明显 agent 示例残留,可报 ai_flavor;若出现示例人物/占位实体泄漏(如未替换示例名、模板角色)→ example_entity_leak。“不是 A,而是 B”本身不是错误,只有在先虚构旧判断再制造假洞察、或反复机械使用时才建议改写。deslop_qc.json 是 deterministic local report-only QC,不是 AIGC detector,不自动重写;只能作为证据参考,不能仅凭它判定。
|
|
86
84
|
另外给一份内容效果 scorecard(1-5,advisory:除事实矛盾/残句外不要据此给 error;缺项可以省略,系统会保留为 null/未评分):promise_match/hook_3s/first_15s_delivery/spine_clarity/stakes_escalation/information_gain/spoken_language/sentence_brevity/tts_pacing/grounding/original_audio_use/subtitle_readability/ending_payoff/style_consistency/ai_flavor/packaging_consistency。`sentence_brevity` 衡量的是句子是否简洁而完整,不是越短越高;连续短句造成串珠式 TTS 应降低分数。ai_flavor 分数含义:5=自然、人味强,1=AI味明显。
|
|
@@ -92,39 +90,23 @@ def merge_review_findings(chunks):
|
|
|
92
90
|
"""Merge chunk review findings deterministically, keeping highest severity."""
|
|
93
91
|
severity_rank = {"error": 3, "warning": 2, "suggestion": 1}
|
|
94
92
|
by_key = {}
|
|
95
|
-
for chunk in chunks
|
|
96
|
-
for f in
|
|
97
|
-
|
|
98
|
-
continue
|
|
99
|
-
key = (f.get("segment"), f.get("category"), f.get("issue"))
|
|
93
|
+
for chunk in chunks:
|
|
94
|
+
for f in chunk["findings"]:
|
|
95
|
+
key = (f["segment"], f["category"], f["issue"])
|
|
100
96
|
old = by_key.get(key)
|
|
101
|
-
if old is None or severity_rank
|
|
102
|
-
f.get("severity"), 0
|
|
103
|
-
) > severity_rank.get(old.get("severity"), 0):
|
|
97
|
+
if old is None or severity_rank[f["severity"]] > severity_rank[old["severity"]]:
|
|
104
98
|
by_key[key] = dict(f)
|
|
105
99
|
return sorted(
|
|
106
100
|
by_key.values(),
|
|
107
101
|
key=lambda f: (
|
|
108
|
-
f
|
|
109
|
-
f
|
|
110
|
-
f
|
|
111
|
-
f
|
|
102
|
+
f["segment"] is None,
|
|
103
|
+
f["segment"] if f["segment"] is not None else 10**9,
|
|
104
|
+
f["category"],
|
|
105
|
+
f["issue"],
|
|
112
106
|
),
|
|
113
107
|
)
|
|
114
108
|
|
|
115
109
|
|
|
116
|
-
def _bundle_fingerprint(bundle):
|
|
117
|
-
return stable_hash(
|
|
118
|
-
{
|
|
119
|
-
"schema_version": bundle.get("schema_version"),
|
|
120
|
-
"clock": bundle.get("clock"),
|
|
121
|
-
"coverage": bundle.get("coverage"),
|
|
122
|
-
"items": bundle.get("items"),
|
|
123
|
-
"context_items": bundle.get("context_items"),
|
|
124
|
-
}
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
110
|
def _bundle_prompt_size(bundle):
|
|
129
111
|
return len(render_evidence_bundle(bundle))
|
|
130
112
|
|
|
@@ -137,16 +119,14 @@ def _chunk_evidence_bundle(bundle, *, max_items=80, max_chars=12000):
|
|
|
137
119
|
range. Context-only research remains advisory and is repeated in each chunk so the
|
|
138
120
|
judge can still use alias/background hints without upgrading them to timeline facts.
|
|
139
121
|
"""
|
|
140
|
-
items = list(bundle
|
|
122
|
+
items = list(bundle["items"])
|
|
141
123
|
if len(items) <= max_items and _bundle_prompt_size(bundle) <= max_chars:
|
|
142
124
|
one = dict(bundle)
|
|
143
125
|
one["chunk_index"] = 0
|
|
144
126
|
one["chunk_count"] = 1
|
|
145
|
-
one
|
|
146
|
-
_bundle_fingerprint(bundle)
|
|
147
|
-
)
|
|
127
|
+
one["metadata"] = dict(bundle["metadata"])
|
|
148
128
|
return [one]
|
|
149
|
-
ranges = bundle
|
|
129
|
+
ranges = bundle["coverage"]["selected_ranges"]
|
|
150
130
|
chunks = []
|
|
151
131
|
used_ids = set()
|
|
152
132
|
for r in ranges:
|
|
@@ -166,16 +146,14 @@ def _chunk_evidence_bundle(bundle, *, max_items=80, max_chars=12000):
|
|
|
166
146
|
used_ids.update(id(item) for item in part)
|
|
167
147
|
chunk = dict(bundle)
|
|
168
148
|
chunk["items"] = part
|
|
169
|
-
chunk["coverage"] =
|
|
170
|
-
chunk["coverage"]["selected_ranges"] = [r]
|
|
149
|
+
chunk["coverage"] = {**bundle["coverage"], "selected_ranges": [r]}
|
|
171
150
|
chunk["chunk_index"] = len(chunks)
|
|
172
151
|
chunks.append(chunk)
|
|
173
152
|
leftovers = [item for item in items if id(item) not in used_ids]
|
|
174
153
|
for start in range(0, len(leftovers), max_items):
|
|
175
154
|
chunk = dict(bundle)
|
|
176
155
|
chunk["items"] = leftovers[start : start + max_items]
|
|
177
|
-
chunk["coverage"] =
|
|
178
|
-
chunk["coverage"]["selected_ranges"] = []
|
|
156
|
+
chunk["coverage"] = {**bundle["coverage"], "selected_ranges": []}
|
|
179
157
|
chunk["chunk_index"] = len(chunks)
|
|
180
158
|
chunks.append(chunk)
|
|
181
159
|
if not chunks:
|
|
@@ -184,11 +162,9 @@ def _chunk_evidence_bundle(bundle, *, max_items=80, max_chars=12000):
|
|
|
184
162
|
chunk["chunk_index"] = 0
|
|
185
163
|
chunks = [chunk]
|
|
186
164
|
count = len(chunks)
|
|
187
|
-
fp = _bundle_fingerprint(bundle)
|
|
188
165
|
for chunk in chunks:
|
|
189
166
|
chunk["chunk_count"] = count
|
|
190
|
-
chunk
|
|
191
|
-
chunk["metadata"]["evidence_bundle_fingerprint"] = fp
|
|
167
|
+
chunk["metadata"] = {**bundle["metadata"], "chunked_review": count > 1}
|
|
192
168
|
return chunks
|
|
193
169
|
|
|
194
170
|
|
|
@@ -198,33 +174,24 @@ def _merge_chunk_reviews(chunk_reviews):
|
|
|
198
174
|
if len(chunk_reviews) == 1:
|
|
199
175
|
return chunk_reviews[0]
|
|
200
176
|
verdict_rank = {"PASS": 0, "OK": 0, "REVISE": 1, "FAIL": 2}
|
|
201
|
-
best = max(chunk_reviews, key=lambda r: verdict_rank
|
|
177
|
+
best = max(chunk_reviews, key=lambda r: verdict_rank[r["verdict"]])
|
|
202
178
|
merged = dict(best)
|
|
203
179
|
merged["findings"] = merge_review_findings(chunk_reviews)
|
|
204
|
-
if any(f
|
|
205
|
-
merged["verdict"] = "FAIL" if best
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
summaries = [
|
|
209
|
-
str(r.get("summary", "")).strip()
|
|
210
|
-
for r in chunk_reviews
|
|
211
|
-
if str(r.get("summary", "")).strip()
|
|
212
|
-
]
|
|
213
|
-
merged["summary"] = summaries[0] if summaries else merged.get("summary", "")
|
|
180
|
+
if any(f["severity"] == "error" for f in merged["findings"]):
|
|
181
|
+
merged["verdict"] = "FAIL" if best["verdict"] == "FAIL" else "REVISE"
|
|
182
|
+
summaries = [r["summary"] for r in chunk_reviews if r["summary"]]
|
|
183
|
+
merged["summary"] = summaries[0] if summaries else best["summary"]
|
|
214
184
|
merged["chunked_review"] = {
|
|
215
185
|
"chunk_count": len(chunk_reviews),
|
|
216
|
-
"findings_before_merge": sum(
|
|
217
|
-
|
|
218
|
-
),
|
|
219
|
-
"findings_after_merge": len(merged.get("findings") or []),
|
|
186
|
+
"findings_before_merge": sum(len(r["findings"]) for r in chunk_reviews),
|
|
187
|
+
"findings_after_merge": len(merged["findings"]),
|
|
220
188
|
}
|
|
221
189
|
return merged
|
|
222
190
|
|
|
223
191
|
|
|
224
192
|
def _research_guardrail_qc(review, context_items):
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
]
|
|
193
|
+
# Assertion keys are whatever the judge returned; only the list itself is normalized.
|
|
194
|
+
assertions = review["grounding_assertions"]
|
|
228
195
|
research_context_assertions = [
|
|
229
196
|
a
|
|
230
197
|
for a in assertions
|
|
@@ -240,26 +207,22 @@ def _research_guardrail_qc(review, context_items):
|
|
|
240
207
|
or "current-timeline" in str(a.get("risk", "")).lower()
|
|
241
208
|
]
|
|
242
209
|
grounding_risk_findings = [
|
|
243
|
-
f
|
|
244
|
-
for f in (review.get("findings") or [])
|
|
245
|
-
if isinstance(f, dict) and f.get("category") == "grounding_risk"
|
|
210
|
+
f for f in review["findings"] if f["category"] == "grounding_risk"
|
|
246
211
|
]
|
|
247
212
|
return {
|
|
248
|
-
"context_only_assertions": len(context_items
|
|
249
|
-
+ len(research_context_assertions),
|
|
213
|
+
"context_only_assertions": len(context_items) + len(research_context_assertions),
|
|
250
214
|
"spoiler_risk_assertions": len(risk_assertions) + len(grounding_risk_findings),
|
|
251
215
|
"policy": "research evidence is context_only unless visual/asr-supported",
|
|
252
216
|
}
|
|
253
217
|
|
|
254
218
|
|
|
255
219
|
def _load_review_research_context(work_dir):
|
|
220
|
+
"""Agent-authored background_research.json: {} when absent; corrupt JSON raises
|
|
221
|
+
(same policy as the brief's loader), a non-object document fails open to {}."""
|
|
256
222
|
path = Path(work_dir) / "background_research.json"
|
|
257
223
|
if not path.exists():
|
|
258
224
|
return {}
|
|
259
|
-
|
|
260
|
-
data = json.loads(path.read_text(encoding="utf-8"))
|
|
261
|
-
except (ValueError, OSError):
|
|
262
|
-
return {}
|
|
225
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
263
226
|
return data if isinstance(data, dict) else {}
|
|
264
227
|
|
|
265
228
|
|
|
@@ -344,16 +307,13 @@ def _format_review_research_context(research, limit=1200):
|
|
|
344
307
|
def _load_optional_json(work_dir, name):
|
|
345
308
|
if work_dir is None:
|
|
346
309
|
return None
|
|
347
|
-
return
|
|
310
|
+
return _load_agent_optional(Path(work_dir), name)
|
|
348
311
|
|
|
349
312
|
|
|
350
313
|
def _format_json_context(title, value, limit=3000):
|
|
351
314
|
if value is None:
|
|
352
315
|
return f"## {title}\n(无)"
|
|
353
|
-
|
|
354
|
-
text = json.dumps(value, ensure_ascii=False, indent=2)
|
|
355
|
-
except (TypeError, ValueError):
|
|
356
|
-
text = str(value)
|
|
316
|
+
text = json.dumps(value, ensure_ascii=False, indent=2)
|
|
357
317
|
return f"## {title}\n{text[:limit]}"
|
|
358
318
|
|
|
359
319
|
|
|
@@ -494,13 +454,17 @@ def parse_review_response(text):
|
|
|
494
454
|
try:
|
|
495
455
|
data = json.loads(candidate)
|
|
496
456
|
except ValueError:
|
|
457
|
+
# Same shape as a parsed review so every consumer reads one contract.
|
|
497
458
|
return {
|
|
498
|
-
|
|
459
|
+
**_normalise_review({}),
|
|
499
460
|
"summary": "评审输出无法解析为 JSON,请人工检查。",
|
|
500
|
-
"findings": [],
|
|
501
461
|
"parse_error": True,
|
|
502
462
|
"raw": raw[:2000],
|
|
503
463
|
}
|
|
464
|
+
return _normalise_review(data)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def _normalise_review(data):
|
|
504
468
|
verdict = str(data.get("verdict", "REVISE")).upper()
|
|
505
469
|
# PASS/REVISE/FAIL is the new vocabulary; OK is kept as a backward-compatible alias.
|
|
506
470
|
if verdict not in ("PASS", "REVISE", "FAIL", "OK"):
|
|
@@ -564,10 +528,9 @@ def parse_review_response(text):
|
|
|
564
528
|
|
|
565
529
|
|
|
566
530
|
def format_review_md(review):
|
|
531
|
+
"""Render a parse_review_response() review; list-item keys stay judge-optional."""
|
|
567
532
|
order = {"error": 0, "warning": 1, "suggestion": 2}
|
|
568
|
-
findings = sorted(
|
|
569
|
-
review.get("findings", []), key=lambda f: order.get(f["severity"], 3)
|
|
570
|
-
)
|
|
533
|
+
findings = sorted(review["findings"], key=lambda f: order[f["severity"]])
|
|
571
534
|
counts = {
|
|
572
535
|
s: sum(1 for f in findings if f["severity"] == s)
|
|
573
536
|
for s in ("error", "warning", "suggestion")
|
|
@@ -575,25 +538,19 @@ def format_review_md(review):
|
|
|
575
538
|
out = [
|
|
576
539
|
"# Narration review",
|
|
577
540
|
"",
|
|
578
|
-
f"Verdict: **{review
|
|
541
|
+
f"Verdict: **{review['verdict']}** "
|
|
579
542
|
f"(errors {counts['error']}, warnings {counts['warning']}, suggestions {counts['suggestion']})",
|
|
580
543
|
"",
|
|
581
|
-
review
|
|
544
|
+
review["summary"] or "_(no summary)_",
|
|
582
545
|
"",
|
|
583
546
|
"## Scorecard",
|
|
584
547
|
]
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
for key in SCORECARD_KEYS:
|
|
588
|
-
v = scorecard.get(key)
|
|
589
|
-
out.append(f"- {key}: {v}/5" if v is not None else f"- {key}: 未评分")
|
|
590
|
-
else:
|
|
591
|
-
out.append("- (none)")
|
|
548
|
+
for key, v in review["scorecard"].items():
|
|
549
|
+
out.append(f"- {key}: {v}/5" if v is not None else f"- {key}: 未评分")
|
|
592
550
|
out.extend(["", "## Highest-return edits"])
|
|
593
|
-
|
|
594
|
-
out.extend([f"- {edit}" for edit in edits] or ["- (none)"])
|
|
551
|
+
out.extend([f"- {edit}" for edit in review["highest_return_edits"]] or ["- (none)"])
|
|
595
552
|
out.extend(["", "## Retention risk points"])
|
|
596
|
-
risks = review
|
|
553
|
+
risks = review["retention_risk_points"]
|
|
597
554
|
if risks:
|
|
598
555
|
for item in risks:
|
|
599
556
|
out.append(
|
|
@@ -602,7 +559,7 @@ def format_review_md(review):
|
|
|
602
559
|
else:
|
|
603
560
|
out.append("- (none)")
|
|
604
561
|
out.extend(["", "## Hook candidates review"])
|
|
605
|
-
hooks = review
|
|
562
|
+
hooks = review["hook_candidates_review"]
|
|
606
563
|
if hooks:
|
|
607
564
|
for item in hooks:
|
|
608
565
|
out.append(
|
|
@@ -613,7 +570,7 @@ def format_review_md(review):
|
|
|
613
570
|
out.extend(
|
|
614
571
|
["", "## Information gain / write-for-ear / grounding", "### Information gain"]
|
|
615
572
|
)
|
|
616
|
-
notes = review
|
|
573
|
+
notes = review["information_gain_notes"]
|
|
617
574
|
out.extend(
|
|
618
575
|
[
|
|
619
576
|
f"- 段 {n.get('segment')}: {n.get('label')} — {n.get('note', '')} {n.get('rewrite', '')}"
|
|
@@ -622,7 +579,7 @@ def format_review_md(review):
|
|
|
622
579
|
or ["- (none)"]
|
|
623
580
|
)
|
|
624
581
|
out.append("### Spoken rewrites")
|
|
625
|
-
rewrites = review
|
|
582
|
+
rewrites = review["spoken_language_rewrites"]
|
|
626
583
|
out.extend(
|
|
627
584
|
[
|
|
628
585
|
f"- 段 {r.get('segment')}: {r.get('original', '')} → {r.get('rewrite', '')}({r.get('why', '')})"
|
|
@@ -631,7 +588,7 @@ def format_review_md(review):
|
|
|
631
588
|
or ["- (none)"]
|
|
632
589
|
)
|
|
633
590
|
out.append("### Grounding assertions")
|
|
634
|
-
assertions = review
|
|
591
|
+
assertions = review["grounding_assertions"]
|
|
635
592
|
out.extend(
|
|
636
593
|
[
|
|
637
594
|
f"- 段 {a.get('segment')}: {a.get('assertion', '')} [{a.get('source', '')}] {a.get('risk', '')}"
|
|
@@ -653,42 +610,25 @@ def format_review_md(review):
|
|
|
653
610
|
def build_grounding_qc(work_dir, review, bundle, *, timeline="source"):
|
|
654
611
|
"""Pure-ish compatibility seam: build grounding QC payload without writing it.
|
|
655
612
|
|
|
656
|
-
It reads optional
|
|
613
|
+
It reads optional QC sidecars from work_dir to preserve the existing artifact
|
|
657
614
|
contract, but has no side effects.
|
|
658
615
|
"""
|
|
659
616
|
work_dir = Path(work_dir)
|
|
660
|
-
items = bundle
|
|
661
|
-
context = bundle
|
|
662
|
-
warnings
|
|
617
|
+
items = bundle["items"]
|
|
618
|
+
context = bundle["context_items"]
|
|
619
|
+
# The runner hands the same pipeline warnings to the bundle and the review.
|
|
620
|
+
warnings = list(bundle["warnings"])
|
|
663
621
|
verdict = "warn" if warnings else "pass"
|
|
664
|
-
if any(
|
|
665
|
-
f.get("severity") == "error"
|
|
666
|
-
for f in (review.get("findings") or [])
|
|
667
|
-
if isinstance(f, dict)
|
|
668
|
-
):
|
|
622
|
+
if any(f["severity"] == "error" for f in review["findings"]):
|
|
669
623
|
verdict = "fail"
|
|
670
|
-
if any(item.get("clock") not in ("source", "output") for item in items):
|
|
671
|
-
verdict = "warn" if verdict == "pass" else verdict
|
|
672
624
|
coverage_meta = build_review_coverage_metadata(bundle)
|
|
673
|
-
visual_items = [item for item in items if item
|
|
674
|
-
asr_items = [item for item in items if item
|
|
675
|
-
visual_fp = _source_fingerprint(work_dir, "vlm_analysis.json") or (
|
|
676
|
-
stable_hash(visual_items) if visual_items else ""
|
|
677
|
-
)
|
|
678
|
-
asr_fp = _source_fingerprint(work_dir, "asr_result.json") or (
|
|
679
|
-
stable_hash(asr_items) if asr_items else ""
|
|
680
|
-
)
|
|
625
|
+
visual_items = [item for item in items if item["source"] == "visual"]
|
|
626
|
+
asr_items = [item for item in items if item["source"] == "asr"]
|
|
681
627
|
return {
|
|
682
628
|
"schema_version": 1,
|
|
683
629
|
"owner": "video-script.review",
|
|
684
630
|
"timeline": timeline,
|
|
685
631
|
"coverage_policy_version": COVERAGE_POLICY_VERSION,
|
|
686
|
-
"source_fingerprints": {
|
|
687
|
-
"vlm": visual_fp,
|
|
688
|
-
"asr": asr_fp,
|
|
689
|
-
"research": _source_fingerprint(work_dir, "background_research.json"),
|
|
690
|
-
"clip_plan": _source_fingerprint(work_dir, "clip_plan_validated.json"),
|
|
691
|
-
},
|
|
692
632
|
"review_coverage": {
|
|
693
633
|
"time_ranges": coverage_meta["time_ranges"],
|
|
694
634
|
"scene_count": coverage_meta["scene_count"],
|
|
@@ -696,18 +636,16 @@ def build_grounding_qc(work_dir, review, bundle, *, timeline="source"):
|
|
|
696
636
|
"dropped_ranges": coverage_meta["dropped_ranges"],
|
|
697
637
|
},
|
|
698
638
|
"evidence_contract": {
|
|
699
|
-
|
|
700
|
-
"
|
|
701
|
-
"
|
|
702
|
-
|
|
703
|
-
),
|
|
639
|
+
# Every timeline item carries the bundle clock; context items are unclocked.
|
|
640
|
+
"source_items": len(items) if bundle["clock"] == "source" else 0,
|
|
641
|
+
"output_items": len(items) if bundle["clock"] == "output" else 0,
|
|
642
|
+
"unclocked_items": 0,
|
|
704
643
|
"context_only_items": len(context),
|
|
705
|
-
"validation": validate_public_evidence_contract(bundle),
|
|
706
644
|
},
|
|
707
645
|
"index_inputs": {
|
|
708
646
|
"vlm": bool(visual_items),
|
|
709
647
|
"asr": bool(asr_items),
|
|
710
|
-
"research":
|
|
648
|
+
"research": (work_dir / "background_research.json").exists(),
|
|
711
649
|
},
|
|
712
650
|
"speech_window_qc": _load_optional_json(work_dir, "silence_periods.qc.json")
|
|
713
651
|
or {"coarse_asr_windows": 0, "low_confidence_speech_flags": 0},
|
|
@@ -11,13 +11,12 @@ from lib import CONFIG, log, api_call
|
|
|
11
11
|
|
|
12
12
|
from evidence_bundle import build_evidence_bundle
|
|
13
13
|
from review_grounding import (
|
|
14
|
-
_load,
|
|
15
14
|
_load_cut_clip_spans,
|
|
15
|
+
_load_required,
|
|
16
16
|
_load_review_grounding,
|
|
17
17
|
remap_grounding_to_output_timeline,
|
|
18
18
|
)
|
|
19
19
|
from review_response import (
|
|
20
|
-
_bundle_fingerprint,
|
|
21
20
|
_chunk_evidence_bundle,
|
|
22
21
|
_load_review_research_context,
|
|
23
22
|
_merge_chunk_reviews,
|
|
@@ -34,9 +33,7 @@ COVERAGE_POLICY_VERSION = "coverage_policy_v1"
|
|
|
34
33
|
|
|
35
34
|
def review_narration(work_dir, *, timeline="source", strict_evidence=False):
|
|
36
35
|
work_dir = Path(work_dir)
|
|
37
|
-
narration =
|
|
38
|
-
if narration is None:
|
|
39
|
-
raise SystemExit(f"缺少 {work_dir / 'narration.json'};先写解说草稿再评审")
|
|
36
|
+
narration = _load_required(work_dir, "narration.json", "先写解说草稿再评审")
|
|
40
37
|
vlm_analysis, asr_result = _load_review_grounding(work_dir)
|
|
41
38
|
warnings = []
|
|
42
39
|
if timeline == "cut_output":
|
|
@@ -62,7 +59,6 @@ def review_narration(work_dir, *, timeline="source", strict_evidence=False):
|
|
|
62
59
|
research=_load_review_research_context(work_dir),
|
|
63
60
|
warnings=warnings,
|
|
64
61
|
)
|
|
65
|
-
bundle_fp = _bundle_fingerprint(bundle)
|
|
66
62
|
chunk_reviews = []
|
|
67
63
|
chunks = _chunk_evidence_bundle(bundle)
|
|
68
64
|
for chunk in chunks:
|
|
@@ -75,11 +71,11 @@ def review_narration(work_dir, *, timeline="source", strict_evidence=False):
|
|
|
75
71
|
)
|
|
76
72
|
resp = api_call(
|
|
77
73
|
{
|
|
78
|
-
"model": CONFIG
|
|
74
|
+
"model": CONFIG["vlm_model"],
|
|
79
75
|
"messages": messages,
|
|
80
76
|
"max_tokens": 2000 if len(chunks) == 1 else 1600,
|
|
81
77
|
"temperature": 0,
|
|
82
|
-
"seed": 7 +
|
|
78
|
+
"seed": 7 + chunk["chunk_index"],
|
|
83
79
|
}
|
|
84
80
|
)
|
|
85
81
|
content = ""
|
|
@@ -88,8 +84,8 @@ def review_narration(work_dir, *, timeline="source", strict_evidence=False):
|
|
|
88
84
|
except (KeyError, IndexError, TypeError):
|
|
89
85
|
log("评审 API 返回结构异常")
|
|
90
86
|
parsed = parse_review_response(content)
|
|
91
|
-
parsed["chunk_index"] = chunk
|
|
92
|
-
parsed["chunk_count"] = chunk
|
|
87
|
+
parsed["chunk_index"] = chunk["chunk_index"]
|
|
88
|
+
parsed["chunk_count"] = chunk["chunk_count"]
|
|
93
89
|
chunk_reviews.append(parsed)
|
|
94
90
|
review = _merge_chunk_reviews(chunk_reviews)
|
|
95
91
|
if warnings:
|
|
@@ -97,10 +93,9 @@ def review_narration(work_dir, *, timeline="source", strict_evidence=False):
|
|
|
97
93
|
review["evidence_contract"] = {
|
|
98
94
|
"schema_version": EVIDENCE_CONTRACT_VERSION,
|
|
99
95
|
"timeline": timeline,
|
|
100
|
-
"clock": bundle
|
|
96
|
+
"clock": bundle["clock"],
|
|
101
97
|
"coverage_policy_version": COVERAGE_POLICY_VERSION,
|
|
102
|
-
"selected_ranges": bundle
|
|
103
|
-
"evidence_bundle_fingerprint": bundle_fp,
|
|
98
|
+
"selected_ranges": bundle["coverage"]["selected_ranges"],
|
|
104
99
|
"chunk_count": len(chunks),
|
|
105
100
|
"warnings": warnings,
|
|
106
101
|
}
|
|
@@ -124,15 +119,14 @@ def _auto_timeline(work_dir):
|
|
|
124
119
|
orchestrator does: cut_output when narration.json is in the cut OUTPUT timeline, else
|
|
125
120
|
source. Without this, reviewing a cut narration on the default 'source' timeline compares
|
|
126
121
|
OUTPUT-time narration against SOURCE-time evidence and floods false-positive 'hallucination'
|
|
127
|
-
findings
|
|
122
|
+
findings.
|
|
128
123
|
|
|
129
124
|
Detection is authoritative-first: the orchestrator records the run's edit_mode in
|
|
130
125
|
recap_run_manifest.json. In orchestrated cut mode narration.json is OUTPUT time; in full
|
|
131
126
|
mode it is SOURCE time. Trusting edit_mode is correct even when stale cut artifacts from a
|
|
132
127
|
prior run linger in a reused work_dir. Only when no manifest is present (standalone review
|
|
133
|
-
or a hand-built work_dir) do we fall back to artifact sniffing
|
|
134
|
-
|
|
135
|
-
output-time narration_mapped.json, so its presence pins us back to source."""
|
|
128
|
+
or a hand-built work_dir) do we fall back to artifact sniffing: a rendered cut
|
|
129
|
+
(clip_plan_validated.json + edited_source.mp4) means narration.json is OUTPUT time."""
|
|
136
130
|
work_dir = Path(work_dir)
|
|
137
131
|
manifest = work_dir / "recap_run_manifest.json"
|
|
138
132
|
if manifest.exists():
|
|
@@ -151,9 +145,7 @@ def _auto_timeline(work_dir):
|
|
|
151
145
|
has_cut = (work_dir / "clip_plan_validated.json").exists() and (
|
|
152
146
|
work_dir / "edited_source.mp4"
|
|
153
147
|
).exists()
|
|
154
|
-
if has_cut
|
|
155
|
-
return "cut_output"
|
|
156
|
-
return "source"
|
|
148
|
+
return "cut_output" if has_cut else "source"
|
|
157
149
|
|
|
158
150
|
|
|
159
151
|
def main():
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
-
from lib import CONFIG,
|
|
6
|
+
from lib import CONFIG, file_identity
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def _empty_evidence(mode):
|
|
@@ -21,11 +21,11 @@ def _read_json(path):
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def _output_payload_is_current(payload, work_dir):
|
|
24
|
-
|
|
24
|
+
plan_path = Path(work_dir) / "clip_plan_validated.json"
|
|
25
25
|
return (
|
|
26
26
|
payload is not None
|
|
27
|
-
and
|
|
28
|
-
and payload["
|
|
27
|
+
and plan_path.exists()
|
|
28
|
+
and payload["clip_plan_identity"] == file_identity(plan_path)
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
|