DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

ExpertKT /

ExpertKT/dsh-sop-guard

Verified

把 skill 的 SOP.json 变成真正的分步白名单:模型先申报在第几步,改文件、跑命令、跑代码的范围在工具执行前就被卡住

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: master@e40dd56e

dsh-sop-guard

English

一个 DeepSeek Harness 插件。它把 skill 目录里的 SOP.json 清单变成真正的分步白名单:skill 带了清单之后,模型必须先申报自己在第几步,然后每一步允许改文件、跑命令、跑代码的范围,由插件在工具真正执行前卡住。被拒的调用没有副作用。

解决什么

skill 告诉模型该怎么做,但挡不住模型不照着做。两种失控很常见:跳过分析步骤直接给一个看起来很完整的答案;为了省时间抄近路,绕开清单里写明的必经步骤。这类问题改提示词没用,因为提示词只是建议。

这个插件把流程从提示词里搬到工具闸门上。当前步骤不允许写文件,模型就写不进去。

安装

还没发到 npm。从仓库装:

npm install github:ExpertKT/dsh-sop-guard

然后把它加进 profile 的 bundle 列表。插件通过 cordis.patch.yml 挂载:

- insert:
    - id: sop-guard
      name: dsh-sop-guard
      config: {}

配置项都不填也能跑:

配置 默认值 说明
mode enforce enforce 直接拒绝;warn 只把同样的拒绝文本写进日志然后放行。填别的值会在加载时报错,不猜。
stateDir ~/.dsh/sop-guard/flows 流程按会话持久化的位置。填 false 只在内存里存。

清单

把 SOP.json 放在 skill 的 SKILL.md 旁边。加载这个 skill 就会为当前会话武装流程。

{
  "version": 1,
  "steps": [
    {
      "id": "inspect",
      "title": "看仓库现状",
      "tools": ["pwsh"],
      "commands": ["^git status\\b", "^git branch\\b"]
    },
    {
      "id": "review",
      "title": "读失败的测试和它覆盖的模块",
      "tools": [],
      "witness": true
    },
    {
      "id": "await-approval",
      "title": "把方案给人看,等人点头",
      "tools": [],
      "approval": true
    },
    {
      "id": "write",
      "title": "改代码",
      "tools": ["write", "edit"]
    },
    {
      "id": "commit",
      "title": "提交",
      "tools": ["pwsh"],
      "commands": ["^git add\\b", "^git commit\\b"]
    }
  ]
}

步骤字段:

  • id:小写字母、数字、连字符,最长 24 字符,done 是保留字。
  • title:出现在拒信和状态输出里。
  • tools:这一步允许的工具名。整个字段省略表示这一步不做工具限制。
  • commands:匹配 shell 命令文本的正则。声明了 pwsh / bash 却不写 commands,这一步的所有 shell 调用都会被拒——没有白名单就没有可核对的东西。
  • witness:这一步不许改任何东西,但必须先用 read / read_image / glob / grep 读过东西。顺带读文件的 shell 命令不算。
  • approval:这一步要人运行 /sop approve 才能推进。确认只管这一步,不跨步骤,也不写进状态文件——会话恢复后要重新问人。

顶层的 gatedTools 数组可以把额外工具名加进闸门的监视范围,对所有步骤生效。

模型怎么配合

插件只注册一个工具 sop_step:

  • sop_step({ step: "inspect" }) 申报当前步骤。申报管整步,不按调用次数消耗。
  • sop_step({ step: "review", evidence: "..." }) 推进。evidence 至少 8 个字符,写清上一步看到了什么。上一步声明了工具时,还要求宿主真观察到一次成功的执行——所以一条退回码非零的失败命令不算数。
  • sop_step({ skill: "名称" }) 在多个已装载的清单之间切换。
  • sop_step({}) 查看当前状态。
  • sop_step({ step: "done", evidence: "..." }) 提前结束流程。结束会丢掉整条闸门,所以它和推进一样:本步要先申报,声明了工具的步要有一次成功执行,标了 witness 的步要真读过依据,标了 approval 的步要人确认。宿主会记下是谁在第几步、用什么理由结束的。

推进之后新的一步是未申报状态,得再申报一次才能用工具。少了这条,一次申报就等于放开后面所有步骤。

当前步骤也会出现在模型的运行时上下文里,步骤一变就重播一遍。这一条针对的是插件管不住的那种情况:模型忘了清单存在,下一次调用前能看到自己在第几步。

人的出口

/sop 打印当前流程和位置。清单里标了 "approval": true 的步骤,要人运行 /sop approve 才放行;没有这一步,模型会停在原地,确认也只对当前步骤有效。/sop off 丢掉这个会话的流程并删掉状态文件,清单写错、或者模型被一条你写坏的规则顶住时用它。这两个出口只留给人。

到底拦住了什么

每一次受管调用都按当前申报的步骤比对:

  • write、edit、delete、move、copy、apply_patch 只有在步骤里点名时才放行。
  • pwsh、bash 要求步骤点名,并且每一段命令都命中这一步的正则。
  • 命令串在引号外按 ;、&、|、换行切成段,逐段核对。2>&1 认作描述符复制,不切段。
  • 自带命令的 shell(pwsh -Command "..."、bash -c "...")核对内层命令,不核对 pwsh 这个词。让 shell 从文件或标准输入读命令的直接拒绝——没有可核对的内容。套两层 shell 同样拒绝。
  • -EncodedCommand、-enc 一律拒绝。
  • 不允许改文件的步骤里,Set-Content、Out-File、Remove-Item、cp、mv、mkdir、tee、dd 这类命令同样过不去,换条路写文件也不行。
  • run_code 的程序体会被扫模块字面量。不允许改文件的步骤里出现 node:fs 会被拒;声明了工具的步骤里出现 node:child_process 会被拒。
  • 标了 approval 的步骤,人没运行 /sop approve 之前,sop_step 推进不过去。

让这个闸门在实际使用中不至于把正常干活也卡死的有三点:

  • 拒信写清步骤、原因、允许的工具、允许的命令、下一步和清单路径。
  • 拒绝发生在工具执行之前,不会留半截文件。
  • 推进和结束都要 evidence,也要宿主真观察到成功执行。只申报不干活,走不完流程,也退不出流程。

它不是什么

这一段请在信任它之前读完。

它不是沙箱。 命令核对是词法层的,看的是模型写下的命令文本,不是展开之后真正跑的东西。$HOME 是在核对之后才展开的。模型先前用写文件工具写下的脚本,运行时想干什么干什么。

evidence 是自述。 插件能证明某个工具跑过,证明不了模型读的是不是该读的文件,也证明不了它的结论是从读到的内容推出来的。witness 把门槛从「有工具成功」抬到「有读取工具成功」,这是把洞改小,不是堵上。想混过去的模型随便 read 一个文件就能过。

程序体扫描是文本匹配。 运行时拼出来的模块名,比如 "node:" + "fs",扫不到。

确认步骤要人坐在键盘前。 框架不会把自己的批准结果报给插件,有些安装里批准弹窗还是自动放行的。插件用自己的握手:标了 "approval": true 的步骤,人没输入 /sop approve 就推进不了。确认按步骤算,只存在内存里,会话恢复后要重新问。插件能证明有人敲了这条命令,证明不了这个人看过模型给出的方案。

子 agent 继承流程,不继承申报和干过的活。 子 agent 从父 agent 的当前位置开始,但要自己重新申报、自己跑出成功的工具调用;观察记录和 /sop approve 的确认都分开算。

运行时文本是中文。 拒信、sop_step 的工具说明、系统提示里的规则都用中文写,中文是这套东西的首要语言。英文清单能跑,但「你哪里做错了」仍然是中文。这份 README 是中文版,英文那份是配套参考。

持久化是每会话一个 JSON 文件。 两个进程恢复同一个会话 id 时靠锁文件仲裁。家目录不可写会关掉持久化并打一条警告,闸门本身照常工作。

如果你要的是「挡住一个主动想逃的模型」,请把允许名单放进操作系统或容器里。这个插件面向的是想好好干活、偶尔抄近路的模型。

状态

1.0.0。拒绝路径、命令白名单、evidence 门槛、观察执行门槛在真实 harness 里对着真清单跑过,但跑的是最后几次改动之前的构建。运行时上下文播报、/sop off、/sop approve、witness 的读取规则、run_code 程序体检查只有单元测试。线上验证还欠着,别当成已经验过。改代码之后从仓库副本先跑测试:

node test/guard.test.mjs

设计取舍和已知边界写在 DESIGN.md。examples/sop-demo/ 里有一份能直接加载的 skill 和清单,测试会核对它和 README 示例一致。测试与示例也打进 npm 包,装完可以自己跑 node node_modules/dsh-sop-guard/test/guard.test.mjs。

许可证

MIT。

—/ 5

No ratings yet

Verified DSH bundle

Commit e40dd56e33af

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout