- Inicio
- Plugins
- Herramientas y funciones
- dsh-consistency-guard
B
dsh-consistency-guard
bycall/dsh-consistency-guard
Consistency guard for long-form writing: scans conversation prose for character, timeline and numeric setting conflicts across chapters, then jumps straight to the conflicting message.
Instalar
dsh plugin --profile web add github:bycall/dsh-consistency-guardREADME
dsh-consistency-guard
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
Plugins relacionados
T
archify (deepseek-harness)
tt-a1i/archify
68.2khace 9 horasHerramientas y funcionesMIT
T
WeKnora (dsh-weknora)
tencent/weknora
27.9khace 10 horasHerramientas y funciones
T
weknora
tencent/weknora
20.2kel mes pasadoHerramientas y funciones
T
BrowserSkill (dsh-plugin-browserskill)
tencent/browserskill
6khace 13 horasHerramientas y funcionesMIT