2 Commits
Author SHA1 Message Date
AskaEth 765ef167bd fix(memory): 复审 p2 返工 —— SQL 空串字面量、两处过期注释、人工路径档位
复审 p2-1items(tip cc6904b)要求的三处,逐条:

1) SQL 双引号改单引号(唯一返工项):
   - preinsert_store.go 的 revertMergedSQL:`merged_into = ""` → `''`。今天功能等价,
     但靠的是 SQLite「双引号标识符解析不到 ⇒ 回退成字符串字面量」的 legacy 行为;
     这是一条**改数据**的语句,还被 RevertMerged 与整理侧回滚共用,不该依赖回退。
   - retention_migration_test.go 的 `WHERE retention_tier = ""` 一并统一成 `''`,
     并在原位留下「为什么」。
2) 两处过期注释:
   - retention_schema.go:「反过来(先自举、后迁移)也成立」是**假结论**,改为
     「生产顺序成立;反向顺序在 0019 处即失败(duplicate column name: status,既有问题)」。
   - store.go 的 ExpiresAt:「本字段目前只写不读」已半过期(Add 现在会把最终落库
     时刻回填到返回值),改成「读回语义是半开的」:Add 返回的条目有值,从库里读回的
     恒为零值。
3) 人工路径(塔裁定「人工动作默认应为 long」):包内的 `RememberManual`(「记住 X」)
   显式钉 `RetentionTier = long`,留存规则因此不许把人工明确要求记住的东西降成临时层
   (extract_test.go 加断言)。面板网关那条(adminAddMemory 直调 Add、不传档位)
   按塔的口径不在本片、留给后续切片 —— 本片对它的唯一影响见回报。

不动(按塔的裁定):preinsert.go 514 行(dev 既有 tech debt)、
design/03 §10.5 与 design/23 §18 的章节(塔的账)、gateway 人工路径。

回归:go build ./... + go vet ./... + go test -count=1 ./internal/runtime/memory/... ./internal/db/...
全绿,内存包 -race 亦绿。
2026-10-26 13:24:35 +08:00
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