新增: 多Agent数据层(V36迁移+3新表+Repo CRUD+7个测试全绿)

- V36: ai_plans/ai_subtasks/ai_conflicts 3 新表 + ai_messages/ai_tool_executions 加 subtask_id

- models: PlanRecord/SubTaskRecord/ConflictRecord 结构体

- PlanRepo/SubTaskRepo/ConflictRepo CRUD(insert/get/list_by_*/update_status/resolve)

- 7个 Repo 单元测试全部通过(内存 SQLite + 全迁移)

- 顺带修复 task_repo.rs 预存测试编译错误(trec_full 参数类型+缺失 await)
This commit is contained in:
lxy
2026-07-01 21:50:16 +08:00
parent f4fc0feff5
commit ae6d3d0043
6 changed files with 735 additions and 7 deletions
+86 -1
View File
@@ -45,7 +45,7 @@ pub fn run(conn: &Connection) -> Result<()> {
// 什么数据库、Redis 在哪、有没有 MQ"的基础设施上下文。
// V33 = 审批重启恢复:ai_conversations 加 pending_approvals TEXT 列,持久化挂起审批快照,
// 重启后从 DB 恢复 pending_approvals 内存态,使待审批不丢。
let steps: [(i32, fn(&Connection) -> Result<()>); 35] = [
let steps: [(i32, fn(&Connection) -> Result<()>); 36] = [
(1, migrate_v1),
(2, migrate_v2),
(3, migrate_v3),
@@ -81,6 +81,7 @@ pub fn run(conn: &Connection) -> Result<()> {
(33, migrate_v33),
(34, migrate_v34),
(35, migrate_v35),
(36, migrate_v36),
];
for (version, migrate_fn) in steps {
@@ -1030,6 +1031,90 @@ fn migrate_v35(conn: &Connection) -> Result<()> {
Ok(())
}
/// V36:多 Agent 并行执行数据层(ai_plans/ai_subtasks/ai_conflicts 3 新表 +
/// ai_messages/ai_tool_executions 加 subtask_id 列)。
/// 设计依据:docs/02-架构设计/专项设计/多Agent并行执行与仲裁合并设计-2026-07-01.md §二
fn migrate_v36(conn: &Connection) -> Result<()> {
// 1. ai_messages 加 subtask_id 列(消息归属子任务,NULL=单 Agent 时期)
if !column_exists(conn, "ai_messages", "subtask_id") {
conn.execute("ALTER TABLE ai_messages ADD COLUMN subtask_id TEXT", [])?;
tracing::info!("v36: ai_messages 加 subtask_id 列");
}
// 2. ai_tool_executions 加 subtask_id 列(工具调用归属子任务)
if !column_exists(conn, "ai_tool_executions", "subtask_id") {
conn.execute("ALTER TABLE ai_tool_executions ADD COLUMN subtask_id TEXT", [])?;
tracing::info!("v36: ai_tool_executions 加 subtask_id 列");
}
// 3. ai_plans 表(Plan 生命周期:用户消息触发→拆解→执行→合并→完成)
conn.execute(
"CREATE TABLE IF NOT EXISTS ai_plans (
id TEXT PRIMARY KEY,
conversation_id TEXT NOT NULL,
user_message_id TEXT,
status TEXT NOT NULL DEFAULT 'planning',
subtask_count INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
completed_at TEXT
)",
[],
)?;
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_ai_plans_conv ON ai_plans(conversation_id, created_at)",
[],
)?;
// 4. ai_subtasks 表(SubTask 状态 + DAG 层级 + Git worktree 分支)
conn.execute(
"CREATE TABLE IF NOT EXISTS ai_subtasks (
id TEXT PRIMARY KEY,
plan_id TEXT NOT NULL REFERENCES ai_plans(id),
persona_id TEXT,
intent TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'pending',
layer INTEGER NOT NULL DEFAULT 0,
deps TEXT,
branch TEXT,
created_at TEXT NOT NULL,
completed_at TEXT
)",
[],
)?;
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_ai_subtasks_plan ON ai_subtasks(plan_id, layer)",
[],
)?;
// 5. ai_conflicts 表(合并冲突:同文件路径 + 跨文件语义冲突)
conn.execute(
"CREATE TABLE IF NOT EXISTS ai_conflicts (
id TEXT PRIMARY KEY,
plan_id TEXT NOT NULL REFERENCES ai_plans(id),
file_path TEXT NOT NULL DEFAULT '',
conflict_type TEXT NOT NULL DEFAULT 'file',
subtask_a TEXT,
subtask_b TEXT,
diff_a TEXT,
diff_b TEXT,
resolution TEXT NOT NULL DEFAULT 'pending',
resolved_by TEXT,
created_at TEXT NOT NULL,
resolved_at TEXT
)",
[],
)?;
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_ai_conflicts_plan ON ai_conflicts(plan_id, resolution)",
[],
)?;
tracing::info!("v36: 建 ai_plans/ai_subtasks/ai_conflicts 表 + subtask_id 列(多 Agent 并行执行数据层)");
conn.execute("INSERT INTO schema_version (version) VALUES (?)", [36])?;
tracing::info!("迁移 v36 完成");
Ok(())
}
/// V21 建表 SQL — 消息拆分存储 ai_messages 表
///
/// 与 V9_SQL 中的 ai_messages 镜像(V9 给新库,此 const 给老库 V21 迁移用 IF NOT EXISTS)。