@stackmemoryai/stackmemory 1.2.2 → 1.2.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/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/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/integrations/linear/config.js +3 -1
- package/dist/src/integrations/linear/sync.js +18 -5
- 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 -1
- 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 +25 -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/tool-definitions.js +215 -1
- 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 +0 -102
- package/dist/src/utils/hook-installer.js +8 -0
- package/package.json +5 -5
- package/scripts/install-claude-hooks-auto.js +8 -0
- package/templates/claude-hooks/cord-trace.js +225 -0
- package/dist/src/core/config/storage-config.js +0 -114
- package/dist/src/core/storage/chromadb-adapter.js +0 -379
- package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
- 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
|
@@ -46,7 +46,10 @@ class StackMemoryContextLoader {
|
|
|
46
46
|
await sharedContextLayer.initialize();
|
|
47
47
|
const session = await sessionManager.getOrCreateSession({});
|
|
48
48
|
if (session.database) {
|
|
49
|
-
this.frameManager = new FrameManager(
|
|
49
|
+
this.frameManager = new FrameManager(
|
|
50
|
+
session.database,
|
|
51
|
+
session.projectId
|
|
52
|
+
);
|
|
50
53
|
this.contextRetriever = new ContextRetriever(session.database);
|
|
51
54
|
}
|
|
52
55
|
logger.info("Context loader initialized successfully");
|
|
@@ -115,17 +118,25 @@ class StackMemoryContextLoader {
|
|
|
115
118
|
totalTokens += sources[sources.length - 1].tokens;
|
|
116
119
|
}
|
|
117
120
|
const budgetedSources = this.budgetManager.allocateBudget({ sources });
|
|
118
|
-
const synthesizedContext = this.synthesizeContext(
|
|
121
|
+
const synthesizedContext = this.synthesizeContext(
|
|
122
|
+
budgetedSources.sources
|
|
123
|
+
);
|
|
119
124
|
logger.info("Context loaded successfully", {
|
|
120
125
|
totalSources: sources.length,
|
|
121
126
|
totalTokens,
|
|
122
|
-
budgetedTokens: budgetedSources.sources.reduce(
|
|
127
|
+
budgetedTokens: budgetedSources.sources.reduce(
|
|
128
|
+
(sum, s) => sum + s.tokens,
|
|
129
|
+
0
|
|
130
|
+
)
|
|
123
131
|
});
|
|
124
132
|
return {
|
|
125
133
|
context: synthesizedContext,
|
|
126
134
|
sources: budgetedSources.sources,
|
|
127
135
|
metadata: {
|
|
128
|
-
totalTokens: budgetedSources.sources.reduce(
|
|
136
|
+
totalTokens: budgetedSources.sources.reduce(
|
|
137
|
+
(sum, s) => sum + s.tokens,
|
|
138
|
+
0
|
|
139
|
+
),
|
|
129
140
|
sourcesCount: budgetedSources.sources.length,
|
|
130
141
|
patterns: request.usePatterns ? patterns : [],
|
|
131
142
|
similarTasks: request.useSimilarTasks ? similarTasks : []
|
|
@@ -144,16 +155,22 @@ class StackMemoryContextLoader {
|
|
|
144
155
|
return [];
|
|
145
156
|
}
|
|
146
157
|
try {
|
|
147
|
-
const searchResults = await this.contextRetriever.search(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
const searchResults = await this.contextRetriever.search(
|
|
159
|
+
taskDescription,
|
|
160
|
+
{
|
|
161
|
+
maxResults: 10,
|
|
162
|
+
types: ["task", "subtask"],
|
|
163
|
+
timeFilter: {
|
|
164
|
+
days: this.config.lookbackDays
|
|
165
|
+
}
|
|
152
166
|
}
|
|
153
|
-
|
|
167
|
+
);
|
|
154
168
|
const similarities = [];
|
|
155
169
|
for (const result of searchResults) {
|
|
156
|
-
const similarity = this.calculateTaskSimilarity(
|
|
170
|
+
const similarity = this.calculateTaskSimilarity(
|
|
171
|
+
taskDescription,
|
|
172
|
+
result.content
|
|
173
|
+
);
|
|
157
174
|
if (similarity >= this.config.similarityThreshold) {
|
|
158
175
|
similarities.push({
|
|
159
176
|
frameId: result.frameId,
|
|
@@ -184,7 +201,10 @@ class StackMemoryContextLoader {
|
|
|
184
201
|
if (!context) return [];
|
|
185
202
|
const relevantPatterns = [];
|
|
186
203
|
for (const pattern of context.globalPatterns) {
|
|
187
|
-
const relevance = this.calculatePatternRelevance(
|
|
204
|
+
const relevance = this.calculatePatternRelevance(
|
|
205
|
+
taskDescription,
|
|
206
|
+
pattern.pattern
|
|
207
|
+
);
|
|
188
208
|
if (relevance >= 0.5) {
|
|
189
209
|
relevantPatterns.push({
|
|
190
210
|
pattern: pattern.pattern,
|
|
@@ -197,7 +217,9 @@ class StackMemoryContextLoader {
|
|
|
197
217
|
});
|
|
198
218
|
}
|
|
199
219
|
}
|
|
200
|
-
return relevantPatterns.sort(
|
|
220
|
+
return relevantPatterns.sort(
|
|
221
|
+
(a, b) => b.relevance * Math.log(b.frequency + 1) - a.relevance * Math.log(a.frequency + 1)
|
|
222
|
+
).slice(0, 8);
|
|
201
223
|
} catch (error) {
|
|
202
224
|
logger.error("Failed to extract patterns", error);
|
|
203
225
|
return [];
|
|
@@ -270,12 +292,14 @@ class StackMemoryContextLoader {
|
|
|
270
292
|
const contextParts = [];
|
|
271
293
|
contextParts.push("Similar tasks from history:");
|
|
272
294
|
for (const sim of similarities) {
|
|
273
|
-
contextParts.push(
|
|
295
|
+
contextParts.push(
|
|
296
|
+
`
|
|
274
297
|
Task: ${sim.task}
|
|
275
298
|
Outcome: ${sim.outcome}
|
|
276
299
|
Similarity: ${Math.round(sim.similarity * 100)}%
|
|
277
300
|
${sim.outcome === "success" ? "\u2705 Successfully completed" : "\u274C Had issues"}
|
|
278
|
-
`.trim()
|
|
301
|
+
`.trim()
|
|
302
|
+
);
|
|
279
303
|
}
|
|
280
304
|
return contextParts.join("\n\n");
|
|
281
305
|
}
|
|
@@ -286,13 +310,15 @@ ${sim.outcome === "success" ? "\u2705 Successfully completed" : "\u274C Had issu
|
|
|
286
310
|
const contextParts = [];
|
|
287
311
|
contextParts.push("Relevant patterns from experience:");
|
|
288
312
|
for (const pattern of patterns2) {
|
|
289
|
-
contextParts.push(
|
|
313
|
+
contextParts.push(
|
|
314
|
+
`
|
|
290
315
|
Pattern: ${pattern.pattern}
|
|
291
316
|
Type: ${pattern.type}
|
|
292
317
|
Frequency: ${pattern.frequency} occurrences
|
|
293
318
|
${pattern.resolution ? `Resolution: ${pattern.resolution}` : ""}
|
|
294
319
|
Relevance: ${Math.round(pattern.relevance * 100)}%
|
|
295
|
-
`.trim()
|
|
320
|
+
`.trim()
|
|
321
|
+
);
|
|
296
322
|
}
|
|
297
323
|
return contextParts.join("\n\n");
|
|
298
324
|
}
|
|
@@ -303,11 +329,13 @@ Relevance: ${Math.round(pattern.relevance * 100)}%
|
|
|
303
329
|
const contextParts = [];
|
|
304
330
|
contextParts.push("Recent successful decisions:");
|
|
305
331
|
for (const decision of decisions) {
|
|
306
|
-
contextParts.push(
|
|
332
|
+
contextParts.push(
|
|
333
|
+
`
|
|
307
334
|
Decision: ${decision.decision}
|
|
308
335
|
Reasoning: ${decision.reasoning}
|
|
309
336
|
Date: ${new Date(decision.timestamp).toLocaleDateString()}
|
|
310
|
-
`.trim()
|
|
337
|
+
`.trim()
|
|
338
|
+
);
|
|
311
339
|
}
|
|
312
340
|
return contextParts.join("\n\n");
|
|
313
341
|
}
|
|
@@ -322,11 +350,15 @@ Date: ${new Date(decision.timestamp).toLocaleDateString()}
|
|
|
322
350
|
contextParts.push("Context from StackMemory:");
|
|
323
351
|
const sortedSources = sources.sort((a, b) => b.weight - a.weight);
|
|
324
352
|
for (const source of sortedSources) {
|
|
325
|
-
contextParts.push(
|
|
326
|
-
|
|
353
|
+
contextParts.push(
|
|
354
|
+
`
|
|
355
|
+
--- ${source.type.replace("_", " ").toUpperCase()} ---`
|
|
356
|
+
);
|
|
327
357
|
contextParts.push(source.content);
|
|
328
358
|
}
|
|
329
|
-
contextParts.push(
|
|
359
|
+
contextParts.push(
|
|
360
|
+
"\nUse this context to inform your approach to the current task."
|
|
361
|
+
);
|
|
330
362
|
return contextParts.join("\n");
|
|
331
363
|
}
|
|
332
364
|
/**
|
|
@@ -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
|
}
|