Files
DevFlow/docs/05-代码审查/定时走查-2026-06-15-第2轮.md
T
lxy f30df333b3 docs: 巡检简报+todo 回写(2026-06-15 第2轮)
巡检发现:
- 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行已建,旧副本待清理但非阻塞)
2026-06-15 17:23:57 +08:00

124 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 定时代码走查 — 第 2 轮(2026-06-15
> 触发:定时走查 cron(每 30 分钟)。本轮范围 = 自上次走查起新增 6 提交(`fddca9d`/`892a642`/`19d64fc`/`d809cf4`/`8710d6c`/`06a2dea`)前端改动 + 工作区未提交(`types.ts`/`project.ts` M)。
> 方法:3 路后台代理并行(AARC-05 store 拆分 / BB-22 状态同步含 B-32/33 核对 / C:CR-11 健壮性+工作区未提交)+ 主代理地面核对(`useAiStream.ts`/`useAiSend.ts`/`workflow.rs`/`f93b758` 提交)。
> 性质:核对记录,不改产品代码(本会话 session-role-diagnose-only)。todo 待修项见 `docs/todo.md`。
> 关联:[定时走查-2026-06-15-P0复核.md](./定时走查-2026-06-15-P0复核.md)(第 1 轮,B-32/33 结论被本轮纠正)。
---
## 核心结论:3 前端 P0 全修(第 3 次纠正过时认知)
| P0 | 第1轮判断 | 第2轮地面复核 | 提交 | 处置 |
|---|---|---|---|---|
| **B-34** selectType | 已修 ✅ | 已修 ✅(确认) | — | 保持 ✅ |
| **B-32** 队列收尾 | 「未修」 | **已修 ✅** | `f93b758` | todo 标 ✅,纠正第1轮 |
| **B-33** 骨架屏 | 「未修」 | **已修 ✅** | `f93b758` | todo 标 ✅,纠正第1轮 |
**B-32/B-33 地面证据**`useAiStream.ts` 当前 81 行,第1轮 Read 时为 73 行旧版):
- `:28` `state.queue = [] // B-32:超时收尾同步清队列` + useAiEvents.ts:225(AiError) + useAiSend.ts:152(stopChat)/124(approveToolCall catch) **四路径全清队列**
- `:43-45` onStreamTimeout 单遍反向扫描 running toolCall → rejected(合并探测 completed 为单次 O(n),实现干净)
**B-32/B-33 修复提交**`f93b758`「修复: B-32+33 流式收尾清队列+回滚 running toolCall」3 文件 +18/-7。
> 第1轮「B-32/33 未修」为过时快照(working tree 当时旧版,与 B-34 同根因)。**定时走查连续 3 轮纠正过时 P0 判断**B-34 → B-32 → B-33),说明走查必须以地面 Read 为准,不可信赖记忆/旧快照。前端 3 P0 至此全部闭环。
---
## 新发现 P0AR-11 前端 listener 永不 attach(功能半接通死代码)
**位置**`src/stores/project.ts:31-55`(定义)+ `:109-110`export+ `src/App.vue:203-213`onMounted 未挂载)
**根因**:工作区未提交改动新增 `startDataChangedListener`/`stopDataChangedListener` 两函数 + export,但**全项目零调用方**(grep 确认)。后端 `emit_data_changed`audit.rs:259-270+ 自动执行路径(audit.rs:351+ 审批路径(commands.rs:175)三处 emit 已就位且逻辑正确,事件 `df-data-changed` 正常发出,但前端 `listen('df-data-changed', …)` 永不执行 — 监听器从未 attach。
**影响**:AR-11「数据变更联动刷新」功能**完全失效**。用户通过 AI 工具(create/update/delete project/task/idea)改数据后,列表不自动刷新,仍需手动刷新(正是 AR-11 要消除的痛点)。后端 emit 成死事件。
**修复方向**`App.vue` onMounted 调 `await projectStore.startDataChangedListener()`onUnmounted 调 `stopDataChangedListener()`(对齐 `ProjectDetail.vue:463/470` 的 workflow listener 生命周期模式,数据变更可能来自任意页面)。
**性质**:工作区未提交半成品(非历史遗留,非 ARC-05 拆分收尾)。代理 C 确认 diff 是纯 AR-11 新增。
> 注:todo:77 AR-11 条目原标「暂缓」,第2轮复核更正为「后端已实施 ✅,前端半接通 🔴」。
---
## ARC-05 上帝 store 拆分 — 质量评级:优
**提交** `8710d6c``project.ts` 362→barrel + 5 子 storestate/projects/tasks/ideas/workflow)。
**3 项硬指标全部兑现**
| 指标 | 证据 |
|---|---|
| barrel 零改动兼容 | 逐字段比对 8710d6c~1 与 8710d6c 的 `return reactive({...})`37 key 完全一致(8 getter state + clearError + 9 project + 4 task + 6 idea + 7 workflow actions + pendingApproval/stats computed)。state getter 用 `get projects() { return state.projects }` 保留「避免 loadXxx 重赋值后视图为空」关键设计 |
| state 真单例 | state.ts 模块级 `export const state = reactive({...})`,ESM 保证全 app 单实例,4 子 store import 同一引用 |
| 依赖图无环 | 4 子 store 互不 import,只依赖叶子 `./state`barrel 单向依赖子 store,无循环/无初始化顺序陷阱 |
**🟡 建议 3**
1. `state.ts:32-37` 可变 `let _eventUnlisten` 跨模块共享 + setter,依赖 ESM live-binding(运行时正确但反直觉),建议注释点明或并入 reactive
2. **AR-11 监听器已侵入 barrel**working tree project.ts:31-55),违反「纯 barrel」定位 — 建议抽第 6 子 store `project/dataChange.ts`(与上面 AR-11 P0 同源)
3. `projects.ts:105` clearError 夹在 projects return 语义错位(属 state 层),建议移除(barrel 已独立从 state 导入)
**⚪ 可选 2**:注释「四子 store」实为 5 文件(四领域+共享 state)/ createXxx 入参类型内联可抽 types。
**✅ 亮点**:越层 invoke 下沉彻底(`approve_human_approval`/`cancel_workflow_node` 下沉 `api/workflow.ts:39-54`B-34 snake_case 对齐在 api 层统一)/ ProjectStore 类型 + 单例 `_storeInstance` 保留 / view 端 7 处 `useProjectStore` 零改动。
---
## B-22 前后端状态同步 — 实现质量良好
**提交** `d809cf4``ai_is_generating` IPCcommands.rs:12+ sendMessage 预检(useAiSend.ts:27)。
**设计对症**:双源(前端 streaming / 后端 generating)各自维护确有不同步风险,发送前查后端真值对症。
**竞态窗口可接受**`useAiSend.ts:42` 查后端与 `:97` 实际 sendMessage 之间有窗口,但后端 `ai_chat_send:57` 原子检查+占用(`if session.generating { Err }` + `generating=true` 同锁内)是真兜底。前端预检仅优化 UX(提前入队而非发出去被拒),降级路径完备(IPC 失败 catch 退化为原 streaming 预检)。
**回归安全**:正常事件流(delta/tool/AiAgentRound/AiCompleted/AiError)未改,仅 sendMessage 入口前置预检,不影响 handleEvent。
**🟡 Issue 1(低)**`useAiSend.ts:53-57` 入队分支复位 `streaming=true` 但**未启动看门狗**resetStreamWatchdog 只在 :89 正常发送路径调)。极端卡死场景(后端既不 emit、Drop spawn 又未执行)streaming 可能永真。建议入队分支也调一次 resetStreamWatchdog,代价一行。非 d809cf4 新引入回归(onStreamTimeout 本就依赖正常路径启动的看门狗)。
**信息 Issue 2**`useAiSend.ts:60-61` 注释「streaming=true 但后端 false」描述与实际复位方向(onStreamTimeout/AiError 复位 streaming=false)有歧义,建议改注释。
---
## CR-11 健壮性批(fddca9d)— ✅5 亮点 + 1 死逻辑副产品
**子项 ⑦⑧⑨⑩⑪⑫ 全部实施**
**✅ 5 亮点**
1. `useAiConversations.ts:77-93` JSON.parse 逐条 try/catch(原单条坏 args 清空整对话 → 单条降级空对象)
2. `useAiEvents.ts:130-133` AiHeartbeat 显式 case 防 TS 穷举穿透
3. `useAiSend.ts:84-85` 复用 findToolCall(消除内联 flatMap+find 重复 + 反向扫描 O(1) 均)
4. `ToolCard.vue:236-242` argString 去 3 处 `as any``Record<string,unknown>` 类型收窄
5. `workflow.ts:44-92` approveHumanApproval 签名收敛 `(decisions: string[], comment?)`(消除单/多选调用方歧义)
**⚠️ ⑪ 实施引入死逻辑(CR-260615-18**`workflow.ts:67-68` `decision = selectType === 'multiple' ? decisions[0] ?? '' : decisions[0] ?? ''` 两分支返回值完全相同,三元无意义。后端 workflow.rs:291-296 有兜底。修:直接 `const decision = decisions[0] ?? ''`
**🟡 其他**CR-19action 字段 emit 但前端不消费,契约冗余)/ CR-20stopDataChangedListener try/catch 过度防御,与 workflow.ts:108 不一致)。
---
## P0 汇总(仍未修)
| ID | 问题 | 状态 |
|---|---|---|
| B-260615-35 | broadcast Lagged 兜底仅 warn → 终态事件丢失前端永久卡死(后端 workflow.rs:90-110 | **未修**(第1轮发现,本轮确认仍在)|
| AR-11 前端 | listener 永不 attachApp.vue 未挂载) | **未修**(本轮新发现,工作区半接通)|
---
## 📊 本轮摘要
| 类别 | 数 | 代表 |
|---|---|---|
| P0 全修确认 | 3 | B-34(保持✅)/ B-32 / B-33(第1轮过时,本轮纠正)|
| 新发现 P0 | 1 | AR-11 前端 listener 永不 attach(功能半接通)|
| 仍存 P0 | 2 | B-35 broadcast Lagged(后端)/ AR-11 前端 attach |
| ✅ 质量肯定 | 2 | ARC-05 store 拆分(优)/ CR-11 健壮性批(5 亮点)|
| 🟡 建议 | 6 | ARC-05 三项 / B-22 看门狗 / CR-18 死逻辑 / CR-19·20 |
| ⚪ 可选 | 4 | ARC-05 两项 / ToolCard 兜底 |
**本轮价值**:第 3 次纠正过时 P0 判断(B-32/33 实已修,f93b758),前端 3 P0 全闭环;新发现 AR-11 前端 listener 永不 attach(工作区半接通死代码,功能未闭环);肯定 ARC-05 拆分(3 硬指标全兑现)与 CR-11 健壮性批质量。
**方法论警示**:连续 3 轮纠正过时判断(B-34→B-32→B-33),根因是第1轮 Read 到 working tree 旧版(73 行)而 HEAD 已是新版(81 行)。**走查必须每次地面 Read,不可信赖上轮快照**。后续走查代理 prompt 应强调「以当前 working tree + HEAD 为准,git log 看提交,勿用记忆」。
todo 映射:B-32/33 标 ✅ + 复核更正 / AR-11todo:77)状态更新 / CR-11todo:212)标 ✅ / 新增 CR-260615-18/19/20。