Files
jkooe 6206645f31 fix(ci): D2 覆盖率口径改为 include 白名单(数字不再被运行环境稀释)
## 缺陷

`server` 的 `test:coverage` 只写了阈值,没有 include/exclude。某些开发机
(IDE / 代理 / 沙箱工具)会在 Node 的 `require` 链上注入 `*.cjs` 钩子,这些
**项目外**文件被覆盖率跟踪器一并统计:

```
# broker-ipc-client.cjs      | 24.76
# node-brokered-fs-shim.cjs  | 50.13
# node-language-shim.cjs     | 82.86
# node-safe-delete-shim.cjs  | 41.91
# all files                  | 76.56   ← 被稀释 10+ 个点
```

危害是双向的:
① 换机器/换环境数字就变,**不能作为交付证明**;
② 60% 门禁在拿被稀释的分母判定 —— `server.js` 真掉 20 个点可能被这些 shim 抵消
   而不报警。

## 修法(用 include 白名单,而不是逐个 exclude 环境特有文件名)

```json
"test:coverage": "node --test --experimental-test-coverage \
  --test-coverage-include='**/server/*.js' \
  --test-coverage-exclude='**/node_modules/**' \
  --test-coverage-exclude='test/**' \
  --test-coverage-lines=60 test/*.test.mjs"
```

`include` 表达的是正确语义:「只统计本项目源码」。逐个 exclude 环境特有的
`*.cjs` 名字换台机器就会再冒出来,不解决问题。

## 三条验收(逐条实测)

1. **报告内无项目外文件**:覆盖率报告的文件列只有 10 个项目源码
   (config / crypto / db / errors / logger / migrate / ratelimit / server / tokens /
   validate .js),`grep -E "Applications|/Users/|node_modules|\.cjs"` 对报告段落
   零命中。
2. **数字可复现**:连跑 3 次,`all files` 均为 `89.29 | 70.85 | 88.65`。
3. **门禁真实会 fail**:阈值临时调到 99 复跑 → `exit=1` 并打印
   `Error: 89.29% line coverage does not meet threshold of 99%.`
   (改回 60 后恢复正常)

## 连带

- `.github/workflows/ci.yml`:把口径写进覆盖率那一步的注释(为什么用 include、
  为什么不能靠 exclude 兜底),本地与 CI 从此同一口径。
- `README.md`:覆盖率与测试数全部换成实测值 ——
  server **89.29%**(原 75.31% 是被污染的数字)、launcher **91.67%**(原 91.06%);
  server 测试 **52**(原 43)、launcher 测试 **451**(原 390);
  并新增「覆盖率口径为何用 include 而不是 exclude」小节,把这次事故写清楚。
2026-10-26 01:59:46 +08:00
..