/**
 * TopicProfileResolver — the SINGLE resolution point for a topic's execution
 * profile (TOPIC-PROFILE-SPEC §5.2), called from spawnSessionForTopic and the
 * tier-escalation consult (§9). In-memory, O(1) per call.
 *
 * Precedence per field: profile-store pin > config default > global default.
 *  - model arm: topic-profile pin > `topicProfiles.defaults` config >
 *    `frameworkDefaultModels` > account default — with the §10.2 clamp run
 *    at THIS boundary for every source (an off-enum config default falls to
 *    the next layer with a once-per-transition disclosure; config never
 *    persists through the store, so a write-time-only clamp would leave a
 *    named hole).
 *  - framework arm: profile-store framework > `config.topicFrameworks`
 *    (the legacy config layer, read-through unchanged — Migration Parity) >
 *    global default. A pinned framework whose CLI is not launchable falls
 *    back to the global default with a once-per-transition notice (§3.5
 *    keep-working: a dead pane is NOT "today's behavior"). The launchability
 *    check is CHEAP/CACHED (fs.existsSync, TTL'd) — never a per-spawn
 *    subprocess.
 *  - A `/local-model` binding is provider-level and WINS the model arm for
 *    that framework (§5.2) — resolution defers to it; the write side refuses
 *    new cloud pins while a binding is active.
 *  - Read-time re-validation: a persisted model pin is re-checked against
 *    the CURRENT closed enum (the enum can shrink after write); a
 *    no-longer-member id falls back with a one-line notice.
 *  - Disabled-flag semantics (§5.2): reads HONOR existing on-disk pins even
 *    when `topicProfiles` is disabled — the flag gates writes, never reads.
 *
 * Fallback notices are deduped per (topic, pin, reason) STATE TRANSITION
 * (§5.2 round-3) — disclosed once, then audit-only until the pin or the
 * underlying condition changes.
 */
import type { IntelligenceFramework } from './intelligenceProviderFactory.js';
import type { TopicProfileStore } from './TopicProfileStore.js';
import { type EffortLevel, type EscalationOverride, type ProfileModelTier, type ThinkingMode } from './topicProfileValidation.js';
import { type TierEscalationConfig } from './ModelTierEscalation.js';
export interface ResolvedTopicProfile {
    framework: IntelligenceFramework;
    /**
     * The model to pass to the launch builder (concrete id), or undefined for
     * the account default. Already clamped through the closed enum.
     */
    model: string | undefined;
    /** The baseline tier pin, when the pin is tier-shaped (§7 in-flight row eligibility). */
    modelTier: ProfileModelTier | null;
    thinkingMode: ThinkingMode | undefined;
    /**
     * The Claude Code `--effort` level to pass at spawn, or undefined for none.
     * An invalid stored value FAILS OPEN to undefined (no `--effort` passed) —
     * resolution never throws and never hands the CLI a bad value.
     */
    effort: EffortLevel | undefined;
    /** §9 — default 'inherit' (the heavy-work ultra mandate stays in force). */
    escalationOverride: EscalationOverride;
    /** Which layer supplied each arm (audit/readout). */
    sources: {
        framework: string;
        model: string;
        thinkingMode: string;
        effort: string;
    };
    /**
     * Once-per-transition fallback notices to surface (empty in the common
     * case). Already deduped — the caller may send them verbatim.
     */
    notices: string[];
}
export interface TopicProfileResolverOptions {
    store: TopicProfileStore;
    /** Global default framework (sessions.framework / INSTAR_FRAMEWORK). */
    defaultFramework: () => IntelligenceFramework;
    /** Legacy config-level framework defaults (`config.topicFrameworks`). */
    configTopicFrameworks: () => Record<string, string>;
    /** `topicProfiles.defaults` — per-topic config-default profiles (§12.5). */
    configProfileDefaults: () => Record<string, {
        model?: string;
        thinkingMode?: string;
        effort?: string;
    }>;
    /** `frameworkDefaultModels` config layer. */
    frameworkDefaultModels: () => Partial<Record<IntelligenceFramework, string>>;
    /** Live tier-escalation config — resolves a modelTier pin to a concrete id. */
    tierEscalationConfig: () => TierEscalationConfig | undefined;
    /** Active `/local-model` binding for a topic (wins the model arm, §5.2). */
    localModelBinding: (topicKey: string) => {
        provider: string;
        model?: string;
    } | null;
    /** Resolve the framework's CLI binary path (for the launchability check). */
    frameworkBinaryPath: (framework: IntelligenceFramework) => string | null;
    /** Audit sink for fallback events (one line each, even when deduped). */
    audit?: (event: Record<string, unknown>) => void;
}
export declare class TopicProfileResolver {
    private readonly opts;
    /** (topic|pin|reason) keys already disclosed — once-per-transition dedupe. */
    private disclosedFallbacks;
    private launchabilityCache;
    constructor(opts: TopicProfileResolverOptions);
    /** O(1) — cache reads only; the single resolution point (§5.2). */
    resolve(topicKey: number | string): ResolvedTopicProfile;
    /**
     * §5.2 cheap/cached launchability: fs.existsSync on the resolved binary
     * path with a TTL — never an unconditional per-spawn subprocess.
     */
    private isLaunchable;
    /** Once-per-(topic,pin,reason) transition dedupe (§5.2 round-3). */
    private onceNotice;
    /** The condition cleared — re-arm the notice for a future recurrence. */
    private clearTransition;
}
//# sourceMappingURL=TopicProfileResolver.d.ts.map