Matt Pocock 的 AI 辅助编程完整工作流

AI CodingLLMTDD软件工程

Matt Pocock 将 AI 辅助编程(AI Coding)的完整工作流划分为两个核心阶段:由人类主导的“白班”(Day Shift),负责规划与对齐;以及由 AI 独立运行的“夜班”(Night Shift),负责自动实现与迭代。完成自动化实现后,工作流还会回到人类手中,由开发者进行手动 QA、注入工程品味,并决定是否合并。

这套工作流的核心理念是:不要把 AI 当作单纯的“需求转代码”编译器,而要通过明确的目标、严格的工程标准和持续的反馈循环,让人类与 AI 始终保持深度对齐。

第一阶段:人类主导的规划与对齐

这一阶段的目标,是由人类明确“目的地”,并与 AI 一起制定抵达目的地的方案。开发者必须紧密参与,不能把尚未想清楚的需求直接交给 AI 实现。

1. 理解 LLM 的局限性

LLM 并不会随着对话变长而一直保持同样的判断力。Matt 用“聪明区”和“愚蠢区”来描述模型在不同上下文长度下的表现:

  • 在对话刚开始、上下文较少时,模型通常处于“聪明区”,注意力集中,推理与决策质量较高。
  • 随着 Token 不断增加,尤其当上下文接近或超过十万 Token 时,注意力会被大量历史信息拉伸,模型更容易进入“愚蠢区”,做出前后不一致或明显不合理的决定。

因此,不应无限延长同一段对话。进入新的工作阶段时,与其不断压缩旧上下文,让模型继承越来越多的“历史沉积物”,不如直接清空上下文,再把当前阶段真正需要的信息重新注入。

这种做法类似电影《记忆碎片》中的记忆重置:每个阶段都从一份清晰、可信的外部记录出发,而不是依赖模型对漫长对话的模糊记忆。

2. 使用“拷问我”技能澄清需求

当开发者收到一个模糊的业务构想时,不要立刻让 AI 写代码,甚至不要急着让它制定实现计划。首先应运行“Grill Me”流程,让 AI 化身为严格的产品经理和架构师,对需求进行连续追问。

这些问题应该覆盖完整业务链路,包括:

  • 用户究竟要解决什么问题?
  • 哪些用户会使用这个功能?
  • 数据从哪里来,又会流向哪里?
  • 历史数据是否需要追溯处理?
  • 边界条件、失败场景和权限规则是什么?
  • 本次迭代明确不处理哪些问题?

例如,需求中提到积分系统时,AI 应继续追问积分是否需要根据历史行为补发、规则变化后是否重新计算、异常数据如何处理等问题。

Grilling 的价值不只是补全需求,而是逼迫人类把隐含假设说出来。只有当开发者和 AI 对核心设计概念形成一致理解,后续的规划和实现才有可靠基础。

3. 编写 PRD,明确目的地

完成需求拷问后,让 AI 根据已经对齐的上下文生成产品需求文档(PRD)。这份文档是整个工作流的“目的地说明”,至少应包含:

  • 产品目标与背景;
  • 用户故事和验收标准;
  • 关键业务规则与边界条件;
  • 已确认的技术实现决策;
  • 测试方向与质量要求;
  • 本次迭代不包含的内容(Out of Scope)。

如果前面的 Grilling 足够深入,开发者通常不需要逐字雕琢 PRD。LLM 很擅长总结已经充分对齐的上下文,真正重要的是确认文档没有遗漏关键决策,也没有擅自扩大需求范围。

4. 将 PRD 拆解为看板任务

接下来,将 PRD 拆成一组可以放入看板的独立任务,并明确任务之间的阻断与依赖关系。最终得到的不是简单的线性待办列表,而是一张任务有向无环图(DAG)。

拆解时最重要的原则是采用垂直切片(Vertical Slices),也就是“曳光弹(Tracer Bullets)”策略。

AI 很容易按照技术层次进行水平拆分:先完成所有数据库工作,再实现全部 API,最后才开始写前端。这种方式会把真正的集成反馈推迟到最后。一旦早期设计有误,所有层次都可能需要返工。

垂直切片要求每个任务都尽可能贯穿完整链路。第一个任务就应该连接数据库、服务层和用户可见的结果,即使它只实现了一个非常小的功能。这样,团队和 AI 能尽早验证架构、数据流与集成方式是否正确。

一个好的任务应当具备以下特征:

  • 范围足够小,能由单个 Agent 独立完成;
  • 交付一个可验证的端到端结果;
  • 明确依赖哪些前置任务;
  • 包含清晰的验收条件;
  • 能在独立分支和隔离环境中实现与测试。

第二阶段:AI 自动实现的夜班

当 PRD 和任务 DAG 准备完成后,人类可以暂时离开键盘,把实现工作交给自动化 Agent 循环。这一阶段也被称为 AFK(Away From Keyboard)工作流。

5. 运行自动化 Ralph 循环

自动化脚本或 Sand Castle 一类工具会把任务 backlog、必要的代码上下文和工程约束注入隔离的 Docker 沙箱。

Agent 根据优先级和依赖关系认领一个当前可执行的 AFK 任务,为它创建独立分支,然后开始自主实现。隔离环境可以避免多个 Agent 互相污染工作区,也让失败任务更容易重试和回收。

整个 Ralph 循环大致如下:

  1. 从 backlog 中选择一个没有被阻断的任务;
  2. 创建独立分支和隔离沙箱;
  3. 读取任务说明、代码上下文与团队规范;
  4. 编写测试和业务代码;
  5. 根据测试、类型检查和编译结果持续修复;
  6. 全部检查通过后提交代码;
  7. 将任务移交给独立审查流程。

6. 建立 TDD 反馈循环

高质量的自动化反馈,是 AI 编程质量的上限。必须为 Agent 提供可靠的单元测试、集成测试、类型检查、静态分析和编译检查,让它能根据明确结果自行迭代。

实现过程应遵循红—绿—重构(Red-Green-Refactor):

  1. **Red:**先编写一个能够表达预期行为、并且当前必然失败的测试;
  2. **Green:**编写最小业务实现,让测试通过;
  3. **Refactor:**在测试保护下改善结构,同时保持所有检查为绿色。

强制先看到测试失败非常重要。它可以证明测试确实覆盖了尚未实现的行为,降低 AI 在已有代码上补写“永远通过”的伪测试的风险。

如果出现类型错误、测试失败或编译问题,Agent 会在沙箱中读取反馈并继续修复,直到所有检查通过,再自动提交 Commit。这使实现过程形成了一个可重复、可观测的闭环,而不是一次性的代码生成。

7. 使用全新上下文进行自动化审查

代码完成后,不要让负责实现的 Agent 顺手审查自己的工作。此时应清空实现阶段的上下文,启用一个新的、处于“聪明区”的 LLM 进行独立审查。条件允许时,还可以使用不同模型交叉审查,例如由一个更强的模型审查另一个模型生成的代码。

审查 Agent 应获得:

  • 当前任务及验收标准;
  • 对应的代码变更或 Commit;
  • 团队编码规范;
  • 架构约束与测试要求。

全新的上下文能减少实现过程中的路径依赖和自我辩护倾向。审查 Agent 应重点检查遗漏的边界条件、错误处理、数据一致性、安全风险、测试有效性,以及代码是否破坏已有架构。

第三阶段:重回人类视野

自动化实现和审查结束后,工作并没有完成。代码需要回到人类开发者手中,接受手动 QA、工程品味判断和最终合并决策。

8. 人类手动 QA,并注入工程品味

即使所有测试都已通过,人类仍然必须亲自启动应用并进行手动 QA。自动化测试只能验证被明确表达出来的预期,无法替代开发者对整体体验、交互细节、信息层级和业务合理性的判断。

如果把规划、实现和 QA 全部交给 AI,工程很容易产出功能上“能跑”、但缺乏一致性和判断力的工业化垃圾。人类 QA 的真正作用,是向产品和代码中注入工程品味(Taste)。

开发者需要关注:

  • 功能是否真正解决了原始问题;
  • 操作流程是否自然,异常状态是否容易理解;
  • 前端交互与视觉反馈是否符合产品整体风格;
  • 实现是否引入了不必要的复杂度;
  • 哪些地方虽然满足验收标准,但仍不够好。

如果 QA 发现问题,不必在当前上下文中临时指挥 AI 修补。更稳妥的做法是把问题写成新的任务,补充验收条件和阻断关系,再送回自动化实现循环。由此形成“规划—实现—审查—QA—再规划”的持续迭代。

9. 并行开发与最终合并

当任务被拆成带依赖关系的 DAG 后,多个没有相互阻断的垂直切片可以并行执行。团队可以同时启动多个 Docker 沙箱,让不同 Agent 各自在独立分支中开发。

并行化的前提不是简单地增加 Agent 数量,而是任务边界足够清晰、共享状态足够少、每个切片都能独立验证。否则,并行工作只会把实现成本转化为更高的冲突处理成本。

各分支完成后,可以由专门的合并 Agent 负责:

  1. 按依赖顺序合并分支;
  2. 处理代码冲突;
  3. 对齐不同切片之间的接口和测试;
  4. 运行完整测试、类型检查与构建;
  5. 整理为最终 Pull Request,交由团队评审。

合并 Agent 负责机械性的整合与反馈循环,人类团队仍然负责最终的架构、产品和质量判断。

如何让代码库对 AI 更友好

除了工作流本身,代码库的模块设计也会直接影响 AI 的产出质量。Matt 借用了《软件设计哲学》中“深模块”和“浅模块”的概念来解释这个问题。

避免大量浅模块

浅模块暴露了复杂接口,却只封装很少的能力。代码库中如果存在大量碎片化的小文件和薄封装,AI 就必须跨越更多文件追踪依赖关系,消耗更多上下文,也更容易在局部修改时遗漏隐含影响。

浅模块还会制造大量不稳定的测试边界。为了测试一个简单行为,Agent 可能需要 Mock 多层依赖,最终得到脆弱且难以理解的测试。

推崇深模块

深模块通过简单、稳定的接口隐藏内部复杂性。调用者只需要理解少量概念,模块内部则可以包含完整的业务规则、数据处理和错误恢复逻辑。

这种结构尤其适合人类与 AI 协作:

  • 人类负责设计模块边界、接口语义和关键不变量;
  • AI 根据测试与约束实现“灰色盒子”内部的具体逻辑;
  • 调用方只依赖稳定接口,不需要理解每个实现细节;
  • 测试可以围绕明确边界验证行为,而不是大量 Mock 内部结构。

这并不意味着人类可以放弃架构设计。恰恰相反,人类需要更主动地掌控模块接口和系统边界,把适合自动化的内部实现交给 AI。这样既能提高迭代速度,也能避免开发者在快速变化的代码库中失去全局理解。

总结

这套工作流并不是追求“让 AI 写更多代码”,而是重新分配人类与 AI 的职责:

  • 人类负责提出问题、澄清需求、设计边界、定义标准并判断质量;
  • AI 负责在清晰约束下实现、测试、修复、审查和整合;
  • 自动化反馈循环连接两者,使每一步都有可验证的结果;
  • 通过主动重置上下文,让不同阶段的 Agent 尽量保持在最佳判断状态。

真正可靠的 AI Coding,不是一次提示词之后等待完整产品出现,而是一套由需求对齐、垂直切片、TDD、独立审查、人工 QA 和任务迭代组成的工程系统。AI 提供速度,人类提供方向、边界与品味。只有两者同时存在,自动化开发才可能持续产出值得合并的代码。