/**
 * Protocol-neutral contract for comparing distributed render plans.
 *
 * The comparator intentionally has no `planHash` field. v1 and v2 use
 * different artifact layouts and hash schemas, so their plan hashes are not
 * expected to match even when they render identical output.
 */
export type PlanParityProtocol = "v1" | "v2";
export interface PlanParityRenderConfig {
    fps: 24 | 30 | 60;
    width: number;
    height: number;
    format: "mp4";
    chunkSize?: number;
    maxParallelChunks?: number;
}
export interface PlanParityDriverInput {
    protocol: PlanParityProtocol;
    projectDir: string;
    outputDir: string;
    renderConfig: PlanParityRenderConfig;
    /**
     * Test-only plan limit. The Lambda-local driver forwards this to v1 as
     * `planDirSizeLimitBytes`; v2 ignores it because it does not materialize a
     * monolithic plan directory.
     */
    planSizeCapBytes?: number;
}
export interface PlanParityChunkArtifact {
    index: number;
    path: string;
    /** Adapter-reported digest, retained for diagnostics. */
    reportedSha256?: string;
}
export interface PlanParityDriverResult {
    protocol: PlanParityProtocol;
    outputPath: string;
    chunks: PlanParityChunkArtifact[];
    transferBytes: {
        downloaded: number;
        uploaded: number;
    };
    /**
     * Maximum materialized bytes observed in the worker scratch directory.
     * This is distinct from S3 storage and from process RSS.
     */
    peakMaterializedBytes: number;
}
export interface PlanParityDriver {
    readonly name: string;
    render(input: PlanParityDriverInput): Promise<PlanParityDriverResult>;
}
export interface PlanParityStreamMetadata {
    video: {
        codecName: string | null;
        width: number;
        height: number;
        pixelFormat: string | null;
        averageFrameRate: string | null;
        realFrameRate: string | null;
        frameCount: number | null;
        colorSpace: string | null;
        colorTransfer: string | null;
        colorPrimaries: string | null;
    } | null;
    audio: {
        codecName: string | null;
        sampleRate: number | null;
        channels: number | null;
        channelLayout: string | null;
    } | null;
    durationSeconds: number;
}
export interface PlanParityMediaMeasurement {
    outputSha256: string;
    outputBytes: number;
    frameSha256: string[];
    pcmAudio: {
        sha256: string;
        /**
         * Interleaved audio frames after canonical decoding to signed 16-bit,
         * 48 kHz, stereo PCM. One sample frame contains two channel samples.
         */
        sampleCount: number;
        bytes: number;
    } | null;
    metadata: PlanParityStreamMetadata;
}
export interface PlanParityChunkMeasurement {
    index: number;
    sha256: string;
    bytes: number;
    reportedSha256?: string;
}
export interface PlanParityMeasurement {
    protocol: PlanParityProtocol;
    driver: string;
    media: PlanParityMediaMeasurement;
    chunks: PlanParityChunkMeasurement[];
    transferBytes: {
        downloaded: number;
        uploaded: number;
        total: number;
    };
    peakMaterializedBytes: number;
}
export interface PlanParityComparisonOptions {
    /** ffprobe duration tolerance. Defaults to 1 ms. */
    durationToleranceSeconds?: number;
    /**
     * Encoded containers can contain non-semantic metadata. Default false:
     * report output digest/size without requiring byte-identical containers.
     */
    requireEncodedOutputEquality?: boolean;
    /** Optional ceiling applied independently to the v2 run. */
    maxV2TransferBytes?: number;
    /** Optional ceiling applied independently to the v2 run. */
    maxV2PeakMaterializedBytes?: number;
}
export interface PlanParityCheck {
    name: string;
    passed: boolean;
    detail: string;
}
export interface PlanParityComparison {
    passed: boolean;
    checks: PlanParityCheck[];
    v1: PlanParityMeasurement;
    v2: PlanParityMeasurement;
}
/**
 * Compare semantic render output plus transport/resource measurements.
 *
 * `outputBytes`, transfer bytes, and working-set bytes are always surfaced.
 * They are not equality gates by default: v2 is expected to change artifact
 * packaging, and encoded containers may carry non-semantic differences.
 */
export declare function comparePlanParityMeasurements(v1: PlanParityMeasurement, v2: PlanParityMeasurement, options?: PlanParityComparisonOptions): PlanParityComparison;
//# sourceMappingURL=plan-parity-contract.d.ts.map