DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

@kira905/dsh-memory-toolkit

Memory Toolkit

DSH 记忆面工具集:独立向量记忆引擎(增量同步 / 混合召回 / 文档索引)+ 记忆库只读体检工具链 + 本地记忆插件 fork(含来源血缘 / 记忆时效)+ persona 记忆体检

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add @kira905/dsh-memory-toolkit@0.3.0
README兼容性版本

兼容性与来源证明

Memory Toolkit 以 @kira905/dsh-memory-toolkit 发布,当前版本为 0.3.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
any
发布来源
npm
Registry 更新时间
2026/11/4

版本

0.3.0stable
2026/11/4
0.2.0stable
2026/11/4

相关插件

正在加载相关插件…

最新版
0.3.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
2.6 MB
文件数
137
Surface
any
许可证
AGPL-3.0-only
发布源
npm
GitHub
★ 2
周下载
0
最近提交
2026/11/4
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 memory-context 分类下经过校验的插件。

Experimental Session Search@deepseek-ai/dsh-experimental-session-search为 Agents 提供搜索和读取当前工作区早期会话的工具。Hindsight Coding Agents@vectorize-io/hindsight-coding-agents面向编程代理的仅反思式 Hindsight 长期记忆(可插拔支持多种运行框架:opencode、……),自动在后台导入(无需设置 CLI)。Contextdsh-context用于上下文洞察和管理的 DeepSeek Harness 插件,提供上下文仪表板和上下文命令,帮助了解上下文的构成及其演变过程。Memory Plugin@openviking/dsh-memory-plugin适用于 DeepSeek Harness 的 OpenViking 记忆与上下文套件

README

dsh-memory-toolkit

这是什么

Agent 的记忆层:向量召回 + FTS5 关键词双路、命中留痕、分层软淘汰,外加一整套只读记忆库体检器具。

它解决什么

「它怎么又忘了」和「它怎么记错了」其实是同一件事的两面:召回不可解释。这里做两件事 —— ① 每次召回都留痕:哪条记忆、因为什么被捡回来,可审计;② 淘汰是软的:搬走不等于删,能查、能恢复。另附 persona ↔ 记忆重叠体检,防止同一件事被写进两处。

一条命令跑起来

npm i -g @kira905/dsh-memory-toolkit
dsh-memory-summary        # 新会话开工简报(只读,dsh 运行中也安全)
dsh-memory-audit          # persona ↔ 记忆 体检

先看它长什么样(真实输出)

list-memory-summary.mjs — 新会话开工简报(只读,dsh 运行中也可安全执行)
用法:node list-memory-summary.mjs [选项]
  --home <dir>            DSH home(缺省 $DSH_HOME 或 ~/.dsh)
  --session <id>         指定会话 id(缺省读 DSH_SESSION_ID)
  --query <text>         直接给召回查询文本(缺省取会话上下文)

三个 CLI 全部只读、不启服务。装法与自检见下方「装完自检」。


本仓装完即用(0.1.3 起):dsh plugin --profile <profile> add @kira905/dsh-memory-toolkit 一条命令,dsh.bundle 会让它自动挂进 profile 的组合列表,不需要再手工写 cordis.patch.yml。包内 3 个 CLI(dsh-memory-audit / dsh-memory-summary / dsh-memory-export)与挂载无关,npm i -g 或 npx 直接用。

装完自检(三条只读验法)

<profile> 换成你实际用的 profile(默认 web),<数据根> 换成你的 DSH 数据根(默认 ~/.dsh)。

# ① 组合树里有没有它(只读、约 0.6 秒、不启服务)
dsh --profile <profile> --dump-config | Select-String "dsh-memory-toolkit"
# 期望:bundle 层出现一行 "# == <登记名>"、insert 层出现 "- id: <entry>"(问的都是「它挂上没」);
#       本仓包名 @kira905/dsh-memory-toolkit —— 带 scope 装的写带 scope 名、老工装 / 手写的可能是裸名,两种都搜一遍
#       ⚠️ 若该包会 insert 一行,还要数一遍"同一个 id 出现了几次",必须 == 1

# ② 组合列表里有没有它(只读)
Get-Content <数据根>/profiles/<profile>/package.json | Select-String "@kira905/dsh-memory-toolkit"
# 期望:dependencies 与 dsh.profile.bundles 两处都有(CLI 类只需要 dependencies;bundles 里也可能写裸名 dsh-memory-toolkit)

# ③ 命令在不在 —— 【只查存在,不执行】
Test-Path <数据根>/profiles/<profile>/node_modules/.bin/dsh-memory-summary.CMD   # 装进 profile 的
Test-Path "$env:APPDATA\npm\dsh-memory-summary.CMD"                           # npm i -g 装的
# 期望:True。两条路径按你实际用的装法挑一条

探针只做存在性检查(只看命令文件在不在,不执行任何命令)。 要不要用 --help 验,见本仓当前说明与该命令的参数表。


DSH(DeepSeek Harness)生态的记忆面工具集 —— 一个独立向量记忆引擎、一套记忆库只读体检工具链、 一个自持 fork 的本地记忆插件,以及一个 persona ↔ 记忆体检小工具。

四件东西原本是同一套自用工作流的不同切面,抽出来独立成仓,可以单独用,也可以拼起来用: 引擎负责"记什么、怎么找回来",工具链负责"看得见、改得动",插件负责"接进会话"。


一、里面有什么

目录是什么形态
memory-engine/记忆引擎(离线层):独立矢量库 · 增量同步 · 兜底 hash 轮转 · 混合召回(向量 + FTS5 + 词表 BM25 + RRF + 编码降级兜底 + 旁路留痕) · 文档索引 · 启动自检 · 本地编码桥纯 Node ESM + node:sqlite
memory-db-tools/记忆库工具集:只读导出 / 六项体检分析 / 结构探针 / 特征词探针 / 与 persona 的重合度 / 看板账本只读探针 / 零改动自证 / 新会话开工简报一组独立 CLI
dsh-memory-local/本地记忆插件:上游 dsh-memory 的自持 fork(跨会话持久记忆 + 召回提示段 + 指针注入链),带构建 / 幂等部署 / 一键回滚 / 部署后自检DSH 插件
persona-memory-audit.mjspersona ↔ 记忆体检:把「persona 正文体积」与「记忆可见率」两项指标固定下来,超阈值即报红单文件 CLI
lib/四件共用的无依赖小件(参数白名单 / HTTP 存活判据 / zstd 帧解析 / 会话文件名 / 坑库打分)纯函数模块

同源说明

本仓部分文件与一套内部生产实现同源(同一份工程长期演进下来的两处落点)。

  • 同源程度:按行级同源度口径统计(同名可比件里,仓内文件的非空行有多少能在参照件中找到,多重集扣减),本仓「≥50% 行同占比」= 64%。
  • 这意味着:本仓是那套实现的提炼导出 —— 既不是逐字副本,也不是完全重写的独立实现。拿单个文件当"独立参考实现"读之前,请先跑下面的判据。
  • 怎么复跑:同源度扫描器见 dsh-quality-toolkit 的 dsh-sim-scan.mjs(--repo <本仓> --prod-root <参照根>);分档阈值与口径写在它的 config/sim-scan.json 里,不藏在代码里。
  • 许可:本仓许可见仓根 LICENSE(有子树例外时以子树 LICENSE 为准)。

来源血缘与记忆时效(0.3.0 新增)

两件与部署无关的通用能力,都在 dsh-memory-local/ 里,都不改既有行为。

① 来源血缘 source_ids

一条记忆可以说清"它是从哪几条观察推出来的"。

  • 落点 = 独立列(memories.source_ids TEXT NOT NULL DEFAULT '',JSON 数组字符串;空串 = 无来源声明)。 绝不写进 tags —— tags 在 FTS 索引里,塞进去会污染全文检索。
  • 写法:memory_write 多一个可选参数 source_ids;读回:MemoryStore#readSourceIds(id)。
  • 迁移有显式版本键(库内新表 schema_meta,memories.source_ids = 0/1),建表 + 加列 + 写键同一事务。 不用 PRAGMA user_version:打开链路里有一行 PRAGMA user_version = N 每连接无条件覆写,放进去等于没写。
  • fail-closed:半迁移(列在键缺 / 键被改过)⇒ 拒写并抛 E_MEMORY_SCHEMA_VERSION_MISMATCH, 不把"读不到列"当成"没有来源"继续跑。

② 记忆时效 until:YYYYMMDD

有时效的判断("这周先把 X 当默认值")给个到期日,到期后不删、只是降权并标出来。

  • 落点 = tags(until:20251130),只加标签、不加列、不改表;认不出来的一律当"无期限"(fail-open)。
  • memory_search 走稳定分区(过期整体后移、组内名次不动、结果集不增不删); 注入侧的指针走标注位降权(名次不动、整行带「已过期(until …)」)—— 指针有 800 字 / 8 条硬预算,后移会把过期条目挤出渲染集 = 实质等于删掉。
  • 没有一条带 until: 时,渲染输出与改动前逐字节一致(有阴性对照测试守着)。
  • 急救关:MEMORY_UNTIL=0 ⇒ 全部按"无期限"处理。

多用户 / 身份范围过滤、设备认账标记、层标与写入影子判定、src 回指参数属部署侧私有实现, 不在本仓(不含其代码、夹具或口径)。

召回链:降级 / 词表第二路 / 命中留痕(0.2.0 新增)

召回有三类老毛病,这一版各给一条可一键关回的解法;出厂默认一条都没改。

毛病现在的做法开关出厂
编码超时/失败 ⇒ 那一轮一条记忆都不注入查询先截断到 256 字符;编码带预算(默认 1500 ms),超时 / 抛错 / 空向量一律降级成固定 Top-K(按最近改动取,条数默认 8),结果里带 degraded.mode = "fixed-topk" 与 encodeError.namefallbackTopK / encodeTimeoutMs / --fallback-top-k / --encode-timeout-ms降级常开(只作用于失败路径,成功路径一字不改)
纯向量对精确词不敏感;中文又走不了 FTS5(unicode61 不切中文)词表第二路:jieba 词典最长匹配切词 + BM25(tf 饱和 + 文档长度归一 + 语料内 idf × 通用词具体度),与向量、FTS 一起进 RRF(k=60)memory-engine/dict/lexicon-config.json 的 enabled、MEMORY_ENGINE_LEXICON=on/off、--lexicon on关(关掉时结果与改动前逐字节一致,见下)
召回了什么、命中了哪条、准不准,事后无从判断旁路 JSONL:query / 命中 id / 分数 / 是否降级 / 时刻;按字节轮转 + 天数清理,不无限增长给目录:--recall-log <目录> 或 DSH_MEMORY_RECALL_LOG_DIR;DSH_MEMORY_RECALL_LOG=off 一键关回不写(库不该在纯查询里偷偷落盘)

为什么这么设计(完整版见 memory-engine/README.md 的「设计依据」):

  • 降级用「最近改动」而不是随便凑数:拿不到向量时,语义相关已无从计算;此时最可能的"有用"是刚写进来的东西。兜底三档依次是数据源直给的 recent() → 元数据按 updated_at 降序 → 向量表里 id 最大的几条,保证非空、顺序确定、仍排除 pinned。
  • 词表默认关:它的收益是"精确词多捞回来一截",代价是"两路融合会重排名次"。本仓对外的承诺是默认行为不改 ⇒ 出厂关、由使用方一行配置打开。打开后 stats.lexiconStatus 从 off 变 ok,命中里出现 sources: ["vector","lexicon"]。
  • 留痕默认不写:query 可能是隐私内容,库不该在纯查询里落盘;要判"召回准不准"就显式给目录,且字节/份数/天数三重封口。实际记录里不存记忆正文,只存 id 与分数。
  • 为什么不复用生产那份补丁:生产侧是"按行号锚点重放"的补丁(patch-*-lexicon.mjs),搬进独立仓必碎;本仓是按行为重写的模块,靠夹具与旧版对拍证明等价,而不是靠 sha 相同。

词典体积与许可:词典.txt(1,029,582 B)+ 词频.txt(219,541 B)来自 jieba 的 extra_dict/dict.txt.small(MIT),随包内嵌在 memory-engine/dict/,合计约 1.25 MB(npm pack --dry-run 实测:整包 tarball 1.1 MB / 解包 2.8 MB / 140 个文件)。 为什么要内嵌:不内嵌的话 npm i 完这一路直接不可用(要么首次运行去联网拉,要么用户自己找词典)。素材目录可用 MEMORY_ENGINE_DICT_DIR 指到别处(打包方嫌大可以把它们挪出包,代价是这一路默认不可用)。

许可按子树优先:memory-engine/dict/ 保持上游 MIT(全文与版权声明见 dict/LICENSE-词典.md), 与仓级 AGPL-3.0 不冲突 —— MIT 与 AGPL 兼容,分发时把那份版权声明原样带上即可(与本仓 dsh-memory-local/ fork 的上游 MIT 同一口径)。 词典/词频按字节原样保留(.gitattributes 里 -text),可与上游 sha256 直接对拍。

怎么复现这些结论:

cd memory-engine
node tools/verify-recall-chain.mjs                                  # 15 项:截断 / 降级 / 词表 / 留痕 / 多来源 / CLI
node tools/verify-recall-chain.mjs --baseline <改动前的 lib 目录>    # 追加 2 项:开关关掉时与旧版逐字对拍

分层软淘汰 + 号段哨兵(0.2.0 新增)

两个老毛病:记忆只能删、不能降级;多台机共用一个库时,id 号段越界没人喊。这一版各给一件,出厂全是干跑 / 只读。

件干什么命令出厂
cli/layer-migrate.mjs给记忆表加一列 layer,存量行回填「缺省层」--db <库>(干跑)· --apply --backup <文件> · --restore <备份> [--apply]干跑:不带 --apply 一个字节都不写
cli/layer-move.mjs把一整层搬到同库的边表 memories_evicted(不删),一条命令出去、一条命令回来--layer <层> --apply · --back --apply · --dump <f> / --verify <f>干跑
cli/band-sentinel.mjs看「下一条新 id」会不会落到别人的号段里--line · --apply --out <文件>只读:缺省连报告文件都不写

层名与号段表都在配置里(memory-engine/config/layers.json、memory-engine/config/bands.json), 代码里没有任何一处写死 core / recall / archival,也没有任何一台机器的名字。

单机 vs 多机:怎么退化

  • 单机(缺省) = 配置里只有一条 band。此时哨兵只读本机库的 sqlite_sequence, 判「下一条新 id」是否落在 [base, base+width)。不 ssh、不猜对端、不假装知道别的机器。 这一步就能抓住最常见的事故形态:合并搬入把 seq 顶高 ⇒ 之后每条新记忆都写进别人的段。
  • 多机(可选) = 配置里有多条 band,且非本机条目带 remote: { ssh, node, db? }。只有这时才逐台去读, 远端命令 / 别名 / node 路径全部来自配置。
  • 远端读不到 ⇒ 结论写「未探测 / 不可达」,退出码不是 4(这条是生产件的血泪假红:把"连不上"和"号段坏了" 混成同一个码,就会天天告警、把真事故淹掉)。4 只留给「本机库读不到」这种真失败。 要"有段没探测就算失败",显式加 --require-all(那时 rc=5)。

判据沿用生产件的好口径:seq 决定的下一条 id 越出本段 ⇒ 红;出现更高位段的行 ⇒ 红 (更高位 id 不可能由这一台合法产生);出现更低位的别台段行 ⇒ 只披露不判红 (历史搬入 / 合并搬入共用段,删行=删记忆,而且不影响后续新 id)。

为什么默认不自动动库

三个命令出厂都是干跑或只读,理由就一条:它们都直接改记忆库,而这个仓的定位是"工具集", 不能替使用者决定"什么时候动、动哪本"。具体收口:

  • 迁移 --apply 必须同时给 --db 与 --backup:不给库路径就不许动(防手滑改到家目录那本), 不给备份路径就拒写(动 schema 前先备份是硬闸,不是建议)。
  • 搬迁默认干跑;真搬要先 --dump 留一份逐行指纹,搬回来再 --verify 对拍。
  • 哨兵是只读件:不写库、不碰 sqlite_sequence、不 VACUUM;要接定时/自检就显式 --apply --out <文件>, 而且机器可读内容只落文件,不上 stdout(日志/报告才可被采集,stdout 留给人读)。

搬走不等于删

layer-move 把整层搬进同一个库文件里的边表 memories_evicted,行原样躺着,另带两列: content_sha(与该行内容绑定的指纹)和 batch(哪一批搬的)。搬回时先核指纹再写回: 边表里只要有一行被改过,整批拒动(不会出现"一半搬回、一半丢了")。

  • 硬判据:搬出行数 + 剩下行数 == 搬前总行数(事务内断言,不成立整批回滚)。
  • 代价(选边表而不是另一个库文件):搬走的行仍占这个库文件的体积 —— 软淘汰省的是上下文与召回面, 不是磁盘;边表也没有 FTS 索引,搬走的行在引擎召回里看不见,只能用 SQL 或 --back 取回。 换来的好处是搬进搬出都在一个事务里,守恒能当场断言,也不会留下一个可能被误删的旁路库文件。
  • 会搬空主表时默认拒跑(--force 才动):那通常是层名填错了。

怎么复现本节结论:

cd memory-engine
node test/run.mjs 12-layering       # 21 项:干跑零写 / 加列回填 / 幂等 / 还原 / 守恒 / 指纹一致 / 号段红绿对照
node cli/layer-migrate.mjs --help
node cli/layer-move.mjs --help
node cli/band-sentinel.mjs --help

会话日志 → 记忆:提炼的边界(0.2.0 新增)

记忆的输入面原先只有一条:库里已经有的记忆(cli/distill.mjs 走的就是这条)。这一版补上第二条 —— 一份会话日志进来,产出 ≤N 条可追溯、可整批撤回的结论条。两个新件,旧入口一个字节都没动:

件干什么出厂
lib/session-source.mjs会话 JSONL 适配层:只挑「能回指来源的结论句」,每条带场次 + 行号 + 字节偏移 + 原文锚纯本地、零依赖
cli/distill-sessions.mjs新入口:抽句 → 预算闸 → 一次模型调用 → 拍快照 → 写回(distilled 前缀 + 批次标签)dry-run

一、不做摘要式写入

抽的是原句,不是"这段讲了什么"的概括。所以下面这些一律不进库(每条都计数,跑完一次性告诉你挡了多少):

  • 寒暄("你好""好的""收到")与疑问句(句末问号);
  • 过程叙述("先…然后…接着…最后…"这种流水账,哪怕句尾偶然出现"决定"两个字);
  • 推测("我觉得/可能/大概/应该是",除非同一句里有"一律/必须"这类规则词撑着);
  • 纯工具输出(工具事件、命令回显)与图片 / 思考段;
  • 超过长度上限(缺省 240 字)的整段转述 —— 宁可漏掉,也不把长文硬塞进记忆库。

二、只写能回指来源的结论条

每条结论都挂着它依据的那几句原文:sessionId + 行号 + 行首字节偏移 + 原文前 48 字。 场次 id 从输入日志 {"type":"session", …} 那一行取:id 或 sessionId 两种字段名都认; 两者都没有就传 --session-id,再没有就一律标 unknown(回指退化成「文件名 + 行号」,CLI 会显式告警)。 模型这一层只允许合成,且必须报出自己引用了哪几条候选(refs);越界引用、空结论、超 120 字、 重复的条目会被直接剔掉(结果里的 rejected 写明理由)。回指不成立 ⇒ 这条宁可不写。

标签形态(与旧提炼条同前缀,撤回器认的就是这个前缀):

distilled src=<批次键> srcids=<行号,...> date=<YYYYMMDD> sess=<场次> run=session:<批次 id>

三、没配每日预算就不跑

不给 --max-tokens、台账里也没配 ⇒ 一次模型都不调,打印「未配置每日预算 ⇒ 本轮不跑(这是故意的)」, 退出码 0(这不是错误)。它不继承内核那 150000 的缺省额度,也绝不"没配 = 无限跑"。 给了预算但当日已超、或者"这一次调用估算下来就会超",同样不跑,并把已用 / 预算写出来。

实测(deepseek-flash,自造三轮夹具会话,每轮一次调用):prompt 344–355 + completion 80–98 = 424–453 token/轮(三轮合计 1311;脚本估算按 1018 token/轮,约 2.3 倍保守)。 建议 --max-tokens 20000:按估算约 19 轮/天,按实测约 45 轮/天。

撤回:一批一个键

一轮 = 一个批次 = 一个来源键,所以撤回是一条命令的事(用既有的撤回器,没另写一个):

node memory-engine/cli/distill-rollback.mjs --db <memory.db> --key <批次键> --apply

撤回器真删前会先 VACUUM INTO 拍快照,并生成一键恢复脚本;删除语句恒带 AND tags LIKE 'distilled%', 所以就算键算错也不会误伤真实记忆。写库前那一份快照则由 distill-sessions 自己拍(--snapshot-dir 可指定), 拍不成就不写库。

压缩日志(.jsonl.zstd)与"不静默失败"

DSH 的会话日志是 zstd 压缩的(而且一次追加一帧,是多帧文件)。session-source 会自己走一遍帧结构、 逐帧解压(node 22.15+ / 24 自带 zstd,零依赖);解不开就抛一条人话错误,告诉你「这是压缩日志,请先解压再喂」, 不会只解第一帧就假装读完了,也不会静默返回空结果。

怎么复现本节结论:

cd memory-engine
node test/run.mjs 13-session-distill   # 40 项:抽句回指 / zstd 多帧 / 预算闸三态 / 快照 fail-closed / 整批撤回
node cli/distill-sessions.mjs --help
node cli/distill-sessions.mjs --source <会话.jsonl>                      # 无预算 ⇒ 打印"不跑",rc=0
node cli/distill-sessions.mjs --source <会话.jsonl> --max-tokens 30000   # dry-run ⇒ 列出将写什么

二、环境要求

  • Node.js ≥ 22(用到内置 node:sqlite,以及 ESM 顶层能力)
  • 平台:Windows / Linux / macOS 均可;路径默认值一律从环境变量或当前工作目录推导,不含任何写死的机器路径
  • memory-engine/ 的本地向量编码额外需要 @huggingface/transformers(可选,见下)

三、安装

git clone https://github.com/kira905/dsh-memory-toolkit.git
cd dsh-memory-toolkit
npm install          # 本仓根包零运行时依赖,此步只装元数据

要跑本地向量编码(memory-engine 的 ONNX 路径),再装它自己的依赖:

cd memory-engine
npm install          # 会拉 @huggingface/transformers(较大,约 300+ MB)

不想装这个依赖也可以:引擎的召回支持HTTP 编码桥(见下),以及纯 FTS5 的降级路径。

四、快速开始(命令可直接照抄)

# ① 体检工具链的用法与参数(零副作用,先看再跑)
node memory-db-tools/audit-export.mjs --help

# ② persona ↔ 记忆体检(只读;读 $DSH_HOME 下的 persona 与记忆库)
node persona-memory-audit.mjs --help

# ③ 新会话开工简报(只读:设备行 + 记忆清单 + pinned 全文)
node memory-db-tools/list-memory-summary.mjs --help

# ④ 记忆引擎的启动自检(需要先在 memory-engine/ 内 npm install)
cd memory-engine && node cli/selfcheck.mjs --json

一次典型的季度记忆库体检(全部只读,产物落你指定的目录):

node memory-db-tools/audit-export.mjs --out ./_audit/memories.json
node memory-db-tools/audit-analyze.mjs --in ./_audit/memories.json --out ./_audit
node memory-db-tools/audit-struct-probe.mjs --in ./_audit/memories.json
node memory-db-tools/audit-verify-unchanged.mjs --baseline ./_audit/memories.json --expect-unchanged

五、与 DSH 的集成点

本仓不依赖 DSH 才能运行,但下面三处是刻意的接缝:

接缝说明
DSH_HOME(缺省 ~/.dsh)记忆库(memory/memory.db)、向量库(memory-vectors/)、preset(.agent-presets/)、profile 覆盖(profiles/<profile>/cordis.patch.yml)一律从它推导
dsh-memory-local/ 的部署形态插件占用上游包槽位 profiles/<profile>/node_modules/dsh-memory(不新增包名、不改 profile wiring),cordis.patch.yml 的 insert.name 必须保持 dsh-memory
环境变量注入MEMORY_ENGINE_*(库/向量/模型/批大小/召回参数)、DOC_INDEX_*(文档索引扫描面)、DSH_ARCHIVE(备份落点)、DSH_PROD_ROOTS(生产树放行闸)

六、数据与安全

  • 对记忆库只读:引擎与全套 audit-* 工具打开 memory.db 一律 readOnly: true;唯一的写口是独立向量库与你自己指定的输出目录。
  • 不收集、不外发:没有任何遥测;唯一的外部网络调用是你主动启用的 LLM/编码端点。
  • 凭据只从环境变量或本地配置文件读,代码里没有、也不会写任何密钥。
  • 生产写闸:还原 / 回滚类脚本动到生产树前必须显式 --allow-production,否则拒跑(--dry-run 是只读档,不受限)。

七、许可

AGPL-3.0(GNU Affero General Public License v3.0),全文见 LICENSE。

个人、学习、开源项目可自由使用与修改。若要在闭源或商业场景中使用(AGPL 的传染条款不适用), 请在 Issues 开一条说明用途,获取商业授权。

子树例外:dsh-memory-local/ 是上游 dsh-memory(MIT)的 fork, 该子树保持上游 MIT 许可(见其 package.json 的 license 字段与 FORK-BASE.json); memory-engine/dict/(词典与词频)来自 jieba(MIT),同样保持上游 MIT(见 dict/LICENSE-词典.md); 其余目录(引擎代码、工具链、共用件)为本项目原创,按 AGPL-3.0 + 商业授权双许可发布。 子树许可优先:分发整包时,上述两个 MIT 子树按 MIT 原样附版权声明即可,不适用 AGPL 的传染条款。

八、相关仓

  • dsh-butler-archive —— DSH 大管家(自主运维机制)归档仓
  • dsh-session-toolkit —— 会话标题 / 会话治理
  • dsh-ecosystem-panel —— 生态面板
  • dsh-firstaid —— 急救台 / 回滚演练
  • 同属 DSH 生态的伴生组件各自独立仓、独立版本、许可各自独立。