27-EXAMPLE · 参考场景走查 — 一家开发型公司从建立到交付一个任务
所属: 27 Graph Agent 架构 的参考场景文档。 版本: v0.1 日期: 2026-08-15 定位: 这份文档不定义任何新机制,它把 27-E2E 端到端任务执行流程 描述的架构跑一遍具体的数。它的用途有三个:
- 实现时的靶子——每个阶段的输入输出都写成了具体的 JSON / 图形,可以直接拿来构造测试数据。
- 验收场景——P2/P3/P4 全部落地后,跑通这一个场景就等于端到端验证。
- 沟通基准——讨论"这里应该怎么设计"时,有一个共同的具体例子可指。
⚠️ 本文档的「配图工厂」是为走查虚构的场景,不是用户提出的原始需求。原始需求原话见 27-REQ。
注意:文中所有数据是设计意图的示例,不是从运行中的系统里导出的真实记录。标 🔴 的地方是当前尚未实现、走查到此会断的环节。
场景设定
用户想做一个「给公众号文章自动生成配图」的小工具,于是建一家公司来做这件事。
阶段 1 · 建公司
用户动作:填两个字段提交。
// POST /api/company/create
{
"id": "auto-illust",
"name": "配图工厂",
"description": "做一个工具:输入公众号文章正文,自动理解段落语义并生成配图,输出图文混排的 HTML。需要能跑在本地,先做 CLI 版本。"
}
系统动作(27-P2 §4.10):
companyService.create()建目录 +company.json(agents: [])- 🔴 自动
hire(id, 'orggraph-planning', {}) - 🔴 fire-and-forget 触发它的首轮对话,把
description带进去
此刻 company.json.agents = ["orggraph-planning"],其余为空。API 立刻返回,组织结构在后台异步生成。
阶段 2 · orggraph-planning 生成 org graph
它读三样东西:
- 公司 description(上面那段)
system/org-graph-templates/*.json(候选骨架,27-P2 §4.8)node bin/lemon.js company templates(现实里能招到的角色,listTemplates()返回 id/name/type/description)
它的判断:description 里有"做一个工具""跑在本地""CLI 版本"→ 匹配 dev.json。
它产出的 org graph——注意这是一张company 级 workflow,不是组织架构图(27-E2E §五定案:Org Graph 是 company 级生成的 workflow,Work Graph 是 org node 级生成的 workflow,两者同构):
// org_graph_nodes + org_graph_edges 的等价视图
{
"nodes": ["code-planner", "code-coder", "code-validator"],
"edges": [
{ "from": "code-planner", "to": "code-coder", "condition": "success", "edge_kind": "forward" },
{ "from": "code-coder", "to": "code-validator", "condition": "success", "edge_kind": "forward" },
{ "from": "code-validator", "to": "code-coder", "condition": "fail", "edge_kind": "backward" }
]
}
边是 success / fail 执行流边,与 work graph 的边完全同构——同一套 schema、同一个执行引擎、同一个控制台 UI 在两层复用。
ceo / hr 这类不参与任务执行的角色仍然可以被招聘进公司(存在于 company.json.agents[]),但不出现在 org graph 这张 workflow 里——org graph 只画"任务怎么流过这家公司"。
它提交图 + 执行招聘(两步,27-P2 §4.1 第 6-7 步):
# 1. 整体提交图定义,过四项校验(无环 / 单一入口 / 可达性 / 回退边标注)后事务性落库
curl -X POST http://localhost:3010/api/company/auto-illust/org-graph -d @/tmp/orggraph.json
# 2. 按拓扑序逐个招聘(注意:P2 v0.4 起 hire 不再需要 --reportsTo,
# 图的结构已在第 1 步整体写入,招聘只负责建 agent 目录)
node bin/lemon.js company hire --id auto-illust --role code-planner
node bin/lemon.js company hire --id auto-illust --role code-coder
node bin/lemon.js company hire --id auto-illust --role code-validator
三个角色在 system/templates/ 里都没有同名模板 → hire() 返回 needs_training → 触发既有的 agent-creator + innovator 培养流水线(company.js:917-940,已实现)。
招完后 orggraph-planning 关掉自己的心跳转入休眠(一次性任务)。后续增量招聘归 HR 管。
阶段 3 · 用户下达一个具体任务
// 🔴 POST /api/company/auto-illust/tasks ← 这个端点目前不存在
{
"task": "先做第一个版本:读一个 markdown 文件,按 H2 分段,每段调用图像生成 API 产出一张配图,最后输出内嵌 base64 图片的 HTML。图像 API 先用 mock,接口留出来。"
}
🔴 缺口:现有的 POST /api/agent/task/dispatch(agent-chat.js:1470)只支持 agent → agent(from/to 都必须是已存在的 agent 目录),没有"用户 → 公司"的入口。见 27-E2E §三 阶段 3。
阶段 4 · 任务进入 org graph 开始执行
任务不需要另建一张顶层图——阶段 2 生成的 org graph 本身就是这家公司的 workflow,任务直接在它上面跑:
[code-planner] --success--> [code-coder] --success--> [code-validator]
↑ │
└────fail(backward)──┘
从入度为 0 的节点(code-planner)开始执行。execution_mode 由用户选:manual(每步点"下一步")或 auto(一路跑到底)。假设选 auto。
阶段 5 · code-planner 的 Work Graph(Level 1)
code-planner 这个 org node 被激活,它先调 workgraph-planning agent 规划自己这一层的图。
规划结果——注意三个验收节点是动态选进来的(27-E2E §十一):
brd-planning → prd-planning → sdd-planning ─┬→ task-test-data ───┐
└→ task-test-script ─┴→ code-planner-validator → loop-validator
planning agent 的选择理由(这是它要在规划时说清楚的):
| 验收节点 | 选/不选 | 理由 |
|---|---|---|
task-test-script |
✅ 选 | "按 H2 分段""输出 HTML"这些行为可以用代码断言真假 |
task-test-data |
✅ 选 | markdown 输入空间复杂,需要正常/边界/异常样本(空文件、没有 H2、H2 嵌套) |
task-benchmark |
❌ 不选 | 这一版图像 API 是 mock,没有"配图质量好不好"这种打分维度要评。如果将来接真实图像 API,就要把这个节点加回来 |
这正是"动态选择加哪几个"的实际含义——不是三个固定都跑。
产出的验收契约(acceptance.json,27-E2E §11.2):
{
"version": "1",
"okr_node_id": "O-001.1.1",
"task_id": "T-xxx",
"benchmark": null, // 本次没选这个节点
"test_data": {
"cases": [
{ "id": "normal", "input": {"md": "# T\n## A\n正文\n## B\n正文"}, "expect": {"sections": 2} },
{ "id": "no-h2", "input": {"md": "# T\n只有正文"}, "expect": {"sections": 0} },
{ "id": "empty", "input": {"md": ""}, "expect": {"error": "empty_input"} }
]
},
"test_script": { "runner": "vitest", "path": "tests/acceptance.spec.js" }
}
两个并行验收节点是 fan-out 的第一个真实用例——它们之间无依赖,可以同时跑,汇合到 code-planner-validator。🔴 这会撞上 CONVENTIONS.md §12「任意 (pid, agent) 同时只允许 1 个 running」和 SessionPool 的 key 复用(见 27-E2E §7.4)。
code-planner-validator 的职责不只是审 SDD,还要审验收标准本身(§7.3):这套 test_data 覆盖了原始需求吗?有没有平凡通过的漏洞?
阶段 6 · code-coder 的 Work Graph(Level 1)+ 并行子图(Level 2)
code-coder org node 激活,同样先调 planning agent。它读到上一阶段的 SDD,把工作拆成三个可并行的 unit:
┌→ [md-parser] → [unittest] ─┐
[start] ┼→ [img-client] → [unittest] ─┼→ [integrate] → [integration-test] → [loop-validator]
└→ [html-render]→ [unittest] ─┘
- fan-out:三个 unit 无依赖,并行(DevLoop 的
_groupUnitsByWave()Kahn 分波已实现,🔴 但波内目前是串行的,loop-controller.js:609注释// 串行跑) - fan-in:
integrate节点等三条支线全绿才能进入ready(多入边 = 汇合点,全部满足才推进,27-P3/P4 §D.1) - 每个
unittest失败 → 打回对应的 unit 重写 = L1 循环,retry_budget=5
假设 integration-test 失败了:html-render 拿到的分段结构和 md-parser 产出的不一致。
这时 loop-validator 要判断"重新 planning 还是跳回某个节点"——这正是 DevLoop BugTriager 四分类已经解决的问题(sdd-process.md P-2):
| 归因 | 本例是否命中 | 动作 | 烧不烧预算 |
|---|---|---|---|
contract_mismatch |
✅ 命中 | 两个 unit 对"分段结构"的契约理解不一致 → 改 SDD 统一契约 → reset 两个 unit | ✅ 烧 l2_budget |
impl_bug |
❌ | — | 不烧 |
spec_ambiguous |
❌ | — | 升 L3 找人 |
infra_flake |
❌ | — | 不烧 |
→ 改 SDD → reset md-parser + html-render → 回到 L1 重跑这两条支线 → 再次 integrate → 再次 integration-test。
l2_budget 默认 3 轮,超出发 project.l2_exhausted 挂起等人。
阶段 7 · code-validator org node + 三级恢复
code-validator 激活,消费阶段 5 产出的 acceptance.json:
| 验收项 | 执行方式 | 状态 |
|---|---|---|
test_script |
引擎起进程跑 vitest,读结果 | 🔴 执行器待建(可搬 DevLoop Integrator) |
test_data |
喂样本比对实际输出 | 🔴 同上 |
benchmark |
本次为 null,跳过 | — |
假设 no-h2 这个 case 一直过不了,而且已经在 L1 打回 code-coder 重写 3 次、L2 重新 planning 1 次,仍然失败。
此时进入你描述的第三级 —— L4 · 迭代 system agent(27-E2E §八):
- 判定这是能力缺陷而非粗心错误(
qa-judge的三分类:粗心错误 / 设计缺陷 / 能力缺陷 →RETRAIN_REQUIRED+capability_gaps[]。🔴 协议已定义在qa-judge/agent.md:223-333,但没有程序化调用入口) - 触发 L4-company(27-E2E §八):只迭代
code-coder在 auto-illust 这家公司的记忆分区(companies/auto-illust/),自动进行、无需人工确认——因为爆炸半径就限制在这一家公司内,改坏了也波及不到别人。 - 回到 L1 重跑 → 再到 code-validator 验证
注意这里不会碰 coder 的 general 本体。如果这次失败暴露的是 code-coder 通用能力上的短板(不只是本公司场景特有的),那属于 L4-general:它不在任务循环里发生,而是等当日的 agent dream 流程——由 master agent 或人工触发,汇总当天所有公司的成功/失败经验,统一蒸馏一次 general 本体,走 git 版本化以便回滚。这个拆分保证了"为修一个任务而改坏十家公司共用 agent"这件事在架构上不可能发生。
⚠️ 这里就是 §7.1 说的熔断失效风险:L4 迭代完之后如果 L1/L2 的计数器重置,"迭代 agent → 重跑 → 再迭代"可以永远循环。所以必须有一个跨层级共享、只增不减的任务级总预算:
{ "total_agent_calls": 100, "total_tokens": 5000000, "wallclock_ms": 7200000, "l4_iterations": 2 }
扣完即挂起等人工,不管哪一层还想重试。
这个场景的成本量级
按 plan-cost-concurrency.md 的实测口径(DevLoop 中项目 8 unit / 2 PRD rev / 2 轮 L2 ≈ 39 次调用 / 410K token / $4.8 / 墙钟 20 分钟)外推本场景:
| 阶段 | agent 调用次数(估) |
|---|---|
| orggraph-planning + 招 5 个角色(其中 2 个走培养流水线) | ~8 |
| Level 0 任务图规划 | 1 |
| code-planner:workgraph-planning 1 + brd/prd/sdd-planning 3 + 验收 2 + code-planner-validator 1 + loop-validator 1 | 8 |
| code-coder:workgraph-planning 1 + 3 unit ×(code+test) 6 + 1.5 次重试 ~4 + integrate 1 + int-test 1 + judge 1 | ~14 |
| L2 一轮修复(triage + 改 SDD + reset 后重跑 2 unit) | ~7 |
| code-validator + L4 一次迭代 | ~6 |
| 合计 | ~44 次 |
粗估 $8-15、墙钟 40-90 分钟(并行后)。这个量级下,"自动模式一键跑到底"必须在启动前把预估成本告诉用户。
走查暴露的 🔴 断点清单
按阻塞程度排序,这也是实现顺序的依据:
| # | 断点 | 出现阶段 | 对应设计 |
|---|---|---|---|
| 1 | qa-judge 没有程序化调用入口(判决无法驱动任何自动动作) |
5, 6, 7 | 27-E2E §11.3 |
| 2 | code-validator 节点的验收执行能力(跑 test_script / 喂 test_data)未实现 | 5, 7 | §11.3 |
| 3 | 「用户 → 公司」任务入口不存在 | 3 | §三 阶段 3 |
| 4 | P2 的 org graph 边模型需从 reports_to 改为 success/fail 执行流边 |
2, 4 | §五定案 + 27-P2 v0.4 修正 |
| 5 | fan-out 并行撞 CONVENTIONS §12 不变量 + SessionPool key 复用 | 5, 6 | §7.4 |
| 6 | 任务级总预算不存在 | 7 | §7.1 |
| 7 | L4-general 的 agent dream 流程不存在(跨公司批量蒸馏层缺失,单点接口已齐) | 7 之后(离线) | §8.1 |
| 8 | orggraph-planning / workgraph-planning agent 均未实现 | 2, 5, 6 | 27-P2 §4.9 |
第 4 项是架构前提,必须先改;改完之后做 1-3 项,这个场景就能在"串行、无 L4"的模式下端到端跑通一遍。