# 统一 Org Graph 主流程 + 全体 Org Agent 自规划 Work Graph + 节点级验证回路 + 前端动态/历史图谱——需求文档(融合版) **日期**: 2026-08-08 **性质**: 需求文档(BRD/PRD 层面),不含详细技术设计。融合并统领以下既有 `docs/todo/` 文档的相关内容: - `docs/todo/org-graph-as-work-graph-unified-loop-requirements.md`(已删除,内容 100% 并入本文档)——本文档是它的展开与拍板;该文档提出的"跨 Org Agent 精确 loop_back"诉求是本文档 FR-4 + §4 关键架构决策的正文。 - `docs/done/task-execution-resume-assumes-planner-artifacts-exist.md`——它记录的 bug 与本文档 FR-1 改动的是**同一段** `run_or_resume_task_lifecycle()` 分支逻辑(见 §2.1 调研结论),折入 Phase 1 一并修,不再单独排期。 - `docs/done/validator-test-script-narrative-output-issue.md` 第 8 节提到的"另一份尚未撰写、关于给 Coder agent 加入 test_script 模块的文档",即本文档 Phase 2(FR-2/FR-3)。 **触发场景**:任务 `2084590a`(修复 `work_node_run.py` 的 `execution_log_file` bug)里,Planner 自规划出的 `benchmark` 节点连续 4 次产出的都是"叙述我做了什么"的散文(跟 `validator-test-script-narrative-output-issue.md` 同一类问题,这次发生在 benchmark 上),LLM judge 的 `on_fail=retry_self` 循环耗尽 `max_attempts=3` 后任务直接 `blocked_pending_human`——暴露出 Validator 从来没有机会在 Coder 开始实现之前复核 Planner 自己的产出。用户随后 2026-08-08 提出四点架构改动设想(见 §1),与当天早些时候整理的 `docs/todo/` 待办优先级建议(P0~P3)高度交叉,要求重新盘点、融合、给出 phase 规划。 **状态**: ✅ Phase 1/2/3 全部已实现(Phase 1: commit `ea19c7d`,2026-08-08;Phase 2a/2b/2c: 2026-08-12~13;Phase 3: 2026-08-13)。§7 列出的问题全部已拍板/已回答,见该节各条目状态。本文档提出的四点架构改动(§1)已全部落地。 --- ## 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.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` 到需要修复的节点,且当根因是**系统性 skill 缺陷**时先修 Skill 本身再重试——完整方法论见 §3.1,不是单纯"跳回某个节点重试"。用它统一/取代 `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 | ### 3.1 核心方法论(用户 2026-08-08 拍板,作为本项目开发的目标写在这里):失败即进化——Reflection → Fix-Skill → Re-loop **这是 Work Graph"自我进化"能力的精髓,FR-4 必须按这个方法论实现,不能退化成"判断失败→跳回某个节点重试"这么简单。** 用户原话的核心洞察:一个节点判断失败后,我们要的不只是"把这一次的错误修好"(fix-bug,只解决这一次),而是"让这一类错误以后不会再发生"(fix-skill,永久解决)——否则下一个类似任务撞上同一个坑,还是要重新踩一遍、重新修一遍。 **四步链路**(不是一个笼统的"loop_back",是四个明确的阶段/节点): 1. **判断分支**:节点产出被判定 `false`/`error`/`wrong`(`judgment.kind` 不管是 `mechanical` 还是 `llm`,只要 `ok=False`)——不是简单重试,跳转到分支 B。 2. **分支 B 第一个节点:Reflection-review**——对整条链路做复盘,不只是"这个节点自己错在哪",而是**全链路根因定位**:到底是哪一个更早的环节(可能是这个节点自己的 Skill 有缺陷,也可能是更早某个上游节点的产出本身就有问题)真正导致了这次失败。判断结论要落到两种性质里的一种: - **一次性内容错误**(这次具体的产出恰好没写好,Skill/方法论本身没问题)——走现有的精确 `loop_back`(Phase 2 SDD §5 的 `dynamic_loop_back`)即可,跳回真正的根因节点重新生成。 - **系统性 skill 缺陷**(这个 org_node 用来产出这类内容的 Skill 本身有方法论层面的问题,同类任务会反复踩同一个坑)——进入第 3 步。 3. **Fix-skill 节点**:不是修这一次的输出,是**修 Skill 本身**——真实调用已经存在的 Skill 迭代机制(`src/skill_update.py::update_skill()` + `src/bug_record.py::create_bug_record(root_cause_category='skill_defect')`),产出一次真实的、Git 版本化、可回滚的 Skill 内容更新(`skill_iteration` 表,`before_git_commit_sha`/`after_git_commit_sha` 都是真实 commit,不是模拟)。**这套机制在代码库里早就存在**(U-015/U-016 时期就建好了),但至今只在 `org_level_loop.py` 的 Org 级粗粒度路径上被触发过——FR-4 要把它真正接进 Work Graph 内部的判断/回路循环,让它成为节点级失败恢复的常规路径之一,不是只有跨 Org Agent 的大失败才配触发。 4. **跳回执行**:Skill 更新落地后,跳回"用这个 Skill 的节点"重新执行——这次用的是刚修好的新 Skill,不是拿旧 Skill 再赌一次运气。跟 `_loop_history_prompt_suffix`(现有机制,把历史反馈拼进 prompt)的本质区别:prompt 里的反馈是**这一次任务专属、跑完就忘**的临时纠偏;Skill 更新是**持久化、跨任务复用**的真正修复——两者不互斥(可以同时生效:这次重试既带着历史反馈,也带着已经更新的 Skill),但 FR-4 的核心价值在后者。 **跟 Phase 2 SDD 的关系**:`docs/done/org-graph-unification-phase2-universal-self-planning-design.md` §5 已经是四步的完整设计(2026-08-12 补齐)——`on_fail.action="dynamic_loop_back"` 触发时,Reflection-review(§5.4)同时判断"跳回哪个节点"和"这是一次性错误还是系统性 Skill 缺陷";系统性缺陷时先经过 Fix-Skill(§5.5,真实调用既有但从未真正投入生产使用的 `skill_update.py::update_skill()`,产出 Git 版本化的 Skill 迭代)再跳回执行。由哪个身份执笔改 Skill,已确认(2026-08-12)统一用 Validator(该文档 §5.5)。 --- ## 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-new-goal-dispatch-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 一并修复 ✅ 已实现(commit `ea19c7d`,2026-08-08) - **详细设计**:`docs/done/org-graph-unification-phase1-review-gate-design.md`(已随实现移入 `docs/done/`,与实现逐条吻合,见该文档更新后的状态行)。 - **范围**:FR-1(含 `task-execution-resume-assumes-planner-artifacts-exist.md` 的修复)。 - **产出**:`task.status`/`execution_event` 两处 schema 迁移、新增独立 org role `planner_reviewer`、`org_node_lifecycle.py` 的 `_PRE_STATE`/`_POST_STATE`/`_REQUIRED_ARTIFACTS` 扩展、`e2e_pipeline.py` 新增复核+重试循环、`run_task_lifecycle()`/`run_or_resume_task_lifecycle()` 新分支。复核失败的重试是任务内部的粗粒度循环(完整重新规划,不接 `org_level_loop.py`),不是"打回整个任务重来"。 - **额外发现**(设计阶段调研中定位,一并修复):`e2e_pipeline.py::run_task_lifecycle()` 对 `artifact_ids["prd"]`/`["benchmark"]` 的无条件下标访问,在自规划图省略这两个类型时会 `KeyError`——这个崩溃在 fresh-run 首次执行就会触发,不需要等到 resume,是比 P0 bug 更早触发的同类问题。 - **前置条件**:无——SDD 已给出具体改动点,可以直接实施。复核阶段本身可以先用任务内部的粗粒度重试兜底(复核失败 → 完整重新规划),不必等 Phase 2 的精确 loop_back 才能上线,先把"Coder 开始前多一道独立判断"这件事跑起来。 - **验收**:能在(已真实复现过的)"benchmark 输出叙述文字冒充产出"场景下,在 Coder 动手之前拦住任务;崩溃后 resume 不再假设 Planner artifact 一定存在;fresh-run 也不再假设 prd/benchmark 一定存在。 ### Phase 2 — 全员自规划 + 合图(方案 A)+ 节点级验证 skill ✅ 已实现(2026-08-13) - **详细设计**:`docs/done/org-graph-unification-phase2-universal-self-planning-design.md`(已随实现移入 `docs/done/`)。Phase 2a(节点级 subagent/skill 绑定 + `dynamic_loop_back`/Reflection-review/Fix-Skill,commit `86fc0bb`)+ Phase 2b(Coder 接入自规划,commit `7c46a2f`)+ Phase 2c(Validator 接入自规划、`org_node` 列删除、`work-graph-node-review` skill)全部落地,详见该文档最终状态行。设计阶段发现范围比原设想更大——`_GENERIC_PROMPT_TEMPLATE` 从未征集 judgment/on_fail、`run_graph()` 的 subagent_type/skill_ref 是 run 级常量不是节点级、现有 `loop_back` 是规划阶段静态声明的单一目标不支持终审失败时动态选择根因节点(新增 `on_fail.action="dynamic_loop_back"` 解决,复用 `root_cause_trace.py` 陪审团结构)——详见该文档 §1/§5。 - **范围**:FR-2 + FR-3 + FR-4,按 §4/§4.1 已拍板的合图路径实现。 - **产出**(按拍板后的最终形状): 1. `work_graph_run.org_node` 列彻底删除(不是下沉/保留),`work_graph_run_query.py`/`work_graph_fork.py` 改造为从 `work_node_execution.subagent_type` 聚合/逐节点判断;`ux_work_graph_run_active` 收窄为 `UNIQUE(task_id)`。 2. Coder/Validator 接入 `plan_work_graph()`,新增 `append_to_run_id` 参数(不是独立函数)实现增量追加进 Phase 1 建好的跨阶段 `work_graph_run`;新增 `_CODER_NODE_CATALOG`/`_VALIDATOR_NODE_CATALOG` 建议节点清单(不是完全自由规划)。 3. `run_graph()`/`_run_one_node()` 扩展为读取节点自己声明的 `subagent_type`/`skill_ref`(缺省退回图级默认),新增节点级验证 skill `work-graph-node-review`,`org_level_loop.py` 的粗粒度 `fast_lane`/`full_replan` 路由被 `dynamic_loop_back` 取代(不删除该模块,其他调用方仍在用)。 - **前置条件**:Phase 1 落地的"复核"阶段先用 `org_level_loop.py` 粗粒度路由兜底上线;Phase 2 把这段兜底逻辑替换成图内精确 loop_back。 - **风险**:Coder 开始自规划、产出内容型节点后,`validator-test-script-narrative-output-issue.md` 记录的叙述文字复发风险需要在本 phase 内验证是否触发,必要时补加机械拦截网(参考 `check_script_compiles()` 的先例),不是事后打补丁。 - **建议前置(非强制)**:`docs/done/work-graph-node-execution-deblackbox-requirements.md`(2026-08-08,单节点执行层去黑盒化,正交但相关)——Phase 2 会大量新增 `judgment.kind="llm"` 节点级判断调用,如果去黑盒化工作先完成,Phase 2 可以直接基于新的 `trigger_org_node_structured()` 设计,不需要在原生 Workflow 和新机制之间选一套来复用。 ### Phase 3 — 前端动态 + 历史图谱 ✅ 已实现(2026-08-13) - **范围**:FR-5a + FR-5b。 - **产出**:`frontend/app.js` 新增独立的四段 Org 级元图(`renderOrgMetaGraph` 等,不是扩展早期 `renderOrgGraphTopology`——后者仍是三段,被既有 smoke test 钉住,未改动);`planner_reviewer` 这一段没有自规划 Work Graph 可展开,改为展示它的 `planner_review_verdict` execution_event 历史列表(`task_query.py` 新增 `_planner_review_events_for_task()`);FR-5b 的 `attempt_number` 回放时间轴(`renderLoopBackTimelineHtml`)复用了此前"已拉取但未渲染"的 `loop_back_events[].feedback`。新增 `frontend/test_org_meta_graph_smoke.js`(35 断言)。 - **依赖说明**:FR-5b 只依赖 `loop_back_events` 数据形状,不需要等 Phase 2 完成;FR-5a 的"复核"这一段需要 Phase 1 新增的 `task.status` 值才有东西可渲染,均已满足。 ### 明确不排期,现已独立立项实施 `scheduler-new-goal-dispatch-requirements.md`(FR-1,新 Goal 自动派发)——本文档保持不合并进任何 phase 的原判断不变,但该需求本身已在 2026-08-13 由用户单独拍板、独立实施完成,见 `docs/done/scheduler-new-goal-dispatch-requirements.md`。 --- ## 7. 待确认的问题(讨论后逐条勾掉,参照 `graph-engineering-open-items.md` 的状态图例) ✅ §4 关键架构决策:方案 A(合图)。2026-08-08 用户拍板。 ✅ FR-1 新增的 `task.status` 枚举值定为 `reviewing_planner_output`。2026-08-08,随 Phase 1 SDD(`docs/done/org-graph-unification-phase1-review-gate-design.md`)一起拍板,理由见该文档 §3.1。 ✅ FR-1 的"复核 Validator"用新增独立 org role `planner_reviewer`,不复用 `validator`。2026-08-08 用户拍板(`AskUserQuestion` 确认),理由见 Phase 1 SDD §2.1——`_PRE_STATE`/`_POST_STATE` 是按 org_node 名字一对一映射,同一个 key 没法挂两组状态转移。 ✅ FR-4 的节点级验证 skill:新开一个 skill,不在 `qa-task-validation` 基础上改造。2026-08-08 用户拍板。理由:`qa-task-validation` 整份内容绑定飞书多维表格语义(硬编码 `tblXXX` 表 ID、状态机是"待测试→已完成"这类 Base 记录写回),判定粒度是整个任务的 PASS/FAIL/INCONCLUSIVE;FR-4 要的是单个 Work Graph 节点的 `judgment.kind="llm"` 回调,输入是一个节点的输出,输出要精确指向 `loop_back` 的目标 `node_id`,和 Base 完全无关,两种用途混进同一份 skill 容易互相污染。新 skill 可以借鉴其判定原则(三态结论、独立复核、真实路径优先)写进 prose,但不复用文件本身。 ✅ Phase 2 的 Coder/Validator 自规划:加一份建议清单(类似 `_PLANNER_NODE_CATALOG`),不是完全自由。2026-08-08 用户拍板——推翻了 `work_graph_plan.py:161-170` 2026-08-06 注释里"Coder/Validator's sub-tasks have no such fixed small vocabulary of node types"的原判断。Phase 2 设计阶段需要给 Coder/Validator 各自定义一份"常见节点类型"参考目录(如 impl/unit_test/integration_check),每项可以像 `_PLANNER_NODE_CATALOG` 一样标注 `suggested_judgment`,但不强制——沿用 Planner 目录"建议不强制"的既有约定,而不是 Planner 文档链那种固定顺序的强约束。 ✅ §4.1 第 1 点:`work_graph_run.org_node`(run 级单值列)彻底移除,查询改为从节点级聚合。2026-08-08 用户拍板——推翻了"保留作冗余字段"的备选项。Phase 2 设计阶段需要解决两处下游改造:`work_graph_run_query.py:62` 的 `WHERE wgr.org_node = ?` 过滤要重写成 JOIN 节点表再过滤;`work_graph_fork.py` 的 fork 谱系展示要重新定义"一个横跨四段的合图 run 展示哪个/哪些 org_node"这个尚未存在的聚合语义(例如展示节点级 org_node 的去重列表,而不是单值)——这是本次决策遗留的新开放问题,不是照抄旧列就能解决的,需要在 Phase 2 SDD 里明确定义。 ✅ §4.1 第 2 点:"增量追加规划"接口:`plan_work_graph()` 新增一个"追加模式"参数(如 `append_to_run_id`),内部完成"读现有 `graph_manifest` → 合并新规划出的节点/边(含 `node_id` 冲突检测) → `UPDATE` 写回",不下放给调用方各自实现。2026-08-08 用户拍板。理由:合并/冲突检测逻辑集中在 `work_graph_plan.py` 一处——该模块本来就是 `_normalize_graph_manifest`/`_validate_loop_back_targets` 等 `graph_manifest` 结构性操作的归属地——避免 Coder、Validator 两个调用点各自实现一遍合并逻辑,未来出现两处不一致的风险。