# 待审查队列 > **职责分离**: > - **主会话**(编码合并后 / 巡检)→ 【**写入**】"当前队列"区,登记待审查项(范围 + 维度 + commit)。 > - **审查 agent**(独立会话 / workflow)→ 【**读取**】"当前队列",执行审查,完成回填结论 + 移到"已审归档"。 > > 这里**只放审查登记**,不放推进待办(推进待办见 [todo.md](./todo.md))。 > 主会话**不在这里做审查**,只登记 + 读 todo 推进。审查发现的【待修代码项】回流 todo 作推进待办。 ## 审查规则(审查 agent 遵守) - 只读审查,**不改代码**。 - **独立 grep/read 核验源码,不信文档 / 会话描述 / 设计声明的结论**(防上下文污染)。 - 每条 finding 须 `file:line` 源码佐证 + evidence。 - 严重度:high(破坏性 / 数据错 / 回归) / med(逻辑瑕疵 / 边界漏) / low(风格 / 可读)。 - 完成回填:总体 verdict(PASS / ISSUES / WATCH)+ high/med/low 清单 + 待修项回流 todo。 ## 状态图例 🟡 待审 / 🔵 审查中 / ✅ 已审(结论) / 🔴 待修(有 high 问题) --- ## 当前队列 ### CR-260618-01 batch68 未提交改动批量(41文件+754/-2434:虚拟滚动删除+timestamp打戳+audit吞错修复+fetch_models合并+分组折叠+todo精简) — ✅ 已审(PASS·🟡1 WATCH) - **复审结论(2026-06-18·主代独立 grep/read 核验 diff)**: ✅ **PASS** — 🔴0 🟡1 ⚪2 - **验证**: git diff HEAD 逐文件核验(41 文件)。 **① provider.rs timestamp 打戳 PASS**: 非 reasoning_content(已在 74003c 提交)。本批新增 `timestamp: Option` 字段 + `now_millis_i64()` + 全构造器自动打戳。serde(default) 向后兼容;注释「provider 映射不读此字段」;单测补 timestamp:None。✅ **② 虚拟滚动删除 PASS(⚠️ WATCH)**: useAiVirtualScroll.ts 整删(-175)。**关键核验**: 被删文件内 `shouldRender()` 已是 `void key; return true`(恒渲染),即虚拟滚动在删除前已因 IO/RO 时序重叠被禁用。本次是清理已失效死代码,非功能回归。AiChat.vue 同步移除所有引用。**🟡 WATCH**: 长对话(500+ 消息)全量 DOM 无兜底方案,桌面端短期可接受,用户反馈卡顿时再评估。 **③ audit.rs+37 PASS(3 项改进)**: PENDING_APPROVAL_PLACEHOLDER 常量抽取(DRY) ✅ | audit_finalize 拆 unwrap_or_default 吞错→Err/None/Err 三路分流(🔒 关键修复) ✅ | update_full 失败加 error 日志 ✅ **④ commands.rs+40 PASS(3 项修复)**: regenerate 对话校验提前到 generating=true 前(防内存消息破坏) ✅ | ai_fetch_models 合并保留用户 weight/enabled label(防排序摇摆) ✅ | ai_conversation_delete retain pending_approvals(防死审批残留) ✅ **⑤ context.rs+63 PASS(F-05 token 预算修复)**: estimate_message 累加 parts token(base64/text/url) + 单测。⚪ chars_ratio 0.35 偏保守,后续可校准。 **⑥ 前端交互层 PASS(6 项)**: 分组折叠(toggleGroupFold+v-show) ✅ | system 压缩摘要展示 ✅ | 复制按钮下沉气泡 ✅ | modelOverride 默认最高权重模型 ✅ | wasNearBottom 切会话重置 ✅ | editEl 函数 ref 修复 v-for 数组收集 bug ✅ **⑦ todo.md 精简 PASS**: 1200→385 行。P0 区全部 [x] 已修保留;活跃待办完整。⚪ 已完成区可进一步归档压缩。 **⑧ 待决策.md 括分 PASS**: +1065 行来自 todo.md C 类抽离,职责分离清晰。 - **🟡 WATCH-1**: 虚拟滚动删除后长对话全量 DOM 性能(观察级) - **⚪ LOW-1**: base64 chars_ratio 0.35 可校准至 ~0.6 - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-02 sweep-fix 6域走查+P3小修+dead_code标注共17处改动(工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·⚪2) - **复审结论(2026-06-18·主代独立 git diff 核验 17 处)**: ✅ **PASS** — 🔴0 🟡0 ⚪2 - **验证**: git diff HEAD 逐文件核验全部 17 处改动。cargo check --workspace EXIT 0 / vue-tsc EXIT 0。 **sweep-fix 12 项逐一核验**: | # | 项 | 判定 | |---|-----|------| | 1 | context.rs parts token 累加 | ✅ 含图消息 base64 不再绕过预算,单测合理 | | 2 | anthropic_compat clone→move | ✅ DRY+零拷贝 | | 3 | scan.rs to_ascii_lowercase | ✅ 非 ASCII 索引安全 | | 4 | scan.rs .is_some_and(!is_null) | ✅ workspaces null 不再误判 | | 5 | adversarial MockProvider reasoning_content | ✅ 编译修复 | | 6 | audit_finalize 拆吞错 | ✅ Err/None 分流(与 CR-01 联动) | | 7 | delete retain pending_approvals | ✅ (与 CR-01 联动) | | 8 | PENDING_APPROVAL_PLACEHOLDER 常量 | ✅ (与 CR-01 联动) | | 9 | ToolCard computed 下沉 | ✅ DRY parsed | | 10 | AiChat 清虚拟滚动死注释 | ✅ (与 CR-01 联动) | | 11 | Projects onUnmounted 清 timer | ✅ 防 timer-leak | | 12 | Knowledge parseContext 去重 | ✅ 冗余 JSON.parse→一次 | **P3 4 项逐一核验**: | # | 项 | 判定 | |---|-----|------| | 13 | wasNearBottom 切会话重置 | ✅ 防 A→B 误触发 collapseAllToolLists | | 14 | TaskDetail wfResultTimer | ✅ 防卸载后写已销毁 ref | | 15 | Ideas .net-sentiment.neutral | ✅ CSS 缺口补全 | | 16 | ai_node schema required=[] | ⚪ WATCH: 运行时允许留空,需确认无其他消费方强制校验 required | | 17 | openai_compat #[allow(dead_code)] | ✅ 标注意图消 warning | - **⚪ WATCH-1**: ai_node.rs required=[] 影响面——若其他 Node Schema 消费方有 required 白名单校验则需同步放宽 - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-03 SW-10 reqwest Client 构建 DRY(工作区未提交·commit-policy-deferred·1 文件域 df-ai) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验源码形态)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: cargo check -p df-ai EXIT 0(无 warning) / cargo test -p df-ai 112 passed 0 failed(不回归)。 **改动 1 处(3 文件 df-ai crate 内)**: | # | 项 | 判定 | |---|-----|------| | 1 | lib.rs 加 `pub(crate) build_provider_client()`(connect_timeout 30s + 回退 Client::new + tracing::warn) | ✅ 纯抽函数,与原两处逐字一致 | | 2 | openai_compat.rs Provider::new 调 `crate::build_provider_client()` 替原 7 行 | ✅ DRY,行为不变 | | 3 | anthropic_compat.rs Provider::new 同替换 | ✅ DRY,行为不变 | **副作用独立核验**(grep 源码形态): - `use reqwest::Client` 两文件仍用于 Provider struct 字段(self.client:Client),非 unused ✅ - `use tracing::{..., warn}` 两文件仍多处用(openai:503 同步调用 warn / anthropic:183/330/364/497/521/535 流式 warn),非 unused ✅ - `use std::time::Duration` 两文件仍用于 :484/:481 `.timeout(Duration::from_secs(60))`,非 unused ✅ - 替换前两处 `Client::builder().connect_timeout(std::time::Duration::from_secs(30)).build().unwrap_or_else(...)` 逐字一致,抽函数后调用点等价 ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-04 SW-16 审计 status 透传 + SW-06 ToolCard watch 合并(工作区未提交·commit-policy-deferred·2 文件) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验源码形态)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: cargo check --workspace EXIT 0(仅 4 pre-existing dead_code 基线 warning) / cargo test -p devflow 92 passed 0 failed / vue-tsc EXIT 0。 **改动 2 项(2 文件)**: | # | 项 | 判定 | |---|-----|------| | 1 | SW-16 audit.rs find_cached 加 audit_repo 参数 + async + 返回 (content,status);查 find_by_tool_call_id 拿缓存来源真实 status 透传 audit_tool_call | ✅ find_by_tool_call_id 已存在复用,审计精度改进零回归 | | 2 | SW-06 ToolCard.vue 双 watch(props.tc.status) 合并(放 :607 三 ref 已定义避 TDZ + immediate 语义) | ✅ immediate 边界安全(approving 初始 false/timer null),行为等价 | **SW-16 独立核验**(grep 源码形态): - find_cached 签名 `async fn(session, audit_repo: &AiToolExecutionRepo, tool_name, args) -> Option<(String,String)>` ✅ - 调用点 :625 `if let Some((cached, status)) = find_cached_high_risk_result(session, &audit_repo, &draft.name, &args).await` ✅(process_tool_calls 内 audit_repo :555 可达) - audit :639 `audit_tool_call(..., &status, ...)` 透传非固定 "completed" ✅ - find_by_tool_call_id 返回 AiToolExecutionRecord.status: String(models.rs:211),rec.status 直接访问 ✅ - fallback completed(审计缺失/查询失败不阻塞去重)✅ **SW-06 独立核验**: - 合并 watch 放原 watch2 位置(approving/approvingTimer/cmdOutputExpanded 三 ref 已定义)避 TDZ ✅ - immediate:true 保留原 watch1 语义;immediate callback 初始 status 下 approving=false/timer=null 无副作用 ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-05 SW-07 AiChat currentText 双 watch 合并(工作区未提交·commit-policy-deferred·1 文件) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: vue-tsc EXIT 0。 **改动 1 项(1 文件)**: | # | 项 | 判定 | |---|-----|------| | 1 | AiChat.vue 删 :2040 watch(currentText→onContentChange) + :2047 合并 callback(onContentChange 先 scheduleStreamParse 后,保持原注册顺序) | ✅ 同源同顺序同条件,行为等价 | **独立核验**: - 原 :2040 watch(currentText, onContentChange) + :2047 watch(currentText, (text)=>{...}) 注册顺序 :2040 先 :2047 后(Vue 同源 watch 按注册顺序执行) ✅ - 合并 callback 内 onContentChange() 先 + scheduleStreamParse 后,保持同顺序 ✅ - 无 immediate(两原 watch 均无),无 TDZ(onContentChange :2032/scheduleStreamParse :912 均在前定义) ✅ - :2039 watch(messages.length→onContentChange)不同源保留 ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-06 SW-19 ToolCard combineOutputs 抽函数 + SW-20 Ideas parseTags 复用(工作区未提交·commit-policy-deferred·2 文件) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验源码形态)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: vue-tsc EXIT 0。 **改动 2 项(2 文件)**: | # | 项 | 判定 | |---|-----|------| | 1 | SW-19 ToolCard.vue 抽 `combineOutputs(stdout, stderr)` 共享函数;combineAndTruncateLines + cmdOutput computed 都复用 | ✅ DRY 收敛,行为不变 | | 2 | SW-20 Ideas.vue 删本地 parseTags(IdeaRecord),import stores/knowledge.ts parseTags;3 调用点改传 .tags | ✅ DRY 复用 store 版,签名收敛 | **独立核验**(grep 源码形态): - ToolCard `combineOutputs` 定义 :463 + 调用 :472/:652 ✅ - Ideas `parseTags` import :214 + 调用 currentIdea.tags(:148/:149) / i.tags(:278) ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-07 SW-08 AuditLog.vue i18n 化(工作区未提交·commit-policy-deferred·3 文件) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验 + i18n message 盲点检查)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: vue-tsc EXIT 0。 **改动 3 项(3 文件)**: | # | 项 | 判定 | |---|-----|------| | 1 | 新建 src/i18n/en/auditLog.ts(auditLog 命名空间:title/refresh/desc/loading/empty + col×7 + pager×4 + risk×3 + status×6 + decided×2) | ✅ 对齐 ideas.ts 风格 | | 2 | 新建 src/i18n/zh-CN/auditLog.ts(中文对应,index glob 自动聚合) | ✅ 中英对称 | | 3 | AuditLog.vue 引入 useI18n + template 15 处文本 t() 化 + riskLabel/statusLabel/decidedLabel 改 t() | ✅ class 映射不国际化(保留),模式对齐 Dashboard/Knowledge/Ideas | **独立核验**(vue-tsc + i18n message 盲点): - vue-tsc EXIT 0 ✅ - useI18n 模式对齐项目现有(Dashboard/Knowledge/Ideas/ProjectDetail 同款 `const { t } = useI18n()`)✅ - message 值仅 `{n}` 标准插值(`page: '第 {n} 页'`),无 `@/`/裸 `{}`(避 prod runtime 报错盲点)✅ - riskLabel/statusLabel/decidedLabel 未知值走 vue-i18n 默认 fallback,但 risk/status/decided 后端值固定不触发 ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-08 SW-09 ai_node provider 三件套 DRY(工作区未提交·commit-policy-deferred·1 文件 df-nodes) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验源码形态)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: cargo check -p df-nodes EXIT 0(无 warning) / cargo test -p df-nodes 82 passed 0 failed 1 ignored(不回归)。 **改动 4 处(1 文件 df-nodes/src/ai_node.rs)**: | # | 项 | 判定 | |---|-----|------| | 1 | 加 `resolve_and_parse(db,config,inputs)` 合并 resolve_provider+parse_params 两步 | ✅ AiNode/SelfReview 逐字重复消除 | | 2 | 加 `provider_from_params(&p)` 封装 build_provider 5 行 | ✅ 同上 | | 3 | AiNode execute :254-262(9 行)→ 2 行(resolve_and_parse + provider_from_params) | ✅ 行为零变化 | | 4 | SelfReview execute parse(:465-466)+ build(:493-498)→ resolve_and_parse + provider_from_params(中间 task 读保留) | ✅ p 生命周期跨 task 读正确 | **独立核验**(grep 源码形态 + 测试): - messages/temperature 差异不抽(AiNode 用 p.system_prompt/p.temperature;SelfReview 强约束 Some(0.0)+REVIEW_SYSTEM_PROMPT)✅ - helper 仅收 provider 三件套,差异区各节点自有 ✅ - 原 resolve_provider/parse_params fn 保留(test 直接调用 :781+),helper 是上层封装非替代 ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-09 UX-260618-04 前端删 cost/intel 标签(工作区未提交·commit-policy-deferred·4 文件) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代自测 + 独立 grep 核验无残留)**: ✅ **PASS** — 🔴0 🟡0 ⚪0 - **验证**: vue-tsc EXIT 0 / grep `tagCost|tagIntel` 全 src/ 无残留。 **改动 4 处(4 文件)**: | # | 项 | 判定 | |---|-----|------| | 1 | ProviderPanel.vue 删 tag-cost/tag-intel 两 span(:114-115) | ✅ 模态/能力/探测源标签保留 | | 2 | AiChat.vue modelOptionLabel 删 intel/cost 拼接,只返 label/model_id + 注释更新 | ✅ 下拉选项不再显示瞎猜档位 | | 3 | i18n en/settings.ts 删 tagCost/tagIntel + 注释 4 维度→模态+能力 | ✅ | | 4 | i18n zh-CN/settings.ts 同 | ✅ | **独立核验**(自主裁决依据 + grep): - 用户已全局决策去掉 cost/intel(B-260618-03 背景)→ 前端删标签是决策落地 ✅ - grep 全 src/ 确认 tagCost/tagIntel 仅 ProviderPanel + AiChat 引用,删后无残留 ✅ - ModelConfig.cost_tier/.intelligence 字段保留(后端 B-03 解耦后清),前端先删引用独立安全 ✅ - i18n 删 key 非加,message 编译盲点不适用 ✅ - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-10 6项编码批·router解耦cost/intel+model_probe去瞎填+executor TOCTOU+审批占位终态化+knowledge_events query+CostTier清理(workflow wexu1isx1·6 agent·主代修SW-02借用+核查·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow wexu1isx1 + 主代 cargo/test/vue-tsc 全量验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪1 - **验证**: cargo check --workspace EXIT 0(5 pre-existing dead_code warning,非本批) / cargo test df-ai 109 passed 0 failed / cargo test df-ai-core 24 passed / cargo test df-workflow 23 passed / cargo test df-storage 全 passed / vue-tsc EXIT 0。 **6 项逐项核验**: | # | 项 | 判定 | |---|-----|------| | 1 | B-03 router 解耦:TaskRequirements 删 min_intelligence/max_cost + select 删步骤4/5 filter + max_by_key 纯 weight 删 Reverse + 9 调用点删传参 + import 清理 + test 改写(删3用例 112→109 + all_dimensions 改 d 胜) | ✅ 主代 grep 核验 min_intelligence/max_cost 代码层 0 残留(仅注释 3 处) | | 2 | B-04 model_probe 去瞎填:heuristic_infer cost/intel 中性默认 Medium/Standard + presets/models.json 17条删两字段 | ✅ 功能维度 modalities/capabilities 保留,中性默认对齐 Default impl | | 3 | B-05 CostTier::Free 清理:删 Free 变体 + test 同步 + 主代补前端 types.ts 删 'free' 对齐 | ✅ grep CostTier::Free 代码 0 残留(仅 todo 任务条目) | | 4 | SW-01 executor TOCTOU:Ok 分支 emit NodeCompleted 移入 !is_cancelled + 取消 emit NodeCancelled 对齐 Err + outputs.insert 保留(不中止后续) | ✅ cargo test df-workflow 23 passed(test_cancelled_node_skips/emits 不回归) | | 5 | SW-02 审批占位终态化:finalize_pending_placeholders helper + 5 处 .clear() 前替换终态 | ✅ 主代修 agent E0502 借用冲突 + cargo check EXIT 0 | | 6 | SW-04 knowledge_events query:KnowledgeEventsRepo::list_recent ORDER BY timestamp 兜底 | ✅ 新方法预防性(无活跃调用方),df-storage test passed | **主代核查·审查防污染印证**: - workflow agent 全按铁律不跑 cargo(只 grep 自验)。SW-02 agent riskNote 第4点预判"disjoint field borrow 应无问题"**错误** —— 主代 cargo check 捕 5 个 E0502(函数参数列表不做 disjoint 推断,只在函数体内合法)。主代修 helper 签名 `&mut AiSession` 整体(函数体内 disjoint)+ 调用点 `&mut *session`(DerefMut 解 guard)。印证:agent 不跑 cargo 的 riskNote 是猜测,主代 cargo 必验(同 Sprint 22 教训)。 - B-03 agent 自验 grep 0 残留准确(主代独立 grep 印证)。 - df-ai test 109 = 112 - 3(B-03 删 intelligence_below_min/max_cost_filters/max_cost_none 3 用例)对齐。 - B-05 riskNote 标注前端 types.ts 'free' 未同步 → 主代补删对齐 Rust(防 DB "free" 值反序列化边界 + 类型宽松)。 - **⚪ WATCH-1**: B-03 行为变更 —— title/compress 失去 max_cost 约束后纯 weight 选模型,同 weight 并列时 max_by_key 返回最后一个(rust Iterator 语义,池顺序决定)。需用户核对 Settings weight 配置合理(用户已全局决策接受,核对 weight 即可)。 - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-11 batch69 全面走查(53文件+1373/-2890:6域全量·Workflow wf_8f2a96d3-dc7·5路并行+安全扫描+主代独立核验降级) — ✅ 已审(ISSUES·🔴1🟡4⚪4) → 🔴已修(主代闭环 2026-06-18) - **结论(2026-06-18·Workflow 5路并行 + 主代独立 grep/read 核验 + High 项逐条源码佐证降级)**: ⚠️ **ISSUES** — 🔴1 🟡4 ⚪4 - **验证**: git diff HEAD 53 文件 / cargo check --workspace EXIT 0 / vue-tsc EXIT 0 / DOMPurify 覆盖确认 **🔴 必须修复 (1)**: | # | file:line | 问题 | 修复 | |---|-----------|------|------| | 1 | `commands.rs:289` | **ai_approve 幂等路径仍 `unwrap_or_default` 吞 DB 错** — audit.rs 已修(B-260617-17 同款 match 三路分流),但 commands.rs:290 `find_by_tool_call_id(...).await.unwrap_or_default()` 仍在。DB 故障时 Err→None→返回「未找到挂起审批」误导用户 | 对齐 audit_finalize 模式: match { Ok(Some)→rec, Ok(None)→return Err, Err(e)→error!+return Err } | **🟡 建议改进 (4)**: | # | file:line | 问题 | 建议 | |---|-----------|------|------| | 2 | `context.rs:57` | base64 chars().count() × 0.35 显著高估图片 token(OpenAI 按像素非字节),含图消息被过度裁剪 | 加注释说明偏保守粗估,或降至 0.10~0.15 | | 3 | `types.ts:207` | IntelligenceTier i18n 标签同删但无注释说明(CostTier 有注释 rationale) | 加注释对齐 UX-260618-04 决策记录 | | 4 | `types.ts:303` | AiMessage.role 新增 'system',前端 `.role ===` / switch 完备性待全量验证 | grep 全 src/ 确认无路径将 system 当 user 可编辑/可发送 | | 5 | `audit.rs:478` | find_cached_high_risk_result N 次串行 DB 查询在 session lock 内,High risk 工具多时锁持有线性增长 | 批量预取或文档标注瓶颈防后续加重量级 IO | **⚪ 可选优化 (4)**: | # | file:line | 问题 | |---|-----------|------| | 6 | `provider.rs:134` | now_millis_i64 i64 截断理论可能(实际 i64::MAX=2920亿年不触发),unwrap_or(0) 兜底值语义不纯 | | 7 | `AiChat.vue:414` | v-if/else-if 链未知 role 落入 AI 分支(后端可控,既有逻辑) | | 8 | `tool_registry.rs:111` | Path Traversal Unicode/8.3/ADS 绕过盲区(Tauri 桌面+审批双防线,门槛高) | | 9 | `AiChat.vue:423` | system 消息 v-html XSS 向量(已确认 useMarkdown.ts:192 `_purify.sanitize()` 覆盖,DOMPurify 默认配置防 script/iframe/object) | **主代核验印证(防污染)**: - H2 🔴 **确认**: `commands.rs:290` grep 命中 `unwrap_or_default()`,与 audit.rs 修复口径不一致 ✅ - H4/H8 XSS **降级🟡**: `useMarkdown.ts:192` 确认 `_purify.sanitize(_marked.parse(wrapped))` 覆盖所有角色(含 system) ✅ - H1 截断 **降级⚪**: i64::MAX = 9.22×10¹⁸ ms ≈ 2920 亿年后,当前 1.7×10¹² ms 远在范围内 ✅ - H9 Path Traversal **降级🟡**: Tauri 桌面应用非网络服务 + High risk 审批双重防线 ✅ - **待修项回流 todo**: 🔴 **1 项** (commands.rs:289 ai_approve 吞错修复) **主代修复闭环(2026-06-18·workflow w999qdu86 3 agent + 主代核查)**: - 🔴1 **BUG-260618-11 已修**:commands.rs:289-303 ai_approve None 分支 match 三路分流(Ok(Some)→状态判断 / Ok(None)→未找到 / Err(e)→tracing::error+明确 DB 故障 Err),对齐 audit.rs audit_finalize。原 unwrap_or_default 已消。行为变更:DB 故障现返「查询审批记录失败(DB 故障),请重试」明确错误(原误为「未找到挂起」),同属 Err 分支语义不变。 - 🟡4 处理:**#2** context.rs:56 chars_ratio 0.35 加注释标注偏保守(值未变,降值属行为变更本次不做) / **#3** types.ts:209 IntelligenceTier 加注释对齐 CostTier + UX-260618-04 决策 / **#5** audit.rs:402 find_cached_high_risk_result 加性能注记(session lock 内串行 DB 查询线性增长,批量预取架构改暂未做) / **#4** system role 完备性 grep 核验 **PASS**(14 处 role 赋值全 user/assistant 无 system;2 处比较点 AiChat.vue:421/2545 只读渲染;发送路径仅 push user/assistant,system 不可编辑不可发送) - 主代核查:cargo check --workspace EXIT 0(4 pre-existing dead_code warning 基线)+ vue-tsc EXIT 0 + 独立 grep 印证 agent selfCheck 无污染 - **🔴1 待修项已闭环,todo BUG-260618-11 已销账** ### CR-260618-12 ToolCard.vue 工具结果渲染 8 项(workflow w2drz3ppo·8 agent 并行核验 isReal 8/8+主代统筹实施·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow w2drz3ppo 8 agent 并行核验 + 主代统筹实施 + vue-tsc 全量验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪1 - **验证**: vue-tsc --noEmit EXIT 0 / grep 印证 ToolCard.vue 22 处新字段 + i18n 18 处新 key 全落地。 **8 项实施(主代统筹:合并冲突/修死代码位置/补漏字段)**: | # | 项 | 判定 | |---|-----|------| | 1 | UX-05 run_workflow 显 execution_id(formatToolResult+toolResultSummary 加 case,删误导 workflowHint,旧 key 保留防引用) | ✅ | | 2 | UX-06 patch_file 模板分支渲染 diff 红绿行(复用 ai-tool-diff-pre)+resultDiffLines computed(parsed.diff 截断 120 行) | ✅ | | 3 | UX-07 delete_file 软删补 backup_path(formatToolResult+toolResultSummary+i18n 加槽) | ✅ | | 4 | UX-08 read_file 模板 has_more 显「shown/total 行,已截断」 | ✅ | | 5 | UX-09 advance_task 加 review_rounds(>0 显退回累加) | ✅ | | 6 | UX-10 list_trash(被 UX-12 list_* 重写吸收,无独立改动) | ✅ 吸收 | | 7 | UX-11 list_directory truncated 显截断提示 | ✅ | | 8 | UX-12 list_* 重写修 Array.isArray 对象误判+结构化列表+file_info modified+write_file old_size/encoding+rename_file cross_volume/bytes_moved | ✅ | **主代统筹裁决(审查防污染,不盲应用 agent edits)**: - **冲突吸收**:UX-10/12 都加 list_trash case + trashCount(文案冲突),采纳 UX-12(修 Array.isArray 对象误判真实 bug——后端返 {items,total,has_more} 对象非数组,原判断恒 false 致折叠态无计数),UX-10 整条吸收 - **死代码位置修正**:write_file 有专属模板分支拦截,formatToolResult write_file case 不触发;old_size/encoding 改模板分支(主渲染路径)非 agent 建议的 formatToolResult case - **type 去重**:12 缺字段合并 ToolResult type 一处 Edit(agent 说缺 truncated/review_rounds/bytes_moved 实际已有,只补真缺) - **task_id 漏列拦截**:UX-05 agent 用 r.task_id 但 typeFieldAdditions 漏,vue-tsc 拦 TS2339,主代补 task_id(印证 agent edits 自身不一致,vue-tsc 必验) **审查防污染印证**:8/8 isReal=true,每份 selfCheck 独立 grep tool_registry.rs 后端返回印证。todo line 号漂移(diffLines agent 说 :678 实际 :696)被主代 Read 核验拦截。单文件域 ToolCard.vue 主代统筹实施(避免并行冲突),workflow 价值在 8 工具并行核验 fan-out + 审查防污染独立核验。 - **⚪ WATCH-1**: list_directory/list_* 截断文案硬编码 {n:1000}(后端 tool_registry.rs:880 max_entries=1000),后端上限变更需同步前端文案 - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-13 SMELL-P0-1吞错降级加warn+B-260618-06表格CSS+coordinator空壳评估(workflow w5siwnipj·6 agent并行核验+主代统筹实施·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow w5siwnipj 6 agent 并行核验 + 主代统筹实施 + cargo/vue-tsc 全量验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪1 - **验证**: cargo check -p devflow EXIT 0(4 pre-existing dead_code warning 基线:PendingApproval/state 字段,非本批) / vue-tsc --noEmit EXIT 0。 **4 项实施(主代统筹)+ 2 项 no-action**: | # | 项 | 判定 | |---|-----|------| | 1 | B-260618-06 markdown 表格 display:block CSS(ai-md.css:59 全局根因 + AiChat.vue:3366 局部) | ✅ 两处移除 display:block/overflow-x:auto,table 恢复 display:table 列对齐,气泡 .ai-msg-bubble--ai.ai-md overflow-x:auto 承载宽表格滚动 | | 2 | SMELL-P0-1 agentic.rs:348 provider 池吞错 | ✅ match + tracing::warn 降级(空 Vec 走原空池兜底零行为变更) | | 3 | SMELL-P0-1 knowledge_inject.rs:130,139,312 检索/解析吞错 | ✅ 三处 match + tracing::warn 降级(空 Vec 不注入/提炼跳过零行为变更) | | 4 | SMELL-P0-1 idea.rs:292-296 tags JSON 解析吞错 | ✅ match + tracing::warn 降级(空 tags 继续评估,tags 影响 scoring ±0.5~1.5 但评估不应因坏 tags 阻塞) | | 5 | SMELL-P0-1 audit.rs:344(吞错) | ❌ 误报 no-action(audit_finalize CR-260618-11 已修三路 match,line 漂移+旧版本) | | 6 | SMELL-P2-4 coordinator.rs 空壳 | ❌ no-action(line 3 模块注释已有「⚠ B 路线占位...勿删」标注齐全,零外部调用,保留 B 路线预留点) | **主代统筹裁决(审查防污染,独立 grep 核验 agent selfCheck)**: - agent selfCheck 6/6 准确(主代独立 Read ai-md.css/knowledge_inject.rs/idea.rs 印证 currentCode 逐字无误,behaviorChange=false 判定可信:加 warn 不改返回值,空 Vec 仍走原降级路径) - **audit 误报印证审查防污染价值**:todo line 声明 audit.rs:344 吞错,独立 grep 核验实为 CR-11 已修的三路 match(:337-347),unwrap_or_default 仅剩 :274(from_str)/:499(to_string)非 DB——line 漂移+旧版本双重原因,workflow agent 独立核验拦截 - **CSS 方案主代补强**:agent 建议全局 ai-md.css 移除 display:block,主代核验确认全局影响面(ProjectDetail/Ideas/Knowledge/TaskDetail 同引用),宽表格滚动仅 AiChat 气泡场景需补 overflow,其他页 markdown 表格少宽表可接受;采纳 agent 核心理念(移除 display:block 恢复列对齐)+ 主代补 AiChat 气泡 overflow-x:auto - **⚪ WATCH-1**: SMELL-P0-1 58 处 unwrap_or_default 全量排查降 P2(5 高危已清,余为 Option 取默认/JSON 序列化等低危,非紧急) - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-14 安全并行批·df-execute补测试+前端ErrorBoundary+6篇文档实施状态标注+executor run评估(workflow wowdnw4ba·5 agent并行·主代独立核验·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow wowdnw4ba 5 agent + 主代 cargo/test/vue-tsc 全量验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪1 - **验证**: cargo check --workspace EXIT 0 / cargo test -p df-execute 5 passed 0 failed / vue-tsc --noEmit EXIT 0。 **5 项逐项核验**: | # | 项 | 判定 | |---|-----|------| | 1 | SMELL-P0-4 df-execute 补测试(tests/shell.rs 5 #[tokio::test] 覆盖成功/非零退出/超时/env注入/working_dir + shell.rs:55 过时TODO注释清理) | ✅ execute逻辑零改动,主代 cargo test 5 passed | | 2 | SMELL-P2-2 前端 ErrorBoundary(main.ts app.config.errorHandler + ErrorBoundary.vue onErrorCaptured 降级UI+重试 + i18n error.ts×2 中英对称) | ✅ 未嵌入仅提供能力,App.vue 未改零行为变更 | | 3 | SMELL-P1-8 文档组1(B-03/AiNode自审/类型对齐 3篇加「实施状态(2026-06-18核对)」标注段) | ✅ 不改设计正文,DOC2 行号经独立 grep 修正 | | 4 | SMELL-P1-8 文档组2(F-01 标 cost/intel 解耦改方向/F-05 标数据模型偏离/secret下沉 标方案B全落地) | ✅ router.rs:27-35/56-63 + provider.rs:97/105-106 file:line 佐证 | | 5 | SMELL-P2-1 executor run 重构评估 | ✅ no-action(SMELL描述过时:run方法实测 151行+2参 非描述282行+8参,SW-01 TOCTOU保留 line 136/138-153,描述系历史形态) | **主代核查·审查防污染印证**: - df-execute tests: cargo check --workspace 默认不编译 tests target,主代补 cargo test -p df-execute 验证 5 测试编译+逻辑双通过(防 check 假绿)。 - executor no-action 印证铁律价值:agent 现场读源码发现 SMELL-P2-1 描述(282行+8参)系历史形态,当前 run 方法 151行+2参已可接受,不盲改(避免动 SW-01 TOCTOU 敏感逻辑引入回归)。源码形态 > todo 描述。 - 6 篇文档标注段独立 grep 核验全在(line 7-11),file:line 佐证真实。ErrorBoundary.vue onErrorCaptured:21 + main.ts errorHandler:12 grep 命中。 - **⚪ WATCH-1**: ErrorBoundary.vue 当前未嵌入任何组件树(仅 main.ts errorHandler 全局兜底生效),后续需包裹易错子树时按需引入(零行为变更设计意图) - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-15 B-260618-23最大轮次修法B+SMELL-P1-2/P1-3样板消除评估(workflow wuirgcxoy·3 agent·主代独立核验·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow wuirgcxoy 3 agent + 主代 vue-tsc 验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪1 - **验证**: vue-tsc --noEmit EXIT 0(B-260618-23 前端) / P1-2/P1-3 no-action 无 rust 改动 cargo 不需。 **3 项逐项核验**: | # | 项 | 判定 | |---|-----|------| | 1 | B-260618-23 Agentic 最大轮次修法 B(App.vue:215-224 onMounted loadAll 后加 setAgentMaxIterations/setAgentMaxRetries 恢复同步 clamp 对齐 GP + GeneralPanel:266 双保险) | ✅ done 修bug正向,主代 vue-tsc EXIT 0 | | 2 | SMELL-P1-2 .map_err 抽 helper | ✅ no-action(前提过时:err_str helper 已存在 mod.rs:23·纯 to_string 样板 0 残留·101 处已用 err_str·主代 grep 印证) | | 3 | SMELL-P1-3 useTauriCommand composable | ✅ no-action(前提不成立:views 仅 AuditLog:102 直接 invoke·invoke 已统一 api 层·try-catch 副作用异构·主代 grep 印证) | **主代核查·审查防污染印证**: - 两 no-action 印证源码形态 > todo 描述:agent 现场读源码发现 err_str helper 早前已落地(P1-2)、invoke 已统一 api 层(P1-3),不盲改。主代独立 grep 印证:err_str 在 mod.rs:23 / to_string 残留仅 mod.rs:22 注释字面量 / views invoke 仅 AuditLog:102。 - B-260618-23 修 bug 行为变更正向(重启后正确恢复持久值),clamp 边界与 GeneralPanel 逐字对齐(Math.min(50,Math.max(1,\|\|10)) / Math.min(10,Math.max(0,??3))),GeneralPanel onMounted sync 保留双保险(IPC 幂等)。 - **⚪ WATCH-1**: B-260618-23 修法 B 依赖 appSettings SQLite 持久化(前端已落 DB),重启后 App.vue loadAll 读真值同步后端。若用户报告仍未生效,查后端 set IPC 是否真落 AtomicUsize + loadAll 是否在发消息前完成 - **待修项回流 todo**: **无** 🔴/🟡 项 ### CR-260618-16 SMELL-P1-1 crates/全域unwrap排查+P1-4聚合评估+P2-3死字段评估(workflow w8774xcev·7 agent·主代独立核验·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow w8774xcev 7 agent + 主代 cargo/test 验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪2 - **验证**: cargo check --workspace EXIT 0 / cargo test -p df-workflow EXIT 0(dag 注释不影响)。 **7 项逐项核验**: | # | crate | 判定 | |---|-----|------| | 1 | df-ai-core+types | ✅ no-action(31处unwrap全#[cfg(test)],生产零危险) | | 2 | df-ai | ✅ no-action(21处全测试,2处生产expect已注释不变量 context:499/model_probe:34) | | 3 | df-storage | ✅ no-action(~50处全测试,全程?+map_err健康) | | 4 | df-workflow | ✅ done(dag.rs:106/135两处运行时unwrap加safe注释,SW-01保留) | | 5 | df-execute | ✅ no-action(unwrap零)+P2-3评估(env死字段5构造点全空HashMap) | | 6 | df-nodes | ✅ no-action(75处全测试)+P1-4评估(缓做)+P2-3评估(NodeOutput.metadata死字段) | | 7 | df-ideas+project | ✅ no-action(49处全测试) | **主代核查·审查防污染印证**: - unwrap 排查绝大多数 no-action 印证 crates/ 错误处理已健康(之前多批重构清理):生产 unwrap 全在 #[cfg(test)] 或已是安全 expect/unwrap_or。仅 df-workflow dag.rs 加 2 处 safe 注释。主代独立 grep 核验 dag.rs:106/135 注释存在 + SW-01 TOCTOU(:136/141/150/163-166)完整保留。 - **P2-3 描述错误修正**:todo:185 写「NodeContext.metadata」有误,源码为准 NodeContext(node.rs:13-26)无 metadata 字段,含 metadata 的是 NodeOutput(node.rs:34)且是死字段(2构造点初始化空+0消费)。ShellRequest.env 同死字段。源码形态 > todo 描述。 - P1-4 评估:df-nodes 拆 df-task-state-machine 缓做(task_state_machine.rs 零 crate 依赖+单一消费者+拆出不解锁循环依赖,收益不抵成本)。 - **⚪ WATCH-1**: crates/ 生产 unwrap 仅 df-workflow 2 处加注释,若未来新代码引入生产 unwrap 需重新评估 - **⚪ WATCH-2**: NodeOutput.metadata + ShellRequest.env 均死字段(0消费),如需清理建议直接删字段(降级方案)或改结构体(纯整洁低优先) - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-17 SMELL-P1-7 bool评估+P1-5下沉评估+NodeOutput.metadata实删+ShellRequest.env评估(workflow weckqp9mv·4 agent·主代独立核验·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·workflow weckqp9mv 4 agent + 主代 cargo 验证 + 独立 grep 核验)**: ✅ **PASS** — 🔴0 🟡0 ⚪1 - **验证**: cargo check --workspace EXIT 0(4 warning 全 pre-existing dead_code 基线·非本次引入)。 **4 项逐项核验**: | # | 任务 | 判定 | |---|------|------| | 1 | SMELL-P1-7 | ✅ no-action(enum 负收益·bool 直映射 DB·2 crud+2 IPC 调用者紧邻定义·真正歧义前端 store 拆 TS 方法非推 enum·IPC 引 enum 触 Tauri 序列化 prod 报错) | | 2 | SMELL-P1-5 | ✅ no-action(advance_task_atomic 已领域层 df-nodes/task_advance_node.rs:43·3 IPC 纯转发✅;record_to_idea 下沉违反依赖倒置·df-ideas→df-storage 倒依赖·IPC 是 adapter 正确归属) | | 3 | NodeOutput.metadata | ✅ done(实删 node.rs 字段+2 构造点 empty()/from_value()·0 消费者·零行为变更) | | 4 | ShellRequest.env | ✅ no-action(前提错·测试 #4 execute_env_injection 实塞 KV 透传子进程验证·活跃消费链非死字段) | **主代核查·审查防污染印证**: - 4 项 3 个 no-action 印证代码库健康。仅 NodeOutput.metadata 实删(纯死代码零消费)。主代 grep 核验 node.rs struct 仅 data 字段 + empty/from_value 唯二构造。 - **P2-3 深化**:批次3 评估为「保留或删·低优先」,批次4 实删 metadata(env 经核为活跃消费链保留)。 - **⚪ WATCH-1**: 其他会话并发改主代码,本核查为 cargo check 快照·源码形态可能已变(memory [[review-batching-worktree-transient]] 教训) - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-18 UX-260618-13 stripMd 列表摘要 MD 剥离(主代串行·规避 AiChat God 文件·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代串行实施 + vue-tsc 验证)**: ✅ **PASS** - **验证**: vue-tsc EXIT 0。 **改动**: - 新建 `src/utils/markdown.ts` stripMd(剥离粗体/斜体/删除线/标题/行内代码/代码块围栏/列表/引用/链接/图片等 MD 语法·保留文字内容·空输入返空串)。 - `Knowledge.vue:71`(item.content) / `Projects.vue:148`(project.description) / `Ideas.vue:47`(idea.description slice) 三列表摘要接入 stripMd。 - 修自引入 bug:首版注释含 `*/` 子序列(`**/__/*`)致 JSDoc 块注释提前闭合 → TS1011/1127·改安全中文措辞。 **主代自测·审查防污染**: - AiChat 标题 strip 子项(待核 title.rs)规避 God 高频文件·留待并发期后。 - 前端纯新增 util + 单行插值·vue-tsc EXIT 0 独立核验。 - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-19 idea.rs:111 promoted_to is_some+unwrap 改 if let Some(Explore2 巡查核验真项·主代串行·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代串行 + cargo 验证 + 独立 grep 核验)**: ✅ **PASS** - **验证**: cargo check --workspace EXIT 0(4 warning 全 pre-existing dead_code 基线·非本次引入)。 - **改动**: `promote_idea` 中 `if record.promoted_to.is_some() { return Err(format!("灵感已立项: {}", record.promoted_to.unwrap())); }` → `if let Some(promoted_to) = &record.promoted_to { return Err(format!("灵感已立项: {}", promoted_to)); }`。消除 `is_some()` 守卫后冗余二次 `unwrap`·改借用·零行为变更。 **主代核查·审查防污染印证**: - Explore2 开放式扫 5 候选·独立 grep 核验后仅此项真:script_node.rs:46 `unwrap_or(-1)` 已安全不 panic(注释 ROI 低) / AuditLog.vue:96 误判(空数据 length=0≠PAGE_SIZE→hasMore 正确 false) / Tasks.vue:144 projectFilters 与 getProjectName 不同用途非重复 / ConnectionPanel.vue 文件不存在(Explore2 虚构)。防污染拦下 4 误报·命中率 20%。 - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-20 批次6 测试补测 scan/router/migrations(workflow w07wahoti·3 agent 并行·零行为变更·主代 grep 核验测试数一致·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代核验) - **结论(2026-06-18·workflow w07wahoti 3 agent + 主代 grep 核验)**: ✅ **PASS** - **3 crate 补测·零行为变更**(只加 `#[cfg(test)] mod`·不改生产): - df-project scan.rs +10(normalize_path 跨平台×3 / is_monorepo workspaces:null 防回归×3 / collect_images 徽章过滤×4)·agent 自报 cargo test 25 passed - df-ai router.rs +3(多模态子集[Text,Vision]过滤 / enabled=false 混池 / 空池 select() 返 None)·自报 112 passed - df-storage migrations.rs +4(column_exists 列存在/不存在/表不存在/精确匹配·:memory: SQLite)·自报 33 单测+11 集成 - **主代 grep 核验(防污染·源码形态 > check 快照·memory review-batching-worktree-transient)**:scan.rs `#[test]`=25(15旧+10新✅) / router.rs=15(12旧+3新✅) / migrations.rs=4(新增✅)·与 agent 自报全一致。 **主代核查·审查防污染印证**: - 零行为变更:cfg(test) 隔离·concurrent 会话改生产不影响 test 编译。agent 三段式自验 cargo(memory workflow-cargo-timeout-wrap)·grep 测试数一致强佐证。 - 测试路 Explore 10 候选核验:shell.rs 批次1 已覆盖(过时) / human_node reject 已充分覆盖(:833-848·低估) / adversarial 有 mod tests(错报 0) / ai_tools+migrations+前端utils 真 0。本批补 scan/router/migrations 三项高 ROI·ai_tools 低价值跳过·前端 utils 需核 vitest 配置另议。 - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-21 ai_tools 补 6 sync test + risk_level 前端核验(主代串行·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代串行 + cargo test 验证)**: ✅ **PASS** - **验证**: cargo test -p df-ai ai_tools::tests 6 passed(112 filtered·现有测试零冲突)。 - **ai_tools.rs +6 sync test**(零行为变更·只加 `#[cfg(test)] mod`): - risk_level_serde_lowercase(Low/Medium/High→"low"/"medium"/"high"·serde rename_all 验证) - register_and_get_tool(注册后可查·不存在返 None·len/is_empty) - register_same_name_overwrites(同名二次注册 HashMap insert 覆盖语义·后注册 risk_level 胜出) - tool_definitions_and_names(注册后 definitions/names 列表正确) - default_is_empty(Default trait 空注册表) - object_schema_collects_required(required 字段收集·is_required true 入 required) - **risk_level 前端核验**:`src/api/types.ts` grep `risk_level` **0 命中** → 后端 `PendingApproval.risk_level`(mod.rs:410)经 IPC 序列化但前端不消费 → **真死**(坐实 SW-260618-21 risk_level 项·佐证选项 a 清理可行)。注:`diff` 活跃(:258 AiApprovalRequired + :328 ToolResult·UX-260618-06)非死。 - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-22 PendingApproval.risk_level 死字段删(主代串行·多角度分析确定推进·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代串行 + cargo check 验证 + 独立 grep 核验)**: ✅ **PASS** - **验证**: cargo check --workspace EXIT 0(`PendingApproval.risk_level` dead_code warning 消失·剩 `diff` + `releases`/`node_executions` 基线)。 **多角度分析·确定推进**: - 字段死坐实:前端 `types.ts` `risk_level` 0 命中(前端不消费)·后端 cargo dead_code 报 never read·0 读取消费者。 - 删波及可控:recover_pending 过滤语义保留(改 `if risk_from_str().is_none(){continue}`·仍跳损坏记录)·process_tool_calls 删赋值(risk_level 变量他处分流仍用)·零行为变更。 **改动**: - `mod.rs:410` 删 `pub risk_level: RiskLevel` 字段 + `:45` 删 `use df_ai::ai_tools::RiskLevel` import(删字段后 unused)。 - `audit.rs:282` recover_pending 删 `risk_level: risk` 赋值 + `:275` 过滤改 `if risk_from_str(&rec.risk_level).is_none() { continue }`(语义保留)。 - `audit.rs:671` process_tool_calls 删 `risk_level,` 赋值(risk_level 变量他处分流仍用)。 **主代 grep 核验(防污染)**: - `AuditRecord.risk_level`(audit.rs:71·:115 序列化返 AuditLog)活跃保留。 - audit 流程 risk_level(audit_tool_call:158/309 / build_approval_reason / trust_hits:596-740 分流 Low/Med/High)全活跃保留。 - PendingApproval 构造的 risk_level 赋值(:282/:671)全删·grep 确认。 - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-23 SW-260618-21 b 预留功能标 allow 消 dead_code warning(主代串行·自主决策 b·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测) - **结论(2026-06-18·主代串行 + cargo check 验证)**: ✅ **PASS**·cargo check --workspace EXIT 0 **0 warning**(原 4 dead_code 全消)。 - **自主决策 b(保留+标 allow)**:5 处预留/IPC 字段标 `#[allow(dead_code)]` + 注释预留意图·零波及消 warning: - `SessionState` enum(mod.rs:172)+ `session_state` fn(:393):预留读视图(SW-02 类终态化复用·0 消费者保留扩展点) - `AppState.releases`(state.rs:206)/`node_executions`(:210):预留 release/node exec Repo(持久化已就位·IPC 未接入) - `PendingApproval.diff`(mod.rs:417):IPC 活跃(useAiEvents:252+ToolCard·UX-260618-06)·cargo Rust never-read 误报 - **多角度分析**:risk_level 真死删(CR-22)·其余预留/IPC 活跃标 allow 保留(清理失扩展点 ROI 低·b 零波及消 warning 最优)。 - **待修项回流 todo**: **无** 🔴/🟡 项 --- ### CR-260618-24 God拆分a(tool_registry file+data抽出+基线测试) + sweep批1-4死依赖/死代码/死导出/注释/i18n/model_fetch(workflow w2xkw4ybh data抽+主代file抽+主代sweep实施·工作区未提交·commit-policy-deferred) — ✅ 已审(ISSUES·🔴1🟡1·review 会话 3 agent 并行核验) - **范围**: - **God 拆分 a(SMELL-P0-2)**:`tool_registry.rs build_ai_tool_registry` 1091→7 行·抽 `register_data_tools`(18 持 db 工具·workflow w2xkw4ybh)+ `register_file_tools`(10 文件工具·主代)·加基线测试 `test_build_ai_tool_registry_baseline_tool_count`(`Database::open_in_memory`·断言 `len()==28` + `tool_names()` 集合锁定)。 - **批1 死依赖/死代码(Rust)**:`df-execute/Cargo.toml` 删 df-types/async-trait/tracing(全仓零引用) · `df-workflow/Cargo.toml` 删 thiserror(零引用) · `df-workflow/eventbus.rs` 删 `emit_human_approval_request`(零调用·实际走 `send()`)+ SendError import · `df-ai/ai_tools.rs` 删 `ToolExecutionResult`(零消费者)。 - **批2 前端**:`useMarkdown.ts` 删 `clearHistoryCache`(零消费) · `useConfirm.ts` 删 `ConfirmFn`/`AnswerFn`(零 import) · `useAiPanel.ts` `restoreUiState` 去 `export`(零外部调用) · `markdown.ts` stripMd 围栏正则 `[a-zA-Z]*`→`[^\n]*`(吃任意 infostring 如 rust,norun) · `time.ts` `formatDate` 读 `i18n.global.locale`(原硬编码 zh-CN·CR-260615-08 漏修)。 - **批3 注释**:`df-project/manager.rs` 删误导 TODO(分层正确·持久化在 storage 层) · `df-ideas/promotion.rs` 精简模块注释(历史空壳已删)。 - **批4 med**:`df-ai/model_fetch.rs` `is_non_chat_model` 删 `|| id.contains("-search")`(误剔合法 search-augmented chat 模型 gpt-4o-search-preview·davinci-search 仍覆盖旧变种)+ 补单测 `is_non_chat_model_keeps_search_augmented_chat`。 - **验证**:`cargo check --workspace` EXIT 0(0 warning) / `cargo test df-ai` 119 passed / `cargo test -p devflow test_build_ai_tool_registry_baseline_tool_count` 1 passed / `vue-tsc` EXIT 0。 - **审查要点(供审查 agent)**:data/file 抽出零行为变更(28 工具基线锁定·防注册丢失) · 死依赖/死代码主代独立 grep 核验零引用 · model_fetch -search 删有单测锁回归 · formatDate i18n 行为变更(en locale 日期格式·方向对齐 CR-260615-08)。 - **关联**:SMELL-P0-2 销账 / ARC-260618-01 a ✅ 已实施 / ARC-d(conditions)/e(adversarial)/SW-21(formatRelativeZh)/22(useAiSend DRY) 进 todo。 - **复审结论(2026-06-18·review 会话 3 agent 并行独立核验,不信主代声明)**: ⚠️ **ISSUES** — 🔴1 🟡1 ⚪1 - ✅ **God 拆分 PASS**(Agent A):build 调 register_data_tools(:367)+ register_file_tools(:368),build 体零残留内联;**重名注册闭环**(巡检 #11 信号消除:28 name 静态互异 + 基线双断言 len==28 + sorted 集合防护 HashMap 覆盖);抽样 run_command/list_projects 逐字一致(get_*_count 仅位置移动非行为变更) - ✅ **批1 死代码全 PASS**(Agent B):df-execute 删 df-types/async-trait/tracing + df-workflow 删 thiserror + eventbus 删 emit_human_approval_request/SendError + ai_tools 删 ToolExecutionResult,**4 项全仓 grep 零引用**(人类审批走 `bus.send()` 非删的 emit),无误删活引用 - ✅ **批4 model_fetch PASS**(Agent C):删 `|| id.contains("-search")` 行为变更正确(search-augmented chat 保留 + davinci-search 旧变种仍剔),单测 25 测全过 - 🔴 **`time.ts:44` formatDate 漏 `.value`**(Agent C 铁证):`legacy:false` composition 模式 `i18n.global.locale` 是 ref,`(i18n as any).global.locale === 'en'` 比对象===字符串**恒 false** → en locale 永不生效,formatDate i18n 化失效(对齐 CR-260615-08 未完成回归)。`App.vue:227`/`GeneralPanel:259` 均用 `.value` 印证。修法:补 `.value`。 - 🟡 **`markdown.ts:19` stripMd 围栏正则边缘回归**:`[a-zA-Z]*`→`[^\n]*` 后,内联裸围栏无换行(`See \`\`\`rust below`)吃到行尾。场景边缘(列表摘要极少内联裸围栏),建议注释标注边界 - ⚪ **`anthropic_compat.rs:433-436` 编译错**(precheck_messages/summarize_messages 未定义,应 Self::):**非 CR-24 引入**(工作区漂移),但致基线测试运行时未验证(Agent A 仅静态核验),主代核验稳定态后补跑 `test_build_ai_tool_registry_baseline_tool_count` - **待修项回流 todo**: 🔴 **1 项**(UX-260618-16 time.ts formatDate 补 .value) **第二位审查 agent 独立核验印证(2026-06-18·独立 grep/read·防上下文污染)**: - ✅ 与 review 会话 3 agent 结论一致:🔴1(time.ts .value) / 🟡1(markdown.ts 边缘) / ⚪1(anthropic_compat 漂移) - **🔴 time.ts:44 漏 .value 二次独立坐实**:`i18n/index.ts:17 legacy:false`(composition 模式)→ `i18n.global.locale` 是 `WritableComputedRef` 非 string。`App.vue:227` + `GeneralPanel.vue:259` 均用 `i18n.global.locale.value = ...` 印证 ref 语义;`(i18n as any).global.locale === 'en'` 比较 ref 对象与字符串 **恒 false** → en locale 永不生效。**本审查 agent 首轮未捕捉此对抗点,经 review 会话坐实后独立复核确认**——印证对抗思维不可省(`.value` 是 vue-i18n legacy/composition 模式高频易错点)。 - **A. God 拆分独立佐证**(超出对方会话覆盖):grep df-ai 全 crate `#[(tokio::)?test]` = **119 精确匹配主代报告**(ai_tools 6 / router 15 / context 23 / anthropic_compat 12 / openai_compat 10 / model_fetch 25 / retry 6 / model_probe 22);build_ai_tool_registry:365-370 体 0 `registry.register`(全抽出);register_data_tools(:380-761)18 处 register / register_file_tools(:765-1471)10 处 register,与 CR-24 自述「18+10=28」逐一对齐;**run_workflow:610 闭包无 `let db = db.clone()` 前缀**(对比其余 17 data 工具全有),CR-52 防御 Err 设计保留;RiskLevel 28 处计数与 28 工具一一对应。 - **B. 批1 死代码独立佐证**:df-execute/Cargo.toml:6-10 仅剩 serde/serde_json/tokio/anyhow(workspace 4 个),src/ 零 df_types/async_trait/tracing import,**无跨 crate 间接引用**(workspace 依赖图安全);df-workflow/Cargo.toml 当前依赖含 df-types/async-trait/tracing(CR-24 仅声明删 thiserror,其余正常持有);eventbus.rs:1-56 仅 send/subscribe/with_capacity/Default/Clone;ai_tools.rs ToolExecutionResult 全仓零引用。 - **C. 批2 前端独立佐证**:clearHistoryCache/ConfirmFn/AnswerFn 全 src 零命中(仅待审查.md 自述);useAiPanel.ts:49 `function restoreUiState()` 无 export,:52 模块内自调;markdown.ts:19 `/```[^\n]*\n?/g`(非 `[a-zA-Z]*`)印证。 - **D. 批3 注释独立佐证**:manager.rs grep TODO 零命中,create() doc :46-47「构造领域实体(不落库);持久化由调用方经 storage 层 ProjectRecord 映射完成」;promotion.rs:1-3 模块注释 3 行精简。 - **E. 批4 med 独立佐证**:model_fetch.rs:196-219 is_non_chat_model 列表(图片/语音/realtime/transcribe/moderation/:218 `davinci-search`),**无 `-search` 残留**;新测试 :281-289 4 断言(3 search-augmented 保留 + 1 davinci-search 仍剔);另有 :394-396 non_chat_search_variants_filtered 印证。 - **🟡 markdown.ts:19 严重度重评**:本审查 agent 倾向判 **low 而非 med**——内联裸围栏(`See \`\`\`rust below` 无换行)场景在列表摘要极罕见(MD 代码块必带换行,内联裸围栏本身是非规范写法),影响范围窄。对方会话判 med 偏保守,差异在严重度估计非事实分歧。建议修法:加 `[^\n]*` 边界注释标注「内联裸围栏场景」即可,无需改正则。 - **⚪ anthropic_compat.rs:433-436 编译错印证**:确认非 CR-24 引入(工作区漂移),需主代核验稳定态后补跑基线测试(对方已记录)。 **主代修复闭环(2026-06-18)**: 🔴 `time.ts:44` 已补 `.value`(`(i18n as any).global.locale.value`·对齐 App.vue:227)·`vue-tsc` EXIT 0 印证 en locale 现正确生效。CR-24 🔴 消·verdict 转 PASS(🟡 markdown.ts:19 边界注释 low 可选·⚪ anthropic_compat 漂移非本 CR 待独立核验)。 --- ### CR-260618-25 wo7d6zdqm findings 推进(secret keyring provider id + shell 超时命令名 + run_command timeout clamp 600s) + wdvtbjozg ux(异步按钮禁用态防双击 + 空态/错误态·7 vue + i18n)(workflow 多代理 + 主代实施·工作区未提交·commit-policy-deferred) — ✅ 已审(PASS·主代自测+workflow) - **范围**: - **wo7d6zdqm 错误消息/安全(主代实施)**:`df-storage/secret.rs` keyring 3 处错误带 provider id(entry_for/set/delete) · `df-execute/shell.rs:102` 超时消息带命令名 · `tool_registry.rs run_command` timeout_secs clamp 600s(防 LLM 传超大冻结) · `utils/time.ts formatDate` 补 `.value`(CR-24 🔴 修复)。 - **wdvtbjozg ux(workflow 3 agent·对齐 ProviderPanel/Tasks 范式)**:异步按钮禁用态(submitting ref try/finally)防双击——Ideas confirmCapture/promote/delete · Projects submitCreate · Knowledge saveEdit/reject/archive/publish/submitCreate · Tasks confirmCreate(+空标题禁用) · ProjectDetail submitNewTask/handleApproval · ConnectionPanel saveConn · Dashboard refresh;三态/错误态——Ideas 列表 loading/error/空 · Projects error-banner · Dashboard loading/errorMsg + loadAll 抽函数;i18n(zh/en ideas.ts listEmpty/creating/deleting/promoting · dashboard.ts err.loadFailed)。 - **验证**:`cargo check -p devflow -p df-storage -p df-execute` EXIT 0 / `vue-tsc` EXIT 0。 - **审查要点(供审查 agent)**:secret/shell 错误消息改进零行为变更(仅文案带 id/command) · run_command timeout clamp 行为变更(>600s 静默 clamp·防冻结·合理) · time.ts .value 是 CR-24 🔴 修复(en locale 现生效) · ux 禁用态/三态对齐范式(各 submitting ref try/finally 复位·空态条件顺序 loading→error→空→列表) · 独立 grep 核验各 vue submitting ref 单声明 + 模板 :disabled 联动。 - **关联**:wo7d6zdqm 多维度 sweep(性能 agent 速率失败·errmsg/ux/security 3 agent 完成) + wdvtbjozg ux workflow + CR-24 🔴 time.ts 修。 - **待修项回流 todo**: 无 **复审结论(2026-06-19·独立 grep 核验源码当前形态)**: ✅ PASS · 🔴0 🟡0 ⚪2(low·可选)。verdict 转 PASS。主代自测(cargo check EXIT 0 / vue-tsc EXIT 0)与独立源码核验一致,无 high/med。 **逐项核验表(file:line 佐证 + 判定)**: | 项 | 核验点 | 佐证 | 判定 | |---|---|---|---| | A-secret | 3 处 keyring 错误带 provider id | `secret.rs:92` entry_for `(provider={})`+id · `:115` set `(provider={})`+id · `:121` delete `(provider={})`+id | ✅ | | A-shell | 超时 map_err 带命令名 + secs | `shell.rs:102` `命令执行超时({}s): {}` 含 `secs`+`request.command`(ShellRequest 字段在作用域内) | ✅ | | A-clamp | timeout_secs `.min(MAX)` + 常量 600 | `tool_registry.rs:26` `MAX_RUN_COMMAND_TIMEOUT_SECS: u64 = 600` · `:792` `.unwrap_or(DEFAULT=60).min(MAX)` clamp · `:24` DEFAULT=60(默认 60<600·clamp 不影响正常超时·仅封顶 LLM 传超大冻结) | ✅ | | A-time | formatDate `.value`(CR-24 🔴) | `time.ts:44` `(i18n as any).global.locale.value === 'en'` · 对齐 `App.vue:227` `i18n.global.locale.value = savedLang`(en locale 现正确生效) | ✅ | | B-Ideas | 三态条件顺序 + store 字段 | `Ideas.vue:37-39` `v-if store.loading`→`v-else-if store.error`→`v-else-if filteredIdeas.length===0`→`v-else 列表` · 顺序正确 · `:236` useProjectStore · `project.ts:90-91,93` store.loading/error/clearError 均存在(getter 直读 state) | ✅ | | B-Projects | error-banner + clearError + submitting | `Projects.vue:13-16` `v-if store.error` + dismiss `store.clearError()` · `:51` `:disabled="submitting \|\| !newName.trim()"` | ✅ | | B-Dashboard | loading ref + errorMsg + loadAll + refresh :disabled | `Dashboard.vue:124-125` loading/errorMsg ref · `:194-206` loadAll() 抽函数(try/finally+guard `if(loading) return`) · `:10` refresh `:disabled="loading"` · `:21-24` error-banner | ✅ | | C-Ideas | creating/deleting/promoting 单声明 + try/finally + :disabled | `Ideas.vue:253-255` 三 ref 各一次声明 · `:402/416/428` 入口 guard(`\|\| xxx.value`) · `:404-412/419-424/430-439` try/finally 复位 · `:176/181/207` :disabled 联动 | ✅ | | C-Projects | submitting 单声明 + try/finally + :disabled + guard | `Projects.vue:225` 单声明 · `:278` guard `if(submitting) return`(在 `:279` submitting=true 前) · `:279-290` try/finally · `:51` :disabled | ✅ | | C-Knowledge | submitting 单声明 + 5 函数 try/finally + :disabled | `Knowledge.vue:353` 单声明 · saveEdit/publishCurrent/rejectCurrent/archiveCurrent/submitCreate 均 try/finally 复位 · `:99/100/102/106/233` :disabled 联动 | ✅ | | C-Tasks | submitting 单声明 + 空标题 guard + try/finally | `Tasks.vue:137` 单声明 · `:222` guard `!newTaskTitle.trim()` 在 `:223` submitting=true 前 · `:223-236` try/finally · `:103` :disabled 联动 · 三态 loading/error/empty `:43-45` | ✅ | | C-ProjectDetail | submitting 单声明 + submitNewTask/handleApproval try/finally + :disabled | `ProjectDetail.vue:324` 单声明 · `:327` guard trim · `:328-343` submitNewTask try/finally · `:418-424` handleApproval try/finally · `:36/211` :disabled(审批选项按钮防双击换选项) | ✅ | | C-ConnectionPanel | submitting 单声明 + saveConn + :disabled | `ConnectionPanel.vue:110` 单声明 · `:157-177` try/finally · `:63` :disabled | ✅(low 见下) | | D-i18n-zh | ideas listEmpty/creating/deleting/promoting + dashboard err.loadFailed | `zh-CN/ideas.ts:20-23` · `zh-CN/dashboard.ts:37` `loadFailed: '加载数据失败,请稍后重试'` | ✅ | | D-i18n-en | 对称 | `en/ideas.ts:20-23` · `en/dashboard.ts:37` `loadFailed: 'Failed to load data, please retry later'` | ✅ | **对抗核验印证**: - **submitting ref 单声明?** ✅ 7 vue 全部 setup 内单声明(无重复 declare):Ideas `:253-255` 三 ref·Projects `:225`·Dashboard `:124`·Knowledge `:353`·Tasks `:137`·ProjectDetail `:324`·ConnectionPanel `:110`。无重复声明。 - **try/finally 复位?** ✅ 所有异步函数均 try/finally 复位(异常路径不卡死)。无漏 finally。 - **store 字段存在?** ✅ project store(`project.ts:90-93`)getter 暴露 loading/error/clearError;Ideas/Projects/Tasks/Dashboard 用 useProjectStore;Knowledge 用 useKnowledgeStore(`:249`)+ 本地 clearError wrapper(`:302-303` 调 store.clearError)。字段均存在、store 用对。 - **行为变更标注?** ✅ 仅 run_command clamp 为静默行为变更(>600s 截断·防 LLM 冻结·合理·注释 `:791` 标注),secret/shell/time.ts 均零行为变更(纯文案/纯 bug 修)。time.ts `.value` 是 CR-24 🔴 必要修复(en locale 原本恒中文·回归)。 - **error-banner 重复?** ✅ Ideas/Projects/Dashboard/Knowledge 各自 error-banner(消费各自 store.error / 本地 errorMsg),非同一 store·非冲突·对齐 Knowledge 范式。 **⚪ low(可选·非必修)**: 1. `Knowledge.vue submitCreate`(:438)/ `ProjectDetail.vue handleApproval`(:417) 缺显式 `if(submitting) return` 入口 guard(其余 5 处有)。实际防并发由模板 `:disabled="submitting"` 兜住(按钮点不动·无重入),IPC 路径单调用,风险极低。可选补 guard 对齐范式一致性。 2. `ConnectionPanel.vue saveConn`(:152) 是同步函数(无 await),submitting try/finally 同步置位即复位,此处 submitting 实际无防双击语义(纯占位/视觉)。无功能影响,可选移除或改 async。 --- ## 已审归档 > 已审 CR 段迁独立文件: [待审查归档/2026-06.md](./07-项目管理/待审查归档/2026-06.md)