# 11 - 当前开发状态与接手指南

> 更新说明（2026-04-20）：
> `memory-system` 的 IPC 方向已确定为 `TCP loopback + 动态端口 + endpoint 文件发现`，并已补齐 Follower 监控与自动接替 MVP。
>
> 更新说明（2026-05-03）：
> 最新缺口清单和“专用 Memory LLM，不复用主模型”的约束见
> [12-缺口清单与专用MemoryLLM.md](12-缺口清单与专用MemoryLLM.md)。

## 目标

本文档用于接手 `memory-system` 后续开发，直接回答以下问题：

1. 当前代码已经做到什么程度
2. 设计文档与实际实现有哪些偏差
3. 下一步应该先接哪一块

---

## 最近提交脉络

- `27da4c6`：首次接入 `tiangong-memory` 骨架
- `d20513e`：修复 Phase A 首轮 review 暴露的问题
- `0b422a6`：继续收敛 actor 全局接入、workspace 透传与第二轮 review 文档
- `19562f5`：将 `tiangong-memory` 收口为显式 `start()/MemoryHandle` API，并落地 TCP loopback IPC 与独立集成测试

相关 review 文档：

- 第一轮：`docs/memory-system/review/2026-04-17-memory-phase-a-review.md`
- 第二轮：`docs/memory-system/review/2026-04-17-memory-phase-a-review-round2.md`

---

## 当前实现总览

### 已落地链路

当前 `memory-system` 已经不是纯文档状态，而是已经接入主运行链路：

1. CLI / Server 启动时调用 `tiangong_memory::start(...)`
2. 得到 `MemoryHandle` 后显式注入 `TiangongCore`
3. Prompt 装配阶段通过 `load_injection_sync()` 读取三级 Injection
4. Core 在 turn 开始前通过注入的 `MemoryHandle.recall_blocking(...)` 做 recall
5. Core 在 turn 结束后通过 `run_micro_rumination_blocking(...)` 触发 Episode 写入
6. Actor 串行协调 `SQLite + Tantivy + Rumination`

### 代码模块现状

| 模块 | 状态 | 说明 |
|------|------|------|
| `types.rs` | 已实现 | 基础类型完整，含 `Episode/Entity/Decision/RecallHit/TurnResult` |
| `injection.rs` | 已实现 | Profile / Workspace / Session 三级 Injection 读写 |
| `db/schema.rs` | 已实现 | `memory_nodes / episodes / entities / decisions / evidence` 建表 |
| `db/sqlite.rs` | 已实现基础 CRUD | Episode、Entity、Decision 的写入/查询/列举/删除已实现；更高层调用链仍待接入 |
| `search/tantivy_search.rs` | 已实现 | Schema、索引、BM25 查询可用 |
| `search/qdrant_search.rs` | 已删除 | Qdrant 支持已移除，向量检索统一使用内置 LanceDB/embedded vector |
| `search/reranker.rs` | 已实现 | QueryIntent 分析 + 双路融合规则已写 |
| `recall.rs` | 已实现基础链路 | BM25-only、embedded vector、融合重排、`tiangong-llm` 模型精排和向量删除链路已接入 |
| `writer.rs` | 已实现基础链路 | 已有规则提取和 Memory LLM 抽取路径；文本模型来源已收口到独立 Memory 配置 |
| `rumination.rs` | 已实现基础链路 | Micro/Meso 可写入，Meta 已覆盖低活跃、失效路径、过期 URL、项目归档标记并输出结构化指标 |
| `workspace_index.rs` | 待实现 | 按 RFC 0012 将在 tiangong-core/src/index/ 中实现，不再放在 memory crate |
| `ipc/` | 基础实现已落地 | 已支持 TCP loopback、动态端口、endpoint 文件发现、token 鉴权，并可通过 bridge 暴露远端 `MemoryHandle` |
| `election/` | MVP 已实现 | 已有 `start_or_connect`、`leader.lock/leader.json`、心跳、follower 连接与自动接替 |
| `actor.rs` | 已实现 | 主消息循环可用，已处理 recall / micro rumination / injection |
| `handle.rs` | 已实现 | async/blocking 两套调用接口齐全 |

---

## 按阶段盘点

### Phase A

**可以认为已完成。**

已落地能力：

- 独立 crate `crates/tiangong-memory`
- 三级 Injection 读写
- SQLCipher + WAL 元数据库初始化
- Actor / Handle 主体
- Core Prompt 注入改造
- CLI / Server 启动接入
- 基础单测

与设计的偏差：

- 文档写的是 GUI / CLI / Server 都初始化 Memory，但目前代码里只看到 CLI 与 Server 显式调用 `start()`，桌面入口未看到对应接线。

### Phase B

**实际状态：已完成约 90%，主链路已经可运行且可独立测试。**

已经实现的部分：

- `tantivy = "0.22"` 已引入
- Tantivy 索引与 BM25 查询已实现
- `store.rs` 已协调 SQLite + Tantivy + LanceDB/embedded vector 双写
- `db/sqlite.rs` 已补齐 Episode/Entity/Decision 基础 CRUD
- `writer.rs` 已能从 `TurnResult` 规则提取 Episode
- `rumination.rs` 的 Micro 路径已接入
- `actor.rs` 已处理 `WriteEpisode / RunMicroRumination`
- runtime 已在 turn 完成后调用 `run_micro_rumination_blocking`
- `ipc/` 已有 TCP loopback 基础实现（动态端口 + endpoint 文件 + token）
- `MemoryHandle` 已支持 local/remote 双态，远端句柄可通过 TCP bridge 调用 recall / injection / rumination / shutdown
- `election/` 已支持 `start_or_connect()`、leader 注册信息、心跳、follower 通过 TCP 连接现有 leader，以及 leader 消失后的自动接替
- `tiangong-memory` 已有独立 integration tests，覆盖 runtime 与 ipc 主链路

未完成或仅骨架的部分：

- EpisodeWriter 已有 LLM 抽取路径，且配置来源已收口到独立 Memory 配置；已提供 `memory_llm_smoke` 手动验证真实 Memory LLM 调用链路，已补 6 个历史指代固定样例验证增量回忆输出，已统一记录 Memory LLM token 用量和耗时，并已补 Deep Recall 跨会话、跨产物、跨 Entity/Decision 固定评测

### Phase C

**实际状态：已进入“代码骨架 + 局部接线”阶段，完成度约 45%。**

已经实现的部分：

- 向量模式已统一为 embedded-only（LanceDB/flat vector），Qdrant 支持已移除
- `tiangong-llm` 已有 `EmbeddingProvider`
- `tiangong-llm` 已有 `RerankProvider`，Recall 可对 BM25 或 hybrid 候选做模型精排
- `search/embedding.rs` 已封装 Memory 侧 query / node / batch embedding 调用
- `reranker.rs`、`recall.rs` 已写
- `core/mod.rs` 已把 recall 结果注入 `user_context`
- `rumination.rs` 已存在 `process_meso()`
- `prompt/assembler.rs` / `sections.rs` 已通过 memory crate 接上 recall / injection 入口

仍未闭环的部分：

- Episode -> Embedding -> VectorIndex upsert 已接入，embedded vector 为唯一向量后端
- `RecallAnchors` 当前基本只用了原始 query，未做真正锚点提取
- `LoadDepth2` 仍返回空数组
- `process_meso()` 只是关键词统计，不是真正的 Entity / Decision 提炼
- recall 质量已进入“BM25 + 可选语义接口 + 可选模型精排”阶段，但仍不是完整 Progressive Recall

### Phase D

**当前仅有占位函数或设计意图，尚未开始真正开发。**

---

## 当前主链路

### 1. 启动链路

- CLI：`crates/tiangong-cli/src/repl.rs`
- Server：`crates/tiangong-server/src/lib.rs`

两者都在进程启动时调用：

```rust
let memory_handle = tiangong_memory::start()?;
```

随后将 `MemoryHandle` 显式传入 `TiangongCore`。

### 2. 注入链路

- `crates/tiangong-core/src/prompt/assembler.rs`
- `crates/tiangong-core/src/prompt/sections.rs`

当前 Prompt 装配会读取：

- `~/.tiangong/memory/profile/agent.md`
- `~/.tiangong/memory/workspaces/<workspace_id>/agent.md`
- `~/.tiangong/memory/sessions/<session_id>/agent.md`

### 3. Recall 链路

- `crates/tiangong-core/src/core/mod.rs`
- `crates/tiangong-memory/src/handle.rs`
- `crates/tiangong-memory/src/store.rs`
- `crates/tiangong-memory/src/recall.rs`

现状：

- turn 前会调用 blocking recall
- 默认实际效果是 BM25-only；配置 rerank 后可使用 BM25 + 模型精排
- 向量模式统一使用内置 LanceDB/embedded vector，已移除 Qdrant 外部依赖
- recall 通过显式注入的 `MemoryHandle` 调用，不再依赖进程级全局单例

### 4. 写入链路

- `core/mod.rs` 组装 `TurnResult`
- `handle.run_micro_rumination_blocking()`
- `actor.rs -> rumination::process_micro()`
- `writer.rs -> store.write_episode()`
- `db/sqlite.rs + search/tantivy_search.rs`

现状：

- 只有 `had_tool_calls == true` 才会产出 Episode
- Episode 摘要来自最后一条 assistant 消息
- Memory 已改为全局单例，所有 workspace 共享同一 Memory 实例，不再按 workspace 分区

---

## 当前问题与风险

### 1. 进程级全局单例设计已经彻底收口

已完成收口。Memory 已改为全局单例模式，不再按 workspace 分区。所有入口共享同一个 Memory 实例。

- 已移除 `ensure_started()/global_handle()` 这类进程级全局入口
- `MemoryHandle` 改为由各入口显式创建并注入 core
- `MEMORY_HANDLES` 已简化为 `Mutex<Option<MemoryEntry>>` 单实例
- 所有 API 函数已移除 `workspace_id` 参数

这意味着：

- `tiangong-memory` 已经可以独立作为库运行和测试
- 运行时模型已确定为全局单例，不再需要按 workspace 分区

### 2. `TODO.md` 与实际实现不同步风险已降低，但仍需持续同步

`TODO.md` 已经补过一轮，但 `memory-system` 当前推进速度较快，后续每完成一个收口项都需要及时同步，否则仍然会再次偏离代码状态。

### 3. GUI / CLI / Server 入口已统一接入

当前 Core 使用全局单例 Memory Handle，GUI、CLI、Server 所有 workspace 共享同一个 Memory 实例。Memory election 的 leader 运行文件为全局唯一，不再按 workspace 分区。

已验证：

- `election_failover_integration::gui_cli_server_processes_share_one_workspace_leader` 会拉起 CLI、GUI、Server 三个真实子进程。
- 同一 workspace 只产生一个 leader，其余入口作为 follower 连接。
- 三个入口各自写入的记忆都能被父进程通过 leader remote handle 召回。

### 4. IPC 与 Election 已接入主链路并完成跨进程实测

这意味着当前 Memory 已具备“本地 actor + TCP bridge + 远端句柄 + 启动时选举/连接 + Follower 自动接替”的主链路，并已有真实多进程 integration test 覆盖 GUI + CLI + Server 组合。

### 5. Recall 与 Rumination 仍偏“规则版 MVP”

目前尚未实现：

- 真正的 RecallAnchors 提取
- Entity / Decision 抽取
- 基于专用 Memory LLM 的 Episode 摘要与结构化抽取质量验证

---

## 建议的接手顺序

### 第一优先级：收口运行时模型

目标：先解决“这套系统在一个长期运行进程里到底如何绑定 workspace”。

建议动作：

1. 决定 Memory Actor 是“全局唯一”还是“按 workspace 分区”
2. 如果保留全局唯一，则所有命令都必须显式携带 workspace/session 上下文，不能再读 store fallback
3. 如果改为按 workspace 分区，则需要把入口持有的 `MemoryHandle` 升级为按 workspace 管理的 registry
4. 补齐 GUI / 桌面入口接入

这是最优先项，因为它决定后续 IPC、Qdrant、Meso 是否会建立在正确的 runtime 抽象上。

### 第二优先级：把 Phase B 真正做完

建议动作：

1. 补齐 SQLite 对 Entity / Decision 的 CRUD
2. 让 EpisodeWriter 输出更完整的 `tool_calls / outcome / importance`
3. 把 TCP IPC + leader election 做成可运行最小闭环
4. 增加至少一组 integration test：
   - turn 完成 -> episode 落库
   - tantivy 可搜
   - workspace scope 正确

### 第三优先级：把 Phase C 从“骨架”推进到“可用”

建议动作：

1. 实现 Episode 向量化与 Qdrant upsert
2. 在启动配置中显式决定是否启用 Qdrant
3. 将 `RecallAnchors` 从原始 query 升级为真正锚点提取
4. 让 `LoadDepth2` 支持定向展开
5. 将 `process_meso()` 升级为真实 Entity / Decision 提取

---

## 建议的近期任务拆分

如果马上继续开发，我建议按下面三个任务拆：

### 任务 A：Memory 运行时模型收口

- 收敛 workspace 上下文透传
- 设计按 workspace 管理的 runtime / handle registry
- 补齐 GUI 入口接线

### 任务 B：Phase B 收尾

- 完成 IPC / election MVP
- 补齐 SQLite CRUD
- 增加 turn -> episode -> tantivy 的集成测试

### 任务 C：Phase C 闭环

- Qdrant upsert
- embedding 调用配置化
- recall anchors / depth2 / meso 提取

---

## 建议验证命令

后续继续开发时，优先使用以下命令验证：

```bash
timeout 180 cargo fmt --all --check
timeout 180 cargo check --workspace
timeout 240 cargo clippy --workspace --all-targets --tests --benches -- -D warnings
timeout 180 cargo test -p tiangong-memory
```

如果涉及跨入口接线，再补：

```bash
timeout 180 cargo check -p tiangong-cli
timeout 180 cargo check -p tiangong-server
```

---

## 接手结论

`memory-system` 当前不是“从零开始”，而是已经有了可运行的 Phase A 主链路、可用的 Phase B 部分能力，以及大量 Phase C 预埋代码。

真正需要接手的重点不是“继续无脑加功能”，而是先把运行时抽象收口，再把 Phase B 的空壳补实，最后再推进 Qdrant 和 Progressive Recall。否则后面越接越容易把错误抽象固化下来。
