驾驭 AI · AI Harness Engineering · 架构层设计

0 阅读9分钟

架构层:决策即边界——为什么"为什么"必须落成文件

AI Harness Engineering 系列 · 第三篇 · 王海涛(公众号:Jia言Yi行 · GitHub:derekwang85 · 腾讯云 TVP / 架构师名人堂)

00-intro.jpg

很多用 AI 编码的项目,死法都差不多:跑了几个星期,代码能用了,功能也在加,但你问任何一个成员"我们当初为什么定这个方案",没有人能答上来。不是他们忘了,是那个"为什么"在无数轮人机对话里蒸发掉了。对话是有记忆的,但每开一个新会话,上一轮的结论就只剩模糊的轮廓;再往后,连轮廓都变成各说各话的猜测。

上一篇文章讲了宪章——战略层回答"要做什么、是什么"。但宪章只能钉住项目的坐标,钉不住坐标移动的理由。AI 编码的高频迭代,每天都在悄悄挪动边界:今天为适配一个接口改了方案,明天为让测试通过又改了约定,每一次都是"为了当下"的合理让步,叠加起来就是架构的慢慢漂移。要拦住它,就得有人把"为什么这么定"落成文件——这个文件,就是架构层的 ADR(Architecture Decision Record,架构决策记录)。


一、对话里留不下决定

01-dialogue.jpg

先讲一个我在项目里反复踩的坑。早期用 Cline 类的 Agent 时,我习惯在对话里敲定方案:改哪个文件、采用什么策略、边界在哪里,说一句"你看着办,按我们讨论的来",就让它开工。当时觉得效率很高——省去了写文档的功夫。

问题是,下次会话的 Agent 完全没有这段记忆。它只看到磁盘上的代码,看不到对话里那些"不要动这个、用那种方式、这里是有意这样折中的"。于是它按照自己的"合理直觉"重构一番,把上次的有意折中当成"历史债务"清掉了。我检查代码的时候才发现,边界又被悄悄地挪回了原始状态。

后来我理解了这件事的本质:人和 AI 的对话,不是持久化的约定,只是一次性的指令流。它既不回溯、也不留档,更不会自己变成约束。想让某个决定真正生效,这个决定就必须离开对话线程,落进一个 AI 每个会话都会读的载体里。一句话:离开对话线程的决定,等于没做决定;只有落成文件的决定,才会真正生效。

二、三个在流失的东西

02-three-drifts.jpg

决策不落地,会从这里开始一个接一个地流失:

记忆漂移。  上次决定"统一用 chunk 切分,不用向量化",这次 Agent 在新会话里看到没切分的代码库,会觉得"这个项目做法不一致",然后自作主张改成向量化。它没有恶意,只是它没看到的那个决定,对它来说就是不存在的约定。磁盘上的代码"看起来"没违反任何明文规则——因为规则根本不在磁盘上。

架构漂移。  决策被覆盖之后,边界并不消失,只是从"钉死"变成"随机"。每次重构都以当下语境为准,一周后两个模块的约定就分叉了。代码没有冲突,但架构的内在一致性在流失。

反复争论。  同一个技术选择,人类团队可能早就在架构评审里达成过共识。但因为没有记录,每次新成员加入、每次新 Agent 进来,都要从头再讨论一遍。讨论耗时还是小事,更麻烦的是——没有记录的争论,会随着对话上下文不同得出不同的结论,团队自己对自己"食言"。

这三个后果合起来,就是史上一句老话在 AI 时代的版本:历史是胜利者写的。  在对话里,没有哪一方是"胜利者",只有最后说话的那个模型——它用什么语境,就定义成什么样。而文件,是唯一不在乎"谁最后说话"的仲裁者。

三、单一事实来源

03-ssot.jpg

把决定落成文件,工程史上早就有成熟答案,叫单一事实来源(Single Source of Truth)。这个概念不是空谈——落到可操作的工程实践里就是:一个决定只有一个权威出处,冲突时以它为准,其余的都是派生物、引用它。数据库、配置管理、文档化的实践都在反复验证这一点。

ADR 就是架构这个维度上的单一事实来源。为什么叫"记录"而不叫"文档"?因为它的定位不是给人读的说明书,而是给系统仲裁的判据——价值不在"讲清楚",而在"钉死一个已发生的选择"。

这一点在 AI 时代变得格外重要。传统工程里,架构文档是给人看的,人自带判断力,写得敷衍一点,也能靠经验和讨论补齐;但 AI 编码里,读这份文件的是"严格的复读机",它不会靠常识补全,只会照着字面执行——文件里没有一个字写"不要动这里",那"不要动这里"对它来说就是允许的。所以对 AI 生效的架构层,只能靠文件本身钉边界,不能靠读者(Agent)的悟性。

四、ADR 长什么样

04-adr-structure.jpg

ADR 的格式没有强制统一的标准,但核心结构大同小异。以本项目实际写过的 ADR-0003 为例,它长这样:

  • 状态:已接受(记录决策当下的判定)
  • 决策者:谁做的决定,责任可追溯
  • 背景:当时为什么需要这个决策,面对的是什么问题
  • 决策:具体定下来怎么做,条理清晰
  • 理由:为什么要这样选,替代方案为什么不行
  • 后果:正面和负面的影响,需要应对什么
  • 应对:对负面后果的处理方式

这套"背景→决策→理由→后果→应对"的结构,本身就是在强迫你做一件反 AI 直觉的事:把"当时这样定"的上下文固定住。因为 AI 编码最怕的就是"后来的 Agent 不知道为什么这里有个奇怪的折中"。ADR 把那个"为什么"赎回来了。

ADR 数量不用多,贵在真实。TradeOMS 积累了 20 个,SmartQuant 有 11 个(其中包含 Agent 编排框架的关键决策),derekinside 也把架构级选择陆续落进了它自己的 ADR 目录。这些不是什么管理冗余,而是项目每走一段就会撞墙、每撞一次墙就把教训凝固成一条记录的产物。它们不追求齐全,追求的是"每一次方向性选择都有据可查"。

五、ADR 是双向反馈的终点

05-bidirectional.jpg

架构层在约束体系里有个特别的位置,它既是下行约束的一环,也是上行反馈的终点。

往下看,宪章回答"要做什么",架构层的 ADR 就把宪章的抽象翻译成"边界在哪"——具体到某个技术栈为什么不能换、某个模块为什么这么划分、某个约定为什么不许破。这是对 AI 的硬约束,改动它,需要先有一份新的 ADR。

往上看,实现层暴露的问题要回流修正约束,而修正的落点正是 ADR。我在重定义规约体系时就是这么做的:当发现"五层"原先的表述会让人误以为是某个项目独有的文件清单时,我没有直接改方法论文档,而是先写了 ADR-0003 记录决策理由,再回写宪章和相关文档。决策留档,这就是上行通道不变成"随便改"的机制——任何一次层级调整,都要能指认它对应的那份决策记录。

在这个体系里,ADR 还允许一种 AI 时代特有的写法:Swarm-Fed ADR——由多 Agent 的共识结果反向喂给决策库。当一个决策经过多个模型、多个角色从不同角度验证后,再把共识沉淀成 ADR,它的可信度比单次对话高得多。这个概念在方法论里是重要的一类,但落地细节这里不展开,后面讲到多 Agent 编排那一篇再细说。

六、第一天就能用的清单

06-checklist.jpg

如果你的项目正在用 AI 编码,今天就能给你的"为什么"存档:

  • 建一个 decisions/ 或 docs/adr/ 目录,作为架构决策的唯一入口
  • 定一个极简模板:状态 决策者 背景 决策 理由 / 后果,六项就够,别过度设计
  • 遇到方向性选择就写一条:什么时候该写?当你为一件事跟 AI 争论超过一轮,或做了一次会波及大量后续代码的决定时
  • 让 AI 开工前读一遍:把 ADR 目录加进宪章要求的必读清单,确保任何 Agent 都看到它对约束没有讨价还价的余地
  • 改动约束先写新 ADR:不是直接改代码或改约定,而是先记录"为什么改",再动手

清单最后一条最反直觉,也最值得说透:改边界之前先写 ADR,看起来是给改动加了门槛,实际上是在保护改动的正当性。  因为 AI 编码里最危险的不是"改错了",而是"改得毫无理由却让人觉得合理"——一个没有记录的改动,和一句没有出处的记忆一样,会在下一次迭代里再次被覆盖。ADR 不是文档负担,它是给每个"为什么"上的保险。写下的那一刻,你就在为这个项目往后的每一次对话,留一个不会消失的坐标原点。


下一篇,我们从塔尖再往下走一层:契约层——从规格到代码。架构层钉住了"为什么",契约层要回答"怎么做、怎么稳定"。