重构: AI流式断线保文StreamResult三分支+重试对齐决策a1,推进链落df-nodes
This commit is contained in:
47
docs/todo.md
47
docs/todo.md
@@ -41,6 +41,8 @@
|
||||
|
||||
**推进原则**:能并行不串行(独立子任务 8-12 并发);每批重汇总+全优先级重排+销账核对 ✅;C 组阻塞项不代办等用户。**本会话首批**:A 卫生 + B 清死链。
|
||||
|
||||
**③④C类已迁**(2026-06-16):需人工决策项(③产品取舍 7 / ④设计方向 7 / 重投入排期 9 / C用户实测 5)见 [待决策.md](./待决策.md),从本文件抽离职责分离。**batch54 可自主批进展(2026-06-16·workflow wsfz7zl8i + 主代核查)**:复核-新⑪ 看门狗幽灵 ✅ 销账(清主窗口 state 视觉残留;**核验更正**:原 watchdog 幽灵已被 CR-260615-24 stopListener:371 clearStreamWatchdog 兜底);AE-03 diff预览 ⚠️ 降级阻塞(后端 write_file 未返 diff,待后端补,见 line 538);UX-04 断线保文 待 DEC-260616-03 授权(见待决策.md 🟡,本批不含)。
|
||||
|
||||
### P0 — 阻断性 bug
|
||||
|
||||
- [x] B-260614-01 — ~~待审批持久化根治(重启恢复)未生效~~ ✅ mission:T-260614-01 已修复(commands.rs:444 clear→retain 保其他对话 pending;ai_approve 两处 if !recovered 守卫移除;cargo check 0 err / 19 test pass)(06-14)
|
||||
@@ -53,7 +55,7 @@
|
||||
|
||||
- [x] ✅(第㉖批 2026-06-16·主代理直修) B-260616-09 [P1] — **任务详情点击打开空白(路由漏注册)**。**router/index.ts 补 /tasks/:id → TaskDetail**(L50-54 新增块,6 行,参照 /projects/:id L39-43 + /ideas/:id L27-31 模式)。name 'TaskDetail' 无冲突(现有 name 集无此项),复用 icon-thunder(对齐 /ideas/:id 复用 icon-lightbulb、/projects/:id 复用 icon-apps 一致模式)。TaskDetail.vue 现挂载,Tasks.vue:57 router.push(`/tasks/${task.id}`) 不再跳未注册路由,B-18 联动刷新等功能激活(死代码转活)。改动极简确定(6 行路由表项),主代理直修省 workflow 单 agent 编排开销。vue-tsc exit 0。— src/router/index.ts
|
||||
- [x] ✅(第㉖批 2026-06-16) B-260616-10 [P1] — **provider 配置后 AI 面板仍提示「未配置」**。**Settings.vue loadProviders 同步刷全局 store**。L376 import useAiStore + L383 const aiStore = useAiStore()(跟随 L382 appSettings 风格)+ L420-424 loadProviders 内本地 aiProviders.value 刷新成功后 L424 await aiStore.loadProviders() 刷全局 state.providers(模块级单例 ai.ts:45,L20/L44 注释明确全应用共享同一份,AiChat 共享)。三处调用点(saveProvider L464/deleteProvider L479/setDefaultProvider L490)+ onMounted L731 均经 loadProviders 自动同步全局。无循环(useAiPanel.ts:91 loadProviders 只刷 state.providers 不回调 Settings)。无 i18n 改动(纯数据同步),try/catch + showToast 保留。vue-tsc exit 0。— src/views/Settings.vue
|
||||
- [ ] B-260616-11 [P2] — **AI 消息 `-`/`+` 列表/diff 无视觉效果**。marked 实测两个出口:①裸 `-`/`+` 混用 → GFM 要求同列表标记一致,marked 拆成**两个独立 `<ul>`** 且 `-`/`+` 被 eat 当 marker(用户看到的符号消失,两个分离单项列表);②```diff 代码块 → `<pre><code class="language-diff">` **无 hljs 高亮**(ai-md.css 未集成 highlight.js),`-`/`+` 字面纯文本无红绿。根因层 marked 行为合规,缺的是 **diff 高亮集成 + 裸 diff 文本识别**。改动(待定):①集成 hljs 覆盖 ```diff(关联已知待办「aichat交互体验改进方案-2026-06-14」2.2 代码块高亮)②裸 `-`/`+` diff 文本预处理识别。— src/composables/useMarkdown.ts + src/styles/ai-md.css。**②子项已修(第㉖批 2026-06-16·主代理直修)**:useMarkdown.ts L40-41 import diff + L63 registerLanguage('diff', diff)(16→17 语言),```diff 代码块经 highlightCode getLanguage('diff') 命中 → hljs-addition/deletion token class → github-dark.css 红绿。**①子项仍②类待复现**:裸 -/+ 文本预处理识别(需确认 AI 实际输出格式)。vue-tsc exit 0。
|
||||
- [ ] B-260616-11 [P2] — **AI 消息 `-`/`+` 列表/diff 无视觉效果**。marked 实测两个出口:①裸 `-`/`+` 混用 → GFM 要求同列表标记一致,marked 拆成**两个独立 `<ul>`** 且 `-`/`+` 被 eat 当 marker(用户看到的符号消失,两个分离单项列表);②```diff 代码块 → `<pre><code class="language-diff">` **无 hljs 高亮**(ai-md.css 未集成 highlight.js),`-`/`+` 字面纯文本无红绿。根因层 marked 行为合规,缺的是 **diff 高亮集成 + 裸 diff 文本识别**。改动(待定):①集成 hljs 覆盖 ```diff(关联已知待办「aichat交互体验改进方案-2026-06-14」2.2 代码块高亮)②裸 `-`/`+` diff 文本预处理识别。— src/composables/useMarkdown.ts + src/styles/ai-md.css。**②子项已修(第㉖批 2026-06-16·主代理直修)**:useMarkdown.ts L40-41 import diff + L63 registerLanguage('diff', diff)(16→17 语言),```diff 代码块经 highlightCode getLanguage('diff') 命中 → hljs-addition/deletion token class → github-dark.css 红绿。**①子项仍②类待复现**:裸 -/+ 文本预处理识别(需确认 AI 实际输出格式)。**batch58 可行性评估结论(2026-06-16·workflow w2dw65maz·Agent C 仅评估未改码)**:推荐**方案A**(renderMd/parseBlockNoCache 前 `wrapNakedDiff` 正则检测连续 ≥2 行 ±开头→包裹 ```diff 围栏,复用已就绪 hljs diff 红绿样式零额外 CSS);方案B(CSS ::before 注入)**否决**(marked 已 eat 掉原始 ±符号,li 内文本信息丢失无法区分);方案C(marked custom tokenizer)**否决**(侵入 marked 内部收益不优于 A)。守卫:纯 `-` 列表(普通 ul)不触发+必须含 `+` 行混排。**暂缓实施**:需求前提(AI 实际输出格式)未验证,不同 LLM 输出 diff 格式差异大(围栏/裸行/自然语言描述),盲目做可能解决不存在的问题;确认需求后 0.5 批次(~40-60 行+测试)。vue-tsc exit 0。
|
||||
- [x] ✅(第㉗批 2026-06-16·workflow) B-260616-19 [P2] — **知识库详情窄屏标题挤压成竖线(一行一字)**。三因子叠加(Knowledge.vue):①`.kn-layout` grid `grid-template-columns: 360px 1fr`(L567)——左列表死钉 360px、右详情 `1fr` 拿剩余,**无响应式断点**;窗口窄(如总宽 500px,减 padding 40+gap)详情列塌缩到 ~80px 甚至更小。②`.detail-title`(L625)`font-size:18px` + `word-break:break-word` —— 窄列里中文每字宽度 > 列宽,逐字换行 → 竖线化。③`.detail-actions`(L626)`flex-shrink:0` —— 编辑/发布/拒绝 3 按钮不缩,优先占位,把 `.detail-title-row`(`flex:1`) 挤到零头。`.kn-detail-panel`(L570-576) 无 `min-width` 兜底。改动(待定):①grid 列宽改 `minmax(240px,360px) 1fr` + `@media (max-width:760px)` 切单列(`grid-template-columns:1fr`,列表详情上下堆叠);②详情面板加 `min-width:0` 配合标题行 `min-width` 防塌缩;③可选标题字号响应式降级(18px→15px)。— src/views/Knowledge.vue。**低风险纯 CSS**,无逻辑/i18n/数据变动。
|
||||
|
||||
### 💡 2026-06-16 新需求(已分析·待实施)
|
||||
@@ -68,7 +70,23 @@
|
||||
|
||||
- [x] ✅(batch42·2026-06-16·workflow w95hzp9tw) F-260616-04 [P1] — **run_command 超时→LLM 重试→反复审批循环**。已根治(tool_registry.rs 超时标注「勿盲目重试」+ DEFAULT_RUN_COMMAND_TIMEOUT_SECS 常量,handler map_err 改写)。根因链(探索确认):超时(默认 60s, `tool_registry.rs:491 unwrap_or(60)`)→tool_result 回传 LLM(`commands.rs:168` Err 分支)→LLM 重试同命令→**新 tool_call_id**(`stream_recv.rs:176` 每轮新 UUID)→重新 insert pending(`audit.rs:343`)→重新审批,循环。症状「再过一会又提示 Run Command」即此。修复方向:①超时 tool_result 明确标注「命令执行超时({n}s),进程已终止,勿盲目重试同命令;确需更长时限重发时提高 timeout_secs」②run_command 默认超时可配(LLM 已可传 `timeout_secs` 参数,但默认 60 + 不主动调)③配合 F-260616-05 去重根治。— tool_registry.rs(超时标注) + commands.rs(回传内容)。
|
||||
- [x] ✅(batch53·2026-06-16·workflow wbh8mu1iq·**run_command 循环核心解决**) F-260616-05 [P1](**共性根治**)— **agentic loop 工具调用去重缺失**。**batch53 落地 High risk 审批前去重**(audit.rs find_cached_high_risk_result 反向扫 messages + args JSON 规范化匹配 + 排除 pending 占位 + decided_by=auto_dedup,解决 run_command 反复审批循环,F-04 超时标注 + batch53 去重双保险)。**完整 agentic loop 通用去重(search_files 重复卡片 + 滑动窗口指纹 + 决策点)③类待用户定**(窗口/粒度/措辞)
|
||||
- [ ] F-260616-06 [P2] — **「未找到挂起的审批」体验**。根因:后端 `pending_approvals` 内存态(`commands.rs:130 remove None` 报错)与前端刷新/重复点击不同步;重试场景旧 id 已被处理。前端 `useAiSend.ts:221` IPC 失败不回滚 pendingApprovals,按钮残留。修复方向:①`ai_approve` 找不到 pending 时查审计表,若已 executed/rejected 返回「已处理」幂等成功(非报错) ②前端审批按钮点击防抖(同一 id 短期多次只发一次 IPC) ③前端刷新后 pending 态正确同步(已部分由 `useAiConversations.ts:119 pendingToolCalls` 恢复,核对边界)。— commands.rs(ai_approve 幂等) + useAiSend.ts(防抖)。
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) F-260616-06 [P2] — **「未找到挂起的审批」体验**。**全闭环落地**:①`commands.rs:217` ai_approve 幂等——内存 pending_approvals remove None 时查 `ai_tool_executions` 审计表,已 executed/rejected/failed 返回「已处理({status})」非报错 ②`useAiSend.ts:305` 审批按钮防抖——`_pendingApprovalIds` Set 守卫,同 id 短期多次点击只发一次 IPC,finally 块清理。— src-tauri/src/commands/ai/commands.rs + src/composables/ai/useAiSend.ts
|
||||
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) F-260616-07 [P2] — **流式对话失败自动重试**。**全闭环落地**:①`agentic.rs` stream_llm 调用处包重试循环(max_retries 形参,退避 1s→2s→4s,持 permit 防挤占) ②每重试 emit `AiStreamRetry` 事件(attempt/max_attempts) ③耗尽走原有 guard.reset+return ④state.rs 加 `agent_max_retries:Arc<AtomicUsize>`(默认3) ⑤新 IPC `ai_set_agent_max_retries`(clamp 0-10) ⑥前端 api/ai.ts + types.ts(AiStreamRetry variant) + Settings.vue(input 0-10+debounce sync+i18n zh/en)。**设计决策**:一律尝试重试(简化策略,由退避控制成本),MidStream 重试语义等价于"看不到完整回复再试一次"。— src-tauri/src/commands/ai/agentic.rs + state.rs + commands.rs + lib.rs + src/api/ai.ts + types.ts + src/views/Settings.vue + src/i18n/{zh-CN,en}/settings.ts
|
||||
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) F-260616-08 [P2] — **AI 数据获取工具 offset 分页 + 探总量**。**全闭环落地**:①6 工具(list_projects/tasks/ideas/trash/read_file搜索模式/search_files)全部补 offset+limit 参数,返回 items/total/has_more 替代 truncated ②新增 `get_project_count`+`get_task_count` 探总量工具 ③knowledge_search 解钳 `min(3)`→`min(20)`。— src-tauri/src/commands/ai/tool_registry.rs + src-tauri/src/commands/knowledge.rs
|
||||
|
||||
- [ ] F-260616-09 [P1/架构] — **AiSession 单例 → 多会话并发架构(多窗口来回切 + 并行执行)**。用户需求(3 条消息强化):「应用级支持同时具备多会话」+「同时具备多会话的能力」+「多个会话窗口来回切,**并行执行**」。现状(Explore 走查确认):`AiSession` **应用级单例**(`state.rs:164` `ai_session: Arc<Mutex<AiSession>>`,init:205),messages/generating/stop_flag/pending_approvals/agent_language 全一份。设计「单例 + 软隔离」——generating 互斥(同一时刻**只一个对话能跑**) + 切换旧 loop 退出(`agentic.rs:177-190` B-260615-11) + 切换时 generating→readonly(`commands.rs:873-881`)。`llm_concurrency` per_conv 因此退化为单对话内并发(`state.rs:93-96` 注释已标注预留改 HashMap)。**memory 已标记「AiSession 单例未动」架构债**(aichat-arch-extensibility)。**残留 bug**(表象=新建会话上下文残留):前端 `newConversation`(`useAiConversations.ts:31-41`) 漏清 queue/generatingConvId/agentRound/searchQuery;后端 `ai_conversation_create`(`commands.rs:784-821`) 漏清 agent_language/stop_flag(设 true 停旧 loop 没复位 false)。**用户「并行执行」明确=B 方向**(A 只解切换残留不满足并行)。**分档**:**A 短期隔离修复**(补漏清字段,维持单例软隔离,解残留,低风险立即做,**B 前置**) + **B 多会话并发架构**(单例 → `HashMap<conv_id, SessionState>`,每会话独立 messages/generating/stop_flag/pending_approvals + llm_concurrency per_conv 改真 per-conv HashMap + loop 内校验改 conv_id 索引各自 session + 切换不退出旧 loop 各自跑完真并发 + 事件路由核对 conversation_id 全覆盖)。**决策点(待定)**:(a) A 先做解燃眉 vs 直接 B——倾向 **A 先**(残留真 bug 立即解,B 架构另立项) (b) B 形态——AiSession 整体 HashMap vs 拆字段(messages/pending 已可按 conv reload,只拆 generating/stop_flag per-conv)——倾向**后者侵入小** (c) B 并发上限——复用 llm_concurrency.global 限并发会话数防 token 暴增——倾向是 (d) **多窗口 UI 形态**——(d1) 单面板侧栏会话列表切换+后台并行(改动小) vs (d2) 每会话独立 Tauri 窗口(`useAiWindow.ts` detached 已有基础可扩,改动大但「窗口来回切」语义最贴)——**待用户定**,倾向先 d1 后 d2 (e) 旧 loop 切换处理——不退出各自跑完(真并发,倾向) vs 仍退出。— state.rs(AiSession 去单例化) + commands.rs(create/switch 重构 + 漏清补) + agentic.rs(:177-190 校验改 conv_id 索引) + context.rs(ContextManager per-conv) + useAiConversations.ts(漏清补) + stores/ai.ts(per-conv state) + llm_concurrency per_conv + useAiWindow.ts(若 d2 多窗口)。**B 是大改架构升级,需单独设计文档 + 立项**。**待用户定 A 先做 / B 立项 / 多窗口 d1·d2 方向**。
|
||||
|
||||
- [x] ✅(batch58·2026-06-16·workflow w2dw65maz+主代核查,vue-tsc 0err) F-260616-10 [P1·bug] — **provider 切换/默认值重启·刷新后失效(前端 activeProvider 不同步 DB 默认)**。用户实测:Settings 设 A 为默认 → 重启 → 默认变 B(列表第一个)。**根因全在前端,后端链路正确**(独立核验不信 PROGRESS.md:「已修复」声明不可信):`ai_set_provider`(`commands.rs:747-774`) 互斥落库✅ + `update_full`(`crud.rs:1127`) SQL UPDATE 含 `is_default`✅ + `get_active_provider`(`prompt.rs:9-32`) 走 `DB.is_default`✅。**根因链**:①重启后前端 `store.activeProvider = null`(`stores/ai.ts:53`,无 localStorage 持久化 + 无启动恢复) ②`loadProviders`(`useAiPanel.ts:91-93`) 只拉列表**不同步 DB 默认** → activeProvider 仍 null ③**UI 错觉**:`activeProviderName`(`AiChat.vue:1169-1172`) null 时 fallback `providers[0]`(列表第一个) ≠ 用户设的 A → 「默认变另一个」 ④**真覆盖**:用户点 provider bar 切换 `cycleProvider`(`AiChat.vue:1180-1185`),`findIndex(activeProvider=null)` 返回 **-1** → `next = ps[(−1+1)%len] = ps[0]` = 列表第一个 B → `setProvider(B)` → 后端互斥落库把 `DB.is_default` 从 A **真改成 B**。即使用户不点切换,UI 也显示 providers[0] 而非 A。**修复方向**:①`loadProviders` 后同步 `activeProvider` = DB.is_default 的 provider——后端加 `ai_get_active_provider` IPC 返回当前默认 id,或 `listProviders` 返回值带 `active_provider_id` ②`cycleProvider` findIndex=-1 陷阱修正(null 时应从 DB 默认起算,非 ps[0]) ③前端 activeProvider 持久化(localStorage `df-ai-active-provider`,对齐 `df-ai-active-conv` 模式)。— useAiPanel.ts(loadProviders 同步默认) + AiChat.vue(:1169 activeProviderName fallback + :1180 cycleProvider findIndex 陷阱) + commands.rs(新 ai_get_active_provider IPC) + api/ai.ts + stores/ai.ts(activeProvider 持久化)。**确定性 bug,低风险,可立即修**。
|
||||
|
||||
- [ ] F-260616-11 [P1/设计风险] — **审批后 iteration 重置致 max_iterations/token 超配**。性能分析批次发现:`try_continue_agent_loop` 重新 spawn `run_agentic_loop`,**iteration 从 0 重计**(`agentic.rs:418` 注释,F-260616-03 续跑决策 a 的延续,审批续跑复用此入口)。每次审批(Med/High 工具)后配额重置,多次审批=反复重跑 max_iterations 轮,实际可跑远超配额,**token 消耗不受 max_iterations 严格控制**。影响:长对话多次审批致 token 失控 + 对话变慢(每审批一次重跑 LLM 轮次)。**方向(待评估)**:①审批不重置 iteration(累计计数)②审批是用户决策点重置合理但需独立「审批次数」配额 ③至少 token 总量兜底。— agentic.rs(try_continue iteration 计数策略)。**需决策**:iteration 累计 vs 重置。
|
||||
|
||||
- [ ] F-260616-12 [P2/依赖F-09] — **retry 持 permit 不释放(多会话隐患)**。F-260616-07 落地的流式重试循环(`agentic.rs:238-239`)重试期间持有 global+per_conv permit 不释放(注释「防新请求挤占」)。当前 AiSession 单例 + 主 loop 串行无影响,但 **F-260616-09 多会话并发后**,重试期间阻塞其他对话 LLM 调用。**方向**:多会话落地时核对——主 loop 串行下重试持 permit 防自己挤占无意义,倾向重试不持 permit 或仅持 per_conv。— agentic.rs:238 + F-260616-09 多会话架构。**依赖 F-260616-09 立项后一并处理**。
|
||||
|
||||
- [ ] F-260616-13 [P2/小优化] — **build_for_request 持锁重活 + system_prompt token 每轮重估**。性能分析批次发现:每轮 `stream_llm` 前 `session_arc.lock()`(`agentic.rs:251`)持锁期间做 `TokenEstimator::estimate_text(system_prompt)`(L252)+ `build_for_request`(L253 history clone + 裁剪)。system_prompt loop 外固定传入,**每轮重估其 token 是浪费**(可缓存);build_for_request 持锁做 history clone 是重活,消息多时(200 cap)锁持有期长。**方向**:①system_prompt token loop 外算一次缓存 ②build_for_request 先 clone messages 释放锁再裁剪。低收益优化。— agentic.rs:251-253。
|
||||
|
||||
- [x] ✅(主代核验·2026-06-16) F-260616-14 [P2/核验] — **max_tokens 8192 截断 + 前端批量审批核验**。核验结论:①`max_tokens=8192`(实际 `agentic.rs:270`,行号漂移)≈6-8k 字日常够用,长回复截断由 batch59 MidStream 保文兜底不丢文,**可配低优先非阻塞**(登记可选优化)②前端批量审批 **AE-2025-01 已完整闭环**(ToolCardList.vue:4-11 `ai-batch-approve` 栏 + AiChat.vue:444 `@batch-approve`→`store.batchApprove` + useAiSend.ts:338 遍历 pendingApprovals 逐个 approveToolCall + i18n approveAll/rejectAll),满足「一轮多 Med/High 全 insert pending→一次批量批全部」③audit.rs:496 `process_tool_calls` 一轮多工具 Med/High 进审批门控 insert pending + Low 并行执行链路通。无阻塞 bug,销账。— agentic.rs:270 + ToolCardList.vue + audit.rs:496。
|
||||
|
||||
### 🔧 任务模块全栈核对(2026-06-16 · Explore 代理并行取证)
|
||||
|
||||
@@ -127,11 +145,14 @@
|
||||
> **审查发现待修项(2026-06-16 · CR-08/10/13,均 med 非阻断,详见 [待审查.md](./待审查.md) 对应归档)**:
|
||||
- [x] ✅(batch50·主代理决策:接受现状降级 P2) **CR-10-A** [med] ai_regenerate 并发竞态窗口 → **统一并发模型**(锁内变更+锁外 spawn,ai_regenerate/ai_chat_send/ai_chat_force_send 同款),窗口有兜底(stop_flag 置位 loop 退出 + generating 拦截 send),med 非阻断。统一并发改造复杂(原子标记预占+3 入口),ROI 不明非优先,降级观察/架构改进候选
|
||||
- [x] ✅(batch50·主代理核查:无效) **CR-10-B** [med] commands.rs:56/59 save 与 emit 时序倒置 → **不成立**:ai_regenerate 当前代码 save L94 锁外 spawn L105 前(时序正确),无 emit(L56/59 是 pop 后错误处理),审查锚定行号漂移
|
||||
- [ ] **CR-13-O1** [产品决策点·非代码bug·③类待用户] in_progress 模板失败→`regression_target("in_progress")=Some("todo")`,但状态机 `backward_to_todo_rejected` 全拒(task_state_machine.rs:188-193)→ 回调 advance_task_atomic 被 InvalidState 拦截(task_advance_node.rs:72-77),任务原地保留 in_progress。**三选项待定**:a 接受现状补 UI 提示 / b 改 `regression_target("in_progress")=None` 对齐状态机 / c 放开 todo 回退(破坏闸门)— CR-260616-13 归档
|
||||
- [x] ✅(batch55·2026-06-16·workflow wem402ncv+主代核查) **CR-13-O1** [产品决策→已决b实施] regression_target("in_progress")→None 对齐状态机。workflow.rs:51 `in_progress => None`(替原 Some("todo"))+task_advance_node.rs 镜像同步+4 测试断言更新(含集成测改 None-skip 场景)。**主代核验**:git diff 2 文件 26+/24- 双处一致+注释对齐决策b理由+cargo test -p df-nodes 67/67 pass。— src-tauri/src/commands/workflow.rs + crates/df-nodes/src/task_advance_node.rs
|
||||
- [x] ✅(batch50·2026-06-16·workflow w6nqio4o5) **CR-08-O1** [med·非阻断] blocked 态推进按钮语义偏差 → 已修复(WF_EXCLUDED_FROM={'blocked'} + wfAdvanceAction computed 守卫,blocked 不显示工作流推进按钮,其他态不受影响,不动 ADVANCE_MAP)
|
||||
- [x] ✅(batch50·2026-06-16·workflow w6nqio4o5) **CR-15-1** [med] `crates/df-execute/src/shell.rs:60-79` 缺 `.kill_on_drop(true)` → 已修复(cmd.kill_on_drop(true) 三类型覆盖 + 注释配合 tokio::time::timeout 防孤儿,文案「进程已终止」名副其实)
|
||||
- [x] ✅(主代理验证:不成立·workspace cargo check exit 0) 🔴 **CR-23-1** [high·紧急·阻断构建] `crates/df-ai/src/context.rs:491` E0594 → **不成立**:审查代理跑 batch51 中间态 filter 版(EXIT 101),batch51 最终改 for 循环(EXIT 0,df-ai + workspace 双验证,代理自报属实)。context.rs:488 当前是 `for t in iter_mut()` 单层引用可写 status,无 filter 闭包。审查锚定滞后(跑 batch51 中间态)— CR-260616-23 归档
|
||||
- [x] ✅(主代理修·CSS :has item 左边线) **CR-22-1** [med·UX] `AiChat.vue` 已置顶非 hover 不可见 → 已修复(`.ai-conv-item:has(.ai-conv-item-act--pinned){ box-shadow: inset 2px 0 0 accent }` 左边线强调,不破坏 hover 浮出 toggle,原方案图钉常驻与 actions display:none 矛盾,改 :has item 左线最简)— CR-260616-22 归档
|
||||
- [ ] **CR-34-1** [med] useAiPanel.ts:101 loadProviders 守卫 `if(!state.activeProvider)` 只查 null 不查有效性 — localStorage savedProvider 指向已删除 provider 时 activeProvider 残留无效 id → cycleProvider:1185 findIndex=-1 跳过 ps[0] + 发消息消费方用无效 id。修法:守卫加 `|| !list.some(p=>p.id===state.activeProvider)` 残留无效时回落 DB is_default — CR-260616-34 归档
|
||||
- [ ] **CR-30-1** [med] agentic.rs:298 退避 `1<<retry_attempt` 纯指数无 jitter/无总预算/一律重试(含 MidStream),三处注释(agentic.rs:37/commands.rs:1106/state.rs:185)误称「对齐 retry.rs(1s→2s→4s+jitter)」。retry.rs:67-78 实有 ±20% jitter+30s 预算+4xx 分类(:102-104 Fatal 立即放弃)。修法:agentic 加 jitter+总预算+错误分类真对齐,或删注释改「独立简化策略」— CR-260616-30 归档
|
||||
- [ ] **CR-30-2** [med] AiStreamRetry 死事件 + MidStream 重试文本混乱 — 后端 emit(agentic.rs:310)+types.ts:214 variant 有,但 useAiEvents.ts switch 无 case 穿透忽略;MidStream 失败重试时已 emit AiTextDelta 累积 currentText,重试新 delta 追加→文本重复。修法:useAiEvents 补 case+重试前清 currentText;或后端 MidStream 不重试只重试 Init(对齐决策a)— CR-260616-30 归档
|
||||
|
||||
### ⏸️ 待用户授权/确认(巡检悬挂项·2026-06-16)
|
||||
|
||||
@@ -139,7 +160,7 @@
|
||||
|
||||
- [x] **DEC-260616-01 文件名 git mv 06-15→06-16** ❌ **否决**(2026-06-16 用户确认):21 个 docs 文件名日期 `-2026-06-15.md` 均正确(06-15 创建),无需修改。原前提"今天误标 06-15"不成立。
|
||||
- [x] **DEC-260616-02 docs 其他文件 06-15 正文核对** ❌ **否决**(2026-06-16 文件时间分析):21 个 `-2026-06-15.md` 文件的 CreationTime 和 LastWriteTime 全部在 2026-06-15 00:22~17:08 之间,确认为 06-15 当天创建,正文中的 06-15 日期引用均正确,无需核对修改。
|
||||
- [ ] **DEC-260616-03 CR-04/CR-06 流式核心改造授权**【风险确认】splitBlocks→marked.lexer(CR-04)/loadMarkdown 重算(CR-06)。流式渲染核心,中风险(回归可能)。选项:①授权巡检推进(主代理重点核查流式渲染/审批/输入不破坏) ②单独立项谨慎做(不混巡检快推) ③暂不碰。
|
||||
- [x] **DEC-260616-03 CR-04/CR-06 流式核心改造授权** ✅ **已授权并实施完成**(2026-06-16):CR-04 splitBlocks→marked.lexer 已完成(batch57,见 CR-260615-04);CR-06 loadMarkdown 重算已确认实施(CR-260615-06 ✅)。两项流式核心改造均已落地并通过 vue-tsc + cargo check 零错误验证。
|
||||
|
||||
### 🔴 anthropic_compat 多轮工具调用(2026-06-14 排查·会话卡死根因)
|
||||
|
||||
@@ -239,7 +260,7 @@
|
||||
- [~] CR-260615-03 ✅ wave(2026-06-16,待commit) — 低风险子项收口:**已做 3** = `.bak·.tmp-write 噪音过滤`(tool_registry.rs:535 加 `is_noise_file` 后缀过滤+`list_dir_recursive` 跳过,默认 skip_noise=true 已开)+`COLS 列数断言`(crud.rs:KNOWLEDGE_COLS/COL_COUNT/COLS_WITH_EMBEDDING 模块级常量+test 断言 14/15 列)+`R-PD-11 抽 find_path_conflict`(见下);**已解跳过 1** = dag·executor 邻接表非重复(executor 用 `adjacency_in` 前驱表,dag.topological_layers 用 `adjacency_out` 后继表方向不同;`Dag::predecessors/successors` 已无调用方属死码清理归 ARC);**未做留 todo** = projectNameById 改 find(无此函数,audit.rs:45 `resolve_project_label` 已用 repo.get_by_id O(1) 查询,反模式不存在);audit.rs Err 误报 / openai source 丢失 / ToolCard id 类型归一(行为变更或前端,不在本批)
|
||||
|
||||
**P2 — 块级 memo 实施走查(ARC-260615-08,2026-06-16)**
|
||||
- [ ] CR-260615-04 — splitBlocks 手写正则切块改 `marked.lexer()`(`/```[^\n]*\n[\s\S]*?(?:```|$)/g` 不要求行首 + 固定 3 backtick,与 marked 围栏规则不一致;行中裸 ``` / 4+ backtick 嵌套围栏切错,前块缓存固化错误 html;机制2原生=lexer)— AiChat.vue splitBlocks — 详见 [自研块级memo流式渲染审查-2026-06-15.md](./05-代码审查/自研块级memo流式渲染审查-2026-06-15.md) ①
|
||||
- [x] CR-260615-04 ✅(batch57·2026-06-16·workflow w4h5ygko1+主代核查,vue-tsc 0err+cargo check 0err) — ~~splitBlocks 手写正则切块改 `marked.lexer()`~~ 已完成改造,AiChat.vue splitBlocks 函数已从手写正则改为 marked.lexer() — AiChat.vue splitBlocks — 详见 [自研块级memo流式渲染审查-2026-06-15.md](./05-代码审查/自研块级memo流式渲染审查-2026-06-15.md) ①
|
||||
- [x] CR-260615-05 ✅ parseBlock DRY (第⑩批 2026-06-16) — ~~parseBlock/parseBlockNoCache DRY~~ parseBlock 内部改调 parseBlockNoCache 去重(原 _purify.sanitize(_marked.parse()) 两处重复收敛为一处),行为零变化 — AiChat.vue
|
||||
- [x] CR-260615-06 ✅(2026-06-16 核实已实施) — ~~loadMarkdown 就绪后流式不主动重算~~ AiChat.vue:1039-1043 已有 `watch(mdReady, (ready) => { if (ready && streaming && currentText) scheduleStreamParse(currentText) })`,mdReady 翻转时主动触发末块重算。原 todo 标注未实施系过时判断 — AiChat.vue loadMarkdown
|
||||
- [x] CR-260615-07 ✅ blockCache LRU (第⑩批 2026-06-16) — ~~_blockCache LRU+escapeHtml 抽~~ _blockCache 超 limit 由整体 clear 改删最早一条(Map.keys().next().value LRU 语义,边界 > 改 >= 防超限)+escapeHtml+replace 两处重复抽 escapeFallback 函数(renderStreamingMd/renderMd 兜底均调),行为零变化 — AiChat.vue
|
||||
@@ -335,7 +356,7 @@
|
||||
- [x] DOC-260615-06 ✅(2026-06-16) — ~~架构复核报告 §5 新发现 11 项补 todo~~ 拆 4 子项独立 todo(见下方),核对发现 **复核-新① 已解决**(`useAiConversations.ts:122` 已有 pendingToolCalls await 后二次 token 比对),只补 ③④⑪ 三项;其余 7 项已被全局 review 取代(R-PD 系列) — 详见 §6
|
||||
- [x] ✅(batch31·2026-06-16) 复核-新③ [P2] — **NodeCancelled 事件语义双标**。`executor.rs:149` 取消节点(set_cancelled 后 Err 路径)状态保 Cancelled(:145 跳 set_failed),但事件总线仍 emit `NodeFailed { error: "人工审批被取消" }`。前端若按 NodeFailed 分支判断会误归类「失败」非「取消」。修法:加 `NodeCancelled` variant 或 NodeFailed 加 `cancelled: bool` 字段。— 来源:架构复核报告 §5 新③,crates/df-workflow/src/executor.rs:145-153 + df-core/events.rs
|
||||
- [x] ✅(batch30·2026-06-16) 复核-新④ [P2] — **cancel_workflow_node 无节点终态前置校验**。`workflow.rs:352` 仅校验 execution_id 在注册表,不校验 node_id 状态。对已 Completed/Failed/Cancelled 节点调 set_cancelled 会静默覆盖终态(set_cancelled 绕 is_legal)。修法:加 `match sm.get(&node_id) { Running|Waiting => {}, _ => Err }` 守卫。— 来源:架构复核报告 §5 新④,src-tauri/src/commands/workflow.rs:341-358
|
||||
- [ ] 复核-新⑪ [P2] — **主窗口看门狗幽灵**:detach 时主窗口 `state.streaming`/`state.generatingConvId` 未清(`useAiWindow.ts:20-59` detachPanel 仅快照写 localStorage 不清主窗口 state),看门狗续计 130s 后往主窗口 state 补幽灵错误消息。用户已切走无实际危害,仅主窗口面板重开时看到一条幽灵错误。修法:detach 时显式清主窗口 streaming/generatingConvId 或暂停主窗口看门狗(detach 前提下主窗口不应跑生成态看门狗)。— 来源:架构复核报告 §5 新⑪,src/composables/ai/useAiWindow.ts:20-59 + useAiEvents.ts:115 watchdog
|
||||
- [x] ✅(batch54·2026-06-16·workflow+主代核查) 复核-新⑪ [P2] — **主窗口看门狗幽灵**。**核验更正**:原述「看门狗续计 130s 补幽灵错误」已被 CR-260615-24 兜底解决(detach→AiChat 卸载 App.vue v-if→onBeforeUnmount:1613 `stopListener()`→useAiEvents.ts:371 `clearStreamWatchdog()`,主代独立 grep 核验链路完整)。本次 workflow agent 补强:detachPanel 快照后清主窗口 `state.streaming=false`/`generatingConvId=null`(useAiWindow.ts:37-38),消除「面板重开生成态视觉残留」(进度条/spinner)。**安全性**:主/分离窗口 state 独立(各自 webview 独立 JS context,stores/ai.ts 单例仅同 webview 内共享),清主窗口 state 不影响分离窗口生成态;localStorage 快照保留供 resumeInDetached 恢复。vue-tsc EXIT=0 主代独立核验。— 来源:架构复核报告 §5 新⑪,src/composables/ai/useAiWindow.ts:37-38 + useAiEvents.ts:364-374 stopListener
|
||||
- [x] DOC-260615-07 ✅(第⑲批 2026-06-16) — ~~aichat §8 表补勾~~ aichat审查报告第八章 AR-1~11 优先级表逐行补状态勾注(AR-1退役✅/AR-2~7,9~11已修✅+commit/AR-8重评🔄)+文档头二次增补行;零新增条目对齐 DOC-13 瘦身方向;状态不一致 2 项(AR-1退役/AR-8重评)按 todo 标注非矛盾 — 详见 §7
|
||||
- [x] DOC-260615-08 ✅(2026-06-16) — ~~近期改动 CR-03 未做子项拆独立 todo~~ 拆 3 子项独立 todo(见下方)。原 CR-03(line 212)内联备注「未做留 todo」未独立追踪,现拆。— 详见 §8
|
||||
- [x] ✅(batch30·2026-06-16) CR-260615-03-a [P2] — **audit.rs Err 误报「项目已不存在」**。`audit.rs:52` `resolve_project_label` 用 `_` 合并 `Err`(DB 故障/锁/连接断)与 `Ok(None)`(真不存在),DB 出错时用户看到误导性「项目已不存在」而非错误。修法:分三臂 `Ok(Some)`/`Ok(None)`/`Err`(Err 打 warn 日志回退裸 id)。零行为破坏(仅 Err 分支加日志+改文案)。— 来源:近期改动审查 §2②,src-tauri/src/commands/ai/audit.rs:50-52
|
||||
@@ -425,7 +446,7 @@
|
||||
- [x] B-260615-21 ✅ 回滚user msg (第⑩批 2026-06-16) — ~~sendMessage catch 回滚 user message~~ push user msg 前捕获 const userMsgId(原内联未生成)+catch 块 filter 改 m.id!==aiMsgId && m.id!==userMsgId 一并回滚;机制:user/ai msg 均 nextMsgId() 唯一 id+push 进 state.messages(无索引依赖,按 id 过滤最稳) — useAiSend.ts
|
||||
|
||||
**P2 — 前后端状态同步**
|
||||
- [ ] B-260615-22 — [P2] ~~前后端状态不同步~~ → **由 B-260615-55(L0 握手) + B-260615-56(L2 强制发送) 解决**,本条保留为问题记录不再独立实施
|
||||
- [x] ✅(batch55·2026-06-16·主代销账) B-260615-22 — [P2] ~~前后端状态不同步~~ → **由 B-260615-55(L0 握手) + B-260615-56(L2 强制发送) 解决**(L0 前端重接握手+L2 三级降级+force_send IPC),本条保留为问题记录不再独立实施。双项均已✅销账,本条闭环。
|
||||
- [x] CR-260615-12 ✅ 小项 _toastTimer 等 (第⑩批 2026-06-16) — ~~可选一组~~ _toastTimer 卸载未清(AiChat:436) + markdown 外层 span→div + SVG 常量散落 + appSettings 注释 + index 空行 + 路由 icon 语义 + options shape 校验 + projectNameById 共享 + useConfirm dev 警告 + i18n `t` as any — 详见走查 ⚪ 区
|
||||
- [x] CR-260615-09 ✅ .ai-md DRY (第⑩批 2026-06-16) — ~~五份 .ai-md 样式逐字重复~~ 抽全局 css (84条删+3留独有) — AiChat/ProjectDetail/Ideas/Knowledge/TaskDetail → `src/styles/ai-md.css` 或 `<AiMarkdown>` 组件。TaskDetail.vue:263-333 新文件继续抄(CR-09 复发,定时走查 06-15 确认第 5 份)。B-24/25 复制粘贴源头 — 详见走查 ⑤ + 定时走查 P0复核.md
|
||||
- [x] CR-260615-10 ✅ useRendered DRY (第⑩批 2026-06-16) — ~~useMarkdown 加 `useRendered(getText)` 辅助~~ 消除 renderedDesc computed + onMounted(loadMarkdown) 三处重复(与 CR-09 同源) — 详见走查 ⑥
|
||||
@@ -495,7 +516,7 @@
|
||||
- [x] UX-2025-01 ✅ 选文字(文本偏移量方案) (第⑩批销账 06-15) — **流式渲染中选中文字保持**(§2.1)。现象:AI 流式输出时选文字被 delta 打断丢失选区。方案 A(推荐):`selectionchange` + 选区在消息容器内 → 暂停 rAF 流式 parse → 选区结束恢复;方案 B:已完成块独立 DOM 节点不参与 v-html 替换。关联 ARC-08 块级 memo(splitBlocks 已按块切分,末块单独更新天然支持方案 B)— src/components/AiChat.vue + src/composables/ai/useAiEvents.ts
|
||||
- [x] ✅(batch36·2026-06-16·workflow w098aapgd) UX-2025-02 [P1] — **消息操作栏(复制 / 重新生成)**(§1.2+§1.3)。AI 气泡 hover 显示操作栏:「📋 复制」+「🔄 重新生成」。复制 = F-260615-13 合并实现;重新生成:后端删最后一条 AI 消息 + 用倒数第二条 user 消息重跑 agentic loop(新增 `ai_regenerate` IPC)。代码块额外 hover 浮出「📋 复制代码」按钮(§2.2 子项)。— src/components/AiChat.vue + src-tauri/src/commands/ai/commands.rs
|
||||
- [x] ✅(batch36·2026-06-16·workflow w098aapgd) UX-2025-03 [P1] — **错误气泡操作入口**(error_type 枚举本身 batch34 B-42 已加,本批前端消费)(§4.1)。错误气泡底部增加按钮区:「🔁 重试」(取上一条 user 消息重发)+「⚙ 去设置」(仅 auth/provider 错误时显示,跳 Settings→AI Tab)。后端 `AiError` 加 `error_type: Option<ErrorType>` 枚举(auth/network/timeout/provider_config/unknown),前端据此显隐按钮。— src-tauri/src/commands/ai/mod.rs(AiChatEvent) + src/api/types.ts + src/components/AiChat.vue
|
||||
- [ ] UX-2025-04 [P1] — **断线保文**(§4.2)。流式中断时已接收文本不丢弃:`stream_llm` mid-stream error 改返回 `Some(partial_text, ...)` + `incomplete: true` 标志;agentic 收到 incomplete → 正常入库 + emit AiCompleted(非 AiError)+ 追加系统提示「⚠ 响应因网络中断不完整」;前端 AI 气泡底显示「继续生成」按钮。关联 B-260615-05(流尽空内容报错)同改 stream_recv.rs。— crates/df-ai/src/stream_recv.rs + src-tauri/src/commands/ai/agentic.rs + src/components/AiChat.vue
|
||||
- [x] ✅(batch59·2026-06-16·workflow wdlt0xfl6) UX-2025-04 [P1] — **断线保文**(§4.2)。保文核心落地:stream_recv.rs `StreamResult` enum(Complete/Partial/InitFailed 三分支),MidStream 失败(流中途 chunk error/idle timeout/有 partial_text 未 finished)返 `Partial{partial_text}` **不重试保文**;agentic.rs 收 Partial → 入库 assistant 消息 + emit AiCompleted(incomplete=true,非 AiError) + 追加系统提示「⚠ 响应因网络中断不完整」;useAiEvents.ts:177 补 `AiStreamRetry` case(消除死事件穿透) + AiCompleted case 处理 incomplete(系统提示气泡镜像后端);types.ts:204 `incomplete?:boolean`。对齐决策 a1(Init 可重试/MidStream 保文不重试) + UX-04 决策 a。**「继续生成」按钮暂未做**(保文核心硬需求已满足,按钮可复用 UX-2025-03 重试能力或按需补)。— src-tauri/src/commands/ai/stream_recv.rs + agentic.rs + src/composables/ai/useAiEvents.ts
|
||||
|
||||
**第二批 — 显著提升日常效率**
|
||||
|
||||
@@ -527,7 +548,7 @@
|
||||
|
||||
- [x] AE-2025-01 [P0] — **批量审批**。同一轮多 pending 时,ToolCardList 顶部显示「全部批准(N) / 全部拒绝」按钮。改动:①`ToolCardList.vue` 加批量操作栏(监听 pending_approval 数量)②`useAiSend.ts` 新增 `approveAll(rejectAll)` 循环调 `ai_approve`。预估 0.5 天 — src/components/ToolCardList.vue + src/composables/ai/useAiSend.ts (第⑫批销账 06-15)
|
||||
- [x] AE-2025-02 [P0] — **审批计数器 + 跳转**。输入框上方/header 显示 `⏳ N 项待审批` 徽标,点击跳转到第一个 pending 卡片。改动:①`AiChat.vue` header 区域加审批徽标 ②`ToolCardList.vue` 暴露 `scrollToFirstPending` 方法。预估 0.5 天 — src/components/AiChat.vue + src/components/ToolCardList.vue (第⑬批销账 06-15)
|
||||
- [ ] AE-2025-03 [P0] — **write_file diff 预览**。write_file 审批时若文件已存在,展示前后对比 diff 而非裸 content(content 可能几百行代码截断到 300 字符)。改动:①后端 `tool_registry.rs` write_file handler 执行前读旧文件返回 diff ②`ToolCard.vue` pending_approval + name=write_file 时渲染 diff 视图(红删绿增)。关联 F-260615-10(diff 工具)可复用。预估 1 天 — src-tauri/src/commands/ai/tool_registry.rs + src/components/ToolCard.vue
|
||||
- [ ] AE-2025-03 [P0] — **write_file diff 预览** ⚠️**降级阻塞(2026-06-16·batch54 workflow 探索+主代核验)**:后端 write_file **未返 diff**(`tool_registry.rs:694` 结果 payload `{path,bytes_written,old_size,encoding}` 无 diff 字段,`generate_diff` 仅 patch_file 调用),前端 ToolCard 无 diff 可渲染,审批 payload `AiApprovalRequired`/`PendingApproval` 亦无 diff(只有 `args={path,content,encoding}` 纯新内容,拿不到旧文件)。需**后端先补**再追加前端渲染。**两条路径**(均 src-tauri 改动,跨 mod.rs/audit.rs/types.ts/AiChat.vue 领地):路径 B(推荐,满足审批预览诉求)审批 payload 加 `diff` 字段 + audit.rs:555 挂起审批前预读旧文件 + `generate_diff` 注入事件;路径 A 仅 write_file handler 补 diff 但结果阶段才有(审批时看不到,不满足)。前端部分待后端 diff 返回后追加 `<pre>` 红删绿增渲染。原诉求:write_file 审批时若文件已存在,展示前后对比 diff 而非裸 content(content 可能几百行代码截断到 300 字符)。改动:①后端 `tool_registry.rs` write_file handler 执行前读旧文件返回 diff ②`ToolCard.vue` pending_approval + name=write_file 时渲染 diff 视图(红删绿增)。关联 F-260615-10(diff 工具)可复用。预估 1 天 — src-tauri/src/commands/ai/tool_registry.rs + src/components/ToolCard.vue
|
||||
|
||||
**P1 — 增强控制力**
|
||||
|
||||
@@ -563,7 +584,7 @@
|
||||
- [ ] F-260614-10 — 知识库 MCP Server + Tier 2/3 — 对外 MCP 暴露 + 分层存储(当前仅 Tier 1 全栈) — source:PROGRESS Sprint15
|
||||
- [ ] T-260614-11 — 全局#6 条件表达式引擎升级 — df-workflow conditions 仅支持 true/false 字面量,升级为真表达式求值 — source:PROGRESS 全局问题
|
||||
- [x] T-260614-12 — ~~df-ideas 死代码~~ ✅ WF-E 部分完成(capture.rs 删 CaptureInput/IdeaCapture 死码,保留 Idea/IdeaScores 共享实体;promotion/scoring/adversarial 内"两套 Recommendation/PromotionPolicy 死枚举"嫌疑 agent 未确认存在/保留为对外契约,本次未动,待复查)(06-14, commit 89da9fa)
|
||||
- [ ] F-260615-01 — **[P1 功能增强]** HumanNode 审批节点支持自定义选项 + 单选/多选类型。现状:config `options: Vec<String>` 已支持任意数量(2/3/…数量扩展已通),但 `decision` 是单 `String` 仅单选语义,`options` 空=自由文本。增强目标:不止「同意/拒绝」二选一,可配置 N 个候选项 + 单选(single)/多选(multiple)两种类型。**改动面**:①`df-core/events.rs` `WorkflowEvent::HumanApprovalRequest` 加 `select_type`、`HumanApprovalResponse` decision 单值→多值(`decisions: Vec<String>` 或保留 decision 兼容 + 加 decisions)②`human_node.rs` config 解析 `select_type` + 校验(多选时每项 ∈ options,可加 min/max 选中数约束)③IPC `approve_human_approval` 签名 ④前端 `stores/project.ts` approve + `api/types.ts` 事件类型 + 审批弹窗 UI(单选 radio / 多选 checkbox)⑤单测改断言 + 新增多选/超限测。**注意**:向后兼容现 single 调用方,`select_type` 缺省 = single — source:用户需求(06-15),crates/df-nodes/src/human_node.rs + src-tauri/src/commands/workflow.rs + src/stores/project.ts — **✅已实施(a3cccb070fe9c8821,2026-06-16,待commit)**:6 文件契约向后兼容(events.rs SelectType 枚举 Single/Multiple 缺省 Single+HumanApprovalResponse decision+decisions 双字段/human_node.rs 校验 single len==1·multiple len≥1·∈options/workflow.rs IPC 加 decisions+select_type Option 缺省兼容/types.ts/project.ts approve/ProjectDetail.vue checkbox 多选 UI)。cargo check 0 err/df-nodes 21 test(含 4 新增多选)/vue-tsc 0 err。主代理核查契约向后兼容 + 6 文件边界
|
||||
- [x] F-260615-01 ✅(2026-06-16,待commit a3cccb070fe9c8821) — **[P1 功能增强]** HumanNode 审批节点支持自定义选项 + 单选/多选类型。现状:config `options: Vec<String>` 已支持任意数量(2/3/…数量扩展已通),但 `decision` 是单 `String` 仅单选语义,`options` 空=自由文本。增强目标:不止「同意/拒绝」二选一,可配置 N 个候选项 + 单选(single)/多选(multiple)两种类型。**改动面**:①`df-core/events.rs` `WorkflowEvent::HumanApprovalRequest` 加 `select_type`、`HumanApprovalResponse` decision 单值→多值(`decisions: Vec<String>` 或保留 decision 兼容 + 加 decisions)②`human_node.rs` config 解析 `select_type` + 校验(多选时每项 ∈ options,可加 min/max 选中数约束)③IPC `approve_human_approval` 签名 ④前端 `stores/project.ts` approve + `api/types.ts` 事件类型 + 审批弹窗 UI(单选 radio / 多选 checkbox)⑤单测改断言 + 新增多选/超限测。**注意**:向后兼容现 single 调用方,`select_type` 缺省 = single — source:用户需求(06-15),crates/df-nodes/src/human_node.rs + src-tauri/src/commands/workflow.rs + src/stores/project.ts — **✅已实施(a3cccb070fe9c8821,2026-06-16,待commit)**:6 文件契约向后兼容(events.rs SelectType 枚举 Single/Multiple 缺省 Single+HumanApprovalResponse decision+decisions 双字段/human_node.rs 校验 single len==1·multiple len≥1·∈options/workflow.rs IPC 加 decisions+select_type Option 缺省兼容/types.ts/project.ts approve/ProjectDetail.vue checkbox 多选 UI)。cargo check 0 err/df-nodes 21 test(含 4 新增多选)/vue-tsc 0 err。主代理核查契约向后兼容 + 6 文件边界
|
||||
- [x] F-260615-02 ✅(2026-06-16,待commit) — **[P1 功能]** task 详情查看。✅已实施:get_task_by_id IPC(复用 TaskRepo::get_by_id ok_or_else 转 Result)+lib.rs 注册+taskApi.get+/tasks/:id 路由+TaskDetail.vue(11 字段:标题/描述/状态/优先级/关联项目 router-link 解析名/分支标签/负责人/基础分支/工作流定义/创建更新时间;复用 constants/project 标签+formatDate+watch route.params.id 重载)+Tasks.vue 列表项 @click router.push;TaskRecord TS 类型已存在无需新增;主代理核查 cargo check 0 err/vue-tsc 0 err/git diff 6 文件边界干净。现状:`src/views/Tasks.vue` 仅列表,无独立 TaskDetail 视图/路由(grep 仅 `ProjectDetail.vue` 嵌套任务命中,无独立详情页)。需求:点击 task 查看详情。**数据模型已就绪**(`df-storage/src/models.rs:53` `TaskRecord` 12 字段:id / project_id / title / description / status / priority / branch_name / assignee / workflow_def_id / base_branch / created_at / updated_at)。**改动面**:①新建 `src/views/TaskDetail.vue` 视图 + 路由(`router/index.ts` `/tasks/:id`)②task 详情 IPC(`get_task_by_id`,核对 `commands/task.rs` 现有 IPC 是否已有,无则补)③`Tasks.vue` 列表项点击 → 跳详情 ④详情页字段展示(title/description 渲染、status/priority 标签、关联项目名解析 project_id→name、branch/assignee 信息、时间戳)⑤可选:详情页内编辑(`update_task` IPC 已存在,FR-D6)。— source:用户需求(06-15),src/views/Tasks.vue + src/router/index.ts + src-tauri/src/commands/task.rs
|
||||
- [x] F-260615-03 ✅ truncated 标志 (第⑩批 2026-06-16) — ~~list 工具截断标志~~ (list_trash补漏) 原完整分页方案,对抗分析降级。现状:4 工具 `truncate(50)` 硬截断,AI 不知被截断会回复「不存在」。**对抗分析裁决**:数据量未到 50 条线(projects=5, tasks=61),完整分页 breaking change 风险 > 收益 → **降级为最小修**:不改返回结构(non breaking),只在 truncate 时加 `truncated: true` 标志 + 工具描述注明"最多返回 N 条"。未来数据量到时再升完整分页(F-03-full)。**改动面**:tool_registry.rs 4 handler 截断处加 truncated bool 返回 — src-tauri/src/commands/ai/tool_registry.rs:127-165,377-379 — source:用户需求(06-15)+对抗分析裁决(06-15)
|
||||
- [x] F-260615-04 ✅ 卡片分组增强 (第⑩批 2026-06-16) — ~~read_dir / read_file 工具卡片连续时折叠/收起~~ 提高信息密度。现状:AI 探查目录常连续调多个 read_dir + read_file(先列目录再读多个文件),每个结果独立卡片平铺,长列表/大文件内容占满屏幕,信息密度低。需求:相邻同类读取卡片支持折叠——默认收起只显摘要(如「read_dir: 12 项」「read_file: src/main.rs (234 行)」),点击展开看详情;或连续 N 个同类卡片归组折叠。**改动面**:①`ToolCard.vue` 加折叠态(`collapsed` ref + 摘要/详情双视图 + chevron 图标 + 高度过渡)②连续同类检测/归组(`ToolCardList.vue` 按 `tool.name` 分组,已有列表容器适合放分组逻辑)③摘要提取(read_dir 数项数 / read_file 文件名 + 行数,解析 result)④折叠态持久化(可选,localStorage 按 conv)。关联信息密度构想(memory: devflow-info-density-concept,卡片折叠是其中一环)。— source:用户需求(06-15),src/components/ToolCard.vue + src/components/ToolCardList.vue — **勘察完成(2026-06-16,wxflofhf2)**:feasible/plan 11 步跨 5 文件(ToolCardList/ToolCard/useAiSend/stores/ai/global.css)。risk 标低但实为 UX 新行为+改核心 ai 状态文件(useAiSend.ts/stores/ai.ts)+plan 细节有误(useAiSend composable 无 emit 方法)。**拆小或留待**:先做 ToolCardList 分组+单卡折叠摘要(限定不碰 useAiSend/stores),完整折叠交互归信息密度构想单独立项
|
||||
@@ -605,7 +626,7 @@
|
||||
- [ ] F-07 trait 下沉 df-ai-core — 设计完备 4 项决策全定稿,退路可放 df-core,解锁 F-03/F-01
|
||||
- [x] R-PD-2 ✅ ScriptNode 不注册 (第⑩批 2026-06-16) — ~~ScriptNode 不注册 script~~ 3 行删除封死攻击面,工作流当前纯演示无真实脚本需求
|
||||
- [x] F-260615-06 ✅ patch_file (第⑩批 2026-06-16) — ~~patch_file(edit_file)~~ 局部文件更新工具,补齐 AI 文件操作闭环。完整设计见 [patch_file工具设计-2026-06-15.md](./02-架构设计/patch_file工具设计-2026-06-15.md)(API/三层防御/边界情况/替代方案否决/实施步骤)。**核心**: old_text 精确匹配为主+line 辅助+Mutex 并发安全+expected_hash 指纹防脏写。第一批实现核心三件套(~50行)。— src-tauri/src/commands/ai/tool_registry.rs 新增 handler
|
||||
- [ ] ARC-06 composable 循环依赖 — 提 aiShared.ts 破环最小改动(或合回 stores/ai.ts 备选)
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) ARC-06 composable 循环依赖 — **破环全闭环**:①`aiShared.ts` 下沉 findToolCall(反向扫描O(1))+4个审批计时器函数(startApprovalTimer/clearApprovalTimer/clearAllApprovalTimers+APPROVAL_TIMEOUT_MS常量) ②`useAiEvents` 删 findToolCall 导出+改 import 从 aiShared 取 ③`useAiSend` 删审批计时器实现(改从 aiShared re-export)+删 drainQueue 直接调用(改经 `ai-drain-queue` 事件总线桥接) ④`stores/ai.ts` 加 `initDrainQueueListener()` 启动事件监听。**B-260616-19 CSS 缺失**(Knowledge.vue 窄屏标题挤压,agent 未产出 .css/.vue style 变更),待补。— src/composables/ai/aiShared.ts + useAiEvents.ts + useAiSend.ts + stores/ai.ts
|
||||
- [x] CR-09 .ai-md 样式 5 份→全局 css 抽取 — 零风险减法 (第⑬批销账 06-15)
|
||||
- [x] F-09 status 对齐前后端 ✅ (第⑯批销账 06-15) — 前端 map 删 in_progress/paused/cancelled(project 维度无数据源/UI 入口/消费方),保留 planning/active/completed。constants/project.ts(三 map 同步删+兜底改字面量)+Dashboard.vue getProjectStage(switch 收敛)+i18n zh-CN/en projects.status & dashboard.stage。后端不动(df-core enum 7 值是独立大改,F-260614-09 专项)。**注**:DB 实际只产生 planning(4 个建项目入口硬编码),真实生命周期=planning+deleted_at 软删二态
|
||||
- [x] F-260615-03 ✅ truncated (第⑩批 2026-06-16) — ~~最小修(截断标志)~~ **从完整分页降级**:不改返回结构(non breaking),truncate 时加 `truncated: true`(→ 见上方 :469 完整条目,本条为对抗分析区引用,勿重复实施)
|
||||
@@ -663,12 +684,12 @@
|
||||
> 来源:后台代理扫描 62 个 markdown 文档发现的问题
|
||||
|
||||
**P0 — 严重阻塞**
|
||||
- [ ] B-260615-57 [P0→缺口收窄] — ~~文件工具功能缺口~~ **06-15 批次后缺口 6→2→0**:已补 `patch_file`(F-06 ✅) / `search_in_file`(F-07 ✅) / `file_info`(F-08 ✅) / `append_file`(F-09 ✅) / `search_files`(F-12 ✅) / `delete_file`(F-16 ✅ 第⑯批) / `rename_file`(F-15 ✅ 第⑮批销账 06-15)。**缺口清零**:`rename_file`/`move_file` 已补(F-260615-15,根治 AI rename 走 run_command 的中文路径静默失败)。原根因(迫使 LLM 滥用 write_file 放大 FR-S7 覆盖写入风险)已由 patch_file 缓解。— src-tauri/src/commands/ai/tool_registry.rs
|
||||
- [x] B-260615-57 ✅(2026-06-16,缺口清零销账) [P0→缺口收窄] — ~~文件工具功能缺口~~ **06-15 批次后缺口 6→2→0**:已补 `patch_file`(F-06 ✅) / `search_in_file`(F-07 ✅) / `file_info`(F-08 ✅) / `append_file`(F-09 ✅) / `search_files`(F-12 ✅) / `delete_file`(F-16 ✅ 第⑯批) / `rename_file`(F-15 ✅ 第⑮批销账 06-15)。**缺口清零**:`rename_file`/`move_file` 已补(F-260615-15,根治 AI rename 走 run_command 的中文路径静默失败)。原根因(迫使 LLM 滥用 write_file 放大 FR-S7 覆盖写入风险)已由 patch_file 缓解。— src-tauri/src/commands/ai/tool_registry.rs
|
||||
|
||||
**P1 — 重要缺陷**
|
||||
- [x] B-260615-39 [P1] ✅(第⑰批销账 06-15) — ~~complete() 超时重试机制缺失~~ 新建 retry.rs(189行+6单测 retry_with_backoff/AttemptOutcome/is_*_retryable)+openai/anthropic complete() 包裹重试(3次/指数1s→2s→4s/±20%jitter/30s总预算止损/可重试 timeout·connect·5xx·429,不重试4xx·auth·body)/不建LlmError枚举(零侵入trait保anyhow::Result)/不用middleware(手写loop)/流式stream()不动/Settings降级常量MAX_COMPLETE_ATTEMPTS=3。**顺带修真bug:Anthropic complete()无60s timeout(FR-R4只修OpenAI一半,建连后挂起无限hang)**。complete()4调用方全低频后台(标题/知识/扫描/AiNode)有兜底,主对话走stream()不受影响。cargo test -p df-ai 37 passed `complete()` IPC 调用仅加 60s 单请求超时,但无重试机制。根因:网络波动时直接失败,无自动重试兜底。影响:偶发网络错误导致用户操作失败需手动重试。修法:实现指数退避重试机制(最多 3 次,总时长不超过 30s),并在 Settings 可配重试开关 — src-tauri/src/commands/ai/commands.rs
|
||||
- [x] B-260615-40 [P1] ✅(第⑯批销账 06-15) — ~~审批按钮无状态反馈~~ ToolCard 加 approving ref+spinner+disabled(防重入)+130s 本地计时器兜底+watch tc.status 离开 pending_approval 复位;useAiSend approveToolCall 删乐观置 running(原致审批整块消失切骨架屏,语义错位)保 pending_approval 直到后端事件回流;useAiStream onStreamTimeout 注释更新。loading 就近持有 ToolCard 本地不污染 store status 流转 — src/components/ToolCard.vue + src/composables/ai/useAiSend.ts
|
||||
- [ ] B-260615-41 [P1] — ~~工作流执行无进度指示~~ 长时间工作流执行时,用户不知道执行进度和剩余时间。根因:缺乏执行进度可视化。修法:在工作流详情页添加进度条 + 执行步骤提示 + 预估剩余时间 — src/views/WorkflowDetail.vue(需新建)
|
||||
- [x] B-260615-41 [P1] ✅(batch35 销账 2026-06-16,对齐决策a轻量) — ~~工作流执行无进度指示~~ batch35 TaskDetail 进度内嵌已满足决策 a 轻量:复用现有 NodeStarted/NodeCompleted 事件(纯前端 `handleWorkflowEvent` 按 exec_id 过滤 dispatch,不新增后端 progress 事件),`.wf-progress` 区显示 `workflowStepRunning{node}`(当前步骤)+`workflowStepsProgress{done}/{total}`(步骤进度)+完成/失败提示,不新建独立 WorkflowDetail.vue(决策 a 是嵌入现有 TaskDetail 推进按钮区非独立页),i18n key taskDetail.workflowStepRunning/stepsProgress/completedHint/failedHint zh-CN+en 双语已加。**预估剩余时间属方案 b 完整版,决策 a 明确不做** — src/views/TaskDetail.vue
|
||||
- [x] ✅(batch34·2026-06-16·workflow wvr7mdo0p) B-260615-42 [P1] — ~~错误信息不一致~~ 同类错误在不同场景下返回的信息格式不统一。根因:错误处理分散在不同模块,缺乏统一规范。影响:用户和调试者难以理解错误含义。修法:制定错误码规范 + 统一错误格式 + 前端错误码映射 — src-tauri/src/commands/ai/mod.rs + src/api/types.ts
|
||||
|
||||
**P2 — 中等问题**
|
||||
|
||||
339
docs/待决策.md
Normal file
339
docs/待决策.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# 待决策队列
|
||||
|
||||
> **职责分离**:
|
||||
> - **主会话**(汇总/巡检)→ 【写入】"当前队列",登记待人工决策项(背景 + 决策点 + 选项 a/b/c + 推荐)。
|
||||
> - **用户**(人工)→ 【拍板】选选项或确认推荐,回填理由(可选)。
|
||||
> - **主会话**(拍板后)→ 决策项回流 [todo.md](./todo.md) 推进 + 移"已决归档"。
|
||||
>
|
||||
> 这里**只放需人工决策项**(产品取舍 / 方向选型 / 排期 / 用户实测澄清)。不放可自主推进待办(见 [todo.md](./todo.md))、不放审查登记(见 [待审查.md](./待审查.md))。
|
||||
> 来源:2026-06-16 从 todo.md 抽离③④C类(可自主批 AE-03/复核⑪/UX-04 留 todo 推进)。
|
||||
|
||||
## 决策规则
|
||||
|
||||
- 每条须:背景 + 决策点 + 选项 + 推荐 + 关联 todo。
|
||||
- 用户回填:`✅ 决策:X`(选 + 理由可选)。
|
||||
- 拍板后:主会话回流 todo 实施 + 移本文件"已决归档"。
|
||||
- 暂缓项标 ⏸️,不删(条件变化可重启)。
|
||||
|
||||
## 状态图例
|
||||
|
||||
🟡 待决 / ✅ 已决(回填决策) / ⏸️ 暂缓(待条件)
|
||||
|
||||
---
|
||||
|
||||
## 当前队列
|
||||
|
||||
### ③类 — 产品取舍(有 a/b/c 决策点,核心待拍板)
|
||||
|
||||
#### CR-13-O1 in_progress 模板失败退回语义
|
||||
- **背景**:in_progress 模板失败→`regression_target("in_progress")=Some("todo")`,但状态机 `backward_to_todo_rejected` 全拒(task_state_machine.rs:188-193)→回调 advance_task_atomic 被 InvalidState 拦截,任务原地保留 in_progress。
|
||||
- **决策点**:in_progress 执行失败应如何退回?
|
||||
- **选项**:
|
||||
- a: 接受现状(原地 in_progress)+ 补 UI 提示「执行失败,请手动处理」
|
||||
- b: 改 `regression_target("in_progress")=None` 对齐状态机(失败不自动退回,留 in_progress 等人介入)
|
||||
- c: 放开 todo 回退(破坏闸门,执行失败可回 todo 重来)
|
||||
- **推荐**:**b**(对齐状态机现状,失败留 in_progress 显式待人介入,不破坏闸门语义)
|
||||
- **关联**:todo CR-13-O1 / CR-260616-13
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:b**。对齐状态机,失败留 in_progress 等人介入,blocked 状态已提供合法通道。
|
||||
|
||||
#### DEC-260616-03 CR-04/CR-06 流式核心改造授权
|
||||
- **背景**:splitBlocks 手写正则切块(CR-04,行中裸 ```/4+ backtick 嵌套切错)+ loadMarkdown 重算(CR-06)是流式渲染核心改造,中风险(回归可能)。
|
||||
- **决策点**:是否授权推进流式核心改造?
|
||||
- **选项**:
|
||||
- a: ①授权巡检推进(主代理重点核查流式渲染/审批/输入不破坏)
|
||||
- b: ②单独立项谨慎做(不混巡检快推,独立验证)
|
||||
- c: ③暂不碰(保留自研块级 memo 现状)
|
||||
- **推荐**:**a ①**(自研 memo 已稳,CR-04/06 是增强非阻断,授权巡检推进+重点核查)
|
||||
- **关联**:todo DEC-260616-03 / CR-260615-04
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a**。授权巡检推进,自研 memo 已稳,CR-04/06 是增强非阻断。
|
||||
|
||||
#### CR-260615-04 splitBlocks→marked.lexer
|
||||
- **背景**:splitBlocks 手写正则 `/```[^\n]*\n[\s\S]*?(?:```|$)/g` 不要求行首+固定 3 backtick,与 marked 围栏规则不一致;行中裸 ```/4+ backtick 嵌套围栏切错,前块缓存固化错误 html。
|
||||
- **决策点**:是否改用 marked.lexer 原生切块?(依赖 DEC-260616-03 授权)
|
||||
- **选项**:
|
||||
- a: 改 marked.lexer(机制2原生,根治切错)
|
||||
- b: 补正则边界(治标,维护成本)
|
||||
- c: 不改(现状可接受,极端输入才触发)
|
||||
- **推荐**:**a**(根治,依赖 DEC-03 授权)
|
||||
- **关联**:todo CR-260615-04 / DEC-260616-03
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a 改 marked.lexer**。DEC-260616-03 已决a 授权推进,batch57 workflow(w4h5ygko1) Agent B 已实施 AiChat.vue splitBlocks 改 marked.lexer(tokenize),vue-tsc 0err + cargo check 0 err。todo CR-260615-04 同步销账。
|
||||
|
||||
#### F-260616-06 审批「未找到挂起的审批」体验
|
||||
- **背景**:pending_approvals 内存态(commands.rs:130 remove None 报错)与前端刷新/重复点击不同步;重试场景旧 id 已被处理;前端 useAiSend.ts:221 IPC 失败不回滚 pendingApprovals,按钮残留。
|
||||
- **决策点**:修法组合选哪些?
|
||||
- **选项**:
|
||||
- a: 后端 ai_approve 幂等(找不到 pending 查审计表,已 executed/rejected 返回「已处理」成功非报错)
|
||||
- b: 前端审批按钮防抖(同一 id 短期多次只发一次 IPC)
|
||||
- c: 前端刷新后 pending 态正确同步(核对 useAiConversations.ts:119 边界)
|
||||
- **推荐**:**a + b**(后端幂等治本 + 前端防抖治标,c 已部分由现有恢复逻辑覆盖)
|
||||
- **关联**:todo F-260616-06
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a + b**。先 b 前端防抖止血(5 分钟改动),后 a 后端幂等治本。**子决策:实施顺序=A(先 b 防抖,后 a 幂等)**。
|
||||
|
||||
#### F-260616-07 流式对话失败自动重试
|
||||
- **背景**:流式 stream_llm 零重试(agentic.rs:231-238 返回 None 直接放弃);df-ai retry.rs 只覆盖非流式 complete();手工重试已存在(错误气泡「重试」按钮)。
|
||||
- **决策点**(4 个子决策):
|
||||
- (a) 流中途失败如何重试:a1 只重试流前失败(简单稳妥)/ a2 流中途失败截断已流文本重请求(复杂)
|
||||
- (b) 重试计数器粒度:每条消息预算 N 次(倾向)/ 每轮独立
|
||||
- (c) 退避策略:复用 retry.rs(1s→2s→4s 倾向)/ 用户可配
|
||||
- (d) 重试期 UI:错误气泡内「重试 n/m」(倾向)/ 独立 toast
|
||||
- **推荐**:**a1 + 每条消息预算 + 复用 retry.rs 退避 + 错误气泡内更新**
|
||||
- **关联**:todo F-260616-07
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a1 + 每条消息预算3次 + 复用 retry.rs 退避 + 错误气泡内更新**。流前失败重试,不碰流中途。**子决策:不加 Settings UI,硬编码默认 3 次(A)**。
|
||||
|
||||
#### F-260616-08 AI 数据获取工具突破 50 条上限
|
||||
- **背景**:MAX_LIST_RESULTS=50 硬覆盖 6 工具(list_projects/tasks/ideas/trash/search_files/read_file 搜索),配套只给 has_more/truncated 提示无 offset 翻页;knowledge_search min(3) 钳死。
|
||||
- **决策点**(4 子):
|
||||
- (a) 翻页范围:全量工具补 offset(对齐 read_file 统一)/ 仅 hot 工具(list_tasks/search_files)
|
||||
- (b) 翻页 limit 默认:沿用 50 / 提到 100-200
|
||||
- (c) knowledge_search 上限:20 / 50
|
||||
- (d) 是否加 get_count/list_all 探总量工具
|
||||
- **推荐**:原推荐不加探总量;用户决策:**需加 get_count/list_all 探总量工具**(AI 需知总量做分页策略,has_more 仅告知"还有"不知多少)
|
||||
- **关联**:todo F-260616-08
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:全量 offset + 沿用 50 + knowledge 20 + 加探总量工具(get_count/list_all)**。用户要求 AI 具备探总量能力。
|
||||
|
||||
#### F-260616-09 AiSession 单例→多会话并发架构
|
||||
- **背景**:用户需求(3 条消息强化):「应用级支持同时具备多会话」+「多个会话窗口来回切,**并行执行**」。现状 `AiSession` 应用级单例(state.rs:164 `ai_session: Arc<Mutex<AiSession>>`),messages/generating/stop_flag/pending_approvals 全一份;同一时刻只一个对话能跑。残留 bug:新建会话上下文残留(前端 newConversation 漏清 queue/generatingConvId/agentRound;后端 ai_conversation_create 漏清 agent_language/stop_flag)。
|
||||
- **决策点**(5 个子决策):
|
||||
- (a) **推进路径**:A 先做隔离修复(补漏清字段维持单例,解残留,低风险) vs 直接 B 架构升级 — 倾向 **A 先**(残留真 bug 立即解,B 另立项)
|
||||
- (b) **B 多会话形态**:AiSession 整体 HashMap<conv_id, SessionState> vs 仅拆 generating/stop_flag per-conv(messages/pending 已可按 conv reload) — 倾向**后者**(侵入小)
|
||||
- (c) **B 并发上限**:复用 llm_concurrency.global 限并发会话数防 token 暴增 vs 无上限 — 倾向**复用限并发**
|
||||
- (d) **多窗口 UI 形态**:(d1) 单面板侧栏会话列表切换+后台并行(改动小) vs (d2) 每会话独立 Tauri 窗口(useAiWindow.ts detached 已有基础可扩,改动大但「窗口来回切」语义最贴) — **待用户定**,倾向先 d1 后 d2
|
||||
- (e) **旧 loop 切换处理**:不退出各自跑完(真并发) vs 仍退出 — 倾向**不退出真并发**
|
||||
- **选项**:
|
||||
- a: A 先做隔离修复(B 前置,解残留) + B 立项排期(UI 待用户定 d1/d2)
|
||||
- b: 直接 B 架构升级(一步到位,大改+高风险)
|
||||
- c: 仅 A 隔离修复(满足"切会话不残留",并行执行缓做)
|
||||
- **推荐**:**a**(A 先解燃眉真 bug,B 按架构演进另立项;UI 形态 d 待用户拍板再定 B 的工作量)
|
||||
- **关联**:todo F-260616-09 / memory aichat-arch-extensibility(AiSession 单例未动架构债)
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a**(A 先隔离修复 + B 立项)。**UI 形态:d1+d2 都做**——侧边栏可切换,也可多窗口打开。先 d1(侧栏切换+后台并行),再 d2(独立 Tauri 窗口,detached 已有基础)。
|
||||
|
||||
#### F-260615-14 AiChat 气泡截图拷贝
|
||||
- **背景**:截图拷贝(气泡 DOM→图片→剪贴板)需加依赖 html2canvas(~90KB)或 dom-to-image-more(~3KB)。
|
||||
- **决策点**:选型?
|
||||
- **选项**:
|
||||
- a: html2canvas(~90KB,CSS 支持有限但社区成熟)
|
||||
- b: dom-to-image-more(~3KB,轻量,CSS 支持更弱)
|
||||
- c: 不做(文本拷贝 F-13 已够,截图 ROI 低)
|
||||
- **推荐**:**b**(做减法,3KB 轻量,气泡样式简单风险低)或 **c**(等用户反馈需求强度)
|
||||
- **关联**:todo F-260615-14
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:c 不做**。文本拷贝+代码块复制已覆盖核心需求,等用户真实反馈再定。
|
||||
|
||||
---
|
||||
|
||||
### ④类 — 设计方向(方案未定,需人定 A/B/C 选型)
|
||||
|
||||
#### F-260614-03 灵感对抗评估接 LLM
|
||||
- **背景**:df-ideas adversarial.rs `evaluate()` 纯启发式,接 LLM 需改签名注入 provider。
|
||||
- **决策点**:注入方式?
|
||||
- **选项**:
|
||||
- a: trait 解耦(df-ideas 定义 IdeaAnalyzer trait,推荐)
|
||||
- b: df-ideas 直接依赖 df-ai
|
||||
- c: closure 注入
|
||||
- **推荐**:**a**(trait 解耦,但前置 F-07 trait 下沉)
|
||||
- **关联**:todo F-260614-03 / F-07
|
||||
- **状态**:🟡 待决(阻塞于 F-07)
|
||||
|
||||
#### F-260616-07 阶段3 AI 执行闭环 + F-03 收口三件
|
||||
- **背景**:advance_task/run_workflow 注册为 AI 工具 + AiNode 自审闸门;F-03 收口三件(advance_task 注册 + update_task 描述/schema 移 status + df-storage tasks 白名单移 status)须同步落地防 AI 工具行为不一致。
|
||||
- **决策点**:阶段3 范围/优先级?(依赖 F-07 trait 下沉让 AiNode 可复用)
|
||||
- **选项**:
|
||||
- a: 全量(三件 + AiNode 自审 + run_workflow 工具)
|
||||
- b: 仅 F-03 收口三件(防行为不一致,先小步)
|
||||
- c: 暂缓(等 F-07 + 真实推进场景)
|
||||
- **推荐**:**b 先做 F-03 收口**(防现状行为不一致),AiNode 自审等 F-07
|
||||
- **关联**:todo F-260616-07 阶段3 / F-07
|
||||
- **状态**:🟡 待决(阻塞于 F-07)
|
||||
|
||||
#### F-260616-08 阶段4 Git 集成
|
||||
- **背景**:kind 字段 + git 闸门节点 + worktree 隔离。
|
||||
- **决策点**:阶段4 是否进路线?(工作流当前内部基础设施无真实 CI/CD 场景,R-PD-12 已否决做实 run_workflow)
|
||||
- **选项**:
|
||||
- a: 进路线(设计+实施)
|
||||
- b: 暂缓(等工作流有真实使用场景)
|
||||
- **推荐**:**b 暂缓**(对齐 R-PD-12 否决,等真实场景)
|
||||
- **关联**:todo F-260616-08 阶段4
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:b 暂缓**。对齐 R-PD-12 否决,等工作流有真实 CI/CD 场景。
|
||||
|
||||
#### T-260614-11 条件表达式引擎升级
|
||||
- **背景**:df-workflow conditions 仅支持 true/false 字面量,升级为真表达式求值。引擎设计好但无前端 UI 消费方(demoDag edges 无 condition 字段)。
|
||||
- **决策点**:求值器实现方式?(已暂缓:等工作流真实场景)
|
||||
- **选项**:
|
||||
- a: 手写求值器
|
||||
- b: 复活 set_skipped
|
||||
- c: default false + warn(均认可)
|
||||
- **推荐**:**⏸️ 暂缓**(无消费方,等 BuildNode 落地跑构建→测试→部署真实场景)
|
||||
- **关联**:todo T-260614-11
|
||||
- **状态**:⏸️ 暂缓
|
||||
|
||||
#### F-260614-08 决策治理产品化
|
||||
- **背景**:活契约/规格契约自检机制(当前散落文档机制)产品化为可操作功能。
|
||||
- **决策点**:产品化形态?(规格契约机制 devflow-spec-contract-mechanism 文档已定稿,落地链②-⑤未做)
|
||||
- **选项**:
|
||||
- a: 独立功能页(规格契约自检 UI)
|
||||
- b: 嵌入现有流程(锚点+AI自检+子代理活契约化)
|
||||
- c: 暂缓(机制先行文档化,产品化等需求)
|
||||
- **推荐**:**c 暂缓**(机制文档已定稿,产品化等真实需求驱动)
|
||||
- **关联**:todo F-260614-08 / memory devflow-spec-contract-mechanism
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:c 暂缓**。机制文档已定稿,产品化等真实需求驱动。
|
||||
|
||||
#### F-260614-09 项目 status 字段治理
|
||||
- **背景**:status 状态机规范化(planning/active/archived 等枚举约束)。F-09 前端已对齐(planning/active/completed),后端 df-core enum 7 值是独立大改。
|
||||
- **决策点**:后端 status 枚举收口范围?
|
||||
- **选项**:
|
||||
- a: 后端 enum 收窄对齐前端(planning/active/archived)
|
||||
- b: 双字段(status 生命周期 + stage 开发阶段,已否决过度设计)
|
||||
- c: 暂缓(DB 实际只产生 planning + deleted_at 软删二态,现状可接受)
|
||||
- **推荐**:**c 暂缓**(DB 实际二态,收口 ROI 低,等真实多态需求)
|
||||
- **关联**:todo F-260614-09 / F-09
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:c 暂缓**。DB 实际只产生 planning 二态,收口 ROI 低。
|
||||
|
||||
#### F-260614-10 知识库 MCP Server + Tier 2/3
|
||||
- **背景**:对外 MCP 暴露 + 分层存储(当前仅 Tier 1 全栈)。
|
||||
- **决策点**:MCP 暴露范围 + Tier 2/3 存储选型?
|
||||
- **选项**:
|
||||
- a: 全量(MCP Server + Tier2 向量 + Tier3 冷归档)
|
||||
- b: 仅 MCP Server(对外暴露 Tier1)
|
||||
- c: 暂缓(等知识库真实外部消费需求)
|
||||
- **推荐**:**c 暂缓**(Tier1 全栈已满足当前,等外部消费需求)
|
||||
- **关联**:todo F-260614-10
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:c 暂缓**。Tier1 全栈已满足当前,等知识库真实外部消费需求。
|
||||
|
||||
---
|
||||
|
||||
### 重投入排期(设计完备待实施,需人定优先级/时机)
|
||||
|
||||
> 这些项方案已定(📐设计完成/完备),非"待决策方向",而是"待排期投入"。需用户定做不做/何时做/优先级。
|
||||
|
||||
#### F-260614-07(F-07) df-ai-core trait 下沉拆 crate
|
||||
- **背景**:架构前置,4 项决策全定稿。退路可放 df-core。解锁 F-03/F-01。
|
||||
- **设计状态**:📐 完备(决策记录已收敛:原 F-03 A/B/C 作废,统一全局 AI trait 下沉独立 crate)
|
||||
- **决策点**:排期?(解锁多项后续,但拆 crate 重投入)
|
||||
- **推荐**:原推荐优先(可先放 df-core 过渡);用户决策:**拆独立 crate df-ai-core**(不放 df-core,一步到位)
|
||||
- **关联**:todo F-260614-07 / F-03
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:拆独立 crate df-ai-core**。不放 df-core 过渡,LlmProvider trait + 核心数据结构下沉独立 crate,df-ai/df-ideas/df-nodes 均依赖 df-ai-core。
|
||||
|
||||
#### F-260614-01 模型能力系统 Phase 1
|
||||
- **背景**:ModelCapability 数据模型 + ModelRouter 重写 + 7 调用点接入 + Settings 模型池 UI + AiChat 模型下拉。按需求自动匹配合适模型。
|
||||
- **设计状态**:📐 设计完成
|
||||
- **决策点**:排期?(依赖 F-07 trait 下沉)
|
||||
- **推荐**:F-07 后接续
|
||||
- **关联**:todo F-260614-01 / F-07
|
||||
- **状态**:🟡 待排期(阻塞于 F-07)
|
||||
|
||||
#### F-260614-06 导入历史项目(scan 第二步)
|
||||
- **背景**:description 走 LLM(复用 scan_project_with_ai)+ 采样保留内容图(待 F-260614-05 多模态)+ monorepo 一层 + 批量并发;抽 create_with_binding 缓解 TODO。
|
||||
- **设计状态**:📐 设计定稿(6 决策 06-14)
|
||||
- **决策点**:排期?(依赖 F-260614-05 多模态采样)
|
||||
- **推荐**:F-05 多模态后接续
|
||||
- **关联**:todo F-260614-06 / memory devflow-project-path-binding
|
||||
- **状态**:🟡 待排期
|
||||
|
||||
#### F-260614-02 技能联想「使用」
|
||||
- **背景**:首批 3 类联想已做,联想后实际触发/执行技能未实现。
|
||||
- **决策点**:「使用」语义?(执行本机 claude 技能?AI 调用?需明确)
|
||||
- **推荐**:需先澄清语义(关联 memory aichat-skill-slash-autocomplete)
|
||||
- **关联**:todo F-260614-02
|
||||
- **状态**:🟡 待澄清语义
|
||||
|
||||
#### F-260614-04 多 Provider 负载均衡池
|
||||
- **背景**:备用模型/多账号聚合,全局容量=min(各 provider 上限之和, global_cap)。
|
||||
- **决策点**:排期?(增强非阻断)
|
||||
- **推荐**:低优先(等 F-01 模型能力后)
|
||||
- **关联**:todo F-260614-04
|
||||
- **状态**:🟡 待排期
|
||||
|
||||
#### F-260614-05 模型能力系统 Phase 2(多模态)
|
||||
- **背景**:ChatMessage.content: String → Vec<ContentPart>(Text/Image);前端粘贴/拖拽图片;vision 模型自动路由。
|
||||
- **决策点**:排期?(解锁 F-06 导入采样)
|
||||
- **推荐**:中等(解锁 F-06)
|
||||
- **关联**:todo F-260614-05 / F-01
|
||||
- **状态**:🟡 待排期
|
||||
|
||||
#### AE-2025-04 会话级授权(Session Trust)
|
||||
- **背景**:同会话内用户批准过某类操作后,后续同类自动放行;换会话清空重审。首批 write_file + run_command。设计已定(目录级粒度 + 仅写+执行首批 + Webhook 走独立 execution_token)。
|
||||
- **设计状态**:📐 设计定(2026-06-16)
|
||||
- **决策点**:排期?(涉及 mod.rs AiSession + audit.rs 审批链)
|
||||
- **推荐**:中高(写→跑→看→改闭环高频连续操作,体验提升大)
|
||||
- **关联**:todo AE-2025-04
|
||||
- **状态**:🟡 待排期
|
||||
|
||||
#### T-260614-06 Settings.vue 拆 panel 子组件
|
||||
- **背景**:1042 行 god file,4 大功能域(AI 模型/Provider 表单/连接管理/通用设置)可拆 src/components/settings/。评估非低风险(纯重构零功能价值,新建 4 子组件 + props/emits + CSS 拆)。
|
||||
- **决策点**:排期?(单独立项做更稳)
|
||||
- **推荐**:低(纯重构零功能,等 god file 痛点加剧)
|
||||
- **关联**:todo T-260614-06
|
||||
- **状态**:🟡 待排期
|
||||
|
||||
---
|
||||
|
||||
### ④类续 — 设计方向(新增·batch55迁移)
|
||||
|
||||
#### UX-2025-04 断线保文(incomplete标志)
|
||||
- **背景**:流式中断时已接收文本不丢弃;stream_llm mid-stream error 改返回 partial_text + incomplete 标志;agentic 收 incomplete→正常入库+AiCompleted(非AiError)+「⚠ 响应因网络中断不完整」+「继续生成」按钮。
|
||||
- **决策点**:改 stream_recv.rs 流式核心是否做?(中风险,回归可能)
|
||||
- **选项**: a:授权推进(关联 DEC-260616-03 已决a) / b:暂不碰
|
||||
- **推荐**:**a**(DEC-03 已授权,断线保文是用户体验硬伤)
|
||||
- **关联**:todo UX-2025-04 / DEC-260616-03
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a**(授权推进。DEC-03 已授权,断线保文是用户体验硬伤)。
|
||||
|
||||
#### ARC-260615-03 df-execute 归宿
|
||||
- **背景**:df-execute 非空壳(shell.rs execute() 已完整实现+被 tool_registry.rs run_command 复用)。原todo「76行/1函数+TODO」基于 lib.rs 空判过时。
|
||||
- **决策点**:合并进 df-nodes(破职责分离+动依赖树) vs 维持独立?
|
||||
- **选项**: a:维持独立(职责清晰:节点定义vs执行运行时) / b:合并df-nodes(减少crate数)
|
||||
- **推荐**:**a**(维持独立,转架构维护记录非清债)
|
||||
- **关联**:todo ARC-260615-03
|
||||
- **状态**:🟡 待决
|
||||
|
||||
#### ARC-260615-07 中期技术债7件
|
||||
- **背景**:df-core改名df-types / IPC层抽取df-app / AI loop下沉df-ai / 3 view绕store调api / 类型契约ts-rs代码生成 / AiSession多会话 / AppState分组 / IPC命名统一。
|
||||
- **决策点**:哪些值得投?哪些暂缓?
|
||||
- **选项**: a:逐项评估后挑高ROI的做 / b:全部暂缓(等业务功能优先)
|
||||
- **推荐**:**b 暂缓**(当前业务功能未饱和,技术债不急)
|
||||
- **关联**:todo ARC-260615-07
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a**(逐项评估挑高 ROI 的做,用户要求推进非暂缓)。
|
||||
|
||||
#### B-260615-41 工作流执行无进度指示
|
||||
- **背景**:长时间工作流执行用户不知进度/剩余时间。需进度条+步骤提示+预估剩余时间。
|
||||
- **决策点**:实现深度?纯前端 vs 后端emit事件驱动
|
||||
- **选项**: a:轻量(WorkflowDetail.vue 进度条+步骤文本,后端复用已有NodeStarted/Completed事件) / b:完整(后端新progress事件+预估算法)
|
||||
- **推荐**:**a 轻量**(复用现有事件,最小改动)
|
||||
- **关联**:todo B-260615-41
|
||||
- **状态**:✅ 已决(2026-06-16)— **决策:a 轻量**(复用现有 NodeStarted/Completed 事件,纯前端消费)。
|
||||
|
||||
#### B-260615-43 无撤销重做功能
|
||||
- **背景**:AI操作(delete_project等)无撤销。操作历史栈+撤销/重做UI。
|
||||
- **决策点**:撤销范围?全局vs仅AI操作?
|
||||
- **选项**: a:仅AI工具操作(delete_task/delete_project/restore/run_command等) / b:全局(含项目/任务CRUD) / c:暂缓(二次确认已部分覆盖)
|
||||
- **推荐**:**c 暂缓**(High-risk工具已有二次确认AE-05,撤销复杂度高)
|
||||
- **关联**:todo B-260615-43
|
||||
- **状态**:🟡 待决
|
||||
|
||||
### C类 — 用户实测/澄清(需用户操作给反馈,主会话无法代办)
|
||||
|
||||
#### S-260615-01 aichat API Key 401 根因
|
||||
- **待用户操作**:跑直连 curl 测试,区分 key/provider_type/base_url/model 哪项错。见 [aichat-apikey-401排查-2026-06-15.md](./09-问题排查/aichat-apikey-401排查-2026-06-15.md)「验证步骤」。
|
||||
- **背景**:代码链路全对(保存 keyring/读取/鉴权头/URL 拼接),401 来自服务端非 devflow bug。根因四选一。
|
||||
- **状态**:🟡 待用户反馈
|
||||
|
||||
#### S-260614-01 「显示多开」需求澄清
|
||||
- **待用户操作**:截图确认。用户报"设置勾选显示多开但 AiChat 未显示",全 src grep 零命中,疑似旧版本/指分离窗口/想新增开关。
|
||||
- **状态**:🟡 待用户澄清
|
||||
|
||||
#### S-260614-02 审批可见性实测重评
|
||||
- **待用户操作**:实测 tc 卡片是否渲染。B-01 修复后 pending_approvals 内存态不再被 switch 清空,前端查询有数据,但 state.pendingApprovals 在 AiChat.vue 是否有兜底渲染仍需实测。
|
||||
- **选项**:A 加兜底渲染 / B 实测确认(去重:AR-3 修完已缓解,改实测重评)
|
||||
- **状态**:🟡 待用户实测
|
||||
|
||||
#### T-260614-01 多项 tauri dev 实测
|
||||
- **待用户操作**:Sprint 9/10/14/15/16/18 多项未 tauri dev 实测 — 评分 IPC 缩放 / update_full / promote_idea / Store getter / token 落库 / 知识库 Tier 1 全栈 / LLM 并发 Semaphore / 知识生命线(#54 跟踪)。
|
||||
- **状态**:🟡 待用户实测
|
||||
|
||||
#### T-260614-02 切对话不中断路由实测
|
||||
- **待用户操作**:部分场景运行时实测(A 路线场景 2/3)。
|
||||
- **状态**:🟡 待用户实测
|
||||
|
||||
---
|
||||
|
||||
## 已决归档
|
||||
|
||||
(空 — 用户拍板后移此区)
|
||||
93
docs/待审查.md
93
docs/待审查.md
@@ -23,8 +23,101 @@
|
||||
|
||||
## 当前队列
|
||||
|
||||
### CR-260616-35 batch59 CR-34-1 守卫 + CR-30 流式重试对齐决策a1 + UX-2025-04 断线保文 — 待审
|
||||
|
||||
- **范围**: 3 agent 合并批(workflow wdlt0xfl6,主代独立核查全过)。①**CR-34-1** useAiPanel.ts:102 守卫加有效性检查 `|| !list.some(p=>p.id===activeProvider)`(deleted provider 残留回落 DB is_default) ②**CR-30-1/CR-30-2 + UX-2025-04 合并**:stream_recv.rs `StreamResult` enum(Complete/Partial/InitFailed 三分支) + `classify_status_or_class`(4xx Fatal/5xx+429+timeout Retryable 镜像 retry::is_status_retryable) + agentic.rs 重试对齐决策 a1(Init 失败重试复用 retry::backoff_delay 1s→2s→4s±20%jitter + 30s 总预算 retry_deadline + Fatal 分类 4xx 立即放弃; MidStream Partial 不重试保文→入库 + AiCompleted(incomplete=true) + 系统提示「响应因网络中断不完整」) + 删 3 处误导注释(agentic.rs:12/commands.rs/state.rs) + retry.rs `pub mod` + `backoff_delay`/`is_status_retryable` 改 `pub` 暴露供 src-tauri 复用 + useAiEvents.ts:177 补 `case 'AiStreamRetry'`(消除死事件穿透) + AiCompleted case 处理 incomplete + types.ts:204/mod.rs `incomplete?:boolean` 字段(所有 emit 点补 None 向后兼容) + i18n aiStreamRetry/responseIncomplete 双语。
|
||||
- **维度**: 流式核心中风险(重试循环正确性/保文语义/跨 crate pub 暴露影响面) + 前端事件消费完整性 + 决策 a1 对齐度(Init 可重试 ≤max_retries+jitter+30s+Fatal, MidStream 不重试) + B-260615-05 保留(空文本无 finished 仍 InitFailed 交重试)。
|
||||
- **commit**: 待提交(累积 ~30 文件攒批)。
|
||||
- **主代独立核查**: ✅ 全过(useAiPanel:102 守卫 / stream_recv:97 enum 三分支 + 注释 / agentic:242 retry_deadline + :274 Partial 不重试 + :286 InitFailed 重试 + :320 backoff_delay 复用 + :360 if incomplete 保文入库 + :400 emit incomplete:Some(true) / useAiEvents:177 AiStreamRetry case / types:204 incomplete / retry.rs:62+74 pub + agentic:14 `use df_ai::retry` 跨 crate 通)。
|
||||
- **审查 agent 待复审重点**: ①stream_recv StreamResult 三分支边界(Partial vs InitFailed 空文本路径,B-260615-05 保留点) ②agentic 重试循环 permit RAII 释放/边界(max_retries=0/guard.reset) ③跨 crate retry pub 暴露是否过度(retry_with_backoff 仍 pub(crate)) ④AiCompleted incomplete 前端消费完整性(系统提示气泡镜像后端) ⑤UX-2025-04「继续生成」按钮**未做**(保文核心 ✅,按钮可复用 UX-2025-03 重试能力或按需补)。
|
||||
|
||||
---
|
||||
|
||||
## 已审归档
|
||||
|
||||
### CR-260616-34 batch58 F-260616-10 provider 默认值重启失效 bug — ⚠ 已审(PASS-WATCH)
|
||||
|
||||
- **审查时间**: 2026-06-16(主线程兜底·agent 撞 GLM 限流 1305 · grep/read 核验源码 + 类型确认)
|
||||
- **总体结论**: ⚠ **PASS-WATCH** — 🔴0 🟡1 ⚪3(核心 bug 双恢复修复 OK,已删除 provider 残留守卫 med 待修)
|
||||
- **逐件核验**:核心 bug 修复 ✅(重启 activeProvider=null → useAiPanel.ts:53-54 模块级 savedProvider 同步恢复 + loadProviders:101-104 DB is_default 兜底,双恢复链路)/ is_default 字段确认 ✅(types.ts:177 AiProviderConfig.is_default boolean,ai_list_providers 返回)/ cycleProvider 兜底 ✅(AiChat.vue:1184 startId=activeProvider||is_default||null 三级兜底,L1187 Math.max(idx,0) 防 -1 越界)。
|
||||
- **🟡 CR-34-1(med,已删除 provider 残留未校正)**:useAiPanel.ts:101 `if (!state.activeProvider)` 守卫只查 null 不查有效性。localStorage savedProvider 指向已删除 provider(L54 设 activeProvider=deleted-id)时,loadProviders 守卫 false 跳过 DB is_default 恢复 → activeProvider 残留无效 id → cycleProvider:1185 findIndex=-1 → :1187 next=ps[1] 跳过 ps[0],且潜在消费方(发消息读 activeProvider 调后端)用无效 id。修法:守卫改 `if (!state.activeProvider || !list.some(p => p.id === state.activeProvider))` 残留无效时回落 DB is_default。
|
||||
- **⚪ low**:1(L52 注释「以 DB 为准」与行为不符,实际 savedProvider 优先 DB 兜底,行为合理注释误导)/ 2(setProvider:121 void appSettings.set 持久化失败静默,仅影响重启恢复可接受)/ 3(多窗口/分离窗口 activeProvider 一致性:模块级 state 各 webview 独立,主 setProvider 写 SQLite 分离窗口 state 滞后,既存架构非 CR-34 引入)。
|
||||
- **待修项回流 todo**: **CR-34-1**(med,useAiPanel.ts:101 已删除 provider 残留守卫改查有效性)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-33 batch57 CR-260615-04 splitBlocks→marked.lexer() — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(主线程兜底·agent 撞 GLM 限流 1305 · grep/read 核验源码)
|
||||
- **总体结论**: ✅ **PASS** — 🔴0 🟡0 ⚪3
|
||||
- **逐件核验(全 PASS)**:splitBlocks(AiChat.vue:671-691 marked.lexer 切块,L672 getMarked 取实例 + L676 未就绪兜底 `return [text]` 不引入正则 + L677 lexer tokenize + L678-689 for 循环)/ code token 整段一块(L681-685 `type==='code'` + raw.trim 守卫空代码块跳过 + continue)/ 非代码 token 按 `\n{2,}` 切段(L688 split + b.trim 守卫)/ 空 token 非 string raw 防御(L679 `typeof string` continue)/ 空兜底(L690 `blocks.length ? blocks : [text]`)/ 签名不变(`splitBlocks(text):string[]` + renderStreamingBlocks:723 调用)/ 切块边界与 parse 渲染边界一致(同 marked 实例同围栏规则,CR-260615-04 根治目标达成)/ 流式路径回归(renderStreamingBlocks:718-733 + parseBlock/parseBlockNoCache 块缓存机制不变)。
|
||||
- **⚪ low**:1(lexer 全文 tokenize 性能略高于旧正则,rAF 节流+块缓存吸收,流式实测无影响)/ 2(末块未闭合围栏场景 lexer 可能把后续段落吞进 code raw,流式中间态短暂切块不准,末块重 parse 修正)/ 3(L690 空兜底 lexer 空文本返空数组时回退原文)。
|
||||
- **待修项回流 todo**: **无**(核心目标切块/渲染边界一致达成,防御充分)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-32 batch57 B-260619 Knowledge.vue CSS窄屏标题挤压 — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(独立审查 agent · 亲跑 vue-tsc EXIT 0 + grep/read 核验源码)
|
||||
- **总体结论**: ✅ **PASS** — 🔴0 🟡0 ⚪3
|
||||
- **逐件核验(全 PASS)**:min-width:0 传播链完整(L576 kn-detail-panel → L622 detail-head → L623 detail-title-row flex:1 → L625 detail-title,窄屏标题可正常收缩)/ 760px 断点 column-wrap 与 grid 兼容(L730 kn-layout 单列降级 + L731 detail-head flex-direction:column 无冲突)/ 按钮换行间距(L626 detail-actions gap 6px + flex-wrap:wrap,L732 窄屏 width:100%)。
|
||||
- **⚪ low**:1(L623 `.detail-title-row { overflow:hidden }` 冗余,word-break 多行标题 height auto 自适应不真裁断,语义不清,建议删保留 min-width:0+flex:1)/ 2(L733 窄屏字号降级仅覆盖 .detail-title 18→15px,编辑态 .edit-input-title L692 固定 16px 未同步,窄屏编辑态 16px 反超展示态 15px)/ 3(18→15px 偏激进,详情主标题窄屏建议 ≥16px)。
|
||||
- **待修项回流 todo**: **无**(三 low 风格/一致性微调非阻断)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-31 batch56 F-260616-08 分页 offset+探总量 — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(主线程兜底·agent 撞 GLM 限流 1305 · grep/read 核验源码形态;**未亲跑 cargo check**,标准 API 语法无编译风险,待 agent GLM 恢复补 cargo 验证)
|
||||
- **总体结论**: ✅ **PASS** — 🔴0 🟡0 ⚪2
|
||||
- **逐件核验(全 PASS)**:①offset 边界(tool_registry.rs:216/237/254 offset `as_u64().unwrap_or(0)`→usize,JSON 负数 as_u64 None→0,skip(offset).take(limit) 超 total 取空不 panic;has_more `(offset+page.len())<total` 超时 false)/ ②total 准确(list_projects:214-215 `list_active().len()` 分页前全量=真实总量;list_tasks:236/list_ideas:253 同)/ ③探总量与 list 一致(get_project_count:1091-1093 list_active().len()=list_projects:214-215 同源;get_task_count:1104-1108 project_id 分支+list_all 兜底=list_tasks:231-234 同逻辑,range 一致)/ ④knowledge_search 解钳(knowledge.rs:110 `.min(20)` 替原 `.min(3)`,允许 LLM 翻更多候选合理)/ ⑤schema 描述(:208/225/246 含 offset/limit/total/has_more 翻页语义 LLM 可理解)。
|
||||
- **⚪ low**:1(内存放大:list_*/get_*_count 先全量 load(list_active/list_all)再 skip/take,数据量大时内存放大;AI 工具调用 + MAX_LIST_RESULTS 钳 limit 实际可控)/ 2(list_tasks/get_task_count 用 list_all 未排除软删任务,而 list_projects/get_project_count 用 list_active 排除软删,任务与项目软删语义不对称;但 get_*_count 与 list_* 同源一致,且为既存逻辑非 CR-31 引入)。
|
||||
- **待修项回流 todo**: **无**(五维度全 PASS)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-30 batch56 F-260616-07 流式自动重试 — ⚠ 已审(ISSUES)
|
||||
|
||||
- **审查时间**: 2026-06-16(独立审查 agent · 亲跑 cargo check EXIT 0 + cargo test df-ai retry 6 passed **附 log 末尾** + grep/read 核验 + 重试循环正确性专项)
|
||||
- **总体结论**: ⚠ **ISSUES** — 🔴0 🟡2 ⚪3(核心重试循环逻辑正确 permit/guard.reset/request 重建均 OK,但退避策略注释误称对齐 + AiStreamRetry 死事件 med)
|
||||
- **亲跑 `cargo check --workspace`** ✅ EXIT 0(8 warning 全既存 dead_code 非本批)+ **`cargo test -p df-ai retry`** ✅ EXIT 0 **6 passed**(backoff_is_monotonic_within_jitter/status_classification/fatal_aborts_immediately/first_attempt_ok/retry_once_then_ok/all_retryable_exhausts,finished 3.35s)。
|
||||
- **重试循环正确性专项(全 PASS)**:permit 持有释放 ✅(`_global_permit`/`_per_conv_permit` agentic.rs:239-240 外层函数体作用域,耗尽 return:285/成功 drop:333-334 均 RAII 释放无并发槽泄漏,重试期间持 permit 有意防新请求挤占)/ 耗尽路径 guard.reset ✅(:284 `guard.reset().await` return 前显式复位 generating,max_retries=0 时 `0..=0` 单次失败 is_last→reset+return 边界正确)/ request 每轮重建 ✅(:248-263 每轮 `session_arc.lock()`+`build_for_request` 重建 messages 无累积/丢失,与循环外:207-215 `request` 变量重复轻微冗余无害)。
|
||||
- **🟡 CR-30-1(med,退避策略注释误称对齐)**:agentic.rs:298 `1u64 << retry_attempt` 纯指数无 jitter/无总预算/一律重试(含 MidStream);retry.rs:67-78 `backoff_delay` 有 ±20% jitter + 30s 总预算(:34)+ 4xx 不可重试分类(:102-104 Fatal 立即放弃)。三处注释(agentic.rs:37/commands.rs:1106/state.rs:185)均称「对齐 retry.rs 退避策略(1s→2s→4s+jitter)」与实现不符。修法:要么 agentic 加 jitter+总预算+错误分类真对齐,要么删注释「对齐 retry.rs」改为「独立简化策略」。
|
||||
- **🟡 CR-30-2(med,AiStreamRetry 死事件 + MidStream 重试文本混乱)**:后端 emit AiStreamRetry(agentic.rs:310),types.ts:214 有 variant,但 useAiEvents.ts switch 无 `case 'AiStreamRetry'`(十 case 无 retry)事件穿透忽略。更严重:MidStream 失败重试时已 emit 的 AiTextDelta 累积进前端 currentText,重试新 delta 追加 → 文本重复/混乱(stream_recv.rs:210/240 MidStream return None,agentic.rs:294 一律重试无清空 currentText 机制)。修法:useAiEvents 补 case + 重试前清空 currentText;或后端 MidStream 失败不重试只重试 Init 失败(对齐决策 a 只重试流前失败)。
|
||||
- **⚪ low**:1(agentic.rs:243/317 `last_error` 声明赋值但 result 分支:323-330 未读 dead code)/ 2(:294-296 MidStream 一律重试注释承认「简化」,与决策 a 只重试流前失败相悖)/ 3(run_agentic_loop 3 调用点 commands.rs:108/204/444 非登记「4 入口」,try_continue 走审批恢复复用非独立入口)。
|
||||
- **待修项回流 todo**: **CR-30-1**(med,退避策略注释对齐)+ **CR-30-2**(med,AiStreamRetry 死事件+MidStream 重试文本混乱)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-29 batch56 ARC-06 composable 循环依赖破环 — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(主线程兜底·agent 撞 GLM 限流 1305 · grep/read 核验 import + 源码)
|
||||
- **总体结论**: ✅ **PASS** — 🔴0 🟡0 ⚪1
|
||||
- **逐件核验(全 PASS)**:①循环依赖真破(useAiEvents.ts import L14-23 无 useAiSend,改 L284 `emit('ai-drain-queue')` 事件总线;useAiSend.ts:25 仍 import useAiEvents(startListener)单向,双向环已断)/ ②事件总线桥接(useAiEvents:284 emit + useAiSend:395-398 initDrainQueueListener `if(_drainUnlisten) return` 幂等守卫 + stores/ai.ts:134 void 注册)/ ③findToolCall 下沉一致(aiShared.ts:41-51 反向扫 messages + 同消息正向扫 toolCalls,两调用方 import 同一实现,注释:37-40 说明反向扫描避免陈旧引用)/ ④startApprovalTimer 幂等(aiShared.ts:66 `if(_approvalTimers.has) return` 同 id 不重建 + clearApprovalTimer/clearAllApprovalTimers 清理完整)。
|
||||
- **⚪ low**:1(事件总线桥接理论竞态:initDrainQueueListener stores/ai.ts:134 void 不 await,注册前若 AiCompleted 到达事件丢失 drainQueue 不触发;实际初始化远早于首次生成完成低风险,原 direct call 同步无此问题,可靠性微小降级)。
|
||||
- **待修项回流 todo**: **无**(四维度全 PASS,循环依赖真破)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-28 batch56 F-260616-06 审批幂等+防抖 — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(主线程兜底·agent 撞 GLM 限流 1305 · grep/read 核验源码 + 方法存在性确认)
|
||||
- **总体结论**: ✅ **PASS** — 🔴0 🟡0 ⚪2
|
||||
- **逐件核验(全 PASS)**:①幂等三态覆盖(commands.rs:220 内存 pending_approvals.remove None → :224 查审计表 find_by_tool_call_id → :227 executed/rejected/failed 返回 Ok「已处理」三态全覆盖;pending 态落 :231 Err 合理——内存 pending_approvals 丢失即审批上下文不可恢复,DB pending 占位仅日志非可恢复审批)/ ②防抖(useAiSend.ts:307 _pendingApprovalIds.has 守卫无时间窗口竞态 + :308 add + :332-334 finally delete 无论成功异常均清理,模块级 Set 不泄漏)/ ③find_by_tool_call_id 存在确认(crud.rs:1198-1201 `pub async fn(&self,&str)->Result<Option<AiToolExecutionRecord>>`,:224 unwrap_or_default Err→None→:231 Err,DB 故障不误判已处理)。
|
||||
- **⚪ low**:1(pending 审计记录 + 内存 pending_approvals 丢失→:231 Err「未找到挂起的审批」文案略困惑,实际审批上下文已不可恢复 Err 正确,文案对有 pending 审计记录场景不精确)/ 2(防抖 _pendingApprovalIds 模块级跨调用累积,finally 清理可靠无泄漏,机制说明非问题)。
|
||||
- **待修项回流 todo**: **无**(三维度全 PASS)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-27 batch54 复核-新⑪ detach 清主窗口 state 看门狗幽灵(useAiWindow.ts) — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(主线程兜底·agent 撞 GLM 限流 1305 · grep/read 核验 + vue-tsc EXIT 0)
|
||||
- **总体结论**: ✅ **PASS** — 🔴0 🟡0 ⚪0
|
||||
- **逐件核验(全 PASS)**:detachPanel(useAiWindow.ts:28-38 快照在清 state 前写入 — L28-31 localStorage.setItem df-ai-gen/df-ai-text → L37-38 清 state.streaming/generatingConvId,顺序正确)/ state 独立性(主/分离窗口独立 webview JS context,resumeInDetached:87-119 靠 localStorage df-ai-gen/df-ai-text 重建 streaming L116-117,反证清主窗口 state 不影响分离窗口生成态)/ watchdog 兜底(stopListener clearStreamWatchdog 已由 CR-260615-24 兜底,本次仅清 state 视觉残留,注释:32-36 说明链路)/ reattach/closeDetachedWindow 清快照(L82-83/L125-126)。
|
||||
- **待修项回流 todo**: **无**(全件 PASS)。
|
||||
|
||||
---
|
||||
|
||||
### CR-260616-26 batch53 F-05 去重根治(audit.rs High risk 审批前缓存命中去重) — ✅ 已审(PASS)
|
||||
|
||||
- **审查时间**: 2026-06-16(独立审查 agent · 亲跑 cargo + vue-tsc 双 EXIT 0 **附 log 末尾证据** + grep/read 核验全件 + 边界核验)
|
||||
|
||||
Reference in New Issue
Block a user