# 27-E2E · 端到端任务执行流程 — 从建公司到验收收敛 > **所属**: [27 Graph Agent 架构](./27-graph-agent-architecture.md) 的跨阶段总览文档,串起 P2(Org Graph)、P3/P4(Work Graph 执行)、P5(自我进化)。 > **版本**: v0.1 > **日期**: 2026-08-15 > **前置**: [27-P2 Org Graph 落地](./27-p2-org-graph.md)、[27-P3/P4 Work Graph 执行控制台](./27-p3-p4-work-graph-console.md)、**以及本文档最重要的参考源** `docs/prd/newfunction/_spec/`(DevLoop 的完整 MVCP 规格,尤其 `loops-overview.md` / `loops-l1.md` / `loops-l2.md` / `loops-l3.md` / `sdd-process.md` / `plan-cost-concurrency.md`)。 > **需求源头**: [27-REQ 原始需求](./27-requirement.md) —— 本文档是对那些原话的结构化转述,原文以那份为准。 > **配套**: [27-EXAMPLE 参考场景走查](./27-example-dev-company-walkthrough.md) —— 本文档讲机制,那份文档把机制在一家具体公司上跑一遍数。两份对照着读。 --- ## 一、这份文档要回答什么 本文档把口述的七阶段端到端流程结构化,然后回答三个问题: 1. 这个流程和已经写好的 P2 / P3-P4 设计有什么差异? 2. 哪些地方没有考虑到? 3. 这个流程是否是这样实现的? --- ## 二、三条核心结论(先给答案) ### 结论 1:这套流程 70-80% 已经在本仓库被详细设计过,但它藏在 DevLoop 的规格里,而不在 27 号文档体系里 `docs/prd/newfunction/_spec/` 是一套 50 份文件、按 **MVCP(Model / View / Control / Process)四象限**组织的完整 SDD。它已经定义了: - **三层嵌套循环 L1 ⊂ L2 ⊂ L3**(`loops-overview.md`),带完整状态机、退出条件、回滚目标、分级预算,甚至给每层配了颜色 token(L1 Emerald / L2 Amber / L3 Violet)。 - **失败归因的四分类调度**(`loops-l2.md` + `sdd-process.md` P-2):`contract_mismatch` / `impl_bug` / `spec_ambiguous` / `infra_flake`,每类决定「改不改设计文档、重置哪些节点、烧不烧预算」。 - **分级预算与熔断**(`sdd-process.md` P-7):`retry_budget=5`(每 Unit)、`l2_budget=3`(每 PRD rev)、`token_budget=5M`(每项目)、单 agent 墙钟 10min。 - **成本与并发预算的数字版**(`plan-cost-concurrency.md`):每个 agent 每次调用的 token 估算、典型项目总成本(中项目 ≈ 410K token ≈ $4.8)、三层并发上限、墙钟估算、6 个监控指标及告警阈值。 - **前端组件全集**(`sdd-view.md` V-1..V-11),且**代码已经存在**:`web/src/components/devloop/` 下 8 个组件,含 `UnitsDAG.vue`(SVG + Kahn 分波布局的 DAG 渲染器)、`LiveAgentStream.vue`(带 Last-Event-ID 断线重连的 SSE 消费)、`UnitDrawer.vue`(节点详情抽屉)。 **这直接影响你的问题「这个流程是否是这样实现的」——答案是:在"一家写代码的公司"这个具体场景下,是的,而且已经实现了大半。** `loop-controller.js` 的 `runProject()` 已完整实现(不是我在 [27-P3/P4](./27-p3-p4-work-graph-console.md) 文档里写的 501,那条陈述已过期,见 §九),包含 Kahn 拓扑分波、L2 闸门、Integrator、Triager 四分支调度、预算熔断、SSE 埋点。 ### 结论 2:DevLoop 就是你这套架构的一个「硬编码实例」 把两者并排看,对应关系是逐项的: | 你描述的通用概念 | DevLoop 里的硬编码版本 | |---|---| | Org Graph(planner → coder → validator) | 固定的 6 个 agent:PM → Architect → Coder/Tester → Integrator → Triager | | org node 调 planning subagent 规划自己的 work graph | Architect 生成 `units.json`(一张带 `depends_on` 的 DAG)——**图是被规划出来的,但规划者是写死的 Architect** | | work graph 节点 = system agent 引用 | Unit = 一次 Coder + Tester 调用 | | work graph 内 loop 回退 | **L1**:`runUnit` 的 retry-with-reflection,`retry_budget=5` | | fan-out 并行 code subagent → fan-in 整合 → integration test | `_groupUnitsByWave()` Kahn 分波 → L2 闸门 → Integrator 跑真实进程 e2e | | 出 bug 时判断「重新 planning 还是跳回某节点」 | **L2**:BugTriager 输出 `category` 四分类,LoopController 据此分支 | | 全局 validator + 人工介入 | **L3**:human feedback loop + `sign-off` | **所以 27 号文档 §五把「DevLoop 收编」列为 P6(可选),这个定位是低估了。** DevLoop 不是一个将来可以顺便合并进来的边缘子系统,它是这套通用架构唯一一个已经跑通的参考实现。正确的做法是**反过来:把 DevLoop 的 L1/L2/L3 机制抽象成通用 Work Graph 引擎的默认行为**,而不是先造一个通用引擎、将来再想办法把 DevLoop 塞进去。 ### 结论 3:你的流程里有一个环节是真正全新的,而且它恰好是风险最大的一环 第七步「不成功则判断是不是需要迭代某一个 system agent 的 skill / memory / data / LLM,先迭代 system agent,再 loop 某个 work graph」——**这一层在 DevLoop 的 L1/L2/L3 里不存在**。DevLoop 的 L3 是「找人类补充需求」,不是「让 agent 自己变强」。这一层对应的是 27 号文档的 P5(自我进化),但 P5 原本被设计成一个离线的、benchmark ≥95 才准生效的慢速通道,**而你的流程把它拉进了任务执行的在线重试循环里**。这个改动带来两个必须处理的风险,见 §八。 --- ## 三、流程还原(七阶段) 每阶段标注:✅ 已实现 / 📐 已设计未实现 / ⚠️ 部分存在有冲突 / ❌ 空白 ### 阶段 1 · 用户新建 company,写入目标和描述 **状态**:✅ 已实现(`POST /api/company/create`,`company-service.js:37`) `company.json` 已有 `description` 字段。当前创建出来的是「没有员工的空壳公司」,响应文案提示"请通知 MasterBot 雇佣 Agent"。 ### 阶段 2 · orggraph-planning 根据描述生成基础 org graph **状态**:📐 已设计未实现([27-P2](./27-p2-org-graph.md) §4.8/§4.9/§4.10) P2 已经设计了:`system/org-graph-templates/{dev,content,ops}.json` 模板库 + `orggraph-planning` agent + 创建时自动招聘并 fire-and-forget 触发首轮对话。 「每个 org node 可以引用已有 system agent,也可以新建一个」——这一点 P2 通过 `hire()` 的 `needs_training` 分支已覆盖(`company.js:917-940` 已有自动触发 agent-creator + innovator 的流水线)。 ⚠️ **但有一处粒度不一致**:你举例说开发型公司需要 planner / code / validator **三个**节点;P2 的 `dev.json` 模板写的是 ceo / cto / hr / devloop-pm / devloop-architect / devloop-coder / devloop-tester **七个**。这不是笔误,而是两种不同的建模视角,见 §五。 ### 阶段 3 · 用户输入一个具体的开发 task **状态**:⚠️ 部分存在,且**没有「给公司下达任务」的入口** 现有任务系统在 `server/routes/agent-chat.js`,不在 `task-service.js`(后者是只读聚合器,靠时间窗口启发式猜测父子关系): - `POST /api/agent/task/dispatch`(行 1470):入参 `{from, to, task, priority, goalId, nodeId, autoExecute, parentTaskId}`,taskId 格式 `T-{base36}`,持久化为**全局平铺 JSON** `system/tasklog/{taskId}.json`,30 分钟去重窗口,`autoExecute` 时 HTTP 自调用触发目标 agent。 - `POST /api/agent/task/report`(行 1656):**已有的完成回调机制**——更新 todo/plan、更新 goal 节点、自动推进 Pipeline、回调唤醒上级 agent。 ❌ **缺口**:`from`/`to` 都必须是已存在的 agent 目录,**只支持 agent → agent 派发,不支持「用户 → 公司」**。你的流程第 3 步需要一个新入口:用户把任务给公司,由公司决定哪个 org node 先接手。 ⚠️ **另一处**:27 号文档 `work_graphs.goal_task_id` 这个单字段不够用。定位一个 OKR 节点需要 `(companyId, okrNodeId)`(OKR 树 per-company 存储,节点 ID 是点分层级)。建议拆成 `goal_id`(一次人类需求,验收边界)+ `task_id`(执行单元,一个 goal 多个)+ `okr_node_id`(长周期度量归属)三个字段,三者基数不同不能混用,见 [27-NAMING](./27-naming-conventions.md) §四。⚠️ 另见 [27-NAMING](./27-naming-conventions.md) §六:OKR 体系当前在代码里叫 `goal`(`goals.js` / `G-001.1.1` / `data/companies/{cid}/goals/`),应正名为 `okr` / `O-001.1.1`。 ### 阶段 4 · 第一个 org node(planner)调 planning-work-graph subagent 规划自己的 work graph **状态**:📐 概念已在 27 号文档 §3.4 定义,执行引擎见 [27-P3/P4](./27-p3-p4-work-graph-console.md),**但 planning agent 本身未设计** 你举的例子 `brd-planning → prd-planning → sdd-planning → benchmark → testdata → planner-validator → loop-validator`,与 DevLoop 的实际链路高度重合: | 你的节点 | DevLoop 对应物 | 状态 | |---|---|---| | brd / prd | PM Agent 产出多页 PRD 站点(`sdd-model.md` M-3) | ✅ 已实现 | | sdd | Architect 产出 SDD(MVCP 四页)+ `units.json` | ✅ 已实现 | | benchmark / testdata | Architect 同步产出 `integration/spec.json`(M-6) | ✅ 已实现 | | planner-validator | Architect 的 self-check + L2 gate 判定 | ✅ 已实现 | | loop-validator | Loop-Validator(27 号 §3.5)/ BugTriager | 📐 27 号未实现;DevLoop 版 ✅ 已实现 | 💡 **值得注意**:DevLoop 的 `loops-l2.md` 已经就「谁来写验收标准」做过一次显式的方案选型(A/B/C 三选一),并选了 **A:由 Architect(设计者)在生成 SDD 时同步产出 `integration/spec.json`**,明确否决了 **C:由 Integrator(执行者)自己写测试**,理由是「容易写一个永远会通过的 trivial test」。你的流程让 planner 阶段产出 benchmark/testdata、让后面的 validator 阶段消费它,正好符合方案 A 的思路——**设计者定标准、执行者不定标准**。这条已经被论证过的原则应该在通用层继承下来。 ### 阶段 5 · 完成当前 org node,进入下一个 org node **状态**:❌ **这是与 P2 设计的核心语义冲突所在**,见 §五 ### 阶段 6 · code agent 规划 code work graph:fan-out 并行 → fan-in 整合 → integration test → 出 bug 判断重新 planning 还是跳回节点 **状态**:⚠️ **结构全部就位,但并行没做,且有一条不变量直接挡路** - **分波结构**:✅ `_groupUnitsByWave()`(`loop-controller.js:523`)是标准 Kahn 拓扑分波,`units.json` 的 `depends_on` 声明 DAG,`doc-store.js` 写入前用三色 DFS 校验无环。前端 `UnitsDAG.vue` 已经能渲染这个分波布局。 - ❌ **波内实际是串行的**:`loop-controller.js:609` 明确注释 `// 串行跑(mock 同步快,不需并行)`,实现是 `for (const uid of wave) { await runUnit(...) }`。 - ⚠️ **改成并行会立刻撞上两处障碍**: 1. `_spec/CONVENTIONS.md` §12 第一条不变量:**「任意 (pid, agent) 同时只允许 1 个 status=running」**——如果并行跑 3 个 coder subagent,它们是同一个 system agent 的三次调用,直接违反这条。 2. `SessionPool` 的 key 是 `acp:{agentName}:{client}:{deploy}:{workDir}[:{scope}]`(`session-pool.js:29`),同 agent 同 workDir 会**复用同一个 session**——并发调用会撞在一起。必须引入 `scope` 之类的实例隔离。 - ✅ **fan-out/fan-in 的现成实现存在**,只是 DevLoop 没用它:`orchestrator.js:265` 的 `executeWithDependencies()` 用 `Scheduler.getExecutionGroups()` 分组 + `Promise.allSettled` 组内并行、组间串行(天然 fan-in 屏障),单点失败降级成 `{status:'ERROR', retryable}` 而不终结整组。另有 `agent-chat.js:2440` 的 sub-agent 批量调度(`MAX_CONCURRENCY=2`,带 `checkpoint.json` 断点续跑)。 - ✅ **「重新 planning 还是跳回原节点」这个判断已经有成熟实现**:这正是 BugTriager 的 `category` 四分类(`sdd-process.md` P-2): | category | 改不改设计文档 | 重置哪些节点 | 烧不烧 L2 预算 | |---|---|---|---| | `contract_mismatch` | ✅ 改 SDD(≈ 重新 planning) | ✅ reset 相关 unit | ✅ 烧 | | `impl_bug` | ❌ | ✅ 只 reset 那一个(≈ 跳回节点) | ❌ 不烧 | | `spec_ambiguous` | ❌(升 L3 找人) | ❌ | ❌ | | `infra_flake` | ❌ | ❌(直接重跑) | ❌ | **这套「不同失败类型消耗不同预算」的设计比单一计数器精细得多**,而且自带防死循环:`confidence < 0.5` 自动升 L3 交给人,`agents-triager.md:397` 还规定「第 2 次 triage 自动升 spec_ambiguous」防止在错误归因上打转。 ### 阶段 7 · 全局 validator:整体判断 / 测试 / 审计 / benchmark / test data,失败则迭代 system agent 再 loop > ⚠️ **v0.2 重要更正**:本节 v0.1 把 benchmark / test data 理解成了**系统级基础设施**,因此去核实 `benchmark-runner.js` / `benchmark.sqlite` 并判定"是假的、不存在"。**这个理解是错的。** 实际设计是:benchmark / test data / test script 是 **work graph 里的三个 agent 节点**(`goal-benchmark` / `goal-test-data` / `goal-test-script`),由 planning agent 动态决定加哪几个。完整设计见 §十一。下面关于既有基础设施的核实结论仍然属实,但**它们与本流程无关**——本流程不使用 `benchmark-runner.js`。 **状态**:⚠️ 产出侧有清晰设计(§十一),**执行侧仍是空白**(产出验收标准 ≠ 执行验收标准) - ⚠️ **`benchmark-runner.js` 是假的**。文件头自述"MVP 版本: 使用 heuristic-based 评分"。实际算法:`successRate` 基础 70 分、描述超 20 字加 5 分、`robustness` 靠 grep 描述里有没有 "error"/"retry"/"timeout" 字符串、`speed`/`cost` 按 layer 查表推算。**测试用例数是伪造的**:`testCasesTotal = 5 + seededRandom(0,10)`。三张表(`benchmark_runs`/`comparisons`/`security_scans`)全部以 `skill_name` 为主体,**没有 agent_id / task_id / company_id 任何一列**——它是给 Skill 打分的,不能给 agent 或 task 用。 - ❌ **"test data" 作为系统概念完全不存在**。全仓库搜到的都是 agent 自己在 workspace 里写的自然语言文本。 - ✅ **唯一真实执行的评测是 DevLoop 的 integration test**(起真实进程跑 e2e,产 `integration/runs/{runId}/result.json`,含 `ok` / `failures[]` / http-trace),但它是 DevLoop 私有的。 - 💡 **`qa-judge` 的协议设计非常契合你的三级恢复,但它没有任何程序化调用入口**。它的输出协议(`system/templates/qa-judge/agent.md:223-333`)是严格 JSON,`status: "PASS" | "REWORK" | "RETRAIN_REQUIRED"`,而它的**缺陷溯源三分类几乎逐条对应你说的三级**: | qa-judge 分类 | 判断标准 | 输出 | 对应你的第几级 | |---|---|---|---| | 粗心错误 | 5 分钟内可修正,无需新知识 | `REWORK` + 具体修正位置 | L1 跳回某节点只改一部分 | | 设计缺陷 | 需要调整设计思路 | `REWORK` + 设计建议 | L2 重新 planning 一张 work graph | | **能力缺陷** | 反映知识框架缺失 | `RETRAIN_REQUIRED` + `capability_gaps[]` | **L4 迭代 system agent** | 但全仓库 grep,`qa-judge` 只出现在测试文件和模板目录里,**生产代码零引用**——它靠 agent 在对话里按 prompt 自行调用,没有调用入口、没有对 JSON 输出做 schema 校验、判决不持久化。 --- ## 四、与 P2 / P3-P4 设计的差异汇总 | # | 你的流程 | P2 / P3-P4 现有设计 | 差异性质 | |---|---|---|---| | 1 | org graph 逐节点**执行**,planner 是「执行的第一个节点」 | org graph 是**静态汇报结构**(`reports_to`/`collaborates_with`),不执行 | **语义冲突**,见 §五 | | 2 | 开发公司 = planner / code / validator 三节点 | `dev.json` 模板 = 7 个层级化角色 | 建模粒度不一致,见 §五 | | 3 | code 阶段 fan-out 并行多个 subagent | P3/P4 的 `advanceOne()` 明确一次只推进**一个**节点 | **能力缺失**,需重新设计 | | 4 | 失败时判断「重新 planning vs 跳回节点」 | P4 的 Loop-Validator 只有「跳回节点」一种 | 缺一个分支;DevLoop 的四分类可直接借用 | | 5 | 第三级:迭代 system agent 本体 | 27 号 P5 有,但被设计成离线慢通道,不在执行循环里 | **新增层级**,见 §八 | | 6 | 验收标准 = benchmark / test data | 两份文档都没提验收标准从哪来、由谁执行 | **完全空白** | | 7 | 用户下达具体 task | 两份文档都没有任务入口设计 | **完全空白** | --- ## 五、Org Graph 的定位(v0.2 已定案) > ✅ **本节 v0.1 提出的 A/B/C 三方案已作废,定案如下**: > > **Org Graph 是 company 级别生成的 workflow;Work Graph 是 org graph node 级别生成的 workflow。** > > 两者是**同一种东西在不同层级上的递归**,不是两种不同的结构: > > | | 生成者 | 生成时机 | 节点指向 | 边的语义 | > |---|---|---|---|---| > | **Org Graph** | orggraph-planning | 建公司时,一次 | org node agent | 执行流(success/fail 条件) | > | **Work Graph** | workgraph-planning agent | 每个 org node 接到任务时 | system agent 引用 | 执行流(success/fail 条件) | > > **这意味着 [27-P2](./27-p2-org-graph.md) 现在的 org graph 模型需要改**:它把边定义成 `reports_to` / `collaborates_with`(静态汇报结构),而实际需要的是**带 success/fail 条件的执行流边**,与 work graph 的边同构。汇报关系如果还需要,应降级为节点上的元数据属性,而不是 org graph 的主干语义。 > > **好处**:一套 schema、一套执行引擎、一套控制台 UI,在两个层级上原样复用;三层下钻(org graph → work graph → 并行子图)天然递归;"启动/下一步/暂停/停止/重试"五个操作在每一层语义完全一致。 > > 下面保留 v0.1 的问题分析作为背景(说明为什么"静态汇报结构"这个建模行不通),A/B/C 方案表已不再适用。 ### 问题(v0.1 分析,保留作为背景) P2 把 Org Graph 定义为**公司的静态协作结构**——节点是角色引用,边是 `reports_to` / `collaborates_with`,它描述"HR 向 CTO 汇报",**它不执行任何东西**。 你描述的是**执行序列**——"org planner agent 作为执行 org graph 的第一个节点"、"完成当前 org graph 节点工作,进入下一个 code graph node agent"。planner → coder → validator 是一条流水线。 **这两件事是正交的**:planner / coder / validator 三者之间大概率没有汇报关系(他们可能都向 CTO 汇报),但他们之间有明确的执行先后。用 `reports_to` 边表达执行顺序会把两种语义混在一张图里,之后无法区分"谁是谁的上级"和"谁的产出喂给谁"。 ### ~~三个方案~~(已作废,见本节开头定案;保留供追溯) | 方案 | 做法 | 评价 | |---|---|---| | **A** | 给 `org_graph_edges` 加第三种 `relation_type='hands_off_to'`,org graph 同时承载汇报结构和执行流水线 | 简单,但把**一条固定流水线焊死在公司上**。一个 bugfix 任务可能不需要 planner,一个调研任务可能不需要 coder——任务级的差异无法表达 | | **B(推荐)** | 每个任务规划一张**顶层 Work Graph,它的节点指向 org node**(而不是直接指向 system agent)。org graph 保持 P2 的静态定义不变 | 任务级的参与者和顺序都可变;**整套 P3/P4 引擎、控制台 UI、暂停/单步/重试全部原样复用**,因为它就是一张 work graph,只是节点类型不同 | | **C** | B + orggraph-planning 额外产出一份 `defaultPipeline` 作为规划起点 | B 的补充,让「开发型公司默认就是 planner→coder→validator」这个直觉落地,同时保留任务级偏离的自由 | ### 定案的落地方式 1. **`org_graph_edges` 改为执行流边**,与 `work_graph_edges` 同构: ```sql -- P2 现有:relation_type IN ('reports_to','collaborates_with') ← 静态汇报结构,作废 -- 改为: condition TEXT NOT NULL CHECK (condition IN ('success','fail')), edge_kind TEXT NOT NULL DEFAULT 'forward' CHECK (edge_kind IN ('forward','backward')), ``` 汇报关系若仍需要,降级为 `org_graph_nodes` 上的一个可空属性(`reports_to_node_id`),不再是图的主干语义。 2. **两层图的递归关系**(复用 [27-P3/P4](./27-p3-p4-work-graph-console.md) 已有的 `parent_node_id`): ``` Org Graph(company 级 workflow,orggraph-planning 建公司时生成) 节点 = org node agent └─ Work Graph(org node 级 workflow,该 node 接到任务时由 planning agent 生成) 节点 = system agent 引用 └─ 嵌套子图(fan-out 出来的并行分支,P3/P4 §4.D.3 已设计) ``` 3. **执行引擎、schema 形态、控制台 UI 在两层之间完全复用**——这是这个定位最大的收益:不需要为 org 级单独造一套控制逻辑,`启动/下一步/暂停/停止/重试` 在每层语义一致,控制台天然是逐层下钻。 --- ## 六、可以直接复用的既有机制(两份设计文档都没引用到) 以下全部来自 `_spec/` 或已落地代码,**建议在 P3/P4 实现前先读一遍,避免重复发明**: 1. **`contract_hash` 三方一致性校验**(`sdd-model.md` M-2/M-5 + `doc-store.js:382`):`hashContract()` 对 `contract.exports` 做递归 key 排序的规范化序列化后 sha256 取前 16 位。Coder 的 `contract_bridge` 工具校验三件事:contract.json 存在、`version` 与重算 hash 自洽、重算 hash 与 `units.json` 声明的 `contract_hash` 相等。**这解决的正是"上游产物改了,下游还停在旧契约上"这个跨节点一致性问题。** 2. **L2 闸门的 hash 校验**(`loops-l2.md`):闸门条件不是"所有节点都跑过一次",而是"所有节点 status=passed **且** `contract_hash` 与当前 SDD 一致",避免设计文档改过之后某个旧节点还停在 passed。 3. **增量重跑算法**(`loops-l3.md`):added / changed / removed / **unchanged** 四分类,`unchanged`(id 在且 hash 不变)**保持 passed 无须重跑**——"这是增量化的关键"。这直接回答了我在 P3/P4 §八.3 列为开放问题的「重试要不要级联下游」。 4. **跨节点读取隔离**(`CONVENTIONS.md` §12):**跨 unit 只允许读 `../{otherUnit}/contract.json`,禁止读 `code/`**。下游只能看到上游的契约,看不到实现。 5. **BugTriager 四分类 + 差异化预算消耗**(§三 阶段 6 的表)。 6. **分级预算与熔断**(`sdd-process.md` P-7)+ **成本/并发的数字版**(`plan-cost-concurrency.md`):三层并发上限(L1 ≤5 并行、L2 串行 1 个、系统 ≤20 ACP session、同公司 ≤3 项目、bash 子进程 ≤50)。 7. **前端组件**:`UnitsDAG.vue` 已实现 SVG + Kahn 分波布局 + 节点状态着色 + 点击下钻;`LiveAgentStream.vue` 已实现带 Last-Event-ID 重连的 SSE 消费。**我在 P3/P4 §四.B.2 写"手写分层布局算法"时不知道这个组件已经存在**,实际工作量应该是扩展它而不是从零写。 8. **任务回调链路**:`POST /api/agent/task/report` 已实现「更新 goal 节点 → 自动推进 Pipeline → 回调唤醒上级 agent」。 9. **`orchestrator.executeWithDependencies()`**:现成的 fan-out/fan-in(`Promise.allSettled` + 依赖分组 + 单点失败降级)。 10. **`memory-service.js`**(1059 行,9 个导出函数):`cerebellum/`(固化的成功执行方案,按关键词召回)、`hippocampus-index.json`(索引)、`autoReflect()`、`consolidateMemory()`。这是 L4 里"迭代 memory"唯一一块已经成熟的基础设施。 --- ## 七、没有考虑到的地方 ### 7.1 三级恢复叠加会让熔断失效(最严重) 你的流程有三级恢复:跳回节点 → 重新 planning → 迭代 system agent。**如果每一级都重置下一级的计数器,整个循环就没有终止条件**,而"直至最后满足这个任务的 benchmark"这句话字面上就是一个无限循环。 具体地说:L1 的 `retry_budget=5` 在 L2 重新 planning 之后会重新计数;L2 的 `l2_budget=3` 在 L4 迭代完 agent 之后如果也重置,那么"迭代 agent → 重跑 L2 三轮 → 再迭代 agent"可以永远跑下去。 **DevLoop 已经部分解决了这个问题**:它的 `l2_budget` 是「每个 PRD rev 3 轮」而不是「每次 L2 3 轮」,且 `impl_bug` / `infra_flake` 不烧预算。但它没有第四层,所以没遇到这个问题。 **建议**:引入一个**任务级总预算**,跨所有层级共享、只增不减: ``` task_budget = { total_agent_calls: 100, // 所有层级所有 agent 调用的总次数 total_tokens: 5_000_000, wallclock_ms: 7_200_000, // 2h l4_iterations: 2, // 迭代 system agent 最多 2 次(最贵、副作用最大) } ``` 任何一层的重试都从这个总池子里扣,扣完即挂起等人工。分层预算(`retry_budget` / `l2_budget`)继续保留作为**局部快速失败**信号,但总预算是最终兜底。 ### 7.2 ~~L4 迭代 public system agent 会污染其他公司~~ ✅ v0.2 已解决 > **已由 §八 的 L4-company / L4-general 拆分解决**:在线自动迭代只碰 company 记忆分区,general 本体的更新移出任务循环、改由定时 dream 流程 + master agent/人工驱动。下面保留原始风险分析作为背景,其中提的三个缓解方案(fork 副本 / 只改私有 / 人工确认)已不再需要单独采纳。 #### 原始风险分析(v0.1,保留作为背景) 27 号文档 §3.2 定义 `scope=public` 的 system agent 跨公司共享记忆。如果 `coder` 是 public、被 10 家公司引用,那么"为了让 A 公司这个任务通过,迭代 coder 的 skill/memory"意味着**为了修一个任务,改了 10 家公司共用的 agent**。 27 号文档自己已经意识到这个风险(§3.2 要求公共 `memory.md` 的写入走自省校验 + git 版本化),但那是针对"缓慢的自我进化"设计的,不是针对"任务失败了赶紧改一下再试"这种在线高频路径。 **建议**(三选一,倾向 A): - **A**:L4 触发时,先把该 system agent **fork 成一个 company-scoped 副本**(`scope='company'`, `owner_company_id`),只改副本,本公司后续调用指向副本。副本表现好、跑过 benchmark ≥95,再走既有的 `depositTemplate()` 链路回灌 public。**这样在线迭代的爆炸半径永远限制在一家公司内。** - **B**:L4 只允许改 company-scoped 的私有记忆(`companies/{cid}/memory.md`),不许碰公共 `memory.md`/`skills/`。能力有限但零风险。 - **C**:L4 需要人工确认才生效。安全但破坏了自动化。 ### 7.3 谁来验收「验收标准」本身(v0.2 已部分缓解) planner 阶段产出 benchmark/testdata/testscript,validator 阶段用它验收。**如果产出了一个过松的标准,任何垃圾都能通过;产出了一个不可能达成的,就永远收敛不了。** DevLoop 就这个问题做过显式决策(`loops-l2.md` 方案 A/B/C),选择"设计者写、执行者不写",明确否决"执行者自己写测试",理由是执行者会写出"永远会通过的 trivial test"。 ✅ **§十一 的三节点设计天然符合这条原则**:`goal-benchmark` / `-test-data` / `-test-script` 三个 agent 与真正写代码的 coder 是**完全不同的 system agent**,产出者和被验收者分离,不存在"自己给自己出考题"的激励问题。 ⚠️ **但仍未解决"标准写错了"这一层**。缓解手段有两个,建议都要: 1. work graph 里的 `planner-validator` 节点承担一项明确职责——审"这套验收标准是否可度量、是否覆盖原始需求、是否存在平凡通过的漏洞",而不只是审 PRD/SDD 本身。 2. 保留人工 sign-off(DevLoop L3 的做法)作为最终关卡,至少在 v1 阶段不要全自动闭环。 ### 7.4 并行与现有不变量冲突 `CONVENTIONS.md` §12 第一条「任意 (pid, agent) 同时只允许 1 个 status=running」+ SessionPool 的 key 复用,两者都挡着 fan-out。必须先设计**同一 system agent 的多实例并发隔离**(给 SessionPool key 加 scope、给不变量加 instance 维度),否则"并行多个 code subagent"跑不起来。 ### 7.5 三层图的暂停/停止如何传播 上一轮 P3/P4 §八.4 已经把"子图不继承父图暂停状态"列为刻意简化。现在变成**三层**(任务级 → org node 级 → 并行子图级),手动模式下用户点"暂停"到底暂停哪一层、正在跑的下层要不要停,会成为真实的困惑点。建议:暂停/停止**向下级联**(符合直觉),"下一步"只作用于当前查看的层级。 ### 7.6 成本量级 按 `plan-cost-concurrency.md` 的实测估算,DevLoop 一个中等项目(8 unit、2 个 PRD rev、2 轮 L2)≈ 39 次 agent 调用、410K token、约 $4.8、墙钟 20 分钟。 你的流程在此之上还要叠加:顶层任务图规划、每个 org node 各自的 work graph 规划、L4 的 agent 迭代 + 重新 benchmark。**粗估一个中等任务 60-100 次 agent 调用、$10-20、1-2 小时**。这个量级下: - 「自动模式一键跑到底」需要在启动前把预估成本告诉用户 - §7.1 的任务级预算不是可选项 ### 7.7 其他 - **失败的部分成功**:fan-out 5 个并行节点,3 成功 2 失败,fan-in 节点要不要跑?(建议:不跑,等全绿;但要有 UI 明确显示"卡在等 2 个失败节点") - **task status 无状态机**:`system/tasklog/{taskId}.json` 的 status 是自由赋值,没有转换校验。 - **`knowledge/` 目录没有读取方**:L4 里"迭代 data"这一维,目录存在、创建时能写一次,但全仓库没有任何代码读它。要么先补读取方,要么 L4 暂时不含这一维。 - **per-agent LLM 选择不存在**:`runtime-resolver.js` 只推断 protocol/transport/launcher,**没有 model 字段**,`config.json` 里也 grep 不到 `model` 键。虽然 `agents-overview.md` 的规格表里给每个 agent 指定了模型(Architect/BugTriager 用 Opus、其余 Sonnet),但**这只存在于文档,代码里没有实现**。L4 想"换 LLM"需要从 client 定义、runtime-resolver、协议层一路新增。 --- ## 八、L4 · System Agent 自我迭代(v0.2 已定案:拆成两条独立通道) 把第七步正式命名为 **L4**。**关键定案:L4 按"改的是 company 分区还是 general 本体"拆成两条完全不同的通道**,它们的触发方式、时机、驱动者、风险等级都不一样: | | **L4-company** | **L4-general** | |---|---|---| | 改什么 | agent 的**公司/角色记忆分区**(`companies/{cid}/`) | agent 的**general 本体**(公共 `agent.md` / `memory.md` / skill) | | 触发 | 任务执行过程中,validator 判定能力缺陷时 | 定时(如每日)或人工手动触发 | | 驱动者 | 执行引擎,**自动** | **master agent 或人工** | | 输入 | 本次任务的失败上下文 | **当天所有公司**的执行成功/失败/经验汇总 | | 在任务循环内 | ✅ 在环内,会触发重跑 | ❌ 离线批处理,不阻塞任何任务 | | 爆炸半径 | 一家公司 | 全局(所以才需要人/master 把关) | 这个拆分**直接解决了 v0.1 §7.2 提出的跨公司污染风险**:在线自动迭代永远只碰 company 分区,general 本体的更新被移出任务循环、改由离线批处理 + 人工/master 驱动。v0.1 提的三个缓解方案(fork 副本 / 只改私有 / 人工确认)不再需要——这个分层本身就是更彻底的答案。 ### 8.1 L4-general 的"agent dream"流程 离线自我更新的形态:**根据当天所有 company 的执行记录(成功、失败、经验),更新 general 本体**。类比睡眠期的记忆固化。 🔴 **现状**:这个流程不存在,但**零件基本齐了**——`memory-service.js`(1059 行)已有 `autoReflect()`(自动反思)、`saveCerebellumPlan()` / `retrieveRelevantPlans()`(小脑:固化的成功执行方案 + 按关键词召回)、`loadHippocampusIndex()` / `syncHippocampusMd()`(海马体索引 + 人类可读版同步)、`updateMemoryMdSections()`。缺的是**跨公司的批量汇总层**:现有全部接口都是 `agentId` 单点的,没有"把这个 agent 在 10 家公司的当日记录聚合起来蒸馏一次"这一步。 建议实现形态:一个定时任务(复用现有 `cron.json` 机制)或手动端点,对每个 public system agent:收集当日跨公司执行记录 → 调 agent 自身或专职 evolver 做蒸馏 → 产出对 general 本体的 diff → **走 27 号文档 §3.2 已定的 git 版本化 + 自省校验**(坏的迭代可 revert)→ 可选的人工确认后生效。 ### 8.2 四个可迭代维度的现状 | 维度 | 现状 | L4-company(在线) | L4-general(离线 dream) | |---|---|---|---| | **memory** | ✅ `memory-service.js` 最成熟,全套读写 API | ✅ 主要手段 | ✅ 主要手段 | | **skill** | ⚠️ 有运行时注入先例(`company.js:941-971` 招聘后 `skillDb.searchSkills` + `copyDir`),但是路由内联的,没封装成服务 | ✅ 纳入,需先封装 | ✅ 纳入 | | **data** (`knowledge/`) | ❌ 目录存在、创建时写一次,但**全仓库没有任何代码读它** | ❌ 先补读取方 | ❌ 先补读取方 | | **LLM** | ❌ 完全不存在 per-agent 模型选择(`runtime-resolver.js` 只推断 protocol/transport/launcher,无 model 字段) | ❌ 改动链路太长 | ❌ 同左 | --- ## 八bis、元 Agent 继承(v0.2 新增) **所有 org graph / work graph 的 node agent,都由一个元 agent 架构继承生成,统一是「全局通用本体 + 公司/角色记忆分区」的结构。** 这条定案取代了 v0.1 §四 里"三个验收 agent 要不要按父节点特化"这个问题——答案是**不特化**:不存在 `goal-benchmark` / `test-planner-benchmark` 各自独立的 agent,只有通用的 benchmark 设计能力,靠记忆分区区分它在不同 org node / 不同公司下的经验积累。agent 池不随 org node 数量膨胀,也与 [27-P1](./27-p1-virtual-reference.md) 虚拟引用寻址的初衷一致(同一份本体,多处引用,各自私有语境)。 ✅ **元 agent 在仓库里已经存在**:`system/templates/base/`("标准基座员工 Base Agent")。它已经强制了一套四段式生命周期: ``` RESEARCH → PLAN → EXECUTE → VERIFY ``` 每阶段之间通过 `node bin/lemon.js task transition --agentId --phase --artifact ` 切换,**切换时清空上下文并换装对应的元技能**(`meta-research` / `meta-plan` / `meta-execute` / `meta-verify`);VERIFY 阶段失败则把原因写入 `_lessons.md` 并打回上一阶段。 💡 **这本身就是一个最小 work graph**:四个节点、线性前进、末端带失败回退边。也就是说"每个 node agent 内部也是一张图"这件事已经有雏形。设计 Work Graph 引擎时应当与它对齐(要么把 base agent 的四段式改写成引擎上的一张标准图模板,要么至少保证两者的阶段语义不冲突),否则会出现"引擎层的 work graph"和"agent 内部的四段式"两套并行的状态机。 --- ## 九、对现有文档的修订要求 调研中发现仓库已推进,**我先前两份文档里有三条陈述已经过期或与已落地代码冲突**,需要修正: | # | 文档 | 错误陈述 | 事实 | |---|---|---|---| | 1 | [27-P2](./27-p2-org-graph.md) §九、[27-P3/P4](./27-p3-p4-work-graph-console.md) §九 | "P1 目前仍是设计稿,未实现,`graph-service.js` 尚不存在" | **P1 已实现并提交**(commit `226489d`),`server/services/graph-service.js` 已存在(104 行),配套测试 `graph-service.test.js` / `agent-manager-p1.test.js` 均在 | | 2 | [27-P3/P4](./27-p3-p4-work-graph-console.md) §三.1 | "`runProject` 目前直接 501" | **已完整实现**(`loop-controller.js:576`),含 Kahn 分波、L2 闸门、Triager 四分支、预算熔断 | | 3 | [27-P2](./27-p2-org-graph.md) §4.1 | 提议建部分唯一索引 `idx_org_graph_nodes_company_role_active`(带 `WHERE status='active'`) | **`graph-service.js:44` 已经建了全量唯一索引 `idx_org_graph_nodes_company_role`**(无 WHERE)。P2 若要加 `status` 列并改成部分索引,必须先 DROP 已落地的那个索引 | | 4 | [27-P3/P4](./27-p3-p4-work-graph-console.md) §四.B.2、§六 T3 | "手写分层布局算法,不引入图形库" 作为新工作量 | `web/src/components/devloop/UnitsDAG.vue` **已实现** SVG + Kahn 分波布局,应改为"扩展既有组件" | 此外建议: - **27 号总文档 §六**:把 P6「DevLoop 收编(可选)」的定位从"可选的后续整合"改为"DevLoop 是本架构的参考实现,通用引擎应从它抽象而来"(结论 2)。 - **27-P2**:**核心建模需推翻重写**——`org_graph_edges` 从 `reports_to`/`collaborates_with` 改为与 `work_graph_edges` 同构的 `condition IN ('success','fail')` + `edge_kind`;汇报关系降级为节点可空属性;§4.3 的 `reportsTo` 语义改为"接在谁后面";§4.7 前端改为复用 Work Graph 画布组件(详见该文档 v0.4 修正块)。 - **27-P3/P4**:补 `node_kind='org_node'`(§五)、fan-out 并行 + 实例隔离(§7.4)、任务级总预算(§7.1)、三层暂停级联(§7.5);把 §八.3 的开放问题用 `loops-l3.md` 的 unchanged 算法关掉。 --- ## 十、可行性判断与落地建议 ### 这个流程能这样实现吗? **能,但不是从零实现——大部分是"把 DevLoop 已经跑通的东西泛化",而不是新造。** 分三类: - **约 50% 是"改造既有实现"**:runProject 的分波执行、Triager 四分支、预算熔断、SSE、DAG 前端组件、contract hash 校验、memory-service——都已经在跑,问题是它们绑死在"写代码"这一个场景上。 - **约 30% 是"补通用层"**:任务入口、org 级任务图(§五)、planning agent、并行实例隔离。 - **约 20% 是真空**:面向 task/agent 的真实 benchmark(现有的是 skill 专用假打分)、test data 全套、qa-judge 的程序化入口、L4。 ### 最大的结构性风险 **整条流程的终止条件(验收)是实现程度最低的一环。** L1/L2/L3 的循环机制都相当成熟,但"跑完了到底算不算通过"这件事,现在没有任何真实执行的评测基础设施支撑(benchmark 是假的、test data 不存在、qa-judge 没有调用入口)。**先建验收,再建循环**——否则会得到一个跑得很顺畅但永远不知道该不该停的系统。 ### 建议的落地顺序 1. **验收先行**:给 qa-judge 补程序化调用入口 + 输出 schema 校验 + 判决持久化;定义 task 级 benchmark/testdata 的存储与执行方式(可以直接抄 DevLoop 的 `integration/spec.json` + 真实进程执行)。 2. **任务入口**:补"用户 → 公司"的任务下达端点,复用既有 `task/dispatch` + `task/report` 回调链路。 3. **org graph 改为执行流图**(§五定案):边模型改造 + 复用 work graph 引擎跑通两层。此时可以端到端跑通一条**串行、无并行、无 L4** 的最小闭环(参照 [27-EXAMPLE](./27-example-dev-company-walkthrough.md) 的场景)。 4. **并行**:先解决实例隔离(SessionPool scope + 不变量),再把 `_groupUnitsByWave` 的波内串行改并行。 5. **L4**:最后做,且第一版只做 memory + skill 两个维度、fork 成 company-scoped 副本、需人工批准。 前三步做完就能验证你描述的主干流程;4、5 是增强。 > **v0.2 调整**:第 1 步"验收先行"的含义因 §十一 的更正而改变——**不是**"建 benchmark 基础设施"(那是误解),而是"定义验收契约格式 + 建执行器"。三个产出 agent 本身不需要新基础设施,它们就是普通 system agent。 --- ## 十一、验收产出节点设计(v0.2 新增) ### 11.1 三个 agent 节点,动态选择 benchmark / test data / test script **不是系统基础设施,是 work graph 里的三个可选 agent 节点**: | 节点 | 产出 | 适用场景 | |---|---|---| | `{org-node}-benchmark` | 打分式验收标准:维度 + 权重 + 及格线 | 质量是**分数而非布尔**的场景——生成内容质量、性能指标、可读性 | | `{org-node}-test-data` | 输入样本集:正常用例 + 边界 + 异常 | 需要**喂数据**才能验证的场景——解析器、转换器、有复杂输入空间的逻辑 | | `{org-node}-test-script` | 可执行断言脚本 | 行为可以**用代码判定真假**的场景——API 契约、函数返回值、状态变更 | **由 planning agent 在规划 work graph 时动态决定加哪几个**——可以三个都加、只加一个、或某种组合。这使得"要不要加验收节点、加哪个"成为 work graph 规划的一等决策,而不是固定模板。 例:`org-planner` 这个 org node 的 work graph 可能长成 ``` brd-planning → prd-planning → sdd-planning ─┬→ goal-benchmark ──┐ ├→ goal-test-data ──┼→ planner-validator → loop-validator └→ goal-test-script ┘ ``` 三个验收节点之间**无依赖,可并行**(fan-out),汇合到 `planner-validator`(fan-in)。这正好是 §7.4 fan-out 能力的第一个真实用例。 ### 11.2 三者必须产出统一的「验收契约」 三个节点的产出形态不同(分数表 / 数据集 / 脚本),但下游 validator 必须能统一消费。**否则每加一种验收节点就要改一次 validator。** 建议:三者都写入同一个 `acceptance.json`(各占一个 section),格式定位参照 DevLoop 已有的 `integration/spec.json`(`sdd-model.md` M-6,含 `cases[]` / `steps[]` / `expect{status,json}` / `involves[]`,并支持 `{{stepN.field}}` 占位符引用前序步骤结果): ```jsonc { "version": "1", "goal_id": "GOAL-xxx", // 这份验收标准属于哪个 goal(一次人类需求) "benchmark": { "dimensions": [{"name":"...","weight":0.4,"pass_threshold":80}] } | null, "test_data": { "cases": [{"id":"...","input":{},"expect":{}}] } | null, "test_script": { "runner": "vitest", "path": "tests/acceptance.spec.js" } | null } ``` 三个字段各自可为 `null`(对应"这次没加这个节点"),validator 只处理非 null 的部分。 ### 11.3 「谁生成、谁执行」逐层递归(v0.2 定案) **产出者与执行者分离,且这个模式在每一层图上都重复出现**: | 层级 | 谁生成验收标准 | 谁执行验收 | |---|---|---| | **Org Graph**(company 级 workflow) | `planner` org node | `validator` org node | | **Work Graph**(org node 级 workflow) | 图内的 `benchmark` / `test-data` / `test-script` 节点 | 图内的 `validator` 节点 | 也就是说,**每个 node agent 都有自己的 benchmark,由它自身所在 work graph 的 validator / test-script / benchmark 节点来运行**——验收不是只发生在最外层的一次总检,而是每一层图收尾时都跑自己那一层的验收。这与 §八bis 元 agent 四段式末尾固定有 VERIFY 阶段,是同一个模式在不同粒度上的体现。 **执行由 agent 节点承担,不由引擎硬编码**,保持"一切都是图上的节点"这个架构一致性;代价是每次验收要烧一次 agent 调用(计入 §7.1 的任务级总预算)。DevLoop 的现成先例是 **Integrator agent 起真实进程跑 e2e**(`agents-integrator.md`),产出 `result.json` 含 `ok` / `failures[]` / http-trace,validator 节点可直接复用这套做法跑 test script / test data。 🔴 **剩余缺口**:benchmark 这类主观打分的判定,`qa-judge` 的输出协议(`PASS` / `REWORK` / `RETRAIN_REQUIRED` + `capability_gaps[]`)本来就是为此设计的——其中 `RETRAIN_REQUIRED` 正好是 §八 **L4-company** 的触发信号——但它目前**没有程序化调用入口**(全仓库 grep,生产代码零引用),需要补入口 + 输出 schema 校验 + 判决持久化。 ### 11.4 命名冲突提醒 仓库里 `benchmark` 一词**已经被占用**:`benchmark-runner.js` / `data/benchmark.sqlite` / `_registry.json` 的 `benchmarkScore` / Arena ELO 排行榜,指的都是**给 Skill 打分**的那套体系(表结构以 `skill_name` 为主键,没有 agent_id/task_id 任何一列)。本文档 §十一 说的是**任务级验收标准**,两者同名但完全无关。建议在实现时给新概念换个不冲突的名字(如 `acceptance-benchmark` 或 `goal-benchmark`),否则日后 grep 和排查会很痛苦。