Repository navigation
v0.8.15
🆕 新增
-
面板暴露后端已有能力(issue #386 第一批):三张只读卡补齐「后端已实现、面板未暴露」的信息盲区。① 状态页「库内一览」新增「Markdown 镜像」健康卡,读
GET /api/dsh-mneme/health展示mirror.status(ok/degraded/unknown)、未落盘提示、last_error三码(磁盘满 / 权限不足 / 同步失败)的人话映射与上次尝试/上次成功时间——面板侧与后端同为 fail-closed:请求失败或 unknown 一律显示「未知」,绝不显示「正常」(镜像写失败此前在库内完全静默);② 设置「连接与安全」新增「独立服务dsh-mneme-serve」卡(一行示例命令 + 复制,并提示它与外部访问 API 默认抢同一端口、令牌同源);③ 同组新增「MCP 服务dsh-mneme-mcp」卡(可复制的.mcp.json挂载片段,数据面走外部访问 API 的 Bearer)。三张卡纯展示,不做进程启停/守护/端口探测,不加配置键;示例命令必须带-p @modusensus/dsh-mneme——bin 名与包名不同,裸npx会去装一个不存在的同名包(test/client.test.js有字面量锁)。 -
记忆库落点检测告警(issue #368):
memoryDir落在宿主 profile 作用域(形如…/profiles/<名字>/…)时,启动打一条可操作告警——#218 末楼记录过 profile 被清理导致整库连带丢失的实际事故。判定是纯路径段匹配(跨平台分隔符、大小写不敏感,只认显式profiles段,不做「看起来像用户数据」的猜测:漏报可容忍、误报等于狼来了)。只检测不搬迁:不改行为、不动数据、不加配置键、不进 settings 白名单(路径配置不是行为开关,与documentDir同口径),存量用户零迁移。根 README 中英成对补「记忆库落点建议」节。 -
注入前判定
preInjectGate(issue #380,E12 D1 裁决落地,opt-in 默认关):每帧注入候选出池后、进入 system prompt 前,一次池级 LLM 调用判出「会向本次请求注入意见/立场」的记忆(判定协议与 E12 实验 protocol-preinject.txt 同源;E12 实测判定+过滤把谄媚率 26.9%→2.5%,且 MemGauge 三阶段考卷实测写入/巩固/检索预算三面对内容毒均无防线——这是唯一过预注册判据的机制)。两级语义复用 #254 writeAdmission:enabled观察档(判定完成落llm_audit_logs,真实 token 用量 + 被标记记忆 id,先看真实负载的意见占比分布)、enforce缓存命中帧真滤除(E12:判定+标记比过滤差 +17.6pp,判定结果绝不进模型上下文)。宿主注入渲染是同步回调 → 判定走 async prefetch + cache 同步消费(queryVectorCache 同款),冷缓存首帧降级为原样注入、下一轮同 key 渲染生效;判定失败原样注入 +degraded审计行(审计行无条件落,无默认模型路由时model_id落unknown占位),防线故障永不阻塞注入;连续降级熔断一个冷却期(判定器系统性坏掉时不逐帧花钱,到期自动恢复)。审查加固(#382 评审):判定与滤除移进service.injectCandidates的touchRecalled之前(与 strictScope 同纪律——留在调用方做时,被滤掉的记忆照样刷温时钟并落mode='inject'曝光账,反馈环会把闸门想压下的意见记忆重新顶上来),recall_runs的「实际注入集」随之只吃滤后集合;整池被标记时放弃本帧 enforce(fail-open:记忆正文可影响判定模型,一条指令型记忆不该让整个记忆块静默失明),形态即审计行的n_flagged == n_pool;clear()(dispose 钩子)后置 disposed、在飞判定不回写缓存;缓存命中刷新序(LRU)。pin 池(#249 逐字保真)与 graphHint 线索行豁免;候选映射m#<i>局部序号(E13b 实测 UUID 回显脆弱);缓存键 = 查询 + 候选id:内容集(轮换/新记忆/内容被就地修正即重判);llmAudit关闭时本闸不运行;lightMode 强制关(applyLightModePreset支持点分键)。白名单 + 计数锁 +2 + 文档(CONFIGURATION.md 新节)。
⚠️ 行为变更
dreamMergeGuard默认值false→true(issue #339 / E8):巩固 merge 护栏自 v0.8.13 引入时是 opt-in 默认关,现改为默认开——合并对象命中长保留类型(与 archive 护栏同表:preference/pattern/rejected_solution/constraint/pitfall)的 merge 决策整条跳过,dreamSkipInvalid(默认开)下被跳条目进dream_runs.skipped、run 记 degraded。依据是它引入时就已写明的机制:archive 护栏只挡 archive 不挡 merge,而 merge 的「更精炼摘要」恰是约束失真的主通道——E8 实测巩固损耗里 10/26 条被丢约束已归位 guarded 类型仍被 merge 吃掉;同类压缩管线的实测也显示安全规则被同速压缩后一轮只剩 53%、五轮只剩 10%,且全程无报错信号。需要旧行为的库显式设dreamMergeGuard: false(面板可关)。
🐛 修复
- 面板
memory_runtime verify的假失败:验证跑到包内去找模型(#387):embedModelCacheDir的约定是「空 =~/.dsh/mneme/models」(README / CONFIGURATION.md / LOCAL_MODEL.md 同口径),local-embedder 与 reranker 也都按String(x ?? "").trim() || 默认解析;但tools.js的 verify 分支把这个值原样交给verifyPayload,而默认 engine 的if (cacheDir)让空串等同于「不设置env.cacheDir」——transformers.js 于是转去找包内相对路径,报错指向node_modules/@huggingface/transformers/models/Xenova/...。真实嵌入用的是用户目录那份(所以检索一切正常),只有面板验证在包内找,报出functional: false的假失败;CLI(scripts/mneme-runtime.mjs)自己解析了默认目录,于是同一份运行时「CLI 通过、面板失败」。修法是把解析收进src/runtime/verify.js的默认 engine(新增导出resolveModelCacheDir),让「验证与真实推理用同一份模型」成为模块自身的不变量——任何调用点传空值都不会再验错地方(收在调用方只能修掉这一处)。顺带补同一调用点的第二处信息缺失:verify 此前不传model,恒探默认小模型Xenova/bge-small-zh-v1.5(与localEmbedModel默认值同字面量,因此只有换过模型才暴露),用户换模型时那份结论不是他实际使用的那份,现在按config.localEmbedModel探(空值仍落默认,默认配置逐字节不变)。回归锁四处:默认 engine 省略 / 空串 / 纯空白 cacheDir 都落用户级默认目录、显式目录不被默认值顶掉、cacheDir与model沿线透传、以及走面板同一条路的端到端用例(memory_runtime {action:"verify"}→verifyPayload→ 默认 engine,假 transformers 入口记录它收到的模型与目录);兜底做变异检验(把resolveModelCacheDir还原成旧行为时三条用例变红)。 - 事务内创建的记忆实体抽取被静默丢弃(#372):
scheduleEntityExtraction在事务内直接 return(注释写 deferred,实际transaction()从不补跑),而自动蒸馏的全部写入都裹在service.transaction()里——session:*来源的记忆自 0.8.x 起 100% 抽不到实体(报告者库内数据:9-25 后 337 条自动蒸馏记忆 0 抽取 0 审计)。修法:事务内入队、COMMIT 成功后由事务本体补跑(回滚路径丢弃,绝不对已回滚的行抽取);saveWithDedupe的合并分支补触发抽取(此前并入的新内容永不进实体面;saveAttr按 (entity_id, attr_key) 先失活再插入,重抽幂等);writeAudit在 LLM 路由解析失败(modelId 为空)时对非 ok 状态补一条 warn——消灭 #108 同款「零实体零日志」盲区。报告者(lqs50)三条主发现全部对源码坐实;其建议的「finally 里补跑」已修正为仅 COMMIT 成功后补跑。
🧹 工程
-
code-scanning 依赖告警清零(
sharp0.35.4 → 0.35.5):GitHub code-scanning 上仅剩的一条 open 告警是sharp@0.35.4命中GHSA-wq5f-xc86-pv6w(CVE-2026-96889,severity high,修复版 0.35.5——随包把上游 librsvg 带到 2.63.2)。它在 mneme 里不是直接依赖,而是@huggingface/transformers声明的^0.35.4传递依赖(本地嵌入运行时构建面,npm 用户装不到)。只改 lockfile 不够:runtime-manifest.json把sharp与 23 个@img/sharp-*(libvips 1.3.3)连 tarball 与 sha512 一起钉死并分发给用户,而扫描器看不见 JSON 清单,漏洞版本会继续发出去。故 lockfile 与清单同步升到sharp 0.35.5+@img/sharp-* 0.35.5+ libvips1.3.4(同一^0.35.4区间内,无 API 变更)。可达性本身很低——mneme 只做文本嵌入与重排,没有任何sharp()调用(不解码 SVG),RCE 还需 glibc Linux 且要攻击者提供 SVG;修的理由是升级免费且清单面向最终用户。npm audit(含 dev 与--omit=dev双口径)0 vulnerabilities;全量测试 1561/1560 pass/0 fail/1 skip。 -
npm 包
files补发docs/,allowScripts对齐 lockfile:README 有 9 处相对链接指向docs/*.md,而files白名单不含docs——这些设计文档在 npm 页面全 404(GitHub 上正常)。白名单加入docs(8 个 md 随包发布)。同处清掉另一笔陈旧账:allowScripts还写着onnxruntime-node@1.24.3与sharp@0.34.5,实际锁文件是1.30.0/0.35.5,而 sharp 0.35.x 已不带 install 脚本——按1.30.0保留 onnxruntime 的 postinstall 白名单、删除 sharp 条目(#384 明确欠的后续)。