dsh-novel-write-engine 0.1.1 → 0.1.2

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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2
4
+
5
+ - `novel_init` 显式传入的 `author`/`description` 必须是字符串;P1/P2 计划在服务边界做运行时窄化:世界计划数组/对象形状、章节标题 4–8 字、narrator、5–8 个节拍、opening/ending、target_words 全部校验,非法输入零写盘。
6
+ - P4 issue 的 `dimension` 必须是当前规则包的十五维之一,`location` 必须是本章实际段落;blocker 在 P4/P5 都不能 `waived`;P5 只能改 issue 的 `status`/`evidence`,不能改写问题定义或严重度。
7
+ - `novel_rollback` 只允许退回当前阶段或更早阶段;`P3 → P6` 这类前进跳过会被拒绝。
8
+ - plan/review/check 任一文件损坏时,`novel_status`/`novel_pipeline` 仍可读,返回 `state_errors` 与 `STATE_UNREADABLE` 阻塞,`next` 指向 `novel_rollback`;回退后可用既有阶段重建,不需要手改文件。P6 的 check 损坏优先于旧 revision 阻塞,`next` 直接给 `novel_check`。
9
+ - `novel_brief` 的 `fields`/`context` 暴露 `plan_error`/`review_error`/`check_error`;损坏状态会阻断需要该文档的写操作。schema 版本高于本引擎的 plan/review/check 不会被当作“可修复损坏”,而是 `ENGINE_SCHEMA_TOO_NEW`,绝不覆盖。
10
+ - `novel_archive` 对“review 存在但没有 `review_digest`”(或摘要已不匹配)的旧数据 fail-closed;status 返回 `REVIEW_DIGEST_MISSING`/`REVIEW_DIGEST_MISMATCH`,`next` 指向回退 P4 重新评审,不会让模型反复撞归档。
11
+ - 每个 brief 阶段有独立上下文预算(P1 6000 / P2 8000 / P3 16000 / P4-P5 24000 / P6 32000 / P8 12000);正文、当前 plan/review/check、摘要等受保护内容不裁剪,截断项与省略数写入 `context_meta` 并参与 digest;预算计算把 `context_meta` 自身的增长算进去,不再用固定预留猜大小。
12
+ - 上下文按正文/计划提及、最近程度、稳定 key 选择角色/世界/锁定/伏笔/时间线/关系;同分按名称/ID 稳定排序,输入顺序变化不改变 brief;不引入 RAG、SQLite 或新依赖。
13
+ - 水词/爽点/感官窗口改为按非空白字符推进,空格、换行、全角空格不再改变窗口结果;全角标点仍按 DESIGN 计入 `nonWsChars`。
14
+ - `RESOURCE_MISMATCH` 同时核对角色、资源名、数量与正负方向;符号必须在金额附近,远处另一段的反向词不能替它开脱。
15
+ - `ready_to_archive` 的九相位条显示 P7 进行中,P8/P9 未完成,不再把尚未发生的 P7 标成已完成。
16
+ - `novel_check` 的 `scope` 真正生效:默认 `content + integrity`,允许只跑其中一类;空数组/未知值零写盘,scope 归一化为固定顺序后写入 check 文档并参与幂等 key。
17
+ - `check:host` 新增真实 headless 工具链:临时 profile 中通过本地 Messages peer 触发 `novel_init`,断言工具声明、工具结果、项目落盘与最终回答;Web 面板与 remove 链路保留。
18
+ - 文档同步 0.1.2 的契约、升级路径与已知限制;状态 schema 仍为 v1,不新增工具/命令/运行时依赖。
19
+
3
20
  ## 0.1.1
4
21
 
5
22
  - `novel_brief` 现在把 `fields` 一并返回,P4 可直接读取 `score_exclusions` 与 `next_tool`;非当前活跃章的 brief 请求被拒绝。
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  它不是一个提示词合集,也不是独立的写作软件。它把「这一章处于什么阶段、下一步只能做什么、正文是否达标、归档要核销哪些实体」变成可执行、可回滚、可审计的引擎;模型负责写,引擎负责裁决和记账。
6
6
 
7
- > **当前版本:0.1.1** · 中文界面 · MIT
7
+ > **当前版本:0.1.2** · 中文界面 · MIT
8
8
  >
9
9
  > **宿主范围**:DSH `>=0.2.1-rc.2 <0.3.0-0`;Node `>=24.9.0`。
10
10
 
@@ -70,7 +70,7 @@
70
70
  - 不是「装完就自动写完整本书」的生成器;它管流程、门禁和状态,正文仍由模型写。
71
71
  - 不是独立 CLI;必须作为 DSH 插件安装到某个 profile 才能使用。
72
72
  - 不提供云端同步、账号体系、在线书城或多人协作。
73
- - 0.1.1 只有中文界面与中文任务书,没有 `locale/`,也不读取系统语言。
73
+ - 0.1.2 只有中文界面与中文任务书,没有 `locale/`,也不读取系统语言。
74
74
 
75
75
  ---
76
76
 
@@ -165,7 +165,7 @@ P7/P8/P9 在 `novel_archive` 一次事务里完成。单章归档后状态是 `d
165
165
  | 宿主形态 | Web(面板 + 预设)、Desktop(面板 + 预设,插件由桌面壳管理)、headless(只有工具/命令,无面板/预设) |
166
166
  | 磁盘 | 项目根目录可写;默认 `stateDir` 可写 |
167
167
  | 网络 | 安装时需要访问 npm / Git 托管;运行插件本身不联网 |
168
- | 语言 | 0.1.1 仅中文 |
168
+ | 语言 | 0.1.2 仅中文 |
169
169
 
170
170
  检查命令:
171
171
 
@@ -269,7 +269,7 @@ dsh plugin --profile web add dsh-novel-write-engine
269
269
  固定版本:
270
270
 
271
271
  ```bash
272
- dsh plugin --profile web add dsh-novel-write-engine@0.1.1
272
+ dsh plugin --profile web add dsh-novel-write-engine@0.1.2
273
273
  ```
274
274
 
275
275
  `dsh` 不在 PATH 时,用 `npx @deepseek-ai/dsh` 代替命令开头的 `dsh`。
@@ -324,13 +324,13 @@ corepack pnpm pack
324
324
  会得到类似:
325
325
 
326
326
  ```text
327
- dsh-novel-write-engine-0.1.1.tgz
327
+ dsh-novel-write-engine-0.1.2.tgz
328
328
  ```
329
329
 
330
330
  把这个 tarball 复制到目标机器,放在一个**稳定、不会随手删除**的路径,然后:
331
331
 
332
332
  ```bash
333
- dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.1.1.tgz
333
+ dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.1.2.tgz
334
334
  ```
335
335
 
336
336
  tarball 安装不会运行源码构建,也不会要求 `allowBuilds`;包内已经包含 `lib/`、`rulepacks/`、`briefs/`、`skills/`、`presets/` 和两层 patch。它是最接近「发布产物」的安装方式。
@@ -345,9 +345,9 @@ tarball 安装不会运行源码构建,也不会要求 `allowBuilds`;包内
345
345
  2. 点 **添加插件**(或旁边的箭头 → **安装第三方插件**)。
346
346
  3. 在包名字段填入以下任一形式:
347
347
  - npm 包名:`dsh-novel-write-engine`
348
- - 精确版本:`dsh-novel-write-engine@0.1.1`
348
+ - 精确版本:`dsh-novel-write-engine@0.1.2`
349
349
  - 源码目录:`/absolute/path/to/dsh-novel-write-engine`
350
- - tarball:`/absolute/path/to/dsh-novel-write-engine-0.1.1.tgz`
350
+ - tarball:`/absolute/path/to/dsh-novel-write-engine-0.1.2.tgz`
351
351
  4. npm 包名从 npm 官方源安装;本地目录和 tarball 直接使用宿主路径。
352
352
  5. 点 **安装**,等待完成。
353
353
  6. 如果出现 **立即启用**,点它;否则安装后到「已安装插件」里把 **dsh-novel-write-engine** 打开。
@@ -461,10 +461,13 @@ dsh --profile web --dump-config | grep -A8 '# == dsh-novel-write-engine'
461
461
  关键点:
462
462
 
463
463
  - **每一步提交前都要先领任务书**,PG-01 会检查 digest。`novel_status` / `novel_pipeline` 在任务书缺失或过期时会先返回 `novel_brief`,不会让你直接撞 PG-01。
464
+ - **plan/review/check 损坏时不是死锁**:status 返回 `state_errors` 与 `STATE_UNREADABLE`;当前阶段晚于重建点时,`next` 指向 `novel_rollback`,已经处在 P2/P4/P6 时则直接指向 `novel_brief` → 对应的 `novel_plan_chapter`/`novel_review`/`novel_check`。不会让模型在同一条 rollback 上循环。P6 的 check 损坏优先于旧 revision 阻塞;归档前 `review_digest` 缺失/不匹配会显示 `REVIEW_DIGEST_MISSING`/`REVIEW_DIGEST_MISMATCH` 并回退 P4。
465
+ - **计划先校验再落盘**:P1 的 `constraints`/`characters`/`locations`/`continuity_notes` 有形状校验;P2 的标题 4–8 字、5–8 个非空节拍、narrator、opening/ending 都会在服务边界拒绝。
466
+ - **上下文有预算**:每个 brief 的 `context.context_meta` 给出 `budget`/`used`/`truncated`/`omitted`;正文、当前 plan/review/check 与摘要受保护,不会被静默截断。裁剪会参与 digest,升级后旧 brief 需要重新领取。
464
467
  - `ready_to_archive` 在 P8 任务书当前后,`next.tool` 才返回 `novel_archive`;P5/P6 有阻塞时返回 `novel_revise`。
465
- - `novel_review` 的 `total` 是必填的,必须等于 `150 - Σdelta`;三段阅读证明必须逐字来自正文,开头/结尾按**实际段落**判定。
466
- - `novel_check` 的 `semantic` 恰好四个语义项,每项带至少 8 字、四条互不相同的正文引用。
467
- - `novel_archive` 的 `state_delta` 要逐实体核销角色、伏笔、时间线、世界、关系;新伏笔标题必须出现在正文,`no_change` 也要写原因。
468
+ - `novel_review` 的 `total` 是必填的,必须等于 `150 - Σdelta`;三段阅读证明必须逐字来自正文,开头/结尾按**实际段落**判定;issue 的 `dimension` 必须是当前十五维之一,`location` 必须是本章实际段落。
469
+ - `novel_check` 的 `semantic` 恰好四个语义项,每项带至少 8 字、四条互不相同的正文引用;`scope` 默认 `content + integrity`,只跑一类时另一类不参与本次 check。
470
+ - `novel_archive` 的 `state_delta` 要逐实体核销角色、伏笔、时间线、世界、关系;新伏笔标题必须出现在正文,`no_change` 也要写原因;review 存在但 `review_digest` 缺失时拒绝归档,需重新 `novel_review`。
468
471
  - 正文改动后,旧的评审分数和 check 会失效;不要试图手工改 `state/` 绕过。
469
472
 
470
473
  ### 5. 看面板
@@ -500,19 +503,19 @@ dsh --profile web --dump-config | grep -A8 '# == dsh-novel-write-engine'
500
503
  | 工具 | 阶段 | 做什么 | 写盘 |
501
504
  |---|---|---|---|
502
505
  | `novel_init` | — | 建项目:`novel.yaml` + `state/` + 目录 | 是 |
503
- | `novel_status` | 任意 | 当前活跃章、阶段、轮次、阻塞项、下一步;`chapter` 只用于字数查询 | 否 |
504
- | `novel_brief` | P1–P6 / P8 | 领取当前活跃章的任务书,返回 `fields` 并记录 digest | 仅任务书签收 |
505
- | `novel_plan_world` | P1 | 提交世界观约束 | 是 |
506
- | `novel_plan_chapter` | P2 | 提交章节计划 | 是 |
506
+ | `novel_status` | 任意 | 当前活跃章、阶段、轮次、阻塞项、`state_errors`、下一步;`chapter` 只用于字数查询 | 否 |
507
+ | `novel_brief` | P1–P6 / P8 | 领取当前活跃章的任务书,返回 `fields`、`context` 与 `context_meta` 并记录 digest | 仅任务书签收 |
508
+ | `novel_plan_world` | P1 | 提交世界观约束;数组/对象形状在服务边界校验 | 是 |
509
+ | `novel_plan_chapter` | P2 | 提交章节计划;标题 4–8 字、5–8 个节拍、opening/ending 非空 | 是 |
507
510
  | `novel_write_draft` | P3 | 提交初稿;格式/字数/摘要不过整体拒绝 | 是 |
508
- | `novel_review` | P4 | 十五维评分、问题清单、三段阅读证明 | 是 |
509
- | `novel_revise` | P5/P6 | 提交修订;blocker 必须有正文证据 | 是 |
510
- | `novel_check` | P6 | 机检 + 四个语义一致性项 | 是 |
511
- | `novel_archive` | P7–P9 | 事务归档;必须带 `state_delta` | 事务 |
511
+ | `novel_review` | P4 | 十五维评分、问题清单、三段阅读证明;issue 维度/段落和 blocker waived 会被拒绝 | 是 |
512
+ | `novel_revise` | P5/P6 | 提交修订;blocker 必须有正文证据,不能降级或 waived;issue 只能改 status/evidence | 是 |
513
+ | `novel_check` | P6 | 机检 + 四个语义一致性项;`scope` 可只跑 `content` 或 `integrity` | 是 |
514
+ | `novel_archive` | P7–P9 | 事务归档;必须带 `state_delta`;旧 review 无 digest 时拒绝 | 事务 |
512
515
  | `novel_word_count` | 任意 | 按引擎唯一口径数字数 | 否 |
513
516
  | `novel_state` | 任意 | 读账本、计划、评审、检查、handoff;`review`/`check` 可按历史章读取 | 否 |
514
517
  | `novel_amend` | 任意 | 带原因修订一个状态文档 | 是,入 journal |
515
- | `novel_rollback` | 任意 | 回退到 P1–P6,保留正文供参考 | 是 |
518
+ | `novel_rollback` | 任意 | 只退回当前阶段或更早,保留正文供参考 | 是 |
516
519
  | `novel_diff` | 任意 | 与上次归档备份或两段文本比较 | 否 |
517
520
  | `novel_export` | 任意 | 导出 `md` / `txt` / `epub` | 导出目录 |
518
521
  | `novel_audit` | 任意 | 读追加式 journal 审计记录 | 否 |
@@ -728,7 +731,7 @@ P8.md
728
731
 
729
732
  ### 9.4 规则包不能运行期切换
730
733
 
731
- `rulepacks/default.yaml` 是随包加载的:词表、格式、标点、语义、跨章阈值、平台默认值都在里面。0.1.1 **不接受**运行期外部规则包路径。
734
+ `rulepacks/default.yaml` 是随包加载的:词表、格式、标点、语义、跨章阈值、平台默认值都在里面。0.1.2 **不接受**运行期外部规则包路径。
732
735
 
733
736
  要改规则,只有两条路:
734
737
 
@@ -796,7 +799,8 @@ corepack pnpm test
796
799
 
797
800
  - 正文可以读,但不建议手改;正文一改,评审分数、check、content hash 都会失效。
798
801
  - `state/` 不要手改;要改就用 `novel_amend`,它要求 `reason` 并写入 journal。
799
- - 要回退阶段用 `novel_rollback`;它会保留正文为参考,清空任务书签收与轮次。
802
+ - 要回退阶段用 `novel_rollback`;它只允许退回当前阶段或更早,会保留正文为参考,清空任务书签收与轮次。
803
+ - plan/review/check 损坏时,status 的 `state_errors` 会指出文件;不要手改。当前阶段晚于重建点时先 `novel_rollback`;已经处在 P2/P4/P6 时直接重新取 brief,再用对应阶段工具重建。
800
804
  - 不要在引擎运行时删 `.engine.lock`;锁由引擎回收,手删可能让两个写者同时进入。
801
805
 
802
806
  ### 10.4 备份与恢复
@@ -810,6 +814,14 @@ corepack pnpm test
810
814
 
811
815
  ## 十一、升级
812
816
 
817
+ ### 11.0 从 0.1.1 升级到 0.1.2
818
+
819
+ 0.1.2 不 bump schema,也不改工具名/参数;但它会主动让三类旧状态暴露出来:
820
+
821
+ 1. **旧 brief 失效**:`context_meta` 进入 digest,升级后第一次调用会要求重新 `novel_brief`;这是预期行为,不是状态损坏。
822
+ 2. **旧 review 无 digest**:0.1.1 之前生成、没有 `pipeline.review_digest` 的 review 会被归档拒绝;重新 `novel_review` 后再归档。
823
+ 3. **损坏的 plan/review/check 不再静默**:status 会显示 `state_errors`;当前阶段晚于 P2/P4/P6 时 `next` 指向 `novel_rollback`,已经到达重建点时直接给出 brief 与阶段修复工具,不需要手改文件。
824
+
813
825
  ### 11.1 升级前
814
826
 
815
827
  1. 看 [CHANGELOG.md](CHANGELOG.md) 和 DSH 的版本要求;
@@ -828,7 +840,7 @@ dsh plugin --profile web add dsh-novel-write-engine@latest
828
840
  也可以固定版本:
829
841
 
830
842
  ```bash
831
- dsh plugin --profile web add dsh-novel-write-engine@0.1.1
843
+ dsh plugin --profile web add dsh-novel-write-engine@0.1.2
832
844
  ```
833
845
 
834
846
  升级后核对:
@@ -870,7 +882,7 @@ corepack pnpm pack
870
882
 
871
883
  ```bash
872
884
  dsh plugin --profile web remove dsh-novel-write-engine
873
- dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.1.1.tgz
885
+ dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.1.2.tgz
874
886
  ```
875
887
 
876
888
  ### 11.5 在 Web / Desktop 里升级
@@ -1050,7 +1062,7 @@ DSH bundle 的 Host 半边在 DSH 进程内执行,不受工作区沙箱限制
1050
1062
 
1051
1063
  ## 十五、已知限制
1052
1064
 
1053
- - **0.1.1 只有中文**:面板、命令、错误、任务书都是中文;没有 `locale/`,不跟随系统语言。
1065
+ - **0.1.2 只有中文**:面板、命令、错误、任务书都是中文;没有 `locale/`,不跟随系统语言。
1054
1066
  - **通过 npm 分发**:安装与升级统一使用 `dsh plugin add`;源码目录和 tarball 用于开发或离线环境。
1055
1067
  - **面板与预设只在 Web/Desktop**:headless / acp / sdk 没有 `agentPresets` 服务,也没有浏览器面板;18 个工具仍可用。
1056
1068
  - **规则包不可运行期替换**:要改词表/阈值,必须改源码、重新构建、重新安装。
@@ -1133,12 +1145,12 @@ tests/ # 单测、集成、falsify、e2e
1133
1145
 
1134
1146
  ### 16.5 当前验证基线
1135
1147
 
1136
- 0.1.1 在 Node 24.19 / DSH 0.2.1-rc.3 上完成过:
1148
+ 0.1.2 在 Node 24.19 / DSH 0.2.1-rc.3 上完成过:
1137
1149
 
1138
- - `corepack pnpm test` 全绿(当前树 348 项);
1150
+ - `corepack pnpm test` 全绿(当前树 379 项);
1139
1151
  - 覆盖率语句/分支/函数/行均达到门槛;
1140
1152
  - `typecheck`、`lint`、`check:hygiene`、`test:isolated`、`build`、`validate:rulepack`、`check:pack`、`check:artifacts`、`check:install` 全绿;
1141
- - `check:host` 在临时 DSH profile 中实测:插件层出现、预设可见、面板未认证 401、认证后 200、`remove` 后层消失。
1153
+ - `check:host` 在临时 DSH profile 中实测:插件层出现、预设可见、面板未认证 401、认证后 200、headless 真实触发 `novel_init` 工具并落盘、`remove` 后层消失。
1142
1154
 
1143
1155
  具体数字会随代码变化;发布前请以重新跑出的结果为准,不要把上面的历史数字当保证。
1144
1156
 
@@ -1150,7 +1162,8 @@ tests/ # 单测、集成、falsify、e2e
1150
1162
  |---|---|
1151
1163
  | [DESIGN.md](DESIGN.md) | 完整设计书:架构、数据模型、规则、门控、事务、面板、预设 |
1152
1164
  | [PLAN.md](PLAN.md) | 0.1.0 实施计划(历史) |
1153
- | [docs/0.1.1-plan.md](docs/0.1.1-plan.md) | 0.1.1 契约收口与证据加固方案 |
1165
+ | [docs/0.1.2-plan.md](docs/0.1.2-plan.md) | 0.1.2 长书可运行性与证据闭环方案 |
1166
+ | [docs/0.1.1-plan.md](docs/0.1.1-plan.md) | 0.1.1 契约收口与证据加固方案(历史) |
1154
1167
  | [docs/tools.md](docs/tools.md) | 18 个工具与命令面速查 |
1155
1168
  | [docs/states.md](docs/states.md) | 状态机、迁移表、轮次与回退 |
1156
1169
  | [docs/rulepack.md](docs/rulepack.md) | 规则包结构、编译器断言、改词表流程 |
package/briefs/P1.md CHANGED
@@ -15,10 +15,12 @@
15
15
  | 字段 | 要求 |
16
16
  |---|---|
17
17
  | `objective` | 一句话说清本章要推进什么,必须是可检验的事件 |
18
- | `constraints` | 本章不能违反的硬约束(人物能力、地点布局、时间线) |
19
- | `characters` | 出场人物及其**本章开始时**的状态 |
20
- | `locations` | 本章用到的地点,布局与容量沿用已锁定值 |
21
- | `continuity_notes` | 与前一章的衔接点、未回收伏笔 |
18
+ | `constraints` | 字符串数组;本章不能违反的硬约束(人物能力、地点布局、时间线) |
19
+ | `characters` | 对象数组,每项 `{name, role, current_state}` 都是非空字符串;写本章开始时的状态 |
20
+ | `locations` | 对象数组,每项 `{name, layout, capacity}`;前两项非空字符串,`capacity` 是有限数字;沿用已锁定值 |
21
+ | `continuity_notes` | 字符串数组;与前一章的衔接点、未回收伏笔 |
22
+
23
+ 数组里的每一项都必须有实际内容;空字符串、字符串冒充数组、对象缺字段都会在落盘前被 `ENGINE_SCHEMA_INVALID` 拒绝。
22
24
 
23
25
  ## 铁律
24
26
 
package/briefs/P4.md CHANGED
@@ -70,5 +70,8 @@
70
70
 
71
71
  - `blocker` 必须修;`advisory` 可改可不改。
72
72
  - 每条 issue 写清 `problem` 与 `fix`,fix 要是可执行动作。
73
+ - `dimension` 必须是本任务书十五维之一(`R-W-01`…`R-W-15` 的实际集合);`location` 必须是「第 N 段」,且 N 在本章实际段落范围内。
74
+ - `blocker` 不能在 P4 或 P5 标记为 `waived`;只能修好后带正文证据标记 `fixed`。
75
+ - 判断不了是否「作者故意」时,先按普通问题处理;0.1.2 不提供自动豁免。
73
76
 
74
77
  完成后:仍有 blocker → P5 修订;全部清零 → P6 校验。
package/briefs/P5.md CHANGED
@@ -5,9 +5,10 @@
5
5
  ## 规则
6
6
 
7
7
  1. 每条 `blocker` issue 必须变成 `fixed`,并给 `evidence`——修订后正文里的**逐字引用**,引擎会回查。
8
- 2. `blocker` 不许 `waived`;只有 advisory 可以带理由豁免。
9
- 3. 改完字数仍要 ≥ {{min_words}},格式要求同 P3。
10
- 4. 改动会抬高或压低评分时,不要自己改分;下一轮 P4 重新评。
8
+ 2. `issues` 里只能改 `status` 与 `evidence`;`dimension`、`location`、`problem`、`fix`、`severity` 是评审归属,改写会被拒绝。新发现留到下一轮 P4。
9
+ 3. `blocker` 不许 `waived`;只有 advisory 可以带理由豁免。
10
+ 4. 改完字数仍要 ≥ {{min_words}},格式要求同 P3。
11
+ 5. 改动会抬高或压低评分时,不要自己改分;下一轮 P4 重新评。
11
12
 
12
13
  ## 提交
13
14
 
package/briefs/P6.md CHANGED
@@ -33,9 +33,15 @@
33
33
 
34
34
  ## 判定
35
35
 
36
+ - 调用时可以传 `scope`:默认 `["content","integrity"]`;只跑 `content` 或只跑 `integrity` 是合法的,空数组/未知值会被拒绝。只跑一类时另一类规则不参与本次 check,但归档仍会重新执行全量机检。
36
37
  - 任一项 `fail` → 校验不过,先重新领取 `novel_brief P6`(check 已改变上下文,旧 digest 会失效),再调用 `novel_revise` 修订并回到 P4 重评(轮次 +1)。
37
38
  - 全过 → 管线进入 `ready_to_archive`,先 `novel_brief P8` 领取终审任务书,再调用 `novel_archive`。
38
39
 
40
+ ## 损坏与恢复
41
+
42
+ - 如果 `novel_status` 返回 `state_errors` 或 `STATE_UNREADABLE`,不要手改文件;按 `next` 指向的 `novel_rollback` 回到 P6,重新取 P6 任务书并 `novel_check`。
43
+ - 如果 `novel_archive` 报 review 没有 `review_digest`,回退到 P4 重新 `novel_review`;不要编辑 `state/pipeline.yaml`。
44
+
39
45
  ## 不许做的
40
46
 
41
47
  - 不许为了让校验过而删掉有信息量的段落。
package/lib/index.d.ts CHANGED
@@ -171,6 +171,12 @@ interface CheckDocument {
171
171
  };
172
172
  verdict: 'pass' | 'fail';
173
173
  }
174
+ /** A state document that exists but cannot be read safely. */
175
+ interface StateError {
176
+ path: string;
177
+ code: 'PLAN_UNREADABLE' | 'REVIEW_UNREADABLE' | 'CHECK_UNREADABLE';
178
+ message: string;
179
+ }
174
180
  /** Word statistics with the single engine-wide counting rule. */
175
181
  interface WordMetrics {
176
182
  total_word_count: number;
@@ -557,6 +563,8 @@ interface GateInput {
557
563
  summaryProvided?: boolean;
558
564
  review: ReviewDocument | null;
559
565
  check: CheckDocument | null;
566
+ /** When set, result-bearing gates run only the named check scopes. */
567
+ scope?: string[];
560
568
  semantic: SemanticItem[];
561
569
  proof: ReadingProof | null;
562
570
  rounds: RoundCounters;
@@ -608,6 +616,8 @@ interface StatusReport {
608
616
  stage: Stage;
609
617
  rounds: RoundCounters;
610
618
  blocking: BlockingItem[];
619
+ /** plan/review/check files that exist but cannot be read safely. */
620
+ state_errors: StateError[];
611
621
  metrics: WordMetrics | null;
612
622
  next: {
613
623
  tool: string;
@@ -623,6 +633,7 @@ interface AdviceReport {
623
633
  args: Record<string, unknown>;
624
634
  reason: string;
625
635
  blocking: BlockingItem[];
636
+ state_errors: StateError[];
626
637
  }
627
638
  /** One history row derived from the journal. */
628
639
  interface AuditRow {
@@ -1140,6 +1151,7 @@ declare class EngineService {
1140
1151
  args: Record<string, unknown>;
1141
1152
  reason: string;
1142
1153
  blocking: BlockingItem[];
1154
+ state_errors: StateError[];
1143
1155
  }>>;
1144
1156
  getBrief(input: BriefInput): Promise<OpResult<{
1145
1157
  stage: string;
@@ -1280,6 +1292,20 @@ declare class EngineService {
1280
1292
  private roundsLimitBlock;
1281
1293
  /** Pipeline blockers plus budget exhaustion, so status/panel cannot say "all clear". */
1282
1294
  private effectiveBlocking;
1295
+ /**
1296
+ * A review that exists but cannot be tied to the pipeline digest would let a
1297
+ * hand-edited review pass archive. Archive already fails closed; status and
1298
+ * next must surface the same repair path instead of pointing at the archive
1299
+ * command forever.
1300
+ */
1301
+ private reviewDigestProblem;
1302
+ private stateErrors;
1303
+ /** The earliest rebuild point for the current state damage. */
1304
+ private recoveryFor;
1305
+ /** Never point at a stage later than the current one; rollback only moves backward. */
1306
+ private clampRollbackTarget;
1307
+ /** State damage that makes this operation unsafe to start. */
1308
+ private stateGateBlock;
1283
1309
  /** Whether the stored brief still signs the current snapshot. */
1284
1310
  private briefIsCurrent;
1285
1311
  /** Arguments valid for the tool `STAGE_NEXT` recommends at this stage. */
@@ -1296,6 +1322,8 @@ declare class EngineService {
1296
1322
  private assertChapterParameter;
1297
1323
  private assertChapter;
1298
1324
  private load;
1325
+ /** Read a review/check without letting one corrupt file wedge every read. */
1326
+ private recoverableDoc;
1299
1327
  private mutate;
1300
1328
  private invalidateReplay;
1301
1329
  private emptySnapshot;
@@ -1342,4 +1370,4 @@ declare const Config: Schema<Config>;
1342
1370
  * created lazily per project root.
1343
1371
  */
1344
1372
  declare function apply(ctx: Context, config: Config): void;
1345
- export { AdviceReport, ArchiveHandoff, AuditRow, BlockingItem, BriefDocument, BriefLibrary, BriefStage, ChapterPlanInput, ChapterRecord, ChapterStatusRow, ChapterSummary, ChaptersDocument, CharacterDelta, CharactersDocument, CheckDocument, Config, Deduction, DeltaAction, DiffReport, DraftInput, ERROR_CODES, EngineBlockedError, EngineError, EngineFaultError, EngineInputError, EngineService, ErrorCode, ExportChapter, ExportKind, ForeshadowDelta, ForeshadowsDocument, GENRES, GateInput, GateOptions, GateResult, Genre, HandoffDocument, LocksDocument, MachineMetrics, NovelProject, OPERATIONS, OpResult, Operation, PLATFORMS, PanelChapterRow, PanelChaptersDto, PanelDraft, PanelGatesDto, PanelSnapshot, PanelSummaryDto, PipelineState, Platform, ReadingProof, ReadingProofReference, RelationshipDelta, RelationshipsDocument, ReviewDocument, ReviewInput, ReviewIssue, RevisionInput, RoundCounters, SCENE_TYPES, SCHEMA_VERSION, SceneType, ScoreDimension, SemanticItem, Severity, Stage, StateDelta, StatusReport, TimelineDelta, TimelineDocument, Violation, Warning, WordMetrics, WorldDelta, WorldDocument, WorldPlanInput, applicableGates, apply, blockedError, briefStageFor, chapterHeading, evaluateGates, faultError, gateName, inject, inputError, loadRulepack, name, parseParagraphLocation, phaseStrip, projectChapter, projectChapters, projectGates, projectSummary, renderBlurb, renderCover, renderEpubChapter, renderMarkdown, renderPlainText, verifyReference };
1373
+ export { AdviceReport, ArchiveHandoff, AuditRow, BlockingItem, BriefDocument, BriefLibrary, BriefStage, ChapterPlanInput, ChapterRecord, ChapterStatusRow, ChapterSummary, ChaptersDocument, CharacterDelta, CharactersDocument, CheckDocument, Config, Deduction, DeltaAction, DiffReport, DraftInput, ERROR_CODES, EngineBlockedError, EngineError, EngineFaultError, EngineInputError, EngineService, ErrorCode, ExportChapter, ExportKind, ForeshadowDelta, ForeshadowsDocument, GENRES, GateInput, GateOptions, GateResult, Genre, HandoffDocument, LocksDocument, MachineMetrics, NovelProject, OPERATIONS, OpResult, Operation, PLATFORMS, PanelChapterRow, PanelChaptersDto, PanelDraft, PanelGatesDto, PanelSnapshot, PanelSummaryDto, PipelineState, Platform, ReadingProof, ReadingProofReference, RelationshipDelta, RelationshipsDocument, ReviewDocument, ReviewInput, ReviewIssue, RevisionInput, RoundCounters, SCENE_TYPES, SCHEMA_VERSION, SceneType, ScoreDimension, SemanticItem, Severity, Stage, StateDelta, StateError, StatusReport, TimelineDelta, TimelineDocument, Violation, Warning, WordMetrics, WorldDelta, WorldDocument, WorldPlanInput, applicableGates, apply, blockedError, briefStageFor, chapterHeading, evaluateGates, faultError, gateName, inject, inputError, loadRulepack, name, parseParagraphLocation, phaseStrip, projectChapter, projectChapters, projectGates, projectSummary, renderBlurb, renderCover, renderEpubChapter, renderMarkdown, renderPlainText, verifyReference };