import type { AutomaticAnalysisHooks } from "./automatic-analysis-completion.js"; import { type CuaActorLabHooks, type CuaActorLabResult } from "./cua-actor-lab.js"; import { type ScriptedBrowserLabHooks, type ScriptedBrowserLabResult } from "./scripted-browser-lab.js"; import { type TerminalProductLabHooks, type TerminalProductLabResult } from "./e2b-terminal-lab.js"; import { type SharedWorldLabHooks, type SharedWorldLabResult } from "./shared-world-lab.js"; import { type ConcurrentSharedWorldLabResult } from "./concurrent-shared-world-lab.js"; import { type OssLabResult } from "./oss-lab.js"; import { type OssMetaLabResult } from "./oss-meta-lab.js"; import { type RunLabProvenance } from "./run-status.js"; import type { ObserverResult } from "./observer.js"; import { type RunResult, type RunScorerProvenance } from "./run.js"; import { type LabConfig } from "./lab-config.js"; export type LabBackend = "synthetic" | "smoke" | "meta" | "cua" | "scripted" | "terminal" | "shared-world" | "concurrent-shared-world"; /** Runtime overrides from CLI flags. Each wins over the config when provided. */ export interface RunLabOptions { automaticAnalysis?: AutomaticAnalysisHooks; cwd: string; runId?: string; /** Which manifest this run came from (#455): threaded to the backend so the run's own * status record and bundle can say which lab produced it. Absent for library callers who * hand a LabConfig directly — the run is then honestly lab-less rather than guessed. */ lab?: RunLabProvenance; dryRun?: boolean; open?: boolean; /** Lane override: synthetic sims, smoke repo limit, or meta desktop count. */ count?: number; /** CUA fan-out only: create a new run for failed/selected lanes from a prior run. */ rerun?: { sourceRunId: string; laneIds?: string[]; }; repos?: string[]; keep?: boolean; redactRepos?: boolean; codexAppServer?: boolean; /** Meta watch-follow plumbing. */ completionTimeoutMs?: number; onObserverReady?: (observer: ObserverResult & { ok: true; }) => Promise | void; /** Computer-use route hooks: subject provisioning (library callers) + test DI seams. */ cuaHooks?: CuaActorLabHooks; /** Scripted-browser route hooks: browser injection + test DI seams (mirror of cuaHooks). */ scriptedHooks?: ScriptedBrowserLabHooks; /** Terminal-product route hooks: sandbox/runtime-auth DI seams (mirror of cuaHooks). */ terminalHooks?: TerminalProductLabHooks; /** Shared-world route hooks: ONE-sandbox / runSession / checkpoint DI seams (mirror of cuaHooks). */ sharedWorldHooks?: SharedWorldLabHooks; /** * CONFIG-DECLARED scorer provenance (#316), forwarded alongside whichever hooks bag carries the * loaded scorer. Its presence is the "declared" marker the terminal route reads to flip a * status:"fail" verdict; the browser routes stamp it as evidence (they already flip). Core-computed * (path + digest), never adopter-supplied; absent for library callers. */ scorerProvenance?: RunScorerProvenance; } export type LabOutcome = { backend: "synthetic"; result: RunResult; } | { backend: "smoke"; result: OssLabResult; } | { backend: "meta"; result: OssMetaLabResult; } | { backend: "cua"; result: CuaActorLabResult; } | { backend: "scripted"; result: ScriptedBrowserLabResult; } | { backend: "terminal"; result: TerminalProductLabResult; } | { backend: "shared-world"; result: SharedWorldLabResult; } | { backend: "concurrent-shared-world"; result: ConcurrentSharedWorldLabResult; }; /** * Route a lab config to its execution backend from its declared composition. * subject.source x execution.target are orthogonal primitives; where both axes collide * (clone x e2b-desktop hosts both the meta bootstrap AND the computer-use serve path) the * actor LANE disambiguates — via routesToComputerUse, the single shared predicate. */ export declare function selectLabBackend(config: LabConfig): LabBackend; /** Resolve dry-run: explicit override wins, else the scenario mode, else the given fallback. */ export declare function resolveLabDryRun(config: LabConfig, override: boolean | undefined, fallback: boolean | undefined): boolean | undefined; /** * The one seam every lab backend is dispatched through. The body runs inside a status scope so a * backend that fails closed and RETURNS an error result — 18 such exits across the backends — can * never leave its liveness record ticking as though the run were still going. See * `withRunStatusScope`. */ export declare function runLab(config: LabConfig, options: RunLabOptions): Promise;