@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.
Files changed (63) 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/storage-tier.js +26 -8
  11. package/dist/src/cli/index.js +1 -57
  12. package/dist/src/core/config/feature-flags.js +0 -4
  13. package/dist/src/core/context/dual-stack-manager.js +10 -3
  14. package/dist/src/core/context/frame-database.js +32 -0
  15. package/dist/src/core/context/frame-handoff-manager.js +2 -2
  16. package/dist/src/core/context/{refactored-frame-manager.js → frame-manager.js} +3 -3
  17. package/dist/src/core/context/index.js +2 -2
  18. package/dist/src/core/database/sqlite-adapter.js +161 -1
  19. package/dist/src/core/digest/frame-digest-integration.js +1 -1
  20. package/dist/src/core/digest/index.js +1 -1
  21. package/dist/src/core/execution/parallel-executor.js +5 -1
  22. package/dist/src/core/projects/project-isolation.js +18 -4
  23. package/dist/src/core/security/index.js +2 -0
  24. package/dist/src/core/security/input-sanitizer.js +23 -0
  25. package/dist/src/core/utils/update-checker.js +10 -6
  26. package/dist/src/daemon/daemon-config.js +2 -1
  27. package/dist/src/daemon/services/auto-save-service.js +121 -0
  28. package/dist/src/daemon/services/maintenance-service.js +76 -1
  29. package/dist/src/features/sweep/prompt-builder.js +2 -2
  30. package/dist/src/integrations/linear/config.js +3 -1
  31. package/dist/src/integrations/linear/sync.js +18 -5
  32. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +33 -7
  33. package/dist/src/integrations/mcp/handlers/cord-handlers.js +397 -0
  34. package/dist/src/integrations/mcp/handlers/index.js +55 -1
  35. package/dist/src/integrations/mcp/handlers/task-handlers.js +55 -12
  36. package/dist/src/integrations/mcp/handlers/team-handlers.js +211 -0
  37. package/dist/src/integrations/mcp/handlers/trace-handlers.js +25 -9
  38. package/dist/src/integrations/mcp/index.js +2 -2
  39. package/dist/src/integrations/mcp/refactored-server.js +31 -10
  40. package/dist/src/integrations/mcp/tool-definitions.js +215 -1
  41. package/dist/src/integrations/ralph/context/context-budget-manager.js +10 -2
  42. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +54 -22
  43. package/dist/src/integrations/ralph/learning/pattern-learner.js +59 -24
  44. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +81 -35
  45. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +12 -4
  46. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +32 -9
  47. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +25 -8
  48. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +17 -5
  49. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +73 -22
  50. package/dist/src/skills/claude-skills.js +0 -102
  51. package/dist/src/utils/hook-installer.js +8 -0
  52. package/package.json +5 -5
  53. package/scripts/install-claude-hooks-auto.js +8 -0
  54. package/templates/claude-hooks/cord-trace.js +225 -0
  55. package/dist/src/core/config/storage-config.js +0 -114
  56. package/dist/src/core/storage/chromadb-adapter.js +0 -379
  57. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
  58. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +0 -409
  59. package/dist/src/skills/repo-ingestion-skill.js +0 -631
  60. package/templates/claude-hooks/chromadb-wrapper +0 -21
  61. /package/dist/src/core/context/{enhanced-rehydration.js → rehydration.js} +0 -0
  62. /package/dist/src/core/digest/{enhanced-hybrid-digest.js → hybrid-digest.js} +0 -0
  63. /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", { 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>
@@ -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.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'];