27-E2E · 端到端任务执行流程 — 从建公司到验收收敛
所属: 27 Graph Agent 架构 的跨阶段总览文档,串起 P2(Org Graph)、P3/P4(Work Graph 执行)、P5(自我进化)。 版本: v0.1 日期: 2026-08-15 前置: 27-P2 Org Graph 落地、27-P3/P4 Work Graph 执行控制台、以及本文档最重要的参考源
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-EXAMPLE 参考场景走查 —— 本文档讲机制,那份文档把机制在一家具体公司上跑一遍数。两份对照着读。
一、这份文档要回答什么
本文档把口述的七阶段端到端流程结构化,然后回答三个问题:
- 这个流程和已经写好的 P2 / P3-P4 设计有什么差异?
- 哪些地方没有考虑到?
- 这个流程是否是这样实现的?
二、三条核心结论(先给答案)
结论 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.mdP-2):contract_mismatch/impl_bug/spec_ambiguous/infra_flake,每类决定「改不改设计文档、重置哪些节点、烧不烧预算」。 - 分级预算与熔断(
sdd-process.mdP-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.mdV-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 文档里写的 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 §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},持久化为全局平铺 JSONsystem/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 §六: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,但 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(...) }。 - ⚠️ 改成并行会立刻撞上两处障碍:
_spec/CONVENTIONS.md§12 第一条不变量:「任意 (pid, agent) 同时只允许 1 个 status=running」——如果并行跑 3 个 coder subagent,它们是同一个 system agent 的三次调用,直接违反这条。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.mdP-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 现在的 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」这个直觉落地,同时保留任务级偏离的自由 |
定案的落地方式
org_graph_edges改为执行流边,与work_graph_edges同构:
-- 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),不再是图的主干语义。
- 两层图的递归关系(复用 27-P3/P4 已有的
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 已设计)
- 执行引擎、schema 形态、控制台 UI 在两层之间完全复用——这是这个定位最大的收益:不需要为 org 级单独造一套控制逻辑,
启动/下一步/暂停/停止/重试在每层语义一致,控制台天然是逐层下钻。
六、可以直接复用的既有机制(两份设计文档都没引用到)
以下全部来自 _spec/ 或已落地代码,建议在 P3/P4 实现前先读一遍,避免重复发明:
contract_hash三方一致性校验(sdd-model.mdM-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相等。这解决的正是"上游产物改了,下游还停在旧契约上"这个跨节点一致性问题。- L2 闸门的 hash 校验(
loops-l2.md):闸门条件不是"所有节点都跑过一次",而是"所有节点 status=passed 且contract_hash与当前 SDD 一致",避免设计文档改过之后某个旧节点还停在 passed。 - 增量重跑算法(
loops-l3.md):added / changed / removed / unchanged 四分类,unchanged(id 在且 hash 不变)保持 passed 无须重跑——"这是增量化的关键"。这直接回答了我在 P3/P4 §八.3 列为开放问题的「重试要不要级联下游」。 - 跨节点读取隔离(
CONVENTIONS.md§12):跨 unit 只允许读../{otherUnit}/contract.json,禁止读code/。下游只能看到上游的契约,看不到实现。 - BugTriager 四分类 + 差异化预算消耗(§三 阶段 6 的表)。
- 分级预算与熔断(
sdd-process.mdP-7)+ 成本/并发的数字版(plan-cost-concurrency.md):三层并发上限(L1 ≤5 并行、L2 串行 1 个、系统 ≤20 ACP session、同公司 ≤3 项目、bash 子进程 ≤50)。 - 前端组件:
UnitsDAG.vue已实现 SVG + Kahn 分波布局 + 节点状态着色 + 点击下钻;LiveAgentStream.vue已实现带 Last-Event-ID 重连的 SSE 消费。我在 P3/P4 §四.B.2 写"手写分层布局算法"时不知道这个组件已经存在,实际工作量应该是扩展它而不是从零写。 - 任务回调链路:
POST /api/agent/task/report已实现「更新 goal 节点 → 自动推进 Pipeline → 回调唤醒上级 agent」。 orchestrator.executeWithDependencies():现成的 fan-out/fan-in(Promise.allSettled+ 依赖分组 + 单点失败降级)。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,产出者和被验收者分离,不存在"自己给自己出考题"的激励问题。
⚠️ 但仍未解决"标准写错了"这一层。缓解手段有两个,建议都要:
- work graph 里的
planner-validator节点承担一项明确职责——审"这套验收标准是否可度量、是否覆盖原始需求、是否存在平凡通过的漏洞",而不只是审 PRD/SDD 本身。 - 保留人工 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 虚拟引用寻址的初衷一致(同一份本体,多处引用,各自私有语境)。
✅ 元 agent 在仓库里已经存在:system/templates/base/("标准基座员工 Base Agent")。它已经强制了一套四段式生命周期:
RESEARCH → PLAN → EXECUTE → VERIFY
每阶段之间通过 node bin/lemon.js task transition --agentId <id> --phase <next> --artifact <path> 切换,切换时清空上下文并换装对应的元技能(meta-research / meta-plan / meta-execute / meta-verify);VERIFY 阶段失败则把原因写入 _lessons.md 并打回上一阶段。
💡 这本身就是一个最小 work graph:四个节点、线性前进、末端带失败回退边。也就是说"每个 node agent 内部也是一张图"这件事已经有雏形。设计 Work Graph 引擎时应当与它对齐(要么把 base agent 的四段式改写成引擎上的一张标准图模板,要么至少保证两者的阶段语义不冲突),否则会出现"引擎层的 work graph"和"agent 内部的四段式"两套并行的状态机。
九、对现有文档的修订要求 —— ✅ 四条全部已落实(2026-08-16 复核)
本节原是「待办清单」,现已全部完成,改为已完成记录保留,供追溯。下表的「修订结果」列是逐条回查文档与代码后的实测结论,不是声称。
| # | 文档 | 原错误陈述 | 事实 | 修订结果 |
|---|---|---|---|---|
| 1 | 27-P2 §九、27-P3/P4 §九 | "P1 目前仍是设计稿,未实现,graph-service.js 尚不存在" |
P1 已实现并提交(commit 226489d),server/services/graph-service.js 已存在,配套测试 graph-service.test.js / agent-manager-p1.test.js 均在 |
✅ 已改。27-P2 文件头「前置」已写明「P1 虚拟引用寻址已实现(commit 226489d)」;27-P3/P4 §九「与 P1」条写明「无直接依赖,已实现(commit 226489d)」 |
| 2 | 27-P3/P4 §三.1 | "runProject 目前直接 501" |
已完整实现(loop-controller.js:576),含 Kahn 分波、L2 闸门、Triager 四分支、预算熔断 |
✅ 已改。27-P3/P4 §三.1 现为「runProject()(行 576,已完整实现…)」,并追加了「波内实际是串行」的补充观察 |
| 3 | 27-P2 §4.1 | 提议建部分唯一索引 idx_org_graph_nodes_company_role_active(带 WHERE status='active'),但没说要先 DROP 旧索引 |
graph-service.js 已经建了全量唯一索引 idx_org_graph_nodes_company_role(无 WHERE),必须先 DROP |
✅ 已改且已落地代码。27-P2 §4.1 的 SQL 现以 DROP INDEX IF EXISTS idx_org_graph_nodes_company_role; 开头;graph-db.js:59-60 已实现这条 DROP + 重建 |
| 4 | 27-P3/P4 §四.B.2、§五 T3 | 把"手写分层布局算法,不引入图形库"当作新工作量 | web/src/components/devloop/UnitsDAG.vue 已实现 SVG + Kahn 分波布局 |
✅ 已改。27-P3/P4 §三.5 新增「前端 DAG 已实现,扩展而非重写」一节;§四.B.2 与 §五 T3 均改为「扩展 UnitsDAG.vue」,并把新增工作量收窄到「subgraph 角标 + backward 曲线路由 + 循环徽标」三块 |
此外建议(复核结论)
| 建议 | 状态 |
|---|---|
| 27 号总文档 §六:把 P6「DevLoop 收编(可选)」的定位改为"DevLoop 是本架构的参考实现,通用引擎应从它抽象而来"(结论 2) | ✅ 已改。27 总纲 §六 P6 行现为「 |
27-P2 核心建模推翻重写:org_graph_edges 从 reports_to/collaborates_with 改为与 work_graph_edges 同构的 condition IN ('success','fail') + edge_kind;汇报关系降级为节点可空属性 |
✅ 已改且已落地代码。server/services/org-graph-service.js 的 validateGraph 已按 condition/edgeKind 建模,四项结构校验(acyclic / single-entry / reachable / backward-labeled)已实现 |
| 27-P3/P4:fan-out 并行 + 实例隔离(§7.4) | ✅ 已处理——但结论是明确排除,不是实现:27-P3/P4 §一非目标第 1 条把它列为独立工作量,并给出 v1 替代约束「一家公司同时只有一个 active root run」 |
| 27-P3/P4:任务级总预算(§7.1) | ✅ 已改。27-P3/P4 §四.A.3「任务级总预算:挂 root run」,budget_json 只在 root run 非空,所有子 run 按 root_run_id 扣同一个池 |
| 27-P3/P4:三层暂停级联(§7.5) | ✅ 已改。27-P3/P4 §四.C「三层级联」定案:暂停/停止向下级联,「下一步」只作用于当前层级 |
27-P3/P4:把 §八.3 的开放问题用 loops-l3.md 的 unchanged 算法关掉 |
✅ 已关。27-P3/P4 §〇 与 §四.C 末段记录了这个 open question 已关闭,判据是 contract_hash 的 added/changed/removed/unchanged 四分类 |
⛔ 一条已作废的建议
| 原建议 | 为什么作废 | 被什么取代 |
|---|---|---|
27-P3/P4:补 node_kind='org_node' —— 即在节点表上开一个专门表示「这是个 org 节点」的枚举值 |
它的前提是「org graph 和 work graph 是两种不同的东西,引擎要靠节点上的一个标记去分辨」。27-REQ R-15.4 推翻了这个前提:两层图是同一种东西在不同层级的递归,引擎泛化后不为它们各写一套,也就不需要在节点粒度上区分层级 | graph_runs.graph_kind IN ('org','work')(27-P3/P4 §四.A.2)。层级信息挂在运行时的 run 上,不挂在定义层的节点上;graph_run_nodes.def_node_id 按所属 run 的 graph_kind 解释到 org_graph_nodes 还是 work_graph_nodes。节点粒度上真正存在的枚举是另一个东西—— node_kind IN ('agent_call','subgraph')(§四.D.0),它区分的是执行语义(调一次 agent / 起一张子图并等它收敛),不是图的层级。org graph 的节点恰好全都是 subgraph,但这是推论,不是定义 |
⚠️ 不要照这条作废建议去加字段。设计里不存在
node_kind='org_node'这个取值,加了会与graph_kind形成两套互相矛盾的层级标记,且node_kind的 CHECK 约束(IN ('agent_call','subgraph'))会直接拒绝它。
十、可行性判断与落地建议
这个流程能这样实现吗?
能,但不是从零实现——大部分是"把 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 没有调用入口)。先建验收,再建循环——否则会得到一个跑得很顺畅但永远不知道该不该停的系统。
建议的落地顺序
- 验收先行:给 qa-judge 补程序化调用入口 + 输出 schema 校验 + 判决持久化;定义 task 级 benchmark/testdata 的存储与执行方式(可以直接抄 DevLoop 的
integration/spec.json+ 真实进程执行)。 - 任务入口:补"用户 → 公司"的任务下达端点,复用既有
task/dispatch+task/report回调链路。 - org graph 改为执行流图(§五定案):边模型改造 + 复用 work graph 引擎跑通两层。此时可以端到端跑通一条串行、无并行、无 L4 的最小闭环(参照 27-EXAMPLE 的场景)。
- 并行:先解决实例隔离(SessionPool scope + 不变量),再把
_groupUnitsByWave的波内串行改并行。 - 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}} 占位符引用前序步骤结果):
{
"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 和排查会很痛苦。