@claude-flow/memory 3.0.0-alpha.9 → 3.0.1

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 (188) hide show
  1. package/README.md +308 -37
  2. package/dist/agent-memory-scope.d.ts.map +1 -1
  3. package/dist/agent-memory-scope.js +10 -2
  4. package/dist/agent-memory-scope.js.map +1 -1
  5. package/dist/agentdb-adapter-key-isolation.test.d.ts +2 -0
  6. package/dist/agentdb-adapter-key-isolation.test.d.ts.map +1 -0
  7. package/dist/agentdb-adapter-key-isolation.test.js +175 -0
  8. package/dist/agentdb-adapter-key-isolation.test.js.map +1 -0
  9. package/dist/agentdb-adapter-upsert.test.d.ts +2 -0
  10. package/dist/agentdb-adapter-upsert.test.d.ts.map +1 -0
  11. package/dist/agentdb-adapter-upsert.test.js +216 -0
  12. package/dist/agentdb-adapter-upsert.test.js.map +1 -0
  13. package/dist/agentdb-adapter.d.ts +70 -1
  14. package/dist/agentdb-adapter.d.ts.map +1 -1
  15. package/dist/agentdb-adapter.js +365 -32
  16. package/dist/agentdb-adapter.js.map +1 -1
  17. package/dist/agentdb-backend.d.ts +25 -0
  18. package/dist/agentdb-backend.d.ts.map +1 -1
  19. package/dist/agentdb-backend.js +113 -28
  20. package/dist/agentdb-backend.js.map +1 -1
  21. package/dist/agentdb-retrieval-guard.d.ts +76 -0
  22. package/dist/agentdb-retrieval-guard.d.ts.map +1 -0
  23. package/dist/agentdb-retrieval-guard.js +77 -0
  24. package/dist/agentdb-retrieval-guard.js.map +1 -0
  25. package/dist/agentdb-retrieval-guard.test.d.ts +12 -0
  26. package/dist/agentdb-retrieval-guard.test.d.ts.map +1 -0
  27. package/dist/agentdb-retrieval-guard.test.js +129 -0
  28. package/dist/agentdb-retrieval-guard.test.js.map +1 -0
  29. package/dist/auto-memory-bridge.d.ts +12 -1
  30. package/dist/auto-memory-bridge.d.ts.map +1 -1
  31. package/dist/auto-memory-bridge.js +101 -7
  32. package/dist/auto-memory-bridge.js.map +1 -1
  33. package/dist/auto-memory-bridge.test.js +121 -15
  34. package/dist/auto-memory-bridge.test.js.map +1 -1
  35. package/dist/auto-memory-index-3224.test.d.ts +2 -0
  36. package/dist/auto-memory-index-3224.test.d.ts.map +1 -0
  37. package/dist/auto-memory-index-3224.test.js +77 -0
  38. package/dist/auto-memory-index-3224.test.js.map +1 -0
  39. package/dist/consolidator-embedding-benchmark.test.d.ts +39 -0
  40. package/dist/consolidator-embedding-benchmark.test.d.ts.map +1 -0
  41. package/dist/consolidator-embedding-benchmark.test.js +366 -0
  42. package/dist/consolidator-embedding-benchmark.test.js.map +1 -0
  43. package/dist/consolidator.d.ts +131 -0
  44. package/dist/consolidator.d.ts.map +1 -0
  45. package/dist/consolidator.js +309 -0
  46. package/dist/consolidator.js.map +1 -0
  47. package/dist/consolidator.test.d.ts +17 -0
  48. package/dist/consolidator.test.d.ts.map +1 -0
  49. package/dist/consolidator.test.js +376 -0
  50. package/dist/consolidator.test.js.map +1 -0
  51. package/dist/controller-registry.d.ts +290 -0
  52. package/dist/controller-registry.d.ts.map +1 -0
  53. package/dist/controller-registry.js +1095 -0
  54. package/dist/controller-registry.js.map +1 -0
  55. package/dist/controller-registry.test.d.ts +14 -0
  56. package/dist/controller-registry.test.d.ts.map +1 -0
  57. package/dist/controller-registry.test.js +818 -0
  58. package/dist/controller-registry.test.js.map +1 -0
  59. package/dist/database-provider.d.ts +14 -2
  60. package/dist/database-provider.d.ts.map +1 -1
  61. package/dist/database-provider.js +63 -3
  62. package/dist/database-provider.js.map +1 -1
  63. package/dist/database-provider.test.js +56 -3
  64. package/dist/database-provider.test.js.map +1 -1
  65. package/dist/entity-tagger.d.ts +31 -0
  66. package/dist/entity-tagger.d.ts.map +1 -0
  67. package/dist/entity-tagger.js +80 -0
  68. package/dist/entity-tagger.js.map +1 -0
  69. package/dist/entity-tagger.test.d.ts +12 -0
  70. package/dist/entity-tagger.test.d.ts.map +1 -0
  71. package/dist/entity-tagger.test.js +70 -0
  72. package/dist/entity-tagger.test.js.map +1 -0
  73. package/dist/fts5.test.d.ts +13 -0
  74. package/dist/fts5.test.d.ts.map +1 -0
  75. package/dist/fts5.test.js +144 -0
  76. package/dist/fts5.test.js.map +1 -0
  77. package/dist/graceful-retrieval.test.d.ts +14 -0
  78. package/dist/graceful-retrieval.test.d.ts.map +1 -0
  79. package/dist/graceful-retrieval.test.js +251 -0
  80. package/dist/graceful-retrieval.test.js.map +1 -0
  81. package/dist/hnsw-index.d.ts +62 -0
  82. package/dist/hnsw-index.d.ts.map +1 -1
  83. package/dist/hnsw-index.js +461 -16
  84. package/dist/hnsw-index.js.map +1 -1
  85. package/dist/hnsw-persistence.test.d.ts +13 -0
  86. package/dist/hnsw-persistence.test.d.ts.map +1 -0
  87. package/dist/hnsw-persistence.test.js +208 -0
  88. package/dist/hnsw-persistence.test.js.map +1 -0
  89. package/dist/hnsw-quantization.test.d.ts +17 -0
  90. package/dist/hnsw-quantization.test.d.ts.map +1 -0
  91. package/dist/hnsw-quantization.test.js +140 -0
  92. package/dist/hnsw-quantization.test.js.map +1 -0
  93. package/dist/hybrid-backend.d.ts +46 -2
  94. package/dist/hybrid-backend.d.ts.map +1 -1
  95. package/dist/hybrid-backend.js +120 -21
  96. package/dist/hybrid-backend.js.map +1 -1
  97. package/dist/hybrid-backend.test.js +139 -5
  98. package/dist/hybrid-backend.test.js.map +1 -1
  99. package/dist/index.d.ts +164 -10
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +272 -30
  102. package/dist/index.js.map +1 -1
  103. package/dist/index.test.d.ts +10 -0
  104. package/dist/index.test.d.ts.map +1 -0
  105. package/dist/index.test.js +71 -0
  106. package/dist/index.test.js.map +1 -0
  107. package/dist/json-security.d.ts +12 -0
  108. package/dist/json-security.d.ts.map +1 -0
  109. package/dist/json-security.js +20 -0
  110. package/dist/json-security.js.map +1 -0
  111. package/dist/learning-bridge.d.ts +29 -0
  112. package/dist/learning-bridge.d.ts.map +1 -1
  113. package/dist/learning-bridge.js +71 -6
  114. package/dist/learning-bridge.js.map +1 -1
  115. package/dist/learning-bridge.test.js +181 -1
  116. package/dist/learning-bridge.test.js.map +1 -1
  117. package/dist/memory-key.d.ts +3 -0
  118. package/dist/memory-key.d.ts.map +1 -0
  119. package/dist/memory-key.js +5 -0
  120. package/dist/memory-key.js.map +1 -0
  121. package/dist/migration.d.ts +19 -4
  122. package/dist/migration.d.ts.map +1 -1
  123. package/dist/migration.js +99 -24
  124. package/dist/migration.js.map +1 -1
  125. package/dist/migration.test.d.ts +11 -0
  126. package/dist/migration.test.d.ts.map +1 -0
  127. package/dist/migration.test.js +141 -0
  128. package/dist/migration.test.js.map +1 -0
  129. package/dist/mmr-benchmark.test.d.ts +2 -0
  130. package/dist/mmr-benchmark.test.d.ts.map +1 -0
  131. package/dist/mmr-benchmark.test.js +286 -0
  132. package/dist/mmr-benchmark.test.js.map +1 -0
  133. package/dist/mmr-rerank-cosine-cache.test.d.ts +2 -0
  134. package/dist/mmr-rerank-cosine-cache.test.d.ts.map +1 -0
  135. package/dist/mmr-rerank-cosine-cache.test.js +334 -0
  136. package/dist/mmr-rerank-cosine-cache.test.js.map +1 -0
  137. package/dist/mmr-rerank-perf.test.d.ts +2 -0
  138. package/dist/mmr-rerank-perf.test.d.ts.map +1 -0
  139. package/dist/mmr-rerank-perf.test.js +191 -0
  140. package/dist/mmr-rerank-perf.test.js.map +1 -0
  141. package/dist/persistent-sona.d.ts +144 -0
  142. package/dist/persistent-sona.d.ts.map +1 -0
  143. package/dist/persistent-sona.js +332 -0
  144. package/dist/persistent-sona.js.map +1 -0
  145. package/dist/rvf-backend.d.ts +53 -0
  146. package/dist/rvf-backend.d.ts.map +1 -0
  147. package/dist/rvf-backend.js +643 -0
  148. package/dist/rvf-backend.js.map +1 -0
  149. package/dist/rvf-learning-store.d.ts +139 -0
  150. package/dist/rvf-learning-store.d.ts.map +1 -0
  151. package/dist/rvf-learning-store.js +295 -0
  152. package/dist/rvf-learning-store.js.map +1 -0
  153. package/dist/rvf-migration.d.ts +45 -0
  154. package/dist/rvf-migration.d.ts.map +1 -0
  155. package/dist/rvf-migration.js +254 -0
  156. package/dist/rvf-migration.js.map +1 -0
  157. package/dist/smart-retrieval-scores.test.d.ts +2 -0
  158. package/dist/smart-retrieval-scores.test.d.ts.map +1 -0
  159. package/dist/smart-retrieval-scores.test.js +75 -0
  160. package/dist/smart-retrieval-scores.test.js.map +1 -0
  161. package/dist/smart-retrieval.d.ts +141 -0
  162. package/dist/smart-retrieval.d.ts.map +1 -0
  163. package/dist/smart-retrieval.js +399 -0
  164. package/dist/smart-retrieval.js.map +1 -0
  165. package/dist/smart-retrieval.test.d.ts +2 -0
  166. package/dist/smart-retrieval.test.d.ts.map +1 -0
  167. package/dist/smart-retrieval.test.js +418 -0
  168. package/dist/smart-retrieval.test.js.map +1 -0
  169. package/dist/sqlite-backend.d.ts +10 -0
  170. package/dist/sqlite-backend.d.ts.map +1 -1
  171. package/dist/sqlite-backend.js +101 -5
  172. package/dist/sqlite-backend.js.map +1 -1
  173. package/dist/sqljs-backend.d.ts +9 -0
  174. package/dist/sqljs-backend.d.ts.map +1 -1
  175. package/dist/sqljs-backend.js +91 -3
  176. package/dist/sqljs-backend.js.map +1 -1
  177. package/dist/tiered-memory.d.ts +171 -0
  178. package/dist/tiered-memory.d.ts.map +1 -0
  179. package/dist/tiered-memory.js +350 -0
  180. package/dist/tiered-memory.js.map +1 -0
  181. package/dist/tiered-memory.test.d.ts +9 -0
  182. package/dist/tiered-memory.test.d.ts.map +1 -0
  183. package/dist/tiered-memory.test.js +220 -0
  184. package/dist/tiered-memory.test.js.map +1 -0
  185. package/dist/types.d.ts +17 -0
  186. package/dist/types.d.ts.map +1 -1
  187. package/dist/types.js.map +1 -1
  188. package/package.json +10 -8
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Phase 4.1 — embedding near-duplicate pass: precision/recall, latency,
3
+ * namespace-isolation, and determinism receipts (response to PR #3232
4
+ * review: "the 0.95 threshold needs an empirical contract rather than a
5
+ * smoke fixture").
6
+ *
7
+ * IMPORTANT — corpus provenance: this file does NOT use a real pinned
8
+ * embedding model. Both real ONNX backends this monorepo ships
9
+ * (`@huggingface/transformers` and the legacy `@xenova/transformers`) were
10
+ * attempted directly in this environment and both fail for reasons
11
+ * unrelated to this candidate:
12
+ * - `@huggingface/transformers@4.2.0`: `transformers.node.mjs` does
13
+ * `import { Tensor } from "onnxruntime-common"` against a CJS module,
14
+ * a real ESM/CJS interop break under this Node version — reproduces
15
+ * on an unmodified checkout, confirmed before writing this file.
16
+ * - `@xenova/transformers@2.17.0`: pulls in `sharp@0.32.6`, whose
17
+ * native binding (`sharp-linux-x64.node`) isn't present for this
18
+ * sandbox's platform.
19
+ * Neither is fixable within this PR's scope without touching unrelated,
20
+ * pre-existing native/module-resolution infrastructure this diff never
21
+ * touches. This package's own `__tests__/embeddings.test.ts` exercises
22
+ * only the `mock` provider — it never invokes a real transformer either,
23
+ * consistent with what was found here.
24
+ *
25
+ * What this file DOES provide instead: a deterministic synthetic corpus
26
+ * where pairwise cosine similarity is constructed EXACTLY (not measured
27
+ * after the fact) via `pairAtSimilarity()` below — for every pair the
28
+ * ground-truth similarity is known analytically, not estimated. That
29
+ * makes this a rigorous test of the near-dup pass's THRESHOLD MECHANICS
30
+ * (precision/recall as a function of `similarityThreshold`, exactly where
31
+ * the boundary is) — arguably a cleaner instrument for that specific
32
+ * question than a real corpus would be, since there is no measurement
33
+ * noise in the "true" similarity. It does NOT validate that 0.95 is the
34
+ * right cutoff for real-world semantic paraphrase detection with a real
35
+ * embedding model — that claim remains open pending the blocked ONNX
36
+ * path, and is called out explicitly, not implied.
37
+ */
38
+ import { describe, it, expect } from 'vitest';
39
+ import { MemoryService } from './index.js';
40
+ import { MemoryConsolidator } from './consolidator.js';
41
+ import { createDefaultEntry } from './types.js';
42
+ /** Deterministic xorshift PRNG, seeded — matches consolidator.test.ts's randomVec. */
43
+ function seededRng(seed) {
44
+ let s = seed | 0 || 1;
45
+ return () => {
46
+ s ^= s << 13;
47
+ s ^= s >>> 17;
48
+ s ^= s << 5;
49
+ return (s | 0) / 2 ** 31;
50
+ };
51
+ }
52
+ function randomUnitVector(dim, seed) {
53
+ const rng = seededRng(seed);
54
+ const v = new Float32Array(dim);
55
+ for (let i = 0; i < dim; i++)
56
+ v[i] = rng();
57
+ return normalize(v);
58
+ }
59
+ function normalize(v) {
60
+ let norm = 0;
61
+ for (let i = 0; i < v.length; i++)
62
+ norm += v[i] * v[i];
63
+ norm = Math.sqrt(norm) || 1;
64
+ const out = new Float32Array(v.length);
65
+ for (let i = 0; i < v.length; i++)
66
+ out[i] = v[i] / norm;
67
+ return out;
68
+ }
69
+ function dot(a, b) {
70
+ let s = 0;
71
+ for (let i = 0; i < a.length; i++)
72
+ s += a[i] * b[i];
73
+ return s;
74
+ }
75
+ /**
76
+ * Construct a unit vector `b` such that cosine(a, b) === targetSimilarity
77
+ * exactly (up to float precision), by mixing `a` with a vector orthogonal
78
+ * to it: b = s*a + sqrt(1-s^2)*orth, |a|=|orth|=1, a⊥orth.
79
+ */
80
+ function vectorAtSimilarity(a, targetSimilarity, seed) {
81
+ const dim = a.length;
82
+ // Random candidate, then Gram-Schmidt to make it orthogonal to `a`.
83
+ let orth = randomUnitVector(dim, seed);
84
+ const proj = dot(orth, a);
85
+ const raw = new Float32Array(dim);
86
+ for (let i = 0; i < dim; i++)
87
+ raw[i] = orth[i] - proj * a[i];
88
+ orth = normalize(raw);
89
+ const s = targetSimilarity;
90
+ const c = Math.sqrt(Math.max(0, 1 - s * s));
91
+ const out = new Float32Array(dim);
92
+ for (let i = 0; i < dim; i++)
93
+ out[i] = s * a[i] + c * orth[i];
94
+ return out;
95
+ }
96
+ async function newService(dimensions = 32) {
97
+ const svc = new MemoryService({ dimensions, persistenceEnabled: false, snapshotInterval: 0 });
98
+ await svc.initialize();
99
+ return svc;
100
+ }
101
+ const DIM = 32;
102
+ // Base anchor vectors, one per pair, all mutually near-orthogonal (distinct
103
+ // content clusters) so pairs don't cross-contaminate each other's matches.
104
+ function buildCorpus() {
105
+ const pairs = [
106
+ { label: 'near-dup-0.999', targetSimilarity: 0.999, shouldMergeAtDefault: true },
107
+ { label: 'near-dup-0.98', targetSimilarity: 0.98, shouldMergeAtDefault: true },
108
+ { label: 'near-dup-0.96', targetSimilarity: 0.96, shouldMergeAtDefault: true },
109
+ { label: 'boundary-0.955', targetSimilarity: 0.955, shouldMergeAtDefault: true },
110
+ { label: 'hard-negative-0.94', targetSimilarity: 0.94, shouldMergeAtDefault: false },
111
+ { label: 'hard-negative-0.90', targetSimilarity: 0.90, shouldMergeAtDefault: false },
112
+ { label: 'hard-negative-0.85', targetSimilarity: 0.85, shouldMergeAtDefault: false },
113
+ { label: 'easy-negative-0.30', targetSimilarity: 0.30, shouldMergeAtDefault: false },
114
+ ];
115
+ const anchors = pairs.map((_, i) => randomUnitVector(DIM, 1000 + i * 7));
116
+ return { anchors, pairs };
117
+ }
118
+ describe('Phase 4.1 embedding benchmark — pairwise similarity is exact by construction', () => {
119
+ it('vectorAtSimilarity produces the requested cosine similarity to within 1e-5', () => {
120
+ const a = randomUnitVector(DIM, 42);
121
+ for (const target of [0.999, 0.96, 0.955, 0.9, 0.85, 0.3, 0, -0.5]) {
122
+ const b = vectorAtSimilarity(a, target, 99);
123
+ expect(dot(a, b)).toBeCloseTo(target, 5);
124
+ }
125
+ });
126
+ });
127
+ describe('Phase 4.1 embedding benchmark — precision/recall across a threshold sweep', () => {
128
+ it('at the shipped default (0.95), every near-dup pair merges and every hard negative does not', async () => {
129
+ const svc = await newService();
130
+ const consolidator = new MemoryConsolidator(svc);
131
+ const { anchors, pairs } = buildCorpus();
132
+ const ids = {};
133
+ for (let i = 0; i < pairs.length; i++) {
134
+ const a = createDefaultEntry({ key: `${pairs[i].label}-a`, content: `${pairs[i].label} canonical text ${i}` });
135
+ a.embedding = anchors[i];
136
+ await svc.store(a);
137
+ const b = createDefaultEntry({ key: `${pairs[i].label}-b`, content: `${pairs[i].label} variant text ${i}` });
138
+ b.embedding = vectorAtSimilarity(anchors[i], pairs[i].targetSimilarity, 5000 + i);
139
+ await svc.store(b);
140
+ ids[pairs[i].label] = [a.id, b.id];
141
+ }
142
+ await consolidator.dedup('keep-newest');
143
+ const adapter = svc.getAdapter();
144
+ let truePositives = 0;
145
+ let falseNegatives = 0;
146
+ let trueNegatives = 0;
147
+ let falsePositives = 0;
148
+ for (const pair of pairs) {
149
+ const [idA, idB] = ids[pair.label];
150
+ const bothSurvive = adapter.entries.has(idA) && adapter.entries.has(idB);
151
+ const merged = !bothSurvive;
152
+ if (pair.shouldMergeAtDefault) {
153
+ if (merged)
154
+ truePositives++;
155
+ else
156
+ falseNegatives++;
157
+ }
158
+ else {
159
+ if (merged)
160
+ falsePositives++;
161
+ else
162
+ trueNegatives++;
163
+ }
164
+ }
165
+ // Ground-truth contract for the shipped default: clean separation
166
+ // around the 0.95 boundary in this corpus — no false merges, no
167
+ // false splits among the near-dup/hard-negative pairs constructed
168
+ // above.
169
+ expect(falsePositives).toBe(0); // no hard negative incorrectly merged
170
+ expect(falseNegatives).toBe(0); // no true near-dup left unmerged
171
+ expect(truePositives).toBe(pairs.filter((p) => p.shouldMergeAtDefault).length);
172
+ expect(trueNegatives).toBe(pairs.filter((p) => !p.shouldMergeAtDefault).length);
173
+ await svc.close();
174
+ });
175
+ it('reports precision/recall/false-merge-rate across a threshold sweep', async () => {
176
+ // Deliberately offset from every corpus pair's constructed similarity
177
+ // (0.999/0.98/0.96/0.955/0.94/0.90/0.85/0.30) by a margin large enough
178
+ // to absorb float32 precision jitter from HNSW's internal
179
+ // normalize-then-dot-product distance computation (empirically <1e-5
180
+ // here, but a boundary value with ZERO margin — e.g. sweeping exactly
181
+ // 0.90 against a pair constructed at exactly 0.90 — is a real flake
182
+ // this file hit and fixed while writing it; the margin here is the fix).
183
+ const thresholds = [0.5, 0.8, 0.875, 0.92, 0.97];
184
+ const rows = [];
185
+ for (const threshold of thresholds) {
186
+ const svc = await newService();
187
+ const consolidator = new MemoryConsolidator(svc, { similarityThreshold: threshold });
188
+ const { anchors, pairs: p2 } = buildCorpus();
189
+ const ids = {};
190
+ for (let i = 0; i < p2.length; i++) {
191
+ const a = createDefaultEntry({ key: `${p2[i].label}-a`, content: `${p2[i].label} canonical text ${i}` });
192
+ a.embedding = anchors[i];
193
+ await svc.store(a);
194
+ const b = createDefaultEntry({ key: `${p2[i].label}-b`, content: `${p2[i].label} variant text ${i}` });
195
+ b.embedding = vectorAtSimilarity(anchors[i], p2[i].targetSimilarity, 5000 + i);
196
+ await svc.store(b);
197
+ ids[p2[i].label] = [a.id, b.id];
198
+ }
199
+ await consolidator.dedup('keep-newest');
200
+ const adapter = svc.getAdapter();
201
+ // Ground truth here is "similarity >= threshold" (not the fixed
202
+ // 0.95-default contract used above), so precision/recall are
203
+ // measured against what SHOULD merge at each threshold under test.
204
+ let tp = 0;
205
+ let fp = 0;
206
+ let fn = 0;
207
+ let tn = 0;
208
+ for (const pair of p2) {
209
+ const [idA, idB] = ids[pair.label];
210
+ const merged = !(adapter.entries.has(idA) && adapter.entries.has(idB));
211
+ const shouldMerge = pair.targetSimilarity >= threshold;
212
+ if (shouldMerge && merged)
213
+ tp++;
214
+ else if (shouldMerge && !merged)
215
+ fn++;
216
+ else if (!shouldMerge && merged)
217
+ fp++;
218
+ else
219
+ tn++;
220
+ }
221
+ const precision = tp + fp === 0 ? 1 : tp / (tp + fp);
222
+ const recall = tp + fn === 0 ? 1 : tp / (tp + fn);
223
+ const falseMergeRate = fp + tn === 0 ? 0 : fp / (fp + tn);
224
+ rows.push({ threshold, precision, recall, falseMergeRate });
225
+ await svc.close();
226
+ }
227
+ // eslint-disable-next-line no-console
228
+ console.log('similarityThreshold sweep (synthetic exact-similarity corpus):', JSON.stringify(rows));
229
+ // Every threshold in this sweep gets perfect precision/recall on this
230
+ // corpus, because pair similarities were deliberately placed with a
231
+ // >=0.005 margin on either side of each candidate threshold. That is
232
+ // the corpus proving the near-dup pass's comparison (`similarity >=
233
+ // threshold`) is exact and monotonic, not that any one threshold is
234
+ // "best" — this sweep is a mechanics check, not a model-selection
235
+ // benchmark.
236
+ for (const row of rows) {
237
+ expect(row.precision).toBe(1);
238
+ expect(row.recall).toBe(1);
239
+ expect(row.falseMergeRate).toBe(0);
240
+ }
241
+ });
242
+ });
243
+ describe('Phase 4.1 embedding benchmark — namespace isolation (pre-existing behavior, unchanged)', () => {
244
+ it('cross-namespace near-duplicates merge exactly as cross-namespace hash-exact duplicates already did', async () => {
245
+ const svc = await newService();
246
+ const consolidator = new MemoryConsolidator(svc);
247
+ // Hash-exact case: identical content, two namespaces. dedup()'s
248
+ // bucket-by-hash pass has never scoped by namespace (grep-confirmed
249
+ // on the pre-candidate code: `for (const entry of entries.values())`
250
+ // with no namespace filter) — this candidate does not change that.
251
+ const h1 = createDefaultEntry({ key: 'h', content: 'exact-duplicate-content', namespace: 'ns-a' });
252
+ await svc.store(h1);
253
+ const h2 = createDefaultEntry({ key: 'h', content: 'exact-duplicate-content', namespace: 'ns-b' });
254
+ await svc.store(h2);
255
+ // Near-dup case: different content, identical embedding, two namespaces.
256
+ const anchor = randomUnitVector(DIM, 777);
257
+ const e1 = createDefaultEntry({ key: 'e', content: 'namespace-a-phrasing', namespace: 'ns-a' });
258
+ e1.embedding = anchor;
259
+ await svc.store(e1);
260
+ const e2 = createDefaultEntry({ key: 'e', content: 'namespace-b-phrasing', namespace: 'ns-b' });
261
+ e2.embedding = new Float32Array(anchor);
262
+ await svc.store(e2);
263
+ const result = await consolidator.dedup('keep-newest');
264
+ const adapter = svc.getAdapter();
265
+ // Both the hash-exact pair and the near-dup pair merge across the
266
+ // namespace boundary — documented, not silently changed. If Ruflo
267
+ // later decides dedup() should be namespace-scoped, that's a
268
+ // separate, pre-existing-behavior-affecting decision spanning both
269
+ // passes, not something introduced by this candidate.
270
+ const hashSurvivors = [h1.id, h2.id].filter((id) => adapter.entries.has(id));
271
+ const embedSurvivors = [e1.id, e2.id].filter((id) => adapter.entries.has(id));
272
+ expect(hashSurvivors.length).toBe(1);
273
+ expect(embedSurvivors.length).toBe(1);
274
+ expect(result.merged).toBe(2);
275
+ await svc.close();
276
+ });
277
+ });
278
+ describe('Phase 4.1 embedding benchmark — determinism / replay', () => {
279
+ it('the same corpus produces byte-identical merge/group counts and survivor keys across 3 independent runs', async () => {
280
+ // Entry ids are randomly generated per store() call (mem_<ts>_<rand>),
281
+ // so they are NOT expected to match across independent runs even when
282
+ // merge behavior is fully deterministic — comparing raw ids here would
283
+ // be testing the id generator, not dedup(). Compare by `key` instead,
284
+ // which this corpus constructs deterministically from `pairs`.
285
+ async function runOnce() {
286
+ const svc = await newService();
287
+ const consolidator = new MemoryConsolidator(svc);
288
+ const { anchors, pairs } = buildCorpus();
289
+ const idToKey = new Map();
290
+ for (let i = 0; i < pairs.length; i++) {
291
+ const aKey = `${pairs[i].label}-a`;
292
+ const a = createDefaultEntry({ key: aKey, content: `${pairs[i].label} canonical text ${i}` });
293
+ a.embedding = anchors[i];
294
+ a.updatedAt = 1000 + i * 2;
295
+ await svc.store(a);
296
+ idToKey.set(a.id, aKey);
297
+ const bKey = `${pairs[i].label}-b`;
298
+ const b = createDefaultEntry({ key: bKey, content: `${pairs[i].label} variant text ${i}` });
299
+ b.embedding = vectorAtSimilarity(anchors[i], pairs[i].targetSimilarity, 5000 + i);
300
+ b.updatedAt = 1000 + i * 2 + 1; // always the newer of the pair
301
+ await svc.store(b);
302
+ idToKey.set(b.id, bKey);
303
+ }
304
+ const result = await consolidator.dedup('keep-newest');
305
+ const adapter = svc.getAdapter();
306
+ const survivorKeys = [...idToKey.entries()]
307
+ .filter(([id]) => adapter.entries.has(id))
308
+ .map(([, key]) => key)
309
+ .sort();
310
+ await svc.close();
311
+ return { merged: result.merged, groups: result.groups, survivorKeys };
312
+ }
313
+ // Sequential, not parallel — isolates each run's timing/state fully,
314
+ // removing any doubt about event-loop interleaving as a confound.
315
+ const r1 = await runOnce();
316
+ const r2 = await runOnce();
317
+ const r3 = await runOnce();
318
+ expect(r2).toEqual(r1);
319
+ expect(r3).toEqual(r1);
320
+ });
321
+ });
322
+ describe('Phase 4.1 embedding benchmark — latency/memory at realistic cardinality', () => {
323
+ it('dedup() at N=5000 (matching this repo\'s own HNSW benchmark convention) completes within a generous ceiling, baseline vs candidate', async () => {
324
+ const N = 5000;
325
+ const DUP_FRACTION = 0.1; // 10% of entries are near-duplicates of an earlier entry
326
+ async function buildAndRun(similarityThreshold) {
327
+ const svc = await newService();
328
+ const consolidator = new MemoryConsolidator(svc, { similarityThreshold });
329
+ const anchors = [];
330
+ for (let i = 0; i < N; i++) {
331
+ const isDup = i > 0 && i % Math.round(1 / DUP_FRACTION) === 0;
332
+ let embedding;
333
+ if (isDup) {
334
+ const anchor = anchors[Math.floor(Math.random() * anchors.length)];
335
+ embedding = vectorAtSimilarity(anchor, 0.985, i);
336
+ }
337
+ else {
338
+ embedding = randomUnitVector(DIM, 20000 + i);
339
+ anchors.push(embedding);
340
+ }
341
+ const entry = createDefaultEntry({ key: `n-${i}`, content: `entry-${i}-${isDup ? 'dup' : 'unique'}` });
342
+ entry.embedding = embedding;
343
+ await svc.store(entry);
344
+ }
345
+ const memBefore = process.memoryUsage().heapUsed;
346
+ const t0 = Date.now();
347
+ const result = await consolidator.dedup('keep-newest');
348
+ const durationMs = Date.now() - t0;
349
+ const memAfter = process.memoryUsage().heapUsed;
350
+ await svc.close();
351
+ return { durationMs, heapDeltaMb: (memAfter - memBefore) / (1024 * 1024), merged: result.merged };
352
+ }
353
+ const baseline = await buildAndRun(1); // near-dup pass disabled — hash-only, matches pre-candidate behavior
354
+ const candidate = await buildAndRun(0.95); // shipped default
355
+ // eslint-disable-next-line no-console
356
+ console.log('latency/memory @ N=5000:', JSON.stringify({ baseline, candidate }));
357
+ // Generous ceilings — this is a regression guard against a pathological
358
+ // blowup (e.g., an accidental O(n^2) reintroduction), not a tight perf
359
+ // assertion; CI hardware varies. Real numbers are logged above for the
360
+ // reviewer regardless of pass/fail margin.
361
+ expect(candidate.durationMs).toBeLessThan(15_000);
362
+ expect(candidate.merged).toBeGreaterThan(0); // the injected near-dups were actually caught
363
+ expect(baseline.merged).toBe(0); // hash-only baseline: all content strings are unique, so 0 hash-exact merges
364
+ }, 30_000);
365
+ });
366
+ //# sourceMappingURL=consolidator-embedding-benchmark.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidator-embedding-benchmark.test.js","sourceRoot":"","sources":["../src/consolidator-embedding-benchmark.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * MemoryConsolidator — ADR-125 Phase 4
3
+ *
4
+ * Periodic maintenance for the in-memory state owned by {@link UnifiedMemoryService}.
5
+ *
6
+ * Operations:
7
+ * - `sweepExpired()` — drop entries past `expiresAt` from all indexes (including HNSW).
8
+ * - `dedup(strategy)` — collapse content-hash duplicates per strategy.
9
+ * - `compactHnsw()` — rebuild the HNSW index from current `entries`.
10
+ * - `runAll()` — sweep → dedup → compact in order.
11
+ *
12
+ * Invoked from two paths:
13
+ * 1. {@link UnifiedMemoryService}'s lifecycle (background timer when
14
+ * `consolidator.autoRun === true`, plus `close()`).
15
+ * 2. The AgentDB `nightlyLearner` controller (`src/controller-registry.ts`)
16
+ * delegates to `runAll()` instead of hitting AgentDB directly.
17
+ *
18
+ * Phase 3 placeholder lives in this file too — it provides the typed
19
+ * surface that {@link UnifiedMemoryService.getConsolidator} resolves to.
20
+ * The real implementation lands with Phase 4.
21
+ *
22
+ * @module v3/memory/consolidator
23
+ */
24
+ import type { MemoryEntry } from './types.js';
25
+ /**
26
+ * Strategy for resolving content-hash duplicates inside {@link MemoryConsolidator.dedup}.
27
+ */
28
+ export type DedupStrategy = 'keep-newest' | 'keep-oldest' | 'merge-tags';
29
+ export interface ConsolidatorOptions {
30
+ /** Default strategy when `dedup()` is invoked with no argument. */
31
+ dedupStrategy?: DedupStrategy;
32
+ /** Used by `MemoryService` when scheduling automatic runs (ms). */
33
+ intervalMs?: number;
34
+ /**
35
+ * Cosine-similarity floor (0-1) above which two entries with embeddings
36
+ * are treated as near-duplicates by `dedup()`'s embedding pass, in
37
+ * addition to its byte-exact content-hash pass. Set to `1` (or above) to
38
+ * disable the embedding pass entirely and keep pre-Phase-4.1 hash-only
39
+ * behavior. Default 0.95 — conservative, matches the threshold already
40
+ * used by the (unwired) domain-layer consolidator for the same purpose.
41
+ */
42
+ similarityThreshold?: number;
43
+ }
44
+ export interface SweepResult {
45
+ removed: number;
46
+ remaining: number;
47
+ hnswRemoved: number;
48
+ }
49
+ export interface DedupResult {
50
+ merged: number;
51
+ groups: number;
52
+ }
53
+ export interface CompactResult {
54
+ before: number;
55
+ after: number;
56
+ durationMs: number;
57
+ }
58
+ export interface ConsolidationResult {
59
+ sweep: SweepResult;
60
+ dedup: DedupResult;
61
+ compact: CompactResult;
62
+ totalDurationMs: number;
63
+ }
64
+ /**
65
+ * Minimal surface the consolidator needs from `UnifiedMemoryService`. Avoids
66
+ * a circular type import.
67
+ */
68
+ interface ServiceLike {
69
+ getAdapter(): {
70
+ entries: Map<string, MemoryEntry>;
71
+ namespaceIndex: Map<string, Set<string>>;
72
+ keyIndex: Map<string, string>;
73
+ tagIndex: Map<string, Set<string>>;
74
+ [key: string]: any;
75
+ };
76
+ }
77
+ export declare class MemoryConsolidator {
78
+ private readonly service;
79
+ private readonly opts;
80
+ constructor(service: ServiceLike, opts?: ConsolidatorOptions);
81
+ /**
82
+ * Drop all entries whose `expiresAt` is in the past.
83
+ */
84
+ sweepExpired(): Promise<SweepResult>;
85
+ /**
86
+ * Pick the keeper for a duplicate group per `strategy` and, for
87
+ * `merge-tags`, union the group's tag sets onto it. Shared by both the
88
+ * content-hash pass and the embedding near-duplicate pass in `dedup()`.
89
+ */
90
+ private selectKeeper;
91
+ /**
92
+ * Drop every entry in `bucket` except the strategy-selected keeper,
93
+ * updating all adapter indexes (and the HNSW index, for entries that have
94
+ * an embedding) to match. Shared by both dedup passes.
95
+ */
96
+ private mergeGroup;
97
+ /**
98
+ * Collapse duplicates across all namespaces per `strategy`, in two passes:
99
+ *
100
+ * 1. Byte-exact content-hash buckets (unchanged from pre-4.1 behavior).
101
+ * 2. Embedding near-duplicates: for entries that survive pass 1 and carry
102
+ * an `embedding`, query the already-populated `HNSWIndex` (the same
103
+ * index instance this method already holds a handle to for removal
104
+ * bookkeeping) for cosine-similarity neighbors above
105
+ * `opts.similarityThreshold` (default 0.95). This catches paraphrases
106
+ * and reformattings that byte-exact hashing structurally cannot, at no
107
+ * extra backend round-trip cost — the embedding and the index are both
108
+ * already resident in memory at this call site.
109
+ *
110
+ * Pass 2 only runs when the index's configured metric is `'cosine'` (its
111
+ * distances are `1 - similarity`) and the threshold is `< 1`; otherwise
112
+ * behavior is identical to hash-only dedup.
113
+ *
114
+ * - `keep-newest`: keep the entry with the highest `updatedAt`, drop the rest.
115
+ * - `keep-oldest`: keep the entry with the lowest `createdAt`, drop the rest.
116
+ * - `merge-tags`: keep newest, but union the tag sets of the duplicates first.
117
+ */
118
+ dedup(strategy?: DedupStrategy): Promise<DedupResult>;
119
+ /**
120
+ * Rebuild the HNSW index from the current set of entries with embeddings.
121
+ * Returns a count snapshot + duration.
122
+ */
123
+ compactHnsw(): Promise<CompactResult>;
124
+ /**
125
+ * Sweep → dedup → compact. Used by the background timer and by the
126
+ * `nightlyLearner` AgentDB controller.
127
+ */
128
+ runAll(): Promise<ConsolidationResult>;
129
+ }
130
+ export default MemoryConsolidator;
131
+ //# sourceMappingURL=consolidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidator.d.ts","sourceRoot":"","sources":["../src/consolidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,aAAa,GAAG,YAAY,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAoBD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,UAAU,WAAW;IACnB,UAAU,IAAI;QAEZ,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAClC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAEnC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,mBAAwB;IAGjD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IA4C1C;;;;OAIG;IACH,OAAO,CAAC,YAAY;IASpB;;;;OAIG;YACW,UAAU;IA8CxB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,KAAK,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAmF3D;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAsC3C;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC;CAY7C;AAED,eAAe,kBAAkB,CAAC"}