@oh-story/dsh 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. package/README.md +7 -7
  2. package/lib/client.js +7 -3
  3. package/lib/client.js.map +2 -2
  4. package/lib/drama/manifest.json +212 -142
  5. package/lib/drama/skills/short-drama/SKILL.md +14 -2
  6. package/lib/drama/skills/short-drama/assets/project-template/short-drama.json +3 -0
  7. package/lib/drama/skills/short-drama/references/creator-documents.md +3 -0
  8. package/lib/drama/skills/short-drama/references/knowhow-index.md +15 -0
  9. package/lib/drama/skills/short-drama/scripts/project_tool.py +131 -0
  10. package/lib/drama/skills/short-drama-assets/SKILL.md +2 -1
  11. package/lib/drama/skills/short-drama-assets/references/asset-review-checklist.md +2 -0
  12. package/lib/drama/skills/short-drama-assets/references/era-anchors.md +37 -0
  13. package/lib/drama/skills/short-drama-assets/references/stage-contract.md +2 -0
  14. package/lib/drama/skills/short-drama-develop/SKILL.md +10 -4
  15. package/lib/drama/skills/short-drama-develop/assets/adaptation-map.example.jsonl +1 -1
  16. package/lib/drama/skills/short-drama-develop/assets/creative-brief.md +8 -0
  17. package/lib/drama/skills/short-drama-develop/references/adaptation-craft.md +80 -13
  18. package/lib/drama/skills/short-drama-develop/references/episode-design.md +95 -12
  19. package/lib/drama/skills/short-drama-develop/references/genre-and-hook-playbook.md +9 -5
  20. package/lib/drama/skills/short-drama-develop/references/genre-cards//345/244/215/344/273/207/346/211/223/350/204/270.md +1 -1
  21. package/lib/drama/skills/short-drama-develop/references/genre-cards//347/263/273/347/273/237/346/265/201.md +51 -0
  22. package/lib/drama/skills/short-drama-develop/references/genre-cards//351/200/206/350/242/255.md +51 -0
  23. package/lib/drama/skills/short-drama-develop/references/genre-cards//351/207/215/347/224/237/347/251/277/350/266/212.md +51 -0
  24. package/lib/drama/skills/short-drama-develop/references/genre-cards.md +10 -7
  25. package/lib/drama/skills/short-drama-develop/references/premise-devices.md +15 -9
  26. package/lib/drama/skills/short-drama-develop/references/serial-character-and-memory.md +3 -2
  27. package/lib/drama/skills/short-drama-develop/references/stage-contract.md +14 -7
  28. package/lib/drama/skills/short-drama-develop/references/story-craft.md +7 -3
  29. package/lib/drama/skills/short-drama-edit/SKILL.md +43 -20
  30. package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +49 -13
  31. package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +4 -2
  32. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Overlay.tsx +31 -0
  33. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +5 -5
  34. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +68 -69
  35. package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +39 -29
  36. package/lib/drama/skills/short-drama-edit/assets/remotion/src/rules.mjs +188 -0
  37. package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +26 -13
  38. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/Card.tsx +72 -0
  39. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/CornerChip.tsx +39 -0
  40. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/ScreenText.tsx +36 -0
  41. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/SystemPanel.tsx +44 -0
  42. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/TaskPanel.tsx +100 -0
  43. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/chrome.tsx +197 -0
  44. package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/tokens.ts +62 -0
  45. package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +1 -0
  46. package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +4 -2
  47. package/lib/drama/skills/short-drama-edit/references/cut-craft.md +3 -1
  48. package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +6 -2
  49. package/lib/drama/skills/short-drama-edit/references/generated-footage.md +12 -6
  50. package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +13 -8
  51. package/lib/drama/skills/short-drama-edit/references/stage-contract.md +2 -0
  52. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1153 -121
  53. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +49 -9
  54. package/lib/drama/skills/short-drama-novel-analyze/SKILL.md +3 -3
  55. package/lib/drama/skills/short-drama-novel-analyze/assets/episode-candidate.example.jsonl +2 -2
  56. package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-triage.md +8 -4
  57. package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-value.md +10 -3
  58. package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +25 -1
  59. package/lib/drama/skills/short-drama-novel-analyze/references/stage-contract.md +1 -0
  60. package/lib/drama/skills/short-drama-review/SKILL.md +2 -2
  61. package/lib/drama/skills/short-drama-review/references/review-method.md +6 -1
  62. package/lib/drama/skills/short-drama-review/references/rubric-assets-prompts.md +11 -0
  63. package/lib/drama/skills/short-drama-review/references/rubric-story-script.md +77 -3
  64. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +15 -0
  65. package/lib/drama/skills/short-drama-review/references/stage-contract.md +3 -0
  66. package/lib/drama/skills/short-drama-storyboard/SKILL.md +13 -5
  67. package/lib/drama/skills/short-drama-storyboard/references/blocking-playbooks.md +1 -1
  68. package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +2 -2
  69. package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +82 -14
  70. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +4 -2
  71. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +5 -3
  72. package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +12 -0
  73. package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +4 -5
  74. package/lib/drama/skills/short-drama-video-prompts/references/generability.md +4 -2
  75. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +40 -1
  76. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +20 -14
  77. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +1 -1
  78. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +8 -7
  79. package/lib/drama/skills/short-drama-video-prompts/references/review-and-fixtures.md +1 -1
  80. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +1 -0
  81. package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +8 -1
  82. package/lib/drama/skills/short-drama-video-prompts/references/wan-3.0.md +103 -0
  83. package/lib/drama/skills/short-drama-video-prompts/scripts/motion_timing_check.py +8 -7
  84. package/lib/drama/skills/short-drama-write/SKILL.md +8 -3
  85. package/lib/drama/skills/short-drama-write/references/dialogue-craft.md +1 -1
  86. package/lib/drama/skills/short-drama-write/references/script-craft.md +56 -3
  87. package/lib/drama/skills/short-drama-write/references/stage-contract.md +4 -0
  88. package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +48 -2
  89. package/lib/index.js +71 -21
  90. package/lib/index.js.map +3 -3
  91. package/lib/oh-story/manifest.json +545 -310
  92. package/lib/oh-story/roles/chapter-extractor.md +11 -11
  93. package/lib/oh-story/roles/character-designer.md +1 -2
  94. package/lib/oh-story/roles/consistency-checker.md +11 -9
  95. package/lib/oh-story/roles/narrative-writer.md +24 -25
  96. package/lib/oh-story/roles/story-architect.md +9 -61
  97. package/lib/oh-story/roles/story-explorer.md +20 -125
  98. package/lib/oh-story/roles/story-researcher.md +0 -1
  99. package/lib/oh-story/skills/story/SKILL.md +6 -6
  100. package/lib/oh-story/skills/story/VERSION +1 -1
  101. package/lib/oh-story/skills/story/references/author-memory-maintenance.md +75 -0
  102. package/lib/oh-story/skills/story/references/author-memory.md +40 -118
  103. package/lib/oh-story/skills/story/scripts/author_memory_commit.py +3 -3
  104. package/lib/oh-story/skills/story-deslop/SKILL.md +24 -25
  105. package/lib/oh-story/skills/story-deslop/references/agent-calls.md +5 -0
  106. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +1 -1
  107. package/lib/oh-story/skills/story-deslop/references/author-memory-maintenance.md +75 -0
  108. package/lib/oh-story/skills/story-deslop/references/author-memory.md +40 -118
  109. package/lib/oh-story/skills/story-deslop/references/banned-words.md +2 -2
  110. package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +21 -4
  111. package/lib/oh-story/skills/story-deslop/references/style-resolution.md +4 -4
  112. package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +3 -3
  113. package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +155 -8
  114. package/lib/oh-story/skills/story-import/SKILL.md +63 -579
  115. package/lib/oh-story/skills/story-import/references/deep-analysis.md +47 -0
  116. package/lib/oh-story/skills/story-import/references/format-and-structure.md +1 -1
  117. package/lib/oh-story/skills/story-import/references/import-report.md +64 -0
  118. package/lib/oh-story/skills/story-import/references/import-special-cases.md +34 -0
  119. package/lib/oh-story/skills/story-import/references/import-tracking.md +95 -0
  120. package/lib/oh-story/skills/story-import/references/length-routing.md +1 -1
  121. package/lib/oh-story/skills/story-import/references/outline-reverse-rules.md +79 -0
  122. package/lib/oh-story/skills/story-import/references/outline-reverse.md +24 -0
  123. package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +95 -91
  124. package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +24 -12
  125. package/lib/oh-story/skills/story-import/references/tracking-initialization.md +1 -1
  126. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +11 -9
  127. package/lib/oh-story/skills/story-import/scripts/build_outline_brief.py +332 -0
  128. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +101 -14
  129. package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +278 -23
  130. package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +179 -23
  131. package/lib/oh-story/skills/story-long-analyze/SKILL.md +28 -50
  132. package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +12 -5
  133. package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +1 -1
  134. package/lib/oh-story/skills/story-long-analyze/references/final-checks.md +19 -0
  135. package/lib/oh-story/skills/story-long-analyze/references/index-rebuild.md +11 -0
  136. package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +21 -55
  137. package/lib/oh-story/skills/story-long-analyze/references/stage1-golden-chapters.md +128 -0
  138. package/lib/oh-story/skills/story-long-analyze/references/stage2-extraction.md +229 -0
  139. package/lib/oh-story/skills/story-long-analyze/references/stage3-plot-rhythm.md +480 -0
  140. package/lib/oh-story/skills/story-long-analyze/references/stage4-characters-settings.md +195 -0
  141. package/lib/oh-story/skills/story-long-analyze/references/stage5-report.md +33 -0
  142. package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +17 -0
  143. package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +1 -1
  144. package/lib/oh-story/skills/story-long-analyze/references/synthesis-inputs.md +39 -0
  145. package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +47 -8
  146. package/lib/oh-story/skills/story-long-scan/SKILL.md +41 -193
  147. package/lib/oh-story/skills/story-long-scan/references/platform-ciweimao.md +19 -0
  148. package/lib/oh-story/skills/story-long-scan/references/platform-fanqie.md +45 -0
  149. package/lib/oh-story/skills/story-long-scan/references/platform-jjwxc.md +28 -0
  150. package/lib/oh-story/skills/story-long-scan/references/platform-qidian.md +35 -0
  151. package/lib/oh-story/skills/story-long-scan/references/platform-qimao.md +27 -0
  152. package/lib/oh-story/skills/story-long-scan/references/topic-decision.md +6 -2
  153. package/lib/oh-story/skills/story-long-write/SKILL.md +32 -73
  154. package/lib/oh-story/skills/story-long-write/references/agent-calls.md +47 -0
  155. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +1 -1
  156. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +18 -201
  157. package/lib/oh-story/skills/story-long-write/references/author-memory-maintenance.md +75 -0
  158. package/lib/oh-story/skills/story-long-write/references/author-memory.md +40 -118
  159. package/lib/oh-story/skills/story-long-write/references/banned-words.md +2 -2
  160. package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +6 -10
  161. package/lib/oh-story/skills/story-long-write/references/character-relations.md +49 -1
  162. package/lib/oh-story/skills/story-long-write/references/deslop-gates.md +171 -0
  163. package/lib/oh-story/skills/story-long-write/references/emotion-on-page.md +116 -0
  164. package/lib/oh-story/skills/story-long-write/references/emotional-arc-design.md +1 -114
  165. package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +1 -1
  166. package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +3 -2
  167. package/lib/oh-story/skills/story-long-write/references/long-format.md +0 -8
  168. package/lib/oh-story/skills/story-long-write/references/long-genre-catalog.md +1 -1
  169. package/lib/oh-story/skills/story-long-write/references/long-genre-mechanics.md +3 -3
  170. package/lib/oh-story/skills/story-long-write/references/opening-design.md +2 -2
  171. package/lib/oh-story/skills/story-long-write/references/outline-conflict.md +4 -4
  172. package/lib/oh-story/skills/story-long-write/references/outline-methods.md +7 -7
  173. package/lib/oh-story/skills/story-long-write/references/outline-rhythm.md +3 -3
  174. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +14 -69
  175. package/lib/oh-story/skills/story-long-write/references/plot-frameworks.md +1 -1
  176. package/lib/oh-story/skills/story-long-write/references/plot-special-topics.md +2 -2
  177. package/lib/oh-story/skills/story-long-write/references/project-files.md +10 -6
  178. package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +1 -1
  179. package/lib/oh-story/skills/story-long-write/references/reference-index.md +4 -4
  180. package/lib/oh-story/skills/story-long-write/references/stop-and-fix.md +9 -0
  181. package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -58
  182. package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
  183. package/lib/oh-story/skills/story-long-write/references/style-resolution.md +4 -4
  184. package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +1 -1
  185. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +11 -9
  186. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +33 -44
  187. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +18 -51
  188. package/lib/oh-story/skills/story-long-write/references/workflow-outline.md +157 -0
  189. package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +53 -67
  190. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +112 -251
  191. package/lib/oh-story/skills/story-long-write/references/workflow-volume.md +142 -0
  192. package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +5 -3
  193. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +18 -56
  194. package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +3 -3
  195. package/lib/oh-story/skills/story-long-write/scripts/build_architect_brief.py +260 -0
  196. package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +96 -16
  197. package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +155 -8
  198. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +101 -14
  199. package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +7 -2
  200. package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +2 -1
  201. package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +250 -50
  202. package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +278 -23
  203. package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +179 -23
  204. package/lib/oh-story/skills/story-review/SKILL.md +19 -273
  205. package/lib/oh-story/skills/story-review/references/agent-prompts.md +184 -0
  206. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +1 -1
  207. package/lib/oh-story/skills/story-review/references/author-memory-maintenance.md +75 -0
  208. package/lib/oh-story/skills/story-review/references/author-memory.md +40 -118
  209. package/lib/oh-story/skills/story-review/references/banned-words.md +2 -2
  210. package/lib/oh-story/skills/story-review/references/batch-review.md +19 -0
  211. package/lib/oh-story/skills/story-review/references/character-relations.md +49 -1
  212. package/lib/oh-story/skills/story-review/references/review-quality.md +2 -1
  213. package/lib/oh-story/skills/story-review/references/review-tracking.md +10 -0
  214. package/lib/oh-story/skills/story-review/references/solo.md +52 -0
  215. package/lib/oh-story/skills/story-review/references/style-resolution.md +4 -4
  216. package/lib/oh-story/skills/story-review/references/tracking-initialization.md +1 -1
  217. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +11 -9
  218. package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +3 -3
  219. package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +155 -8
  220. package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +278 -23
  221. package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +179 -23
  222. package/lib/oh-story/skills/story-setup/SKILL.md +69 -458
  223. package/lib/oh-story/skills/story-setup/references/agent-references/agent-quality.md +4 -4
  224. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +1 -1
  225. package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +2 -2
  226. package/lib/oh-story/skills/story-setup/references/agent-references/benchmark-style-load.md +107 -0
  227. package/lib/oh-story/skills/story-setup/references/agent-references/character-relations.md +49 -1
  228. package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +21 -4
  229. package/lib/oh-story/skills/story-setup/references/agent-references/emotion-on-page.md +116 -0
  230. package/lib/oh-story/skills/story-setup/references/agent-references/emotional-arc-design.md +1 -114
  231. package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +1 -1
  232. package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +1 -1
  233. package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-catalog.md +1 -1
  234. package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-mechanics.md +3 -3
  235. package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +7 -5
  236. package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +2 -2
  237. package/lib/oh-story/skills/story-setup/references/agent-references/outline-conflict.md +4 -4
  238. package/lib/oh-story/skills/story-setup/references/agent-references/outline-methods.md +7 -7
  239. package/lib/oh-story/skills/story-setup/references/agent-references/outline-rhythm.md +3 -3
  240. package/lib/oh-story/skills/story-setup/references/agent-references/short-emotional-methods.md +1 -1
  241. package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +0 -15
  242. package/lib/oh-story/skills/story-setup/references/agent-references/short-reversal.md +1 -1
  243. package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -58
  244. package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
  245. package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +4 -4
  246. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +18 -56
  247. package/lib/oh-story/skills/story-setup/references/diagnostics.md +3 -3
  248. package/lib/oh-story/skills/story-short-analyze/SKILL.md +37 -110
  249. package/lib/oh-story/skills/story-short-analyze/references/analysis-character-relations.md +1 -1
  250. package/lib/oh-story/skills/story-short-analyze/references/analysis-method.md +42 -0
  251. package/lib/oh-story/skills/story-short-analyze/references/optional-modules.md +97 -0
  252. package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +9 -47
  253. package/lib/oh-story/skills/story-short-analyze/references/quality-checklist.md +80 -0
  254. package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +4 -4
  255. package/lib/oh-story/skills/story-short-analyze/references/stage2-3-structure-emotion.md +308 -0
  256. package/lib/oh-story/skills/story-short-analyze/references/{material-decomposition.md → stage4-6-reversal-summary.md} +303 -374
  257. package/lib/oh-story/skills/story-short-scan/SKILL.md +30 -64
  258. package/lib/oh-story/skills/story-short-scan/references/manual-rank-input.md +36 -0
  259. package/lib/oh-story/skills/story-short-scan/references/platform-dianzhong.md +24 -0
  260. package/lib/oh-story/skills/story-short-scan/references/platform-heiyan.md +21 -0
  261. package/lib/oh-story/skills/story-short-scan/references/topic-match.md +38 -0
  262. package/lib/oh-story/skills/story-short-write/SKILL.md +23 -34
  263. package/lib/oh-story/skills/story-short-write/references/agent-calls.md +13 -0
  264. package/lib/oh-story/skills/story-short-write/references/author-memory-maintenance.md +75 -0
  265. package/lib/oh-story/skills/story-short-write/references/author-memory.md +40 -118
  266. package/lib/oh-story/skills/story-short-write/references/banned-words.md +2 -2
  267. package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +1 -21
  268. package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +1 -1
  269. package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +0 -15
  270. package/lib/oh-story/skills/story-short-write/references/output-contract.md +9 -47
  271. package/lib/oh-story/skills/story-short-write/references/reference-index.md +17 -49
  272. package/lib/oh-story/skills/story-short-write/references/scene-craft.md +40 -0
  273. package/lib/oh-story/skills/story-short-write/references/short-craft.md +7 -43
  274. package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -3
  275. package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -1
  276. package/lib/oh-story/skills/story-short-write/references/short-reversal.md +1 -1
  277. package/lib/oh-story/skills/story-short-write/references/style-resolution.md +4 -4
  278. package/lib/oh-story/skills/story-short-write/references/submission-craft.md +1 -1
  279. package/lib/oh-story/skills/story-short-write/references/villain-and-reveal.md +5 -10
  280. package/lib/oh-story/skills/story-short-write/references/workflow-design.md +19 -12
  281. package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +22 -32
  282. package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +84 -17
  283. package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +7 -119
  284. package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +3 -3
  285. package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +155 -8
  286. package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +7 -2
  287. package/lib/types/client/video-studio.d.ts.map +1 -1
  288. package/lib/types/native-hooks.d.ts +2 -2
  289. package/lib/types/native-hooks.d.ts.map +1 -1
  290. package/lib/types/role-tool.d.ts.map +1 -1
  291. package/lib/types/skill-provider.d.ts.map +1 -1
  292. package/lib/types/video-project.d.ts.map +1 -1
  293. package/lib/types/workspace-route.d.ts.map +1 -1
  294. package/lib/video-recap/CHANGELOG.md +60 -1
  295. package/lib/video-recap/README.en.md +348 -137
  296. package/lib/video-recap/README.md +340 -136
  297. package/lib/video-recap/manifest.json +406 -251
  298. package/lib/video-recap/skills/video-assemble/SKILL.md +30 -15
  299. package/lib/video-recap/skills/video-assemble/references/audio-modes.md +63 -0
  300. package/lib/video-recap/skills/video-assemble/references/explicit-audio-mix.md +75 -0
  301. package/lib/video-recap/skills/video-assemble/references/foreground-compose.md +118 -0
  302. package/lib/video-recap/skills/video-assemble/references/narration-adoption.md +103 -0
  303. package/lib/video-recap/skills/video-assemble/references/packaging.md +45 -0
  304. package/lib/video-recap/skills/video-assemble/references/pair-media.md +74 -0
  305. package/lib/video-recap/skills/video-assemble/references/source-score.md +147 -0
  306. package/lib/video-recap/skills/video-assemble/references/subtitle-track.md +202 -0
  307. package/lib/video-recap/skills/video-assemble/scripts/adoption/__init__.py +1 -0
  308. package/lib/video-recap/skills/video-assemble/scripts/adoption/audio_mix_binding.py +279 -0
  309. package/lib/video-recap/skills/video-assemble/scripts/adoption/frozen_audio.py +187 -0
  310. package/lib/video-recap/skills/video-assemble/scripts/adoption/narration_binding.py +323 -0
  311. package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_inputs.py +109 -0
  312. package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_publish.py +130 -0
  313. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +10 -46
  314. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +378 -119
  315. package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +29 -12
  316. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +95 -44
  317. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +75 -32
  318. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +11 -11
  319. package/lib/video-recap/skills/video-assemble/scripts/compose_foreground.py +293 -0
  320. package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +71 -78
  321. package/lib/video-recap/skills/video-assemble/scripts/jianying/__init__.py +1 -0
  322. package/lib/video-recap/skills/video-assemble/scripts/{jianying_builders.py → jianying/builders.py} +39 -67
  323. package/lib/video-recap/skills/video-assemble/scripts/{jianying_model.py → jianying/model.py} +3 -11
  324. package/lib/video-recap/skills/video-assemble/scripts/{jianying_optional.py → jianying/optional.py} +1 -1
  325. package/lib/video-recap/skills/video-assemble/scripts/jianying/schema.py +53 -0
  326. package/lib/video-recap/skills/video-assemble/scripts/{jianying_templates.py → jianying/templates.py} +1 -1
  327. package/lib/video-recap/skills/video-assemble/scripts/{jianying_timeline_contract.py → jianying/timeline_contract.py} +34 -13
  328. package/lib/video-recap/skills/video-assemble/scripts/{jianying_writer.py → jianying/writer.py} +7 -17
  329. package/lib/video-recap/skills/video-assemble/scripts/lib.py +37 -4
  330. package/lib/video-recap/skills/video-assemble/scripts/media.py +12 -21
  331. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +64 -34
  332. package/lib/video-recap/skills/video-assemble/scripts/packaging.py +122 -0
  333. package/lib/video-recap/skills/video-assemble/scripts/pair_media.py +216 -0
  334. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +1 -3
  335. package/lib/video-recap/skills/video-assemble/scripts/source_score.py +469 -0
  336. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +25 -9
  337. package/lib/video-recap/skills/video-assemble/scripts/subtitles/__init__.py +1 -0
  338. package/lib/video-recap/skills/video-assemble/scripts/{subtitle_core.py → subtitles/core.py} +13 -6
  339. package/lib/video-recap/skills/video-assemble/scripts/{subtitle_render.py → subtitles/render.py} +5 -4
  340. package/lib/video-recap/skills/video-assemble/scripts/subtitles/track.py +324 -0
  341. package/lib/video-recap/skills/video-assemble/scripts/subtitles/track_binding.py +200 -0
  342. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +30 -46
  343. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +91 -7
  344. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +22 -8
  345. package/lib/video-recap/skills/video-cut/SKILL.md +34 -16
  346. package/lib/video-recap/skills/video-cut/references/shot-review.md +50 -0
  347. package/lib/video-recap/skills/video-cut/scripts/cut.py +2 -28
  348. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +58 -62
  349. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +21 -106
  350. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +14 -9
  351. package/lib/video-recap/skills/video-cut/scripts/lib.py +39 -0
  352. package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +2 -155
  353. package/lib/video-recap/skills/video-cut/scripts/narrative_selection.py +244 -0
  354. package/lib/video-recap/skills/video-cut/scripts/shot_review.py +357 -0
  355. package/lib/video-recap/skills/video-recap/SKILL.md +86 -42
  356. package/lib/video-recap/skills/video-recap/references/audio-routing.md +126 -0
  357. package/lib/video-recap/skills/video-recap/references/config-playbook.md +12 -8
  358. package/lib/video-recap/skills/video-recap/references/data-schema.md +44 -33
  359. package/lib/video-recap/skills/video-recap/references/resource-library.md +151 -0
  360. package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +1 -1
  361. package/lib/video-recap/skills/video-recap/scripts/doctor.py +123 -30
  362. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +22 -75
  363. package/lib/video-recap/skills/video-recap/scripts/lib.py +3 -3
  364. package/lib/video-recap/skills/video-recap/scripts/library.py +509 -0
  365. package/lib/video-recap/skills/video-recap/scripts/materials.py +63 -91
  366. package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +8 -70
  367. package/lib/video-recap/skills/video-recap/scripts/project_binding.py +286 -0
  368. package/lib/video-recap/skills/video-recap/scripts/qc/__init__.py +1 -0
  369. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_client.py → qc/mimo_client.py} +1 -1
  370. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_evidence.py → qc/mimo_evidence.py} +33 -66
  371. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_observations.py → qc/mimo_observations.py} +3 -11
  372. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_payload.py → qc/mimo_payload.py} +4 -7
  373. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_report.py → qc/mimo_report.py} +17 -28
  374. package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_runner.py → qc/mimo_runner.py} +2 -2
  375. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +0 -19
  376. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +119 -50
  377. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +32 -114
  378. package/lib/video-recap/skills/video-recap/scripts/recap_review.py +9 -23
  379. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +387 -334
  380. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +23 -23
  381. package/lib/video-recap/skills/video-recap/scripts/recap_source.py +278 -0
  382. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +25 -12
  383. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +59 -52
  384. package/lib/video-recap/skills/video-recap/scripts/resource_lock.py +162 -0
  385. package/lib/video-recap/skills/video-script/SKILL.md +16 -13
  386. package/lib/video-recap/skills/video-script/references/creative-editing-playbook.md +9 -5
  387. package/lib/video-recap/skills/video-script/references/promotional-copy.md +68 -0
  388. package/lib/video-recap/skills/video-script/references/research-guide.md +1 -1
  389. package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +24 -76
  390. package/lib/video-recap/skills/video-script/scripts/lib.py +10 -87
  391. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +63 -39
  392. package/lib/video-recap/skills/video-script/scripts/review.py +0 -2
  393. package/lib/video-recap/skills/video-script/scripts/review_grounding.py +35 -59
  394. package/lib/video-recap/skills/video-script/scripts/review_response.py +66 -128
  395. package/lib/video-recap/skills/video-script/scripts/review_runner.py +12 -20
  396. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +4 -4
  397. package/lib/video-recap/skills/video-script/scripts/validate.py +53 -42
  398. package/lib/video-recap/skills/video-understanding/SKILL.md +6 -4
  399. package/lib/video-recap/skills/video-understanding/references/data-schema.md +50 -156
  400. package/lib/video-recap/skills/video-understanding/references/research-guide.md +4 -4
  401. package/lib/video-recap/skills/video-understanding/scripts/asr.py +85 -65
  402. package/lib/video-recap/skills/video-understanding/scripts/asr_timing_evidence.py +270 -0
  403. package/lib/video-recap/skills/video-understanding/scripts/brief.py +2 -5
  404. package/lib/video-recap/skills/video-understanding/scripts/briefing/__init__.py +1 -0
  405. package/lib/video-recap/skills/video-understanding/scripts/{agent_brief.py → briefing/builder.py} +38 -35
  406. package/lib/video-recap/skills/{video-script/scripts/brief_context.py → video-understanding/scripts/briefing/context.py} +4 -35
  407. package/lib/video-recap/skills/{video-script/scripts/brief_inputs.py → video-understanding/scripts/briefing/inputs.py} +9 -31
  408. package/lib/video-recap/skills/video-understanding/scripts/{brief_timeline.py → briefing/timeline.py} +5 -6
  409. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +65 -116
  410. package/lib/video-recap/skills/video-understanding/scripts/detect.py +31 -40
  411. package/lib/video-recap/skills/video-understanding/scripts/lib.py +30 -86
  412. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +63 -39
  413. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +4 -4
  414. package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +17 -79
  415. package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +14 -40
  416. package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +64 -46
  417. package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +31 -11
  418. package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +19 -14
  419. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +80 -108
  420. package/lib/video-recap/skills/video-voiceover/SKILL.md +29 -19
  421. package/lib/video-recap/skills/video-voiceover/references/index-tts.md +31 -0
  422. package/lib/video-recap/skills/video-voiceover/scripts/approved_text_policy.py +123 -0
  423. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +51 -59
  424. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +8 -44
  425. package/lib/video-recap/skills/video-voiceover/scripts/providers/__init__.py +1 -0
  426. package/lib/video-recap/skills/video-voiceover/scripts/providers/index_tts.py +184 -0
  427. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +212 -134
  428. package/package.json +1 -1
  429. package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +0 -538
  430. package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +0 -603
  431. package/lib/oh-story/skills/story-long-scan/references/scan-output-format.md +0 -207
  432. package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +0 -561
  433. package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +0 -98
  434. package/lib/video-recap/skills/video-recap/references/creative-editing-playbook.md +0 -225
  435. package/lib/video-recap/skills/video-recap/references/research-guide.md +0 -74
  436. package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +0 -250
  437. package/lib/video-recap/skills/video-script/scripts/agent_brief.py +0 -399
  438. package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +0 -327
  439. package/lib/video-recap/skills/video-script/scripts/narration.py +0 -12
  440. package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +0 -348
  441. package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +0 -290
  442. /package/lib/video-recap/skills/video-assemble/scripts/{jianying_tracks.py → jianying/tracks.py} +0 -0
  443. /package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_contract.py → qc/mimo_contract.py} +0 -0
  444. /package/lib/video-recap/skills/video-voiceover/scripts/{fish_audio.py → providers/fish_audio.py} +0 -0
@@ -0,0 +1,195 @@
1
+ # Stage 4:角色、设定与关系
2
+
3
+ Stage 4 时刻读本文件与 [synthesis-inputs.md](synthesis-inputs.md)(取料与事实保真)。
4
+
5
+ ## 核心规则
6
+
7
+ 从 Stage 2 的 `涉及人物`、状态变化和批次关系观察归一实体,再结合 Stage 3 剧情单元生成角色档案与设定。关系记录动作方向、触发、双方得失、表面/真实状态、阶段变化和证据;“甲保护乙”与“乙依赖甲”分别记录。
8
+
9
+ 关系图只从 `角色/角色关系.md` 生成:`"{PYTHON}" "{story-long-analyze skill 根}/scripts/render_relation_chart.py" --root "{拆文目录}" --png`。主产物是 `人物关系图/人物关系图.md`(Mermaid + 文字清单,任何 Markdown 查看器都显示中文);PNG 只在找到能显示图中全部文字的字体时生成(表情等符号不画进图片)。字体不够就不出图,不得自行改画拼音或首字母版,把脚本的 `author_message` 转告作者。
10
+
11
+ 至少一份角色档案和一份设定文件落盘后运行 `manage_analysis_run.py mark-stage --stage stage4`;缺任一类文件时不得标完成。
12
+
13
+ ## 角色过滤来源
14
+
15
+ Stage 4 从紧凑章块的 `涉及人物`、`状态变化` 和批次 `关系变化` 汇总角色提及,再应用下表过滤;不依赖已删除的独立“出场人物表”。
16
+
17
+ | 分类 | 标准 | 提取深度 |
18
+ |------|------|----------|
19
+ | 不提取 | 出场1次且无台词(通用路人) | 跳过 |
20
+ | 简化提取 | 出场2-3次且单一功能 | 功能标签+首次章节 |
21
+ | 完整提取 | 出场3次以上/有台词且推动剧情/与主角直接互动 | 完整档案 |
22
+
23
+ 别名合并:主条目用首次正式名,别名列于 `aliases: []`。
24
+
25
+ ## 角色合并
26
+
27
+ **合并**:
28
+ 1. 收集所有章节的角色提及数据
29
+ 2. 别名匹配(仅 proper_name 和 nickname,置信度 ≥0.85)
30
+ 3. descriptor/title 永不触发合并
31
+ 4. 确认后保留首次正式名
32
+
33
+ ## 角色与设定提取
34
+
35
+ Stage 2 紧凑事实中的 `涉及人物`、`状态变化` 与批次 `关系变化` 在此阶段归一为完整档案。
36
+
37
+ ### 角色两阶段模型
38
+
39
+ **阶段 A:轻量提及(Stage 2 输出)**
40
+ - 每章 `涉及人物` 记录关键人物,`状态变化` 记录本章可见净变化;
41
+ - 批次 `关系变化` 补充有方向的动作、触发与得失;
42
+ - 不另建出场人物表,不在单章内完成跨章人物定型。
43
+
44
+ **阶段 B:完整档案(Stage 4 构建)**
45
+ - 合并逐章 `涉及人物`、`状态变化` 和批次关系观察
46
+ - 跨章节别名解析(批次 `跨批状态` 的「已确认别名」是现成线索)
47
+ - 群体称呼、无名路人和泛称(亲属、社交、身份、年龄外貌类称呼,如大哥、掌柜、老师、小伙子)不建档,除非原文固定用它指代某一个人
48
+ - 构建完整角色档案
49
+
50
+ ### 一人一实体原则
51
+
52
+ - **绝对禁止**将不同人物的信息合并到同一个实体中
53
+ - 每个角色实体必须对应唯一的一个人物
54
+ - 如果无法确定两个称呼是否指向同一人物,必须分开创建实体
55
+
56
+ ### 别名解析规则
57
+
58
+ **别名类型**:
59
+
60
+ | 类型 | 定义 | 可合并 | 示例 |
61
+ |------|------|--------|------|
62
+ | proper_name | 专名/全名/常用名 | 是 | "希尔曼""林雷·巴鲁克" |
63
+ | nickname | 绰号/外号,须有同指证据 | 是(置信度≥0.85) | "龙血战士林雷" |
64
+ | descriptor | 描述性称谓 | 否 | "红发壮汉""随从""队长" |
65
+ | title | 头衔/职务 | 否 | "护卫队长""家主""族长" |
66
+
67
+ **合并约束**:
68
+ - 仅 proper_name 和 nickname(置信度 ≥0.85)可用于合并
69
+ - descriptor 和 title **永不**触发实体合并
70
+ - nickname 须提供同指证据:同位说明、括号别名、上下文指代、明确改名
71
+
72
+ **Archetype 量化判断**:
73
+
74
+ | 类型 | 标准 | 提取深度 |
75
+ |------|------|----------|
76
+ | **主角** | 出现章节 ≥50% 总章节 + 推动主线 + 有完整成长轨迹 | 完整档案+弧线+动机链 |
77
+ | **反派** | 与主角对立 + 推动核心冲突 + 有明确动机 | 完整档案+动机链 |
78
+ | **核心配角** | 出现章节 ≥20% OR 推动重要支线 OR 有独立人格和成长 | 完整档案+关系 |
79
+ | **功能角色** | 出现章节 <20% + 作用有限(提供信息/道具/一次性互动) | 简化档案 |
80
+
81
+ 边界模糊优先归入更低等级。**特殊**:前期 minor 后期 supporting → 判为 supporting。重要导师/伙伴即使出现少也可判为 supporting。
82
+
83
+ **角色档案结构**(200-500字):
84
+ 1. 身份背景(1-2句)
85
+ 2. 核心经历(3-5句,按时序)
86
+ 3. 性格特质(1-2句,从行为归纳)
87
+ 4. 能力特长(1-2句)
88
+ 5. 人际关系(1-2句)
89
+ 6. 成长轨迹(如有,1句)
90
+
91
+ ### 金手指合并规则
92
+
93
+ - 相互关联、共同作用的元素**合并为一个**(如"戒指+导师灵魂"是一个整体)
94
+ - 同一事物的不同描述角度**不拆分**
95
+ - 只有完全独立、互不依赖的能力来源才拆分为多个
96
+ - 长篇特点:金手指可能复杂多样,需详尽描述演化过程和多重能力
97
+ - 无金手指时注明
98
+
99
+ **金手指类型**:system(系统)/ space(空间)/ rebirth(重生)/ transmigration(穿越)/ special_physique(特殊体质)/ artifact(神器)/ bloodline(血脉)/ other(其他)
100
+
101
+ ### 世界观(按主题拆分到多个文件)
102
+
103
+ 字段与落盘位置:
104
+
105
+ | 字段 | 说明 | 落盘文件 |
106
+ |------|------|----------|
107
+ | 类型 | 奇幻/现实/平行世界 | 各文件 frontmatter 或开头注明 |
108
+ | 力量体系 | 名称、等级、晋升方式(文本描述) | `设定/世界观/力量体系.md`(>=200字独立,否则并入 背景设定) |
109
+ | 地理 | 分布、主要区域、关键地点(文本描述) | `设定/世界观/地理.md`(同上,>=200字独立) |
110
+ | 势力 | 门派/组织/家族/国家 | **每个势力一个文件** `设定/势力/{势力名}.md`(>=200字独立;不足合并到 `设定/世界观/背景设定.md`) |
111
+ | 核心规则 | 世界运转的基本规则 | `设定/世界观/背景设定.md` |
112
+ | 特殊设定 | 区别于现实的独特设定 | `设定/世界观/背景设定.md`(与核心规则同文件) |
113
+ | 金手指 | 见上方「金手指合并规则」 | `设定/世界观/金手指.md`(统一在 `设定/世界观/` 子目录下,不放扁平 `设定/金手指.md`) |
114
+
115
+ > 模板见下方「输出模板」。下游导入只原样同步当前主题文件,不再现场拆分扁平文件。
116
+
117
+ ## 人物关系提取
118
+
119
+ 每对关系:
120
+
121
+ | 字段 | 说明 |
122
+ |------|------|
123
+ | 主体 → 客体 | 有向关系;反向动作存在时另记一条 |
124
+ | 关系动作/类型 | 保护、依赖、控制、服从、欺骗、竞争等动作及家人/师徒/朋友/敌人/恋人/同事/上下级/商业/其他类型 |
125
+ | 表面/真实状态 | 文本允许区分时分别记录;未证实的真实状态标推断等级 |
126
+ | 触发事件 | 导致关系建立或变化的具体行动/事件 |
127
+ | 双方得失 | 信任、资源、地位、行动空间、风险、债务、暴露或失控 |
128
+ | 变化后状态 | 本阶段结束时的状态及后续约束 |
129
+ | 证据 | A/B/C 强度、章节、情节点或 source locator |
130
+
131
+ ### 关系提取策略
132
+
133
+ **数据源**:从已提取的情节点描述中提取关系(不从原文提取),更高效、更聚焦。
134
+
135
+ **批量提取**:复用 Stage 2 每个连续章节批次的关系观察,只记录新关系或关系变化;不为了固定章数单独重读原文。
136
+
137
+ **关系演变追踪**:当同一对角色关系发生变化时,记录演变轨迹:
138
+ ```
139
+ 第{N}章:{关系状态A} → 第{M}章:{关系状态B}
140
+ 触发事件:{具体事件}
141
+ 情感转变:{正面→负面/负面→正面/中立→复杂 等}
142
+ ```
143
+
144
+ **最终状态合并**:同一有向关系的多阶段状态保留最新状态作为主记录,历史变化写入演变轨迹。反向关系动作不能因角色对相同而被去重。
145
+
146
+ **隐含关系推断**:当角色间没有直接互动但有间接证据时:
147
+ - 通过第三方的评价/描述推断(置信度标 0.7)
148
+ - 通过共同出现的频率和场合推断(置信度标 0.6)
149
+ - 推断关系标记 `[推断]`,与直接证据关系区分
150
+
151
+ **关系网络密度**:
152
+ - 统计主要角色(主角+核心配角)的关系数量
153
+ - 关系数 < 3 → 关系网偏薄,检查是否有遗漏
154
+ - 关系数 > 10 → 关系网过密,检查是否有误合并
155
+
156
+ ## 输出模板
157
+
158
+ > **Stage 4 直接按主题拆分输出多个文件**(与当前导入、长篇写作项目结构对齐)。下游不再现场拆分扁平文件。
159
+ > **事实保真**:等级/数值/距离/属性/势力数等硬事实回原文核对,原文未给的写「原文未明确」、禁编造填空(见 [synthesis-inputs.md](synthesis-inputs.md)「合成阶段事实保真」)。
160
+
161
+ `设定/世界观/力量体系.md`:
162
+ - 文本描述,含等级、晋升条件。长篇注意多层级力量体系
163
+ - 内容 < 200 字且不构成独立体系 → 合并到 `设定/世界观/背景设定.md`,本文件可省略
164
+
165
+ `设定/世界观/地理.md`:
166
+ - 分布、主要区域、关键地点(文本描述)
167
+ - 内容 < 200 字 → 合并到 `背景设定.md`,本文件可省略
168
+
169
+ `设定/世界观/背景设定.md`:
170
+ - 核心规则 + 特殊设定
171
+ - 内容不足独立成文件的「力量体系 / 地理 / 势力」也合并到这里
172
+ - 无特殊世界观时:本文件输出 "本书为现实题材,无特殊世界观设定"
173
+
174
+ `设定/世界观/金手指.md`:
175
+ - 类型{system/space/rebirth/transmigration/special_physique/artifact/bloodline/other} | 名称 | 描述(300-600字,含能力/获取/机制/进化史/多重能力演化)| 核心机制 | 当前能力
176
+ - 合并规则见上方「金手指合并规则」。
177
+ - 无金手指时:输出空文件,注明"本书无明显金手指设定"
178
+
179
+ `设定/势力/{势力名}.md`(每个核心势力一个文件):
180
+ - 名称 / 类型(门派/组织/家族/国家)/ 核心人物 / 立场倾向 / 与其他势力关系 / 关键事件
181
+ - 内容 >= 200 字时独立;不足合并到 `设定/世界观/背景设定.md`(不丢失信息)
182
+
183
+ `角色/{角色名}.md`(每角色):
184
+ - 200-500字档案(身份背景→核心经历→性格特质→能力特长→人际关系→成长轨迹)
185
+ - archetype:protagonist/antagonist/supporting/minor
186
+ - 关键情节(3-5个转折点,按时序排列)
187
+ - 成长弧线(character_arc:如有明显变化则总结,如"从普通少年成长为觉醒血脉的强者")
188
+ - 别名列表(标注类型和置信度)
189
+
190
+ `角色/角色关系.md` 从逐章事实和批次观察聚合,不重新读整本原文:
191
+
192
+ | 关系ID | 主体 → 客体 | 关系动作/类型 | 表面关系 | 真实关系 | 触发事件 | 双方得失 | 变化后状态 | 证据强度 | 证据 |
193
+ |---|---|---|---|---|---|---|---|---|---|
194
+
195
+ 同一对角色的最新状态和历史演变都保留;“甲保护乙”与“乙依赖甲”分别记录。关系图只由此文件生成,不手画、不另建关系事实,命令见上方「核心规则」。它总是写出 `人物关系图/人物关系图.md`(Mermaid 图 + 文字清单,任何 Markdown 查看器都显示中文,作为主产物);只有装了 matplotlib 且找到能显示图中全部文字的字体(不算 LastResort 这类只画方框的兜底字体)时,才另画 `核心人物关系.png` 与 `关键关系演变.png`,表情等符号不画进图片。字体不够就不出图,绝不改用拼音或首字母,并把脚本返回的说明转告作者。
@@ -0,0 +1,33 @@
1
+ # Stage 5:主报告与完整概要
2
+
3
+ Stage 5 时刻读本文件与 [synthesis-inputs.md](synthesis-inputs.md)。`拆文报告.md` 的模板与写法在 [author-facing.md](author-facing.md)「拆文报告.md」。
4
+
5
+ ## 备份与标记
6
+
7
+ 生成新的 `拆文报告.md` 前先执行:
8
+
9
+ ```text
10
+ "{PYTHON}" "{story-long-analyze skill 根}/scripts/manage_analysis_run.py" mark-stage --root "{拆文目录}" --stage stage5 --prepare
11
+ ```
12
+
13
+ 若旧报告存在,命令会完整复制到 `_analysis_cache/legacy/拆文报告.md`;已存在的首份备份不覆盖。当前旧报告与首份备份不同时,另存一份带内容 hash 的历史备份。其他旧产物与已有摘要不得覆盖。新报告落盘后再用不带 `--prepare` 的 `mark-stage` 标记完成。
14
+
15
+ ## 完整概要
16
+
17
+ 整体故事框架识别 + 500-1000字高密度全书概要(涵盖主要剧情线阶段性发展、核心人物作用、关键转折点、因果关系)。
18
+
19
+ > **怎么来**:Stage 5 从已落盘的 `剧情/故事线.md`(含故事框架识别)与各剧情单元文件自行生成概要,写入 `概要.md`,不等前面时刻交来文本。覆盖 Stage 0 的 thin first-pass 段,章节索引和卷段表保留。
20
+
21
+ ## 报告写法
22
+
23
+ 输出 `拆文报告.md`,模板与写法规则见 [author-facing.md](author-facing.md)「拆文报告.md」。它是 `快速预览.md` 的超集(「基本信息」「黄金三章评分」两节同名同结构),面向作者阅读:不出现脚本名、字段名、状态值、批次编号、质量指标名和证据分级字母;情绪模块卡、事件、披露、节奏节点的编号只在带名称时出现(如「退婚当众打脸」(EM-003)),关系写成「甲 → 乙:由……到……」。
24
+
25
+ 报告只综合权威底层结果,不为写总报告重新阅读全文,也不复制所有逐章摘要。每条结论写一句人话,再指向对应文件和章节;机械可追溯信息(`source_locator`、证据强度、`EV/RV/AX/EM` 全量编号)留在 `剧情/节奏.md`、`剧情/情绪模块.md`、剧情单元和 `角色/角色关系.md` 里。
26
+
27
+ ### 三层灵感库最小消费契约
28
+
29
+ - 单书案例以 `剧情/*.md` 的剧情单元为准,可迁移机制以 `剧情/情绪模块.md` 的 `EM-*` 为准;主报告是阅读入口,不作为第二份结构化真源。
30
+ - 客观事件、披露节点和三维节奏分别使用 `EV-*`、`RV-*`、`AX-*`;披露必须引用事件;机制卡通过 ID 引用,报告只用「名称(ID)」的带名引用,避免跨层复制全文。
31
+ - 每条可检索结论保留剧情单元/章节、`source_locator` 或定位词及证据强度;`chapter_index.csv` 的逐章 hash 和 `_progress.md` 批次范围 hash 用于判断原文范围是否变化。
32
+ - 下游先运行兼容检查器读取 `classification`、`current_capabilities`、`conflicts` 和覆盖范围。缺项时请求长篇拆文的定点增强;不得把旧资料概括成伪造的当前主产物,也不得为入库重新阅读全文。
33
+ - 是否进入灵感库、跨书归并、差异保留和检索策略由三层灵感库能力决定;单书拆文不自动入库。
@@ -50,6 +50,23 @@
50
50
  - 每项标 `high / med / low` 置信度及来源路径;
51
51
  - 原文锚点 4–6 段,每段标章节、行号、基调和示范点。
52
52
 
53
+ ## 字段速查
54
+
55
+ 完整模板见 [style-profile-protocol.md](style-profile-protocol.md)。
56
+
57
+ | 段落 | 内容 | 必标可信度 | 上限 |
58
+ |---|---|---|---|
59
+ | 生成记录 | 参考了哪些资料 + 抽样看了哪几章 + 文风是否可用 | 否 | <100 字 |
60
+ | 整体语感 | 句长分布 / 标点习惯 / 段落节奏 | 是(每子项一标) | ~500 字 |
61
+ | 对话技法 | 潜台词模式 / 对话标签 / 角色语气区分 | 是(潜台词必标) | ~400 字 |
62
+ | 情绪交替模式 | 章内基调切换 / 跨章基调周期 / 喜剧↔重击转场 | 是(章内切换必标) | ~400 字 |
63
+ | 可借鉴技巧 | 写法技巧 Top 5 + 可借鉴套路 Top 3(从拆文报告引用;情绪/节奏意图只引用 `剧情/情绪模块.md` / `剧情/节奏.md`,不在文风中重定义) | 否 | ~300 字 |
64
+ | 分层模仿建议 | 基础层 / 进阶层 / 适配层,各写可执行边界 | 否 | ~350 字 |
65
+ | **原文锚点片段** | **4-6 段 × 300-500 字**,按基调分类,标"出处 + 行号 + 示范点" | 否 | ~2400 字 |
66
+ | 不可模仿 | 对标书缺陷或不适合本项目的技法 | 否 | <100 字 |
67
+
68
+ **总上限 ~4000 字**。
69
+
53
70
  ## 质量检查
54
71
 
55
72
  - 每条高置信结论都有资料路径或可核原文锚点;
@@ -128,6 +128,6 @@
128
128
  ## 覆盖与不可模仿原则
129
129
 
130
130
  - **覆盖**:文风优先级排在 Gate D(节奏调整)、Gate B(句式去套路)、标点默认习惯之上——这些 Gate 是去 AI 味的**默认值**,文风有更具体的指令时文风赢。
131
- - **不可覆盖(硬约束)**:banned-words / Gate F 章末禁升华 / 禁止万能/堆叠比喻 / 禁止章末预告 / 字数下限——这些硬约束永远赢,即使文风示范了相反的用法。
131
+ - **不可覆盖**:细纲事件、信息揭露边界、用户字数范围、文件结构。禁用词、结尾、比喻等表达默认值按 style-resolution 的优先级裁决,对标文风低置信时让位给默认值。
132
132
 
133
133
  精确决议表见 `.claude/agents/narrative-writer.md` 的“被调用协议”段。
@@ -0,0 +1,39 @@
1
+ # Stage 3–5:取料与事实保真
2
+
3
+ Stage 3、4、5 各自的时刻都读本文件。
4
+
5
+ ## 取料
6
+
7
+ 不整份 Read 批次缓存(每批约七成是和逐章摘要重复的章节块),改用只读的 `digest` 按需取料,输出是 Markdown:
8
+
9
+ ```text
10
+ "{PYTHON}" "{story-long-analyze skill 根}/scripts/manage_analysis_run.py" digest --root "{拆文目录}" --part observations [--chapters 1-60]
11
+ "{PYTHON}" "{story-long-analyze skill 根}/scripts/manage_analysis_run.py" digest --root "{拆文目录}" --part chapters --chapters 1-60 --fields 三维节奏,涉及,状态变化 --points brief
12
+ ```
13
+
14
+ - `observations`:按章序汇总已提交批次的跨章观察(剧情点、关键事件与披露候选、关系变化、三维峰谷、跨批状态),是 Stage 3–4 的主语料;
15
+ - `chapters`:从逐章摘要抽字段(概要、关键事件、因果、局面结果、涉及、信息变化、状态变化、三维节奏、章尾钩子、证据),`--points brief` 给每点「标题|类型|基调」,`full` 另带白描;
16
+ - 全书放不进一次上下文时按 `--chapters` 分窗口取、分组合并,窗口间只带剧情状态、关键候选与证据引用,不扩写内容;只有关键证据冲突才定点 Read 单章 `章节/第N章_摘要.md`,最多增加一次定点核验;
17
+ - 旧项目没有批次缓存时,直接复用现有剧情、节奏、情绪、关系和逐章资料,不要为了统一格式先把旧摘要重新压缩一遍;证据不足或冲突时标未知或待核;
18
+ - Stage 3–5 不回读原文,也不各自重读同一批原文;Stage 6 可以按索引定点读取 4–6 段文风锚点,但不得重新扫描整本原文。
19
+
20
+ ## 阶段标记
21
+
22
+ Stage 1 黄金三章与快速预览落盘后标 `stage1`;计划不再有批次时标 `stage2`。Stage 3–6 各运行一次。文件成功原子落盘后再标记:
23
+
24
+ ```text
25
+ "{PYTHON}" "{story-long-analyze skill 根}/scripts/manage_analysis_run.py" mark-stage \
26
+ --root "{拆文目录}" --stage stage3 --output "剧情/节奏.md"
27
+ ```
28
+
29
+ 阶段完成只看约定产物存在且进度行完成;没有依赖 hash 或 Stage receipt。`mark-stage` 会按阶段检查:Stage 1 的黄金三章与快速预览、Stage 2 的全部摘要、Stage 3 的情绪模块与节奏、Stage 4 的角色与设定、Stage 5 的报告、Stage 6 的文风。Stage 6 的单独重建见 [style-profile-generator.md](style-profile-generator.md),允许按索引定点读取 4–6 段原文,不重扫全书,也不触发其他阶段。
30
+
31
+ ## 合成阶段事实保真(阶段 3-5:剧情/设定/角色/报告)
32
+
33
+ 阶段 3-5 从章节摘要二次合成,离原文已两跳,最易把「摘要没说的」用合理推断补成「看似坐实的事实」——这是拆文事实错误的最大来源(典型:给「双系魔法师」凭空补第二系、把坐骑等级安到骑手头上、给原文没给的字段编一个数值、把出场区间填成连续跨度含没出场的章)。强模型也照样漂移,因为越远离原文,模型越靠世界知识与"合理性"填空。三条硬约束:
34
+
35
+ 1. **硬事实必须可溯源**:力量等级、数值、距离、属性、势力数量、谁对谁说了什么、角色出场章节——先检查批次证据或已有事实的章节和定位;命中不到就改写为“资料未明确”或删除,不为聚合二次读取原文。
36
+ 2. **缺失写「原文未明确」,禁编造填空**:原文没给的字段,写「原文未明确/节选未涉及」,绝不用近义项、别处的范例或惯例补一个看似合理的值。
37
+ 3. **跨指代不串**:相邻实体的属性不互相挪用——坐骑等级≠骑手等级、A 的台词≠B 的台词、本章统计数字≠相邻章数字。
38
+
39
+ 落盘后做一次**事实可溯源自检**:抽查设定、角色和报告里的硬事实,逐条核对到本次允许使用的证据源。`raw-original` 可按 `source_locator` 机械定位原文,`existing-results` 只能核对计划列出的旧成果文件;旧成果没有的细节改写为「旧资料未提供」或删除,不借核证之名回读已覆盖章节原文。此自检独立于 Stage 3 的质量阈值——阈值查归类质量,它查事实真伪。
@@ -51,6 +51,7 @@ POINT_ALIASES = {"揭示": "信息揭示", "转折": "转折点", "变化": "状
51
51
  "交谈": "对话", "化解": "解决"}
52
52
  MIN_PLOT_POINTS = 10
53
53
  MAX_PLOT_POINTS = 30
54
+ CHARS_PER_FLOOR_POINT = 200
54
55
  MAX_CHAPTERS = 3
55
56
  MAX_CHARS = 25_000
56
57
  # Stage 3-6 each run once over complete Stage 2 output; their rows decide 最终状态.
@@ -260,6 +261,17 @@ def write_state(progress: Path, state: Dict[str, Any]) -> bool:
260
261
  return True
261
262
 
262
263
 
264
+ def min_plot_points(chapter_chars: Optional[int]) -> int:
265
+ """Raw-chapter floor: chars / 200 rounded, at least 1, at most 10 (a ~540-char prologue needs 3)."""
266
+ if chapter_chars is None:
267
+ return MIN_PLOT_POINTS
268
+ return max(1, min(MIN_PLOT_POINTS, (chapter_chars + CHARS_PER_FLOOR_POINT // 2) // CHARS_PER_FLOOR_POINT))
269
+
270
+
271
+ def chars_by_chapter(rows: Optional[Sequence[Dict[str, Any]]]) -> Dict[int, int]:
272
+ return {row["chapter"]: row["char_count"] for row in rows or []}
273
+
274
+
263
275
  def summary_path(root: Path, chapter: int) -> Path:
264
276
  return root / "章节" / ("第%s章_摘要.md" % chapter)
265
277
 
@@ -370,7 +382,7 @@ def add_recoverable_caches(root: Path, state: Dict[str, Any],
370
382
  if input_kind == "raw-original":
371
383
  if rows is None or current_hash != range_sha256(rows, start, end):
372
384
  continue
373
- records = parse_model_output(metadata["model_output"], start, end, input_kind)
385
+ records = parse_model_output(metadata["model_output"], start, end, input_kind, chars_by_chapter(rows))
374
386
  missing = [chapter for chapter in range(start, end + 1) if not summary_path(root, chapter).is_file()]
375
387
  if missing and not all(chapter in records for chapter in missing):
376
388
  continue
@@ -419,6 +431,13 @@ def plan_command(args: argparse.Namespace) -> Dict[str, Any]:
419
431
  reuse_targets = ((semantic - summaries) | invalid_reuse) - raw_targets
420
432
  raw_targets -= cache_covered
421
433
  reuse_targets -= cache_covered
434
+ window = parse_chapter_window(args.chapters)
435
+ if window:
436
+ if window[0] > int(expected):
437
+ raise RunError("invalid_chapter_window", "%s-%s beyond %s chapters" % (window[0], window[1], expected))
438
+ in_window = set(range(window[0], window[1] + 1))
439
+ raw_targets &= in_window
440
+ reuse_targets &= in_window
422
441
  if raw_targets and index_rows is None:
423
442
  raise RunError("chapter_index_required", "raw-original work remains")
424
443
  if index_rows is not None:
@@ -457,6 +476,16 @@ def plan_command(args: argparse.Namespace) -> Dict[str, Any]:
457
476
  selected.append({"input_kind": item["input_kind"], "start": child["end"] + 1, "end": item["end"]})
458
477
  break
459
478
 
479
+ # Handoff = the committed batch that ends nearest before a batch's first chapter.
480
+ committed = [row for row in state["batches"].values() if completed_batch(root, row, index_rows)]
481
+
482
+ def handoff_cache(start: int) -> Optional[str]:
483
+ before = [row for row in committed if row["end"] < start]
484
+ if not before:
485
+ return None
486
+ row = max(before, key=lambda value: (value["end"], value["start"]))
487
+ return row.get("cache") or cache_path(root, row["batch_id"]).relative_to(root).as_posix()
488
+
460
489
  batches = []
461
490
  raw_reads = 0
462
491
  result_reads = 0
@@ -473,12 +502,18 @@ def plan_command(args: argparse.Namespace) -> Dict[str, Any]:
473
502
  else:
474
503
  sources = sorted(set(preferred_paths.get(str(chapter), "") for chapter in range(item["start"], item["end"] + 1)) - {""})
475
504
  result_reads += len(sources)
505
+ chapter_chars = [index_by_chapter[chapter]["char_count"] for chapter in range(item["start"], item["end"] + 1)] \
506
+ if item["input_kind"] == "raw-original" else []
476
507
  batches.append({
477
508
  "batch_id": batch_id, "chapter_range": [item["start"], item["end"]],
478
509
  "input_kind": item["input_kind"], "range_sha256": current_range_hash,
479
510
  "source_files": sources, "cache": "_analysis_cache/批次-%s.md" % batch_id,
480
- "chapter_chars": [index_by_chapter[chapter]["char_count"] for chapter in range(item["start"], item["end"] + 1)]
481
- if item["input_kind"] == "raw-original" else [],
511
+ "chapter_chars": chapter_chars,
512
+ # Reuse gap summaries have no length to scale by: at least one point each.
513
+ "min_plot_points": [min_plot_points(chars) for chars in chapter_chars]
514
+ if chapter_chars else [1] * (item["end"] - item["start"] + 1),
515
+ "input_file": "_analysis_cache/输入-%s.md" % batch_id,
516
+ "handoff_cache": handoff_cache(item["start"]),
482
517
  })
483
518
  required_stages = list(report.get("stage_repairs", []))
484
519
  if batches or recoverable_caches:
@@ -495,6 +530,8 @@ def plan_command(args: argparse.Namespace) -> Dict[str, Any]:
495
530
  "required_stages": required_stages,
496
531
  "state_written": False,
497
532
  }
533
+ if window:
534
+ payload["chapter_window"] = [window[0], window[1]]
498
535
  if args.next is not None:
499
536
  if args.next < 0:
500
537
  raise RunError("invalid_next", str(args.next))
@@ -582,7 +619,8 @@ def parse_plot_points(body: str, chapter: int, minimum: int) -> List[Dict[str, A
582
619
  return points
583
620
 
584
621
 
585
- def parse_model_output(text: str, start: int, end: int, input_kind: str) -> Dict[int, Dict[str, Any]]:
622
+ def parse_model_output(text: str, start: int, end: int, input_kind: str,
623
+ chapter_chars: Optional[Dict[int, int]] = None) -> Dict[int, Dict[str, Any]]:
586
624
  text = normalized(text)
587
625
  if "BATCH_ERROR:" in text:
588
626
  raise RunError("extractor_reported_error", "model returned BATCH_ERROR")
@@ -594,8 +632,6 @@ def parse_model_output(text: str, start: int, end: int, input_kind: str) -> Dict
594
632
  raise RunError("chapter_marker_mismatch", "expected %s; received %s" % (expected_tokens, actual_tokens))
595
633
  if actual_tokens and actual_tokens != expected_tokens:
596
634
  raise RunError("chapter_marker_mismatch", "expected %s; received %s" % (expected_tokens, actual_tokens))
597
- # Projections rebuilt from old results may hold fewer beats than a fresh reading.
598
- minimum = MIN_PLOT_POINTS if input_kind == "raw-original" else 1
599
635
  records = {} # type: Dict[int, Dict[str, Any]]
600
636
  for match in CHAPTER_BLOCK_RE.finditer(text):
601
637
  chapter = int(match.group(1))
@@ -603,6 +639,8 @@ def parse_model_output(text: str, start: int, end: int, input_kind: str) -> Dict
603
639
  if not re.search(r"(?m)^##\s+第%s章(?:\s+.*)?$" % chapter, body):
604
640
  raise RunError("chapter_schema_incomplete", "chapter %s heading missing" % chapter)
605
641
  fields = {name: compact_field(body, name) for name in COMPACT_FIELDS} # type: Dict[str, Any]
642
+ # Raw floor scales with chapter length; projections rebuilt from old results need only one beat.
643
+ minimum = min_plot_points((chapter_chars or {}).get(chapter)) if input_kind == "raw-original" else 1
606
644
  fields["情节点"] = parse_plot_points(body, chapter, minimum)
607
645
  records[chapter] = fields
608
646
  if input_kind == "raw-original" and set(records) != set(range(start, end + 1)):
@@ -706,7 +744,7 @@ def commit_from_cache(root: Path, metadata: Dict[str, Any], cache: Path,
706
744
  raise RunError("range_hash_mismatch", batch_id)
707
745
  else:
708
746
  current_hash = metadata["range_sha256"]
709
- records = parse_model_output(metadata["model_output"], start, end, input_kind)
747
+ records = parse_model_output(metadata["model_output"], start, end, input_kind, chars_by_chapter(index_rows))
710
748
  hashes = {row["chapter"]: row["chapter_sha256"] for row in index_rows or []}
711
749
  created = []
712
750
  kept = []
@@ -741,8 +779,8 @@ def commit_command(args: argparse.Namespace) -> Dict[str, Any]:
741
779
  if end - start + 1 > MAX_CHAPTERS:
742
780
  raise RunError("batch_too_large", "%s exceeds %s chapters" % (args.batch_id, MAX_CHAPTERS))
743
781
  text = args.input.read_text(encoding="utf-8-sig")
744
- records = parse_model_output(text, start, end, input_kind)
745
782
  index_rows = read_index(root, args.index) if input_kind == "raw-original" or (args.index or root / "chapter_index.csv").is_file() else None
783
+ records = parse_model_output(text, start, end, input_kind, chars_by_chapter(index_rows))
746
784
  if input_kind == "raw-original" and end > start:
747
785
  total_chars = sum(row["char_count"] for row in index_rows if start <= row["chapter"] <= end)
748
786
  if total_chars > MAX_CHARS:
@@ -1044,6 +1082,7 @@ def build_parser() -> argparse.ArgumentParser:
1044
1082
  plan.add_argument("--intent", choices=("continue", "enhance"), default="continue")
1045
1083
  plan.add_argument("--next", type=int, metavar="N",
1046
1084
  help="only print the first N batches (0 = counts only); remaining_batches stays total")
1085
+ plan.add_argument("--chapters", help="only plan this chapter window, e.g. 40-80")
1047
1086
  plan.set_defaults(handler=plan_command)
1048
1087
  commit = sub.add_parser("commit", help="validate and atomically commit one batch")
1049
1088
  commit.add_argument("--root", required=True, type=Path)