AI研发流程初步实践(四):长期迭代维护与架构演进
如果你尝试过用AI辅助开发一个真实项目,很可能经历过这样的轨迹:第一个版本,你让AI一口气搭好了原型,代码跑起来了,你觉得”AI太强了,开发效率至少翻了五倍”;第二个版本,你让AI加新功能,虽然开始遇到一些”改A崩B”的情况,但整体还能推进;到了第三个版本,你发现代码已经彻底不可维护了——改一行要动五个文件、加一个字段引入了三个bug、AI每次新会话都建议”不如重写吧”。
这不是你一个人的问题。这是AI辅助开发领域最普遍的困境,我们称之为”第三个版本之死”。为什么AI辅助项目特别容易死在第三个版本?如何让项目健康地迭代十几个版本?这篇文章从概念到实践,系统性地回答这个问题。
一、概念:AI辅助项目的”第三个版本之死”
要理解为什么AI辅助项目容易在第三个版本崩溃,先要看AI的工作方式本质。
AI在单次会话中表现极好:它有足够的上下文窗口理解当前任务,能写出结构清晰、功能完整的代码。但它有一个致命弱点——没有跨版本的长期记忆。每次新会话,AI不知道上个版本做了什么决策、为什么那么做、有哪些约束和权衡。它面对的是”当前代码现状”,看不到代码的演进历史。
这就导致一个典型循环:
- 第一个版本:项目从零开始。AI没有任何历史包袱,从空白仓库搭建,结构清晰、代码整洁。你觉得”AI写项目太靠谱了”。
- 第二个版本:你在现有代码基础上让AI加功能。AI读一下现有代码,理解结构,然后叠加新功能。开始出现一些”兼容性”问题,但整体还行。
- 第三个版本:代码已经积累了多层抽象、多种风格、多个版本的临时补丁。AI新会话读代码时,已经无法完全理解所有模块的关系。改一处可能漏三处。AI开始建议”这部分重构一下吧,太乱了”。
问题不在AI的能力,在缺乏跨版本的知识传递机制。每个版本的上下文被丢弃了,AI每次都从”当前代码”反推设计意图——而代码本身不会记录”为什么这么做”。
这就是长期迭代维护要解决的核心矛盾:AI的单次会话能力极强,但跨版本记忆为零。没有系统化的方法,项目必然在第三到第五个版本之间进入”改不动”的状态。
二、通用设计方案:结构化迭代的方法论
解决”第三个版本之死”不是靠更聪明的AI,而是靠结构化的迭代方法论。下图展示了从版本规划到持续演进的完整框架:

这套方法论由七个核心实践组成,覆盖版本规划、迭代节奏、质量基线、架构演进、知识记忆、重构治理和文档同步。
2.1版本规划:L1/L2/L3分层路线图
长期项目需要两层规划,分别应对”方向”和”落地”两个维度。
路线图(L1/L2/L3) 是粗粒度的长期方向。L1是当前版本要做的具体内容,L2是接下来两三个版本的大方向,L3是远期愿景。路线图不到任务级别,而是以”能力域”为单位描述。例如:”L1实现核心CLI交互 + 基础工具集;L2引入多会话管理和记忆系统;L3探索多渠道接入和skill自演化能力”。
路线图的价值不在于”准确预测未来”,而在于为当前版本的决策提供坐标系。写L1 spec时遇到”这个抽象要不要引入”的问题,对照路线图问一句:”这个决策会堵死L2的路吗?”如果L2计划引入多渠道,那L1在设计通信层时就要预留抽象接口,不能写死成单一通道。
单版本spec 是针对L1的详细设计。它细到文件级别、接口签名、测试用例、验收标准。spec只覆盖当前版本,不做未来假设——但做决策时要对照路线图。
两者的关系可以类比地图和导航:路线图是地图,告诉你大方向在哪;spec是导航,告诉你这段路怎么走。没有地图,导航可能绕远路;没有导航,地图无法落地。
2.2迭代节奏:封仓 → UAT → 冷却
迭代不是无休止的功能堆叠,而是有节奏的推进。每个版本走完一个完整循环:
- 规划期:先写brainstorming梳理需求,再写spec做详细设计,最后写plan分解任务。这个阶段不写代码,只思考和设计。
- 实现期:按照plan拆解成subtask,逐个执行。每个subtask走TDD红→绿→重构循环。
- 封仓期:功能开发完成后”封仓”——不再加新功能,只修bug、补文档、跑全量测试。封仓的标志是提交一个版本tag。
- UAT期:用户验收测试。对照spec逐项核验四类清单——功能完整性、边界情况、错误处理、文档一致性。
- 发布期:合入主分支、推版本tag、更新部署。
- 冷却期:版本发布后不立即开启下一版本。花一两天时间整理design-notes、回顾本版本踩的坑、调整project_memory、更新路线图。
为什么需要冷却期?因为连续滚动开发容易陷入”加功能→出bug→修bug→加功能”的恶性循环,没有时间反思。冷却期是”抬头看路”的时间——回顾哪些spec决策事后看是错的、哪些AI行为模式暴露了新问题、哪些技术债该排进下个版本。
迭代节奏的核心是版本边界清晰。每个版本有明确的开始和结束,有独立的设计文档和changelog,不把多个版本的设计混在一起。
2.3测试基线管理:不退化红线
长期迭代里,测试基线是项目健康最敏感的指标。可以把它想象成心电图的基线——基线稳定,项目健康;基线波动,项目在恶化。
测试基线管理三条铁律:
- 总数只增不减:新功能配新测试,总数应该持续上升。总数下降意味着要么删了测试(必须有理由),要么skip了测试(必须有理由)。无理由的总数下降是红色警报。
- 通过率不退化:上个版本936/938(2个flaky),这个版本不能变成920/950。通过率下降意味着引入了新bug或新的flaky测试。
- flaky必须治理:长期项目里flaky测试是慢性毒药。一开始一两个偶发失败,你会告诉自己”等等就绿了”。几个月后,”红着也正常”成了习惯,测试红灯彻底失去警示意义。每个版本必须把flaky数量压到零,或者至少是可解释、可跟踪的极少数量。
每次封仓时,在版本发布笔记里记录测试基线的快照:测试总数、通过数、失败数、flaky数、覆盖率的增量变化。下一版本开始前对照这个快照,确保基线没有退化。
历史遗留的flaky测试不能放任不管。能修则修(通常是时序、并发、外部依赖问题),不能修的隔离到单独的test suite,不计入主基线。绝对不能把flaky测试留在主测试套件里污染信号。
2.4架构演进:加法而不减法
长期项目的架构演进遵循一条看起来反直觉的原则:加法而不减法。
新版本叠加新抽象,不删除老抽象——除非有明确的重构版本。为什么?因为删除抽象会破坏向后兼容,而AI辅助项目里,”谁在引用这个抽象”经常不清楚。AI写的代码可能引用了一个内部API,但没人记得所有引用点。贸然删除,下游某处就无声无息地崩了。
加法的具体做法:新抽象与老抽象并存,新功能用新抽象,老功能维持老抽象,逐步迁移。例如,v0.1用plain HTTP通信,v0.2引入WebSocket,两者并存;v0.3引入统一的Channel抽象,新接入点用Channel,老的HTTP和WebSocket路径维持不动。直到某个专门的版本做”统一抽象”重构,才删除老路径。
加法原则的代价是代码量会膨胀,抽象层会叠加。但这是可控的代价——比”每次重构推翻一切”的代价小得多。膨胀到一定程度(比如三层wrapper嵌套),安排一个专门的重构版本去收敛,不要在功能版本里”顺手重构”。
加法原则更深层的意义是尊重历史代码。每一行代码在写的时候都有它的理由(即使那个理由现在已经不成立)。随意重写意味着丢弃了那段代码承载的调试经验和边缘case处理。保守旧代码,直到你有充分证据证明它确实该被替换。
2.5 design-notes与project_memory
这是解决”AI没有跨版本记忆”的关键机制,由两部分构成:
design-notes(跨版本设计笔记) 是给人读的长期记忆。它记录的是”为什么”——为什么做某个决策、为什么定某个约束、为什么放弃某个方案。design-notes不写具体代码(代码在仓库里),不写单版本设计细节(那在spec里)。它写的是跨版本才能看到的东西:约束的演化(”v0.1没有分层约束,v0.2发现core依赖access的问题后加了单向依赖规则”)、原则的确立(”v0.3引入了加法而不减法原则,因为v0.2的重构导致了两天回归测试”)、教训(”v0.2因为AI跳过测试直接写实现,导致上线后出hotfix”)。
design-notes的累积效应在项目后半程才显现。前三五个版本你可能觉得”没什么好记的”,但到第十个版本回头看,design-notes是压缩了整个项目的设计智慧。新人(无论是人类新开发者还是AI新会话)读design-notes比读所有spec更高效——它直接告诉你”什么不能做”和”为什么这样做”。
project_memory(项目级知识库) 是给AI读的项目宪法。它每次会话注入system prompt,告诉AI这个项目的基本规则。project_memory的内容包括:
- 硬约束:AI必须遵守的规则。例如”core层不能import access层””API key只能从环境变量读取””测试不能依赖外部网络”。
- 教训:踩过的坑及对应约束。例如”AI倾向跳过测试直接写实现,必须用skill强制TDD”。
- 当前版本焦点:本版本做什么、不做什么,避免AI跑偏到未来版本的规划。
- 架构地图:项目的分层结构和模块职责。
project_memory要精简。它每次会话都会注入,太长浪费token、稀释信号。几百到一千字最合适,只覆盖最关键的约束与原则。详细设计放spec,design-notes承载完整版本记忆,project_memory是”宪法”而不是”法典”。
2.6重构时机与依赖升级
长期项目无法避免重构和依赖升级,但时机比什么都重要。
该重构的信号: 抽象层叠加到明显混乱(三层以上wrapper嵌套)、某模块改动成本远超功能价值(改一行要动五个文件)、测试基线长期flaky暗示架构有问题、新会话理解代码的成本陡增。
不该重构的信号: 功能版本里顺手重构(重构应该独立成版本)、没写测试的模块直接重构(重构后无法验证行为是否不变)、AI建议重构(AI没有沉没成本概念,它经常建议推翻重来——你需要压制这个冲动)、为了”代码好看”重构(重构应该为了可维护性,不是审美)。
重构版本的特征:不增加新功能,只调整结构;测试基线总数不变(行为不变),通过率必须100%;spec明确标注”重构范围”和”不重构范围”,防止重构蔓延到不应该改的模块。
依赖升级策略同样需要谨慎。引入新依赖时问自己五个问题:
- 必要性:能不能用标准库或已有依赖解决?
- 维护活跃度:最近一次提交什么时候?有定期发版吗?issue响应积极吗?
- 体积成本:带来多少传递依赖?
- 兼容性:与现有依赖版本冲突吗?
- 安全性:有已知CVE吗?
升级已有依赖时,minor版本通常安全但也要跑全量测试;major版本必须单独安排升级版本——读changelog、跑全量测试、UAT核验。AI倾向于”用最新版本”,但不最新不一定是坏事,稳定比新鲜重要。
2.7文档同步
每次封仓时,三份文档必须与代码同步:
- CHANGELOG:每个版本一个条目,分Added/Changed/Fixed/Removed四类。面向用户,不写技术细节。
- README:功能列表、快速开始、配置说明。新功能加进功能表,配置项更新到说明部分。
- ARCHITECTURE:模块说明、分层结构、设计原则。新增模块加章节,架构调整更新结构图。
“比没有文档更糟的是过时的文档”——这句话在AI辅助开发里尤其成立。AI读代码时如果也读了过时的架构文档,会被误导做出错误决策。每次封仓检查文档同步,不是一个可选的”最佳实践”,而是维持AI输出质量的必要条件。
三、市面其他方案对比
在实际项目中,不同的团队和项目对长期迭代采取了不同的策略。大致有三种典型路线。
3.1方案A:一次性开发,不维护
这种方案的核心策略是”用完即弃”。用AI快速搭建原型或MVP,项目交付后不计划做长期维护。如果后面需要改动,直接用新会话重写,不关心现有代码的兼容性。
适用场景: 一次性原型验证、黑客马拉松项目、短期活动页面、学习实验代码。
优势: 开发速度最快,没有历史包袱,AI每次都从零开始,输出质量最高。
代价: 无法用于产品级项目。每次重写意味着所有测试、文档、调试经验全部丢弃。项目无法积累,所有”长期价值”都归零。
方案A本身不是”错的”,它是特定场景下的理性选择——如果你的项目不需要活过第三个版本,那就不需要长期迭代的方法论。问题在于很多团队误判了需求,以为”先做个原型,后面再维护”,但原型做完后项目活下来了,却没有对应的维护策略,结果在第三个版本崩溃。
3.2方案B:人工复盘式迭代
这种方案依赖开发者的个人经验来管理迭代。没有系统化的基线、文档、流程约束。开发者的做法是:做完一个版本,自己回忆一下遇到什么问题,下次注意。约束在脑子里,不在工具或文档里。
适用场景: 单人小项目、开发者经验丰富且自律性强、项目规模小(不超过5个模块)。
优势: 灵活,不引入额外流程负担。对于极小的项目(一两个文件),确实不需要复杂的迭代管理。
代价: 高度依赖个人经验,无法跨项目传承。开发者如果休假或转向其他项目,知识就丢了。对于AI辅助开发,这个问题更严重——AI新会话完全继承不了开发者脑子里的”经验”。每次新会话,AI面对代码库时没有任何历史背景,方案B的”经验在脑子里”对于AI来说等于不存在。
而且,没有测试基线、没有design-notes、没有封仓节奏,项目规模稍大(超过5个模块)就会开始出现”改A崩B”的情况。方案B在AI辅助开发中尤其不可持续——AI写代码的速度快,但因为没有系统化约束,制造混乱的速度也快。
3.3方案C:封仓节奏 + 测试基线 + 设计笔记
这是结构化的迭代方案,也是前面”通用设计方案”部分系统描述的方法论。核心特征:
- 封仓节奏:每个版本有清晰边界,规划→实现→封仓→UAT→冷却,节奏化推进。
- 测试基线:测试总数不降、通过率不降、flaky定期清零。基线作为项目健康的客观信号。
- 设计笔记:design-notes跨版本累积设计决策,project_memory作为AI的项目宪法。
- 加法而不减法:尊重旧代码,不随意重写,用”叠加”代替”替换”。
适用场景: 产品级项目、多人协作项目、预期迭代5个版本以上的项目。
优势: 项目可持续性可预测,测试基线提供了客观健康指标,design-notes让新AI会话能快速了解项目历史,节奏化推进给反思留空间。
代价: 需要投入额外精力维护文档和基线;流程约束在项目初期感觉”太重”——前三五个版本可能不需要这么复杂的体系,但第五个版本之后,前期的投入开始显现回报。
3.4设计哲学对比
| 维度 | 方案A(一次性开发) | 方案B(人工复盘) | 方案C(结构化迭代) |
|---|---|---|---|
| 核心哲学 | 用完即弃 | 经验驱动 | 系统化基线 + 知识累积 |
| 版本边界 | 无(一次开发) | 模糊(凭感觉) | 清晰(封仓定版) |
| 测试基线 | 无 | 无或松散 | 严格管理(不退化) |
| 跨版本知识 | 丢弃 | 存在脑子里 | design-notes + project_memory |
| 架构策略 | 每次重写 | 按需重构 | 加法而不减法 |
| 适用项目 | 原型、实验 | 单人小项目 | 产品级、长期项目 |
| 对AI友好度 | 低(无历史传递) | 低(经验不可传递) | 高(知识显式化) |
三种方案各有适用场景,核心在于匹配项目需求。做原型用方案A是效率最高的;做个人小项目用方案B可以接受;但AI辅助代码库一旦需要迭代5个版本以上,方案C不是”可选”的,而是”必须”的——没有系统化的迭代管理,AI辅助开发的速度优势会被”第三个版本之死”完全抵消。
四、aptbot的设计特点
aptbot作为学习型个人助理项目,从一开始就选择了方案C。这不是因为它”最先进”,而是因为项目定位决定了它必须活过很多版本:作为一个开源学习项目,aptbot不仅要自己健康迭代,还要作为示例展示如何健康迭代。
具体实践中,aptbot做了以下关键设计:
分层路线图驱动迭代。 aptbot的路线图清晰分层:L1做核心agent loop和基础工具系统,L2做记忆系统和多会话管理,L3做skill自演化和多渠道。每进入新版本,对照路线图确认方向,确保每一版的设计决策都不堵死下一版的路。例如L1设计工具系统时,就预留了工具注册和发现机制,为L2的skill系统做准备——虽然L2的skill系统还没实现,但L1的抽象已经留下了扩展点。
严格封仓节奏。 每个版本走brainstorming → spec → plan → subtask执行 → finishing收尾 → UAT核验 的完整流程。封仓后冷却期用于整理design-notes和project_memory。不赶版本、不跳步骤。
测试基线自动记录。 每次封仓记录测试基线快照,发布到下个版本时对比。保持测试总数持续增长(不删除现有测试,只为新功能加测试),保持通过率稳定。flaky测试在发现当版本就治理,不遗留到下一版本。
加法而不减法的架构实践。 aptbot的架构演进严格遵守这条原则。新抽象叠加在老抽象之上,老代码除非在专门的重构版本中,否则不做破坏性修改。这意味着aptbot的代码库在早期版本会保留一些”不那么优雅”的实现——但这些实现经过测试验证、处理过真实边界情况,它们的价值超过了”看起来更干净”的重写冲动。
design-notes和project_memory作为项目基础设施。 这两个文件不是”有空再写”的补充文档,而是每次版本迭代的正式产出。封仓前必须更新design-notes和project_memory,作为冷却期的标准流程。project_memory保持精简(几百字),每次AI新会话自动注入,确保新会话知道”什么能做、什么不能做、这个版本在做什么”。
五、发展方向
长期迭代维护的实践也在持续演进。几个值得关注的趋势:
自动化基线监控。 当前测试基线靠人工记录和对比,未来可以引入自动化工具,每次构建自动生成基线报告,基线退化时自动告警。这能进一步降低维护测试基线的认知负担。
AI辅助设计笔记生成。 design-notes目前需要开发者手动整理,未来可以由AI在版本封仓时自动生成”版本回顾草案”,开发者审核后确认。这能降低维护design-notes的门槛,让更多项目受益于跨版本知识累积。
更细颗粒度的记忆分层。 当前project_memory是”全注入”模式——每次会话注入全部约束。未来可能根据当前subtask的上下文,智能选择注入哪些约束。比如当前subtask涉及安全,就注入安全相关的约束;涉及测试,就注入TDD约束。这能减少token浪费,提高信号密度。
自适应的迭代节奏。 不同阶段的项目可能需要不同的迭代节奏——早期可能需要更快的版本循环,成熟期可能需要更长的冷却和反思时间。未来可能引入自适应节奏,根据测试基线趋势、代码变更量、缺陷率等指标自动建议迭代节奏。
aptbot会在后续版本逐步探索这些方向。核心原则不变:长期迭代的关键不是技术,而是习惯——养成记录、反思、基线化、节奏化的习惯。工具可以辅助,习惯必须自己建立。
小结
这篇文章从”第三个版本之死”这个核心矛盾出发,系统性地梳理了长期迭代维护的方法论:
- 版本规划要分层——L1/L2/L3路线图指引方向,单版本spec负责落地。两者互为坐标系。
- 迭代节奏要固定——规划→实现→封仓→UAT→冷却,每个版本走完完整循环。冷却期是反思的空间。
- 测试基线要严格——总数不降、通过率不降、flaky清零。基线是项目健康的客观信号。
- 架构演进要克制——加法而不减法,尊重旧代码,不随意重写。重构应该独立成版本。
- 知识记忆要显式化——design-notes记录跨版本设计决策,project_memory约束AI行为。
- 文档要同步——CHANGELOG / README / ARCHITECTURE在封仓时与代码对齐。
三条路线中,方案C(结构化迭代)是长期项目唯一可持续的选择。它不是增加负担,而是避免”第三个版本之死”的最大保障。
下一篇我们讨论AI的能力边界——什么它擅长、什么它不擅长、什么时候必须人工介入。