org-graph-unification-and-universal-self-planning-requirements.md 19 KB

统一 Org Graph 主流程 + 全体 Org Agent 自规划 Work Graph + 节点级验证回路 + 前端动态/历史图谱——需求文档(融合版)

日期: 2026-08-08 性质: 需求文档(BRD/PRD 层面),不含详细技术设计。融合并统领以下三份既有 docs/todo/ 文档的相关内容,讨论请统一在本文档继续,原文档保留作为触发场景/根因排查的原始记录,不删除:

  • docs/todo/org-graph-as-work-graph-unified-loop-requirements.md——本文档是它的展开与拍板;该文档提出的"跨 Org Agent 精确 loop_back"诉求是本文档 FR-4 + §4 关键架构决策的正文。
  • docs/todo/task-execution-resume-assumes-planner-artifacts-exist.md——它记录的 bug 与本文档 FR-1 改动的是同一段 run_or_resume_task_lifecycle() 分支逻辑(见 §2.1 调研结论),折入 Phase 1 一并修,不再单独排期。
  • docs/todo/validator-test-script-narrative-output-issue.md 第 8 节提到的"另一份尚未撰写、关于给 Coder agent 加入 test_script 模块的文档",即本文档 Phase 2(FR-2/FR-3)。

触发场景:用户 2026-08-08 提出四点架构改动设想(见 §1),与当天早些时候整理的 docs/todo/ 待办优先级建议(P0~P3)高度交叉,要求重新盘点、融合、给出 phase 规划。

状态: 草稿,讨论中——§4 关键架构决策已拍板(方案 A,合图,2026-08-08),其余 §7 列出的问题仍待确认。沿用 org-graph-as-work-graph-unified-loop-requirements.md 的"逐条开放问题讨论 → 用户拍板 → 展开设计文档"两段式流程,本文档本身不是最终设计。


1. 用户提出的四点改动

  1. Org Graph 固定流程从 Planner → Coder → Validator 改为 Planner → Validator → Coder → Validator——Coder 开始实现之前,Planner 自己的产出先过一道独立复核。
  2. 每个 Org Agent(不只 Planner)接到 goal 任务时,固定第一步是自己规划一张 Work Graph:每个节点声明用哪个 subagent + skill + tools + data 实现,以及判断节点成功/失败分别跳转到哪个节点(边的数据定义)。
  3. 前端要支持这张图的动态显示(执行中实时更新)和历史显示(多轮 loop 的回放),因为一定会有 loop(Validator 节点判断不通过时跳回前面某个节点)。
  4. 每个 Org Agent 都要有一套配套的 skill + subagent 定义——除了 Planner 现有的 brd/prd/sdd/benchmark/test_script 这类产出型 skill,还需要一个"验证型"skill:验证每个节点的结果,判断通过/不通过,不通过时精确跳回需要修复的那个节点,让该节点重新执行。

2. 现状盘点(2026-08-08 代码调研结论)

2.1 Org Graph 固定流程写死的位置

  • src/org_node_lifecycle.py:30-31:_PRE_STATE/_POST_STATE 只认 3 个 org_node(planner/coder/validator),线性对应 task.status 的 queued → planning_brd_prd_sdd → coding → validating。
  • task.status 是 CHECK 约束的固定枚举(src/schema.py:106-111:queued/planning_brd_prd_sdd/planning_failed/coding/coding_failed/validating/routed_fast_lane/routed_full_replan/blocked_pending_human/done),没有"Planner 产出待复核"这个中间态的容身之处。
  • 真正的调用顺序在 src/e2e_pipeline.py::run_task_lifecycle()(第 878 行起):trigger_org_node_full(planner) → plan_documents() → trigger_org_node_full(coder) → implement_code() → trigger_org_node_full(validator) → validate_implementation_with_own_graph()。src/task_execution.py::run_or_resume_task_lifecycle() 的 resume 分支复刻了同一条状态判断链。
  • 这正是 task-execution-resume-assumes-planner-artifacts-exist.md 记录的 bug 所在的同一段代码:planning_brd_prd_sdd 分支的注释写的是"Planner done, Coder not yet triggered",无条件假设 sdd/prd/benchmark artifact 已经存在——插入一个新的"复核中"状态,必然要重写这段分支逻辑,顺手把这个已知假设过时的 bug 一并修掉比分两次改更省事。

2.2 现有的两套独立、粒度不同的 loop 机制(沿用并确认 org-graph-as-work-graph-unified-loop-requirements.md §1 的判断)

  • 跨 Org Agent、粗粒度:src/org_loop_route.py:36-39,_NEW_STATUS/_NEW_ORG_NODE 只有两个目标——fast_lane→回 coder/coding,full_replan→回 planner/planning_brd_prd_sdd,_LOOP_LIMIT = 3。src/org_level_loop.py 的根因分类(coder/planning)也是 1:1 映射到这两个粗粒度目标,没有节点级精度。
  • 单个 Org Agent 内部、细粒度:work_graph_orchestrate.py 的 judgment/on_fail/loop_back 机制(docs/done/work-graph-self-planning-and-loop-back-design.md)能精确跳回同一张图内的某个节点,但只在同一次 plan_work_graph() 调用产出的同一张图内部生效——Planner 和 Coder 是两次独立调用,节点 id 空间互不相通,这正是 org-graph-as-work-graph-unified-loop-requirements.md §4 提出、至今没有方案的问题。

2.3 已经具备、可以直接复用的能力(不需要重新发明)

  • plan_work_graph(conn, org_node, ...)(work_graph_plan.py:336)本身已经是 org_node-generic 的:org_node == "planner" 走 _PROMPT_TEMPLATE(固定催化清单),其余任何 org_node 都会落到 _GENERIC_PROMPT_TEMPLATE(自由规划 {node_id, depends_on, task_prompt})——但目前只有 Planner 的调用点在用它。Coder 的 implement_code()(e2e_pipeline.py:617-650)和 Validator 的 validate_implementation_with_own_graph() 用的 _VALIDATOR_MANIFEST(e2e_pipeline.py:210-222)都是 Python 字面量硬编码的单/双节点图,没有 judgment/on_fail 字段,也从未调用过 plan_work_graph()。
  • judgment/on_fail/loop_back 执行引擎(work_graph_orchestrate.py)已验证是 org-agent-agnostic 的,不需要重做。
  • 逐节点落盘(docs/done/work-graph-partial-artifact-persistence-requirements.md,已实现)、Role Package 抽象(roles/<role_id>/role.json,已实现——新增 skill 只改 JSON,不碰 Python)、design-dynamic-work-graph skill(已存在,coder/validator 角色已声明,但目前只在人工发起的 work_graph_fork.py 时间旅行调试功能里用,没接生产路径)都是现成积木。
  • 前端 SVG DAG 渲染器(frontend/app.js::renderGraphVisualizerPanel/mountGraphVisualizerEdges)已经支持 on_failure 边线、自环(retry_self)计数徽标、经由既有 WS 事件流的准实时刷新——比它自己的 wireframe(docs/wireframes/v_graph_visualizer.html)还完整。
  • loop_back_events 数据已经从后端透出(task_query.py:185 _loop_back_events_for_run(),含 source_node_id/target_node_id/attempt_number/feedback[]/created_at),前端已经用它驱动边标签和自环徽标计数——只是 feedback[] 拉取了但没渲染。

2.4 明确的缺口

  • 没有任何"逐节点判断输出是否合格、并决定精确 loop_back 到哪个节点"的通用 skill——今天的 judgment.kind="llm" 是引擎特性(一次额外的 LLM 判断调用),不对应任何角色的具名 skill/prompt 资产;qa-task-validation 判断的是整体实现,不是单个节点。
  • Coder、Validator 两处调用点仍是硬编码 manifest,未接入自规划。
  • 插入新的"Planner 产出复核"阶段需要 task.status schema 迁移;跨图 loop_back 寻址此前完全没有方案,现已按 §4 拍板为合图(方案 A),但 §4.1 列出的三个具体迁移点还未设计。
  • 前端:同一个 work_graph_run 内多轮 loop_back 只能看最新一次结果,没有按 attempt_number 的历史回放;Org 四段(Planner/复核/Coder/终审)之间没有统一元图,只有各自独立页面 + 文字徽标链接(fork 谱系同理,见 docs/done/work-graph-time-travel-debugging-design.md)。

3. 目标(草案 FR,待讨论细化为正式验收标准)

# 需求描述 对应用户诉求
FR-1 Org Graph 固定流程改为 Planner → Validator(复核 Planner 产出) → Coder → Validator(终审实现):新增 task.status 枚举值(schema 迁移)+ org_node_lifecycle._PRE_STATE/_POST_STATE 扩展 + run_task_lifecycle()/run_or_resume_task_lifecycle() 新分支。该分支落地时一并修复 task-execution-resume-assumes-planner-artifacts-exist.md 记录的 resume 假设 artifact 存在的 bug(同一段代码路径,不分两次改)。 1
FR-2 Coder(implement_code())、Validator(validate_implementation_with_own_graph())两处调用点,把硬编码 manifest 换成真实调用 plan_work_graph(conn, "coder"/"validator", ...)——函数本身已通用,只需替换调用点。 2
FR-3 graph_manifest 节点 schema 扩展显式的"实现绑定"字段:这个节点由哪个 subagent + 哪个 skill + 哪些 tools + 输入输出 data 实现。今天的 judgment/on_fail 已覆盖"怎么判断成功/失败、失败去哪",但"用什么实现"这一半目前只是 _GENERIC_PROMPT_TEMPLATE 给的一段自由文本 task_prompt,不是结构化字段——这是本次真正的新增 schema 工作。 2
FR-4 新增一个 org-agent-无关的"节点级验证"skill(可被任意角色的 role.json 引用),作为 judgment.kind="llm" 的标准实现:验证节点输出、判断根因、精确 loop_back 到需要修复的节点。用它统一/取代 org_level_loop.py 今天的粗粒度 fast_lane/full_replan 路由——这是 org-graph-as-work-graph-unified-loop-requirements.md 的核心诉求,按 §4 已拍板的方案 A(合图)落地:loop_back 目标节点和触发验证的节点在同一个 work_graph_run 内,不需要跨图寻址。 4
FR-5a 前端新增 Org 级元图:把 Planner/复核 Validator/Coder/终审 Validator 四段渲染成一张顶层图,每段可展开成该 Org Agent 自己的 Work Graph 详情(复用现有 renderGraphVisualizerPanel,不重写渲染器)。 3
FR-5b 前端新增同一个 work_graph_run 内按 attempt_number 的历史回放时间轴/scrubber,复用已经在拉取但未渲染的 loop_back_events[].feedback。 3

4. 关键架构决策:方案 A(合图)——已确认,2026-08-08

延续 org-graph-as-work-graph-unified-loop-requirements.md §4 提出、原本没有答案的问题:跨 Org Agent 的"节点"地址空间不通。今天的 loop_back 只能在同一个 work_graph_run 内部跳转;Planner 和 Coder 各自的 plan_work_graph() 调用产出互不相通的节点 id 空间。FR-1 插入新的"复核"阶段后,这个问题从"理论上的开放问题"变成了"复核失败必须精确跳回 Planner 图里的哪个节点,而不是重新触发整个 Planner"这个具体的实现阻塞点。

当时摆在台面上的两个方案:

  • 方案 A(合图):Planner→复核→Coder→终审 四段合并成一张跨阶段大图,loop_back 天然能跳(同一张图内部)。
  • 方案 B(图间路由):保留"每个 Org Agent 各自一张图"的边界,新增一层跨图路由(复合地址如 {run_id, node_id})。

用户拍板(2026-08-08):采用方案 A。 FR-4、Phase 2 均按合图路径设计。

4.1 合图决策落地时需要处理的具体冲突点(Phase 2 设计阶段解决,本轮不预先决定怎么改)

  1. work_graph_run.org_node 是单值列,且有唯一约束:src/schema.py:130(org_node TEXT NOT NULL CHECK (org_node != ''))+ src/schema.py:152(CREATE UNIQUE INDEX ux_work_graph_run_active ON work_graph_run(task_id, org_node),语义是"同一 task 同一 org_node 同一时刻只有一个活跃 run")。合图后一个 work_graph_run 会同时容纳 Planner/Coder/Validator 各自规划出的节点,org_node 归属需要下沉到节点级别而不是 run 级别——这正好可以和 FR-3(节点声明由哪个 subagent/skill 实现)合并解决:节点级的"实现绑定"字段天然可以承载"这个节点属于哪个 org_node"。ux_work_graph_run_active 这条唯一索引的语义也要重新设计(大图模式下"活跃 run"变成 per-task 唯一,而不是 per-(task, org_node) 唯一)。
  2. FR-2(各 Org Agent 自规划)与"一张大图"如何协调:不能是一次性提前把四段全部规划完——Coder 需要看到 Planner 的真实产出内容才能规划自己的实现节点,Validator 同理需要看到 Coder 的真实 diff。合理的模型是增量追加:每个阶段的 plan_work_graph() 调用把自己规划出的节点追加进同一个 run_id 的 graph_manifest,而不是像今天一样各自开一个新 run_id。追加的原子性、并发写入 graph_manifest 的锁语义、追加后 topological_layers() 要不要对已执行完的前半部分重新分层,是 Phase 2 SDD 需要给出具体算法的地方。
  3. REQ-06 断点续跑的代价被重新评估、判断没有原先设想的那么大:合图讨论之初认为方案 A 会"打破每个 Org Agent 各自一次 claude -p 调用、各自断点续跑的隔离边界"(work-graph-self-planning-and-loop-back-requirements.md §1.3)。但节点级持久化(work_node_execution 表)本来就是"每个节点独立一次 claude -p 调用 + 独立落盘",这个粒度不因为节点归属同一个 run_id 还是分属不同 run_id 而改变——真正需要新设计的是上面两条(org_node 单值列迁移、增量追加规划机制),不是 REQ-06 本身。Phase 2 设计阶段仍需用真实测试验证这个判断。

5. 非目标

  1. 不动 scheduler-production-polling-loop-requirements.md 的 FR-1(新 Goal 自动派发)——该文档已明确这是独立的自主权边界决策,与本次 Org Graph 主流程改动正交,不合并排期。
  2. 不要求第一版就把 validator-test-script-narrative-output-issue.md 的根因彻底修完——FR-2/FR-3 落地后 Coder 也会产出 test_script 类内容节点,叙述文字复发风险依然存在(该文档已记录用户接受此已知风险);本文档只是把"给 Coder 加 test_script 模块"接进 FR-2/FR-3 范围,Phase 2 落地时需要专门验证这条风险有没有复现,不单独立项新对策。
  3. 不重写 work_graph_orchestrate.py 的 judgment/on_fail/loop_back 引擎本身——它已经是通用的,本次只新增调用方(FR-2)和一个 skill(FR-4),不改引擎代码。
  4. 不重写前端已有的 SVG DAG 渲染器——FR-5 是在现有 renderGraphVisualizerPanel/mountGraphVisualizerEdges 基础上新增元图和回放时间轴,不是推倒重来。

6. Phase 规划

Phase 1 — Org 主流程改造 + resume bug 一并修复

  • 范围:FR-1(含 task-execution-resume-assumes-planner-artifacts-exist.md 的修复)。
  • 产出:task.status schema 迁移、org_node_lifecycle.py 扩展、run_task_lifecycle()/run_or_resume_task_lifecycle() 新分支。
  • 前置条件:无——调研已给出具体改动点,可以先做。复核阶段本身可以先用 org_level_loop.py 现有的粗粒度路由兜底(复核失败 → 整个打回 Planner 重来),不必等 Phase 2 的精确 loop_back 才能上线,先把"Coder 开始前多一道独立判断"这件事跑起来。
  • 验收:能在(已真实复现过的)"benchmark 输出叙述文字冒充产出"场景下,在 Coder 动手之前拦住任务;崩溃后 resume 不再假设 Planner artifact 一定存在。

Phase 2 — 全员自规划 + 合图(方案 A)+ 节点级验证 skill

  • 范围:FR-2 + FR-3 + FR-4,按 §4/§4.1 已拍板的合图路径实现。
  • 产出:
    1. work_graph_run.org_node 从 run 级单值列下沉为节点级字段(与 FR-3 的 subagent/skill/tools/data 绑定字段合并设计),ux_work_graph_run_active 唯一约束按合图后的新语义调整(schema 迁移)。
    2. Coder/Validator 接入 plan_work_graph(),但不再各自开新 run_id——改为把自己规划出的节点增量追加进 Phase 1 已经建好的同一个跨阶段 work_graph_run(§4.1 第 2 点的追加机制)。
    3. 新增节点级验证 skill,org_level_loop.py 的粗粒度 fast_lane/full_replan 路由被替换为图内精确 loop_back(因为合图后失败节点和目标节点天然在同一个 run_id,不再需要跨图路由层)。
  • 前置条件:Phase 1 落地的"复核"阶段先用 org_level_loop.py 粗粒度路由兜底上线;Phase 2 把这段兜底逻辑替换成图内精确 loop_back,同时完成 §4.1 的三个迁移点。
  • 风险:Coder 开始自规划、产出内容型节点后,validator-test-script-narrative-output-issue.md 记录的叙述文字复发风险需要在本 phase 内验证是否触发,必要时补加机械拦截网(参考 check_script_compiles() 的先例),不是事后打补丁。

Phase 3 — 前端动态 + 历史图谱(可与 Phase 2 并行)

  • 范围:FR-5a + FR-5b。
  • 产出:Org 级元图 + work_graph_run 内 attempt_number 回放时间轴。
  • 依赖说明:FR-5b 只依赖 loop_back_events 数据形状,今天已存在,不需要等 Phase 2 完成;FR-5a 的"复核"这一段需要 Phase 1 新增的 task.status 值才有东西可渲染,其余三段可以先做。

明确不排期

scheduler-production-polling-loop-requirements.md 的 FR-1(新 Goal 自动派发)——保持独立评审,不合并进本文档的任何 phase。


7. 待确认的问题(讨论后逐条勾掉,参照 graph-engineering-open-items.md 的状态图例)

✅ §4 关键架构决策:方案 A(合图)。2026-08-08 用户拍板。 🔲 FR-1 新增的 task.status 枚举值具体叫什么名字(不影响功能,但要在讨论时定下来,避免实现时随意起名,例如 planner_output_review/reviewing_planner_output 等候选)。 🔲 FR-1 的"复核 Validator"和"终审 Validator"是否复用同一个 validator org role 跑两次(带不同的 manifest/prompt),还是需要一个新的 org role——影响 roles/ 目录结构和 org_node_lifecycle._PRE_STATE/_POST_STATE 的 key 设计。 🔲 FR-4 的节点级验证 skill 是在 qa-task-validation 基础上改造,还是新开一个 skill。 🔲 Phase 2 的 Coder/Validator 自规划,要不要像 Planner 一样有一份"允许的节点类型清单"约束,还是完全自由(对应 _PROMPT_TEMPLATE vs _GENERIC_PROMPT_TEMPLATE 的既有分野)。 🔲 §4.1 第 1 点:org_node 下沉到节点级别后,work_graph_run.org_node(run 级)这一列要不要保留(比如作为"发起该 run 的原始 org_node"这种冗余但方便查询的字段),还是彻底移除、查询时改成从节点聚合。 🔲 §4.1 第 2 点:"增量追加规划"的具体接口形态——是 plan_work_graph() 新增一个"追加模式"参数直接 UPDATE 已有 run_id 的 graph_manifest,还是由调用方(e2e_pipeline.py)读出旧 graph_manifest、拼接新节点、再整体写回。