-- 0027 的回滚:只撤结构(删列),**不改写任何一行的数据**。 -- -- 回滚的代价(如实登记):`temporal` 这一列的值全部丢失。它对本迁移之前写入的行 -- 本来就恒为 `''`(未分型),因此丢的只是「本迁移之后提取器标出的时间性位」。 -- -- 真正需要说明的是**判定行为**:`retention_tier` / `expires_at` 是另两列,本回滚 -- **刻意不动它们**。 -- - 已被判成 temp 的行(其中一部分是 `temporal=one_off` 带来的)保持原状:读侧 -- 时效闸与后台清扫都只认 `expires_at`(纯 SQL,不依赖本列),因此回滚后它们的 -- 行为**逐字不变**,到期照旧消失、照旧被清扫; -- - 若回滚时顺手把那些行的 `expires_at` 清空,那是一次 schema 回滚**改数据**, -- 会把已经判定的临时记忆全部升回永久,同时还留在 `retention_tier='temp'` 上 -- —— 那正是「temp ⇔ 非空 expires_at」这条不变量的反面。 -- 要重判档位就重跑判定:列会以默认值 `''` 重建,历史行回到「未分型」。 -- -- SQLite 的 DROP COLUMN 要求该列不被索引/视图/触发器引用:本列没有索引(见 up), -- 因此无需先删索引(0026 的 down 因为带索引才要以 DROP INDEX 开头)。 ALTER TABLE memory_items DROP COLUMN temporal;