Metadata-Version: 2.4
Name: keepm
Version: 3.2.0
Summary: Admission-controlled local Markdown memory MCP for AI coding agents
Project-URL: Homepage, https://github.com/LeoKon3/KeepM
Project-URL: Repository, https://github.com/LeoKon3/KeepM
Project-URL: Issues, https://github.com/LeoKon3/KeepM/issues
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastmcp<4,>=3
Requires-Dist: PyYAML<7,>=6
Requires-Dist: questionary<3,>=2
Requires-Dist: tomlkit<1,>=0.13
Requires-Dist: watchfiles<2,>=1
Provides-Extra: dev
Requires-Dist: pytest<9,>=8; extra == "dev"
Requires-Dist: pytest-asyncio<2,>=0.24; extra == "dev"
Dynamic: license-file

# KeepM V3

![KeepM Unicode wordmark](assets/keepm-wordmark.svg)

> 带准入控制、本地优先、无模型依赖的 AI 编码 Agent 长期记忆引擎。

[![Version](https://img.shields.io/badge/version-3.2.0-6f42c1.svg)](https://pypi.org/project/keepm/)
[![Python](https://img.shields.io/badge/python-3.11%2B-3776ab.svg)](https://www.python.org/)
[![MCP](https://img.shields.io/badge/MCP-supported-2ea44f.svg)](https://modelcontextprotocol.io/)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/LeoKon3/KeepM/blob/main/LICENSE)

[English](README_EN.md) · [简体中文](README.md)

## 为什么需要 KeepM？

长对话会让重要事实淹没在上下文中间；如果任由 Agent 把自主推断直接写成长期记忆，一次误判又可能持续污染未来会话。

KeepM 在“推理”与“保留”之间建立明确的准入边界：

- **Markdown 是唯一真源。** 记忆保留在本地，可迁移、可审查，也能用 Obsidian 或任意 Markdown 编辑器直接查看和修改。
- **SQLite 是可重建的机器索引。** 名称、aliases、tags、description 和正文通过加权 FTS5 渐进检索，WikiLink 提供正向关系与反向链接。
- **三层生命周期隔离污染。** 已确认结论、Agent 推断候选和未完成任务状态走不同的准入路径。
- **服务端不隐藏模型。** 当前 Agent 负责语义提炼；KeepM 负责 Schema、去重、checksum、短时凭证、内容限制和安全状态流转。

> **核心原则：Markdown 是唯一真源，SQLite 是可删除、可完整重建的派生索引。**

## 总体架构与数据流

```text
┌──────────────────────────────────────────────────────────────┐
│ Agent 宿主：Codex / Claude Code / 其他 MCP 客户端            │
│ 语义提炼 · 准入分类 · 冲突处理                               │
└─────────────────────────────┬────────────────────────────────┘
                              │ MCP stdio
                              ▼
┌──────────────────────────────────────────────────────────────┐
│ KeepM MCP Server                                             │
│ 格式校验 · 槽位去重 · checksum · 冲突事务 · 生命周期 · 诊断  │
└──────────────────────┬──────────────────────┬────────────────┘
                       │ 权威写入             │ 派生路由
                       ▼                      ▼
┌──────────────────────────────┐  ┌────────────────────────────┐
│ 本地 Markdown                │  │ 本地 SQLite                │
│ 正式记忆 · Inbox · handoff   │  │ FTS5 · aliases · links     │
│ 唯一真源                     │  │ 可删除、可完整重建         │
└──────────────────────┬───────┘  └────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────┐
│ Obsidian / 任意 Markdown 编辑器（可选的人类界面）            │
└──────────────────────────────────────────────────────────────┘
```

检索采用渐进式流程：`memory_context` 返回有长度边界的第一层上下文，`memory_search` 缩小候选范围，`memory_read` 只打开明确相关的权威笔记。Agent 无需全量扫描 Markdown 目录。

## 三层记忆生命周期

| 层级 | 存储内容 | 状态 | 是否进入普通检索 |
| --- | --- | --- | --- |
| **正式记忆** | 已确认的偏好、决策、约束、修复方法与可复用知识 | `active`、`superseded`、`archived` | 仅 `active` |
| **Inbox Proposal** | Agent 推断但尚未确认的高价值候选结论 | `pending`、`promoted`、`rejected` | 否 |
| **Handoff** | 恢复未完成任务所需的临时状态 | `active`、`completed` | 否 |

> **Handoff 存未完成的“事”，Inbox 存待确认的“候选结论”，正式记忆存已确认、可复用的“果”。**

三层内容分别位于 `<Markdown 根目录>/Memory/` 下的正式记忆目录、`Inbox/` 和 `.handoffs/`；SQLite 索引与可选审计日志保存在用户数据目录，不会取代 Markdown 真源。

同一个 Markdown 根目录（或 Obsidian Vault）可以供多个已接入项目共用。`Memory/global/` 保存跨项目适用的正式记忆，`Memory/projects/<project-id>/` 保存项目专属记忆；这两个数据范围与 Agent 的安装范围无关。KeepM 只在明确选择的项目中注册 MCP、策略和 Hook，不提供用户级 Agent 接入。

## 快速开始

环境要求：Python 3.11+、[uv](https://docs.astral.sh/uv/) 和一个本机可写的 Markdown 目录。

```bash
uvx keepm setup
```

`uvx` 会在隔离环境中运行 KeepM，无需永久安装。交互向导会完成最少且完整的接入：

- 指定共用的 Markdown 存储根目录与默认记忆语言（`zh` / `en`）；
- 选择 Codex 或 Claude Code；
- 指定要接入的项目目录，默认使用当前工作目录；
- 仅在该项目中注册 `keepm` stdio MCP Server、安装受管理的 Agent 记忆策略，并默认配置 `SessionStart` / `Stop` Hook。

自动化配置：

```bash
uvx keepm setup --yes --root /path/to/notes --agent codex --project-dir /path/to/project
```

可选的运维参数包括 `--deep-reconcile-seconds`（默认 1800，`0` 禁用周期深扫）、`--verification-review-days`（默认 180）和 `--sqlite-journal-mode wal|delete`（默认 `wal`；网络文件系统可显式选择 `delete`，但这不会提供跨机器锁）。

重复执行 setup 是幂等的，只会更新目标项目中 KeepM 管理的配置块。`~/.config/keepm/config.toml` 只保存 KeepM 自身的本机 Vault 配置，不会在所有项目中全局启用 Agent。KeepM 不要求安装或运行 Obsidian；在 WSL 中直接使用 `/mnt/c/...` 形式的 Windows 挂载路径即可。

## 极简维护命令

健康报告复用 `memory_doctor` 的确定性诊断结果，只导出状态和 finding 元数据，不包含记忆正文、Proposal 内容或任何 repair/update token：

```bash
uvx keepm doctor --format json
uvx keepm doctor --format markdown --output keepm-health.md
```

Safe GC 只处理 `Memory/.trash/` 中具有可信软删除时间、且超过指定期限的普通文件。默认命令只生成预览和短时一次性计划；repair 备份、符号链接、无可信删除时间的文件以及正常的 active/archived/superseded 记忆均不会被删除：

```bash
# 仅预览，不删除
uvx keepm gc --older-than-days 30

# 使用预览返回的 token 执行完全相同且未变化的计划
uvx keepm gc --confirm --token <gc-token>
```

确认后的 GC 是不可恢复删除；trash 内容、checksum、候选集合或 token 时效发生变化时会拒绝执行并要求重新预览。

## Agent 工作流与低噪对话式审核

```text
任务开始
  └─ memory_context(query)
       ├─ 上下文充足 ─────────────────► 继续主任务
       └─ 上下文不足
            └─ memory_search ─► 只 memory_read 相关记忆

产生值得保留的信息
  ├─ 用户明确要求或已确认 ─────────────► memory_create / memory_update
  ├─ Agent 推断且有长期价值 ──────────► memory_propose ─► Inbox 待审核
  └─ 尚未完成的任务状态 ──────────────► memory_handoff_create / update
```

写操作会立即刷新对应索引，不需要在任务开始或结束时常规调用 `memory_sync`。Hook 只负责提醒当前 Agent 做有边界的恢复或检查点整理；KeepM 不读取原始对话，也不会调用模型。

KeepM 使用受控对话完成 Inbox 审核，不依赖 GUI 或 Obsidian 插件。Agent 只有在用户主动要求、当前对话刚产生新 Proposal，或 Inbox 出现过期/数量阈值信号时，才会在主任务回答末尾提醒；每次最多呈报 3 条。

> **Agent 对话式审核示例**
>
> 顺便提醒：检测到 2 条待审核候选记忆：
>
> - **Proposal P1［项目偏好］** 优先使用 pnpm 而非 npm（建议：**批准**）
> - **Proposal P2［架构决策］** 放弃 Redis，改用 SQLite（建议：**批准**）
>
> 可以回复“批准 Proposal P1、拒绝 Proposal P2”或“稍后”。

主任务永远优先，Proposal 使用独立于 `Step 1` 等主任务步骤的编号。“行”“好的”“按你说的办”“按建议处理”等泛化赞同只授权主任务，绝不授权 Inbox 变更；多条候选时用户必须明确引用 `Proposal P1` 等标签。只有最近明确呈报了一条 Proposal 时，“批准记忆提案”才可授权该唯一候选。用户回复“稍后”或忽略提醒后，本次会话不再重复打扰；沉默不会批准、拒绝、修改或删除任何内容。

正式记忆使用“槽位命名”：`project-package-manager` 表示稳定主题，`pnpm` 只是该槽位当前的结论。`memory_context` / `memory_search` 在发现 active 名称、别名硬碰撞或同 kind 主题重叠时会返回有界的 `conflict_hints`；Agent 必须完整读取相关候选并核对项目真源，不能只信第一条。

确认冲突并得到用户明确授权后，Agent 先预览 `memory_resolve_conflict(dry_run=true)`，再用绑定同一方案的短时 token 执行。`supersede` 保留历史关系，`archive` 归档失去独立价值的节点，`delete` 只把错误节点移入可恢复回收站。KeepM 会同时校验两份 checksum/token、拒绝 `supersedes` 环，并通过可恢复的文件事务日志与单次 SQLite 事务保证崩溃一致；若进程在多文件替换中断，下次启动会继续提交或安全回滚。

## MCP 工具一览

| 分组 | 工具 | 用途 |
| --- | --- | --- |
| 上下文 | `memory_status`、`memory_context` | 运行状态、有长度边界的任务上下文和仅计数的 Inbox 信号 |
| 检索 | `memory_search`、`memory_read`、`memory_links` | active 记忆加权检索、权威读取、WikiLink 与反向链接 |
| 正式记忆 | `memory_create`、`memory_update`、`memory_delete`、`memory_resolve_conflict` | 创建已确认记忆；保护更新、删除及两条 active 记忆的预览式冲突解决 |
| Inbox | `memory_propose`、`memory_inbox_list`、`memory_inbox_read`、`memory_inbox_update`、`memory_inbox_promote`、`memory_inbox_reject`、`memory_inbox_prune` | 隔离、查看、修正、批准、拒绝、合并或安全清理候选 |
| Handoff | `memory_handoff_create`、`memory_handoff_read`、`memory_handoff_update`、`memory_handoff_complete` | 保存、恢复、更新和归档未完成任务状态 |
| 运维 | `memory_doctor`、`memory_repair`、`memory_sync` | 诊断损坏、预览授权的确定性修复、对账或重建索引 |

修改或删除已有对象前必须完整读取当前内容，并提供一次性版本凭证；如果 Markdown 在读写之间发生变化，KeepM 会拒绝过期操作，不会盲目覆盖。

## 对账、文件系统与长期健康

- **分层对账：** 高频快速路径使用 `mtime_ns + size`；服务启动、默认每 30 分钟一次的周期深扫，以及 `memory_doctor` 都会重新计算内容 SHA-256。`memory_status` 返回 `last_checksum_scan` 和 `deep_scan_due`。
- **落盘边界：** 单文件写入会先 `fsync` 临时文件，`os.replace` 后再 `fsync` 父目录；Markdown 仍是唯一真源，Doctor 只报告损坏，不猜测性重写。
- **单活 Writer：** 一个 Vault 同一时间只能由一台机器写入。`memory_status` 会尽力识别 NFS/SMB 等网络文件系统并给出提示；SQLite journal mode 可显式配置为 `wal` 或 `delete`，但两者都不能替代跨主机协调。
- **核验提示：** `memory_doctor` 只对 active 的 `constraint`、`fix`、`workflow` 给出 `verification_missing` / `verification_overdue` info；`decision` 和 `preference` 默认免检，系统绝不因此自动归档或改写记忆。
- **结构化报告：** `memory_doctor(report_format=json|markdown)` 和 `keepm doctor` 复用同一份无正文健康报告；CLI 可安全写入本地 JSON/Markdown，不引入 HTML 渲染。
- **Host 确认适配：** `memory_status.host_confirmation` 根据 MCP 客户端能力报告 `elicitation` 或 `proposal-protocol`。不支持、取消或调用错误都 fail closed；当前 Proposal P1/P2 明确授权协议始终保留，不会把能力缺失当成批准。

## 设计哲学与非目标

- **本地优先且透明：** 不依赖云服务、HTTP 守护进程或私有存储格式。
- **先准入，后保留：** 用户确认的知识才能成为正式记忆；Agent 推断在批准前只能留在 Inbox。
- **确定性安全护栏：** 正文限长、高置信度秘密检测、Unicode 槽位去重、单文件原子写入、可恢复冲突事务、checksum、短时凭证、关系环检测、软删除和 doctor 授权修复。
- **人类可编辑真源：** 手工修改的 Markdown 会增量对账；无效文件会被诊断和隔离，不会被猜测性改写。
- **不内置 LLM、Embedding 或向量数据库：** 语义提炼由当前 Agent 完成，KeepM 只执行确定性规则。
- **不使用伪置信度、静默衰减或自动提升：** 用明确生命周期状态和 `verified_at` 管理记忆，审核阈值绝不构成写入授权。
- **不要求 Obsidian 插件或审核 UI：** Obsidian 只是可选编辑器，受控 Agent 对话才是标准审核入口。
- **不归档原始对话：** 临时进度进入有边界的 handoff，长期记忆只保留提炼后的可复用结论。

## License

[MIT](https://github.com/LeoKon3/KeepM/blob/main/LICENSE)
