@@ -20,13 +20,13 @@ RALPH-loop is a development methodology for iterative AI-powered task completion
2020
2121# # Example Scenario
2222
23- You need to iteratively improve code until all tests pass. Instead of asking Claude to " write perfect code," you use RALPH-loop to:
23+ You need to iteratively improve code until all tests pass. Instead of asking the model to " write perfect code," you use RALPH-loop to:
2424
25251. Send the initial prompt with clear success criteria
26- 2. Claude writes code and tests
27- 3. Claude runs tests and sees failures
26+ 2. The model writes code and tests
27+ 3. The model runs tests and sees failures
28284. Loop automatically re-sends the prompt
29- 5. Claude reads test output and previous code, fixes issues
29+ 5. The model reads test output and previous code, fixes issues
30306. Repeat until all tests pass and completion promise is output
3131
3232# # Basic Implementation
@@ -52,56 +52,66 @@ public class RalphLoop
5252 public async Task< string> RunAsync(string prompt)
5353 {
5454 await _client.StartAsync ();
55- var session = await _client.CreateSessionAsync(new SessionConfig { Model = " gpt-5" });
5655
5756 try
5857 {
59- while (_iteration < _maxIterations)
60- {
61- _iteration++;
62- Console.WriteLine($" \n--- Iteration {_iteration} ---" );
58+ var session = await _client.CreateSessionAsync(
59+ new SessionConfig { Model = " gpt-5.1-codex-mini" });
6360
61+ try
62+ {
6463 var done = new TaskCompletionSource<string> ();
6564 session.On(evt =>
6665 {
6766 if (evt is AssistantMessageEvent msg)
6867 {
6968 _lastResponse = msg.Data.Content;
70- done.SetResult (msg.Data.Content);
69+ done.TrySetResult (msg.Data.Content);
7170 }
7271 });
7372
74- // Send prompt (on first iteration) or continuation
75- var messagePrompt = _iteration == 1
76- ? prompt
77- : $" {prompt}\n\nPrevious attempt:\n{_lastResponse}\n\nContinue iterating... " ;
73+ while (_iteration < _maxIterations)
74+ {
75+ _iteration++ ;
76+ Console.WriteLine( $" \n--- Iteration {_iteration} --- " ) ;
7877
79- await session.SendAsync(new MessageOptions { Prompt = messagePrompt });
80- var response = await done.Task;
78+ done = new TaskCompletionSource<string> ();
8179
82- // Check for completion promise
83- if (response.Contains(_completionPromise))
84- {
85- Console.WriteLine($" ✓ Completion promise detected: {_completionPromise}" );
86- return response;
80+ // Send prompt (on first iteration) or continuation
81+ var messagePrompt = _iteration == 1
82+ ? prompt
83+ : $" {prompt}\n\nPrevious attempt:\n{_lastResponse}\n\nContinue iterating..." ;
84+
85+ await session.SendAsync(new MessageOptions { Prompt = messagePrompt });
86+ var response = await done.Task;
87+
88+ // Check for completion promise
89+ if (response.Contains(_completionPromise))
90+ {
91+ Console.WriteLine($" ✓ Completion promise detected: {_completionPromise}" );
92+ return response;
93+ }
94+
95+ Console.WriteLine($" Iteration {_iteration} complete. Continuing..." );
8796 }
8897
89- Console.WriteLine($" Iteration {_iteration} complete. Continuing..." );
98+ throw new InvalidOperationException(
99+ $" Max iterations ({_maxIterations}) reached without completion promise" );
100+ }
101+ finally
102+ {
103+ await session.DisposeAsync ();
90104 }
91-
92- throw new InvalidOperationException(
93- $" Max iterations ({_maxIterations}) reached without completion promise" );
94105 }
95106 finally
96107 {
97- await session.DisposeAsync ();
98108 await _client.StopAsync ();
99109 }
100110 }
101111}
102112
103113// Usage
104- var loop = new RalphLoop(maxIterations: 5, completionPromise: " DONE " );
114+ var loop = new RalphLoop(maxIterations: 5, completionPromise: " COMPLETE " );
105115var result = await loop.RunAsync(" Your task here" );
106116Console.WriteLine(result);
107117` ` `
@@ -115,38 +125,31 @@ public class PersistentRalphLoop
115125{
116126 private readonly string _workDir;
117127 private readonly CopilotClient _client;
128+ private readonly int _maxIterations;
118129 private int _iteration = 0;
119130
120131 public PersistentRalphLoop(string workDir, int maxIterations = 10)
121132 {
122133 _workDir = workDir;
134+ _maxIterations = maxIterations;
123135 Directory.CreateDirectory(_workDir);
124136 _client = new CopilotClient ();
125137 }
126138
127139 public async Task< string> RunAsync(string prompt)
128140 {
129141 await _client.StartAsync ();
130- var session = await _client.CreateSessionAsync(new SessionConfig { Model = " gpt-5" });
131142
132143 try
133144 {
134- // Store initial prompt
135- var promptFile = Path.Combine(_workDir, " prompt.md" );
136- await File.WriteAllTextAsync(promptFile, prompt);
145+ var session = await _client.CreateSessionAsync(
146+ new SessionConfig { Model = " gpt-5.1-codex-mini" });
137147
138- while (_iteration < 10)
148+ try
139149 {
140- _iteration++;
141- Console.WriteLine($" \n--- Iteration {_iteration} ---" );
142-
143- // Build context including previous work
144- var contextBuilder = new StringBuilder(prompt);
145- var previousOutput = Path.Combine(_workDir, $" output-{_iteration - 1}.txt" );
146- if (File.Exists(previousOutput))
147- {
148- contextBuilder.AppendLine($" \nPrevious iteration output:\n{await File.ReadAllTextAsync(previousOutput)}" );
149- }
150+ // Store initial prompt
151+ var promptFile = Path.Combine(_workDir, " prompt.md" );
152+ await File.WriteAllTextAsync(promptFile, prompt);
150153
151154 var done = new TaskCompletionSource<string> ();
152155 string response = " " ;
@@ -155,29 +158,48 @@ public class PersistentRalphLoop
155158 if (evt is AssistantMessageEvent msg)
156159 {
157160 response = msg.Data.Content;
158- done.SetResult (msg.Data.Content);
161+ done.TrySetResult (msg.Data.Content);
159162 }
160163 });
161164
162- await session.SendAsync(new MessageOptions { Prompt = contextBuilder.ToString () });
163- await done.Task;
165+ while (_iteration < _maxIterations)
166+ {
167+ _iteration++;
168+ Console.WriteLine($" \n--- Iteration {_iteration} ---" );
164169
165- // Persist output
166- await File.WriteAllTextAsync(
167- Path.Combine(_workDir, $" output-{_iteration}.txt" ),
168- response);
170+ done = new TaskCompletionSource<string> ();
169171
170- if (response.Contains(" COMPLETE" ))
171- {
172- return response;
172+ // Build context including previous work
173+ var contextBuilder = new StringBuilder(prompt);
174+ var previousOutput = Path.Combine(_workDir, $" output-{_iteration - 1}.txt" );
175+ if (File.Exists(previousOutput))
176+ {
177+ contextBuilder.AppendLine($" \nPrevious iteration output:\n{await File.ReadAllTextAsync(previousOutput)}" );
178+ }
179+
180+ await session.SendAsync(new MessageOptions { Prompt = contextBuilder.ToString () });
181+ await done.Task;
182+
183+ // Persist output
184+ await File.WriteAllTextAsync(
185+ Path.Combine(_workDir, $" output-{_iteration}.txt" ),
186+ response);
187+
188+ if (response.Contains(" COMPLETE" ))
189+ {
190+ return response;
191+ }
173192 }
174- }
175193
176- throw new InvalidOperationException(" Max iterations reached" );
194+ throw new InvalidOperationException(" Max iterations reached" );
195+ }
196+ finally
197+ {
198+ await session.DisposeAsync ();
199+ }
177200 }
178201 finally
179202 {
180- await session.DisposeAsync ();
181203 await _client.StopAsync ();
182204 }
183205 }
0 commit comments