实践:博客审核队列的验证链路
原则和机制都已经清楚。这一节用规约章建立的博客审核队列的载体走一遍完整流程。前半段展示三层机制怎么从载体派生加人判定失效边界建起来。后半段展示建成的机制跑一遍五份产出,抓到三种漂移。整个流程沿用规约章的共同产出框架。
起点:载体在手
规约章结尾产出的载体分五块:产品交互块、API 契约块、schema 块、通知机制块、垃圾处理块。每块自足,跨块契约在 API 契约块里明确。这份载体就是这一节的起点。
建立三层机制沿用规约章的共同产出框架,同一个元原则。差别在于载体已经在手。大模型能直接从载体反推候选检查项,不需要人先告诉它检查什么。
派生的具体路径分三个方向。硬门禁的候选来自载体里的结构性规定。schema 块里"reviewer_id 是 uuid"派生"检查 SQL 字段类型是 uuid"这个脚本检查项。API 契约块里"所有错误响应必须带 error_code"派生"检查后端所有错误响应有 error_code 字段"。产品交互块里"审核状态包含四种:待审、审核中、通过、拒绝"派生"检查状态枚举完备"。
软门禁的候选来自载体里的意图条目。通知块里"合并通知要分类列出通过和拒稿"派生一个 subagent:"审通知模板文案是否分类列出通过和拒稿"。反垃圾块里"识别到疑似垃圾时先隔离等主编确认"派生一个 subagent:"审代码里主编确认这个动作是否有独立入口"。schema 块里"审核历史保留三年"派生一个 subagent:"审 SQL 里保留策略是否覆盖三年周期"。
集成验证的候选来自载体里的跨块契约。API 契约块里"session 用 token 表示"派生一个 Mock 设置:"模拟 token 交互,前后端各在泳道里跑"。API 契约块里"审核提交返回 review_id"派生一个 Mock:"模拟审核提交返回,前端拿这个 review_id 做下一步操作"。
大模型自己能把这些候选检查项铺开。人不介入。三层机制的初稿产出了。
初稿的规模值得留意。博客审核队列的载体大约六七十页,五个块加起来包含几百个决策点。派生出来的候选检查项跟决策点数量大致同级。硬门禁的脚本检查项大约有一百多条。软门禁的 subagent 任务大约有几十个(每个 subagent 负责一个语义角度)。集成验证的 Mock 场景有二十多个(对应 API 契约里的每一条跨块交互)。这套规模一个人自己写要花几周。大模型从载体反推只花几分钟。这就是载体作为共同产出前置成果带来的效率。
人在这一步没做的事包括:写脚本、写 subagent 提示词、设计 Mock。这些都是机械工作,大模型能可靠完成。人的时间要留给下一步。
人判定失效边界
候选检查项摆出来之后,人的介入在失效边界。三层机制每一层的能力上限画在哪里,是人要判断的。判定沿用规约章共同产出的三条件(领域、杠杆、呈现形式)。判定内容从意图变成失效边界,接口原则相同。
走三个具体案例。
第一个是硬门禁的 uuid 类型检查。大模型抛回给技术 lead。领域够,技术 lead 熟悉数据类型和字段用途。杠杆够,字段类型错就是数据完整性问题,可能带来查询错误、外键失败、跨系统集成问题。呈现用产品行为的语言,问"字段类型强校验,允许还是不允许类型隐式转换"。技术 lead 判定:"不允许,严格校验,因为审核系统跟外部推送系统会用同一个 reviewer_id,类型不一致会导致外部集成出错"。这个判定加上理由写入硬门禁的失效边界文档:"抓所有字段类型不匹配,不抓 uuid 的语义误用,比如把用户 uuid 用作会话 uuid 这类误用"。
第二个是软门禁的拒稿反馈 subagent。大模型抛回给产品经理。领域够,产品经理熟悉用户体验和反馈机制。杠杆够,反馈机制直接决定作者和主编的日常操作体验。呈现用"允许分类标签之外的自由文字备注共存吗,还是必须严格分类"。产品经理判定:"允许,备注是补充说明。主编需要在标签之外说明具体理由的场景很多。"这个判定加上理由写入软门禁 subagent 的失效边界文档:"抓分类标签是否作为主要反馈机制,允许分类标签加自由文字备注共存,可能对分类标签为空但备注独立填写的情况误报"。
第三个是集成验证的 session token 传输。大模型抛回给架构师。领域够,架构师熟悉认证机制。杠杆够,认证方式影响安全性和跨端兼容性。呈现用"session token 用什么方式传输:cookie、Authorization header、或者两者都支持"。架构师判定:"cookie,团队现有前端库都是 cookie based,改成 header 需要重写前端认证逻辑。"这个判定加上理由写入集成验证的失效边界文档:"抓 token 传输方式不匹配,不抓 token 内容的语义正确性,那部分是块内的软门禁范围"。
三个判定都在共同产出的三条件判定框架内跑通。判定的是失效边界,接口原则相同。
判定过程里也有大模型不能自动做的其他决定要处理。举一个具体的。软门禁里派生了一个 subagent:"审代码里主编确认这个动作是否有独立入口。"这个 subagent 的检查方式有多种可能。它可以只看代码里有没有一个叫"主编确认"的函数。也可以看有没有一个前端页面显示待确认列表。也可以看有没有 API 端点接收主编的确认操作。三种检查方式对应三种失效模式,抓到的漂不完全一样。选哪一种是判定问题。大模型抛回给产品经理:"主编确认这个动作,你希望验证的是代码层面有函数、UI 层面有页面、还是 API 层面有端点?"产品经理说三个都要,理由是缺任何一层这个功能就残缺。这个判定把 subagent 拆成三个子 subagent,每个子 subagent 覆盖一个层面。
这类判定不是大模型无能,是它没有意图信息。它不知道产品经理心里对"主编确认这个动作"的完整期望是什么。给它足够信息之后,它可以派生。三层机制建立的过程里,人的判定散落在这类具体决定点上。规模不大,几十个到一百个左右,跟意图的复杂度成正比。
失效边界文档的覆盖检查
三层的失效边界写下来是三份文档。合起来做覆盖检查,决定三层的互补是否成立。
硬门禁的边界文档说:"抓所有结构性违规,包括字段类型、函数签名、契约字段完备度、checklist 覆盖度。不抓语义误用,比如同类型字段的业务错用,也不抓文案的意思对错。"
软门禁的边界文档说:"抓块内语义漂移,包括意图对齐、逻辑忠实、约束遵守。可能对同类冗余的边界情况误报,比如分类标签为空但备注独立填写。不抓跨块假设,也不抓 attention 承载力之外的整体行为。"
集成验证的边界文档说:"抓跨块契约差异,包括 API 传输方式、字段格式约定、状态机跳转的假设。不抓块内诊断细节,也不告诉具体是哪一块产出的问题。"
三份文档比对做覆盖检查。问两个问题。第一,有没有漂移地点被两层都声称能抓,但两层机制类型相同,实际是同类冗余而不是互补。第二,有没有漂移地点没被任何一层覆盖。
博客案例这一版。硬门禁抓结构,软门禁抓块内语义,集成验证抓跨块假设。三层机制类型不同(脚本、模型、行为预演),失效模式不重叠。两个漂移地点(代码与载体块之间、载体块之间)都有专门机制覆盖。覆盖检查通过。
三层机制的初始建立完成,可以跑了。
覆盖检查通过不是终点。它意味着按照当前对漂移的理解,三层机制的覆盖是完整的。真正跑起来之后可能发现意料之外的漂——原来不知道能这样漂的地方,机制就没准备。这类发现进入演进循环,属于下一章。这里的失效边界文档是初始建立时的产出,是运行的起点,不是终态。
跑一遍:硬门禁扫结构
五个 Agent 从五个块各自产出代码。前端 Agent 拿产品交互块,产出前端代码。后端 Agent 拿 API 契约块,产出后端代码和 API 实现。数据库 Agent 拿 schema 块,产出建表 SQL 和迁移脚本。通知 Agent 拿通知机制块,产出事件到发送通道。反垃圾 Agent 拿垃圾处理块,产出识别到隔离流程。
五份产出摆在验证链的入口。硬门禁先跑。
检查项按照失效边界文档的规定运行。字段类型检查扫所有 schema 相关代码。签名一致性检查扫 API 端点。checklist 覆盖度检查扫每个块的完备性。命名规范检查扫所有代码文件。
在这份产出上抓到两个问题。数据库 Agent 的 SQL 里 reviewer_id 字段类型写成了 int。schema 块规定的是 uuid。这跟建立时判定的失效边界完全对应。硬门禁抓到,问题回给数据库 Agent。Agent 改成 uuid,脚本再扫,通过。
后端 Agent 有两个端点的错误响应漏了 error_code 字段。API 契约块规定所有错误响应必须带这个字段。硬门禁抓到,问题回给后端 Agent。Agent 补上字段,脚本再扫,通过。
硬门禁跑的时间几分钟就完成。全部检查项按顺序过一遍,标出所有违规。这一层的成本很低,跑得频繁没问题。事实上硬门禁应该在每次 Agent 提交产出时都跑,作为最前置的过滤。抓到的问题让 Agent 立刻改。改完再跑,反复到通过。
硬门禁的失效在这里也能观察到。通知块里合并模板的实际文案是散文,脚本按照结构规则判断不了文案的语义对不对。类似的,反垃圾块里"识别到疑似垃圾时先隔离等主编确认"这句意图,脚本能查代码里有没有一个函数叫"隔离",但查不出隔离行为跟意图对不对齐。文案的抓取、逻辑的抓取,都要下一层。
跑一遍:软门禁并行审语义
启动多个 subagent。每个 subagent 拿一个块的载体和对应代码,独立 context 跑,只审一个角度。
Subagent A 审通知块。载体规定合并通知的模板要分类列出通过和拒稿。它检查实际文案。作者提交了三篇稿件,两篇通过一篇拒稿,合并模板生成的文本是"你的三篇稿件都被审核通过"。三篇都说通过。这跟载体规定的分类列出直接冲突。语义漂。
Subagent B 审反垃圾块。载体规定识别到疑似垃圾时先隔离等主编确认。它检查代码里"主编确认"这个动作是不是有独立入口。找到了,前端有一个"待确认队列"页面,主编可以看隔离的稿件并选择放行或维持隔离。对齐。
Subagent C 审 schema 块。载体规定审核历史保留三年。它检查 SQL 里的分区归档策略。按年分区,超过三年的分区归档到冷存储。对齐。
这里胥克谦的一条原则要单独提。他的原话:"只审不改。边审边改的不能并行。"改的动作会干扰审的独立性。这里的每个 subagent 只出报告,不动代码。主流程汇总报告之后,让通知 Agent 修改合并模板。修改后再走软门禁到通过。
软门禁跑的时间比硬门禁长。每个 subagent 是一个独立的模型调用,读几页载体加几百行代码,做语义判断,出报告。单个 subagent 几十秒到一分钟。所有 subagent 并行跑,实际墙钟时间接近最长的那个。整套软门禁跑一遍两三分钟。
Subagent 数量的规模值得留意。博客案例大概启动了几十个 subagent,覆盖五个块的语义角度。这个规模大模型自己能编排。每个 subagent 的提示词从载体的对应条目自动生成。启动、并行、汇总都是脚本能做的机械工作。人在这个环节不介入。
软门禁的失效在这里也能观察到。每个 subagent 只看一个块。前后端的 session 传输方式差异,subagent A 看不到(它审的是通知块),subagent B 看不到(它审的是反垃圾块)。跨块要下一层。
跑一遍:集成验证跑跨块契约
前端在自己的泳道跑,后端用 Mock 替代。Mock 按照 API 契约的规定响应。反过来也一样,后端在泳道里跑,前端用 Mock 替代。两边独立跑通自己的测试。
然后跑真实集成。前端的实际实现连到后端的实际实现。跑一个完整用户旅程。作者投稿,主编看到稿件,审核通过,作者收到通知。
集成挂了。前端发的请求带的是 Cookie: session=xyz。后端读的是 Authorization header,读不到 token,返回 401。作者收到的是认证失败的错误,不是审核通过的通知。
回到载体分析。API 契约块规定"session 用 token 表示"。前端和后端都遵守了这条规定,都在用 token 做认证。契约里没规定 token 用什么方式传输。这是载体本身的漏项。第二漂移地点的漂。
解决方式回到共同产出流程。抛回可判定决策。产品经理选 cookie,理由是团队现有前端库都是 cookie based。这跟建立时判定 session token 传输方式的路径完全一样。运行时载体出漏项要补决策,跟建立时判定失效边界共用同一个共同产出机制。载体补决策之后,前后端 Agent 都基于新载体修改代码。再跑集成,通过。
集成验证跑的时间是三层里最长的。前后端泳道各自跑一遍要几分钟。真实集成跑用户旅程要几分钟。整套集成验证跑一遍十几分钟。这一层的成本高,跑的频率比前两层低。事实上集成验证应该在硬软门禁都通过之后再跑。前两层能抓的问题在低成本的层里就抓完了,集成验证专注在只有它能抓的地方。
集成验证的失效在这里也能观察到。它发现"合不上",但不告诉是前端错了还是后端错了还是契约漏了。诊断要靠回到载体分析。这里 session token 传输差异的诊断路径很清楚——回到 API 契约块看它规定了什么。如果契约里明确规定用 header 而前端用了 cookie,那是前端漂(第一漂移地点)。如果契约里没规定传输方式,那是契约漏项(第二漂移地点)。诊断的走向决定了修在哪里。前者是修前端代码,后者是补契约再修前端和后端。
三层互补落到具体产出上
三种漂移在这个跑通里都出现了。每一层各抓自己那类。
硬门禁抓的是代码结构不符合载体。uuid 类型和 error_code 字段。第一漂移地点的结构性漂。
软门禁抓的是代码语义不符合载体。通知合并模板文案错位。第一漂移地点的语义性漂。
集成验证抓的是载体本身有漏。API 契约没规定 token 传输方式。第二漂移地点的漂。
三层各自的失效场景在跑通里都能观察到。硬门禁抓不到文案语义,语义靠软门禁补。软门禁抓不到跨块假设,跨块靠集成验证补。集成验证抓不到块内诊断细节,诊断要回到硬软门禁的结果。三层的失效不重叠。加起来覆盖两个漂移地点。
有一个具体的观察值得留意。三层抓漂的顺序不是巧合,是设计出来的。硬门禁跑得便宜跑得快,先跑一遍能过滤掉大量结构性问题,让后面的层专注在结构以外的东西。软门禁跑得比硬门禁贵,先让硬门禁清理过一遍再跑,效率高。集成验证跑得最贵,只在前两层通过之后跑一次。这个顺序让整套验证的成本分布合理。跑得贵的层只在必要时启用。
这个顺序也有另一个好处。硬门禁抓的问题回给 Agent 修改的时候,修改动作可能引入新的语义漂。修完之后软门禁再跑一次能抓到这类新引入的漂。软门禁抓的语义问题回给 Agent 修改的时候,修改可能引入新的跨块假设差异。修完之后集成验证跑一次能抓到。上一层的抓漂加下一层的抓漂形成一个瀑布式的清理过程。
正常流里人不进入
三层验证过程里的所有代码修改由 Agent 自动执行。硬门禁标问题,Agent 修,脚本再扫。软门禁 subagent 出报告,主流程根据报告让 Agent 修,再审。集成验证发现载体漏,补决策后 Agent 修,再跑集成。
人可能进入的位置只有两个。第一是建立机制时判定失效边界。前面的三个例子(uuid 类型、拒稿反馈、session token 传输)都是这种情况。第二是运行时载体出漏项要补决策。集成验证抓到 session token 传输方式漏项之后回去补决策,是这种情况。
两处介入都在共同产出的框架内跑。都符合共同产出的三条件判定。差别只在时间点和判定内容。建立时判定的是失效边界,运行时判定的是载体新增决策。同一个机制的两次使用。
正常运行流里人不介入。三层跑完通过,产出合并。五份产出合起来是完整的博客审核队列功能。
跟卷一相比,形态不变。卷一里的验证也是产出通过之后进合并。差别在可信度的来源。卷一里的最后一道是人。卷二里的最后一道是失效互补的三层机制。人的整体判断力换成了三层机制的失效边界互补。
这个替换的性质要看清楚。卷一里人做的整体判断有它自己的失效场景——带宽和盲区。卷二的三层机制也有失效场景,但这些失效场景是显式的、可陈述的、互补的。可信度不来自"最后一道更聪明",来自"最后一道的失效场景清清楚楚,且被其他机制覆盖"。
从操作性上看这个替换的收益也明显。卷一里的人做一次全项目 review 要几小时,且质量随疲劳下降。卷二里的三层机制每次跑二十分钟以内,质量稳定不受疲劳影响。多轮 review 的成本从人的几天缩到机器的几个小时。产出速度跟得上并行 Agent 的产出速度。
到这里本章的论证闭环。载体和验证机制本身怎么持续维护是下一章的话题。产品会变,模型会升级,新场景会暴露旧机制的漏。这些是演进要处理的。
Harness Engineering Playbook · AgentsZone Community