novel-writer-cli 0.3.0 → 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 (75) hide show
  1. package/README.md +1 -1
  2. package/agents/chapter-writer.md +43 -14
  3. package/agents/character-weaver.md +7 -1
  4. package/agents/plot-architect.md +20 -7
  5. package/agents/quality-judge.md +199 -20
  6. package/agents/style-analyzer.md +14 -8
  7. package/agents/style-refiner.md +10 -3
  8. package/agents/world-builder.md +8 -1
  9. package/dist/__tests__/agent-prompts-anti-ai-upgrade.test.js +194 -6
  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 +2 -2
  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 +129 -19
  62. package/skills/start/SKILL.md +23 -3
  63. package/skills/start/references/vol-planning.md +12 -3
  64. package/templates/ai-blacklist.json +1024 -246
  65. package/templates/ai-sentence-patterns.json +167 -0
  66. package/templates/genre-excitement-map.json +48 -0
  67. package/templates/genre-golden-standards.json +80 -0
  68. package/templates/genre-weight-profiles.json +15 -0
  69. package/templates/golden-chapter-gates.json +230 -0
  70. package/templates/novel-ask/example.question.json +3 -2
  71. package/templates/platform-profile.json +141 -1
  72. package/templates/platforms/fanqie.md +35 -0
  73. package/templates/platforms/jinjiang.md +35 -0
  74. package/templates/platforms/qidian.md +35 -0
  75. package/templates/style-profile-template.json +3 -0
@@ -74,6 +74,76 @@
74
74
  },
75
75
  "_comment_naming": "Naming conflict lint (M7): enabled; only exact duplicates are configured as blocking by default."
76
76
  },
77
+ "fanqie": {
78
+ "$schema": "schemas/platform-profile.schema.json",
79
+ "schema_version": 1,
80
+ "platform": "fanqie",
81
+ "created_at": "2026-02-27T00:00:00Z",
82
+ "_comment_created_at": "Init SHOULD overwrite this with the actual creation timestamp.",
83
+ "word_count": {
84
+ "target_min": 1500,
85
+ "target_max": 2500,
86
+ "hard_min": 1000,
87
+ "hard_max": 3500
88
+ },
89
+ "hook_policy": {
90
+ "required": true,
91
+ "min_strength": 3,
92
+ "allowed_types": ["question", "threat_reveal", "twist_reveal", "emotional_cliff", "next_objective"],
93
+ "fix_strategy": "hook-fix"
94
+ },
95
+ "info_load": {
96
+ "max_new_entities_per_chapter": 5,
97
+ "max_unknown_entities_per_chapter": 3,
98
+ "max_new_terms_per_1k_words": 5
99
+ },
100
+ "compliance": {
101
+ "banned_words": [],
102
+ "duplicate_name_policy": "soft",
103
+ "script_paths": {
104
+ "lint_blacklist": "scripts/lint-blacklist.sh",
105
+ "lint_cliche": "scripts/lint-cliche.sh"
106
+ }
107
+ },
108
+ "scoring": {
109
+ "genre_drive_type": "plot",
110
+ "weight_profile_id": "plot:v1"
111
+ },
112
+ "retention": {
113
+ "title_policy": {
114
+ "enabled": true,
115
+ "min_chars": 2,
116
+ "max_chars": 30,
117
+ "forbidden_patterns": ["^\\s*$", "^(?:无题|未命名|待定)$"],
118
+ "auto_fix": false
119
+ },
120
+ "hook_ledger": {
121
+ "enabled": true,
122
+ "fulfillment_window_chapters": 10,
123
+ "diversity_window_chapters": 5,
124
+ "max_same_type_streak": 2,
125
+ "min_distinct_types_in_window": 2,
126
+ "overdue_policy": "warn"
127
+ }
128
+ },
129
+ "_comment_retention": "Retention guardrails (M7): fanqie keeps the shorter-window mobile-reading defaults used by the legacy tomato profile.",
130
+ "readability": {
131
+ "mobile": {
132
+ "enabled": true,
133
+ "max_paragraph_chars": 300,
134
+ "max_consecutive_exposition_paragraphs": 3,
135
+ "blocking_severity": "hard_only"
136
+ }
137
+ },
138
+ "_comment_readability": "Mobile readability lint (M7): enabled, but only hard issues are allowed to block when implemented.",
139
+ "naming": {
140
+ "enabled": true,
141
+ "near_duplicate_threshold": 0.88,
142
+ "blocking_conflict_types": ["duplicate"],
143
+ "exemptions": {}
144
+ },
145
+ "_comment_naming": "Naming conflict lint (M7): enabled; only exact duplicates are configured as blocking by default."
146
+ },
77
147
  "tomato": {
78
148
  "$schema": "schemas/platform-profile.schema.json",
79
149
  "schema_version": 1,
@@ -126,7 +196,7 @@
126
196
  "overdue_policy": "warn"
127
197
  }
128
198
  },
129
- "_comment_retention": "Retention guardrails (M7): tomato tends to favor shorter windows; defaults are enabled; enforcement/blocking is implemented in later pipeline steps (hook_ledger.overdue_policy defaults to warn).",
199
+ "_comment_retention": "Retention guardrails (M7): legacy tomato profile remains for backward compatibility; canonical internal behavior maps to fanqie.",
130
200
  "readability": {
131
201
  "mobile": {
132
202
  "enabled": true,
@@ -143,6 +213,76 @@
143
213
  "exemptions": {}
144
214
  },
145
215
  "_comment_naming": "Naming conflict lint (M7): enabled; only exact duplicates are configured as blocking by default."
216
+ },
217
+ "jinjiang": {
218
+ "$schema": "schemas/platform-profile.schema.json",
219
+ "schema_version": 1,
220
+ "platform": "jinjiang",
221
+ "created_at": "2026-02-27T00:00:00Z",
222
+ "_comment_created_at": "Init SHOULD overwrite this with the actual creation timestamp.",
223
+ "word_count": {
224
+ "target_min": 2000,
225
+ "target_max": 3000,
226
+ "hard_min": 1500,
227
+ "hard_max": 3800
228
+ },
229
+ "hook_policy": {
230
+ "required": true,
231
+ "min_strength": 3,
232
+ "allowed_types": ["emotional_cliff", "question", "next_objective"],
233
+ "fix_strategy": "hook-fix"
234
+ },
235
+ "info_load": {
236
+ "max_new_entities_per_chapter": 4,
237
+ "max_unknown_entities_per_chapter": 2,
238
+ "max_new_terms_per_1k_words": 4
239
+ },
240
+ "compliance": {
241
+ "banned_words": [],
242
+ "duplicate_name_policy": "soft",
243
+ "script_paths": {
244
+ "lint_blacklist": "scripts/lint-blacklist.sh",
245
+ "lint_cliche": "scripts/lint-cliche.sh"
246
+ }
247
+ },
248
+ "scoring": {
249
+ "genre_drive_type": "character",
250
+ "weight_profile_id": "character:v1"
251
+ },
252
+ "retention": {
253
+ "title_policy": {
254
+ "enabled": true,
255
+ "min_chars": 2,
256
+ "max_chars": 28,
257
+ "forbidden_patterns": ["^\\s*$", "^(?:无题|未命名|待定)$"],
258
+ "auto_fix": false
259
+ },
260
+ "hook_ledger": {
261
+ "enabled": true,
262
+ "fulfillment_window_chapters": 8,
263
+ "diversity_window_chapters": 5,
264
+ "max_same_type_streak": 2,
265
+ "min_distinct_types_in_window": 2,
266
+ "overdue_policy": "warn"
267
+ }
268
+ },
269
+ "_comment_retention": "Retention guardrails (M7): jinjiang defaults bias toward shorter emotional payoff windows and subtler hook variety.",
270
+ "readability": {
271
+ "mobile": {
272
+ "enabled": true,
273
+ "max_paragraph_chars": 340,
274
+ "max_consecutive_exposition_paragraphs": 3,
275
+ "blocking_severity": "hard_only"
276
+ }
277
+ },
278
+ "_comment_readability": "Mobile readability lint (M7): enabled, but only hard issues are allowed to block when implemented.",
279
+ "naming": {
280
+ "enabled": true,
281
+ "near_duplicate_threshold": 0.88,
282
+ "blocking_conflict_types": ["duplicate"],
283
+ "exemptions": {}
284
+ },
285
+ "_comment_naming": "Naming conflict lint (M7): enabled; only exact duplicates are configured as blocking by default."
146
286
  }
147
287
  }
148
288
  }
@@ -0,0 +1,35 @@
1
+ # 番茄平台写作指南
2
+
3
+ ## 定位
4
+
5
+ 番茄读者要的是“很快就爽、很快就懂、很快就想追下一章”。单章允许信息密度高,但不接受长时间铺垫后才给反馈。
6
+
7
+ ## 节奏密度
8
+
9
+ - 每章至少要有 1 个明确推进点:危机、反击、收益、反转,四者至少命中其一
10
+ - 铺设背景时,必须夹在动作、对话或冲突里,不要独立拉出大段设定说明
11
+ - 前三章尤其要快:主角尽早出场,冲突尽早落地,奖励或威胁尽早给到
12
+
13
+ ## 对话比例
14
+
15
+ - 目标对话占比约 40%–50%
16
+ - 角色对白要直接推动冲突、试探和立场碰撞,不要让对白只做解释
17
+ - 场景转换尽量用人物行动和对白带过去,而不是纯叙述概括
18
+
19
+ ## 章末钩子
20
+
21
+ - 每章末尾都应留下明确追读理由:威胁升级、打脸前夜、反转揭晓前一拍、下一目标承诺
22
+ - 钩子要落在最后 1–2 段,避免“收尾完了再补一句悬念”
23
+ - 禁止作者式预告,钩子必须来自剧情本身
24
+
25
+ ## 情绪回报节奏
26
+
27
+ - 情绪铺设到回报,优先控制在 2–3 章内
28
+ - 不要把压抑、憋屈、误会拖太久;若本章压住读者情绪,下 1–2 章必须给反弹
29
+ - 爽点最好是可描述、可复述、可截图传播的
30
+
31
+ ## 风格要求
32
+
33
+ - 语言尽量干净直接,句子以推进为先
34
+ - 设置描写要“嵌在动作里”,不要独立写成环境展示段
35
+ - 主角视角要有存在感:选择、判断、反击意图必须清晰
@@ -0,0 +1,35 @@
1
+ # 晋江平台写作指南
2
+
3
+ ## 定位
4
+
5
+ 晋江读者首先看人物关系张力,其次才看外部事件。开篇可以不追求大爆点,但必须尽快让人物气质、关系方向和情绪基调站住。
6
+
7
+ ## 节奏密度
8
+
9
+ - 以角色驱动为主:每章都要让人物关系、情绪温度或立场碰撞发生变化
10
+ - 外部情节服务人物,而不是盖过人物
11
+ - 前三章要尽快让读者知道“谁和谁最重要、为什么会在意他们”
12
+
13
+ ## 对话比例
14
+
15
+ - 对话比例没有硬指标,但对白必须承担关系推进和个性呈现
16
+ - 角色个性优先通过动作、反应、措辞体现,不要靠旁白直接下定义
17
+ - 情绪变化要落在细节里:停顿、错位反应、避重就轻、试探、反讽,都比“他很在意/她很难过”更有效
18
+
19
+ ## 章末钩子
20
+
21
+ - 优先使用情绪钩子和关系钩子,而不是单纯外部事件钩子
22
+ - 章末可以留下误会升级、关系倒挂、情绪失衡、下一次碰撞的期待
23
+ - 如果使用情节钩子,也要让它同时牵动人物关系
24
+
25
+ ## 情绪回报节奏
26
+
27
+ - 情绪铺垫到第一次回报,尽量控制在 2–4 章
28
+ - CP 或核心关系对象应尽早出现并建立存在感,不要长期只靠提及
29
+ - 角色之间要尽快形成可感知的化学反应:吸引、对抗、拉扯、互补,至少有一种
30
+
31
+ ## 风格要求
32
+
33
+ - style_naturalness 要高:人物说话像人,不像立场说明器
34
+ - 文风可以精致,但不能生硬;句子要贴着人物情绪走
35
+ - 关系戏要靠具体行为、具体场面、具体反应成立,避免空泛抒情
@@ -0,0 +1,35 @@
1
+ # 起点平台写作指南
2
+
3
+ ## 定位
4
+
5
+ 起点读者接受稍慢一拍的展开,但前提是“有代入、有世界、有承诺”。设定可以多一点,节奏可以稳一点,但不能空。
6
+
7
+ ## 节奏密度
8
+
9
+ - 单章维持中速推进:既要有事件推进,也要有世界或系统信息增量
10
+ - 允许系统、规则、势力、职业、修炼体系等搭建,但每次搭建都要服务当前冲突或目标
11
+ - 如果本章主要承担铺设功能,也要给读者一个明确的主线抓手
12
+
13
+ ## 对话比例
14
+
15
+ - 目标对话占比约 30%–40%
16
+ - 对话主要承担立场碰撞、信息揭露和人物关系确认,不必追求高密度
17
+ - 叙述可以稍多,但要保证读者始终能“看到场景、理解规则、跟住主角判断”
18
+
19
+ ## 章末钩子
20
+
21
+ - 起点钩子优先是“下一步会发生什么”和“更大的世界差异点是什么”
22
+ - 系统提示、势力动向、隐藏规则、升级门槛、敌人反制,都适合作为章末承诺
23
+ - 钩子不一定特别炸,但必须让读者清楚下一章值得继续看
24
+
25
+ ## 情绪回报节奏
26
+
27
+ - 情绪和世界观回报可以比番茄稍长,但最好 3–5 章内有一次清晰兑现
28
+ - 若前文压了规则、谜团或成长线,本卷前段必须尽快给一次验证
29
+ - 不要让主角长期只在“观察”和“理解”,缺少行动反馈
30
+
31
+ ## 风格要求
32
+
33
+ - 沉浸感优先:世界运行逻辑、场景细节、主角判断链要让人信服
34
+ - 设定表达要和事件推进绑在一起,避免百科式说明
35
+ - 允许系统搭建和术语,但每章都要让读者感到“这套设定正在推动故事”
@@ -7,6 +7,9 @@
7
7
  "reference_author": null,
8
8
  "_reference_author_comment": "仿写模式时填写参考作者名,原创模式为 null",
9
9
 
10
+ "platform": null,
11
+ "_platform_comment": "平台绑定(qidian|tomato|fanqie|jinjiang);init 时若已选择平台则自动填充,未选择时保持 null",
12
+
10
13
  "avg_sentence_length": null,
11
14
  "_avg_sentence_length_comment": "平均句长(字数),如 18 表示平均每句 18 字",
12
15