@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.
Files changed (360) hide show
  1. package/README.md +14 -14
  2. package/lib/client.js +237 -84
  3. package/lib/client.js.map +3 -3
  4. package/lib/drama/manifest.json +183 -77
  5. package/lib/drama/skills/short-drama/SKILL.md +5 -1
  6. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +140 -9
  7. package/lib/drama/skills/short-drama/scripts/project_tool.py +11 -0
  8. package/lib/drama/skills/short-drama-assets/references/character-and-look.md +28 -0
  9. package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +8 -2
  10. package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
  11. package/lib/drama/skills/short-drama-edit/SKILL.md +146 -0
  12. package/lib/drama/skills/short-drama-edit/agents/openai.yaml +4 -0
  13. package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +60 -0
  14. package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +15 -0
  15. package/lib/drama/skills/short-drama-edit/assets/remotion/remotion.config.ts +6 -0
  16. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +26 -0
  17. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +88 -0
  18. package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +46 -0
  19. package/lib/drama/skills/short-drama-edit/assets/remotion/src/index.ts +4 -0
  20. package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +32 -0
  21. package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +13 -0
  22. package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +43 -0
  23. package/lib/drama/skills/short-drama-edit/references/cut-craft.md +38 -0
  24. package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +29 -0
  25. package/lib/drama/skills/short-drama-edit/references/generated-footage.md +54 -0
  26. package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +60 -0
  27. package/lib/drama/skills/short-drama-edit/references/stage-contract.md +51 -0
  28. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1156 -0
  29. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +520 -0
  30. package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -0
  31. package/lib/drama/skills/short-drama-image-prompts/assets/image-prompts.md +5 -0
  32. package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-prompts.md +3 -0
  33. package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +11 -0
  34. package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +2 -2
  35. package/lib/drama/skills/short-drama-novel-analyze/references/chapter-extraction.md +4 -1
  36. package/lib/drama/skills/short-drama-produce/SKILL.md +29 -4
  37. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +22 -0
  38. package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +13 -12
  39. package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
  40. package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +7 -0
  41. package/lib/drama/skills/short-drama-produce/scripts/fixture_adapter.py +18 -1
  42. package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +181 -2
  43. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +199 -3
  44. package/lib/drama/skills/short-drama-review/SKILL.md +2 -0
  45. package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +7 -0
  46. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +10 -0
  47. package/lib/drama/skills/short-drama-storyboard/SKILL.md +12 -1
  48. package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +4 -0
  49. package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
  50. package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +78 -2
  51. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +2 -0
  52. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +12 -5
  53. package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +17 -0
  54. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +76 -7
  55. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +5 -2
  56. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +21 -0
  57. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +6 -17
  58. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +12 -3
  59. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +61 -5
  60. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +3 -3
  61. package/lib/drama/skills/short-drama-write/SKILL.md +11 -2
  62. package/lib/drama/skills/short-drama-write/references/screenplay-format.md +6 -0
  63. package/lib/drama/skills/short-drama-write/references/stage-contract.md +1 -0
  64. package/lib/index.js +290 -90
  65. package/lib/index.js.map +4 -4
  66. package/lib/novel-to-game/README.md +299 -59
  67. package/lib/novel-to-game/README_ZH.md +299 -56
  68. package/lib/novel-to-game/VERSION +1 -1
  69. package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +3 -1
  70. package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +11 -3
  71. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +397 -8
  72. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +0 -31
  73. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +71 -73
  74. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +78 -89
  75. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +37 -14
  76. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +5 -5
  77. package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -1
  78. package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +11 -16
  79. package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +11 -11
  80. package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +23 -0
  81. package/lib/novel-to-game/manifest.json +77 -87
  82. package/lib/novel-to-game/skills/game-art-direction/SKILL.md +9 -35
  83. package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +27 -106
  84. package/lib/novel-to-game/skills/game-build/SKILL.md +17 -35
  85. package/lib/novel-to-game/skills/game-build/references/blender-asset-workflow.md +24 -0
  86. package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +45 -82
  87. package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +14 -45
  88. package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +30 -65
  89. package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +13 -27
  90. package/lib/novel-to-game/skills/game-concept/SKILL.md +16 -34
  91. package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
  92. package/lib/novel-to-game/skills/game-qa/SKILL.md +9 -20
  93. package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +10 -6
  94. package/lib/novel-to-game/skills/game-world-design/SKILL.md +19 -32
  95. package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +23 -72
  96. package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +14 -48
  97. package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +36 -103
  98. package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +9 -18
  99. package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +4 -4
  100. package/lib/novel-to-game/skills/novel-to-game/SKILL.md +10 -27
  101. package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -6
  102. package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +6 -11
  103. package/lib/oh-story/manifest.json +419 -254
  104. package/lib/oh-story/roles/chapter-extractor.md +177 -237
  105. package/lib/oh-story/roles/character-designer.md +1 -1
  106. package/lib/oh-story/roles/consistency-checker.md +4 -4
  107. package/lib/oh-story/roles/narrative-writer.md +56 -243
  108. package/lib/oh-story/roles/story-architect.md +6 -6
  109. package/lib/oh-story/roles/story-explorer.md +11 -11
  110. package/lib/oh-story/skills/story/SKILL.md +13 -7
  111. package/lib/oh-story/skills/story/VERSION +1 -1
  112. package/lib/oh-story/skills/story/references/author-memory.md +61 -29
  113. package/lib/oh-story/skills/story/scripts/author_memory_commit.py +934 -170
  114. package/lib/oh-story/skills/story-cover/SKILL.md +10 -1
  115. package/lib/oh-story/skills/story-deslop/SKILL.md +54 -229
  116. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +29 -56
  117. package/lib/oh-story/skills/story-deslop/references/author-memory.md +61 -29
  118. package/lib/oh-story/skills/story-deslop/references/banned-words.md +3 -1
  119. package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +154 -0
  120. package/lib/oh-story/skills/story-deslop/references/style-resolution.md +27 -0
  121. package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
  122. package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +6 -1
  123. package/lib/oh-story/skills/story-deslop/scripts/check-degeneration.js +39 -20
  124. package/lib/oh-story/skills/story-deslop/scripts/normalize-punctuation.js +10 -5
  125. package/lib/oh-story/skills/story-deslop/scripts/style-whitelist.js +39 -0
  126. package/lib/oh-story/skills/story-import/SKILL.md +78 -82
  127. package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
  128. package/lib/oh-story/skills/story-import/references/format-and-structure.md +2 -2
  129. package/lib/oh-story/skills/story-import/references/state-tracking.md +4 -69
  130. package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +10 -8
  131. package/lib/oh-story/skills/story-import/references/tracking-initialization.md +31 -0
  132. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +9 -34
  133. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +197 -15
  134. package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +210 -2
  135. package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +3 -0
  136. package/lib/oh-story/skills/story-long-analyze/SKILL.md +91 -258
  137. package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +245 -0
  138. package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +2 -2
  139. package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
  140. package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +113 -105
  141. package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +169 -125
  142. package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +172 -64
  143. package/lib/oh-story/skills/story-long-analyze/references/semantic-acceptance-fixtures.md +84 -0
  144. package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +42 -132
  145. package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +5 -5
  146. package/lib/oh-story/skills/story-long-analyze/scripts/build_chapter_index.py +466 -0
  147. package/lib/oh-story/skills/story-long-analyze/scripts/inspect_existing_assets.py +702 -0
  148. package/lib/oh-story/skills/story-long-analyze/scripts/inspiration_index.py +864 -0
  149. package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +1106 -0
  150. package/lib/oh-story/skills/story-long-analyze/scripts/render_relation_chart.py +425 -0
  151. package/lib/oh-story/skills/story-long-scan/SKILL.md +4 -1
  152. package/lib/oh-story/skills/story-long-write/SKILL.md +52 -216
  153. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +29 -56
  154. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +72 -12
  155. package/lib/oh-story/skills/story-long-write/references/author-memory.md +61 -29
  156. package/lib/oh-story/skills/story-long-write/references/banned-words.md +3 -1
  157. package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +20 -0
  158. package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
  159. package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +10 -4
  160. package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
  161. package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +6 -15
  162. package/lib/oh-story/skills/story-long-write/references/long-format.md +2 -0
  163. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +2 -0
  164. package/lib/oh-story/skills/story-long-write/references/project-files.md +110 -0
  165. package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +12 -4
  166. package/lib/oh-story/skills/story-long-write/references/reference-index.md +86 -0
  167. package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -1
  168. package/lib/oh-story/skills/story-long-write/references/style-craft.md +9 -29
  169. package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
  170. package/lib/oh-story/skills/story-long-write/references/style-resolution.md +27 -0
  171. package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +31 -0
  172. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +9 -34
  173. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +88 -118
  174. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +55 -119
  175. package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +15 -11
  176. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +73 -54
  177. package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +22 -0
  178. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +63 -4
  179. package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +934 -170
  180. package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +531 -0
  181. package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +6 -1
  182. package/lib/oh-story/skills/story-long-write/scripts/check-degeneration.js +39 -20
  183. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +197 -15
  184. package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +90 -23
  185. package/lib/oh-story/skills/story-long-write/scripts/normalize-punctuation.js +10 -5
  186. package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +285 -0
  187. package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +58 -0
  188. package/lib/oh-story/skills/story-long-write/scripts/style-whitelist.js +39 -0
  189. package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +210 -2
  190. package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +3 -0
  191. package/lib/oh-story/skills/story-review/SKILL.md +80 -87
  192. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +29 -56
  193. package/lib/oh-story/skills/story-review/references/author-memory.md +61 -29
  194. package/lib/oh-story/skills/story-review/references/banned-words.md +3 -1
  195. package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +10 -4
  196. package/lib/oh-story/skills/story-review/references/review-quality.md +6 -12
  197. package/lib/oh-story/skills/story-review/references/style-resolution.md +27 -0
  198. package/lib/oh-story/skills/story-review/references/tracking-initialization.md +31 -0
  199. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +9 -34
  200. package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
  201. package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +6 -1
  202. package/lib/oh-story/skills/story-review/scripts/check-degeneration.js +39 -20
  203. package/lib/oh-story/skills/story-review/scripts/normalize-punctuation.js +10 -5
  204. package/lib/oh-story/skills/story-review/scripts/style-whitelist.js +39 -0
  205. package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +210 -2
  206. package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +3 -0
  207. package/lib/oh-story/skills/story-setup/SKILL.md +58 -43
  208. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +29 -56
  209. package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +3 -1
  210. package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +154 -0
  211. package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +10 -4
  212. package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +2 -2
  213. package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +2 -2
  214. package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +1 -1
  215. package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +1 -1
  216. package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -1
  217. package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
  218. package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +27 -0
  219. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +63 -4
  220. package/lib/oh-story/skills/story-setup/references/diagnostics.md +38 -0
  221. package/lib/oh-story/skills/story-short-analyze/SKILL.md +22 -3
  222. package/lib/oh-story/skills/story-short-analyze/references/analysis-writing-techniques.md +1 -1
  223. package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +5 -1
  224. package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +2 -2
  225. package/lib/oh-story/skills/story-short-scan/SKILL.md +5 -1
  226. package/lib/oh-story/skills/story-short-write/SKILL.md +15 -324
  227. package/lib/oh-story/skills/story-short-write/references/author-memory.md +61 -29
  228. package/lib/oh-story/skills/story-short-write/references/banned-words.md +3 -1
  229. package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +60 -0
  230. package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +10 -4
  231. 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
  232. package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +1 -1
  233. 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
  234. 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
  235. 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
  236. package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +5 -5
  237. 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
  238. package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +5 -5
  239. 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
  240. package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +1 -1
  241. package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +1 -1
  242. package/lib/oh-story/skills/story-short-write/references/reference-index.md +55 -0
  243. package/lib/oh-story/skills/story-short-write/references/short-craft.md +12 -14
  244. package/lib/oh-story/skills/story-short-write/references/short-deslop.md +10 -10
  245. package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -1
  246. package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -2
  247. package/lib/oh-story/skills/story-short-write/references/style-resolution.md +27 -0
  248. package/lib/oh-story/skills/story-short-write/references/workflow-design.md +78 -0
  249. package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +126 -0
  250. package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +32 -0
  251. package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +5 -5
  252. package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
  253. package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +6 -1
  254. package/lib/oh-story/skills/story-short-write/scripts/check-degeneration.js +39 -20
  255. package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +34 -5
  256. package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +90 -23
  257. package/lib/oh-story/skills/story-short-write/scripts/normalize-punctuation.js +10 -5
  258. package/lib/oh-story/skills/story-short-write/scripts/style-whitelist.js +39 -0
  259. package/lib/types/client/drama-production-view.d.ts.map +1 -1
  260. package/lib/types/client/file-activity.d.ts +19 -1
  261. package/lib/types/client/file-activity.d.ts.map +1 -1
  262. package/lib/types/client/index.d.ts.map +1 -1
  263. package/lib/types/client/production-prompts.d.ts +7 -0
  264. package/lib/types/client/production-prompts.d.ts.map +1 -1
  265. package/lib/types/client/production-runtime.d.ts +33 -0
  266. package/lib/types/client/production-runtime.d.ts.map +1 -1
  267. package/lib/types/drama-adapters.d.ts +5 -3
  268. package/lib/types/drama-adapters.d.ts.map +1 -1
  269. package/lib/types/native-hooks.d.ts +52 -0
  270. package/lib/types/native-hooks.d.ts.map +1 -1
  271. package/lib/types/role-identity.d.ts +17 -0
  272. package/lib/types/role-identity.d.ts.map +1 -0
  273. package/lib/types/role-tool.d.ts.map +1 -1
  274. package/lib/types/skill-provider.d.ts.map +1 -1
  275. package/lib/video-recap/CHANGELOG.md +31 -1
  276. package/lib/video-recap/manifest.json +162 -162
  277. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +4 -9
  278. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +47 -60
  279. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +77 -115
  280. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +41 -40
  281. package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +22 -32
  282. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +102 -192
  283. package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +14 -35
  284. package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +14 -12
  285. package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +8 -9
  286. package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +3 -14
  287. package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +23 -12
  288. package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +1 -4
  289. package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +24 -25
  290. package/lib/video-recap/skills/video-assemble/scripts/lib.py +31 -85
  291. package/lib/video-recap/skills/video-assemble/scripts/media.py +100 -144
  292. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +101 -195
  293. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +10 -21
  294. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +90 -169
  295. package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +69 -122
  296. package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +10 -17
  297. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +33 -48
  298. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +14 -20
  299. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +135 -213
  300. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +49 -57
  301. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +38 -74
  302. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +46 -95
  303. package/lib/video-recap/skills/video-cut/scripts/lib.py +23 -25
  304. package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +70 -173
  305. package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +28 -53
  306. package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +162 -322
  307. package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +6 -7
  308. package/lib/video-recap/skills/video-recap/scripts/doctor.py +104 -124
  309. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +255 -412
  310. package/lib/video-recap/skills/video-recap/scripts/lib.py +30 -52
  311. package/lib/video-recap/skills/video-recap/scripts/materials.py +97 -120
  312. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +7 -12
  313. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +46 -97
  314. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +18 -36
  315. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +29 -47
  316. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +43 -76
  317. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +2 -1
  318. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +2 -1
  319. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +2 -2
  320. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +129 -145
  321. package/lib/video-recap/skills/video-recap/scripts/recap_review.py +27 -20
  322. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +20 -31
  323. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +31 -106
  324. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +43 -113
  325. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +196 -377
  326. package/lib/video-recap/skills/video-script/scripts/agent_brief.py +1 -1
  327. package/lib/video-recap/skills/video-script/scripts/agent_text.py +63 -172
  328. package/lib/video-recap/skills/video-script/scripts/brief_context.py +80 -135
  329. package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +125 -167
  330. package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +93 -208
  331. package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +20 -46
  332. package/lib/video-recap/skills/video-script/scripts/lib.py +30 -26
  333. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +145 -140
  334. package/lib/video-recap/skills/video-script/scripts/review_response.py +12 -42
  335. package/lib/video-recap/skills/video-script/scripts/review_runner.py +0 -6
  336. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +39 -100
  337. package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +33 -124
  338. package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +1 -1
  339. package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +63 -172
  340. package/lib/video-recap/skills/video-understanding/scripts/asr.py +1 -2
  341. package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +80 -135
  342. package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +125 -167
  343. package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +93 -208
  344. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +1 -1
  345. package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +20 -46
  346. package/lib/video-recap/skills/video-understanding/scripts/lib.py +31 -26
  347. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +145 -140
  348. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +39 -100
  349. package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +33 -124
  350. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +1 -4
  351. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +7 -13
  352. package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +12 -30
  353. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +98 -131
  354. package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +17 -28
  355. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +151 -240
  356. package/package.json +45 -45
  357. package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -59
  358. package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +0 -53
  359. package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -42
  360. 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
- require(len(cleaned.encode("utf-8")) <= max_bytes, f"{label} exceeds {max_bytes} bytes")
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
- require(size <= DELTA_MAX_BYTES, f"chapter delta is {size} bytes; hard cap is {DELTA_MAX_BYTES}")
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