diff --git a/docs/API.md b/docs/API.md index 731a287..cb59eeb 100644 --- a/docs/API.md +++ b/docs/API.md @@ -4785,3 +4785,48 @@ window.__AGENTMAIL_TOKEN__ = ''; // 省略则走 Cookie 而那个差异**不存在**(是我探针的假绿造出来的) ``` ## (E) 边界: 只读探针 + 三个**注定失败**的写入尝试(无一改到生产);仓库/生产未动 + +--- + +- ★★ **顺着我自己的假绿,在 `deploy/lib/env-defaults.sh` 里查到同一形状的第二处**(已修 `031848d`) + 这是"`[ -w ]` 查权限位、而拦截在另一层"那一条的**同一个错,长在我自己的 scope 里** + + ## (A) 缺陷:两处"可写吗"都只看权限位 + ``` + deploy/lib/env-defaults.sh:196 if mkdir -p "$_am_home" 2>/dev/null && [ -w "$_am_home" ]; then + deploy/lib/env-defaults.sh:179 ... [ ! -d "$_am_home" ] || [ ! -w "$_am_home" ]; then + 本机实测(同一台、同一 shell,uid=0): + [ -w /root ] ⇒ true / touch /root/x ⇒ **Permission denied** + [ -w /opt/agentmail ] ⇒ true ⇒ touch /opt/agentmail/x ⇒ **Permission denied** + ★ 注意 177 行**原本就写着** "mkdir -p 对已存在的不可写目录会返回成功,所以必须再单独判" —— + 诊断是对的,**但"那个单独判"选错了层**(`-w` 而不是真写) + ``` + ## (B) 后果正撞在文件自己存在的理由上 —— **误指对象** + ``` + HOME 空 + uid=0 ⇒ _am_home=/root ⇒ 179/196 判"可用" ⇒ HOME=/root 放行 + ⇒ ② 段取 $HOME/.cache/go-build 当 GOCACHE + ⇒ 那里用的是**真写探针**(297 行 `: > "$_am_gocache/.agentmail-probe"`)⇒ 失败 + ⇒ 报出「**GOCACHE**=/root/.cache/go-build 不可写」 + ⇒ 根因是 **HOME**,报出来的是 **GOCACHE** —— 而本文件的头号理由是"把环境问题说清楚", + 它却把一个环境问题**指到了另一个对象**上(实测可复现) + ⇒ ★ 同一文件里**两种做法并存**: 297 行真写、196 行看权限位 —— + "同一个问题两套判据"本身就是缺陷的形状(一处对一处错,而错的那处更靠前) + ``` + ## (C) 修法与验证 + ``` + 加 `_am_can_write()`(**真去写探针文件**,与 297 行同一办法),179/196 两处都用它。 + ★ **必须两处一起改**: 196 的 else 是 `exit 2`(不是 fallback)⇒ 只改 196 会让 /root + 直接 exit 2,而不是改判到 fallback。 + ★ WARN 括注从"(非 root / passwd 里没有可用目录)"改成"(已实测真写探针;uid=%s)" —— + 原括注是**按 uid 猜的原因**,而判据已不按 uid 判(uid=0 也会走到这里): + **不报没验过的原因**。 + ⚠️ 前半句 `按身份推出来的 HOME=%s 不可用` **一字未动** —— + 它是 `plugins/pi-mail-bridge/test/env-guard.test.mjs:268` 的 assert.match **锚**。 + 我第一版改成了"写不进去",**实测把 pi 的测试弄红(16/17)**,已改回 ⇒ 17/17 绿。 + ⇒ 记法: 改文案前先 grep 全仓**谁匹配这句话**;"锚"是别人的判据,不是我的措辞。 + ★ 变异测试: `_am_can_write` 改成恒真 ⇒ **被抓住**,且复现的正是上面那条误指 + (HOME 空时不再改判 ⇒ 直接报「GOCACHE 不可写」)✓ + ★ 反空真: 对 /tmp、工作区返真;对 /root、/opt/agentmail、/nonexistent、空串返假 + ⇒ 有区分力(非恒真、非恒红)✓ + ``` + ## (D) 边界: 只读探针 + 三次注定失败的写入尝试(无一改到生产);生产未动;三处 source 者未改