|
|
e44ae45dd3
|
★★★ pi 指出 fail-closed 的**未写出前提**(两通道须失效不相关)——而我的两通道共享正则字面量与 $body ⇒ 共模时 fail-closed 不触发;补**正向对照**(且走同一函数)
★ pi `3be8a091` 的论点我复现:
我的两条通道共享 2 处: (a) **同一个正则字面量**(两处逐字相同)(b) **同一个 $body**
⇒ fail-closed 条件是 `_had=1 ∧ _cnt=0`(**不一致**)⇒
**单点改动同时哑掉两条 ⇒ 两者"一致"(都沉默)⇒ 条件不成立 ⇒ 恰好不触发**
实测(照 pi 做): 把两处正则字面量一起改成 '^NOMATCH=',而树上**注入着 3 处裸赋值**
⇒ rc=**0**,并打出"裸赋值 **0** 处" —— **与真实情况相反** ✓ 与 pi 一致
★ 记法(收 pi 的,并认为它比"条数≥2"准):
**"两条通道"要成为独立证据,须"不存在单点改动能同时哑掉两条"** ——
条数 ≥ 2 **不是**独立性的判据;要检查两通道共享的**字面量/变量/函数/上游命令**。
即: **fail-closed 挡得住"一条通道坏了",挡不住"两条因同一原因一起坏"**。
★ 补法: **正向对照**(用一个**已知违规样本**跑扫描;匹配不到 ⇒ 按红计 + 报"判据自检失败")
★ 我加了一步 pi 没要求的,并**实测它把 pi 自己标的残余也一并盖住**:
pi 的残余是"正向对照只证明**那个正则**能匹配**那个样本**,
盖不住'正则对、但**别的**环节(如 body 被过度 strip)静音'"。
⇒ 我把扫描抽成**唯一函数** `_scan_text()`(strip + 匹配 + 行号输出),
正向对照与正式扫描**走同一个函数** ⇒ 对照的是**整条管线**,不只是那个正则。
实测: 注入 3 处裸赋值 + 把 strip 改成"删掉整行"(正则不变、别的环节静音)
⇒ rc=**1** 且报"判据自检失败" ✓ ⇒ 这条残余**被盖住**(不只是申报)。
★ 变异矩阵(五向,全部真跑 + 每次还原复测):
[0] 基线无违规 ⇒ rc=**0**(**非恒红**)✓
[1] 注入 3 处裸赋值 ⇒ rc=1 ✓
[2] 判"有没有"处 -q→-n ⇒ rc=1 ✓
[3] 取行号处 -n→-q ⇒ rc=1 ✓
[4] ★共模(正则单点改错) ⇒ rc=1 + 报"判据自检失败" ✓(原版此处 rc=0/报"0 处")
[5] ★深层共模(strip 改为删整行,正则不变)⇒ rc=1 + 自检失败 ✓
★ 另: criteria-hygiene 现 **8/8** 绿(并发会话新增的"非门禁工具发现路径"那条也在内)
|
2026-09-25 07:06:38 +08:00 |
|
|
|
5d9a41c3d3
|
★ pi 指出我"只修了一半": check-require-declaration.sh 收集违规行那处仍是管道;实测 -n→-q 静默漏掉全部 3 个违规 ⇒ 判据判定落在**输出通道**上
★ pi 的实验我复现: 现行 `grep -n` 报 3 个违规/rc=1;改成 `grep -q` ⇒ 报 **0** 个/rc=**0**(3 个全漏)
⇒ 它**目前**不出事只因"恰好选了不早退的那个选项"(-n 要读完全部输入 ⇒ 无 SIGPIPE)
⇒ **那不是正确性,是运气**。与我上一版在 :78-82 修的是同一条,我却漏了 :102。
★ 修法**三样一起做**(我做前两样后**实测仍有洞**,故补第三样):
① 去管道(<<< here-string)⇒ 生产者不再收 SIGPIPE,-n/-q 都不再有 141
② 两条**独立通道**: "有没有违规"用 `grep -q` 的**退出码**;"哪几行"用 `grep -n` 的**输出**
③ ★ **不一致时 fail-closed**: 若"退出码说有"而"行号通道没给出行号" ⇒ 判据内部自相矛盾
⇒ **按"有违规"计**并报出该矛盾。
实测缺 ③ 会怎样: 只做 ①② 时,把取行号那处改成 `-q` ⇒ 报 0 个、rc=**0**(又是全漏)
⇒ **"计数"与"证据"走同一条通道时,那条通道静音就等于"没有"** ⇒
要么分通道,要么规定**静音=失败侧**(本处取后者)。
★ 验证(全部真跑,含三个变异):
· 基线 rc=0(3 个调用者,裸赋值 0 处)
· [A] 注入 3 处裸赋值 ⇒ rc=1 ✓
· [B] 判"有没有"那处 -q→-n ⇒ rc=1 ✓
· [C] 取行号那处 -n→-q(pi 的变异) ⇒ rc=1 ✓ 且 **fail-closed 报出 3 次** ✓
· 每个变异后还原并复测 rc=0;`git diff --numstat` 仅剩我的文件
(同目录另有并发会话在改 check-deploy-drift.mjs —— 未 add 它的改动)
· criteria-hygiene 7/7 绿、pi 的 env-guard 17/17 绿、bash -n 过;生产未动
|
2026-09-25 07:01:34 +08:00 |
|
|
|
d562f55d78
|
采纳 pi 反提案: 声明动作化 agentmail_require + 新判据 check-require-declaration.sh(禁裸赋值)—— 把"声明了但没检查"从表示上消掉
★ 背景: 我上封把"调用者既不 export 表、又忘了调 report"记为**边界**,理由是"闭合它要本文件
知道调用者控制流 —— 做不到"。pi 指出**前提可以换掉**(我复核采纳):
病根不是"控制流不可知",而是"**声明**(赋值)与**检查**(调用)是两个可分离的动作"。
⇒ 把声明做成**动作**: `agentmail_require <命令…>` = 赋值 + 立刻检查 ⇒ 该状态**不存在**。
★ 改动:
· env-defaults.sh 加 `agentmail_require()`(内部就是赋值 + agentmail_env_check_require)
· 三个调用者由 `AGENTMAIL_REQUIRE="…"` 改为 `agentmail_require …`(各 1 行)
也顺带把"重新导出为环境变量"的写法去掉了 —— 表只在本进程内被 ③b 读,不需要 export
· 新判据 `deploy/check-require-declaration.sh`(755): deploy/ 下的**调用者**不得写裸赋值
· install.sh 接线,走 `CHECK_GATE_RC` **累积**通道(照 check-file-modes.sh 的既有做法:
直接调会在 set -e 下中止,把后面的收尾诊断全吃掉)
★★ 判据自己的两个 bug,都是**实测**抓出来的(不是审出来的):
① 假红: 我第一版按"`deploy/**/*.sh` 全扫"划范围 ⇒ 立刻把 `env-defaults.sh:449`
(`agentmail_require()` 函数体里的 `AGENTMAIL_REQUIRE="$*"` —— **动作自己的实现**)
判成违规。⇒ 改为按**性质**划: "调用者"= **真的 source 了本库**的文件,
减去定义动作的那个库自己("调用者"这个身份由 source 这个动作定义,不由目录猜)。
② ★ 假阴且**不稳定**: `strip_comments "$f" | grep -q …` 在 `set -o pipefail` 下,
`grep -q` 一命中就退出 ⇒ `sed` 收 SIGPIPE(rc=141)⇒ **管道整体 141** ⇒ if 判假 ⇒ 漏文件。
实测同一个脚本两次分别找到 **2** 个与 **1** 个调用者(实际 3 个),
而 rc=141 被 if 静默吞掉 ⇒ 集合**偏少且不稳** ⇒ "裸赋值 0 处"会是**假绿**。
⇒ 改为先收集到变量、再 `grep <<<"$body"`(无管道)。修后重复 10 次**稳定 3 个**。
★ 验证(全部真跑):
· 基线 rc=0(3 个调用者,裸赋值 0 处);重复 10 次稳定 3
· 变异①: 把 redeploy-plugin.sh 改回裸赋值 ⇒ rc=**1** ✓
· 变异②: 注释掉一个调用者的 source(仍剩 2)⇒ rc=0 ✓ 非空转
· 变异③: 三个 source 全注释 ⇒ **集合空** ⇒ rc=**1** ✓(防空转,不是恒绿)
· 每个变异后**还原**并复测 rc=0;`git diff --numstat` 确认只有预期行
· criteria-hygiene **7/7** 绿(新 check-*.sh 已被 install.sh 真调用)
· pi 的 env-guard **17/17** 绿;五个脚本 bash -n 全过;生产未动
★ 残留(判据头已如实写): 盖"字面裸赋值",**不盖间接赋值**(经 eval/read/env 注入)——
补它需 shell 语义分析,超出"一条 grep 型判据"的射程。
|
2026-09-25 06:51:25 +08:00 |
|