记忆 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 一处。