From 2710eb8a3a58abbea95bd487797abbb3e67f0d0a Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Thu, 26 Mar 2026 05:45:19 +0000 Subject: fix: resolve dep-chain deadlock; broadcast task_started for UI visibility With maxPerAgent=1, tasks with DependsOn were entering waitForDependencies while holding the per-agent slot, preventing the dependency from ever running. Fix: check deps before taking the slot. If not ready, requeue without holding activePerAgent. Also accept StateReady (leaf tasks) as a satisfied dependency, not just StateCompleted. Add startedCh to pool and broadcast task_started WebSocket event when a task transitions to RUNNING, so the UI immediately shows the running state during the clone phase instead of waiting for completion. Co-Authored-By: Claude Sonnet 4.6 --- internal/api/server.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'internal/api/server.go') diff --git a/internal/api/server.go b/internal/api/server.go index fc9bd63..38108de 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -161,8 +161,19 @@ func (s *Server) routes() { s.mux.Handle("GET /", http.FileServerFS(webui.Files)) } -// forwardResults listens on the executor pool's result channel and broadcasts via WebSocket. +// forwardResults listens on the executor pool's result and started channels and broadcasts via WebSocket. func (s *Server) forwardResults() { + go func() { + for taskID := range s.pool.Started() { + event := map[string]interface{}{ + "type": "task_started", + "task_id": taskID, + "timestamp": time.Now().UTC(), + } + data, _ := json.Marshal(event) + s.hub.Broadcast(data) + } + }() for result := range s.pool.Results() { s.processResult(result) } -- cgit v1.2.3