dsh-novel-write-engine
Verifieddsh-novel-write-engine · v0.2.2 · MIT · Web UI
Novel writing engine for DeepSeek Harness: state machine, gates, rulepacks and ledgers moved from prompts into code.
Install
dsh plugin add dsh-novel-write-engine Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
dsh-novel-write-engine
把小说创作的「状态、门禁、规则、账本」从提示词搬进代码的 DeepSeek Harness 插件。
它不是一个提示词合集,也不是独立的写作软件。它把「这一章处于什么阶段、下一步只能做什么、正文是否达标、归档要核销哪些实体」变成可执行、可回滚、可审计的引擎;模型负责写,引擎负责裁决和记账。
0.2.0 起,它同时管理整本书:书级蓝图 → 卷/章大纲 → 世界观设定集 → 单章 P1–P9 流水线 → 归档回写大纲 → 报告/体检/搜索/面板。大纲可以从 Markdown/YAML/JSON 导入,也可以由模型按章卡结构生成;严格模式下 P2/P3 会按章卡校验标题、场景、字数与 cast。
0.2.2 把多项目选择从“进程最近一次工具调用”改为会话级持久绑定:显式 project_root 成功后会记住当前 DSH 会话;同一工作区的 A/B 会话不再串书。面板 v4 增加项目选择器与 choose/missing 状态,/novel scan 用于发现项目,/novel resume 与面板复制按钮共用同一份续写指令;项目被删除/移动/替换时 fail-closed,不静默换书。
当前版本:0.2.2 · 中文界面 · MIT
宿主范围:DSH
>=0.2.1-rc.2 <0.3.0-0;Node>=24.9.0。
目录
- 一、它解决什么问题
- 二、功能全貌
- 三、兼容性与前置条件
- 四、先装好 DSH 宿主
- 五、安装本插件
- 六、验证安装
- 七、五分钟快速开始
- 八、使用方式
- 九、配置
- 十、数据、备份与状态
- 十一、升级
- 十二、卸载
- 十三、故障排查
- 十四、安全与边界
- 十五、已知限制
- 十六、开发与验证
- 十七、文档地图与许可
一、它解决什么问题
网文连载最常见的失败,不是「模型不会写」,而是:
- 写着写着忘了这是第几章、上一章结尾是什么、哪些伏笔还没回收;
- 每章的字数、格式、评分标准靠模型自己记,越写越松;
- 评审只给一个「87 分」,指不出扣分在哪一段,也无法核对;
- 归档时角色、地点、时间线、关系、伏笔只更新一半,下一章开始自相矛盾;
- 多个项目、多个会话之间状态漂移,换一个会话就像换了一个人。
本插件把这些东西收进一个 单一写入口 EngineService:
模型 / 用户
│
├── 28 个 novel_* 工具
├── 5 条 /novel* 命令(含 outline/guide/report/doctor/search 子命令)
├── 只读侧边栏「网文工坊」
└── 7 份阶段任务书(briefs)
│
▼
EngineService(唯一写入口)
│
├── 13 条门控 PG-01 ~ PG-13
├── 15 维评分 / 满分 150
├── 规则包 rulepacks/default.yaml
├── 书级蓝图/大纲/世界观(outline/)
├── 事务化归档 + journal 审计
└── chapters/ 正文 + state/ 影子账本
最重要的架构约束:工具、命令、面板、任务书都不能直接读改写项目文件;所有写操作都经过 EngineService。正文 chapters/chapter-NNN.md 是唯一真实来源,state/*.yaml 是引擎维护的影子层,不允许反向手改。
它不是什么
- 不是独立的桌面写作应用,不能脱离 DSH 运行。
- 不是「装完就自动写完整本书」的生成器;它管流程、门禁和状态,正文仍由模型写。
- 不是独立 CLI;必须作为 DSH 插件安装到某个 profile 才能使用。
- 不提供云端同步、账号体系、在线书城或多人协作。
- 0.2.x 仍是中文界面与中文任务书,没有
locale/,也不读取系统语言。 - 不提供云端同步、多人协作、RAG/向量库或富文本编辑器;整书规划与单章流水线都在本地 YAML/Markdown 上完成。
二、功能全貌
| 能力 | 说明 |
|---|---|
28 个 novel_* 工具 |
书级蓝图/大纲/世界观 + 单章流水线 + 报告/体检/搜索/引导/重开/备份恢复 |
5 条 /novel* 命令 |
状态、下一步、统计、导出、隐藏操作;/novel 内含 outline/guide/report/doctor/search 子命令 |
| 1 个侧边栏面板「网文工坊」 | 只读;Hero、统计、全书规划、世界观、质量趋势、健康、最近活动、九阶段轨、章节卡、门控区 |
| 1 个内置 Agent 预设「网文工坊」 | 28 个工具全开,不挂载 bash / 文件写入工具;会话开始后不能切换 |
| 1 个入口技能 | 告诉模型什么时候该用引擎、哪些写入口是唯一的 |
| 13 条门控 | 任务书、阶段、字数、格式、摘要、场景类型、大纲对齐、评分、问题清零、阅读证明、一致性、轮次、归档原子性 |
| 15 维评分 | 满分 150,默认过关线 120;分数必须逐项可核对 |
| 事务化归档 | staging → 校验 → 备份 → pending journal → rename → 读回 → committed journal |
| 规则包外置 | 词表、格式、标点、语义、跨章阈值都在 rulepacks/default.yaml,代码只执行 |
| 六种导出 | Markdown、纯文本、EPUB 3、大纲、世界观、书级提案;正文导出附 cover.svg 与 blurb.txt |
| 整书规划层 | 书级蓝图、卷结构、章卡(严格模式)、世界观设定集;支持 Markdown/YAML/JSON 导入 |
| 可观测性 | novel_status 书级摘要、novel_report、novel_doctor、novel_search、panel v4、journal 活动 |
| 多项目注册表 | stateDir/projects.yaml 记录已知项目与面板默认 active;不影响项目目录 |
| 运行期依赖极少 | 只有 yaml 一个运行时依赖;Host 侧不访问外部网络、不调用外部 API、不读环境变量里的密钥 |
关键设计
- 状态机而不是自由对话:阶段只能按合法迁移前进;不合法操作返回
ENGINE_STAGE_ORDER并告诉你当前可用操作。 - 门控先于写盘:写初稿、修订、归档都是先校验、后落盘;坏稿不会进入项目。
- 评分是算术,不是感觉:
total = 150 - Σdelta,每个维度score = max - Σdelta,不闭合就拒绝。 - 阅读证明:P4/P5 要提交三段逐字引用,P6 会重新核验这份证明;开头/结尾按实际段落判定,防「没读就评」。
- 归档是一次事务:P7 状态同步、P8 终审、P9 索引与交接不是三个可以半途而废的步骤。
- 模型不分配 ID:只写
key,引擎分配FS-*/TE-*/RL-*等编号并回执映射。 - 可控修订:
novel_amend是唯一的状态手工修改入口,必须带原因并写入 journal;novel_rollback保留正文供参考。
九个阶段
| 阶段 | 名称 | 谁执行 | 产物 |
|---|---|---|---|
| P1 | 世界观约束 | 模型 | plans/chNNN.world.yaml |
| P2 | 章节计划 | 模型 | plans/chNNN.chapter.yaml |
| P3 | 初稿 | 模型 | chapters/chapter-NNN.md |
| P4 | 评审 | 模型 | reviews/chNNN.review.yaml |
| P5 | 修订 | 模型(有 blocker 时) | 覆盖正文 |
| P6 | 一致性校验 | 引擎机检 + 模型语义项 | checks/chNNN.check.yaml |
| P7 | 状态同步 | 引擎事务 | state/*.yaml |
| P8 | 终审 | 引擎事务 | 三端一致性报告 |
| P9 | 归档 | 引擎事务 | 章节索引 + 交接 |
P7/P8/P9 在 novel_archive 一次事务里完成。单章归档后状态是 done;下一章仍从 P1 开始。只有项目配置的 total_chapters 全部归档,面板才显示「全书完成」。
十三道门控
| 编号 | 名称 | 管什么 |
|---|---|---|
| PG-01 | BRIEF_REQUIRED |
当前阶段任务书已签发,digest 匹配 |
| PG-02 | STAGE_ORDER |
只能提交当前阶段允许的产物 |
| PG-03 | WORD_COUNT |
字数达到项目下限 |
| PG-04 | FORMAT |
段落、标点、Markdown、标题等格式 blocker 为零 |
| PG-05 | SUMMARY_SCHEMA |
十章摘要的十个字段齐全且类型正确 |
| PG-06 | SCENE_TYPE |
场景类型合法,节奏约束满足 |
| PG-13 | OUTLINE_ALIGNMENT |
有章卡时标题/场景/目标字数/cast 必须一致;严格模式无卡也拒绝;归档卡不可改 |
| PG-07 | SCORE |
十五维齐全、算术闭合、总分达到 minScore |
| PG-08 | ISSUES_CLEARED |
所有 blocker issue 已修复并带正文证据 |
| PG-09 | READING_PROOF |
三段逐字引用能在正文对应位置找到;开头/结尾按实际段落判定 |
| PG-10 | CONSISTENCY |
伏笔、时间线、资源、关系、重复段落等跨章对账 |
| PG-11 | ROUNDS |
评审/修订、校验/修订均不超过 3 轮 |
| PG-12 | ARCHIVE_ATOMIC |
归档事务三端一致且读回验证通过 |
门控按固定顺序求值,并且收集全部失败项,不是遇到第一个就返回——这样模型可以一次改完。
十五维评分
| 组 | 维度 |
|---|---|
| A 核心叙事(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 |
| B 商业指标(45) | R-W-11 元描写与视角侵入 10 · R-W-13 信息增量 15 · R-W-14 钩子质量 10 · R-W-15 期待值兑现 10 |
| C 格式硬性(15) | R-W-06 段落长度 4 · R-W-07 去 AI 味 4 · R-W-08 硬性禁令 4 · R-W-09 字数 2 · R-W-10 标题 1 |
合计严格 150。默认 minScore = 120,可在配置里改;它是 PG-07 的唯一过关线。
类型与平台
- 类型(12):玄幻修仙、都市现代、西方奇幻、悬疑推理、科幻、游戏系统、历史架空、无限流、轻小说、军事、末世流、言情。
- 平台(4):
fanqie(番茄)、qidian(起点)、qimao(七猫)、jinjiang(晋江)。
平台只决定规则包里的默认字数区间与对话比例;项目 novel.yaml 可以覆盖自己声明的那部分。
三、兼容性与前置条件
| 项目 | 要求 |
|---|---|
| DSH | >=0.2.1-rc.2 <0.3.0-0;由 package.json 的 engines.dsh 声明,安装与启动都会检查 |
| Node.js | >=24.9.0 |
| pnpm | CLI 安装/卸载插件需要;建议 11.x(本仓库开发基线为 11.28.9) |
| 宿主形态 | Web(面板 + 预设)、Desktop(面板 + 预设,插件由桌面壳管理)、headless(只有工具/命令,无面板/预设) |
| 磁盘 | 项目根目录可写;默认 stateDir 可写 |
| 网络 | 安装时需要访问 npm / Git 托管;运行期 Host 侧不访问外部网络,Web 客户端只向宿主面板发同源 GET |
| 语言 | 0.2.x 仅中文 |
检查命令:
node --version # 应 >= 24.9.0
dsh --version # 应 >= 0.2.1-rc.2,且 < 0.3.0-0
pnpm --version # CLI 安装插件时需要
如果 dsh 不在 PATH 里,可以用 npx @deepseek-ai/dsh 代替下文的 dsh。但 dsh plugin 仍然需要本机有 pnpm。
本仓库固定 pnpm 11.28.9。若本机版本不符,先执行
corepack prepare [email protected] --activate,或直接把下文的pnpm换成corepack pnpm。
四、先装好 DSH 宿主
如果你已经在使用 DSH Web,并且 dsh --version 满足要求,可以直接跳到第五节。
方式 A:npx 直接运行(最快)
# 先确保有 pnpm,因为后面安装插件要用
corepack enable
corepack prepare [email protected] --activate
# 启动 Web UI;默认 http://127.0.0.1:3080
npx @deepseek-ai/dsh web
不想自动打开浏览器:
npx @deepseek-ai/dsh web --no-open
方式 B:全局安装 CLI
npm install -g @deepseek-ai/dsh
dsh web
升级:
npm update -g @deepseek-ai/dsh
方式 C:从源码运行
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
corepack pnpm install
corepack pnpm run build
corepack pnpm dsh web
方式 D:Desktop
从 DSH 官方发行页安装 Desktop。Desktop 使用自己保留的 desktop profile,插件应在 Desktop 的「插件」页安装,不要用 dsh plugin --profile web 去改装 Desktop——那是另一个 profile。
DSH 的 profile 与 DSH_HOME
DSH 把不同应用形态放在 profile 里:
| 启动方式 | profile | 面板 | 内置预设 |
|---|---|---|---|
dsh web |
web |
有 | 有 |
| Desktop | desktop |
有 | 有 |
dsh headless |
headless |
无 | 无 |
dsh --profile <名字> web |
<名字> |
取决于该 profile | 取决于该 profile |
profile 默认位于:
~/.dsh/profiles/<profile>/
Windows 为 %USERPROFILE%\.dsh\profiles\<profile>\。如果设置了 DSH_HOME,则以 $DSH_HOME/profiles/<profile>/ 为准。
结论:插件必须装进你实际启动的那个 profile。装在 web、却用 --profile myweb 启动,是不会出现面板和预设的。
五、安装本插件
前置条件:DSH 已安装并满足版本要求,本机有 pnpm。
5.1 从 npm 安装(推荐)
corepack enable
corepack prepare [email protected] --activate
# 安装最新版到 web profile
dsh plugin --profile web add dsh-novel-write-engine
固定版本:
dsh plugin --profile web add [email protected]
dsh 不在 PATH 时,用 npx @deepseek-ai/dsh 代替命令开头的 dsh。
安装命令会下载 npm 包、写入 ~/.dsh/profiles/web 的依赖,并把插件加入该 profile 的 dsh.profile.bundles。不要用 npm install 代替:它只会下载包,不会把插件加入 profile。
web 是 dsh web 使用的默认 profile。自定义 profile 把 web 换成实际名字;Desktop 使用自己的 desktop profile,请在桌面端插件页安装。
安装后重启 DSH,或刷新 Web 页面。
5.2 从源码目录安装(开发)
git clone https://github.com/ThzxxArt/dsh-novel-write-engine.git
cd dsh-novel-write-engine
corepack enable
corepack prepare [email protected] --activate
corepack pnpm install
corepack pnpm build
# 把当前目录装进 web profile
dsh plugin --profile web add "$PWD"
PowerShell:
git clone https://github.com/ThzxxArt/dsh-novel-write-engine.git
cd dsh-novel-write-engine
corepack enable
corepack prepare [email protected] --activate
corepack pnpm install
corepack pnpm build
dsh plugin --profile web add (Get-Location).Path
源码目录安装是 link 关系,不是拷贝:profile 的 dependencies 里出现的是 link:/你的/源码目录。之后修改 src/ 必须重新 corepack pnpm build 并重启 DSH;否则 DSH 仍加载旧的 lib/。
5.3 从 tarball 安装(离线)
在能构建的机器上:
git clone https://github.com/ThzxxArt/dsh-novel-write-engine.git
cd dsh-novel-write-engine
corepack pnpm install
corepack pnpm build
corepack pnpm pack
会得到类似:
dsh-novel-write-engine-0.2.2.tgz
把这个 tarball 复制到目标机器,放在一个稳定、不会随手删除的路径,然后:
dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.2.2.tgz
tarball 安装不会运行源码构建,也不会要求 allowBuilds;包内已经包含 lib/、rulepacks/、briefs/、skills/、presets/ 和两层 patch。它是最接近「发布产物」的安装方式。
升级时用新的 tarball 重装;旧的 tarball 可以留档,便于回滚。
5.4 从 DSH 插件页安装
适用于你不想在终端里操作,或者 DSH 跑在另一台机器上。插件页既能装 npm 包名,也能装本地目录或 tarball;路径必须是 DSH 宿主 能访问的路径。
- 打开 DSH Web,左侧栏进入 插件。
- 点 添加插件(或旁边的箭头 → 安装第三方插件)。
- 在包名字段填入以下任一形式:
- npm 包名:
dsh-novel-write-engine - 精确版本:
[email protected] - 源码目录:
/absolute/path/to/dsh-novel-write-engine - tarball:
/absolute/path/to/dsh-novel-write-engine-0.2.2.tgz
- npm 包名:
- npm 包名从 npm 官方源安装;本地目录和 tarball 直接使用宿主路径。
- 点 安装,等待完成。
- 如果出现 立即启用,点它;否则安装后到「已安装插件」里把 dsh-novel-write-engine 打开。
- 刷新页面;新开一个会话。
Desktop 的插件页管理的是
desktopprofile,和 CLI 的webprofile 是两套依赖、两套锁文件。不要混用。
六、验证安装
按顺序做这四步,任何一步失败都能定位到不同层。
1. 看配置层
dsh --profile web --dump-config | grep -A8 '# == dsh-novel-write-engine'
有 # == dsh-novel-write-engine 说明 bundle 层已合成。没有则是装错 profile,或安装没有成功。
2. 看侧边栏
重启 DSH(或刷新页面)后,左侧栏应出现 网文工坊。
- 没有入口:当前不是 Web/Desktop profile,或 client bundle 没有加载。
- 入口在但页面 404/空白:检查 DSH 版本、浏览器缓存,重启后再试。
3. 看会话预设
新开一个会话,在预设选择器里应出现 网文工坊。
- 没有预设:你用的是 headless / acp / sdk profile,它们没有
agentPresets服务;工具仍然可用。 - 有预设但选不了:看插件页是否已启用;看 DSH 版本是否满足范围。
4. 看工具与命令
在任意会话里输入:
/novel
应返回状态卡或「还没有项目」的提示。也可以直接对模型说:
列出你当前可用的 novel_* 工具。
应能看到 28 个(toolsMode=core 时只有 10 个,见第八节)。
七、五分钟快速开始
1. 新开一个「网文工坊」会话
左侧栏 → 新建会话 → 预设选 网文工坊。
这个预设的工具是「小说专用」的:有 28 个 novel_* 工具、任务书、网页、待办、子智能体等,但不挂载 bash / 文件写入工具。正文只能经引擎写。
2. 直接说人话
例如:
在 /home/me/novels/星海 开一本都市现代、番茄平台的书,
书名《星海旧梦》,作者是我,每章 2200–2800 字,共 120 章。
先做全书蓝图、第一卷大纲和世界观设定,再写第一章的世界观约束和章节计划。
模型会调用 novel_init 建项目,然后按 novel_guide 的提示做书级规划;也可以跳过蓝图直接写第一章,严格大纲是可选开关。0.2.2 推荐顺序:
novel_init
→ novel_blueprint(梗概/主题/基调/视角/卷结构)
→ novel_outline(章卡)或 novel_outline_import(Markdown/YAML/JSON)
→ novel_worldbook(设定/规则/势力/地点/角色/术语/前史)
→ novel_brief P1 …
3. 等价的 novel_init 参数
如果你想自己确认字段:
{
"title": "星海旧梦",
"genre": "都市现代",
"platform": "fanqie",
"author": "你的笔名",
"description": "一句话简介",
"words_per_chapter": [2200, 2800],
"total_chapters": 120,
"premise": "旧案重启,档案员被迫入局。",
"strict_outline": true,
"project_root": "/home/me/novels/星海"
}
premise、logline、themes、tone、pov、audience、selling_points、ending 与 strict_outline 都是可选的书级种子;不填也能开书,之后用 novel_blueprint 补。
genre 必须是 12 类之一,platform 必须是 fanqie / qidian / qimao / jinjiang 之一。对 novel_init,省略 project_root 时只使用配置 projectRoot,不读会话绑定、工作区或 active;创建成功后才绑定当前会话。其他工具省略 project_root 时按 0.2.2 的四层顺序解析:当前 DSH 会话绑定 → 会话 cwd 中唯一项目 → 唯一注册项目/配置 projectRoot;有多个项目且无法唯一确定时返回 ENGINE_PROJECT_AMBIGUOUS,需要 /novel use 或显式 project_root。active 只影响面板默认,不再静默决定 Agent 的工具项目。
4. 一章的标准调用顺序
| 步骤 | 调用 | 说明 |
|---|---|---|
| 0 | novel_blueprint / novel_outline |
书级蓝图与当前章卡(严格模式必须) |
| 1 | novel_brief P1 |
领取 P1 世界观任务书,签收 digest |
| 2 | novel_plan_world |
提交世界观约束 |
| 3 | novel_brief P2 |
领取 P2 章节计划任务书 |
| 4 | novel_plan_chapter |
提交本章计划 |
| 5 | novel_brief P3 |
领取 P3 初稿任务书 |
| 6 | novel_write_draft |
提交正文;格式/字数/摘要不过则整体拒绝 |
| 7 | novel_brief P4 |
领取 P4 评审任务书 |
| 8 | novel_review |
十五维评分 + 三段阅读证明 |
| 9 | 有 blocker:novel_brief P5 → novel_revise |
修订后回到 P4 重评 |
| 10 | 无 blocker:novel_brief P6 → novel_check |
机检 + 五个语义项(含 POV) |
| 11 | novel_brief P8 |
领取终审任务书 |
| 12 | novel_archive |
必须带 state_delta,一次事务归档 |
| 13 | novel_export md |
或 txt / epub / outline / worldbook / proposal |
关键点:
- 每一步提交前都要先领任务书,PG-01 会检查 digest。
novel_status/novel_pipeline在任务书缺失或过期时会先返回novel_brief,不会让你直接撞 PG-01。 - 坏状态不是死锁:plan/review/check/worldPlan、八个 ledger 与 outline/worldbook 损坏时,status 返回
state_errors与STATE_UNREADABLE;plan/review/check 走 rollback/阶段重建,ledger/project/规划文档则novel_state返回raw、next指向novel_amend。novel_amend会为当前所有不可读状态文档豁免 journal 的既有 hash,并在同一事务里写目标文档与state/pipeline.yaml(不是只写一个文件);其他可读文件的外部改动仍拒绝。P6 的 check 损坏优先于旧 revision 阻塞;归档前review_digest缺失/不匹配会回退 P4。损坏或丢失的novel.yaml也走同一条PROJECT_UNREADABLE修复路径。 - 计划先校验再落盘:P1 的
constraints/characters/locations/continuity_notes有形状校验;P2 的标题长度读 rulepack、5–8 个非空节拍、narrator、opening/ending 都会在服务边界拒绝。P2 可选cast(1–8 人),名字必须来自 P1 世界计划或角色台账。 - 上下文有预算且不裁主角团:每个 brief 的
context.context_meta给出budget/used/truncated/omitted;P1world_plan的目标/约束/连续性说明、P3/P4/P5 的本章活跃角色完整卡、P6 的active_cast与正文/当前 plan/review/check/摘要受保护;world_plan.characters/locations是可裁剪的候选名单,other_characters只放压缩索引。裁剪会参与 digest,升级后旧 brief 需要重新领取。 - 长书读口:
novel_state {kind:"chapters"}默认返回紧凑索引,include_summary/chapter_range按需取;panel 只送最近 30 行。归档继承上一章 handoff 的 volume/volume_name;act/act_progress 从上一章推进,handoff.act/act_progress可覆盖。 ready_to_archive在 P8 任务书当前后,next.tool才返回novel_archive;P5/P6 有阻塞时返回novel_revise。novel_review的total是必填的,必须等于150 - Σdelta;三段阅读证明必须逐字来自正文,开头/结尾按实际段落判定;issue 的dimension必须是当前十五维之一,location必须是本章实际段落。novel_check的semantic恰好五个语义项(L2-SCENE-ANCHOR/L2-CHARACTER-STATE/L2-CAUSALITY/L2-VOICE/L2-POV),每项带至少 8 字、五条互不相同且来自不同句子的正文引用;scope默认content + integrity,只跑一类时另一类不参与本次 check,且通过后仍停留 P6(CHECK_SCOPE_PARTIAL),不能归档。novel_archive的state_delta要逐实体核销角色、伏笔、时间线、世界、关系;新伏笔标题必须出现在正文,no_change也要写原因;review 存在但review_digest缺失时拒绝归档,需重新novel_review。- 正文改动后,旧的评审分数和 check 会失效;不要试图手工改
state/绕过。
5. 看面板
归档后打开左侧 网文工坊:
- Hero:书名、类型、平台、当前章、阶段;
- 统计:已归档章节、总字数、平均分、待处理门控;
- 全书规划:蓝图/严格模式、章卡进度、全部卷(滚动列表)、世界观计数、质量趋势、健康度;
- 九阶段轨;
- 下一步卡与“复制续写指令”;
- 章节卡、门控区与最近活动。
面板每 15 秒静默同步一次,也可以点刷新;它只读,所有写操作仍在对话/工具里。
八、使用方式
8.1 三种会话形态
| 形态 | 怎么进 | 工具 | 写文件能力 | 面板/预设 |
|---|---|---|---|---|
| 内置预设「网文工坊」 | 新会话选预设 | 28 个全开 | 不挂 bash/fs 写入工具,正文只经引擎 | 有 |
| 普通会话 | 任意标准会话 | 28 个工具在根层注册 | 可能还有 bash/fs;引擎保证会被绕过 | 有面板,无专用预设 |
| headless / 自动化 | dsh --profile headless "..." |
28 个(或 core 10 个) | 取决于该 profile | 无面板、无预设 |
要用「引擎保证」就用「网文工坊」预设。 普通会话里,模型仍然可以用文件工具直接改 state/ 或正文;那时你得到的是「引擎工具 + 人工操作」的混合状态,事务、门控、审计都不再完整。
预设是会话类型,会话开始后不能切换。要换形态就新开一个会话。
8.2 28 个工具
| 工具 | 阶段 | 做什么 | 写盘 |
|---|---|---|---|
novel_init |
— | 建项目:novel.yaml + state/ + outline/ + 目录 |
是 |
novel_status |
任意 | 当前活跃章、阶段、轮次、阻塞项、state_errors、下一步;chapter 只用于字数查询 |
项目正文否;显式 root 写绑定 |
novel_brief |
P1–P6 / P8 | 领取当前活跃章的任务书,返回 fields、context;context.world_plan 与 context.context_meta 在 context 内,并记录 digest |
仅任务书签收 |
novel_plan_world |
P1 | 提交世界观约束;数组/对象形状在服务边界校验 | 是 |
novel_plan_chapter |
P2 | 提交章节计划;标题长度读 rulepack、5–8 个节拍、opening/ending 非空;可选 cast 1–8 人 |
是 |
novel_write_draft |
P3 | 提交初稿;格式/字数/摘要不过整体拒绝 | 是 |
novel_review |
P4 | 十五维评分、问题清单、三段阅读证明;issue 维度/段落和 blocker waived 会被拒绝 | 是 |
novel_revise |
P5/P6 | 提交修订;支持整章 content 或 patch:{expected_hash,edits};blocker 必须有正文证据,不能降级或 waived |
是 |
novel_check |
P6 | 机检 + 五个语义一致性项;advisories 与 blocker 分开,可用 acknowledge 记录知悉;单 scope 不推进归档 |
是 |
novel_archive |
P7–P9 | 事务归档;必须带 state_delta;旧 review 无 digest 时拒绝 |
事务 |
novel_word_count |
任意 | 按引擎唯一口径数字数 | 否 |
novel_state |
任意 | 读账本、计划、评审、检查、handoff、outline/worldbook、history/backups/briefs;chapters 默认紧凑,支持 include_summary/chapter_range;损坏 ledger 返回 raw |
否 |
novel_amend |
任意 | 带原因修订 novel.yaml、八个 ledger 或 outline/worldbook,带不变量与单目标 repair |
是,入 journal |
novel_rollback |
任意 | 只退回当前阶段或更早,保留正文供参考 | 是 |
novel_diff |
任意 | 与上次归档备份或两段文本比较 | 否 |
novel_export |
任意 | 导出 md / txt / epub / outline / worldbook / proposal |
导出目录 |
novel_audit |
任意 | 读追加式 journal 审计记录,含被拒 attempt;支持 chapter/op/status/since/until/cursor | 否 |
novel_pipeline |
任意 | 「下一步该做什么」的建议 | 否 |
novel_blueprint |
任意 | 写书级蓝图:梗概、主题、基调、视角、读者、卖点、结局、卷结构 | 是 |
novel_outline |
任意 | 写卷/章卡;严格模式、归档卡保护、归档章自动回填 | 是 |
novel_outline_import |
任意 | 从 Markdown / YAML / JSON 导入大纲;dry_run 先预览 |
可选 |
novel_worldbook |
任意 | 增量更新世界观设定集(设定/规则/势力/地点/角色/术语/前史) | 是 |
novel_search |
任意 | 跨正文、摘要、大纲、世界观、台账搜索,带章号/段落号/片段 | 否 |
novel_doctor |
任意 | 项目体检:项目/流水线/状态、journal、正文 hash、孤立正文、大纲覆盖与漂移、当前阶段产物、锁、备份、目标进度、下一步 | 否 |
novel_report |
任意 | 全书报告:进度、大纲、世界观、质量、节奏、角色、伏笔、时间线、关系、活动 | 否 |
novel_guide |
任意 | 上手引导:当前状态、已完成步骤、下一步工具、命令与提示;无项目也能用 | 否 |
novel_reopen |
已归档章 | 从归档备份把紧邻的上一章重开到 P3;必须带非空 reason,活动章未开始、备份存在时才允许 |
是 |
novel_restore |
活动章 | 从带 manifest 的 txid 备份恢复正文/计划/评审/校验;已归档章拒绝,先 novel_reopen |
是 |
工具失败时统一返回:
[ENGINE_XXX] 说明 — 可操作建议
三类错误:
- 改参数:
ENGINE_SCHEMA_INVALID、ENGINE_STAGE_ORDER、ENGINE_PROJECT_NOT_FOUND、ENGINE_PROJECT_EXISTS; - 改正文:
ENGINE_GATE_BLOCKED、ENGINE_SCORE_MISMATCH、ENGINE_READING_PROOF_INVALID、ENGINE_DELTA_UNVERIFIED; - 查环境:
ENGINE_SCHEMA_TOO_NEW、ENGINE_PATH_ESCAPE、ENGINE_LOCK_TIMEOUT、ENGINE_TXN_ABORTED、ENGINE_RULEPACK_INVALID。
8.3 五条命令
注册的命令是 5 条:
| 命令 | 作用 |
|---|---|
/novel |
不带参数 = 状态;/novel status 同义 |
/novel-next |
下一步工具与理由 |
/novel-stats |
章节数、总字数、平均分、未回收伏笔、规则包版本 |
/novel-export |
导出 md / txt / epub / outline / worldbook / proposal |
/novel-admin |
/novel-admin <op> <json> 执行隐藏/运维操作 |
/novel 还有子命令:
/novel next
/novel stats
/novel outline
/novel guide
/novel report
/novel doctor
/novel search <关键词>
/novel export md|txt|epub|outline|worldbook|proposal
/novel projects
/novel current
/novel use <path|title|.>
/novel unbind
/novel scan [--register]
/novel resume
/novel admin
/novel admin novel_state {"kind":"pipeline"}
toolsMode=core 时只注册 10 个高频工具:
novel_init, novel_status, novel_guide, novel_brief, novel_outline,
novel_write_draft, novel_review, novel_revise, novel_check, novel_archive
其余 18 个非 core 工具不消失,改走命令;/novel admin 可显式调用非 core 操作(core 里只有 novel_outline / novel_guide 也在 admin 表中):
/novel admin novel_plan_world {...}
/novel admin novel_plan_chapter {...}
/novel admin novel_word_count {"text":"..."}
/novel admin novel_state {"kind":"pipeline"}
/novel admin novel_amend {...}
/novel admin novel_rollback {...}
/novel admin novel_diff {...}
/novel admin novel_export {"kind":"md"}
/novel admin novel_audit {"limit":20}
/novel admin novel_pipeline
/novel admin novel_blueprint {...}
/novel admin novel_outline_import {...}
/novel admin novel_worldbook {...}
/novel admin novel_search {"query":"..."}
/novel admin novel_doctor
/novel admin novel_report
/novel admin novel_reopen {"chapter":2,"reason":"..."}
/novel admin novel_restore {"txid":"..."}
多项目注册表与设定包导入不走工具 schema;日常发现/切换用 /novel scan、/novel use,底层登记仍可用:
/novel admin novel_registry_list
/novel admin novel_registry_register {"root":"/abs/book"}
/novel admin novel_registry_activate {"root":"/abs/book"}
/novel admin novel_registry_forget {"root":"/abs/book"}
/novel admin novel_import {"kind":"characters","content":{...},"dryRun":true}
/novel admin novel_import {"kind":"characters","content":{...},"dryRun":false}
novel_import 先预览 diff;dryRun: true 不写盘。novel_registry_forget 只删注册表行,永远不删项目目录。
8.4 侧边栏「网文工坊」
- 只读 HTTP 路由:
GET/HEAD /api/novel-write-engine/panel?root=<可选>; - 精确路由,复用 connection 的认证/Origin 闸门;未认证返回 401/403,连接层缺席返回 503;
- 返回
schemaVersion;版本不一致时面板提示刷新; - 状态:loading(骨架)、choose(多项目先选)、missing(项目不在)、empty(显示
novel_init)、error(重试)、outdated(刷新)、ready; - 顶部项目选择器(
aria-label="切换项目");选择只影响面板 GET 的?root=,写入浏览器localStorage,不调用 activate、不写会话绑定; - 只接受注册表、active 或配置
projectRoot的路径;未登记路径返回missing.reason="not_registered",不读取任意目录; - 章节超过 30 章时只渲染最近 30 张,并显示总记录数;卷列表展示全部卷,长列表在滚动容器内;
- 下一步卡提供“复制续写指令”,文本与
/novel resume同源,只写浏览器剪贴板; - 窄屏纵向堆叠,支持减少动态效果。
面板不是第二个写入口。它没有改名、归档、回退按钮。
8.5 导出
工具调用(由模型执行):
{ "kind": "md" }
{ "kind": "txt" }
{ "kind": "epub" }
{ "kind": "md", "chapter": 3 }
对话命令(全书):
/novel export md
/novel export txt
/novel export epub
/novel export outline
/novel export worldbook
/novel export proposal
/novel-export epub
输出:
exports/
├── book.md / book.txt / book.epub # 全书
├── book-ch001.md / .txt / .epub # 单章
├── outline.md # 大纲(与导入模板同形)
├── worldbook.md # 世界观设定集
├── proposal.md # 书级提案
├── cover.svg
└── blurb.txt
- Markdown:
# 书名、## 第N章 标题; - 纯文本:无 Markdown 装饰,UTF-8 无 BOM;
- EPUB:EPUB 3,自写 ZIP 容器,
mimetype首条且 store 方式; - 封面是纯 SVG 字符串,不依赖 canvas;平台简介由模板生成,不调用模型。
8.6 多项目与会话绑定
四层选择模型:
- 显式
project_root(成功后写入当前会话绑定); stateDir/session-bindings.yaml中当前 DSHSessionId的绑定;- 会话 cwd 的有限工作区发现(
cwd、cwd/novel、唯一直接子目录;多候选报歧义); - 唯一注册项目或配置
projectRoot;有多个项目时不猜active。
/novel projects 列出项目;* 当前会话,P 面板默认,! 目录缺失/待修复
/novel current 当前绑定或推导来源
/novel use /abs/book 切换当前会话;active 不变
/novel use . 按当前 cwd 的工作区规则选唯一项目
/novel use 书名 按注册表精确标题切换;重名要求用路径
/novel unbind 只清当前会话绑定,不删项目
/novel scan 只读扫描当前工作区候选
/novel scan --register 只登记健康项目;不改 active、不绑会话
/novel resume 输出可粘贴的续写指令;只读
projects.yaml仍是 v1,新增可选created_at;session-bindings.yaml只保存会话选择,删掉不会删书;/novel use成功绑定后会 best-effort 把项目加入注册表,便于随后在/novel projects与面板看到;不改变 active。novel.yaml损坏时不绑定、不登记,先用显式project_root修复;- 无显式
project_root时,注册/绑定文件损坏 fail-closed,不静默重建;显式project_root的读取仍可用(损坏的绑定不会被更新),写事务提交后元数据失败只回 warning; - 项目目录被删除时保留登记与绑定,返回
ENGINE_PROJECT_MISSING,不自动回退、不自动重建; - 原路径被另一本书占用时返回
ENGINE_PROJECT_IDENTITY_MISMATCH,必须显式重新/novel use; /novel admin novel_registry_activate只改面板默认,不切换当前会话;forget不删绑定与项目。
8.7 整书规划、观测与修复
# 1. 书级蓝图与卷
novel_blueprint {premise, logline, themes, tone, pov, audience,
selling_points, ending, strict, volumes}
# 2. 章卡;或从 Markdown/YAML/JSON 导入
novel_outline {chapters}
novel_outline_import {format:"markdown", content:"...", dry_run:true}
# 3. 世界观设定集(按段替换)
novel_worldbook {setting, rules, factions, locations, characters, glossary, backstory}
# 4. 每次写章前看 guide;写完随时看 report/doctor/search
novel_guide
novel_report
novel_doctor
novel_search {query:"蜡印", scope:"all"}
# 5. 已归档章要改:先重开紧邻的上一章,再走 P3→P9
novel_reopen {chapter:3, reason:"结尾需要重写"}
- 严格大纲:
book.strict=true时 P2/P3 必须要有章卡;只要章卡存在,标题/场景/目标字数/cast 在任何模式下都受 PG-13 约束。要关闭严格缺卡检查用novel_blueprint {strict:false}。 - 归档卡不可直接改;
novel_reopen需要非空reason,会从该章归档事务的备份恢复索引/台账/handoff/正文。 novel_doctor只读;novel_amend才是修复写入口。- 报告/体检/搜索结果都带章号与可定位片段,不是笼统摘要。
九、配置
9.1 六个配置项
| 键 | 默认 | 说明 |
|---|---|---|
projectRoot |
./novel |
无会话绑定/工作区/唯一项目时的兜底根;相对路径相对于 DSH 进程工作目录 |
minScore |
120 |
PG-07 过关线,整数 0..150;唯一 owner |
toolsMode |
all |
all 注册 28 个工具;core 只注册 10 个,其余走 /novel admin |
briefsOverrides |
空 | 自定义任务书目录;某阶段文件缺失时回退包内 briefs/<阶段>.md |
backupRetention |
5 |
保留的归档备份目录数;只清理引擎自己创建的 backups/<txid> |
stateDir |
空 → ~/.dsh/novel-write-engine |
多项目注册表与会话绑定位置;不要放进项目目录 |
stateDir的默认值是代码按当前用户 home 拼出的~/.dsh/novel-write-engine,不跟随DSH_HOME。如果你改了DSH_HOME,建议显式把它设成绝对路径。非法值不会静默改写:
toolsMode不是all|core、minScore越界、backupRetention < 1都会让插件拒绝启动。
9.2 在哪里改
不要改 node_modules 里的 cordis.patch.yml,也不要在项目目录里放「插件配置」。正确位置是你启动的那个 profile 的用户 patch:
$DSH_HOME/profiles/<profile>/cordis.patch.yml
默认 Web:
~/.dsh/profiles/web/cordis.patch.yml
在文件末尾追加(如果已经有同 id 的覆盖项,就改那一条,不要重复):
- id: novel-write-engine
name: dsh-novel-write-engine
config:
projectRoot: /home/me/novels
minScore: 125
toolsMode: core
briefsOverrides: /home/me/novel-briefs
backupRetention: 10
stateDir: /home/me/.dsh-novel-state
Windows 路径:
- id: novel-write-engine
name: dsh-novel-write-engine
config:
projectRoot: D:/novels
minScore: 125
toolsMode: all
briefsOverrides: ''
backupRetention: 5
stateDir: C:/Users/you/.dsh/novel-write-engine
patch 会替换整行 config。因此:
- 你想保留默认值的键可以省略(schema 会填默认值);
- 但不要把「只改一个键」理解成深合并;
- 最稳妥的写法是把你关心的键都写全;
- 改完重启 DSH(或让 HMR 重载),再新开会话验证。
9.3 任务书覆盖
briefsOverrides 指向一个目录,里面按阶段放:
P1.md
P2.md
P3.md
P4.md
P5.md
P6.md
P8.md
某个文件不存在时,该阶段回退到包内 briefs/ 的版本;不会因为缺一个文件而整体失效。任务书内容会参与 PG-01 的 digest,改任务书等于改门控输入,最好在开新书前确定。
9.4 规则包不能运行期切换
rulepacks/default.yaml 是随包加载的:词表、格式、标点、语义、跨章阈值、平台默认值都在里面。0.2.x 不接受运行期外部规则包路径。
要改规则,只有两条路:
- 改源码里的
rulepacks/default.yaml,重新corepack pnpm build;源码目录安装重启即可,tarball 分发则重新打包/安装; - 等后续版本提供正式的规则包覆盖机制。
改规则后至少跑:
corepack pnpm build
corepack pnpm validate:rulepack
corepack pnpm test
规则包编译器会检查十五维合计 150、词条唯一 owner、互斥/豁免引用真实规则码、阈值区间、正则可编译;不合法会 ENGINE_RULEPACK_INVALID,插件拒绝启动。
十、数据、备份与状态
10.1 项目布局
<projectRoot>/
├── novel.yaml # 项目定义(书名、类型、平台、目标)
├── outline/ # 卷/幕/章规划
├── chapters/chapter-001.md # 正文(唯一 SSOT)
├── plans/chNNN.world.yaml # P1
├── plans/chNNN.chapter.yaml # P2
├── reviews/chNNN.review.yaml # P4
├── checks/chNNN.check.yaml # P6
├── state/
│ ├── pipeline.yaml # 控制流 SSOT
│ ├── chapters.yaml # 章节索引
│ ├── characters.yaml
│ ├── world.yaml
│ ├── locks.yaml
│ ├── timeline.yaml
│ ├── foreshadows.yaml
│ ├── relationships.yaml
│ ├── handoff.yaml
│ ├── archive-digests.json # 内部归档幂等账本(journal 跟踪)
│ └── journal.jsonl # 追加式事务日志
├── backups/<txid>/ # 归档前快照
├── exports/ # 导出产物
└── .engine.lock # 写锁(pid + 时间戳)
- 所有 YAML 顶层都有
schema_version;未知顶层键拒绝加载。 schema_version > 1会被拒绝(ENGINE_SCHEMA_TOO_NEW),防止旧版静默破坏新数据。state/是影子层,只有引擎能写;不要把state/chapters.yaml当成正文来源。journal.jsonl是追加式审计;novel_audit读它。- 备份只清理引擎自己创建的
backups/<txid>;你自己放进backups/的文件不会被删。
10.2 多项目注册表
默认:
~/.dsh/novel-write-engine/projects.yaml
projects.yaml 只记录项目路径、标题、可选 created_at 与 active;session-bindings.yaml 按 DSH SessionId 记录显式选择。两者都不保存正文,删掉不会删任何书。面板用 projects/active/配置找默认项目,不读会话绑定。
10.3 手工修改的边界
- 正文可以读,但不建议手改;正文一改,评审分数、check、content hash 都会失效。
state/不要手改;要改就用novel_amend,它要求reason并写入 journal。- 要回退阶段用
novel_rollback;它只允许退回当前阶段或更早,会保留正文为参考,清空轮次;任务书收据留在 state/briefs.yaml,digest 仍匹配时可复用。 - plan/review/check 损坏时,status 的
state_errors会指出文件;不要手改。当前阶段晚于重建点时先novel_rollback;已经处在 P2/P4/P6 时直接重新取 brief,再用对应阶段工具重建。八个 ledger、novel.yaml或 outline/worldbook 损坏时,novel_state返回 raw,按next调novel_amend修复;当前所有不可读状态文档的 journal hash 会被豁免,其他可读文件的外部改动仍 fail-closed。 - 不要在引擎运行时删
.engine.lock;锁由引擎回收,手删可能让两个写者同时进入。
10.4 备份与恢复
- 归档等事务会生成
backups/<txid>/; backupRetention控制保留数量,默认 5;- 事务日志会记录 pending/committed;崩溃后引擎按 journal 恢复或拒绝半迁移;
- 要手动保底,最稳妥的是在升级前复制整个项目目录,或在 DSH 外做文件快照。
十一、升级
11.0 从 0.2.1 升级到 0.2.2
0.2.2 不迁移项目数据,但改变多项目选择与面板契约:
- 面板 payload v4:旧标签页显示刷新;刷新后出现项目选择器、choose/missing 状态和复制续写按钮。
lastRoot删除:工具不再跟随进程内“最近碰过谁”。A/B 会话分别绑定、重启后仍在;显式project_root成功后写入session-bindings.yaml。active降级:只影响面板默认与无 Agent 调用;有 Agent 且多项目无上下文时返回歧义,不静默选 active。novel_init省略 root:只使用配置projectRoot,不读会话绑定/工作区/active;创建成功后才绑定当前会话。- 项目删除/移动/替换 fail-closed:返回 MISSING/IDENTITY_MISMATCH,不自动回退、不自动重建、不清登记与绑定。
- 新增命令:
/novel projects|current|use|unbind|scan|resume;scan/resume不是新工具,工具仍 28、操作仍 32。 - 面板完整卷:0.2.1 只显示前 8 卷的 UI 截断已修复;全部卷在滚动容器中展示。
回滚到 0.2.1 时,session-bindings.yaml 被旧版忽略;旧版恢复 lastRoot 行为。注册表新增的 created_at 对旧版可忽略。
11.0.1 从 0.2.0 升级到 0.2.1
0.2.1 不迁移项目数据,但改变几处契约:
- 面板 payload v3:旧标签页会显示刷新提示;刷新即可。面板根容器现在自己是滚动区,长内容不再被裁掉。
- P2 计划不可变:
plans/chNNN.chapter.yaml不再写summary;旧项目仍回退读它。新摘要/标题/场景/叙述者进入state/pipeline.yaml的draft,novel_write_draft/novel_revise后以它为准。 - 评分与证据历史:评审/校验/正文/废弃稿按 revision 写入
history/;novel_report的维度样本会变多,ChapterRecord保存 lifetime rounds(含 rollbacks)/final_check/archived_at,这是历史证据而不是统计错误。amend 不能改写这些字段。 - 审计更完整:通过参数形状校验、进入项目锁后被 gate/delta/state 拒绝的调用会出现在
novel_audit,状态为aborted、attempt:true并带 code;事务失败/崩溃恢复的 aborted 行也带 code;锁前纯参数错误不写 journal。 - 检查文档分层:advisory 进入
machine.advisories,不再混入violations;用acknowledge记录知悉,blocker 不能 acknowledge。数字矛盾固定 advisory,数字事实只匹配相邻的“别名+数字+单位”。 - 新工具
novel_restore:从novel_state {kind:"backups"}列出的 txid 恢复活动章的正文/计划/世界观计划/评审/校验;P2/P4/P6 在第二次提交起会留下 pre-image。恢复本身再建备份且不 replay;已归档章先novel_reopen。 - 修订可 patch:
novel_revise可传patch:{expected_hash,edits}代替整章;hash 不匹配、锚点不唯一或编辑重叠都会拒绝。 - 字数有分解:
total_word_count仍含标点;新字段punctuation_chars与 PG-03 分解让口径可见。 - 大纲覆盖率改口径:规划覆盖 = 章卡数 / 目标章数,归档覆盖 = 归档卡数 / 目标章数;
card_coverage是逐章“有 archived 卡”的比例;缺卡数单独输出。 - worldbook facts:新增声明式数字事实,进入计数、brief 上下文、搜索与 P6 检查;
facts只做作者声明的 canon 对账,不等同外部史实库。 - 伏笔 anchor:可读
title与逐字anchor分离,anchor 至少 8 个字符;单字子串不再能绕过校验。
11.0.2 从 0.1.3 升级到 0.2.0
0.2.0 新增 outline/outline.yaml 与 outline/worldbook.yaml,新增 9 个工具与 PG-13;旧项目缺少两份规划文档时按空规划读取,不会报错。新项目默认写入两份空文档;严格大纲默认关闭,novel_outline 首次提交才开启。P6 语义项从 4 条变 5 条(新增 L2-POV),旧的 4 条 check 需要重跑。面板 payload v1 → v2,旧标签页显示刷新。所有升级后第一次取 brief 会因上下文新增 book_plan/outline_card/worldbook 而失效,重新 novel_brief 即可。
需要知道的行为变化:
- 损坏台账可修:八个 ledger 或 outline/worldbook 损坏时 status/panel 仍可读;
novel_state返回raw,用novel_amend修复。amend 会为当前所有不可读状态文档豁免 journal 的既有 hash;真正可读文件的外部改动仍 fail-closed。 - chapters 不变量:amend 不能删已归档章、不能改
content_hash/archive_digest;有章节文件时还会核对 hash。 - P2 cast 可选:旧 plan 没有
cast仍可读;新 plan 可传 1–8 人,P3 会把这些人物的完整卡放进上下文。 - chapters 查询变紧凑:
novel_state {kind:"chapters"}默认不再带 summary;需要完整摘要加include_summary:true或chapter_range。 - 单 scope check 不再归档:只跑 content 或 integrity 的 check 通过后停留 P6,并附
CHECK_SCOPE_PARTIAL;必须再跑完整 scope。 - handoff 派生:归档不再每章重算
ceil(chapter/20);volume/volume_name 继承上一章,act/act_progress 从上一章推进,handoff.act/act_progress可覆盖。 - panel 上限 30 行:长书面板只送最近 30 章,统计仍用全书总数。
11.0.2 从 0.1.1 升级到 0.1.2
0.1.2 不 bump schema,也不改工具名/参数;但它会主动让三类旧状态暴露出来:
- 旧 brief 失效:
context_meta进入 digest,升级后第一次调用会要求重新novel_brief;这是预期行为,不是状态损坏。 - 旧 review 无 digest:0.1.1 之前生成、没有
pipeline.review_digest的 review 会被归档拒绝;重新novel_review后再归档。 - 损坏的 plan/review/check 不再静默:status 会显示
state_errors;当前阶段晚于 P2/P4/P6 时next指向novel_rollback,已经到达重建点时直接给出 brief 与阶段修复工具,不需要手改文件。
11.1 升级前
- 看 CHANGELOG.md 和 DSH 的版本要求;
- 确认
dsh --version仍满足插件engines.dsh; - 复制一份项目目录(或至少确认
backups/完整); - 升级后新开会话验证,不要指望旧会话立刻换工具定义。
11.2 从 npm 升级(正式分发,推荐)
# 在目标 profile 里升级到最新版
dsh plugin --profile web remove dsh-novel-write-engine
dsh plugin --profile web add dsh-novel-write-engine@latest
也可以固定版本:
dsh plugin --profile web add [email protected]
升级后核对:
dsh --profile web --dump-config | grep -A6 '# == dsh-novel-write-engine'
profile 的依赖由 pnpm 管理。不要在
~/.dsh/profiles/web里直接npm update或手改package.json/锁文件;那会绕开dsh.profile.bundles的激活逻辑,出现“包装了但插件没启用”。统一用dsh plugin remove+add,或在插件页点 更新。
11.3 从源码目录升级
cd /path/to/dsh-novel-write-engine
git pull
corepack enable
corepack prepare [email protected] --activate
corepack pnpm install
corepack pnpm build
# 先移除旧链接,再装新目录(同一路径时,remove + add 最干净)
dsh plugin --profile web remove dsh-novel-write-engine
dsh plugin --profile web add "$PWD"
然后重启 DSH,或刷新 Web 页面并新开会话。
11.4 从 tarball 升级
先构建新 tarball:
corepack pnpm build
corepack pnpm pack
再:
dsh plugin --profile web remove dsh-novel-write-engine
dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.2.2.tgz
11.5 在 Web / Desktop 里升级
从 npm 安装的 bundle 会在插件页出现 版本 区块和 更新 按钮;源码目录(link:)和 tarball(file:)不属于这一类,页面不会给「更新」。两种路径分别是:
npm 安装:
- 插件页 → 打开
dsh-novel-write-engine; - 点 更新到 x.y.z;
- 刷新页面,新开会话。
源码目录 / tarball:
- 插件页 → 打开
dsh-novel-write-engine→ 卸载; - 添加插件 → 填新的目录或 tarball → 安装 → 启用;
- 刷新页面,新开会话。
插件页更新底层仍然是「移除旧版本 → 安装新版本 → 失败则恢复旧版本」。
11.6 升级配置会保留吗
用户配置写在 profile 的 cordis.patch.yml,不在包内。remove/add 不会删除它;只要新版本仍然使用 id: novel-write-engine,覆盖项继续生效。
升级后仍建议检查:
dsh --profile web --dump-config | grep -A8 '# == dsh-novel-write-engine'
11.7 升级 DSH 本身
npx:每次运行可加@latest,例如npx @deepseek-ai/dsh@latest web;- 全局:
npm update -g @deepseek-ai/dsh; - 源码:
git pull && corepack pnpm install && corepack pnpm run build; - Desktop:用官方安装包或应用内更新。
DSH 升级后如果 engines.dsh 不再匹配,插件会被拒绝。此时升级插件,或把 DSH 降到兼容版本;不要用「改 package.json 绕过」当长期方案。
十二、卸载
12.1 在 Web / Desktop 卸载
- 左侧栏 → 插件;
- 打开 dsh-novel-write-engine;
- 点 卸载,确认;
- 刷新页面;
- 新开会话确认
novel_*工具与「网文工坊」预设消失。
12.2 用 CLI 卸载
建议先停止 DSH(尤其是没有 HMR 的 profile):
dsh plugin --profile web remove dsh-novel-write-engine
如果 DSH 正在运行且 profile 支持 HMR,也可以在运行时移除;以插件页/CLI 的提示为准。若提示当前 profile 正在使用该包,停止 DSH 后重试。
dsh plugin remove只从 profile 移除插件层,不会删除你的小说项目、stateDir注册表或备份。
卸载会:
- 从 profile 的
dsh.profile.bundles移除该层; - 从
dependencies移除包; - 停止并卸载它的 Host 行与 client 面板;
- 不会删除你的小说项目、
stateDir注册表或备份。
12.3 清理配置覆盖
如果你在 profile 的 cordis.patch.yml 里加过:
- id: novel-write-engine
name: dsh-novel-write-engine
config: ...
卸载后把这一段删掉。否则它会成为一个指向不存在行的用户 patch;不同 DSH 版本对这种情况的提示可能不同,清掉最干净。
12.4 清理数据(可选)
卸载插件不会删书。确认不再需要后,再手动清理:
# 多项目注册表与会话绑定(只影响选择/查看,不影响书)
rm -rf "$HOME/.dsh/novel-write-engine"
# 某个项目(先确认路径!)
rm -rf "/absolute/path/to/your/novel-project"
Windows PowerShell:
Remove-Item -Recurse -Force "$HOME\.dsh\novel-write-engine"
Remove-Item -Recurse -Force "D:\novels\your-book"
不要为了卸载本插件去删整个 ~/.dsh:那里还有 DSH 的配置、凭据、会话和其他插件。
12.5 验证卸载
dsh --profile web --dump-config | grep dsh-novel-write-engine
# 应无输出
新开会话:面板入口消失,预设列表里没有「网文工坊」,/novel 不再被识别。
十三、故障排查
| 现象 | 最可能的原因 | 处理 |
|---|---|---|
dsh plugin add 404 / 找不到包 |
包名拼错、registry 不可达,或镜像尚未同步 | 确认 npm view dsh-novel-write-engine version;必要时切回官方 registry |
npm install 成功但 DSH 没有插件 |
npm install 不会把插件加入 profile |
执行 dsh plugin --profile web add dsh-novel-write-engine,见 5.1 |
dsh: command not found |
CLI 未全局安装 | 用 npx @deepseek-ai/dsh ...,或先 npm i -g @deepseek-ai/dsh |
dsh plugin 报找不到 pnpm |
只装了 DSH,没装 pnpm | corepack enable && corepack prepare [email protected] --activate |
--dump-config 没有插件层 |
装到了别的 profile | 用实际启动的 profile 重装;dsh --profile <name> ... |
| 插件页显示已安装但开关打不开 | 包不完整/版本不兼容/被更高层覆盖 | 看插件页诊断;用 tarball 重装;检查 engines.dsh |
| 侧边栏没有「网文工坊」 | 不是 Web/Desktop profile,或 client bundle 未加载 | 用 dsh web / Desktop;刷新;重启 |
| 预设列表没有「网文工坊」 | headless/acp/sdk 没有 agentPresets,或插件未启用 |
改用 Web;插件页启用;新开会话 |
会话里没有 novel_* 工具 |
插件未启用、旧会话未刷新、装错 profile | 新开会话;重启;--dump-config 核对 |
ENGINE_STAGE_ORDER |
跳过了阶段或顺序不对 | /novel / novel_status 看下一步;按 novel_brief 领任务书 |
ENGINE_GATE_BLOCKED |
门控未过 | 看 blocking 的 code/detail/hint;改正文或补证据;不要手改 state |
ENGINE_PROJECT_NOT_FOUND |
项目根不对/未初始化 | /novel scan 发现项目;novel_init,或传正确的 project_root |
ENGINE_PROJECT_AMBIGUOUS |
有多个项目,无法从会话/cwd 唯一确定 | `/novel use <path |
ENGINE_PROJECT_MISSING |
当前会话绑定的目录被删除/未挂载 | 恢复目录后重试;或显式 /novel use <新路径>;不会自动换书 |
ENGINE_PROJECT_IDENTITY_MISMATCH |
原路径已被另一本书占用,created_at 不同 |
确认后用 /novel use 重新绑定;旧绑定仍 fail-closed |
| 面板空白/显示没有项目 | 当前没有项目,或 active 指向旧路径 | 先 novel_init;多项目时用面板选择器或 /novel use 选择 |
| 面板显示「需要刷新」 | 浏览器缓存了旧 client bundle | 刷新页面;重启 DSH |
| 升级后仍是旧行为 | 源码目录没 corepack pnpm build,或旧会话未换 |
重新构建;重启;新开会话 |
| 卸载后配置项还在 | profile 的 cordis.patch.yml 还留着覆盖 |
删除 id: novel-write-engine 的段落 |
EACCES / 写入失败 |
项目根或 stateDir 对 DSH 进程不可写 |
改权限,或换可写路径 |
仍然卡住时,提供这四样信息
dsh --version与node --version;dsh --profile <name> --dump-config里插件层那一段;- 插件页的版本/诊断,或
dsh plugin --profile <name> list的输出; - 具体报错的
[ENGINE_*]代码与完整 hint。
不要贴出 API Key、Token、密码或完整正文。
十四、安全与边界
14.1 它在宿主进程里运行
DSH bundle 的 Host 半边在 DSH 进程内执行,不受工作区沙箱限制。安装本插件等于允许它在 DSH 进程权限下读写你给它的项目目录和 stateDir。只从你信任的 npm 包、源码或 tarball 安装。
14.2 它不向外联网
Host 侧没有 fetch、HTTP 客户端或遥测;运行期依赖只有 yaml。它不读取环境变量里的 API Key,也不会把正文发到任何第三方服务。Web 客户端只会向宿主自己的只读面板路由发同源 GET,不访问外部地址;模型调用本身由 DSH 负责,与本插件无关。
14.3 面板是只读的
/api/novel-write-engine/panel 只接受 GET/HEAD,并复用 DSH connection 的认证与 Origin 校验。项目选择器只改 ?root= 与浏览器 localStorage,复制按钮只写剪贴板;它们不能改项目、注册表或会话绑定。所有写操作仍然要经过工具/命令。
14.4 状态文件不是「随便改的 YAML」
state/ 是引擎的影子层。手改会让 journal 哈希对账失败,后续事务可能拒绝执行。要改状态,用 novel_amend 并写原因;要回退,用 novel_rollback。
14.5 备份不是万能的
backups/ 保留的是引擎事务快照,不是外部备份。磁盘损坏、误删整目录、手动 rm -rf 都不在它的保护范围。重要书稿请另做文件级备份。
14.6 安装来源
- 优先从 npm 官方 registry 安装,并核对包名、发布者与版本;离线环境可用你自己构建的 tarball,并记录 SHA-256;
- 不要从聊天记录里复制来路不明的 Git 地址并给
allowBuilds授权; allowBuilds等于允许包在安装时以你的用户权限执行脚本。
十五、已知限制
- 书级大纲是 0.2.0 的新数据源:
outline/outline.yaml与outline/worldbook.yaml由引擎读写;有章卡时 P2/P3 受 PG-13 约束,严格模式还要求章卡存在。大纲是规划层,不替代state/台账。 - 0.2.x 只有中文:面板、命令、错误、任务书都是中文;没有
locale/,不跟随系统语言。 - 通过 npm 分发:安装与升级统一使用
dsh plugin add;源码目录和 tarball 用于开发或离线环境。 - 面板与预设只在 Web/Desktop:headless / acp / sdk 没有
agentPresets服务,也没有浏览器面板;28 个工具仍可用。 - 规则包不可运行期替换:要改词表/阈值,必须改源码、重新构建、重新安装。
- 普通会话可能绕过引擎:只有「网文工坊」预设不挂 bash/fs 写工具;在普通会话里手动改文件,事务与门控保证不再完整。
- 预设会话开始后不能切换。
- 同一物理项目请固定一个路径:注册表按规范化路径(
path.resolve)去重;同一本书通过符号链接和真实路径分别登记会变成两个 root,可能显示两行或报歧义。请在/novel use/project_root中固定使用其中一个路径。 - 单章轮次上限 3:超过需要
novel_rollback,不是无限重试。 - 面板只读:没有在面板里直接改正文/归档的按钮。
- DSH 仍是 developer preview:
0.3.0之前可能有破坏性变更;升级 DSH 前先看插件engines.dsh。 - 没有云同步/多人协作/在线书城:数据都在本机项目目录与
stateDir。
十六、开发与验证
16.1 环境
corepack enable
corepack prepare [email protected] --activate
corepack pnpm install
16.2 常用命令
corepack pnpm typecheck # host + client 类型检查
corepack pnpm test # 单元 + 集成 + e2e
corepack pnpm test:coverage # 覆盖率 + 分层门禁
corepack pnpm build # host → client → client d.ts
corepack pnpm test:isolated # 每个源文件独立编译
corepack pnpm validate:rulepack # 需先 build
corepack pnpm check:artifacts # 真正 import 构建后的 host / client
corepack pnpm check:hygiene # v8 ignore 预算 + 假断言扫描
corepack pnpm check:pack # 需先 build;检查 tarball 内容
corepack pnpm check:install # 需先 build;空项目安装并加载
corepack pnpm check:host # 需本机 dsh;真实 Web 宿主安装/面板/卸载
预设层需要真实 DSH checkout:
DSH_BUNDLE_ROOT=/path/to/deepseek-harness/packages/bundle/web-app corepack pnpm check:preset
check:preset 不伪造 bundle root;没有宿主 checkout 时它不会假装通过。
check:host 使用临时 DSH_HOME 与临时 profile:build → npm pack → dsh plugin add → --dump-config → 启动 Web → 面板 401/200 → 卸载 → 确认层消失,并断言宿主声明全部 28 个工具。它需要 PATH 里有 dsh(或设置 DSH_BIN),不会碰你的真实 profile;没有 DSH 时以退出码 2 明确失败,不伪造通过。
16.3 发布前手动验证
corepack pnpm build && corepack pnpm pack;- 在临时 DSH home 里
dsh plugin --profile web add <tarball>; --dump-config确认插件层;- 启动 Web,确认面板、预设、28 个工具、
/novel; - 跑一遍
novel_init → P1 → … → archive → export; dsh plugin remove,确认层与面板消失;- 确认项目数据未被卸载动作删除。
pnpm check:host 覆盖第 1–4 与第 6 步的自动断言(含 28 个工具的宿主声明、面板 v4 字段与空态结构)。/novel 命令的 handler 与路由由 tests/adapters、tests/smoke 的假宿主覆盖,真实宿主命令路由仍属于第 4 步的人工确认;第 5 步也是人工全流程(需要可用模型)。
16.4 项目结构
src/
├── domain/ # 字数、评分、迁移、SimHash、文本
├── rules/ # 规则编译器、注册表、检测流水线
├── store/ # FsStore、事务、锁、journal、迁移、注册表
├── engine/ # EngineService、门控、任务书、投影
├── tools/ # 28 个工具适配器
├── commands/ # 5 条命令 + admin
├── client/ # 侧边栏面板
├── remote/ # 只读 panel 路由
├── export/ # Markdown / TXT / EPUB
└── skills/ # 入口技能
briefs/ # P1/P2/P3/P4/P5/P6/P8 任务书
rulepacks/ # default.yaml
presets/ # 内置 Agent 预设 patch
tests/ # 单测、集成、falsify、e2e
16.5 当前验证基线
0.2.2 在 Node 24.19 / DSH 0.2.1-rc.3 上完成过:
npm test全绿:77 个测试文件 / 772 项;- 覆盖率:语句 93.87% / 分支 89.15% / 函数 97.89% / 行 93.87%,高于 0.2.1 基线(93.86 / 89.04 / 97.81 / 93.86);
test:coverage与逐文件 domain/book/insight/viewmodel 门禁全过; typecheck、lint、check:hygiene(138 files,0 v8 ignore)、test:isolated(58 源文件)、build、validate:rulepack、check:pack(25 files)、check:artifacts、check:install(26 packages)全绿;check:preset从真实 bundle 解析 13 个 packages;check:host在临时 DSH profile 中实测:面板未认证 401、认证后 200(payload v4)、预设可见、headless 真实触发novel_init并落盘、remove后层消失;check:crash在真实子进程 SIGKILL 后恢复 pending journal:目标项目仍可读,无遗留 pending 事务;agnes-2.5-flash与agnes-3.0-flash在临时项目完成 P1→P8、归档、report/doctor/panel v4、history/backups、六种导出、novel_reopen与重新归档;P1/P2/P3 为真实模型,P4/P6 为确定性夹具,详见 0.2.2-real-model-evidence.md。
具体数字会随代码变化;发布前请以重新跑出的结果为准,不要把上面的历史数字当保证。完整验收矩阵见 docs/0.2.2-evidence.md。
十七、文档地图与许可
| 文档 | 内容 |
|---|---|
| DESIGN.md | 完整设计书:架构、数据模型、规则、门控、事务、面板、预设 |
| PLAN.md | 0.1.0 实施计划(历史) |
| docs/0.2.0-plan.md | 0.2.0 整书生命周期:蓝图/大纲/世界观/章卡/观测 |
| docs/0.2.2-plan.md | 0.2.2 会话级项目选择、scan/resume、面板 v4 与完整卷 |
| docs/0.2.2-evidence.md | 0.2.2 验收矩阵与质量门证据 |
| docs/0.2.2-real-model-evidence.md | 0.2.2 两条真实模型 P1→P8 链路回执 |
| docs/0.2.1-plan.md | 0.2.1 可信账本、历史、备份、计划分权与质量门禁 |
| docs/0.2.0-real-model-evidence.md | 真实模型全链路验证回执 |
| docs/0.1.2-plan.md | 0.1.2 长书可运行性与证据闭环方案(历史) |
| docs/0.1.1-plan.md | 0.1.1 契约收口与证据加固方案(历史) |
| docs/tools.md | 28 个工具与命令面速查 |
| docs/states.md | 状态机、迁移表、轮次与回退 |
| docs/rulepack.md | 规则包结构、编译器断言、改词表流程 |
| CHANGELOG.md | 版本变更 |
| LICENSE | MIT |
反馈
- 仓库:https://github.com/ThzxxArt/dsh-novel-write-engine
- 问题:请附 DSH/Node 版本、安装方式、
--dump-config片段、完整[ENGINE_*]错误与 hint。 - 不要提交真实 Token、密码、未公开书稿或含个人信息的项目文件。
许可
MIT。见 LICENSE。