Files
MailUI4Agents/deploy
JianFeeeee 2393703100 feat(deploy): 构建步打印**工作树清单** —— 把不可归因的 modified=true 换成有名字的清单
pi 2026-09-25 提的第三种处置(既不判红、也不只留一个 bool),我采纳。

## 为什么一个 bool 不够

`go build` 在脏树上**照样**写 `vcs.revision=<HEAD>`,只额外记 `vcs.modified=true`。
那个位只说"含未提交代码",**不说是谁的什么** —— 而本仓是**多 agent 并发**:
未提交改动通常**不是部署者的**,是别人的在飞工作。

⇒ 这不是理论,本仓**已经付过代价**(`check-deploy-drift` 判据⑥ 注释里那笔账):
  2026-09-14 `pool.mjs` 一行未提交的 `let missingSessionCount = 0;` 被"从脏工作区做的"
  快照原样带进生产,而当时判据① 报的是「逐字节一致」。

## 处置:打印清单,不判红

```
say "3. 构建二进制" 之后、go build 之前:
  git status --porcelain 非空 ⇒ warn "工作树不干净 —— 下面这份未提交清单会被**编进这次构建**" + 逐行打印
  否则                        ⇒ ok "工作树干净(构建件不含未提交代码)"
```

★ 位置贴紧构建步:`go build` 读的就是**此刻**的工作树,所以这份清单才对应"进了这份二进制的东西"。
★ 判红与否改变不了的事实:**清单有名字,bool 没有** —— 出事时能直接看出"带进去的是谁的那两个文件",
  而不只能回答"当时是脏的"。(本会话同族:一个位 vs 一份清单 = 不可归因 vs 可归因。)

## 同时给 ⑤b 记一条**边界**(避免下一个人把它补错)

`check-deploy-drift` 的 ⑤b **读不到构建时的工作树** —— 它读的是二进制内嵌位,
而它那里的 `git status` 问的是**此刻**的树(两者可能不同:构建完又提交了、别人的改动进来了)。
⇒ 注释里写明:清单归**部署脚本**(那里才是同一时刻),⑤b 只回答"含不含未提交代码",
  **别把 ⑤b 补成 `git status` 然后当成构建清单**。

## 验证

`bash -n` 通过;`--dry-run` rc=0 且不落地(只留 0 字节锁),清单在 dry-run 下照常打印(只读);
自检 63 项绿、`判据自检失败` 不出现。
2026-09-25 06:38:13 +08:00
..