/**
 * EventToWorkItemBridge
 *
 * Subscribes to autonomy-relevant events on the EventBus and creates the
 * appropriate WorkItem(s) so the autonomy chain advances without an explicit
 * Trigger Engine (Arch Veto V5 — `.crewly/tmp/autonomy-doc-review-arch-2026-04-26.md`).
 *
 * Subscribed events (all `CRITICAL_EVENT_TYPES`):
 *   - `task:done_by_worker`  → verification WI for TL
 *   - `task:rejected`        → retry WI (or escalation review WI at retry cap)
 *   - `task:blocked`         → review WI (`reviewReason: 'task_blocked'`)
 *   - `team:all_tasks_done`  → emit `mission:review_due` (if mission active)
 *   - `mission:review_due`   → review WI mirroring REVIEW-1's id pattern
 *   - `mission:stale`        → review WI (`reviewReason: 'no_active_work'`)
 *   - `mission:replanned`    → review WI (`reviewReason: 'scheduled_review'`)
 *
 * Idempotency contract (Arch Veto V1):
 *   Every auto-created WorkItem carries a deterministic `id` and a documentary
 *   `metadata.idempotencyKey === id`. The real dedup gate is
 *   `TaskPoolService.addToPool` which short-circuits on duplicate id. So a
 *   replayed event fires the bridge handler again, the bridge re-builds the
 *   same id, and addToPool's existing dedup is the safety net — no separate
 *   idempotency store needed.
 *
 * Retry cap (Arch Veto V2):
 *   `task:rejected` increments `retryCount` on the new retry WI. At
 *   `sourceWI.retryCount >= DEFAULT_MAX_RETRIES` (3) the bridge escalates to
 *   a review WI for the TL with `reviewReason: 'max_retries_exceeded'` and
 *   does NOT enqueue another retry. Retry WIs target the original worker;
 *   escalation WIs target the team lead resolved via `pickTeamLead()`.
 *
 * Status mutations (Arch Veto V3):
 *   The bridge does NOT mutate status directly — every state change goes
 *   through `TaskPoolService.transitionStatus()` (the canonical guarded
 *   entrypoint TRANS-1 shipped). Search guard (see PR body for full grep
 *   command — kept out of the doc comment so the grep doesn't false-positive
 *   on its own description).
 *
 * Team-lead resolution (Arch Veto V4):
 *   `pickTeamLead()` may return `null`. The bridge throws
 *   {@link BridgeTeamLeadResolutionError} on null — no silent fallback to
 *   the executor session.
 *
 * No parallel scheduler entity (Arch Veto V5):
 *   The bridge is a pure event listener. It does NOT subclass anything called
 *   "Trigger", does NOT create one, does NOT register with a TriggerEngine.
 *   See PR body for the grep guard command.
 *
 * Cron-recursion block (Arch Vetos V6 / V9):
 *   When the bridge derives a new WI from a source WI whose
 *   `metadata.triggerSource === 'cron'`, the new WI's triggerSource is
 *   demoted to `'event'` (cron sessions cannot beget more cron jobs). Any
 *   call to {@link assertNoCronFromCron} from a cron-source WI throws
 *   {@link CronRecursionError}. The retry path tags `triggerSource: 'event'`
 *   directly so demotion is the default rather than the exceptional path.
 *
 * @module services/event-bus/event-to-workitem-bridge
 */
import { type ComponentLogger } from '../core/logger.service.js';
import { TaskPoolService } from '../task-pool/task-pool.service.js';
import { type WorkItem } from '../../types/v2/work-item.types.js';
import type { Mission } from '../../types/v2/mission.types.js';
import type { Team } from '../../types/index.js';
import type { EventType } from '../../types/event-bus.types.js';
import type { EventBusService } from './event-bus.service.js';
/**
 * Event types the bridge subscribes to. Listed in the same order as the
 * dispatch table to make the start() registration easy to audit.
 */
export declare const BRIDGE_SUBSCRIBED_EVENTS: readonly EventType[];
/**
 * Vocabulary for `metadata.triggerSource` — what kind of impulse caused
 * this WorkItem to exist. Bridge-created WIs always tag with `'event'`;
 * cron-fired WIs are demoted to `'event'` to satisfy V6/V9.
 */
export type WorkItemAutoSource = 'event' | 'cron' | 'manual';
/**
 * Thrown when a cron-sourced WorkItem attempts to create another cron-recurring
 * WorkItem. Encoded as a named error so tests + observability can distinguish
 * the recursion guard from generic bridge errors.
 */
export declare class CronRecursionError extends Error {
    constructor(message: string);
}
/**
 * Thrown when the bridge cannot resolve a Team Lead session for a team that
 * needs an escalation/verification WorkItem. Per Arch Veto V4 the bridge
 * MUST NOT silently fall back to the executor session — losing visibility
 * on a stalled escalation is worse than failing loudly.
 */
export declare class BridgeTeamLeadResolutionError extends Error {
    constructor(message: string);
}
/**
 * V6 / V9 guard: throw if a cron-sourced WI tries to create another cron job.
 *
 * @param sourceWI - WI being reacted to
 * @param attemptedAction - Short label for the action that would create cron
 * @throws CronRecursionError when sourceWI.metadata.triggerSource === 'cron'
 */
export declare function assertNoCronFromCron(sourceWI: WorkItem, attemptedAction: string): void;
/**
 * Optional dependency injection container so tests can supply fakes for the
 * mission loader and team resolver without touching the real fs / storage.
 *
 * Production wiring uses the singletons from {@link StorageService} and
 * {@link TaskPoolService} via the loader / resolver helpers in
 * {@link EventToWorkItemBridge.boot}.
 */
export interface BridgeDependencies {
    /** Live event bus instance. */
    eventBus: EventBusService;
    /** TaskPool for read-back + addToPool. */
    taskPool: TaskPoolService;
    /** Loads a mission by id. Returns null if missing. */
    loadMission: (missionId: string) => Promise<Mission | null>;
    /** Loads a team by id. Returns null if missing. */
    loadTeam: (teamId: string) => Promise<Team | null>;
    /** Optional logger override (defaults to component logger). */
    logger?: ComponentLogger;
}
/**
 * EventToWorkItemBridge — the BRIDGE-1 deliverable.
 *
 * Wired in `backend/src/index.ts` via {@link EventToWorkItemBridge.boot}; tests
 * construct via the {@link EventToWorkItemBridge} constructor directly with
 * fake dependencies.
 *
 * @example
 * ```typescript
 * const bridge = EventToWorkItemBridge.boot(eventBus);
 * bridge.start();
 * // … later, on shutdown:
 * bridge.stop();
 * ```
 */
export declare class EventToWorkItemBridge {
    private readonly eventBus;
    private readonly taskPool;
    private readonly loadMission;
    private readonly loadTeam;
    private readonly logger;
    private unsubscribers;
    private started;
    /**
     * In-flight async handler invocations. Test code calls
     * {@link flushPending} to await every in-flight dispatch deterministically.
     * Production code never reads this — handlers continue running off the
     * event loop with their own try/catch.
     */
    private pendingDispatches;
    constructor(deps: BridgeDependencies);
    /**
     * Production wiring helper — constructs a bridge from singletons.
     *
     * Tests should use the constructor directly with fake `loadMission` /
     * `loadTeam` rather than reaching for `boot`.
     *
     * @param eventBus - The live event bus
     * @returns A bridge instance ready to `start()`
     */
    static boot(eventBus: EventBusService): EventToWorkItemBridge;
    /**
     * Subscribe to all bridge events. Idempotent — calling twice is a no-op.
     *
     * Each handler is wrapped so that a thrown error inside a single event
     * dispatch is logged but does NOT propagate to `EventBus.publish()`. The
     * EventBus itself also isolates handler errors (see
     * `dispatchInProcess`); the inner try/catch belt-and-braces against the
     * particular case where a handler returns a non-Promise that subsequently
     * throws on access (rare but observed in jest fake-timer setups).
     */
    start(): void;
    /**
     * Wait for every in-flight handler dispatch to settle. Test affordance —
     * production code does not need this; the EventBus + safeDispatch already
     * isolate handler errors. Tests use it to assert deterministically that
     * `addToPool` has been called by the time the expectation runs, even
     * though `EventBus.publish` is synchronous and bridge handlers are async.
     *
     * Calling more than once is safe — pending dispatches are removed as they
     * settle, so a second call is effectively a no-op when nothing is in flight.
     */
    flushPending(): Promise<void>;
    /**
     * Detach every subscription. Safe to call multiple times.
     */
    stop(): void;
    /**
     * `task:done_by_worker` → create a verification WI for the team lead.
     *
     * Idempotency: `${sourceWI.id}:verify:${sourceWI.id}` (one verify WI per task done).
     * V4: throws if no TL resolvable.
     */
    private handleTaskDoneByWorker;
    /**
     * `task:rejected` → retry WI (cap at DEFAULT_MAX_RETRIES) or escalation review WI.
     *
     * - retryCount < cap → retry WI assigned to original worker, retryCount + 1
     * - retryCount >= cap → review WI for TL with reviewReason='max_retries_exceeded'
     *
     * Idempotency:
     *   - retry path: `${sourceWI.id}:retry:${retryAttempt}`
     *   - escalation: `${sourceWI.id}:review:max_retries`
     */
    private handleTaskRejected;
    /**
     * `task:blocked` → review WI for TL with `reviewReason='task_blocked'`.
     *
     * Idempotency: `${sourceWI.id}:review:blocked` (one review per blocked WI).
     */
    private handleTaskBlocked;
    /**
     * `team:all_tasks_done` → emit `mission:review_due` if mission is active.
     *
     * The downstream `mission:review_due` handler then creates the actual
     * review WorkItem. We split the emission from the WI-creation so the
     * existing REVIEW-1 sweep path and BRIDGE-1's event-driven path converge
     * on the same idempotency key (REVIEW-1 uses `${missionId}:review:${YYYY-MM-DD}`;
     * BRIDGE-1's mission:review_due handler uses the same).
     */
    private handleTeamAllTasksDone;
    /**
     * `mission:review_due` → review WI mirroring REVIEW-1's id pattern.
     * Idempotency: `${missionId}:review:${YYYY-MM-DD}` — same as REVIEW-1.
     */
    private handleMissionReviewDue;
    /**
     * `mission:stale` → review WI with `reviewReason='no_active_work'`.
     * Idempotency: `${missionId}:review:stale:${YYYY-MM-DD}`.
     */
    private handleMissionStale;
    /**
     * `mission:replanned` → review WI tied to the replan event id.
     * Idempotency: `${missionId}:review:replan:${eventId}`.
     */
    private handleMissionReplanned;
    /**
     * Build an auto-created WorkItem with all the BRIDGE-1 metadata invariants
     * filled in (deterministic id, idempotencyKey === id, triggerSource derived
     * from source WI, parent linkage). Pulls every shared field through one
     * factory so each handler stays declarative and the V1 grep guard
     * (`grep -c "idempotencyKey:" backend/src/services/event-bus/event-to-workitem-bridge.service.ts`
     * ≥ 6) holds without litter.
     */
    private buildAutoWorkItem;
    /**
     * Resolve the source WorkItem from an event. Prefers `event.workItemId`
     * (BRIDGE-1.1 explicit field), falls back to `event.taskId` for events
     * whose publishers haven't been migrated yet.
     *
     * @param event - The event being handled
     * @returns The source WorkItem, or null when nothing matches
     */
    private resolveSourceWorkItem;
    /**
     * Resolve the team-lead session for a source WI's owning team.
     * Throws {@link BridgeTeamLeadResolutionError} if no TL is resolvable —
     * Arch Veto V4 forbids silently falling back to the executor.
     */
    private resolveTeamLeadSession;
    /**
     * Resolve TL for a mission. Same V4 fail-fast contract as
     * {@link resolveTeamLeadSession} but keyed on `mission.ownerTeamId`.
     */
    private resolveTeamLeadSessionForMission;
    /**
     * Wrap a handler so a thrown error is caught at the bridge boundary instead
     * of bubbling into EventBus.dispatchInProcess. Errors from handlers
     * shouldn't crash the publisher — they should be observable via logs and
     * — for tests — rethrowable from a deterministic spy point.
     */
    private safeDispatch;
}
//# sourceMappingURL=event-to-workitem-bridge.service.d.ts.map