本文是「AI 效能」系列的总设计,讨论 Harness 在软件研发自动化场景中的流程骨架。同系列还包括 all-repos 本地镜像 与 AI 自动开发的架构设计。
先给出答案
这套流程只保留三个部分:持久化层保存任务的等级、工作流状态与错误信息;代码编排层轮询领取任务、调用能力入口、读取交接物并推进状态;AI 能力层在工作空间里执行业务并产出标准交接物。三者之间靠「状态 + 交接物」解耦,而不是靠自然语言对话互相猜测进度。
关键要点
- 流程不按传统岗位划分,业务上只有产品与交付两个抽象角色。
- 任务分级是进入自动链之前的门槛,本身不进入状态树。
- 每个节点只有 pending、in_progress、completed 三种状态。
- 代码只校验交接物,不解析自然语言。
- 阻断由人工解除,技术异常自动重试,重启按节点边界恢复。
三层结构
持久化层是唯一的状态事实来源。它保存任务等级、当前工作流状态、错误信息,以及通知投递记录;通知独立落表,投递失败重试也不影响主流程。这里刻意不做过度拆分——不单独拆流程表、节点表或调用记录表,状态集中在一处,避免多处写入带来的不一致。
代码编排层负责领取与推进。它不承载业务判断,只做三件事:按状态确定当前节点与动作、调用对应的能力入口、读取并校验交接物是否合法。AI 能力层则在被授予的工作空间里执行任务,产出结构化交接物。
三层的边界很清楚:能力层不直接访问持久化层,编排层不解析自然语言,只读取节点约定的交接物;本地不保存流程状态,本地快照只是投影,随时可以从持久化层重建。
两个角色与顶层流程
系统没有传统岗位划分,业务角色只有两个抽象:产品工程师承担产品流程,交付工程师承担交付流程。
Product: task(分级 gate) → prd(in → do → out)
Delivery: development(in → do → out) → testing(in → do → out) → archive(人工)
每个节点都按同一个节奏推进:in 负责进入与准备,do 负责执行,out 负责收口与产出。产品流程复用同一套节点动作,交接物统一挂在产品节点上;归档是人工节点,不调用能力入口。
任务分级作为入口门槛
任务分级发生在进入自动链之前,由上游接口写入等级,不进入状态树。这样自动链本身保持简单,不为分级再增加一层状态。
| 等级 | 范围 | 处理方式 |
|---|---|---|
| XS | 改字段、改文本这类极小需求 | 自动领取并执行 |
| S | 不跨业务模块的功能变更 | 自动领取并执行 |
| M | 跨模块、需要业务判断的需求 | 默认进入人工协同,不自动领取 |
| L | 需要架构级拆解的大需求 | 先由人工拆成多个 M |
分级的意义是把自动化的野心限制在能力可控的范围内。等级越界,失败面就不可控;因此自动链只认 XS 与 S,其余等级交给人工协同承接,具体边界见 AI 自动开发的架构设计。
节点状态与推进规则
每个节点有 pending、in_progress、completed 三种状态,当前动作取 in、do、out 或空;自动链结束后清空当前动作。推进规则可以概括为一张表。
| 场景 | 结果 |
|---|---|
| in 通过 | 节点进入进行中 |
| do 通过 | 保持进行中,继续执行 out |
| out 通过 | 节点完成 |
| 任一动作被拒绝 | 保持当前动作,写入阻断原因 |
| 执行异常 | 记录错误、累加失败次数,自动重试 |
阻断原因非空时,编排层停止领取该任务,由人工处理后清除;技术异常走自动重试,达到上限后停止。两种失败被明确区分:需要人判断的停住等人工,纯技术波动交给重试。
交接契约
能力层每完成一个动作,都在工作空间内写入标准交接物,形如一份结构化结果加一份可读说明。交接物必须包含 result 字段,取值为 passed、rejected 或 error,其余字段由具体节点的能力定义。
编排层只做有限校验:JSON 合法、任务标识一致、result 合法、必要产物确实落在工作空间内。通过后,它读取对应的说明文档继续推进。某些关键节点还有硬约束,例如产品收口必须存在非空的产品文档,测试收口必须存在非空的测试报告,否则节点不得标记完成。用「产物是否真实存在」代替「对话里是否说过」,是这套设计可靠性的来源。
异常与恢复
程序重启后不做调用级续跑,而是按节点边界恢复:未阻断的进行中节点退回 pending,保留当前节点与入口动作作为重入标记,从节点入口重新执行,避免把半途状态误判成一次全新的 AI Loop。
完整初始形态第一次进入自动链时会重建工作空间代次并固化现场,同一代次内复用;已经有进度的任务,则按恢复现场处理。一个任务对应一个固定工作空间代次,既保证现场隔离,也避免重复初始化。
设计原则
- 状态只保存在持久化层,通知独立落表,本地不保留真相。
- 一个任务对应一个固定工作空间代次,代次内复用同一现场。
- 分级门槛由上游写入,自动链只执行产品、开发、测试,归档由人工维护。
- 能力层不访问持久化层,编排层只校验交接物;阻断人工解除,异常自动重试,重启按节点边界恢复。
常见问题
为什么流程里没有传统岗位?
因为流程关心的是「产出是否满足进入下一步的条件」,而不是「由谁来做」。产品与交付两个抽象角色足以覆盖环节划分,具体谁来执行不影响流程状态机。
为什么代码不解析自然语言?
自然语言没有稳定契约,解析它会把不确定性引入编排层。把判断压在结构化交接物上,编排层才能确定性地推进状态,出错时也有明确的校验点。
阻断和异常有什么区别?
阻断是「需要人判断」的停住,比如交接物被拒绝;异常是「技术波动」的失败,比如调用超时。前者等人工清除,后者自动重试,两者不能混为一谈。
这和直接对着 AI 聊天开发有什么不同?
直接聊天把进度留在对话里,换一个会话就得重新交接。这套流程把进度放在持久化状态里,把每个节点的产出固化为交接物,因此可以无人值守地领取、推进和恢复。