# 49 · 竞争式并行 + 执行级验证严谨度——参考 Antigravity Teamwork 的两条提案 > **状态**: 📝 **设计讨论,不代表已拍板**(同 41 号文档的定位)。本文档是参照 Google Antigravity「Teamwork」 > 多智能体框架()与我们自己 > 系统做对比后,针对两个具体缺口给出的方案草稿,供下一步决定要不要立项、按什么优先级。 > **日期**: 2026-09-04 > **触发场景**: 用户读完 Antigravity Teamwork 的博客文章,要求对照我们的 org/work graph 体系找异同, > 随后指定「27 号 P4(真并行)」与「34/35 号文档指出的验证严谨度不稳定问题」这两项,要求参考文章 > 现在就产出一份 todo 方案。 --- ## 一、先纠正一个前提:27 号 P4「真并行」现在剩的东西,比想象的少很多 写这份文档前重读了 [27-P4](../../done/system-design/27-p4-parallel-and-artifacts.md) 全文——它虽然还挂在 `todo/`,但文档 自己 §五末尾已经写明**阶段 A(隔离)/ B(并行)/ C(产物索引)全部已实现**(2026-08-21,`advanceBatch` 真并发、`Promise.allSettled` fan-out、`graph_files` 产物索引、控制台 fan-in 可视化都已落地并有单测/真跑 验收)。这是本仓库第二次撞见「文档落后于代码」这个模式(第一次是文档自己 §3.6/§五校准块记录的)。 **写这份文档时还没做的,有四件小事——2026-09-08 复核时发现其中两条本身就判断错了**: | 项 | 现状 | 是否与本文档的新提案相关 | |---|---|---| | ~~T2:DevLoop 规格 `(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 明确的开放问题(不在本文档拍板) 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 机制](../../done/system-design/29-dream-design.md)目前做的是"把 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 并发~~ **2026-09-08 已全部做完**——且核实时发现这行本身有两处误判:`graph_edge_contracts.role` 列其实在本文档写作前就已落库(`graph-edge-contract-role.test.js` 早于本文档日期,见 27-P4 §四 校准),T1 的✅当时只做完了 `maxSessions` 上限,`scope` 参数从未真正接线(本轮一并补上,见 27-P4 §4.2)。三件事详见 [27-P4](../../done/system-design/27-p4-parallel-and-artifacts.md) 对应小节 | — | | 提案 A(竞争候选) | 已拆分成独立的详细设计草稿,见 [50 号文档](./50-competing-candidates-critic-synthesis-design.md)——需要先找到一个真实任务撞上"单次成功率低、需要多解法比较"的场景,再决定要不要做骨架 + 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](../../done/system-design/27-p4-parallel-and-artifacts.md):本文档 §一 是对它当前状态的复核,不修改它的结论; §二的竞争候选提案建立在它已完成的 fan-out 能力之上。 - [50-competing-candidates-critic-synthesis-design](./50-competing-candidates-critic-synthesis-design.md): §二提案 A 的详细设计草稿(骨架 JSON、命名、critic/synthesis 分工、预算风险量化),本文档只保留结论。 - [34](../../done/system-design/34-validator-scored-without-real-deliverable.md) / [35](../../done/system-design/35-validation-rigor-and-body-readiness-proposal.md):本文档 §三是 对 35 号提案 D 的泛化延伸,不推翻已实施的部分。 - [29-dream-design](../../done/system-design/29-dream-design.md):§3.3 陷阱注册表是在 Dream 现有 批处理框架内新增一类输出,不改动 Dream 的核心机制(独立判定/四落点/fail-closed 等既有设计保留)。 - [48-task-acceptance-contract-binding](../../done/system-design/48-task-acceptance-contract-binding.md): §3.2 明确指出如果证据泛化立项,需要重新过一遍它"待定"一节的 `benchmark` vs `test_script` 取舍。