Releases: modusensus/dsh-mneme
Releases · modusensus/dsh-mneme
Release list
dsh-mneme v0.3.7 — 启动竞态修复
🩹 v0.3.7 — 启动竞态修复(issue #6 跟进)
heptaspirit 验证发现的启动竞态 bug:人工编辑 md 镜像 → 重启 → 向量重建失败(embeddedCount 减 1)。
根因
mergeHumanEdits 回灌在插件 apply 同步段执行,而 embedder.init() 是异步的(模型加载 0.3-0.9s)——回灌触发 embedSingle 时 extractor 未就绪,抛错被吞,向量重建静默失败。
修复(三层)
- index.js:回灌移入
embedder.init().then()内执行,extractor 就绪后再重建向量;init 失败走 keyword 降级 - service.js:
scheduleEmbed加就绪门——embedder 带ready标志时,未就绪的写进入 pending 队列,init 完成后 flush(上限 100,~3s 轮询封顶,fail-safe)——顺带覆盖运行中热写入的同类竞态 - local-embedder.js:
init幂等保护(已初始化直接返回)+ready标志
测试
- 443 / 443 全绿
dsh-mneme v0.3.6 — 镜像债务建模
🩹 v0.3.6 — 镜像债务建模(audit peer 4 类阻断修复)
安全审计 peer 在 v0.3.2 复验中发现 4 类运行时阻断,已全部修复:
1. COMMIT→dirty 崩溃窗口
- SQLite 提交后、markMirrorDirty 前进程退出 → DB=New/mirror=Old/dirty=false
- 修复:recoverMirror 触发条件扩为
dirty || generation > applied_generation,desired/applied 不一致也能恢复
2. markMirrorDirty 自身失败
- 镜像失败 + 状态写失败同时发生 → false-clean 终态
- 修复:generation 债务模型——即使状态写失败,desired 与 applied 的差距仍可被下次 recover 捕获
3. 全局状态丢失
- mirror_state 只有 id=main,无 generation/fence/CAS;双 worker 交织时一个成功清掉另一个未恢复故障
- 修复:
markMirrorCleanForGenerationCAS/fence 语义(旧 gen 清新故障被拦截);type_status逐 type 表达部分成功
4. health fail-open
- /health 未鉴权 + 泄漏 last_error + 读失败返回 dirty=false
- 修复:requireAuth 鉴权 + 脱敏错误码(no-space/permission/sync-failed)+ 读失败 fail-closed(status: unknown)
测试
- 新增 14 个回归测试(
test/mirror-generation.test.js):崩溃窗口 / 双 worker fence / 逐 type / health 脱敏 / 迁移幂等 - 修复随包 mirror-dirty 测试旧断言(5 列→8 列)
- 443 / 443 全绿
dsh-mneme v0.3.5 — 向量修复 + 安全文档
🩹 v0.3.5 — 向量修复 + 安全文档
Issue #6 — scheduleEmbed 兜底(Local/Ollama/OpenAI 路由)
- 根因:
LocalEmbedder/OllamaEmbedder/OpenAIEmbedder(新路由)都没有schedule方法,导致内容更新后向量被清空但不重建(静默 no-op) - 修复:
scheduleEmbed加能力检测——有schedule走原路径;否则用embedSingle拼 title+content 生成向量 →store.setEmbedding重建 - 告别静默吞错:外层 try/catch +
logger.warn - 覆盖三种 provider,一处改动
SECURITY.md v2.1
- 移除不存在的配置键(apiKeyMasking / auditRecalls / auditDreams),替换为真实存在的(policyEpoch / conflictFreezeEnabled / entityExtractionEnabled)
- EOL 措辞不编造日期
- 完整安全策略:版本支持 / 漏洞报告 / 响应时间线 / 严重度分级 / 设计原则 / 审计史 / 披露政策
测试
- 429 全绿(核心受影响文件 59 测试验证通过)
dsh-mneme v0.3.4 — 安全依赖升级
🛡️ v0.3.4 — 安全依赖升级
合并社区 PR #5(@anupamme):修复 CVE-2026-39244。
变更
- adm-zip 0.5.18 → 0.6.0(通过 overrides 强制传递依赖版本)
- 修复 CVE-2026-39244(精心构造的 ZIP 文件导致过度内存分配的 DoS,HIGH)
- 仅改依赖元数据,无源码改动,API 完全兼容(onnxruntime postinstall 解压路径验证)
测试
- 全部测试文件单独验证通过(429 全绿基线),adm-zip 升级无破坏
dsh-mneme v0.3.3 — 社区 issue 修复
🩹 v0.3.3 — 社区 issue 修复
两个社区 issue(@heptaspirit)已修复:
Issue #3 — 人工编辑后向量不一致
mergeHumanEdits(启动 mirror 合并回库)更新记忆后补 scheduleEmbed,与 saveWithDedupe 路径对齐- 人工编辑 title/content 后,该记忆的 embedding 向量会重新生成,向量与内容保持一致
Issue #4 — 模型缓存目录生命周期
- 默认缓存目录用户级化:
embedModelCacheDir为空时解析到~/.dsh/mneme/models,与依赖树解耦(重装 node_modules 不丢模型) - 文档字段名修正:
LOCAL_MODEL.md的embedCacheDir/embedModel/embedDevice→embedModelCacheDir/localEmbedModel/localEmbedDevice(照文档配不再被静默丢弃) - 已配置非空值的用户无感,向后兼容
测试
- 429 / 429 全绿,stress 全绿
dsh-mneme v0.3.2 — Mirror 健康状态
🩺 v0.3.2 — Mirror 健康状态(F-NEW-03)
安全审计 peer 在 v0.2.11 复验中发现 F-NEW-03:syncMirror 失败只被瞬时吞掉,无持久 dirty 状态、启动重试、人工 reconcile 入口、健康状态。已修复:
修复
- store.js:新增
mirror_state表 +setMirrorState/getMirrorState/markMirrorDirty/markMirrorClean/clearMirrorDirty(幂等迁移) - service.js:syncMirror 失败持久记 dirty / 成功清 dirty;
recoverMirror()启动检测 dirty → 有界重试(最多 3 次)安全重渲染;getMirrorHealth()暴露状态 - api.js:新增
/api/dsh-mneme/health端点 - index.js:启动时
recoverMirror()
意义
- 镜像同步失败不再"静默自愈靠运气"——持久记录、启动重试、可观测
- 故障注入后无需业务写即收敛(peer 要求)
测试
- 新增 11 个回归测试(dirty 持久化 / 跨重启 / 有界重试 / 端到端收敛 / fail-safe)
- 416 / 416 全绿,stress 全绿
dsh-mneme v0.3.1 — Logger 统一
🪵 v0.3.1 — Logger 统一(kimi 审查修复)
Kimi 审查发现的代码质量问题:extractor/service 内部用 console.warn 而非统一 logger 体系。已接入:
修复
- extractor.js:3 处
console.warn→logger?.warn?.(),extractEntities签名加logger参数 - service.js:4 处
console.warn→logger?.warn?.(),createService签名加logger参数 - index.js:把
ctx.logger传入 createService + extractEntities - test/fnew-0112:断言从
console.warn更新为logger.warn
意义
- 所有日志统一走 DSH 的
ctx.logger体系,可被宿主正确采集/过滤 logger可选链,不传则静默,行为完全向后兼容
测试
- 404 / 404 全绿,stress 全绿
dsh-mneme v0.3.0 — 记忆基因
🧬 v0.3.0 — 记忆基因(Structured Memory)
dsh-mneme 从「文本仓库」进化为「结构化知识库」——实体(Gene)+ 属性(Base)+ 时间轴(Timeline)。
新增
- 三张新表:
entities(基因)/entity_attrs(碱基对)/entity_relations(序列关系)+ 索引,幂等迁移 - valid_until 时间轴:新属性写入→旧行失效;查询当前 =
valid_until IS NULL,历史可追溯 - LLM 实体抽取器(
src/entities/extractor.js):JSON 抽取 + resolveEntity 去重 + 属性时间轴写入,全程 fail-safe - entity:/attr: 前缀搜索:entity_attrs 精确命中(score=1.0)> 关键词提及(0.7),attr: 支持属性过滤
- autoDream 增强:update 决策自动建立 supersedes 自引用;merge 迁移 loser 实体属性到 keeper
- 配置:
entityExtractionEnabled(默认 false,开关隔离)/entityExtractionModel/entityExtractionMaxEntities/entityExtractionMaxAttrs/entitySearchEnabled
设计原则
- 开关哲学:默认关闭,v0.2.x 行为完全一致
- 向后兼容:memories 表不变,三表通过 memory_id 外键关联
- Fail-safe:抽取失败降级纯文本存储,不阻塞写入
- 审计优先:属性变更不覆盖历史,valid_until 保留完整时间轴
测试
- 新增 31 个测试(
test/entities.test.js):Schema/实体 CRUD/时间轴/抽取器/搜索/autoDream/Fail-safe - 404 / 404 全绿,stress 全绿
- 文档:
docs/ENTITIES.md+ README 更新
dsh-mneme v0.2.11 — 审计复验修复
🩹 v0.2.11 — 审计复验修复(F-NEW-01 / F-NEW-02)
安全审计 peer 在 v0.2.10 真实包复验中发现两项新阻断,已修复:
F-NEW-01 启动回灌静默改回
- 现象:SQLite 已提交 New、镜像同步失败留旧机器镜像后,重启把 DB 静默改回 Old,无冲突标记
- 修复:启动回灌
mergeHumanEdits复用 last-rendered digest 判定——digest 匹配(无人触碰)跳过覆盖;新增 hasDiff 守卫
F-NEW-02 transaction mirror 失败误报未提交
- 现象:DB 已 COMMIT 但 finally 内 syncMirror 失败 → 被当成未提交,API/receipt/audit 虚报 reconcile/applied:0
- 修复:syncMirror fail-safe(mirror.sync 包 try/catch,不向外抛);transaction 提交状态不再被 mirror 失败污染;receipt/outcome 从实际提交事实生成
测试
- 新增 10 个回归测试(故障注入 + 关闭重开 DB 终态断言)
- 373 / 373 全绿,stress 全绿
dsh-mneme v0.2.10 — 镜像 digest 基线
🩹 v0.2.10 — 镜像 digest 基线(安全审计 peer 阻断项修复)
修复
安全审计 peer 在真实 npm 包上发现:未被人工改动的机器镜像会被误判为"人工编辑 vs 记忆库并发更新",导致:
- 直接 update / transaction update / saveWithDedupe merge / Dream merge 四条路径回滚成旧值 + 伪冲突标记
- 现有 355 测试未覆盖此场景
方案
- last-rendered digest 基线:渲染时每条例目写
<!-- mirror-digest: sha256(title\x00content) --> - 判定时比较文件 hash 与 digest:
- digest 匹配 = 无人触碰 → 机器 wins(精确落地)
- digest 不匹配 / 无 digest = 人工动过 → 三方合并(保留双方)
测试
- 新增 8 个回归测试(4 条机器写路径 + 真实人工编辑控制组 + 老文件无 digest)
- 临时禁用修复验证:4 条机器写路径精确失效 → 确认是真回归测试
- 363 / 363 全绿