# yammory_system
**您的助手不再追问那些它本该知道的事。**
它跨会话记得您——每个科目里您到了哪一层、您喜欢别人怎么跟您说话、哪些事您已经定下来了——并且没有您的批准,任何一条写入都不会落盘,所以关于您的事,不会被背着您存下来。
[](LICENSE)
[](https://github.com/topics/dsh-plugin)
[](#compatibility)
[](https://github.com/KhalilYamber/yammory-system/actions)
[](https://github.com/KhalilYamber/yammory-system/releases)
[English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
分发渠道:仅 GitHub 一条——没有 npm 包,也没有市场上架。
---
## Why this exists
一个有本事的助手,依然是个失忆的助手。每次会话它都从头来过:不知道您已经懂了特征向量、却从没碰过张量网络;不知道您宁可被纠正、也不愿被鼓励;也不知道三周前您已经决定不走那条路。于是您一次次重新自我介绍,而这场本可以从有趣处开始的对话,从零开始。
`yammory_system` 给 DeepSeek Harness 一个地方存住这些知识,以及一套不去猜也能用上它的办法。三件事让它区别于一个记忆仓库:
- **先决定怎么说话,再去检索。** 七面画像携带分领域知识水位,所以助手在开口之前就知道您能接住哪些词——注入发生在提示组装时,而非检索之后。
- **没有您,什么都不写。** 每条写路径都被强制经过服务内部 DSH 自己的审批门。被拒的写同样留证;静默写入不是本插件能到达的状态。
- **它的工作您可以查。** 模型看过的每一句都有记录,库是一个您可以浏览、导出与审计的普通 SQLite 文件,一整类错误由设计拦下,而非靠自觉。
## Install
```sh
# 1. install the bundle into your profile
dsh plugin --profile web add "github:KhalilYamber/yammory-system#main"
# 2. restart and verify the row
dsh --profile web --dump-config | grep -A3 'id: yammory_system'
```
其他渠道与卸载:
- **git channel**(最新 `main`):`dsh plugin --profile web add git+https://github.com/KhalilYamber/yammory-system.git`。
- **tarball channel**:在本仓库执行 `npm pack`,然后 `dsh plugin --profile web add ./yammory_system-.tgz`。
- **uninstall**:`dsh plugin --profile web remove yammory_system`(记忆库与会话日志保留)。
## The first minute
重启之后,什么都不用配,您就该看到:
| 位置 | 是什么 |
|---|---|
| 侧栏底部 | 设置旁边的一个**记忆**入口(它开关抽屉;可用 `panel.enabled` 隐藏) |
| 会话标题栏 | 会话级的记忆开关——关掉即停掉该会话的注入、召回、写入与观察 |
| 侧栏底部 → 该入口 | 抽屉:按轨道与层级列出的条目、搜索、预警线用量、近期审计、三个可观测数,以及一个只排队登记的**整理全库**按钮 |
| DSH 设置 → `yammory-system` | 每一个配置项,各自带一个问号,用大白话解释它 |
| `/memory` | `list`、`query`、`stats`、`audit`、`session on|off`、`export` / `import `,以及更多 |
## Table of contents
- [Why this exists](#why-this-exists)
- [Install](#install)
- [The first minute](#the-first-minute)
- [How it works](#how-it-works)
- [Capabilities](#capabilities)
- [Compatibility](#compatibility)
- [Configuration](#configuration)
- [Tools & surfaces](#tools--surfaces)
- [MCP server](#mcp-server)
- [Permissions & data](#permissions--data)
- [Security boundaries](#security-boundaries)
- [Known limitations](#known-limitations)
- [How it's different](#how-its-different)
- [dsh-memory-protocol v1](#dsh-memory-protocol-v1)
- [What we learned from the terminal memories](#what-we-learned-from-the-terminal-memories)
- [Development](#development)
- [Topics](#topics)
- [Contributors](#contributors)
- [Upstream](#upstream)
## How it works
`yammory_system` 是能力接缝,不是又一个仓库:一个类型安全的 `ctx.memory` 服务、一个本地 SQLite 提供方(`node:sqlite`,WAL,`0600`,位于 `$DSH_HOME/dsh-memento/memory.db`),以及它的消费方——`memory` 工具与注入系统提示的冻结快照。
两条轨道 × 两个层级 × 按 agent 隔离:`user` 轨(关于用户的事实)与 `agent` 轨(环境事实与约定),各自再分为 `user-global` 与 `workspace` 层,并按 `agentPreset` 隔离。快照在会话首次组装提示时冻结一次,会话中途不再变化。预热块承载表达约束与常驻画像,末行是一行目录(`本工作区与 agent 轨另有 N 条记忆不在本块`),让模型知道还有东西可按需取——只报条数,正文仍留在 `memory_recall` 那一侧。
## Capabilities
- **审批门不可绕过。** 每条写路径(`add` / `replace` / `remove` / `seed`)都被强制经过服务内部的审批 waterfall,而非工具层。`writePolicy: ask | auto | off` 是模型看不见的配置;`replace` / `remove` / `consolidate` 的审批载荷携带将被改动条目的全文,被拒的写同样落一条 `*-denied` 审计行。
- **模型可见 ⟺ 已记录。** 注入的快照逐字进入 `system/message`;每次写都能从 `approval/asked` + `approval/decided` + 插件自有审计表重建。
- **有界且诚实。** 每轨每层软预警线(默认 user 2000 / agent 4000)。越线绝不拦写——只提示这一格值得整合。绝不截断、绝不自动压缩。
- **会话级开关。** 每个会话一个自己的记忆开关(插件自有 SQLite 表,schema v6;默认开)。关掉即四件同时停:**注入停**(该会话的冻结预热块立刻作废)、**召回禁**(`SESSION_MEMORY_OFF`)、**写入停**(与审批门同层拦截)、**观察不碰**(本会话不扫,历史选区也不选它)。管理面只读(`/memory list` / `budgets` / `audit` / `export`)照常可用。用 `/memory session on|off` 或输入框下方的开关切换;开关状态本身绝不进会话日志,审计行 `text` 恒为 `null`。
- **观察,并让观察自己跑下去。** 观察通道读一段您自己的旧发言,落下面向「问卷够不到的那几面」的行为条目;现在有一条只读检查在距上次观察超过一周时提醒(一行 `observe-due` 审计 + 下一次会话预热段末行一句),另有一条每周的计划任务能在**一个工作区**里无人值守地跑完它:无头 `dsh` 会话扫描、至多推断 3 条带证据的条目、过同一道审批门落库,放行靠它自己的写策略来源(`source:observation`,`auto` / `ask` / `off`)。插件里不装定时器;调度是一条 Windows 计划任务,与整理轮同理。
- **整理与度量。** 模型驱动的整理把「在讲同一件事」的条目并成一条带 `merged` 标的条目,旧条目降级为 `superseded`——仍在库里,退出每个会话的可见集,绝不物理删。它不跨桶(`track × scope × agentKey`,workspace 层再加 `workspaceKey`),也绝不自动跑。合并能否不经人眼落写,由五根机械硬杠判定(同桶 / 条数 / 去标点、空白**与符号**后逐字一致 / 相似度 / 覆盖度),不由模型自报把握:只有「去过标点、空白与符号后逐字相同」的那一档判 `auto`、可以无人值守落写;改写过的同义句连 review 线都够不着,落 `skip`(原地不动);一字之差落 `review`,等你过目。因此一个后台轮(由您自己的计划任务唤起的无头 `dsh` 会话)能自行合掉机制上明确无歧义的重复,硬杠不敢担保的部分则留着等您。写入把审计来源钉成 `tidy-auto`,所以粒度写策略(`source:tidy-auto`)可以只放行这一条路,其余写入仍留在审批门后。另有只读的 `agent/turn-stopping` 检查,它只提示积压过线(一行 `tidy-due` 审计 + 下个会话预热段末行一句)。`/memory stats` 打印可观测三数(重复率 / 召回命中率 / 注入量),抽屉面板里同样有这三行;成功率刻意留白,因为本仓库没有「注入之后对方是否真听懂了」这条信号源。面板上的**整理全库**按钮是排队,不是动作:它按同一套审批策略只写一行标记(`tidy_requests`,schema v7),下次会话的预热段请模型跑一次全库整理,等真的有整理落写时标记转 `done`——面板这边一条都不会合并。
- **治理:把降级走回来,把冲突按面裁决。** `restore` 把一次降级走反方向(`superseded → active`,`version` 不动,重新进入每个会话的可见集),它是脱离降级态的唯一出口。`arbitrate` 处理「同一条事实、两个来源」:在**一个面**上裁决,方向由固定表决定——能力听观察、意愿听自陈,其余五面**两条都留**并各打 `gap` 标(落差本身即证据)。表即方向,所以没有反向参数可传;同组内保留 `updatedAt` 最新者。两者与所有写路径同门:同一审批门、同一会话开关、同一桶内边界;审计也逐条留痕——`restore` 每条一行,`arbitrate` 每次降级一行(`text` 恒为 `null`,只记 id)、打标一行 `arbitrate-tag`,收尾一行 `arbitrate` 摘要写清保留了谁、降级了谁、理由是什么。
## Compatibility
| Surface | Status |
|---|---|
| Harness | DeepSeek Harness `dsh-v0.1.5-rc.2`(2026-09-09 已适配):会话信封保留 ignorable 字段但仅用于存量日志读取兼容——Session.append 仍无法盖章,门控行为不变。 2026-09-11 已对照 dsh-v0.1.5-rc.2 master checkout 核验(全部门禁链 + profile 安装冒烟)。 |
| Node | `^22.19.0 || >=24.0.0` |
| Platforms | Windows / macOS / Linux(纯 host;无原生代码、无网络) |
| Model | 任意 |
## Configuration
所有可调项均为 Schemastery `Config` 字段(可在 cordis.yml 中修改)。非法值在加载期响亮失败。在 `yammory_system` 行下覆盖。
**设置面板。** DSH 设置服务挂载时,下表除 `enabled` 外的全部字段可在 DSH 设置侧栏的插件一级项 **`yammory-system`**(与通用设置、插件等并列)中编辑;修改写入设置用户层(`settings.yaml`),无需改文件。几乎全部即时生效(写策略、语言、预算、各上限、提案、面板;`dbPath` / `auditRetentionDays` 经重开 store 生效;`retrieval.vector` 经重装检索器生效)——只有 `snapshotOrder` 需要 DSH 重载。设置服务缺失时一切回退组合配置,与从前完全一致。侧栏底部的记忆入口可在同一页面隐藏(`panel.enabled`)。
| Key | Default | Meaning |
|---|---|---|
| `enabled` | `true` | 总开关;`false` 移除服务、工具、快照、命令、面板与 answerer(设置页不可编辑——禁用的插件没有设置项) |
| `panel.enabled` | `true` | 显示侧栏底部的记忆入口;在设置页保存 `false` 后立即隐藏,无需刷新(设置页本身不受影响) |
| `dbPath` | `''` → `$DSH_HOME/dsh-memento/memory.db` | 绝对路径,或相对 `$DSH_HOME`(Windows 上回退到 `~/.dsh`) |
| `budgets.user.userGlobal` | `2000` | user 轨 user-global 层的软预警线 |
| `budgets.user.workspace` | `2000` | user 轨 workspace 层的软预警线 |
| `budgets.agent.userGlobal` | `4000` | agent 轨 user-global 层的软预警线 |
| `budgets.agent.workspace` | `4000` | agent 轨 workspace 层的软预警线 |
| `writePolicy` | `'ask'` | 默认写策略:`ask` / `auto` / `off`(模型不可见) |
| `writePolicies` | `{}` | 按轨/作用域或按来源的覆盖(如 `user/workspace`、`source:claude`) |
| `language` | `'en'` | 模型可见文本与命令输出语言:`en` / `zh` |
| `snapshotOrder` | `-50` | 快照段顺序(在 harness 身份之后、persona 之前) |
| `maxEntriesPerQuery` | `20` | 每次查询默认结果上限(硬上限 1000) |
| `commandListLimit` | `50` | 每次 `/memory list` / `query` 渲染的条目数 |
| `commandAuditLimit` | `10` | 每次 `/memory audit` 渲染的审计行数 |
| `recall.historyLimitDefault` | `8` | `memory_recall` 默认扫描的会话数 |
| `recall.snippetCap` | `5` | `memory_recall` 每个会话的片段数 |
| `recall.snippetChars` | `300` | `memory_recall` 片段字符数 |
| `recall.windowDays` | `30` | `memory_recall` 近期窗口天数 |
| `observe.days` | `14` | `memory_observe scan` 的回看天数(硬上限 90) |
| `observe.sessions` | `8` | 单次扫描采样最近多少个会话(硬上限 20) |
| `observe.perSession` | `12` | 每个会话采样几条发言,均匀分布,好让开场与中后段的改口都留得下(硬上限 20) |
| `observe.messageChars` | `400` | 单条发言超过多少字符即截断加省略号(硬上限 800) |
| `observe.totalChars` | `12000` | 整段切片的字符预算;到顶即停并报出未覆盖范围(硬上限 30000) |
| `recall.weighting.heat` | `0.3` | 热度加成上限(乘性;`0` = 关闭)。热度 = 召回次数(封顶)× 距上次召回的半衰期衰减——记忆要靠持续被召回才保得住热度 |
| `recall.weighting.heatSaturation` | `10` | 吃满热度加成所需的召回次数 |
| `recall.weighting.heatHalfLifeDays` | `14` | 热度半衰期(天):久未被召回即失温 |
| `recall.weighting.freshness` | `0.2` | 新旧加成上限(乘性;`0` = 关闭) |
| `recall.weighting.freshnessHalfLifeDays` | `30` | 新旧半衰期(天) |
| `recall.weighting.tagDiscount` | `0.5` | 词元只在 `tags` 命中时的权重(正文命中记 `1`) |
| `retrieval.vector` | `false` | 语义召回开关:`true` **且注册了真语义嵌入 provider** 时才换装向量召回——伪嵌入(哈希袋)刻意不算数,它不做语义建模、会让中文召回静默归零;否则保持零依赖 keyword 检索器(中文二字分词、任一词元命中、热度/新旧加权、相关度排序) |
| `panelEntriesLimit` | `200` | Web 面板条目分页大小 |
| `panelAuditLimit` | `20` | Web 面板默认审计行数 |
| `auditRetentionDays` | `0` | 审计保留天数(0 = 永久保留) |
| `proposals.enabled` | `true` | 每次成功压缩后自动捕获一条记忆提案 |
| `proposals.maxChars` | `2000` | 提案字符上限 |
| `proposals.maxPending` | `8` | 待处理提案上限 |
## Tools & surfaces
| Surface | Kind | Notes |
|---|---|---|
| `memory` | tool | 带 Save/Skip 指引的 add/replace/remove/consolidate/supersede/auto-tidy/restore/arbitrate/query/tidy;条目可带画像坐标(`facet` 七面之一、`level` 分领域知识水平);`supersede` 把 1..20 条并成一条带 `merged` 标的条目、旧条目降级为 `superseded`(留痕不删),`restore` 把降级条目救回,`arbitrate` 按裁决表在一个面上裁两个来源的冲突,`tidy` 返回只读整理计划;写入走审批门 |
| `memory_profile` | tool | 31 个子领域刻度上的分领域知识水平(`set` / `list` / `get`);`set` 走审批门并落审计,`tier` 由 `level` 推导 |
| `yammory-survey` | skill | 用户主动激发的画像问卷,覆盖 24 个问卷合法子板块;经 `memory` + `memory_profile` 落库。源文件:`skills/yammory-survey/` |
| `memory_recall` | tool | 有界的记忆匹配(查询按词元切分:中文二字、英文整词;任一词元命中即召回,按相关度排序)+ 近期会话历史匹配 |
| `memory_observe` | tool | 观察通道:`scan` 只读取「用户本人」旧发言的有界切片(`cwd` 精确收窄、系统注入的伪发言过滤并计数、预算缺口如实报出);`commit` 以一次审批、一次原子写落 1..8 条带证据的条目,`source` 固定 `observation` |
| `yammory-observe` | skill | 用户主动发起的行为观察,把五个仅观察面(思维方式与思辨 / 人格特质 / 情绪模式与心理强度 / 自我认知 / 决策与行动风格)经 `memory_observe` 落库。源文件:`skills/yammory-observe/` |
| `yammory-tidy` | skill | 用户主动发起的记忆整理:读只读计划、把讲同一件事的条目并成一条、旧条目降级留痕(不删、不跨桶)。源文件:`skills/yammory-tidy/`;判据表在 `references/merge-rules.md` |
| `yammory-experience` | skill | 把「干活的教训」收进 agent 轨(环境事实/约定/教训),与用户画像分家,判据只有一句:这条知识该不该每一轮都在场。源文件:`skills/yammory-experience/` |
| `/memory` | command | `list` · `query` · `add` · `remove` · `consolidate` · `restore ` · `arbitrate ` · `tidy [--days=N]` · `stats` · `proposals` · `budgets` · `audit` · `export` · `import ` · `adapters` · `observe [--days=N]` · `session [on|off]` |
| session switch | session header | 会话标题栏里的会话记忆开关,紧挨 Agent 预设(`conversation.session.header.actions`,session scope):显示当前状态并点击切换,走 `GET`/`POST /api/memento/session`(与面板路由同一条 `connection.fetch` 信任栅栏) |
| web panel | client drawer | 对记忆内容只读,且拆成两个世界:**记忆**页签是七面多边形结构树(先看分类、点开才见条目)+ 知识水位块;**经验**页签把 agent 轨按话题分桶。两侧共用搜索、预算条、可观测三数与审计尾部;另有一个用户动作按钮,只登记一条全库整理标记;侧栏入口可隐藏(`panel.enabled`) |
| settings section | DSH 设置侧栏 → `yammory-system` | 免改文件编辑除 `enabled` 外的全部配置字段;即时/重载生效时机在页面内标注 |
## MCP server
`yammory_system` 附带一个只读 stdio **MCP 服务器**(`yammory_system-mcp`),让外部 MCP 客户端(Claude、Codex 等)无需 harness 即可检索记忆库。它通过 newline-delimited JSON(NDJSON)承载 JSON-RPC 2.0——每行一个 JSON 对象,不支持 `Content-Length` 分帧。
**只读。** 数据库以 `node:sqlite` 的 `readOnly: true` 打开(不跑迁移、不写 WAL、不 bump recall-count);库文件不存在时返回空结果而非崩溃。
| 工具 | 用途 |
|---|---|
| `memory_search` | `{query, limit?}` → 排序后的条目(经检索 Provider seam 的大小写不敏感子串检索) |
| `memory_stats` | `{}` → `{total, namespaces}` 条目总数 + 按轨道/作用域概览 |
直接运行:
```sh
node bin/mcp-server.mjs
# 或从 GitHub 渠道装好之后:npx yammory_system-mcp
#(本仓库尚未发布到 npm 注册表;上面的 -p github:… 就是取包来源)
```
数据库路径取自 `$DSH_MEMENTO_DB_PATH`(绝对路径,或相对 `$DSH_HOME`);默认为 `$DSH_HOME/dsh-memento/memory.db`。
Claude Desktop(`claude_desktop_config.json`)配置示例:
```json
{
"mcpServers": {
"yammory_system": {
"command": "npx",
"args": ["-y", "-p", "github:KhalilYamber/yammory-system", "yammory_system-mcp"],
"env": {
"DSH_MEMENTO_DB_PATH": "/home/you/.dsh/dsh-memento/memory.db"
}
}
}
}
```
服务器只读:无网络、无写入、无审批门——仅检索与统计。
## Permissions & data
- **Permissions**:workshop 清单声明 `harness:tool`、`filesystem:read`、`filesystem:write`,以及 `network:none` / `subprocess:none` / `shell:none` / `python:none` / `credentials:none`。写审批走官方审批接缝。
- **Data**:本地 SQLite 数据库(`0600`),零网络、零凭据。
- **Session log**:审计完整性来自审批对(`approval/asked` + `approval/decided`)加插件自有审计表。
## Security boundaries
- **仅公开服务。** 只消费 `tools`、`systemPrompt` 与审批接缝;不改 engine / agent-loop / apiproxy / 官方 UI。
- **零网络、零凭据。** 本地数据库,POSIX 文件权限 `0600`。
- **失败要大声。** 库损坏、schema 过新或非法配置在加载期抛错;子串歧义返回结构化错误。越预警线不拦写。
- **一进程一库。** 多个会话共享 SQLite 库;共享同一 `$DSH_HOME` 的两个进程写同一文件(SQLite 锁下后写覆盖)。
## Known limitations
- **会话事件已声明、尚未发出(rc.2)。** `memory/added|updated|removed|recalled|snapshot` 已合并声明,但 rc.2 没有仓库外事件类型的注册面;一旦 harness 构建收录这些类型即自动开启发出。
- **`ask` 策略需要 answerer。** 未组合 UI/ACP answerer 时,写入失败关闭。
- **无 FTS5 索引。** 子串搜索走大小写不敏感的 `instr`(对 CJK 正确)。
- **观察面是白名单,而白名单有边界。** `memory_observe scan` 只保留 `source.kind` 为 `user` / `user-rpc` 的 `user/message` 事件;本机实测这一条会挡下全部 `user/message` 的 48%(运行时上下文、AGENTS.md、skill 目录、goal 轮次、子代理通知)。但它分不出「人打的」与「外部桥接注入、同样声明 `kind: 'user'` 的」——事件日志只带这一个信号。故单条引文只算弱证据;要下结论,须跨会话重复出现。
- **被叫作「语义」的那半边召回还不语义。** `retrieval.vector` 只在注册了真正声明为语义的嵌入 provider 时才生效,而本仓库自带的那个 provider 声明 `false`,所以今天这个开关是**按设计**回落到关键词召回。要开真正的语义召回,得先有一个本仓库尚未选定的嵌入来源。
## How it's different
| Plugin | 是什么 | yammory_system 的差异 |
|---|---|---|
| dsh-mneme | 自进化记忆,功能面宽 | 只做小语料画像:靠「按用户水平说话」差异化,不靠加功能 |
| dsh-meow-memory | 七层库、BM25 检索 | 不做检索工程:分领域水位表 + 分面裁决 |
| dsh-persona-memory | 画像注入 | 多一层:常驻画像之上再带**分领域知识水位**与**分面裁决** |
| dsh-memory-evolve | 记忆仓库 / 进化循环 | 类型化服务接缝、审批门与会话日志审计;无仓库野心 |
| dsh-mnemon | 记忆存储助手 | 协议 + 门 + 审计,而非又一个 store |
| dsh-kb-sieve | 知识库筛选 | 无检索工程:小语料子串搜索,经 `session_search`/`sessionQuery` 跨会话召回 |
| dsh-tdai-memory | 任务驱动记忆工具 | 预算按 track×layer 且在服务内强制执行,而非尽力而为 |
| claude-bridge | Claude Code 桥接 | DSH 原生;未来的 `seed(source:'claude')` 路径让桥接写入同一 store |
| dsh-external/Recall | 外部 agent 记忆 | 本地优先、零网络、走 DSH 自有审批接缝 |
| Official MCP memory examples | DSH 宣称的"memory = 外部 MCP"立场 | **原生第一方**补充:同目标、无外部服务器;两者共存 |
今天真正立得住的差异是上表最后两条:**带分领域知识水位的七面画像**(在任何检索发生之前就决定助手该用什么口吻说话),以及**分面裁决**(同一条事实有两个来源时怎么收场——能力听观察、意愿听自陈,其余五面两条都留、各打一个 `gap` 标)。
名称是 **`yammory_system`**(走 GitHub 渠道安装;尚未发布到 npm 注册表)。不是 `dsh-recall`(易与 dsh-external/Recall 混淆),也不是已删除的旧名 `dsh-memory`。
## dsh-memory-protocol v1
`yammory_system` 是 DSH 记忆协议的社区预演——官方 `ctx.memory` 接缝的一个候选形态。该协议把本插件的接缝规范化为跨插件契约:
- **Entry spec** — 两条轨道 × 两个层级 × 按 agent 隔离,外加短 `tags`(≤16 × ≤32 字符)与每次 `replace` 递增的每条目 `version`。
- **Write semantics** — 幂等的唯一子串条件写;批准即所见载荷(`replace` / `remove` / `consolidate` 携带将被改动的全文)。
- **Audit contract** — 每次写都能从 `approval/asked` + `approval/decided` + 提供方账本重建。
- **预警线模型** — 每层软预警线 / `AMBIGUOUS_MATCH` 语义。
- **Schema versioning** — 带响亮版本检查的迁移规则。
- **Spec** — [docs/protocol-v1.md](docs/protocol-v1.md)(中文: [protocol-v1.zh.md](docs/protocol-v1.zh.md));规范性 JSON Schema 见 [docs/schemas/dsh-memory-protocol-v1.schema.json](docs/schemas/dsh-memory-protocol-v1.schema.json)。
**Adapter registry** — `ctx.memoryAdapters`(`register` / `list` / `adapt` / `export`)让第三方记忆插件通过注册纯数据转换器接入协议(可逆 `register()`;导入走审批门 `seed`,导出只读)。接入指南:[docs/adapters-guide.md](docs/adapters-guide.md)(中文: [adapters-guide.zh.md](docs/adapters-guide.zh.md))。
| Built-in adapter | External format | Notes |
|---|---|---|
| `mem0` | mem0 fact collections(`{facts: [{memory, metadata?}]}`) | `metadata.category` / `metadata.tags` 成为 tags;原始 `messages` 数组被拒绝——适配器只转换、绝不抽取 |
| `hermes-memory-md` | Hermes `memory.md`(`## section` + 列表项) | 章节名成为 tags;非列表散文响亮失败 |
| `claude-code-memory-md` | `CLAUDE.md` 风格 markdown(标题、列表、段落) | 列表项与段落成为条目;章节名成为 tags |
**Conformance suite** — [test/protocol-conformance/](test/protocol-conformance/README.md):可分发用例集,任何声明兼容的提供方都能跑(`node test/protocol-conformance/run.mjs --provider ./your-factory.mjs`);本仓库 CI 以自有提供方为黄金参考运行它(`npm run test:conformance`)。
- **Upstream proposal** — [docs/upstream-proposal.md](docs/upstream-proposal.md)(中文: [upstream-proposal.zh.md](docs/upstream-proposal.zh.md)):为何官方 `ctx.memory` 接缝应采纳该协议、差异与迁移路径。
## What we learned from the terminal memories
`yammory_system` 不是 Claude Code、Codex 或 Hermes 的移植——但其设计刻意吸收了它们各自做对的部分,并拒绝有害的部分:
| Terminal memory | 做对了什么 | yammory_system 采纳了什么 |
|---|---|---|
| **Claude Code** — `CLAUDE.md` | 分层纯文本记忆文件(用户级 → 项目级),人类可读、可编辑,自动合并进每个会话 | 纯文本条目;`user-global` / `workspace` 层按会话合并;可浏览、`export`、审计的 store——透明即特性 |
| **Codex** — `AGENTS.md` | 按目录作用域自动发现并注入的指令,零模型摩擦 | 按会话 cwd 隔离的 `workspace` 层(Windows 大小写不敏感);会话开始时自动注入冻结快照 |
| **Hermes** — `memory.md` | 主动记忆保存,以及"只在工具层强制门可被后期工具注入绕过"的安全教训 | 带 Save/Skip 指引的 `memory` 工具 + 审批门控的自动捕获提案;门位于 `ctx.memory` 写方法内部,而非工具层 |
来源:[Claude Code memory](https://code.claude.com/docs/en/memory) · [Codex AGENTS.md](https://developers.openai.com/codex/cli/agents-md) · [Hermes memory](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/memory.md) · [Hermes #48181](https://github.com/NousResearch/hermes-agent/issues/48181)。
刻意拒绝的部分:隐藏地自动摘要进模型私有状态(此处压缩摘要成为等待人类 approve/dismiss 的**待处理提案**)、仓库/向量库野心,以及任何缺少人类可见审批或审计链的写入。也采纳了:Hermes 记载的"两个进程共享一个主目录写同一记忆文件"的告诫——见 Security boundaries。
## Development
```sh
npm install # node ^22.19 || >=24
npm test # node --test: 365 tests
npm run lint # oxlint
npm run test:conformance # dsh-memory-protocol v1 conformance suite
npm run typecheck # tsc --checkJs gate
npm run check:coverage # line-coverage gate
npm run check:readmes # five-language README consistency gate
npm run verify:self-contained # reject out-of-repo dependency specs
npm run verify:artifacts # artifact presence + syntax + import
```
`lib/` 零 DSH 依赖(仅 node: 内置模块);DSH 导入只出现在 `index.mjs`。
## Topics
`dsh`, `dsh-plugin`, `deepseek-harness`, `memory`, `agent-memory`, `approval`, `audit`, `sqlite`, `cordis`, `llm`
## Contributors
- [@Niuniu-Sir](https://github.com/Niuniu-Sir) — [issue #1](https://github.com/PerryLink/dsh-memento/issues/1) 中的启动崩溃报告,催生了 0.3.1 引入的 `~/.dsh` 回退。
## Upstream
This project is a fork of [`dsh-memento`](https://github.com/PerryLink/dsh-memento), originally part of the [PerryLink DSH plugin family](https://github.com/PerryLink). Upstream attribution and the Apache-2.0 licence are preserved.
[Apache License 2.0](LICENSE) © 2026 dsh-memento contributors