Files
DevFlow/docs/待决策.md
绝尘 549f198cea 更新: 待决策回填(7DEC+3专题按推荐) + 父②V29
- DEC-01 父② 知识图谱独立 V29(V28 已被灵感软删除 ideas.deleted_at 占用)
- DEC-02 #7 保留 purge / DEC-03 #6 拆 const(接 LLM 后升 a) / DEC-04 #9/#10 逗号 tags
- DEC-05 层2 维持白名单 / DEC-06 父③排父②后 / DEC-07 父④排父②后
- 专题-1 workspace_root ①先行分发前定② / 专题-2 审批超时不做(等待即等待) / 专题-3 F-09归父④
2026-06-26 22:16:30 +08:00

406 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 待决策队列
> **职责分离**:
> - **主会话**(汇总/巡检)→ 【写入】"当前队列",登记待人工决策项(背景 + 决策点 + 选项 a/b/c + 推荐)。
> - **用户**(人工)→ 【拍板】选选项或确认推荐,回填理由(可选)。
> - **主会话**(拍板后)→ 决策项回流 [todo.md](./todo.md) 推进 + 迁入"已决归档"。
>
> 这里**只放需人工决策项**(产品取舍 / 方向选型 / 排期 / 用户实测澄清)。不放可自主推进待办(见 [todo.md](./todo.md))、不放审查登记(见 [待审查.md](./待审查.md))。
>
> **已决策历史**按月归档,见 [07-项目管理/待决策归档/](./07-项目管理/待决策归档/)。拍板后的项迁入对应 `YYYY-MM.md`(随时间增长追加月份文件,防本文件膨胀;文件不存在则新建)。
> 来源:2026-06-16 从 todo.md 抽离③④C类(可自主批 AE-03/复核⑪/UX-04 留 todo 推进)。
## 决策规则
- 每条须:背景 + 决策点 + 选项 + 推荐 + 关联 todo。
- 用户回填:`✅ 决策:X`(选 + 理由可选)。
- 拍板后:主会话回流 todo 实施 + 迁入 [07-项目管理/待决策归档/YYYY-MM.md](./07-项目管理/待决策归档/)(按月文件)。
- 暂缓项标 ⏸️,不删(条件变化可重启)。
## 状态图例
🟡 待决 / ✅ 已决(回填决策) / ⏸️ 暂缓(待条件)
---
## 当前队列
### ✅ 2026-06-26 任务图谱推进待决策(已按推荐方向全部决策)
> 来源:用户 2026-06-26 多角度论证(基于代码实况) + 确认「按推荐方向决策」7 DEC + 3 专题全部拍板。
> **关键修正**:DEC-01 V28 已被灵感软删除(`ideas.deleted_at`,commit 005079f)占用 → 知识图谱用 **V29**;DEC-03 推荐由 a 修正为 **c**(启发式是过渡,接 LLM 评分后按需升 a)。
#### ✅ DEC-260626-01 父② 知识图谱 Phase 1 多工程合并
- **决策**:**b** — 知识图谱独立 Phase 1(**V29**,V28 已被灵感软删除占用)。多工程代码零行(grep 全空),合并无理由,多工程后续 V30+。
- **关联**:todo 父②
- **状态**:✅ 已决(2026-06-26)
#### ✅ DEC-260626-02 ⑤.2 #7 promote 补偿删除方式
- **决策**:**b** — 保留 purge。补偿是内部回滚建错的 project(非用户删除),purge 干净不污染回收站。
- **关联**:todo ⑤.2 #7(标"保留 purge 不改")
- **状态**:✅ 已决(2026-06-26)
#### ✅ DEC-260626-03 ⑤.2 #6 评分关键词配置形式
- **决策**:**c** — 先拆 const 到独立文件(中/英两套,最小改动)。原推荐 a 修正:启发式是过渡(scoring.rs TODO 接 LLM 语义评分),接 LLM 后按需升 a(JSON 文件)。
- **关联**:todo ⑤.2 #6
- **状态**:✅ 已决(2026-06-26)
#### ✅ DEC-260626-04 ⑤.2 #9/#10 表单补全交互
- **决策**:**a** — tags 逗号分隔输入框(对标 Knowledge.vue 先例)+ priority 下拉 + source 输入。chip 组件留 UX 升级。
- **关联**:todo ⑤.2 #9/#10
- **状态**:✅ 已决(2026-06-26)
#### ✅ DEC-260626-05 BUG-260620-05 层2 授权政策
- **决策**:**a** — 维持方案①(白名单+弹窗三档)。层1(工程内免授权,F-260619-03 方案①)已解痛点,层2 黑名单制安全风险 + 分发冲突。
- **关联**:todo BUG-260620-05 层2(标"维持①不做")
- **状态**:✅ 已决(2026-06-26)
#### ✅ DEC-260626-06 父③ ToolCard 跨轮合并 + 审批状态机排期
- **决策**:**b** — 等 G1 实测 + 父② 后再做。审批是高危路径,AiChat.vue 仍在频繁改动,择稳定窗口专项。
- **关联**:todo 父③(排父②后)
- **状态**:✅ 已决(2026-06-26)
#### ✅ DEC-260626-07 父④ F-09 per-conv 真多会话排期
- **决策**:**a** — 父② Phase 1 后启动。F-09 是 Phase 4 前置,大改不与父② 并行(回归交叉)。
- **关联**:todo 父④(排父②后)
- **状态**:✅ 已决(2026-06-26)
#### ✅ 专题-1 workspace_root 分发适配
- **决策**:**① 先行**(去默认白名单,dev 自用 projects.path 自动授权够),**分发前定②**(去相对锚)。
- **状态**:✅ 已决(2026-06-26,① 立即/② 分发前)
#### ✅ 专题-2 BUG-260623-03 审批 pending 超时兜底
- **决策**:**c 无超时**(不做超时兜底)。用户:等待审批就是等待,一直等待,超时概念多余。审批是用户主动行为,不审批自然挂起等待,无需超时强制 reject/倒计时。
- **状态**:✅ 已决(2026-06-26,不做超时,关闭 BUG-260623-03)
#### ✅ 专题-3 F-09 streaming/currentText per-conv
- **决策**:**暂缓**(随 B 路线多会话并发同批做,即 DEC-07 父④)。
- **状态**:✅ 已决(2026-06-26,归父④)
---
#### T-260614-11 条件表达式引擎升级
- **背景**:df-workflow conditions 仅支持 true/false 字面量,升级为真表达式求值。引擎设计好但无前端 UI 消费方(demoDag edges 无 condition 字段)。
- **决策点**:求值器实现方式?(已暂缓:等工作流真实场景)
- **选项**:
- a: 手写求值器
- b: 复活 set_skipped
- c: default false + warn(均认可)
- **推荐**:**⏸️ 暂缓**(无消费方,等 BuildNode 落地跑构建→测试→部署真实场景)
- **关联**:todo T-260614-11
- **状态**:⏸️ 暂缓
### 🟡 待用户实测/澄清(需用户操作,主会话无法代办)
#### S-260614-02 审批可见性实测重评
- **待用户操作**:实测 tc 卡片是否渲染。B-01 修复后 pending_approvals 内存态不再被 switch 清空,前端查询有数据,但 state.pendingApprovals 在 AiChat.vue 是否有兜底渲染仍需实测。
- **选项**:A 加兜底渲染 / B 实测确认(去重:AR-3 修完已缓解,改实测重评)
- **状态**:🟡 待用户实测
#### T-260614-01 多项 tauri dev 实测
- **待用户操作**:Sprint 9/10/14/15/16/18 多项未 tauri dev 实测 — 评分 IPC 缩放 / update_full / promote_idea / Store getter / token 落库 / 知识库 Tier 1 全栈 / LLM 并发 Semaphore / 知识生命线(#54 跟踪)。
- **状态**:🟡 待用户实测
#### T-260614-02 切对话不中断路由实测
- **待用户操作**:部分场景运行时实测(A 路线场景 2/3)。
- **状态**:🟡 待用户实测
#### S-260623-01 「自托管」含义澄清
- **背景**:用户要求设置支持「自主执行(含高危)+ 自托管」。**自主执行含高危已实现** —— `autoExecuteMode` 三档 `low`/`medium`/`all`(AdvancedSection.vue F-#97, 2026-06-22),`all` = 完全 AI 接管含高危(delete/purge/run_command),选时二次确认。设置 → 高级 → AI 自动执行范围。但「自托管」grep 全项目无匹配,含义未明确。
- **待用户澄清**:「自托管」指什么?
- **选项**:
- a: 自托管 AI 模型 endpoint(用户配自己的模型 API/本地模型,非默认 provider)
- b: 自管执行策略(= autoExecuteMode 已覆盖,无需另做)
- c: 自托管后端服务(用户自部署 df-relay/df-tunnel,非默认 `u-work.1216.top`)
- d: 其他(用户补充)
- **关联**:task105 / memory(设置自主执行已实现)
- **状态**:✅ **自用阶段定案(2026-06-23)** —— 用户决策:小程序当前自用(开发阶段),分发是产品终态但留后续(过渡期靠改 device_id 实现多机)。故「自托管」现阶段 = 已实现的自主执行(autoExecuteMode all 含高危),无另义。分发阶段再做配置层(MINIDEC-01)+ 配对(MINIDEC-02)。
#### ~~B-260617-11 tauri.conf.json 打包目标收窄确认~~
- **状态**:✅ 已决(2026-06-18) — 已迁入归档。决策:A 临时本地构建,要求高速。提交前 revert 为 `"all"`
### 🟡 待设计/架构演进(有决策点,需方案设计或长期规划)
#### ARC-260615-07 架构重构批(排期/优先级决策)
- **背景**:src-tauri IPC 编排层 5711 行成事实业务层,7 项架构债。df-core→df-types 已完成(CR-61),剩 6 项独立大改。
- **决策点**:6 项重构何时做/优先级/是否做(每项 ROI 与风险权衡,无法纯技术论证——做不做是资源/产品取舍)
- **选项(剩余 6 项)**:
- a: df-app 抽取(IPC 编排层 5711 行独立 crate)
- b: AI agent loop 从 IPC 下沉 df-ai(逻辑与 IO 分离)
- c: 类型契约 ts-rs 代码生成(替代手写 types.ts)
- d: AiSession 多会话(B 路线前置,关联 S-260614-01)
- e: AppState 分组(5711 行 state 拆分)
- f: IPC 命名统一
- **推荐**:**⏸️ 缓做**(重构低 ROI,当前功能优先;待稳定后按 d→b→a 顺序,d 是 B 路线前置可先)
- **关联**:todo ARC-260615-07 / memory aichat-arch-extensibility
- **状态**:🟡 待排期决策
#### UX-260617-01 aichat 消息全量重叠(待 DevTools 定位根因)
- **背景**:用户实测消息大量重叠堆叠。5 角度分析排除 CSS/scoped/DOM,核心嫌疑虚拟滚动 IO 半激活态不一致 + height=0 未设 minHeight → slot 塌 0 → 重叠。
- **决策点**:根因确切触发路径(需 DevTools 实测,静态分析已到极限)
- **选项**:
- a: 虚拟滚动 IO/RO 时序竞态(主嫌疑,unload 分支 minHeight 兜底修复)
- b: 其他(DOM 结构问题,需 DevTools 实查)
- **推荐**:**待用户 DevTools 实测**(shouldRenderMsg 卸载时检查 slot 实际高度 + IO unobserve/observe 时序),定位后修法明确(unload 分支 minHeight fallback)
- **关联**:todo UX-260617-01 / docs/05-代码审查/AI聊天组件极端数据场景分析-2026-06-17.md
- **状态**:🟡 待 DevTools 验证根因
#### UX-260617-28 双监听器同通道(长期架构演进)
- **背景**:useAiEvents + useAiContext 各自 listen('ai-chat-event'),人工 AiCompressing flag 协调防双重处理,非架构保证。未来新增事件处理可能触发双重 bug。
- **决策点**:是否升级单一分发器模式(架构保证)
- **选项**:
- a: 保持现状(AiCompressing flag 协调够用)
- b: 单一分发器(架构保证,但大改)
- **推荐**:**⏸️ 暂缓**(当前 flag 协调有效,未来新增事件处理触发双重 bug 时再升级)
- **关联**: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行,单文件域,风险中) — **✅ 已实施(2026-06-18 workflow w2xkw4ybh data 抽出 + 主代 sweep 批4)·build_ai_tool_registry 1091→7 行·抽 register_data_tools(18 持 db 工具)+ register_file_tools(10 文件工具)·加基线测试 test_build_ai_tool_registry_baseline_tool_count(Database::open_in_memory·断言 len()==28 + tool_names() 集合)·主代核查 cargo check --workspace EXIT 0 / cargo test df-ai 119 passed / devflow 基线 1 passed / vue-tsc EXIT 0**
- 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
- **状态**:🟡 待排期决策(a 已实施·b/c 待排期:b AiChat 并发改中缓·c 待专项窗口)
#### 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)
#### F-260616-09-B 多会话并发架构 B 阶段实施决策(设计完成 2026-06-19·待拍板)
- **背景**:F-09 B 阶段设计文档完成 [F-09-多会话并发架构设计-2026-06-19.md](./02-架构设计/已编号方案/F-09-多会话并发架构设计-2026-06-19.md)。核验发现 **A 路线补漏已全部落地**(commands.rs:1404-1409 + useAiConversations.ts:80-83)→ **阶段1 跳过**。AiSession 12 字段。阶段2(B 主体,批1-8)待启动。
- **决策点**:
- **⚠️ b-1(关键·须拍板)**:messages 是否 per-conv。原决策 b「messages 按 conv reload(不 per-conv)」与决策 e「切换不退出各自跑完」**矛盾**(单例 messages 下旧 loop push 污染新 conv,B-260615-11 退出校验必须保留→与 e 冲突)。设计推荐**修正 b 为 messages per-conv**(e 的技术必然必要条件,侵入面增量极小:ContextManager 挪 HashMap)。
- **⚠️ c-1**:global permits=3 默认值 + Settings 加「并发会话数上限」配置项。
- **e-1(主代已定✅)**:旧 loop save_conversation 保持原路径(save 接 conv_id 零改动)。低风险技术细节,主代裁决采纳。
- **推荐**:**✅ b-1 采纳(messages per-conv,技术必然)+ c-1 保持 3 + Settings 配置 + e-1 原路径**。拍板后启动阶段2 批1(PerConvState 数据结构 + 访问器)。
- **关联**:todo F-260616-09 / 设计文档 / memory aichat-arch-extensibility
- **状态**:✅ **主代自主裁决采纳(2026-06-19)** —— 用户授权「自主推进,能多角度确定的方案不等审批」。b-1 多角度论证充分(messages per-conv 是决策 e 技术必然必要条件,无替代);c-1 合理默认(global=3,Settings 配置后续);e-1 零改动技术细节。启动阶段2 批1。用户醒后可追认/推翻。
#### F-260619-05 任务可关联灵感(产品粒度/方向决策·todo 已登记)
- **背景**:tasks 表无 idea 关联字段;projects 已有 `idea_id REFERENCES ideas(id)` 模式。用户要任务关联灵感。todo.md 已登记(设计点+改动点+验收)。
- **决策点**(产品取舍,需用户拍板):
- **粒度**:一对一(`source_idea_id`,任务来源单灵感)vs 一对多(`related_idea_ids` JSON,借鉴 releases.task_ids)
- **存储**:tasks 加 `idea_id` 列(迁移,复用 projects.idea_id 外键)vs 关联表 `task_idea_links`(多对多,灵活复杂)
- **方向**:单向(任务→灵感)vs 双向(灵感侧反向显示关联任务列表)
- **推荐**:**tasks 加 `idea_id REFERENCES ideas(id)`**(复用 projects 模式,1对1 起步,单向,后续按需扩展)。低侵入(单列迁移 + Repo 白名单 + 工具 idea_id 参数 + 前端展示)。
- **关联**:todo.md F-260619-05(设计点详情)
- **状态**:✅ **已实施**(2026-06-20 调研确认)— tasks.idea_id 1对1 单向已落地:TaskRepo `idea_id` 字段(task_repo.rs:34 row.get / :52 INSERT / :63 UPDATE / :83 SELECT 全含)+ create_task 工具 idea_id 可选参数(tool_registry.rs:637「可选传 idea_id 关联灵感(1对1 单向)」)。复用 projects.idea_id 模式,粒度 1对1/单向/单列,符合推荐方向。前端任务卡片展示灵感来源(可选增强)待补。
#### 消息级溯源 P2 切读策略(技术决策·大改需知情)
- **背景**:消息级溯源 P0(地基 ai_messages 表 ✅ CR-10)+ P1(溯源字段 ✅ CR-12)完成。P2 切读是拆表实际启用(读写路径从 `ai_conversations.messages` JSON 切到 `ai_messages` 表)。
- **决策点**(技术策略,影响读写路径改造):
- **a 三阶段渐进**(设计推荐):Phase1 脏标记 → Phase2 双写(旧列+新表)→ Phase3 切读删旧列。安全(双写期可对比回退),有性能开销+复杂。
- **b 一次性切读**:直接切+删旧列。简单,但切读前无回退(风险)。
- **推荐**:**a 三阶段渐进**(低风险,设计推荐)。但大改(ContextManager restore/clear/compress/replace 读写路径 + save_conversation 双写 + V22 删旧列重建表),需充分测试。
- **关联**:消息级溯源 P0(CR-10 ✅)/ P1(CR-12 ✅)/ 消息拆分存储设计文档
- **状态**:🟡 待用户拍板(P2 是否现在做 + 策略 a/b)。大改建议用户知情后启动。
#### BUG-260623-03 审批 pending 无超时兜底(aichat 卡死·架构)
- **背景**:实测会话 4ae73423 末尾 advance_task 触发审批 `__PENDING__` 后,`agentic/mod.rs:1464` loop return,恢复唯一依赖用户主动 ai_approve。全库无审批超时定时器(cache.rs:31 占位标记无时间戳)。用户离开/忘记 → generating=true 永久挂起,会话卡死,用户须手动重发(且该会话 token 已大,重发易触上限)。属 aichat 中断B,非 generating 状态机卡死(generating 已收敛 GeneratingGuard)。
- **决策点**:审批 pending 超时兜底怎么实现?
- **选项**:
- a: 后端 per-conv 定时器(到期自动 reject + emit 超时,触及 AiSession 单例 + 定时器机制,最彻底)
- b: 前端倒计时提示(用户可见到期,后端不变,最小改动)
- c: 无超时(现状,靠用户手动)
- **推荐**:**b 前端倒计时**(最小改动不触 AiSession;用户可见主动处理)。a 后端定时器最彻底但触及单例大改,归 [[devflow-async-approval-concept]]
- **关联**:memory devflow-async-approval-concept / docs/05-代码审查/aichat-会话实测分析-2026-06-22.md(CR-260622-01 修正)
- **状态**:🟡 待决策
### df-miniapp 全功能审查(2026-06-23 workflow wll7qabgr + 主代补审)
> 6 区域并行审查(chat/会话页/useAiChat/连接层/组件/工程)。已**自主实施**:F1 看门狗 clearWatchdog 兜底 / F2 regenerate 守卫 / F3 flushCurrentText id 精确回填 / F9 stop 终态兜底 + 停止按钮(原无停止入口) / F21 连接状态中文文案 + 手动重连 / switch default 分支 / 二进制帧 warn / scheduleReconnect maxAttempts / 删 test 死页。以下为需决策项。
#### MINIDEC-260623-01 relay 配置层范围(F15·产品方向·分发卡点)
- **背景**:config.ts relayHost/deviceId/token 全硬编码(setConfig 零调用方,storage 未接,无设置页)。当前填测试服 wss + 本机 device_id(联调期)。分发后用户无法改连自托管中继 → 连不上。
- **决策点**:配置层做到什么程度?
- **选项**:
- a: 完整设置页(表单 + setConfig 接 storage 持久化 + getConfig 回退),用户可改 relay/device/token
- b: 仅接 storage 持久化(setConfig 真生效,无 UI,靠代码/build env 注入)
- c: MVP 接受硬编码(仅自用联调),设置页立项后续
- **推荐**:**b 至少接 storage**(成本极小让配置真生效);a 设置页 UI 视分发排期。依赖 S-260623-01「自托管」含义(c 自托管后端 → 必须 a)。
- **关联**:S-260623-01 / memory cross-end-rust-backend
- **状态**:⏸️ **暂缓(2026-06-23)** —— 用户决策:当前自用,硬编码够;分发阶段(产品终态)再做设置页。过渡期多机靠改 device_id。
#### MINIDEC-260623-02 配对绑定流程(F16·跨端大改)
- **背景**:ControlMessage.pair 类型已定义但从不发送,deviceId/token 靠用户手抄(查桌面端 KV)。无二维码配对/绑定校验链路。
- **决策点**:配对流程是否本轮做?
- **选项**:
- a: 完整配对(桌面端生成 QR → relay 校验绑定 → miniapp 扫码获 device_id/token)
- b: MVP 过渡(设置页手填 + UI 提示去哪找 device_id/token)
- c: 不做(手抄够用)
- **推荐**:**⏸️ b MVP 过渡**(a 跨端协作工作量大,依赖 MINIDEC-260623-01 设置页先落)
- **关联**:MINIDEC-260623-01
- **用户已定未来愿景(2026-06-23)**:分发阶段做完整配对授权,三步:① 设备端弹二维码 ② 小程序扫码识别并授权,双方来回点击确认 ③ 授权管理(设定授权的权限范围等)。本轮不做,留专项。
- **状态**:⏸️ **暂缓(2026-06-23)** —— 当前自用靠手抄 device_id;分发阶段按上述愿景做完整 QR 配对 + 权限范围管理(跨端 df-miniapp/df-relay/桌面端协同,专项立项)。
#### MINIDEC-260623-03 WS 重连续流策略(F10·行为差异·需拍板)
- **背景**:watchdog 在 WS 重连后不重启。重连期间 device 续推 AiTextDelta 会丢(断连窗口)或半截文本错位。当前断连 onStatus 已 reset generating + clearWatchdog(连接断肯定停),但重连后续流未处理。
- **决策点**:重连后续流策略?
- **选项**:
- a: onStatus 'connected' 主动发 load_messages 重新同步整个会话(最稳,但重置视图)
- b: 收到 AiTextDelta 时若 !generating 隐式恢复 + 补 assistant 占位(最平滑,有幽灵续流风险)
- c: 不处理(接受断连窗口该轮丢失)
- **推荐**:**c 现状**(MVP 断连窗口丢失可接受,a/b 复杂度高)。重度依赖移动端弱网再升级 a。
- **状态**:✅ **已实施 a**(2026-06-23)—— 用户决策「断网不丢消息 + 从远端拉完整」。useAiChat syncOnConnect:ws 'connected' → 发 load_messages 拉完整历史(断网期间 missed 消息恢复 + 兼修冷启动空白 P1-C)。cargo check 0 + vue-tsc 0 + build DONE。
#### MINIDEC-260623-04 审批双源状态分裂统一(F4/F5/F6/F13·渲染源决策)
- **背景**:审批状态双写——pendingApprovals 数组 + messages[].toolCalls.status。AiApprovalRequired 双写为源头,AiError/switchConversation 只清 pendingApprovals 一侧(messages 内 tc 留陈旧 pending_approval)→ 可能渲染陈旧审批按钮,点 approve 命中已失效 tool_call。chat 页按 m.toolCalls 内联渲染审批按钮,pendingApprovals 仅顶部徽标计数。
- **决策点**:统一单一渲染源?
- **选项**:
- a: 以 pendingApprovals 为准(messages tc 仅显示 status 不渲染按钮)—— 改 chat 页渲染逻辑(行为变更)
- b: switchConversation/AiError 清 pendingApprovals 时同步遍历 messages 把 pending_approval 标 rejected —— 改 useAiChat 状态清理(纯后端态,UI 不变)
- **推荐**:**b 同步清理**(最小行为变更,治陈旧按钮根因)。a 渲染源统一更彻底但 UI 改动大。
- **关联**:BUG-260623-03(审批超时,后端侧)
- **状态**:✅ **已实施 a 单一渲染源**(2026-06-23)—— 用户决策「审批断网重连恢复卡片状态」。审批卡改从 pendingApprovals 独立面板渲染(与 messages 解耦,避重连 load_messages 替换 messages 的竞态);remote_bridge 加 sync_pending 路由(读 AiSession.pending_approvals 按 conv 过滤重发 AiApprovalRequired/AiDirAuthRequired);useAiChat onStatus 'connected' 清 pendingApprovals + 发 sync_pending 重建;handleEvent 加同 id 去重防竞态重复。内联工具卡保留状态徽标/参数/结果(按钮移面板)。cargo 0 + vue-tsc 0 + build DONE。
#### MINIDEC-260623-05 会话页管理缺口(删除/重命名·需后端命令)
- **背景**:conversations/index.vue 仅列表/切换/新建/下拉刷新。无删除/重命名(需后端 delete_conversation/rename_conversation 命令 + remote_bridge 路由,当前无)。
- **决策点**:miniapp 是否需要会话管理?
- **选项**:
- a: 本轮加(后端命令 + bridge 路由 + 会话页长按菜单)
- b: 暂不做(用户回桌面端管理,MVP 仅查看/切换)
- **推荐**:**⏸️ b 暂不做**(miniapp 定位轻量操作终端,会话管理桌面端足够)
- **状态**:✅ **重命名已实施 / 删除暂缓**(2026-06-23)—— 用户决策「小程序对齐桌面端能改会话名」。remote_bridge 加 rename_conversation 路由(调 ai_conversation_rename + 推 AiConversationList 刷新);useAiChat renameConversation 方法(乐观本地更新);conversations/index.vue 长按会话 uni.showModal 编辑。删除会话暂不做(桌面端管理)。cargo 0 + vue-tsc 0 + build DONE。
#### MINIDEC-260623-06 心跳/历史替换协议(F8/F20·跨模块·低优先)
- **背景**:(F8)心跳活性检测依赖「任意入站消息」,低活跃场景每 ~60s 误判半开死连接触发无谓重连(relay 无 pong);(F20)AiMessageHistory 整体替换会丢弃正在进行的乐观气泡(device 主动推历史路径难区分 load 响应)。
- **决策点**:是否本轮改 relay 协议?
- **选项**:
- a: relay 加 pong + 历史事件加 load_id/sync_source flag(跨模块改 df-relay + 后端 events)
- b: 前端缓解(放宽 DEAD_FACTOR / 「仅本地空才替换历史」启发式,语义脆弱)
- c: 暂缓(MVP 低频空闲场景可忍)
- **推荐**:**⏸️ c 暂缓**(跨模块改动 ROI 低)
- **状态**:⏸️ 暂缓
#### MINIDEC-260623-07 regenerate 零调用方 + 备份组件漂移(P3 收尾)
- **背景**:(1) useAiChat.regenerate() 零调用方(全死,已加 generating 守卫防御);(2) MdView.vue/MentionInput.vue 因绕工具组件解析 bug 被 chat 页内联,源文件保留备用但已与内联实现漂移(MdView 无 mdCache、MentionInput 是 MVP 占位)——「拆回」时会引入旧实现。
- **决策点**:regenerate 加 UI(重发按钮)or 删?备份组件同步/删/保留?
- **选项**:
- a: regenerate 加重发按钮 + 备份组件同步内联实现(或删)
- b: regenerate 删减负 + 备份组件保留标注释(预留工具 bug 修复后拆回)
- **推荐**:**b**(regenerate 删减负,备份保留预留意图)。或 a 视移动端重发需求。
- **状态**:✅ **随 P1-F 选 a**(2026-06-23)—— 🟡 收尾批给 regenerate 加「重发」UI 入口(对齐桌面端),故保留函数不再删;备份组件(MdView/MentionInput)保留预留注释(绕工具解析 bug,未来拆回)。
---
## workspace_root 分发适配(编译期 CARGO_MANIFEST_DIR 写死,跨机器/跨平台失效)
**背景**:`workspace_root_path()`(state.rs)/ `workspace_root()`(tool_registry.rs)/ `workspace_root_str()`(mod.rs)三处同源用 `env!("CARGO_MANIFEST_DIR")`(编译期写死编译机源码路径)。DevFlow 打包分发后:
- 用户机器无编译机路径(如 `E:\wk-lab\devflow`)→ workspace_root 失效
- 跨平台(Windows/Linux 各发行版)各自编译机路径写死,分发到不同机器/平台均失效
- 影响:相对路径锚点(check_path_authorization / resolve_workspace_path_impl)+ 默认白名单(default_with_root)+ run_command 默认 working_dir 均依赖此值,分发后指向不存在路径 → AI 文件工具全部失效
**当前(开发机自用)**:CARGO_MANIFEST_DIR = 开发机 DevFlow 源码,AI 访问源码合理。仅开发期有效。
**根因**:workspace_root 语义错位 — 当前 = DevFlow 自身源码目录(开发 DevFlow 的语义);但 DevFlow 分发后是"用户用它开发自己项目的工具",workspace_root 应 = 用户项目(动态,非编译期)。
**方向(运行期动态 workspace_root)**:
- **a current_exe 安装目录**:`std::env::current_exe().parent()`。分发后 = 安装目录。但安装目录非用户工作空间(AI 应访问用户项目,非 DevFlow 安装目录)。语义仍错。
- **b 用户项目绑定(推荐方向)**:workspace_root 概念淡化,默认白名单 = 用户绑定项目(projects.path,reload_allowed_dirs 已读),相对路径锚 = 当前活跃项目目录。无固定编译期 root。最贴合"用户用 DevFlow 开发自己项目"语义。需改 check_path_authorization / resolve 锚活跃项目(当前锚固定 workspace_root)。
- **c 用户配置工作空间**:KV workspace_path,用户首启配置。灵活但需 UI + 首启引导。
- **d 混合**:debug 开发期 CARGO_MANIFEST_DIR(源码)/ release 分发期 current_exe 或用户项目(`cfg!(debug_assertions)` 区分)。过渡方案。
**决策点**:
- workspace_root 语义(DevFlow 安装目录 vs 用户项目 vs 用户配置工作空间)
- 相对路径锚点(固定 root vs 活跃项目)
- 是否区分开发期/分发期(cfg!(debug_assertions))
- docs/kms 开发机暴露(随 b/c 自然解决:无固定 root 则 docs/kms 不在默认白名单)
**关联**:F-260619-03 去固定根(已删 is_authorized 硬编码放行)/ projects.path 自动授权(reload_allowed_dirs)/ memory [[devflow-project-path-binding]]
**状态**:🟡 待决策(workspace_root 运行期动态方案 a/b/c/d)。**分发前必须解决**(否则分发后 AI 文件工具全部失效)。
**注**:授权弹窗侧三档(once 本次单次 / session 当前会话 / always 始终)已于 2026-06-24 落地(F-260619-03 Phase B 演进,AllowedDirs 加 once 层 + 弹窗加"当前会话"按钮,详见 todo + 待审查 CR-260624-01)——**授权机制侧就绪**。本节待决策的是**相对路径锚点**(固定编译期 root vs 活跃项目),非授权机制。
**2026-06-25 弱化决策(用户)**:方向**去掉"活跃项目/根据地"概念抽象**——active_workspace 全局缓存动态锚曾试加(state.rs OnceLock+SyncRwLock + reload_active_workspace KV active_project_id)后撤回,用户明确不要此层。workspace_root 变量**暂留**(不删,resolve 相对锚/trust_key/run_command working_dir 仍引用),**弱化其默认依赖**。实质方案二选一分发前定:① 去默认白名单(default_with_root 不硬塞 workspace_root,工程根靠 projects.path 自动授权)② 去相对锚(AI 改绝对路径,相对路径不 join)。当前:逻辑不动,变量保留。
**2026-06-23 进展(BUG-260623-01)**:实测会话 6acb7f9b 暴露 write_file/append_file/rename_file 父目录校验**误用 workspace_root**(tool_registry.rs:1112/1418/1555 原用 `starts_with(workspace_root())`)→ 用户授权的其他项目目录(ai-news 等)parent 不 starts_with devflow 源码目录 → 误拒「禁止在项目目录之外创建目录」(用户授权了仍拒)。**已修**:三处改用 `allowed_dirs.is_authorized(parent)` 脱离 workspace_root。**仍写死残留**(待本决策 a/b/c/d 根治):delete_file:1482 trash 目录 / resolve_workspace_path_impl:380 相对路径 join / run_command:1791 working_dir 默认。
---
## F-260619-03 路径授权政策:工程内默认免授权(用户 2026-06-20 指令)
**用户政策指令**:"默认直接访问,明确知道无权限才申请"。
**背景**:F-260619-03 Phase C 去固定根(b22e9ae)后,`reload_allowed_dirs` 在 KV allowed_dirs 或 projects.bind_directory 非空时**丢失 workspace_root**,致工程内路径(如 docs/)误弹窗。用户反馈"本来就有访问权限,为什么还来申请"。详见 todo BUG-260620-05。
**决策点(语义范围澄清)**:
- **层1 工程内默认免授权**(dev 自用足够):`reload_allowed_dirs` 无条件保留 workspace_root(state.rs:618 去 `all_dirs.is_empty()` 包裹)。工程内路径默认放行,workspace_root 外非白名单仍弹窗。1 行修复,确定性 bug(注释承诺失配)。
- **层2 全局默认放行**(语义翻转):`is_authorized` 改黑名单制——非黑名单路径默认放行,仅明确敏感(系统目录/凭据)拒。等于实质去掉白名单授权机制。安全风险大(任何非黑名单路径 AI 可访问),涉 P0 去固定根决策方向推翻。
**与 P0 去固定根冲突**:P0(CR-260620-01 ⑤)决策"去掉代码硬编码固定放行,用户从白名单删工程根后工程根也需授权"。层1 恢复工程内免授权=部分推翻 P0。但 P0 "用户删 root" 语义当前未落地(set/get filter root,root 不可删),层1 不破坏现有能力。
**与分发适配衔接**:层1 workspace_root = CARGO_MANIFEST_DIR(编译期写死),开发机自用有效;分发后失效则依赖 projects.path 自动授权(reload 已读 project_dirs)。分发适配见上节"workspace_root 分发适配"方案 b。
**倾向**:层1(满足 dev 自用 + 不破坏安全 + 修注释承诺失配的确定性 bug)。层2 若需全局放行另立专项。
**状态**:🟡 待用户拍板(层1 确定性 bug 可直改 1 行;层2 语义翻转需明确安全边界)。
---
## F-09 streaming/currentText 改 per-conv(消息重叠/多会话串扰根治)
**背景**:BUG-260624-01 消息重叠核心修复后,论证 workflow 边界角度指出残留根因——`streaming`/`currentText` 是 store 全局单例(非 per-conv),F-09 多会话并发下 A 后台生成(streaming=true)+ 切 B 会话,B 末条 AI 气泡命中 `isLastAi&&streaming&&currentText` 会渲 A 残留 currentText。当前修复(flushCurrentText 自清 + activeConversationId watch 清 streamingBlocks)已大幅收窄残留窗口,但单例根因未除。
**决策点**:是否立项 per-conv 化(streaming/currentText/streamingBlocks 改 Map<convId,...>)?
- **a 立项根治**:store 改 per-conv Map,所有读写点改。大改(涉 ai.ts store + useAiEvents/useAiStream/useAiConversations/MessageList 多处),对齐 [[aichat-arch-extensibility]] AiSession 单例未动 + [[fe-arch-tech-debt]] status 无 union。
- **b 暂缓(当前缓解够用)**:自清 + activeConv watch 已覆盖主路径(新轮/切会话/结束清),残留仅极端并发场景(A 后台 streaming + 切 B)。等 B 路线多会话并发([[aichat-b-route-parallel-multiround]])正式推进时一并 per-conv。
**多角度论证(自主决策依据)**:
- 根治性:a 一次性消除单例串扰族 bug;b 缓解主路径,极端并发残留。
- 改动面:a 大(store + 5 composable + MessageList),回归风险高,需全链路测;b 零额外改动。
- 时机:b 与 B 路线多会话并发同批做更合理(那时 per-conv 是前置),现在单独做与 B 路线重复拆改。
- 当前用户场景:自用单会话为主,多会话并发(A 后台 + 切 B)非高频。
**倾向**:**⏸️ b 暂缓**(当前修复缓解有效 + per-conv 是 B 路线大改 + 与多会话并发同批更合理)。
**状态**:🟡 待拍板(若用户多会话并发场景频繁 → a 立项;当前单会话为主 → b 暂缓随 B 路线)。
---
## 已决归档
按月归档(随时间增长追加月份文件,防主文件膨胀):
- [2026-06.md](./07-项目管理/待决策归档/2026-06.md) — 2026-06 已决策/已实施/已排期/已解决历史(③类产品取舍 12 项 / ④类设计方向 6 项 / 重投入排期 8 项 / ④类续 5 项 / C类已解决 2 项)
> 新月份拍板项累积时,新建 `YYYY-MM.md` 承载。