/** * 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//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=` 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; } /** * 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; /** * 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=` 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