feat(memory): 记忆整理**应用路径 + 调度修复 + 手动真跑**(TIDY-1,主人投诉的根因)
主人实测:memory_items 1191 行、候选 77 条全 pending、memory_tidy_runs 仅 1 行、两晚定时没跑。 根因两条(都在这片里修掉): ① **以前根本没有执行面** —— 只有只读试算,候选永远 pending ② **调度被重启饿死** —— interval=24h 的 ticker 从进程启动算起,两天重启十几次 ⇒ 24h 永远走不完 - 应用路径:逐条 / 按 run 批量(默认 100、硬顶 500、超限 truncated)/ revert;**软合并** (status + merged_into/merged_from/merge_count,**绝不改 content、行不删**)+ 审计 (memory.tidy.apply / memory.tidy.revert)+ **幂等**(候选状态条件更新 + 行 status 闸两道) - 调度:改成**到点即跑**(catchUp:无历史+窗口内 / 距上次 run ≥ interval / 窗口起点晚于上次 run), 「上次 run」以 memory_tidy_runs 为**持久事实**;注入时钟用例证明**重启不饿死** - 手动真跑端点 POST /admin/memories/tidy/run(同档鉴权 + 审计 + 回执:新增/合并/软删/耗时) - 候选表加 run_id 列 + 索引(前滚;顺序=建表→补列→建索引,否则既有库会 no such column) - 3 个变异自检(删 catchUp / 去掉两道 status 闸 / truncated 恒 false) ⚠️ 生产库零动作:1191 行真跑与 77 条候选应用**未执行**(按红线由主人确认后主会话执行) ⚠️ 契约段在报告里(candidates 列表/apply/revert/tidy.run),Docs/ 待登记
This commit is contained in:
1 parent
57d0e8c543
commit
454ddb0b70
18 files changed
+3181
-71
No files matched your search
@@ -39,14 +39,17 @@ type TidyEvidence struct {
|
||||
|
||||
// TidyCandidate 是一条整理建议(落库形状,design/23 §10)。
|
||||
type TidyCandidate struct {
|
||||
ID string
|
||||
PersonaID string
|
||||
Scope Scope
|
||||
ProjectID string
|
||||
Kind Kind
|
||||
Action TidyAction
|
||||
SourceIDs []string
|
||||
TargetID string
|
||||
ID string
|
||||
PersonaID string
|
||||
Scope Scope
|
||||
ProjectID string
|
||||
Kind Kind
|
||||
Action TidyAction
|
||||
SourceIDs []string
|
||||
TargetID string
|
||||
// RunID 是产出这条候选的那一轮整理(切片 TIDY-1 补的列:批量应用的抓手)。
|
||||
// 幂等跳过的候选保留**首次**产它的那一轮,不被后来的轮次改写。
|
||||
RunID string
|
||||
ProposedContent string
|
||||
MergedContent string
|
||||
Reason string
|
||||
@@ -151,6 +154,11 @@ func buildCandidates(pr tidyPair, v tidyVerdict, now time.Time) []TidyCandidate
|
||||
re.MergedContent = ""
|
||||
re.Reason = "kind_mismatch"
|
||||
re.Evidence.ProposedKind = string(target.Kind)
|
||||
// KindA 在 reclassify 候选上**重新定义**为「被改那一行当前的 kind」:
|
||||
// merge 候选的 KindA/KindB 是一对各自的 kind(供 diff 预览),而
|
||||
// reclassify 候选只有一个主体(absorbed),回滚必须知道它原来的 kind,
|
||||
// 否则 revert 会拿另一条行的 kind 去覆盖(design/23 §8 的可逆口径)。
|
||||
re.Evidence.KindA = string(absorbed.Kind)
|
||||
out = append(out, re)
|
||||
}
|
||||
return out
|
||||
|
||||
Reference in new issue
Block a user