fix(worker): harden review re-run, timestamps, and queue affordance

- Clear ReviewFeedback only after a successful re-run so a failed/cancelled
  run keeps it for a manual retry.
- Clear stale StartedAt/FinishedAt when rejecting a task back to the queue.
- Only non-planning standalone tasks gate on review (guard PlanningPhase).
- Hide "send to queue" for WaitingForReview tasks so review isn't bypassed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-06-02 08:00:13 +02:00
parent 4684a0af76
commit 1cb5171fba
5 changed files with 37 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ using ClaudeDo.Worker.Config;
using ClaudeDo.Worker.Runner;
using ClaudeDo.Worker.State;
using Microsoft.EntityFrameworkCore;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
namespace ClaudeDo.Worker.Queue;
@@ -188,17 +189,27 @@ public sealed class QueueService : BackgroundService
using (var context = _dbFactory.CreateDbContext())
sessionId = (await new TaskRunRepository(context).GetLatestByTaskIdAsync(taskId, ct))?.SessionId;
await _state.ClearReviewFeedbackAsync(taskId, ct);
if (sessionId is not null)
{
await _runner.ContinueAsync(taskId, feedback, "queue", ct);
return;
}
else
{
task.Description = string.IsNullOrWhiteSpace(task.Description)
? $"Reviewer feedback: {feedback}"
: $"{task.Description}\n\nReviewer feedback: {feedback}";
await _runner.RunAsync(task, "queue", ct);
}
task.Description = string.IsNullOrWhiteSpace(task.Description)
? $"Reviewer feedback: {feedback}"
: $"{task.Description}\n\nReviewer feedback: {feedback}";
// Clear the consumed feedback only once the run reached a successful
// terminal state, so a failed or cancelled run keeps it for a manual retry.
TaskStatus statusAfter;
using (var context = _dbFactory.CreateDbContext())
statusAfter = await context.Tasks.Where(t => t.Id == taskId)
.Select(t => t.Status).FirstAsync(CancellationToken.None);
if (statusAfter is TaskStatus.WaitingForReview or TaskStatus.Done)
await _state.ClearReviewFeedbackAsync(taskId, CancellationToken.None);
return;
}
await _runner.RunAsync(task, "queue", ct);