From 63d430f423369a98ecdb36935cc1b83ab5c1b2ff Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Mon, 21 Sep 2026 04:26:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3:=20API.md=20=E8=AE=B0?= =?UTF-8?q?=E4=B8=80=E6=9D=A1=20=E2=80=94=E2=80=94=20**"=E8=AE=A1=E6=95=B0?= =?UTF-8?q?"=E5=AF=B9=E4=BA=86=E4=B8=8D=E4=BB=A3=E8=A1=A8"=E8=B4=A6?= =?UTF-8?q?=E8=AE=B0=E4=B8=8A=E4=BA=86"**=EF=BC=88=E5=B7=B2=E8=AF=BB?= =?UTF-8?q?=E6=9D=83=E5=A8=81=E5=88=97=E9=9D=99=E9=BB=98=E5=B0=91=E8=A1=8C?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 接在「已读按调用者记录」那节后面(同一段语义迁移的下游后果)。 `markReadFor` 把 reader 前置成 `$1`,而调用方 `where` 早把 `$1` 用成 recipient ⇒ 绑定表右移一格 ⇒ 最后一封永远插不进(单封一封都不插)。 `marked` 与 `mails.status` 都对,只有权威列 `mail_reads` 静默少行 ⇒ 邮件"看起来已读、实际仍算未读" ⇒ 重启补投时被当新信重投。 **为什么 7 天零痕迹**:`marked` 来自**另一条 UPDATE**,而当时那 4 个测试断言的 是冗余列 `mails.status` —— **判据守错了列**。 教训(写成可复用的):**一个值的"计数"来自 A 语句、"记账"来自 B 语句时, A 对不代表 B 对;判据必须断言决定行为的那个列。** 修在 `17908c1`,回归判据 `internal/repo/markread_authcolumn_test.go`。 --- docs/API.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/API.md b/docs/API.md index c950b45..7a2d6d1 100644 --- a/docs/API.md +++ b/docs/API.md @@ -456,6 +456,17 @@ curl -X POST {host}/api/v1/mail/read -H "Authorization: Bearer $AGENT_KEY" 读取成功"),之二是补投判据归零 ⇒ 那封信不再补投。 - 兼容说明:`mails.status` 仍然会被刷新(`read`/`archived`),但它现在只表示 "有人读过 / 已归档",**不再是未读判据**。 +- ★★ **"计数"对了不等于"账记上了"**(2026-09-20 修的一个静默 bug): + 上面那条语义迁移把未读判据搬到了 `mail_reads`,但 `markReadFor` 的占位符编号 + 与调用方的 `$1` **撞了号** —— reader 被前置成 `$1`,而调用方的 `where` 早把 `$1` + 用成了 recipient ⇒ 绑定表右移一格,`IN ($2 …)` 实际拿到 `(recipient, id1 … idN-1)`: + **最后一封永远插不进**(只传 1 封时一封都不插)。 + 症状:`POST /mail/read` 的 `marked` 与 `mails.status` **都是对的**, + 只有 `mail_reads` 静默少行 ⇒ 邮件"看起来已读、实际仍算未读" ⇒ 重启补投时**被当新信重投**。 + **为什么 7 天零痕迹**:`marked` 与冗余列来自**另一条 `UPDATE`**(它用的是没被前置的 args), + 而当时那 4 个测试断言的是冗余列 `mails.status` —— **判据守错了列**。 + 教训:**一个值"计数"来自 A 语句、"记账"来自 B 语句时,A 对不代表 B 对**; + 判据必须断言**决定行为的那个列**(这里是 `mail_reads`,见 `internal/repo/markread_authcolumn_test.go`)。 ### 每个 Agent 可用的模型范围