ARTICLE / ai
多智能体SDD实战:规格驱动开发的质量闭环与诚实终审
当你在一天之内让几十个 AI 子代理产出一百多个提交,质量怎么守?这不是假想场景——在最近一个内容社区产品的商业化攻坚里,我们用多智能体 SDD(Spec-Driven Development,规格驱动开发)流程单日跑出了 35 个提交、88.6MB 的协作会话,随后一天的 UI 打磨波次又追加了 19 个提交,全程没有一个"看起来对但实际是错"的结论混进主干。这篇文章把这套质量闭环拆开讲:规格怎么先行、复审怎么独立、终审怎么诚实、测试抖动怎么定位。每个机制都来自真实工程日志,不是方法论推演。
一、问题:多智能体编程的规模化质量困境
单个 AI 编程代理的质量问题已经有很多讨论:幻觉、越界改动、测试造假。但当编排从"一个代理"升级到"一个军团"——35 个子代理并行攻坚、每个代理只看局部上下文——质量问题会发生质变:
第一,上下文碎片化。每个子代理拿到的是 task brief(任务简报),不是全局意图。简报写得含糊,代理就会用概率最高的方案覆盖你的真实需求,而且每个代理猜的方向可能不一样。
第二,证据可信度分层。代理汇报"测试全过"时,你无法直接判断这是真全过、选择性跑过、还是把失败断言删了之后的过。大规模并行时人工逐条核对不可行。
第三,结论措辞越界。多轮复审中最常见的诚实性风险,是把"本地静态合同通过"误写成"真实平台能力通过"。一字之差,验收结论就错了。
SDD 流程的价值就在于:它不试图让代理更聪明,而是让每个环节都产出可核验的证据,让质量靠结构而不是靠运气。
二、SDD 是什么:与 TDD、Vibe Coding 的差异
一句话定义:先写规格、按规格派活、按规格验收。规格(spec)在动手前就提交评审并冻结,之后每个子代理的任务简报都从规格拆解而来,每个提交的验收标准也回指规格。
三种模式的对比:
| 维度 | Vibe Coding | TDD | SDD 多智能体 |
|---|---|---|---|
| 意图载体 | 对话中的自然语言 | 测试用例 | 冻结的规格文档 + task brief |
| 质量锚点 | 人的直觉 | 断言通过 | 规格↔实现↔复审三方对齐 |
| 并行性 | 差(单人对话) | 中 | 高(task 粒度派发) |
| 典型失败 | 边界条件埋雷 | 测试本身写错 | 规格含糊传导到全线 |
关键差异在最后一行:TDD 的失败模式是测试写错,SDD 的失败模式是规格含糊。所以 SDD 的第一道工序不是写代码,是把规格写到可以直接拆任务的程度。
三、质量闭环的六个机制
以下是这套流程里真正起作用的六个机制,全部经过多日、多波次的实战检验。
3.1 规格先行,task brief 预写
第一个提交永远是规格文档:先提交"做什么、不做什么、验收标准",评审通过后再拆出全部 task brief(一次预写 10 个),之后才允许实现提交进场。这样每个子代理开工前,任务边界、验收口径、禁止事项都已经白纸黑字。规格含糊的成本在第一天就支付,而不是在第十九个提交返工时支付。
3.2 基线锁定:截图基线与冻结哈希
UI 波次开始前,先用一个专门提交捕获核心 UI 的基线状态(8 张最终定稿的截图)。之后每个 UI 改动都有 before/after 客观对照——避免"我觉得变好了"这种不可审计的主观判断。基线锁定的投入产出比极高:后续 8 个 UI 提交全部自动获得了对照证据。
后端改动用另一招:冻结哈希。API 侧改动不应改变移动端测试基线;如果移动端冻结哈希变了,说明改动越界,直接打回。一个哈希值就是一个廉价的越界探测器。
3.3 报告与复审分离
实现者提交 task-N-report(实现报告),独立复审者只看 diff 和证据、不重跑测试、不改代码,产出 PASS / ADDRESSED / NEEDS_CONTEXT / FAIL 四档判定。这条分离纪律的价值在于:复审者的信息源被限制在"证据"而非"实现者的自我描述",杜绝了"自己给自己签字"。
3.4 失败证据不可覆盖
修复波次只追加新证据,旧的失败截图、失败日志原样保留——“不会用新的结果覆盖历史”。没有这条纪律,三天后你将无法回答"当初到底修了什么、原来什么样",复盘链路彻底断裂。
3.5 诚实分级终审
终审输出标准化的分级计数:Critical / Important / Minor 三档,结论只有两种合法形态——“With fixes”(带已知问题通过)或"NOT APPROVED"。实测最典型的一次终审:0 Critical / 1 Important / 3 Minor,其中 Important 是"私密摘要压缩未实现(只加了折叠箭头)",Minor 里有"误导性 CTA"。同时终审必须显式关闭已解决的疑虑、显式声明未验证项(商业发布、原生交互、生产验收)。
诚实结论比全绿值钱。一个"With fixes + 1 Important"的真实终审,比一个虚假的 DONE 有价值得多——因为前者还能指导下一步,后者会把问题带进生产。
3.6 授权边界即提交边界
子代理的修复提交严格只含授权文件清单,提交前用 diff 统计核对实际改动文件数与授权数一致,未经过限定范围复审不合并。实战里有个反面教材式的正面案例:一个子代理尝试清理临时夹具目录,被命令执行器拒绝(清理类命令在执行前被沙箱策略拦截),报告里如实记录"拒绝发生在执行前,无任何文件被创建或触碰"。这说明两件事:沙箱策略在真实工作流里确实生效;子代理遇到拒绝如实上报而不是绕过,本身就是闭环的一部分。
四、实战数据:两天的波次复盘
以下数据来自项目工程日志的当日复盘,均为实际运行记录。
商业化攻坚日(35 提交):35 个子代理执行 7 个规格化 task + 修复波次 + 多轮独立复审,本地合并门禁最终 PASS,但商业发布判定为 NOT APPROVED——因为外部验收和系统级验收没做。注意这两个判定的区别:前者说"代码可以进主干",后者说"产品可以见用户"。混用这两个判定是 AI 编程验收最常见的事故源。
UI 打磨日(19 提交):从基线截图锁定开始,移动端 8 个波次(每波 = 实现 + 验收),API 域 3 个波次,最终验证矩阵为移动端 1400/1400 通过、headless 14/14、原生 UI 14/14、API 黑盒 1/1;API 侧 1135 通过 / 4 跳过;lint、构建、数据库迁移检查全过。终审给出 0 Critical / 1 Important / 3 Minor 的 With-fixes 结论。
还有一个容易漏看的信号:主仓日志零提交不等于无活动。多智能体流程的全部产出往往落在 worktree 分支上,主仓与分支之间的 gap(实测 51 个提交)本身就是"等待终审"的排队信号。只盯主仓 git log 的日报会把最活跃的一天误报成"无进展"。
五、测试抖动的 A/B 诊断法
多智能体高吞吐带来的新问题:完整 API 测试套件出现间歇性失败——同一份代码,A 次运行挂 2 个测试,B 次运行全过。失败点集中在 auth 相关套件,疑似测试环境共享状态污染,但直接读代码定位不了因果。
这时候用 A/B 双臂对照诊断,固定代码、只变运行范围与顺序:
- 臂 A:跑完整套件(复现失败),记录失败的套件和运行顺序。
- 臂 B1:只跑失败的 13 个测试——13/13 全过。
- 臂 B2:按 A 的顺序重放前 21 个套件——434/434 全过,而原始 A 运行在同一位置有 2 个失败。
同时用三件套佐证排除环境因素:工作区 tracked diff 为零(代码完全相同)、无残留 stash、无残留测试进程。三臂对照支持一个假设:某个套件的 loopback listener 没有正确关闭,污染了后续套件——即 listener 生命周期假设。
这里的纪律比结论更重要:A/B 对照只能支持假设,不能证明因果。报告措辞必须是"支持 X 假设",最终以限定范围的修复(只保留三个套件的显式 listener)加完整门禁重跑来收口。测试抖动的排查优先级可以固化成一个序列:残留进程、共享 listener/socket、时间敏感断言、真并发缺陷——从最廉价的排除项开始。
六、生产级数据可靠性:坏记录持久隔离
内容审核后台的清理管线暴露了另一类问题:一条损坏记录会让清理任务反复失败,低频任务被坏记录长期占住(饥饿)。
修复方案是"持久隔离 + 退避 + 公平排序"三件组合拳。坏记录不删不改,写入现有的错误与重试时间字段做隔离——不新增迁移、不扩 schema,后续有效记录继续清理,原始可疑对象保持原样。这条铁律值得单独记:可疑对象可能是证据,永远不删不改,隔离用现有字段实现,避免 schema 迁移耦合进一次数据修复。
公平排序是容易被忽略的暗坑:当扫描间隔长于退避时间时,简单的重试队列会让低频任务饿死——退避必须配合公平排序才完整。修复后的三层门禁:API 1449 通过 / 4 外部跳过、Flutter 1519 通过 / 1 跳过、管理台 26 通过。其中 4 项外部依赖集成测试按原配置跳过是已知基线而不是回归——报告必须区分"外部跳过"和"失败",否则门禁数字会自己吓自己。
七、常见误区
误区一:把复审当成重跑测试。 独立复审者的职责是审证据链(diff 是否越界、断言是否被削弱、结论措辞是否越界),不是替实现者跑测试。复审者一旦开始改代码,“独立"就没了。
误区二:用全绿数字当结论。 1400/1400 通过只说明本地门禁过了,不说明商业发布没问题。本地合并门禁和商业发布门禁是两道门,结论措辞必须分开。
误区三:新证据覆盖旧失败。 修复后把失败截图删了换成通过的截图,等于销毁修复理由。历史失败记录原样保留,新证据另开章节。
误区四:并发问题用大重构回应。 实测教训:共享缓存引入并发时序问题后,正确切口是只修读取快路径,不动已获准的写入串行化设计——大范围重构会引入新变量,让回归归因变成不可能任务。修复前先补一个能独立复现并发问题的失败测试(RED),是唯一安全网。
误区五:只看主仓活动。 多智能体的产出在 worktree 分支排队等终审,主仓安静恰恰可能意味着大战在途。
八、总结
这套流程的核心不是任何一个工具,而是一条证据链:规格冻结 → 基线锁定 → 报告复审分离 → 失败证据保留 → 分级诚实终审 → 授权边界收口。每个环节都产出可核验的中间产物,让"质量"从形容词变成名词。
三个最值得直接抄走的实践:终审结论只允许 With-fixes 或 NOT APPROVED 两种形态,逼所有灰色地带显式化;主仓与分支的 gap 当成"待终审队列"监控,别让日报漏掉最大的工作量;测试抖动用 A/B 三臂对照定位,措辞永远停留在"支持假设"直到完整门禁重跑收口。
多智能体编程的规模化不在代理数量,而在证据密度——一个能追溯每个结论来源的 19 提交波次,比一百个无法复盘的"全绿"提交更接近生产级。