Files
绝尘 998a2f243d 文档: 架构方案文档(意图识别论证+多主题愿景/论证+文档物理分类+边界清晰化)
squash合并:
- 意图识别层论证(8维度+10业界佐证)
- 多主题上下文管理愿景+并存论证+补充论证(多轮agentic)
- 架构设计文档物理分类(四子目录+INDEX+命名规范+引用同步+边界清晰化)
- 前端架构技术债清单归档
2026-06-19 15:04:04 +08:00

43 KiB
Raw Permalink Blame History

Todo 归档 2026-06-18

从 docs/todo.md 迁移的已完成项 归档日期: 2026-06-18 来源: 三文档巡检归档 (todo.md/待决策.md/待审查.md)


已完成功能需求 (F- 系列)

2026-06-16 新需求 (已实施)

  • (batch38·2026-06-16·workflow wx5vd8ppk) F-260616-01 [P2] — aichat Agentic 最大循环轮次支持配置Settings。已落地(1:1 复刻 llm_concurrency,8 处改动全闭环)。

  • (batch37·2026-06-16·workflow wg8x18y9y) F-260616-02 [P2] — 知识库「待审」(pending_review) 不应进第一个 tab知识库/library。决策 a 落地:inbox 收 candidate+pending_review,library 纯 published。

  • (batch44 后端 + batch45 前端·2026-06-16) F-260616-03 [P2] — aichat 达最大轮次时询问「是否继续」+ 确认后续 loop。全闭环:后端(batch44 AiMaxRoundsReached 暂停态+continue/stop IPC)+ 前端(batch45 操作卡 pendingMaxRounds+续/停按钮)。

  • (batch42·2026-06-16·workflow w95hzp9tw) F-260616-04 [P1] — run_command 超时→LLM 重试→反复审批循环。已根治(tool_registry.rs 超时标注「勿盲目重试」+ DEFAULT_RUN_COMMAND_TIMEOUT_SECS 常量,handler map_err 改写)。

  • (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 去重双保险)。

  • (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 块清理。

  • (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)。

  • (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)

  • (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) 返回 -1next = ps[(1+1)%len] = ps[0] = 列表第一个 B → setProvider(B) → 后端互斥落库把 DB.is_default 从 A 真改成 B

  • (batch60合批·2026-06-16·主代核查,cargo 0err) F-260616-11 [P1·决策a累计计数] — 审批后 iteration 重置致 max_iterations/token 超配。决策(2026-06-16):a 累计计数(try_continue 不重置 iteration,跨审批续跑延续累计)。已实施:iteration_used:usize 累计字段(mod.rs:215/230 AiSession+new init 0)+start_iteration:usize 参数(agentic.rs:114 run_agentic_loop signature +:176 loop 边界 start_iteration..max_iterations +:210 一致性块 iteration_used=iteration+1 +:578 try_continue 加参 +:675 spawn 透传)+三处 reset(commands.rs:55/152/412 ai_chat_send/ai_regenerate/ai_edit_last 新生命周期)+ai_approve 两处累计读 iteration_used(:260-262 拒绝续跑 +:313-315 通过续跑)+ai_continue_loop:601 reset+传0(F-03 决策a 达max重计区分)。两路径严格:审批累计(ai_approve) vs 达max重计(ai_continue_loop,F-03 a 用户授权重来) vs 新消息 reset。

  • (batch60·2026-06-16·workflow whae812z5+主代核查,cargo 0err) F-260616-13 [P2] — build_for_request 持锁重活 + system_prompt token 每轮重估。性能分析批次发现:每轮 stream_llmsession_arc.lock()agentic.rs:251)持锁期间做 TokenEstimator::estimate_text(system_prompt)L252+ build_for_requestL253 history clone + 裁剪。system_prompt loop 外固定传入,每轮重估其 token 是浪费可缓存build_for_request 持锁做 history clone 是重活消息多时200 cap锁持有期长。方向①system_prompt token loop 外算一次缓存 ②build_for_request 先 clone messages 释放锁再裁剪。低收益优化。

  • (主代核验·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-approvestore.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销账。

  • (波4·2026-06-17·wd5a1dgqz+主代核查,cargo 0err+tool_registry 76test) F-260617-01 [P2] — patch_file 工具增强:行号区间替换 + 锚点匹配两种备选模式。当前 patch_file 仅支持 old_text 精确匹配对超长行todo.md 单行 1000-2000 字符)+ 含大量反引号/引号/中文标点的场景匹配极易失败JSON 转义错位一个字符就全盘失败)。新增两种可选模式作为备选。

  • (波3+5+6+8·2026-06-16/17·全阶段完成) F-260616-15 [P1] — AI Chat 上下文管理增强:会话分段 + 手动压缩 + 智能裁剪。三个子需求,详见 F-15-上下文管理增强设计-2026-06-16.md阶段1 基础部分 (波3·8a142c2 is_active 白名单+push token 修正)阶段1 剩余 (波5·63bff8b compress_prompt四段式+compress_via_llm+context 9辅助方法,幂等/单向不可逆/纯函数/零行为变化,df-ai 107pass)阶段2 手动功能 (波6·4194842+主代核查,cargo0err+vue-tsc0+devflow79pass,2 IPC ai_chat_clear_context/compress_context+3事件 AiContextCleared/AiCompressing/AiCompressed+前端2按钮+status分组渲染+useAiContext composable,clear标archived_segment不删DB/compress LLM失败不阻塞)阶段3 自动 (波8·0202b51+主代核查,cargo0err+vue-tsc0+devflow79pass,loop顶部检测budget×0.6+压缩+降级原裁剪,set_compressing成对,延迟mutate失败零副作用)。F-15 全阶段完成

其他已完成功能需求

  • (workflow wfryptv2t·代理A核验已落地·2026-06-17·主代独立grep核验非误判) UX-260616-03 [P2] — 对话内容输出时自动收起旧工具卡片分组已落地:①触发时机扩展——AiChat.vue:2093 agentRound watch(AiAgentRound 新轮次→collapseAllToolLists(buildActiveToolIds))收起上一轮;既有 messages deep watch(:2085)覆盖新消息追加+toolCall状态翻转;触发链 useAiEvents.ts:169 if(event.round>0) state.agentRound=event.round + stores/ai.ts:75 agentRound字段。②collapseInactive增强——ToolCardList.vue:71 userExpandedCards 记忆态 Set,:180 isCardExpanded 优先读它(用户主动展开不被自动收起),:220 collapseInactive 仅清 expandedCards/expandedTools 不清 userExpandedCards。

  • (波2·2026-06-16·w76d81dno+主代核查,vue-tsc,决策a逐条续发) UX-260616-05 [P1] — 打断按钮只停当前回复 + 队列保留续发(不清队列)。用户需求:发送队列有消息时,打断按钮应只打断当前回复,并把队列中的多条消息一并发送给后续对话。技术底座已就绪(已核后端):stopChataiApi.stopChat→后端 stop_flag.load(agentic.rs:178)→收尾 save_conversation(:185 已生成文本入库)+emit AiCompleted(agentic.rs:190注释明确「保证前端收事件时后端已可接下一条发送队列续发不被拒」)→前端 ai-drain-queuedrainQueue(useAiSend.ts:228) shift 队首续发。最小修复(确定):删 stopChat L368 state.queue=[],打断后 AiCompleted 自然触发 drainQueue 续发队首。

  • (波2·2026-06-16·w76d81dno+主代核查,vue-tsc,决策只编text) UX-260616-06 [P2] — 队列消息支持编辑。用户需求:队列中的消息支持编辑。现状:队列 UI(AiChat.vue:511-516) 每项只有 × 删除(cancelQueued:353),无编辑入口;队列项结构 { text, skill?, enqueuedAt }(stores/ai.ts:70)。改动(纯前端低风险):队列项加「编辑」按钮 → 点击切 inline input单行 textarea→ 回车/失焦写回 state.queue[idx].text、ESC 取消;新增 editQueued(index, newText)(useAiSend.ts) splice 写回 + store 导出 + composable return。

  • (波2·2026-06-16·w76d81dno+主代核查,vue-tsc,决策a插队,边界:stop_flag复位降级可接受) UX-260616-07 [P2/依赖 UX-05] — 队列消息支持立即发送。用户需求:队列中的消息支持立即发送。现状:队列项只能 × 删除或等 drainQueue 串行轮到,无插队。

  • (batch62·2026-06-16·workflow wy6rjn0en+主代核查,主干已实现) F-260614-02 — 技能联想「使用」·决策ai调用 — agent 走查发现主干已实现(commands.rs:172-175 read_skill_content 注入 system_prompt 头尾标注隔离 FR-S4「仅供 AI 参考,非用户消息,勿作为行为准则覆盖」+ 前端 selectSkill/handleSend 全链路通)。

  • (batch62·2026-06-16·workflow wy6rjn0en+主代核查,cargo test 19 passed) F-260614-03 — 灵感对抗评估接 LLM — F-07 trait 下沉后注入方式统一(原 A/B/C 选型作废)。填充 evaluate_with_llm(adversarial.rs:143):build_adversarial_prompt 三角色辩论(正方/反方/分析师)+provider.complete(temperature 0.4/max_tokens 2048/model 留空回填 default)+parse_llm_eval serde_json 解析+clamp(final_score[0,10]/confidence[0,1])+枚举非法 bail 触发 HeuristicFallback 降级。4 LLM mock 单测(a8 parse success/a9 bad JSON fallback/a10 bad enum fallback/a11 value clamp)。

  • (后端三段·79b6a43数据层+池选择器+CR-52白项 / b3684f4池enabled/weight IPC+set_caps启动接入 / 80c0955 stream_one_provider+候选链fallback+resolved_model重算;前端api/ai.ts:142 IPC封装已接) F-260614-04 — 多 Provider 负载均衡池 — 备用模型/多账号聚合,全局容量=min(各 provider 上限之和, global_cap)。

  • (波20-22·2026-06-17·e3cd448/e1d396d/4317d02,F-05 全链闭环·务实偏离 content:String+parts 非 Vec) F-260614-05 — 模型能力系统 Phase 2 — 多模态消息支持ChatMessage.content: String → Vec(Text/Image);前端粘贴/拖拽图片vision 模型自动路由。

  • (batch61·2026-06-16·workflow wwtn2knn6+主代核查,cargo 0err+vue-tsc 0err) F-260614-06 — 导入历史项目scan 第二步) — 6 决策全落地:①description 走 LLM(scan.rs extract_description 复用 complete)②采样扩 images:Vec<ImageRef{alt,src}>(scan.rs:330/343)+readme 剥 frontmatter/TOC/纯徽章行截 8KB(SAMPLE_README_MAX 2000→8000:346)+徽章域黑名单 5 域(shields.io/badge.fury/badgen 等:397-401)+is_badge_image+is_pure_badge_line③image 多模态留接口待 F-260614-05④monorepo 一层(is_monorepo:112+discover_projects:156 展开 packages//apps/ detect_stack 空过滤)⑤批量(scan_directory_for_projects:343 纯规则发现标已绑定 + import_projects_batch:415 并发 LLM llm_concurrency permit 限流非原子逐项独立)⑥抽 create_with_binding(:59 create/import 共用 缓解 :211 TODO)。

  • (batch61·2026-06-16·workflow wwtn2knn6+主代核查,cargo 0err+7单测) F-260614-07 — [架构前置] df-ai-core trait 下沉拆 crate — 4 决策全落地:①df-ai-core 新 crate(仅 trait+数据结构 LlmProvider+ChatMessage 等,ContextManager/TokenEstimator 留 df-ai)②构造注入 Engine::new(Arc)+Engine::heuristic()(idea.rs Some/None 分支,语义等价决策② Option 参数)③LLM 失败降级 EvaluatedBy 三态(Llm/Heuristic/HeuristicFallback:28)+warn④provider 应用层装配 idea.rs build_default_provider(DB is_default→build_provider→Option→Arc::from:192)。

  • F-260615-01 (2026-06-16,待commit a3cccb070fe9c8821) — [P1 功能增强] HumanNode 审批节点支持自定义选项 + 单选/多选类型。现状config options: Vec<String> 已支持任意数量2/3/…数量扩展已通),但 decision 是单 String 仅单选语义,options 空=自由文本。

  • 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。

  • F-260615-03 truncated 标志 (第⑩批 2026-06-16) — list 工具截断标志 (list_trash补漏) 原完整分页方案,对抗分析降级。

  • F-260615-04 卡片分组增强 (第⑩批 2026-06-16) — read_dir / read_file 工具卡片连续时折叠/收起 提高信息密度。

  • F-260615-07 search_in_file (第⑩批销账 06-15) — read_file 加 search 参数 已落地。

  • F-260615-13 复制按钮 (第⑩批 2026-06-16销账) — 消息气泡复制按钮 已落地AiChat.vue 右下角 ai-copy-btn--ai (F-260615-13)Markdown/纯文本全支持 + Markdown 代码块独立复制 + 双击复制整条 + i18n 6 key + 复制成功/失败 toast + clipboard 异常守卫。

  • F-260615-14 消息操作栏 (第⑩批 2026-06-16销账) — 消息操作栏(复制 / 重新生成) 已落地(操作栏 ai-msg-actions 已移除复制按钮(仅留「重新生成」并 gate 到末条 AI 消息),复制统一走气泡内右下角图标 ai-copy-btn--aiF-260615-13

UX 交互改进 (已完成)

  • UX-2025-01 选文字(文本偏移量方案) (第⑩批销账 06-15) — 流式渲染中选中文字保持§2.1)。

  • (batch36·2026-06-16·workflow w098aapgd) UX-2025-02 [P1] — 消息操作栏(复制 / 重新生成)§1.2+§1.3)。

  • (batch36·2026-06-16·workflow w098aapgd) UX-2025-03 [P1] — 错误气泡操作入口(error_type 枚举本身 batch34 B-42 已加,本批前端消费)§4.1)。

  • (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} 不重试保文

  • (第⑳批 2026-06-16) UX-2025-05 [P2] — 代码块语法高亮 + 复制按钮§2.2)。高亮部分完成:highlight.js(core+16 语言按需注册,~50-60KB gzip)+ marked.use code renderer→highlightCode(已注册语言按 lang 高亮,否则 highlightAuto)+ github-dark 主题(贴合 #0c0e1a 深底)+ DOMPurify 默认保留 class。

  • (batch41 store + batch43 UI·2026-06-16·workflow wcy478m3y) UX-2025-06 [P2] — 对话搜索§3.1)。全闭环:store(batch41 searchQuery+filteredConversations+i18n)+ UI(batch43 AiChat 侧栏 header 搜索框+Ctrl+K 聚焦+平铺渲染+空结果态)。

  • UX-2025-07 (第⑲批 2026-06-16) — 键盘快捷键 onGlobalKeydown(AiChat.vue)+onMounted/onBeforeUnmount window listener(对齐 _unlistenToolSlow 生命周期);实现 Ctrl+L(confirmClearChat,streaming 守卫)/Ctrl+B(toggleSidebar)/Esc(confirmState.visible→answerConfirm(false)>props.detached→closeDetachedWindow 优先级)。

  • (batch47·2026-06-16·workflow wjkywbhff) UX-2025-08 [P2] — 新建对话 confirm 弹窗§3.4 增强)。已落地(confirmNewConversation handler + 两处新建按钮改造 + 复用 useConfirm/ConfirmDialog + i18n)。

  • (batch51·2026-06-16·workflow wdfffj1ti) UX-2025-09 [P2] — 编辑已发送消息并重新生成§1.1)。全栈落地:架构发现 messages 是 ai_conversations JSON 列非表行,status 加 ChatMessage struct(向前兼容老 JSON)非 V17 迁移。

  • (batch52·2026-06-16·workflow w91svrokz) UX-2025-10 [P2] — @ 实体引用§1.4)。全栈落地:AiChat @ popover(复用技能架构 .ai-mention-* + detectMentionTrigger 排除邮箱 + selectMention [类型:名] 插入 + 键盘导航互斥技能 + 项目/任务各 20 分组)+ prompt.rs 任务段注入(state.tasks.list_active,签名零变化降级避碰 ai_chat_send 领地)+ i18n 5 key。

  • UX-2025-11 [P2] — 输入框高度提升§1.5。textarea 最大高度 120px→200px~10 行),超过后再内部滚动。或可拖拽 resize handle。

  • UX-2025-13 [P2] — 消息时间戳§2.4)。气泡下方极小字号(dim 色)展示相对时间(复用 time.ts 已有 common.justNow 等 keyhover tooltip 展示完整时间。

  • (第㉒批 2026-06-16) UX-2025-14 [P2] — Provider 切换反馈§5.1。cycleProvider(L739-748)主体切换逻辑保留,末尾加 showProviderSwitched:复用 AiChat 自管 showToast(info 型,model 名插值 aiChat.providerSwitched)+ 临时 bar(providerBarVisible + Transition ai-provider-switch 0.15s 淡入/淡出 + 2000ms 自动淡出,展示 aiChat.providerSwitchHint model 名小字+accent 脉动圆点)。

  • (第㉓批 2026-06-16) UX-2025-15 [P2] — 技能参数用法展示§5.2)。浮层 .ai-skill-item 改 column:.ai-skill-item-row(name/desc/src 单行)+ code.ai-skill-item-hint(v-if s.argument_hint,等宽 dim 11px,L390)。

  • (第㉒批 2026-06-16) UX-2025-16 [P2] — 侧栏宽度可拖拽§6.1)。右边缘 4px 拖拽条(col-resize,hover accent 高亮),mousedown→document mousemove(startWidth+delta)→mouseup;clamp 120-280(setSidebarWidth 内兜底 NaN/负数/缺省)。

  • (batch49·2026-06-16·workflow wkan76fon) UX-2025-17 [P3] — 对话置顶§3.2)。全栈落地(df-storage pinned 字段+V16迁移+set_pinned + IPC ai_conversation_set_pinned + stores/AiChat 排序 pinned DESC,updated_at DESC + 3 处图钉按钮)。

  • (batch46 后端 + batch48 前端·2026-06-16) UX-2025-18 [P3] — 对话导出§3.3)。全闭环:后端(batch46 ai_conversation_export IPC commands.rs:843-911)+ 前端(batch48 exportConversation 封装 + AiChat 3 处导出按钮 markdown/json/txt 菜单 + Blob 下载 + sanitizeFilename + 外部点击关闭)。

  • (第㉒批 2026-06-16) UX-2025-20 [P3] — 空状态引导 + 标题过渡§7.3+§7.4)。空态:messages 空+非流式时 .ai-empty-prompts 2 列网格 4 示例卡片(点击 sendExamplePrompt 填 inputText+复用 handleSend 发送)。无 provider 显「去设置」按钮(goToSettings:嵌入 router.push('/settings'),分离窗口降级 showToast 提示去主窗口)。标题淡入:titleFlash ref + watch(activeConv.title)空→非空(loadConversations 回填触发)置 flash 驱动 0.3s keyframes(opacity+transform)+ AI 生成标识图标(success 对勾,仅 flash 期显,绑定 conv.id===activeConversationId)。

aichat 交互缺陷修复 (已完成)

  • (commit 8abcd56·同 B-260617-09 根因·防御修复已落地·待用户实测确认) UX-260617-01 [P0]🎯消息/工具卡大量重叠堆叠(用户实测确认)【核心嫌疑=虚拟滚动 IO/RO 时序竞态致 slot 塌 0。防御修复已落地(useAiVirtualScroll.ts IO 卸载分支 minHeight 三层 fallback + registerSentinel 首次挂载 40px 兜底)。vue-tsc EXIT 0。待用户实测:若消除则根因确认,否则 DevTools 验证次嫌疑(v-html DOM 破坏/CSS)】

  • UX-260617-02 [P1]🎯CR-59 审查发现:onPoolWeightChange 缺乐观更新 revert 逻辑 — Settings.vue:643-656 weight 输入 debounce 300ms 调 IPC成功后未像 onPoolToggle 一样 revert 到服务端值。IPC 失败或延迟时 UI 显示旧值而非回滚。

  • UX-260617-03 [P1]🎯copyMsgContent 失败误报「已复制」(已记录未修)AiChat.vue:1037-1040 clipboard.writeText 权限拒绝 → catch 仍 showToast('copied')。用户见"已复制"去粘贴发现空。

  • UX-260617-04 [P1]🎯offsetToDOMPosition 恒返回 root 致选区恢复错位(已记录未修)AiChat.vue:908-921 createTreeWalker 后 currentNode 初始=root 非 Text → ?? 恒取左 → 循环无 nextNode 推进 → 选区恒错位。UX-2025-01 功能实际失效。

  • UX-260617-08 [P1]🎯switchConversation/loadConversations 异常静默吞没useAiConversations.ts:36-44 catch 为空 + :117-119 switchConversation catch 仅 messages=[] 无反馈。网络抖动/IPC 断开 → 对话列表突然变空/切换后空白用户不知原因。

  • UX-260617-09 [P1]🎯startListener 吞掉注册异常导致全量事件静默丢失useAiEvents.ts:354-373 IIFE 内 aiApi.onEvent(handleEvent) 异常被完全吞没(无 console.error/toast/log。所有聊天事件(文本/完成/审批)全丢 → UI 表现"发了消息永远不回"。

  • UX-260617-10 [P1]🎯AiError 不清理 pendingApprovals错误后残留审批卡useAiEvents.ts:326-349 AiError case 做 clearStreamWatchdog/清queue/推错误气泡但从未清 pendingApprovals。出错时有 tool_call 处于 pending_approval → 残留可点击审批按钮。

  • UX-260617-11 [P1]🎯modelOverride 跨对话泄漏useAiSend.ts:67 模块级 ref注释明确要求"前端应同步清 null"但无任何代码执行此清除。switchConversation/newConversation 不触碰。对话A选模型覆盖→切对话B→override 静默生效。

  • (wf wf_b8b2a7b7 + 主代修缺陷·commit 3055b06) UX-260617-13 [P1] 已修刷新后主面板无流式恢复【抽 restoreGeneratingState() 共享恢复链(分离窗口 resumeInDetached 薄包装委托),AiChat.vue onMounted 主面板分支(detached=false)调 store.restoreGeneratingState({fromMainPanel:true})。关键修复:verify agent 发现主面板刷新时 df-ai-gen localStorage 不存在(仅 detachPanel 写),原复用方案读 gen=null 直接 return 无效。加 fromMainPanel 选项绕过 localStorage:用 state.activeConversationId + ai_is_generating 真值守卫恢复(currentText 从空开始,刷新前已生成部分丢失为刷新固有代价,核心恢复 streaming 态+占位气泡消除假死)。幂等守卫(state.streaming 已 true 跳过)+ R4 后端真值守卫保留。vue-tsc EXIT 0】

  • UX-260617-14 [P2]🎯审批超时 130s 静默复位无反馈ToolCard.vue:507,541-54 超时仅 approving.value=false,无 toast/error/日志。用户无法区分"审批完成状态没更新"和"超时复位"。

  • UX-260617-15 [P2]🎯regenerate/editMessage 丢弃图片 partsuseAiSend.ts:148-190 regenerate/edit 均无 parts 参数。含图片消息重生成/编辑后图片消失。

  • UX-260617-16 [P2]🎯无路由离开/关闭保护,未发送输入静默丢失 — AiChat.vue 缺 beforeRouteLeave/onBeforeUnload 守卫。输入框有内容/已粘贴图片时切页面 → 内容瞬间消失无提示。

  • UX-260617-17 [P2]🎯ToolCardList 分组名硬编码中文绕过 i18nToolCardList.vue:259-274 nameMap 全硬编码中文('读取文件'等)。英文 locale 下分组标题仍显示中文。

  • UX-260617-18 [P2]🎯isToolFailure() 正则过于宽泛误判合法输出为失败ToolCard.vue:220-224 /执行失败|failed|error[:\s]/i 匹配任何含这些子串的文本。search_files 结果列 error.log / run_command stderr 含 warning 均被标红。

  • UX-260617-19 [P2]🎯stopChat 本地先行 reset 与后端竞态窗口useAiSend.ts:479-488 先设 streaming=false 再发 IPC stop。IPC 失败时后端继续生成但前端已停止;若后续事件也丢失则永久卡死。注释承认风险但无缓解。

架构审查已修项 (ARC- 系列)

  • ARC-260615-01 wave(2026-06-16,待commit) — stores/settings.ts mock 死代码 grep 验零消费者 + 删文件 + index.ts 清导出 + 清 appSettings.ts:8 过时注释

  • ARC-260615-02 (2026-06-16,待commit) — /decisions 路由死链 删 nav 项App.vue secondaryNav+ 删 nav.decisions i18n keyzh/en。决策治理 = F-260614-08 长期项未实现,入口提前占位成死链;dashboard.recentDecisionsDashboard.vue不同命名空间保留

  • (决策a·2026-06-16·转架构维护记录无代码) ARC-260615-03 — 重评降级2026-06-16df-execute 非空壳——shell.rs execute() 已完整实现cmd/sh 跨平台 + kill_on_drop + timeout + env+ 被 tool_registry.rs run_command 复用F-260615-05。原 todo「76 行/1 函数 + TODO」基于 lib.rs 空判,过时。合并进 df-nodes 破坏职责分离(节点定义 vs 执行运行时)+ 动依赖树,转架构维护决策,非清债

  • ARC-260615-04 wave(2026-06-16,待commit) — stores/index.tsexport useAiStore barrel 补导出(3 处 view 直连可选迁移,非强制)

  • (batch29·2026-06-16) ARC-260615-05 — stores/project.ts 上帝 store 拆分(四领域+越层 invoke 核验越层 invoke 0 命中(已下沉 api/workflow.ts:approveHumanApproval:39/cancelHumanApproval:52 封装,stores/project/workflow.ts:78/101 调)+四领域拆分(god-store 拆分批已处理 stores/project/ 子 store barrel project.ts:122-123 委托)。vue-tsc exit 0

  • (batch29·2026-06-16) ARC-260615-06 — events↔stream 循环依赖 提 aiShared.ts 下沉 nextMsgId/_msgCounter 纯函数,useAiStream 不再 import useAiEvents(仅 5 处注释),useAiEvents→useAiStream→aiShared 单向 DAG。vue-tsc exit 0

  • (batch30·2026-06-16 评估维持现状) ARC-260615-06b [P3] — useAiEvents↔useAiSend 另一环(useAiEvents:19 import useAiSend/useAiSend:23 import useAiEvents),靠事件总线 ai-approval-clear-timers 部分缓解,非本批范围。遗留自 ARC-06 核验

  • ARC-260615-08 (2026-06-16,待commit) — [渲染优化·自研块级 memo 已实施] 流式 Markdown 渲染——保留 marked+DOMPurify+.ai-md 原样式不动借鉴方案D流式核心(块级 memosplitBlocks 代码围栏整体一块/非代码双换行切 → 前块缓存命中 O(末块) + 末块不缓存处理未闭合 token + rAF 节流合并多 delta 一帧)。退役 AR-1 纯文本短路

2026-06-17 走查修复项

  • (commit 645f73d) B-260617-12 [P3·可选] — LEGACY_STATUS_MAP 映射 DRY 重复。抽 mapLegacyStatus(status) 函数收敛两处 LEGACY_STATUS_MAP[status] ?? status 一行重复。vue-tsc EXIT 0。—— src/constants/project.ts(:96-98)

  • (commit f6e4e82) 🚨 B-260617-14 [P1] 已修74003bc 漏提交 adversarial.rs + project.rs【补提两文件 reasoning_content: None,HEAD 干净 checkout 编译通过】

  • (不做·优化方向错误) B-260617-15 [P2·可选] — reasoning_content 落库存储膨胀【核验 DeepSeek API 规范:有 tool_calls 的 assistant 消息 reasoning_content 必须在后续请求回传(否则 400 "must be passed back")。verify agent "只走顶层"分析错误——实际需 messages 数组回传。落库剥离会导致重新加载对话后历史消息无 reasoning_content → DeepSeek 400(重新引入 BUG-12)。reasoning_content 必须保留在内存+落库+请求全链路,不可优化】

2026-06-18 用户反馈交互调整

  • UX-260618-00本批 4 项 AiChat/ToolCard 交互调整):

    • AI 气泡复制去重(UX-260618-01):删 ai-msg-actions 内复制按钮(栏仅留「重新生成」+gate 末条 AI isLastAi),复制统一走气泡内右下角图标 ai-copy-btn--ai
    • run_command 显命令 + 可折叠输出(UX-260618-02):toolDisplayName 加 run_command 分支显 $ <命令首行截断>(折叠头部可见)+ body 新增命令行($+完整命令)常显 & 输出可折叠(失败默认展开看 stderr/成功折叠,本地 ref cmdOutputExpanded+watch status)。
    • 历史消息时间戳全显「刚刚」(BUG-260618-01):根因 ChatMessage(df-ai-core/provider.rs)无 timestamp 字段,后端从未持久化每条消息时间,前端加载历史 timestamp: Date.now() 全塞当下。
    • 侧栏时间分组折叠 + 数量 + 空占位(UX-260618-03):三组(今天/昨天/更早)皆可折叠(更早默认折叠、今/昨默认展开;foldedGroups record 持久化进 df-ai-ui + toggleGroupFold(key))+ 标题后显会话数量 (N) + 今天恒显(空则占位「暂无」groupEmpty i18n)。
  • BUG-260618-02本批 3 项模型选择/上下文修复·cargo check --workspace EXIT 0 + vue-tsc EXIT 0:

    • specify 模式跑成别的 provider 模型:agentic.rs:350 ProviderPool::select 原传 None(无视用户指定),改传 model_override.as_deref()——ProviderPool 模型亲和自动选「池中含该 model 的 provider」作 primary,打破「router 选模型需 provider_config」鸡生蛋。
    • 测试连接/拉取模型后权重失效:commands.rs ai_fetch_modelsupdated.model_configs = configs.clone() 直接覆盖,丢弃用户在 Settings 调过的 model weight/enabled/label。改合并:新探测值为主(更新能力维度),按 model_id 匹配保留旧 weight/enabled/label,新模型用探测默认。
    • 压缩上下文前端折叠藏消息:用户诉求=压缩只后端 LLM 省 token,界面不藏消息。后端压缩逻辑正确(compress_via_llm 摘要 + is_active 白名单不发 LLM + DB 保留原文),问题在前端。

2026-06-18 6 域并行走查修复项

  • (主代修·SW 批·cargo df-nodes EXIT 0) SW-260618-15 [P3] — ai_node schema required=[provider_id] 过度约束。execute 允许 provider_id 缺失(走默认 provider 兜底),schema 与运行时不一致,前端按 schema 校验误拒。把 provider_id 从 required 移除。

  • (主代修·SW 批·vue-tsc EXIT 0) SW-260618-18 [P3] — wasNearBottom 模块级切会话不重置。会话 A 上滑切 B 后首滚到底误触发一次 collapseAllToolLists(收起本身无害但语义偏差)。建议 watch(activeConversationId) 内重置 true。

  • (主代修·SW 批·vue-tsc EXIT 0) SW-260618-21 [P3] — TaskDetail wfResult setTimeout 未卸载清理。wfResult 终态提示 3s timer,组件卸载后仍触发写已销毁 ref。补 wfResultTimer + onBeforeUnmount。

  • (主代修·SW 批·vue-tsc EXIT 0) SW-260618-23 [P3] — Ideas net-sentiment neutral CSS 缺失。sentimentClass 返回 'neutral' 但 CSS 只定义 positive/negative,中性无样式。纯样式缺口。

  • (主代修·SW 批·部分·cargo df-ai EXIT 0 warning 消除) SW-260618-24 [P3] — dead_code 基线 6 处 warning(已标 finish_reason/call_type 2 处 serde 反序列化字段 #[allow(dead_code)] 消除 warning;其余 4 处 session_state/risk_level/diff/releases/node_executions 保留作待办提醒——session_state 待 P0 状态机收敛任务承接,risk_level/diff 待审批卡预览消费,releases/node_executions 待功能模块落地,标 #[allow] 会掩盖待办故保留)(df-ai finish_reason/call_type + mod.rs SessionState/session_state/risk_level/diff + state.rs releases/node_executions)。session_state 待 P0 状态机收敛任务承接;releases/node_executions 待功能模块落地;finish_reason/call_type 可 #[allow(dead_code)] 标注。非本次引入,勿回退。

2026-06-18 工作区进展

  • (2026-06-18·转向彻底移除·工作区待提交) B-260618-01 — 原"回退 0ca5d98 恢复虚拟滚动裁剪"→ 转向彻底移除虚拟滚动(删 useAiVirtualScroll.ts + AiChat.vue 移除全链路。理由IO/RO 时序竞态致重叠shouldRender 恒 true 时 IO 仍设/清 sentinel minHeight 竞态源未除)+ 消息量级不需要。B-260617-09 真闭环。

  • (2026-06-18·工作区待提交·vue-tsc EXIT 0) B-260618-03ToolCardList 首卡折叠 bugisCardExpandedToolCardList.vueci===0 兜底 return true 覆盖用户折叠——多卡分组首卡默认展开,用户点折叠后 ci===0 仍 true 重新展开。修复:加 userCollapsedCards 记忆态,isCardExpanded 最优先判断用户折叠。

  • (2026-06-18·工作区待提交·vue-tsc EXIT 0) B-260618-04ToolCardList 全部展开/收起下沉 + 宽度对齐U-260618。①global-toggle 从 topbar 下沉到首个可折叠分组标题行尾巴firstCollapsibleGi computed与 run_command 分组标题同行chevron 移除 margin-left:auto②分组标题行加 max-width:var(--df-msg-max-width)(90%) 对齐气泡/卡片宽度(原无 max-width 拉满 100%③global-toggle 移除独立按钮 padding/背景高度=文字行高不撑高标题行。

  • (2026-06-18·工作区待提交·vue-tsc EXIT 0) B-260618-05AI 独立窗口吸附挤出屏幕 + 宽度偏窄。①吸附挤出:syncToMain 把 AI 窗口放主窗口右(pos.x+size.width+GAP),主窗口最大化时 AI x=屏幕宽+4 挤出屏幕。修复:syncToMain 增强——主窗口 isMaximized 时 unmaximize + 主+AI 宽度超屏幕时缩小主窗口(newMainWidth=screenWidth-GAP-AI_WIDTH-pos.x,最小 400px 保护)+ _isSyncing flag 防 syncToMain 改主窗口 size 触发 onResized 递归;屏幕宽度用顶层函数 currentMonitor()(@tauri-apps/api/window,非 Window 实例方法)。②独立窗口窄:detachPanel width 520→600 对齐吸附态 AI_DOCK_WIDTH。

P1 缺陷修复 (已完成)

  • B-260614-08 — promote_idea 两步写非事务 mission:T-260614-05 已修复idea.rs 第二步 update_full 失败时补偿删除已建 projectRepository 不支持跨 repo 共享事务对象,选补偿删除非真事务,改动最小;附 logging

  • T-260614-03 — 工具层白名单与 crud 白名单双份去重 WF-B ⑤ 已解决tool_registry update_project 复用 is_allowed_column与 CRUD 白名单同源,删硬编码 match

  • T-260614-04 — 路径校验根治 已完成resolve_workspace_path 加 canonicalize 防 symlink 逃逸 + 词法 starts_with 兜底仅校验、返回词法路径保持前端友好cargo check 0 err / 22 test pass

  • T-260614-09 — idea.rs 物理删不级联 WF-E 完成idea.rs:149 delete→purge_with_descendants1 行,签名兼容)

  • T-260614-10 — findBinding canonicalize WF-E 判定已解决normalize_path 已含 canonicalize 优先 + 词法回退find_binding_conflict 两端对称已用,无需重复加;零改动)

  • T-260614-12 — df-ideas 死代码 WF-E 部分完成capture.rs 删 CaptureInput/IdeaCapture 死码,保留 Idea/IdeaScores 共享实体promotion/scoring/adversarial 内"两套 Recommendation/PromotionPolicy 死枚举"嫌疑 agent 未确认存在/保留为对外契约,本次未动,待复查)

2026-06-17 实测发现 bug (审批流程三连)

  • (波9·e23b316+主代核查,cargo0err+devflow79pass,方案a2后端分支) B-260617-01 [P1] — run_workflow 作为 AI 工具无法执行 + 无意义重试 + 审批混淆。三个关联问题:
    • 问题 1run_workflow handlertool_registry.rs:530-546仅持有 db: Arc<Database>,无法访问 AppHandle/Stateregistry/event_bus/workflows Repo返回 Err("run_workflow 工具需经 Tauri IPC 执行...")。审批通过后 ai_approvecommands.rs:329ai_tools.execute() → handler 必然 Err → audit_status="failed" → 错误信息作为 tool_result 回传 LLM。工作流实际未执行任务状态未推进。
    • 问题 2handler Err → tool_result=错误提示 → LLM 认为失败 → 重试(1/4) → 同结果循环。工具定义未标 no_retry,浪费 token + 用户反复审批。
    • 问题 3:前端渲染的是 AI 工具审批tool_call pending_approval非工作流 HumanNode 审批。用户批准后工作流引擎从未启动HumanNode 审批节点从未到达。
    • 修复方向方案 A推荐:前端拦截 — ai_approve 中识别 run_workflow tool_call → 不走 ai_tools.execute → 直接 invoke('run_workflow', {task_id, target_status}) → 结果回填 tool_result。方案 B:后端注入 State — build_ai_tool_registry 传入 AppHandle 使 handler 可直接执行。问题 2/3 随 A 自动消解。

aichat API Key 401 排查 (已定位)

  • wave(2026-06-16,待commit) B-260615-01 — Err 分支加诊断 提取纯函数 fmt_diag+extract_error_diag(name/status_or_class/timeout·connect 分类,14 单测);约束:LlmProvider trait 无 base_url/endpoint,仅 name() 近似 provider_type(provider_type + 实际请求 url + HTTP 状态码),当前只透传服务端文本看不出端点,401 难定位 — stream_recv.rs:107-113

其他已修复问题

  • (核验已实现·canRetry/canOpenSettings 已落地) UX-260616-01 [P2] — 工具调用失败时「重试」提示语义模糊【独立核验:AiChat.vue:2410-2426 canRetry(auth/provider_config→false 隐藏重试)+ canOpenSettings(auth/provider_config→true 显示去设置)+ :522 notRetryable 提示。Fatal 类错误(4xx/鉴权)已去掉重试按钮改去设置。工具失败走 AiToolCallCompleted(非 AiStreamRetry)语义已清晰——ToolCard 显示错误,LLM 据 tool_result 自决】

  • (主代修·commit 待提交·vue-tsc EXIT 0) UX-260616-02 [P3] — 「全部收起」合并一行【核验 searchFiles i18n key 是死 key(无渲染点),实际合并 batch-approve + global-toggle 同行:ToolCardList.vue template 包 .ai-tool-topbar flex row + global-toggle margin-left:auto 右对齐】

  • (第㉒批 2026-06-16) UX-2025-19 [P2] — 消息列表虚拟滚动 已被 B-260618-01 彻底移除虚拟滚动取代。原 e38474b 自研 IntersectionObserver+sentinel+末条保活, 因 IO/RO 时序竞态致消息重叠反复(shouldRender 恒 true 仍重叠), 最终删除 useAiVirtualScroll.ts + AiChat.vue 移除全链路。

2026-06-16 走查修复项

  • (第㉖批 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。

  • (第㉖批 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。

  • (ca9b318·wrapNakedDiff落地+第㉖批diff语言注册) B-260616-11 [P2] — AI 消息 -/+ 列表/diff 无视觉效果。两项子项均已落地:①裸 diff 预处理 wrapNakedDiff(ca9b318 useMarkdown.ts:+96 守卫4:纯-列表不触发/≥2行连续±/已在围栏不动/段落级处理+短路优化+缓存key用wrapped) ②diff 围栏高亮(第㉖批 useMarkdown.ts import diff+registerLanguage('diff')+highlightCode getLanguage('diff')→hljs addition/deletion token+github-dark.css 红绿)。

  • (第㉗批 2026-06-16·workflow) B-260616-19 [P2] — 知识库详情窄屏标题挤压成竖线(一行一字)。三因子叠加Knowledge.vue.kn-layout grid grid-template-columns: 360px 1frL567——左列表死钉 360px、右详情 1fr 拿剩余,无响应式断点;窗口窄(如总宽 500px减 padding 40+gap详情列塌缩到 ~80px 甚至更小。②.detail-titleL625font-size:18px + word-break:break-word —— 窄列里中文每字宽度 > 列宽,逐字换行 → 竖线化。③.detail-actionsL626flex-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/数据变动。


归档自 todo.md 2026-06-18 三文档巡检