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/§五校准块记录的)。
写这份文档时还没做的,有四件小事——2026-09-08 复核时发现其中两条本身就判断错了:
| 项 | 现状 | 是否与本文档的新提案相关 |
|---|---|---|
(pid,agent) → (pid,agent,scope) |
2026-09-08 已做;且原计划「改 HTML 重跑 spec:extract」是错的——CONVENTIONS.md 不是任何 HTML 的生成物,是手写文件,直接改 |
无关,独立小任务 |
| T5:账户欠费门 | 桩子已落地,卡在计费系统接口确认,非本仓库能单方面推进 | 无关 |
graph_edge_contracts.role 列缺失 |
2026-09-08 复核:role 列与 normalizeContracts() 的 produces/needs 区分早就落库了(graph-edge-contract-role.test.js 的提交日期早于本文档写作日期),本文档没有独立验证就照抄了 27-P4 当时那张表的过期状态 |
无关 |
advanceTree 不会同时推「兄弟子 run」 |
2026-09-08 已按代码里当时写好的升级路径改成 Promise.allSettled 并发推进 |
相关——本文档 §二 的新提案建立在"节点内部并发已具备"之上,兄弟子 run 并发是它的地基,现已补齐 |
也就是说,「27 号 P4 真并行」作为独立议题现在已经彻底收口(2026-09-08)。真正值得用 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 明确的开放问题(不在本文档拍板)
workgraph-planning按什么判据选「竞争型」而不是「分解型」fan-out?现在完全没有这条判据。- synthesis 节点的人设怎么写——它既不能是候选方案的作者(会有自证倾向,Antigravity 原文也强调了 这一点:候选和批评者要分离),又要有足够能力做技术判断,这可能需要一个新角色而不是复用现有的。
- 成本:N 个候选 = N 倍预算消耗,
checkBudget(任务级共池)需不需要为这类节点单独提额度? - 这条能力值不值得投入,取决于当前系统里有没有真实撞上"单次尝试成功率低、需要多解法比较"的任务—— 目前没有实证需求,是从 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段)维持不变,不重新拍板。
四、任务划分(粗粒度,立项前不细化)
| 项 | 内容 | 依赖 |
|---|---|---|
advanceTree 兄弟子 run 并发graph_edge_contracts.role 列其实在本文档写作前就已落库(graph-edge-contract-role.test.js 早于本文档日期,见 27-P4 §四 校准),T1 的✅当时只做完了 maxSessions 上限,scope 参数从未真正接线(本轮一并补上,见 27-P4 §4.2)。三件事详见 27-P4 对应小节 |
— | |
| 提案 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 明确指出如果证据泛化立项,需要重新过一遍它"待定"一节的
benchmarkvstest_script取舍。