2 Commits
Author SHA1 Message Date
AskaEth 44c25eb03b refactor(memory): 到期清扫挂点从 wait 注入缝改为 TidyService.Start
塔裁定:清扫不许挂在注入缝上 —— 包一层 s.wait 会让「清扫是否存活」依赖于
「loop 每一轮都调 s.wait」这个**没有任何契约固定**的假设;将来谁换了等待原语、
或把循环改成 select + 自己的 timer,清扫会**静默消失**(不报错、不红测试,
只是临时期限再也删不掉)。后台件起在 Start 里,读者一眼看到它们同生共死。

- tidy_service.go:Start 里紧跟 go s.loop(cctx) 起 go s.expirySweepLoop(cctx),
  wg 计数与既有那一笔同处(同一把锁内加,避免 Add 与 Stop 的 wg.Wait 相撞)。
  `if !s.cfg.Enabled { … return }` 仍在其前 ⇒ 语义与改动前逐字相同:整理被关掉
  ⇒ 清扫不跑(与 preinsert_gc 随审查服务启停同口径)。
- expire_loop.go:删掉 AttachExpirySweep 与对 s.wait 的包裹;文件头写明
  「挂点必须是 Start 里那处显式的 go」,防止后人改回注入缝。
- expire_loop_test.go:那条运行时对照改写成 TestTidyServiceStart_清扫随服务起停
  —— 真 Start、真 Stop(Stop 不超时即证明清扫随 ctx 退出且登记在同一个 wg)。
- wire_memory_tidy.go:去掉组合根的挂载调用,注释改成「起在 Start 里,组合根零接线」。
- wire_memory_tidy_test.go:把 go s.expirySweepLoop(cctx) 钉进 TestMemoryTidyIsWired
  的 seams(摘掉那一行 ⇒ 用例红,已实测)。
2026-10-13 21:43:27 +08:00
AskaEth a017ab6cf8 feat(memory): 临时记忆到期物理删除(有界清扫 + 同步清向量 + 删前审计)
design/23 §19 的第 ② / ③ 步:读侧时效闸(M1)只负责「看不见」,本切片负责
「真删掉」。三条护栏照 §19.3:删除是本包内唯一 DELETE 出口、有界(500 行/批 ×
20 批)、删前留审计。

- internal/runtime/memory/expire.go:扫描集合写死为「expires_at ≠ '' ∧
  expires_at ≤ now ∧ status='active' ∧ 来源非受限」。空 expires_at(长期/日常
  记忆,含 M2 登记的「INSERT 与补写之间中断」窗口)结构性进不了集合;受限来源
  复用 nonOwnerSource(与整理/审查同一处判据)。键集游标 (expires_at, rowid)
  保证被跳过的行只读一次、扫描位置一定前移。审计串 = id + persona_id + scope +
  expires_at + 按 rune 截断(48)的摘要 —— 本仓唯一一处允许携带内容片段的审计。
- internal/runtime/memory/expire_loop.go:清扫循环挂在 TidyService 的生命周期上
  (AttachExpirySweep 由组合根调用),随心跳 ctx 跑、随 Stop 停;一轮只写一行
  汇总日志,逐条的那一行进审计。
- internal/runtime/memory/vector/delete.go:新增可选删除能力 vector.Deleter +
  两个后端实现,删行时同步清向量(M1 reviewer 的 finding:过期向量占 top-K 预算)。
- cmd/cyrene/wire_memory_tidy.go:挂上清扫;顺带把已过时的「这十键」改成「这十一
  键」(M2 加了第十一键 tempTtlSec)。
2026-10-13 21:43:27 +08:00