记忆层模型(INV-MEM-49)
wesgine 的记忆系统使用七值闭域层模型组织所有记忆条目。层是引擎的封闭域,消费方(前端/产品)不推导也不裁剪。
七层闭域
AllMemoryLayers() = [
"environment", // L1 环境信息
"consensus", // L2 部门共识
"about_me", // L3 关于我
"agent_memory", // L4 角色记忆
"session", // 会话记忆
"working", // 工作缓存
"unknown", // 未识别
]
L1 环境信息(environment)
- 来源:宿主环境感知器自动产出
- 可写性:❌ 不可人工写入
- Actor 归属:无(Cell 级共享)
- 典型内容:操作系统版本、安装的工具链、语言运行时版本
L2 部门共识(consensus)
- 来源:admin 写入
- 可写性:✅ 需要 admin 权限
- Actor 归属:无(Cell 级共享)
- 典型内容:团队编码规范、项目约定、部门策略
L3 关于我(about_me)
- 来源:用户交互产出
- 可写性:✅ 可写
- Actor 归属:✅ 按 Actor 隔离
- 典型内容:个人偏好、习惯、配置喜好
L4 角色记忆(agent_memory)
- 来源:Agent 交互产出
- 可写性:✅ 可写
- Actor 归属:✅ 按 Actor 隔离
- 典型内容:Agent 学到的用户偏好、纠正记录、技能使用经验
会话记忆(session)
- 来源:运行时自动产出
- 可写性:❌ 不可人工写入
- 特点:绑定特定 SessionID,跨会话不可见
工作缓存(working)
- 来源:运行时自动产出
- 可写性:❌ 不可人工写入
- 特点:临时工作数据
未识别(unknown)
- 来源:引擎兜底
- 说明:未覆盖的 scope 落
unknown,而不是塞进某个真实层
层判定单点 LayerOf(INV-MEM-49)
此前五个消费方各自从 scope + metadata 推导层,只有 Teleclaw 判对——其余都把 consensus 和 about_me 合并(两者共用 ScopeGlobal)。
现在收敛成 memory.LayerOf(e) 单点:
func LayerOf(e MemoryEntry) MemoryLayer {
// 基于 scope, namespace, actor 综合判断
// 返回七值之一,不猜测
}
DTO 下发 layer 字段,消费方一律消费不推导。
层谓词 LayerClauses
LayerOf 答「这一行是哪层」,LayerClauses(layer) 答「哪些行是这层」。
两者必须由同一份定义生成——前者是读方向,后者是 SQL 下推方向。
Layer 与 Scope 互斥
Layer 与 Scope 同时给出返回 ErrMemoryLayerScopeConflict(400),不做交集。
三个动词按层提问(INV-MEM-53)
写入:SaveToLayer
POST /cells/{id}/memory { layer: "about_me", content: "..." }
LayerTarget(layer) 一张表答三件事:落哪个 scope / 要不要 actor / namespace 谁给。
错误码:
| 错误 | 含义 |
|---|---|
ErrLayerNotWritable | environment / session / working 不可人工写入 |
ErrUnknownLayer | 层名不存在 |
ErrLayerShared | consensus 带了 actor(共享层不能私有化) |
ErrLayerNamespaceRequired | agent_memory 没给 namespace |
清空:ClearLayer
DELETE /cells/{id}/memory/layer?layer=about_me&actor=alice
收结构体 ClearLayerRequest,不收三个位置参数(避免 (layer, actor, ns) 与 (layer, ns, actor) 混淆)。
计数:CountByLayer
GET /cells/{id}/memory/counts?actor=alice
返回 Record<MemoryLayer, number>,键覆盖全部层含 0。
可写层
只有三个层可以人工写入:
consensus(需 admin)about_meagent_memory
对应 wesui 的 WRITABLE_MEMORY_LAYERS。
耐久性由 Kind 决定(INV-MEM-54)
跨会话可见性由 Kind 的 kindDurability 判定——不是 Formation。
Formation 是溯源(哪个机制铸出这行),耐久性是寿命。两者真的不一致:
- "别用 tabs" 出自一次纠正事件(episodic 溯源)却永久有效
- Plan 是用户亲手写的(declarative 溯源)却在产出它的任务外毫无意义
Kind 必填
// 空 kind → ErrKindRequired
saveCore(entry) // entry.Kind 不能为空
Episodic Kind 必须带 SessionID
// episodic 缺 SessionID → ErrSessionRequired
// 否则 201 比 400 坏——写成功但永不召回
Actor 提列(INV-MEM-48)
actor 从 Metadata["actor"] JSON 键提升为 wes_memories.actor 独立列。
影响:
- SQL 能做等值判定(不再是
LIKE子串预筛) UserNS归一 /ActorScopedKey转义 /MigrationRules全删- 无兼容读路径(DEV-1 清库)
各产品场景
| 产品 | 特点 |
|---|---|
| wescode | 1 workspace = 1 Cell,actor 恒为 "local";L2/L3 同人但分开渲染 |
| wesclaw | 个人助手 N=1,L2 恒空(无 admin 写入) |
| wescraft | 团队版多 actor,四层同时非空 |
| 企业版 | 部门 Cell 多员工,L2 有部门共识,L3/L4 按员工隔离 |
前端约束
- 七层芯片恒定渲染,计数 0 也画
- 分组列表只画非空层(空组
continue) - 禁词:
scope/MemoryScope/owner/metadata.actor/ namespace 原文 - 层 → 用户词由 wesui
useLayerLabels()单点持有