wb-memory-discipline
让 WorkBuddy 现有的三层记忆(云记忆 / 用户级本地 MEMORY.md / 工作区记忆)从摆设变成真生效的纪律层。本 Skill 不替代内置记忆机制,只提供"什么该记、写哪、怎么加载、怎么淘汰"的操作协议。
适用场景(触发词)
记一下 / 记住这个 / 决策记录 / 参数变更 / 跨会话 / 加载上次 / 该记什么 / 收工 / 总结 / 蒸馏
> 触发后先判定四类并回显摘要,未确认不落盘;闲聊中误说触发词不会静默写盘。
核心原则
- 显式闸门(零自动捕获 + 安全过滤):只写四类,密钥/隐私拒写,其余禁止写盘。
- 写入路由表:什么内容写哪个文件,不靠即兴判断。
- 主动加载协议:HANDOFF → 工作区 MEMORY → 用户级 MEMORY → 近 3 天日志 → 云注入,带加载预算。
- 结构化模板:决策/参数/偏好/教训/开放问题/阻塞,不写自由日记。
- 差异化淘汰:高价值永久,临时限时,绝不自动删。
- 用户确认优先:核心动作(写盘 / 删除 / 覆盖 / 写用户级)需用户确认,不做静默自动动作;低风险追加 / 索引默认执行仅回显(见检查点分级)。
机制 A:显式闸门
四类
- (a) 决策 / commit / 参数变更
- (b) 跨会话阻塞上下文
- (c) 用户明说偏好(拆为 (c1) 跨项目偏好→用户级、(c2) 项目偏好→工作区,见写入路由表)
- (d) 踩坑 / 教训(格式:"X 翻车,原因 Y")
安全 / 隐私过滤(显式优先级)
判定顺序(命中即执行,不进入歧义升级):
1. 纯敏感 → 整条拒写并说明,不追问、不脱敏后偷记。范围:密钥 / token / 密码 / 凭证、身份证 / 手机号 / 客户隐私 / 公司敏感数据。
2. 混合敏感 → 将敏感片段替换为 <env:NAME> 或 <redacted>,其余内容按四类闸门正常判定;占位符必须可解析(如 <env:DB_TOKEN> 对应真实变量名),不可解析则整条拒写。
- 例:"记一下 DB 配置,key 是 sk-xxx" → "DB 配置(连接凭证 <env:DB_TOKEN>)",再按 (a)/(c) 等路由。
3. WB 不得把任何明文凭证写入 MEMORY;确需记录只记脱敏引用(如 客户A=<脱敏:张*>)。
拒写理由速查表
| 用户内容 | 判定 | 理由 |
|---|---|---|
| "今天天气不错" | 拒 | 非四类 |
| "刚才那个 bug 修了" | 拒(除非关联参数变更) | 临时状态 |
| "我觉得 AI 会取代程序员" | 拒 | 观点非偏好,无操作价值 |
| "帮我查个东西" | 拒 | 临时请求 |
| "记一下这个 key:sk-xxxx" | 拒(安全过滤) | 明文凭证,违反隐私闸门 |
| "下次别用那个库了,坑多" | 记→(d) 教训 | 已验证反模式 |
| "缓存超时从 30s 改为 60s" | 记→(a) 参数变更 | 含 old→new |
歧义升级规则
- 白名单直接拒(不追问):命中下方「拒写理由速查表」的明确非四类情形(闲聊 / 临时状态 / 观点 / 临时请求 / 纯敏感)→ 直接按表拒写或安全拒写,不进入追问。A1、A2 等即属此类,判拒而非追问。
- 白名单外且语义无法归类 → 追问一次:WB 判断不出属于 a/b/c1/c2/d 哪一类时,不默认拒写,追问用户:"我判断这条为临时信息,要我记下来吗?(记→归入 a/b/c1/c2/d 之一)"。
- 若命中安全过滤(纯敏感),直接拒写并说明,不追问(见机制 A 安全过滤)。
机制 B:主动加载协议
读取顺序
- HANDOFF.md(跨天恢复最关键的单一交接面)
- 工作区 MEMORY.md(项目级长期记忆)
- 用户级 MEMORY.md(跨项目偏好)
- 最近 1–3 天日志(临时上下文)
- 云注入(最低优先级)
冲突时以本地为准:HANDOFF / 工作区 MEMORY / 用户级 MEMORY 优先于云注入;云注入仅作参考,不静默采信。
显式校验动作(已落地,非 TODO):加载后若发现云注入内容与本地 ## 决策 / ## 参数 / ## 教训 任一区块冲突,WB 必须输出一行校验提示:⚠ 云注入[冲突内容摘要] 与本地 MEMORY ## <区块>[条目摘要] 冲突,以本地为准,既不静默采信云注入、也不双向改写本地。
加载预算
不每次全量读,防止爆上下文:
- HANDOFF.md:全量(本就精简)
- 工作区 / 用户级 MEMORY.md:读区块索引(## 标题)+ 关键词命中段落,不全文灌入
- 日志:仅最近 3 天,且只读当日摘要行
- 超预算时优先保留 HANDOFF + 决策/参数/教训区块
双模式
- 模式 A(依赖框架能力):仅当 WB 框架提供「会话启动自动 hook」时成立——会话启动先只读索引(HANDOFF 全量若存在 + 两处 MEMORY 仅 ## 标题),提示"是否加载上次项目状态";用户确认后再注入命中段落,不预先灌入全文。先用「自动 hook 验证法」判定当前版本是否支持。
- 模式 B(降级,框架不支持 hook 时的实际形态):用户说"继续 / 加载上次 / 记一下"时 Read → 同上。若验证法判定不支持,首次使用输出:"当前 WB 版本不支持自动加载,请用『加载上次』触发。"不假定自动加载已生效。
自动 hook 验证法
- 新开 WB 会话,首轮不输入"加载上次"等触发词。
- 观察 WB 是否仍自动 Read HANDOFF + 三处 MEMORY / 日志。
- 判定:
- 若首轮未说触发词即自动 Read → 模式 A 成立。
- 若必须用户说触发词才 Read → 模式 B,首次使用输出:"当前 WB 版本不支持自动加载,请用『加载上次』触发。"
路径失败降级
Read 任一文件失败(不存在 / 无权限):
- 提示用户:"<路径> 不可读,是否创建记忆骨架?"
- 用户确认 → 创建 MEMORY.md 骨架(见 references/MEMORY_SKELETON.md)后继续;
- 不静默失败,不抛错中断会话。
- 若用户级 <id> 解析失败(环境变量缺失 / 路径变化):提示用户确认用户级 MEMORY 路径,确认前不写用户级;不猜测路径。
与 WB 内置记忆指令的关系(消除冲突)
WB 内置 <memory_system> 要求:完成实质工作后自动检查并 append 当日日志(YYYY-MM-DD.md 正文)。本 Skill 硬闸写"未确认不落盘、绝不做静默自动写盘"。二者维度不同、不冲突,钉死如下:
- 被本 Skill 收编的低风险追加:当日临时日志 append(
YYYY-MM-DD.md正文)→ 对应机制 C 写入路由表「今日临时上下文」项,属低风险追加,按检查点分级默认执行 + 回显,不逐条追问。即内置自动日志与本 Skill 一致,不是例外。 - 仍须强确认的高风险动作:任何跨会话持久化区块写盘(决策 / 参数 / 偏好 / 教训 / 开放问题 / HANDOFF)、写用户级 MEMORY、删除 / 覆盖、淘汰 / 归档、创建骨架 → 仍须用户显式同意,不因"内置自动写"而静默写。
- 一句话:内置自动日志 = 本 Skill 已定义的低风险当日上下文追加;本 Skill 硬闸只管跨会话持久化写盘与删除。两者不打架。
机制 C:结构化模板(与项目级日志解耦)
本 Skill 模板仅用于 WB 本地记忆区块,不替代各项目自有的日志 / 决策记录格式(如编号体系、数据库表),各记各的。
写入路由表
| 内容类别 | 目标文件 | 区块 |
|---|---|---|
| (c1) 跨项目偏好 | 用户级 MEMORY.md | ## 偏好 |
| (c2) 项目偏好 | 工作区 MEMORY.md | ## 偏好(仅收项目级) |
| (a) 项目决策 | 工作区 MEMORY.md | ## 决策 |
| (a) 参数变更 | 工作区 MEMORY.md | ## 参数 |
| (d) 踩坑/教训 | 工作区 MEMORY.md | ## 教训 |
| (b) 跨会话阻塞上下文 | HANDOFF.md ## 阻塞(仅当前会话阻塞摘要)+ 工作区 MEMORY.md ## 开放问题(长期唯一事实源) | — |
| 今日临时上下文 | 工作区 YYYY-MM-DD.md | 正文 |
| 收工交接 | HANDOFF.md | 全文 |
(用户级路径:~/.workbuddy/user-<id>/MEMORY.md,<id> 由 WB 环境变量或已知路径解析;工作区路径:<workspace>/.workbuddy/memory/)
> 工作区 ## 偏好 仅收项目级偏好(如"本项目不用 pandas");跨项目偏好一律走用户级 (c1)。两者不混,避免孤儿区块。
> (b) 同步规则:HANDOFF.md ## 阻塞 只放当前会话阻塞摘要;长期开放问题以工作区 MEMORY.md ## 开放问题 为唯一事实源。收工 / 总结时单向同步(把仍开放的条目从工作区同步进 HANDOFF),不双向写、不在两处重复维护。
MEMORY.md 整体骨架
# MEMORY.md
> 本地事实源,云注入仅作参考。
## 决策
## 参数
## 偏好
## 教训
## 开放问题
> 区块作用域(消除孤儿):用户级 MEMORY.md 仅用 ## 偏好(c1);工作区 MEMORY.md 用 ## 决策(a) / ## 参数(a) / ## 偏好(c2,仅项目级) / ## 教训(d) / ## 开放问题(b)。每个区块均有明确写入者,无预留空白块。
机制 D:差异化淘汰策略
| 来源区块 | 内容类型 | 淘汰策略 |
|---|---|---|
| ## 决策 | 决策记录 | 永久保留;被取代时标 状态:已被 YYYY-MM-DD 取代,不删原条 |
| ## 参数 | 参数变更 | 永久保留(含 old→new 追溯链) |
| ## 偏好 | 用户偏好 | 永久保留;撤销时加 撤销:YYYY-MM-DD,不物理删 |
| ## 教训 | 踩坑记录 | 永久保留(最高价值) |
| ## 开放问题 | 未关闭问题 | 14 天未更新 → 提示;升级为决策后保留链接,状态改 已升级→## 决策 |
| 每日日志正文 | 临时上下文 | 7 天未处理 → 标记待删并提示;14 天未处理 → 再次提示用户确认删或移入 archive/。绝不自动删 |
蒸馏定义
蒸馏 = 提取精华进对应区块,非复制粘贴。
蒸馏判定(逐条询问,不自动判断)
每日日志正文是否保留,不由 WB 自动判定。执行蒸馏时逐条询问用户:"这条(<摘要>)还要保留吗?①蒸馏进区块 ②删(需你确认)③暂存"。WB 不预设"未引用"。
蒸馏触发与过期检查
- 触发:用户说"收工 / 总结 / 蒸馏"时执行。
- 过期检查:在加载时或收工时检查每日日志的 7/14 天待处理项与开放问题 14 天挂起项,提示用户处理;不依赖后台定时任务(WB 无定时能力时仅在上述两个时机检查)。
- 每日日志模板见 references/DAILY_LOG_template.md。
检查点 / 确认机制(硬闸)
本 Skill 全程以"用户确认"为前置闸,不做任何静默自动动作:
- 写入确认:每次写入后回显"已记入 <文件> ## <区块>:<摘要>"。
- 歧义确认:WB 无法分类时追问用户一次,不默认拒写也不默认记。
- 安全确认:命中纯敏感过滤整条拒写并说明,不追问;混合敏感脱敏后按四类判定(见机制 A)。
- 路径失败确认:Read 失败→提示是否创建骨架,用户确认才建。
- 淘汰确认:蒸馏/删除逐条询问,绝不自动删、绝不自动覆盖。
- 加载确认:新会话加载前提示"是否加载上次项目状态",不自动假定。
任一环节未获用户确认,Skill 不前进、不写盘。
确认强度分级(不伤硬闸)
- 默认执行 + 回显(低风险):向已有区块追加内容、加载索引 / 标题 —— 执行后仅回显,不逐条追问。
- 强确认(高风险,必须用户显式同意):删除 / 覆盖、写用户级 MEMORY、安全边界判定、创建骨架、淘汰 / 归档。
- 核心硬闸(不静默写盘、不静默删、不自动假定)始终生效;分级只放宽"低风险追加 / 索引"的追问频率,不放开否决权。
冲突 / 覆盖 / 过期规则
- 决策被新决策推翻:旧条保留,加
状态:已被 YYYY-MM-DD 取代,不删。 - 偏好撤销:加
撤销:YYYY-MM-DD,不物理删。 - 开放问题升级为决策:原条目状态改
已升级→## 决策[日期],保留链接,不直接删。 - 参数回滚:照常追加新条(old→new),追溯链完整。
多工作区隔离
用户级 <id> 由 WB 环境变量(如 WB_USER_ID)或已知路径 ~/.workbuddy/user-*/ 解析;工作区记忆仅作用于当前 <workspace>,互不串。
路线图
- 日志模板:已实现
references/DAILY_LOG_template.md(## 摘要/## 待蒸馏),供每日日志与蒸馏/加载稳定输入。 - 蒸馏辅助:已实现
scripts/distill_helper.py——扫描工作区 memory 下所有YYYY-MM-DD.md的## 待蒸馏候选并给出建议路由,纯只读、绝不自动删除,仅降低逐条判断成本;删除 / 蒸馏仍须用户确认(见机制 D)。