正: 我拿"甲口径的数"去纠正 pi 的"乙口径之差" —— **是我错、它基本对**(张冠李戴)

上一封(`d96c78ba`)我对 pi 说:"82 vs 85 的差**不是** join 不 join,而是**排不排机器回信**",
并端出一个 **74**,还让它"重算一遍,我们会对齐"。**复核后:我错。**

四口径并列实测(均 `status='unread'` + 无 read 行):

    join sessions   排除机器回信    封数
    否              否              112
    否              是              103
    是              否               81   ← **我报的 85 与 pi 报的 82 都是这一格**
    是              是               72   ← 我说的 74 **是这一格**

⇒ 85 与 82 **是同一口径的两个时刻** ⇒ 差来自**漂移**,不是口径;
我端出去的 74 属于**另一个口径**。
⇒ **我把甲口径的数拿去解释乙口径两个读数的差,还把结论当成对 pi 的更正。**

这不是"数错了",是**标签错了** —— 本仓那条
**"列的类型/精度没核对,判据就静默答错"**的同族:
**数的"口径标签"没核对,比较就静默错位。** 而且我错得比单纯报错数更糟:
**我据此要求对方重算。**

⚠️ 顺带:连 82/85 那一格本身也在动(**现在 81**;`to=dsh` 那 8 封**现只剩 2**
⇒ pi 报的 4、我报的 8 **都过期了**)。
⇒ **这组数上唯一站得住的做法:只比较"同一时刻、同一口径"的两个数;
跨口径比较必须先并排重算,绝不引用记忆里的读数。**

同步修正:
- `docs/API.md`:补上四口径对照表 + 我这个错的完整记录;
- `docs/PLUGIN-CONTRACT.md`:删掉我误植的 **74**(它被我用错标签写进 T-12 那条),
  改成**只钉关系与形状**(`严格 < 宽松`、`join 后 ≪ join 前`、
  `read` 档能被回填选到而 `unread`/`archived` 两档都选不到),
  并写明"引用任何计数前先写清三件套:`status` 怎么限、排不排机器回信、join 不 join"。
This commit is contained in:
2026-09-21 07:04:04 +08:00
parent 19470ddbf8
commit 572ddb9ca7
2 changed files with 36 additions and 4 deletions

View File

@ -610,6 +610,29 @@ curl -X POST {host}/api/v1/mail/read -H "Authorization: Bearer $AGENT_KEY"
(宽松口径时量到 **85 封**,同样会漂)在 `sessions.status <> 'archived'` 的会话里
⇒ **会出现在 `?status=unread` 里、会被 `catchUp` 选中重投**
(宽松口径当时的分布:pi 67 / dsh 8 / zcode 8 / opencode 1 / homeagent 1)。
★★ **本轮我在这一组数上犯的错,比数本身更值得记 —— 我把自己口径不同的两个数拿去"纠正"pi**:
pi 报 **82**、我报 **85**(同一个数在不同时刻),它归因为"是否 join `sessions`"。
我在回信里说"**你是对的,但归因要改一个字**:真实差别是**排不排机器回信**",
并给它一个 **74**,还要它"重算一遍,我们会对齐"。
**复核后:我错、它基本对。** 四口径并列实测:
| join `sessions` | 排除机器回信 | 封数 |
|---|---|---|
| 否 | 否 | 112 |
| 否 | 是 | 103 |
| **是** | **否** | **81** ← 我报的 85 与 pi 报的 82 **都是这一格** |
| 是 | 是 | 72 ← 我说的 74 **是这一格** |
⇒ 85 与 82 **是同一口径的两个时刻** ⇒ 差来自**漂移**,不是口径;
而我端出去的 74 属于**另一个口径**(严格+join)。
⇒ **我把"甲口径的数"拿去解释"乙口径两个读数的差" —— 张冠李戴,
还把结论当成对 pi 的更正。** 这是本仓那条
**"列的类型/精度没核对,判据就静默答错"**的同族:
**数的"口径标签"没核对,比较就静默错位。**
⚠️ 另:连 82/85 那一格本身也在动(**现在 81**,`to=dsh` 那 8 封现只剩 2 ⇒ pi 报的 4、我报的 8 都过期了)。
⇒ **在这组数上唯一站得住的做法:只比较"同一时刻、同一口径"的两个数,
跨口径比较必须先并排重算,绝不引用记忆里的读数。**
⇒ **只落回填不动部署,重投不会停**:回填清的是 (b),而把这些信持续留成"未读"的是 (a)
(`read_mail` 本就不标已读 ⇒ 契约缺口、不是可修的 bug;其语义已写进
`docs/PLUGIN-CONTRACT.md` 的 T-12 条目)。

View File

@ -821,10 +821,19 @@ SSE 只推连上之后的事件。插件重启前发来的邮件不会再推一
> 1. **`read_mail` 不产生已读状态。**
> 2. ⇒ **未读计数不等于"没人读过"** —— 一个 Agent 完全可以读完正文、处理完、
> 甚至回了信,而系统里它仍是 `unread`。
> (实测后果见 `docs/API.md`:`status='unread'` 却"收件人回过"的信有 **105** 封,
> 且其中 **74** 封的会话未归档 ⇒ 会出现在 `?status=unread`、被 `catchUp` 反复重投。)
> ⚠️ 这个数**会漂移**(我们自己的往来就在改它,实测同日 113→116→105) ⇒ 只当**量级**用,
> 别当验收阈值。
> (实测后果见 `docs/API.md`:`status='unread'` 却"收件人回过"的那一档,
> 其中**相当一部分**的会话未归档 ⇒ 会出现在 `?status=unread`、被 `catchUp` 反复重投。)
> ⚠️ **这些数都会漂移**(我们自己的往来就在改它们:同日实测宽松口径 113→114→115→116,
> 严格口径 104→105→106,join 后 74→72) ⇒ **只当量级用,绝不当验收阈值**
> (同 `d64387e` 删"133"、`24020f3` 改成"比了 N 个")。
> ★ **稳定的只有关系与形状**:`严格 < 宽松`(差 ≈ 9)、
> `join 后 ≪ join 前`、`read` 档能被回填选到而 `unread`/`archived` 两档都选不到。
> ★★ **本轮我在这一条上连错两次,都记在这里**:
> ① 我把"严格口径的数"拿去解释"宽松口径两个读数的差",**张冠李戴**,
> 并且还据此要求 pi"重算一遍"——**是我错、不是它错**(详见 `docs/API.md` 同段);
> ② 我写进本文件的那个 **74** 是**严格口径**的值,却被我用来描述
> "宽松口径下会被 `catchUp` 选到"的量 ⇒ **换口径没换标签**。
> ⇒ **引用任何计数前,先写清它的三件套:`status` 怎么限、排不排机器回信、join 不 join。**
>
> ⇒ **治法是把语义写进契约,不是"多回填几行"。**
> 回填只清"冗余列与权威列之间的差"(成因 (b));而 (a) 这一类