Commit 6c09327e7fc453fe83a5c36fc3a42bca04148b3e

Authored by yibo
1 parent ec6c1029

docs: 新增49/50号文档——参考Antigravity Teamwork的并行/验证严谨度提案

对照 Google Antigravity「Teamwork」多智能体框架博客文章,产出两份设计
讨论文档(均标注"不代表已拍板"):

- 49号:纠正27号P4「真并行」现状认知(阶段A/B/C早已实现,又一次「文档
  落后于代码」);给验证严谨度问题提两个方向——benchmark段证据要求泛
  化(建议推进)、陷阱注册表落点定案为独立文件 known_pitfalls.md;实地
  核实"验收路径引导到test_script段"的工作量后结论是不做,撞上
  test_script.path 解析根不含项目根的结构性冲突。

- 50号:竞争候选+对抗批评+综合的详细设计草稿,critic/synthesis 强制
  分离的依据是仓库真实事故(qa-judge 早期评判+判决合一导致过一次无限
  循环,20次调用/31分钟才熔断);量化了N路候选的预算超支风险。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UP1omSsXkyGhopHvWeSnyy
docs/README.md
... ... @@ -66,6 +66,8 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d
66 66 | [41-graph-vs-fde-reliability-discussion.md](./todo/system-design/41-graph-vs-fde-reliability-discussion.md) | 📝 **讨论记录 + 落地实测,非设计方案**。org/work graph 与 master-Innovator-FDE 两套工作流的稳定性对比:根因是"拓扑运行时生成 vs 写死"。问题 7 是真实执行记录——新建 `org-hunt/digest/evolve`(graph 原生协议,方法论抄 innovator-hunt/digest/evolver)跑 Hunt→Digest→Evolve,11 轮真跑中挖出并修复 5 个独立缺陷(建公司自动规划竞态、work-graph 模板库缺内容型交付物骨架、验收节点任务描述越权、两个规划 agent 的路径口径写错、R-19 产出索引 `indexNodeOutputs()` 不覆盖项目根——最后一条改了 `graph-engine.js` 核心逻辑,加 `contract.json` 的 `produces` 显式声明机制,全局生效,补了 2 条守卫测试)。最终产出与原生 FDE(`prd-methodology-trial`)对比:内容骨架可迁移、质量不打折,但过程严谨度不如原生 FDE,可靠性差距悬殊(原生一次跑通,graph 版 11 轮才稳定)。`routeFailure` 的 `infra_flake` 分支绕过跨层寻址(`target_node`)这个口子已按最保守方案补上(2026-08-31,见文内清单)——但堵不住 30 号文档记录的那次真实事故,那次事故点名的目标是下游节点,图模型本身就不允许 backward 边指向非祖先,属于修复范围之外 |
67 67 | [37-org-graph-department-scoping.md](./todo/system-design/37-org-graph-department-scoping.md) | 📝 **设计讨论,调用点扫描已完成,尚未立项实现**。现状 org graph 按 `company_id` 单例(`27-P2` 标题原文即"公司级"),塞不下 HR/财务/市场这类跟"交付流水线"无关的公司常设职能——`system/agents/hr/`("招·留·管·退")本体已存在却从没被装进任何图,全靠 fire-and-forget chat 招聘、无图执行审计轨迹。提议把 org graph 作用域从 `company_id` 升级为 `(company_id, department_id)`,一家公司可装配多张部门图,每张仍保持人工固定/慢变/可审计。全仓库调用点扫描结论:改造面是最初估算的 4 倍——真正的单点真相在 `work-graph-db.js:readDefGraph` 的裸 SQL 不变式(不在服务层),还牵涉两个易混淆服务文件间必须字节级一致的重复唯一索引、独立的 `graph-seed-service.js` 对账子系统、`company-hire-org-layer.test.js` 专属测试、`orggraph-planning`/`task-planning` 两份 agent 人设文档的自我认知改写 |
68 68 | [36-prd-agent-methodology-training-feasibility.md](./todo/system-design/36-prd-agent-methodology-training-feasibility.md) | 📝 **调研 + 阶段一/二均已完成**。回应"落地页太单薄是不是该用 Innovator 先训练专业 agent、再用 Dream 持续迭代"——认同方向。**阶段一**:`graph-engine.js` 结算节点后把 `success`/`fail:<reason>` 写进本体 `memory.md`(此前只有人类对话路径会写,Dream 天天空转)。**阶段二**:新建独立试验节点 `prd-methodology-trial` 走真实 Hunt→Digest→Evolve,2 轮收敛(96/97 分,真实基线 50 分),三个真实历史项目反推验证方法论有效;过程中连带修复同一个 2026-08-16 改名批次遗留的 5 处 `innovator`→`org-innovator` 死链(后端两处硬编码、前端"重新训练"按钮、`/api/agent/list` 展示 id 来源的四个 `config.json`),以及 `AgentScaffold` 默认模板一处裸相对路径缺陷。结论:FDE 对方法论类角色确实管用,但收敛速度/验收严谨度依赖任务书显式写明的自纠正要求,非免人工黑盒。环节 3(训练产物 → 雇佣本体转换)尚未开工 |
  69 +| [49-antigravity-inspired-parallel-verification-proposal.md](./todo/system-design/49-antigravity-inspired-parallel-verification-proposal.md) | 📝 **设计讨论,不代表已拍板**(2026-09-04)。对照 Google Antigravity「Teamwork」多智能体框架博客文章,给 27 号 P4「真并行」与 34/35 号「验证严谨度不稳定」两个议题出的方案草稿。**先纠正一个前提**:重读 27-P4 全文后发现阶段 A/B/C 早已全部实现(又一次「文档落后于代码」),真并行现在只剩 T2/role 列/`advanceTree` 兄弟子 run 并发三件小事,可独立收口。**新提案 A**:借鉴长证明模式的「竞争候选+对抗批评+综合」,区别于现有 `executor-fanout.json` 的分解型 fan-out——需要先有真实场景验证价值,不建议凭空立项,详细设计见 [50 号文档](./todo/system-design/50-competing-candidates-critic-synthesis-design.md)。**新提案 B**:把 35 号提案 D「浏览器关键词命中才要证据」泛化成 benchmark 段全维度默认要求执行级证据(**唯一建议现在推进的部分**);实地核实过把验收路径引导到 `test_script` 段的工作量后**结论是不做**——撞上 `test_script.path` 解析根不含 `org-coder` 实际写代码的项目根这个结构性冲突,改造面远超预期;新增「陷阱注册表」,把 validator 判卷失败的结构化原因喂回 Dream 机制,落点已定案为独立文件 `known_pitfalls.md`(不复用 `memory.md`,避免语义混淆)。建议推进顺序:陷阱注册表最低成本先做,证据泛化次之,竞争候选需要真实场景才立项 |
  70 +| [50-competing-candidates-critic-synthesis-design.md](./todo/system-design/50-competing-candidates-critic-synthesis-design.md) | 📝 **设计草稿,不代表已拍板**(2026-09-04)。49 号文档提案 A 的展开:竞争候选骨架 JSON 形状草稿(`candidate-council.json`,未定案)、命名(按 27-NAMING 节点带前缀/本体不带前缀两轴)、`workgraph-planning` 选型判据方向。**关键设计约束**:critic(评判)与 synthesis(择优/融合)必须拆成两个节点,依据是仓库真实事故——`qa-judge` 早期"评判+终态判决合一"设计导致过一次无限循环(20 次调用/31 分钟才熔断,记录在 `deliverable.json` 的反模式说明里),新骨架延续 `validator-triager`/`benchmark-validator` 已验证的"归因/打分/判定三者分离"范式。**预算风险量化**:N 路候选并行消耗 N 倍预算,且 `checkBudget` 只在批量拾取前查一次,实际可能超支到 `maxConcurrency-1`(默认最多多花 4 次调用)才被拦下,候选数 N 目前代码层没有硬顶 |
69 71 | [46-mandatory-planning-and-task-decomposition.md](./todo/system-design/46-mandatory-planning-and-task-decomposition.md) | 📝 **Phase 0-3 v2 均已实现且做过真实回归**(2026-09-02)。承接 43 号文档的追问:任务规划应是每个任务默认前置步骤,来源覆盖模型自身能力/知识库经验/线上 deep research。**Phase 1**:新 agent `subtask-planning`,钩在 `enqueueTaskRun`(显式 opt-in),产物写共享 `artifacts/subtask-plan.json`。**Phase 2**:经验检索(扫已雇 agent 的 dream 沉淀)+ 按需 deep research(图外调用 org-hunt,默认关闭);真实回归揪出一个关键词打分噪音压过信号的真缺陷并修复。**Phase 3 走过一轮推翻重来**:v1("认领"pull 语义 + CAS)做完真实回归才发现"认领后没有触发源",讨论后确认"多方竞争"场景根本不存在(只有 CEO 一人拍板)——**v2 改成 CEO 心跳直接发现+派发(push)**,子任务走一张现造的轻量 work graph(`org-coder`+`org-validator` 两节点,跳过公司完整 org graph 的规划仪式)。v2 真实回归:CEO 心跳真的发现并派发了子任务,`org-coder` 产出质量达标,但 `org-validator` 卡在硬依赖的 `acceptance.json`(只有 `org-planner` 会产出,轻量图没有这个节点)——**验证这一半有真实的结构性缺口,后续方向见 [48 号文档](./done/system-design/48-task-acceptance-contract-binding.md)**。验证过程顺手修了一个更大范围的真实 bug:两套心跳系统的自环调用一直缺内部认证令牌、暗中 401。Phase 4(独立开发验证循环)、Phase 5(看板 UI)未开工 |
70 72  
71 73 ## todo/future/(暂缓,非当前重心)
... ...
docs/todo/system-design/49-antigravity-inspired-parallel-verification-proposal.md 0 → 100644
  1 +# 49 · 竞争式并行 + 执行级验证严谨度——参考 Antigravity Teamwork 的两条提案
  2 +
  3 +> **状态**: 📝 **设计讨论,不代表已拍板**(同 41 号文档的定位)。本文档是参照 Google Antigravity「Teamwork」
  4 +> 多智能体框架(<https://antigravity.google/blog/teamwork-when-ai-becomes-a-research-partner>)与我们自己
  5 +> 系统做对比后,针对两个具体缺口给出的方案草稿,供下一步决定要不要立项、按什么优先级。
  6 +> **日期**: 2026-09-04
  7 +> **触发场景**: 用户读完 Antigravity Teamwork 的博客文章,要求对照我们的 org/work graph 体系找异同,
  8 +> 随后指定「27 号 P4(真并行)」与「34/35 号文档指出的验证严谨度不稳定问题」这两项,要求参考文章
  9 +> 现在就产出一份 todo 方案。
  10 +
  11 +---
  12 +
  13 +## 一、先纠正一个前提:27 号 P4「真并行」现在剩的东西,比想象的少很多
  14 +
  15 +写这份文档前重读了 [27-P4](./27-p4-parallel-and-artifacts.md) 全文——它虽然还挂在 `todo/`,但文档
  16 +自己 §五末尾已经写明**阶段 A(隔离)/ B(并行)/ C(产物索引)全部已实现**(2026-08-21,`advanceBatch`
  17 +真并发、`Promise.allSettled` fan-out、`graph_files` 产物索引、控制台 fan-in 可视化都已落地并有单测/真跑
  18 +验收)。这是本仓库第二次撞见「文档落后于代码」这个模式(第一次是文档自己 §3.6/§五校准块记录的)。
  19 +
  20 +**真正还没做的,只有四件小事**:
  21 +
  22 +| 项 | 现状 | 是否与本文档的新提案相关 |
  23 +|---|---|---|
  24 +| T2:DevLoop 规格 `(pid,agent)` → `(pid,agent,scope)` | 改 HTML 重跑 `spec:extract` 即可,纯机械改动 | 无关,独立小任务 |
  25 +| T5:账户欠费门 | 桩子已落地,卡在计费系统接口确认,非本仓库能单方面推进 | 无关 |
  26 +| `graph_edge_contracts.role` 列缺失 | `produces`/`needs` 落库后不可区分,只影响诊断展示 | 无关 |
  27 +| **`advanceTree` 不会同时推「兄弟子 run」** | 一次只推最深的一个 active run;两个并行 `subgraph` 节点各自的子 run 靠外层循环轮流服务,不是真并发。**这是当前唯一还成立的"并行"缺口** | **相关**——本文档 §二 的新提案建立在"节点内部并发已具备"之上,兄弟子 run 并发是它的地基 |
  28 +
  29 +也就是说,「27 号 P4 真并行」作为独立议题基本可以**收口**(只剩 T2/T5/role 列三件机械/外部依赖的小事,
  30 +不需要新设计)。真正值得用 Antigravity 这篇文章来对照、能长出新东西的,是**同一个 run 内部并行做完之后,
  31 +"要不要做竞争式的多候选并行"**这个更高一层的问题——这是 Antigravity 有而我们没有的能力,不是把 27-P4
  32 +剩下的小尾巴做完就能自动获得的。下面 §二 是这条新提案。
  33 +
  34 +---
  35 +
  36 +## 二、新提案 A:竞争候选 + 对抗批评 + 综合(借鉴 Antigravity 长证明模式)
  37 +
  38 +### 2.1 我们现在的 fan-out 和 Antigravity 的竞争生成,是两种不同的东西
  39 +
  40 +27-P4 的 fan-out 解决的是**任务可分解**场景——三个互不重叠的子任务并行跑,各自独立,fan-in 只是等齐。
  41 +Antigravity 长证明模式解决的是**任务不可分解、但存在多种解法**场景——同一个问题,N 个候选策略**并行
  42 +尝试同一件事**,每个配一个专门的「证伪者」(falsifier)批评,胜出的进入综合树,被驳斥的路线连反对
  43 +意见都保留供后续复用。
  44 +
  45 +这两种并行的图形状完全不同:
  46 +
  47 +```
  48 +27-P4 fan-out(分解): Antigravity 竞争生成(不分解,多解法):
  49 + entry entry
  50 + / | \ / | \
  51 + a b c (各做不同的子任务)
  52 + \ | / candA candB candC (各做同一件事,但方法不同)
  53 + join | | |
  54 + critic critic critic (对抗式批评,不是简单验收)
  55 + \ | /
  56 + synthesis (综合/择优,不是简单 join)
  57 +```
  58 +
  59 +我们目前的 `work-graph-templates/`(`planner.json`/`executor.json`/`executor-fanout.json`/
  60 +`validator.json`/`deliverable.json`)里,`executor-fanout.json` 的 fan-out 是**分解型**——`org-coder`
  61 +把工作拆成互不重叠的几个 unit 各自实现。**没有一张骨架是竞争型**——同一个问题让多个 agent 各自独立
  62 +给出完整方案,再挑最好的。
  63 +
  64 +### 2.2 什么场景值得引入竞争型骨架
  65 +
  66 +不是所有任务都值得——多候选意味着 token/时间成本乘 N,只有在**验收标准明确、方案空间大、单次尝试
  67 +成功率不高**的场景才划算。参照 Antigravity 五个模式各自的适用边界,对应到我们系统里大概是:
  68 +
  69 +- **算法/方案选型类子任务**(比如「给这批数据设计一个去重策略」「优化这段热点代码」)——有客观可判定的
  70 + 验收标准(正确性 + 性能基准),但实现路径不唯一,容易一次性收敛到局部最优解。
  71 +- **不适合**:常规 CRUD/界面开发这类目标单一、路径也基本单一的任务——多候选纯粹浪费预算,不会有 fan-out
  72 + 分解已经在做的收益。
  73 +
  74 +判断该不该走竞争型骨架,理论上应该由 `workgraph-planning` 现场决定(它已经在按任务形状选骨架),但
  75 +这需要给它一条新的选型判据,不是本文档能单方面拍板的——**这正是要留给下一步讨论的开放问题**。
  76 +
  77 +### 2.3 落地形状草稿(未定案)
  78 +
  79 +如果要做,大概率是新增一张 `work-graph-templates/candidate-council.json` 骨架(暂定名),形状:
  80 +
  81 +```
  82 +entry → {candidate-1, candidate-2, candidate-3}(并行,复用 27-P4 已有的 fan-out 能力)
  83 + ↓ 各自 ↓ 各自 ↓ 各自
  84 + critic-1 critic-2 critic-3 (每个候选配一个批评者,不是自己批评自己)
  85 + ↓ ↓ ↓
  86 + synthesis(综合/择优节点)
  87 +```
  88 +
  89 +**跟现有 `executor-fanout.json` 的关键区别不在图结构(两者拓扑相似),而在节点职责**:
  90 +
  91 +- `executor-fanout.json` 的 fan-in 节点做的是「集成」(把不重叠的产物拼起来)。
  92 +- `candidate-council.json` 的 synthesis 节点要做的是「择优或融合」——需要读三份**互相竞争、覆盖同一个
  93 + 目标**的候选方案 + 三份批评意见,给出取舍。这是一个新的节点职责,目前系统里没有对应的 agent 人设
  94 + (`org-coder-validator`/`integrator` 都不是干这个的)。
  95 +
  96 +**被驳斥路线保留反对意见供复用**——这条在我们系统里有现成落点:`graph_files`/`timeline.ndjson` 已经
  97 +会记录每个节点的产出和结算事件,critic 节点的批评意见本来就会作为产物落盘,天然可被 synthesis 节点
  98 +读到。不需要新机制,只是要求 critic 产出结构化(不是自由文本吐槽)。
  99 +
  100 +### 2.4 明确的开放问题(不在本文档拍板)
  101 +
  102 +1. `workgraph-planning` 按什么判据选「竞争型」而不是「分解型」fan-out?现在完全没有这条判据。
  103 +2. synthesis 节点的人设怎么写——它既不能是候选方案的作者(会有自证倾向,Antigravity 原文也强调了
  104 + 这一点:候选和批评者要分离),又要有足够能力做技术判断,这可能需要一个新角色而不是复用现有的。
  105 +3. 成本:N 个候选 = N 倍预算消耗,`checkBudget`(任务级共池)需不需要为这类节点单独提额度?
  106 +4. 这条能力值不值得投入,取决于**当前系统里有没有真实撞上"单次尝试成功率低、需要多解法比较"的任务**——
  107 + 目前没有实证需求,是从 Antigravity 文章反推出来的假设性场景,需要先找一个真实案例验证价值,
  108 + 不建议在没有真实痛点前直接立项写代码(同 46 号文档的方法论:真实回归优于凭空设计)。
  109 +
  110 +---
  111 +
  112 +## 三、新提案 B:验证严谨度——从"能不能查得到证据"扩展到"默认要求执行级证据"
  113 +
  114 +### 3.1 现状盘点(核实过代码,不是凭印象)
  115 +
  116 +`server/services/goal-contract.js` 的三段契约里,`test_script` 段**本来就是执行级验证**——真实子进程
  117 +跑测试文件,退出码即判决(`SECTIONS`/`RUNNERS` 见该文件 81/86 行,注释原话「不起 LLM:benchmark/
  118 +test_data 是纯声明式比对,test_script 走真实子进程」)。这条能力已经具备,跟 Antigravity「锁步共
  119 +模拟」的精神是一致的——**都是拿真实执行结果做判决,不靠 LLM 一次性读代码给印象分**。
  120 +
  121 +问题是它**用得少**。48 号文档「待定」一节记录过原因:`subtask-planning` 在 `org-coder` 动手之前就要
  122 +交契约,那时候还不知道测试文件会落在哪个路径,所以当时选了更省事的 `benchmark` 段(LLM 按维度打分,
  123 +不依赖具体文件路径)。这是一个合理的工程取舍,但代价是**这条链路上的验收退化成了纯 LLM 判分**——
  124 +`org-validator` 判卷时"自行取证判分"(48 号真实回归判词原话),有没有真的去跑代码、读文件、执行测试,
  125 +取决于这次判卷的 agent 主不主动,跟 34 号文档发现的"验证严谨度完全不稳定"是同一个根因:
  126 +**结构化契约本身不强制要求执行级证据,只是给了一个可以被认真对待、也可以被走过场的评分维度。**
  127 +
  128 +35 号文档的提案 D 已经缓解了一部分——`evidence_hint` 命中浏览器类关键词的维度必须有证据支撑,否则
  129 +判不过。但这条判据的触发范围窄(只认浏览器类关键词),别的维度(比如"函数对边界输入的处理是否正确")
  130 +不受约束。
  131 +
  132 +### 3.2 提案:把"要求证据"从"浏览器关键词命中"泛化为"benchmark 段全部维度默认要求"
  133 +
  134 +**核心变化**:`goal-contract.js` 的 `benchmark` 段每个 `dimension` 增加一个必填/半必填的 `evidence`
  135 +字段(校验维度打分是否真的对应一次可复核的动作),而不是像现在只挑浏览器关键词命中的维度查。具体
  136 +形状留待立项时定,方向上应该是「validator 写维度判分时,必须一并记录"我是怎么判的"——跑了什么命令 /
  137 +读了哪个文件的哪一段 / 执行了什么断言,而不是空白」。这跟 35 号提案 D 是同一机制的泛化,不是另起
  138 +一套。**这是本节唯一建议现在就推进的部分**——理由见 §3.2b,`test_script` 引导方案成本远超预期。
  139 +
  140 +### 3.2b 工作量评估:把验收路径引向 `test_script` 段——结论是"不建议现在做",撞上一个结构性冲突
  141 +
  142 +2026-09-04 对代码做了一轮实地核实(不是估算),结论跟直觉不一样:这不是"给 `org-coder` 补一条测试
  143 +文件路径约定"这么轻的事,中间卡着一个**当前系统里没人处理过的目录结构冲突**。
  144 +
  145 +**发现一:`org-coder` 现在完全没有测试文件路径约定**(`system/agents/org-coder/agent.md` 通读,无
  146 +`tools.md`)。硬约束只区分 `artifact`(路径按 sdd 指定,否则落"项目根")和 `log`(节点私有目录下的
  147 +`coder.log`),没有第三类"测试文件"。48 号文档真实回归里 `org-coder` 写出的 `test/convert.test.js`
  148 +是 LLM 当场自己起的名字,不是系统约定——这一点原设计文档里已经点破。
  149 +
  150 +**发现二:DevLoop 有"路径固定写死在提示词里"的先例,但执行机制是另一套,代码不能照搬,只能借鉴思路。**
  151 +`devloop-tester` 走 `vitest --reporter=json` + typebox 校验产出 `result.json`;`devloop-integrator`
  152 +起真实服务进程按 `spec.json` 里的用例列表打 HTTP 请求。两者都不是"退出码即判决",跟 `goal-contract.js`
  153 +的 `runTestScript` 是完全不同的技术路线,唯一可迁移的只有"角色只能写自己私有子目录下固定相对路径"
  154 +这条设计模式。
  155 +
  156 +**发现三(阻塞项):`test_script.path` 的可解析根,天然不包含 `org-coder` 实际写代码的地方。**
  157 +`resolveInsideArtifacts`(`goal-contract.js:184-213`)只认两个根——契约目录 `tasks/{taskId}/` 与
  158 +`runs/{rootRunId}/artifacts/`。但 `org-coder` 的写入边界(`graph-engine.js:5076-5090`
  159 +`describeWriteBoundary`)规定它的产物必须落在**项目根**(`allocateRunProjectRoot`,
  160 +`{RUNS_ROOT}/{rootRunId}/project/`,`company.json.target_dir` 配了 `linked-*` 时甚至可能在仓库外任意
  161 +目录),这是与 `runs/{rootRunId}/artifacts/` **同级但不同**的第三个目录,`resolveInsideArtifacts` 根本
  162 +不会去那里找。也就是说,**48 号文档真实回归里那份 `test/convert.test.js`,此刻物理上就无法被
  163 +`test_script.path` 引用到**——不是"这次运气不好没配合",是两个解析根的定义里压根没有项目根这一项,
  164 +结构性地够不着。
  165 +
  166 +**发现四(好消息,不是瓶颈):`org-validator`/`coder-validator` 已经是"段不可知"的消费方**,统一走
  167 +`goal-contract.js run --target ... --run-id ...`,退出码即判决,`test_script` 段不需要它们的
  168 +`agent.md`/`tools.md` 改一行。`org-validator/tools.md:50-52` 甚至已经明确禁止 agent 自己手拼
  169 +`npx vitest run` 绕开执行器——这条纪律已经就位,不用重建。
  170 +
  171 +**发现五(次要限制):`RUNNERS` 白名单目前只有 `'node'`**(`goal-contract.js:82-88`),是实测撞过
  172 +"根 `vitest.config` 的 `include` 覆盖不到 `data/`,直接 `No test files found`"之后主动收窄的,注释里
  173 +留了升级路径(临时 `vitest.config` + `--config`)但没实现。如果 `org-coder` 写的是前端类测试(vitest
  174 +等非 node 原生断言),这条也会成为障碍——但这是发现三解决之后才需要面对的**第二层**限制,暂不是
  175 +当前的瓶颈。
  176 +
  177 +**结论与建议**:要让验收路径真的走通 `test_script`,最小改动面是——① 解决发现三的结构冲突(要么把
  178 +`resolveInsideArtifacts` 的搜索根扩展到项目根,需要重新审视逃逸校验、覆盖 `target_dir` 配到仓库外的
  179 +情形;要么反过来要求 `org-coder` 把测试文件额外镜像一份到 `artifacts/`,多一条写入规则但不动
  180 +`goal-contract.js`);② 给 `org-coder` 补测试文件路径约定(`agent.md` 新增一条硬约束);③ 给
  181 +`subtask-planning` 同步这条约定,让它在交 `acceptance` 时能提前引用这个固定路径。三步都不是"改一行
  182 +提示词"量级,且①本身还没有定案的方案,只有两条待权衡的路径。**不建议现在推进**——跟提案 A 同样的
  183 +判断标准:没有真实场景证明当前 `benchmark` 段判分不够用之前,不该为了"原则上更严谨"就承担这笔结构性
  184 +改造成本。§3.2 的证据泛化(改动小、不碰目录结构)已经能覆盖大部分"防止空手套白狼"的诉求,作为当前
  185 +唯一建议推进的部分。
  186 +
  187 +### 3.3 提案:陷阱注册表(anti-lessons registry)——Dream 目前没有的一层
  188 +
  189 +Antigravity 把验证器发现的缺陷提炼成一个**与具体答案无关的陷阱库**,后续尝试主动避坑。我们的
  190 +[29 号 Dream 机制](../../done/system-design/29-dream-design.md)目前做的是"把 agent 经验蒸馏进
  191 +`SKILL.md`/`soul.md`/`agent.md`",偏向沉淀**成功模式**,没有专门做"系统性收集验证失败原因"这一层。
  192 +
  193 +**具体提案**(成本不高,可以独立于 §二/§3.2 单独立项):
  194 +
  195 +- 数据源:`org-validator`/`coder-validator` 等验收节点判卷失败(`fail_reason` 非空)时,除了走既有的
  196 + 归因/回退流程,额外把"为什么判不过"这条结构化理由(不是原始 transcript,是提炼过的、与具体任务
  197 + 内容无关的失败模式)追加进一个新的沉淀点。
  198 +- **落点决策(2026-09-04 已拍板)**:每个被雇佣本体目录下新增独立文件 `known_pitfalls.md`(类似
  199 + `_lessons.md` 但专门收"别人踩过的坑",不是这个本体自己的经验),由 Dream 的现有蒸馏批处理顺带写,
  200 + 不需要新的定时任务。**不**复用 `memory.md` 加受管区块——`memory.md` 目前的语义是"这个本体自己积累
  201 + 的经验",混进"别人的教训"会损伤这条语义的纯度,且独立文件的装配成本(多读一个文件)远低于维护
  202 + 一个新受管区块的隔离逻辑。
  203 +- 消费方:同角色本体下次执行前,把这份陷阱库当成额外上下文的一部分注入(跟 `agent.md`/`soul.md` 同一
  204 + 个装配流程,不需要新的读取路径)。
  205 +
  206 +### 3.4 明确不做 / 与既有文档的边界
  207 +
  208 +- 不做 Antigravity 那种"连续锁步共模拟"式的领域特定深度验证(硬件周期级对表)——那是他们特定领域
  209 + (RISC-V 模拟器)的定制方案,我们没有对应场景,硬套没有意义。我们能借鉴的只是"默认要求执行级证据"
  210 + 这条**原则**,不是具体机制。
  211 +- 35 号文档四条提案已实施的部分不重做,本提案是在它的基础上**泛化范围**,不是推翻。
  212 +- **`test_script` 引导方案不做**(§3.2b 已给出工作量评估与结论):撞上 `test_script.path` 解析根
  213 + 不含项目根这个结构性冲突,改造面远超"给 `org-coder` 补一条约定",没有真实场景压力前不值得做。
  214 + 48 号文档"待定"一节的既有结论(走 `benchmark` 段)维持不变,不重新拍板。
  215 +
  216 +---
  217 +
  218 +## 四、任务划分(粗粒度,立项前不细化)
  219 +
  220 +| 项 | 内容 | 依赖 |
  221 +|---|---|---|
  222 +| P4 收口 | T2(DevLoop 规格)、role 列、`advanceTree` 兄弟子 run 并发 | 无,可独立随时做 |
  223 +| 提案 A(竞争候选) | 已拆分成独立的详细设计草稿,见 [50 号文档](./50-competing-candidates-critic-synthesis-design.md)——需要先找到一个真实任务撞上"单次成功率低、需要多解法比较"的场景,再决定要不要做骨架 + critic/synthesis 角色 | 无实证需求前不建议立项 |
  224 +| 提案 B-1(证据泛化) | `goal-contract.js` schema 扩展 + `org-validator`/`coder-validator` agent.md 调整 | 35 号提案 D 已有的机制,扩大范围即可,成本可控 |
  225 +| 提案 B-1b(`test_script` 引导) | **已评估,不建议做**——见 §3.2b,撞上 `test_script.path` 解析根不含项目根的结构性冲突,改造面远超预期 | 不立项 |
  226 +| 提案 B-2(陷阱注册表) | Dream 蒸馏批处理新增一类输出 + 装配读取路径接上,落点已定案为独立文件 `known_pitfalls.md`(见 §3.3) | 与 29 号 Dream 机制集成,成本较低,可独立于 B-1 先做 |
  227 +
  228 +**建议的推进顺序**(如果拍板要做):B-2(陷阱注册表)成本最低、跟现有 Dream 机制正交,可以先单独验证;
  229 +B-1(证据泛化)次之;提案 A(竞争候选)需要先看 50 号文档的具体设计,且仍然需要真实场景验证价值才
  230 +建议立项。
  231 +
  232 +---
  233 +
  234 +## 五、与既有文档的关系
  235 +
  236 +- [27-P4](./27-p4-parallel-and-artifacts.md):本文档 §一 是对它当前状态的复核,不修改它的结论;
  237 + §二的竞争候选提案建立在它已完成的 fan-out 能力之上。
  238 +- [50-competing-candidates-critic-synthesis-design](./50-competing-candidates-critic-synthesis-design.md):
  239 + §二提案 A 的详细设计草稿(骨架 JSON、命名、critic/synthesis 分工、预算风险量化),本文档只保留结论。
  240 +- [34](../../done/system-design/34-validator-scored-without-real-deliverable.md) /
  241 + [35](../../done/system-design/35-validation-rigor-and-body-readiness-proposal.md):本文档 §三是
  242 + 对 35 号提案 D 的泛化延伸,不推翻已实施的部分。
  243 +- [29-dream-design](../../done/system-design/29-dream-design.md):§3.3 陷阱注册表是在 Dream 现有
  244 + 批处理框架内新增一类输出,不改动 Dream 的核心机制(独立判定/四落点/fail-closed 等既有设计保留)。
  245 +- [48-task-acceptance-contract-binding](../../done/system-design/48-task-acceptance-contract-binding.md):
  246 + §3.2 明确指出如果证据泛化立项,需要重新过一遍它"待定"一节的 `benchmark` vs `test_script` 取舍。
... ...
docs/todo/system-design/50-competing-candidates-critic-synthesis-design.md 0 → 100644
  1 +# 50 · 竞争候选 + 对抗批评 + 综合——新图骨架详细设计草稿
  2 +
  3 +> **状态**: 📝 **设计草稿,不代表已拍板**。这是 [49 号文档](./49-antigravity-inspired-parallel-verification-proposal.md)
  4 +> §二"提案 A"的展开——49 号只给了三节点拓扑草图,本文档补上骨架 JSON 形状、命名、critic/synthesis
  5 +> 分工、预算风险的具体数字。**49 号文档已明确:没有真实场景验证价值前不建议立项写代码**,本文档只是
  6 +> 把"如果要做,该怎么做"想清楚,供下一步决定要不要排期时参考,不是开工指令。
  7 +> **日期**: 2026-09-04
  8 +> **前置阅读**: [49 号文档](./49-antigravity-inspired-parallel-verification-proposal.md) §二(提案动机与
  9 +> 场景边界)、[27-P4](./27-p4-parallel-and-artifacts.md)(并行执行引擎,本设计的地基)、
  10 +> [27-naming-conventions.md](./27-naming-conventions.md)(命名规则)
  11 +
  12 +---
  13 +
  14 +## 一、跟现有骨架的本质区别(复述 49 号 §2.1,作为设计前提)
  15 +
  16 +`executor-fanout.json` 是**分解型** fan-out:`split` 把任务拆成互不重叠的子任务分给不同分支,`merge`
  17 +做的是**拼接**(把互补的子产物合并成一个整体)。竞争候选是**同型** fan-out:N 个分支做的是**同一件事**,
  18 +下游节点要做的是**评判 + 择一/融合**,不是拼接。两者拓扑相似、语义完全不同——这是本设计最容易踩错的
  19 +地方,写骨架 JSON 时必须在 `whenToUse`/`dataContractNotes` 里把这条区别说透,否则 `workgraph-planning`
  20 +选型时会混淆(现有 `executor.json` vs `deliverable.json` 就发生过一次真实混淆事故,见 §三.2 引用)。
  21 +
  22 +---
  23 +
  24 +## 二、骨架 JSON 形状草稿
  25 +
  26 +沿用 `system/work-graph-templates/README.md:129-165` 定义的字段结构,不发明新字段。
  27 +
  28 +```jsonc
  29 +// system/work-graph-templates/candidate-council.json(暂定名,未定案)
  30 +{
  31 + "id": "candidate-council",
  32 + "label": "候选方案竞争评审",
  33 + "whenToUse": "验收标准客观可判定,但实现路径不唯一、单次尝试容易收敛到局部最优解的子任务。典型信号词:\
  34 +'设计一个策略/方案'、'优化/选型'、'有几种做法都值得试'。跟 executor-fanout 的区别:executor-fanout 是\
  35 +把一个任务拆成不重叠的子任务分给不同分支各自完成(分解型);本骨架是让多个分支各自独立给出同一个目标\
  36 +的完整方案,再由 critic 评判、synthesis 择优或融合(同型竞争)。不确定任务是该分解还是该竞争时,默认\
  37 +选分解型(executor-fanout)——竞争型成本是 N 倍,只在"真的不确定哪条路线更优"时才划算。",
  38 + "ownerOrgNode": "{{orgNode}}",
  39 + "nodes": [
  40 + { "nodeName": "{{orgNode}}-candidate-a", "systemAgentId": "{{candidateAgent}}" },
  41 + { "nodeName": "{{orgNode}}-candidate-b", "systemAgentId": "{{candidateAgent}}" },
  42 + { "nodeName": "{{orgNode}}-critic-a", "systemAgentId": "candidate-critic" },
  43 + { "nodeName": "{{orgNode}}-critic-b", "systemAgentId": "candidate-critic" },
  44 + { "nodeName": "{{orgNode}}-synthesis", "systemAgentId": "candidate-synthesis" },
  45 + { "nodeName": "{{orgNode}}-validator", "systemAgentId": "{{validatorAgent}}" }
  46 + ],
  47 + "dataContractNotes": "候选分支数按实际任务增减(本文件给 2 路起手式,同 executor-fanout 的先例)。\
  48 +每路候选各配一个独立的 critic 节点——critic 只评判、不产出最终方案,也不是候选自己的下游必经步骤,\
  49 +是平行的另一个节点。critic 产出的评语(kind=artifact)与候选产出(kind=artifact)都要能被 synthesis \
  50 +节点区分来源,建议候选各自产出走 contract kind(分支间不冲突,同 executor-fanout 对 split 节点的处理),\
  51 +critic 评语走 artifact kind。千万不要把 critic 和 synthesis 合并成一个节点——qa-judge 早期版本就是\
  52 +"既提修改意见又下终态判决"合一设计,导致过一次真实的无限循环事故(20 次调用/31 分钟才熔断,见\
  53 +deliverable.json 的反模式记录),这条教训必须在本骨架延续。",
  54 + "edges": [
  55 + { "from": "{{orgNode}}-candidate-a", "to": "{{orgNode}}-critic-a", "condition": "success", "produces": ["contract"] },
  56 + { "from": "{{orgNode}}-candidate-b", "to": "{{orgNode}}-critic-b", "condition": "success", "produces": ["contract"] },
  57 + { "from": "{{orgNode}}-critic-a", "to": "{{orgNode}}-synthesis", "condition": "success", "produces": ["artifact"] },
  58 + { "from": "{{orgNode}}-critic-b", "to": "{{orgNode}}-synthesis", "condition": "success", "produces": ["artifact"] },
  59 + { "from": "{{orgNode}}-synthesis", "to": "{{orgNode}}-validator", "condition": "success", "produces": ["artifact"] },
  60 + { "from": "{{orgNode}}-candidate-a", "to": "{{orgNode}}-candidate-a", "condition": "fail", "edgeKind": "backward" },
  61 + { "from": "{{orgNode}}-candidate-b", "to": "{{orgNode}}-candidate-b", "condition": "fail", "edgeKind": "backward" },
  62 + { "from": "{{orgNode}}-synthesis", "to": "{{orgNode}}-candidate-a", "condition": "fail", "edgeKind": "backward" }
  63 + ]
  64 +}
  65 +```
  66 +
  67 +⚠️ 以上是**未经 `validateGraph`/`work-graph-skeletons.test.js` 实测**的草稿,backward 边、fail 兜底边
  68 +的具体挂法(尤其 synthesis 失败该退回哪个候选,还是退回两个候选的公共上游)需要按 `workgraph-planning/
  69 +agent.md` 约束三(每个非入口节点至少一条不带 `failReason` 的兜底边)与约束五(backward 边判定)逐条
  70 +过一遍才能定案,本文档只给方向,不做最终结构校验。
  71 +
  72 +### 关键设计决策:critic 和 synthesis 必须是两个不同节点
  73 +
  74 +这不是本文档凭空要求,是仓库里**已有真实事故记录**——`system/agents/qa-judge/` 是仓库唯一一个"既提
  75 +修改意见又下终态判决"的合一设计先例,`system/work-graph-templates/deliverable.json` 的
  76 +`dataContractNotes`(第 6 行)明确记录了一次真实故障:`org-hunt` 套 `executor.json` 后误选中
  77 +`qa-judge`,critic/judge 合一导致无限重复确认,最终判 `infra_flake`,烧了 **20 次调用 / 31 分钟**才
  78 +被熔断拦下。同一份文档同时留了正面先例:`validator-triager`(只归因不判定)与 `benchmark-validator`
  79 +(只打分不算总分,算术交给不跑 LLM 的 `goal-contract.js`)——这两个都是"评价类角色拆分"的既有范式,
  80 +新的 critic/synthesis 分工应该照这个模式设计:**critic 只给评语和分数,不下终态;synthesis 只做择优/
  81 +融合决策,不重新评分**。
  82 +
  83 +---
  84 +
  85 +## 三、命名(按 27-naming-conventions.md §3.1/§3.2)
  86 +
  87 +| 层 | 名称 | 依据 |
  88 +|---|---|---|
  89 +| Work Graph 节点 | `{父org节点全名}-candidate-a`/`-candidate-b`、`-critic-a`/`-critic-b`、`-synthesis` | §3.1:Work Graph 节点带父节点全名前缀 |
  90 +| System Agent 本体(candidate) | 不新增,复用宿主领域已有的实现类 agent(比如 `org-coder` 场景下就是 `org-coder` 本体本身,跑两次、走两个不同 session scope,见 27-P4 §4.2 的多实例隔离机制) | 候选不是新角色,是同一个实现角色跑两次不同方案,不需要新本体 |
  91 +| System Agent 本体(critic) | `candidate-critic`(不带前缀) | §3.2:本体不带前缀,避免同一本体因前缀被迫复制成多份 |
  92 +| System Agent 本体(synthesis) | `candidate-synthesis`(不带前缀) | 同上 |
  93 +
  94 +**候选节点为什么不需要新本体**:候选做的是"用不同方法解决同一个问题",这本质上是**同一个实现角色**
  95 +(比如 `org-coder`)被调用两次、每次给不同的方法论提示("方案 A 用递归实现,方案 B 用迭代实现"这类
  96 +差异化指令可以放在节点的任务描述里,不需要两个不同的本体)。这与 27-P4 §4.2 已经落地的"同一 system
  97 +agent 的多实例隔离"(`session-pool.js` 的 `scope` 参数)正好对上——两路候选各自拿到独立 session,
  98 +互不污染上下文,机制已经具备,不需要新代码。
  99 +
  100 +**避坑**:`system/work-graph-templates/README.md:210-212` 列出的 6 个命名冲突 id(`agent-creator`/
  101 +`digester`/`evolver`/`evolver-youtube-crawler`/`innovator-*` 系列)不能用;`critic`/`synthesis` 这两个
  102 +职能词目前在 27-NAMING 速查表里没有先例,需要在正式立项时补进 §七 速查表,避免未来又冒出"judge"/
  103 +"reviewer"这类近义词造成混淆(`triager` vs `validator` 已经因为语义邻近踩过一次坑,见 27-NAMING §3.5)。
  104 +
  105 +---
  106 +
  107 +## 四、`workgraph-planning` 选型判据(新增,未定案)
  108 +
  109 +参照 `planner.json` 五节点裁剪判据表(`workgraph-planning/agent.md:181-233`)的成功模式——那张表训练
  110 +前只给"你被允许裁剪"这句空泛授权时打分 34/100,训练出具体的信号+阈值判据表后才到 100/100。新骨架的
  111 +选型判据必须避免重蹈"同义反复式空泛授权"的覆辙,至少要在两处补齐:
  112 +
  113 +1. **骨架自身的 `whenToUse` 字段**(已在 §二草稿里写了初版,需要经过同款训练/评审流程收敛,不能只
  114 + 凭这份草稿直接上生产)。
  115 +2. **`workgraph-planning/agent.md` 新增一条硬规则**,给出"要不要开竞争候选、开几路"的具体信号词和
  116 + 阈值——候选参考信号:
  117 + - S1:验收标准是否已经客观可判定(有明确的正确性/性能基准,不是主观描述)——`否` 则不该开竞争,
  118 + 应该先把验收标准搞清楚,这是另一个问题。
  119 + - S2:该子任务此前是否已经因为"方案有问题需要打回重做"触发过 backward 边——如果是,说明单次尝试
  120 + 成功率确实低,竞争候选可能划算;**如果从未撞过**,不该凭空开竞争(这条呼应 49 号 §2.4 的开放
  121 + 问题 4:"目前没有实证需求")。
  122 + - S3:候选数 N——没有代码层硬顶(见 §五),判据必须给出建议范围(比如 2-3 路),避免 LLM 现场
  123 + 漫无边际地开出过多分支。
  124 +
  125 +**这条判据表本身要不要现在写、写成什么样,属于"立项时才需要拍板"的内容,本文档只指出"必须有"和
  126 +"不能是空泛授权"这两条硬要求,不代本节写最终版本。**
  127 +
  128 +---
  129 +
  130 +## 五、预算与并发风险(量化数字,来自 2026-09-04 代码核实)
  131 +
  132 +- `advanceBatch` 的并发上限取 `run.max_concurrency`,缺省 `DEFAULT_MAX_CONCURRENCY = 5`
  133 + (`server/services/work-graph-db.js:62`)。
  134 +- `checkBudget`(`server/services/graph-engine.js:3029-3044`)只在**取出候选之后、真正 claim 之前**
  135 + 查一次,判定的是"当前已花是否达到上限",**不是"这一批 claim 之后会不会超支"**。也就是说,如果预算
  136 + 只剩 3 次调用余量,但这一轮一次性取出了 5 个 ready 候选(默认并发上限),5 个都会被 claim 并真正
  137 + 跑起来——**实际消耗可能超出预算上限,超出幅度最多是 `maxConcurrency - 1`(默认最多多花 4 次调用)**,
  138 + 下一轮 `checkBudget` 才会拦下后续批次。
  139 +- 对竞争候选设计的直接影响:如果一次性并行展开 N 路候选(N ≤ 5 会被一次性全部 claim),预算消耗是
  140 + N 倍(候选节点 + 各自的 critic 节点,粗算一次三节点竞争至少是 6 个 agent 调用:2 候选 + 2 critic +
  141 + 1 synthesis + 后续 validator),且这个倍数消耗**不会被预算闸门提前拦住**。立项时如果要控制这个
  142 + 风险,需要考虑给竞争型子图单独设一个更保守的 `max_concurrency`,或者在 `workgraph-planning` 的
  143 + 选型判据里对候选数 N 直接设建议上限(见 §四 S3)。
  144 +
  145 +---
  146 +
  147 +## 六、明确不做(本文档范围外)
  148 +
  149 +- 不实现具体的 `candidate-critic`/`candidate-synthesis` agent 人设(`agent.md`/`tools.md`)——那是
  150 + 立项后的工作,本文档只给分工原则(critic/synthesis 分离)。
  151 +- 不修改 `work-graph-templates/README.md` 或 `27-naming-conventions.md` 补录新职能词——留给立项时做。
  152 +- 不实现 §四的选型判据表——只给了判据应该覆盖的信号维度,具体阈值/文案需要走跟 `planner.json` 五节点
  153 + 判据表同款的训练/评审流程才能定案,不能直接照抄草稿上生产。
  154 +- 不解决"候选数 N 没有代码层硬顶"这件事本身——如果立项,这可能是最先要补的安全阀,但本文档只指出
  155 + 风险,不给实现。
  156 +
  157 +---
  158 +
  159 +## 七、与既有文档的关系
  160 +
  161 +- [49-antigravity-inspired-parallel-verification-proposal](./49-antigravity-inspired-parallel-verification-proposal.md):
  162 + 本文档是它 §二 提案 A 的展开,结论一致——没有真实场景前不建议立项。
  163 +- [27-P4](./27-p4-parallel-and-artifacts.md):本设计完全建立在它已完成的并行执行能力(`advanceBatch`/
  164 + 多实例 session 隔离)之上,不需要 27-P4 补任何代码。
  165 +- `system/work-graph-templates/deliverable.json`:critic/synthesis 分离的设计依据直接来自它记录的
  166 + `qa-judge` 真实反模式事故,本文档延续同一条教训。
  167 +- `system/agents/validator-triager/`、`system/agents/benchmark-validator/`:评价类角色"归因/打分/
  168 + 算术判定三者分离"的既有范式,是设计 critic/synthesis 分工时的直接参照。
... ...