Files
Cyrene_v2/internal/db/migrations/0026_memory_retention_tier.down.sql
T
AskaEth cc6904b1b4 feat(memory): retention_tier 档位列 + defer 与档位合并为同一判定(M37)
主人 2026-10-26 对「记忆分型」裁定「两列」:kind(关于什么)保留,新增
retention_tier(留多久 / 干什么用)。本片把这条轴从列、判定、写入、读侧过滤
一路打通,并把「判第五态 defer」与「判 retention_tier=temp」合并成一个判定。

结构(迁移 0026 + 自举前滚):
- memory_items 新增 retention_tier TEXT NOT NULL DEFAULT ''(空串 = 尚未分型,
  历史行与受限来源行),索引 idx_memory_items_retention_tier;up/down 均实跑过
  (在隔离的生产库副本上 migrate → 建 Store → down → 再 up,5073 行零丢失)。
- NewStore 幂等前滚该列 + 建索引(ensureRetentionSchema),与迁移同形由测试钉住。

判定(retention.go,全仓唯一入口):
- RetentionTier 闭集 temp/daily/work/long/knowledge + 空串未分型;与 kind 正交。
- resolveRetention 的优先级:调用方显式档位 > 显式有效期(⇒ temp)> 受限来源
  不分型 > 留存规则 N1~N7 ⇒ temp > 默认 long。判据靠元数据,规则不许推翻显式档位。
- tempDeadline 是「档位 → expires_at」的唯一换算:temp ⇔ 有效期非空,两列同一笔
  INSERT 落下(M2 登记过的「INSERT 与补写之间的短窗口」就此关闭)。

合并(defer ⇔ temp):
- judgeIngest 不再跑留存规则,只读 Add 落定的 item.RetentionTier;规则调用点因此
  全仓唯一(源码级断言钉住)。
- 判定不再依赖同步闸是否开启:闸未接/关着时档位与有效期照样落库。
- 异步层对已是 temp 的行不重复改写(避免 TTL 随审查延迟漂移)。
- IngestRuleVersion d3.3 → d3.4(判据作用范围变了,按既有硬规矩升版)。

读侧:
- 四条列表读路径的 SELECT 与 scanItem 读出 retention_tier(14 列);Get 同样读回。
- 新增 ListByPersonaTiers / ListScopeTiers / ListTiers / ListProjectTiers(可选档位
  过滤,缺省不过滤 ⇒ 历史行照常返回;显式传空串只取未分型;非法档位报错)。
  原方法签名逐字不变 —— 网关 MemoryStore 接口钉着它们,可变参数会编译不过。
- store.go 的读路径拆到 store_list.go,守 500 行上限。

回归:go build ./... + go vet ./... + go test ./... 全绿(内存包另有 -race)。
2026-10-26 13:09:30 +08:00

18 lines
1.2 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 0026 的回滚:先删索引、再删列(与 0019 同一顺序口径 —— SQLite 拒绝 DROP COLUMN
-- 删除一个仍被索引引用的列)。
--
-- 回滚的代价(如实登记):`retention_tier` 这一列的值**全部丢失**。它对本迁移之前
-- 写入的行本来就恒为 `''`(未分型),因此丢的只是「本迁移之后被判出来的档位」。
-- 真正不可逆的只有一条:**判成 temp 的行不会被自动改回长期层** —— 它们的
-- `expires_at` 是另一列(0019 就存在),本回滚**刻意不动它**:
--
-- - 若回滚时顺手清空 `expires_at`,一次 schema 回滚就会把已经判定的临时记忆
-- 全部升回永久(那是改数据,不是回滚结构);
-- - 若不清空,回滚后这些行仍是「有时效的行」,读侧时效闸(纯 SQL,不依赖本列)
-- 照旧隐藏它们,后台清扫照旧删除它们 —— 即**行为不变**。
--
-- 因此本回滚只撤结构、绝不改写任何一行的时效数据;要重判档位,重跑判定即可
-- (`retention_tier` 列会以默认值 `''` 重建,历史行回到「未分型」)。
DROP INDEX IF EXISTS idx_memory_items_retention_tier;
ALTER TABLE memory_items DROP COLUMN retention_tier;