dsh-prime-memory 0.26.5-beta.0 → 0.26.6

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.en.md +62 -1
  3. package/README.md +52 -1
  4. package/dist/client.js +36785 -134
  5. package/dist/config.d.ts +9 -0
  6. package/dist/config.js +8 -0
  7. package/dist/contract.d.ts +76 -0
  8. package/dist/embedding-child.cjs +192 -0
  9. package/dist/embedding-worker.cjs +2 -0
  10. package/dist/graph/apply.d.ts +9 -0
  11. package/dist/graph/apply.js +12 -2
  12. package/dist/graph/constraints.d.ts +3 -1
  13. package/dist/graph/constraints.js +4 -2
  14. package/dist/graph/preview.d.ts +92 -0
  15. package/dist/graph/preview.js +186 -0
  16. package/dist/graph/search.d.ts +32 -6
  17. package/dist/graph/search.js +102 -12
  18. package/dist/graph/types.d.ts +26 -1
  19. package/dist/graph/types.js +26 -1
  20. package/dist/hooks/recall.js +36 -2
  21. package/dist/index.js +23 -3
  22. package/dist/llm.d.ts +7 -2
  23. package/dist/llm.js +14 -22
  24. package/dist/pipeline/graph.d.ts +26 -1
  25. package/dist/pipeline/graph.js +74 -4
  26. package/dist/pipeline/l1.js +87 -26
  27. package/dist/pipeline/md-sync.js +4 -2
  28. package/dist/pipeline/runner.d.ts +26 -0
  29. package/dist/pipeline/runner.js +74 -7
  30. package/dist/pipeline/slot-migrate.d.ts +3 -2
  31. package/dist/pipeline/slot-migrate.js +3 -2
  32. package/dist/projection/recall.d.ts +10 -3
  33. package/dist/projection/recall.js +14 -0
  34. package/dist/settings.js +3 -0
  35. package/dist/stats.d.ts +1 -1
  36. package/dist/stats.js +47 -12
  37. package/dist/store/embedding-source.d.ts +4 -2
  38. package/dist/store/embedding-source.js +5 -2
  39. package/dist/store/graph-store.d.ts +111 -4
  40. package/dist/store/graph-store.js +324 -15
  41. package/dist/store/l1.d.ts +17 -9
  42. package/dist/store/l1.js +55 -18
  43. package/dist/store/local-embedding.d.ts +9 -5
  44. package/dist/store/local-embedding.js +137 -17
  45. package/dist/store/memory-md-disable.d.ts +3 -2
  46. package/dist/store/memory-md.d.ts +3 -3
  47. package/dist/store/memory-md.js +6 -4
  48. package/dist/store/runtime-installer.d.ts +13 -1
  49. package/dist/store/runtime-installer.js +40 -2
  50. package/dist/store/session-recalled.d.ts +9 -3
  51. package/dist/store/session-recalled.js +24 -5
  52. package/dist/store/sqlite.d.ts +24 -12
  53. package/dist/store/sqlite.js +97 -31
  54. package/dist/store/supersede.d.ts +10 -2
  55. package/dist/store/supersede.js +10 -2
  56. package/dist/store/validity.d.ts +150 -0
  57. package/dist/store/validity.js +209 -0
  58. package/dist/tools/index.d.ts +15 -1
  59. package/dist/tools/index.js +393 -11
  60. package/dist/types.d.ts +9 -0
  61. package/dist/util/json-repair.d.ts +48 -0
  62. package/dist/util/json-repair.js +285 -0
  63. package/dist/validity-backfill.d.ts +78 -0
  64. package/dist/validity-backfill.js +160 -0
  65. package/dsh.plugin.json +2 -2
  66. package/package.json +5 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # 更新日志(Changelog)
2
2
 
3
+ ## [0.26.6] — 2026-10-22
4
+
5
+ ### 新增
6
+
7
+ - **图谱确定性写面(计划 graph-write-plane)**:写面从"add/delete/import"补齐"改、重投、迁"三语义。
8
+ - `memory_update`(高权限):修订一条既有记忆——就地产新版本(version+1,新 id),旧版经退场汇流口
9
+ `superseded` 软删(可恢复),随后对 [旧,新] 强制重投让图谱边跟随;extKey 不随血缘走(幂等索引由旧行占位)。
10
+ - `memory_reproject`(需 `graph.enabled`):抹掉"已按当前版本投影"凭证、按高优先级重新入队——绕开
11
+ `projector_version` 永久跳过;幂等(在途任务不堆重)。手加/导入的记忆长期不出现在图谱里的纠正通道。
12
+ - `memory_migrate_relation`(高权限):源导式关系迁移——硬校验来源全部"现存未退场"(判据单源
13
+ `classifyValidity`)→ 显式边提案经 `applyGraphProjection` 纯函数校验落库(同 (起点,关系) 换目标自动闭旧边
14
+ 出新边)→ 新增承载新关系的 L1 源记录留可回溯根据(metadata `proposal_source='tool'` + 决策凭证)。
15
+ 全程不提供、也不会提供绕过投影直写 `graph_*` 表的入口(零无源事实不变量)。
16
+ - **非蒸馏写入自动入投影队**:`memory_add`/`memory_import` 与蒸馏产出同优先级(`GRAPH_PRIORITY_NEW`)进队——
17
+ 闭合"只有蒸馏才投影"的旁路缺口(手加记录 projected=None 的真根因)。图谱向量路缺陷同步修复:
18
+ 嵌入启用时投影收尾为落库的 active 节点补写 `graph_node_vec`(旧版本该调用生产零落点、全库 0 行)。
19
+ - **记忆时效三档与工具反查(计划 expiry-tiering,ADR-0022)**:退场方式/有效性定性/持续性/现实有效期
20
+ 四轴正交,六态(current/historical/expired/expired_suspect/superseded/retired)判据单源 `classifyValidity`(查询期谓词,
21
+ 不落库翻态);`dsh_validity` metadata 标注落写侧汇流口(证据链 activity_*→evidence、工具直填→llm_inferred、
22
+ 兜底→unknown)。门2 灰度闸 `validity.tieringEnabled`(默认关):开时被动注入剔 `expired`、`expired_suspect`
23
+ 保留带"疑似失效"标注,召回卡显示 `validity`/`validUntil`。门3:`memory_search` 新增 `include_expired` /
24
+ `as_of`(有效期回放,不复活退场)/ `follow_supersede`(顺/逆取代链)三参数,全缺省时输出与改前逐字一致。
25
+ 存量标注由零 LLM 的 `validity-backfill` 低频补齐(启动 3 分钟首轮、6h 续跑;改过的记录顺手重投图谱保鲜)。
26
+
27
+ ### 修复
28
+
29
+ - **门1 解耦:合法历史 valid_to 不再被静默遮蔽**(bugfix,不受灰度门控):退场判据全仓改为只认取代标记
30
+ (`retiredL1Sql`/`isRetired`/md 投射层同口径一对);`retire()` 不再闭合 valid_to,它回归纯现实有效期。
31
+ 升版后首启自动做一次 FTS 全量回灌收敛误遮蔽历史(`gate1.retire-decoupled.v1` 戳幂等,日志报回灌/跳过数;
32
+ 向量面由增量重嵌自动补齐或设置页手动重建加速);面板"已退场"区/删除线/计数随之只认真退场行。
33
+ - **退场→图谱退役传播补腿(R9)**:软删/取代后按"来源是否全部退场态"重算清扫——全退场的 active/disputed
34
+ 节点·边标 archived 墓碑(保留行 expand 可见),来源全部复活(restore)则拉回 active;多源支撑的节点不误杀。
35
+ - **md 同步退场收敛**:`.disable` 回灌的"已退场"判据换 marker 单源,修复同批翻转波及的"第二轮重复计数、
36
+ 永不收敛 same"。
37
+
3
38
  ## 0.26.2 (2026-10-18)
4
39
 
5
40
  - hosts: 追加 0.2.1-rc.2 声明面枚举(34/34 @deepseek-ai/* 宿主 peer 逐包 npm 实测 rc.2 在版;本插件不触 ctx.web provider 与 conversation.input.model.label 槽,代码零改动,纯元数据发版;农场 rc.2 格挂账待命)
@@ -22,6 +57,10 @@
22
57
  - **撤下浮动球 UI(`client/src/longtask-fab.ts`;beta.1 起曾随包发布)**:悬浮建议面板的归属本在 context-compression 侧(「建议启动压缩」是其领域),pm 属误载——2026-10-02 用户裁定撤下。撤下不违座位契约(settings.section 恰一个 + 输入栏 pill,body 单例不占座位),但全应用级 overlay 会与其他插件的悬浮 UI 抢占屏幕角落;长任务开关与手动压缩入口待长任务定版时落记忆设置分节。
23
58
  - **`session-mode-set` 的 `mode` 转为可选**:与 `longTask` 二选一必传——纯切长任务开关不再被迫发送档位(旧客户端恒传 mode,行为不变)。响应 `mode` 改回当前生效值。
24
59
 
60
+ ### 修复
61
+
62
+ - **嵌入推理子进程隔离,根治 libvips DLL 撞名(`fix #11`)**:旧路径把 transformers 推理放在 worker_threads 子线程,与宿主 Electron 同进程——插件 runtime 的 sharp/libvips 与宿主 sharp/libvips 同名不同路径时在 OS LoadLibrary 层冲突(切大模型 bge-small→bge-m3 时崩溃)。现在默认改走 `child_process.fork()` 独立子进程(`resources/embedding-child.cjs`,主线程侧 `RealChildChannel` 协议代理),DLL 表物理隔离;配置经 env `DSH_EMBED_CFG` 传递,向量经 number[][] 序列化回传(512d×32 条 ≈64KB,<5ms,实测 batch32 含序列化 91ms、单条中位数 5ms),零拷贝 transfer 降级为可忽略开销。旧 `RealWorkerChannel` 与 `embedding-worker.cjs` 保留一版作回滚逃生门(`opts.useWorker=true`,下版删);`RuntimeInstaller.isReady()` 兼验 sharp 平台原生件就位(--ignore-scripts 半装状态检出即触发重装)。真机 worker↔child 32 对向量 cosine=1.0(IEEE754 float32 往返无损)。用户无感知,非 breaking。
63
+
25
64
  ## [0.26.1] — 2026-10-15
26
65
 
27
66
  ### 新增
package/README.en.md CHANGED
@@ -474,7 +474,9 @@ adds 12 agent-facing memory tools (high-privilege writes `memory_add` / `memory_
474
474
  `memory_import`, ruminate controls `memory_ruminate`, the memory graph
475
475
  `memory_search_graph` / `memory_expand_graph_node`, decision-receipt backtracking
476
476
  `memory_receipts`, and conflict adjudication `memory_resolve_conflict`), the `skills/memport`
477
- cross-tool memory transfer, and storefront screenshot declarations.
477
+ cross-tool memory transfer, and storefront screenshot declarations; the deterministic
478
+ write-plane adds three more (`memory_update` / `memory_reproject` / `memory_migrate_relation`,
479
+ see the "Deterministic graph write plane" section).
478
480
 
479
481
  Two of those tools exist for **traceability**:
480
482
 
@@ -518,6 +520,65 @@ The restore entry point accepts **directory names only, never paths**: otherwise
518
520
 
519
521
  > **One semantic you need to know**: `cleanup-retired` only removes **already-retired** records, and the snapshot is taken **before** deletion — so every record a cleanup snapshot can bring back carries a retirement marker. By default `snapshot-restore` only writes the row back to the main table (and reports it honestly in `stillRetired`); **"back in the main table" ≠ "back in recall"**. For a genuine one-call rollback add `unretire: true`, or call `records-restore` on that batch of ids afterwards.
520
522
 
523
+ ## Memory expiry tiers and supersede-chain lookup
524
+
525
+ A memory's "temporality" splits into **four non-substitutable axes** ([ADR-0022](./docs/adr/0022-expiry-tiering-and-validity.md)):
526
+ retirement mode (supersede marker), validity state (derived at query time), objective persistence, and the
527
+ real-world validity window (`valid_to`). The old model crammed all four into one `valid_to` column — the cost
528
+ was that perfectly legal historical memories ("a trip that ended in 2020") were **silently shadowed from the
529
+ retrieval surface** although they never retired.
530
+
531
+ | Tier | Meaning | Indexed | Auto-injected (default) | Explicit tool query |
532
+ | --- | --- | --- | --- | --- |
533
+ | `current` | open-ended, not past its window | ✅ | ✅ | ✅ |
534
+ | `historical` | point/closed-span/timeless, not retired | ✅ | ✅ | ✅ |
535
+ | `expired` | window closed **with trustworthy evidence** | ✅ | ❌ (gated, gate 2) | ✅ `include_expired` |
536
+ | `expired_suspect` | same but the window source is untrustworthy (flag, never hide) | ✅ | ✅ annotated | ✅ |
537
+ | `superseded` / `retired` | soft-deleted (restorable) | ❌ | ❌ | via supersede chain only |
538
+
539
+ Three gates:
540
+
541
+ - **Gate 1 (bugfix, ungated)**: retirement is judged by the marker alone, everywhere; the first boot after
542
+ upgrade runs one full FTS back-fill that returns wrongly-shadowed history to the retrieval surface
543
+ (log reports back-filled/skipped counts; vectors catch up incrementally or via the manual re-index button).
544
+ - **Gate 2 (grey flag `validity.tieringEnabled`, off by default)**: when on, passive injection drops
545
+ `expired` and keeps `expired_suspect` with a "suspected expired" annotation; recall bubbles show
546
+ "expired since X". A same-named runtime toggle (OR-ed with the deploy config) lives on the settings overview.
547
+ - **Gate 3 (`memory_search` parameters, all off by default = byte-identical to before)**: `include_expired`
548
+ admits trustworthy-expired rows with `state`/`valid_from`/`valid_to`/`valid_to_source`; `as_of` replays the
549
+ validity axis at a past moment (never reviving retired rows); `follow_supersede` walks the supersede chain
550
+ to answer "what did this entry replace".
551
+
552
+ Legacy rows get their `dsh_validity` annotation from a low-frequency local back-fill (zero LLM; touched
553
+ records are re-projected into the graph to keep it fresh). The classifier is a single source: the six tiers
554
+ are query-time predicates, never wall-clock-driven stored state.
555
+
556
+ ## Deterministic graph write plane and the correction channel
557
+
558
+ The graph is a **derived projection** of L1: nodes/edges are always recomputed from current
559
+ facts, so the single source of truth for every write is L1 itself —
560
+ **correction = edit the source + reproject, never hand-written SQL**. This plugin does not
561
+ offer, and will never offer, an entry that bypasses projection to write `graph_*` tables
562
+ directly ("zero source-less facts" invariant: every edge traces back to live L1 records via
563
+ `sourceRecordIds`).
564
+
565
+ | Action | Tool | Preconditions | Notes |
566
+ | --- | --- | --- | --- |
567
+ | Revise one memory | `memory_update` | high-privilege mode | Read old → create new (`version+1`, new id) → old row retires via the shared soft-delete confluence with a `superseded` marker (restorable) → new version enters retrieval; then both [old, new] ids are force-reprojected so graph edges follow (edges supported only by the old source get tombstoned). Not a physical delete; the JSONL fact source is append-only and never rewritten |
568
+ | Force reprojection | `memory_reproject` | `graph.enabled` | Erases the "already projected at current version" receipts and re-enqueues at top priority, bypassing the permanent `projector_version` skip. Idempotent: in-flight jobs never pile up. **Manually added/imported memories that never showed up in the graph: this is the back-fill projection channel** (non-distilled writes now auto-enqueue; the tool remains the correction path for legacy rows and post-edit freshness) |
569
+ | Migrate one relation | `memory_migrate_relation` | high-privilege mode | Source-derived semantics: hard-validate that every `source_record_ids` is live and un-retired → the new relation lands through the deterministic projection branch (same (from, relation) with a new target closes the old edge) → a new L1 carrier record is written as the traceable basis (tagged `proposal_source=tool` plus a decision receipt). Old edges are not flipped back by later rejections: the reprojection batch pulls only the carrier, not sources whose text still describes the old relation |
570
+ | Non-distilled writes auto-enqueue | `memory_add` / `memory_import` | `graph.enabled` | After a successful write, records join the projection queue at the same priority as distillation output (`GRAPH_PRIORITY_NEW`) — the "only distillation projects" bypass is closed |
571
+
572
+ Two boundaries worth knowing:
573
+
574
+ - **Frequent updates accumulate version rows**: retired old rows stay in the main table (the
575
+ price of restorability); volume is governed by the existing `cleanup-retired` (dry-run +
576
+ snapshot gate).
577
+ - **The graph vector path activates with the embedding source**: `graph_node_vec` is
578
+ *structurally absent* when embeddings are off (not an empty table); once embeddings are on,
579
+ projection wrap-up writes vectors for freshly landed active nodes (legacy nodes catch up
580
+ via reprojection/rebuild).
581
+
521
582
  ## Roadmap
522
583
 
523
584
  Features under planning — feedback and priorities welcome in the
package/README.md CHANGED
@@ -461,6 +461,56 @@ fsync),断电等极端崩溃最多丢最后一小段尾部,检索库可用
461
461
 
462
462
  > **一处必须知道的语义**:`cleanup-retired` 只清理**已退场**记录,而快照拍在删除**之前**——所以清理快照能找回的每一条都带着退场标记。默认情况下 `snapshot-restore` 只把行写回主表(并在 `stillRetired` 里如实报出),**"回到主表" ≠ "回到召回"**;要一步完成真正的回滚,加 `unretire: true`,或随后对该批 id 调 `records-restore`。
463
463
 
464
+ ## 记忆时效三档与失效链反查
465
+
466
+ 一条记忆的"时间性"拆成**四根互不替代的轴**(ADR-0022):退场方式(取代标记)、有效性定性
467
+ (查询期派生六态)、客观持续性(persistence)、现实有效期(valid_to)。旧版把这四件事塞进
468
+ 一根 `valid_to` 列,代价是"2020 年结束的旅行"这类**合法历史记录被检索面静默遮蔽**——
469
+ 它没退场,只是成了历史。
470
+
471
+ | 档 | 含义 | 进索引 | 被动注入(默认) | 工具显式查 |
472
+ | --- | --- | --- | --- | --- |
473
+ | `current` | 仍在持续且未到有效期 | ✅ | ✅ | ✅ |
474
+ | `historical` | 时点/已结束区间/无时间性,未退场 | ✅ | ✅ | ✅ |
475
+ | `expired` | 有效期已闭合**且来源可信** | ✅ | ❌ 需开门2 | ✅ `include_expired` |
476
+ | `expired_suspect` | 同上但有效期来源不可信(宁判疑不静默隐) | ✅ | ✅ 带标注 | ✅ |
477
+ | `superseded` / `retired` | 取代/人工退场(软删,可恢复) | ❌ 撤出 | ❌ | 仅取代链反查 |
478
+
479
+ 三扇门:
480
+
481
+ - **门1(bugfix,不受灰度门控)**:退场判据全仓改为只认取代标记;升版后首启自动做一次
482
+ FTS 全量回灌,把误遮蔽的历史记忆放回检索面(日志报回灌/跳过数;向量面由增量重嵌补齐,
483
+ 或设置页手动「语义检索重建」加速)。
484
+ - **门2(灰度闸 `validity.tieringEnabled`,默认关)**:开时被动注入剔除 `expired`,
485
+ `expired_suspect` 保留并在注入行带"疑似失效"标注;召回卡泡泡同步显示"已于 X 失效"。
486
+ 面板概览有同名运行时开关(与部署配置取或),验证通过后再评估翻默认。
487
+ - **门3(`memory_search` 反查参数,默认全关 = 与改前逐字一致)**:`include_expired` 放行
488
+ 可信过期项并附 `state`/`valid_from`/`valid_to`/`valid_to_source`;`as_of` 按有效期回放
489
+ 历史时刻(不复活退场记忆);`follow_supersede` 顺取代链反查"本条取代了谁"。
490
+
491
+ 存量记录的 `dsh_validity` 标注由低频本地回填补齐(零 LLM;改过的记录顺手重投图谱保鲜)。
492
+ 判据单源 `classifyValidity`:六态是查询期谓词,不会随墙钟落库翻态。
493
+
494
+ ## 图谱确定性写面与纠正通道
495
+
496
+ 图谱是 L1 的**派生投影**:节点/边永远由"当前事实重算"产出,所以写面的唯一真源是 L1,
497
+ **纠正 = 改源 + 重投,不是手写 SQL**。本插件不提供、也永远不会提供绕过投影直写
498
+ `graph_*` 表的入口("零无源事实"不变量:每条边都能沿 `sourceRecordIds` 点查回现存 L1 记录)。
499
+
500
+ | 动作 | 工具 | 前提 | 说明 |
501
+ | --- | --- | --- | --- |
502
+ | 修订一条记忆 | `memory_update` | 高权限模式 | 读旧 → 造新(`version+1`,新 id)→ 旧行经退场汇流口 `superseded` 软删(可恢复)→ 新版进检索面;随后对 [旧,新] 强制重投,图谱边跟随(旧源支撑的边自动标墓碑)。不是物理删,也不覆写 JSONL 事实源 |
503
+ | 强制重投 | `memory_reproject` | 配置 `graph.enabled` | 抹掉"已按当前版本投影"凭证、按高优先级重新入队——绕开 `projector_version` 的永久跳过。幂等:在途任务不堆重。**手加/导入的记忆长期不出现在图谱里,用它补投影**(非蒸馏写入现已自动入队,此工具是给存量与改后保鲜的纠正通道) |
504
+ | 迁移一条关系 | `memory_migrate_relation` | 高权限模式 | 源导语义:先硬校验 `source_record_ids` 全部"现存未退场" → 新关系经确定性投影支路落库(同 (起点,关系) 换目标自动闭旧边出新边)→ 新增一条承载新关系的 L1 源记录留可回溯根据(带 `proposal_source=tool` 审计标记与决策凭证)。旧边不会因后续重投被翻回:重投批只拉载体记录,不拉描述旧关系的旧源 |
505
+ | 非蒸馏写入自动入队 | `memory_add` / `memory_import` | 配置 `graph.enabled` | 落库成功后与蒸馏产出同优先级(`GRAPH_PRIORITY_NEW`)进投影队——"只有蒸馏才投影"的旁路缺口已闭合 |
506
+
507
+ 两条必须知道的边界:
508
+
509
+ - **频繁 update 会累积版本行**:旧行以退场态留在主表(可恢复的设计代价),规模由既有
510
+ `cleanup-retired`(干跑 + 快照门禁)控制;
511
+ - **图谱向量路随嵌入源激活**:`graph_node_vec` 在嵌入关闭时**结构性不存在**(不是空表);
512
+ 启用嵌入后,投影收尾会为落库的 active 节点补写向量(旧版本存量节点经重投/重建逐步补齐)。
513
+
464
514
  ## 路线图
465
515
 
466
516
  以下为规划中的功能,欢迎在 [Issues](https://github.com/drscrewdriver/dsh-prime-memory/issues) 反馈需求与优先级:
@@ -477,7 +527,8 @@ fsync),断电等极端崩溃最多丢最后一小段尾部,检索库可用
477
527
  相对上游,本仓库新增了面向 Agent 的 12 个记忆工具(含高权限写入 `memory_add` / `memory_delete` /
478
528
  `memory_import`、反刍控制 `memory_ruminate` 系列、记忆图谱 `memory_search_graph` /
479
529
  `memory_expand_graph_node`、决策凭证回溯 `memory_receipts`、矛盾裁决 `memory_resolve_conflict`)、
480
- `skills/memport` 跨工具记忆搬运,以及商店截图声明。
530
+ `skills/memport` 跨工具记忆搬运,以及商店截图声明;确定性写面计划又补上三件
531
+ (`memory_update` / `memory_reproject` / `memory_migrate_relation`,见"图谱确定性写面"一节)。
481
532
 
482
533
  其中两个工具服务于**可追溯性**:
483
534