@stackmemoryai/stackmemory 0.3.22 → 0.3.25

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 (44) hide show
  1. package/dist/cli/commands/ralph.js +294 -0
  2. package/dist/cli/commands/ralph.js.map +7 -0
  3. package/dist/cli/index.js +2 -0
  4. package/dist/cli/index.js.map +2 -2
  5. package/dist/integrations/ralph/bridge/ralph-stackmemory-bridge.js +586 -0
  6. package/dist/integrations/ralph/bridge/ralph-stackmemory-bridge.js.map +7 -0
  7. package/dist/integrations/ralph/context/context-budget-manager.js +297 -0
  8. package/dist/integrations/ralph/context/context-budget-manager.js.map +7 -0
  9. package/dist/integrations/ralph/context/stackmemory-context-loader.js +356 -0
  10. package/dist/integrations/ralph/context/stackmemory-context-loader.js.map +7 -0
  11. package/dist/integrations/ralph/index.js +14 -0
  12. package/dist/integrations/ralph/index.js.map +7 -0
  13. package/dist/integrations/ralph/learning/pattern-learner.js +397 -0
  14. package/dist/integrations/ralph/learning/pattern-learner.js.map +7 -0
  15. package/dist/integrations/ralph/lifecycle/iteration-lifecycle.js +444 -0
  16. package/dist/integrations/ralph/lifecycle/iteration-lifecycle.js.map +7 -0
  17. package/dist/integrations/ralph/orchestration/multi-loop-orchestrator.js +459 -0
  18. package/dist/integrations/ralph/orchestration/multi-loop-orchestrator.js.map +7 -0
  19. package/dist/integrations/ralph/performance/performance-optimizer.js +354 -0
  20. package/dist/integrations/ralph/performance/performance-optimizer.js.map +7 -0
  21. package/dist/integrations/ralph/ralph-integration-demo.js +178 -0
  22. package/dist/integrations/ralph/ralph-integration-demo.js.map +7 -0
  23. package/dist/integrations/ralph/state/state-reconciler.js +400 -0
  24. package/dist/integrations/ralph/state/state-reconciler.js.map +7 -0
  25. package/dist/integrations/ralph/swarm/git-workflow-manager.js +309 -0
  26. package/dist/integrations/ralph/swarm/git-workflow-manager.js.map +7 -0
  27. package/dist/integrations/ralph/swarm/swarm-coordinator.js +656 -0
  28. package/dist/integrations/ralph/swarm/swarm-coordinator.js.map +7 -0
  29. package/dist/integrations/ralph/types.js +1 -0
  30. package/dist/integrations/ralph/types.js.map +7 -0
  31. package/dist/integrations/ralph/visualization/ralph-debugger.js +581 -0
  32. package/dist/integrations/ralph/visualization/ralph-debugger.js.map +7 -0
  33. package/package.json +1 -1
  34. package/scripts/deploy-ralph-swarm.sh +365 -0
  35. package/scripts/ralph-integration-test.js +274 -0
  36. package/scripts/ralph-loop-implementation.js +404 -0
  37. package/scripts/swarm-monitor.js +509 -0
  38. package/scripts/test-parallel-swarms.js +443 -0
  39. package/scripts/test-pre-publish-quick.sh +4 -2
  40. package/scripts/test-swarm-git-workflow.js +338 -0
  41. package/scripts/testing/ralph-cli-test.js +88 -0
  42. package/scripts/testing/ralph-integration-validation.js +727 -0
  43. package/scripts/testing/ralph-swarm-test-scenarios.js +613 -0
  44. package/scripts/validate-swarm-implementation.js +467 -0
@@ -0,0 +1,404 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { execSync } from 'child_process';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ class RalphLoop {
9
+ constructor(options = {}) {
10
+ this.baseDir = options.baseDir || '.ralph';
11
+ this.maxIterations = options.maxIterations || 50;
12
+ this.verbose = options.verbose || false;
13
+
14
+ this.paths = {
15
+ task: path.join(this.baseDir, 'task.md'),
16
+ criteria: path.join(this.baseDir, 'completion-criteria.md'),
17
+ iteration: path.join(this.baseDir, 'iteration.txt'),
18
+ feedback: path.join(this.baseDir, 'feedback.txt'),
19
+ state: path.join(this.baseDir, 'state.json'),
20
+ complete: path.join(this.baseDir, 'work-complete.txt'),
21
+ progress: path.join(this.baseDir, 'progress.jsonl'),
22
+ history: path.join(this.baseDir, 'history')
23
+ };
24
+ }
25
+
26
+ async initialize(task, criteria) {
27
+ // Create directory structure
28
+ fs.mkdirSync(this.baseDir, { recursive: true });
29
+ fs.mkdirSync(this.paths.history, { recursive: true });
30
+
31
+ // Initialize files
32
+ fs.writeFileSync(this.paths.task, task);
33
+ fs.writeFileSync(this.paths.criteria, criteria);
34
+ fs.writeFileSync(this.paths.iteration, '0');
35
+ fs.writeFileSync(this.paths.feedback, '');
36
+
37
+ // Initial state
38
+ const state = {
39
+ startTime: Date.now(),
40
+ task: task.substring(0, 100),
41
+ status: 'initialized'
42
+ };
43
+ fs.writeFileSync(this.paths.state, JSON.stringify(state, null, 2));
44
+
45
+ this.log('Ralph Loop initialized');
46
+ }
47
+
48
+ async runWorkerIteration() {
49
+ const iteration = this.getCurrentIteration();
50
+ const task = fs.readFileSync(this.paths.task, 'utf8');
51
+ const feedback = this.getFeedback();
52
+
53
+ this.log(`Worker iteration ${iteration} starting...`);
54
+
55
+ // Step 1: Analyze current state (fresh context)
56
+ const analysis = await this.analyzeCurrentState();
57
+
58
+ // Step 2: Plan based on task and feedback
59
+ const plan = await this.createPlan(task, feedback, analysis);
60
+
61
+ // Step 3: Execute changes
62
+ const changes = await this.executeChanges(plan);
63
+
64
+ // Step 4: Validate changes
65
+ const validation = await this.validateChanges();
66
+
67
+ // Step 5: Save iteration artifacts
68
+ await this.saveIterationArtifacts(iteration, {
69
+ analysis,
70
+ plan,
71
+ changes,
72
+ validation
73
+ });
74
+
75
+ // Step 6: Commit changes
76
+ this.commitChanges(iteration, plan.summary);
77
+
78
+ return {
79
+ iteration,
80
+ changes: changes.length,
81
+ validation
82
+ };
83
+ }
84
+
85
+ async runReviewerIteration() {
86
+ const iteration = this.getCurrentIteration();
87
+ const task = fs.readFileSync(this.paths.task, 'utf8');
88
+ const criteria = fs.readFileSync(this.paths.criteria, 'utf8');
89
+
90
+ this.log(`Reviewer iteration ${iteration} evaluating...`);
91
+
92
+ // Fresh evaluation of current state
93
+ const evaluation = await this.evaluateAgainstCriteria(criteria);
94
+
95
+ if (evaluation.complete) {
96
+ fs.writeFileSync(this.paths.complete, 'true');
97
+ this.log('Task completed successfully!');
98
+ return { complete: true };
99
+ }
100
+
101
+ // Generate feedback for next iteration
102
+ const feedback = this.generateFeedback(evaluation);
103
+ fs.writeFileSync(this.paths.feedback, feedback);
104
+
105
+ // Increment iteration
106
+ this.incrementIteration();
107
+
108
+ return {
109
+ complete: false,
110
+ feedback: feedback.substring(0, 200)
111
+ };
112
+ }
113
+
114
+ async analyzeCurrentState() {
115
+ // Simulate fresh analysis of codebase
116
+ const files = this.scanRelevantFiles();
117
+ const tests = this.getTestStatus();
118
+ const lastCommit = this.getLastCommit();
119
+
120
+ return {
121
+ filesCount: files.length,
122
+ testsPass: tests.passing,
123
+ testsFail: tests.failing,
124
+ lastChange: lastCommit
125
+ };
126
+ }
127
+
128
+ async createPlan(_task, feedback, _analysis) {
129
+ // In real implementation, this would use an LLM
130
+ // Here we simulate planning based on feedback
131
+ const needsWork = feedback.includes('failing') ||
132
+ feedback.includes('incomplete') ||
133
+ feedback === '';
134
+
135
+ return {
136
+ summary: `Iteration work based on: ${feedback.substring(0, 50)}`,
137
+ steps: needsWork ? ['Fix issues', 'Add features', 'Update tests'] : ['Polish'],
138
+ priority: needsWork ? 'high' : 'low'
139
+ };
140
+ }
141
+
142
+ async executeChanges(plan) {
143
+ // Simulate making code changes
144
+ const changes = [];
145
+
146
+ for (const step of plan.steps) {
147
+ changes.push({
148
+ step,
149
+ timestamp: Date.now(),
150
+ result: 'simulated'
151
+ });
152
+ }
153
+
154
+ return changes;
155
+ }
156
+
157
+ async validateChanges() {
158
+ // Run tests and checks
159
+ try {
160
+ const testResult = this.runTests();
161
+ const lintResult = this.runLint();
162
+
163
+ return {
164
+ testsPass: testResult.passing > 0,
165
+ lintClean: lintResult.clean,
166
+ errors: [...testResult.errors, ...lintResult.errors]
167
+ };
168
+ } catch (error) {
169
+ return {
170
+ testsPass: false,
171
+ lintClean: false,
172
+ errors: [error.message]
173
+ };
174
+ }
175
+ }
176
+
177
+ async evaluateAgainstCriteria(criteria) {
178
+ // Parse criteria and check each
179
+ const criteriaLines = criteria.split('\n').filter(l => l.trim().startsWith('-'));
180
+ const results = {};
181
+
182
+ for (const criterion of criteriaLines) {
183
+ const key = criterion.replace('-', '').trim().substring(0, 20);
184
+ // Simulate checking (in reality would analyze code)
185
+ results[key] = Math.random() > 0.3; // 70% chance of meeting each criterion
186
+ }
187
+
188
+ const complete = Object.values(results).every(v => v === true);
189
+
190
+ return {
191
+ complete,
192
+ criteria: results,
193
+ unmet: Object.entries(results)
194
+ .filter(([_, v]) => !v)
195
+ .map(([k]) => k)
196
+ };
197
+ }
198
+
199
+ generateFeedback(evaluation) {
200
+ if (evaluation.unmet.length === 0) {
201
+ return 'All criteria met';
202
+ }
203
+
204
+ return `Still need to address:\n${evaluation.unmet.map(c => `- ${c}`).join('\n')}`;
205
+ }
206
+
207
+ async saveIterationArtifacts(iteration, artifacts) {
208
+ const iterDir = path.join(this.paths.history, `iteration-${String(iteration).padStart(3, '0')}`);
209
+ fs.mkdirSync(iterDir, { recursive: true });
210
+
211
+ fs.writeFileSync(
212
+ path.join(iterDir, 'artifacts.json'),
213
+ JSON.stringify(artifacts, null, 2)
214
+ );
215
+
216
+ // Log progress
217
+ const progress = {
218
+ iteration,
219
+ timestamp: Date.now(),
220
+ changes: artifacts.changes.length,
221
+ validation: artifacts.validation.testsPass,
222
+ errors: artifacts.validation.errors.length
223
+ };
224
+
225
+ fs.appendFileSync(this.paths.progress, JSON.stringify(progress) + '\n');
226
+ }
227
+
228
+ commitChanges(iteration, summary) {
229
+ try {
230
+ execSync('git add -A', { stdio: 'pipe' });
231
+ execSync(`git commit -m "Ralph iteration ${iteration}: ${summary}" --allow-empty`, { stdio: 'pipe' });
232
+ this.log(`Committed iteration ${iteration}`);
233
+ } catch (error) {
234
+ this.log(`Commit failed: ${error.message}`);
235
+ }
236
+ }
237
+
238
+ scanRelevantFiles() {
239
+ // Simulate file scanning
240
+ return ['index.js', 'auth.js', 'test.js'];
241
+ }
242
+
243
+ getTestStatus() {
244
+ try {
245
+ execSync('npm test', { stdio: 'pipe' });
246
+ return { passing: 5, failing: 0 };
247
+ } catch {
248
+ return { passing: 3, failing: 2 };
249
+ }
250
+ }
251
+
252
+ runTests() {
253
+ const status = this.getTestStatus();
254
+ return {
255
+ passing: status.passing,
256
+ failing: status.failing,
257
+ errors: status.failing > 0 ? ['Some tests failed'] : []
258
+ };
259
+ }
260
+
261
+ runLint() {
262
+ try {
263
+ execSync('npm run lint', { stdio: 'pipe' });
264
+ return { clean: true, errors: [] };
265
+ } catch {
266
+ return { clean: false, errors: ['Lint issues found'] };
267
+ }
268
+ }
269
+
270
+ getLastCommit() {
271
+ try {
272
+ return execSync('git log -1 --oneline', { encoding: 'utf8' }).trim();
273
+ } catch {
274
+ return 'No commits yet';
275
+ }
276
+ }
277
+
278
+ getCurrentIteration() {
279
+ try {
280
+ return parseInt(fs.readFileSync(this.paths.iteration, 'utf8'));
281
+ } catch {
282
+ return 0;
283
+ }
284
+ }
285
+
286
+ incrementIteration() {
287
+ const current = this.getCurrentIteration();
288
+ fs.writeFileSync(this.paths.iteration, String(current + 1));
289
+ }
290
+
291
+ getFeedback() {
292
+ try {
293
+ return fs.readFileSync(this.paths.feedback, 'utf8');
294
+ } catch {
295
+ return '';
296
+ }
297
+ }
298
+
299
+ isComplete() {
300
+ return fs.existsSync(this.paths.complete);
301
+ }
302
+
303
+ log(message) {
304
+ if (this.verbose) {
305
+ console.log(`[Ralph] ${message}`);
306
+ }
307
+ }
308
+
309
+ async run() {
310
+ while (!this.isComplete()) {
311
+ const iteration = this.getCurrentIteration();
312
+
313
+ if (iteration >= this.maxIterations) {
314
+ console.log('Max iterations reached!');
315
+ break;
316
+ }
317
+
318
+ // Worker phase
319
+ await this.runWorkerIteration();
320
+
321
+ // Reviewer phase
322
+ const review = await this.runReviewerIteration();
323
+
324
+ if (review.complete) {
325
+ console.log('Task completed!');
326
+ break;
327
+ }
328
+
329
+ // Brief pause between iterations
330
+ await new Promise(resolve => setTimeout(resolve, 1000));
331
+ }
332
+
333
+ // Final summary
334
+ this.printSummary();
335
+ }
336
+
337
+ printSummary() {
338
+ const iterations = this.getCurrentIteration();
339
+ const progress = fs.readFileSync(this.paths.progress, 'utf8')
340
+ .split('\n')
341
+ .filter(Boolean)
342
+ .map(line => JSON.parse(line));
343
+
344
+ console.log('\n=== Ralph Loop Summary ===');
345
+ console.log(`Total iterations: ${iterations}`);
346
+ console.log(`Total changes: ${progress.reduce((sum, p) => sum + p.changes, 0)}`);
347
+ console.log(`Final status: ${this.isComplete() ? 'COMPLETE' : 'INCOMPLETE'}`);
348
+ }
349
+ }
350
+
351
+ // CLI Interface
352
+ async function main() {
353
+ const args = process.argv.slice(2);
354
+ const command = args[0];
355
+
356
+ if (command === 'init') {
357
+ const task = args[1] || 'Implement a feature';
358
+ const criteria = args[2] || '- Tests pass\n- Code works\n- No errors';
359
+
360
+ const loop = new RalphLoop({ verbose: true });
361
+ await loop.initialize(task, criteria);
362
+ console.log('Ralph Loop initialized. Run with: node ralph-loop-implementation.js run');
363
+
364
+ } else if (command === 'run') {
365
+ const loop = new RalphLoop({ verbose: true });
366
+
367
+ if (!fs.existsSync(loop.paths.task)) {
368
+ console.error('No task found. Initialize first with: node ralph-loop-implementation.js init');
369
+ process.exit(1);
370
+ }
371
+
372
+ await loop.run();
373
+
374
+ } else if (command === 'status') {
375
+ const loop = new RalphLoop();
376
+ const iteration = loop.getCurrentIteration();
377
+ const complete = loop.isComplete();
378
+ const feedback = loop.getFeedback();
379
+
380
+ console.log(`Iteration: ${iteration}`);
381
+ console.log(`Status: ${complete ? 'COMPLETE' : 'IN PROGRESS'}`);
382
+ console.log(`Last feedback: ${feedback.substring(0, 100)}`);
383
+
384
+ } else {
385
+ console.log(`
386
+ Ralph Loop Implementation
387
+
388
+ Usage:
389
+ node ralph-loop-implementation.js init [task] [criteria] - Initialize a new loop
390
+ node ralph-loop-implementation.js run - Run the loop
391
+ node ralph-loop-implementation.js status - Check current status
392
+
393
+ Example:
394
+ node ralph-loop-implementation.js init "Add login feature" "- Tests pass\\n- JWT works\\n- Error handling"
395
+ node ralph-loop-implementation.js run
396
+ `);
397
+ }
398
+ }
399
+
400
+ if (import.meta.url === `file://${process.argv[1]}`) {
401
+ main().catch(console.error);
402
+ }
403
+
404
+ export { RalphLoop };