@sesamespace/hivemind 0.12.2 → 0.12.4
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.
- package/dist/{chunk-ZAPHLG7V.js → chunk-FIHSUSBJ.js} +2 -2
- package/dist/{chunk-EJM4KCCY.js → chunk-J3WGHS5W.js} +2 -2
- package/dist/{chunk-R7RHYYOM.js → chunk-PGLO6WA5.js} +189 -30
- package/dist/{chunk-R7RHYYOM.js.map → chunk-PGLO6WA5.js.map} +1 -1
- package/dist/{chunk-3F7M2BPR.js → chunk-TJBUZUVY.js} +3 -3
- package/dist/{chunk-SNW6Z2W4.js → chunk-XW4AQDZA.js} +2 -2
- package/dist/{chunk-ZI4AN7GT.js → chunk-YDK3Z5IW.js} +2 -2
- package/dist/commands/fleet.js +3 -3
- package/dist/commands/init.js +3 -3
- package/dist/commands/start.js +3 -3
- package/dist/commands/watchdog.js +3 -3
- package/dist/index.js +2 -2
- package/dist/main.js +6 -6
- package/dist/start.js +1 -1
- package/package.json +1 -1
- package/test/claude-integration.test.ts +325 -0
- package/.session-log.json +0 -58
- /package/dist/{chunk-ZAPHLG7V.js.map → chunk-FIHSUSBJ.js.map} +0 -0
- /package/dist/{chunk-EJM4KCCY.js.map → chunk-J3WGHS5W.js.map} +0 -0
- /package/dist/{chunk-3F7M2BPR.js.map → chunk-TJBUZUVY.js.map} +0 -0
- /package/dist/{chunk-SNW6Z2W4.js.map → chunk-XW4AQDZA.js.map} +0 -0
- /package/dist/{chunk-ZI4AN7GT.js.map → chunk-YDK3Z5IW.js.map} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Watchdog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FIHSUSBJ.js";
|
|
4
4
|
import {
|
|
5
5
|
defaultSentinelConfig,
|
|
6
6
|
loadConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-PGLO6WA5.js";
|
|
8
8
|
|
|
9
9
|
// packages/cli/src/commands/watchdog.ts
|
|
10
10
|
import { resolve } from "path";
|
|
@@ -76,4 +76,4 @@ Options:
|
|
|
76
76
|
export {
|
|
77
77
|
runWatchdogCommand
|
|
78
78
|
};
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-TJBUZUVY.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startPipeline
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PGLO6WA5.js";
|
|
4
4
|
|
|
5
5
|
// packages/cli/src/commands/start.ts
|
|
6
6
|
import { resolve } from "path";
|
|
@@ -66,4 +66,4 @@ Options:
|
|
|
66
66
|
export {
|
|
67
67
|
runStartCommand
|
|
68
68
|
};
|
|
69
|
-
//# sourceMappingURL=chunk-
|
|
69
|
+
//# sourceMappingURL=chunk-XW4AQDZA.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SesameClient,
|
|
3
3
|
getClaudeCodeOAuthToken
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PGLO6WA5.js";
|
|
5
5
|
|
|
6
6
|
// packages/cli/src/commands/init.ts
|
|
7
7
|
import { resolve, dirname } from "path";
|
|
@@ -436,4 +436,4 @@ Options:
|
|
|
436
436
|
export {
|
|
437
437
|
runInitCommand
|
|
438
438
|
};
|
|
439
|
-
//# sourceMappingURL=chunk-
|
|
439
|
+
//# sourceMappingURL=chunk-YDK3Z5IW.js.map
|
package/dist/commands/fleet.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runFleetCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-J3WGHS5W.js";
|
|
4
|
+
import "../chunk-FIHSUSBJ.js";
|
|
5
|
+
import "../chunk-PGLO6WA5.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runFleetCommand
|
package/dist/commands/init.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runInitCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-YDK3Z5IW.js";
|
|
4
|
+
import "../chunk-FIHSUSBJ.js";
|
|
5
|
+
import "../chunk-PGLO6WA5.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runInitCommand
|
package/dist/commands/start.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runStartCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-XW4AQDZA.js";
|
|
4
|
+
import "../chunk-FIHSUSBJ.js";
|
|
5
|
+
import "../chunk-PGLO6WA5.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runStartCommand
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runWatchdogCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-TJBUZUVY.js";
|
|
4
|
+
import "../chunk-FIHSUSBJ.js";
|
|
5
|
+
import "../chunk-PGLO6WA5.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runWatchdogCommand
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
PrimaryMemorySync,
|
|
5
5
|
Watchdog,
|
|
6
6
|
WorkerMemorySync
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FIHSUSBJ.js";
|
|
8
8
|
import {
|
|
9
9
|
Agent,
|
|
10
10
|
AutoDebugger,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
setLogLevel,
|
|
35
35
|
startPipeline,
|
|
36
36
|
startWorker
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-PGLO6WA5.js";
|
|
38
38
|
import "./chunk-DGUM43GV.js";
|
|
39
39
|
export {
|
|
40
40
|
Agent,
|
package/dist/main.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runInitCommand
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YDK3Z5IW.js";
|
|
5
5
|
import {
|
|
6
6
|
runStartCommand
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XW4AQDZA.js";
|
|
8
8
|
import {
|
|
9
9
|
runFleetCommand
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-J3WGHS5W.js";
|
|
11
11
|
import {
|
|
12
12
|
runServiceCommand
|
|
13
13
|
} from "./chunk-6QZDXOMW.js";
|
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
} from "./chunk-ICSJNKI6.js";
|
|
17
17
|
import {
|
|
18
18
|
runWatchdogCommand
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-TJBUZUVY.js";
|
|
20
|
+
import "./chunk-FIHSUSBJ.js";
|
|
21
|
+
import "./chunk-PGLO6WA5.js";
|
|
22
22
|
import "./chunk-DGUM43GV.js";
|
|
23
23
|
|
|
24
24
|
// packages/cli/src/commands/session.ts
|
package/dist/start.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Suite for Claude Code Integration
|
|
3
|
+
*
|
|
4
|
+
* Tests the bidirectional context bridge, memory storage,
|
|
5
|
+
* and real-time notification systems.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeEach, afterEach } from "@jest/globals";
|
|
9
|
+
import { ClaudeContextBridge } from "../packages/runtime/src/tools/context-bridge.js";
|
|
10
|
+
import { ClaudeNotifier } from "../packages/runtime/src/tools/claude-notifier.js";
|
|
11
|
+
import { MemoryClient } from "../packages/runtime/src/memory-client.js";
|
|
12
|
+
import { Logger } from "../packages/runtime/src/logger.js";
|
|
13
|
+
import { writeFileSync, unlinkSync, existsSync } from "fs";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import { homedir } from "os";
|
|
16
|
+
|
|
17
|
+
describe("Claude Code Integration", () => {
|
|
18
|
+
let contextBridge: ClaudeContextBridge;
|
|
19
|
+
let memoryClient: MemoryClient;
|
|
20
|
+
let logger: Logger;
|
|
21
|
+
let workspaceDir: string;
|
|
22
|
+
let sessionLogPath: string;
|
|
23
|
+
|
|
24
|
+
beforeEach(async () => {
|
|
25
|
+
// Set up test environment
|
|
26
|
+
workspaceDir = "/tmp/test-workspace";
|
|
27
|
+
sessionLogPath = join(homedir(), ".claude", "session.log");
|
|
28
|
+
|
|
29
|
+
// Create mock implementations
|
|
30
|
+
logger = {
|
|
31
|
+
info: jest.fn(),
|
|
32
|
+
warn: jest.fn(),
|
|
33
|
+
error: jest.fn(),
|
|
34
|
+
debug: jest.fn(),
|
|
35
|
+
} as any;
|
|
36
|
+
|
|
37
|
+
memoryClient = {
|
|
38
|
+
search: jest.fn().mockResolvedValue([]),
|
|
39
|
+
storeEpisode: jest.fn().mockResolvedValue({}),
|
|
40
|
+
} as any;
|
|
41
|
+
|
|
42
|
+
// Create context bridge
|
|
43
|
+
contextBridge = new ClaudeContextBridge({
|
|
44
|
+
workspaceDir,
|
|
45
|
+
memoryClient,
|
|
46
|
+
logger,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await contextBridge.initialize();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
contextBridge.destroy();
|
|
54
|
+
// Clean up test files
|
|
55
|
+
if (existsSync(sessionLogPath)) {
|
|
56
|
+
unlinkSync(sessionLogPath);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe("Context Preparation", () => {
|
|
61
|
+
it("should prepare context with all fields", async () => {
|
|
62
|
+
const context = {
|
|
63
|
+
goal: "Fix authentication bug",
|
|
64
|
+
requirements: ["Must support OAuth", "Handle token refresh"],
|
|
65
|
+
recentErrors: ["401 Unauthorized on /api/user"],
|
|
66
|
+
relevantPatterns: ["Use middleware for auth"],
|
|
67
|
+
workingFiles: ["src/auth.ts", "src/middleware.ts"],
|
|
68
|
+
knownConstraints: ["JWT tokens expire after 1 hour"],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
await contextBridge.prepareContext(context);
|
|
72
|
+
|
|
73
|
+
const contextFile = join(workspaceDir, "CLAUDE_CONTEXT.md");
|
|
74
|
+
expect(existsSync(contextFile)).toBe(true);
|
|
75
|
+
|
|
76
|
+
const content = require('fs').readFileSync(contextFile, 'utf-8');
|
|
77
|
+
expect(content).toContain("Fix authentication bug");
|
|
78
|
+
expect(content).toContain("Must support OAuth");
|
|
79
|
+
expect(content).toContain("401 Unauthorized");
|
|
80
|
+
expect(content).toContain("Use middleware for auth");
|
|
81
|
+
expect(content).toContain("src/auth.ts");
|
|
82
|
+
expect(content).toContain("JWT tokens expire after 1 hour");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should include memory search results", async () => {
|
|
86
|
+
// Mock memory search
|
|
87
|
+
(memoryClient.search as jest.Mock).mockResolvedValue([
|
|
88
|
+
{ content: "Previous auth implementation used Passport.js" },
|
|
89
|
+
{ content: "Refresh tokens stored in Redis" },
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
await contextBridge.prepareContext({ goal: "Implement authentication" });
|
|
93
|
+
|
|
94
|
+
expect(memoryClient.search).toHaveBeenCalledWith("Implement authentication", "global", 5);
|
|
95
|
+
|
|
96
|
+
const contextFile = join(workspaceDir, "CLAUDE_CONTEXT.md");
|
|
97
|
+
const content = require('fs').readFileSync(contextFile, 'utf-8');
|
|
98
|
+
expect(content).toContain("Previous auth implementation used Passport.js");
|
|
99
|
+
expect(content).toContain("Refresh tokens stored in Redis");
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe("Session Log Monitoring", () => {
|
|
104
|
+
it("should detect and process DISCOVERY entries", (done) => {
|
|
105
|
+
contextBridge.on('insight', ({ type, content }) => {
|
|
106
|
+
expect(type).toBe('DISCOVERY');
|
|
107
|
+
expect(content).toBe('Found JWT validation in middleware');
|
|
108
|
+
done();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Simulate Claude writing to session log
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
writeFileSync(sessionLogPath, "DISCOVERY: Found JWT validation in middleware\n", { flag: 'a' });
|
|
114
|
+
}, 100);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("should detect and process NEED entries", (done) => {
|
|
118
|
+
contextBridge.on('context-request', (need) => {
|
|
119
|
+
expect(need).toBe('Database schema for users table');
|
|
120
|
+
done();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
writeFileSync(sessionLogPath, "NEED: Database schema for users table\n", { flag: 'a' });
|
|
125
|
+
}, 100);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("should store PATTERN entries in memory", (done) => {
|
|
129
|
+
contextBridge.on('insight', async ({ type }) => {
|
|
130
|
+
if (type === 'PATTERN') {
|
|
131
|
+
// Give it time to store
|
|
132
|
+
setTimeout(() => {
|
|
133
|
+
expect(memoryClient.storeEpisode).toHaveBeenCalledWith({
|
|
134
|
+
context_name: "claude-code-insights",
|
|
135
|
+
role: "system",
|
|
136
|
+
content: "PATTERN: Always validate JWT in middleware",
|
|
137
|
+
metadata: expect.objectContaining({
|
|
138
|
+
type: "PATTERN",
|
|
139
|
+
source: "claude-code",
|
|
140
|
+
}),
|
|
141
|
+
});
|
|
142
|
+
done();
|
|
143
|
+
}, 100);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
writeFileSync(sessionLogPath, "PATTERN: Always validate JWT in middleware\n", { flag: 'a' });
|
|
149
|
+
}, 100);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("should deduplicate identical patterns", async () => {
|
|
153
|
+
// Write the same pattern twice
|
|
154
|
+
writeFileSync(sessionLogPath, "PATTERN: Use async/await for DB calls\n");
|
|
155
|
+
await new Promise(resolve => setTimeout(resolve, 600));
|
|
156
|
+
writeFileSync(sessionLogPath, "PATTERN: Use async/await for DB calls\n", { flag: 'a' });
|
|
157
|
+
await new Promise(resolve => setTimeout(resolve, 600));
|
|
158
|
+
|
|
159
|
+
// Should only store once
|
|
160
|
+
expect(memoryClient.storeEpisode).toHaveBeenCalledTimes(1);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe("Real-time Context Injection", () => {
|
|
165
|
+
it("should append context when Claude needs it", async () => {
|
|
166
|
+
// Mock memory search for additional context
|
|
167
|
+
(memoryClient.search as jest.Mock).mockResolvedValue([
|
|
168
|
+
{ content: "Users table has columns: id, email, password_hash, created_at" },
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
// Prepare initial context
|
|
172
|
+
await contextBridge.prepareContext({ goal: "Fix user query" });
|
|
173
|
+
|
|
174
|
+
// Simulate Claude needing more info
|
|
175
|
+
writeFileSync(sessionLogPath, "NEED: Database schema\n", { flag: 'a' });
|
|
176
|
+
|
|
177
|
+
// Wait for processing
|
|
178
|
+
await new Promise(resolve => setTimeout(resolve, 600));
|
|
179
|
+
|
|
180
|
+
// Check that context was appended
|
|
181
|
+
const contextFile = join(workspaceDir, "CLAUDE_CONTEXT.md");
|
|
182
|
+
const content = require('fs').readFileSync(contextFile, 'utf-8');
|
|
183
|
+
expect(content).toContain("Additional Context");
|
|
184
|
+
expect(content).toContain("You asked about: Database schema");
|
|
185
|
+
expect(content).toContain("Users table has columns");
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("Session Summary", () => {
|
|
190
|
+
it("should retrieve categorized insights", async () => {
|
|
191
|
+
// Mock memory with various insight types
|
|
192
|
+
(memoryClient.search as jest.Mock).mockResolvedValue([
|
|
193
|
+
{ content: "DISCOVERY: Auth uses JWT with RS256" },
|
|
194
|
+
{ content: "PATTERN: Validate tokens in middleware" },
|
|
195
|
+
{ content: "ERROR: Missing JWKS endpoint" },
|
|
196
|
+
{ content: "COMPLETE: Implemented token refresh" },
|
|
197
|
+
{ content: "NEED: Public key for verification" },
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
const summary = await contextBridge.getSessionSummary();
|
|
201
|
+
|
|
202
|
+
expect(summary.discoveries).toContain("Auth uses JWT with RS256");
|
|
203
|
+
expect(summary.patterns).toContain("Validate tokens in middleware");
|
|
204
|
+
expect(summary.errors).toContain("Missing JWKS endpoint");
|
|
205
|
+
expect(summary.completions).toContain("Implemented token refresh");
|
|
206
|
+
expect(summary.needs).toContain("Public key for verification");
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("Notification System", () => {
|
|
211
|
+
it("should emit urgent events for NEED requests", (done) => {
|
|
212
|
+
const notifier = new ClaudeNotifier({
|
|
213
|
+
logger,
|
|
214
|
+
contextBridge,
|
|
215
|
+
onNeed: async (need) => {
|
|
216
|
+
expect(need).toBe("API documentation");
|
|
217
|
+
done();
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Simulate Claude needing something
|
|
222
|
+
writeFileSync(sessionLogPath, "NEED: API documentation\n", { flag: 'a' });
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("should handle critical errors", (done) => {
|
|
226
|
+
const notifier = new ClaudeNotifier({
|
|
227
|
+
logger,
|
|
228
|
+
contextBridge,
|
|
229
|
+
onError: async (error) => {
|
|
230
|
+
expect(error).toBe("Cannot find module 'auth'");
|
|
231
|
+
done();
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
writeFileSync(sessionLogPath, "ERROR: Cannot find module 'auth'\n", { flag: 'a' });
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("should create urgent events", (done) => {
|
|
239
|
+
const notifier = new ClaudeNotifier({
|
|
240
|
+
logger,
|
|
241
|
+
contextBridge,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
notifier.on('urgent-event', (event) => {
|
|
245
|
+
expect(event.type).toBe("immediate");
|
|
246
|
+
expect(event.text).toContain("[Claude Code Urgent]");
|
|
247
|
+
expect(event.text).toContain("Missing database credentials");
|
|
248
|
+
done();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
notifier.createUrgentEvent("Missing database credentials", "test-channel");
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
describe("End-to-End Integration", () => {
|
|
256
|
+
it("should handle a complete Claude Code session", async () => {
|
|
257
|
+
// Prepare context
|
|
258
|
+
await contextBridge.prepareContext({
|
|
259
|
+
goal: "Implement user authentication",
|
|
260
|
+
requirements: ["Support JWT", "Handle refresh tokens"],
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Simulate Claude Code session
|
|
264
|
+
const sessionLog = [
|
|
265
|
+
"DISCOVERY: Found existing Passport.js setup",
|
|
266
|
+
"PATTERN: Use httpOnly cookies for refresh tokens",
|
|
267
|
+
"NEED: Redis connection details",
|
|
268
|
+
"ERROR: Redis connection failed",
|
|
269
|
+
"COMPLETE: Implemented JWT authentication",
|
|
270
|
+
];
|
|
271
|
+
|
|
272
|
+
for (const line of sessionLog) {
|
|
273
|
+
writeFileSync(sessionLogPath, line + "\n", { flag: 'a' });
|
|
274
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Wait for processing
|
|
278
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
279
|
+
|
|
280
|
+
// Verify memory storage
|
|
281
|
+
const storeEpisodeCalls = (memoryClient.storeEpisode as jest.Mock).mock.calls;
|
|
282
|
+
expect(storeEpisodeCalls.length).toBeGreaterThanOrEqual(2);
|
|
283
|
+
|
|
284
|
+
// Verify discoveries and patterns were stored
|
|
285
|
+
const storedContent = storeEpisodeCalls.map(call => call[0].content);
|
|
286
|
+
expect(storedContent).toContain("DISCOVERY: Found existing Passport.js setup");
|
|
287
|
+
expect(storedContent).toContain("PATTERN: Use httpOnly cookies for refresh tokens");
|
|
288
|
+
|
|
289
|
+
// Get session summary
|
|
290
|
+
const summary = await contextBridge.getSessionSummary();
|
|
291
|
+
expect(summary.discoveries.length).toBeGreaterThan(0);
|
|
292
|
+
expect(summary.patterns.length).toBeGreaterThan(0);
|
|
293
|
+
expect(summary.errors.length).toBeGreaterThan(0);
|
|
294
|
+
expect(summary.completions.length).toBeGreaterThan(0);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
describe("Test Suite Requirements", () => {
|
|
300
|
+
it("should cover all critical functionality", () => {
|
|
301
|
+
const testCategories = [
|
|
302
|
+
"Context Preparation",
|
|
303
|
+
"Session Log Monitoring",
|
|
304
|
+
"Real-time Context Injection",
|
|
305
|
+
"Session Summary",
|
|
306
|
+
"Notification System",
|
|
307
|
+
"End-to-End Integration"
|
|
308
|
+
];
|
|
309
|
+
|
|
310
|
+
const criticalFeatures = [
|
|
311
|
+
"Prepare context with memory search",
|
|
312
|
+
"Monitor session log in real-time",
|
|
313
|
+
"Store discoveries and patterns",
|
|
314
|
+
"Deduplicate patterns",
|
|
315
|
+
"Inject context on NEED",
|
|
316
|
+
"Emit notifications for urgent needs",
|
|
317
|
+
"Generate session summaries",
|
|
318
|
+
"Handle complete sessions"
|
|
319
|
+
];
|
|
320
|
+
|
|
321
|
+
// This test just documents what we're testing
|
|
322
|
+
expect(testCategories.length).toBeGreaterThanOrEqual(6);
|
|
323
|
+
expect(criticalFeatures.length).toBeGreaterThanOrEqual(8);
|
|
324
|
+
});
|
|
325
|
+
});
|
package/.session-log.json
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"timestamp": "2026-03-10T00:00:00Z",
|
|
3
|
-
"summary": "Fixed stale PID reporting in `hivemind service status` by rewriting showStatus() to parse PIDs from `launchctl list` output instead of PID files. Added kickstart recovery for KeepAlive services (memory, watchdog). Removed hardcoded wrapper scripts from git tracking and added them to .gitignore since they are generated dynamically during `hivemind service install`.",
|
|
4
|
-
"decisions": [
|
|
5
|
-
{
|
|
6
|
-
"topic": "PID source",
|
|
7
|
-
"choice": "Parse PID from launchctl list output using regex",
|
|
8
|
-
"rationale": "launchctl is the authoritative source for launchd-managed process PIDs; PID files go stale when launchd restarts a crashed process",
|
|
9
|
-
"alternatives_considered": ["Keep PID file approach with periodic refresh", "Use ps/pgrep to find processes"]
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"topic": "Stale service recovery",
|
|
13
|
-
"choice": "Auto-kickstart KeepAlive services (memory, watchdog) but not agent",
|
|
14
|
-
"rationale": "Agent is managed by watchdog, so kickstarting it from status would bypass watchdog's coordination",
|
|
15
|
-
"alternatives_considered": ["Kickstart all services", "Only report status without recovery"]
|
|
16
|
-
}
|
|
17
|
-
],
|
|
18
|
-
"patterns": [
|
|
19
|
-
{
|
|
20
|
-
"pattern": "Wrapper scripts in bin/ are generated dynamically during `hivemind service install` with correct local paths — never commit them",
|
|
21
|
-
"scope": "project-wide"
|
|
22
|
-
}
|
|
23
|
-
],
|
|
24
|
-
"gotchas": [
|
|
25
|
-
{
|
|
26
|
-
"issue": "Wrapper scripts had hardcoded paths from another developer's machine committed to git",
|
|
27
|
-
"resolution": "Removed from git tracking with `git rm --cached`, added bin/*-wrapper.sh to .gitignore",
|
|
28
|
-
"prevention": "The .gitignore entry will prevent future accidental commits"
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
"files_changed": [
|
|
32
|
-
{
|
|
33
|
-
"path": "packages/cli/src/commands/service.ts",
|
|
34
|
-
"action": "modified",
|
|
35
|
-
"purpose": "Rewrote showStatus() to use launchctl as PID source with kickstart recovery"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"path": ".gitignore",
|
|
39
|
-
"action": "modified",
|
|
40
|
-
"purpose": "Added bin/*-wrapper.sh pattern"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"path": "bin/agent-wrapper.sh",
|
|
44
|
-
"action": "deleted",
|
|
45
|
-
"purpose": "Removed hardcoded wrapper script from git tracking"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"path": "bin/memory-wrapper.sh",
|
|
49
|
-
"action": "deleted",
|
|
50
|
-
"purpose": "Removed hardcoded wrapper script from git tracking"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"path": "bin/watchdog-wrapper.sh",
|
|
54
|
-
"action": "deleted",
|
|
55
|
-
"purpose": "Removed hardcoded wrapper script from git tracking"
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|