记忆 accessed_at 归一化
wesgine 的 accessed_at 下界归一化设计——消除零值语义陷阱。
问题根源
accessed_at 列定义为 NOT NULL DEFAULT 0。
"从未被召回"的条目时间戳是 1970-01-01——比行本身早 55 年。
为什么零值是最坏的值
accessed_at 决定了什么被记住:
| 读者 | 零值的影响 |
|---|---|
GC retentionScore | 衰减到 ~0,优先被淘汰 |
| hybrid ranker | 排序压到底部 |
| Digest | 判定为 stale |
ORDER BY accessed_at DESC | 排到末尾 |
零值不是中性状态——它是该字段最坏的取值,且落在最新写入的行上。
曾经的六份补偿
六个读者各自带一份 if AccessedAt.IsZero() { use CreatedAt }。
第七个读者(context_index.go 的 ORDER BY)没带:同一行在五处读作创建时间、在一处读作 epoch,不报错。
治法:归一一处
saveCore 落盘前将 accessed_at 抬平到 created_at。
ddlMemoriesV10 幂等修复存量数据。
六份读者补偿代码删除——归一后不再需要。
第二排序键
ORDER BY accessed_at DESC, created_at DESC, id
created_at 不是整洁性 tiebreaker:List 在排序后切 Offset/Limit,并列时不确定的顺序移动的是页边界。
INV-MEM-51
accessed_at 的下界是 created_at,归一只在 saveCore 一处。