feat(prompts): retry prompt from file, append only real captured errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ using System.Text;
|
||||
|
||||
namespace ClaudeDo.Data;
|
||||
|
||||
public enum PromptKind { System, Planning, PlanningInitial, Retry, DailyPrep, WeeklyReport }
|
||||
public enum PromptKind { System, Planning, PlanningInitial, Retry, DailyPrep, WeeklyReport, Agent }
|
||||
|
||||
public static class PromptFiles
|
||||
{
|
||||
@@ -16,6 +16,7 @@ public static class PromptFiles
|
||||
PromptKind.Retry => Path.Combine(Root, "retry.md"),
|
||||
PromptKind.DailyPrep => Path.Combine(Root, "daily-prep.md"),
|
||||
PromptKind.WeeklyReport => Path.Combine(Root, "weekly-report.md"),
|
||||
PromptKind.Agent => Path.Combine(Root, "agent.md"),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(kind))
|
||||
};
|
||||
|
||||
@@ -59,6 +60,7 @@ public static class PromptFiles
|
||||
PromptKind.Retry => RetryDefault,
|
||||
PromptKind.DailyPrep => DailyPrepDefault,
|
||||
PromptKind.WeeklyReport => WeeklyReportDefault,
|
||||
PromptKind.Agent => "",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace ClaudeDo.Worker.Runner;
|
||||
|
||||
public sealed class ClaudeProcess : IClaudeProcess
|
||||
{
|
||||
public const string NoResultPrefix = "Claude exited with code";
|
||||
|
||||
private readonly WorkerConfig _cfg;
|
||||
private readonly ILogger<ClaudeProcess> _logger;
|
||||
|
||||
@@ -100,7 +102,7 @@ public sealed class ClaudeProcess : IClaudeProcess
|
||||
|
||||
var error = lastStderr.Length > 0
|
||||
? lastStderr.ToString().Trim()
|
||||
: $"Claude exited with code {exitCode} and no result.";
|
||||
: $"{NoResultPrefix} {exitCode} and no result.";
|
||||
|
||||
return new RunResult
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ public sealed class TaskRunner
|
||||
{
|
||||
_logger.LogInformation("Auto-retrying task {TaskId} with session {SessionId}", task.Id, result.SessionId);
|
||||
var retryConfig = resolvedConfig with { ResumeSessionId = result.SessionId };
|
||||
var retryPrompt = $"The previous attempt failed with:\n\n{result.ErrorMarkdown}\n\nTry again and fix the issues.";
|
||||
var retryPrompt = BuildRetryPrompt(result.ErrorMarkdown);
|
||||
|
||||
var retryResult = await RunOnceAsync(task.Id, task.Title, slot, runDir, retryConfig, 2, true, retryPrompt, ct);
|
||||
|
||||
@@ -403,4 +403,14 @@ public sealed class TaskRunner
|
||||
.Select(p => p!.Trim());
|
||||
return string.Join("\n\n", trimmed);
|
||||
}
|
||||
|
||||
public static string BuildRetryPrompt(string? capturedError)
|
||||
{
|
||||
var basePrompt = PromptFiles.ReadOrDefault(PromptKind.Retry);
|
||||
var isReal = !string.IsNullOrWhiteSpace(capturedError)
|
||||
&& !capturedError!.StartsWith(ClaudeProcess.NoResultPrefix, StringComparison.Ordinal);
|
||||
return isReal
|
||||
? $"{basePrompt}\n\nCaptured error from the failed run:\n\n{capturedError!.Trim()}"
|
||||
: basePrompt;
|
||||
}
|
||||
}
|
||||
|
||||
29
tests/ClaudeDo.Worker.Tests/Runner/RetryPromptTests.cs
Normal file
29
tests/ClaudeDo.Worker.Tests/Runner/RetryPromptTests.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using ClaudeDo.Worker.Runner;
|
||||
|
||||
namespace ClaudeDo.Worker.Tests.Runner;
|
||||
|
||||
public class RetryPromptTests
|
||||
{
|
||||
[Fact]
|
||||
public void Generic_no_result_error_is_not_appended()
|
||||
{
|
||||
var prompt = TaskRunner.BuildRetryPrompt($"{ClaudeProcess.NoResultPrefix} 1 and no result.");
|
||||
Assert.DoesNotContain("Captured error", prompt);
|
||||
Assert.Contains("did not complete", prompt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Real_error_is_appended()
|
||||
{
|
||||
var prompt = TaskRunner.BuildRetryPrompt("error CS1002: ; expected");
|
||||
Assert.Contains("Captured error", prompt);
|
||||
Assert.Contains("CS1002", prompt);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Null_error_yields_bare_prompt()
|
||||
{
|
||||
var prompt = TaskRunner.BuildRetryPrompt(null);
|
||||
Assert.DoesNotContain("Captured error", prompt);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user