dsh-testkit: The Real Host Release Barrier for the DeepSeek Harness Plugin

前言

在 DSH「一切皆插件」的开发方式下,插件作者最容易踩的坑往往不在编译期:产物能构建、单测能通过,发布之后却可能因为 tarball 缺文件、bundle 在宿主里注册失败、卸载弄坏 profile 而翻车。这类问题的共同点是,它们只出现在「用户实际安装的那个打包产物」与「真实宿主」之间,作者本机的静态检查覆盖不到。

dsh-testkit 补的就是这一段:把 npm pack 出来的产物放进精确指定的真实 DSH 宿主,完整走一遍生命周期,并把证据留给维护者审查。

这是什么

iiwish/dsh-testkit 自述为 “The real-host release gate for DeepSeek Harness plugins”,即 DeepSeek Harness 插件的真实宿主发布门槛。它明确了自己的边界:是发布门槛,不是单元测试框架、静态 linter、模型输出评估器,也不是安全认证。整个流程不做模型调用,不需要模型 API key,许可证为 MIT。

一次隔离运行回答三个发布问题:

发布问题 一次隔离运行给出的证据
可发布的产物能否安装并注册? npm pack、精确版本 DSH 安装、bundle 组装、配置行、services 与 tool schema
承诺的行为是否可用? 确定性运行时探针、声明的工具调用、可选 loopback HTTP 路由、显式浏览器 smoke
用户能否干净地卸载? 卸载、同 profile 重启、能力检查、owned-path 残留、进程与端口检查

生命周期:从 resolve 到 cleanup

一次完整的隔离生命周期是:

resolve -> install-dsh -> package -> install-plugin -> assemble -> boot -> register
        -> exercise -> update? -> uninstall -> reboot -> recover? -> cleanup

每次隔离生命周期只测试一个被测插件;多插件所有权与更新顺序属于组合层面问题,不在这个工具的职责内。

适配器目前只接受 @deepseek-ai/dsh 的精确版本:0.1.1-rc.2(默认)、0.1.0-rc.80.1.0-rc.70.1.0-rc.6。未知版本会在创建 runner 之前以退出码 4 终止,宿主版本漂移不会被误标为插件失败。官方 dsh-v0.1.2-alpha.1 因对应 npm 包不可用仍是待定 canary;0.1.2-alpha.2 仅进入一次性 canary 矩阵。两个 alpha 都不在默认支持矩阵内。

通过意味着什么

  • 报告中标识的同一个打包产物完成了全部必需阶段;
  • 配置行来自 DSH --dump-config,services 与 tool schema 来自进程内 Cordis 探针;
  • 声明的 exercise 通过真实工具运行时执行,不经过模型选择;
  • 卸载后同一 profile 重启,没有被测 bundle、能力或可归因残留;
  • 必需的 observer 可用,缺少必需覆盖记为 unsupported,不会合成一个「通过」。

反过来,通过也不代表任意可执行代码安全、模型输出良好或未断言的行为可用。

行为与洁净度验证

行为侧的手段包括:确定性运行时探针、声明的工具调用、可选的 loopback HTTP 路由断言,以及显式的浏览器 smoke 测试。HTTP 与浏览器流量限制在 runner 自有的 127.0.0.1;缺少 Chromium 记为 unsupported

卸载洁净度验证覆盖:同 profile 重启、能力检查、owned-path 残留、进程与端口检查。

安装与启用

运行要求:Node.js 22 或更新版本,以及 Docker(Docker 是默认 runner)。

安装为 devDependency:

pnpm add -D dsh-testkit

安装后 CLI 入口为 dsh-test,最短路径是先生成场景,再执行测试:

pnpm dsh-test init
pnpm dsh-test

典型用法

dsh-test init 生成场景

dsh-test init 离线运行,定位最近的 Git worktree,生成三个可审查的文件:

  1. <plugin-root>/dsh-testkit.yaml:包含精确 DSH 版本与探测到的行期望;
  2. <repository-root>/.github/workflows/dsh-lifecycle.yml:默认只读 token 契约与正确的嵌套路径;
  3. <repository-root>/.agents/skills/dsh-testkit/SKILL.md:让兼容的编码智能体执行同一道门槛。

生成是字节级幂等的,并对所有目标做预检;发现冲突会停止全部写入,除非显式传 --force。如果被测 bundle 在仓库根目录之下:

pnpm dsh-test init plugin/
pnpm dsh-test --config plugin/dsh-testkit.yaml

场景即代码

场景是 schemaVersion: 1 的 YAML。init 生成的起始场景大致如下:

schemaVersion: 1
name: my-plugin-quick
subject:
  source: .
dsh:
  version: 0.1.1-rc.2
expect:
  boot: success
  rows: [tool-my-plugin]
  services: [myService]
  tools: [my_tool]
exercise:
  - tool: my_tool
    arguments:
      value: smoke
observers:
  filesystem: required
  process: preferred
  ports: preferred
  network: off
  canary: preferred

expect 声明 boot 结果、配置行、services 与 tools,exercise 声明要执行的工具调用。本地目录 subject 以只读方式挂载,复制到 runner 拥有的可写根目录后再打包;声明了 prepareprepackpostpack 时,会在副本内按 packageManager 与 lockfile 恢复依赖再 npm pack,原始检出不会被改动。场景还支持 http.routes、更新目标、预期失败与恢复、阶段重跑、observer 策略与全局 watchdog,细节见仓库内的 Scenario Reference。

对提供 DSH web 路由的插件,设置 profile: web 并添加仅 Docker 的断言,例如要求 /health 返回 200:

profile: web
http:
  routes:
    - id: health
      path: /health
      expect:
        status: 200
        json:
          status: ok
          version: $subject.packageVersion

CI 集成

生成的 workflow 默认使用只读 token,并把这一契约写进文件:

permissions:
  contents: read

steps:
  - uses: iiwish/dsh-testkit/.github/actions/dsh-test@v0
    with:
      plugin: .
      dsh-version: 0.1.1-rc.2
      config: dsh-testkit.yaml
      publish-junit-check: 'false'

默认行为是把 JUnit 注解写进 job、上传完整证据目录,并给出 artifact ID、URL、digest、报告路径与稳定退出码,不调用 Checks API。受信任的 push 或 release workflow 可以开启命名 JUnit Check:

permissions:
  contents: read
  checks: write

steps:
  - uses: iiwish/dsh-testkit/.github/actions/dsh-test@v0
    with:
      plugin: .
      dsh-version: 0.1.1-rc.2
      publish-junit-check: 'true'

开启 publish-junit-check 需要 checks: write 权限,且不要对不受信任的 fork PR 启用。GitHub Enterprise Server 与其他 CI 系统可以直接调用 CLI。

报告与退出码

报告落在 .dsh-testkit/runs/:canonical 的 report.json、CI 可用的 junit.xml、可读的 report.md、脱敏命令日志与有界阶段证据。

退出码是稳定的,脚本可以直接按它分支:

退出码 含义
0 通过
1 生命周期失败
2 输入无效
3 基础设施错误
4 不支持
5 flaky

适用场景与注意

适合谁:维护 DSH 插件的作者、审查发布 PR 的维护者、运营插件模板的团队,以及需要可复现宿主级 bug 报告的人。

使用前注意几点:

  • 每次隔离生命周期只测一个被测插件;多插件的所有权与更新顺序是组合层面的问题;
  • 适配器只接受前文列出的四个精确 DSH 版本,其他版本以退出码 4 终止;
  • 一个「通过」不代表任意可执行代码安全、模型输出良好或未断言行为可用,它也不是安全认证;
  • 两个 alpha 版本仅进 canary 矩阵,不在默认支持范围内。

安全方面需要说明:在 DSH 生态里,插件以当前 dsh 进程的权限运行,安装任何插件前都应检查其源码与许可证。dsh-testkit 本身以 npm devDependency 形式安装,许可证为 MIT,源码公开;它不做模型调用,CI 侧默认最小权限(只读 token)。

小结

dsh-testkit 把发布验证从「我本地能跑」推进到「这个打包产物在精确的真实宿主上装得上、跑得动、卸得干净,并且留下了证据」。对维护 DSH 插件的团队来说,把它挂在发布 PR 和 tag 上,是一种成本可控的把关方式。

目录页为社区维护的独立站点,与 DeepSeek / 幻方无官方从属关系。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye