# 知识库模块

> 创建: 2026-06-13 | 阶段: Tier 1 已实现

---

## 概述

知识库是 DevFlow 的"共享记忆层"，被动积累 AI 对话中产生的可复用经验，供后续对话注入使用。外部工具（Claude Code / CodeX / Cursor）可通过相同 IPC 接口读写，内外零差异。

---

## 实现状态

| 功能 | 状态 |
|------|------|
| candidate→published 状态机 | ✅ Tier 1 |
| 手动录入（Knowledge.vue）| ✅ Tier 1 |
| AI 自动提炼（对话完成后）| ✅ Tier 1 |
| LIKE 关键词检索 + 注入 system prompt | ✅ Tier 1 |
| 审核收件箱（人工门控）| ✅ Tier 1 |
| 向量 embedding + 混合检索 | ✅ Phase 5.5（开关控制，默认关）|
| ai_node prompt 注入 | ⬜ Tier 2 |
| MCP 对外 API | ⬜ Tier 2 |

---

## 状态机

```
candidate ──→ pending_review ──→ published ──→ archived
    │                │               │
    └────────────────┴───────────────┘
                (可直接到 archived)
```

- AI 提炼只产 **candidate**，绝不自动 published（人工门控）
- `knowledge_archive`：软删除（status=archived），不物理删除

---

## 知识类型（KnowledgeKind）

7 种：`pitfall`（踩坑）/ `review_rule`（审查规则）/ `prompt_template`（Prompt 模板）/ `architecture_pattern`（架构模式）/ `diagnosis`（诊断知识）/ `deployment_note`（部署经验）/ `workflow_optimization`（工作流优化）

---

## IPC 命令（11 个）

| Command | 说明 |
|---------|------|
| `knowledge_list(status?)` | 列表，默认仅 published（library 纯已发布，F-260616-02 决策 a）；显式传 status 按该状态过滤（含 archived） |
| `knowledge_get(id)` | 单条查询 |
| `knowledge_search(query, kind?, limit?)` | LIKE 检索，默认 top-3，`limit.clamp` 上限 20（`min(20)`） |
| `knowledge_create(input)` | 创建（status=candidate）|
| `knowledge_update_status(id, status)` | 状态转换（含合法矩阵校验）|
| `knowledge_record_reuse(id)` | reuse_count +1 |
| `knowledge_list_candidates()` | 待处理收件箱（candidate+pending_review，按 confidence 排序）|
| `knowledge_archive(id)` | 软删除 |
| `knowledge_get_config()` | 读取 KnowledgeConfig |
| `knowledge_save_config(config)` | 保存 KnowledgeConfig |
| `knowledge_extract_now()` | 手动触发提炼（ManualOnly 模式）|

---

## KnowledgeConfig

```rust
pub struct KnowledgeConfig {
    pub auto_extract: bool,            // 提炼总开关，默认 true
    pub trigger_mode: ExtractTrigger,  // on_complete | manual_only(OnIdle 已下线,见 KP-2)
    pub min_messages: u32,             // 守卫：最少消息数，默认 4
    pub auto_inject: bool,             // 聊天注入开关，默认 true
    pub vector_enabled: bool,          // 向量检索开关，默认 false
    pub embedding_provider_id: Option<String>,  // 仅 openai_compat 类型
    pub embedding_model: Option<String>,
}
```

存储：`AppState.knowledge_config: Arc<Mutex<KnowledgeConfig>>` 为内存真相源，并通过 `SettingsRepo` KV 表（key=`df-knowledge-config`）持久化；`knowledge_save_config` 落库、`AppState::init` reload 恢复（KP-1 已修复）。

---

## 检索与注入

### LIKE 检索（默认）

`search(query, kind, limit=3)` → `WHERE title LIKE ? OR content LIKE ?` → `ORDER BY reuse_count DESC`

### 混合检索（vector_enabled=true）

三层降级链：
1. 开关关 → 纯 LIKE
2. embed 调用失败 → 纯 LIKE
3. 正常 → 双信号排序（同时命中 LIKE+向量 cos≥0.3 > 仅 LIKE > 仅向量 cos≥0.3）

嵌入时机：知识**发布时**（不在 candidate 阶段浪费 embed 调用），`spawn_embedding_for_knowledge` fire-and-forget。

### 注入位置

system prompt 头部（[知识库上下文] --- [技能指令] --- [原始 system prompt]），仅 auto_inject=true 时生效。

---

## AI 自动提炼流程

1. `run_agentic_loop` 正常退出 → `maybe_spawn_extraction()` 守卫检查
2. 守卫：`auto_extract=true` + `messages.len() >= min_messages`
3. `tauri::async_runtime::spawn` 后台执行，不 await（不阻断聊天）
4. 取最后 6 条 user/assistant 消息 → 构造 JSON schema prompt → LLM `complete()`
5. `serde_json::from_str<Vec<ExtractedItem>>` 解析，失败整批丢弃（warn 不报错）
6. 逐条写 `knowledges`（status=candidate，source_ref="conv:{id}"）

---

## 矛盾知识处理

不做结构层消歧，在内容和 tags 中自述限制范围。检索时两条知识都可能返回，由 LLM 上下文理解取舍。

---

## 外部工具访问（规划）

Tier 1+ 目标：MCP Shell 封装（`mcp-server` 转发 IPC），外部工具使用逻辑与内部零差异：
- 外部写入：走 candidate → 人工审核流程
- 外部读取：`knowledge_search` / `knowledge_list`（published）

---

## 相关文档

- [df-storage 存储层](./df-storage-存储层-2026-06-12.md) — knowledges 表结构 + 向量工具函数
- [df-ai AI 集成模块](./df-ai-AI集成模块-2026-06-12.md) — hybrid_search / generate_embedding / extract
- [功能决策记录](../02-架构设计/滚动规范/功能决策记录-2026-06-14.md) — 检索方案演进决策


---

## 已知问题（2026-06-16 审查）

> 来源：全量源码逐行审查（knowledge.rs / knowledge_inject.rs / knowledge_timeline.rs / stores/knowledge.ts / Knowledge.vue / agentic.rs / commands.rs / state.rs）
>
> **修复进度汇总（2026-06-21）：**
> - ✅ 已修复：**KP-1** 配置持久化 / **KP-2** OnIdle 下线；跨审查项 **R-P1-4** `build_provider` 统一工厂（secret::build_provider_for）、**CR-28** error 通道（AiError emit 覆盖 build_provider_for Err 分支）、**CR-29** 审批等待态竞态（B-260615-26 guard disarm + try_continue generating 复位重检）。
> - 🔧 本 workflow 修复中：**KP-3**（try_continue 知识注入）/ **KP-5**（编辑生命线事件）/ **KP-6**（嵌入失败重试/标记）。

### 🔴 P0 严重

#### KP-1: KnowledgeConfig 不持久化 — 重启丢失全部配置 ✅ 已修复

> **状态：已修复（P0 设置走查-2026-06-21）。** `knowledge_save_config` / `knowledge_get_config` 现读写 `SettingsRepo` KV（key=`df-knowledge-config`，JSON 序列化）；`AppState::init` 增加 `reload_knowledge_config` 恢复。下方原文保留供溯源。

- **位置：** `state.rs:208` 初始化 + `knowledge.rs:knowledge_save_config`
- **现象：** `knowledge_save_config` 仅写入内存 `Arc<Mutex<KnowledgeConfig>>`，未落库。应用重启后 `AppState::init` 永远用 `KnowledgeConfig::default()`
- **影响：** 用户配置的向量检索 provider、提炼参数等关闭应用后全部丢失。系统已有 `app_settings` KV 表和 `SettingsRepo` 可用，但未接入
- **修复方向：** `knowledge_save_config` / `knowledge_get_config` 读写 `SettingsRepo`（key=`knowledge_config`，value=JSON）

#### KP-2: OnIdle 触发模式完全未实现 — 配置项为死代码 ✅ 已修复（下线）

> **状态：已修复（OnIdle 下线）。** `ExtractTrigger` 仅保留 `OnComplete` / `ManualOnly` 两变体，`OnIdle` 变体与 `idle_timeout_ms` 字段已从 `state.rs` 移除（`idle_timeout_ms` 在 `src-tauri` 内零残留）。`trigger_mode` 取值同步收敛。下方原文保留供溯源。

- **位置：** `state.rs` 定义 `ExtractTrigger::OnIdle` + `idle_timeout_ms`；`knowledge_inject.rs:maybe_spawn_extraction`
- **现象：** `maybe_spawn_extraction` 仅检查 `trigger_mode == OnComplete`，`OnIdle` 与 `ManualOnly` 都直接 `return Ok(())`。`idle_timeout_ms` 在整个 `src-tauri` 中零引用
- **影响：** 用户选择 `OnIdle` 模式后，知识提炼永远不会触发（与 ManualOnly 行为相同但无任何提示）
- **修复方向：** 要么实现 idle 定时器（tokio::time::interval 轮询 AiSession 最后活动时间），要么移除 OnIdle 变体并在前端隐藏该选项

#### KP-3: 审批恢复循环路径缺失知识注入 🔧 本 workflow 修复中

> **状态：本 workflow 修复中。** `try_continue_agent_loop`（agentic/mod.rs）现已在续跑轮重建 system prompt 时调用 `build_knowledge_context` 注入知识库上下文（参考代码 :1420-1444 区段注释）。下方原文保留供溯源。

- **位置：** `agentic.rs:try_continue_agent_loop` vs `commands.rs:ai_chat`
- **现象：** `ai_chat` 首次消息时调用 `build_knowledge_context` 注入 system prompt；`try_continue_agent_loop`（审批通过后恢复循环）仅调用 `build_system_prompt`，**未调用** `build_knowledge_context`
- **影响：** 对话经历工具审批流程后恢复时，system prompt 中不包含任何知识库上下文，AI 在多轮工具调用场景下丢失经验注入

---

### 🟡 P1 中等

#### KP-4: 前端搜索只能搜到 published 知识

- **位置：** `knowledge.rs:knowledge_search` → `KnowledgeRepo::search`（底层固定 `WHERE status='published'`）
- **现象：** 前端搜索栏调用链 `store.search()` → `knowledgeApi.search()` → IPC → `repo.search()`，底层 SQL 硬编码 `status='published'`
- **影响：** 知识库 Tab 列表加载的是 `list_non_archived()`（含 candidate/pending_review/published），但搜索只能命中 published，导致列表显示条目数 > 可搜索条目数，体验矛盾
- **修复方向：** 前端搜索走独立的 `knowledge_list` + 前端过滤，或后端新增 `search_all_status()` 方法供前端使用

#### KP-5: 编辑操作缺失生命线事件 🔧 本 workflow 修复中

> **状态：本 workflow 修复中。** 计划在 `knowledge_timeline.rs` 新增 `EVENT_UPDATED` + `KnowledgeTimeline::record_updated()`，并接入 `knowledge.rs:knowledge_update`（:375-411）。下方原文保留供溯源。

- **位置：** `knowledge.rs:knowledge_update`
- **现象：** `knowledge_create` 有 `record_created`，`knowledge_update_status` 有 `record_status_change`，但 `knowledge_update`（编辑 title/content/tags 等）**无任何 Timeline 调用**
- **影响：** 知识被编辑修改后，生命周期时间线中不显示编辑记录，审计追踪存在断档
- **修复方向：** 新增 `EVENT_UPDATED` 事件类型 + `KnowledgeTimeline::record_updated()` 方法

#### KP-6: 嵌入生成失败无重试/标记 — 可能永久无向量索引 🔧 本 workflow 修复中

> **状态：本 workflow 修复中。** 计划在 `knowledge_inject.rs:spawn_embedding_for_knowledge`（:91-118）增加失败标记/重试，配合 `migrations.rs`（knowledges 表）`embedding IS NULL` 补偿。下方原文保留供溯源。

- **位置：** `knowledge_inject.rs:spawn_embedding_for_knowledge`
- **现象：** 发布时 fire-and-forget 生成嵌入，失败只 `warn log`，无重试机制、无失败标记
- **影响：** provider 临时不可用（网络抖动/API 限流）时该知识永远不会获得向量嵌入，即使后续 provider 恢复。混合检索中该条目向量信号永久缺失
- **修复方向：** 可选方案：(a) 定期补偿任务扫描 `published AND embedding IS NULL`；(b) 前端详情页显示嵌入状态并提供"重新生成"按钮

#### KP-7: 前端 updateStatus 后仅本地移除 — 不刷新列表

- **位置：** `stores/knowledge.ts:updateStatus`
- **现象：** 发布/拒绝/归档操作后仅 `filter` 移除本地数组中的条目，不重新 `loadList()` / `loadCandidates()`
- **影响：** 状态变化后需手动刷新才能看到最新列表。若其他路径（如 AI 提炼）并发写入候选列表，本地状态会进一步偏离

---

### 🟢 P2 低优先级

#### KP-8: 搜索后分类筛选状态丢失

- **位置：** `Knowledge.vue:onSearchInput`
- **现象：** 搜索框清空时触发 `store.loadList()`，但不恢复之前的 `activeKind` 分类筛选状态

#### KP-9: knowledge_search limit 硬限 3 条

- **位置：** `knowledge.rs:knowledge_search` → `.min(3)`
- **现象：** 即使传入 `limit=10` 也只返回最多 3 条。Tier 1 内部合理，但 Tier 2 MCP 对外开放后可能受限

#### KP-10: 矛盾知识无消歧机制

- **位置：** 模块设计层面（文档已记录此决策）
- **现象：** 两条矛盾知识可能同时返回，完全依赖 LLM 上下文理解取舍。当前 top-3 限制降低了冲突概率，但随知识积累会逐渐显现
