dsh-novel-write-engine 0.0.0-stage → 0.1.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/CHANGELOG.md +44 -0
- package/LICENSE +21 -0
- package/README.md +1167 -2
- package/briefs/P1.md +29 -0
- package/briefs/P2.md +34 -0
- package/briefs/P3.md +56 -0
- package/briefs/P4.md +74 -0
- package/briefs/P5.md +26 -0
- package/briefs/P6.md +42 -0
- package/briefs/P8.md +41 -0
- package/cordis.patch.yml +6 -0
- package/lib/client.js +694 -0
- package/lib/index.d.ts +1345 -0
- package/lib/index.js +7469 -0
- package/lib/types/client/dto.d.ts +61 -0
- package/lib/types/client/index.d.ts +17 -0
- package/lib/types/client/panel.d.ts +14 -0
- package/lib/types/client/viewmodel.d.ts +66 -0
- package/lib/types/constants.d.ts +64 -0
- package/lib/types/types.d.ts +650 -0
- package/package.json +135 -4
- package/presets/novel-write-engine.patch.yml +56 -0
- package/rulepacks/default.yaml +231 -0
- package/skills/entry.md +68 -0
package/briefs/P1.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# P1 · 世界观约束
|
|
2
|
+
|
|
3
|
+
你是第 {{chapter}} 章的世界观约束者。本阶段**不写正文**,只确定「这一章在什么规则下发生」。
|
|
4
|
+
|
|
5
|
+
## 本阶段要看
|
|
6
|
+
|
|
7
|
+
- 《{{title}}》,类型 {{genre}},平台 {{platform}}。
|
|
8
|
+
- 先调 `novel_state` 读 `characters`、`world`、`locks`、`foreshadows`,确认人物状态与已锁定设定。
|
|
9
|
+
- 再调 `novel_status` 看当前章与阻塞项。
|
|
10
|
+
|
|
11
|
+
## 产出
|
|
12
|
+
|
|
13
|
+
调用 `novel_plan_world`,参数:
|
|
14
|
+
|
|
15
|
+
| 字段 | 要求 |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `objective` | 一句话说清本章要推进什么,必须是可检验的事件 |
|
|
18
|
+
| `constraints` | 本章不能违反的硬约束(人物能力、地点布局、时间线) |
|
|
19
|
+
| `characters` | 出场人物及其**本章开始时**的状态 |
|
|
20
|
+
| `locations` | 本章用到的地点,布局与容量沿用已锁定值 |
|
|
21
|
+
| `continuity_notes` | 与前一章的衔接点、未回收伏笔 |
|
|
22
|
+
|
|
23
|
+
## 铁律
|
|
24
|
+
|
|
25
|
+
1. 已锁定设定不许改;要改先 `novel_amend` 并在理由里说明。
|
|
26
|
+
2. 不新增未经铺垫的能力、神器、势力。
|
|
27
|
+
3. 不写「本章将是高潮」这类空话,写事件。
|
|
28
|
+
|
|
29
|
+
完成后管线进入 P2,下一步调 `novel_brief` 取 P2 任务书。
|
package/briefs/P2.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# P2 · 章节预检
|
|
2
|
+
|
|
3
|
+
本章计划决定「怎么写」,不是「写什么」。写的是可执行的节拍表,不是剧情梗概。
|
|
4
|
+
|
|
5
|
+
## 输入
|
|
6
|
+
|
|
7
|
+
- P1 的世界观计划:`novel_state {"kind":"planWorld","chapter":{{chapter}}}`(对应 `plans/ch{{chapter_pad}}.world.yaml`)。
|
|
8
|
+
- 上一章结尾(`state/handoff.yaml` 的 `last_summary`)。
|
|
9
|
+
- 未回收伏笔:`novel_state foreshadows`。
|
|
10
|
+
|
|
11
|
+
## 产出
|
|
12
|
+
|
|
13
|
+
调用 `novel_plan_chapter`:
|
|
14
|
+
|
|
15
|
+
| 字段 | 要求 |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `title` | 不带「第N章」前缀,4~8 字;引擎会拼前缀并校验 |
|
|
18
|
+
| `scene_type` | 四选一:战斗/动作章、日常过渡章、情感爆发章、纯叙事章 |
|
|
19
|
+
| `narrator` | 视角人物,必须在本章出场;第一人称写成 `陈默(第一人称「我」)`,引擎接受括号/引号里的正文别名 |
|
|
20
|
+
| `beats` | 5~8 个节拍,每个是一句话的可检验动作 |
|
|
21
|
+
| `opening` | 前两段打算怎么写(场景 + 动作 + 一个钩子) |
|
|
22
|
+
| `ending` | 断章点,必须是新信息或新麻烦 |
|
|
23
|
+
| `target_words` | `[{{min_words}}, {{max_words}}]` |
|
|
24
|
+
|
|
25
|
+
## 场景类型纪律
|
|
26
|
+
|
|
27
|
+
- 不许连续三章同型;战斗章不许连排两章。
|
|
28
|
+
- 情感爆发章必须有一个明确的情绪转折点,不许整章都在铺垫。
|
|
29
|
+
|
|
30
|
+
## 断章
|
|
31
|
+
|
|
32
|
+
结尾落在一个**未解决的问题**上。不要总结、不要升华、不要预告下一章。
|
|
33
|
+
|
|
34
|
+
完成后管线进入 P3,下一步调 `novel_brief` 取 P3 任务书。
|
package/briefs/P3.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# P3 · 初稿
|
|
2
|
+
|
|
3
|
+
本阶段只做一件事:把 P2 的节拍写成正文。
|
|
4
|
+
|
|
5
|
+
## 硬指标
|
|
6
|
+
|
|
7
|
+
- 字数 ≥ {{min_words}}(引擎口径:汉字 + 英文单词 + 数字 + 标点)。
|
|
8
|
+
- 单段 ≤ 90 字;段与段之间空一行。
|
|
9
|
+
- 对话只用英文直引号 `"`;**中文弯引号 `“ ”`、直角引号 `「 」` 都是 ILLEGAL_QUOTE blocker**;禁全角分号 `;`、禁 `...`。
|
|
10
|
+
- 不写 Markdown:禁 `#`、`**`、`---`、`>`、表格。
|
|
11
|
+
- 不写「Day 1」「第X卷」「读者」「作者」这类出戏标签。
|
|
12
|
+
|
|
13
|
+
## 写法
|
|
14
|
+
|
|
15
|
+
1. 一段一个信息点。先动作,后反应,最后才允许一句心理。
|
|
16
|
+
2. 对话要有区分度:不同角色说话的句长、口头禅、攻击性不同。
|
|
17
|
+
3. 每 600 字左右至少一个爽点或新信息,不许连续铺垫。
|
|
18
|
+
4. 结尾断在动作中间或新信息刚落地时。
|
|
19
|
+
|
|
20
|
+
## 提交
|
|
21
|
+
|
|
22
|
+
调用 `novel_write_draft`,参数至少包含 `chapter`、`chapter_title`、`content`、`scene_type`、`narrator` 与完整 `summary` 十个字段。**形状必须完全如下**:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"events": ["本章发生的事件,至少一条"],
|
|
27
|
+
"characters_appeared": ["本章出现的人物名"],
|
|
28
|
+
"foreshadows": {
|
|
29
|
+
"planted": [{ "key": "letter", "title": "旧信封", "description": "无名信" }],
|
|
30
|
+
"advanced": [{ "key": "FS-001", "note": "日期被改", "new_info": true }],
|
|
31
|
+
"resolved": ["FS-002"]
|
|
32
|
+
},
|
|
33
|
+
"new_elements": { "locations": ["旧办公室"], "abilities": [], "artifacts": [] },
|
|
34
|
+
"resource_changes": [
|
|
35
|
+
{ "character": "他", "resource": "铜钱", "delta": -200, "reason": "买信封" }
|
|
36
|
+
],
|
|
37
|
+
"opening": "正文前两段里的逐字引用,至少 12 字",
|
|
38
|
+
"continuity": { "opens_from": "上一章结尾", "ends_with": "本章结尾的钩子" },
|
|
39
|
+
"hook_strength": 4,
|
|
40
|
+
"pleasure_points": ["本章的爽点"],
|
|
41
|
+
"plot_advancement": "high"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `foreshadows.planted` **不是字符串数组**,每项是 `{key,title,description}`。
|
|
46
|
+
- `new_elements` 是**对象**,不是数组;三个键都必须是字符串数组(没有就 `[]`)。
|
|
47
|
+
- `resource_changes` 每项是 `{character,resource,delta,reason}`,`delta` 是非零整数;没有变化就 `[]`。
|
|
48
|
+
- `opening` 必须逐字出现在正文前两段,不能写剧情概括。
|
|
49
|
+
- `continuity` 是 `{opens_from,ends_with}` 对象。
|
|
50
|
+
- `hook_strength` 是 1–5 的整数,`plot_advancement` 是 `high|mid|low`。
|
|
51
|
+
|
|
52
|
+
## 提交前自检
|
|
53
|
+
|
|
54
|
+
先调 `novel_word_count` 看字数,再提交。门控失败会返回**全部**阻塞项,一次改完再交。
|
|
55
|
+
|
|
56
|
+
完成后管线进入 P4,下一步调 `novel_brief` 取 P4 任务书。
|
package/briefs/P4.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# P4 · 评审
|
|
2
|
+
|
|
3
|
+
你是独立评审,不是作者。本轮是第 {{round}} 轮(上限 3 轮)。
|
|
4
|
+
|
|
5
|
+
## 先证明你读过
|
|
6
|
+
|
|
7
|
+
调用 `novel_review` 必须带 `proof`,三处引用:
|
|
8
|
+
|
|
9
|
+
| 位置 | 要求 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `opening` | 前两段里的一处,≥12 字 |
|
|
12
|
+
| `middle` | 正文中部的一处,≥12 字 |
|
|
13
|
+
| `ending` | 最后两段里的一处,≥12 字 |
|
|
14
|
+
|
|
15
|
+
引用必须**逐字**来自正文。`paragraph` 允许 ±1 段定位误差,但开头/结尾边界按引文的**实际段落**判定;把中段引用写成 `paragraph: 2` 不会变成开头引用。伪造会被 `ENGINE_READING_PROOF_INVALID` 打回。
|
|
16
|
+
|
|
17
|
+
## 十五维评分(满分 150)
|
|
18
|
+
|
|
19
|
+
| 组 | 维度 |
|
|
20
|
+
|---|---|
|
|
21
|
+
| 核心叙事 90 | R-W-01 人设驱动 15 · R-W-02 情绪外化 10 · R-W-03 对话区分度 10 · R-W-04 爽点密度 20 · R-W-05 断章法则 15 · R-W-12 反文青病 20 |
|
|
22
|
+
| 商业指标 45 | R-W-11 元描写与视角侵入 10 · R-W-13 信息增量 15 · R-W-14 钩子质量 10 · R-W-15 期待值兑现 10 |
|
|
23
|
+
| 格式硬性 15 | R-W-06 段落长度 4 · R-W-07 去 AI 味 4 · R-W-08 硬性禁令 4 · R-W-09 字数 2 · R-W-10 标题 1 |
|
|
24
|
+
|
|
25
|
+
## 调用形状
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"chapter": 1,
|
|
30
|
+
"dimensions": [
|
|
31
|
+
{
|
|
32
|
+
"id": "R-W-01",
|
|
33
|
+
"max": 15,
|
|
34
|
+
"deductions": [
|
|
35
|
+
{ "rule": "NO_MOTIVE", "location": "第 2 段", "note": "动作缺少动机", "delta": 5 }
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"issues": [
|
|
40
|
+
{
|
|
41
|
+
"id": "REV-001",
|
|
42
|
+
"severity": "blocker",
|
|
43
|
+
"dimension": "R-W-01",
|
|
44
|
+
"location": "第 2 段",
|
|
45
|
+
"problem": "缺动机",
|
|
46
|
+
"fix": "补一句理由",
|
|
47
|
+
"status": "open"
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"total": 145,
|
|
51
|
+
"proof": {
|
|
52
|
+
"opening": { "paragraph": 1, "quote": "正文前两段里的逐字引用" },
|
|
53
|
+
"middle": { "paragraph": 3, "quote": "正文中部的逐字引用" },
|
|
54
|
+
"ending": { "paragraph": 5, "quote": "最后两段里的逐字引用" }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
十五个维度必须全部出现,`max` 用上表的满分;没有扣分的维度写 `"deductions": []`。
|
|
60
|
+
`dimensions`/`issues`/`proof` 可以是 JSON 对象,也可以是 JSON 字符串;引擎两者都接受。
|
|
61
|
+
|
|
62
|
+
## 扣分规则
|
|
63
|
+
|
|
64
|
+
- `total = 150 - Σdelta`,引擎会复算;差 1 分都过不了。
|
|
65
|
+
- 每条扣分必须写 `rule`、`location`(「第 N 段」)、`note`;指不到段落的扣分无效。
|
|
66
|
+
- 同一片段只罚最重的一项;互斥对见 `novel_brief` 返回的 `fields.score_exclusions`,先应用互斥再算总分。
|
|
67
|
+
- 过关线:总分 ≥ {{min_score}}。
|
|
68
|
+
|
|
69
|
+
## issue
|
|
70
|
+
|
|
71
|
+
- `blocker` 必须修;`advisory` 可改可不改。
|
|
72
|
+
- 每条 issue 写清 `problem` 与 `fix`,fix 要是可执行动作。
|
|
73
|
+
|
|
74
|
+
完成后:仍有 blocker → P5 修订;全部清零 → P6 校验。
|
package/briefs/P5.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# P5 · 修订
|
|
2
|
+
|
|
3
|
+
只改评审指出的问题,不重写整章。第 {{round}} 轮。
|
|
4
|
+
|
|
5
|
+
## 规则
|
|
6
|
+
|
|
7
|
+
1. 每条 `blocker` issue 必须变成 `fixed`,并给 `evidence`——修订后正文里的**逐字引用**,引擎会回查。
|
|
8
|
+
2. `blocker` 不许 `waived`;只有 advisory 可以带理由豁免。
|
|
9
|
+
3. 改完字数仍要 ≥ {{min_words}},格式要求同 P3。
|
|
10
|
+
4. 改动会抬高或压低评分时,不要自己改分;下一轮 P4 重新评。
|
|
11
|
+
|
|
12
|
+
## 提交
|
|
13
|
+
|
|
14
|
+
调用 `novel_revise`:
|
|
15
|
+
|
|
16
|
+
- `content`:修订后的完整正文(不是 diff)。
|
|
17
|
+
- `summary`:如果事件、伏笔、资源有变化,同步更新;没变化可省略。**如果改动前两段/opening,必须同时提交新的 summary**,否则引擎会拒绝。
|
|
18
|
+
- `proof`:修订后正文的三个逐字引用(opening/middle/ending),每段至少 12 字;PG-09 会逐条回查,开头/结尾按实际段落判定,不能改写、编造或靠提交段落号挪动边界。
|
|
19
|
+
|
|
20
|
+
## 常见返工原因
|
|
21
|
+
|
|
22
|
+
- 只改了措辞,没解决 issue 指出的信息缺口。
|
|
23
|
+
- `evidence` 抄的是旧句子。
|
|
24
|
+
- 改完段落超 90 字。
|
|
25
|
+
|
|
26
|
+
提交后回到 P4 重新评审;轮次由引擎自增,你不需要也不允许传轮次。
|
package/briefs/P6.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# P6 · 一致性校验
|
|
2
|
+
|
|
3
|
+
本阶段由引擎跑机检、你补语义项。**不要重写正文**。
|
|
4
|
+
|
|
5
|
+
## 机检(引擎自动)
|
|
6
|
+
|
|
7
|
+
- 格式与字数:引号、分号、省略号、长段、标题。
|
|
8
|
+
- 跨章对账:重复段落、伏笔休眠、资源余额、时间倒退、关系未声明、锁定描写漂移。
|
|
9
|
+
|
|
10
|
+
## 语义项(你提供)
|
|
11
|
+
|
|
12
|
+
调用 `novel_check` 传 `semantic`,形状必须是:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
[
|
|
16
|
+
{ "id": "L2-SCENE-ANCHOR", "verdict": "pass", "evidence": "正文中的逐字引用", "note": "场景与计划一致" },
|
|
17
|
+
{ "id": "L2-CHARACTER-STATE", "verdict": "pass", "evidence": "正文中的逐字引用", "note": "心理状态与台账一致" },
|
|
18
|
+
{ "id": "L2-CAUSALITY", "verdict": "pass", "evidence": "正文中的逐字引用", "note": "转折有前置因果" },
|
|
19
|
+
{ "id": "L2-VOICE", "verdict": "pass", "evidence": "正文中的逐字引用", "note": "对话可区分" }
|
|
20
|
+
]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
四个 id 必须各出现一次;`verdict` 只能是 `pass`/`fail`;`evidence` 至少 8 字、必须逐字出现在正文里,且四条引用必须互不相同。四项引用同一句话不算四份证据,会被 `SEMANTIC_EVIDENCE_INVALID` 拒绝。
|
|
24
|
+
|
|
25
|
+
| id | 检查 |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `L2-SCENE-ANCHOR` | 本章场景与 P1 计划的地点一致 |
|
|
28
|
+
| `L2-CHARACTER-STATE` | 人物状态与 `characters` 台账一致 |
|
|
29
|
+
| `L2-CAUSALITY` | 关键转折有前置因果,不是突然降神 |
|
|
30
|
+
| `L2-VOICE` | 对话能区分说话人 |
|
|
31
|
+
|
|
32
|
+
每项必须带 `evidence`:正文中的逐字引用。找不到引用=该项不成立。
|
|
33
|
+
|
|
34
|
+
## 判定
|
|
35
|
+
|
|
36
|
+
- 任一项 `fail` → 校验不过,先重新领取 `novel_brief P6`(check 已改变上下文,旧 digest 会失效),再调用 `novel_revise` 修订并回到 P4 重评(轮次 +1)。
|
|
37
|
+
- 全过 → 管线进入 `ready_to_archive`,先 `novel_brief P8` 领取终审任务书,再调用 `novel_archive`。
|
|
38
|
+
|
|
39
|
+
## 不许做的
|
|
40
|
+
|
|
41
|
+
- 不许为了让校验过而删掉有信息量的段落。
|
|
42
|
+
- 不许把语义项全部填 `pass` 而不给证据。
|
package/briefs/P8.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# P8 · 终审
|
|
2
|
+
|
|
3
|
+
归档前最后一遍。本阶段由引擎执行事务,你只确认两件事。
|
|
4
|
+
|
|
5
|
+
## 确认清单
|
|
6
|
+
|
|
7
|
+
1. **正文没变**:`novel_check` 之后没有再改正文。改了就必须重新校验。
|
|
8
|
+
2. **摘要属实**:`summary` 里的伏笔、资源变化能在正文中找到依据。
|
|
9
|
+
3. **delta 齐了**:本章出现过的每个角色、新地点/能力/物品、伏笔、事件、关系,都在 `state_delta` 里逐条声明 `created` / `updated` / `no_change`;`no_change` 必须写 `reason`。
|
|
10
|
+
|
|
11
|
+
## 调用
|
|
12
|
+
|
|
13
|
+
`novel_archive` 必须同时传 `chapter` 与 `state_delta`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"chapter": 3,
|
|
18
|
+
"state_delta": {
|
|
19
|
+
"characters": { "主角": { "action": "no_change", "reason": "本章没有状态变化" } },
|
|
20
|
+
"foreshadows": { "FS-007": { "action": "updated", "note": "日期被改动", "new_info": true } },
|
|
21
|
+
"timeline": { "0": { "action": "created", "story_time": "Day 3 清晨", "description": "收到信" } },
|
|
22
|
+
"world": {},
|
|
23
|
+
"relationships": {}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `timeline` 的键是 `summary.events` 的下标(字符串)。
|
|
29
|
+
- `relationships` 的键是 `"甲|乙"`;每项至少 `{ "action": "created", "type": "关系类型", "description": "..." }`,缺 `type` 会被拒绝。
|
|
30
|
+
- `characters` 的键是人物名;`world` 的键是新地点/能力/物品名;`foreshadows` 的键是 summary 里的 planted key 或已分配的 `FS-xxx`。
|
|
31
|
+
- 第一人称的叙述者若在 `narrator` 里声明为 `陈默(第一人称「我」)`,正文用「我」也视为出现,但角色键仍写 `陈默`。
|
|
32
|
+
- 每个新实体至少写 `action: "created"`;已存在且没变化写 `action: "no_change", reason: "..."`。
|
|
33
|
+
- `world` 新实体还要写 `kind: "location"|"ability"|"artifact"` 和 `description`。
|
|
34
|
+
- `state_delta` 可以是对象,也可以是 JSON 字符串;引擎两者都接受。
|
|
35
|
+
- 未知伏笔 key、未声明角色、`no_change` 缺原因都会被 `ENGINE_DELTA_UNVERIFIED` 拒绝,引擎不会猜。
|
|
36
|
+
- 不要传正文、不要传评分、不要传轮次。`handoff` 可选,用于覆盖卷/幕/进度。
|
|
37
|
+
|
|
38
|
+
## 归档后
|
|
39
|
+
|
|
40
|
+
- 管线进入 `done`,章节号 +1,轮次清零。
|
|
41
|
+
- 若还有下一章,从 `novel_brief P1` 重新开始。
|