阿里妹导读
AI Native 不仅指产品形态。在一些更窄的场景里,比如编程领域,它也可以特指 AI Native 研发。但这里的AI Native 研发,不是让 Agent 写更多代码,也不是让 AI 零散参与研发流程,而是在清晰边界、可观测 checkpoint 和可验证闭环下,让代码生成、测试、修复、验证等实施动作尽可能由 AI 连续完成。人的角色不消失,而是上移到设定目标与边界、审阅 checkpoint、判断转向和最终验收。(文章内容基于作者个人技术实践与独立思考,旨在分享经验,仅代表个人观点。)
一、Code is cheap
最近 20 天,AI 帮我提交了 70 万行代码,10个项目,同时并行。
不是 IDE 补全那种”AI 占 100%”。是把一个完整任务整包交出去——读地形、定方案、写实现、跑验证、修 bug——AI 自己全套跑完,我只在关键节点拽一下方向。
如果你觉得这只是我们的特例,外部世界其实已经给了足够多的信号:AI 公司工程师在用 Claude Code、Codex 这类工具开发自己的 AI 产品;普通工程师从查搜索结果、翻 Stack Overflow,迁移到直接问 ChatGPT / Claude;Google 等公司也公开提到新代码里 AI 生成占比在上升;Cursor、Devin 这类 AI-first 团队,则把产品团队规模压到了过去很难想象的程度。 当同样的变化进入复杂工程现场,会怎样改变一个工程师的产能结构?
典型的研发场景:产品线多、内部平台复杂、存量系统长、权限和发布链路严格。过去真正昂贵的不是敲代码,而是读懂历史、找准边界、确认影响面、跑通验证、控制发布风险。现在一旦模型可以整包接住”读地形、定方案、写实现、跑验证、修 bug”这一串动作,代码本身就开始从稀缺资源,变成可以快速生成、快速验证、快速丢弃的过程产物。
外部行业信号 + 内部实践,同时指向同一件事。
真正要警觉的不是”AI 越来越强”——这件事大家都已经接受了。而是另一件事:
代码本身,正在变得非常便宜。
二、泥头车与长尾
代码廉价化的第一个副作用,是长尾的极端拉伸。
差距不是”会用 AI”和”不会用 AI”——这一拨差距其实已经不大,差不多人人都用过。真正在拉开的是用 AI 的层级差距。
这不只发生在普通用户里。我观察到,在很多集中了大量优秀工程师的公司内部,长尾同样很长。头部的人(包括我自己)已经能用 AI 同时推进 5 个项目,把任务整包交给模型自动跑;尾部的人,还停留在用 LLM 写写单测、补几个注释的阶段。这不是技术能力的差距,是对 AI 的使用方式的差距——而这个差距,正在以周为单位放大。
放大它的不是 AI 自己。AI 不在乎任何人。它只是残忍地学习、代替、撞死所有跟不上它的人。这没有感情成分——它就是一辆不停加速的泥头车,旧流程、旧身份、旧经验是不是还没准备好,它都不会停下来等。
所以摆在每个人面前的只有两条路。
第一条,在它撞到你之前多跑两步。具体的意思是:在大模型公司还没把某个能力做成标准产品之前,你抢先用它实现。那段窗口期是你最后的护城河——不是因为你比 AI 强,而是因为 AI 还没顾上你这块。
第二条,爬上这辆车,无论姿势多狼狈。具体的意思是迅速把自己转型成 100% AI 工作者,让 AI 帮你跑、帮你写、帮你交付。你不再是车前的行人,是车上的乘客。
这篇文章讲的是第二条——爬上车的方法。这套方法叫 Harness。
那 Harness 到底是什么?我的粗糙定义是:人定方向,模型推进。
你不替模型写每一步代码,但你要定方向、控节奏、看终点。Harness 就是把这套姿态搬到大模型身上。
但让大模型真正接手任务,不是普通的工具调用——它有两个底层事实,让 Harness 必须直接针对它们设计。后面所有的方法和技巧,都是从这两个事实出发推出来的。
三、大模型的两个底层事实
那”两个底层事实”具体是什么?它们不是 AI 公司能很快解决的,是大模型本身的属性——所以 Harness 的方法必须直接针对它们设计。
3.1 事实一:概率生成器
大模型不是确定性函数。
想理解这件事,得先看它的底层机制。大模型每说一句话、每写一行代码,本质都是”一个 token 接一个 token 往外吐”——token 是它处理的最小单元,可以是一个汉字、一个英文单词,也可以是单词的一小段。每吐一个 token 之前,模型基于前面已经吐出的所有内容,对词表里所有可能的下一个 token(通常几万到十几万个)算一个概率分布。
打个最直观的比方。输入”我今天早上吃了一个”,模型会对词表里每个候选 token 打分——”包子” 可能 12%、”鸡蛋” 8%、”苹果” 5%、”汉堡” 3%……然后按某种采样策略从这个分布里挑一个,接到末尾,再基于新的上下文重新算下一个 token 的概率分布。整段输出就是这样一步一步采样累积出来的。
这种机制有两个直接的结果。第一,模型每一步的输出不是”想清楚再说”,而是”按概率挑一个”——所以同样的输入,多次跑结果可能略有不同。第二,每一步的小偏差会沿着链路累积——一旦某一步挑歪了一点,后面所有 token 都基于这个偏差继续挑下去,越走越远。
推论很直接:给它的自由空间越大,它跑偏的概率越大。
具体翻车的样子是这样的:你把一个相对模糊的目标交给它,它可能洋洋洒洒生成 500 行代码但方向完全不对,review 的时候根本下不去手;它修了一个 bug,顺手”优化”了你不想动的部分;你不知道它为什么这么写,不敢上线。这些都不是模型不够聪明,是它在过大的搜索空间里乱选了路。
这也是 best-practice slop 的来源。这里说的 best-practice slop,不是简单的”AI 写得烂”,而是 AI 在一个过大的目标空间里,把网上最常见、最像最佳实践的套路糊上来,生成一套看似专业、语言完整、结构漂亮,但不贴业务地形、不解决真实问题的平均产物。它最危险的地方是:读起来像方案,跑起来像进度,最后却离真实目标越来越远。
所以事实一的工程对策不是把每一步实现都规定死,而是先做反 slop:任务开始前反复和模型讨论需求,让它复述目标;理解错了,人立刻纠正;证据不足,就继续搜索代码、日志、历史 spec;几轮之后,把目标、边界、证据、判断标准沉淀成一份精华文档,也就是后面 §5.2 的 spec。这一轮可能不写一行代码,但它已经把模型从”凭概率在巨大空间里乱选路”,挪到了”在清晰目标和边界内自主推进”。
3.2 事实二:上下文宝贵
大模型的上下文窗口是有限的,而且——给得太多反而会腐烂。
这不是”模型不努力”,是 transformer 注意力机制的内在限制。模型每生成一个 token,都要在上下文窗口里所有 token 之间分配注意力——窗口越长,每个 token 拿到的注意力权重越稀薄。同一段关键信息,放在 2k 上下文里能被精准命中,放进 100k 上下文里就可能被噪音淹没。
学术界有一个非常有名的发现,叫 “Lost in the Middle”(Liu et al. 2023, Stanford)。研究发现,LLM 对长上下文的记忆呈 U 型分布:开头记得清楚,结尾记得清楚,中间的信息最容易被遗忘。即使是最强的前沿模型,把关键事实放在长上下文的中段,命中率都会显著下降。后续 NIAH(Needle-in-a-Haystack)等长上下文 benchmark 反复验证了这个现象——上下文窗口的物理大小,和模型在窗口中段实际能用上的信息量,是两回事。
多轮对话的场景更糟。除了 U 型衰减,还会叠加几个问题:旧方案和新方案在窗口里共存,模型分不清”哪个是当前结论”;模型自动总结时会丢失细节,你没法保证它每次都保留核心;recency bias 让它过度看重最近几轮的内容,更早的关键决策被无声地稀释。
你常会遇到这种情况:AI 在第 15 轮对话里把第 5 轮已经修好的逻辑改回去了,还振振有词地说”这是更优的方案”。这不是它故意捣乱,是它的上下文里早就分不清哪些是当前结论、哪些是历史尝试。
而且要注意——自动总结只能延缓上下文腐烂,不能解决它。每次总结都是有损压缩,几轮下来核心已经走样。真正的解是定期重启(后面 §7 会展开 new-chat 这个 skill),用 spec 作为外部真相源喂给一个全新的 chat。
所以很多人本能反应”给 AI 越多上下文越好”是错的。真正要节约的不是 token,是上下文——省 token 是成本问题,省上下文是质量问题。这是一对很多人弄反的东西。
这两个事实,直接逼出我自己摸出来的方法论。
四、方法论:水流理论 + 最小混沌单元
Harness 是一个 generic 概念——任何在 LLM 上做 delegation 的方法都能叫 Harness。但怎么 Harness 才有效,需要一套具体方法论。我针对前面那两个事实,发展出两个核心理念:水流理论 和 最小混沌单元。
它们不是平行的”两根支柱”——而是纬度不同但互相协作的两件事:一个是协作姿态(怎么和模型一起工作),一个是任务结构(每次给模型多大的活)。
4.1 理念一:水流理论 —— 一种编程方式
水流理论解决的是 AI Coding 里最核心的协作问题:怎么让模型自己推进,又不失控。
传统软件工程习惯先把路径设计清楚,再让代码按路径执行。放到比喻里,这像是在挖水渠。过去这很合理,因为代码是确定性产物。
但大模型不是普通代码生成器。它会搜索、组合、试探、绕路。你把每一步都规定死,反而把它最有价值的探索能力封住了,让它退化成打字员。
所以水流理论的核心不是”放任模型”,而是把控制点从代码细节上移到三件事:边界、checkpoint、风险通道。模型像水一样,会顺着上下文地形自己寻找通往 coding 目标的路径;人的工作,是用堤坝式的边界、水闸式的 checkpoint 和安全通道,让它能流动、可引导、出问题也接得住。
第一,先定边界。对应到 coding,就是任务包和 spec:目标是什么,哪些文件 / 能力可以动,哪些 scope 明确不碰,验收标准是什么。用水流比喻说,这就是先修堤——不是规定水每一米怎么走,而是先规定哪里不能淹。堤坝不是凭空长出来的;放水前通过讨论、复述、纠正、查证、收边界把 spec 磨出来,就是前面说的反 slop,§5.1 会用 case 展开。
第二,过程中看 checkpoint。模型开始推进后,人不逐行盯代码,而是在关键节点看它的计划、证据和风险,然后决定放行、追问、加料、绕道、回炉或阻止。用水流比喻说,这就是水闸——不是遥控每一滴水,而是在关键节点调节流向和水量。具体动作 §5.3 会展开。
第三,风险要进安全通道。高风险改动先进测试环境、灰度、金丝雀;出了问题能回滚。用水流比喻说,就是别让水直接冲进城市。§5.5 的多层 safety net 会展开这一层。
所以水流理论最关键的判断,是区分两种情况:
漫溢:模型在边界内自由探索,方案可能和你原想法不同,但目标对、边界没破。允许它,同时通过 checkpoint 持续观察和引导。溃堤:模型违反 spec、扩大 scope、连续验证失败。这不是探索,是风险失控,必须转向或回炉。checkpoint 的注意力不该放在”模型每一步是不是按我想的写”,而是放在:有没有越过边界,目标有没有走偏,风险有没有进入安全通道。至于 checkpoint 如何刷新模型注意力,§5.3 和 §5.6 会展开。
水流理论的真正核心是——速度 + 方向 + 安全,三者都要:
既要发挥 AI 的主动能动性和速度,也要让它走向我们想要的方向,而且不造成破坏和巨大损失。
这是水流理论作为”编程方式”的最终态——把控制点上移:从”代码细节”上移到”目标、边界、检查点、验证结果”。后面 §5.5 的多层 safety net,就是这套防洪工程在验收阶段的具体落地。
4.2 理念二:最小混沌单元
—— 对抗两个事实的结构选择
水流理论解决了”怎么协作”,但还有一个问题没回答:这次让模型跑多远?
这个问题的答案,是从两个底层事实直接推出来的。
直觉是”反正模型会自己找路,让它一口气做完最省事”。但概率会随长度累积偏差(事实一),上下文会随长度腐烂(事实二)——任务过大最大的风险不是它一定失败,是它失败得太晚。等它做完整段才发现方向不对,回滚半径就是整个任务。
所以每次交给模型的任务,要做到:
小到目标清楚、边界可见、结果能验、失败能局部回炉;
大到模型仍然有自主设计、实现、修复、验证的空间。
简称:小到可检查,大到可自治。
最小混沌单元是一种结构性的防御:不要把过大的任务一次性交给模型,而是拆成能逐段验证的任务单元;每段都能检查,接得上继续,接不上局部回炉。它直接对应两个事实——粒度小,搜索空间小(事实一);单次任务上下文也小,不容易腐烂(事实二)。
但光有粒度还不够。每一段任务里,模型看到的上下文必须是干净、精炼、聚焦的——否则段再小也会被腐烂的输入污染。所以最小混沌单元配套了三件上下文设施:
spec —— 把决策持久化成一份外部真相源,对抗对话腐烂、跨 session 接得上。codemap—— 把代码地形摘要化,避免把整个 repo 塞进窗口。new-chat —— 跨 session 换水,把累积噪音留在原地,用 spec 喂给一个全新的 chat。这三件套加上”粒度小”,合起来才是完整的最小混沌单元。后面 §5 / §7 里会反复看到它们出场。
4.3 两个理念在不同纬度上协作
这两个理念是不同维度针对同一件事——都为”让 AI Coding 又快又稳地跑起来”服务,只是下手的位置不一样:
水流理论是 coding 的协作方式—— 人和模型怎么配合:观察、追问、加料、转向、验收。它管的是动作维度——每个 checkpoint 上的反应、每次转向的判断、每一层 safety net 的兜底。最小混沌单元 + 上下文设施是 coding 的材料原料—— 每次喂给模型的输入:任务粒度 + spec / codemap / new-chat 三件套。它管的是原料维度——决定模型这一段任务里看到什么、能看多远、记得多清楚。没有水流理论,最小混沌单元会退化成”把任务切碎再瀑布式遥控”——模型的探索能力照样被封死;没有最小混沌单元,水流理论会让模型在过大的搜索空间里迷失——错误等到失败才暴露。两者一起立起来,delegation 在大模型身上才真的能成立。
它们唯一的接触点在 checkpoint:checkpoint 是水流理论的实施位,也是最小混沌单元的验收点。它产出的笔记——加料的内容、追问澄清的事实——会沉淀回 spec 和 codemap。协作姿态上看到的东西,最终回到原料里。这是两条主线交汇的地方。
4.4 概念地图:两个核心,一组设施
读到这里,几个词可能会开始重叠:反 slop、揉搓、pre-research、spec、任务包、codemap、new-chat、上下文设施。它们不是八套方法,而是一棵树。
spec 是核心产物:反 slop / 揉搓 / pre-research,都是把目标、边界、证据、判断标准沉淀进 spec 的动作;任务包是 spec 在本轮执行里的切片。
checkpoint 是核心动作:它是实施中的介入位,负责复述目标、补约束、看证据、转向、回炉、验收。
codemap / new-chat 是支援工具:codemap 帮模型读代码地形,new-chat 帮模型重启腐烂对话;它们和 spec 一起构成上下文设施。
下面说”上下文”时要区分两个含义:§3 的上下文是模型窗口;工程流程里的上下文,是 spec / codemap / new-chat 这套外部设施。
下面用两个真实 case 把这两个理念长成血肉。一个是从 0 到 1(全新项目),一个是从 1 到 N(存量项目治理)——它们方法论核心一样但战术细节不同:0→1 是建房子,1→N 是在跑着的飞机上换引擎。
五、Case 复盘:从 0→1 到 1→N
下面这两个 case 演示 Harness 流程在不同地形下的表现:
Case A:adaptive-room-harness——一个 0→1 的全新项目(多 agent 协作 room 系统)。系统已开源,下面所有对话片段都来自真实的推进过程。Case B:脱敏后的内部存量项目治理——某大型企业客户反馈”敏感资源外发审批”能力里,同一个用户、同一个资源、同一条规则,在审批未完成前每 5 分钟反复收到审批卡片。Case B 已做业务脱敏:产品名、客户名、字段名都是替代写法,但触发链路、状态机、幂等策略和上线方式保留真实结构。
两个 case 的本质差异只在起手(5.1 展开)。一旦目标和现状清楚,后续的落 spec / 切任务 / do it / 转向 / 验收,是同一套 Harness 流程——我们用 case A 走主线把流程演示完,在相应处穿插 case B 的特殊形态。
5.1 起手·两种姿态
0→1 的起手是和模型讨论收敛目标,1→N 的起手是定位历史地形。这是上下文密度差异的第一个表现——0→1 上下文稀薄,目标都还没成型;1→N 上下文厚重,光是定位”现状是什么”就要读一堆历史 spec 和代码。后续 Harness 流程统一,但 1→N 场景下 spec / codemap / 多 checkpoint 用得密度会更高。
下面分别看两种起手长什么样。
0→1 起手·反 slop:描述需求 + 讨论收敛目标(case A)
我有一个模糊的想法——做一个多 agent 协作 room 系统:复杂任务来的时候,主 agent 可以按需拉起几个参与者讨论、拆解、生成方案。但具体怎么做,我自己也没完全想清楚——room 是按需 wake 还是常驻?参与者是谁来定?讨论什么时候算收敛?
这种”想法已经有但形态没清楚”的状态,是最危险的——直接让 AI 写代码,它会基于自己的猜测往一个方向飞奔,最后产出的东西不是我要的。
正确的起手不是写代码,是和模型讨论收敛目标。
我打开了一个 skill 叫 sdd-riper-one——这是 sdd-riper 项目里的”标准控盘入口”,它会强制我在动手之前完成 Research / Innovate / Plan 三个阶段,每个阶段都要有 review 和 approve,不允许直接跳到写代码。这种强约束特别适合 0→1:当目标本身还不清楚时,比起”日常默认入口” sdd-riper-one-light 的轻协议,sdd-riper-one 的完整阶段门禁能逼你和模型把”要做什么”想透再动手。
第一轮讨论是这样开始的:
我想做一个多 agent 协作 room:复杂任务进来,主 agent 拉起其他 agent 一起讨论、拆解、生成方案。
不要写代码。先和我讨论——你怎么理解这个目标?room 是按需创建还是常驻?参与者怎么定?讨论怎么停止?
模型给了一版理解。看完我立刻发现几处不对:
它默认 room 是常驻的——但我想要按需 wake(成本低、生命周期清晰、便于 transcript 落盘) 它把”参与者”定义成固定角色(codeowner / reviewer 之类)——但我想要主 agent 根据任务动态决定 它没考虑讨论的”收敛信号”——我想要每轮发言后判断是否产出 artifact 才停止 我把这几点反馈回去:
不,你理解错了。room 我想要按需创建——任务来了 wake、任务完了 close,不要常驻。
参与者也是动态的,不是固定角色。
讨论的收敛信号是”产出了 artifact”——不是固定轮数。
这就是水流理论的第一个动作——不规定它怎么实现,只规定它必须先和我对齐目标。如果模型复述错了,立刻拉回来。
来回三五轮之后,目标形态清晰了:
adaptive-room-harness 的核心目标:- 主 agent 接到复杂任务时,可以 wake 一个 room- room 内动态选择参与者(不是固定角色)- 多轮发言,主 agent 判断 artifact 收敛信号- transcript / artifact 落盘到本地- room 在 artifact 产出后自动 close 这一段讨论没产出一行代码,但产出了清晰的目标形态。0→1 起手的核心动作就是这个——不是写代码,是先和模型讨论,把模糊的想法磨成清晰的目标。
这一步就是反 slop。它不是”多聊几句”,而是在动手前用复述、纠正、查证、收边界,把模型的搜索空间压进 spec:先让模型把自己的理解说出来,偏了就纠正,空了就补证据,宽了就收边界。等目标被揉成 spec,再切任务包。否则模型很容易带着一个”看似合理”的误解开始狂奔,最后产出一堆漂亮但不贴地的代码和方案。
1→N 起手·读历史 spec / codemap(case B)
存量项目的起手完全不同。
我接到的任务是:某大型企业客户反馈,敏感资源外发审批卡片每 5 分钟反复推送给审批人。具体形状是:用户触发某条外发规则,系统创建一张审批卡片;但审批还没完成时,后台调度器又扫到同一个用户、同一个资源、同一条规则,于是重复发卡。这是个线上问题,必须修。但我对这个模块的现状记忆已经模糊——上次改过吗?灰度 key 是哪个?哪些边界已经触发过?
第一句话不是和模型讨论”我想做什么”,而是让模型先去定位地形:
阅读项目,我之前做了一个修复,是修复【敏感资源外发审批】反复发送审批卡片的那个 bug,我好像记到 spec 文档里了。你看看是哪一个,对应的灰度 key 是什么。
为什么是这种起手?因为存量项目的真相不在我的脑子里,也不全在代码里——主要在历史决策的 spec 文档里。让模型先扫一遍 mydocs/specs/ 找到相关历史 spec,比我从头描述需求高效得多。
这就是事实二(上下文宝贵)的实际应用:spec 是高密度的过往决策摘要,比扫整个代码库省 100 倍上下文。
如果项目没有历史 spec 落盘怎么办? 这时候才用 codemap——让模型扫一遍代码生成”地形索引”(入口、调用链、关键文件、风险点全部摘要化)。codemap 是同一个理念(节约上下文)的另一种工具,针对没有历史决策记录的存量项目场景。
存量项目里这两种姿态经常组合用:先读历史 spec 找方向,再用 codemap 验证当前代码确实是 spec 描述的那个状态——防止历史决策已经被后续提交悄悄推翻。
5.2 落初步 spec + 分解任务/边界/checkpoint
目标清楚之后,下一步不是写代码,是把目标分解成可执行的东西,并且全部落到一份本地文档里——这份文档叫 spec,是后续所有动作的真相源。
我对模型说:
基于刚才讨论收敛的目标,请你做两件事:
1.把目标整理成一份初步的 IDEA_DOC(启动 spec),放在 docs/IDEA_DOC_V2.md。包含:核心目标、关键能力、明确不做、验收维度、关键决策(含为什么)。
2.基于 spec,给我一个最小可交付的第一轮任务包:目标足够小、边界足够清楚、能在一个 session 内验完。
模型给了两份产物——一份是 spec,一份是任务包。spec 大致长这样(节选):
adaptive-room-harness · IDEA_DOC_V2(启动 spec)
注意”待后续补充”那一节——0→1 的 spec 不需要一次写完。它是启动文档,会随工作推进不断回写。我们要的不是一份完美 spec,而是一份始终在长的活 spec。
任务包是 spec 的一个具体子集。我看了模型给的任务包,反复确认了几次边界(这种来回讨论本身就是给模型补边界的过程),最终定下来:
第一轮任务包 目标: Codex CLI 能拉起两个 agent 进入同一个 room, 围绕同一任务发言,本地能留下 transcript 和 artifact。 边界: 不做 UI / 不做长期心跳 / 不做审批流 / 不做云端同步 / 不重构现有目录结构 自由度: - 模型可以自选具体实现路径 - 但 room state 字段语义、adapter 调用约定不能改 - 引入新依赖前必须 checkpoint checkpoint: - 每次准备改代码前先复述 diff 计划 - 发现”想做但不应做”的事情,立刻暂停汇报 - 完成后给 commit-ready 检查表 验收: - 一条命令创建 room - 两个 agent 进入、发言能写入 transcript - 失败时有清晰错误(不静默吞掉) - 没有顺手做 UI / 心跳等非目标能力 任务包里的每一件都在解决同一个问题:让模型能自主推进,同时让人能稳定控盘。边界负责限制范围,尤其是明确”不做哪些事”,因为模型的概率性偏差倾向于”顺手把更多事情做掉”;checkpoint 负责把推进过程拆成可观察、可干预的节点;验收负责定义结果是否真的能交付。
存量项目里 spec 长什么样(case B 视角):1→N 场景的 spec 不是从零写,是在历史 spec 上增量补。case B 那次任务,落 spec 时是”这次发现审批 pending status 没有被正确持久化,导致调度器重复扫描同一条外发规则;决策加 Tair 两段式幂等机制(processing lock 60s + active pending 30min),灰度 key 是
任务包到位,下一步才是把活交给模型,让它推进。
5.3 推进·让任务过 checkpoint
任务包定下来之后,把它整包交给模型,然后说一句话让它开始:
do it
或者:
继续 / ok / 好 / 可以
这些都是口癖——意思都一样,允许它推进到下一个 checkpoint。do it 不是某个严格定义的特殊指令,和”继续”、”ok”没有本质区别,都是 Harness 流程里的放行动作。
模型开始推进。它会读相关文件、设计 adapter 接口、写代码、跑测试、修 bug——全套自己跑。我不盯每一行代码,只看 checkpoint。
按任务包的约定,模型在准备改代码前必须先停下来汇报。第一个 checkpoint 它给我的内容大致是这样:
当前进度:已读完 room state、CLI entry、现有 mock。发现 agent runtime adapter 的 trait 还没定义。
下一步 diff 计划:
1.新建 src/runtime/adapter.rs(定义 RuntimeAdapter trait,含 wake / send / close)
2.改 src/room/state.rs(加 participants: Vec
3.加单测覆盖 wake → send → close 的最小路径
风险:room state 字段改动可能影响现有 CLI command,需要确认。
这个 checkpoint 上,我对模型的输入分三类——默认放行 / 深入观察 / 方向控制——一共 6 种动作。
类别 动作 占比 实际含义 默认放行放行— do it / 继续 / ok~9% 当前计划可接受,进入下一段 深入观察追问— 反向澄清模型~25% 先把不确定性读清楚,再决定是否推进 方向控制加料— 沿原方向叠新约束 / 优先级 / 材料~47% 同向补充信息,让模型带着新约束继续 方向控制绕道— 不对,改方向~5% 调整方案方向 方向控制回炉— 从某个上游 checkpoint 重新来~2% 回到前一个决策点局部重做 方向控制阻止— 停 / 等等<1% 先暂停(实际人多直接 ctrl-c) 数据是从我自己几个项目的真实输入分布出来的。一个反直觉的事实:
最高频的不是放行,是加料。”还有,文档开头强调聚焦的场景” / “不需要那么细” / “ok 注意核心目标,阶段目标这些都要确认” / “把 X 也补到 spec 里”——这种”沿当前方向叠新约束”的动作占了将近一半。深入观察(追问)也有 ~25%。真正的”默认通过”反而只有 ~9%。
这反映了 checkpoint 的本质:checkpoint 不是裁判判决,是细颗粒控盘。人不只是判断模型的方案对不对,更多时候是在推进过程中一边观察、一边补约束。这些补的约束、追问澄清出来的事实,有时会沉淀回 spec 和 codemap——协作中看到的东西,最终回到上下文设施里,这就是 §4 末尾说的两条主线交汇点。
所以 checkpoint 上真正要看的,不是”这几行代码我会不会亲手这么写”,而是四件事:有没有越界,目标有没有偏,证据链够不够,风险有没有被导进安全通道。这就是 §4 说的水闸注意力。
注意——checkpoint 上还有一个不那么显眼但很重要的副作用:让模型复述核心目标和当前进度时,目标会被拉回它的近期上下文。这是利用 recency bias 反向工作,对抗事实二的 lost-in-the-middle。第 N 轮对话里目标可能已经淹在中段,checkpoint 的复述动作把它推回尾段,模型下一段推进时就能更准地对齐目标。
6 种动作的具体形态:
加料——”还有,文档开头强调聚焦的场景” / “不需要那么细”。它沿当前方向叠新 spec,让 checkpoint 变成 spec 微迭代的一次回合。追问——”完成 X 现在还缺什么?” / “可以确认吗?有证据吗?” / “为什么这么做?是不是 Y 更合理?”。横向的元层动作:先把不确定的事情澄清掉,再决定 flow 哪个方向。放行——”do it / 继续 / ok”。计划合理、风险可控、还在边界内,就让它进入下一段。绕道——”回到本轮目标——不要处理 web UI、不要做心跳”。或者它的方案比我原设想更贴近代码地形,”或许该绕道”,让它先解释:为什么更适合?是否仍满足本轮目标?没扩大 scope?证据成立就顺着它(顺着模型,但不是模型说什么都对),不成立就拉回来。回炉——”这条路走不通了。回到 spec 的’按需 wake’那一节重读”。承认这一段 chaos unit 接错了,让它在局部回滚而不是流到下游再爆。阻止——理论上是”先按住它,让它把卡点结构化讲出来”。实际很少出现——不满意时人通常直接 ctrl-c 中断,而不是用言语阻止。实际输入经常是混合的——一条消息常常同时做多件事:
“ok 注意核心目标” = 放行 + 加料 “不要 mysql 改成 redis” = 绕道 + 加料 “为什么用 X?我倒觉得 Y 更好” = 追问 + 软性绕道 别强行把一条消息归为单一类别。6 种是主要桶,混合是常态。
第一轮推进结束后,模型回到下一个 checkpoint。这样一段一段往前推——每段都”小到可检查、大到可自治”(callback §4 最小混沌单元),如果某段接不上,回炉的代价只是一段,不是整段任务。
走顺利的时候,0→1 项目可能 2-3 个 checkpoint 就推到验收了。但偶尔绕道和回炉必须触发——下一节看转向的硬规则。
5.4 转向·当绕道和回炉成为必须
5.3 讲的 6 种动作里,绕道和回炉有一种特殊形态——当模型走偏到必须打断的程度。转向就是这种特殊形态的统称:不是日常微调,而是明显越界前的强制校正(强制绕道 + 强制回炉),由硬规则触发。
转向不是骂跑偏。转向是把分叉点说清楚。
case A 推进里有一次典型转向。第二个 checkpoint,模型给我的 diff 计划里包括了”实现 room 的 keep-alive 心跳”。我意识到我和模型对 room 的生命周期理解不一致。我打断它:
不,你理解错了。我的意思是 room 的生命周期:
是在一个长任务里,每需要的时候就 wake 一次、讨论一次、落地一次;
还是在一个长任务里,room 时刻保持存活,随时 ready?
模型回答:”我理解的是后者,所以才打算加心跳。”
我回:”是前者。room 按需 wake,任务完了 close。spec 里第二节’明确不做’写过——’持久化常驻 room’。回头看一下 IDEA_DOC_V2.md。”
模型回去读 spec,确认了我的理解,然后重新规划:心跳模块整个砍掉,改成”按需 wake / 任务结束自动 close”的状态机。
这就是一次完整的转向。它有几个特征:
触发点很明确:模型的 diff 计划违反了 spec 里已经定的”按需 wake”决策。打断的姿态是讨论分叉,不是责备:我没说”你又错了”,我直接把分叉说出来——”是 A 还是 B?” 让模型自己看清自己理解的是哪一种。转向后回到 spec:spec 是真相源。我让模型回去重读相关章节,而不是我口头再复述一遍。这也是为什么 spec 必须落到本地文件,不能只在脑子里——脑子里的东西会随着对话腐烂。方向校正后立刻继续:转向不是停工,是在 checkpoint 上调整方向,然后继续推进。什么时候必须转向?我有三条硬规则:
spec 冲突—— 模型的方案违反了 spec 里已经定的目标 / 边界 / 关键决策。越界—— 模型准备改动的范围超出本轮任务包允许的边界。连续验证失败—— 同一条路径,模型连续两次跑测试都失败,且没有新的证据说明继续有意义。触发这三条之一,就不再放行,必须先暂停、更新 spec、或者重切任务包。
case A 这种 0→1 项目,整个推进里转向通常只有 1-2 次主要分叉——因为目标和边界在 5.1、5.2 已经讨论得很清楚,模型偏的概率不高。
case B 视角:转向是常态
存量项目场景就完全不同。case B 那次任务,一次推进里我转向了多次。下面是 4 个典型:
1.质疑模型给的事实:「确定吗?这个 key 好像不是我的 key 啊」
2.注入业务约束:「缩减一点范围 我们用户量非常巨大的」
3.叫停过深探索:「我们太 deep 了 不应该……」
4.提自己的假设让模型验证:「每 5 分钟重复命中,是不是审批 pending status 没有正确持久化,导致调度器一直把它当成未处理请求?」
存量项目里转向是常态,不是例外。原因有两层:
上下文密度高,方案不确定性大——模型读历史 spec / codemap 拿到的是过去的快照,但代码可能已经变化、上下游可能已经改动、灰度可能已经满量。每一次它给出的方案都需要我用业务直觉验证一遍。这是上下文厚的代价:信息量大,但每一条都需要再核实。存量项目的边界比 0→1 紧得多——动一行代码可能影响线上百万用户,所以当模型说”我打算改 X”,我必须立刻判断 X 是否在允许的边界内。这种高频转向的场景里,除了上面的四种打断动作,还有一个 case A 没用到的工具特别关键:new chat。
状态机演变:
before: user triggers sensitive export rule -> create approval card -> pending status not persisted correctly -> scheduler retries every 5 min -> duplicate card after: processing_lock 60s active_pending 30min key = orgId + uid + ruleId + resourceId + targetHash 灰度 key 控制
进阶工具:new-chat skill ——对抗上下文腐烂的杀手锏
讨论完方案、落到 spec 之后,我做了一个动作:
new chat 修复这个问题?
这一句触发的是 sdd-riper 项目里的 new-chat skill——它会自动把当前 spec + handoff 喂给一个全新的 chat,旧 chat 的累积噪音和过期假设全部留在原地。
为什么要 new chat?因为前面的诊断 + 讨论 chat 已经累计几十轮对话,里面混着假设、否定的方案、临时猜测。如果直接在这个 chat 里实施,模型很容易把已经否掉的方案又捡起来用——这就是事实二(上下文宝贵)的典型翻车场景。自动总结只能延缓衰减,new-chat 是 clean restart。
new chat + 已经落地的 spec = 干净上下文 + 外部真相源——这是下一轮的最佳起手姿态。new chat 第一句话直接接 spec:
请按 spec 实现【敏感资源外发审批】审批未完成前审批卡片重复推送治理:
重点实现 spec 中的两段式 Tair pending 幂等:processing lock 60s / active pending key 30min / key 维度 orgId+uid+ruleId+resourceId+targetHash……
注意遵守 AGENTS.md:No Spec, No Code;代码改动前先复述方案等我批准。
这条 prompt 几乎完美——明确指向 spec、明确具体技术细节、明确控盘节奏。new chat 干净接手之后,后续 do it / checkpoint 流程和 case A 完全一样,case B 实施只用了一个 session 就推完。
转向之后,剩下的就是把活推到验收。
5.5 验收·多层 safety net
模型说”完成了”——这是 Harness 里最危险的瞬间。
Agent 最危险的时候不是它报错。报错至少说明它还在反馈、还知道哪里不对。更危险的是它说”完成了”,但没有证据。
不听”完成了”,要证据。
但仅靠”看一份自验报告”远远不够。AI Coding 泛滥之后,单点验收很容易漏;让 “code is cheap” 真正稳定下来,靠的不是哪一个 review,是一个 multi-layer safety net——多层叠加把风险一层层压低。这是 AI 时代工程化的最后底线。
下面是 5 层验收:
第 1 层·自验(模型自己写报告)
我会要它给一份验收报告,包含 7 个维度:
实际改了什么(diff 摘要) 跑了什么验证命令 验证结果是什么(输出 / 日志 / 截图) 哪些任务包验收标准已经覆盖(逐条对照) 哪些风险 / 边界没有覆盖 哪些参数、结果、日志可以反向证明任务做对了 如果后续出问题,建议从哪里排查 case A 第一轮 do it 跑完,模型给我的报告大致是这样(节选):
验收报告:双 agent room 闭环最小可运行版本
room create --agents <a,b> 命令)- 加 tests/room_play_test.rs(覆盖 wake → send → artifact → close)我看完这份报告,做几件事:
逐条对照任务包:报告里每一条对得上任务包验收标准吗?没对上的说清楚为什么?抽样跑一遍:报告里写的命令我自己跑一遍,看输出和它说的一致吗。这是端到端的人工验证——不是看代码,是看运行结果。检查”没覆盖的”是不是合理:比如”多 agent 并行发言冲突”没覆盖——回头查 spec,确认这一项确实在”待后续补充”里,本轮就不该做。注意:整个验收过程里,我一行代码都没看——但前提是验证证据完整:测试都跑过、命令都对得上、artifact 都落地,证据链能覆盖任务包每一条验收标准。没有这些前提,不看代码就是裸奔。
第 1 层只是起点。这一层之后还有 4 层——第 1 层只能 catch 模型自己愿意承认的问题,看不到模型自己看不到的盲点。
第 2 层·自测(让模型自己跑接口测试)
自验报告说”测试都跑过”——但跑的是单测和命令行抽样。真实生产场景的接口、线上参数、异常分支,单测不一定覆盖到。所以要让模型自己主动跑接口级测试:
模型生成测试参数(边界值、异常输入、典型业务场景、错误码触发条件) 调用测试环境的接口(HTTP / RPC / SDK call) 把返回的 JSON、日志、错误码完整喂回给自己(或喂给另一个干净 chat 的 agent) 让模型判断:返回符合预期吗?日志有异常 trace 吗?参数边界覆盖到了吗?性能指标在合理范围吗? 这一层的核心是把”运行验证”也自动化掉——不是验收的人手动跑测,是模型自己跑、自己读日志、自己判断是否自洽。模型 + 测试环境 + 接口 + 日志,组成一个闭环的自测系统。
第 3 层·他测(独立视角)
A. review by 另一个 agent
case B 的实施 chat 跑完之后,我做了一个动作:
review 一遍
让另一个 agent review 一遍
让另一个干净上下文的 agent 做 review——这相当于代码 review,但是 AI 之间的。review agent 找出了 4 处 race condition + 几个 P2/P3 级问题,都是实施 agent 自己写的时候完全没意识到的。
为什么有效?因为自己 review 自己等于没 review——实施 agent 已经在它自己的方案里”住”了几十轮对话,注意力被自己的设计锚住,看不到自己的盲点。换一个干净上下文的 agent,从中性视角扫一遍,盲点就暴露了。
这本质上是事实一(概率生成器)的应用:第一遍写的代码不可能完美,需要独立视角验证。
B. 测试同学的端到端回归
在 AI Coding 泛滥时代,测试同学的角色不是消失,是上移。他们不再写单测(那由模型 + 自动化做了),但他们做的是:
测试策略设计——基于业务理解决定哪些路径必须覆盖边界场景探索——AI 想不到的奇怪 corner case,靠人的业务直觉抓端到端流程回归——跨服务、跨模块的真实业务流,不靠 mock机器永远找不到的 corner case,靠人的业务直觉抓。在所有都被 AI 写的世界里,测试同学的人为回归是工程化最后的人为底线——他们的工作不是被 AI 取代,而是变得更不可替代。
第 4 层·自动化回归 + 自动化巡检(CI/CD 兜底)
A. CI/CD 全量自动化回归:每次合并前跑全套自动化测试套件——单测、集成测、契约测、性能基准。这不是 nice to have,是必须。AI 写代码快,但 AI 经常会破坏隐式假设;只有完整回归才能 catch AI 不知道的旧 contract。
B. 自动化巡检:覆盖代码风格、安全漏洞扫描、依赖版本检查、性能指标基线、错误率告警、SLO 预算。巡检不验证”代码做了什么”,验证”代码没破坏什么”——这两者都要有。
第 4 层是工程基础设施,一次建好长期受益。没有这一层,前 3 层全是裸奔——因为模型只能 catch 它知道的东西,巡检 catch 它不知道的偏离。
第 5 层·灰度 + 金丝雀 + 一键回滚(线上兜底)
review 找出问题修完之后,不一定走完整本地回归再发——前提先说清楚:边界已经卡死、灰度 key 完全可控、监控覆盖到位、一键回滚就绪。满足这套工程基础后,下面这段对话才合理:
「我想的是不测直接发 可以吗」
「最坏的问题?」
「ok 我觉得加一个灰度 这样我不需要测试就行」
单独看像不负责任,但在前提到位时这其实是合理的速度选择——用灰度 + 监控替代完整本地回归,不是放弃验证。
存量项目里更深一层:
「这个【冲突】可以加灰直接止血吗?比如先触发发卡 陆续发的过程中加灰 然后立刻止血」
这是用灰度作为应急止血的工具——线上已经在出问题,等不及测试,先发出去然后快速加灰收回风险。这不是”赌”,是用灰度 + 金丝雀作为一种 in-flight 风险控制工具。
风险越高,启用的层越多:
场景 启用层 Case A(0→1,没线上流量) 第 1 层(自验)+ 第 2 层(自测) Case B(1→N,有线上流量) 全 5 层关键基础设施 / 生命攸关系统 全 5 层 + 影子流量 + 金丝雀长期观察 + 多级回滚预案
多层 safety net 的核心姿态
代码廉价化不是放弃验证,是把验证从”人手 review 代码”迁移到”多层自动化 + 关键节点人工兜底”:
越靠前的层(自验、自测)由模型 / 工具自动跑——速度快、成本低、覆盖大量但浅 越靠后的层(人工回归、灰度、金丝雀)由人 + 工程基础介入——慢但 catch 自动化漏掉的关键风险 每一层都不能少。AI Coding 泛滥之后,多层 safety net 是工程化的最后底线——也是让 “code is cheap” 真正稳定常态的工程基础。
case 复盘到这里完整跑完。整套 Harness 流程的标准动作 + 两种 case 的差异:
步骤 0→1 动作(case A 主线) 1→N 特殊形态(case B 穿插) 5.1 起手描述需求 → 多轮讨论收敛目标(sdd-riper-one / 复述目标) 读历史 spec / codemap 定位地形 5.2 落 spec + 任务包讨论结果落成启动 spec,分出第一个任务包 spec 是在历史 spec 上增量补,不是从零写 5.3 do it + checkpoint让模型自主推进;checkpoint 上 6 种动作(放行 / 阻止 / 绕道 / 回炉 + 追问 / 加料) (同 case A) 5.4 转向1-2 次主要转向(spec 冲突 / 越界 / 连续验证失败) 高频转向(4+ 次连环:质疑 / 约束注入 / 叫停 / 提假设)+ new chat 干净实施 5.5 验收第 1 层自验 + 第 2 层自测(低风险够用) 全 5 层启用:自验 / 自测 / 他测(review agent + 测试同学)/ 自动化回归 + 巡检 / 灰度 + 金丝雀
5.6 复述机制·对抗两个事实的同一个动作
回头看,整个 Harness 流程里,”让模型复述”这个动作出现了两次,目的不一样:
阶段 复述目的 对抗哪个事实 实施前反 slop(§5.1 揉搓 → 复述 → 纠正 → §5.2 精华 spec)让模型暴露理解偏差,人纠正后再重述,逼出共识 事实一:把搜索空间从无限收窄到 spec 级别实施中(§5.3 checkpoint 上的复述)让目标重新进入模型近期上下文,对抗注意力衰减 事实二:用 recency bias 反向把目标推回尾段同一个动作,两种用法。实施前,它防止模型在错误目标上产出 best-practice slop;实施中,它持续把目标、边界、证据和新约束拉回上下文窗口。也是为什么 spec 必须落在本地文件、必须反复回写:spec 不只是一份文档,它是实施前揉搓出来的共识,也是实施中反复把注意力拉回来的锚点。
case B 末段抛出的”不测直接发 + 灰度兜底”听起来像不负责任,但它实际是 Harness 时代上线策略的合理形态——背后的工程逻辑就是代码廉价化。下面 §6 §7 展开。
六、升华:代码廉价化的四个层级
走到这里,前面铺垫的论点可以收拢了。代码廉价化不是孤立的现象,它在工程上引发四个层级的连锁后果——每一层都已经在前面段落里出现过,这一节把它们一句话推到底。
现象层·代码可抛弃性
§1 说代码正在变得非常便宜。这件事推到极致就是——代码不只是便宜,是可抛弃。
case B 末段的”不测直接发 + 灰度兜底”就是这个逻辑的具体落地:一段功能写出来,灰度发现方向不对,直接 drop 重写。只要边界清楚、破坏面可控,这是合理的工程选择。
这意味着传统工程师追求的很多东西被釜底抽薪——不再需要为了”以后改不动”做复杂架构;不再需要为了”代码寿命”做精细优化;不再需要把代码当瓷器去捧。
代码不再是瓷器,也不再是一次性消耗品——它是卫生纸。用过就扔,写得不好就撕一张新的。
但这句话有边界。生产事故不是卫生纸,用户信任不是卫生纸,组织责任不是卫生纸。代码可以便宜,后果不能便宜——所以下面 §6.3 §6.4 才需要把工程纪律从”手写代码”整体上移到”边界 + 证据 + 灰度 + 回滚”。
工作方式层·高速迭代压倒一切
一旦承认代码是卫生纸,整个程序员的工作方式必须推翻重来。新的工作方式核心只有一个词——高速迭代。
快速写、快速测、快速上线;出问题就快速回滚、快速重写、快速改;不可维护就直接另起炉灶。
为什么以前不能这样?因为以前代码贵——写慢、改慢、重写贵——所以完美主义、过度设计、架构评审都有经济意义。但今天 AI 让”写”几乎免费,CI/CD/灰度让”测/上线/回滚”标准化。真正贵的不再是代码,是时间窗口和市场反应速度。
一句话总结:如果代码贵,节俭代码;如果代码廉价,节俭时间。代码是过程,不是资产。
实践姿态层·我经常不看代码
§5.5 已经埋过一个伏笔——case A 验收过程里,我一行代码都没看。
这不是疏忽。是 Harness 时代质量控制面的根本转移。
我看的是:模型说做了什么、跑了什么验证、结果是什么、命令我自己跑一遍输出对不对。我不关心模型某段代码够不够优雅,我关心端到端效果是否成立。
这背后的逻辑是 §4 水流理论里”控制点上移”的最终形态——从代码细节,上移到目标、边界、检查点、验证结果。工程质量从”源码级审美”,迁移到”结果、证据、风险控制”。
这不是不要质量,是质量的来源从”亲手写出优雅代码”变成”任务包 + checkpoint + 多层 safety net(自验 / 自测 / 他测 / 自动化回归 + 巡检 / 灰度 + 金丝雀)”——是工程纪律对个人审美的替代。
但这也有硬边界。
0→1 项目、内部工具、demo、原型,或者任务包边界清楚、验证证据完整、可灰度可回滚、代码本身可抛弃的场景,适合这种姿态。你可以少看代码,多看结果;少纠结实现细节,多盯证据链。
但权限、支付、安全、数据删除路径,基础库 / SDK / infra 核心,隐式 contract 多、测试覆盖差的老系统,或者没有灰度和回滚机制的线上改动,不适合这样玩。那不是同一种工程地形,也不该用同一种工作姿态。
身份层·工程师价值结构在迁移
§2 说过,长尾在以周为单位拉开。差距不在”会不会用 AI”,在”用到第几层”。
走完整篇文章,”用到第几层”应该清楚了——它不是技术差距,是工程师价值结构在系统性迁移:
一线工程师:从”写代码的人”迁移到”切任务包 + 做 checkpoint + 看证据的人” TL:从”评审 PR 的人”迁移到”定 spec + 设 codemap + 看 review agent 报告的人” 架构师:从”设计模式的人”迁移到”设计协作姿态、控制面、Harness 工具集的人” QA:从”写测试用例的人”迁移到”设计测试策略、做端到端回归、抓 AI 想不到的 corner case、写灰度兜底”——AI 时代 QA 的角色不是消失,是上移;是 multi-layer safety net 里唯一不能被 AI 替代的人为底线
这条迁移路径上的人,正在重新定义”工程师”这个职业的内核。
七、收口:把方法变成团队能力 + 操作卡片
要让这条迁移路径走通,方法不能只在高手脑子里——要让团队能复用,就得把它沉淀成 skill 和模板。
sdd-riper 项目里有四个可以配合使用的入口:
sdd-riper-one-light—— 日常默认入口,适合已经切得清楚的任务。重点是 micro-spec / checkpoint / 证据 / handoff。sdd-riper-one—— 标准控盘入口,适合复杂项目、架构变更、团队训练、审计交接,强制 RIPER 五阶段门禁(case A 用的就是这个)。codemap —— 给陌生代码库做”地形索引”的入口(case B 在没有历史 spec 时会用)。本质是节约代码上下文——不用把整个 repo 塞给模型,用一份摘要导航按需回读。new-chat—— 对抗上下文腐烂的杀手锏。把当前 spec + handoff 自动喂给一个全新的 chat,旧 chat 的腐烂全部留在原地。自动总结只能延缓腐烂、且有损压缩;new-chat是 clean restart,节约对话上下文的真正解。case B 落 spec 之后用的就是这个。四者的握手协议:
codemap 告诉模型 代码地形 在哪 /
spec 告诉模型 这次任务到底要什么 /
checkpoint 告诉人类 模型下一步准备怎么动 /
new-chat 告诉所有人 旧上下文已经腐烂,用 spec 重启 /
证据告诉团队 结果是不是能交付。
spec / codemap / new-chat 是上下文管理三件套——分别对应持久化精炼 / 读码有重点 / 跨 session 换水。三者都是事实二”上下文宝贵”的具体武器,也是最小混沌单元在每一段任务里能立得住的工程基础。
如果只带走一张卡片,就是这张:
未来真正稀缺的,不是写代码的人,而是能让大模型在正确边界里大胆流动,并且把端到端结果安全收回来的人。
千问云-为Agent而生,驱动AI生产力 扫描下方二维码,直达千问云体验
点击阅读原文即可体验!