From a28403aeabac42243ce98601185b041066a3038c Mon Sep 17 00:00:00 2001 From: dsh Date: Fri, 2 Oct 2026 04:05:45 +0800 Subject: [PATCH] =?UTF-8?q?docs(debt):=20=E6=9B=B4=E6=96=B0=20=E2=80=94?= =?UTF-8?q?=E2=80=94=20=E7=AC=AC=E2=91=A4=E6=9D=A1=E5=88=A4=E6=8D=AE?= =?UTF-8?q?=E7=9A=84=E5=90=A6=E8=AF=81=E6=B8=85=E5=8D=95=E9=80=90=E6=9D=A1?= =?UTF-8?q?=E5=AE=9E=E6=B5=8B=EF=BC=8C=E5=B9=B6=E6=BE=84=E6=B8=85"?= =?UTF-8?q?=E8=A6=81=E4=B8=8D=E8=A6=81=E6=95=B4=E9=93=BE=E6=8A=91=E5=88=B6?= =?UTF-8?q?"=EF=BC=88=E4=B8=8D=E9=9C=80=E8=A6=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 复核 pi 的 cd04c2b3(09-25 04:57:05,37 分钟后由 d99834a3 答复,79 封在后)。 他认下"修法①不能用"(环上 5 跳 kind 全是 summary ⇒ 跳过 summary 会放行那个环), 并给了一张四条修法死因的判决表,第⑤条"回查 relayed_mails"写的是**暂未发现反例**。 ★ 本轮把「暂未发现反例」升级为**四个否证方向逐条实测**(不只验最易验的那个): 命中判据 = 10 封 D1 被指向那封【自身非 failure 键】⇒ 误杀正常转发 : **0** ✓ D2 被指向那封【mails 表已不存在】⇒ 回查空漏判 : **0** ✓ D3 判据与标题不一致 : **0** ✓ D4 链长 >1 层(本封自己也是上一份报告的报告) : **10/10** ⚠️ ★★ D4 澄清了 pi 判决表那条未决项 —— **不需要整链抑制机制**: 10 封链长实测 2/2/5/2/3/3/4/3/2/4 ⇒ **最长 5 层** 我一度以为"链长>1 ⇒ 只抑制一跳会漏、要整链砍" —— **这个推断是错的**: 判据是**逐跳独立**的,每一跳各自回查**自己**的 target,而链上**每一跳**都命中 ⇒ 链在生成过程中就被**逐跳**砍断,根本长不起来 ⇒ 那 10 封是**判据未上线时的历史遗留**(正是它要消灭的东西) ⇒ pi 判决表的备注「需与『环整体抑制还是只抑制一跳』配套决定」**不成立** ★ 这正是 ⑬′ 的用处: 只跑 D1 我会漏掉 D4,而 D4 才是要去澄清"要不要整链机制"的那一条。 ★ 复核 pi 的数据更正,方向对但**他自己那数也已是旧快照**: 他说 summary=422 / permission=138(我 09-25 报 419/138) 此刻实测: summary=**455** / permission=**137** ⇒ 我引的确实是旧快照 ✓(他更正成立);但 422 现在也不是现值了 ⇒ 且 permission 从 138 **降到 137**,与我上轮查到的"那批测试夹具数据成组删除" (zcode 的 8f056b73 权限请求不在了)**吻合** —— 第三次应验"引用必须带时刻"。 未做: 没改代码(本轮只读 SQL)。该位仍未落地(落点在桥侧)。 10 封与四个 D 都是此刻的瞬时值。 验证: repo Debt ok; criteria-hygiene 10/10。 ⚠️ debt-visibility **仍 0/1 失败**,原因与本提交无关: harmony-appearance.test.mjs 边界声明 6 > 登记 4 —— 那是**另一会话未提交**的工作树改动 (+183 行),该判据自己写着"别只改数字,先补一笔";那笔债的内容属对方工作,我不代填。 --- docs/DEBTS.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/DEBTS.json b/docs/DEBTS.json index 6a2c63c..8bf5ef6 100644 --- a/docs/DEBTS.json +++ b/docs/DEBTS.json @@ -435,10 +435,10 @@ { "id": "failure-report-cycle-suppress-by-relayed-mails-lookup", "count": 1, - "due": "桥侧要抑制『报告的报告』时(照此判据实现);或任何人再算这类环的规模时(口径必须是 '%failure:%' 与 '%-failure:%' 的并集)", + "due": "桥侧要抑制『报告的报告』时(照此判据实现;**无需整链抑制机制**,逐跳判定自带该性质);或任何人再算这类环的规模时(口径必须是 '%failure:%' 与 '%-failure:%' 的并集)", "where": "relayed_mails.relay_key(最后一段 = 被指向那封的 mail_id)· 桥侧落点 plugins/*-mail-bridge/src/index.ts(出站生成 key 处)· 实测环 e43496ed→2ffb7dbb→84900edd→b3789a21→41ea9a15 · 载荷侧 notify/mail.go grep relay=0(故加字段要改网关)", - "kind": "**『报告的报告』的自激环,判据已在元数据里**:本封 relay_key 指向的那封 ∈ relayed_mails ⇒ 该抑制,网关契约一个字不用改(逐跳实测:第 2 跳起 4/4 命中,第 1 跳是根不命中)。本轮修正 pi 一处口径误读——标题启发式在真值口径下 **10/10 全中、漏 0**,问题是它答的是另一个问题(『是失败报告』59 封 vs 『在报告报告』10 封),拿它抑制会误杀 59 封真报告", - "note": "★★★ 2026-09-30 登记。这条在会话里由 pi `2053c8db` 提出(2026-09-25 04:53:14,我 20 分钟后 `148a4220`/`27fd0135` 两封答复),**账本里此前没有**。本轮把它连同**一处口径修正**一起落进来。\n\n## 问题:失败报告的\"环\"(报告的报告)会自激\n\n```\n一条失败报告本身也被 relay(kind=summary、relay_key=`*-failure:<上游id>`)\n⇒ 它的失败回报又生成一条新失败报告 ⇒ 环\n⇒ 抑制点必须在 **ClaimRelay 之前** return(否则占住幂等键,见 `relay-placeholder-leak-…`)\n```\n\n## ★ pi 找出的位:**回查 `relayed_mails`**,网关契约一个字不用改\n\n```\n载荷里**没有** relay 身份(notify/mail.go 全文件 grep relay = **0**;mail.go:39 的 RelayKey\n只用于入站校验、不下发)⇒ 载荷加字段这条路要改网关\n★ 但元数据里**已经完整存在**: 本封的 `relay_key` 最后一段就是**被指向那封的 mail_id**\n 判据 = 「本封的 relay_key 所指向的那封 ∈ relayed_mails」⇒ 这是一封**报告的报告** ⇒ 抑制\n⇒ 桥只要拿本封来信 id 去查一次 relayed_mails 即可,**不依赖标题、不依赖载荷**\n```\n实测逐跳(2026-09-30,pi 那条环 `f76025c9` 的 5 跳):\n```\n第 1 跳 e43496ed target=b3ce9d0f 在 relayed_mails? **False** ← 根,回报合法\n第 2 跳 2ffb7dbb target=e43496ed **True** ← 该抑制\n第 3 跳 84900edd target=2ffb7dbb **True**\n第 4 跳 b3789a21 target=84900edd **True**\n第 5 跳 41ea9a15 target=b3789a21 **True**\n```\n⚠️ `f76025c9` 那封本身在 mails 表里**已查不到**(归档/清理),但环上 5 跳都在,逐跳判定成立。\n\n## ★★ 本轮的实测修正:pi 说\"标题启发式漏失远超 30%\"—— **在真值口径下不成立**\n\n```\nfailure 类 relay 封数 = **113**(口径: relay_key LIKE '%failure:%' OR '%-failure:%')\n ★ 注意口径: 真实键是 `model-failure:` / `zcode-failure:` / `service-failure:`(**连字符**)\n 而 `homeagent:failure:` 才用**冒号** ⇒ 只写 '%failure:%' 只匹配到那 16 个(pi 09-25 已纠正过这点)\n真值(该抑制,元数据判据) = **10** 封\n 标题含「处理失败」的能认出 = **10 / 10** ⇒ ★ **漏 0 封**(标题里 `处理失败:` 逐层叠加)\n标题判据认出的总数 = **59** 封\n```\n⇒ **两个判据回答的不是同一个问题**(这是我预判错的地方):\n```\n标题判据认「这封**是**失败报告」 ⇒ **59** 封 ⇒ 真报告,**该发**\n元数据判据认「这封**在报告**一份报告」 ⇒ **10** 封 ⇒ **该抑制**\n⇒ 用标题去抑制会**误杀 59 封真报告**;标题认得全,但它答的是另一个问题\n⇒ 而 pi 的位在**正确性**上更硬(不依赖标题、不误杀),在**召回**上与标题持平\n★ 所以对 pi 那句的准确修正是: 不是「标题漏得多」,而是\n **「标题答的是另一个问题;拿它去抑制会误杀」**。\n```\n\n## 可判动作 / 修法要点\n\n· 桥侧:`data.mail_id` → 查本封 ∈ `relayed_mails` ? 是 ⇒ 抑制回报;否 ⇒ 正常回报。\n· ⚠️ 抑制必须发生在 **ClaimRelay 之前**,否则又落一个占位行(永占幂等键)。\n· 口径陷阱:判 failure 类要用 `'%failure:%'` **或** `'%-failure:%'` **两者并集**。\n 只写 `'%failure:%'` 只能命中 `homeagent:failure:*` 那 24 个(实测),\n 漏掉全部连字符族(`model-` / `zcode-` / `service-`)。\n ⇒ 只写前者会**漏 89 个**(113 − 24),不是漏 97 —— 我第一版把数算反了,已按实测改。\n\n## 边界 / 未做\n\n· **没有改任何代码**(本轮只读 SQL)。该位**未落地**——落点在桥侧(`plugins/*-mail-bridge/src/index.ts`),\n 且要与\"环整体抑制还是只抑制一跳\"配套决定。\n· 10 / 59 / 113 都是**此刻**的值(瞬时量),引用须带时刻。\n· 我**没有**去核\"标题判据在别的 session 上是否也 10/10\"——样本只此一个环族。\n· 我**没有**判定 pi 那句\"漏失远超 30%\"是在哪个口径下说的(他未附口径)——\n 我只能说在真值口径下它不成立。\n· 未能回给 pi(`send_mail` 被会话闸挡下)。" + "kind": "**『报告的报告』的自激环,判据已在元数据里**:本封 relay_key 指向的那封 ∈ relayed_mails ⇒ 该抑制,网关契约一个字不用改(逐跳实测:第 2 跳起 4/4 命中,第 1 跳是根不命中;链长实测最长 5 层但判据逐跳独立 ⇒ 不需要『整链抑制』的配套机制)。本轮修正 pi 一处口径误读——标题启发式在真值口径下 **10/10 全中、漏 0**,问题是它答的是另一个问题(『是失败报告』59 封 vs 『在报告报告』10 封),拿它抑制会误杀 59 封真报告 本轮把 pi 的『暂未发现反例』升级为**四个否证方向逐条实测,三个为空**", + "note": "★★★ 2026-09-30 登记。这条在会话里由 pi `2053c8db` 提出(2026-09-25 04:53:14,我 20 分钟后 `148a4220`/`27fd0135` 两封答复),**账本里此前没有**。本轮把它连同**一处口径修正**一起落进来。\n\n## 问题:失败报告的\"环\"(报告的报告)会自激\n\n```\n一条失败报告本身也被 relay(kind=summary、relay_key=`*-failure:<上游id>`)\n⇒ 它的失败回报又生成一条新失败报告 ⇒ 环\n⇒ 抑制点必须在 **ClaimRelay 之前** return(否则占住幂等键,见 `relay-placeholder-leak-…`)\n```\n\n## ★ pi 找出的位:**回查 `relayed_mails`**,网关契约一个字不用改\n\n```\n载荷里**没有** relay 身份(notify/mail.go 全文件 grep relay = **0**;mail.go:39 的 RelayKey\n只用于入站校验、不下发)⇒ 载荷加字段这条路要改网关\n★ 但元数据里**已经完整存在**: 本封的 `relay_key` 最后一段就是**被指向那封的 mail_id**\n 判据 = 「本封的 relay_key 所指向的那封 ∈ relayed_mails」⇒ 这是一封**报告的报告** ⇒ 抑制\n⇒ 桥只要拿本封来信 id 去查一次 relayed_mails 即可,**不依赖标题、不依赖载荷**\n```\n实测逐跳(2026-09-30,pi 那条环 `f76025c9` 的 5 跳):\n```\n第 1 跳 e43496ed target=b3ce9d0f 在 relayed_mails? **False** ← 根,回报合法\n第 2 跳 2ffb7dbb target=e43496ed **True** ← 该抑制\n第 3 跳 84900edd target=2ffb7dbb **True**\n第 4 跳 b3789a21 target=84900edd **True**\n第 5 跳 41ea9a15 target=b3789a21 **True**\n```\n⚠️ `f76025c9` 那封本身在 mails 表里**已查不到**(归档/清理),但环上 5 跳都在,逐跳判定成立。\n\n## ★★ 本轮的实测修正:pi 说\"标题启发式漏失远超 30%\"—— **在真值口径下不成立**\n\n```\nfailure 类 relay 封数 = **113**(口径: relay_key LIKE '%failure:%' OR '%-failure:%')\n ★ 注意口径: 真实键是 `model-failure:` / `zcode-failure:` / `service-failure:`(**连字符**)\n 而 `homeagent:failure:` 才用**冒号** ⇒ 只写 '%failure:%' 只匹配到那 16 个(pi 09-25 已纠正过这点)\n真值(该抑制,元数据判据) = **10** 封\n 标题含「处理失败」的能认出 = **10 / 10** ⇒ ★ **漏 0 封**(标题里 `处理失败:` 逐层叠加)\n标题判据认出的总数 = **59** 封\n```\n⇒ **两个判据回答的不是同一个问题**(这是我预判错的地方):\n```\n标题判据认「这封**是**失败报告」 ⇒ **59** 封 ⇒ 真报告,**该发**\n元数据判据认「这封**在报告**一份报告」 ⇒ **10** 封 ⇒ **该抑制**\n⇒ 用标题去抑制会**误杀 59 封真报告**;标题认得全,但它答的是另一个问题\n⇒ 而 pi 的位在**正确性**上更硬(不依赖标题、不误杀),在**召回**上与标题持平\n★ 所以对 pi 那句的准确修正是: 不是「标题漏得多」,而是\n **「标题答的是另一个问题;拿它去抑制会误杀」**。\n```\n\n## 可判动作 / 修法要点\n\n· 桥侧:`data.mail_id` → 查本封 ∈ `relayed_mails` ? 是 ⇒ 抑制回报;否 ⇒ 正常回报。\n· ⚠️ 抑制必须发生在 **ClaimRelay 之前**,否则又落一个占位行(永占幂等键)。\n· 口径陷阱:判 failure 类要用 `'%failure:%'` **或** `'%-failure:%'` **两者并集**。\n 只写 `'%failure:%'` 只能命中 `homeagent:failure:*` 那 24 个(实测),\n 漏掉全部连字符族(`model-` / `zcode-` / `service-`)。\n ⇒ 只写前者会**漏 89 个**(113 − 24),不是漏 97 —— 我第一版把数算反了,已按实测改。\n\n## 边界 / 未做\n\n· **没有改任何代码**(本轮只读 SQL)。该位**未落地**——落点在桥侧(`plugins/*-mail-bridge/src/index.ts`),\n 且要与\"环整体抑制还是只抑制一跳\"配套决定。\n· 10 / 59 / 113 都是**此刻**的值(瞬时量),引用须带时刻。\n· 我**没有**去核\"标题判据在别的 session 上是否也 10/10\"——样本只此一个环族。\n· 我**没有**判定 pi 那句\"漏失远超 30%\"是在哪个口径下说的(他未附口径)——\n 我只能说在真值口径下它不成立。\n· 未能回给 pi(`send_mail` 被会话闸挡下)。\n\n## ★★ 第⑤条判据的否证清单(2026-09-30 逐条实测,全部为空)\n\npi 那张判决表里第⑤条写的是「**暂未发现反例**」。本轮把它升级为**四个方向逐一实测**:\n\n```\n命中判据的封数 = **10**(口径同前: '%failure:%' ∪ '%-failure:%')\n D1 被指向那封【自身非 failure 键】⇒ 会误杀正常转发 : **0** ✓\n D2 被指向那封【在 mails 表已不存在】⇒ 回查空 ⇒ 漏判 : **0** ✓\n D3 判据与标题不一致(标题不含『处理失败』) : **0** ✓\n D4 链长 >1 层(本封自己也是上一份报告的报告) : **10/10** ⚠️ 见下\n⇒ 前三个方向都没有反例;D4 不是反例,而是它的**工作方式**。\n```\n\n### D4 澄清了一个未决项:要不要\"整链抑制\"?(**不需要**)\n\n```\n10 封的链长实测: 2/2/5/2/3/3/4/3/2/4 ⇒ **最长 5 层**(41ea9a15←b3789a21←84900edd←2ffb7dbb←e43496ed)\n★ 我一度以为\"链长 >1 ⇒ 只抑制一跳会漏、需要整链砍的额外机制\" —— **这个推断是错的**:\n 判据是**逐跳独立**的 —— 每一跳各自回查**自己**的 target,而链上**每一跳**都命中\n ⇒ 链在生成过程中就被**逐跳**砍断,根本长不起来\n⇒ 这 10 封是**判据未上线时的历史遗留**(正是它要消灭的东西)\n⇒ ★ 所以 pi 判决表那条备注「需与『环整体抑制还是只抑制一跳』配套决定」——\n **不成立**: 不需要配套决定,逐跳判定自带这个性质。\n★ 这条是我自己的 ⑬′ 读法派上用场: 我没有只验 D1(最容易被验的那个),\n 而是先把**否证方向列全**再逐条跑 —— 若只跑 D1,我会漏掉 D4,\n 而 D4 恰恰是要我去澄清\"要不要整链机制\"的那一条。\n" } ] }