/**
 * replayFrom — deterministic agent run replay.
 *
 * Given a runId, a ReplayLoader (fetches original trace + recorded artifacts),
 * and a ReplayRunner (re-executes the agent with virtualized dependencies),
 * replayFrom produces a ReplayResult containing:
 *   - The replayed trace.
 *   - A match flag: true iff rootHash of replay === rootHash of original.
 *   - A diff array listing step-level field mismatches (when match is false).
 *
 * Design invariant:
 *   Replay proves byte-identical traces when ClockPort, RandomPort, and
 *   LLMResponseCache are virtualized. It does NOT prove LLM provider-side
 *   determinism — the provider may return different tokens under identical
 *   inputs (temperature, context window, batching).
 *
 * @module replay/replay
 */
import type { Trace, TraceStep } from "../trace/schema.js";
import type { ClockPort } from "./clock.js";
import type { RandomPort } from "./random.js";
import type { LLMResponseCache } from "./llm-cache.js";
/**
 * Controls strictness of the replay session.
 *
 * - 'strict': crypto()/cryptoUuid() throws CryptoRandomDuringReplayError.
 *             Any non-deterministic call is surfaced immediately.
 * - 'tolerant': crypto()/cryptoUuid() returns fresh bytes (non-fatal).
 *               Useful for runs that legitimately mix deterministic + crypto calls.
 */
export type ReplayMode = "strict" | "tolerant";
/**
 * Virtualised execution context for a replay run.
 * Pass this to ReplayRunner.run() in place of the production context.
 */
export interface ReplayContext {
    /** runId of the original run being replayed. */
    readonly originalRunId: string;
    /**
     * A distinct runId for this replay run.
     * Must differ from originalRunId — replay runs are traceable separately.
     */
    readonly replayRunId: string;
    /** Strictness mode for crypto calls. */
    readonly mode: ReplayMode;
    /** Virtualized clock replaying the original run's timestamps. */
    readonly clock: ClockPort;
    /** Virtualized PRNG replaying the original run's random values. */
    readonly random: RandomPort;
    /** Virtualized LLM cache replaying the original run's responses. */
    readonly cache: LLMResponseCache;
}
/**
 * Result of a replay execution.
 *
 * match === true  → replay is byte-identical to the original (rootHash matches).
 * match === false → at least one step diverged; see diff for details.
 */
export interface ReplayResult {
    /** The replay run identifier. */
    replayRunId: string;
    /** The trace produced by the replay run. */
    trace: Trace;
    /**
     * True iff the rootHash of the replay trace equals the rootHash of the
     * original trace. This is the primary audit assertion.
     */
    match: boolean;
    /**
     * Step-level field mismatches, populated when match is false.
     * Empty array when match is true.
     */
    diff?: {
        stepIndex: number;
        field: keyof TraceStep;
        original: unknown;
        replayed: unknown;
    }[];
}
/**
 * Port for loading the artifacts needed to replay a run.
 * The host provides a concrete implementation (e.g. pgsql, file system).
 */
export interface ReplayLoader {
    /**
     * Fetch the original Trace for the given runId.
     * Throws if the run is not found.
     */
    loadOriginalTrace(runId: string): Promise<Trace>;
    /**
     * Fetch all recorded artifacts for the given runId:
     *   - recordedTs: timestamps array for RecordedClock
     *   - recordedNext: float array for RecordedRandom.next()
     *   - recordedUuids: UUID array for RecordedRandom.uuid()
     *   - cache: LLMResponseCache populated with the original run's responses
     */
    loadCacheEntries(runId: string): Promise<{
        recordedTs: number[];
        recordedNext: number[];
        recordedUuids: string[];
        cache: LLMResponseCache;
    }>;
}
/**
 * Port for re-executing the agent with a virtualised context.
 * The host provides a concrete implementation that wires the agent
 * to the virtualised ClockPort, RandomPort, and LLMResponseCache.
 *
 * Extended contract (counterfactual support):
 *   Implementations MAY inspect `(ctx as { strategyOverride?: string }).strategyOverride`
 *   to swap their compute strategy for offline counterfactual analysis.
 *   This field is injected exclusively by `replayCounterfactual` (offline tool) —
 *   it is never present in production replay contexts.
 */
export interface ReplayRunner {
    /**
     * Re-execute the agent using ctx (virtual clock/random/cache)
     * starting from the state described in originalTrace.
     *
     * Returns the new Trace produced by the replay.
     *
     * @param ctx           Virtualised execution context. When ctx carries a
     *                      `strategyOverride` field (injected by replayCounterfactual),
     *                      the implementation SHOULD honour it by swapping its
     *                      compute strategy accordingly. This parameter is optional
     *                      on the interface — existing implementations that do not
     *                      inspect it remain fully compatible.
     * @param originalTrace Original trace providing the starting state.
     */
    run(ctx: ReplayContext, originalTrace: Trace): Promise<Trace>;
}
/**
 * Thrown when strict-mode replay detects a non-deterministic deviation
 * that cannot be represented as a diff (e.g. step count mismatch, missing steps).
 *
 * For field-level mismatches, see ReplayResult.diff instead.
 */
export declare class NonDeterministicReplayError extends Error {
    readonly stepIndex: number;
    readonly reason: string;
    constructor(stepIndex: number, reason: string);
}
/**
 * Main replay entry point.
 *
 * 1. Loads the original trace and recorded artifacts via ReplayLoader.
 * 2. Builds a ReplayContext with RecordedClock, RecordedRandom, and LLM cache.
 * 3. Re-executes the agent via ReplayRunner.run().
 * 4. Compares rootHashes and computes a step-level diff if they differ.
 *
 * @param runId   The original run identifier to replay.
 * @param loader  Host-provided loader for trace + artifacts.
 * @param runner  Host-provided runner that wires the agent to virtualised deps.
 * @param opts    Optional overrides: replay mode, step index to replay from.
 */
export declare function replayFrom(runId: string, loader: ReplayLoader, runner: ReplayRunner, opts?: {
    mode?: ReplayMode;
    fromStepIndex?: number;
}): Promise<ReplayResult>;
//# sourceMappingURL=replay.d.ts.map