Files
aios/docs/incidents/WEIXIN_TEXT_IMAGE_CACHE_ISOLATION_20260711.md
T

3.3 KiB
Raw Blame History

微信文本-图片缓存隔离事故报告

结论

本次事故已经按最新备份链路回滚并收口。当前文档只记录证据、回滚和验收边界,不把“真实 inbound 已完成”写成结论。

现象

  • 纯文本消息被误答成旧图片回复,属于 stale-image reply on pure text。
  • 现场证据显示 types=1 且 hasMedia=false,但后续又进入 message_type=image、image_count=0、implicit_image_message,最终落到 cached_image_expired。
  • 这说明“诊断文本”被误判成图片意图后,又继承了 sender 级旧图缓存。

根因

  • fixes/patch_openclaw_weixin_hermes.py:768-839 把文本意图判断和缓存回退放在同一条链上。
  • looksLikeHermesImageFollowup() 会把含图片关键字的诊断文本推进 image intent。
  • resolveHermesFollowupImageContext() 随后会读取 sender 级缓存;一旦缓存命中失败或过期,就会落到 cached_image_expired,从而让纯文本沾上旧图上下文。
  • handleHermesImplicitImage() 继续把消息送入 handleHermes(..., "implicit_image_message"),所以误判会沿着同一条图片处理通道传播。

护栏不变量

  • 没有明确图片 follow-up 语义的纯文本,不能进入 handleHermesImplicitImage()。
  • 只有真实图片 follow-up 且缓存仍有效时,才允许走 resolveHermesCachedImageEntry() 的 cached_image_matched 路径。
  • /hermes 这类 slash 路径保持原有分流,slash/channel 面不变。
  • 这次修复的守卫目标,就是把“文本诊断”与“图片缓存回退”拆开,避免再把普通文本提升成图片意图。

TDD 与幂等性

  • 66d637fc0364a617c7b9fd8cd9baa68fb0368675(fix(weixin): isolate text from stale image cache)引入了隔离修复和 tests/test_weixin_image_followup_intent.py。
  • 2de29c59bb946cc3db3e14e8a06270391ede8401(fix(weixin): add process-only runtime patch mode)继续收紧 process-only 运行模式,保持回放幂等。
  • 相关测试证据已写入 reports/codex/UCC_WECHAT_SEND_BACKEND_OWNER_TEST_20260707.md:27,其中本地测试记录为 Ran 7 tests ... OK。
  • 生产 npm 分发侧本身缺少 tsconfig/tests,baseline 与 patched 共享这一限制,所以这里不把分发目录的缺口当成回归点;验收以 node check 和 7 tests 为准。

回滚与备份

  • 回滚按最新备份执行,基线指向 /data/aios-gitops/runtime/latest-backup-dir.txt 所示的最新备份目录。
  • 备份路径链路按供给证据记录为 T064506Z、T074212Z、T081658Z。
  • 本次恢复后,部署过程哈希记录为 e9625d12 和 c00c58f8,slash/channel 口径保持不变。

运行态验证

  • gateway PID 由 4025932 变为 1723576,当前活跃监听仍在 18789。
  • 现场/供给证据显示 journal plugin errors = 0、channel lastError = false、cache preserved。
  • 这说明回滚后运行态没有再冒出新的插件错误,缓存状态也仍然保留。

未完成的真实验收

  • owner 纯文本
  • diagnostic text
  • genuine image-followup message

以上三类消息仍需要真实到达,才能把这次“文本隔离”结论升格为完整的线上接受;本报告不把它们伪装成已经完成。

安全说明

  • 本次仅新增文档,没有修改代码、runtime、services 或 secrets。
  • 报告里没有任何凭据、密钥或原始敏感 ID。