# 定时代码走查 — 第 6 轮(2026-06-15) > 触发:定时走查 cron(每 30 分钟)。范围 = **列表页 + Dashboard + AI 面板/窗口垂直切片**(此前从未深查)。1 新提交(CR-22 修复)。 > 方法:2 路代理(A 列表页 / B Dashboard+AI窗口)+ 主代理地面核 stopListener。 > 性质:核对记录,不改产品代码(本会话 session-role-diagnose-only)。todo 见 `docs/todo.md`。 > 关联:[第1-5轮](./)。 --- ## CR-22 ✅ + CR-23 撤销(价值第 5 次闭环) - `16aeacc` CR-22 ✅:types.ts 3 枚举注释对齐后端(Task/Idea/Project status)+ 删 AiConversationSummary.models 冗余 - CR-23 撤销(不适用):接收方核对 B-34「Tauri 不转」注释在 ARC-05 拆分时已简化(workflow.ts:81/project.ts:58 仅风格对齐无错误说明) --- ## 🔴 分离窗口生命周期(新功能首次深查,P1 核心) **代理 B R1-R5**。地面核 `stopListener`(useAiEvents.ts:258) **全仓零调用**(grep App/AiChat/AiDetached onUnmounted/onBeforeUnmount 都不调)确认 R2。 ### CR-260615-24 [P1] listener 双注册 + 永不清理(R1+R2) - **R1 双窗口重复消费 ai-chat-event**:后端 `app.emit`(stream_recv/agentic/commands/audit 多处)是**全局广播**发给所有 webview。主窗口(AiChat.vue:790)+ 分离窗口(AiDetached 渲染 AiChat)各注册 `listen('ai-chat-event')`,两窗口 handleEvent 都触发 → delta 各 `+=` 一次 / AiAgentRound 各 push 空气泡。当前靠 App.vue:94 `v-if="panelOpen && !detached"` detach 时卸载主窗口 AiChat 间接停,但 state 是模块级单例(handleEvent 仍写主窗口 state),**脆弱隐式契约**。 - **R2 stopListener 零调用**:useAiEvents.ts:258 定义但全仓无调用点 → listener + watchdog 永久泄漏(startListener 幂等防重复注册,但卸载不释放)。 - **边界影响**:reattach 重叠窗口期多一条空 assistant 消息(非崩溃/非数据损坏)。 - **修**:AiChat.vue onBeforeUnmount 补 `store.stopListener()` + detach 时主窗口显式 stopListener / reattach startListener,或后端 `emit_to(label)` 定向。 ### CR-260615-25 [P2] 分离窗口状态机缺口(R3/R4/R5) - **R3**:`win.once('tauri://destroyed')` 置 detached=false 但**不恢复 panelOpen=true**(只 reattachPanel 显式设)→ 用户直接 X 关分离窗口后面板消失,需手动 Ctrl+I - **R4**:`resumeInDetached`(useAiWindow.ts:79-95) 强行重建生成态(读 df-ai-gen 置 streaming=true + push 空气泡),与后端 `ai_is_generating` 真值可能失配 → 假气泡 / 130s 后 watchdog 假超时 - **R5**:分离窗口 onMounted `switchConversation`(useAiWindow.ts:81) + loadConversations 内自动 switch,后端 **AiSession 单例** activeConversationId 被分离窗口覆盖 → 主窗口期间发消息可能落错会话(B-22 同类延伸) --- ## 🟡 列表页(代理 A) ### CR-260615-26 [P2] AR-11 + B-29 契约交互 + Tasks 空态(R-1/Y-2) - **R-1**:AR-11 监听器(project.ts:38)对 task 调 `loadTasks()` **无参 → 全量加载**,破坏 B-260615-29 建立的「store.tasks 反映当前筛选」契约。filteredGroups 二次过滤**兜住结果正确**,但 store.tasks 变全量(createTask push 到全量数组)+ 性能 - **Y-2**:Tasks.vue:39-71 **无 loading/error/empty 兜底**,加载失败或无结果时空白页(store.error/loading 零引用)。对比 Projects.vue:107 至少有空态 ### ✅ 列表页亮点 - **Projects/Tasks i18n 100%**(grep 确认中文仅注释/console)— CR-08 范围内这两页**无硬编码遗漏** - Projects.vue useConfirm composable 抽离(DRY,消除 4 视图重复) - B-260615-29 筛选重载注释保留(可追溯) --- ## 🟡 Dashboard(代理 B) ### CR-260615-27 [P2] refresh 兜底 + stage 颜色 + 死代码(M1/M3/L4) - **M1**:refresh(Dashboard.vue:202-204)Promise.all **无 try/catch**,任一接口失败 unhandledrejection + 用户无反馈(onMounted 有 try/catch 但 refresh 无) - **M3**:getProjectStage(:150) status→stage 映射 **planning 归 coding stage(颜色紫)但 label planning**,颜色语义撒谎(cancelled 归 testing 同) - **L4**:决策/批注两 panel(:103-120) 永远空态,CSS(.decision-row/.anno-row :504-572) 完整但模板未用 = **死代码** ### ✅ Dashboard 亮点 - **无图表库**,纯 CSS 进度条 + 数字 stat,GPU 友好动画,**无性能问题** - aiShared 破环正确(ARC-06),nextMsgId 两窗口各自独立不冲突 --- ## 📊 本轮摘要 | 类别 | 数 | 代表 | |---|---|---| | 价值闭环 | 1 | CR-22 ✅ + CR-23 撤销 | | P1 新发现 | 1 | 分离窗口 R1+R2 listener 双注册+泄漏(CR-24)| | P2 新发现 | 3 | 分离窗口状态机(CR-25)/ 列表页契约+空态(CR-26)/ Dashboard(CR-27)| | 亮点 | 4 | 列表页 i18n 100% / Dashboard 纯 CSS 无性能问题 / aiShared 破环 / useConfirm DRY | **本轮价值**:**分离窗口是新功能,前几轮横切(按提交/改动)完全没覆盖**,垂直切片(Dashboard+AI窗口维度)首次深查即暴露 P1(listener 泄漏)+ 状态机缺口。**再次印证 task2/3 垂直走查价值** — 横切收敛后,垂直切片是新发现来源(i18n/api/列表页/AI窗口 4 个垂直切片均挖出真问题)。 **方法论**:分离窗口 P1(R1+R2)经地面核 stopListener 零调用坐实(避免第5轮代理 A 假阳性教训),走查发现须地面验证。 todo 映射:CR-260615-24(P1 分离窗口 listener)/ CR-25(P2 状态机)/ CR-26(P2 列表页)/ CR-27(P2 Dashboard)。