novel-writer-cli 0.2.1 → 0.5.0

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 (76) hide show
  1. package/README.md +1 -1
  2. package/agents/chapter-writer.md +69 -29
  3. package/agents/character-weaver.md +7 -1
  4. package/agents/plot-architect.md +20 -7
  5. package/agents/quality-judge.md +239 -15
  6. package/agents/style-analyzer.md +14 -8
  7. package/agents/style-refiner.md +48 -25
  8. package/agents/world-builder.md +8 -1
  9. package/dist/__tests__/agent-prompts-anti-ai-upgrade.test.js +311 -0
  10. package/dist/__tests__/agent-prompts-platform-expansion.test.js +33 -0
  11. package/dist/__tests__/anti-ai-infrastructure.test.js +548 -0
  12. package/dist/__tests__/anti-ai-templates.test.js +156 -0
  13. package/dist/__tests__/canon-status-lifecycle.test.js +481 -0
  14. package/dist/__tests__/commit-gate-decision.test.js +65 -0
  15. package/dist/__tests__/commit-prototype-pollution.test.js +1 -1
  16. package/dist/__tests__/excitement-type-annotation.test.js +240 -0
  17. package/dist/__tests__/excitement-type.test.js +21 -0
  18. package/dist/__tests__/gate-decision.test.js +62 -15
  19. package/dist/__tests__/genre-excitement-mapping.test.js +355 -0
  20. package/dist/__tests__/golden-chapter-gates.test.js +79 -0
  21. package/dist/__tests__/golden-chapter-mini-planning.test.js +485 -0
  22. package/dist/__tests__/helpers/quickstart-mini-planning.js +61 -0
  23. package/dist/__tests__/init.test.js +57 -5
  24. package/dist/__tests__/instructions-platform-expansion.test.js +125 -0
  25. package/dist/__tests__/next-step-gate-decision-routing.test.js +98 -0
  26. package/dist/__tests__/orchestrator-state-write-path.test.js +1 -1
  27. package/dist/__tests__/platform-profile.test.js +57 -1
  28. package/dist/__tests__/quickstart-pipeline.test.js +73 -6
  29. package/dist/__tests__/scoring-weights.test.js +193 -0
  30. package/dist/__tests__/steps-id.test.js +2 -0
  31. package/dist/__tests__/validate-quickstart-prereqs.test.js +2 -0
  32. package/dist/advance.js +27 -2
  33. package/dist/anti-ai-context.js +535 -0
  34. package/dist/cli.js +3 -1
  35. package/dist/commit.js +22 -0
  36. package/dist/excitement-type.js +12 -0
  37. package/dist/gate-decision.js +98 -2
  38. package/dist/golden-chapter-gates.js +143 -0
  39. package/dist/init.js +76 -7
  40. package/dist/instructions.js +552 -6
  41. package/dist/next-step.js +124 -88
  42. package/dist/platform-profile.js +20 -8
  43. package/dist/quickstart-mini-planning.js +30 -0
  44. package/dist/scoring-weights.js +38 -3
  45. package/dist/steps.js +1 -1
  46. package/dist/validate.js +293 -214
  47. package/dist/volume-commit.js +271 -5
  48. package/dist/volume-planning.js +78 -3
  49. package/docs/user/README.md +1 -0
  50. package/docs/user/migration-guide.md +166 -0
  51. package/docs/user/novel-cli.md +4 -3
  52. package/docs/user/quick-start.md +354 -57
  53. package/package.json +1 -1
  54. package/schemas/platform-profile.schema.json +2 -2
  55. package/scripts/lint-blacklist.sh +221 -76
  56. package/scripts/lint-structural.sh +538 -0
  57. package/skills/continue/SKILL.md +6 -0
  58. package/skills/continue/references/context-contracts.md +71 -6
  59. package/skills/continue/references/periodic-maintenance.md +12 -1
  60. package/skills/novel-writing/references/quality-rubric.md +79 -26
  61. package/skills/novel-writing/references/style-guide.md +416 -28
  62. package/skills/start/SKILL.md +23 -3
  63. package/skills/start/references/vol-planning.md +12 -3
  64. package/templates/ai-blacklist.json +1275 -54
  65. package/templates/ai-sentence-patterns.json +167 -0
  66. package/templates/brief-template.md +5 -0
  67. package/templates/genre-excitement-map.json +48 -0
  68. package/templates/genre-golden-standards.json +80 -0
  69. package/templates/genre-weight-profiles.json +15 -0
  70. package/templates/golden-chapter-gates.json +230 -0
  71. package/templates/novel-ask/example.question.json +3 -2
  72. package/templates/platform-profile.json +141 -1
  73. package/templates/platforms/fanqie.md +35 -0
  74. package/templates/platforms/jinjiang.md +35 -0
  75. package/templates/platforms/qidian.md +35 -0
  76. package/templates/style-profile-template.json +18 -1
@@ -9,6 +9,11 @@
9
9
  StyleAnalyzer 从用户样本中提取以下可量化特征:
10
10
 
11
11
  - **avg_sentence_length**:平均句长(字数),用于校准生成文本的句式节奏
12
+ - **sentence_length_std_dev**:句长标准差,控制句长波动而不是只看平均值
13
+ - **paragraph_length_cv**:段落长度变异系数,避免整章段落长得像复制粘贴
14
+ - **emotional_volatility**:情感波动性,确保情绪不是单线平推
15
+ - **register_mixing**:语域混合度,保留口语/书面语/方言之间的自然落差
16
+ - **vocabulary_richness**:词汇丰富度,防止高频表达反复回流
12
17
  - **dialogue_ratio**:对话占全文比例,控制叙述与对话的平衡
13
18
  - **rhetoric_preferences**:修辞偏好列表(频率标注),如比喻、排比、短句切换
14
19
  - **forbidden_words**:作者从不使用的词汇(精准收录,不过度泛化)
@@ -44,79 +49,420 @@ StyleAnalyzer 从用户样本中提取以下可量化特征:
44
49
 
45
50
  ## Layer 2: 约束注入(生成层)
46
51
 
47
- ChapterWriter prompt 中注入以下硬约束:
52
+ ChapterWriter prompt 中注入以下约束与目标:
48
53
 
49
54
  ### 2.1 AI 用语黑名单
50
55
 
51
- 从 `ai-blacklist.json` 加载,生成时完全禁止。包含但不限于:
56
+ 从 `ai-blacklist.json` 加载,默认视作高危表达。叙述文默认避免;角色对话若因身份、语气、情境而合理,可按上下文克制保留。重点关注:
52
57
  - 情感描写类:不禁、莫名、油然而生、心中暗道、嘴角微微上扬
53
58
  - 过渡连接类:与此同时、值得一提的是、毫无疑问
54
59
  - 形容夸张类:宛如、恍若、仿佛置身于
60
+ - **"像"字比喻限频**:`像+具体意象`(如"像一把刀""像一根绷紧的弦")≤1/千字;排除非比喻义用法("好像有人来了""像是累了")。详见 `ai-blacklist.json.category_metadata.simile_cliche.like_simile_rule`
61
+ - 叙述连接词:在叙述段落中零容忍,优先用动作、场景切换、信息落差推进
55
62
  - 详见 `${NOVEL_CLI_ROOT}/templates/ai-blacklist.json`
56
63
 
57
64
  ### 2.2 角色语癖
58
65
 
59
- 每个重要角色至少定义 1 个口头禅或说话习惯:
60
- - 口头禅出现频率:每 2-3 次对话出现 1 次(不可每句都加)
66
+ 为重要角色准备可辨识的口头禅或说话习惯:
67
+ - 语癖应反复出现,但频率不规则:有时连续几轮对话都不出现,有时在压力、撒谎、兴奋时突然滑出来
61
68
  - 语癖需符合角色背景(文化人用文言、江湖人用俚语)
62
69
  - 不同角色的语癖必须可区分
63
70
 
64
71
  ### 2.3 反直觉细节
65
72
 
66
- 每章至少 1 处"反直觉"的生活化细节,例如:
73
+ 鼓励在需要打破“完美感”的地方插入反直觉的生活化细节,但不设固定数量。某些章节可以没有,某些章节也会自然冒出几处,例如:
67
74
  - 打斗中途想起锅里还炖着汤
68
75
  - 修炼突破时被蚊子咬了一口
69
76
  - 严肃对话中对方裤子上有个洞
70
77
 
71
- 目的:打破 AI 生成文本的"完美感"和"刻板感"。
78
+ 目的:打破 AI 生成文本的“完美感”和“刻板感”,让人物像活人而不是任务执行器。
72
79
 
73
80
  ### 2.4 场景描写限制
74
81
 
75
82
  - 场景描写最多 2 句,优先用人物动作带出环境
76
83
  - 禁止大段环境白描("空气中弥漫着……远处是……近处有……")
77
- - 好的范例:`他一脚踢开歪斜的门板,霉味扑面——这地方至少荒了三年。`
84
+ - 好的范例:`他一脚踢开歪斜的门板,霉味扑面。这地方荒了好几年。`
78
85
 
79
86
  ### 2.5 句式多样性
80
87
 
81
- - 禁止连续 3 句相同句式(如连续 3 个"他……"开头)
82
- - 长短句交替:2-3 个短句后接 1 个长句,或反之
83
- - 避免排比过度(连续排比 ≤ 3 项)
88
+ - 避免在相邻 5-7 句里出现 3 句以上同句式(如连续以“他……”或“就在这时……”起头)
89
+ - 长短句要形成波动,不要机械轮换:短句可以成组爆发,随后由较长句回收;也可以长句铺陈后突然切成短句
90
+ - 排比通常保持短促、克制,并由动作、对话或信息转折打断;不要连续多段都用同一种排比开头
91
+ - 句首的主语、时间状语、转折词不要连续堆叠成节拍器式节奏
84
92
 
85
93
  ### 2.6 标点符号约束
86
94
 
87
- LLM 对特定标点有系统性过度使用倾向,是最容易被读者感知的 AI 痕迹之一:
95
+ LLM 对特定标点有系统性过度使用倾向,是最容易被读者感知的 AI 痕迹之一。生成阶段先按千字频率把握趋势;进入 §2.10 L6 结构复核时,再用章节/段落上限做硬检查。两套约束发生冲突时,以更严格的一侧为准。
88
96
 
89
- - **破折号(——)限频**:每千字 ≤ 1 处。LLM 极度偏好用破折号做解释性插入、情绪停顿和场景切换,频率远高于人类写手。应改用逗号、句号或重组句式
97
+ - **总体原则**:按千字频率看趋势,不按单章机械卡数。情绪峰值章可以短暂上浮,但不能连续数章都靠同一种标点撑节奏
98
+ - **破折号(——)**:**0 处/千字(零容忍)**。LLM 极度偏好用破折号做解释性插入、情绪停顿和场景切换,是最明显的 AI 写作标志之一。一律改用逗号、句号、省略号或重组句式,不设任何例外
90
99
  - ✗ `他看向远方——那是他曾经的家。` → ✓ `他看向远方。那是他曾经的家。`
91
100
  - ✗ `门开了——是她。` → ✓ `门开了,是她。`
92
101
  - ✗ `一切都结束了——或许吧。` → ✓ `一切都结束了。或许吧。`
93
- - **省略号(……)限频**:每千字 2 处,禁止连续两句以省略号结尾
94
- - **感叹号(!)限频**:每千字 3 处(对话内不计),叙述文中避免连续感叹
102
+ - `他刚想到"也许还能谈"——窗外那声急刹打断了他。` ✓ `他刚想到"也许还能谈"……窗外那声急刹把后半句硬生生掐断。`
103
+ - **省略号(……)**:通常保持在 0-2 处/千字,避免连续两句都靠省略号收尾
104
+ - **感叹号(!)**:通常保持在 0-3 处/千字;对话中可以略宽,但叙述文不要连续感叹
95
105
 
96
106
  ### 2.7 对话与内心活动格式
97
107
 
98
- 人物说话和内心活动统一使用中文双引号(""),格式如下:
108
+ 人物说话和内心活动统一使用中文双引号(“”),格式如下:
99
109
 
100
- - **说话**:`XX说:"我出去了。"``"我出去了。"XX甩手离开。`
101
- - **内心活动**:`XX心想:"关我什么事。"` 或 `XX暗道:"这人不对劲。"`
110
+ - **说话**:`XX说:“我出去了。”``“我出去了。”XX甩手离开。`
111
+ - **内心活动**:`XX心想:“关我什么事。”` 或 `XX暗道:“这人不对劲。”`
102
112
  - **禁止**使用单引号('')、直角引号(「」)、英文引号("")包裹对话和心理活动
103
- - 引号内的句末标点在引号内:`"走吧。"` 而非 `"走吧"。`
113
+ - 引号内的句末标点在引号内:`“走吧。”` 而非 `“走吧”。`
114
+
115
+ ### 2.8 统计分布目标
116
+
117
+ 当 style-profile 有统计字段时,优先贴着目标写;字段为空时,回退到人类写作的通用范围。目标不是“命中一个点”,而是落在合理波动带里。
118
+ > 注:CS-A1 当前将相关统计字段平铺在 `style-profile.json` 顶层,而不是放在嵌套 `statistical` 对象中;以下按已落地字段名引用。`narration_connectors` 暂无独立字段,先用 `writing_directives` + 黑名单类别作为约束锚点。
119
+
120
+ #### 2.8.1 `sentence_length_variance`(句长方差)
121
+
122
+ - 主要读取:`style-profile.json.sentence_length_std_dev`
123
+ - 回退目标:8-18
124
+ - AI 特征:`std_dev < 6`,句子像同一把尺子量出来
125
+ - 写法提醒:把短句用在冲突、判断、动作切换,把长句留给铺陈、迟疑和复盘
126
+
127
+ #### 2.8.2 `paragraph_length_cv`(段落长度变异系数)
128
+
129
+ - 主要读取:`style-profile.json.paragraph_length_cv`
130
+ - 回退目标:0.4-1.2
131
+ - AI 特征:`CV < 0.3`,段落长度过于整齐
132
+ - 写法提醒:让单句段、短段、中段交错出现,不要每段都像同一个模板裁出来。常规章节更常见于 0.4-0.9;悬疑、恐怖或高碎片化场景可以短时上浮到 1.0-1.2,但不宜长期维持。
133
+
134
+ #### 2.8.3 `vocabulary_diversity`(词汇多样性)
135
+
136
+ - 主要读取:`style-profile.json.vocabulary_richness`(当前枚举代理;若后续提供数值型 `vocabulary_diversity_score`,以数值为准)
137
+ - 名称约定:方法论层统一称 `vocabulary_diversity`;当前落地字段仍是 `vocabulary_richness`;Layer 4 保留 `vocabulary_diversity_score` 作为观测指标名
138
+ - 回退目标:`medium`,理想接近 `high`
139
+ - AI 特征:`low`,高频词、同义反复、口头禅式副词持续回流
140
+ - 写法提醒:同一章里避免反复调用同一组“微微/缓缓/显然/实际上”来填充节奏
141
+
142
+ #### 2.8.4 `narration_connectors`(叙述连接词)
143
+
144
+ - 主要锚点:`ai-blacklist.json.categories.narration_connector` + `style-profile.json.writing_directives`
145
+ - 回退目标:叙述段落为 0;一旦命中就应优先改写,不要拿它当推进骨架
146
+ - AI 特征:靠“与此同时/值得一提的是/事实上/总之”串联段落
147
+ - 写法提醒:叙述推进优先用动作、视角切换、信息落差,不要用逻辑连接词搭脚手架
148
+
149
+ #### 2.8.5 `register_mixing`(语域混合)
150
+
151
+ - 主要读取:`style-profile.json.register_mixing`
152
+ - 辅助锚点:`style-profile.json.writing_directives`(用于保留口语/书面语/行话切换的正向提示)
153
+ - 回退目标:`medium`
154
+ - AI 特征:`low`,整章语域平得像统一播音腔
155
+ - 写法提醒:旁白、人物口语、行业黑话、方言滑落可以有轻微落差,但不能全员同声同调
156
+
157
+ #### 2.8.6 `emotional_arc`(情感弧线)
158
+
159
+ - 主要读取:`style-profile.json.emotional_volatility`
160
+ - 回退目标:`medium`
161
+ - AI 特征:`low`,情绪单线推进,没有迟疑、反弹、回收
162
+ - 写法提醒:一章内最好出现情绪转折,不要从头到尾只在一个强度档位匀速滑行
163
+
164
+ | 维度 | style-profile 字段/锚点 | 回退目标 | AI 特征 |
165
+ |------|-------------------------|----------|---------|
166
+ | `sentence_length_variance` | `sentence_length_std_dev` | 8-18 | `< 6`,句长过匀 |
167
+ | `paragraph_length_cv` | `paragraph_length_cv` | 0.4-1.2 | `< 0.3`,段长过匀 |
168
+ | `vocabulary_diversity` | `vocabulary_richness` | `medium`,理想接近 `high` | `low`,高频词回流 |
169
+ | `narration_connectors` | `writing_directives` + `ai-blacklist.narration_connector` | 叙述段落 0 | 连接词串段 |
170
+ | `register_mixing` | `register_mixing` + `writing_directives` | `medium` | `low`,整章播音腔 |
171
+ | `emotional_arc` | `emotional_volatility` | `medium` | `low`,情绪单线平推 |
172
+
173
+ ### 2.9 人性化技法工具箱
174
+
175
+ 不要只会“反直觉细节”这一招。人写作的自然感来自多种技术交替出现,而不是固定配额地刷同一种花样。
176
+
177
+ #### 认知(cognitive)
178
+
179
+ - `thought_interrupt` / 思维中断:角色的思路被外界刺激突然打断,留下不完整心流。例:`他刚想到”也许还能谈”……窗外那声急刹把后半句硬生生掐断。` 使用省略号表达中断,不使用破折号(§2.6 零容忍)。
180
+ - `self_correction` / 自我纠正:角色先说/先想一个版本,再立刻修正。例:`“我不在乎。”她顿了一下,改口,“不对,我只是现在不想在乎。”`
181
+
182
+ #### 感官(sensory)
183
+
184
+ - `sensory_intrusion` / 感官侵入:高压场面里插入刺鼻气味、皮肤疼痒、衣料摩擦等杂讯。例:`他举枪时,鼻腔里忽然钻进一股铁锈味,像旧水管刚被拧开。`
185
+ - `mundane_detail` / 琐碎细节:在大事件里保留无关紧要但真实的小东西。例:`她哭得肩膀发抖,手里却还捏着刚买的两根葱。`
186
+
187
+ #### 语言(linguistic)
188
+
189
+ - `dialect_slip` / 方言滑落:情绪上来时,人物语言从标准表达滑向地域口吻。例:`“你少来这套。”他忍了半句,还是漏出一句,“莫挨老子。”`
190
+ - `incomplete_sentence` / 不完整句:保留被吞掉的句尾和没说完的话。例:`“我本来以为你会……”她没接下去,只把杯子推远了一点。`
191
+ - `rhetorical_question` / 反问:问题不是为了得到答案,而是为了施压、推开或自我确认。例:`“你真觉得我会信?”`
192
+
193
+ #### 情感(emotional)
194
+
195
+ - `stream_of_consciousness` / 意识流片段:短时间内让念头不按逻辑顺序滑动。例:`门还没开,他先想到的是灯没关、药没吃、她是不是又在咳。`
196
+ - `emotional_non_sequitur` / 情感跳跃:人物情绪并不顺着事件线性移动。例:`她明明该怕,偏偏先觉得丢脸。`
197
+ - `contradiction` / 矛盾:同一人物在同一场景里保留相反冲动。例:`他想把真相全说出来,又恨不得她一个字都别问。`
198
+
199
+ #### 结构(structural)
200
+
201
+ - `nested_parenthetical` / 嵌套补充:在主句中插入短促旁注,制造人类说话时的补丁感。例:`他把钥匙塞回去,动作很轻,轻得近乎心虚。`
202
+ - `abrupt_topic_shift` / 突然转题:人物为了逃避、试探或缓冲,突然把话题切到别处。例:`“你昨晚去哪了?”她没答,低头问,“锅里那汤是不是糊了?”`
203
+
204
+ 每章从工具箱中随机采样若干技法使用,不固定数量,不固定组合。不要机械凑满;没有自然落点时,可以不用。
205
+
206
+ | 技法 | 类别 | 中文名 |
207
+ |------|------|--------|
208
+ | `thought_interrupt` | 认知 | 思维中断 |
209
+ | `self_correction` | 认知 | 自我纠正 |
210
+ | `sensory_intrusion` | 感官 | 感官侵入 |
211
+ | `mundane_detail` | 感官 | 琐碎细节 |
212
+ | `dialect_slip` | 语言 | 方言滑落 |
213
+ | `incomplete_sentence` | 语言 | 不完整句 |
214
+ | `rhetorical_question` | 语言 | 反问 |
215
+ | `stream_of_consciousness` | 情感 | 意识流片段 |
216
+ | `emotional_non_sequitur` | 情感 | 情感跳跃 |
217
+ | `contradiction` | 情感 | 矛盾 |
218
+ | `nested_parenthetical` | 结构 | 嵌套补充 |
219
+ | `abrupt_topic_shift` | 结构 | 突然转题 |
220
+
221
+ #### C23 内心活动锚点(与 SP-07 互补)
222
+
223
+ `SP-07` 防的是“直接把情绪名字告诉读者”,`C23` 防的是“高压节点里完全不写角色怎么感受到这件事”。两者一起工作,才不会把正文压成只有动作记录的空壳:
224
+
225
+ - `SP-07` 防止:`她感到一阵愤怒。` `他心中涌起悲伤。`
226
+ - `C23` 防止:角色连着做选择、挨打、得知真相,却只剩“走 / 看 / 说 / 打”的外显动作,没有任何主观感知
227
+
228
+ **纯动作记录流**:连续句子只描述外在可观察行为(走、跑、抬手、开门、说话、挥刀),没有角色的感官侵入、碎片思绪、生理反应、思维中断或自我纠正。此类段落连续 **≤5 句**;若进入第 6 句,必须补入最小必要的主观感知。
229
+
230
+ **关键节点触发**:当章节出现生死抉择、重大取舍、重大信息获知、规则骤变、SP 大量扣除等高压节点时,节点前后 **2-3 句** 内应至少出现一处内心活动锚点。它不是每章固定配额,而是“该有反应的地方不能空”。
231
+
232
+ **口径说明**:ChapterWriter 写作时以“前后 **2-3 句** 内自然落锚”为目标;QualityJudge 以“前后 3 句仍为空”作为扣分阈值,属于评审兜底,不要求额外扩写成长段心理描写。
233
+
234
+ **边界案例**:
235
+
236
+ - **应触发**:角色主动放弃重要道具、盟友或机会,即使不是立刻生死,也会改变后续局势
237
+ - **应触发**:角色听到半真半假、但足以改变下一步判断的重要消息,即便“重大”程度还在发酵
238
+ - **不应触发**:战斗中的单次战术微调(换步、格挡、侧闪)若尚未改变胜负或关系格局,不必每一下都补内心活动
239
+ - **不应触发**:日常对话里获知不影响目标、关系或风险等级的琐碎信息,不必强行补锚点
240
+ - **高速场景写法**:格斗、追逐、逃亡等高肾上腺素场景也不需要长段内省;锚点可以压缩成 1 句最小必要的生理/感官闪念,但不能连续 6 句都只剩动作记录
241
+
242
+ | 合法内心活动 | 非法情绪标签 / 解释型旁白 |
243
+ |--------------|---------------------------|
244
+ | `铁锈味突然顶上来,她这才发现自己把后槽牙咬得发酸。` | `她感到非常紧张。` |
245
+ | `门闩一响,她脑子里先蹦出来的居然是:灯没关。` | `她知道自己其实是在害怕。` |
246
+ | `他想说“算了”,话到舌尖又缩回去,喉咙像卡了砂。` | `他内心充满挣扎。` |
247
+ | `掌心一层薄汗,刀柄差点滑出去。` | `他此刻十分恐惧。` |
248
+
249
+ **与 C12 / C18 的关系**:
250
+
251
+ - `C12 反直觉细节` 提供“人味来源”,可以拿来给关键节点补真实触感
252
+ - `C18 人性化技法抽样` 提供技法池(`sensory_intrusion` / `stream_of_consciousness` / `thought_interrupt` / `self_correction` 等)
253
+ - `C23` 只是触发式底线:有关键节点或动作流超限时必须补;没有自然落点时,仍然不要为了凑“内心戏”硬塞一段解释
254
+
255
+ ### 2.10 六层结构规则
256
+
257
+ #### L1 反模板句式
258
+
259
+ **禁止:**
260
+ - “首先……其次……最后……”三段式总结
261
+ - “一方面……另一方面……”二元对立
262
+ - “不仅……而且……更……”递进堆砌
263
+ - 连续多段都用同样句式开头的排比陈述
264
+
265
+ **替代:**
266
+ - 用场景推进,不用逻辑推进
267
+ - 用对话推进,不用讲义推进
268
+ - 用动作推进,不用摘要推进
269
+
270
+ #### L2 形容词/副词密度控制
271
+
272
+ | 规则 | 默认限制 |
273
+ |------|----------|
274
+ | 每 300 字强调词(极其/非常/十分/无比) | ≤2 |
275
+ | 每 300 字形容词总量 | ≤6 |
276
+ | 连续两个以上形容词修饰同一名词 | 禁止 |
277
+ | “的”字连用(如“XX的XX的XX”) | 连用≤2 |
278
+
279
+ #### L3 四字成语/词组密度控制
280
+
281
+ | 规则 | 默认限制 |
282
+ |------|----------|
283
+ | 每 500 字四字成语/词组 | ≤3 |
284
+ | 连续使用 2 个以上四字词组 | 禁止 |
285
+ | 同一段落四字词组 | ≤2 |
286
+
287
+ 特别注意:四字词组连用是 AI 写作最明显的特征之一。
288
+
289
+ #### L4 对话去 AI 化(语义/语用子层)
290
+
291
+ 每句对话都应当能被解释出一个主要意图:
292
+
293
+ | 意图类型 | 用途示例 |
294
+ |---------|----------|
295
+ | 试探 | “你今天怎么这么安静?” |
296
+ | 回避 | “这事以后再说。” |
297
+ | 施压 | “你确定?再想想。” |
298
+ | 诱导 | “如果是我,我会现在就走。” |
299
+ | 挑衅 | “就你?” |
300
+ | 敷衍 | “嗯,行,知道了。” |
301
+
302
+ **禁止:**
303
+ - 对话里堆“我认为”“我觉得我们应该”这类书面表达(除非角色身份要求)
304
+ - 对话和叙述重复同一信息
305
+ - 所有角色语气、句长、口头禅完全同质化
306
+
307
+ **自测:**去掉对话标签后,能否大致分辨是谁在说话?
308
+
309
+ #### L5 段落结构 `⚙️ 可覆写`
310
+
311
+ | 规则 | 默认值 | 类型覆写参考 |
312
+ |------|--------|--------------|
313
+ | 单句段占比 | 25%-45% | 科幻 15%-30% / 悬疑 20%-35% / 恐怖 30%-50% |
314
+ | 每段字数 | 20-100 字(超过 80 字建议优先考虑拆分) | 科幻可放宽到 120 字 |
315
+ | 连续 3 段以上同句式 | 禁止 | 通用 |
316
+ | 连续 3 段以上相似长度(±10 字) | 需要打散 | 通用 |
317
+
318
+ 节奏口诀:长-短-短-长-短,如呼吸般起伏。
319
+
320
+ #### L6 标点节奏 `⚙️ 可覆写`
321
+
322
+ | 规则 | 默认值 | 类型覆写参考 |
323
+ |------|--------|--------------|
324
+ | 省略号(……)单段频次 | ≤1/段 | 通用 |
325
+ | 省略号(……)章节总量 | ≤5/章 | 悬疑/恐怖可放宽到 ≤8/章 |
326
+ | 感叹号(!)单段频次 | ≤1/段 | 通用 |
327
+ | 感叹号(!) | ≤8/章 | 科幻收紧到 ≤5/章 |
328
+ | 破折号(——) | 0/章(零容忍) | 通用 |
329
+ | 省略号与感叹号同句连用 | 禁止 | 通用 |
330
+ | 问号连用(??)/感叹号连用(!!) | 禁止 | 通用 |
331
+
332
+ #### L7 句式模式检测
333
+
334
+ **检测方式**:LLM 语义理解(非正则),参考 `${NOVEL_CLI_ROOT}/templates/ai-sentence-patterns.json`。
335
+
336
+ 8 种结构级 AI 句式模式:
337
+
338
+ | ID | 名称 | severity | per_chapter_max | 核心特征 |
339
+ |----|------|----------|-----------------|----------|
340
+ | SP-01 | 解释型旁白句 | high | 0 | 作者替人物翻译潜台词 |
341
+ | SP-02 | 模板转折句 | high | 0 | 机械先负后正/先正后负平衡句 |
342
+ | SP-03 | 抽象判词句 | medium | 2 | "那股XX劲""一种XX的感觉" |
343
+ | SP-04 | 管理/项目腔 | medium | 2 | PRD 语气入侵小说 |
344
+ | SP-05 | 重复解释 | high | 0 | 前句暗示 X,后句旁白重述 X |
345
+ | SP-06 | 因果说明句 | medium | 2 | "毕竟""之所以……是因为" |
346
+ | SP-07 | 情绪标签句 | high | 0 | "感到一阵愤怒""心中涌起悲伤" |
347
+ | SP-08 | 全知评论句 | medium | 2 | "他不知道的是""注定不会平静" |
348
+
349
+ - severity=high 的模式:零容忍,命中即修改
350
+ - severity=medium 的模式:每章 ≤2 处,超出必须修改
351
+ - 与 L1-L6 互补:L1-L6 抓文本表面特征,L7 抓结构/语义级模式
352
+
353
+ ### 2.11 类型覆写机制
354
+
355
+ - 覆写来源优先读取 `brief.md` 中显式写出的“类型覆写”说明;若未提供,再回退到 `brief.md` 的题材字段
356
+ - 只要命中类型覆写,类型参数优先于默认值
357
+ - 未列出的题材先使用默认值;当前 v1 只显式覆写科幻、悬疑、恐怖、言情 4 类
358
+
359
+ | 类型 | L5 段落结构覆写 | L6 标点节奏覆写 | 额外说明 |
360
+ |------|-----------------|-----------------|----------|
361
+ | 科幻 | 单句段 15%-30%;单段可放宽到 120 字 | 感叹号 ≤5/章 | `难以形容` / `不可名状` 灰度允许,建议 ≤2/章且尽量补具体感官 |
362
+ | 悬疑 | 单句段 20%-35%;段长上限维持 100 字但更强调断点 | 省略号 ≤8/章 | 优先保留疑点与停顿,不要把信息一次说满 |
363
+ | 恐怖 | 单句段 30%-50% | 省略号 ≤8/章 | 允许更碎的呼吸感,但不能靠标点堆恐惧 |
364
+ | 言情 | 使用默认值 | 使用默认值 | 重心放在语气差异和情感回收,不靠模板抒情 |
365
+
366
+ **注**:破折号零容忍(§2.6 / L6)为全局约束,对所有题材生效,不受类型覆写影响。
367
+
368
+ ### 2.12 润色执行流程
369
+
370
+ > 默认顺序:黑名单扫描 → 结构规则检查 → 抽象转具体 → 节奏朗读测试。
371
+
372
+ #### Step 1:黑名单扫描
373
+
374
+ 对照 §2.1 的重点说明与 `ai-blacklist.json` 的 14 个 categories 逐项扫:总结概括词、枚举模板词、学术腔、叙述连接词、环境套话、叙事填充、机械开合词、段首套话、平滑过渡、情绪套话、表情套话、比喻套话、动作套话、抽象空词。
375
+
376
+ 判断标准:
377
+ - 角色对话中因身份合理使用 → 保留
378
+ - 本章首次出现且没有更自然替代 → 可保留
379
+ - 其他情况 → 替换
380
+
381
+ #### Step 2:结构规则检查
382
+
383
+ 按 §2.10 的 7 层逐项过一遍:
384
+ 1. 有没有模板句式?
385
+ 2. 形容词/副词是否超密度?
386
+ 3. 四字词组是否连用?
387
+ 4. 对话是否有明确意图,去掉标签后能否分辨角色?
388
+ 5. 段落长短是否有交错?
389
+ 6. 标点频率是否开始撑节奏?
390
+ 7. 有没有命中 L7 句式模式(解释型旁白、模板转折、抽象判词、管理腔、重复解释、因果说明、情绪标签、全知评论)?
391
+
392
+ #### Step 3:抽象→具体转换
393
+
394
+ 重点把这些表达翻译成可见动作或可感知细节:
395
+ - `感到XX` → 身体反应、动作、语气变化
396
+ - `非常/极其` → 更具体的程度和后果
397
+ - `难以形容` → 尽量补出几个可感知点
398
+ - 通用比喻 → 换成本书人物和场景会自然想到的专属意象
399
+
400
+ #### Step 4:节奏朗读测试
401
+
402
+ 默读全章,重点查:
403
+ - 有没有连续 3 句以上同节奏?
404
+ - 有没有逻辑连接词堆起来的“讲稿味”?
405
+ - 有没有描写过长、读者会滑过去的段落?
406
+ - 有没有整章几乎只在推进任务,或高压段之间硬切到下一个高压段?
407
+ - 若有,优先在已有段落缝隙补 1 句最小感官 / 环境过渡;若要解决问题必须新增完整功能性停留段(闲聊 / 回忆 / 生活细节),则不要在 StyleRefiner 阶段硬补,应回到 ChapterWriter / QualityJudge 处理
408
+
409
+ ### 2.13 快速检查清单
410
+
411
+ > 时间不够时,先查这 5 项。
412
+
413
+ - [ ] 四字词组:有无连续 2 个以上四字词组?有就拆
414
+ - [ ] 情绪直述:有无“感到XX”“心中涌起XX”?有就改动作或生理反应
415
+ - [ ] 微微系列:有无“微微一笑”“微微皱眉”“微微点头”?有就换具体描写
416
+ - [ ] 缓缓系列:有无“缓缓开口”“缓缓说道”?有就简化或补动作
417
+ - [ ] 标点过度:有无破折号(零容忍,命中即改)?省略号、感叹号是否频率超限?
418
+
419
+ ### 2.14 结构呼吸感
420
+
421
+ **信息效率过高** 是章节级 AI 特征:每个段落都精准服务情节推进,每句对白都像任务分配,没有闲笔、没有喘息、没有让读者消化信息的空白。`C24` 要解决的不是“拖字数”,而是让章节保留必要的停顿与人味。
422
+
423
+ #### 功能性停留
424
+
425
+ 功能性停留 = 不直接服务于主线推进,但能提供氛围、角色层次或阅读缓冲的片段。判断标准:删掉该片段后,本章主线因果链仍然成立,只是少了氛围 / 人味 / 消化空间。
426
+
427
+ | 类型 | 示例作用 | 注意事项 |
428
+ |------|----------|----------|
429
+ | 环境闲描 | 雨声、灯影、屋里的味道、街边噪音 | 仍受 `C13` 约束,单次环境闲描 **≤2 句** |
430
+ | 角色闲聊 | 打趣、抱怨、跑题、自言自语 | 仍要能归到 `C19` 的敷衍 / 短暂避锋式缓冲 / 转移等合法意图;1-2 句是上限,不是目标 |
431
+ | 感官片段 | 冷气钻进领口、手心发黏、鼻腔里的铁锈味 | 可与 `C23` 内心锚点共用,但 `C24` 关注的是结构位置 |
432
+ | 回忆碎片 | 与当前场景有关的半句旧事或条件反射 | 只取一闪而过的关联,不展开成长回顾 |
433
+ | 生活细节 | 哭着还捏着两根葱、说狠话前先扶正碗沿 | 优先使用 `C12` 式反直觉细节,避免套模板 |
434
+
435
+ #### 密度建议
436
+
437
+ - 章节**正文字数**达到 **1000 字以上** 时,优先守住功能性停留总量不超过章节正文字数的 **≤10%**
438
+ - 在该预算内,通常每 **1000-1500 字** 安排一处更短、更轻的功能性停留;若预算与频率冲突,以 `≤10%` 上限为准
439
+ - 高潮战斗 / 追逐 / 对峙章可以减少停留,但高压段结束后最好仍给 1-2 句节奏放缓的过渡
440
+ - 过渡章 / 日常章可以略多,但不要把“呼吸感”写成无效灌水
441
+
442
+ #### 好 / 坏对比
443
+
444
+ **坏例子(信息效率过高)**:角色进门、交代任务、发现线索、立刻转场;对白句句只为推进冲突,没有任何闲笔或缓冲。
445
+
446
+ **好例子(有结构呼吸感)**:推进完任务后,先留一小段雨声、饭菜味或角色一句不合时宜的抱怨,让读者消化,再进入下一个动作节点。
447
+
448
+ #### 与其它约束的关系
449
+
450
+ - `C12 反直觉细节`:提供“停留时写什么”的具体手段
451
+ - `C13 场景描写精简`:环境闲描仍受 2 句限制,不能借 `C24` 大段铺景
452
+ - `C18 人性化技法`:提供微观表达工具,`C24` 决定“哪里值得放慢”
453
+ - `C19 对话意图`:废话不是乱写,仍要落在敷衍 / 短暂避锋式缓冲 / 转移 / 打趣等可辨识意图上;1-2 句是上限,不是目标
104
454
 
105
455
  ## Layer 3: 后处理(StyleRefiner)
106
456
 
107
457
  ### 润色规则
108
458
 
109
- StyleRefiner 对初稿逐项执行:
459
+ StyleRefiner 默认按 §2.12 的四步流程执行,并额外遵守:
110
460
 
111
- 1. **黑名单扫描**:全文搜索 `ai-blacklist.json` 中所有词条
112
- 2. **逐个替换**:命中项替换为风格相符的自然表达,替代词需符合上下文语境
113
- 3. **标点频率修正**:
114
- - 破折号(——)超过 1 处/千字 → 逐个替换为逗号、句号或重组句式
115
- - 省略号(……)超过 2 处/千字 → 削减或改用具体描写
116
- 4. **句式调整**:
117
- - 句长偏离 style-profile 的 avg_sentence_length > 30% 的句子进行拆分或合并
118
- - 相邻 5 句中出现 ≥ 2 个相同句式 → 改写其中 1 句
461
+ 1. **优先修叙述,不乱动角色声线**:角色身份合理的对话表达宁可保留,也不要为了“去 AI”把人说成一个模子
462
+ 2. **结构问题优先于辞藻问题**:先拆模板句式、重复节奏和标点堆砌,再处理词级替换
463
+ 3. **style-profile 对齐**:句长、段长、语域混合、词汇丰富度优先贴近 style-profile;没有字段时退回 §2.8 的通用范围
119
464
  4. **修改量控制**:总修改量 ≤ 原文 15%(字数变化比)
465
+ 5. **结构呼吸感最小修补**:中层只负责检测“信息效率过高”并补 1 句级过渡,不负责新增完整功能性停留段;需要整段闲笔时回到 ChapterWriter
120
466
 
121
467
  ### 不可修改项
122
468
 
@@ -127,7 +473,43 @@ StyleRefiner 对初稿逐项执行:
127
473
 
128
474
  ## Layer 4: 检测度量(QualityJudge)
129
475
 
130
- ### 风格自然度评分标准
476
+ ### 风格自然度三区判定(13 指标)
477
+
478
+ | # | 指标 | green(人类范围) | yellow(边界) | red(AI 特征) |
479
+ |---|------|------------------|----------------|----------------|
480
+ | 1 | `blacklist_hit_rate` | 0-1 次/千字 | 1-3 次/千字 | >3 次/千字 |
481
+ | 2 | `sentence_repetition_rate` | 相邻 5 句中 0-1 个重复句式 | 相邻 5 句中 2 个重复句式 | 相邻 5 句中 ≥3 个重复句式 |
482
+ | 3 | `sentence_length_std_dev` | 8-18,或落在 style-profile 目标附近 | 6-8 或 18-24 | <6(过匀) |
483
+ | 4 | `paragraph_length_cv` | 0.4-1.2,或落在 style-profile 目标附近 | 0.3-0.4 或 1.2-1.5 | <0.3(过匀) |
484
+ | 5 | `vocabulary_diversity_score` | 当前仅有枚举时 `vocabulary_richness=high`;若未来提供数值字段,则 ≥0.45 | 当前仅有枚举时 `medium`;若未来提供数值字段,则 0.35-0.45 | 当前仅有枚举时 `low`;若未来提供数值字段,则 <0.35 |
485
+ | 6 | `narration_connector_count` | 0 | 1 个孤立命中(仍应改写) | ≥2 个,或连续多段靠连接词推进 |
486
+ | 7 | `humanize_technique_variety` | 单章自然出现 ≥1 种不同技法,且无刷项感 | 0,且其余指标未出现 red(不阻断,但提示检查是否过匀) | 0,且同时伴随至少 1 项句式/连接词等其它 red |
487
+ | 8 | `em_dash_count` | 0 | (无 yellow) | >0(零容忍) |
488
+ | 9 | `sentence_pattern_score` | 0 处 high + ≤2 处 medium | >2 处 medium + 0 处 high | ≥1 处 high 命中 |
489
+ | 10 | `simile_density` | ≤1 处/千字 | >1 且 ≤2 处/千字 | >2 处/千字 |
490
+ | 11 | `dialogue_distinguishability` | high(去标签后可辨识) | medium(勉强可辨识) | low(无法辨识) |
491
+ | 12 | `ellipsis_density` | 0-2 处/千字 | >2 且 ≤3 处/千字 | >3 处/千字 |
492
+ | 13 | `exclamation_density` | 0-3 处/千字 | >3 且 ≤5 处/千字 | >5 处/千字 |
493
+
494
+ > `vocabulary_diversity` 是方法名,`vocabulary_richness` 是现行 style-profile 字段,`vocabulary_diversity_score` 是 Layer 4 观测指标名;三者指向同一维度的不同层名。
495
+ > `humanize_technique_variety` 是复合条件指标,也是事后观察指标,不是生成配额;不要为了把分数刷到 green,机械往章节里塞技法。
496
+ > `em_dash_count` 无 yellow 区间:破折号是最明显的 AI 写作标志,只要出现即为 red。
497
+ > `sentence_pattern_score` 聚合自 `sentence_pattern_violations[]`;分项证据仍保留在独立数组中。
498
+ > `simile_density` 仅计 `像+具体意象`(如”像一把刀”),排除非比喻义(”好像有人来了””像是累了”)。
499
+ > `dialogue_distinguishability` 由 LLM 基于”去掉对话标签后,仅凭语气/用词/句式能否分辨说话人”进行估算。
500
+ > green 表示”仍在人类可接受范围”,不等于旧 5 分制的满分;若沿用 Legacy Fallback 或旧 `quality-rubric` 打满分,`blacklist_hit_rate` 仍建议压到 0 次/千字。
501
+
502
+ 建议映射:
503
+ - 全 green → 5 分
504
+ - 1-2 个 yellow,余下为 green → 4 分
505
+ - 3 个及以上 yellow,或恰好 1 个 red → 3 分
506
+ - 2-3 个 red → 2 分
507
+ - 4 个及以上 red → 1 分
508
+ - `structural_rule_violations` 0 条不降分;1-2 条按“额外 +1 个 yellow”处理;3 条及以上按“额外 +1 个 red”处理
509
+
510
+ ### Legacy Fallback:原 4 指标 5 分表
511
+
512
+ 当当前流程只能拿到旧 4 指标时,使用下表作为向后兼容模式:
131
513
 
132
514
  | 分数 | AI 黑名单命中率 | 句式重复率 | 破折号频率 | style-profile 匹配度 |
133
515
  |------|----------------|-----------|-----------|---------------------|
@@ -137,6 +519,12 @@ StyleRefiner 对初稿逐项执行:
137
519
  | 2 | 5-7 次/千字 | ≥ 3/5 句 | 5-6/千字 | 明显偏移 |
138
520
  | 1 | > 7 次/千字 | 频繁重复 | > 6/千字 | 严重偏移 |
139
521
 
522
+ ### 升级提示
523
+
524
+ - 旧项目若还没有新的统计字段,可先继续使用 `vocabulary_richness` 等枚举代理,并在无法取得 13 指标时回退到 7 指标或 Legacy Fallback
525
+ - 回退层级:`13-indicator`(默认)→ `7-indicator`(正文过短或 `ai_sentence_patterns` 缺失时)→ `4-indicator-compat`(正文破损或 style_profile 缺失时)
526
+ - 现有章节不需要立刻整库重评;从下次重跑 StyleAnalyzer、StyleRefiner、QualityJudge 时逐步补齐即可
527
+
140
528
  ### 黑名单维护机制
141
529
 
142
530
  - **初始化**:`${NOVEL_CLI_ROOT}/templates/ai-blacklist.json` 提供 ≥ 30 个常见 AI 高频中文用语
@@ -20,11 +20,26 @@
20
20
 
21
21
  1) 用 AskUserQuestion 询问是否写入平台画像(可选):
22
22
  - `qidian` (Recommended)
23
- - `tomato`
23
+ - `fanqie (番茄)`
24
+ - `jinjiang (晋江)`
24
25
  - 暂不设置(后续可手动补齐 `platform-profile.json`)
25
26
 
26
- 2) 执行初始化:
27
- - `${NOVEL} init --platform <qidian|tomato>` 或
27
+ > 兼容说明:若用户在 free-form 输入里手动填 `tomato`,仍应接受;但不要把它作为可见选项展示。
28
+
29
+ 2) 再询问用户的**预期题材**(仅用于兼容性提醒与后续 `brief.md` 对齐,不阻断 init):
30
+ - `玄幻 (xuanhuan)`
31
+ - `都市 (dushi)`
32
+ - `科幻 (scifi)`
33
+ - `历史 (history)`
34
+ - `悬疑 (suspense)`
35
+ - `言情 (romance)`
36
+
37
+ > 选择后提醒用户:后续填写 `brief.md` 时,`- **题材**:` 字段应与这里保持一致,否则 CLI 无法稳定匹配 `genre_excitement_map` / `genre_golden_standards`。
38
+
39
+ 3) 若可读取到当前项目根目录中的 `genre-golden-standards.json`,或可读取到 CLI 自带的同名模板,且用户选择的 genre + platform 命中 `invalid_combinations`,显示 WARNING,但继续初始化(不阻断);若两处都不可读(例如全新空目录尚未 init),则跳过检查且不提示。
40
+
41
+ 4) 执行初始化:
42
+ - `${NOVEL} init --platform <qidian|fanqie|jinjiang>` 或
28
43
  - `${NOVEL} init`
29
44
 
30
45
  > `init` 只负责创建 `.checkpoint.json` + `staging/**`(以及可选平台模板)。后续所有流程都由 `next/instructions` 驱动。
@@ -38,4 +53,9 @@
38
53
  ## 常见断点策略(建议)
39
54
 
40
55
  - 遇到 `${NOVEL} commit ...`:执行前用 AskUserQuestion 让用户确认(commit 会移动 staging → final);commit 后运行 `${NOVEL} next --json` 继续
56
+ - QUICK_START 顺序固定为 `world → characters → style → f0 → trial → results`;不要跳步,也不要凭经验跳过 `novel validate` / `novel advance`
57
+ - 遇到 `quickstart:f0` / PlotArchitect packet 时,把它当成 `vol-01` 的迷你规划:生成 chapters `1..3` 的 `outline.md`、3 个 L3 契约、`storyline-schedule.json`、`foreshadowing.json`(以及 `new-characters.json`),先写到 `staging/volumes/vol-01/`,经 `novel validate quickstart:f0` 校验后,再由 `novel advance quickstart:f0` 提交到 `volumes/vol-01/`
58
+ - Quick Start resume 语义:`quickstart_phase=style` 的下一步是 `f0`;`quickstart_phase=f0` 且 `volumes/vol-01/` 种子已提交时,下一步是 `trial`
59
+ - 遇到 `quickstart:trial` / `quickstart:results` 且 packet manifest 中存在 `paths.chapter_contract` / `paths.volume_outline` / `paths.volume_foreshadowing` 时,原样透传给 ChapterWriter / QualityJudge;这些都是来自 `volumes/vol-01/` 的黄金三章规划产物。若缺失,则保持 legacy free-writing fallback
60
+ - 遇到 `volume:outline` / PlotArchitect packet 时,若 `packet.manifest.inline.genre_excitement_map` 存在,原样透传给 `plot-architect`;这是 CLI 按 `brief.md` 题材匹配后的 Ch1-3 默认爽点映射,skill 层不要重算或改写
41
61
  - 遇到 `review:*`(卷末回顾):按 packet.next_actions 执行;必要时暂停让用户阅读 `volumes/vol-XX/review.md`
@@ -4,8 +4,9 @@
4
4
 
5
5
  0. 计算本卷规划章节范围(确定性):
6
6
  - `V = current_volume`
7
- - `plan_start = last_completed_chapter + 1`
7
+ - 默认 `plan_start = last_completed_chapter + 1`
8
8
  - `plan_end = V * 30`(每卷 30 章约定;如 `plan_start > plan_end` 视为数据异常,提示用户先修复 `.checkpoint.json`)
9
+ - 若 `V == 1` 且 `volumes/vol-01/chapter-contracts/chapter-001.json`、`chapter-002.json`、`chapter-003.json` 已存在(来自 Quick Start F0),则把它们视为只读 seed:`plan_start = 4`,并记录 `seed_range = [1,3]`
9
10
  - 创建目录(幂等):`mkdir -p staging/volumes/vol-{V:02d}/chapter-contracts`
10
11
  1. 若 `.checkpoint.json.pending_actions` 存在与本卷有关的 `type == "spec_propagation"` 待办(例如世界规则/角色契约变更影响到 `plan_start..plan_end`):
11
12
  - 展示待办摘要(变更项 + 受影响角色/章节契约)
@@ -26,22 +27,29 @@
26
27
  - `characters`:读取 `characters/active/*.md`(以 `<DATA type="character_profile" ...>` 注入)+ `characters/active/*.json`(L2 contracts 结构化 JSON)
27
28
  - `user_direction`:用户额外方向指示(如有)
28
29
  - `prev_chapter_summaries`(首卷替代 `prev_volume_review`):若 `prev_volume_review` 不存在且 `last_completed_chapter > 0`,读取最近 3 章 `summaries/chapter-*-summary.md` 作为上下文(黄金三章是 QUICK_START 多轮交互的核心产出,PlotArchitect 必须基于其已建立的人物关系和情节基调规划后续章节),以 `<DATA type="summary" ...>` 注入
30
+ - 当 `plan_start > 1`(首卷已有 F0 种子)时,额外提供 `existing_volume_outline` / `existing_storyline_schedule` / `existing_foreshadowing` / `existing_chapter_contracts_dir`,并在 inline 中标注 `volume_plan_seed_range=[1,3]`
29
31
  3. 使用 Task 派发 PlotArchitect Agent 生成本卷规划产物(写入 staging 目录,step 6 commit 到正式路径):
30
32
  - `staging/volumes/vol-{V:02d}/outline.md`(严格格式:每章 `###` 区块 + 固定 `- **Key**:` 行)
31
33
  - `staging/volumes/vol-{V:02d}/storyline-schedule.json`
32
34
  - `staging/volumes/vol-{V:02d}/foreshadowing.json`
33
35
  - `staging/volumes/vol-{V:02d}/new-characters.json`(可为空数组)
34
36
  - `staging/volumes/vol-{V:02d}/chapter-contracts/chapter-{C:03d}.json`(`C ∈ [plan_start, plan_end]`)
37
+ - 若已有 `seed_range=[1,3]`:只生成新章节(从 4 开始),不得重写 `chapter-001/002/003.json`
38
+ - commit 合并策略:`storyline-schedule.json` 的 `active_storylines` 去重合并;`foreshadowing.json` 按 `id` 合并并保留既有 `history`;`new-characters.json` 按 `name|first_chapter` 去重
35
39
  - (注意:`foreshadowing/global.json` 为事实索引,由 `/novel:continue` 在每章 commit 阶段从 `foreshadow` ops 更新;卷规划阶段不生成/覆盖 global.json)
36
- 4. 规划产物校验(对 `staging/` 下的产物执行;失败则停止并给出修复建议,禁止"缺文件继续写"导致断链):
40
+ 4. 规划产物校验(对 `staging/` 下的产物执行;失败则停止并给出修复建议,禁止“缺文件继续写”导致断链):
37
41
  - `outline.md` 可解析:可用 `/^### 第 (\\d+) 章/` 找到章节区块,且连续覆盖 `plan_start..plan_end`(不允许跳章,否则下游契约缺失会导致流水线崩溃)
38
42
  - 每个章节区块包含固定 key 行:`Storyline/POV/Location/Conflict/Arc/Foreshadowing/StateChanges/TransitionHint`
43
+ - 兼容旧大纲时,`ExcitementType` 可作为可选第 9 行;新生成的大纲应显式输出该行(无显式爽点写 `null`)
44
+ - 若存在 `ExcitementType`,其值必须是 `reversal | face_slap | power_up | reveal | cliffhanger | setup | null`;未知值仅警告并按 `null` 处理,不阻断流水线
39
45
  - 允许 `TransitionHint` 值为空;但 key 行必须存在(便于机器解析)
40
46
  - `storyline-schedule.json` 可解析(JSON),`active_storylines` ≤ 4,且本卷 `outline.md` 中出现的 `storyline_id` 均属于 `active_storylines`
41
47
  - `chapter-contracts/` 全量存在且可解析(JSON),并满足最小一致性检查:
42
48
  - `chapter == C`
43
49
  - `storyline_id` 与 outline 中 `- **Storyline**:` 一致
50
+ - `excitement_type` 缺失仅警告并按 `null` 处理;若存在未知值同样仅警告,不阻断流水线
44
51
  - `objectives` 至少 1 条 `required: true`
52
+ - 若已有 `seed_range=[1,3]`,则校验范围只覆盖新增章节;`chapter-001/002/003.json` 视为既有只读输入,不应出现在 staging 重写结果中
45
53
  - 链式传递检查(最小实现):若 `chapter-{C-1}.json.postconditions.state_changes` 中出现角色 X,则 `chapter-{C}.json.preconditions.character_states` 必须包含 X(值可不同,代表显式覆盖)。对 `plan_start` 章:若 `chapter-{plan_start-1}.json` 不存在(如首卷试写章无契约),跳过该章的链式传递检查,其 preconditions 由 PlotArchitect 从试写摘要派生
46
54
  - `foreshadowing.json` 与 `new-characters.json` 均存在且为合法 JSON
47
55
  5. 审核点交互(AskUserQuestion):
@@ -54,7 +62,8 @@
54
62
  3) 暂不进入写作(保持 VOL_PLANNING,规划产物保留在 staging 中)
55
63
  6. 若确认进入写作:
56
64
  - commit 规划产物(staging → 正式目录):
57
- - `mv staging/volumes/vol-{V:02d}/* → volumes/vol-{V:02d}/`(幂等覆盖)
65
+ - 常规情况:`mv staging/volumes/vol-{V:02d}/* → volumes/vol-{V:02d}/`
66
+ - 首卷已有 F0 seed 时:`outline.md` 只追加新章节到已有 1-3 章之后;`storyline-schedule.json` / `foreshadowing.json` 做增量合并,保留 F0 的 seed 条目;`chapter-001/002/003.json` 保持只读不覆盖,只复制新章节契约(从 4 开始)
58
67
  - 清空 `staging/volumes/` 和 `staging/foreshadowing/`
59
68
  - 读取 `volumes/vol-{V:02d}/new-characters.json`:
60
69
  - 若非空:批量调用 CharacterWeaver 创建角色档案 + L2 契约(按 `first_chapter` 升序派发 Task,便于先创建早出场角色)