@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
|
@@ -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) {
|
|
@@ -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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
250
|
-
|
|
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(
|
|
297
|
+
insights.push(
|
|
298
|
+
"Some iterations took significantly longer than average - investigate bottlenecks"
|
|
299
|
+
);
|
|
275
300
|
}
|
|
276
|
-
const consecutiveFailures = this.findConsecutiveFailures(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
`
|
|
510
|
+
`
|
|
511
|
+
).join("")}
|
|
461
512
|
</div>
|
|
462
513
|
</body>
|
|
463
514
|
</html>
|
|
@@ -3,9 +3,6 @@ import { dirname as __pathDirname } from 'path';
|
|
|
3
3
|
const __filename = __fileURLToPath(import.meta.url);
|
|
4
4
|
const __dirname = __pathDirname(__filename);
|
|
5
5
|
import { logger } from "../core/monitoring/logger.js";
|
|
6
|
-
import {
|
|
7
|
-
RepoIngestionSkill
|
|
8
|
-
} from "./repo-ingestion-skill.js";
|
|
9
6
|
import {
|
|
10
7
|
RecursiveAgentOrchestrator
|
|
11
8
|
} from "./recursive-agent-orchestrator.js";
|
|
@@ -617,22 +614,6 @@ class ClaudeSkillsManager {
|
|
|
617
614
|
this.dashboardLauncher = new module.DashboardLauncherSkill();
|
|
618
615
|
logger.info("Dashboard launcher initialized (manual launch required)");
|
|
619
616
|
});
|
|
620
|
-
const chromaConfig = {
|
|
621
|
-
apiKey: process.env["CHROMADB_API_KEY"] || "",
|
|
622
|
-
tenant: process.env["CHROMADB_TENANT"] || "",
|
|
623
|
-
database: process.env["CHROMADB_DATABASE"] || "stackmemory",
|
|
624
|
-
collectionName: process.env["CHROMADB_COLLECTION"] || "stackmemory_repos"
|
|
625
|
-
};
|
|
626
|
-
if (chromaConfig.apiKey && chromaConfig.tenant) {
|
|
627
|
-
this.repoIngestionSkill = new RepoIngestionSkill(
|
|
628
|
-
chromaConfig,
|
|
629
|
-
context.userId,
|
|
630
|
-
process.env["CHROMADB_TEAM_ID"]
|
|
631
|
-
);
|
|
632
|
-
this.repoIngestionSkill.initialize().catch((error) => {
|
|
633
|
-
logger.warn("Repo ingestion skill initialization failed:", error);
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
617
|
import("../features/tasks/linear-task-manager.js").then((module) => {
|
|
637
618
|
const taskStore = new module.LinearTaskManager();
|
|
638
619
|
const frameManager = context.frameManager;
|
|
@@ -662,7 +643,6 @@ class ClaudeSkillsManager {
|
|
|
662
643
|
checkpointSkill;
|
|
663
644
|
archaeologistSkill;
|
|
664
645
|
dashboardLauncher;
|
|
665
|
-
repoIngestionSkill = null;
|
|
666
646
|
rlmOrchestrator = null;
|
|
667
647
|
apiSkill;
|
|
668
648
|
specGeneratorSkill;
|
|
@@ -738,64 +718,6 @@ class ClaudeSkillsManager {
|
|
|
738
718
|
};
|
|
739
719
|
}
|
|
740
720
|
return this.rlmOrchestrator.execute(args[0], options);
|
|
741
|
-
case "repo":
|
|
742
|
-
case "ingest":
|
|
743
|
-
if (!this.repoIngestionSkill) {
|
|
744
|
-
return {
|
|
745
|
-
success: false,
|
|
746
|
-
message: "Repo ingestion skill not initialized. Please configure ChromaDB."
|
|
747
|
-
};
|
|
748
|
-
}
|
|
749
|
-
const repoCommand = args[0];
|
|
750
|
-
switch (repoCommand) {
|
|
751
|
-
case "ingest":
|
|
752
|
-
const repoPath = args[1] || process.cwd();
|
|
753
|
-
const repoName = args[2] || path.basename(repoPath);
|
|
754
|
-
return await this.repoIngestionSkill.ingestRepository(
|
|
755
|
-
repoPath,
|
|
756
|
-
repoName,
|
|
757
|
-
options
|
|
758
|
-
);
|
|
759
|
-
case "update":
|
|
760
|
-
const updatePath = args[1] || process.cwd();
|
|
761
|
-
const updateName = args[2] || path.basename(updatePath);
|
|
762
|
-
return await this.repoIngestionSkill.updateRepository(
|
|
763
|
-
updatePath,
|
|
764
|
-
updateName,
|
|
765
|
-
options
|
|
766
|
-
);
|
|
767
|
-
case "search":
|
|
768
|
-
const query = args[1];
|
|
769
|
-
if (!query) {
|
|
770
|
-
return {
|
|
771
|
-
success: false,
|
|
772
|
-
message: "Search query required"
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
const results = await this.repoIngestionSkill.searchCode(query, {
|
|
776
|
-
repoName: options?.repoName,
|
|
777
|
-
language: options?.language,
|
|
778
|
-
limit: options?.limit,
|
|
779
|
-
includeContext: options?.includeContext
|
|
780
|
-
});
|
|
781
|
-
return {
|
|
782
|
-
success: true,
|
|
783
|
-
message: `Found ${results.length} results`,
|
|
784
|
-
data: results
|
|
785
|
-
};
|
|
786
|
-
case "stats":
|
|
787
|
-
const stats = await this.repoIngestionSkill.getRepoStats(args[1]);
|
|
788
|
-
return {
|
|
789
|
-
success: true,
|
|
790
|
-
message: "Repository statistics",
|
|
791
|
-
data: stats
|
|
792
|
-
};
|
|
793
|
-
default:
|
|
794
|
-
return {
|
|
795
|
-
success: false,
|
|
796
|
-
message: `Unknown repo command: ${repoCommand}. Use: ingest, update, search, or stats`
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
721
|
case "dashboard":
|
|
800
722
|
const dashboardCmd = args[0];
|
|
801
723
|
if (!this.dashboardLauncher) {
|
|
@@ -1011,9 +933,6 @@ class ClaudeSkillsManager {
|
|
|
1011
933
|
"spec",
|
|
1012
934
|
"agent"
|
|
1013
935
|
];
|
|
1014
|
-
if (this.repoIngestionSkill) {
|
|
1015
|
-
skills.push("repo");
|
|
1016
|
-
}
|
|
1017
936
|
if (this.rlmOrchestrator) {
|
|
1018
937
|
skills.push("rlm", "lint");
|
|
1019
938
|
}
|
|
@@ -1097,27 +1016,6 @@ Launch the StackMemory web dashboard for real-time monitoring
|
|
|
1097
1016
|
- launch: Start the web dashboard and open in browser (default)
|
|
1098
1017
|
- stop: Stop the dashboard server
|
|
1099
1018
|
Auto-launches on new sessions when configured
|
|
1100
|
-
`;
|
|
1101
|
-
case "repo":
|
|
1102
|
-
return `
|
|
1103
|
-
/repo ingest [path] [name] [--incremental] [--include-tests] [--include-docs]
|
|
1104
|
-
/repo update [path] [name] [--force-update]
|
|
1105
|
-
/repo search "query" [--repo-name name] [--language lang] [--limit n]
|
|
1106
|
-
/repo stats [repo-name]
|
|
1107
|
-
|
|
1108
|
-
Ingest and search code repositories in ChromaDB:
|
|
1109
|
-
- ingest: Index a new repository (defaults to current directory)
|
|
1110
|
-
- update: Update an existing repository with changes
|
|
1111
|
-
- search: Semantic search across ingested code
|
|
1112
|
-
- stats: View statistics about ingested repositories
|
|
1113
|
-
|
|
1114
|
-
Options:
|
|
1115
|
-
- --incremental: Only process changed files
|
|
1116
|
-
- --include-tests: Include test files in indexing
|
|
1117
|
-
- --include-docs: Include documentation files
|
|
1118
|
-
- --force-update: Force re-indexing of all files
|
|
1119
|
-
- --language: Filter search by programming language
|
|
1120
|
-
- --limit: Maximum search results (default: 20)
|
|
1121
1019
|
`;
|
|
1122
1020
|
case "recursive":
|
|
1123
1021
|
return `
|
|
@@ -31,6 +31,14 @@ const CANONICAL_HOOKS = [
|
|
|
31
31
|
timeout: 2,
|
|
32
32
|
commandPrefix: "node",
|
|
33
33
|
required: true
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
scriptName: "cord-trace.js",
|
|
37
|
+
eventType: "PostToolUse",
|
|
38
|
+
matcher: "mcp__.*__cord_(spawn|fork|complete|ask|tree)",
|
|
39
|
+
timeout: 2,
|
|
40
|
+
commandPrefix: "node",
|
|
41
|
+
required: true
|
|
34
42
|
}
|
|
35
43
|
];
|
|
36
44
|
const DEAD_HOOKS = ["sms-response-handler.js"];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackmemoryai/stackmemory",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"postinstall": "node scripts/install-claude-hooks-auto.js || true",
|
|
88
88
|
"init": "node dist/scripts/initialize.js",
|
|
89
89
|
"build": "rm -rf dist && node esbuild.config.js",
|
|
90
|
-
"lint": "eslint src/**/*.ts scripts/**/*.ts",
|
|
91
|
-
"lint:fix": "eslint src/**/*.ts scripts/**/*.ts --fix --max-warnings=-1",
|
|
90
|
+
"lint": "eslint 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
91
|
+
"lint:fix": "eslint 'src/**/*.ts' 'scripts/**/*.ts' --fix --max-warnings=-1",
|
|
92
92
|
"lint:fast": "oxlint src scripts",
|
|
93
93
|
"format": "prettier --write src/**/*.ts scripts/**/*.ts",
|
|
94
94
|
"test": "vitest",
|
|
@@ -121,6 +121,7 @@
|
|
|
121
121
|
"daemon:status": "node dist/cli/index.js daemon status",
|
|
122
122
|
"sync:start": "node scripts/background-sync-manager.js",
|
|
123
123
|
"sync:setup": "./scripts/setup-background-sync.sh",
|
|
124
|
+
"eval:cord": "npx tsx scripts/evals/cord-vs-flat-eval.ts",
|
|
124
125
|
"prepare": "echo 'Prepare step completed'",
|
|
125
126
|
"verify:dist": "node scripts/verify-dist.cjs",
|
|
126
127
|
"test:smoke-db": "bash scripts/smoke-init-db.sh",
|
|
@@ -197,7 +198,6 @@
|
|
|
197
198
|
"@xenova/transformers": "^2.17.2",
|
|
198
199
|
"blessed": "^0.1.81",
|
|
199
200
|
"blessed-contrib": "^4.11.0",
|
|
200
|
-
"chokidar": "^5.0.0"
|
|
201
|
-
"chromadb": "^3.2.2"
|
|
201
|
+
"chokidar": "^5.0.0"
|
|
202
202
|
}
|
|
203
203
|
}
|
|
@@ -81,6 +81,14 @@ try {
|
|
|
81
81
|
commandPrefix: 'node',
|
|
82
82
|
required: true,
|
|
83
83
|
},
|
|
84
|
+
{
|
|
85
|
+
scriptName: 'cord-trace.js',
|
|
86
|
+
eventType: 'PostToolUse',
|
|
87
|
+
matcher: 'mcp__.*__cord_(spawn|fork|complete|ask|tree)',
|
|
88
|
+
timeout: 2,
|
|
89
|
+
commandPrefix: 'node',
|
|
90
|
+
required: true,
|
|
91
|
+
},
|
|
84
92
|
];
|
|
85
93
|
|
|
86
94
|
const DEAD_HOOKS = ['sms-response-handler.js'];
|