liuyun847/dsh-host-compliance-check

dsh-host-compliance-check

DSH 宿主插件:轮末自动派发需求合规检查子智能体 (DeepSeek Harness)

미분류dsh

dsh-host-compliance-check

DSH(DeepSeek Harness)宿主插件:模仿 Trae 的 stop-hook 配置(hooks.json 的 PostToolUse + Stop → decision 移交),不自动派发检查子智能体;在主会话 轮次正常结束时,若本轮修改过文件,向主会话注入一段 notice 形态的合规提醒 提示词(source.kind='plugin:compliance-check' + source.form='notice' + 一句话 summary,正文带文件清单),由主模型当场自行判断:直接收尾 / 简要自查 / 派 subagent 深入检查(按其结算通知收活)。

(v0.4.0 变更) 与 0.3.x 的差异:

  • 收集信源从"会话事件日志 + run_code 源码启发式解析"改为 tools/result 实时精确记录 —— 顶层 write/edit 与 run_code 内 tools.write/edit 子派发都经工具管道 emit tools/result(exec.name/exec.arguments 为真实 调用,exec.agent 携带会话),file_path 精确,删除正则猜源码的脆弱逻辑;
  • 注入消息由裸 plugin 文本改为 notice 形态(form:'notice' + summary ≤120,boundContextSummary 语义),不再以 [AUTO] 文本冒充用户输入;
  • diag 日志路径改为基于 DSH_HOME/用户主目录推导,不再硬编码。

(v0.4.1 变更) 注入正文去掉"阻塞等待"措辞:是否前台等待由会话自身的人格纪律决定, 插件只负责提醒与给出手续 —— 与「永不阻塞」型预设(coordinator)的指令冲突由此消除。

(v0.4.2 起) 会话格式 v4 兼容(DSH 0.1.7-rc.1 起):v4 的准入规则 要求 user/message 的 source.kind 是非空字符串且不得等于 'plugin' (旧版"插件包装"写法已退役),违反时该消息落盘被拒、整轮以 format v4 message requires a producer-owned source kind 失败(错误码 UNKNOWN)。 第三方插件注入消息的正确写法是 kind: 'plugin:<插件名>',且 source 里不再有 plugin 字段 ⇒ 本插件注入消息由 { kind:'plugin', plugin:'compliance-check' } 改为 { kind:'plugin:compliance-check' };form / summary 语义与 UI 折叠展示不变 (UI 按 source.kind !== 'user' 判为注入行、按 source.form 折叠)。

特性

  • 轮末提醒:主会话轮次正常结束时,若本轮修改过文件且本用户输入尚未提醒过, 注入 notice 提醒(进 next-step 队列 → 本 turn 继续,主模型当场看到并响应, 响应完 turn 才真正结束 —— 等价 Trae 的 block)
  • 精确收集 = tools/result 实时记录(对顶层 write/edit 与 run_code 内子派发 均触发;scope-filtered 按 agent 分发):
    • exec.name ∈ {write, edit} 且成功 → 提取真实 file_path;
    • 事件日志仅作兜底(顶层 tool/call 的 write/edit),不再解析 run_code 源码
  • 只支持标准模式写入;PTC 裸写(await import('node:fs') + 直接文件 API, 绕过 tools 绑定)不经过工具管道、不产生 tools/result,本插件检测不到 (已知限制;合规做法是程序内用 tools.write/edit)
  • 每用户输入最多提醒一次(新用户消息经 agent/pre-step 复位记录与标记)
  • 只对主会话触发:GUI 恢复/续写历史会话创建的 fork 会话(带 parentSession、无 origin)视为主会话,照常提醒;仅排除子代理会话(header origin: 'subagent'),避免嵌套提醒
  • 提示词携带全部用户输入历史(按时间顺序拼接、跳过插件注入,超长截断保留最新)供对照, 不只取最近一条;内置自查清单与处理方式引导(可直接结束 / 派 subagent 深查,按其结算通知收活)
  • 提醒以 notice 消息呈现(source.kind='plugin:compliance-check' + source.form='notice',summary 一句话 ≤120),UI 折叠展示、不冒充用户输入

配置(cordis.patch.yml 的 entry config)

字段默认值说明
skipPaths[]跳过匹配的路径(RegExp/字符串数组),命中则不记录
diagfalse写诊断日志到 ~/.dsh/compliance-diag.log(DSH_HOME 优先;排查用)

(0.2.x 的 providerName/promptTemplate/diffMaxChars/diffMaxLinesPerFile/watchTools 与 0.3.x 的源码解析逻辑均已移除。)

安装

本包是组合包(bundle):注册行(id: compliance-check)随包发布在包内 cordis.patch.yml 里, 宿主按 profile package.json 的 dsh.profile.bundles 加载 —— 不需要再往 profile 的 cordis.patch.yml 里贴任何 - insert: 行。

在 profile 目录(如 ~/.dsh/profiles/desktop/)下执行:

dshpm add file:./plugins/dsh-host-compliance-check --profile desktop

dshpm 是替代 dsh plugin add 的装卸 CLI,装包的同时会把包名写进 dsh.profile.bundles; 装完重启 dsh 生效。

  • 启停:插件页 →「已安装」区里本卡的总开关(写 dsh.profile.bundles); 点开卡片后每一行还有行级开关(向 profile 的 cordis.patch.yml 写 disabled 覆盖 —— profile 层在包层之后应用,所以覆写优先)。 ⚠ 包内注册行当前是 disabled: true(随迁移保持停用,与迁移前一致)⇒ 装好默认不生效。 要启用它,拨这一行(compliance-check)的行级开关:它向 profile 的 cordis.patch.yml 写 disabled 覆写,而 profile 层在包层之后应用 ⇒ 能盖掉包内那一行;或者直接删掉包内 cordis.patch.yml 里的 disabled: true(改完记得同步副本,并按上面口径触发一次重组合)。 ⚠ 不要用卡片总开关:那只决定本包在不在 dsh.profile.bundles 里,而它本来就是开着的 (随迁移进入 bundles) —— 总开关关掉只会整个卸载本包,不会让这一行生效。
  • 卸载:dshpm remove dsh-host-compliance-check --profile desktop。 ⚠ 若 profile 的 pnpm 带供应链策略,pnpm remove 会报 ERR_PNPM_RESOLUTION_POLICY_VIOLATIONS_UNHANDLED;绕过办法是进 profile 目录直接跑 pnpm remove dsh-host-compliance-check --config.minimum-release-age=0 (dshpm 的 --fast 只对 add 有效 —— pnpm remove 不接受 --minimum-release-age 这类参数)。

注意:本仓库以 plugins/dsh-host-compliance-check/ 为活源,运行时加载 node_modules/ 下的 file: 拷贝(二者独立)。改动活源后需把 lib/index.js、package.json、cordis.patch.yml 同步复制到 node_modules/dsh-host-compliance-check/,再重启 dsh 才生效。 (本包 7/7 共享文件 2026-09-26 实测均为独立拷贝,两侧 fileId 不同属正常 —— 不要去重建硬链接。全机机制见 dsh-plugin-manager\README.md「本地 file: 插件的落盘形态」。测试与 tests/ 不进运行副本(files 白名单不含它,副本里那份是旧安装残留),node tests/… 从源码目录跑。) 包内 cordis.patch.yml 属包层 patch,改它不需要重启,但它不会自己触发重组合 —— dsh-hmr 只监视 profile 的 cordis.patch.yml、home 层 cordis.patch.yml 与 profile 的 package.json 三个输入 (dsh-hmr/lib/index.js:353-376),包内文件不在其中;重组合时会重读全部 bundle 层,所以改完要有一次触发 才被读入:在插件页点一下本卡(或任意行级)开关,或保存 profile patch 的任意一处改动。 lib/*.js 是模块代码,loader 按 URL 缓存已 import 的模块实例,改完必须重启 dsh。

工作原理

  • 监听 agent/pre-step:检测到用户新消息(source.kind === 'user')时复位 该会话的"已提醒"标记与本轮写入记录;
  • 监听 tools/result:每次工具成功结束(顶层或 run_code 子派发),若是 write/edit 则把精确 file_path 记入该会话本轮表(应用 skipPaths 过滤);
  • 监听 agent/turn-stopping(≈ Trae Stop):仅主会话且未提醒过、本轮表非空时, agent.inject 注入 notice 提醒 —— 注入 next-step 使本 turn 继续,主模型当场响应;
  • 事件日志兜底:仅当实时记录缺失时,从会话事件取顶层 tool/call 的 write/edit;
  • 提示词正文带文件清单、本轮用户输入摘录、自查清单与处理方式引导(可直接结束或 派 subagent/subagent_fork 深查(按其结算通知收活));
  • 已知边界:run_code 程序内 PTC 裸写(await import('node:fs') 等直接文件 API,绕过 tools 绑定)不产生 tools/result,本插件不检测;如需要覆盖请改用 tools.write/edit;
  • 无子代理派发、无 ctx.get('subagents') 依赖。

开发

pnpm install
# 修改活源 plugins/dsh-host-compliance-check/ 后,同步 lib/ 与 package.json 到
# node_modules/dsh-host-compliance-check/(file: 拷贝,不自动同步;本包 7/7 共享文件实测均为
# 独立拷贝,两侧 fileId 不同属正常,不要去重建硬链接),再重启 dsh
# 纯函数单测(提取/记录/收集/提示词组装):
node plugins/dsh-host-compliance-check/tests/diff.test.mjs

License

MIT