复盘驱动开发

每篇复盘必须收口为红线、门禁或技能

Posted by walikrence on September 8, 2026

背景脱敏:一个多仓库的游戏项目,客户端仓 docs/reviews/ 下现有 75 个 Markdown 文件,分 10 个问题域子目录;服务端仓同目录约 137 篇。大部分复盘由 AI 编码代理在事故修完的同一会话里写成。本文讲的不是怎么写复盘,是怎么让复盘不白写:每篇复盘必须收口为三种产出物之一,红线、门禁或技能,否则视为没做完。

问题:口头分析冒充复盘

4 月 24 日一次会话,用户说「完整复盘一下为何没有 res」。代理输出了一份格式完整的 Markdown 报告:原因分析、已完成 / 未完成表、改进措施。看起来像复盘,但五步流程一步都没走:没按模板写文件、没归档到问题域目录、没更新规则、没验证闭环。会话一结束,这段分析随上下文一起消失。

这次事件后来自己成了一篇复盘,结论是「复盘」这个词被理解成了「分析问题并输出报告」,而不是「执行一个有实体产出的工作流」。识别信号很具体:会话里有「复盘」主题的长篇输出,但 docs/reviews/ 下没有新增文件。

设计:五步流程与产出物分级

技能定义的复盘流程是五步:写文档、按问题域归档、提炼预防措施、逐条实施、验证闭环。核心原则一句话:复盘文档是中间产物,红线和技能才是最终交付物。

提炼出来的预防措施按落地位置分三级:

产出物 落在哪 适用
红线 项目规范文件(每次会话必读) 跨场景通用的禁止项,一句话能说清
门禁 pre-push hook 或 CI 脚本 能被程序判定的违规,人和代理都会犯
技能 skills/<名>/SKILL.md 特定场景的操作规程,有触发条件

三级的区别在于「谁来执行」。红线靠代理读到后遵守;门禁不需要任何人记得,推送时自动跑;技能只在对应场景被触发时加载,不占常驻上下文。同一个教训往往三级同时落:红线说「不许」,门禁数「还剩几处」,技能写「正确的做法」。

模板里的关键字段也是为收口服务的:TL;DR、时间线、根因分直接原因和深层原因、修复方案由浅入深、「经验总结」表要求每条是「代理或人能执行的动作」,「改进建议」表强制三列「谁、做什么、怎么验证」且占全文 30% 以上,末尾是「产出清单」。问题域目录固定为缓存与路由、协议与错误处理、初始化与超时、稳定性与安全、流程与规范等,同域满 3 篇必须写一篇汇总。

三个案例

案例一:解锁头像框只显示不发放,潜伏 21 天。 8 月 24 日测试报单「角色解锁的头像框在背包看不到」。根因不是忘了发放,是模型选错:头像框需要「拥有态」(进背包、能穿戴、可过期),却被塞进一张「不落库、按等级实时推导」的展示物配置表。界面判定写的是 Locked = level < cfg.UnlockLevel,只看等级,界面真会从锁变成已解锁,策划也照着配了解锁等级,唯独道具从未发放。21 天里每个人看到的都是正常的。

收口三级齐全。红线两条进规范文件:「解锁态 / 拥有态判定不得脱离真实持有,禁止按等级现算」,识别信号是判定表达式里没有任何查询玩家实际持有的调用;「同一张表里同类字段的不对称等于漏做信号」,因为同表的语音包有 ItemId 列而特效没有,并列躺了 20 天。门禁一条:一个遍历枚举的单测,每个外观类型必须登记留存语义(临时 / 走道具 / 走拥有列表),漏登记 CI 当场红,错误信息直接向作者抛出「这东西需不需要在玩家账下留存」。再加一个会数数的检查 CountUnmappedDressEffects(),收口判据 12 → 0。

案例二:两种失败原因合并一个错误码,礼包越买越超。 8 月 6 日,玩家金币清零进一个区间制门槛的场次(下限 2 万、上限 500 万)弹入场不足礼包,连买 4 次到 2400 万仍反复弹、进不了场。服务端一周前加了「超上限拒绝」,但结果映射把「超上限」和「不足」合并成同一个线上错误码,客户端一律弹补币礼包,买得越多离上限越远。

收口为一条红线:「失败原因禁止合并一码,一条错误信息只能对应一个根因;复合条件失败时拆成各自分支分别报错,并在文案里点明排查方向」。红线正文附了两个反例,这一起和 8 月 12 日锦标赛弹窗把「配表查不到该 Id」与「类型串不在枚举中」共用一句提示、被误诊成客户端枚举缺类型的事。

案例三:跨仓协议改造顺序倒挂,聊天服务全断。 8 月 14 日,聊天服务线格式从 JSON 改 protobuf 二进制。客户端先合入并出包,服务端的双读改动还躺在 6 个未推送的分支里。线上服务端日志每 100 毫秒一条 invalid character '\b'\b0x08,protobuf 第一个字段的首字节,服务端在按 JSON 解二进制帧。同一天为了让客户端编译通过,生成产物 Wire.cs 被手工放进 CI 产物区,CI 同步以 rm -rf 重建该目录,「删除→恢复→再删」循环了两轮。

收口同样三级:红线「协议格式变更只有一个安全顺序,服务端能同时接受新旧格式先合并部署,客户端再切新格式发版」,附排查判据;红线「CI 产物区禁止手工放文件,编译红要判产物缺失还是依赖倒挂」,附一条命令 git log --diff-filter=A -- "*<名>.proto" 输出为空即证明服务端从来没有过它;门禁脚本扫描客户端产物区找孤儿 proto 挂进 pre-push;技能「协议同步」补孤儿产物判据与跨仓顺序红线。

为什么「只分析不收口」一定失效

三个原因,都有实证。

第一,分析留在会话里就等于没有。4 月 24 日那次口头复盘,唯一留下的痕迹是后来为它写的复盘。

第二,措辞粒度不够会放过变体。8 月 23 日一次跨仓交付,「给已存在的表改键要写迁移器」这条知识早已写在技能检查清单里,同一个函数里还有两个先例和一段注释,但这次加的是列不是键,清单没拦住。这是同一家族的第三次变体:「表要有键」拦不住「查询键无键」,「改键要迁移」拦不住「加列要迁移」。修法是改措辞为「改键或加列」,并补 DEFAULT 要求。只有落成文字并被下一次复盘回头修订的知识,才有机会越写越准。

第三,没有数字的收口靠自觉。8 月 17 日一次长跑清理,阶段声明「DTO 已建好」字面属实,但 9 个调用方一个没接,能暴露纯粹因为门禁报了「还剩 21 处」。于是又多了一条红线:收口类任务的判据是旧路径调用方计数归零,不是新东西已建好。

数据

  • 客户端仓复盘 75 个文件、10 个问题域;服务端仓约 137 篇。
  • 案例一潜伏 21 天,收口计数 12 → 0,真实玩家账号端到端验证通过。
  • 案例二连买 4 次、金币到 2400 万仍进不了场。
  • 案例三每 100 毫秒重连一次,产物区删恢复循环 2 轮。
  • 同一知识被变体绕过 3 次后才修到足够粒度。

教训

  • 复盘的完成判据是产出物存在,不是分析写得好。 红线进规范文件、门禁进 pre-push 或 CI、技能进 skills 目录,三者至少落一个。
  • 能被程序判定的教训优先做门禁。 门禁不依赖任何人记得,且会给出「还剩几处」的数字;红线依赖被读到。
  • 改进建议三列缺一不可:谁、做什么、怎么验证。 「加强审查」不是动作,「在 X 增加断言 Y、跑 Z 命令看到 0」才是。
  • 知识需要被下一次事故修订。 措辞粒度只能在变体出现时校准,前提是它先被写下来。
  • 收口要有会数数的东西。 「建好了」不等于「没人走旧路了」,中间隔着全部调用方。