@lumenflow/memory 3.8.7 → 3.9.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.
@@ -0,0 +1,232 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { afterEach, describe, expect, it } from 'vitest';
4
+ import fs from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { loadSignals } from '../mem-signal-core.js';
8
+ import { createControlPlaneSyncAdapter, DEFAULT_CONTROL_PLANE_SYNC_STATE_PATH, } from '../control-plane-sync-adapter.js';
9
+ const SIGNALS_FILE = path.join('.lumenflow', 'memory', 'signals.jsonl');
10
+ const MEMORY_FILE = path.join('.lumenflow', 'memory', 'memory.jsonl');
11
+ const WORKSPACE_ID = 'workspace-test';
12
+ const SESSION_ID = 'session-test';
13
+ async function writeJsonl(filePath, records) {
14
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
15
+ const content = records.map((record) => JSON.stringify(record)).join('\n');
16
+ await fs.writeFile(filePath, `${content}${content ? '\n' : ''}`, 'utf-8');
17
+ }
18
+ async function readSyncState(baseDir) {
19
+ const statePath = path.join(baseDir, DEFAULT_CONTROL_PLANE_SYNC_STATE_PATH);
20
+ const raw = await fs.readFile(statePath, 'utf-8');
21
+ return JSON.parse(raw);
22
+ }
23
+ describe('control-plane sync adapter (WU-2152)', () => {
24
+ const tempRoots = [];
25
+ afterEach(async () => {
26
+ await Promise.all(tempRoots.map((root) => fs.rm(root, { recursive: true, force: true })));
27
+ tempRoots.length = 0;
28
+ });
29
+ it('pushes local-only signals and ignores origin:remote entries', async () => {
30
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'control-plane-sync-adapter-'));
31
+ tempRoots.push(root);
32
+ await writeJsonl(path.join(root, SIGNALS_FILE), [
33
+ {
34
+ id: 'sig-local01',
35
+ message: 'local signal',
36
+ created_at: '2026-03-02T00:00:00.000Z',
37
+ read: false,
38
+ wu_id: 'WU-2152',
39
+ type: 'handoff',
40
+ },
41
+ {
42
+ id: 'sig-remote01',
43
+ message: 'remote signal',
44
+ created_at: '2026-03-02T00:00:01.000Z',
45
+ read: false,
46
+ wu_id: 'WU-2152',
47
+ origin: 'remote',
48
+ },
49
+ ]);
50
+ const pushInputs = [];
51
+ const adapter = createControlPlaneSyncAdapter({
52
+ baseDir: root,
53
+ workspaceId: WORKSPACE_ID,
54
+ sessionId: SESSION_ID,
55
+ signalPort: {
56
+ async pushSignals(input) {
57
+ pushInputs.push(input.signals);
58
+ return { accepted: input.signals.length };
59
+ },
60
+ async pullSignals() {
61
+ return { signals: [] };
62
+ },
63
+ },
64
+ memoryPort: {
65
+ async syncMemory() {
66
+ return { pushed: 0, pulled: 0, conflicts: [] };
67
+ },
68
+ },
69
+ });
70
+ const result = await adapter.pushLocalSignals();
71
+ expect(result.pushed).toBe(1);
72
+ expect(pushInputs).toHaveLength(1);
73
+ expect(pushInputs[0]).toEqual([
74
+ expect.objectContaining({
75
+ id: 'sig-local01',
76
+ kind: 'handoff',
77
+ origin: 'local',
78
+ }),
79
+ ]);
80
+ const syncState = await readSyncState(root);
81
+ expect(syncState.lastPushedSignalId).toBe('sig-local01');
82
+ });
83
+ it('pulls remote signals to local JSONL and prevents re-push echo loops', async () => {
84
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'control-plane-sync-adapter-'));
85
+ tempRoots.push(root);
86
+ const pushedSignals = [];
87
+ const adapter = createControlPlaneSyncAdapter({
88
+ baseDir: root,
89
+ workspaceId: WORKSPACE_ID,
90
+ sessionId: SESSION_ID,
91
+ signalPort: {
92
+ async pushSignals(input) {
93
+ pushedSignals.push(input.signals);
94
+ return { accepted: input.signals.length };
95
+ },
96
+ async pullSignals() {
97
+ return {
98
+ signals: [
99
+ {
100
+ id: 'sig-remote-100',
101
+ kind: 'handoff',
102
+ timestamp: '2026-03-02T00:10:00.000Z',
103
+ payload: {
104
+ message: 'remote handoff',
105
+ wu_id: 'WU-2152',
106
+ lane: 'Framework: Memory',
107
+ },
108
+ origin: 'remote',
109
+ source_agent_id: 'agent-remote',
110
+ },
111
+ ],
112
+ next_cursor: 'cursor-100',
113
+ };
114
+ },
115
+ },
116
+ memoryPort: {
117
+ async syncMemory() {
118
+ return { pushed: 0, pulled: 0, conflicts: [] };
119
+ },
120
+ },
121
+ });
122
+ const pullResult = await adapter.pullSignals();
123
+ expect(pullResult.pulled).toBe(1);
124
+ const localSignals = await loadSignals(root, { wuId: 'WU-2152' });
125
+ expect(localSignals).toHaveLength(1);
126
+ expect(localSignals[0]).toEqual(expect.objectContaining({
127
+ message: 'remote handoff',
128
+ origin: 'remote',
129
+ remote_id: 'sig-remote-100',
130
+ }));
131
+ const pushResult = await adapter.pushLocalSignals();
132
+ expect(pushResult.pushed).toBe(0);
133
+ expect(pushedSignals).toHaveLength(0);
134
+ const syncState = await readSyncState(root);
135
+ expect(syncState.pullCursor).toBe('cursor-100');
136
+ });
137
+ it('syncs only project lifecycle memory nodes', async () => {
138
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'control-plane-sync-adapter-'));
139
+ tempRoots.push(root);
140
+ await writeJsonl(path.join(root, MEMORY_FILE), [
141
+ {
142
+ id: 'mem-p001',
143
+ type: 'note',
144
+ lifecycle: 'project',
145
+ content: 'project memory',
146
+ created_at: '2026-03-02T00:00:00.000Z',
147
+ },
148
+ {
149
+ id: 'mem-w001',
150
+ type: 'note',
151
+ lifecycle: 'wu',
152
+ content: 'wu memory',
153
+ created_at: '2026-03-02T00:00:01.000Z',
154
+ },
155
+ ]);
156
+ let capturedLocalRecords = [];
157
+ const adapter = createControlPlaneSyncAdapter({
158
+ baseDir: root,
159
+ workspaceId: WORKSPACE_ID,
160
+ sessionId: SESSION_ID,
161
+ signalPort: {
162
+ async pushSignals() {
163
+ return { accepted: 0 };
164
+ },
165
+ async pullSignals() {
166
+ return { signals: [] };
167
+ },
168
+ },
169
+ memoryPort: {
170
+ async syncMemory(input) {
171
+ capturedLocalRecords = input.local_records.map((record) => ({
172
+ id: record.id,
173
+ namespace: record.namespace,
174
+ key: record.key,
175
+ }));
176
+ return { pushed: input.local_records.length, pulled: 0, conflicts: [] };
177
+ },
178
+ },
179
+ });
180
+ const result = await adapter.syncProjectMemory();
181
+ expect(result.pushed).toBe(1);
182
+ expect(capturedLocalRecords).toEqual([
183
+ {
184
+ id: 'mem-p001',
185
+ namespace: 'project',
186
+ key: 'mem-p001',
187
+ },
188
+ ]);
189
+ });
190
+ it('opens circuit breaker after 3 consecutive remote failures', async () => {
191
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'control-plane-sync-adapter-'));
192
+ tempRoots.push(root);
193
+ await writeJsonl(path.join(root, SIGNALS_FILE), [
194
+ {
195
+ id: 'sig-local-fail',
196
+ message: 'local signal',
197
+ created_at: '2026-03-02T00:00:00.000Z',
198
+ read: false,
199
+ },
200
+ ]);
201
+ const nowMs = 1_000;
202
+ let remoteAttempts = 0;
203
+ const adapter = createControlPlaneSyncAdapter({
204
+ baseDir: root,
205
+ workspaceId: WORKSPACE_ID,
206
+ sessionId: SESSION_ID,
207
+ now: () => nowMs,
208
+ signalPort: {
209
+ async pushSignals() {
210
+ remoteAttempts += 1;
211
+ throw new Error('remote unavailable');
212
+ },
213
+ async pullSignals() {
214
+ return { signals: [] };
215
+ },
216
+ },
217
+ memoryPort: {
218
+ async syncMemory() {
219
+ return { pushed: 0, pulled: 0, conflicts: [] };
220
+ },
221
+ },
222
+ });
223
+ await adapter.pushLocalSignals();
224
+ await adapter.pushLocalSignals();
225
+ await adapter.pushLocalSignals();
226
+ expect(remoteAttempts).toBe(3);
227
+ const result = await adapter.pushLocalSignals();
228
+ expect(result.skippedReason).toBe('circuit-open');
229
+ expect(remoteAttempts).toBe(3);
230
+ });
231
+ });
232
+ //# sourceMappingURL=control-plane-sync-adapter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-plane-sync-adapter.test.js","sourceRoot":"","sources":["../../src/__tests__/control-plane-sync-adapter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { afterEach, describe, expect, it } from 'vitest';
4
+ import fs from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { promoteProjectMemory } from '../memory-promotion.js';
8
+ const MEMORY_RELATIVE_PATH = path.join('.lumenflow', 'memory', 'memory.jsonl');
9
+ function fixtureNode(id, lifecycle, overrides = {}) {
10
+ return {
11
+ id,
12
+ type: 'note',
13
+ lifecycle,
14
+ content: `node-${id}`,
15
+ created_at: '2026-03-01T12:00:00.000Z',
16
+ ...overrides,
17
+ };
18
+ }
19
+ async function writeMemory(baseDir, nodes) {
20
+ const memoryFile = path.join(baseDir, MEMORY_RELATIVE_PATH);
21
+ await fs.mkdir(path.dirname(memoryFile), { recursive: true });
22
+ const content = nodes.map((node) => JSON.stringify(node)).join('\n');
23
+ await fs.writeFile(memoryFile, `${content}${content ? '\n' : ''}`, 'utf-8');
24
+ }
25
+ async function readMemory(baseDir) {
26
+ const memoryFile = path.join(baseDir, MEMORY_RELATIVE_PATH);
27
+ try {
28
+ const content = await fs.readFile(memoryFile, 'utf-8');
29
+ return content
30
+ .split('\n')
31
+ .filter((line) => line.trim().length > 0)
32
+ .map((line) => JSON.parse(line));
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ }
38
+ describe('promoteProjectMemory (WU-2145)', () => {
39
+ const tempRoots = [];
40
+ afterEach(async () => {
41
+ await Promise.all(tempRoots.map((root) => fs.rm(root, { recursive: true, force: true })));
42
+ tempRoots.length = 0;
43
+ });
44
+ it('promotes only project lifecycle nodes from worktree memory to main memory', async () => {
45
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memory-promotion-'));
46
+ tempRoots.push(root);
47
+ const mainDir = path.join(root, 'main');
48
+ const worktreeDir = path.join(root, 'worktree');
49
+ await writeMemory(mainDir, [fixtureNode('mem-mai1', 'project')]);
50
+ await writeMemory(worktreeDir, [
51
+ fixtureNode('mem-pro1', 'project'),
52
+ fixtureNode('mem-ses1', 'session'),
53
+ fixtureNode('mem-wu01', 'wu'),
54
+ ]);
55
+ const result = await promoteProjectMemory(worktreeDir, mainDir);
56
+ expect(result.promotedCount).toBe(1);
57
+ expect(result.promotedNodeIds).toEqual(['mem-pro1']);
58
+ const mainMemory = await readMemory(mainDir);
59
+ const ids = mainMemory.map((node) => node.id);
60
+ expect(ids).toContain('mem-mai1');
61
+ expect(ids).toContain('mem-pro1');
62
+ expect(ids).not.toContain('mem-ses1');
63
+ expect(ids).not.toContain('mem-wu01');
64
+ });
65
+ it('is a no-op when no project nodes exist in the worktree memory', async () => {
66
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memory-promotion-'));
67
+ tempRoots.push(root);
68
+ const mainDir = path.join(root, 'main');
69
+ const worktreeDir = path.join(root, 'worktree');
70
+ await writeMemory(mainDir, []);
71
+ await writeMemory(worktreeDir, [fixtureNode('mem-sess', 'session')]);
72
+ const result = await promoteProjectMemory(worktreeDir, mainDir);
73
+ expect(result.promotedCount).toBe(0);
74
+ expect(result.promotedNodeIds).toEqual([]);
75
+ const mainMemory = await readMemory(mainDir);
76
+ expect(mainMemory).toHaveLength(0);
77
+ });
78
+ it('skips project nodes that already exist in main memory (idempotent)', async () => {
79
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memory-promotion-'));
80
+ tempRoots.push(root);
81
+ const mainDir = path.join(root, 'main');
82
+ const worktreeDir = path.join(root, 'worktree');
83
+ await writeMemory(mainDir, [fixtureNode('mem-proj', 'project')]);
84
+ await writeMemory(worktreeDir, [fixtureNode('mem-proj', 'project')]);
85
+ const result = await promoteProjectMemory(worktreeDir, mainDir);
86
+ expect(result.promotedCount).toBe(0);
87
+ expect(result.promotedNodeIds).toEqual([]);
88
+ const mainMemory = await readMemory(mainDir);
89
+ expect(mainMemory.filter((node) => node.id === 'mem-proj')).toHaveLength(1);
90
+ });
91
+ });
92
+ //# sourceMappingURL=memory-promotion.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-promotion.test.js","sourceRoot":"","sources":["../../src/__tests__/memory-promotion.test.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAW9D,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAE/E,SAAS,WAAW,CAClB,EAAU,EACV,SAAyC,EACzC,YAAwC,EAAE;IAE1C,OAAO;QACL,EAAE;QACF,IAAI,EAAE,MAAM;QACZ,SAAS;QACT,OAAO,EAAE,QAAQ,EAAE,EAAE;QACrB,UAAU,EAAE,0BAA0B;QACtC,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,KAA0B;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAC5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,OAAO;aACX,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aACxC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAsB,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1F,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC3E,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEhD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,CAAC,WAAW,EAAE;YAC7B,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC;YAClC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC;YAClC,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC;SAC9B,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAEhE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAErD,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC3E,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEhD,MAAM,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,WAAW,CAAC,WAAW,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAEhE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAE3C,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC3E,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEhD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,CAAC,WAAW,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAEhE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAE3C,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,79 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { afterEach, describe, expect, it } from 'vitest';
4
+ import fs from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { createSignal, loadSignals } from '../mem-signal-core.js';
8
+ const SIGNALS_RELATIVE_PATH = path.join('.lumenflow', 'memory', 'signals.jsonl');
9
+ async function writeSignals(baseDir, records) {
10
+ const signalsPath = path.join(baseDir, SIGNALS_RELATIVE_PATH);
11
+ await fs.mkdir(path.dirname(signalsPath), { recursive: true });
12
+ const lines = records.map((record) => JSON.stringify(record)).join('\n');
13
+ await fs.writeFile(signalsPath, `${lines}${lines ? '\n' : ''}`, 'utf-8');
14
+ }
15
+ describe('signal contract enforcement (WU-2291)', () => {
16
+ const tempRoots = [];
17
+ afterEach(async () => {
18
+ await Promise.all(tempRoots.map((root) => fs.rm(root, { recursive: true, force: true })));
19
+ tempRoots.length = 0;
20
+ });
21
+ it('fails explicitly on legacy signals that omit strict metadata fields', async () => {
22
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'signal-schema-extension-'));
23
+ tempRoots.push(root);
24
+ await writeSignals(root, [
25
+ {
26
+ id: 'sig-legacy1',
27
+ message: 'legacy signal',
28
+ created_at: '2026-03-01T12:00:00.000Z',
29
+ read: false,
30
+ wu_id: 'WU-2146',
31
+ },
32
+ ]);
33
+ await expect(loadSignals(root, { wuId: 'WU-2146' })).rejects.toThrow(/legacy signal record is not supported/i);
34
+ });
35
+ it('writes canonical strict metadata defaults for local signals', async () => {
36
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'signal-schema-extension-'));
37
+ tempRoots.push(root);
38
+ const created = await createSignal(root, {
39
+ message: 'local signal without explicit metadata',
40
+ wuId: 'WU-2146',
41
+ });
42
+ expect(created.signal.type).toBe('coordination');
43
+ expect(created.signal.sender).toBe('system');
44
+ expect(created.signal.origin).toBe('local');
45
+ expect(created.signal.remote_id).toBe(created.signal.id);
46
+ const loaded = await loadSignals(root, { wuId: 'WU-2146' });
47
+ expect(loaded).toHaveLength(1);
48
+ expect(loaded[0]?.type).toBe('coordination');
49
+ expect(loaded[0]?.sender).toBe('system');
50
+ expect(loaded[0]?.origin).toBe('local');
51
+ expect(loaded[0]?.remote_id).toBe(loaded[0]?.id);
52
+ });
53
+ it('round-trips explicit metadata fields through create/load JSONL flow', async () => {
54
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'signal-schema-extension-'));
55
+ tempRoots.push(root);
56
+ const created = await createSignal(root, {
57
+ message: 'handoff to remote agent',
58
+ wuId: 'WU-2146',
59
+ type: 'handoff',
60
+ sender: 'agent-alpha',
61
+ target_agent: 'agent-beta',
62
+ origin: 'mcp',
63
+ remote_id: 'remote-123',
64
+ });
65
+ expect(created.signal.type).toBe('handoff');
66
+ expect(created.signal.sender).toBe('agent-alpha');
67
+ expect(created.signal.target_agent).toBe('agent-beta');
68
+ expect(created.signal.origin).toBe('mcp');
69
+ expect(created.signal.remote_id).toBe('remote-123');
70
+ const loaded = await loadSignals(root, { wuId: 'WU-2146' });
71
+ expect(loaded).toHaveLength(1);
72
+ expect(loaded[0]?.type).toBe('handoff');
73
+ expect(loaded[0]?.sender).toBe('agent-alpha');
74
+ expect(loaded[0]?.target_agent).toBe('agent-beta');
75
+ expect(loaded[0]?.origin).toBe('mcp');
76
+ expect(loaded[0]?.remote_id).toBe('remote-123');
77
+ });
78
+ });
79
+ //# sourceMappingURL=signal-schema-extension.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-schema-extension.test.js","sourceRoot":"","sources":["../../src/__tests__/signal-schema-extension.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,267 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { loadSignals, createSignal } from './mem-signal-core.js';
6
+ import { loadMemory } from './memory-store.js';
7
+ const REMOTE_TIMEOUT_MS = 200;
8
+ const CIRCUIT_FAILURE_THRESHOLD = 3;
9
+ const CIRCUIT_OPEN_MS = 60_000;
10
+ const SKIPPED_CIRCUIT_OPEN = 'circuit-open';
11
+ export const DEFAULT_CONTROL_PLANE_SYNC_STATE_PATH = path.join('.lumenflow', 'state', 'control-plane-sync.json');
12
+ const DEFAULT_SYNC_STATE = {
13
+ remoteFailureCount: 0,
14
+ circuitOpenUntilMs: 0,
15
+ };
16
+ function asString(value) {
17
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
18
+ }
19
+ function buildSignalPayload(signal) {
20
+ return {
21
+ message: signal.message,
22
+ wu_id: signal.wu_id,
23
+ lane: signal.lane,
24
+ sender: signal.sender,
25
+ target_agent: signal.target_agent,
26
+ };
27
+ }
28
+ function toRemoteSignal(signal) {
29
+ return {
30
+ id: signal.id,
31
+ kind: signal.type ?? 'signal',
32
+ timestamp: signal.created_at,
33
+ payload: buildSignalPayload(signal),
34
+ origin: 'local',
35
+ source_agent_id: signal.sender,
36
+ };
37
+ }
38
+ function extractMessage(signal) {
39
+ const payloadMessage = signal.payload.message;
40
+ if (typeof payloadMessage === 'string' && payloadMessage.trim().length > 0) {
41
+ return payloadMessage;
42
+ }
43
+ return `[${signal.kind}] remote signal`;
44
+ }
45
+ async function runWithTimeout(promise, timeoutMs) {
46
+ let timer;
47
+ const timeoutPromise = new Promise((_, reject) => {
48
+ timer = setTimeout(() => reject(new Error('Remote control-plane call timed out')), timeoutMs);
49
+ });
50
+ try {
51
+ return await Promise.race([promise, timeoutPromise]);
52
+ }
53
+ finally {
54
+ if (timer) {
55
+ clearTimeout(timer);
56
+ }
57
+ }
58
+ }
59
+ function isCircuitOpen(state, nowMs) {
60
+ return state.circuitOpenUntilMs > nowMs;
61
+ }
62
+ function markRemoteFailure(state, options, nowMs) {
63
+ const nextFailureCount = state.remoteFailureCount + 1;
64
+ if (nextFailureCount >= options.circuitFailureThreshold) {
65
+ return {
66
+ ...state,
67
+ remoteFailureCount: 0,
68
+ circuitOpenUntilMs: nowMs + options.circuitOpenMs,
69
+ };
70
+ }
71
+ return {
72
+ ...state,
73
+ remoteFailureCount: nextFailureCount,
74
+ };
75
+ }
76
+ function clearRemoteFailures(state) {
77
+ return {
78
+ ...state,
79
+ remoteFailureCount: 0,
80
+ circuitOpenUntilMs: 0,
81
+ };
82
+ }
83
+ async function readSyncState(baseDir) {
84
+ const syncStatePath = path.join(baseDir, DEFAULT_CONTROL_PLANE_SYNC_STATE_PATH);
85
+ try {
86
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- path is rooted to baseDir + constant
87
+ const raw = await fs.readFile(syncStatePath, 'utf-8');
88
+ const parsed = JSON.parse(raw);
89
+ return {
90
+ ...DEFAULT_SYNC_STATE,
91
+ ...parsed,
92
+ remoteFailureCount: parsed.remoteFailureCount ?? 0,
93
+ circuitOpenUntilMs: parsed.circuitOpenUntilMs ?? 0,
94
+ };
95
+ }
96
+ catch (error) {
97
+ const err = error;
98
+ if (err.code === 'ENOENT') {
99
+ return { ...DEFAULT_SYNC_STATE };
100
+ }
101
+ throw error;
102
+ }
103
+ }
104
+ async function writeSyncState(baseDir, state) {
105
+ const syncStatePath = path.join(baseDir, DEFAULT_CONTROL_PLANE_SYNC_STATE_PATH);
106
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- path is rooted to baseDir + constant
107
+ await fs.mkdir(path.dirname(syncStatePath), { recursive: true });
108
+ const serializable = {
109
+ lastPushedSignalId: state.lastPushedSignalId,
110
+ pullCursor: state.pullCursor,
111
+ memoryCursor: state.memoryCursor,
112
+ remoteFailureCount: state.remoteFailureCount,
113
+ circuitOpenUntilMs: state.circuitOpenUntilMs,
114
+ };
115
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- path is rooted to baseDir + constant
116
+ await fs.writeFile(syncStatePath, `${JSON.stringify(serializable, null, 2)}\n`, 'utf-8');
117
+ }
118
+ function getSignalsAfterWatermark(signals, lastPushedSignalId) {
119
+ if (!lastPushedSignalId) {
120
+ return signals;
121
+ }
122
+ const markerIndex = signals.findIndex((signal) => signal.id === lastPushedSignalId);
123
+ if (markerIndex < 0) {
124
+ return signals;
125
+ }
126
+ return signals.slice(markerIndex + 1);
127
+ }
128
+ function toProjectMemoryRecords(memory) {
129
+ return memory.nodes
130
+ .filter((node) => node.lifecycle === 'project')
131
+ .map((node) => ({
132
+ id: node.id,
133
+ namespace: 'project',
134
+ key: node.id,
135
+ value: {
136
+ type: node.type,
137
+ lifecycle: node.lifecycle,
138
+ content: node.content,
139
+ created_at: node.created_at,
140
+ updated_at: node.updated_at,
141
+ wu_id: node.wu_id,
142
+ metadata: node.metadata,
143
+ tags: node.tags,
144
+ },
145
+ updated_at: node.updated_at ?? node.created_at,
146
+ origin: 'local',
147
+ }));
148
+ }
149
+ export function createControlPlaneSyncAdapter(options) {
150
+ const now = options.now ?? Date.now;
151
+ const remoteTimeoutMs = options.remoteTimeoutMs ?? REMOTE_TIMEOUT_MS;
152
+ const circuitOpenMs = options.circuitOpenMs ?? CIRCUIT_OPEN_MS;
153
+ const circuitFailureThreshold = options.circuitFailureThreshold ?? CIRCUIT_FAILURE_THRESHOLD;
154
+ const circuitConfig = {
155
+ circuitFailureThreshold,
156
+ circuitOpenMs,
157
+ };
158
+ async function executeRemote(action) {
159
+ const state = await readSyncState(options.baseDir);
160
+ const nowMs = now();
161
+ if (isCircuitOpen(state, nowMs)) {
162
+ return { ok: false, state };
163
+ }
164
+ try {
165
+ const result = await action(state);
166
+ const nextState = clearRemoteFailures(state);
167
+ await writeSyncState(options.baseDir, nextState);
168
+ return { ok: true, result, state: nextState };
169
+ }
170
+ catch {
171
+ const nextState = markRemoteFailure(state, circuitConfig, nowMs);
172
+ await writeSyncState(options.baseDir, nextState);
173
+ return { ok: false, state: nextState };
174
+ }
175
+ }
176
+ return {
177
+ async pushLocalSignals() {
178
+ const state = await readSyncState(options.baseDir);
179
+ if (isCircuitOpen(state, now())) {
180
+ return { pushed: 0, skippedReason: SKIPPED_CIRCUIT_OPEN };
181
+ }
182
+ const allSignals = await loadSignals(options.baseDir);
183
+ const afterWatermark = getSignalsAfterWatermark(allSignals, state.lastPushedSignalId);
184
+ const localSignals = afterWatermark.filter((signal) => signal.origin !== 'remote');
185
+ if (localSignals.length === 0) {
186
+ return { pushed: 0 };
187
+ }
188
+ const remoteSignals = localSignals.map(toRemoteSignal);
189
+ const remoteResult = await executeRemote(async () => runWithTimeout(options.signalPort.pushSignals({
190
+ workspace_id: options.workspaceId,
191
+ session_id: options.sessionId,
192
+ signals: remoteSignals,
193
+ }), remoteTimeoutMs));
194
+ if (!remoteResult.ok) {
195
+ const refreshed = await readSyncState(options.baseDir);
196
+ if (isCircuitOpen(refreshed, now())) {
197
+ return { pushed: 0, skippedReason: SKIPPED_CIRCUIT_OPEN };
198
+ }
199
+ return { pushed: 0, skippedReason: 'remote-error' };
200
+ }
201
+ const currentState = await readSyncState(options.baseDir);
202
+ const nextState = {
203
+ ...currentState,
204
+ lastPushedSignalId: localSignals[localSignals.length - 1]?.id,
205
+ };
206
+ await writeSyncState(options.baseDir, nextState);
207
+ return { pushed: remoteResult.result.accepted };
208
+ },
209
+ async pullSignals() {
210
+ const remoteResult = await executeRemote(async (state) => runWithTimeout(options.signalPort.pullSignals({
211
+ workspace_id: options.workspaceId,
212
+ session_id: options.sessionId,
213
+ cursor: state.pullCursor,
214
+ }), remoteTimeoutMs));
215
+ if (!remoteResult.ok) {
216
+ const refreshed = await readSyncState(options.baseDir);
217
+ if (isCircuitOpen(refreshed, now())) {
218
+ return { pulled: 0, skippedReason: SKIPPED_CIRCUIT_OPEN };
219
+ }
220
+ return { pulled: 0, skippedReason: 'remote-error' };
221
+ }
222
+ const pullResponse = remoteResult.result;
223
+ for (const signal of pullResponse.signals) {
224
+ await createSignal(options.baseDir, {
225
+ message: extractMessage(signal),
226
+ wuId: asString(signal.payload.wu_id),
227
+ lane: asString(signal.payload.lane),
228
+ type: signal.kind,
229
+ sender: signal.source_agent_id,
230
+ target_agent: asString(signal.payload.target_agent),
231
+ origin: 'remote',
232
+ remote_id: signal.id,
233
+ });
234
+ }
235
+ const currentState = await readSyncState(options.baseDir);
236
+ const nextState = {
237
+ ...currentState,
238
+ pullCursor: pullResponse.next_cursor ?? currentState.pullCursor,
239
+ };
240
+ await writeSyncState(options.baseDir, nextState);
241
+ return { pulled: pullResponse.signals.length };
242
+ },
243
+ async syncProjectMemory() {
244
+ const state = await readSyncState(options.baseDir);
245
+ const indexedMemory = await loadMemory(path.join(options.baseDir, '.lumenflow', 'memory'));
246
+ const localRecords = toProjectMemoryRecords(indexedMemory);
247
+ const remoteResult = await executeRemote(() => runWithTimeout(options.memoryPort.syncMemory({
248
+ workspace_id: options.workspaceId,
249
+ session_id: options.sessionId,
250
+ direction: 'bidirectional',
251
+ local_records: localRecords,
252
+ cursor: state.memoryCursor,
253
+ }), remoteTimeoutMs));
254
+ if (!remoteResult.ok) {
255
+ return { pushed: 0, pulled: 0, conflicts: [] };
256
+ }
257
+ const currentState = await readSyncState(options.baseDir);
258
+ const nextState = {
259
+ ...currentState,
260
+ memoryCursor: remoteResult.result.next_cursor ?? currentState.memoryCursor,
261
+ };
262
+ await writeSyncState(options.baseDir, nextState);
263
+ return remoteResult.result;
264
+ },
265
+ };
266
+ }
267
+ //# sourceMappingURL=control-plane-sync-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-plane-sync-adapter.js","sourceRoot":"","sources":["../src/control-plane-sync-adapter.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAe,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAsB,MAAM,mBAAmB,CAAC;AAEnE,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,yBAAyB,GAAG,CAAC,CAAC;AACpC,MAAM,eAAe,GAAG,MAAM,CAAC;AAC/B,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAoE5C,MAAM,CAAC,MAAM,qCAAqC,GAAG,IAAI,CAAC,IAAI,CAC5D,YAAY,EACZ,OAAO,EACP,yBAAyB,CAC1B,CAAC;AA+CF,MAAM,kBAAkB,GAAc;IACpC,kBAAkB,EAAE,CAAC;IACrB,kBAAkB,EAAE,CAAC;CACtB,CAAC;AAEF,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3E,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,QAAQ;QAC7B,SAAS,EAAE,MAAM,CAAC,UAAU;QAC5B,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC;QACnC,MAAM,EAAE,OAAO;QACf,eAAe,EAAE,MAAM,CAAC,MAAM;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,MAAmB;IACzC,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;IAC9C,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3E,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,IAAI,iBAAiB,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,cAAc,CAAI,OAAmB,EAAE,SAAiB;IACrE,IAAI,KAAiC,CAAC;IACtC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QACtD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IACvD,CAAC;YAAS,CAAC;QACT,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAgB,EAAE,KAAa;IACpD,OAAO,KAAK,CAAC,kBAAkB,GAAG,KAAK,CAAC;AAC1C,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAgB,EAChB,OAEC,EACD,KAAa;IAEb,MAAM,gBAAgB,GAAG,KAAK,CAAC,kBAAkB,GAAG,CAAC,CAAC;IACtD,IAAI,gBAAgB,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;QACxD,OAAO;YACL,GAAG,KAAK;YACR,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK,GAAG,OAAO,CAAC,aAAa;SAClD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,GAAG,KAAK;QACR,kBAAkB,EAAE,gBAAgB;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAgB;IAC3C,OAAO;QACL,GAAG,KAAK;QACR,kBAAkB,EAAE,CAAC;QACrB,kBAAkB,EAAE,CAAC;KACtB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,OAAe;IAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qCAAqC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,2GAA2G;QAC3G,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,OAAO;YACL,GAAG,kBAAkB;YACrB,GAAG,MAAM;YACT,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,CAAC;YAClD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,CAAC;SACnD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAA8B,CAAC;QAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,EAAE,GAAG,kBAAkB,EAAE,CAAC;QACnC,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,KAAgB;IAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qCAAqC,CAAC,CAAC;IAChF,2GAA2G;IAC3G,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG;QACnB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;KAC7C,CAAC;IACF,2GAA2G;IAC3G,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,wBAAwB,CAAC,OAAiB,EAAE,kBAA2B;IAC9E,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,kBAAkB,CAAC,CAAC;IACpF,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAqB;IACnD,OAAO,MAAM,CAAC,KAAK;SAChB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC;SAC9C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACd,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,SAAS,EAAE,SAAS;QACpB,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,KAAK,EAAE;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB;QACD,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU;QAC9C,MAAM,EAAE,OAAO;KAChB,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,OAAuC;IAEvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,iBAAiB,CAAC;IACrE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,eAAe,CAAC;IAC/D,MAAM,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,IAAI,yBAAyB,CAAC;IAE7F,MAAM,aAAa,GAAG;QACpB,uBAAuB;QACvB,aAAa;KACd,CAAC;IAEF,KAAK,UAAU,aAAa,CAC1B,MAAwC;QAExC,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC;QACpB,IAAI,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACjD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;YACjE,MAAM,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACjD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,gBAAgB;YACpB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;gBAChC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC;YAC5D,CAAC;YAED,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,cAAc,GAAG,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;YACtF,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;YACnF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YACvB,CAAC;YAED,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAEvD,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,KAAK,IAAI,EAAE,CAClD,cAAc,CACZ,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC;gBAC7B,YAAY,EAAE,OAAO,CAAC,WAAW;gBACjC,UAAU,EAAE,OAAO,CAAC,SAAS;gBAC7B,OAAO,EAAE,aAAa;aACvB,CAAC,EACF,eAAe,CAChB,CACF,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;gBACrB,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACvD,IAAI,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;oBACpC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC;gBAC5D,CAAC;gBACD,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;YACtD,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,SAAS,GAAc;gBAC3B,GAAG,YAAY;gBACf,kBAAkB,EAAE,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE;aAC9D,CAAC;YACF,MAAM,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAEjD,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClD,CAAC;QAED,KAAK,CAAC,WAAW;YACf,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACvD,cAAc,CACZ,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC;gBAC7B,YAAY,EAAE,OAAO,CAAC,WAAW;gBACjC,UAAU,EAAE,OAAO,CAAC,SAAS;gBAC7B,MAAM,EAAE,KAAK,CAAC,UAAU;aACzB,CAAC,EACF,eAAe,CAChB,CACF,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;gBACrB,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACvD,IAAI,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;oBACpC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC;gBAC5D,CAAC;gBACD,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;YACtD,CAAC;YAED,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC;YACzC,KAAK,MAAM,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBAC1C,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE;oBAClC,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC;oBAC/B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;oBACpC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;oBACnC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,MAAM,EAAE,MAAM,CAAC,eAAe;oBAC9B,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;oBACnD,MAAM,EAAE,QAAQ;oBAChB,SAAS,EAAE,MAAM,CAAC,EAAE;iBACrB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,SAAS,GAAc;gBAC3B,GAAG,YAAY;gBACf,UAAU,EAAE,YAAY,CAAC,WAAW,IAAI,YAAY,CAAC,UAAU;aAChE,CAAC;YACF,MAAM,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAEjD,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACjD,CAAC;QAED,KAAK,CAAC,iBAAiB;YACrB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC3F,MAAM,YAAY,GAAG,sBAAsB,CAAC,aAAa,CAAC,CAAC;YAE3D,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,CAC5C,cAAc,CACZ,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;gBAC5B,YAAY,EAAE,OAAO,CAAC,WAAW;gBACjC,UAAU,EAAE,OAAO,CAAC,SAAS;gBAC7B,SAAS,EAAE,eAAe;gBAC1B,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,KAAK,CAAC,YAAY;aAC3B,CAAC,EACF,eAAe,CAChB,CACF,CAAC;YAEF,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;gBACrB,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;YACjD,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,SAAS,GAAc;gBAC3B,GAAG,YAAY;gBACf,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,IAAI,YAAY,CAAC,YAAY;aAC3E,CAAC;YACF,MAAM,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAEjD,OAAO,YAAY,CAAC,MAAM,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/index.js CHANGED
@@ -20,11 +20,13 @@ export { filterSummarizableNodes, summarizeWu, getCompactionRatio as getSummariz
20
20
  export * from './mem-triage-core.js';
21
21
  export * from './mem-index-core.js';
22
22
  export * from './mem-promote-core.js';
23
+ export * from './memory-promotion.js';
23
24
  export * from './mem-profile-core.js';
24
25
  export * from './mem-delete-core.js';
25
26
  export * from './mem-recover-core.js';
26
27
  export * from './memory-schema.js';
27
28
  export * from './memory-store.js';
29
+ export * from './control-plane-sync-adapter.js';
28
30
  // WU-1238: Decay scoring and access tracking
29
31
  export * from './decay/scoring.js';
30
32
  export * from './decay/access-tracking.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;GAGG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,kBAAkB,IAAI,2BAA2B,GAClD,MAAM,yBAAyB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAElC,6CAA6C;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;GAGG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,kBAAkB,IAAI,2BAA2B,GAClD,MAAM,yBAAyB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iCAAiC,CAAC;AAEhD,6CAA6C;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC"}
@@ -50,7 +50,62 @@ const SIGNAL_ID_LENGTH = 8;
50
50
  const ERROR_MESSAGES = {
51
51
  MESSAGE_REQUIRED: 'message is required and cannot be empty',
52
52
  INVALID_WU_ID: 'Invalid WU ID format. Expected WU-XXX (e.g., WU-1473)',
53
+ INVALID_SIGNAL_METADATA: 'Signal metadata fields must be non-empty strings when provided',
54
+ LEGACY_SIGNAL_RECORD: 'Legacy signal record is not supported by the strict signal contract. Migrate records before loading signals.',
55
+ INVALID_SIGNAL_RECORD: 'Invalid signal record in signals.jsonl',
53
56
  };
57
+ const DEFAULT_SIGNAL_TYPE = 'coordination';
58
+ const DEFAULT_SIGNAL_SENDER = 'system';
59
+ const DEFAULT_SIGNAL_ORIGIN = 'local';
60
+ function normalizeOptionalString(value, fieldName) {
61
+ if (value === undefined) {
62
+ return undefined;
63
+ }
64
+ const normalized = value.trim();
65
+ if (normalized.length === 0) {
66
+ throw createError(ErrorCodes.VALIDATION_ERROR, `${ERROR_MESSAGES.INVALID_SIGNAL_METADATA}: ${fieldName}`);
67
+ }
68
+ return normalized;
69
+ }
70
+ function isNonEmptyString(value) {
71
+ return typeof value === 'string' && value.trim().length > 0;
72
+ }
73
+ function parseStrictSignalRecord(line, lineNumber) {
74
+ let parsed;
75
+ try {
76
+ parsed = JSON.parse(line);
77
+ }
78
+ catch {
79
+ throw createError(ErrorCodes.VALIDATION_ERROR, `${ERROR_MESSAGES.INVALID_SIGNAL_RECORD} at line ${lineNumber}`);
80
+ }
81
+ if (typeof parsed !== 'object' || parsed === null) {
82
+ throw createError(ErrorCodes.VALIDATION_ERROR, `${ERROR_MESSAGES.INVALID_SIGNAL_RECORD} at line ${lineNumber}`);
83
+ }
84
+ const candidate = parsed;
85
+ if (!isNonEmptyString(candidate.id) ||
86
+ !isNonEmptyString(candidate.message) ||
87
+ !isNonEmptyString(candidate.created_at) ||
88
+ typeof candidate.read !== 'boolean') {
89
+ throw createError(ErrorCodes.VALIDATION_ERROR, `${ERROR_MESSAGES.INVALID_SIGNAL_RECORD} at line ${lineNumber}`);
90
+ }
91
+ if (!isNonEmptyString(candidate.type) ||
92
+ !isNonEmptyString(candidate.sender) ||
93
+ !isNonEmptyString(candidate.origin) ||
94
+ !isNonEmptyString(candidate.remote_id)) {
95
+ throw createError(ErrorCodes.VALIDATION_ERROR, `${ERROR_MESSAGES.LEGACY_SIGNAL_RECORD} (line ${lineNumber})`);
96
+ }
97
+ return {
98
+ ...candidate,
99
+ id: candidate.id,
100
+ message: candidate.message,
101
+ created_at: candidate.created_at,
102
+ read: candidate.read,
103
+ type: candidate.type,
104
+ sender: candidate.sender,
105
+ origin: candidate.origin,
106
+ remote_id: candidate.remote_id,
107
+ };
108
+ }
54
109
  /**
55
110
  * Generates a unique signal ID using random bytes.
56
111
  *
@@ -152,7 +207,7 @@ function isValidWuId(wuId) {
152
207
  * });
153
208
  */
154
209
  export async function createSignal(baseDir, options) {
155
- const { message, wuId, lane } = options;
210
+ const { message, wuId, lane, type, sender, target_agent, origin, remote_id } = options;
156
211
  // Validate message is provided and non-empty
157
212
  if (!message || typeof message !== 'string' || message.trim().length === 0) {
158
213
  throw createError(ErrorCodes.VALIDATION_ERROR, ERROR_MESSAGES.MESSAGE_REQUIRED);
@@ -161,13 +216,23 @@ export async function createSignal(baseDir, options) {
161
216
  if (wuId !== undefined && !isValidWuId(wuId)) {
162
217
  throw createError(ErrorCodes.INVALID_WU_ID, ERROR_MESSAGES.INVALID_WU_ID);
163
218
  }
219
+ const normalizedType = normalizeOptionalString(type, 'type') ?? DEFAULT_SIGNAL_TYPE;
220
+ const normalizedSender = normalizeOptionalString(sender, 'sender') ?? DEFAULT_SIGNAL_SENDER;
221
+ const normalizedTargetAgent = normalizeOptionalString(target_agent, 'target_agent');
222
+ const normalizedOrigin = normalizeOptionalString(origin, 'origin') ?? DEFAULT_SIGNAL_ORIGIN;
223
+ const normalizedRemoteId = normalizeOptionalString(remote_id, 'remote_id');
164
224
  // Build signal object
165
225
  const signal = {
166
226
  id: generateSignalId(),
167
227
  message: message.trim(),
168
228
  created_at: new Date().toISOString(),
169
229
  read: false,
230
+ type: normalizedType,
231
+ sender: normalizedSender,
232
+ origin: normalizedOrigin,
233
+ remote_id: '',
170
234
  };
235
+ signal.remote_id = normalizedRemoteId ?? signal.id;
171
236
  // Add optional fields
172
237
  if (wuId) {
173
238
  signal.wu_id = wuId;
@@ -175,6 +240,9 @@ export async function createSignal(baseDir, options) {
175
240
  if (lane) {
176
241
  signal.lane = lane;
177
242
  }
243
+ if (normalizedTargetAgent) {
244
+ signal.target_agent = normalizedTargetAgent;
245
+ }
178
246
  // Ensure memory directory exists
179
247
  const memoryDir = getMemoryDir(baseDir);
180
248
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool creates known directory
@@ -228,7 +296,7 @@ export async function loadSignals(baseDir, options = {}) {
228
296
  }
229
297
  // Parse JSONL content
230
298
  const lines = content.split('\n').filter((line) => line.trim());
231
- const signals = lines.map((line) => JSON.parse(line));
299
+ const signals = lines.map((line, index) => parseStrictSignalRecord(line, index + 1));
232
300
  // Merge receipt-based read state (WU-1472)
233
301
  const receiptIds = await loadReceiptIds(baseDir);
234
302
  for (const signal of signals) {
@@ -1 +1 @@
1
- {"version":3,"file":"mem-signal-core.js","sourceRoot":"","sources":["../src/mem-signal-core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mem-signal-core.js","sourceRoot":"","sources":["../src/mem-signal-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Project memory promotion for wu:done cleanup flow (WU-2145).
5
+ *
6
+ * Copies project-lifecycle memory nodes from a WU worktree memory store to the
7
+ * main checkout memory store before worktree deletion.
8
+ */
9
+ import fs from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import { appendNode, loadMemoryAll } from './memory-store.js';
12
+ import { LUMENFLOW_MEMORY_PATHS } from './paths.js';
13
+ const PROJECT_LIFECYCLE = 'project';
14
+ function isProjectNode(node) {
15
+ return node.lifecycle === PROJECT_LIFECYCLE;
16
+ }
17
+ function resolveMemoryDir(baseDir) {
18
+ return path.join(baseDir, LUMENFLOW_MEMORY_PATHS.MEMORY_DIR);
19
+ }
20
+ /**
21
+ * Promote project-lifecycle nodes from worktree memory into main memory.
22
+ *
23
+ * Rules:
24
+ * - Only nodes with lifecycle='project' are eligible
25
+ * - Nodes already present in main memory (same id) are skipped
26
+ * - If no project nodes exist, this is a no-op
27
+ */
28
+ export async function promoteProjectMemory(worktreeDir, mainDir) {
29
+ const worktreeMemoryDir = resolveMemoryDir(worktreeDir);
30
+ const mainMemoryDir = resolveMemoryDir(mainDir);
31
+ const worktreeMemory = await loadMemoryAll(worktreeMemoryDir);
32
+ const mainMemory = await loadMemoryAll(mainMemoryDir);
33
+ const projectNodes = worktreeMemory.nodes.filter(isProjectNode);
34
+ if (projectNodes.length === 0) {
35
+ return {
36
+ promotedCount: 0,
37
+ promotedNodeIds: [],
38
+ skippedCount: 0,
39
+ skippedNodeIds: [],
40
+ };
41
+ }
42
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- path is derived from vetted workspace root + fixed memory dir suffix.
43
+ await fs.mkdir(mainMemoryDir, { recursive: true });
44
+ const promotedNodeIds = [];
45
+ const skippedNodeIds = [];
46
+ for (const node of projectNodes) {
47
+ if (mainMemory.byId.has(node.id)) {
48
+ skippedNodeIds.push(node.id);
49
+ continue;
50
+ }
51
+ await appendNode(mainMemoryDir, node);
52
+ mainMemory.byId.set(node.id, node);
53
+ promotedNodeIds.push(node.id);
54
+ }
55
+ return {
56
+ promotedCount: promotedNodeIds.length,
57
+ promotedNodeIds,
58
+ skippedCount: skippedNodeIds.length,
59
+ skippedNodeIds,
60
+ };
61
+ }
62
+ //# sourceMappingURL=memory-promotion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-promotion.js","sourceRoot":"","sources":["../src/memory-promotion.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,iBAAiB,GAAG,SAAS,CAAC;AASpC,SAAS,aAAa,CAAC,IAAgB;IACrC,OAAO,IAAI,CAAC,SAAS,KAAK,iBAAiB,CAAC;AAC9C,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,OAAe;IAEf,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACxD,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAEhD,MAAM,cAAc,GAAG,MAAM,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,aAAa,CAAC,CAAC;IAEtD,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAChE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,eAAe,EAAE,EAAE;YACnB,YAAY,EAAE,CAAC;YACf,cAAc,EAAE,EAAE;SACnB,CAAC;IACJ,CAAC;IAED,4IAA4I;IAC5I,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnD,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACjC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACtC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACnC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,OAAO;QACL,aAAa,EAAE,eAAe,CAAC,MAAM;QACrC,eAAe;QACf,YAAY,EAAE,cAAc,CAAC,MAAM;QACnC,cAAc;KACf,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/memory",
3
- "version": "3.8.7",
3
+ "version": "3.9.1",
4
4
  "description": "Memory layer for LumenFlow workflow framework - session tracking, context recovery, and agent coordination",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -56,7 +56,7 @@
56
56
  "ms": "^2.1.3",
57
57
  "yaml": "^2.8.2",
58
58
  "zod": "^4.3.6",
59
- "@lumenflow/core": "3.8.7"
59
+ "@lumenflow/core": "3.9.1"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@vitest/coverage-v8": "^4.0.18",