/**
 * Per-runtime emitter dispatcher — V2 Phase 3, Round 1.
 *
 * Proposal: 2026-05-08-COMPONENT-DEPENDENCIES-V2.md, "Realize bridge" section.
 *
 * The dispatcher is a small registry + lookup framework. The real work lives in
 * each topology-specific emitter implementation (library.ts, and future
 * service.ts / managed.ts / executable.ts / messaging.ts files).
 *
 * Round 1 ships: dispatcher framework + library topology emitter (this file +
 * library.ts). The two cross-branch types — `ResolvedComponent` (Agent A) and
 * `FactoryV2Metadata` / `InstanceFactory` (Agent B) — are imported from their
 * canonical locations: Round 1d (this commit) reconciled the local stubs with
 * the merged real types.
 *
 * Round 2 will add: service, managed, executable, messaging emitters + CLI wiring.
 */
// ─── Dispatcher ───────────────────────────────────────────────────────────────
/**
 * Look up the correct emitter for the factory's topology.
 *
 * The emitters map is injected by the caller, making the dispatcher
 * extensible without engine changes: register new emitters by adding
 * entries to the map.
 *
 * @param factory - The resolved factory metadata (drives the topology lookup).
 * @param emitters - Registry of topology → RuntimeEmitter. Typically built
 *   once per realize run by `buildDefaultEmitters()`.
 * @returns The matching RuntimeEmitter.
 * @throws Error if no emitter is registered for the factory's topology.
 */
export function dispatchRuntimeEmitter(factory, emitters) {
    // V2 P3 R1d reconciliation: Agent B's loader populates factory.v2metadata
    // (with topology defaulted from factory.category). Pre-V2 factories
    // without v2metadata fall back to 'library' — the only emitter Round 1
    // registers, so dispatch is deterministic.
    const topology = factory.v2metadata?.topology ?? 'library';
    const emitter = emitters.get(topology);
    if (!emitter) {
        const available = Array.from(emitters.keys()).sort().join(', ');
        throw new Error(`No runtime emitter registered for topology '${topology}'. Available: ${available || '(none)'}`);
    }
    return emitter;
}
/**
 * Build the default emitter registry for a realize run.
 *
 * Round 1 shipped library; Round 2 added service / managed / executable /
 * messaging. All 5 are registered here so the realize-side dispatcher can
 * pick whichever the factory's v2metadata.topology selects.
 *
 * The 'external' topology is intentionally NOT registered — V2's design
 * defines it as a passthrough requiring manual wiring (no auto-emission).
 * Specs that bind a factory with topology: 'external' will trip a clear
 * "No runtime emitter registered" error, which is the desired behavior.
 *
 * Imports are deferred to avoid circular deps — each emitter file imports
 * only from dispatcher.ts, not vice versa.
 */
export async function buildDefaultEmitters() {
    const [{ LibraryRuntimeEmitter }, { ServiceRuntimeEmitter }, { ManagedRuntimeEmitter }, { ExecutableRuntimeEmitter }, { MessagingRuntimeEmitter },] = await Promise.all([
        import('./library.js'),
        import('./service.js'),
        import('./managed.js'),
        import('./executable.js'),
        import('./messaging.js'),
    ]);
    const map = new Map();
    map.set('library', new LibraryRuntimeEmitter());
    map.set('service', new ServiceRuntimeEmitter());
    map.set('managed', new ManagedRuntimeEmitter());
    map.set('executable', new ExecutableRuntimeEmitter());
    map.set('messaging', new MessagingRuntimeEmitter());
    return map;
}
//# sourceMappingURL=dispatcher.js.map