diff --git a/crates/df-workflow/src/dag_def.rs b/crates/df-workflow/src/dag_def.rs index 6182329..9adde2b 100644 --- a/crates/df-workflow/src/dag_def.rs +++ b/crates/df-workflow/src/dag_def.rs @@ -6,7 +6,15 @@ use std::collections::HashMap; /// DAG 定义 — 可序列化/反序列化,用于持久化和模板 #[derive(Serialize, Deserialize, Clone, Debug)] pub struct DagDef { + // BUG-260621-01: nodes/edges 加 #[serde(default)]。 + // 前端 run_workflow 推进链传空 dag `{}`(设计意图:空 dag + target_status → + // workflow.rs:91 dag.nodes.is_empty() 进 template_for 自动选模板)。原无 default + // 时,`{}` 在 Tauri IPC 入口反序列化 DagDef 即报 `missing field nodes`,挡在选模板 + // 逻辑之前。加 default 后 `{}` → 空 DagDef(HashMap/Vec 的 Default 均空集合), + // 顺利进 :91 选模板分支。非空 dag 零回归(serde default 仅补缺失字段)。 + #[serde(default)] pub nodes: HashMap, + #[serde(default)] pub edges: Vec, } @@ -78,3 +86,28 @@ impl Default for DagDef { Self::new() } } + +#[cfg(test)] +mod tests { + use super::*; + + // BUG-260621-01: 前端 run_workflow 推进链传空 dag `{}`,serde 必须能反序列化 + // 成空 DagDef(非报 missing field),后续 workflow.rs:91 dag.nodes.is_empty() + // 进 template_for 选模板。nodes/edges 加 #[serde(default)] 前此用例会失败。 + #[test] + fn empty_json_deserializes_to_empty_dagdef() { + let dag: DagDef = serde_json::from_str("{}").expect("空 JSON 应反序列化为空 DagDef"); + assert!(dag.nodes.is_empty()); + assert!(dag.edges.is_empty()); + } + + // 零回归:非空 dag 反序列化行为不变(serde default 仅补缺失字段)。 + #[test] + fn nonempty_dag_deserializes_unchanged() { + let json = r#"{"nodes":{"n1":{"id":"n1","node_type":"echo","config":{}}},"edges":[]}"#; + let dag: DagDef = serde_json::from_str(json).expect("非空 dag 反序列化"); + assert_eq!(dag.nodes.len(), 1); + assert!(dag.nodes.contains_key("n1")); + assert!(dag.edges.is_empty()); + } +} diff --git a/docs/todo.md b/docs/todo.md index 5fbca3f..89b1c00 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -54,7 +54,7 @@ > 用户排查任务/项目/灵感查询能力现状,登记缺口为待办/缺陷,本轮不实施代码。详单见 [查询能力补全方案-2026-06-21.md](./02-架构设计/专项设计/查询能力补全方案-2026-06-21.md)。 -- [ ] BUG-260621-01 [P1🔴·确定修法] — **run_workflow 空 dag 反序列化失败(missing field nodes),阻塞任务工作流推进**。前端 TaskDetail.vue:333 传 `{}` 空 dag(设计意图:空 dag+target_status→template_for 选模板),但 DagDef.nodes/edges(dag_def.rs:9-10)无 #[serde(default)],serde 反序列化挡在选模板逻辑(workflow.rs:91)之前。修法(2 行):nodes/edges 各加 #[serde(default)]。非空 dag 零回归,空 dag 走选模板分支符合设计。— `crates/df-workflow/src/dag_def.rs`(:9-10) + `src/views/TaskDetail.vue`(:333) +- [x] BUG-260621-01 [P1🔴·确定修法] — **run_workflow 空 dag 反序列化失败(missing field nodes),阻塞任务工作流推进** ✅ **2026-06-22 修复**:DagDef.nodes/edges 各加 `#[serde(default)]`,`{}` 反序列化成空 DagDef → workflow.rs:91 `is_empty()` 进 template_for 选模板。2 单测防回归(空 `{}` + 非空零回归),df-workflow cargo test 51 passed。— `crates/df-workflow/src/dag_def.rs` + `src/views/TaskDetail.vue`(:333) - [x] F-260621-02 [P2] — **任务/项目/灵感列表查询维度补全(下沉后端+关键词搜索+排序分页)** ✅ **2026-06-22 实施**:三实体新增 `list_by_query` 动态 WHERE(累积式 where_clauses+params_vec 收口)+ order_by 白名单防注入 + limit/offset 钳制;命令层 `list_{tasks,projects,ideas}` 吃 `Option` 双参向后兼容(旧无参/单参路径等价全量);前端 Tasks/Ideas status/keyword 筛选下沉后端 query(Tasks.vue buildTaskQuery / Ideas.vue watch 防抖)。索引缺口(idx_tasks_priority/assignee)与 P3 排序分页 UI 待数据量驱动再加。详见查询能力补全方案-2026-06-21.md。— `commands/{task,project,idea}.rs` + `crates/df-storage/src/crud/{task,project,idea}_repo.rs` + `src/api/{task,project,idea}.ts` + `src/views/{Tasks,Projects,Ideas}.vue`