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_backup 的 restore/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-plugin、dsh-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_backup,mode 为 restore 或 backup |
全量(整批覆盖 / 入库前体检) |
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 批量改写)只详列fail,warn压成一行汇总 —— 本机 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_SCHEDULER 是 Symbol()(非 Symbol.for),跨实例注册失败会导致所有工具调用崩。dsh-llm 仅用于构造回传上下文消息,缺失时插件降级为"审核照跑、不注入上下文"。
开发
pnpm install
pnpm run build # tsc → dist/
pnpm test # node test/smoke.mjs:假 ctx + 真实审核引擎,端到端
pnpm run typecheck
冒烟测试在临时目录里造两个技能(一个只有 warn、一个含 fail),用假 ctx(tools.register 捕获工具、subprocess.spawn 委托 node:child_process、on() 捕获 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