演进:harness 必然演化
🚧 本章为初稿。
到上一章结束,harness 已经建成。载体承载完整意图,三层机制在两个漂移地点上都有覆盖,五个 Agent 并行工作产出可以合并。这一整套东西一旦跑起来,看起来就是完成品。
但 harness 本身是设计出来的东西。设计的时候基于当时看到的失效模式,看不到还没暴露的失效模式。项目跑一段时间,产品迭代、模型升级、新场景出现,harness 自身的失效模式就会浮现。
卷一的演进章处理的是 spec 过时的问题。一个人盯着一个项目,看到测试报告知道哪里是 spec 没跟上,凭对项目的理解知道改哪个文件,改完一审一合就完了。发现、归因、修正三个动作都由人做。这套路径在卷二里跑不动了。产品变化、模型升级带来的常规演进走规约章和验证章的机制就行。多个 Agent 并行产出,人盯不过来。凭对项目的理解归因也不成立,因为项目规模超出个人领域覆盖。
这一章讨论的是另一类问题。规约章和验证章的机制自己也需要维护。载体的结构可能过时,验证机制的覆盖可能跟不上,失效边界文档可能跟实际脱节。这些属于 harness 自身的失效。
harness 自身也会失效
验证章的三层机制在两个漂移地点上有覆盖,前提假设是载体本身是对的,验证机制自己是够的。前提被打破的时候,三层机制抓不到。
具体形态有几种。
第一种是软门禁的 subagent 过时。subagent 是根据某一时刻的载体派生的。博客审核队列上线时,通知块下面有一个 subagent 负责审"通知合并模板文案是否分类列出通过和拒稿"。产品经理后来加了"作者可选静音某类通知"这个新意图。载体里的静音相关条目补进去了,但通知块的 subagent 没扩展。结果作者选择静音某类通知之后依然收到这类通知,语义漂在软门禁范围外,三层机制没抓到。
第二种是集成验证的用户旅程盖不到新组合。一开始集成验证只跑三个核心用户旅程,投稿到审核、审核到通知、拒稿后修改再投。后来加了批量审核和主编转派两个功能,每个功能上线时各自的载体走过共同产出,各自的三层验证也过了。但集成验证的用户旅程还是那三个,没扩展到"批量审核 + 主编转派"这类新组合。跨块新组合的漂逃过整套三层机制。
第三种是载体的块划分装不下新的复杂度。一开始的五个块对齐五个决策边界,边界清晰。产品经理加了"跨栏目投稿"功能。"栏目"这个概念既涉及产品交互块(作者选栏目的界面)、又涉及 API 契约块(栏目权限在请求间的传递)、也涉及 schema 块(栏目字段和索引)。三个块的 Agent 各自扩展了一部分栏目相关的决策,块之间的一致性开始靠 Agent 猜。原本清晰的决策边界被稀释,跨块决策开始重新出现漂的可能。
第四种是失效边界文档跟实际脱节。硬门禁的失效边界文档写"能查所有字段类型不匹配"。这一条上线时是对的,硬门禁的脚本能覆盖 TypeScript 原始类型和 interface 结构的所有对比场景。模型升级半年后,Agent 开始使用 branded types 这类新的类型模式来表达业务约束(比如把 UUID 和普通 string 通过品牌类型区分)。硬门禁的检查规则针对的是老式的类型形态,对 branded types 的类型漂检测不到。文档写的能力范围比实际的能力范围大了一圈。
这些形态有一个共同点。失效发生在三层机制之外的层级。三层机制的失效边界是显式的,但三层机制自己是否还有效这件事没有对应的自动检测层。硬门禁的语义盲区靠软门禁补,软门禁的跨块盲区靠集成验证补,集成验证的诊断细节盲区靠回到载体分析。链条走到最后还需要一个判断,判断这套链条本身是否还工作。这个判断只能落在人身上。
这个判断没法自动化的原因跟验证章里三层机制自己审自己这条路走不通是同源的。任何检测机制都有失效边界,检测机制自己失效时它没法检测自己。要判断整套机制是不是还工作,判断者必须站在机制之外。在卷二的场景里,机制之外的位置只有人。
harness 自身的失效需要独立于验证章的机制处理。跟规约章里 spec 变载体、验证章里验证从人转移到机制的性质一样。认清一个新的层级问题,然后单独处理。
ISO 9001 的双轨制
harness 自身失效怎么处理,工业界几十年前就遇到过这类问题并给出了答案。系统运行中出现异常,异常的原因跨越多个层级,需要一套方法让系统持续改进。ISO 9001 的异常处理原则是最成熟的一套。它的核心是双轨。
每次异常发生,必须给出两套方案。短期方案让流程立刻继续,长期方案让这类异常不再发生。
短期方案的目标是恢复运行。生产线上出了不合格品,短期方案可能是加严抽检、临时人工复核、隔离已受影响的批次。这些动作让线上产品可以继续出厂。
长期方案的目标是消除根因。分析这批不合格品为什么发生,找到是原料的问题、工艺的问题还是设备的问题,改原料、改工艺、改设备。这个动作让同类异常在未来的产品上不再出现。
双轨的关键在于分离。只做短期是持续救火,每次异常都要人工顶一次,成本累积但系统本身没改进。只做长期赶不上业务节奏,改设备可能要几周,产线不能等这几周。两条轨必须并行。
ISO 9001 把这个原则工程化,不依赖人的自觉。异常报告的模板强制要求两个字段,短期措施和长期措施。异常处理委员会的会议必须同时给出两个决议。审计的时候两个方案都要能追溯。这一套让双轨从原则变成实际的流程。
双轨制在别的高风险行业也是标配。航空业的事故调查报告有两部分,短期是停飞或临时改程序,长期是改设计、改培训、改法规。医疗的不良事件处理也是两轨,短期是抢救和隔离,长期是改临床路径或改设备。这些行业共同经历过"只做短期救火导致同类事故反复发生"的教训。双轨制是这个教训的沉淀。
双轨制在 harness 上的落地
双轨制迁移到 harness 演化上,形状基本一样。发现 harness 自身失效之后,短期方案让业务继续,长期方案让 harness 自身改进。
发现的位置在业务运行中。外部信号来自用户或运营。主编在群里说"最近审核状态刷不出来,我 approve 完就转圈"。运营查用户投诉发现审核相关的报告两周里涨了 40%。这些是最直观的信号,但也最滞后,等信号明显的时候业务已经受影响一段时间。
harness 内部的运行指标是先行信号。缓存命中率的持续下降说明系统在处理越来越多没见过的场景。软门禁的误报率上升说明 subagent 的失效边界跟实际偏了——本来是通过的产出被判成有问题,或者本来有问题的产出被判成通过。集成验证挂的频次上升说明用户旅程覆盖不到新组合。这些指标自动收集,但要人看趋势和判断严重程度。人识别到 harness 有问题,才启动演进流程。
这一步没法自动化,因为要求识别的对象是验证章的三层机制自己,检测者不能是同一套三层机制。
胥克谦有一个具体的观察。缓存命中率突然掉下来往往是 harness 出问题的第一个信号。一个健康跑着的 harness 在覆盖类似场景时会大量命中缓存。命中率的持续下降说明系统在处理越来越多没见过的场景。这些场景要么是新功能带来的(属于常规演进),要么是 harness 的覆盖跟不上(属于自身失效)。区分这两种情况要靠人查。
短期方案让业务不停。团队 leader 可能花半天把最近三次载体变更相关的代码手动过一遍,把三层机制没抓到的问题用眼睛捞出来交给 Agent 修。这一步的成本是几个小时的人力,产出是当前批次代码的清理。也可能写一个针对性脚本,把当前发现的高危场景固化成检查规则,比如"所有引用 batchReview 和 transferReviewer 两个方法的代码位置必须显式处理并发锁"。这个脚本不是硬门禁的一部分,是临时的过滤器,出问题解决之后可以撤掉。还有一种做法是把风险功能临时下线,比如把"批量审核"功能 disable 掉一周,让业务只走单条审核,等长期方案上线再打开。这些动作的共同点是不改 harness。载体不动,三层机制不动,失效边界文档不动。改的是当前代码或当前的运行时配置。
长期方案改的就是 harness 自身。走规约章的共同产出机制。大模型扩展决策点、抛回可判定决策、人做判定、大模型精修载体或验证机制。抛回的判定内容跟规约章和验证章里都不一样。规约章里判定的是意图,验证章里判定的是失效边界,本章里判定的是 harness 应该怎么改。
举例。大模型抛回给架构师:"当前 subagent 的划分是每块一个,跨块的语义漂靠集成验证抓。这次失效说明这个分工在新场景下有漏。有两个候选方向。方向一是引入跨块 subagent,违反三层机制原有的分层但能直接覆盖漏洞。方向二是修改集成验证的用户旅程生成规则,让用户旅程跟着载体演化自动扩展。你选哪个?"这是一个典型的 harness 结构判定。架构师熟悉三层机制的分工,能判定这两个方向的取舍。判定完之后大模型精修具体实现,走验证章的三层验证,验的是修改后的 harness 是不是覆盖了之前漏掉的失效模式。
双轨的分离也要工程化。每次 harness 元级别失效的处理必须两个 output。短期方案的 output 是让业务当天恢复的动作。长期方案的 output 是 harness 的具体变更。缺任何一个都不合格。
实践案例
博客审核队列上线三个月。中间通过规约章和验证章的机制加了三个功能,批量审核、主编转派、审核历史导出。每个功能上线时载体走过共同产出,代码通过了三层验证,都是正常的演进。
从上上周开始,主编反馈审核操作偶尔失败,具体表现是提交审核后偶尔看到状态没更新。运营方查用户投诉,最近两周审核相关的报告上升了 40%。团队去查代码,每个功能单独看都对,测试也过,三层验证也过。进一步查发现是几个新功能之间的交互产生了竞态。批量审核跟主编转派同时发生时状态机会漂。
排查到 harness 层面,root cause 是软门禁 subagent 只审自己块内的意图对齐,跨块的新组合场景归集成验证抓。集成验证的用户旅程是初始几个核心流程加进去的,后来加的三个功能都没扩展用户旅程。跨块交互漂逃过了整套三层机制。这是 harness 自身的失效。验证机制的覆盖跟不上载体的演化。
短期方案两天内做完。手动 review 最近三次载体更新对应的产出,重点看跨功能交互的代码。找出几个具体的竞态点,让 Agent 修。加一个临时脚本,把当前已知的几个高危跨功能组合场景固化成断言,在集成之前先跑一遍。业务这条线跑起来了。
长期方案花了一周。走共同产出。大模型扩展出三个候选方向。一是让集成验证的用户旅程生成规则跟随载体演化自动扩展。二是加一个专门审跨块交互的 subagent。三是重新设计块的划分让跨块交互变少。三个方向的成本和收益不同,抛回给架构师判定。架构师选方案一,理由是它改的是集成验证机制本身,跟验证章的原有分层保持一致,不引入新的机制类型。
大模型基于这个判定精修集成验证的机制。用户旅程的生成规则变成每次载体加新功能时,用户旅程要自动加入这个新功能跟已有功能的组合场景。这个规则本身也是共同产出的一部分。具体加什么组合、组合怎么排列,这些是人可判定的失效边界,抛回给架构师定。架构师的判定包括几条。组合的粒度按功能对,不按功能列表全排列,因为全排列爆炸。核心业务流程里的组合优先于边缘流程。已经在生产上出过问题的组合直接进用户旅程作为回归测试。这些判定写进集成验证的失效边界文档,成为下一轮覆盖检查的输入。
判定完之后覆盖检查跑通,改进的验证机制上线。这一版机制会自动追踪载体的演化,下次载体加新功能时用户旅程自动扩展。
演进的产出是集成验证机制的元级别更新,加上失效边界文档的增补。短期方案的临时脚本作为过渡在长期方案上线后可以撤掉。业务代码没有留下技术债,harness 保留了这次演进带来的改进。这次的改进对下一次载体新增功能永久生效。
这一次演进只处理了一种 harness 失效。一个团队跑几个月,类似的演进可能会发生几十次。每次都留下 harness 的一次改进。载体的某个块被重新划分,某个 subagent 被扩展,某条失效边界被修订。这些改动累加起来,跑得越久的 harness 覆盖的失效模式越多。
代码只是这些演化的一次落地。真正沉淀下来的是 harness 自身。多人协同、跨项目复用、组织层面的 harness 治理,是下一卷讨论的话题。
Harness Engineering Playbook · AgentsZone Community