feat: add orchestrator observability to Mission Control

Add real-time visibility into the parallel orchestrator's decisions
and state in the Mission Control UI. The orchestrator now has its
own avatar ("Maestro") and displays capacity/queue information.

Backend changes (server/websocket.py):
- Add OrchestratorTracker class that parses orchestrator stdout
- Define regex patterns for key orchestrator events (spawn, complete, capacity)
- Track coding/testing agent counts, ready queue, blocked features
- Emit orchestrator_update WebSocket messages
- Reset tracker state when agent stops or crashes

Frontend changes:
- Add OrchestratorState, OrchestratorStatus, OrchestratorEvent types
- Add WSOrchestratorUpdateMessage to WSMessage union
- Handle orchestrator_update in useWebSocket hook
- Create OrchestratorAvatar component (Maestro - robot conductor)
- Create OrchestratorStatusCard with capacity badges and event ticker
- Update AgentMissionControl to show orchestrator above agent cards
- Add conducting/baton-tap CSS animations for Maestro

The orchestrator status card shows:
- Maestro avatar with state-based animations
- Current orchestrator state and message
- Coding agents, testing agents, ready queue badges
- Blocked features count (when > 0)
- Collapsible recent events list

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Auto
2026-01-23 13:02:36 +02:00
parent b21d2e3adc
commit a03d945fcd
8 changed files with 751 additions and 31 deletions

View File

@@ -960,6 +960,67 @@
}
}
/* ============================================================================
Orchestrator (Maestro) Animations
============================================================================ */
@keyframes conducting {
0%, 100% {
transform: rotate(-10deg);
}
25% {
transform: rotate(5deg);
}
50% {
transform: rotate(-5deg);
}
75% {
transform: rotate(10deg);
}
}
@keyframes baton-tap {
0%, 100% {
transform: translateY(0) rotate(0deg);
}
25% {
transform: translateY(-3px) rotate(-2deg);
}
50% {
transform: translateY(0) rotate(0deg);
}
75% {
transform: translateY(-3px) rotate(2deg);
}
}
@keyframes maestro-idle {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-2px);
}
}
@keyframes maestro-complete {
0% {
transform: scale(1) rotate(0deg);
}
25% {
transform: scale(1.05) rotate(-3deg);
}
50% {
transform: scale(1.1) rotate(0deg);
}
75% {
transform: scale(1.05) rotate(3deg);
}
100% {
transform: scale(1) rotate(0deg);
}
}
/* ============================================================================
Utilities Layer
============================================================================ */
@@ -1089,6 +1150,23 @@
.animate-confetti {
animation: confetti 2s ease-out forwards;
}
/* Orchestrator (Maestro) animation utilities */
.animate-conducting {
animation: conducting 1s ease-in-out infinite;
}
.animate-baton-tap {
animation: baton-tap 0.6s ease-in-out infinite;
}
.animate-maestro-idle {
animation: maestro-idle 2s ease-in-out infinite;
}
.animate-maestro-complete {
animation: maestro-complete 0.8s ease-in-out;
}
}
/* ============================================================================