文档: 架构方案文档(意图识别论证+多主题愿景/论证+文档物理分类+边界清晰化)
squash合并: - 意图识别层论证(8维度+10业界佐证) - 多主题上下文管理愿景+并存论证+补充论证(多轮agentic) - 架构设计文档物理分类(四子目录+INDEX+命名规范+引用同步+边界清晰化) - 前端架构技术债清单归档
This commit is contained in:
113
docs/02-架构设计/INDEX.md
Normal file
113
docs/02-架构设计/INDEX.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# 02-架构设计 索引
|
||||
|
||||
> 创建:2026-06-19 | 维护:本目录文档增删时同步
|
||||
> 上级索引:[../INDEX.md](../INDEX.md)
|
||||
> 命名规范:见本目录 [文档记录规范-2026-06-14.md](./滚动规范/文档记录规范-2026-06-14.md) §九「文档命名规范」
|
||||
|
||||
本目录是 DevFlow 的**架构设计 / 设计决策 / 设计方案 / 构想**文档集合(不含实现流水,流水走 `PROGRESS.md`;不含审查报告,审查走 `05-代码审查/`)。
|
||||
|
||||
按**性质**分四类,每类一个子目录:
|
||||
|
||||
| 子目录 | 内容 |
|
||||
|---|---|
|
||||
| [滚动规范/](./滚动规范/) | 长期维护的真相源 / 规范 / 决策记录 |
|
||||
| [已编号方案/](./已编号方案/) | 带 F/B/CR 编号的方案文档 |
|
||||
| [专项设计/](./专项设计/) | 无编号的主题设计 / 审查派生方案 |
|
||||
| [构想审查/](./构想审查/) | 瞬时构想 / UX 改进方案 / 模块审查报告 / 论证 |
|
||||
|
||||
---
|
||||
|
||||
## 一、规范与决策记录(滚动维护)
|
||||
|
||||
长期维护的真相源 / 规范文档,跨多个 Sprint 持续追加。子目录:[滚动规范/](./滚动规范/)
|
||||
|
||||
| 文档 | 状态 | 核心内容 |
|
||||
|---|---|---|
|
||||
| [业务系统设计-2026-06-12.md](./滚动规范/业务系统设计-2026-06-12.md) | 🏗 ARCHITECTURE 载体 | 项目无独立 ARCHITECTURE.md,本文档为实质载体:产品定位 / crate 结构 / 数据模型 / Phase 规划 |
|
||||
| [Phase1架构决策-2026-06-12.md](./滚动规范/Phase1架构决策-2026-06-12.md) | 📐 ADR | Phase 1 引擎骨架阶段架构级选型(ADR-001 引擎不绑定业务 等) |
|
||||
| [功能决策记录-2026-06-14.md](./滚动规范/功能决策记录-2026-06-14.md) | 📋 滚动 | 功能**需求规格 + 设计决策规格**(为什么这么定 / 要做什么)。最高频引用(67 入链) |
|
||||
| [功能决策记录-归档-2026-06-14.md](./滚动规范/功能决策记录-归档-2026-06-14.md) | 🗄 归档只读 | 从主文档归档:纯流水 / 老 Sprint 决策 / UX 微调 / 已被取代细节 |
|
||||
| [经验记录-2026-06-14.md](./滚动规范/经验记录-2026-06-14.md) | 📋 滚动 | 踩坑 / 约定 / 技巧 / bug 排查教训 |
|
||||
| [文档记录规范-2026-06-14.md](./滚动规范/文档记录规范-2026-06-14.md) | 📐 规范 | 文档路由规则 / 职责矩阵 / 命名规范 / 治理 hook |
|
||||
| [功能创意池-2026-06-14.md](./滚动规范/功能创意池-2026-06-14.md) | 💡 待评估 | 5 架构创意(演化 / 时效 / 回溯 / 债务 / 契约),评估通过才转 concept |
|
||||
|
||||
---
|
||||
|
||||
## 二、架构设计方案(已编号,F/B/CR 系列)
|
||||
|
||||
带功能 / bug / review 编号的方案文档,编号对应 `todo.md` / `待审查.md` 跟踪项。子目录:[已编号方案/](./已编号方案/)
|
||||
|
||||
| 文档 | 编号 | 状态 | 核心内容 |
|
||||
|---|---|---|---|
|
||||
| [F-01-模型能力系统与智能路由设计-2026-06-16.md](./已编号方案/F-01-模型能力系统与智能路由设计-2026-06-16.md) | F-260614-01 | ✅ 已落地(路由改方向) | 模型配置四维度 / 探测器 / 厂商拉取 / 路由器 |
|
||||
| [F-02-技能联想使用-实施机制设计-2026-06-16.md](./已编号方案/F-02-技能联想使用-实施机制设计-2026-06-16.md) | F-260614-02 | 📐 设计 | `/` 联想技能 → AI 调用执行机制 |
|
||||
| [F-05-多模态实施方案设计-2026-06-16.md](./已编号方案/F-05-多模态实施方案设计-2026-06-16.md) | F-260614-05 | 🚧 阶段1-2已落地(形态偏离) | 多模态 content/parts 设计 + provider 适配 |
|
||||
| [F-07-df-ai-core-trait下沉设计-2026-06-14.md](./已编号方案/F-07-df-ai-core-trait下沉设计-2026-06-14.md) | F-260614-07 | ✅ 已落地 | LlmProvider trait 下沉新 crate df-ai-core |
|
||||
| [F-09-多会话并发架构设计-2026-06-19.md](./已编号方案/F-09-多会话并发架构设计-2026-06-19.md) | F-260616-09 | 📐 草案 | AiSession 单例 → 多会话并发(B 阶段)。**当前真相源** |
|
||||
| [F-09B-多会话并发设计-2026-06-16.md](./已编号方案/F-09B-多会话并发设计-2026-06-16.md) | F-260616-09 | 🗄 过时(被 F-09 取代) | 06-16 旧版,行号已过期。保留回溯,新设计看 F-09 |
|
||||
| [F-15-上下文管理增强设计-2026-06-16.md](./已编号方案/F-15-上下文管理增强设计-2026-06-16.md) | F-260616-15 | 📐 设计 | ContextManager 分段 / 压缩 / 裁剪 |
|
||||
| [B-03-人工审批响应机制-2026-06-14.md](./已编号方案/B-03-人工审批响应机制-2026-06-14.md) | B-260614-03 | ✅ 已落地(B-03a) | HumanNode execute subscribe/send/select 完整审批链 |
|
||||
| [B-260616-21排查方案-2026-06-16.md](./已编号方案/B-260616-21排查方案-2026-06-16.md) | B-260616-21 | 📐 排查方案 | 工具卡片重复渲染根因(audit 重复 emit Started) + 修复方案 |
|
||||
|
||||
---
|
||||
|
||||
## 三、专项设计文档(无编号,主题命名)
|
||||
|
||||
跨多个跟踪项的专题设计 / 审查发现派生方案。子目录:[专项设计/](./专项设计/)
|
||||
|
||||
| 文档 | 状态 | 核心内容 |
|
||||
|---|---|---|
|
||||
| [Agent架构说明-2026-06-14.md](./专项设计/Agent架构说明-2026-06-14.md) | 📐 现状盘点 | Agent 引擎单链 ReAct 能力边界(查实的事实,非构想) |
|
||||
| [规格契约自检机制-2026-06-14.md](./专项设计/规格契约自检机制-2026-06-14.md) | 📐 设计待落地 | 活契约(锚点 + AI 自检 + 子代理)取代独立 spec |
|
||||
| [AiNode自审实施方案-2026-06-16.md](./专项设计/AiNode自审实施方案-2026-06-16.md) | ✅ ②-⑤已落地 | AiNode 自审闸门 + verdict DAG 阻断 |
|
||||
| [secret下沉与provider注入方案-2026-06-16.md](./专项设计/secret下沉与provider注入方案-2026-06-16.md) | ✅ 方案 B 全量落地 | secret 纯密钥下沉 df-storage |
|
||||
| [patch_file工具设计-2026-06-15.md](./专项设计/patch_file工具设计-2026-06-15.md) | 📐 设计待实施(P0) | AI 局部编辑工具:old_text 精确匹配 + 三层防御 |
|
||||
| [generating状态机加固-2026-06-15.md](./专项设计/generating状态机加固-2026-06-15.md) | 📐 设计 | generating 生命周期状态机(guard 收敛) |
|
||||
| [密钥迁移健壮性-2026-06-15.md](./专项设计/密钥迁移健壮性-2026-06-15.md) | 📐 设计未实施 | 空 api_key 不覆盖未迁移态明文密钥 |
|
||||
| [条件表达式引擎-2026-06-15.md](./专项设计/条件表达式引擎-2026-06-15.md) | 📐 设计(R-PD-3) | ConditionEngine 接线 + 条件边求值 |
|
||||
| [工作流脚本执行边界-2026-06-15.md](./专项设计/工作流脚本执行边界-2026-06-15.md) | 📐 设计(R-PD-2) | ScriptNode 任意 shell 执行安全边界 |
|
||||
| [查询效率优化方案-2026-06-19.md](./专项设计/查询效率优化方案-2026-06-19.md) | 📐 待评审(PERF-260619-01) | SQL 下推 / 精确拉取 / 缓存 / 字段投影 |
|
||||
| [任务推进链实施路径-2026-06-16.md](./专项设计/任务推进链实施路径-2026-06-16.md) | 📐 规划定稿(D-01~04已决) | advance_task 走 df-nodes Node trait,4 阶段路径 |
|
||||
| [推进链阶段2实施路径-2026-06-16.md](./专项设计/推进链阶段2实施路径-2026-06-16.md) | 📐 设计(F-260616-06) | 工作流联动任务推进:task_id + 完成回调 + DAG 模板 |
|
||||
|
||||
---
|
||||
|
||||
## 四、构想 / 改进方案 / 审查报告(主题命名)
|
||||
|
||||
瞬时构想、UX 改进方案、模块审查报告、架构论证。子目录:[构想审查/](./构想审查/)
|
||||
|
||||
| 文档 | 状态 | 核心内容 |
|
||||
|---|---|---|
|
||||
| [任务推进构想-2026-06-14.md](./构想审查/任务推进构想-2026-06-14.md) | 📐 AI-First 推进链设计 | 任务由 AI 执行 → AI 自审 → 人工核对(人转审批者) |
|
||||
| [aichat审查报告-2026-06-14.md](./构想审查/aichat审查报告-2026-06-14.md) | 📋 审查(AR-1~11) | aichat 全链路 6 块发现 + 修复进度对照 |
|
||||
| [aichat异步审批构想-2026-06-14.md](./构想审查/aichat异步审批构想-2026-06-14.md) | 💡 构想 | 审批 pending 不卡对话 |
|
||||
| [aichat交互体验改进方案-2026-06-14.md](./构想审查/aichat交互体验改进方案-2026-06-14.md) | 📐 待讨论 | 消息编辑 / 流式渲染 / 对话管理 等非授权交互 |
|
||||
| [aichat授权体验改进方案-2026-06-14.md](./构想审查/aichat授权体验改进方案-2026-06-14.md) | 📐 待讨论 | tool_calls 风险分流授权机制 |
|
||||
| [aichat信息密度构想-2026-06-14.md](./构想审查/aichat信息密度构想-2026-06-14.md) | 💡 构想 | 卡片折叠 + 会话详情面板 |
|
||||
| [aichat流式Markdown渲染调研-2026-06-15.md](./构想审查/aichat流式Markdown渲染调研-2026-06-15.md) | 📐 调研(未实施) | AR-1 流式渲染优化:rAF 节流 / 块级 diff / 换库 |
|
||||
| [工作流审批审查报告-2026-06-14.md](./构想审查/工作流审批审查报告-2026-06-14.md) | 📋 审查 | 审批链路对抗审查(头号 bug human_node.rs:41 缺 await) |
|
||||
| [对抗论证裁决报告-2026-06-12.md](./构想审查/对抗论证裁决报告-2026-06-12.md) | 🗄 归档 | 项目方向三路对抗论证裁决(方向有价值 scope 须砍) |
|
||||
| [产品定位调整-2026-06-12.md](./构想审查/产品定位调整-2026-06-12.md) | 📐 方向 | 从「想法到代码」到「想法到创作」 |
|
||||
| [前后端类型对齐-2026-06-12.md](./构想审查/前后端类型对齐-2026-06-12.md) | 🗄 已过时 | ts-rs 代码生成未采用,正文枚举表不反映代码。**实际形态以 `crates/df-types/src/types.rs` 为准**(见正文顶部实施状态块) |
|
||||
| [多主题并存论证-2026-06-19.md](./构想审查/多主题并存论证-2026-06-19.md) | 📐 论证(供决策) | 多主题交织并行 8 维度论证:SOTA 准确率天花板 + 副作用工具误判代价 → 近期不做 |
|
||||
| [意图识别层论证-2026-06-19.md](./构想审查/意图识别层论证-2026-06-19.md) | 📐 论证(供决策) | 通用前置意图识别层 8 维度论证 + 触发时机 |
|
||||
| [多主题上下文管理愿景-2026-06-19.md](./构想审查/多主题上下文管理愿景-2026-06-19.md) | 💡 远期愿景 | 无感多主题对话:主题检测前置 + 多主题多摘要(关联 F-15 / 意图识别) |
|
||||
| [多主题并存补充论证-多轮模式-2026-06-19.md](./构想审查/多主题并存补充论证-多轮模式-2026-06-19.md) | 📐 论证(供决策) | agentic 多轮模式可突破天花板,但近期结论不变 |
|
||||
|
||||
---
|
||||
|
||||
## 文档命名规范摘要
|
||||
|
||||
完整规范见 [文档记录规范-2026-06-14.md](./滚动规范/文档记录规范-2026-06-14.md) §九。摘要:
|
||||
|
||||
| 类别 | 命名格式 | 示例 |
|
||||
|---|---|---|
|
||||
| 功能 / bug / review 方案 | `<编号>-<主题>-<日期>.md` | `F-09-多会话并发架构设计-2026-06-19.md` |
|
||||
| 滚动维护文档 | `<主题>-<日期>.md`(不带编号) | `功能决策记录-2026-06-14.md` |
|
||||
| 专题设计 / 构想 | `<主题>-<日期>.md`(主题含领域前缀如 `aichat` / `工作流`) | `aichat审查报告-2026-06-14.md` |
|
||||
|
||||
**被取代 / 过时文档**:不删,文件顶部加 `## 实施状态` 或 `> 过时` 块标注,本索引「状态」列标 🗄。
|
||||
|
||||
---
|
||||
|
||||
> **物理分类说明**(2026-06-19):本目录按性质分四个子目录物理归档(滚动规范 / 已编号方案 / 专项设计 / 构想审查),INDEX.md 留根做分类索引。文档间引用统一用相对路径(同子目录 `./`、跨子目录 `../子目录/`、跨 docs 目录 `../../02-架构设计/子目录/`)。
|
||||
@@ -39,7 +39,7 @@
|
||||
> **超出原设计、后追加的能力 — 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 闭环)待用户执行。
|
||||
> **⑥ 端到端联调 — 代码层完成,实测类待用户**:联调依赖 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` 注释)。
|
||||
>
|
||||
@@ -279,6 +279,6 @@ if has_tool_calls { /* push */ }
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [df-ai AI 集成模块](../03-模块文档/df-ai-AI集成模块-2026-06-12.md)
|
||||
- [aichat 审查报告-2026-06-14](./aichat审查报告-2026-06-14.md)
|
||||
- [流式 Markdown 渲染调研-2026-06-15](./aichat流式Markdown渲染调研-2026-06-15.md)
|
||||
- [df-ai AI 集成模块](../../03-模块文档/df-ai-AI集成模块-2026-06-12.md)
|
||||
- [aichat 审查报告-2026-06-14](../构想审查/aichat审查报告-2026-06-14.md)
|
||||
- [流式 Markdown 渲染调研-2026-06-15](../构想审查/aichat流式Markdown渲染调研-2026-06-15.md)
|
||||
@@ -114,7 +114,7 @@ D-04 路径取舍 ──▶ 阶段1 是否先行
|
||||
```
|
||||
### 🗺️ 任务推进链实施路径(2026-06-16 规划·供其他会话读取)
|
||||
|
||||
> 详见 [任务推进链实施路径-2026-06-16.md](./02-架构设计/任务推进链实施路径-2026-06-16.md)。
|
||||
> 详见 [任务推进链实施路径-2026-06-16.md](./任务推进链实施路径-2026-06-16.md)。
|
||||
> 推进能力实现度 0%。**阶段 1 已解除阻塞(D-01/D-03/D-04 三决策已定 2026-06-16),可启动 F-01~05**。
|
||||
> 核对纠正:AI 有 update_task/run_command 工具,无 run_workflow/advance_task。
|
||||
|
||||
@@ -247,7 +247,7 @@ R-P1-2(已修)解决的是 `shell::execute` 超时未 kill 子进程致僵
|
||||
## 七、落地动作清单
|
||||
|
||||
- [ ] 后端:`src-tauri/src/state.rs:227-229` 删除 `registry.register("script", ...)` + 加决策注释
|
||||
- [ ] 后端:`crates/df-nodes/script_node.rs` 顶部加注释「当前未注册到 NodeRegistry,见 docs/02-架构设计/工作流脚本执行边界-2026-06-15.md」
|
||||
- [ ] 后端:`crates/df-nodes/script_node.rs` 顶部加注释「当前未注册到 NodeRegistry,见 docs/02-架构设计/专项设计/工作流脚本执行边界-2026-06-15.md」
|
||||
- [ ] 前端:`src/views/ProjectDetail.vue` 下线 demoDag + runDemoWorkflow + 模板按钮(推荐 a)
|
||||
- [ ] 文档:本设计文档归档到 `docs/02-架构设计/`
|
||||
- [ ] 决策记录:补一条功能决策记录(ScriptNode 不注册的安全边界 + 未来 BuildNode 升力路径)
|
||||
453
docs/02-架构设计/专项设计/查询效率优化方案-2026-06-19.md
Normal file
453
docs/02-架构设计/专项设计/查询效率优化方案-2026-06-19.md
Normal file
@@ -0,0 +1,453 @@
|
||||
# PERF-260619-01 查询效率优化方案
|
||||
|
||||
> **状态**:方案设计完成,待评审
|
||||
> **日期**:2026-06-19
|
||||
> **范围**:DevFlow 前后端数据查询链路
|
||||
|
||||
---
|
||||
|
||||
## 一、探索分析
|
||||
|
||||
### 1.1 问题全景
|
||||
|
||||
当前 DevFlow 的数据查询链路存在 **6 个核心问题**,分布在后端 SQL 层、前端 store 层、前端视图层三个层面。
|
||||
|
||||
### 1.2 问题清单
|
||||
|
||||
| # | 层 | 问题 | 严重度 | 代码位置 |
|
||||
|---|---|---|---|---|
|
||||
| P1 | 后端 SQL | `list_tasks` 全量查询后内存 `retain` 过滤 project_id | 中 | `commands/task.rs:32-37` |
|
||||
| P2 | 前端视图 | `ProjectDetail.vue` 全量 `loadTasks()` 后 computed 过滤 | 中 | `ProjectDetail.vue onMounted` |
|
||||
| P3 | 前端视图 | `TaskDetail.vue` 独立 `projectApi.list()` 拉全量项目仅解析单个项目名 | 低 | `TaskDetail.vue load()` |
|
||||
| P4 | 前端视图 | `Dashboard.vue` 每次进入全量加载 projects+tasks+ideas | 低 | `Dashboard.vue loadAll()` |
|
||||
| P5 | 前端 store | 无跨视图缓存/去重,路由切换重复 IPC | 中 | `stores/project.ts` 全局 |
|
||||
| P6 | 后端 SQL | 无字段投影,列表场景返回完整 Record(含 description 大字段) | 低 | CRUD 层全局 |
|
||||
|
||||
### 1.3 问题详解
|
||||
|
||||
#### P1:`list_tasks` 内存过滤(中)
|
||||
|
||||
**现状**:
|
||||
```rust
|
||||
// commands/task.rs:32-37
|
||||
pub async fn list_tasks(state, project_id: Option<String>) -> Result<Vec<TaskRecord>, String> {
|
||||
let mut tasks = state.tasks.list_active().await.map_err(err_str)?; // SELECT * FROM tasks WHERE deleted_at IS NULL
|
||||
if let Some(pid) = project_id {
|
||||
tasks.retain(|t| t.project_id == pid); // 内存过滤
|
||||
}
|
||||
Ok(tasks)
|
||||
}
|
||||
```
|
||||
|
||||
**影响**:每次按项目筛选任务时,从 SQLite 拉取**全部未删除任务**(含 14 个字段含 description),然后在 Rust 端 `retain` 过滤。当前 6 个项目 ~15 个任务时影响极小,但随任务增长线性退化。
|
||||
|
||||
**注释中的判断**(task.rs:28):*"任务量小,无需 SQL 下推,避免新增专用查询方法"* — 当前成立,但需提前规划。
|
||||
|
||||
#### P2:`ProjectDetail.vue` 全量 loadTasks(中)
|
||||
|
||||
**现状**:
|
||||
```typescript
|
||||
// ProjectDetail.vue onMounted
|
||||
await store.loadProjects()
|
||||
await store.loadTasks() // 无参 → 全量拉取所有项目的任务
|
||||
// 然后 computed 前端过滤
|
||||
const projectTasks = computed(() =>
|
||||
store.tasks.filter(t => t.project_id === projectId.value)
|
||||
)
|
||||
```
|
||||
|
||||
**影响**:进入项目详情页时拉取**所有项目的全部任务**,仅为展示当前项目的任务。这与 `Tasks.vue` 的按项目筛选加载模式(B-260615-29 契约)不一致。
|
||||
|
||||
**根因**:`ProjectDetail.vue` 使用全局 `store.tasks` 单例 + computed 过滤,而非按 project_id 精确拉取。设计意图是"不覆盖全局 tasks 单例"(避免破坏 Tasks 视图的筛选状态),但代价是全量拉取。
|
||||
|
||||
#### P3:`TaskDetail.vue` 独立拉全量项目列表(低)
|
||||
|
||||
**现状**:
|
||||
```typescript
|
||||
// TaskDetail.vue load()
|
||||
const [t, ps] = await Promise.all([
|
||||
taskApi.get(taskId.value), // 拉单个任务 ✓
|
||||
projectApi.list(), // 拉全部项目 ✗ 仅为解析 project_id → name
|
||||
])
|
||||
```
|
||||
|
||||
**影响**:TaskDetail 绕过 store 直接调 `projectApi.list()`,拉取全部项目(含 description 大字段),仅为从 `projects.find(p => p.id === task.project_id)` 解析一个项目名。
|
||||
|
||||
**根因**:TaskDetail 设计为"绕 store 独立入口"(有本地 `df-data-changed` 监听补偿),不依赖全局 store 的 projects 数组。
|
||||
|
||||
#### P4:`Dashboard.vue` 全量三实体加载(低)
|
||||
|
||||
**现状**:
|
||||
```typescript
|
||||
// Dashboard.vue loadAll()
|
||||
await Promise.all([store.loadProjects(), store.loadTasks(), store.loadIdeas()])
|
||||
```
|
||||
|
||||
**影响**:每次进入 Dashboard 全量拉取三个实体。Dashboard 只需要:
|
||||
- 项目数 + 活跃任务数(统计)
|
||||
- 项目列表(名称 + 状态 + updated_at)
|
||||
- 灵感列表前 4 条(标题 + score + status)
|
||||
|
||||
但拉取了完整 Record(含 description / ai_analysis / scores 等大字段)。
|
||||
|
||||
**缓解因素**:store 是全局单例,如果用户先访问过其他页面(Tasks/Projects),数据已在 store 中。但 Dashboard 的 `loadAll` 无条件覆盖刷新。
|
||||
|
||||
#### P5:无跨视图缓存/去重(中)
|
||||
|
||||
**现状**:
|
||||
- `Tasks.vue onMounted` → `loadProjects() + loadTasks()`
|
||||
- `ProjectDetail.vue onMounted` → `loadProjects() + loadTasks()`
|
||||
- `Dashboard.vue onMounted` → `loadProjects() + loadTasks() + loadIdeas()`
|
||||
- `TaskDetail.vue load()` → `projectApi.list()`(绕 store)
|
||||
|
||||
**影响**:路由切换时(如 Tasks → ProjectDetail → Tasks),每次 onMounted 都重新发起 IPC 全量拉取。store 虽然是单例(数据在内存),但 `loadXxx` 方法无条件覆盖刷新,没有"数据未过期则跳过"的判断。
|
||||
|
||||
**根因**:store 的 load 方法无 dirty/timestamp 标记,无法判断"已有数据是否新鲜"。
|
||||
|
||||
#### P6:无字段投影(低)
|
||||
|
||||
**现状**:所有查询返回完整 Record。
|
||||
|
||||
- `ProjectRecord`:9 字段(含 description 可能很长)
|
||||
- `TaskRecord`:14 字段(含 description + output_json 可能很长)
|
||||
- `IdeaRecord`:13 字段(含 ai_analysis + scores + description)
|
||||
|
||||
列表场景(Tasks/Dashboard/Projects)只需要 id/name/status/priority 等少量字段,详情页才需要全字段。
|
||||
|
||||
**影响**:IPC 传输 + JSON 序列化开销。当前数据量小,影响不明显。
|
||||
|
||||
### 1.4 关键约束
|
||||
|
||||
| # | 约束 | 来源 | 影响 |
|
||||
|---|---|---|---|
|
||||
| C1 | `store.tasks` 必须反映 Tasks 视图当前筛选(activeProject),不能被无参 `loadTasks()` 覆盖为全量 | B-260615-29 契约 | P2 修复不能简单改为 `loadTasks(projectId)`,因为会覆盖全局 tasks 单例 |
|
||||
| C2 | 后端 AI 工具执行后 emit `df-data-changed`,前端按 entity 刷新对应列表 | AR-11 事件机制 | 优化时需保留联动;缓存策略需响应此事件失效 |
|
||||
| C3 | TaskDetail 绕 store 直接调 API,有本地 `df-data-changed` 监听补偿 | 设计决策 | P3 修复需考虑是否回归 store 或保持独立 |
|
||||
| C4 | 任务 status 只能走 `advance_task_atomic` 状态机 | 状态机收口 | 不影响查询优化,但 update_task 白名单已移除 status |
|
||||
| C5 | SQLite 本地存储,当前数据量小(~6 项目 ~15 任务) | 实际数据 | 短期性能影响极小,优化面向中长期数据增长 |
|
||||
| C6 | CRUD 层(`impl_repo!` 宏)无 SELECT 列裁剪、无 LIMIT/OFFSET 支持 | 架构现状 | P6 需扩展宏或新增专用查询方法 |
|
||||
|
||||
---
|
||||
|
||||
## 二、方案设计
|
||||
|
||||
### 2.1 设计原则
|
||||
|
||||
1. **渐进式**:分阶段实施,每阶段独立可交付、可验证
|
||||
2. **低风险**:优先做不改 API 契约的内部优化,外部行为不变
|
||||
3. **数据量驱动**:当前数据量小,不做过度设计;预留扩展点但不提前实现
|
||||
4. **不破坏 AR-11**:所有缓存/优化方案必须保留 `df-data-changed` 事件联动
|
||||
|
||||
### 2.2 分阶段实施计划
|
||||
|
||||
---
|
||||
|
||||
### Phase 1:SQL 下推 + 精确查询(低风险,高 ROI)
|
||||
|
||||
**目标**:消除后端全量查询 + 内存过滤,前端视图精确拉取所需数据。
|
||||
|
||||
**改动点**:
|
||||
|
||||
#### 1.1 TaskRepo 新增 `list_active_by_project`(后端)
|
||||
|
||||
```rust
|
||||
// crates/df-storage/src/crud/task_repo.rs
|
||||
impl TaskRepo {
|
||||
/// 列出指定项目的未删除任务
|
||||
pub async fn list_active_by_project(&self, project_id: &str) -> Result<Vec<TaskRecord>> {
|
||||
let conn = self.conn.clone();
|
||||
let project_id = project_id.to_owned();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let guard = conn.blocking_lock();
|
||||
let mut stmt = guard
|
||||
.prepare("SELECT id, project_id, title, description, status, priority, branch_name, assignee, workflow_def_id, base_branch, review_rounds, output_json, created_at, updated_at FROM tasks WHERE deleted_at IS NULL AND project_id = ?1 ORDER BY created_at DESC")
|
||||
.map_err(storage_err)?;
|
||||
let rows = stmt.query_map(params![project_id], |row| task_from_row(row)).map_err(storage_err)?;
|
||||
// ...collect
|
||||
}).await.map_err(storage_err)?
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
⚠️ **依赖注意(F-260619-01 idea_id)**:上方 SQL 硬编码 14 列,与 `list_active()` 完全重复。若 F-260619-01(TaskRecord 新增 `idea_id` 字段)先于本方案落地,`task_from_row` 会调 `row.get("idea_id")`,但 SQL 列表无此列 → rusqlite 报错。两案并行时须同步加列,或改用 `SELECT * FROM tasks WHERE ...`(rusqlite 允许结果集含 from_row 未消费的多余列)。
|
||||
|
||||
#### 1.2 `list_tasks` 命令层路由(后端)
|
||||
|
||||
```rust
|
||||
// commands/task.rs
|
||||
pub async fn list_tasks(state, project_id: Option<String>) -> Result<Vec<TaskRecord>, String> {
|
||||
match project_id {
|
||||
Some(pid) => state.tasks.list_active_by_project(&pid).await.map_err(err_str),
|
||||
None => state.tasks.list_active().await.map_err(err_str),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**外部行为不变**:API 签名 + 返回类型一致,前端零改动。
|
||||
|
||||
#### 1.3 `ProjectDetail.vue` 按项目精确拉取(前端)
|
||||
|
||||
**问题**:不能直接 `store.loadTasks(projectId)`,因为会覆盖全局 tasks 单例(违反 C1)。
|
||||
|
||||
**方案**:ProjectDetail 不用全局 `store.tasks`,改为本地 ref + 精确拉取:
|
||||
|
||||
```typescript
|
||||
// ProjectDetail.vue
|
||||
const localTasks = ref<TaskRecord[]>([])
|
||||
|
||||
onMounted(async () => {
|
||||
await store.loadProjects()
|
||||
localTasks.value = await taskApi.list(projectId.value) // 精确拉取
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
**收益**:从全量拉取 → 仅拉取当前项目任务。
|
||||
|
||||
⚠️ **必须配套(评审升级)**:ProjectDetail 当前**没有** `df-data-changed` 监听——它靠全局 `store.tasks`(App.vue 的 `startDataChangedListener` 刷新 store → computed 自动响应)间接获得 AR-11 联动。改为本地 ref 后这条链路**断裂**。必须在 onMounted 中新增本地 `df-data-changed` 监听:
|
||||
|
||||
```typescript
|
||||
// ProjectDetail.vue onMounted 新增(必须,非可选)
|
||||
let _unlistenDataChanged: (() => void) | null = null
|
||||
onMounted(async () => {
|
||||
await store.loadProjects()
|
||||
localTasks.value = await taskApi.list(projectId.value)
|
||||
// AR-11 本地监听:entity=task 时按当前 projectId 精确刷新
|
||||
_unlistenDataChanged = await listen<DfDataChangedPayload>('df-data-changed', (event) => {
|
||||
if (event.payload.entity === 'task') {
|
||||
taskApi.list(projectId.value).then(ts => { localTasks.value = ts })
|
||||
}
|
||||
})
|
||||
})
|
||||
onUnmounted(() => {
|
||||
_unlistenDataChanged?.()
|
||||
// ...existing unlisten cleanup
|
||||
})
|
||||
```
|
||||
|
||||
> **注意**:ProjectDetail 现有的 `store.startEventListener()` 是**工作流节点事件**监听(`workflowStore.startEventListener`),不是数据变更监听,两者不可混淆。
|
||||
|
||||
#### 1.4 `TaskDetail.vue` 改用 store 或 get_project(前端)
|
||||
|
||||
**方案 A**:改用 `store.projects` 复用全局缓存,不再独立 `projectApi.list()`:
|
||||
|
||||
```typescript
|
||||
// TaskDetail.vue
|
||||
const store = useProjectStore()
|
||||
const projectName = computed(() =>
|
||||
store.projects.find(p => p.id === task.value?.project_id)?.name ?? task.value?.project_id ?? '—'
|
||||
)
|
||||
// load() 只拉单个任务,不再拉全量项目
|
||||
async function load() {
|
||||
task.value = await taskApi.get(taskId.value)
|
||||
}
|
||||
```
|
||||
|
||||
⚠️ **前置条件(评审纠错)**:原方案声称"App.vue 根 onMounted 已有 projects 预加载",经核验**不成立**——App.vue onMounted 只做 appSettings/migrate/theme/locale/Agentic 轮次恢复/AR-11 listener 启动,**未调用 `store.loadProjects()`**。当前 projects 加载分散在各视图 onMounted 中(Tasks/ProjectDetail/Dashboard 各自调)。
|
||||
|
||||
采用方案 A 必须二选一补齐前置:
|
||||
- **A-1(推荐)**:App.vue onMounted 加 `await store.loadProjects()`(一行改动,全局受益,所有视图共享缓存)。
|
||||
- **A-2(保守)**:TaskDetail load() 内加 `if (store.projects.length === 0) await store.loadProjects()` lazy 补偿,不依赖全局预加载。
|
||||
|
||||
**方案 B**:两步查询单个项目,替代全量 `projectApi.list()`:
|
||||
|
||||
```typescript
|
||||
async function load() {
|
||||
task.value = await taskApi.get(taskId.value)
|
||||
// 拿到 task 后按 project_id 查单个项目
|
||||
if (task.value?.project_id) {
|
||||
const p = await projectApi.get(task.value.project_id)
|
||||
projectName.value = p?.name ?? task.value.project_id
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
方案 B 无先后依赖问题(串行两步,先 task 后 project),IPC 开销为查 1 条 vs 查全量。**不依赖全局 store 状态**,保持 TaskDetail"绕 store 独立入口"的设计一致性。
|
||||
|
||||
**推荐**:
|
||||
- 若同时实施 Phase 2 缓存 → **方案 A-1**(App.vue 预加载 + store 缓存,全链路最优)
|
||||
- 若只实施 Phase 1 → **方案 B**(零全局依赖,改动最小,不引入 store 耦合)
|
||||
|
||||
---
|
||||
|
||||
### Phase 2:前端缓存 + 去重(中等风险,中 ROI)
|
||||
|
||||
**目标**:避免路由切换时的重复 IPC,引入脏标记/时间戳缓存。
|
||||
|
||||
**改动点**:
|
||||
|
||||
#### 2.1 store 加载方法增加新鲜度判断
|
||||
|
||||
⚠️ **评审补充 — tasks 缓存筛选维度冲突**:`loadTasks(projectId?)` 带筛选参数。若 Tasks 视图选了项目 A(`store.tasks` 只含项目 A),30s 内切到 Dashboard 调 `loadTasks()` 无参全量——缓存命中跳过,但 `store.tasks` 仍是项目 A 子集,Dashboard 的 `stats.activeTasks` 统计错误。
|
||||
|
||||
**解决方案**:tasks 缓存须记录筛选维度,筛选变化时强制刷新:
|
||||
|
||||
```typescript
|
||||
// stores/project/state.ts 新增
|
||||
export const state = reactive({
|
||||
// ...existing...
|
||||
_projectsLoadedAt: 0,
|
||||
_tasksLoadedAt: 0,
|
||||
_ideasLoadedAt: 0,
|
||||
_tasksFilter: undefined as string | undefined, // 当前 tasks 缓存对应的筛选(undefined=全量)
|
||||
})
|
||||
|
||||
// stores/project/projects.ts
|
||||
const STALE_MS = 30_000 // 30s 内不重复拉取
|
||||
|
||||
async function loadProjects(force = false) {
|
||||
if (!force && Date.now() - state._projectsLoadedAt < STALE_MS && state.projects.length > 0) {
|
||||
return // 数据新鲜,跳过
|
||||
}
|
||||
state.loading = true
|
||||
state.projects = await projectApi.list()
|
||||
state._projectsLoadedAt = Date.now()
|
||||
}
|
||||
|
||||
// stores/project/tasks.ts — 筛选维度 + TTL 双判断
|
||||
async function loadTasks(projectId?: string, force = false) {
|
||||
const filter = projectId // undefined=全量, string=按项目
|
||||
// 筛选变化 → 强制刷新(防 Dashboard 拿到 Tasks 视图的子集)
|
||||
const filterChanged = state._tasksFilter !== filter
|
||||
if (!force && !filterChanged && Date.now() - state._tasksLoadedAt < STALE_MS) {
|
||||
return // 数据新鲜 + 筛选一致,跳过
|
||||
}
|
||||
state.loading = true
|
||||
state.tasks = await taskApi.list(filter)
|
||||
state._tasksLoadedAt = Date.now()
|
||||
state._tasksFilter = filter
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 AR-11 事件联动失效缓存
|
||||
|
||||
⚠️ **评审补充 — AR-11 条件刷新与缓存交互**:当前 AR-11 listener 的 task 分支有 `_activeTaskProject !== undefined` 守卫(CR-260615-26)。若 Tasks 视图未挂载(undefined),entity=task 时不触发 load,缓存也不失效。用户之后进 Tasks 时 onMounted 调 `loadTasks`,若缓存未过期则命中跳过——拿到过期数据。
|
||||
|
||||
**解决方案**:AR-11 失效缓存与条件刷新分离——缓存时间戳无条件清零(下次 load 必拉新),load 调用仍守卫:
|
||||
|
||||
```typescript
|
||||
// stores/project.ts startDataChangedListener
|
||||
if (entity === 'project') {
|
||||
state._projectsLoadedAt = 0 // 无条件失效缓存
|
||||
void projectsStore.loadProjects(true) // force 刷新
|
||||
} else if (entity === 'task') {
|
||||
state._tasksLoadedAt = 0 // 无条件失效缓存(下次任意视图 loadTasks 必拉新)
|
||||
if (_activeTaskProject !== undefined) {
|
||||
void tasksStore.loadTasks(_activeTaskProject === 'all' ? undefined : _activeTaskProject)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.3 Dashboard loadAll 利用缓存
|
||||
|
||||
⚠️ **评审补充 — Dashboard stats 对 tasks 全量的依赖**:Dashboard 的 `stats.activeTasks`(`project.ts:105`)从 `state.tasks` 算 `filter(t => t.status === 'in_progress').length`。若 `state.tasks` 是某项目子集(Tasks 视图留下的),统计偏小。Dashboard loadAll 须确保 tasks 全量:
|
||||
|
||||
```typescript
|
||||
// Dashboard.vue
|
||||
async function loadAll() {
|
||||
await Promise.all([
|
||||
store.loadProjects(), // 命中缓存则跳过
|
||||
store.loadTasks(), // 无参=全量;筛选维度变化时强制刷新(2.1 逻辑保证)
|
||||
store.loadIdeas(),
|
||||
])
|
||||
}
|
||||
```
|
||||
|
||||
> Dashboard 调 `loadTasks()` 无参(filter=undefined),若 Tasks 视图留下的 filter 是某项目 id,`filterChanged=true` → 强制全量刷新,stats 正确。
|
||||
|
||||
**风险**:
|
||||
- `df-data-changed` 必须可靠失效缓存(当前 AR-11 已覆盖 create/update/delete/restore/purge/bind_directory)
|
||||
- 用户在外部修改 SQLite(如直接操作数据库)后缓存不新鲜 — 桌面应用场景概率极低
|
||||
|
||||
---
|
||||
|
||||
### Phase 3:字段投影(低优先级,远期)
|
||||
|
||||
**目标**:列表场景只返回需要的字段,减少 IPC 传输 + 序列化开销。
|
||||
|
||||
**现状评估**:当前数据量极小(6 项目 15 任务),description 字段平均 ~500 字节,全量传输 < 10KB。**Phase 3 在数据量达到百级之前不需要实施。**
|
||||
|
||||
**预留方案**(不实施,仅记录):
|
||||
|
||||
```rust
|
||||
// 方向:impl_repo! 宏扩展 columns 参数,或新增 list_summary 方法
|
||||
pub async fn list_active_summary(&self) -> Result<Vec<ProjectSummary>> {
|
||||
// SELECT id, name, status, created_at, updated_at FROM projects WHERE ...
|
||||
}
|
||||
```
|
||||
|
||||
前端新增 `ProjectSummary` / `TaskSummary` 类型,列表视图用 Summary,详情页用完整 Record。
|
||||
|
||||
**成本**:需新增 DTO 类型 + 前端类型同步 + 视图适配,复杂度较高。
|
||||
|
||||
---
|
||||
|
||||
### 2.3 优先级矩阵
|
||||
|
||||
| Phase | 问题覆盖 | 风险 | ROI | 建议时机 |
|
||||
|-------|---------|------|-----|---------|
|
||||
| Phase 1 | P1 + P2 + P3 | 低(不改 API 契约) | 高 | **立即实施** |
|
||||
| Phase 2 | P4 + P5 | 中(缓存一致性) | 中 | Phase 1 验证后 |
|
||||
| Phase 3 | P6 | 低(纯新增) | 低(当前数据量) | 数据量达百级时 |
|
||||
|
||||
### 2.4 涉及文件
|
||||
|
||||
| Phase | 文件 | 改动类型 |
|
||||
|-------|------|---------|
|
||||
| 1.1 | `crates/df-storage/src/crud/task_repo.rs` | 新增 `list_active_by_project` 方法 |
|
||||
| 1.2 | `src-tauri/src/commands/task.rs` | `list_tasks` 路由分支 |
|
||||
| 1.3 | `src/views/ProjectDetail.vue` | 改用本地 ref + 精确拉取 + **新增 df-data-changed 本地监听** |
|
||||
| 1.4 | `src/views/TaskDetail.vue` | 方案 B:改用 `projectApi.get(id)` 单查;或方案 A-1/A-2 复用 store.projects |
|
||||
| 1.4-A1 | `src/App.vue` | (方案 A-1)onMounted 新增 `store.loadProjects()` 预加载 |
|
||||
| 2.1 | `src/stores/project/state.ts` | 新增时间戳 + `_tasksFilter` 字段 |
|
||||
| 2.2 | `src/stores/project/projects.ts` | loadProjects 加新鲜度判断 |
|
||||
| 2.3 | `src/stores/project/tasks.ts` | loadTasks 加筛选维度 + TTL 双判断 |
|
||||
| 2.4 | `src/stores/project.ts` | AR-11 listener 无条件失效缓存 + 条件刷新分离 |
|
||||
| 2.5 | `src/views/Dashboard.vue` | loadAll 利用缓存(筛选维度保证全量 tasks) |
|
||||
|
||||
### 2.5 验收标准
|
||||
|
||||
#### Phase 1
|
||||
1. `list_tasks(Some(pid))` 走 SQL WHERE 下推,不再内存过滤
|
||||
2. `ProjectDetail.vue` 不再全量 loadTasks,改为按 projectId 精确拉取
|
||||
3. `ProjectDetail.vue` 新增本地 `df-data-changed` 监听,entity=task 时刷新 localTasks
|
||||
4. `TaskDetail.vue` 不再独立 `projectApi.list()`(改用方案 B 单查或方案 A 复用 store)
|
||||
5. B-260615-29 契约不破坏(store.tasks 仍反映 Tasks 视图筛选)
|
||||
6. AR-11 事件联动正常(create/update/delete 后 ProjectDetail + Tasks 列表均刷新)
|
||||
7. 若选方案 A-1:App.vue onMounted 成功预加载 projects,TaskDetail projectName 正确解析
|
||||
8. 若 F-260619-01 已先行:`list_active_by_project` SQL 含 idea_id 列(或用 SELECT *)
|
||||
9. `cargo check --workspace` EXIT 0 + `vue-tsc` EXIT 0
|
||||
|
||||
#### Phase 2
|
||||
10. 30s 内路由切换不重复 IPC(store 缓存命中)
|
||||
11. `df-data-changed` 事件正确失效缓存并刷新
|
||||
12. Dashboard 统计数据准确(Tasks 视图筛选某项目后切 Dashboard,stats 不偏小)
|
||||
13. Tasks 视图未挂载时 AR-11 entity=task 事件仍清零缓存(下次进 Tasks 拿新数据)
|
||||
|
||||
### 2.6 风险评估
|
||||
|
||||
| 风险 | 概率 | 影响 | 缓解措施 |
|
||||
|------|------|------|---------|
|
||||
| ProjectDetail 改本地 ref 后 AR-11 不刷新任务 | **高** | 中 | **必须配套**:onMounted 新增本地 `df-data-changed` 监听,entity=task 时重新 `taskApi.list(projectId)`(详见 1.3) |
|
||||
| TaskDetail 改用 store.projects 时 projects 未加载 | 中 | 低 | App.vue onMounted **新增** `store.loadProjects()`(A-1),或 TaskDetail 内 lazy 补偿(A-2),或改用方案 B 完全规避 |
|
||||
| Phase 2 缓存筛选维度冲突致 Dashboard stats 错误 | 中 | 中 | tasks 缓存记录 `_tasksFilter`,筛选变化时 `filterChanged=true` 强制刷新(详见 2.1) |
|
||||
| Phase 2 AR-11 守卫 + 缓存致 Tasks 拿过期数据 | 中 | 低 | AR-11 无条件清零 `_tasksLoadedAt`(下次 load 必拉新),load 调用仍守卫(详见 2.2) |
|
||||
| Phase 2 缓存导致用户看到过期数据 | 低 | 低 | 30s TTL 短 + AR-11 强制失效 + 手动刷新按钮兜底 |
|
||||
| list_active_by_project SQL 列与 idea_id 不同步 | 中 | 中 | 两案并行时同步加列,或改用 `SELECT *`(详见 1.1) |
|
||||
| list_active_by_project SQL 注入 | 极低 | 高 | 使用参数化查询 `params![project_id]`,不走 `query` 宏的 field 拼接 |
|
||||
|
||||
---
|
||||
|
||||
## 三、决策记录
|
||||
|
||||
### D1:Phase 1 先行,Phase 2 视需
|
||||
|
||||
**理由**:Phase 1 是纯内部优化(SQL 下推 + 精确拉取),不改 API 契约,风险极低,ROI 明确。Phase 2 引入缓存层有一致性风险,待 Phase 1 验证后再评估必要性。
|
||||
|
||||
### D2:不实施 Phase 3(字段投影)
|
||||
|
||||
**理由**:当前数据量极小(< 10KB 全量传输),字段投影需新增 DTO 类型 + 前端类型同步 + 视图适配,成本远高于收益。当任务数达到 ~200+ 或 description 平均长度 > 5KB 时再评估。
|
||||
|
||||
### D3:ProjectDetail 用本地 ref 而非改 store 契约
|
||||
|
||||
**理由**:store.tasks 全局单例 + B-260615-29 筛选契约是硬约束(C1)。改 store 支持"多任务列表"会引入复杂度(哪个视图的数据?切换时怎么办?)。ProjectDetail 用本地 ref + 精确拉取更简单清晰,且 AR-11 可通过本地监听补偿。
|
||||
@@ -4,7 +4,7 @@
|
||||
> 类型:架构设计文档(不碰任何 code)
|
||||
> 关联:F-260614-05 多模态 Phase 2 / F-260614-04 多 Provider 负载均衡池
|
||||
> 前置:F-07 df-ai-core trait 下沉 ✅ 已完成(batch61·2069f79)
|
||||
> 决策记录:见 [功能决策记录-2026-06-14.md](./功能决策记录-2026-06-14.md) §「模型能力系统」行
|
||||
> 决策记录:见 [功能决策记录-2026-06-14.md](../滚动规范/功能决策记录-2026-06-14.md) §「模型能力系统」行
|
||||
|
||||
---
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
> 状态:📐 设计定稿(2026-06-16,未实施)
|
||||
> 类型:架构设计文档(不碰任何 code)
|
||||
> 关联:F-260614-01(Phase 1 模型能力,未实施)/ F-06 导入历史项目(已留 ImageRef 接口)
|
||||
> 决策记录:见 [功能决策记录-2026-06-14.md](./功能决策记录-2026-06-14.md) §「模型能力系统 Phase 2」行
|
||||
> 决策记录:见 [功能决策记录-2026-06-14.md](../滚动规范/功能决策记录-2026-06-14.md) §「模型能力系统 Phase 2」行
|
||||
|
||||
---
|
||||
|
||||
@@ -504,7 +504,7 @@ F-01 未落地前,阶段 1-3 已让多模态可用(静态白名单 + 手动
|
||||
|
||||
## 9. 决策记录锚点
|
||||
|
||||
以下决策已在 [功能决策记录-2026-06-14.md](./功能决策记录-2026-06-14.md) 记录或待补:
|
||||
以下决策已在 [功能决策记录-2026-06-14.md](../滚动规范/功能决策记录-2026-06-14.md) 记录或待补:
|
||||
- 「分阶段实施路线」§(行 134-138):Phase 1 不改 content / Phase 2 多模态 / Phase 3 Agent 内路由 —— 本文档展开 Phase 2。
|
||||
- 新增决策(建议补入功能决策记录,由后续会话触发 decision-record 技能):
|
||||
1. content 向后兼容用自定义 deserialize(String→单 Text 片),否决 untagged enum。
|
||||
@@ -290,5 +290,5 @@ F-260614-07(本任务:df-ai-core trait 下沉)
|
||||
---
|
||||
|
||||
**相关文档**:
|
||||
- [功能决策记录 — AI trait 下沉条目](./功能决策记录-2026-06-14.md) (决策记录主文档)
|
||||
- [功能决策记录 — 对抗评估启发式 fallback 待接 LLM](./功能决策记录-2026-06-14.md) (灵感模块条目)
|
||||
- [功能决策记录 — AI trait 下沉条目](../滚动规范/功能决策记录-2026-06-14.md) (决策记录主文档)
|
||||
- [功能决策记录 — 对抗评估启发式 fallback 待接 LLM](../滚动规范/功能决策记录-2026-06-14.md) (灵感模块条目)
|
||||
148
docs/02-架构设计/构想审查/多主题上下文管理愿景-2026-06-19.md
Normal file
148
docs/02-架构设计/构想审查/多主题上下文管理愿景-2026-06-19.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# 多主题上下文管理愿景
|
||||
|
||||
> 来源:用户架构愿景(2026-06-19)。未来方向,非近期实施。
|
||||
> 关联:[意图识别层论证](./意图识别层论证-2026-06-19.md)(主题检测前置) / F-15 上下文管理(基础已落地)
|
||||
|
||||
## 愿景
|
||||
|
||||
**无感多主题对话(交织并行)**:同一对话中多主题**交织并行**(A-B-A-B,非线性前 A 后 B 分段),系统自动识别主题归属 + 多主题上下文并存 + 交织路由,实现:
|
||||
- ✅ **省 token**:每主题独立摘要,非全历史(交织场景 A-B 混杂,主题隔离收益更大)
|
||||
- ✅ **提速**:短上下文(当前主题摘要),LLM 处理快
|
||||
- ✅ **提精准**:主题聚焦(B 噪声不干扰 A 处理),LLM 注意力集中,回复更准
|
||||
|
||||
### 场景(交织并行,用户深化)
|
||||
|
||||
```
|
||||
消息1 → 主题 A(新,如"处理 bug X")
|
||||
消息2 → 主题 B(新,A 仍活跃,如"加 feature Y")
|
||||
消息3 → 主题 A(补充,A-B 交织)
|
||||
消息4 → 主题 B(补充,A-B 并行)
|
||||
```
|
||||
|
||||
**关键**:多主题**同时活跃 + 交织**(非"前 A 段|后 B 段"线性,非"一主题完成才切")。主题数不定(2+)。
|
||||
|
||||
### 意图识别 = 核心前置(用户深化)
|
||||
|
||||
**多主题并存 → 每消息必须识别"归属哪个主题"**(否则无法路由:消息3 是 A 补充还是新主题 C?)。
|
||||
|
||||
- **意图识别**(输入意图/会话意图)= 多主题并存的**前置依赖**(每消息主题归属)
|
||||
- 多主题并存是意图识别的**核心应用场景**
|
||||
- 两者**绑定**:做多主题并存,必须先做意图识别
|
||||
- **触发条件调整**:多主题并存需求 = 意图识别的强触发(非仅图片/文档输入 或 工具>40)
|
||||
|
||||
## 与 F-09 多会话的关系(架构复用)
|
||||
|
||||
- **F-09 多会话**(已落地 d899c58)= **会话级隔离**(conv_id,`HashMap<conv_id, PerConvState>`)
|
||||
- **多主题并行** = **会话内主题级隔离**(topic = 轻量会话)
|
||||
- **架构复用**:F-09 per_conv 模式 → 会话内 topic 层级
|
||||
|
||||
```
|
||||
conv_id(会话)
|
||||
└─ topics: HashMap<topic_id, {messages, summary, last_active}>
|
||||
├─ topic A(消息1,3...)
|
||||
├─ topic B(消息2,4...)
|
||||
└─ ...
|
||||
```
|
||||
|
||||
**多主题 = F-09 多会话的"会话内"深化**(topic 级 per-conv)。PerConvState/ContextManager 隔离模式复用到 topic 层。
|
||||
|
||||
## 与现有架构关系
|
||||
|
||||
| 现有 | 现状 | 愿景进化 |
|
||||
|---|---|---|
|
||||
| **F-15 上下文管理**(分段 archived_segment / 压缩 compressed) | ✅ 已落地(commit 4194842 等),按 **token 阈值**(budget*0.6)触发压缩 | **主题感知**:按主题边界分段,非 token 阈值 |
|
||||
| **ContextManager**(context.rs) | 单摘要/单分段 | **多摘要并存**(每主题一份) |
|
||||
| **意图识别**(预留 coordinator/intent.rs) | 空白(近期不做) | **主题检测前置**(主题=意图维度;图片/文档输入时启动) |
|
||||
| **router**(模型路由) | 静态 weight | 主题/意图→模型(远期) |
|
||||
|
||||
## 多主题识别与摘要
|
||||
|
||||
### 主题切换检测
|
||||
- **embedding 相似度**:当前消息 vs 历史主题向量,相似度低于阈值 = 新主题
|
||||
- **LLM 分类**:fast model 判主题归属(准但延迟)
|
||||
- **关键词/规则**:主题关键词变化(快但弱)
|
||||
- **渐进**:规则→embedding→LLM(随规模升级)
|
||||
|
||||
### 每主题独立摘要
|
||||
- 主题段(主题边界内消息)→ LLM 摘要 → **多摘要并存**(ContextManager 扩展:HashMap<topic_id, summary>)
|
||||
- 复用 F-15 `compress_prompt` 四段式(意图/决策/文件/约束),按主题
|
||||
- 摘要触发:主题切换时(非 token 阈值)
|
||||
|
||||
### 上下文按主题分段
|
||||
- 当前:`build_eviction_units` 三元组(保护区 + 可压缩)
|
||||
- 愿景:主题边界分段(每主题一段,切换时归档前主题 + 摘要)
|
||||
|
||||
## 智能摘要切换
|
||||
|
||||
### 当前主题识别
|
||||
- 用户消息 → 归属主题(检测:延续当前主题 / 切换新主题 / 回到旧主题)
|
||||
|
||||
### 上下文路由(主题→摘要)
|
||||
- 当前主题摘要 + 关键历史(其他主题摘要压缩/可选展开)
|
||||
- 无感切换(用户不手动切,系统自动选摘要)
|
||||
|
||||
### 场景
|
||||
- 用户聊主题 A(代码)→ 切主题 B(闲聊)→ 回主题 A:系统保留 A 摘要,B 切换时归档,回 A 时恢复 A 摘要(非全历史 reload)
|
||||
|
||||
## 收益量化(预估)
|
||||
|
||||
- **省 token**:多主题对话,每主题摘要 ~500-1000 token,vs 全历史 ~5-10K token(累积),**降幅 80%+**(长对话多主题)
|
||||
- **提速**:短上下文(当前主题),LLM 首 token 快 + 处理快
|
||||
- **提精准**:主题聚焦,LLM 不被跨主题噪声干扰
|
||||
|
||||
## 可行性
|
||||
|
||||
| 组件 | 实现 | 基础 |
|
||||
|---|---|---|
|
||||
| 主题检测 | embedding/LLM/关键词 | 新增(intent.rs 扩展) |
|
||||
| 多主题摘要 | ContextManager 扩展(HashMap<topic, summary>) | F-15 压缩基础 |
|
||||
| 智能切换 | 上下文路由(topic→summary) | 新增 |
|
||||
| 持久化 | 每主题摘要落 DB | conversation 扩展 |
|
||||
|
||||
## 实现路径(远期,分阶段)
|
||||
|
||||
1. **主题检测**(规则/embedding):消息→主题标签
|
||||
2. **主题分段**:ContextManager 按主题边界分段(替代 token 阈值)
|
||||
3. **多主题摘要**:每主题 LLM 摘要 + HashMap 存
|
||||
4. **智能切换**:当前主题识别 + 摘要路由
|
||||
5. **持久化**:主题摘要落 DB(跨会话恢复)
|
||||
|
||||
## 风险评估(用户深化·误判代价不对称)
|
||||
|
||||
### 误判代价不对称(核心风险)
|
||||
- **不做多主题**(全历史 A-B 混杂):LLM 信息在,可能跑题但**用户可纠正**(信息未丢)
|
||||
- **多主题误判**(消息3[A 补充]误判为 B):路由 B 上下文 → LLM 用 B 回 A → **完全错位**(比全历史更糟,信息丢失)
|
||||
|
||||
**误判 > 不隔离代价**。意图识别准确性是**硬约束**(必须高准确,否则不如不做)。
|
||||
|
||||
### fallback 策略(前提,降误判代价)
|
||||
- **低置信度→全历史**:意图识别不确定时**不隔离**(安全降级,避免走偏)
|
||||
- **摘要并存**:即使误判 A/B 摘要都在,信息不丢(LLM 可选/用户纠正)
|
||||
- **用户显式纠正**:"这是 A 主题"→ 重新路由(手动 override)
|
||||
|
||||
### 复杂度 vs 收益 vs 准确性
|
||||
- **复杂度**(高):主题识别(意图瓶颈)+ 多主题上下文管理(HashMap/交织路由/摘要)+ 持久化
|
||||
- **收益**(中,长对话交织):省 token + 提精准
|
||||
- **准确性风险**(高):embedding/LLM 分类中文意图+交织主题挑战大,准确率不够→误判走偏→比不做更糟
|
||||
|
||||
## 结论(近期不值得,远期可行)
|
||||
|
||||
- **近期不值得**:复杂度高 + 意图准确性瓶颈 + 误判代价不对称 → ROI 低。F-15(token 阈值)+ F-09(多会话手动切)够用
|
||||
- **远期可行**:意图识别准确率有保障(技术成熟/数据积累)+ 长对话交织场景多时,**fallback 是前提**(低置信度降级全历史)
|
||||
|
||||
## 触发条件(何时做)
|
||||
|
||||
- 当前 F-15(token 阈值压缩)够用,多主题是**长对话多主题场景**优化
|
||||
- 触发:用户反馈长对话跨主题时上下文混乱 / token 成本高 / 回复跑题
|
||||
- 依赖:意图识别(主题检测)**准确率有保障 + fallback 健壮**(非仅预留就绪)
|
||||
|
||||
## 与意图识别关系
|
||||
|
||||
- **主题识别 = 意图识别的一种**(主题是意图维度:代码/闲聊/搜索/项目/...)
|
||||
- 意图识别预留(图片/文档输入时启动),主题摘要可**先于完整意图识别**(主题检测独立于模型路由)
|
||||
- 两者共享前置层(coordinator/intent.rs 落地)
|
||||
|
||||
## 备注
|
||||
|
||||
- 用户原话:「多主题识别与摘要 + 智能摘要切换 → 无感多主题对话 + 上下文压缩(省 token)+ 提速 + 提精准」
|
||||
- 这是**远期愿景**,近期 F-15(token 阈值)够用。触发条件达成时启动。
|
||||
60
docs/02-架构设计/构想审查/多主题并存补充论证-多轮模式-2026-06-19.md
Normal file
60
docs/02-架构设计/构想审查/多主题并存补充论证-多轮模式-2026-06-19.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# 多主题并存补充论证:多轮模式(agentic 意图识别)
|
||||
|
||||
> 来源:multitopic-analysis 子代理补充(IRCoT/ReAct/Reflexion/FLARE/AwN/ECLAIR/Copilot/Cursor 硬数据)+ 用户深化(多轮请求上下文 + 实体 NER + 异步预热 + 边界场景)。
|
||||
> 对原报告(多主题并存论证-2026-06-19.md)维度 2/3/4/6/8 的修正。纯论证,不改代码。
|
||||
|
||||
## 核心修正
|
||||
|
||||
**原报告**:准确率天花板是硬约束(SOTA 55.8/73%,不可绕过)。
|
||||
**修正**:agentic 多轮模式**确实能突破天花板**(硬数据支撑),准确率从被动分类 55.8/73% → 可能 85%+。
|
||||
|
||||
## 突破证据(SOTA 硬数据)
|
||||
|
||||
| 模式 | 增益 | 来源 |
|
||||
|---|---|---|
|
||||
| IRCoT(检索+CoT 交替) | QA F1 **+7~15** | ACL 2023 |
|
||||
| ReAct(推理+行动) | 准确率 **+30%** | NeurIPS 2022 |
|
||||
| Reflexion(反思修正) | pass@1 **91% vs 80%**(+11%) | NeurIPS 2023 |
|
||||
| Agentic RAG(多跳) | 34% → 89%(+55pp) | Medium |
|
||||
|
||||
## 但仍有约束(修正不改变近期结论)
|
||||
|
||||
1. **>90% 仍是硬线**:devflow 有副作用工具(销账/状态机/文件写),Reflexion 91% 是上限非保证,**须沙箱实测**(不能假设 devflow 场景达标)
|
||||
2. **增益对场景敏感**:FLARE 大场景仅 56.5%;简单请求多轮无收益反增延迟
|
||||
3. **边界场景 30-50% fallback 不变**:多轮不消除边界(模糊/跨主题/新主题),ROI 仍稀释
|
||||
4. **三重栈复杂度**:多轮编排 + 实体 NER + 异步预热 ~1300-1700 行 + 意图层先决(远期重投入)
|
||||
5. **异步预热解"慢"**(关键技术):Copilot(sub-200ms 日 4 亿次)/ Cursor(生产落地)证明可行,但实现复杂度最高(草稿预分析 + 就绪判断 + 取消/重试 + 状态隔离)
|
||||
6. **主动澄清 vs 无感张力**:业界范式(AwN/ECLAIR)倾向"低置信→主动问用户",违反"无感"愿景
|
||||
|
||||
## 修正后分阶段路径
|
||||
|
||||
```
|
||||
近期(0-3月):不做(原结论不变)
|
||||
- 多轮是有前景的远期方向,但当前技术栈不具备(意图层未落/异步预热未建/多轮未验证)
|
||||
|
||||
中期(3-12月,低风险试点,按 ROI 排序):
|
||||
1. 用户显式标主题(零误判)
|
||||
2. 意图识别层 intent.rs 工具级落地(独立ROI + 多主题先决)
|
||||
3. 半自动高门槛(embedding>95%才隔离,多轮暂不上)
|
||||
|
||||
远期(12+月,完整 agentic 多主题):
|
||||
技术栈:意图层(稳定) + 异步预热(解延迟) + 多轮编排(IRCoT/Reflexion) + 实体NER
|
||||
触发(全部满足):准确率实测>90% + 异步预热就绪 + 意图层稳定 + 真实痛点
|
||||
顺序锁定:意图层 → 异步预热 → 多轮+NER(不可颠倒)
|
||||
```
|
||||
|
||||
## 关键风险
|
||||
|
||||
- **不能假设 devflow 场景多轮一定达>90%**:Reflexion 91% 是受控 benchmark,devflow 交织主题 + 副作用工具更难,**必须沙箱实测**
|
||||
- **"继续"/"1"短指代消息**:全历史 LLM 天然消解(零逻辑,可靠);多主题下需路由(继承上一条主题),若上一条误判则错误传播
|
||||
|
||||
## Sources
|
||||
|
||||
- [IRCoT (ACL 2023)](https://aclanthology.org/2023.acl-long.557/)
|
||||
- [ReAct (NeurIPS 2022)](https://arxiv.org/abs/2210.03629)
|
||||
- [Reflexion (NeurIPS 2023)](https://arxiv.org/abs/2303.11366)
|
||||
- [FLARE 复测 56.5%](https://beancount.io/bean-labs/research-logs/2026/05/18/flare-active-retrieval-augmented-generation)
|
||||
- [AwN Learning to Ask](https://arxiv.org/html/2409.00557v3)
|
||||
- [ECLAIR (AAAI)](https://ojs.aaai.org/index.php/aaai/article/view/35152/37307)
|
||||
- [GitHub Copilot 工程](https://github.blog/ai-and-ml/github-copilot/the-road-to-better-completions-building-a-faster-smarter-github-copilot-with-a-new-custom-model/)
|
||||
- [Cursor + Fireworks](https://fireworks.ai/blog/cursor)
|
||||
72
docs/02-架构设计/构想审查/多主题并存论证-2026-06-19.md
Normal file
72
docs/02-架构设计/构想审查/多主题并存论证-2026-06-19.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 多主题并存(交织并行)多角度论证
|
||||
|
||||
> 来源:multitopic-analysis 子代理 8 维度论证 + WebSearch SOTA 硬数据 + 业界产品派/学术派佐证。
|
||||
> 纯架构论证,不改代码。供架构决策。
|
||||
|
||||
## TL;DR
|
||||
|
||||
**近期不做自动多主题路由**。SOTA 准确率天花板(55.8/73%)远低>90% 硬阈值 + devflow 有副作用工具(误判不可逆) + 边界场景 30-50% 降级稀释 ROI + 业界零参照(头部产品全用物理隔离)。
|
||||
|
||||
## 核心结论(数据驱动)
|
||||
|
||||
### 1. 准确率天花板是硬约束(不可绕过)
|
||||
- **TopiOCQA F1 = 55.8**(最贴近 A-B-A-B 交织 SOTA,TACL 2022)→ 误判率 25-45%
|
||||
- **MultiWOZ DST JGA ≈ 73.6%**(受控,开放域更差)
|
||||
- devflow 硬阈值(有副作用工具):**需 >90-95%** 才值得做
|
||||
- **当前 SOTA 远低于阈值** → 自动路由不具备落地条件
|
||||
|
||||
### 2. 误判代价不对称(因 devflow 有副作用工具)
|
||||
- 不做多主题(全历史):信息冗余但**都在**,可逆
|
||||
- 多主题误判(消息3[A]误判 B):信息**错误路由**,LLM 用 B 回 A → **完全错位**
|
||||
- devflow 工具(销账/状态机/文件写)**不可逆** → 误判触发不可逆副作用,**比全历史更糟**
|
||||
|
||||
### 3. 业界零参照(头部产品全用物理隔离)
|
||||
- ChatGPT:Projects(用户手动分会话)
|
||||
- Claude/Claude Code:memory 按 Project 隔离
|
||||
- Cursor 2.0:子代理 + git worktree 物理隔离
|
||||
- Devin 2.0:拆任务到隔离 VM
|
||||
- Cline:Tasks 独立会话,跨 session 不传上下文
|
||||
- **无一做单会话内自动主题路由** → devflow 若做是先行者(高风险)
|
||||
|
||||
### 4. 边界场景频率致命稀释 ROI
|
||||
- 新主题/通用寒暄(15-25%)+ 模糊不能明确 A/B(10-15%)+ 跨主题对比(5-10%)= **30-50% 消息降级全历史**
|
||||
- 代价 100% 承担(复杂度+误判风险),收益只作用于 50-70% 消息 → **ROI 为负**
|
||||
|
||||
### 5. 长上下文不救场
|
||||
- **lost-in-the-middle**(Liu et al. TACL 2023,被引 4690+):长上下文 U 型退化
|
||||
- A-B-A-B 切回旧主题 A 时,A 历史信息可能落在"中间段"被遗忘 → 即使全历史也在,关键信息仍可能丢
|
||||
|
||||
## 分阶段路径
|
||||
|
||||
| 阶段 | 触发条件 | 动作 |
|
||||
|---|---|---|
|
||||
| **近期**(0-3月) | 现状(29工具,单provider,中短对话) | **不做**,F-09+F-15 够用,储备设计 |
|
||||
| **中期**(3-12月) | 用户主动反馈痛点 | 试点**显式标主题**(用户手动标,零误判)或**半自动 fallback**(高门槛>95%才隔离) |
|
||||
| **远期**(12+月) | 准确率>90% + 意图层稳定 + 真实痛点(三者齐备) | 完整自动多主题 + 强 fallback |
|
||||
|
||||
**中期试点原则**:**绝不直接上全自动路由**。优先"用户显式标主题"(零误判)或"半自动高门槛"(embedding>95% 才隔离,其余全历史)。
|
||||
|
||||
## fallback 是硬要求(任何阶段)
|
||||
|
||||
- **置信度必须**(低→全历史不隔离)
|
||||
- **业界范式**:Rasa/工业对话系统用"阈值+双层 fallback(OOS/低置信澄清)",非"自动全历史兜底"
|
||||
- "低置信→全历史"看似安全,实则(a)token 高 (b)放大 lost-in-the-middle (c)边界 30-50% 触发 → **多主题愿景在边界退化为不做多主题**
|
||||
|
||||
## 与 F-09 关系(架构可行但非瓶颈)
|
||||
|
||||
- F-09 多会话(已落地 d899c58)铺路 85%:per_conv/ContextManager/压缩/持久化可复用到 topic 层
|
||||
- 多主题 = F-09 的"会话内"深化(topic 级 per-conv),架构改动 ~650-800 行
|
||||
- **架构就绪 ≠ 值得做**:真正瓶颈是准确率天花板 + 误判代价,非架构
|
||||
|
||||
## Sources
|
||||
|
||||
- [TopiOCQA F1=55.8](https://direct.mit.edu/tacl/article/doi/10.1162/tacl_a_00471/110550/)
|
||||
- [MultiWOZ 2.4 JGA≈73.6%](https://github.com/smartyfh/multiwoz2.4)
|
||||
- [Lost in the Middle](https://arxiv.org/abs/2307.03172)
|
||||
- [RAG 错误不可逆](https://aclanthology.org/2026.eacl-long.147.pdf)
|
||||
- [Pinecone Less is More](https://www.pinecone.io/blog/why-use-retrieval-instead-of-larger-context/)
|
||||
- [Rasa Failing Gracefully](https://medium.com/rasa-blog/failing-gracefully-with-rasa-8ead6b43f2f4)
|
||||
- [Claude memory per-project](https://simonwillison.net/2025/Sep/12/claude-memory/)
|
||||
- [Cursor 2.0 parallel agents](https://medium.com/towards-data-engineering/parallel-ai-agents-in-cursor-2-0-a-practical-guide-e808f89cffb9)
|
||||
- [Devin Manage Devins](https://cognition.ai/blog/devin-can-now-manage-devins)
|
||||
- [Cline Tasks](https://docs.cline.bot/core-workflows/task-management)
|
||||
106
docs/02-架构设计/构想审查/意图识别层论证-2026-06-19.md
Normal file
106
docs/02-架构设计/构想审查/意图识别层论证-2026-06-19.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# 意图识别层(通用前置)多角度论证
|
||||
|
||||
> 来源:intent-analysis 子代理 8 维度论证 + WebSearch 10 业界佐证 + devflow 源码核验。
|
||||
> 纯架构论证,不改代码。供架构决策。
|
||||
|
||||
## 核心结论
|
||||
|
||||
1. **方向正确**:意图识别作为通用前置层(每消息),服务四下游(工具预选/模型路由/上下文策略/审批预估)——业界共识(TianPan/NVIDIA/LangChain 佐证),用户洞察准确。
|
||||
2. **当前不急**:devflow 29 工具处于业界"产品派不做意图层"临界点(Claude Code <20 工具不分类 / OpenAI 原生 tool_choice 非前置),痛点不致命(未到 417 工具崩 20% 线)。
|
||||
3. **近期建议**:精简工具描述降 token(零架构改动,立即可做)。
|
||||
4. **中期触发**(工具>40 或多模型用户):上**方式 A 规则**(零延迟零成本纯赚),落 `intent.rs` + tool domain 标签。
|
||||
5. **远期升级**(工具>80 或 MCP):**方式 D 两阶段**(规则兜底 + Flash 分类),警惕 Tool RAG 生产退化(《340 Tools》反例)。
|
||||
6. **落地约束**:意图层只在 `agentic/mod.rs` loop 入口生效一次,不进 loop 体;输出"子集扩充+模型建议"非"硬性裁剪";None fallback 全量零回归。
|
||||
7. **架构兼容**:与双轨/审计/provider 工厂三高杠杆零冲突;`coordinator.rs` 空壳保留 B 路线多 Agent,意图层独立落 `intent.rs`。
|
||||
|
||||
## 痛点量化(现状)
|
||||
|
||||
- **工具全量下发**:`agentic/mod.rs:423 tool_definitions()` 全 29 工具 schema 每消息塞 request,~6000-8000 token/消息(中位估算)。
|
||||
- **模型路由静态化**:`router.rs:56-63` TaskRequirements 硬编码 needs_tool_use=true/modalities=[Text],闲聊和写代码走同模型。
|
||||
- **coordinator.rs 空壳**:B 路线占位(L5-30),意图识别无落脚点。
|
||||
- **上下文策略纯阈值**:`agentic/mod.rs:513-641` 自动压缩按 token>budget*0.6,不按意图。
|
||||
|
||||
## 实现方式对比
|
||||
|
||||
| 方式 | 延迟 | token | 准确 | 推荐 |
|
||||
|---|---|---|---|---|
|
||||
| A.规则/关键词 | <1ms | 0 | 中(中文意图,覆盖70%+) | ⭐ 近期 |
|
||||
| B.embedding | 10-50ms | 0+1次embedding | 中 | ✗ ROI低(单用户桌面) |
|
||||
| C.fast model | 300-800ms | ~200-500 | 高 | 中期补(盈亏工具>40+多模型) |
|
||||
| D.两阶段(A+C) | 混合 | 混合 | 高 | ⭐ 远期 |
|
||||
|
||||
## 收益量化(方式 A 规则,中期)
|
||||
|
||||
- 工具子集降 token:29→8-12 子集,**省 4000-5000 token/消息,降幅 60%**。
|
||||
- 模型路由省成本:60% 闲聊→Flash(¥0.0014/M)/ 40% 工具→Plus(¥5/M),**混合均价降 60%**(多模型用户)。
|
||||
- 决策准确:工具数 <10 时 LLM 选错概率显著降(反推 417→20% 数据)。
|
||||
- 审批预估前置:前端预判 High 风险,提前提示。
|
||||
|
||||
## 盈亏平衡(方式 C fast model)
|
||||
|
||||
| 维度 | 阈值 | devflow 现状 | 值得上 C? |
|
||||
|---|---|---|---|
|
||||
| 工具数 | >40 | 29 | 临界,即将 |
|
||||
| 多模型 | 用户配 Flash+Plus | 多数单 provider | 多数无收益 |
|
||||
| 延迟容忍 | 接受 +500ms 首字 | 流式敏感 | 负面 |
|
||||
|
||||
**结论**:方式 A 规则零成本纯赚(近期可上);方式 C 盈亏在"工具>40 且多模型"之后。
|
||||
|
||||
## 风险 + fallback
|
||||
|
||||
| 风险 | 缓解 |
|
||||
|---|---|
|
||||
| 意图误判(漏工具) | **子集扩充非裁剪**(project+file 兜底,18 工具仍<29) |
|
||||
| 单点故障 | None fallback 全量工具(零回归) |
|
||||
| 延迟敏感 | 方式 A 无延迟;C 需并行/异步预热 |
|
||||
| Flash 超时/非法 | fallback 全量/规则结果 |
|
||||
|
||||
**关键设计原则**:意图层是"加权推荐"非"硬性裁剪";None 时全量(现状)零回归。
|
||||
|
||||
## 业界佐证(WebSearch 10 来源)
|
||||
|
||||
**学术/框架派**(主张前置意图层):
|
||||
- TianPan《Intent Classification Layer》(417 工具崩 20%,论证需专用前置层)
|
||||
- NVIDIA AIQ《Intent Classifier》(单次 LLM 多输出:意图+元响应+判定)
|
||||
- Medium《Intent-to-Action Layer》(prompt→intent→structure→policy→route→tools→execution)
|
||||
- LangChain《Context Engineering》(RAG 工具描述,只发相关工具)
|
||||
- Red Hat《Tool RAG》(企业级工具扩展解法)
|
||||
|
||||
**产品派**(工具可控时不做前置):
|
||||
- OpenAI function calling(tool_choice 是"约束"非"前置分类",意图责任留开发者)
|
||||
- Claude Code 子代理(任务级路由,非消息级;<20 核心工具不做意图层)
|
||||
|
||||
**反例(警惕)**:《OpenAI 340 Tools 生产案例》——语义工具选择初期有效但准确率随时间退化,需持续监控。
|
||||
|
||||
**定价**:智谱 GLM Plus ¥5/M vs Flash ¥0.0014/M(500倍差,意图路由省钱空间)。
|
||||
|
||||
## devflow 整合(改动面)
|
||||
|
||||
| 模块 | 现状 | 接入点 | 改动 |
|
||||
|---|---|---|---|
|
||||
| coordinator.rs | B 路线空壳 | 保留(多Agent) | 不动 |
|
||||
| **intent.rs**(新增) | — | 意图识别落点 | ~200 行(规则引擎+Intent 枚举) |
|
||||
| tool_registry.rs | tool_definitions() 全量 | 加 tool_definitions_subset(intent) + 工具 domain 标签 | ~50 行 + 29 register 加 domain |
|
||||
| agentic/mod.rs | loop 外 tool_defs | loop 入口插意图识别 | ~30 行(入口加调用) |
|
||||
| router.rs | 静态 TaskRequirements | 意图→TaskRequirements 构造 | agentic 构造点改,router 不动 |
|
||||
|
||||
**总计 ~300-400 行,中等改动**。与双轨/审计/provider 工厂零冲突。
|
||||
|
||||
## 分阶段路径(触发条件)
|
||||
|
||||
```
|
||||
近期(29工具,单provider):精简工具描述(零架构),储备设计(本文档)
|
||||
中期(工具>40 或多模型):方式A规则(intent.rs + domain标签 + subset + 模型路由)
|
||||
远期(工具>80 或MCP):方式D两阶段(A规则兜底+C Flash分类),警惕Tool RAG退化
|
||||
```
|
||||
|
||||
## Sources
|
||||
|
||||
- [TianPan Intent Classification](https://tianpan.co/blog/2026-04-16-intent-classification-agent-routers)
|
||||
- [NVIDIA AIQ Intent Classifier](https://docs.nvidia.com/aiq-blueprint/2.0.0/architecture/agents/intent-classifier.html)
|
||||
- [LangChain Context Engineering](https://www.langchain.com/blog/context-engineering-for-agents)
|
||||
- [Red Hat Tool RAG](https://next.redhat.com/2025/11/26/tool-rag-the-next-breakthrough-in-scalable-ai-agents/)
|
||||
- [OpenAI 340 Tools 反例](https://pub.towardsai.net/openai-function-calling-works-great-until-you-have-340-tools-12-tenants-real-production-traffic-fe02da116e39)
|
||||
- [Claude Code Subagents](https://www.builder.io/blog/claude-code-subagents)
|
||||
- [OpenAI Function Calling](https://developers.openai.com/api/docs/guides/function-calling)
|
||||
- [智谱定价](https://open.bigmodel.cn/pricing)
|
||||
@@ -392,7 +392,7 @@
|
||||
|
||||
## 决策治理产品化评估(2026-06-13)
|
||||
|
||||
> 审视 DevFlow 是否应把决策治理(记录/锚点/完成度/自检/漂移)做成产品功能。机制设计详见 [规格契约自检机制-2026-06-14.md](./规格契约自检机制-2026-06-14.md)。
|
||||
> 审视 DevFlow 是否应把决策治理(记录/锚点/完成度/自检/漂移)做成产品功能。机制设计详见 [规格契约自检机制-2026-06-14.md](../专项设计/规格契约自检机制-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 协作层,未沉淀进产品。
|
||||
@@ -459,7 +459,7 @@
|
||||
4. **无环且与 ai.rs 拆分不冲突**:`df-ai-core`(叶,trait+类型)← `df-ai`(impl) / `df-ideas`(use trait),`src-tauri` 装配。「ai.rs 子 module 不下沉 crate」规避的是 src-tauri→df-ai 反向依赖;本决策是 df-ai→df-ai-core 正向拆分,方向相反、互不矛盾。
|
||||
- **否决项**:纯 A(per-module trait)= 全局 N 份发散契约,反模式;裸 B(df-ideas 直接依赖 df-ai)= 纯逻辑 crate 被 reqwest 污染、自检摩擦上升。
|
||||
- **退路**:若不愿加新 crate,trait 可放 `df-core`(语义稍糙——LLM 非领域类型,但零新 crate,可接受)。
|
||||
- **状态**:📐 设计定稿(2026-06-14,4 项决策已定:① 拆分边界=仅 trait+数据结构 ② provider 注入=构造注入 `Engine::new(Option<Arc<dyn LlmProvider>>)` ③ LLM 失败=自动降级启发式+warn+`EvaluatedBy` 标记 ④ provider 构造=应用层 src-tauri 装配注入),未实施。详见 [F-07-df-ai-core-trait下沉设计-2026-06-14.md](./F-07-df-ai-core-trait下沉设计-2026-06-14.md)。
|
||||
- **状态**:📐 设计定稿(2026-06-14,4 项决策已定:① 拆分边界=仅 trait+数据结构 ② provider 注入=构造注入 `Engine::new(Option<Arc<dyn LlmProvider>>)` ③ LLM 失败=自动降级启发式+warn+`EvaluatedBy` 标记 ④ provider 构造=应用层 src-tauri 装配注入),未实施。详见 [F-07-df-ai-core-trait下沉设计-2026-06-14.md](../已编号方案/F-07-df-ai-core-trait下沉设计-2026-06-14.md)。
|
||||
|
||||
### df-core → df-types 改名:类型库非核心,语义明示「类型契约层」[2026-06-17]
|
||||
- **决策**:crate `df-core` 改名为 `df-types`。全 workspace 机械改名(54 处源码引用 + git mv + 9 个 Cargo.toml 依赖声明 + Cargo.lock 自动迁移)。
|
||||
@@ -480,11 +480,11 @@
|
||||
4. **decision 强制校验**:options 非空时强制 `decision ∈ options`,非法值报错而非静默放行——审批门控不能被脏输入绕过;options 空时允许自由文本。
|
||||
5. **B-06/B-07 是并发隔离/取消的前置,非单流功能前置**:单工作流 B-03 照常工作;并发安全等 B-06(execution_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](./B-03-人工审批响应机制-2026-06-14.md)。
|
||||
- **状态**:📐 设计完成(2026-06-14),未实施。详见 [B-03-人工审批响应机制-2026-06-14.md](../已编号方案/B-03-人工审批响应机制-2026-06-14.md)。
|
||||
|
||||
## 任务推进链(7 态状态机 + 工作流联动)
|
||||
|
||||
> tasks 表从 todo→done 的状态推进链路。阶段1(7 态状态机 + advance_task CAS 原子写 + 软删除)已落地;阶段2(工作流联动:task_id + 完成回调 advance_task + DAG 模板)进行中。详细实施路径见 [任务推进链实施路径-2026-06-16.md](./任务推进链实施路径-2026-06-16.md) / [推进链阶段2实施路径-2026-06-16.md](./推进链阶段2实施路径-2026-06-16.md)。关联决策 D-260616-01~04(前端7态对齐 / 软删除 / Node trait 归属 / 阶段1先行)。
|
||||
> tasks 表从 todo→done 的状态推进链路。阶段1(7 态状态机 + advance_task CAS 原子写 + 软删除)已落地;阶段2(工作流联动:task_id + 完成回调 advance_task + DAG 模板)进行中。详细实施路径见 [任务推进链实施路径-2026-06-16.md](../专项设计/任务推进链实施路径-2026-06-16.md) / [推进链阶段2实施路径-2026-06-16.md](../专项设计/推进链阶段2实施路径-2026-06-16.md)。关联决策 D-260616-01~04(前端7态对齐 / 软删除 / Node trait 归属 / 阶段1先行)。
|
||||
|
||||
### advance_task / 状态机走 df-nodes Node trait,不复活 df-task(D-260616-03)
|
||||
- **决策**:任务推进业务逻辑(`can_transition_to` 状态机 / `advance_task` 原子写 / 闸门节点)落在 **df-nodes crate 的 Node trait 扩展**(`task_state_machine.rs` / `task_advance_node.rs`),IPC 层 thin 入口。不复活 2026-06-12 刚因零引用删除(cf017f8)的 df-task crate,不塞 commands/task.rs。
|
||||
@@ -534,7 +534,7 @@
|
||||
| ✅ IPC参数驼峰/蛇形不对齐(误报澄清):Tauri v2 自动将前端 camelCase 参数名转后端 snake_case,`approve({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-03-人工审批响应机制-2026-06-14.md),待实施**(依赖 B-06 并发隔离 / B-07 取消前置) | 工作流引擎 | 2026-06-13 多代理探索 → 2026-06-14 设计 | P0 |
|
||||
| 📐 df-workflow HumanNode 假实现:execute 注释"等待审批"但首次迭代直接 return "同意" — **设计完成 [B-03-人工审批响应机制-2026-06-14.md](../已编号方案/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 每节点拿全新空 StateMachine:self.state_machine 从不传入 NodeContext,HumanNode is_cancelled 恒 false,取消机制失效 | 工作流引擎 | 2026-06-13 多代理探索 | P1 |
|
||||
| 🟡 promote_idea 两步写非事务:INSERT project 成功后若 UPDATE idea 失败,项目存在但想法状态未变,补偿删除可修 | 灵感/立项 | 2026-06-13 代码审查 | P1 |
|
||||
@@ -24,10 +24,10 @@
|
||||
|---|---|---|
|
||||
| `PROGRESS.md`(根级) | 工作流水:Sprint 做了啥 / 遗留 / 下一步 | 决策原因、实现细节、需求规格 |
|
||||
| `ARCHITECTURE.md` | 系统架构全貌:crate 结构 / 数据模型 / Phase 规划 | 功能点取舍、Sprint 流水 |
|
||||
| `02-架构设计/Phase1架构决策-2026-06-12.md` | 架构级选型(ADR,系统级) | 功能实现层取舍 |
|
||||
| `02-架构设计/功能决策记录-2026-06-14.md` | 功能**需求规格 + 设计决策规格**(为什么这么定 + 要做什么) | 流水、架构级选型、经验性内容 |
|
||||
| `02-架构设计/经验记录-2026-06-14.md` | 经验性内容(踩坑/约定/技巧/bug 排查教训) | 决策、需求、流水 |
|
||||
| `02-架构设计/功能决策记录-归档-2026-06-14.md` | 纯流水/老 Sprint/UX 微调/已被取代(归档只读) | (不再维护更新) |
|
||||
| `02-架构设计/滚动规范/Phase1架构决策-2026-06-12.md` | 架构级选型(ADR,系统级) | 功能实现层取舍 |
|
||||
| `02-架构设计/滚动规范/功能决策记录-2026-06-14.md` | 功能**需求规格 + 设计决策规格**(为什么这么定 + 要做什么) | 流水、架构级选型、经验性内容 |
|
||||
| `02-架构设计/滚动规范/经验记录-2026-06-14.md` | 经验性内容(踩坑/约定/技巧/bug 排查教训) | 决策、需求、流水 |
|
||||
| `02-架构设计/滚动规范/功能决策记录-归档-2026-06-14.md` | 纯流水/老 Sprint/UX 微调/已被取代(归档只读) | (不再维护更新) |
|
||||
| `03-模块文档/*.md` | 各 crate 实现细节(单模块内) | 跨模块决策、流水 |
|
||||
| `04-功能迭代/DEVFLOW-N.*.md` | 功能开发过程记录(一次性,开发期) | 持续维护的决策 |
|
||||
| `05-代码审查/*.md` | 审查报告与发现 | (若成决策 → 转记功能决策记录) |
|
||||
@@ -153,7 +153,35 @@ Stop hook 触发 skill 时同理,不另立记录位置。
|
||||
|
||||
---
|
||||
|
||||
## 八、待修(文档不一致)
|
||||
## 八、文档命名规范(2026-06-19 确立)
|
||||
|
||||
> 本节确立 `docs/02-架构设计/` 及同类设计文档目录的命名格式,便于检索 / 排序 / 关联跟踪项。规范为**对现状的归纳**,不强制回溯重命名(重命名引用代价大,见 §十一 riskNote)。
|
||||
|
||||
### 格式
|
||||
|
||||
统一为 `<前缀>-<主题>-<日期>.md`,前缀按文档性质分三类:
|
||||
|
||||
| 类别 | 前缀 | 格式 | 示例 |
|
||||
|---|---|---|---|
|
||||
| 功能 / bug / review 方案 | 功能编号(`F-NN` / `B-NN` / `CR-NN`)或 bug ID(`B-YYMMDD-NN`) | `<编号>-<主题>-<日期>.md` | `F-09-多会话并发架构设计-2026-06-19.md` / `B-03-人工审批响应机制-2026-06-14.md` |
|
||||
| 滚动维护文档(跨 Sprint 持续追加) | 无编号 | `<主题>-<日期>.md` | `功能决策记录-2026-06-14.md` / `经验记录-2026-06-14.md` |
|
||||
| 专题设计 / 构想 / 审查报告 | 主题(含领域前缀如 `aichat` / `工作流` / `任务推进`) | `<主题>-<日期>.md` | `aichat审查报告-2026-06-14.md` / `工作流脚本执行边界-2026-06-15.md` |
|
||||
|
||||
### 约定
|
||||
|
||||
1. **日期 = 创建日期**(YYYY-MM-DD),不随更新变(更新在正文「实施状态」块体现,不改文件名日期)。
|
||||
2. **前缀 = 跟踪项编号**时,与 `todo.md` / `待审查.md` 的编号一一对应,便于双向定位。
|
||||
3. **被取代 / 过时文档不删**:文件顶部加 `## 实施状态` 块或 `> 过时` 标注,索引「状态」列标 🗄。例:`F-09B-多会话并发设计-2026-06-16.md` 被 `F-09-...-2026-06-19.md` 取代,旧版保留回溯。
|
||||
4. **同主题多版本**:新版用相同主编号 + 不同日期(`F-09` 与 `F-09B` 为历史命名,新设计统一用主编号 + 日期,不再加 `B` 后缀)。
|
||||
|
||||
### 检索
|
||||
|
||||
按性质四类查阅,见本目录 [INDEX.md](../INDEX.md):
|
||||
- 滚动规范与决策记录 / 已编号方案 / 专项设计 / 构想与审查
|
||||
|
||||
---
|
||||
|
||||
## 九、待修(文档不一致)
|
||||
|
||||
- ~~`docs/INDEX.md` 在 `07-项目管理/` 树下登记了 `PROGRESS.md`,但实际 PROGRESS 只在根级,`07-项目管理/` 下无此文件~~ → ✅ 已修(2026-06-12):移除该行,PROGRESS 统一指向根级。
|
||||
|
||||
@@ -161,7 +189,7 @@ Stop hook 触发 skill 时同理,不另立记录位置。
|
||||
|
||||
**相关文档**:
|
||||
- `docs/INDEX.md` — 文档导航
|
||||
- `docs/02-架构设计/功能决策记录-2026-06-14.md` — 需求规格 + 设计决策规格(本规范的主要应用对象)
|
||||
- `docs/02-架构设计/经验记录-2026-06-14.md` — 踩坑/约定/技巧/bug 排查教训
|
||||
- `docs/02-架构设计/功能决策记录-归档-2026-06-14.md` — 归档只读(纯流水/老 Sprint/UX 微调)
|
||||
- `docs/02-架构设计/滚动规范/功能决策记录-2026-06-14.md` — 需求规格 + 设计决策规格(本规范的主要应用对象)
|
||||
- `docs/02-架构设计/滚动规范/经验记录-2026-06-14.md` — 踩坑/约定/技巧/bug 排查教训
|
||||
- `docs/02-架构设计/滚动规范/功能决策记录-归档-2026-06-14.md` — 归档只读(纯流水/老 Sprint/UX 微调)
|
||||
- `PROGRESS.md` — 工作流水
|
||||
Reference in New Issue
Block a user