/** * Event Bus Types * * Port interface for the event bus - the backbone of the hexagonal architecture. * EventBus is the PORT. Implementations (EventEmitterBus, RabbitMQ, etc.) are ADAPTERS. */ /** * Base interface for all domain events. * Every event in the system extends this. */ export interface DomainEvent { /** Event type identifier (e.g., 'process:spawned', 'server:started') */ type: string; /** When the event occurred */ timestamp: Date; /** Event-specific data */ payload: unknown; } /** * Event Bus Port Interface * * All modules communicate through this interface. * Can be swapped for external systems (RabbitMQ, WebSocket forwarding) later. */ // ============================================================================= // Domain Event Types - Typed payloads for each event // ============================================================================= /** * Process Events */ export interface ProcessSpawnedEvent extends DomainEvent { type: 'process:spawned'; payload: { processId: string; pid: number; command: string; }; } export interface ProcessStoppedEvent extends DomainEvent { type: 'process:stopped'; payload: { processId: string; pid: number; exitCode: number | null; }; } export interface ProcessCrashedEvent extends DomainEvent { type: 'process:crashed'; payload: { processId: string; pid: number; signal: string | null; }; } /** * Server Events */ export interface ServerStartedEvent extends DomainEvent { type: 'server:started'; payload: { port: number; host: string; pid: number; }; } export interface ServerStoppedEvent extends DomainEvent { type: 'server:stopped'; payload: { uptime: number; }; } /** * Log Events */ export interface LogEntryEvent extends DomainEvent { type: 'log:entry'; payload: { processId: string; stream: 'stdout' | 'stderr'; data: string; }; } /** * Git Worktree Events */ export interface WorktreeCreatedEvent extends DomainEvent { type: 'worktree:created'; payload: { worktreeId: string; branch: string; path: string; }; } export interface WorktreeRemovedEvent extends DomainEvent { type: 'worktree:removed'; payload: { worktreeId: string; branch: string; }; } export interface WorktreeMergedEvent extends DomainEvent { type: 'worktree:merged'; payload: { worktreeId: string; sourceBranch: string; targetBranch: string; }; } export interface WorktreeConflictEvent extends DomainEvent { type: 'worktree:conflict'; payload: { worktreeId: string; sourceBranch: string; targetBranch: string; conflictingFiles: string[]; }; } /** * Agent Events */ export interface AgentSpawnedEvent extends DomainEvent { type: 'agent:spawned'; payload: { agentId: string; name: string; taskId: string; worktreeId: string; }; } export interface AgentStoppedEvent extends DomainEvent { type: 'agent:stopped'; payload: { agentId: string; name: string; taskId: string; reason: 'user_requested' | 'task_complete' | 'error' | 'waiting_for_input'; }; } export interface AgentCrashedEvent extends DomainEvent { type: 'agent:crashed'; payload: { agentId: string; name: string; taskId: string; error: string; }; } export interface AgentResumedEvent extends DomainEvent { type: 'agent:resumed'; payload: { agentId: string; name: string; taskId: string; sessionId: string; }; } export interface AgentWaitingEvent extends DomainEvent { type: 'agent:waiting'; payload: { agentId: string; name: string; taskId: string; sessionId: string; question: string; options?: Array<{ label: string; description?: string }>; multiSelect?: boolean; }; } /** * Task Dispatch Events */ export interface TaskQueuedEvent extends DomainEvent { type: 'task:queued'; payload: { taskId: string; priority: string; dependsOn: string[]; }; } export interface TaskDispatchedEvent extends DomainEvent { type: 'task:dispatched'; payload: { taskId: string; agentId: string; agentName: string; }; } export interface TaskCompletedEvent extends DomainEvent { type: 'task:completed'; payload: { taskId: string; agentId: string; success: boolean; message: string; }; } export interface TaskBlockedEvent extends DomainEvent { type: 'task:blocked'; payload: { taskId: string; reason: string; blockedBy?: string[]; }; } /** * Merge Coordination Events */ export interface MergeQueuedEvent extends DomainEvent { type: 'merge:queued'; payload: { taskId: string; agentId: string; worktreeId: string; priority: 'low' | 'medium' | 'high'; }; } export interface MergeStartedEvent extends DomainEvent { type: 'merge:started'; payload: { taskId: string; agentId: string; worktreeId: string; targetBranch: string; }; } export interface MergeCompletedEvent extends DomainEvent { type: 'merge:completed'; payload: { taskId: string; agentId: string; worktreeId: string; targetBranch: string; }; } export interface MergeConflictedEvent extends DomainEvent { type: 'merge:conflicted'; payload: { taskId: string; agentId: string; worktreeId: string; targetBranch: string; conflictingFiles: string[]; }; } /** * Union of all domain events - enables type-safe event handling */ export type DomainEventMap = | ProcessSpawnedEvent | ProcessStoppedEvent | ProcessCrashedEvent | ServerStartedEvent | ServerStoppedEvent | LogEntryEvent | WorktreeCreatedEvent | WorktreeRemovedEvent | WorktreeMergedEvent | WorktreeConflictEvent | AgentSpawnedEvent | AgentStoppedEvent | AgentCrashedEvent | AgentResumedEvent | AgentWaitingEvent | TaskQueuedEvent | TaskDispatchedEvent | TaskCompletedEvent | TaskBlockedEvent | MergeQueuedEvent | MergeStartedEvent | MergeCompletedEvent | MergeConflictedEvent; /** * Event type literal union for type checking */ export type DomainEventType = DomainEventMap['type']; // ============================================================================= // Event Bus Port Interface // ============================================================================= /** * Event Bus Port Interface * * All modules communicate through this interface. * Can be swapped for external systems (RabbitMQ, WebSocket forwarding) later. */ export interface EventBus { /** * Emit an event to all subscribed handlers */ emit(event: T): void; /** * Subscribe to events of a specific type */ on( eventType: T['type'], handler: (event: T) => void ): void; /** * Unsubscribe from events of a specific type */ off( eventType: T['type'], handler: (event: T) => void ): void; /** * Subscribe to a single occurrence of an event type */ once( eventType: T['type'], handler: (event: T) => void ): void; }