这份写的是「该长成什么样」和「判据」,不写过程。 一步步做了什么、量到什么数,在
记忆体设计蓝图.md(步骤日志);当时怎么栽的,在各条记忆正文里。 这份本身就是周末重写知识库要用的格式样板:每一句都是现状或判据,没有一句是故事。 网页版 https://hoop-docs.pages.dev/memory-design(从这份 md 生成,改这份再跑./tools/deploy_docs.sh)。
0. 一页判据(全文的缩影,记不住别的就记这七条)
- 记忆是收件箱,不是档案馆。 每条教训进来都要问「毕业到哪儿」,答得上来的搬走、索引删一行;答不上来的才留。
- 知识库写现状,不写过程。 过程有它自己的地方(git 历史 · CHANGELOG · 记忆正文)。判据:每句"现在是这样"能不能指到
file:line。 - 规矩按「什么时候需要它」分三类,只有第一类留在每次都读的地板上:时刻在眼前 / 动手那一刻 / 按题目找。
- 能做成闸的就别靠记得。 是非题 + 挂在动作上 + 返工只退一步 + 出事不报错 + 后果重 → 做成 blocking guardrail(PreToolUse hook)。
- 会当场报错的伤口不用装护栏。 闸是留给静默出事的。
- 同一件事实只能有一个出处。 铁律 / 记忆索引 / 哨兵前言里重复的那批,收成一份。
- 名字就是索引。 知识库一个部分一份、名字就是那个部分,L1 只留一行指路,不再需要目录文件。
1. 每次调用真读什么(2026-09-04 量的)
| 大小 | 性质 | |
|---|---|---|
| ① CLI 自己的底(系统提示 + 工具说明) | ≈ 2.3 万 tok | 动不了 |
② CLAUDE.md(含图纸地图 8 行 / 2 KB) |
8.8 KB | L1 |
③ docs/铁律.md |
12.6 KB / 29 条 | L1,整份必读 |
④ MEMORY.md(记忆主索引) |
19.1 KB / 154 条 | L2 索引,闸限 20 KB |
⑤ 哨兵前言(core + workroom + 各家 task.md) |
22 KB 字 | 走 --append-system-prompt --system-prompt-snapshot on |
| ⑥ 本轮指令(哪间房响了 / 打招呼) | 2–4 KB | user 消息,每轮不同,缓存不了 |
不每次读、要用才翻的:4 份分索引(224 条 / 24 KB)· 377 份记忆正文(1.2 MB)· docs/00-目录.md(27 KB,09-03 起不再 @ 进 L1)· docs/ 101 份。
判据:读的钱按次付,缓存只免"重写"不免"读"。 --append-system-prompt 解决的是"每轮累积一份",不解决"每次都读";把一份 25 KB 的东西从 user 消息挪进系统提示,每次调用的成本几乎不变。
2. 规矩按触发方式分三类
| 类 | 什么时候需要它 | 载体 | 每次调用成本 | 现状 |
|---|---|---|---|---|
| A 时刻在眼前 | 要犯那一刻它必须已经在眼前,而你不知道自己要犯 | 铁律.md(整份 @ 进 L1) |
付 | 29 条,已是「只写命令不写故事」格式,但仍夹故事 |
| B 动手那一刻 | 敲某条命令 / 改某个文件 / 发某条消息的那一秒 | PreToolUse hook(§3) | 零(不动手一个字不读) | 六条规矩、上膛三条 |
| C 按题目找 | 干某一块活才需要:状态、账号、图纸、某模块的判据 | 分索引 · 知识库(§6)· 记忆正文 | 零,翻了才付 | 靠自觉翻;实测一半会话一份图纸都没开 |
判据:A 类越少越好(每条都在每次调用收钱,而且越长遵循度越低);能从 A 搬去 B 的一定搬;C 类要靠"名字就是索引"才翻得到。
3. 闸(guardrail)层 —— B 类的载体
3.1 是什么
- 专业名:PreToolUse hook(Claude Code 官方机制);行业词 guardrail;安全术语 policy enforcement point。
- 分 advisory(只提醒,索引那种)和 blocking(不合格过不去)。这一层做的是 blocking。
- 机制:分身每次要跑命令 / 改文件之前,系统先把那条命令原文交给我们的小程序;它退 0 放行,退 2 拦下并把那条教训原文打到分身眼前。分身想跳过也跳不过。
- 成本:放行一条命令 25 ms(最慢 46),一个 token 不烧。
3.2 什么样的规矩才做成闸(五条同时成立)
- 是非题:看得出来,不用琢磨(
--delete在不在命令里 ✓;「这算不算坏话」✗) - 挂在看得见的动作上:跑命令 / 改文件 / 发消息
- 返工只退一步:拦下时要重做的是那一条命令,不是那一整段活(错误织进做完的活里的,不该做闸,该留 A 类或做成测试)
- 出事不报错:静默的才需要闸;会当场报错的不用(zsh 不做单词拆分 →
pathspec did not match,自己会喊疼) - 后果重或回不来
判据:闸拦错一次的代价全家一起付。 所以先小步上膛,误报率看一天再扩。
3.3 现状(2026-09-04)
- 出处:主仓
tools/hoop-lib/act_guard.py;各机器~/.hoop/act_guard.py软链;钩子写在~/.claude/settings.json的PreToolUse(matcher: Bash),和memory_guard.py并排。 - 规矩表六条:
rsync --delete·git add ./-A·rm· 裸git stash pop·flutter run直推真机 · 非 NOVA 出 TF 包。 - 默认只上膛三条不可逆的:
rsync --delete/git add ./flutter run直推真机。~/.hoop/act_guard_rules一行一个名字可改,单独一行all全开。 - 每条规矩两个用例:一个该拦的、一个长得像但不该拦的(
echo '别加 --delete'必须放行:引号和 heredoc 正文先剥掉再看)。自检 19 条,走真钩子路径看退出码。 - 它管不到的:没经过动作的字(我在终端直接打给你看的)、判断题、方向理解错 —— 那些仍只能靠 A 类。
3.4 索引里挂得上闸的那批(量过的)
主索引 154 条里 18 条挂得上(11%);其中整行删得掉的只有 3 行(≈ 400 字节,2%)—— 索引按行挤、一行装 3–5 条,删不掉整行就省不到字。 结论:闸的价值不在省字,在把那 18 条从"要我记得"变成"忘了也不会犯"。 搬不搬 18 条,待 Jeff 拍板(他 09-04:「别做,我想想」)。
4. 教训的去处(收件箱怎么清)
一条 feedback 记忆只有四个毕业去处;毕业后索引删一行,正文留档或删:
| 去处 | 什么样的教训 | 在哪 | 毕业后 |
|---|---|---|---|
| 闸(hook / 守卫 / 测试) | 满足 §3.2 五条 | tools/ · app/test/ · backend/*_test.go |
机器替你记,记忆可删 |
| 步骤(操作单) | 有固定顺序的活:出包 8 步、建 spider 11 条、装哨兵 | docs/必读-*.md 或知识库那一份的「动它之前」 |
记忆并进那份单 |
| 判据(铁律) | 判断题 · 跨场景 · 换台机器换个人也成立 | docs/铁律.md,一两行 |
记忆只留正文当案底 |
| 代码注释 | 只在那一处成立的坑 | 写在那一行旁边 | 记忆可删 |
留在记忆里的只应该是:还没想清楚归哪儿的、太冷门不值得搬的、只对这一条线成立的、或只有故事没判据的。
判据:每条教训问它「毕业到哪儿」,答不上来的才留。 记忆应该越用越薄。
自带的一道筛子:记忆是各台机器自己的、故意不共享(NOVA 栽的跟 Navi 栽的不是一回事);docs 和 tools 在 git 里全家共读。换台机器也成立的才配毕业进 docs / tools;只对我成立的留在我的记忆里。
现状数字(2026-09-04):feedback 204 份;已进铁律 24 份、已做成代码 ≈ 2 份、还躺在收件箱 178 份;毕业了的 24 份也没销户,索引里还占着行。
已毕业的好样本:必读-建Spider.md = 11 条真栽过的教训并成一份操作单。
5. 记忆文件三类怎么处理(377 份,1.2 MB)
| 类型 | 份数 | 大小 | 处理 |
|---|---|---|---|
feedback 教训 |
204(54%) | 509 KB | 按 §4 毕业;留下的砍故事留判据 |
project 状态 |
131(34%) | 590 KB | 大多数不该在记忆里:游戏进度 → TASKS.md 或代码;账号 → _index-env;悬着的事 → WIP.md。状态写进一个没人更新的地方 = 必陈(和 DEPLOY.md 写"待执行"同一个病) |
reference 指路 |
37(9%) | 105 KB | 留,它们短 |
判据:会过期的东西不进记忆;记忆只放"以后别再犯"和"怎么找到"。
6. 知识库(docs/)重写 —— C 类的载体
6.1 为什么重写而不是修
101 份里 14 份标着 ⚠️ 与现实不符,CASTLE.md 被作废却仍自称真相来源,多数混写"现状"和"从哪版改到哪版"。过程文字不是白占地方,是会把人带错方向的:它看起来像真相。
6.2 三条判据(周末做之前先读)
- 从代码写,不从旧图纸写。 旧 docs 只当"当年想做什么"的线索;现状以代码为准。判据:每句"现在是这样"能不能指到
file:line。GREEN_ENERGY_ASBUILT.md是样板。 - 只写现状,不写过程。 变更史留在 git 和 CHANGELOG,一个字不进图纸。
- 一个部分一份,名字就是那个部分。
chat·calls·games·music·community·wallet·sentinel……十几份,不是一百份。
6.3 每份的结构
docs/<部分>.md
├── 现状:现在怎么工作 · 动它看哪几个文件 · 哪几个数不能碰 ← 从代码写,带 file:line
└── 动它之前:这块的判据和步骤 ← 从记忆毕业来的(§4),没有一句是故事
两件事合成一件:重写一份图纸的时候,顺手把归这个模块的教训过一遍,写进「动它之前」;跨模块的进铁律;哪儿都不归的留在记忆。
6.4 老的怎么办
- 旧 101 份整个挪进
docs/archive/,不删,重写时当线索翻。 - 写完一份、对着代码核完一份,对应的旧几份才算真作废。核是慢活,不能省。
docs/00-目录.md随之退役:名字就是索引,CLAUDE.md只留一行「要看哪块就开docs/<部分>.md」。
6.5 为什么不选另外两条路
- 不做地图生成器 + 守卫:那是在给一堆过期文字续命。
- 不把目录塞进
--append-system-prompt:它只解决"每轮累积",不解决"每次都读",25 KB 照付。
7. L1 去重:同一条规矩三个出处
铁律 / 记忆索引「一犯就出事」那节 / 哨兵前言 core.md,讲的是同一批教训(读消息新到旧、别加 --anyway、稿子写自己家路径……)。三份手抄,一改就腐(铁律 23)。
- 本体 = 铁律(它已经是「只写命令不写故事」的格式,也是唯一跨机器的教训层)。
- 前言只留哨兵机制(怎么拉消息、怎么发、怎么落卡),教训改成「见铁律 N」。
- 索引那节里和铁律重复的,改成一行指过去。
- 前言
core.md自己也是过程写法(「每条括号里的日期 = 当时真栽的那次」),同样按「留判据砍故事」处理。
8. 状态
已做(2026-09-03/04)
- 主索引留判据砍故事 24.3 → 18.5 KB,闸拧到 20 KB(memory_guard.py,主仓出处、各机器软链)
- 00-目录.md 从 L1 摘掉,换 8 行图纸地图(77 个名字,1,957 字节)
- 动手闸 act_guard.py 装上,上膛三条;19 条自检
- 出包流水线收进仓 tools/tf-build/,口令挪出 git,announce 没读到 APPROVED 不发 General
待 Jeff 拍板(各一句) - 索引里挂得上闸的 18 条,搬不搬(§3.4) - 周末重写知识库怎么分工(§6) - 前言里的教训收进铁律(§7)
明确不做 - 地图生成器 / 守卫(§6.5) - 目录塞 append(§6.5) - 判断题做成闸(§3.2)
9. 关联
- 步骤日志:
记忆体设计蓝图.md(每做一步记一步;线上/memory) - 各机器砍索引操作单:
必读-砍记忆索引.md - 闸的出处:
tools/hoop-lib/memory_guard.py·tools/hoop-lib/act_guard.py - 哨兵成本账:
SENTINEL_COST_HANDOFF.md