feat(worker): add PlanningChainCoordinator for sequential subtask execution
Coordinates Waiting -> Queued transitions between sibling subtasks: when a child finishes Done, the next Waiting sibling is promoted to Queued. WorkerHub.QueuePlanningSubtasksAsync exposes this to the UI; TaskRunner advances the chain on completion. Also tightens the planning-session prompt: planner must use MCP tools, not direct edits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,9 @@ using ClaudeDo.Data.Models;
|
||||
using ClaudeDo.Data.Repositories;
|
||||
using ClaudeDo.Worker.Config;
|
||||
using ClaudeDo.Worker.Hub;
|
||||
using ClaudeDo.Worker.Planning;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
|
||||
|
||||
namespace ClaudeDo.Worker.Runner;
|
||||
|
||||
@@ -16,6 +18,7 @@ public sealed class TaskRunner
|
||||
private readonly ClaudeArgsBuilder _argsBuilder;
|
||||
private readonly WorkerConfig _cfg;
|
||||
private readonly ILogger<TaskRunner> _logger;
|
||||
private readonly PlanningChainCoordinator _chain;
|
||||
|
||||
public TaskRunner(
|
||||
IClaudeProcess claude,
|
||||
@@ -24,7 +27,8 @@ public sealed class TaskRunner
|
||||
WorktreeManager wtManager,
|
||||
ClaudeArgsBuilder argsBuilder,
|
||||
WorkerConfig cfg,
|
||||
ILogger<TaskRunner> logger)
|
||||
ILogger<TaskRunner> logger,
|
||||
PlanningChainCoordinator chain)
|
||||
{
|
||||
_claude = claude;
|
||||
_dbFactory = dbFactory;
|
||||
@@ -33,6 +37,7 @@ public sealed class TaskRunner
|
||||
_argsBuilder = argsBuilder;
|
||||
_cfg = cfg;
|
||||
_logger = logger;
|
||||
_chain = chain;
|
||||
}
|
||||
|
||||
public async Task RunAsync(TaskEntity task, string slot, CancellationToken ct)
|
||||
@@ -338,6 +343,23 @@ public sealed class TaskRunner
|
||||
await _broadcaster.TaskFinished(slot, task.Id, "done", finishedAt);
|
||||
_logger.LogInformation("Task {TaskId} completed (turns={Turns}, tokens_in={In}, tokens_out={Out})",
|
||||
task.Id, result.TurnCount, result.TokensIn, result.TokensOut);
|
||||
|
||||
// Sequential planning chain: if this task has a parent, flip the next
|
||||
// Waiting sibling to Queued so the queue pickup loop dispatches it next.
|
||||
if (task.ParentTaskId is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var advanced = await _chain.OnChildFinishedAsync(
|
||||
task.Id, TaskStatus.Done, CancellationToken.None);
|
||||
if (advanced is not null)
|
||||
await _broadcaster.TaskUpdated(advanced);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "PlanningChain advance failed for {TaskId}", task.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleFailure(string taskId, string taskTitle, string slot, RunResult result)
|
||||
|
||||
Reference in New Issue
Block a user