# CLI 定位决策：`dsh-plugin-dev check` / `verify` 该不该存在（2026-10-13）

> **本文回答一个具体的工程质疑**（来自 `_analysis/v2-6-forward-compat.md` §5）：
> 同族已有 33 项、带裁定语义与退出码契约的 `dsh-plugin-doctor`，本库的 16 项检查是不是**更弱的重复**，
> 该不该削减甚至删掉？
>
> **结论：保留，但把分工写成不可含糊的三条。** 下面是判据与"什么情况下该反过来削减"的触发条件。

---

## 1. 先摆事实（实测，不是估计）

| 事实 | 值 | 来源 |
|---|---|---|
| 本库检查项 | **16** | `src/cli/skill-sections.ts` 的引用表，`check-facts.mjs` 断言 |
| 同族 `dsh-plugin-doctor` 检查项 | **33**（规范门禁 21） | `guide/family-toolchain.md` §2 |
| 本库**独有**的检查 | **5** | `guide/family-toolchain.md` §3.2 交叉对照表 |
| `check` 是否跑在任何工作流里 | **否** | `.github/workflows/` 无任何步骤调用它 |
| `dsh-plugin-doctor` 是否是本仓 CI 门禁 | **是** | `plugin-doctor.yml` 以精确版本钉住调用 |
| 本库 `check` 的代码量 | 781 行 + 13 个测试块 | `src/cli/commands/check.ts` |

**光看这张表，"砍掉"是合理结论**：11 项是更弱的重复，且它不在任何门禁里——一份没人跑、又和别人重叠的检查，维护成本是纯支出。

## 2. 但有三个事实让"砍掉"不成立

### 2.1 独有 5 项里有 1 项是家族唯一的检测器

`redline-async-apply-registration` 检测 **async `apply()` 在首个 `await` 之后注册**——这个缺陷在卸载窗口内
静默丢失注册，表现为"装了、日志全绿、能力时有时无"。同族 `dsh-plugin-upgrade` 的 `legC` 走廊卡
**明确点名本库这个 lint** 作为 seam E2 的预防门（见 `guide/family-toolchain.md` §3.2）。
`dsh-plugin-doctor` 的 `K5` 只查 `apply` 的**返回形态**，查不到注册顺序。

删掉它，家族内就没有任何东西能机械发现这个缺陷。

### 2.2 本库的检查**每一项都链回可读章节**

`dsh-plugin-doctor` 的裁定有严格的退出码契约与降级语义，但它的输出是**判定**；
本库 `check` 的每一项都带 `skillRef`，指向该规则在知识库里的**正文**。
两者面向不同需求：**"过没过" vs "为什么、该改哪一行"**。这是本库存在的理由，不是重复。

> 这条承诺此前**部分是空的**——审计发现 2 项引用了根本没写该规则的章节，11 项引用的标题已漂移。
> 本轮已全部修正，并加 `tests/skill-sections.test.ts` 防再漂。**承诺现在是可验证的。**

### 2.3 `verify` 的价值不在强度，而在**零依赖自足**

`verify` 在 D 组各轴都弱于 doctor（D9 甚至是反的：它删掉自己的沙箱）。
但它**只用 Node 内置模块**，能在没有 network、没有 pnpm 全局状态、没有 doctor 安装的机器上跑完
`pack → 干净 DSH_HOME 安装 → 启动 → 卸载`。对"第一次接手的作者"和离线环境，这是唯一能跑的那条。

## 3. 因此的分工（写死，不再含糊）

| 问题 | 用哪个 | 为什么 |
|---|---|---|
| "我这项改动过没过？给个裁定和 CI 退出码" | **`dsh-plugin-doctor`** | 33 项、有裁定语义、有降级检测、已是本仓门禁 |
| "为什么这条规则存在？我该改哪一行？" | **本库 `check`** | 每项带 `kb` 引用，指向正文 |
| "我这台机器什么都没有，先自证一下" | **本库 `verify`** | 零依赖、离线可跑 |
| "这个缺陷同族还有谁能发现？" | **本库 `check`** 的 async-apply lint | 家族唯一 |

**发布前建议两个都跑**，`SKILL.md` 与 README 已这样写。

## 4. 反过来：什么情况下应该削减

本文不是"永远保留"。以下任一条件成立，就该重新裁定：

1. **`dsh-plugin-doctor` 获得异步注册顺序检查**（例如 `K5` 扩展为同时校验注册时序）——
   那 2.1 的唯一性消失，本库的 `check` 就退化为"带文档链接的 doctor 子集"，应削减到文档链接层。
2. **doctor 的裁定输出开始携带正文引用**——那 2.2 的差异消失。
3. **本库 `check` 连续 3 个版本没有新增或修正任何检查**——说明它已停止演化，
   而维护成本（781 行 + 13 测试块 + 约 45% 的历史 churn）仍在支付。

**触发条件应定期核**：`guide/family-toolchain.md` 的交叉对照表是唯一需要更新的地方。

## 5. 本轮已做的、与此决策无关的改进

- 修掉 11 处 citation 漂移与 2 处"引用不存在的规则"（`tests/skill-sections.test.ts` 现在守着）。
- `check --stirct` 这类拼写错误此前静默退出 0，现在报 `UsageError` 并以退出码 2 结束。
- `manifest-files` 此前无条件要求 `lib`/`dist` 目录，导致 `new --lang js` 过不了自己的 `check`；已修，
  并在 `verify-artifacts.mjs` 里加了 **scaffold → check 往返断言**——这正是当初漏掉它的原因。
