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,226 @@
1
+ /**
2
+ * Feedback Builder
3
+ *
4
+ * Builds feedback prompts to show the AI the results of its actions.
5
+ * This is a core component of the Ralph pattern - the AI must see
6
+ * actual results (test output, errors, git diff) to iterate effectively.
7
+ */
8
+ import { exec } from 'node:child_process';
9
+ import { promisify } from 'node:util';
10
+ import { debug } from '../utils/index.js';
11
+ const execAsync = promisify(exec);
12
+ const DEFAULT_CONFIG = {
13
+ cwd: process.cwd(),
14
+ maxOutputLines: 50,
15
+ includeGitDiff: true,
16
+ maxDiffSize: 5000,
17
+ };
18
+ /**
19
+ * Feedback Builder
20
+ *
21
+ * Creates structured feedback for the AI based on what happened
22
+ * in the previous iteration.
23
+ */
24
+ export class FeedbackBuilder {
25
+ config;
26
+ constructor(config = {}) {
27
+ this.config = { ...DEFAULT_CONFIG, ...config };
28
+ }
29
+ /**
30
+ * Build feedback from action execution results
31
+ */
32
+ buildFromActions(executionResult) {
33
+ const lines = [];
34
+ for (const result of executionResult.results) {
35
+ const icon = result.success ? '✓' : '✗';
36
+ lines.push(`${icon} ${result.message}`);
37
+ // Include output for EXECUTE actions or failures
38
+ if (result.output && (result.action.type === 'EXECUTE' || !result.success)) {
39
+ const outputLines = result.output.split('\n');
40
+ const truncated = outputLines.slice(0, this.config.maxOutputLines);
41
+ if (outputLines.length > this.config.maxOutputLines) {
42
+ truncated.push(`... (${outputLines.length - this.config.maxOutputLines} more lines)`);
43
+ }
44
+ lines.push('```');
45
+ lines.push(...truncated);
46
+ lines.push('```');
47
+ }
48
+ // Include error details for failures
49
+ if (!result.success && result.error) {
50
+ lines.push(` Error: ${result.error}`);
51
+ }
52
+ }
53
+ return {
54
+ type: 'actions',
55
+ title: 'Action Results',
56
+ content: lines.join('\n'),
57
+ success: executionResult.allSucceeded,
58
+ };
59
+ }
60
+ /**
61
+ * Build feedback from verification results
62
+ */
63
+ buildFromVerification(results) {
64
+ if (results.length === 0) {
65
+ return {
66
+ type: 'verification',
67
+ title: 'Verification',
68
+ content: 'No verification hooks configured.',
69
+ success: true,
70
+ };
71
+ }
72
+ const lines = [];
73
+ let allPassed = true;
74
+ for (const result of results) {
75
+ const icon = result.passed ? '✓' : '✗';
76
+ lines.push(`${icon} ${result.message} (${result.durationMs}ms)`);
77
+ if (!result.passed) {
78
+ allPassed = false;
79
+ // Include failure output
80
+ if (result.output) {
81
+ const outputLines = result.output.split('\n');
82
+ const truncated = outputLines.slice(-this.config.maxOutputLines); // Last N lines for errors
83
+ if (outputLines.length > this.config.maxOutputLines) {
84
+ lines.push(`... (${outputLines.length - this.config.maxOutputLines} lines omitted)`);
85
+ }
86
+ lines.push('```');
87
+ lines.push(...truncated);
88
+ lines.push('```');
89
+ }
90
+ }
91
+ }
92
+ return {
93
+ type: 'verification',
94
+ title: 'Verification Results',
95
+ content: lines.join('\n'),
96
+ success: allPassed,
97
+ };
98
+ }
99
+ /**
100
+ * Build feedback from current git diff
101
+ */
102
+ async buildFromGitDiff() {
103
+ if (!this.config.includeGitDiff) {
104
+ return null;
105
+ }
106
+ try {
107
+ const { stdout } = await execAsync('git diff --stat HEAD 2>/dev/null', {
108
+ cwd: this.config.cwd,
109
+ maxBuffer: 100000,
110
+ });
111
+ const diffStat = stdout.trim();
112
+ if (!diffStat) {
113
+ return null; // No changes
114
+ }
115
+ // Get actual diff (limited)
116
+ const { stdout: diffContent } = await execAsync('git diff HEAD 2>/dev/null', {
117
+ cwd: this.config.cwd,
118
+ maxBuffer: this.config.maxDiffSize * 2,
119
+ });
120
+ let content = diffContent.trim();
121
+ if (content.length > this.config.maxDiffSize) {
122
+ content = content.substring(0, this.config.maxDiffSize) + '\n... (diff truncated)';
123
+ }
124
+ return {
125
+ type: 'git-diff',
126
+ title: 'Current Changes',
127
+ content: `\`\`\`diff\n${content}\n\`\`\``,
128
+ success: true,
129
+ };
130
+ }
131
+ catch {
132
+ debug('Failed to get git diff');
133
+ return null;
134
+ }
135
+ }
136
+ /**
137
+ * Build an error feedback section
138
+ */
139
+ buildError(error) {
140
+ const message = error instanceof Error ? error.message : error;
141
+ return {
142
+ type: 'error',
143
+ title: 'Error',
144
+ content: `An error occurred: ${message}`,
145
+ success: false,
146
+ };
147
+ }
148
+ /**
149
+ * Build a suggestion section
150
+ */
151
+ buildSuggestion(suggestion) {
152
+ return {
153
+ type: 'suggestion',
154
+ title: 'Suggestion',
155
+ content: suggestion,
156
+ success: true,
157
+ };
158
+ }
159
+ /**
160
+ * Combine sections into complete iteration feedback
161
+ */
162
+ async buildComplete(actionResult, verificationResults, options = {}) {
163
+ const sections = [];
164
+ // Add action results
165
+ if (actionResult) {
166
+ sections.push(this.buildFromActions(actionResult));
167
+ }
168
+ // Add verification results
169
+ if (verificationResults.length > 0) {
170
+ sections.push(this.buildFromVerification(verificationResults));
171
+ }
172
+ // Add git diff if requested
173
+ if (options.includeGitDiff !== false) {
174
+ const diffSection = await this.buildFromGitDiff();
175
+ if (diffSection) {
176
+ sections.push(diffSection);
177
+ }
178
+ }
179
+ // Add suggestion if provided
180
+ if (options.suggestion) {
181
+ sections.push(this.buildSuggestion(options.suggestion));
182
+ }
183
+ // Calculate overall status
184
+ const overallSuccess = sections.every((s) => s.success);
185
+ const verificationPassed = verificationResults.every((r) => r.passed);
186
+ const taskComplete = actionResult?.taskComplete === true && verificationPassed;
187
+ // Format for prompt
188
+ const formatted = this.formatForPrompt(sections, taskComplete);
189
+ return {
190
+ sections,
191
+ overallSuccess,
192
+ taskComplete,
193
+ formatted,
194
+ };
195
+ }
196
+ /**
197
+ * Format feedback sections for inclusion in prompt
198
+ */
199
+ formatForPrompt(sections, taskComplete) {
200
+ const lines = ['## Feedback from Previous Iteration'];
201
+ if (taskComplete) {
202
+ lines.push('');
203
+ lines.push('✅ **Task verified complete!** All actions succeeded and verification passed.');
204
+ lines.push('');
205
+ }
206
+ for (const section of sections) {
207
+ lines.push('');
208
+ lines.push(`### ${section.title}`);
209
+ lines.push(section.content);
210
+ }
211
+ if (!taskComplete && sections.some((s) => !s.success)) {
212
+ lines.push('');
213
+ lines.push('### Next Steps');
214
+ lines.push('Review the failures above and continue working on the task.');
215
+ lines.push('Use [ACTION:EXECUTE] to investigate issues if needed.');
216
+ }
217
+ return lines.join('\n');
218
+ }
219
+ }
220
+ /**
221
+ * Create a feedback builder with custom configuration
222
+ */
223
+ export function createFeedbackBuilder(config) {
224
+ return new FeedbackBuilder(config);
225
+ }
226
+ //# sourceMappingURL=feedback-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback-builder.js","sourceRoot":"","sources":["../../src/core/feedback-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * File Safeguard Manager
3
+ *
4
+ * Protects existing files from accidental deletion while allowing
5
+ * cleanup of agent-created files.
6
+ */
7
+ /**
8
+ * File safeguard configuration
9
+ */
10
+ export interface FileSafeguardConfig {
11
+ /** Working directory */
12
+ cwd: string;
13
+ /** Whether to allow deletion of existing files */
14
+ allowDeleteExisting: boolean;
15
+ /** Path to store baseline snapshot */
16
+ baselinePath: string;
17
+ }
18
+ /**
19
+ * Baseline snapshot data
20
+ */
21
+ export interface BaselineSnapshot {
22
+ /** When the snapshot was created */
23
+ createdAt: string;
24
+ /** List of files that existed at session start */
25
+ files: string[];
26
+ /** Number of files in the baseline */
27
+ count: number;
28
+ }
29
+ /**
30
+ * File operation tracking
31
+ */
32
+ export interface FileOperations {
33
+ /** Files that existed before session */
34
+ baselineFiles: Set<string>;
35
+ /** Files created during session */
36
+ createdFiles: Set<string>;
37
+ /** Files modified during session */
38
+ modifiedFiles: Set<string>;
39
+ /** Deletion attempts that were blocked */
40
+ blockedDeletions: string[];
41
+ }
42
+ /**
43
+ * File Safeguard Manager class
44
+ */
45
+ export declare class FileSafeguardManager {
46
+ private config;
47
+ private operations;
48
+ private initialized;
49
+ constructor(config?: Partial<FileSafeguardConfig>);
50
+ private getNormalizedRelativePath;
51
+ /**
52
+ * Initialize by creating baseline snapshot
53
+ */
54
+ initialize(): Promise<void>;
55
+ /**
56
+ * Create baseline snapshot of existing files
57
+ */
58
+ private createBaseline;
59
+ /**
60
+ * Load existing baseline from file
61
+ */
62
+ private loadBaseline;
63
+ /**
64
+ * Check if a file existed before the session
65
+ */
66
+ isBaselineFile(filePath: string): boolean;
67
+ /**
68
+ * Check if a file was created during this session
69
+ */
70
+ isCreatedFile(filePath: string): boolean;
71
+ /**
72
+ * Track a file creation
73
+ */
74
+ trackFileCreation(filePath: string): void;
75
+ /**
76
+ * Track a file modification
77
+ */
78
+ trackFileModification(filePath: string): void;
79
+ /**
80
+ * Check if a file can be deleted
81
+ */
82
+ canDelete(filePath: string): boolean;
83
+ /**
84
+ * Get summary of file operations
85
+ */
86
+ getSummary(): {
87
+ baselineCount: number;
88
+ createdCount: number;
89
+ modifiedCount: number;
90
+ blockedCount: number;
91
+ };
92
+ /**
93
+ * Get detailed file operation info
94
+ */
95
+ getDetails(): {
96
+ created: string[];
97
+ modified: string[];
98
+ blockedDeletions: string[];
99
+ };
100
+ /**
101
+ * Clean up baseline file (call at end of session)
102
+ */
103
+ cleanup(): Promise<void>;
104
+ }
105
+ /**
106
+ * Create a file safeguard manager
107
+ */
108
+ export declare function createFileSafeguardManager(config?: Partial<FileSafeguardConfig>): FileSafeguardManager;
109
+ //# sourceMappingURL=file-safeguard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-safeguard.d.ts","sourceRoot":"","sources":["../../src/core/file-safeguard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,mBAAmB,EAAE,OAAO,CAAC;IAC7B,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;CACtB;AAWD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wCAAwC;IACxC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,mCAAmC;IACnC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,oCAAoC;IACpC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,0CAA0C;IAC1C,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,WAAW,CAAkB;gBAEzB,MAAM,GAAE,OAAO,CAAC,mBAAmB,CAAM;IAUrD,OAAO,CAAC,yBAAyB;IAKjC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBjC;;OAEG;YACW,cAAc;IA6B5B;;OAEG;YACW,YAAY;IAc1B;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKzC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKxC;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQzC;;OAEG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK7C;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAwBpC;;OAEG;IACH,UAAU,IAAI;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACtB;IASD;;OAEG;IACH,UAAU,IAAI;QACZ,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,gBAAgB,EAAE,MAAM,EAAE,CAAC;KAC5B;IAQD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,oBAAoB,CAEtG"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * File Safeguard Manager
3
+ *
4
+ * Protects existing files from accidental deletion while allowing
5
+ * cleanup of agent-created files.
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, warn } from '../utils/index.js';
12
+ const execAsync = promisify(exec);
13
+ /**
14
+ * Default configuration
15
+ */
16
+ const DEFAULT_CONFIG = {
17
+ cwd: process.cwd(),
18
+ allowDeleteExisting: false,
19
+ baselinePath: '.ghcralph/baseline-files.json',
20
+ };
21
+ /**
22
+ * File Safeguard Manager class
23
+ */
24
+ export class FileSafeguardManager {
25
+ config;
26
+ operations;
27
+ initialized = false;
28
+ constructor(config = {}) {
29
+ this.config = { ...DEFAULT_CONFIG, ...config };
30
+ this.operations = {
31
+ baselineFiles: new Set(),
32
+ createdFiles: new Set(),
33
+ modifiedFiles: new Set(),
34
+ blockedDeletions: [],
35
+ };
36
+ }
37
+ getNormalizedRelativePath(filePath) {
38
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(this.config.cwd, filePath);
39
+ return path.relative(this.config.cwd, absolutePath).replace(/\\/g, '/');
40
+ }
41
+ /**
42
+ * Initialize by creating baseline snapshot
43
+ */
44
+ async initialize() {
45
+ if (this.initialized)
46
+ return;
47
+ try {
48
+ // Try to load existing baseline
49
+ const loaded = await this.loadBaseline();
50
+ if (loaded) {
51
+ debug('Loaded existing baseline snapshot');
52
+ this.initialized = true;
53
+ return;
54
+ }
55
+ // Create new baseline
56
+ await this.createBaseline();
57
+ this.initialized = true;
58
+ }
59
+ catch (err) {
60
+ warn('Failed to initialize file safeguards: ' + (err instanceof Error ? err.message : String(err)));
61
+ }
62
+ }
63
+ /**
64
+ * Create baseline snapshot of existing files
65
+ */
66
+ async createBaseline() {
67
+ try {
68
+ // Get list of tracked files from git
69
+ const { stdout } = await execAsync('git ls-files', { cwd: this.config.cwd });
70
+ const files = stdout.trim().split('\n').filter(Boolean);
71
+ // Store in memory
72
+ this.operations.baselineFiles = new Set(files);
73
+ // Save to file
74
+ const snapshot = {
75
+ createdAt: new Date().toISOString(),
76
+ files,
77
+ count: files.length,
78
+ };
79
+ const baselinePath = path.join(this.config.cwd, this.config.baselinePath);
80
+ const baselineDir = path.dirname(baselinePath);
81
+ // Ensure directory exists
82
+ await fs.mkdir(baselineDir, { recursive: true });
83
+ await fs.writeFile(baselinePath, JSON.stringify(snapshot, null, 2));
84
+ debug(`Created baseline with ${files.length} files`);
85
+ }
86
+ catch (err) {
87
+ debug('Failed to create baseline: ' + (err instanceof Error ? err.message : String(err)));
88
+ }
89
+ }
90
+ /**
91
+ * Load existing baseline from file
92
+ */
93
+ async loadBaseline() {
94
+ try {
95
+ const baselinePath = path.join(this.config.cwd, this.config.baselinePath);
96
+ const content = await fs.readFile(baselinePath, 'utf-8');
97
+ const snapshot = JSON.parse(content);
98
+ this.operations.baselineFiles = new Set(snapshot.files);
99
+ debug(`Loaded baseline with ${snapshot.count} files from ${snapshot.createdAt}`);
100
+ return true;
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ }
106
+ /**
107
+ * Check if a file existed before the session
108
+ */
109
+ isBaselineFile(filePath) {
110
+ const relativePath = this.getNormalizedRelativePath(filePath);
111
+ return this.operations.baselineFiles.has(relativePath);
112
+ }
113
+ /**
114
+ * Check if a file was created during this session
115
+ */
116
+ isCreatedFile(filePath) {
117
+ const relativePath = this.getNormalizedRelativePath(filePath);
118
+ return this.operations.createdFiles.has(relativePath);
119
+ }
120
+ /**
121
+ * Track a file creation
122
+ */
123
+ trackFileCreation(filePath) {
124
+ const relativePath = this.getNormalizedRelativePath(filePath);
125
+ if (!this.operations.baselineFiles.has(relativePath)) {
126
+ this.operations.createdFiles.add(relativePath);
127
+ debug(`Tracked file creation: ${relativePath}`);
128
+ }
129
+ }
130
+ /**
131
+ * Track a file modification
132
+ */
133
+ trackFileModification(filePath) {
134
+ const relativePath = this.getNormalizedRelativePath(filePath);
135
+ this.operations.modifiedFiles.add(relativePath);
136
+ }
137
+ /**
138
+ * Check if a file can be deleted
139
+ */
140
+ canDelete(filePath) {
141
+ // Always allow if override is set
142
+ if (this.config.allowDeleteExisting) {
143
+ return true;
144
+ }
145
+ const relativePath = this.getNormalizedRelativePath(filePath);
146
+ // Allow deletion of files created during session
147
+ if (this.operations.createdFiles.has(relativePath)) {
148
+ return true;
149
+ }
150
+ // Block deletion of baseline files
151
+ if (this.operations.baselineFiles.has(relativePath)) {
152
+ this.operations.blockedDeletions.push(relativePath);
153
+ warn(`Blocked deletion of pre-existing file: ${relativePath}`);
154
+ return false;
155
+ }
156
+ // Allow deletion of unknown files (not in baseline, not tracked as created)
157
+ return true;
158
+ }
159
+ /**
160
+ * Get summary of file operations
161
+ */
162
+ getSummary() {
163
+ return {
164
+ baselineCount: this.operations.baselineFiles.size,
165
+ createdCount: this.operations.createdFiles.size,
166
+ modifiedCount: this.operations.modifiedFiles.size,
167
+ blockedCount: this.operations.blockedDeletions.length,
168
+ };
169
+ }
170
+ /**
171
+ * Get detailed file operation info
172
+ */
173
+ getDetails() {
174
+ return {
175
+ created: Array.from(this.operations.createdFiles),
176
+ modified: Array.from(this.operations.modifiedFiles),
177
+ blockedDeletions: this.operations.blockedDeletions,
178
+ };
179
+ }
180
+ /**
181
+ * Clean up baseline file (call at end of session)
182
+ */
183
+ async cleanup() {
184
+ try {
185
+ const baselinePath = path.join(this.config.cwd, this.config.baselinePath);
186
+ await fs.unlink(baselinePath);
187
+ debug('Cleaned up baseline file');
188
+ }
189
+ catch {
190
+ // Ignore cleanup errors
191
+ }
192
+ }
193
+ }
194
+ /**
195
+ * Create a file safeguard manager
196
+ */
197
+ export function createFileSafeguardManager(config) {
198
+ return new FileSafeguardManager(config);
199
+ }
200
+ //# sourceMappingURL=file-safeguard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-safeguard.js","sourceRoot":"","sources":["../../src/core/file-safeguard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Git Branch Manager
3
+ *
4
+ * Manages git branch isolation for safe Ralph operations
5
+ */
6
+ /**
7
+ * Git branch manager configuration
8
+ */
9
+ export interface GitBranchConfig {
10
+ /** Prefix for GitHub Copilot Ralph branches (default: 'ralph/') */
11
+ branchPrefix: string;
12
+ /** Whether to auto-create branches without prompting */
13
+ autoCreate: boolean;
14
+ /** Working directory */
15
+ cwd: string;
16
+ }
17
+ /**
18
+ * Working directory status
19
+ */
20
+ export interface WorkingDirStatus {
21
+ /** Whether the working directory is clean */
22
+ isClean: boolean;
23
+ /** Number of modified files */
24
+ modifiedFiles: number;
25
+ /** Number of untracked files */
26
+ untrackedFiles: number;
27
+ }
28
+ /**
29
+ * Branch info
30
+ */
31
+ export interface BranchInfo {
32
+ /** Current branch name */
33
+ name: string;
34
+ /** Whether this is a main/master branch */
35
+ isMain: boolean;
36
+ /** Whether this is a Ralph branch */
37
+ isRalphBranch: boolean;
38
+ }
39
+ /**
40
+ * Git Branch Manager class
41
+ */
42
+ export declare class GitBranchManager {
43
+ private config;
44
+ constructor(config?: Partial<GitBranchConfig>);
45
+ /**
46
+ * Check if we're in a git repository
47
+ */
48
+ isGitRepository(): Promise<boolean>;
49
+ /**
50
+ * Get current branch information
51
+ */
52
+ getCurrentBranch(): Promise<BranchInfo>;
53
+ /**
54
+ * Get working directory status
55
+ */
56
+ getWorkingDirStatus(): Promise<WorkingDirStatus>;
57
+ /**
58
+ * Stash current changes
59
+ */
60
+ stashChanges(message?: string): Promise<boolean>;
61
+ /**
62
+ * Pop stashed changes
63
+ */
64
+ popStash(): Promise<boolean>;
65
+ /**
66
+ * Generate a branch name from task info
67
+ */
68
+ generateBranchName(taskTitle: string, taskId?: string): string;
69
+ /**
70
+ * Create and switch to a new Ralph branch
71
+ */
72
+ createAndSwitchBranch(branchName: string): Promise<boolean>;
73
+ /**
74
+ * Switch to an existing branch
75
+ */
76
+ switchBranch(branchName: string): Promise<boolean>;
77
+ /**
78
+ * Check if a branch exists
79
+ */
80
+ branchExists(branchName: string): Promise<boolean>;
81
+ /**
82
+ * Get the default branch (main/master)
83
+ */
84
+ getDefaultBranch(): Promise<string>;
85
+ /**
86
+ * Merge a Ralph branch back to the original branch
87
+ */
88
+ mergeBranch(sourceBranch: string, targetBranch: string): Promise<boolean>;
89
+ /**
90
+ * Delete a branch
91
+ */
92
+ deleteBranch(branchName: string, force?: boolean): Promise<boolean>;
93
+ /**
94
+ * Get the list of GitHub Copilot Ralph branches
95
+ */
96
+ listRalphBranches(): Promise<string[]>;
97
+ /**
98
+ * Prepare the branch for a Ralph operation
99
+ * Returns the branch name to use
100
+ */
101
+ prepareForOperation(taskTitle: string, taskId?: string, options?: {
102
+ branch?: string;
103
+ force?: boolean;
104
+ }): Promise<{
105
+ branchName: string;
106
+ created: boolean;
107
+ originalBranch: string;
108
+ }>;
109
+ /**
110
+ * Get the latest commit hash
111
+ */
112
+ getLatestCommitHash(): Promise<string | null>;
113
+ /**
114
+ * Get the commit count on current branch
115
+ */
116
+ getCommitCount(): Promise<number>;
117
+ }
118
+ /**
119
+ * Create a git branch manager with configuration
120
+ */
121
+ export declare function createGitBranchManager(config?: Partial<GitBranchConfig>): GitBranchManager;
122
+ //# sourceMappingURL=git-branch-manager.d.ts.map