# Dsh Slice Bench

> 判断 DSH 插件在指定 harness 版本上能否加载。把插件单独放进最小的 Cordis 树启动，判定来自 DSH 自己的启动审计，不经过模型推断。只读，不修改用户仓库与 ~/.dsh。换版本重新运行即得该版本的结论。

- Skill: `33moren33/dsh-slice-bench` (Agent Skill, multi-file: 44 files)
- Install (CLI): `npx skillmds@latest add 33moren33/dsh-slice-bench`
- Raw SKILL.md: https://api.skillmd.com/api/skills/33moren33/dsh-slice-bench/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: 33moren33 (https://skillmd.com/u/33moren33)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/33moren33/dsh-slice-bench

---


# 判断一个插件在某个 harness 版本上还能不能用

把一个插件单独放进一棵最小的 Cordis 树里启动——这是 Simulink 对封装模块的老办法；能照搬是因为 Cordis 本身就支持只启动一小块，判定也出自它自己的启动审计。所以换哪个插件、换哪两版都照跑，不需要内置任何版本清单。

判定全部来自启动审计。你的职责是运行命令、读取输出、如实转述。⛔ 不要自行推断结论，也不要改写官方的措辞。

⛔ **「不要自行推断结论」是不要替引擎下判断，不是不许质疑本工具。** 装置也会产生红灯，而且长得和真故障一模一样。**这份 skill 最该被质疑的地方，恰恰是它的装置。**

⛔ **默认只读**：诊断阶段不修改插件源码、不修改依赖、不修改 `~/.dsh`，任何情况下都不修改被测的 DSH 目录。用户明确要求修复时才修，改动方案与影响面要完整写进报告，并用同一条命令在新旧两版各复跑一次作为证据。

## 用法不在这里，在命令自己身上

⛔ **本文不复述任何参数。** 每条命令 `--help` 会印出它的全部参数、可照抄的示例，以及四档退出码的完整措辞——那些由代码生成，不会和实现漂开。本文只讲**怎么读它给你的结果**。

| 命令 | 它回答什么 |
| --- | --- |
| `manifest.js` | 插件声明的 SDK 包，在这一版还在不在 |
| `talk.js` | 挂上去跑一轮对话，起不起得来、走不走得完 |
| `slice.js` | 插件自带的那层配置，单独起／按实际叠法起，起不起得来 |
| `provider.js` | 谁提供这个服务／这个包这一版还在吗、它要什么、它导出什么 |
| `flow.js` | 单个包隔离启动，记录它对每个服务做了什么 |
| `survey.js`／`closure.js`／`bundles.js` | 全量盘点：逐包能否独立激活、最小可启动包集、官方条目索引 |
| `matrix/run.js` | 同一份会话产物，新旧版本能否互相读取 |

⚠️ 这八条是本工具目前的内部分工，不是你必须走的八步。多数任务只用到前四条。

## 退出码四档，`0` 之外还有一个「绿但不算数」

**每条命令都要看退出码，不能只看屏幕上那几行。** 完整措辞由 `--help` 印出，这里只讲怎么用：

- `1` 是**被测对象**被判定为失败——照抄它点名的条目与服务。
- `2` 是**没能给出答案**：引擎路径错、参数错，或本工具自己出错、或本工具的组合缺了东西。⛔ 这不是关于插件的结论。
- `3` 是**跑起来了、什么都没失败，但结论不完整**。⛔ 不许表述为「通过」，命令那几行会写清还缺什么。

⭐ `1` 与 `2` 的分工是这套工具的地基。**看到 `2`，先看命令本身和本工具，别写进关于插件的报告。**

## ⭐⭐ 失败有四种形状，绿灯只覆盖第一种

**一件事有几种失败方式，判词就得有几档；少一档，那一档就会伪装成成功。** 这是本文最该记住的一节。

1. **起不来** —— 启动审计拒绝整棵树，点名是哪个条目、在等什么。这是唯一一种一眼看得见的。
2. **起来了，但回调在等** —— 某个条目已报 ACTIVE，而它内部用 `ctx.inject([...], cb)` 建的作用域还在等一个没人提供的服务。**启动审计只审条目，看不见条目底下的作用域**，所以屏幕上的绿灯是真的，覆盖面却是缺的：那段回调不执行，它要注册的东西一样都不在。
   ⭐ 这一档同时是**下一个版本会不会坏的预告**——一旦上游把该依赖从作用域注入提升为条目级 `inject`，整棵树立刻起不来。
3. **回调执行了，但抛了异常** —— 基座接住它、写进日志，条目照样报 ACTIVE、条目数照样对。**这是最像成功的一种失败**：一个 `apply` 整段炸掉、什么都没注册成的插件，输出曾经与成功那次逐字相同。看到 `⛔ 出错` 那几行，绿灯就不覆盖抛异常的那一段。
4. **装载阶段就死** —— 一个包删掉某个具名导出，所有 `import` 它的模块在装载时直接抛，那时还轮不到任何服务。报错形如 `does not provide an export named '<名字>'`。

## 判据是两版之差，不是单版的绝对值

问「新版本有没有影响它」时：**两个版本的退出码、等待项、未覆盖项完全相同 ⇒ 没有跨版本差异，这本身就是一个合法且完整的结论**，即使那个退出码是 `3`。

⚠️ 同一条判据的反面同样有用：**被测插件往 stderr 喊的话，两版逐字相同 ⇒ 是隔离环境的副作用，不是跨版本差异**（它抱怨找不到 profile、找不到配置，多半属于这类）。只在一版出现才值得追。

⛔ 「`3` 不算通过」是**回归验收**的规矩，别把它压到跨版本比较上——有些 `3` 原理上消不掉（比如插件的浏览器侧部分），那时会把结论卡死。

### ⭐ 对照组：先把被测对象拿掉跑一次

按实际叠法起的时候，**必须先跑一次不带被测插件的对照组**，只铺底座。

**对照组的合格线是「起得来」，不是「退出码 0」。** 引擎自带的组件本来就有几处作用域在等，那是它们的设计，不是故障。**⛔ 合格线一律写成「相对基线的变化」，不能写成一个绝对数字**——这个错犯过两次，两次都把正确结论报成了错的。

叠上去之后要比的是**相对对照组多了什么**：条目数应当等于对照组加上你这层插入的行数；等待项应当与对照组逐字相同，多出来的才是你这层带来的；出现对照组没有的报错，才是你这层的问题。

## 一层不是一棵树

一份 `cordis.patch.yml` 是**一层配置**，不是一棵完整的树——按上游的定义，bundle 发布的就是配置层，profile 把它列出的各层按顺序叠到一个空的条目表上。**一份补丁点名别的包是规范内的用法**，插件全家桶就是这么做的。

于是两种起法答的不是同一件事，⛔ 往往不可兼得：

| 怎么起 | 答什么 | 特有的发现 |
| --- | --- | --- |
| 单独起 | 这一层自己带齐了什么、靠别人提供什么 | **缺提供者** |
| 叠着起 | 它按用户实际的叠法起不起得来 | **撞名**（把别人已经带进来的东西又带一遍） |

**自带得越全越容易撞。按上游的定义，叠加层该追求的是后者**——单独起红、叠着起绿，是一个健康的叠加层，不算失败。

⭐ **一层薄薄的叠加层单独起必然红，那种红没有信息量；但「两版红得不一样」永远有信息量。** 别把前一句用到后一种情况上。

⚠️ 撞的是**服务名与工具名**，不是条目 id——给自己的行加前缀躲得开 id 冲突，躲不开这个。
⚠️ 只要有一行 `import` 失败，整层就整体抛错，撞名检查根本轮不到。这时两种起法的输出会逐字相同，⛔ 别读成「没有撞名」，那是「没测到」。

## ⭐ 两种方向相反的破坏，各看一行

**「上一版能起、这一版起不来」的成因，绝大多数落在这两行之一，而它们互相看不见对方。**

- **「它要什么」变了** —— 条目级 `inject` 多了一项。⛔ 导出的函数一个没变，所以比对导出接口看不出来。
- **「它导出啥」少了** —— 删掉一个具名导出，`import` 它的模块在装载阶段就死。⛔ 那时还轮不到任何服务，所以「它要什么」那一行完全看不出来。

⭐⭐ **「修好这一个之后还有没有第二个」不用靠重跑撞出来。** 装载失败一次只报第一个缺失绑定，所以逐个改、逐次重跑是最贵的走法。**插件要哪些名字读它自己就有，引擎给哪些名字读一次就有，相减即可**——第一条命令（`manifest.js`）会把这个插件从 SDK 取的全部具名符号一次列全，并标明哪些在这一版没了。⛔ 它印的是全集，不是「第一个」。

⛔ **别用文件搜索代替命令，也别停在「没了」** ——搬家常常连名字一起改，拿同一个名字再搜是找不到的。源码检出的包目录是分层的，按包名直接找会找不到，从而得出「这一版删了它」的错误结论；npm 安装目录的布局又是另一套。

## ⛔ 贯穿全程：每个红灯先问「这是被测对象，还是这套装置」

判定来自引擎自己的启动审计，但**引擎看见的是我们搭给它的那个环境**。看到任何红灯，先过这三问：

1. 两个版本是不是同一种形态？（一个源码检出、一个 npm 安装，包集本来就不同）
2. 报错里点名的文件／包，是被测插件的，还是本工具或引擎自己的？
3. 对照组跑了吗？把被测对象拿掉，剩下的部分自己是绿的吗？

⭐ **装置会认领两种自己的缺口**，都由命令自己印出来，不需要你去推：

- **挂在本工具的对话组合里跑，而组合缺了插件要的服务** → 点名提供者、给出补上它的命令，退 `2`（没能给出答案），⛔ 不是 `1`。
- **一层单独起，而红的原因全是「别人该提供的服务这里没有」** → 点名提供者，退 `3`（未判定），并给出按实际叠法再跑一次的命令。**叠加层单独起本来就会红，那不是对插件的判定。**

**它只认得出「引擎里有提供者，而这次的树里没挂」这一种**，其余仍要你自己判。
⚠️ 装载失败、撞名这类**不是缺提供者**的红，仍然是 `1`，那是真判定。

## ⭐ 比两台引擎：按「会不会让插件起不来」分档读

`survey.js` 把一份引擎的全部契约采下来（每个包**要什么**、**给什么**、官方把它挂在哪个 id 下），`--against` 拿它和另一份比。读法只有一条:**看档，不看条数**。

| 档 | 里面是什么 | 怎么读 |
| --- | --- | --- |
| **会让插件起不来** | 包没了／具名导出少了／条目级 `inject` 多了一项 | 每一条都是某个插件的硬故障 |
| **可能有影响** | 条目 id 变了（撞名的形状跟着变）／config 变了（有些插件不给配置会自我禁用） | 要结合那个插件自己的写法判断 |
| **判不了** | 两份快照形态不同时的「包在不在」／某个包这一版没起来所以没测到它提供什么 | ⛔ 这一档**不是结论**，别当成发现 |
| **不会让插件起不来** | 新增的包、新增的导出、不再要求的依赖 | 记录，不排队 |

⭐ **加 `--plugin` 把这个比较投影到某个插件的接触面上**（它 import 的那些名字、它声明的依赖）。引擎级几十条落到单个插件头上通常只剩一两条——**那一两条才是它要改的东西**。全量和单插件是同一个计算的两个视图，不是两件事。

## 量程边界（都要写进报告）

- **⛔ 浏览器侧一行都测不到。** `manifest.js` 会自己认领这一条：它本来就在解析那份 `package.json`，所以有没有浏览器侧由它印出来（`dsh.client.inject`／`dsh.client.platform`／`exports` 里的 `./client`，并说明是哪个信号触发的），⛔ 不用你去翻文件。**有的话，从那一刻起所有结论只适用于主机侧。**⚠️ 这类插件等的是 `connection`／`webRuntime`／`clientModules` 这类通道时，记为「未覆盖」然后停手——⛔ 别继续往树里补提供者，补进去的自己又会等别的，永远追不完。
- **⛔ 看不见用户实际的 profile。** 能证明「和官方底座撞了」，不能证明「和用户的机器不撞」。报结论必须写明你是按哪几个 bundle 叠的。
- **⛔ 跨形态比较两个方向都会错。** 装机版报某个名字缺失，可能只是没被装进来，⛔ 不等于这一版删了它；源码检出报「都在」，⛔ 不等于用户装得到。命令会自报本次是哪种形态。
- **⛔ 不发网络请求。** 某个版本在 npm 上有没有、发了哪些包，本工具答不了，要你自己查。
- **可加载不等于功能正确。** 插件内部的逻辑错误不在覆盖范围内。

## 五个常见误判

1. 两个版本**都通过**时，先确认测的是不是插件真正发布的那棵树——最容易出错的一处：插件自带的组合没跑，而本工具的组合替它补上了缺口。
2. 两个版本**都失败**时先排查本工具的组合，而非插件。
3. 未剔除插件自带的 `@deepseek-ai` 副本 → 测的是插件自带的 SDK 版本，不是被测引擎。
4. **只看屏幕不看退出码** → 绿色的三行下面可能跟着「本次没测到你自带的组合」。
5. 把**盘点**读成**判定**：引擎自己就有几十个包不能单独启动（抽象接缝、纯 bundle），全量扫描里的 `refused` 属正常。

## 报告格式

- **结论**：一句话，含版本号与判定来源（例：「在 <版本> 上，启动审计报告它等待服务 X」）
- **证据**：命令、原始输出与**退出码**，⛔ 不改写措辞
- **未覆盖部分**：浏览器侧、条件分支中的调用、功能正确性
- **建议**：指出需要进一步核查的位置，⛔ 不代替用户决定如何修改

## 配置纪律

1. **官方包那几行的配置一律取自官方 bundle**，命令会替你抄。⛔ 自己编配置，报出来的会是我们的配置错误，而不是被测对象的问题。
2. **被测插件自己那一行的配置由插件作者提供。** 有些插件不给配置会自我禁用，这时缺的不是官方配置，要向用户要。

## 参考

[references/method.md](references/method.md) —— 隔离测试的原理、判定纪律、依赖的官方接口。

