49-antigravity-inspired-parallel-verification-proposal.md 19.9 KB

49 · 竞争式并行 + 执行级验证严谨度——参考 Antigravity Teamwork 的两条提案

状态: 📝 设计讨论,不代表已拍板(同 41 号文档的定位)。本文档是参照 Google Antigravity「Teamwork」 多智能体框架(https://antigravity.google/blog/teamwork-when-ai-becomes-a-research-partner)与我们自己 系统做对比后,针对两个具体缺口给出的方案草稿,供下一步决定要不要立项、按什么优先级。 日期: 2026-09-04 触发场景: 用户读完 Antigravity Teamwork 的博客文章,要求对照我们的 org/work graph 体系找异同, 随后指定「27 号 P4(真并行)」与「34/35 号文档指出的验证严谨度不稳定问题」这两项,要求参考文章 现在就产出一份 todo 方案。


一、先纠正一个前提:27 号 P4「真并行」现在剩的东西,比想象的少很多

写这份文档前重读了 27-P4 全文——它虽然还挂在 todo/,但文档 自己 §五末尾已经写明阶段 A(隔离)/ B(并行)/ C(产物索引)全部已实现(2026-08-21,advanceBatch 真并发、Promise.allSettled fan-out、graph_files 产物索引、控制台 fan-in 可视化都已落地并有单测/真跑 验收)。这是本仓库第二次撞见「文档落后于代码」这个模式(第一次是文档自己 §3.6/§五校准块记录的)。

真正还没做的,只有四件小事:

项 现状 是否与本文档的新提案相关
T2:DevLoop 规格 (pid,agent) → (pid,agent,scope) 改 HTML 重跑 spec:extract 即可,纯机械改动 无关,独立小任务
T5:账户欠费门 桩子已落地,卡在计费系统接口确认,非本仓库能单方面推进 无关
graph_edge_contracts.role 列缺失 produces/needs 落库后不可区分,只影响诊断展示 无关
advanceTree 不会同时推「兄弟子 run」 一次只推最深的一个 active run;两个并行 subgraph 节点各自的子 run 靠外层循环轮流服务,不是真并发。这是当前唯一还成立的"并行"缺口 相关——本文档 §二 的新提案建立在"节点内部并发已具备"之上,兄弟子 run 并发是它的地基

也就是说,「27 号 P4 真并行」作为独立议题基本可以收口(只剩 T2/T5/role 列三件机械/外部依赖的小事, 不需要新设计)。真正值得用 Antigravity 这篇文章来对照、能长出新东西的,是同一个 run 内部并行做完之后, "要不要做竞争式的多候选并行"这个更高一层的问题——这是 Antigravity 有而我们没有的能力,不是把 27-P4 剩下的小尾巴做完就能自动获得的。下面 §二 是这条新提案。


二、新提案 A:竞争候选 + 对抗批评 + 综合(借鉴 Antigravity 长证明模式)

2.1 我们现在的 fan-out 和 Antigravity 的竞争生成,是两种不同的东西

27-P4 的 fan-out 解决的是任务可分解场景——三个互不重叠的子任务并行跑,各自独立,fan-in 只是等齐。 Antigravity 长证明模式解决的是任务不可分解、但存在多种解法场景——同一个问题,N 个候选策略并行 尝试同一件事,每个配一个专门的「证伪者」(falsifier)批评,胜出的进入综合树,被驳斥的路线连反对 意见都保留供后续复用。

这两种并行的图形状完全不同:

27-P4 fan-out(分解):          Antigravity 竞争生成(不分解,多解法):
        entry                          entry
       /  |  \                        /  |  \
      a   b   c        (各做不同的子任务)
       \  |  /                     candA candB candC   (各做同一件事,但方法不同)
        join                          |     |     |
                                   critic critic critic  (对抗式批评,不是简单验收)
                                        \   |   /
                                        synthesis        (综合/择优,不是简单 join)

我们目前的 work-graph-templates/(planner.json/executor.json/executor-fanout.json/ validator.json/deliverable.json)里,executor-fanout.json 的 fan-out 是分解型——org-coder 把工作拆成互不重叠的几个 unit 各自实现。没有一张骨架是竞争型——同一个问题让多个 agent 各自独立 给出完整方案,再挑最好的。

2.2 什么场景值得引入竞争型骨架

不是所有任务都值得——多候选意味着 token/时间成本乘 N,只有在验收标准明确、方案空间大、单次尝试 成功率不高的场景才划算。参照 Antigravity 五个模式各自的适用边界,对应到我们系统里大概是:

  • 算法/方案选型类子任务(比如「给这批数据设计一个去重策略」「优化这段热点代码」)——有客观可判定的 验收标准(正确性 + 性能基准),但实现路径不唯一,容易一次性收敛到局部最优解。
  • 不适合:常规 CRUD/界面开发这类目标单一、路径也基本单一的任务——多候选纯粹浪费预算,不会有 fan-out 分解已经在做的收益。

判断该不该走竞争型骨架,理论上应该由 workgraph-planning 现场决定(它已经在按任务形状选骨架),但 这需要给它一条新的选型判据,不是本文档能单方面拍板的——这正是要留给下一步讨论的开放问题。

2.3 落地形状草稿(未定案)

如果要做,大概率是新增一张 work-graph-templates/candidate-council.json 骨架(暂定名),形状:

entry → {candidate-1, candidate-2, candidate-3}(并行,复用 27-P4 已有的 fan-out 能力)
          ↓ 各自             ↓ 各自             ↓ 各自
       critic-1           critic-2           critic-3   (每个候选配一个批评者,不是自己批评自己)
          ↓                  ↓                  ↓
                      synthesis(综合/择优节点)

跟现有 executor-fanout.json 的关键区别不在图结构(两者拓扑相似),而在节点职责:

  • executor-fanout.json 的 fan-in 节点做的是「集成」(把不重叠的产物拼起来)。
  • candidate-council.json 的 synthesis 节点要做的是「择优或融合」——需要读三份互相竞争、覆盖同一个 目标的候选方案 + 三份批评意见,给出取舍。这是一个新的节点职责,目前系统里没有对应的 agent 人设 (org-coder-validator/integrator 都不是干这个的)。

被驳斥路线保留反对意见供复用——这条在我们系统里有现成落点:graph_files/timeline.ndjson 已经 会记录每个节点的产出和结算事件,critic 节点的批评意见本来就会作为产物落盘,天然可被 synthesis 节点 读到。不需要新机制,只是要求 critic 产出结构化(不是自由文本吐槽)。

2.4 明确的开放问题(不在本文档拍板)

  1. workgraph-planning 按什么判据选「竞争型」而不是「分解型」fan-out?现在完全没有这条判据。
  2. synthesis 节点的人设怎么写——它既不能是候选方案的作者(会有自证倾向,Antigravity 原文也强调了 这一点:候选和批评者要分离),又要有足够能力做技术判断,这可能需要一个新角色而不是复用现有的。
  3. 成本:N 个候选 = N 倍预算消耗,checkBudget(任务级共池)需不需要为这类节点单独提额度?
  4. 这条能力值不值得投入,取决于当前系统里有没有真实撞上"单次尝试成功率低、需要多解法比较"的任务—— 目前没有实证需求,是从 Antigravity 文章反推出来的假设性场景,需要先找一个真实案例验证价值, 不建议在没有真实痛点前直接立项写代码(同 46 号文档的方法论:真实回归优于凭空设计)。

三、新提案 B:验证严谨度——从"能不能查得到证据"扩展到"默认要求执行级证据"

3.1 现状盘点(核实过代码,不是凭印象)

server/services/goal-contract.js 的三段契约里,test_script 段本来就是执行级验证——真实子进程 跑测试文件,退出码即判决(SECTIONS/RUNNERS 见该文件 81/86 行,注释原话「不起 LLM:benchmark/ test_data 是纯声明式比对,test_script 走真实子进程」)。这条能力已经具备,跟 Antigravity「锁步共 模拟」的精神是一致的——都是拿真实执行结果做判决,不靠 LLM 一次性读代码给印象分。

问题是它用得少。48 号文档「待定」一节记录过原因:subtask-planning 在 org-coder 动手之前就要 交契约,那时候还不知道测试文件会落在哪个路径,所以当时选了更省事的 benchmark 段(LLM 按维度打分, 不依赖具体文件路径)。这是一个合理的工程取舍,但代价是这条链路上的验收退化成了纯 LLM 判分—— org-validator 判卷时"自行取证判分"(48 号真实回归判词原话),有没有真的去跑代码、读文件、执行测试, 取决于这次判卷的 agent 主不主动,跟 34 号文档发现的"验证严谨度完全不稳定"是同一个根因: 结构化契约本身不强制要求执行级证据,只是给了一个可以被认真对待、也可以被走过场的评分维度。

35 号文档的提案 D 已经缓解了一部分——evidence_hint 命中浏览器类关键词的维度必须有证据支撑,否则 判不过。但这条判据的触发范围窄(只认浏览器类关键词),别的维度(比如"函数对边界输入的处理是否正确") 不受约束。

3.2 提案:把"要求证据"从"浏览器关键词命中"泛化为"benchmark 段全部维度默认要求"

核心变化:goal-contract.js 的 benchmark 段每个 dimension 增加一个必填/半必填的 evidence 字段(校验维度打分是否真的对应一次可复核的动作),而不是像现在只挑浏览器关键词命中的维度查。具体 形状留待立项时定,方向上应该是「validator 写维度判分时,必须一并记录"我是怎么判的"——跑了什么命令 / 读了哪个文件的哪一段 / 执行了什么断言,而不是空白」。这跟 35 号提案 D 是同一机制的泛化,不是另起 一套。这是本节唯一建议现在就推进的部分——理由见 §3.2b,test_script 引导方案成本远超预期。

3.2b 工作量评估:把验收路径引向 test_script 段——结论是"不建议现在做",撞上一个结构性冲突

2026-09-04 对代码做了一轮实地核实(不是估算),结论跟直觉不一样:这不是"给 org-coder 补一条测试 文件路径约定"这么轻的事,中间卡着一个当前系统里没人处理过的目录结构冲突。

发现一:org-coder 现在完全没有测试文件路径约定(system/agents/org-coder/agent.md 通读,无 tools.md)。硬约束只区分 artifact(路径按 sdd 指定,否则落"项目根")和 log(节点私有目录下的 coder.log),没有第三类"测试文件"。48 号文档真实回归里 org-coder 写出的 test/convert.test.js 是 LLM 当场自己起的名字,不是系统约定——这一点原设计文档里已经点破。

发现二:DevLoop 有"路径固定写死在提示词里"的先例,但执行机制是另一套,代码不能照搬,只能借鉴思路。 devloop-tester 走 vitest --reporter=json + typebox 校验产出 result.json;devloop-integrator 起真实服务进程按 spec.json 里的用例列表打 HTTP 请求。两者都不是"退出码即判决",跟 goal-contract.js 的 runTestScript 是完全不同的技术路线,唯一可迁移的只有"角色只能写自己私有子目录下固定相对路径" 这条设计模式。

发现三(阻塞项):test_script.path 的可解析根,天然不包含 org-coder 实际写代码的地方。 resolveInsideArtifacts(goal-contract.js:184-213)只认两个根——契约目录 tasks/{taskId}/ 与 runs/{rootRunId}/artifacts/。但 org-coder 的写入边界(graph-engine.js:5076-5090 describeWriteBoundary)规定它的产物必须落在项目根(allocateRunProjectRoot, {RUNS_ROOT}/{rootRunId}/project/,company.json.target_dir 配了 linked-* 时甚至可能在仓库外任意 目录),这是与 runs/{rootRunId}/artifacts/ 同级但不同的第三个目录,resolveInsideArtifacts 根本 不会去那里找。也就是说,48 号文档真实回归里那份 test/convert.test.js,此刻物理上就无法被 test_script.path 引用到——不是"这次运气不好没配合",是两个解析根的定义里压根没有项目根这一项, 结构性地够不着。

发现四(好消息,不是瓶颈):org-validator/coder-validator 已经是"段不可知"的消费方,统一走 goal-contract.js run --target ... --run-id ...,退出码即判决,test_script 段不需要它们的 agent.md/tools.md 改一行。org-validator/tools.md:50-52 甚至已经明确禁止 agent 自己手拼 npx vitest run 绕开执行器——这条纪律已经就位,不用重建。

发现五(次要限制):RUNNERS 白名单目前只有 'node'(goal-contract.js:82-88),是实测撞过 "根 vitest.config 的 include 覆盖不到 data/,直接 No test files found"之后主动收窄的,注释里 留了升级路径(临时 vitest.config + --config)但没实现。如果 org-coder 写的是前端类测试(vitest 等非 node 原生断言),这条也会成为障碍——但这是发现三解决之后才需要面对的第二层限制,暂不是 当前的瓶颈。

结论与建议:要让验收路径真的走通 test_script,最小改动面是——① 解决发现三的结构冲突(要么把 resolveInsideArtifacts 的搜索根扩展到项目根,需要重新审视逃逸校验、覆盖 target_dir 配到仓库外的 情形;要么反过来要求 org-coder 把测试文件额外镜像一份到 artifacts/,多一条写入规则但不动 goal-contract.js);② 给 org-coder 补测试文件路径约定(agent.md 新增一条硬约束);③ 给 subtask-planning 同步这条约定,让它在交 acceptance 时能提前引用这个固定路径。三步都不是"改一行 提示词"量级,且①本身还没有定案的方案,只有两条待权衡的路径。不建议现在推进——跟提案 A 同样的 判断标准:没有真实场景证明当前 benchmark 段判分不够用之前,不该为了"原则上更严谨"就承担这笔结构性 改造成本。§3.2 的证据泛化(改动小、不碰目录结构)已经能覆盖大部分"防止空手套白狼"的诉求,作为当前 唯一建议推进的部分。

3.3 提案:陷阱注册表(anti-lessons registry)——Dream 目前没有的一层

Antigravity 把验证器发现的缺陷提炼成一个与具体答案无关的陷阱库,后续尝试主动避坑。我们的 29 号 Dream 机制目前做的是"把 agent 经验蒸馏进 SKILL.md/soul.md/agent.md",偏向沉淀成功模式,没有专门做"系统性收集验证失败原因"这一层。

具体提案(成本不高,可以独立于 §二/§3.2 单独立项):

  • 数据源:org-validator/coder-validator 等验收节点判卷失败(fail_reason 非空)时,除了走既有的 归因/回退流程,额外把"为什么判不过"这条结构化理由(不是原始 transcript,是提炼过的、与具体任务 内容无关的失败模式)追加进一个新的沉淀点。
  • 落点决策(2026-09-04 已拍板):每个被雇佣本体目录下新增独立文件 known_pitfalls.md(类似 _lessons.md 但专门收"别人踩过的坑",不是这个本体自己的经验),由 Dream 的现有蒸馏批处理顺带写, 不需要新的定时任务。不复用 memory.md 加受管区块——memory.md 目前的语义是"这个本体自己积累 的经验",混进"别人的教训"会损伤这条语义的纯度,且独立文件的装配成本(多读一个文件)远低于维护 一个新受管区块的隔离逻辑。
  • 消费方:同角色本体下次执行前,把这份陷阱库当成额外上下文的一部分注入(跟 agent.md/soul.md 同一 个装配流程,不需要新的读取路径)。

3.4 明确不做 / 与既有文档的边界

  • 不做 Antigravity 那种"连续锁步共模拟"式的领域特定深度验证(硬件周期级对表)——那是他们特定领域 (RISC-V 模拟器)的定制方案,我们没有对应场景,硬套没有意义。我们能借鉴的只是"默认要求执行级证据" 这条原则,不是具体机制。
  • 35 号文档四条提案已实施的部分不重做,本提案是在它的基础上泛化范围,不是推翻。
  • test_script 引导方案不做(§3.2b 已给出工作量评估与结论):撞上 test_script.path 解析根 不含项目根这个结构性冲突,改造面远超"给 org-coder 补一条约定",没有真实场景压力前不值得做。 48 号文档"待定"一节的既有结论(走 benchmark 段)维持不变,不重新拍板。

四、任务划分(粗粒度,立项前不细化)

项 内容 依赖
P4 收口 T2(DevLoop 规格)、role 列、advanceTree 兄弟子 run 并发 无,可独立随时做
提案 A(竞争候选) 已拆分成独立的详细设计草稿,见 50 号文档——需要先找到一个真实任务撞上"单次成功率低、需要多解法比较"的场景,再决定要不要做骨架 + critic/synthesis 角色 无实证需求前不建议立项
提案 B-1(证据泛化) goal-contract.js schema 扩展 + org-validator/coder-validator agent.md 调整 35 号提案 D 已有的机制,扩大范围即可,成本可控
提案 B-1b(test_script 引导) 已评估,不建议做——见 §3.2b,撞上 test_script.path 解析根不含项目根的结构性冲突,改造面远超预期 不立项
提案 B-2(陷阱注册表) Dream 蒸馏批处理新增一类输出 + 装配读取路径接上,落点已定案为独立文件 known_pitfalls.md(见 §3.3) 与 29 号 Dream 机制集成,成本较低,可独立于 B-1 先做

建议的推进顺序(如果拍板要做):B-2(陷阱注册表)成本最低、跟现有 Dream 机制正交,可以先单独验证; B-1(证据泛化)次之;提案 A(竞争候选)需要先看 50 号文档的具体设计,且仍然需要真实场景验证价值才 建议立项。


五、与既有文档的关系

  • 27-P4:本文档 §一 是对它当前状态的复核,不修改它的结论; §二的竞争候选提案建立在它已完成的 fan-out 能力之上。
  • 50-competing-candidates-critic-synthesis-design: §二提案 A 的详细设计草稿(骨架 JSON、命名、critic/synthesis 分工、预算风险量化),本文档只保留结论。
  • 34 / 35:本文档 §三是 对 35 号提案 D 的泛化延伸,不推翻已实施的部分。
  • 29-dream-design:§3.3 陷阱注册表是在 Dream 现有 批处理框架内新增一类输出,不改动 Dream 的核心机制(独立判定/四落点/fail-closed 等既有设计保留)。
  • 48-task-acceptance-contract-binding: §3.2 明确指出如果证据泛化立项,需要重新过一遍它"待定"一节的 benchmark vs test_script 取舍。