Files
DevFlow/docs/02-架构设计/功能决策记录-2026-06-14.md

78 KiB
Raw Blame History

功能决策记录

日常开发中对各功能做的需求规格 + 设计决策规格(功能粒度,补 Phase 1 架构决策 之下的实现层选择)。聚焦「要做什么 / 为什么这么定」,便于日后回溯。

创建2026-06-12 | 范围Sprint 510 | 维护:随开发追加

约定

判断标准3 个月后回看,这条是否仍影响对系统/功能设计的理解?是 → 留本文档;否 → 分流。

本文档只记两类

  • 设计决策规格 已落地 / 🚧 待实测 / 📐 设计未实施)——「为什么这么定」。三要素:决策 → 原因/取舍 → 状态。来源标 [Sprint N][日期]
  • 需求规格 / 待办📋)——「要做什么 / 为什么需要」。与 PROGRESS 流水区分:这里记「要做什么 / 为什么需要」PROGRESS 记「做了啥」。

经验性内容(踩坑 / 约定 / 技巧 / bug 排查教训)→ 经验记录-2026-06-14.md老条 / 纯流水 / UX 微调 / 已被取代功能决策记录-归档-2026-06-14.md

记录规则见 文档记录规范

人机协同设计基准

AI coding 下的「过度设计」判断基准 [2026-06-13]

  • 决策:项目为一人开发 + 全程 AI coding人定方向/审查AI 实现),代码被 AI 反复读写。权衡设计时采用新基准——AI 反复读写的代码,「结构清晰」和「隐性耦合显式化」权重高于传统判断;但「过度抽象」(多层 trait/Builder/工厂)仍不做,因 AI 读简单直白代码 > 读层层抽象。
  • 原因/取舍:① AI 每次理解代码靠注释和结构比人更依赖1600 行单文件(如 AiChat.vue消耗大量 context拆分反而降低 AI 理解成本;② 隐性依赖(如分离窗口 localStorage 跨 webview人凭经验避开、AI 易踩坑。故:组件拆分从「不做」升为「值得做」;隐性耦合早修或显式标注。③ 规模没到的优化list_all LIMIT、白名单拆表仍按数据量客观判断不因 AI coding 而变。
  • 状态📐 基准原则(指导后续取舍)

AI Chat 可靠性

流式可靠性三重保险 [Sprint 6 + 2026-06-13]

  • 决策:① reqwest Client 加 connect_timeout(30s)不设请求总 timeout;② stream_llmtokio::time::timeout(120s)单个 stream.next()idle 间隔),不包整个流;③ 前端 stores/ai.ts 加 streaming watchdog——发送启动 60s 计时,收到 AiTextDelta/工具事件/审批结果重置AiApprovalRequired 暂停审批等待不计AiCompleted/AiError 清除60s 无活跃事件则置 streaming=false + push 错误「响应中断」。
  • 原因/取舍:连接阶段防无限 hang总 timeout 会误砍流式长生成任务流式可持续数分钟。idle 120s 防「连上后中途静默」无限 hang只卡单 chunk 间隔,不卡总时长。前端 60s 独立计时(短于后端 120s双保险——后端任何路径漏发收尾崩溃/事件丢失/agent loop 异常退出)前端永久 streaming=true 卡死。审批等待暂停(不计超时)避免误判用户思考。
  • 边界审批组件未渲染见「需求与待办·审批可见性缺口」AiApprovalRequired 暂停后永久卡watchdog 救不了,需审批可见性兜底。
  • 状态 Sprint 6 + 2026-06-13

断连丢弃残缺响应

  • 决策:维护 finished_received 标志;流尽未收到 finished 信号 → emit AiError 并丢弃残缺响应,不当完整入库
  • 原因:防脏历史污染对话记录(半截回复入库后无法续接)。
  • 状态 Sprint 6

停止生成:保留已生成文本

  • 决策AiSession.stop_flag: Arc<AtomicBool> + 多检查点响应;停止后保留已生成文本
  • 原因:用户主动停止 ≠ 丢弃成果已输出内容有价值。idle无输出时最多等 120sP2 可用 tokio::sync::Notify 优化为绝对即时)。
  • 状态 Sprint 6运行时待实测

切对话:从「拒绝切换」演进到「不中断路由」

  • 决策Sprint 6 生成中拒绝切换(防 active_conversation_id 被改致旧 loop 串台写库)→ Sprint 8 改为后台对话按 conversation_id 路由,生成中可切换不打断
  • 原因:拒绝切换体验差;后端给所有 event 加 conversation_id + spawn 前快照 conv_id + 前端按 id 路由(后台对话事件不污染当前视图),既不串台又不打断。
  • 状态 Sprint 8部分场景待实测

AI Chat 工具调用与审批

Agentic Loop 最多 10 轮

  • 决策run_agentic_loop 上限 10 轮(MAX_AGENT_ITERATIONS)。
  • 原因:防失控循环;单链 ReAct 10 轮覆盖绝大多数任务。超出需规划式B 路线)。
  • 状态 Sprint 5

风险门控Low 自动 / Medium+High 审批

  • 决策:工具按 RiskLevel 分级Low 自动执行Medium/High 暂停等人工审批。
  • 原因:读操作放行,写/删操作把关——可靠性 vs 效率的平衡点。
  • 状态 Sprint 5

tool_calls 按 index 排序

  • 决策assistant 消息与 tool_result 两处均按 index 排序。
  • 原因:消除 HashMap 迭代乱序致多工具结果错位。
  • 状态 Sprint 6

路径校验:拒 .. 遍历 + 扩敏感目录

  • 决策:正斜杠→反斜杠规范化 + 拒 .. 路径遍历 + 扩 .aws/.gnupg
  • 原因最小加固防越权读写根治级workspace 白名单 + canonicalize待边界明确后再做。
  • 状态 Sprint 6边界加固待续

list_directory 递归防爆:噪音目录剪枝 + 条目上限 + skip_noise_dirs 开关 [2026-06-14]

  • 决策list_dir_recursive 递归时跳过噪音目录(.git/node_modules/target/dist/build/.next/.cache/__pycache__/.venv/venv/.idea)——列出但不深入内部;硬上限 1000 条 + truncated 标志;默认 max_depth 3→2skip_noise_dirs 参数(默认 true)。
  • 原因AI 广扫项目根传 recursive:true 时,.git/node_modules/target 铺平致 13782 项塞进对话 messageUI 卡 + token 爆)。剪枝防爆炸,但保留访问能力:① 噪音目录仍列出(看得见存在 + 大小);② 想看内部时 list_directory 直接指向该目录depth=0 起算),或传 skip_noise_dirs:false 强制递归进去(仍受 1000 上限 + truncated 保护,适合看编译产物 dist / 运行结果 target 做比对。1000 上限 + truncated 让"想全扫"退化为"分层定点查",不丢信息。
  • 状态 2026-06-14 落地cargo check 通过)

max_tokens 8192 + length 算 finished

  • 决策max_tokens 4096→8192finish_reason="length"(截断)纳入 finished。
  • 原因:大任务输出撞 4096 上限被误判断连、丢弃整段响应8192 贴合实际,截断视为正常完成。
  • 状态 Sprint 6

审批:删全屏 Modal 保留行内卡片 [Sprint 8]

  • 决策:移除全屏 Tool Approval Modal保留工具卡片内联审批按钮。
  • 原因:全屏 Modal 打断对话流,行内审批更轻量。
  • 状态 Sprint 8

AI Chat Provider 协议

provider_type 路由 OpenAI / Anthropic

  • 决策:新增 anthropic_compat.rs 实现 Anthropic Messages APIprovider_type 分发到 OpenAICompat 或 AnthropicCompat分发处用 Box<dyn LlmProvider> trait object。
  • 原因GLM 等订阅端点走 Anthropic 协议(x-api-key + 顶层 system + 必填 max_tokens + SSE content_block统一 Provider trait 屏蔽差异,上层 Agentic Loop / AiNode 零改动(不感知协议)。
  • 状态 Sprint 8用户实测对话流式 OK

端点 URL 三段智能拼接

  • 决策messages_url() 按 base_url 末段判断——已含 /v1/messages 直用;以 /v1 结尾补 /messages;仅域名(如 …/api/anthropicapi.anthropic.com)补 /v1/messages
  • 原因GLM 订阅端点 open.bigmodel.cn/api/anthropic 与 Claude 官方 api.anthropic.com 约定不同(前者无 /v1后者需补不强制用户填全路径降低配置门槛。GLM 端点已实测。
  • 状态 Sprint 8

max_tokens 必填兜底 4096 / tool_result 连续合并为一条 user

  • 决策:① Anthropic 协议 max_tokens 必填(协议无默认),DEFAULT_MAX_TOKENS=4096 兜底OpenAI 协议 max_tokens 可选,缺则报错);② 连续多条 role=Tooltool_result累积遇非 Tool 消息 flush 为单条 user 消息含多个 tool_result 块。
  • 原因:① 统一兜底避免上层每个调用点都要传值(与 OpenAI Provider 的 8192 上限独立,此处仅缺省兜底)。② Anthropic 要求 tool_result 必须在 user 角色内;多工具并发结果合并为一条 user 而非一对一,贴合协议「一回合一组结果」语义,减少消息碎片。
  • 状态 Sprint 8

默认标识is_default 落库为真相源 [Sprint 10 → 2026-06-13]

  • 决策ai_set_provider 互斥写 DB目标 is_default=true、其余 false,仅写变化记录);ai_save_provider 新建时若全表尚无默认则自动设为默认(首个);ai_list_providers 直接返 DB 值。session.active_provider_id 降为运行时缓存,由 set_provider 同步,重启清零不影响——get_active_provider 兜底取 DB is_default
  • 原因/取舍Sprint 10 原 active 作真相源 → 致「重启默认丢失」bugactive 是内存态重启清零,而 is_default 字段恒写 false重启后无默认可恢复。is_default 字段本为持久化默认而存在回归本职最自然session 持久化需额外存储,重复造轮子。互斥写库保证「唯一默认」语义。
  • 边界:互斥写库逐条 update_full 不加事务——repo 未暴露事务接口;桌面单用户无并发触发,失败即报错、重试自愈。多用户/高并发场景需给 repo 补 execute_transaction
  • 状态 2026-06-13 落地(重启保默认 / 互斥写库 / 首个自动默认实测待补)

📋 delete_provider IPC 缺失(前端假删除)[Sprint 10]

  • 需求Settings 删 Provider 当前只前端 filter 移除,不调后端(无 ai_provider_delete 命令),重启后配置回归。
  • 原因交互欺骗——用户以为删除成功DB 实际未动。需补 ai_provider_delete IPClib.rs 注册 + ai.rs 实现 + 前端真调),并加二次确认。
  • 状态📐 待实施 → Sprint 10 已实现(ai_delete_provider 命令 + 删默认清 active + 自建 confirmDialog 二次确认)

模型能力与路由Model Capability & Auto-Routing

能力声明:复用 ai_providers.models JSON 字段,不建新表 [2026-06-13]

  • 决策:每个 Provider 下可选模型的能力声明(模态/功能/成本等级)存入已有 ai_providers.modelsJSON 数组),不新建独立表。新增 crates/df-ai/src/model_capability.rs 定义 ModelCapabilityname / modalities / functions / max_tokens / cost_tier+ TaskRequirements + Modality / CostTier 枚举。
  • 原因/取舍:模型能力是 Provider 配置的内在属性,非独立实体——无生命周期管理、无跨表 JOIN 需求JSON 嵌入单行足够Provider 通常 1-5 个);models 列已在 V9 建表且全链路预留,复用零 schema 变更;独立表需外键/级联/JOIN对桌面应用过度工程备份迁移友好配置自包含一行。代价无法 SQL 查询「所有有 vision 的模型」,但此查询当前和近期均不需要。
  • 状态📐 设计未实施Phase 1数据模型 + 场景级路由)

路由层:纯函数 ModelRouter重写现有骨架 [2026-06-13]

  • 决策:重写 crates/df-ai/src/router.rs 已有但空的 ModelRouter——从 TaskRequirements + Provider model_pool → 按硬性要求筛选候选 → 按 cost_tier 升序取最便宜。路由是同步纯函数(无 I/O、无全局可变态可单测。7 个 LLM 调用点统一接入。override_model 字段支持用户显式指定(聊天手动切)和工作流节点 config.model节点作者指定两种覆盖优先级最高。
  • 原因:路由是确定性计算(静态配置→模型名),无需 async/service 化;纯函数可单测;统一入口避免散装 if-else。
  • 各调用点路由策略:主对话 chat(has_image)→Standard/Premium标题生成 title_generation()→Economy 最便宜;知识提炼 knowledge_extraction()→Economy/Standard工作流 AiNode workflow_node() + override=config.model→节点指定优先Embedding (×2) 不走路由器(独立路径,不同模型类)。
  • 向后兼容models=None(老记录)→ model_pool 空 → 所有 route 返回 default_model → 行为不变。
  • 状态📐 设计未实施Phase 1

Embedding 不进通用路由器 [2026-06-13]

  • 决策Embedding 模型不走 ModelRouter继续走独立路径KnowledgeConfig.embedding_model + embedding_provider_id)。
  • 原因Embedding 是完全不同的模型类——API 不同(/v1/embeddings vs /v1/chat/completions)、用途不同(向量化 vs 生成)、通常更小更专用。混入通用模型池会混淆用户并增加路由分支复杂度。
  • 状态📐 设计未实施Phase 1 确认不动 embedding 路径)

分阶段实施路线 [2026-06-13]

  • Phase 1(本次):数据模型 + ModelRouter 重写 + 7 调用点接入 + Settings 模型池编辑 UI + AiChat 模型下拉。ChatMessage.content 保持 String 不改。
  • Phase 2后续多模态消息——ChatMessage.content: String → Vec(Text/Image);前端粘贴/拖拽图片vision 模型自动路由。
  • Phase 3后续Agent 内智能路由——Agentic Loop 每轮按子任务构造不同 TaskRequirements成本预算控制模型级联降级跨 Provider 搜索。
  • 状态📐 设计未实施

📋 模型能力系统 — 完整改动文件清单 [2026-06-13]

  • 后端 Rustcrates/df-ai/src/model_capability.rs新增 ModelCapability / TaskRequirements / Modality / CostTier/ router.rs重写 ModelRouter 匹配逻辑)/ lib.rsre-export/ df-storage/src/migrations.rsV10 版本号推进,无需 ALTER/ src-tauri/src/commands/ai.rs7 调用点加 routerai_save_provider 加 models 参数;新增 ai_set_chat_model_override
  • 前端 TS/Vuesrc/api/types.ts(新增 ModelCapability / Modality / FunctionCapabilities / CostTier 类型)/ src/api/ai.tssaveProvider 加 models 参数;新增 setChatModelOverride()/ src/stores/ai.tsavailableModels / activeModelOverride 状态 + setModelOverride action/ src/views/Settings.vueProvider 表单增加模型池编辑区)
  • 状态📐 待实施Phase 1 全量清单)

灵感模块(评估闭环)

启发式评分维度

  • 决策:三维固定 5.0 → 内容启发式priority / 描述充实度 / tags / 中英关键词clamp 0-10。
  • 原因:固定值无区分度;启发式基于 idea 内容给差异化评分。
  • 状态 Sprint 9启发式未接 LLM

对抗评估:启发式 fallback 待接 LLM

  • 决策:正反方论点/evidence 基于真实 idea 内容生成confidence 由评分驱动;未接 df-ai LlmProvider。UI 诚实标注——评估区标题加「启发式」黄标(.eval-mode-tag),对齐实现深度避免名实不符,接 LLM 后摘除。
  • 原因先打通评估闭环LLM 生成论点 + 启发式 fallback 为后续增强。
  • → 接入方式已定:走全局 AI trait 下沉(见 crate 治理 — AI trait 下沉拆 df-ai-core)。evaluate()LlmProvider 注入参数,启发式降级为 fallbackF-03 原 A/B/C 选型据此收敛为「全局统一 trait」。
  • 状态📐 设计未实施LLM 接入)

前后端标签对齐

  • 决策recommendation 全小写空格(后端原 "With Resources" 不匹配前端 map keyassessmentClass 映射到 CSS 类名(.immediate/.soon/...)。
  • 原因:大小写/类名不一致致中文标签不显示、badge 无色。
  • 状态 Sprint 9

评分 0-10crate→ 0-100前端IPC 缩放 + 多字段写回用单事务 [Sprint 9/10]

  • 决策:① crate 内 IdeaScores 维持 0-10IPC 层 evaluate_idea 组装 scores JSON 时 *10 缩放为 0-100并用中文维度键可行性/影响力/紧急度/综合)。② evaluate_idea / promote_idea 写回想法用 update_full(单事务覆盖整条记录),放弃多次 update_field
  • 原因:① 前端雷达图直接当百分比渲染、零前端改动crate 内 0-10 符合评分直觉IPC 层做单位适配。② 多次 update_field 各自独立连接中途失败致数据半成品update_full 原子。
  • 状态🚧 Sprint 9/10编译/构建通过,未 tauri dev 实测)

想法立项promotion

复用 df-project 领域层crate do_promote 留纯决策 TODO [Sprint 10]

  • 决策promote_idea IPC 复用 df_project::manager::ProjectManager::create_from_idea 构造项目实体 + 映射 ProjectRecord 持久化 + update_full 回写想法df-ideas crate 内 IdeaPromoter/do_promote 保留纯决策 TODO不真正创建项目。
  • 原因crate 不依赖 df-storage/df-project避免循环依赖、保持可单测手动立项无需 Auto/Manual/SemiAuto 策略判断(用户点即确认),副作用放 IPC 组合,与 evaluate_idea 同模式crate 纯决策留待自动/半自动晋升场景复用。
  • 状态🚧 Sprint 10编译/构建通过,未 tauri dev 实测)

promoted_to 非空拒绝重复立项 [Sprint 10]

  • 决策promote_idea 取想法后校验 promoted_to 已存在则返回错误,不创建新项目。
  • 原因:防同一想法多次点「立项」生成多个项目;幂等保护。
  • 状态🚧 Sprint 10

项目管理(删除 / 回收站)

项目删除软删回收站deleted_at + 应用层级联),非物理删 [2026-06-13]

  • 决策:删项目改为软删——projectsdeleted_at TEXTV11 迁移),delete_projectdeleted_at(进回收站,可恢复);list_projects 过滤 deleted_at IS NULL;回收站(list_deleted_projects)可「恢复」(清 deleted_at或「彻底删除」purge_project 事务级联物理删 branches→releases→tasks→projects不可逆。子表软删时不动FK 仍满足,项目数据完整保留待恢复。
  • 原因/取舍:① 用户要求「可恢复」——纯 CASCADE 物理删不可逆,误删难挽回;软删 + 回收站给反悔余地。② SQLite ALTER TABLE 改不了已有表 FK 约束,给老库 projects 加 ON DELETE CASCADE 须重建表(高风险),故不走 DDL 级联,改应用层级联purge 时事务内顺序删子表),语义等价且可测、不依赖 PRAGMA foreign_keys。③ 软删只标记 projects 行、子表不动——恢复时项目连同历史任务/分支/发布完整还原。④ 两级风险分级:日常软删可逆 / 回收站 purge 二次确认后物理删不可逆。
  • 边界ProjectRecord 不带 deleted_at 字段,纯靠 SQL WHERE deleted_at IS NULL 过滤models/types 零变更。ai.rs build_system_prompt 同步改用 list_active(防软删项目泄漏进 AI 上下文)。soft_delete/restore 守卫对称,重复操作幂等。
  • 状态 2026-06-13 落地V11 迁移 + ProjectRepo 5 方法 + 3 IPC 命令 + 回收站 modal + 删除入口cargo check + vue-tsc + 11 integration test 全绿)

项目管理(目录绑定 / 技术栈探测)

项目绑定真实代码目录:扩 ProjectRecord + df-project scan [2026-06-13]

  • 决策ProjectRecordpath(绑定目录绝对路径)+ stack(技术栈 JSON 数组字符串两字段V12 迁移nullable技术栈探测逻辑放新建 df-project/src/scan.rs::detect_stack(纯函数,浅读根目录标志文件识别 rust/go/python/java/csharp/vue/react/angular/svelte/next/vite/typescript/node/tauricommands 层薄封装 4 命令(scan_project_stack/check_path_binding/relocate_project_path/check_path_existscheck/relocatecanonicalize 规范化路径防绕过重复检查。新建项目可选绑定目录→自动探测栈,详情页支持重定位 + 目录失联检测 + 防重复绑定。
  • 原因/取舍:① 扩 df-storage ProjectRecord 而非激活 df-project ProjectContext 空壳——ProjectContext 虽早设计 root_path/tech_stack/repo_url/ai_context 字段,但 manager.rs 标注 TODO 从未接存储/运行时;激活需新建 project_contexts 表 + 填充暂不需要字段,第一步过重,守 YAGNI。ProjectRecord 是实际运行链路,直接扩最快见效。② scan 放 df-project 而非 commands 层——ProjectContext.tech_stack 本就是 df-project 职责字段scan 是其天然能力且可被 df-ai/df-workflow 复用,放 commands 变一次性代码。③ migration nullable——老项目 path/stack=NULL 零影响。④ 一致性原则:先在「新建流」验证,第二步「导入历史项目」复用同一套 scan/relocate/checkBinding。
  • 边界path 规范化canonicalize仅用于比较存库保留用户输入的原始可读路径。程序化创建项目想法晋升、AI 工具path/stack = None不绑定目录df-projectProjectContext 刻意未激活ai_context/repo_url 等暂留空)。
  • 状态 2026-06-13 落地V12 迁移 + detect_stack + 4 IPC 命令 + 选目录/查重/卡片栈 + 重定位/目录状态cargo build + scan 4 单测 + vue-tsc 全绿)。📋 导入历史项目(第二步):复用 scan/relocate/checkBinding加 monorepo 子目录识别 + README 首段抽 description + 批量。

导入/绑定项目 AI 扫描填信息:规则探测兜底 + LLM 增强,采样与 LLM 调用分层 [2026-06-14]

  • 决策:导入/绑定项目时规则 detect_stack(快/免费/准)必跑兜底 + LLM 分析采样README+目录树+清单,不读源码)产出 description 摘要与 stack 细化LLM 失败降级纯规则。采样逻辑放 df-project纯 IOLLM 调用放 commands 层。
  • 原因/取舍:① 规则兜底保证 LLM 不稳定时仍有基础信息LLM 只补规则搞不定的摘要。② 采样与 LLM 分层——采样纯 IO 属 df-project 职责可复用LLM 调用依赖 df-ai放 commands 使 df-project 保持无 LLM 依赖(防循环)。③ 不读源码控 token+隐私。④ 结果预览让用户把关防 LLM 瞎编。
  • 状态 2026-06-14 落地scan_project_with_ai 命令 + 前端 AI 扫描预览;编译/单测/类型全绿)。

导入历史项目scan 第二步设计description 走 LLM + 采样保留内容图 + monorepo 一层 + 批量并发 [2026-06-14]

  • 决策F-06 = scan 第二步,选根目录 → 发现项目(含 monorepo 子目录)→ 勾选批量导入。六点收敛:① description 走 LLM 复用 scan_project_with_aicommand 层 complete不做纯规则抽取(跨 README 格式 brittle采样改进——ProjectSampleimages: Vec<ImageRef{alt,src}>readme 剥 frontmatter/TOC/纯徽章行后截 ~8KBSAMPLE_README_MAX=2000 偏小粗暴),保留内容图 markdown 原样;③ image 多模态条件化——当前 ChatMessage.content:StringF-260614-05 未做)走纯文本降级,采样层先不丢 image 引用留接口Phase 2 上线后读 base64 喂 visionmonorepo 一层识别is_monorepo 检 pnpm-workspace/lerna/turbo/nx + package.json workspacesdiscover_projects 展开 packages/*/apps/* 直接子目录,detect_stack 空的过滤);⑤ 批量流程——scan_directory_for_projects 规则发现(快、不跑 LLM+ 标已绑定项;用户勾选后 import_projects_batch 对勾选项并发 LLM 抽 descriptionllm_concurrency 双层 permit 限流)+ 复用绑定入库,非原子逐项独立;⑥ 对称改进——抽内部 create_with_bindingcreate_project + import batch 共用「校验+防重+探测+insert」缓解决策记录:211 TODOrelocate 不并入update 非 insert
  • 原因/取舍:① description 纯规则抽首段会撞徽章墙/多语言引导/TOC——抽出来是噪音语义抽取归 LLMimage 不能粗暴跳过(修正原 plan 错把 image 归噪音)——架构图/截图是 description 关键信息一张顶千字只跳徽章shields.io/badge.fury 等域 + build/version/license/coverage 关键词);③ 采样不丢 image = F-06 不被 F-260614-05 阻塞但不留遗憾,两者配套;④ 批量只对勾选项跑 LLM远少于发现全量平衡速度质量⑤ 「子代理」= 轻量 complete 复用现有 scan_project_with_ai 路径,非 aichat ReAct 重 agent批量精修不值得上多轮
  • 边界:导入项目 status 默认 planning(对齐 create_project导入后手改预览表格只读name/desc/stack/已绑定标记,不展示 image导入后详情页改不关联 idea批量无实时进度条最终 toast 汇总(导入 N/跳过 MLLM 全失败 description 留空让用户手填(不喂噪音)。
  • 状态📐 2026-06-14 设计定稿待实施6 决策经 3 轮讨论收敛,修正原 plan 两处草率:纯规则 description + 跳 image📋 实现时df-project 加 discover_projects/is_monorepo + collect_sample 扩 images + 徽章过滤commands 加 scan_directory_for_projects/import_projects_batch + 抽 create_with_binding;前端 Projects.vue 加导入 modal + i18nscan.rs 单测(采样剥噪音/image 收集/monorepo/discover

AI 工具绑定目录bind_directory 专用工具 + 工具层白名单同步 + prompt 禁冒充 [2026-06-14]

  • 决策:① update_project 工具白名单补 path/stack同步 db 新字段);② 新增 bind_directory 专用工具(绑定目录不走通用 update③ 系统 prompt 加约束:工具失败须明说,禁用替代操作冒充原意图成功。
  • 原因/取舍:① review AI 对话发现 update_project(path) 被工具层白名单拒db 字段加了但工具层漏同步AI 转而改写 description 却回复「已记录」冒充绑定成功误导用户。② 专用工具语义清晰,防 AI 走通用 update 捷径冒充。③ prompt 约束防单链 ReAct「自我圆场」幻觉失败时用替代谎报成功
  • 状态 2026-06-14 落地(白名单同步 / bind_directory / prompt 中英约束;编译全绿)。📋 待清:工具层白名单与 crud 白名单双份去重(详见经验记录)。

📋 项目管理 review 剩余问题与处理论证(供后续会话)[2026-06-14]

  • 背景:项目管理 review 12 条9 条已修①delete 软删 / ②回收站工具 restore+purge+list_trash / ③collect_sample spawn_blocking / ④normalize_path 抽公共 / ⑥i18n / ⑦parseStack 抽 utils / ⑧ConfirmDialog / ⑫create_project 加 path。剩余 4 条 + 1 新发现论证如下,设计视角取全局 + 对称 + 优雅,非局部最优。
  • 值得改(全局必要 + 对称缺失)
    • ⑤ update 白名单双份tool_registry update_project 硬编码 5 字段 vs crud allowed_columns已致一次 bug。对称论证两者语义不同——DB 白名单=SQL 安全列(含 id/created_at/idea_id 系统字段AI 白名单=业务可改子集。不能复制,应派生AI ⊂ DB减系统字段真相源在 DB 一处。当前平行两份不对称,必漂移。
    • ⑩ scan_project_with_ai 无 LLM 超时。全局complete 卡住占 llm_concurrency 全局 permit → 阻塞主对话/标题生成/知识提炼,不止单次扫描。对称:stream_llm 有 idle 120s timeout见「流式可靠性三重保险」complete 非流式却无——两套 LLM 超时策略不对称,应对齐。
    • 🆕 create_project 与 bind_directory 绑定逻辑重复tool_registry create:170 内联绑定 + bind_directory:220 重复,已标 TODOcommands/project.rs create/relocate 同样)。对称+优雅:绑定是单一子操作,应集中 df-projectnormalize_path 已归此create/bind/relocate 共用一个 bind fn。当前 create 内联 bind 破坏「同名操作同实现」的对称。
  • 低优先(局部优化,降级兜底,过度反伤优雅)
    • ⑨ collect_sample 文件大小限制read_to_string 全读再截,实际 README/清单 <10KB 概率低。最多一行 metadata skip >1MB,不必过度。
    • ⑪ parse_scan_result JSON 提取:单 JSON 对象 OK多段场景降级兜底空 desc+规则 stack已足够。
  • 状态📋 待后续会话处理。优先级 ⑤⑩ + create/bind 去重(中,全局/对称必要)> ⑨⑪(低/可选)。

知识库df-evolve / 共享记忆层)

核心定位与设计决策。详细字段/参数级决策见各条目。

定位 + 被动 Service 退化 [2026-06-13]

  • 决策知识库df-evolve定位为整个 DevFlow 的共享记忆层——每个模块idea/task/workflow/review/chat既是知识生产者也是消费者而非孤立展示功能页。df-evolve 褫夺「自动进化引擎」角色Sprint 2 对抗论证已砍,自用阶段 ROI 低/过度工程),退化为被动 Service 层,只暴露 search/retrieve/record_reuse/feedback/save 供各模块调用;被动 Service 复用 df-ai 检索做消费侧EventBus 做事件驱动提示(非自动抓取)。
  • 原因:手脑(各业务模块)分离无学习能力;知识库做「肌肉记忆」中枢系统才越用越懂你。砍的是自动挖矿,非知识库本身。
  • 状态📐 设计未实施(用户拍板定位)

沉淀审核机制知识状态机AI 只产草稿 [2026-06-13]

  • 决策:知识加 status 字段,状态机 candidate → pending_review → published → archivedAI 提炼的知识一律进 candidate绝不直接入正式库;草稿进「待审核收件箱」,人工逐条编辑(内容/分类/标签)→ 发布或丢弃。verified = 发布审核时一次性人工标intake 决断动作,非 ongoing 评分)。沿用 IdeaRecord 的 pending_review 状态机模式。
  • 原因沉淀必须有人工把关用户要求「人工能够编辑或调整必须有这些过程」——AI 提议、人裁决、系统如实记,非黑箱自动学习。
  • 状态📐 设计未实施(用户明确要求加审核机制)

AI 提炼产出:字段集 + 置信度(唯一指标)+ 查重 [2026-06-13]

  • 决策AI 提炼一条 candidate 时产出——内容字段kind分类AI 判定 7 类之一)、titlecontenttagssource_ref(原始证据片段);质量指标confidenceHigh/Medium/LowAI 自评,唯一质量指标);提炼时另做查重(比对 published 库,重复则不产/标合并,非存储字段)。克制边界:质量指标只留 confidence——不加 generality/specificity/novelty 等维度(过工程化 + 多耗 token适用范围并入 tags 不单列 scope 字段。
  • 原因kindsource_ref 是 AI 必填但易漏的两项confidence 服务降噪 + 审核分诊 + 透明,但不绕过人审门high 也不自动发布)。
  • 状态📐 设计未实施

透明化provenance 溯源 + 收件箱 + 注入告知 [2026-06-13]

  • 决策:① 每条知识标来源(哪次 Chat/task/review 产出 + 原始片段),可跳回——复用现有 source_project + source_ref 字段;② 「待审核收件箱」作明确信息渠道;③ 复用时显式告知本次注入了哪几条、为什么命中。
  • 原因用户要求「透明化让人们有很好的信息获取渠道」——不黑箱。provenance 字段现有模型已有,零新增成本。
  • 状态📐 设计未实施

克制原则:宁缺毋滥,小步迭代 [2026-06-13]

  • 决策:① 检索注入保守——精确匹配(标签/关键词)优先,语义模糊匹配后做top-N 限 1-3 条,置信不够一条都不塞;② 关联不自动推断——IdeaGraph 自动聚类/关联发现先不做,只支持人工标注;③ 沉淀不主动监听全量事件——仅「一键沉淀」或事件提示后「确认」才产 candidate从小到大——先 AI Chat 单点双向跑通验证手感,再串 review/idea。
  • 原因:用户要求「尽可能克制,不要做大胆的连接,从小到大」——贯彻 Sprint 2「scope 砍 60%」精神到知识库,避免重蹈「自动进化」过度工程覆辙。
  • 状态📐 设计未实施(用户明确要求克制)

指标客观化reuse_count 唯一信号,撤销 effectiveness 人工评分 [2026-06-13]

  • 决策:知识排名/淘汰只用 reuse_count 一个客观信号(检索注入自动 +1撤销 effectiveness 的人工 👍/👎 评分主观、有摩擦、信号不准淘汰改客观——reuse_count=0 且超 N 天未用 → 提示归档。
  • 演进初版三指标reuse_count + effectiveness + verified共同排序权重 → 同日修正:用户指出 👍/👎 是「人为、主观、非准确」的非必要干预,撤销。「用过 ≠ 有用」的质量顾虑改由两层客观兜底——① intake 审核门(一次性决断)② 发现噪音直接删。召回不准根因在标签/搜索质量,靠 intake 打准标签解决。
  • 状态📐 设计未实施

📋 分层落地 Tier 1/2/3 + 来源/去向审查 [2026-06-13]

  • 需求:知识库联动分三层——Tier 1必做AI Chat ↔ 知识库双向 + 手动录入(沉淀 + 检索注入 + reuse_count + 审核收件箱 + 状态机,无人工评分Tier 2串创作流带前置ai_node 检索 prompt_template、工作流 NodeFailed → pitfall仅失败时)、决策记录 → architecture_pattern前置:先补 df-traceability 持久化Tier 3evolve_engine 自动挖事件。
  • 审查(来源):① /review 源移出——devflow 无代码审查功能df-stages/coding.rs 审查节点是 TODO 空壳);② 想法评估源存疑——对抗论点是「一次性结论」非可复用知识;③ 决策记录源标前置——DecisionJournal 所有 SQLite 查询 TODO 未持久化;④ 工作流源限定失败时——运行日志≠提炼知识。
  • 审查(去向)Chat 轴是唯一 Tier 1 就绪消费端(检索→注入对话/提示词ai_node prompt 注入属 Tier 2工作流无主动消费仅被动产 pitfall决策溯源消费半残。→ 来源/去向双收敛到 Chat 轴。
  • 状态📐 待实施(先做 Tier 1Chat + 手动录入)

对外暴露MCP Server 双向协议 [2026-06-13]

  • 决策:知识库对外 API 采用 MCP Server 形式暴露,双向(读+写。Tier 1 先做 DevFlow 内部闭环Tauri IPC命令层设计完全对齐 MCP 语义Tier 1+ 套 MCP server封装已有 command。MCP 暴露:① Resource (读)list/search/getTool (写)create_candidateTool (计数)record_reuse。
  • 原因:① Claude Code 原生吃 MCP——本机主力工具零集成成本② Cursor 也支持 MCP双向价值:外部工具(尤其 Claude Code 做代码审查/重构时是高质量知识来源——审查结论→review_rule、踩坑经历→pitfall接 MCP 自动回流知识库等于开「第二来源入口」。克制Tier 1 不实现 MCP 本身,但 6 个核心命令search/list/get/create/update_status/record_reuse全部按可暴露设计。
  • 状态📐 设计未实施Tier 1+ 事项)

矛盾知识处理:纯标签+内容自述source_project 仅溯源 [2026-06-13]

  • 决策:矛盾知识不建冲突关系表、不加 scope 字段、不做 access control。消歧靠 tags["Go","微服务"] vs ["Go","单体"]+ content 自述适用范围 + source_project 仅作来源溯源展示不参与检索过滤。AI 提炼 prompt 加约束:「适用范围有限制必须在 content 或 tags 中标注」。零数据结构变更。
  • 原因/取舍:矛盾是少数场景,为 minority 建关系系统是过度工程source_project 若做绑定/过滤会提高维护门槛 + 降低通用知识复用率;检索 top-N≤3 返回时内容本身场景描述足够消费者判断。
  • 状态📐 设计未实施

AI 提炼触发 + 知识注入:可配置 [2026-06-13]

  • 决策:① AI 提炼默认自动触发(后台 detached task4 个配置项:auto_extractdefault true/ trigger_modeon_complete|on_idle|manual_onlydefault on_complete/ min_messagesdefault 4/ idle_timeout_msdefault 30000。② Chat system prompt 知识注入加开关auto_inject: booldefault true关闭时首行返回空字符串零开销
  • 原因/取舍手动按钮依赖用户记得点→遗忘→空库死循环自动触发保证持续流入候选。但用户控制欲不同——4 配置项覆盖从「全自动」到「全手动」。每次 complete() <500 input/<200 output token可关零成本。注入开关给用户「先积累再开启 / 调试不被干扰」的控制权。
  • 状态📐 提炼设计未实施 / 注入已实施Tier 1

检索方案LIKE + top-N向量检索提前到 Tier 1Phase 5.5[2026-06-13]

  • 决策Tier 1 检索用 SQLite title/content LIKE '%query%' + ORDER BY reuse_count DESC LIMIT 3;收件箱排序用 CASE WHEN confidence 'high'→3/'medium'→2/'low'→1(非纯 TEXT 字典序)。向量检索从 Tier 2 提前到 Tier 1 同步实施Phase 5.5),加 Settings 开关vector_enabled,默认 false
  • 原因/取舍:知识库核心消费场景是 AI 自动注入(拿用户自然语言 query 检索非关键词精确搜索——「部署后白屏」匹配不到「Nginx SPA 路由」,纯 LIKE 语义盲区从第一天就存在。开关化解「本地优先/零依赖」哲学冲突:默认关闭纯 LIKE 零外部调用,开启后才走 embed API。
  • 实施细节:① LlmProvider trait 加 embed()OpenAICompat 实现Anthropic 不支持);② V8 幂等补 embedding BLOBf32 小端序列化NULL=未嵌入走 LIKE嵌入时机=发布时candidate 不浪费 embedpublished 才参与检索);④ 纯 Rust 余弦(<50k 条暴力遍历够用,不引 sqlite-vec 避免 Windows C 扩展编译风险);⑤ 三层降级链开关关→LIKE开但 provider 缺/embed 失败→自动回 LIKE正常→混合检索双信号>LIKE 单>向量单cos≥0.3 滤噪)。
  • 状态 Tier 1 LIKE + 向量混合检索Phase 5.5)均已实施,编译通过待实测

知识生命线:独立 knowledge_events 表(非 JSON 嵌主表)[2026-06-13]

  • 决策:知识产生/审核/引用/归档四类审计事件存独立 knowledge_eventsV10 迁移),而非塞进 knowledges.context_json 字段。
  • 原因/取舍:事件是追加型(只增不改删),语义与主表 CRUD 完全不同一条知识可被引用数百次JSON 嵌主表致行膨胀 + 写更新竞争(每次引用都重写整行)。独立表可建 (knowledge_id,event_type) 复合索引事件表写失败只丢审计、不影响知识本身fire-and-forget 隔离)。未来加新事件类型只加一行 insert不动主表 schema。
  • 状态 已实施V10 迁移 + KnowledgeEventsRepo + 前端生命线时间线)

📋 知识详情页 + 编辑能力candidate 审核闭环)[2026-06-13]

  • 需求:卡片点不开详情、不能编辑、看不到「为什么产生」。详情页需呈现完整生命线 + candidate 可编辑修正后发布。
  • 决策Knowledge.vue 重构为 Ideas 式左右分栏(左卡片列表 @click 选中 / 右详情面板四分区:①基本信息 ②溯源 ③引用记录 ④生命周期时间线);可编辑字段 title/content/tags/confidence/reasoning 走 knowledge_update(部分更新)。
  • 原因/取舍candidate 编辑是审核闭环刚需——AI 提炼必有水分/措辞瑕疵,只能原样发布或整条拒绝会让审核空转。详情复用 Ideas 已验证的 master-detail 模式。published 编辑不做(有归档+重提炼替代)。
  • 状态 已实施(编译+vue-tsc+df-storage 21 单测全绿GUI 实测待 #54

AI Chat 上下文窗口与并发控制(架构结论)

实现细节见 归档文档「AI Chat 上下文窗口与并发控制」。

设计决策 [2026-06-13]

  • ContextManager 类型替换为 messages 真相源AiSession.messagesVec<ChatMessage> 改为 ContextManager(非 wrapper 包装层),消息真相源唯一,避免 Vec + ContextManager 双存导致状态分裂。裁剪仅影响发送视图(build_for_request 返回裁剪版,all_messages_clone 返全量落库)。
  • 淘汰算法:分组滑动窗口 + 三元组保护Assistant(tool_calls) + Tool(result)* + Assistant(final_text) 工具调用三元组作为原子整体;最后 6 条≈2 个完整用户轮次)设为保护区永不淘汰。
  • Token 计数零依赖chars_count × 0.35 粗估(误差 ±15% 可接受),不引入 tiktoken-rs5MB BPE 数据文件对 Tauri 打包不友好)。
  • 双层 Semaphore 并发控制AppState LlmConcurrency——全局并发默认 3 / 单对话默认 2permit 在 3 个叶子 LLM 调用点 acquirerun_agentic_loop stream_llm 前、generate_title_via_llmextract_knowledge_from_conversation),工具执行不受控。per_conv 实为应用级单一信号量(因 AiSession 单例 + generating 互斥,命名宽泛但当前语义正确,多对话路线时改 HashMap。Semaphore 重建用「软收敛」策略(替换内层 Arc旧 permit 不受影响)。
  • 裁剪策略与模型选择正交ContextConfig 不含 mode/模型选择字段;「高精度/低精度对话」属 LLM 调用层参数,与裁剪策略是正交维度。
  • 状态 已落地2026-06-13cargo check + vue-tsc 通过,待 tauri dev 实测)

i18n

legacy:false + zh-CN 默认 + locale 拆分 + glob 聚合 [Sprint 7 + 2026-06-13]

  • 决策:① legacy:false / globalInjection / zh-CN 默认 + en fallback / localStorage df-language 持久化。② zh-CN.ts/en.ts 单文件 → zh-CN/*.ts + en/*.ts 按模块拆分nav/dashboard/ai/common/settings/ideas/knowledge/projects/projectDetail/tasks/aiChat/aiToolindex.tsimport.meta.glob('./*.ts', { eager, import: 'default' }) 自动聚合(排除 index 自身)。新增模块文件即生效,不改 index。
  • 原因:① Composition API 模式;默认中文贴合自用,英文兜底。② 全量 i18n 接入8 view ~640 处中文)用多代理并行,模块隔离零冲突(每代理建自己模块 + 改自己 view不动共享 index比单文件扩 key多代理改同一 zh-CN.ts 冲突更适合并行。glob eager 运行时聚合,动态新增模块即拾取。
  • 状态 Sprint 7 + 2026-06-13curl 验证 vite 正确展开 globvue-tsc PASS

状态枚举 i18nconstants 存 keyview 包 $t

  • 决策constants/project.tsPROJECT_STATUS_LABELS/TASK_STATUS_LABELS 值从中文文案改存 i18n keyplanning: 'projects.status.planning'projectStatusLabel/taskStatusLabel 返回 keyview 显示处包 $t(projectStatusLabel(x))PRIORITY_LABELSP0/P1是代号非文案不动。
  • 原因constants 是纯数据/结构层,不应含展示文案(违反分层);文案归 localeconstants 管映射结构。
  • 状态 已落地

📋 项目 status 字段语义混乱(生命周期 vs 开发阶段)

  • 现象:后端 projects.status DEFAULT 'active' + list_active/软删除active/deleted 生命周期),但前端 PROJECT_STATUS_LABELS 是 planning/in_progress/paused/completed/cancelled开发阶段两套塞一个 status 字段。DB 实际只有 status='active'(新建默认,阶段值从没产生),前端 map 不认 → 显示英文 "active"。
  • 治标:补 projects.status.active🚀进行中),不再显示英文。→ 根本未除。
  • 治理方向:① 后端支持阶段流转planning→in_progress…② 前端 map 对齐后端真实值active/deleted/archived③ 拆双字段status 生命周期 + stage 开发阶段)。
  • 状态📐 待治理(治标已落地,根本病根未除)

i18n import 统一 @/i18n 路径别名 [2026-06-15]

  • 决策vite.config.ts 加 resolve.alias.{ '@': '/src' } 路径别名;全项目 i18n import 统一为 import i18n from '@/i18n',替代相对路径 ../i18n/../../i18n
  • 原因/取舍CR-08 i18n 批量改造时workflow 代理将 stores/ 下层文件 i18n import 从相对路径(../../i18n)改为错误多层的 ../../../i18n 或正确的 @/i18n(但项目无别名配置),导致 vite 构建失败(Could not resolve)。相对路径随文件深度变化易断stores/ 两层 vs composables/ai/ 三层 vs utils/ 一层);@/i18n 绝对路径不随文件位置变化零维护成本Vue/Vite 生态标准做法(多数 Vue 项目默认配 @ → src别名仅影响构建时解析运行时无开销。
  • 影响范围9 个源文件(import 侧) + 1 个配置文件(vite.config.ts)。
  • 状态 已落地commit d6eb855 + 6254d06

状态持久化

窗口位置/大小:用 tauri-plugin-window-state纯 Rust 层)

  • 决策:窗口位置/大小/最大化用 tauri-plugin-window-state 插件Rust 层自动接管),而非前端 localStorage + setPosition/restore 方案。
  • 原因:插件自动覆盖主窗口 + 动态创建的 ai-detached 子窗口,零前端代码、零竞态;前端方案需手动同步且对子窗口生命周期处理复杂。需配套 window-state:default capability 权限。
  • 状态 Sprint 10

detached/docked 不持久化

  • 决策UI 布局持久化,但 detached/docked 重启后强制回 false,不随 df-ai-ui 落盘。
  • 原因:重启后分离窗口必然不存在,若恢复为 true 会让 UI 状态指向不存在的窗口按钮失灵、panelOpen 错乱)。这两个态是运行时临时态,不属可恢复布局。
  • 状态 Sprint 10

UI 布局 localStorage + 模块级恢复的细节见 归档文档

应用启动 / 数据库配置

Dev 与 Build 拆分独立数据库 [2026-06-13]

  • 决策lib.rs 启动时按 cfg!(debug_assertions) 选 DB 文件名——debugDev 模式)用 devflow-dev.dbreleaseBuild 模式)用 devflow.db,两库同处 app_data_dir()top.1216.devflow)下,靠文件名区分。
  • 原因/取舍原启动代码无编译模式分支Dev 与 Build 共用一个 devflow.db——Dev 频繁改动/清空会污染 Build 侧真实运行数据。拆分后 Dev 库可随意折腾Build 库长期保留作运行效果基线。文件名区分而非子目录——改动最小lib.rs 一行 if两库平铺同目录便于备份/查看。现有 devflow.db 文件名未变归 Build零迁移零数据丢失Dev 首次启动自动建空库。
  • 边界app_data_dir()tauri.conf.jsonidentifier 决定、与编译模式无关故拆分前两种模式确读同一文件。docs/使用手册备份命令 cp devflow.db 仍正确(备份 Build 真实数据)。
  • 状态 2026-06-13 落地(lib.rs:24

UI 反馈与弹层

toast/confirm 自建,不引 Arco / 不用 window.confirm [Sprint 10]

  • 决策Settings 页轻量提示与删除确认用自建 toast(顶部 fixed3s 自动消失)+ confirmDialog(遮罩 + 卡片Promise 化),而非引入 Arco Message/Modal 或原生 window.confirm
  • 原因:① @arco-design/web-vue 虽在依赖但 main.tsapp.use 注册,引 Message/Modal 要补全局注册 + 样式加载,过重违反做减法;② window.confirm 在 Tauri webview2 带「来自 localhost:端口」来源信息,无法去除,体验差。自建零依赖、样式可控(主题色)、await confirmDialog() 语义贴近原生 confirm。
  • 演进 [2026-06-13]AiChat 删对话需确认 → 第二处复用落地。抽成 src/components/ConfirmDialog.vuevisible/msg/dangerLabel props + @result emit。按钮样式内联自包含不依赖外部 .btn-*——因 Settings 是 scoped,组件拿不到其内定义的 .btn-danger。选 SFC 组件而非 useConfirm() composable模板/遮罩/Transition 动画/CSS 才是真正重复主体Promise 封装留在调用方(~8 行)。
  • 状态 Sprint 10

技能 / 联想

首批 Claude 3 类 + path 去重

  • 决策:技能联想首批数据源 = Claude skills / commands / plugins 三类SKILL.md frontmatter按 path 去重(cache/marketplaces/ 重复)。
  • 原因frontmatter 格式统一(name/description/user_invocable可统一解析Codex frontmatter 一致后续可扩展openclaw 属 agent 选择层不纳入。
  • 状态 Sprint 8待实测

决策治理产品化评估2026-06-13

审视 DevFlow 是否应把决策治理(记录/锚点/完成度/自检/漂移)做成产品功能。机制设计详见 规格契约自检机制-2026-06-14.md

5 痛点产品内未覆盖,真实运转的寄生 Claude Code 层 [2026-06-13]

  • 决策DevFlow 产品内对决策治理 5 痛点「设计满格、代码两极」——df-traceability 死代码(无表/无 IPC/无前端);契约锚点/AI 自检/漂移检测=规格契约自检机制-2026-06-14.md 纯设计稿0 行代码);完成度无聚合视图。唯一真实运转的(功能决策记录-2026-06-14.md + decision-record skill + dr-check hook寄生在 Claude Code 协作层,未沉淀进产品。
  • 原因/取舍:没用 Claude Code 的用户DevFlow 给不了任何决策治理能力。这套能力寄生在协作工具上,核心价值未进产品。
  • 状态📐 待产品定位决策

df-traceability 是锚点雏形Sprint 2 被砍(死代码可复活)[2026-06-13]

  • 决策crates/df-traceability/Annotation.location(文件路径+行号)= 规格契约自检机制设计的「代码锚点」雏形,Decision struct 精确对应决策记录痛点。但 Sprint 2 对抗论证时被砍/降级,此后无表、无 IPCquery 方法全 vec![]
  • 原因/取舍:非显然关联——文档层设计的活契约+锚点机制,本质是产品外部用更轻方式重发明被砍的 df-traceability 轮子。是否复活取决于产品定位抉择Sprint 2 砍的理由(优先级低/过度设计)现需重新评估。
  • 状态📐 待评估

产品化推荐路径 C 混合,完成度驾驶舱起步 [2026-06-13]

  • 决策三路径——A 全产品化(复活 df-traceability 全栈+spec 自检 AI成本大/重蹈 Sprint 2 覆辙风险B 纯寄生(承认是 Claude Code 协作层,只优化 skill/hook产品核心价值存疑C 混合推荐——产品做数据底座decisions 表+完成度聚合+视图AI 验证/漂移留协作层。最小起步:只做完成度驾驶舱(痛点 3
  • 原因/取舍C 分离「确定的数据层」与「不确定的智能层」,先做确定的低风险项。完成度驾驶舱起步:①最痛(记不住做了/没做②技术已存在tasks/ideas 有 status缺聚合 IPC+Dashboard 视图)③立刻可见④验证真会用再扩(避免 Sprint 2 式膨胀)。
  • 状态📐 待用户拍板DevFlow 要否成为「决策治理/完成度驾驶舱」产品)

crate 治理 / 模块结构2026-06-14

跨 crate 的删留与拆分决策。涉及 df-evolve 领域保留决策的推翻、coordinator 空壳的去留、ai.rs god file 的拆分方式。

删除 5 个零引用 crate推翻 df-evolve 领域保留决策)[2026-06-14]

  • 决策:整删 5 个 crate——df-evolve / df-plugin / df-stages / df-task / df-traceability推翻既有「df-evolve 领域类型保留」决策:连同 Knowledge/PromptTemplate/ReviewRule 领域类型一起整删,知识库领域统一走 df_storage::models::KnowledgeRecord,不再维护独立领域模型层。
  • 原因/取舍
    • 零引用铁证:全仓跨 crate 引用为 0——src-tauri/src 下 0 处 use,其他 crate Cargo.toml 不依赖,仅 src-tauri/Cargo.toml 声明 df-evolve 但源码零用。整坨孤立骨架。
    • 推翻归档决策功能决策记录-归档-2026-06-14.md:355 原记「Knowledge/PromptTemplate/ReviewRule 领域类型有意保留待 Tier 1 Service 复用」——本次决定放弃 Tier 1 独立领域模型路线。理由:① 知识库 Tier 1 已在 KnowledgeRecorddf-storage上落地 LIKE + 向量混合检索 + 状态机,实际运转的领域模型就是 KnowledgeRecorddf-evolve 的领域类型成为「理想但悬空」的另一套定义,重复且误导;② 维护两套领域类型是「未来可能复用」的预期成本 vs 「现在重复定义 + 误导性地雷」的实际危害,用户选消灭后者。
    • df-task::Task 一并删Task(含 branch_id/tags/estimate_hours 等比 TaskRecord 更丰富的字段)作为「理想任务领域模型」长期悬空零引用,任务领域统一用 df_storage::models::TaskRecord
    • df-traceability 整删:原被记为「锚点雏形可复活」(见上方「决策治理产品化评估」)。本次决定删除——如未来真需锚点机制,重新评估而非保留死码。死码「可复活」是一种伪期权,实际价值是误导后续维护者以为它在运转。
    • df-plugin / df-stages 属过早设计df-pluginWASM/动态库、df-stages11 阶段节点 execute() 全空壳未启动即删与「人机协同设计基准」中「AI 反复读写的代码不养空壳」一致。
  • 影响:① src-tauri/Cargo.toml 需移除 df-evolve 依赖声明;② 「决策治理产品化评估」中 df-traceability 相关条目(锚点雏形 / 完成度驾驶舱数据底座)状态需重新标注为「无现存代码可复用」;③ 知识库功能域(## 知识库)所有决策继续适用,但实现载体明确为 KnowledgeRecord 而非 df-evolve 领域类型。
  • 状态 2026-06-14 落地(用户拍板删 5 crate + 领域类型)

coordinator.rs 保留B 路线占位空壳,不删)[2026-06-14]

  • 决策crates/df-ai/src/coordinator.rsAgentCoordinator(多 agent 协作占位空壳,run() 返回硬编码 TODO保留不删加注释标注「B 路线待立项」。
  • 原因/取舍:与 aichat 升级 A/B 路线拆分一致——A 路线先做 UX 快赢已进行B 路线单独立项补多 agent 协作决策能力。coordinator 是 B 路线的入口锚点,有意保留占位而非删除:① B 路线立项时有现成挂载点trait + 结构骨架),不必从零设计;② 与上述 5 crate 删除不矛盾——5 crate 是「无路线图占位的纯死码」coordinator 是「有明确后续路线B 路线)的占位」,二者判断标准不同。区别在「是否绑定明确的演进路线」。
  • 状态📐 B 路线待立项(保留空壳 + 加注释)

ai.rs 拆分:低风险子 module 而非下沉 crate [2026-06-14]

  • 决策src-tauri/src/commands/ai.rs2663 行 god file拆成 commands/ai/ 子 module 目录11 个文件mod + commands + agentic + stream_recv + conversation + title + audit + skills + prompt + tool_registry + knowledge_injectpub use 保持 state.rs/lib.rs/knowledge.rs 引用路径零改动。采用低风险子 module 方案而非下沉到 df-ai crate
  • 原因/取舍:① 2663 行单文件消耗大量 AI context每次理解靠结构与「人机协同设计基准」中「组件拆分从『不做』升为『值得做』」一致。② 选子 module 不选下沉 crate——下沉到 df-ai 需动 crate 依赖图df-ai 反向依赖 src-tauri 的 state/types引入循环依赖风险 + 跨 crate 重构成本;子 module 仅在同 crate 内切目录,pub use 保持对外 API 不变,零引用路径改动,重构面最小。③ 子 module 仍能达成「职责单一」的 AI 可读性目标,与下沉 crate 收益相当但风险低一个数量级。
  • 实施验证2026-06-14 落地)
    • 11 文件合计 2833 行,最大 knowledge_inject.rs 557 行含测试commands.rs 529 行17 个 IPC 命令),其余均 < 400 行。
    • 路径契约全保:commands::ai::{AiSession, build_ai_tool_registry, restore_pending_approvals, spawn_embedding_for_knowledge, trigger_extraction_now} + 17 个 invoke 命令state.rs/lib.rs/knowledge.rs/commands/mod.rs 零改动
    • cargo check 0 errorcargo test ai:: 19 passed。剩 3 warning 全为预存非本次引入。
    • 顺带修 bugai_conversation_listmodels 字段从 JSON 字符串直塞改为解析为 Vec<String> 数组下发(前端期望数组,原代码传字符串)。
  • 状态 2026-06-14 落地11 子 module + glob 重导出 + models bug 修复cargo check/test 通过)

前端 ai.ts 拆分路线Astore 留 state 单例 + composable不引入 Pinia [2026-06-14]

  • 决策src/stores/ai.ts758 行 god store拆成 store 骨架(留 reactive state 单例 + 模块级私有变量)+ src/composables/ai/ 下 6 个 composableuseAiEvents/useAiStream/useAiSend/useAiConversations/useAiWindow/useAiPanel)。useAiStore() 统一入口展开所有 composable 方法,返回 shape 不变,组件零改动
  • 原因/取舍
    1. 与项目既有 store 风格一致——project/knowledge/settings 全是「手写 reactive + 工厂函数」模式,引入 Pinia 会破坏一致性、增加心智负担。
    2. 组件零改动——AiChat.vue/AiDetached.vue 等用 const { state, sendMessage } = useAiStore() 解构,保持 useAiStore 返回 shape 不变即可。
    3. 选路线 Acomposable 挪逻辑、store 留 state而非路线 BPinia 多 store——后者要改 19 个 state 字段归属和所有组件 import风险远大于收益。
    4. 与后端 ai.rs 子 module 拆分配对——前后端 god file/god store 同步拆解采用各自生态的惯用拆法Rust 子 module / Vue composable不强求统一模式。
  • 影响:确立项目 store 架构约定(手写 reactive + composable不用 Pinia影响所有未来 store 设计。
  • 状态🚧 执行中workflow w20yb6n6b 编排vue-tsc 自验证)

AI trait 下沉:拆 df-ai-core 轻层,确立全局 AI 接入标准 [2026-06-14 📐]

  • 决策:将 LlmProvider trait + AI 数据类型(ChatMessage / CompletionRequest / ToolDefinition 等)从 df-ai 拆出,下沉到新轻量 crate df-ai-core(零 http 依赖);df-ai 保留为「实现 + ModelRouter + provider 工厂」hub持有 reqwest/openai_compat/anthropic_compat);所有消费 cratedf-ideas 接对抗评估、未来 df-knowledge/df-workflow 等)只依赖 df-ai-core 的 trait不直接依赖 df-ai;真实 provider 由 src-tauri 最上层装配注入。F-260614-03 及后续所有 AI 接入点统一照此,不再 per-module 自定义 trait。
  • 原因/取舍(纯 ai-coding 工作模式下重算 F-03 原 A/B/C 选型):
    1. 砍「人审查的契约面」而非「打字量」——一份全局 trait = 一份契约给人过目 + 规格契约 self-check 锚一点per-module 自定义 trait原 A= N 份发散契约,审查负担与漂移风险同涨。纯 ai-coding 下接线/mock 全由 AI 吸收,故 A 的「适配器成本」、B 的「mock 成本」论点作废。
    2. 保住纯逻辑 crate 零摩擦自检——df-ideas/df-storage 只依赖 trait 不拖 reqwest,规格契约机制 A/B 测试自动跑无 http 依赖;裸 Bdf-ideas 直接依赖 df-ai会污染纯逻辑 crate、自检摩擦上升。
    3. 与现有 roadmap 对齐——ModelRouterF-260614-01、多 Provider 负载均衡池F-260614-04、provider 工厂(已落地)本就在 df-ai 内走「gateway」方向消费方选型应顺此而非另起 N 个 trait。
    4. 无环且与 ai.rs 拆分不冲突df-ai-coretrait+类型)← df-ai(impl) / df-ideas(use trait)src-tauri 装配。「ai.rs 子 module 不下沉 crate」规避的是 src-tauri→df-ai 反向依赖;本决策是 df-ai→df-ai-core 正向拆分,方向相反、互不矛盾。
    • 否决项:纯 Aper-module trait= 全局 N 份发散契约,反模式;裸 Bdf-ideas 直接依赖 df-ai= 纯逻辑 crate 被 reqwest 污染、自检摩擦上升。
    • 退路:若不愿加新 cratetrait 可放 df-core语义稍糙——LLM 非领域类型,但零新 crate可接受
  • 状态📐 设计定稿2026-06-144 项决策已定:① 拆分边界=仅 trait+数据结构 ② provider 注入=构造注入 Engine::new(Option<Arc<dyn LlmProvider>>) ③ LLM 失败=自动降级启发式+warn+EvaluatedBy 标记 ④ provider 构造=应用层 src-tauri 装配注入),未实施。详见 F-07-df-ai-core-trait下沉设计-2026-06-14.md

工作流人工审批节点B-03

HumanNode 审批响应机制subscribe→send→select! 广播过滤等待 [2026-06-14 📐]

  • 决策df-workflow HumanNode.execute 改为「先 subscribe() → 发 HumanApprovalRequesttokio::select! 循环等 HumanApprovalResponse」,按 execution_id + node_id 双键过滤命中后返回 NodeOutputselect! 三分支 = 响应 / 超时(配置 timeout_secs 默认 3600s/ 取消500ms 轮询 is_cancelled)。复用既有 EventBus(broadcast) / HumanApprovalResponse 事件 / approve_human_approval IPC / 前端 store——零新增基础设施仅改 HumanNode 一处。
  • 原因/取舍
    1. 订阅时序铁律tokio broadcast 不回放历史,必须 subscribe() 先于 send(Request),否则 receiver 错过 Response 死等超时。
    2. 双键过滤node_id 单键不够跨工作流可能重复、execution_id 单键不够(同层多 HumanNode双键才完备。
    3. Lagged 容忍capacity 256 + 审批低频,漏自身 Response 概率极低;continue 优于丢弃(丢弃误判超时更糟)。
    4. decision 强制校验options 非空时强制 decision ∈ options非法值报错而非静默放行——审批门控不能被脏输入绕过options 空时允许自由文本。
    5. B-06/B-07 是并发隔离/取消的前置,非单流功能前置:单工作流 B-03 照常工作;并发安全等 B-06execution_id 下沉);取消机制需 B-07 + set_cancelled + cancel IPC单列 B-03b。B-03a响应等待 + 超时)不依赖 B-07。
  • 边界:取消分支在 B-07 + set_cancelled 补齐前恒 false等价无取消功能不残跨工作流并发 HumanNode 在 B-06 修前有 Response 错配风险。
  • 状态📐 设计完成2026-06-14未实施。详见 B-03-人工审批响应机制-2026-06-14.md

任务推进链7 态状态机 + 工作流联动)

tasks 表从 todo→done 的状态推进链路。阶段17 态状态机 + advance_task CAS 原子写 + 软删除已落地阶段2工作流联动task_id + 完成回调 advance_task + DAG 模板)进行中。详细实施路径见 任务推进链实施路径-2026-06-16.md / 推进链阶段2实施路径-2026-06-16.md。关联决策 D-260616-01~04前端7态对齐 / 软删除 / Node trait 归属 / 阶段1先行

advance_task / 状态机走 df-nodes Node trait不复活 df-taskD-260616-03

  • 决策:任务推进业务逻辑(can_transition_to 状态机 / advance_task 原子写 / 闸门节点)落在 df-nodes crate 的 Node trait 扩展task_state_machine.rs / task_advance_node.rsIPC 层 thin 入口。不复活 2026-06-12 刚因零引用删除cf017f8的 df-task crate不塞 commands/task.rs。
  • 原因/取舍:① 对齐 D3「业务逻辑在 df-nodes 实现Node trait 纯接口df-workflow/src/node.rs:67」原则② 复活一个零引用刚删的 crate 是制造新死码df-nodes 补 df-storage 依赖读 TaskRecord 即可(核实无循环依赖);③ IPC 层保持 thintask.rs 仅 3 行转发)守住 D3 不让业务逻辑下沉 IPC。前端对齐后端 7 态D-260616-01types.rs:131激活 InReview/Testing/Blocked 三闸门态)。
  • 状态 阶段1 落地commit d2cb38c7态状态机 + advance_task CAS + 软删除25 测试);🚧 阶段2 进行中batch32注册 TaskAdvanceNode + config 下沉 + HumanNode reject

DagExecutor config 下沉:节点级覆盖全局级 deep_merge④-1

  • 决策DagExecutor.run 构造 NodeContext.config 从「initial_config.clone() 覆盖一切」改为「deep_merge(node_def_config, initial_config)」——节点级配置覆盖全局级节点定义优先。Dag 加 node_configs: HashMap<NodeId, Value>build_dag 填入 NodeDef.configrun 合并下沉。
  • 原因/取舍原实现executor.rs:99-107用全局 initial_config 覆盖 NodeDef.config节点级配置被完全忽略——TaskAdvanceNode.execute 读 ctx.config.task_id 拿到全局 config 而非节点定义写的 task_id节点参数化失效。这是阶段2 的架构前置阻塞点:不修则 TaskAdvanceNode 无法从 DAG 接收 task_id。选「节点级覆盖全局级」节点定义优先而非全局覆盖节点级因节点是更具体的配置源。deep_merge 对 Object 递归合并,非 Object 节点级直接覆盖。现有 HumanNode/AiNode 也受益(它们当前读 ctx.config 拿全局 config但无人通过 NodeDef.config 定义节点参数故未暴露)。
  • 状态🚧 实施中batch32 ④-1 agentdag.rs + executor.rs + registry.rs + workflow.rs配 deep_merge / node_config_overrides 测试)。

DAG 模板硬编码,不建 workflow_defs 表(②-6

  • 决策:任务推进的工作流 DAG 模板todo→in_progress / in_review→testing / testing→done 三条推进边 + 退回)硬编码df-nodes/task_workflow_templates.rs(导出 template_for(target_status) -> DagDef不建 workflow_defs 表tasks.workflow_def_id 字段留 None。
  • 原因/取舍模板数量少且稳定3 条推进边 + 退回),建表需 CRUD UI + 版本管理 + 关联维护,过度工程。业务系统设计-2026-06-12.md 确认 workflow_defs 从未建表(工作流定义 dag_json 内嵌 workflow_executions延续此约定。硬编码模板随代码版本管理零运行时配置开销。
  • 状态📐 设计定稿待实施(②-6batch33+)。

工作流回调语义:成功与任务推进解耦,失败按 target 退回(②-3/②-4/②-5

  • 决策:工作流完成后回调 advance_task 的语义——成功executor Oktask_id + target_status 都 Some 时调 advance_task_atomic,回调失败只 warn 不回滚工作流(工作流已完成是事实,任务推进失败前端提示手动处理);失败executor Err按 target_status 推算退回态testing→in_review / in_review→in_progress调 advance或加 failure_target_status 参数。HumanNode reject②-5从 Ok 改返 Err使审查拒绝走 failed 触发退回。
  • 原因/取舍工作流成功与任务推进是两个独立事实解耦避免「工作流成功但任务推进失败时回滚已完成工作流」的复杂性失败退回让审查拒绝能回流上一态review_rounds+1。CAS 已防回调与手动 advance 并发撞advance_task_atomic 捕获 InvalidState 降级。跨表事务缺失阶段2 回调失败降级阶段3/4 补 Database.transaction())。
  • 状态📐 设计定稿待实施batch32 做 ②-5 HumanNode reject 语义化batch33 做 ②-3/②-4 回调)。

需求与待办

汇集散落于各决策条目状态(📐/🚧)的待办 + 新增需求细节 + 需求澄清。单一清单,避免遗漏。

📋 待做需求

需求 功能域 来源 优先级
Sprint 9/10 多项编译过未 tauri dev 实测(评分 IPC 缩放 / update_full / promote_idea / Store getter 灵感/立项/Store Sprint 910 🚧 P1
切对话不中断路由:部分场景运行时实测 AI Chat 可靠性 Sprint 8 🚧 P1
技能联想「使用」:首批 3 类联想已做,联想后实际触发/执行技能未实现 技能/联想 Sprint 8 P2
灵感对抗评估接 LLM论点/evidence 由 df-ai LlmProvider 生成(现启发式 fallback 灵感模块 Sprint 9 📐 P2
知识库 Tier 1AI Chat ↔ 知识库双向闭环(沉淀+检索注入+reuse_count+审核收件箱+状态机+provenance 溯源+克制检索,无人工评分) 知识库 2026-06-13 已实施(Sprint 15) P1
路径校验根治workspace 白名单 + canonicalize现仅拒 .. + 敏感目录) 工具调用 Sprint 6 P2
停止生成 idle 即时优化:tokio::sync::Notify 替代 120s 轮询 AI Chat 可靠性 Sprint 6 P3
多 Provider 负载均衡池(备用模型/多账号聚合,全局容量=min(各 provider 上限之和, global_cap) AI Chat 并发控制 2026-06-13 📐 P2
裁剪/压缩消息按需召回Query Function + 分层存储: TrimRecord 追踪被移除范围 → DB 全量归档按需检索 → 精准注入 build_for_request触发方式待定:自动/手动/语义检索) 上下文窗口管理 2026-06-13 📐 P3
IPC参数驼峰/蛇形不对齐误报澄清Tauri v2 自动将前端 camelCase 参数名转后端 snake_caseapprove({toolCallId}) / setConcurrencyConfig({globalLimit}) 实际正确、功能正常——无需修 AI Chat 2026-06-13 审查误报
🔴 df-workflow ConditionEngine 默认 true所有未识别条件表达式均通过工作流条件分支形同虚设Ok(false)Err 一行可修 工作流引擎 2026-06-13 代码审查 P0
🔴 df-workflow DagExecutor execution_id 硬编码 "dummy-execution-id":所有执行 ID 相同,追踪/审计失效 工作流引擎 2026-06-13 代码审查 P1
📐 df-workflow HumanNode 假实现execute 注释"等待审批"但首次迭代直接 return "同意" — 设计完成 B-03-人工审批响应机制-2026-06-14.md,待实施(依赖 B-06 并发隔离 / B-07 取消前置) 工作流引擎 2026-06-13 多代理探索 → 2026-06-14 设计 P0
🔴 df-workflow NodeRegistry::default() 的 script 工厂 unimplemented! panic用 default() 构建注册表 + 跑 script 节点即崩溃进程(非优雅 Err 工作流引擎 2026-06-13 多代理探索 P0
🔴 df-workflow executor 每节点拿全新空 StateMachineself.state_machine 从不传入 NodeContextHumanNode is_cancelled 恒 false取消机制失效 工作流引擎 2026-06-13 多代理探索 P1
🟡 promote_idea 两步写非事务INSERT project 成功后若 UPDATE idea 失败,项目存在但想法状态未变,补偿删除可修 灵感/立项 2026-06-13 代码审查 P1
🔴 分离窗口detached跨窗口状态失效用 localStorage 传递生成态快照df-ai-gen/textTauri 多 webview 不共享 localStorage 致静默失效;用户点 X 关闭(非 closeDetachedWindow后主窗口 detached 永真卡死reattachPanel 死代码未接线)。需改 Tauri 全局 emit/listen 同步 + 窗口销毁事件复位 AI Chat 分离窗口 2026-06-13 代码审查 P1
模型能力声明与自动路由系统 Phase 1ModelCapability 数据模型 + ModelRouter 重写 + 7 调用点接入 + Settings 模型池编辑 UI + AiChat 模型下拉。核心:按任务需求(模态/功能/成本)自动匹配合适模型,不再所有场景共用 default_model 模型能力与路由 2026-06-13 📐 设计完成 P1
模型能力系统 Phase 2多模态消息支持——ChatMessage.content: String → Vec(Text/Image);前端粘贴/拖拽图片vision 模型自动路由 模型能力与路由 2026-06-13 📐 P2
模型能力系统 Phase 3Agent 内智能路由——Agentic Loop 每轮按子任务构造不同 TaskRequirements成本预算控制模型级联降级跨 Provider 搜索 模型能力与路由 2026-06-13 📐 P3
📋 待澄清「显示多开」:用户报"设置里勾选'显示多开'但 AiChat 未显示"。全 src grep 多开|多窗口|multi|multiInstance 零命中Settings.vue settings 对象仅 8 字段无此项。AiChat 唯一相关的是常驻「分离窗口」按钮(不受设置控制)。疑似:① 用户指分离窗口按钮(本就常驻不需设置);② 看的是打包旧版本界面;③ 想新增"允许分离窗口"设置开关。待用户截图/确认位置再定 AI Chat 2026-06-13 需求澄清
🔴 待审批持久化根治(重启恢复)未生效——两处逻辑断裂致恢复链路跑不通:① ai_conversation_switch 无条件 pending_approvals.clear() 清空 restore_pending_approvals(init)重建的内存 HashMapai_pending_tool_calls/ai_approve 均依赖内存态 → 重启后前端 switchConversation 触发 clear → 审批卡片查空永不显示、审批报"未找到挂起的审批";② ai_approve 的 recovered 守卫跳过 save_conversation(注释称"防空 messages 污染老对话"前提不成立——switch 时 restore_from_messages 已载完整历史,审批时 messages 非空 → 执行的工具结果不落库,重启后 toolCard 显示 completed 但 result 仍是占位"需要用户审批,等待确认"。修复方向pending 恢复链路改查 DBai_tool_executions WHERE status='pending' 持久化真相源)绕过内存 clearai_approve 内存 miss 时 fallback DB 单条重建再执行recovered 审批通过后正常 save。可顺带删 restore_pending_approvalsDB 即真相源)。阻断用户"功能逻辑层面解决"诉求——现"根治"实为表面修复 AI Chat 审批持久化 2026-06-13 /review 审查①② P0
📋 审批可见性缺口pendingApprovals 无兜底渲染→卡死 [2026-06-13]AI 发起 Med/High 工具审批AiApprovalRequired后暂停等审批不发 delta前端审批唯一出口是 ToolCard 的 pending_approval 内联卡片(靠 findToolCall 置 tc.status但 state.pendingApprovals 数组有数据却零渲染AiChat.vue 仅 @approve 转发,无 pendingApprovals 模板)。若 tc 卡片未显示审批,用户看不到审批按钮 → AI 永久等 → 文字停卡死。待修A. AiChat.vue 加 pendingApprovals 醒目渲染(顶部条/浮层)兜底审批可见性;或 B. 运行时确认 tc 卡片是否渲染。配套watchdog 在 AiApprovalRequired 暂停,审批没弹则 watchdog 盲点,需加"审批超时未响应"提示 AI Chat 审批 2026-06-13 📋 A/B 待定
📋 node_executions 全表 list当前只写不读若未来前端要看某次工作流执行的节点明细新增 list_node_executions(execution_id) 命令 工作流引擎 2026-06-13 代码审查 📐 待需求驱动

📋 需求澄清

  • 「决策」术语边界2026-06-12devflow 语境「决策/决策需求点」= 日常开发功能细节取舍(为什么这么定), aichat 决策能力升级B 路线 coordinator/conditions。后者属架构层记 Phase2计划/模块文档,不混入本文档。
  • 代码审查甄别原则2026-06-13审查发现问题时按「运行时失败/数据损坏 → 简单清理 → 记录不动 → 不做」四档甄别。当前项目规模下list_all 无 LIMIT、ALLOWED_COLUMNS 不分表、bool→int 重复等属「记录不动」——个人工具表不超千行,加分页/拆白名单是过度设计,维护成本 >> 收益。原则:真实 bug 修、简单清理做、规模不到位的优化先不动,保持全局简洁和扩展容易。

文档维护

文档历史项保留原则:标状态不删行 [2026-06-15]

  • 决策所有文档ARCHITECTURE.md + 模块文档)中的历史设计项一律保留原文不删除,仅在行末或旁注标注实现状态:✅ 已实现 / ❌ 未实现(设计预留) / ⚠️ 骨架空壳(有文件但无实质逻辑) / ~~已删~~R-PD-X 等重构决策引用)。
  • 原因/取舍:全量核对报告(2026-06-15)发现 ARCHITECTURE.md 含多出虚构/过时项(ModelRouter 已删/Docker 等 5 节点未实现)。初版方案为「删虚构行+注」,用户两次明确否决删方案,要求保留全部历史项+标状态。理由:① 保留设计演进痕迹,接手方可理解"曾经考虑过什么、为什么没做";② 删除会导致核对报告等交叉引用断链;③ 标状态列比删行信息量更大。
  • 影响范围DOC-260615-01~14 全部文档修项均遵循此原则。已落地ARCHITECTURE.md §5.4 ModelRouter 标 ❌ ~~已删~~ + §5.5 8 节点标 / commit be38a44
  • 状态 2026-06-15 落地(用户两次否决删方案后定稿,首批标注已 commit

相关文档