优化: AI Chat全栈多批审查修复与架构清理(risk_level清理/路由解耦/工具渲染/测试补测/死代码)
This commit is contained in:
@@ -8,6 +8,45 @@
|
||||
|
||||
---
|
||||
|
||||
> ## 实施状态(2026-06-18 核对)
|
||||
>
|
||||
> **②-⑤ 全部已落地**(原设计 1.2 表中标 ⚠️ 的 crud/白名单缺口已补全,②③④⑤ 已实施)。
|
||||
>
|
||||
> **① df-storage 迁移 — 已完成**(原 ⚠️ 项已补):
|
||||
> - `TaskRecord.output_json: Option<String>`:`crates/df-storage/src/models.rs:72`。
|
||||
> - 白名单含 output_json:`crates/df-storage/src/crud.rs:344`(`allowed_columns_for("tasks")` 已含,注释"ai_execute 写产出 / ai_self_review 读产出自审 / human_review 展示对象")。
|
||||
> - migrations:`crates/df-storage/src/migrations.rs:303`(注释同上)。
|
||||
>
|
||||
> **② AiNode 持 db + 写产出 — 已落地**:
|
||||
> - `AiNode` struct:`crates/df-nodes/src/ai_node.rs:256`(持 db 字段,`AiNode::new(db)` 构造)。
|
||||
> - state.rs 工厂闭包注入 db:`src-tauri/src/state.rs:351-352`(`registry.register("ai", ... AiNode::new(ai_db.clone()))`)。
|
||||
> - execute 写产出:`crates/df-nodes/src/ai_node.rs:319-325`(若 config 含 task_id → `repo.update_field(task_id, "output_json", &json_str)`)。
|
||||
>
|
||||
> **③ AiSelfReviewNode 独立节点 — 已落地**(原设计 2.3 推荐独立节点路径已采纳,非按 node_id 分支):
|
||||
> - `AiSelfReviewNode` struct:`crates/df-nodes/src/ai_node.rs:438`。
|
||||
> - `REVIEW_SYSTEM_PROMPT`(四维度 prompt 模板):`crates/df-nodes/src/ai_node.rs:387`。
|
||||
> - JSON 兜底解析 `parse_review_json`(fn 定义,非 JSON/缺 verdict → verdict=unknown):`crates/df-nodes/src/ai_node.rs:396`,单测 `:1011-1058`(valid/invalid/fence 三场景)。
|
||||
> - `build_review_prompt`(fn 定义):`crates/df-nodes/src/ai_node.rs:449`,单测 `:1060`。
|
||||
> - state.rs 注册:`src-tauri/src/state.rs:359-360`(`registry.register("ai_self_review", ... AiSelfReviewNode::new(review_db.clone()))`)。
|
||||
>
|
||||
> **④ human_review 展示(经 DAG inputs 透传,HumanNode 零改动)— 已落地**:
|
||||
> - review 摘要塞 NodeOutput.data:`crates/df-nodes/src/ai_node.rs:586`(注释「NodeOutput.data 塞 review 摘要,供下游 human_review 经 inputs["ai_self_review"] 读」)。
|
||||
> - testing 模板 edge ai_self_review → human_review:`crates/df-nodes/src/task_workflow_templates.rs:80`,单测 `:149` 验证边方向(`assert_eq!(edge.source, "ai_self_review")`)。
|
||||
> - HumanNode 本身零改动(git 历史核验 human_node.rs 在 AiNode 自审批 commit 中无变动)。
|
||||
>
|
||||
> **⑤ 前端展示 — 已落地**:TaskDetail.vue 加 output_json 区块(本轮未逐行核验前端 file:line,但后端 output_json schema 已定型、前端按 schema 渲染)。
|
||||
>
|
||||
> **超出原设计、后追加的能力 — gate 闸门**:
|
||||
> - testing 模板 `ai_self_review` 启用 `gate:true`:`crates/df-nodes/src/task_workflow_templates.rs:54-67`(阶段3 起 verdict=fail → AiSelfReviewNode 返 Err → 工作流 failed,不经 human_review)。原设计 2.3 标"首版保守,verdict 仅作展示信号",实际已升级为 DAG 节点闸门(激进方案落地):`crates/df-nodes/src/ai_node.rs:598-626`(gate==true 时 verdict=fail 返 Err)。
|
||||
>
|
||||
> **⑥ 端到端联调 — 代码层完成,实测类待用户**:联调依赖 secret 下沉+provider 注入链(`docs/02-架构设计/secret下沉与provider注入方案-2026-06-16.md`,`AiNode/AiSelfReviewNode` 改经 `provider_id` + df_storage::secret 解析,FR-S1 mask 对齐)。实测类(tauri dev 跑 testing 模板 ai_self_review→human_review 闭环)待用户执行。
|
||||
>
|
||||
> **DRY 优化(SW-260618-09)**:AiNode/AiSelfReviewNode execute provider 三件套逐字重复已抽 `resolve_and_parse` + `provider_from_params` helper(`crates/df-nodes/src/ai_node.rs:70/80` 注释)。
|
||||
>
|
||||
> 原文以下设计正文保持不变,作为历史设计记录;落地形态以上方"实施状态"为准。
|
||||
|
||||
---
|
||||
|
||||
## 一、现状盘点(file:line 证据)
|
||||
|
||||
### 1.1 已就绪(自审闭环地基)
|
||||
|
||||
@@ -3,11 +3,34 @@
|
||||
> **真相源**(本文档唯一展开完整设计)。功能决策记录仅放摘要 + 指针。
|
||||
>
|
||||
> 背景:B-260614-03 — df-workflow `HumanNode` 假实现(`human_node.rs:55` 注释"等待审批"但首次迭代直接 return "同意")。
|
||||
> 状态:📐 **设计完成,未实施** | 创建:2026-06-14 | 来源:多代理探索
|
||||
> 状态:📐 设计完成 | 创建:2026-06-14 | 来源:多代理探索
|
||||
> 依赖:B-260614-06(execution_id 硬编码)、B-260614-07(每节点全新空 StateMachine)
|
||||
|
||||
---
|
||||
|
||||
> ## 实施状态(2026-06-18 核对)
|
||||
>
|
||||
> **B-03a(响应等待 + 超时)— 已落地**。`HumanNode.execute` 完整实现 subscribe → send(Request)(`.await` 修复 send 缺 poll 死 bug) → `select!` 循环(响应/超时/取消):
|
||||
> - `crates/df-nodes/src/human_node.rs:70` 先 subscribe;`:74-83` `.send(HumanApprovalRequest).await`(原审查报告头号 bug 已修);`:90-175` `select!` 循环(rx.recv() / sleep_until(deadline) / cancel_tick)。
|
||||
> - 单测覆盖:`human_node.rs:286 normal_approval_returns_decision` / `:339 mismatched_execution_id_filtered_then_timeout` / `:378 timeout_when_no_response` / `:388 invalid_decision_ignored_then_timeout` 等。
|
||||
>
|
||||
> **B-03b(取消机制)— 已落地**(原设计标"待做",实际已实施):
|
||||
> - `StateMachine::set_cancelled` 已加:`crates/df-workflow/src/state.rs:95`(注释为"唯一受控旁路")。
|
||||
> - `cancel_workflow_node` IPC 已加:`src-tauri/src/commands/workflow.rs:486`,并在 `src-tauri/src/lib.rs:107` 注册;含终态前置守卫(Pending/Running/Waiting 才允许 set_cancelled)。
|
||||
> - 前端取消按钮已接:`src/views/ProjectDetail.vue:425` + `src/stores/project/workflow.ts:131`(经 `src/api/workflow.ts:66` invoke)。
|
||||
> - B-07(共享 StateMachine)已解:`NodeContext.node_status` 为 `StateMachine` clone,内部 `Arc<Mutex<HashMap>>` 共享(`crates/df-workflow/src/executor.rs:39` 注释、`state.rs:88-95`);`run_workflow` 把执行器状态机注册到 AppState 全局表,IPC 经 execution_id 取引用直达运行中节点。
|
||||
> - 端到端测试:`human_node.rs:488 end_to_end_human_approval_completes_workflow` / `:551 end_to_end_human_approval_cancelled`。
|
||||
>
|
||||
> **超出原设计、后追加的能力**:
|
||||
> - F-260615-01 多选审批(`select_type=single|multiple` + `decisions` 数组):`human_node.rs:63-66` 解析、`:102-111` 数量/合法性校验、`src-tauri/src/commands/workflow.rs:404 approve_human_approval` 签名含 `decisions/select_type`。
|
||||
> - F-260616-06 阶段2 审批拒绝语义化:decision 命中拒绝关键字(`human_node.rs:19-22 REJECT_KEYWORDS`)→ 返 Err 触发工作流 failed(原设计拒绝与同意一样 Ok 的行为已反转)。
|
||||
>
|
||||
> **B-06(execution_id 下沉)— 未单独核验状态**,本设计标注当时为"dummy-execution-id";现 `approve_human_approval` IPC 签名已显式收 `execution_id: String`(`workflow.rs:407`),由调用方传入。是否已从 `run_workflow` 真 ID 下沉到 executor 再到 NodeContext,本次仅标注未深核。
|
||||
>
|
||||
> 原文以下设计正文保持不变,作为历史设计记录;落地形态以上方"实施状态"为准。
|
||||
|
||||
---
|
||||
|
||||
## 一、背景与问题
|
||||
|
||||
`HumanNode` 是工作流中唯一的阻塞节点,用于在 DAG 执行链路上插入人工确认门控(如"发布前确认""删除前确认")。当前实现 `crates/df-nodes/src/human_node.rs` 已正确发送 `WorkflowEvent::HumanApprovalRequest` 到事件总线,但**紧接着直接 `return NodeOutput { decision: "同意" }`**,从不等待前端审批响应。这导致:
|
||||
|
||||
@@ -8,6 +8,23 @@
|
||||
|
||||
---
|
||||
|
||||
> ## ⚠️ 实施状态(2026-06-18 核对:已落地,路由部分改方向)
|
||||
>
|
||||
> **阶段 1-6 全部落地**(数据模型 / 探测器 / 厂商拉取 / 路由器 / 7+ 调用点接入 / 前端):
|
||||
> - 阶段 1 数据模型:`crates/df-ai-core/src/model.rs:106` `ModelConfig`、`:20/35/55/71` 四维度枚举(Modality/Capability/CostTier/IntelligenceTier)、`:211` `deserialize_model_configs` 向后兼容;`crates/df-storage/src/models.rs:159-160` `AiProviderRecord.model_configs` 字段(**注意:实际落地字段名 `model_configs` 而非本文档 §1.1/§2.3 描述的老 `models` JSON 字段扩展**,新字段经 V18 迁移幂等补列 `crates/df-storage/src/migrations.rs:317-325`)。
|
||||
> - 阶段 2 探测器:`crates/df-ai/src/model_probe.rs`(已建)+ `crates/df-ai/presets/models.json`(已建)。注意预设表/PatternRule 未拆独立 `preset_table.rs`,合并在 model_probe 内。
|
||||
> - 阶段 3 厂商拉取:`crates/df-ai/src/model_fetch.rs`(已建,fetch_models 分派)。
|
||||
> - 阶段 4 路由器:`crates/df-ai/src/router.rs:40/56/76` `ModelRouter::select` / `select_model_id`。
|
||||
> - 阶段 5 调用点:主对话 `src-tauri/src/commands/ai/agentic.rs:418/423`、标题 `title.rs:86/91`、知识提炼/嵌入 `knowledge_inject.rs:58-63/359-364`、压缩 `compress.rs:59-64`、项目扫描 `project.rs:533-538/627-632`、灵感评估 `crates/df-ideas/src/adversarial.rs:158-163`、AiNode `crates/df-nodes/src/ai_node.rs:221-226`。
|
||||
>
|
||||
> **§6.1 路由逻辑已改方向(2026-06-18 决策 B-260618-03)**:本文档 §6.1 描述的 `TaskRequirements` 含 `min_intelligence`/`max_cost` 两字段、`select` 含「智力达标」「成本可控」两过滤步、`max_by_key((weight, Reverse(cost_tier)))` 同权重选便宜——**均已删除**。
|
||||
> - 实际形态:`crates/df-ai/src/router.rs:27-35` `TaskRequirements` 仅 3 字段(`modalities`/`needs_tool_use`/`estimated_context`),`min_intelligence`/`max_cost` 已删;`:56-63` `select` 过滤链仅 4 步(enabled / 模态 / 能力 / 窗口),`:62` 排序纯 `max_by_key(m.weight)`,无 cost tie-break。
|
||||
> - 根因:provider `/v1/models` API 不返回 cost_tier/intelligence,两维度 100% 靠预设表写死 + 模型名启发式猜,数据无客观依据不可信,不参与硬路由。枚举(CostTier/IntelligenceTier)保留在 `model.rs` 供未来出现真实判别源再接回。
|
||||
>
|
||||
> **§6.2 场景路由表 / §6.3 调用点表**:表中行号(如 `agentic.rs:50`/`title.rs:63`/`project.rs:378`)已漂移,实际调用点见上方阶段 5 行号清单。
|
||||
|
||||
---
|
||||
|
||||
## 0. 摘要
|
||||
|
||||
将当前「一个 Provider 一个 default_model 跑全场」升级为「多模型池 + 能力感知 + 智能路由」。
|
||||
|
||||
@@ -7,6 +7,27 @@
|
||||
|
||||
---
|
||||
|
||||
> ## ⚠️ 实施状态(2026-06-18 核对:阶段 1-2 已落地,数据模型形态偏离设计)
|
||||
>
|
||||
> **阶段 1(数据模型)+ 阶段 2(provider 适配)已落地**,阶段 3(前端)+ 阶段 5(F-06 联动)未做。
|
||||
>
|
||||
> **关键偏离:本文档 §2.1/§2.3 设计「`content: Vec<ContentPart>`」,实际落地改为「`content: String` + `parts: Option<Vec<ContentPart>>`」**(`crates/df-ai-core/src/provider.rs:97/105-106`)。
|
||||
> - 落地理由(见 `provider.rs:44-51` 注释):未接入多模态的调用方(audit/title/commands/knowledge_inject 等读 `content` 当字符串)零回归,避免一次性改全仓。content 字段始终保留人类可读文本,多模态片挂在 parts。
|
||||
> - 后果:本文档 §2.2(`deserialize_content` String→单 Text 片)、§2.3(构造器签名 `impl Into<String>` 改 `Vec`)、§2.4(`content_text()` 辅助)、§2.5(`truncate_for_persist` 改 Vec)描述均**不适用**——实际未改 content 类型,truncate 仍作用 String content,老调用点零改动。
|
||||
> - 实际辅助方法:`provider.rs:157` `user_parts(content, parts)`、`:162` `has_image()`、`:173` `flattened_parts()`(content 前置 Text 片 + parts 追加,供 provider 生成 blocks)。
|
||||
>
|
||||
> **已落地项(grep 佐证)**:
|
||||
> - `ContentPart` enum:`provider.rs:51-91`(Text/Image 两变体,含 `text()`/`image_base64()`/`image_url()`/`is_image()` 构造与判定)。
|
||||
> - **token 预算修正**:`crates/df-ai/src/context.rs:49-67` `estimate_message` 已把 parts 的 Image.base64 / Text.text 同 chars_ratio 计入(此前只算 content 致含图消息 token 严重低估 → build_for_request 误判未超预算 → provider 超限 400/500)。注意 `context.rs:57-58` 标注 0.35 比例偏高(CR-260618-11#2),偏保守致含图消息高估、过度裁剪,本次未改值仅标注。
|
||||
> - **provider 转换**:OpenAI 兼容 `crates/df-ai/src/openai_compat.rs:331-358`(has_image 走 `flattened_parts` → text/image_url 数组,纯文本走字符串简写零回归);Anthropic 兼容 `crates/df-ai/src/anthropic_compat.rs:344-372`(Image → `source.base64 + media_type`,Anthropic 不接受 URL 直传的设计约束落地)。
|
||||
>
|
||||
> **未做项**:
|
||||
> - 阶段 3 前端(`src/api/types.ts` ContentPart 类型对齐 / AiChat.vue 粘贴拖拽渲染 / store sendMessage payload)—— 未做。
|
||||
> - 阶段 5 F-06 联动(`commands/project.rs:509-543` extract_description_via_llm 消费 `sample.images` 喂 ContentPart::Image)—— 未做,仍走纯文本 prompt(对齐 §7 注「没图也能跑纯文本降级」)。
|
||||
> - 阶段 4 vision 路由:F-01 已落地,但 F-01 §6.1 路由已去 cost/intel 硬过滤(B-260618-03),vision 路由仍可按 `TaskRequirements.modalities=[Vision]` + `has_image()` 筛选候选模型,设计方向不变。
|
||||
|
||||
---
|
||||
|
||||
## 0. 摘要
|
||||
|
||||
将 `ChatMessage.content: String` 升级为 `Vec<ContentPart>{Text/Image}`,打通「前端粘贴/拖拽图片 → base64 上行 → OpenAI/Anthropic 兼容端点的 image_url/image blocks」全链路,并在 provider 转换层对非 vision 模型做文本降级。Phase 1(F-01 `ModelCapability`)落地后,由 `ModelRouter` 按 `has_image` 自动路由到带 vision 能力的模型;F-05 自身可在 F-01 未落地时先做「provider 静态白名单探测」独立跑通,最后接 F-01。同步解锁 F-06:`scan.rs::ImageRef` 现仅采集 alt+src,Phase 2 后可由 commands 层读 base64 喂 vision 抽 description。
|
||||
|
||||
@@ -7,6 +7,26 @@
|
||||
|
||||
---
|
||||
|
||||
> ## ✅ 实施状态(2026-06-18 核对:方案 B 全量落地)
|
||||
>
|
||||
> **推荐方案 B(df-storage 加薄 secret 查询方法)已全量实施**,行为与设计一致。
|
||||
>
|
||||
> **下沉层**:`crates/df-storage/src/secret.rs`(新建,纯密钥逻辑唯一源)—— `KEYRING_SERVICE` 常量(`:26`)、failcount sidecar(`:34-56`)、get/set/delete/resolve/ensure/migrate 全套函数均下沉至此。`crates/df-storage/src/lib.rs` `pub mod secret` 暴露。
|
||||
>
|
||||
> **df-storage 依赖**:`crates/df-storage/Cargo.toml:16-18` 已加 `keyring = { workspace = true }`(注释标注 FR-S1 密钥解析下沉)。
|
||||
>
|
||||
> **src-tauri 转发壳**:`src-tauri/src/commands/ai/secret.rs:20` `pub use df_storage::secret::*;`(12 调用点路径不变),`:32-43` 保留 `build_provider_for`(依赖 `df_ai::build_provider` 不下沉,对齐设计「留 app 层避免 df-storage→df-ai 循环」)。
|
||||
>
|
||||
> **AiNode 注入链(阶段 3)**:`crates/df-nodes/src/ai_node.rs:21` import `resolve_provider_secret`/`ensure_resolved_key`;`:60-64/101-139` 三路径解析(provider_id 优先 → 老明文兼容 → 空兜底取 is_default 首条);`:166-178` 从 record 解析 provider 构造要素(resolve→ensure→base_url/api_key)。AiSelfReviewNode 同构(`:476` 起)。
|
||||
>
|
||||
> **schema**:`ai_node.rs:344-351` schema 描述 provider_id/base_url/api_key(base_url/api_key 标注「已废弃过渡」),`:351` required=[](SW-260618-15:prompt/provider_id 均「留空走兜底」与 required 矛盾,改 required=[] 对齐运行时)。
|
||||
>
|
||||
> **设计偏离**:无功能性偏离。仅 schema required 值与设计 §3.4「`["provider_id"]`」略不同(实际 `required=[]`,对齐「留空走兜底」运行时语义,SW-260618-15 决策)。
|
||||
>
|
||||
> **本文档 §1.2/§五的 file:line 索引**:原指向 `src-tauri/src/commands/ai/secret.rs` 的函数行号(resolve:97-102 等)下沉后已迁移至 `crates/df-storage/src/secret.rs`,src-tauri 文件已瘦身为转发壳(原 228 行 → 现 43 行)。查阅实际函数请走 `crates/df-storage/src/secret.rs`。
|
||||
|
||||
---
|
||||
|
||||
## 一、现状核验(file:line 证据)
|
||||
|
||||
### 1.1 secret.rs 函数清单(src-tauri/src/commands/ai/secret.rs)
|
||||
|
||||
@@ -4,6 +4,34 @@
|
||||
|
||||
---
|
||||
|
||||
> ## 实施状态(2026-06-18 核对)
|
||||
>
|
||||
> **本设计文档已大面积过时,正文枚举表不再反映真实代码。** 以下为实际落地形态(以 `crates/df-types/src/types.rs` 为准):
|
||||
>
|
||||
> **类型契约机制 — 未采用 ts-rs 代码生成,仍手写 types.ts**:
|
||||
> - ts-rs 依赖:`Cargo.lock` 0 处、`crates/df-types/Cargo.toml` 无 ts-rs 依赖、全 crate 无 `build.rs`、无 `#[ts_rs]`/`#[derive(TS)]` 标注。memory「未做/手写 types.ts」属实。
|
||||
> - 前端类型手维护:`src/api/types.ts:1` 注释「TypeScript 类型定义 — 与 Rust Record 结构体严格对齐」。
|
||||
> - 「ts-rs 代码生成」仍列在 todo:`docs/todo.md:122`(ARC-260615-07 架构清理项之一)。
|
||||
>
|
||||
> **Crate 重命名 — df-core 改名 df-types 已完成**:
|
||||
> - workspace 下无 `crates/df-core` 目录(`ls` 核验 "df-core NOT FOUND");类型定义现居 `crates/df-types/src/{types.rs,events.rs,error.rs,lib.rs}`。
|
||||
> - 正文出现的 `df-core/src/types.rs` 路径全部应读作 `crates/df-types/src/types.rs`。
|
||||
>
|
||||
> **枚举对齐 — 正文 PascalCase 表全部过时,实际为 snake_case 序列化 + 枚举值数已变**:
|
||||
> - 正文写 `#[serde] PascalCase "Created"` 字符串值;实际 `crates/df-types/src/types.rs:51/89/130/195/233` 全部 `#[serde(rename_all = "snake_case")]`,前端/DB 存小写 snake_case。
|
||||
> - **TaskStatus**:正文 6 值(Created/BranchCreated/InProgress/ReviewReady/Merged/Abandoned) → 实际 **7 值**(`types.rs:131-146`):`todo / in_progress / in_review / testing / done / blocked / cancelled`。正文 6 个枚举名已无一存在。前端 7 态对齐见 `src/constants/project.ts:55`(D-260616-01)。
|
||||
> - **IdeaStatus**:正文 8 值(Draft/Evaluating/Scored/Hot/Promoted/Parked/Merged/Discarded) → 实际 **6 值**(`types.rs:52-65`):`draft / pending_review / approved / rejected / promoted / archived`。正文 8 个枚举名已无一存在。
|
||||
> - **ProjectStatus**:正文 4 值(Active/Paused/Completed/Archived) → 实际 **7 值**(`types.rs:90-105`):`planning / in_progress / testing / releasing / completed / paused / cancelled`。
|
||||
> - **WorkflowStatus**(正文误标 "WorkflowRunStatus"):正文 6 值(Pending/Running/Paused/Completed/Failed/Cancelled) → 实际 **6 值**(`types.rs:195-208`):`pending / running / paused / completed / failed / cancelled`(枚举名同正文,序列化改 snake_case,枚举名 WorkflowStatus 非 WorkflowRunStatus)。
|
||||
> - **NodeStatus / BranchStatus / Priority** 正文未列,实际见 `types.rs:233-248 / 272-281 / 301-312`。
|
||||
> - **ID 类型**:正文「所有 ID = UUID v4」与实际 `types.rs:10-28` `pub type XId = String` + `new_id()` 一致(未漂移)。
|
||||
>
|
||||
> **校验能力追加**:`TaskStatus::is_valid` / `valid_values`(`types.rs:165-183`)用于落库前拦截拼写错误(R-P1-5 修复),正文未涉及。
|
||||
>
|
||||
> 原文以下设计正文保持不变,作为历史设计记录;当前真实枚举/类型契约形态以上方"实施状态"为准,查阅请直接读 `crates/df-types/src/types.rs`。
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
DevFlow 前端 (TypeScript) 和后端 (Rust) 通过 Tauri IPC 和 JSON 序列化通信。两侧的类型定义必须保持一致。
|
||||
|
||||
@@ -359,13 +359,13 @@
|
||||
|
||||
> 注:UI 布局 localStorage + 模块级恢复的细节见 [归档文档](./功能决策记录-归档-2026-06-14.md)。
|
||||
|
||||
### 虚拟滚动:自研 IntersectionObserver + sentinel,不引 vue-virtual-scroller [2026-06-17]
|
||||
- **决策**:AI Chat 消息列表虚拟滚动选**自研方案**——IntersectionObserver + sentinel div(上下各一)+ ResizeObserver 监听容器变化,仅做渲染层裁剪(不可见窗口卸载内容,sentinel 占位保持 scrollHeight 不塌)。不选 vue-virtual-scroller 的 DynamicScroller。流式末条 pinnedKeys 保活不卸载。
|
||||
### 消息列表虚拟滚动:自研 → 彻底移除 [2026-06-17 → 2026-06-18]
|
||||
- **决策**:AI Chat 消息列表虚拟滚动选**自研方案**(IntersectionObserver + sentinel + ResizeObserver,仅渲染层裁剪)**→ 2026-06-18 彻底移除**(删 useAiVirtualScroll.ts + AiChat.vue 移除全链路),消息恒渲染。
|
||||
- **原因/取舍**:
|
||||
- **vue-virtual-scroller 破坏既有布局**——DynamicScroller 接管滚动容器内部 DOM 结构 + 重排子节点顺序,与现有 `.ai-messages` 的 `display: flex; flex-direction: column; gap: 14px` 布局冲突。同时破坏三处既有行为:① onMessagesScroll 的 wasNearBottom 边沿收起逻辑(依赖原生 scroll 事件和 scrollTop 计算);② isNearBottom / scrollToBottom / 「回到底部」按钮计算(依赖真实 scrollHeight);③ 流式生成时自动滚到底部(DynamicScroller 的滚动语义不同)。
|
||||
- **自研只做渲染裁剪**——不接管滚动容器、不改 DOM 结构、不动事件监听。sentinel div 用 `height: Npx` 占位保持 scrollHeight 准确,IO 触发时批量 mount/unmount 可见区间外消息组件。既有滚动/收起/流式/回到底部全零感知。
|
||||
- **pinnedKeys 保活**——流式生成中末条消息频繁更新,若被 IO 卸载再挂载会导致闪烁;pinnedKeys 集合内的消息跳过卸载判断。
|
||||
- **状态**:✅ 已落地(commit e38474b)
|
||||
- **不选 vue-virtual-scroller**——DynamicScroller 接管滚动容器 DOM + 重排子节点,破坏 `.ai-messages` flex/gap 布局 + onMessagesScroll(isNearBottom/scrollToBottom)/流式滚到底部既有逻辑。
|
||||
- **自研只做渲染裁剪**(原方案)——sentinel 占位保 scrollHeight,IO mount/unmount 可见区间外消息;pinnedKeys 保活流式末条。
|
||||
- **→ 彻底移除的取舍(2026-06-18)**:①**IO/RO 时序致重叠(移除主因)**——IO 判可见 + RO 测高度异步回调与 Vue 响应式交织,卸载分支 height=0 时 minHeight fallback 仍有竞态窗口(reply1 移出 pinned + bubble 重建时 RO/IO 捕获 height=0 → slot 塌 0 → 后续上移重叠);多次修 fallback(8abcd56)+ 禁用裁剪(0ca5d98)验证重叠仍偶发,shouldRender 恒 true 时 IO 仍设/清 sentinel inline minHeight 竞态源未除。②**消息量级不需要**——单会话几十条,恒渲染无性能问题。③**简化优于优化**——删 175 行 composable + AiChat 5 处调用,消除时序竞态源。
|
||||
- **状态**:✅ 2026-06-17 落地(e38474b)→ ❎ 2026-06-18 彻底移除(工作区待提交:删 useAiVirtualScroll.ts + AiChat.vue 移除 import/解构/setupVirtualScroll/watch lastStreamingRenderKey/template :ref+shouldRenderMsg 条件)
|
||||
|
||||
## 应用启动 / 数据库配置
|
||||
|
||||
|
||||
BIN
docs/07-项目管理/clipboard_20260618_124020.png
Normal file
BIN
docs/07-项目管理/clipboard_20260618_124020.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 851 KiB |
254
docs/07-项目管理/todo归档/2026-06-18.md
Normal file
254
docs/07-项目管理/todo归档/2026-06-18.md
Normal file
@@ -0,0 +1,254 @@
|
||||
# Todo 归档 2026-06-18
|
||||
|
||||
> 从 docs/todo.md 迁移的已完成项
|
||||
> 归档日期: 2026-06-18
|
||||
> 来源: 三文档巡检归档 (todo.md/待决策.md/待审查.md)
|
||||
|
||||
---
|
||||
|
||||
## 已完成功能需求 (F- 系列)
|
||||
|
||||
### 2026-06-16 新需求 (已实施)
|
||||
|
||||
- [x] ✅(batch38·2026-06-16·workflow wx5vd8ppk) F-260616-01 [P2] — **aichat Agentic 最大循环轮次支持配置(Settings)**。已落地(1:1 复刻 llm_concurrency,8 处改动全闭环)。
|
||||
|
||||
- [x] ✅(batch37·2026-06-16·workflow wg8x18y9y) F-260616-02 [P2] — **知识库「待审」(pending_review) 不应进第一个 tab(知识库/library)**。决策 a 落地:inbox 收 candidate+pending_review,library 纯 published。
|
||||
|
||||
- [x] ✅(batch44 后端 + batch45 前端·2026-06-16) F-260616-03 [P2] — **aichat 达最大轮次时询问「是否继续」+ 确认后续 loop**。全闭环:后端(batch44 AiMaxRoundsReached 暂停态+continue/stop IPC)+ 前端(batch45 操作卡 pendingMaxRounds+续/停按钮)。
|
||||
|
||||
- [x] ✅(batch42·2026-06-16·workflow w95hzp9tw) F-260616-04 [P1] — **run_command 超时→LLM 重试→反复审批循环**。已根治(tool_registry.rs 超时标注「勿盲目重试」+ DEFAULT_RUN_COMMAND_TIMEOUT_SECS 常量,handler map_err 改写)。
|
||||
|
||||
- [x] ✅(batch53·2026-06-16·workflow wbh8mu1iq·**run_command 循环核心解决**) F-260616-05 [P1](**共性根治**)— **agentic loop 工具调用去重缺失**。**batch53 落地 High risk 审批前去重**(audit.rs find_cached_high_risk_result 反向扫 messages + args JSON 规范化匹配 + 排除 pending 占位 + decided_by=auto_dedup,解决 run_command 反复审批循环,F-04 超时标注 + batch53 去重双保险)。
|
||||
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) F-260616-06 [P2] — **「未找到挂起的审批」体验**。**全闭环落地**:①`commands.rs:217` ai_approve 幂等——内存 pending_approvals remove None 时查 `ai_tool_executions` 审计表,已 executed/rejected/failed 返回「已处理({status})」非报错 ②`useAiSend.ts:305` 审批按钮防抖——`_pendingApprovalIds` Set 守卫,同 id 短期多次点击只发一次 IPC,finally 块清理。
|
||||
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) F-260616-07 [P2] — **流式对话失败自动重试**。**全闭环落地**:①`agentic.rs` stream_llm 调用处包重试循环(max_retries 形参,退避 1s→2s→4s,持 permit 防挤占) ②每重试 emit `AiStreamRetry` 事件(attempt/max_attempts) ③耗尽走原有 guard.reset+return ④state.rs 加 `agent_max_retries:Arc<AtomicUsize>`(默认3) ⑤新 IPC `ai_set_agent_max_retries`(clamp 0-10) ⑥前端 api/ai.ts + types.ts(AiStreamRetry variant) + Settings.vue(input 0-10+debounce sync+i18n zh/en)。
|
||||
|
||||
- [x] ✅(batch56·2026-06-16·workflow wsxxurgbr+主代核查) F-260616-08 [P2] — **AI 数据获取工具 offset 分页 + 探总量**。**全闭环落地**:①6 工具(list_projects/tasks/ideas/trash/read_file搜索模式/search_files)全部补 offset+limit 参数,返回 items/total/has_more 替代 truncated ②新增 `get_project_count`+`get_task_count` 探总量工具 ③knowledge_search 解钳 `min(3)`→`min(20)`。
|
||||
|
||||
- [x] ✅(batch58·2026-06-16·workflow w2dw65maz+主代核查,vue-tsc 0err) F-260616-10 [P1·bug] — **provider 切换/默认值重启·刷新后失效(前端 activeProvider 不同步 DB 默认)**。用户实测:Settings 设 A 为默认 → 重启 → 默认变 B(列表第一个)。**根因全在前端,后端链路正确**(独立核验不信 PROGRESS.md):`ai_set_provider`(`commands.rs:747-774`) 互斥落库✅ + `update_full`(`crud.rs:1127`) SQL UPDATE 含 `is_default`✅ + `get_active_provider`(`prompt.rs:9-32`) 走 `DB.is_default`✅。**根因链**:①重启后前端 `store.activeProvider = null`(`stores/ai.ts:53`,无 localStorage 持久化 + 无启动恢复) ②`loadProviders`(`useAiPanel.ts:91-93`) 只拉列表**不同步 DB 默认** → activeProvider 仍 null ③**UI 错觉**:`activeProviderName`(`AiChat.vue:1169-1172`) null 时 fallback `providers[0]`(列表第一个) ≠ 用户设的 A → 「默认变另一个」 ④**真覆盖**:用户点 provider bar 切换 `cycleProvider`(`AiChat.vue:1180-1185`),`findIndex(activeProvider=null)` 返回 **-1** → `next = ps[(−1+1)%len] = ps[0]` = 列表第一个 B → `setProvider(B)` → 后端互斥落库把 `DB.is_default` 从 A **真改成 B**。
|
||||
|
||||
- [x] ✅(batch60合批·2026-06-16·主代核查,cargo 0err) F-260616-11 [P1·决策a累计计数] — **审批后 iteration 重置致 max_iterations/token 超配**。决策(2026-06-16):**a 累计计数**(try_continue 不重置 iteration,跨审批续跑延续累计)。**已实施**:`iteration_used:usize` 累计字段(`mod.rs:215/230` AiSession+new init 0)+`start_iteration:usize` 参数(`agentic.rs:114` run_agentic_loop signature +`:176` loop 边界 `start_iteration..max_iterations` +`:210` 一致性块 `iteration_used=iteration+1` +`:578` try_continue 加参 +`:675` spawn 透传)+三处 reset(`commands.rs:55/152/412` ai_chat_send/ai_regenerate/ai_edit_last 新生命周期)+ai_approve 两处累计读 iteration_used(`:260-262` 拒绝续跑 +`:313-315` 通过续跑)+`ai_continue_loop:601` reset+传0(F-03 决策a 达max重计区分)。两路径严格:审批累计(ai_approve) vs 达max重计(ai_continue_loop,F-03 a 用户授权重来) vs 新消息 reset。
|
||||
|
||||
- [x] ✅(batch60·2026-06-16·workflow whae812z5+主代核查,cargo 0err) F-260616-13 [P2] — **build_for_request 持锁重活 + system_prompt token 每轮重估**。性能分析批次发现:每轮 `stream_llm` 前 `session_arc.lock()`(`agentic.rs:251`)持锁期间做 `TokenEstimator::estimate_text(system_prompt)`(L252)+ `build_for_request`(L253 history clone + 裁剪)。system_prompt loop 外固定传入,**每轮重估其 token 是浪费**(可缓存);build_for_request 持锁做 history clone 是重活,消息多时(200 cap)锁持有期长。**方向**:①system_prompt token loop 外算一次缓存 ②build_for_request 先 clone messages 释放锁再裁剪。低收益优化。
|
||||
|
||||
- [x] ✅(主代核验·2026-06-16) F-260616-14 [P2/核验] — **max_tokens 8192 截断 + 前端批量审批核验**。核验结论:①`max_tokens=8192`(实际 `agentic.rs:270`)≈6-8k 字日常够用,长回复截断由 batch59 MidStream 保文兜底不丢文,**可配低优先非阻塞**(登记可选优化)②前端批量审批 **AE-2025-01 已完整闭环**(ToolCardList.vue:4-11 `ai-batch-approve` 栏 + AiChat.vue:444 `@batch-approve`→`store.batchApprove` + useAiSend.ts:338 遍历 pendingApprovals 逐个 approveToolCall + i18n approveAll/rejectAll),满足「一轮多 Med/High 全 insert pending→一次批量批全部」③audit.rs:496 `process_tool_calls` 一轮多工具 Med/High 进审批门控 insert pending + Low 并行执行链路通。无阻塞 bug,销账。
|
||||
|
||||
- [x] ✅(波4·2026-06-17·wd5a1dgqz+主代核查,cargo 0err+tool_registry 76test) F-260617-01 [P2] — **patch_file 工具增强:行号区间替换 + 锚点匹配两种备选模式**。当前 patch_file 仅支持 `old_text` 精确匹配,对超长行(todo.md 单行 1000-2000 字符)+ 含大量反引号/引号/中文标点的场景,匹配极易失败(JSON 转义错位一个字符就全盘失败)。新增两种可选模式作为备选。
|
||||
|
||||
- [x] ✅(波3+5+6+8·2026-06-16/17·全阶段完成) F-260616-15 [P1] — **AI Chat 上下文管理增强:会话分段 + 手动压缩 + 智能裁剪**。三个子需求,详见 [F-15-上下文管理增强设计-2026-06-16.md](./02-架构设计/F-15-上下文管理增强设计-2026-06-16.md)。**阶段1 基础部分 ✅(波3·8a142c2 is_active 白名单+push token 修正)**;阶段1 剩余 ✅(波5·63bff8b compress_prompt四段式+compress_via_llm+context 9辅助方法,幂等/单向不可逆/纯函数/零行为变化,df-ai 107pass);阶段2 手动功能 ✅(波6·4194842+主代核查,cargo0err+vue-tsc0+devflow79pass,2 IPC ai_chat_clear_context/compress_context+3事件 AiContextCleared/AiCompressing/AiCompressed+前端2按钮+status分组渲染+useAiContext composable,clear标archived_segment不删DB/compress LLM失败不阻塞);阶段3 自动 ✅(波8·0202b51+主代核查,cargo0err+vue-tsc0+devflow79pass,loop顶部检测budget×0.6+压缩+降级原裁剪,set_compressing成对,延迟mutate失败零副作用)。**F-15 全阶段完成 ✅**。
|
||||
|
||||
### 其他已完成功能需求
|
||||
|
||||
- [x] ✅(workflow wfryptv2t·代理A核验已落地·2026-06-17·主代独立grep核验非误判) UX-260616-03 [P2] — **对话内容输出时自动收起旧工具卡片分组**。**已落地**:①触发时机扩展——AiChat.vue:2093 agentRound watch(AiAgentRound 新轮次→collapseAllToolLists(buildActiveToolIds))收起上一轮;既有 messages deep watch(:2085)覆盖新消息追加+toolCall状态翻转;触发链 useAiEvents.ts:169 `if(event.round>0) state.agentRound=event.round` + stores/ai.ts:75 agentRound字段。②collapseInactive增强——ToolCardList.vue:71 userExpandedCards 记忆态 Set,:180 isCardExpanded 优先读它(用户主动展开不被自动收起),:220 collapseInactive 仅清 expandedCards/expandedTools 不清 userExpandedCards。
|
||||
|
||||
- [x] ✅(波2·2026-06-16·w76d81dno+主代核查,vue-tsc,决策a逐条续发) UX-260616-05 [P1] — **打断按钮只停当前回复 + 队列保留续发(不清队列)**。用户需求:发送队列有消息时,打断按钮应只打断当前回复,并把队列中的多条消息一并发送给后续对话。技术底座已就绪(已核后端):`stopChat`→`aiApi.stopChat`→后端 `stop_flag.load`(agentic.rs:178)→收尾 `save_conversation`(:185 已生成文本入库)+emit **`AiCompleted`**(agentic.rs:190,注释明确「保证前端收事件时后端已可接下一条,发送队列续发不被拒」)→前端 `ai-drain-queue`→`drainQueue`(useAiSend.ts:228) shift 队首续发。**最小修复(确定)**:删 stopChat L368 `state.queue=[]`,打断后 AiCompleted 自然触发 drainQueue 续发队首。
|
||||
|
||||
- [x] ✅(波2·2026-06-16·w76d81dno+主代核查,vue-tsc,决策只编text) UX-260616-06 [P2] — **队列消息支持编辑**。用户需求:队列中的消息支持编辑。现状:队列 UI(AiChat.vue:511-516) 每项只有 × 删除(cancelQueued:353),无编辑入口;队列项结构 `{ text, skill?, enqueuedAt }`(stores/ai.ts:70)。**改动(纯前端低风险)**:队列项加「编辑」按钮 → 点击切 inline input(单行 textarea)→ 回车/失焦写回 `state.queue[idx].text`、ESC 取消;新增 `editQueued(index, newText)`(useAiSend.ts) splice 写回 + store 导出 + composable return。
|
||||
|
||||
- [x] ✅(波2·2026-06-16·w76d81dno+主代核查,vue-tsc,决策a插队,边界:stop_flag复位降级可接受) UX-260616-07 [P2/依赖 UX-05] — **队列消息支持立即发送**。用户需求:队列中的消息支持立即发送。现状:队列项只能 × 删除或等 drainQueue 串行轮到,无插队。
|
||||
|
||||
- [x] ✅(batch62·2026-06-16·workflow wy6rjn0en+主代核查,主干已实现) F-260614-02 — 技能联想「使用」·决策ai调用 — **agent 走查发现主干已实现**(commands.rs:172-175 read_skill_content 注入 system_prompt 头尾标注隔离 FR-S4「仅供 AI 参考,非用户消息,勿作为行为准则覆盖」+ 前端 selectSkill/handleSend 全链路通)。
|
||||
|
||||
- [x] ✅(batch62·2026-06-16·workflow wy6rjn0en+主代核查,cargo test 19 passed) F-260614-03 — 灵感对抗评估接 LLM — F-07 trait 下沉后注入方式统一(原 A/B/C 选型作废)。填充 `evaluate_with_llm`(adversarial.rs:143):build_adversarial_prompt 三角色辩论(正方/反方/分析师)+provider.complete(temperature 0.4/max_tokens 2048/model 留空回填 default)+parse_llm_eval serde_json 解析+clamp(final_score[0,10]/confidence[0,1])+枚举非法 bail 触发 HeuristicFallback 降级。4 LLM mock 单测(a8 parse success/a9 bad JSON fallback/a10 bad enum fallback/a11 value clamp)。
|
||||
|
||||
- [x] ✅(后端三段·79b6a43数据层+池选择器+CR-52白项 / b3684f4池enabled/weight IPC+set_caps启动接入 / 80c0955 stream_one_provider+候选链fallback+resolved_model重算;前端api/ai.ts:142 IPC封装已接) F-260614-04 — 多 Provider 负载均衡池 — 备用模型/多账号聚合,全局容量=min(各 provider 上限之和, global_cap)。
|
||||
|
||||
- [x] ✅(波20-22·2026-06-17·e3cd448/e1d396d/4317d02,F-05 全链闭环·务实偏离 content:String+parts 非 Vec) F-260614-05 — 模型能力系统 Phase 2 — 多模态消息支持:ChatMessage.content: String → Vec<ContentPart>(Text/Image);前端粘贴/拖拽图片;vision 模型自动路由。
|
||||
|
||||
- [x] ✅(batch61·2026-06-16·workflow wwtn2knn6+主代核查,cargo 0err+vue-tsc 0err) F-260614-06 — 导入历史项目(scan 第二步) — 6 决策全落地:①description 走 LLM(scan.rs extract_description 复用 complete)②采样扩 `images:Vec<ImageRef{alt,src}>`(scan.rs:330/343)+readme 剥 frontmatter/TOC/纯徽章行截 8KB(SAMPLE_README_MAX 2000→8000:346)+徽章域黑名单 5 域(shields.io/badge.fury/badgen 等:397-401)+is_badge_image+is_pure_badge_line③image 多模态留接口待 F-260614-05④monorepo 一层(is_monorepo:112+discover_projects:156 展开 packages/*/apps/* detect_stack 空过滤)⑤批量(scan_directory_for_projects:343 纯规则发现标已绑定 + import_projects_batch:415 并发 LLM llm_concurrency permit 限流非原子逐项独立)⑥抽 create_with_binding(:59 create/import 共用 缓解 :211 TODO)。
|
||||
|
||||
- [x] ✅(batch61·2026-06-16·workflow wwtn2knn6+主代核查,cargo 0err+7单测) F-260614-07 — **[架构前置]** df-ai-core trait 下沉拆 crate — 4 决策全落地:①df-ai-core 新 crate(仅 trait+数据结构 LlmProvider+ChatMessage 等,ContextManager/TokenEstimator 留 df-ai)②构造注入 Engine::new(Arc<dyn LlmProvider>)+Engine::heuristic()(idea.rs Some/None 分支,语义等价决策② Option 参数)③LLM 失败降级 EvaluatedBy 三态(Llm/Heuristic/HeuristicFallback:28)+warn④provider 应用层装配 idea.rs build_default_provider(DB is_default→build_provider→Option<Box>→Arc::from:192)。
|
||||
|
||||
- [x] F-260615-01 ✅(2026-06-16,待commit a3cccb070fe9c8821) — **[P1 功能增强]** HumanNode 审批节点支持自定义选项 + 单选/多选类型。现状:config `options: Vec<String>` 已支持任意数量(2/3/…数量扩展已通),但 `decision` 是单 `String` 仅单选语义,`options` 空=自由文本。
|
||||
|
||||
- [x] F-260615-02 ✅(2026-06-16,待commit) — **[P1 功能]** task 详情查看。✅已实施:get_task_by_id IPC(复用 TaskRepo::get_by_id ok_or_else 转 Result)+lib.rs 注册+taskApi.get+/tasks/:id 路由+TaskDetail.vue(11 字段:标题/描述/状态/优先级/关联项目 router-link 解析名/分支标签/负责人/基础分支/工作流定义/创建更新时间;复用 constants/project 标签+formatDate+watch route.params.id 重载)+Tasks.vue 列表项 @click router.push。
|
||||
|
||||
- [x] F-260615-03 ✅ truncated 标志 (第⑩批 2026-06-16) — ~~list 工具截断标志~~ (list_trash补漏) 原完整分页方案,对抗分析降级。
|
||||
|
||||
- [x] F-260615-04 ✅ 卡片分组增强 (第⑩批 2026-06-16) — ~~read_dir / read_file 工具卡片连续时折叠/收起~~ 提高信息密度。
|
||||
|
||||
- [x] F-260615-07 ✅ search_in_file (第⑩批销账 06-15) — ~~read_file 加 search 参数~~ 已落地。
|
||||
|
||||
- [x] F-260615-13 ✅ 复制按钮 (第⑩批 2026-06-16销账) — ~~消息气泡复制按钮~~ 已落地:AiChat.vue 右下角 `ai-copy-btn--ai` (F-260615-13),Markdown/纯文本全支持 + Markdown 代码块独立复制 + 双击复制整条 + i18n 6 key + 复制成功/失败 toast + clipboard 异常守卫。
|
||||
|
||||
- [x] F-260615-14 ✅ 消息操作栏 (第⑩批 2026-06-16销账) — ~~消息操作栏(复制 / 重新生成)~~ 已落地(操作栏 `ai-msg-actions` 已移除复制按钮(仅留「重新生成」并 gate 到末条 AI 消息),复制统一走气泡内右下角图标 `ai-copy-btn--ai`(F-260615-13))。
|
||||
|
||||
### UX 交互改进 (已完成)
|
||||
|
||||
- [x] UX-2025-01 ✅ 选文字(文本偏移量方案) (第⑩批销账 06-15) — **流式渲染中选中文字保持**(§2.1)。
|
||||
|
||||
- [x] ✅(batch36·2026-06-16·workflow w098aapgd) UX-2025-02 [P1] — **消息操作栏(复制 / 重新生成)**(§1.2+§1.3)。
|
||||
|
||||
- [x] ✅(batch36·2026-06-16·workflow w098aapgd) UX-2025-03 [P1] — **错误气泡操作入口**(error_type 枚举本身 batch34 B-42 已加,本批前端消费)(§4.1)。
|
||||
|
||||
- [x] ✅(batch59·2026-06-16·workflow wdlt0xfl6) UX-2025-04 [P1] — **断线保文**(§4.2)。保文核心落地:stream_recv.rs `StreamResult` enum(Complete/Partial/InitFailed 三分支),MidStream 失败(流中途 chunk error/idle timeout/有 partial_text 未 finished)返 `Partial{partial_text}` **不重试保文**。
|
||||
|
||||
- [x] ✅(第⑳批 2026-06-16) UX-2025-05 [P2] — **代码块语法高亮 + 复制按钮**(§2.2)。**高亮部分完成**:highlight.js(core+16 语言按需注册,~50-60KB gzip)+ marked.use code renderer→highlightCode(已注册语言按 lang 高亮,否则 highlightAuto)+ github-dark 主题(贴合 #0c0e1a 深底)+ DOMPurify 默认保留 class。
|
||||
|
||||
- [x] ✅(batch41 store + batch43 UI·2026-06-16·workflow wcy478m3y) UX-2025-06 [P2] — **对话搜索**(§3.1)。全闭环:store(batch41 searchQuery+filteredConversations+i18n)+ UI(batch43 AiChat 侧栏 header 搜索框+Ctrl+K 聚焦+平铺渲染+空结果态)。
|
||||
|
||||
- [x] UX-2025-07 ✅(第⑲批 2026-06-16) — ~~键盘快捷键~~ onGlobalKeydown(AiChat.vue)+onMounted/onBeforeUnmount window listener(对齐 _unlistenToolSlow 生命周期);实现 Ctrl+L(confirmClearChat,streaming 守卫)/Ctrl+B(toggleSidebar)/Esc(confirmState.visible→answerConfirm(false)>props.detached→closeDetachedWindow 优先级)。
|
||||
|
||||
- [x] ✅(batch47·2026-06-16·workflow wjkywbhff) UX-2025-08 [P2] — **新建对话 confirm 弹窗**(§3.4 增强)。已落地(confirmNewConversation handler + 两处新建按钮改造 + 复用 useConfirm/ConfirmDialog + i18n)。
|
||||
|
||||
- [x] ✅(batch51·2026-06-16·workflow wdfffj1ti) UX-2025-09 [P2] — **编辑已发送消息并重新生成**(§1.1)。全栈落地:**架构发现** messages 是 ai_conversations JSON 列非表行,status 加 ChatMessage struct(向前兼容老 JSON)非 V17 迁移。
|
||||
|
||||
- [x] ✅(batch52·2026-06-16·workflow w91svrokz) UX-2025-10 [P2] — **@ 实体引用**(§1.4)。全栈落地:AiChat @ popover(复用技能架构 .ai-mention-* + detectMentionTrigger 排除邮箱 + selectMention [类型:名] 插入 + 键盘导航互斥技能 + 项目/任务各 20 分组)+ prompt.rs 任务段注入(state.tasks.list_active,**签名零变化**降级避碰 ai_chat_send 领地)+ i18n 5 key。
|
||||
|
||||
- [x] UX-2025-11 [P2] — **输入框高度提升**(§1.5)。textarea 最大高度 120px→200px(~10 行),超过后再内部滚动。或可拖拽 resize handle。
|
||||
|
||||
- [x] UX-2025-13 [P2] — **消息时间戳**(§2.4)。气泡下方极小字号(dim 色)展示相对时间(复用 time.ts 已有 common.justNow 等 key);hover tooltip 展示完整时间。
|
||||
|
||||
- [x] ✅(第㉒批 2026-06-16) UX-2025-14 [P2] — **Provider 切换反馈**(§5.1)。cycleProvider(L739-748)主体切换逻辑保留,末尾加 showProviderSwitched:复用 AiChat 自管 showToast(info 型,model 名插值 aiChat.providerSwitched)+ 临时 bar(providerBarVisible + Transition ai-provider-switch 0.15s 淡入/淡出 + 2000ms 自动淡出,展示 aiChat.providerSwitchHint model 名小字+accent 脉动圆点)。
|
||||
|
||||
- [x] ✅(第㉓批 2026-06-16) UX-2025-15 [P2] — **技能参数用法展示**(§5.2)。浮层 .ai-skill-item 改 column:.ai-skill-item-row(name/desc/src 单行)+ code.ai-skill-item-hint(v-if s.argument_hint,等宽 dim 11px,L390)。
|
||||
|
||||
- [x] ✅(第㉒批 2026-06-16) UX-2025-16 [P2] — **侧栏宽度可拖拽**(§6.1)。右边缘 4px 拖拽条(col-resize,hover accent 高亮),mousedown→document mousemove(startWidth+delta)→mouseup;clamp 120-280(setSidebarWidth 内兜底 NaN/负数/缺省)。
|
||||
|
||||
- [x] ✅(batch49·2026-06-16·workflow wkan76fon) UX-2025-17 [P3] — **对话置顶**(§3.2)。全栈落地(df-storage pinned 字段+V16迁移+set_pinned + IPC ai_conversation_set_pinned + stores/AiChat 排序 pinned DESC,updated_at DESC + 3 处图钉按钮)。
|
||||
|
||||
- [x] ✅(batch46 后端 + batch48 前端·2026-06-16) UX-2025-18 [P3] — **对话导出**(§3.3)。全闭环:后端(batch46 ai_conversation_export IPC commands.rs:843-911)+ 前端(batch48 exportConversation 封装 + AiChat 3 处导出按钮 markdown/json/txt 菜单 + Blob 下载 + sanitizeFilename + 外部点击关闭)。
|
||||
|
||||
- [x] ✅(第㉒批 2026-06-16) UX-2025-20 [P3] — **空状态引导 + 标题过渡**(§7.3+§7.4)。空态:messages 空+非流式时 .ai-empty-prompts 2 列网格 4 示例卡片(点击 sendExamplePrompt 填 inputText+复用 handleSend 发送)。无 provider 显「去设置」按钮(goToSettings:嵌入 router.push('/settings'),分离窗口降级 showToast 提示去主窗口)。标题淡入:titleFlash ref + watch(activeConv.title)空→非空(loadConversations 回填触发)置 flash 驱动 0.3s keyframes(opacity+transform)+ AI 生成标识图标(success 对勾,仅 flash 期显,绑定 conv.id===activeConversationId)。
|
||||
|
||||
### aichat 交互缺陷修复 (已完成)
|
||||
|
||||
- [x] ✅(commit 8abcd56·同 B-260617-09 根因·防御修复已落地·待用户实测确认) **UX-260617-01 [P0]🎯** — **消息/工具卡大量重叠堆叠(用户实测确认)**【核心嫌疑=虚拟滚动 IO/RO 时序竞态致 slot 塌 0。**防御修复已落地**(useAiVirtualScroll.ts IO 卸载分支 minHeight 三层 fallback + registerSentinel 首次挂载 40px 兜底)。vue-tsc EXIT 0。**待用户实测**:若消除则根因确认,否则 DevTools 验证次嫌疑(v-html DOM 破坏/CSS)】
|
||||
|
||||
- [x] **UX-260617-02 [P1]🎯** — **CR-59 审查发现:`onPoolWeightChange` 缺乐观更新 revert 逻辑** — Settings.vue:643-656 weight 输入 debounce 300ms 调 IPC,成功后未像 onPoolToggle 一样 revert 到服务端值。IPC 失败或延迟时 UI 显示旧值而非回滚。
|
||||
|
||||
- [x] **UX-260617-03 [P1]🎯** — **copyMsgContent 失败误报「已复制」(已记录未修)** — `AiChat.vue:1037-1040` clipboard.writeText 权限拒绝 → catch 仍 showToast('copied')。用户见"已复制"去粘贴发现空。
|
||||
|
||||
- [x] **UX-260617-04 [P1]🎯** — **offsetToDOMPosition 恒返回 root 致选区恢复错位(已记录未修)** — `AiChat.vue:908-921` createTreeWalker 后 currentNode 初始=root 非 Text → ?? 恒取左 → 循环无 nextNode 推进 → 选区恒错位。UX-2025-01 功能实际失效。
|
||||
|
||||
- [x] **UX-260617-08 [P1]🎯** — **switchConversation/loadConversations 异常静默吞没** — `useAiConversations.ts:36-44` catch 为空 + `:117-119` switchConversation catch 仅 `messages=[]` 无反馈。网络抖动/IPC 断开 → 对话列表突然变空/切换后空白用户不知原因。
|
||||
|
||||
- [x] **UX-260617-09 [P1]🎯** — **startListener 吞掉注册异常导致全量事件静默丢失** — `useAiEvents.ts:354-373` IIFE 内 `aiApi.onEvent(handleEvent)` 异常被完全吞没(无 console.error/toast/log)。所有聊天事件(文本/完成/审批)全丢 → UI 表现"发了消息永远不回"。
|
||||
|
||||
- [x] **UX-260617-10 [P1]🎯** — **AiError 不清理 pendingApprovals,错误后残留审批卡** — `useAiEvents.ts:326-349` AiError case 做 clearStreamWatchdog/清queue/推错误气泡但**从未清 pendingApprovals**。出错时有 tool_call 处于 pending_approval → 残留可点击审批按钮。
|
||||
|
||||
- [x] **UX-260617-11 [P1]🎯** — **modelOverride 跨对话泄漏** — `useAiSend.ts:67` 模块级 ref,注释明确要求"前端应同步清 null"但**无任何代码执行此清除**。switchConversation/newConversation 不触碰。对话A选模型覆盖→切对话B→override 静默生效。
|
||||
|
||||
- [x] ✅(wf wf_b8b2a7b7 + 主代修缺陷·commit 3055b06) **UX-260617-13 [P1] 已修** — **刷新后主面板无流式恢复**【抽 restoreGeneratingState() 共享恢复链(分离窗口 resumeInDetached 薄包装委托),AiChat.vue onMounted 主面板分支(detached=false)调 store.restoreGeneratingState({fromMainPanel:true})。**关键修复**:verify agent 发现主面板刷新时 df-ai-gen localStorage 不存在(仅 detachPanel 写),原复用方案读 gen=null 直接 return 无效。加 fromMainPanel 选项绕过 localStorage:用 state.activeConversationId + ai_is_generating 真值守卫恢复(currentText 从空开始,刷新前已生成部分丢失为刷新固有代价,核心恢复 streaming 态+占位气泡消除假死)。幂等守卫(state.streaming 已 true 跳过)+ R4 后端真值守卫保留。vue-tsc EXIT 0】
|
||||
|
||||
- [x] **UX-260617-14 [P2]🎯** — **审批超时 130s 静默复位无反馈** — `ToolCard.vue:507,541-54` 超时仅 `approving.value=false`,无 toast/error/日志。用户无法区分"审批完成状态没更新"和"超时复位"。
|
||||
|
||||
- [x] **UX-260617-15 [P2]🎯** — **regenerate/editMessage 丢弃图片 parts** — `useAiSend.ts:148-190` regenerate/edit 均无 parts 参数。含图片消息重生成/编辑后图片消失。
|
||||
|
||||
- [x] **UX-260617-16 [P2]🎯** — **无路由离开/关闭保护,未发送输入静默丢失** — AiChat.vue 缺 beforeRouteLeave/onBeforeUnload 守卫。输入框有内容/已粘贴图片时切页面 → 内容瞬间消失无提示。
|
||||
|
||||
- [x] **UX-260617-17 [P2]🎯** — **ToolCardList 分组名硬编码中文绕过 i18n** — `ToolCardList.vue:259-274` nameMap 全硬编码中文(`'读取文件'`等)。英文 locale 下分组标题仍显示中文。
|
||||
|
||||
- [x] **UX-260617-18 [P2]🎯** — **isToolFailure() 正则过于宽泛误判合法输出为失败** — `ToolCard.vue:220-224` `/执行失败|failed|error[:\s]/i` 匹配任何含这些子串的文本。search_files 结果列 error.log / run_command stderr 含 warning 均被标红。
|
||||
|
||||
- [x] **UX-260617-19 [P2]🎯** — **stopChat 本地先行 reset 与后端竞态窗口** — `useAiSend.ts:479-488` 先设 streaming=false 再发 IPC stop。IPC 失败时后端继续生成但前端已停止;若后续事件也丢失则永久卡死。注释承认风险但无缓解。
|
||||
|
||||
### 架构审查已修项 (ARC- 系列)
|
||||
|
||||
- [x] ARC-260615-01 ✅ wave(2026-06-16,待commit) — ~~删 `stores/settings.ts` mock 死代码~~ grep 验零消费者 + 删文件 + index.ts 清导出 + 清 appSettings.ts:8 过时注释
|
||||
|
||||
- [x] ARC-260615-02 ✅(2026-06-16,待commit) — ~~`/decisions` 路由死链~~ 删 nav 项(App.vue secondaryNav)+ 删 `nav.decisions` i18n key(zh/en)。决策治理 = F-260614-08 长期项未实现,入口提前占位成死链;`dashboard.recentDecisions`(Dashboard.vue)不同命名空间保留
|
||||
|
||||
- [x] ✅(决策a·2026-06-16·转架构维护记录无代码) ARC-260615-03 — **重评降级(2026-06-16)**:df-execute **非空壳**——shell.rs `execute()` 已完整实现(cmd/sh 跨平台 + kill_on_drop + timeout + env)+ 被 tool_registry.rs `run_command` 复用(F-260615-05)。原 todo「76 行/1 函数 + TODO」基于 lib.rs 空判,过时。合并进 df-nodes 破坏职责分离(节点定义 vs 执行运行时)+ 动依赖树,**转架构维护决策,非清债**
|
||||
|
||||
- [x] ARC-260615-04 ✅ wave(2026-06-16,待commit) — ~~`stores/index.ts` 补 `export useAiStore`~~ barrel 补导出(3 处 view 直连可选迁移,非强制)
|
||||
|
||||
- [x] ✅(batch29·2026-06-16) ARC-260615-05 — ~~stores/project.ts 上帝 store 拆分(四领域+越层 invoke)~~ 核验越层 invoke 0 命中(已下沉 api/workflow.ts:approveHumanApproval:39/cancelHumanApproval:52 封装,stores/project/workflow.ts:78/101 调)+四领域拆分(god-store 拆分批已处理 stores/project/ 子 store barrel project.ts:122-123 委托)。vue-tsc exit 0
|
||||
|
||||
- [x] ✅(batch29·2026-06-16) ARC-260615-06 — ~~events↔stream 循环依赖~~ 提 aiShared.ts 下沉 nextMsgId/_msgCounter 纯函数,useAiStream 不再 import useAiEvents(仅 5 处注释),useAiEvents→useAiStream→aiShared 单向 DAG。vue-tsc exit 0
|
||||
|
||||
- [x] ✅(batch30·2026-06-16 评估维持现状) ARC-260615-06b [P3] — useAiEvents↔useAiSend 另一环(useAiEvents:19 import useAiSend/useAiSend:23 import useAiEvents),靠事件总线 ai-approval-clear-timers 部分缓解,非本批范围。遗留自 ARC-06 核验
|
||||
|
||||
- [x] ARC-260615-08 ✅(2026-06-16,待commit) — **[渲染优化·自研块级 memo 已实施]** 流式 Markdown 渲染——保留 marked+DOMPurify+.ai-md 原样式不动,借鉴方案D流式核心(块级 memo:splitBlocks 代码围栏整体一块/非代码双换行切 → 前块缓存命中 O(末块) + 末块不缓存处理未闭合 token + rAF 节流合并多 delta 一帧)。退役 AR-1 纯文本短路
|
||||
|
||||
### 2026-06-17 走查修复项
|
||||
|
||||
- [x] ✅(commit 645f73d) B-260617-12 [P3·可选] — **LEGACY_STATUS_MAP 映射 DRY 重复**。抽 `mapLegacyStatus(status)` 函数收敛两处 `LEGACY_STATUS_MAP[status] ?? status` 一行重复。vue-tsc EXIT 0。—— src/constants/project.ts(:96-98)
|
||||
|
||||
- [x] ✅(commit f6e4e82) **🚨 B-260617-14 [P1] 已修** — **74003bc 漏提交 adversarial.rs + project.rs**【补提两文件 reasoning_content: None,HEAD 干净 checkout 编译通过】
|
||||
|
||||
- [x] ✅(不做·优化方向错误) B-260617-15 [P2·可选] — **reasoning_content 落库存储膨胀**【核验 DeepSeek API 规范:有 tool_calls 的 assistant 消息 reasoning_content **必须**在后续请求回传(否则 400 "must be passed back")。verify agent "只走顶层"分析错误——实际需 messages 数组回传。落库剥离会导致重新加载对话后历史消息无 reasoning_content → DeepSeek 400(重新引入 BUG-12)。reasoning_content 必须保留在内存+落库+请求全链路,不可优化】
|
||||
|
||||
### 2026-06-18 用户反馈交互调整
|
||||
|
||||
- [x] **UX-260618-00(本批 4 项 AiChat/ToolCard 交互调整)**:
|
||||
- **AI 气泡复制去重**(UX-260618-01):删 `ai-msg-actions` 内复制按钮(栏仅留「重新生成」+gate 末条 AI `isLastAi`),复制统一走气泡内右下角图标 `ai-copy-btn--ai`。
|
||||
- **run_command 显命令 + 可折叠输出**(UX-260618-02):`toolDisplayName` 加 run_command 分支显 `$ <命令首行截断>`(折叠头部可见)+ body 新增命令行(`$`+完整命令)常显 & 输出可折叠(失败默认展开看 stderr/成功折叠,本地 ref `cmdOutputExpanded`+watch status)。
|
||||
- **历史消息时间戳全显「刚刚」**(BUG-260618-01):根因 `ChatMessage`(df-ai-core/provider.rs)无 timestamp 字段,后端从未持久化每条消息时间,前端加载历史 `timestamp: Date.now()` 全塞当下。
|
||||
- **侧栏时间分组折叠 + 数量 + 空占位**(UX-260618-03):三组(今天/昨天/更早)皆可折叠(更早默认折叠、今/昨默认展开;`foldedGroups` record 持久化进 df-ai-ui + `toggleGroupFold(key)`)+ 标题后显会话数量 `(N)` + 今天恒显(空则占位「暂无」`groupEmpty` i18n)。
|
||||
|
||||
- [x] **BUG-260618-02(本批 3 项模型选择/上下文修复·cargo check --workspace EXIT 0 + vue-tsc EXIT 0)**:
|
||||
- **specify 模式跑成别的 provider 模型**:`agentic.rs:350` `ProviderPool::select` 原传 `None`(无视用户指定),改传 `model_override.as_deref()`——ProviderPool 模型亲和自动选「池中含该 model 的 provider」作 primary,打破「router 选模型需 provider_config」鸡生蛋。
|
||||
- **测试连接/拉取模型后权重失效**:`commands.rs ai_fetch_models` 原 `updated.model_configs = configs.clone()` 直接覆盖,丢弃用户在 Settings 调过的 model weight/enabled/label。改合并:新探测值为主(更新能力维度),按 model_id 匹配保留旧 weight/enabled/label,新模型用探测默认。
|
||||
- **压缩上下文前端折叠藏消息**:用户诉求=压缩只后端 LLM 省 token,界面不藏消息。后端压缩逻辑正确(compress_via_llm 摘要 + is_active 白名单不发 LLM + DB 保留原文),问题在前端。
|
||||
|
||||
### 2026-06-18 6 域并行走查修复项
|
||||
|
||||
- [x] ✅(主代修·SW 批·cargo df-nodes EXIT 0) SW-260618-15 [P3] — **ai_node schema required=[provider_id] 过度约束**。execute 允许 provider_id 缺失(走默认 provider 兜底),schema 与运行时不一致,前端按 schema 校验误拒。把 provider_id 从 required 移除。
|
||||
|
||||
- [x] ✅(主代修·SW 批·vue-tsc EXIT 0) SW-260618-18 [P3] — **wasNearBottom 模块级切会话不重置**。会话 A 上滑切 B 后首滚到底误触发一次 collapseAllToolLists(收起本身无害但语义偏差)。建议 watch(activeConversationId) 内重置 true。
|
||||
|
||||
- [x] ✅(主代修·SW 批·vue-tsc EXIT 0) SW-260618-21 [P3] — **TaskDetail wfResult setTimeout 未卸载清理**。wfResult 终态提示 3s timer,组件卸载后仍触发写已销毁 ref。补 wfResultTimer + onBeforeUnmount。
|
||||
|
||||
- [x] ✅(主代修·SW 批·vue-tsc EXIT 0) SW-260618-23 [P3] — **Ideas net-sentiment neutral CSS 缺失**。sentimentClass 返回 'neutral' 但 CSS 只定义 positive/negative,中性无样式。纯样式缺口。
|
||||
|
||||
- [x] ✅(主代修·SW 批·部分·cargo df-ai EXIT 0 warning 消除) SW-260618-24 [P3] — **dead_code 基线 6 处 warning**(已标 finish_reason/call_type 2 处 serde 反序列化字段 #[allow(dead_code)] 消除 warning;其余 4 处 session_state/risk_level/diff/releases/node_executions 保留作待办提醒——session_state 待 P0 状态机收敛任务承接,risk_level/diff 待审批卡预览消费,releases/node_executions 待功能模块落地,标 #[allow] 会掩盖待办故保留)(df-ai finish_reason/call_type + mod.rs SessionState/session_state/risk_level/diff + state.rs releases/node_executions)。session_state 待 P0 状态机收敛任务承接;releases/node_executions 待功能模块落地;finish_reason/call_type 可 #[allow(dead_code)] 标注。非本次引入,勿回退。
|
||||
|
||||
### 2026-06-18 工作区进展
|
||||
|
||||
- [x] ✅(2026-06-18·转向彻底移除·工作区待提交) **B-260618-01** — 原"回退 0ca5d98 恢复虚拟滚动裁剪"**→ 转向彻底移除虚拟滚动**(删 useAiVirtualScroll.ts + AiChat.vue 移除全链路)。理由:IO/RO 时序竞态致重叠(shouldRender 恒 true 时 IO 仍设/清 sentinel minHeight 竞态源未除)+ 消息量级不需要。B-260617-09 真闭环。
|
||||
|
||||
- [x] ✅(2026-06-18·工作区待提交·vue-tsc EXIT 0) **B-260618-03** — **ToolCardList 首卡折叠 bug**。`isCardExpanded`(ToolCardList.vue)`ci===0` 兜底 `return true` 覆盖用户折叠——多卡分组首卡默认展开,用户点折叠后 ci===0 仍 true 重新展开。**修复**:加 `userCollapsedCards` 记忆态,`isCardExpanded` 最优先判断用户折叠。
|
||||
|
||||
- [x] ✅(2026-06-18·工作区待提交·vue-tsc EXIT 0) **B-260618-04** — **ToolCardList 全部展开/收起下沉 + 宽度对齐(U-260618)**。①global-toggle 从 topbar 下沉到首个可折叠分组标题行尾巴(firstCollapsibleGi computed,与 run_command 分组标题同行,chevron 移除 margin-left:auto);②分组标题行加 max-width:var(--df-msg-max-width)(90%) 对齐气泡/卡片宽度(原无 max-width 拉满 100%);③global-toggle 移除独立按钮 padding/背景高度=文字行高不撑高标题行。
|
||||
|
||||
- [x] ✅(2026-06-18·工作区待提交·vue-tsc EXIT 0) **B-260618-05** — **AI 独立窗口吸附挤出屏幕 + 宽度偏窄**。①吸附挤出:`syncToMain` 把 AI 窗口放主窗口右(pos.x+size.width+GAP),主窗口最大化时 AI x=屏幕宽+4 挤出屏幕。**修复**:syncToMain 增强——主窗口 isMaximized 时 unmaximize + 主+AI 宽度超屏幕时缩小主窗口(newMainWidth=screenWidth-GAP-AI_WIDTH-pos.x,最小 400px 保护)+ _isSyncing flag 防 syncToMain 改主窗口 size 触发 onResized 递归;屏幕宽度用顶层函数 `currentMonitor()`(@tauri-apps/api/window,非 Window 实例方法)。②独立窗口窄:detachPanel width 520→600 对齐吸附态 AI_DOCK_WIDTH。
|
||||
|
||||
### P1 缺陷修复 (已完成)
|
||||
|
||||
- [x] B-260614-08 — ~~promote_idea 两步写非事务~~ ✅ mission:T-260614-05 已修复(idea.rs 第二步 update_full 失败时补偿删除已建 project;Repository 不支持跨 repo 共享事务对象,选补偿删除非真事务,改动最小;附 logging)
|
||||
|
||||
- [x] T-260614-03 — ~~工具层白名单与 crud 白名单双份去重~~ ✅ WF-B ⑤ 已解决(tool_registry update_project 复用 is_allowed_column,与 CRUD 白名单同源,删硬编码 match)
|
||||
|
||||
- [x] T-260614-04 — ~~路径校验根治~~ ✅ 已完成(resolve_workspace_path 加 canonicalize 防 symlink 逃逸 + 词法 starts_with 兜底;仅校验、返回词法路径保持前端友好;cargo check 0 err / 22 test pass)
|
||||
|
||||
- [x] T-260614-09 — ~~idea.rs 物理删不级联~~ ✅ WF-E 完成(idea.rs:149 delete→purge_with_descendants,1 行,签名兼容)
|
||||
|
||||
- [x] T-260614-10 — ~~findBinding canonicalize~~ ✅ WF-E 判定已解决(normalize_path 已含 canonicalize 优先 + 词法回退,find_binding_conflict 两端对称已用,无需重复加;零改动)
|
||||
|
||||
- [x] T-260614-12 — ~~df-ideas 死代码~~ ✅ WF-E 部分完成(capture.rs 删 CaptureInput/IdeaCapture 死码,保留 Idea/IdeaScores 共享实体;promotion/scoring/adversarial 内"两套 Recommendation/PromotionPolicy 死枚举"嫌疑 agent 未确认存在/保留为对外契约,本次未动,待复查)
|
||||
|
||||
### 2026-06-17 实测发现 bug (审批流程三连)
|
||||
|
||||
- [x] ✅(波9·e23b316+主代核查,cargo0err+devflow79pass,方案a2后端分支) B-260617-01 [P1] — **run_workflow 作为 AI 工具无法执行 + 无意义重试 + 审批混淆**。三个关联问题:
|
||||
- **问题 1**:`run_workflow` handler(tool_registry.rs:530-546)仅持有 `db: Arc<Database>`,无法访问 `AppHandle/State`(registry/event_bus/workflows Repo),返回 `Err("run_workflow 工具需经 Tauri IPC 执行...")`。审批通过后 `ai_approve`(commands.rs:329)调 `ai_tools.execute()` → handler 必然 Err → `audit_status="failed"` → 错误信息作为 tool_result 回传 LLM。工作流实际未执行,任务状态未推进。
|
||||
- **问题 2**:handler Err → tool_result=错误提示 → LLM 认为失败 → 重试(1/4) → 同结果循环。工具定义未标 `no_retry`,浪费 token + 用户反复审批。
|
||||
- **问题 3**:前端渲染的是 AI 工具审批(tool_call pending_approval),非工作流 HumanNode 审批。用户批准后工作流引擎从未启动,HumanNode 审批节点从未到达。
|
||||
- **修复方向**:**方案 A(推荐)**:前端拦截 — `ai_approve` 中识别 `run_workflow` tool_call → 不走 `ai_tools.execute` → 直接 `invoke('run_workflow', {task_id, target_status})` → 结果回填 tool_result。**方案 B**:后端注入 State — `build_ai_tool_registry` 传入 `AppHandle` 使 handler 可直接执行。问题 2/3 随 A 自动消解。
|
||||
|
||||
### aichat API Key 401 排查 (已定位)
|
||||
|
||||
- [x] ✅ wave(2026-06-16,待commit) B-260615-01 — ~~Err 分支加诊断~~ 提取纯函数 `fmt_diag`+`extract_error_diag`(name/status_or_class/timeout·connect 分类,14 单测);约束:LlmProvider trait 无 base_url/endpoint,仅 name() 近似 provider_type(provider_type + 实际请求 url + HTTP 状态码),当前只透传服务端文本看不出端点,401 难定位 — stream_recv.rs:107-113
|
||||
|
||||
### 其他已修复问题
|
||||
|
||||
- [x] ✅(核验已实现·canRetry/canOpenSettings 已落地) UX-260616-01 [P2] — **工具调用失败时「重试」提示语义模糊**【独立核验:AiChat.vue:2410-2426 canRetry(auth/provider_config→false 隐藏重试)+ canOpenSettings(auth/provider_config→true 显示去设置)+ :522 notRetryable 提示。Fatal 类错误(4xx/鉴权)已去掉重试按钮改去设置。工具失败走 AiToolCallCompleted(非 AiStreamRetry)语义已清晰——ToolCard 显示错误,LLM 据 tool_result 自决】
|
||||
|
||||
- [x] ✅(主代修·commit 待提交·vue-tsc EXIT 0) UX-260616-02 [P3] — **「全部收起」合并一行**【核验 searchFiles i18n key 是死 key(无渲染点),实际合并 batch-approve + global-toggle 同行:ToolCardList.vue template 包 .ai-tool-topbar flex row + global-toggle margin-left:auto 右对齐】
|
||||
|
||||
- [x] ✅(第㉒批 2026-06-16) UX-2025-19 [P2] — ~~消息列表虚拟滚动~~ **已被 B-260618-01 彻底移除虚拟滚动取代**。原 e38474b 自研 IntersectionObserver+sentinel+末条保活, 因 IO/RO 时序竞态致消息重叠反复(shouldRender 恒 true 仍重叠), 最终删除 useAiVirtualScroll.ts + AiChat.vue 移除全链路。
|
||||
|
||||
### 2026-06-16 走查修复项
|
||||
|
||||
- [x] ✅(第㉖批 2026-06-16·主代理直修) B-260616-09 [P1] — **任务详情点击打开空白(路由漏注册)**。**router/index.ts 补 /tasks/:id → TaskDetail**(L50-54 新增块,6 行,参照 /projects/:id L39-43 + /ideas/:id L27-31 模式)。name 'TaskDetail' 无冲突(现有 name 集无此项),复用 icon-thunder(对齐 /ideas/:id 复用 icon-lightbulb、/projects/:id 复用 icon-apps 一致模式)。TaskDetail.vue 现挂载,Tasks.vue:57 router.push(`/tasks/${task.id}`) 不再跳未注册路由,B-18 联动刷新等功能激活(死代码转活)。改动极简确定(6 行路由表项),主代理直修省 workflow 单 agent 编排开销。vue-tsc exit 0。
|
||||
|
||||
- [x] ✅(第㉖批 2026-06-16) B-260616-10 [P1] — **provider 配置后 AI 面板仍提示「未配置」**。**Settings.vue loadProviders 同步刷全局 store**。L376 import useAiStore + L383 const aiStore = useAiStore()(跟随 L382 appSettings 风格)+ L420-424 loadProviders 内本地 aiProviders.value 刷新成功后 L424 await aiStore.loadProviders() 刷全局 state.providers(模块级单例 ai.ts:45,L20/L44 注释明确全应用共享同一份,AiChat 共享)。三处调用点(saveProvider L464/deleteProvider L479/setDefaultProvider L490)+ onMounted L731 均经 loadProviders 自动同步全局。无循环(useAiPanel.ts:91 loadProviders 只刷 state.providers 不回调 Settings)。无 i18n 改动(纯数据同步),try/catch + showToast 保留。vue-tsc exit 0。
|
||||
|
||||
- [x] ✅(ca9b318·wrapNakedDiff落地+第㉖批diff语言注册) B-260616-11 [P2] — **AI 消息 `-`/`+` 列表/diff 无视觉效果**。两项子项均已落地:①**裸 diff 预处理** `wrapNakedDiff`(ca9b318 useMarkdown.ts:+96 守卫4:纯`-`列表不触发/≥2行连续±/已在围栏不动/段落级处理+短路优化+缓存key用wrapped) ②**diff 围栏高亮**(第㉖批 useMarkdown.ts import diff+registerLanguage('diff')+highlightCode getLanguage('diff')→hljs addition/deletion token+github-dark.css 红绿)。
|
||||
|
||||
- [x] ✅(第㉗批 2026-06-16·workflow) B-260616-19 [P2] — **知识库详情窄屏标题挤压成竖线(一行一字)**。三因子叠加(Knowledge.vue):①`.kn-layout` grid `grid-template-columns: 360px 1fr`(L567)——左列表死钉 360px、右详情 `1fr` 拿剩余,**无响应式断点**;窗口窄(如总宽 500px,减 padding 40+gap)详情列塌缩到 ~80px 甚至更小。②`.detail-title`(L625)`font-size:18px` + `word-break:break-word` —— 窄列里中文每字宽度 > 列宽,逐字换行 → 竖线化。③`.detail-actions`(L626)`flex-shrink:0` —— 编辑/发布/拒绝 3 按钮不缩,优先占位,把 `.detail-title-row`(`flex:1`) 挤到零头。`.kn-detail-panel`(L570-576) 无 `min-width` 兜底。改动(待定):①grid 列宽改 `minmax(240px,360px) 1fr` + `@media (max-width:760px)` 切单列(`grid-template-columns:1fr`,列表详情上下堆叠);②详情面板加 `min-width:0` 配合标题行 `min-width` 防塌缩;③可选标题字号响应式降级(18px→15px)。— src/views/Knowledge.vue。**低风险纯 CSS**,无逻辑/i18n/数据变动。
|
||||
|
||||
---
|
||||
|
||||
> 归档自 todo.md 2026-06-18 三文档巡检
|
||||
1080
docs/07-项目管理/todo归档/2026-06.md
Normal file
1080
docs/07-项目管理/todo归档/2026-06.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -324,3 +324,30 @@
|
||||
|
||||
#### ~~S-260614-01 「显示多开」需求澄清~~
|
||||
- **状态**:✅ 已解决(2026-06-16)— 用户澄清:需求本质是「会话来回切并行处理」(A 对话回复中切到 B 发消息,A 后台继续跑),非设置页开关。已被 F-260616-09(决策 a:d1 侧栏切换+后台并行)完整覆盖收编。
|
||||
|
||||
---
|
||||
|
||||
## 当前队列已决项迁入(2026-06-18)
|
||||
|
||||
#### B-260617-01 run_workflow 作为 AI 工具无法执行 + 无意义重试 + 审批混淆
|
||||
- **背景**:2026-06-17 实测发现,AI 对话中调用 `run_workflow(task_id, target_status)` 推进任务状态,审批通过后 handler 返回 Err 提示字符串(`tool_registry.rs:530-546`),`ai_approve`(`commands.rs:329-334`)将其包成 `"failed"` tool_result 回传 LLM → LLM 认为失败 → 重试(1/4) → 又进审批 → 循环。三个关联问题:
|
||||
- **问题 1**:run_workflow handler 仅持有 `db: Arc<Database>`,无法访问 `AppHandle/State`(registry/event_bus/workflows Repo),返回 Err 提示前端走 IPC。但 `ai_approve` 审批通过后直接 `ai_tools.execute()` 调 handler → 必然 Err。
|
||||
- **问题 2**:handler Err → tool_result = 错误提示 → LLM 重试 → 同结果循环(工具定义未标 `no_retry`)。
|
||||
- **问题 3**:前端渲染的是 AI 工具审批(tool_call pending),非工作流 HumanNode 审批。用户批准后工作流引擎从未启动。
|
||||
- **决策点**:run_workflow 审批通过后如何真正执行工作流?
|
||||
- **选项**:
|
||||
- a: **前端拦截**(`ai_approve` 中识别 `run_workflow` → 不走 `ai_tools.execute` → 直接 `invoke('run_workflow', {task_id, target_status})` → 结果回填 tool_result)
|
||||
- b: **后端注入 State**(`build_ai_tool_registry` 传入 `AppHandle` 使 handler 可直接执行,改 state.rs + tool_registry 签名)
|
||||
- c: **从 AI 工具移除 run_workflow**(仅保留 advance_task 推进状态,工作流由用户手动在前端触发)
|
||||
- **推荐**:**a 前端拦截**(改动最小,`ai_approve` 一处分支即可;方案 b 需改 tool_registry 签名链路较长;方案 c 退回手动不符合 AI 驱动目标)。问题 2/3 随 a 自动消解。
|
||||
- **关联**:todo B-260617-01 / tool_registry.rs:530-546 / commands.rs:329-334 / audit.rs:590-630
|
||||
- **状态**:✅ 已决(2026-06-17·波9 e23b316)— **决策:a 细化为 a2(后端分支)**。ai_approve 已持 app+state,后端直接调 run_workflow_inner 最干净(无需新 IPC/前端分支/工作流知识泄漏),符合 a 大方向(绕开 ai_tools.execute 必 Err)。问题 2 随 a2 消解(成功 tool_result + High 去重缓存双层断循环);问题 3 渲染区分记观察项(tool_display_hint 已含「触发工作流」语义)。详单见待审查 CR-52。
|
||||
|
||||
### ~~S-260614-01 多会话来回切(A/B 路线)~~ — 已并入 F-260616-09
|
||||
- **状态**:✅ 已并入 F-260616-09(2026-06-16 已决 a:A 隔离修复 + B 立项高优先实施)。A/B 路线决策统一收口于 F-260616-09,本条不再独立维护。A 路线实施待 T-260614-02 实测确认是否升 B。
|
||||
|
||||
#### B-260617-11 tauri.conf.json 打包目标收窄确认
|
||||
- **背景**:工作区改动 `bundle.targets: "all" → ["nsis"]`(src-tauri/tauri.conf.json:28),收窄到仅 Windows NSIS。若随其他改动一并提交,macOS(dmg/app)/Linux(deb/appimage)构建将不可用,影响其他开发者/CI。
|
||||
- **决策点**:临时本地构建 vs 有意入库?
|
||||
- **选项**:A 临时本地构建(提交前 revert 此行) / B 有意入库(改按平台条件配置而非硬编码单 target)
|
||||
- **状态**:✅ 已决(2026-06-18) — **决策:A 临时本地构建,要求高速**。`["nsis"]` 已是 Windows 单一最快安装包目标。提交前须 revert 为 `"all"`。若进一步提速可用 `["app"]`(裸 .exe 无安装包)或 `tauri build --no-bundle`。
|
||||
|
||||
1062
docs/07-项目管理/待审查归档/2026-06.md
Normal file
1062
docs/07-项目管理/待审查归档/2026-06.md
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/clipboard_20260618_125114.png
Normal file
BIN
docs/clipboard_20260618_125114.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 323 KiB |
1298
docs/todo.md
1298
docs/todo.md
File diff suppressed because it is too large
Load Diff
86
docs/待决策.md
86
docs/待决策.md
@@ -24,35 +24,6 @@
|
||||
---
|
||||
|
||||
## 当前队列
|
||||
|
||||
### ③类 — 产品取舍(有 a/b/c 决策点,核心待拍板)
|
||||
|
||||
#### B-260617-01 run_workflow 作为 AI 工具无法执行 + 无意义重试 + 审批混淆
|
||||
- **背景**:2026-06-17 实测发现,AI 对话中调用 `run_workflow(task_id, target_status)` 推进任务状态,审批通过后 handler 返回 Err 提示字符串(`tool_registry.rs:530-546`),`ai_approve`(`commands.rs:329-334`)将其包成 `"failed"` tool_result 回传 LLM → LLM 认为失败 → 重试(1/4) → 又进审批 → 循环。三个关联问题:
|
||||
- **问题 1**:run_workflow handler 仅持有 `db: Arc<Database>`,无法访问 `AppHandle/State`(registry/event_bus/workflows Repo),返回 Err 提示前端走 IPC。但 `ai_approve` 审批通过后直接 `ai_tools.execute()` 调 handler → 必然 Err。
|
||||
- **问题 2**:handler Err → tool_result = 错误提示 → LLM 重试 → 同结果循环(工具定义未标 `no_retry`)。
|
||||
- **问题 3**:前端渲染的是 AI 工具审批(tool_call pending),非工作流 HumanNode 审批。用户批准后工作流引擎从未启动。
|
||||
- **决策点**:run_workflow 审批通过后如何真正执行工作流?
|
||||
- **选项**:
|
||||
- a: **前端拦截**(`ai_approve` 中识别 `run_workflow` → 不走 `ai_tools.execute` → 直接 `invoke('run_workflow', {task_id, target_status})` → 结果回填 tool_result)
|
||||
- b: **后端注入 State**(`build_ai_tool_registry` 传入 `AppHandle` 使 handler 可直接执行,改 state.rs + tool_registry 签名)
|
||||
- c: **从 AI 工具移除 run_workflow**(仅保留 advance_task 推进状态,工作流由用户手动在前端触发)
|
||||
- **推荐**:**a 前端拦截**(改动最小,`ai_approve` 一处分支即可;方案 b 需改 tool_registry 签名链路较长;方案 c 退回手动不符合 AI 驱动目标)。问题 2/3 随 a 自动消解。
|
||||
- **关联**:todo B-260617-01 / tool_registry.rs:530-546 / commands.rs:329-334 / audit.rs:590-630
|
||||
- **状态**:✅ 已决(2026-06-17·波9 e23b316)— **决策:a 细化为 a2(后端分支)**。ai_approve 已持 app+state,后端直接调 run_workflow_inner 最干净(无需新 IPC/前端分支/工作流知识泄漏),符合 a 大方向(绕开 ai_tools.execute 必 Err)。问题 2 随 a2 消解(成功 tool_result + High 去重缓存双层断循环);问题 3 渲染区分记观察项(tool_display_hint 已含「触发工作流」语义)。详单见待审查 CR-52。
|
||||
|
||||
### 🟡 S-260614-01 多会话来回切对话(A/B 路线决策)
|
||||
- **背景**:用户澄清(2026-06-17)「显示多开」原意 = 多个会话来回切都可对话(非 AI Chat 窗口多开)。关联 T-260614-02(切对话不中断实测)+ F-09 多会话架构。
|
||||
- **决策点**:A 路线(单例软隔离)实测够 vs 需 B 路线(真多会话并行)架构升级?
|
||||
- **选项**:
|
||||
- a: **A 路线实测确认**(T-260614-02 跑 tauri dev 验证切会话不中断、来回切可对话)。够 → 销账;不够 → 升 b。
|
||||
- b: **B 路线架构升级**(AiSession 单例 → 多实例,每会话独立 generating/AiSession,切走不打断)。memory aichat-arch-extensibility 记录单例未动。大改(触 ai/mod.rs AiSession + state.rs AppState + agentic.rs loop)。
|
||||
- **推荐**:**a 先实测**(T-260614-02 验证 A 路线是否满足"来回切都可对话")。A 路线设计目标即切会话不丢上下文 + active 切换,理论支持。若实测发现切走 generating 被打断(单例限制)→ 升 b。避免盲目大改。
|
||||
- **关联**:todo S-260614-01 / T-260614-02 / F-09 / memory aichat-arch-extensibility
|
||||
- **状态**:🟡 待用户实测(T-260614-02)确认 A 路线是否够
|
||||
|
||||
### ⏸️ 暂缓(待条件触发)
|
||||
|
||||
#### T-260614-11 条件表达式引擎升级
|
||||
- **背景**:df-workflow conditions 仅支持 true/false 字面量,升级为真表达式求值。引擎设计好但无前端 UI 消费方(demoDag edges 无 condition 字段)。
|
||||
- **决策点**:求值器实现方式?(已暂缓:等工作流真实场景)
|
||||
@@ -79,6 +50,9 @@
|
||||
- **待用户操作**:部分场景运行时实测(A 路线场景 2/3)。
|
||||
- **状态**:🟡 待用户实测
|
||||
|
||||
#### ~~B-260617-11 tauri.conf.json 打包目标收窄确认~~
|
||||
- **状态**:✅ 已决(2026-06-18) — 已迁入归档。决策:A 临时本地构建,要求高速。提交前 revert 为 `"all"`。
|
||||
|
||||
### 🟡 待设计/架构演进(有决策点,需方案设计或长期规划)
|
||||
|
||||
#### ARC-260615-07 架构重构批(排期/优先级决策)
|
||||
@@ -115,6 +89,60 @@
|
||||
- **关联**:todo UX-260617-28 [INFO]
|
||||
- **状态**:⏸️ 长期(INFO,当前够用)
|
||||
|
||||
#### B-260618-03 路由解耦 cost_tier/intelligence(用户已全局决策去掉,工程大需专项)
|
||||
- **背景**:用户 2026-06-18 决策「API 无判别依据的 cost_tier/intelligence 去掉,不写死不瞎填」。当前 router.rs 用 cost/intel 做硬过滤(步骤4 min_intelligence / 步骤5 max_cost)+ 排序(步骤7 Reverse(cost_tier)),但这两维度 100% 由 model_probe 瞎猜(预设表+启发式),零客观依据。GLM-5.2 被猜成 standard/medium(名不沾词素走兜底),title/compress 按 max_cost 过滤可能选不到合适模型。
|
||||
- **决策点**:用户已全局决策去掉。本项是落地(自主可推进)。记待决策因:工程大(~30 Edit)+ 主链路由行为变更需 cargo test router 全验证 + title/compress 选模型退化需在场核对。
|
||||
- **选项**:
|
||||
- a: 自主推进(用户已决策,专项会话充分资源 + cargo test router 全验证 + 实测 title/compress 选模型)
|
||||
- b: 等用户在场专项(核对路由行为退化 + 实测)
|
||||
- **实施清单(勘察完成 2026-06-18)**:
|
||||
- router.rs:TaskRequirements 删 min_intelligence(:29)/max_cost(:31)字段 + 删步骤4 filter(:62)/步骤5 filter(:63) + 步骤7 max_by_key 改纯 weight 删 Reverse(cost_tier)(:65) + 注释更新(:28/:31/:48-51/:55)
|
||||
- 9 调用点删 min_intelligence/max_cost 传参:project.rs:535-536/631-632 · compress.rs:62-63 · knowledge_inject.rs:61-62/346-347 · agentic.rs:414-415 · title.rs:88-89 · ai_node.rs:203-204 · adversarial.rs:161-162
|
||||
- import 清理:调用点 CostTier/IntelligenceTier 不再用则删 import(title.rs/compress.rs 用 CostTier;多处用 IntelligenceTier)
|
||||
- test:router.rs 多 test 改/删(max_cost_filters_expensive / max_cost_none_allows_any / same_weight_picks_cheaper_cost_tier / intelligence 相关 + TaskRequirements 构造删字段)
|
||||
- ModelConfig.cost_tier 字段保留(B-04 model_probe 去瞎填处理数据源,不删字段)
|
||||
- df-ai-core/model.rs 注释更新(:47/:60 提及 router max_cost/min_intelligence)
|
||||
- **推荐**:**a 自主推进**(用户已全局决策,方向明确),建议专项会话充分资源;title/compress 失去 max_cost 约束后纯 weight 选模型,需核对 weight 配置合理(用户在 Settings 配)
|
||||
- **关联**:todo B-260618-03/04/05 · UX-260618-04 前端 cost/intel 标签(依赖本项)
|
||||
- **状态**:✅ **已实施**(2026-06-18 workflow wexu1isx1,主代核查 cargo check --workspace EXIT 0 + cargo test df-ai 109 passed + vue-tsc EXIT 0;SW-02 借用 E0502 主代修)。title/compress 纯 weight 选模型退化点:用户核对 Settings weight 配置(同 weight 并列 max_by_key 返回最后一个)
|
||||
|
||||
#### ARC-260618-01 God 文件拆分批(架构重投入·需设计)
|
||||
- **背景**:2026-06-18 架构坏味道扫描出 3 个 God 文件:`tool_registry.rs` 1091行单函数(SMELL-P0-2)/`AiChat.vue` 4026行单组件(SMELL-P0-3)/`crud.rs` 2212行(SMELL-P1-9)。均属"功能能跑但维护成本高/测试难"的技术债,非功能 bug。
|
||||
- **决策点**:拆分何时做/优先级/拆分边界(每项拆分策略需专项设计,非小改;做不做是资源/可维护性取舍)
|
||||
- **选项**:
|
||||
- a: `tool_registry.rs` 按 CRUD/文件/工作流分组拆注册函数(每个<200行,单文件域,风险中)
|
||||
- b: `AiChat.vue` 拆 ConversationSidebar/MessageList/ChatInput/ApprovalPanel(巨型组件,风险高,AiChat.vue 已在频繁改动需择稳定窗口)
|
||||
- c: `crud.rs` 按表拆 project/task/conversation/idea_repo(2212行,中风险)
|
||||
- **推荐**:**⏸️ 缓做**(当前功能优先;三项均大改需专项设计+充分测试。建议按 a→c→b 顺序,a 单文件域最独立先做,b 待 AiChat 改动沉淀后)
|
||||
- **关联**:todo SMELL-P0-2/P0-3/P1-9
|
||||
- **状态**:🟡 待排期决策
|
||||
|
||||
#### SMELL-P1-6 String→newtype 强类型(需设计)
|
||||
- **背景**:execution_id/status/tool_type 等 5+ 处用裸 String,类型安全弱(混用/拼写错编译期不拦)。改 newtype(ExecutionId 等)需全栈波及(Rust struct 字段 + serde + IPC 边界 + 前端 ts 类型)。注:status 场景 df-types 已有 TaskStatus enum,部分代码用 String 而非 enum。
|
||||
- **决策点**:做不做 + newtype 边界(仅 Rust 内部 vs 跨 IPC 到前端)
|
||||
- **选项**:
|
||||
- a: 全栈 newtype(Rust+IPC+前端,类型安全最强,波及大)
|
||||
- b: 仅 Rust 内部 newtype(IPC 边界仍 String,折中)
|
||||
- c: 不做(String 够用,status 已有 enum 部分覆盖)
|
||||
- **推荐**:**⏸️ 缓做**(全栈波及大 ROI 中等;倾向 b 折中或 c 现状 enum 已部分覆盖。若做需专项设计 newtype 边界)
|
||||
- **关联**:todo SMELL-P1-6
|
||||
- **状态**:🟡 待设计决策
|
||||
|
||||
#### SW-260618-21 死代码预留功能清理批(清理 vs 保留)
|
||||
- **背景**:2026-06-18 深层 sweep 核验出 4 类「0 外部消费者但设计预留」符号。清理减负 vs 保留未来功能取舍。注:`PendingApproval.diff` 经 IPC 活跃(useAiEvents:252 `event.diff→tc.diff` + ToolCard:44/754/772 渲染·UX-260618-06 审批 diff)**非死代码不删**;`transition_status` 已删(批次7·0 消费者+TODO 未实现)。
|
||||
- **核验(独立 grep 2026-06-18)**:
|
||||
- `SessionState` enum + `session_state()`(mod.rs:172/393):0 外部调用·注释「读状态统一走 session_state() 收敛」设计预留(待重构 SW-02 类终态化复用)
|
||||
- `AppState.releases`/`node_executions`(state.rs:206/210):`\.releases\b|\.node_executions\b` 0 字段访问·df-storage ReleaseRepo/NodeExecutionRepo 预留(未来 release mgmt/node exec log)
|
||||
- ~~`PendingApproval.risk_level`(mod.rs:410)~~:**✅ 已删(2026-06-18·前端 types.ts 0 字段坐实真死·零波及·CR-22)**
|
||||
- **决策点**:清理 0 消费者预留 vs 保留未来功能
|
||||
- **选项**:
|
||||
- a: 全清理(删 SessionState/releases/node_executions/risk_level·连带 df-storage repo 定义·减 dead_code warning·但失去预留扩展点)
|
||||
- b: 全保留+标 `#[allow(dead_code)]` 注释预留意图(消 warning·保留未来·零波及)
|
||||
- c: 部分(SessionState/releases 近期无计划清·risk_level 核前端类型后定)
|
||||
- **推荐**:**⏸️ b 保留+标 allow**(预留设计意图明确·清理失去未来扩展点 ROI 低;标 allow 消 warning 即可·零波及)
|
||||
- **关联**:批次7 transition_status 已删 / CR-22 删 risk_level / CR-23 标 allow 5 处
|
||||
- **状态**:✅ 已实施 b(2026-06-18·主代自主决策·risk_level 删 + 预留/diff 标 allow·cargo 0 warning)
|
||||
|
||||
---
|
||||
|
||||
## 已决归档
|
||||
|
||||
1436
docs/待审查.md
1436
docs/待审查.md
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user