feat(mission-control): show running Worker operations in a Running now section

Registry of active verify/merge/rebase/worktree-creation operations in the Worker,
GetActiveOperations snapshot + OperationStarted/OperationEnded hub events, and a
Running now section in Mission Control with ticking elapsed time.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-10-01 12:08:43 +02:00
co-authored by Claude Sonnet 5.5
parent 488c28a9d5
commit 2dbec543df
18 changed files with 539 additions and 18 deletions
+8 -1
View File
@@ -75,6 +75,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
private readonly HandlerRestartCoordinator? _handlerRestart;
private readonly HandlerRoundState? _roundState;
private readonly ConnectedClientTracker? _clientTracker;
private readonly RunningOperationRegistry? _operations;
public WorkerHub(
QueueService queue,
@@ -116,7 +117,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
TicketImportService ticketImport = null!,
HandlerRestartCoordinator? handlerRestart = null,
HandlerRoundState? roundState = null,
ConnectedClientTracker? clientTracker = null)
ConnectedClientTracker? clientTracker = null,
RunningOperationRegistry? operations = null)
{
_queue = queue;
_waker = waker;
@@ -158,6 +160,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
_handlerRestart = handlerRestart;
_roundState = roundState;
_clientTracker = clientTracker;
_operations = operations;
}
// Tracks connected UI clients so an out-of-band caller (external MCP's start_list_handler)
@@ -203,6 +206,10 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
public IReadOnlyList<WorkerLogRecord> GetRecentLogs() =>
_logBuffer?.Snapshot() ?? Array.Empty<WorkerLogRecord>();
/// <summary>Operations running right now — lets a connecting or reconnecting UI recover state before the started/ended events.</summary>
public IReadOnlyList<RunningOperationDto> GetActiveOperations() =>
_operations?.Snapshot() ?? Array.Empty<RunningOperationDto>();
// Maps the two exceptions service methods throw into client-facing HubExceptions:
// KeyNotFoundException -> notFoundMessage, InvalidOperationException -> its own message.
private static async Task HubGuard(Func<Task> action, string notFoundMessage = "task not found")