@stackmemoryai/stackmemory 1.2.1 → 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.
Files changed (100) hide show
  1. package/dist/src/cli/codex-sm.js +6 -8
  2. package/dist/src/cli/commands/config.js +0 -81
  3. package/dist/src/cli/commands/context-rehydrate.js +133 -47
  4. package/dist/src/cli/commands/db.js +35 -8
  5. package/dist/src/cli/commands/handoff.js +1 -1
  6. package/dist/src/cli/commands/linear.js +9 -0
  7. package/dist/src/cli/commands/ralph.js +2 -2
  8. package/dist/src/cli/commands/setup.js +2 -2
  9. package/dist/src/cli/commands/signup.js +3 -1
  10. package/dist/src/cli/commands/skills.js +123 -1
  11. package/dist/src/cli/commands/storage-tier.js +26 -8
  12. package/dist/src/cli/index.js +1 -57
  13. package/dist/src/core/config/feature-flags.js +0 -4
  14. package/dist/src/core/context/dual-stack-manager.js +10 -3
  15. package/dist/src/core/context/frame-database.js +32 -0
  16. package/dist/src/core/context/frame-handoff-manager.js +2 -2
  17. package/dist/src/core/context/{refactored-frame-manager.js → frame-manager.js} +3 -3
  18. package/dist/src/core/context/index.js +2 -2
  19. package/dist/src/core/database/sqlite-adapter.js +161 -1
  20. package/dist/src/core/digest/frame-digest-integration.js +1 -1
  21. package/dist/src/core/digest/index.js +1 -1
  22. package/dist/src/core/execution/parallel-executor.js +5 -1
  23. package/dist/src/core/projects/project-isolation.js +18 -4
  24. package/dist/src/core/security/index.js +2 -0
  25. package/dist/src/core/security/input-sanitizer.js +23 -0
  26. package/dist/src/core/utils/update-checker.js +10 -6
  27. package/dist/src/daemon/daemon-config.js +2 -1
  28. package/dist/src/daemon/services/auto-save-service.js +121 -0
  29. package/dist/src/daemon/services/maintenance-service.js +76 -1
  30. package/dist/src/features/sweep/prompt-builder.js +2 -2
  31. package/dist/src/hooks/graphiti-hooks.js +149 -0
  32. package/dist/src/hooks/session-summary.js +30 -0
  33. package/dist/src/integrations/graphiti/linear-graphiti-bridge.js +115 -0
  34. package/dist/src/integrations/greptile/client.js +101 -0
  35. package/dist/src/integrations/greptile/config.js +14 -0
  36. package/dist/src/integrations/greptile/index.js +11 -0
  37. package/dist/src/integrations/greptile/types.js +4 -0
  38. package/dist/src/integrations/linear/config.js +3 -1
  39. package/dist/src/integrations/linear/sync.js +18 -5
  40. package/dist/src/integrations/linear/webhook.js +16 -0
  41. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +33 -7
  42. package/dist/src/integrations/mcp/handlers/cord-handlers.js +397 -0
  43. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +456 -0
  44. package/dist/src/integrations/mcp/handlers/index.js +55 -1
  45. package/dist/src/integrations/mcp/handlers/task-handlers.js +55 -12
  46. package/dist/src/integrations/mcp/handlers/team-handlers.js +211 -0
  47. package/dist/src/integrations/mcp/handlers/trace-handlers.js +25 -9
  48. package/dist/src/integrations/mcp/index.js +2 -2
  49. package/dist/src/integrations/mcp/refactored-server.js +31 -10
  50. package/dist/src/integrations/mcp/server.js +27 -0
  51. package/dist/src/integrations/mcp/tool-definitions.js +215 -1
  52. package/dist/src/integrations/ralph/context/context-budget-manager.js +10 -2
  53. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +54 -22
  54. package/dist/src/integrations/ralph/learning/pattern-learner.js +59 -24
  55. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +81 -35
  56. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +12 -4
  57. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +32 -9
  58. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +25 -8
  59. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +17 -5
  60. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +73 -22
  61. package/dist/src/skills/claude-skills.js +46 -103
  62. package/dist/src/skills/parallel-agent-skill.js +514 -0
  63. package/dist/src/utils/hook-installer.js +8 -0
  64. package/package.json +5 -5
  65. package/scripts/gepa/.before-optimize.md +140 -159
  66. package/scripts/gepa/config.json +7 -1
  67. package/scripts/gepa/evals/fixtures/api-endpoint.ts +31 -0
  68. package/scripts/gepa/evals/fixtures/brittle-integration.ts +38 -0
  69. package/scripts/gepa/evals/fixtures/fts5-triggers.sql +23 -0
  70. package/scripts/gepa/evals/fixtures/leaky-service.ts +70 -0
  71. package/scripts/gepa/evals/fixtures/mcp-dispatch-stub.ts +39 -0
  72. package/scripts/gepa/evals/fixtures/pr-diff.txt +24 -0
  73. package/scripts/gepa/evals/fixtures/unsafe-webhook.ts +34 -0
  74. package/scripts/gepa/evals/fixtures/unwrapped-db-op.ts +42 -0
  75. package/scripts/gepa/evals/stackmemory-tasks.jsonl +8 -0
  76. package/scripts/gepa/generations/gen-000/baseline.md +172 -159
  77. package/scripts/gepa/generations/gen-001/baseline.md +172 -159
  78. package/scripts/gepa/generations/gen-001/variant-a.md +156 -146
  79. package/scripts/gepa/generations/gen-001/variant-b.md +199 -170
  80. package/scripts/gepa/generations/gen-001/variant-c.md +127 -46
  81. package/scripts/gepa/generations/gen-001/variant-d.md +160 -107
  82. package/scripts/gepa/hooks/reflect.js +44 -5
  83. package/scripts/gepa/optimize.js +281 -39
  84. package/scripts/gepa/results/eval-1-baseline.json +187 -10
  85. package/scripts/gepa/results/eval-1-variant-a.json +188 -11
  86. package/scripts/gepa/results/eval-1-variant-b.json +188 -11
  87. package/scripts/gepa/results/eval-1-variant-c.json +168 -11
  88. package/scripts/gepa/results/eval-1-variant-d.json +169 -12
  89. package/scripts/gepa/state.json +18 -18
  90. package/scripts/install-claude-hooks-auto.js +8 -0
  91. package/templates/claude-hooks/cord-trace.js +225 -0
  92. package/dist/src/core/config/storage-config.js +0 -114
  93. package/dist/src/core/storage/chromadb-adapter.js +0 -379
  94. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
  95. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +0 -409
  96. package/dist/src/skills/repo-ingestion-skill.js +0 -631
  97. package/templates/claude-hooks/chromadb-wrapper +0 -21
  98. /package/dist/src/core/context/{enhanced-rehydration.js → rehydration.js} +0 -0
  99. /package/dist/src/core/digest/{enhanced-hybrid-digest.js → hybrid-digest.js} +0 -0
  100. /package/dist/src/core/session/{enhanced-handoff.js → handoff.js} +0 -0
@@ -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(session.database, session.projectId);
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((task) => this.executeParallelTask(task, execution));
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((r) => r.success) ? "success" : "partial";
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
- id: uuidv4(),
116
- title: description,
117
- description,
118
- criteria,
119
- priority: 1,
120
- estimatedIterations: 3,
121
- dependencies: [],
122
- type: "single"
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((c) => c.toLowerCase().includes("function") || c.toLowerCase().includes("implement")),
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
- id: uuidv4(),
177
- title: description,
178
- description,
179
- criteria,
180
- priority: 1,
181
- estimatedIterations: Math.min(8, Math.max(3, complexity.score)),
182
- dependencies: [],
183
- type: "single"
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(`Executing phase ${phase.id} with ${phase.tasks.length} tasks`);
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({ loopId: taskResult.loopId, error: taskResult.error || "Unknown error" });
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({ loopId: loopResult.loopId, error: loopResult.error || "Unknown error" });
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 { success: false, loopId: taskBreakdown.id, error: error.message };
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: { phases: [], totalEstimatedTime: 0, parallelizable: false },
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", { orchestrationId: orchestratedTask.id, loopId: loopResult.loopId });
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(`Average loop duration: ${Math.round(avgLoopDuration / 1e3)}s`);
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("Complex task benefited from breakdown into multiple loops");
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 = ["project", "initialize", "setup", "scaffold", "create structure"];
382
- return setupKeywords.some((keyword) => description.toLowerCase().includes(keyword));
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((s) => s.toLowerCase().includes("implement") || s.toLowerCase().includes("create") || s.toLowerCase().includes("add")) || null;
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(sessionData.codeStructure);
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(learning);
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(this.knowledgeBase.learningsByCategory).flat().flatMap((learning) => learning.automationOpportunities).filter((opp) => opp.implementation === "hook");
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(this.knowledgeBase.learningsByCategory).flat().length;
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(taskConfig.complexity);
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(session, "coherence_degradation", overallCoherence);
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(recentOutputs, session.task);
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(recentOutputs, session.task);
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((i) => i.type === "checkpoint").length
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", { sessionId: session.id });
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(...activeSessions.map((s) => s.config.maxDuration)),
459
- activeSessionCount: activeSessions.filter((s) => s.state.status === "active").length,
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((sum, s) => sum + s.interventions.length, 0)
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", { encoding: "utf8" }).trim();
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", { encoding: "utf8" }).trim();
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", { encoding: "utf8" });
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}"`, { encoding: "utf8" });
247
- logger.info(`Removed worktree at ${worktreetPath} for branch ${branchName}`);
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("Failed to check/remove worktrees", worktreeError);
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}`, { 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}`, { 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(`Could not clean up directory for agent ${agent.id}`, error);
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(Array.from(this.activeAgents.values()));
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", { swarmId: this.swarmState.id, error });
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((a) => a.workingDirectory);
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("Swarm has been running for over 1 hour - consider cleanup");
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) {
@@ -27,7 +27,10 @@ class RalphDebugger {
27
27
  await sessionManager.initialize();
28
28
  const session = await sessionManager.getOrCreateSession({});
29
29
  if (session.database) {
30
- this.frameManager = new FrameManager(session.database, session.projectId);
30
+ this.frameManager = new FrameManager(
31
+ session.database,
32
+ session.projectId
33
+ );
31
34
  }
32
35
  logger.info("Debugger initialized successfully");
33
36
  } catch (error) {
@@ -111,7 +114,10 @@ class RalphDebugger {
111
114
  contextSize: iter.contextSize,
112
115
  phase: iter.phase
113
116
  })),
114
- totalDuration: session.performance.iterationTimes.reduce((sum, time) => sum + time, 0)
117
+ totalDuration: session.performance.iterationTimes.reduce(
118
+ (sum, time) => sum + time,
119
+ 0
120
+ )
115
121
  };
116
122
  const html = await this.generateTimelineHTML(timeline);
117
123
  const timelinePath = path.join(".ralph-debug", `timeline-${loopId}.html`);
@@ -165,7 +171,10 @@ class RalphDebugger {
165
171
  diagram.metrics = {
166
172
  totalNodes: diagram.nodes.length,
167
173
  totalEdges: diagram.edges.length,
168
- avgContextSize: session.performance.contextSizes.length > 0 ? session.performance.contextSizes.reduce((sum, size) => sum + size, 0) / session.performance.contextSizes.length : 0,
174
+ avgContextSize: session.performance.contextSizes.length > 0 ? session.performance.contextSizes.reduce(
175
+ (sum, size) => sum + size,
176
+ 0
177
+ ) / session.performance.contextSizes.length : 0,
169
178
  maxContextSize: Math.max(...session.performance.contextSizes)
170
179
  };
171
180
  return diagram;
@@ -230,15 +239,24 @@ class RalphDebugger {
230
239
  async updatePerformanceMetrics(session) {
231
240
  const currentMemory = process.memoryUsage().heapUsed;
232
241
  session.performance.memoryUsage.push(currentMemory);
233
- session.performance.peakMemory = Math.max(session.performance.peakMemory, currentMemory);
242
+ session.performance.peakMemory = Math.max(
243
+ session.performance.peakMemory,
244
+ currentMemory
245
+ );
234
246
  const contextSize = await this.calculateContextSize(session.ralphDir);
235
247
  session.performance.contextSizes.push(contextSize);
236
248
  if (session.performance.iterationTimes.length > 0) {
237
- session.performance.averageIterationTime = session.performance.iterationTimes.reduce((sum, time) => sum + time, 0) / session.performance.iterationTimes.length;
249
+ session.performance.averageIterationTime = session.performance.iterationTimes.reduce(
250
+ (sum, time) => sum + time,
251
+ 0
252
+ ) / session.performance.iterationTimes.length;
238
253
  }
239
254
  if (session.performance.contextSizes.length > 0) {
240
255
  const avgContextSize = session.performance.contextSizes.reduce((sum, size) => sum + size, 0) / session.performance.contextSizes.length;
241
- session.performance.contextEfficiency = Math.max(0, 1 - avgContextSize / 1e4);
256
+ session.performance.contextEfficiency = Math.max(
257
+ 0,
258
+ 1 - avgContextSize / 1e4
259
+ );
242
260
  }
243
261
  }
244
262
  /**
@@ -246,8 +264,13 @@ class RalphDebugger {
246
264
  */
247
265
  async generateSummary(session) {
248
266
  const totalIterations = session.iterations.length;
249
- const successfulIterations = session.iterations.filter((i) => i.success).length;
250
- const totalDuration = session.performance.iterationTimes.reduce((sum, time) => sum + time, 0);
267
+ const successfulIterations = session.iterations.filter(
268
+ (i) => i.success
269
+ ).length;
270
+ const totalDuration = session.performance.iterationTimes.reduce(
271
+ (sum, time) => sum + time,
272
+ 0
273
+ );
251
274
  return {
252
275
  loopId: session.loopId,
253
276
  totalIterations,
@@ -271,18 +294,26 @@ class RalphDebugger {
271
294
  const avgDuration = durations.reduce((sum, d) => sum + d, 0) / durations.length;
272
295
  if (durations.some((d) => d > avgDuration * 2)) {
273
296
  patterns.push("Variable iteration times detected");
274
- insights.push("Some iterations took significantly longer than average - investigate bottlenecks");
297
+ insights.push(
298
+ "Some iterations took significantly longer than average - investigate bottlenecks"
299
+ );
275
300
  }
276
- const consecutiveFailures = this.findConsecutiveFailures(session.iterations);
301
+ const consecutiveFailures = this.findConsecutiveFailures(
302
+ session.iterations
303
+ );
277
304
  if (consecutiveFailures.length > 2) {
278
305
  patterns.push("Multiple consecutive failures detected");
279
- insights.push("Consider adjusting approach or criteria after consecutive failures");
306
+ insights.push(
307
+ "Consider adjusting approach or criteria after consecutive failures"
308
+ );
280
309
  }
281
310
  if (session.performance.contextSizes.length > 1) {
282
311
  const contextGrowth = session.performance.contextSizes[session.performance.contextSizes.length - 1] - session.performance.contextSizes[0];
283
312
  if (contextGrowth > 1e3) {
284
313
  patterns.push("Significant context growth");
285
- insights.push("Context is growing rapidly - consider context pruning strategies");
314
+ insights.push(
315
+ "Context is growing rapidly - consider context pruning strategies"
316
+ );
286
317
  }
287
318
  }
288
319
  return { patterns, insights };
@@ -292,9 +323,14 @@ class RalphDebugger {
292
323
  */
293
324
  async analyzeContextFlow(session) {
294
325
  return {
295
- avgContextSize: session.performance.contextSizes.length > 0 ? session.performance.contextSizes.reduce((sum, size) => sum + size, 0) / session.performance.contextSizes.length : 0,
326
+ avgContextSize: session.performance.contextSizes.length > 0 ? session.performance.contextSizes.reduce(
327
+ (sum, size) => sum + size,
328
+ 0
329
+ ) / session.performance.contextSizes.length : 0,
296
330
  maxContextSize: Math.max(...session.performance.contextSizes),
297
- contextGrowthRate: this.calculateGrowthRate(session.performance.contextSizes),
331
+ contextGrowthRate: this.calculateGrowthRate(
332
+ session.performance.contextSizes
333
+ ),
298
334
  efficiency: session.performance.contextEfficiency
299
335
  };
300
336
  }
@@ -303,7 +339,9 @@ class RalphDebugger {
303
339
  */
304
340
  async analyzePerformance(session) {
305
341
  return {
306
- memoryEfficiency: this.calculateMemoryEfficiency(session.performance.memoryUsage),
342
+ memoryEfficiency: this.calculateMemoryEfficiency(
343
+ session.performance.memoryUsage
344
+ ),
307
345
  iterationEfficiency: session.performance.averageIterationTime,
308
346
  resourceUtilization: {
309
347
  cpu: "N/A",
@@ -318,7 +356,10 @@ class RalphDebugger {
318
356
  */
319
357
  async generateVisualization(session) {
320
358
  const htmlContent = await this.generateVisualizationHTML(session);
321
- const vizPath = path.join(".ralph-debug", `visualization-${session.loopId}.html`);
359
+ const vizPath = path.join(
360
+ ".ralph-debug",
361
+ `visualization-${session.loopId}.html`
362
+ );
322
363
  await fs.mkdir(path.dirname(vizPath), { recursive: true });
323
364
  await fs.writeFile(vizPath, htmlContent);
324
365
  return {
@@ -343,17 +384,25 @@ class RalphDebugger {
343
384
  async generateRecommendations(session) {
344
385
  const recommendations = [];
345
386
  if (session.performance.averageIterationTime > 3e4) {
346
- recommendations.push("Consider breaking down complex tasks into smaller iterations");
387
+ recommendations.push(
388
+ "Consider breaking down complex tasks into smaller iterations"
389
+ );
347
390
  }
348
391
  if (session.performance.contextEfficiency < 0.7) {
349
- recommendations.push("Optimize context management - consider using context budgeting");
392
+ recommendations.push(
393
+ "Optimize context management - consider using context budgeting"
394
+ );
350
395
  }
351
396
  const successRate = session.iterations.filter((i) => i.success).length / Math.max(1, session.iterations.length);
352
397
  if (successRate < 0.5) {
353
- recommendations.push("Low success rate detected - review task criteria and approach");
398
+ recommendations.push(
399
+ "Low success rate detected - review task criteria and approach"
400
+ );
354
401
  }
355
402
  if (session.performance.peakMemory > 500 * 1024 * 1024) {
356
- recommendations.push("High memory usage detected - investigate memory leaks");
403
+ recommendations.push(
404
+ "High memory usage detected - investigate memory leaks"
405
+ );
357
406
  }
358
407
  return recommendations;
359
408
  }
@@ -450,14 +499,16 @@ class RalphDebugger {
450
499
  <body>
451
500
  <h1>${timeline.title}</h1>
452
501
  <div class="timeline">
453
- ${timeline.iterations.map((iter) => `
502
+ ${timeline.iterations.map(
503
+ (iter) => `
454
504
  <div class="iteration ${iter.success ? "success" : "failure"}">
455
505
  <h3>Iteration ${iter.iteration}</h3>
456
506
  <p>Duration: ${iter.duration}ms</p>
457
507
  <p>Changes: ${iter.changes} | Errors: ${iter.errors}</p>
458
508
  <p>Context Size: ${iter.contextSize}</p>
459
509
  </div>
460
- `).join("")}
510
+ `
511
+ ).join("")}
461
512
  </div>
462
513
  </body>
463
514
  </html>