dsh-engram 0.5.0 → 0.6.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 +119 -32
- package/README.zh.md +103 -35
- package/docs/CONTEXT-GC-GUIDE.zh.md +15 -9
- package/docs/PROPOSAL-evolution.zh.md +684 -0
- package/docs/RELEASE-NOTES-v0.5.1.md +54 -0
- package/docs/RELEASE-NOTES-v0.6.0.md +64 -0
- package/lib/api.js +5 -0
- package/lib/boundary-prune.js +29 -2
- package/lib/client.js +329 -5
- package/lib/index.js +165 -18
- package/lib/jit.js +224 -0
- package/lib/ledger.js +458 -0
- package/lib/session-cjk.js +2 -2
- package/lib/settings.js +12 -4
- package/lib/usage.js +47 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -264,8 +264,8 @@ curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
|
|
|
264
264
|
<!-- dsh-market compatibility block — keep labels bilingual and in sync with
|
|
265
265
|
docs/RELEASE-NOTES.TEMPLATE.md (market README convention) -->
|
|
266
266
|
|
|
267
|
-
- **DSH 版本 / DSH versions**: `>=0.1.2-alpha.2 <0.3.0-0` (本版 `0.
|
|
268
|
-
- **最后验证日期 / Last verified**: 2026-10-
|
|
267
|
+
- **DSH 版本 / DSH versions**: `>=0.1.2-alpha.2 <0.3.0-0` (本版 `0.6.0`; 已发布的 `0.3.7`、`0.4.0` 仍声明旧的 `0.1.x` 范围 `>=0.1.2-alpha.2 <0.2.0-0` — 见下方矩阵)
|
|
268
|
+
- **最后验证日期 / Last verified**: 2026-10-19 — Context Ledger / 默认值纠偏 / JIT 推送,npm test 359/359 通过
|
|
269
269
|
- **安装方式已验证 / Verified install**: `dsh plugin --profile web add dsh-engram`
|
|
270
270
|
|
|
271
271
|
> **Short version.** Every **published** release (`0.2.0` … `0.3.6`) supports
|
|
@@ -279,7 +279,9 @@ curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
|
|
|
279
279
|
| --- | --- | --- | --- |
|
|
280
280
|
| `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` |
|
|
281
281
|
| `0.3.7` / `0.4.0` (npm) | published | **new DSH, settings `installSection`** — `>=0.1.2-alpha.2 <0.2.0-0` | `engines.dsh` + peers `>=0.1.2-alpha.2 <0.2.0-0` |
|
|
282
|
-
| `0.5.0` (
|
|
282
|
+
| `0.5.0` (npm) | published | **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` |
|
|
283
|
+
| `0.5.1` | published | 同 `0.5.0` — 会话扫描修复(`session.v<N>.jsonl.zstd`,issue #8)、数据导出/导入 GUI、替换/冲突可视化(issue #3) | 同 `0.5.0` |
|
|
284
|
+
| `0.6.0` (本期 / this release) | published | 同 `0.5.0` — Context Ledger、BoundaryPrune/ResultPack 默认开 + 账本否决、JIT 推送、Context GC 改 opt-in | 同 `0.5.0` |
|
|
283
285
|
|
|
284
286
|
### Where the API family broke — `0.1.2-alpha.2`
|
|
285
287
|
|
|
@@ -313,7 +315,7 @@ the loader), and the settings form is keyed by the profile entry id (`engram`),
|
|
|
313
315
|
so nothing needs "mounting". `0.5.0` feature-detects the two generations in
|
|
314
316
|
`installEngramSettings`:
|
|
315
317
|
|
|
316
|
-
- DSH `≥0.1.7` / `0.2.x` — the
|
|
318
|
+
- DSH `≥0.1.7` / `0.2.x` — the 31 GUI knobs are the volatile `Config` fields
|
|
317
319
|
(`lib/settings.js` `makeEngineConfigSchema`, exported as `Config` from
|
|
318
320
|
`lib/index.js`); the card reads/writes entry `engram` through the same
|
|
319
321
|
`/api/dsh-engram/settings` HTTP route, and the `service.settings` seam
|
|
@@ -329,7 +331,27 @@ drives mutations).
|
|
|
329
331
|
So: keep DSH on `0.1.1-rc.2` or older while running a release ≤ `0.3.6`, and
|
|
330
332
|
upgrade the plugin to `>=0.3.7` before moving DSH to `0.1.2-alpha.2`.
|
|
331
333
|
|
|
332
|
-
### Current release — `0.
|
|
334
|
+
### Current release — `0.6.0`
|
|
335
|
+
|
|
336
|
+
From a "memory plugin" to a **context portfolio**: make token savings auditable
|
|
337
|
+
first, then use the ledger to correct defaults, veto unprofitable prunes and
|
|
338
|
+
push memory at deterministic moments.
|
|
339
|
+
|
|
340
|
+
- **Context Ledger** — per session / workspace / day
|
|
341
|
+
`net = avoided − injected − rewrite penalty`; exposed on `/stats` and
|
|
342
|
+
`/overview`, rendered on the telemetry page, persisted to
|
|
343
|
+
`~/.dsh/engram/ledger.json`.
|
|
344
|
+
- **Default correction** — `boundaryPrune` / `resultPack` default ON (pruning is
|
|
345
|
+
lossless via the archive); `gcReplacesCompaction` / `autoWebCompaction` are
|
|
346
|
+
now opt-in (no preset rewriting by default).
|
|
347
|
+
- **Ledger veto** — `boundaryPruneAdaptive` stops pruning a workspace whose own
|
|
348
|
+
accounting is net negative after ≥3 real fires (fail-open).
|
|
349
|
+
- **JIT push** — error recurrence / file focus / goal completion, append-only,
|
|
350
|
+
≤3 lines per session, silent without a hit; `[JIT]` section + `jitEnabled`.
|
|
351
|
+
- **Migration** — restart `dsh web` after upgrading; if you still want Context
|
|
352
|
+
GC takeover, set `gcReplacesCompaction:true` (plus `autoWebCompaction:true`
|
|
353
|
+
for web presets). The `0.5.1` versioned session-log fix (issue #8) and data
|
|
354
|
+
backup GUI (issue #3) are unchanged.
|
|
333
355
|
|
|
334
356
|
The published `0.4.0` declared `>=0.1.2-alpha.2 <0.2.0-0` — which the semver
|
|
335
357
|
gate **rejects on every DSH `0.2.0-0` prerelease** (`<0.2.0-0` excludes
|
|
@@ -350,7 +372,7 @@ feature-detected legacy fallback).
|
|
|
350
372
|
`0.1.2-alpha.2` is the minimum version for this API family: host settings are
|
|
351
373
|
**feature-detected** — on DSH `≤0.1.5` they register the `dsh-engram`
|
|
352
374
|
namespace via `settings.installSection`; on `≥0.1.7` / `0.2.x` the form is the
|
|
353
|
-
plugin's `Config` with the
|
|
375
|
+
plugin's `Config` with the 31 GUI knobs marked `.volatile()` (entry id
|
|
354
376
|
`engram`). The browser settings card reads and writes through the plugin's own
|
|
355
377
|
HTTP route (`/api/dsh-engram/settings`, see Route B above) on both. The full
|
|
356
378
|
regression suite (npm test 329/329, incl. the new settings-v2 coverage for the
|
|
@@ -615,10 +637,12 @@ Triggers follow DSH's own compaction timing (step pressure / context-overflow /
|
|
|
615
637
|
`/compact`); the lock, replay validation, tool-call/result pairing and token
|
|
616
638
|
pricing are all reused from the basic engine. Any error falls back to the
|
|
617
639
|
default compressor — compaction is never broken; with `gcReplacesCompaction:
|
|
618
|
-
false` (or a host without `dsh-compaction-basic`) a bare
|
|
619
|
-
is mounted instead, so the `compaction` service never
|
|
620
|
-
dsh-engram is installed. Mounting registers the `compaction`
|
|
621
|
-
plugin's fiber, so unloading/reloading engram restores the
|
|
640
|
+
false` (the default since v0.6, or a host without `dsh-compaction-basic`) a bare
|
|
641
|
+
`BasicCompactionEngine` is mounted instead, so the `compaction` service never
|
|
642
|
+
disappears while dsh-engram is installed. Mounting registers the `compaction`
|
|
643
|
+
service on the plugin's fiber, so unloading/reloading engram restores the
|
|
644
|
+
default engine. **Taking over compaction is opt-in**: turn on
|
|
645
|
+
`gcReplacesCompaction` (and `autoWebCompaction` for web presets).
|
|
622
646
|
|
|
623
647
|
> **Shrink gate**: the harness refuses any checkpoint that is not strictly
|
|
624
648
|
> smaller than the evicted span (`summary is not smaller than the shadowed
|
|
@@ -633,19 +657,19 @@ plugin's fiber, so unloading/reloading engram restores the default engine.
|
|
|
633
657
|
|
|
634
658
|
#### Where it is enabled (the entry point)
|
|
635
659
|
|
|
636
|
-
Assembly happens on **two planes
|
|
660
|
+
Assembly happens on **two planes**, but both switches are opt-in (no takeover by
|
|
661
|
+
default):
|
|
637
662
|
|
|
638
|
-
- **Host plane (headless / TUI / base profiles)
|
|
663
|
+
- **Host plane (headless / TUI / base profiles)**:
|
|
639
664
|
the main plugin (`lib/index.js`) mounts the engine inside `ctx.effect` via
|
|
640
665
|
`mountCompactionEngine(ctx, resolved, { readWorkspace }) → new Engine()`,
|
|
641
666
|
registering the `compaction` service on its own fiber; the plugin patch
|
|
642
667
|
disables the base `compaction-basic` row, making engram the sole host-plane
|
|
643
|
-
provider. `gcReplacesCompaction:
|
|
644
|
-
`
|
|
645
|
-
(
|
|
646
|
-
`
|
|
647
|
-
- **Preset plane (web profile) —
|
|
648
|
-
preset**: web keeps compaction inside each agent preset's isolated realm
|
|
668
|
+
provider. `gcReplacesCompaction: false` (default) → a bare
|
|
669
|
+
`BasicCompactionEngine` (DSH's own summarizer); `true` → `ContextGcEngine`
|
|
670
|
+
(pointer summaries). Enable via profile patch
|
|
671
|
+
(`config: { gcReplacesCompaction: true }`) or the settings card.
|
|
672
|
+
- **Preset plane (web profile) — covers every stock preset once enabled**: web keeps compaction inside each agent preset's isolated realm
|
|
649
673
|
(the shipped presets mount their own `compaction-basic`), unreachable from a
|
|
650
674
|
host-plane row — and unreachable from a profile patch too (`mountPreset`
|
|
651
675
|
builds its `Include.Config` with no patches; verified against the harness
|
|
@@ -655,8 +679,9 @@ Assembly happens on **two planes** — and web is now fully automatic, zero conf
|
|
|
655
679
|
root: `standard`, `code`, `cordis`, and your own presets): it swaps the
|
|
656
680
|
`compaction-basic` row inside the `compaction` group for
|
|
657
681
|
`dsh-engram/compaction`. That auto-wiring is:
|
|
658
|
-
- **
|
|
659
|
-
memory-GC section)
|
|
682
|
+
- **off by default (opt-in)** (`autoWebCompaction: false`, toggle in the
|
|
683
|
+
settings card's memory-GC section); once enabled it is idempotent — an
|
|
684
|
+
already-wired preset is left alone;
|
|
660
685
|
**what "off" means**: the plugin stops auto-wiring on later boots (the
|
|
661
686
|
headless/TUI/base host plane is unaffected) — it does NOT un-wire presets
|
|
662
687
|
that were already wired; use `npm run web-compaction:revert` for that;
|
|
@@ -711,9 +736,10 @@ Assembly happens on **two planes** — and web is now fully automatic, zero conf
|
|
|
711
736
|
|
|
712
737
|
#### First impressions after an npm install (perceive / guide / configure)
|
|
713
738
|
|
|
714
|
-
- **
|
|
715
|
-
|
|
716
|
-
|
|
739
|
+
- **Semi-automatic (opt-in)**: DSH's own summarizer stays the default. Turn on
|
|
740
|
+
`gcReplacesCompaction` (host plane) and `autoWebCompaction` (web presets) in
|
|
741
|
+
the settings card, then boot once — `mountCompactionEngine` takes over and
|
|
742
|
+
the stock presets are rewritten. **No file editing after that.**
|
|
717
743
|
- **Perceivable**: at boot the plugin writes an authoritative snapshot to
|
|
718
744
|
`$DSH_HOME/engram/context-gc.status.json` (`host` plane mode + the per-preset
|
|
719
745
|
`web` results + effective config). At any time run `npx dsh-engram status` or
|
|
@@ -722,8 +748,9 @@ Assembly happens on **two planes** — and web is now fully automatic, zero conf
|
|
|
722
748
|
log lines confirm it too: `engram context-gc: compaction = Context GC …` and
|
|
723
749
|
`engram web-provision: wired Context GC into preset …`.
|
|
724
750
|
- **Configurable**: one settings card (memory-GC section) governs everything:
|
|
725
|
-
`autoWebCompaction` (web auto-wiring
|
|
726
|
-
(Context GC vs default
|
|
751
|
+
`autoWebCompaction` (web auto-wiring, default off), `gcReplacesCompaction`
|
|
752
|
+
(Context GC vs host summarizer, default off), `gcNarrative` (narrative
|
|
753
|
+
safety net).
|
|
727
754
|
Changes take effect after restarting `dsh web`, and the web rows are
|
|
728
755
|
refreshed to match automatically.
|
|
729
756
|
|
|
@@ -740,7 +767,7 @@ means that preset was customized (or has no compaction group) and was left untou
|
|
|
740
767
|
`dsh-compaction-basic unavailable` means the backend is missing and everything
|
|
741
768
|
falls back to the default compressor.
|
|
742
769
|
|
|
743
|
-
### BoundaryPrune (subtask-boundary pruning, default
|
|
770
|
+
### BoundaryPrune (subtask-boundary pruning, default ON + ledger veto)
|
|
744
771
|
|
|
745
772
|
Context GC owns *what a compaction summary says*; BoundaryPrune owns *when a
|
|
746
773
|
deterministic prune fires*: at todo-completion progress and goal terminal
|
|
@@ -775,10 +802,13 @@ later request. The two switches are independent.
|
|
|
775
802
|
T2048+small-edges lands 2.4× the first-prune savings of the host default on
|
|
776
803
|
the real corpus (10.14M vs 4.23M chars). Lowering the threshold is safe with
|
|
777
804
|
`resultPack` on, which archives the removed middles.
|
|
778
|
-
- Default **
|
|
805
|
+
- Default **on**: `boundaryPrune: true` (`false` is the opt-out). Adaptive gate
|
|
806
|
+
`boundaryPruneAdaptive: true` lets the Context Ledger stop further fires once
|
|
807
|
+
this workspace's own accounting is net negative (≥3 fires) — evidence can only
|
|
808
|
+
turn pruning off. The log shows
|
|
779
809
|
`engram boundary-prune (todo @N reqs): pruned …`.
|
|
780
810
|
|
|
781
|
-
### ResultPack L2 (archive + `result_recall`, default
|
|
811
|
+
### ResultPack L2 (archive + `result_recall`, default ON)
|
|
782
812
|
|
|
783
813
|
BoundaryPrune makes pruning lossless: the removed middle of every pruned
|
|
784
814
|
tool result is redacted (same rules as the memory write path) and archived to
|
|
@@ -816,6 +846,58 @@ Mechanisms must be provably activating, and dormant ones are off by default.
|
|
|
816
846
|
the loop already measured from session logs (engram_recall queries → hits →
|
|
817
847
|
engram_detail follows) so you can see injection→query→detail activation.
|
|
818
848
|
|
|
849
|
+
### Context Ledger (net-savings accounting)
|
|
850
|
+
|
|
851
|
+
Turns "saves tokens" into a checkable number. Every model request is one ledger
|
|
852
|
+
tick: injected `[ENGRAM]`/`[RECALL]` and `[ESR]` blocks are charged per request
|
|
853
|
+
they survive; results removed by BoundaryPrune are credited per later request
|
|
854
|
+
they no longer replay; every prune pays one prefix-rewrite penalty
|
|
855
|
+
`(1 − ledgerCacheDiscount)` (the KV-cache break). `GET /api/dsh-engram/stats`
|
|
856
|
+
and `/overview` return `ledger`:
|
|
857
|
+
|
|
858
|
+
- `totals` — `requests / injectedChars / avoidedChars / rewriteCount /
|
|
859
|
+
rewriteChars / netChars / netTokens` with
|
|
860
|
+
`net = avoided − injected − rewriteChars × (1 − discount)`;
|
|
861
|
+
- `byWorkspace` / `byDay` — the same arithmetic per workspace and calendar day
|
|
862
|
+
(`byDay` newest first);
|
|
863
|
+
- `openSessions` — sessions still accumulating in memory (a restart loses at
|
|
864
|
+
most `flushEvery` requests).
|
|
865
|
+
|
|
866
|
+
The Telemetry tab renders it directly (net-token headline, saved / injected /
|
|
867
|
+
rewrite-penalty cards, a 14-day red/green net chart), and the memory overview
|
|
868
|
+
adds a "net context tokens" stat card. Durable rollup at
|
|
869
|
+
`~/.dsh/engram/ledger.json` (atomic write, daily buckets, delta flush); the hot
|
|
870
|
+
path is an integer add, zero I/O and zero model calls.
|
|
871
|
+
Defaults: `ledgerEnabled: true`, `ledgerCacheDiscount: 0.1`; off = no listeners,
|
|
872
|
+
no writes. **Honest scope**: tokens are `chars / 4` estimates, not provider
|
|
873
|
+
billing, and no quality delta is claimed; Context GC compaction savings are not
|
|
874
|
+
wired yet (the host does not expose before/after sizes), so the ledger only
|
|
875
|
+
counts what it can prove.
|
|
876
|
+
|
|
877
|
+
### JIT push (v0.6-C)
|
|
878
|
+
|
|
879
|
+
Pull-only recall measured dormant (24 `engram_recall` / 8 `engram_detail` across
|
|
880
|
+
112 real sessions), so v0.6 pushes on three deterministic events instead. One
|
|
881
|
+
line per event, at most 3 lines per session (`jitMaxLines`, `jitMaxLineChars`=220),
|
|
882
|
+
and silence when there is nothing relevant to point at:
|
|
883
|
+
|
|
884
|
+
| Event | Trigger | What is pushed |
|
|
885
|
+
|---|---|---|
|
|
886
|
+
| Error recurrence | the same `cmd:` signature fails a second time and a prior error/procedure memory exists | that memory's id + a one-line excerpt + `engram_detail` |
|
|
887
|
+
| File focus | the same file is edited twice in a row and a filePath/dir-anchored memory exists | preference first, then fact/decision |
|
|
888
|
+
| Goal completion | goal complete/block while active ESR tasks remain | the first two open tasks + `esr_status` |
|
|
889
|
+
|
|
890
|
+
- **Append-only**: a pushed line is never edited or withdrawn, so the prefix
|
|
891
|
+
changes once per push. Each push charges a rewrite
|
|
892
|
+
(`estimatePrefixChars + line length`) in the Context Ledger
|
|
893
|
+
(`rewriteCount` / `rewriteChars`), visible on the telemetry page.
|
|
894
|
+
- **Silent without a hit** — no memory/task to point at, no line.
|
|
895
|
+
- **Zero LLM, pure rules**; `jitEnabled:false` disables it, and the empty
|
|
896
|
+
`[JIT]` section costs nothing.
|
|
897
|
+
- **Not yet**: the resume brief (next-day continuation) and an explicit
|
|
898
|
+
remaining-requests ROI gate — today the 3-line budget plus the ledger are the
|
|
899
|
+
guardrails.
|
|
900
|
+
|
|
819
901
|
## Auto-capture policy
|
|
820
902
|
|
|
821
903
|
Capture is deterministic and offline — it only sees tool *results*, never the
|
|
@@ -900,12 +982,13 @@ Defaults are token-conscious; override any key via the profile patch
|
|
|
900
982
|
autoCapture: true # zero-LLM tool-result capture
|
|
901
983
|
autoCapturePreferences: true # zero-LLM user-correction/preference capture (prefer/avoid/switch-to cues)
|
|
902
984
|
preferenceCapturePerSession: 8 # per-session preference memory cap
|
|
903
|
-
boundaryPrune:
|
|
985
|
+
boundaryPrune: true # ResultPack L1: prune stale over-threshold tool results at todo/goal boundaries (default ON)
|
|
986
|
+
boundaryPruneAdaptive: true # ledger veto: stop pruning this workspace once its net is negative (>=3 fires)
|
|
904
987
|
boundaryPruneThresholdChars: 0 # threshold override (0 = host 8192; e.g. 2048 prunes earlier)
|
|
905
988
|
boundaryPruneHeadChars: 0 # retained head under an override (0 = host 4096)
|
|
906
989
|
boundaryPruneTailChars: 0 # retained tail under an override (0 = host 1024)
|
|
907
990
|
boundaryPruneIdleCadence: 0 # request-count boundary for todo/goal-less sessions (0 = event-only)
|
|
908
|
-
resultPack:
|
|
991
|
+
resultPack: true # ResultPack L2: archive pruned middles + result_recall paged recall (default ON; needs L1 on)
|
|
909
992
|
resultPackRetentionDays: 7 # archive retention days (mtime sweep on the GC cadence)
|
|
910
993
|
sessionSearch: true # engram_recall may also FTS past sessions
|
|
911
994
|
recallScope: workspace # recall scope: "workspace" (strict isolation, default) | "global" (opt-in cross-workspace recall with [W:<ws>] origin markers)
|
|
@@ -924,8 +1007,12 @@ Defaults are token-conscious; override any key via the profile patch
|
|
|
924
1007
|
gcEnabled: true # scheduled memory GC
|
|
925
1008
|
gcIntervalHours: 24 # sweep cadence
|
|
926
1009
|
gcStableRetentionDays: 120 # stable tasks leave [ESR] after this
|
|
927
|
-
gcReplacesCompaction:
|
|
1010
|
+
gcReplacesCompaction: false # Context GC: take over DSH auto-compact (default off = host summarizer; true = opt-in pointers)
|
|
928
1011
|
gcNarrative: true # scoped LLM narrative for un-provenanced turns; false = fully mechanical (zero LLM)
|
|
1012
|
+
autoWebCompaction: false # rewrite stock web presets (default off; explicit opt-in, revert with the CLI)
|
|
1013
|
+
jitEnabled: true # JIT push: error recurrence / file focus / goal completion → one memory line
|
|
1014
|
+
ledgerEnabled: true # Context Ledger: injected cost / prune savings / rewrite penalty → net tokens
|
|
1015
|
+
ledgerCacheDiscount: 0.1 # cached-prefix price share; rewrites pay (1−discount)
|
|
929
1016
|
engramIndexOrder: 40 # systemPrompt section order (before tools band)
|
|
930
1017
|
esrOrder: 41
|
|
931
1018
|
```
|
|
@@ -933,7 +1020,7 @@ Defaults are token-conscious; override any key via the profile patch
|
|
|
933
1020
|
## Development
|
|
934
1021
|
|
|
935
1022
|
```sh
|
|
936
|
-
npm test #
|
|
1023
|
+
npm test # 359 tests: core + web API + GC + usage-observability + Context GC + ESR triggers + BoundaryPrune + preference learning + Context Ledger + JIT push (node:test)
|
|
937
1024
|
npm run eval # offline recall + structure benchmark (deterministic)
|
|
938
1025
|
npm run build:client
|
|
939
1026
|
```
|
package/README.zh.md
CHANGED
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
- **记忆 GC(pi-esr 约束)** — 定时、机械、只归档的回收:TTL 过期记忆归档、超容量工作区淘汰低价值条目、
|
|
86
86
|
stable 任务超保留窗离开 `[ESR]` 表面、悬空链接边清理。工作集(active 任务引用 / 任务记忆 / 已入索引命中)
|
|
87
87
|
永不触碰;**不硬删任何东西**——归档条目保留 id、始终可重取。
|
|
88
|
-
- **Context GC(自动 GC = 替代 DSH 自动 compact)** — 不是记忆面板 GC
|
|
88
|
+
- **Context GC(自动 GC = 替代 DSH 自动 compact,opt-in)** — 不是记忆面板 GC:开启后接管 DSH 自带的上下文压缩
|
|
89
89
|
(`compaction` 服务),把「有损 LLM 全量摘要」换成**机械驱逐 + 重取指针**——扫描被驱逐轮次里的
|
|
90
90
|
engram/ESR 锚(`#记忆id`、`tsk_*`、`ent_*`、`file_path`),只留一行「细节在 `engram_detail` /
|
|
91
91
|
`engram_recall` / `[ESR]` 里」;只有无锚轮次才走 scoped LLM 叙事兜底(`gcNarrative`,默认开、可关成纯机械)。
|
|
@@ -166,8 +166,8 @@ curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
|
|
|
166
166
|
|
|
167
167
|
<!-- dsh-market 兼容信息块 —— 与 docs/RELEASE-NOTES.TEMPLATE.md 的市场 README 公约保持一致 -->
|
|
168
168
|
|
|
169
|
-
- **DSH 版本**:`>=0.1.2-alpha.2 <0.3.0-0`(本版 `0.
|
|
170
|
-
- **最后验证日期**:2026-10-
|
|
169
|
+
- **DSH 版本**:`>=0.1.2-alpha.2 <0.3.0-0`(本版 `0.6.0`;已发布的 `0.3.7`、`0.4.0` 仍声明旧的 `0.1.x` 范围 `>=0.1.2-alpha.2 <0.2.0-0` —— 见下文矩阵)
|
|
170
|
+
- **最后验证日期**:2026-10-19 —— Context Ledger / 默认值纠偏 / JIT 推送,npm test 359/359 通过
|
|
171
171
|
- **安装方式已验证**:`dsh plugin --profile web add dsh-engram`
|
|
172
172
|
|
|
173
173
|
> **一句话结论**:所有**已真正发布**的版本(`0.2.0` … `0.3.6`)**只支持旧版
|
|
@@ -179,7 +179,9 @@ curl -s -X POST http://127.0.0.1:3080/api/dsh-engram/import \
|
|
|
179
179
|
| --- | --- | --- | --- |
|
|
180
180
|
| `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` |
|
|
181
181
|
| `0.3.7` / `0.4.0`(npm) | 已发布 | **新版 DSH,settings `installSection`** —— `>=0.1.2-alpha.2 <0.2.0-0` | `engines.dsh` + peers 同范围 |
|
|
182
|
-
| `0.5.0
|
|
182
|
+
| `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` |
|
|
183
|
+
| `0.5.1` | 已发布 | 同 `0.5.0` —— 会话扫描修复(`session.v<N>.jsonl.zstd`,issue #8)、数据导出/导入 GUI、替换/冲突可视化(issue #3) | 同 `0.5.0` |
|
|
184
|
+
| `0.6.0`(本期 / this release) | 已发布 | 同 `0.5.0` —— Context Ledger、BoundaryPrune/ResultPack 默认开 + 账本否决、JIT 推送、Context GC 改 opt-in | 同 `0.5.0` |
|
|
183
185
|
|
|
184
186
|
### API 族断裂点:`0.1.2-alpha.2`
|
|
185
187
|
|
|
@@ -206,7 +208,7 @@ HTTP 路由(`/api/dsh-engram/settings`,与记忆 viewer 同样的同源 fetc
|
|
|
206
208
|
profile 条目 id(`engram`)为命名空间,不再需要任何“挂载”调用。`0.5.0`
|
|
207
209
|
在 `installEngramSettings` 里对两代际做特性检测:
|
|
208
210
|
|
|
209
|
-
- DSH `≥0.1.7` / `0.2.x` ——
|
|
211
|
+
- DSH `≥0.1.7` / `0.2.x` —— 31 个 GUI 旋钮即 `Config` 的 volatile 字段
|
|
210
212
|
(`lib/settings.js` `makeEngineConfigSchema`,由 `lib/index.js` 导出为
|
|
211
213
|
`Config`);卡片仍走同一 `/api/dsh-engram/settings` HTTP 路由读写条目 `engram`,
|
|
212
214
|
`service.settings` 接缝在 `loader/volatile-update` 事件上把 `resolved`
|
|
@@ -219,7 +221,23 @@ profile 条目 id(`engram`)为命名空间,不再需要任何“挂载”
|
|
|
219
221
|
所以:跑 ≤ `0.3.6` 的已发布版本时请把 DSH 保持在 `0.1.1-rc.2` 或更旧;升级
|
|
220
222
|
DSH 到 `0.1.2-alpha.2` 之前,先升级插件到 `>=0.3.7`。
|
|
221
223
|
|
|
222
|
-
### 当前发布版本 —— `0.
|
|
224
|
+
### 当前发布版本 —— `0.6.0`
|
|
225
|
+
|
|
226
|
+
从「记忆插件」转向**上下文投资组合**:先把省 token 变成可审计的账本,再用账本
|
|
227
|
+
纠正默认值、否决不划算的剪枝,并按确定性事件把记忆推给模型。
|
|
228
|
+
|
|
229
|
+
- **Context Ledger**:每会话/工作区/天记录 `net = 节省 − 注入 − 重写罚金`,
|
|
230
|
+
`/stats` 与 `/overview` 返回,GUI 遥测页有面板;落盘 `~/.dsh/engram/ledger.json`。
|
|
231
|
+
- **默认值纠偏**:`boundaryPrune` / `resultPack` 默认开(剪枝由归档兜底),
|
|
232
|
+
`gcReplacesCompaction` / `autoWebCompaction` 改 opt-in(不再主动改写宿主预设)。
|
|
233
|
+
- **账本否决**:`boundaryPruneAdaptive` 在某 workspace 净收益为负且 ≥3 次剪枝时
|
|
234
|
+
自动停剪(fail-open)。
|
|
235
|
+
- **JIT 推送**:错误复发 / 文件焦点 / goal 完成三类事件,append-only、每会话 ≤3 行、
|
|
236
|
+
无命中沉默;`[JIT]` section + `jitEnabled`。
|
|
237
|
+
- **迁移**:升级后重启 `dsh web`;若仍要 Context GC 接管,显式打开
|
|
238
|
+
`gcReplacesCompaction:true`(web 还需 `autoWebCompaction:true`)。
|
|
239
|
+
- `0.5.1` 的会话日志版本化修复(`session.v<N>.jsonl.zstd`,issue #8)与数据备份
|
|
240
|
+
GUI(issue #3)保持不变。
|
|
223
241
|
|
|
224
242
|
已发布的 `0.4.0` 声明 `>=0.1.2-alpha.2 <0.2.0-0`——这个范围被 semver 门槛在
|
|
225
243
|
**所有 DSH `0.2.0-0` 预发布**上拒绝(`<0.2.0-0` 排除 `0.2.0-rc.x`),且其宿主设置端
|
|
@@ -237,13 +255,13 @@ Config** 模型(并带特性检测的旧代际回退)。
|
|
|
237
255
|
|
|
238
256
|
`0.1.2-alpha.2` 是这组 API 的最低版本:宿主设置注册按代际**特性检测**——DSH `≤0.1.5`
|
|
239
257
|
走 `settings.installSection` 注册 `dsh-engram` 命名空间;`≥0.1.7` / `0.2.x` 走插件
|
|
240
|
-
`Config`(
|
|
258
|
+
`Config`(31 个 GUI 旋钮标记为 `.volatile()`,条目 id `engram`)。浏览器设置卡在两代际
|
|
241
259
|
都经插件自有 HTTP 路由(`/api/dsh-engram/settings`,见上文 Route B)读写。完整回归
|
|
242
260
|
(npm test 329/329,含新增的 volatile-Config 模型 settings-v2 覆盖)在 DSH
|
|
243
261
|
`0.2.0-rc.2` 依赖集(cordis 4.0.4 + schemastery 3.18.4 + cosmokit,与全局 DSH CLI 同版本)
|
|
244
262
|
上通过;`.volatile()`/loader 热提交路径与 describe 侧投影已针对真实 `dsh-settings
|
|
245
263
|
0.2.0-rc.2` 工具函数验证;并在隔离的 `dsh 0.2.0-rc.2` profile 上完成了**真机启动烟测并
|
|
246
|
-
通过**:插件启动无版本范围拒绝、设置卡表单以条目 `engram` 对外提供(全部
|
|
264
|
+
通过**:插件启动无版本范围拒绝、设置卡表单以条目 `engram` 对外提供(全部 31 个 GUI
|
|
247
265
|
旋钮,含 `trustedHosts`)、`/api/dsh-engram/settings` 的 GET → PUT(mutate ops,
|
|
248
266
|
revision 0→1)→ unset 往返落盘并读回。旧的 `0.1.0-rc.7` 与 `0.1.1` API 图不在
|
|
249
267
|
本发布版本的兼容范围内。
|
|
@@ -333,6 +351,7 @@ node scripts/setup-links.mjs # 把 @deepseek-ai 工作区包软链进 node_m
|
|
|
333
351
|
纯 SVG 实现(无图表库,保持 bundle 纯净)。
|
|
334
352
|
以及一个 **遥测仪表盘** 页签:把 /stats 的真实调用累计(工作区 × 天滚动)画成纯 SVG 仪表盘——三枚大圆环
|
|
335
353
|
直读 **ESR 主动性**(与 escalate 阈值 0.34 比对,偏低标橙并提示)、**召回命中率**、**detail 转化**,
|
|
354
|
+
外加一块 **Context Ledger** 面板(净 token、节省/注入/重写罚金三卡、近 14 天净收益红绿柱),
|
|
336
355
|
五张小指标卡(累计调用 / esr / 记忆 / 平均命中每查询 / 失败),近 14 天 mem-vs-esr 堆叠柱状图 +
|
|
337
356
|
工具调用 Top 8 横向条形图(mem 蓝 / esr 紫,与全文配色一致),20s 自动刷新,样本不足(<10 次)自动标注。
|
|
338
357
|
以及 **详情侧栏**(主从布局):任务 / 记忆 / 节点 / 关系行都可一键在右侧打开详情卡——任务含
|
|
@@ -349,7 +368,7 @@ node scripts/setup-links.mjs # 把 @deepseek-ai 工作区包软链进 node_m
|
|
|
349
368
|
面板同时列出各工具调用计数与最近 14 天逐日滚动。这些是真实会话的真实数字——想提升 ESR 主动性,
|
|
350
369
|
就观察面板上 esr 占比并调整注入提示。
|
|
351
370
|
- **设置 → 插件 → 插件配置 → dsh-engram** — 与内置「终端 / Agent 循环 / 网页搜索」同款的
|
|
352
|
-
**默认折叠卡片**:标题 + 一行描述 +
|
|
371
|
+
**默认折叠卡片**:标题 + 一行描述 + 箭头,点击展开/收起;展开后常用 11 项 + 高级分组按
|
|
353
372
|
「捕获与检索 / 索引 / 生命周期与 GC / 安全」四个分组展示。改动对新建会话即时生效
|
|
354
373
|
(已冻结的块保持稳定);支持放弃修改 / 保存,有未保存改动时标题上出现「未保存」徽标。
|
|
355
374
|
卡片通过连接自身的 settings RPC 直连命名空间(不走 isLoopback 门控的 scope),因此即使
|
|
@@ -373,7 +392,7 @@ npm run build:client
|
|
|
373
392
|
## 测试与评测
|
|
374
393
|
|
|
375
394
|
```sh
|
|
376
|
-
npm test #
|
|
395
|
+
npm test # 359 项单元测试(含 usage 滚动 / /stats 路由 / Context GC / ESR 触发 / BoundaryPrune / Context Ledger / JIT 推送)
|
|
377
396
|
npm run eval # 离线召回 + 结构基准(确定性语料,跑真实 store/recall 路径)
|
|
378
397
|
```
|
|
379
398
|
|
|
@@ -431,7 +450,7 @@ GC 永不触碰工作集:active 任务 `memory_refs` 引用的记忆、task
|
|
|
431
450
|
(`hits >= promoteHits`)。用 `esr_gc` + `dry_run: true` 先预览。**不硬删**——报告的末尾为所有
|
|
432
451
|
归档项附上重取指针,归档可恢复、不是丢失。
|
|
433
452
|
|
|
434
|
-
### Context GC(替换 DSH 自动 compact)
|
|
453
|
+
### Context GC(替换 DSH 自动 compact,opt-in)
|
|
435
454
|
|
|
436
455
|
DSH 默认的上下文压缩是**有损 LLM 全量摘要**(`compaction-basic`):被驱逐的历史被压缩成散文,
|
|
437
456
|
不可查询、摘要本身还烧 token。dsh-engram 的自动 GC 替代它:`ContextGcEngine extends
|
|
@@ -446,7 +465,9 @@ BasicCompactionEngine` 只重写唯一的 `summarize()` 钩子,把摘要正文
|
|
|
446
465
|
|
|
447
466
|
触发时机完全跟随 DSH 现有 compact(step pressure / context-overflow / `/compact`);锁、回放校验、
|
|
448
467
|
tool-call/result 配对、token 定价全部复用基本引擎。任何错误 → 回退默认压缩,**永不破坏 compact**。
|
|
449
|
-
装配即注册 `compaction` 服务,卸载/reload engram
|
|
468
|
+
装配即注册 `compaction` 服务,卸载/reload engram 自动还回默认引擎。**自 v0.6 起默认不接管**:
|
|
469
|
+
默认挂裸 `BasicCompactionEngine`(宿主 LLM 摘要),要换成指针摘要需显式打开
|
|
470
|
+
`gcReplacesCompaction`(web 预设还需 `autoWebCompaction`)。
|
|
450
471
|
|
|
451
472
|
> **收缩闸门(shrink gate)**:harness 拒绝任何不比被驱逐片段更小的 checkpoint(`summary is not
|
|
452
473
|
> smaller than the shadowed content`),否则压缩回滚、上下文永不缩小、最终触发模型侧溢出。Context GC
|
|
@@ -457,24 +478,23 @@ tool-call/result 配对、token 定价全部复用基本引擎。任何错误
|
|
|
457
478
|
|
|
458
479
|
#### 启用入口(这一节就是答案:该功能开在哪)
|
|
459
480
|
|
|
460
|
-
Context GC
|
|
481
|
+
Context GC 的装配在**两个平面**,但两个开关都是 opt-in(默认不接管):
|
|
461
482
|
|
|
462
483
|
- **host 平面(headless / TUI / base 型 profile)——开箱即用,无需任何配置**:
|
|
463
484
|
主插件 `lib/index.js` 在 `ctx.effect` 里直接
|
|
464
485
|
`mountCompactionEngine(ctx, resolved, { readWorkspace }) → new Engine()` 注册 `compaction` 服务;
|
|
465
486
|
配合插件 patch 禁用基座 `compaction-basic` 行,engram 即为该平面唯一 provider。
|
|
466
|
-
- `gcReplacesCompaction:
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
-
|
|
470
|
-
|
|
471
|
-
- **preset 平面(web profile)——全自动,零配置,覆盖全部预设**:web 面把 compaction 放在 agent
|
|
487
|
+
- `gcReplacesCompaction: false`(**默认**)→ 挂裸 `BasicCompactionEngine`(DSH 默认 LLM 摘要),
|
|
488
|
+
**`compaction` 服务永不缺席**;
|
|
489
|
+
- `gcReplacesCompaction: true` → `ContextGcEngine`(机械驱逐 + 重取指针,opt-in);
|
|
490
|
+
- 开启:profile patch 里给 engram 行加 `config: { gcReplacesCompaction: true }`,或在设置卡打开。
|
|
491
|
+
- **preset 平面(web profile)——显式开启后覆盖全部 stock 预设**:web 面把 compaction 放在 agent
|
|
472
492
|
preset 的 isolate realm(shipped 预设自挂 `compaction-basic`),host 条目进不去、profile patch 也
|
|
473
493
|
够不到预设文件(`mountPreset` 的 Include 不带 patches——已对源码核实)。所以插件在启动时
|
|
474
494
|
(`agentPresets` 服务就绪后)**自动改写每个仍处于出厂 stock 布局的预设**——默认预设 + 整张 roster
|
|
475
495
|
(shipped 根 + `~/.dsh/.agent-presets` 用户根,`standard`/`code`/`cordis` 和你自己的预设都覆盖):
|
|
476
496
|
把 `compaction` 组里的 `compaction-basic` 行换成 `dsh-engram/compaction`。这一自动装配是:
|
|
477
|
-
-
|
|
497
|
+
- **默认关(opt-in)**(`autoWebCompaction: false`;设置卡「记忆 GC」可开),开启后幂等——已替换则跳过;
|
|
478
498
|
**关掉的含义**:只是在之后的启动时不再自动接管(headless/TUI/base 的 host 平面不受影响)——
|
|
479
499
|
它**不会**还原之前已接管的预设,要还原用 `npm run web-compaction:revert`;
|
|
480
500
|
- **逐预设判定,只碰 stock 布局**——用户自定义过 compaction 组的预设,以及根本没有 compaction 组的
|
|
@@ -520,15 +540,16 @@ Context GC 的装配在**两个平面**——web 现在**全部自动**,零配
|
|
|
520
540
|
|
|
521
541
|
#### 从 npm 安装后的第一印象(可感知 / 易引导 / 易配置)
|
|
522
542
|
|
|
523
|
-
-
|
|
524
|
-
|
|
543
|
+
- **半自动(opt-in)**:默认保留 DSH 自己的摘要;在设置卡打开 `gcReplacesCompaction`(host 平面)与
|
|
544
|
+
`autoWebCompaction`(web 预设)后,启动一次即由 `mountCompactionEngine` 接管、并把全部 stock
|
|
545
|
+
预设改写成 `dsh-engram/compaction`。开启后无需再手动改文件。
|
|
525
546
|
- **可感知**:插件启动时把权威状态写到 `$DSH_HOME/engram/context-gc.status.json`
|
|
526
547
|
(`host` 平面模式 + `web` 平面每个预设的接管结果 + 生效配置)。随时
|
|
527
548
|
`npx dsh-engram status` 或 `npx dsh-engram doctor` 查看;web 记忆看板(ESR 任务看板)头部也有
|
|
528
549
|
一枚状态徽标("Context GC·主机 ·N 预设",来自 overview API)。启动日志也有两行关键确认:
|
|
529
550
|
`engram context-gc: compaction = Context GC …` 与 `engram web-provision: wired Context GC into preset …`。
|
|
530
|
-
- **易配置**:一个设置卡(「记忆 GC」区)管全部:`autoWebCompaction`(web
|
|
531
|
-
`gcReplacesCompaction`(用 Context GC
|
|
551
|
+
- **易配置**:一个设置卡(「记忆 GC」区)管全部:`autoWebCompaction`(web 自动接管,默认关)、
|
|
552
|
+
`gcReplacesCompaction`(用 Context GC 还是宿主摘要,默认关)、`gcNarrative`(叙事兜底开关)——
|
|
532
553
|
改动后 `dsh web` 重启生效,web 预设行会被自动刷新成新配置。
|
|
533
554
|
|
|
534
555
|
**验证是否生效**:`dsh web`(或对应 profile)重启后——
|
|
@@ -541,7 +562,7 @@ Context GC 的装配在**两个平面**——web 现在**全部自动**,零配
|
|
|
541
562
|
- (若见 `… keeping the existing compaction service` 说明同域已有 provider、未替换成功;`web-provision … skipped (custom)`
|
|
542
563
|
说明某预设是自定义/无 compaction 布局、未被触碰;`dsh-compaction-basic unavailable` 说明环境缺依赖,自动回退默认压缩。)
|
|
543
564
|
|
|
544
|
-
### BoundaryPrune
|
|
565
|
+
### BoundaryPrune(子任务边界剪枝,默认开 + 账本否决)
|
|
545
566
|
|
|
546
567
|
Context GC 管「压缩的摘要内容」,BoundaryPrune 管「确定性剪枝的触发时机」——
|
|
547
568
|
在 todo 完成推进 / goal 终态这些子任务边界,主动调用 DSH 自带的
|
|
@@ -566,10 +587,13 @@ Context GC 管「压缩的摘要内容」,BoundaryPrune 管「确定性剪枝
|
|
|
566
587
|
并配更小保留边缘(`boundaryPruneHeadChars`/`boundaryPruneTailChars`)可更早
|
|
567
588
|
开剪——T2048+小边缘在真实语料上首剪节省是宿主默认的 2.4 倍(10.14M vs 4.23M
|
|
568
589
|
字符)。降阈值在 `resultPack` 开启时安全(被剪中段有归档兜底)。
|
|
569
|
-
-
|
|
570
|
-
|
|
590
|
+
- 默认**开**:`boundaryPrune: true`;`false` 是 opt-out。自适应闸门
|
|
591
|
+
(`boundaryPruneAdaptive: true`,默认开)让 Context Ledger 在该 workspace 真实剪枝后
|
|
592
|
+
净收益为负(≥3 次)时自动停剪——证据只能关、不会自行开。启动日志出现
|
|
593
|
+
`engram boundary-prune (todo @N reqs): pruned …`;被账本否决时出现
|
|
594
|
+
`engram boundary-prune: ledger gate holds for …`。
|
|
571
595
|
|
|
572
|
-
### ResultPack L2(结果归档 + `result_recall
|
|
596
|
+
### ResultPack L2(结果归档 + `result_recall`,默认开)
|
|
573
597
|
|
|
574
598
|
让 BoundaryPrune 剪枝**无损**:每个被剪工具结果的被移除中段,按与记忆写入
|
|
575
599
|
相同的规则脱敏后归档到 `~/.dsh/engram/resultpack/<callId>.json`,并在剪枝
|
|
@@ -584,8 +608,9 @@ Context GC 管「压缩的摘要内容」,BoundaryPrune 管「确定性剪枝
|
|
|
584
608
|
[ENGRAM] 索引);保留期 `resultPackRetentionDays`(默认 7 天)按 mtime 清理,
|
|
585
609
|
搭 GC 同一节奏。
|
|
586
610
|
- **自我禁用**:只开 L2 不开 L1 将无内容可归档,故不注册工具并打一条警告。
|
|
587
|
-
-
|
|
588
|
-
|
|
611
|
+
- 默认**开**:`resultPack: true`(与默认开启的 L1 配对,保证默认剪枝无损);
|
|
612
|
+
关掉后 L1 仍可工作,但被剪中段不可召回。开启时启动日志出现
|
|
613
|
+
`engram result-pack enabled: result_recall(callId, offset) registered`。
|
|
589
614
|
|
|
590
615
|
### 激活遥测(SoL-Pi M15/C13)
|
|
591
616
|
|
|
@@ -600,6 +625,45 @@ overview)现在返回 `activation: { boundaryPrune, recall }`:
|
|
|
600
625
|
(engram_recall 查询 → 命中 → engram_detail 下钻)闭合,可看到
|
|
601
626
|
注入→查询→下钻的完整激活。
|
|
602
627
|
|
|
628
|
+
### Context Ledger(净收益账本)
|
|
629
|
+
|
|
630
|
+
把「省 token」变成可核对的账。每个模型请求记一笔:注入的 `[ENGRAM]`/`[RECALL]`
|
|
631
|
+
与 `[ESR]` 块按存活请求数计入成本;被 BoundaryPrune 剪掉的结果按后续请求数计入
|
|
632
|
+
节省;每次剪枝按 `(1 − ledgerCacheDiscount)` 计一次前缀重写罚金(KV 缓存击穿)。
|
|
633
|
+
`GET /api/dsh-engram/stats` 与 `/overview` 返回 `ledger`:
|
|
634
|
+
|
|
635
|
+
- `totals` — `requests / injectedChars / avoidedChars / rewriteCount / rewriteChars /
|
|
636
|
+
netChars / netTokens`(`net = avoided − injected − rewriteChars × (1 − discount)`);
|
|
637
|
+
- `byWorkspace` / `byDay` — 按工作区、按天的同一口径,`byDay` 倒序;
|
|
638
|
+
- `openSessions` — 仍在累计、尚未落盘的会话数(进程重启最多丢 `flushEvery` 个请求的账)。
|
|
639
|
+
|
|
640
|
+
GUI「遥测」页签直接画这块账本(净 token 大数字 + 节省/注入/重写罚金三卡 + 近 14 天红绿柱),
|
|
641
|
+
记忆概览页也多一张「上下文净 token」卡。落盘在 `~/.dsh/engram/ledger.json`(原子写、按天滚动、
|
|
642
|
+
delta 落盘),进程内只做整数累加,热路径零 I/O、零模型调用。默认 `ledgerEnabled: true`、
|
|
643
|
+
`ledgerCacheDiscount: 0.1`;关掉 = 不挂监听、不写文件。**口径诚实**:token 按
|
|
644
|
+
`chars / 4` 估算,不含 provider 实际计费与模型质量差;Context GC 的压缩节省暂未
|
|
645
|
+
接入(宿主未暴露前后大小),因此账本只记「可证明」的部分。
|
|
646
|
+
|
|
647
|
+
### JIT 推送(v0.6-C)
|
|
648
|
+
|
|
649
|
+
拉取式召回被实证休眠(112 会话仅 24 次 `engram_recall`、8 次 `engram_detail`),所以
|
|
650
|
+
v0.6 增加按事件**推送**:三个确定性事件,命中才推、每次一行、每会话最多 3 行(`jitMaxLines`,
|
|
651
|
+
每行 `jitMaxLineChars`=220):
|
|
652
|
+
|
|
653
|
+
| 事件 | 触发条件 | 推什么 |
|
|
654
|
+
|---|---|---|
|
|
655
|
+
| 错误复发 | 同一 `cmd:` 签名第二次失败,且已有 error/procedure 记忆 | 该记忆的 id + 一行摘要 + `engram_detail` 下钻 |
|
|
656
|
+
| 文件焦点 | 同一文件连续第二次编辑,且有 filePath/dir 锚定记忆 | 优先 preference,其次 fact/decision |
|
|
657
|
+
| 目标完成 | goal complete/block 且有 active ESR 任务 | 前两个未闭环任务 + `esr_status` 提示 |
|
|
658
|
+
|
|
659
|
+
- **append-only**:推送行一旦出现就不再改写/撤回,前缀每次推送只变一次;
|
|
660
|
+
每次推送按 `estimatePrefixChars + 行长度` 记一次重写罚金(Context Ledger 的
|
|
661
|
+
`rewriteCount` / `rewriteChars`),净收益可在遥测页直接看。
|
|
662
|
+
- **无命中沉默**:没有可指向的记忆/任务就不推——宁可不推,也不灌噪声。
|
|
663
|
+
- **零 LLM、纯规则**;`jitEnabled:false` 一键关,`[JIT]` section 为空时不占任何 token。
|
|
664
|
+
- **尚未做**:resume brief(隔天继续)与「预计剩余请求不足时跳过推送」的显式 ROI 门——
|
|
665
|
+
当前靠 3 行硬预算 + 账本观测。
|
|
666
|
+
|
|
603
667
|
## 自动捕获策略
|
|
604
668
|
|
|
605
669
|
捕获是确定性、离线的——只看到工具*结果*,从不看对话本身。什么会被记录成一条记忆:
|
|
@@ -672,12 +736,13 @@ promote: 2 pending todo(s) vs 1 ESR task(s) — esr_task(name="…") #suggest-pr
|
|
|
672
736
|
autoCapture: true # 零 LLM 工具结果捕获
|
|
673
737
|
autoCapturePreferences: true # 零 LLM 用户纠正/偏好捕获(prefer/avoid/switch-to 句式)
|
|
674
738
|
preferenceCapturePerSession: 8 # 每会话偏好记忆条数上限
|
|
675
|
-
boundaryPrune:
|
|
739
|
+
boundaryPrune: true # ResultPack L1:todo/goal 边界剪掉超阈值旧工具结果(默认开)
|
|
740
|
+
boundaryPruneAdaptive: true # 账本否决:该 workspace 净收益为负(≥3 次剪枝)时自动停剪
|
|
676
741
|
boundaryPruneThresholdChars: 0 # 阈值覆盖(0=宿主 8192;如 2048 可更早开剪)
|
|
677
742
|
boundaryPruneHeadChars: 0 # 覆盖时的保留头部(0=宿主 4096)
|
|
678
743
|
boundaryPruneTailChars: 0 # 覆盖时的保留尾部(0=宿主 1024)
|
|
679
744
|
boundaryPruneIdleCadence: 0 # 空闲步数边界(0=仅事件边界;覆盖无 todo/goal 会话)
|
|
680
|
-
resultPack:
|
|
745
|
+
resultPack: true # ResultPack L2:剪掉的中段脱敏归档 + result_recall 按页召回(默认开,须与 L1 同开)
|
|
681
746
|
resultPackRetentionDays: 7 # 归档保留天数(mtime 清理,走 GC 节奏)
|
|
682
747
|
sessionSearch: true # engram_recall 也可对历史会话 FTS
|
|
683
748
|
recallScope: workspace # 召回范围:workspace(严格工作区隔离,默认)| global(可选跨工作区召回,带 [W:<ws>] 来源标记)
|
|
@@ -695,9 +760,12 @@ promote: 2 pending todo(s) vs 1 ESR task(s) — esr_task(name="…") #suggest-pr
|
|
|
695
760
|
gcEnabled: true # 定时记忆 GC
|
|
696
761
|
gcIntervalHours: 24 # 回收节奏
|
|
697
762
|
gcStableRetentionDays: 120 # 超过此天数的 stable 任务离开 [ESR]
|
|
698
|
-
gcReplacesCompaction:
|
|
763
|
+
gcReplacesCompaction: false # Context GC:接管 DSH 自动 compact(默认关=宿主 LLM 压缩;true=opt-in 指针摘要)
|
|
699
764
|
gcNarrative: true # 无锚轮次走 scoped LLM 叙事;false=纯机械(零 LLM)
|
|
700
|
-
|
|
765
|
+
jitEnabled: true # JIT 推送:错误复发/文件焦点/goal 完成时推一行已有记忆
|
|
766
|
+
ledgerEnabled: true # Context Ledger:注入成本/剪枝节省/前缀重写罚金 → 净 token
|
|
767
|
+
ledgerCacheDiscount: 0.1 # 缓存折价:重写按 (1−0.1) 计罚金;0.1 = 命中只付 10%
|
|
768
|
+
autoWebCompaction: false # web 预设自动改写(默认关;开启需显式确认,可用 revert 还原)
|
|
701
769
|
boundaryPruneMinRemaining: 50 # 偿还门:预计剩余请求数低于此值不剪
|
|
702
770
|
engramIndexOrder: 40 # systemPrompt section 顺序(位于 tools 段之前)
|
|
703
771
|
esrOrder: 41
|
|
@@ -706,7 +774,7 @@ promote: 2 pending todo(s) vs 1 ESR task(s) — esr_task(name="…") #suggest-pr
|
|
|
706
774
|
## 开发
|
|
707
775
|
|
|
708
776
|
```sh
|
|
709
|
-
npm test #
|
|
777
|
+
npm test # 359 个测试:核心 + Web API + GC + Context GC + ESR 触发 + Context Ledger + JIT(node:test)
|
|
710
778
|
npm run build:client
|
|
711
779
|
```
|
|
712
780
|
|