Repository navigation
v0.12.0 — 投影经济学与归档-重读循环修复(含面板开关同步补丁)
0.12.0 — 2026-10-18
把「归档—重读」自激循环修掉,并把投影经济学补齐:按灵枢统一架构 v1.2 P5-3(率与失真必须同时声明),
让每条回执/工作卡都说清「释放了多少、失真等级、怎么取回、取回多少钱」,并让最便宜的取回动作成为默认动作。
事实前提:memory_lab_recall 在真实会话 303 步里被调用 0 次(read 182 / pwsh 109 / grep 80),而同键重读 55 次。
已发布到 GitHub:tag v0.12.0(提交 d0329d5)与 Release 附件 dsh-memory-context-lab-0.12.0.tgz(139 文件 / 784.2 kB / sha256 b74a1b23…1b23,远端 digest 一致)已按补丁后的包重打覆盖(见下「面板开关同步」)。安装状态以 DSH 为准,本包不代为安装或重启。
折叠语义(P0-6,硬前置)
- 回注包不再被卡片折叠吞掉:
card-fold.mjs曾把recall算作卡形态,同一步的回注包(prepend)与工作卡(append)两条相邻user/message正好满足minRun=2,下一次归档就被折成一条回执——刚读回的证据从投影消失,模型只能再读一次。现在recall移出CARD_FOLD_FORMS并登记为CARD_FOLD_EXCLUDED_FORMS,是断组边界;人类/assistant/tool-result 仍是硬边界。 - 折叠计划改用活动面顺序(不再按 seq 排序):replace 事件拿到的 seq 比它左边仍在面上的节点大,按 seq 排序会把折叠回执挪到被保留的卡后面,于是下一轮把断组边界读成卡、把卡读成边界(每轮注 2 张卡时卡数不收敛)。
投影头与回读可用性(P0-5 / P0-1)
- 投影头:每条回执/卡片加一行
投影:A 类(可完整重建)|释放 ≈N token / M 字|取回 ≈K token。失真只有 A 类(原文在冷库、可逐字节重建);构造 B 类直接抛错。投影头 ≤1 行 / ≤120 字符,超限先丢取回段再丢字数列。取回代价取冷库载荷既有 token 估算,不新增计算。 - 新格式占新号:操作回执
format 6、片段回执format 7;旧格式 1/2/4/5 的渲染逐字节不变(恢复依赖逐字节相等,这是 format 4 引入时的教训)。 - 可回读动作行:
记录 ID:按 … 别名回读→可回读:memory_lab_recall(record_ids=["mcl2-…"])|A 类可完整重建,命令面降到第二行命令面:/memory-lab2 read …。新格式不再重复那句「相关提问会自动回注要点」(真实会话里一次都没兑现)。 - 工作卡「本步可回读」:最多 3 条,每条 = 记录 ID + 工具/范围/对象 + 取回代价;只描述结构、不复述正文(复述正文等于撤销归档);单行 ≤80 字符,超出的只报计数。
- 成本账本拆三路:
toolRecallReads/commandRecallReads/fileReReads(+fileReReadChars),互不覆盖;修复前只有一个evidenceReReads,把「按 ID 回读」与「重读文件」混在一起,于是插件以为自己「回读 0 次」。
读取账本与读取租约(P0-2 / P0-3)
read-ledger.json:会话隔离根新增账本,键<path>|<offset>,记seq/coldRecordId/hash/chars/firstSeenAt/reads/unchangedReads/lastReadStep。归档含读取类结果的操作时登记;不拦截、不改写工具行为;restore后失效、重启不清零、单会话上限 4,000 条按lastReadStep淘汰。- 失败关闭:账本不可读、不是合法 JSON、schema 不符,或部分条目不可解析,一律
ok:false且不写盘——不静默重建为空。 status重复读取两行:口径 A(重读字符/全部内容字符)与口径 B(内容完全未变的重读)分开报,标「本账本口径」,不把看不见的历史算成 0。retainReads(默认 3,TTL=2N):全历史模式下retainOperations仍为 0(设计不变),最近 N 个含读取结果的操作强制保留,M 步后租约到期并标readLeaseExpired(转「需复核」)。这是降权轴,不是保护集扩张——v1.2 §8.3 的受保护集无界增长是未解问题。retainReads: 0完全退回旧行为;写类操作不受影响。
卡片净占用上界与降噪(P0-4 / P1-6)
CARD_NET_CHAR_CAP = 4000(字符,不是条数):MIN_OPERATION_CHARS = 1200对 span 同样生效,短卡永远进不了候选,所以按字符算。超上限时折叠同一段连续卡组(哪怕只有 2 张),不放宽minRun(放宽会跨非卡节点吞掉助手消息)。- 最新一张工作卡永远保护:它是模型当前能看到的状态面;折叠回执保留全部成员
seq:(替换不是删除);上界到了却折不动时如实告警并计cardCapUnreached。 - 降噪:丢弃页脚只报「类别 × 段/行数」,删掉逐条重要度打分算式;软段头不再重复整条类目次序;增量卡硬上限 24 行 / 1600 字符,超出只留「变化摘要 + 记录 ID」。
其它修复
onEnabled失败语义(P1-1):index.mjs注入的是同步对象,旧写法onEnabled?.(agent)?.catch(...)在同步返回值上访问.catch是undefined→ TypeError,且发生在enable()尾部、状态已落盘之后且不在 try 内:命令显示失败,引擎其实已启用。现在同步/异步都接,抛错(含异步 rejection)一律降级为提示「计划先行未生效」。- 任务锚(P1-2):
isReceiptMessage改由单一常量表SURFACE_INJECTION_MARKERS判定(v1/v2 回执、折叠回执、聚合凭证);无source.form的旧折叠回执不再被当成人类请求。 - 回注信息量门槛(P1-3):命中项必须有结构事实(范围/工具/片段种类)才注入;纯壳不注入,也不产生空块。
- 卡片角色一致性(P1-4):硬保护项带
role/kind;同一 seq 出现在两类硬保护时降级「角色未确认」并告警。不引入req:/evt:双命名空间(同号在本会话未复现)。 - 回执 status(P1-5):工具结果回执加
status=ok|fail|partial,失败附首错行(≤200 字符,不改写原文);非工具结果标kind=message。 - 检索口径文案(P1-7):工具描述与告警不再说「不含正文词」,如实写「覆盖记录 ID/kind/工具名/callId/范围,以及每条记录 ≤8 KiB 的正文词元(含中文二元组)」;描述与
INDEX_TEXT_MAX_BYTES引用同一常量。
面板开关同步(0.12.0 补丁,2026-10-18 重打)
首发 0.12.0 漏了两处未提交的修复,真实新会话里表现为「开关闪一下又关掉、之后点不动」:
- 权威状态记录读错账本:
recordAuthoritativeState只读 v1 的records,v2 会话永远读到空账本,于是每条状态类命令后写出的plugin:dsh-memory-context-lab/state都是空账本默认值。现在按引擎归属取对应账本(v2 读v2.records)。 - 缺席的开关位被按默认 false 补齐:v2 账本没有
planFirst、v1 账本没有fullHistory,旧实现一律补false,于是每写一条权威记录就把刚折叠出来的开关压回关。现在账本没有的位不表态(投影保留日志折叠值),而v2 专属位在 v2 不持有时写 false——否则面板会停在「降温已停用、全历史仍显示开」,再点只得到「v2 引擎未启用」,看起来就是关不掉。 shareL2Content补进权威字段表(原实现折叠时被静默丢弃)。/memory-lab set planfirst支持 v2 会话:旧实现只看 v1 账本,v2 会话里既不落账、还误报「本会话尚未启用降温」。- 回归:新增
test/v2-authoritative-ledger.test.mjs(4 项,走插件真实入口 apply → 命令 → 投影重放),覆盖「开 → 关 → 再点启用降温不回退」完整往返。
测试与验证
- 76 套 / 790 项断言全绿(Node v24.19.0),新增 14 套;
entry-coverage保证入口 == 磁盘。 - 6 个 P0 各做一次变异必红(改回去 → 对应新套件红 → 复原 → 绿):P0-6a / P0-5a / P0-1a / P0-2a / P0-3b / P0-4c。
- 蜂巢:确定性全量(job
…_0006、回修后…_0007)与只读独立复审(job…_0003,verdict REJECT → 2 条 finding 已回修并加回归)。 - 探针:
probe:revert28/28、probe:lingshuexit 0、probe:hostSKIP(未提供--asar)。 - 面板开关补丁(同日重打):
v2-authoritative-ledger4 项全绿;源码线test:all与release/镜像各自 76 套 / 790 项全绿。
兼容性
- 不新增/不删除模型可见工具(工具集逐字节不变,前缀缓存纪律)。
- 旧格式回执与旧日志:format 1/2/4/5 渲染不变,旧折叠回执按标记识别;
read-ledger.json缺失时按空账本处理。 - 不阻止重读、不自动回注正文、不恢复 v1 保留数、不扩保护集、不做 B 类有损投影、不放宽折叠阈值、不改
MIN_OPERATION_CHARS。
安装:下载 dsh-memory-context-lab-0.12.0.tgz,执行 dsh plugin add <tgz 绝对路径>,随后重启 DSH Desktop。