BlueXIII's Blog

热爱技术,持续学习

过去的研发流程一直以本机Codex为主。需求分析、阅读源码、修改代码、运行测试、处理环境问题,基本都在同一个任务里完成。Codex能直接看到本机工作树、依赖、数据库、容器和未提交差异,遇到问题可以反复执行“修改—测试—诊断—再修改”,这套方式很顺手。

ChatGPT能够通过GitHub读取项目以后,也可以进入这套研发流程。ChatGPT更适合长时间讨论需求、比较方案和做独立审阅,Codex则仍然适合留在本机实施。两者不必争夺“主力开发者”的位置,也不应该同时修改同一个工作区。比较自然的分工是:ChatGPT在上游定义问题、在下游检查结果,Codex完成中间那段需要本地反馈的工作。

1
2
3
4
5
6
ChatGPT:定义问题、形成需求、设计方案、独立审阅
Codex:本地实施、测试迭代、环境操作、修复审阅问题
负责人:确认产品取舍、接受风险、合并、发布

GitHub:保存分支、提交、PR、Issue和交接记录
仓库文档:保存正式需求、设计、实施和版本事实

模型能力当然重要,但在研发流程中,能不能访问真实环境同样重要。ChatGPT可以读懂一段迁移代码,却不能因此宣布数据库迁移已经成功;Codex可以在本机把测试跑通,也不代表它在经历完整个实现过程后仍能像陌生审阅者一样发现设计盲点。把这两种能力串起来,比让它们重复做同一件事更合适。

不需要再发明一套ChatGPT流程

如果仓库已经有需求、设计、实施和审阅记录,没有必要增加“ChatGPT任务”“Codex任务”之类的新流程对象。无论由谁完成,工作性质并没有改变:

  • ChatGPT修改需求、设计、测试或代码,仍然是一轮正常的实施工作;
  • ChatGPT针对固定提交做正式独立审阅,仍然是一轮工程审阅;
  • 负责人在真实界面和环境中使用产品,仍然属于真实使用验证,ChatGPT不能代替;
  • 普通PR里的一条Review意见,不需要为了显得正式而单独建立审阅流程;
  • 对话中确认的需求和设计,最后仍要写回REQ、设计文档或ADR,不能只留在聊天记录里。

Agent只是当前工作的执行者。流程如果绑定了某个模型名称,换工具以后就要重写;把规则落在分支、提交、验证证据和正式文档上,即使以后换成其他Agent,也不影响协作方式。

GitHub只是协作枢纽

引入ChatGPT以后,很容易把Issue和PR当成新的事实源,最终形成两套互相矛盾的记录。正式事实仍应保存在仓库里,GitHub负责讨论、交接和合入。

对象 保存的内容
REQ 为什么改变产品,希望得到什么结果
系统设计、能力设计和ADR 系统应该怎样工作,为什么作出这个选择
实施、使用和审阅记录 实际做过什么,得到什么结果
GitHub Issue 外部反馈、待办、讨论和跨会话提醒
GitHub PR 一组具体差异的讨论、审阅和合入过程
Git分支 一项工作的临时候选
Commit SHA 某次交接或审阅面对的准确版本
Git标签 已经冻结的正式版本

这种分层也不依赖GitHub。以后换成GitLab、Forgejo甚至只使用本地Git,REQ、设计和Commit SHA仍然成立,变化的只是协作界面。

ChatGPT连接GitHub的具体能力可能随使用的App、插件和权限配置而不同,因此流程不能假定它一定能直接写仓库。连接具备写操作时,ChatGPT可以建立分支、提交候选和更新PR;只有读取能力时,它给出设计或Review结果,再由Codex写回仓库。无论使用哪种连接方式,交接对象都应该是正式文档、PR和固定SHA。

用两类PR把定义和实现分开

所有修改都塞进一个PR看起来省事,实际会让需求、设计和代码同时变化。ChatGPT审阅实现时,找不到已经确认的设计基线;Codex写到一半,也不知道对话里的新想法是不是正式范围。

PR可以区分为Definition PR和Implementation PR。这里的名称只是说明用途,不需要增加复杂的GitHub类型或自动化。

Definition PR:先确认改成什么样

产品行为、业务规则、接口含义、权限、安全、数据或交付范围发生变化时,先准备Definition PR:

1
2
3
4
5
6
7
8
9
原始想法
→ 负责人和ChatGPT讨论范围
→ ChatGPT检查已有REQ、设计、源码和历史决定
→ 建立或修改REQ
→ 修改受影响的系统设计和能力设计
→ 必要时准备ADR
→ 在Draft PR中讨论阻塞问题
→ 负责人确认
→ 合入主分支

通常可以把REQ和受影响的设计放进同一个Definition PR,不必为了流程机械拆分。只有改动很大、横跨多个领域,或者必须先单独确定产品方向时,才把需求和设计分成两个PR。

未确认的设计不要和实现混在一起。Definition PR合入以后,Codex面对的是主分支上已经接受的设计,不需要从聊天记录中猜测哪个版本才算最终决定;ChatGPT后续审阅代码时,也有稳定的比较对象。

Implementation PR:实现已经确认的设计

Definition PR合入以后,Codex从新的主分支建立任务分支和本机worktree:

1
2
3
4
5
6
7
8
已经接受的REQ和设计
→ Codex建立任务分支与worktree
→ 实现代码和测试
→ 运行针对性检查
→ 运行仓库规定的完整验证
→ 推送分支并更新Draft PR
→ 固定HEAD SHA
→ 交给ChatGPT审阅

ChatGPT在Implementation PR里不必重新设计整个功能,主要检查这些问题:

  • 实现是否符合REQ和已经接受的设计;
  • 修改是否悄悄扩大了需求范围;
  • 失败场景、权限边界和恢复行为是否遗漏;
  • 测试有没有覆盖真正的风险;
  • 代码、实施记录和验证证据能否互相对应;
  • 是否为了一个局部需求引入了不必要的复杂结构。

发现阻塞问题后,由Codex在本机修复并重新验证。负责人看到的不是一段“应该没问题”的回答,而是固定候选、Review意见和对应的验证结果。

不同工作交给谁

ChatGPT并非不适合修改代码,真正缺少的通常是完整的本地反馈循环。它可以写出第一版代码,但数据库、并发、容器和部署类修改仍要在真实工作树中收口。

工作类型 默认主导者 处理方式
原始需求讨论、范围收敛 ChatGPT 对话分析后形成REQ候选
产品设计、架构设计、ADR ChatGPT 通过Definition PR确认
文档Review和重写 ChatGPT 修改候选或给出明确差异
小范围纯逻辑修改 ChatGPT或Codex ChatGPT可以准备第一版,Codex本机验证
中等规模代码修改 Codex ChatGPT先明确设计和实施边界
数据库、并发、事务和Runtime Codex 本机实现,ChatGPT针对固定SHA审阅
Docker、部署、环境和Secret Codex ChatGPT分析方案,不替代环境操作
测试方案和遗漏分析 ChatGPT Codex补充测试并实际运行
自动化验证 Codex 在本机或受控开发机执行
真实界面使用 负责人 记录真实使用中发现的问题
正式工程审阅 新的ChatGPT会话 固定提交,独立阅读
合并、标签和正式发布 负责人 Agent准备候选和证据

这张表不是硬性权限表。一个很小的文案错误没必要先开Definition PR,一个已经确定行为的局部修复也可以直接交给Codex。判断依据仍然是改动有没有改变正式设计,以及验证是否依赖本地环境。

一个分支同时只能有一个写入者

ChatGPT和Codex可以共同处理同一项工作,但只能串行接棒,不能同时写同一个分支。否则很容易出现远端分支已经变化、本机仍然基于旧提交修改,或者一方为了整理提交而覆盖另一方历史的情况。

协作时遵守这些规则:

  1. 一项任务只保留一个主要分支。
  2. 一个分支在任一时刻只有一个当前写入者。
  3. 交接前,当前写入者提交并推送全部候选变化。
  4. 交接记录写出完整HEAD SHA,不使用含糊的“最新提交”。
  5. 接棒者开始前确认远端HEAD仍然等于交接SHA。
  6. 共享分支不做force push,交接后不重写历史。
  7. 试错提交需要整理时,在最终合入主分支时squash。
  8. 两个Agent要尝试不同方案时,分别建立分支或PR,不在同一个分支里互相覆盖。
1
2
3
4
5
一项任务
→ 一轮实施工作
→ 一个短期分支
→ 一个隔离工作空间
→ 一个当前写入者

对Codex来说,隔离工作空间通常是本机worktree;对通过GitHub工作的ChatGPT来说,隔离空间是远端分支和Draft PR。同一项任务可以在不同阶段更换写入者,换人之前必须先形成可以准确定位的提交。

worktree只隔离代码目录,并不会自动隔离数据库、容器、端口、缓存和凭据。多个本机Agent并行工作时,这些资源仍要单独分配。相关约束在让多个Agent在不同worktree工作中有更完整的记录。

尽早建立Draft PR

ChatGPT和Codex共同参与的任务,可以在工作稳定之前就建立Draft PR。它不是“准备合并”的信号,而是两边共同使用的交接面。

PR正文顶部只保留当前状态:

1
2
3
4
5
6
7
## 协作状态

当前阶段:需求 / 设计 / 实现 / 验证 / 评审 / 待确认
当前写入者:ChatGPT / Codex / 负责人
当前候选:<完整HEAD SHA>
下一接棒者:ChatGPT / Codex / 负责人
下一步:一句话说明需要做什么

这些字段会随着任务推进而更新。每次正式交接再增加一条不可变的PR评论,保留当时的准确状态。

ChatGPT把已经确认的定义交给Codex时,可以使用下面的格式:

1
2
3
4
5
6
7
8
9
10
11
12
### 交接给Codex

- 基线:main@<SHA>
- 当前候选:<HEAD SHA>
- 正式依据:REQ-000123、CAP-005、ADR-0012
- 本轮目标:……
- 明确不做:……
- 可以修改:……
- 已经完成:……
- 已运行验证:……
- 未验证和风险:……
- 下一步:在本机worktree实施并运行……

Codex完成本机工作后,再把固定候选交给ChatGPT:

1
2
3
4
5
6
7
8
9
### 交接给ChatGPT审阅

- 比较起点:main@<SHA>
- 固定候选:<HEAD SHA>
- 实际修改:……
- 本机验证:……
- 失败、跳过和警告:……
- 明确未验证:……
- 重点审阅:……

PR原有的来源、范围、设计、验证和恢复内容可以继续保留,只需增加这段很短的协作状态,不必再造一份复杂清单。

Token省在交接,而不是省掉必要信息

让ChatGPT和Codex协作,如果每次都把仓库、全部文档和完整聊天记录重新发一遍,Token只会比原来更多。需要减少的是重复上下文,而不是把需求和验证记录删短。

可以给不同阶段准备不同的上下文包:

阶段 应该提供 通常不需要提供
需求与设计 原始问题、相关REQ、现有设计、历史决定、必要源码 本机缓存、完整测试日志、无关模块
本机实施 已接受的REQ和设计、验收条件、允许修改范围、相关代码 前期所有方案争论、已经否决的长篇讨论
独立审阅 比较起点、固定HEAD SHA、REQ、已接受设计、验证摘要 实现过程的完整聊天、Agent的思考过程
负责人确认 PR摘要、阻塞问题、验证结果、未解决风险 每次命令输出和全部中间尝试

这里有几个很实际的节省点。

ChatGPT完成需求讨论后,不把整段对话交给Codex,而是写成REQ、设计和一条交接评论。Codex只读取实施所需的正式结论。需求为什么改变、哪些方案已经否决,如果将来仍有价值,就写进ADR;没有进入正式文档的闲聊不再反复传递。

Codex完成实现后,也不把本机终端的全部输出塞给ChatGPT。PR记录执行了什么验证、结果如何、哪些检查失败或跳过,详细日志只在需要诊断时按链接或附件读取。

独立审阅使用新的ChatGPT会话,只给固定SHA和相关事实源。它不需要恢复实施会话的全部历史,也不会因为读过每一步尝试而沿用实现者的判断。

另外,不再让两个Agent各做一次全仓库调查。ChatGPT在Definition阶段确认受影响的能力和设计,Codex实施时围绕这部分代码工作;如果Codex发现实际依赖超出原范围,再把新的事实写回PR,而不是默默扩大任务。

这套方法没有一个固定的Token节省比例。项目结构、文档质量和任务大小不同,差异会很大。可以确定的是,长对话不再成为唯一的记忆载体,每位接棒者也不必从项目起点重新建立上下文。

Review发现的问题放在哪里

ChatGPT审阅PR时,并不是每条意见都要建立Issue:

  • 当前PR内可以直接修复并验证的问题,留在PR评论中;
  • 修复会明显扩大当前范围的问题,建立待复核的GitHub Issue;
  • 需要长期追踪的问题,再登记到仓库内的正式问题台账;
  • 会改变产品行为的问题,从Issue转入REQ和设计流程;
  • 只有改进建议、还不能说明存在缺陷时,保留为建议,不机械建Issue。

如果一个GitHub Issue已经关联仓库内的正式问题记录,PR合入不一定代表问题已经验证关闭。这时PR使用Refs #123更准确,等实施、验证和正式台账都收口以后再关闭Issue。只有没有进入正式台账、并且合入本PR就能真实结束的问题,才适合使用Closes #123

这样做会多一步状态确认,但能避免GitHub显示“已关闭”,仓库记录却仍然等待验证的矛盾。

普通Review和独立Review

ChatGPT参与过需求和设计,随后在同一段对话中检查代码是否符合自己的设计,这种Review效率很高,普通PR完全可以这样做。不过它仍然可能受之前方案影响,对权限、Secret、事务、并发、迁移、删除和恢复等高风险修改,应使用新的会话做独立Review:

  1. 固定完整HEAD SHA;
  2. 新建一个没有参与实施讨论的ChatGPT会话;
  3. 只提供PR、REQ、已接受的设计、相关源码和审阅目标;
  4. 不把原实现讨论全部复制过去;
  5. 审阅期间不继续修改被审候选;
  6. 结论需要长期保存时,写入正式审阅记录。

固定SHA保证审阅者看到的内容不会在审阅途中变化。新会话减少了对原方案的锚定,也顺便缩小了上下文。OpenAI当前的Codex用例同样包含GitHub PR审阅,它可以作为额外的代码审阅入口,但没有必要让ChatGPT和Codex对每一个普通PR重复给出相同Review。

验证责任仍然留在本机

ChatGPT可以阅读测试代码、判断覆盖是否充分、补充测试、查看GitHub Actions结果和分析失败日志。它也可以指出“这里应该补一组事务回滚测试”,但不能因为代码看起来合理,就把没有执行过的测试写成通过。

本机Codex负责运行仓库规定的验证命令,并记录:

  • 验证对应的HEAD SHA和比较起点;
  • 当时的Git tree是否干净;
  • 运行过哪些命令;
  • 哪些检查通过、失败或跳过;
  • 是否使用数据库、容器、浏览器或其他外部环境;
  • 哪些风险仍然没有验证。

本机测试、远端CI、数据库检查、容器运行和负责人真实使用解决的是不同问题,不能互相替代。ChatGPT给出的代码候选,也要先由Codex拉到本机worktree中验证,再进入合并判断。

权限从最小范围开始

ChatGPT的GitHub连接先只开放需要协作的仓库。读取源码、文档、Issue、PR和CI结果可以作为日常能力;任何写操作都只进入自己的短期分支,不直接推送主分支。

操作 建议边界
读取源码、文档、Issue、PR和CI结果 允许
建立短期分支、更新Draft PR 连接支持时允许
向任务分支提交 写入前确认
添加Review意见或待登记Issue 允许
直接推送主分支 禁止
合并PR、创建标签、正式Release 负责人确认
修改Secret或真实环境 交给本机Codex,另行确认
修改Workflow权限 独立任务处理
删除分支、Issue或历史证据 负责人确认

这里约束的是动作风险,不是对某个模型的信任程度。即使以后连接能力更强,也没有必要让远端Agent绕过PR直接修改主分支。

落到仓库只需要几处小改动

这套协作不需要马上增加新的CI门禁或GitHub自动化。先修改四个位置就够了:

  • AGENTS.md继续保持工具无关,只写产品取舍、合并和发布等通用权限边界,不塞入某个模型的操作说明;
  • Git协作规范增加“一个分支一个当前写入者、固定SHA交接、共享分支不强推”几条规则;
  • PR模板增加当前阶段、当前写入者、当前候选、下一接棒者和下一步;
  • 研发手册补充本地worktree、远端分支、普通Review和固定SHA独立Review的关系。

最终形成的链路是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
原始想法

负责人和ChatGPT分析需求

Definition Draft PR
├─REQ
├─受影响的设计
└─必要的ADR

负责人确认并合入主分支

Codex建立任务分支和本机worktree

实现、针对性测试、完整验证

Implementation Draft PR并固定HEAD

新的ChatGPT会话Review
├─阻塞问题:Codex修复并重新验证
├─后续问题:建立待复核Issue
└─普通建议:明确记录去向

负责人确认并合并

记录实际合入提交、同步问题与版本关系

这样安排以后,ChatGPT不必复制Codex的本机开发过程,Codex也不必重新经历ChatGPT的全部需求讨论。GitHub保存两边交接时的准确状态,仓库文档保存最终结论,长对话只负责帮助形成判断,不再负责充当项目记忆。

ACDL研发流程系列第1篇,共15篇。

下一篇:ACDL研发流程02:从想法到项目骨架

1.ACDL是什么

ACDL是Agent Collaborative Development Lifecycle的缩写,中文名称为“Agent协同研发体系”。它是当前项目根据自己的实际研发方式形成的一套方法,用来组织人和Agent从发现问题、设计、实施、验证到正式版本的协作过程。

它不是行业标准,也不是某一种Agent编程工具的使用方法。ACDL关注的核心问题是:当Agent已经能够实际读取仓库、修改跨模块代码、运行测试、操作环境并参与评审时,项目怎样仍然保持清楚的方向、边界和结果。

ACDL也不等于“让Agent写代码”。编码只是其中一个环节。

2.为什么Agent参与以后需要重新组织研发过程

Agent带来的最大变化,不只是写代码更快,而是很多原来需要多人分别完成的工作,可以由一个Agent连续跨越多个层次完成

这会带来明显效率,也放大几类风险:

  • 一个模糊想法可以很快被实现成复杂方案,即使方向一开始就错了;
  • 对话里随口讨论的内容可能被下一次会话误当成已经确认的要求;
  • 多个Agent可以同时修改不同模块,也可能同时依赖同一个尚未稳定的接口或数据结构;
  • 代码、设计、测试和环境可能分别停留在不同状态;
  • Agent很容易报告“测试通过”,但Director仍然不知道最初的问题是否真正解决;
  • 一项修改进入main以后,如果没有明确记录,很难再回答它最终属于哪个正式版本。

传统研发中的需求管理、领域建模、测试、CI和代码评审仍然有价值。ACDL没有要替代这些做法,而是重新回答四个问题:

1.项目上下文放在哪里;
2.什么事情Agent可以直接决定,什么事情需要Director确认;
3.多个Agent怎样安全地同时工作;
4.怎样判断一轮工作和一个正式版本真正结束。

3.ACDL已经怎样落在当前项目仓库里

ACDL不是一张独立流程图。它已经体现在仓库目录、编号、状态和工具中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
project/
├─AGENTS.md
├─docs/
│ ├─00-规范/ 长期研发和文档规则
│ ├─01-需求/ REQ和候选路线
│ ├─02-设计/ 系统、能力、横切设计、ADR和索引
│ ├─03-实施/ ISSUE、ACL、DFL和ERL
│ ├─04-版本/ 版本验收、发布说明和Git标签
│ ├─05-环境/ 当前环境和环境变更
│ ├─11-手册/ 产品技术和研发流程教程
│ ├─12-交流材料/
│ ├─13-交付与申报材料/
│ ├─21-历史工作记录/
│ └─22-历史基线材料/
├─scripts/
├─apps/、packages/、providers/
├─tests/
└─deploy/

这些目录不是把同一件事重复写很多遍。

  • 需求说明为什么要改变
  • 设计说明系统应该怎样工作
  • 实施记录说明这一轮实际做了什么
  • 环境记录说明现在运行什么
  • 版本记录说明最终正式交付了什么

一个新Agent不需要依赖过去的聊天记忆来重新猜项目状态,只要沿这些入口读取当前任务所需的内容。

4.Agent进入仓库后从哪里开始

当前项目中的Agent先读取根目录AGENTS.md。它负责说明工作规则和安全边界,例如:

  • 项目和文档从哪里进入;
  • 哪些决定需要Director确认;
  • 历史代码、真实数据和Secret怎样处理;
  • 测试、发布和远程操作有哪些前置条件;
  • 修改真实环境时哪些动作需要额外授权。

然后从docs/README.md进入当前项目记录,再按任务选择REQ、已经确认的设计、Loop记录、环境状态以及真正相关的代码和测试。

1
2
3
4
5
AGENTS.md
→docs/README.md
→当前REQ、设计、Loop或环境记录
→实际代码和测试
→仓库工具与验证入口

历史文档可以用来理解为什么曾经那样做,但不能因为搜索结果先出现一份旧材料,就拿它替代当前设计。

5.规范负责定规则,入口负责带路

docs/00-规范/保存需要长期重复执行的规则。Agent不必一开始把所有规范都读完,而是先从docs/00-规范/README.md判断当前任务涉及什么,再读取真正命中的章节。例如,改中文文档时看写作规范,判断是否要改设计时看设计评审规范,开展ACL、DFL或ERL时看实施流程规范。

规范告诉参与者怎样工作,不会替具体任务给出产品答案。某项功能当前应该怎样表现,仍然要从REQ和Accepted设计中读取;某次实施做了什么,则从对应Loop记录和实际代码中核对。手册只能帮助理解这些关系,不能成为另一套规则来源。

6.scripts把一部分规则变成可执行检查

仓库中的scripts/大致分成:

1
2
3
4
5
6
scripts/
├─verify/ 读取和检查,不修改项目状态
├─generate/ 根据已有输入生成派生内容
├─workflows/ 创建或更新ISSUE、ACL和Loop记录
├─operations/ 改变安装、发布、恢复或开发环境
└─lib/ 供上述工具复用的内部实现

常用公开入口包括:

  • pnpm docs:check:检查文档结构、状态、编号、链接和追踪关系;
  • pnpm verify:根据实际差异选择验证深度;
  • pnpm trace:render:重新生成设计要求追踪视图;
  • pnpm issue:new:登记需要持续追踪的问题;
  • pnpm loop:new:创建ACL编号和记录骨架;
  • pnpm loop:status:按允许的状态变化更新Loop;
  • scripts/operations/:安装、升级、回退、恢复和开发环境发布。

运行脚本前仍然要理解它会读取什么、修改什么。verify/主要是检查;workflows/会改仓库记录;operations/会真正改变环境,三者风险完全不同。

7.一项产品变化怎样穿过这些目录

继续用“收藏会话”这个教学例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docs/01-需求/
→说明为什么员工需要收藏

docs/02-设计/
→确认用户行为、归属、权限和技术实现

docs/03-实施/
→启动ACL,记录起点、范围、实际修改和验证

代码与测试
→实现已经确认的行为

docs/05-环境/
→需要实机验证时记录环境到底运行什么

docs/04-版本/
→验收时选择实际纳入范围并由Git标签固定

这条路线可以返回前面。实现发现设计无法落地,就回到设计;真实使用发现需求本身需要改变,就回到REQ;独立评审发现实现缺陷,则登记问题并开始新的处理。

目录的作用是让事情有明确归属,不是强迫每项工作只能单向前进。

8.ACDL中的Director和Agent

Director

Director是对方向、取舍、授权和最终结果负责的人,不是传统公司岗位名称。

在不同阶段,他可能在做完全不同的判断:

  • 发现问题时,从用户角度判断痛点是否真实;
  • 需求阶段决定是否改变产品;
  • 设计阶段确认用户行为、架构、安全和数据取舍;
  • 实施阶段处理超出Agent边界的决定;
  • DFL中真实使用产品;
  • 版本阶段确认实际范围和剩余风险。

这些工作不要求Director亲手写完所有代码或执行每条测试,但最终的产品决定、风险接受和交付结论不能交给Agent自行批准。

Agent

Agent是实际研发参与者,而不只是代码生成器。它可以:

  • 调查问题和现有实现;
  • 参与需求和设计讨论;
  • 修改前端、后端、数据、测试和部署;
  • 运行自动化和实机验证;
  • 收集失败证据并定位原因;
  • 作为独立评审者检查其它工作。

Agent能力越强,边界越要清楚。它可以提出改变产品的建议,但不能因为方案看起来合理就自行把它实现成新的产品规则。

9.项目上下文不能只存在聊天里

一个长期项目会经历大量会话和不同Agent,也可能同时存在多个工作目录。某次聊天里的信息不会自动成为其它会话都知道的共同背景。

因此,重要的需求和决定要进入项目文档;当前工作范围要进入Loop启动方案;实际失败和结果要进入实施记录;环境和版本状态也要有自己的长期入口。文档不再只是帮助人理解代码的说明材料,而要成为Director和Agent都能持续读取的项目源码

这不是把“所有聊天都转成文档”,而是只把以后继续工作仍然需要知道的信息写到它负责的位置。

10.为什么按任务而不是按岗位组织Agent

Agent可以跨前端、后端、数据和测试完成端到端工作,因此当前项目更适合按可以独立完成和验证的结果拆任务,而不是把同一功能切成“前端Agent”“后端Agent”“测试Agent”。

一个任务如果必须等其它Agent完成才能证明自己正确,它往往只是一个实施步骤,而不是适合并行的独立任务。

ACDL后面的ACL和并行协作规则,就是为了让不同Agent在彼此清楚的任务边界内工作,而不是共享一个模糊现场。分支和worktree是需要隔离文件修改时的工具,不是每轮ACL必须补齐的形式。

11.代码合并和部署都不能自动代表完成

以下几件事必须区分:

  • 代码已经写完;
  • 自动化验证已经通过;
  • 候选已经部署到环境;
  • Director已经真实使用并确认体验;
  • 独立工程评审已经结束;
  • Loop已经完成;
  • 正式版本已经验收并创建Git标签。

它们回答不同问题。某项工作可能只需要做到其中一部分,也可能根据风险需要继续更多检查。ACDL要求把“完成到哪一步”说准确,而不是用一个泛化的“已完成”覆盖所有状态。

12.ACDL最终想得到什么

ACDL不是为了增加流程对象,而是让下面这条协作能够长期重复:

1
2
3
4
5
Director给出问题、方向和边界
→仓库保存当前需求、设计和工作范围
→Agent实施、验证并带回真实证据
→Director依据结果继续、调整或结束
→需要正式交付时由Git标签固定版本

13.与外部方法的关系

行业已经在尝试回答类似问题,但相似名称之下往往对应不同对象和范围。

例如,微软提出的Agent development lifecycle更关注怎样发现、实验、构建、部署和稳定运行一个Agent产品。ACDL面对的问题不同:不论最终产品是不是Agent,Director都在使用Agent参与软件研发,因此它关注的是人和Agent怎样共同管理需求、设计、实施、验证和版本。

GitHub的Spec Kit强调规格驱动开发,让规格成为Agent实施时的重要依据,而不是只把代码当成真相。这个方向对ACDL很有启发,但“规格到实现”仍然不等于一项产品变化已经完整交付。环境发布、真实使用、独立评审、未解决问题和正式版本仍然需要继续处理。

这些方法都在快速发展,对“Agent是产品、开发工具、工作者还是协作者”也没有完全统一的语义。ACDL会吸收其中适合当前项目的思想,但不会为了对齐某个外部方法而重新包装自己的研发对象和流程。

下一章会回到项目最早期,说明当只有一个模糊想法时,怎样先通过PoC和MVP建立项目骨架,而不是一开始就套上完整ACDL。

ACDL研发流程系列第3篇,共15篇。

上一篇:ACDL研发流程02:从想法到项目骨架

下一篇:ACDL研发流程04:需求怎样走完整个ACDL

1.项目变大以后,代码本身讲不完整个项目

项目还小时,Director往往可以在一次对话中向Agent讲清大部分背景。实现方向即使有偏差,返工成本也有限。

规模上来以后,Agent虽然仍然可以快速读取代码,却不一定知道:

  • 某个行为是刻意设计,还是尚未修复的实现偏差;
  • 一项限制来自产品要求、安全边界,还是当时的临时做法;
  • 一段看似多余的代码是否仍有现实用途;
  • 某个测试验证的是长期规则,还是只服务一次实现;
  • 当前开发环境是否真的已经运行这份代码;
  • 一项已经结束的工作当时有哪些失败、跳过和剩余问题。

如果这些信息只保存在人的记忆、聊天记录和提交标题里,每次换会话、换Agent或隔一段时间继续工作,都需要重新猜测。更危险的是,Agent通常不会因为缺少背景自动停止,它很可能会沿着一组错误假设继续完成一份逻辑自洽的实现。

代码规模只是一个提醒。即使项目不大,只要涉及多任务并行、安全、生产数据、环境发布或长期交付,也需要更早把重要上下文写进仓库。

2.文档是代码的“源码”

在当前项目中,文档不只是代码完成后的使用说明。需求记录为什么要改,已经确认的设计定义系统应该怎样工作。Agent先读取需求和已经确认的设计,再把它们变成代码和测试。从这个意义上说,文档是代码的“源码”。

这个说法不表示所有文档都要在编码前写完。不同文档承担不同职责:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
REQ
→说明为什么改变、希望得到什么结果

已经确认的设计
→说明系统现在应该怎样工作

代码和测试
→实现并验证已经确认的行为

实施记录
→保存这一轮实际做了什么、失败了什么、结果怎样

环境记录
→保存环境现在运行什么

版本记录
→保存正式交付最后纳入什么

设计可以指导后续实现;实施记录不能反过来因为代码已经写出来,就悄悄改变设计;环境记录也不能因为服务器当前恰好这样配置,就自动成为长期架构规则。

当前项目中文档和代码的规模约为1:2。这不是要求项目为了凑比例而增加文字,而是一个经验观察:一个能够长期交给Agent建设的项目,通常需要写下与代码规模相匹配的产品目标、工程规则、实际修改和验证结果。过期、重复或没有实际用途的文档同样应该整理,文档数量从来不是目标。

3.同一类信息只在一个位置完整维护

文档变多以后,真正危险的问题往往不是“没有文档”,而是“有两份都像正确答案的文档”。

因此先明确每类信息由哪里负责:

想知道什么 先到哪里找
发现了什么问题、现在准备怎样处理 ISSUE台账和必要的问题详情
为什么要改变产品、想得到什么结果 REQ
系统现在应该怎样工作 系统、能力和横切设计
这一轮准备做什么、实际发生了什么 对应ACL、DFL或ERL记录
某个正式版本实际交付了什么 版本与发布说明
环境现在运行什么、怎样恢复 环境记录

其它文档需要这些信息时,只保留帮助当前读者理解的摘要,再链接到负责该信息的位置。不要复制一份长期需要手工同步的第二正文。

如果代码和已经确认的设计不一致,也不能简单地说“代码才是真相”。先判断是实现没有做到设计,还是设计已经需要改变,然后走对应流程。

4.编号解决“这是谁”,状态解决“现在能不能用”

标题和文件路径会变化,长期对象需要稳定身份。当前项目使用例如:

  • STD-:规范;
  • REQ-:需求;
  • SYS-CAP-CRS-:系统、能力和横切设计;
  • ADR-IDX-:重要决策记录和设计索引;
  • ISSUE-:持续跟踪的问题;
  • ACL-DFL-ERL-:实施Loop。

编号一旦使用就不回收、不分配给另一件事。标题可以调整,文件也可以在规则允许时移动,但引用的身份保持稳定。

文档状态回答另一个问题:这份内容目前处于什么阶段。

  • Draft:仍在整理;
  • ProposedReview:已经提出或进入评审;
  • Accepted:规范、产品或设计已经确认,可以在声明范围内采用;
  • Completed:计划、记录或正式版本已经执行结束;
  • Superseded:已经被更新内容替代,保留用于追溯。

不同对象还可能有自己的业务状态,例如REQ有候选已选中已排期,Loop有ReadyIn ProgressReviewCompleted。不要把文档状态和对象状态混成一个字段,也不要从Completed推断结果一定没有遗留问题。

5.链接让后来的人能够从任何入口继续追踪

编号告诉我们“是哪一项”,状态告诉我们“现在能不能采用”,链接则告诉我们“为什么出现、由什么实现、后来去了哪里”。

一项产品变化常见的关系是:

1
2
3
4
5
6
7
问题或反馈
→REQ
→受影响的设计和必要ADR
→ACL、DFL或ERL
→实施和验证证据
→产品版本
→Git标签

这不是要求所有工作都必须经过这些对象,而是说明一旦对象存在,它们之间应该能互相找到。

链接也能减少重复。例如发布说明只需要概括用户能感知的变化,并链接版本总览和实施入口;它不需要再次复制几十条测试输出。

6.Git保存文档结论怎样变化

当前项目把文档和代码放在同一个Git仓库中。设计、实现和测试在同一项工作中变化时,它们能够通过提交和差异保持对应。

当前设计文档应直接表达现在应该怎样工作,不要不断在正文中堆叠“之前如何、后来又如何”。普通变化由Git历史保留;一项重要决定被替代时,才使用ADR或历史记录解释为什么变化。

实施记录和环境证据则不同。它们保存的是当时真实发生的事情,失败候选、跳过项和实际限制不能为了让最终故事更漂亮而回头改写。

7.自然语言负责解释,统一字段负责让工具检查

背景、取舍和原因适合用普通中文说明;编号、状态和关系如果完全依靠工具从自然语言猜测,很容易出错。

所以当前项目同时保留:

  • 面向人的正文;
  • 文档开头的统一字段;
  • ISSUE、REQ和Loop登记表;
  • 少量JSON等结构化数据,例如设计要求追踪账本;
  • 由结构化数据生成的可读视图。

结构化不等于把所有文档改成表格和JSON。只有需要自动检查、同步或长期引用的信息才进入结构化字段;真正的背景、规则和理由仍然应该写成正常正文。

8.把机械检查交给仓库工具

当编号、状态和链接已经成为项目规则,重复检查适合交给工具:

  • pnpm docs:check检查文档结构、编号、状态、路径、链接和追踪关系;
  • pnpm trace:render根据设计要求账本重建设计要求视图;
  • ISSUE工具负责分配问题编号并维护外部关系;
  • Loop工具负责创建ACL记录,并按允许的状态变化同步登记表和文档。

工具只能判断格式和关系是否一致,不能决定需求值不值得做、设计是不是合理,也不能代替Director确认Loop结论。

9.文档和代码在同一项工作中保持一致

文档不应该总在代码完成几周以后再补。更可靠的做法是:

1.实施前,REQ和已经确认的设计已经能说明目标和边界;
2.实施中发现设计与现实冲突时,先说明差异,再决定修实现还是回到设计;
3.接口、事务、迁移、错误或其它长期技术约定发生变化时,同步更新负责该结论的能力设计或横切设计;
4.实际提交、测试、失败、跳过和剩余问题随工作写入实施记录;
5.环境发生变化时更新环境记录;
6.得到需要的确认以后,再修改相应状态;
7.提交前运行文档和差异检查。

这不要求每改一行代码都新建文档。修复已经确认设计的局部缺陷,可以直接引用现有设计;不改变含义的错字和链接修正,也不需要制造REQ或Loop。更新哪些文档,只看这项工作真正改变了什么。

10.用“收藏会话”看这些文档怎样配合

假设Director确认员工需要一种方式重新找到重要会话。

REQ先说明员工当前遇到的问题、期望结果、非目标和验收场景。设计再说明收藏属于谁、员工如何操作、失去访问权时怎样处理,以及数据、接口和权限如何实现。

ACL启动时引用这些已经确认的内容,保存本轮起点、范围和验证方法。实施过程中,代码和测试证明实现结果,实施记录保存真实修改和失败。需要实机验证时,环境记录说明当时到底部署了什么。最后如果这项变化进入正式版本,版本记录保存实际纳入范围并由Git标签固定。

这个例子说明的不是“一个功能必须写多少份文档”,而是不同问题由不同文档回答,并且可以沿链接互相追踪

11.文档建设是一项持续工程

第一次整理文档时,需要建立入口、明确职责并处理明显冲突。之后每项工作只在真正受影响的位置持续维护,而不是几个月以后再集中补写、重新猜测当时发生了什么。

一套文档真正可用的标准很简单:新的Director或Agent从总入口开始,能够找到当前需求和设计,区分进行中与已结束的工作,看到环境当前状态,并追溯正式版本和验证依据。

这些是ACDL能够长期运行的基础。下一章将进一步说明,一项需求怎样从这里进入完整研发流程。

ACDL研发流程系列第2篇,共15篇。

上一篇:ACDL研发流程01:认识ACDL以及为什么需要新的研发体系

下一篇:ACDL研发流程03:像维护代码一样建设文档

项目刚开始时,先验证方向

一个项目刚开始时,Director可能只有一个模糊想法:某类用户遇到了一个问题,现在的软件似乎解决得不好,新技术也许能够提供一种不同做法。此时连产品是否值得做都还不确定,立即建立完整需求、设计、版本和交付记录,只会让尚未验证的猜测看起来像已经确认的需求和设计。

冷启动要做的,是用尽可能低的成本回答三个问题:

1.我们是否正在解决一个真实且值得处理的问题?
2.我们想到的核心做法是否可行?
3.我们能否做出一个有人愿意真正使用的最小结果?

这一章是ACDL之前的冷启动教程,不属于ACDL的强制流程。它的终点不是“产品已经设计完成”,而是得到一个方向清楚、可以运行、值得继续建设的项目骨架。

先把需求说清,不要急着设计答案

不过度设计,不等于带着一句模糊口号就让Agent写代码。如果Director说不清准备为谁解决什么问题,Agent只能自己补全产品目标。它也许能很快生成一个界面完整的系统,但这个系统很可能没有真正用户。

开始实现前,Director至少要能用普通语言说清:

  • 谁会遇到这个问题;
  • 他当时想完成什么任务;
  • 现在为什么难以完成;
  • 什么最小改变能让他得到实际价值;
  • 用什么现象判断方向值得继续;
  • 当前已经确认什么,还在猜什么。

这些问题要清楚,但答案不必一次完整。例如,Director可以确定“企业员工希望用自然语言让智能体完成一项重复任务”,但暂时不决定最终要支持多少类工具、怎样编排多个Agent、是否提供插件市场。前者是决定要验证什么,后者是在证据出现前就提前设计未来。

用对话把脑中的想法说出来

冷启动时,可以把Agent当作一个随时讨论想法的伙伴。Director不必先写出完整方案,可以直接讲自己看到的问题和初步想法,让Agent帮助追问、重述和比较不同做法。

这时不需要准备一个巨大而完美的Prompt。多聊几轮,每次说清一个问题,发现Agent理解不对就马上纠正。最终目的不是让Agent替Director作决定,而是帮助Director说清需求,找到下一件最值得验证的事。

善用语音对话

当Director脑中已经有很多背景,但还没有组织成一份书面材料时,语音往往比键盘更适合快速说出和展开想法。具备语音能力的对话工具可以用来追问、头脑风暴和边说边修正想法。Director可以要求Agent先听完背景,再逐个提问;也可以在听到错误理解时立即打断并纠正。

语音会话结束后可以回看聊天中的文本,但转写不一定与当时说过的每句话完全一致。因此,不要把整段语音转写直接当作需求文档。对话结束时,可以让Agent整理出“问题、已确认事实、当前假设、候选方向、下一步验证”,再由Director亲自删改和确认。

让工具选择服从当前问题

冷启动的大部分对话不需要一次给出最终答案。日常发散、用户场景梳理和候选方向比较更看重对话连续,复杂架构、安全边界和高成本选择则需要更充分的调查与推理。使用什么工具或模型,应根据当前问题、可用能力和风险决定。

无论使用什么工具,重要结论都要回到可核对的事实。对话可以帮助形成候选方向,但不能替代PoC、真实使用、代码验证或Director确认。

从PoC到MVP,再到项目骨架

对话能够帮助Director改进问题,但不能证明一个想法可行。一旦当前最需要验证的问题已经清楚,就让Agent做出可以运行、能够验证想法的最小结果。

PoC、MVP和项目骨架不是三道必须严格依次审批的流程。一个熟悉的技术方向可能不需要单独PoC,一个复杂想法也可能需要多个相互独立的PoC。它们表示的是三种不同的问题。

用PoC验证最大的不确定性

PoC是Proof of Concept,即概念验证。它只需要回答一个对方向有决定作用的问题,例如:目标模型能否稳定识别特定业务指令,某个企业系统是否提供必需的接口,或者一条实时交互链路能否达到可接受的延迟。

为了尽快得到答案,PoC可以临时写死数据,可以只在本机运行,也可以没有完整界面。它暂时不必具备正式产品所需的通用性、运维性和全部安全要求。但Director要清楚记住这些省略:PoC证明了一个概念可能成立,不代表它已经可以直接进入生产。

用MVP验证最小用户价值

MVP是Minimum Viable Product,即最小可行产品。PoC回答“某个关键想法能不能做到”,MVP则回答“最小的完整体验是否已经能给用户带来价值”。

MVP不是把所有功能都做到粗糙的半成品,也不是把几个PoC放在同一页面上。它需要选中一个真实用户和一项核心任务,让用户可以从开始走到结果。与这项任务无关的个性化、管理界面、扩展接口和高级配置,都可以暂时不做。

把有效结果整理成可以继续开发的骨架

当PoC已经证明关键做法可行,MVP也让Director看到了最小用户价值,就需要决定哪些临时结果值得保留,哪些应该删掉重做。不要因为原型已经能运行,就让所有临时代码直接变成长期基础。

一个可以继续开发的项目骨架,通常已经具备:

  • 明确的目标用户和核心任务;
  • 一条可以真正运行的端到端路径;
  • 已经选定并实际跑通的基本技术栈;
  • 能够安装、启动、运行最小测试的代码仓库;
  • 大致稳定的核心模块边界;
  • 已知限制、未验证假设和下一步决定。

骨架不等于空白的脚手架目录,也不等于已经完成的产品。它是一个有核心路径、有实际技术选择、可以让Agent继续读取、修改和运行的最小代码仓库。

什么不要提前设计

冷启动阶段最容易发生的偏差,是Director和Agent开始为尚未出现的未来编写大量结构。一旦话题变成通用插件体系、无限扩展、完整角色矩阵、多租户、微服务、多地容灾或全部平台组合,先回到当前用户和最小任务,问一句:现在有什么证据说明必须解决这个问题?

不要过度设计,也不等于所有决定都留给未来。会让PoC根本无法开始,或者后续更换成本极高的事情,仍然需要Director当场做出最小决定,例如核心数据归属、不能突破的安全边界、目标部署环境、基本技术栈和必须接入的外部系统。只决定当前试验必须依赖的部分,并清楚记下还没有决定的内容。

用一个例子走完冷启动

假设Director最初只有一个想法:“做一个能帮企业员工工作的Agent平台。”这句话无法直接指导实现,因为“帮助工作”可以包含几乎无限多种任务。

Director先通过语音和文字对话补充自己观察到的问题。几轮追问后,当前最值得验证的场景变成:一名企业员工在自己的私有工作空间中,通过对话要求Agent读取一份文件并生成摘要。系统暂时不解决多Agent协作、公共Skill市场、企业审批和多种业务系统接入。

第一个PoC只验证模型能否根据员工指令正确读取文件并返回有用摘要。它可以使用本地文件和临时脚本,不先建账号体系和完整界面。

PoC证明核心链路可行以后,MVP再提供最小的登录、对话、私有工作空间和结果展示,让一名真实员工可以完整走完这项任务。Director亲自试用,判断这条路径是否值得继续投入。

方向成立后,Agent清理只为试验服务的临时代码,保留真正有用的端到端路径,补上基本构建、测试和运行入口,形成可以继续开发的项目骨架。

这个例子只用于说明冷启动方法,不是当前项目的历史记录。

什么时候结束冷启动

冷启动没有一个固定天数,也不需要等到所有问题都有答案。出现以下情况时,项目通常已经值得结束快速试验,进入持续的工程化建设:

  • Director能够说清主要用户、核心问题和当前产品边界;
  • 至少一条核心使用路径已经可以真正运行;
  • 最重要的可行性假设已经由PoC或实际结果验证;
  • 基本技术栈、代码仓库和核心模块已经能够支持后续开发;
  • 下一批工作需要跨会话追踪,或者开始涉及多个并行任务;
  • 错误决定和实施偏离的返工成本已经明显上升。

按实际复杂度增加工程约束

项目结束冷启动以后,不需要立即套用完整ACDL,也不应只根据代码行数决定流程深度。更有用的判断是:一项决定是否已经难以撤回,工作是否需要跨会话继续,多个任务会不会互相影响,是否涉及安全、生产数据、环境发布或正式交付。

当一次对话已经难以掌握全部目标和历史决定时,就开始系统建设文档、明确验收场景并补齐自动化测试;当多项工作需要并行、错误决定的代价明显提高或准备形成正式版本时,再引入Loop、独立评审和版本验收。代码规模可以提醒复杂度正在增长,却不能替这些事实作决定。

无论代码行数是多少,都不要把全部聊天记录和临时代码原样留给后续Agent自己理解。Director需要与Agent一起整理当前确认的问题、产品边界、技术选择、已知限制和未决问题。下一章将说明这些内容怎样进入文档,并像代码一样持续维护。

ACDL研发流程系列第4篇,共15篇。

上一篇:ACDL研发流程03:像维护代码一样建设文档

下一篇:ACDL研发流程05:决定为什么要改变产品

多项工作同时发生时,需要共同的事实入口

当需求、实现缺陷、环境问题和评审发现同时存在,或者多个Agent并行工作时,Director面对的已经不是“怎样让Agent写完一个功能”这一个问题。此时,任何参与者都需要知道当前依据是什么、哪项工作正在改变什么,以及结果最终进入了哪里。

每个任务单独看都可能很小,组合起来却容易出现更大的问题:一项修改使用了过期设计,两个并行任务改变了同一个接口或数据规则,已经部署的代码没有经过真实使用,或者一个看似完成的版本仍然遗留阻断问题。

完整ACDL要解决的,是一项需求如何在这样的项目中保持方向、留下证据,并最终成为Director可以确认并负责的交付结果。是否需要完整流程取决于工作能否在一次短任务中可靠结束、风险大小和是否准备正式交付,不由代码行数机械决定。

本章继续使用“收藏会话”这个虚构例子。它只用于讲解流程,不是当前项目的实际开发记录。

先认识REQ(Requirement)、ISSUE和三种Loop

完整路线中会反复出现REQ、ISSUE、ACL、DFL和ERL。先说清它们各自保存什么,后面再看这些对象怎样连在一起。

REQ(Requirement)记录一项需求

REQ是Requirement的缩写,中文称为“需求”。在ACDL中,它特指一项需要持续追踪的需求,记录为什么要改变产品、希望得到什么结果,以及怎样判断需求已经满足。它不提前决定数据库、接口和代码结构。

ISSUE记录一个待处理问题

ISSUE与REQ不是同一件事。ISSUE保存一个需要跨会话处理的问题,记录问题从哪里发现、当前状态和下一步去向。它可以是实现缺陷、环境问题、尚未复核清楚的反馈,也可以是DFL或ERL中发现的问题。

如果已经可以确认要改变产品,可以直接登记REQ;如果还需要调查是实现缺陷还是新需求,先使用ISSUE保留问题。调查清楚后,恢复已经确认行为的实现缺陷可以进入ACL,需要改变产品的问题则进入REQ和设计。

ACL(Agentic Coding Loop)、DFL(Developer Feedback Loop)和ERL(Engineering Review Loop)是三种Loop

一轮Loop是一个有明确准备、执行、证据和结论的工作单元,不是指Agent在同一个Prompt里反复循环。ACDL在实施阶段使用三种Loop:

简称 全称 主导者 主要回答的问题
ACL Agentic Coding Loop Agent 是否已经把确认的设计变成代码,并通过相应的自动化验证
DFL Developer Feedback Loop 负责人 负责人使用固定候选完成真实任务后,这项变化是否真的好用
ERL Engineering Review Loop 独立Agent 检查固定提交、差异或版本后,是否发现正确性、安全、数据、测试或发布风险

“主导”表示谁负责推动这轮工作的主要过程,不表示由它独自完成,也不改变Director的决定权。Agent主导ACL中的实施和验证;负责人主导DFL中的真实使用和反馈;没有参与被评内容实施的Agent主导ERL中的独立检查。三种Loop都有自己的编号、范围、起点、记录和结束条件,都要保留实际发生的事,并由负责人确认结论。

每一种Loop都可以单独启动和结束,不要求另外两种Loop在之前已经完成或之后继续开展。Loop只是ACDL组织实施、真实使用和独立评审的方式,不是ACDL的同义词。

先看完整路线

一项需求进入正式版本时,主路线可以先简化为四个阶段:

1
2
3
4
5
6
真实问题或新想法
→1.需求管理:决定要不要改变产品
→2.产品与架构设计:决定改成什么样
→确定目标版本
→3.实施:按当前目的单独启动ACL、DFL或ERL
→4.版本验收与冻结:确认实际范围并创建Git标签

这条路线只是建立全局印象,不是一条只能向前的传送带。实施发现设计无法落地时,工作要回到设计;真实使用发现用户需要不同的行为时,工作要回到需求;独立评审发现实现缺陷时,则建立新的实施工作。

还有三个边界需要先记住:

  • ISSUE用于保留需要跨会话处理的问题,但不是每项需求的必经步骤。已经形成明确需求的想法,可以直接进入REQ。
  • 路线图只在多个候选需求需要比较顺序和依赖时使用,不是每项工作都要先写一份路线图。
  • 部署可以发生在实施中、真实使用前或正式版本完成后,因此环境发布可能出现在多个阶段,不单独算成一个主阶段。

第一阶段:需求管理,先决定为什么要改

Director发现,员工的会话越来越多,重要内容很难再次找到。此时已经可以确认需要一项新的用户行为,因此这个例子可以直接登记REQ,不为了让流程看起来完整而先制造一个ISSUE。

需求先说清四件事:

  • 问题:员工难以从大量会话中快速找回重要内容;
  • 期望结果:员工可以收藏自己有权访问的会话,之后能够容易地再次找到;
  • 非目标:本次不同时建设共享收藏、标签分类和智能推荐;
  • 验收场景:员工收藏会话后,刷新页面和重新登录仍能看到收藏状态,并能从列表中优先找到它;取消收藏后恢复普通显示。

这时不决定数据库增加什么表,也不因为某个界面容易实现就提前限定产品答案。Director先判断这个问题是否值得保留,再确认需求进入设计。如果尚无足够证据,需求继续留在候选中,不过早确定目标版本,让尚未确认的需求看起来像已经承诺交付。

第二阶段:产品与架构设计,找到负责当前答案的文档

当前项目按系统设计、能力设计和横切设计组织长期设计。它们是三类事实职责,不是每项REQ必须依次经过的三个阶段。Director和Agent先找到真正负责当前事实的文档,再检查相关的共同规则。

系统设计说明当前项目整体是什么

系统设计回答产品面向谁、整体提供什么、哪些事情不做,以及核心进程、存储和外部边界怎样组成。

“收藏会话”并不自动意味着系统设计需要修改。Director和Agent先检查这项需求是否改变产品整体范围或核心系统边界;没有改变时,就引用现有答案,不为了形式完整而重写。

能力设计把用户行为和实现边界放在一起

收藏会话主要改变Conversation能力,因此从受影响的能力设计开始。它需要回答:谁可以收藏,关系属于谁,用户从哪里操作,收藏后如何显示,无权访问或会话已删除时看到什么结果,以及数据、接口、事务、迁移和测试从哪里进入。

能力设计不按前端、后端或代码目录划分,也不是旧领域设计和模块设计的简单拼接。它围绕一项完整能力保存用户行为和长期实现约定,避免Agent在几份文档之间拼接同一个答案。

横切设计保存多个能力共同遵守的规则

员工隔离、数据所有权、接口错误和审计等规则如果由多个能力共同遵守,就从相应横切设计读取。只有这项需求确实改变共同规则时才修改;单一能力特有的决定仍留在能力设计中。

设计目录还包括ADR和IDX。ADR保存重要选择的背景、方案比较和代价,IDX保存设计地图、旧编号迁移和要求追踪;它们都不代替当前设计正文。旧PLAT / DOMAIN / MODULE只用于历史追溯,活动设计使用SYS / CAP / CRS

设计的目的是让Agent有一份可以实施的当前答案,而不是在写代码前猜完所有细节。如果一项不确定性必须用代码证明,可以在明确范围内做可以清理的技术原型,但原型不能自动变成产品承诺。Agent可以调查代码、比较方案和指出风险,产品行为、权限、数据和长期技术边界仍然由Director确认。阻断问题解决之后,受影响的设计进入Accepted,才可以作为Agent按设计修改代码的依据。

从设计进入实施:确定目标版本

当设计已经确认,Director准备将这项需求放入一次交付时,才为REQ确定目标版本并把它置为已排期。目标版本只表示当前准备为哪个版本工作,不表示这项功能已经交付。

第三阶段:实施,按当前目的选择一种Loop

ACL、DFL和ERL不是一条固定流水线,也没有谁必须放在谁后面。Director根据当前要解决的问题单独启动其中一种:把已经确认的设计变成代码时使用ACL,了解现有产品是否好用时使用DFL,独立检查一份固定代码或版本时使用ERL。

一项新需求通常会因为需要实施而启动ACL,但这不表示随后必须开展DFL和ERL。反过来,Director也可以直接对正在使用的产品启动DFL,或者直接对现有代码和版本启动ERL,无需先有一轮ACL。某种Loop发现问题后,先把问题作为REQ或ISSUE另行处理;原Loop不因此延长,三种Loop也不因此组成一条流程。

ACL(Agentic Coding Loop):实施已经确认的改变

ACL由Agent主导。Agent依据已经确认的需求和设计推进编码、测试、记录和问题排查;Director负责确认目标、边界以及本轮最后是否可以结束。

对“收藏会话”这项新需求,当前目的是把已经确认的设计变成代码,因此启动ACL。开始前,大目标被拆成能够独立完成和验证的任务,每项任务可以建立一轮ACL,由Agent完成实施和自动化验证。

如果收藏功能的范围不大,最简单的做法是用一轮ACL完成从界面、接口到存储和测试的端到端结果。如果范围已经大到一轮难以检查,再按可以独立验证的用户结果拆分。例如:

  • 一轮让员工能够收藏和取消收藏,并在刷新和重新登录后保留状态;
  • 一轮让员工在大量会话中优先看到和快速找回收藏内容。

每一轮都要跨越完成该结果所需的代码层,不把同一个结果拆成“前端Agent”、“后端Agent”和“测试Agent”共享一个模糊任务。上述两轮如果存在依赖,就按顺序开展。项目需要并行时,让其它Agent处理边界清楚的独立任务;存在文件冲突风险时,再为任务建立独立worktree。

每轮ACL在编码前先登记编号,记下工作来源、起点提交、目标、非目标、设计依据、执行范围、验证方法和停止条件。这些内容组成本轮的启动方案,用来防止Agent在实施中丢失目标。

Agent从记录清楚的基线提交和工作树开始,读取需求、已经确认的设计和本轮启动方案,再修改代码、文档和测试。它可以用很多个短循环实现和检查,但这些内部尝试仍然属于同一轮ACL。

在收藏功能中,自动化测试至少需要挑战本轮改变的风险:收藏是否可以保存和取消,刷新后是否保留,重复操作是否产生错误数据,一名员工是否无法收藏或查看他人的会话。测试要回答已经确认的行为,不是只追求数量和覆盖率。

实施记录随着工作追加内容,保存实际提交、测试命令与结论、使用的环境、失败和跳过项、方案变化、证据位置和剩余问题。不用最后的成功结果反过来改写开始时的计划,也不删除中间出现的失败。

如果实施只能通过改变已经确认的用户行为、权限、数据或架构边界继续,Agent要停下实现,说明冲突,回到受影响的设计进行评审。Agent不能为了让代码通过测试而自行重新定义产品。

代码完成、自动化测试通过或部署到开发环境,都不会自动结束本轮ACL。本轮范围、候选提交、验证证据、失败和剩余问题整理清楚之后,实施记录先进入Review。负责人确认结论后,还要把结果合入目标分支并记录实际合入提交,这轮ACL才进入Completed

DFL(Developer Feedback Loop):在真实使用中发现问题

DFL由Director主导。Director亲自操作和感受产品,判断它是否符合真实工作习惯;Agent可以帮助准备环境、记录过程和调查问题,但不能代替Director使用产品并给出反馈。

DFL用来了解产品在真实界面、账号、数据和操作过程中是否好用。它可以检查刚完成的变化,也可以单独检查已经运行很久的功能,不需要以某轮ACL为前提。

以收藏功能为例,Director使用真实账号和已有会话完成收藏、刷新、重新登录、取消收藏和再次寻找。这种使用可能发现,功能都能操作,但收藏内容在真实列表中仍然很难找到。DFL需要记下实际环境、操作过程、观察和感受,不以“找到的问题越多越好”为目标。

ERL(Engineering Review Loop):独立检查固定的提交、差异或版本

ERL由没有参与被评内容实施的Agent主导。独立性来自固定评审对象、清楚范围和没有参与原实施过程,而不是来自某个模型等级。原来主导ACL的Agent可以提供背景,但不能代替这次检查。

ERL用来检查产品与设计是否一致,以及代码在正确性、权限与数据、并发与恢复、测试和发布方面是否存在风险。它可以评审刚完成的代码,也可以单独审查现有提交或版本,不需要先完成ACL或DFL。

开始ERL前,负责人和评审Agent先固定完整提交、差异范围或Git标签,并写清评审范围、问题等级和结束条件。Agent据此开展独立检查,不根据一句“帮我看看代码”无限扩展。Agent或辅助工具给出的发现还要回到代码、设计、测试和运行证据复核,未经复核的推测不能直接算作已经确认的问题。

三种Loop各自结束,发现的问题另行处理

ACL、DFL和ERL各有自己的结束条件。一轮Loop完成,只表示这一轮约定的实施、使用或评审范围已经走完,证据已经整理,发现也有了清楚去向;它不表示其它两种Loop也已经完成,更不表示三种Loop必须补齐。

任何一种Loop发现的问题都需要先复核和分类,再决定去向:

1
2
3
4
5
6
7
8
9
10
11
12
需要跨会话处理、用于恢复已经确认行为的实现缺陷
→ISSUE

需要改变用户行为、权限、安全、数据或正式范围的发现
→REQ
→重新设计和确认

环境或运行问题
→环境记录和必要的ISSUE

重复发现或误报
→记录复核依据和不继续处理的原因

DFL开始前先记下实际使用的环境、制品、提交、角色和账号,ERL开始前先记下实际检查的提交、差异或标签;检查过程中都不直接修改这些内容。需要修改时,先在原记录中写下局部发现,再建立ACL处理。只有问题需要跨工作单元、跨会话、跨责任人或跨版本继续时,才登记全局ISSUE。修复完成后,DFL固定新候选并开始下一次尝试,ERL继续保留原基线上的发现。

第四阶段:版本验收与冻结,只纳入已经确认的结果

目标版本是工作目标,正式版本是已经验收的事实。两者之间不是等到日期后自动发生的状态变化。

准备版本验收时,Director核对本次实际准备纳入的REQ、ACL、DFL和ERL,而不是根据编号或早期关联关系自动把它们全部算进来。被选中的工作需要说清:

  • 需求的验收场景得到了什么结论;
  • 当前产品和技术设计是否已经确认;
  • 实际纳入了哪些提交和Loop结果;
  • 本版本实际采用了哪些自动化验证、真实使用或独立评审证据,没有开展的检查是否与本次风险所需的检查范围匹配;
  • 还有哪些未解决问题,它们是被修复、排除在本版本之外,还是由Director明确接受风险;
  • 发布说明是否准确表达使用者能够感知的新增、修复、限制和升级影响。

如果这些问题还没有可靠答案,版本继续保持Review。已经合并代码、部署到某个环境或者达到原定日期,都不能代替这次验收。

Director确认实际范围、验收结论、未解决问题和发布说明后,才创建指向对应提交的Git标签。标签、版本记录和发布说明相互一致之后,版本进入Completed,实际纳入的REQ才进入已完成

完整ACDL(Agent Collaborative Development Lifecycle)不等于所有工作都走全套

这个例子从新的产品需求一直走到正式版本,因此经过了四个主阶段。真实工作必须从它的实际起点进入:

  • 代码没有做到已经确认的设计,可以从ISSUE和ACL开始,不重新制造一项需求;
  • 不改变产品行为的工程维护,可以建立计划版本为未确定的ACL;
  • 已经稳定的小范围文档修正,可以在阅读现有依据和完成文档检查后结束;
  • 真实使用或独立评审可以为了了解当前系统单独开展,不必等待一个新版本。

“完整处理一项工作”通常表示走到这项工作自己的Loop结束条件,不表示Agent可以自行开启版本验收、将REQ改为已完成或创建Git标签。形成正式版本是另一个需要Director明确决定的目标。

完整ACDL表示项目知道每项工作应该从哪里开始,谁有权决定,Agent应该依据什么执行,怎样留下验证证据,以及在什么条件下可以结束。它不是用最长的路径处理所有小事。

在这条路线中,Director始终负责从需求到正式版本的关键决定:决定值得解决的问题,确认产品和技术边界,决定什么可以实施,根据真实证据确认每轮结论,并对最终版本负责。Agent可以承担大量调查、设计、实施、验证和评审工作,但不会因此接管Director的决定和责任。

后续章节将把这条完整路线拆开。下一章先讲一项真实问题怎样进入ISSUE或REQ,以及怎样走到能够指导Agent实施的已确认设计。

ACDL研发流程系列第5篇,共15篇。

上一篇:ACDL研发流程04:需求怎样走完整个ACDL

下一篇:ACDL研发流程06:共同完成产品与架构设计

Agent最容易在问题不清楚时显得高效

Agent很擅长把一句话迅速变成界面、接口和代码。问题是,如果这句话本身混入了未经确认的假设,Agent也会很快把错误方向做得像模像样。

例如,“给会话增加收藏按钮”听起来已经可以开发,但它没有说明员工遇到了什么困难,也没有说明收藏以后怎样帮助员工。直接从这句话开始,讨论很容易围绕按钮位置、图标和数据库字段展开,真正的问题反而没人再问。

进入设计之前,Director和Agent需要先回答两件事:现在到底发生了什么,产品是否准备作出改变。先弄清发生了什么,再决定产品要不要改变;已经想到的方案不能反过来冒充问题。

第一步:先描述发生了什么

问题描述要从使用现场开始,而不是从已经想到的功能名称开始。对于本章的例子,可以先写成:

员工的会话越来越多。需要再次查看一段重要内容时,员工经常要在列表中反复滚动和打开多个会话,仍然很难快速找到目标。

这段话还不是需求,但它已经说清了谁遇到问题、当时想完成什么任务以及现在受到什么阻碍。接下来可以继续补充:这种情况出现得多不多,哪些员工受到影响,搜索和最近使用是否已经解决了一部分问题,以及我们掌握的是实际观察还是猜测。

Director不需要独自完成调查。Agent可以查看当前产品和代码,整理已有反馈,复现现象,找出相似功能,也可以追问描述中的空白。但Agent此时产出的是调查材料,不是替Director作出的产品决定。

一个有用的问题描述通常能让读者看出:

  • 谁在什么情况下遇到了困难;
  • 当前实际发生了什么;
  • 问题造成了什么影响;
  • 哪些内容已经确认,哪些仍然只是推测;
  • 为什么这件事值得继续处理。

不需要跨会话保留的一次性观察,可以继续留在当前讨论中。问题需要以后继续调查、交给其它Agent处理,或者需要长期保留来源和去向时,再为它分配ISSUE编号并登记。

第二步:判断是ISSUE还是REQ(Requirement)

ISSUE和REQ保存的不是同一种东西。ISSUE保存一个需要继续处理的问题,REQ保存一项已经确认需要改变产品的需求。

最实用的判断方法,是看“处理完成后,当前已经确认的承诺会不会改变”。这里的承诺来自已经确认的设计,不是来自代码恰好怎样运行。

1
2
3
4
5
6
7
8
9
10
已经确认需要改变用户行为、业务规则、权限、数据边界或正式范围
→登记REQ

还不知道是实现缺陷、新需求还是环境问题
→先登记ISSUE并调查

代码没有做到已经确认的设计
→这是实现问题
→需要跨会话追踪时登记ISSUE
→问题和范围已经清楚时可以直接准备ACL

如果员工目前只是偶尔找不到会话,还不确定问题来自列表错误、搜索失效还是缺少新的产品行为,就先登记ISSUE。ISSUE记录发现时间、环境、操作、期望结果、实际结果、影响、证据和下一步,让后续Agent不必重新猜测问题从哪里来。

如果已经确认产品需要提供一种新的方式,让员工主动标记并重新找到重要会话,就可以直接登记REQ,不需要为了流程完整先制造一个ISSUE。REQ是Requirement的缩写,它负责追踪为什么改变产品、希望得到什么结果以及最终进入了哪个正式版本。

ISSUE调查结束后可能有不同去向:实现偏离已有设计的问题进入实施;需要改变产品的问题转为REQ;环境问题进入环境处理;重复、误报或不再处理的问题保留判断依据后结束。ISSUE不是较小的REQ,REQ也不是换了名字的ISSUE。

第三步:把REQ(Requirement)写到Director能够决定是否继续

REQ的目标不是让Agent马上写代码,而是让Director能够判断这项改变是否值得进入设计。正文先写清四件事:问题、期望结果、非目标和验收场景。

以“收藏会话”为例,可以这样表达:

  • 问题:员工难以从大量会话中重新找到重要内容;
  • 期望结果:员工可以标记自己有权访问的重要会话,之后能够容易地再次找到;
  • 非目标:本次不同时建设共享收藏、标签分类和智能推荐;
  • 验收场景:员工收藏会话后,刷新页面和重新登录仍能看到收藏状态,并能从列表中优先找到它;取消收藏后恢复普通显示。

这里故意没有决定使用新的数据表还是已有字段,也没有规定接口路径和前端组件。REQ描述产品为什么改变和成功以后能观察到什么,具体实现留给后面的设计。

验收场景也不是一句“功能开发完成”。它要让Director能够实际操作,让Agent能够据此设计测试。例如,重新登录后收藏状态是否保留是一项可观察结果;“接口已经实现”只能证明存在一段代码,不能证明员工的问题得到解决。

需求从出现到进入设计,通常会经过以下状态:

1
2
待评估 →候选 →已选中
↘不采纳

待评估表示刚刚登记,还没有判断是否值得保留;候选表示问题值得继续考虑,但现在不一定投入;已选中表示Director确认可以开始产品与架构设计。多个候选需要比较顺序和依赖时,再使用路线图;一项明确需求不需要为了形式完整先写路线图。

需求被选中时还不确定目标版本。设计可能发现新的依赖、风险或不可行之处,过早排期只会把一个尚未理解清楚的想法包装成承诺。等设计得到确认以后,再决定是否交付以及放入哪个目标版本。

REQ的需求状态和Markdown文档状态表达两件不同的事。候选已选中说明需求走到了哪里;DraftReviewAccepted说明一份文档是否已经可以采用。不要用“设计中”“开发中”作为需求状态,也不要因为REQ正文已经写得完整,就宣称需求已经排期或完成。

GitHub Issues怎样与本地ISSUE联动

到这里,需求管理的核心判断已经讲清:先理解真实问题,再决定使用ISSUE继续调查,还是使用REQ确认一项产品变化。GitHub Issues解决的是另一个问题——怎样让不了解当前项目文档目录的人提交反馈,并在熟悉的讨论和看板入口中看到进展。

GitHub Issues适合接收反馈、继续讨论和查看工作进展。项目外部的参与者可以直接提交看到的现象、复现步骤和期望结果,Director和Agent也可以在其中补充调查线索。

但GitHub Issue不是ACDL中负责维护编号和状态的正式记录。它的标题、正文、标签和打开状态都可能被人工修改,也不能完整表达问题与REQ、ACL、DFL、ERL、版本和环境记录的关系。当前项目仍然以docs/03-实施/ISSUE/README.md中的本地ISSUE台账保存正式编号、状态、严重程度和处理去向。

两者建立关系后各自保留自己的作用:

1
2
3
4
5
GitHub Issue
→接收原始反馈、开展讨论、提供看板入口

ISSUE-六位编号
→保存正式编号、当前状态和后续去向

不是每个本地ISSUE都必须创建GitHub Issue。只在GitHub入口有助于收集反馈、开展讨论或展示进展时建立关联。反过来,GitHub上的普通反馈也不自动成为本地ISSUE;能够在当前讨论中直接判断和处理的内容,无需为了同步而分配编号。

从GitHub新反馈建立本地ISSUE

新建的GitHub反馈可以先使用status:待登记标签。这个标签只表示它还没有通过本地ISSUE登记判断,不是ACDL新增的一种正式问题状态。

Director或Agent先阅读反馈,确认来源、现象和已知事实。如果问题需要跨会话复现、调查、决定或处理,再用issue:import为它取得本地编号。先使用--dry-run预览准备写入的文件和编号:

1
2
pnpm issue:import -- --github=42 --repository=example-org/acdl-project --category=实现缺陷 --severity=S2 --dry-run
pnpm issue:import -- --github=42 --repository=example-org/acdl-project --category=实现缺陷 --severity=S2

导入会保留GitHub原始反馈,把它作为问题来源,并在本地ISSUE台账中记录一对一的外部关系。分类和严重程度仍由复核事实决定,不直接照搬提交者的选择。

如果复核后确认它是重复反馈、不属于本项目,或者可以在当前会话内直接处理,就在GitHub中说明判断,不为了让工具产生结果而导入本地。

关联两边已经存在的问题

有时问题已经先在DFL、ERL、环境记录或当前开发中取得本地ISSUE编号,后来才出现对应的GitHub Issue。这时不再导入第二个本地问题,而是把两个已有编号关联起来:

1
2
pnpm issue:link -- --id=ISSUE-000036 --github=42 --repository=example-org/acdl-project --dry-run
pnpm issue:link -- --id=ISSUE-000036 --github=42 --repository=example-org/acdl-project

一个本地ISSUE只能关联一个GitHub Issue,一个GitHub Issue也不能同时代表多个本地ISSUE。发现重复入口时,先确定哪个本地ISSUE负责保存正式编号和处理结论,再把其它入口标记为重复并指向它。

关联操作只建立编号之间的关系,不会因为GitHub Issue已经关闭就把本地问题改成已关闭,也不会用GitHub标签覆盖本地分类和严重程度。

从本地ISSUE单向同步到GitHub

建立关联以后,本地ISSUE台账继续由Director和Agent根据调查、实施与验证事实更新。GitHub用于显示结果,不反向决定本地状态。

需要检查两边是否一致时,先运行不带--apply的同步命令。它只报告差异,不修改GitHub:

1
pnpm issue:sync -- --repository=example-org/acdl-project

确认差异符合预期后,再明确使用--apply更新GitHub:

1
pnpm issue:sync -- --repository=example-org/acdl-project --apply

同步会把本地ISSUE编号写入GitHub标题,更新正文中的受管理摘要和根据本地状态自动生成的标签,并根据本地ISSUE是否已经结束打开或关闭GitHub Issue。已关闭映射为已经完成;不处理重复映射为不计划处理;其它本地状态保持GitHub Issue打开。

GitHub提交者的原始反馈正文和人工添加的分类标签会继续保留。同步只修改明确由仓库管理的内容,不把整个GitHub正文重写成本地台账副本。GitHub中的手工关闭、重新打开或改标签也不会反向改写本地事实。

本地ISSUE台账和同步工具的变化进入main后,Sync GitHub IssuesWorkflow会读取仓库内容,执行同一套单向同步。这个Workflow只获得修改GitHub Issues所需的权限,不会修改仓库文件,也不影响代码质量检查。

同步失败只表示GitHub展示可能落后。本地ISSUE的编号、状态和处理关系仍以仓库中的台账为准。

需求管理结束在哪里

这一阶段结束时,Director确认的不是实现方案,而是“这个问题值得进入产品与架构设计”。REQ进入已选中,表示问题、期望结果、非目标和验收场景已经足以支持下一步讨论;它不表示技术方案已经确定、目标版本已经承诺或Agent可以开始编码。

1
2
3
4
5
真实问题或反馈,包括需要持续处理的GitHub反馈
→判断是否需要长期追踪
→使用ISSUE调查,或者直接登记REQ
→Director决定候选是否进入设计
→REQ进入已选中

下一章从这项已经选中的REQ开始,说明怎样在系统、能力和横切设计中找到负责当前答案的位置,并把产品行为和技术方案整理成可以一致指导实施的设计。

ACDL研发流程系列第7篇,共15篇。

上一篇:ACDL研发流程06:共同完成产品与架构设计

下一篇:ACDL研发流程08:让多个Agent在不同worktree工作

已经确认的设计还不是Agent可以直接执行的任务

经过需求管理和产品与架构设计,Director和Agent已经知道为什么要改,也共同确认了系统应该怎样工作。但一份已经确认的设计通常会同时涉及多个用户结果、代码模块和验证方式,它说明的是系统长期应该怎样工作,不是当前这一轮工作的大小。

如果只对Agent说“按设计把收藏会话做完”,它需要自己决定从哪里开始、这一次做到哪里、先处理哪些风险,以及什么证据才能说明已经完成。任务过大时,Agent可能在长时间实施中丢失目标;任务过碎时,又会留下一组单独通过测试、合在一起却不能工作的局部结果。

启动ACL之前的任务,就是把已经确认的设计变成一个或几个边界清楚、能够独立验证的实施目标。

先认识ACL(Agentic Coding Loop)

ACL的全称是Agentic Coding Loop,是由Agent主导的开发Loop。Agent读取已经确认的需求和设计,调查当前代码,实施改动,补充测试,运行验证,并记录真实结果。Director负责确认本轮的目标和边界,处理需要人作出的取舍与授权,并在最后判断这轮工作能否结束。

一轮ACL不是一次Prompt,也不是一个Git提交。Agent可以在其中经历很多次“调查—修改—测试—讨论”的短循环,也可以产生多个逻辑清楚的提交。只要这些工作仍在完成同一个独立目标,就没有必要为每一次Agent对话或每一个代码步骤新建ACL。

ACL也不是ACDL的缩写。ACDL是当前项目完整的研发体系,ACL只是其中把已确认改变变成代码和自动化验证的一种Loop。

第一步:判断是否真的需要拆分

拆分不是默认动作。如果一项改变范围不大,Agent能够在一轮能够持续理解的范围内完成端到端实施,而Director也能一次看懂完整差异和验证结果,用一轮ACL完成往往最清楚。

当出现以下情况时,才需要考虑拆成多轮ACL:

  • 一轮工作包含多个可以分别使用、分别验收的结果;
  • 任务大到Agent难以在一份启动方案和当前摘要中持续保持准确上下文;
  • 部分改动的数据、安全、迁移或发布风险明显不同,需要分开验证和停止;
  • 前一个结果能够形成已经确认、并且在并行期间不会变化的接口或数据结果,后一个结果可以从这个新起点单独开始;
  • 不同结果确实可以由不同Agent独立推进,无需彼此等待尚未定稿的结论。

文件多、预计代码行数多或可以分给多个Agent,都不是单独的拆分理由。先看能否形成可验证结果,再谈任务数量。

第二步:按结果拆分,不按代码层拆分

一个好任务要能回答:完成以后,系统新增了什么可以被证明的结果?

以收藏会话为例,如果完整改动在一轮ACL中仍然容易理解和验证,可以直接实现:

员工可以收藏和取消收藏自己有权访问的会话,重新登录后收藏状态仍然保留,并且能够在会话列表中找回它们。

如果这个目标已经太大,可以拆成两个用户结果:

1.员工可以收藏和取消收藏自己有权访问的会话,收藏状态能够持久保留。
2.员工可以在大量会话中筛选收藏内容,失去访问权或已删除的会话不会由此重新暴露。

这两项有明确依赖:第二项依赖第一项已经形成稳定的收藏含义和数据结果,因此可以拆开,但不应为了并行而同时开始。

下面这种拆法看上去容易分工,却不是三个可独立验证的任务:

  • 一个Agent只建表和写数据访问;
  • 一个Agent只写接口;
  • 一个Agent只做页面按钮和交互。

每一部分都要等待其它部分才能证明用户结果,契约还可能在三个Agent实施时继续变化。这些更适合成为同一轮ACL中的实施步骤,由一个Agent维持端到端上下文。

第三步:先想清楚怎样验证,再决定任务怎样拆

“可以独立验证”不是要求每个任务都能单独发布给用户,而是在它结束时,Director和Agent能够用实际证据判断目标是否达成。检查一个候选任务时,先试着写出它的验证方法:

  • 什么正常结果能证明它已经完成;
  • 哪些失败、权限、并发、数据或恢复风险必须用测试或实际操作检查;
  • 用单元、契约、集成、迁移、构建、浏览器或实际环境中的哪些方法取得证据;
  • 完成后留下的结果能否作为下一项工作的可靠起点。

如果一个任务只能写成“完成后与其它任务一起验证”,它很可能只是一个实施步骤。如果一个任务要同时使用十几种验证方式,而任何一组失败都会把整轮工作拉回起点,则需要再看它是否包含多个可分开的结果。

有些工作没有立即可见的用户界面,也能独立验证。例如一次数据迁移可以用输入拒绝、前后数据对照和回退演练证明,一项不改变对外行为的主线维护可以用定点测试和完整检查证明。重点是结果能被判断,不是每个任务都要变成一项新功能。

第四步:登记ACL,分别记录身份和版本关系

对于一项新需求,设计确认以后,Director还要决定是否准备实施,以及它当前准备服务哪个目标版本。确定后,REQ填写目标版本并进入已排期。目标版本只表示当前准备把这项工作放入哪次交付,不表示它已经完成,也不是不可改变的承诺。

之后,每个准备开始的独立任务登记一轮ACL。现行ACL统一使用ACL-六位编号。编号只表达身份,一经使用不回收、不复用;计划版本和实际纳入版本另用字段记录。排期变化时更新版本关系和原因,不修改ACL编号,也不为同一轮工作机械重建ACL。

当前项目提供命令帮助分配下一个ACL编号,同时新建登记表条目和实施记录:

1
2
pnpm loop:new -- --version=未确定 --title=主题 --source=工作来源 --goal=本轮目标 --dry-run
pnpm loop:new -- --version=未确定 --title=主题 --source=工作来源 --goal=本轮目标

启动内容已经准备好、但尚未发生第一次真实执行时,可以增加--ready创建为Ready;不加时会创建为In Progress并记录开始时间。命令只负责生成编号、登记入口和文档骨架,不会替Director判断需求是否已排期、设计是否已确认,也不表示Agent已经获得超出已有边界的授权。--mainline--with-plan已经移除,不应再使用。

第五步:在编码前写好启动方案

启动方案是这轮ACL的工作说明,用来防止Agent在长时间实施中逐渐忘记原始目标。它不需要预测每一处代码改动,但需要让新会话或接手的Agent不依赖原对话也能回答以下问题:

  • 这轮工作从哪项REQ、ISSUE、设计偏差或工程缺口而来;
  • 从哪个分支和完整Git提交开始,开始时已有工作树是什么状态;
  • 本轮要得到什么结果,哪些相关内容明确不做;
  • 以哪些已经确认的设计、ADR,以及环境当前运行的提交、配置和服务状态为依据;
  • 允许改动什么,需要使用哪些数据库、端口、容器、账号或其它外部资源;
  • 准备怎样实施和验证,遇到什么情况必须停下来;
  • 什么证据齐全后才能认为本轮达到完成条件。

非目标要写具体。例如“本轮实现员工个人收藏,不实现收藏文件夹、团队共享和全局搜索”,就比“不扩大范围”更能阻止Agent顺手增加未经设计的功能。

实施步骤可以使用S1S2等稳定编号。每一步写明前置条件、实施范围、完成判定和失败时怎样处理,方便在上下文压缩或新会话中继续。这些步骤是一轮ACL内的进度节点,不会因为有编号就自动变成新的ACL。

每轮ACL默认只有一篇主记录,启动方案、当前摘要、实施与验证、剩余问题和结论依次写在其中。启动方案在第一次真实执行后视为快照;后续变化追加原因和影响,不把最后结果反写成原计划。只有确实需要在执行前单独批准高风险或恢复边界时,才另建计划,不因任务复杂机械拆成两套状态。

第六步:让新会话能够继续当前任务

启动ACL时,不要把过去所有聊天记录和整个文档目录不加选择地丢给Agent。有用的上下文应当让它知道当前决定、真实现状和下一个动作:

1.读取本轮启动方案,确认目标、非目标、停止条件和完成条件。
2.读取相关REQ、已经确认的设计和必要ADR,理解产品行为与技术边界。
3.读取仓库对Agent的工程要求,再定位实际代码、测试、迁移、构建和发布入口。
4.核对当前分支、起点提交、工作树差异和需要使用的外部资源。
5.用自己的话复述本轮目标和预计路径,显示出它对任务的真实理解。

如果Agent不能说清本轮结束时应该看到什么结果,或者现场的Git状态与启动方案不一致,就先查明原因,不立即实施。这一步不是考试Agent,而是在编码前尽早暴露上下文缺口。

什么时候才算ACL已经启动

一轮ACL真正开始时,不只有一个编号,而且具备以下事实:

  • 工作来源和需要遵守的设计依据已经明确;
  • 计划版本已经写明,尚未确定时如实填写未确定
  • 本轮的主记录、启动分支、不会变化的起点提交和已有工作树状态可以追溯;
  • 目标、非目标、实施范围、验证方法、停止条件和完成条件已经写入启动方案;
  • Agent已核对上下文、当前工作树和外部资源,知道下一个要执行的动作。

其中任何一项缺失,就继续补齐准备,不用“先让Agent开始写,后面再补文档”掩盖起点不清。进入这个状态以后,Agent才从第一个实施步骤开始主导这轮ACL。

回头检查这条路径

1
2
3
4
5
6
7
8
已经确认的设计
→Director决定实施和目标版本
→REQ进入已排期
→按可验证结果确定一轮或多轮ACL
→登记ACL并记录起点提交
→写好启动方案
→Agent核对上下文、当前工作树和外部资源
→从第一个实施步骤开始ACL

拆分的目的不是让登记表出现更多编号,而是让每轮工作都有Agent能够持续理解的范围和可以判断的结果。一轮ACL启动后,如果还有其它能够独立推进的任务,就可以进一步判断它们是否适合由多个Agent在不同worktree中并行开发。

ACDL研发流程系列第8篇,共15篇。

上一篇:ACDL研发流程07:把设计拆成可以独立验证的任务

下一篇:ACDL研发流程09:完成代码、验证并更新环境

多Agent不等于把同一个任务切成多份

Agent可以很快地读取代码和生成实现,所以多个Agent同时工作看上去是最直接的加速方式。但如果它们正在等待同一个未定稿接口,修改同一批文件,或者各自理解了不同的产品结果,并行只会把返工也同时放大。

当前项目并行的基本单位不是Agent,而是第7章已经拆好的独立任务。每项任务有自己的工作来源、ACL、目标、非目标、起点和验证结果,然后再交给一个主要Agent。不把数据库、接口、页面和测试分给几个Agent,让它们在同一项尚未定稿的改变中相互等待。

如果当前只有一项端到端任务,一个Agent保持完整上下文通常更快。只有出现两项或更多能够真正独立推进的工作时,才需要组织并行开发。

第一步:先确认这些任务能否并行

可以独立验证是并行的第一个条件,但还不够。Director和Agent还要看任务之间的依赖、文件交叉和外部资源。

两项任务通常适合并行,需要同时满足以下条件:

  • 它们不需要等待对方的未定稿结论,已知依赖要么已经完成,要么已经确认接口和数据格式在并行期间不会变化;
  • 它们的主要修改范围能够分开,少量共同文件也能预先说明谁先改、谁在集成时适配;
  • 它们可以使用不同的测试数据库、端口、容器、账号或证据目录,不会互相改写外部状态;
  • 需要隔离文件修改时,每项工作都能在自己的worktree中实施、测试、提交和记录;
  • Director已经知道谁负责最终集成,以及几项结果以什么顺序进入主线。

上一章把收藏会话拆成“保存收藏状态”和“筛选收藏内容”两个结果,但第二项依赖第一项,它们仍然需要串行。假如当前还有一项Runtime恢复缺陷和一项文档检查工具优化,而它们分别有自己的工作来源和验证方法,就可以与收藏会话同时开展:

1
2
3
4
同一个已确认起点
├─收藏会话ACL→worktree A→Agent A
├─Runtime恢复ACL→worktree B→Agent B
└─文档工具ACL→worktree C→Agent C

这里同时推进的是三项工作,不是三个Agent共同完成收藏会话。

如果两项工作同时改动一个核心契约,共用一个无法分离的真实环境,或者第二项的验证结果完全取决于第一项的实现,就先保持串行。不需要为了让Agent都有事做而制造并行任务。

第二步:需要文件隔离时,一项任务使用一个worktree

worktree是Git在同一个仓库上同时保留多个工作目录的方式。每个worktree检出自己的分支,Agent可以在其中查看、修改和测试文件,不会把未提交差异混到其它任务的目录里。

存在文件冲突风险时,推荐使用以下对应关系:

1
2
3
4
5
一项独立任务
→一轮ACL
→一个短期分支
→一个worktree
→一个主要Agent

分支、worktree和Pull Request都按实际需要使用。只做只读调查、修改范围完全不相交,或者当前Harness已经提供其它可靠隔离时,不为了形式机械创建。需要隔离文件差异时,主工作树保留共同起点,每个并行任务在独立worktree中开展。

分支名称可以由小写ACL编号和简短主题组成,例如acl-000039-conversation-favorites。分支跟踪的是工作而不是Agent身份,不要使用模型名或Agent名命名。

建立worktree前,先根据当前运行时确认是哪一种Harness。Orca、Codex或其它Harness已经提供原生worktree能力时,优先使用它的创建和交付入口;原生能力不可用或不适合当前任务时,才用Git命令作为后备,并选择稳定、可识别的非临时目录。无论由哪种工具创建,都先记下完整起点提交、分支和目录。

不同任务可以从同一个已确认提交开始,也可以根据已知依赖从不同提交开始。无论怎样选择,每轮ACL的启动方案都保存自己的分支、明确的起点提交和worktree路径,不用“从最新代码开始”这种无法复现的说法。

同一任务需要多个Agent时,可以串行接棒

并行规则解决的是多项独立任务怎样同时推进。另一种常见情况是,同一项任务先由ChatGPT整理需求或设计候选,再由本地Agent实施和验证,最后交给ChatGPT或其它Agent评审。它们处理的是同一轮工作,不需要为了参与者不同而拆成多个ACL,适合按阶段串行接棒。

本机Agent通常使用worktree取得完整文件、依赖和验证反馈;通过GitHub参与的远端Agent通常使用远端分支、提交和Draft Pull Request取得隔离空间。远端Agent是否能够写入,取决于连接器和仓库权限:能够写入时可以直接准备候选,只有读取能力时则提交分析或评审意见,由当前写入者落地。工具能力不同,不改变仓库事实源和Director确认边界。

同一分支由多个Agent接力时,推荐采用以下约定:

1.任一时刻只指定一个当前写入者,其他Agent只读或评审;
2.交接前提交并推送候选变化,记录完整HEAD提交;
3.接棒者先核对远端分支仍指向交接提交,再开始修改;
4.已经交接的共享分支不强制推送、不改写交接历史;
5.两个Agent要探索不同方案时使用不同分支,不在同一分支互相覆盖;
6.共同决定写回REQ、设计、ADR或Loop记录,Pull Request只保存差异讨论和交接摘要。

这些约定用于降低远端与本机协作中的竞态,不表示每项工作都必须创建Pull Request。只有一名Agent、没有远端评审或无需隔离时,继续使用原来的短路径即可。

需要反复交接时,可以在Draft Pull Request顶部维护一段简短的当前状态:

1
2
3
4
5
6
7
## 协作状态

- 当前阶段:需求、设计、实现、验证、评审或待确认
- 当前写入者:当前负责修改分支的人或Agent
- 当前候选:完整HEAD提交
- 下一接棒者:下一位参与者
- 下一步:一句话说明要完成的动作

每次正式交接再用Pull Request评论保留固定快照,至少说明基线、当前候选、正式依据、本轮目标和非目标、实际修改、已运行与未运行的验证、剩余风险和下一步。新会话先读取这段交接、正式文档和固定提交,不依赖上一段聊天记录恢复现场。

第三步:把代码之外的资源也分开

worktree隔离了文件目录、当前分支和未提交差异,但它们仍然属于同一个Git仓库,也仍然在同一台机器或同一套基础设施上工作。它不会自动分开:

  • Git的共享引用和对象;
  • 测试数据库及其中的数据;
  • 本机端口、进程、容器、网络和数据卷;
  • 开发或真实环境;
  • 测试账号、外部系统和限额;
  • 日志、截图、检查结果和其它证据目录。

因此,Director在启动并行任务时,为每轮ACL分配不会冲突的外部资源。例如,每项数据库测试使用独立的专用测试库,每个本地服务使用不同端口,每轮验证写入自己的证据目录。只有一套的真实环境默认串行更新,不让两个Agent同时发布并相互覆盖结果。

这些分配写入各自启动方案。如果无法把一项关键外部资源分配成互不影响的独立资源,就把需要它的步骤排成明确的串行顺序,不用“小心一点”代替隔离。

第四步:为每个Agent准备独立上下文

每个主要Agent只需要读取完成自己任务所需的上下文,不需要理解所有并行任务的实施细节。交付一个worktree时,至少让Agent知道:

  • 它负责的ACL编号、工作来源和启动方案;
  • 需要遵守的REQ、Accepted设计和ADR;
  • worktree路径、当前分支和明确的起点提交;
  • 可以修改的范围、已经分配的外部资源和不可执行的高风险动作;
  • 任务与其它ACL的已知依赖、预计集成顺序和交付方式;
  • 完成前需要运行的定点验证和需要保留的证据。

不需要把Director与其它Agent的全部聊天记录同步到每个worktree。共同决定写回REQ、设计或启动方案,当前进展写入各自实施记录的“当前摘要”。任务在新会话中继续时,Agent重新读取这些内容并核对当前Git差异,不从记忆中猜测上一次做到了哪里。

第五步:让每个Agent交付一个可以独立验证的完整结果

并行开始以后,每个Agent在自己的worktree中推进完整任务。它可以修改前端、接口、领域逻辑、数据和测试中真正受影响的部分,不被“你只是前端Agent”之类的职能划分限制。完成时留下的是一个能被验证的结果,不是一批等别人收尾的文件。

并行开发不需要让Agent之间持续互相播报每个实施细节。他们只需要告知会影响其它任务的变化:稳定契约改变、共享资源冲突、起点被修正,或者原定依赖不再成立。Director根据这些事实决定调整集成顺序、暂停某项工作,或者回到设计重新确认。

如果一个Agent发现需要改动另一项ACL的范围,它不直接进入对方worktree修改。它先记录新事实和影响,由Director判断这是可以在集成时处理的局部适配,还是原来的任务拆分已经不再成立。如果会改变已确认的产品行为或技术边界,就暂停受影响的实施并回到设计。

第六步:主线依次接收并行结果

多项任务可以同时开发,但不能同时改写主线。每个Agent先在自己的分支上完成范围内的代码、文档、定点验证和实施记录,并把修改整理成容易理解、目的单一的提交。Director或当次指定的集成Agent根据依赖和风险决定接收顺序。

第一项结果进入主线以后,下一项先取得最新的main,处理它与当前main的差异,再重新运行受影响的定点验证。希望保持线性历史时,任务分支可以先同步当前主线:

1
git rebase main

确认冲突已经解决且相关验证仍然通过后,再在主工作树中接收该分支:

1
git merge --ff-only acl-000039-conversation-favorites

代码冲突有两种。一种只是同一文件不同位置的机械冲突,集成Agent根据两边已确认的结果处理并重新测试。另一种暴露了两项任务对对象、状态、接口或权限的理解不同,这不是选择哪边代码更好合并的问题,而是设计矛盾。Director与Agent需要先回到相关设计统一答案。

每项结果进入主线时做受影响的验证,全部接收后再做跨任务的整体验证。分支能够合并只证明Git接受了这些差异,不证明几项工作组合后的系统能够工作。

第七步:完成交付后再清理worktree

一项分支进入主线,不表示它的ACL已经结束。实际修改、验证、失败和跳过项、剩余问题、Director的结论确认以及实际合入提交仍要完整保留。ACL只有在这些事实齐全后才能进入Completed

确认分支结果已进入主线、所有需要的记录和证据已经交付,而且没有Agent继续使用该目录后,才移除worktree和对应短期分支。未合并结果、失败现场、待复核差异和其它Agent仍在使用的worktree都需要保留,不为了目录整洁而提前删除。

并行数量取决于Director能够评审和合并多少结果

可用Agent数量不是并行数量的上限判断。Director还要看有多少真正独立的任务,外部资源能分成几份,以及自己能否及时处理歧义、评审结果和组织集成。

如果五个Agent同时完成五个分支,但主线一次只能安全接收一个,其它分支就会迅速过期,后续时间都用在重新同步、解决冲突和补做验证上。少量稳定的并行通常比一次启动尽可能多的Agent更快。

回头检查这条路径

1
2
3
4
5
6
7
多项已启动的独立ACL
→检查依赖、修改范围和外部资源
→按冲突风险决定是否建立分支和worktree
→为每个主要Agent交付独立上下文
→各自完成可以独立验证的完整结果和定点验证
→按已定顺序依次进入主线
→运行整体验证并保留各轮记录

并行开发的目标是同时推进多项独立结果,不是让更多Agent出现在同一项任务中。worktree把各项任务的文件和未提交修改分开,启动方案和实施记录把上下文分开,外部资源分配和主线集成则让这些结果能够安全重新组合。

同一任务的多Agent协作采用另一条按需路径:

1
2
3
4
5
6
一项已启动的ACL
→当前写入者在隔离空间完成一个固定候选
→提交、推送并记录完整HEAD
→下一位Agent核对基线后接棒或评审
→共同结论写回正式事实源
→本地完成必要验证并由Director确认结果

两条路径可以同时存在:不同任务之间并行,同一任务内部串行。关键是每个时刻都能回答谁在写、正在修改哪个固定候选、下一步由谁接棒,以及哪些结论已经写回仓库。

ACDL研发流程系列第9篇,共15篇。

上一篇:ACDL研发流程08:让多个Agent在不同worktree工作

下一篇:ACDL研发流程10:通过真实使用和独立评审发现遗漏

Agent写完代码只是实施的中间状态

进入这一章时,一轮ACL(Agentic Coding Loop)已经有明确目标、已经确认的设计、起点提交、启动方案和核对过的工作树。Agent现在可以主导实施,但它要交付的不是“已经修改了若干文件”,而是一个能够被证明、被评审、必要时能安全进入环境的结果。

Agent生成代码的速度很快,真正限制研发速度的往往是判断和验证:它是否理解了正确问题,是否在未经确认的地方自行作出了决定,测试是否真的覆盖风险,以及这些修改在真实环境中能不能正常工作。

因此,本章不把“编码”和“测试”看成前后两个大阶段。Agent会在很多次短循环中实施和验证,直到范围内的目标完成并取得相应证据。

第一步:从验收场景找出最容易出错的地方

实施前,Agent先从REQ的验收场景和已经确认的设计出发,列出这次改动最容易出错的地方。这份风险判断会决定要查哪些代码,以及后面需要什么测试,不按前端、后端和数据库等目录机械列工作量。

以收藏会话为例,除了页面上有一个可以点击的入口,Agent还要考虑:

  • 收藏、取消收藏和重复操作得到什么结果;
  • 刷新和重新登录后,收藏状态是否仍然保留;
  • 员工失去会话访问权或会话被删除后,数据和页面怎样变化;
  • 两次请求同时到达时,是否会生成重复关系或错误状态;
  • 存储、接口或页面失败时,员工看到什么,系统能否恢复;
  • 新数据结构怎样迁移,发布失败后怎样回到可用状态。

任务范围不同,需要关心的风险也不同。纯文档修正不需要虚构并发和恢复场景,数据迁移则不能只看类型检查通过。要根据可能发生的错误选择验证方法,不是为了形式完整每次复制同一份清单。

第二步:用短反馈循环推进实施

Agent每完成一个有意义的小结果,就运行与它最直接相关的验证。修改一个纯函数时先运行相关单元测试,改动进程之间的契约时先运行契约和两端映射测试,修改数据状态时使用专用测试库验证迁移、事务和恢复。

一次常见的短循环是:

1
2
3
4
5
读取当前设计和代码
→实现一个有意义的小结果
→运行离改动最近的验证
→查看差异和失败原因
→进入下一个小结果

短循环的目的是尽早暴露问题。每改几行就运行整套验证会让反馈变慢,等几天后再一次性测试又会让失败难以定位。定点测试是与当前改动最直接相关的检查,用来指导实施;统一验证覆盖更大的受影响范围,用来证明整项修改合在一起以后仍然正常,两者不能互相替代。

验证失败时,Agent先理解错误,不为了得到绿色结果而盲目改测试。如果测试正在拒绝已经确认的设计中明确禁止的行为,就修复代码;如果测试与已确认设计不一致,就更正测试。无法判断谁错时,回到REQ和设计找答案,不让当前实现自动获得优先权。

第三步:让代码、测试和文档一起更新

文档是代码的“源码”,所以实施不是先把代码写完,最后再想起更新文档。Agent每形成一个稳定结果,就检查三种内容是否仍然一致:

  • 设计文档说明系统现在应该怎样工作;
  • 代码实现已经确认的行为和技术边界;
  • 测试在关键输入上证明代码没有削弱这些要求。

设计已经说清、代码只是没做到时,修改代码和测试,不需要为了显示工作完整而改几句无关文档。实施让接口、事务、迁移、错误码、部署或恢复方式形成新的长期约定时,负责该结论的能力设计或横切设计也要同步反映最终答案。

已经编号的稳定设计要求需要长期追踪时,在要求账本登记测试、检查、分析或实机验证方式。测试只有真的能判断某项具体要求是否满足时,才把它记为直接验证;只是主题相关时,保留为支持性证据。不用“有一个相关测试”代替对要求的真正判断。

实施记录也在同一过程中追加。当前步骤、已完成步骤、阻塞事项和下一动作写入“当前摘要”;真实修改、提交、环境、验证结果、失败和跳过项随着工作发生而记录。启动方案保留开始前的决定,不用最后的实际做法反过来改写原方案。

第四步:实施中发现新情况时先分类

代码会暴露设计时没有看到的事实。这不一定表示设计失败,但Agent要先判断新情况属于哪一类,再决定能否继续:

  • 私有函数怎样拆、局部变量怎样命名、已有约定下怎样组织局部代码,通常由Agent在实施中决定;
  • 实施顺序、定点检查或局部做法需要调整,但本轮目标、范围和已经确认的设计不变时,在实施记录追加方案变更;
  • 需要改变某项能力的用户流程、对象状态、接口含义、事务、迁移或长期恢复约定时,暂停受影响实施并回到相应能力设计,产品问题变化时同时回到REQ;
  • 需要改变多个能力共同遵守的安全、数据、接口、审计或部署规则时,回到横切设计;
  • 需要改变产品定位、核心进程、存储或外部边界时,回到系统设计,并重新判断是否需要ADR。

暂停受影响的部分不等于整轮ACL失败。Agent保留已经取得的事实和证据,Director与Agent更新并确认相关需求和设计后,再根据新确认的设计判断是继续当前ACL,还是调整范围或启动新的ACL。

第五步:完成功能后,再验证整项修改

定点验证可以告诉Agent一个局部改动是否正确,但不能证明它没有破坏其它包、契约、构建或运行入口。当范围内实施和定点回归已经完成,Agent再根据实际差异运行一次统一验证。

统一验证不是一条永远不变的命令清单。它会根据改动范围选择需要执行哪些检查:纯文档要检查结构、状态、追踪和差异格式;普通代码要增加静态、类型、依赖、构建和非数据库自动化测试;数据库、进程、单节点部署和运维变化还需要专用测试库、镜像或对应运行环境。现行工具版本、命令和分类规则从《开发与验证》读取,不在教程中复制一份容易过期的清单。

验证结果要能对应到实际被测内容。工作树干净时,完整提交可以唯一定位代码;还有未提交差异时,只记录HEAD会遗漏真正被测的内容,还要保存能够精确对应已提交、未提交和未跟踪文件的Git树标识。验证过程中如果差异发生变化,这次结果就不能用来证明最后代码。

第一次统一验证失败时,保留失败结果,找到失败阶段和根因,再完成定点修复与回归。根因修复以后只自动重跑一次统一验证;第二次仍然失败就停止并报告,不通过连续重跑等待一次偶然成功。实施记录同时保存首次统一验证是直接通过,还是经过定点修复后通过。

第六步:停止继续修改,重新检查为什么还不能交付

验证通过后,Agent先停止继续增加改动,将实现整理成一个或几个能够单独理解的Git提交,然后重新阅读最后准备交付的完整差异。这次自检不是解释自己为什么这样写,而是尝试找到不能交付的理由。

自检时,把REQ验收场景、已经确认的设计、启动方案、完整差异、测试和实施记录放在一起对照,重点查找:

  • 代码是否超出本轮目标,或者遗漏了本轮承诺的结果;
  • 实现是否偷偷改变了已经确认的用户行为、权限或数据边界;
  • 正常流程、失败、并发、迁移、回退和恢复是否都有与风险高低匹配的处理;
  • 测试是否只覆盖了容易通过的路径,以及跳过项是否被错写成通过;
  • 文档是否把计划中的结果提前写成了已经发生的事实;
  • 调试输出、临时文件、生成垃圾、真实Secret或其它无关差异是否被带入提交。

阻塞问题修复后,重新运行受影响的验证。需要Director确认实施结果或Loop结论的工作,先形成固定候选提交、验证证据和Review记录,不在确认前把候选直接写入目标分支。如果当次评审必须取得远端证据,可以按仓库当前协作方式使用评审分支或Pull Request。

第七步:按需要使用远端CI复验

本地验证会受到工作站操作系统、已安装依赖、缓存和未提交文件影响。仓库当前的Quality Workflow可以在干净的Linux环境中重新检出固定提交,安装锁定依赖,并执行文档、追踪、静态、类型、构建和非数据库自动化检查。它能够发现本机现状掩盖的问题,结果也可以精确对应到远端提交。

远端CI、评审分支和Pull Request都不是每轮ACL的固定门禁。需要在Director确认前取得远端证据时,再按仓库当前托管平台和工作流建立评审入口;不能为了触发检查就提前把待确认结果写入目标分支。

Quality Workflow当前不是进入main前必须通过的检查。只有Director明确要求,或者当前正式发布步骤依赖远端结果时,才把等待它作为当前同步步骤。非强制不表示已知失败可以忽略;远端失败仍要保留结果,并根据失败阶段开展定点诊断。

这项远程复验不使用业务Secret和测试数据库,不构建产品镜像,也不连接或发布任何环境。它通过不能代替真实PostgreSQL测试、镜像检查、容器宿主行为、浏览器验证或环境发布。

第八步:在需要时把结果更新到环境

不是每轮ACL都需要更新环境。纯文档、不影响运行结果的工具修改,以及已经由自动化证明的局部重构,可以在完成本地验证后停止。只有需要检查真实网络、容器、Secret、存储、浏览器路径或外部系统时,才把结果更新到相应环境。

发布前,Agent和Director核对:

  • 目标环境的当前记录、运行状态和正在进行的其它工作;
  • 准备发布的完整源码提交或完整Git树、制品和配置输入;
  • 与这次改动相关的测试已经通过,未覆盖风险已经明确;
  • 数据、文件和当前服务是否需要快照,迁移、回退和恢复入口是否可用;
  • 本次操作是否在已授权范围内,超出范围的事项是否已经取得Director确认;
  • 发布失败后保留哪些现场,在什么条件下停止、回退或恢复。

当前项目同时提供小范围快速发布和完整发布入口。选择哪一种由实际差异决定,不由Agent想要更快完成决定。小范围源码改动在快速发布明确支持时可以使用它;包清单、锁文件、数据库迁移、Runtime模板、部署编排、网络、Secret或宿主配置变化超出快速范围,需要先保存快照并走完整发布。发布工具因输入、起点或范围不符而拒绝时,先查明原因,不绕过拒绝也不自动改换发布方式。

发布后,Agent检查实际运行进程、健康状态、入口、关键用户路径、数据和恢复材料,确认环境中运行的源码、制品、迁移结果和配置确实来自这次发布。环境记录保存当前状态、发布时间、输入、结果、证据和恢复入口;ACL实施记录保存本轮为什么更新环境以及发布结论。

发布失败时,保留失败步骤、服务和数据状态及已经生成的证据。在已授权范围内恢复环境,再定点诊断根因;涉及删除数据、扩大权限、改变Secret、不可逆迁移或其它超出授权范围的操作,先取得Director确认。

第九步:整理实际结果并提交Director评审

实施和范围内验证完成后,Agent更新实施记录,让下一个读者无需回放整段对话也能看懂真实结果:

  • 实际修改了什么,对应哪些提交和被测Git内容;
  • 运行了哪些测试和检查,在什么环境下得到什么结果;
  • 第一次统一验证是直接通过、定点修复后通过,还是仍未通过;
  • 是否开展远端CI复验,已知结果和失败怎样处理;
  • 发布了什么,目标环境现在运行什么,并通过了哪些发布后检查;
  • 哪些原定步骤发生变化,为什么改,影响了什么;
  • 有哪些失败、跳过、尚未覆盖的风险和剩余问题;
  • 当前是否达到启动方案中的完成条件。

“代码写完”、“测试都过了”或“环境已更新”都不是足够的结论。Agent需要明确它建议本轮进入Review的理由,也要直接说明什么仍然不能被证明。

形成评审候选以后,ACL还没有进入Completed,REQ也没有进入已完成。Director可以先确认这轮ACL的实施结果,也可以根据风险另行开展DFL(Developer Feedback Loop)或ERL(Engineering Review Loop)。DFL和ERL都不是ACL之后必须依次执行的步骤,下一章会说明它们各自在什么情况下有价值。

回头检查这条路径

1
2
3
4
5
6
7
8
9
10
已启动的ACL
→从验收场景识别风险
→用短反馈循环实施和定点验证
→同步代码、测试、文档和实施记录
→遇到设计冲突时暂停并返回需求或设计
→运行统一验证并保留失败证据
→自检固定差异
→在需要时使用远端CI复验
→在需要时更新环境并验证实际状态
→整理记录并进入Review

环境更新成功只证明这组结果已经进入某个环境,不表示真实使用中没有遗漏,也不表示ACL已结束或正式版本已形成。

ACDL研发流程系列第11篇,共15篇。

上一篇:ACDL研发流程10:通过真实使用和独立评审发现遗漏

下一篇:ACDL研发流程12:不同工作从哪里开始、在哪里结束

停止编码、Loop结束和正式版本是三件事

Agent完成最后一次代码修改时,一项工作还没有自动结束。测试结果可能尚未整理,环境中可能运行着另一个提交,计划中的步骤也可能发生了变化。如果此时只留下“代码已完成”,后续的人仍然不知道哪些结果可以相信。

一轮Loop进入Completed,也不表示正式产品版本已经形成。ACL(Agentic Coding Loop)只证明约定的实施与验证已经结束,DFL(Developer Feedback Loop)只证明一组真实任务已经使用并记录,ERL(Engineering Review Loop)只证明一个具体提交或版本范围已经独立检查。它们可以分别在不同时间结束,也可以暂时留在主线等待以后被某个版本选择。

正式版本回答的是更大的问题:这次准备向使用者交付哪些变化,采用了哪些代码和证据,还有什么限制,以及哪一个Git提交代表这个结果。

1
2
3
4
5
6
7
8
停止编码
→Agent不再增加本轮改动

Loop结束
→本轮范围、结果、证据和剩余问题已经确认;ACL还已合入目标分支并记录合入提交

正式版本形成
→若干已结束工作经过版本验收,由Git标签固定

这三个时刻可以相隔很久。一个小型维护ACL可以结束后继续留在main;几周以后,Director准备正式版本时再决定是否把它纳入。环境发布也可以发生在Loop执行中、DFL开始前或正式版本之后,不能代替其中任何一个结论。

先让每轮Loop如实结束

结束一轮Loop时,Agent先把启动时的目标和实际结果放在一起看,而不是只检查有没有最新提交。记录需要让Director看懂:

  • 本轮从哪个分支和提交开始,最后形成了什么提交或评审对象;
  • 实际完成了哪些实施、验证、真实使用或独立评审;
  • 哪些测试、发布和复核通过,在哪个环境得到结果;
  • 哪些步骤失败、跳过、不适用或与原方案不同;
  • 发现了什么问题,哪些已经解决,哪些由ISSUE、REQ、ACL或环境记录继续处理;
  • 本轮目标是否达到,以及这个结论不能证明什么。

计划中的步骤没有发生时,写“未执行”并说明影响,不把它从记录中删掉。实施改变了原方案时,保留变化原因和确认结果,不用最后的做法改写启动方案。Loop结束保存的不是一个漂亮故事,而是下一个人能够复核的实际过程。

整理完成后,先让Loop进入Review。ACL使用专门的评审入口,检查固定候选是否有与当前提交和Git树匹配的最近一次pnpm verify成功证据:

1
2
pnpm loop:review -- --id=ACL-000039 --dry-run
pnpm loop:review -- --id=ACL-000039

DFL和ERL使用pnpm loop:status -- --id=轮次编号 --status=Review,同步登记表和对应记录。

进入Review表示Agent认为结束条件已经具备,正在等待Director确认。它不是一种委婉的完成状态,也不能因为等待时间较长就自动变成Completed

Director检查本轮结论和未解决问题的去向。DFL和ERL在结论得到确认后可以进入Completed;ACL还必须先合入目标分支,并在主记录中把主线合入提交填写为实际提交。满足这些条件后,再明确确认:

1
pnpm loop:status -- --id=ACL-000039 --status=Completed --confirm="确认本轮结论和未解决问题去向"

命令会同步必要计划、记录和Loop登记表的状态,并记录Director的确认内容,但不能替代Director作出确认。对于ACL,脚本还会拒绝主线合入提交仍为待填写的记录。只修改登记表、只把文档改成Completed,或者在聊天中说一句“没问题”,都没有完整保存这次状态变化。

如果本轮目标已经放弃,使用Withdrawn如实停止,不把未完成工作包装成Completed。已经发生的调查、修改、失败和证据继续保留,编号也不重新使用。需要继续的部分可以建立新的Loop,并把原记录作为来源。

目标版本不是一份提前承诺全部范围的计划

一项完成设计的REQ准备交付时,Director会先确定目标版本,并在docs/04-版本/产品版本总览.md建立Review入口。这个入口只说明当前准备组织哪一次交付,不提前保证所有候选需求和关联Loop最终都会进入。

目标版本、REQ排期和正式版本形成是三个不同动作:

1
2
3
4
5
6
7
8
建立目标版本
→为一次候选交付分配版本号并建立记录

REQ进入已排期
→确认它准备服务这个目标版本

正式版本形成
→确认实际纳入的内容,并创建Git标签

DFL和ERL记录中的“关联版本”也不是纳入证明。它只保存开始这轮工作时已知的版本背景。一轮DFL可能检查多个版本,一轮ERL也可能在目标版本尚未确定时开始。只有产品版本总览在验收时明确选择,这轮工作才成为该版本的验收证据,或者成为版本形成前必须通过的ERL。

计划版本为未确定的ACL同样不会因为合入main就自动属于下一个版本。Director准备版本时,可以选择其中与本次交付有关的工作,也可以让其它维护继续留在主线。

版本验收先选择实际纳入的内容

准备正式版本时,Director和Agent先从当前目标中筛选实际范围。产品版本总览需要明确列出:

  • 实际纳入的REQ,以及每项需求的验收场景得到什么结论;
  • 实际纳入的ACL及其完整提交;
  • 被选作验收证据的DFL和被选作版本形成前必须通过的ERL;
  • 版本源码提交、环境实际运行的提交、制品与配置,以及详细证据入口;
  • 明确排除的需求、Loop和未完成范围;
  • 尚未解决的问题及其影响和处理决定。

被选中的ACL、DFL和ERL需要已经进入Completed,历史上已经使用Accepted结束的记录可以继续按历史事实处理。还在In ProgressReview的Loop不能因为“只差确认”就算作已经纳入。

关联同一目标版本但没有被选中的DFL或ERL,不会自动阻止版本。它可能检查了另一个主题,也可能还没有实际执行。Director需要明确排除并说明影响,不能一面忽略未完成范围,一面宣称这些范围已经通过。

以“收藏会话”为例,某个候选版本可以选择收藏需求对应的ACL和一次真实使用DFL。Director根据权限与数据风险判断现有自动化验证已经足够,本次没有开展ERL,也可以形成版本;但发布说明和验收结论只能引用实际存在的ACL与DFL证据,不能写成“已经完成独立工程评审”。

回到最初问题判断版本是否真的可用

版本验收不是把所有通过的测试结果加在一起。Director重新回到REQ中的问题、期望结果和验收场景,判断当前候选是否真的解决了最初的用户问题。

收藏接口、页面和测试全部通过,却仍然无法让员工从长列表中更快找到收藏会话,这个版本就没有完成最初需求。相反,某项内部重构没有用户可见变化,只要它达到自己的工程目标,也不需要编造一段产品价值证明。

Director还要逐项查看未解决问题。它们不要求全部清零,但必须有清楚决定:

  • 在形成版本前修复,并用新的ACL和验证证据更新候选;
  • 把受影响功能或场景排除在本版本之外;
  • 作为已知限制保留,并说明影响和后续去向;
  • 对确实可以接受的剩余风险作出明确决定。

涉及Secret泄露、越权、跨员工访问、数据损坏、无法恢复或未批准业务写入的问题,不能只写进“已知限制”就继续。候选范围需要修复或排除;作为版本形成前必须通过检查的ERL已经规定阻断等级时,也要遵守开始评审前确定的标准。

证据不足时,版本继续保持Review。可以补验证、继续DFL、开展ERL、启动修复ACL,或者缩小实际范围。达到原定日期、已经投入很多时间和环境运行正常,都不能代替这次判断。

确定最终要打标签的提交,并写面向使用者的发布说明

验收范围稳定以后,Agent固定准备打标签的完整提交。这个提交要包含版本结论和发布说明,源码、文档、迁移、配置及生成内容也要与实际验收对象一致。工作树中未提交的修改不能暗中成为版本的一部分。

如果正式版本包含可执行产品变化,需要按当前《开发与验证》完成相应的完整发布验证,并保存能够对应到候选提交或完整Git树的证据。验证过程中候选发生变化,原结果不能继续证明新代码;修复后需要重新选择受影响的验证范围。

详细命令输出继续保存在验证和实施证据中,产品版本总览只汇总实际范围、关键结果、限制、Director结论和入口。不要把每轮测试的详细过程和输出复制进版本文档,也不要让读者为了理解一次发布先阅读几十份实施记录。

每个正式版本另有一份V0.X-发布说明.md,面向实际使用者说明:

  • 新增了哪些可以观察到的行为;
  • 修复了哪些已经存在的问题;
  • 有哪些工程、运维、升级或兼容影响;
  • 哪些范围没有纳入,当前有哪些已知限制;
  • 使用了哪些关键验收和发布验证。

发布说明只写能够从本次范围和证据核实的结果。提交标题写了“优化”,不表示使用者一定能够感知优化;某个DFL没有开展,也不能根据设计预期补写成已经实机通过。没有对应内容的分类可以直接说明没有,不用为了让文档饱满而补造变化。

Director确认以后用Git标签固定版本

当实际范围、验收场景、证据、排除项、剩余问题和发布说明都已经清楚,Director才确认版本可以形成。这里确认的是一个具体候选提交和一组具体事实,不是笼统批准“最近这些工作”。

Git标签创建前,产品版本总览和发布说明保持Review。Agent先把已经确认的版本结论和发布说明写入准备打标签的提交,再创建指向这个完整提交的V0.X标签,并核对标签确实存在、名称正确、指向预期提交。

1
2
3
4
固定版本候选提交
→Director确认实际范围和验收结论
→创建并核对V0.X Git标签
→记录真实标签和完成状态

Git标签让版本获得一个始终指向同一Git提交的固定标识。REQ中的目标版本、ACL编号、GitHub Milestone、Pull Request、发布分支、Docker镜像名称和某个环境的部署状态都不能替代这个标签。

“冻结正式版本”不是禁止仓库继续开发,也不是把所有相关文档变成不可修改。它表示以后提到这个版本时,始终能够回到同一个Git提交、同一份发布说明和同一组验收事实。后来发现问题时建立新的ISSUE、ACL或版本,不移动旧标签,也不把后续结果追溯写成旧版本当时已经具备。

创建标签后,再更新版本和REQ状态

真实Git标签创建并核对以后,Agent完成最后的状态更新:

  • 在产品版本总览中记录实际标签、标签提交、验收结论和已知限制;
  • 把版本及其发布说明从Review改为Completed
  • 把实际纳入的REQ从已排期改为已完成
  • 确认本版本采用且没有未关闭阻断问题的相关设计处于Accepted
  • 再次核对标签、版本总览、发布说明和实际提交相互一致。

这些状态更新不能提前发生。REQ进入已完成表示它已经随正式版本交付,不表示代码已经合并或某轮ACL刚刚结束。发布说明进入Completed也以真实存在的Git标签为前提。

正式版本形成后,不代表它已经部署到每个环境。环境记录继续回答某个环境当前运行什么提交、制品和配置,版本记录回答哪个提交经过正式验收。某个环境可以暂时停留在旧版本,也可以在正式版本形成前运行候选用于DFL,两类记录各自回答自己的问题,不能用环境状态代替版本结论。

回头检查版本怎样形成

1
2
3
4
5
6
7
8
9
10
各轮ACL、DFL或ERL完成自己的范围
→Agent整理实际结果并进入Review
→Director确认每轮结论和问题去向
→Loop进入Completed
→准备正式交付时选择实际纳入范围
→回到REQ验收场景和剩余风险作判断
→固定候选提交并形成发布说明
→Director确认版本结论
→创建并核对Git标签
→完成版本、REQ和相关设计状态

一项工作走到Loop结束就可以停下,不需要为了显得完整而立即制造正式版本。只有Director明确准备一次正式交付时,才把多轮已结束工作组成版本。下一章将从不同类型的实际任务出发,说明它们应该从ACDL的哪里进入,又在什么位置结束。

0%