/**
 * Cross-cycle replay propagation.
 *
 * When a parent cycle spawns a child cycle (via mesh.delegate or compute
 * strategy), the child must inherit a deterministic-replay context that — on
 * replay — reproduces the SAME outputs as the original chain.
 *
 * Design:
 *   ChainedReplayContext extends ReplayContext with chain-ancestry metadata.
 *   propagateContext() derives a child ctx from a parent ctx:
 *     - Clock: cloned at the parent's current cursor position (child picks up
 *       where parent left off — continuous, non-resetting).
 *     - Random: cloned at the parent's current cursor positions.
 *     - LLMCache: composite (withParent) — child looks up parent on miss,
 *       writes disabled in replay mode.
 *   replayChain() drives a multi-cycle chain replay end-to-end.
 *
 * Invariant:
 *   A child cycle replayed with propagateContext(parentCtx, childRunId) produces
 *   the same rootHash as the original child cycle IF AND ONLY IF the parent ctx
 *   has consumed the same number of clock/random values that the original parent
 *   had consumed at the point it spawned the child.
 *
 * @module replay/cross-cycle
 */
import type { ReplayMode, ReplayContext, ReplayLoader, ReplayRunner, ReplayResult } from "./replay.js";
/**
 * Extends ReplayContext with chain-ancestry metadata for cross-cycle replay.
 *
 * Chain invariant:
 *   chainRootRunId is constant across all cycles in the chain.
 *   chainDepth is 0 for the root cycle, 1 for direct children, etc.
 *   parentRunId is undefined only for the root cycle (depth === 0).
 */
export interface ChainedReplayContext extends ReplayContext {
    /**
     * runId of the direct parent cycle.
     * Undefined for the root cycle (chainDepth === 0).
     */
    readonly parentRunId?: string;
    /**
     * Zero-based depth in the spawning chain.
     * Root cycle = 0. Each delegation increments by 1.
     */
    readonly chainDepth: number;
    /**
     * runId of the root (depth-0) cycle in this chain.
     * Same for all cycles in a chain — used as the chain correlation key.
     */
    readonly chainRootRunId: string;
}
/**
 * Summary of all cycles replayed in a chain.
 * Used by callers to verify the full ancestry post-replay.
 */
export interface ChainCorrelation {
    /** runId of the root (depth-0) cycle. */
    rootRunId: string;
    /** Each cycle entry in replay order (root first, deepest child last). */
    chain: {
        runId: string;
        parentRunId?: string;
        depth: number;
        /** rootHash produced by this cycle's replay. */
        rootHash: string;
    }[];
}
/**
 * Result of replaying an entire chain of N cycles.
 *
 * match === true iff ALL cycles in the chain matched their original rootHash.
 * results contains individual ReplayResult per cycle (in chain order).
 * correlation contains the ancestry summary.
 */
export interface ChainReplayResult {
    /** True iff every cycle in the chain is byte-identical to its original. */
    match: boolean;
    /** Per-cycle replay results in chain order (root first). */
    results: ReplayResult[];
    /** Chain correlation summary. */
    correlation: ChainCorrelation;
}
/**
 * Thrown by replayChain when a non-root cycle references a parentRunId that
 * is not present in the runIds list.
 */
export declare class MissingParentRunError extends Error {
    readonly runId: string;
    readonly parentRunId: string;
    constructor(runId: string, parentRunId: string);
}
/**
 * Derive a child ChainedReplayContext from a parent ChainedReplayContext.
 *
 * - clock: cloned at parent's current cursor position (child inherits NEXT timestamps).
 * - random: cloned at parent's current cursor positions (continuous stream).
 * - cache: composite cache — child looks up parent on miss, writes disabled.
 * - chainDepth: parent.chainDepth + 1.
 * - chainRootRunId: inherited unchanged from parent.
 *
 * IMPORTANT: call this AFTER the parent runner has finished executing (so the
 * parent's clock/random cursors reflect all timestamps consumed during the
 * parent cycle). If called mid-parent-execution the cursors will be wrong.
 *
 * @param parentCtx   The finished parent cycle's ChainedReplayContext.
 * @param childRunId  The originalRunId of the child cycle being replayed.
 */
export declare function propagateContext(parentCtx: ChainedReplayContext, childRunId: string): ChainedReplayContext;
/**
 * Replay a chain of N cycles using shared virtualized dependencies.
 *
 * Cycles are replayed in the order provided by `runIds`. Each cycle after the
 * first inherits its context from the preceding cycle via `propagateContext`.
 *
 * The chain structure is: runIds[0] is the root (depth 0), runIds[1] is its
 * direct child (depth 1), etc. This matches linear delegation chains. For
 * tree-shaped chains (one parent spawning multiple children) call replayChain
 * once per branch.
 *
 * @param runIds   Ordered list of original runIds — root first.
 * @param loader   Loader for traces + artifacts. Must be able to load all runIds.
 * @param runner   Runner that executes each cycle with its virtualised context.
 * @param opts     Optional mode override (default: "strict").
 */
export declare function replayChain(runIds: string[], loader: ReplayLoader, runner: ReplayRunner, opts?: {
    mode?: ReplayMode;
}): Promise<ChainReplayResult>;
/**
 * Extended replayFrom that accepts an optional parentCtx.
 *
 * When parentCtx is supplied, the child run inherits clock/random/cache from
 * the parent via propagateContext instead of loading fresh artifacts.
 * This enables replaying a single child cycle in isolation when the parent
 * context is already available (e.g. for targeted debugging of a specific cycle).
 *
 * The loader is still called for the child's originalTrace.
 * loadCacheEntries is skipped — the parent ctx provides the cache.
 */
export declare function replayFromWithParent(runId: string, loader: ReplayLoader, runner: ReplayRunner, opts?: {
    mode?: ReplayMode;
    parentCtx?: ChainedReplayContext;
}): Promise<ReplayResult>;
//# sourceMappingURL=cross-cycle.d.ts.map