@stackmemoryai/stackmemory 1.10.5 → 1.12.0

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 (92) hide show
  1. package/README.md +104 -23
  2. package/dist/src/cli/claude-sm.js +266 -84
  3. package/dist/src/cli/codex-sm.js +185 -33
  4. package/dist/src/cli/commands/bench.js +209 -2
  5. package/dist/src/cli/commands/cache.js +126 -0
  6. package/dist/src/cli/commands/daemon.js +41 -0
  7. package/dist/src/cli/commands/handoff.js +40 -9
  8. package/dist/src/cli/commands/onboard.js +70 -3
  9. package/dist/src/cli/commands/optimize.js +117 -0
  10. package/dist/src/cli/commands/orchestrate.js +230 -5
  11. package/dist/src/cli/commands/orchestrator.js +312 -24
  12. package/dist/src/cli/commands/pack.js +322 -0
  13. package/dist/src/cli/commands/search.js +40 -1
  14. package/dist/src/cli/commands/setup.js +177 -7
  15. package/dist/src/cli/commands/skills.js +10 -1
  16. package/dist/src/cli/commands/state.js +265 -0
  17. package/dist/src/cli/gemini-sm.js +19 -29
  18. package/dist/src/cli/index.js +90 -29
  19. package/dist/src/cli/opencode-sm.js +38 -21
  20. package/dist/src/cli/utils/determinism-watcher.js +66 -0
  21. package/dist/src/cli/utils/real-cli-bin.js +44 -0
  22. package/dist/src/core/cache/content-cache.js +238 -0
  23. package/dist/src/core/cache/index.js +11 -0
  24. package/dist/src/core/cache/token-estimator.js +16 -0
  25. package/dist/src/core/context/frame-database.js +38 -30
  26. package/dist/src/core/cross-search/cross-project-search.js +269 -0
  27. package/dist/src/core/{merge → cross-search}/index.js +6 -4
  28. package/dist/src/core/database/sqlite-adapter.js +0 -83
  29. package/dist/src/core/extensions/provider-adapter.js +5 -0
  30. package/dist/src/core/models/model-router.js +22 -2
  31. package/dist/src/core/monitoring/logger.js +2 -1
  32. package/dist/src/core/optimization/trace-optimizer.js +413 -0
  33. package/dist/src/core/provenance/confidence-scorer.js +128 -0
  34. package/dist/src/core/provenance/index.js +40 -0
  35. package/dist/src/core/provenance/provenance-store.js +194 -0
  36. package/dist/src/core/provenance/types.js +82 -0
  37. package/dist/src/core/session/project-handoff.js +64 -0
  38. package/dist/src/core/session/session-manager.js +28 -0
  39. package/dist/src/core/shared-state/canonical-store.js +564 -0
  40. package/dist/src/core/skill-packs/index.js +18 -0
  41. package/dist/src/core/skill-packs/parser.js +42 -0
  42. package/dist/src/core/skill-packs/registry.js +224 -0
  43. package/dist/src/core/skill-packs/types.js +66 -0
  44. package/dist/src/core/trace/trace-event-store.js +282 -0
  45. package/dist/src/core/trace/trace-event.js +4 -0
  46. package/dist/src/daemon/daemon-config.js +7 -0
  47. package/dist/src/daemon/services/github-service.js +126 -0
  48. package/dist/src/daemon/unified-daemon.js +30 -0
  49. package/dist/src/features/sweep/pty-wrapper.js +13 -5
  50. package/dist/src/hooks/schemas.js +2 -0
  51. package/dist/src/integrations/claude-code/subagent-client.js +89 -0
  52. package/dist/src/integrations/github/pr-state.js +158 -0
  53. package/dist/src/integrations/linear/client.js +4 -1
  54. package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +188 -0
  55. package/dist/src/integrations/mcp/handlers/index.js +40 -59
  56. package/dist/src/integrations/mcp/server.js +425 -311
  57. package/dist/src/integrations/mcp/tool-alias-registry.js +370 -0
  58. package/dist/src/integrations/mcp/tool-definitions.js +98 -229
  59. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +3 -40
  60. package/dist/src/integrations/ralph/learning/pattern-learner.js +1 -20
  61. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -2
  62. package/dist/src/mcp/stackmemory-mcp-server.js +315 -0
  63. package/dist/src/orchestrators/multimodal/determinism.js +243 -0
  64. package/dist/src/orchestrators/multimodal/harness.js +147 -77
  65. package/dist/src/orchestrators/multimodal/providers.js +44 -3
  66. package/dist/src/utils/hook-installer.js +0 -8
  67. package/package.json +10 -1
  68. package/packs/coding/python-fastapi/instructions.md +60 -0
  69. package/packs/coding/python-fastapi/pack.yaml +28 -0
  70. package/packs/coding/typescript-react/instructions.md +47 -0
  71. package/packs/coding/typescript-react/pack.yaml +28 -0
  72. package/packs/core/commands/capture.md +32 -0
  73. package/packs/core/commands/learn.md +73 -0
  74. package/packs/core/commands/next.md +36 -0
  75. package/packs/core/commands/restart.md +58 -0
  76. package/packs/core/commands/restore.md +29 -0
  77. package/packs/core/commands/start.md +57 -0
  78. package/packs/core/commands/stop.md +65 -0
  79. package/packs/core/commands/summary.md +40 -0
  80. package/packs/core/manifest.json +24 -0
  81. package/packs/ops/decision-recovery/instructions.md +65 -0
  82. package/packs/ops/decision-recovery/pack.yaml +89 -0
  83. package/dist/src/cli/commands/team.js +0 -168
  84. package/dist/src/core/context/shared-context-layer.js +0 -620
  85. package/dist/src/core/context/stack-merge-resolver.js +0 -748
  86. package/dist/src/core/merge/conflict-detector.js +0 -430
  87. package/dist/src/core/merge/resolution-engine.js +0 -557
  88. package/dist/src/core/merge/stack-diff.js +0 -531
  89. package/dist/src/core/merge/unified-merge-resolver.js +0 -302
  90. package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
  91. package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
  92. /package/dist/src/core/{merge → cache}/types.js +0 -0
@@ -1,430 +0,0 @@
1
- import { fileURLToPath as __fileURLToPath } from 'url';
2
- import { dirname as __pathDirname } from 'path';
3
- const __filename = __fileURLToPath(import.meta.url);
4
- const __dirname = __pathDirname(__filename);
5
- import { v4 as uuidv4 } from "uuid";
6
- import { logger } from "../monitoring/logger.js";
7
- class ConflictDetector {
8
- SIMILARITY_THRESHOLD = 0.8;
9
- /**
10
- * Detect all types of conflicts between two frame stacks
11
- */
12
- detectConflicts(stack1, stack2) {
13
- const conflicts = [];
14
- const parallelConflicts = this.detectParallelSolutions(stack1, stack2);
15
- conflicts.push(...parallelConflicts);
16
- const decisionConflicts = this.detectConflictingDecisions(
17
- stack1.events,
18
- stack2.events
19
- );
20
- conflicts.push(...decisionConflicts);
21
- const structuralConflicts = this.detectStructuralDivergence(
22
- stack1.frames,
23
- stack2.frames
24
- );
25
- conflicts.push(...structuralConflicts);
26
- logger.info(`Detected ${conflicts.length} conflicts between stacks`, {
27
- stack1Id: stack1.id,
28
- stack2Id: stack2.id,
29
- conflictTypes: this.summarizeConflictTypes(conflicts)
30
- });
31
- return conflicts;
32
- }
33
- /**
34
- * Analyze frames to find parallel solutions to the same problem
35
- */
36
- analyzeParallelSolutions(frames) {
37
- const solutions = [];
38
- const groupedFrames = this.groupSimilarFrames(frames);
39
- for (const group of groupedFrames) {
40
- if (group.length > 1) {
41
- group.forEach((frame) => {
42
- solutions.push({
43
- frameId: frame.frame_id,
44
- solution: this.extractSolution(frame),
45
- approach: this.analyzeApproach(frame),
46
- author: frame.inputs?.author || "unknown",
47
- timestamp: frame.created_at,
48
- effectiveness: this.calculateEffectiveness(frame)
49
- });
50
- });
51
- }
52
- }
53
- return solutions;
54
- }
55
- /**
56
- * Identify conflicting decisions in event streams
57
- */
58
- identifyConflictingDecisions(events) {
59
- const conflicts = [];
60
- const decisions = this.extractDecisions(events);
61
- for (let i = 0; i < decisions.length; i++) {
62
- for (let j = i + 1; j < decisions.length; j++) {
63
- if (this.decisionsConflict(decisions[i], decisions[j])) {
64
- conflicts.push({
65
- decision1: decisions[i].payload?.decision || "",
66
- decision2: decisions[j].payload?.decision || "",
67
- impact: this.assessImpact(decisions[i], decisions[j]),
68
- canCoexist: this.canCoexist(decisions[i], decisions[j])
69
- });
70
- }
71
- }
72
- }
73
- return conflicts;
74
- }
75
- /**
76
- * Detect parallel solutions between two stacks
77
- */
78
- detectParallelSolutions(stack1, stack2) {
79
- const conflicts = [];
80
- for (const frame1 of stack1.frames) {
81
- for (const frame2 of stack2.frames) {
82
- if (this.framesAreSimilar(frame1, frame2) && !this.framesAreIdentical(frame1, frame2)) {
83
- conflicts.push({
84
- id: uuidv4(),
85
- type: "parallel_solution",
86
- frameId1: frame1.frame_id,
87
- frameId2: frame2.frame_id,
88
- severity: this.calculateParallelSeverity(frame1, frame2),
89
- description: `Parallel solutions detected: "${frame1.name}" vs "${frame2.name}"`,
90
- detectedAt: Date.now(),
91
- conflictingPaths: this.extractPaths(frame1, frame2)
92
- });
93
- }
94
- }
95
- }
96
- return conflicts;
97
- }
98
- /**
99
- * Detect conflicting decisions between event streams
100
- */
101
- detectConflictingDecisions(events1, events2) {
102
- const conflicts = [];
103
- const decisions1 = this.extractDecisions(events1);
104
- const decisions2 = this.extractDecisions(events2);
105
- for (const d1 of decisions1) {
106
- for (const d2 of decisions2) {
107
- if (this.decisionsConflict(d1, d2)) {
108
- conflicts.push({
109
- id: uuidv4(),
110
- type: "conflicting_decision",
111
- frameId1: d1.frame_id,
112
- frameId2: d2.frame_id,
113
- severity: this.assessImpact(d1, d2),
114
- description: `Conflicting decisions: "${d1.payload?.decision}" vs "${d2.payload?.decision}"`,
115
- detectedAt: Date.now()
116
- });
117
- }
118
- }
119
- }
120
- return conflicts;
121
- }
122
- /**
123
- * Detect structural divergence in frame hierarchies
124
- */
125
- detectStructuralDivergence(frames1, frames2) {
126
- const conflicts = [];
127
- const tree1 = this.buildFrameTree(frames1);
128
- const tree2 = this.buildFrameTree(frames2);
129
- const divergences = this.findDivergences(tree1, tree2);
130
- for (const divergence of divergences) {
131
- conflicts.push({
132
- id: uuidv4(),
133
- type: "structural_divergence",
134
- frameId1: divergence.node1,
135
- frameId2: divergence.node2,
136
- severity: this.calculateDivergenceSeverity(divergence),
137
- description: `Structural divergence at depth ${divergence.depth}`,
138
- detectedAt: Date.now()
139
- });
140
- }
141
- return conflicts;
142
- }
143
- /**
144
- * Helper: Check if two frames are similar (solving same problem)
145
- */
146
- framesAreSimilar(frame1, frame2) {
147
- const nameSimilarity = this.calculateSimilarity(frame1.name, frame2.name);
148
- if (nameSimilarity > this.SIMILARITY_THRESHOLD) return true;
149
- if (frame1.type === frame2.type && frame1.parent_frame_id === frame2.parent_frame_id) {
150
- return true;
151
- }
152
- const inputSimilarity = this.compareInputs(frame1.inputs, frame2.inputs);
153
- return inputSimilarity > this.SIMILARITY_THRESHOLD;
154
- }
155
- /**
156
- * Helper: Check if frames are identical
157
- */
158
- framesAreIdentical(frame1, frame2) {
159
- return frame1.frame_id === frame2.frame_id;
160
- }
161
- /**
162
- * Helper: Calculate string similarity (Levenshtein-based)
163
- */
164
- calculateSimilarity(str1, str2) {
165
- const maxLen = Math.max(str1.length, str2.length);
166
- if (maxLen === 0) return 1;
167
- const distance = this.levenshteinDistance(str1, str2);
168
- return 1 - distance / maxLen;
169
- }
170
- /**
171
- * Helper: Levenshtein distance implementation
172
- */
173
- levenshteinDistance(str1, str2) {
174
- const matrix = [];
175
- for (let i = 0; i <= str2.length; i++) {
176
- matrix[i] = [i];
177
- }
178
- for (let j = 0; j <= str1.length; j++) {
179
- matrix[0][j] = j;
180
- }
181
- for (let i = 1; i <= str2.length; i++) {
182
- for (let j = 1; j <= str1.length; j++) {
183
- if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
184
- matrix[i][j] = matrix[i - 1][j - 1];
185
- } else {
186
- matrix[i][j] = Math.min(
187
- matrix[i - 1][j - 1] + 1,
188
- matrix[i][j - 1] + 1,
189
- matrix[i - 1][j] + 1
190
- );
191
- }
192
- }
193
- }
194
- return matrix[str2.length][str1.length];
195
- }
196
- /**
197
- * Helper: Compare frame inputs
198
- */
199
- compareInputs(inputs1, inputs2) {
200
- const keys1 = Object.keys(inputs1 || {});
201
- const keys2 = Object.keys(inputs2 || {});
202
- const allKeys = /* @__PURE__ */ new Set([...keys1, ...keys2]);
203
- if (allKeys.size === 0) return 1;
204
- let matches = 0;
205
- for (const key of allKeys) {
206
- if (JSON.stringify(inputs1[key]) === JSON.stringify(inputs2[key])) {
207
- matches++;
208
- }
209
- }
210
- return matches / allKeys.size;
211
- }
212
- /**
213
- * Helper: Calculate severity for parallel solutions
214
- */
215
- calculateParallelSeverity(frame1, frame2) {
216
- if (frame1.state === "closed" && frame2.state === "closed") {
217
- const outputSimilarity = this.compareInputs(
218
- frame1.outputs,
219
- frame2.outputs
220
- );
221
- if (outputSimilarity < 0.5) return "critical";
222
- if (outputSimilarity < 0.7) return "high";
223
- }
224
- if (frame1.parent_frame_id === frame2.parent_frame_id) {
225
- return "high";
226
- }
227
- return "medium";
228
- }
229
- /**
230
- * Helper: Extract decision events
231
- */
232
- extractDecisions(events) {
233
- return events.filter(
234
- (e) => e.event_type === "decision" || e.payload?.type === "decision" || e.payload?.decision !== void 0
235
- );
236
- }
237
- /**
238
- * Helper: Check if two decisions conflict
239
- */
240
- decisionsConflict(d1, d2) {
241
- const resource1 = d1.payload?.resource || d1.payload?.path;
242
- const resource2 = d2.payload?.resource || d2.payload?.path;
243
- if (resource1 && resource2 && resource1 === resource2) {
244
- return d1.payload?.decision !== d2.payload?.decision;
245
- }
246
- return this.hasLogicalConflict(d1.payload, d2.payload);
247
- }
248
- /**
249
- * Helper: Check for logical conflicts in payloads
250
- */
251
- hasLogicalConflict(payload1, payload2) {
252
- if (payload1?.architecture && payload2?.architecture) {
253
- return payload1.architecture !== payload2.architecture;
254
- }
255
- if (payload1?.technology && payload2?.technology) {
256
- return payload1.technology !== payload2.technology;
257
- }
258
- return false;
259
- }
260
- /**
261
- * Helper: Assess impact of conflicting decisions
262
- */
263
- assessImpact(d1, d2) {
264
- if (d1.payload?.type === "architecture" || d2.payload?.type === "architecture") {
265
- return "high";
266
- }
267
- if (d1.payload?.scope === "implementation" || d2.payload?.scope === "implementation") {
268
- return "medium";
269
- }
270
- return "low";
271
- }
272
- /**
273
- * Helper: Check if decisions can coexist
274
- */
275
- canCoexist(d1, d2) {
276
- if (d1.payload?.scope !== d2.payload?.scope) {
277
- return true;
278
- }
279
- const resource1 = d1.payload?.resource;
280
- const resource2 = d2.payload?.resource;
281
- return resource1 !== resource2;
282
- }
283
- /**
284
- * Helper: Build frame tree structure
285
- */
286
- buildFrameTree(frames) {
287
- const tree = /* @__PURE__ */ new Map();
288
- for (const frame of frames) {
289
- if (frame.parent_frame_id) {
290
- if (!tree.has(frame.parent_frame_id)) {
291
- tree.set(frame.parent_frame_id, /* @__PURE__ */ new Set());
292
- }
293
- const parentSet = tree.get(frame.parent_frame_id);
294
- if (parentSet) {
295
- parentSet.add(frame.frame_id);
296
- }
297
- }
298
- }
299
- return tree;
300
- }
301
- /**
302
- * Helper: Find divergence points in trees
303
- */
304
- findDivergences(tree1, tree2) {
305
- const divergences = [];
306
- for (const [node, children1] of tree1) {
307
- if (tree2.has(node)) {
308
- const children2 = tree2.get(node);
309
- if (children2 && !this.setsEqual(children1, children2)) {
310
- divergences.push({
311
- node1: node,
312
- node2: node,
313
- depth: this.calculateDepth(node, tree1)
314
- });
315
- }
316
- }
317
- }
318
- return divergences;
319
- }
320
- /**
321
- * Helper: Check if two sets are equal
322
- */
323
- setsEqual(set1, set2) {
324
- if (set1.size !== set2.size) return false;
325
- for (const item of set1) {
326
- if (!set2.has(item)) return false;
327
- }
328
- return true;
329
- }
330
- /**
331
- * Helper: Calculate node depth in tree
332
- */
333
- calculateDepth(node, tree) {
334
- let depth = 0;
335
- let current = node;
336
- for (const [parent, children] of tree) {
337
- if (children.has(current)) {
338
- depth++;
339
- current = parent;
340
- }
341
- }
342
- return depth;
343
- }
344
- /**
345
- * Helper: Calculate divergence severity
346
- */
347
- calculateDivergenceSeverity(divergence) {
348
- if (divergence.depth === 0) return "critical";
349
- if (divergence.depth === 1) return "high";
350
- if (divergence.depth === 2) return "medium";
351
- return "low";
352
- }
353
- /**
354
- * Helper: Extract paths from frames
355
- */
356
- extractPaths(frame1, frame2) {
357
- const paths = [];
358
- if (frame1.inputs?.path) paths.push(frame1.inputs.path);
359
- if (frame2.inputs?.path) paths.push(frame2.inputs.path);
360
- if (frame1.outputs?.files) paths.push(...frame1.outputs.files);
361
- if (frame2.outputs?.files) paths.push(...frame2.outputs.files);
362
- return [...new Set(paths)];
363
- }
364
- /**
365
- * Helper: Extract solution from frame
366
- */
367
- extractSolution(frame) {
368
- return frame.outputs?.solution || frame.digest_text || "No solution description";
369
- }
370
- /**
371
- * Helper: Analyze approach taken
372
- */
373
- analyzeApproach(frame) {
374
- if (frame.outputs?.approach) return frame.outputs.approach;
375
- if (frame.type === "debug") return "Debug approach";
376
- if (frame.type === "review") return "Review approach";
377
- return "Standard approach";
378
- }
379
- /**
380
- * Helper: Calculate solution effectiveness
381
- */
382
- calculateEffectiveness(frame) {
383
- let score = 0.5;
384
- if (frame.state === "closed") score += 0.2;
385
- if (frame.outputs && Object.keys(frame.outputs).length > 0) score += 0.1;
386
- if (frame.digest_text) score += 0.1;
387
- if (frame.closed_at && frame.created_at) {
388
- const duration = frame.closed_at - frame.created_at;
389
- if (duration < 3e5) score += 0.1;
390
- }
391
- return Math.min(score, 1);
392
- }
393
- /**
394
- * Helper: Group similar frames together
395
- */
396
- groupSimilarFrames(frames) {
397
- const groups = [];
398
- const processed = /* @__PURE__ */ new Set();
399
- for (const frame of frames) {
400
- if (processed.has(frame.frame_id)) continue;
401
- const group = [frame];
402
- processed.add(frame.frame_id);
403
- for (const other of frames) {
404
- if (!processed.has(other.frame_id) && this.framesAreSimilar(frame, other)) {
405
- group.push(other);
406
- processed.add(other.frame_id);
407
- }
408
- }
409
- groups.push(group);
410
- }
411
- return groups;
412
- }
413
- /**
414
- * Helper: Summarize conflict types
415
- */
416
- summarizeConflictTypes(conflicts) {
417
- const summary = {
418
- parallel_solution: 0,
419
- conflicting_decision: 0,
420
- structural_divergence: 0
421
- };
422
- for (const conflict of conflicts) {
423
- summary[conflict.type]++;
424
- }
425
- return summary;
426
- }
427
- }
428
- export {
429
- ConflictDetector
430
- };