/**
 * Event Bus Types Module
 *
 * Type definitions for the agent event bus (pub/sub) system.
 * Agents publish lifecycle events (idle, busy, active, inactive),
 * and subscribers receive notifications when matching events occur.
 *
 * @module types/event-bus
 */
// =============================================================================
// Enums and Constants
// =============================================================================
/**
 * Valid agent lifecycle event types
 */
export const EVENT_TYPES = [
    // Agent lifecycle events
    'agent:status_changed',
    'agent:idle',
    // 2026-05-20 follow-up to the Sora stuck-WI incident — split idle into
    // two semantically distinct events so subscriptions that mean "tell me
    // when the agent FINISHED a task" stop getting woken by the unrelated
    // "agent just registered and has nothing to do yet" transition.
    //
    // - agent:idle_after_registration: fires once when an agent first
    //   transitions to idle after registration, without having been
    //   workingStatus=in_progress at any point. Useful for fleet-monitoring
    //   dashboards. NOT useful for delegation-complete signalling — a
    //   peer-watch trigger keyed on this would consume the wake-up event
    //   before the delegatee has even claimed the WI.
    // - agent:idle_after_task: fires when an agent returns to idle after
    //   having been busy. This is the event delegation-watchers want.
    //
    // `agent:idle` continues to fire alongside both (back-compat for
    // existing subscribers). New subscribers should prefer the precise
    // variant.
    'agent:idle_after_registration',
    'agent:idle_after_task',
    'agent:busy',
    'agent:active',
    'agent:inactive',
    'agent:context_warning',
    'agent:context_critical',
    'agent:oauth_url',
    // Hierarchical task events
    'task:submitted',
    'task:accepted',
    'task:working',
    'task:input_required',
    'task:verification_requested',
    'task:completed',
    'task:failed',
    'task:cancelled',
    // Architecture Upgrade: Task Event Chain (Phase 6)
    'task:assigned',
    'task:done',
    'task:verified',
    'task:blocked',
    'task:needs_clarification',
    'team:all_tasks_done',
    // BRIDGE-1: worker / verification lifecycle events the EventToWorkItemBridge
    // consumes to auto-create verification, retry, and review WorkItems.
    // `task:done_by_worker` is published by `submitForVerification`; `task:rejected`
    // is published by `verifyItem` when a TL rejects a worker's submission.
    'task:done_by_worker',
    'task:rejected',
    // BRIDGE-1: mission-level events the bridge fans out into review WorkItems.
    // `mission:review_due` is REVIEW-1's cadence-driven trigger; `mission:stale`
    // and `mission:replanned` cover the missing autonomy hooks the doc review
    // called out (see autonomy_v1 §4 item 5).
    'mission:review_due',
    'mission:stale',
    'mission:replanned',
    // INBOUND-1: Request lifecycle events. `request:created` is published by
    // RequestService.create() so the SLA subscriber can auto-create a
    // `respond_to_user` WorkItem for the orchestrator when an inbound user
    // message lands without a corresponding WI on the orc's plate.
    // `request:sla_breached` is published by RequestSlaSubscriber when the
    // 5-minute SLA timer fires and the respond_to_user WI is still not done.
    'request:created',
    'request:sla_breached',
    // INBOUND-1.f1: WorkItem queue mutation event. Published by
    // TaskPoolService.addToPool whenever a fresh WorkItem is enqueued. Carries
    // both the new WorkItem id and — when the WI was decomposed from a Request
    // (e.g. the orc decomposed an inbound Slack message into delegate WIs) —
    // the source `requestId` so the RequestSlaSubscriber can self-resolve a
    // tracked respond_to_user WI on decomposition (auto-close path b).
    // Treated as CRITICAL — queue mutations are user-visible.
    'workitem:queued',
    // Hierarchy communication events
    'hierarchy:escalation',
    'hierarchy:delegation',
    'hierarchy:report_up',
    // B0 (interim) per `.crewly/specs/2026-05-05-trigger-persistence-bug.md`:
    // Fired exactly once when the backend HTTP server begins listening, after
    // EventBusService is wired and all subscribers have had a chance to attach.
    // Subscribers (e.g. self-watch-scribe) use this as a freshness signal to
    // re-arm in-memory triggers (`schedule-followup`, `watch-for-event`) that
    // are wiped on every restart. Treated as CRITICAL because re-arm latency
    // determines coverage gap of every trigger-dependent watchdog in the system.
    'system:backend_restarted',
    // Memory pressure broadcast (2026-05-14 follow-up): emitted by the
    // reconciler when it has skipped wake actions due to memory pressure
    // for long enough that the user-facing system has visibly stalled.
    // Orc subscribes so it can surface "system memory critical, X agents
    // frozen" in its next reply instead of silently spinning. The
    // reconciler emits with built-in throttling (no more than once per
    // sustained pressure episode + a re-fire cap) so this never floods.
    'system:memory_pressure',
    // Stuck-WI escalation (2026-05-20 follow-up): emitted by the reconciler
    // when a WorkItem has been in `queued` past the staleness threshold
    // (default 1h, lower per dispatch cadence) AND the existing recovery
    // chain (DispatchSubscriber, AgentAutoClaim, wake-under-pressure)
    // hasn't transitioned it. This is the missing actionable signal for
    // the 2026-05-20 ESTestNode incident: Sora's WI sat queued for 53min
    // because all three recovery paths require the target to be already
    // suspended/inactive, but Sora was `active-but-idle` and silently
    // dropped the message. ORC subscribes (filtered to `owner === self`)
    // so it can re-deliver, re-target, or fail-fast the stuck work.
    // The reconciler emits with per-WI dedup so a long-stuck WI doesn't
    // re-fire every reconcile tick — see ReconcilerDataProvider.broadcastStaleQueuedWIs.
    'task:queued_too_long',
];
/**
 * Critical event types that the orchestrator MUST receive.
 * These indicate actionable state changes: task completions, failures,
 * agent crashes, context exhaustion, and escalations.
 */
export const CRITICAL_EVENT_TYPES = new Set([
    'task:completed',
    'task:failed',
    'task:cancelled',
    'task:input_required',
    'agent:idle',
    'agent:idle_after_registration',
    'agent:idle_after_task',
    'agent:inactive',
    'agent:context_critical',
    'hierarchy:escalation',
    // Architecture Upgrade: task event chain — these drive workflow progression
    'task:done',
    'task:verified',
    'task:blocked',
    'task:needs_clarification',
    'task:assigned',
    'team:all_tasks_done',
    // BRIDGE-1: worker submission, TL rejection, and mission-level reviews are
    // all queue-creating events — they MUST not be debounced into oblivion.
    'task:done_by_worker',
    'task:rejected',
    'mission:review_due',
    'mission:stale',
    'mission:replanned',
    // INBOUND-1: a fresh user request and an SLA breach are both
    // user-visible — must bypass any debounce.
    'request:created',
    'request:sla_breached',
    // INBOUND-1.f1: queue mutations are user-visible (the SLA subscriber
    // depends on every decomposition firing exactly once for auto-close).
    'workitem:queued',
    // B0 (interim) per `.crewly/specs/2026-05-05-trigger-persistence-bug.md`:
    // backend-restart broadcast must NOT be debounced — coverage of every
    // trigger-dependent watchdog depends on exactly-one delivery per restart.
    'system:backend_restarted',
    // Memory pressure is user-facing — orc surfaces it in its next reply.
    // Debouncing here would defeat the purpose; the reconciler already
    // throttles the emission rate at the source.
    'system:memory_pressure',
    // Stuck WI escalation — orc needs the actionable signal that one of
    // its delegations has been silently dropped. The reconciler dedups
    // per-WI so this never floods even when many WIs are stuck.
    'task:queued_too_long',
]);
/**
 * Info event types that are noisy for the orchestrator terminal.
 * Repeated idle/busy toggles, minor status changes, and routine hierarchy
 * updates fall here. Subscribers can still opt-in via explicit subscription.
 */
export const INFO_EVENT_TYPES = new Set([
    'agent:status_changed',
    'agent:busy',
    'agent:active',
    'agent:context_warning',
    'agent:oauth_url',
    'task:submitted',
    'task:accepted',
    'task:working',
    'task:verification_requested',
    'hierarchy:delegation',
    'hierarchy:report_up',
]);
/**
 * Check if an event type is critical (requires immediate delivery).
 *
 * @param eventType - The event type to check
 * @returns True if the event type is critical
 */
export function isCriticalEventType(eventType) {
    return CRITICAL_EVENT_TYPES.has(eventType);
}
/**
 * Get the list of critical event types as an array (for subscription creation).
 *
 * @returns Array of critical EventType values
 */
export function getCriticalEventTypes() {
    return Array.from(CRITICAL_EVENT_TYPES);
}
// =============================================================================
// Type Guards
// =============================================================================
/**
 * Check if a value is a valid EventType
 *
 * @param value - Value to check
 * @returns True if value is a valid EventType
 */
export function isValidEventType(value) {
    return typeof value === 'string' && EVENT_TYPES.includes(value);
}
/**
 * Check if an object is a valid CreateSubscriptionInput
 *
 * @param value - Value to check
 * @returns True if value is a valid CreateSubscriptionInput
 */
export function isValidCreateSubscriptionInput(value) {
    if (!value || typeof value !== 'object') {
        return false;
    }
    const input = value;
    // Validate eventType: single string or array of strings
    if (Array.isArray(input.eventType)) {
        if (input.eventType.length === 0) {
            return false;
        }
        if (!input.eventType.every((t) => isValidEventType(t))) {
            return false;
        }
    }
    else if (!isValidEventType(input.eventType)) {
        return false;
    }
    // Validate filter
    if (!input.filter || typeof input.filter !== 'object') {
        return false;
    }
    // Validate subscriberSession
    if (typeof input.subscriberSession !== 'string' || input.subscriberSession.trim().length === 0) {
        return false;
    }
    // Validate optional ttlMinutes
    if (input.ttlMinutes !== undefined) {
        if (typeof input.ttlMinutes !== 'number' || input.ttlMinutes <= 0) {
            return false;
        }
    }
    // Validate optional oneShot
    if (input.oneShot !== undefined && typeof input.oneShot !== 'boolean') {
        return false;
    }
    // Validate optional messageTemplate
    if (input.messageTemplate !== undefined && typeof input.messageTemplate !== 'string') {
        return false;
    }
    return true;
}
//# sourceMappingURL=event-bus.types.js.map