dsh-prime-memory 0.21.0 → 0.22.2

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 (63) hide show
  1. package/dist/client.js +1581 -1150
  2. package/dist/config.d.ts +149 -0
  3. package/dist/config.js +35 -0
  4. package/dist/conflict-service.d.ts +8 -0
  5. package/dist/conflict-service.js +19 -0
  6. package/dist/contract.d.ts +131 -0
  7. package/dist/domain-gate.d.ts +8 -0
  8. package/dist/domain-gate.js +30 -0
  9. package/dist/graph/constraints.d.ts +4 -2
  10. package/dist/graph/constraints.js +4 -2
  11. package/dist/hooks/recall.d.ts +2 -0
  12. package/dist/hooks/recall.js +21 -2
  13. package/dist/hooks/skill-recall.d.ts +25 -0
  14. package/dist/hooks/skill-recall.js +72 -0
  15. package/dist/index.d.ts +98 -0
  16. package/dist/index.js +26 -1
  17. package/dist/memport/format.d.ts +70 -0
  18. package/dist/memport/format.js +305 -0
  19. package/dist/memport/prefilter.d.ts +62 -0
  20. package/dist/memport/prefilter.js +132 -0
  21. package/dist/memport/scan.d.ts +13 -0
  22. package/dist/memport/scan.js +100 -0
  23. package/dist/metadata-validators.d.ts +22 -0
  24. package/dist/metadata-validators.js +45 -0
  25. package/dist/pipeline/l1.js +16 -2
  26. package/dist/pipeline/ruminate.d.ts +3 -0
  27. package/dist/pipeline/ruminate.js +50 -1
  28. package/dist/pipeline/slot-migrate.d.ts +45 -0
  29. package/dist/pipeline/slot-migrate.js +45 -0
  30. package/dist/projection/recall.d.ts +74 -0
  31. package/dist/projection/recall.js +148 -0
  32. package/dist/projection/slots.d.ts +5 -0
  33. package/dist/projection/slots.js +9 -2
  34. package/dist/prompts/graph-projection.js +3 -0
  35. package/dist/prompts/l1-extraction.d.ts +4 -1
  36. package/dist/prompts/l1-extraction.js +27 -4
  37. package/dist/settings.js +106 -11
  38. package/dist/skills/crystallize.d.ts +41 -0
  39. package/dist/skills/crystallize.js +75 -0
  40. package/dist/stats.d.ts +18 -1
  41. package/dist/stats.js +184 -5
  42. package/dist/store/file-versions.d.ts +2 -0
  43. package/dist/store/file-versions.js +2 -0
  44. package/dist/store/l1.d.ts +2 -0
  45. package/dist/store/l1.js +4 -0
  46. package/dist/store/memory-sources.d.ts +59 -0
  47. package/dist/store/memory-sources.js +214 -0
  48. package/dist/store/session-recalled.d.ts +25 -0
  49. package/dist/store/session-recalled.js +163 -0
  50. package/dist/store/skill-store.d.ts +99 -0
  51. package/dist/store/skill-store.js +330 -0
  52. package/dist/store/sqlite.d.ts +5 -0
  53. package/dist/store/sqlite.js +30 -4
  54. package/dist/tools/index.d.ts +0 -13
  55. package/dist/tools/index.js +58 -7
  56. package/dist/tools/skills.d.ts +13 -0
  57. package/dist/tools/skills.js +130 -0
  58. package/dist/types.d.ts +6 -0
  59. package/dist/util/maturity.d.ts +27 -0
  60. package/dist/util/maturity.js +26 -0
  61. package/dist/wing-backfill.js +7 -4
  62. package/dsh.plugin.json +2 -2
  63. package/package.json +14 -14
package/dist/config.d.ts CHANGED
@@ -90,6 +90,49 @@ export interface MemoryConfig {
90
90
  * **0 = 不做超时降级**(显式关闭,而非"立刻全部超时")。 */
91
91
  timeoutDays: number;
92
92
  };
93
+ /** 轨3 memport Connect:外部记忆来源登记与只读扫描。**默认关**——
94
+ * scan 仅预览(不写库),写库仍走 memory_import;enabled 关时 memory-sources 与 memport-scan 端点均不可用。 */
95
+ memport: {
96
+ enabled: boolean;
97
+ /** 单源扫描记录上限(0 = 不限;仍受总护栏)。 */
98
+ scanMaxRecords: number;
99
+ };
100
+ /** 轨2 技能结晶(程序性记忆)。**默认关**:allowPromote 也默认关(上线先只计数不晋升,
101
+ * distinct-session 达阈后才开);injectionTier 不用 union,消费侧归一。 */
102
+ skills: {
103
+ enabled: boolean;
104
+ /** 开且 enabled 时,每轮 pre-step 才注入 active 技能。 */
105
+ inject: boolean;
106
+ /** candidate→active 自动晋升总闸(默认关,只计数)。 */
107
+ allowPromote: boolean;
108
+ /** 晋升需 distinct session 数。 */
109
+ minSessions: number;
110
+ /** 晋升需证据条数下限(与 minSessions 同时满足)。 */
111
+ minEvidence: number;
112
+ /** 每轮技能注入字节预算(独立于召回 2000 预算)。 */
113
+ maxPerTurnBytes: number;
114
+ /** 技能目录常驻字节预算。 */
115
+ maxSkillCatalogBytes: number;
116
+ /** excerpt 档每技能正文截断。 */
117
+ excerptChars: number;
118
+ /** active 技能闲置多少天后自动归档(0 = 不做闲置归档)。 */
119
+ idleArchiveDays: number;
120
+ };
121
+ /** wing 存量回填护栏(默认 300 条/120s;想一次多跑点可调大,代价是后台占用更久)。 */
122
+ backfill: {
123
+ /** 单次回填处理条数上限。 */
124
+ maxRecords: number;
125
+ /** 单次回填墙钟预算(ms),超时剩留待再次触发。 */
126
+ timeBudgetMs: number;
127
+ };
128
+ /** 使用场景(G1):抽取时产出“何时该浮现”数组落 metadata.dsh_usage_scenario。默认关,关时抽取产物逐字不变。 */
129
+ usageScenario: {
130
+ enabled: boolean;
131
+ };
132
+ /** 类型叙述模板(G2):抽取时按 7 类型各自的“前因后果”骨架写 content。默认关,关时 prompt 逐字不变。 */
133
+ narrativeTemplates: {
134
+ enabled: boolean;
135
+ };
93
136
  recall: {
94
137
  enabled: boolean;
95
138
  /** 每步自动召回注入的 L1 条数。 */
@@ -203,6 +246,12 @@ export interface MemoryConfig {
203
246
  maxAlwaysOnBytes: number;
204
247
  /** 槽位正文最大字符数。 */
205
248
  maxBodyChars: number;
249
+ /**
250
+ * 旧语义迁移(默认关):反刍收尾时,把“钉成常驻、但内容已由一条活 L1 记忆承载”的
251
+ * rule 槽位软退场(dropped),让那条记忆回到相关性召回而非每轮硬注入。
252
+ * 需用户显式授权:动的是手动建的约定,不自动生效。
253
+ */
254
+ migrateLegacy: boolean;
206
255
  };
207
256
  /** 是否注册模型可调用的记忆工具。 */
208
257
  tools: boolean;
@@ -322,6 +371,7 @@ export declare function liveSettingsSchema(): Schema<NoInfer<Schemastery.ObjectS
322
371
  embedRemoteDimensions: Schema<number, number, "defined">;
323
372
  memoryMutate: Schema<boolean, boolean, "defined">;
324
373
  conflictFreeze: Schema<boolean, boolean, "defined">;
374
+ skillsEnabled: Schema<boolean, boolean, "defined">;
325
375
  toolRoom: Schema<boolean, boolean, "defined">;
326
376
  toolGraph: Schema<boolean, boolean, "defined">;
327
377
  toolRuminate: Schema<boolean, boolean, "defined">;
@@ -424,6 +474,7 @@ export declare function liveSettingsSchema(): Schema<NoInfer<Schemastery.ObjectS
424
474
  embedRemoteDimensions: Schema<number, number, "defined">;
425
475
  memoryMutate: Schema<boolean, boolean, "defined">;
426
476
  conflictFreeze: Schema<boolean, boolean, "defined">;
477
+ skillsEnabled: Schema<boolean, boolean, "defined">;
427
478
  toolRoom: Schema<boolean, boolean, "defined">;
428
479
  toolGraph: Schema<boolean, boolean, "defined">;
429
480
  toolRuminate: Schema<boolean, boolean, "defined">;
@@ -499,6 +550,51 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
499
550
  maxPending: Schema<number, number, "defined">;
500
551
  timeoutDays: Schema<number, number, "defined">;
501
552
  }>>, "plain">;
553
+ memport: Schema<Schemastery.ObjectS<NoInfer<{
554
+ enabled: Schema<boolean, boolean, "defined">;
555
+ scanMaxRecords: Schema<number, number, "defined">;
556
+ }>>, Schemastery.ObjectT<NoInfer<{
557
+ enabled: Schema<boolean, boolean, "defined">;
558
+ scanMaxRecords: Schema<number, number, "defined">;
559
+ }>>, "plain">;
560
+ skills: Schema<Schemastery.ObjectS<NoInfer<{
561
+ enabled: Schema<boolean, boolean, "defined">;
562
+ inject: Schema<boolean, boolean, "defined">;
563
+ allowPromote: Schema<boolean, boolean, "defined">;
564
+ minSessions: Schema<number, number, "defined">;
565
+ minEvidence: Schema<number, number, "defined">;
566
+ maxPerTurnBytes: Schema<number, number, "defined">;
567
+ maxSkillCatalogBytes: Schema<number, number, "defined">;
568
+ excerptChars: Schema<number, number, "defined">;
569
+ idleArchiveDays: Schema<number, number, "defined">;
570
+ }>>, Schemastery.ObjectT<NoInfer<{
571
+ enabled: Schema<boolean, boolean, "defined">;
572
+ inject: Schema<boolean, boolean, "defined">;
573
+ allowPromote: Schema<boolean, boolean, "defined">;
574
+ minSessions: Schema<number, number, "defined">;
575
+ minEvidence: Schema<number, number, "defined">;
576
+ maxPerTurnBytes: Schema<number, number, "defined">;
577
+ maxSkillCatalogBytes: Schema<number, number, "defined">;
578
+ excerptChars: Schema<number, number, "defined">;
579
+ idleArchiveDays: Schema<number, number, "defined">;
580
+ }>>, "plain">;
581
+ backfill: Schema<Schemastery.ObjectS<NoInfer<{
582
+ maxRecords: Schema<number, number, "defined">;
583
+ timeBudgetMs: Schema<number, number, "defined">;
584
+ }>>, Schemastery.ObjectT<NoInfer<{
585
+ maxRecords: Schema<number, number, "defined">;
586
+ timeBudgetMs: Schema<number, number, "defined">;
587
+ }>>, "plain">;
588
+ usageScenario: Schema<Schemastery.ObjectS<NoInfer<{
589
+ enabled: Schema<boolean, boolean, "defined">;
590
+ }>>, Schemastery.ObjectT<NoInfer<{
591
+ enabled: Schema<boolean, boolean, "defined">;
592
+ }>>, "plain">;
593
+ narrativeTemplates: Schema<Schemastery.ObjectS<NoInfer<{
594
+ enabled: Schema<boolean, boolean, "defined">;
595
+ }>>, Schemastery.ObjectT<NoInfer<{
596
+ enabled: Schema<boolean, boolean, "defined">;
597
+ }>>, "plain">;
502
598
  recall: Schema<Schemastery.ObjectS<NoInfer<{
503
599
  enabled: Schema<boolean, boolean, "defined">;
504
600
  maxResults: Schema<number, number, "defined">;
@@ -730,12 +826,14 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
730
826
  maxSlots: Schema<number, number, "defined">;
731
827
  maxAlwaysOnBytes: Schema<number, number, "defined">;
732
828
  maxBodyChars: Schema<number, number, "defined">;
829
+ migrateLegacy: Schema<boolean, boolean, "defined">;
733
830
  }>>, Schemastery.ObjectT<NoInfer<{
734
831
  enabled: Schema<boolean, boolean, "defined">;
735
832
  inject: Schema<boolean, boolean, "defined">;
736
833
  maxSlots: Schema<number, number, "defined">;
737
834
  maxAlwaysOnBytes: Schema<number, number, "defined">;
738
835
  maxBodyChars: Schema<number, number, "defined">;
836
+ migrateLegacy: Schema<boolean, boolean, "defined">;
739
837
  }>>, "plain">;
740
838
  tools: Schema<boolean, boolean, "defined">;
741
839
  benchControl: Schema<boolean, boolean, "defined">;
@@ -836,6 +934,7 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
836
934
  embedRemoteDimensions: Schema<number, number, "defined">;
837
935
  memoryMutate: Schema<boolean, boolean, "defined">;
838
936
  conflictFreeze: Schema<boolean, boolean, "defined">;
937
+ skillsEnabled: Schema<boolean, boolean, "defined">;
839
938
  toolRoom: Schema<boolean, boolean, "defined">;
840
939
  toolGraph: Schema<boolean, boolean, "defined">;
841
940
  toolRuminate: Schema<boolean, boolean, "defined">;
@@ -938,6 +1037,7 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
938
1037
  embedRemoteDimensions: Schema<number, number, "defined">;
939
1038
  memoryMutate: Schema<boolean, boolean, "defined">;
940
1039
  conflictFreeze: Schema<boolean, boolean, "defined">;
1040
+ skillsEnabled: Schema<boolean, boolean, "defined">;
941
1041
  toolRoom: Schema<boolean, boolean, "defined">;
942
1042
  toolGraph: Schema<boolean, boolean, "defined">;
943
1043
  toolRuminate: Schema<boolean, boolean, "defined">;
@@ -1013,6 +1113,51 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
1013
1113
  maxPending: Schema<number, number, "defined">;
1014
1114
  timeoutDays: Schema<number, number, "defined">;
1015
1115
  }>>, "plain">;
1116
+ memport: Schema<Schemastery.ObjectS<NoInfer<{
1117
+ enabled: Schema<boolean, boolean, "defined">;
1118
+ scanMaxRecords: Schema<number, number, "defined">;
1119
+ }>>, Schemastery.ObjectT<NoInfer<{
1120
+ enabled: Schema<boolean, boolean, "defined">;
1121
+ scanMaxRecords: Schema<number, number, "defined">;
1122
+ }>>, "plain">;
1123
+ skills: Schema<Schemastery.ObjectS<NoInfer<{
1124
+ enabled: Schema<boolean, boolean, "defined">;
1125
+ inject: Schema<boolean, boolean, "defined">;
1126
+ allowPromote: Schema<boolean, boolean, "defined">;
1127
+ minSessions: Schema<number, number, "defined">;
1128
+ minEvidence: Schema<number, number, "defined">;
1129
+ maxPerTurnBytes: Schema<number, number, "defined">;
1130
+ maxSkillCatalogBytes: Schema<number, number, "defined">;
1131
+ excerptChars: Schema<number, number, "defined">;
1132
+ idleArchiveDays: Schema<number, number, "defined">;
1133
+ }>>, Schemastery.ObjectT<NoInfer<{
1134
+ enabled: Schema<boolean, boolean, "defined">;
1135
+ inject: Schema<boolean, boolean, "defined">;
1136
+ allowPromote: Schema<boolean, boolean, "defined">;
1137
+ minSessions: Schema<number, number, "defined">;
1138
+ minEvidence: Schema<number, number, "defined">;
1139
+ maxPerTurnBytes: Schema<number, number, "defined">;
1140
+ maxSkillCatalogBytes: Schema<number, number, "defined">;
1141
+ excerptChars: Schema<number, number, "defined">;
1142
+ idleArchiveDays: Schema<number, number, "defined">;
1143
+ }>>, "plain">;
1144
+ backfill: Schema<Schemastery.ObjectS<NoInfer<{
1145
+ maxRecords: Schema<number, number, "defined">;
1146
+ timeBudgetMs: Schema<number, number, "defined">;
1147
+ }>>, Schemastery.ObjectT<NoInfer<{
1148
+ maxRecords: Schema<number, number, "defined">;
1149
+ timeBudgetMs: Schema<number, number, "defined">;
1150
+ }>>, "plain">;
1151
+ usageScenario: Schema<Schemastery.ObjectS<NoInfer<{
1152
+ enabled: Schema<boolean, boolean, "defined">;
1153
+ }>>, Schemastery.ObjectT<NoInfer<{
1154
+ enabled: Schema<boolean, boolean, "defined">;
1155
+ }>>, "plain">;
1156
+ narrativeTemplates: Schema<Schemastery.ObjectS<NoInfer<{
1157
+ enabled: Schema<boolean, boolean, "defined">;
1158
+ }>>, Schemastery.ObjectT<NoInfer<{
1159
+ enabled: Schema<boolean, boolean, "defined">;
1160
+ }>>, "plain">;
1016
1161
  recall: Schema<Schemastery.ObjectS<NoInfer<{
1017
1162
  enabled: Schema<boolean, boolean, "defined">;
1018
1163
  maxResults: Schema<number, number, "defined">;
@@ -1244,12 +1389,14 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
1244
1389
  maxSlots: Schema<number, number, "defined">;
1245
1390
  maxAlwaysOnBytes: Schema<number, number, "defined">;
1246
1391
  maxBodyChars: Schema<number, number, "defined">;
1392
+ migrateLegacy: Schema<boolean, boolean, "defined">;
1247
1393
  }>>, Schemastery.ObjectT<NoInfer<{
1248
1394
  enabled: Schema<boolean, boolean, "defined">;
1249
1395
  inject: Schema<boolean, boolean, "defined">;
1250
1396
  maxSlots: Schema<number, number, "defined">;
1251
1397
  maxAlwaysOnBytes: Schema<number, number, "defined">;
1252
1398
  maxBodyChars: Schema<number, number, "defined">;
1399
+ migrateLegacy: Schema<boolean, boolean, "defined">;
1253
1400
  }>>, "plain">;
1254
1401
  tools: Schema<boolean, boolean, "defined">;
1255
1402
  benchControl: Schema<boolean, boolean, "defined">;
@@ -1350,6 +1497,7 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
1350
1497
  embedRemoteDimensions: Schema<number, number, "defined">;
1351
1498
  memoryMutate: Schema<boolean, boolean, "defined">;
1352
1499
  conflictFreeze: Schema<boolean, boolean, "defined">;
1500
+ skillsEnabled: Schema<boolean, boolean, "defined">;
1353
1501
  toolRoom: Schema<boolean, boolean, "defined">;
1354
1502
  toolGraph: Schema<boolean, boolean, "defined">;
1355
1503
  toolRuminate: Schema<boolean, boolean, "defined">;
@@ -1452,6 +1600,7 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
1452
1600
  embedRemoteDimensions: Schema<number, number, "defined">;
1453
1601
  memoryMutate: Schema<boolean, boolean, "defined">;
1454
1602
  conflictFreeze: Schema<boolean, boolean, "defined">;
1603
+ skillsEnabled: Schema<boolean, boolean, "defined">;
1455
1604
  toolRoom: Schema<boolean, boolean, "defined">;
1456
1605
  toolGraph: Schema<boolean, boolean, "defined">;
1457
1606
  toolRuminate: Schema<boolean, boolean, "defined">;
package/dist/config.js CHANGED
@@ -69,6 +69,8 @@ export function liveSettingsSchema() {
69
69
  memoryMutate: Schema.boolean().default(false),
70
70
  // §C 人工冲突裁决总开关:默认 false(冻结消耗注意力,不可默认全开)
71
71
  conflictFreeze: Schema.boolean().default(false),
72
+ // 轨2 技能结晶总开关(看板可拨):默认 false。开=注册 memory_skill_* 工具 + 注入 active 技能 + skills-* 端点可用。
73
+ skillsEnabled: Schema.boolean().default(false),
72
74
  // 工具分组封印(v0.21.0):false = 该组工具不注册,从模型工具列表消失。
73
75
  // 核心读(memory_search/read_scene/receipts/conversation_search)与槽位三件不受控。
74
76
  toolRoom: Schema.boolean().default(true),
@@ -129,6 +131,37 @@ export const memorySchema = Schema.object({
129
131
  // 30 天:足够跨过假期与项目间歇,又不至于让互相矛盾的两条记忆长期并列召回。
130
132
  timeoutDays: Schema.number().min(0).max(3650).default(30),
131
133
  }),
134
+ // 轨3 memport Connect:默认关(新功能默认关)。scan 为**只读预览**,写库仍走 memory_import。
135
+ memport: Schema.object({
136
+ enabled: Schema.boolean().default(false),
137
+ // 单源扫描上限(防极端大包在事件循环里阻塞 RPC;scan 是手动触发,仍留护栏)。
138
+ scanMaxRecords: Schema.number().min(0).max(20_000).default(5000),
139
+ }),
140
+ // 轨2 技能结晶:默认关 + allowPromote 关(先只计数不晋升)。
141
+ skills: Schema.object({
142
+ enabled: Schema.boolean().default(false),
143
+ inject: Schema.boolean().default(true),
144
+ allowPromote: Schema.boolean().default(false),
145
+ minSessions: Schema.number().min(1).max(100).default(3),
146
+ minEvidence: Schema.number().min(1).max(1000).default(5),
147
+ maxPerTurnBytes: Schema.number().min(0).max(8192).default(600),
148
+ maxSkillCatalogBytes: Schema.number().min(0).max(8192).default(2048),
149
+ excerptChars: Schema.number().min(0).max(4000).default(240),
150
+ idleArchiveDays: Schema.number().min(0).max(3650).default(90),
151
+ }),
152
+ // wing 回填护栏:默认与旧行为一致(300 条 / 120s),需一次多跑点时调大。
153
+ backfill: Schema.object({
154
+ maxRecords: Schema.number().min(1).max(10_000).default(300),
155
+ timeBudgetMs: Schema.number().min(1000).max(1_800_000).default(120_000),
156
+ }),
157
+ // 使用场景(G1):默认关;开时抽取 prompt 追加 usageScenario 指令(off 逐字不变)。
158
+ usageScenario: Schema.object({
159
+ enabled: Schema.boolean().default(false),
160
+ }),
161
+ // 类型叙述模板(G2):默认关;开时抽取 prompt 追加分类型 content 骨架(off 逐字不变)。
162
+ narrativeTemplates: Schema.object({
163
+ enabled: Schema.boolean().default(false),
164
+ }),
132
165
  recall: Schema.object({
133
166
  enabled: Schema.boolean().default(true),
134
167
  maxResults: Schema.number().min(1).max(20).default(5),
@@ -221,6 +254,8 @@ export const memorySchema = Schema.object({
221
254
  maxSlots: Schema.number().min(1).max(32).default(8),
222
255
  maxAlwaysOnBytes: Schema.number().min(128).max(16_384).default(2048),
223
256
  maxBodyChars: Schema.number().min(32).max(2048).default(512),
257
+ // 旧 slot 语义迁移:默认关(不自动碰用户手动 pin 的常驻约定)。
258
+ migrateLegacy: Schema.boolean().default(false),
224
259
  }),
225
260
  tools: Schema.boolean().default(true),
226
261
  benchControl: Schema.boolean().default(false),
@@ -39,6 +39,14 @@ export interface ConflictListDeps {
39
39
  l1: Pick<L1Store, 'listConflictPending' | 'countConflictPendingUnresolved' | 'getByIds'>;
40
40
  /** `conflictFreeze.enabled`。 */
41
41
  conflictFreezeEnabled: boolean;
42
+ /** G3 成熟度旁注用:召回使用统计(缺省按 0 强化)。 */
43
+ usage?: {
44
+ get(id: string): {
45
+ used: number;
46
+ } | null | undefined;
47
+ };
48
+ /** 时效半衰期(天);≤0 = 衰减关 → aging 视为 null。 */
49
+ decayHalfLifeDays?: number;
42
50
  }
43
51
  /**
44
52
  * 列出待裁决对。
@@ -1,4 +1,5 @@
1
1
  import { DEFER_MAX } from './store/conflicts.js';
2
+ import { computeMaturity } from './util/maturity.js';
2
3
  const OUTCOMES = ['winner', 'loser', 'both', 'defer'];
3
4
  function view(partial) {
4
5
  return { pair_id: '', outcome: '', resolved_at: '', removed_record_id: '', ...partial };
@@ -150,6 +151,9 @@ export function listConflictPairs(deps, opts = {}) {
150
151
  const contentById = new Map();
151
152
  // §C 三轴(conflict-3axis):记忆记录自带有效期与持续性,取出来用于裁决视图对比。
152
153
  const axisById = new Map();
154
+ // G3 成熟度旁注:取 priority/updatedAt 供 computeMaturity(读时派生,不落库)。
155
+ const priorityById = new Map();
156
+ const updatedAtById = new Map();
153
157
  for (const r of deps.l1.getByIds([...ids])) {
154
158
  contentById.set(r.id, r.content);
155
159
  axisById.set(r.id, {
@@ -157,8 +161,18 @@ export function listConflictPairs(deps, opts = {}) {
157
161
  validTo: (r.validTo ?? null),
158
162
  persistence: (r.persistence ?? null),
159
163
  });
164
+ priorityById.set(r.id, r.priority ?? 60);
165
+ updatedAtById.set(r.id, r.updatedAt ?? 0);
160
166
  }
161
167
  const axisOf = (id) => axisById.get(id) ?? { validFrom: null, validTo: null, persistence: null };
168
+ // 成熟度(priority + 被用次数 + 老化)——仅帮人工裁决看“哪条更确立”,不参与自动了结。
169
+ const halfLife = deps.decayHalfLifeDays ?? 0;
170
+ const maturityOf = (id) => {
171
+ const aging = halfLife > 0
172
+ ? Math.max(0.5, Math.pow(0.5, Math.max(0, (Date.now() - (updatedAtById.get(id) ?? 0)) / 86_400_000) / halfLife))
173
+ : null;
174
+ return computeMaturity({ priority: priorityById.get(id) ?? 60, usage: deps.usage?.get(id) ?? null, agingWeight: aging });
175
+ };
162
176
  const items = pending.map((p) => {
163
177
  const w = axisOf(p.winnerId);
164
178
  const l = axisOf(p.loserId);
@@ -184,6 +198,8 @@ export function listConflictPairs(deps, opts = {}) {
184
198
  // ('hard' / ''),使"旧行经 ALTER 回填"与"读取面兜底"呈现同一个形状。
185
199
  conflict_type: p.conflictType ?? 'hard',
186
200
  claim_key: p.claimKey ?? '',
201
+ winner_maturity: maturityOf(p.winnerId),
202
+ loser_maturity: maturityOf(p.loserId),
187
203
  };
188
204
  });
189
205
  return { enabled: true, total: deps.l1.countConflictPendingUnresolved(), items };
@@ -201,6 +217,7 @@ export function renderConflicts(v) {
201
217
  const vf = side === 'winner' ? p.winner_valid_from_ms : p.loser_valid_from_ms;
202
218
  const vt = side === 'winner' ? p.winner_valid_to_ms : p.loser_valid_to_ms;
203
219
  const ps = side === 'winner' ? p.winner_persistence : p.loser_persistence;
220
+ const mt = side === 'winner' ? p.winner_maturity : p.loser_maturity;
204
221
  const parts = [];
205
222
  const vfS = iso(vf);
206
223
  const vtS = iso(vt);
@@ -210,6 +227,8 @@ export function renderConflicts(v) {
210
227
  parts.push(`有效期止 ${vtS}`);
211
228
  if (ps)
212
229
  parts.push(`持续性 ${ps}`);
230
+ if (mt)
231
+ parts.push(`成熟度 ${mt}`);
213
232
  return parts.length ? ` 三轴: ${parts.join(' / ')}` : '';
214
233
  };
215
234
  const rows = v.items.map((p, i) => {
@@ -103,6 +103,9 @@ export interface MemoryLiveSettings {
103
103
  /** §C 人工冲突裁决总开关:true = 去重判定"两边都像对的"时冻结冲突对,停放到待人工裁决区;
104
104
  * false = 默认,冲突按 LLM 的 winner/loser 自动了结。运行时覆盖静态 config 的 conflictFreeze.enabled。 */
105
105
  conflictFreeze: boolean;
106
+ /** 轨2 技能结晶总开关(看板可拨):true = 注册 memory_skill_* 工具、注入 active 技能、skills-* 端点可用。
107
+ * 默认 false(新功能默认关);与部署 cfg.skills.enabled 取或(任一开则生效)。 */
108
+ skillsEnabled: boolean;
106
109
  }
107
110
  /** 召回停用原因(session-stats recall.enabled=false 时带出;短路序第一个为假的因子)。 */
108
111
  export type RecallDisabledReason = 'deploy' | 'global' | 'session' | 'mode';
@@ -796,6 +799,13 @@ export interface UiRecord {
796
799
  retired?: boolean;
797
800
  /** 退场原因:`conflict`(裁决) / `superseded`(取代) / `manual`(人工) / `unknown`。未退场为 null。 */
798
801
  retiredReason?: string | null;
802
+ /**
803
+ * 成熟度(G3 读时派生):priority + 被用次数 + 老化权重合成。
804
+ * 可选字段——旧 client 忽略=向后兼容;不参与存储/快照(纯投影)。
805
+ */
806
+ maturity?: 'low' | 'mid' | 'high';
807
+ /** 使用场景(G1):从 metadata.dsh_usage_scenario 读出;功能关/无则 undefined。 */
808
+ usageScenario?: string[];
799
809
  }
800
810
  export interface ListRecordsResponse {
801
811
  items: UiRecord[];
@@ -1218,6 +1228,9 @@ export interface ConflictPairView {
1218
1228
  loser_valid_from_ms?: number | null;
1219
1229
  loser_valid_to_ms?: number | null;
1220
1230
  loser_persistence?: string | null;
1231
+ /** G3 成熟度旁注(读时派生,仅帮人工看“哪条更确立”,不参与自动裁决)。 */
1232
+ winner_maturity?: 'low' | 'mid' | 'high';
1233
+ loser_maturity?: 'low' | 'mid' | 'high';
1221
1234
  review_state?: 'unseen' | 'deferred';
1222
1235
  /** R1:复看次数(面板据此显示"已复看 N 次");达 `DEFER_MAX` 即钉子户。 */
1223
1236
  defer_count?: number;
@@ -1303,6 +1316,110 @@ export interface ReceiptsResponse {
1303
1316
  items: ReceiptItemView[];
1304
1317
  total: number;
1305
1318
  }
1319
+ /** 外部来源视图(轨3 Connect;路径指针,不含正文)。 */
1320
+ export interface MemorySourceView {
1321
+ id: string;
1322
+ kind: string;
1323
+ path: string;
1324
+ label?: string;
1325
+ lastScanAt: string;
1326
+ lastImportAt: string;
1327
+ disabled: boolean;
1328
+ status: 'active' | 'retired';
1329
+ }
1330
+ export interface MemorySourcesListResponse {
1331
+ sources: MemorySourceView[];
1332
+ /** 写门/启用态提示(面板据它显示“导入需开高权限”)。 */
1333
+ memoryMutate: boolean;
1334
+ }
1335
+ export interface MemorySourcesAddRequest {
1336
+ id: string;
1337
+ kind: string;
1338
+ path: string;
1339
+ label?: string;
1340
+ }
1341
+ export interface MemorySourcesAddResponse {
1342
+ id: string;
1343
+ created: boolean;
1344
+ notice: string;
1345
+ }
1346
+ export interface MemorySourcesRetireRequest {
1347
+ id: string;
1348
+ /** true = 恢复为 active;缺省/ false = 退役(不删数据,来源仍可重放)。 */
1349
+ active?: boolean;
1350
+ }
1351
+ export interface MemorySourcesRetireResponse {
1352
+ changed: boolean;
1353
+ notice: string;
1354
+ }
1355
+ export interface MemportScanRequest {
1356
+ /** 省略 = 扫描全部启用来源;指定 = 只扫该 id。 */
1357
+ sourceId?: string;
1358
+ }
1359
+ export interface MemportScanCounts {
1360
+ dup: number;
1361
+ 'near-dup': number;
1362
+ 'conflict-candidate': number;
1363
+ new: number;
1364
+ }
1365
+ export interface MemportScanSourceResult {
1366
+ sourceId: string;
1367
+ label?: string;
1368
+ /** 命中的 .mem 包数(只读,未写库)。 */
1369
+ files: number;
1370
+ /** 解析出的总条数(受 scanMaxRecords 上限)。 */
1371
+ total: number;
1372
+ /** 每包校验失败原因(不阻断其余来源)。 */
1373
+ errors: string[];
1374
+ counts: MemportScanCounts;
1375
+ /** 新记录样本预览(正文截断;实际写库走 memory_import,那里才做脱敏)。 */
1376
+ sampleNew: Array<{
1377
+ type: string;
1378
+ content: string;
1379
+ }>;
1380
+ }
1381
+ export interface MemportScanResponse {
1382
+ /** cfg.memport.enabled——关时 sources 为空并附 notice。 */
1383
+ enabled: boolean;
1384
+ sources: MemportScanSourceResult[];
1385
+ notice?: string;
1386
+ }
1387
+ /** 技能摘要(轨2 SkillsTab;供人工审阅/晋升/pin/归档)。 */
1388
+ export interface SkillView {
1389
+ id: string;
1390
+ title: string;
1391
+ status: 'candidate' | 'active' | 'archived';
1392
+ tier: 'full' | 'excerpt' | 'hint';
1393
+ pinned: boolean;
1394
+ sessionCount: number;
1395
+ updatedAt: string;
1396
+ }
1397
+ export interface SkillsListResponse {
1398
+ enabled: boolean;
1399
+ /** 自动晋升总闸(allowPromote);关时 promote 动作会被拒。 */
1400
+ allowPromote: boolean;
1401
+ memoryMutate: boolean;
1402
+ skills: SkillView[];
1403
+ }
1404
+ export interface SkillsActionRequest {
1405
+ id: string;
1406
+ action: 'promote' | 'archive' | 'pin' | 'unpin' | 'set-tier';
1407
+ tier?: 'full' | 'excerpt' | 'hint';
1408
+ reason?: string;
1409
+ }
1410
+ export interface SkillsActionResponse {
1411
+ changed: boolean;
1412
+ notice: string;
1413
+ }
1414
+ /** dsh-memory/session-recalled (G-live):本会话已注入、未被压缩覆盖的召回集。 */
1415
+ export interface SessionRecalledRequest {
1416
+ sessionId: string;
1417
+ }
1418
+ export interface SessionRecalledResponse {
1419
+ sessionId: string;
1420
+ /** 按召回插入序(旧→新);复用 UiRecord(含 maturity/usageScenario)。 */
1421
+ records: UiRecord[];
1422
+ }
1306
1423
  export interface DshMemoryRequestMap {
1307
1424
  'dsh-memory/stats': Record<string, never>;
1308
1425
  'dsh-memory/token-cost': TokenCostRequest;
@@ -1350,6 +1467,13 @@ export interface DshMemoryRequestMap {
1350
1467
  'dsh-memory/cleanup-retired': CleanupRetiredRequest;
1351
1468
  'dsh-memory/snapshots-list': SnapshotsListRequest;
1352
1469
  'dsh-memory/snapshot-restore': SnapshotRestoreRequest;
1470
+ 'dsh-memory/memory-sources-list': Record<string, never>;
1471
+ 'dsh-memory/memory-sources-add': MemorySourcesAddRequest;
1472
+ 'dsh-memory/memory-sources-retire': MemorySourcesRetireRequest;
1473
+ 'dsh-memory/memport-scan': MemportScanRequest;
1474
+ 'dsh-memory/skills-list': Record<string, never>;
1475
+ 'dsh-memory/session-recalled': SessionRecalledRequest;
1476
+ 'dsh-memory/skills-action': SkillsActionRequest;
1353
1477
  }
1354
1478
  export interface DshMemoryResponseMap {
1355
1479
  'dsh-memory/stats': StatsResponse;
@@ -1398,6 +1522,13 @@ export interface DshMemoryResponseMap {
1398
1522
  'dsh-memory/cleanup-retired': CleanupRetiredResponse;
1399
1523
  'dsh-memory/snapshots-list': SnapshotsListResponse;
1400
1524
  'dsh-memory/snapshot-restore': SnapshotRestoreResponse;
1525
+ 'dsh-memory/memory-sources-list': MemorySourcesListResponse;
1526
+ 'dsh-memory/memory-sources-add': MemorySourcesAddResponse;
1527
+ 'dsh-memory/memory-sources-retire': MemorySourcesRetireResponse;
1528
+ 'dsh-memory/memport-scan': MemportScanResponse;
1529
+ 'dsh-memory/skills-list': SkillsListResponse;
1530
+ 'dsh-memory/session-recalled': SessionRecalledResponse;
1531
+ 'dsh-memory/skills-action': SkillsActionResponse;
1401
1532
  }
1402
1533
  /** 全部端点名(client 调用与 host case 表的共用字面量来源)。 */
1403
1534
  export type DshMemoryEndpoint = keyof DshMemoryResponseMap;
@@ -47,3 +47,11 @@ export declare function sortByDomainWeight<T extends {
47
47
  id: string;
48
48
  score: number;
49
49
  }>(hits: readonly T[], wingOf: (id: string) => unknown, weights: Record<string, number>): T[];
50
+ /**
51
+ * G1 使用场景细排(纯函数、**score 不改写**、默认关时不进此路径):
52
+ * 命中查询词的 usageScenario 记忆上浮;未命中/无场景的记录保持原序(fail-open)。
53
+ * 保守:只按“命中强度”重排,不引入新相关性判断;无查询词时原样返回。
54
+ */
55
+ export declare function sortByUsageScenario<T extends {
56
+ id: string;
57
+ }>(hits: readonly T[], scenariosOf: (id: string) => readonly string[], query: string): T[];
@@ -149,3 +149,33 @@ export function sortByDomainWeight(hits, wingOf, weights) {
149
149
  };
150
150
  return [...hits].sort((a, b) => weightOf(b.id) - weightOf(a.id) || b.score - a.score);
151
151
  }
152
+ /** 分词(小写、按非字母数字/非 CJK 切、去长度<2 的碎片)。供场景词重叠用。 */
153
+ function normTokens(s) {
154
+ return new Set(s.toLowerCase().split(/[^0-9a-z\u4e00-\u9fa5]+/).map((t) => t.trim()).filter((t) => t.length >= 2));
155
+ }
156
+ /**
157
+ * G1 使用场景细排(纯函数、**score 不改写**、默认关时不进此路径):
158
+ * 命中查询词的 usageScenario 记忆上浮;未命中/无场景的记录保持原序(fail-open)。
159
+ * 保守:只按“命中强度”重排,不引入新相关性判断;无查询词时原样返回。
160
+ */
161
+ export function sortByUsageScenario(hits, scenariosOf, query) {
162
+ const q = normTokens(query);
163
+ if (q.size === 0)
164
+ return [...hits];
165
+ const matchOf = (id) => {
166
+ let best = 0;
167
+ for (const s of scenariosOf(id)) {
168
+ let ov = 0;
169
+ for (const t of normTokens(s))
170
+ if (q.has(t))
171
+ ov++;
172
+ if (ov > best)
173
+ best = ov;
174
+ }
175
+ return best;
176
+ };
177
+ return hits
178
+ .map((h, i) => ({ h, i, m: matchOf(h.id) }))
179
+ .sort((a, b) => b.m - a.m || a.i - b.i)
180
+ .map((x) => x.h);
181
+ }
@@ -13,8 +13,10 @@ export declare const GRAPH_NODE_TYPE_SET: ReadonlySet<string>;
13
13
  /** 记录生命周期四态(节点/fact/边通用)。 */
14
14
  export declare const GRAPH_STATUSES: readonly GraphRecordStatus[];
15
15
  export declare const GRAPH_STATUS_SET: ReadonlySet<string>;
16
- /** 规范中文关系词(提示词给枚举;校验不做白名单——关系是开放词表,只做长度钳制)。 */
17
- export declare const GRAPH_RELATION_WORDS: readonly ["使用", "属于", "创建", "参与", "贡献", "依赖", "位于", "相关"];
16
+ /** 规范中文关系词(提示词给枚举;校验不做白名单——关系是开放词表,只做长度钳制)。
17
+ * 后四个为因果边(导致/因为/修复了/取代)——让"前因后果"跨记录成链;仅当 graph.enabled 时
18
+ * 才参与投影(整块图谱默认关,不碰非图谱用户的蒸馏产物)。 */
19
+ export declare const GRAPH_RELATION_WORDS: readonly ["使用", "属于", "创建", "参与", "贡献", "依赖", "位于", "相关", "导致", "因为", "修复了", "取代"];
18
20
  /** 提案字段上限(校验侧截断/丢弃与提示词内插共用同一组数字)。 */
19
21
  export declare const GRAPH_CAP: {
20
22
  /** 提案内临时引用(ref)长度。 */
@@ -4,8 +4,10 @@ export const GRAPH_NODE_TYPE_SET = new Set(GRAPH_NODE_TYPES);
4
4
  /** 记录生命周期四态(节点/fact/边通用)。 */
5
5
  export const GRAPH_STATUSES = ['active', 'superseded', 'disputed', 'archived'];
6
6
  export const GRAPH_STATUS_SET = new Set(GRAPH_STATUSES);
7
- /** 规范中文关系词(提示词给枚举;校验不做白名单——关系是开放词表,只做长度钳制)。 */
8
- export const GRAPH_RELATION_WORDS = ['使用', '属于', '创建', '参与', '贡献', '依赖', '位于', '相关'];
7
+ /** 规范中文关系词(提示词给枚举;校验不做白名单——关系是开放词表,只做长度钳制)。
8
+ * 后四个为因果边(导致/因为/修复了/取代)——让"前因后果"跨记录成链;仅当 graph.enabled 时
9
+ * 才参与投影(整块图谱默认关,不碰非图谱用户的蒸馏产物)。 */
10
+ export const GRAPH_RELATION_WORDS = ['使用', '属于', '创建', '参与', '贡献', '依赖', '位于', '相关', '导致', '因为', '修复了', '取代'];
9
11
  /** 提案字段上限(校验侧截断/丢弃与提示词内插共用同一组数字)。 */
10
12
  export const GRAPH_CAP = {
11
13
  /** 提案内临时引用(ref)长度。 */
@@ -20,6 +20,7 @@ import type { MemoryConfig } from '../config.js';
20
20
  import type { LiveSettingsHandle } from '../settings.js';
21
21
  import type { L1Store } from '../store/l1.js';
22
22
  import type { PersonaStore } from '../store/persona.js';
23
+ import type { SessionRecalledStore } from '../store/session-recalled.js';
23
24
  import type { SceneStore } from '../store/scenes.js';
24
25
  import type { SessionModeStore } from '../store/session-modes.js';
25
26
  import type { RecallUsageStore } from '../store/recall-usage.js';
@@ -90,6 +91,7 @@ export declare function registerRecall(ctx: Context, cfg: MemoryConfig, stores:
90
91
  l1: L1Store;
91
92
  scenes: Record<'chat' | 'work', SceneStore>;
92
93
  persona: Record<'chat' | 'work', PersonaStore>;
94
+ recalled?: SessionRecalledStore;
93
95
  }, logger: MemoryLogger, live: LiveSettingsHandle, modes: SessionModeStore, dataDir: string,
94
96
  /** 召回使用统计(可选;未装配 = 零成本旁路):进 topN(注入)才算 used。 */
95
97
  usage?: RecallUsageStore): RecallHooks;