/**
 * SandboxHarness — executes a scenario in an isolated environment and
 * emits a rich SandboxSpan into the trace.
 *
 * Two built-in drivers:
 *   - `SubprocessSandboxDriver` — spawn in a local cwd with env vars.
 *     Fast, no dependencies, fine for unit tests and most CI gates.
 *   - `DockerSandboxDriver` — lifted from tangle-router's sandbox path;
 *     shells out to `docker run`. Stronger isolation, slower startup.
 *
 * Consumers implement `SandboxDriver` for custom backends (Firecracker,
 * Cloudflare sandbox product, etc.). The harness doesn't care which.
 */
import type { TraceEmitter } from './trace/emitter';
export interface HarnessConfig {
    /** Setup command (e.g. "pnpm install"). Non-zero exit fails the run. */
    setupCommand?: string;
    /** Run command (e.g. "pnpm build"). */
    runCommand?: string;
    /** Test command (e.g. "pnpm test --run"). Drives the test count + pass count. */
    testCommand?: string;
    /** Absolute cwd for the subprocess driver. Ignored by docker driver. */
    cwd?: string;
    /** Max wall-clock per phase in ms. Default 10 minutes. */
    timeoutMs?: number;
    /**
     * Cap on captured stdout+stderr bytes per phase. A runaway process can
     * otherwise grow the in-memory buffer without bound. Once hit, further
     * output is dropped and `outputTruncated` is set. Default 16 MiB.
     */
    maxOutputBytes?: number;
    /** Image for the docker driver. */
    image?: string;
    /** Extra env vars (validated; shell-escaped). */
    env?: Record<string, string>;
    /** Parser for the test output — maps stdout/stderr/exit code → pass count. */
    testParser?: TestOutputParser;
}
export interface TestOutputParser {
    id: string;
    parse(stdout: string, stderr: string, exitCode: number): {
        testsTotal: number;
        testsPassed: number;
    } | undefined;
}
export interface SandboxResult {
    phase: 'setup' | 'run' | 'test';
    exitCode: number;
    stdout: string;
    stderr: string;
    wallMs: number;
    testsTotal?: number;
    testsPassed?: number;
    /**
     * True when the process was killed because it exceeded `timeoutMs`. A
     * SIGKILLed child can still close with exit code 0; callers MUST treat
     * a timed-out phase as a hard failure regardless of `exitCode`, never
     * as a pass. `undefined`/`false` means the process completed on its own.
     */
    killedByTimeout?: boolean;
    /**
     * True when captured stdout/stderr hit `maxOutputBytes` and further
     * output was dropped. The result is still returned (the process was
     * not killed for this), but downstream parsers see truncated text.
     */
    outputTruncated?: boolean;
}
export interface SandboxDriver {
    id: string;
    exec(phase: SandboxResult['phase'], command: string, config: HarnessConfig): Promise<SandboxResult>;
}
/** Vitest default summary line: "Tests  X passed | Y failed". */
export declare const vitestTestParser: TestOutputParser;
/** Pytest default: "collected N items" + " X passed, Y failed". */
export declare const pytestTestParser: TestOutputParser;
/** Jest: "Tests: X passed, Y total" (and optional failed). */
export declare const jestTestParser: TestOutputParser;
/** Composite parser — tries a list of parsers in order. */
export declare function composeParsers(...parsers: TestOutputParser[]): TestOutputParser;
export interface SubprocessSandboxDriverOptions {
    /**
     * Default cwd for all `exec` calls. Used when the per-call `HarnessConfig`
     * does not set its own `cwd`. Lets callers bind the driver to a working
     * directory once instead of spreading cwd into every harness config —
     * useful when the harness config is constructed far from the call site
     * (e.g. starter-foundry's promoter passes a static HarnessConfig per
     * family taxonomy but needs a per-run composed-scaffold cwd).
     */
    cwd?: string;
    /**
     * Default env merged into every `exec` call's env (per-call `HarnessConfig.env`
     * still wins on key collision). Same ergonomic rationale as `cwd` above.
     */
    env?: Record<string, string>;
}
export declare class SubprocessSandboxDriver implements SandboxDriver {
    id: string;
    private defaultCwd?;
    private defaultEnv?;
    constructor(options?: SubprocessSandboxDriverOptions);
    exec(phase: SandboxResult['phase'], command: string, config: HarnessConfig): Promise<SandboxResult>;
}
export declare class DockerSandboxDriver implements SandboxDriver {
    id: string;
    exec(phase: SandboxResult['phase'], command: string, config: HarnessConfig): Promise<SandboxResult>;
}
export interface SandboxHarnessResult {
    passed: boolean;
    setup?: SandboxResult;
    run?: SandboxResult;
    test?: SandboxResult;
    totalWallMs: number;
    /** Final score — 0 when no tests; otherwise testsPassed/testsTotal. */
    score: number;
}
export declare class SandboxHarness {
    private driver;
    constructor(driver?: SandboxDriver);
    run(config: HarnessConfig, emitter: TraceEmitter): Promise<SandboxHarnessResult>;
}
//# sourceMappingURL=sandbox-harness.d.ts.map