ghcralph 0.1.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 (160) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +327 -0
  3. package/bin/ghcralph.js +2 -0
  4. package/dist/cli.d.ts +12 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +92 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/config.d.ts +8 -0
  9. package/dist/commands/config.d.ts.map +1 -0
  10. package/dist/commands/config.js +118 -0
  11. package/dist/commands/config.js.map +1 -0
  12. package/dist/commands/index.d.ts +11 -0
  13. package/dist/commands/index.d.ts.map +1 -0
  14. package/dist/commands/index.js +11 -0
  15. package/dist/commands/index.js.map +1 -0
  16. package/dist/commands/init.d.ts +15 -0
  17. package/dist/commands/init.d.ts.map +1 -0
  18. package/dist/commands/init.js +116 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/rollback.d.ts +8 -0
  21. package/dist/commands/rollback.d.ts.map +1 -0
  22. package/dist/commands/rollback.js +238 -0
  23. package/dist/commands/rollback.js.map +1 -0
  24. package/dist/commands/run.d.ts +28 -0
  25. package/dist/commands/run.d.ts.map +1 -0
  26. package/dist/commands/run.js +407 -0
  27. package/dist/commands/run.js.map +1 -0
  28. package/dist/commands/status.d.ts +8 -0
  29. package/dist/commands/status.d.ts.map +1 -0
  30. package/dist/commands/status.js +399 -0
  31. package/dist/commands/status.js.map +1 -0
  32. package/dist/core/action-executor.d.ts +96 -0
  33. package/dist/core/action-executor.d.ts.map +1 -0
  34. package/dist/core/action-executor.js +289 -0
  35. package/dist/core/action-executor.js.map +1 -0
  36. package/dist/core/checkpoint-manager.d.ts +94 -0
  37. package/dist/core/checkpoint-manager.d.ts.map +1 -0
  38. package/dist/core/checkpoint-manager.js +236 -0
  39. package/dist/core/checkpoint-manager.js.map +1 -0
  40. package/dist/core/config-manager.d.ts +62 -0
  41. package/dist/core/config-manager.d.ts.map +1 -0
  42. package/dist/core/config-manager.js +184 -0
  43. package/dist/core/config-manager.js.map +1 -0
  44. package/dist/core/config-schema.d.ts +74 -0
  45. package/dist/core/config-schema.d.ts.map +1 -0
  46. package/dist/core/config-schema.js +84 -0
  47. package/dist/core/config-schema.js.map +1 -0
  48. package/dist/core/context-builder.d.ts +116 -0
  49. package/dist/core/context-builder.d.ts.map +1 -0
  50. package/dist/core/context-builder.js +388 -0
  51. package/dist/core/context-builder.js.map +1 -0
  52. package/dist/core/feedback-builder.d.ts +94 -0
  53. package/dist/core/feedback-builder.d.ts.map +1 -0
  54. package/dist/core/feedback-builder.js +226 -0
  55. package/dist/core/feedback-builder.js.map +1 -0
  56. package/dist/core/file-safeguard.d.ts +109 -0
  57. package/dist/core/file-safeguard.d.ts.map +1 -0
  58. package/dist/core/file-safeguard.js +200 -0
  59. package/dist/core/file-safeguard.js.map +1 -0
  60. package/dist/core/git-branch-manager.d.ts +122 -0
  61. package/dist/core/git-branch-manager.d.ts.map +1 -0
  62. package/dist/core/git-branch-manager.js +302 -0
  63. package/dist/core/git-branch-manager.js.map +1 -0
  64. package/dist/core/github-plan.d.ts +86 -0
  65. package/dist/core/github-plan.d.ts.map +1 -0
  66. package/dist/core/github-plan.js +333 -0
  67. package/dist/core/github-plan.js.map +1 -0
  68. package/dist/core/index.d.ts +43 -0
  69. package/dist/core/index.d.ts.map +1 -0
  70. package/dist/core/index.js +26 -0
  71. package/dist/core/index.js.map +1 -0
  72. package/dist/core/local-markdown-plan.d.ts +65 -0
  73. package/dist/core/local-markdown-plan.d.ts.map +1 -0
  74. package/dist/core/local-markdown-plan.js +154 -0
  75. package/dist/core/local-markdown-plan.js.map +1 -0
  76. package/dist/core/loop-engine.d.ts +133 -0
  77. package/dist/core/loop-engine.d.ts.map +1 -0
  78. package/dist/core/loop-engine.js +420 -0
  79. package/dist/core/loop-engine.js.map +1 -0
  80. package/dist/core/loop-events.d.ts +48 -0
  81. package/dist/core/loop-events.d.ts.map +1 -0
  82. package/dist/core/loop-events.js +24 -0
  83. package/dist/core/loop-events.js.map +1 -0
  84. package/dist/core/loop-state.d.ts +51 -0
  85. package/dist/core/loop-state.d.ts.map +1 -0
  86. package/dist/core/loop-state.js +48 -0
  87. package/dist/core/loop-state.js.map +1 -0
  88. package/dist/core/markdown-parser.d.ts +51 -0
  89. package/dist/core/markdown-parser.d.ts.map +1 -0
  90. package/dist/core/markdown-parser.js +122 -0
  91. package/dist/core/markdown-parser.js.map +1 -0
  92. package/dist/core/plan-manager.d.ts +61 -0
  93. package/dist/core/plan-manager.d.ts.map +1 -0
  94. package/dist/core/plan-manager.js +7 -0
  95. package/dist/core/plan-manager.js.map +1 -0
  96. package/dist/core/progress-tracker.d.ts +74 -0
  97. package/dist/core/progress-tracker.d.ts.map +1 -0
  98. package/dist/core/progress-tracker.js +198 -0
  99. package/dist/core/progress-tracker.js.map +1 -0
  100. package/dist/core/prompt-examples.d.ts +52 -0
  101. package/dist/core/prompt-examples.d.ts.map +1 -0
  102. package/dist/core/prompt-examples.js +194 -0
  103. package/dist/core/prompt-examples.js.map +1 -0
  104. package/dist/core/response-parser.d.ts +90 -0
  105. package/dist/core/response-parser.d.ts.map +1 -0
  106. package/dist/core/response-parser.js +209 -0
  107. package/dist/core/response-parser.js.map +1 -0
  108. package/dist/core/verification-hooks.d.ts +103 -0
  109. package/dist/core/verification-hooks.d.ts.map +1 -0
  110. package/dist/core/verification-hooks.js +268 -0
  111. package/dist/core/verification-hooks.js.map +1 -0
  112. package/dist/index.d.ts +13 -0
  113. package/dist/index.d.ts.map +1 -0
  114. package/dist/index.js +17 -0
  115. package/dist/index.js.map +1 -0
  116. package/dist/integrations/auth.d.ts +28 -0
  117. package/dist/integrations/auth.d.ts.map +1 -0
  118. package/dist/integrations/auth.js +76 -0
  119. package/dist/integrations/auth.js.map +1 -0
  120. package/dist/integrations/copilot-agent.d.ts +104 -0
  121. package/dist/integrations/copilot-agent.d.ts.map +1 -0
  122. package/dist/integrations/copilot-agent.js +235 -0
  123. package/dist/integrations/copilot-agent.js.map +1 -0
  124. package/dist/integrations/index.d.ts +18 -0
  125. package/dist/integrations/index.d.ts.map +1 -0
  126. package/dist/integrations/index.js +14 -0
  127. package/dist/integrations/index.js.map +1 -0
  128. package/dist/integrations/mcp-tools.d.ts +129 -0
  129. package/dist/integrations/mcp-tools.d.ts.map +1 -0
  130. package/dist/integrations/mcp-tools.js +272 -0
  131. package/dist/integrations/mcp-tools.js.map +1 -0
  132. package/dist/integrations/tokens.d.ts +45 -0
  133. package/dist/integrations/tokens.d.ts.map +1 -0
  134. package/dist/integrations/tokens.js +50 -0
  135. package/dist/integrations/tokens.js.map +1 -0
  136. package/dist/types/index.d.ts +53 -0
  137. package/dist/types/index.d.ts.map +1 -0
  138. package/dist/types/index.js +7 -0
  139. package/dist/types/index.js.map +1 -0
  140. package/dist/utils/index.d.ts +23 -0
  141. package/dist/utils/index.d.ts.map +1 -0
  142. package/dist/utils/index.js +37 -0
  143. package/dist/utils/index.js.map +1 -0
  144. package/dist/utils/output.d.ts +59 -0
  145. package/dist/utils/output.d.ts.map +1 -0
  146. package/dist/utils/output.js +96 -0
  147. package/dist/utils/output.js.map +1 -0
  148. package/dist/utils/paths.d.ts +34 -0
  149. package/dist/utils/paths.d.ts.map +1 -0
  150. package/dist/utils/paths.js +67 -0
  151. package/dist/utils/paths.js.map +1 -0
  152. package/dist/utils/shell.d.ts +26 -0
  153. package/dist/utils/shell.d.ts.map +1 -0
  154. package/dist/utils/shell.js +65 -0
  155. package/dist/utils/shell.js.map +1 -0
  156. package/dist/utils/validation.d.ts +27 -0
  157. package/dist/utils/validation.d.ts.map +1 -0
  158. package/dist/utils/validation.js +43 -0
  159. package/dist/utils/validation.js.map +1 -0
  160. package/package.json +86 -0
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Action Executor
3
+ *
4
+ * Executes parsed actions from AI responses.
5
+ * This component bridges the gap between AI intent and filesystem reality.
6
+ */
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+ import { exec } from 'node:child_process';
10
+ import { promisify } from 'node:util';
11
+ import { debug, info, warn } from '../utils/index.js';
12
+ const execAsync = promisify(exec);
13
+ const DEFAULT_CONFIG = {
14
+ cwd: process.cwd(),
15
+ execute: true,
16
+ commandTimeout: 30000, // 30 seconds
17
+ };
18
+ /**
19
+ * Action Executor class
20
+ */
21
+ export class ActionExecutor {
22
+ config;
23
+ constructor(config = {}) {
24
+ this.config = { ...DEFAULT_CONFIG, ...config };
25
+ }
26
+ /**
27
+ * Execute all actions from a parsed response
28
+ */
29
+ async executeAll(parseResult) {
30
+ const results = [];
31
+ let taskComplete = false;
32
+ let completionReason;
33
+ for (const action of parseResult.actions) {
34
+ const result = await this.executeAction(action);
35
+ results.push(result);
36
+ if (action.type === 'COMPLETE' && result.success) {
37
+ taskComplete = true;
38
+ completionReason = action.reason;
39
+ }
40
+ // Stop on first failure (except for COMPLETE which is informational)
41
+ if (!result.success && action.type !== 'COMPLETE') {
42
+ warn(`Action failed: ${result.error}`);
43
+ // Continue with remaining actions? For now, we'll continue
44
+ }
45
+ }
46
+ const allSucceeded = results.every((r) => r.success);
47
+ const summary = this.buildSummary(results);
48
+ const executionResult = {
49
+ results,
50
+ allSucceeded,
51
+ taskComplete,
52
+ summary,
53
+ };
54
+ if (completionReason) {
55
+ executionResult.completionReason = completionReason;
56
+ }
57
+ return executionResult;
58
+ }
59
+ /**
60
+ * Execute a single action
61
+ */
62
+ async executeAction(action) {
63
+ debug(`Executing action: ${action.type}`);
64
+ if (!this.config.execute) {
65
+ return {
66
+ action,
67
+ success: true,
68
+ message: `[DRY RUN] Would execute ${action.type}`,
69
+ };
70
+ }
71
+ try {
72
+ switch (action.type) {
73
+ case 'CREATE':
74
+ return await this.executeCreate(action);
75
+ case 'EDIT':
76
+ return await this.executeEdit(action);
77
+ case 'DELETE':
78
+ return await this.executeDelete(action);
79
+ case 'EXECUTE':
80
+ return await this.executeCommand(action);
81
+ case 'COMPLETE':
82
+ return this.executeComplete(action);
83
+ default:
84
+ return {
85
+ action,
86
+ success: false,
87
+ message: `Unknown action type`,
88
+ error: `Unknown action type: ${action.type}`,
89
+ };
90
+ }
91
+ }
92
+ catch (err) {
93
+ const errorMsg = err instanceof Error ? err.message : String(err);
94
+ return {
95
+ action,
96
+ success: false,
97
+ message: `Failed to execute ${action.type}`,
98
+ error: errorMsg,
99
+ };
100
+ }
101
+ }
102
+ /**
103
+ * Execute a CREATE action
104
+ */
105
+ async executeCreate(action) {
106
+ const fullPath = path.resolve(this.config.cwd, action.path);
107
+ // Security: ensure path is within cwd
108
+ if (!fullPath.startsWith(this.config.cwd)) {
109
+ return {
110
+ action,
111
+ success: false,
112
+ message: `Cannot create file outside working directory`,
113
+ error: `Path escapes working directory: ${action.path}`,
114
+ };
115
+ }
116
+ // Create parent directories if needed
117
+ const dir = path.dirname(fullPath);
118
+ await fs.mkdir(dir, { recursive: true });
119
+ // Write the file
120
+ await fs.writeFile(fullPath, action.content, 'utf-8');
121
+ // Make executable if it's a script
122
+ if (action.path.endsWith('.sh') || action.content.startsWith('#!/')) {
123
+ await fs.chmod(fullPath, 0o755);
124
+ }
125
+ info(`Created: ${action.path}`);
126
+ return {
127
+ action,
128
+ success: true,
129
+ message: `Created ${action.path}`,
130
+ };
131
+ }
132
+ /**
133
+ * Execute an EDIT action
134
+ */
135
+ async executeEdit(action) {
136
+ const fullPath = path.resolve(this.config.cwd, action.path);
137
+ // Security: ensure path is within cwd
138
+ if (!fullPath.startsWith(this.config.cwd)) {
139
+ return {
140
+ action,
141
+ success: false,
142
+ message: `Cannot edit file outside working directory`,
143
+ error: `Path escapes working directory: ${action.path}`,
144
+ };
145
+ }
146
+ // Read current content
147
+ let content;
148
+ try {
149
+ content = await fs.readFile(fullPath, 'utf-8');
150
+ }
151
+ catch {
152
+ return {
153
+ action,
154
+ success: false,
155
+ message: `File not found: ${action.path}`,
156
+ error: `Cannot edit non-existent file: ${action.path}`,
157
+ };
158
+ }
159
+ // Find and replace the old content
160
+ if (!content.includes(action.oldContent)) {
161
+ return {
162
+ action,
163
+ success: false,
164
+ message: `Old content not found in ${action.path}`,
165
+ error: `The specified old content was not found in the file`,
166
+ };
167
+ }
168
+ const newFileContent = content.replace(action.oldContent, action.newContent);
169
+ await fs.writeFile(fullPath, newFileContent, 'utf-8');
170
+ info(`Edited: ${action.path}`);
171
+ return {
172
+ action,
173
+ success: true,
174
+ message: `Edited ${action.path}`,
175
+ };
176
+ }
177
+ /**
178
+ * Execute a DELETE action
179
+ */
180
+ async executeDelete(action) {
181
+ const fullPath = path.resolve(this.config.cwd, action.path);
182
+ // Security: ensure path is within cwd
183
+ if (!fullPath.startsWith(this.config.cwd)) {
184
+ return {
185
+ action,
186
+ success: false,
187
+ message: `Cannot delete file outside working directory`,
188
+ error: `Path escapes working directory: ${action.path}`,
189
+ };
190
+ }
191
+ // Check file safeguard
192
+ if (this.config.fileSafeguard && !this.config.fileSafeguard.canDelete(action.path)) {
193
+ return {
194
+ action,
195
+ success: false,
196
+ message: `Cannot delete protected file: ${action.path}`,
197
+ error: `File is protected by safeguard (existed before session)`,
198
+ };
199
+ }
200
+ // Check if file exists
201
+ try {
202
+ await fs.access(fullPath);
203
+ }
204
+ catch {
205
+ return {
206
+ action,
207
+ success: false,
208
+ message: `File not found: ${action.path}`,
209
+ error: `Cannot delete non-existent file`,
210
+ };
211
+ }
212
+ await fs.unlink(fullPath);
213
+ info(`Deleted: ${action.path}`);
214
+ return {
215
+ action,
216
+ success: true,
217
+ message: `Deleted ${action.path}`,
218
+ };
219
+ }
220
+ /**
221
+ * Execute an EXECUTE action (shell command)
222
+ */
223
+ async executeCommand(action) {
224
+ info(`Executing: ${action.command}`);
225
+ try {
226
+ const { stdout, stderr } = await execAsync(action.command, {
227
+ cwd: this.config.cwd,
228
+ timeout: this.config.commandTimeout,
229
+ maxBuffer: 1024 * 1024, // 1MB
230
+ });
231
+ const output = stdout + (stderr ? `\nSTDERR:\n${stderr}` : '');
232
+ return {
233
+ action,
234
+ success: true,
235
+ message: `Executed: ${action.command}`,
236
+ output: output.trim(),
237
+ };
238
+ }
239
+ catch (err) {
240
+ const execError = err;
241
+ const output = (execError.stdout ?? '') + (execError.stderr ? `\nSTDERR:\n${execError.stderr}` : '');
242
+ return {
243
+ action,
244
+ success: false,
245
+ message: `Command failed: ${action.command}`,
246
+ output: output.trim(),
247
+ error: execError.message ?? 'Command execution failed',
248
+ };
249
+ }
250
+ }
251
+ /**
252
+ * Execute a COMPLETE action (just marks completion)
253
+ */
254
+ executeComplete(action) {
255
+ info(`Task complete: ${action.reason}`);
256
+ return {
257
+ action,
258
+ success: true,
259
+ message: `Task marked complete: ${action.reason}`,
260
+ };
261
+ }
262
+ /**
263
+ * Build a human-readable summary of executed actions
264
+ */
265
+ buildSummary(results) {
266
+ const parts = [];
267
+ const succeeded = results.filter((r) => r.success);
268
+ const failed = results.filter((r) => !r.success);
269
+ for (const result of succeeded) {
270
+ const icon = '✓';
271
+ parts.push(`${icon} ${result.message}`);
272
+ }
273
+ for (const result of failed) {
274
+ const icon = '✗';
275
+ parts.push(`${icon} ${result.message}: ${result.error}`);
276
+ }
277
+ if (parts.length === 0) {
278
+ return 'No actions executed';
279
+ }
280
+ return parts.join('\n');
281
+ }
282
+ }
283
+ /**
284
+ * Create an action executor with custom configuration
285
+ */
286
+ export function createActionExecutor(config) {
287
+ return new ActionExecutor(config);
288
+ }
289
+ //# sourceMappingURL=action-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-executor.js","sourceRoot":"","sources":["../../src/core/action-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Checkpoint Manager
3
+ *
4
+ * Manages automatic git commits after each loop iteration
5
+ */
6
+ /**
7
+ * Checkpoint configuration
8
+ */
9
+ export interface CheckpointConfig {
10
+ /** Whether to auto-commit after each iteration (default: true) */
11
+ autoCommit: boolean;
12
+ /** Prefix for commit messages (default: 'ghcralph:') */
13
+ messagePrefix: string;
14
+ /** Working directory */
15
+ cwd: string;
16
+ }
17
+ /**
18
+ * Checkpoint record
19
+ */
20
+ export interface Checkpoint {
21
+ /** Iteration number */
22
+ iteration: number;
23
+ /** Commit hash */
24
+ commitHash: string;
25
+ /** Commit message */
26
+ message: string;
27
+ /** Files modified in this commit */
28
+ filesModified: string[];
29
+ /** Timestamp of the commit */
30
+ timestamp: Date;
31
+ /** Token usage for the iteration */
32
+ tokensUsed: number;
33
+ }
34
+ /**
35
+ * Checkpoint Manager class
36
+ */
37
+ export declare class CheckpointManager {
38
+ private config;
39
+ private checkpoints;
40
+ constructor(config?: Partial<CheckpointConfig>);
41
+ /**
42
+ * Check if auto-commit is enabled
43
+ */
44
+ isAutoCommitEnabled(): boolean;
45
+ /**
46
+ * Get all checkpoints
47
+ */
48
+ getCheckpoints(): Checkpoint[];
49
+ /**
50
+ * Get the last checkpoint
51
+ */
52
+ getLastCheckpoint(): Checkpoint | null;
53
+ /**
54
+ * Check if there are any modified files to commit
55
+ */
56
+ hasChangesToCommit(): Promise<boolean>;
57
+ /**
58
+ * Get list of modified files
59
+ */
60
+ getModifiedFiles(): Promise<string[]>;
61
+ /**
62
+ * Stage all modified files
63
+ */
64
+ stageAllChanges(): Promise<boolean>;
65
+ /**
66
+ * Create a checkpoint commit
67
+ */
68
+ createCheckpoint(iteration: number, summary: string, tokensUsed: number): Promise<Checkpoint | null>;
69
+ /**
70
+ * Rollback to a specific checkpoint
71
+ */
72
+ rollbackTo(commitHash: string): Promise<boolean>;
73
+ /**
74
+ * Hard rollback to a specific checkpoint (discard changes)
75
+ */
76
+ hardRollbackTo(commitHash: string): Promise<boolean>;
77
+ /**
78
+ * Rollback by N iterations
79
+ */
80
+ rollbackIterations(count?: number): Promise<boolean>;
81
+ /**
82
+ * Get the initial commit hash before Ralph started
83
+ */
84
+ getInitialCommit(): Promise<string | null>;
85
+ /**
86
+ * Rollback all Ralph changes (to state before Ralph started)
87
+ */
88
+ rollbackAll(): Promise<boolean>;
89
+ }
90
+ /**
91
+ * Create a checkpoint manager with configuration
92
+ */
93
+ export declare function createCheckpointManager(config?: Partial<CheckpointConfig>): CheckpointManager;
94
+ //# sourceMappingURL=checkpoint-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-manager.d.ts","sourceRoot":"","sources":["../../src/core/checkpoint-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,UAAU,EAAE,OAAO,CAAC;IACpB,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;CACb;AAWD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,IAAI,CAAC;IAChB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAoB;gBAE3B,MAAM,GAAE,OAAO,CAAC,gBAAgB,CAAM;IAIlD;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAI9B;;OAEG;IACH,cAAc,IAAI,UAAU,EAAE;IAI9B;;OAEG;IACH,iBAAiB,IAAI,UAAU,GAAG,IAAI;IAQtC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;IAS5C;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAa3C;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWzC;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAyD7B;;OAEG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYtD;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW1D;;OAEG;IACG,kBAAkB,CAAC,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IA8B7D;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgBhD;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAStC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,iBAAiB,CAE7F"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Checkpoint Manager
3
+ *
4
+ * Manages automatic git commits after each loop iteration
5
+ */
6
+ import { exec } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+ import { debug, warn } from '../utils/index.js';
9
+ const execAsync = promisify(exec);
10
+ /**
11
+ * Default configuration
12
+ */
13
+ const DEFAULT_CONFIG = {
14
+ autoCommit: true,
15
+ messagePrefix: 'ghcralph:',
16
+ cwd: process.cwd(),
17
+ };
18
+ /**
19
+ * Checkpoint Manager class
20
+ */
21
+ export class CheckpointManager {
22
+ config;
23
+ checkpoints = [];
24
+ constructor(config = {}) {
25
+ this.config = { ...DEFAULT_CONFIG, ...config };
26
+ }
27
+ /**
28
+ * Check if auto-commit is enabled
29
+ */
30
+ isAutoCommitEnabled() {
31
+ return this.config.autoCommit;
32
+ }
33
+ /**
34
+ * Get all checkpoints
35
+ */
36
+ getCheckpoints() {
37
+ return [...this.checkpoints];
38
+ }
39
+ /**
40
+ * Get the last checkpoint
41
+ */
42
+ getLastCheckpoint() {
43
+ if (this.checkpoints.length === 0) {
44
+ return null;
45
+ }
46
+ const last = this.checkpoints[this.checkpoints.length - 1];
47
+ return last ?? null;
48
+ }
49
+ /**
50
+ * Check if there are any modified files to commit
51
+ */
52
+ async hasChangesToCommit() {
53
+ try {
54
+ const { stdout } = await execAsync('git status --porcelain', { cwd: this.config.cwd });
55
+ return stdout.trim().length > 0;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ /**
62
+ * Get list of modified files
63
+ */
64
+ async getModifiedFiles() {
65
+ try {
66
+ const { stdout } = await execAsync('git status --porcelain', { cwd: this.config.cwd });
67
+ return stdout
68
+ .trim()
69
+ .split('\n')
70
+ .filter(Boolean)
71
+ .map(line => line.substring(3).trim());
72
+ }
73
+ catch {
74
+ return [];
75
+ }
76
+ }
77
+ /**
78
+ * Stage all modified files
79
+ */
80
+ async stageAllChanges() {
81
+ try {
82
+ await execAsync('git add -A', { cwd: this.config.cwd });
83
+ debug('Staged all changes');
84
+ return true;
85
+ }
86
+ catch (err) {
87
+ warn('Failed to stage changes: ' + (err instanceof Error ? err.message : String(err)));
88
+ return false;
89
+ }
90
+ }
91
+ /**
92
+ * Create a checkpoint commit
93
+ */
94
+ async createCheckpoint(iteration, summary, tokensUsed) {
95
+ if (!this.config.autoCommit) {
96
+ debug('Auto-commit disabled, skipping checkpoint');
97
+ return null;
98
+ }
99
+ // Check if there are changes to commit
100
+ const hasChanges = await this.hasChangesToCommit();
101
+ if (!hasChanges) {
102
+ debug('No changes to commit for checkpoint');
103
+ return null;
104
+ }
105
+ // Get list of modified files before staging
106
+ const filesModified = await this.getModifiedFiles();
107
+ // Stage all changes
108
+ const staged = await this.stageAllChanges();
109
+ if (!staged) {
110
+ return null;
111
+ }
112
+ // Build commit message
113
+ const truncatedSummary = summary.length > 50
114
+ ? summary.substring(0, 47) + '...'
115
+ : summary;
116
+ const message = `${this.config.messagePrefix} iteration ${iteration} - ${truncatedSummary}`;
117
+ const fullMessage = `${message}\n\nTokens used: ${tokensUsed}\nFiles modified: ${filesModified.length}`;
118
+ try {
119
+ // Create commit
120
+ await execAsync(`git commit -m "${fullMessage.replace(/"/g, '\\"')}"`, { cwd: this.config.cwd });
121
+ // Get commit hash
122
+ const { stdout } = await execAsync('git rev-parse HEAD', { cwd: this.config.cwd });
123
+ const commitHash = stdout.trim();
124
+ const checkpoint = {
125
+ iteration,
126
+ commitHash,
127
+ message,
128
+ filesModified,
129
+ timestamp: new Date(),
130
+ tokensUsed,
131
+ };
132
+ this.checkpoints.push(checkpoint);
133
+ debug(`Created checkpoint: ${commitHash.substring(0, 7)} - ${message}`);
134
+ return checkpoint;
135
+ }
136
+ catch (err) {
137
+ warn('Failed to create checkpoint commit: ' + (err instanceof Error ? err.message : String(err)));
138
+ return null;
139
+ }
140
+ }
141
+ /**
142
+ * Rollback to a specific checkpoint
143
+ */
144
+ async rollbackTo(commitHash) {
145
+ try {
146
+ // Soft reset to keep changes in working directory for review
147
+ await execAsync(`git reset --soft "${commitHash}"`, { cwd: this.config.cwd });
148
+ debug(`Rolled back to ${commitHash.substring(0, 7)}`);
149
+ return true;
150
+ }
151
+ catch (err) {
152
+ warn('Failed to rollback: ' + (err instanceof Error ? err.message : String(err)));
153
+ return false;
154
+ }
155
+ }
156
+ /**
157
+ * Hard rollback to a specific checkpoint (discard changes)
158
+ */
159
+ async hardRollbackTo(commitHash) {
160
+ try {
161
+ await execAsync(`git reset --hard "${commitHash}"`, { cwd: this.config.cwd });
162
+ debug(`Hard rolled back to ${commitHash.substring(0, 7)}`);
163
+ return true;
164
+ }
165
+ catch (err) {
166
+ warn('Failed to hard rollback: ' + (err instanceof Error ? err.message : String(err)));
167
+ return false;
168
+ }
169
+ }
170
+ /**
171
+ * Rollback by N iterations
172
+ */
173
+ async rollbackIterations(count = 1) {
174
+ if (this.checkpoints.length < count) {
175
+ warn(`Cannot rollback ${count} iterations, only ${this.checkpoints.length} checkpoints available`);
176
+ return false;
177
+ }
178
+ // Get the checkpoint to rollback to
179
+ const targetIndex = this.checkpoints.length - count - 1;
180
+ if (targetIndex < 0) {
181
+ // Rollback before first checkpoint - get parent of first checkpoint
182
+ const firstCheckpoint = this.checkpoints[0];
183
+ if (!firstCheckpoint)
184
+ return false;
185
+ try {
186
+ const { stdout } = await execAsync(`git rev-parse "${firstCheckpoint.commitHash}^"`, { cwd: this.config.cwd });
187
+ const parentHash = stdout.trim();
188
+ return this.hardRollbackTo(parentHash);
189
+ }
190
+ catch {
191
+ warn('Cannot find parent commit for rollback');
192
+ return false;
193
+ }
194
+ }
195
+ const targetCheckpoint = this.checkpoints[targetIndex];
196
+ if (!targetCheckpoint)
197
+ return false;
198
+ return this.hardRollbackTo(targetCheckpoint.commitHash);
199
+ }
200
+ /**
201
+ * Get the initial commit hash before Ralph started
202
+ */
203
+ async getInitialCommit() {
204
+ if (this.checkpoints.length === 0) {
205
+ return null;
206
+ }
207
+ const firstCheckpoint = this.checkpoints[0];
208
+ if (!firstCheckpoint)
209
+ return null;
210
+ try {
211
+ const { stdout } = await execAsync(`git rev-parse "${firstCheckpoint.commitHash}^"`, { cwd: this.config.cwd });
212
+ return stdout.trim();
213
+ }
214
+ catch {
215
+ return null;
216
+ }
217
+ }
218
+ /**
219
+ * Rollback all Ralph changes (to state before Ralph started)
220
+ */
221
+ async rollbackAll() {
222
+ const initialCommit = await this.getInitialCommit();
223
+ if (!initialCommit) {
224
+ warn('No checkpoints to rollback');
225
+ return false;
226
+ }
227
+ return this.hardRollbackTo(initialCommit);
228
+ }
229
+ }
230
+ /**
231
+ * Create a checkpoint manager with configuration
232
+ */
233
+ export function createCheckpointManager(config) {
234
+ return new CheckpointManager(config);
235
+ }
236
+ //# sourceMappingURL=checkpoint-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-manager.js","sourceRoot":"","sources":["../../src/core/checkpoint-manager.ts"],"names":[],"mappings":"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"}