3.3 KiB
3.3 KiB
微信文本-图片缓存隔离事故报告
结论
本次事故已经按最新备份链路回滚并收口。当前文档只记录证据、回滚和验收边界,不把“真实 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。