# DevFlow — 项目进展与工作交接

> 创建: 2026-06-10 | 最后更新: 2026-06-15 | 当前阶段: 全量待办编排完成(Sprint 23) → 首批 A+B 清债（ARC-02 死链已删 / AR-1 退役 / ARC-03 降级重评）；api_key 明文存储(FR-S1)降级延后

---

## 一、项目速览

| 项目 | 值 |
|------|-----|
| 定位 | AI 原生创作流程驾驶舱，从想法到创作成果的全流程管理 |
| 技术栈 | Tauri v2 + Vue 3 + TypeScript + Pinia / Rust Workspace (8 crate) / SQLite |
| 路径 | `E:/wk-lab/devflow/` |
| 架构文档 | `ARCHITECTURE.md` (22,745 字) |
| Git 状态 | 未首次 commit，代码全在 untracked |
| AI 能力 | df-ai OpenAI/Anthropic 双协议 Provider + 12 工具 + Agentic Loop |

---

## 二、代码规模统计

### Rust 后端 (78 个 .rs 文件)

| Crate | 文件数 | 总行数 | 有效行 | 实现程度 |
|-------|--------|--------|--------|---------|
| df-core | 4 | 429 | ~260 | ✅ 完整 — 错误/事件/状态枚举/ID生成 |
| df-workflow | 9 | 908 | ~620 | ✅ 核心 — DAG拓扑排序/执行器/状态机/事件总线 可用 |
| df-storage | 5 | ~2,100 | ~1,400 | ✅ 完整 — 连接/迁移/建表(V1-V8) + impl_repo! 宏 CRUD + KnowledgeRepo（search/list_by_status/set_embedding/search_vector 等）+ 余弦相似度工具函数 |
| df-execute | 5 | 203 | 129 | ✅ Shell 执行器真实可用（tokio::process，被 run_command 复用） |
| df-ideas | 7 | 761 | ~500 | ✅ 评分/对抗启发式已真实化（Sprint 9）— 捕获/评估/晋升/关联图 有逻辑，晋升/关联图仍骨架 |
| df-project | 5 | 272 | 175 | ⚡ 混合 — 数据模型/Timeline 可用，调度器 骨架 |
| df-ai | 9 | 1,965 | ~1,300 | ✅ 完整 — OpenAI/Anthropic 双协议 Provider + 流式 SSE + 上下文窗口(ContextManager 分组滑窗) + token usage 解析 + 12 工具 |
| df-nodes | 9 | ~500 | ~350 | ⚡ 混合 — script_node（接 Shell）/ ai_node（接 df-ai，Sprint 7）真实可用，human_node 半实现（审批响应 TODO），其余骨架 |
| **合计** | **53** | **~7,400** | **~4,800** | 已删除 5 个零引用 crate（2026-06-14，原 78/9100/5900） |

### 前端 (9 页面 + 2 组件 + Store + i18n)

| 类别 | 文件数 | 行数 | 状态 |
|------|--------|------|------|
| Vue 页面 | 9 | ~3,372 | ✅ UI 全部真实 — 无空壳（含 AiHome/AiDetached）|
| Vue 组件 | 2 | ~1,400 | ✅ AiChat（主面板）+ ConfirmDialog |
| Pinia Store | 4+ | ~800 | ✅ composable 模式，View 已引用（Sprint 4 接入）|
| Router | 1 | ~90 | ✅ 10 条路由含动态路由（Sprint 7 增 AiHome/AiDetached）|
| i18n | 2 | ~94 | ✅ 已注册 main.ts（Sprint 7）+ localStorage 持久化 |
| 设计系统 | 1 | 105 | ✅ CSS 变量/动画/Arco 暗色覆盖 |
| **前端合计** | | **~8,812** | |

> Tauri Commands 已达 **67 个**（src-tauri/src/lib.rs invoke_handler 注册数：project 14 / task 5 / idea 6 / workflow 5 / ai 19 / knowledge 14 / settings 4），见后端 src-tauri/src/commands/。

**前端关键问题**（Sprint 4/7 已全部解决）：
- ~~所有 View 组件数据硬编码~~ ✅ Sprint 4 接 Store 真数据
- ~~所有按钮事件处理函数为空函数~~ ✅ Sprint 4 接 Store action
- ~~i18n 插件未注册~~ ✅ Sprint 7 注册 + $t() 全 view 改造
- ~~Arco Design 组件库未实际使用~~ ✅ 已用（表单/弹窗/消息等），CSS 变量覆盖暗色

---

## 三、架构分层与依赖关系

```
真实可用路径（有端到端逻辑）:
  df-core (类型基础)
    → df-workflow (DAG 拓扑排序 + 执行器 + 状态机 + EventBus)
      → df-execute/shell (tokio::process Shell 执行)
      → df-storage (SQLite 连接 + 迁移 + 建表)

待打通路径（骨架就位，需填充）:
  df-workflow → df-nodes (8种节点 execute() 待实现)
  ~~df-workflow → df-stages (11种阶段节点 execute() 待实现)~~ — df-stages 已移除（2026-06-14 零引用清理）
  ~~df-ai → LlmProvider 实现~~ ✅ 已打通（OpenAI/Anthropic 双协议真实 HTTP，Sprint 5/8）
  ~~df-storage → 所有 crate 的 CRUD 操作~~ ✅ 已打通（impl_repo! 宏 CRUD + 多 Repo，Sprint 2）
  ~~Tauri commands → Rust 业务逻辑~~ ✅ 已打通（Sprint 3 时点 47 commands 全接业务；现 67）
  ~~Vue Views → Pinia Store → Tauri IPC → Rust~~ ✅ 已打通（Sprint 4）
```

---

## 四、全局性问题

| # | 问题 | 影响 | 优先级 | 状态 |
|---|------|------|--------|------|
| 1 | **无 CRUD 层** — df-storage 只有建表 | 所有 crate 无法持久化数据 | P0 | ✅ Sprint 2 |
| 2 | **Tauri IPC 未建** — 只有 greet 示例 command | 前端无法调用后端 | P0 | ✅ Sprint 3（17 commands） |
| 3 | **Store 未接入 View** — 两套独立硬编码数据 | 数据流断裂 | P0 | ✅ Sprint 4 |
| 4 | **AI Provider 无实现** — trait 定义完整但无 HTTP client | AI 功能全部不可用 | P1 | ✅ Sprint 5 |
| 5 | **同层节点未并行** — DagExecutor 有 TODO 注释 | 工作流执行效率 | P1 | ✅ Sprint 3（join_all） |
| 6 | **条件表达式引擎** — 仅支持 true/false 字面量 | 条件分支不可用 | P2 | ⬜ 待办 |
| 7 | **i18n 未注册** — 翻译文件存在但未挂载 | 多语言不生效 | P2 | ✅ Sprint 7 |
| 8 | **未 git commit** — 代码全 untracked | 无版本基线 | P0 | ✅ Sprint 2 |
| 9 | **AI 删项目绕过软删** — tool_registry:263 `repo.delete` 物理删，IPC 走 `soft_delete` 进回收站；AI 层缺 restore/purge/list_trash 工具（仅 project 表有回收站设计，故最该修） | AI 对话删项目 = 数据丢失不可恢复，与 UI 删语义割裂 | P1 | ✅ Sprint 21 已修（tool_registry 补 restore_project/purge_project/list_trash，delete_project 改 soft_delete） |
| 10 | **api_key 明文存储** — DB 落盘仍明文（migrations.rs:446 api_key TEXT NOT NULL） | 本地库被读/备份外流则泄露 | P0 | 🟡 部分修（FR-S1：IPC mask+编辑不回填✅ commit 49ac060；DB 明文落盘❌ 待迁移 keyring 单列） |

---

## 五、Phase 规划与当前进度

### Phase 1 — 引擎骨架 ✅ 完成

| 任务 | 状态 | 说明 |
|------|------|------|
| df-core 类型系统 | ✅ 完成 | 错误/事件/状态枚举/ID生成 |
| df-workflow DAG 引擎 | ✅ 完成 | 拓扑排序/执行器/状态机/EventBus |
| df-storage SQLite 基础表 | ✅ 完成 | 6 张表 + 4 索引，缺 CRUD |
| df-execute Shell 执行 | ✅ 完成 | tokio::process 实现 |
| 最小前端：项目列表 + 工作流日志 | ✅ 完成 | Sprint 4：5 页面接 Store + 创建/运行交互 |
| 验证：3 节点简单工作流 | ⬜ 待验证 | 后端就绪，需端到端跑通 |
| df-storage CRUD 层 | ✅ 完成 | Sprint 2：6 Repo + impl_repo! 宏；Sprint 3 增 BranchRepo |
| 对抗式评估系统 | ✅ 完成 | Sprint 6：AdversarialEngine + 正反方辩论 + AI 分析师 |
| Migrations V2（关联字段 + branches 表） | ✅ 完成 | Sprint 3 |
| Executor 同层并行 + 状态转换校验 | ✅ 完成 | Sprint 3，4 单测全绿 |
| Tauri IPC 命令 | ✅ 完成 | Sprint 3：17 commands + 事件转发 |
| Store 接入 View | ✅ 完成 | Sprint 4：API 层 + composable Store + 5 页面改造 |

### Phase 2 — AI 集成 ✅ 核心完成

| 任务 | 状态 | 说明 |
|------|------|------|
| df-ai Provider 实现 | ✅ | OpenAI 兼容 HTTP client，流式 SSE 解析 |
| AI 工具注册 + V3 迁移 | ✅ | AiToolRegistry + 12 工具（list/create/update/delete + 文件系统） |
| AI IPC 命令 | ✅ | 17 个 AI command（对话/工具执行/审批门控） |
| AI Chat 面板 | ✅ | 侧边栏 + 分离窗口 + 拖拽调宽 + 对话管理 |
| Agentic Loop | ✅ | 多轮工具调用循环（max 10 轮）+ 中/高风险人工审批 |
| AI Node 实现 | ✅ | df-nodes 接 df-ai：config 驱动 provider（base_url/api_key/model/prompt）→ OpenAICompatProvider.complete → 输出 text/model/usage；注册 "ai" 节点；未端到端实测 |
| **AI Chat LLM 优化** | ✅ ABCD 完成 | 任务 #43：P0 可靠性 ✅；P1 上下文窗口（ContextManager 分组滑窗）✅ + 并行化（工具 join_all / save 后台）✅；**Sprint 14 流式 token 用量记录（usage 解析 + 累加落库 + 展示 + Settings 开关）✅**；Part C 并发 Semaphore（双层 + 运行时可调）+ Part D Settings UI ✅（Sprint 16）；Review 两轮 8 修复 ✅ | |

### Phase 3 — 想法池 + 多项目 (3-4 周) | 🚧 进行中 — Sprint 9 评估闭环已通（启发式评分 + 对抗评估接 IPC），晋升前端层闭环，多项目/关联图待续；Sprint 12 全面审查修 5 项前端 bug（置信度条/状态选择/删除确认等），死代码组缓另会话重审
### Phase 4 — 节点丰富 + 阶段插件 (3-4 周) | ⬜ 未开始
### Phase 5 — 体验打磨 (4-6 周) | ⬜ 未开始

---

## 六、工作迭代日志

### [Sprint 1] 2026-06-10 — 项目初始化

**工作内容**：
- 创建项目骨架：`bun create vite` + Tauri v2 + Cargo Workspace
- 编写完整架构文档 `ARCHITECTURE.md` (22,745 字)
- 13 个 Rust crate 全部创建，类型系统和接口设计完整（2026-06-14 评审后删 5 僵尸 crate，现 8 crate）
- 9 个 Vue 页面 UI 全部编写（~3,372 行），设计系统完善
- 4 个 Pinia Store 定义（state + computed）
- i18n 中英文翻译

**代码规模**：Rust ~4,108 行 / Vue+TS ~3,896 行 / 总计 ~8,000 行

**遗留问题**：
1. 所有数据硬编码，无持久化
2. 前后端未桥接
3. 未做 git commit

**下一步建议**：
1. 首次 git commit 建立基线
2. 优先实现 df-storage CRUD 层（所有持久化的前置条件）
3. 实现 Tauri IPC 命令层
4. 将 Store 接入 View，替换硬编码数据
5. 端到端验证：3 节点简单工作流跑通

---

### [Sprint 2] 2026-06-10/11 — 设计审查 + 对抗论证 + 阻塞项修复

**工作内容**：
- 三路功能审查（架构/前端/数据模型）：发现 4 条核心路径全断、缺 10 张表、状态枚举三套不一致
- 三路对抗论证（市场/技术/需求"魔法打败魔法"）：综合结论 = 方向有价值、scope 必须砍 60%
- 修复 Phase 1 阻塞项：Shell Windows 兼容（cmd /C）、状态枚举统一（types.rs 为准）、DAG 序列化（DagDef + NodeRegistry）
- 实现 df-storage CRUD 层（6 Repo + impl_repo! 宏 + spawn_blocking + 列名白名单）
- ScriptNode 接入 df-execute Shell 执行器
- 建立 docs/ 8 层文档体系（中文命名）
- 新增设计文档：业务系统设计、对抗论证裁决报告、想法探索-对抗式评估

**关键决策（详见 docs/02-架构设计/对抗论证裁决报告.md）**：
- 定位调整："产研操作系统" → "本地优先的个人开发流程驾驶舱"
- 砍掉：插件系统、经验进化（自动）、需求-测试追溯、多模型路由、Agent 协作
- 降级：想法池（简化+对抗式评估）、标注（TODO 扫描器）、决策留痕（字段级）
- Phase 1 只激活 6 个 crate，其余 7 个标记预留
- 验证策略：先自用 3 个月再决定是否对外

**遗留问题**：
1. Executor 同层并行化 + StateMachine 转换校验（任务 #8）
2. Migrations V2 补字段（promoted_to/workflow_def_id/project_id 等）+ branches 表（任务 #9）
3. Tauri IPC / 前端 Store 对接尚未开始
4. Sprint 2 的代码变更未 commit

**下一步**：
1. commit Sprint 2 变更
2. Migrations V2 + Executor 并行化
3. Tauri IPC（AppState + project/task/workflow commands）
4. 前端类型对齐 + Store 接 View

### [Sprint 3] 2026-06-11 — Migrations V2 + Executor 并行化 + Tauri IPC（三代理并行）

**工作内容**（三个子代理并行，目录互不重叠）：
- **Migrations V2**（df-storage/df-core）：版本推进到 2 — ideas 补 promoted_to/ai_analysis/scores、tasks 补 workflow_def_id/base_branch、workflow_executions 补 project_id/task_id、新建 branches 表（含 2 索引）；BranchRecord/BranchRepo/BranchStatus 枚举同步落地，ALLOWED_COLUMNS 白名单 +8 列
- **Executor 并行化**（df-workflow）：同层节点改 futures::join_all 并发，三阶段模式（串行准备→并发执行→串行收尾）规避借用冲突；StateMachine 增加转换校验（仅 Pending→Running、Running→Completed/Failed 合法，set_xxx 改返回 Result）；4 个单测全绿（含并行耗时断言 <180ms、失败中止下游层）
- **Tauri IPC**（src-tauri）：AppState（db + 6 Repo + EventBus + NodeRegistry）+ 17 个 command（project/task/idea CRUD + run_workflow/list/get executions）；run_workflow 先落库 status=running 立即返回 execution_id，事件经 app.emit("workflow-event") 转发前端，完成后回写状态。注意：NodeRegistry 不能用 default()（script 工厂是 unimplemented! 占位），改为 new() + 手动注册真实 ScriptNode

**验证**：cargo check 通过（仅 1 个 dead_code 警告：releases/node_executions Repo 暂无 command 使用）；cargo test -p df-workflow 4 passed

**遗留问题**：
1. executor 失败路径只发 NodeFailed 不发 WorkflowFailed，目前由 run_workflow 在 IPC 层补发——后续应下沉到 executor
2. 前端 Store/View 仍硬编码，未调用任何 command
3. NodeRegistry::default() 的 unimplemented! 占位是隐患，应改为注册真实节点或移除

**下一步**：
1. 前端类型对齐（id: string、状态枚举对齐 types.rs）+ src/api/ 封装层
2. Store 加 action 接 API，核心 4 页面（Dashboard/Projects/ProjectDetail/Tasks）接 Store
3. 端到端验证：tauri dev 创建项目 → 运行 3 节点工作流 → 日志实时展示

### [Sprint 4] 2026-06-11 — 前端交互功能（API 层 + Store + 5 页面）

**工作内容**：
- **API 层**：新建 `src/api/` 目录 — types.ts（与 Rust Record 严格对齐）+ project/task/idea/workflow 四个 invoke 封装 + 事件监听（listen workflow-event）
- **Store 重写**：`stores/project.ts` 改为 composable 模式（reactive 全局状态 + 12 个 actions + computed stats），不依赖 Pinia
- **Projects.vue**：接 Store 真数据 + 创建项目模态框（名称/描述）+ 卡片点击跳详情页 + status 中文映射
- **ProjectDetail.vue**：路由参数加载项目 + 真实任务列表 + **3 节点 Shell DAG 工作流运行**（环境检查→运行测试→构建产物）+ 实时事件日志 + 创建任务模态框 + onUnmounted 清理监听
- **Tasks.vue**：项目/状态双筛选联动 + 创建任务模态框（选择项目+标题）+ 状态/优先级中文映射
- **Ideas.vue**：捕捉想法模态框 + 选中详情（tags JSON 解析、scores 展示）+ 删除功能
- **Dashboard.vue**：统计卡从 Store computed 计算 + Active Projects/Idea Pool 接真数据 + quickCapture 跳 Ideas

**代码变更**：13 files, +1059/-486

**遗留问题**：
1. 端到端验证未完成：需 tauri dev 实际创建项目→运行工作流→确认日志展示
2. 无数据时空状态展示较简陋
3. ~~Settings/Knowledge/Decisions 三个页面仍为硬编码 demo~~ ✅ Sprint 7 已解决（三 view 接 stores/{knowledge,settings}.ts，无 ref([ 硬编码）

**下一步**：
1. 端到端验证：tauri dev → 创建项目 → 运行 3 节点工作流 → 日志实时展示
2. 修复验证中发现的问题
3. 考虑 Phase 2 规划

### [Sprint 5] 2026-06-11 — AI Chat 全功能（Provider + 工具执行 + Agentic Loop）

**工作内容**：
- **df-ai Provider**：OpenAI 兼容 HTTP client，SSE 流式解析，ChatMessage/CompletionRequest 类型系统
- **V3 存储迁移**：ai_providers、ai_conversations、ai_tool_executions 三张表 + 对应 Repo
- **AI IPC 命令层**：17 个 command — 对话发送/流式推送、工具执行/审批门控（低风险自动/中高风险人工）、对话管理（CRUD + 切换）
- **AI 工具注册**：12 个工具 — list_projects/tasks/ideas（只读）、create_project/task/idea（创建）、update_project（更新）、delete_project（删除）、read_file/list_directory/write_file（文件系统）
- **Agentic Loop**：多轮工具调用循环（max 10 轮），流式输出→检测工具调用→执行→结果回传→继续，中高风险暂停等审批后恢复
- **AI Chat 前端**：侧边栏面板 + 拖拽调宽 + 分离独立窗口 + 对话列表管理 + 工具审批弹窗 + AgentRound 多轮消息
- **Tauri Capabilities**：ai-detached 窗口权限配置

**代码变更**：20+ files，新增 ~2000 行

**遗留问题**：
1. ~~空白屏问题：Vite 启动正常（122s）、HTML 200，但 webview 显示空白~~ ✅ Sprint 7 已修复（index.html 主题防闪烁脚本 + 启动计时埋点 __APP_T0 + body 背景色）
2. AI Node 未实现 — 目前只有骨架，需接入 df-ai 的 LlmProvider（任务 #44）
3. AI Chat LLM 调用逻辑待优化：长对话可靠性、大任务执行稳定性、token 消耗控制（任务 #43）— **P0 可靠性已在 Sprint 6 完成，P1 token 控制待办**

**下一步**：
1. 排查并修复空白屏问题
2. 实际验证 AI Chat 端到端（选 Provider → 发消息 → 工具调用 → 审批）
3. HumanNode + Settings 页面
4. AI Chat LLM 调用逻辑优化（任务 #43）
5. AI Node 实现（任务 #44）

### [Sprint 6] 2026-06-11 — AI Chat 调用可靠性 P0 + 前端类型修复

**工作内容**：

**A. AI Chat 调用可靠性 P0（df-ai + src-tauri，跨前后端 6 文件）** — 三路代理核对（调用链/上下文-token/前端）后定位可靠性死锁类问题，本轮按"先保命"只做 P0 五项（P1 token 控制设计已定，留待下轮）：
- **P0-1 连接超时**：`openai_compat.rs` Client 加 `connect_timeout(30s)` 防连接阶段无限 hang；不设总 timeout（避免 reqwest 总时长限制误砍流式长生成任务）
- **P0-2 流式 idle timeout**：`stream_llm` 用 `tokio::time::timeout(120s)` 包 `stream.next()`，防"连上后中途静默"无限 hang
- **P0-3 断连检测丢弃残缺**：维护 `finished_received` 标志，流尽未收到 finished 信号 → emit AiError + **丢弃残缺响应不当完整入库**（防脏历史污染）
- **P0-4 停止生成**：`AiSession.stop_flag: Arc<AtomicBool>` + 新 `ai_chat_stop` command + 前端停止按钮（streaming 时切换为珊瑚红方块按钮）；run_agentic_loop/stream_llm 多检查点响应，停止后保留已生成文本
- **P0-5 切对话防护**：`ai_conversation_switch` 生成中拒绝切换（防 active_conversation_id 被改导致旧 loop 的 save_conversation 串台写库）

**B. 前端既有类型错误修复（14 处，让 `bun run build` 通过）**：
- `types.ts`：删重复的 `WorkflowEventPayload`（declaration merging 冲突）
- `stores/project.ts`：补 `invoke` import + `payload.event.data` 类型断言 + **return 包 `reactive()` 自动解包 computed**（一处解决 Dashboard/ProjectDetail 的 store.stats/pendingApproval 解包，消费端零改动）
- `Ideas/Tasks/ProjectDetail`：去掉 `parseInt(number)` 误用 → `new Date(timestamp)`
- `ProjectDetail.vue`：删 unused `nextTick` import
- `AiChat.vue`：删死代码 `TOOL_STATUS_MAP` + `toolStatusLabel`

**C. AI Chat 代码审查修复（9 处，ai.rs + openai_compat.rs）** — 对 P0 代码做 /review 审查后修复，cargo check ✓：
- 🔴① `finish_reason="length"`（max_tokens 截断）纳入 finished — 修「大任务输出撞 4096 上限被误判断连、丢弃整段响应」（与 ④ 配合是本轮关键）
- 🔴② 路径校验最小加固：正斜杠→反斜杠规范化 + 拒 `..` 遍历 + 扩 `.aws`/`.gnupg`（根治 workspace 白名单 + canonicalize 待定边界后再做）
- 🔴③ tool_calls 按 index 排序（assistant 消息 line506 + tool_result line709 两处），消 HashMap 迭代乱序
- 🔴④ max_tokens 4096→8192，贴合大任务
- 🟡⑤ `ai_chat_stop` 在审批等待态清 pending_approvals + 复位 generating（原 stop_flag 无人读取，停止按钮表面无反应、会话卡 generating=true）
- ⚪⑨ 4 个 i18n 小函数（language_instruction/capability_section/behavior_rules/context_label）合并为 `system_prompt_parts`
- ⚪⑩ `extract_title` 单次 chars 遍历
- ⚪⑪ reqwest builder 降级加 `warn!`

**代码变更**：df-ai/openai_compat.rs、src-tauri/{commands/ai.rs, lib.rs}、前端 7 文件（+ C 轮 review：ai.rs、openai_compat.rs）

**验证**：cargo check -p devflow ✓（仅既有 warning）、vue-tsc --noEmit ✓、bun run build ✓（built in 2.47s）

**遗留问题 / 下一步**：
1. **P1 token 控制（任务 #43 续）**：流式 usage 采集（`stream_options:{include_usage:true}` + SSE usage 字段）+ token 预算自适应窗口（chars≈/3.5 启发式估算）+ 历史摘要压缩（早期摘要 + 近期全文）—— 设计已定，未实施。**⚠️ usage 采集 2026-06-11 用户叫停暂缓（结构层写一半已回退），P1 从 token 估算/裁剪/摘要续**
2. **实测验证**：`cargo tauri dev` 跑起来验证停止按钮/超时/断连真实生效（本轮仅编译 + 类型验证）
3. 停止生成边界：LLM 正常输出时停止立即生效（<1s）；idle（无输出）时最多等 120s idle timeout —— P2 可用 `tokio::sync::Notify` 优化为绝对即时
4. ~~Sprint 5 遗留的空白屏问题仍待排查~~ ✅ Sprint 7 已修复（用户实测确认）

### [Sprint 7] 2026-06-11 — 空白屏修复 + i18n 接入 + 剩余页面接 Store

**工作内容**：
- **空白屏修复**（前端）：`index.html` 加主题防闪烁脚本（localStorage `df-theme` 渲染前置 `data-theme`）+ 启动计时埋点 `window.__APP_T0` + body 背景 `#0c0e1a`；`main.ts` 加 `.use(i18n)` 并打印 mount 耗时日志。用户实测确认空白屏消失
- **i18n 接入**：`main.ts` 注册 `i18n` 插件；`i18n/index.ts` 完整（legacy:false / globalInjection / zh-CN 默认 + en fallback / localStorage `df-language` 持久化）；App.vue 导航与各 view 改 `$t()`
- **剩余 3 页面接 Store**：`Knowledge.vue`/`Settings.vue`/`Decisions` 去硬编码 `ref([...])`，对接新建 `stores/{knowledge,settings,ai}.ts`
- **新路由**：`/` redirect → `/ai-home`，新增 `AiHome.vue`（默认落地页）/`AiDetached.vue`（分离窗口）；路由 9→11 条
- **df-nodes 实现度修正**：核对发现 `script_node.rs` 早为真实实现（接 df_execute Shell + 非零退出码判断），`human_node.rs` 半实现（发 `HumanApprovalRequest` 事件 + 超时循环，但审批响应 TODO 直接返回"同意"）—— 非文档原记"全骨架"

**遗留问题 / 下一步**：
1. **P1 token 控制（任务 #43 续）**：仍待办（usage 采集用户叫停，从 token 估算/裁剪/摘要续）
2. **条件表达式引擎**（conditions.rs 仍 true/false 字面量）— P2 未动
3. ~~AI Node 实现（任务 #44）~~ ✅ 本轮已实现：`ai_node.rs` 接 df-ai `OpenAICompatProvider`，从 `ctx.config` 读 base_url/api_key/model/prompt/system_prompt/temperature/max_tokens 调 `complete()`，prompt 支持上游输入优先；`df-nodes/Cargo.toml` 加 df-ai 依赖；`state.rs` build_registry 注册 "ai"。cargo check ✓（未端到端实测真实 LLM 调用）
4. **df-stages** 11 个 execute() 全空骨架 — Phase 4
5. **HumanNode 审批响应闭环**：目前直接返回"同意"，需前端审批弹窗回写结果

### [Sprint 8] 2026-06-12 — Anthropic 协议 + 切对话不中断 + 技能联想需求调研

**工作内容**：

**A. aichat 升级 A 路线（UX 快赢，已实现并验证）** — 详见 memory `aichat-roadmap-ab-split`：
- **Anthropic 协议 Provider**：新增 `crates/df-ai/src/anthropic_compat.rs`，实现 `LlmProvider` trait 覆盖 Anthropic Messages API（`x-api-key` + `anthropic-version`、顶层 `system`、必填 `max_tokens`、SSE event 类型解析、`content_block` tool_use）。按 `provider_type` 路由分发（`run_agentic_loop` / `ai_node`）。支持 GLM 订阅端点 `https://open.bigmodel.cn/api/anthropic` — **用户实测对话流式 OK**
- **切对话不打断生成**：后端 `AiChatEvent` 全变体加 `conversation_id`，agentic loop spawn 前快照 conv_id，所有 emit 填充；`ai_conversation_switch` 生成中只读返回；前端 `stores/ai.ts` 按 conversation_id 路由（后台对话事件不污染当前视图，完成/错误时刷新侧边栏）
- **审查项落地**：删全屏 Tool Approval Modal（保留行内卡片审批）、错误友好化（`friendlyError` 正则映射 404/401/timeout/network → 中文提示 + `isError` 红色气泡）、智能滚动（`isNearBottom` < 80px 阈值）、provider bar 点击切换、未配 provider 空状态引导、删死 class
- **B 路线（规划式多智能体）单独立项**：填 `coordinator.rs` + `conditions.rs` 空壳，详见 memory `aichat-decision-capability`

**B. 技能联想功能（首批 Claude 3 类，已实现待实测）**：
- **需求**：aichat 输入框输入 `/` → 联想列出本机 Claude 技能（SKILL.md），按输入过滤，选中插入 `/name`；发送时后端读 SKILL.md 全文注入 system prompt / context
- **首批数据源 = Claude 3 类**（SKILL.md frontmatter 统一 `name` / `description` / `user_invocable` / `metadata.argument-hint` / `triggers[]`，只取 `user_invocable: true`）：
  1. Claude skills：`~/.claude/skills/*/SKILL.md`（23 个：sleep / mission-control / idea / cpa 等）
  2. Claude commands：`~/.claude/commands/*.md`（1 个：idea）
  3. Claude plugins：`~/.claude/plugins/marketplaces/**/skills/*/SKILL.md`（caveman 全家、官方 frontend-design / skill-creator / mcp-server-dev、wuming prompt-optimizer；`cache/` 与 `marketplaces/` 重复需按 path 去重）
  - 加项目级 `.claude/skills` + `.claude/commands`（DevFlow 暂无）
- **实现要点**：① 后端新 IPC `list_skills()` 扫 Claude 3 类来源解析 frontmatter + 按 path 去重，返回 `[{name, description, argument_hint, triggers, source}]`；② 前端输入框 `/` 触发联想浮层（名称 + description）；③ `/name` 发送 → 后端读 SKILL.md 注入 context；④ 跨平台 home 路径（dirs crate）

**C. 多工具 skill 体系调研结论（仅记录，后续按需扩展）**：
| 工具 | 本机状态 | skill 机制 | 是否纳入 |
|------|---------|-----------|---------|
| Claude Code | ✅ 已装 | SKILL.md（skills + commands + plugins 三类） | ✅ 首批数据源 |
| Codex (OpenAI) | ✅ 已装 | SKILL.md（`~/.codex/vendor_imports/skills/skills/.curated/*/SKILL.md`，39 个：figma / notion / playwright / security / vercel·netlify·render-deploy / latex 等；frontmatter 与 Claude 一致，可统一解析） | ⏳ 后续可扩展 |
| openclaw | ✅ 已装 | 多 agent gateway（`~/.openclaw/openclaw.json` 注册 8 agent 绑各 workspace + glm-5，经飞书 channel binding），非 SKILL.md；`agents/` 实体目录暂空 | ❌ 属 agent 选择层，非 skill 联想，暂不纳入 |
| opencode | ❌ 未装 | AGENTS.md + custom agents + slash commands（机制待确认） | ⏳ 待装后调研 |

**代码变更**：A 路线 — `crates/df-ai/src/{anthropic_compat.rs, lib.rs}`、`src-tauri/src/commands/ai.rs`、`crates/df-nodes/src/ai_node.rs`、`src/views/Settings.vue`、`src/stores/ai.ts`、`src/components/AiChat.vue`、`src/api/types.ts`

**遗留问题 / 下一步**：
1. **技能联想（B）已实现待实测** — `ai_list_skills` IPC（扫 skills/commands/plugins 三类 + frontmatter 解析 + name 去重）+ `ai_chat_send` 加 `skill` 参数读 SKILL.md 注入 system prompt + 前端 `/` 浮层（↑↓ 导航 / Enter·Tab 选中 / chip 显示 / Esc 关）。cargo check ✓（7 warning 既有）/ bun build ✓（4.68s）。实测：重启 dev → AiChat 输入 `/` → 选技能 → 发送
2. **A 路线剩余场景实测**：切对话不中断（场景 2/3）、错误友好化（场景 4）待用户实测
3. **B 路线（规划式能力）**：coordinator / conditions 空壳，单独立项

### [Sprint 9] 2026-06-12 — 灵感模块评估闭环（启发式评分 + 对抗评估接 IPC）

**工作内容**：
- **df-ideas 修复与真实化**：① 修 adversarial.rs E0308 类型错（`AdversarialEval.negative: Argument` vs `generate_negative_argument` 返 `CounterArgument` 直接赋值，df-ideas 实际编译不过——前文档"cargo check 通过"为误记）→ 删 CounterArgument、正反方归一 Argument；② scoring.rs 三维固定 5.0 → 内容启发式（priority / 描述充实度 / tags / 中英关键词，clamp 0-10）；③ adversarial.rs 正反方论点/evidence 基于真实 idea 内容生成，confidence 由评分驱动，final_score=综合评分，AssessmentLevel 由 overall 映射
- **devflow 接 df-ideas**：`src-tauri/Cargo.toml` +df-ideas +chrono 依赖（df-ideas 此前为孤儿 crate，devflow 未依赖、零 IPC 接入）
- **evaluate_idea IPC**（commands/idea.rs）：取 IdeaRecord → record_to_idea 转 df-ideas::Idea → ScoringEngine + AdversarialEngine.evaluate → 组装前端扁平结构（对齐 Ideas.vue AdversarialEval interface）→ 写回 scores（中文维度 0-100）/score（0-100）/ai_analysis/status=pending_review → 返回更新记录；lib.rs 注册
- **前端接真实评估**：api/idea.ts +evaluate；stores/project.ts +evaluateIdea action；Ideas.vue 删 mockEval 调真实 + evaluating loading 态
- **审核修 2 bug**：① recommendation 大小写（后端原 "With Resources" 与前端 assessmentLabel 全小写 map key 不匹配致中文标签不显示）→ 全小写空格；② assessmentClass 生成的 class 与 CSS 类名不一致致 badge 无色 → map 映射到 .immediate/.soon/.conditional/.revised/.defer/.cancel

**代码变更**：df-ideas/{scoring,adversarial}.rs、src-tauri/{Cargo.toml,commands/idea.rs,lib.rs}、前端 {api/idea.ts,stores/project.ts,views/Ideas.vue}（8 文件）

**验证**：cargo check -p df-ideas ✓、cargo check -p devflow ✓、bun run build ✓（vue-tsc + vite 3.3s）

**遗留问题 / 下一步**：
1. 对抗评估仍启发式，未接 df-ai LlmProvider（设计：LLM 生成正反方论点 + 启发式 fallback）
2. promotion.rs do_promote 仍 TODO（晋升走前端 createProject 闭环，不经 df-ideas/promotion）
3. evaluate_idea 用 list_all().find() + 5 次 update_field（IdeaRepo 无 get/多字段更新，量小可接受）
4. IdeaGraph 关联图零接入（自动关联发现/聚类待续）
5. scores JSON 含「综合」维度也被雷达图渲染一行（小瑕疵）

### [Sprint 10] 2026-06-12 — AiChat 工具卡片自动折叠（卡片级折叠 + 新内容追加自动收起）

**工作内容**：
- **需求**：对话中工具调用卡片（List Projects / List Tasks / Create Idea / List Ideas / 读取文件等）完成后仍整卡铺开，多步调用时界面臃肿。目标——展示更友好紧凑：所有卡片可点击 header 展开/收起，新内容追加时旧卡片自动收起为单行 header（类似 ChatGPT/Cursor 旧 tool call 折叠）
- **卡片级折叠**（区别于 read_file 已有的内容级折叠）：`.ai-tool-card` 内 body 区（骨架屏/审批/拒绝/file/dir/write/通用结果）包进 `.ai-tool-body`，`v-show` 控制显隐；header 加 `@click` + ▸ 箭头指示器；新增 `expandedCards` Set + `toggleCardExpand` + `cardCollapseClass`，与既有 `expandedTools`（read_file 预览级）职责分离不互相干扰
- **自动收起**：deep watch `store.state.messages` + 轻量 JSON snapshot diff 检测新内容（新消息 / toolCall 状态变化 / 文本增长）→ 清除旧 completed/rejected 的展开态，保留 running/pending 活跃卡片；`isFirst` guard 防首次加载/切对话误触发
- **running/pending_approval 强制展开**（需看骨架屏与审批按钮）；`v-show` 保留 DOM 避免重挂载

**代码变更**：`src/components/AiChat.vue`（template header/body 包裹 + script 状态与 watcher + style 折叠态），单文件 7 处改动

**验证**：vue-tsc --noEmit ✓（运行时待 `bun run tauri dev` 实测多步工具调用折叠效果）

**遗留问题 / 下一步**：
1. ~~审查项 ①~~ ✅ 已落地（2026-06-12）：`isRunningOrPending(status)` → `shouldKeepOpen(tc)`，`running` / `pending_approval` / `rejected` / `write_file` 强制展开（短结果不折叠、原因/路径不丢失），仅 `read_file` / `list_directory` / 通用 JSON 大体量结果折叠。vue-tsc --noEmit ✓。决策详见 [功能决策记录 - 短结果保持展开](docs/02-架构设计/功能决策记录.md)
2. 实测验证：tauri dev 发多步工具调用消息，观察"执行中展开→完成→新内容追加自动收起→点击 header 重展开"

### [Sprint 11] 2026-06-13 — AI Chat LLM 优化（上下文窗口管理 + 并行化）

**任务 #43 续**（Part A + B 落地，Part C/D 待续）

**工作内容**：

**Part A: 上下文窗口管理（df-ai/context.rs + ai.rs 接线）** — 长对话无限增长致 `context_length_exceeded` 死锁
- **A1 ContextManager**（`crates/df-ai/src/context.rs` 新增 ~350 行）：TokenEstimator 字符粗估（chars×0.35 + per_message 4 + per_tool_call 30，零依赖，保守 ±15%）+ ContextConfig（max_tokens 128k / output_reserve 8192 / safety 0.85）+ 分组滑动窗口淘汰——淘汰单元保工具调用三元组原子性（ToolCallHead + ToolResultTail* + 紧随文本 Assistant 同进同出），保护区最后 6 条永不裁；裁剪仅影响发送视图（build_for_request 返裁剪 Vec），不影响持久化（all_messages_clone 返全量）。5 单测全绿（短对话无裁剪 / 超预算裁剪保保护区 / 三元组原子性双分支 / replace 重估 token / restore 重建缓存）
- **A2 ai.rs 接线**（~15 处）：AiSession.messages 类型 `Vec<ChatMessage>` → `ContextManager`；核心 run_agentic_loop 用 `build_for_request(sys_tokens)` 替代全量 `.clone()`；save/title 用 `all_messages_clone()`；switch 用 `restore_from_messages()`；`replace_tool_result` 收敛为 ContextManager 方法（DRY，删自由函数）

**Part B: 并行化改造（ai.rs）** — 串行瓶颈 + Completed 事件阻塞
- **B1 process_tool_calls 并行化**：Low 风险工具 `futures::future::join_all` 并行 execute + 即时 emit Completed，结果串行回填 session.messages（N 个独立工具 ≈ 最慢一个耗时，原 N 倍串行）；Med/High 仍串行审批门控。tool_result push 顺序变化无语义影响（LLM 按 tool_call_id 关联，不看绝对位置）
- **B2 正常完成后台化**：save+extract+title 打包同一 `tauri::async_runtime::spawn`（非裸 spawn save——保 maybe_spawn_extraction 读已落库消息的顺序依赖）；Completed 事件即时下发
- **B3 标题后台化**：`ensure_conversation_title` 签名收 `provider_config` 克隆进 task 自建 provider（`&dyn` 非 'static 无法 move），`spawn_ensure_title` 后台（含 2 处 stop 路径）

**关键取舍**：①打包 spawn 而非裸 spawn save（保 extract 顺序依赖）；②并发 upsert 低概率丢少量 token 可接受（非功能错误）；③停止路径保持同步 save（避免 stop 后即发新消息的并发 upsert 竞态丢 token）

**代码变更**：`crates/df-ai/src/context.rs`（新增）、`src-tauri/src/commands/ai.rs`（核心改造）、`docs/02-架构设计/功能决策记录.md`（8 条新决策：Part A 2 + Part B 3 + 既有的）

**验证**：cargo check -p df-ai ✓（5 单测绿）、cargo check -p devflow ✓（6 既有 warning，无 error，无单测回归）

**遗留问题 / 下一步**：
1. **Part C/D 未做**（todo #48-52 已建）—— Part C 双层 Semaphore（global 默认 3 / per_conv 默认 2）+ 3 LLM 调用点（stream_llm / 标题 / 提炼）加 permit + `ai_set_concurrency_config` command；Part D Settings.vue 两 setting-row + localStorage 持久化 + onMounted 同步
2. **实测验证**（P1）：tauri dev 验证长对话裁剪行为 + 多工具并行耗时 + Completed 事件即时性

### [Sprint 12] 2026-06-13 — 灵感模块全面审查 + A 类问题修复

**工作内容**：

- **df-ideas 灵感模块全面审查**（前端 Ideas.vue / api / store + IPC idea.rs + crate 7 文件 + df-project/manager + df-storage/crud）：按「界面展示 / 交互 / 功能可用性 / 合理性」+「功能架构 / 代码逻辑 / 代码架构」六维逐条核对，共 12 项发现（🔴5 🟡5 ⚪2）。复核确认 12 项全部真实存在、无误判无虚报。
- **修复 A 类 5 项**（明确知道怎么做、零争议，全在 Ideas.vue）：
  - ① 置信度进度条不显示填充（`::after` 无 width + 锚点跑到 `.debate-column`）→ 拆 `.confidence-bar`（灰轨）+ `.confidence-fill`（填充层，正绿反红），删失效 `::after`
  - ② 状态 select 改选不生效（v-model 绑只读 computed 致写失败、回弹并写回旧 status）→ 弃 v-model，改 `:value` + `@change` 读 `event.target.value`
  - ③ 删 `filterIdeas` 空函数及其 `@input` 绑定（filteredIdeas 本是 computed 自动响应）
  - ④ 删除想法加 `confirm()` 二次确认
  - ⑥ 对抗评估标题加「启发式」tag（诚实标注当前为启发式非 LLM，避免「对抗辩论」措辞误导）
- **决策**：死代码/双套抽象组（⑦⑧⑨⑩）缓到另一会话，届时重新审核问题真实性；B 类（⑤⑥根治⑪⑫）方案未定，待定方向后再推。

**代码变更**：`src/views/Ideas.vue`（单文件 9 处：模板 5 + script 3 + CSS 2 段）

**验证**：`vue-tsc --noEmit` ✓（零错误零输出）

**遗留问题 / 下一步**：
1. **B 类（有必要但方案未定）**：⑤ 立项引导（三种改法改变产品流程语义：放宽显示条件 / 保持 approved 门槛加提示 / 评估达标自动 approved）/ ⑥ 对抗评估接 df-ai LlmProvider 根治（大工程，单独立项；当前 UI「启发式」标记为临时绕过）/ ⑪ 状态常量集中（跨 Rust+TS 双侧，IdeaStatus 枚举已有但 IdeaRecord 用 String 落库）/ ⑫ 实体↔Record 映射（评估为合理分层，建议不改）
2. **缓组（另会话重审真实性后再动）**：⑦ df-ideas 死代码空壳（capture/graph/evaluator/promotion；IdeaGraph 关联图是已知下一步增强需求，删/留需定）/ ⑧ 两套 Recommendation 枚举 + 两套评估入口并存（adversarial 6 变体实用 vs evaluator 5 变体仅死代码引用）/ ⑨ PromotionPolicy 三档死枚举 / ⑩ Idea 实体构造分散（record_to_idea 与 IdeaCapture::capture 字段重叠）
3. **实测验证**：tauri dev 看置信度条彩色填充 / 状态切换生效 / 删除弹确认 / 评估区「启发式」标

### [Sprint 13] 2026-06-13 — 文档记录治理体系（路由规范 + decision-record skill + 降频自检 hook）

**背景**：功能决策/需求散落于对话、PROGRESS、模块文档，缺统一真相源与触发机制。建立「单一真相源 + 自动自检」治理体系。

**工作内容**：
- **文档记录规范**（`docs/02-架构设计/文档记录规范.md` 新建）：核心原则（SSOT / 不复制只引用 / 决策与流水分离 / 先主后辅）+ 文档职责矩阵（每类信息唯一主文档）+ 内容路由表 + 更新顺序 + 唯一性记录与检测（记前 grep 查重 / 单向引用 / 定期扫描）+ 与 skill 关系 + 治理体系实现决策（hook 设计取舍）
- **功能决策记录扩展**（`docs/02-架构设计/功能决策记录.md`）：约定节加需求条目说明；末尾新增「需求与待办」总览（📋 待做需求表 + 需求澄清）——散落各决策条目 📐/🚧 状态的待办汇集为单一清单
- **decision-record skill 增强**（`~/.claude/skills/decision-record/SKILL.md`）：除「为什么这么定」决策，增记需求细节（待做/规格/澄清）；维护规则（记前查重 / 演进 `→` 标注 / 定期压缩防爆炸）；原则补「更新优先于新增」
- **降频自检 Stop hook**（`~/.claude/hooks/dr-check.sh` + `settings.json` Stop 配置）：累计 ≥10 轮 或 (>1 轮 且 距上次 ≥10 分钟) 才注入自检提示触发 skill；纯脚本计数无 API（替代每轮自检，省 ~90% token）；`stop_hook_active` guard 防循环；状态按项目隔离（`~/.claude/.dr-state/`，不污染 git）。设计取舍详见 [文档记录规范 - 治理体系实现决策](docs/02-架构设计/文档记录规范.md)
- **修 `docs/INDEX.md` 误登记**：PROGRESS 实际在根级，移除 `07-项目管理/` 树下的重复登记行

**代码变更**：非产品代码——`docs/02-架构设计/{文档记录规范.md,功能决策记录.md,INDEX.md}`、`~/.claude/{skills/decision-record/SKILL.md,hooks/dr-check.sh,settings.json}`

**验证**：hook 逻辑实测（首战静默初始化 / 2-9 轮静默计数 / 第 10 轮或 ≥10 分钟触发 / 防循环 guard）；无 jq 依赖纯脚本

**遗留问题 / 下一步**：
1. hook 实际长期触发频率待观察（10 轮 / 10 分钟阈值是否合理，按需调）
2. 决策爆炸后执行首次压缩（> 300 行 / 老 Sprint > 3 / 单域 > 10 条触发归档或拆域）

### [Sprint 14] 2026-06-13 — 流式 token 用量记录 + Provider 默认态持久化

**工作内容**：

**A. 流式 Token 用量获取 + 记录 + 展示 + 设置开关**（跨 df-ai/df-storage/src-tauri/前端，11 文件）— `stream_llm` 全程丢弃 token 计数、`AiCompleted.total_tokens` 恒 0 的旧疾根治（Sprint 6 P1 token 控制中「usage 采集用户叫停」项重启落地）：
- **Provider 层 usage 解析**：`StreamChunk` 加 `usage: Option<TokenUsage>`；OpenAI 开 `stream_options:{include_usage:true}` 末 chunk 取累计 usage；Anthropic `message_start`/`message_delta` 累积（output_tokens 当累计值覆盖，非增量）
- **累加落库**：`ai_conversations` 加 `prompt_tokens`/`completion_tokens` 列（V5 迁移）；`save_conversation` upsert 走累加模式（读旧值叠加，非覆盖——保审批暂停→恢复跨 loop 实例总用量正确）；`run_agentic_loop` 局部累加器每轮叠加
- **前端展示 + 开关**：store 双状态 `lastTokenUsage`（单次）+ `convTokenTotal`（对话累计，切对话从 DB 加载）；AI 气泡底部 token 条（默认关闭，`df-show-token-usage` 开关放 Settings）
- **model 记录**：消息级 model + 对话级 models 数组（C+B），取 `default_model` 配置值补填不覆盖

**B. Provider 默认态持久化（is_default 重启丢失 bug 修复）** — 「设为默认」重启后丢失、两条记录都显示「设为默认」按钮的 bug 根治：
- 根因：`is_default` 字段恒写 `false` + `ai_set_provider` 只改内存 session 不落库 → 重启 session 清零默认全丢
- 修复：`ai_set_provider` 互斥落库（目标 true/其余 false，仅写变化记录）；`ai_save_provider` 新建首个自动默认；`ai_list_providers` 直返 DB 值；`active_provider_id` 降为运行时缓存

**代码变更**：A — df-ai/{provider,openai_compat,anthropic_compat}.rs、df-storage/{models,crud,migrations}.rs、src-tauri/commands/ai.rs、前端 {types,stores/ai,components/AiChat,views/Settings}（11 文件）；B — src-tauri/commands/ai.rs（3 函数）

**验证**：cargo check --workspace ✓（0 error，6 既有 warning）、vue-tsc --noEmit ✓。**未 tauri dev 运行时实测**

**遗留问题 / 下一步**：
1. tauri dev 实测：token 落库 / 切换对话总量加载 / 重启保默认 / 首个自动默认
2. `ai_save_provider` get_by_id 双调用（review 🟡①，冗余往返，待合并）
3. Settings 页面 UI 重构（Part D，用户说稍后）
4. model UI 展示（暂缓）

### [Sprint 15] 2026-06-13 — 知识库 Tier 1 全栈打通 + Phase 5.5 向量检索

**工作内容**：

**Tier 1 知识库双向闭环（AI Chat ↔ 知识库，全栈打通）** — candidate→published 状态机 + AI 提炼 + 手动录入 + 知识注入：

**A. 存储层（df-storage，V7/V8 迁移）**：
- V7 建表 `knowledges`（id/kind/title/content/tags/status/confidence/reuse_count/verified/source_project/source_ref/created_at/updated_at），3 索引
- V8 幂等补列 `embedding BLOB`（PRAGMA table_info 探测，同 v4/v5/v6 模式）
- `KnowledgeRecord`（models.rs），含 `embedding: Option<Vec<u8>>`
- `KnowledgeRepo`（crud.rs）：`search()`（LIKE 双分支，按 kind 可选过滤）/ `list_by_status()`（CASE WHEN confidence 语义排序）/ `increment_reuse_count()`（SQL 原子 +1）/ `top_used()`；向量扩展：`set_embedding()` / `search_vector()`（纯 Rust 余弦批量比较，skip 维度不匹配）；工具函数：`f32s_to_blob` / `blob_to_f32s` / `cosine_similarity`

**B. 领域层（df-evolve）**：
- `KnowledgeStatus` 枚举（Candidate/PendingReview/Published/Archived，snake_case，`from_str`/`as_str`）
- `Confidence` 枚举（High/Medium/Low，同上）
- `Knowledge` struct：移除 `effectiveness` 字段，时间字段统一 String 毫秒（对齐全部既有 model）
- `pattern.rs`：清理死参数 `result_quality: f32`

**C. IPC 层（src-tauri/commands/knowledge.rs 新建，11 个 Command）**：
- `knowledge_{list,get,search,create,update_status,record_reuse,list_candidates,archive,get_config,save_config,extract_now}`
- 状态转换合法矩阵硬编码：candidate→{pending_review|published|archived}; pending_review→{published|archived}; published→{archived}
- `knowledge_archive`（软删除，匹配 `ai_conversation_archive` 语义）
- 配置读写：`knowledge_{get,save}_config`（读写 `AppState.knowledge_config: Arc<Mutex<KnowledgeConfig>>`）
- 手动提炼：`knowledge_extract_now`

**D. AI 集成（ai.rs，知识注入 + 提炼）**：
- `build_knowledge_context()`：`auto_inject` 开关 → `hybrid_search()` top-3 → `increment_reuse_count` fire-and-forget → 注入 system prompt 头部
- `extract_knowledge_from_conversation()`：后台 spawn，min_messages≥4 守卫 → 取最后 6 条消息 → LLM JSON 提炼 → 逐条写 candidate；提炼失败仅 warn 不阻断
- `maybe_spawn_extraction()`：agentic loop 两处正常退出统一调用（`OnComplete` 默认模式）

**Phase 5.5 — 向量检索（Settings 开关，默认关闭）**：
- `LlmProvider::embed()` trait 方法：默认返回 Err，openai_compat 实现 POST `/v1/embeddings`（按 index 排序）
- `KnowledgeConfig` 加三字段：`vector_enabled`（默认 false）/ `embedding_provider_id`（排除 anthropic）/ `embedding_model`
- `generate_embedding()`：截断 8000 字 → build_provider → embed()
- `spawn_embedding_for_knowledge()`：知识发布时 fire-and-forget 生成嵌入（不在 candidate 阶段浪费调用）
- `hybrid_search()`：三层降级链——开关关→LIKE; embed 失败→LIKE; 正常→双信号排序（同时命中>仅 LIKE>仅向量 cos≥0.3）；不引入 sqlite-vec（规避 Windows MSVC C 扩展编译风险）
- `Settings.vue`：语义检索开关 + v-if 联动 embedding provider 下拉 + 模型名输入

**E. 前端（TypeScript + Vue）**：
- `types.ts`：`KnowledgeRecord` / `CreateKnowledgeInput` / `KnowledgeConfig`（含 vector 三字段）
- `api/knowledge.ts`（新建，11 个 invoke 封装）
- `stores/knowledge.ts`（完全重写，getter 模式，消除全部 15 条 mock + localStorage）
- `Knowledge.vue`（完全重写：知识库/审核收件箱双 Tab + 状态徽章 + confidence 指示器 + 新增对话框 + 候选 badge）
- `App.vue`：侧栏候选 badge（`candidateCount` ref，store loadCandidates 后更新）

**F. 配置设计**（AppState 内存 + IPC，非 Tauri config 插件）：
- `KnowledgeConfig`（state.rs）：auto_extract / trigger_mode / min_messages / idle_timeout_ms / auto_inject / vector_enabled / embedding_provider_id / embedding_model

**代码变更**：df-storage（models.rs/crud.rs/migrations.rs）/ df-evolve（knowledge.rs/pattern.rs）/ src-tauri（state.rs + commands/knowledge.rs 新建 + commands/ai.rs + lib.rs）/ 前端（api/types.ts + api/knowledge.ts 新建 + api/index.ts + stores/knowledge.ts + views/Knowledge.vue + views/Settings.vue + App.vue）。约 1,400 行 Rust + 700 行 TS。

**验证**：cargo check 0 error ✓，vue-tsc 0 error ✓。**未 tauri dev 运行时实测**

**遗留问题 / 下一步**：
1. tauri dev 实测 10 项功能验证清单（手动录入 / 审核流 / 归档 / 检索注入 / reuse_count / AI 提炼 OnComplete / AI 提炼 Manual / 配置修改 / 注入开关 / 矛盾场景）
2. 向量检索待实测（需配 embedding provider + 开启开关 + 发布 ≥1 条知识后验证混合排序）
3. Tier 2 待做：ai_node prompt 注入 / 工作流 NodeFailed→pitfall / 决策记录→architecture_pattern（前置 traceability 持久化）
4. 知识库 API 对外暴露（MCP Shell 封装，外部工具 Claude Code/CodeX/Cursor 使用）

### [Sprint 16] 2026-06-13 — AI Chat LLM 优化收尾(Part C/D + Review 修复) + AI Node 单测

**工作内容**：
- **Part C LLM 并发控制**：`state.rs` 新增 `LlmConcurrency`(双层 `Arc<Mutex<Arc<Semaphore>>>` — 全局默认 3 / 单对话默认 2,运行时替换内层 Arc 重建);`ai.rs` 3 个叶子 LLM 调用点(stream_llm / generate_title / extract_knowledge)加 permit,acquire 顺序固定 global→per_conv 防死锁,stream 后显式 `drop` 不占工具执行槽;新增 `ai_set_concurrency_config` command(运行时调并发上限);`lib.rs` 注册
- **Part D Settings UI**：`Settings.vue` 通用设置区加「全局最大并发 / 单对话并发」两 setting-row + 前端 clamp(1-10 / 1-5)+ debounce 300ms + localStorage 持久化 + onMounted 启动同步 + onUnmounted 清 timer
- **Review 两轮 8 修复**：首轮 6(① per_conv 单例语义注释 / ② save-extract 并发注释改正 / ③ permit 显式 drop / ④ Settings clamp / ⑤ 合并 to_chat_messages 进 all_messages_clone / ⑥ system prompt 超 budget warn)+ 复审 2(后端 set_concurrency 补 clamp 边界对齐前端 / onUnmounted 清 debounce timer)
- **AI Node 单测**：`ai_node.rs` 重构抽 `parse_params` 纯函数(execute 参数解析剥离,单测不 mock LLM 零网络)+ 7 单测(缺参×3 / prompt 上游优先回退 / config 取值 / 可选默认值 / 显式参数解析)
- **任务收尾**：#43/#44 → completed(代码 + 单测全绿,GUI 实测转跟踪);新增 #54(GUI 动态实测跟踪任务)

**代码变更**：
- `crates/df-ai/src/context.rs`(Review ⑤⑥ — 合并 to_chat_messages / system prompt 超 budget warn)
- `src-tauri/src/state.rs`(LlmConcurrency 双层 Semaphore + per_conv 单例语义注释)
- `src-tauri/src/commands/ai.rs`(permit×3 + drop / process_tool_calls join_all 并行 / save 后台 spawn / ai_set_concurrency_config command + clamp)
- `src-tauri/src/lib.rs`(注册 ai_set_concurrency_config)
- `src/views/Settings.vue`(并发 UI + clamp + debounce + onUnmounted)
- `crates/df-nodes/src/ai_node.rs`(parse_params 重构 + 7 单测)
- `docs/02-架构设计/功能决策记录.md`(新增「AI Node」域记 parse_params 决策 + per_conv 退化条目)

**验证**：cargo check 0 error ✓ / df-ai context 5 单测 ✓ / df-nodes ai_node 7 单测 ✓ / vue-tsc 0 error ✓。**未 tauri dev 运行时实测**(转 #54 跟踪)

**遗留问题 / 下一步**：
1. **#54 GUI 动态实测**(用户跑 tauri dev,Claude 核对日志):长对话裁剪(context_trimmed 日志 + DB 全量)/ 多工具并行(Low join_all 时序)/ save 异步不阻塞 Completed / 双层 Semaphore 限流(多对话撞 RPM)/ Settings 并发即时生效 + 刷新保持 / DAG ai 节点真调 LLM
2. ~~AI Node 可补 GLM 集成测试~~ ✅ 已补并通过:`glm_live_complete`(`#[ignore]` + env var)真调 GLM glm-4-flash 返回"通过",usage 解析正确(provider 调用层验证;GUI DAG 触发仍属 #54)

### [Sprint 17] 2026-06-13 — 模块文档↔代码一致性审查(4 文档纠错补全)

**工作内容**:
- **审查范围**:docs/03 模块文档(df-ai / df-storage / df-workflow)+ docs/01 技术文档(SQLite-CRUD 模式)共 4 份 vs 对应 crate 代码,三代理并行审查
- **🔴 硬伤 28 全修**:df-ai(LlmProvider trait 签名 / 删 OpenAI 虚构 idle-timeout + finished_received / ContextManager 方法名 replace_tool_result_content + build_for_request 返回元组 / Token 公式 / Anthropic usage take() / 工具归属)/ df-storage(V1 表名 / Repo 表名 releases·workflow_executions / search published 过滤 / increment_reuse_count updated_at / cosine epsilon / blob 截断)/ SQLite-CRUD 整篇过时(表 6→11 / CRUD 待→已 / 时间 INTEGER→TEXT / 写返回 ()→String·bool / 连接池→单连接 / schema.rs→migrations.rs)/ df-workflow(Node trait 按值 + 默认 false + node_type / 文件名 conditions·eventbus / 虚构事件区分已发未发)
- **⚪ 虚构 7 全清**:df-workflow(阻塞节点「等待人工操作」标未实现 / 持久化快照删改仅内存态 / 断点续跑补无暂停恢复机制)/ df-ai(conditions.rs 不存在,清状态表 + 决策缺口表虚构引用 / AiToolRegistry「12 工具」夸大改基础设施)
- **🟡 核心 8 + 碎琐 10 补全**:df-ai(apply_openai_sse / apply_anthropic_event 纯函数 / ContextManager 6 pub 方法 / Anthropic 事件全集 / 文件结构 router·stream / URL 三分支 / finish=length / max_tokens 4096 / PROTECT_COUNT / budget 公式)/ df-workflow(NodeRegistry / DagDef / StateMachine / Dag API / NodeContext·NodeOutput 字段 / EventBus API / 条件引擎默认放行 warn)/ df-storage(list_non_archived / set_archived 例外对照)

**代码变更**:无(纯文档纠错,代码未动)

**验证**:每项修正均经代理 Read 代码复核签名/SQL/行为后改;git diff 4 文档落地(df-ai 443 / df-storage 134 / SQLite-CRUD 56 / df-workflow 122 行变动)

**遗留问题 / 下一步**:
1. 4 文档已与代码实质一致;后续若改 df-ai/df-storage/df-workflow 公开接口,需同步对应模块文档(文档治理:模块文档随代码变)
2. df-evolve(knowledge.rs / pattern.rs)本轮未审 — docs/03 无对应模块文档,若补可另起审查

### [Sprint 18] 2026-06-13 — 知识生命线(详情页 + 溯源 + 引用 + 生命周期)

**工作内容**:
- **根因**:知识库 candidate 卡片点不开详情、不能编辑、看不到"为什么产生";reasoning 字段被 prompt 要求但写库丢弃(bug);increment_reuse_count 只 +1 不记去向;无状态变更历史。用户要求呈现知识完整生命周期:产生→审核→引用→归档,且约束异步不阻塞、代码简洁易扩展。

**A. 存储层(df-storage,V10 迁移)**:
- V10:幂等补 `knowledges.reasoning TEXT` 列 + 新建 `knowledge_events` 审计表(id/knowledge_id/event_type/source_ref/context_json/timestamp + 3 索引)
- `KnowledgeRecord` 加 `reasoning: Option<String>`;新增 `KnowledgeEventRecord`(6 字段)
- `KnowledgeEventsRepo`(impl_repo! 宏 7 方法 + 扩展 `list_by_knowledge`/`list_by_knowledge_type`);5 处显式 SELECT 列列举 + from_row + insert/update body 全线接 reasoning

**B. 后端埋点(src-tauri)**:
- **新建 `commands/knowledge_timeline.rs`** — `KnowledgeTimeline` 独立记录器(持 Arc<Database>),便捷方法 record_extracted/referenced/status_change/created,内部 `fire()` 吞错误 fire-and-forget。各业务流程只调一行,不内联写 SQL(代码简洁约束)
- `extract_knowledge_from_conversation`:回填 reasoning(修 bug)+ 查对话标题 + insert 后记 extracted 事件
- `build_knowledge_context`:加 conv_id 参数 + spawn 块内 increment_reuse_count 后记 referenced 事件(conv_id+query);调用点上移 conv_id 快照
- `knowledge_create/update_status`:记 created/status_changed 事件(归档复用 status_changed,删 dead code EVENT_ARCHIVED/record_archived)
- 3 新 IPC command:`knowledge_get_detail`(聚合 knowledge+events)/`knowledge_update`(部分更新编辑)/`knowledge_events`(查生命线);AppState 加 `knowledge_events` Repo;lib.rs 注册

**C. 前端**:
- types.ts:KnowledgeRecord 加 reasoning + 新增 KnowledgeEventRecord/KnowledgeDetailPayload/UpdateKnowledgeInput
- api/store:各加 getDetail/update/getEvents
- **Knowledge.vue 全面重构**:Ideas 式左右分栏(左卡片列表 @click 选中 / 右详情四分区 — ①基本信息+编辑 ②溯源(产生方式/来源对话/AI reasoning) ③引用记录(复用次数+最近 N 条) ④生命周期时间线)。可编辑 title/content/tags/confidence

**关键决策**(详见 docs/02-架构设计/功能决策记录.md):① 独立 events 表非 JSON 嵌主表(引用数百次防行膨胀);② 独立 KnowledgeTimeline 记录器(不散落埋点);③ 归档复用 status_changed(防冗余);④ reasoning 回填(修 prompt 要求但丢弃的 bug)

**代码变更**:df-storage(migrations/models/crud)+ src-tauri(state/knowledge_timeline 新建/ai/knowledge/lib/mod)+ 前端(types/api/knowledge.ts/stores/knowledge.ts/Knowledge.vue)= 12 文件

**验证**:cargo check --workspace ✓(仅既有警告)/ vue-tsc --noEmit ✓ 零错误 / cargo test -p df-storage ✓ 21 单测全过。**未 tauri dev 运行时实测**

**遗留问题 / 下一步**:
1. **#54 GUI 实测**:AI 对话结束→提炼→收件箱→点详情看 reasoning+来源;发布→生命线 status_changed;新对话注入→referenced 事件;编辑 candidate→保存
2. 老库历史 candidate 无 reasoning/events,详情页降级展示(手动录入/无溯源)——属预期兼容
3. knowledge_events 纯追加表,长期可清理 >90 天 referenced 事件(本次不做)

### [Sprint 19] 2026-06-14 — list_directory 防爆 + localStorage→SQLite 统一持久化 + token/发送 bug 修复

**工作内容**:用户报多个 AiChat bug + 提需求:list_directory 扫出 13782 项塞爆对话;token 显示"0 in";发送卡住/留框;LLM 并发上限太小;localStorage 散落要统一入 SQLite。同时用户并行主导 ai.rs→ai/ + ai.ts→composables 模块拆分(我观察配合,不接管)。

**A. list_directory 递归防爆(Part A)**:
- `list_dir_recursive`(ai/tool_registry.rs)加噪音目录剪枝(`.git`/`node_modules`/`target`/`dist`/`build`/`.next`/`.cache`/`__pycache__`/`.venv`/`venv`/`.idea`)——**列出但不深入内部**;硬上限 1000 条 + `truncated` 标志;默认 max_depth 3→2;加 `skip_noise_dirs` 参数(默认 true,AI 看编译产物 dist/target 时传 false)
- 根因:AI 广扫项目根传 `recursive:true`,噪音目录铺平致 13782 项塞进对话 message(UI 卡 + token 爆)

**B. localStorage → SQLite 统一持久化(Part B)**:
- 新建 `app_settings` KV 表(V13 迁移)+ 手写 `SettingsRepo`(get/set/get_all/delete,不走 `impl_repo!` 宏因 KV 无固定 schema);4 IPC(settings_get/set/get_all/delete);AppState 加 settings 字段
- 前端 `appSettings` store(reactive 缓存 + 300ms debounce + `useSetting` ref)+ api 封装
- **11 key 迁移**:敏感 `df-connections` + UI 偏好(theme/language/ai-width/ai-ui/token/concurrency)+ `df-ai-active-conv`;**例外 `df-ai-gen`/`df-ai-text`**(流式临时快照,高频写留 localStorage)。App.vue onMounted 一次性迁移旧 localStorage

**C. Bug 修复**:
- **token prompt=0**:GLM 流式 usage 带 completion 不带 prompt → 加估算兜底(provider 返回 0 时按请求消息 `TokenEstimator::estimate_message` 求和)
- **发送卡住/留框**:`sendMessage` IPC 失败时无 catch → streaming 永真(光标卡死)+ handleSend 回填输入(消息已显示);改 try/catch 回滚 streaming + 清空气泡占位
- **LLM 并发上限**:三层(模板 max / JS Math.min / 后端 .clamp)全去上限,保留 min=1 + `per-conv ≤ global` 约束

**D. token 暴增诊断 + 清理**:
- 查 SQLite 实数据:对话 e4365d47 累积 in=115万 / out=2万 / 消息体 1.6MB
- 根因:**单条 list_directory 工具结果 1.2MB**(13782 项,Part A 修复前产生)落库后每轮重发 + save 累加 → 暴增;token 估算准,膨胀是真(非估算锅)
- 删除污染对话(`ai_conversations` 1 行 + `ai_tool_executions` 123 行)

**E. 模块拆分(用户主导,本会话发生,我配合不接管)**:
- `ai.rs`(2651 行)→ `ai/` 11 子模块(agentic/audit/commands/conversation/knowledge_inject/mod/prompt/skills/stream_recv/title/tool_registry),旧 ai.rs 删
- `stores/ai.ts`(749 行)→ 薄壳 + `composables/ai/*`(events/stream/send/conversations/window/panel)
- `df-evolve` crate 移除(workspace/代码零引用)
- 踩坑(glob 重导出命令宏符号 / super 路径失效 / 0 字节残留触发 E0761)已记入经验记录.md

**关键决策**(详见功能决策记录 / 经验记录):① list_directory 剪枝 + skip_noise 保留访问能力(定点查/强制递归两路通);② KV 表统一持久化复用 SettingsRepo(兑现经验记录预言);③ token 估算兜底(provider 不报时按消息估);④ 发送失败回滚 streaming;⑤ 并发去上限保 per-conv≤global

**代码变更**:src-tauri(`commands/ai/` 新模块 + `commands/settings.rs` + state.rs + lib.rs)+ crates/df-storage(migrations V13 + crud SettingsRepo)+ 前端(api/settings.ts + stores/appSettings.ts + App.vue/Settings.vue/composables/ai/* + i18n)≈ 25 文件

**验证**:cargo check ✓ / vue-tsc ✓ 零错 / tauri dev 启动 ✓ 运行;token/发送/并发/list_directory 已实测

**遗留 / 下一步**:
1. **Fix 1(待用户最终定)**:工具结果入库前截断 50KB(堵 `read_file` 1MB 洞 + 防御);Fix 2(放宽旧工具结果裁剪)因 Part A 已杀主源,延后不做
2. Settings.vue(1037 行)拆 panel 子组件——早前建议,用户已做 ai.rs,此件待评估
3. 诊断日志清理(handleEvent/approveToolCall 早期调试 console.log 残留)

### [Sprint 20] 2026-06-14 — 项目管理模块代码审查 + 全局核对（3-agent review 验证）

**工作内容**: 应用户要求审查「项目管理 / 项目导入 / 生命周期可用性」（后端 commands/project.rs + ai/tool_registry.rs + df-project/scan.rs + 前端 Projects.vue / ProjectDetail.vue）。先 3-agent 并行 review 出 15 项发现，剔幻觉 2 项（read_readme 命名误判 / conflict.name null 过度防御）后剩 13 项；再应要求**全局核对**（grep 全仓库 6 维度）确认每项发现是孤例还是系统性，保证全局成立有效。**本次仅审查 + 核对，未改代码。**

**验证结论**: 13/13 发现**事实全部成立**，无幻觉。4 处行号偏差（① 249→263 / ⑤ 113→136 / ⑫ 130→145 / ③ 未标→271）；2 处范围需补（⑧ 实 8 处非 3 处 / ③ 漏 relocate:212）。

**🔴 必须修复（3）**:
1. **AI delete_project 硬删绕过软删**（tool_registry.rs:263 `repo.delete` 物理 DELETE vs IPC project.rs:120 `soft_delete` 进回收站）—— 同一操作两种后果，AI 对话删 = 数据丢失不可恢复，UI 删 = 可恢复。**数据安全缺口**
2. **AI 缺回收站生命周期工具**（restore/purge/list_deleted 全无）—— ProjectRepo 有完整方法（crud.rs:572/591/610/634）+ IPC 全注册（project.rs:125-145），AI 层零覆盖，割裂工作流
3. **collect_sample 同步 IO 阻塞 async**（project.rs:271 在 async fn 内直接同步调 df-project::scan）—— 对比 scan_project_stack（:182）用了 spawn_blocking，不一致

**🟡 建议改进（6）**: ④ normalize_path 两份重复（project.rs:154 + tool_registry.rs:180）/ ⑤ update 白名单双份不同步（tool_registry:136 硬编码 vs crud.rs:287 allowed_columns，idea_id 字段不同步）/ ⑥ AI 扫描 + 目录状态文案硬编码未走 $t（Projects.vue:33/195 + ProjectDetail.vue:93）/ ⑦ parseStack 两份重复（Projects.vue:143 + ProjectDetail.vue:321）/ ⑧ 原生 alert/confirm（全局 8 处非仅 ProjectDetail 3 处，Ideas.vue:378/391 同病）/ ⑨ collect_sample 无文件大小预检（scan.rs:151/205 read 全文后截断）

**⚪ 可选（3）**: ⑩ LLM 无超时（project.rs:297 占 llm_concurrency permit 无限 await）/ ⑪ JSON 提取取首尾花括号（project.rs:368-369 多 JSON 场景错）/ ⑫ create_project 无 path 参数（tool_registry:145 需 create+bind 两步）

**全局核对关键定性**（6 维度 grep 全仓库）:
- **① 是 project 特例但最该修**: soft_delete/回收站机制**全仓库仅 project 一张表有**（task/idea/branch/release/workflow 本就物理删，无语义不一致）；正因 project 唯一设计回收站，AI 硬删直接击穿其数据安全设计
- **⑧ 系统性**: 全仓库 8 处原生弹窗（ProjectDetail 4 + Projects 2 + Ideas 2），非局部
- **③ 范围补报**: 不只 :271，relocate_project_path:212 同步 detect_stack 同样阻塞，3 处未包 spawn_blocking vs 1 处包了
- **src-tauri 层自身干净**: `std::fs` 同步调用零匹配，阻塞全在跨 crate 调同步的 df-project::scan
- **④⑤⑦ 精准**: 全仓库确为两份/一处，无更多副本；validate_path/resolve_workspace_path 是安全校验，职责不同非 normalize 重复

**未改代码**（待用户定推进批次）

**遗留 / 下一步（修复批次建议）**:
- **批1 数据安全**: ①（AI delete 改 soft_delete）+ ②（补 restore/purge/list_trash 三工具，复用 ProjectRepo 对应方法）
- **批2 阻塞 + 去重**: ③（:270/:271/:212 三处统一 spawn_blocking）+ ④（抽公共 normalize_path 到 df-project/df-core）+ ⑤（tool_registry 复用 allowed_columns_for）
- **批3 前端**: ⑥（补 i18n key）+ ⑦（抽 src/utils/project.ts）+ ⑧（全局 8 处 alert/confirm 换 Arco Modal）
- ⚪ 可选: ⑨⑩⑪⑫ 按需

---

### [设计] 2026-06-14 — B-03 人工审批响应机制设计

**工作内容**：df-workflow HumanNode 审批响应机制设计（B-260614-03）。勘察确认链路基础设施 90% 已通（EventBus broadcast / `HumanApprovalResponse` 事件 / `approve_human_approval` IPC / 前端 store 已接通），唯一缺口为 `human_node.rs:55` 发完请求直接 return "同意"。设计：订阅时序铁律（`subscribe()` 先于 `send(Request)`）+ `tokio::select!` 循环（响应 / 超时 / 取消）+ execution_id+node_id 双键过滤 + Lagged 容忍。澄清 B-06/B-07 前置真实影响（B-06=并发隔离，非单流功能前置；B-07=取消必要非充分），拆 **B-03a**（响应等待 + 超时）/ **B-03b**（取消机制：`set_cancelled` + cancel IPC + 前端按钮）。

**产出**：完整设计文档 [B-03-人工审批响应机制.md](./docs/02-架构设计/B-03-人工审批响应机制.md)；功能决策记录加「工作流人工审批节点（B-03）」摘要章节。

**下一步**：B-06（execution_id 下沉）/ B-07（共享 StateMachine）前置修复 → 落 B-03a 实现 → B-03b 取消机制补全。

### [Sprint 21] 2026-06-14 — Workflow 编排推进 Sprint 20 批次 + 审批闭环实施

**工作内容**: 以 workflow（实施 + 对抗验证两阶段，文件域隔离 + prompt 钉死约束）并行推进 Sprint 20 审查发现 + df-workflow 审批闭环。先 commit 基线 cf017f8（Phase2 阶段收尾 167 文件，排除无关的 `src-tauri/儿童每日打卡应用/`），后 A/B/C/D 四 workflow 各独立 commit 隔离可审。失控教训内化：workflow 确定控制流替代 background agent stop hook 循环，全程禁碰决策记录 + 禁自主续推。

**A 数据安全**（commit 3f0839a）: AI `delete_project` 由 `repo.delete` 物理删改 `soft_delete` + 新增 `restore_project`/`purge_project`/`list_trash` 三工具（复用 ProjectRepo 回收站方法）+ `list_projects` 改 `list_active` 排除回收站（验证捕的漏网：LLM 原能看到已软删项目）。tool_registry.rs。
**B 阻塞去重**（commit d5a6417）: `collect_sample`/`detect_stack` 四处 `spawn_blocking`（含验证捕的 bind_directory 漏网）+ `normalize_path` 抽公共到 `df-project/scan` + tool_registry `update_project` 复用 crud `is_allowed_column`（删硬编码白名单，与 CRUD 同源）。scan.rs/crud.rs/project.rs/tool_registry.rs。
**C 前端**（commit 02ff88f）: 扫描/目录状态文案走 `$t`（zh-CN+en）+ `parseStack` 抽公共 `src/utils/project.ts` + 8 处原生 `alert`/`confirm` 全换（confirm→ConfirmDialog / alert→Arco Message），控制流语义不变。vue-tsc 0 error。8 文件。
**D 审批闭环**（commit 22964a2）: B-06 DagExecutor 接收 `execution_id` 下沉 NodeContext（消除 dummy）+ B-07 `node_status` 共享 `self.state_machine.clone()` + B-03a HumanNode `execute` 重写 `subscribe→send→select!`（响应/超时/取消 + execution_id+node_id 双键过滤 + Lagged 容忍，照 B-03 设计）+ eventbus 删 `try_recv_human_approval` 死代码 + human_node 7 单测。executor.rs/workflow.rs/human_node.rs/eventbus.rs。

**验证**: cargo check 0 error / df-storage 32 + df-project 4 + df-workflow 11 + df-nodes 14 test 全过 / vue-tsc 0 error。A/B 各 1 issue（list_projects 泄漏 / bind_directory 漏网）主代理补修；C/D 验证 safe 0 issue。

**遗留 / 下一步**: B-03b 取消机制（`set_cancelled` + cancel IPC + 前端按钮）待做；T-09/T-10 非阻断记 todo；架构前置 df-ai-core（F-07）待设计解锁 F-03。

### [Sprint 22] 2026-06-14 — Wave1 收尾清债（workflow 推进 + 主代理补完 agent 半成品）

**工作内容**: Wave1 四任务并行 pipeline（实现 + Explore 对抗审查，文件域隔离），收尾 Sprint 21 遗留的 B-03b 审批取消机制 + 三个 P2 清债项。每个 Agent 钉死约束（只碰白名单 + 禁碰决策记录/构想文档 + 禁自主续推 + cargo check 自验）。

**B-03b 审批取消端到端**（commit 4aa689e）: agent 初版完成三件基础设施（`set_cancelled` + cancel IPC + 前端取消按钮）但留**半成品**——`workflow_cancel_state` 全局孤立 StateMachine 实例，IPC `set_cancelled` 写入后无法达运行中 HumanNode 的 `ctx.node_status`（executor.state_machine 的 clone，B-07 仅 clone 传递未共享底层 HashMap）。**Explore 审查 agent（无 Edit 权限，只验编译 + 白名单）漏抓此语义缺陷**。主代理补完：StateMachine 内部 `HashMap`→`Arc<Mutex<HashMap>>`（clone 即共享底层）+ AppState `workflow_state_registry`（execution_id→StateMachine）+ run_workflow 注册执行器状态机/完成清理 + cancel IPC 经 execution_id 取共享引用 `set_cancelled` 直达 HumanNode `is_cancelled` 轮询。`clone_shares` 单测验证共享语义。state.rs/executor.rs/state.rs(tauri)/workflow.rs/lib.rs/project.ts/ProjectDetail.vue。

**T-09 级联删**（commit 89da9fa）: idea.rs:149 `delete`→`purge_with_descendants`（防孤儿子记录），1 行签名兼容。
**T-10 canonicalize**（commit 89da9fa）: 判定已解决——`normalize_path` 已含 canonicalize 优先 + 词法回退，`find_binding_conflict` 两端对称已用，零改动。
**T-12 df-ideas 死代码**（commit 89da9fa）: capture.rs 删 `CaptureInput`/`IdeaCapture` 死码，保留 `Idea`/`IdeaScores` 共享实体；promotion/scoring/adversarial 内"两套 Recommendation/PromotionPolicy 死枚举"嫌疑未确认存在/保留为对外契约，本次未动待复查。

**验证**: cargo check 0 error / cargo test 全过（0 failed，含 `clone_shares` 新测）/ vue-tsc 0 error。

**教训**: workflow 对抗审查用 Explore agent 能防越权 + 验编译 + 验白名单，但抓不到"功能实际不工作"类语义缺陷（IPC 写了读不到、共享未通）——这类需主代理读实现逻辑复核，不能只信审查 verdict。

**遗留 / 下一步**: Wave2 候选 F-07（df-ai-core trait 下沉，解锁 F-03，需先定 trait 边界）；T-12 df-ideas 其余嫌疑项待复查。

### [Sprint 23] 2026-06-15 — 全量待办编排 + 首批 A+B 清债热身

**工作内容**: 全量 `todo.md`（~40 未完成项）汇总按可执行性分 8 组（A 卫生 / B 零风险减法 / C 需用户输入 / D 功能 / E 架构 / F 全局 review P2 / G 测试 / H 长期池），加「编排推进总览」章节供后续会话全局视图。首批推进 A+B 组。

**ARC-08 转自研块级 memo**（前会话遗留补记，待 commit）: 流式 Markdown 渲染——方案 D（markstream-vue）试装后样式还原成本高且脆（代码块 chrome / 暗色 `--ms-*` 变量 / prose 作用域 4 处对接随库漂移），转自研块级 memo（方案 B 增强版）：保留 marked+DOMPurify+.ai-md 原样式零对接 + splitBlocks 块级 memo O(末块) + rAF 节流 + 末块不缓存处理未闭合 token。退役 AR-1 流式纯文本短路。详见 [aichat流式Markdown渲染调研-2026-06-15.md](docs/02-架构设计/aichat流式Markdown渲染调研-2026-06-15.md) §5。

**A todo 卫生**:
- AR-1 标退役（被 ARC-08 取代）
- AR-8 重评：前端 rAF 已被 ARC-08 覆盖，剩后端 50ms 合批 + 滚动，降优先级
- ARC-03 降级重评：df-execute **非空壳**（shell.rs `execute()` 完整 + 被 `run_command` 复用），原「空壳合并」前提失效，转架构维护决策非清债

**B 清死链**（ARC-260615-02）: 删 App.vue secondaryNav `/decisions` 死链项（router 无此路由，决策治理 = F-260614-08 长期项入口提前占位）+ 删 `nav.decisions` i18n key（zh/en）。`dashboard.recentDecisions`（Dashboard.vue）不同命名空间保留。

**代码变更**: `src/App.vue` / `src/i18n/{zh-CN,en}/nav.ts` / `docs/todo.md`（编排总览 + AR-1/AR-8/ARC-02/ARC-03 状态回写）。

**验证**: vue-tsc EXIT=0。

**B-03b-R8 human 端到端集成测试**（待 commit）: human_node.rs 加 2 端到端测（`end_to_end_human_approval_completes_workflow` / `end_to_end_human_approval_cancelled`），覆盖 executor 驱动 a(SleepNode)→b(HumanNode) 两层 DAG 的 Request 真发出 + outputs 收集 + 双节点 Completed，以及外部 set_cancelled → human cancel_tick → executor 跳过 set_failed + 状态保持 Cancelled。封死 R6/R7 回归土壤。10 测全过（8 现有单测 + 2 新端到端）。

**遗留 / 下一步**: 下批方向三选一（D 功能增强 F-15-01~04 / E 架构重投入 F-14-01·07 / G 测试 dev 验证 ARC-08 + T-14-01·02）；C 组阻塞项（S-260615-01 curl 测 / S-260614-01 多开澄清）等用户输入。

### [Sprint 24] 2026-06-15 — P0 generating 状态机加固 + 独立项批量

**工作内容**: 多代理编排推进——P0 generating 卡 true 根治组合（B-09/10/11）串行 + 5 独立项 workflow 并行 + 3 项 read-only 勘察下一波。主代理全程核查（失控防护）。

**P0 三项**（generating 卡 true 根治，agentic.rs + commands.rs）:
- B-09: GeneratingGuard RAII（new/reset().await 幂等/Drop spawn 兜底）+ run_agentic_loop 入口实例化 + 5 处手动复位替换 + try_continue:318 保留手动（should_continue=false 须保 generating=true 待审批）
- B-10: ai_conversation_create 加 app:AppHandle（Tauri 自动注入）+ generating=true 软复位（记 old_conv→复位→清 pending→stop_flag→释锁→emit 零 token AiCompleted→relock 续建）+ 硬拦移除
- B-11: 两处 conv_id 一致性校验（循环顶部 + push 块内，防软复位后旧 loop 污染新对话）

**独立 7 项**（B-19 根因指针随 09~18 销账）:
- B-12: SessionState enum 视图（Idle/Streaming/AwaitingApproval）+ session_state() 读侧收敛（mod.rs，三调用点注释待后续替换）
- B-18: pending_approvals 单例设计文档注释（mod.rs）
- R-PD-4: keyring 迁移失败阈值告警（MIGRATION_FAIL_THRESHOLD=3 + sidecar 计数 + 达阈值升级 warn，secret.rs，不改兼容时序）
- R-PD-5: approve IPC 加 decision∈options 校验（⚠️半完成：前端 stores/project.ts:252 未传 options，校验形同虚设，待前端补传触发）
- R-PD-13: run_workflow Lagged 结构化 warn + 风险注释（workflow.rs）
- B-20: handleSend catch 加 reactive toast（AiChat.vue 复用 Settings 模式，文案待 i18n）
- B-21: sendMessage catch 一并回滚 user message（useAiSend.ts）

**勘察下一波**（read-only workflow wxflofhf2）: F-260615-02 TaskDetail（已完成核查通过：get_task_by_id IPC + /tasks/:id 路由 + TaskDetail.vue 11 字段 + 列表跳转，cargo check/vue-tsc 0 err）/ F-260615-04 ToolCard折叠（plan 11 步复杂+改核心 ai 文件+细节有误，拆小或留待）/ AR-11 数据联动（勘察 implPlan 含伪代码错误 std::env::var/.match，暂缓待重设计 emit 点）。

**代码变更**: agentic.rs / commands.rs / mod.rs / secret.rs / workflow.rs / AiChat.vue / useAiSend.ts。

**验证**: cargo check 0 error / vue-tsc 0 error / df-nodes 17 test pass（含 2 human 端到端测，P0 不破坏）。主代理独立核查（非 agent 自报）：git diff --stat 文件边界 + 编译复核 + R-PD-4 落地核查（agent 报告夸大称改 75 行实际在更早基线，功能存在即销账）。

**失控防护**: 每 agent prompt 锁死文件 + 禁碰决策记录 + 禁自主扩展 + 返回 schema。R-PD-4 agent 把已有代码当自己的（边界检查不准，非造假，同类 WF-G AR-7）。

**遗留 / 下一步**:
- R-PD-5 半完成：前端补传 options 触发新校验
- B-13~17 待续（stop 兜底/Notify 即时打断/heartbeat 提外/MAX_AGENT_ITERATIONS 配置化/key_len 复用）
- F-260615-02 TaskDetail 实施中（后台 agent）
- AR-11 暂缓（等本批提交后重设计 emit 点，audit.rs app_handle 可达性待核查）/ F-260615-04 拆小或留待

### [Sprint 25] 2026-06-15 — P0 收尾 + 下一波编排

**B-15/16/17 P0 收尾**（零行为变优化）:
- B-15: stream_recv.rs heartbeat interval 提到 loop 外（省每轮重建，节拍不变）
- B-16: agentic.rs MAX_AGENT_ITERATIONS pub(crate)→pub const + 配置接入点注释（无现成配置槽，未引入 AppState 字段）
- B-17: agentic.rs key_len 复用 resolve_provider_secret（去重复 keyring resolve，build_provider 内联因 secret.rs 锁边界，DRY 隐患注释标注等价性）
- 核查：cargo check 0 err / df-nodes 17 test pass

**下一波编排 workflow wcvigw3z4**（3 实施 + 4 勘察，循环链路）:
- 实施（文件隔离）：B-13 stop 兜底（commands.rs）/ R-PD-5 前端补 options 闭环（stores/project.ts）/ CR-05+07 块级 memo 低风险子项 parseBlock DRY + escapeHtml 抽（AiChat.vue，禁碰 splitBlocks/loadMarkdown 流式核心）
- 勘察 read-only（为下一波确定）：B-260615-22 状态同步两方案对比 / B-14 stop_flag→Notify 即时打断跨4文件设计 / F-260615-01 HumanNode 多选审批契约变更影响 / ARC-06 composables/ai 循环依赖拆点

**遗留 / 下一步**: 等勘察结果派下一波实施；AR-11 emit 点已查明（audit.rs process_tool_calls 有 app_handle）待本批提交后派；F-260615-03 breaking change / F-260615-04 需定交互 待用户确认；改动堆积（git diff 100+ 文件）建议择机提交收口。

<!--

### [Sprint N] YYYY-MM-DD — 简述

**工作内容**：
- 具体做了什么

**代码变更**：
- 修改了哪些文件/Crate

**遗留问题**：
- 1. ...

**下一步**：
- 1. ...

-->

---

## 七、开发约定

### 构建命令

```bash
# Rust 检查
cd E:/wk-lab/devflow && cargo check

# 前端开发
cd E:/wk-lab/devflow && bun run dev

# Tauri 开发（必须用这个，不能 cargo build）
cd E:/wk-lab/devflow && bun run tauri dev

# Tauri 构建
cd E:/wk-lab/devflow && bun run tauri build
```

### 关键设计决策

1. **引擎不绑定业务** — Workflow Engine 只做 DAG 执行，阶段是插件
2. **无 panic** — 所有占位代码返回空/默认值，不使用 `todo!`/`unimplemented!`
3. **本地优先** — SQLite 嵌入，不依赖云服务
4. **想法第一公民** — 想法池独立于项目
5. **多任务/分支并行** — 同一项目多任务各绑 Git 分支

### 复用资源

| 资源 | 路径 | 复用点 |
|------|------|--------|
| u-desk-rust Tauri 经验 | `E:/wk-lab/u-desk-rust/` | Workspace + crate 拆分 + Tauri v2 |
| Rust proxy 工具链 | `E:/wk-oth/rust-work/` | 连接管理，内嵌调用 |
| Tauri 开发铁律 | Memory: `feedback_tauri_dev_rules` | 必须用 `cargo tauri dev/build` |
