巡检发现:
- 2196c77 workflow 整文件替换回退破坏(AiChat+Ideas 12项功能)
- B-260615-03 truncated 标志已落地
- AR-8-scroll scrollToBottom smooth 已补
- CR-260615-09 .ai-md 残余:4详情页各21处 scoped .ai-md
(全局 ai-md.css 75行已建,旧副本待清理但非阻塞)
5.5 KiB
5.5 KiB
定时代码走查 — 第 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 次闭环)
16aeaccCR-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:94v-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)。