@stackmemoryai/stackmemory 1.10.5 → 1.14.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 (225) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +107 -24
  3. package/bin/claude-sm +16 -1
  4. package/bin/claude-smd +16 -1
  5. package/bin/codex-smd +16 -1
  6. package/bin/gemini-sm +16 -1
  7. package/bin/hermes-sm +21 -0
  8. package/bin/hermes-smd +21 -0
  9. package/bin/opencode-sm +16 -1
  10. package/dist/src/cli/claude-sm.js +266 -84
  11. package/dist/src/cli/codex-sm.js +225 -33
  12. package/dist/src/cli/commands/bench.js +209 -2
  13. package/dist/src/cli/commands/brain.js +206 -0
  14. package/dist/src/cli/commands/cache.js +126 -0
  15. package/dist/src/cli/commands/company-os.js +184 -0
  16. package/dist/src/cli/commands/context.js +5 -0
  17. package/dist/src/cli/commands/daemon.js +41 -0
  18. package/dist/src/cli/commands/handoff.js +40 -9
  19. package/dist/src/cli/commands/onboard.js +70 -3
  20. package/dist/src/cli/commands/operator.js +127 -0
  21. package/dist/src/cli/commands/optimize.js +117 -0
  22. package/dist/src/cli/commands/orchestrate.js +232 -5
  23. package/dist/src/cli/commands/orchestrator.js +315 -26
  24. package/dist/src/cli/commands/pack.js +322 -0
  25. package/dist/src/cli/commands/patterns.js +254 -0
  26. package/dist/src/cli/commands/portal.js +161 -0
  27. package/dist/src/cli/commands/scaffold.js +92 -0
  28. package/dist/src/cli/commands/search.js +40 -1
  29. package/dist/src/cli/commands/setup.js +178 -11
  30. package/dist/src/cli/commands/skills.js +10 -1
  31. package/dist/src/cli/commands/state.js +265 -0
  32. package/dist/src/cli/commands/sync.js +253 -0
  33. package/dist/src/cli/commands/tasks.js +130 -1
  34. package/dist/src/cli/commands/vision.js +221 -0
  35. package/dist/src/cli/gemini-sm.js +19 -29
  36. package/dist/src/cli/hermes-sm.js +224 -0
  37. package/dist/src/cli/index.js +105 -39
  38. package/dist/src/cli/opencode-sm.js +38 -21
  39. package/dist/src/cli/utils/determinism-watcher.js +66 -0
  40. package/dist/src/cli/utils/real-cli-bin.js +116 -0
  41. package/dist/src/core/brain/brain-store.js +187 -0
  42. package/dist/src/core/brain/brain-sync.js +193 -0
  43. package/dist/src/core/brain/index.js +78 -0
  44. package/dist/src/core/brain/types.js +10 -0
  45. package/dist/src/core/cache/content-cache.js +238 -0
  46. package/dist/src/{integrations/diffmem → core/cache}/index.js +5 -5
  47. package/dist/src/core/cache/token-estimator.js +39 -0
  48. package/dist/src/core/config/feature-flags.js +2 -6
  49. package/dist/src/core/context/frame-database.js +79 -27
  50. package/dist/src/core/context/recursive-context-manager.js +1 -1
  51. package/dist/src/core/context/rehydration.js +2 -1
  52. package/dist/src/core/cross-search/cross-project-search.js +269 -0
  53. package/dist/src/core/cross-search/index.js +10 -0
  54. package/dist/src/core/database/sqlite-adapter.js +14 -84
  55. package/dist/src/core/extensions/provider-adapter.js +5 -0
  56. package/dist/src/core/models/model-router.js +54 -2
  57. package/dist/src/core/models/provider-pricing.js +58 -4
  58. package/dist/src/core/monitoring/logger.js +2 -1
  59. package/dist/src/core/optimization/trace-optimizer.js +413 -0
  60. package/dist/src/core/patterns/index.js +22 -0
  61. package/dist/src/core/patterns/pattern-applier.js +39 -0
  62. package/dist/src/core/patterns/pattern-observer.js +157 -0
  63. package/dist/src/core/patterns/pattern-store.js +259 -0
  64. package/dist/src/core/patterns/types.js +19 -0
  65. package/dist/src/core/provenance/confidence-scorer.js +128 -0
  66. package/dist/src/core/provenance/index.js +40 -0
  67. package/dist/src/core/provenance/provenance-store.js +194 -0
  68. package/dist/src/core/provenance/types.js +82 -0
  69. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  70. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  71. package/dist/src/core/session/project-handoff.js +64 -0
  72. package/dist/src/core/session/session-manager.js +28 -0
  73. package/dist/src/core/shared-state/canonical-store.js +564 -0
  74. package/dist/src/core/skill-packs/index.js +18 -0
  75. package/dist/src/core/skill-packs/parser.js +42 -0
  76. package/dist/src/core/skill-packs/registry.js +224 -0
  77. package/dist/src/core/skill-packs/types.js +79 -0
  78. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  79. package/dist/src/core/storage/cloud-sync.js +574 -0
  80. package/dist/src/core/storage/two-tier-storage.js +5 -1
  81. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  82. package/dist/src/core/tasks/md-task-parser.js +138 -0
  83. package/dist/src/core/trace/trace-event-store.js +282 -0
  84. package/dist/src/core/vision/index.js +27 -0
  85. package/dist/src/core/vision/signals.js +79 -0
  86. package/dist/src/core/vision/types.js +22 -0
  87. package/dist/src/core/vision/vision-file.js +146 -0
  88. package/dist/src/core/vision/vision-loop.js +220 -0
  89. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  90. package/dist/src/daemon/daemon-config.js +52 -0
  91. package/dist/src/daemon/services/desire-path-service.js +566 -0
  92. package/dist/src/daemon/services/github-service.js +126 -0
  93. package/dist/src/daemon/services/research-stream-service.js +320 -0
  94. package/dist/src/daemon/services/telemetry-service.js +192 -0
  95. package/dist/src/daemon/unified-daemon.js +58 -1
  96. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  97. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  98. package/dist/src/features/operator/adapter-factory.js +62 -0
  99. package/dist/src/features/operator/browser-adapter.js +109 -0
  100. package/dist/src/features/operator/desktop-adapter.js +125 -0
  101. package/dist/src/features/operator/index.js +39 -0
  102. package/dist/src/features/operator/llm-decision.js +137 -0
  103. package/dist/src/features/operator/operator-logger.js +92 -0
  104. package/dist/src/features/operator/overnight-runner.js +327 -0
  105. package/dist/src/features/operator/screen-adapter.js +91 -0
  106. package/dist/src/features/operator/session-manager.js +127 -0
  107. package/dist/src/features/operator/state-machine.js +227 -0
  108. package/dist/src/features/operator/task-queue.js +81 -0
  109. package/dist/src/features/portal/index.js +26 -0
  110. package/dist/src/features/portal/server.js +240 -0
  111. package/dist/src/features/portal/types.js +14 -0
  112. package/dist/src/features/portal/ui.js +195 -0
  113. package/dist/src/features/sweep/pty-wrapper.js +13 -5
  114. package/dist/src/features/tasks/task-aware-context.js +2 -1
  115. package/dist/src/features/tui/simple-monitor.js +0 -23
  116. package/dist/src/features/tui/swarm-monitor.js +8 -66
  117. package/dist/src/features/web/client/hooks/use-socket.js +12 -0
  118. package/dist/src/{core/merge/index.js → features/web/client/lib/utils.js} +8 -4
  119. package/dist/src/features/web/client/next-env.d.js +4 -0
  120. package/dist/src/features/web/client/stores/session-store.js +12 -0
  121. package/dist/src/features/web/server/gcp-billing.js +76 -0
  122. package/dist/src/features/web/server/index.js +10 -0
  123. package/dist/src/features/web/server/spend-calculator.js +228 -0
  124. package/dist/src/hooks/schemas.js +6 -1
  125. package/dist/src/integrations/anthropic/client.js +3 -2
  126. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  127. package/dist/src/integrations/claude-code/subagent-client.js +307 -11
  128. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  129. package/dist/src/integrations/github/pr-state.js +158 -0
  130. package/dist/src/integrations/linear/client.js +4 -1
  131. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  132. package/dist/src/integrations/linear/webhook-server.js +18 -22
  133. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  134. package/dist/src/integrations/mcp/handlers/index.js +40 -84
  135. package/dist/src/integrations/mcp/server.js +542 -641
  136. package/dist/src/integrations/mcp/tool-alias-registry.js +297 -0
  137. package/dist/src/integrations/mcp/tool-definitions.js +152 -682
  138. package/dist/src/mcp/stackmemory-mcp-server.js +571 -231
  139. package/dist/src/orchestrators/multimodal/determinism.js +244 -0
  140. package/dist/src/orchestrators/multimodal/harness.js +149 -78
  141. package/dist/src/orchestrators/multimodal/providers.js +44 -3
  142. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  143. package/dist/src/utils/hook-installer.js +0 -8
  144. package/dist/src/utils/process-cleanup.js +1 -7
  145. package/docs/README.md +42 -0
  146. package/docs/guides/README_INSTALL.md +208 -0
  147. package/package.json +27 -9
  148. package/packs/coding/python-fastapi/instructions.md +60 -0
  149. package/packs/coding/python-fastapi/pack.yaml +28 -0
  150. package/packs/coding/typescript-react/instructions.md +47 -0
  151. package/packs/coding/typescript-react/pack.yaml +28 -0
  152. package/packs/core/commands/capture.md +32 -0
  153. package/packs/core/commands/learn.md +73 -0
  154. package/packs/core/commands/next.md +36 -0
  155. package/packs/core/commands/restart.md +58 -0
  156. package/packs/core/commands/restore.md +29 -0
  157. package/packs/core/commands/start.md +57 -0
  158. package/packs/core/commands/stop.md +65 -0
  159. package/packs/core/commands/summary.md +40 -0
  160. package/packs/core/manifest.json +24 -0
  161. package/packs/ops/decision-recovery/instructions.md +65 -0
  162. package/packs/ops/decision-recovery/pack.yaml +89 -0
  163. package/scripts/claude-code-wrapper.sh +11 -0
  164. package/scripts/claude-sm-setup.sh +12 -1
  165. package/scripts/codex-wrapper.sh +11 -0
  166. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  167. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  168. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  169. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  170. package/scripts/hooks/cleanup-shell.sh +12 -1
  171. package/scripts/hooks/task-complete.sh +12 -1
  172. package/scripts/install-code-execution-hooks.sh +12 -1
  173. package/scripts/install-sweep-hook.sh +12 -0
  174. package/scripts/install.sh +11 -0
  175. package/scripts/opencode-wrapper.sh +11 -0
  176. package/scripts/portal/cloud-init.yaml +69 -0
  177. package/scripts/portal/setup.sh +69 -0
  178. package/scripts/portal/stackmemory-portal.service +34 -0
  179. package/scripts/setup-claude-integration.sh +12 -1
  180. package/scripts/smoke-init-db.sh +23 -0
  181. package/scripts/stackmemory-daemon.sh +11 -0
  182. package/scripts/verify-dist.cjs +11 -4
  183. package/dist/src/cli/commands/ralph.js +0 -1053
  184. package/dist/src/cli/commands/team.js +0 -168
  185. package/dist/src/core/context/shared-context-layer.js +0 -620
  186. package/dist/src/core/context/stack-merge-resolver.js +0 -748
  187. package/dist/src/core/merge/conflict-detector.js +0 -430
  188. package/dist/src/core/merge/resolution-engine.js +0 -557
  189. package/dist/src/core/merge/stack-diff.js +0 -531
  190. package/dist/src/core/merge/unified-merge-resolver.js +0 -302
  191. package/dist/src/hooks/diffmem-hooks.js +0 -376
  192. package/dist/src/integrations/diffmem/client.js +0 -208
  193. package/dist/src/integrations/diffmem/config.js +0 -14
  194. package/dist/src/integrations/greptile/client.js +0 -101
  195. package/dist/src/integrations/greptile/config.js +0 -14
  196. package/dist/src/integrations/greptile/index.js +0 -11
  197. package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
  198. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  199. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  200. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  201. package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
  202. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  203. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  204. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -391
  205. package/dist/src/integrations/ralph/index.js +0 -17
  206. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -435
  207. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  208. package/dist/src/integrations/ralph/loopmax.js +0 -488
  209. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  210. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  211. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  212. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  213. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  214. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  215. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  216. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  217. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  218. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  219. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1007
  220. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  221. package/scripts/ralph-loop-implementation.js +0 -404
  222. /package/dist/src/core/{merge → cache}/types.js +0 -0
  223. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  224. /package/dist/src/{integrations/greptile/types.js → core/trace/trace-event.js} +0 -0
  225. /package/dist/src/{integrations/ralph → features/operator}/types.js +0 -0
@@ -1,448 +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 { EventEmitter } from "events";
6
- import { execSync } from "child_process";
7
- import { logger } from "../../../core/monitoring/logger.js";
8
- class IterationLifecycle extends EventEmitter {
9
- config;
10
- hooks = {};
11
- checkpoints = [];
12
- currentIteration;
13
- iterationHistory = [];
14
- activeTimers = /* @__PURE__ */ new Map();
15
- constructor(config, hooks) {
16
- super();
17
- this.config = {
18
- hooks: {
19
- preIteration: config?.hooks?.preIteration ?? true,
20
- postIteration: config?.hooks?.postIteration ?? true,
21
- onStateChange: config?.hooks?.onStateChange ?? true,
22
- onError: config?.hooks?.onError ?? true,
23
- onComplete: config?.hooks?.onComplete ?? true
24
- },
25
- checkpoints: {
26
- enabled: config?.checkpoints?.enabled ?? true,
27
- frequency: config?.checkpoints?.frequency || 5,
28
- retentionDays: config?.checkpoints?.retentionDays || 7
29
- }
30
- };
31
- if (hooks) {
32
- this.registerHooks(hooks);
33
- }
34
- this.setupEventHandlers();
35
- }
36
- /**
37
- * Register lifecycle hooks
38
- */
39
- registerHooks(hooks) {
40
- this.hooks = { ...this.hooks, ...hooks };
41
- logger.debug("Lifecycle hooks registered", {
42
- registered: Object.keys(hooks)
43
- });
44
- }
45
- /**
46
- * Start iteration with lifecycle management
47
- */
48
- async startIteration(iterationNumber, context) {
49
- logger.info("Starting iteration", { iteration: iterationNumber });
50
- this.emitEvent({
51
- type: "iteration.started",
52
- timestamp: Date.now(),
53
- iteration: iterationNumber,
54
- data: { context }
55
- });
56
- let processedContext = context;
57
- if (this.config.hooks.preIteration && this.hooks.preIteration) {
58
- try {
59
- processedContext = await this.hooks.preIteration(context);
60
- logger.debug("Pre-iteration hook executed", {
61
- original: context.tokenCount,
62
- processed: processedContext.tokenCount
63
- });
64
- } catch (error) {
65
- await this.handleError(error, { phase: "preIteration", context });
66
- }
67
- }
68
- this.startTimer(`iteration-${iterationNumber}`);
69
- return processedContext;
70
- }
71
- /**
72
- * Complete iteration with lifecycle management
73
- */
74
- async completeIteration(iteration) {
75
- logger.info("Completing iteration", { iteration: iteration.number });
76
- this.currentIteration = iteration;
77
- const duration = this.stopTimer(`iteration-${iteration.number}`);
78
- if (this.config.hooks.postIteration && this.hooks.postIteration) {
79
- try {
80
- await this.hooks.postIteration(iteration);
81
- logger.debug("Post-iteration hook executed");
82
- } catch (error) {
83
- await this.handleError(error, { phase: "postIteration", iteration });
84
- }
85
- }
86
- if (this.shouldCreateCheckpoint(iteration.number)) {
87
- await this.createCheckpoint(iteration);
88
- }
89
- this.emitEvent({
90
- type: "iteration.completed",
91
- timestamp: Date.now(),
92
- iteration: iteration.number,
93
- data: {
94
- iteration,
95
- duration,
96
- success: iteration.validation.testsPass
97
- }
98
- });
99
- await this.cleanOldCheckpoints();
100
- }
101
- /**
102
- * Handle iteration failure
103
- */
104
- async failIteration(iterationNumber, error, context) {
105
- logger.error("Iteration failed", {
106
- iteration: iterationNumber,
107
- error: error.message
108
- });
109
- this.stopTimer(`iteration-${iterationNumber}`);
110
- if (this.config.hooks.onError && this.hooks.onError) {
111
- try {
112
- await this.hooks.onError(error, context);
113
- } catch (hookError) {
114
- logger.error("Error hook failed", { error: hookError.message });
115
- }
116
- }
117
- this.emitEvent({
118
- type: "iteration.failed",
119
- timestamp: Date.now(),
120
- iteration: iterationNumber,
121
- data: {
122
- error: error.message,
123
- stack: error.stack,
124
- context
125
- }
126
- });
127
- }
128
- /**
129
- * Handle state change
130
- */
131
- async handleStateChange(oldState, newState) {
132
- logger.debug("State change detected", {
133
- old: oldState.status,
134
- new: newState.status,
135
- iteration: newState.iteration
136
- });
137
- if (this.config.hooks.onStateChange && this.hooks.onStateChange) {
138
- try {
139
- await this.hooks.onStateChange(oldState, newState);
140
- } catch (error) {
141
- await this.handleError(error, {
142
- phase: "stateChange",
143
- oldState,
144
- newState
145
- });
146
- }
147
- }
148
- this.emitEvent({
149
- type: "state.changed",
150
- timestamp: Date.now(),
151
- iteration: newState.iteration,
152
- data: {
153
- oldStatus: oldState.status,
154
- newStatus: newState.status,
155
- changes: this.detectStateChanges(oldState, newState)
156
- }
157
- });
158
- if (newState.status === "completed" && oldState.status !== "completed") {
159
- await this.handleCompletion(newState);
160
- }
161
- }
162
- /**
163
- * Handle loop completion
164
- */
165
- async handleCompletion(state) {
166
- logger.info("Loop completed", {
167
- iterations: state.iteration,
168
- duration: state.lastUpdateTime - state.startTime
169
- });
170
- if (this.config.hooks.onComplete && this.hooks.onComplete) {
171
- try {
172
- await this.hooks.onComplete(state);
173
- } catch (error) {
174
- await this.handleError(error, { phase: "completion", state });
175
- }
176
- }
177
- await this.createFinalCheckpoint(state);
178
- this.cleanupTimers();
179
- }
180
- /**
181
- * Create checkpoint
182
- */
183
- async createCheckpoint(iteration) {
184
- const checkpoint = {
185
- id: this.generateCheckpointId(),
186
- iteration: iteration.number,
187
- timestamp: Date.now(),
188
- state: await this.captureCurrentState(),
189
- gitCommit: await this.getCurrentGitCommit(),
190
- verified: false
191
- };
192
- checkpoint.verified = await this.verifyCheckpoint(checkpoint);
193
- this.checkpoints.push(checkpoint);
194
- logger.info("Checkpoint created", {
195
- id: checkpoint.id,
196
- iteration: checkpoint.iteration,
197
- verified: checkpoint.verified
198
- });
199
- if (this.hooks.onCheckpoint) {
200
- try {
201
- await this.hooks.onCheckpoint(checkpoint);
202
- } catch (error) {
203
- logger.error("Checkpoint hook failed", { error: error.message });
204
- }
205
- }
206
- this.emitEvent({
207
- type: "checkpoint.created",
208
- timestamp: Date.now(),
209
- iteration: iteration.number,
210
- data: { checkpoint }
211
- });
212
- return checkpoint;
213
- }
214
- /**
215
- * Get checkpoints
216
- */
217
- getCheckpoints() {
218
- return [...this.checkpoints];
219
- }
220
- /**
221
- * Get last checkpoint
222
- */
223
- getLastCheckpoint() {
224
- return this.checkpoints[this.checkpoints.length - 1];
225
- }
226
- /**
227
- * Restore from checkpoint
228
- */
229
- async restoreFromCheckpoint(checkpointId) {
230
- const checkpoint = this.checkpoints.find((c) => c.id === checkpointId);
231
- if (!checkpoint) {
232
- throw new Error(`Checkpoint not found: ${checkpointId}`);
233
- }
234
- logger.info("Restoring from checkpoint", {
235
- id: checkpoint.id,
236
- iteration: checkpoint.iteration
237
- });
238
- if (checkpoint.gitCommit) {
239
- await this.restoreGitState(checkpoint.gitCommit);
240
- }
241
- await this.restoreRalphState(checkpoint.state);
242
- logger.info("Checkpoint restored successfully");
243
- }
244
- /**
245
- * Get iteration events
246
- */
247
- getEvents(filter) {
248
- let events = [...this.iterationHistory];
249
- if (filter?.type) {
250
- events = events.filter((e) => e.type === filter.type);
251
- }
252
- if (filter?.iteration !== void 0) {
253
- events = events.filter((e) => e.iteration === filter.iteration);
254
- }
255
- if (filter?.since) {
256
- events = events.filter((e) => e.timestamp >= filter.since);
257
- }
258
- return events;
259
- }
260
- /**
261
- * Clean up resources
262
- */
263
- cleanup() {
264
- this.cleanupTimers();
265
- this.removeAllListeners();
266
- this.iterationHistory = [];
267
- this.checkpoints = [];
268
- }
269
- /**
270
- * Setup internal event handlers
271
- */
272
- setupEventHandlers() {
273
- this.on("*", (event) => {
274
- logger.debug("Lifecycle event", {
275
- type: event.type,
276
- iteration: event.iteration
277
- });
278
- });
279
- }
280
- /**
281
- * Emit and track event
282
- */
283
- emitEvent(event) {
284
- this.iterationHistory.push(event);
285
- this.emit(event.type, event);
286
- this.emit("*", event);
287
- }
288
- /**
289
- * Should create checkpoint based on frequency
290
- */
291
- shouldCreateCheckpoint(iteration) {
292
- if (!this.config.checkpoints.enabled) {
293
- return false;
294
- }
295
- return iteration % this.config.checkpoints.frequency === 0;
296
- }
297
- /**
298
- * Generate checkpoint ID
299
- */
300
- generateCheckpointId() {
301
- return `chk-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
302
- }
303
- /**
304
- * Capture current state
305
- */
306
- async captureCurrentState() {
307
- return {
308
- loopId: "current",
309
- task: "",
310
- criteria: "",
311
- iteration: this.currentIteration?.number || 0,
312
- status: "running",
313
- startTime: Date.now(),
314
- lastUpdateTime: Date.now()
315
- };
316
- }
317
- /**
318
- * Get current git commit
319
- */
320
- async getCurrentGitCommit() {
321
- try {
322
- return execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
323
- } catch {
324
- return "";
325
- }
326
- }
327
- /**
328
- * Verify checkpoint integrity
329
- */
330
- async verifyCheckpoint(checkpoint) {
331
- try {
332
- if (!checkpoint.state.loopId || !checkpoint.state.task) {
333
- return false;
334
- }
335
- if (checkpoint.gitCommit) {
336
- execSync(`git rev-parse ${checkpoint.gitCommit}`, { encoding: "utf8" });
337
- }
338
- return true;
339
- } catch {
340
- return false;
341
- }
342
- }
343
- /**
344
- * Clean old checkpoints based on retention
345
- */
346
- async cleanOldCheckpoints() {
347
- const cutoff = Date.now() - this.config.checkpoints.retentionDays * 24 * 60 * 60 * 1e3;
348
- const before = this.checkpoints.length;
349
- this.checkpoints = this.checkpoints.filter((c) => c.timestamp >= cutoff);
350
- const removed = before - this.checkpoints.length;
351
- if (removed > 0) {
352
- logger.debug("Cleaned old checkpoints", { removed });
353
- }
354
- }
355
- /**
356
- * Create final checkpoint
357
- */
358
- async createFinalCheckpoint(state) {
359
- const checkpoint = {
360
- id: `final-${this.generateCheckpointId()}`,
361
- iteration: state.iteration,
362
- timestamp: Date.now(),
363
- state,
364
- gitCommit: await this.getCurrentGitCommit(),
365
- verified: true
366
- };
367
- this.checkpoints.push(checkpoint);
368
- logger.info("Final checkpoint created", {
369
- id: checkpoint.id,
370
- iterations: state.iteration
371
- });
372
- }
373
- /**
374
- * Restore git state
375
- */
376
- async restoreGitState(commit) {
377
- execSync("git stash", { encoding: "utf8" });
378
- execSync(`git checkout ${commit}`, { encoding: "utf8" });
379
- }
380
- /**
381
- * Restore Ralph state
382
- */
383
- async restoreRalphState(state) {
384
- logger.debug("Ralph state restored", { iteration: state.iteration });
385
- }
386
- /**
387
- * Detect state changes
388
- */
389
- detectStateChanges(oldState, newState) {
390
- const changes = [];
391
- for (const key of Object.keys(newState)) {
392
- if (JSON.stringify(oldState[key]) !== JSON.stringify(newState[key])) {
393
- changes.push(key);
394
- }
395
- }
396
- return changes;
397
- }
398
- /**
399
- * Handle errors
400
- */
401
- async handleError(error, context) {
402
- logger.error("Lifecycle error", {
403
- error: error.message,
404
- context
405
- });
406
- if (this.config.hooks.onError && this.hooks.onError) {
407
- try {
408
- await this.hooks.onError(error, context);
409
- } catch (hookError) {
410
- logger.error("Error hook failed", { error: hookError.message });
411
- }
412
- }
413
- }
414
- /**
415
- * Start timer for metrics
416
- */
417
- startTimer(name) {
418
- const start = Date.now();
419
- const timeout = setTimeout(() => {
420
- this.activeTimers.delete(name);
421
- }, 0);
422
- timeout.startTime = start;
423
- this.activeTimers.set(name, timeout);
424
- }
425
- /**
426
- * Stop timer and get duration
427
- */
428
- stopTimer(name) {
429
- const timer = this.activeTimers.get(name);
430
- if (!timer) return 0;
431
- const duration = Date.now() - (timer.startTime || Date.now());
432
- clearTimeout(timer);
433
- this.activeTimers.delete(name);
434
- return duration;
435
- }
436
- /**
437
- * Clean up all timers
438
- */
439
- cleanupTimers() {
440
- for (const timer of this.activeTimers.values()) {
441
- clearTimeout(timer);
442
- }
443
- this.activeTimers.clear();
444
- }
445
- }
446
- export {
447
- IterationLifecycle
448
- };