dsh-engram 0.3.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -238,6 +238,83 @@ curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
238
238
  -d "{\"payload\": $(cat engram-backup.json), \"mode\": \"merge\"}"
239
239
  ```
240
240
 
241
+ ## Compatibility
242
+
243
+ <!-- dsh-market compatibility block — keep labels bilingual and in sync with
244
+ docs/RELEASE-NOTES.TEMPLATE.md (market README convention) -->
245
+
246
+ - **DSH 版本 / DSH versions**: `>=0.1.2-alpha.2 <0.2.0-0` (dsh-engram `0.3.7`; releases `0.2.0`–`0.3.6` support the old generation only — see matrix below)
247
+ - **最后验证日期 / Last verified**: 2026-09-10 — full regression on `dsh-v0.1.5-alpha.1`; real-machine settings GET/PUT/conflict/reset/restart-persistence on `dsh 0.1.5-rc.1` (isolated profile)
248
+ - **安装方式已验证 / Verified install**: `dsh plugin --profile web add dsh-engram`
249
+
250
+ > **Short version.** Every **published** release (`0.2.0` … `0.3.6`) supports
251
+ > the **old** DSH API graph (`0.1.0-rc.7` / `0.1.1`, peers `^0.1.0-rc.7`)
252
+ > **only**. DSH `0.1.2-alpha.2` and newer are **not** compatible with those
253
+ > releases — the settings/client API family broke there. New-DSH support
254
+ > **starts with `0.3.7`**, the first release of the new API generation
255
+ > (described below).
256
+
257
+ | dsh-engram release | Status | DSH support | Declared via |
258
+ | --- | --- | --- | --- |
259
+ | `0.2.0` … `0.3.6` (npm, GitHub v0.3.3–v0.3.6) | published | **old DSH only** — `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` |
260
+ | `0.3.7` (npm, GitHub v0.3.7) | published | **new DSH only** — `>=0.1.2-alpha.2 <0.2.0-0` | `engines.dsh` + peers `>=0.1.2-alpha.2 <0.2.0-0` |
261
+
262
+ ### Where the API family broke — `0.1.2-alpha.2`
263
+
264
+ `0.1.2-alpha.2` is the first version of the new API family and the first that
265
+ **breaks** the released plugin versions:
266
+
267
+ - `@deepseek-ai/dsh-settings` **removed** `settingsNamespace()` and
268
+ `installSettingsSection()` — the exact imports every release ≤ `0.3.6` uses —
269
+ and replaced them with `settings.installSection`. The old host half fails to
270
+ load on `0.1.2-alpha.2+`.
271
+ - The web client half swapped its inject set: `@deepseek-ai/dsh-client-runtime`
272
+ no longer exists in the new family (replaced by `dsh-api-remotes` plus
273
+ `dsh-client-locale` / `-conversation` / `-renderer` / `-ui-settings-plugins`),
274
+ and the settings card used to talk through `ctx.remote.settings`.
275
+ - Supporting bumps at the same boundary: `@deepseek-ai/cordis` `^4.0.1 → ^4.0.2`,
276
+ `@deepseek-ai/schemastery` `^3.18.1 → ^3.18.2`, and `@deepseek-ai/dsh` stopped
277
+ shipping `config/agent-presets` in the package (moved to `dsh.configTrees`).
278
+
279
+ The web config card no longer depends on any of this: since `0.3.7` it reads
280
+ and writes the `dsh-engram` settings namespace through the plugin's **own**
281
+ HTTP route (`/api/dsh-engram/settings`, same-origin fetch like the memory
282
+ viewer), so the card is generation-agnostic on both sides of the
283
+ `0.1.2-alpha.2` boundary.
284
+
285
+ So: keep DSH on `0.1.1-rc.2` or older while running a release ≤ `0.3.6`, and
286
+ upgrade the plugin to `>=0.3.7` before moving DSH to `0.1.2-alpha.2`.
287
+
288
+ ### Current release — `0.4.0`
289
+
290
+ This release declares support for DSH `>=0.1.2-alpha.2 <0.2.0-0` and was fully
291
+ validated against the `dsh-v0.1.5-alpha.1` source and web runtime from the local
292
+ `deepseek-harness` checkout.
293
+
294
+ | Component | Supported range |
295
+ | --- | --- |
296
+ | DSH runtime / host / client package family | `>=0.1.2-alpha.2 <0.2.0-0` |
297
+ | `@deepseek-ai/cordis` | `^4.0.2` |
298
+ | `@deepseek-ai/schemastery` | `^3.18.2` |
299
+ | Node.js | `>=22.19.0` |
300
+
301
+ `0.1.2-alpha.2` is the minimum version for this API family: host settings use
302
+ `settings.installSection`, and the browser settings card reads and writes
303
+ through the plugin's own HTTP route (`/api/dsh-engram/settings`, see Route B
304
+ above). Host import and settings-registration smoke checks pass on
305
+ `0.1.2-alpha.2` and `0.1.3-alpha.2`; the full regression suite is validated
306
+ on `0.1.5-alpha.1` (real-machine GET/PUT/conflict/reset/persist-across-restart
307
+ all verified on `dsh 0.1.5-rc.1` with an isolated profile). The older
308
+ `0.1.0-rc.7` and `0.1.1` API graphs are outside this release's compatibility
309
+ range.
310
+
311
+ To install the DSH version used for validation:
312
+
313
+ ```sh
314
+ npm install --global @deepseek-ai/dsh@0.1.5-alpha.1
315
+ dsh --version
316
+ ```
317
+
241
318
  ## Install
242
319
 
243
320
  ```sh
@@ -605,6 +682,32 @@ means that preset was customized (or has no compaction group) and was left untou
605
682
  `dsh-compaction-basic unavailable` means the backend is missing and everything
606
683
  falls back to the default compressor.
607
684
 
685
+ ### BoundaryPrune (subtask-boundary pruning, default OFF)
686
+
687
+ Context GC owns *what a compaction summary says*; BoundaryPrune owns *when a
688
+ deterministic prune fires*: at todo-completion progress and goal terminal
689
+ events, it calls DSH's own `toolResultPruner` (deterministic surface-replace,
690
+ zero LLM) so long-stale over-threshold tool results stop replaying in every
691
+ later request. The two switches are independent.
692
+
693
+ - **Evidence chain** ([oracle analysis](docs/ORACLE-ANALYSIS.zh.md) +
694
+ [proposal](docs/PROPOSAL-resultpack.zh.md)): 97 real sessions measured —
695
+ 2.77B–7.53B chars of tool-result replay exposure (~692M–1.88M tokens), 96%
696
+ of result bytes from bash/read/run_code; the counterfactual simulation says
697
+ todo boundaries cover 79% of that exposure and a repayment gate lifts
698
+ cache-aware net savings 12–32% on every threshold config.
699
+ - **Repayment gate**: a prune rewrites the prefix (one KV-cache break), so it
700
+ fires only while the session is still expected to run at least
701
+ `boundaryPruneMinRemaining` (default 50) more requests — expectation is a
702
+ workspace-history prior with ×2 growth projection past it, so long sessions
703
+ are never starved.
704
+ - **Honest activation surface**: sessions with no goal and no todo progress
705
+ simply never trigger (no boundary → no prune, zero side effects); the
706
+ corpus-wide dry run activates on 38% of sessions. If the pruner service is
707
+ absent the mechanism disables itself with one log line.
708
+ - Default **off**: `boundaryPrune: false`. When on, the log shows
709
+ `engram boundary-prune (todo @N reqs): pruned …`.
710
+
608
711
  ## Auto-capture policy
609
712
 
610
713
  Capture is deterministic and offline — it only sees tool *results*, never the
@@ -713,7 +816,7 @@ Defaults are token-conscious; override any key via the profile patch
713
816
  ## Development
714
817
 
715
818
  ```sh
716
- npm test # 152 tests: core + web API + GC + usage-observability + Context GC + ESR triggers (node:test)
819
+ npm test # 279 tests: core + web API + GC + usage-observability + Context GC + ESR triggers + BoundaryPrune (node:test)
717
820
  npm run eval # offline recall + structure benchmark (deterministic)
718
821
  npm run build:client
719
822
  ```
package/README.zh.md CHANGED
@@ -149,6 +149,72 @@ curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
149
149
  -d "{\"payload\": $(cat engram-backup.json), \"mode\": \"merge\"}"
150
150
  ```
151
151
 
152
+ ## 兼容性
153
+
154
+ <!-- dsh-market 兼容信息块 —— 与 docs/RELEASE-NOTES.TEMPLATE.md 的市场 README 公约保持一致 -->
155
+
156
+ - **DSH 版本**:`>=0.1.2-alpha.2 <0.2.0-0`(dsh-engram `0.3.7`;`0.2.0`–`0.3.6` 仅旧代际 —— 见下文矩阵)
157
+ - **最后验证日期**:2026-09-10 —— `dsh-v0.1.5-alpha.1` 完整回归;`dsh 0.1.5-rc.1` 隔离 profile 真机验证设置 GET/PUT/冲突/复位/跨重启持久化
158
+ - **安装方式已验证**:`dsh plugin --profile web add dsh-engram`
159
+
160
+ > **一句话结论**:所有**已真正发布**的版本(`0.2.0` … `0.3.6`)**只支持旧版
161
+ > DSH**(`0.1.0-rc.7` / `0.1.1` API 图,peers `^0.1.0-rc.7`)。DSH
162
+ > `0.1.2-alpha.2` 及更新版本与它们**不兼容**——settings/client API 族在该版本
163
+ > 断裂。新版 DSH 支持**自 `0.3.7` 起**提供——它是新 API 代际的第一个发布(见下文)。
164
+
165
+ | dsh-engram 发布版本 | 状态 | 支持的 DSH | 声明方式 |
166
+ | --- | --- | --- | --- |
167
+ | `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` |
168
+ | `0.3.7`(npm + GitHub v0.3.7) | 已发布 | **仅新版** —— `>=0.1.2-alpha.2 <0.2.0-0` | `engines.dsh` + peers 同范围 |
169
+
170
+ ### API 族断裂点:`0.1.2-alpha.2`
171
+
172
+ `0.1.2-alpha.2` 是新 API 族的第一个版本,也是第一个**让已发布插件失效**的版本:
173
+
174
+ - `@deepseek-ai/dsh-settings` **移除了** `settingsNamespace()` 与
175
+ `installSettingsSection()`(≤ `0.3.6` 的每个发布都直接 import 这两个符号),
176
+ 改为 `settings.installSection`——旧宿主端在 `0.1.2-alpha.2+` 上直接加载失败。
177
+ - Web 客户端注入集整体更换:`@deepseek-ai/dsh-client-runtime` 在新代际**已不存在**
178
+ (被 `dsh-api-remotes` + `dsh-client-locale` / `-conversation` / `-renderer` /
179
+ `-ui-settings-plugins` 取代),设置卡此前改走 `ctx.remote.settings`。
180
+ - 同一边界的伴随升级:`@deepseek-ai/cordis` `^4.0.1 → ^4.0.2`、
181
+ `@deepseek-ai/schemastery` `^3.18.1 → ^3.18.2`、`@deepseek-ai/dsh` 不再随包
182
+ 发布 `config/agent-presets`(改为 `dsh.configTrees` 机制)。
183
+
184
+ **web 设置卡已不依赖上面任何一项**:自 `0.3.7` 起,配置卡通过插件**自有**
185
+ HTTP 路由(`/api/dsh-engram/settings`,与记忆 viewer 同样的同源 fetch)读写
186
+ `dsh-engram` settings namespace,因此在 `0.1.2-alpha.2` 分界线两侧都是代际无关的。
187
+
188
+ 所以:跑 ≤ `0.3.6` 的已发布版本时请把 DSH 保持在 `0.1.1-rc.2` 或更旧;升级
189
+ DSH 到 `0.1.2-alpha.2` 之前,先升级插件到 `>=0.3.7`。
190
+
191
+ ### 当前发布版本 —— `0.4.0`
192
+
193
+ 当前发布版本声明适配 DSH `>=0.1.2-alpha.2 <0.2.0-0`,并以本地
194
+ `deepseek-harness` 的 `dsh-v0.1.5-alpha.1` 代码和 Web 运行时完成完整验证。
195
+
196
+ | 组件 | 适配版本 |
197
+ | --- | --- |
198
+ | DSH runtime / host / client 包族 | `>=0.1.2-alpha.2 <0.2.0-0` |
199
+ | `@deepseek-ai/cordis` | `^4.0.2` |
200
+ | `@deepseek-ai/schemastery` | `^3.18.2` |
201
+ | Node.js | `>=22.19.0` |
202
+
203
+ `0.1.2-alpha.2` 是这组 API 的最低版本:宿主设置注册使用
204
+ `settings.installSection`,浏览器端设置卡通过插件自有 HTTP 路由
205
+ (`/api/dsh-engram/settings`,见上文 Route B)读写。
206
+ `0.1.2-alpha.2` 和 `0.1.3-alpha.2` 已完成宿主导入与设置注册 smoke 验证;
207
+ `0.1.5-alpha.1` 已完成完整回归(并在 `dsh 0.1.5-rc.1` 隔离 profile 上真机验证
208
+ 设置 GET/PUT/冲突/复位/跨重启持久化全通)。旧的 `0.1.0-rc.7` 与 `0.1.1` API 图不在
209
+ 本发布版本的兼容范围内。
210
+
211
+ 如需按验证版本安装 DSH:
212
+
213
+ ```sh
214
+ npm install --global @deepseek-ai/dsh@0.1.5-alpha.1
215
+ dsh --version
216
+ ```
217
+
152
218
  ## 安装
153
219
 
154
220
  ```sh
@@ -267,10 +333,18 @@ npm run build:client
267
333
  ## 测试与评测
268
334
 
269
335
  ```sh
270
- npm test # 152 项单元测试(含 usage 滚动 / /stats 路由 / Context GC / ESR 触发)
336
+ npm test # 279 项单元测试(含 usage 滚动 / /stats 路由 / Context GC / ESR 触发 / BoundaryPrune)
271
337
  npm run eval # 离线召回 + 结构基准(确定性语料,跑真实 store/recall 路径)
272
338
  ```
273
339
 
340
+ 另有三个**会话语料分析工具**(零 LLM、确定性,读 `~/.dsh/sessions` 真实日志):
341
+
342
+ ```sh
343
+ node eval/oracle-analysis.mjs # 浪费源量化:结果重放暴露 / 融合候选 / 机制激活率
344
+ node eval/simulate-boundary-prune.mjs # L0 反事实仿真:边界剪枝的预期节省与偿还门扫掠
345
+ node eval/dryrun-boundary-prune.mjs # BoundaryPrune 全量干跑:真实激活面与节省
346
+ ```
347
+
274
348
  `npm run eval` 的检索部分参照 LongMemEval 的问答式评测:受控语料(ASCII + CJK、标签/实体/时间戳已知),
275
349
  对真实 `domain.recall()` 逐一校准 **Precision@k / Recall@k / MRR / Hit@1**(probe 覆盖 tag 精确、子串、
276
350
  多词、CJK、短语唯一、标签排序、负样本无回);结构部分借鉴 StructMemEval:精确去重率(同文本存 3 次折叠为 1)、
@@ -427,6 +501,26 @@ Context GC 的装配在**两个平面**——web 现在**全部自动**,零配
427
501
  - (若见 `… keeping the existing compaction service` 说明同域已有 provider、未替换成功;`web-provision … skipped (custom)`
428
502
  说明某预设是自定义/无 compaction 布局、未被触碰;`dsh-compaction-basic unavailable` 说明环境缺依赖,自动回退默认压缩。)
429
503
 
504
+ ### BoundaryPrune(子任务边界剪枝,默认关)
505
+
506
+ Context GC 管「压缩的摘要内容」,BoundaryPrune 管「确定性剪枝的触发时机」——
507
+ 在 todo 完成推进 / goal 终态这些子任务边界,主动调用 DSH 自带的
508
+ `toolResultPruner`(确定性 surface-replace,零 LLM),把早已超阈值的旧工具
509
+ 结果剪掉头尾保留,省掉它们在后续每个请求里的整段重放。两个开关互相独立。
510
+
511
+ - **证据链**([docs/ORACLE-ANALYSIS.zh.md](docs/ORACLE-ANALYSIS.zh.md) +
512
+ [docs/PROPOSAL-resultpack.zh.md](docs/PROPOSAL-resultpack.zh.md)):97 个真实
513
+ 会话实测,工具结果重放暴露 2.77B–7.53B 字符(≈692M–1.88M token),96% 的
514
+ 结果字节来自 bash/read/run_code;反事实仿真显示 todo 边界覆盖 79% 的暴露,
515
+ 且偿还门在所有配置下提升净收益 12–32%。
516
+ - **偿还门**:剪枝会重写前缀(KV 缓存击穿一次),只有当会话预计还要跑
517
+ `boundaryPruneMinRemaining`(默认 50)个以上请求时才 fire——预计长度用
518
+ workspace 历史先验 + 超过后 ×2 外推(有界乐观),长会话不会被挡死。
519
+ - **诚实激活面**:goal=0 且无 todo 推进的会话天然不触发(无边界不剪,零副作用);
520
+ 全量干跑 77 会话激活 38%。pruner 服务缺席即自动禁用并打一条日志。
521
+ - 默认**关**:`boundaryPrune: false`。开启后启动日志出现
522
+ `engram boundary-prune (todo @N reqs): pruned …`。
523
+
430
524
  ## 自动捕获策略
431
525
 
432
526
  捕获是确定性、离线的——只看到工具*结果*,从不看对话本身。什么会被记录成一条记忆:
@@ -515,6 +609,8 @@ promote: 2 pending todo(s) vs 1 ESR task(s) — esr_task(name="…") #suggest-pr
515
609
  gcStableRetentionDays: 120 # 超过此天数的 stable 任务离开 [ESR]
516
610
  gcReplacesCompaction: true # Context GC:接管 DSH 自动 compact(false=回退默认 LLM 压缩)
517
611
  gcNarrative: true # 无锚轮次走 scoped LLM 叙事;false=纯机械(零 LLM)
612
+ boundaryPrune: false # BoundaryPrune:todo/goal 边界主动剪超阈值旧工具结果(默认关)
613
+ boundaryPruneMinRemaining: 50 # 偿还门:预计剩余请求数低于此值不剪
518
614
  engramIndexOrder: 40 # systemPrompt section 顺序(位于 tools 段之前)
519
615
  esrOrder: 41
520
616
  ```
@@ -0,0 +1,63 @@
1
+ # Oracle Analysis:真实会话 token 浪费源量化
2
+
3
+ > 方法论来自 [SoL-Pi](https://nvlabs.github.io/SoL-Pi/)(NVIDIA Labs):**动手造机制之前,先在真实轨迹上量化浪费源**("Oracle Analysis" / M6 "Use issue history and blind failure mining as proposal evidence" / M42 "Choose tasks with mechanism headroom before scaling")。
4
+ >
5
+ > 工具:`node eval/oracle-analysis.mjs`(流式解压 `~/.dsh/sessions`,零 LLM、确定性、约 90 秒跑完全量)。
6
+
7
+ ## 语料
8
+
9
+ 97 个真实会话日志(3 个 workspace 桶),13,900 次模型请求,15,020 次工具调用,65 轮 compaction,1,376 次会话中途 inbox splice。模型混合 local-vllm deepseek-v4-flash 为主,兼 glm-5.3 / qwen3.8-flash 等。
10
+
11
+ ## M1 工具结果重放暴露(ObservationPack headroom,SoL-Pi C11/C23)
12
+
13
+ 每个工具结果产生后,会在后续每个请求里重放(直到 compaction 改写历史)。exposure = Σ 结果字符 × 后续请求数:
14
+
15
+ | 口径 | 字符数 | ≈token(chars/4) |
16
+ |---|---|---|
17
+ | naive(无 compaction 截断,上界) | 7.53B | 1.88B |
18
+ | compaction 截断(下界) | 2.77B | 692M |
19
+ | 占「重放+固定开销」比重 | 57.6%(naive)– 21.2%(cut) | — |
20
+
21
+ - **top-10 结果占全会话结果字节的 46.1%(中位数)**——少数巨型输出承载了近一半的重放压力,正是 ObservationPack「归档载荷、留 handle+摘录」的靶子。
22
+ - 结果字节来源:**bash 14.2M + read 10.6M + run_code 6.1M ≈ 96%**。截断/归档机制只需覆盖这三个工具即可命中几乎全部暴露。
23
+ - 重放最重的会话(解析器开发,549–1,399 请求/会话)单会话重放高达 91–383Mc(23–96M token)——长时程会话正是 SoL-Pi 指出效率差异可测的场景。
24
+
25
+ **固定开销**(每个请求重发的 system+tools schema):全语料 436Mc ≈ 109M token,平均 ~7.8K token/请求;富预设(43 工具)单请求 schema 41.8Kc。**本插件自身 schema 仅 2.9Kc(≈730 token,占该预设 7%)——插件的开销主张成立。**
26
+
27
+ ## M2 Action-Fusion headroom(SoL-Pi "Action Fusion")
28
+
29
+ 编辑类调用(edit/write/str_replace_editor,共 1,993 次)之后**紧接着**由模型发起 bash(中间隔一次模型决策)的候选:607 次。
30
+
31
+ - 占全部工具调用 **4.0%**;占 bash 调用 **7.5%**;占步间转移 ~4.4%(SoL-Pi 在 Pi 上测得 12.3%,DSH 上 headroom 更小)。
32
+ - 结论:融合编辑+运行为单一工具调用是**上游 harness 的杠杆**,不是插件的;优先级排后。
33
+
34
+ ## M3 engram 机制激活(SoL-Pi M15 "prove mechanism activation")
35
+
36
+ 挂载插件的 66 个会话(全桶):
37
+
38
+ | 指标 | 值 |
39
+ |---|---|
40
+ | 有任何 engram/esr 工具调用 | 26/66(39.4%) |
41
+ | 显式 engram_recall | 6 会话(9.1%),共 8 次,命中 8/8 |
42
+ | engram_detail 下钻 | **0/66** |
43
+ | engram_store / esr_* | 76 / 38 次 |
44
+
45
+ **写路径激活良好,显式读路径近乎休眠**(autoRecallOnStart 的注入不走工具调用,本指标不可见——这本身就是个遥测缺口)。0 次 detail 说明渐进披露的第二层从未被用到:要么索引行已足够(设计成功,上下文成本仅 ~175 token/会话),要么模型从未想到下钻(机制休眠)。区分二者需要新增遥测:**记录每次 [ENGRAM] 注入后本会话是否发生 recall/detail,以及 recall 是否紧随索引覆盖的主题**。
46
+
47
+ ## 副产品发现
48
+
49
+ - **1,376 次会话中途 splice**(agent/inbox/spliced)是 prompt 前缀抖动(C20)的主要来源,每次都可能击穿 KV 缓存、把重放从缓存价打回全价。
50
+ - 65 轮 compaction 集中在长会话;截断口径(naive vs cut)差异即来自它们。
51
+
52
+ ## 下一个机制怎么选(按 headroom 排序)
53
+
54
+ 1. **结果首插压缩(C11/C23)**:对 bash/read/run_code 输出在进入首个 prompt 前归档截断(保头保尾、留 handle、可分页召回)。靶子占结果字节 96%,且与 SoL-Pi 已在配对 A/B 中验证的 ObservationPack 同构。注意 KV 缓存折价与 1376 次 splice 击穿,收益按 token 占用与缓存击穿双口径核算。
55
+ 2. **激活遥测(M15)**:给 /stats 增加「注入→下钻」漏斗计数,并做一次「仅索引 vs 索引+detail 工具」的 A/B,判定 detail 层是否该保留。
56
+ 3. **Action Fusion**:作为上游 DSH 提案(4–7.5% headroom),不在本插件做。
57
+
58
+ ## 口径与限制
59
+
60
+ - token 为 chars/4 估算(CJK 偏差存在,只用于量级)。
61
+ - KV 缓存未折价:重放 token 多数走缓存读价(约 1/10),但中途 splice/compaction 会击穿前缀,击穿部分按全价计——真实成本在两者之间。
62
+ - exposure 的真值介于 naive 与 cut 之间(compaction 摘要本身仍会重放,未计入)。
63
+ - 本机语料为单人三 workspace,非基准任务集;数字用于选机制,不宣称普适。
@@ -0,0 +1,135 @@
1
+ # dsh-engram 改进方案 · ResultPack(工具结果边界剪枝 + 可召回归档)
2
+
3
+ > 依据:[SoL-Pi](https://nvlabs.github.io/SoL-Pi/) 四幸存机制之二(ObservationPack:归档载荷、上下文留 handle+摘录、按页召回)
4
+ > 与提案池 C11「Reduce tool output before its first prompt insertion」/ C23「Build observation packs before paying for full bodies」。
5
+ > 数据:[Oracle Analysis](./ORACLE-ANALYSIS.zh.md)(97 真实会话、13.9K 请求、15.0K 工具调用)。
6
+ > **状态:L1 已实现(`lib/boundary-prune.js`,默认关;L0 见 §6,全量干跑见 §6.1)。L2 归档召回未实施。**
7
+
8
+ ---
9
+
10
+ ## 1. 实测问题(为什么是它)
11
+
12
+ Oracle M1:工具结果重放暴露 **2.77B–7.53B chars(≈692M–1.88B tok 估算)**,占重放+固定开销 21–58%;
13
+
14
+ - 结果字节 **96% 来自 bash(14.2M)+ read(10.6M)+ run_code(6.1M)**;
15
+ - **top-10 结果占会话结果字节中位数 46.1%** —— 少数大结果 × 后续请求数的乘数是浪费本体;
16
+ - 浪费不在"单次插入"(三大工具已有界:bash 64KB 尾截+spill 文件、read 行分页、run_code 序列化字节帽),而在于 **有界结果在每个后续请求里整段重放,直到 compaction 改写历史**。
17
+
18
+ SoL-Pi 的 ObservationPack 正是针对这个乘数:载荷归档、上下文只留 handle+短摘录、需要时按页召回(其配对 EdgeBench:账单 −23.58%)。
19
+
20
+ ## 2. 接缝盘点(已核实 DSH 源码,诚实版)
21
+
22
+ | 接缝 | 核实结果 | 对 ResultPack 的含义 |
23
+ |---|---|---|
24
+ | `ctx.on("tools/result")` | 签名 `Readonly<ToolExecutionResult>`,返回 `undefined`,`notifyResult` 冻结且注释明言"不暴露改写通道" | **不能**在分发点改写 |
25
+ | `tools.guard()` | 同步检查、返回字符串即否决 | 只能否决,不能改写 |
26
+ | `ToolDefinition.finalizeContent` | 定义自有(`defineTool` 时闭包),`applyFinalContent` 在通知前应用 | 只能管**我们自己注册的工具** |
27
+ | `ctx.tools.register()` 重名 | 同层重复即失败;scoped 只能 shadow 全局,bash 注册在预设组合层 | **不能**包裹宿主 bash/read |
28
+ | **`toolResultPruner` 服务**(`dsh-compaction-tool-result-pruner`) | `pruneSession(session)`:对 surface 上超阈值(`thresholdChars` 8192 / `headChars` 4096 / `tailChars` 1024)的 tool/result 做 **surface-replace**,中段替换为 `[... tool result middle pruned ...]`,前置 `compaction/prune` 影子价事件,replay-safe;纯确定性、零 LLM | **唯一的结果改写通道,且是可注入服务**。宿主今天只在 context-overflow 兜底时调用;调用时机没有任何限制 |
29
+ | `BasicCompactionEngine` | "Implementations own trigger policy…" —— 触发策略归引擎所有;pressure/overflow 触发由引擎在 step 边界注册 | 自定义引擎可以引入**新触发时机**(与 PROPOSAL-contextgc 同一接缝) |
30
+
31
+ > 结论:**严格意义的首插改写(C11)在插件层不可达**(观察者只读、finalizer 定义自有、同层重名失败)——那是上游 PR(给 ToolRuntime 开放可扩展的 finalizeContent 链)。
32
+ > 但 DSH 原生的等价物已经存在:pruner 的 surface-replace 可以在**插入后的任何时刻**执行。缺的只是"何时执行"的策略 —— 这正是插件能补的。
33
+
34
+ ## 3. 核心思路:三个层次,逐层验收
35
+
36
+ ### L0 · 反事实仿真(先算后造,SoL-Pi M9「从关键检查点重放备选」)
37
+
38
+ 扩展 `eval/oracle-analysis.mjs`:记录每个会话的 `goal/change`(completed/blocked)seq 与逐请求 seq,离线模拟"在每个 goal 完成边界,对 seq < 边界 且超阈值的结果执行 prune"后的重放暴露变化,扣除重写代价(前缀从首个被替换节点起分叉)。参数扫掠:阈值 {8192, 4096, 2048} × 边界策略 {goal-only, goal+guard N 步}。**产出:预期节省区间 + 最优参数,再决定是否实现。**
39
+
40
+ ### L1 · BoundaryPrune(goal 边界 + 偿还门,纯时机策略)
41
+
42
+ 新 `lib/boundary-prune.js`(~150 行):
43
+
44
+ 1. 监听 goal 完成事件(复用 lib/goal-capture.js 的事件源);
45
+ 2. 注入 `ctx.get("toolResultPruner")`,对**边界之前**的超阈值结果调 pruner(或带 range 的自实现变体,只剪旧结果,新结果留给活跃任务);
46
+ 3. **偿还门**(SoL-Pi Online Context Compact 的时钟):`预期剩余请求数 × 节省重放 chars > 重写前缀成本` 才执行。预期剩余请求数用本会话请求速率 × 该 workspace 历史会话长度中位数估计(oracle 数据已给出);
47
+ 4. 默认**关**,配置卡可开(C13:休眠机制默认关闭)。
48
+
49
+ 与 PROPOSAL-contextgc 正交互补:contextgc 管 pressure 压缩的**摘要内容**(LLM 摘要 → 指针摘要),本提案管**确定性剪枝的触发时机**(overflow 兜底 → goal 边界主动)。
50
+
51
+ ### L2 · ResultPack 本体(pruned 中段归档 + `result_recall` 按页召回)
52
+
53
+ L1 剪掉的中段今天直接丢弃(仅 session 日志保留原文,模型取不到)。L2 把它补成完整 ObservationPack:
54
+
55
+ - 剪枝时把中段存入插件存储域,键 = callId,带脱敏(复用 lib/redact.js);
56
+ - 注册 `result_recall(callId, offset?)` 工具,按页返回归档中段 —— 与 [ENGRAM] 渐进披露同一哲学:索引行→详情下钻;
57
+ - 剪枝结果尾部追加一行 handle:`[middle pruned: result_recall(callId) 可取]`,模型可自主决定是否下钻(M3 遥测将能看到激活率)。
58
+
59
+ ### L3 · 上游提案(严格 C11)
60
+
61
+ 向 DSH 提 PR:ToolRuntime 开放 per-tool 可扩展 finalizeContent 链(或"结果归档 transport")。附上 oracle 数据(96% 集中在三个工具、top-10 占 46%)作为动机。
62
+
63
+ ## 4. 评测与能力下限(预声明,constrained efficiency)
64
+
65
+ - **效率轴**(L0 仿真给出预期;实现后用 oracle 重跑实测):重放暴露变化、每会话节省 chars×requests;
66
+ - **能力轴门**:①recall-bench 不回退(插件行为不变);②人工抽检边界剪枝后的会话,确认无"模型回头要被剪信息"的失败模式(bash 有 spill 文件路径保留在头部、read 本身分页,L1 阶段可恢复性风险低;L2 归档后风险趋零);
67
+ - **KV 经济诚实账**:每次剪枝都从前缀首个被替换节点处击穿缓存;偿还门显式计入。1,376 次中途 splice 已常态性击穿前缀,边界剪枝的机会成本并不总是新增的。
68
+
69
+ ## 5. 风险与反面
70
+
71
+ - **能力损失**:8192 以下的小结果永不剪(pruner 语义),乘数浪费仍在 —— L0 仿真会量化这部分残余;
72
+ - **goal 事件稀疏**:实测五个最大会话 goal/change 为 4/0/4/0/2 —— 两个最大会话为 **0**,goal 边界可能根本不出现;备选边界必须有:`todo/write` 完成态、step 空转检测,L0 仿真应把"无 goal 会话"单独归档报告;
73
+ - **上游变动**:pruner 是 rc 版本(0.1.2-rc.1)服务,签名可能漂移 —— L1 用 `ctx.get` 探测 + 特性检测,缺席即禁用并告警;
74
+ - **过拟合警告**(SoL-Pi Discussion):本方案针对"交互循环的重复浪费"而非任务答案,抗过拟合;但仿真参数不应在评测语料上调到最优再宣称泛化。
75
+
76
+ ## 6. L0 仿真结果(eval/simulate-boundary-prune.mjs,已执行)
77
+
78
+ 语料:77 个 >10 请求的会话,M1 cut 暴露 2.77Bc;缓存价 0.1、break window 5 请求、marker 42c。缓存感知口径:节省按缓存读价 ×0.1 计,重写代价 = 首个被剪节点前的存活前缀 ×0.9 一次性付全价(保守:未扣除更早剪枝已缩小的前缀)。
79
+
80
+ **覆盖率**:goal/todo 边界存在于 32/77 会话,但它们持有 **79% 的 M1 cut 暴露**(2.19Bc vs 未覆盖会话 583Mc)——机制可达性不是天花板。
81
+
82
+ | 策略 | 阈值 | naive 上界 | 缓存感知净 | 偿还(中位/p90 请求) |
83
+ |---|---|---|---|---|
84
+ | goal-only | 8192 | 72Mc(2.6%) | +5.0Mc | 5 / 320 |
85
+ | goal-only | 2048 | 219Mc(7.9%) | +19.2Mc | 2 / 299 |
86
+ | todo-progress | 8192 | 313Mc(11.3%) | +20.9Mc | 10 / 748 |
87
+ | todo-progress | 4096 | 509Mc(18.3%) | +38.0Mc | 7 / 628 |
88
+ | todo-progress | 2048 | 670Mc(24.1%) | +51.1Mc | 11 / 527 |
89
+ | goal+todo | 2048 | 702Mc(25.3%) | +50.4Mc | 28 / 527 |
90
+
91
+ **加偿还门**(只 fire 预计能回本的边界,gate=50 请求,剩余请求数取后见之明):
92
+
93
+ | 阈值 | 无门净 | gate=50 净 | 变化 |
94
+ |---|---|---|---|
95
+ | 8192 | 21.7Mc | 28.6Mc | **+32%** |
96
+ | 4096 | 38.8Mc | 44.5Mc | **+15%** |
97
+ | 2048 | 55.0Mc | 61.6Mc | **+12%** |
98
+
99
+ ### 结论(凭数字)
100
+
101
+ 1. **偿还门被数据验证**:所有配置下 gate=50 都优于无门——SoL-Pi Online Context Compact 的"未来节省须偿还重写"时钟不是装饰,是净收益的主要保护者(p90 偿还 527–897 请求:无门时大量剪枝永远回不了本)。
102
+ 2. **goal-only 是死路**(6 会话、2.6–7.9%):goal 稀疏性实锤。**todo-progress 是主力边界**;goal 只作锦上添花(goal+todo ≈ todo-progress)。
103
+ 3. **规模与阈值**:T4096 是能力风险与收益的平衡点(18.3% naive / +38–44.5Mc 净);T2048 收益更高(24% / +61.6Mc)但剪 1,817 个结果(是 T8192 的 5.5 倍),**没有 L2 归档就不该开**。
104
+ 4. **缓存价敏感性**:节省 ∝ 缓存价,代价 ∝ (1−缓存价)。0.1 是保守假设;缓存价 0.25 的服务商上净收益约 ×2.5。
105
+ 5. 净收益的天花板约 **+62Mc(缓存价口径)/ 702Mc(naive 口径)** ≈ 缓存价池(277Mc)的 22% —— 单机制天花板有限,但这是零 LLM、确定性、默认关的可选开关,且 KV 未击穿部分(短会话/无边界)另有 contextgc 负责。
106
+
107
+ ### L1 实施参数(由仿真直接给定)
108
+
109
+ - 边界源:`todo/write` 完成数递增(必须)+ goal complete/block(顺带);
110
+ - 阈值默认 T4096(head 2048 / tail 512),配置卡可调 T2048–T8192;
111
+ - 偿还门:预期剩余请求数 ≥ 50(剩余数用 workspace 历史会话长度中位数估计,oracle 数据已有);
112
+ - 默认关,`boundaryPrune` 配置项 + 激活遥测(每次 fire 记一条 `boundary-prune` 事件计数,进 /stats)。
113
+
114
+ ## 7. L1 实现与全量干跑(已完成)
115
+
116
+ `lib/boundary-prune.js`(~170 行):`ctx.on("session/event")` 监听 todo/goal 边界 → 偿还门 → `ctx.get("toolResultPruner").pruneSession(session)`(DSH 原生确定性 surface-replace,8192/4096/1024)。配置 `boundaryPrune`(默认关)+ `boundaryPruneMinRemaining`(默认 50);pruner 服务缺席即禁用并打一条日志;全程 fail-contained。测试:`test/boundary-prune.test.mjs`(边界判定、高水位、偿还门算术、外推策略;npm test 279/279 过)。
117
+
118
+ **偿还门外推修正**(实现期发现):初版用经验中位数 120 作期望总长,干跑暴露它把 1247 请求的长会话在 71 请求处永久挡死——经验先验对长会话是灾难性低估,而 L0 恰恰显示暴露集中在长会话。修正:先验只作下界锚点,会话超过先验后按当前请求数 ×2 外推(有界乐观)。这正是 SoL-Pi P11「不要从训练命中泛化」的现场复现。
119
+
120
+ **全量干跑**(`eval/dryrun-boundary-prune.mjs`,77 会话 >10 请求,DSH 默认阈值 8192,门 50):
121
+
122
+ - **29/77 会话激活(38%),303 个结果被剪,≈3.47M 字符**;
123
+ - 命中分布健康:最大会话(eb2eb,1399 请求)fired 2 次;57 请求的中会话也命中(6be70);
124
+ - 偿还门拦掉 21 个不划算边界(对照 L0 的 +12%~+32% 净收益提升);
125
+ - 注意:此为「首剪节省」而非完整重放乘数节省——每次 fire 之后的后续请求才持续省;完整口径即 L0 仿真的 ~18% M1 cut 暴露。
126
+
127
+ **干跑同时确认的边界稀疏性现实**:多个大会话(如 216e8/34940,goal=0 且无 todo 递增)完全不触发——机制对「无计划工作流」天然不激活,这不是 bug 而是激活面诚实性:无边界就不剪,零副作用。覆盖更多工作流需要 L2 的其他边界源(如 step 空转),已列入后续。
128
+
129
+ ## 8. 后续
130
+
131
+ - **L2(未实施)**:pruned 中段归档 + `result_recall` 按页召回 + handle 行;T2048 阈值与 L2 绑定。
132
+ - **激活遥测**:fire 事件已可从 session log 的 `compaction/prune` 序列读出;建议 /stats 加一个「boundary-prune vs overflow-prune 来源区分」计数(用 fire 前后日志行归属判定)。
133
+ - **上游提案(L3)**:ToolRuntime 开放 finalizeContent 链,附 oracle 数据。
134
+
135
+
@@ -0,0 +1,34 @@
1
+ ## dsh-engram v0.4.0
2
+
3
+ 以 SoL-Pi(NVIDIA Labs)的 harness 效率研究为方法论起点:先量化、再造机制。本版本新增会话语料测量工具链与第一个由数据驱动的上下文效率机制。
4
+
5
+ ### 功能
6
+
7
+ - **BoundaryPrune(子任务边界剪枝,默认关)** — 在 todo 完成推进 / goal 终态边界,主动调用 DSH 自带 `toolResultPruner`(确定性 surface-replace、零 LLM、replay-safe),让超阈值旧工具结果停止在后续每个请求里整段重放。含**偿还门**(预计剩余请求 < `boundaryPruneMinRemaining`(默认 50)不剪;先验下界 + ×2 外推,长会话不被挡死)、pruner 服务特性检测(缺席即禁用)、fail-contained。配置 `boundaryPrune`(默认关)/ `boundaryPruneMinRemaining`。
8
+ - **证据链工具链(eval/,零 LLM、确定性,读 ~/.dsh/sessions 真实日志)**:
9
+ - `oracle-analysis.mjs` — 浪费源量化:结果重放暴露(97 会话实测 2.77B–7.53B 字符,96% 字节来自 bash/read/run_code,中位会话 top-10 结果占 46%)、edit→exec 融合候选、插件机制激活率、goal/todo 边界与 splice 事件捕获。
10
+ - `simulate-boundary-prune.mjs` — L0 反事实仿真:阈值 × 边界策略 × 偿还门扫掠;todo 边界覆盖 79% 暴露,偿还门全配置提升净收益 12–32%。
11
+ - `dryrun-boundary-prune.mjs` — BoundaryPrune 全量干跑:77 会话激活 38%,303 结果首剪 ≈3.47M 字符。
12
+ - **文档**:docs/ORACLE-ANALYSIS.zh.md(测量报告)、docs/PROPOSAL-resultpack.zh.md(接缝盘点 + L0/L1 记录;严格首插改写需上游 PR,已论证)。
13
+
14
+ ### 修复
15
+
16
+ - (无 — 本版本为纯新增;boundaryPrune 默认关,不开即零行为变化)
17
+
18
+ ### 其他
19
+
20
+ - 测试 279/279 过(新增 6 个 BoundaryPrune 用例);prepublishOnly 真实 tarball 安装双入口导入验证过。
21
+ - README 中英双语新增 BoundaryPrune 小节与 eval 工具说明;配置示例更新。
22
+
23
+ ## DSH 版本支持
24
+
25
+ - **支持的 DSH 范围**:>=0.1.2-alpha.2 <0.2.0-0
26
+ - **peer 声明**:
27
+ - `@deepseek-ai/dsh-compaction`: `>=0.1.2-alpha.2 <0.2.0-0`
28
+ - `@deepseek-ai/dsh-compaction-basic`: `>=0.1.2-alpha.2 <0.2.0-0`
29
+ - `@deepseek-ai/dsh-llm`: `>=0.1.2-alpha.2 <0.2.0-0`
30
+ - `@deepseek-ai/dsh-settings`: `>=0.1.2-alpha.2 <0.2.0-0`
31
+ - `@deepseek-ai/dsh-storage-domain`: `>=0.1.2-alpha.2 <0.2.0-0`
32
+ - **验证版本**:`dsh-v0.1.5-alpha.1`(本地 deepseek-harness checkout)
33
+ - **最后验证日期**:2026-09-14
34
+ - **安装方式已验证**:`dsh plugin --profile web add dsh-engram`
@@ -0,0 +1,68 @@
1
+ # Release Notes 模板(每次发布必用)
2
+
3
+ 每个 GitHub Release 正文都应包含以下区块。**「DSH 版本支持」一节为必填**,
4
+ 其余按发布内容填写。版本支持信息从 `package.json` 读取,避免手写漂移:
5
+
6
+ ```sh
7
+ # 直接生成「DSH 版本支持」markdown 段(读 package.json 的 engines.dsh + peers)
8
+ npm run dsh-engram:release-notes
9
+ # 或
10
+ node scripts/gen-release-notes.mjs
11
+ ```
12
+
13
+ ---
14
+
15
+ ## 模板正文(复制后填空)
16
+
17
+ ```
18
+ ## dsh-engram v<版本号>
19
+
20
+ <一句话:自上一个版本以来的主题>
21
+
22
+ ### 功能
23
+ - ...
24
+
25
+ ### 修复
26
+ - ...
27
+
28
+ ### 其他
29
+ - ...
30
+
31
+ ## DSH 版本支持(必填)
32
+
33
+ - **支持的 DSH 范围**:`<复制自 package.json engines.dsh,如 >=0.1.2-alpha.2 <0.2.0-0>`
34
+ - **验证版本**:`<如 dsh-v0.1.5-alpha.1>`(本地 deepseek-harness checkout)
35
+ - **最后验证日期**:`<YYYY-MM-DD>`
36
+ - **安装方式已验证**:`<如 dsh plugin --profile web add dsh-engram>`
37
+ - **peer 声明**:`<复制自 package.json peerDependencies 中的 @deepseek-ai/dsh-* 范围>`
38
+
39
+ > ⚠️ 新旧分界:DSH `0.1.2-alpha.2` 起 settings/client API 族大改
40
+ > (`@deepseek-ai/dsh-settings` 移除 `settingsNamespace`/`installSettingsSection`,
41
+ > 改 `settings.installSection`;client 注入集从 `dsh-client-runtime` 换到
42
+ > `dsh-api-remotes` 等;cordis `^4.0.2`、schemastery `^3.18.2`)。
43
+ > 若本版本仍声明 peers `^0.1.0-rc.7`,说明它**只支持旧版 DSH**
44
+ > (≤ `0.1.1-rc.2`),正文必须写明「仅支持旧版 DSH」并用上面第一段替换当前示例。
45
+ ```
46
+
47
+ ---
48
+
49
+ ## 历史版本口径(补注用,legacy releases 说明)
50
+
51
+ 已发布版本 `0.2.0` … `0.3.6` 的 Release/README 如果缺失 DSH 兼容说明,统一补这
52
+ 一段:
53
+
54
+ ```
55
+ ## DSH 版本支持
56
+
57
+ - **支持的 DSH 范围**:仅旧版 —— `0.1.0-rc.7` / `0.1.0-rc.8` / `0.1.1-rc.1` / `0.1.1-rc.2`
58
+ - **peer 声明**:`@deepseek-ai/dsh-*@^0.1.0-rc.7`
59
+ - ⚠️ DSH `>=0.1.2-alpha.2` 与本版本**不兼容**(settings/client API 族在该版本断裂)。
60
+ 如需新版 DSH,请升级插件到 `master` 的下一个发布。
61
+ ```
62
+
63
+ ## dsh-market 兼容信息格式参考
64
+
65
+ - 包清单的版本兼容字段是 **semver 范围**:`package.json` / `dsh.plugin.json` 的
66
+ `engines.dsh`(如 `">=0.1.5-alpha.2"` 或 `"0.1.0-rc.6 || 0.1.2-rc.1"`)。
67
+ - 市场侧 README 公约(`## Compatibility` 段):
68
+ `DSH 版本` · `最后验证日期` · `安装方式已验证`。