AI 编码代理 SDD、Plan、Goal 与 ExecPlan:基于 Loop 的可控交付指南

13 阅读36分钟

摘要

AI 编码代理的主要风险不是单行代码写错,而是在目标、规格和边界尚未确认时,以远高于人工评审速度的节奏持续扩大改动。本文建立一套从 SDD(规格驱动开发)Plan、Goal、ExecPlan 的工作框架,并用 Loop 把探索、规划、执行、验证和人工评审串成受控闭环。

SDD 规定“应该构建什么、什么才算正确”;Plan 负责只读调查和下一小步的方案取舍;Goal 负责在批准范围内完成一个可验证的交付;ExecPlan 负责管理多个小时、多个里程碑和多个 Goal 的长任务;Loop 则规定每轮何时验证、何时停止、是否继续。ExecPlan 是 SDD 与 Loop 在多阶段 Agent 工作中的一种应用,不是二者的替代品。

本文给出四种工作选择:问题清楚时直接修改并验证;影响面不清时使用 Plan-only;一个 PR 可完成时使用受控 Goal;跨多个里程碑且结果可机器验证、容易回滚时才使用 ExecPlan。核心治理原则是:路线图不直接授权执行,发现不等于授权,超预算或出现架构分歧必须暂停,每个批次都要有范围、非目标、验证证据、人工检查点和自然终点。

最终目标不是让 Agent 自主完成更多代码,而是让每轮交付都能回答:改了什么、为什么这样改、证据是什么、还剩什么风险、谁批准继续。

总框架:SDD 与 Loop

本文把 SDD(Spec-Driven Development,规格驱动开发)Loop(受控反馈循环) 作为理解 Plan、Goal 和 ExecPlan 的上层框架。

SDD:先定义应该构建什么

SDD 的核心不是先写一份很长的需求文档,而是把实现前提变成可检查的规格。规格至少应说明:

  • 目标行为和用户可观察结果;
  • 范围、非目标和兼容约束;
  • 输入、输出、接口和状态变化;
  • 错误处理、安全边界和不可逆操作;
  • 验收标准、测试证据和未解决问题。

对 AI 编码代理而言,SDD 解决的是方向和契约问题:代理不能只根据一句“重构一下”自行推断产品意图,也不能把测试通过当作规格已经满足。Plan、Goal 和 ExecPlan 都应引用或补齐这些规格,但它们本身不是 SDD 的同义词。

Loop:控制如何推进

Loop 解决的是执行过程中的反馈与授权问题:

探索 → 规划 → 人工批准 → 执行 → 验证 → 评审 → 停止或进入下一轮

每轮都要有独立的范围、预算、验证证据和停止点。新发现可以改变下一轮的 Plan,但不能因为 Agent 已经发现了旁支问题,就自动获得继续修改的授权。Loop 的目标是缩短“证据到决策”的反馈周期,而不是让 Agent 连续产生更多未审查代码。

四者的关系

SDD:定义应该构建什么、必须满足什么约束
  ↓
ExecPlan:组织多阶段工作如何按里程碑推进
  ↓
Plan:决定下一小步怎么做,以及为什么这样做
  ↓
Goal:在批准范围内完成这一小步
  ↓
Loop:执行、验证、评审,并决定是否继续

因此,ExecPlan 是 SDD 和 Loop 在多阶段 Agent 工作中的一种应用形态,但不是 SDD 或 Loop 本身:

概念主要回答的问题
SDD应该构建什么,什么才算满足要求?
ExecPlan多个阶段如何按顺序、带证据地完成?
Plan下一小步怎么做,方案取舍是什么?
Goal这一小步的可交付结果和边界是什么?
Loop做完后如何验证、评审并决定是否继续?

如果一份 ExecPlan 只有步骤清单,没有目标规格、验收标准和停止条件,它不是完整的 SDD 实践;如果它没有执行后的验证、评审和人工继续决策,它也没有真正实现 Loop。

本文核心观点

  1. AI 速度不能直接等同于交付速度。 交付速度受评审、验证和决策吞吐约束。
  2. Plan 与 Goal 共同实现受控 Loop:Plan 定义路径与证据,Goal 定义结果与边界,评审决定下一轮。 Roadmap 不应直接变成自治执行 Goal。
  3. 默认采用短工作流,例外采用长自治。 可预定义路径的任务不需要开放式 Agent。
  4. 小批量是 AI 工程的控制面。 它降低错误累积、沉没成本和人工认知负载。
  5. 测试通过不是整体正确。 还要证明范围、兼容性、可评审性和真实运行行为。
  6. 发现不是授权。 代理发现旁支问题后应记录并停止扩张,由人决定是否形成新 Goal。
  7. 大型重构必须拆分。 每个 Goal 都应独立验证、评审和回滚。
  8. Loop 迭代的是认知与交付,不是未审查的代码量。 每轮都应有独立的批准、验证和停止点。

1. 新手快速上手

先用一句话理解

  • SDD:先把目标行为、约束和验收标准写成可检查的规格。
  • Plan:先只读调查,弄清问题和方案,暂不改代码。
  • Goal:在已经批准的范围内,完成一件可验证的小事。

它们合起来形成一个受控 Loop:规格确认 → 发现与规划 → 人工批准 → 有边界地执行 → 验证与评审 → 再决定下一步。新手只要记住:先确认什么才算正确;不确定时再 Plan;方案确认后,用 Goal 执行一个小切片;完成后回到人工评审,而不是让 Agent 自行继续。

先确认规格,再开始 Plan

Plan 不是用来替代需求澄清的。开始只读调查前,至少要写出一版轻量 SDD:

  • 目标行为:用户或调用方最终能观察到什么;
  • 非目标:本次明确不处理什么;
  • 约束:兼容性、安全、性能、权限和不可逆操作边界;
  • 验收:哪些测试、指标或产物可以证明完成。

规格不完整时,Plan 的任务是识别缺口并提出问题,而不是擅自补齐产品决策。规格确认后,Plan 才能围绕真实目标调查调用链、候选方案和最小切片。

Plan:先弄清楚,再决定是否动手

当你不确定问题在哪里、会影响哪些文件,或者需要在多个方案中做选择时,先进入 Plan 模式。此时要求 Codex 阅读代码、解释现状、给出方案,但不要修改文件。

一个简单的 Plan 请求可以这样写:

只读分析这个问题,不修改文件。

请说明:
1. 问题现在出现在哪个流程;
2. 可能影响哪些模块或文件;
3. 推荐怎样最小化修改;
4. 需要哪些测试来验证。

输出方案后停止,等待我确认。

Plan 的作用是帮助你做决定,不代表代码已经完成。发现前提不对时,继续讨论或重新规划即可。

Goal:一次只完成一件小事

当方案已经确认,且你能明确说明“完成后应该看到什么结果”时,再创建 Goal。一个好的 Goal 至少包含五件事:

  1. 目标:要实现什么可观察结果;
  2. 范围:哪些文件或模块可以改,哪些不能改;
  3. 验证:哪些测试、构建或产物必须通过;
  4. 边界:最多改多少文件、花多长时间,遇到什么情况必须停;
  5. 结束:当前事项完成后停止,不自动开始下一项。

示例:

仅修复视频页面切换策略后不生效的问题。

- 只修改策略选择和视频会话创建相关代码;
- 不改公共接口、视觉行为和其他页面;
- 补充对应测试,并运行定向测试;
- 如果需要修改无关模块或无法确定兼容性,停止并报告;
- 验证通过后停止,等待评审。

不要把“完成整个重构”“顺便优化相关代码”写成 Goal。这类目标太大,既难验证,也会让代理不断扩大工作范围。

一个最简单的使用流程

  1. 先问自己:问题清楚吗? 不清楚,先 Plan。
  2. 阅读 Plan: 只批准其中一个最小、可评审的修改。
  3. 创建 Goal: 写清目标、范围、验证和停止条件。
  4. 检查结果: 看 diff 和测试证据;满意后再考虑下一件事。

执行中发现的新问题,先记录下来。除非不处理就无法完成当前 Goal,否则不要让代理顺手继续修改。

什么时候不必使用 Plan 或 Goal?

  • 只是解释代码、查询状态:直接提问即可。
  • 只有一行配置、根因明确的小修复:可以直接修改并验证。
  • 跨多个模块、需要多次评审的大型重构:拆成多个 Plan 和 Goal,不要用一个 Goal 包办。

先小后大

第一次使用时,选择一个预计 30 分钟内可以完成、测试方式明确的小问题。先建立一次受控闭环,再逐步扩大任务规模。

客户端差异

并非所有 Codex 客户端都有独立的 Goal 按钮。没有该功能时,可以把 Goal 的目标、范围、验证和停止条件直接写进任务提示词或 Issue。治理原则不变。

2. Plan、Goal 与相关载体的职责

AI 可以快速生成代码,但评审、验证和决策仍由人完成。如果代理持续扩大范围,代码产出越快,团队积累的评审压力和返工风险就越大。

因此,SDD、Plan 和 Goal 的治理共同解决一个核心问题:让 AI 在明确规格和授权边界内自主执行,而不是让它自行决定正确性或整个项目接下来要做什么。

从 Loop 的角度看,Plan 和 Goal 不是两个孤立命令,而是同一控制系统的不同阶段:

Loop 阶段Plan/Goal 中的实现人的职责
规格SDD 定义目标行为、约束和验收标准确认需求、风险和非目标
观察Explore 与 Plan 收集调用链、测试和兼容面证据判断问题定义和证据是否充分
选择Plan 给出候选切片、取舍和预算批准一个切片,明确非目标
行动Goal 在已批准范围内修改授权范围、权限和风险上限
验证Goal 运行分层测试并报告实际 diff判断证据是否足以接受交付
学习与继续Review 记录结果、风险与 Follow-ups决定停止、重新 Plan 或开启下一 Goal

因此,Loop 追求的是更快、更可靠地缩短“证据到决策”的反馈周期,而不是让 Agent 连续执行更多步骤。

各类文档分别负责什么?

载体主要作用不应该承载什么
SDD / 规格目标行为、约束、接口和验收标准具体执行进度和临时探索结果
AGENTS.md项目规则、常用命令、仓库导航当前任务进度和临时实现细节
Roadmap / Epic长期方向、阶段和依赖对 Agent 的无限执行授权
Plan调查结果、实施路径、风险和验证方式未经批准的新任务清单
Goal一个可验证结果及其范围、预算和停止条件整个项目路线图或“持续优化”
PR / CL(代码评审单)人工评审、合并和回滚单元多个互不相关的改动主题
ADR / Decision Log关键决策、备选方案和理由机械执行步骤

可以把它们理解成:

Roadmap:最终要去哪里
SDD:什么结果才算正确
Plan:下一小步怎么走
Goal:这一步做到什么程度才算完成
ExecPlan:多个小步如何按里程碑推进
PR:人如何检查和接收这一步

ExecPlan:多小时工作的执行契约

ExecPlan 可以理解为面向复杂任务的可执行计划文档。它不是把更多待办事项堆在一起,而是把目标、现状、方案、里程碑、预算、风险、验证证据和停止条件放到同一份可持续更新的文档中。OpenAI 的 PLANS.md 实践强调:计划应自包含、可维护,记录关键决策和发现,并让每个里程碑都能独立验证和恢复。OpenAI: Using PLANS.md for multi-hour problem solving

ExecPlan 与本指南中的载体关系如下:

载体关系
Roadmap / Epic提供长期方向,不直接授权执行
Plan为一个切片调查问题并提出方案
Goal在批准范围内完成一个可交付结果
ExecPlan当任务跨越多个小时或多个里程碑时,持续管理多个受控 Goal
PR / CL承载每个里程碑的评审、合并和回滚

因此,ExecPlan 不应把多个 Goal 变成一个无限自治任务。正确关系是:

ExecPlan(总执行契约)
  → 里程碑 1:Plan → 批准 → Goal → 验证 → 评审
  → 里程碑 2:Plan → 批准 → Goal → 验证 → 评审
  → 里程碑 3:Plan → 批准 → Goal → 验证 → 评审

ExecPlan 的最小字段

# ExecPlan: <任务名称>

## 目标与非目标
- 目标:<可观察结果>
- 非目标:<明确不处理的内容>

## 当前状态
- 已确认的调用链、文件、测试和外部依赖
- 未确认的前提与待补证据

## 方案与取舍
- 推荐方案及原因
- 放弃的替代方案及原因

## 里程碑
1. <一个可独立验证和回滚的切片>
2. <一个可独立验证和回滚的切片>

## 每个里程碑的执行约束
- In scope / Out of scope
- 文件、时间、diff 和新抽象预算
- 测试、构建和人工检查点
- 完成条件、暂停条件和回滚方式

## 决策日志
- 日期、决策、证据、影响

## 发现与 Follow-ups
- 新发现及其证据
- 不属于当前范围的后续事项,不自动执行

## 最终验收
- 行为结果
- 测试与构建证据
- 实际 diff 和未完成风险

ExecPlan 的执行规则

  1. 先建立计划,再开始修改。 先读取代码、测试和约束;计划未经确认时不执行高风险动作。
  2. 按里程碑推进。 每个里程碑都要有独立 diff、验证结果和回滚路径。
  3. 计划是活文档。 新证据可以更新计划,但不能静默扩大范围;影响方向、接口或预算时必须回到人工批准点。
  4. 发现不是授权。 旁支问题进入 Follow-ups,除非当前目标无法完成,否则不顺手修改。
  5. 完成即停止。 一个里程碑完成后报告结果,等待人工决定是否开始下一个里程碑。
  6. 验证必须可追溯。 记录命令、测试结果、diff、日志或其他证据,不用“看起来没问题”替代验收。

什么时候使用 ExecPlan

只有在以下条件基本满足时,才考虑多小时 ExecPlan:

  • 结果可以由测试、指标或确定性产物验证;
  • 环境隔离,执行不会覆盖未提交工作;
  • 每个里程碑可以独立提交、回滚和恢复;
  • 外部写入、删除、迁移和权限变化有人工门禁;
  • 墙钟时间、最大重试次数、diff 和文件预算明确;
  • 任务不是开放式架构探索或需要频繁产品判断。

遗留系统“全面重构”、视觉品味调整、缺少回归保护的业务迁移,不适合直接交给 ExecPlan。

ExecPlan 提示词示例

先不要修改文件。请为这个多阶段任务生成 ExecPlan。

要求:
- 先调查现状、调用链、测试和兼容面;
- 拆成可独立验证、提交和回滚的里程碑;
- 为每个里程碑写清范围、非目标、文件/时间/diff 预算;
- 写出验证命令、完成条件、暂停条件和回滚方式;
- 单独列出决策日志和不自动执行的 Follow-ups。

输出 ExecPlan 后停止,等待批准。执行期间只推进当前已批准的里程碑,
超预算、发现新架构分歧或需要范围外修改时立即暂停。

Plan 与 ExecPlan 的根本区别

Plan 和 ExecPlan 都发生在修改代码之前,但解决的问题不同:

对比项PlanExecPlan
核心问题下一步应该怎么做?多阶段工作如何持续、可控地做完?
主要产物一份候选方案和一个建议切片一份持续维护的执行契约
时间跨度通常一个短任务或一个 Goal多小时、多个里程碑或多个 Goal
是否执行默认只读,输出后等待批准批准后可按里程碑推进,但每个里程碑仍需验证和评审
关注重点调查、影响面、方案取舍里程碑、预算、状态、决策日志、证据和恢复
结束条件方案清楚,能创建一个受控 Goal所有批准里程碑完成,或明确停止并交接
变化处理发现新事实后重新规划更新活文档,但不得静默扩大范围
失败恢复重新做一次 Plan从最近一个已验证里程碑恢复

可以用一个简单判断来区分:

Plan 决定“做哪一小步以及为什么”;ExecPlan 管理“多小步如何按顺序、带证据地完成”。

Plan 的输出通常应该在这里停下:

只读调查 → 形成方案 → 选择一个切片 → 等待批准

ExecPlan 则把多个受控循环串起来,但不取消每一轮的人工边界:

ExecPlan
  → Plan 里程碑 1 → Goal 1 → 验证 → Review
  → Plan 里程碑 2 → Goal 2 → 验证 → Review
  → Plan 里程碑 3 → Goal 3 → 验证 → Review

因此,ExecPlan 不是“自动批准后续工作的超级 Plan”,也不是把整个 Roadmap 改名为计划文件。它必须保留每个里程碑的批准点、停止点和回滚点。

三种场景的连续选择

从任务开始到交付,可以按下面的路径选择工作方式:

  1. 只读回答:问题清楚,只需要解释代码、查询状态或给出建议,不需要修改。
  2. Plan-only:问题位置、影响面或实现方案不清楚;只读调查,输出方案后停止。
  3. 单次 Goal:方案已确定,范围小,能在一个 PR 或一个审查批次中完成。
  4. 多个 Plan + Goal:跨模块、跨 PR 或需要多轮架构决策,但每一步都能短周期完成。
  5. ExecPlan:工作预计持续多个小时,存在多个依赖里程碑,但每个里程碑都能独立验证、提交、回滚和恢复。

选择逻辑可以压缩为:

是否需要调查?
  否 → 直接修改并验证
  是 → Plan-only
          ↓ 方案是否已经确定?
          否 → 继续 Plan 或请求人工决策
          是 → 一个批次能否完成?
                  是 → Goal
                  否 → 多个 Plan/Goal
                           ↓ 是否跨小时且可机器验证?
                           是 → ExecPlan
                           否 → 保持人工驱动的短批次

什么时候 Plan 足够

以下任务通常只需要 Plan,不需要 ExecPlan:

  • 一个明确 bug 的根因定位;
  • 一个 API 字段或配置项的修改;
  • 单模块内的小型重构;
  • 只需补充一组回归测试的修复;
  • 需要在两种实现方案中做选择,但最终只会执行一个小切片。

Plan 的完成标准是“可以安全地批准下一步”,而不是“把未来所有工作都写完”。如果 Plan 已经能够给出准确文件、明确行为、测试和回滚方式,就应停止继续拆解,创建一个小 Goal。

什么时候需要升级为 ExecPlan

满足以下特征中的多数时,才考虑 ExecPlan:

  • 任务会跨越多个独立 PR 或多个工作阶段;
  • 前一阶段的结果会决定后一阶段的路径;
  • 需要持续记录决策、发现和未决问题;
  • 预计执行时间超过一个普通 Goal 的预算;
  • 每个阶段都有自动化测试、指标或确定性产物;
  • 可以建立隔离工作区和明确的恢复点;
  • 任务不是开放式架构探索,而是路径虽长、验收仍然明确。

不应因为任务“看起来很大”就直接使用 ExecPlan。开放式遗留系统重构、视觉品味判断、频繁变化的产品需求和没有可靠回归测试的迁移,仍应拆成多个由人驱动的 Plan/Goal。

ExecPlan 如何承接 Plan

ExecPlan 的第一版不是凭空写出的,而是由一次只读 Plan 产生:

  1. Plan 调查代码、调用链、测试、兼容面和风险。
  2. 人工从 Plan 中批准第一个里程碑,并确认非目标和预算。
  3. ExecPlan 将后续里程碑、依赖和验收标准记录下来,但不自动授权执行。
  4. 当前 Goal 完成后,写入实际结果、diff、测试证据和新发现。
  5. 人工决定是继续执行 ExecPlan 的下一个里程碑,还是回到 Plan 重新评估。

这保证了 ExecPlan 既有全局上下文,又不会跳过局部批准。尤其当实际代码与初始假设不一致时,正确动作是更新 Plan 或暂停,而不是让 Agent 自己“顺着发现继续做”。

一个完整例子:播放器迁移

只用 Plan 的阶段:

只读审计播放器入口、Native/Exo 两条路径、状态所有权和现有测试。
请判断是否可以定义统一播放器接口,并给出第一个最小切片。
不要修改文件,输出后停止。

Plan 可能得出:先增加契约测试,再让 Native 路径接入接口;暂不迁移 Exo、Fragment 和策略选择。

用 Goal 执行第一个切片:

Goal:定义最小 VideoPlayer 契约并为 Native 路径补充测试。

In scope:接口文件、Native adapter、契约测试。
Out of scope:Exo、Fragment、策略选择、旧入口删除。
预算:最多 5 个生产文件,约 300 行逻辑 diff,执行 60 分钟。
完成:契约测试和 Native 定向测试通过,构建不变。
停止:发现需要修改策略选择或公开接口时暂停。

升级为 ExecPlan 的情况:

当 Native adapter、Exo adapter、会话策略、行为迁移和旧入口删除需要连续多个里程碑时,再创建 ExecPlan。此时 ExecPlan 负责维护顺序、依赖、总体验收和决策日志;每个阶段仍然分别使用 Plan 和 Goal。

把计划写成长文不等于 ExecPlan

以下写法看起来详细,实际上仍然不是 ExecPlan:

  • 只有“待完成事项”,没有每个里程碑的完成证据;
  • 把所有未来工作列出来,却没有预算和人工批准点;
  • 发现新问题后直接追加到当前执行列表;
  • 只有最终验收,没有中间可回滚状态;
  • 写了“持续优化”“完成全部重构”等没有自然终点的目标。

真正的 ExecPlan 必须能够在任意里程碑暂停,并回答:

当前完成了什么?依据是什么?下一步为什么是它?谁批准继续?如果不继续,系统能否安全停在这里?

根据任务选择工作方式

任务情况推荐方式
解释代码、查询状态直接只读回答
根因明确的小修复单次修改并验证
需求不清或影响范围未知Plan-only,输出方案后停止
路径明确、一个 PR 可完成创建有边界的 Goal
跨模块或多周重构Roadmap 拆成多个 Plan/Goal
多小时且可机器验证、易回滚满足准入条件后使用 ExecPlan

默认优先选择短、可预测的工作流。只有成功路径无法预先确定,同时结果又能可靠验证时,才考虑提高 Agent 的自治程度。Anthropic: Building effective agents

3. 失控案例:为什么“大 Goal”会失败

下面的案例来自一次经过脱敏的媒体模块重构。原始目标同时包含代码清理、测试补齐、模块文档、三个功能域重构、双播放器迁移、设备验收和旧代码删除。

它看起来有顺序、有验收,也强调渐进兼容,但本质上仍是一个 Epic:需要多个 PR、多次架构决策和多轮人工验收,不应该直接作为一个 Goal 执行。

错误 Goal 原文:把整个 Epic 装进一个 Goal

下面保留经过模块名脱敏的原始 Goal。它不是推荐模板,而是用于说明“大而完整”为什么不等于“可执行”。

标题: SampleGallery 渐进式可维护性重构目标

原则:
  - 功能完全兼容、渐进替换
  - 保持 XML / ViewBinding,不迁移 Compose
  - 新增 Kotlin + StateFlow 状态层和端口适配层

清理与基线:
  - 盘点不可达代码、重复资源、大块注释、动态资源访问
  - 逐批清理且每批构建验证
  - 补齐媒体过滤、损坏文件、定位、旋转、续播、倍速、USB、
    删除/导出、播放限制、语音和硬键回归

模块契约:
  - 建立根、browser、main、data、assistant、wallpaper 的 AGENTS.md
  - 记录职责、接口、状态所有权、依赖、测试入口和禁止项

Browser:
  - 定义 BrowserUiState / BrowserAction / BrowserEffect
  - 分离会话、导航、全屏/轮播、删除/导出、图片编辑
  - 将会话状态从 GalleryConstant 迁入生命周期状态持有者

Video:
  - 定义统一 VideoPlayer 能力接口
  - 实现 NativeVideoPlayer 与 ExoVideoPlayer
  - 增加开发配置策略,默认 Native,会话内固定,不自动回退
  - 抽出播放状态机和音频焦点、持久化、手势、语音/硬键、
    HVAC、系统属性、设备安全信号等端口或协调器
  - 双策略验收后删除 VideoFragment2 旧入口

Picture:
  - 分离装载/缩放、旋转、退出位置、轮播、运行限制
  - 保持壁纸入口和原有交互兼容

交付顺序:
  - 清理与测试基线
  - 模块契约
  - Browser 状态层
  - Video 双策略
  - Picture
  - 删除旧代码和死资源

全局验收:
  - 生产源码以 1000 行为目标阈值
  - JVM / Robolectric 覆盖各类状态和系统事件
  - 两套播放器执行同一组契约测试
  - 每阶段运行模块单测、assembleDebug、lint
  - 每阶段执行包含 USB、设备信号、音频焦点等设备清单

这个 Goal 同时包含代码清理、回归建设、文档契约、Browser 架构迁移、Video 双实现迁移、Picture 拆分、设备验收和旧代码删除。它应该被保存为 Roadmap,再拆成多个 Goal。

错误 Plan 原文:完成一步后自动追加下一步

执行过程中没有先形成一份完整、静态、等待批准的 Plan,而是从局部实现开始,随后不断改写 Plan。

Plan 快照 A:从 Video seek 局部切片开始

1. [completed] 审计两种策略 seek 手势状态与调用时序
2. [in_progress → completed] 迁移共同 seeking 状态到手势端口
3. [pending] 补齐双策略回归、契约并完成构建验证

这个切片本身可以成立,但没有文件数、diff、时间、新抽象和构建次数预算。

Plan 快照 B:完成 Video 后自动转入 Picture

1. [completed] 验证视频 seek 端口迁移的完整模块门禁
2. [completed] 审计 Picture 状态与 Fragment 责任边界
3. [completed] 提取下一项 Picture 纯状态并补充回归验证
4. [in_progress] 继续分批清理与最终验收

Video 小目标完成后没有停止评审,而是把 Picture 自动接入同一个 Goal。“继续分批清理与最终验收”也没有可判定终点。

Plan 快照 C:继续追加 Browser 微抽象

更新 1:
- [completed] 提取 Browser 硬键重复计数端口并验证
- [completed] 提取 Browser 系统栏回调保护端口并验证
- [in_progress] 继续分批清理与最终验收

更新 2:
- [in_progress] 提取 Browser pager interaction 端口
- [pending] 继续分批清理与最终验收

此时,“发现一个可提取状态就创建一个端口”已经替代人工架构选择。Plan 也从执行前的授权契约,退化成了没有终点的进度流水账。

失控是怎样发生的?

阶段实际行为应有控制动作
启动把整个重构路线图创建为持久 Goal只做 Plan-only,先验证前提并拆分 PR
局部实现完成 Video 小切片后继续进入 Picture完成一个切片即停止并评审
发现问题发现待删除入口仍是活跃入口停止执行,返回 Plan 修正路线图
范围扩张不断发现并提取新的 Browser 微抽象记录到 Follow-ups,不自动实施
验证多次构建和测试通过仍需检查范围、兼容性和真实设备行为
用户介入数小时后因改动过大被人工叫停应由时间、文件数或 diff 门禁更早停止

为什么测试通过仍然不算成功?

局部测试和构建只能证明部分代码可以运行,不能证明:

  • 累计 diff 仍然适合人工评审;
  • 新增抽象确实有必要;
  • 未授权模块没有被修改;
  • 旧入口可以安全删除;
  • 设备、系统事件和真实交互保持兼容;
  • 临时兼容层将来会被删除。

因此,测试绿色是完成条件之一,不是范围正确和设计正确的替代品。

根因

  1. Roadmap 被当成 Goal:长期方向没有被拆成单次交付。
  2. Plan 变成开放 Backlog:新发现被自动追加并实施。
  3. 没有人工检查点:跨模块和架构决策未经重新批准。
  4. 没有硬预算:时间、文件数、diff 和新抽象数量都无上限。
  5. 没有自然终点:局部完成后,Agent 继续领取下一项任务。

正确做法

第一轮只做只读调查:

只读审计示例模块的 Browser、Video 和 Picture 结构,不修改文件。
验证播放器真实入口、现有测试和外部兼容面。
输出按 PR 拆分的路线图,并为第一个切片给出文件范围、预算、
完成条件和回滚方式。输出后停止,等待批准。

人工确认调查结果后,只批准一个小 Goal,例如“定义最小播放器接口和契约测试,不迁移页面、不改变运行路径”。这个 Goal 完成并通过评审后,才为下一步重新进入 Plan。

案例结论

问题不在于 Agent 做得不够多,而在于团队把一个多周 Epic 交给了没有预算、没有批准点、没有自然终点的 Goal。

4. 标准工作流:SDD、Plan 与 Goal 构成受控 Loop

flowchart LR
    S[SDD<br/>定义规格与验收] --> E[Explore<br/>只读取证]
    E --> P[Plan<br/>定义一个交付批次]
    P --> A{人工批准?}
    A -->|否| P
    A -->|是| X[Execute<br/>受预算约束]
    X --> V[Verify<br/>分层验证]
    V --> R{是否满足完成条件?}
    R -->|否且范围内| X
    R -->|发现扩展/超预算| T[停止并报告]
    R -->|是| H[Review<br/>人工评审]
    H --> D{人工决定<br/>是否开启下一轮?}
    D -->|是| E
    D -->|否| N[结束当前工作]

阶段 A:SDD,先定义正确性

先写清目标行为、非目标、兼容约束和验收标准。规格可以很短,但必须足以判断候选方案是否满足需求。若关键需求、权限边界或不可逆操作仍不明确,应在这里暂停并请求决策。

阶段 B:Explore,只读探索

输出必须是证据而不是代码:

  • 当前调用链和状态所有权;
  • 外部兼容面;
  • 已有测试覆盖与缺口;
  • 候选切片及其收益、风险和文件影响;
  • 对任务前提的验证结果。

此阶段禁止修改生产代码。若发现“待删除旧入口实际上仍被调用”,应先修正路线图,而不是继续实现原计划。

阶段 C:Approve,批准一个批次

由人选择一个切片,确认:

  • 目标和非目标;
  • 允许修改的模块;
  • diff 与时间预算;
  • 公开接口和兼容要求;
  • 测试层级;
  • 停止条件。

阶段 D:Execute,受预算执行

代理只执行已批准 Plan。旁支问题进入 Follow-ups,不得顺手修改。

阶段 E:Review,完成即停止

交付仅包含:

  • 改动摘要;
  • 行为证据和测试结果;
  • 实际 diff 规模;
  • 未执行项目与风险;
  • 建议的下一个 Goal,但不自动启动。

这条路径才是本文所说的 Loop:每轮从 SDD 规定的正确性出发,经由证据和 Plan,进入受限 Goal,最后以验证和人工评审结束。Loop 的闭环点在人工是否批准下一轮,而不是 Agent 完成局部实现后自动领取新任务。这样既保留了“观察结果、调整路径、继续推进”的迭代能力,也让每次范围扩张、架构取舍和风险接受都有明确责任人。

5. 预算与强制停止条件

以下数值是本文结合上述资料给出的团队默认值建议,不是 OpenAI、Google 或 DORA 的强制标准。团队应按代码库和风险校准。

5.1 默认批次预算

项目默认值升级条件
代理执行时间45–90 分钟超过 90 分钟必须人工续期
生产文件≤ 5 个跨模块或公开接口变更需预批
总文件≤ 10 个生成文件可单独计算
人工可读逻辑 diff约 100–300 行接近 1000 行必须拆分或预先获批
新抽象≤ 1 个第二个抽象进入后续 Goal
模块跨度1 个主模块适配层可作为显式例外
完整构建每个批准批次 1 次中间使用定向测试
Goal1 个评审结果禁止“以及顺便”

5.2 必须停止的条件

  • 预计或实际超过任一预算;
  • 任务前提被证伪;
  • 需要修改未授权模块、公开接口、Manifest、持久化键或外部协议;
  • 需要新增第二种架构抽象或第三方依赖;
  • 发现用户已有改动与当前任务冲突;
  • 关键行为没有可执行回归保护;
  • 测试环境连续两次因同一外部原因失败;
  • 出现多个同样合理、但取舍会影响长期架构的方案;
  • 需要删除旧路径、资源或数据;
  • 人工验收是唯一完成证据。

预算不是 KPI

预算的作用是触发重新决策,不是鼓励代理通过压缩代码、减少测试或隐藏变更来“达标”。

6. 分层验证:先定向,后全量

层级何时运行示例
L0 静态检查每次编辑后引用搜索、格式、git diff --check
L1 定向测试每个逻辑小步单个状态处理器、接口或适配器契约
L2 模块编译/测试批次实现稳定后testDebugUnitTest、模块编译
L3 完整构建/lint批次交付前一次assembleDebug、lint 报告
L4 集成/设备验证PR 候选或发布前USB、音频焦点、车机信号、前后台

如果 L3 存在已知上游阻断,必须记录报告路径与根因,并明确它不能证明什么;不得为了变绿而修改范围外配置。

7. 大型重构如何拆分

Fowler 的 Branch by Abstraction 允许旧实现与新实现通过同一抽象并存,并要求系统在迁移期间始终可构建、可运行。Martin Fowler: Branch By Abstraction

当接口存在多个消费者时,Parallel Change 将迁移拆成 Expand、Migrate、Contract 三阶段,每阶段都可发布和验证;但如果 Contract 不执行,系统可能比迁移前更复杂。Martin Fowler: Parallel Change

媒体模块示例拆分

以下是路线图,不是一个 Goal,也不是一个可以直接执行的 ExecPlan。它需要先形成 SDD 和总体 ExecPlan,再按里程碑分别经过 Plan 与 Goal:

  1. Discovery Goal:只读盘点播放器入口、兼容接口和现有回归,不改代码。
  2. Test Baseline Goal:只增加 Native 当前行为测试,不重构生产代码。
  3. Contract Goal:定义最小 VideoPlayer 能力接口和一组契约测试,不迁移 Fragment。
  4. Native Adapter Goal:让现有 Native 路径通过接口,默认行为不变。
  5. Exo Adapter Goal:让现有 Exo 路径通过同一组契约测试,不改策略选择。
  6. Session Strategy Goal:仅实现进入会话时固定策略及无自动回退。
  7. One Workflow Goal:一次迁移一个行为,例如续播,完成后停下评审。
  8. Contract Goal:证据证明旧入口无消费者后,单独删除旧代码和资源。

每个 Goal 都应拥有独立 diff、测试证据和回滚路径。不要把八个 Goal 重新包装成一个“多里程碑自治任务”,除非满足第 9 节的长任务准入条件。

8. 可复制提示词模板

8.1 Plan-only:先规划,不改代码

模式:Plan-only。禁止修改任何文件。

背景:<业务背景和当前问题>
目标:为 <单一结果> 形成一个可评审执行计划。

先确认规格:
- 目标行为:<用户/调用方可观察结果>
- 非目标:<本次不处理的内容>
- 约束:<兼容、安全、性能、权限或不可逆操作边界>
- 验收:<测试、指标或确定性产物>

请先读取:
- <文件/模块>
- <测试>
- <外部接口>

输出必须包含:
1. 当前数据流与控制流证据;
2. 任务前提是否成立;
3. 2–3 个切片方案及取舍;
4. 推荐方案涉及的准确文件;
5. 行为兼容面、测试与回滚;
6. 预计文件数、逻辑 diff 和耗时;
7. 哪些决策必须由我批准。

停止条件:输出计划后停止,等待批准;不得开始实现。

8.2 受控 Goal:一个 PR 级交付

Goal:<可观察、可验证的单一结果>

规格依据:
- 目标行为:<本次要满足的 SDD 结果>
- 验收标准:<可执行的测试或产物>

In scope:
- <允许修改的行为和文件>

Out of scope:
- 不处理 <相邻问题>
- 不修改 <模块/公开接口/资源/依赖>

兼容约束:
- <Intent、广播、偏好键、API、UI 等>

预算:
- 最长 60 分钟;
- 最多 5 个生产文件、10 个总文件;
- 约 300 行人工可读逻辑 diff;
- 最多新增 1 个抽象。

验证:
- 每步运行 <定向测试>;
- 交付前运行 <模块测试/构建>;
- 人工验证项只列清单,不声称完成。

强制停止:
- 前提不成立、需要跨范围修改、超预算或存在架构分歧时停止;
- 完成当前 Goal 后停止,不自动开始下一项。

交付格式:完成 / 验证 / 未做与原因 / 风险。

8.3 只读审计 Goal

Goal:验证 <旧入口/资源/依赖> 是否可以删除。
权限:只读,不修改代码、不删除文件。
证据:Manifest、直接引用、反射/动态资源、生成代码、测试、构建配置、运行入口。
完成条件:给出“可删除 / 不可删除 / 证据不足”结论,并列出证据路径。
停止条件:报告完成即停止。

8.4 超预算续期

不要继续修改。请报告:
- 已完成与未完成;
- 当前 diff 规模;
- 超预算原因;
- 最小可交付截点;
- 回退到批准范围的方法;
- 继续执行所需的新预算和新增风险。
等待我明确批准后再继续。

9. 多小时 ExecPlan 的准入条件

OpenAI 的 ExecPlan 适合复杂、多小时任务,但其前提是计划自包含、持续维护、每个里程碑独立可验证,并记录发现与决策。OpenAI: Using PLANS.md

ExecPlan 的准入顺序应是:先确认 SDD 规格,再用 Plan 验证路径和依赖,最后才批准 ExecPlan 的里程碑。没有稳定的目标行为、验收标准或回滚边界时,ExecPlan 只能记录不确定性,不能替代需求决策。

只有以下项目全部满足,才适合无人值守多小时运行:

  • 目标结果可通过测试、指标或确定性产物机器验证;
  • 执行环境隔离,不会覆盖未提交工作;
  • 每个里程碑都可独立提交、回滚和恢复;
  • 所有破坏性和外部动作均需人工批准;
  • 路径虽长,但不是架构偏好探索;
  • 预算、最大重试次数和墙钟超时明确;
  • 代理可以访问真实运行日志或等价观测;
  • 有自动化评审或强测试,而非只靠编译通过;
  • 人工接受可能产生的 diff 规模;
  • 完成后不会自动开启旁支优化。

不适合的典型任务:遗留系统开放式“全面重构”、视觉品味调整、缺少回归的业务流程迁移、需要频繁产品判断的工作。

10. 参考资料与观点来源


一句话原则

让 AI 自主决定“怎么完成一个已批准的小目标”,不要让它自主决定“接下来整个系统还应该改什么”。