/**
 * SandboxPool — bounded checkout/release pool for mutation slots.
 *
 * The composite-mutator's `code` channel needs an isolated workspace per
 * mutation attempt: a git worktree, a sandbox container, a tmpdir clone —
 * whatever the consumer's runtime is. Without a pool, every consumer
 * re-implements the same machinery (mint N slots, check one out per
 * mutation, reset before reuse, drain at the end, track utilisation for
 * the cost ledger). This primitive ships that machinery so consumers
 * supply only a `SlotFactory`.
 *
 * Generic over a slot resource `T` so the same pool serves git worktrees
 * (T = path), Tangle sandboxes (T = SandboxBox), or anything else with
 * the create/reset/destroy lifecycle.
 *
 * Concurrency: FIFO via the shared `Mutex` primitive. Each `checkout()`
 * either takes an idle slot or queues until one is released. Lifecycle
 * is single-process — multi-process pools need external coordination
 * (file locks, etc.) and are deliberately out of scope.
 */
export interface PoolSlot<T> {
    /** Stable id assigned at slot creation. Use for telemetry / lineage. */
    readonly id: string;
    /** Consumer-defined resource. */
    readonly resource: T;
}
export interface SlotFactory<T> {
    /** Build a new slot. Called lazily as the pool grows up to `size`. */
    create(slotId: string): Promise<T>;
    /**
     * Reset a slot to a clean state before reuse. Called BEFORE every
     * checkout returns it (including the first — so the factory's
     * `create` can leave the slot dirty and let `reset` normalise).
     * Optional; default is a no-op.
     */
    reset?(slot: PoolSlot<T>): Promise<void>;
    /** Tear the slot down. Called by `drain()`. */
    destroy(slot: PoolSlot<T>): Promise<void>;
}
export interface SandboxPool<T> {
    /**
     * Take a slot. If all slots are busy, the promise resolves when one
     * is released. Always pair with the returned `release` (or wrap with
     * `withSlot`).
     */
    checkout(): Promise<{
        slot: PoolSlot<T>;
        release: () => void;
    }>;
    /**
     * Run `fn` with a checked-out slot, releasing on completion or throw.
     * The convenience wrapper most callers should use.
     */
    withSlot<R>(fn: (slot: PoolSlot<T>) => Promise<R>): Promise<R>;
    /** Destroy every slot. Idempotent. */
    drain(): Promise<void>;
    /** How many slots have been minted (≤ `size`). */
    poolSize(): number;
    /** How many checkouts are currently outstanding. */
    activeCheckouts(): number;
    /** Snapshot of busy/total durations for the cost ledger. */
    utilization(): {
        busyMs: number;
        totalMs: number;
        checkouts: number;
    };
}
export interface CreateSandboxPoolOpts<T> {
    /** Maximum concurrent slots. Slots are minted on first need, not eagerly. */
    size: number;
    factory: SlotFactory<T>;
}
export declare function createSandboxPool<T>(opts: CreateSandboxPoolOpts<T>): SandboxPool<T>;
//# sourceMappingURL=sandbox-pool.d.ts.map