Skip to content

v0.13.0 — 恢复闭环、压力闸门与补丁重打

Choose a tag to compare

@DreamRift DreamRift released this 19 Oct 01:52
· 1 commit to main since this release

0.13.0 — 2026-10-18

这一版先修数据不可恢复,再修降温净亏:前者是「原文一定回得来」这条产品承诺的直接违背,
后者是「低占用时降温省下的是最便宜的缓存读、付出的是最贵的未命中输入」。同一版里做面板瘦身。

恢复闭环(P0,修复前 230 条归档里 221 条不可恢复)

  • 归档回执退出折叠:isCardNode() 曾把以 [已归档操作·v2] 开头的归档回执也判成工作卡。折叠把整组回执换成一条只留 seq: 的折叠回执,而 restoreReceipts() 按 replacementSeq 找节点——找不到就逐条 skipped: 回执节点已不在活动面。回执是 restore 的唯一句柄,折掉它等于删掉「原文可恢复」的承诺。现在折叠只治理工作状态卡;归档回执与回注包同为断组边界。
  • 第二通道(冷库重建):回执节点已不在活动面时不再直接判不可恢复——按 nodeId 读冷库、核对 archiveMac(body) === row.hash,通过则在活动面重建原文(rebuilt: true)。hash 不符仍然失败关闭,绝不把来历不明的正文塞回上下文。
  • 恢复对账不变量:restored + skipped + forgotten 必须等于输入行数,不等即告警。这是 221/230 事件静默发生的直接原因——没有对账,少恢复的那些既没回来、也没被报出来。

压力闸门(P0,替代「无压力也降温」)

  • 新判据 src/v2/pressure.mjs:占用率(assembledTokens / contextWindow)达到阈值才自动降温;0 = 无压力也降温(旧行为,保留为显式选择)。实测会话占用 8.3%–13.5%,默认 20% 下它一次都不会归档——这正是修复。
  • 滞回 + 动态死区(智能论 3.4 §2.7.2):进入 enter,退出 enter − max(5%, 3σ),σ 取最近 30 次占用率的标准差、上限 20。防的是一次降温后在阈值附近反复抖动。
  • 失败关闭:占用率或窗口不可判定时不归档,status 写明 pressure-unknown。
  • 观测面:status 新增「压力闸门:占用低于进入阈值 / 已回落到退出阈值以下 / 占用率不可判定 / 闸门已关闭」四种如实理由;成本账本新增 belowGateCount。修复前这些只能从 state.lastMeasurement 里翻出来。
  • 离线回放:以真实会话 246 步占用序列为夹具,断言闸门 20% 下归档 0 次。

面板瘦身

  • 删除四个开关:「保留最近操作」(全历史模式下恒为 0,已是死开关)、「全历史记忆上下文」(唯一模式,不再需要开关)、「自动降温」(由压力闸门取代)、「自动回注」(恒开——它是取回闭环的一部分,不是应被关掉的选项)。
  • 新增「压力闸门」一行:开关 + 阈值(1–95)。开关关闭 = 写 0 = 无压力也降温。
  • 状态行改写:降温状态 · 压力闸门(≥N% / 关)· 已归档 · 计划中。

取回通道(P0)

  • memory_lab_recall 在 PTC 形态下可读:run_code 里拿到的是原始 value,而 ids/query 模式此前不填顶层 text(只有 working-set 填),于是模型 r.text?.slice(...) 得到 undefined,判定回读失败并放弃——实测 246 步里唯一一次回读就是这样失败的(冷库其实返回了 779 token)。现在顶层 text 在所有模式下都是可判定的摘要 + 指针(不复制正文,一次回读只付一遍 token),工具描述同步写明这条读法。

插件消息不再冒充人类(P1)

  • source.kind 改为 dsh-memory-context-lab:此前一律写 'user',宿主侧所有按 kind === 'user' 取人类输入的功能都被污染。已取证的消费点:dsh-session-title(实测标题请求的 messageSeqs 是 [31, 155, 157, 159],后三条全是归档回执)、dsh-session-turn-outline(用回执填「本轮提问」)、dsh-session-reference、dsh-web-deepseek-api;聊天 UI 对非 'user' 的 kind 走 role:'inject' 分支,比冒充用户气泡诚实。dsh-session 的 user/message 不变量对 source.kind 无约束(已核对 lib/types/invariant.js),日志不会因此打不开。旧日志仍是 kind:'user' + form,读取端按 form 识别,不依赖 kind。

折叠回执(P1)

  • 标签如实:归档回执曾被一律标成「回注包」——两者是完全不同的东西(回执是 restore 句柄,回注包是当轮检索证据)。现在按形态显式列出,未知形态写「未知形态」而不是猜。
  • 区间有序:成员按活动面顺序排列,seq 可能比左侧更早的节点小,于是出现过 seq 243–189 / 802–770 这种倒置区间(实测 4 处)。现在端点取 min/max。
  • 最新全量卡永不被折:增量卡的语义是「相对最近一张全量卡的变化」,全量卡是它的基准。实测最新全量卡(seq 2565)被折掉后,后续 5 张增量卡仍在引用一张模型看不见的卡。

验证

  • 83 套件全绿(2026-10-18,Node v24.19.0);新增 6 套:恢复完整性、孤儿重建、压力闸门纯函数、压力闸门接线、PTC 回读、source.kind 契约、全量卡保护。
  • 改回去必红:恢复闭环与压力闸门各做一次「临时回退修复 → 用例失败 → 恢复修复 → 用例通过」。
  • 离线回放夹具:test/fixtures/replay-c5af11b4.jsonl(1,249 行 / 246 步,只留结构、工具名、字符数,不含工作区正文)。
  • 未完成:回执文案里的「相关提问会自动回注要点」未删——buildBatchReceipt 同时用于渲染与 restore 的逐字节比对,改文案必须配合回执格式号升级,纳入下一批;架构分层(kernel/store/host)与 v1 拆除、ReFold 去重/折叠算子、情节日志尚未开工。

0.13.0 补丁重打(2026-10-19)

首发的 0.13.0 在真机上暴露四处界面缺陷(排查报告 v1)。四处都是读路径问题:命令能写进去,界面读不回来。

  • 面板「压力闸门」点不动(A2,核心):viewOf() 从未输出 pressureGate,而面板用 view.pressureGate 推 pressureOn——视图读到 undefined → 开关永远画成「关」、阈值框永远 disabled、状态行永远「未启用」,而命令其实已经写进会话设置,用户感知就是「点了没反应」。现在视图按 0..95 收敛后如实输出,越界或非整数回落 DEFAULT_SETTINGS.pressureGate(0 是合法值,不得回落)。
  • 设置页常驻「配置加载中…」(B,核心):宿主用同一个组件渲染两个座位——描述行传 { view: 'summary' } 且刻意不传 form,设置区传 { view: 'page', form }。原实现在 !snapshot 早退分支里把「没有 form」当成「命名空间未服务」,于是详情页常驻一句把视图差异说成宿主故障的文案,而下方设置卡其实工作正常。现在 summary 分支提到快照判断之前,兜底文案改为「设置尚未就绪:宿主未提供本插件的设置表单」。
  • 设置页配不到闸门阈值(C):buildConfigSchema() 的 defaults 块补 pressureGate(范围 0..95,与 NUMERIC_SETTINGS.pressure 同域,不进 settingFields——它是阈值不是档位);设置卡的「全局默认设置」补一个数字输入行。连带必改:settingsValueOf() 是白名单构造,漏字段会让用户保存其他设置时把闸门整块抹掉,已同步。
  • v1 会话点闸门必然失败(D):该行硬编码 /memory-lab2,但闸门是 v1/v2 共用的引擎判据(apply-engine 的 runAutoCooling),v1 也接受 /memory-lab set pressure N。现在命令前缀按会话引擎分流。
  • 权威状态记录补 pressureGate(P2):该机制的意义是「命令被拒绝时面板不得显示已生效」,闸门同样受此约束——否则被拒绝的 set pressure 仍会停在面板上。越界值丢弃(失败关闭),不写进记录。

为什么 83 套没挡住:client.test.mjs 手造了含 pressureGate: 20 的 view,只测「开关 → 命令」映射,从未测「投影 → 视图」这段契约;summary 用例只断言「文本非空」,而误报文案恰好非空。本批新增 test/v2-pressure-view.test.mjs(投影 → 视图契约 4 条),并把 summary 断言改成「必须命中摘要行 + 不得出现任何未就绪兜底」——第一次只写了后半句,把分支关掉后用例仍然绿,是假绿。

验证:84 套全绿(2026-10-19,Node v24.19.0);四处修复各做一次「改回去必红 → 复原必绿」(投影缺字段 4 红、summary 分支关闭 1 红、schema 默认值漂移 1 红、前缀硬编码 1 红)。