diff --git a/docs/todo.md b/docs/todo.md
index 1b8059b..7456864 100644
--- a/docs/todo.md
+++ b/docs/todo.md
@@ -387,7 +387,7 @@ graph TD
- [x] ✅ **P1-b** Dashboard 统计源解耦(治 H6/H7 翻页/筛选后统计错乱;统计走后端 count_tasks 独立通道,`d1321af`)
- [x] ✅ **P1-c** 列表状态持久化 — **2026-08-09 核验销账**:usePersistedRef 已接入 Tasks/Projects/Knowledge/Ideas/AuditLog;ProjectDetail Tab 手写 localStorage 按 projectId 隔离(动态 key,usePersistedRef 静态 key 不适用)保留
- [x] ✅ **P1-d** AuditLog 后端 WHERE 筛选 + 真实 total — **2026-08-09 核验销账**:list_tool_executions(record.rs:182)支持 status/risk_level/tool_keyword WHERE + count_by_query 独立 COUNT 真实 total + limit/offset 分页;前端 AuditLog.vue buildQuery 传后端 + usePersistedRef 持久化
-- [~] **P1-e** 审批体系一致 — **部分(2026-08-09 核验)**:挂起计时✅(ApprovalPopup :191 MM:SS)/ 授权粒度统一✅(ToolCard/ApprovalPopup/DirAuthDialog 同 i18n)/ deny 二次确认✅(本批补 DirAuthDialog)/ **失败 toast 🟡待设计**(ApprovalPopup runApproval 乐观移除且 catch 仅 console.error;useAiApproval 失败仅气泡无 toast,需设计 toast 接入)
+- [x] ✅ **P1-e** 审批体系一致 — **全部落地(2026-08-09)**:挂起计时✅(ApprovalPopup :191 MM:SS)/ 授权粒度统一✅(ToolCard/ApprovalPopup/DirAuthDialog 同 i18n)/ deny 二次确认✅(DirAuthDialog 补)/ **失败 toast ✅ 本批落地**(useAiApproval catch emit('ai-toast') + AiChat listen;ApprovalPopup 窗口内自包含 useToast)
- [~] **P1-f** cmd 闪烁 N² — **部分(2026-08-09 核验)**:前端展开缓存已做(FileExplorer loadedChildren 去重);**后端每次展开新目录仍整仓 git status 扫描(module.rs:654)待架构级缓存,登记待设计**
- [x] ✅ **P1-g** store.tasks.filter 污染 — **2026-08-09 核验+补全销账**:ProjectDetail 独立 taskApi.list 已修;ChatInput @项目 enrichment 独立拉取(projectTasksCache)已修 + @任务联想本批改独立全量缓存 taskSuggestionCache(隔离 Tasks 页筛选子集)+ mentionTotal 对齐
@@ -406,8 +406,8 @@ graph TD
- [x] **AC-1** ✅ 已落地(2026-08-09 核验):双层拦截——调用级 `cache.rs:251 find_cached_readonly_result`(同 tool_name+canonical_args 已 completed 即返缓存+警告头,第 2 次即命中)+ 轮级 `is_repetitive_exploration`(helpers.rs:304-332,单签名≥3/唯一率<40%)→ `check_stall_breaker`(警示→硬熔断 emit AiHelpRequired)
- [x] **AC-2** ✅ 已落地(2026-08-09 核验,提交 fe780c0):`MAX_TOOL_CALLS_PER_ROUND=8`(agentic/mod.rs:245)+ 目录列举去重(readonly_cache_args_key 只取 path,返目录专用警告)+ `detect_listing_bypass`(run_command 含列举命令且引用已列目录→警告,保守式不硬拒)
- [x] **AC-3** ✅ 已落地(2026-08-09 核验):prompt.rs:304/323 项目/任务清单已含 id + 注明语(projects_listed_note "引用用 id 非名称");**兜底机制超要求**:entity_resolve.rs name→id 自动解析(RESOLVE_MAP 12 工具 + UUID 跳过 + 0 命中/重名返可行动错误 + 9 单测,audit/mod.rs process_tool_calls 单点漏斗)
-- [~] **AC-4** 🟡 部分(2026-08-09 核验):read_file 结果级提示已落地(tools/file.rs:185-197,支持语言集内追加"改用 read_symbol")+ 三态本体(code_intel.rs:130)+ 缓存兜底;**缺口**:无按模型分级、无符号级命中检测、无采用率回测(prompt 引导对弱模型仍偏弱,待评估)
-- [~] **AC-5** 🟡 部分(2026-08-09 核验):画像复盘已做(docs/AI工具失败画像复盘-2026-08-08.md)+ 2/5 自愈机制落地(advance_task legal_targets 回灌 task_state_machine.rs:121 / patch_file 相近锚点 file.rs:552);**缺口**:无运行时按工具失败率统计机制(read_file 相近文件候选、search_files 空结果引导为复盘建议未落地,待评估)
+- [~] **AC-4** 🟡 部分(2026-08-09 核验):read_file **符号级命中**提示已补强(tools/file.rs:179-196 用 code_intel contains_definition 检测内容含定义节点才提示,替代旧按扩展名)+ 三态本体(code_intel.rs:130)+ 缓存兜底 + 单测 4;**缺口**:无按模型分级、无采用率回测(待评估)
+- [~] **AC-5** 🟡 部分(2026-08-09 核验):画像复盘已做(docs/AI工具失败画像复盘-2026-08-08.md)+ 4/5 自愈机制落地(advance_task legal_targets / patch_file 相近锚点 + **本批补 read_file/read_symbol NotFound 相近文件名候选 + search_files total=0 引导**);**缺口**:无运行时按工具失败率统计机制(待评估)
### 💡 2026-08-04 MCP 多进程架构潜在问题(分析登记)
@@ -462,7 +462,7 @@ graph TD
- [x] **CSW-P1-1** — ✅ 已修:`useAiEvents.ts:101-102` 非当前会话 `AiCompleted` 仍 emit `ai-drain-queue`(带 conversationId,未被 isCurrent 吞);`useAiSend.ts:271-306` drainQueue 用目标 convId
- [x] **CSW-P1-2** — ✅ 已修:`conversation.rs:363-368` 非 live 分支先判 `mem_has_unsaved`(len>persisted_msg_count || needs_full_rewrite),有未落库内存则跳过 restore,DB 快照不再覆盖内存
- [x] **CSW-P1-3** — ✅ 已修:`conversation.rs:335/415-417` `already_live` 分支 pending 完全不动(不 finalize/不 retain/不从 DB 恢复),首屏用 per_conv 内存消息
-- [ ] **CSW-P1-4** — 🔴 **未修,需设计**:切到生成中 conv 首响应气泡丢失(`useAiConversations.ts:333` 仍整体替换 messages 无 round0 占位补回;后端 already_live 分支 :336-352 只返回 user 消息,assistant 占位要轮末才入;MessageList 要求末条 assistant 才渲染流式 + aiShared.ts flushCurrentText 遇 user break)。需设计 round0 assistant 占位气泡补回机制,前后端协同
+- [x] **CSW-P1-4** — ✅ **已修(2026-08-09)**:切到生成中 conv 首响应气泡丢失——前端 switchConversation(useAiConversations.ts:336-355)在 parse 成功、active 置位后,若 `targetGen && 末条是 user` 补前端占位 assistant 气泡(`round0-pending-` 判重),承接 currentText 供 MessageList isLastAi 流式渲染 + flushCurrentText 回填。纯前端,不需后端协同
- [x] **CSW-P1-5** — ✅ 已修:`conversation.rs:613-616` 删除先登记 `deleted_convs` 再删库,save 入口 :259-265 命中直接 return + :416-426 INSERT 前二次校验,封死 Ok(None) 复活窗口
- [x] **CSW-P1-6** — ✅ 已修:`useAiConversations.ts:255-259` `if (!force && id === state.activeConversationId) return` 同 id 短路,不清文本不重拉
- [x] **CSW-P1-7** — ✅ 已修:`useAiConversations.ts:269/303-305` switchingConvs 集合缓冲切换往返窗口;`useAiEvents.ts:110-115` 非当前命中 switchingConvs 的 delta 累积到 per-conv 流式态而非 drop
diff --git a/src-tauri/src/commands/ai/code_intel.rs b/src-tauri/src/commands/ai/code_intel.rs
index 4a5d0f6..0a0fe15 100644
--- a/src-tauri/src/commands/ai/code_intel.rs
+++ b/src-tauri/src/commands/ai/code_intel.rs
@@ -92,6 +92,56 @@ pub fn is_supported_ext(ext: &str) -> bool {
matches!(ext, "rs" | "ts" | "tsx" | "js" | "jsx" | "vue" | "go" | "java" | "py")
}
+/// 判断 source 内容是否真的含可提取的函数/类/结构体定义(AC-4 read_file 符号级命中提示)。
+///
+/// read_file 读取成功后据此决定是否追加「改用 read_symbol」提示:仅当内容里真的存在
+/// DEFINITION_KINDS 定义节点才提示——比旧按扩展名判断更准,无定义的文件不瞎提示。
+/// 与 read_symbol 同语法树逻辑(grammar_for + DEFINITION_KINDS + Vue 切 \n";
+ assert!(contains_definition(vue, "vue"));
+ // 无