AI-Native 系列 · 工程实践
仓库里下一个「开发者」不是人。六项实践,让代码库为它做好准备。
一分钟速览:你能带走什么
一个对抗性 AI 从头到尾读完了我的仓库,找出了 21 个我漏掉的 bug——其中包括一个路径穿越漏洞。这样的读者已成新常态。于是我围绕六项实践重构了代码库——OOP、AI 原生、上下文工程、保障工程、循环工程、图工程——并把一切都量化:代码质量 56→95,AI 响应 130s→3s,合并前修复 9 个 bug。下面逐一说明每项实践的含义,以及背后的实测依据。
下面的每一项实践,我都会用讲给聪明的 15 岁孩子听的方式讲清楚,然后用一周内在同一个仓库上的真实数据来佐证。约 8 分钟读完。
那个从不跳读的读者
上周,在合并一个分支之前,我把仓库交给了一个对抗性 AI 审查者,只给了一条指令:find how this fails in production. No compliments.(中译:找出这段代码在生产环境中会如何失败,不要说好话。) 它返回了 21 项发现。其中一个是真实存在的路径穿越漏洞——本该拦下它的一个词法检查,却让它Recordings/../../.ssh/id_rsa轻松绕了过去;那个文件我自己也审查过,却没发现。
那一刻,抽象的道理第一次变得具体:下一个读你代码的「开发者」,不再是那个疲惫地扫一眼 diff 的人类,而是一个会读完全部一万行代码、走遍每一条分支、并把你仓库的结构照字面意思去理解的智能体。如果你的代码库只对人类可读,那就等于把它最好的读者——也是最严苛的审查者——挡在了门外。
所以问题变了,不再是「这段代码干净吗」,而是变成了"can an agent work here?"(中译:智能体能在这里工作吗?) 六条实践就是答案。它们没有一个是新的。新的是它们为了什么而存在.
1 · OOP——结构即智能体可读性
大白话版: 面向对象编程,就是把代码分成一个个小单元,每个单元只干一件事,并且把「怎么干」藏起来。这个单元只承诺「给我 markdown,我还你分块」——外人不用知道更多。
OOP 的经典论据是方便人类维护。但现在有个更硬的理由:缝隙,才是智能体能安全操作的地方。 我的数据摄取脚本原本是一整坨过程式代码,自动重构循环给它打了 56/100 分,而且几乎改不动(只挤出了 +2 分就放弃了)。当我把它拆成三条缝隙后——一个负责摄取、一个负责嵌入、一个负责存储MarkdownChunker,各管一段OpenAIEmbedder, a KnowledgeStore——其中任何一个都能单独替换(换个 embedding 提供商、换个数据库),不影响其他部分。我要是让智能体「切换到本地嵌入模型」,现在影响范围只是一个类,而不是整个文件。
成果: 仓库 Python 代码的质量分从 56 涨到 95/100——类型标注、文档字符串、嵌套层级,三项全部拉满 100%——整个过程中仓库自带的测试闸门始终亮绿灯。
2 · AI-native——智能体是一等公民
大白话版: 一个 AI-native 的仓库,把智能体当用户对待,而不是当入侵者防着。它会提供智能体无监督工作所需的一切:一份解释架构的指南,以及——最重要的——一条机器可自行发现的完成线.
我的仓库里有一份架构指南CLAUDE.md,不仅记录代码做了什么,还记录了那些坑(「绝不要把二进制文件热替换进已签名的包里——macOS 会在执行时直接杀掉它」)。仓库根目录还有一份 MakefileMakefile,里面只有一个目标:`make check`check。这个目标,就是仓库对「完成」的定义。回报立刻就来了:有个编排工具,我把它指向这个仓库,它自己就发现了 `make check` make check,一次性发现并运行了它,还回报了一个诚实的绿色状态。零配置。仓库自己告诉了 agent 该如何验证自己。
成果:anyagent goal --drive发现了这个目标Makefile:check,运行了它,退出码为 0。同一道关卡如今在每次 push 时都会在 CI 里跑一遍。
3 · 上下文工程——上下文是预算,不是背包
大白话:塞进 AI 提示词里的任何内容,都要占用时间和注意力。上下文工程,就是决定什么配得上占一个位置——并且按承载它的模型的实际容量来调整大小。
我的 AI 助手的系统提示词,在不知不觉间已经膨胀到 87KB 的知识包积累量。在支持提示词缓存的云端模型上,这几乎是免费的。但在 API 中断期间我切换到的本地 7B 模型上,代价极其惨重——而且这种代价悄无声息:模型把提示词的大部分内容截断,根本没读到,而每次响应却要耗时两分多钟。我实测了一下:没有系统提示词时是 0.3 秒,带上完整知识包是 129.7 秒。把提示词精简到 5KB、并把知识包挪到按需加载的文件后:3.0 秒。同一个模型,同一套硬件,快了 43 倍——靠的是删掉那些模型压根没读到的字。
成果: 每次响应从 130 秒降到 3 秒,前后都用计时调用实测过。这些知识包并没有被删除——只是被挪到了只在任务需要时才加载的文件里。
4 · 保障工程(harness engineering)——让真相变得廉价
大白话: 保障是围绕代码的一整套装置,它让验证变得廉价、让糊弄的代价变得高昂:探针、关卡、自测。原则是站在用户的高度上验证——测试用户实际体验到的东西,而不是函数返回了什么。
这一条保障救了那一整周。我的应用的转录功能悄无声息地什么都没产出。单元测试全部通过——问题出在 macOS 权限机制里,而这套机制只有部署成真实的 app bundle 时才会暴露出来。发现它靠的是这样一套保障:一个探针应用,专门复现系统级的 kill 信号;一套崩溃报告取证方法,用来确定究竟是哪个进程的权限出了问题;最后还有一个扬声器对麦克风的自测——把合成语音播放进实时麦克风管线——端到端地证明了修复确实有效,全程无需人工介入。我的用户说 "I am not a testing machine"(中译:我不是个测试机器)的时候,他是对的。这正是保障机制该干的活。
证据: 三个根因(权限被杀、提示词归因错误、运行循环饥饿),每一个都由专门打造的探针单独锁定,最终的自测在零人工介入的情况下生成了 51 段实时转录片段,节奏约为每 1.2 秒一段。
5 · 循环工程——闭环反馈,诚实评分
大白话: 循环就是「行动→测量→调整」的任何一个周期。循环工程要做的,是让这些周期既闭环(测量结果真的会反哺回去),又诚实(遇到瓶颈就如实报告瓶颈,绝不假装成功)。
这个仓库在各个层面都跑着循环:一条带熔断器的 LLM 故障转移链(如果主服务商在调用中途挂掉,下一层会接手回答);转录里逐段的兜底机制(云端失败→本地接管这一段,不丢一句话);还有前面提到的重构循环,它最有价值的行为其实是停下来——它报告 56→58,说「没有可提的改动」,然后停手不干了。一个会给自己加分作假的引擎,比没有引擎更糟。这次诚实的瓶颈报告,恰恰告诉了我机器的努力到哪里为止、判断该从哪里接手。
证据: 重构循环如实报告了自己在 58/100 遇到瓶颈,而不是谎称大功告成;后续人工介入的一轮把它推到了 95,用的还是同一套检验关卡。每一步都过测试关卡,一旦退步就回滚。
6 · 图工程——记忆 = 实体加关系
大白话: 文件和文件夹记不住事物之间的关系。而图——把事物彼此连接起来——才是工作得以累积的方式:这场会议属于那个项目,这份转录喂给那个知识库。
这个仓库的记忆层从头到尾都是图状的:转录文本变成知识库里的嵌入向量(按含义检索,而不是按文件名);会议导出到一个知识图谱引擎,绘制出「谁在讨论什么」的关系网;而最新加入的一条边——「项目化(Projectize)」——会把一场会议的笔记放进项目文件夹,那个工作还在继续的地方,下一步该做什么也已经安排妥当。录音过去是个死胡同,现在它成了一个带边的节点。
成果: 一次会议只需点一下,项目仓库里就会新增一份带日期的笔记文档,下一步已经自动路由好了——这次会议加入了项目的图谱,而不是在资料库里烂掉。
过程中踩过的坑(故意留着不删)
- 自动化重构循环在 58/100 触顶不动了。引擎负责路由和把关,缺口还得靠判断力来补。
- 为了验证得快一些,我把一个固定的二进制文件热替换进了已安装的应用里。macOS 当场就把它杀了,因为这破坏了 bundle 的代码签名。这个教训已经记进了仓库的智能体指南里,这样不管是人还是智能体,都不会再踩一次。
- 在 21 项对抗性发现里,我在合并前修复了 9 个,并且在 PR 中如实记录了另外 12 个,而不是假装它们不存在。一个诚实的 ❌ 胜过一个虚假的 ✅。
一句话版本
用接缝组织你的代码(OOP),给智能体一个前门和一条终点线(AI-native),把上下文当钱来花(上下文工程),让真相验证起来很便宜(保障工程),诚实地闭合每一个反馈循环(循环工程),把记忆存成「实体加关系」(图工程)。然后把你的仓库交给你能找到的最苛刻的审阅者——那个从不跳读的读者——让它逼你变得更好。