新增: 父子任务支持(数据→后端→前端全链路,会话前基线收尾)
- df-nodes task_advance_node(父聚合推进)+ task.rs 命令(create parent_id 支持/delete 级联软删子任务)+ task_graph 工具 - 前端 Tasks 树形列表(折叠箭头/子进度徽章/缩进)+ 新建弹窗父任务下拉 + TaskDetail 父面包屑/子任务面板 - 设计文档: 父子任务支持设计-2026-08-04
This commit is contained in:
@@ -203,10 +203,11 @@ pub fn register(registry: &mut AiToolRegistry, db: &Arc<Database>) {
|
||||
let id = args["id"].as_str().ok_or_else(|| anyhow::anyhow!("缺少 id"))?;
|
||||
let target_status = args["target_status"].as_str()
|
||||
.ok_or_else(|| anyhow::anyhow!("缺少 target_status"))?;
|
||||
// 复用 df-nodes 推进链核心逻辑(状态机 + 原子 CAS + review_rounds),
|
||||
// 与 commands::task::advance_task IPC 同源,避免双轨。
|
||||
// 复用 df-nodes 推进链核心逻辑(状态机 + 原子 CAS + review_rounds + 父聚合),
|
||||
// 与 commands::task::advance_task IPC 同源,避免双轨。设计 D3:子任务推进后
|
||||
// 自动触发父 status 聚合(advance_task_with_parent,父聚合失败仅 warn 不阻断)。
|
||||
let repo = df_storage::crud::TaskRepo::new(&db);
|
||||
let updated = df_nodes::task_advance_node::advance_task_atomic(
|
||||
let updated = df_nodes::task_advance_node::advance_task_with_parent(
|
||||
&repo, id, target_status,
|
||||
).await?;
|
||||
// 返回推进后的 TaskRecord(含新 status / 累加后的 review_rounds),供 LLM 确认推进结果。
|
||||
|
||||
@@ -138,11 +138,11 @@ pub fn register(registry: &mut AiToolRegistry, db: &Arc<Database>) {
|
||||
|
||||
// ── move_task_queue (Medium,设计 §2.1 + §五) ──
|
||||
// 跨池移动任务(backlog/todo/decision/active/done),按一致性约束联动 status。
|
||||
// 对齐 commands::task::move_task_queue 语义:
|
||||
// 全部逻辑收口到 TaskRepo::move_task_queue 单事务方法(读当前 → 联动 status →
|
||||
// 写 queue+status 于同一 transaction),与 commands::task::move_task_queue 共用,防漂移。
|
||||
// - done → status 强制 done / backlog → status 强制 todo
|
||||
// - active → status 若不在执行中三态则强制 in_progress / todo → status 强制 todo
|
||||
// - decision → status 不变(待决策池保留执行态)
|
||||
// status 写入走专用 set_status_for_aggregation(绕过 status 收口,move_task_queue 是合法非状态机路径)。
|
||||
declare_tool!(
|
||||
registry,
|
||||
db: Arc<Database>,
|
||||
@@ -156,50 +156,14 @@ pub fn register(registry: &mut AiToolRegistry, db: &Arc<Database>) {
|
||||
.ok_or_else(|| anyhow::anyhow!("缺少 new_queue"))?
|
||||
.trim()
|
||||
.to_string();
|
||||
// queue 白名单校验(对标 commands::task::validate_queue)
|
||||
const TASK_QUEUE_VALUES: &[&str] = &["backlog", "todo", "decision", "active", "done"];
|
||||
if !TASK_QUEUE_VALUES.contains(&new_queue.as_str()) {
|
||||
anyhow::bail!("非法 new_queue 值 {:?},合法值: {:?}", new_queue, TASK_QUEUE_VALUES);
|
||||
}
|
||||
|
||||
// 单事务原子移动:读当前 → 一致性联动 status → 写 queue+status 全在
|
||||
// TaskRepo::move_task_queue 同一 transaction 内完成(queue 白名单/联动规则单点)。
|
||||
let repo = df_storage::crud::TaskRepo::new(&db);
|
||||
let current = repo
|
||||
.get_by_id(id)
|
||||
let updated = repo
|
||||
.move_task_queue(id, &new_queue)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow::anyhow!("任务 {id} 不存在"))?;
|
||||
|
||||
// 一致性约束联动:根据 new_queue 决定 status 是否需调整
|
||||
// (对标 commands::task::move_task_queue 同源逻辑,单一真相源)
|
||||
const ACTIVE_OK_STATUSES: &[&str] = &["in_progress", "in_review", "testing"];
|
||||
let new_status = match new_queue.as_str() {
|
||||
"done" => "done".to_string(),
|
||||
"backlog" => "todo".to_string(),
|
||||
"active" => {
|
||||
if ACTIVE_OK_STATUSES.contains(¤t.status.as_str()) {
|
||||
current.status.as_str().to_string()
|
||||
} else {
|
||||
"in_progress".to_string()
|
||||
}
|
||||
}
|
||||
"todo" => "todo".to_string(),
|
||||
"decision" => current.status.as_str().to_string(),
|
||||
_ => unreachable!("queue 白名单已收口"),
|
||||
};
|
||||
|
||||
// 写 queue(queue 已在 tasks 白名单);与 current 不同才写(避免无谓 updated_at 抖动)
|
||||
if current.queue != new_queue {
|
||||
repo.update_field(id, "queue", &new_queue).await?;
|
||||
}
|
||||
// 写 status(专用 set_status_for_aggregation 绕过 status 收口,合法非状态机路径)
|
||||
if current.status.as_str() != new_status {
|
||||
repo.set_status_for_aggregation(id, &new_status).await?;
|
||||
}
|
||||
|
||||
// 回读最新记录返回
|
||||
let updated = repo
|
||||
.get_by_id(id)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow::anyhow!("任务 {id} 不存在(移动后回读失败)"))?;
|
||||
Ok(serde_json::to_value(&updated)?)
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user