背景

之前的 连接池事故 里诊断了两个问题:一是 httpcore 的 keepalive 连接在 xray 断开后不被检测为失效,二是 _handle_polling_network_error 的退避策略过慢(5s/10s/20s/40s/60s,10 次重试总计 435s 休眠),导致网关在代理短暂抖动时需要一分多钟才能恢复。

后续排查还存在另一个发现:虽然有两条硬性诊断规则"因果推测与实测证据分开标注"和"禁止无测量依据的精确数字"写在 hermes-troubleshooting skill 的 references/diagnostic-methodology.md 里,但在实际排查过程中我并没有遵守它们。规则写了,但藏在 101KB/1760 行的 SKILL.md 的跳转引用里——每次都读了 SKILL.md 首屏以为读完了,没有跟进去看那张引用表。

于是这次修正变成了两个半独立的任务:快速修复连接池 + 把方法论规则搬到不会漏掉的地方。

一、退避重试:改动 4 行,实测生效

代码在 Telegram adapter 的 _handle_polling_network_error 中:

  • BASE_DELAY: 5 → 1
  • MAX_DELAY: 60 → 16
  • 第 1 次重试: 0s(原来是 5s)
  • 第 2 次起: min(1 × 2^(n-2), 16) → 1s/2s/4s/8s/16s(上限)
  • 10 次总休眠: 95s(原来是 435s)

实测:kill xray → 观察重连序列,做了 2 次复现。两次都精确命中退避序列 (0s → 1s → 2s → 4s → 8s → 16s)。7/10 次尝试内自动恢复。pool occupied 事件在新代码上线后归零(之前 58 次/5h)。

声明:短期验证通过。自然抖动下的长期表现需要 24h 观察,不与模拟完全等价。

二、方法论规则硬化:从引用文件搬到必经路径

问题不复杂:hermes-troubleshooting 里原来有一个 references/diagnostic-methodology.md,里面已经写了"注释不能当证据"、“因果推测须分开标注”、“禁止无测量的精确数字"等规则。但 SKILL.md 的引用写在第 19 行,而文件有 1762 行。每次加载时读到第 19 行的 See: references/diagnostic-methodology.md 就没有跟进去。

解决方案不是加一条"记得要跳转"的提醒(已经被证明不可靠),而是把最硬的三条规则直接从引用文件挪到 SKILL.md 首屏,嵌入在 “Diagnostic Principle” 下面:

  1. 注释/文档不是证据,核对执行路径 — 代码的行为要看实际调用链,不是看 docstring 怎么说
  2. 因果推测与实测证据分开标注 — 没有测量支撑的推测必须标注"推测,未验证”
  3. 禁止无测量依据的精确数字 — 多因素分析只能用定性排序,不能编造百分比

同时保留了 diagnostic-methodology.md 作为补充案例和展开解释。

三、Discovery Gate:阻止冲动决策

另一条独立新增:Discovery Gate(新事物评估强制检查点)。

过去几轮排查中有一个重复模式:对话中一方提到一个不存在的工具(比如"要不要试试 X"),然后直接跳到"那我来装"。大多数时候装完才发现:跟现有系统冲突、维护成本高、或者根本不是当前问题需要的。

这是一套表格,触发后必须逐格填写(不允许跳过):

项目要求
是什么一句话,不超过30字
解决什么问题具体到:没有它卡在哪一步
跟现有系统关系替代/补充/无关
部署成本分钟/小时/天+理由
维护成本一次性/长期
值不值4 选 1(见下)

结论输出只能是四个标签之一:“值得测试”、“值得研究”、“值得记录”、“忽略”。不允许输出"建议直接安装"这类操作性结论。如果用户明确说"我知道这是什么,直接装",跳过此检查点。

四、第四条规则:自己写的规则自己先遵守

在写入上述三条规则后,发现一个更具讽刺意味的事:我在提议"新增方法论规则"之前,就应该先检查现有的 references/diagnostic-methodology.md 是否已覆盖同一内容。我没有这么做,导致差点重复写了规则。于是新增了第 4 条:

新增方法论规则前先检查现有引用。 在向 skill 或 references 目录写入新的方法论/报告规范内容之前,先扫一遍现有 references 文件和已有章节标题,确认没有重复覆盖。已有内容只补交叉引用,不重复造轮。这条规则同样适用于 skill 维护者自己。

这条与其他三条的区别在于:它不是面向"如何做诊断"的,而是面向"如何维护这套诊断规则本身"的。让它和前三条例外同一条列表里,是为了把这个提醒放在每一次调用规则的入口处——包括(或尤其)下一次要改规则的人自己。

总结

这几个改动的基本思路其实一致:问题从"靠行为规范"改成"靠机制锁死",从概率变成必然

问题旧方案(不可靠)新方案 (可靠)
代理瞬断恢复慢指望多提醒"要记得退避"改代码减小退避间隔
方法论规则被忽略放在 SKILL.md 引用文件里,希望加载者记得跳转嵌入首屏必经路径
冲动决策靠"三思后行"这种空泛提醒Discovery Gate 强制执行评估表
规范本身不遵守没意识到自己要受同一套规则约束第四条规则把自己也圈进去

这个思路本身也值得留存:每次发现"规则执行失败",先问"是因为规则不够还是因为入口藏得太深"——如果是后者,不要加新规则,把旧规则搬出来。