@claude-flow/memory 3.0.0-alpha.17 → 3.0.0-alpha.18

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/dist/agentdb-adapter.d.ts +60 -1
  2. package/dist/agentdb-adapter.d.ts.map +1 -1
  3. package/dist/agentdb-adapter.js +253 -9
  4. package/dist/agentdb-adapter.js.map +1 -1
  5. package/dist/consolidator.d.ts +96 -0
  6. package/dist/consolidator.d.ts.map +1 -0
  7. package/dist/consolidator.js +209 -0
  8. package/dist/consolidator.js.map +1 -0
  9. package/dist/consolidator.test.d.ts +17 -0
  10. package/dist/consolidator.test.d.ts.map +1 -0
  11. package/dist/consolidator.test.js +239 -0
  12. package/dist/consolidator.test.js.map +1 -0
  13. package/dist/controller-registry.d.ts +7 -0
  14. package/dist/controller-registry.d.ts.map +1 -1
  15. package/dist/controller-registry.js +92 -5
  16. package/dist/controller-registry.js.map +1 -1
  17. package/dist/database-provider.d.ts +13 -2
  18. package/dist/database-provider.d.ts.map +1 -1
  19. package/dist/database-provider.js +37 -2
  20. package/dist/database-provider.js.map +1 -1
  21. package/dist/database-provider.test.js +41 -0
  22. package/dist/database-provider.test.js.map +1 -1
  23. package/dist/fts5.test.d.ts +13 -0
  24. package/dist/fts5.test.d.ts.map +1 -0
  25. package/dist/fts5.test.js +144 -0
  26. package/dist/fts5.test.js.map +1 -0
  27. package/dist/graceful-retrieval.test.d.ts +14 -0
  28. package/dist/graceful-retrieval.test.d.ts.map +1 -0
  29. package/dist/graceful-retrieval.test.js +144 -0
  30. package/dist/graceful-retrieval.test.js.map +1 -0
  31. package/dist/hnsw-index.d.ts +51 -0
  32. package/dist/hnsw-index.d.ts.map +1 -1
  33. package/dist/hnsw-index.js +217 -0
  34. package/dist/hnsw-index.js.map +1 -1
  35. package/dist/hnsw-persistence.test.d.ts +13 -0
  36. package/dist/hnsw-persistence.test.d.ts.map +1 -0
  37. package/dist/hnsw-persistence.test.js +208 -0
  38. package/dist/hnsw-persistence.test.js.map +1 -0
  39. package/dist/index.d.ts +149 -13
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +260 -32
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.test.d.ts +10 -0
  44. package/dist/index.test.d.ts.map +1 -0
  45. package/dist/index.test.js +71 -0
  46. package/dist/index.test.js.map +1 -0
  47. package/dist/rvf-backend.d.ts.map +1 -1
  48. package/dist/rvf-backend.js +155 -1
  49. package/dist/rvf-backend.js.map +1 -1
  50. package/dist/smart-retrieval.d.ts +24 -0
  51. package/dist/smart-retrieval.d.ts.map +1 -1
  52. package/dist/smart-retrieval.js +19 -0
  53. package/dist/smart-retrieval.js.map +1 -1
  54. package/dist/sqlite-backend.d.ts +10 -0
  55. package/dist/sqlite-backend.d.ts.map +1 -1
  56. package/dist/sqlite-backend.js +87 -0
  57. package/dist/sqlite-backend.js.map +1 -1
  58. package/dist/sqljs-backend.d.ts +9 -0
  59. package/dist/sqljs-backend.d.ts.map +1 -1
  60. package/dist/sqljs-backend.js +87 -0
  61. package/dist/sqljs-backend.js.map +1 -1
  62. package/package.json +4 -4
  63. package/dist/hnsw-lite.d.ts +0 -23
  64. package/dist/hnsw-lite.d.ts.map +0 -1
  65. package/dist/hnsw-lite.js +0 -168
  66. package/dist/hnsw-lite.js.map +0 -1
@@ -0,0 +1,209 @@
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 { createHash } from 'node:crypto';
25
+ import { HNSWIndex } from './hnsw-index.js';
26
+ export class MemoryConsolidator {
27
+ service;
28
+ opts;
29
+ constructor(service, opts = {}) {
30
+ this.service = service;
31
+ this.opts = opts;
32
+ }
33
+ /**
34
+ * Drop all entries whose `expiresAt` is in the past.
35
+ */
36
+ async sweepExpired() {
37
+ const adapter = this.service.getAdapter();
38
+ const entries = adapter.entries;
39
+ const namespaceIndex = adapter.namespaceIndex;
40
+ const keyIndex = adapter.keyIndex;
41
+ const tagIndex = adapter.tagIndex;
42
+ const index = adapter.index;
43
+ const now = Date.now();
44
+ const toRemove = [];
45
+ for (const entry of entries.values()) {
46
+ if (entry.expiresAt != null && entry.expiresAt < now) {
47
+ toRemove.push(entry);
48
+ }
49
+ }
50
+ let hnswRemoved = 0;
51
+ for (const entry of toRemove) {
52
+ entries.delete(entry.id);
53
+ namespaceIndex.get(entry.namespace)?.delete(entry.id);
54
+ keyIndex.delete(`${entry.namespace}:${entry.key}`);
55
+ for (const tag of entry.tags)
56
+ tagIndex.get(tag)?.delete(entry.id);
57
+ if (entry.embedding) {
58
+ const removed = await index.removePoint(entry.id);
59
+ if (removed)
60
+ hnswRemoved += 1;
61
+ }
62
+ }
63
+ // Clean up empty namespace/tag sets to keep memory bounded
64
+ for (const [ns, ids] of namespaceIndex) {
65
+ if (ids.size === 0)
66
+ namespaceIndex.delete(ns);
67
+ }
68
+ for (const [tag, ids] of tagIndex) {
69
+ if (ids.size === 0)
70
+ tagIndex.delete(tag);
71
+ }
72
+ return {
73
+ removed: toRemove.length,
74
+ remaining: entries.size,
75
+ hnswRemoved,
76
+ };
77
+ }
78
+ /**
79
+ * Collapse content-hash duplicates across all namespaces per `strategy`.
80
+ *
81
+ * - `keep-newest`: keep the entry with the highest `updatedAt`, drop the rest.
82
+ * - `keep-oldest`: keep the entry with the lowest `createdAt`, drop the rest.
83
+ * - `merge-tags`: keep newest, but union the tag sets of the duplicates first.
84
+ */
85
+ async dedup(strategy) {
86
+ const adapter = this.service.getAdapter();
87
+ const entries = adapter.entries;
88
+ const namespaceIndex = adapter.namespaceIndex;
89
+ const keyIndex = adapter.keyIndex;
90
+ const tagIndex = adapter.tagIndex;
91
+ const index = adapter.index;
92
+ const effective = strategy ?? this.opts.dedupStrategy ?? 'keep-newest';
93
+ // Bucket by content hash
94
+ const buckets = new Map();
95
+ for (const entry of entries.values()) {
96
+ const hash = createHash('sha256').update(entry.content).digest('hex');
97
+ const bucket = buckets.get(hash);
98
+ if (bucket)
99
+ bucket.push(entry);
100
+ else
101
+ buckets.set(hash, [entry]);
102
+ }
103
+ let merged = 0;
104
+ let dupGroups = 0;
105
+ for (const bucket of buckets.values()) {
106
+ if (bucket.length <= 1)
107
+ continue;
108
+ dupGroups += 1;
109
+ // Choose keeper
110
+ let keeper;
111
+ if (effective === 'keep-oldest') {
112
+ keeper = bucket.reduce((acc, e) => e.createdAt < acc.createdAt ? e : acc);
113
+ }
114
+ else {
115
+ // keep-newest + merge-tags share this branch
116
+ keeper = bucket.reduce((acc, e) => e.updatedAt > acc.updatedAt ? e : acc);
117
+ }
118
+ if (effective === 'merge-tags') {
119
+ const tagSet = new Set(keeper.tags);
120
+ for (const e of bucket)
121
+ for (const t of e.tags)
122
+ tagSet.add(t);
123
+ const oldTags = keeper.tags;
124
+ keeper.tags = [...tagSet];
125
+ // Update tagIndex membership for newly-added tags
126
+ for (const t of keeper.tags) {
127
+ if (!oldTags.includes(t)) {
128
+ if (!tagIndex.has(t))
129
+ tagIndex.set(t, new Set());
130
+ tagIndex.get(t).add(keeper.id);
131
+ }
132
+ }
133
+ }
134
+ // Drop everyone except the keeper
135
+ for (const e of bucket) {
136
+ if (e.id === keeper.id)
137
+ continue;
138
+ entries.delete(e.id);
139
+ namespaceIndex.get(e.namespace)?.delete(e.id);
140
+ const compositeKey = `${e.namespace}:${e.key}`;
141
+ if (keyIndex.get(compositeKey) === e.id) {
142
+ keyIndex.delete(compositeKey);
143
+ }
144
+ for (const tag of e.tags)
145
+ tagIndex.get(tag)?.delete(e.id);
146
+ if (e.embedding) {
147
+ await index.removePoint(e.id);
148
+ }
149
+ merged += 1;
150
+ }
151
+ }
152
+ return { merged, groups: dupGroups };
153
+ }
154
+ /**
155
+ * Rebuild the HNSW index from the current set of entries with embeddings.
156
+ * Returns a count snapshot + duration.
157
+ */
158
+ async compactHnsw() {
159
+ const adapter = this.service.getAdapter();
160
+ const entries = adapter.entries;
161
+ const index = adapter.index;
162
+ const before = index.size;
163
+ const t0 = Date.now();
164
+ // Build a fresh HNSW from current entries that have embeddings.
165
+ const cfg = index.getConfig();
166
+ const fresh = new HNSWIndex({
167
+ dimensions: cfg.dimensions,
168
+ M: cfg.M,
169
+ efConstruction: cfg.efConstruction,
170
+ maxElements: cfg.maxElements,
171
+ metric: cfg.metric,
172
+ });
173
+ for (const entry of entries.values()) {
174
+ if (entry.embedding) {
175
+ try {
176
+ await fresh.addPoint(entry.id, entry.embedding);
177
+ }
178
+ catch {
179
+ // Tolerate dimension mismatches in malformed datasets.
180
+ }
181
+ }
182
+ }
183
+ // Swap pointers atomically and re-forward events
184
+ adapter.index = fresh;
185
+ if (typeof adapter.emit === 'function') {
186
+ fresh.on('point:added', (data) => adapter.emit('index:added', data));
187
+ }
188
+ const durationMs = Date.now() - t0;
189
+ return { before, after: fresh.size, durationMs };
190
+ }
191
+ /**
192
+ * Sweep → dedup → compact. Used by the background timer and by the
193
+ * `nightlyLearner` AgentDB controller.
194
+ */
195
+ async runAll() {
196
+ const start = Date.now();
197
+ const sweep = await this.sweepExpired();
198
+ const dedup = await this.dedup();
199
+ const compact = await this.compactHnsw();
200
+ return {
201
+ sweep,
202
+ dedup,
203
+ compact,
204
+ totalDurationMs: Date.now() - start,
205
+ };
206
+ }
207
+ }
208
+ export default MemoryConsolidator;
209
+ //# sourceMappingURL=consolidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidator.js","sourceRoot":"","sources":["../src/consolidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Phase 4 — MemoryConsolidator (ADR-125)
3
+ *
4
+ * Verifies:
5
+ * - `sweepExpired()` after 1000 entries with `expiresAt` in the past →
6
+ * `entries.size === 0` AND `hnsw.size === 0` (Acceptance Criterion #4).
7
+ * - `dedup('keep-newest')` collapses content-hash duplicates and keeps the
8
+ * newest by `updatedAt`.
9
+ * - `dedup('keep-oldest')` keeps the oldest by `createdAt`.
10
+ * - `dedup('merge-tags')` unions tags and keeps the newest.
11
+ * - `compactHnsw` rebuilds the index so size matches `entries.size`.
12
+ * - Auto-run timer with a small interval calls `runAll()` at least once.
13
+ * - `nightlyLearner` controller delegates to `MemoryConsolidator.runAll()`
14
+ * when a `MemoryService` is registered.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=consolidator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidator.test.d.ts","sourceRoot":"","sources":["../src/consolidator.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Phase 4 — MemoryConsolidator (ADR-125)
3
+ *
4
+ * Verifies:
5
+ * - `sweepExpired()` after 1000 entries with `expiresAt` in the past →
6
+ * `entries.size === 0` AND `hnsw.size === 0` (Acceptance Criterion #4).
7
+ * - `dedup('keep-newest')` collapses content-hash duplicates and keeps the
8
+ * newest by `updatedAt`.
9
+ * - `dedup('keep-oldest')` keeps the oldest by `createdAt`.
10
+ * - `dedup('merge-tags')` unions tags and keeps the newest.
11
+ * - `compactHnsw` rebuilds the index so size matches `entries.size`.
12
+ * - Auto-run timer with a small interval calls `runAll()` at least once.
13
+ * - `nightlyLearner` controller delegates to `MemoryConsolidator.runAll()`
14
+ * when a `MemoryService` is registered.
15
+ */
16
+ import { describe, it, expect, vi } from 'vitest';
17
+ import { MemoryService } from './index.js';
18
+ import { MemoryConsolidator } from './consolidator.js';
19
+ import { ControllerRegistry } from './controller-registry.js';
20
+ import { createDefaultEntry } from './types.js';
21
+ function randomVec(dim, seed) {
22
+ const out = new Float32Array(dim);
23
+ let s = seed | 0 || 1;
24
+ for (let i = 0; i < dim; i++) {
25
+ s ^= s << 13;
26
+ s ^= s >>> 17;
27
+ s ^= s << 5;
28
+ out[i] = ((s | 0) / 2 ** 31);
29
+ }
30
+ return out;
31
+ }
32
+ async function newService(opts = {}) {
33
+ const svc = new MemoryService({
34
+ dimensions: 8,
35
+ persistenceEnabled: false,
36
+ snapshotInterval: 0,
37
+ ...opts,
38
+ });
39
+ await svc.initialize();
40
+ return svc;
41
+ }
42
+ describe('Phase 4 — MemoryConsolidator.sweepExpired', () => {
43
+ it('Acceptance Criterion #4 — 1000 expired entries → 0 remaining + HNSW emptied', async () => {
44
+ const svc = await newService();
45
+ const consolidator = new MemoryConsolidator(svc);
46
+ const past = Date.now() - 1;
47
+ for (let i = 0; i < 1000; i++) {
48
+ const entry = createDefaultEntry({
49
+ key: `expired-${i}`,
50
+ content: `content-${i}`,
51
+ expiresAt: past,
52
+ });
53
+ entry.embedding = randomVec(8, i + 1);
54
+ await svc.store(entry);
55
+ }
56
+ const adapter = svc.getAdapter();
57
+ expect(adapter.entries.size).toBe(1000);
58
+ expect(adapter.index.size).toBe(1000);
59
+ const result = await consolidator.sweepExpired();
60
+ expect(result.removed).toBe(1000);
61
+ expect(result.remaining).toBe(0);
62
+ expect(result.hnswRemoved).toBe(1000);
63
+ expect(adapter.entries.size).toBe(0);
64
+ expect(adapter.index.size).toBe(0);
65
+ await svc.close();
66
+ });
67
+ it('leaves non-expired entries untouched', async () => {
68
+ const svc = await newService();
69
+ const consolidator = new MemoryConsolidator(svc);
70
+ // 5 expired + 5 fresh
71
+ for (let i = 0; i < 5; i++) {
72
+ const entry = createDefaultEntry({
73
+ key: `e-${i}`,
74
+ content: `e-${i}`,
75
+ expiresAt: Date.now() - 1,
76
+ });
77
+ entry.embedding = randomVec(8, i + 1);
78
+ await svc.store(entry);
79
+ }
80
+ for (let i = 0; i < 5; i++) {
81
+ const entry = createDefaultEntry({ key: `f-${i}`, content: `f-${i}` });
82
+ entry.embedding = randomVec(8, i + 100);
83
+ await svc.store(entry);
84
+ }
85
+ const result = await consolidator.sweepExpired();
86
+ expect(result.removed).toBe(5);
87
+ expect(result.remaining).toBe(5);
88
+ await svc.close();
89
+ });
90
+ });
91
+ describe('Phase 4 — MemoryConsolidator.dedup', () => {
92
+ it('keep-newest: drops 10 duplicates and keeps newest by updatedAt', async () => {
93
+ const svc = await newService();
94
+ const consolidator = new MemoryConsolidator(svc);
95
+ // 40 unique + 10 dupes of the same content as entry 0
96
+ const dupContent = 'duplicate-marker';
97
+ const newestTimestamps = [];
98
+ for (let i = 0; i < 40; i++) {
99
+ const entry = createDefaultEntry({ key: `u-${i}`, content: `unique-${i}` });
100
+ entry.embedding = randomVec(8, i + 1);
101
+ await svc.store(entry);
102
+ }
103
+ // The first dup has the OLDEST updatedAt; the last dup has the NEWEST.
104
+ for (let i = 0; i < 10; i++) {
105
+ const entry = createDefaultEntry({ key: `dup-${i}`, content: dupContent });
106
+ entry.embedding = randomVec(8, i + 500);
107
+ entry.updatedAt = 1_000_000_000 + i; // monotonic, last is newest
108
+ await svc.store(entry);
109
+ newestTimestamps.push(entry.updatedAt);
110
+ }
111
+ const result = await consolidator.dedup('keep-newest');
112
+ expect(result.merged).toBe(9);
113
+ expect(result.groups).toBe(1);
114
+ // Survivor's updatedAt should equal the max of the dup timestamps
115
+ const adapter = svc.getAdapter();
116
+ const survivors = [...adapter.entries.values()].filter((e) => e.content === dupContent);
117
+ expect(survivors.length).toBe(1);
118
+ expect(survivors[0].updatedAt).toBe(Math.max(...newestTimestamps));
119
+ await svc.close();
120
+ });
121
+ it('keep-oldest: keeps the entry with the lowest createdAt', async () => {
122
+ const svc = await newService();
123
+ const consolidator = new MemoryConsolidator(svc);
124
+ const ids = [];
125
+ for (let i = 0; i < 3; i++) {
126
+ const entry = createDefaultEntry({ key: `o-${i}`, content: 'same' });
127
+ entry.embedding = randomVec(8, i + 1);
128
+ entry.createdAt = 1000 + i; // i=0 is oldest
129
+ await svc.store(entry);
130
+ ids.push(entry.id);
131
+ }
132
+ const result = await consolidator.dedup('keep-oldest');
133
+ expect(result.merged).toBe(2);
134
+ const adapter = svc.getAdapter();
135
+ expect(adapter.entries.size).toBe(1);
136
+ expect(adapter.entries.has(ids[0])).toBe(true);
137
+ await svc.close();
138
+ });
139
+ it('merge-tags: unions tag sets across the duplicates and keeps newest', async () => {
140
+ const svc = await newService();
141
+ const consolidator = new MemoryConsolidator(svc);
142
+ for (let i = 0; i < 3; i++) {
143
+ const entry = createDefaultEntry({
144
+ key: `t-${i}`,
145
+ content: 'same',
146
+ tags: [`tag-${i}`, 'common'],
147
+ });
148
+ entry.embedding = randomVec(8, i + 1);
149
+ entry.updatedAt = 1000 + i;
150
+ await svc.store(entry);
151
+ }
152
+ const result = await consolidator.dedup('merge-tags');
153
+ expect(result.merged).toBe(2);
154
+ const adapter = svc.getAdapter();
155
+ const survivors = [...adapter.entries.values()];
156
+ expect(survivors.length).toBe(1);
157
+ const survivor = survivors[0];
158
+ expect(new Set(survivor.tags)).toEqual(new Set(['tag-0', 'tag-1', 'tag-2', 'common']));
159
+ await svc.close();
160
+ });
161
+ });
162
+ describe('Phase 4 — MemoryConsolidator.compactHnsw', () => {
163
+ it('rebuilds the HNSW index so size matches entries.size after sweep', async () => {
164
+ const svc = await newService();
165
+ const consolidator = new MemoryConsolidator(svc);
166
+ // Insert + expire half
167
+ const half = 20;
168
+ for (let i = 0; i < half * 2; i++) {
169
+ const entry = createDefaultEntry({
170
+ key: `c-${i}`,
171
+ content: `c-${i}`,
172
+ expiresAt: i < half ? Date.now() - 1 : undefined,
173
+ });
174
+ entry.embedding = randomVec(8, i + 1);
175
+ await svc.store(entry);
176
+ }
177
+ await consolidator.sweepExpired();
178
+ const result = await consolidator.compactHnsw();
179
+ expect(result.before).toBeGreaterThanOrEqual(half);
180
+ expect(result.after).toBe(half);
181
+ const adapter = svc.getAdapter();
182
+ expect(adapter.index.size).toBe(adapter.entries.size);
183
+ await svc.close();
184
+ });
185
+ });
186
+ describe('Phase 4 — MemoryService auto-run timer', () => {
187
+ it('invokes consolidator.runAll() at the configured interval', async () => {
188
+ const svc = new MemoryService({
189
+ dimensions: 8,
190
+ persistenceEnabled: false,
191
+ snapshotInterval: 0,
192
+ consolidator: { autoRun: true, intervalMs: 50 },
193
+ });
194
+ await svc.initialize();
195
+ // Spy on the lazily-loaded consolidator. getConsolidator() returns a
196
+ // singleton, so swap its runAll for a spy after first construction.
197
+ const consolidator = await svc.getConsolidator();
198
+ const spy = vi.spyOn(consolidator, 'runAll');
199
+ // Wait long enough for at least one tick.
200
+ await new Promise((r) => setTimeout(r, 180));
201
+ expect(spy).toHaveBeenCalled();
202
+ await svc.close();
203
+ });
204
+ it('close() clears the consolidator timer', async () => {
205
+ const svc = new MemoryService({
206
+ dimensions: 8,
207
+ persistenceEnabled: false,
208
+ snapshotInterval: 0,
209
+ consolidator: { autoRun: true, intervalMs: 50 },
210
+ });
211
+ await svc.initialize();
212
+ const consolidator = await svc.getConsolidator();
213
+ const spy = vi.spyOn(consolidator, 'runAll');
214
+ await svc.close();
215
+ await new Promise((r) => setTimeout(r, 150));
216
+ // No new calls after close()
217
+ const callCountAtClose = spy.mock.calls.length;
218
+ await new Promise((r) => setTimeout(r, 150));
219
+ expect(spy.mock.calls.length).toBe(callCountAtClose);
220
+ });
221
+ });
222
+ describe('Phase 4 — nightlyLearner controller delegates to MemoryConsolidator', () => {
223
+ it('returns a wrapper bound to consolidator.runAll when memoryService is registered', async () => {
224
+ const svc = await newService();
225
+ const registry = new ControllerRegistry();
226
+ await registry.initialize({ memoryService: svc });
227
+ const inst = registry.get('nightlyLearner');
228
+ expect(inst).toBeTruthy();
229
+ expect(inst.source).toBe('memory-consolidator');
230
+ expect(typeof inst.runAll).toBe('function');
231
+ const result = await inst.runAll();
232
+ expect(result).toHaveProperty('sweep');
233
+ expect(result).toHaveProperty('dedup');
234
+ expect(result).toHaveProperty('compact');
235
+ await registry.shutdown();
236
+ await svc.close();
237
+ });
238
+ });
239
+ //# sourceMappingURL=consolidator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidator.test.js","sourceRoot":"","sources":["../src/consolidator.test.ts"],"names":[],"mappings":"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"}
@@ -90,6 +90,13 @@ export interface RuntimeConfig {
90
90
  * on this injection point.
91
91
  */
92
92
  agentdb?: unknown;
93
+ /**
94
+ * `MemoryService` (or compatible) used to back the `nightlyLearner`
95
+ * controller. When provided, ADR-125 Phase 4 wraps it with
96
+ * `MemoryConsolidator.runAll()` instead of delegating directly to AgentDB's
97
+ * `NightlyLearner`. Accepts `any` to avoid a circular import.
98
+ */
99
+ memoryService?: any;
93
100
  }
94
101
  /**
95
102
  * Level-based initialization order per ADR-053.
@@ -1 +1 @@
1
- {"version":3,"file":"controller-registry.d.ts","sourceRoot":"","sources":["../src/controller-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller-registry.d.ts","sourceRoot":"","sources":["../src/controller-registry.ts"],"names":[],"mappings":"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"}
@@ -387,7 +387,6 @@ export class ControllerRegistry extends EventEmitter {
387
387
  case 'causalRecall':
388
388
  case 'learningSystem':
389
389
  case 'explainableRecall':
390
- case 'nightlyLearner':
391
390
  case 'graphTransformer':
392
391
  case 'graphAdapter':
393
392
  case 'gnnService':
@@ -397,11 +396,20 @@ export class ControllerRegistry extends EventEmitter {
397
396
  case 'rvfOptimizer':
398
397
  case 'mmrDiversityRanker':
399
398
  return this.agentdb !== null;
399
+ // ADR-125 Phase 4 — nightlyLearner is enabled when EITHER an AgentDB
400
+ // is present (legacy path) OR a MemoryService is registered (new path
401
+ // backed by MemoryConsolidator.runAll).
402
+ case 'nightlyLearner':
403
+ return this.agentdb !== null || !!this.config.memoryService;
400
404
  // SemanticRouter — auto-enable if agentdb available (exported since alpha.10)
401
405
  case 'semanticRouter':
402
406
  return this.agentdb !== null;
403
- // Optional controllers
407
+ // ADR-125 Phase 5 — hybridSearch auto-enables when a MemoryService is
408
+ // registered. Replaces the prior "placeholder, require explicit enable"
409
+ // posture.
404
410
  case 'hybridSearch':
411
+ return !!this.config.memoryService;
412
+ // Optional controllers
405
413
  case 'agentMemoryScope':
406
414
  case 'sonaTrajectory':
407
415
  case 'federatedSession':
@@ -494,9 +502,69 @@ export class ControllerRegistry extends EventEmitter {
494
502
  });
495
503
  return cache;
496
504
  }
497
- case 'hybridSearch':
498
- // BM25 hybrid search — placeholder for future implementation
499
- return null;
505
+ case 'hybridSearch': {
506
+ // ADR-125 Phase 5 — real RRF + MMR hybrid search.
507
+ // Calls semanticSearch() (which degrades gracefully when embedder is
508
+ // unavailable) AND searchKeyword() independently, fuses via RRF, then
509
+ // diversifies via MMR (lambda=0.7).
510
+ const memSvc = this.config.memoryService;
511
+ if (!memSvc)
512
+ return null;
513
+ const adapter = typeof memSvc.getAdapter === 'function' ? memSvc.getAdapter() : null;
514
+ if (!adapter)
515
+ return null;
516
+ const { applyRRF, applyMMR } = await import('./smart-retrieval.js');
517
+ return {
518
+ /**
519
+ * Run a fused hybrid search.
520
+ * @param query Free-form query string.
521
+ * @param opts.limit Final result count (default 10).
522
+ * @param opts.fanOutK Per-arm fanout before fusion (default = limit * 3).
523
+ * @param opts.mmrLambda MMR relevance/diversity balance (default 0.7).
524
+ */
525
+ search: async (query, opts = {}) => {
526
+ const limit = opts.limit ?? 10;
527
+ const fanOutK = opts.fanOutK ?? Math.max(limit * 3, 20);
528
+ const mmrLambda = opts.mmrLambda ?? 0.7;
529
+ // Dense arm — may internally fall back to keyword if embedder is
530
+ // missing, but that's still a valid signal to fuse.
531
+ let dense = [];
532
+ try {
533
+ dense = await adapter.semanticSearch(query, fanOutK);
534
+ }
535
+ catch {
536
+ dense = [];
537
+ }
538
+ // Sparse arm — FTS5 / keyword search.
539
+ let sparse = [];
540
+ try {
541
+ sparse = await adapter.searchKeyword(query, { k: fanOutK });
542
+ }
543
+ catch {
544
+ sparse = [];
545
+ }
546
+ // Adapt SearchResult[] → SearchCandidate[] expected by RRF
547
+ const toCands = (results) => results.map((r) => ({
548
+ id: r.entry.id,
549
+ key: r.entry.key,
550
+ content: r.entry.content,
551
+ namespace: r.entry.namespace,
552
+ metadata: r.entry.metadata,
553
+ createdAt: r.entry.createdAt,
554
+ updatedAt: r.entry.updatedAt,
555
+ score: r.score,
556
+ _entry: r.entry,
557
+ }));
558
+ const fused = applyRRF([toCands(dense), toCands(sparse)], 60);
559
+ const diverse = applyMMR(fused, mmrLambda, limit);
560
+ return diverse.map((s) => ({
561
+ entry: s.candidate._entry,
562
+ score: s.score,
563
+ }));
564
+ },
565
+ source: 'hybrid-rrf-mmr',
566
+ };
567
+ }
500
568
  case 'agentMemoryScope':
501
569
  // Agent memory scope — placeholder, activated when explicitly enabled
502
570
  return null;
@@ -646,6 +714,25 @@ export class ControllerRegistry extends EventEmitter {
646
714
  }
647
715
  }
648
716
  case 'nightlyLearner': {
717
+ // ADR-125 Phase 4 — prefer the MemoryConsolidator when a
718
+ // MemoryService is registered. The consolidator's `runAll()` is the
719
+ // documented entry point for sweep + dedup + compact and replaces the
720
+ // thin delegate to AgentDB's NightlyLearner.
721
+ const memSvc = this.config.memoryService;
722
+ if (memSvc && typeof memSvc.getConsolidator === 'function') {
723
+ try {
724
+ const consolidator = await memSvc.getConsolidator();
725
+ return {
726
+ run: () => consolidator.runAll(),
727
+ runAll: () => consolidator.runAll(),
728
+ sweepExpired: () => consolidator.sweepExpired(),
729
+ dedup: (s) => consolidator.dedup(s),
730
+ compactHnsw: () => consolidator.compactHnsw(),
731
+ source: 'memory-consolidator',
732
+ };
733
+ }
734
+ catch { /* fall through to AgentDB */ }
735
+ }
649
736
  if (!this.agentdb)
650
737
  return null;
651
738
  try {