novel-writer-cli 0.0.1
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.
- package/LICENSE +21 -0
- package/README.md +103 -0
- package/agents/chapter-writer.md +142 -0
- package/agents/character-weaver.md +117 -0
- package/agents/consistency-auditor.md +85 -0
- package/agents/plot-architect.md +128 -0
- package/agents/quality-judge.md +232 -0
- package/agents/style-analyzer.md +109 -0
- package/agents/style-refiner.md +97 -0
- package/agents/summarizer.md +128 -0
- package/agents/world-builder.md +161 -0
- package/dist/__tests__/character-voice.test.js +445 -0
- package/dist/__tests__/commit-prototype-pollution.test.js +45 -0
- package/dist/__tests__/engagement.test.js +382 -0
- package/dist/__tests__/foreshadow-visibility.test.js +131 -0
- package/dist/__tests__/hook-ledger.test.js +1028 -0
- package/dist/__tests__/naming-lint.test.js +132 -0
- package/dist/__tests__/narrative-health-injection.test.js +359 -0
- package/dist/__tests__/next-step-prejudge-guardrails.test.js +325 -0
- package/dist/__tests__/next-step-title-fix.test.js +153 -0
- package/dist/__tests__/platform-profile.test.js +274 -0
- package/dist/__tests__/promise-ledger.test.js +189 -0
- package/dist/__tests__/readability-lint.test.js +209 -0
- package/dist/__tests__/text-utils.test.js +39 -0
- package/dist/__tests__/title-policy.test.js +147 -0
- package/dist/advance.js +75 -0
- package/dist/character-voice.js +805 -0
- package/dist/checkpoint.js +126 -0
- package/dist/cli.js +563 -0
- package/dist/cliche-lint.js +515 -0
- package/dist/commit.js +1460 -0
- package/dist/consistency-auditor.js +684 -0
- package/dist/engagement.js +687 -0
- package/dist/errors.js +7 -0
- package/dist/fingerprint.js +16 -0
- package/dist/foreshadow-visibility.js +214 -0
- package/dist/fs-utils.js +68 -0
- package/dist/hook-ledger.js +721 -0
- package/dist/hook-policy.js +107 -0
- package/dist/instruction-gates.js +51 -0
- package/dist/instructions.js +406 -0
- package/dist/latest-summary-loader.js +29 -0
- package/dist/lock.js +121 -0
- package/dist/naming-lint.js +531 -0
- package/dist/ner.js +73 -0
- package/dist/next-step.js +408 -0
- package/dist/novel-ask.js +270 -0
- package/dist/output.js +9 -0
- package/dist/platform-constraints.js +518 -0
- package/dist/platform-profile.js +325 -0
- package/dist/prejudge-guardrails.js +370 -0
- package/dist/project.js +40 -0
- package/dist/promise-ledger.js +723 -0
- package/dist/readability-lint.js +555 -0
- package/dist/safe-parse.js +36 -0
- package/dist/safe-path.js +29 -0
- package/dist/scoring-weights.js +290 -0
- package/dist/steps.js +60 -0
- package/dist/text-utils.js +18 -0
- package/dist/title-policy.js +251 -0
- package/dist/type-guards.js +6 -0
- package/dist/validate.js +131 -0
- package/docs/user/README.md +17 -0
- package/docs/user/guardrails.md +179 -0
- package/docs/user/interactive-gates.md +124 -0
- package/docs/user/novel-cli.md +289 -0
- package/docs/user/ops.md +123 -0
- package/docs/user/quick-start.md +97 -0
- package/docs/user/spec-system.md +166 -0
- package/docs/user/storylines.md +144 -0
- package/package.json +48 -0
- package/schemas/README.md +18 -0
- package/schemas/character-voice-drift.schema.json +135 -0
- package/schemas/character-voice-profiles.schema.json +141 -0
- package/schemas/engagement-metrics.schema.json +38 -0
- package/schemas/hook-ledger.schema.json +108 -0
- package/schemas/platform-profile.schema.json +235 -0
- package/schemas/promise-ledger.schema.json +97 -0
- package/scripts/calibrate-quality-judge.sh +91 -0
- package/scripts/compare-regression-runs.sh +86 -0
- package/scripts/lib/_common.py +131 -0
- package/scripts/lib/calibrate_quality_judge.py +312 -0
- package/scripts/lib/compare_regression_runs.py +142 -0
- package/scripts/lib/run_regression.py +621 -0
- package/scripts/lint-blacklist.sh +201 -0
- package/scripts/lint-cliche.sh +370 -0
- package/scripts/lint-readability.sh +404 -0
- package/scripts/query-foreshadow.sh +252 -0
- package/scripts/run-ner.sh +669 -0
- package/scripts/run-regression.sh +122 -0
- package/skills/cli-step/SKILL.md +158 -0
- package/skills/continue/SKILL.md +348 -0
- package/skills/continue/references/context-contracts.md +169 -0
- package/skills/continue/references/continuity-checks.md +187 -0
- package/skills/continue/references/file-protocols.md +64 -0
- package/skills/continue/references/foreshadowing.md +130 -0
- package/skills/continue/references/gate-decision.md +53 -0
- package/skills/continue/references/periodic-maintenance.md +46 -0
- package/skills/novel-writing/SKILL.md +77 -0
- package/skills/novel-writing/references/quality-rubric.md +140 -0
- package/skills/novel-writing/references/style-guide.md +145 -0
- package/skills/start/SKILL.md +458 -0
- package/skills/start/references/quality-review.md +86 -0
- package/skills/start/references/setting-update.md +44 -0
- package/skills/start/references/vol-planning.md +61 -0
- package/skills/start/references/vol-review.md +58 -0
- package/skills/status/SKILL.md +116 -0
- package/skills/status/references/sample-output.md +60 -0
- package/templates/ai-blacklist.json +79 -0
- package/templates/brief-template.md +46 -0
- package/templates/genre-weight-profiles.json +90 -0
- package/templates/novel-ask/example.answer.json +12 -0
- package/templates/novel-ask/example.question.json +51 -0
- package/templates/platform-profile.json +148 -0
- package/templates/style-profile-template.json +58 -0
- package/templates/web-novel-cliche-lint.json +41 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"description": "platform-profile.json 默认模板库(init 阶段按平台选择并写入项目根目录的 platform-profile.json;平台绑定不可变)",
|
|
4
|
+
"last_updated": "2026-03-01",
|
|
5
|
+
"_comment": "Each entry under defaults is a full platform-profile.json object aligned with schemas/platform-profile.schema.json. Init SHOULD overwrite created_at and MAY apply user-confirmed overrides.",
|
|
6
|
+
"defaults": {
|
|
7
|
+
"qidian": {
|
|
8
|
+
"$schema": "schemas/platform-profile.schema.json",
|
|
9
|
+
"schema_version": 1,
|
|
10
|
+
"platform": "qidian",
|
|
11
|
+
"created_at": "2026-02-27T00:00:00Z",
|
|
12
|
+
"_comment_created_at": "Init SHOULD overwrite this with the actual creation timestamp.",
|
|
13
|
+
"word_count": {
|
|
14
|
+
"target_min": 2500,
|
|
15
|
+
"target_max": 3500,
|
|
16
|
+
"hard_min": 1800,
|
|
17
|
+
"hard_max": 4500
|
|
18
|
+
},
|
|
19
|
+
"hook_policy": {
|
|
20
|
+
"required": true,
|
|
21
|
+
"min_strength": 3,
|
|
22
|
+
"allowed_types": ["question", "threat_reveal", "twist_reveal", "emotional_cliff", "next_objective"],
|
|
23
|
+
"fix_strategy": "hook-fix"
|
|
24
|
+
},
|
|
25
|
+
"info_load": {
|
|
26
|
+
"max_new_entities_per_chapter": 6,
|
|
27
|
+
"max_unknown_entities_per_chapter": 3,
|
|
28
|
+
"max_new_terms_per_1k_words": 6
|
|
29
|
+
},
|
|
30
|
+
"compliance": {
|
|
31
|
+
"banned_words": [],
|
|
32
|
+
"duplicate_name_policy": "soft",
|
|
33
|
+
"script_paths": {
|
|
34
|
+
"lint_blacklist": "scripts/lint-blacklist.sh",
|
|
35
|
+
"lint_cliche": "scripts/lint-cliche.sh"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scoring": {
|
|
39
|
+
"genre_drive_type": "plot",
|
|
40
|
+
"weight_profile_id": "plot:v1"
|
|
41
|
+
},
|
|
42
|
+
"retention": {
|
|
43
|
+
"title_policy": {
|
|
44
|
+
"enabled": true,
|
|
45
|
+
"min_chars": 2,
|
|
46
|
+
"max_chars": 30,
|
|
47
|
+
"forbidden_patterns": ["^\\s*$", "^(?:无题|未命名|待定)$"],
|
|
48
|
+
"auto_fix": false
|
|
49
|
+
},
|
|
50
|
+
"hook_ledger": {
|
|
51
|
+
"enabled": true,
|
|
52
|
+
"fulfillment_window_chapters": 12,
|
|
53
|
+
"diversity_window_chapters": 5,
|
|
54
|
+
"max_same_type_streak": 2,
|
|
55
|
+
"min_distinct_types_in_window": 2,
|
|
56
|
+
"overdue_policy": "warn"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"_comment_retention": "Retention guardrails (M7): title policy + hook ledger windows/diversity. Defaults are enabled; enforcement/blocking is implemented in later pipeline steps (hook_ledger.overdue_policy defaults to warn).",
|
|
60
|
+
"readability": {
|
|
61
|
+
"mobile": {
|
|
62
|
+
"enabled": true,
|
|
63
|
+
"max_paragraph_chars": 320,
|
|
64
|
+
"max_consecutive_exposition_paragraphs": 3,
|
|
65
|
+
"blocking_severity": "hard_only"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"_comment_readability": "Mobile readability lint (M7): enabled, but only hard issues are allowed to block when implemented.",
|
|
69
|
+
"naming": {
|
|
70
|
+
"enabled": true,
|
|
71
|
+
"near_duplicate_threshold": 0.88,
|
|
72
|
+
"blocking_conflict_types": ["duplicate"],
|
|
73
|
+
"exemptions": {}
|
|
74
|
+
},
|
|
75
|
+
"_comment_naming": "Naming conflict lint (M7): enabled; only exact duplicates are configured as blocking by default."
|
|
76
|
+
},
|
|
77
|
+
"tomato": {
|
|
78
|
+
"$schema": "schemas/platform-profile.schema.json",
|
|
79
|
+
"schema_version": 1,
|
|
80
|
+
"platform": "tomato",
|
|
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): tomato tends to favor shorter windows; defaults are enabled; enforcement/blocking is implemented in later pipeline steps (hook_ledger.overdue_policy defaults to warn).",
|
|
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
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "风格指纹模板 — 由 StyleAnalyzer Agent 填充,ChapterWriter 和 StyleRefiner 读取",
|
|
3
|
+
|
|
4
|
+
"source_type": null,
|
|
5
|
+
"_source_type_comment": "original(用户原创样本)| reference(参考作者)| template(预置模板)| write_then_extract(先写后提)",
|
|
6
|
+
|
|
7
|
+
"reference_author": null,
|
|
8
|
+
"_reference_author_comment": "仿写模式时填写参考作者名,原创模式为 null",
|
|
9
|
+
|
|
10
|
+
"avg_sentence_length": null,
|
|
11
|
+
"_avg_sentence_length_comment": "平均句长(字数),如 18 表示平均每句 18 字",
|
|
12
|
+
|
|
13
|
+
"sentence_length_range": [null, null],
|
|
14
|
+
"_sentence_length_range_comment": "[最短句, 最长句],如 [8, 35]",
|
|
15
|
+
|
|
16
|
+
"dialogue_ratio": null,
|
|
17
|
+
"_dialogue_ratio_comment": "对话占全文比例,如 0.4 表示 40%",
|
|
18
|
+
|
|
19
|
+
"description_ratio": null,
|
|
20
|
+
"_description_ratio_comment": "描写(环境+心理)占比",
|
|
21
|
+
|
|
22
|
+
"action_ratio": null,
|
|
23
|
+
"_action_ratio_comment": "动作叙述占比",
|
|
24
|
+
|
|
25
|
+
"rhetoric_preferences": [],
|
|
26
|
+
"_rhetoric_preferences_comment": "修辞偏好列表,格式 [{\"type\": \"短句切换\", \"frequency\": \"high|medium|low\"}]",
|
|
27
|
+
|
|
28
|
+
"forbidden_words": [],
|
|
29
|
+
"_forbidden_words_comment": "作者从不使用的词汇列表(精准收录,不过度泛化)",
|
|
30
|
+
|
|
31
|
+
"preferred_expressions": [],
|
|
32
|
+
"_preferred_expressions_comment": "作者常用的特色表达",
|
|
33
|
+
|
|
34
|
+
"character_speech_patterns": {},
|
|
35
|
+
"_character_speech_patterns_comment": "角色语癖,格式 {\"角色名\": \"语癖描述 + 具体示例\"}",
|
|
36
|
+
|
|
37
|
+
"paragraph_style": {
|
|
38
|
+
"avg_paragraph_length": null,
|
|
39
|
+
"dialogue_format": null
|
|
40
|
+
},
|
|
41
|
+
"_paragraph_style_comment": "avg_paragraph_length 为平均段落字数,dialogue_format 为 引号式 | 无引号式",
|
|
42
|
+
|
|
43
|
+
"narrative_voice": null,
|
|
44
|
+
"_narrative_voice_comment": "第一人称 | 第三人称限制 | 全知",
|
|
45
|
+
|
|
46
|
+
"style_exemplars": [],
|
|
47
|
+
"_style_exemplars_comment": "从样本中提取的 3-5 段最能代表目标风格质感的原文片段(每段 50-150 字)。ChapterWriter 写作前作为 few-shot 锚点阅读,StyleRefiner 润色时作为风格参照。预置模板模式填入该风格类型的典型范文片段",
|
|
48
|
+
|
|
49
|
+
"writing_directives": [],
|
|
50
|
+
"_writing_directives_comment": "正向写作指令数组,每条含 directive + do/dont 对比示例。格式:[{\"directive\": \"用短动作句推进\", \"do\": \"他拔刀。刀光一闪。人头落地。\", \"dont\": \"他迅速地拔出了腰间的长刀,在刀光闪烁之间,对方的头颅便已经滚落在地。\"}]。旧格式(纯字符串数组)仍兼容,但新提取应使用 DO/DON'T 格式",
|
|
51
|
+
|
|
52
|
+
"override_constraints": {},
|
|
53
|
+
"_override_constraints_comment": "可选:覆盖 ChapterWriter 默认写作约束。支持的 key:anti_intuitive_detail (bool, 默认 true), max_scene_sentences (int, 默认 2)。未设置的 key 使用默认值",
|
|
54
|
+
|
|
55
|
+
"analysis_notes": null,
|
|
56
|
+
"_analysis_notes_comment": "StyleAnalyzer 的分析备注"
|
|
57
|
+
}
|
|
58
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"description": "网文套路词 / 模板腔 lint 词库(独立于 ai-blacklist;支持分级 severity + whitelist/exemptions)",
|
|
4
|
+
"last_updated": "2026-02-27",
|
|
5
|
+
|
|
6
|
+
"words": ["下一刻", "只见", "冷笑一声", "淡淡道", "不屑一顾", "轰然", "刹那间", "与此同时"],
|
|
7
|
+
|
|
8
|
+
"categories": {
|
|
9
|
+
"transition_cliche": ["与此同时", "下一刻", "刹那间"],
|
|
10
|
+
"expression_cliche": ["冷笑一声", "淡淡道", "不屑一顾"],
|
|
11
|
+
"sound_effect_cliche": ["轰然"],
|
|
12
|
+
"visual_cliche": ["只见"]
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"severity": {
|
|
16
|
+
"_comment": "Severity levels: warn | soft | hard. Executors MAY apply platform-profile-driven gating rules for hard terms.",
|
|
17
|
+
"default": "warn",
|
|
18
|
+
"per_category": {
|
|
19
|
+
"transition_cliche": "warn",
|
|
20
|
+
"expression_cliche": "soft",
|
|
21
|
+
"sound_effect_cliche": "warn",
|
|
22
|
+
"visual_cliche": "warn"
|
|
23
|
+
},
|
|
24
|
+
"per_word": {
|
|
25
|
+
"淡淡道": "soft",
|
|
26
|
+
"不屑一顾": "soft"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"whitelist": [],
|
|
31
|
+
|
|
32
|
+
"exemptions": {
|
|
33
|
+
"_comment": "Structured exemptions to reduce false positives. Executors may ignore unsupported fields.",
|
|
34
|
+
"exact": [],
|
|
35
|
+
"regex": [],
|
|
36
|
+
"notes": []
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
"update_log": []
|
|
40
|
+
}
|
|
41
|
+
|