Repository navigation
Open
Labels
Description
背景:两套现行模式各有一个实测缺口
现行 conflict 相位的两种模式(#126 六分支、#166 冻结人审、#170 跨 scope 保护)各有实证缺口:
- 自动裁决(默认):E13b 投毒实验实测 P(毒胜出)=86.8%(自信框架话术即可操纵判官),且
applyConflict的 supersededSuffix——胜者正文追加败者前 100 字(src/dream/decisions.js)——构成值级泄漏通道,端到端 ASR 反升 15.5pp(数据见 persistbench-sycophancy 公开仓 E13 三阶段)。 - 冻结人审(
conflictFreezeEnabled):对作者本地长期运行库 788 对已裁决矛盾的全量分类:
| 类别 | 占比 | 本质 |
|---|---|---|
| 近重复(reason 为相似度回声) | 46% | 该走 merge 的去重工作,被窄 prompt(conflict/keep 二选一)逼成输赢裁决 |
| 跨作用域重复 | 20% | 同一内容落两个归属,机械去重 |
| 真矛盾 | ~27% | 真正需要消解的残余 |
| 时序演进 | 5% | 新者胜即可 |
三个关键结构事实:
- 两侧 created_at 差 <1 天的占 76%——是同日双录,不是「旧事实 vs 新事实」,纯时序规则对大多数对无区分力;
- 17.5 万条召回审计中仅 8% 的对曾两侧同场——92% 的人审花费在从未一起进入上下文的对上;
- 人审量 ≈30 条/天且仍在加速;而人审界面([面板] 冲突裁决窗看不到全文、无判读依据:用户只能整对删除或乱选 #400)恰好看不见最能消解矛盾的字段:created_at、scope、epistemic、来源(
candidateConflicts只给 id/type/title/content + 相似度)。
提案:确定性分诊 + 矛盾账本 + 惰性消解(零人工)
原则:存储层不再由 LLM 决定胜者(降级为分类器);零归档、零正文改写;确定性规则先行(R0/R1 记账先走,与 candidates 分档哲学同构);消解推迟到有信息的时刻。
1. 分诊四档(conflict 相位前置)
| 档 | 判据(确定性优先) | 处置 |
|---|---|---|
| T1 近重复 | 同 type + sim≥阈值(宁宽勿严)+ created_at 差 <24h + 内容高重叠 | 改送 merge 相位(复用现行自动合并路径) |
| T2 跨作用域重复 | 跨 scope + 内容高重叠 | 去重账本(照 differentiated_pairs 的 bookkeeping 惯例,正文零改动);检索侧他 scope 本就降权 |
| T3 时序演进 | created_at 差大 + 同实体同谓词 + 变更语信号 | 取代链:旧行写 superseded_by(双时间戳列),检索降权,不归档 |
| T4 真矛盾 | 规则不可判定 → LLM 只分类(输出 contradict 标注 + 影响面),不选胜者 | 矛盾账本:两条都活、互标 conflicts_with |
LLM 冲突相位保留但降级:候选输入补齐 created_at / scope / epistemic / 来源列;输出只影响账本元数据,不影响任何记忆行的存废。
2. 矛盾账本(新表 conflict_ledger)
每对 T4 一行(两侧 id、检出 run_id、分类理由、similarity、状态 open / superseded / differentiated / zombied)。幂等迁移;照 conflict_reviewed 惯例只记账、不触发 write hooks。
3. 惰性消解四时刻(零人工)
- 检索时:fuseRecall 矛盾感知——账本对两侧同召时组内按确定性序排位:epistemic 信任级优先(observation > inferred > subjective,复用
EPISTEMIC_PRIORITY;isImportedRow外来行恒垫底)→ 服务器时钟 created_at 新者 → 仍平手则两条都注入 + 一行机械标注(「以下两条互相矛盾,检出 YYYY-MM-DD」),把消解交给会话上下文(条件化呈现); - 会话里:用户自然纠正 → 蒸馏铸新行 → 下一轮巩固六分支正常走 supersede/merge → 账本对自动关闭(resolved-by-mint,回执可查);
- 巩固时:挂账超 N 天且同召过的对,进低频「证据重蒸馏」队列(
memory_mintsprovenance 回链源窗口,错峰基建已有);产出仍是元数据,不是归档; - 时间本身:同召率 0 且挂账超 M 天 → 转 zombied;两侧照常参与 heat,无任何内容处置。
4. 安全兜底
- 排序键只用服务器单调时钟(记忆内容声称的时间绝不做主排序键——防伪新鲜度)+ epistemic 信任级 +
isImportedRow恒败:投毒要生效必须驱动一条真实写入,攻击面从「LLM 读话术」收窄到「写入准入」(与 [Feature] 写入准入(non-write 判定):把「这条该不该进库」前移到 LLM 之前 #254 串联)。 - 账本候选进 **preInjectGate(preInjectGate 注入前判定:意见/立场记忆先判定后处置(#380,opt-in 默认关) #382)**判定输入;标注注入是良性矛盾的默认路径,毒候选由门控拦截。
- 账本模式下 supersededSuffix 永不执行——E13b 泄漏根因消除而非防守。
5. 外部依据
- 确定性规则 > LLM 裁决:MemoryAgentBench-FC 确定性配方 78–94.8 vs Zep 7.0 / Mem0 18 / HippoRAG2 54;同池换掉 LLM 判断 +10.8pp(p<0.001)。
- 失效不删(non-lossy)是 Zep / Mem0^g / MemOS 共识;覆写派代价已被 MemConflict 实证(六系统平均 AA <0.56,静态假话最难)。
- 版本 + 时间元数据是把消解推迟到使用时刻的前提(Zep 时间窗、StateMem 取代链 +15~32 分、Hindsight 观察层同构);StateMemBench C1「supersede 后不引旧值」可作验收靶。
- 两个必须吸收的警告:纯新鲜度规则让静态假话靠伪造新鲜度赢(→ 信任级必要);词法检测对不可判定冲突 recall 仅 0.181(TANGLE)→「不可判定 → 条件化呈现」是必要组件而非可选。
配置面(新改动自查清单映射)
- 新键
conflictLedgerEnabled:opt-in 默认关;config.jsschema 与settings.js白名单成对;test/api.test.js旗标计数锁 +1; - 与
conflictFreezeEnabled互斥(config 校验抛错); conflict_pending保留(历史审计);面板冲突队列 UI 骨架复用为账本只读视图(去裁决按钮);- [Feature Request] scope 标注缺人工入口与提升回路:自动载体标签不该直接吃硬过滤效力 #170 跨 scope 保护在账本模式自然退役(无归档即无越权归档),
isCrossScopeDecision保留给非账本路径。
实验方案(beta)
- 三臂对照:确定性配方 vs LLM 裁决(现行 auto)vs 冻结(现行 freeze);
- 验收靶:StateMemBench C1 + MemConflict 本地复刻(动态/静态/条件三分类,判 P(毒胜出) 与 CRS)+ E13b 毒框架复跑(persistbench harness);
- 判据预注册(<5pp 噪声尺惯例):动态冲突 P(旧值引用) ≤ 冻结臂;静态假话不劣于冻结臂;token 成本 ≤ 冻结臂(LLM 只分类不产出合并文本);
- 灰度:先 shadow 模式(只记账、不影响检索排序)跑一周,验证分诊分布是否复现 46/20/5/27,再切 enforce。
关联与开放问题
- [audit] 冲突自动裁决档(conflictAutoResolveEnabled)开启前的三条硬边界:阈值数字过期、freeze 父子绑定、NULL scope 被判为同 scope #616(自动裁决档三条硬边界):若立项,T1-T3 即其「机械兜底清单」的展开;NULL scope 被判同 scope 的边界在账本模式下不再影响存废;
- sleep [feature]:冲突候选池建议接入 entity_attrs 属性失效与实体废弃信号,解决跨主题记忆局部过时漏判 #585:entity_attrs 属性失效/实体废弃信号可并入 T3 判据;
- 已知边界:LongMemEval 显示确定性配方在 knowledge-update 场景不赢基线——新鲜度规则只覆盖动态冲突,静态假话依赖蒸馏质量门(E13a 证明蒸馏无过滤效应),beta 实验列为观察项;
- 顺带发现的小修:
resolveConflictPending的 JSDoc 写「a = 冻结时 LLM 的建议胜者」,但saveConflictPending存入时按 uuid 排序,注释与现实不符; - 关联:sleep 冲突阶段建议支持 merge/update(当前只有 conflict/keep,互补型重复被当作"输赢"处理) #126 feat(conflicts): 冲突待确认的集中处理——队列 API + 状态页人工确认视图 #166 [Feature Request] scope 标注缺人工入口与提升回路:自动载体标签不该直接吃硬过滤效力 #170 [面板] 冲突裁决窗看不到全文、无判读依据:用户只能整对删除或乱选 #400 [bug] sleep 冲突阶段的输入侧没有任何预算:全部候选对一次塞进一个 prompt、判 keep 不留痕,单请求实测 163,054 token(整池 163,840),失败后按冷却重排同一输入 #529 [bug] sleepActionSet="full" 下 differentiate 形成正反馈死循环:双侧追加相同注记拉高余弦相似度 + 字面 includes 幂等失效,实测单条堆叠 19 段「差异注记」 #533 sleep [feature]:冲突候选池建议接入 entity_attrs 属性失效与实体废弃信号,解决跨主题记忆局部过时漏判 #585 [bug] 冲突冻结队列一次灌满 60 条:freeze 分支绕过三个上限,且面板静默截断到 50 #603
完整设计文档与数据挖掘脚本随实现 PR 附上。
Activity
modusensus commentedon Nov 10, 2026
与 #616 自动裁决档的关系修正 + #585 并入(规格补全)
补全两处关系,避免规格与 main 现状错位。
1.
conflictAutoResolveEnabled已存在(默认关),本设计是它的展开而非竞争main 上(#614 / 6b7c497)自动裁决档已落:freeze 分支内嵌 autoPool——同 scope + sim ≥
conflictAutoResolveMinSimilarity(默认 0.95)的对自动 supersede,留信息量更大的一条(非更新者;实测新条更短占 55-57%),三级兜底(长度 → updated_at → id)保证重放确定,赢家正文一字不动,可追溯性留在被归档侧(#126 原设计,避开了 conflict 动作的正文追加泄漏)。对应关系:
autoResolved/autoFailed透出 → 并入规格可观测性一节;isCrossScopePairNULL 修复 → 非账本路径仍需;conflict_reviewed补 winner 列 → 账本模式下 T4 不再产生 winner,由 ledger 表承载(非账本路径不阻塞)。2. #585 并入 T3 作为主判据
entity_attrs已有invalidateOldAttr落下的失效关系(同实体同属性 old_memory_id ↔ new_memory_id、值不同),正是 T3 需要的属性级取代信号,比内容启发式强,且能抓「跨主题局部过时」(整段向量 0.45–0.60 进不了findPotentialConflicts的盲区)。并入方式:T3 候选池 = 时序+内容启发式 ∪ entity_attrs 失效对 ∪ 实体废弃关联对;#529/#533 账本 +sleepConflictMaxPairs预算照旧兜成本。依赖说明:
entity_attrs在entityExtractionEnabled(默认关)之后才有数据——未开抽取的库 T3 退化为纯内容启发式,规格不改判据优先级。modusensus commentedon Nov 10, 2026
digest 补全:三个影响实现的增量
#166→#616 的完整时间线已挖完(digest 留作者本地研究工作区),三个增量事实影响 beta 实现:
conflictAutoResolveEnabled今天开了也是「假成功」。上一条评论说的 0.85–0.95 空带由此有更硬的口径:T1(merge 相位路由)不只是补空带,是这条空带里唯一会实际接住对的路。顺带入档为 beta 非目标:#170 尾巴(memory_update 可放宽归属、仅 actor=tool 审计)、#605(双写者重复跑)、#557(dream_runs 无界增长——
conflict_ledger建表时预留保留期键位考虑,避免重蹈)。feat(dream): 冲突分诊账本 enforce 档——确定性处置接线(#641 beta 第二阶段)
feat(dream): T3 取代链——旧行 superseded_by 指向新行,检索降权不归档(#641 beta 第三阶段)
Merge pull request #643 from slow-stack/feat/641-conflict-ledger
Merge pull request #644 from slow-stack/feat/641-conflict-enforce
feat(recall): 被取代行的检索降权——fuseRecall 感知取代链(#641 beta 第三阶段续)
feat(inject): T4 矛盾感知——取代行不进注入、矛盾对同批排位与互相标注(#641 beta 第三阶段续)
feat(panel): 矛盾账本只读页 + conflictLedgerMode 面板座位(#641 beta 第三阶段收官)
feat(dream): 冲突分诊账本 enforce 档——确定性处置接线(#641 beta 第二阶段)
feat(dream): T3 取代链——旧行 superseded_by 指向新行,检索降权不归档(#641 beta 第三阶段)
1 remaining item
feat(inject): T4 矛盾感知——取代行不进注入、矛盾对同批排位与互相标注(#641 beta 第三阶段续)
feat(panel): 矛盾账本只读页 + conflictLedgerMode 面板座位(#641 beta 第三阶段收官)
feat(dream): 冲突分诊账本 enforce 档——确定性处置接线(#641 beta 第二阶段)
feat(dream): T3 取代链——旧行 superseded_by 指向新行,检索降权不归档(#641 beta 第三阶段)
feat(recall): 被取代行的检索降权——fuseRecall 感知取代链(#641 beta 第三阶段续)
feat(inject): T4 矛盾感知——取代行不进注入、矛盾对同批排位与互相标注(#641 beta 第三阶段续)
feat(panel): 矛盾账本只读页 + conflictLedgerMode 面板座位(#641 beta 第三阶段收官)
feat(dream): 冲突分诊账本 enforce 档——确定性处置接线(#641 beta 第二阶段)
feat(dream): T3 取代链——旧行 superseded_by 指向新行,检索降权不归档(#641 beta 第三阶段)
feat(recall): 被取代行的检索降权——fuseRecall 感知取代链(#641 beta 第三阶段续)
feat(inject): T4 矛盾感知——取代行不进注入、矛盾对同批排位与互相标注(#641 beta 第三阶段续)
feat(panel): 矛盾账本只读页 + conflictLedgerMode 面板座位(#641 beta 第三阶段收官)
Merge pull request #650 from slow-stack/feat/641-conflict-enforce
feat(memory): 单次场合情绪进注入,图像描述档不再整档静默