diff --git a/docs/reviews/archive-status-fix-2026-09-28.md b/docs/reviews/archive-status-fix-2026-09-28.md new file mode 100644 index 0000000..81c5295 --- /dev/null +++ b/docs/reviews/archive-status-fix-2026-09-28.md @@ -0,0 +1,60 @@ +# [探针] 归档会话回信可达性 —— 缺陷已修,等待人决策 + +**状态**:代码已改完并自验通过;**未 push、未部署、未动任何生产数据**。 +下一步全部需要人拍板,故停在这里等一句话。 + +## 一句话结论 + +「归档后不可见」这条契约被 `reply_to` / `permission/request` / 平台会话 adopt 三条路绕过; +成因是 `TouchSession` 顺手把 `sessions.status` 写回 `active`,而「不可见」的两条判据 +分居 `sessions.status` 与 `mails.status` 两张表。已按**不变量**收口,不是逐个堵入口。 + +## 三个 commit(都在本地,未 push) + +| commit | 内容 | +|---|---| +| `e78888b` | `TouchSession` 只写 `updated_at`;`EnsureSessionOpen` 成为三个建邮件函数的共同前置;`reply_to` 恢复 404;`permission/request` 补参与方判据;**adopt 路径第四个入口**;不变量判据 | +| `2b77b17` | `MarkMailRead` 补 `AND status <> 'archived'`(反向洞,pi 复核时发现) | +| `a3ca64b` | `DecidePermission` 补同一处守卫(pi §五);修正我在 `e78888b` 漏落的参与方误用(会把管理员挡在决策门外) | + +改动面:5 个文件、+505/-4,全部在 `/home/program/agentmail` 内。 + +## 判据:8 条,且都验过「去掉修复就转红」 + +`server/internal/repo/session_status_invariant_test.go`,核心是不变量: + +> 对任意 `session_id`:`sessions.status='archived'` ⟹ 该会话全部邮件 archived + +不写成「某条路径返回 404」是因为入口会变(今天三个、明天可能第四个), +而**两个能写那两张表的入口一个都不能分叉**,是由构造保证的。 + +每条都实测过回退修复即转红,不是「改完就绿」的装饰。 + +## 已确认的边界(都经生产库读数复核) + +- **修好的**:不再新增分叉。四条复活路径(reply_to / permission / adopt / 反向改写两处)全堵。 +- **刻意没做的**:存量数据一条没动。`reply_to` 那 9 条的成因确证,清理动作可从成因推出; + 但要等**先部署**,否则旧代码会继续造新的。 +- **明确不要做的**:不要按「反向破坏」去清那 424 封 `read` —— pi 的更正确认, + 且我补的读数显示**主体是回填前的真实已读事实**,清了会破坏 `mail_reads`。 +- **仍未定位、不猜的**:两处 + ① 那两条大线索(268/463 封)上零星 `archived` 邮件的**写入方** —— 全仓唯一写该列的 + 是 `ArchiveSession`(瞬时全条),而实测分布横跨 5 天、第 1 行是 `read` 而第 114 行 + `archived`,**当前代码产不出这个形状**; + ② 38 封无 `mail_reads` 的行级 `read`,同样无机制可解释。 + +## 需要人决定的四件事 + +1. **推不推**这三个 commit(我没 push)。 +2. **部不部署**,以及谁执行。 +3. **存量 9 条**清不清(压测垃圾整条归档;真实对话那两条只动 `sessions` 行、 + 碰都不碰 `mails` 行)。按 pi 与我一致的顺序:部署 → 重数签名 → 才清。 +4. `docs/DEBTS.json` 里 `archive-session-filter-partial`(`FindSessionByAddress` + 缺归档过滤,补上会把重复归档从 200 变 404,属行为变更)**仍未提交** —— + 那文件与另一并行会话的改动混在一起,我不愿夹带。 + +## 顺带发现 + +工作区**无跨会话互斥**:本轮 `server/` 有另一并行会话同时在改 `ratelimit*.go` +及其两个新测试文件。那几处我全程未碰、未纳入我的 commit。 +(DEBTS 里 `shared-workspace-unserialized-deploy` 已登记此风险。)