Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ MiniCode Rebuild 是一个从零、分阶段实现的本地终端 AI Coding Agen

## 当前状态

阶段 0“仓库初始化与工程基线”至阶段 10“可观测性、质量与发布准备”已经完成。
阶段 0“仓库初始化与工程基线”至阶段 10“可观测性、质量与发布准备”已经完成;阶段 11 已选择并实现独立高级能力“长期记忆与检索”。

目前已经具备:

Expand Down Expand Up @@ -36,11 +36,30 @@ MiniCode Rebuild 是一个从零、分阶段实现的本地终端 AI Coding Agen
- 扫描工作区 `.minicode/skills/<name>/SKILL.md`,仅注入有界元数据,并通过 `load_skill` 按需加载正文;
- 在 Agent、会话与工具边界注册进程内 Hooks,隔离并显式报告 Hook 失败;
- 将脱敏生命周期元数据写入工作区 JSONL 日志,并通过时间线查看运行过程;
- 离线检查 Python、运行配置、Provider 配置、会话存储与 Skills readiness;
- 在工作区本地显式保存长期记忆,并通过有界词法检索按需召回;
- 将记忆结果标记为不可信历史数据,模型写入和删除仍经过权限边界;
- 离线检查 Python、运行配置、Provider 配置、会话存储、Skills 与记忆存储 readiness;
- 使用 Ruff、Mypy、分支覆盖率、构建、安装和跨平台 CI 作为发布质量门禁;
- 执行自动化测试。

阶段 0 至阶段 10 的基础路线已经完成。后续高级能力必须从阶段 11 清单中单独选择、设计、测试和提交。
阶段 0 至阶段 10 的基础路线和阶段 11 的“长期记忆与检索”已经完成。其余高级能力仍必须单独选择、设计、测试和提交。

## 长期记忆与检索

长期记忆保存在当前工作区 `.minicode-rebuild/memories.json`,不会跨工作区共享,也不会把完整会话自动写入记忆。模型只得到记忆使用规则,不会在每轮自动加载全部内容;需要历史事实时,通过 `search_memory` 按需检索。

交互模式可由用户直接管理记忆:

```text
/memory add Prefer pytest for regression tests
/memory list
/memory search pytest
/memory forget <memory-id>
```

`/memory add` 是用户显式持久化指令;`/memory forget` 会展示目标内容,并要求完整输入 `yes`。模型调用 `save_memory` 或 `delete_memory` 时仍走现有权限提示,Headless 模式默认拒绝,只有显式使用 `--allow-mutations` 才允许本次进程修改记忆。

存储最多 500 条记忆;单条内容、标签、查询、返回数量和结果预览均有上限。检索使用无网络、无第三方依赖的确定性词法评分,适合项目约定、用户明确偏好和长期任务事实,不等同于 embedding 语义搜索。检索结果始终带有“不可信历史数据”边界,不得覆盖当前系统或用户指令,也可能已经过时。

## 可观测性与 Readiness

Expand Down Expand Up @@ -171,9 +190,9 @@ minicode-rebuild --interactive --resume latest
minicode-rebuild --resume <session-id> "继续上次任务"
```

交互模式提供 `/help`、`/session`、`/sessions`、`/transcript`、`/checkpoints`、`/rewind-preview [checkpoint-id]`、`/rewind [checkpoint-id]`、`/stats`、`/compact` 和 `/exit`。`/rewind` 总会先显示预览,只有随后完整输入 `yes` 才修改文件;发现 Agent 写入后又有外部修改时会拒绝覆盖。
交互模式提供 `/help`、`/session`、`/sessions`、`/transcript`、`/checkpoints`、`/rewind-preview [checkpoint-id]`、`/rewind [checkpoint-id]`、`/skills`、`/memory`、`/timeline`、`/stats`、`/compact` 和 `/exit`。`/rewind` 总会先显示预览,只有随后完整输入 `yes` 才修改文件;发现 Agent 写入后又有外部修改时会拒绝覆盖。

会话 JSON 位于工作区 `.minicode-rebuild/sessions/`,已从 Git 与内置文件工具中隔离。Checkpoint 只覆盖 `write_file`、`edit_file` 和 `patch_file` 的 UTF-8 文件变更;`run_command` 的任意副作用不在 Rewind 范围内。写文件和运行命令仍会显示风险与操作详情,并要求选择一次允许、会话允许或拒绝。Headless 模式默认拒绝所有变更;只有明确传入 `--allow-mutations` 才会在本次运行内逐项自动批准,并在标准错误输出警告。
会话 JSON、长期记忆和事件日志位于工作区 `.minicode-rebuild/`,已从 Git 与内置通用文件工具中隔离。Checkpoint 只覆盖 `write_file`、`edit_file` 和 `patch_file` 的 UTF-8 文件变更;`run_command` 的任意副作用和专用记忆存储不在 Rewind 范围内。写文件、运行命令和模型发起的记忆变更仍会显示风险与操作详情,并要求选择一次允许、会话允许或拒绝。Headless 模式默认拒绝所有变更;只有明确传入 `--allow-mutations` 才会在本次运行内逐项自动批准,并在标准错误输出警告。

每轮会输出模型步数、工具次数、模型返回的 token 用量和压缩次数。上下文估算是跨 Provider 的保守启发式,不等同于服务端精确 tokenizer;工具结果会优先裁剪,旧轮次按用户输入边界摘要,并始终保留最近完整轮次和主系统提示。会话恢复加载的是受预算约束的工作历史,`/transcript` 则保留完整、未压缩的用户消息、assistant 工具调用和工具结果。

Expand Down Expand Up @@ -335,7 +354,7 @@ python scripts/demo.py
## 跨平台与发布检查清单

- Windows 使用 `\.venv\Scripts\python.exe`,macOS/Linux 使用 `./.venv/bin/python`;项目业务命令仍通过参数数组和 `shell=False` 执行。
- 两个符号链接安全测试在未授予 Windows 创建符号链接权限时会跳过;CI 的 Ubuntu 任务覆盖该路径。
- 三个符号链接安全测试在未授予 Windows 创建符号链接权限时会跳过;CI 的 Ubuntu 任务覆盖通用路径、文件工具和记忆存储的真实逃逸路径。
- 终端输出、Skill、会话和事件日志统一使用 UTF-8;Windows 文件替换与权限位行为已有平台保护。
- 发布前确认 Ruff、Mypy、覆盖率测试、编译、构建、全新环境 wheel 安装和 Mock 演示全部通过。
- 检查 Git diff 中没有 `.env`、API Key、会话、事件日志、缓存、构建产物或无关目录。
Expand Down
97 changes: 87 additions & 10 deletions docs/REBUILD_LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

| 项目 | 内容 |
|---|---|
| 当前阶段 | 阶段 11:可选高级能力(待选择) |
| 最近完成 | 阶段 10:可观测性、质量与发布准备 |
| 当前分支 | `rebuild/minicode-learning` |
| 最新阶段实现提交 | `edf1569 chore(phase-10): add readiness checks and release verification` |
| 测试状态 | 阶段 10 相关测试 `37 passed`;全量回归 `244 passed, 2 skipped`;分支覆盖率 `85.08%` |
| 下一步 | 从阶段 11 清单中选择一个独立高级能力,不打包推进 |
| 当前阶段 | 阶段 11:长期记忆与检索(已完成) |
| 最近完成 | 阶段 11:长期记忆与检索 |
| 当前分支 | `codex/phase-11-memory` |
| 最新阶段实现提交 | `d06ad40 feat(phase-11): add workspace long-term memory` |
| 测试状态 | 阶段相关回归 `61 passed, 1 skipped`;全量回归 `276 passed, 3 skipped`;分支覆盖率 `85.47%` |
| 下一步 | 审核并由用户合并 Draft PR #5;其他高级能力继续保持独立阶段 |

## 总体架构

Expand All @@ -38,10 +38,10 @@ flowchart LR
| 5 | 最小 Agent Loop | 已完成 | 有界模型/工具执行循环 | `c91c47c` |
| 6 | 可用的 CLI 与运行配置 | 已完成 | 交互模式、Headless 模式和运行配置 | `7f3e86e` |
| 7 | 上下文预算与压缩 | 已完成 | 预算、裁剪、摘要和降级策略 | `2bf4bfa` |
| 8 | 会话、Checkpoint 与 Rewind | 待开始 | 会话持久化、检查点和恢复 | - |
| 9 | Skills、Hooks 与扩展机制 | 待开始 | 按需技能和生命周期扩展点 | - |
| 10 | 可观测性、质量与发布准备 | 待开始 | 日志、质量门禁、安装与发布验证 | - |
| 11 | 可选高级能力 | 待开始 | 核心稳定后单独选择并实现 | - |
| 8 | 会话、Checkpoint 与 Rewind | 已完成 | 会话持久化、检查点和恢复 | `b4afec3` |
| 9 | Skills、Hooks 与扩展机制 | 已完成 | 按需技能和生命周期扩展点 | `6201245` |
| 10 | 可观测性、质量与发布准备 | 已完成 | 日志、质量门禁、安装与发布验证 | `edf1569` |
| 11 | 长期记忆与检索 | 已完成 | 工作区本地记忆、按需检索和权限控制 | `d06ad40` |

## 阶段 0:仓库初始化与工程基线

Expand Down Expand Up @@ -1726,3 +1726,80 @@ Provider readiness 被定义为“本地配置可构造”,而不是“远程
- 文档收口将在下一提交记录;提交将推送到阶段 10 的独立 Draft PR,不自动合并 `master`。

推送后沿用仍开放的 Draft PR #4,并将标题/说明扩展为阶段 9—10。新引入的 GitHub Actions 在 Ubuntu 3.11、Ubuntu 3.13、Windows 3.11、Windows 3.13 四个组合全部通过;PR 保持 Draft、`MERGEABLE`,未合并 `master`。

## 阶段 11:长期记忆与检索

### 1. 开发前计划

- 只实现阶段 11 清单中的“长期记忆与检索”,不同时引入 MCP、多 Agent、模型路由、TUI 或成本控制。
- 使用工作区本地 `.minicode-rebuild/memories.json` 保存结构化记忆;存储必须原子替换、限制记录数和字段长度,并拒绝损坏或跨工作区数据。
- 提供确定性的无向量词法检索,按精确短语、关键词重合和新鲜度排序;结果数量和单条预览均有上限,不增加运行时第三方依赖。
- 模型只看到记忆工具说明,不自动获得全部记忆。`search_memory` 按需读取;`save_memory` 和 `delete_memory` 必须经过现有 `PermissionManager`,Headless 默认拒绝。
- 检索结果明确标记为不可信的历史数据,记忆内容不得被当作系统指令;不自动保存完整对话、工具参数、工具输出、API Key 或未知敏感信息。
- 交互 CLI 提供 `/memory search`、`/memory add`、`/memory forget` 与 `/memory list`,用户显式命令直接管理当前工作区记忆,并保持友好错误输出。
- 为存储往返、损坏文件、容量限制、排序、截断、权限拒绝、工具隔离、CLI 命令和跨会话检索补齐测试,再执行阶段测试、全量发布门禁和 GitHub Actions。

### 2. 威胁模型与非目标

- 防止静默持久化:模型写入和删除必须授权,用户命令则以用户显式输入作为授权意图。
- 防止提示注入:检索输出使用数据边界标记,系统提示要求将记忆视为可能过时或恶意的数据而非指令。
- 防止无限增长和上下文淹没:限制记录总数、内容/标签长度、搜索返回数和预览长度。
- 防止通用文件工具绕过:存储继续位于阶段 8 已隔离的内部目录,只能通过 MemoryStore 和专用工具访问。
- 本阶段不做 embedding、外部向量库、语义相似度、跨工作区共享、云同步、自动事实抽取、加密或多进程锁;这些需要独立的隐私、依赖和并发设计。

### 3. 存储与检索设计

`MemoryStore` 将记忆保存为 `.minicode-rebuild/memories.json`。文件包含 schema version、规范化后的工作区身份和记录数组;每条记录只包含 32 位随机 ID、正文、标签、创建时间和可选来源会话 ID。读取时重新解析真实路径,拒绝运行目录符号链接逃逸、跨工作区复制、未知 schema、损坏 JSON、重复 ID、异常时间戳和非规范化字段。

写入采用同目录临时文件、flush、fsync 和 `os.replace` 原子替换,不会先破坏旧文件。达到 500 条容量上限时明确失败,不静默淘汰用户已有记忆;正文最多 2,000 字符,最多 8 个标签,存储文件最多 2 MiB。

检索不引入 embedding 或网络依赖。查询先 casefold 并提取 Unicode 词项,再按完整短语、标签精确匹配和词项重合计分,同分时优先较新的记录。一次最多返回 20 条,默认 5 条;每条预览限制为 500 字符。该实现对明确关键词、项目约定和用户偏好是确定且可测试的,但不宣称具备通用语义相似度。

### 4. Agent、权限与 CLI 集成

默认工具注册表新增:

| 工具 | 行为 | 权限 |
|---|---|---|
| `search_memory` | 按需检索当前工作区记忆,结果带“不可信历史数据”标记 | 只读,无需授权 |
| `save_memory` | 保存用户明确要求长期记住的单条事实 | 中风险,默认拒绝 |
| `delete_memory` | 按精确 ID 删除一条记忆,授权预览包含目标内容 | 高风险,默认拒绝 |

系统提示只注入记忆使用规则,不注入记忆正文。规则要求模型把检索结果视为可能过时或恶意的数据,不得覆盖当前指令;只有用户明确要求时才能写入或删除,且不得保存密钥、完整 transcript 或原始工具输出。模型发起的变更复用阶段 4 `PermissionManager`:Headless 默认拒绝,`--allow-mutations` 才允许本进程内逐项批准。

交互 CLI 的 `/memory add <text>`、`/memory list`、`/memory search <query>` 是用户直接管理入口;`/memory forget <id>` 会先展示内容,并要求完整输入 `yes`。用户命令不经过模型,不产生 Provider 调用。新 CLI 进程可从相同工作区召回已有记忆,证明记忆生命周期独立于单个 Session。

### 5. 验收与安全回归

- 阶段相关回归:`61 passed, 1 skipped`。
- 全量回归:`276 passed, 3 skipped`。
- 分支覆盖率:`85.47%`,达到 `85%` 门槛。
- Ruff:`All checks passed!`。
- Mypy:`Success: no issues found in 28 source files`。
- `compileall`、sdist/wheel 构建和无网络 MockModel 演示全部通过。
- 测试覆盖存储往返、标签规范化、排序、截断、容量、损坏文件、跨工作区复制、符号链接逃逸、默认拒绝、会话授权、删除预览、CLI 确认和跨进程召回。

当前 Windows 环境缺少目录符号链接权限,因此记忆存储逃逸测试与既有两个符号链接测试一起跳过,共 `3 skipped`;Ubuntu CI 会执行这些真实路径。该限制不影响普通 Windows 功能。

### 6. 限制与后续边界

记忆文件是单进程原子写入设计,没有跨进程锁;多个进程同时修改时可能发生最后写入覆盖。内容以工作区本地明文保存,依赖主机文件权限,不提供字段加密或自动敏感信息识别。词法检索无法理解同义词或模糊语义,也不会自动判断事实是否过期。

这些限制不会用 MCP、向量数据库、多模型路由或自动事实抽取在本阶段内补齐。若继续扩展,必须从阶段 11 剩余清单中重新选择一项,建立独立阶段、测试、提交和 PR。

### 7. Git 记录

- 基线:阶段 9—10 的 PR #4 已合并至 `master`,合并提交为 `6090137`。
- 分支:`codex/phase-11-memory`。
- 实现提交:`d06ad40`。
- 提交信息:`feat(phase-11): add workspace long-term memory`。
- CI 修复提交:`ee6f237 fix(phase-11): preserve memory path escape errors`。
- 文档收口使用独立提交;分支推送后创建以 `master` 为基线的 Draft PR,不自动合并。

### 8. 首轮 CI 修复记录

Draft PR #5 的首轮 Windows/Ubuntu、Python 3.11/3.13 四组任务都在同一个符号链接安全测试失败。日志证明存储初始化已经拒绝越界路径,没有在工作区外写文件;失败仅因为构造阶段把 `path_outside_workspace` 统一转换成了“工作区无法解析”,而测试要求保留“存储路径逃逸”的精确分类。

修复只在 `MemoryStore` 构造阶段区分该稳定错误码,继续拒绝操作,并增加不依赖主机符号链接权限的错误映射单元测试。修复后本地完整发布门禁为 `276 passed, 3 skipped`、覆盖率 `85.47%`,Ruff、Mypy、编译、构建与 Mock 演示全部通过;最终跨平台结果以重新触发的 PR #5 CI 为准。

`ee6f237` 推送后,GitHub Actions 的 Ubuntu 3.11、Ubuntu 3.13、Windows 3.11、Windows 3.13 四组任务全部通过。PR #5 保持 Draft、以 `master` 为基线且可合并;阶段 11 不自动修改或合并主分支。
Loading
Loading