dsh-memory-steward
Manifest validMemory Butler: Completes the lifecycle closure for `dsh-memory-evolve` after memory is persisted — a budget watchdog, cleanup due-date reminders, a pending-approval queue with an approval Tab, and execution with backup. Memory files are observed in read-only mode; all writes are routed back to the upstream official HTTP API.
dsh-memory-steward · 记忆管家
⚠️ 已放弃使用记忆插件路线,转为使用文档管理路线(dsh-doc-kit)。
给 dsh-memory-evolve 补上记忆入库之后的那半程: 预算看门狗 → 整理到期提醒 → 模型出方案 → 你在 Tab 审批 → 带备份执行。
前置依赖:本插件是 memory-evolve 的伴生治理层,单独装它没有意义——所有执行都回调它的官方 HTTP API,
记忆的存储与单写者永远是上游。零代码耦合:只依赖 4 条官方路由(memory/delete|update|archive、memory-files)与 6 个记忆文件路径。
它解决什么问题
上游把「记忆入库」做得很完整(五轨 · 审查 · 技能 · 合并规则),但入库之后没人管:
| 你会遇到的问题 | 管家做什么 |
|---|---|
| 记忆悄悄涨到超预算,没人告诉你 | 三轨条数/字节对照预算(固定阈值,或设基准后按 ×倍率);只在超预算时往 systemPrompt 注入一行 |
| 「是不是该整理了」全靠人想起来 | 超预算或归档超量 + 距上次整理够天数 + 无待审 → 提醒里直接给出这一轮怎么跑(轻量模式先跑归档预筛,省 token) |
| 整理方案靠会话临场发挥,判完就散 | memory_propose 提交成待审批队列:红点、勾选/全选/反选/批量采纳、拒绝、恢复待审 |
| 改错了回不去 | 每次执行前把 6 个记忆文件整份备份;失败可断点续跑(已成功的 op 不重放) |
| 提案正文与执行回显把队列文件撑爆 | 三层治理:队列只留 pending + 最近 N 条已结项;正文只活在队列与 backups/;另有只追加的事件日志(一行 ≈200 B,含摘要与失败原因,不含正文) |
实测(本机 13 条历史):proposals.json 147,788 → 13,855 B;Tab 每 15s 轮询的列表接口 138,849 → 5,934 B。
它长什么样

一个 Tab 装下:库存与预算(三轨条数/字节 vs 预算)· 全自动采纳与预算基准 · 触发方式与整理参数 · 历史保留策略(最近 N 条 / M 天 / 已结项精简正文)· 整理开销审计(每轮 ≈tokens)· 待审批与历史列表。
安装
# 1. 先装伴生插件(记忆的存储与单写者)
dsh plugin --profile web add github:csyangwen/dsh-memory-evolve
# 2. 再装管家
dsh plugin --profile web add github:rezon-aki/dsh-memory-steward
# 发布到 npm 之后也可以:dsh plugin --profile web add dsh-memory-steward
重启 dsh web 即生效(cordis.patch.yml 由 bundle 清单自动注册,不要再手动 insert 同 id)。
会话视图会多出「整理审批」Tab;有待审时标题带 🔴 计数。
配套补丁:别让「整理动作」写进记忆
上游有两处会让整理意图变成记忆条目(回执),永久占注入预算——本机实测 48 条全局记忆里有 10 条是这种回执。补丁 patches/dsh-018-memory-facts-vs-tickets-patch.mjs 补上判别规则:
| 位置 | 现状 | 打补丁后 |
|---|---|---|
lib/i18n.js 的 snap.reviewStep / snap.dueWarning(每轮常驻下发的收尾指令) | 全局轨只开了一个出口 memory_suggest(语义=新增事实)。审查时发现「这三条该合并」没有操作出口,只能把动作描述成事实塞进去,你一点确认就永久落进 MEMORY.md | 补一句判别:整理动作(合并/归档/删除/清运)不是事实,不得写成记忆条目;装了整理插件就走它的提案工具 memory_propose |
skills/memory-consolidate/SKILL.md 的硬边界 | 「只走 memory 工具 replace/archive/add」——它是「一轮系统性整合」的入口技能,却把整理定义成直接改记忆 | 改成「事实与工单分开」:零散单条直改,成批整理走提案队列,工单本身不写成条目 |
边界:只改文案、不改逻辑;幂等(文件里已含 memory_propose 即整份跳过);纯文本替换,dsh plugin --profile web update dsh-memory-evolve 重装即还原。内核/插件升级会覆盖,升级后需重打——本机把它放进升级流程的 patches/ 目录,升级时按 @applies-to 自动重挂。
自己打(人类):
git clone https://github.com/rezon-aki/dsh-memory-steward && cd dsh-memory-steward
node patches/dsh-018-memory-facts-vs-tickets-patch.mjs # 默认 web profile
node patches/dsh-018-memory-facts-vs-tickets-patch.mjs web-test # 指定 profile
node patches/dsh-018-memory-facts-vs-tickets-patch.mjs --root=<dsh-memory-evolve 包目录> # 影子/临时副本
期望输出 已打补丁 2 个文件 / 6 处;再跑一次应输出 无需打补丁(契约已在)。打完重启 dsh web。
让 agent 自己打——把下面这段原样丢给它:
在本机给 dsh-memory-evolve 打「事实 / 工单判别」补丁:①
grep -c memory_propose ~/.dsh/profiles/web/node_modules/dsh-memory-evolve/lib/i18n.js,非 0 说明已打过、直接结束;② 从 https://github.com/rezon-aki/dsh-memory-steward 取patches/dsh-018-memory-facts-vs-tickets-patch.mjs;③node dsh-018-memory-facts-vs-tickets-patch.mjs(非默认 profile 加 profile 名;影子环境设DSH_HOME=<影子目录>);④ 核对输出为「已打补丁 2 个文件 / 6 处」或「无需打补丁」,并 grep 确认lib/i18n.js出现「不是事实」;⑤ 重启dsh web。补丁只改文案;若报「无匹配文本」说明上游改过这句,别强行替换。
Tab 里有什么
- 库存与预算:三轨条数/字节 vs 预算、最老条目、到期状态(超预算/归档超量/距上次整理)
- 待审批列表:勾选、全选/反选、批量采纳/拒绝;「▸ 查看详细」展开时才按需拉正文(原记忆 → 修改后)
- 历史:保留策略与「已淘汰/已精简」计数、单条删除记录、清空历史、清理事件日志(留 7 天 / 清空,都带 confirm)
- 整理开销:最近 N 轮的 ≈tokens(盘点输入 + 提案输出),超目标标红
- 配置区:自动检查 / 注入提醒 / 轻量模式 / 整理间隔 / 归档阈值 / 预算倍率 / 审计保留轮数 / 历史保留(条数·天数·精简)/ 自动采纳
三个工具
| 工具 | 用途 |
|---|---|
memory_audit | 库存/预算/候选簇/归档预筛/条目清单。deep 跑上游扫描器;archiveCheck 归档预筛(三桶:疑似已收录/归档独占/待判,最省 token);track:'all' 一次拉全量 |
memory_propose | 提交提案(单条或 proposals 数组批量 ≤20 条):archive / remove / replace / purge。match 只需唯一子串,host 解析成整条正文;执行时会按该子串再解析一次(审批期间条目被改写也能对上),单个 op 失败不再中止整条提案 |
memory_sweep_status | 到期查询(check)与计时复位(complete) |
安全边界
- 绝不直接写记忆文件:写入一律走 memory-evolve 官方 HTTP API(带
origin头);单写者永远是它。 - 执行锁:每条提案同时只跑一次——并发/重复提交会被挡掉(曾因批量按钮双击造成「已成功却标 failed」)。
- 提案期校验:
replace的新正文不能为空、不能含条目分隔符§(等到审批才炸太晚)。 - 一键自检:
node scripts/selfcheck.mjs→ 技能同步 / 状态目录可写 / 客户端 bundle 组合 / 上游写入契约 / 上游存活 / 工具注册 / 队列可读,逐项 PASS-FAIL。缺上游时报 FAIL,而不是静默失灵。
成本
插件本身不调 LLM——判读由会话里的模型做。一轮整理的开销 = 盘点清单(输入)+ 提案正文(输出),按字符 ÷2 估算,
常规轮次目标 ≤2K tokens(合并类 replace 要把新旧正文都写进 ops,一轮大重构 10K+ 属正常)。
/api/rounds 与 Tab 的「整理开销」卡片同口径。
配置
Tab 里改,落盘在 <memoryDir>/steward/config.json(默认 ~/.dsh/memories/steward/config.json):
| 键 | 默认 | 说明 |
|---|---|---|
autoCheck | true | 自动检查:12h 定时 + 回合末刷新库存 |
nudge | true | 超预算/到期时往 systemPrompt 注入一行提醒 |
lightMode | true | 提醒里优先建议 archiveCheck + deep,候选多再拉全量 |
sweepIntervalDays | 7 | 距上次整理够多少天才再次提醒 |
archiveMaxEntries | 30 | 归档轨条数阈值(超过也视为「该做一轮」) |
budgetRatio | 1.5 | 设基准后:预算 = max(固定阈值, ⌈基准 × 该值⌉) |
roundKeep | 10 | 开销审计滚动保留轮数 |
historyKeep | 20 | 队列保留最近 N 条已结项 |
historyKeepDays | 30 | 已结项早于 M 天才可能被淘汰/精简(与 N 取「且」) |
historySlim | true | 已结项正文精简(有备份即精简,正文只留 backups/) |
autoApprove | off | off / deterministic(只自动跑确定性归档)/ all |
baseline | null | 预算基准快照;设了就用「基准 ×倍率」而非固定阈值 |
纯手动模式 = autoCheck:false + nudge:false(Tab 一键):此后只有工具/API 调用才刷新、才产提案。
HTTP API
同一 webServer,带 Host/Origin 围栏(跨站请求 403):
| 路由 | 说明 |
|---|---|
GET /api/status | 库存、预算、到期状态、历史统计、技能同步状态、客户端 bundle 路径 |
GET /api/proposals | 轻量列表(不含 ops/results 正文);GET /api/proposals/:id 按需取完整 ops |
POST /api/proposals/{approve,reject,restore,purge} | 审批动作(空 ids 的 purge = 清空历史,待审保留) |
POST /api/propose / POST /api/scan | 外部提交提案 / 跑确定性重复检测 |
POST /api/config / POST /api/baseline | 改配置 / 设或清预算基准 |
GET /api/rounds | 整理开销审计 |
GET /api/selfcheck | 自检(同 scripts/selfcheck.mjs) |
POST /api/history/clear | 事件日志:{days:N} 删 N 天前、{all:true} 整文件删(只删日志) |
开发
无构建步骤:lib/index.js(host,ESM)与 lib/client.js(client,window.__ModuleLoader__.load 包装的 CJS)就是源码。
npm test # 33 例,node --test,不需要安装任何依赖(Node ≥ 20)
node scripts/selfcheck.mjs # 对运行中的实例逐项自检(加 --json 看原始返回)
node scripts/fixture.mjs seed|status|clear # 造/查/清浏览器验收夹具(原样重写,不改语义)
测试用三件套:假 ctx(收集注册的工具/路由/提示词)+ 临时记忆库 + 一个同时扮演管家 API 与 memory-evolve API 的本地服务;
客户端测试用迷你 React 把 lib/client.js 当浏览器 bundle 渲染,并断言「展开详情确实按需请求」。
- 设计文档:docs/ARCHITECTURE.md
- 人机分工的验收清单:TESTING.md
- 变更记录:CHANGELOG.md
许可
MIT。伴生插件 dsh-memory-evolve 亦为 MIT。
Comments
Loading…
From the same category
by ranxianglei
基本稳定可用 100K tokens is enough. Universal context-compression proxy for ALL AI coding agents,10w上下文足矣
★ 814
↓ 423.4k/wk
MIT
TypeScript
Oct 11, 2026
dsh plugin --profile web add billion-contextby Han-1413141
DeepSeek Harness session cost meter plugin: session/daily cost, budget, history, OpenCode Go quota, official & custom-provider balance, Codex-like token heatmap, peak/off-peak pricing with pre-switch
★ 388
↓ 23k/wk
MIT
JavaScript
Oct 10, 2026
dsh plugin --profile web add dsh-cost-meterby Nwflower
Import 14+ external agent chat histories (Claude Code, Codex, ChatGPT, Cursor, Gemini, Reasonix, opencode, ZCode, Grok Build, OpenClaw, Pi, Hermes, Kimi CLI, DSH) into DeepSeek Harness as resumable se
★ 224
MIT
JavaScript
Oct 7, 2026
dsh plugin --profile web add dsh-chat-importby Totoro-qaq
DeepSeek Harness plugin for previewable cross-preset session migration. Fixed-schema handoffs preserve state, source-model intent, and unresolved images; the original session stays untouched.
★ 165
MIT
JavaScript
Oct 11, 2026
dsh plugin --profile web add dsh-plugin-bridgeby Anionex
deepseek harness对话和代码状态回退插件 | DSH — rewind conversation and workspace state, powered by a persistent Change Ledger
★ 131
BSD-3-Clause
JavaScript
Oct 1, 2026
dsh plugin --profile web add @anionex/dsh-turn-rewindby SiriLee
DSH 插件:真正便捷无感的同窗口内对话回退,从不新建分支;自带轻量工作区备份,可一并还原文件(完整 Claude Code /rewind 语义)。 · DSH plugin: genuinely effortless in-window conversation rewind — never forking a new session; ships a lightweight workspac
★ 123
↓ 5.5k/wk
MIT
TypeScript
Oct 9, 2026
dsh plugin --profile web add dsh-rewind-plugin