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行已建,旧副本待清理但非阻塞)
This commit is contained in:
2026-06-15 17:23:57 +08:00
parent 672d677046
commit f30df333b3
17 changed files with 2184 additions and 15 deletions

View File

@@ -0,0 +1,85 @@
# 定时代码走查 — 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/Failedforward 任务永远 `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.vue362 行新文件)— 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 半硬编码 |
| ✅ 亮点 | — | XSSDOMPurify + escapeFallback 双层)/ `void mdReady` 响应式依赖捕获(注释明确 B-24 修复点)/ Promise.all 并发 / onMounted 不阻塞 load |
### 2. 后端提交 `2de0c6e`16 文件 1418+/152-)— 工程化重构扎实1 真实 P0 + 文档完善项
| # | 等级 | 位置 | 发现 |
|---|---|---|---|
| ① | 🔴 | stream_recv.rs:97-1082de0c6e 版) | 注释虚假承诺「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` 下沉 aiShareduseAiStream 注释明确「本模块不再 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 个真实 P0B-35、确认 1 个架构亮点落地aiShared 破环)。无运行时 panic/数据损坏/并发竞争类硬伤,后端重构质量评级**良**。
todo 映射B-260615-35新增CR-260615-09 描述更新四→五份B-260615-34 标 ✅B-260615-32/33 加复核标注。