npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-engram

v0.9.0

Published

Minimalist long-term memory for DeepSeek Harness, distilling symbolic-index + pi-esr ideas: zero-LLM auto-capture, a symbolic [ENGRAM] index with progressive disclosure, and an ESR-lite evidence-closure protocol (esr_task / esr_node / esr_close / esr_link

Readme

dsh-engram

中文 · English · 已交付 UI 控件清单

CI

为 DeepSeek Harness 设计的极简长期记忆插件,融合了 symbolic-index 与 pi-esr 的思想—— 目标只有一个:省 token。

  • 零 LLM 摄入 — 纯模式匹配从工具结果自动捕获有意义的事件(带书面 -m 提交信息的 git 里程碑、 关键文件编辑、反复出现的错误),另有显式 engram_store。热路径上没有任何模型调用,纯粹的操作 ——git push / git stash / 无提交信息的 commit——刻意从不记录(见下方「自动捕获策略」)。 每条写入先过一道确定性密钥脱敏器——API key、JWT、Bearer token、私钥、AWS/Stripe/Slack/GitHub token 与 key=value 形密钥一律替换为 <REDACTED:…> 标记,且在去重哈希 / 字符上限 / 落盘之前完成, 敏感内容永远进不了磁盘。测试失败用纯模式识别(npm test / node --test / vitest/pytest/jest
    • 失败行)自动捕获为 tags:["error","test"]、信号上调。DSH goal 域打通:completed/blocked 的 goal(goal/change 会话事件)自动沉淀为 handoff/error 记忆(tag:goal),目标结局不随会话消散 (读取面见 GET /api/dsh-engram/goals)。
  • 用户纠正/偏好学习(autoCapturePreferences,默认开,零 LLM) — 「AI 犯错被纠正后,教训要留存」 (correx、PAHF、Mem0 偏好提取): 一个 session/event 监听器盯 user/message,用确定性纠正/偏好句式把用户话语沉淀为独立的 preference 记忆 kind——中文(不要用X、改用X、以后统一用X…)与英文(don't use X、 switch to X、prefer X、never use X…)模式,三种方向(avoid / switch-to / prefer), 并带疑问句 / 一次性操作指令 / 记忆工具元话语过滤器抑制误报。preference 记忆在 [ENGRAM] 块里压过其它所有 kind([R] 前缀),让用户的长期规则成为每会话模型看到的第一行; 每会话上限 + 近期窗口去重与自动捕获同纪律。零 LLM、零向量、确定性纯函数——提取片段有界, 每条写入依旧先过密钥脱敏器。
  • 符号索引 + 渐进披露 — 一个紧凑的 [ENGRAM] 块(默认预算 700 字符 ≈ 175 token;每条记忆一行)在 组装提示词时注入,并按会话冻结,让请求前缀字节稳定以复用 KV 缓存。模型需要细节时用 engram_recall / engram_detail 下钻,而不是把命中的原文灌进上下文。召回对内存池做 进程内 BM25 排序(TF·IDF + 标签/短语加权 + 时间衰减因子,确定性、零依赖); 命中实体锚定的记忆时附带实体邻域关系简表(复用 esr_link:node --rel--> node · conf%); 与历史失败高度同源的新错误会唤醒旧 error 记忆(刷新 recency + 命中,向 promoteHits 爬升直至重回索引,失败不重复堆积);本地零命中时自动兜底到 DSH 自带的跨会话全文索引 (ctx.sessionQuery,按 cwd 过滤)——不另建 SQLite,完全复用宿主。当 FTS 兜底也返回空、 且查询含 CJK 中文(FTS5 中文分词整段只算一个 token)时,召回会对最近若干会话日志做 有界的子串扫描(zstd 解压 + LRU 缓存,限文件数与字节),追加命中会话的确定性 # past sessions 行。
  • 会话启动自动召回(autoRecallOnStart,默认开) — 纯拉取式设计有个被实证戳穿的盲区: 召回工具只交模型自觉,而真实会话里模型几乎从不主动调 engram_recall(实测 19 个会话数千次 工具调用只出现 ~5 次召回)。因此宿主在新会话首次组装时,用会话首条用户消息对工作区做 一次确定性 BM25 召回,把命中前 ≤3 条直接注入 [RECALL] 块(默认 700 字符预算,"少而准", agentmemory 候选①)——相关记忆不依赖模型想起来就已在上下文里。纯规则、零 LLM、 纯读不 bump 命中;superseded 过期真相不占注入槽(仍可 engram_detail 重取); 与 [ENGRAM] 一起按会话冻结保持前缀稳定。
  • 读路径激活(D) — 命中条目的单行预览被截断(>140 字符)时带 … 标记,且块尾 引导行点名该具体 id:#<id> truncated — engram_detail <id> (full) · engram_recall <query>。 模型由此知道完整记录就在一次确定性 engram_detail 之后,而不是以为预览就是全文 (实证盲区:66 个会话 0 次 engram_detail——下钻路径此前对模型不可见)。
  • 记忆间语义(supersede/contradict) — engram_store 可选收 supersedes / contradicts 记忆 id(同工作区校验)。被 supersede 的「过期真相」在召回里降级到尾部、并从 [ENGRAM] 块中剔除(新陈述占行);被 contradicts 的记忆保留排序但标注 · contradicted by <id>。 旧行永不删除——可重取,只是排得诚实。可选 autoSupersede 配置(默认关)对"实体锚定 + 替换式更新(改用/不再/no longer/switched…)"自动打 supersedes;显式 supersedes 永远优先。
  • 失败→解法闭环(零 LLM) — error 记忆带 cmd: 签名标签;同命令随后跑通时自动沉淀 procedure 记忆(fixed: <cmd> — N earlier failing runs now succeed),并把旧 error 行打上 resolved(不影响其排序),召回因此浮出解法而不是过期失败。
  • ESR-lite 证据闭环 — esr_task / esr_close / esr_link 给任务一个 draft → active → stable 生命周期,其中 stable 必须要有真实证据(artifact / evaluation / memory_ref),把"缺什么" 摊在明面上,而不是让 agent 没有证据就宣布完成。可开 verifyArtifact(默认开):非 URL 的 artifact 按工作区(= 会话 cwd)解析并在磁盘上实存校验,路径不存在则任务保持 ACTIVE、给出原因; force:true(或关掉该开关)可跳过磁盘校验——三种证据门照样必填。工具与网页表单共享同一个 证据门(store.evidenceGate),口径绝不会漂移。 任务不再是孤立节点:esr_task(entity=…) 一键挂点——自动建 ent_<slug> 节点并挂 task --relates_to--> entity 边(幂等),挂着领域锚点的任务立刻带关系; esr_dep 双写——依赖边同时进 tasks[].deps(blocker 逻辑)与 links 表,图谱里每条 任务依赖都是一等可见的边。
  • ESR 触发机制(pi-esr 对齐,混合:静态协议 + 冻结快照 + 单调渐进 actionables + 拉取) — 前缀缓存稳定是核心。模型「何时用 ESR」靠静态方法论(engram:esr-method,每轮逐字节相同); [ESR] 块 = 确定性冻结快照(会话开始定下、确定性排序、时间戳排除、明示 WILL NOT auto-refresh)+ 本会话单调渐进的 actionables:promote:/root-cause:/close:/stale:/escalate: 在它们成熟的那一刻被一次追加进块并冻结(永不回撤)——前缀只在「真正出现新决策点信息」时变化、 绝不逐轮漂移,同时保留决策点提醒(漏斗最窄处 / 复发失败 / 收工 / stale / 平衡)。实时状态仍可 拉取:esr_status(全量视图 + since_revision 增量短响应 + 派生 actionables)。 recorder 由 tools/result 订阅喂入(actionables 的数据源);P4 转化度量照常(#suggest-* 标记 + 10 分钟归因 + GET /api/dsh-engram/triggerstats)。纯规则、零 LLM。
  • 会话结束 todo 自动沉淀(draft 兜底,autoSinkTodosOnEnd 默认开) — 会话内 todo 仍是 轻量、随会话而逝的"工作记忆";但当会话在其拆解边界(session/disposed)关闭时仍挂着 pending todo,这些待办会自动转为该工作区的 ESR draft 任务(名称=todo 原文、描述「源自会话计划」、 按已存在任务名去重、受 maxTasksPerWorkspace 上限约束),计划从此不静默蒸发。落到 draft 而非 active:不占 [ESR] 的 active 行、不产生证据义务,仍需刻意的 esr_claim / esr_task 推进才变 active——「进行中默认不写」的取舍不变,只把「收尾丢数据」的缺口补上。可关(profile patch 或设置卡)。
  • 记忆 GC(pi-esr 约束) — 定时、机械、只归档的回收:TTL 过期记忆归档、超容量工作区淘汰低价值条目、 stable 任务超保留窗离开 [ESR] 表面、悬空链接边清理。工作集(active 任务引用 / 任务记忆 / 已入索引命中) 永不触碰;不硬删任何东西——归档条目保留 id、始终可重取。
  • Context GC(自动 GC = 替代 DSH 自动 compact,opt-in) — 不是记忆面板 GC:开启后接管 DSH 自带的上下文压缩 (compaction 服务),把「有损 LLM 全量摘要」换成机械驱逐 + 重取指针——扫描被驱逐轮次里的 engram/ESR 锚(#记忆id、tsk_*、ent_*、file_path),只留一行「细节在 engram_detail / engram_recall / [ESR] 里」;只有无锚轮次才走 scoped LLM 叙事兜底(gcNarrative,默认开、可关成纯机械)。 六条 GC 约束(working-set-protected / pointer-salience / no-provenance-no-evict…)全部落地;任何错误回退 默认压缩,永不破坏 compact。
  • Web 查看器 — 一个带统计的记忆浏览器和配置卡片,完全构建在 DSH 原生设置槽位上(不碰任何第三方 UI 包)。
MIT   ·   node >= 22.19   ·   host 半边 + 浏览器半边合在一包

为什么还要一个记忆插件?

对既有 DSH 插件生态的调研显示,记忆领域里"召回桥 / 审批门 / LLM 蒸馏 / 向量+图"这几个方向已经挤满了。 dsh-engram 补的是对 token 纪律真正重要的三个空白:

  1. 写入路径没有模型 — 捕获是确定性的模式匹配。
  2. 提示词里不灌全文 — 只注入有界的符号索引 + 会话启动时自动召回的最相关 ≤3 条(预算内), 更深的检索按需进行("检索到≠灌全文")。
  3. 诚实的任务闭环 — 没有证据就不能宣布 STABLE。

DSH 已经提供跨会话 FTS(ctx.sessionQuery)、存储(ctx.storageDomain)、提示词注入钩子和设置槽位; dsh-engram 只是这些能力之上的一层薄组合层,而非重新实现。

安全模型

DSH 插件生态还很年轻、缺乏背书:没有官方目录、没有签名校验,且 harness 的读写权限三档约束不了插件自身代码。因此记忆插件面对的信任何题比工具更高——它趴在你的提示词前缀上,还替你在磁盘上写东西。dsh-engram 的模型,直说如下:

  • 永远不联网。 本插件没有出口 socket、没有遥测、没有更新探针。任何东西都不可能把会话带出本机。
  • 无 shell、除一个存储文件外不碰文件系统。 不执行命令、不碰任意路径。全部数据只落在一个 storage-domain 单元 ~/.dsh/storages/dsh_engram.json(外加经 DSH 自身 ctx.sessionQuery 做的会话日志读取)。
  • 密钥在落盘之前就被脱敏。 每条写入路径——engram_store、自动捕获,以及本节的导入/恢复——都先把文本过一遍确定性的 redactText 规则引擎(API Key、JWT、Bearer token、私钥、key=value 密钥形态),之后才做去重哈希、字符上限与落盘。敏感文本永不落盘,召回时自然也不会有。
  • 要做什么坏事,必须借你 harness 自己的权限。 插件只通过你已信任的工具同款的 seam 向宿主"请求"做事;不扩沙箱策略、不拉高到 danger-full-access——你保持 profile 默认,engram 就只继承那些边界。
  • Web API 只读为主、loopback 栅栏。 /api/dsh-engram 下的 GUI 路由拒绝任何非回环调用方,除非你用 trustedHosts 显式放行某个主机名;即便放行,同源栅栏依然生效。
  • 可核验。 npm run dsh-engram -- doctor(scripts/dsh-engram.mjs doctor)报告插件被配置去碰什么;整个 store 可检视、不透明的东西为零。如果对这一段有怀疑,要查的代码就是 lib/redact.js、lib/store.js 和本插件的 cordis.patch.yml。

这不是说它是个气闸:如果你的 profile 给了 agent danger-full-access 或 shell,agent 可以用——engram 是记忆层而不是沙箱。上面这句话的意思是:dsh-engram 自己不新增任何攻击面。

数据契约:导出 / 导入

记忆不该当人质。四张表(memories / tasks / links / entities)可以用一个稳定、带版本号的机器可读格式整体倒出再恢复——重装、换机,或者(写一层薄适配器之后)搬到别的 harness / MCP 端点 / Claude Code skill,语料都跟得走。契约是带自描述头的纯 JSON:

GET  /api/dsh-engram/export?workspace=/path/to/project   # 单个工作区
GET  /api/dsh-engram/export                              # 全部工作区
{
  "meta": { "format": "dsh-engram/export", "version": 1, "exportedAt": 1724…, "workspace": "/path/to/project" },
  "memories": [ /* 全部行,含归档——备份不丢溯源 */ ],
  "tasks":    [ /* draft/active/stable + 归档 */ ],
  "links":    [ /* 类型化边 */ ],
  "entities": [ /* 图节点 */ ]
}

恢复默认幂等、破坏性操作有门禁:

POST /api/dsh-engram/import          # body: { payload, mode, dryRun?, workspace?, confirm? }
  • mode: "merge"(默认)— 只写 id 尚不存在的行,备份可以随便重复套用而不会重复;每行保留自己的 workspace。
  • mode: "replace" — 先把目标 workspace 的四张表清空,再只恢复属于它的行。破坏性操作,因此 body 里还要求 confirm: "restore"。
  • dryRun: true — 只算出完全相同的执行计划(会写什么 / 跳过什么),不写任何一行。
  • 导入遵守与 storeMemory 相同的不可变约定:记忆文本落盘前先过密钥脱敏;会破坏契约的行(缺 id/workspace、空文本、超 maxMemoryChars、merge 时 id 已存在、超工作区记忆上限)会被跳过并写进响应报告,而不是中止整批。

单工作区的恢复往返:

curl -s "http://127.0.0.1:3080/api/dsh-engram/export?workspace=$PWD" -o engram-backup.json
curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
  -H "content-type: application/json" \
  -d "{\"payload\": $(cat engram-backup.json), \"mode\": \"merge\"}"

兼容性

  • DSH 版本:>=0.1.2-alpha.2 <0.3.0-0(本版 0.7.2;已发布的 0.3.7、0.4.0 仍声明旧的 0.1.x 范围 >=0.1.2-alpha.2 <0.2.0-0 —— 见下文矩阵)
  • 最后验证日期:2026-10-27 —— DSH 0.2.1-rc.2(dsh --version)+ web profile 实机组合;npm test 483/483 通过
  • 安装方式已验证:dsh plugin --profile web add dsh-engram

一句话结论:所有已真正发布的版本(0.2.0 … 0.3.6)只支持旧版 DSH(0.1.0-rc.7 / 0.1.1 API 图,peers ^0.1.0-rc.7)。DSH 0.1.2-alpha.2 及更新版本与它们不兼容——settings/client API 族在该版本 断裂。新版 DSH 支持自 0.3.7 起提供——它是新 API 代际的第一个发布(见下文)。

| dsh-engram 发布版本 | 状态 | 支持的 DSH | 声明方式 | | --- | --- | --- | --- | | 0.2.0 … 0.3.6(npm 全量 + GitHub v0.3.3–v0.3.6) | 已发布 | 仅旧版 —— 0.1.0-rc.7 / 0.1.0-rc.8 / 0.1.1-rc.1 / 0.1.1-rc.2 | peers @deepseek-ai/dsh-*@^0.1.0-rc.7 | | 0.3.7 / 0.4.0(npm) | 已发布 | 新版 DSH,settings installSection —— >=0.1.2-alpha.2 <0.2.0-0 | engines.dsh + peers 同范围 | | 0.5.0(npm) | 已发布 | DSH 0.1.2-alpha.2 … <0.3.0-0 —— 设置卡迁移到 entry-id volatile Config(0.1.7+/0.2.x),≤0.1.5 自动回退 installSection | engines.dsh + peers >=0.1.2-alpha.2 <0.3.0-0 | | 0.5.1 | 已发布 | 同 0.5.0 —— 会话扫描修复(session.v<N>.jsonl.zstd,issue #8)、数据导出/导入 GUI、替换/冲突可视化(issue #3) | 同 0.5.0 | | 0.6.0 | 已发布 | 同 0.5.0 —— Context Ledger、BoundaryPrune/ResultPack 默认开 + 账本否决、JIT 推送、Context GC 改 opt-in | 同 0.5.0 | | 0.7.0 | 已发布 | 同 0.5.0 —— 会话 episode、恢复简报、实体页/实体卡、可重验证锚点 + 分层 TTL | 同 0.5.0 | | 0.7.1(npm) | 已发布 | 同 0.5.0 —— web 平面 Context GC 适配 DSH 0.2.0 声明式预设(14 空格缩进)、bundle patch 重新启用 host 平面 tool-result-pruner、压缩节省接入 Context Ledger | 同 0.5.0 | | 0.7.2 | 已发布 | 同 0.5.0 —— L1 边界剪枝改经 ctx.inject 武装,修掉「pruner 行比插件晚激活一帧就永久休眠」的启动时序竞态 | 同 0.5.0 | | 0.7.3–0.7.4(npm latest) | 已发布 | 同 0.5.0 —— 设置卡迁到「Engram 记忆 → 设置」tab(DSH 0.2.1 删了旧 section);修 DSH 0.2.x 上「推送腿」整条静默失效([RECALL] 启动召回、JIT 推送) | 同 0.5.0 | | 0.7.5–0.7.13 | 本地 | 同 0.5.0 —— 账本按会话落行 + gate-audit;L1 从「自己剪」转成「记账 + 归因」;压缩入账读真实事件形状;会话计数重启不清零;CLI 尊重 DSH_HOME | 同 0.5.0 | | 0.8.0–0.8.5 | 本地 | 同 0.5.0 —— 证据化 procedure、导出 DSH Skill、subagent 交接胶囊、审批门 + GUI、记忆行文件信号(⚠file-changed/⚠file-missing)、G6 门改单边 + 隐藏规格语料(Δ=+58.3pp) | 同 0.5.0 | | 0.8.6(npm) | 已发布 | 同 0.5.0 —— 修 issue #9:宿主不暴露 sessionQuery/snapshotEvents 时退回 seq+eventAt 逐条读,四项注入特性不再静默休眠;warn 报出宿主 surface;G6 第五轮 Δ=+90.0pp | 同 0.5.0 | | 0.8.7(npm) | 已发布 | 同 0.5.0 —— 推送腿落盘($DSH_HOME/engram/push-legs.jsonl)+ status 打印事件日志读法;minimal 预设不再承诺永远不会发生的自动接管 | 同 0.5.0 | | 0.8.8 | 本地 | 同 0.5.0 —— 修推送腿遥测写错目录(engram/engram/)导致状态显示「还没记录」;pushLegsPath 契约写死在一处 | 同 0.5.0 | | 0.9.0(本期 / this release) | 本地(tag,未发 npm) | 同 0.5.0 —— 产品代码只有一条 CLI 修复(--presets-dir 优先);主体是评测:G6 网络围栏(per-uid 出网白名单 + 两条前置探针)、密钥语料第 4 条自证、污染三分类与重算、G7 实测 0.2956%。不是 1.0:宿主仍 rc、G1 未测、减法债未还 | 同 0.5.0 |

API 族断裂点:0.1.2-alpha.2

0.1.2-alpha.2 是新 API 族的第一个版本,也是第一个让已发布插件失效的版本:

  • @deepseek-ai/dsh-settings 移除了 settingsNamespace() 与 installSettingsSection()(≤ 0.3.6 的每个发布都直接 import 这两个符号), 改为 settings.installSection——旧宿主端在 0.1.2-alpha.2+ 上直接加载失败。
  • Web 客户端注入集整体更换:@deepseek-ai/dsh-client-runtime 在新代际已不存在 (被 dsh-api-remotes + dsh-client-locale / -conversation / -renderer / -ui-settings-plugins 取代),设置卡此前改走 ctx.remote.settings。
  • 同一边界的伴随升级:@deepseek-ai/cordis ^4.0.1 → ^4.0.2、 @deepseek-ai/schemastery ^3.18.1 → ^3.18.2、@deepseek-ai/dsh 不再随包 发布 config/agent-presets(改为 dsh.configTrees 机制)。

web 设置卡已不依赖上面任何一项:自 0.3.7 起,配置卡通过插件自有 HTTP 路由(/api/dsh-engram/settings,与记忆 viewer 同样的同源 fetch)读写 dsh-engram settings namespace,因此在 0.1.2-alpha.2 分界线两侧都是代际无关的。

0.1.7 / 0.2.0 还有一次 settings 断裂——0.4.0 在最新 DSH 上启动被拒的 真正原因:@deepseek-ai/dsh-settings 在 0.1.7-alpha.2 再次移除了 settings.installSection(0.2.x 一路保留)。新设置模型是条目式的:可编辑字段 是插件自身 Config 的 .volatile() 字段(由 loader 校验并热提交),设置表单以 profile 条目 id(engram)为命名空间,不再需要任何“挂载”调用。0.5.0 在 installEngramSettings 里对两代际做特性检测:

  • DSH ≥0.1.7 / 0.2.x —— 34 个 GUI 旋钮即 Config 的 volatile 字段 (lib/settings.js makeEngineConfigSchema,由 lib/index.js 导出为 Config);卡片仍走同一 /api/dsh-engram/settings HTTP 路由读写条目 engram, service.settings 接缝在 loader/volatile-update 事件上把 resolved 重新同步,卡片编辑对新会话即时生效。
  • DSH ≤0.1.5 —— 照旧注册旧 settings.installSection 命名空间(dsh-engram)。

声明范围 >=0.1.2-alpha.2 <0.3.0-0 同时覆盖两代际;HTTP wire 命名空间在两代际都保持 dsh-engram(由接缝的活动命名空间驱动写入)。

所以:跑 ≤ 0.3.6 的已发布版本时请把 DSH 保持在 0.1.1-rc.2 或更旧;升级 DSH 到 0.1.2-alpha.2 之前,先升级插件到 >=0.3.7。

当前发布版本 —— 0.7.2

修复 L1 边界剪枝的启动时序竞态(真机定位:组合里多挂两个 bundle 就复现)。

BoundaryPrune 在插件安装时用严格 ctx.get("toolResultPruner") 取宿主剪枝器;而 0.2.0 的 web profile 里,剪枝器的 fiber 比插件晚激活约 100 ms(实测:dsh-context + dshmarket + dsh-engram 组合下 t0 strict=undefined / loose=object,100 ms 后 strict 才 拿到服务)。严格查找此时为空 → installBoundaryPrune 放弃 → L1 整个进程生命周期都不武装, 账本唯一的「剪枝节省」入账腿静默断掉;设备快照还会把这种"还没到"报成"行不存在",把人引向错误的排查方向。

  • 改经 ctx.inject(["toolResultPruner"], …) 武装 — cordis 在服务真正激活那一刻回调 (重载后也会重新武装),不再赌安装顺序;武装成功后立刻重写状态快照。
  • 区分「缺失」与「晚到」 — boundaryPruneAvailability 增加非严格查找:行被禁用/没装 报 no toolResultPruner service … (the bundle patch must re-enable …),只是 fiber 未激活 报 registered but its fiber is not active yet。两种原因以前在快照里长得一模一样。
  • 验证 — 用真实 profile 的 bundle 组合(含 dsh-context)在隔离 DSH_HOME 复现 armed:false,修复后同一组合 armed:true · threshold 8192;npm test 406/406。

上一发布版本 —— 0.7.1

修复 DSH 0.2.0 声明式预设下的 web 平面 Context GC 接管:旧版自动装配以 agent.cordis.yml 的 4 空格布局为锚,而 0.2.0 把预设换成 dsh-web-app/presets/<id>.patch.yml 里的 @deepseek-ai/dsh-agent-preset 声明(行在 14/16/18 空格缩进),导致 autoWebCompaction 静默跳过所有预设。

  • 结构化定位 compaction 行:找 group: true 的 compaction 组,组内按 - id: + name: 双重校验定位 stock/engram 行,替换块继承该行自己的缩进;旧版与声明式布局都 swap → restore 逐字节还原。顺带修掉旧 stock 替换串不含行尾换行、可能半改写文件的隐患。
  • 声明式预设发现:roster 不再带 path 时把 id 映射到出厂 <presetsDir>/<id>.patch.yml (DSH_WEB_PRESETS_DIR 可覆盖);无出厂文件的用户自定义声明式预设跳过并打日志。
  • status/doctor 适配:自动发现两种布局并显示布局类型;doctor 新增 autoWebCompaction=false、node_modules 预设(npm update dsh 会恢复出厂布局)、 profile patch preset-* 覆写(优先于 shipped 文件)三类提示。
  • 迁移:打开 autoWebCompaction 后重启一次 dsh web,下一次启动即幂等接管所有 stock 声明式预设;npm test 396/396。

上一发布版本 —— 0.7.0

把「记忆」从事件记录推进到可维护的当前真相:会话结束自动沉淀 episode、 新会话给恢复简报、esr_node 升级为实体页、文件锚点让过期真相可被检测。

  • 会话 episode:session/disposed 零 LLM 生成紧凑纪要(文件/命令/失败→修复/ 决策/未闭环),不进索引,每 workspace 保留 20 条。
  • 恢复简报:新会话注入最近 7 天最新 episode([RESUME] ≤240 字符 + 下钻指针)。
  • 实体页 + 实体卡:truth / timeline / open loops / conflicts / relations; 索引前置最多 2 张实体卡,engram_detail(entity=…) 下钻。
  • 可重验证锚点:带 filePath 的记忆记录 mtime/size/sha256;会话启动有界 重验证,改动/缺失 → stale(不进索引/truth,仍可 detail 重取)。
  • 分层 TTL:preference/procedure 永久、episode 14 天、error 60 天、其余 180 天。
  • 迁移:只有新写入会落锚(不回溯历史);升级后重启 dsh web;episode 要等一个 会话结束,resume brief 在下一个新会话生效。0.6.0 的账本/默认值/JIT 保持不变。

已发布的 0.4.0 声明 >=0.1.2-alpha.2 <0.2.0-0——这个范围被 semver 门槛在 所有 DSH 0.2.0-0 预发布上拒绝(<0.2.0-0 排除 0.2.0-rc.x),且其宿主设置端 仍在调用 dsh-settings 0.1.7+ 已移除的 installSection API。0.5.0 两处都修复:范围放宽到 <0.3.0-0(用 DSH 自身的 includePrerelease 检查验证过, 0.2.0-rc.2 及整个 0.2.x 线都放行);设置卡迁移到上面描述的 entry-id volatile Config 模型(并带特性检测的旧代际回退)。

| 组件 | 适配版本 | | --- | --- | | DSH runtime / host / client 包族 | >=0.1.2-alpha.2 <0.3.0-0 | | @deepseek-ai/cordis | ^4.0.2 | | @deepseek-ai/schemastery | ^3.18.2 | | Node.js | >=22.19.0 |

0.1.2-alpha.2 是这组 API 的最低版本:宿主设置注册按代际特性检测——DSH ≤0.1.5 走 settings.installSection 注册 dsh-engram 命名空间;≥0.1.7 / 0.2.x 走插件 Config(34 个 GUI 旋钮标记为 .volatile(),条目 id engram)。浏览器设置卡在两代际 都经插件自有 HTTP 路由(/api/dsh-engram/settings,见上文 Route B)读写。完整回归 (npm test 396/396,含新增的 volatile-Config 模型 settings-v2 覆盖)在 DSH 0.2.0-rc.2 依赖集(cordis 4.0.4 + schemastery 3.18.4 + cosmokit,与全局 DSH CLI 同版本) 上通过;.volatile()/loader 热提交路径与 describe 侧投影已针对真实 dsh-settings 0.2.0-rc.2 工具函数验证;并在隔离的 dsh 0.2.0-rc.2 profile 上完成了真机启动烟测并 通过:插件启动无版本范围拒绝、设置卡表单以条目 engram 对外提供(全部 34 个 GUI 旋钮,含 trustedHosts)、/api/dsh-engram/settings 的 GET → PUT(mutate ops, revision 0→1)→ unset 往返落盘并读回。旧的 0.1.0-rc.7 与 0.1.1 API 图不在 本发布版本的兼容范围内。

如需按验证版本安装 DSH:

npm install --global @deepseek-ai/[email protected]
dsh --version

安装

# 从 GitHub(本仓库)
dsh plugin --profile web add github:skepsun/dsh-engram

# 发布到 npm 之后
dsh plugin --profile web add dsh-engram

# 本地开发(符号链接——改动立即生效)
dsh plugin --profile web add link:/path/to/dsh-engram

然后重启 dsh web。数据保存在 ~/.dsh/storages/dsh_engram.json。

npm 与 GitHub 两种装法都不需要手动补依赖:pnpm 会自动安装 zod, 并把可选的 @deepseek-ai/* peers 嵌套装进插件自身的 node_modules,CLI 也会 自动把插件登记进 profile 的 dsh.profile.bundles。下面的 setup-links 只在 link: 开发工作流里需要——pnpm 故意不为符号链接目录安装依赖。

需要新建会话才能看到注入的 [ENGRAM]/[ESR] 块和全部工具——提示词与工具注册表都是按会话装配的。

link: 安装的依赖准备

符号链接安装的插件从自身 checkout 的 node_modules 解析 import,而这层依赖 不被 git 跟踪,换机器(尤其 Windows)会报 ERR_MODULE_NOT_FOUND: Cannot find package 'zod'(接着是 @deepseek-ai/* peers)。 一条命令重建依赖层:

cd /path/to/dsh-engram
node scripts/setup-links.mjs     # 把 @deepseek-ai 工作区包软链进 node_modules,
                                 # 并安装 zod(优先复用 harness pnpm store,
                                 # 找不到则回退 `npm install`)

脚本会自动定位 harness:../deepseek-harness(仓库上一级平级),也支持「仓库父级平级」布局 (如 E:\deepseek-harness 与 E:\kototoro_demo\dsh-engram)——都找不到再用 DSH_HARNESS_DIR 指定。 node scripts/setup-links.mjs --check 只打印状态不写入。

在 Web 端能得到什么

重启后,全部落在 DSH 原生设置界面里:

  • 侧边栏「ESR 看板」入口 + 全屏看板 — 侧栏(New Session 下方)新增一行 ESR 看板 入口,右侧带实时活动任务数徽标(30s 轮询 /overview 汇总各工作区 active 任务)。点击在中间列打开全屏看板:草稿 / 进行中(证据缺口) / 就绪(证据齐) / 已闭环 四列 + 工作区筛选 + 搜索 + 内联新建表单 + 每张卡片的「补齐证据 → 关闭」表单(与 esr_close 同一证据门:artifact + evaluation + memory_refs)。头部带「看板 / 图谱」切换:图谱视图复用完整的关系图谱(esr_node/esr_link 力导向图,实体圆节点 + 任务勾选徽标,支持拖拽/缩放/点选查看关系明细),跟随工作区筛选,20s 轮询保持实时。入口与看板按 task-board 的 DOM 级挂载惯例自愈(MutationObserver 重插/重挂),并与 task-board / ssh 面板做跨面板互斥(打开本面板会关掉对方,点侧栏会话/项目行自动回到对话)。对话子树始终挂载在下方、由 html[data-dsh-engram-board-active] 控制显隐,切换零状态丢失。

  • 输入框上方的「任务」统一条 — 接管 DSH 内建 todo 工具的自己同款 dock 槽位 (同一个 conversation.input.dock 单元格 / id: todo、更低 priority,从而遮蔽内建 TodoPanel),把两套任务平面合并成一个现代化控件:会话当前计划(todo_write 的 todos 投影)+ 工作区持久 ESR 任务(证据缺口徽标 + 内联「补齐证据 → 关闭」表单)

    • 关系图(以 节点 → 关系 → 节点 芯片呈现,实体/任务名自动解析)。有内容才显示, 15s 轮询保持实时;若 loopback 围栏的 API 不可达,内建计划仍照常渲染(只是不显示 ESR 部分)。 条首有工作区切换 chip:默认跟随当前会话(标题注明),下拉可把 ESR 任务/关系的来源固定到任意 工作区(打 ✓ 标记),再点 × 或「跟随会话」即恢复;切换即时重取,内置 todo 仍属本会话——纯 UI 焦点 切换,不动模型会话上下文(注入块按会话冻结,前缀稳定)。
  • 设置 → Engram 记忆 — 独立的一级设置页签(位于「插件」之后),不再是「插件」页里的子 tab;默认 「全部工作区」视图完整展示所有工作区的记忆/任务/关系(按工作区分组,工作区下拉 + 上一/下一工作区 翻页;记忆表格另行 10 条/页分页 + 跳页下拉,仅「类型 / 内容 / 操作」三列——正文列占满,时间、 标签、signal/hits/TTL 等全部折叠进内容行内(meta 行 + 标签行),正文限高三行省略、 行内「展开全文/收起」与 hover 均可看全文,归档/删除按钮竖向堆叠)。概览统计卡片(各工作区/类型的计数、自动捕获总量、各工作区 [ENGRAM] 索引 token 估算、GC 累计统计)、可搜索/可过滤的记忆表格(含归档与删除操作)、ESR 任务看板(「新建任务」 表单 + 点击「填写证据关闭…」补 artifact/evaluation/memory_ref 转 STABLE)、节点与关系清单 (节点 = 模型用 esr_node 登记的领域对象,如包/服务/仓库/概念;关系 = esr_link), 以及一个独立的 关系图谱 页签:手写 SVG 力导向图(无第三方图库,保持 bundle 纯净), 实体为圆形节点、任务为勾选徽标、关系按类型着色带方向箭头;支持拖拽节点/平移/滚轮缩放/重组, 悬停高亮邻域、点选节点在悬浮面板查看其全部关系与关联对象,悬空链接(端点缺失)单独计数提示。 以及一个 注入预览 页签:用与 systemPrompt 完全相同的纯函数实时渲染模型每个会话看到的 [ENGRAM] 索引块(order 40)与 [ESR] 任务/闭环块(order 41),终端风双栏展示(行级着色: 块头/任务行/drill 行/escalate 提醒高亮),附行数·字符·~tokens 成本与记忆/任务/关系/节点计数芯片, 每 20s 自动刷新、可一键复制注入块原文(新增 GET /api/dsh-engram/preview?workspace=…)。 以及记忆 GC 面板(dry-run 开关 + 运行按钮 + 指针报告)。 任务卡片(看板与 ESR 页)都带 证据进度环:一个三弧 SVG 圆环对应 artifact · evaluation · memory_ref 三道闭环门——全绿=证据齐可闭环、琥珀=有缺口、灰=尚无证据; 看板头部还有一个聚合环,显示全部进行中任务的证据完备度(%)与就绪数,一次看清整盘闭环进度。 纯 SVG 实现(无图表库,保持 bundle 纯净)。 以及一个 遥测仪表盘 页签:把 /stats 的真实调用累计(工作区 × 天滚动)画成纯 SVG 仪表盘——三枚大圆环 直读 ESR 主动性(与 escalate 阈值 0.34 比对,偏低标橙并提示)、召回命中率、detail 转化, 外加一块 Context Ledger 面板(净 token、节省/注入/重写罚金三卡、近 14 天净收益红绿柱), 五张小指标卡(累计调用 / esr / 记忆 / 平均命中每查询 / 失败),近 14 天 mem-vs-esr 堆叠柱状图 + 工具调用 Top 8 横向条形图(mem 蓝 / esr 紫,与全文配色一致),20s 自动刷新,样本不足(<10 次)自动标注。 以及 详情侧栏(主从布局):任务 / 记忆 / 节点 / 关系行都可一键在右侧打开详情卡——任务含 状态徽标、证据进度环、完整 id/时间线、缺口清单、可跳转的记忆引用与「补齐证据→闭环」表单(独立于行内 表单,成功后联动刷新);记忆含全文、标签、signal/hits/TTL/来源会话元数据;节点含全部入射/出射关系 (按类型着色 + 方向 + 置信度);点击任务里的记忆引用可直达该记忆详情,找不到时给提示。 POST /api/dsh-engram/tasks 与 POST /api/dsh-engram/tasks/close(与 esr_task / esr_close 同一证据门)。 模型侧的主动行为由 [ENGRAM]/[ESR] 注入块驱动:多步工作即时建任务、反复出现的领域对象即时登记节点、相关任务/节点即时互连。

真实行为观测(agent 遥测) — ESR 页顶部新增「agent 行为观测」面板:每次模型调用 engram_*/esr_* 工具都实时累计到 按(工作区 × 天)的 usage 滚动行(新增 usage 表 + GET /api/dsh-engram/stats),折算成指标: ESR 主动性 = esr 工具调用数 /(记忆 + esr 工具调用总数);召回命中率 = 有命中的 engram_recall 次数 / 总次数; 平均命中/查询;detail 转化 = 命中召回后很快跟一次 engram_detail 的比例(会话内 8 事件窗口);失败数按工具记。 面板同时列出各工具调用计数与最近 14 天逐日滚动。这些是真实会话的真实数字——想提升 ESR 主动性, 就观察面板上 esr 占比并调整注入提示。

  • 设置 → Engram 记忆 → 「设置」tab — 配置卡默认展开(DSH 0.2.1 去掉了 settings.plugin.item 槽位,旧的「插件 → 插件配置」位置不再渲染)。同一张卡、同一套传输: 标题 + 一行说明 + chevron,展开后 ~12 个选项分四组——捕获与检索 / 索引 / 生命周期与 GC / 安全。改动对新会话生效(已冻结的块保持不变);Discard / Save,标题栏带「未保存」徽标。 卡片走插件自有 /api/dsh-engram/settings 路由(不经过 isLoopback 围栏), 经授权隧道访问 GUI 时也能改。
  • 设置 → 插件 → 插件配置 → dsh-engram(仅 DSH ≤ 0.2.0,旧 settings.plugin.item 座位)— 与内置「终端 / Agent 循环 / 网页搜索」同款的 默认折叠卡片:标题 + 一行描述 + 箭头,点击展开/收起;展开后常用 11 项 + 高级分组按 「捕获与检索 / 索引 / 生命周期与 GC / 安全」四个分组展示。改动对新建会话即时生效 (已冻结的块保持稳定);支持放弃修改 / 保存,有未保存改动时标题上出现「未保存」徽标。 卡片通过连接自身的 settings RPC 直连命名空间(不走 isLoopback 门控的 scope),因此即使 GUI 经运营商授权的隧道访问也保持可编辑。

浏览器半边由 DSH 的 client-module loader 直接从本包提供(dsh.client + exports["./client"],无需重建 web 应用);数据来自 loopback 围栏保护的 /api/dsh-engram/* 路由族。围栏默认关闭隧道访问;如需经授权的 隧道域名访问记忆查看器,把域名加进插件的 trustedHosts 配置(如通过 registry 或 profile patch):

// patch/engram.json
{ "engram": { "trustedHosts": ["cream-club-fragrances-caught.trycloudflare.com"] } }

修改 client/src 后重建 bundle:

npm run build:client

测试与评测

npm test    # 381 项单元测试(含 usage 滚动 / /stats 路由 / Context GC / ESR 触发 / BoundaryPrune / Context Ledger / JIT 推送)
npm run eval  # 离线召回 + 结构基准(确定性语料,跑真实 store/recall 路径)

另有三个会话语料分析工具(零 LLM、确定性,读 ~/.dsh/sessions 真实日志):

node eval/oracle-analysis.mjs             # 浪费源量化:结果重放暴露 / 融合候选 / 机制激活率
node eval/simulate-boundary-prune.mjs     # L0 反事实仿真:边界剪枝的预期节省与偿还门扫掠
node eval/dryrun-boundary-prune.mjs       # BoundaryPrune 全量干跑:真实激活面与节省

npm run eval 的检索部分参照 LongMemEval 的问答式评测:受控语料(ASCII + CJK、标签/实体/时间戳已知), 对真实 domain.recall() 逐一校准 Precision@k / Recall@k / MRR / Hit@1(probe 覆盖 tag 精确、子串、 多词、CJK、短语唯一、标签排序、负样本无回);结构部分借鉴 StructMemEval:精确去重率(同文本存 3 次折叠为 1)、 实体锚定覆盖率、节点/链接卫生(无悬空链接)。数字诚实、非调优——任何人跑出来都一样,复现即所得。

两层「真实测试」的分工:npm run eval 回答「检索层本身有多好」(确定性、可复现); /api/dsh-engram/stats + 观测面板回答「真实会话里模型实际怎么用」(ESR 主动性、召回命中率、detail 转化), 两者结合才能判断:召回层没问题但命中率低 = 模型没学会问;反之亦然。

工具

| 工具 | 用途 | 类型 | |---|---|---| | engram_store | 显式存入一条记忆(kind、tags、可选实体锚点、可选 supersedes/contradicts id,可选 source/conditions) | 写 | | engram_recall | 工作区记忆的确定性关键词召回;可选 search_sessions 跨会话 FTS;可选 scope=global/recallScope 跨工作区召回(带 [W:<ws>] 来源标记) | 读 | | engram_detail | 一条记忆 id 的完整记录(来源、标签、命中数) | 读 | | esr_task | 创建任务实体(draft → active) | 写 | | esr_close | 按证据协议关闭任务(artifact + evaluation + memory_ref) | 写 | | esr_link | 在两个实体之间添加类型化关系(迷你图) | 写 | | esr_dep | 在任务间添加依赖边(blocks / relates-to / parent-of) | 写 | | esr_claim | 原子认领任务(assignee + claimedAt,draft → active) | 写 | | esr_unclaim | 释放已认领任务的 assignee | 写 | | esr_ready | 列出可认领任务(无 blocker、无人认领) | 读 | | esr_status | 拉取实时 ESR 状态 + 派生提示(since_revision 增量短响应) | 读 | | esr_node | 创建/更新实体节点(稳定符号) | 写 | | esr_gc | 运行本工作区的记忆 GC(dry_run:true 预览不落库) | 写 | | esr_model | 工作区预计算心智模型(brief/full,max_chars) | 读 |

[ESR] 块是每会话冻结快照,绝不中途刷新——要最新状态调 esr_status。

GC:两块——记忆面板回收 + Context GC(替代自动 compact)

记忆面板回收(存储维护)

定时回收(gcIntervalHours,默认 24h)+ esr_gc 手动触发 + GUI 按钮,按 pi-esr 方式把存储保持在 有界内——机械、工作集保护、只归档:

  • TTL 过期记忆归档(软删;id 保留,可通过 GUI 的 archived 筛选检索);
  • 超容量工作区淘汰最低价值的非保护记忆;
  • stable 任务超 gcStableRetentionDays 归档、离开 [ESR];
  • 两端点都已消失的链接被清理(悬空边)。

GC 永不触碰工作集:active 任务 memory_refs 引用的记忆、task 类记忆、已入索引的命中 (hits >= promoteHits)。用 esr_gc + dry_run: true 先预览。不硬删——报告的末尾为所有 归档项附上重取指针,归档可恢复、不是丢失。

Context GC(替换 DSH 自动 compact,opt-in)

DSH 默认的上下文压缩是有损 LLM 全量摘要(compaction-basic):被驱逐的历史被压缩成散文, 不可查询、摘要本身还烧 token。dsh-engram 的自动 GC 替代它:ContextGcEngine extends BasicCompactionEngine 只重写唯一的 summarize() 钩子,把摘要正文换成:

  1. 扫描被驱逐消息的 provenance 锚——engram_store/engram_recall/engram_detail 回显的 #记忆id、esr_* 涉及的 tsk_*/ent_*、file_path 锚(esr_gc 等管理工具不算锚);
  2. 指针摘要:每条被驱逐类别都带显式重取调用(engram_detail(id: "…") / engram_recall(query) / [ESR] 块 / esr_ready),active 工作集在摘要里复述不驱逐;
  3. 兜底叙事:只有无锚轮次(纯对话/推理)才走 scoped LLM 摘要(gcNarrative,默认开;关掉后整条 路径零 LLM,无锚轮次截断原文保留)。

触发时机完全跟随 DSH 现有 compact(step pressure / context-overflow / /compact);锁、回放校验、 tool-call/result 配对、token 定价全部复用基本引擎。任何错误 → 回退默认压缩,永不破坏 compact。 装配即注册 compaction 服务,卸载/reload engram 自动还回默认引擎。自 v0.6 起默认不接管: 默认挂裸 BasicCompactionEngine(宿主 LLM 摘要),要换成指针摘要需显式打开 gcReplacesCompaction(web 预设还需 autoWebCompaction)。

收缩闸门(shrink gate):harness 拒绝任何不比被驱逐片段更小的 checkpoint(summary is not smaller than the shadowed content),否则压缩回滚、上下文永不缩小、最终触发模型侧溢出。Context GC 据此自预测闸门:用 host tokenMeter 复刻 harness 的 framing 估算(实测逐 token 一致),把指针 摘要/叙事体按被驱逐 span 的 token 预算动态裁剪尾部(指针头与工作集保留,细节仍在会话日志可 重取),保证 checkpoint 严格缩得更小、压缩真正提交——不出现"start 涨、summary 不涨"的假接管。 完整用法见 docs/CONTEXT-GC-GUIDE.zh.md(从 0 开始的使用教程)。

启用入口(这一节就是答案:该功能开在哪)

Context GC 的装配在两个平面,但两个开关都是 opt-in(默认不接管):

  • host 平面(headless / TUI / base 型 profile)——开箱即用,无需任何配置: 主插件 lib/index.js 在 ctx.effect 里直接 mountCompactionEngine(ctx, resolved, { readWorkspace }) → new Engine() 注册 compaction 服务; 配合插件 patch 禁用基座 compaction-basic 行,engram 即为该平面唯一 provider。
    • gcReplacesCompaction: false(默认)→ 挂裸 BasicCompactionEngine(DSH 默认 LLM 摘要), compaction 服务永不缺席;
    • gcReplacesCompaction: true → ContextGcEngine(机械驱逐 + 重取指针,opt-in);
    • 开启:profile patch 里给 engram 行加 config: { gcReplacesCompaction: true },或在设置卡打开。
  • preset 平面(web profile)——显式开启后覆盖全部 stock 预设:web 面把 compaction 放在 agent preset 的 isolate realm(shipped 预设自挂 compaction-basic),host 条目进不去、profile patch 也 够不到预设文件(mountPreset 的 Include 不带 patches——已对源码核实)。所以插件在启动时 (agentPresets 服务就绪后)自动改写每个仍处于出厂 stock 布局的预设——默认预设 + 整张 roster, 两代预设布局都覆盖:旧版 <root>/<id>/agent.cordis.yml 组合文件(DSH ≤ 0.1.x,行在 4 空格)与 声明式 @deepseek-ai/dsh-web-app/presets/<id>.patch.yml(DSH ≥ 0.2.0,行在 @deepseek-ai/dsh-agent-preset 声明里、14 空格缩进;没有出厂文件的用户自定义声明式预设不碰): 把 compaction 组里的 compaction-basic 行换成 dsh-engram/compaction。行按 YAML 结构定位 (带 group: true 的列表项)、按 - id: 与 name: 双重校验,与缩进列数无关。这一自动装配是:
    • 默认关(opt-in)(autoWebCompaction: false;设置卡「记忆 GC」可开),开启后幂等——已替换则跳过; 关掉的含义:只是在之后的启动时不再自动接管(headless/TUI/base 的 host 平面不受影响)—— 它不会还原之前已接管的预设,要还原用 npm run web-compaction:revert;
    • 逐预设判定,只碰 stock 布局——用户自定义过 compaction 组的预设,以及根本没有 compaction 组的 预设(如 shipped minimal),一律不写、只记日志;
    • 带备份 + 严格校验:每个文件写前在旁边留 .engram.bak(create-only,保留首次 原件;旧版布局为 agent.cordis.yml.engram.bak,声明式布局为 <id>.patch.yml.engram.bak), 写后重读校验,任何一步可疑即回滚该文件;改写失败只 warn,该会话仍用 DSH 默认摘要, 永不影响宿主。
    • 配置真实传导:写进预设行的引擎配置来自设置卡/配置里的 gcReplacesCompaction 与 gcNarrative——改了这两个开关,下次启动会自动把已接管的行刷新成新配置(幂等重写), 所以设置卡对 web 平面同样生效,不再硬编码 true/true。
    • 手动的完全等价物(预览 / 审计 / 卸载前回归,随 npm 包发布的 CLI,自动发现两代预设布局—— 旧版根、出厂声明式预设与上次启动记录的路径;--presets-dir <dir> 覆盖声明式目录探测、 --file 指定单个):
      npx dsh-engram status     # stock → 未动;wired → 已接管;custom → 不碰
      npx dsh-engram doctor     # status + 按缺口排序的下一步建议
      npx dsh-engram enable     # 等价于启动时自动装配(通常 no-op)
      npx dsh-engram revert     # 还原全部预设的 stock 行(卸载 dsh-engram 前先跑这个)
      (仓库内 npm run web-compaction:* 是同一 CLI 的别名。) 替换后的 compaction 组形如:
    - id: compaction
      name: cordis:group
      group: true
      isolate:
        compaction: true
        toolResultPruner: true
      config:
        - id: engram-compaction       # ← 替换原 compaction-basic
          name: dsh-engram/compaction
          config:
            gcReplacesCompaction: true   # 来自设置;false=该 session 用默认 LLM 摘要
            gcNarrative: true            # 来自设置;false=纯机械无 LLM
        - id: command-compact
          name: '@deepseek-ai/dsh-command-compact'
        - id: tool-result-pruner
          name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
          # 原有配置保留
    ⚠️ 卸载前先 revert:预设引用 dsh-engram/compaction 后,卸载 dsh-engram 会让该行悬空、 web 会话挂 loading。所以卸载 engram 前先 npx dsh-engram revert(还原全部预设, 或逐个恢复各自的 .engram.bak)。harness 大版本升级会覆盖 shipped 预设,悬空引用随之自愈。

从 npm 安装后的第一印象(可感知 / 易引导 / 易配置)

  • 半自动(opt-in):默认保留 DSH 自己的摘要;在设置卡打开 gcReplacesCompaction(host 平面)与 autoWebCompaction(web 预设)后,启动一次即由 mountCompactionEngine 接管、并把全部 stock 预设改写成 dsh-engram/compaction。开启后无需再手动改文件。
  • 可感知:插件启动时把权威状态写到 $DSH_HOME/engram/context-gc.status.json (host 平面模式 + web 平面每个预设的接管结果 + 生效配置)。随时 npx dsh-engram status 或 npx dsh-engram doctor 查看;web 记忆看板(ESR 任务看板)头部也有 一枚状态徽标("Context GC·主机 ·N 预设",来自 overview API)。启动日志也有两行关键确认: engram context-gc: compaction = Context GC … 与 engram web-provision: wired Context GC into preset …。
  • 易配置:一个设置卡(「记忆 GC」区)管全部:autoWebCompaction(web 自动接管,默认关)、 gcReplacesCompaction(用 Context GC 还是宿主摘要,默认关)、gcNarrative(叙事兜底开关)—— 改动后 dsh web 重启生效,web 预设行会被自动刷新成新配置。

验证是否生效:dsh web(或对应 profile)重启后——

  • host 平面(headless/TUI/base):启动日志出现 engram context-gc: compaction = Context GC (mechanical eviction + re-fetch pointers);
  • web 平面:日志出现 engram web-provision: wired Context GC into preset "standard" (…); restart dsh web so sessions pick it up (每个被接管的预设一行);或 npx dsh-engram status 显示 wired;任意预设的会话内 command-compact/压力触发即走机械驱逐 + 重取指针。
  • (若见 … keeping the existing compaction service 说明同域已有 provider、未替换成功;web-provision … skipped (custom) 说明某预设是自定义/无 compaction 布局、未被触碰;dsh-compaction-basic unavailable 说明环境缺依赖,自动回退默认压缩。)

BoundaryPrune(子任务边界剪枝,默认开 + 账本否决)

Context GC 管「压缩的摘要内容」,BoundaryPrune 管「确定性剪枝的触发时机」—— 在 todo 完成推进 / goal 终态这些子任务边界,主动调用 DSH 自带的 toolResultPruner(确定性 surface-replace,零 LLM),把早已超阈值的旧工具 结果剪掉头尾保留,省掉它们在后续每个请求里的整段重放。两个开关互相独立。

  • 证据链(docs/ORACLE-ANALYSIS.zh.md + docs/PROPOSAL-resultpack.zh.md):97 个真实 会话实测,工具结果重放暴露 2.77B–7.53B 字符(≈692M–1.88M token),96% 的 结果字节来自 bash/read/run_code;反事实仿真显示 todo 边界覆盖 79% 的暴露, 且偿还门在所有配置下提升净收益 12–32%。
  • 偿还门:剪枝会重写前缀(KV 缓存击穿一次),只有当会话预计还要跑 boundaryPruneMinRemaining(默认 50)个以上请求时才 fire——预计长度用 workspace 历史先验 + 超过后 ×2 外推(有界乐观),长会话不会被挡死。
  • 诚实激活面:goal=0 且无 todo 推进的会话天然不触发(无边界不剪,零副作用); 全量干跑 77 会话激活 38%。pruner 服务缺席即自动禁用并打一条日志。
  • 边界源:默认 todo 完成推进 / goal 终态事件;可选空闲步数边界 (boundaryPruneIdleCadence,默认 0=关)——覆盖约 62% 从不动 todo/goal 的 会话(侦察:eval/recon-idle-boundary.mjs;反事实:eval/simulate-idle-cadence.mjs 显示 cadence 50 时节省 +85%),仍受偿还门约束。
  • 阈值覆盖:boundaryPruneThresholdChars(默认 0=宿主 8192)。设为 2048 并配更小保留边缘(boundaryPruneHeadChars/boundaryPruneTailChars)可更早 开剪——T2048+小边缘在真实语料上首剪节省是宿主默认的 2.4 倍(10.14M vs 4.23M 字符)。降阈值在 resultPack 开启时安全(被剪中段有归档兜底)。
  • 默认开:boundaryPrune: true;false 是 opt-out。自适应闸门 (boundaryPruneAdaptive: true,默认开)让 Context Ledger 在该 workspace 真实剪枝后 净收益为负(≥3 次)时自动停剪——证据只能关、不会自行开。启动日志出现 engram boundary-prune (todo @N reqs): pruned …;被账本否决时出现 engram boundary-prune: ledger gate holds for …。

ResultPack L2(结果归档 + result_recall,默认开)

让 BoundaryPrune 剪枝无损:每个被剪工具结果的被移除中段,按与记忆写入 相同的规则脱敏后归档到 ~/.dsh/engram/resultpack/<callId>.json,并在剪枝 节点尾部追加 handle——[middle archived: result_recall(<callId>) 可取]—— 模型知道完整结果就在一步之遥。result_recall(callId, offset?) 按页返回 归档中段(渐进披露,与 [ENGRAM] → engram_detail 同一哲学,也是 SoL-Pi 机制③ ObservationPack 的完整形态)。

  • 构造性无损:L1 剪掉的是重放、L2 保留的是可随时取回的原文——「模型回头 找被剪结果」的失败模式归零。
  • 成本受控:归档在记忆域之外(大块内容永远不会撑大 domain JSON 或 [ENGRAM] 索引);保留期 resultPackRetentionDays(默认 7 天)按 mtime 清理, 搭 GC 同一节奏。
  • 自我禁用:只开 L2 不开 L1 将无内容可归档,故不注册工具并打一条警告。
  • 默认开:resultPack: true(与默认开启的 L1 配对,保证默认剪枝无损); 关掉后 L1 仍可工作,但被剪中段不可召回。开启时启动日志出现 engram result-pack enabled: result_recall(callId, offset) registered。

激活遥测(SoL-Pi M15/C13)

机制必须可证明在激活,休眠机制默认关。/api/dsh-engram/stats(以及 GUI overview)现在返回 activation: { boundaryPrune, recall }:

  • boundaryPrune——BoundaryPrune 真实 fire 的累计持久记录(fires / prunedResults / charsRemoved / byKind todo|goal|step / lastFire),每次剪枝 落盘到 ~/.dsh/engram/boundary-prune.status.json,与 resultPack 无关。
  • recall——召回漏斗的注入腿:实际进过会话的 [RECALL] 块数量 (recall-injections.json),与从 session log 已统计的另一端 (engram_recall 查询 → 命中 → engram_detail 下钻)闭合,可看到 注入→查询→下钻的完整激活。

Context Ledger(净收益账本)

把「省 token」变成可核对的账。每个模型请求记一笔:注入的 [ENGRAM]/[RECALL] 与 [ESR] 块按存活请求数计入成本;被 BoundaryPrune 剪掉的结果按后续请求数计入 节省;每次剪枝按 (1 − ledgerCacheDiscount) 计一次前缀重写罚金(KV 缓存击穿)。 GET /api/dsh-engram/stats 与 /overview 返回 ledger:

  • totals — requests / injectedChars / avoidedChars / rewriteCount / rewriteChars / netChars / netTokens(net = avoided − injected − rewriteChars × (1 − discount));
  • byWorkspace / byDay — 按工作区、按天的同一口径,byDay 倒序;
  • openSessions — 仍在累计、尚未落盘的会话数(进程重启最多丢 flushEvery 个请求的账)。

GUI「遥测」页签直接画这块账本(净 token 大数字 + 节省/注入/重写罚金三卡 + 近 14 天红绿柱), 记忆概览页也多一张「上下文净 token」卡。落盘在 ~/.dsh/engram/ledger.json(原子写、按天滚动、 delta 落盘),进程内只做整数累加,热路径零 I/O、零模型调用。默认 ledgerEnabled: true、 ledgerCacheDiscount: 0.1;关掉 = 不挂监听、不写文件。

节省的两条入账腿(v0.7.1 补齐,此前只记成本所以净值恒负):

  1. L1 边界剪枝——toolResultPruner 剪掉的 chars,按后续请求数计入(需要有 host 平面的 toolResultPruner;DSH ≥ 0.2.0 的 web profile 把该行移进 agent preset 的 isolate realm,本 bundle 的 cordis.patch.yml 会重新启用 host 行,状态快照里 boundaryPrune.armed 可核对);
  2. 压缩(Context GC)——每次 checkpoint 用「被替换区间可见字符数 − checkpoint 字符数」 入账,host 平面与 web 预设域(经 engramLedger 服务桥接)走同一个账本。

口径诚实:token 按 chars / 4 估算,不含 provider 实际计费与模型质量差; 某工作区还没发生过剪枝/压缩时「节省」就是 0,净值等于注入成本 + 重写罚金(负值正常), 遥测页会直接提示这一点。

JIT 推送(v0.6-C)

拉取式召回被实证休眠(112 会话仅 24 次 engram_recall、8 次 engram_detail),所以 v0.6 增加按事件推送:三个确定性事件,命中才推、每次一行、每会话最多 3 行(jitMaxLines, 每行 jitMaxLineChars=220):

| 事件 | 触发条件 | 推什么 | |---|---|---| | 错误复发 | 同一 cmd: 签名第二次失败,且已有 error/procedure 记忆 | 该记忆的 id + 一行摘要 + engram_detail 下钻 | | 文件焦点 | 同一文件连续第二次编辑,且有 filePath/dir 锚定记忆 | 优先 preference,其次 fact/decision | | 目标完成 | goal complete/block 且有 active ESR 任务 | 前两个未闭环任务 + esr_status 提示 |

  • append-only:推送行一旦出现就不再改写/撤回,前缀每次推送只变一次; 每次推送按 estimatePrefixChars + 行长度 记一次重写罚金(Context Ledger 的 rewriteCount / rewriteChars),净收益可在遥测页直接看。
  • 无命中沉默:没有可指向的记忆/任务就不推——宁可不推,也不灌噪声。
  • 零 LLM、纯规则;jitEnabled:false 一键关,[JIT] section 为空时不占任何 token。
  • 尚未做:resume brief(隔天继续)与「预计剩余请求不足时跳过推送」的显式 ROI 门—— 当前靠 3 行硬预算 + 账本观测。

会话纪要 + 恢复简报(v0.7-A/D)

  • episode:会话结束(session/disposed)时,用零 LLM 规则把事件日志压成一条紧凑纪要—— 改过哪些文件、跑过哪些命令、哪些失败后修复(cmd×N→fixed)、git commit 的书面主题、 仍挂着的 todo。只在有实质内容时生成(纯 ls 会话不写);永不进 [ENGRAM] 索引; 每个 workspace 只保留最近 20 条,超出自动归档。 数据源全部是已有事件(tool/call 的 arguments、tool/result、todo/write),不调模型。
  • 恢复简报:新会话第一次组装时,取最近 7 天最新的 episode,注入 ≤240 字符的 [RESUME] 行 + engram_detail <id> 指针;与 [ENGRAM]/[RECALL] 一起按会话冻结。 没有近期 episode 就不注入——隔天继续项目时不用重新交代背景。
  • 设置键:episodeEnabled、resumeBriefEnabled(均默认开), episodeMaxPerWorkspace / resumeBriefMaxAgeDays / resumeBriefMaxChars 可调。

实体页 + 实体卡(v0.7-B)

esr_node 从「图上的点」升级成可读的页:对一个实体(package / repo / 服务 / bug…) 聚合当前真相、时间线、未闭环任务、冲突与关系。

  • 实体卡(索引内,默认开):[ENGRAM] 为活跃实体(有锚定记忆或未闭环任务) 渲染一行,最多 2 张: [ENT] dsh-engram · package · 3 mem · 1 open · truth: … #id · page: engram_detail(entity="dsh-engram") 这些实体的平铺记忆行不再重复(真相由卡片承载);其余实体仍列在 nodes: 一行。
  • 完整页(按需下钻):engram_detail(entity="<name|id>") 返回 truth / timeline / open loops / conflicts / relations 五段,带 memory id 与证据缺口; 没有注册节点但有记忆锚定的名字也会生成虚拟页。
  • 纯函数、确定性排序:preference 排在 truth 最前,superseded 旧真相不进 truth, 冲突按无序对去重(#a vs #b)。
  • 设置键 entityCardsEnabled(默认开);entityCardsMax / entityCardChars 可调。

可重验证锚点 + 分层 TTL(v0.7-C)

「把过去当真相」是记忆插件最大的可信度问题。v0.7 给带 filePath 的记忆加锚点:

  • 写入时记录 {path, mtimeMs, size, hash?}(≤256KB 的文件存 sha256,大文件只存 stat), 落盘在记忆行的 anchor 字段;相对路径按 workspace 解析为绝对路径。
  • 会话启动时做一次有界重验证(最多 40 条):文件缺失/改动 → 记忆打 stale 标签; [ENGRAM] 索引与实体页 truth 不再自动展示它,但不删除——engram_detail 仍可重取,实体页 timeline 会标 · stale。
  • 分层 TTL:preference / procedure 永久;episode 默认 14 天;error 默认 60 天; 其余按 expireDays(默认 180 天)。真正删除仍只发生在 GC 的归档(不硬删)。
  • 设置键:anchorRevalidate(默认开)、episodeTtlDays、errorTtlDays。
  • 未做:离线「巩固任务」(episode 抽象/合并)——确定性规则只能做 rollup,不是语义抽象; 在没有证据前不引入,留到 v0.8 与 playbook 一起考虑。

自动捕获策略

捕获是确定性、离线的——只看到工具结果,从不看对话本身。什么会被记录成一条记忆:

| 工具结果 | 行为 | 信号 | |---|---|---| | git commit … -m "提交信息" | 记录——书面提交信息就是这条记忆 | 0.55 | | git merge / rebase / cherry-pick / tag / checkout -b | 记录(里程碑) | 0.5 | | git push / git stash / 无 -m 的 commit | 跳过——操作回显,不是决策 | — | | 写入/编辑关键配置与文档路径 | 记录 | 0.3 | | 读取配置路径 | 记录 | 0.3 | | 反复出现的工具错误 | 记录(按消息去重) | 0.25 |

显式 engram_store 的记录不受上述规则约束(按会话限流)。

谁能拿到 [ENGRAM] 索引行(这才是真正进提示词的部分): signal >= minIndexSignal 或 hits >= promoteHits 或 kind === "task", 再由 indexMaxLines / indexMaxChars 封顶。另有一道额外的闸保持管道干净: 自动捕获的 git 命令回显——文本里嵌着 shell 命令链(git push: cd … && …)—— 即使信号超阈值也不进索引,直到被召回命中晋升为止。其余条目安静地躺在存储里, 按需用 engram_recall / engram_detail 取用——「检索到 ≠ 注入」。

注入块

模型实际看到的内容(每个会话渲染一次,然后冻结):

ESR 操作协议(静态,每轮逐字节相同)
  1. 动工前:esr_ready 看可认领工作;esr_status 拿实时状态。
  2. 多步工作 → esr_task(draft 起步);动工 → esr_claim;收工 → esr_close(三证齐)。
  state 是唯一真相:拿不准 state 就 call esr_status。

[ENGRAM] workspace: symbolic-index · 2 memories · 1 task(s) active · 0 links
[D] 06-18 Decided: use sqlite-vec for retrieval #a2331d87
[T] 06-18 Retrieval upgrade — ACTIVE · gap: artifact, evaluation, memory_ref #tsk_8b26
drill: use [RECALL] below · engram_detail <id> (full record) · engram_recall <query> (more) · esr_task/esr_node/esr_link (work)

[RECALL] recall · 1 hit(s) · first msg: retrieval
- [D] 06-18 Decided: use sqlite-vec for retrieval upgrade #a2331d87 ×2
context: use above · engram_detail <id> · engram_recall <query>

[ESR] tasks: 1 active / 1 stable
- tsk_0d: Retrieval upgrade — ACTIVE · gap: artifact, evaluation, memory_ref
- closed: tsk_9a (RAG eval)  ·  +1
snapshot from session start — WILL NOT auto-refresh; call esr_status for live state
# this-session actionables (frozen)
promote: 2 pending todo(s) vs 1 ESR task(s) — esr_task(name="…") #suggest-promote

前缀:[D] 决定 · [E] 错误 · [P] 流程 · [F] 事实 · [I] 洞察 · [H] 交接 · [T] 任务。 被反复使用(hits >= promoteHits)的流程记忆升格为「实证经验」——前缀变 [P✓] 且稳定排在 索引块最前(每组内部仍按新旧排序,块保持确定性);这是我们对 TencentDB Agent Memory「Skill= 经过验证的可执行经验」的零 LLM 对应物。 入选规则遵循「自动捕获策略」(信号阈值 / 命中晋升 / git 回显守卫),并按配置的行数与字符预算封顶。 # id 通过 engram_detail 取完整记录。工作区没有任务时,[ESR] 仍会渲染一行点名 esr_task/esr_close, 让机制对模型保持可见,而不是整体消失。

[RECALL](会话启动自动召回,autoRecallOnStart)按会话首条消息对工作区做确定性 BM25 召回, 把命中前 autoRecallLimit 条注入,受 autoRecallMaxChars 字符预算约束;无命中或空工作区时不渲染。 它是一条提示而不是全文灌入——模型该把它当成"这条相关,可能需要用 engram_detail 看细节"。 纯读、不 bump 命中、superseded 过期真相不占槽位;随 [ENGRAM] 一起按会话冻结。

配置

默认值以 token 为优先;可通过 profile 补丁(~/.dsh/profiles/web/cordis.patch.yml)或 Web 配置卡片覆盖任意键:

- id: engram
  config:
    autoCapture: true        # 零 LLM 工具结果捕获
    autoCapturePreferences: true  # 零 LLM 用户纠正/偏好捕获(prefer/avoid/switch-to 句式)
    preferenceCapturePerSession: 8  # 每会话偏好记忆条数上限
    boundaryPrune: true        # ResultPack L1:todo/goal 边界剪掉超阈值旧工具结果(默认开)
    boundaryPruneAdaptive: true  # 账本否决:该 workspace 净收益为负(≥3 次剪枝)时自动停剪
    boundaryPruneThresholdChars: 0   # 阈值覆盖(0=宿主 8192;如 2048 可更早开剪)
    boundaryPruneHeadChars: 0  # 覆盖时的保留头部(0=宿主 4096)
    boundaryPruneTailChars: 0  # 覆盖时的保留尾部(0=宿主 1024)
    boundaryPruneIdleCadence: 0   # 空闲步数边界(0=仅事件边界;覆盖无 todo/goal 会话)
    resultPack: true           # ResultPack L2:剪掉的中段脱敏归档 + result_recall 按页召回(默认开,须与 L1 同开)
    resultPackRetentionDays: 7 # 归档保留天数(mtime 清理,走 GC 节奏)
    sessionSearch: true      # engram_recall 也可对历史会话 FTS
    recallScope: workspace   # 召回范围:workspace(严格工作区隔离,默认)| global(可选跨工作区召回,带 [W:<ws>] 来源标记)
    autoRecallOnStart: true  # 会话启动自动召回:按首条消息注入 [RECALL] 块(false=回到纯拉取)
    autoRecallLimit: 3       # [RECALL] 最多注入条数(少而准)
    autoRecallMaxChars: 700  # [RECALL] 字符预算
    autoCapturePerSession: 40
    indexMaxLines: 12        # [ENGRAM] 行数上限
    indexMaxChars: 700       # [ENGRAM] 字符上限(token 预算)
    minIndexSignal: 0.4      # 低于此信号的自动捕获不进索引
                             # (git 命令回显即便超阈值也不进,直到命中晋升)
    promoteHits: 3           # ……直到被召回这么多次才进索引
    expireDays: 180          # 记忆 TTL(0 = 永不过期)
    maxMemoriesPerWorkspace: 2000
    gcEnabled: true          # 定时记忆 GC
    gcIntervalHours: 24      # 回收节奏
    gcStableRetentionDays: 120  # 超过此天数的 stable 任务离开 [ESR]
    gcReplacesCompaction: false # Context GC:接管 DSH 自动 compact(默认关=宿主 LLM 压缩;true=opt-in 指针摘要)
    gcNarrative: true        # 无锚轮次走 scoped LLM 叙事;false=纯机械(零 LLM)
    jitEnabled: true         # JIT 推送:错误复发/文件焦点/goal 完成时推一行已有记忆
    episodeEnabled: true     # 会话纪要:结束时零 LLM 生成 episode(不进索引,供恢复简报)
    resumeBriefEnabled: true # 恢复简报:新会话注入最近 7 天最新 episode
    entityCardsEnabled: true # 实体卡:[ENGRAM] 为活跃实体渲染一行真相 + 任务 + 下钻指针
    anchorRevalidate: true   # 会话启动重验证 filePath 锚点(改动/缺失 → stale,不进索引/truth)
    episodeTtlDays: 14       # episode TTL(preference/procedure 永久,error 60 天,其余 expireDays)
    ledgerEnabled: true      # Context Ledger:注入成本/剪枝节省/前缀重写罚金 → 净 token
    ledgerCacheDiscount: 0.1 # 缓存折价:重写按 (1−0.1) 计罚金;0.1 = 命中只付 10%
    autoWebCompaction: false   # web 预设自动改写(默认关;开启需显式确认,可用 revert 还原)
    boundaryPruneMinRemaining: 50  # 偿还门:预计剩余请求数低于此值不剪
    engramIndexOrder: 40    # systemPrompt section 顺序(位于 tools 段之前)
    esrOrder: 41

开发

npm test            # 381 个测试:核心 + Web API + GC + Context GC + ESR 触发 + Context Ledger + JIT(node:test)
npm run build:client

仓库结构:lib/(宿主半边:store / capture / index-block / tools / api / settings)、 client/(浏览器半边,TSX + build.mjs)、test/(node:test)。

故障排查

Web 界面一打开就停在 “Failed to load plugins”,loader 报错形如:

failed to apply loader entry … (@linxin666/dsh-client-ui-web-ui-settings):
keyed slot "settings.plugin.item" requires options.key

原因:DSH 自 0.1.0-rc.7 起把配置卡槽位 settings.plugin.item 声明为按 settings 命名空间键控(卡片用自身编辑的命名空间作 key 注册——dsh-engram 的配置卡正是用 key: "dsh-engram" 这样注册的)。@linxin666/dsh-web-ui-all 0.2.0 之前的 dsh-client-ui-web-ui-settings 向该槽位注册分组卡片时没有 提供 key;而 loader 只要有一个 entry 失败就会中止整个启动流程,于是 GUI 一直卡在失败页。

修复方式:

  • 正确修复——升级全家桶:@linxin666/dsh-web-ui-all@^0.2.x。0.2 系列已把自身设置面从键控槽位迁出,改为一级 settings.section(上游正是 为这个报错做的修复)。
  • 临时解阻:在已安装的 node_modules/@linxin666/dsh-client-ui-web-ui-settings/lib/client.js 中给那 个 settings.plugin.item 注册补上 key: "web-ui-plugins",然后重启 dsh web。(在按命名空间键控的派发下,分组卡片只是不显示,不影响页面其 他部分。)

相关项目

  • symbolic-index — 原始跨会话记忆插件(5 信号 RRF 融合、sqlite-vec、Dream Engine)。
  • pi-esr — 项目全周期的证据驱动任务状态;这里的闭环协议是它的简化形态。

许可

MIT