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

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已结束或正式版本已形成。