修复: 第五个落点 —— 判据写对了,却**没有任何人执行它**(check-file-modes.sh 空转)

pi `4fc16f66` 报的是 rc=2 那半个缝(M18)—— 我复核后**已经在 `e99a657` 修好了**,
而它的**父提交正是 pi 报信时读的 `6ee9902`**。又是同一形状的竞态。

但照 pi §四 那句「**每条分支的前提本身也要能被构造**」做审计时,
我发现**第五个落点,而且这一格的判据本身写得完全正确**:

`deploy/check-file-modes.sh` = 源文件权限政策的**唯一**判据。
它甚至专门修过自己那份 `[ -x ]` 恒真的 root 陷阱(`b7dc9e9`),改成直接读权限位 —— 修得对。
**但它从来没有被任何东西执行过。** 全仓 `grep -rn "check-file-modes"` 只有:
  · `check-deploy-drift.mjs` 3 处**注释**(谈分工)
  · `run-all.mjs:951` **注释**(讲 root 陷阱)
  · `summary.py:77` **注释**,且**说法与实现不符**
  · `summary.py:431` 一句 `print(...)` 的**文案**
⇒ 唯一一处非注释提及是一句 print 的文案。没有 install.sh / redeploy-* / hook / CI / cron 调它。
**而它当时正红着**:2 个文件是 600 + `jobs/` 缺属主 x 位。

★ 为什么这一类**只能靠判据守**(实测):
  `git status` 看不见、`git diff` 看不见、`git ls-files -s` **只记 100644/100755**
  (组/其他读位**不进版本库**)⇒ 把受跟踪文件 `chmod 600 ↔ 644` 两次 `git status` 都空。
  套件也看不见(`jobs/` 缺 x 位时实测 `diag=none`、`ran=48`,全绿)⇒ **没有第二条通道**。
  0600 在"跑的人恰好是属主"时不炸,换身份就是 EACCES,而那串报错**看起来像代码问题**。

修法:
  · 接进 `deploy/install.sh`(check-shared-libs 之后),**走 `--check` 累积通道**
    (照既有 npm_rc/CHECK_GATE_RC)。⚠️ 我第一版**直接调**,而门禁红时它 `exit 1`、
    install.sh 是 `set -e` ⇒ 当场吞掉后面所有诊断:**实测**接线后 `构建 Gateway`
    在日志里命中 **0 次**(接线前 2 次)—— 正是 install.sh:141-157 刚修过的同一个毛病,
    我自己又造了一遍。改累积后回到 2 次,门禁报 `[FAIL] 权限政策没过(退出码 1)`。
  · 修那两个文件:600 → 644 ⇒ 权限政策现在绿(rc=0)。
  · 新增判据 `criteria-hygiene` 第 7 条:政策门禁必须被入口脚本在**可执行位置**调用。

★★ 变异验证时**我自己先假绿了一次**(单记):第一版用 `code()` 剥注释,而
`lib/read.mjs` 的 `stripComments()` 只认 `//` 与 `/* */` —— 那是 **JS** 的注释,
**`install.sh` 是 shell,注释是 `#`** ⇒ 对 shell 文件**原样返回** ⇒ 判据读到了
**我写在它上面那段解释里的** `` #   `check-file-modes.sh` 红时 `exit 1` ``。
  变异①(接线整段删掉)⇒ 第一版 **rc=0(假绿)**;自剥 shell `#` 后 **rc=1** ✓
  变异②(只在 echo 里提一句)⇒ rc=1 ✓
  变异③(gates 恒空 ∀x∈∅)⇒ rc=1(`只找到 0 个`)✓
(③ 第一次 python 锚点没匹配上、变异没施加,我重测并**先打印"变异已施加"**才算数。)

★ 射程如实标出:只管 `deploy/check-*.sh`(政策门禁族);**不管** `check-deploy-drift.mjs`
这类**按需手动工具**(自带 `--self-check`、文档写明"事后自查")——要求它进入口是**错的**。
它实测同样 0 处调用,但**本判据不覆盖它,也没修它**。判"有没有接线",不判"接得对不对"。

★ 通用纪律(CRITERIA.md §16.1.2):**判据自己也要能"被证明它真的在看代码"。**
若判据读的**语言**与 stripComments 实现的**语言**不一致(shell vs JS、Python vs JS),
那"剥注释"是**假的** ⇒ 判据消费散文,而**变异验证是唯一能戳破它的东西**。

全套 checks=516→**517** pass=512 fail=5 red=5 broken=0 verdict=red(5 条红都是别的会话的);
mutants=48 ran=48 skipped=0 diag=none baseline=7/7✓;5 个自检各 rc=0。
This commit is contained in:
2026-09-20 05:22:42 +08:00
parent efb1c1d2ca
commit 1c3335f0c9
4 changed files with 238 additions and 1 deletions

View File

@ -969,6 +969,91 @@ pi 报的第 1–3 例都修好之后,我顺着同一条线**审计全部 61
> 同族的第三个自查问(pi 归纳):"守着它的判据,它自己的样本由谁守";
> 这一条是它的**镜像**:"**被守的那个东西没挂上时,谁来说**"。
#### 16.1.2 ★★ 第五个落点:**判据写对了,却没有任何人执行它**(dsh 2026-09-19)
同一个形状的又一格,而且这一格的判据**本身写得完全正确**:
`deploy/check-file-modes.sh` = **源文件权限政策的唯一判据**
("受跟踪文件不得比 0644 更严;可执行与否按 `git ls-files -s` 记的那位判")。
它甚至专门修过**自己那份 `[ -x ]` 恒真的 root 陷阱**(`b7dc9e9`),改成直接读权限位 —— 修得对。
**但它从来没有被任何东西执行过。** 全仓 `grep -rn "check-file-modes"` 的结果:
```
deploy/check-deploy-drift.mjs:147,149,442 ← 都在注释里谈"分工"
client/electron/test/run-all.mjs:951 ← 注释(讲 root 陷阱)
client/electron/test/mutants/summary.py:77 ← 注释,且**说法与实现不符**
client/electron/test/mutants/summary.py:431 ← 一句 print(...) 的**文案**
```
⇒ **唯一一处非注释提及是一句 `print` 的文案。** 没有任何 `install.sh` / `redeploy-*.sh` /
hook / CI / cron 调用它。**而它当时正红着**:
```
[FAIL] 权限过严:docs/DSH-0.1.5-MAIL-CHANNEL-ROOTCAUSE.md 是 600
[FAIL] 权限过严:scripts/repair-legacy-spliced-ids.mjs 是 600
[FAIL] 目录不可进入:client/electron/test/mutants/jobs(drw-r--r--,缺属主 x 位)
```
★ **为什么这一类只能靠判据守、不能指望"顺手看见"**(实测):
| 手段 | 能否发现 600 vs 644 |
|---|---|
| `git status` | **不能**(两次都空) |
| `git diff` | **不能** |
| `git ls-files -s` | **只记 `100644`/`100755`** ⇒ 组/其他读位**不进版本库** |
| 套件(`jobs/` 缺 x 位时) | **不能**(实测 `diag=none`、`ran=48`,全绿) |
⇒ 这一类**没有第二条通道**。0600 在"跑的人恰好是属主"时不炸,一旦换身份(`install.sh`
自己会切身份判可写性;套件里还有**以 `nobody` 降权跑**的判据)就是 EACCES,
而那串报错**看起来像代码问题**。
**`summary.py:77` 那句"那个只在部署时跑"是实现与说法不符**(实际从没跑过)——
按本仓口径:**说法与实现不一致 ⇒ 以实现为准**,故以实现(从没跑)为准并把它接上线。
**修法**:接进 `deploy/install.sh`(`check-shared-libs.sh` 之后)。
⚠️ **接线必须走 `--check` 的累积通道**(照既有 `npm_rc`/`CHECK_GATE_RC`):
门禁红时它 `exit 1`,而 `install.sh` 是 `set -e` ⇒ 直接调会**在那里中止**、
后面 `build-stamp`/钩子/收尾诊断**一行都不打**。
**实测(我第一版就是直接调的)**:接线后 `构建 Gateway` 在日志里命中 **0 次**
(接线前 2 次)—— 正是 `install.sh:141-157` 刚修过的同一个毛病,我自己又造了一遍。
改成累积通道后 `构建 Gateway` 回到 2 次,门禁报 `[FAIL] 权限政策没过(退出码 1)`。
**新增判据**(`criteria-hygiene.test.mjs`,第 7 条):政策门禁(`deploy/check-*.sh`)
必须至少被一个入口脚本在**可执行位置**调用。
★ **射程如实标出**:
- 只管 `deploy/check-*.sh`(政策门禁那一族);**不管** `check-deploy-drift.mjs`
这类**按需手动工具**(自带 `--self-check`、文档写明是"事后自查")——
要求它也进入口是**错的**(把工具当门禁,然后逼人硬挂上去)。
- 判"**有没有**接线",**不判"接得对不对"**(挂累积通道是另一条纪律)。
- `check-deploy-drift.mjs` 同样不在任何入口被调用(实测 0 处),
但它是**工具**不是门禁 ⇒ **本判据不覆盖它,也没修它**。
★★ **变异验证时我自己先假绿了一次(值得单记)**:
第一版用 `code()`(剥注释)读入口脚本 —— 而 `lib/read.mjs` 的 `stripComments()`
只认 `//` 与 `/* */`,那是 **JS** 的注释,**`install.sh` 是 shell,注释是 `#`** ⇒
对 shell 文件它**原样返回**。于是判据读到了**我写在它上面那段解释里的**
`` # `check-file-modes.sh` 红时 `exit 1` `` ⇒ **变异验证①(把接线整段删掉)判据仍绿**。
| 变异 | 第一版(用 `code()`) | 修后(自剥 shell `#`) |
|---|---|---|
| ① 接线拆掉 | **rc=0(假绿)** | **rc=1** ✓ |
| ② 只在 `echo` 里提一句 | — | **rc=1** ✓ |
| ③ gates 恒空(∀x∈∅) | — | **rc=1**(`只找到 0 个`)✓ |
⇒ 修法:自己剥 shell 注释(行首/空白后的 `#`;**故意不碰 `${VAR#pat}`**),
并抹掉 `echo`/`printf` 开头的散文行。**已知限制**:引号内的 `#` 会被当注释起点,
方向是**假红**(漏掉接线),不是假绿 —— 假红当场看得见。
> **纪律(这一格的通用形式):判据自己也要能"被证明它真的在看代码"。**
> 一条"在源码里找某个写法"的判据,若它**读的那种语言**和
> `stripComments` **实现的那种语言**不一致(shell vs JS、Python vs JS、模板 vs 源码),
> 那么"剥注释"是**假的** ⇒ 判据会**消费散文**,而**变异验证是唯一能戳破它的东西**。
> 本仓 `stripComments` 自己那段注释早警告过"判据开始消费散文",
> 但警告的是**字符串**,**没覆盖"另一种语言的注释"** —— 这一格是那个洞的实例。
### 16.2 ★★ **同一优先级写了两遍 ⇒ 两个顺序**:不变式只在**对角线**上被验过(pi + dsh 2026-09-18)
§16.1 讲"结论到不了决定颜色的那一格"。这一节是它的**镜像**: