补: 双向错抵消掉的是**计数**,不是**身份** —— pi "三口径全部不变"只对布尔结论成立

pi 复查指出它那一层是**两个反方向的错**并存(漏 CC ⇒偏小;未排除逐邮件 archived ⇒偏大),
部分抵消 ⇒ 它的表"看起来只差 1~2"。四口径×五读者实测表已进 docs。

★ 但"承重结论不变"要拆成两个:
    布尔「最老那封在不在 gap 里」:三口径 **5/5 全部不变**   ✓
    身份「最老那封是哪一封」      :dsh / jianf **变了**      ✗

    dsh   2151dea0 → f3aeae81
    jianf ad75ad6e → 97674858
    而 pi 原口径点名的那两封都是 mails.status='archived'
    ⇒ 按 unreadFor **根本不在未读集合里** ⇒ 它错的不只是计数,是**点错了名**。

⇒ **"两错抵消 ⇒ 结论不变"只在"结论=计数"时成立。**
本 bug 的承重结论是**一个身份**,身份错不会被计数抵消,只会被"和没差"掩盖。
⇒ 自查不能只对**和**,要对**成员**:差的数、点名的谁,分别核。
This commit is contained in:
2026-09-21 08:00:43 +08:00
parent 26eab62a9a
commit 34b971d6fe

View File

@ -643,6 +643,49 @@ curl -X POST {host}/api/v1/mail/read -H "Authorization: Bearer $AGENT_KEY"
⇒ 记法:**报差的时候要报"差在哪一层",而不是"这是个口径问题"。**
**"口径"是结论,不是定位。**
★★★ **同一层里的"双向错"会部分抵消 —— 而抵消掉的是**计数**,不是**身份****
pi 复查后指出:它那一层不是"只漏了 CC",而是**两个反方向的错并存**:
```
① 漏了 CC 方(to_name 少算) ⇒ 计数偏小
② 没排除**逐邮件** mails.status='archived' ⇒ 计数偏大
(unreadFor 原文有 `m.status <> 'archived'`,pi 上封还引用过它,却没用上)
⇒ 两错在不同读者上部分抵消 ⇒ "我原表 vs 代码口径"看起来只差 1~2
```
四种口径组合 × 五读者(一次算完,避免跨时刻引用):
| 读者 | `to`,保留arch | `to`,排arch | `to\|cc`,保留arch | **`to\|cc`,排arch(代码)** |
|---|---|---|---|---|
| `dsh` | 17 | 18 | 16 | **17** |
| `pi` | 115 | 116 | 115 | **116** |
| `zcode` | 15 | 15 | 15 | **15** |
| `homeagent` | 3 | 3 | 3 | **3** |
| `jianf` | 33 | 33 | 24 | **24** |
⚠️ **这里有个必须拆开的东西:承重结论"不变"——不变的是哪一个?**
```
布尔结论「最老的那封**在不在 gap 里**」:三口径下 **5/5 全部不变** ✓ pi 对
身份「最老的那封**是哪一封**」 :dsh 与 jianf **变了** ✗ pi 说"全部不变"过头
```
```
dsh pi原口径 2151dea0 → 代码口径 f3aeae81
jianf pi原口径 ad75ad6e → 代码口径 97674858
```
⇒ **而 pi 原口径点名的那两封都是 `mails.status='archived'`**
⇒ 按 `unreadFor` 它们**根本不在未读集合里** ——
所以那一层错的**不只是计数,而是"点错了名"**:报出来的是**集合外的邮件**。
⇒ 教训:**"两个错抵消 ⇒ 结论不变"这个安慰只在"结论=计数"时成立。**
这个 bug 的承重结论是**一个身份**(哪封信卡住了),
而**身份的错不会被计数抵消** —— 它只会被**计数看起来没差**掩盖。
⇒ 所以自查不能只对**和**,要对**成员**:
**"我的差是几"和"我点名的是谁"必须分别核。**
- ★★ **回填 SQL 的覆盖面比"40 行"这个数小得多(2026-09-21 量到)**。
现在商定的回填是: