Passer au contenu principal
L

dsh-doc-guard

lucky8197/dsh-doc-guard

Garde de cohérence documentation-code : audite les en-têtes de version, tableaux de changelog, arborescences, nombres de modules et de tests et références croisées entre documents pour détecter les dérives, avec des suggestions de correction en lecture seule triées par sévérité.

Installer

dsh plugin --profile web add github:lucky8197/dsh-doc-guard

README

dsh-doc-guard(文档-代码一致性守护)

Document-Code Consistency Guard for DeepSeek Harness. A read-only DSH plugin that audits your versioned Markdown design docs against the actual repository: header version numbers, changelog tables, directory-structure trees, module/test counts, and cross-document references. It detects drift (docs saying one thing, code being another) and outputs actionable, severity-sorted fix suggestions. Install with: dsh plugin --profile web add "github:<your-github-user>/dsh-doc-guard#main".

很多仓库用「版本化 Markdown 文档」记录设计:doc/ 下多份文档,头部有 文档版本:vX.Y, 更新记录是 Markdown 表格,正文含目录结构树、模块/系统清单、测试计数、验收数字与文档间互相引用。 代码改完后文档极易漂移:改了代码没加更新记录行、版本号没递增、结构树与真实文件树不符、 测试数与验收记录对不上、文档间引用版本不一致。

dsh-doc-guard 用纯启发式、全程只读地审计这些维度,检测漂移并按严重度输出可直接执行的修复建议。 是 DSH 生态中第一个做「文档漂移审计」的插件(context-doctor 只审上下文注入成本,不审文档漂移)。

特性

审计维度说明漂移类型严重度
版本号一致性头部 **文档版本:vX.Y**(或 > - 文档版本:vX.Y)与更新记录表最新行版本比对;文档间 对应技术设计 vX 引用值与目标文档当前版本比对version_mismatchhigh
更新记录表解析 | 版本 | 日期 | 更新内容 | 表格:最新版本≠头部版本、更新内容为空(禁止只改版本号不记内容)version_mismatch / missing_recordhigh / medium
代码变更未记录最近代码文件 mtime 晚于记录表最新日期超过窗口 → 「可能有未记录的代码变更」(mtime 启发式,安全边界内不执行 git)stale_recordlow
结构树漂移代码块中 ├──/└── 目录树 vs 真实文件系统(自动排除构建/VCS 目录;目录级摘要树只比目录层级)tree_missing / tree_extramedium / low
模块/系统清单N 个 System / N 份文档 / N 个测试文件 等计数声明 vs 真实计数(目录条目/文档数/测试数)count_mismatchlow
测试计数Core 199/199、Net 91 通过/4 跳过 等验收数字 vs 测试源文件静态统计(按扩展名识别 [Fact]/it(/#[test]/def test_/@Test/func Test,不执行测试)count_mismatchlow
文档间交叉引用详见 §X / 见实现文档 §X → 被引文档是否存在;对应技术设计 vX → 版本值是否等于被引文档当前版本cross_ref / version_mismatchhigh

全部启发式可配置、可忽略;误报宁可少——无法确定性解析的目标一律跳过,不猜测。

快速安装

# GitHub 源(构建产物 lib/ 已入库,无需构建)
dsh plugin --profile web add "github:<your-github-user>/dsh-doc-guard#main"

安装后重启 dsh web,doc_guard 工具即出现在模型工具列表;dsh --profile web --dump-config | grep doc-guard 应输出含 id: doc-guard 的挂载记录。

工具用法

doc_guard
  参数:
    cwd?: string          审计起点目录(默认当前会话工作目录)
    docs?: string[]       要审计的文档路径(默认自动发现 cwd 下 doc*/ 目录 + 根目录含版本头的 *.md)
    includeCounts?: boolean  是否做测试计数/模块计数启发式(默认 true)
    detail?: 'summary' | 'developer'  默认 summary;developer 附可定位 receipt(路径+行号)
  输出:canonical JSON 报告(见下),渲染为分节文本

canonical JSON

{
  "tool": "doc_guard",
  "version": 1,
  "cwd": "/path/to/repo",
  "docs": [
    { "path": "doc/实现文档.md", "headerVersion": "v1.43",
      "records": [{ "version": "v1.43", "date": "2026-08-15", "hasSummary": true }] }
  ],
  "drifts": [
    { "severity": "high",
      "kind": "version_mismatch",
      "doc": "doc/实现文档.md",
      "detail": "头部文档版本 v1.43 与更新记录表最新行版本 v1.42(第 8 行)不一致",
      "evidence": "文档版本:v1.43;更新记录 v1.42 / 2026-08-14",
      "fix": "在 doc/实现文档.md 更新记录表追加 v1.43 行(含日期与更新内容),或把头部版本改回 v1.42" }
  ],
  "stats": { "docsScanned": 3, "driftCount": 1 },
  "suggestions": [ { "severity": "high", "text": "…" } ]
}

detail=developer 时附加 receipt:每份文档的版本头/记录表行号、每条漂移所在行号、 测试文件静态统计明细(路径+标记数)——供 Agent 定点修复。

配置(cordis 配置节)

# ~/.dsh/profiles/web/cordis.patch.yml 或 cordis.yml 中
- insert:
    - id: doc-guard
      name: 'dsh-doc-guard'
      config:
        docsPatterns: ["doc/**/*.md", "*.md"]     # 自动发现的文档 glob
        ignoreTreePaths: [".git", "bin", "obj", "node_modules", "dist", "lib", ".dsh"]  # 结构树忽略
        countTolerance: 1                          # 计数对比容差(±N 内算一致)
        staleCommitWindow: 5                       # "代码改了文档没动"窗口(天,mtime 启发式)
        maxEvidenceLen: 200                        # 报告 evidence 片段最大长度(字符)
        maxFileBytes: 524288                       # 单文件大小硬上限(字节),超限跳过

staleCommitWindow 语义为「最近 N 天内有代码变更但文档记录未跟进」。 因安全边界禁止执行 git(见下),实现为只读 mtime 启发式而非提交数。

安全边界(硬性要求)

  • 全程只读:只用 ctx.fs 的 resolve/stat/readText/listDir 子集; 唯一的 node:fs 使用是只读 stat 取文件 mtime(陈旧度启发式),不写、不删、不执行;
  • 单文件 > 512 KB 跳过(maxFileBytes 可配,硬上限);
  • 报告不含完整文件内容:只含路径、统计与 ≤200 字符的证据片段;
  • 不执行测试、不跑构建:测试计数用静态扫描(按扩展名匹配测试标记);
  • 不修改任何文件:审计前后仓库内容逐字节不变(有测试断言)。

防误报设计(误报宁可少)

  • 更新记录表区域(历史快照)不参与当前状态判定:v1.42:对应实现文档 v1.41 是历史事实,不是当前引用;
  • 里程碑/作用域验收数字(M3 83/83 全绿、Core 153/153 + Net 24/24)不与全局总数对比—— 仅当全文是单一通用标签(tests 290/290 等)且声明数 ≤3 时才与静态统计对比;
  • 目录级摘要树(无文件名明细)只比对目录层级,不报 tree_extra;
  • 树中未展开的目录(列出但无子行)不报其内容为 extra;隐藏/临时文件(.env、*.tmpdir)忽略;
  • 流程图/时序图/ASCII 框图(└──▶ M5 ──▶ M6、───┬───┘)不会被误判为结构树;
  • 多树块文档只取行数最多的主结构树;game01.slnx 这类文件标签不会当目录根。

工程结构

dsh-doc-guard/
├── package.json          # name=dsh-doc-guard, type=module, main=./lib/index.js,
│                         # dsh.bundle.patch=./cordis.patch.yml; peerDeps: @deepseek-ai/cordis
├── cordis.patch.yml      # - insert: [{ id: doc-guard, name: 'dsh-doc-guard' }]
├── tsconfig.json         # 编译到 lib/types/(纯 tsc,无打包器)
├── scripts/
│   ├── setup-dsh-deps.mjs    # 定位本机 DSH 安装并链接 @deepseek-ai/* 依赖(junction/symlink)
│   ├── build.sh              # setup + tsc(POSIX)
│   ├── build-win.mjs         # 等效 Windows 构建(无 bash 依赖)
│   ├── self-test.mjs         # 对任意仓库跑审计引擎
│   └── verify-drift.mjs      # 注入漂移验证(真实仓库拷贝 + 篡改版本号)
├── src/
│   ├── index.ts          # apply(ctx):注册 doc_guard 工具 + 配置读取
│   ├── audit.ts          # 编排:runAudit 全链路 + developer receipt
│   ├── scan.ts           # 文档发现、版本头/更新记录表/结构树/计数/交叉引用解析、测试静态统计
│   ├── diff.ts           # 结构树 vs 磁盘对比(虚拟根/摘要树/穷尽目录处理)
│   ├── analyze.ts        # 六类漂移判定 + 严重度分级 + 修复建议 + 分节渲染
│   └── types.ts          # canonical 类型 + 配置 + fs 服务面子集
└── tests/                # node --test(54 用例,零测试依赖,真实临时目录端到端)

开发 / 测试 / 构建

npm install                 # 安装 typescript/@types/node(devDeps)
npm run setup               # 定位本机 DSH 安装,链接 @deepseek-ai/* 依赖
npm test                    # node --test 'tests/*.test.ts'(54 用例)
npm run build:win           # Windows 构建;POSIX 用 npm run build(scripts/build.sh)
node scripts/self-test.mjs /path/to/repo    # 对真实仓库跑审计引擎

构建产物 lib/(lib/index.js + lib/types/*)入库提交——GitHub 源安装依赖它,用户无需构建即可 dsh plugin add。

FAQ

Q: 为什么不执行 git log 判断「代码改了文档没动」? 安全边界禁止执行任何命令(含 git)。实现为只读 mtime 启发式:最近代码文件修改时间 vs 更新记录最新日期。

Q: 测试计数为什么有时不报? 只有「全文单一通用标签(tests/测试/全部)且声明 ≤3」的验收数字才与全局静态统计对比; Core 199/199、M3 83/83 这类带作用域的里程碑数字无法静态映射,宁可少报。

Q: 报告会泄露文档内容吗? 不会。报告只含路径、统计与 ≤200 字符证据片段(maxEvidenceLen 可调)。

Q: 支持哪些测试框架标记? 按扩展名静态匹配:C# [Fact]/[Theory]、JS/TS it(/test(、Rust #[test]、 Python def test_、Java/Kotlin @Test、Go func Test。

License

BSD-3-Clause。见 LICENSE。

Plugins associés