1. ArgumentList (fix injection): ClaudeArgsBuilder.Build() now returns IReadOnlyList<string>; ClaudeProcess populates ProcessStartInfo.ArgumentList instead of Arguments, so values like system prompts are never shell-split. DailyPrepPrompt, RefinePrompt, and WeekReportService migrated similarly. All IClaudeProcess fakes updated. 2. ContinueAsync exception guard: wrap RunOnceAsync in try/catch matching the RunAsync pattern so an unexpected exception never leaves the task stuck in Running status. 3. Planning chain cascade: OnChildFinishedAsync now calls CancelAsync on the immediate blocked successor when a child fails or is cancelled, triggering a recursive cascade that clears the entire remaining chain instead of leaving it wedged. 4. FailAsync guard: restrict valid source states to Running and Queued; WaitingForReview -> Failed is now rejected, preventing an invalid transition that could corrupt the review workflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
1.7 KiB
C#
56 lines
1.7 KiB
C#
using ClaudeDo.Data.Models;
|
|
using ClaudeDo.Worker.Refine;
|
|
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
|
|
|
|
namespace ClaudeDo.Worker.Tests.Refine;
|
|
|
|
public sealed class RefinePromptTests
|
|
{
|
|
[Fact]
|
|
public void BuildArgs_includes_read_tools_when_repo_available()
|
|
{
|
|
var args = RefinePrompt.BuildArgs(20, canReadRepo: true);
|
|
|
|
Assert.Contains("--permission-mode", args);
|
|
Assert.Contains("acceptEdits", args);
|
|
Assert.Contains("mcp__claudedo__add_subtask", args);
|
|
Assert.Contains("Read", args);
|
|
Assert.Contains("Grep", args);
|
|
Assert.Contains("Glob", args);
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildArgs_drops_read_tools_in_text_only_mode()
|
|
{
|
|
var args = RefinePrompt.BuildArgs(20, canReadRepo: false);
|
|
|
|
Assert.DoesNotContain("Glob", args);
|
|
Assert.Contains("mcp__claudedo__update_task", args);
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildPrompt_seeds_task_fields_and_open_subtasks()
|
|
{
|
|
var task = new TaskEntity
|
|
{
|
|
Id = "abc12345",
|
|
ListId = "l",
|
|
Title = "T",
|
|
Description = "D",
|
|
Status = TaskStatus.Idle,
|
|
CreatedAt = DateTime.UtcNow,
|
|
};
|
|
var subtasks = new List<SubtaskEntity>
|
|
{
|
|
new() { Id = "s1", TaskId = "abc12345", Title = "open one", Completed = false, CreatedAt = DateTime.UtcNow },
|
|
new() { Id = "s2", TaskId = "abc12345", Title = "done one", Completed = true, CreatedAt = DateTime.UtcNow },
|
|
};
|
|
|
|
var prompt = RefinePrompt.BuildPrompt(task, subtasks);
|
|
|
|
Assert.Contains("abc12345", prompt);
|
|
Assert.Contains("open one", prompt);
|
|
Assert.DoesNotContain("done one", prompt);
|
|
}
|
|
}
|