/**
 * Capability dispatcher — the typed channel analyzers use to request a
 * capability (lint, depVulns, coverage, …) by descriptor. The dispatcher
 * runs every registered provider concurrently, filters nulls and
 * rejections, and aggregates the survivors using the descriptor's
 * bespoke aggregator.
 *
 * Caching is in-memory and per-dispatcher-instance: the same `(cwd, capId)`
 * request inside one analyzer run reuses the same Promise, so two reports
 * (e.g. `health` + `vulnerabilities`) sharing a process don't double-shell
 * out to `pip-audit`. Process exit clears the cache; persistent caching
 * is out of scope.
 *
 * Provider failures are isolated: one provider throwing does not abort the
 * dispatch. The thrown error is logged via the optional `onProviderError`
 * hook and that provider's contribution is dropped from the aggregate.
 */
import type { CapabilityProvider } from '../languages/capabilities/provider';
import type { CapabilityDescriptor } from '../languages/capabilities/descriptors';
import type { CapabilityEnvelope } from '../languages/capabilities/types';
export interface DispatcherOptions {
    /** Called once per provider that throws or rejects. Default: silent. */
    onProviderError?(capId: string, source: string, err: unknown): void;
    /**
     * Called once per provider whose Promise never settles within the
     * deadline. Default: warns on stderr. Tests pass a stub to capture
     * stalls without polluting test output.
     */
    onProviderStall?(capId: string, source: string, stalledMs: number): void;
    /**
     * Per-provider deadline. Stalled providers are treated as if they
     * had returned `null` with a "stalled at >Ns (deadline)" reason —
     * the rest of the dispatch still completes via `Promise.allSettled`,
     * and the stall surfaces in `toolsUnavailable` via the existing
     * `availabilityFromOutcome` machinery. Default:
     * `DEFAULT_PROVIDER_DEADLINE_MS` (12 minutes).
     */
    providerDeadlineMs?: number;
}
/**
 * D080 (2.4.7): when a multi-pack capability has providers that
 * return null silently (tool unavailable on the customer's machine),
 * the rendered tool label hides which packs were attempted.
 * gatherWithProvenance exposes both the aggregated envelope AND the
 * per-provider {ran, skipped} split so consumers can surface
 * "lint ran: ruff; not run: eslint (not installed)" instead of just
 * "lint ran: ruff."
 */
export interface DispatchOutcome<T extends CapabilityEnvelope> {
    envelope: T | null;
    /** All provider sources we ATTEMPTED to run (one per provider passed in). */
    attempted: string[];
    /** Sources that returned a non-null envelope. Subset of `attempted`. */
    succeeded: string[];
    /** Sources that returned null (tool absent, no config, etc.). */
    skipped: string[];
    /**
     * Per-source reasons for skipping, when the provider exposes a
     * `gatherOutcome` method (the same channel `DepVulnsProvider`,
     * `LicensesProvider`, and `LintProvider` use to surface
     * unavailability reasons). Empty record when no provider supplied
     * a reason — legacy `gather()`-only providers don't propagate
     * "why" through this boundary, so their skip entries land in
     * `skipped` without an entry here. Consumers should treat absent
     * keys as "reason unknown" and render accordingly.
     */
    skipReasons: Record<string, string>;
}
export declare class CapabilityDispatcher {
    private readonly cache;
    private readonly opts;
    constructor(opts?: DispatcherOptions);
    gather<T extends CapabilityEnvelope>(cwd: string, cap: CapabilityDescriptor<T>, providers: ReadonlyArray<CapabilityProvider<T>>): Promise<T | null>;
    /**
     * Same gather + cache semantics as `gather()`, plus per-provider
     * provenance (which sources we attempted, which returned null).
     * D080 (2.4.7): consumed by quality/health report renderers so the
     * "Tool" label honestly reflects which providers were attempted even
     * when one returned null silently.
     */
    gatherWithProvenance<T extends CapabilityEnvelope>(cwd: string, cap: CapabilityDescriptor<T>, providers: ReadonlyArray<CapabilityProvider<T>>): Promise<DispatchOutcome<T>>;
    /** Test seam — drop the in-memory cache between runs. */
    clearCache(): void;
    private run;
}
/** Process-wide singleton. Tests should construct their own instance. */
export declare const defaultDispatcher: CapabilityDispatcher;
//# sourceMappingURL=dispatcher.d.ts.map