@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
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""build_architect_brief.py — 把「出卷纲」「出一批细纲」这一时刻要用的流程与模板拼成任务包。
|
|
3
|
+
|
|
4
|
+
用法:
|
|
5
|
+
python build_architect_brief.py --project <书目录> --task world
|
|
6
|
+
python build_architect_brief.py --project <书目录> --task volume [--volume N]
|
|
7
|
+
python build_architect_brief.py --project <书目录> --task outline --chapters A-B
|
|
8
|
+
python build_architect_brief.py --project <临时目录> --task <任务> --rules-only # 仓库预算守卫计量用
|
|
9
|
+
|
|
10
|
+
开书与规划按作者确认点分时刻(见 references/workflow-setup.md)。卷纲与每批细纲最重,
|
|
11
|
+
有子代理时交给 story-architect 在新上下文里做:主会话只跑本脚本、把任务包路径交给它,
|
|
12
|
+
自己不读包里的内容。任务包写在书内 `.story/work/排纲/`,是这次任务的输入数据,不是 reference。
|
|
13
|
+
|
|
14
|
+
包里只有该时刻需要的东西,三种任务都附 SKILL.md 的「新增物三级」判据(包外读不到 SKILL.md):
|
|
15
|
+
- world:workflow-setup.md 的 Phase 2 与设定模板、character-basics.md、long-genre-mechanics.md 的
|
|
16
|
+
「核心梗三层递进设计」、character-relations.md 的「人物关系类型」、reader-contract-and-progression.md。
|
|
17
|
+
- volume:workflow-volume.md(卷纲流程、排纲自查、节奏锚与对标迁移)、artifact-protocols.md
|
|
18
|
+
(大纲与卷纲模板)、emotional-methods.md 的「长篇单元情绪引擎」(排纲自查第 1 项)、
|
|
19
|
+
reader-contract-and-progression.md(第 4 项契约四问)。
|
|
20
|
+
- outline:workflow-outline.md(批次步骤、细纲模板与验收、补纲、设定补全、排纲底稿模板)、
|
|
21
|
+
character-basics.md 的主角卡与配角卡模板;首章在范围内时加 opening-design.md。
|
|
22
|
+
流程里点名、但只在某些书才用得上的参考(多对标时的跨书召回、女频手册、弧线与反转速查、灵感库)
|
|
23
|
+
不进包,列在包末「按条件可读」,给出绝对路径与小节,条件满足才读。
|
|
24
|
+
本书的方向、设定与作者口头定下的事都在 `设定/`,不进包,由执行者按包里的流程定点读。
|
|
25
|
+
`--rules-only` 只拼规则部分(不取本书卷纲),供仓库的预算守卫计量每次调用的加载量。
|
|
26
|
+
|
|
27
|
+
stdout 输出一行 JSON:任务包路径、字数(去空白)、包含的资料。
|
|
28
|
+
Exit: 0 = 已写出;2 = 参数或资料缺失(含卷纲单元只覆盖了请求章节的一部分)。
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import argparse
|
|
34
|
+
import json
|
|
35
|
+
import re
|
|
36
|
+
import sys
|
|
37
|
+
from pathlib import Path
|
|
38
|
+
|
|
39
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
40
|
+
from outline_view import parse as parse_volume, slice_arc, strip_retired, unit_chapter_range # noqa: E402
|
|
41
|
+
|
|
42
|
+
SKILL_ROOT = Path(__file__).resolve().parent.parent
|
|
43
|
+
REFERENCES = SKILL_ROOT / "references"
|
|
44
|
+
WORK_DIR = (".story", "work", "排纲")
|
|
45
|
+
# 包外按条件可读:(文件, 小节或 None=整份, 条件)。条件由执行者读 `设定/` 判断。
|
|
46
|
+
CROSS_BOOK = ("cross-book-recall.md", None, "`设定/题材定位.md`「对标登记」里有 2 本及以上对标书")
|
|
47
|
+
INSPIRATION = ("cross-book-recall.md", "公共灵感标签召回", "工作区有 `灵感库/`(零命中不阻塞)")
|
|
48
|
+
CONDITIONAL = {
|
|
49
|
+
"world": [("female-audience-writing.md", None, "本书是女频"), CROSS_BOOK, INSPIRATION],
|
|
50
|
+
"volume": [CROSS_BOOK, ("emotional-arc-design.md", "六种弧线速查", "情绪弧线选型拿不准"),
|
|
51
|
+
("long-reversal.md", "反转类型", "本卷规划了反转"), INSPIRATION],
|
|
52
|
+
"outline": [CROSS_BOOK, INSPIRATION],
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def read_reference(name: str) -> str:
|
|
57
|
+
path = REFERENCES / name
|
|
58
|
+
if not path.is_file():
|
|
59
|
+
raise SystemExit(f"ERROR: 缺少 reference:{path}")
|
|
60
|
+
return path.read_text(encoding="utf-8").lstrip("")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def section(text: str, start: str, end: str | None = None) -> str:
|
|
64
|
+
"""取 start 标题行到 end 标题行之前(end 省略则到文末);找不到 start 就报错,不静默给空。"""
|
|
65
|
+
match = re.search(rf"^#+\s*{re.escape(start)}.*$", text, re.M)
|
|
66
|
+
if match is None:
|
|
67
|
+
raise SystemExit(f"ERROR: reference 里找不到小节「{start}」")
|
|
68
|
+
stop = re.search(rf"^#+\s*{re.escape(end)}.*$", text[match.end():], re.M) if end else None
|
|
69
|
+
return text[match.start(): match.end() + stop.start() if stop else len(text)].rstrip()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def new_addition_tiers() -> str:
|
|
73
|
+
"""SKILL.md 的「新增物三级」判据:排纲、定设定都要按它分级,而任务包外的 SKILL.md 读不到。"""
|
|
74
|
+
text = (SKILL_ROOT / "SKILL.md").read_text(encoding="utf-8")
|
|
75
|
+
match = re.search(r"^> \*\*新增物三级\*\*.*?(?=^(?!>))", text, re.M | re.S)
|
|
76
|
+
if match is None:
|
|
77
|
+
raise SystemExit("ERROR: SKILL.md 里找不到「新增物三级」")
|
|
78
|
+
return "\n".join(line[2:] if line.startswith("> ") else line.lstrip(">") for line in match.group(0).rstrip().splitlines())
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def conditional_reads(task: str) -> str:
|
|
82
|
+
lines = ["下面几份在包外,只在条件满足时读,只读点名的那一节(没点名读整份);条件不满足不读:"]
|
|
83
|
+
for name, part, when in CONDITIONAL[task]:
|
|
84
|
+
where = f"「{part}」一节" if part else "整份"
|
|
85
|
+
lines.append(f"- {when}:读 `{REFERENCES / name}` {where}")
|
|
86
|
+
return "\n".join(lines)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def emit(text: str, stream) -> None:
|
|
90
|
+
"""统一按 UTF-8 写出:Windows 控制台默认 GBK/ASCII 时直接 print 中文会崩。"""
|
|
91
|
+
stream.buffer.write((text + "\n").encode("utf-8"))
|
|
92
|
+
stream.flush()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def render(sections, chosen, span, preamble) -> str:
|
|
96
|
+
"""与 outline_view.emit 同一取法(剔除已退役条目、情绪弧线按单元截段),只是返回文本。"""
|
|
97
|
+
out = ["\n".join(strip_retired(preamble, False)).rstrip()] if preamble else []
|
|
98
|
+
for sec in sections:
|
|
99
|
+
if sec not in chosen:
|
|
100
|
+
continue
|
|
101
|
+
body = slice_arc(sec, span) if ("情绪弧线" in sec.title or "排班" in sec.title) else sec.lines
|
|
102
|
+
out.append("\n".join(strip_retired(body, False)).rstrip())
|
|
103
|
+
return "\n\n".join(out) + "\n"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def unit_closures(project: Path, first: int, last: int) -> list[tuple[str, str]]:
|
|
107
|
+
"""story-architect 没有执行命令的权限:由脚本先把覆盖本批章节的剧情单元闭包取出来放进包里。
|
|
108
|
+
|
|
109
|
+
取法同 `outline_view.py --unit U --stage outline`;一卷里有几个单元时,卷契约与卷级常任只随第一个单元给一次。"""
|
|
110
|
+
found: list[tuple[str, str]] = []
|
|
111
|
+
covered: set[int] = set()
|
|
112
|
+
undeclared: list[str] = []
|
|
113
|
+
for volume in sorted((project / "大纲").glob("卷纲_第*卷.md")):
|
|
114
|
+
lines, sections = parse_volume(volume.read_text(encoding="utf-8"))
|
|
115
|
+
# 单元卡有标题、没写作用域行时取段器认不出它——点名缺哪一行,而不是笼统说找不到单元。
|
|
116
|
+
undeclared += [f"{volume.name}「{s.title.strip()}」" for s in sections
|
|
117
|
+
if s.scope is None and s.unit and "剧情单元" in s.title]
|
|
118
|
+
if any(s.scope and (s.kind is None or (s.kind != "卷级常任" and s.unit is None)) for s in sections):
|
|
119
|
+
raise SystemExit(f"ERROR: {volume.name} 作用域声明无效,先跑 outline_view.py --check 修正")
|
|
120
|
+
active = [s for s in sections if s.status != "已退役"]
|
|
121
|
+
shared = [s for s in active if s.kind == "卷级常任" or s.scope is None]
|
|
122
|
+
units = sorted({s.unit for s in active if s.unit and s.kind == "单元级"})
|
|
123
|
+
given = False
|
|
124
|
+
for unit in units:
|
|
125
|
+
span = unit_chapter_range(active, unit)
|
|
126
|
+
if not (span and span[0] <= last and span[1] >= first):
|
|
127
|
+
continue
|
|
128
|
+
covered.update(range(span[0], span[1] + 1))
|
|
129
|
+
live = [s for s in active if s.unit == unit and s.kind in ("单元级", "批次底稿")]
|
|
130
|
+
if given:
|
|
131
|
+
text = "(卷契约与卷级常任同上一段,不重复。)\n\n" + render(sections, set(live), span, None)
|
|
132
|
+
else:
|
|
133
|
+
text = render(sections, set(shared + live), span, lines[:sections[0].start] if sections else None)
|
|
134
|
+
given = True
|
|
135
|
+
found.append((f"{volume.name} · 单元 {unit}(第{span[0]}-{span[1]}章)", text))
|
|
136
|
+
missing = [n for n in range(first, last + 1) if n not in covered]
|
|
137
|
+
if missing:
|
|
138
|
+
hint = (f";这些单元卡缺「> 作用域:单元级 {{单元ID}}」声明行:{'、'.join(undeclared)}"
|
|
139
|
+
if undeclared else "(单元卡要写「> 作用域:单元级 {单元ID}」和「章节范围:第A-B章」)")
|
|
140
|
+
where = "找不到覆盖" if not found else "剧情单元只覆盖了一部分,缺覆盖"
|
|
141
|
+
raise SystemExit(f"ERROR: 卷纲里{where}第{compress(missing)}章的剧情单元{hint},先补卷纲"
|
|
142
|
+
"(`outline_view.py --check --strict` 列出全部问题)")
|
|
143
|
+
return found
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def compress(numbers: list[int]) -> str:
|
|
147
|
+
"""[4, 5, 6, 9] → 4-6、9"""
|
|
148
|
+
spans, start = [], numbers[0]
|
|
149
|
+
for prev, cur in zip(numbers, numbers[1:] + [None]):
|
|
150
|
+
if cur != prev + 1:
|
|
151
|
+
spans.append(f"{start}-{prev}" if start != prev else f"{start}")
|
|
152
|
+
start = cur
|
|
153
|
+
return "、".join(spans)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def weight(text: str) -> int:
|
|
157
|
+
return len(re.sub(r"\s", "", text))
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def build(task: str, volume: int | None, chapters: tuple[int, int] | None,
|
|
161
|
+
project: Path | None = None, rules_only: bool = False) -> tuple[str, list[str]]:
|
|
162
|
+
outside = "写作技法只读本包,外加包末「按条件可读」里条件满足的那几节。"
|
|
163
|
+
if task == "world":
|
|
164
|
+
head = ("# 任务包:出核心设定提案\n\n"
|
|
165
|
+
"按下面 Phase 2 的流程,把核心设定写成文件:`设定/题材定位.md`(在定方向时已写的部分上补全,不删作者已定的内容)、"
|
|
166
|
+
"`设定/关系.md`、主角与关键角色的 `设定/角色/{名}.md`、影响全书的 `设定/世界观/{主题}.md`。"
|
|
167
|
+
"作者在定方向时说过的话都在 `设定/题材定位.md`,先读它;拿不准的写成二选一的候选留给作者定,不替作者拍板,"
|
|
168
|
+
"物价、收入、力量档位这类全书刻度按下附「新增物三级」属先问作者,只给候选。"
|
|
169
|
+
f"不出卷纲、不写正文。{outside}交付后只回:写了哪些文件、主角与核心冲突各一句、"
|
|
170
|
+
"要作者定的事(没有写「无」)。")
|
|
171
|
+
setup = read_reference("workflow-setup.md")
|
|
172
|
+
parts = [("workflow-setup.md(Phase 2 与设定模板)",
|
|
173
|
+
section(setup, "Phase 2:核心设定", "Agent 调用:story-architect + character-designer") + "\n\n"
|
|
174
|
+
+ section(setup, "定设定时建的文件模板")),
|
|
175
|
+
("character-basics.md", read_reference("character-basics.md")),
|
|
176
|
+
("long-genre-mechanics.md(核心梗三层递进设计)",
|
|
177
|
+
section(read_reference("long-genre-mechanics.md"), "核心梗三层递进设计", "微创新与差异化设计")),
|
|
178
|
+
("character-relations.md(人物关系类型)",
|
|
179
|
+
section(read_reference("character-relations.md"), "人物关系类型", "感情流人设核心法")),
|
|
180
|
+
("reader-contract-and-progression.md", read_reference("reader-contract-and-progression.md"))]
|
|
181
|
+
elif task == "volume":
|
|
182
|
+
label = f"第{volume}卷" if volume else "本卷"
|
|
183
|
+
head = (f"# 任务包:出{label}卷纲\n\n"
|
|
184
|
+
f"只交付全书体量与阶段总览(`大纲/大纲.md`,已有就只补本卷相关部分)和 `大纲/卷纲_第{volume or 'X'}卷.md`,"
|
|
185
|
+
"不出细纲、不写正文、不建 `追踪/`。本书方向、设定、对标登记与作者已定的事读 `设定/`(先读 "
|
|
186
|
+
f"`设定/题材定位.md`)。{outside}交付后只回:写了哪些文件、排纲自查 1–4 "
|
|
187
|
+
"的结论各一句、要作者定的事(没有写「无」)。")
|
|
188
|
+
parts = [("workflow-volume.md", read_reference("workflow-volume.md")),
|
|
189
|
+
("artifact-protocols.md", read_reference("artifact-protocols.md")),
|
|
190
|
+
("emotional-methods.md(长篇单元情绪引擎)",
|
|
191
|
+
section(read_reference("emotional-methods.md"), "长篇单元情绪引擎", "决策路由")),
|
|
192
|
+
("reader-contract-and-progression.md", read_reference("reader-contract-and-progression.md"))]
|
|
193
|
+
else:
|
|
194
|
+
first, last = chapters
|
|
195
|
+
head = (f"# 任务包:出第{first}-{last}章细纲\n\n"
|
|
196
|
+
f"只交付 `大纲/细纲_第{first:03d}章` 到第{last:03d}章,以及排纲底稿与必要的设定补全,不写正文、"
|
|
197
|
+
"不建 `追踪/`。本批涉及的卷纲单元段附在包末(已按单元取好),卷纲本身不整读;设定从 `设定/` 定点读;"
|
|
198
|
+
f"{outside}交付后只回:写了哪些文件、"
|
|
199
|
+
"每章一句核心事件、要作者定的事(没有写「无」)。")
|
|
200
|
+
basics = read_reference("character-basics.md")
|
|
201
|
+
parts = [("workflow-outline.md", read_reference("workflow-outline.md")),
|
|
202
|
+
("character-basics.md(主角卡、配角卡)", section(basics, "第1节:主角卡", "第3节"))]
|
|
203
|
+
if first <= 3:
|
|
204
|
+
parts.append(("opening-design.md", read_reference("opening-design.md")))
|
|
205
|
+
if not rules_only:
|
|
206
|
+
parts += [(f"卷纲取段:{name}", text) for name, text in unit_closures(project, first, last)]
|
|
207
|
+
parts.append(("SKILL.md(新增物三级)", new_addition_tiers()))
|
|
208
|
+
parts.append(("按条件可读(包外)", conditional_reads(task)))
|
|
209
|
+
body = [head + ("\n\n包里流程写到的脚本命令(取段、`--check`、`check-outline-contract.js`)由主会话在你交付后跑,"
|
|
210
|
+
"你不执行命令;需要的取段结果已放进包里。")]
|
|
211
|
+
for name, text in parts:
|
|
212
|
+
body.append(f"\n---\n\n<!-- 资料:{name} -->\n\n{text.strip()}\n")
|
|
213
|
+
return "\n".join(body), [name for name, _ in parts]
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def parse_range(value: str) -> tuple[int, int]:
|
|
217
|
+
match = re.fullmatch(r"\s*(\d+)\s*(?:-\s*(\d+))?\s*", value or "")
|
|
218
|
+
if not match:
|
|
219
|
+
raise SystemExit("ERROR: --chapters 写成 A-B,如 1-10")
|
|
220
|
+
first = int(match.group(1))
|
|
221
|
+
last = int(match.group(2) or first)
|
|
222
|
+
if first < 1 or last < first:
|
|
223
|
+
raise SystemExit("ERROR: --chapters 范围无效")
|
|
224
|
+
return first, last
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def main(argv=None) -> int:
|
|
228
|
+
parser = argparse.ArgumentParser(description="拼出 story-architect 出卷纲/细纲的任务包")
|
|
229
|
+
parser.add_argument("--project", required=True, type=Path, help="书目录")
|
|
230
|
+
parser.add_argument("--task", required=True, choices=("world", "volume", "outline"))
|
|
231
|
+
parser.add_argument("--volume", type=int, help="卷号(volume 任务)")
|
|
232
|
+
parser.add_argument("--chapters", help="章节范围 A-B(outline 任务)")
|
|
233
|
+
parser.add_argument("--rules-only", action="store_true", help="只拼规则部分、不取本书卷纲(预算守卫计量用)")
|
|
234
|
+
args = parser.parse_args(argv)
|
|
235
|
+
try:
|
|
236
|
+
if not args.project.is_dir():
|
|
237
|
+
raise SystemExit(f"ERROR: 书目录不存在:{args.project}")
|
|
238
|
+
chapters = parse_range(args.chapters) if args.task == "outline" else None
|
|
239
|
+
if args.task == "outline" and chapters[1] - chapters[0] >= 10:
|
|
240
|
+
raise SystemExit("ERROR: 一批细纲最多 10 章,拆成两批")
|
|
241
|
+
text, included = build(args.task, args.volume, chapters, args.project, args.rules_only)
|
|
242
|
+
except SystemExit as exc:
|
|
243
|
+
emit(str(exc), sys.stderr)
|
|
244
|
+
return 2
|
|
245
|
+
out_dir = args.project.joinpath(*WORK_DIR)
|
|
246
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
247
|
+
if args.task == "world":
|
|
248
|
+
name = "核心设定.md"
|
|
249
|
+
elif args.task == "volume":
|
|
250
|
+
name = f"卷纲_第{args.volume}卷.md" if args.volume else "卷纲.md"
|
|
251
|
+
else:
|
|
252
|
+
name = f"细纲_第{chapters[0]:03d}-{chapters[1]:03d}章.md"
|
|
253
|
+
out = out_dir / name
|
|
254
|
+
out.write_text(text, encoding="utf-8")
|
|
255
|
+
emit(json.dumps({"brief": str(out), "chars": weight(text), "includes": included}, ensure_ascii=False), sys.stdout)
|
|
256
|
+
return 0
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
if __name__ == "__main__":
|
|
260
|
+
sys.exit(main())
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
"""build_writer_prompt.py — 确定性组装 narrative-writer 的 spawn prompt 骨架。
|
|
3
3
|
|
|
4
4
|
用法:
|
|
5
|
-
python build_writer_prompt.py --project <书目录> --chapter N [--out <文件>]
|
|
5
|
+
python build_writer_prompt.py --project <书目录> --chapter N [--out [<文件>]]
|
|
6
|
+
|
|
7
|
+
`--out` 不带路径时留档到本章工作目录 `<书目录>/.story/work/第NNN章/writer_prompt.md`。
|
|
8
|
+
分组 segment、prompt 留档和逐章事务 JSON 都只放这个书内工作目录——不写系统 /tmp
|
|
9
|
+
(多本书/多会话同章号会互相覆盖,Windows 也没有 /tmp),也不写进 正文/(会被当成章节)。
|
|
10
|
+
`storyctl.py chapter commit` 成功后自动删除该章工作目录。
|
|
6
11
|
|
|
7
12
|
跑在「写前准备」第一步。stdout 分两区,`===` 分隔线以上是 prompt 正文
|
|
8
13
|
(主会话照抄,空槽以外一字不改),以下是核对报告(不进 prompt)。
|
|
@@ -10,10 +15,16 @@
|
|
|
10
15
|
职责边界:
|
|
11
16
|
- 脚本做确定性部分:固定首行、定位、标题行字面量、细纲指针、文风全文路径与裁决、
|
|
12
17
|
上一章结尾、降档判定与情绪/节奏槽、固定块指针。
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
- 脚本代查作者记忆(prose_style + story_design)并填好 author_preferences。
|
|
19
|
+
- 脚本注入 `设定/题材定位.md`「作者已定」(本书的偏好、红线与否掉的方案),超过 AUTHOR_DECIDED_CHARS
|
|
20
|
+
可见字截断并注明去原文看;它是书级设定,优先于作者记忆。
|
|
21
|
+
- 主会话填九个固定槽:执行安排 / 本章意图 / 作者本轮要求 / 本章技法 / 本节速记 / 涉及角色 /
|
|
22
|
+
genre_prose_card / 必读设定 / style_resolution。另有两个条件槽,出现时同样标[主会话填]:
|
|
23
|
+
author_preferences 块内的限定范围(--genre/--workflow)作者记忆未代查时,由主会话判断是否适用后补查
|
|
24
|
+
(脚本查询失败时则整块手查);降档不成立时「情绪与节奏召回」也归主会话。
|
|
25
|
+
核对报告末尾的「待填槽位」给出本次实际个数(9-11)。
|
|
26
|
+
材料槽对应原流程步骤 3「写前准备」的四项输出(本节速记 / 目标情绪 / 涉及角色 /
|
|
27
|
+
本章技法)加上作者本轮要求、题材卡、设定补漏与作者偏好——都是判断,脚本做不了。
|
|
17
28
|
- 续写状态卡校验后由主会话筛选,在「本节速记」槽内写入本章需要的状态。
|
|
18
29
|
- 可选块缺失留标题并写明原因(「没有」与「漏了」在产物上必须长得不一样)。
|
|
19
30
|
必在块缺失退出码 2 —— 那是数据问题,要修数据后重跑,不是回落手拼的理由。
|
|
@@ -23,7 +34,9 @@ Exit: 0 = 骨架已输出;2 = 输入缺失或无效。
|
|
|
23
34
|
|
|
24
35
|
import argparse
|
|
25
36
|
import io
|
|
37
|
+
import json
|
|
26
38
|
import re
|
|
39
|
+
import subprocess
|
|
27
40
|
import sys
|
|
28
41
|
from pathlib import Path
|
|
29
42
|
from outline_view import parse as parse_volume
|
|
@@ -31,6 +44,14 @@ from outline_view import parse as parse_volume
|
|
|
31
44
|
TAIL_CHARS = 400 # 上一章结尾注入的目标字符数(按整行回退,不切半句)
|
|
32
45
|
STATE_SECTIONS = ("当前位置", "长期约束", "核心角色状态", "活跃伏笔", "近三章速记", "下一章承诺", "连贯性风险")
|
|
33
46
|
SLOT_MARK = "[主会话填]"
|
|
47
|
+
AUTHOR_DECIDED_CHARS = 600 # 「作者已定」注入上限(去空白字数);超了截断,写手按提示回原文看
|
|
48
|
+
WORK_ROOT = (".story", "work")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def chapter_work_dir(project: Path, chapter: int) -> Path:
|
|
52
|
+
"""本章临时文件的唯一落点;与 storyctl.py 提交后清理的目录同一口径。"""
|
|
53
|
+
width = max(3, len(str(chapter)))
|
|
54
|
+
return project.joinpath(*WORK_ROOT, f"第{chapter:0{width}d}章")
|
|
34
55
|
|
|
35
56
|
|
|
36
57
|
def read_text(path: Path):
|
|
@@ -58,7 +79,7 @@ def find_chapter_file(directory: Path, chapter: int, prefix: str):
|
|
|
58
79
|
return None
|
|
59
80
|
pattern = re.compile(rf"^{prefix}第0*{chapter}章.*\.md$")
|
|
60
81
|
for entry in sorted(directory.iterdir()):
|
|
61
|
-
if entry.is_file() and pattern.match(entry.name):
|
|
82
|
+
if entry.is_file() and pattern.match(entry.name) and "_原稿_" not in entry.name:
|
|
62
83
|
return entry
|
|
63
84
|
return None
|
|
64
85
|
|
|
@@ -125,6 +146,135 @@ def previous_chapter_tail(project: Path, chapter: int):
|
|
|
125
146
|
return prev, "\n".join(reversed(picked))
|
|
126
147
|
|
|
127
148
|
|
|
149
|
+
MEMORY_KINDS = ("prose_style", "story_design")
|
|
150
|
+
# 限定「流程」的作者记忆里,这些取值指的就是长篇写正文。
|
|
151
|
+
LONG_WRITE_WORKFLOWS = {"长篇", "长篇写作", "写长篇", "长篇连载", "长篇网文", "长篇正文", "story-long-write"}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def scoped_memory_values(workspace: Path):
|
|
155
|
+
"""项目级 store 里限定题材/流程的 active 条目取值:{"genre": {...}, "workflow": {...}}。"""
|
|
156
|
+
values = {"genre": set(), "workflow": set()}
|
|
157
|
+
state = read_text(workspace / ".story" / "作者记忆" / "_author-memory-state.json")
|
|
158
|
+
try:
|
|
159
|
+
items = (json.loads(state) if state else {}).get("items") or {}
|
|
160
|
+
items = list(items.values())
|
|
161
|
+
except (ValueError, AttributeError, TypeError):
|
|
162
|
+
return values
|
|
163
|
+
for item in items:
|
|
164
|
+
if not isinstance(item, dict):
|
|
165
|
+
continue
|
|
166
|
+
scope = item.get("scope") if isinstance(item.get("scope"), dict) else {}
|
|
167
|
+
if (item.get("status") == "active" and item.get("kind") in MEMORY_KINDS
|
|
168
|
+
and scope.get("level") in values and scope.get("value")):
|
|
169
|
+
values[scope["level"]].add(scope["value"])
|
|
170
|
+
return values
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def genre_line(project: Path):
|
|
174
|
+
"""「题材类型」行的原文;未填的模板占位({…})当没有。"""
|
|
175
|
+
text = read_text(project / "设定" / "题材定位.md") or ""
|
|
176
|
+
match = re.search(r"^[ \t]*[-*+]?[ \t]*\**题材(?:类型)?\**[ \t]*[::](.*)$", text, re.M)
|
|
177
|
+
if not match or "{" in match.group(1):
|
|
178
|
+
return ""
|
|
179
|
+
return match.group(1).strip()
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def book_genres(project: Path):
|
|
183
|
+
"""「题材类型」行按分隔符切成词。"""
|
|
184
|
+
return {word.casefold() for word in re.split(r"[\W_丨×]+", genre_line(project)) if word}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
GENRE_CARD_DIR = Path(__file__).resolve().parent.parent / "references" / "genre-prose-cards"
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def match_genre_cards(project: Path):
|
|
191
|
+
"""题材正文提示卡缺失时,按「题材类型」原文匹配题材卡(卡头的 genre 与 aliases),替主会话省掉整读索引。
|
|
192
|
+
|
|
193
|
+
按在题材类型里出现得越靠前越优先(主题材在前),同位置按置信度高→低;最多返回主、辅两张:[(路径, 置信度)]。"""
|
|
194
|
+
raw = genre_line(project).casefold()
|
|
195
|
+
if not raw or not GENRE_CARD_DIR.is_dir():
|
|
196
|
+
return []
|
|
197
|
+
rank = {"high": 0, "medium": 1, "low": 2}
|
|
198
|
+
hits = []
|
|
199
|
+
for card in sorted(GENRE_CARD_DIR.glob("*.md")):
|
|
200
|
+
head = (read_text(card) or "").split("---")
|
|
201
|
+
meta = head[1] if len(head) > 2 else ""
|
|
202
|
+
genre = re.search(r"^genre:\s*(.+)$", meta, re.M)
|
|
203
|
+
aliases = re.search(r"^aliases:\s*\[(.*)\]", meta, re.M)
|
|
204
|
+
confidence = re.search(r"^confidence:\s*(\w+)", meta, re.M)
|
|
205
|
+
names = [genre.group(1).strip()] if genre else [card.stem]
|
|
206
|
+
names += [a.strip() for a in aliases.group(1).split(",")] if aliases else []
|
|
207
|
+
where = [raw.find(name.casefold()) for name in names if name and name.casefold() in raw]
|
|
208
|
+
if where:
|
|
209
|
+
level = confidence.group(1) if confidence else "low"
|
|
210
|
+
hits.append((min(where), rank.get(level, 2), card, level))
|
|
211
|
+
hits.sort(key=lambda row: (row[0], row[1], row[2].name))
|
|
212
|
+
return [(card, level) for _, _, card, level in hits[:2]]
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def author_decided(project: Path):
|
|
216
|
+
"""`设定/题材定位.md`「## 作者已定」一节:去掉模板占位行;返回 (正文, 是否截断)。没有这一节返回 (None, False)。"""
|
|
217
|
+
text = read_text(project / "设定" / "题材定位.md") or ""
|
|
218
|
+
match = re.search(r"^##[ \t]*作者已定[^\n]*\n(.*?)(?=^#{1,2}[ \t]|\Z)", text, re.M | re.S)
|
|
219
|
+
if not match:
|
|
220
|
+
return None, False
|
|
221
|
+
lines = [line.rstrip() for line in match.group(1).splitlines()
|
|
222
|
+
if line.strip() and not re.fullmatch(r"\s*[-*+]?\s*\{.*\}\s*", line)]
|
|
223
|
+
kept, used, cut = [], 0, False
|
|
224
|
+
for line in lines:
|
|
225
|
+
size = len(re.sub(r"\s", "", line))
|
|
226
|
+
if used + size > AUTHOR_DECIDED_CHARS:
|
|
227
|
+
cut = True
|
|
228
|
+
break
|
|
229
|
+
kept.append(line)
|
|
230
|
+
used += size
|
|
231
|
+
return "\n".join(kept), cut
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def query_author_memory(project: Path):
|
|
235
|
+
"""代主会话做写正文那一次作者记忆查询(prose_style + story_design,每次 ≤2KB)。
|
|
236
|
+
|
|
237
|
+
工作区取书目录及其祖先里第一个带 `.story-deployed` 的目录;找不到就把书目录当工作区。
|
|
238
|
+
限定题材的条目只在取值出现在本书「题材类型」里时代查,限定流程的只认长篇写作的取值;
|
|
239
|
+
其余限定条目不猜,报给主会话自己判断。
|
|
240
|
+
返回 (条目列表, 超编 ID 列表, 未代查的限定取值, 错误);错误时由主会话按 author-memory.md 手动查询。
|
|
241
|
+
"""
|
|
242
|
+
workspace = next((d for d in (project, *project.parents) if (d / ".story-deployed").is_file()), project)
|
|
243
|
+
script = Path(__file__).with_name("author_memory_commit.py")
|
|
244
|
+
if not script.is_file():
|
|
245
|
+
return None, [], {}, "author_memory_commit.py 缺失"
|
|
246
|
+
scoped = scoped_memory_values(workspace)
|
|
247
|
+
book = book_genres(project)
|
|
248
|
+
genres = sorted(v for v in scoped["genre"] if v.casefold() in book) or [None]
|
|
249
|
+
workflows = sorted(v for v in scoped["workflow"] if v.casefold() in {w.casefold() for w in LONG_WRITE_WORKFLOWS})
|
|
250
|
+
skipped = {"genre": sorted(v for v in scoped["genre"] if v not in genres),
|
|
251
|
+
"workflow": sorted(v for v in scoped["workflow"] if v not in workflows)}
|
|
252
|
+
items, omitted, seen = [], [], set()
|
|
253
|
+
for genre in genres:
|
|
254
|
+
for workflow in workflows or [None]:
|
|
255
|
+
command = [sys.executable, str(script), "query", "--workspace", str(workspace), "--book-root", str(project)]
|
|
256
|
+
for kind in MEMORY_KINDS:
|
|
257
|
+
command += ["--kind", kind]
|
|
258
|
+
if genre:
|
|
259
|
+
command += ["--genre", genre]
|
|
260
|
+
if workflow:
|
|
261
|
+
command += ["--workflow", workflow]
|
|
262
|
+
completed = subprocess.run(command, capture_output=True, text=True, encoding="utf-8", check=False)
|
|
263
|
+
try:
|
|
264
|
+
result = json.loads(completed.stdout or "{}")
|
|
265
|
+
except ValueError:
|
|
266
|
+
result = {}
|
|
267
|
+
if not result.get("ok"):
|
|
268
|
+
return None, [], {}, result.get("error") or completed.stderr.strip() or "query 失败"
|
|
269
|
+
for item in result.get("items") or []:
|
|
270
|
+
if item.get("id") not in seen:
|
|
271
|
+
seen.add(item.get("id"))
|
|
272
|
+
items.append(item)
|
|
273
|
+
omitted += [i for i in result.get("omitted_ids") or [] if i not in omitted and i not in seen]
|
|
274
|
+
omitted = [i for i in omitted if i not in seen]
|
|
275
|
+
return items, omitted, {k: v for k, v in skipped.items() if v}, None
|
|
276
|
+
|
|
277
|
+
|
|
128
278
|
def learn_heading_form(project: Path, chapter: int, title: str):
|
|
129
279
|
"""从已有正文学标题行形态(层级/章号填充位数/分隔符),不按通用规则推导。
|
|
130
280
|
|
|
@@ -233,7 +383,7 @@ def build(project: Path, chapter: int, report: list):
|
|
|
233
383
|
parts.append(
|
|
234
384
|
"——— 文风 ———\n"
|
|
235
385
|
"(本书无可用的 设定/文风.md,未进入自定义文风模式;"
|
|
236
|
-
"按
|
|
386
|
+
"按 benchmark-recall.md 走对标文风召回,由主会话补路径与召回指令)")
|
|
237
387
|
report.append("文风:custom_style=false,文风召回归主会话(未跳过,留标题)")
|
|
238
388
|
|
|
239
389
|
# ---- 上一章结尾(不给路径,避免写手回头读整章)----
|
|
@@ -277,7 +427,10 @@ def build(project: Path, chapter: int, report: list):
|
|
|
277
427
|
needs = {"题材正文提示卡": card_text, "目标情绪": target_emotion,
|
|
278
428
|
"单元情绪引擎": engine, "单元节拍/章功能分配": tempo}
|
|
279
429
|
why = [name + "缺有效内容" for name, value in needs.items() if not substantive(value)]
|
|
280
|
-
|
|
430
|
+
# 无对标(项目与工作区都没有对标书)时文风本就没有对标可召回:不因 custom_style 缺失拒绝降档
|
|
431
|
+
no_benchmark = not any(d.is_dir() for base in (project / "对标", project / "拆文库", project.parent / "拆文库")
|
|
432
|
+
if base.is_dir() for d in base.iterdir())
|
|
433
|
+
if not custom_style and not no_benchmark:
|
|
281
434
|
why.append("custom_style=false")
|
|
282
435
|
downgrade = not why
|
|
283
436
|
|
|
@@ -292,28 +445,33 @@ def build(project: Path, chapter: int, report: list):
|
|
|
292
445
|
if tempo:
|
|
293
446
|
lines.append(f" {tempo}")
|
|
294
447
|
slot_recall = "——— 情绪与节奏召回 ———\n" + "\n".join(lines)
|
|
295
|
-
report.append(f"
|
|
448
|
+
report.append(f"召回降档:成立,{'无对标,' if no_benchmark and not custom_style else '文风、'}题材卡、目标情绪和单元 {unit_id} 情绪/节拍均可用")
|
|
296
449
|
else:
|
|
297
450
|
slot_recall = ("——— 情绪与节奏召回 ———\n"
|
|
298
451
|
f"{SLOT_MARK} 降档不成立(" + "、".join(why) +
|
|
299
|
-
"),按
|
|
452
|
+
"),按 benchmark-recall.md 走全量召回后填此槽")
|
|
300
453
|
report.append("召回降档:不成立(" + "、".join(why) + ")—— 全量召回归主会话")
|
|
301
454
|
|
|
302
455
|
# ---- 需要主会话判断的槽位 ----
|
|
456
|
+
work_dir = chapter_work_dir(project, chapter)
|
|
303
457
|
parts.append(
|
|
304
458
|
"——— 执行安排 ———\n"
|
|
305
459
|
f"{SLOT_MARK} 全章细纲用于整体编排。默认按自然转场或因果停顿分前后两组,"
|
|
306
|
-
"
|
|
307
|
-
"
|
|
460
|
+
"填写当前组的情节点/片段;先只写前组,主会话测一次 checkpoint 后"
|
|
461
|
+
"再给后组和机器剩余区间。只有用户明确要求一次成文时才填「全章,直接写最终路径」。\n"
|
|
462
|
+
f"分组临时文件:前组 {work_dir / '前组.md'},后组 {work_dir / '后组.md'}"
|
|
463
|
+
"(只写这里,不写 /tmp 或 正文/)。")
|
|
308
464
|
parts.append(f"——— 本章意图(一句话)———\n{SLOT_MARK}")
|
|
465
|
+
parts.append("——— 作者本轮要求 ———\n"
|
|
466
|
+
f"{SLOT_MARK} 作者这次明确说的:字数范围、必须发生、不许发生、写到哪里停、章尾要留什么;没有写「无」。")
|
|
309
467
|
parts.append(slot_recall)
|
|
310
468
|
# 伏笔与卷级禁忌走「主会话筛选后写进速记」这条原设计路线(步骤 3 状态筛选),
|
|
311
469
|
# 不由脚本整栏注入——筛选是判断,而整栏注入还会把伏笔栏里的作者侧真相一并下放。
|
|
312
470
|
# 代价是它依赖主会话逐章想起来,所以这里把提示语写成写死的三问清单。
|
|
313
471
|
parts.append(
|
|
314
|
-
"———
|
|
315
|
-
f"{SLOT_MARK}
|
|
316
|
-
"
|
|
472
|
+
"——— 本章技法 ———\n"
|
|
473
|
+
f"{SLOT_MARK} 按细纲主功能填 打脸/反转/感情/悬疑/日常/无 之一(对照 SKILL.md「本章技法」),"
|
|
474
|
+
"再写一句用在哪几段;写手按自己的读取表读对应文件,这里不摘技法。本书文风只覆盖冲突表达条款,不停读整份文件。")
|
|
317
475
|
parts.append(
|
|
318
476
|
"——— 本节速记 ———\n"
|
|
319
477
|
f"{SLOT_MARK} 按 workflow-chapter 步骤 3「状态筛选」产出(`追踪/上下文.md` 不注入"
|
|
@@ -325,18 +483,53 @@ def build(project: Path, chapter: int, report: list):
|
|
|
325
483
|
"——— 涉及角色 ———\n"
|
|
326
484
|
f"{SLOT_MARK} 按细纲「人物出场顺序」与「镜头准入」的台词位/动作位分配,"
|
|
327
485
|
"列出本章要读的角色卡;本节速记已给全状态的不必再列。")
|
|
486
|
+
if not substantive(card_text):
|
|
487
|
+
cards = match_genre_cards(project)
|
|
488
|
+
if cards:
|
|
489
|
+
named = ";".join(f"{'主' if i == 0 else '辅'}题材 {card}(置信度 {level})" for i, (card, level) in enumerate(cards))
|
|
490
|
+
report.append(f"题材卡:本书还没有题材正文提示卡,按「题材类型」匹配到 {named};生成后落盘,后续章直接读")
|
|
491
|
+
else:
|
|
492
|
+
report.append("题材卡:本书还没有题材正文提示卡,题材卡无匹配——读 style-genre-modules.md"
|
|
493
|
+
"「题材正文提示卡」一节与最接近的流派一节生成后落盘")
|
|
328
494
|
parts.append("——— 题材正文提示卡(genre_prose_card,只含本章相关条目)———\n"
|
|
329
495
|
f"{SLOT_MARK} 主题材抽 3-5 条、辅题材 1-2 条;只作内部校准,不进正文")
|
|
330
496
|
parts.append(slot_setting)
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
497
|
+
decided, cut = author_decided(project)
|
|
498
|
+
if decided:
|
|
499
|
+
note = (f"\n(超过 {AUTHOR_DECIDED_CHARS} 字已截断,其余见 {project / '设定' / '题材定位.md'}「作者已定」,动笔前读完)"
|
|
500
|
+
if cut else "")
|
|
501
|
+
parts.append("——— 作者已定(本书的决定,高于作者记忆,与细纲冲突以细纲为准并在交付摘要里说明)———\n"
|
|
502
|
+
+ decided + note)
|
|
503
|
+
report.append("作者已定:已注入" + ("(超长截断,写手需回原文读完)" if cut else ""))
|
|
504
|
+
else:
|
|
505
|
+
report.append("作者已定:题材定位里没有或为空,未注入")
|
|
506
|
+
items, omitted, skipped, memory_error = query_author_memory(project)
|
|
507
|
+
if memory_error:
|
|
508
|
+
memory_block = (f"{SLOT_MARK} 组装脚本查询作者记忆失败({memory_error}),"
|
|
509
|
+
"按 author-memory.md 手动 query prose_style + story_design 后填入;无则写「无」")
|
|
510
|
+
report.append(f"作者记忆:脚本查询失败——{memory_error},归主会话手动查询")
|
|
511
|
+
elif items:
|
|
512
|
+
memory_block = "\n".join(f"- {item.get('assertion', '').strip()}({item.get('id', '')})" for item in items)
|
|
513
|
+
report.append(f"作者记忆:已注入 {len(items)} 条" + (
|
|
514
|
+
f";超编未装下 {len(omitted)} 条({'、'.join(omitted)}),转告作者建议「整理作者记忆」" if omitted else ""))
|
|
515
|
+
else:
|
|
516
|
+
memory_block = "无"
|
|
517
|
+
report.append("作者记忆:无相关 active 条目")
|
|
518
|
+
if skipped and not memory_error:
|
|
519
|
+
named = ";".join(f"{'题材' if k == 'genre' else '流程'}:{'、'.join(v)}" for k, v in skipped.items())
|
|
520
|
+
memory_block += (f"\n{SLOT_MARK} 另有限定范围的作者记忆未代查({named}):本书适用的,"
|
|
521
|
+
"带 --genre/--workflow 跑 SKILL.md「核心方法」的 query 命令(--kind prose_style --kind story_design)后补进本块")
|
|
522
|
+
report.append(f"作者记忆:限定范围未代查({named}),归主会话判断是否适用")
|
|
523
|
+
parts.append("——— author_preferences(作者记忆,低优先级倾向,不逐条追求命中)———\n" + memory_block)
|
|
524
|
+
parts.append("——— style_resolution ———\n"
|
|
525
|
+
f"{SLOT_MARK} 本轮请求里作者对表达的明确要求及其覆盖的默认条款(没有写「无」);"
|
|
526
|
+
"本书文风与作者记忆的裁决见上方各块,同一裁决传去味与审稿。")
|
|
527
|
+
|
|
528
|
+
parts.append("检查分工:写手负责编排、内容覆盖和格式自检;主会话质量阶段负责语义去味及最终文件扫描。写手不提前重复整轮去味或相同检查链,保留情节点落点、新增申报与原定交付。")
|
|
336
529
|
|
|
337
530
|
# ---- 固定块:压成指针,不重述 agent 定义 ----
|
|
338
531
|
parts.append(
|
|
339
|
-
"本次照你的铁律 1-8
|
|
532
|
+
"本次照你的铁律 1-8 与被调用协议执行(细纲优先边界、正文形状、新增物三级、"
|
|
340
533
|
"阅读体验字段、交付三附件均以你的定义为准,此处不重述)。")
|
|
341
534
|
parts.append(
|
|
342
535
|
"字数目标按细纲执行,字数口径 visible_chars_v1;按执行安排交付,"
|
|
@@ -360,7 +553,8 @@ def main(argv=None):
|
|
|
360
553
|
parser = argparse.ArgumentParser()
|
|
361
554
|
parser.add_argument("--project", required=True)
|
|
362
555
|
parser.add_argument("--chapter", required=True, type=int)
|
|
363
|
-
parser.add_argument("--out", default=None
|
|
556
|
+
parser.add_argument("--out", nargs="?", const="", default=None,
|
|
557
|
+
help="prompt 留档路径;不带值时留档到本章工作目录 writer_prompt.md")
|
|
364
558
|
args = parser.parse_args(argv)
|
|
365
559
|
|
|
366
560
|
project = Path(args.project).resolve()
|
|
@@ -391,9 +585,16 @@ def main(argv=None):
|
|
|
391
585
|
f"标题预检:《{title}》" + ("与既有章重名 → " + "、".join(clashes)
|
|
392
586
|
if clashes else "无重名"))
|
|
393
587
|
|
|
394
|
-
if args.out:
|
|
395
|
-
|
|
396
|
-
|
|
588
|
+
if args.out is not None:
|
|
589
|
+
out = Path(args.out) if args.out else chapter_work_dir(project, args.chapter) / "writer_prompt.md"
|
|
590
|
+
try:
|
|
591
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
592
|
+
with io.open(out, "w", encoding="utf-8", newline="\n") as handle:
|
|
593
|
+
handle.write(prompt)
|
|
594
|
+
except OSError as exc:
|
|
595
|
+
sys.stderr.write(f"留档写入失败:{out}({exc})\n")
|
|
596
|
+
return 2
|
|
597
|
+
report.append(f"留档:{out}")
|
|
397
598
|
|
|
398
599
|
sys.stdout.write(prompt)
|
|
399
600
|
sys.stdout.write("\n" + "=" * 60 + "\n")
|