fix(deploy): C 扩到全文件(133/0 闭合)+ ① 加 realpath 判据 + ②b 明说"恒等" + 环境自足收成一处

pi 这一封四个实质点,逐个实测后处理:

**C. 口径扩到全部文件**(他给的是算术,不是口味,我认):
原先按后缀取(`.conf/.service/.timer/.bak*`),我说的"零违规就不扩"是把口味当论证。
他把成本量化了:差集极小 ⇒ 多读几次文件(几十 KB),而收益是那个 `0` 从
**"有范围的 0"**(只对我划的圈成立)变成**"闭合的 0"**(对整棵 /etc/systemd 成立)。
他还补了一句我没想到的:这条判据只报**内容里含仓库路径**的文件,
所以含仓库串的 `.dpkg-old`/`~`/无后缀文件**恰恰都是真信号**(过期的旧真相),
不是噪声 —— 我先前"二进制会变成噪声"的担心本来就不成立。
**验收实测:比了 133 个文件(全部,不筛后缀)、命中 0。**
另按他要求把"零违规"这个前提写进注释,并说明"红/WARN 拆分"为什么推迟
(零违规时拆分是重构不是修 bug;出现第一个非白名单命中时再决定分档)。

**反例 1(②b 对 pi 是跑不到的分支)**:确认。pi 的依赖是全局包软链
(`-> /usr/lib/node_modules/@earendil-works/pi-coding-agent`),`cp -a` 保留软链
⇒ 两侧 realpath 到**同一个 inode**(实测 `statSync(a).ino === statSync(b).ino`)
⇒ 版本集合按构造相等 ⇒ **②b 对 pi 永远不会红**。这正是本文件自己列过的第三种形态
(断言在、区分力不在),比"没写判据"更坏因为它看起来是绿的。
已改:两侧 realpath 相同时**明说"恒等、区分力为零"**并指出它真正覆盖谁(有 vendored 树的宿主),
不再报"版本集合一致"这种让人误以为验过的措辞。自检加了这一条。

**反例 2(① 的 realpath 盲区)**:确认,形状真实且三条判据全都看不见 ——
①只 grep 内容(仓库那份 unit 文本里没有仓库字面量)、②比内容(live 就是 repo 那个 inode,
必然"一致")、④只查固定名单。已加 realpath 判据:被检文件 realpath 落在仓库里 ⇒ 红,
与内容无关。自检加**正反两面**(内容干净但指向仓库 ⇒ 红;指向仓库外 ⇒ 不许红,
否则这条判据恒红)。实测:本机 `/etc/systemd/system` 下 0 条指向仓库的软链
(即这个 0 现在才是闭合的)。

**反例 3(环境假设第四次 ⇒ 建议收成一处)**:采纳。四次的形态一模一样
(HOME ⇒ 又一次 HOME ⇒ TMPDIR ⇒ GOMODCACHE/GOPATH),每次"再加一个预检"只挡已知那一个。
新增 `deploy/lib/env-defaults.sh`:一处给全 HOME/TMPDIR/GOMODCACHE(GOPATH)/PATH,
只设**未设**的变量,注释里写明四次历史与"否则第五次一定会来";
三个部署脚本开头 source 它;**删掉**我上一轮加的那个分散 go 预检。
实测:在 `HOME`/`TMPDIR`/`GOPATH`/`GOMODCACHE` **全空**的环境里
`bash deploy/install.sh --check` **exit 0**(go vet + go test 自己站起来),
兜住的变量会在 `AGENTMAIL_ENV_DEFAULTS` 里说明。

docs 补两条纪律:13「锚点必须一一对应 —— 连'文件名'都会骗你」(E 的探针教训)、
14「退出码也有量纲」(--self-check 的退出码不是自检的结论)。

验证:npm test exit 0;check-shared-libs exit 0;drift --self-check **35/0**;
prune 干跑 exit 0;install.sh --check 空环境 exit 0。
This commit is contained in:
2026-09-14 20:42:54 +08:00
parent d47035aaff
commit 7eec311756
6 changed files with 224 additions and 31 deletions

View File

@ -45,6 +45,11 @@
set -uo pipefail
REPO=${REPO:-/home/program/agentmail}
# 环境自足:一处给全(HOME/TMPDIR/GOMODCACHE/PATH)。原先这里只有一行内联兜底
# (`TMPDIR=${TMPDIR:-/tmp} npx tsc …`)—— 那正是"第四次"那种分散补丁的形状。
# shellcheck source=./lib/env-defaults.sh
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/env-defaults.sh"
GATEWAY_DB=${GATEWAY_DB:-/opt/agentmail/data/agentmail.db}
DEST_ROOT=${DEST_ROOT:-/opt/agentmail/plugins}
STAGE_ONLY=0