让 AI Coding 从提示词驱动,走向有护栏、有证据、可恢复的工程治理 系统。
原文链接 :AI 小老六
导语
把 AI 接进研发流程以后,最容易被误判的一件事是:只要模型足够强,编码交付就会自然变快。真实落地时会发现,模型生成代码的速度并不是瓶颈,瓶颈常常出现在它周围的工程环境里。
一个编码智能体可以快速读文件、改代码、跑命令,但它也会忘记上下文、误判团队约束、绕过分层边界,甚至在验证没有完成时给出"已完成"的结论。工程师被迫反复补充提示词、贴报错、纠偏、复查,最后形成一种很别扭的状态:表面上是在用 AI,实际是在给 AI 当流程调度器。
本文讨论的不是"怎么写更好的 Prompt",而是另一个更工程化的问题:如果要让 AI 真正参与服务端交付,需要在大模型和 Code IDE 之间补上一层什么样的治理系统。
答案可以概括为两层:
| 层 | 核心职责 |
|---|---|
| Harness | 把知识、权限、状态、证据、失败处置和自进化机制组织成一套可执行的研发治理框架 |
| Loop | 驱动 Harness 自动推进,把人从重复的过程干预里拿出来,只在关键判断点介入 |
这套体系的目标不是让人退出研发,而是让工程师不再被迫一拍一拍地驱动 AI,把注意力重新放回架构判断、风险取舍和最终交付质量上。
从"模型能力问题"转向"工程治理问题"
一次普通 AI Coding 任务里,模型真正写代码可能很快,慢的是它不知道该怎么安全地完成这件事。
它可能不知道仓库分层约束,把 infra 反向 import 到 biz/strategy;它可能改了一个调用点,却漏掉另一个入口;它可能跑通了局部测试,却顺手改了不该碰的函数;它也可能在失败后不知道该回滚、重试,还是停下来问人。
这些问题看起来像模型不够聪明,但根因并不全在模型。更准确地说,是模型被放进了一个过于裸露的工程现场:
- 没有稳定的项目地图,它只能临时猜仓库结构。
- 没有硬边界,它可以在规划阶段直接动业务代码。
- 没有证据闭环,它会把"我认为完成了"当成交付结果。
- 没有跨会话记忆,上一次纠正过的问题下一次还会重犯。
这类问题很难靠"提示词写详细一点"解决。提示词是软约束,工程交付需要的是硬机制。
图:人工驱动的 AI Coding 循环,问题集中在人反复补上下文与纠偏。
真正需要补齐的,不是另一个更长的提示词,而是一层能把 AI 行为纳入工程秩序的运行环境。
四层分工:智力、工具、治理和驱动
图:AI Coding 体系中,智力、工具、治理和驱动需要分层协作。
在 AI Coding 体系里,至少要区分四件事:谁负责思考,谁负责执行,谁负责治理,谁负责推动流程。
| 层级 | 负责什么 | 类比 | 不负责什么 |
|---|---|---|---|
| 大模型 | 理解需求、生成代码、做语义判断 | 一颗强但健忘的 CPU | 不记住组织约束,不保证每次正确 |
| Code IDE / CLI | 读写文件、跑命令、调用工具、连接 MCP | 操作系统或容器运行时 | 不判断这一步该不该做 |
| Harness | 知识、权限、状态、证据、失败处置、自进化 | 框架、网关、流水线、配置中心的组合 | 不产生智力,不替代 IDE 工具 |
| Loop | 自动推进流程,在卡点找人 | CI/CD 流水线 | 不亲自写代码,不绕过确认 |
大模型提供智力,Code IDE 提供工具,这两层都会持续变强。但它们叠加起来仍然缺一层东西:谁来规定当前阶段允许做什么、产出是否可信、失败后往哪里退、经验如何沉淀。
Harness 解决的就是这层治理。Loop 则负责把 Harness 驱动起来,让流程不再依赖人每一步手动敲"继续"。
图:大模型、Code IDE、Harness 与 Loop 的四层职责边界。
开发前:把仓库变成 AI 能安全进入的工作区
智能体每次会话都近似从空白开始。它不会天然知道这个仓库的模块边界、接口入口、构建命令、分层约束,也不会知道哪些行为是团队长期禁止的。
所以在真正交给 AI 写业务代码前,Harness 先做一件看似"不产出需求代码"、但非常关键的事:把普通仓库整理成 AI 能读懂、有接口资料、有提交护栏的工作区。
这一步可以拆成三层。
| 准备层 | 产物 | 解决的问题 |
|---|---|---|
| 知识层 | AGENTS.md、ARCHITECTURE.md、docs/AGENTS.md |
给模型一张稳定地图,而不是让它临时 grep |
| 接口层 | docs/reference/<接口>.md |
把调用链、入参出参、PSM、IDL 映射前置成资产 |
| 护栏层 | .harness/、pre-commit、pre-push、分层校验脚本 |
在提交点拦住违反工程约束的变更 |
知识层:地图比百科全书更有用
知识层不是把所有代码解释一遍,而是给模型一张足够稳定的项目地图。
AGENTS.md 负责导航,告诉模型不同任务该看哪里;ARCHITECTURE.md 承载架构约束、依赖方向和不变量;docs/AGENTS.md 按任务场景把文档组织起来。
这里的关键取舍是:知识不是越多越好。过时或低质量的知识会主动误导模型,比没有知识更危险。高层结构、模块边界、构建测试命令、分层约束这些稳定信息,适合沉淀;具体实现细节则不适合每次代码合入后机械同步。
接口层:把一次次检索变成可复用资产
服务端需求经常围绕接口展开。模型需要知道接口入口、调用链、入参出参、IDL 映射、PSM 以及相关目录。如果每次都让模型自己 grep,它会把大量上下文窗口消耗在原始代码扫描上。
以 AskQuestion 接口为例,读现成接口文档只需要约 5431 字符,约 1.6k tokens;如果让模型自行 grep 并拼出上下文,会命中 10 个业务文件,约 73872 字符,约 22k tokens。后者大约是前者的 13 倍,而且还建立在"模型知道该搜什么、不会重复读"的理想前提上。
接口层的价值在于把检索成本从"每次需求都付一遍"变成"建一次、反复用"。
护栏层:提交点必须有硬门禁
知识层让模型看得懂,护栏层让错误不容易进入仓库。
Harness 会把分层依赖校验、增量 gofmt、go mod tidy 干净性检查、OpenSpec 门禁等能力挂到 Git hooks 上。比如从 ARCHITECTURE.md 中读取依赖方向,生成 check_layer_dependency.sh,拦住 infra 反向 import biz/strategy 这类违反架构不变量的代码。
这一步的边界也要讲清楚:hooks 只在提交或 push 时生效,不能管理开发过程本身;知识和门禁也会过期,需要被检测和刷新。也就是说,开发前准备只是把工地建好,还没有解决"施工过程如何受控"的问题。
开发中:用运行时把 AI 行为管起来
图:运行时护栏把模型行为纳入可控、可观、可恢复的边界。
开发中阶段,Harness 要回答的问题是:一次需求从规划到实现、验证、推送、归档,如何做到可控、可观、可恢复、可扩展。
这四个性质对应四套机制。
Guard Runtime:正确性不能靠模型自觉
可控是 Harness 的核心。一个会忘、会编、会抄近路的执行者,不能只靠提醒它"请遵守规则"。Harness 用四道防线把不确定性关进确定边界里。
| 防线 | 机制 | 解决的问题 |
|---|---|---|
| 硬执法 | pre_tool_use Guard 按 control.yaml 裁决工具调用 |
让越界写操作在执行前被阻断 |
| 验令牌 | 每代 framework_token 控制运行态修改 |
防止模型或脚本伪造框架状态变更 |
| 证据 + 权限前置 | verifier 派生 emit,派单前钉死工具和写路径 | 结果不靠模型自报,权限不靠临场判断 |
| 失败处置 | heal 由内核引擎裁定 | 失败后往哪退,不交给刚失败的执行者决定 |
Guard 的关键在于它不读 Prompt,也不相信模型自述。它只看运行时投影:当前节点是谁、允许写哪些路径、处于执行还是暂停状态、generation 是否匹配。
同一个 .go 文件,在不同节点下会有完全不同的裁决结果:
图:同一写操作在不同流程节点下会得到不同的 Guard 裁决。
这不是提示词能提供的硬度。提示词最多告诉模型"不要这样做",Guard 则让"这样做"根本执行不了。
Evidence Runtime:过程必须可回放
AI Coding 最让人不安的不是它会出错,而是它出错以后不知道错在哪。Harness 把关键过程都落成结构化记录:
| 文件 | 内容 | 用途 |
|---|---|---|
current.yaml |
当前节点、状态、恢复点 | 单一事实源 |
audit.jsonl |
谁通过什么机制改了状态,依据什么证据 | 回放推进与回退 |
observations.jsonl |
Guard 拦截了什么工具、目标路径、原因 | 追踪越界行为,也是后续自进化原料 |
这些记录不是普通日志噪声,而是带证据的运行时账本。写入方只能是框架内核,所有写入走统一接口并凭令牌,不接受 by=user 这类自报,也不允许 Prompt 或普通脚本直接改文件。
这样才能保证并发安全、状态一致,也保证可观测性不会因为有人绕开接口偷偷改盘而失真。
Recovery Runtime:断点续跑不能带病运行
一次需求可能跨多次会话,也可能被上下文压缩中断,甚至换人接手。Harness 的恢复机制分两层。
第一层是流程能续。状态和产物都落盘,续跑时读取 current.yaml,知道上一次跑到哪个节点、当前变更是什么、下一步该从哪里继续。
第二层是环境能自检。续跑不是无条件信任旧状态,而是重新跑一遍就绪校验,包括工具是否存在、环境变量是否齐全、能力注册表是否完整,以及开发前装好的门禁是否过期。
门禁新鲜度不靠感觉,而靠 .harness/.gate-stamp.json 里的版本号和各脚本 sha256 指纹比对:
| 结果 | 含义 | 处理 |
|---|---|---|
ok |
版本和指纹一致 | 放行 |
stale |
版本或指纹不一致 | 触发刷新 |
uninitialized |
从未初始化 | 阻断并要求初始化 |
这解决了开发前准备的一个老问题:知识和门禁会过期,但不能指望人每次都想起来检查。把新鲜度检测嵌入每条流程的起点,才是真正可持续的做法。
Flow Runtime:新增流程不应该改内核
如果每增加一个流程、接入一个能力都要修改框架内核,系统很快会变成一堆特例。Harness 的设计是把流程顺序从代码里挪到模板里,把能力职责收进自包含契约里,内核只认三种结构:
| 结构 | 作用 |
|---|---|
| flow | 节点和路由 |
| contract | 门禁、输入输出、verifier、emit |
| control | 当前节点的权限投影和执法依据 |
能力是积木,模板是接线,内核是装配工。
图:能力、模板与内核分离后,新增流程不需要改动系统地基。
在内核和 Guard 代码里,不应该写死 plan-writer、dag-executor 或 phase-0 这类具体能力名。节点合法性来自模板,路由来自 emit,权限来自 contract 编译后的 control。
这样新增流程时,改的是模板和契约,不是系统地基。
业务视角:一次交付如何形成闭环
从业务架构看,Harness 覆盖三个阶段,Loop 站在上层驱动整条链路。
图:开发前、开发中与跨需求自进化构成完整交付闭环。
开发前的知识和门禁是开发中的基底;开发中产生的纠正信号,又会进入跨需求自进化;自进化结果回写到知识、门禁或框架 lesson,下一次交付的起点就更高。
这不是一次性工具,而是一个会吸收使用反馈的工程系统。
系统视角:控制面只编排,不直接写业务
从系统架构看,Harness 可以拆成入口层、调度层、功能层、基建层,以及旁路的自进化治理。
图:Harness 控制面负责编排、证据与边界,不直接写业务代码。
这里有几个硬原则:
- 控制面只编排、路由和收证据,不直接写业务代码。
- 能力节点互不直接调用,只通过 emit 和运行态交互。
- Guard 是唯一硬边界,按内核写下的
control.yaml裁决每一次工具调用。 - 自进化、知识维护、架构守护属于旁路能力,可插拔,不阻塞主链路。
Loop:自动推进,但不绕过人的判断
Harness 让一次开发过程受控,Loop 让这个过程不再依赖人每一步手动推动。
Loop 不是"设个定时器让 AI 无人值守乱跑"。它真正做的是把非必要的人类干预拿掉:补上下文、决定下一步、跑校验、失败重试这些动作由流程接住;真正需要人负责的地方,例如关键授权、blocking 未决项、最终确认,仍然停下来找人。
一个完整 Loop 大致由这些模块构成:
| Loop 模块 | 作用 | Harness 中的对应能力 |
|---|---|---|
| Automations | 自动触发和推进 | 跑完节点、收证据、算下一步、派下一单 |
| Skills | 把项目知识沉淀下来 | 知识层、接口层、节点 contract |
| Sub-agents | 生成和检查分离 | coco exec 独立子进程、plan-review、dag-executor |
| Plugins / Connectors | 接入真实平台 | Git、Codebase、飞书、TCC 等连接 |
| Worktrees | 多任务隔离 | 独立工作目录 |
| Memory | 跨会话状态 | .harness/runtime/ 状态与产物 |
Loop 的关键不在于"能不能继续跑",而在于"该不该继续跑"。
以 OpenSpec 规划为例,第一层是确定性的工程校验:openspec validate --strict 检查格式、章节和 schema。它可以判断方案结构是否合法,但看不懂内容是否真的可执行。
第二层是语义评审:独立的 plan-review 子进程逐条判断 Open Questions 是否存在 blocking 项。
比如下面两段从格式上都合法:
markdown
## Open Questions
- 无阻塞当前实现的未决项。
markdown
## Open Questions
- GetSelfServiceProgressDisplayRequest.shop_order_ids 在真实接口侧是否要求逗号分隔、JSON 数组字符串,还是允许单个订单 ID 字符串。
- biz_type=4 之外是否还会有其他业务类型接入,以及是否需要做数值到业务枚举名的转换。
- 当展示查询返回空文案但无错误时,是否应保留空字符串原样返回,还是增加服务端兜底文案。
工程校验会认为二者都通过,但语义评审必须把第二段判定为 blocking,因为这些问题直接影响接口实现。如果没有 blocking,Loop 自动往下走;如果存在 blocking,Loop 停下来找人确认。
图:OpenSpec 先过工程校验,再由独立评审判断是否存在 blocking 问题。
Loop 的安全性建立在 Harness 之上。没有 Guard、证据、heal、状态落盘和卡点确认的自动循环,只是把错误也自动化了。
自进化:把同一个纠正只发生一次
图:真实纠正被沉淀为知识资产,下一次交付从更高起点开始。
单次开发跑稳之后,还有一个更长期的问题:同一个坑不应该每个 session 都重新踩一次。
工程师经常会在开发中纠正 AI:"这个接口入参要先校验""这层不能直接依赖那个实现""这个场景之前出过事故"。如果这句话只活在当前对话里,它就会在会话结束时消失。下一次模型从空白开始,仍然可能犯同样的错。
这就是意图债:组织没有沉淀下来的隐性约束,会以一次次人工纠偏的形式反复偿还。
Harness 的自进化机制把纠正变成结构化资产,分三步走。
收集:把纠正落成 correction
纠正信号有四类,其中前三类本来就在运行时产生,只是过去没有被系统性消化。
| 来源 | 触发点 | 记录位置 |
|---|---|---|
guard_deny |
Guard 拦下一次越界 | observations.jsonl |
heal_fail |
同类失败撞到预算上限 | heal 记录 |
review_reject |
评审给出 blocking 结论 | 评审结论 |
user_correction |
工程师当场纠正 | /harness-correct 新增入口 |
一条 correction 可以长这样:
json
{
"source": "guard_deny | heal_fail | user_correction | review_reject",
"node": "implement",
"signal": {
"what": "把 infra 直接 import 了 biz/strategy",
"expected": "infra 只能依赖 biz/shared/port",
"evidence_ref": "observations.jsonl#L42 | audit run-id | 用户原话"
},
"scope_hint": "project_knowledge | framework"
}
收集不应该打扰主流程。写入失败最多留痕,不能影响当前需求继续交付。
分析:聚类根因,只给建议
不是每条 correction 都立刻改文件,而是在会话收尾或同类问题累计到阈值时,由独立判定者聚类根因,判断它属于项目知识缺口还是框架问题。
yaml
clusters:
- root_cause: "infra 层反向依赖 biz/strategy(架构不变量被违反)"
occurrences: 3
scope: project_knowledge
target_doc: "ARCHITECTURE.md"
proposed_patch: "在「依赖方向」补充:infra 仅依赖 biz/shared/port,禁止 import biz/*/strategy 实现"
- root_cause: "Guard 对 sed -i 判定误拦了合法的 action 脚本"
occurrences: 4
scope: framework
proposed_fix: "judge_bash 放行带 token 的 action 声明前缀"
判定者只给建议,不能直接改盘。改不改、怎么改,必须进入下一步确认。
回写:项目知识走分支,框架问题走 lesson
如果判定为项目知识缺口,回写目标就是开发前那套资产:
| 缺口类型 | 回写位置 |
|---|---|
| 架构约束、依赖方向、不变量 | ARCHITECTURE.md |
| 模块边界、项目地图、常用命令 | AGENTS.md |
| 接口入参出参、调用链、PSM | docs/reference/<接口>.md |
| 其他长期项目约束 | 项目 lesson |
回写不能直接落主干。框架在新分支上生成知识 patch,给出 diff 摘要,人确认后再提交,最终合入仍走正常 MR。
如果判定为框架问题,例如某个门禁误拦合法操作、某个流程设计不合理,则自动登记为框架 lesson,交给维护者消化。原文中的 OpenClaw 示例说明了这类机制的价值:当 developer-plugin 仍引用 v1 skills/harness-entry/setup/reference 旧目录结构,而 v2 已迁移到 kernel/guard/flow/selfguard 后,问题被提报、定位为文档协作类缺陷,并在后续版本中通过更新 guardian_audit.py 的 REQUIRED_SOURCES 等方式修复。
自进化的关键不在于"AI 自己变聪明",而是把真实使用中的纠正不断写回系统。下一次开发开始时,模型读到的已经是吸收过上次教训的知识和规则。
模型变强以后,治理层仍然有价值
一个常见问题是:如果未来 Codex、Claude Code 这类通用 Code Agent 越来越强,这套框架会不会很快失效?
答案取决于我们把问题分成哪两类。
第一类是模型能力不足带来的问题,例如代码质量不稳定、复杂任务拆解不好、局部逻辑想不周全。这类问题会随着模型升级持续缓解。
第二类问题不会因为模型变强自然消失:
- 模型不会天然知道你团队的分层规约、内部中间件、历史事故和接口禁忌。
- 组织需要权限边界、审计证据和可回放过程,而不是"模型说完成了"。
- 推远端、合主干、发布等关键动作必须有人负责拍板,这是责任归属问题。
- 每次会话从零开始的问题,仍然需要外部记忆和知识沉淀机制来解决。
通用 Code Agent 未来可能内置更好的记忆、子代理、任务拆解和自动循环,但它不可能天然对齐每个组织的工程上下文。内部平台、Codebase、飞书流程、TCC、发布规范、团队架构习惯,都需要团队自己定义治理层。
因此,Harness 押注的不是某个模型,而是一层可替换、可演进的组织工程治理 :
图:治理层稳定承载组织约束,模型、执行器和平台都可以替换。
模型会换,执行器会换,平台连接也会换。真正稳定的是知识层、契约、Guard、流程、证据、审计,以及它们背后承载的组织习惯。
结语
AI Coding 的核心矛盾,不是"模型能不能写代码",而是"组织敢不敢把真实交付过程交给一个不完全可信、会遗忘、会误判边界的执行者"。
只靠提示词,工程师会一直留在循环里,负责补上下文、贴报错、纠偏、确认下一步。Harness 和 Loop 要解决的是这件事:把可确定、可重复、可验证的部分交给系统,把真正需要判断和负责的部分留给人。
Build the loop, stay the engineer。搭建 Loop 的意义,不是让工程师变成按启动键的人,而是让工程师从低价值的过程驱动里退出来,继续站在目标、架构、风险和交付质量的判断位置上。
推荐阅读
Loop Runtime 架构拆解:别再手动催 Agent,先把工程闭环跑起来
Hermes Agent Skill Runtime 架构拆解:让 AI Agent 不再从零开始