@oh-story/dsh 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/README.md +30 -15
  2. package/lib/client.js +93 -16
  3. package/lib/client.js.map +2 -2
  4. package/lib/drama/manifest.json +165 -69
  5. package/lib/drama/skills/short-drama/SKILL.md +5 -1
  6. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +126 -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 +18 -0
  9. package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +10 -1
  10. package/lib/drama/skills/short-drama-edit/SKILL.md +148 -0
  11. package/lib/drama/skills/short-drama-edit/agents/openai.yaml +4 -0
  12. package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +60 -0
  13. package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +15 -0
  14. package/lib/drama/skills/short-drama-edit/assets/remotion/remotion.config.ts +6 -0
  15. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +26 -0
  16. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +88 -0
  17. package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +46 -0
  18. package/lib/drama/skills/short-drama-edit/assets/remotion/src/index.ts +4 -0
  19. package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +32 -0
  20. package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +13 -0
  21. package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +43 -0
  22. package/lib/drama/skills/short-drama-edit/references/cut-craft.md +81 -0
  23. package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +58 -0
  24. package/lib/drama/skills/short-drama-edit/references/generated-footage.md +96 -0
  25. package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +113 -0
  26. package/lib/drama/skills/short-drama-edit/references/stage-contract.md +55 -0
  27. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1041 -0
  28. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +456 -0
  29. package/lib/drama/skills/short-drama-image-prompts/assets/image-prompts.md +5 -0
  30. package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-prompts.md +3 -0
  31. package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +2 -2
  32. package/lib/drama/skills/short-drama-novel-analyze/references/chapter-extraction.md +4 -1
  33. package/lib/drama/skills/short-drama-produce/SKILL.md +24 -3
  34. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +28 -0
  35. package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +24 -5
  36. package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +7 -0
  37. package/lib/drama/skills/short-drama-produce/scripts/fixture_adapter.py +18 -1
  38. package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +181 -2
  39. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +57 -2
  40. package/lib/drama/skills/short-drama-review/SKILL.md +3 -0
  41. package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +20 -0
  42. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +36 -0
  43. package/lib/drama/skills/short-drama-storyboard/SKILL.md +7 -0
  44. package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +4 -0
  45. package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +39 -0
  46. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +2 -0
  47. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +7 -1
  48. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +101 -6
  49. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +7 -1
  50. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +35 -0
  51. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +3 -1
  52. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +13 -3
  53. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +35 -4
  54. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +1 -1
  55. package/lib/drama/skills/short-drama-write/SKILL.md +13 -2
  56. package/lib/drama/skills/short-drama-write/references/screenplay-format.md +6 -0
  57. package/lib/drama/skills/short-drama-write/references/stage-contract.md +1 -0
  58. package/lib/index.js +4 -2
  59. package/lib/index.js.map +2 -2
  60. package/lib/novel-to-game/VERSION +1 -1
  61. package/lib/novel-to-game/manifest.json +28 -28
  62. package/lib/novel-to-game/skills/game-art-direction/SKILL.md +6 -27
  63. package/lib/novel-to-game/skills/game-build/SKILL.md +12 -29
  64. package/lib/novel-to-game/skills/game-concept/SKILL.md +10 -26
  65. package/lib/novel-to-game/skills/game-qa/SKILL.md +5 -15
  66. package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +1 -1
  67. package/lib/novel-to-game/skills/game-world-design/SKILL.md +19 -28
  68. package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +1 -2
  69. package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +6 -9
  70. package/lib/novel-to-game/skills/novel-to-game/SKILL.md +6 -11
  71. package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -4
  72. package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +1 -3
  73. package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +3 -5
  74. package/lib/oh-story/manifest.json +292 -172
  75. package/lib/oh-story/roles/character-designer.md +1 -1
  76. package/lib/oh-story/roles/narrative-writer.md +56 -242
  77. package/lib/oh-story/roles/story-architect.md +1 -1
  78. package/lib/oh-story/skills/story/SKILL.md +1 -1
  79. package/lib/oh-story/skills/story/VERSION +1 -1
  80. package/lib/oh-story/skills/story/references/author-memory.md +10 -8
  81. package/lib/oh-story/skills/story-deslop/SKILL.md +20 -182
  82. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +19 -47
  83. package/lib/oh-story/skills/story-deslop/references/author-memory.md +10 -8
  84. package/lib/oh-story/skills/story-deslop/references/banned-words.md +3 -1
  85. package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +154 -0
  86. package/lib/oh-story/skills/story-deslop/references/style-resolution.md +27 -0
  87. package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +6 -1
  88. package/lib/oh-story/skills/story-deslop/scripts/check-degeneration.js +39 -20
  89. package/lib/oh-story/skills/story-deslop/scripts/normalize-punctuation.js +10 -5
  90. package/lib/oh-story/skills/story-deslop/scripts/style-whitelist.js +39 -0
  91. package/lib/oh-story/skills/story-import/SKILL.md +2 -2
  92. package/lib/oh-story/skills/story-import/references/format-and-structure.md +2 -2
  93. package/lib/oh-story/skills/story-import/references/tracking-initialization.md +31 -0
  94. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +2 -29
  95. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +176 -12
  96. package/lib/oh-story/skills/story-long-analyze/SKILL.md +1 -1
  97. package/lib/oh-story/skills/story-long-write/SKILL.md +20 -193
  98. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +19 -47
  99. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +62 -7
  100. package/lib/oh-story/skills/story-long-write/references/author-memory.md +10 -8
  101. package/lib/oh-story/skills/story-long-write/references/banned-words.md +3 -1
  102. package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +20 -0
  103. package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +6 -4
  104. package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +2 -2
  105. package/lib/oh-story/skills/story-long-write/references/long-format.md +2 -0
  106. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +2 -0
  107. package/lib/oh-story/skills/story-long-write/references/project-files.md +108 -0
  108. package/lib/oh-story/skills/story-long-write/references/reference-index.md +87 -0
  109. package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -1
  110. package/lib/oh-story/skills/story-long-write/references/style-craft.md +9 -29
  111. package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
  112. package/lib/oh-story/skills/story-long-write/references/style-resolution.md +27 -0
  113. package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +31 -0
  114. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +2 -29
  115. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +51 -52
  116. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +8 -7
  117. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +36 -15
  118. package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +22 -0
  119. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +69 -2
  120. package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +410 -0
  121. package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +6 -1
  122. package/lib/oh-story/skills/story-long-write/scripts/check-degeneration.js +39 -20
  123. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +176 -12
  124. package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +90 -23
  125. package/lib/oh-story/skills/story-long-write/scripts/normalize-punctuation.js +10 -5
  126. package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +283 -0
  127. package/lib/oh-story/skills/story-long-write/scripts/style-whitelist.js +39 -0
  128. package/lib/oh-story/skills/story-review/SKILL.md +13 -3
  129. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +19 -47
  130. package/lib/oh-story/skills/story-review/references/author-memory.md +10 -8
  131. package/lib/oh-story/skills/story-review/references/banned-words.md +3 -1
  132. package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +6 -4
  133. package/lib/oh-story/skills/story-review/references/review-quality.md +2 -2
  134. package/lib/oh-story/skills/story-review/references/style-resolution.md +27 -0
  135. package/lib/oh-story/skills/story-review/references/tracking-initialization.md +31 -0
  136. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +2 -29
  137. package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +6 -1
  138. package/lib/oh-story/skills/story-review/scripts/check-degeneration.js +39 -20
  139. package/lib/oh-story/skills/story-review/scripts/normalize-punctuation.js +10 -5
  140. package/lib/oh-story/skills/story-review/scripts/style-whitelist.js +39 -0
  141. package/lib/oh-story/skills/story-setup/SKILL.md +17 -10
  142. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +19 -47
  143. package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +3 -1
  144. package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +154 -0
  145. package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +6 -4
  146. package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +2 -2
  147. package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +1 -1
  148. package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -1
  149. package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
  150. package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +27 -0
  151. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +69 -2
  152. package/lib/oh-story/skills/story-setup/references/diagnostics.md +38 -0
  153. package/lib/oh-story/skills/story-short-analyze/references/analysis-writing-techniques.md +1 -1
  154. package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +2 -2
  155. package/lib/oh-story/skills/story-short-write/SKILL.md +18 -186
  156. package/lib/oh-story/skills/story-short-write/references/author-memory.md +10 -8
  157. package/lib/oh-story/skills/story-short-write/references/banned-words.md +3 -1
  158. package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +60 -0
  159. package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +6 -4
  160. 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
  161. package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +1 -1
  162. 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
  163. 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
  164. 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
  165. package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +5 -5
  166. 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
  167. package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +5 -5
  168. 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
  169. package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +1 -1
  170. package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +1 -1
  171. package/lib/oh-story/skills/story-short-write/references/reference-index.md +53 -0
  172. package/lib/oh-story/skills/story-short-write/references/short-craft.md +12 -14
  173. package/lib/oh-story/skills/story-short-write/references/short-deslop.md +10 -10
  174. package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -1
  175. package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -2
  176. package/lib/oh-story/skills/story-short-write/references/style-resolution.md +27 -0
  177. package/lib/oh-story/skills/story-short-write/references/workflow-design.md +77 -0
  178. package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +5 -5
  179. package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +6 -1
  180. package/lib/oh-story/skills/story-short-write/scripts/check-degeneration.js +39 -20
  181. package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +34 -5
  182. package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +90 -23
  183. package/lib/oh-story/skills/story-short-write/scripts/normalize-punctuation.js +10 -5
  184. package/lib/oh-story/skills/story-short-write/scripts/style-whitelist.js +39 -0
  185. package/lib/types/client/drama-production-view.d.ts.map +1 -1
  186. package/lib/types/client/index.d.ts.map +1 -1
  187. package/lib/types/client/production-prompts.d.ts.map +1 -1
  188. package/lib/types/client/production-runtime.d.ts +17 -0
  189. package/lib/types/client/production-runtime.d.ts.map +1 -1
  190. package/lib/types/skill-provider.d.ts.map +1 -1
  191. package/lib/video-recap/CHANGELOG.md +31 -1
  192. package/lib/video-recap/manifest.json +162 -162
  193. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +4 -9
  194. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +47 -60
  195. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +77 -115
  196. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +41 -40
  197. package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +22 -32
  198. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +102 -192
  199. package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +14 -35
  200. package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +14 -12
  201. package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +8 -9
  202. package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +3 -14
  203. package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +23 -12
  204. package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +1 -4
  205. package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +24 -25
  206. package/lib/video-recap/skills/video-assemble/scripts/lib.py +31 -85
  207. package/lib/video-recap/skills/video-assemble/scripts/media.py +100 -144
  208. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +101 -195
  209. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +10 -21
  210. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +90 -169
  211. package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +69 -122
  212. package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +10 -17
  213. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +33 -48
  214. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +14 -20
  215. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +135 -213
  216. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +49 -57
  217. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +38 -74
  218. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +46 -95
  219. package/lib/video-recap/skills/video-cut/scripts/lib.py +23 -25
  220. package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +70 -173
  221. package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +28 -53
  222. package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +162 -322
  223. package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +6 -7
  224. package/lib/video-recap/skills/video-recap/scripts/doctor.py +104 -124
  225. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +255 -412
  226. package/lib/video-recap/skills/video-recap/scripts/lib.py +30 -52
  227. package/lib/video-recap/skills/video-recap/scripts/materials.py +97 -120
  228. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +7 -12
  229. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +46 -97
  230. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +18 -36
  231. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +29 -47
  232. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +43 -76
  233. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +2 -1
  234. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +2 -1
  235. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +2 -2
  236. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +129 -145
  237. package/lib/video-recap/skills/video-recap/scripts/recap_review.py +27 -20
  238. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +20 -31
  239. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +31 -106
  240. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +43 -113
  241. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +196 -377
  242. package/lib/video-recap/skills/video-script/scripts/agent_brief.py +1 -1
  243. package/lib/video-recap/skills/video-script/scripts/agent_text.py +63 -172
  244. package/lib/video-recap/skills/video-script/scripts/brief_context.py +80 -135
  245. package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +125 -167
  246. package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +93 -208
  247. package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +20 -46
  248. package/lib/video-recap/skills/video-script/scripts/lib.py +30 -26
  249. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +145 -140
  250. package/lib/video-recap/skills/video-script/scripts/review_response.py +12 -42
  251. package/lib/video-recap/skills/video-script/scripts/review_runner.py +0 -6
  252. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +39 -100
  253. package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +33 -124
  254. package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +1 -1
  255. package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +63 -172
  256. package/lib/video-recap/skills/video-understanding/scripts/asr.py +1 -2
  257. package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +80 -135
  258. package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +125 -167
  259. package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +93 -208
  260. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +1 -1
  261. package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +20 -46
  262. package/lib/video-recap/skills/video-understanding/scripts/lib.py +31 -26
  263. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +145 -140
  264. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +39 -100
  265. package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +33 -124
  266. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +1 -4
  267. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +7 -13
  268. package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +12 -30
  269. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +98 -131
  270. package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +17 -28
  271. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +151 -240
  272. package/package.json +41 -41
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env python3
2
+ """卷纲取段器 —— 让「不整读卷纲」成立。
3
+
4
+ 按声明作用域选取卷级、单元级和批次材料;未声明的旧段保守纳入并告警。
5
+
6
+ 段头约定(每个 ## / ### / #### 标题的**下一行非空行**):
7
+
8
+ > 作用域:卷级常任
9
+ > 作用域:单元级 D1-03
10
+ > 作用域:批次底稿 D1-03|状态:在用
11
+ > 作用域:批次底稿 D1-02|状态:已退役
12
+
13
+ 退役行(行内覆盖):以 `⊘` 起头的列表行 / 表格行,默认过滤。
14
+
15
+ 用法:
16
+ outline_view.py --toc 卷纲.md
17
+ outline_view.py --unit D1-03 卷纲.md
18
+ outline_view.py --contract 卷纲.md
19
+ outline_view.py --check 卷纲.md
20
+ 任意子命令加 --history 连退役行一起输出
21
+ """
22
+ import argparse
23
+ import io
24
+ import re
25
+ import sys
26
+
27
+ HEADING = re.compile(r"^(#{2,4})\s+(.*\S)\s*$")
28
+ SCOPE = re.compile(r"^>\s*作用域[::]\s*(.+?)\s*$")
29
+ RETIRED_LINE = re.compile(r"^\s*(?:[-*]\s*)?⊘|^\s*\|\s*⊘")
30
+ # 单元块内不该出现的全卷字样——出现即说明这条常任规则放错了地方
31
+ LEAK = re.compile(r"全卷常任|全程生效|全卷生效|本单元起常任|自 ?[LD]\d+-\d+ ?起生效")
32
+ # 指向卷级的指针行不算泄漏:单元块可以引用常任规则,不可以复述它
33
+ POINTER = re.compile(r"全卷常任裁定|已提为卷级|不复读|规则本身见|见「全卷")
34
+ UNIT_IN_TITLE = re.compile(r"(?<![\w-])([LD]\d+-\d+|U\d+)(?![\w-])")
35
+ # 批次底稿里出现跨章祈使=这条约束在写作期还有效,而写作档不给底稿 → 必须下沉
36
+ IMPERATIVE = re.compile(r"全程不许|一律不许|往后任何章|此后不再|往后每|从此不|终局前不")
37
+ CH_RANGE = re.compile(r"章节范围[::]\s*第\s*(\d+)\s*[-–—~至]\s*(\d+)\s*章")
38
+ ARC_ROW = re.compile(r"^\|\s*(\d+)\s*\|")
39
+
40
+
41
+ def read(path):
42
+ with io.open(path, encoding="utf-8-sig") as handle:
43
+ return handle.read()
44
+
45
+
46
+ class Section:
47
+ __slots__ = ("level", "title", "start", "end", "scope", "kind",
48
+ "unit", "status", "lines")
49
+
50
+ def __init__(self, level, title, start):
51
+ self.level = level
52
+ self.title = title
53
+ self.start = start # 标题行号(0 基)
54
+ self.end = None
55
+ self.scope = None # 原始作用域串,None = 未声明
56
+ self.kind = None # 卷级常任 / 单元级 / 批次底稿
57
+ self.unit = None
58
+ self.status = "在用"
59
+ self.lines = []
60
+
61
+
62
+ def parse(text):
63
+ lines = text.split("\n")
64
+ sections = []
65
+ fence = None
66
+ for index, line in enumerate(lines):
67
+ marker = re.match(r"^\s{0,3}(`{3,}|~{3,})", line)
68
+ if marker:
69
+ value = marker.group(1)
70
+ if fence is None:
71
+ fence = value
72
+ elif value[0] == fence[0] and len(value) >= len(fence):
73
+ fence = None
74
+ continue
75
+ if fence:
76
+ continue
77
+ match = HEADING.match(line)
78
+ if match:
79
+ if sections:
80
+ sections[-1].end = index
81
+ sections.append(Section(len(match.group(1)), match.group(2), index))
82
+ if sections:
83
+ sections[-1].end = len(lines)
84
+ for section in sections:
85
+ section.lines = lines[section.start:section.end]
86
+ for candidate in section.lines[1:]:
87
+ if not candidate.strip():
88
+ continue
89
+ scope_match = SCOPE.match(candidate)
90
+ if scope_match:
91
+ section.scope = scope_match.group(1)
92
+ break
93
+ if section.scope:
94
+ head = section.scope.split("|")[0].strip()
95
+ if head == "卷级常任":
96
+ section.kind = "卷级常任"
97
+ elif re.fullmatch(r"单元级(?:\s+[A-Za-z][\w-]*)?", head):
98
+ section.kind = "单元级"
99
+ elif re.fullmatch(r"批次底稿(?:\s+[A-Za-z][\w-]*)?", head):
100
+ section.kind = "批次底稿"
101
+ found = re.search(r"^(?:单元级|批次底稿)\s+([A-Za-z][\w-]*)$", head)
102
+ if found:
103
+ section.unit = found.group(1)
104
+ if "已退役" in section.scope:
105
+ section.status = "已退役"
106
+ if section.unit is None:
107
+ found = re.search(r"剧情单元\s+([A-Za-z][\w-]*)", section.title) or UNIT_IN_TITLE.search(section.title)
108
+ if found:
109
+ section.unit = found.group(1)
110
+ if section.unit is None and section.scope is None:
111
+ for line in section.lines[1:]:
112
+ field = re.match(r"^\s*[-*+]\s*单元ID\s*[::]\s*([A-Za-z][\w-]*)\s*$", line.replace("**", ""))
113
+ if field:
114
+ section.unit = field.group(1)
115
+ break
116
+ return lines, sections
117
+
118
+
119
+ def strip_retired(block_lines, keep_history):
120
+ if keep_history:
121
+ return block_lines
122
+ return [line for line in block_lines if not RETIRED_LINE.match(line)]
123
+
124
+
125
+ def unit_chapter_range(sections, unit):
126
+ for section in sections:
127
+ if section.unit == unit and section.kind == "单元级" and "剧情单元" in section.title:
128
+ for line in section.lines:
129
+ found = CH_RANGE.search(line)
130
+ if found:
131
+ return int(found.group(1)), int(found.group(2))
132
+ return None
133
+
134
+
135
+ def slice_arc(section, span):
136
+ """情绪弧线这类逐章表:只留本单元章区间的行,表头与说明照留。"""
137
+ if span is None:
138
+ return section.lines
139
+ low, high = span
140
+ kept = []
141
+ for line in section.lines:
142
+ row = ARC_ROW.match(line)
143
+ if row and not (low <= int(row.group(1)) <= high):
144
+ continue
145
+ kept.append(line)
146
+ return kept
147
+
148
+
149
+ def emit(sections, chosen, span, keep_history, note, preamble):
150
+ out = ["\n".join(strip_retired(preamble, keep_history)).rstrip()] if preamble else []
151
+ for section in sections:
152
+ if section not in chosen:
153
+ continue
154
+ body = section.lines
155
+ if "情绪弧线" in section.title or "排班" in section.title:
156
+ body = slice_arc(section, span)
157
+ body = strip_retired(body, keep_history)
158
+ out.append("\n".join(body).rstrip())
159
+ text = "\n\n".join(out)
160
+ sys.stdout.write(text + "\n")
161
+ if note:
162
+ sys.stderr.write(note + "\n")
163
+
164
+
165
+ def cmd_toc(sections):
166
+ print("%-3s %-6s %-9s %-8s %-46s %s" %
167
+ ("#", "行", "作用域", "单元", "段", "字符"))
168
+ for number, section in enumerate(sections, 1):
169
+ size = sum(len(line) + 1 for line in section.lines)
170
+ print("%-3d %-6d %-9s %-8s %-46s %d" %
171
+ (number, section.start + 1, section.kind or "**未声明**",
172
+ (section.unit or "-") + ("(退)" if section.status == "已退役" else ""),
173
+ section.title[:44], size))
174
+
175
+
176
+ def cmd_check(sections, strict=False):
177
+ problems = []
178
+ warnings = []
179
+ for section in sections:
180
+ if section.kind == "批次底稿":
181
+ for offset, line in enumerate(section.lines):
182
+ if IMPERATIVE.search(line):
183
+ warnings.append(
184
+ ("W1", "第%d行" % (section.start + offset + 1),
185
+ "批次底稿里有跨章祈使,写作档不给底稿——确认已下沉到单元级段或细纲:%s"
186
+ % line.strip()[:52]))
187
+ for section in sections:
188
+ where = "第%d行「%s」" % (section.start + 1, section.title[:36])
189
+ if section.scope is None:
190
+ (problems if strict else warnings).append(("E1" if strict else "W2", where, "缺「> 作用域:」声明行;旧段保守纳入"))
191
+ continue
192
+ if section.kind is None:
193
+ problems.append(("E2", where, "作用域值不认识:%s" % section.scope))
194
+ if section.kind in ("单元级", "批次底稿") and section.unit is None:
195
+ problems.append(("E3", where, "单元级/批次底稿段未标单元ID"))
196
+ if section.kind in ("单元级", "批次底稿"):
197
+ for offset, line in enumerate(section.lines):
198
+ if LEAK.search(line) and not POINTER.search(line):
199
+ problems.append(
200
+ ("E4", "第%d行" % (section.start + offset + 1),
201
+ "单元块内出现全卷字样,常任规则放错了位置:%s"
202
+ % line.strip()[:56]))
203
+ for code, where, message in problems + warnings:
204
+ print("%s %s %s" % (code, where, message))
205
+ print("---")
206
+ print("段 %d / 问题 %d / 告警 %d(告警不阻断,逐条人工判断)"
207
+ % (len(sections), len(problems), len(warnings)))
208
+ return 1 if problems else 0
209
+
210
+
211
+ def main():
212
+ parser = argparse.ArgumentParser(add_help=True)
213
+ parser.add_argument("path")
214
+ parser.add_argument("--toc", action="store_true")
215
+ parser.add_argument("--unit")
216
+ parser.add_argument("--contract", action="store_true")
217
+ parser.add_argument("--check", action="store_true")
218
+ parser.add_argument("--history", action="store_true")
219
+ parser.add_argument("--strict", action="store_true", help="新建卷纲校验:缺作用域也视为错误")
220
+ parser.add_argument("--stage", choices=["outline", "write"], default="outline",
221
+ help="outline=排纲档(带在用批次底稿);"
222
+ "write=写作档(只要卷级常任+单元级,底稿一概不给)")
223
+ args = parser.parse_args()
224
+
225
+ if hasattr(sys.stdout, "reconfigure"):
226
+ sys.stdout.reconfigure(encoding="utf-8")
227
+ sys.stderr.reconfigure(encoding="utf-8")
228
+
229
+ try:
230
+ lines, sections = parse(read(args.path))
231
+ except (OSError, UnicodeError) as error:
232
+ sys.stderr.write(f"无法读取卷纲:{error}\n")
233
+ return 2
234
+ if not sections:
235
+ sys.stderr.write("卷纲里没有 ## 段,路径对不对?\n")
236
+ return 2
237
+
238
+ if args.toc:
239
+ cmd_toc(sections)
240
+ return 0
241
+ if args.check:
242
+ return cmd_check(sections, args.strict)
243
+
244
+ invalid = [s for s in sections if s.scope and
245
+ (s.kind is None or (s.kind != "卷级常任" and s.unit is None))]
246
+ if invalid:
247
+ sys.stderr.write("作用域声明无效,先运行 --check 修正\n")
248
+ return 1
249
+ active = [s for s in sections if args.history or s.status != "已退役"]
250
+ permanent = [s for s in active if s.kind == "卷级常任"]
251
+ undeclared = [s for s in active if s.scope is None]
252
+ note = ("%d 段未声明作用域,已保守纳入;用 --check 查看" % len(undeclared)) if undeclared else None
253
+ preamble = lines[:sections[0].start]
254
+ if args.contract:
255
+ emit(sections, set(permanent + undeclared), None, args.history, note, preamble)
256
+ return 0
257
+
258
+ if args.unit:
259
+ unit = args.unit
260
+ owned = [s for s in active if s.unit == unit]
261
+ if not owned:
262
+ sys.stderr.write(
263
+ "找不到单元 %s —— 不静默降级。核对单元ID,或先补卷纲。\n" % unit)
264
+ return 1
265
+ if args.stage == "write":
266
+ # 写作档不给批次底稿:它是排纲期的工作底稿,其中有写作期约束力的条目
267
+ # 必须已经下沉到单元级段或细纲(见 artifact-protocols.md 段位契约纪律④)
268
+ live = [s for s in owned if s.kind == "单元级"]
269
+ else:
270
+ live = [s for s in owned
271
+ if s.kind == "单元级"
272
+ or s.kind == "批次底稿"]
273
+ chosen = set(permanent + live + undeclared)
274
+ span = unit_chapter_range(active, unit)
275
+ emit(sections, chosen, span, args.history, note, preamble)
276
+ return 0
277
+
278
+ parser.print_help()
279
+ return 2
280
+
281
+
282
+ if __name__ == "__main__":
283
+ sys.exit(main())
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ // Book-local only: never inherit an unrelated workspace or another book's choices.
7
+ function loadStyleWhitelist(file) {
8
+ const parent = path.dirname(path.resolve(file));
9
+ const book = path.basename(parent) === '正文' ? path.dirname(parent) : parent;
10
+ try {
11
+ return fs.readFileSync(path.join(book, '.deslop-whitelist'), 'utf8')
12
+ .split(/\r?\n/).map(line => line.trim())
13
+ .filter(line => line && !line.startsWith('#'))
14
+ .sort((a, b) => b.length - a.length);
15
+ } catch (error) {
16
+ if (error.code === 'ENOENT') return [];
17
+ throw error;
18
+ }
19
+ }
20
+
21
+ function styleSpans(text, whitelist) {
22
+ const spans = [];
23
+ for (const literal of whitelist) {
24
+ for (let at = text.indexOf(literal); at !== -1; at = text.indexOf(literal, at + 1)) {
25
+ spans.push([at, at + literal.length]);
26
+ }
27
+ }
28
+ return spans;
29
+ }
30
+
31
+ function maskStyleText(text, whitelist) {
32
+ const chars = text.split('');
33
+ for (const [start, end] of styleSpans(text, whitelist)) {
34
+ chars.fill('?', start, end);
35
+ }
36
+ return chars.join('');
37
+ }
38
+
39
+ module.exports = { loadStyleWhitelist, styleSpans, maskStyleText };
@@ -6,12 +6,14 @@ metadata: {"openclaw":{"source":"https://github.com/zenstory-ai/oh-story-claudec
6
6
  ---
7
7
  # story-review:多视角对抗式审查
8
8
 
9
- > Spawn 版本提示(不阻断 spawn):先读取项目根 `.story-deployed` 的 `agents_version`。与本版 `agents_version: 29` 不一致时(标记缺失、字段缺失/非整数、小于或大于 29)**照常按文件存在性检查并 spawn**,但只检查当前运行时的 canonical 目录;同时报告 `Notice: agents bundle 版本不匹配(项目 {N},本版 29)` 并提示重新运行 `/story-setup` 后新开会话;大于 29 时额外提示先更新 oh-story-claudecode,不要用本地旧版 setup 降级覆盖。只有 agent 文件缺失、或运行时不暴露 custom agent 时才降级 solo/direct,报告 `Fallback: ... -> solo`。
9
+ > Spawn 版本提示(不阻断 spawn):先读取项目根 `.story-deployed` 的 `agents_version`。与本版 `agents_version: 30` 不一致时(标记缺失、字段缺失/非整数、小于或大于 30)**照常按文件存在性检查并 spawn**,但只检查当前运行时的 canonical 目录;同时报告 `Notice: agents bundle 版本不匹配(项目 {N},本版 30)` 并提示重新运行 `/story-setup` 后新开会话;大于 30 时额外提示先更新 oh-story-claudecode,不要用本地旧版 setup 降级覆盖。只有 agent 文件缺失、或运行时不暴露 custom agent 时才降级 solo/direct,报告 `Fallback: ... -> solo`。
10
10
 
11
11
  你是审查协调器。你的职责是找出小说文本中的结构、角色、文字、设定问题,并给出可执行修改建议。
12
12
 
13
13
  **执行铁律:审查是找问题,不是验证正确性。**
14
14
 
15
+ **文风裁决**:正文写作、改写或审稿前先读 [references/style-resolution.md](references/style-resolution.md),加载本书文风并形成 `style_resolution`;无作者记忆也执行。当前请求、本书文风和 active 偏好按维度覆盖通用 references;同一裁决交给后续执行者。
16
+
15
17
  ## 作者习惯边界
16
18
 
17
19
  若作者记忆 state 已存在,审查前用 `scripts/author_memory_commit.py query` 获取本次相关 active 条目(总输出 ≤2KB)。它们只能帮助解释意图和组织报告,不能降低 rubric 严重度、把事实冲突判为无问题或跳过平台门禁;当前请求仍优先。完整规则见 [references/author-memory.md](references/author-memory.md)。
@@ -231,6 +233,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
231
233
  你的任务是【找问题】,不是验证正确性。以最严苛的标准审视。
232
234
  项目路径:{项目根}
233
235
  审查范围:{文件路径/章节/必要摘录}
236
+ 文风路径:{本书文风全文路径,无则写无}
237
+ style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
234
238
  审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
235
239
  Rubric Source: file | embedded fallback
236
240
  相关文件路径:{设定/大纲/细纲文件路径}
@@ -266,6 +270,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
266
270
  你的任务是【找问题】,不是验证正确性。以最严苛的标准审视。
267
271
  项目路径:{项目根}
268
272
  审查范围:{文件路径/章节/必要摘录}
273
+ 文风路径:{本书文风全文路径,无则写无}
274
+ style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
269
275
  审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
270
276
  Rubric Source: file | embedded fallback
271
277
  相关角色文件:{角色设定文件路径}
@@ -295,6 +301,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
295
301
  你的任务是【找问题】,不是验证正确性。以最严苛的标准审视。
296
302
  项目路径:{项目根}
297
303
  审查范围:{文件路径/章节/必要摘录}
304
+ 文风路径:{本书文风全文路径,无则写无}
305
+ style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
298
306
  审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
299
307
  Rubric Source: file | embedded fallback
300
308
  AI 味 / 禁用词摘要:{从 anti-ai-writing、banned-words 或内置 fallback 提取,必须内联}
@@ -303,11 +311,11 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
303
311
  1. 是否存在禁用词/套话/陈词滥调,或“像/好像/仿佛/如同”式比喻成片堆叠?
304
312
  2. 是否出现 AI 写作指纹、8 种 AI 写作模式(含模式 8 解释腔/上帝视角/安排感)或章末总结体?
305
313
  3. 格式是否合规(按戏剧单元/镜头自然断段、无机械字数切分、无空行、对话独立成行、主语节奏自然)?
306
- 4. 标点节奏是否匹配语气/人物声线:是否通篇句号化、随机堆砌问号/感叹号,或残留 `……`/`——` 硬造停顿?正文(含对话)里的破折号是否已清理?
314
+ 4. 标点节奏是否匹配语气/人物声线:是否通篇句号化、随机堆砌问号/感叹号,或残留 `……`/`——` 硬造停顿?本书已明确授权且有功能的停顿不因符号本身判错。
307
315
  5. 是否出现“这五个字 / 短短四字 / 三个字一落 / 八个字砸下去”等正文内具体字数表达?若统计口径不明、未见机器核对结果或无叙事必要,标为问题并建议改成非具体数字表达。
308
316
  6. 节奏是否均匀(有无连续多节无情绪变化)?
309
317
  7. 是否存在删掉无损的任务卡点或流程细节?若只是水/局部节奏问题标 S3;明显拖垮主线推进标 S2。
310
- 8. 身体部位同一词是否超 5 次?
318
+ 8. 身体细节是否重复、无功能?按本书文风和叙事作用判断,不设单词次数硬线。
311
319
  9. AI味分级(轻度/中度/重度)及证据。
312
320
  10. 去 AI 补充复核:是否有作者解释总结/意义尾巴;是否连续堆精致戏剧反应短语;是否把已有手机/屏幕/公告/规则/证据载体改成叙述者解释;是否把任务卡点当成自然感或凑字数手段;是否机械删除了有功能的生活化/角色化比喻或短篇主观审判句。
313
321
 
@@ -328,6 +336,8 @@ full/lean 模式下,主会话必须把“审查基准包摘要”直接写进
328
336
  审查范围:{文件路径/章节/必要摘录}
329
337
  已知角色:{从设定文件提取角色列表}
330
338
  继承的开放项(分批审查必填,无则写「无」):{从 追踪/伏笔.md 提取的、预计回收章 ≤ 本批末章的已埋未回收伏笔,连同上一批未解决 findings 摘要}
339
+ 文风路径:{本书文风全文路径,无则写无}
340
+ style_resolution:{本次生效要求及来源、被覆盖的默认条款、事实边界;文字风格判断共用}
331
341
  审查基准包摘要:{Phase 1 形成的 rubric / fallback 摘要,必须内联}
332
342
  Rubric Source: file | embedded fallback
333
343
  可选补充参考:本 Skill 的 `story-review/references/review-quality.md`;若不可读,不影响事实冲突扫描。
@@ -1,5 +1,7 @@
1
1
  # 去AI味完整指南
2
2
 
3
+ > 本文件的句长、视角、标点、修辞与禁用词是默认写法,服从 [style-resolution.md](style-resolution.md) 的逐维裁决。所选 Gate 检查表达效果,不因作者有意选择某写法就机械删除;获准命中按书级 `.deslop-whitelist` 处理。
4
+
3
5
  <!-- 同名副本×5 字节同步,改动后跑 scripts/check-shared-files.sh -->
4
6
 
5
7
  > 识别AI写作指纹、系统性去AI三遍法、禁用词约束、改写范例库。用于正文写作后做去AI味自检和改写时查阅。
@@ -105,18 +107,11 @@
105
107
 
106
108
  ### 规则 2:动作 + 对话 + 情绪反应
107
109
 
108
- 三要素循环推进,不要单写心理活动超过 2 段:
110
+ 动作、对话与情绪反应按场景需要交织,不按固定顺序轮换,不为凑齐三项补反应。
109
111
 
110
- ```
111
- 动作 -> 对话 -> 情绪反应 -> 动作 -> 对话 -> ……
112
- ```
112
+ 情绪没有固定译法,关键节点也可以准确直写。上下文已让情绪成立,不另补反应;需要补足信息时,优先选择、台词、策略、物件或实际后果。
113
113
 
114
- 情绪不用"他感到/他觉得",用身体反应和行为表现:
115
- - 不写"他很紧张" -> 写"手心全是汗,筷子差点掉了"
116
- - 不写"她很愤怒" -> 写"她把杯子摔在地上,碎片弹到脚背上也没弯腰捡"
117
- - 不写"他很伤心" -> 写"他在车里坐了二十分钟才发动引擎"
118
-
119
- 以上替换针对关键情绪节点;低强度过场情绪可一笔直写("他有点烦"),不必处处外化。
114
+ 身体细节只有带来新信息、影响动作或体现人物与场景特点时才保留。只在句尾重复标注情绪的微动作删掉,不换部位或同义动作。去味时沿用原文已有事实,不凭空添加摔杯子、攥袖口等行为。
120
115
 
121
116
  ### 规则 3:句子该多长(短句是工具,不是默认)
122
117
 
@@ -157,7 +152,7 @@
157
152
  1. 用行为代替形容词
158
153
  2. 用细节代替总结
159
154
  3. 用对话代替旁白说明
160
- 4. 用反应代替情绪词
155
+ 4. 用后果代替情绪总结
161
156
 
162
157
  ---
163
158
 
@@ -219,8 +214,7 @@
219
214
  > 完整禁用词表和句式模板见 [banned-words.md](banned-words.md)
220
215
 
221
216
  ### 正确替代示例
222
- - '他感到一丝紧张' -> '他的手在抖'
223
- - '她很伤心' -> '她背过身,把袖口攥皱了'
217
+ - '他感到一丝紧张,手心全是汗' -> '他签名时划破了纸'(身体细节只在造成后果时留)
224
218
  - '"好的。"他说道' -> '"好的。"他把门卡塞回口袋'
225
219
  - '他深吸一口气' -> '他把话咽回去'
226
220
 
@@ -276,7 +270,7 @@ AI 喜欢把事情凑成三个以显"完整"。-> 砍到只剩最有力的一条
276
270
  | 解释因果 | 「之所以…是因为」「原来…」「这意味着」「正是因为」-> 删。因果只从角色动作、对话、反应里让读者自己拼 |
277
271
  | 上帝视角剧透 | 「她不知道的是」「殊不知」「多年以后」「冥冥之中」「仿佛预示着」-> 删。只写角色此刻知道的,悬念让读者自己悬 |
278
272
  | 替读者下结论/定性 | 「演得真好」「这出戏她看过一遍」「他就是这样薄情的人」-> 删。把证据(神态、动作、台词)摆出来,定性留给读者 |
279
- | 替角色总结心理 | 「她明白,这一切都是命」-> 换成一句带偏见的闪念或一个身体反应 |
273
+ | 替角色总结心理 | 「她明白,这一切都是命」-> 无新增信息就删;确有角色判断时保留带偏见的闪念,不强配身体反应 |
280
274
  | 总结/动机/评价链把意义说满 | 「他终于明白」「这是最好的选择」「所有人都会记住这一刻」-> 删掉定性,改成角色当下要处理的具体缺口、未完成动作或局部反馈;不是保留评价再硬塞物件/动作 |
281
275
  | 安排感/硬铺垫 | 为后文强行交代背景、整段回忆倒叙 -> 背景按角色此刻真实所需,用闪念、半句话、物件零碎带出,不集中交代 |
282
276
  | 升华式收尾 | 结尾对仗拔高、金句点题 -> 用一个动作或一句留白收住,把"意思"压进画面里 |
@@ -315,7 +309,7 @@ AI 喜欢把事情凑成三个以显"完整"。-> 砍到只剩最有力的一条
315
309
 
316
310
  自检:删完连读一遍,读感像提纲或流水口令,就是删过了——把非峰值句恢复成自然白话,不是接着删。
317
311
 
318
- 本模式约束的是删减的度,不降低清理力度:禁用词、套路句式、告知式心理照删照改,模式 1-8 与 Gate A-G 全额执行;回填只回结构虚词和连接,不保留、不恢复任何模板措辞。
312
+ 本模式约束的是删减的度,不降低清理力度:选定 Gate 内的禁用词、套路句式、告知式心理照删照改;回填只回结构虚词和连接,不保留、不恢复任何模板措辞。
319
313
 
320
314
  ### 模式 10:二修伪自然(油腻倒装 / 监控动作清单 / 对话指标化)
321
315
 
@@ -381,7 +375,7 @@ AI 喜欢把事情凑成三个以显"完整"。-> 砍到只剩最有力的一条
381
375
  ## 系统性去AI三遍法
382
376
 
383
377
  ### Pass 1:去泛化(Strip Generic)
384
- - 抽象情绪总结句 -> 删或替换为具体动作
378
+ - 抽象情绪总结句 -> 按规则 2 判断:删重复说明,保留准确直写,需要时用原文已有信息落地
385
379
  - 假深度句 -> 删
386
380
  - 意义膨胀 -> 缩小到具体影响
387
381
  - 空洞结论 -> 删
@@ -411,13 +405,9 @@ AI 喜欢把事情凑成三个以显"完整"。-> 砍到只剩最有力的一条
411
405
 
412
406
  **原则**:少即是多。每段加 1-2 个具体细节就够了。
413
407
 
414
- ### 升级策略
408
+ ### 执行范围
415
409
 
416
- | AI味程度 | 策略 |
417
- |----------|------|
418
- | 轻度 | 只做 Pass 1 |
419
- | 中度 | Pass 1 + Pass 2 |
420
- | 重度 | 完整三遍 + 重点段落重写 |
410
+ 调用方指定 Gate 时,只处理选定 Gate;三遍法只安排顺序,不重新分级或扩大范围。未指定范围时,按实际问题选择适用检查。
421
411
 
422
412
  ### 自检清单
423
413
  - 对话自然度检查:对话是否使用口语化表达,是否避免了书面语/正式腔调
@@ -456,31 +446,13 @@ AI 喜欢把事情凑成三个以显"完整"。-> 砍到只剩最有力的一条
456
446
 
457
447
  ## 改写范例库
458
448
 
459
- ### 情绪外化范例
460
-
461
- **紧张**
462
- - '他感到一阵紧张,心跳不由自主地加快了'
463
- - 他攥紧了手里的纸杯,水洒出来一些
449
+ ### 情绪落地示例
464
450
 
465
- **愤怒**
466
- - '愤怒在他心中燃烧,他不由得握紧了拳头'
467
- - 他把筷子往桌上一拍,碗里的汤溅了出来
468
-
469
- **悲伤**
470
- - '一丝悲伤涌上心头,她的眼中闪过泪光'
471
- - 她低头搅着咖啡,搅了很久
472
-
473
- **害怕**
474
- - '恐惧瞬间笼罩了他,他感到一阵战栗'
475
- - 他的背贴在墙上,不敢动
476
-
477
- **失望**
478
- - '她感到一丝失落,心仿佛被什么东西揪住了'
479
- - "哦。"她把手机锁了屏
480
-
481
- **惊讶**
482
- - '他的瞳孔微微收缩,显然没有想到会听到这样的话'
483
- - 他张了张嘴,什么都没说出来
451
+ | 原文与语境 | 处理 |
452
+ |---|---|
453
+ | 「他很紧张。再错一题,补考也过不了。」 | 情绪有具体原因,可以直写,不补手抖或出汗 |
454
+ | 「她已经决定不再等他。她攥了攥袖口。」袖口动作无后续作用 | 删除第二句,不换成低头或咬唇 |
455
+ | 「手腕的伤让他握不住笔,签名只写了一半。」 | 保留,身体状态造成动作失败,不能当作情绪套话删除 |
484
456
 
485
457
  ### 场景描写范例
486
458
 
@@ -571,7 +543,7 @@ AI 喜欢把事情凑成三个以显"完整"。-> 砍到只剩最有力的一条
571
543
  - [ ] **无书面语连词堆砌**:无"于是乎/与此同时/从而/因而/诚然"泛滥
572
544
  - [ ] **章尾无总结升华**:用动作/对话/悬念收束,无感悟/哲理/预告
573
545
  - [ ] **无大段心理描写**:心理活动不超过2段,无括号标注内心
574
- - [ ] **情绪用动作展示**:关键情绪节点无直接写"愤怒/伤心/紧张",用身体反应替代;低强度过场情绪可一笔直写,不必处处外化
546
+ - [ ] **情绪落地**:按规则 2 保留准确直写与有功能的身体细节,删除重复说明,不给每个情绪词配动作
575
547
  - [ ] **对话口语化**:无书面腔,不同角色语气可区分
576
548
  - [ ] **标点不压平**:没有把质问、爆发、犹豫全部压成句号;也没有随机堆砌 `?`/`!`,或用 `……`/`——` 硬造停顿
577
549
  - [ ] **Show Don't Tell**:用行为代替形容词,用细节代替总结
@@ -6,13 +6,15 @@
6
6
 
7
7
  加载优先级从高到低:
8
8
 
9
- 1. 安全、平台、字数、文件协议等硬性门禁;
9
+ 1. 安全、用户授权范围、明确的平台交付要求、字数与文件协议;句长、视角、修辞和标点偏好不属于不可覆盖的硬门禁;
10
10
  2. 用户在当前请求中的明确要求;
11
11
  3. 当前书的 `设定/文风.md`、题材定位、细纲和其他项目设定;
12
12
  4. 作者记忆中的本书偏好;
13
13
  5. 作者记忆中的题材、流程和全局偏好;
14
14
  6. 对标素材、通用方法和默认值。
15
15
 
16
+ 按表达维度取最窄适用要求:低优先级只补缺项,不与高优先级要求并列执行。通用 references 自称“必须/禁用”不改变此顺序;审稿不因作者有意采用的表达本身扣分,真实可读性与因果问题仍照常评价。
17
+
16
18
  作者记忆不能把本书事实写进 `.story/作者记忆/`,不能覆盖当前请求,不能降低审稿 rubric,也不能让去 AI 味改动剧情意图。小说事实继续由各书的 `追踪/` 和 `设定/` 管理。
17
19
 
18
20
  ## 文件与所有权
@@ -27,7 +29,7 @@
27
29
  └── 变更记录.md # 最近 100 次、最新在前的事务记录
28
30
  ```
29
31
 
30
- 三个 Markdown 文件都从 state 确定性生成,禁止手改;完整历史保留在 state,变更记录只展示最近 100 次。`作者画像.md` 是人类管理视图,普通写作 agent 不整份注入,而是调用 `query` 取得本次相关的紧凑上下文。作者记忆不存在时,普通写作、审稿和去味任务直接继续,不自动初始化空目录;首次 `record` 会随事务创建。
32
+ 三个 Markdown 文件都从 state 确定性生成,禁止手改;完整历史保留在 state,变更记录只展示最近 100 次。`作者画像.md` 是人类管理视图,普通写作 agent 不整份注入,而是调用 `query` 取得本次相关的紧凑上下文。`query` 要显式传 `--book`、已知的 `--genre` / `--workflow`;只传 kind 不会返回本书或题材项。作者记忆不存在时,普通写作、审稿和去味任务直接继续,不自动初始化空目录;首次 `record` 会随事务创建。
31
33
 
32
34
  工作区必须显式传给脚本。优先使用已经包含 `.story/作者记忆/` 的最近祖先;首次初始化时使用承载多本书、`.active-book`、`长篇/`、`短篇/` 或 `拆文库/` 的创作工作区根。不要把用户主目录当默认工作区。
33
35
 
@@ -79,7 +81,7 @@
79
81
 
80
82
  - 同一类型、范围、归纳文本再次出现时,脚本强化原条目,累加证据和确认次数,不重复建条目。
81
83
  - 新偏好与 active 条目矛盾时,先以 `conflict` 记候选,并在 `conflicts_with` 列出冲突 ID;当前任务仍按本轮明确要求执行。
82
- - 作者选定新规则时用 `replace`,一次性启用新条目并把旧条目标成 `superseded`。
84
+ - 同一范围的规则改版用 `replace`,启用新条目并将旧条目标成 `superseded`。本书例外用 `remember` 新建 book 条目,保留 global 习惯;只有作者明确撤销或改变旧规则范围时才跨范围替换。
83
85
  - pending 可以用 `decide=activate|reject`;冲突候选不能绕过旧规则直接 activate。
84
86
  - 作者说“忘掉 / 这不再是我的习惯”时用 `forget`,保留历史证据但不再加载。
85
87
  - active 条目的语义不可原地偷改;语义变化必须 replace,历史才可审计。
@@ -139,17 +141,17 @@
139
141
  ```json
140
142
  {
141
143
  "action": "replace",
142
- "old_ids": ["AP001", "AP002"],
144
+ "old_ids": ["AP001"],
143
145
  "preference": {
144
146
  "kind": "prose_style",
145
- "scope": {"level": "book", "value": "雾港来信"},
146
- "assertion": "本书对话允许更长的试探,但避免解释设定",
147
- "quote": "这本书可以让对话慢一点,多试探,但还是别拿台词讲设定。",
147
+ "scope": {"level": "global", "value": null},
148
+ "assertion": "以后对话允许更长的试探,但避免解释设定",
149
+ "quote": "把以前对话都要短的习惯替换掉:以后可以让对话慢一点,多试探,但还是别拿台词讲设定。",
148
150
  "source_ref": "conversation:2026-08-25",
149
151
  "source": "explicit_user",
150
152
  "confidence": "high",
151
153
  "importance": "high",
152
- "reason": "作者明确用本书新规则替代旧候选"
154
+ "reason": "作者明确替换原有全局规则,不是新增本书例外"
153
155
  }
154
156
  }
155
157
  ```
@@ -1,8 +1,10 @@
1
1
  # AI味禁用词与句式表
2
2
 
3
+ > 表达默认值服从 [style-resolution.md](style-resolution.md);文件结构与事实约束不豁免。
4
+
3
5
  <!-- 同名副本×6 字节同步,改动后跑 scripts/check-shared-files.sh -->
4
6
 
5
- ## 最毒禁用句式(出现即修,最高优先级)
7
+ ## 默认优先检查的句式(先对照本书文风)
6
8
 
7
9
  写网文最毒的 AI 句式,作者一旦养成就会反复出现。Gate A 第一遍扫描必须命中:
8
10
 
@@ -133,13 +133,15 @@
133
133
 
134
134
  角色情绪是连续的、循序渐进的。从生气到高兴:生气 → 不那么生气 → 不生气 → 高兴,每次转变需对应事件触发。不能跳步。
135
135
 
136
- ### 情绪四步法(缺一不可)
136
+ ### 情绪与行动的因果检查
137
137
 
138
138
  1. 遇到事件(失衡状态)
139
- 2. 情绪反应(外在表现:动作、表情、语言)
140
- 3. 内心思考(即使没思考也要写出"没有思考",表达鲁莽)
139
+ 2. 情绪反应(可以直写,也可以体现在语言、选择或有功能的动作中)
140
+ 3. 内心思考(只写影响理解的判断;鲁莽可以直接体现在行动里)
141
141
  4. 采取行动(基于前三步结果回应)
142
142
 
143
+ 用于检查转变是否成立,不要求逐步写满;上下文已清楚的反应或思考无需补写。
144
+
143
145
  ### 对话不平淡三思路
144
146
 
145
147
  - 对话本身带来/强化某个核心驱动力(期待、爽感、悬念)
@@ -154,7 +156,7 @@
154
156
  - 大量信息通过对话展示会显得啰嗦,部分信息转化为情节、心理描写、旁白、环境、动作
155
157
  - 用角色的语气和立场包裹信息,不是机械陈述设定
156
158
  - 设定用到哪个稍微带出来就行,不需完完全全讲明白前因后果
157
- - **角色不当"科普嘴"**:设定/原理/前因后果不能靠任何角色(尤其信息型/AI 配角)整段讲解——Gate G 同样适用于角色台词。拆成角色在压力下挤出的半句话 + 身体反应 + 留白,用到哪带哪点
159
+ - **角色不当"科普嘴"**:设定/原理/前因后果不能靠任何角色(尤其信息型/AI 配角)整段讲解——Gate G 同样适用于角色台词。按角色当下的目的和对话阻力取舍信息,用到哪带哪点,不固定拼接身体反应。
158
160
 
159
161
  ### 信息拉扯示例(以"主角新书起飞了"为例)
160
162
 
@@ -51,7 +51,7 @@
51
51
  - [ ] 没有连续多段同一情绪
52
52
  - [ ] 对话符合人物身份(不同人说话方式不同)
53
53
  - [ ] 标点节奏符合语气和人物声线:没有通篇句号化,也没有随机堆砌问号/感叹号;正文(含对话)不残留 `……`/`——`,迟疑或打断已改为动作、短句、逗号或句号
54
- - [ ] 情绪通过动作落地(不是直接说"他很难过")
54
+ - [ ] 情绪词有落点(融进动作句、当对话提示语、结句后直接换事或接场内物件),不是接更多情绪
55
55
  - [ ] 标题行以外没有章节/写作元信息:不得出现 `第[一二三四五六七八九十百千万两0-9]+章|上一章|上章|前一章|本章|这一章|前文|后文|伏笔|细纲|读者` 这类词;需要承接前文时改成角色能感知的事件锚点或相对时间;故事内真实阅读/讨论“第X章”或真实读者身份语境除外
56
56
 
57
57
  ### 连载连续性
@@ -135,7 +135,7 @@
135
135
  | 空泛总结 | 「他终于明白了」「一切尽在不言中」 | 删掉,用行动代替 |
136
136
  | 套路修辞 | 「命运仿佛在和他开玩笑」 | 删掉或换成具体描述 |
137
137
  | 比喻堆叠 | 连续多处「像/好像/仿佛/如同」,每个画面都靠比喻解释 | 只留最有叙事功能的少数比喻,其余改成动作、物件、声音或后果 |
138
- | 情绪标签 | 「他感到一阵悲伤」 | 改为行为表现 |
138
+ | 空转情绪句 | 「他感到一阵悲伤」,无落点 | 删,或写他此刻做不成的事;直写本身不算缺陷 |
139
139
  | 心理描写空转 | 内心独白无新信息、重复同一情绪或复述读者已知 | 只压缩空转部分;带新信息、决断或情绪转折的独白不按句数压缩 |
140
140
 
141
141
  ### 维度 5:逻辑连贯