diff --git a/docs/README.md b/docs/README.md index 65977f3..c4b5e69 100644 --- a/docs/README.md +++ b/docs/README.md @@ -66,6 +66,8 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d | [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 边指向非祖先,属于修复范围之外 | | [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 人设文档的自我认知改写 | | [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:` 写进本体 `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(训练产物 → 雇佣本体转换)尚未开工 | +| [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`,避免语义混淆)。建议推进顺序:陷阱注册表最低成本先做,证据泛化次之,竞争候选需要真实场景才立项 | +| [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 目前代码层没有硬顶 | | [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)未开工 | ## todo/future/(暂缓,非当前重心) diff --git a/docs/todo/system-design/49-antigravity-inspired-parallel-verification-proposal.md b/docs/todo/system-design/49-antigravity-inspired-parallel-verification-proposal.md new file mode 100644 index 0000000..08f5f45 --- /dev/null +++ b/docs/todo/system-design/49-antigravity-inspired-parallel-verification-proposal.md @@ -0,0 +1,246 @@ +# 49 · 竞争式并行 + 执行级验证严谨度——参考 Antigravity Teamwork 的两条提案 + +> **状态**: 📝 **设计讨论,不代表已拍板**(同 41 号文档的定位)。本文档是参照 Google Antigravity「Teamwork」 +> 多智能体框架()与我们自己 +> 系统做对比后,针对两个具体缺口给出的方案草稿,供下一步决定要不要立项、按什么优先级。 +> **日期**: 2026-09-04 +> **触发场景**: 用户读完 Antigravity Teamwork 的博客文章,要求对照我们的 org/work graph 体系找异同, +> 随后指定「27 号 P4(真并行)」与「34/35 号文档指出的验证严谨度不稳定问题」这两项,要求参考文章 +> 现在就产出一份 todo 方案。 + +--- + +## 一、先纠正一个前提:27 号 P4「真并行」现在剩的东西,比想象的少很多 + +写这份文档前重读了 [27-P4](./27-p4-parallel-and-artifacts.md) 全文——它虽然还挂在 `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 机制](../../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 并发 | 无,可独立随时做 | +| 提案 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](./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` 取舍。 diff --git a/docs/todo/system-design/50-competing-candidates-critic-synthesis-design.md b/docs/todo/system-design/50-competing-candidates-critic-synthesis-design.md new file mode 100644 index 0000000..d0b69a6 --- /dev/null +++ b/docs/todo/system-design/50-competing-candidates-critic-synthesis-design.md @@ -0,0 +1,168 @@ +# 50 · 竞争候选 + 对抗批评 + 综合——新图骨架详细设计草稿 + +> **状态**: 📝 **设计草稿,不代表已拍板**。这是 [49 号文档](./49-antigravity-inspired-parallel-verification-proposal.md) +> §二"提案 A"的展开——49 号只给了三节点拓扑草图,本文档补上骨架 JSON 形状、命名、critic/synthesis +> 分工、预算风险的具体数字。**49 号文档已明确:没有真实场景验证价值前不建议立项写代码**,本文档只是 +> 把"如果要做,该怎么做"想清楚,供下一步决定要不要排期时参考,不是开工指令。 +> **日期**: 2026-09-04 +> **前置阅读**: [49 号文档](./49-antigravity-inspired-parallel-verification-proposal.md) §二(提案动机与 +> 场景边界)、[27-P4](./27-p4-parallel-and-artifacts.md)(并行执行引擎,本设计的地基)、 +> [27-naming-conventions.md](./27-naming-conventions.md)(命名规则) + +--- + +## 一、跟现有骨架的本质区别(复述 49 号 §2.1,作为设计前提) + +`executor-fanout.json` 是**分解型** fan-out:`split` 把任务拆成互不重叠的子任务分给不同分支,`merge` +做的是**拼接**(把互补的子产物合并成一个整体)。竞争候选是**同型** fan-out:N 个分支做的是**同一件事**, +下游节点要做的是**评判 + 择一/融合**,不是拼接。两者拓扑相似、语义完全不同——这是本设计最容易踩错的 +地方,写骨架 JSON 时必须在 `whenToUse`/`dataContractNotes` 里把这条区别说透,否则 `workgraph-planning` +选型时会混淆(现有 `executor.json` vs `deliverable.json` 就发生过一次真实混淆事故,见 §三.2 引用)。 + +--- + +## 二、骨架 JSON 形状草稿 + +沿用 `system/work-graph-templates/README.md:129-165` 定义的字段结构,不发明新字段。 + +```jsonc +// system/work-graph-templates/candidate-council.json(暂定名,未定案) +{ + "id": "candidate-council", + "label": "候选方案竞争评审", + "whenToUse": "验收标准客观可判定,但实现路径不唯一、单次尝试容易收敛到局部最优解的子任务。典型信号词:\ +'设计一个策略/方案'、'优化/选型'、'有几种做法都值得试'。跟 executor-fanout 的区别:executor-fanout 是\ +把一个任务拆成不重叠的子任务分给不同分支各自完成(分解型);本骨架是让多个分支各自独立给出同一个目标\ +的完整方案,再由 critic 评判、synthesis 择优或融合(同型竞争)。不确定任务是该分解还是该竞争时,默认\ +选分解型(executor-fanout)——竞争型成本是 N 倍,只在"真的不确定哪条路线更优"时才划算。", + "ownerOrgNode": "{{orgNode}}", + "nodes": [ + { "nodeName": "{{orgNode}}-candidate-a", "systemAgentId": "{{candidateAgent}}" }, + { "nodeName": "{{orgNode}}-candidate-b", "systemAgentId": "{{candidateAgent}}" }, + { "nodeName": "{{orgNode}}-critic-a", "systemAgentId": "candidate-critic" }, + { "nodeName": "{{orgNode}}-critic-b", "systemAgentId": "candidate-critic" }, + { "nodeName": "{{orgNode}}-synthesis", "systemAgentId": "candidate-synthesis" }, + { "nodeName": "{{orgNode}}-validator", "systemAgentId": "{{validatorAgent}}" } + ], + "dataContractNotes": "候选分支数按实际任务增减(本文件给 2 路起手式,同 executor-fanout 的先例)。\ +每路候选各配一个独立的 critic 节点——critic 只评判、不产出最终方案,也不是候选自己的下游必经步骤,\ +是平行的另一个节点。critic 产出的评语(kind=artifact)与候选产出(kind=artifact)都要能被 synthesis \ +节点区分来源,建议候选各自产出走 contract kind(分支间不冲突,同 executor-fanout 对 split 节点的处理),\ +critic 评语走 artifact kind。千万不要把 critic 和 synthesis 合并成一个节点——qa-judge 早期版本就是\ +"既提修改意见又下终态判决"合一设计,导致过一次真实的无限循环事故(20 次调用/31 分钟才熔断,见\ +deliverable.json 的反模式记录),这条教训必须在本骨架延续。", + "edges": [ + { "from": "{{orgNode}}-candidate-a", "to": "{{orgNode}}-critic-a", "condition": "success", "produces": ["contract"] }, + { "from": "{{orgNode}}-candidate-b", "to": "{{orgNode}}-critic-b", "condition": "success", "produces": ["contract"] }, + { "from": "{{orgNode}}-critic-a", "to": "{{orgNode}}-synthesis", "condition": "success", "produces": ["artifact"] }, + { "from": "{{orgNode}}-critic-b", "to": "{{orgNode}}-synthesis", "condition": "success", "produces": ["artifact"] }, + { "from": "{{orgNode}}-synthesis", "to": "{{orgNode}}-validator", "condition": "success", "produces": ["artifact"] }, + { "from": "{{orgNode}}-candidate-a", "to": "{{orgNode}}-candidate-a", "condition": "fail", "edgeKind": "backward" }, + { "from": "{{orgNode}}-candidate-b", "to": "{{orgNode}}-candidate-b", "condition": "fail", "edgeKind": "backward" }, + { "from": "{{orgNode}}-synthesis", "to": "{{orgNode}}-candidate-a", "condition": "fail", "edgeKind": "backward" } + ] +} +``` + +⚠️ 以上是**未经 `validateGraph`/`work-graph-skeletons.test.js` 实测**的草稿,backward 边、fail 兜底边 +的具体挂法(尤其 synthesis 失败该退回哪个候选,还是退回两个候选的公共上游)需要按 `workgraph-planning/ +agent.md` 约束三(每个非入口节点至少一条不带 `failReason` 的兜底边)与约束五(backward 边判定)逐条 +过一遍才能定案,本文档只给方向,不做最终结构校验。 + +### 关键设计决策:critic 和 synthesis 必须是两个不同节点 + +这不是本文档凭空要求,是仓库里**已有真实事故记录**——`system/agents/qa-judge/` 是仓库唯一一个"既提 +修改意见又下终态判决"的合一设计先例,`system/work-graph-templates/deliverable.json` 的 +`dataContractNotes`(第 6 行)明确记录了一次真实故障:`org-hunt` 套 `executor.json` 后误选中 +`qa-judge`,critic/judge 合一导致无限重复确认,最终判 `infra_flake`,烧了 **20 次调用 / 31 分钟**才 +被熔断拦下。同一份文档同时留了正面先例:`validator-triager`(只归因不判定)与 `benchmark-validator` +(只打分不算总分,算术交给不跑 LLM 的 `goal-contract.js`)——这两个都是"评价类角色拆分"的既有范式, +新的 critic/synthesis 分工应该照这个模式设计:**critic 只给评语和分数,不下终态;synthesis 只做择优/ +融合决策,不重新评分**。 + +--- + +## 三、命名(按 27-naming-conventions.md §3.1/§3.2) + +| 层 | 名称 | 依据 | +|---|---|---| +| Work Graph 节点 | `{父org节点全名}-candidate-a`/`-candidate-b`、`-critic-a`/`-critic-b`、`-synthesis` | §3.1:Work Graph 节点带父节点全名前缀 | +| System Agent 本体(candidate) | 不新增,复用宿主领域已有的实现类 agent(比如 `org-coder` 场景下就是 `org-coder` 本体本身,跑两次、走两个不同 session scope,见 27-P4 §4.2 的多实例隔离机制) | 候选不是新角色,是同一个实现角色跑两次不同方案,不需要新本体 | +| System Agent 本体(critic) | `candidate-critic`(不带前缀) | §3.2:本体不带前缀,避免同一本体因前缀被迫复制成多份 | +| System Agent 本体(synthesis) | `candidate-synthesis`(不带前缀) | 同上 | + +**候选节点为什么不需要新本体**:候选做的是"用不同方法解决同一个问题",这本质上是**同一个实现角色** +(比如 `org-coder`)被调用两次、每次给不同的方法论提示("方案 A 用递归实现,方案 B 用迭代实现"这类 +差异化指令可以放在节点的任务描述里,不需要两个不同的本体)。这与 27-P4 §4.2 已经落地的"同一 system +agent 的多实例隔离"(`session-pool.js` 的 `scope` 参数)正好对上——两路候选各自拿到独立 session, +互不污染上下文,机制已经具备,不需要新代码。 + +**避坑**:`system/work-graph-templates/README.md:210-212` 列出的 6 个命名冲突 id(`agent-creator`/ +`digester`/`evolver`/`evolver-youtube-crawler`/`innovator-*` 系列)不能用;`critic`/`synthesis` 这两个 +职能词目前在 27-NAMING 速查表里没有先例,需要在正式立项时补进 §七 速查表,避免未来又冒出"judge"/ +"reviewer"这类近义词造成混淆(`triager` vs `validator` 已经因为语义邻近踩过一次坑,见 27-NAMING §3.5)。 + +--- + +## 四、`workgraph-planning` 选型判据(新增,未定案) + +参照 `planner.json` 五节点裁剪判据表(`workgraph-planning/agent.md:181-233`)的成功模式——那张表训练 +前只给"你被允许裁剪"这句空泛授权时打分 34/100,训练出具体的信号+阈值判据表后才到 100/100。新骨架的 +选型判据必须避免重蹈"同义反复式空泛授权"的覆辙,至少要在两处补齐: + +1. **骨架自身的 `whenToUse` 字段**(已在 §二草稿里写了初版,需要经过同款训练/评审流程收敛,不能只 + 凭这份草稿直接上生产)。 +2. **`workgraph-planning/agent.md` 新增一条硬规则**,给出"要不要开竞争候选、开几路"的具体信号词和 + 阈值——候选参考信号: + - S1:验收标准是否已经客观可判定(有明确的正确性/性能基准,不是主观描述)——`否` 则不该开竞争, + 应该先把验收标准搞清楚,这是另一个问题。 + - S2:该子任务此前是否已经因为"方案有问题需要打回重做"触发过 backward 边——如果是,说明单次尝试 + 成功率确实低,竞争候选可能划算;**如果从未撞过**,不该凭空开竞争(这条呼应 49 号 §2.4 的开放 + 问题 4:"目前没有实证需求")。 + - S3:候选数 N——没有代码层硬顶(见 §五),判据必须给出建议范围(比如 2-3 路),避免 LLM 现场 + 漫无边际地开出过多分支。 + +**这条判据表本身要不要现在写、写成什么样,属于"立项时才需要拍板"的内容,本文档只指出"必须有"和 +"不能是空泛授权"这两条硬要求,不代本节写最终版本。** + +--- + +## 五、预算与并发风险(量化数字,来自 2026-09-04 代码核实) + +- `advanceBatch` 的并发上限取 `run.max_concurrency`,缺省 `DEFAULT_MAX_CONCURRENCY = 5` + (`server/services/work-graph-db.js:62`)。 +- `checkBudget`(`server/services/graph-engine.js:3029-3044`)只在**取出候选之后、真正 claim 之前** + 查一次,判定的是"当前已花是否达到上限",**不是"这一批 claim 之后会不会超支"**。也就是说,如果预算 + 只剩 3 次调用余量,但这一轮一次性取出了 5 个 ready 候选(默认并发上限),5 个都会被 claim 并真正 + 跑起来——**实际消耗可能超出预算上限,超出幅度最多是 `maxConcurrency - 1`(默认最多多花 4 次调用)**, + 下一轮 `checkBudget` 才会拦下后续批次。 +- 对竞争候选设计的直接影响:如果一次性并行展开 N 路候选(N ≤ 5 会被一次性全部 claim),预算消耗是 + N 倍(候选节点 + 各自的 critic 节点,粗算一次三节点竞争至少是 6 个 agent 调用:2 候选 + 2 critic + + 1 synthesis + 后续 validator),且这个倍数消耗**不会被预算闸门提前拦住**。立项时如果要控制这个 + 风险,需要考虑给竞争型子图单独设一个更保守的 `max_concurrency`,或者在 `workgraph-planning` 的 + 选型判据里对候选数 N 直接设建议上限(见 §四 S3)。 + +--- + +## 六、明确不做(本文档范围外) + +- 不实现具体的 `candidate-critic`/`candidate-synthesis` agent 人设(`agent.md`/`tools.md`)——那是 + 立项后的工作,本文档只给分工原则(critic/synthesis 分离)。 +- 不修改 `work-graph-templates/README.md` 或 `27-naming-conventions.md` 补录新职能词——留给立项时做。 +- 不实现 §四的选型判据表——只给了判据应该覆盖的信号维度,具体阈值/文案需要走跟 `planner.json` 五节点 + 判据表同款的训练/评审流程才能定案,不能直接照抄草稿上生产。 +- 不解决"候选数 N 没有代码层硬顶"这件事本身——如果立项,这可能是最先要补的安全阀,但本文档只指出 + 风险,不给实现。 + +--- + +## 七、与既有文档的关系 + +- [49-antigravity-inspired-parallel-verification-proposal](./49-antigravity-inspired-parallel-verification-proposal.md): + 本文档是它 §二 提案 A 的展开,结论一致——没有真实场景前不建议立项。 +- [27-P4](./27-p4-parallel-and-artifacts.md):本设计完全建立在它已完成的并行执行能力(`advanceBatch`/ + 多实例 session 隔离)之上,不需要 27-P4 补任何代码。 +- `system/work-graph-templates/deliverable.json`:critic/synthesis 分离的设计依据直接来自它记录的 + `qa-judge` 真实反模式事故,本文档延续同一条教训。 +- `system/agents/validator-triager/`、`system/agents/benchmark-validator/`:评价类角色"归因/打分/ + 算术判定三者分离"的既有范式,是设计 critic/synthesis 分工时的直接参照。