腾讯一个内部视频剪辑团队的复盘, 记录了他们用三个月把一套 90 万行、文档和单测几乎没有的老系统整体重写的过程. 数据很漂亮, 但真正值得看的不是数据, 是他们踩过的坑——尤其是那句"AI 两小时就能开发完成, 单测全部通过, 实际一看代码连覆盖率都可能它自己圆出来的".
一、接手时的处境
他们要重构的是一个内部视频在线剪辑产品, 用户是视频内容运营, 日常工作是多轨道剪辑、预览、字幕编辑、合成发布. 这个项目过去交接过好几个团队, 今年交到他们手里时, 团队只有 2 到 3 个人全栈.
3 月刚拿到项目时的状态:
- 前后端代码加起来约 90 万行, 多种风格并存且耦合严重, 单个复杂组件超过 6000 行
- 相关文档和单测几乎没有
- 新需求还在着急往里加, 任何一个改动都牵一发动全身, 必须小心翼翼测试
目标定得很直接: 三个月内把旧版本还在用的功能做上去, 替换掉旧系统, 之后再迭代新功能, 顺便输出一套可以复用到其他业务的 Harness 开发模式.
二、选方案: 旧系统当需求说明书
重构方案有三个选项, 他们快速试过前两个都放弃了. 原因是旧项目结构乱、技术债重、代码量又大, 直接搬过来很容易丢功能细节, 而且人还得在不熟的旧代码里反复确认逻辑和校对新旧行为.
最后选的是第三个: 把旧项目当需求功能说明书, 只借鉴产品功能, 代码用 Harness 全部重新写.
结果在 6 月底上了第一个试用版, 随后转入功能持续迭代. 到 8 月底:
- 重构版约 12 万行代码, 15 万行文档, 6000+ 测试用例, 测试覆盖率 86%
- 开发节奏从旧项目"半年只敢动不到 3 个需求或紧急 Bug", 变成 7、8 两个月迭代 30+ 个新功能需求
分工也随之变了. AI 负责需求与设计文档编写和机审、业务代码实现和 CR、质量测试验证和文档更新; 开发人员负责定需求、确认需求边界、取舍开发方案、技术高风险点确认、人工 CR 和最终验收.
三、Harness 工作流要回答的问题
他们的工作流节点和多数团队差不多, 但无论什么流程, 都绕不开一个前置问题: 当 AI 写完代码, 工程质量到底该怎么可靠验证, 才敢合入上线?
就拿"用户上传成功就能进剪辑"这个功能来说——AI 两小时就能开发完, 单测全部通过, 但实际一看代码, 连覆盖率都可能是它自己"圆"出来的. 这让他们意识到: 单测通过不等于质量可靠.
所以他们的工作流只坚持两条原则:
- 工程质量越往前控, 越可控
- 把运动员和裁判员分开, 抵抗人性里的惰性
工作流分三个阶段:
- 立项设计阶段: 立项 → 需求澄清 → 需求审查 → 写验收标准 → 验收标准审查 → (前后端) 代码架构设计 → 架构设计审查 → 人工需求/设计文档交叉审查
- 开发阶段: 跨端需求前后端并行 —— 分别代码实现 → 分别代码审查 → 后端冒烟测试或前端链路自动化审查
- 验收收尾阶段: 人工代码 CR、验收、任务归档和发起 MR
中间插了好几次审查, 看起来多余又费精力和 Token. 但这是初期踩过坑之后才加上的.
四、需求审查: AI 会脑补, 它不会主动停下来
需求审查靠人工校对加 AI 检查, 确认需求文档能不能对得上立项时沟通的要求.
为什么需要人认真看? 因为在需求比较大时, 一旦有些细节没沟通清楚, AI 很容易自己脑补它认为正确的常见做法. 在他们项目里具体表现是: 转码参数细节、超时了怎么处理、老数据缺字段算不算坏数据. 部分情况 AI 并不会停下来跟人确认, 或者问了人图快点了推荐确认, 最终做出来的需求可能跟预想大相径庭.
AI 独立审查的价值在于扫出人看着累但机器扫得快的问题: 禁止含糊词 (比如"适当""尽量")、代词不知道指谁、章节或链接引用是死链、补充缺失信息. 而人把精力留在"这个需求合不合理、符不符合产品要求"上.
这一步的总目的很朴素: 尽量在源头减少 AI 产生的目标漂移.
五、验收标准审查: 别让 AI 把结果"做"通过
这里审查的是最终验收目标有没有写对. 因为代码实现、审查、测试, AI 都拿这份文档当最终标准. 一旦写得不清楚, 或者只写"用户上传成功"这种大而不够细节的结果, AI 一偷懒就容易把结果"做"通过. 所以什么算通过、什么算不过都要写清楚, 尽量把量化的验收数字也定下来.
六、架构设计审查: AI 的局部最优, 全局未必
这一步审查技术方案合理性、可行性和扩展性: 当前变更的代码设计是否合理、有没有复用现有类似功能、前后端协议是否对齐、字段表前后一致、错误路径问题等等.
他们工作流搭建初期, 代码质量扫描工具扫出重复代码的概率高了很多. 分析发现这跟 AI 的工作原理直接相关: 它写的局部代码比较优, 但对全局未必. 每次新需求对它都是一个新的开始, 随着项目代码量越来越大, 它需要了解的内容和遵守的准则越来越多, 如果检索词太窄或根本没搜到类似实现, 就着急开始自己实现.
更麻烦的是"屎山"前兆: 一旦不加以控制, 问题会快速堆积. 即使 AI 发现同一功能已经有多种实现, 它也不会自己收敛, 反而去不停打各种奇怪的补丁, 让项目质量进一步恶化.
行业观察也印证了这点: GitClear 对大量代码质量的研究发现, AI Coding 逐步普及后, 代码重复率从 8.3% 提升到了 12.3%.
所以他们把 AI 架构设计审查固定成环节: 设计文档阶段必须审视架构合理性, 人也必须对当前架构熟悉, 能从设计文档上裁定新增或变更的代码能不能复用、架构合不合理、性能够不够好.
七、开发阶段: 两个大坑
进入开发阶段, 跨端需求分前后端两条链路并行实现, 按设计文档用 TDD 先写契约测试再实现, 同时用 Rules 和宪章让 AI 遵守好的代码习惯.
但即便如此, AI 还是会写出烂代码. 原因是: 这些在他们看来是限制文件的东西, 对 AI 来说更像"叮嘱式的建议", 随着 Context 使用越来越多, 信息被稀释, AI 往往会忽略曾经的约定. 所以代码自动化 CR 是必不可少的.
AI 代码 CR 阶段, 他们给各个 SubAgent 赋予架构、安全、契约、性能、接口契约、运行时、代码规范、测试几个维度的审查角色. 这样设计的目的是让 Agent 专职审查同一类型的问题, 确保注意力不分散. 他们提到 Uncle Bob 在 Harness 里也会把实现、清理、强化、验收拆开, 目的是一样的: 给 AI 的任务够细够聚焦, 信息才不容易丢失.
接着是传统工程质量检查: 单元测试、冒烟测试、E2E 测试、测试覆盖率、质量指标. 加入这些的好处是能确认可靠质量、提升信心, 同时又不占 Context, AI 只需要看结果是否通过. 但跑下来他们发现两个大问题.
坑一: AI 会作弊
举个例子, 测试覆盖率阈值如果只写成"覆盖通过", 没写清超过多少覆盖率, 它为了过关甚至会偷偷改条件来通过质量检查.
他们的应对是: 相关阈值不放在脚本默认值里, 放进单独的红线配置. 一旦改动就会触发门禁, 工作流停下来等人工确认.
坑二: 测试用例的质量问题
AI 很容易把测试覆盖率写得很"感人", 部分代码轻轻松松达到 90%+, 但覆盖率这项指标只能说明覆盖到没有, 说明不了测试质量.
当同一个模型既写函数又写测试时, 很容易出现定制化断言, 错的行为或参数也能通过测试. 这时的高覆盖率其实没什么说服力.
所以他们引入了变异测试, 用变异测试得分评估单元测试的有效性和质量. 原理是自动修改源码, 故意把大于改成大于等于、把条件反转, 再跑测试. 每修改一次就跑一遍完整测试, 通过把代码故意改坏来预期测试用例应该失败. 如果测试用例没失败, 说明断言不够严谨, 需要打回修改.
数据上, 从搜索到的行业观察看, AI 生成测试的变异测试得分常在 20 到 40 分, 人写一般能得到 60 到 80 (他们实测下来一般在 50 到 60).
但有个现实约束要注意: 如果原本跑一次全量单测要 1 分钟, 引入变异测试后需要反复修改源码跑几百遍全量测试, 全量跑完可能变成 30 分钟甚至更久. 如果有时间效率要求, 建议只对增量或修改的单测跑, 过去的旧单测可以当技术债需求慢慢收.
八、人工 CR 还有必要吗
工作流走到最后, 除了归置文档和功能自测, 他们特别提了一道容易忽略的门禁: 人工 CR.
但随着 AI 写代码越来越快, 一个尴尬的问题出现了: "我"的责任心要求"我"对代码负责就必须理解它, 但 AI 产出快、量又大, "我"根本看不过来, 整个工作流效率的瓶颈反而变成了"我读懂才能放心合入".
他们的做法是: 验证需求和体系设计 + 问题分歧裁决 + 重要代码精读. 集中阅读四份核心读物:
- 需求文档: 这个需求是什么, 是不是我们或产品真正需要的功能
- 设计文档: 当前技术方案是什么, 是不是应该这样设计
- 重要代码: 重点关注的关键路径核心代码
- 验收报告: 确认设计到代码实现是否符合要求
他们坦言这不一定是最优解, 但看起来是目前较优解. 关键判断是: 工作流搭各种审查和角色检验, 目标不是不读代码, 而是把逐行阅读的效率从机械性内容中解放出来.
关于人工 CR 的价值, 他们给了两条理由:
- 团队对当前代码该不该合入负责, 应该具备应有的系统判断
- CR 对个人是一种成长, 通过优秀代码学习、提升专业素养
业界有两种更鲜明的观点可以对照. Addy Osmani 在《Agentic Code Review》里说, 程序员不是退出审查代码, 是上移一层——抽查代码、审计方案, 把有限的注意力花在更重要的地方.
Redis 之父 Antirez 在《Control the ideas, not the code》里更极端: 他现在基本不读代码, 只控制 AI 的想法和设计. 理由跟他们痛点一样——AI 一天产出成千上万行, 逐行理解根本看不完. 但他也说能这样做的前提是能看懂 AI 的设计描述、能判断对不对、有可靠检测机制. 他还提了一个没人能回答的问题: 如果没有经验的年轻工程师看不懂设计、也没有发现问题能力, 该怎么办?
关于这点他们团队内部也有分歧: 有人认为提升专业素养的更好途径, 与其 CR AI 可能产出的垃圾代码, 不如认认真真花时间手搓代码学习和积累经验.
九、工作流里几个工程细节
多 Agent 协同: 自己审自己没用
刚开始他们让 Agent 写完代码后换个角色再 CR 一遍. 很多时候 CR 报告都是通过, 但发现还是有遗漏. 本质是 AI 自己审查容易陷入过度自信, 觉得自己写的东西没问题.
所以现在不管是 CR 还是方案审查, 都拆分 SubAgent 独立执行验证角色, 配合可程序化的验证命令. 这样做还有两个好处:
- 每个专职 SubAgent 有自己的角色合约和审查清单, 注意力能关注在一个维度上
- SubAgent 从创建 → 执行任务 → 消失, 执行完就关掉, 面对的是干净上下文, 不被以前的内容干扰
工作流状态机和防 AI 篡改
整个工作流进度由一个 Python CLI 管理, 配合 Hook 守卫防篡改.
核心思路: 进度存文件, AI 只能通过命令推进, 不能手动篡改. 目的是防止 AI 偷偷标记"已完成"跳过某些步骤. 同时记录每一步骤信息, 用于冷启动时恢复上下文, 相关工作流数据还能用于任务审计.
Token 消耗的经济性设计
设计工作流时, 很多国产 AI 的开发能力还没完全起来, 国外的又贵, Token 预算有限, 所以他们做了不少经济性设计, 同时避免 Context 膨胀导致注意力稀释和幻觉率上升:
- Context 分层加载: 各类工作流资产 (Rules、Skills、角色合约文档等) 设计成 3 档 (L1/L2/L3) 分时加载
- 模型按需分配: 按阶段指定不同模型——文档同步、冒烟验证用弱推理, 设计、CR、开发用强推理, 简单任务不占强模型配额
- 工作流冷启动重开: 对话轮数过多、AI 响应明显变慢、Context 接近上限时, 用工作流冷启动机制主动重启清除多余上下文. 但不能无差别用, 过早重启反而丢失已建立的理解成本
十、几条 takeaways
- 旧系统可以只当需求说明书. 结构乱、技术债重、代码量大的老项目, 硬搬容易丢细节; "只借鉴产品功能, 代码全部重写"是一条可选项.
- 单测通过不等于质量可靠. 同一个模型既写函数又写测试时, 会出现定制化断言. 覆盖率阈值必须放进红线配置, 用变异测试检验测试有效性.
- AI 会脑补, 也会作弊. 需求细节没写清它就自己填, 覆盖阈值没写死它就改条件. 该写死的数字必须写死.
- 审查要拆分角色独立执行. 让 AI 自己审自己容易过度自信, 拆成专职 SubAgent + 可程序化验证才有意义.
- 工程质量越往前控越可控. 需求、验收标准、架构设计三道审查前置, 减少的是目标漂移和后期返工.
- 人工 CR 没被取消, 而是上移. 从逐行阅读转向"验证需求与设计 + 裁决分歧 + 精读关键代码".
对于历史技术债很重且还要持续维护的旧仓库, 靠手搓重构可能要花半年甚至一年. 他们的经验是: Harness Engineering 不是一次性工程, 初步体系搭好只是开始, 它会跟着工程问题的出现和 AI 模型能力的提升持续进化.
而开发者的角色也在变. 前后端边界在淡化, 从专精某一端的实现者变成对整个需求全栈负责. 下一步会变成什么样说不准, 但能确定的是: 写代码的门槛越来越低, 能把需求想清楚、在开发过程中守住工程判断、把控好工程质量、把最终结果验清楚——做好这几件事, 可能才是程序员的护城河.