import type { LedgerEntry } from '../runtime/telemetry/exporters/local-ledger.js';
import type { RuntimeStateSnapshot } from '../runtime/diagnostics/types.js';
/**
 * Category of a mismatch between expected and replayed state.
 *
 * - `missing_event`    : an event expected at this revision was absent.
 * - `extra_event`      : an event appeared that was not in the recording.
 * - `payload_mismatch` : event name matched but payload differed.
 * - `ordering`         : events arrived in different order than recorded.
 * - `state_divergence` : domain state diverged after applying event.
 */
export type MismatchClass = 'missing_event' | 'extra_event' | 'payload_mismatch' | 'ordering' | 'state_divergence';
export type ReplayMismatchOwnerDomain = 'turn' | 'tasks' | 'tools' | 'providers' | 'session' | 'conversation' | 'agents' | 'workflows' | 'permissions' | 'transport' | 'unknown';
export type ReplayMismatchFailureMode = 'missing_event' | 'extra_event' | 'ordering_violation' | 'payload_schema_mismatch' | 'payload_type_mismatch' | 'payload_value_mismatch' | 'missing_terminal_summary' | 'terminal_outcome_diverged' | 'stop_reason_diverged';
/**
 * A single actionable mismatch entry produced by diff mode.
 */
export interface ReplayMismatch {
    /** The revision at which the mismatch was detected. */
    readonly rev: number;
    /** Mismatch classifier. */
    readonly kind: MismatchClass;
    /** Human-readable description — sufficient to act on without raw dumps. */
    readonly description: string;
    /** The event name involved, if applicable. */
    readonly eventName?: string;
    /** Key fields from the recorded payload, if applicable. */
    readonly recordedSummary?: string;
    /** Key fields from the replayed payload, if applicable. */
    readonly replayedSummary?: string;
    /** Likely owning runtime domain for the divergence. */
    readonly ownerDomain?: ReplayMismatchOwnerDomain;
    /** Narrower replay failure mode for operator triage. */
    readonly failureMode?: ReplayMismatchFailureMode;
    /** Related turn ID when the divergence can be tied to a single turn. */
    readonly relatedTurnId?: string;
}
export type ReplayTurnOutcome = 'completed' | 'failed' | 'cancelled';
export interface ReplayTurnSummary {
    readonly turnId: string;
    readonly outcome: ReplayTurnOutcome;
    readonly terminalEvent: 'PREFLIGHT_FAIL' | 'TURN_COMPLETED' | 'TURN_ERROR' | 'TURN_CANCEL';
    readonly startedRev?: number;
    readonly terminalRev: number;
    readonly stopReason?: string;
    readonly message?: string;
}
/**
 * The replay-local state tree at a given revision.
 *
 * Built by folding ledger entries over the initial snapshot; each step
 * produces a new immutable frame.
 */
export interface ReplayFrame {
    /** The revision this frame represents (0 = initial snapshot). */
    readonly rev: number;
    /** The event that produced this frame (absent for the initial snapshot). */
    readonly entry?: LedgerEntry;
    /** Domain state at this revision — merged from snapshot + events applied so far. */
    readonly domains: Record<string, Record<string, unknown>>;
}
export type ReplayStatus = 'idle' | 'loaded' | 'running' | 'exhausted';
/**
 * Snapshot of engine state for the Replay panel.
 */
export interface ReplayEngineSnapshot {
    readonly status: ReplayStatus;
    readonly runId: string | null;
    readonly currentRev: number;
    readonly totalRevisions: number;
    readonly currentFrame: ReplayFrame | null;
    readonly mismatches: readonly ReplayMismatch[];
    readonly turnSummaries: readonly ReplayTurnSummary[];
}
/**
 * DeterministicReplayEngine.
 *
 * Usage:
 * ```ts
 * const engine = new DeterministicReplayEngine('/path/to/project');
 * engine.load(runId, snapshot, ledgerEntries);
 * engine.step();          // advance one event
 * engine.step(5);         // advance five events
 * engine.seek(10);        // jump to rev 10
 * const report = engine.diff();  // compare current to recorded
 * engine.export('replay.json');  // write report inside the project root
 * ```
 */
export declare class DeterministicReplayEngine {
    private readonly _projectRoot;
    private _status;
    private _runId;
    private _snapshot;
    /**
     * Returns the initial snapshot that was loaded, or null if no run is loaded.
     */
    getInitialSnapshot(): RuntimeStateSnapshot | null;
    private _entries;
    private _frames;
    private _currentFrameIndex;
    private _mismatches;
    private _turnSummaries;
    private readonly _subscribers;
    constructor(projectRoot: string);
    private _isInsideRoot;
    /**
     * Load a run for replay.
     *
     * Replaces any currently loaded run. The engine is positioned at rev 0
     * (the initial snapshot) after loading.
     *
     * @param runId    - The run identifier.
     * @param snapshot - The initial state snapshot captured at run start.
     * @param entries  - All ledger entries for this run, in any order (sorted internally).
     */
    load(runId: string, snapshot: RuntimeStateSnapshot, entries: LedgerEntry[]): void;
    /**
     * Advance the replay cursor by `n` steps (default: 1).
     *
     * Returns the frames that were stepped over.
     * If fewer than `n` events remain, steps to the end.
     *
     * @param n - Number of steps to advance.
     * @returns The frames produced by the steps.
     */
    step(n?: number): ReplayFrame[];
    /**
     * Seek to a specific revision.
     *
     * Valid revisions are 0 (initial snapshot) through `totalRevisions`.
     * Clamped to valid range.
     *
     * @param targetRev - Target revision number.
     */
    seek(targetRev: number): void;
    /**
     * Run diff mode: compare each replayed frame against the recorded sequence.
     *
     * Produces a list of `ReplayMismatch` entries that identify divergences
     * with actionable classifiers and descriptions — not raw payload dumps.
     *
     * Diff analysis covers:
     * - Missing events (recorded entry has no corresponding replayed frame)
     * - Extra events (frame exists past the recorded sequence)
     * - Payload mismatches (event name matches, but key payload fields differ)
     * - Ordering violations (same events, different rev sequence)
     *
     * @returns Ordered list of mismatches (by rev).
     */
    diff(): ReplayMismatch[];
    /**
     * Export the current replay report (frames + mismatches) to a JSON file.
     *
     * The exported object contains:
     * - `runId`
     * - `exportedAt` (epoch ms)
     * - `totalRevisions`
     * - `currentRev`
     * - `mismatches`
     * - `frames` (condensed: rev, eventName, domainNames only — no full state)
     *
     * @param filePath - Absolute path to write the JSON report.
     * @returns A promise that resolves when the file is written.
     */
    export(filePath: string): Promise<void>;
    /**
     * Get a snapshot of engine state for the Replay panel.
     */
    getSnapshot(): ReplayEngineSnapshot;
    /**
     * Register a callback invoked when engine state changes.
     * @returns An unsubscribe function.
     */
    subscribe(callback: () => void): () => void;
    /** Reset to idle — clears all loaded state. */
    reset(): void;
    /**
     * Convert a RuntimeStateSnapshot into a flat domain map.
     */
    private _snapshotToDomains;
    /**
     * Apply a single ledger entry to the previous frame, producing a new frame.
     *
     * Event payloads are merged into the domain state by convention:
     * the payload is treated as a partial update to the event's implied domain
     * (derived from the event name prefix, e.g. "turn:" → "turn" domain).
     * Unknown domain prefixes are collected into a synthetic "_events" domain.
     */
    private _applyEntry;
    /**
     * Compare two payloads at a key-level and return a mismatch if they diverge.
     *
     * Reports only the first differing key to keep the output actionable.
     */
    private _diffPayloads;
    private _deriveTurnSummaries;
    private _diffTurnSummaries;
    private _extractTurnId;
    private _inferOwnerDomain;
    private _notify;
}
//# sourceMappingURL=deterministic-replay.d.ts.map