技术文档
当前版本 7.3.4 · 更新记录见 CHANGELOG(下方「版本说明」)
dsh-novel-writer 的 22 个工具全部在本地运行,不使用在线大模型:所有指标由规则统计与本地 ONNX 推理得出。本组页面面向二次开发与集成方,逐工具说明参数契约、计算原理、约束边界与源码位置。
阅读约定
每个工具页固定按以下顺序组织,可以跳读:
- 参数:名称、类型、是否必填、语义与校验方式;
- 输出结构:返回体字段与渲染层行为;
- 计算原理:公式、词表、阈值与取舍,尽量给出可直接对照源码的表达式;
- 约束与边界:对调用方模型的限制、被静默跳过的情形,以及跨版本不可比之处;
- 源码位置:
lib/*.js中的对应实现。
版本说明
每条一行,展开可读完整说明;最新一版默认展开。完整历史见 CHANGELOG。
-
7.3.4· 2026-11-14 收干净 7.3.3 之后又核出的一轮:3 条上一轮漏修(诊断读数上限文案、连贯性审计的大纲方向行判据、MCP 死分支)+ 4 条 7.3.3 自己带出来的(BODY_TOO_LARGE 死导入导出、只删空目录时 remaining/skipped/审计日志不如实、空目录已消失时文案自相矛盾、面板冷启动拿已删除的书名去要数据)没有新功能,全是「说错的话」和「没说的话」。最实际的一条是连贯性审计的大纲对照: 它仍写死
/^- \d+ /,而 7.3.3 已经把钩子承接与novel_outline统一到OUTLINE_LINE_RE——于是用* 12 …/## 12 …/- 第12章 …/ 行首带缩进写大纲的作者会被误报「没有方向行」。诊断报告的 「读数上限 2000 条」也是无条件写的,而明细模式实际只读 200 条。 另有一批是 7.3.3 自己带出来的:把#6/#7挪回 core 单点实现后,BODY_TOO_LARGE的导入悬空了(连带两处说明变成假话);「只删空目录」的提前返回分支 把remaining写死成 0、不标partial、还绕开了delete_apply审计日志;空目录在预览后已消失时回「未能移除(见失败项)」而failed是空数组; 面板冷启动会拿一本 localStorage 里记住、其实已被删除的书名去要数据,且落定后不会纠正。7.3.3· 2026-11-13 按外部源码审计报告修完 34 条 + 它漏掉的 16 条:GET 请求能删书、删书路由跟随局域网开关、POST /state 写错书库根、设定表读失败仍拿默认词表出待办、取消被记成数据故障、裸台词行号退化成 0、scanSlop 不归一换行(工具数仍 22)这一版来自一份外部源码审计报告(36 条)。它的准确度比上一份高:34 条有真问题, 只有 2 条我判「影响不成立」。最该先看的是三条数据安全:
GET请求真的会删书 (?action=apply移进回收站、?action=purge不可恢复,而文档写着「破坏性动作一律走 POST」); 删书路由跟随allowLanState(文档说「仅支持回环」,实际一开局域网访问, 不带Origin头的脚本就能删);POST /state用了过期的书库根 (另两处都走resolveUiRootInfo,唯独它自己直取lastRoot,实测把创作资料写进了过期路径)。 另有一批「静默失效」:设定表读失败后仍用默认词表产出禁用词待办、最小宿主下插件加载中断(22 个工具已注册、 提示词分区一条没注册)、三处把「用户取消」当成读取失败并写进事件日志、词表改名报假成功还暗地停用条目。 语义写反的典型是开写包对「后文才埋的伏笔」一处说「本章尚未埋下、不要透露」、另一处渲染成「本章将首次埋下」。 数量口径有两处变化,跨版本不可直接比较:scanSlop现在归一换行(纯 CR 不再让整章变 1 行), 句末 ASCII...从此计入未完句(gapIndex会上升)。 同时把新加的门禁补齐——ui-audit的 R9 此前自称「双向」其实缺了CSS→JS方向, 补上后立刻又抓出 15 个死 CSS 类。7.3.2· 2026-11-12 修 7.3.1 自己引入的 4 个回归(开写包假降级 / 重试流泄漏 / 纯本地阈值存不进 / 回收站加载态),清 22 条残留,并更正上版日志里 3 处不实说法(工具数仍 22)只修 bug。上一版修完 79 条之后,独立复审发现修复本身基本属实(75/83 真修好、7 条刻意保留且依据充分), 但我在修的过程中新引入了 4 个问题,最重的一条是:修「读失败被谎报成未初始化」时把披露条件写反了 (
!read.missing成功时也为真),于是任何创作资料已初始化的书,每次开写包都会多出 2~4 条假降级。 这个 bug 能过测,是因为当时只测了「坏了要报」、没测「好了不能报」——本版补了test/brief-degrade-test.mjs做三态对照(套件 36→37),并验证过它在旧条件上会红。 另三条:重试的 LLM 流在用户取消时不释放、纯本地模式下「提问节奏」永远存不进、回收站「加载中」会卡死。 同时更正上一版更新日志里 3 处与源码不符的说法(一个被列为「已清理」其实被保留的组件、 只改了一半的8~70注释、声称覆盖但实际没覆盖的建章自动章号)。7.3.1· 2026-11-12 修第三方源码审计里 79 条能举证的缺陷:删除/恢复越界、审计渲染返回类型、面板阈值显示、草稿镜像防护恒失效、推理型模型兜底失效(工具数仍 22)这一版只修 bug,不加功能。起点是一份 88 条的外部审计清单:79 条成立、3 条误报(清单自己已标出)、 6 条「代码属实但影响不成立」。三条最该知道的:① 书名里写
../..时删除目标能逃出novels/, 而restore的反向通道同样不校验(两条都加了测试,且是先写测试证明会失败再修); ② 对抗性审计的三个动作 render 返回的是字符串,会让下一轮请求失败(不是当轮报错); ③ 面板拿不到宿主下发的chatThreshold,把 150 显示成 400,再点保存就把真实值覆盖掉。 另有一批「静默失效」:草稿镜像不得落进正文目录的防护因缺两个 import 恒返回 false、 推理型模型(先出 reasoning-delta)的非净化兜底永久不触发、必用词表损坏时开写包完全静默。 5 处口径变化已单列(actionChainRatio修正、氛围链路取最强、标题截断、戏谑分流、日志上限文案), 新旧数值不可直接比较;工具数仍 22,无迁移步骤。7.3.0· 2026-11-10 实时聊天写作:逐段写、程序按字数阈值让你确认,草稿进独立目录(工具数 21 → 22)新增第 22 个工具 novel_draft(草稿镜像):AI 一段段地写,每写完一段就把这一段正文交给它,由程序追加进独立目录
.novel-writer/drafts/<书>/并自行累计字数——只追加,AI 不读、不改、不清;正式章节在用户确认前一个字节都不动。它不生成正文,也不判断该不该问人:action只有commit,返回值里的nextAction(continue/ask_user)由程序按字数阈值判定(默认 400,可在面板「提问节奏」填 100~5000),够阈值才把本批合并后的正文(combinedText)与固定文案的question一起交出去;计数存在该章的<章键>__state.json里,账本丢失时按镜像里的## 第N段段头重建。为什么必须另起目录:插件所有章节扫描都按novels/<书>/枚举并把每个.md当一章参与字数、六维基线与语义索引,半成品放进去会污染这些数字,而界面上只表现为「数字怪怪的」——工具层用isInsideBookDir硬断言拦死,路径落进正文目录直接拒绝。章键归一(能解析出章号就统一成第NN章,并认领同章号的既有文件,避免升级后同一章多出一份)与纪律(开关features.chatWriting,默认关;打开后系统提示注入八条硬约束,开写包多一个chatWriting分区;novel_new_chapter定稿时由插件自己追加一条「定稿落盘」记录,已有逐段内容只写标记、一个字都没有才补正文)。面板:诊断报告页新增只读的「草稿镜像」卡片(选书 → 章节留空列文件、填章号看逐段正文),数据来自GET /api/dsh-novel-writer/draft?book=&chapter=,不提供修改/清理。按书删除把drafts/单独登记成data:drafts(整目录移入回收站)——它不是扁平文件白名单的一员(放进去会永远命中 0 个文件而被跳过,留下孤儿目录)。工具数 21 → 22,参数契约只加这一个工具,书库格式不变;详见 novel_draft。 -
7.2.0· 2026-11-07 对抗性审计:改稿台新增严格对账、独立 AI 任务书与证据复核(编造的原文判废),工具数仍 21新入口挂在 novel_fix_plan 上,不新增工具(仍为 21 个):
action="audit"严格对账——只跑八条可机器判定的契约(必用词 / 替身词、世界观禁用词、套话、原地打转、大纲兑现、章末收束、连续裸台词、伏笔登记),每条违约要么带 1-based 行号与原句片段、要么明确标成全章层面,契约没跑会写明原因(ran: false)而不是「查过没问题」;action="audit_brief"生成给另一个没有写作上下文的 AI 的审计任务书(判据、取证 JSON 格式、「举不出证据一条都不许写」的硬约束,末尾附正文);action="audit_verify"逐条复核它交回的claims——行号错但原文确实在文中 →corrected(自动修正行号),全文找不到 →rejected(疑似编造证据),并给出score(可信证据占比)。明确不做文学评论:抽象度 / 物件偏少 / 感官单通道这类风格症状仍在改稿台与开写包里作建议,但不进审计;审计永不修改正文,三个动作都不落盘。参数契约只加一个claims,书库格式不变,详见 novel_fix_plan 的「严格对账的 8 条契约」与「为什么这不是文学评论」两节。 -
7.0.0· 2026-11-01 修尺子:细节密度词表去噪,动作链示例不再恒取开头三句、不再截断这一版只做一件事:修尺子。细节密度的几张词表(动作 / 物件 / 五个感官通道)此前全是单字正则——「一点」贡献 2 个"动作动词",「根本 / 要被」贡献"物件名词",「一样 / 里面」贡献"视觉",「痛苦 / 语气 / 力气」贡献"嗅觉",「干净 / 麻烦」贡献"触觉",「温柔」贡献"温度"。也就是说,过去基于这些数字得出的"感官偏科""动作干瘪"结论,测的是词表,不是你的正文。
① 加上下文豁免层:新增lib/lexicons/collocation-guards.js(193 条搭配,覆盖 7 个通道),这些虚词搭配命中时不再计数;实测同一章细节密度下降约 15%~20%。② 动作链示例修两个旧 bug:旧版actionChains.length < 3填满即止、且遍历从全书开头开始,于是每一章拿到的都是本书第 1 章开头那三句(所谓"按章轮换"根本无从谈起);旧版还按 40 个码点硬截断,放进开写包等于教模型写残句——现在只取 15~70 字的完整句并等距抽样。③ 面板可见:「诊断报告」页新增度量口径区,显示当前口径、还有几个缓存来自旧口径,并提供「重建分析缓存」按钮(只删analysis/*-chapters-metrics.json派生缓存;你在「基线范围」里选的章节存在baseline/下,不会被删)。
质量门禁:新增test/density-precision-test.mjs——陷阱句必须为 0、真信号必须仍被计入、固定语料计数锁定、豁免表不许有"死条目"(登记了却根本不命中该通道词表)。
升级须知:细节密度(动作 / 物件 / 五维感官)在多数书上会下降,这是修掉虚词灌水、不是能力退化,同一章的新旧数值不可直接比较;六维基线(动作密度 / 抽象度 / 修饰密度 / 虚化 / 留白 / 复杂度)本次未改,口径不变。缓存随版本号失效,首次测量会重建。工具数仍为 21,参数契约与书库格式不变。
Phase 0 / 1A / 1B(同一版本内继续补完,不另起版本号):Phase 0 修尺子(细节密度上下文豁免、动作链只取完整句,见上);Phase 1A novel_chapter_brief 新增 5 个字段——actionChains(原著典型颗粒度动作链,p60~p85 分位取样 + 按目标章号确定性轮换)、clauseFrames(大纲子句框架,7 类动词元类 + 填空格式,插件不生成问句)、prevChapterIssues(上一章遗留问题)、symptomPrescriptions(症状处方,相关性门控 + 3 章 2 中滞回 + 每章最多 3 条)、referenceProvenance(参照集来源),受新增总预算enhanceChars(compact 450 / full 900 字,装填优先级「上一章遗留 & 症状处方 > 子句框架 > 动作链」)约束,开写清单另加一条恒定项「章末收束闸门」;Phase 1B novel_new_chapter 新增可选参数plan(不写入正文,只用于写盘后核对兑现)与返回字段postWriteAudit(最多 5 条,按严重度降序:未兑现的 plan 子句 / 章末升华 / 连续站桩对话 / 高频套话;只告警、不阻断保存),新增套话库lib/lexicons/slop.js(8 类 / 73 条 pattern),novel_fix_plan 据此新增一类待办 AI套话(按类别归并、给命中处数与行号区间、target「0 处」,不罗列套话原文),并把参照集与诊断集分开。Phase 2 novel_fix_plan 接入本地向量审计(lib/vector-audit.js,纯本地 ONNX、零外网、不需要任何 API key):新增两类待办 原地打转(连续 ≥3 块语义雷同且没有新信息:章内 z ≥ 2.0、绝对余弦 ≥ 0.80、新二字组占比 < 0.12)与 大纲漏写(大纲子句「关键词命中 || 向量相似 ≥ 0.42」,都未命中才报);只在改稿台跑(单块约 47ms,进开写包/建章/常规自检会拖垮高频路径),受语义嵌入开关与引擎可用性双重门控,不可用时明确跳过并披露。测试套件 18 → 23 套,工具数仍为 21,版本号仍为 7.0.0。 -
6.9.5· 2026-10-29 词表体系集中整修:修掉情绪虚高与六维失真,修「先生 / 蜡烛」误伤中式日常语境这一版只处理审查中已确认的问题,不发新功能。三处影响最大的修复:① 愤怒情绪虚高——
DUTIR_TO_EMOTION此前把大连理工词典的「恶」类(10,262 词,含无聊 / 尴尬 / 愚蠢 / 虚伪 / 啰嗦等贬义评价)全部映射成「愤怒」,导致表面主导情绪偏向 anger 并连带推高氛围轴;现在「恶」不再计入五类主情绪,只由效价词库承担负向。② 开写包与审计口径分裂——未登记worldview时开写包此前直接返回worldview: null(不给禁词),写完后审计却按默认表报错;现在两边统一走同一裁决点,开写包按文化基准注入默认表并在降级说明里写明「哪套基准、共多少条」。③ 东方语用误伤——从东方禁用称谓移除「先生」(教书先生 / 账房先生 / 说书先生 属正常用法),并把「点烛 / 蜡烛 / 礼拜」三条硬规则收窄为「祭坛点烛 / 祭坛蜡烛·祷告蜡烛·献祭蜡烛 / 做礼拜·礼拜日·主日礼拜」,此前「点起蜡烛」「礼拜佛祖」会被判硬错误。
其余修复:单字否定词(没 / 莫 / 无 / 未)误吞角色名后的情绪词(「苏莫愤怒」「林未恐惧」);修饰密度误杀「天真的 / 认真的 / 所有的 / 原有的」;动作密度混入 70 余个非动词与性质形容词导致虚高,且二字程度副词(十分 / 非常 / 格外)未豁免;抽象度按任意 2~4 字切片(「他很想」「天空」「认真」「她醒来」全部命中);必用词审计在专名与替身词互相包含时(「魔导步枪」vs「步枪」)误报;关键词提取的停用字条件写反(||应为&&)导致「她的 / 着她」霸榜;大纲解析漏认「节」;幽默度扫描只看前 6000 字;对话占比把 ASCII 直引号数了两次;文化基准检测与「文化基准存疑」提示未接子串碰撞守卫。
词表扩充:西幻标记词补 28 个高信号词(子爵 / 大公 / 纹章 / 骑士团 / 告解室 / 魅魔 / 地下城 / 羊皮纸 / 先令 等),中式标记词补齐与禁用词表一致的 27 个市井与制度词,非净化模式的淡化特征库补时间跳跃 / 委婉总结 / 元评论三类,意象载荷补五组微表情与肢体反应。另为「失敬 / 银子 / 银两 / 铜钱 / 包袱」补上前后字守卫与实证反例。
升级须知:缓存随版本号失效,首次分析会重建;动作密度、抽象度、修饰密度与愤怒占比在多数书上会下降(修掉虚高,不是退化),跨版本对照请用本版重取基线;词表扩张会让既有书新出现一些用语候选(覆盖变宽,不是新增误报)。工具数仍为 21,参数契约与书库格式不变。 -
6.9.0· 2026-10-22 非净化模式重做:动笔前给目标带、动笔时兜底、写完可核对(新增「直白度」度量)起因是用户反馈「非净化模式开了跟没开一样」。核查结论:旧版只往系统提示里加 5 行抽象要求,动笔那一刻模型拿到的材料里一个字都没有——问题不在力度,在可执行性与位置。本版改成三层:① 动笔前——novel_chapter_brief 新增
rawMode分区(原著「把场面绕过去」的写法密度、处/千字,启发式;本章目标带;一条硬约束同时进plan.checklist),建章返回也带同一提示;② 动笔时——新增llm/stream兜底层:三层闸门(开关 / 系统提示里的非净化模式标记 / 输出开头的自我刹车特征)全中时,丢弃本次输出只重试一次,重试只在系统消息尾部追加写作指令(不改用户消息,不用「你已获授权」这类话术),事件记raw日志且不记录任何正文;③ 写完后——新增直白度度量(lib/explicit.js,纯规则、零 token):六类淡化写法密度 + 对话段落占比,novel_style_check 在开关打开时给出「本章 X 处/千字 vs 原著 Y 处/千字」与一句结论(clean / new / similar / softer / much-softer / more-explicit)。与同类「破甲」插件的取舍:只借「注入位置 + 拒绝检测重试」的工程结构,不借去人格 / 宿主补丁 / 「永不拒绝」那套——那套会改变整个 agent 的行为边界,超出本插件职责。已知边界:直白度是启发式(只数明确的淡化写法,不数比喻多、句子长这类风格差异),不作为质量评分;重试只一次且只认三类自我刹车特征;兜底依赖宿主llm/stream,缺失时安静跳过并留痕;效果取决于模型本身。工具数 21、参数契约与书库格式不变。 -
6.8.0· 2026-10-22 按书删除与回收站:删一本书不必再翻 12 个位置(issue #2)回应 issue #2「删不干净」:一本书的资料散在 12 个位置——正文、创作资料、数据目录 9 个按书子目录与
state.json的设定库条目,另有 v0.8.0 前留在数据目录根上的旧位置伏笔表。本版新增第 21 个工具 novel_delete_book(按书删除):一次列出全部待清理位置、文件数、体积与样例,默认只预览,action:"apply"才执行;keys/面板勾选框可只清其中几类(例如只删报告历史与缓存,正文留着)。匹配改为前缀 + 分隔符边界(书名后必须紧跟./-/_或到此结束,另加fix-plan-<书>-与旧位置两条规则),因此删《孤舟》不会碰到《孤舟子》;只删<书>.json必然漏掉<书>-<hash>.json、<书>__style_2.json这类文件。执行时内容移入回收站(.novel-writer/trash/<书>-<时间戳>/)并写manifest.json,restore原样移回(目标已存在则逐文件跳过、绝不覆盖),purge才彻底删除;书名撞上_global/创作资料/ 点号目录时直接拒绝。面板同样可用:首页第一个分区新增一行「删除整本书」,点进去是独立页面(选书 → 预览清单 → 逐处勾选确认,页面下方常驻回收站,恢复 / 彻底删除都在同一页),书库概况里的每本书旁也保留快捷删除按钮;「报告历史」里还能逐份删除报告(同样进回收站,条目名「(报告历史)」);另有宿主路由POST /api/dsh-novel-writer/delete-book(仅回环)与POST /api/dsh-novel-writer/reports {action:"forget"},与工具共用同一套回收站。已知边界:移入回收站不释放磁盘空间,trash/不自动清理(面板数据目录体积会把回收站算进去);恢复按文件粒度、不做合并改写,同名文件一律跳过。工具数 20 → 21,参数契约与书库格式其余部分不变。 -
6.7.0· 2026-10-20 面板视觉全面改版:只改长相与说法,功能面不动起因是三条用户反馈:① 不好看 ② 太杂、功能难找 ③ 描述看得半懂不懂。本版只改网页端面板——
lib/client.js的渲染层、tools/client-src/V6-components.css(4.6 KB → 19.4 KB 的视觉系统)、图标源,以及同步更新断言的test/client-test.mjs。功能面完全不变:8 个视图一个不少(features/tools/baseline/creation/reports/model/lexicon/diagnose),ALL_TOOLS仍为 20,controller 的api.*语义与后端路由零改动。五条设计原则:① 一个页面只讲一件事(标题告诉你在哪,正文只放这一页的内容,不重复全局状态);② 安静的默认态(开着的开关不再整行变蓝、也不再贴「已开启」——开关本身就是状态;颜色只留给「需要注意」与唯一主操作);③ 说人话(描述写「对你有什么用」,工具 IDnovel_xxx、参数action=audit与内部术语不进主文案,最多收进「说明」展开区或 tooltip);④ 一种卡片、一种行、一种分区标题(全面板只用这三种积木,不再出现虚线框、无阴影框、蓝色胶囊标题等第 N 种容器);⑤ 路径与维护信息往下沉(文件路径、数据目录、state.json统一收进页面底部的「存储位置」折叠区,一个页面只出现一次)。具体变化:删掉每页的大 Hero 卡与子页的蓝色胶囊标题,主页只在标题下留一行副标题,分区标题改为 12px 灰色小标签;首页按「写作资料 / AI 行为 / 功能与工具 / 记录与维护 / 高级」分区,原来独立的「书库统计」卡并进「写作资料」卡底部的一行书库概况(「书库 N 部 · M 章 · X 字」,点开是每本书一行,含「7 天未动」);工具行统一由PreferenceRow承载,导航行行尾是「计数 + ›」;标题、按钮与分组名不再使用彩色 emoji,改为线性图标(图标源 52 个键、每个工具行一枚专属图标);阈值行的 slider 辅助输入一并移除,每维只留「低于 / 高于」两个百分比输入框。升级须知:无需迁移——不新增配置文件、不改书库格式、不改任何工具的参数契约;面板布局与导航有调整,如果你依赖旧的操作路径,按新界面的中文标签找一次即可。所有既有行为断言(剪贴板三条降级路径、reqId过期丢弃、破坏性操作二次确认、hook 稳定性)一条没删。设计规格全文见仓库内 tools/UI-REDESIGN.md(16 KB:工作纪律、设计原则、视觉系统、信息架构、文案风格)。 -
6.6.5· 2026-10-19 情感复杂度与置信度联动:不可采信时不再给顶格结论起因是一句用户反馈:「写作插件用情感曲线测试我的某些小说时会直接爆掉」「第一章的情感复杂度会直接爆掉」。核查结论是不是崩溃,是输出自相矛盾:同一份返回体里一边写着
confidence: "low"与「检测到高密度成人向内容 / 感官描写…请勿采信」的caveat,另一边照样给出complexity: { score: 0.6, level: "high" }——下游只要读level就会得出「情感复杂度高」,而这个结论已被工具自己否定。实测(书库里的《棍妹》第一、二章,成人向内容密度 8.99‰ / 9.77‰):两章都判level: "high",而两章的confidence都是"low"。本版让emotionComplexity(perChapter, reliability)接收可靠性信号({ polluted, pollutedBy, noData },由analyzeText在算完污染与零命中判定后传入,经emotionalQuantification透传):level降级为"unknown"(新增取值,此前只有low/medium/high),并新增reliable(boolean)与reliabilityNote(固定说明,可采信时为空串);score数值保留,但reliable: false已标明它的地位。触发条件三类:污染(成人向内容 / 感官描写 ≥ 1.5‰、或战斗/爽文 ≥ 3‰、或恐怖/疯狂 ≥ 3‰,阈值与词表都是既有实现、本版未改)、无数据(全文零情感词命中)与无 clean 数据(stats.length === 0,覆盖「只命中弱情绪词、clean 一个强词都没有」的情形——这一条由文档负责人独立实测抓出后于本版内一并修掉,同一早退分支不再给low+reliable: true);三条的score 0都表示「没测到」而不是「情感简单」。真凶之一在渲染层:lib/core.js的【情感量化】段此前打印JSON.stringify(q.complexity).slice(0, 120),而reliable/reliabilityNote排在对象末尾、必然被 120 字符截掉,于是「本项不可采信」永远到不了渲染文本;现在改成可读的一行(- 复杂度: <score>(<level>)熵 X/Y,多样性 N,主次 A↔B(k),章间漂移 有/无(基准 …)),并在reliable === false时单独起一行写出reliabilityNote;novel_style_report的渲染此前完全没有这一项,本版一并补上。如实交代:本版只做了 P0(可信度联动 + 渲染补齐),原计划的 P1「用 clean 计数重算复杂度」经核查已经满足(perChapter传的本来就是cleanScoresOf聚合的 clean 计数,实测第二章complexity.dominant = anger与cleanDominant一致、而 rawdominant是 joy),因此不写成「本版新增」;成人向内容 / 感官描写密集的文本的情感维度本来就不适用,本版做的是「别在不适用的语料上硬给一个高置信度的数字」、不是「让插件准确判断 成人向内容 的情感」,这类文本建议改用节奏 / 爽点 / 对话密度等维度;阈值(1.5‰ / 3‰)未调;情感复杂度没有「正确值」(score是熵归一化 0.5 + 多样性 0.25 + 主次冲突 0.25 的启发式聚合),本版只是让它在不可采信时不再冒充结论。工具数与参数契约不变(20 个)。另:CACHE_VERSION = PLUGIN_VERSION,分析缓存跟着插件版本号走,所以升级会自动失效旧口径的结果、不需要手动清缓存。详见 novel_sentence_analysis。 -
6.6.0· 2026-10-15 可观测性与诊断:本地事件日志 + 第 20 个工具 novel_diagnose起因是一句用户反馈:「有些错误光看提示看不出来,能不能加日志」。本版加了本地事件日志与诊断报告,但刻意不做成「给作者看日志文件」——作者不会去读
.jsonl,真正的消费者是替他操作的 AI。新增第 20 个工具 novel_diagnose:读日志 + 做五处体检——书库根、书库内容(书数/章数/字数/解析不出章号的文件/过短章,只统计不读正文)、插件数据目录(应有子目录、JSON 能否解析、zstd 压缩缓存、0 字节、超大与读不出的文件)、语义引擎(惰性探测,不加载模型)、开关与状态快照(哪些工具/功能被关了、总开关在哪一档、lastRoot 是否失效)——把近期调用与降级失败、「工具 × 书名」反复出问题的组合、高频失败类型、可执行建议与「本次覆盖与未覆盖」聚合成一份中文报告(report/events/clear;days默认 7、上限 90)。工具调用审计在注册层统一包一层,20 个工具一处覆盖(含诊断自身,不散落埋点),只记工具名、安全参数摘要(书名/章号/action 等定位字段 +content/text的长度)、耗时、状态与错误 code。静默失败的留痕是选择性的:6 个服务端模块里 catch 点 163(块级} catch161 + 链式.catch(2;旧稿的 164 把core.js注释里引用的写法也算成了代码,属口径过计),另有 84 处logEvent(调用点——这两个是不同总体:84 处里 77 处落在 catch 体内(=有留痕的 catch 点),其余 7 处根本不在 catch 里(书库根轨迹resolveRoot/noteRoot共 6 处 + 工具调用审计installToolAudit1 处,它在finally里),所以静默的 catch 点 = 163 − 77 = 86(旧稿的「静默 80」是拿 84 减 164 得来的,会少算 6 处;分 7 类,理由是"不存在/空是常态、已如实披露、重抛由审计层记、纯清理、允许的探测、有意不记的每项分支、无法区分 ENOENT");根解析另加一条只记「可疑决策」的留痕。本版内另修三处契约(都由实测触发):参数摘要的长度/计数派生键(contentChars/textChars/srcChars/filesCount/chaptersCount/termsCount)与name此前漏登记在白名单外被整批丢掉——「只记长度」当时并不成立,现补齐;分享层改为 fail-closed(readLogEvents只有显式forShare === false才返回本地层,其余一律脱敏);分享层的redacted: true由条件性改为恒带(层级标志,不是"有内容"标志)。另有一组 P0 修复:「读不到」不再被说成「没有」——只有ENOENT才说「尚未初始化 / 未登记 / 尚未保存 / 无创作资料」,文件存在却读不出来时只说「该文件存在,但读不出来」并给出路径与原因(novel_outline 的 read、开写包的锚包、novel_style_report 的action=get、连贯性审计的大纲对照四处)。覆盖口径如实交代:四处里三处(创作资料读取 / 风格判断读取 / 大纲对照)端到端生效;锚包那一处在真实工具路径上不可达(内部try里全是预读文本上的字符串操作,唯一会抛的assert在try之外),该分支只有函数级与源码级断言、没有端到端覆盖。另有一条残留同类缺陷(下版处理):把某章文件换成同名目录后,scanChapters的if (!entry.isFile()) continue会静默跳过它——该章从章表消失、诊断的「读不出来的文件」计数为 0、开写包degraded里也没有「读取章节失败」,即这一条路径上「读不到」仍被讲成「没有」。日志落在状态目录旁(~/.dsh/dsh-novel-writer/logs/events.jsonl,512 KB 轮转、留最近 3 份),不在书库根——理由很实在:最常见的故障就是「书库根不对」,那时.novel-writer/根本不存在或不可写。隐私是两级设计(口径在本版定稿时改准):本地日志靠字段白名单以元数据为主(时间 / 工具名 / 书名 / 章号 / 状态 / 耗时 / 计数 / 路径 / 错误 code),但自由文本字段(错误消息等)经收敛后至多保留一句(≤160 字)——所以本机日志里可能出现被错误消息回显的输入片段(实测:novel_lexicon找不到词条时会把传入的词条名回显进detail),日志文件不出本机;而任何离开本机的内容(诊断报告、面板「复制诊断包」、诊断路由)一律走分享层,自由文本整体剔除,报告层再把错误一律归类成固定 code(JSON.parse的报错会回显文件内容片段,而 summaries/plots/settings 正是由正文派生的)——因为值层面的长度 / 标点启发式从原理上无法保证自由文本里不含正文,真正的保证是「离开本机的东西不含自由文本」。报 bug 请用面板「复制诊断包」或novel_diagnose的输出,不要直接附本机日志文件。面板新增「诊断」入口(选统计窗口 + 一键复制诊断包,用于贴进 issue);新增GET /api/dsh-novel-writer/diagnose路由,与工具同一实现。本工具不判定对错、也不减少 bug,只让定位变快:静默失败只接了有诊断价值的那部分(「文件不存在」这类正常分支刻意不记),并发/性能只给已记录到的耗时、不做压测,各清单有条数与读取预算上限。工具数 19 → 20,参数契约与书库格式不变。 -
6.5.5· 2026-10-11 风格基线可指定范围:按全书 / 按部分,锚点不再跟着 AI 一起漂回应 issue #1「风格漂移」:AI 续写每章只参考上一章,从第 2 章起它参考的就是自己的产物;而「六维基线」与「原著锚段」原本都从全书取样——书越长 AI 占比越高,锚点自己也在漂(既测不出对原著的偏移,锚段也逐代变成 AI 的文风)。本版给侧栏「风格基线」面板加上基线范围:按全书(默认,=旧行为,存量书零迁移)/ 按部分(展开章节选择器,只用勾选的章——是「只用」,不是「优先 + 不够再补」)。正在检查的那一章永远排除(即使它在选中列表里):拿自己跟自己比必然「完美符合」,比不检查更糟。勾中的章(剔除目标章后)少于 3 章时推荐容差自动放宽到至少 ±25%,所以单章也能当基线;勾中的章若取不到(已改名 / 删除,或正文过短无法测量)会被跳过并如实计数,一章都取不到时回退「按全书」并在返回体里写明原因——两种文案:选择都失效 → 「(自定义选择已失效,已回退全书)」;只选中了本章自身 → 「(选中的章只有本章自身,不能作为自己的基线,已回退全书)」。范围按书保存(
<书库根>/.novel-writer/baseline/<书名>.json),与全局的容差设置(styleTolerance)不同层。风格自检 / 开写包 / 改稿台 / 风格画像 / 建章五路同源,baselineScope的文案随之反映用户的选择(开写包与建章还把范围写进模型可见的渲染文本)。插件不判定「你是否漂移了」(文风本就允许演变,那不可判定),只回答「相对你指定的标杆,这一章偏了多少」。工具数与调用参数不变(19 个),五路返回体各新增两个只读字段:baselineScope(文案)与baselineMode(all/custom)。 -
6.5.0· 2026-10-09 用语审计误报修复:子串守卫、行号定位与分档,并堵住正则回溯用语审计此前是纯子串匹配,而禁用词 93% 是 2 字词,于是「里正」会在「这里正是」上误报(实测 19 句无辜句子报出 15 条,其中 14 条是误报)。本版:新增子串碰撞守卫表(紧邻字/序列有实证才挡)、候选改为行号区间定位(不再贴原文,按需回读)、按词长分硬命中 / 待判 / 提示三档(2 字词交给模型读那一行自行判断,明确允许判"不是问题")、中式基准下禁词与客套词去重(旧版每词报两遍)。安全侧:登记的正则新增静态校验(拒绝嵌套量词与无界通配——实测同类模式在 29 字符上要跑 40 秒)并改为逐句扫描,被拒绝的模式会显式报出而不是静默跳过。新增逐词静音(
worldview.allowWords,仅本书生效)。工具数与参数契约不变(19 个)。 -
6.4.0· 2026-10-09 用语规范接线:欧式设定下的中式市井词拦截链全线接通开写包现在会渲染「语用规范」(称谓、客套、仪式、语气),禁用词表改为与用户登记合并而非整份替换,并取消了 10 条截断。连贯性审计的章节模式同时返回用语命中。工具数与参数不变(19 个)。
-
6.3.0· 2026-10-06 审计修复版:必用词分区、词表损坏保护与面板修复v6.3.0:本地测试版。第 19 个工具 novel_lexicon(必用词表,v6.2.0 新增)在本版修掉一批缺陷并对齐界面:开写包补上【必用词·优先使用】分区(此前plan.checklist的硬指令指向一个不存在的分区,avoid勿用词一条都到不了模型)、词表文件损坏后按层开关会把整层条目静默清空(现改为拒写并明确报「词表文件损坏」,原条目不再丢失)、面板「合并 / 全局」两个视图加载失败,均已修复;词表面板三层视图改用官方分段控件,改名撞车改为明确报错。工具数与参数契约不变(19 个)。 -
6.1.0章节查找、复测、文本统计、语义短段落与 MCP/界面修复v6.1.0:修复章节查找、复测、文本统计、语义短段落与 MCP/界面问题;当前规则以下列页面为准。历史版本的报告数值可能因计分修正而变化。 -
6.0.0界面全面重构(工具与状态文件零变化)v6.0.0 界面全面重构(工具与状态文件零变化)。本版把面板外观按 DSH 官方设计体系统一(--dsw-alias-*语义 token / 0.5px 发丝线 / 官方圆角尺度 / 官方 UI primitives),随后又按「官网式重构」收敛:强调色统一为 DeepSeek 蓝(state-business-primary)、主面板改「品牌光晕头部 + 分区 kicker + 图标卡 + 状态 pill」、内容卡由描边改为软阴影与悬停抬升、二级页标题与按钮家族统一、各级页面宽度恒定一致。若你是从旧版升级,工具数量、参数与返回结构均未变动,无需改任何调用。详解见 novel_sentence_config 的「界面为什么『看起来像 DSH』(v5.5.0)」一节。
v6.0.0 再进一层:源码分块 + 构建链装配、6 个实际使用的统一组件(单一行模式 PreferenceRow / 分组卡 GroupCard)、19+5 枚线图标、阈值 slider 辅助输入、页面级 push-pop 过渡动画;工具 / 参数 / 状态文件依旧零变化。 -
5.0.0新增开写包与改稿台;系统提示词增加「档位 × 场景」v5.0.0 新增两个工具。novel_chapter_brief(开写包)把动笔前要读的材料装配成一次只读调用;novel_fix_plan(改稿台)把风格自检的测量数据翻译成按优先级排序的待办清单。工具数 16 → 18,另为 novel_plot 增加action: "graph"结构视图(不新增工具,跨章计算并入既有伏笔工具)。两个新工具均不生成正文,也不调用在线模型。v5.0.0 另有系统提示词的「档位 × 场景」两个正交维度。档位(systemPromptMode:off/brief/full)决定注入多少,场景(promptScene:general/writing/revising/auditing/setup)决定注入什么;场景仅在full档下生效,且只改提示词内容、不改任何工具能力。老状态文件没有promptScene键时落到general(即 4.x 的通用工作流,本版仅在其中补入 7 行新工具入口指引),既有工作流不变。两字段的读写入口与完整语义见 novel_sentence_config。
工具总览
章节与文稿
分析与测量
设定、剧情与创作资料
审计与配置
该调哪个工具
工具数到 22 之后,「选对工具」本身也有了成本。下表按你想回答的问题给出口径;其中三个分析类工具名字最像,一并说明区别。
| 你想回答的问题 | 用哪个 | 主要输出 |
|---|---|---|
| 这本书整体是怎么写的(写作手法) | novel_sentence_analysis | 九类句式分布与排列规律、句式模板、段落结构、句长节奏、情感曲线、风格指纹与节奏建议 |
| 我这一章写得像不像原著 | novel_style_check | 单章 vs 全书其余章的指纹相似度与 high / medium / low 分级、偏差清单、六维出带判定、原著锚段 |
| 这本书是什么风格 | novel_style_report | 六维测量与 μ±σ 基线、词汇、题材与流派、情感、氛围 12 轴、语义距离、锚包与 AI 风格判断 |
| 动笔前我该读哪些材料 | novel_chapter_brief | 承接口、上一章钩子、大纲方向行、命中人物卡、未回收伏笔及埋设距离、世界观禁用词、六维基线、锚段与骨架、禁用清单与三段式 plan |
| 这一章要改哪里、改完没有 | novel_fix_plan | 按 severity → effort 排序的待办清单(带段落行号与改写方向,不给改写后的正文)+ verify 三态复测 |
| 全书有没有断线 / 丢人 / 忘伏笔 | novel_plot(action: "graph") | 伏笔生命周期与埋设距离、人物出场矩阵与连续缺席(≥ 5 章)、线索活跃度与最大空档、时间线顺序核对、大纲方向行对照 |
| 我想让 AI 必须用我的专有名词 / 惯用词 | novel_lexicon | 开写包注入的硬清单(lexicon 分组词条 + plan.checklist 硬指令)、成稿 audit 的覆盖率与未使用清单、以及「通用词替身顶替」的行号与原句(只读) |
| 出错了但看不出原因,或面板列不出书 | novel_diagnose | 近期调用 / 降级 / 失败聚合、高频失败类型、「工具 × 书名」反复出问题的组合,五处体检(书库根 / 书库内容 / 数据目录损坏 / 语义引擎 / 开关快照)与可执行建议,以及本次覆盖与未覆盖清单(只含元数据,可安全贴进 issue) |
novel_sentence_analysis / novel_style_check / novel_style_report 用的是同一套句式与情感引擎,读写的也是同一批缓存文件(<book>-chapters-metrics.json 分章六维测量、<book>-full.json 全书分析、analysis/<book>-<sha1>.json 句式报告历史、style-reports/<book>.json 风格判断)——分章测量的指纹按文件名排序后再哈希,因此三者交替调用命中同一份缓存,不会互相击穿。它们不合并,是因为回答的问题互不替代(怎么写 / 像不像 / 是什么风格),输出形状也各不相同;合并会把三份 output.schema 并成一份、并让三个稳定的工具名消失(MCP 客户端配置、文档页与提示词一起失效),代价大于收益。这里用「意图 → 工具」的对照表做消歧,而不是减少工具数。
共同约定
书库根目录与路径
所有工具接受可选的 root(含 novels 子目录的目录)。解析优先级:调用参数 root → 插件配置项 → MCP 启动参数 --root → 环境变量 DSH_NOVEL_WRITER_ROOT → 当前工作目录。MCP 形态下,参数里的 root 必须落在启动时 --root 指定范围内;越界时由 MCP 层静默回退到 --root,只写入 stderr 日志,调用方不会收到错误(插件层 resolveRoot 本身不做范围校验,范围校验只在 MCP 层 isInsideRoot 进行)。书名、分类等片段经 sanitizeSegment 过滤,防止路径穿越。
数据落盘
所有派生数据集中写在 <书库根>/.novel-writer/ 下:plots(伏笔)、settings(设定)、lexicon(必用词表)、summaries(摘要)、analysis(分析报告)、audits(审计)、embedding(语义索引)、style-reports(风格画像)。写盘采用临时文件 + 原子替换;失败会抛出 ENOVELWRITEFAIL 而不是静默丢弃。
唯一的例外是 v6.6.0 的事件日志:它写在状态目录旁——~/.dsh/dsh-novel-writer/logs/events.jsonl(受 DSH_NOVEL_WRITER_STATE 覆盖;512 KB 轮转、保留 3 份历史),不在 <书库根>/.novel-writer/。理由很实在:最常见的故障就是「书库根不对」,那时 .novel-writer/ 根本不存在或不可写,偏偏最需要留下证据。日志以元数据为主(工具名 / 书名 / 章号 / 状态 / 耗时 / 计数 / 路径 / 错误 code),但自由文本字段(错误消息等)经收敛后至多保留一句(≤160 字)——所以本机日志里可能出现被错误消息回显的输入片段,该文件不出本机;聚合查看与对外分享见 novel_diagnose(报告与面板「复制诊断包」走分享层,自由文本整体剔除)。
语义引擎的可用性
语义检索、语义风格距离与语义隐性情感依赖随包分发的 bge-small-zh-v1.5 量化模型(约 24MB)与 onnxruntime-web(WASM)。引擎不可用时这些能力自动降级为纯规则模式,其余功能不受影响;返回体会以 skippedDims 或专用文案说明降级原因,而非返回空结果。引擎相关的降级同样会记入事件日志,可由 novel_diagnose 聚合查看(本工具只聚合已记录到的事件,不会主动跑一次推理去探测)。
MCP 形态的边界
包内 mcp/server.mjs 把同样 22 个工具暴露为 stdio MCP 服务器(可用 Streamable HTTP 传输)。协议侧:未知工具返回 -32602(Protocol Error);支持 2025-11-25 / 2025-06-18 / 2025-03-26 / 2024-11-05 版本协商并原样回显;JSON-RPC 批量请求自 2025-06-18 起按规范拒绝;单行报文上限 4 MiB;novel_import 的 src 默认限制在书库根内,需显式加 --allow-external-src 才能放开。