Skip to content

dsh-skill-audit

Verified

@caesarloo/dsh-skill-audit · v0.1.0 · MIT

Audit DSH skills automatically: a host-layer tools/post-execute plugin that runs the skill-audit engine after skill files change (write/edit/shell) or after a dsh_config_git_backup restore, feeding findings back to the model as context; also registers the

Install

dsh plugin add @caesarloo/dsh-skill-audit

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

@caesarloo/dsh-skill-audit

DSH 技能一改就自动被审核 的插件:监听 tools/post-execute,在技能文件被 write/edit/shell 改动之后、或在 dsh_config_git_backuprestore/backup 之后,跑一遍技能审核,并把结论作为上下文回传给模型。同时注册 skill_audit 工具供按需调用。

为什么需要插件(而不是 hooks.json)

DSH 自带的 Claude Code 钩子桥接(@deepseek-ai/dsh-hooks-claude-code)通过 ctx.shell 执行钩子命令。当宿主没有可用的沙箱 runner 时(Windows 上 ACL 后端未挂载时的实测情形),执行器按设计 fail-closed:命令根本不会启动,会话日志里只留下

hook/invoked  PostToolUse ...
hook/result   decision=pass  stderr=sandbox mode "workspace-write" is requested
              but no sandbox backend is usable on this host; refusing to run the command unconfined

—— 也就是说 hooks.json 配置得再正确也没用。同类第三方 hooks 插件(如 dsh-hooks-plugindsh-plugin-hooks)同样走 ctx.shell,会撞同一堵墙。

本插件在 harness 进程内ctx.subprocess(host 层)直接跑审核脚本,不经过 ctx.shell,因此不受沙箱策略限制;这也是官方对"没有 Claude Code 对应物的定制行为"给出的推荐形态。

安装

# 从 npm(推荐)
dsh plugin --profile web add @caesarloo/dsh-skill-audit

# 本地开发(link 到工作副本)
dsh plugin --profile web add C:\workspace\dsh-skill-audit

装完重启 dsh(bundle 层变更无 HMR;dsh --profile web --dump-config 应能看到 id: tool-skill-audit)。

前置

审核逻辑不在本插件内(单一真源),默认调用:

<DSH_HOME>/skills/skill-audit/scripts/audit-skills.ps1

skill-audit 技能的静态审核引擎(frontmatter 契约、脚本 UTF-8 BOM + PowerShell 5.1 可解析、SKILL.md 引用完整性、凭据泄漏、机器专属路径、危险命令)。该脚本不存在时:skill_audit 工具返回明确错误,自动触发静默跳过(不会因为审核引擎缺失而干扰正常写文件)。

配置

- insert:
    - id: tool-skill-audit
      name: '@caesarloo/dsh-skill-audit'
      config:
        skillsRoot: 'C:\Users\me\.dsh\skills'        # 可选,缺省 <DSH_HOME>/skills
        auditScript: '...\audit-skills.ps1'          # 可选,缺省 <skillsRoot>/skill-audit/scripts/audit-skills.ps1
        autoAudit: true                              # 可选,false = 只保留工具、不做自动触发
        powershell: 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
        timeoutMs: 120000                            # 可选,单次审核超时
        maxContextChars: 2000                        # 可选,回传上下文的字符上限

正常使用无需任何配置(路径从 DSH_HOME 推导)。

自动触发规则

工具调用 审核范围
写入类文件工具(write/edit/multi_edit/notebook_edit/apply_patch …),目标路径落在 <skillsRoot>/<技能>/ 只审该技能(快,约 1 秒)
只读工具(read/glob/grep 不触发 —— 它们同样携带 file_path 却不修改内容;不加这条白名单,每读一次技能文件就会注入一次审核上下文
dsh_config_git_backupmoderestorebackup 全量(整批覆盖 / 入库前体检)
pwsh / bash 等 shell,命令行同时含 skills 与写操作迹象(Set-Content/Copy-Item/Remove-Item/robocopy/git checkout …) 全量(shell 里改了哪个文件无法精确判定,宁可全量)
其它工具、或路径不在技能目录内 不触发,静默 next()
  • 审核在 tools/post-execute(写入之后) 执行,因此审的是新内容(对比:pre-execute 时文件还没落盘,只能审到旧版本)。
  • 上下文分级:定向单技能(write/edit)时详列 fail + warn全量场景(restore/backup、shell 批量改写)只详列 failwarn 压成一行汇总 —— 本机 11 个技能里 9 个各有 1~3 条元数据类 warn,逐条列出会把上下文挤爆并失去焦点。全量且只有 warn 时完全不注入(背景噪音不该打断写入);全部通过时同样保持安静,只写 <DSH_HOME>/vet/skill-audits/
  • 自动触发永远不会影响工具调用本身:任何异常都被吞掉并委托 next()

skill_audit 工具

skill_audit()                      # 审计 skillsRoot 下全部技能
skill_audit({ skill: 'a,b' })      # 只审指定技能(逗号分隔)

返回逐技能的通过/注意/失败与逐条发现,并把同样的 JSON 结论写入 <DSH_HOME>/vet/skill-audits/latest.json + 时间戳档,保留最近 40 份)。

依赖约定

@deepseek-ai/dsh-tools@deepseek-ai/dsh-subprocess@deepseek-ai/dsh-llm 一律声明为 optional peerDependencies,由宿主提供,本包不打包它们。这是刻意的:这两个包若与主包各装一份,会形成两个模块实例,而 TOOL_RUNTIME_SCHEDULERSymbol()(非 Symbol.for),跨实例注册失败会导致所有工具调用崩dsh-llm 仅用于构造回传上下文消息,缺失时插件降级为"审核照跑、不注入上下文"。

开发

pnpm install
pnpm run build      # tsc → dist/
pnpm test           # node test/smoke.mjs:假 ctx + 真实审核引擎,端到端
pnpm run typecheck

冒烟测试在临时目录里造两个技能(一个只有 warn、一个含 fail),用假 ctxtools.register 捕获工具、subprocess.spawn 委托 node:child_processon() 捕获 waterfall 处理器)驱动真实实现,断言:工具注册、planAudit 的六类范围判定、parseReport 的容错、定向/全量审核输出、上下文注入与静默路径、引擎缺失时的 fail-closed。

SMOKE_PLUGIN_DIST 可指向另一份构建产物,但该副本必须位于能解析 @deepseek-ai/dsh-tools 的树中;不要指向 dsh 安装树(~/.dsh/profiles/web/node_modules/...)——裸 node 在那里会解析到版本不匹配的 dsh-llm 副本。

边界(明确不做)

  • 不实现审核规则本身(在 skill-audit 技能的脚本里,此处只负责触发与回传);
  • 不改写工具输入、不阻塞工具调用(fail 也只在上下文里告知模型);
  • 不覆盖 SessionStart/Stop 等非工具事件;
  • 不做技能目录的文件系统监视(dsh-skill-filesystem 已有 watcher;本插件只在工具调用后触发)。

License

MIT