/**
 * CircuitBreakingIntelligenceProvider — wraps any IntelligenceProvider with the
 * account-global LlmCircuitBreaker.
 *
 * This is the structural chokepoint that makes the breaker universal: every
 * IntelligenceProvider built by the factory (and at the few direct construction
 * sites) is wrapped once, so EVERY consumer — current and future — is protected
 * without having to remember to consult the breaker (Structure > Willpower).
 *
 * Behaviour:
 *   - Before delegating, ask the breaker. If it's open, throw
 *     LlmCircuitOpenError WITHOUT spawning the underlying provider — this is
 *     what actually stops the bleeding: no `claude -p` subprocess, no tokens.
 *   - On success, tell the breaker the provider responded (closes it).
 *   - On a rate-limit error, trip the breaker and re-throw a typed
 *     RateLimitError so callers/telemetry can distinguish it.
 *   - On any other error, close the breaker (the limit isn't the cause) and
 *     re-throw the original error unchanged so existing fallback paths behave
 *     exactly as before.
 *
 * Callers that already swallow provider errors (e.g. PromptGate's silent
 * fallback) will swallow LlmCircuitOpenError too — which is precisely the
 * desired behaviour: skip the LLM step while the breaker is open and fall back
 * to heuristics, at zero subprocess cost.
 */
import type { IntelligenceProvider, IntelligenceOptions } from './types.js';
import { LlmCircuitBreaker } from './LlmCircuitBreaker.js';
/**
 * Minimal structural recorder the funnel writes per-call metrics to. Kept as a
 * local interface (not an import of FeatureMetricsLedger) so core/ never depends
 * on monitoring/ — the concrete ledger is injected at runtime via
 * setFeatureMetricsRecorder(). FeatureMetricsLedger.record() satisfies this.
 */
export interface FeatureMetricsRecorder {
    record(entry: {
        feature: string;
        kind?: 'llm' | 'event';
        outcome: 'fired' | 'noop' | 'error' | 'shed';
        latencyMs?: number;
        waited?: boolean;
        waitMs?: number;
        /**
         * Per-call token usage (Iris-audit item 1). Surfaced by the underlying
         * provider via IntelligenceOptions.onUsage and forwarded here so
         * /metrics/features reports real cost instead of always-0. The ledger
         * stores null when omitted (e.g. the circuit was open and no call ran).
         */
        tokensIn?: number;
        tokensOut?: number;
        /**
         * Cache-read input tokens — an informational SUBSET of tokensIn
         * (token-audit-completeness). Fresh cost = tokensIn − tokensCached.
         */
        tokensCached?: number;
        /**
         * Observable Intelligence: the resolved model + framework that actually
         * served this call, surfaced by the provider via IntelligenceOptions.onModel.
         * Recorded independently of token usage so codex/gemini/pi calls (which
         * report no tokens) are still attributable to a provider.
         */
        model?: string;
        framework?: string;
        /** Correlates a 'fired' verdict to a downstream record (e.g. a commitment id). */
        verdictId?: string;
    }): void;
}
export declare function setFeatureMetricsRecorder(recorder: FeatureMetricsRecorder | null): void;
export declare function getFeatureMetricsRecorder(): FeatureMetricsRecorder | null;
/** Test-only seam. */
export declare function _resetUnlabeledEmissionForTest(): void;
export declare class CircuitBreakingIntelligenceProvider implements IntelligenceProvider {
    private readonly inner;
    private readonly breaker;
    constructor(inner: IntelligenceProvider, breaker?: LlmCircuitBreaker);
    /**
     * Record one funnel call to the per-feature metrics ledger (Phase 1b). Pure
     * side-channel: it MUST never throw into the LLM path (observability must not
     * break what it observes — the Close the Loop principle applied to itself).
     * outcome here is funnel-level: 'noop' = the call completed (the fired-vs-noop
     * VERDICT is the caller's interpretation → Phase 2); 'error' = it failed;
     * 'shed' = the circuit was open so NO call ran (no token cost, no network
     * round-trip). Keeping 'shed' distinct from 'noop' is what makes the metric
     * honest: 'calls' minus 'shed' = real round-trips, so the breaker shedding
     * load can't masquerade as completed work (the 0ms-latency confound).
     */
    private recordMetric;
    evaluate(prompt: string, options?: IntelligenceOptions): Promise<string>;
}
/**
 * Wrap a provider with the shared circuit breaker. No-ops on null (so callers
 * can pass a possibly-null factory result through unchanged) and is idempotent
 * (never double-wraps).
 */
export declare function wrapIntelligenceWithCircuitBreaker(provider: IntelligenceProvider | null | undefined, breaker?: LlmCircuitBreaker): IntelligenceProvider | null;
//# sourceMappingURL=CircuitBreakingIntelligenceProvider.d.ts.map