@oh-story/dsh 0.1.8 → 0.1.10
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 +237 -84
- package/lib/client.js.map +3 -3
- package/lib/drama/manifest.json +183 -77
- package/lib/drama/skills/short-drama/SKILL.md +5 -1
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +140 -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 +28 -0
- package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +8 -2
- package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
- package/lib/drama/skills/short-drama-edit/SKILL.md +146 -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 +38 -0
- package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +29 -0
- package/lib/drama/skills/short-drama-edit/references/generated-footage.md +54 -0
- package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +60 -0
- package/lib/drama/skills/short-drama-edit/references/stage-contract.md +51 -0
- package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1156 -0
- package/lib/drama/skills/short-drama-edit/scripts/selftest.py +520 -0
- package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -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-image-prompts/references/common-recipe.md +11 -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 +29 -4
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +22 -0
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +13 -12
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
- 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 +199 -3
- package/lib/drama/skills/short-drama-review/SKILL.md +2 -0
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +7 -0
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +10 -0
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +12 -1
- package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +4 -0
- package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +78 -2
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +2 -0
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +12 -5
- package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +17 -0
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +76 -7
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +5 -2
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +21 -0
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +6 -17
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +12 -3
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +61 -5
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +3 -3
- package/lib/drama/skills/short-drama-write/SKILL.md +11 -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 +290 -90
- 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 +9 -35
- 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 +17 -35
- 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 +16 -34
- package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
- package/lib/novel-to-game/skills/game-qa/SKILL.md +9 -20
- package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +10 -6
- package/lib/novel-to-game/skills/game-world-design/SKILL.md +19 -32
- 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 +9 -18
- 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 +10 -27
- package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -6
- package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +6 -11
- package/lib/oh-story/manifest.json +419 -254
- package/lib/oh-story/roles/chapter-extractor.md +177 -237
- package/lib/oh-story/roles/character-designer.md +1 -1
- package/lib/oh-story/roles/consistency-checker.md +4 -4
- package/lib/oh-story/roles/narrative-writer.md +56 -243
- package/lib/oh-story/roles/story-architect.md +6 -6
- package/lib/oh-story/roles/story-explorer.md +11 -11
- package/lib/oh-story/skills/story/SKILL.md +13 -7
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory.md +61 -29
- 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 +54 -229
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +29 -56
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +61 -29
- 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/author_memory_commit.py +934 -170
- 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 +78 -82
- package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +2 -2
- 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 +10 -8
- package/lib/oh-story/skills/story-import/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +9 -34
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +197 -15
- package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +210 -2
- package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +3 -0
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +91 -258
- package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +245 -0
- package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +2 -2
- package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
- package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +113 -105
- package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +169 -125
- package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +172 -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/style-profile-generator.md +42 -132
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +5 -5
- 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 +1106 -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 +4 -1
- package/lib/oh-story/skills/story-long-write/SKILL.md +52 -216
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +29 -56
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +72 -12
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +61 -29
- 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/cross-book-recall.md +26 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +10 -4
- package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +6 -15
- 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 +110 -0
- package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +12 -4
- package/lib/oh-story/skills/story-long-write/references/reference-index.md +86 -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 +9 -34
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +88 -118
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +55 -119
- package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +15 -11
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +73 -54
- 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 +63 -4
- 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_writer_prompt.py +531 -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 +197 -15
- 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 +285 -0
- package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +58 -0
- package/lib/oh-story/skills/story-long-write/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +210 -2
- package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +3 -0
- package/lib/oh-story/skills/story-review/SKILL.md +80 -87
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +29 -56
- package/lib/oh-story/skills/story-review/references/author-memory.md +61 -29
- package/lib/oh-story/skills/story-review/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +10 -4
- package/lib/oh-story/skills/story-review/references/review-quality.md +6 -12
- 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 +9 -34
- 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 +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-review/scripts/tracking_commit.py +210 -2
- package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +3 -0
- package/lib/oh-story/skills/story-setup/SKILL.md +58 -43
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +29 -56
- 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 +10 -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/long-emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +1 -1
- 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 +63 -4
- package/lib/oh-story/skills/story-setup/references/diagnostics.md +38 -0
- package/lib/oh-story/skills/story-short-analyze/SKILL.md +22 -3
- package/lib/oh-story/skills/story-short-analyze/references/analysis-writing-techniques.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +5 -1
- package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +2 -2
- package/lib/oh-story/skills/story-short-scan/SKILL.md +5 -1
- package/lib/oh-story/skills/story-short-write/SKILL.md +15 -324
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +61 -29
- 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 +10 -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 +55 -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 +78 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +126 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +32 -0
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +5 -5
- 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 +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/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 +33 -0
- package/lib/types/client/production-runtime.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 +52 -0
- 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/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 +45 -45
- package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -59
- 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 -42
- package/lib/oh-story/skills/story-long-write/references/state-tracking.md +0 -108
|
@@ -117,11 +117,26 @@ def require_known_keys(mapping: dict[str, Any], allowed: set[str], label: str) -
|
|
|
117
117
|
require(not unknown, f"{label} contains unsupported fields: {', '.join(sorted(unknown))}")
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
# 事务校验期间收集全部超长字段,一次报完;None 表示逐条立即报错(初始化、状态读取等路径)。
|
|
121
|
+
_LENGTH_ISSUES: list[str] | None = None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def length_hint(label: str, text: str, max_bytes: int) -> str:
|
|
125
|
+
"""把字节上限换算成字数:模型写的是中文,只看得懂「要删几个字」。"""
|
|
126
|
+
size = len(text.encode("utf-8"))
|
|
127
|
+
allowed = max(1, max_bytes * len(text) // size)
|
|
128
|
+
return (f"{label} exceeds {max_bytes} bytes(现 {len(text)} 字,上限约 {allowed} 字,"
|
|
129
|
+
f"至少删 {len(text) - allowed} 字)")
|
|
130
|
+
|
|
131
|
+
|
|
120
132
|
def clean_text(value: object, label: str, *, allow_empty: bool = False, max_bytes: int = 768) -> str:
|
|
121
133
|
require(isinstance(value, str), f"{label} must be a string")
|
|
122
134
|
cleaned = " ".join(value.replace("|", "|").split())
|
|
123
135
|
require(allow_empty or bool(cleaned), f"{label} must not be empty")
|
|
124
|
-
|
|
136
|
+
if len(cleaned.encode("utf-8")) > max_bytes:
|
|
137
|
+
if _LENGTH_ISSUES is None:
|
|
138
|
+
raise TrackingError(length_hint(label, cleaned, max_bytes))
|
|
139
|
+
_LENGTH_ISSUES.append(length_hint(label, cleaned, max_bytes))
|
|
125
140
|
return cleaned
|
|
126
141
|
|
|
127
142
|
|
|
@@ -277,9 +292,15 @@ def archive_retired_tracking_paths(tracking: Path) -> list[str]:
|
|
|
277
292
|
return retired
|
|
278
293
|
|
|
279
294
|
|
|
295
|
+
def _both_blank(position: dict[str, Any]) -> bool:
|
|
296
|
+
return all(isinstance(position.get(key), str) and not position[key].strip() for key in ("story_time", "scene"))
|
|
297
|
+
|
|
298
|
+
|
|
280
299
|
def validate_position(value: object, label: str = "context.position") -> dict[str, Any]:
|
|
281
300
|
position = as_mapping(value, label)
|
|
282
301
|
require_known_keys(position, {"volume", "volume_start_chapter", "story_time", "scene"}, label)
|
|
302
|
+
require(not _both_blank(position),
|
|
303
|
+
f"{label}.story_time and {label}.scene must not be empty: fill where this chapter ends")
|
|
283
304
|
return {
|
|
284
305
|
"volume": safe_file_component(position.get("volume"), f"{label}.volume"),
|
|
285
306
|
"volume_start_chapter": as_int(
|
|
@@ -781,7 +802,13 @@ def render_delta(chapter: int, title: str, delta: dict[str, Any], core_names: se
|
|
|
781
802
|
lines.extend(f"- {item}" for item in retired)
|
|
782
803
|
payload = "\n".join(lines) + "\n"
|
|
783
804
|
size = byte_size(payload)
|
|
784
|
-
|
|
805
|
+
if size > DELTA_MAX_BYTES:
|
|
806
|
+
longest = sorted((line for line in lines if line.startswith("- ")), key=len, reverse=True)[:3]
|
|
807
|
+
allowed = DELTA_MAX_BYTES * len(payload) // size
|
|
808
|
+
raise TrackingError(
|
|
809
|
+
f"chapter delta is {size} bytes; hard cap is {DELTA_MAX_BYTES}(逐章记录现 {len(payload)} 字,"
|
|
810
|
+
f"上限约 {allowed} 字,至少压缩 {len(payload) - allowed} 字;最长几项:"
|
|
811
|
+
+ ";".join(f"{line[2:18]}…({len(line) - 2} 字)" for line in longest) + ")")
|
|
785
812
|
return payload
|
|
786
813
|
|
|
787
814
|
|
|
@@ -901,6 +928,17 @@ def normalize_initial_document(document: object) -> dict[str, Any]:
|
|
|
901
928
|
|
|
902
929
|
|
|
903
930
|
def normalize_transaction(project: Path, state: dict[str, Any], document: object) -> dict[str, Any]:
|
|
931
|
+
global _LENGTH_ISSUES
|
|
932
|
+
_LENGTH_ISSUES = []
|
|
933
|
+
try:
|
|
934
|
+
transaction = _normalize_transaction(project, state, document)
|
|
935
|
+
finally:
|
|
936
|
+
issues, _LENGTH_ISSUES = _LENGTH_ISSUES, None
|
|
937
|
+
require(not issues, f"{len(issues)} 个字段超长,一次改完再提交:" + ";".join(issues))
|
|
938
|
+
return transaction
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
def _normalize_transaction(project: Path, state: dict[str, Any], document: object) -> dict[str, Any]:
|
|
904
942
|
root = as_mapping(document, "transaction")
|
|
905
943
|
require_known_keys(
|
|
906
944
|
root,
|
|
@@ -999,6 +1037,13 @@ def merge_transaction(state: dict[str, Any], transaction: dict[str, Any]) -> dic
|
|
|
999
1037
|
"a revision must resubmit every current context item; retire them in an append transaction instead: "
|
|
1000
1038
|
+ ";".join(sorted(dropped)),
|
|
1001
1039
|
)
|
|
1040
|
+
kept = set(next_context["long_term_constraints"]) | set(next_context["continuity_risks"])
|
|
1041
|
+
still_listed = sorted(set(transaction["delta"]["retired_context_items"]) & kept)
|
|
1042
|
+
require(
|
|
1043
|
+
not still_listed,
|
|
1044
|
+
"delta.retired_context_items lists items that are still in context; remove them from context: "
|
|
1045
|
+
+ ";".join(still_listed),
|
|
1046
|
+
)
|
|
1002
1047
|
undeclared = sorted(dropped - set(transaction["delta"]["retired_context_items"]))
|
|
1003
1048
|
require(
|
|
1004
1049
|
not undeclared,
|
|
@@ -1188,6 +1233,126 @@ def check_project(project: Path) -> dict[str, Any]:
|
|
|
1188
1233
|
return state
|
|
1189
1234
|
|
|
1190
1235
|
|
|
1236
|
+
# 事务草稿里各文本字段的字数上限(按全中文估:UTF-8 每字 3 字节),写进提示,免得模型反复试错。
|
|
1237
|
+
DRAFT_LIMITS = {
|
|
1238
|
+
"delta.result": 160, "character_changes[].change": 120, "foreshadow_changes[].summary": 120,
|
|
1239
|
+
"timeline_events[].objective_fact / reader_knowledge": 160, "context.position.story_time / scene": 80,
|
|
1240
|
+
"character_snapshots.*.goal / state": 100, "逐章记录总量": 1024,
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
def draft_transaction(project: Path, chapter: int) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]:
|
|
1245
|
+
"""按当前 state 预填一份逐章事务:修订号、模式、章名和整份提交的上下文当前值都填好,
|
|
1246
|
+
调用方只写本章变化。另返回在场核心角色的当前快照,供有变化时整份改写后放进事务。
|
|
1247
|
+
新章(append)的故事时间与场景留空:它们必须是本章结束时的位置,沿用上一章的值能静默提交,
|
|
1248
|
+
所以不预填,上一章的值另行返回作参考。"""
|
|
1249
|
+
state = load_state(project)
|
|
1250
|
+
last = state["last_committed_chapter"]
|
|
1251
|
+
require(1 <= chapter <= last + 1, f"draft chapter must be between 1 and {last + 1}")
|
|
1252
|
+
mode = "append" if chapter == last + 1 else "revision"
|
|
1253
|
+
title = ""
|
|
1254
|
+
for outline in sorted((project / "大纲").glob(f"细纲_第{chapter:03d}章*.md")):
|
|
1255
|
+
match = re.search(rf"^#{{1,4}}\s*第\s*0*{chapter}\s*章\s*[::]\s*(.+?)\s*$",
|
|
1256
|
+
outline.read_text(encoding="utf-8"), re.M)
|
|
1257
|
+
if match:
|
|
1258
|
+
title = match.group(1).strip()
|
|
1259
|
+
break
|
|
1260
|
+
context = json.loads(json.dumps(state["context"], ensure_ascii=False))
|
|
1261
|
+
previous_position = {key: context["position"][key] for key in ("story_time", "scene")}
|
|
1262
|
+
delta: dict[str, Any] = {
|
|
1263
|
+
"result": "", "character_changes": [], "foreshadow_changes": [], "timeline_events": [],
|
|
1264
|
+
"constraints": [], "next_chapter_commitments": [],
|
|
1265
|
+
}
|
|
1266
|
+
if mode == "append":
|
|
1267
|
+
delta.update({"retired_context_items": [], "retired_characters": []})
|
|
1268
|
+
context["position"].update({"story_time": "", "scene": ""})
|
|
1269
|
+
document = {
|
|
1270
|
+
"schema_version": INPUT_SCHEMA_VERSION,
|
|
1271
|
+
"mode": mode,
|
|
1272
|
+
"chapter": chapter,
|
|
1273
|
+
"chapter_title": title,
|
|
1274
|
+
"expected_state_revision": state["state_revision"],
|
|
1275
|
+
"delta": delta,
|
|
1276
|
+
"context": {key: context[key] for key in
|
|
1277
|
+
("position", "long_term_constraints", "active_character_names", "continuity_risks")},
|
|
1278
|
+
"character_snapshots": {},
|
|
1279
|
+
}
|
|
1280
|
+
snapshots = {name: state["characters"][name] for name in context["active_character_names"]
|
|
1281
|
+
if name in state["characters"]}
|
|
1282
|
+
return document, snapshots, previous_position if mode == "append" else {}
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
def rebuild_stale_draft(document: dict[str, Any], existing: dict[str, Any], append: bool,
|
|
1286
|
+
current_characters: Any = ()) -> str:
|
|
1287
|
+
"""修订号变了:中间提交过别的事务。以当前状态为底,只自动合并确定安全的部分,其余列给调用方核对。
|
|
1288
|
+
|
|
1289
|
+
新章草稿之间只可能插进修订事务,修订不能删约束与风险条目,所以当前约束与风险覆盖旧底稿:
|
|
1290
|
+
旧草稿多出来的就是本章新增,delta 里声明退役的就是本章删除,可以精确合并。
|
|
1291
|
+
修订草稿之间可能插进新章(新章能退役条目),在场角色名修订也能删,都无法判断谁新:
|
|
1292
|
+
取当前状态,差异列出来;只有本章带了快照的新角色名自动加回。"""
|
|
1293
|
+
def items(value: object) -> list[str]:
|
|
1294
|
+
return [item for item in value if isinstance(item, str)] if isinstance(value, list) else []
|
|
1295
|
+
|
|
1296
|
+
def norm(item: str) -> str:
|
|
1297
|
+
return " ".join(item.replace("|", "|").split())
|
|
1298
|
+
|
|
1299
|
+
notes = ["修订号已变:context 按当前状态重建,本章已填的 delta" + ("、新增与退役的约束、结尾位置" if append else "")
|
|
1300
|
+
+ "已合并"]
|
|
1301
|
+
for key in ("delta", "character_snapshots"):
|
|
1302
|
+
if isinstance(existing.get(key), dict):
|
|
1303
|
+
document[key] = existing[key]
|
|
1304
|
+
if existing.get("chapter_title"):
|
|
1305
|
+
document["chapter_title"] = existing["chapter_title"]
|
|
1306
|
+
old_context = existing.get("context") if isinstance(existing.get("context"), dict) else {}
|
|
1307
|
+
delta = document["delta"] if isinstance(document["delta"], dict) else {}
|
|
1308
|
+
context = document["context"]
|
|
1309
|
+
retired = {norm(item) for item in items(delta.get("retired_context_items"))}
|
|
1310
|
+
left_out: list[str] = []
|
|
1311
|
+
for key in ("long_term_constraints", "continuity_risks"):
|
|
1312
|
+
current = {norm(item) for item in context[key]}
|
|
1313
|
+
extra = []
|
|
1314
|
+
for item in items(old_context.get(key)):
|
|
1315
|
+
if norm(item) not in current:
|
|
1316
|
+
current.add(norm(item))
|
|
1317
|
+
extra.append(item)
|
|
1318
|
+
if append:
|
|
1319
|
+
context[key] = [item for item in context[key] if norm(item) not in retired] + extra
|
|
1320
|
+
else:
|
|
1321
|
+
left_out += extra
|
|
1322
|
+
snapshots = document["character_snapshots"] if isinstance(document["character_snapshots"], dict) else {}
|
|
1323
|
+
names = context["active_character_names"]
|
|
1324
|
+
for name in items(old_context.get("active_character_names")):
|
|
1325
|
+
if name in names:
|
|
1326
|
+
continue
|
|
1327
|
+
if append and name in snapshots:
|
|
1328
|
+
names.append(name)
|
|
1329
|
+
else:
|
|
1330
|
+
left_out.append(f"在场角色 {name}")
|
|
1331
|
+
names[:] = [name for name in names if name not in set(items(delta.get("retired_characters")))]
|
|
1332
|
+
known = set(current_characters)
|
|
1333
|
+
for name in list(snapshots):
|
|
1334
|
+
if name not in known and name not in names:
|
|
1335
|
+
snapshots.pop(name)
|
|
1336
|
+
left_out.append(f"角色快照 {name}")
|
|
1337
|
+
if left_out:
|
|
1338
|
+
notes.append("草稿里有、当前状态没有的条目没有自动带回(可能已被别的提交退役),本章确实需要就加回:"
|
|
1339
|
+
+ ";".join(left_out))
|
|
1340
|
+
old_position = old_context.get("position") if isinstance(old_context.get("position"), dict) else {}
|
|
1341
|
+
position = context["position"]
|
|
1342
|
+
if append:
|
|
1343
|
+
for key in ("story_time", "scene"):
|
|
1344
|
+
if isinstance(old_position.get(key), str) and old_position[key].strip():
|
|
1345
|
+
position[key] = old_position[key]
|
|
1346
|
+
differs = [f"{key}:草稿写的是「{old_position[key]}」,当前状态是「{position[key]}」"
|
|
1347
|
+
for key in ("volume", "volume_start_chapter")
|
|
1348
|
+
if key in old_position and old_position[key] != position[key]]
|
|
1349
|
+
if differs:
|
|
1350
|
+
notes.append("卷信息与当前状态不同,已取当前状态,本章确实换卷就改回(" + ";".join(differs) + ")")
|
|
1351
|
+
if snapshots:
|
|
1352
|
+
notes.append("带过来的角色快照(" + "、".join(snapshots) + ")可能被中间的提交改过,逐个对照 current_snapshots 重核")
|
|
1353
|
+
return ";".join(notes)
|
|
1354
|
+
|
|
1355
|
+
|
|
1191
1356
|
def build_parser() -> argparse.ArgumentParser:
|
|
1192
1357
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
1193
1358
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
@@ -1197,12 +1362,55 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1197
1362
|
subparser.add_argument("--input", type=Path, required=True, help="UTF-8 JSON input document")
|
|
1198
1363
|
check_parser = subparsers.add_parser("check")
|
|
1199
1364
|
check_parser.add_argument("--project", type=Path, required=True, help="book project root containing 追踪/")
|
|
1365
|
+
draft_parser = subparsers.add_parser("draft", help="write a pre-filled chapter transaction to fill in")
|
|
1366
|
+
draft_parser.add_argument("--project", type=Path, required=True, help="book project root containing 追踪/")
|
|
1367
|
+
draft_parser.add_argument("--chapter", type=int, required=True)
|
|
1368
|
+
draft_parser.add_argument("--out", type=Path, help="default: <project>/.story/work/第NNN章/tracking.json")
|
|
1369
|
+
draft_parser.add_argument("--force", action="store_true",
|
|
1370
|
+
help="discard an existing draft instead of only refreshing its revision")
|
|
1200
1371
|
return parser
|
|
1201
1372
|
|
|
1202
1373
|
|
|
1203
1374
|
def main() -> int:
|
|
1204
1375
|
args = build_parser().parse_args()
|
|
1205
1376
|
try:
|
|
1377
|
+
if args.command == "draft":
|
|
1378
|
+
document, snapshots, previous_position = draft_transaction(args.project, args.chapter)
|
|
1379
|
+
out = args.out or args.project / ".story" / "work" / f"第{args.chapter:03d}章" / "tracking.json"
|
|
1380
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
1381
|
+
refreshed = ""
|
|
1382
|
+
if out.exists() and not args.force:
|
|
1383
|
+
# 重跑 draft 不冲掉已经填好的变化。修订号变了说明中间提交过别的事务:context 按当前
|
|
1384
|
+
# 状态重建(沿用旧 context 会把那次变更整份覆盖回去),只带过本章自己填的部分。
|
|
1385
|
+
existing = read_json(out)
|
|
1386
|
+
require(isinstance(existing, dict) and existing.get("chapter") == document["chapter"]
|
|
1387
|
+
and existing.get("mode") == document["mode"],
|
|
1388
|
+
f"{out} already holds a draft for a different chapter or mode; pass --force to replace it")
|
|
1389
|
+
if existing.get("expected_state_revision") == document["expected_state_revision"]:
|
|
1390
|
+
document, refreshed = existing, "已有草稿且修订号未变,原样保留"
|
|
1391
|
+
else:
|
|
1392
|
+
refreshed = rebuild_stale_draft(document, existing, bool(previous_position),
|
|
1393
|
+
load_state(args.project)["characters"])
|
|
1394
|
+
out.write_text(json.dumps(document, ensure_ascii=False, indent=1) + "\n", encoding="utf-8")
|
|
1395
|
+
fill = ("只填 delta 里本章的变化;context 其余字段已是当前值,要撤下的长期约束或连贯性风险从 context 删掉并把原文放进 "
|
|
1396
|
+
"delta.retired_context_items(仅 append);本章有变化的核心角色把下面的当前快照整份改好放进 character_snapshots,"
|
|
1397
|
+
"并在 character_changes 写一句变化。不要从脚本源码或 state 文件里另找格式。")
|
|
1398
|
+
blank = not (document["context"]["position"].get("story_time") or document["context"]["position"].get("scene"))
|
|
1399
|
+
if previous_position and blank:
|
|
1400
|
+
fill = ("context.position 的 story_time 与 scene 留空,填本章结束时的故事时间与场景(上一章结束时见 "
|
|
1401
|
+
"previous_position;换卷时连同 volume 与 volume_start_chapter 一起改)。") + fill
|
|
1402
|
+
payload = {
|
|
1403
|
+
"draft": str(out),
|
|
1404
|
+
"mode": document["mode"],
|
|
1405
|
+
"expected_state_revision": document["expected_state_revision"],
|
|
1406
|
+
"fill": (f"{refreshed};要从头生成加 --force。" if refreshed else "") + fill,
|
|
1407
|
+
"limits_chars": DRAFT_LIMITS,
|
|
1408
|
+
"current_snapshots": snapshots,
|
|
1409
|
+
}
|
|
1410
|
+
if previous_position:
|
|
1411
|
+
payload["previous_position"] = previous_position
|
|
1412
|
+
emit(json.dumps(payload, ensure_ascii=False))
|
|
1413
|
+
return 0
|
|
1206
1414
|
if args.command == "init":
|
|
1207
1415
|
result = initialize(args.project, read_json(args.input))
|
|
1208
1416
|
elif args.command == "commit":
|
|
@@ -172,6 +172,9 @@ def target_from_outline(value: str) -> int:
|
|
|
172
172
|
|
|
173
173
|
|
|
174
174
|
def _chapter_number_from_name(name: str, *, outline: bool) -> int | None:
|
|
175
|
+
# 改稿流程把原文备份为 第N章_章名_原稿_{日期}.md,与 hooks 一样不把它当本章正文。
|
|
176
|
+
if not outline and "_原稿_" in name:
|
|
177
|
+
return None
|
|
175
178
|
pattern = r"^细纲_第0*(\d+)章.*\.md$" if outline else r"^第0*(\d+)章(?:[_\- ].*)?\.md$"
|
|
176
179
|
match = re.match(pattern, name)
|
|
177
180
|
return int(match.group(1)) if match else None
|
|
@@ -6,17 +6,19 @@ metadata: {"openclaw":{"source":"https://github.com/zenstory-ai/oh-story-claudec
|
|
|
6
6
|
---
|
|
7
7
|
# story-review:多视角对抗式审查
|
|
8
8
|
|
|
9
|
-
> Spawn 版本提示(不阻断 spawn):先读取项目根 `.story-deployed` 的 `agents_version`。与本版 `agents_version:
|
|
9
|
+
> Spawn 版本提示(不阻断 spawn):先读取项目根 `.story-deployed` 的 `agents_version`。与本版 `agents_version: 32` 不一致时(标记缺失、字段缺失/非整数、小于或大于 32)**照常按文件存在性检查并 spawn**,但只检查当前运行时的 canonical 目录;同时在「这次怎么审的」里用一句白话提示作者「审稿助手是旧版,运行 /story-setup 后新开会话」,`Notice: agents bundle 版本不匹配(项目 {N},本版 32)` 原文写进技术备注行;大于 32 时额外提示先更新 oh-story-claudecode,不要用本地旧版 setup 降级覆盖。只有 agent 文件缺失、或运行时不暴露 custom agent 时才降级 solo/direct,报告 `Fallback: ... -> solo`。
|
|
10
10
|
|
|
11
11
|
你是审查协调器。你的职责是找出小说文本中的结构、角色、文字、设定问题,并给出可执行修改建议。
|
|
12
12
|
|
|
13
13
|
**执行铁律:审查是找问题,不是验证正确性。**
|
|
14
14
|
|
|
15
|
+
**文风裁决**:正文写作、改写或审稿前先读 [references/style-resolution.md](references/style-resolution.md),加载本书文风并形成 `style_resolution`;无作者记忆也执行。当前请求、本书文风和 active 偏好按维度覆盖通用 references;同一裁决交给后续执行者。
|
|
16
|
+
|
|
15
17
|
## 作者习惯边界
|
|
16
18
|
|
|
17
|
-
若作者记忆 state 已存在,审查前用 `scripts/author_memory_commit.py query` 获取本次相关 active
|
|
19
|
+
若作者记忆 state 已存在,审查前用 `scripts/author_memory_commit.py query --kind delivery --kind interaction --kind prose_style --book-root {书目录}` 获取本次相关 active 条目(`--kind` 必传;不传 `--book-root` 就拿不到本书级偏好;总输出 ≤2KB)。它们只能帮助解释意图和组织报告,不能降低 rubric 严重度、把事实冲突判为无问题或跳过平台门禁;当前请求仍优先。完整规则见 [references/author-memory.md](references/author-memory.md)。
|
|
18
20
|
|
|
19
|
-
用户对报告格式或协作方式作出稳定声明时,在本轮审查完成后用 `record`
|
|
21
|
+
用户对报告格式或协作方式作出稳定声明时,在本轮审查完成后用 `record` 记录,并按 author-memory.md「回执怎么告诉作者」转告;只记作者明确说的,一次性要求不记录,不从反复修改推断。审查发现、工具告警和助手建议本身绝不自动学习。
|
|
20
22
|
|
|
21
23
|
---
|
|
22
24
|
|
|
@@ -25,7 +27,7 @@ metadata: {"openclaw":{"source":"https://github.com/zenstory-ai/oh-story-claudec
|
|
|
25
27
|
- `/story-review` 或 `/story-review full` → 优先 spawn 全部 4 个 Agent;如果当前已经在子代理内,核心 Agent 未部署/异常,或 spawn 失败,自动降级为 solo。
|
|
26
28
|
- `/story-review lean` → 优先 spawn `story-architect` + `consistency-checker`;如果当前已经在子代理内,任一所需 Agent 未部署/异常,或 spawn 失败,自动降级为 solo。
|
|
27
29
|
- `/story-review solo` → 不 spawn Agent,由当前会话执行基础审查。
|
|
28
|
-
- 未指定 → 默认 full
|
|
30
|
+
- 未指定 → 默认 full,并在报告开头用一句话说明这次实际是怎么审的。
|
|
29
31
|
|
|
30
32
|
---
|
|
31
33
|
|
|
@@ -40,13 +42,13 @@ metadata: {"openclaw":{"source":"https://github.com/zenstory-ai/oh-story-claudec
|
|
|
40
42
|
- lean 必需 agent:`story-architect`、`consistency-checker`
|
|
41
43
|
- 对每个必需 Agent 文件:
|
|
42
44
|
- **Claude Code agent(`.claude/agents/`)**:读取 frontmatter,确认 `name:` 与 subagent_type 完全一致;frontmatter 缺失、不可解析或 name 不匹配时视为 malformed agent。
|
|
43
|
-
- **OpenCode agent(`.opencode/agents/`)**:文件名即 agent 名(OpenCode 不要求在 frontmatter 中写 `name:`),读取 frontmatter 确认 `mode: subagent` 和 `
|
|
45
|
+
- **OpenCode agent(`.opencode/agents/`)**:文件名即 agent 名(OpenCode 不要求在 frontmatter 中写 `name:`),读取 frontmatter 确认 `mode: subagent` 和 `permissions:` 规则列表存在且可解析即可(2.x 用复数 `permissions:`,旧版单数 `permission:` 视为待重新部署);frontmatter 缺失或不可解析视为 malformed。
|
|
44
46
|
- **Codex agent(`.codex/agents/`)**:文件名为 `{agent}.toml`,TOML 必须可解析,且包含 `name`、`description`、`developer_instructions`;`name` 必须与目标 agent 完全一致。
|
|
45
47
|
- **Antigravity agent(`.agents/agents/`)**:路径为 `.agents/agents/agent-name/agent.md`(`agent-name` 为目标 agent 名),frontmatter 必须可解析,且 `name` 与目标 agent 一致、`mainAgent: false`、`subagent: true`、`tools` 非空;缺失或不匹配视为 malformed。
|
|
46
|
-
- 如果目标模式所需任一文件缺失或 malformed,**不要尝试 spawn 缺失/异常 Agent**;自动降级为 `solo
|
|
48
|
+
- 如果目标模式所需任一文件缺失或 malformed,**不要尝试 spawn 缺失/异常 Agent**;自动降级为 `solo`,报告开头用一句话告诉作者「审稿助手缺失或损坏,这次由我一个人审;运行 `/story-setup` 后可多视角审」,降级原因 `missing agents -> solo` / `malformed agents -> solo` 与问题文件写进技术备注行的 Fallback、Files 两栏。
|
|
47
49
|
5. **确认 Agent 工具可用**:Claude/OpenCode/Codex 需要当前运行时的子 Agent/Task 调用能力,Antigravity 需要 `invoke_subagent`;不可用时直接降级为 `solo`,报告 `Fallback: agent tool unavailable -> solo`。
|
|
48
|
-
6. **运行时失败降级**:如果任何 Agent spawn 返回失败、`subagent_type` / `agent_type` / `TypeName` 不可用、frontmatter/TOML 运行时解析失败或子 Agent 无法启动,停止继续 spawn,改用 `solo` 重新审查,并报告 `Fallback: spawn failed -> solo` 与失败的 agent 名;不要把部分成功的 Agent 结果当成 full/lean 结论。
|
|
49
|
-
7.
|
|
50
|
+
6. **运行时失败降级**:如果任何 Agent spawn 返回失败、`subagent_type` / `agent` / `agent_type` / `TypeName` 不可用、frontmatter/TOML 运行时解析失败或子 Agent 无法启动,停止继续 spawn,改用 `solo` 重新审查,并报告 `Fallback: spawn failed -> solo` 与失败的 agent 名;不要把部分成功的 Agent 结果当成 full/lean 结论。
|
|
51
|
+
7. **确定实际模式**:请求模式与实际模式都写进报告末尾的技术备注行。
|
|
50
52
|
|
|
51
53
|
---
|
|
52
54
|
|
|
@@ -54,16 +56,12 @@ metadata: {"openclaw":{"source":"https://github.com/zenstory-ai/oh-story-claudec
|
|
|
54
56
|
|
|
55
57
|
`story-review` 的核心审查标准必须始终可用。参考文件是增强资料,不是运行前提。
|
|
56
58
|
|
|
57
|
-
###
|
|
59
|
+
### 报告面向作者(必须遵守)
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
报告写给作者:审了什么、哪里要改、为什么(用读者感受和故事后果说,附原文引用)、要作者拍板的事、下一步。reviewer 名、S1–S4、Gate、检测器类别名、脚本名、PASS/FAIL、文件字段名不进正文;位置写「第 N 章「引文」」或「第 N 章第 M 段」。优先级换成白话(小节标题照模板):S1、S2 → **必须改**,S3 → **建议改**,S4 → **可以不改**。执行路径只写在报告最后一行,格式固定:
|
|
60
62
|
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Effective Mode: full | lean | solo
|
|
64
|
-
Fallback: none | project custom agents unavailable -> solo | missing agents -> solo | malformed agents -> solo | agent tool unavailable -> solo | spawn failed -> solo | subagent recursion guard -> solo
|
|
65
|
-
Rubric: fanqie | qidian | zhihu | generic web-fiction
|
|
66
|
-
Rubric Source: file | embedded fallback
|
|
63
|
+
```text
|
|
64
|
+
技术备注:Mode {请求}→{实际} · Fallback {none | project custom agents unavailable -> solo | missing agents -> solo | malformed agents -> solo | agent tool unavailable -> solo | spawn failed -> solo | subagent recursion guard -> solo} · Rubric {fanqie | qidian | zhihu | generic} ({file | embedded})[ · Files {缺失或异常的 agent 文件}][ · Notice {版本不匹配原文}]
|
|
67
65
|
```
|
|
68
66
|
|
|
69
67
|
### 参考资料解析顺序
|
|
@@ -98,7 +96,7 @@ Rubric Source: file | embedded fallback
|
|
|
98
96
|
|
|
99
97
|
### 内置审查基准包(路径不可读时必用)
|
|
100
98
|
|
|
101
|
-
如果上述参考文件在当前项目中不可读,**不要把审查降级为无 rubric,也不要在报告里说“无法加载具体 rubric
|
|
99
|
+
如果上述参考文件在当前项目中不可读,**不要把审查降级为无 rubric,也不要在报告里说“无法加载具体 rubric”后停止使用标准**。必须使用本节内置基准包,技术备注行的 Rubric 来源写 `embedded`。
|
|
102
100
|
|
|
103
101
|
通用网文内容 rubric:
|
|
104
102
|
- 核心卖点:本章是否围绕明确卖点推进;看不出卖点至少 S2。
|
|
@@ -168,7 +166,7 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
168
166
|
- 番茄小说 → 优先读取 `story-review/references/rubrics/fanqie.md`;不可读时使用内置番茄 fallback 摘要。
|
|
169
167
|
- 起点 → 优先读取 `story-review/references/rubrics/qidian.md`;不可读时使用内置起点 fallback 摘要。
|
|
170
168
|
- 知乎盐言 → 优先读取 `story-review/references/rubrics/zhihu.md`;不可读时使用内置知乎 fallback 摘要。
|
|
171
|
-
- 未识别平台 → 优先读取 `story-review/references/quality-rubric.md`;不可读时使用内置通用网文内容 rubric
|
|
169
|
+
- 未识别平台 → 优先读取 `story-review/references/quality-rubric.md`;不可读时使用内置通用网文内容 rubric;技术备注行写 `generic` 与 `file | embedded`。
|
|
172
170
|
5. **形成审查基准包摘要**:把已加载的文件内容或内置 fallback 摘要压缩为 5-12 条审查标准,后续 solo 和子 Agent 都必须使用这份摘要。摘要必须保留一条句长标准:叙述默认是逗号长句,碎句和电报体与 AI 腔同级处理,不因「短」放行。
|
|
173
171
|
6. **确定性预检(只报告,不修改)**:当审查范围包含本地正文文件路径时,运行本 skill 自带脚本:
|
|
174
172
|
```bash
|
|
@@ -195,7 +193,7 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
195
193
|
|
|
196
194
|
## 统一 Findings Schema(所有模式必须使用)
|
|
197
195
|
|
|
198
|
-
所有 reviewer(包括 solo
|
|
196
|
+
所有 reviewer(包括 solo)输出问题时必须使用统一结构,方便综合排序;它只在 reviewer 与综合裁决之间流转,给作者的报告按 Phase 4 模板转写。`location` 必须使用工具读取结果显示的原始文件行号;不要删除空行后重新编号。
|
|
199
197
|
|
|
200
198
|
对 `consistency` / `factual` / `causal` / `rule_boundary` 类 finding,`fix` 字段只写事实统一方向(例如“统一为左臂旧伤,并同步正文/设定中冲突处”或“需在 A/B 时间线中裁定一个来源”),不要写文学创作建议。
|
|
201
199
|
|
|
@@ -208,7 +206,7 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
208
206
|
fix: "可执行修改建议"
|
|
209
207
|
```
|
|
210
208
|
|
|
211
|
-
|
|
209
|
+
严重度定义(与长篇写作、检测器同一刻度:S1/S2=必须修,S3=建议看,S4=仅提示):
|
|
212
210
|
- **S1**:会破坏主线、角色动机、世界规则或读者信任,需优先修。
|
|
213
211
|
- **S2**:明显影响章节效果、留存、节奏、人物可信度,建议本轮修。
|
|
214
212
|
- **S3**:局部质量问题,如措辞、轻微格式、局部节奏,可排期修。
|
|
@@ -218,7 +216,7 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
218
216
|
|
|
219
217
|
## Phase 2:并行 Spawn Agent(full/lean 模式)
|
|
220
218
|
|
|
221
|
-
使用当前运行时的 Agent 工具并行调用(Codex 原生子代理使用 `agent_type`,Claude Code
|
|
219
|
+
使用当前运行时的 Agent 工具并行调用(Codex 原生子代理使用 `agent_type`,Claude Code 使用 `subagent_type`,OpenCode 使用 `subagent` 工具的 `agent` 参数,Antigravity 使用 `invoke_subagent` + 同名 `TypeName`;实际字段以当前 CLI 暴露的工具为准)。每个 Agent 不继承父对话上下文,prompt 必须自包含项目路径、审查范围、文件路径、必要摘录、审查基准包摘要、Rubric Source 和统一 Findings Schema。
|
|
222
220
|
|
|
223
221
|
**调用规则**:执行 Phase 0 后,只有实际模式仍是 full/lean 时才 spawn。不要 spawn 缺失 Agent。
|
|
224
222
|
|
|
@@ -231,6 +229,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
231
229
|
你的任务是【找问题】,不是验证正确性。以最严苛的标准审视。
|
|
232
230
|
项目路径:{项目根}
|
|
233
231
|
审查范围:{文件路径/章节/必要摘录}
|
|
232
|
+
文风路径:{本书文风全文路径,无则写无}
|
|
233
|
+
style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
|
|
234
234
|
审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
|
|
235
235
|
Rubric Source: file | embedded fallback
|
|
236
236
|
相关文件路径:{设定/大纲/细纲文件路径}
|
|
@@ -266,6 +266,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
266
266
|
你的任务是【找问题】,不是验证正确性。以最严苛的标准审视。
|
|
267
267
|
项目路径:{项目根}
|
|
268
268
|
审查范围:{文件路径/章节/必要摘录}
|
|
269
|
+
文风路径:{本书文风全文路径,无则写无}
|
|
270
|
+
style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
|
|
269
271
|
审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
|
|
270
272
|
Rubric Source: file | embedded fallback
|
|
271
273
|
相关角色文件:{角色设定文件路径}
|
|
@@ -295,6 +297,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
295
297
|
你的任务是【找问题】,不是验证正确性。以最严苛的标准审视。
|
|
296
298
|
项目路径:{项目根}
|
|
297
299
|
审查范围:{文件路径/章节/必要摘录}
|
|
300
|
+
文风路径:{本书文风全文路径,无则写无}
|
|
301
|
+
style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
|
|
298
302
|
审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
|
|
299
303
|
Rubric Source: file | embedded fallback
|
|
300
304
|
AI 味 / 禁用词摘要:{从 anti-ai-writing、banned-words 或内置 fallback 提取,必须内联}
|
|
@@ -303,11 +307,11 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
303
307
|
1. 是否存在禁用词/套话/陈词滥调,或“像/好像/仿佛/如同”式比喻成片堆叠?
|
|
304
308
|
2. 是否出现 AI 写作指纹、8 种 AI 写作模式(含模式 8 解释腔/上帝视角/安排感)或章末总结体?
|
|
305
309
|
3. 格式是否合规(按戏剧单元/镜头自然断段、无机械字数切分、无空行、对话独立成行、主语节奏自然)?
|
|
306
|
-
4. 标点节奏是否匹配语气/人物声线:是否通篇句号化、随机堆砌问号/感叹号,或残留 `……`/`——`
|
|
310
|
+
4. 标点节奏是否匹配语气/人物声线:是否通篇句号化、随机堆砌问号/感叹号,或残留 `……`/`——` 硬造停顿?本书已明确授权且有功能的停顿不因符号本身判错。
|
|
307
311
|
5. 是否出现“这五个字 / 短短四字 / 三个字一落 / 八个字砸下去”等正文内具体字数表达?若统计口径不明、未见机器核对结果或无叙事必要,标为问题并建议改成非具体数字表达。
|
|
308
312
|
6. 节奏是否均匀(有无连续多节无情绪变化)?
|
|
309
313
|
7. 是否存在删掉无损的任务卡点或流程细节?若只是水/局部节奏问题标 S3;明显拖垮主线推进标 S2。
|
|
310
|
-
8.
|
|
314
|
+
8. 身体细节是否重复、无功能?按本书文风和叙事作用判断,不设单词次数硬线。
|
|
311
315
|
9. AI味分级(轻度/中度/重度)及证据。
|
|
312
316
|
10. 去 AI 补充复核:是否有作者解释总结/意义尾巴;是否连续堆精致戏剧反应短语;是否把已有手机/屏幕/公告/规则/证据载体改成叙述者解释;是否把任务卡点当成自然感或凑字数手段;是否机械删除了有功能的生活化/角色化比喻或短篇主观审判句。
|
|
313
317
|
|
|
@@ -328,6 +332,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
328
332
|
审查范围:{文件路径/章节/必要摘录}
|
|
329
333
|
已知角色:{从设定文件提取角色列表}
|
|
330
334
|
继承的开放项(分批审查必填,无则写「无」):{从 追踪/伏笔.md 提取的、预计回收章 ≤ 本批末章的已埋未回收伏笔,连同上一批未解决 findings 摘要}
|
|
335
|
+
文风路径:{本书文风全文路径,无则写无}
|
|
336
|
+
style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
|
|
331
337
|
审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
|
|
332
338
|
Rubric Source: file | embedded fallback
|
|
333
339
|
可选补充参考:本 Skill 的 `story-review/references/review-quality.md`;若不可读,不影响事实冲突扫描。
|
|
@@ -355,56 +361,43 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
|
|
|
355
361
|
2. 合并去重:按 `severity` 排序(S1 > S2 > S3 > S4),同级内按影响范围排序。
|
|
356
362
|
3. **可选事实核查**:如果审查内容涉及需要验证的外部事实(历史年代、地理方位、职业细节等),只有在 `Effective Mode` 仍为 `full`/`lean`、当前不是子 Agent、当前运行时的 Agent 工具可用且对应 canonical agent 目录下的 `story-researcher` 已部署时,才可额外 spawn;Antigravity 检查 `.agents/agents/story-researcher/agent.md`,用 `invoke_subagent` + `TypeName: "story-researcher"`。`solo`、missing/malformed/stale/spawn failed 降级或子代理递归保护场景下不得 spawn,只能在报告中标记“需人工事实核查”。
|
|
357
363
|
4. **分歧呈现**:如果 reviewer 间有冲突意见,明确呈现分歧让用户裁决;不要自动妥协。
|
|
358
|
-
5.
|
|
364
|
+
5. 按「报告面向作者」输出综合审查报告:开头说明审查方式与范围,证据不足项写成作者能补的材料,执行路径只进技术备注行。
|
|
359
365
|
|
|
360
366
|
---
|
|
361
367
|
|
|
362
368
|
## Phase 4:输出报告(full / lean 模式)
|
|
363
369
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
注意:下列 `Requested Mode`、`Effective Mode`、`Fallback`、`Rubric`、`Rubric Source` 五个英文 key 必须逐字保留;不要改成“请求模式/实际模式/回退/评估标准”等中文 key。
|
|
370
|
+
只有实际模式确实为 `full` 或 `lean` 时才使用本模板;如果 Phase 0 或运行时失败导致降级 `solo`,必须改用 solo 模式模板。lean 排除的视角写进「这次怎么审的」;full/lean 必需 reviewer 缺失或 spawn 失败时降级 solo,不在本模板里标「未看」后继续综合。
|
|
367
371
|
|
|
372
|
+
<!-- author-report -->
|
|
368
373
|
```md
|
|
369
|
-
===
|
|
370
|
-
|
|
371
|
-
Effective Mode: full | lean
|
|
372
|
-
Fallback: none
|
|
373
|
-
Rubric: fanqie | qidian | zhihu | generic web-fiction
|
|
374
|
-
Rubric Source: file | embedded fallback
|
|
375
|
-
审查范围: {章节/文件/批次}
|
|
376
|
-
|
|
377
|
-
## Verdict Summary / 结论汇总
|
|
378
|
-
- story-architect: APPROVE / CONCERNS(n) / REJECT / NOT_RUN
|
|
379
|
-
- character-designer: APPROVE / CONCERNS(n) / REJECT / NOT_RUN
|
|
380
|
-
- narrative-writer: APPROVE / CONCERNS(n) / REJECT / NOT_RUN
|
|
381
|
-
- consistency-checker: APPROVE / CONCERNS(n) / REJECT / NOT_RUN
|
|
374
|
+
=== 《{书名}》{审查范围}审查 ===
|
|
375
|
+
这次怎么审的:{结构、人物、文字、设定一致性四个视角分头看 | 精简审:结构和设定一致性两个视角},按{番茄 | 起点 | 知乎盐言 | 通用网文}的标准。
|
|
382
376
|
|
|
383
|
-
|
|
377
|
+
总体判断:{可以发 | 改完下面几处再发 | 这一章需要重写}——{一句话理由,用读者感受说}
|
|
384
378
|
|
|
385
|
-
##
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
- S4: n
|
|
379
|
+
## 必须改({n} 处)
|
|
380
|
+
1. 第{N}章「{原文引用}」
|
|
381
|
+
问题:{读者会怎么想、哪里读不通}
|
|
382
|
+
建议:{具体改法}
|
|
390
383
|
|
|
391
|
-
##
|
|
392
|
-
|
|
384
|
+
## 建议改({n} 处)
|
|
385
|
+
{同上格式}
|
|
393
386
|
|
|
394
|
-
##
|
|
395
|
-
{
|
|
387
|
+
## 可以不改({n} 处)
|
|
388
|
+
{一行一条:位置 + 问题 + 改法;风格微调也放这里}
|
|
396
389
|
|
|
397
|
-
##
|
|
398
|
-
{
|
|
390
|
+
## 需要你决定
|
|
391
|
+
{审稿视角有分歧、或事实需要你裁定时,写成问题 + 选项 + 我的建议,例如「第12章写左臂受伤、第15章写右臂,统一成哪边?建议左臂(第12章交代了伤的来历)」;没有就写"无"}
|
|
399
392
|
|
|
400
|
-
##
|
|
401
|
-
{
|
|
393
|
+
## 没法判断的地方
|
|
394
|
+
{缺哪份设定或大纲导致没法核对、需要人工查证的外部事实;没有就写"无"}
|
|
402
395
|
|
|
403
|
-
##
|
|
404
|
-
{
|
|
396
|
+
## 下一批接着核对
|
|
397
|
+
{仅分批审查:留到下一批回头看的问题 + 预计在哪几章兑现;否则删掉本节}
|
|
405
398
|
|
|
406
|
-
|
|
407
|
-
{
|
|
399
|
+
下一步:{例如「说"改第12章",我按必须改的几处动手」「AI 味集中的段落可以说"去 AI 味"」}
|
|
400
|
+
技术备注:Mode {full | lean}→{full | lean} · Fallback none · Rubric {…} ({file | embedded})
|
|
408
401
|
```
|
|
409
402
|
|
|
410
403
|
---
|
|
@@ -414,50 +407,50 @@ APPROVE(通过) / CONCERNS(有问题) / REJECT(需重写)
|
|
|
414
407
|
不 spawn Agent。先按 Phase 1 第 4 步识别目标平台并加载对应 rubric;即使是 solo,也必须用平台 rubric、`story-review/references/quality-rubric.md` 或内置审查基准包校准判断。
|
|
415
408
|
|
|
416
409
|
solo 必须执行基础检查:
|
|
417
|
-
1.
|
|
410
|
+
1. 格式合规性检查:按戏剧单元/画面分段而非机械按字数切分(偶发稍长的完整推理、氛围或情绪链不算违规,通篇同阈值切段或碎成提纲才算);段首建立主语、段中用代词或省略,连续无必要重复同一角色名才算主语过密;无段间空行;对话独立成行;具体数字须确认统计正确且有叙事必要。
|
|
418
411
|
2. 简单的设定一致性 grep(角色名、属性、关键设定、伏笔关键词)+ 推理型一致性检查(规则边界、设定层级、跨章因果链、可滥用漏洞、代价一致性)。
|
|
419
412
|
3. AI 味与禁用词检查(优先读取 `story-review/references/banned-words.md` 与 `story-review/references/anti-ai-writing.md`,不可读时使用内置 AI 味 / 禁用词 fallback 速查)。
|
|
420
413
|
4. 通用网文内容评分(优先读取 `story-review/references/quality-rubric.md`,不可读时使用内置通用网文内容 rubric)。
|
|
421
|
-
5. 按统一 Findings Schema
|
|
414
|
+
5. 按统一 Findings Schema 整理问题,再按下方模板写给作者。
|
|
422
415
|
|
|
423
416
|
### solo 模式输出格式
|
|
424
417
|
|
|
418
|
+
<!-- author-report -->
|
|
425
419
|
```md
|
|
426
|
-
===
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
Rubric: fanqie | qidian | zhihu | generic web-fiction
|
|
431
|
-
Rubric Source: file | embedded fallback
|
|
432
|
-
审查范围: {章节/文件}
|
|
420
|
+
=== 《{书名}》{审查范围}审查(单人审)===
|
|
421
|
+
这次怎么审的:我一个人审{;原因一句话,如"审稿助手还没装,运行 /story-setup 后可以四个视角审"},按{番茄 | 起点 | 知乎盐言 | 通用网文}的标准。
|
|
422
|
+
|
|
423
|
+
总体判断:{可以发 | 改完下面几处再发 | 这一章需要重写}——{一句话理由}
|
|
433
424
|
|
|
434
|
-
##
|
|
425
|
+
## 格式与设定
|
|
426
|
+
- 分段与人名节奏:{没问题 | 第N章第M段起……}
|
|
427
|
+
- 空行与对话换行:{没问题 | ……}
|
|
428
|
+
- 具体数字:{没问题 | 第N章「……」对不上或没必要}
|
|
429
|
+
- 前后矛盾:{没发现 | 第N章「……」与第M章「……」矛盾}
|
|
430
|
+
- 因果和规则漏洞:{没发现 | ……}
|
|
435
431
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
- [{x| }] 对话独立成行:通过/不通过;证据:...
|
|
441
|
-
- [{x| }] 具体字数表达已确认统计正确且有叙事必要;不能确认时已改成非具体数字表达:通过/不通过;证据:...
|
|
442
|
-
- 违规位置:{列出}
|
|
432
|
+
## 必须改({n} 处)
|
|
433
|
+
1. 第{N}章「{原文引用}」
|
|
434
|
+
问题:{读者会怎么想、哪里读不通}
|
|
435
|
+
建议:{具体改法}
|
|
443
436
|
|
|
444
|
-
|
|
437
|
+
## 建议改({n} 处)
|
|
438
|
+
{同上格式}
|
|
445
439
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
- 推理型一致性:{规则边界/设定层级/跨章因果/可滥用漏洞/代价一致性的发现;无则写“未发现”}
|
|
440
|
+
## 可以不改({n} 处)
|
|
441
|
+
{一行一条}
|
|
449
442
|
|
|
450
|
-
|
|
451
|
-
|
|
443
|
+
## 需要你决定
|
|
444
|
+
{问题 + 选项 + 我的建议;没有就写"无"}
|
|
452
445
|
|
|
453
|
-
|
|
454
|
-
{
|
|
446
|
+
## 没法判断的地方
|
|
447
|
+
{缺哪份设定或大纲导致没法核对、需要人工查证的外部事实;没有就写"无"}
|
|
455
448
|
|
|
456
|
-
|
|
457
|
-
{
|
|
449
|
+
## 下一批接着核对
|
|
450
|
+
{仅分批审查填写;否则删掉本节}
|
|
458
451
|
|
|
459
|
-
|
|
460
|
-
{
|
|
452
|
+
下一步:{一句话}
|
|
453
|
+
技术备注:Mode {full | lean | solo}→solo · Fallback {…} · Rubric {…} ({file | embedded})
|
|
461
454
|
```
|
|
462
455
|
|
|
463
456
|
---
|