采纳 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 型判据"的射程。
This commit is contained in:
@ -132,7 +132,7 @@ fi
|
||||
# 本脚本依赖的外部命令:缺一个就 exit 2 + 人话(见 env-defaults.sh 的 ③b 一节)。
|
||||
# 为什么必须显式声明:**"命令不在"与"命令在但输出为空"必须分开** ——
|
||||
# 下游把前者读成后者时就会产出假绿(journalctl 那两处就是:工具缺失被读成"无 panic")。
|
||||
AGENTMAIL_REQUIRE="git go npm npx node curl systemctl flock"
|
||||
agentmail_require git go npm npx node curl systemctl flock
|
||||
agentmail_env_report
|
||||
|
||||
# 与 `redeploy-gateway.sh` / `reset-demo.sh` 同源(pi 评审 2026-09-14 对出来的):
|
||||
@ -375,6 +375,22 @@ else
|
||||
"$REPO/deploy/check-file-modes.sh"
|
||||
fi
|
||||
|
||||
# 调用者声明政策:`deploy/` 下的调用者必须用 `agentmail_require` 动作声明依赖的命令,
|
||||
# 不许写裸赋值 `AGENTMAIL_REQUIRE="…"`(裸赋值与那次检查**可分离** ⇒ 检查会静默失效)。
|
||||
# 理由与射程见 `deploy/check-require-declaration.sh` 头注释。
|
||||
# ★ 与上面 `check-file-modes.sh` **同样走 `CHECK_GATE_RC` 累积通道**(理由同上,不再重复):
|
||||
# 直接调会在 `set -e` 下中止,把后面的收尾诊断全部吃掉。
|
||||
if [[ $CHECK_ONLY -eq 1 ]]; then
|
||||
_rd_rc=0
|
||||
"$REPO/deploy/check-require-declaration.sh" || _rd_rc=$?
|
||||
if [[ $_rd_rc -ne 0 ]]; then
|
||||
echo " [FAIL] 调用者声明政策没过(退出码 ${_rd_rc})—— 上面标了 [FAIL] 的那几处就是" >&2
|
||||
[[ -n "${CHECK_GATE_RC:-}" ]] || CHECK_GATE_RC="$_rd_rc"
|
||||
fi
|
||||
else
|
||||
"$REPO/deploy/check-require-declaration.sh"
|
||||
fi
|
||||
|
||||
# 插件的纯函数测试(自动转发去重等)。
|
||||
# 插件不参与构建产物,但它的逆行为会直接变成用户收件箱里的重复邮件,
|
||||
# 因此也纳入部署前的门禁。zod 已在 node_modules 里就不重装。
|
||||
|
||||
Reference in New Issue
Block a user