STATE RESET每轮必清 4 处
服务端归档会话 + 蓝方去重台账 + 两台企微清屏 + 红方进度文件。漏一处就串台,而串台的表现和真 bug 长得一样。
红蓝对抗一天能逼出 9 类事故,修一个 bug 只要几分钟——时间全花在「发现」和「核查原因」两段。清完 7 月企微通道的全部证据,14 个实例指向同一个根属性:这条链上每一层在失败时都返回成功。
// 样本 = 企微方案B 自动代回通道 · 2026-07-01 ~ 07-29 · 抖音通道未纳入
杭州机恢复自动代回后连踩三坑。把这一次逐段拆开,就能看清时间的去处——真修只是一行参数,前面两段各吃掉一个数量级。
蓝方「该回的全没回」,静默停摆 4.5 小时才被人发现。没有任何告警——护栏在正常拒发、进程在正常轮询、返回码全是 0。
第一发假设是版本回归(记录原文:「一度误判成版本回归」)。同一个「没回」症状对着六七个候选层:遮挡 / 坐标 / 读屏漏抄 / 基线推进 / 身份门 / 生成失败 / 回执落库 / 实跑版本。
计划任务弹出的 cmd 黑窗盖在企微前面 → 每轮截屏拍到黑窗+左侧列表 → 把窗口标题、会话列表碎片当成客户消息读出来、客户名一并读错 → 身份门比对「当前窗口≠目标会话」逐条拒发。护栏没坏,是喂给它的名字是错的。
任务动作改成 start /min 起黑窗,重启后当轮读屏即恢复读到真实气泡。同批另两坑:空白微信昵称让身份门永久卡死(改中文备注名)、跑红方会停掉蓝方两个任务而收工只删了 STOP 闸。
// 同一条链上的历史节拍:2026-07-01 读屏三连修 15:42 → 15:48 → 16:00(18 分钟三版)。「修」从来不是瓶颈。
周期 = 发现延迟 + 定位轮数 × 单轮验证成本 + 修复(分钟级)
三项里只有最后一项快。前两项都由同一件事决定:失败的时候,系统告诉你的是真话还是假话。
这不是「之一」,是唯一贯穿全部证据的根属性。7 月这条通道上清出 14 个实例:返回码 0、HTTP 200、workflow success、迁移已应用、DB 记 sent、卡片绿灯——每一个都在真实失败时点亮。
一层的「成功」信号由该层自己签发,而签发依据是「我把调用发出去了」(proof-of-call),不是「事情真的发生了」(proof-of-effect)。
后果是双杀:失败没有出口(发现延迟被拉到天 / 周量级)+ 所有可信信号都是假的(第一发假设几乎必错,定位轮数膨胀)。
| 层 / 动作 | 它报告的「成功」 | 实际状态 | 代价 |
|---|---|---|---|
| 拉起 loop云电脑 · schtasks /run | rc=0 | 任务动作瞬间死、零输出——日志句柄没释放,追加重定向建不起来,而错误信息本身要走那个失败的重定向 | 一晚空转 4 次 |
| 看门狗 v1云电脑 · 自动恢复 | rc=0 | 任务引擎仍标 Running,/run 被当重复实例拒掉 | 白等一个 5min 周期 |
| 发布链路GHA · vercel-deploy | CI 绿 · PR 已合 · meta 端点 200 | paths-ignore 里有 cloudpc/**,而被发布的脚本正在那个目录——只改脚本的提交不触发部署,发出去的永远是旧字节 | 自愈链 全程是断的 |
| launcher 同步云电脑 · 自更新 | 重启成功 | 103KB 穿墙下载 3 次挂 1 次,挂的那次恰好是要装新版那次 → 检测到新版→退出→同步失败→旧版重启 | 永远装不上 |
| Claude 评审GHA · PR review | workflow success | 缺 --allowedTools,跑完 20~39 轮后发评论被权限系统全部拒掉;5 个 PR 的 bot 评论数 0 | ≈$6.4 白烧 评审形同虚设 |
| 跨模型 fail-over服务端 · 空回复保险 | 代码在册 | 判据「当前模型 ≠ 默认模型」在企微回滚同款模型后恒 false | 保险 19 天 没执行过 |
| 收权迁移Supabase · REVOKE | 迁移已应用 | REVOKE FROM PUBLIC 对 Supabase 的 anon 角色实际收不掉 | #1043 → #1045 返修 |
| GUI 发送云电脑 · _deliver | 「已发送并落库」 | 输入框坐标失准时字打进了任务栏,DB 照样记 sent | 全天假发送 |
| 发送回执云电脑 → 服务端 | 屏幕上有回复 | 回执静默失败,DB 无记录 | 实盘对练 判成「漏回」 |
| 数据库查询服务端 · supabase-js | data=null | 不解构 error 时,查询故障被当成「0 条结果」 | 审计报出假的 「100% 漏写率」 |
| 读回通道诊断 · Fly 日志 | grep 命中 0 | --no-tail 一次只回 100 行 ≈ 4 秒窗口,几分钟一次的稀疏事件必然抓不到 | 误判「远程命令 根本不执行」 |
| 机队体检诊断 · md5 快照 | 四台三个 md5 | 当天连发 4 版、各机停在不同 PR,窗口期快照本身就是分叉的 | 误判 「自愈有盲点」 |
| 身份门云电脑 · 发送护栏 | 护栏正常拒发 | 喂进去的会话名是黑窗标题碎片 | 停摆 4.5h + 误判版本回归 |
| 空跑监控GHA · 元监控 | run 时长 < 90s | 代理指标两头都会错(真跑也可能快、空跑也可能慢) | 监控自己 也要返修 #1104 |
团队 memory 里已经独立命名过这个模式至少三次:《「绿」不等于「在保护」》《deploy 状态 ≠ 真相》《supabase 失败静默返回 0 条》。同一根因被反复重新发现,本身就是它没被系统性处理的证据。
把 7 月各起故障按「发现用了多久」排开,规律非常干净:只要失败在日志里留下一行,就是分钟级;只要它伪装成成功,就是天到周量级。严重性完全不影响这个排序。
// 条长为 log₁₀(分钟) 归一化,否则前两项在图上看不见。样本取自部署台账与 memory 中有明确起止记录的 5 起;发现时刻本身未被制度化记录(见 §07 缺口 E),所以这是能拿到的最强证据、不是全量分布。
定位轮数要乘上单轮成本才是真实开销。这条链的验证发生在真机 GUI 上——两台云电脑对练、每轮必清 4 处状态、一句回复动辄几十秒到十几分钟。
// 我从 07-19 那份实盘归档逐轮算的(aiReplyAt − customerAt,n=25)。那次 26 轮从 07-17 09:03 一直跑到 07-19 13:21。
服务端归档会话 + 蓝方去重台账 + 两台企微清屏 + 红方进度文件。漏一处就串台,而串台的表现和真 bug 长得一样。
「客户消息落库 → 生成 → GUI 上屏」这条链上的丢单,离线评测和单测全测不出——只有造一个镜像对手 loop 连续冲它才会暴露。
企微聊天界面是自绘原生 UI:调试端口只暴露文档预载 webview、无障碍树恒空。探针已入库,别再花时间试 DOM / UIA / CDP。
第一轮给出的是「四种税」清单。复核之后,其中一条属于过度归因、一条过于乐观、一条诊断层次不对——修正后结论反而更锐。
我把它当成「红蓝 harness 自己产假 bug」的硬证据。复核发现:那 10 条文本干净通顺、不像被读歪;归因是归档文件自己写的「可能被读侧改写/漏字」;而当时回放的剧本 从未进过版本控制(git log --all 零命中),今天已无法复核。
正确表述:证据链不可复核
自更新链路(md5 比对 + 预启动同步 + 看门狗)确实落地了、方向对。但它上线当晚就被端到端探针逼出 3 个真 bug;现在风险已反转到另一头:07-29 单日合 8 个 PR、脚本至少发 4 版,自愈会在 ~10 分钟内把新版铺满全部生产机——没有灰度、没有观察窗、没有回滚演练。
风险反转:发布节奏 > 治理能力
第一轮开的处方是「补心跳告警」。诊断层次错了:现有信号不是没有,而是会说谎。如果新加的心跳也只报「进程还在」,它就是第 15 个假成功——看门狗自己就踩过(rc=0 但空转)。
验收标准:它怎样才会红?
三处修正有个共同点:我复用了记录里现成的归因,而没有去验那个归因本身。这正是 §02 描述的同一个陷阱在分析层的复现——「记录说 X」和「X 是真的」之间,仍然需要一个外部断言。
这是「假成功是关键因素」最强的反面证据:把 7 月所有确实见效的改进摆在一起,它们全是同一个动作——把判断依据从「返回码 / 哈希 / 时长 / 模型推理」换成「该层之外的业务事实」。
| 要判什么 | 原来看(proof-of-call) | 换成看(proof-of-effect) | 效果 |
|---|---|---|---|
| 自愈跑没跑 | 四台 md5 是否相等 | 机上日志有没有 [sync] updated 轨迹 | 推翻误判 |
| 进程起没起 | rc=0 | 进程存在性(按命令行匹配) | 不再空转 |
| 日志能不能写 | 直接拉起、失败再说 | 先用同一个操作探测追加写,成功才拉起 | 6~12s 起来 (原本等 5min) |
| 评审跑没跑 | run 时长 < 90s | PR 上有没有真的出现评论 | #1104 |
| 消息发没发到 | DB 的 sent 标记 | 上屏核验 | 灭掉假发送 |
| 该改哪一层 | 让 LLM 判 fixTarget | 确定性规则分层(6 个候选模型全 0/2) | 400 条回测 仅 2 条命中且都真 |
| 质检结论真假 | 让模型再读一遍对话 | 外部证据:同事名册 / 演练剧本原文 / 部署时间 | 5 条里 0 条 该照着改 |
| 整族丢单 | 逐个变种打正则补丁 | 欠答自愈:末条是客户且其后无回复就一律补生成 | 从机制上灭族 |
它们不是根因,但会把根因的代价放大,或者让代价无法被看见。按杠杆从大到小排。
.env 各自手改detected_at / rootcaused_at每一条都附「它怎样才会红」——没有这一栏的防线,本身就是下一个假成功。
清单化、进 review checklist:返回码 → 进程存在性;deploy → 线上 md5/commit;评审 → 评论数;发送 → 上屏核验;查询 → error 必抛。这是把 §06 那张表制度化,而不是每次靠人想起来。
怎样才会红:抽掉被断言的那一环,检查必须立刻变红
loop 已按纪律把双指标写进本地状态文件,但云端没有任何东西读它(全仓 grep 零命中)。让 loop 每轮上报状态,一个 cron 比 last_tick + 业务 delta,超阈值推红牌。直接缩短 §03 里最长的那几根条。
怎样才会红:杀掉 loop 后必须在 N 分钟内自己弹红牌
跑红方会停掉蓝方的 loop 与看门狗两个任务,收工只删 STOP 闸不够。改成 红方退出即自动恢复这两个任务(或让看门狗无条件自恢复)。07-29 那 4.5 小时就是这条纪律漏了。
怎样才会红:红方异常退出后,蓝方必须自己回来
给 harness 的调用加一个显式 tag(header 或字段),所有告警、质检、统计按 tag 排除。替掉现在「≥2 个会话才告警」的猜法——那个阈值同时会漏掉真实的单会话爆发。
怎样才会红:带 tag 的流量必须 0 次进入告警与质检台账
回放剧本、人物卡、以及每次跑的运行时快照全部入仓。目标不是好看,是让 38% 的配对失败可以被事后归因、让红蓝结论能被第二个人复验。
怎样才会红:拿历史 run 重跑配对,命中率应可复现
部署台账的「起因」段固定加 detected_at / rootcaused_at。成本近零,下个月就能直接出「发现 / 定位 / 修复」三段的真实分布,不用再像本页这样靠翻档估。
怎样才会红:缺这两个字段的条目在月度复盘里计为不可分析
现状是 ~10 分钟铺满全部生产机、无观察窗。加 canary / stable 两档 + 定期回滚演练。这条是修正 ② 带出来的新风险,不在第一轮结论里。
怎样才会红:故意发一版坏脚本,canary 必须先炸且 stable 不受影响
逐个变种打补丁已被证明追不上(样板文案家族反复复发);确定性读取路线(DOM / UIA / CDP)已判死并入库探针,别再重新评估。
按团队规矩,先说清哪些是我算的、哪些是转述的、哪些至今没法验。
deploy-ids.md 逐段记录aiReplyAt − customerAt,n=25