npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-consistency-guard

v0.1.0

Published

Consistency guard for long-form writing in DeepSeek Harness: scans conversation prose for character, timeline and numeric setting conflicts, then jumps straight to the conflicting lines.

Downloads

256

Readme

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(id consistency-guard-dock):输入框上方的冲突胶囊 + 展开列表。
    • settings.section(id consistency-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