@stackmemoryai/stackmemory 1.2.2 → 1.2.6
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/README.md +10 -6
- package/dist/src/cli/claude-sm.js +33 -4
- package/dist/src/cli/codex-sm-danger.js +4 -1
- package/dist/src/cli/codex-sm.js +6 -8
- package/dist/src/cli/commands/config.js +0 -81
- package/dist/src/cli/commands/context-rehydrate.js +133 -47
- package/dist/src/cli/commands/db.js +35 -8
- package/dist/src/cli/commands/handoff.js +1 -1
- package/dist/src/cli/commands/linear.js +9 -0
- package/dist/src/cli/commands/ralph.js +2 -2
- package/dist/src/cli/commands/setup.js +2 -2
- package/dist/src/cli/commands/signup.js +3 -1
- package/dist/src/cli/commands/skills.js +108 -1
- package/dist/src/cli/commands/storage-tier.js +26 -8
- package/dist/src/cli/index.js +1 -57
- package/dist/src/core/config/feature-flags.js +0 -4
- package/dist/src/core/context/dual-stack-manager.js +10 -3
- package/dist/src/core/context/frame-database.js +32 -0
- package/dist/src/core/context/frame-handoff-manager.js +2 -2
- package/dist/src/core/context/{refactored-frame-manager.js → frame-manager.js} +3 -3
- package/dist/src/core/context/index.js +2 -2
- package/dist/src/core/database/sqlite-adapter.js +161 -1
- package/dist/src/core/digest/frame-digest-integration.js +1 -1
- package/dist/src/core/digest/index.js +1 -1
- package/dist/src/core/execution/parallel-executor.js +5 -1
- package/dist/src/core/projects/project-isolation.js +18 -4
- package/dist/src/core/security/index.js +2 -0
- package/dist/src/core/security/input-sanitizer.js +23 -0
- package/dist/src/core/utils/update-checker.js +10 -6
- package/dist/src/daemon/daemon-config.js +2 -1
- package/dist/src/daemon/services/auto-save-service.js +121 -0
- package/dist/src/daemon/services/maintenance-service.js +76 -1
- package/dist/src/features/sweep/prompt-builder.js +2 -2
- package/dist/src/hooks/daemon.js +0 -8
- package/dist/src/integrations/linear/config.js +3 -1
- package/dist/src/integrations/linear/sync.js +18 -5
- package/dist/src/integrations/linear/webhook.js +0 -16
- package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +33 -7
- package/dist/src/integrations/mcp/handlers/cord-handlers.js +397 -0
- package/dist/src/integrations/mcp/handlers/index.js +55 -9
- package/dist/src/integrations/mcp/handlers/task-handlers.js +55 -12
- package/dist/src/integrations/mcp/handlers/team-handlers.js +211 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js +28 -9
- package/dist/src/integrations/mcp/index.js +2 -2
- package/dist/src/integrations/mcp/refactored-server.js +31 -10
- package/dist/src/integrations/mcp/server.js +0 -130
- package/dist/src/integrations/mcp/tool-definitions.js +196 -67
- package/dist/src/integrations/ralph/context/context-budget-manager.js +10 -2
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +54 -22
- package/dist/src/integrations/ralph/learning/pattern-learner.js +59 -24
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +81 -35
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +12 -4
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +32 -9
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +25 -8
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +17 -5
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js +73 -22
- package/dist/src/skills/claude-skills.js +37 -103
- package/dist/src/skills/theory-skill.js +191 -0
- package/dist/src/utils/hook-installer.js +16 -0
- package/package.json +6 -6
- package/scripts/install-claude-hooks-auto.js +8 -0
- package/templates/claude-hooks/cord-trace.js +225 -0
- package/templates/claude-hooks/theory-capture.js +100 -0
- package/dist/src/core/config/storage-config.js +0 -114
- package/dist/src/core/storage/chromadb-adapter.js +0 -379
- package/dist/src/hooks/graphiti-hooks.js +0 -253
- package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
- package/dist/src/integrations/graphiti/client.js +0 -115
- package/dist/src/integrations/graphiti/config.js +0 -17
- package/dist/src/integrations/graphiti/linear-graphiti-bridge.js +0 -115
- package/dist/src/integrations/graphiti/types.js +0 -4
- package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +0 -409
- package/dist/src/skills/repo-ingestion-skill.js +0 -631
- package/templates/claude-hooks/chromadb-wrapper +0 -21
- /package/dist/src/core/context/{enhanced-rehydration.js → rehydration.js} +0 -0
- /package/dist/src/core/digest/{enhanced-hybrid-digest.js → hybrid-digest.js} +0 -0
- /package/dist/src/core/session/{enhanced-handoff.js → handoff.js} +0 -0
|
@@ -25,7 +25,10 @@ class PatternLearner {
|
|
|
25
25
|
await sharedContextLayer.initialize();
|
|
26
26
|
const session = await sessionManager.getOrCreateSession({});
|
|
27
27
|
if (session.database) {
|
|
28
|
-
this.frameManager = new FrameManager(
|
|
28
|
+
this.frameManager = new FrameManager(
|
|
29
|
+
session.database,
|
|
30
|
+
session.projectId
|
|
31
|
+
);
|
|
29
32
|
}
|
|
30
33
|
logger.info("Pattern learner initialized successfully");
|
|
31
34
|
} catch (error) {
|
|
@@ -40,7 +43,9 @@ class PatternLearner {
|
|
|
40
43
|
logger.info("Starting pattern learning from completed loops");
|
|
41
44
|
try {
|
|
42
45
|
const completedLoops = await this.getCompletedRalphLoops();
|
|
43
|
-
logger.info(
|
|
46
|
+
logger.info(
|
|
47
|
+
`Found ${completedLoops.length} completed loops for analysis`
|
|
48
|
+
);
|
|
44
49
|
if (completedLoops.length < this.config.minLoopCountForPattern) {
|
|
45
50
|
logger.info("Not enough loops for pattern extraction");
|
|
46
51
|
return [];
|
|
@@ -55,7 +60,9 @@ class PatternLearner {
|
|
|
55
60
|
const taskPatterns = await this.extractTaskPatterns(completedLoops);
|
|
56
61
|
patterns.push(...taskPatterns);
|
|
57
62
|
await this.saveLearnedPatterns(patterns);
|
|
58
|
-
logger.info(
|
|
63
|
+
logger.info(
|
|
64
|
+
`Learned ${patterns.length} patterns from ${completedLoops.length} loops`
|
|
65
|
+
);
|
|
59
66
|
return patterns;
|
|
60
67
|
} catch (error) {
|
|
61
68
|
logger.error("Failed to learn patterns", error);
|
|
@@ -97,7 +104,10 @@ class PatternLearner {
|
|
|
97
104
|
analyses.push(analysis);
|
|
98
105
|
}
|
|
99
106
|
} catch (error) {
|
|
100
|
-
logger.warn(
|
|
107
|
+
logger.warn(
|
|
108
|
+
`Failed to analyze loop ${frame.frame_id}`,
|
|
109
|
+
error
|
|
110
|
+
);
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
return analyses;
|
|
@@ -159,15 +169,21 @@ class PatternLearner {
|
|
|
159
169
|
examples: successfulLoops.slice(0, 3).map((l) => l.task),
|
|
160
170
|
metadata: {
|
|
161
171
|
avgIterations,
|
|
162
|
-
minIterations: Math.min(
|
|
163
|
-
|
|
172
|
+
minIterations: Math.min(
|
|
173
|
+
...successfulLoops.map((l) => l.iterationCount)
|
|
174
|
+
),
|
|
175
|
+
maxIterations: Math.max(
|
|
176
|
+
...successfulLoops.map((l) => l.iterationCount)
|
|
177
|
+
)
|
|
164
178
|
}
|
|
165
179
|
});
|
|
166
180
|
const criteriaPatterns = this.extractCriteriaPatterns(successfulLoops);
|
|
167
181
|
patterns.push(...criteriaPatterns);
|
|
168
182
|
const successFactors = this.extractSuccessFactors(successfulLoops);
|
|
169
183
|
patterns.push(...successFactors);
|
|
170
|
-
return patterns.filter(
|
|
184
|
+
return patterns.filter(
|
|
185
|
+
(p) => p.confidence >= this.config.confidenceThreshold
|
|
186
|
+
);
|
|
171
187
|
}
|
|
172
188
|
/**
|
|
173
189
|
* Extract patterns from failed loops to avoid
|
|
@@ -191,7 +207,9 @@ class PatternLearner {
|
|
|
191
207
|
metadata: { failureType: failure.type }
|
|
192
208
|
});
|
|
193
209
|
}
|
|
194
|
-
return patterns.filter(
|
|
210
|
+
return patterns.filter(
|
|
211
|
+
(p) => p.confidence >= this.config.confidenceThreshold
|
|
212
|
+
);
|
|
195
213
|
}
|
|
196
214
|
/**
|
|
197
215
|
* Extract iteration-specific patterns
|
|
@@ -223,7 +241,10 @@ class PatternLearner {
|
|
|
223
241
|
const patterns = [];
|
|
224
242
|
for (const [taskType, taskLoops] of Object.entries(taskGroups)) {
|
|
225
243
|
if (taskLoops.length >= this.config.minLoopCountForPattern) {
|
|
226
|
-
const taskSpecificPatterns = await this.extractSpecializedPatterns(
|
|
244
|
+
const taskSpecificPatterns = await this.extractSpecializedPatterns(
|
|
245
|
+
taskLoops,
|
|
246
|
+
taskType
|
|
247
|
+
);
|
|
227
248
|
patterns.push(...taskSpecificPatterns);
|
|
228
249
|
}
|
|
229
250
|
}
|
|
@@ -266,12 +287,15 @@ class PatternLearner {
|
|
|
266
287
|
*/
|
|
267
288
|
classifyTaskType(task) {
|
|
268
289
|
const taskLower = task.toLowerCase();
|
|
269
|
-
if (taskLower.includes("test") || taskLower.includes("unit"))
|
|
290
|
+
if (taskLower.includes("test") || taskLower.includes("unit"))
|
|
291
|
+
return "testing";
|
|
270
292
|
if (taskLower.includes("fix") || taskLower.includes("bug")) return "bugfix";
|
|
271
293
|
if (taskLower.includes("refactor")) return "refactoring";
|
|
272
|
-
if (taskLower.includes("add") || taskLower.includes("implement"))
|
|
294
|
+
if (taskLower.includes("add") || taskLower.includes("implement"))
|
|
295
|
+
return "feature";
|
|
273
296
|
if (taskLower.includes("document")) return "documentation";
|
|
274
|
-
if (taskLower.includes("optimize") || taskLower.includes("performance"))
|
|
297
|
+
if (taskLower.includes("optimize") || taskLower.includes("performance"))
|
|
298
|
+
return "optimization";
|
|
275
299
|
return "general";
|
|
276
300
|
}
|
|
277
301
|
/**
|
|
@@ -331,7 +355,10 @@ class PatternLearner {
|
|
|
331
355
|
// Additional helper methods for pattern analysis
|
|
332
356
|
analyzeIterations(iterations) {
|
|
333
357
|
return {
|
|
334
|
-
avgDuration: iterations.length > 0 ? iterations.reduce(
|
|
358
|
+
avgDuration: iterations.length > 0 ? iterations.reduce(
|
|
359
|
+
(sum, i) => sum + (i.updated_at - i.created_at),
|
|
360
|
+
0
|
|
361
|
+
) / iterations.length : 0,
|
|
335
362
|
progressPattern: this.extractProgressPattern(iterations),
|
|
336
363
|
commonIssues: this.extractCommonIssues(iterations)
|
|
337
364
|
};
|
|
@@ -347,11 +374,16 @@ class PatternLearner {
|
|
|
347
374
|
return iterations.filter((i) => i.outputs?.errors?.length > 0).flatMap((i) => i.outputs.errors).slice(0, 3);
|
|
348
375
|
}
|
|
349
376
|
extractCriteriaPatterns(loops) {
|
|
350
|
-
const criteriaWords = loops.flatMap(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
377
|
+
const criteriaWords = loops.flatMap(
|
|
378
|
+
(l) => l.criteria.toLowerCase().split(/\s+/)
|
|
379
|
+
);
|
|
380
|
+
const wordCounts = criteriaWords.reduce(
|
|
381
|
+
(acc, word) => {
|
|
382
|
+
acc[word] = (acc[word] || 0) + 1;
|
|
383
|
+
return acc;
|
|
384
|
+
},
|
|
385
|
+
{}
|
|
386
|
+
);
|
|
355
387
|
const commonCriteria = Object.entries(wordCounts).filter(([_, count]) => count >= this.config.minLoopCountForPattern).sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
356
388
|
return commonCriteria.map(([word, count]) => ({
|
|
357
389
|
id: `criteria-${word}`,
|
|
@@ -374,12 +406,15 @@ class PatternLearner {
|
|
|
374
406
|
return [];
|
|
375
407
|
}
|
|
376
408
|
groupByTaskType(loops) {
|
|
377
|
-
return loops.reduce(
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
409
|
+
return loops.reduce(
|
|
410
|
+
(acc, loop) => {
|
|
411
|
+
const type = loop.taskType;
|
|
412
|
+
if (!acc[type]) acc[type] = [];
|
|
413
|
+
acc[type].push(loop);
|
|
414
|
+
return acc;
|
|
415
|
+
},
|
|
416
|
+
{}
|
|
417
|
+
);
|
|
383
418
|
}
|
|
384
419
|
summarizeSuccessPattern(loops) {
|
|
385
420
|
const avgIterations = loops.reduce((sum, l) => sum + l.iterationCount, 0) / loops.length;
|
|
@@ -29,7 +29,10 @@ class MultiLoopOrchestrator {
|
|
|
29
29
|
await sessionManager.initialize();
|
|
30
30
|
const session = await sessionManager.getOrCreateSession({});
|
|
31
31
|
if (session.database) {
|
|
32
|
-
this.frameManager = new FrameManager(
|
|
32
|
+
this.frameManager = new FrameManager(
|
|
33
|
+
session.database,
|
|
34
|
+
session.projectId
|
|
35
|
+
);
|
|
33
36
|
}
|
|
34
37
|
logger.info("Orchestrator initialized successfully");
|
|
35
38
|
} catch (error) {
|
|
@@ -92,11 +95,15 @@ class MultiLoopOrchestrator {
|
|
|
92
95
|
results: /* @__PURE__ */ new Map(),
|
|
93
96
|
sharedState: coordination?.sharedState || {}
|
|
94
97
|
};
|
|
95
|
-
const promises = tasks.map(
|
|
98
|
+
const promises = tasks.map(
|
|
99
|
+
(task) => this.executeParallelTask(task, execution)
|
|
100
|
+
);
|
|
96
101
|
try {
|
|
97
102
|
await Promise.allSettled(promises);
|
|
98
103
|
execution.endTime = Date.now();
|
|
99
|
-
execution.status = Array.from(execution.results.values()).every(
|
|
104
|
+
execution.status = Array.from(execution.results.values()).every(
|
|
105
|
+
(r) => r.success
|
|
106
|
+
) ? "success" : "partial";
|
|
100
107
|
return execution;
|
|
101
108
|
} catch (error) {
|
|
102
109
|
logger.error("Parallel execution failed", error);
|
|
@@ -111,16 +118,18 @@ class MultiLoopOrchestrator {
|
|
|
111
118
|
async analyzeAndBreakdownTask(description, criteria) {
|
|
112
119
|
const complexity = this.assessTaskComplexity(description);
|
|
113
120
|
if (complexity.score < 5) {
|
|
114
|
-
return [
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
return [
|
|
122
|
+
{
|
|
123
|
+
id: uuidv4(),
|
|
124
|
+
title: description,
|
|
125
|
+
description,
|
|
126
|
+
criteria,
|
|
127
|
+
priority: 1,
|
|
128
|
+
estimatedIterations: 3,
|
|
129
|
+
dependencies: [],
|
|
130
|
+
type: "single"
|
|
131
|
+
}
|
|
132
|
+
];
|
|
124
133
|
}
|
|
125
134
|
const subtasks = [];
|
|
126
135
|
if (this.needsSetup(description)) {
|
|
@@ -141,7 +150,9 @@ class MultiLoopOrchestrator {
|
|
|
141
150
|
id: uuidv4(),
|
|
142
151
|
title: "Core Implementation",
|
|
143
152
|
description: coreTask,
|
|
144
|
-
criteria: criteria.filter(
|
|
153
|
+
criteria: criteria.filter(
|
|
154
|
+
(c) => c.toLowerCase().includes("function") || c.toLowerCase().includes("implement")
|
|
155
|
+
),
|
|
145
156
|
priority: 2,
|
|
146
157
|
estimatedIterations: 5,
|
|
147
158
|
dependencies: subtasks.length > 0 ? [subtasks[0].id] : [],
|
|
@@ -172,16 +183,18 @@ class MultiLoopOrchestrator {
|
|
|
172
183
|
type: "documentation"
|
|
173
184
|
});
|
|
174
185
|
}
|
|
175
|
-
return subtasks.length > 0 ? subtasks : [
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
return subtasks.length > 0 ? subtasks : [
|
|
187
|
+
{
|
|
188
|
+
id: uuidv4(),
|
|
189
|
+
title: description,
|
|
190
|
+
description,
|
|
191
|
+
criteria,
|
|
192
|
+
priority: 1,
|
|
193
|
+
estimatedIterations: Math.min(8, Math.max(3, complexity.score)),
|
|
194
|
+
dependencies: [],
|
|
195
|
+
type: "single"
|
|
196
|
+
}
|
|
197
|
+
];
|
|
185
198
|
}
|
|
186
199
|
/**
|
|
187
200
|
* Create execution plan from breakdown
|
|
@@ -225,14 +238,19 @@ class MultiLoopOrchestrator {
|
|
|
225
238
|
try {
|
|
226
239
|
task.status = "executing";
|
|
227
240
|
for (const phase of task.executionPlan.phases) {
|
|
228
|
-
logger.info(
|
|
241
|
+
logger.info(
|
|
242
|
+
`Executing phase ${phase.id} with ${phase.tasks.length} tasks`
|
|
243
|
+
);
|
|
229
244
|
if (phase.parallelExecution && phase.tasks.length > 1) {
|
|
230
245
|
const parallelResult = await this.executeParallelLoops(phase.tasks);
|
|
231
246
|
for (const [taskId, taskResult] of parallelResult.results) {
|
|
232
247
|
if (taskResult.success) {
|
|
233
248
|
result.completedLoops.push(taskResult.loopId);
|
|
234
249
|
} else {
|
|
235
|
-
result.failedLoops.push({
|
|
250
|
+
result.failedLoops.push({
|
|
251
|
+
loopId: taskResult.loopId,
|
|
252
|
+
error: taskResult.error || "Unknown error"
|
|
253
|
+
});
|
|
236
254
|
}
|
|
237
255
|
}
|
|
238
256
|
} else {
|
|
@@ -244,7 +262,10 @@ class MultiLoopOrchestrator {
|
|
|
244
262
|
await this.updateSharedContext(task, loopResult);
|
|
245
263
|
}
|
|
246
264
|
} else {
|
|
247
|
-
result.failedLoops.push({
|
|
265
|
+
result.failedLoops.push({
|
|
266
|
+
loopId: loopResult.loopId,
|
|
267
|
+
error: loopResult.error || "Unknown error"
|
|
268
|
+
});
|
|
248
269
|
if (this.config.fallbackStrategy === "abort") {
|
|
249
270
|
throw new Error(`Task failed: ${loopResult.error}`);
|
|
250
271
|
}
|
|
@@ -302,7 +323,11 @@ class MultiLoopOrchestrator {
|
|
|
302
323
|
loopInfo.endTime = Date.now();
|
|
303
324
|
}
|
|
304
325
|
this.activeLoops.delete(taskBreakdown.id);
|
|
305
|
-
return {
|
|
326
|
+
return {
|
|
327
|
+
success: false,
|
|
328
|
+
loopId: taskBreakdown.id,
|
|
329
|
+
error: error.message
|
|
330
|
+
};
|
|
306
331
|
}
|
|
307
332
|
}
|
|
308
333
|
/**
|
|
@@ -314,7 +339,11 @@ class MultiLoopOrchestrator {
|
|
|
314
339
|
id: execution.id,
|
|
315
340
|
description: `Parallel task: ${task.title}`,
|
|
316
341
|
breakdown: [task],
|
|
317
|
-
executionPlan: {
|
|
342
|
+
executionPlan: {
|
|
343
|
+
phases: [],
|
|
344
|
+
totalEstimatedTime: 0,
|
|
345
|
+
parallelizable: false
|
|
346
|
+
},
|
|
318
347
|
status: "executing",
|
|
319
348
|
startTime: execution.startTime,
|
|
320
349
|
loops: /* @__PURE__ */ new Map(),
|
|
@@ -333,7 +362,10 @@ class MultiLoopOrchestrator {
|
|
|
333
362
|
* Update shared context between tasks
|
|
334
363
|
*/
|
|
335
364
|
async updateSharedContext(orchestratedTask, loopResult) {
|
|
336
|
-
logger.debug("Updating shared context", {
|
|
365
|
+
logger.debug("Updating shared context", {
|
|
366
|
+
orchestrationId: orchestratedTask.id,
|
|
367
|
+
loopId: loopResult.loopId
|
|
368
|
+
});
|
|
337
369
|
}
|
|
338
370
|
/**
|
|
339
371
|
* Generate insights from orchestration
|
|
@@ -342,12 +374,16 @@ class MultiLoopOrchestrator {
|
|
|
342
374
|
const insights = [];
|
|
343
375
|
const avgLoopDuration = Array.from(task.loops.values()).filter((l) => l.endTime && l.startTime).map((l) => l.endTime - l.startTime).reduce((sum, duration) => sum + duration, 0) / task.loops.size;
|
|
344
376
|
if (avgLoopDuration > 0) {
|
|
345
|
-
insights.push(
|
|
377
|
+
insights.push(
|
|
378
|
+
`Average loop duration: ${Math.round(avgLoopDuration / 1e3)}s`
|
|
379
|
+
);
|
|
346
380
|
}
|
|
347
381
|
const successRate = result.completedLoops.length / (result.completedLoops.length + result.failedLoops.length);
|
|
348
382
|
insights.push(`Success rate: ${Math.round(successRate * 100)}%`);
|
|
349
383
|
if (task.breakdown.length > 3) {
|
|
350
|
-
insights.push(
|
|
384
|
+
insights.push(
|
|
385
|
+
"Complex task benefited from breakdown into multiple loops"
|
|
386
|
+
);
|
|
351
387
|
}
|
|
352
388
|
return insights;
|
|
353
389
|
}
|
|
@@ -378,8 +414,16 @@ class MultiLoopOrchestrator {
|
|
|
378
414
|
return { score, factors };
|
|
379
415
|
}
|
|
380
416
|
needsSetup(description) {
|
|
381
|
-
const setupKeywords = [
|
|
382
|
-
|
|
417
|
+
const setupKeywords = [
|
|
418
|
+
"project",
|
|
419
|
+
"initialize",
|
|
420
|
+
"setup",
|
|
421
|
+
"scaffold",
|
|
422
|
+
"create structure"
|
|
423
|
+
];
|
|
424
|
+
return setupKeywords.some(
|
|
425
|
+
(keyword) => description.toLowerCase().includes(keyword)
|
|
426
|
+
);
|
|
383
427
|
}
|
|
384
428
|
needsTesting(criteria) {
|
|
385
429
|
return criteria.some((c) => c.toLowerCase().includes("test"));
|
|
@@ -389,7 +433,9 @@ class MultiLoopOrchestrator {
|
|
|
389
433
|
}
|
|
390
434
|
extractCoreTask(description) {
|
|
391
435
|
const sentences = description.split(".");
|
|
392
|
-
return sentences.find(
|
|
436
|
+
return sentences.find(
|
|
437
|
+
(s) => s.toLowerCase().includes("implement") || s.toLowerCase().includes("create") || s.toLowerCase().includes("add")
|
|
438
|
+
) || null;
|
|
393
439
|
}
|
|
394
440
|
canExecuteInParallel(breakdown) {
|
|
395
441
|
return breakdown.some((task) => task.dependencies.length === 0);
|
|
@@ -160,7 +160,9 @@ class CompoundingEngineeringManager {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
if (sessionData.codeStructure) {
|
|
163
|
-
const structurePattern = this.analyzeCodeStructurePattern(
|
|
163
|
+
const structurePattern = this.analyzeCodeStructurePattern(
|
|
164
|
+
sessionData.codeStructure
|
|
165
|
+
);
|
|
164
166
|
if (structurePattern) {
|
|
165
167
|
patterns.push(structurePattern);
|
|
166
168
|
}
|
|
@@ -228,7 +230,9 @@ class CompoundingEngineeringManager {
|
|
|
228
230
|
* Update compounded knowledge with new learning
|
|
229
231
|
*/
|
|
230
232
|
async updateCompoundedKnowledge(learning) {
|
|
231
|
-
this.knowledgeBase.learningsByCategory[learning.developmentPhase].push(
|
|
233
|
+
this.knowledgeBase.learningsByCategory[learning.developmentPhase].push(
|
|
234
|
+
learning
|
|
235
|
+
);
|
|
232
236
|
this.knowledgeBase.totalFeatures++;
|
|
233
237
|
await this.updateBestPractices(learning);
|
|
234
238
|
await this.updateMetrics(learning);
|
|
@@ -246,7 +250,9 @@ class CompoundingEngineeringManager {
|
|
|
246
250
|
* Generate automation hooks
|
|
247
251
|
*/
|
|
248
252
|
async generateHooks() {
|
|
249
|
-
const allOpportunities = Object.values(
|
|
253
|
+
const allOpportunities = Object.values(
|
|
254
|
+
this.knowledgeBase.learningsByCategory
|
|
255
|
+
).flat().flatMap((learning) => learning.automationOpportunities).filter((opp) => opp.implementation === "hook");
|
|
250
256
|
const hookCounts = /* @__PURE__ */ new Map();
|
|
251
257
|
for (const opp of allOpportunities) {
|
|
252
258
|
hookCounts.set(opp.task, (hookCounts.get(opp.task) || 0) + 1);
|
|
@@ -305,7 +311,9 @@ export async function ${hookName.replace(/-/g, "")}Hook() {
|
|
|
305
311
|
* Get current compounding metrics
|
|
306
312
|
*/
|
|
307
313
|
getCompoundingMetrics() {
|
|
308
|
-
const totalLearnings = Object.values(
|
|
314
|
+
const totalLearnings = Object.values(
|
|
315
|
+
this.knowledgeBase.learningsByCategory
|
|
316
|
+
).flat().length;
|
|
309
317
|
const automationLevel = this.knowledgeBase.automatedHooks.length / Math.max(totalLearnings, 1);
|
|
310
318
|
const recentLearnings = totalLearnings > 5 ? totalLearnings / 5 : totalLearnings;
|
|
311
319
|
return {
|
|
@@ -35,7 +35,9 @@ class ExtendedCoherenceManager {
|
|
|
35
35
|
*/
|
|
36
36
|
async startCoherenceSession(agentConfig, taskConfig, sessionConfig) {
|
|
37
37
|
const sessionId = uuidv4();
|
|
38
|
-
const defaultConfig = this.generateConfigForComplexity(
|
|
38
|
+
const defaultConfig = this.generateConfigForComplexity(
|
|
39
|
+
taskConfig.complexity
|
|
40
|
+
);
|
|
39
41
|
const config = { ...defaultConfig, ...sessionConfig };
|
|
40
42
|
const session = {
|
|
41
43
|
id: sessionId,
|
|
@@ -150,7 +152,11 @@ class ExtendedCoherenceManager {
|
|
|
150
152
|
duration: metrics.duration
|
|
151
153
|
});
|
|
152
154
|
if (overallCoherence < session.config.coherenceThreshold) {
|
|
153
|
-
await this.interventeInSession(
|
|
155
|
+
await this.interventeInSession(
|
|
156
|
+
session,
|
|
157
|
+
"coherence_degradation",
|
|
158
|
+
overallCoherence
|
|
159
|
+
);
|
|
154
160
|
}
|
|
155
161
|
const timeSinceCheckpoint = Date.now() - session.state.lastCheckpoint;
|
|
156
162
|
const checkpointDue = timeSinceCheckpoint > session.config.checkpointInterval * 60 * 1e3;
|
|
@@ -166,10 +172,16 @@ class ExtendedCoherenceManager {
|
|
|
166
172
|
const duration = (now - session.metrics[0]?.startTime || now) / (1e3 * 60);
|
|
167
173
|
const recentOutputs = await this.getRecentAgentOutputs(session);
|
|
168
174
|
const outputQuality = this.assessOutputQuality(recentOutputs);
|
|
169
|
-
const contextRetention = this.assessContextRetention(
|
|
175
|
+
const contextRetention = this.assessContextRetention(
|
|
176
|
+
recentOutputs,
|
|
177
|
+
session.task
|
|
178
|
+
);
|
|
170
179
|
const taskRelevance = this.assessTaskRelevance(recentOutputs, session.task);
|
|
171
180
|
const repetitionRate = this.calculateRepetitionRate(recentOutputs);
|
|
172
|
-
const divergenceRate = this.calculateDivergenceRate(
|
|
181
|
+
const divergenceRate = this.calculateDivergenceRate(
|
|
182
|
+
recentOutputs,
|
|
183
|
+
session.task
|
|
184
|
+
);
|
|
173
185
|
const errorRate = this.calculateErrorRate(recentOutputs);
|
|
174
186
|
const progressRate = this.calculateProgressRate(session);
|
|
175
187
|
return {
|
|
@@ -186,7 +198,9 @@ class ExtendedCoherenceManager {
|
|
|
186
198
|
errorRate,
|
|
187
199
|
memoryUsage: await this.getMemoryUsage(session),
|
|
188
200
|
contextWindowUsage: await this.getContextWindowUsage(session),
|
|
189
|
-
stateCheckpoints: session.interventions.filter(
|
|
201
|
+
stateCheckpoints: session.interventions.filter(
|
|
202
|
+
(i) => i.type === "checkpoint"
|
|
203
|
+
).length
|
|
190
204
|
};
|
|
191
205
|
}
|
|
192
206
|
/**
|
|
@@ -293,7 +307,9 @@ class ExtendedCoherenceManager {
|
|
|
293
307
|
* Restart session from last good checkpoint
|
|
294
308
|
*/
|
|
295
309
|
async restartSession(session) {
|
|
296
|
-
logger.info("Restarting session from checkpoint", {
|
|
310
|
+
logger.info("Restarting session from checkpoint", {
|
|
311
|
+
sessionId: session.id
|
|
312
|
+
});
|
|
297
313
|
const checkpoint = await this.loadLatestCheckpoint(session);
|
|
298
314
|
if (checkpoint) {
|
|
299
315
|
session.state = { ...checkpoint.state };
|
|
@@ -455,13 +471,20 @@ Begin your extended coherence work session now.
|
|
|
455
471
|
getCoherenceCapabilities() {
|
|
456
472
|
const activeSessions = Array.from(this.activeSessions.values());
|
|
457
473
|
return {
|
|
458
|
-
maxSessionDuration: Math.max(
|
|
459
|
-
|
|
474
|
+
maxSessionDuration: Math.max(
|
|
475
|
+
...activeSessions.map((s) => s.config.maxDuration)
|
|
476
|
+
),
|
|
477
|
+
activeSessionCount: activeSessions.filter(
|
|
478
|
+
(s) => s.state.status === "active"
|
|
479
|
+
).length,
|
|
460
480
|
averageCoherence: activeSessions.reduce((sum, s) => {
|
|
461
481
|
const recent = s.metrics.slice(-1)[0];
|
|
462
482
|
return sum + (recent ? this.calculateOverallCoherence(recent) : 0);
|
|
463
483
|
}, 0) / activeSessions.length,
|
|
464
|
-
totalInterventions: activeSessions.reduce(
|
|
484
|
+
totalInterventions: activeSessions.reduce(
|
|
485
|
+
(sum, s) => sum + s.interventions.length,
|
|
486
|
+
0
|
|
487
|
+
)
|
|
465
488
|
};
|
|
466
489
|
}
|
|
467
490
|
}
|
|
@@ -195,7 +195,9 @@ class GitWorkflowManager {
|
|
|
195
195
|
// Private helper methods
|
|
196
196
|
getCurrentBranch() {
|
|
197
197
|
try {
|
|
198
|
-
return execSync("git rev-parse --abbrev-ref HEAD", {
|
|
198
|
+
return execSync("git rev-parse --abbrev-ref HEAD", {
|
|
199
|
+
encoding: "utf8"
|
|
200
|
+
}).trim();
|
|
199
201
|
} catch (error) {
|
|
200
202
|
logger.warn("Failed to get current branch", error);
|
|
201
203
|
return "main";
|
|
@@ -229,7 +231,9 @@ class GitWorkflowManager {
|
|
|
229
231
|
createBranch(branchName) {
|
|
230
232
|
try {
|
|
231
233
|
try {
|
|
232
|
-
const currentBranch = execSync("git branch --show-current", {
|
|
234
|
+
const currentBranch = execSync("git branch --show-current", {
|
|
235
|
+
encoding: "utf8"
|
|
236
|
+
}).trim();
|
|
233
237
|
if (currentBranch === branchName) {
|
|
234
238
|
try {
|
|
235
239
|
execSync("git checkout main", { encoding: "utf8" });
|
|
@@ -238,17 +242,26 @@ class GitWorkflowManager {
|
|
|
238
242
|
}
|
|
239
243
|
}
|
|
240
244
|
try {
|
|
241
|
-
const worktrees = execSync("git worktree list --porcelain", {
|
|
245
|
+
const worktrees = execSync("git worktree list --porcelain", {
|
|
246
|
+
encoding: "utf8"
|
|
247
|
+
});
|
|
242
248
|
const lines = worktrees.split("\n");
|
|
243
249
|
for (let i = 0; i < lines.length; i++) {
|
|
244
250
|
if (lines[i].startsWith("branch ") && lines[i].includes(branchName)) {
|
|
245
251
|
const worktreetPath = lines[i - 1].replace("worktree ", "");
|
|
246
|
-
execSync(`git worktree remove --force "${worktreetPath}"`, {
|
|
247
|
-
|
|
252
|
+
execSync(`git worktree remove --force "${worktreetPath}"`, {
|
|
253
|
+
encoding: "utf8"
|
|
254
|
+
});
|
|
255
|
+
logger.info(
|
|
256
|
+
`Removed worktree at ${worktreetPath} for branch ${branchName}`
|
|
257
|
+
);
|
|
248
258
|
}
|
|
249
259
|
}
|
|
250
260
|
} catch (worktreeError) {
|
|
251
|
-
logger.warn(
|
|
261
|
+
logger.warn(
|
|
262
|
+
"Failed to check/remove worktrees",
|
|
263
|
+
worktreeError
|
|
264
|
+
);
|
|
252
265
|
}
|
|
253
266
|
execSync(`git branch -D ${branchName}`, { encoding: "utf8" });
|
|
254
267
|
logger.info(`Deleted existing branch ${branchName} for fresh start`);
|
|
@@ -257,7 +270,9 @@ class GitWorkflowManager {
|
|
|
257
270
|
execSync(`git checkout -b ${branchName}`, { encoding: "utf8" });
|
|
258
271
|
} catch (error) {
|
|
259
272
|
logger.error(`Failed to create branch ${branchName}`, error);
|
|
260
|
-
throw new GitWorkflowError(`Failed to create branch: ${branchName}`, {
|
|
273
|
+
throw new GitWorkflowError(`Failed to create branch: ${branchName}`, {
|
|
274
|
+
branchName
|
|
275
|
+
});
|
|
261
276
|
}
|
|
262
277
|
}
|
|
263
278
|
checkoutBranch(branchName) {
|
|
@@ -265,7 +280,9 @@ class GitWorkflowManager {
|
|
|
265
280
|
execSync(`git checkout ${branchName}`, { encoding: "utf8" });
|
|
266
281
|
} catch (error) {
|
|
267
282
|
logger.error(`Failed to checkout branch ${branchName}`, error);
|
|
268
|
-
throw new GitWorkflowError(`Failed to checkout branch: ${branchName}`, {
|
|
283
|
+
throw new GitWorkflowError(`Failed to checkout branch: ${branchName}`, {
|
|
284
|
+
branchName
|
|
285
|
+
});
|
|
269
286
|
}
|
|
270
287
|
}
|
|
271
288
|
branchExists(branchName) {
|
|
@@ -907,10 +907,15 @@ You are a PROJECT COORDINATOR. Your role is to:
|
|
|
907
907
|
await fs.rmdir(agent.workingDirectory, { recursive: true });
|
|
908
908
|
logger.debug(`Cleaned up working directory for agent ${agent.id}`);
|
|
909
909
|
} catch (error) {
|
|
910
|
-
logger.warn(
|
|
910
|
+
logger.warn(
|
|
911
|
+
`Could not clean up directory for agent ${agent.id}`,
|
|
912
|
+
error
|
|
913
|
+
);
|
|
911
914
|
}
|
|
912
915
|
}
|
|
913
|
-
await this.gitWorkflowManager.coordinateMerges(
|
|
916
|
+
await this.gitWorkflowManager.coordinateMerges(
|
|
917
|
+
Array.from(this.activeAgents.values())
|
|
918
|
+
);
|
|
914
919
|
this.activeAgents.clear();
|
|
915
920
|
this.swarmState = {
|
|
916
921
|
id: uuidv4(),
|
|
@@ -932,7 +937,10 @@ You are a PROJECT COORDINATOR. Your role is to:
|
|
|
932
937
|
logger.info("Swarm cleanup completed successfully");
|
|
933
938
|
} catch (error) {
|
|
934
939
|
logger.error("Failed to cleanup completed swarm", error);
|
|
935
|
-
throw new SwarmCoordinationError("Cleanup failed", {
|
|
940
|
+
throw new SwarmCoordinationError("Cleanup failed", {
|
|
941
|
+
swarmId: this.swarmState.id,
|
|
942
|
+
error
|
|
943
|
+
});
|
|
936
944
|
}
|
|
937
945
|
}
|
|
938
946
|
/**
|
|
@@ -958,14 +966,18 @@ You are a PROJECT COORDINATOR. Your role is to:
|
|
|
958
966
|
* Get swarm resource usage and cleanup recommendations
|
|
959
967
|
*/
|
|
960
968
|
getResourceUsage() {
|
|
961
|
-
const workingDirs = Array.from(this.activeAgents.values()).map(
|
|
969
|
+
const workingDirs = Array.from(this.activeAgents.values()).map(
|
|
970
|
+
(a) => a.workingDirectory
|
|
971
|
+
);
|
|
962
972
|
const memoryEstimate = this.activeAgents.size * 50;
|
|
963
973
|
const isStale = Date.now() - this.swarmState.startTime > 36e5;
|
|
964
974
|
const hasCompletedTasks = this.swarmState.completedTaskCount > 0 && this.swarmState.activeTaskCount === 0;
|
|
965
975
|
const recommendations = [];
|
|
966
976
|
let cleanupRecommended = false;
|
|
967
977
|
if (isStale) {
|
|
968
|
-
recommendations.push(
|
|
978
|
+
recommendations.push(
|
|
979
|
+
"Swarm has been running for over 1 hour - consider cleanup"
|
|
980
|
+
);
|
|
969
981
|
cleanupRecommended = true;
|
|
970
982
|
}
|
|
971
983
|
if (hasCompletedTasks) {
|