背景
AI 辅助开发正在改变日常编码方式,但它也把一个老问题放大了:上下文很容易丢。
在短会话里,这个问题不明显。一次对话里把背景讲清楚,AI 通常就能继续往下做。但只要把时间拉长,问题就会迅速出现:
- 隔了一天再继续,很多前提需要重新解释
- 换了人接手,同样的问题又要从头讲一遍
- 文档越积越多,却很难判断哪一份才是当前事实
- 代码能说明“现在是什么”,却很难说明“为什么会这样”
很多团队会在两个极端之间摇摆:
- 完全依赖对话上下文,把知识留在聊天记录里
- 试图用大而全的文档系统覆盖一切
前者的问题是上下文不可持续,后者的问题是维护成本极高,最后往往一起失效。
所以我更倾向于把“长期记忆”从普通文档里单独抽出来,设计成一套更轻、更结构化、同时适合人和 AI 阅读的记忆层。本文把这套做法称为“项目记忆系统”。
它解决的不是“文档不足”,而是“上下文失真”
这套系统最核心的目标,不是多写文档,而是降低上下文在流转过程中的失真。
在实际协作里,失真通常来自四个地方:
-
对话是短期记忆 AI 助手擅长处理当前窗口里的问题,但不天然擅长跨会话延续历史判断。
-
普通文档容易混杂不同层次的信息 有的文件同时写背景、过程、方案、结论、待办,时间一久就没人知道应该先看哪一段。
-
同一事实散落在多个地方 README 写了一份,设计文档写了一份,缺陷复盘里又写了一份,最后三份内容彼此不完全一致。
-
代码无法完整承载决策背景 代码能表达实现,但无法天然表达边界、权衡、已知坑点和历史替代方案。
所以,“项目记忆系统”不是文档系统的替代品,而是代码与文档之间的一层结构化记忆接口。
设计目标
如果把目标说得足够克制,我认为它应该只追求四件事:
-
支持跨会话续作 不管是隔天继续,还是换人接手,都能快速恢复工作上下文。
-
沉淀稳定结论 重点记录“为什么这样做”“哪些约束不能破坏”“哪些历史结论已经过时”。
-
服务人机共读 人类阅读时要足够清晰,AI 读取时也要足够结构化、可检索、可引用。
-
保持低维护成本 如果一套记忆系统自身需要大量维护,它很快也会变成新的负担。
这四个目标里,第四个经常被忽略,但它决定了系统能不能活下来。
一句话定义
项目记忆系统是一组与代码仓并存的结构化文件,用来沉淀长期有效的技术上下文,并为人类协作和 AI 协作提供统一入口。
这里的关键词有三个:
- 结构化:不是随手堆文档,而是明确分类和职责
- 长期有效:优先记录可复用的结论,而不是一次性过程
- 统一入口:让“从哪里开始理解系统”这件事变得确定
与普通文档的区别
| 普通文档 | 项目记忆 |
|---|---|
| 常常按写作主题组织 | 优先按“信息职责”组织 |
| 容易混合过程、背景和结论 | 强调分层存放 |
| 面向人阅读 | 同时面向人和 AI 读取 |
| 可以很长 | 倾向索引化、专题化 |
| 常见问题是“写了但找不到” | 常见问题是“是否放在了唯一正确位置” |
普通文档当然仍然需要,只是它更适合承载长分析、方案说明、架构阐述。
项目记忆系统更像一层“知识索引和稳定结论层”,它不追求面面俱到,而追求快速找准事实源。
目录结构:先分层,再落文件
下面给出一个可直接落地的目录示例。目录名本身不是重点,重点是分层思路。比如 .project-memory/ 这个名字完全可以替换成 memory/、context/ 或其他更适合你的命名。
.project-memory/
├── MEMORY_RULES.md # 更新规则:写入前先看
├── MEMORY.md # 长期记忆索引:只放链接和一句话摘要
├── TOOLS.md # 环境、构建、调试入口
├── architecture/ # 架构结论与主链路
│ ├── overview.md
│ └── core-flows.md
├── runtime-rules/ # 运行时约束与稳定规则
│ └── <topic>-runtime-rules.md
├── bug-fix/ # 缺陷复盘
│ └── YYYYMMDD_<desc>.md
├── plans/ # 实施计划与技术评估
│ └── YYYY-MM-DD-<desc>.md
├── decisions/ # 决策记录(ADR)
│ └── NNNN-<desc>.md
├── operations/ # 当前状态、交接、脆弱区域、变更摘要
│ ├── current-status.md
│ ├── handoff.md
│ ├── fragile-areas.md
│ └── changelog.md
└── templates/ # 模板文件
这套结构里最关键的不是目录数量,而是下面四种分层:
- 索引层:告诉你先看哪里
- 结论层:沉淀稳定规则和架构事实
- 过程层:记录缺陷、计划和决策过程
- 操作层:承载当前活跃事项和交接信息
一旦这四层混在一起,记忆系统很快就会腐烂。
核心原则一:索引优先,不把入口写成正文
MEMORY.md 的职责应该非常单纯:它是入口,不是正文。
错误的做法是把它越写越长,最后变成“总述 + 历史 + 结论 + 待办”的混合文件。这样做短期看起来方便,长期一定会失控。
更好的做法是让索引文件只承担两件事:
- 指向事实源
- 给出一句话摘要,帮助判断是否值得点进去
例如:
# MEMORY.md
- [渲染运行规则](runtime-rules/render-runtime-rules.md) — 线程模型、缓存约束、生命周期边界
- [核心链路](architecture/core-flows.md) — 主数据流、状态同步和关键回写顺序
- [脆弱区域](operations/fragile-areas.md) — 高频踩坑点与历史认知偏差
索引一旦保持精简,入口就不会失效。
核心原则二:同一种信息只有一个归属位置
很多文档失效,不是因为没人写,而是因为同一种内容被写到了多个地方。
例如:
- 架构结论既出现在架构文档里,也出现在缺陷复盘里
- 待办事项既出现在 handoff,也出现在 README
- 运行规则既出现在实现说明里,也出现在 issue 记录里
这时真正的问题不是“内容够不够”,而是“谁才是事实源”。
所以项目记忆系统要强制回答一个问题:
每一种信息,唯一应该放在哪里?
一个可执行的划分方式如下:
| 内容类型 | 推荐归属位置 |
|---|---|
| 架构总览 | architecture/overview.md |
| 关键链路 | architecture/core-flows.md |
| 运行时约束 | runtime-rules/<topic>-runtime-rules.md |
| 缺陷复盘 | bug-fix/YYYYMMDD_<desc>.md |
| 计划与评估 | plans/YYYY-MM-DD-<desc>.md |
| 决策记录 | decisions/NNNN-<desc>.md |
| 活跃事项 | operations/current-status.md |
| 交接待办 | operations/handoff.md |
| 脆弱点与历史偏差 | operations/fragile-areas.md |
只要这个映射足够清楚,后续维护成本会明显下降。
核心原则三:同一事实只维护一份
这条原则和上一条相关,但更严格。
不是“同类信息集中”,而是“同一事实只能有一份正文”。其他地方如果需要提到它,只能:
- 链接过去
- 做一句话引用
- 标明“以 X 文件为准”
这会强迫我们停止写“看起来方便、实际上危险”的重复内容。
例如,“某个模块的状态同步顺序”一旦被确认,就应该只在对应的运行时规则文件里维护。缺陷复盘里如果需要引用,只写一句:
最终行为以
runtime-rules/...中的顺序约束为准。
这样做的直接收益是:
- 减少口径分裂
- 降低更新漏改概率
- 让 AI 在检索时更容易命中真实事实源
核心原则四:把“稳定结论”和“当前事项”拆开
很多团队会把长期知识和短期状态写在一个文件里,这几乎一定会导致入口失效。
例如一个文件既有:
- 当前在做什么
- 哪些问题待验证
- 系统为什么这么设计
- 历史上踩过哪些坑
那它最终一定会越来越长,也越来越不可信。
比较稳妥的做法是明确区分:
- 长期记忆:稳定结论、架构规则、决策、可复用经验
- 短期操作信息:当前阻塞、待办优先级、这轮变更的验证状态
前者应该追求稳定,后者应该允许高频更新。
这也是为什么 operations/ 这一层很重要。它让“今天该做什么”不必污染“系统长期应该怎么理解”。
为什么还需要 fragile-areas.md
如果只保留“正确结论”,很多系统仍然不够好用,因为真实协作里还有一种高价值信息:
哪些地方最容易被误判,哪些历史说法已经不再成立。
这类信息不完全属于架构,也不完全属于缺陷复盘,但它对接手者和 AI 都非常重要。
例如下面这些内容就很适合放进脆弱区域文件:
- 哪些旧文档已经部分过时
- 哪些现象表面看像 UI 问题,实际根因常在底层
- 哪些改动表面上是局部修改,实际会影响整条链路
- 哪些区域过去反复出问题,回归时必须优先关注
这份文件本质上是一张“认知偏差清单”。它能显著降低重复踩坑的概率。
命名规范不是形式主义,而是检索能力的一部分
我很建议所有专题文件都使用语义化命名,而不是随手起名。
推荐格式示例:
| 目录 | 命名格式 | 示例 |
|---|---|---|
bug-fix/ | YYYYMMDD_<brief-desc>.md | 20260328_cache-race.md |
plans/ | YYYY-MM-DD-<brief-desc>.md | 2026-03-28-render-refactor.md |
decisions/ | NNNN-<brief-desc>.md | 0001-state-sync-strategy.md |
runtime-rules/ | <topic>-runtime-rules.md | image-cache-runtime-rules.md |
这样做有三个好处:
- 文件名本身携带主题信息
- 人类能快速扫读
- AI 在检索时更容易建立弱语义匹配
文件命名其实也是记忆系统的一部分。
Frontmatter:给机器看的元信息层
对于 bug-fix/、plans/、decisions/ 这类专题文件,建议统一使用 YAML frontmatter。
---
date: 2026-03-28
status: fixed
type: bug-fix
modules: [render, cache]
related:
- ../runtime-rules/image-cache-runtime-rules.md
---
这样做并不是为了“文档更正式”,而是为了让这些文件具备可解析性。
它至少能支持三类能力:
- 自动筛选某个阶段仍未完成的计划
- 关联某次缺陷修复涉及的模块和规则
- 为 AI 或脚本提供更稳定的结构化输入
如果没有这层元信息,后续很多自动化能力都很难做稳。
预警机制:防止记忆系统重新长成一堆杂物
一个容易被忽略的经验是:记忆系统也会腐烂。
所以除了定义目录和职责,还需要定义“什么时候该警觉”。
例如可以设定一些预警阈值:
| 文件 | 预警信号 |
|---|---|
MEMORY.md 超过 80 行 | 很可能开始混入正文 |
current-status.md 超过 40 行 | 很可能混入历史日志 |
handoff.md 待办超过 10 条 | 很可能没有及时清理完成项 |
| 单个复盘文件超过 150 行 | 很可能混入方案设计或背景长文 |
这些阈值不是为了机械限制篇幅,而是为了触发一次检查:
这个文件是否开始承载不属于它的内容?
这一步很关键。因为大多数系统不是在设计阶段失败的,而是在维护阶段慢慢变形的。
什么内容不应该进入长期记忆
这条规则比“应该写什么”更重要。
以下内容我通常不会放进长期记忆:
- 一次性试错命令
- 大段原始日志
- 没有复用价值的讨论记录
- 很快会失效的临时判断
- 敏感配置、账号、密钥、私有地址
长期记忆最怕的不是内容少,而是噪音太多。
一旦噪音比例过高,AI 和人类都会更难从中提取真正有价值的上下文。
这套系统与 README、ADR、Wiki 的关系
项目记忆系统不是要取代已有文档,而是给它们补一层结构。
可以简单理解为:
- README:给第一次进入仓库的人看,回答“这是什么、怎么跑起来”
- Wiki / docs:承载长分析、方案说明、背景材料
- ADR:记录关键技术决策及其权衡
- 项目记忆系统:作为统一入口,把长期有效的上下文组织起来
其中 decisions/ 目录本身可以直接采用 ADR 形式,但它不应孤立存在,而应被索引系统引用,并与计划、复盘、运行规则建立关联。
也就是说,这套设计不是“另起一套文档体系”,而是在现有文档之上建立“更适合协作和检索的骨架”。
为什么它特别适合 AI 辅助开发
这套方法对 AI 友好,主要不是因为“文件多”,而是因为它把上下文变成了可预测的结构。
对于 AI 来说,最重要的不是信息总量,而是:
- 入口是否明确
- 文件职责是否清楚
- 事实源是否唯一
- 哪些内容稳定、哪些内容临时,能否区分
只要这四件事成立,AI 在会话启动时就可以按固定顺序读取上下文,例如:
- 先读更新规则,避免写错位置
- 再读总索引,建立整体地图
- 再读工具入口,确认构建和验证方式
- 按任务需要进入架构、运行规则、复盘或计划
- 最后补充当前状态和交接信息
这个顺序本质上就是在告诉 AI:
- 先理解地图
- 再理解约束
- 最后进入具体问题
这比“把整个仓库全扫一遍”更高效,也更可靠。
如果今天开始落地,我会先做哪三件事
如果你不想一次性搭完整套体系,我建议先做最小可用版本:
1. 建一个真正精简的 MEMORY.md
它只做入口,不做正文。
2. 建一个 operations/handoff.md
把“下一次继续时最需要知道什么”固定下来。
3. 建一个 runtime-rules/
把那些“代码里不容易直接看出来,但改坏了后果很明显”的规则单独沉淀出来。
只做这三件事,很多协作效率问题就已经会明显改善。
后续再逐步补上:
bug-fix/用于缺陷复盘decisions/用于 ADRfragile-areas.md用于认知偏差和高频坑点
这比一开始就试图设计完整知识库更容易成功。
维护成本从哪里来
任何记忆系统都有成本,关键是成本要可控。
这套设计的主要成本不在“写文档”,而在三件事:
- 判断一条信息该写到哪里
- 发现重复内容后主动合并
- 在系统演进后及时标记过时结论
换句话说,它真正要求的不是写作能力,而是信息治理能力。
如果一个团队已经习惯把所有内容都塞进一个 README,或者把大量判断留在聊天记录里,那么这套方法一开始会有一点阻力。但一旦入口和职责稳定下来,后续成本通常会越来越低,而不是越来越高。
总结
项目记忆系统想解决的,本质上不是“缺少文档”,而是“上下文无法长期稳定流转”。
它的核心思想可以压缩成四句话:
- 入口要轻:索引优先,不让入口承担正文职责
- 事实要唯一:同一事实只维护一份
- 信息要分层:稳定结论、过程记录、当前状态分开存放
- 结构要可持续:通过命名、模板和预警机制控制维护成本
如果把它用一句更直白的话总结,那就是:
不要试图让 AI 记住一切,而要为它准备一套可持续读取的长期记忆。
这套方法并不依赖某个特定工具,也不依赖某个具体平台。目录名、文件名和细节规则都可以调整,但有两个原则我认为最好不要放弃:
- 单一事实源
- 索引优先
只要这两个原则成立,整套系统就会有很强的可迁移性。