巡检发现:
- 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行已建,旧副本待清理但非阻塞)
86 lines
8.1 KiB
Markdown
86 lines
8.1 KiB
Markdown
# 定时代码走查 — P0 状态复核(2026-06-15)
|
||
|
||
> 触发:定时走查 cron(每 30 分钟)。本轮重点 = 自上次走查(HEAD `4b5f096`)起新增内容走查 + 既有 P0 修复状态地面复核。
|
||
> 方法:2 路后台代理(TaskDetail.vue 新文件 / 后端提交 `2de0c6e` 16 文件大改)+ 主代理地面核对(`project.ts:273` / `workflow.rs:211` / `useAiStream.ts` / `stream_recv.rs` / `todo.md`)。
|
||
> 性质:核对记录,不改产品代码(本会话 session-role-diagnose-only)。todo 待修项见 `docs/todo.md`。
|
||
> 关联:[工作区多角度走查-2026-06-15.md](./工作区多角度走查-2026-06-15.md)(上一轮,3 P0 + DRY 发现源头)。
|
||
|
||
---
|
||
|
||
## 核心结论:纠正过时认知(定时走查首要价值)
|
||
|
||
| P0 | 上轮判断 | 本轮地面复核 | 处置 |
|
||
|---|---|---|---|
|
||
| **B-260615-34** selectType | 「未修,仍 camelCase」 | **已修 ✅** — `project.ts:273` 现为 `select_type: ... ?? 'single'` + 正确注释「Tauri 2 IPC 不转 camelCase,须 snake_case 对齐后端 workflow.rs:211」;后端 `workflow.rs:211` 同 `select_type: Option<String>`。前后端契约对齐。 | todo 标 `[x] ✅`,删过时描述 |
|
||
| **B-260615-32** 队列收尾 | 未修 | **仍未修 ❌** — `onStreamTimeout`(useAiStream.ts:24-53)复位 streaming/generatingConvId/currentText + clearStreamWatchdog + 反向扫 completed toolCall 区分文案 + push 错误消息,**仍不清 `state.queue`**(useAiSend:116 有 clearQueue 但收尾路径未调)→ 生成中输入消息丢失 | todo 加复核标注,仍 `[ ]` |
|
||
| **B-260615-33** 骨架屏 | 未修 | **仍未修 ❌** — `onStreamTimeout` 仍**不回滚 running toolCall**(只读 `status===completed` 做文案判断,不改 running→rejected)→ 审批卡片后端 hang 时永久骨架屏,无重审入口 | todo 加复核标注,仍 `[ ]` |
|
||
|
||
> 「B-34 未修」是上一轮压缩前快照,之后提交(`80b9243`「P0 bug 修复」批)已修。后端代理通过后端 IPC 签名推断「前端已对齐」**结论正确**。定时走查纠正过时认知,避免「以为没修催着修」。
|
||
|
||
---
|
||
|
||
## 新发现 P0(后端代理 ②)
|
||
|
||
### B-260615-35 — broadcast `Lagged` 兜底仅 warn,关键终态事件丢失时前端永久卡死
|
||
|
||
**位置**:`src-tauri/src/commands/workflow.rs:90-110`(forward 任务循环)
|
||
|
||
**问题**:`run_workflow` 的 forward 任务靠 `finished = matches!(event, WorkflowCompleted | WorkflowFailed)` 判定退出。broadcast 滑动窗口 `Lagged(n)` 时丢 n 条最旧事件,代码注释**已识别风险**(「关键终态事件可能永久丢失」),但兜底措施只有 `tracing::warn!`,**没有主动从 DB 查终态或加 watchdog 超时**。若 Lagged 恰好丢了 WorkflowCompleted/Failed,forward 任务永远 `rx.recv().await` 等不到 finished,前端依赖事件关闭审批/完成弹窗的场景**永久卡死**,只能靠 DB 轮询兜底(实时性差)。
|
||
|
||
**修法(代理建议)**:`Err(RecvError::Lagged(n))` 分支后加被动超时/主动查 DB — 累计 lag 次数到阈值或单次 n 过大时,查 `WorkflowRepo::get_by_id(&forward_exec_id)` 看是否终态,若是则补 emit `workflow-event` 给前端并 break。需把 `state.db.clone()` 也 move 进 forward 任务(当前仅 executor spawn 持有 db)。
|
||
|
||
**优先级**:P0(低频但后果为「永久卡死」无自愈),开发者已知未做兜底。
|
||
|
||
---
|
||
|
||
## 新内容走查结果
|
||
|
||
### 1. TaskDetail.vue(362 行新文件)— DRY 复发,单文件质量良好
|
||
|
||
| # | 等级 | 发现 |
|
||
|---|---|---|
|
||
| ① | 🔴 | `.ai-md` 样式块**第 5 份重复**(CR-260615-09 复发):`:263-333` ~70 行与 ProjectDetail/Ideas/Knowledge 逐字符同,累计 ~350 行重复 CSS。TaskDetail 是抽公共样式(`src/styles/ai-md.css` 或 `composables/useMarkdownCss.ts`)最佳时机 |
|
||
| ② | 🔴 | `renderedDescription` computed **第 4 份重复**(CR-260615-10 复发):`:116-119` `void mdReady.value` 技巧四处重复。建议 `useMarkdown` 增 `renderedRef()` 帮手收敛 |
|
||
| ③-⑦ | 🟡 | 路由 id 空守 / 快切竞态(无序号/AbortController)/ 错误信息缺 `.message` 优先 / `projectApi.list()` 全量拉取仅解名 / 静态文案半 i18n 半硬编码 |
|
||
| ✅ 亮点 | — | XSS(DOMPurify + escapeFallback 双层)/ `void mdReady` 响应式依赖捕获(注释明确 B-24 修复点)/ Promise.all 并发 / onMounted 不阻塞 load |
|
||
|
||
### 2. 后端提交 `2de0c6e`(16 文件 1418+/152-)— 工程化重构扎实,1 真实 P0 + 文档完善项
|
||
|
||
| # | 等级 | 位置 | 发现 |
|
||
|---|---|---|---|
|
||
| ① | 🔴 | stream_recv.rs:97-108(2de0c6e 版) | 注释虚假承诺「stop_notify 即时打断」,实际该提交无 stop_notify 分支。**working tree 已修** — `80b9243` 补了本地 Notify + 第 3 select 分支(:102-154 现状),无需记 todo |
|
||
| ② | 🔴 | workflow.rs:90-110 | **见 B-260615-35**(broadcast Lagged 终态丢失) |
|
||
| ③ | 🟡 | stream_recv.rs:60-69 | `"timed out"` 分支**非死代码**(代理自查纠正初判:`"operation timed out"` 不含子串 `"timeout"`),可合并到首分支提升可读性 |
|
||
| ④ | 🟡 | commands.rs:265-287 | `ai_chat_stop` 3s 兜底任务用闭包前快照 conv_id,会话切换后 emit 错对话(spawn 内重新读 active_conversation_id 配合 generating 判定) |
|
||
| ⑤ | 🟡 | commands.rs:367/313/452 | tauri async cmd 内同步调 keyring IO 占 runtime worker,建议 `spawn_blocking`(Linux secret-service D-Bus 慢时影响明显) |
|
||
| ⑥ | 🟡 | commands.rs:313-322 | `ai_list_providers` mask 后 api_key 字段语义模糊(`""`/`"sk-xxx"`/`"sk-1••••xyz9"` 三语义混一字段),建议拆 `has_api_key: bool` + `api_key_mask` |
|
||
| ⑦ | 🟡 | secret.rs:51-64 | failcount sidecar 锚 `current_dir()` 不稳定(跨启动 cwd 变化致计数失效),建议改 `app_data_dir`(同 db_path) |
|
||
| ⑧ | ⚪ | Cargo.toml + secret.rs | keyring noop backend 自检缺失,Linux 漏 feature 时 set 静默成功 get 永空 → 兜底误判「已迁移」清 DB api_key 致密钥永久丢失 |
|
||
| ⑨ | ⚪ | agentic.rs:317-361 | 达 MAX_AGENT_ITERATIONS 后先 emit AiError 再 emit AiCompleted,前端 UX 处理依赖实现 |
|
||
| ⑩ | ⚪ | workflow.rs:213 | `let _ = &app;` 显式占位,直接删 app 参数更清晰(Tauri 自动重生成路由) |
|
||
| ✅ 亮点 | — | B-09 GeneratingGuard RAII 收敛复位(Drop 兜底 panic/异常路径)/ B-11 stale loop 一致性校验(会话切换旧 loop 自动退出)/ stream_recv 错误诊断体系(char 迭代修 UTF-8 边界 panic + 11 单测)/ secret.rs keyring 优先+DB 兜底双源 / tool_registry 双层校验防 symlink 逃逸 + 单次 open 消 TOCTOU |
|
||
|
||
---
|
||
|
||
## 其他确认
|
||
|
||
- **aiShared.ts 破环 ✅ 亮点**(ARC-260615-06 落地):`nextMsgId` 下沉 aiShared,useAiStream 注释明确「本模块不再 import useAiEvents,环消除」。4 composable 共享同一计数器,边界严格(仅下沉「无依赖、被多 composable 共用」成员)。
|
||
- **stream_recv.rs working tree 已补 stop_notify ✅**(:102-154 三分支 select! 含 stop_notify 即时打断)。2de0c6e 提交自带的注释虚假承诺问题,已被后续 `80b9243` 修代码侧,**当前 working tree OK,无需记 todo**。
|
||
|
||
---
|
||
|
||
## 📊 本轮摘要
|
||
|
||
| 类别 | 数 | 代表 |
|
||
|---|---|---|
|
||
| P0 状态复核 | 3 | B-34 已修 ✅(纠正过时)/ B-32 未修 / B-33 未修 |
|
||
| 新发现 P0 | 1 | B-260615-35 broadcast Lagged 终态丢失 |
|
||
| 🔴 DRY 复发 | 2 | CR-09(四→五份)/ CR-10(第四份)|
|
||
| 🟡 建议 | 12 | TaskDetail 5 + 后端 5 + stream_recv 1 + workflow 1 |
|
||
| ⚪ 可选 | 4 | 后端 3 + TaskDetail 1 |
|
||
| ✅ 亮点 | 4 | aiShared 破环 / GeneratingGuard RAII / stale loop 校验 / stream_recv 错误诊断 |
|
||
|
||
**本轮价值**:纠正 1 个过时 P0 判断(B-34 已修)、坐实 2 个 P0 仍未修(B-32/33)、新增 1 个真实 P0(B-35)、确认 1 个架构亮点落地(aiShared 破环)。无运行时 panic/数据损坏/并发竞争类硬伤,后端重构质量评级**良**。
|
||
|
||
todo 映射:B-260615-35(新增);CR-260615-09 描述更新(四→五份);B-260615-34 标 ✅;B-260615-32/33 加复核标注。
|