/**
 * Distributed-render path for the regression harness.
 *
 * The regression harness has two modes:
 *
 *   - `in-process` (default) — calls `executeRenderJob`, the same path the
 *     `hyperframes render` CLI takes. This is what produced every existing
 *     `tests/<name>/output/output.mp4` golden baseline.
 *
 *   - `distributed-simulated` — calls `plan()` → `renderChunk()` per chunk
 *     → `assemble()` from `@hyperframes/producer/distributed`. No Temporal
 *     or Lambda involvement: the controller and chunk worker are both this
 *     process, but they go through the same artifact (planDir + frozen
 *     `meta/encoder.json` + per-chunk concat-copy) that a real fan-out
 *     would.
 *
 * Both modes share the per-fixture `minPsnr` threshold — distributed must
 * pass the same quality bar the in-process renderer passes against the
 * same frozen baseline. A separate {@link DISTRIBUTED_SIMULATED_MIN_PSNR_DB}
 * pathology floor catches the case where a fixture authored a permissive
 * threshold and distributed regresses to fully-black output. The 50 dB
 * "distributed vs in-process" contract is a per-render comparison
 * (fresh in-process vs fresh distributed); against the frozen baseline
 * file it's unreachable for either mode due to shared encoder/JPEG-
 * capture jitter, so the harness can't use it as a per-test gate.
 *
 * Not every fixture can run in distributed-simulated mode. Distributed mode
 * refuses HDR mp4, NTSC framerates, and non-{24,30,60} fps at plan time.
 * Fixtures that don't meet the constraints are skipped — the harness logs
 * the reason and the fixture is treated as "passed (skipped)" in
 * distributed-simulated mode.
 */
import type { Fps } from "@hyperframes/core";
import { type DistributedFormat } from "./services/distributed/shared.js";
/**
 * Three-mode contract that backs `--mode=<value>` on the regression
 * harness CLI:
 *
 *   - `in-process` — `executeRenderJob`, the same path the CLI takes.
 *   - `distributed-simulated` — `plan` → `renderChunk` × N → `assemble`
 *     in-process. No adapter (no Temporal, no Lambda).
 *   - `lambda-local` — drives the OSS `@hyperframes/aws-lambda` handler
 *     dispatch through a filesystem-backed fake S3, so every event
 *     shape SFN sends in production also lands here. Catches regressions
 *     in event JSON / S3 path conventions without paying for a real AWS
 *     round-trip.
 */
export type HarnessMode = "in-process" | "distributed-simulated" | "lambda-local";
/**
 * Absolute pathology floor for `--mode=distributed-simulated` — catches
 * a chunk that renders fully-black against a fixture authored with a
 * permissive `minPsnr`. Non-pathological drift is caught by the fixture's
 * own threshold; both modes share the same encoder/JPEG-capture jitter
 * floor against the frozen baseline file, so the 50 dB distributed-vs-
 * in-process contract value is unreachable for either mode and isn't a
 * useful per-test gate.
 */
export declare const DISTRIBUTED_SIMULATED_MIN_PSNR_DB = 10;
/** Result of {@link checkDistributedSupport}. */
export type DistributedSupportResult = {
    supported: true;
} | {
    supported: false;
    reason: string;
};
/**
 * Decide whether a fixture's `renderConfig` is one the distributed pipeline
 * can actually run. Two hard gates:
 *
 *   - fps must be `{ num: 24|30|60, den: 1 }`. `DistributedRenderConfig.fps`
 *     accepts only the three integer values, and rationals like
 *     `{ num: 30000, den: 1001 }` (NTSC) trip the type system at the call
 *     site. We surface this gate in code rather than only in TS so the
 *     harness can skip the fixture cleanly instead of throwing.
 *   - hdr must not be `true`. Distributed mode is SDR-only at v1.
 *
 * Callers that want the structured reason can read it off the returned
 * `reason` field; the message is intended to be log-friendly.
 */
export declare function checkDistributedSupport(renderConfig: {
    fps: Fps;
    format?: DistributedFormat;
    hdr?: boolean;
}): DistributedSupportResult;
/**
 * Inputs for {@link runDistributedSimulatedRender}. The harness has already
 * prepared `projectDir` (a working copy of the fixture's `src/` directory)
 * and `tempRoot` (where the harness writes its scratch artifacts).
 */
export interface RunDistributedSimulatedInput {
    /** Working copy of the fixture's `src/` — contains `index.html`. */
    projectDir: string;
    /** Scratch root for plan + chunks; must be a directory the harness owns. */
    tempRoot: string;
    /** Where to write the assembled final mp4 / mov / png-sequence directory. */
    renderedOutputPath: string;
    /** From the fixture's renderConfig — must pass `checkDistributedSupport`. */
    fps: 24 | 30 | 60;
    format: DistributedFormat;
    /**
     * Codec for `format: "mp4"`. Defaults to `"h264"`; pass `"h265"` to
     * exercise the libx265 closed-GOP path. Ignored for non-mp4 formats —
     * `plan()` throws if codec is passed with a non-mp4 format.
     */
    codec?: "h264" | "h265";
    /** Optional chunkSize override; defaults to the plan's 240. */
    chunkSize?: number;
    /** Optional maxParallelChunks override; defaults to the plan's 16. */
    maxParallelChunks?: number;
    /** Forwarded to `plan()` and re-applied by `renderChunk()` at boot. */
    variables?: Record<string, unknown>;
}
/**
 * Run the distributed pipeline against a single fixture as if a fan-out
 * adapter were driving it. The three activities run serially in this
 * process — there is no Temporal, no Lambda, no S3 — so the planDir,
 * chunk outputs, and assembled output all live under `tempRoot`.
 *
 * Width and height are required by `DistributedRenderConfig` for cross-call
 * sanity but are not consulted at render time — `plan()` reads the
 * composition's `data-width` / `data-height` attributes and overrides
 * whatever the config carried. The harness passes a dummy 1920×1080 here
 * for that reason; if the contract ever changes, the fixture's authored
 * dimensions will flow through `PlanResult` and we can switch to using
 * those instead.
 */
export declare function runDistributedSimulatedRender(input: RunDistributedSimulatedInput): Promise<void>;
/**
 * Pick the PSNR threshold for a fixture given the harness mode. Both modes
 * share the fixture's authored `minPsnr` — distributed must clear the same
 * quality bar in-process clears against the same frozen baseline.
 * Distributed-simulated additionally lifts the threshold to
 * {@link DISTRIBUTED_SIMULATED_MIN_PSNR_DB} for fixtures with a permissive
 * authored threshold; that absolute floor catches fully-black-output
 * regressions independent of fixture tolerance.
 */
export declare function resolveMinPsnrForMode(mode: HarnessMode, fixtureMinPsnr: number): number;
/**
 * Parse `--mode=<value>` from a single CLI token. Returns the parsed mode
 * when the token matches the expected shape, `null` otherwise so the
 * caller can pass the token through to the next handler. Throws on a
 * known prefix with a bad value (`--mode=foo`) — surfacing a typo at
 * parse time is cheaper than discovering at render time.
 */
export declare function parseHarnessModeFlag(token: string): HarnessMode | null;
//# sourceMappingURL=regression-harness-distributed.d.ts.map