长文创作一致性守卫:扫描会话正文,发现人物年龄、等级、境界、年份等设定跨章节矛盾,点击直接跳转到冲突原文位置。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-consistency-guard
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:bycall/dsh-consistency-guard
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
DeepSeek Harness(dsh)长文创作一致性守卫插件:扫描会话正文中的人物设定、时间线、数值型设定,自动发现跨章节矛盾,并点击直接跳转到冲突原文位置。
背景:百万字长篇创作中,人物年龄/等级/境界、时间线、数值设定在数十次对话迭代后极易失控。dsh 内置没有跨章节内容审计能力,现有写作类插件做的是编辑与导出,本插件补上「一致性守卫」这一环。
功能
| 能力 | 说明 |
|---|---|
| 实体提取引擎 | 纯前端规则引擎,从会话正文中提取属性设定:年龄(25 岁 / 二十七岁)、年份(1998 年 / 星历 412 年)、身高(180cm / 身高 180)、等级、境界。中英文数字统一归一化,25岁 与 二十七岁 可正确比对。 |
| 实体归属 | 优先匹配设定字典中的已知人名,其次按常见姓氏识别,最后用「动词/属性词邻接」启发式回退;内置停用词拦截,避免把「境界三层的修士」误判成人名。 |
| 设定字典 | settings.section 插槽提供编辑器:维护 实体 / 属性 / 标准值 条目,保存在浏览器本地存储(localStorage),编辑后 dock 面板即时生效,无需重载。 |
| 两级冲突检测 | 数值矛盾(numeric):同一实体同一属性出现两个不同数值——硬性矛盾,如林默第 1 轮 25 岁、第 7 轮 27 岁。表述差异(wording):非数值属性的表述漂移,低置信度提示。无归属的 mention 归入 (unattributed) 桶,只给提示、不误报硬冲突。 |
| 冲突 dock 面板 | 输入框上方( conversation.input.dock 插槽)显示冲突数胶囊:无冲突为绿色、有冲突为红色;点击展开冲突列表(portal 到页面根部,不受布局容器裁剪),按「数值矛盾优先 + 轮次」排序。 |
| 点击定位跳转 | 点击任意冲突项 → 切回「对话」视图 → 平滑滚动到第二个冲突值所在消息并红色高亮。若目标在未加载的更早记录中,自动调用 loadOlder(最多 3 次)后重试。 |
安装
dsh plugin --profile web add file:/path/to/dsh-consistency-guard
然后在 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 数组中加入 "dsh-consistency-guard",重启 DSH.app(或硬刷新浏览器窗口)生效。
卸载
dsh plugin --profile web remove dsh-consistency-guard
工作原理
- 插槽注册(客户端):通过
ctx.slots注册两个服务——conversation.input.dock(idconsistency-guard-dock):输入框上方的冲突胶囊 + 展开列表。settings.section(idconsistency-guard-settings):设定字典编辑区。
- 数据来源:插槽组件拿到会话快照,读取
snapshot.chat.order/snapshot.chat.nodes,取assistant的data.blocks[kind=text]与user/steering的文本作为正文来源;工具调用与代码输出刻意跳过,避免把代码里的数字当成设定。 - 扫描流水线:正文 → 按句切分 → 句内属性模式匹配(
年龄/岁/身高/cm/等级/境界/年份)→ 值归一化 → 实体归属 → 按(实体, 属性)分组 → 组内出现两个及以上不同值即判定冲突。 - 属性轴区分:
境界/修为与等级/级别是中文类型小说中两个独立维度,刻意不合并,否则「境界三层,等级 9」会被误判为矛盾。 - 跳转机制:复用 dsh 聊天视图的内置语义锚点
data-chat-anchor-key="<key>",跳转 = 找到该行 →scrollIntoView+ 红色高亮;点击胶囊先按 label 点击[role="tab"]切回「对话」(中文「对话」/ 英文「Chat」,回退首个 Tab),再轮询等待目标行挂载。 - 字典联动:字典保存在 localStorage,
apply内维护一个极简订阅器(subscribe/getDict/setDict),设置区保存后即时广播给 dock 面板。
目录结构
dsh-consistency-guard/
├── package.json # dsh.bundle.patch + dsh.client + exports["./client"]
├── cordis.patch.yml # 挂载插件到 profile 层叠
├── lib/
│ ├── index.js # 服务端挂载入口(UI-only,最小实现)
│ └── client.js # 客户端 bundle(window.__ModuleLoader__.load 格式)
└── test/
└── smoke.cjs # 冒烟测试(mock ModuleLoader + ctx + 纯函数断言)
开发说明
- 纯手写客户端 bundle(仅依赖
react,零构建步骤),格式遵循 dsh web 的 lazy-CJS 模块表契约:window.__ModuleLoader__.load({ id, factory })。 dsh.client.inject声明了插件可用的客户端服务:slots/sessions/locale。- 所有核心逻辑(实体提取、归一化、人名校验、冲突检测、字典读写)都是不依赖 react 的纯函数,通过
exports.__test暴露给冒烟测试。 - 校验:
node --check lib/client.js;冒烟测试node test/smoke.cjs(覆盖工厂物化、两个插槽注册、中文数字归一、实体归属、去重、人名校验、端到端冲突检测)。
冒烟测试覆盖
factory materialized; exports: [ 'apply', 'inject', '__test' ]
registered slots: ["conversation.input.dock[consistency-guard-dock]","settings.section[consistency-guard-settings]"]
cnNumToInt: ok
normalizeValue: ok
extractMentions attribution + dedup: ok
plausibleName: ok
mentions: 8 conflicts: 2
detectConflicts end-to-end: ok
loadDict without localStorage: ok
ALL CHECKS PASSED
端到端用例模拟《归墟》修订场景:林默第 1 轮 25 岁 / 第 7 轮 27 岁(报数值矛盾)、沈砚青等级 9 → 12(报数值矛盾)、苏晚晴两处均为 27 岁(不误报)、境界三层与等级 9 不合并(不误报)。
已知限制
- 规则引擎覆盖常见中文小说设定的属性词,未收录的属性不会参与比对;设定字典用于补强专有名词。
- 人名识别基于常见姓氏表 + 启发式,生僻姓名建议加入设定字典以确保归属准确。
- 设定字典保存在浏览器 localStorage,换浏览器或清理站点数据后需要重新录入。
路线图(二期)
- 伏笔追踪:标记「伏笔-回收」对,扫描未回收伏笔
- 时间线校验:事件先后顺序矛盾检测
- 语料库统计:章节字数、出场角色频次、设定引用热图
- 一致性审计报告(Markdown)一键导出
License
MIT
链接
同类插件
tt-a1i/archify#integrations/deepseek-harness★ 92724
从仓库或系统描述生成经过校验的自包含交互式架构图、流程图、时序图、数据流图和生命周期图。
dream-num/dsh-univer-office★ 657
为 DeepSeek Harness 打造一个真正的办公环境。Univer Office 插件将电子表格、文档、幻灯片、画布、多维表格等汇聚到同一个运行时——数据互联、修改经过校验、变更按版本管理,并以隔离工作树支持多 Agent 协作。
ECNU/EduWork#dsh-knowledge-studio★ 275
基于工作区资料的 Studio,复用 DSH 模型与共享成果服务,制作报告、演示文稿、表格、思维导图、测验、闪卡及音视频。Office 生成需 Python 3.12+ 及相关依赖,并配置 DSH_OFFICE_PYTHON;媒体渲染需 Chromium;本地语音转写另需 whisper.cpp 和模型。
PerryLink/dsh-industry-research★ 215
面向 DeepSeek Harness 的确定性行业研究报告:公司与行业研究流程基于分阶段证据产出结构化、可核验的报告。
HuanLinOTO/dsh-plugin-mineru★ 51
向模型暴露 MineRU 文档解析工具。
PolinniZhong/dsh-knit★ 48
把会话工作区里已有的 Markdown 文档、源码、图片与视频列进 DSH 侧边栏,按与当前对话的相关性排序。默认的词法模式用最近几条消息在本地与标题、摘要、正文做带 IDF 加权的匹配(BM25)—— 不调用模型、没有网络出口,内容不出本机。列表来自工作区扫描,而不是「最近打开记录」,所以重启 DSH 或新开会话都不会变空。排序结果组织成主要 / 辅助 / 相关三层的阅读顺序,每一条都写明可核验的理由(命中了哪个字段、被哪一篇引用),点一行即可就地预览:Markdown 按渲染后的样子显示、相对路径图片真实渲染、源码走宿主自带的语法高亮、视频走 HTTP Range 流式播放。同一份 Context Pack 也作为 knit_docs 工具交给 agent。后续版本陆续补上读取证据与生命周期(归因在读那一刻冻结)、固定 / 排除(排除先于检索生效,且可恢复)、关系证据(引用 / 导入 / 测试,带行号)与增量索引(重启后复用)。v0.23 起还多一条可选的混合检索:默认关闭,只有你自己配好 Ollama 或 OpenAI 兼容的 embedding 服务才会生效。它生效时,发出去的是你这句查询原话加上每篇候选文件的标题与摘要 —— Markdown 的摘要取自正文首段(不超过 60 字),代码的摘要是它所在的工作区相对目录,图片 / 视频贡献的是文件名;完整正文与绝对路径都不发送,指向本机服务(loopback)时内容不出这台机器。v0.24 起还能做变更关联:用一条只读的 git status(固定 argv、不走 shell、子进程环境白名单),配合同一套引用 / 导入 / 测试 / 提及证据,指出这次改动大概率该一起看哪些文件 —— 默认关闭。语义检索的收益仍待真 provider 实测,因此不承诺召回提升。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。