新增: 后续批次测试用例设计 + 批次规划同步worktree方案

- 测试用例:8大类共70+用例(迁移/Repo/拆解/worktree/并行/仲裁/模板/CI/审批/拆分/端到端/边界)

- 批次同步:数据层+worktree+并行(12项)/仲裁+冲突UI+编译检查(10项)/模板+节点(10项)/Git-CI+DockerNode(6项)/审批政策+小程序+收尾(8项)

- INDEX注册两份设计文档
This commit is contained in:
2026-07-01 21:30:58 +08:00
parent af2e085bea
commit 6833792de2
3 changed files with 315 additions and 21 deletions

View File

@@ -435,35 +435,76 @@
> 设计文档:[多Agent并行执行与仲裁合并设计-2026-07-01.md](docs/02-架构设计/专项设计/多Agent并行执行与仲裁合并设计-2026-07-01.md)
### Batch 37 — 数据层 + 并行执行
### 数据层 + Git worktree 隔离 + 并行执行
| # | 任务 | 文件 |
|---|------|------|
| 1 | V36 迁移(ai_plans/ai_subtasks/ai_conflicts 3 新表 + ai_messages/ai_tool_executions 加 subtask_id ) | migrations.rs |
| 2 | PlanRepo / SubTaskRepo / ConflictRepo CRUD | 新 repo 文件 |
| 3 | Coordinator.dispatch 改 JoinSet 层内并行(写 SubTask 降级串行) | coordinator.rs |
| 4 | Token 预算池(超限拒绝新 SubTask) | coordinator.rs |
| 5 | 子 Agent 独立 ContextManager + fork 快照(隔离上下文) | coordinator.rs |
| 6 | 4 个新事件类型(AiPlanCreated/AiSubTaskStatusChanged/AiMergeCompleted/AiConflictResolved) | AiChatEvent |
| 7 | PlanProgress 接入真实状态 + 发送即展示 | PlanProgress.vue |
| 8 | 工具卡按 subtask_id 折叠归组(带 persona 徽章) | MessageList.vue |
| 9 | 前端 PlanRecord/SubTaskRecord/ConflictRecord 类型 | api/types.ts |
| 1 | V36 迁移(ai_plans/ai_subtasks/ai_conflicts 3 新表 + ai_messages/ai_tool_executions 加 subtask_id + subtasks.branch + conflicts.conflict_type) | migrations.rs |
| 2 | PlanRepo / SubTaskRepo / ConflictRepo CRUD + models 结构体 | 新 repo 文件 |
| 3 | Git worktree 生命周期管理(create/commit/merge/remove) | 新 git_worktree.rs |
| 4 | Coordinator.dispatch JoinSet 层内并行(每 SubTask 绑 worktree) | coordinator.rs |
| 5 | Token 预算池(AtomicU64 CAS,超限降级串行) | coordinator.rs |
| 6 | 子 Agent 独立 ContextManager + fork 快照 + worktree_path | coordinator.rs |
| 7 | 层间 merge 到 plan 分支 + 下一层基于 plan 创建 worktree | coordinator.rs |
| 8 | 4 个新事件 + 事件双写(emit + publish_event) | AiChatEvent |
| 9 | 前端类型定义(PlanRecord/SubTaskRecord/ConflictRecord) | api/types.ts |
| 10 | PlanProgress 接入真实状态 + 发送即展示 | PlanProgress.vue |
| 11 | 工具卡按 subtask_id 折叠分组 + persona 徽章 | MessageList.vue |
| 12 | 编译警告清理(coordinator_plan unused / audit 子模块 unused imports) | 各文件 |
### Batch 38 — 仲裁合并 + UI 完善
### 仲裁合并 + 冲突 UI + 编译检查
| # | 任务 | 文件 |
|---|------|------|
| 1 | Coordinator.merge 冲突检测(按文件路径) | coordinator.rs |
| 2 | Reviewer Agent 仲裁(persona.rs 扩展) | persona.rs + coordinator.rs |
| 3 | 冲突 diff 展示 + resolution 按钮 | 新 ConflictResolver.vue |
| 4 | AiConflictResolved 事件闭环 | AiChatEvent |
| 5 | 技术债扫尾(编译警告 / unused import) | 各文件 |
| 1 | Coordinator.merge: git merge-tree 三方合并预检 | coordinator.rs + git_worktree.rs |
| 2 | 冲突检测:同文件路径(file) + 编译失败(semantic) | coordinator.rs |
| 3 | Reviewer Agent 仲裁(persona 扩展:读 diff → 推荐 resolution + 理由) | persona.rs |
| 4 | 合并产出落回主对话(可展开单条,默认折叠) | coordinator.rs + MessageList.vue |
| 5 | ConflictResolver.vue(git diff 展示 + resolution 按钮) | 新组件 |
| 6 | resolve_conflict IPC + AiConflictResolved 事件闭环 | AiChatEvent |
| 7 | 命令互斥锁(run_command 对同目录 npm/cargo 加 mutex) | audit/approval.rs |
| 8 | agentic/mod.rs 拆分(2222行 → 提取 compress/title/knowledge_inject 独立模块) | agentic/*.rs |
| 9 | AiChat 进度条补全(后端 AiAgentRound 补 max_rounds + 前端 completed 计数) | AiChat.vue |
| 10 | context.rs 拆分(1956行 → 提取 sanitize/budget/compress 独立模块) | context/*.rs |
### Batch 39-40 — P1 模板系统 + Git/CI(远期)
### 模板系统 + 节点补齐
1. YAML 模板加载器 + SubflowNode
2. GitNode(分支/PR/合并) + DockerNode(容器构建/测试)
3. 从模板加载工作流 → Git 分支 → 代码生成 → PR → CI 全链路
| # | 任务 | 文件 |
|---|------|------|
| 1 | YAML 模板格式定义(DagDef schema: nodes/edges/conditions/persona) | 新设计文档 |
| 2 | 模板加载器(YAML → DagDef 反序列化 + 校验) | df-workflow |
| 3 | SubflowNode(嵌套子工作流节点,递归调 Executor) | df-nodes |
| 4 | GitNode(分支创建/checkout/commit/merge,复用 git CLI) | df-nodes |
| 5 | HTTPNode(通用 HTTP 请求: GET/POST/PUT/DELETE) | df-nodes |
| 6 | NotifyNode(桌面通知 + Webhook: 飞书/钉钉/自定义) | df-nodes |
| 7 | 内置模板 3 个预设(代码审查 / bug修复 / 功能开发) | assets/templates/ |
| 8 | 前端模板选择入口(AiChat 输入框 /template 触发) | AiChat.vue |
| 9 | 模板 CRUD IPC + 前端管理 UI | 新模板管理页 |
| 10 | MessageList.vue 继续拆分(1386行 → 提取 StreamRenderer/ToolCardGroup/EmptyState) | MessageList.vue + 子组件 |
### Git/CI 集成 + DockerNode + God 文件收尾
| # | 任务 | 文件 |
|---|------|------|
| 1 | DockerNode(容器内构建/测试,CLI 模式起步: docker run/exec) | df-nodes |
| 2 | PR 创建链路(GitNode 创建分支 → 提交 → push → 创建 PR) | df-nodes + API |
| 3 | CI 状态读取(调 GitHub/Gitea API 读 PR check 结果) | 新 ci_status.rs |
| 4 | CI 状态面板(前端新组件展示 PR check 通过/失败/pending) | 新 CIStatus.vue |
| 5 | 全链路集成测试(模板加载 → 分支 → 代码生成 → PR → CI → 结果回显) | 集成测试 |
| 6 | ChatInput.vue 继续拆分(1155行 → 提取 MentionPopover/EnrichmentPanel) | ChatInput.vue + 子组件 |
### 审批政策 + 小程序完善 + 体验收尾
| # | 任务 | 文件 |
|---|------|------|
| 1 | 审批策略数据结构(Persona × Node × RiskLevel → Policy) | 新 policy.rs |
| 2 | 策略引擎(替代硬编码 auto_exec_mode 三档,支持细粒度规则) | policy.rs |
| 3 | 策略持久化(app_settings KV 或独立 policy 表 + 热加载) | migrations + repo |
| 4 | 前端策略配置 UI(设置页新增:规则列表 + 新建/编辑/删除) | 新 PolicyPanel.vue |
| 5 | 小程序 MentionInput 接真实数据(替换占位列表为真实技能路由/实体检索) | df-miniapp |
| 6 | 小程序长会话虚拟化(替代 MAX_RENDER_MSGS=200 截断,滚动入视口才 parse) | df-miniapp |
| 7 | 快捷键完善(Ctrl+N/Ctrl+R WebView2 实测 + 绑定决策) | AiChat.vue |
| 8 | ARCHITECTURE.md 状态同步 + 走查报告剩余项扫尾 | 文档
---

View File

@@ -87,7 +87,8 @@
| [项目知识图谱与任务队列系统-2026-06-26.md](./专项设计/项目知识图谱与任务队列系统-2026-06-26.md) | 📐 设计 | 项目级知识图谱 + 任务队列:依赖解析 / 优先级调度 |
| [工程系统设计-2026-06-29.md](./专项设计/工程系统设计-2026-06-29.md) | ✅ 已落地 | 项目多工程(Module) + Git 状态查询 + 文件浏览器 + Git AI 工具(只读3+写3) |
| [架构债迁移设计-2026-06-29.md](./专项设计/架构债迁移设计-2026-06-29.md) | 📐 设计草案 | #8/#15/#18/#19 架构债迁移路径(AI状态机抽离/IPC错误结构化/配置统一/连接池) |
| [多Agent并行执行与仲裁合并设计-2026-07-01.md](./专项设计/多Agent并行执行与仲裁合并设计-2026-07-01.md) | 📐 设计 | P0 Batch 37-38 实施依据:混合数据模型(messages加FK列+Plan/SubTask/Conflict独立表)、JoinSet层内并行、Reviewer仲裁、事件协议、UI交互(PlanProgress+工具卡分组+冲突徽章) |
| [多Agent并行执行与仲裁合并设计-2026-07-01.md](./专项设计/多Agent并行执行与仲裁合并设计-2026-07-01.md) | 📐 设计 | 混合数据模型(messages加FK列+Plan/SubTask/Conflict独立表)、Git worktree隔离、JoinSet层内并行、四层冲突防线、Reviewer仲裁、事件协议、UI交互 |
| [后续批次测试用例设计-2026-07-01.md](./专项设计/后续批次测试用例设计-2026-07-01.md) | 📐 测试 | 多Agent并行/worktree隔离/仲裁合并/模板系统/Git-CI/审批政策 的单元+集成+端到端测试用例 |
---

View File

@@ -0,0 +1,252 @@
# 后续批次测试用例设计 — 2026-07-01
> 覆盖:多Agent并行执行 / Git worktree 隔离 / 仲裁合并 / 模板系统 / Git-CI / 审批政策
> 关联:[多Agent并行执行与仲裁合并设计-2026-07-01.md](02-架构设计/专项设计/多Agent并行执行与仲裁合并设计-2026-07-01.md)
---
## 一、测试分层
| 层级 | 范围 | 工具 |
|------|------|------|
| **单元测试** | 纯函数/数据结构/repo CRUD | `#[test]` Rust / vitest TS |
| **集成测试** | 跨模块协作(dispatch+merge+worktree) | `#[tokio::test]` |
| **端到端** | 用户发消息→Plan→并行→合并→展示 | 手动 + 日志验证 |
---
## 二、数据层与并行执行 测试用例
### 2.1 V36 迁移
| ID | 场景 | 预期 |
|----|------|------|
| MIG-01 | 新库空跑 V36 | 3 新表 + 2 列 ALTER 成功,ai_plans 为空 |
| MIG-02 | 老库(有数据)跑 V36 | ai_messages/ai_tool_executions 加 subtask_id 列(NULL),原有数据不动 |
| MIG-03 | V36 幂等(重跑) | 不崩溃,版本号已写入直接跳过 |
| MIG-04 | 老库 ai_messages 有 100 条数据 | subtask_id 全部为 NULL,查询不报错 |
### 2.2 Repo CRUD
| ID | 场景 | 预期 |
|----|------|------|
| REPO-01 | PlanRepo.insert + get | 写入后能按 id 读回,字段完整 |
| REPO-02 | PlanRepo.update_status | planning→executing→done 状态流转正确 |
| REPO-03 | SubTaskRepo.insert + list_by_plan | 按 plan_id 查子任务,layer 排序正确 |
| REPO-04 | SubTaskRepo.update_status | pending→running→done 流转 |
| REPO-05 | ConflictRepo.insert + list_pending | 按 plan_id 查 resolution=pending 的冲突 |
| REPO-06 | ConflictRepo.resolve | 更新 resolution + resolved_by + resolved_at |
| REPO-07 | SubTaskRepo 查 branch=NULL | 非 Git 工程的 SubTask branch 为 NULL,查询正常 |
### 2.3 Coordinator 拆解
| ID | 场景 | 输入 | 预期 |
|----|------|------|------|
| DEC-01 | 读+写意图 | "先 read 文件再修改" | 2 SubTask(read→write),write deps=[read] |
| DEC-02 | 纯读意图 | "分析现有代码结构" | 1 SubTask(read),无 deps |
| DEC-03 | 纯写意图 | "implement new feature" | 1 SubTask(write),无 deps |
| DEC-04 | 兜底意图 | "你好" | 1 SubTask(default) |
| DEC-05 | 人设分配 | "review this code" | SubTask persona=reviewer |
| DEC-06 | Plan 非空 | 任意非空输入 | plan.tasks.len() >= 1 |
### 2.4 Git worktree 隔离
| ID | 场景 | 预期 |
|----|------|------|
| WT-01 | worktree 创建 | `.devflow/wt/{plan_id}/A` 目录存在,git branch `subtask/{plan_id}/A` 存在 |
| WT-02 | worktree 内 write_file | 写入落到 worktree 目录,主目录文件不变 |
| WT-03 | 同层并行隔离 | SubTask A 写 main.rs,SubTask B 读 main.rs → B 读到的是 fork 基点内容,非 A 的改动 |
| WT-04 | worktree commit | SubTask 完成后 git add+commit,分支有新 commit |
| WT-05 | worktree 清理 | Plan 完成后 `.devflow/wt/{plan_id}/` 目录被移除 |
| WT-06 | 非 Git 工程降级 | 无 .git 的工程 → branch=NULL,走串行,不崩溃 |
| WT-07 | worktree 创建失败 | 磁盘满/权限不足 → 降级串行,日志告警 |
### 2.5 并行调度
| ID | 场景 | 预期 |
|----|------|------|
| PAR-01 | 线性链(2层×1任务) | Layer0 done → Layer1 启动,总耗时≈串行 |
| PAR-02 | 并行层(1层×3任务) | 3 SubTask 并发执行,总耗时≈最慢的一个 |
| PAR-03 | 钻石依赖 | A→{B,C}→D,B/C 并行,D 等 B+C 都 done |
| PAR-04 | 层间隔离 | Layer1 的 SubTask 能读到 Layer0 merge 后的改动 |
| PAR-05 | 单 SubTask 失败 | 标记 error,不中断同层其他 SubTask |
| PAR-06 | 全部 SubTask 失败 | Plan.status=error |
| PAR-07 | SubTask 超时(120s) | 标记 error,其他 SubTask 不受影响 |
### 2.6 Token 预算池
| ID | 场景 | 预期 |
|----|------|------|
| TOK-01 | 预算充足 | try_reserve(10k) → true,consumed+=10k |
| TOK-02 | 预算超限 | consumed=98k,total=100k,try_reserve(5k) → false |
| TOK-03 | 并发 reserve | 2 个 SubTask 同时 reserve(CAS 竞争) | 只有一个成功 |
| TOK-04 | 超限降级串行 | 预算用完 → 剩余 SubTask 串行执行(不拒绝) |
### 2.7 事件协议
| ID | 场景 | 预期 |
|----|------|------|
| EVT-01 | AiPlanCreated | 前端 PlanProgress 立即展示 DAG 层结构 |
| EVT-02 | AiSubTaskStatusChanged | 节点状态从 pending→running→done 更新 |
| EVT-03 | AiMergeCompleted(无冲突) | 合并输出展示,无冲突徽章 |
| EVT-04 | AiMergeCompleted(有冲突) | 冲突徽章出现 |
| EVT-05 | AiConflictResolved | 冲突徽章消失 |
| EVT-06 | 事件双写 | emit 和 publish_event 都触发 |
---
## 三、仲裁合并与冲突 测试用例
### 3.1 Git merge 冲突检测
| ID | 场景 | 预期 |
|----|------|------|
| MRG-01 | 无冲突合并 | A 改 file1,B 改 file2 → merge-tree 无冲突 → git merge 成功 |
| MRG-02 | 同文件冲突 | A 改 main.rs 第10行,B 改 main.rs 第10行 → conflict markers 出现 |
| MRG-03 | 同文件不冲突区 | A 改 main.rs 第10行,B 改 main.rs 第50行 → git 自动合并成功 |
| MRG-04 | 跨层同文件 | Layer0 改 main.rs,merge 到 plan;Layer1 改 main.rs → 基于已含 Layer0 的版本,无冲突 |
| MRG-05 | 三方合并预检 | git merge-tree 返回非空冲突列表 → 不执行 merge,标记 conflict |
### 3.2 编译检查(semantic 冲突)
| ID | 场景 | 预期 |
|----|------|------|
| CMP-01 | 合并后编译通过 | cargo check exit 0 → 无 semantic 冲突 |
| CMP-02 | 合并后编译失败 | A 删函数 foo(),B 在调 foo() → cargo check 失败 → conflict_type=semantic |
| CMP-03 | 前端项目 | tsc --noEmit 失败 → semantic 冲突 |
| CMP-04 | 无构建工具的工程 | 跳过编译检查(无 cargo/tsc) → 不阻塞 merge |
### 3.3 Reviewer 仲裁
| ID | 场景 | 预期 |
|----|------|------|
| ARB-01 | Reviewer 推荐 A | diff_a 更完整 → resolution=a,resolved_by=reviewer |
| ARB-02 | Reviewer 推荐 merged | 两者各有价值 → resolution=merged,给出合并方案 |
| ARB-03 | Reviewer 无法判断 | 两者等价 → resolution=pending,留给用户 |
| ARB-04 | Reviewer 超时 | LLM 调用超时 → 自动降级为 pending |
### 3.4 冲突解决闭环
| ID | 场景 | 预期 |
|----|------|------|
| RSV-01 | 用户选接受 A | resolution=a,文件应用 A 的改动,B 的改动丢弃 |
| RSV-02 | 用户选手动 | resolution=manual,用户在 worktree 手动编辑后 commit |
| RSV-03 | 全部冲突解决 | Plan.status 从 merging→done |
| RSV-04 | 前端徽章更新 | AiConflictResolved 事件 → 冲突徽章消失 |
### 3.5 合并产出落回主对话
| ID | 场景 | 预期 |
|----|------|------|
| OUT-01 | 无冲突合并 | 主对话新增 1 条 assistant 消息(merged_output) |
| OUT-02 | 有冲突合并 | 主对话新增 1 条 + 冲突徽章 |
| OUT-03 | 展开查看子 Agent 轨迹 | 点击展开 → 从 ai_messages WHERE subtask_id=? 加载,按 SubTask 分组 |
| OUT-04 | 折叠状态默认 | 新消息默认折叠,只显示摘要 |
### 3.6 命令互斥锁
| ID | 场景 | 预期 |
|----|------|------|
| LCK-01 | 同目录 npm install 并发 | 第二个等第一个完成才执行(不并行) |
| LCK-02 | 不同目录 npm install | 并行执行(锁 key 含目录) |
| LCK-03 | cargo + npm 同目录 | 不互斥(锁 key 含命令名) |
---
## 四、模板系统 测试用例
### 4.1 YAML 模板加载
| ID | 场景 | 预期 |
|----|------|------|
| TPL-01 | 合法 YAML 加载 | DagDef 结构完整,nodes/edges/conditions 正确解析 |
| TPL-02 | 缺必填字段 | nodes 为空 → 报错"模板节点不能为空" |
| TPL-03 | 依赖闭环 | A→B→A → 报错"依赖存在环" |
| TPL-04 | 未知节点类型 | node.type="UnknownNode" → 报错"未知节点类型" |
| TPL-05 | 内置模板加载 | 3 个内置模板(代码审查/bug修复/功能开发)全部加载成功 |
| TPL-06 | 自定义模板 CRUD | 创建→读取→更新→删除,持久化到 DB |
### 4.2 SubflowNode
| ID | 场景 | 预期 |
|----|------|------|
| SUB-01 | 嵌套子工作流执行 | SubflowNode 加载子模板 → 递归执行 → 返回子工作流结果 |
| SUB-02 | 子工作流审批 | 子工作流内的 HumanNode 审批 → 挂起 → 恢复 |
| SUB-03 | 嵌套深度限制 | 超过 MAX_PLAN_DEPTH → 报错 |
### 4.3 新节点
| ID | 场景 | 预期 |
|----|------|------|
| NODE-01 | GitNode 创建分支 | branch_name 存在,git branch 列表可见 |
| NODE-02 | GitNode commit | 工作区改动已提交,git log 有新记录 |
| NODE-03 | HTTPNode GET | 请求成功,返回 body 存入 NodeOutput |
| NODE-04 | HTTPNode 超时 | 30s 超时 → 返回错误,不阻塞 |
| NODE-05 | NotifyNode 桌面通知 | 系统通知弹出 |
| NODE-06 | NotifyNode Webhook | POST 到飞书/钉钉,HTTP 200 |
---
## 五、Git/CI 集成 测试用例
| ID | 场景 | 预期 |
|----|------|------|
| CI-01 | DockerNode 构建成功 | docker run cargo build → exit 0 → 构建产物存在 |
| CI-02 | DockerNode 构建失败 | docker run cargo build → exit !=0 → 返回 stderr |
| CI-03 | PR 创建 | GitNode push → API 创建 PR → PR URL 返回 |
| CI-04 | CI 状态读取 | 调 API → 返回 check 结果(passed/failed/pending) |
| CI-05 | 全链路 | 模板→分支→代码→commit→push→PR→CI→结果回显,全流程不中断 |
| CI-06 | CI 失败时 | 前端 CI 面板显示红色,日志可查看 |
---
## 六、审批政策 测试用例
| ID | 场景 | 预期 |
|----|------|------|
| POL-01 | coder+Low → auto | 匹配规则 → 自动执行 |
| POL-02 | coder+High → approve | 匹配规则 → 走审批 |
| POL-03 | reviewer+任意 → auto | reviewer 只读工具,全部自动 |
| POL-04 | 无匹配规则 | 降级到 auto_exec_mode 三档(向后兼容) |
| POL-05 | 策略热加载 | 修改策略 → 下次工具调用立即生效(不重启) |
| POL-06 | 策略冲突检测 | 同一 Persona+Node+Risk 有多条规则 → 优先级最高的生效 |
---
## 七、God 文件拆分 测试用例
| ID | 场景 | 预期 |
|----|------|------|
| REF-01 | agentic/mod.rs 拆分 | 拆出 compress/title/knowledge_inject 后,原文件<800 行,cargo check 通过 |
| REF-02 | context.rs 拆分 | 拆出 sanitize/budget/compress 后,原文件<800 行,所有 context 测试通过 |
| REF-03 | MessageList.vue 拆分 | 拆出 StreamRenderer/ToolCardGroup/EmptyState,vue-tsc 通过 |
| REF-04 | ChatInput.vue 拆分 | 拆出 MentionPopover/EnrichmentPanel,vue-tsc 通过 |
| REF-05 | 拆分后行为不变 | 原有所有单元测试/集成测试全绿 |
---
## 八、端到端手动测试
| ID | 场景 | 步骤 | 预期 |
|----|------|------|------|
| E2E-01 | 简单并行任务 | 发"先读取 main.rs 再修改 utils.rs" | PlanProgress 展示 2 层,Layer0 读,Layer1 写,最终合并输出 |
| E2E-02 | 并行同文件冲突 | 发"同时重构 auth.rs 的两个函数" | 2 SubTask 并行改同文件 → 冲突徽章 → 用户选择 → 最终输出 |
| E2E-03 | 取消并行任务 | 发消息→Plan 执行中→点停止 | 所有 SubTask 停止,worktree 清理,Plan.status=error |
| E2E-04 | 切换会话后台执行 | 发消息→切换到另一个会话 | 原 Plan 后台继续,PlanProgress 在原会话保留 |
| E2E-05 | 非 Git 工程 | 在无 .git 的项目中发并行任务 | 降级串行执行,正常完成 |
| E2E-06 | 模板驱动全链路 | 选"功能开发"模板→AI 执行 | 从模板加载工作流→创建分支→写代码→测试→PR |
| E2E-07 | 长对话不崩溃 | 50+ 轮对话后发并行任务 | token 预算池正常,不 OOM,PlanProgress 正常展示 |
---
## 九、边界与异常
| ID | 场景 | 预期 |
|----|------|------|
| EDGE-01 | 空 Plan | decompose 返回空 Plan → 不启动 dispatch,主对话正常回复(退单 Agent) |
| EDGE-02 | 全部 SubTask 超时 | Plan.status=error,前端展示超时提示,worktree 清理 |
| EDGE-03 | Git 不可用 | git 命令失败 → 降级串行,日志告警,不崩溃 |
| EDGE-04 | DB 写入失败 | PlanRepo.insert 失败 → 降级不落库,内存态执行,日志告警 |
| EDGE-05 | worktree 磁盘满 | 创建失败 → 降级串行 |
| EDGE-06 | token 预算=0 | 设置项 df-ai-plan-token-budget=0 → 不限制(等价无限) |
| EDGE-07 | 冲突解决时会话删除 | resolve_conflict IPC 到达时会话已删 → 忽略,清理 conflict 记录 |