fix(worker): harden CLI injection, stuck-Running, chain wedge, and Fail guard

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>
This commit is contained in:
mika kuns
2026-06-09 10:05:40 +02:00
co-authored by Claude Sonnet 4.6
parent 763732a9b3
commit 33bdff8a6e
20 changed files with 331 additions and 99 deletions
+15 -6
View File
@@ -12,13 +12,22 @@ public static class RefinePrompt
public static string LogPath(string taskId) =>
System.IO.Path.Combine(Paths.AppDataRoot(), "logs", $"refine-{Short(taskId)}.log");
public static string BuildArgs(int maxTurns, bool canReadRepo)
public static IReadOnlyList<string> BuildArgs(int maxTurns, bool canReadRepo)
{
var tools = canReadRepo
? $"{GetTaskTool} {UpdateTaskTool} {AddSubtaskTool} Read Grep Glob"
: $"{GetTaskTool} {UpdateTaskTool} {AddSubtaskTool}";
return "-p --output-format stream-json --verbose --permission-mode acceptEdits " +
$"--max-turns {maxTurns} --allowedTools {tools}";
var args = new List<string>
{
"-p", "--output-format", "stream-json", "--verbose",
"--permission-mode", "acceptEdits",
"--max-turns", maxTurns.ToString(),
"--allowedTools", GetTaskTool, UpdateTaskTool, AddSubtaskTool,
};
if (canReadRepo)
{
args.Add("Read");
args.Add("Grep");
args.Add("Glob");
}
return args;
}
public static string BuildPrompt(TaskEntity task, IEnumerable<SubtaskEntity> subtasks)