# 推进链阶段2 实施路径(F-260616-06) > 2026-06-16 Plan agent 评估产出。阶段1(7态状态机+advance_task CAS+软删除,commit d2cb38c)已落地。阶段2 目标:工作流联动任务推进(task_id + 完成回调 advance_task + DAG 模板)。 > > 决策依据:D-260616-03(advance_task/节点走 df-nodes Node trait,不复活 df-task)。 ## 一、现状基线(代码事实) | 维度 | 现状 | 评估 | |---|---|---| | 推进链状态机 | `task_state_machine.rs` 7态 + can_transition/is_regression,完整单测 | ✅ 阶段2 复用零改动 | | advance_task 原子写 | `advance_task_atomic(repo,id,target)` IPC 直驱已注册,CAS+软删+退回 bump_rounds | ✅ 复用 | | TaskAdvanceNode (Node trait) | `task_advance_node.rs:101-166` 已实现,持 Arc,execute 读 ctx.config | ✅ 节点就绪,仅未注册 | | build_registry 未注册 | `state.rs:232` `fn build_registry()` 无参,无法构造持 db 的 TaskAdvanceNode | 🔴 阻塞点 | | run_workflow task_id | `workflow.rs:36` 签名无 task_id;但 WorkflowRecord.task_id 字段(models/migrations/crud)全链路就绪(写库硬编码 None) | 🟡 IPC 扩展,持久层零改动 | | DagExecutor.run | `executor.rs:49` initial_config.clone() 下沉 NodeContext.config,**忽略 NodeDef.config** | 🔴 DAG 设计缺口(④-1) | | WorkflowCompleted 事件 | 仅 total_duration_ms,无 execution_id/task_id | 🟡 回调需 IPC 闭包捕获 task_id | ## 二、实施步骤 ### ④ 类 — 架构前置(阻塞) **④-1 DagExecutor config 下沉语义修复** - 问题:`executor.rs:99-107` NodeContext.config = initial_config.clone() 覆盖 NodeDef.config,TaskAdvanceNode 读不到节点配置。 - 修法(方案 A):`NodeContext.config = deep_merge(node_def_config, initial_config)` 节点级覆盖全局级。Dag 加 `node_configs: HashMap`,build_dag 填入,run 合并下沉。 - 文件锁:`crates/df-workflow/src/{dag.rs,executor.rs,registry.rs}` + `src-tauri/src/commands/workflow.rs` ### ② 类 — 需设计/行为变更(依赖④) - **②-1 build_registry 注入 db + 注册 TaskAdvanceNode** — 改签名 `build_registry(db: Arc)` + move 闭包 `register("task_advance", move |_| Box::new(TaskAdvanceNode::new(db.clone())))` + init 调用传 db.clone()。不改 Node trait(构造时注入)。文件锁:`src-tauri/src/state.rs` - **②-2 run_workflow 加 task_id + target_status 参数** — IPC 签名扩展(Option 可选兼容)+ WorkflowRecord.task_id 填入 + spawn move 捕获。文件锁:`workflow.rs` + `api/workflow.ts` + `stores/project/workflow.ts` - **②-3 完成回调 WorkflowCompleted→advance_task** — spawn 闭包内 executor.run Ok 后,task_id+target_status 都 Some 时调 advance_task_atomic。失败 warn 不回滚(工作流成功语义与任务推进解耦)。文件锁:`workflow.rs` - **②-4 失败回调退回语义** — failed 时按 target_status 推算退回态(testing→in_review,in_review→in_progress)调 advance,或加 failure_target_status 参数。文件锁:`workflow.rs` - **②-5 HumanNode reject 语义化** — options 含 reject/block 时返 Err(非 Ok),使工作流 failed 触发退回。文件锁:`crates/df-nodes/src/human_node.rs` - **②-6 DAG 模板** — `df-nodes/task_workflow_templates.rs`(新)导出 `template_for(target_status)->DagDef`,5 前向边+退回。不建 workflow_defs 表(模板少且稳定,硬编码;tasks.workflow_def_id 留 None)。文件锁:`crates/df-nodes/src/task_workflow_templates.rs` ### ① 类 — 可并行(无依赖) - **①-1 前端 TaskDetail 工作流推进按钮** — 与手动 advance 并存,调 workflowApi.run+监听进度。文件锁:`TaskDetail.vue` + `api/workflow.ts` + `stores/project/workflow.ts` - **①-3 i18n 文案** — `locales/{zh-CN,en}/tasks.ts` ## 三、风险 + 依赖 | 风险 | 缓解 | |---|---| | 状态机联动一致性(工作流回调 vs 手动 advance 并发撞 CAS) | advance_task_atomic 已 CAS,回调层捕获 InvalidState 降级 | | advance 失败回滚(工作流 Ok 但回调 advance 失败) | 不回滚工作流(已完成事实),回调失败 warn+前端提示手动处理 | | 工作流 failed 退回语义 | ②-4 按 target 推算退回态或 failure_target_status 参数 | | DAG 循环 | DagExecutor 拓扑排序已检测环,充分 | | task_id 缺失降级 | task_id/target_status 都 None 时不触发回调,向后兼容 | | DagExecutor config 下沉(④-1) | 必须先修,否则节点参数化失效 | | HumanNode reject 语义化(②-5) | 阶段2 必做,否则审查拒绝无法退回 | | 跨表事务缺失 | 阶段2 回调失败降级,阶段3/4 补 Database.transaction() | ## 四、实施顺序(串行关键路径) ``` ④-1 (config 下沉) → ②-1 (注册 TaskAdvanceNode) ← 单 task_advance 节点 DAG 可端到端 → ②-5 (HumanNode reject 语义化) ← 审查拒绝能走 failed → ②-2 (run_workflow task_id) → ②-3 (完成回调) ← AiNode+HumanNode 工作流推进任务可跑 → ②-4 (失败回调退回) → ②-6 (DAG 模板) ← 前端可一键触发 → ①-1 / ①-3 (前端接入 + i18n) ← 并行收尾 ``` **最小可验证里程碑**(④-1+②-1+②-2+②-3):`run_workflow(name, dag, {}, taskId="t1", targetStatus="in_progress")`,DAG=单 task_advance 节点,验证任务 todo→in_progress。无 AiNode/HumanNode 依赖,纯推进链联动验证。 ## 五、TaskAdvanceNode 注册路径 ```rust fn build_registry(db: Arc) -> NodeRegistry { let mut registry = NodeRegistry::new(); registry.register("human", |_| Box::new(df_nodes::human_node::HumanNode)); registry.register("ai", |_| Box::new(df_nodes::ai_node::AiNode)); registry.register("task_advance", move |_| { Box::new(df_nodes::task_advance_node::TaskAdvanceNode::new(db.clone())) }); registry } ``` 工厂闭包 move 捕获 db(构造时注入),每次 create 调用 clone 构造新实例。不改 Node trait。 ## 六、DAG 模板形态(阶段2) 工作流级 target_status(一个工作流对应一次推进): - `todo→in_progress`:单 AiNode 执行 - `in_review→testing`:AiNode 自审 + HumanNode 核对(reject→②-5 Err→failed→②-4 退回 in_progress,review_rounds+1) - `testing→done`:HumanNode 最终核对 节点级不携带 target_status(避免节点间状态不一致),工作流级统一。