记忆 Actor 字段提列
wesgine 的记忆系统将 actor 从 Metadata JSON 键提升为 wes_memories 表的独立列,从根本上解决了归属判定的一致性问题。
问题背景
在提列之前,Actor 归属信息编码在三个不同的地方:
| 位置 | 用途 | 问题 |
|---|---|---|
Metadata["actor"] JSON 子串 | 归属判定 | SQL 只能 LIKE 预筛,不是精确判定 |
UserNS(actor) 命名空间前缀 | 命名空间寻址 | 前缀编码需要额外归一化 |
AgentScopedKey dedup 键 | 去重 | 与前两者各有各的归一规则 |
核心缺陷:"actor":" bob " 两边的空格在 SQL 的 LIKE 和 Go 的 TrimSpace 下给出相反答案——行被挡在 LIMIT 之外且没有任何错误。
提列设计(INV-MEM-48)
变更
wes_memories新增actor独立列(ddlMemoriesV10)- SQL 从"预算"升格为"判定"——等值匹配代替
LIKE UserNS归一化、AgentScopedKey转义、迁移规则全部删除- 不留兼容读路径
收益
| 之前 | 之后 |
|---|---|
SQL LIKE "%actor%" 预筛 + Go 补偿 | SQL actor = ? 精确判定 |
6 处各自补偿 if AccessedAt.IsZero() | 归一一处(saveCore) |
UserNS(actor) 前缀编码 | actor 是独立列 |
迁移 SQL 铸出非 UserNS 行 | 无迁移副作用 |
判据收敛
提列后,Actor 归属只有两个判定点:
| 面 | 单点 | 职责 |
|---|---|---|
| 读 | memory.ActorVisible(entry, actor) | 判定一个条目对某 actor 是否可见 |
| 写 | saveCore 内的 RequireActor | 确保每条私有域写入都带 actor |
所有调用方(删除、Digest、GC、HTTP handler)都通过这两个单点。
归属可见性规则
func ActorVisible(entry MemoryEntry, actor string) bool {
// 共享域(ScopeSystem, ScopeGlobal 无 actor)→ 所有人可见
// 私有域 → actor 必须匹配
// 空 actor 查询 → 管理视图(全 Cell)
}
关键:空 actor 是合法值(admin 管理视图),漏传 actor 不报错而是返回更多数据。
同批删除的死接线
提列时同批清理了以下不再需要的代码:
CellNS()— Cell 级命名空间(Cell 已是物理隔离域)MigrationRules/migrateScope— 零写入方却会批量铸出带 actor 的非UserNS行ListConventions的 global 半边 — 惯例只在 Agent 域内有意义
相关文档
- 记忆 Actor 边界 →
memory-actor-boundary.md - 记忆层模型总览 →
memory-layer-overview.md - 记忆写入管道 →
memory-save-pipeline.md - 记忆
accessed_at归一 →memory-accessed-at-details.md