/**
 * SessionLivenessOracle — the single, tri-state answer to "is this tmux session
 * alive?" for every autonomous session killer.
 *
 * Spec: docs/specs/unified-session-lifecycle-robustness.md §P1.
 *
 * The 2026-05-27 incident: the boot purge probed `tmux has-session` with a 1s
 * timeout inside a bare try/catch, so a *timeout* (tmux busy at boot) threw the
 * same error as "session gone" — and live sessions were mass-purged. The oracle
 * is the structural fix:
 *
 *   - `dead` is returned ONLY on a definitive negative: the tmux server is
 *     reachable (a `list-sessions` succeeded) AND the session's exact canonical
 *     id is absent from that list. Never inferred from a prefix match, an
 *     unrecognized error string, or an exit code.
 *   - Anything else — timeout, server-unreachable, ENOENT/EPIPE, unknown failure
 *     — is `indeterminate`. The hard rule (enforced by every caller) is: NEVER
 *     transition a session to killed on `indeterminate`. Indeterminate means
 *     "ask again next tick," never "reap now."
 *
 * Performance contract (§P1): liveness for the whole set is resolved from ONE
 * `tmux list-sessions` (no per-session fork), cached for a short TTL so multiple
 * killers in one tick never re-probe. The list call is async (never
 * execFileSync), retried once with backoff, and bounded by a total wall-clock
 * cap so a slow tmux can never block boot — unresolved sessions are left
 * `indeterminate` and finished by the first monitoring tick.
 */
export type Liveness = 'alive' | 'dead' | 'indeterminate';
export interface LivenessResult {
    liveness: Liveness;
    /** Diagnostic reason — for the reap-log / debugging, never user-facing prose. */
    reason: string;
}
export interface SessionLivenessOracleConfig {
    /** Per-attempt timeout for the `list-sessions` probe (ms). Must be > a floor. */
    probeTimeoutMs: number;
    /** Retries (in addition to the first attempt) on a transient/unreachable result. */
    probeRetries: number;
    /** Backoff between retries (ms). */
    probeBackoffMs: number;
    /** Total wall-clock cap across all attempts (ms). On cap → indeterminate. */
    bootCapMs: number;
    /** How long a successful list snapshot is trusted before a refresh (ms). */
    cacheTtlMs: number;
}
export declare const DEFAULT_LIVENESS_CONFIG: SessionLivenessOracleConfig;
/** Floors enforced at startup validation (a 0ms timeout would re-create the death spiral). */
export declare const LIVENESS_FLOORS: {
    readonly minProbeTimeoutMs: 1000;
    readonly minBootCapMs: 2000;
};
type ExecFn = (file: string, args: string[], opts: {
    timeout: number;
}) => Promise<{
    stdout: string;
    stderr: string;
}>;
export interface SessionLivenessOracleDeps {
    tmuxPath: string;
    /** promisified execFile — injected for testability. */
    exec: ExecFn;
    now?: () => number;
    /** Optional sink for diagnostics. */
    log?: (msg: string) => void;
}
/**
 * Validate a liveness config against the floors. Returns an array of human-readable
 * problems (empty = valid). Called at startup so a nonsensical knob is rejected
 * loudly rather than silently re-creating the boot-purge bug.
 */
export declare function validateLivenessConfig(cfg: Partial<SessionLivenessOracleConfig>): string[];
export declare class SessionLivenessOracle {
    private readonly cfg;
    private readonly deps;
    private readonly now;
    private snapshot;
    private snapshotAt;
    /** Coalesce concurrent refreshes so N killers in one tick share one tmux call. */
    private inflight;
    constructor(deps: SessionLivenessOracleDeps, cfg?: Partial<SessionLivenessOracleConfig>);
    /**
     * Liveness for a single session. Uses the cached list snapshot when fresh,
     * otherwise refreshes (one shared tmux call). Never throws.
     */
    probe(tmuxSession: string): Promise<LivenessResult>;
    /**
     * Liveness for many sessions resolved from ONE snapshot. This is the boot-purge
     * path: one `tmux list-sessions` for the whole tracked set, no per-session fork.
     */
    probeAll(tmuxSessions: string[]): Promise<Map<string, LivenessResult>>;
    /** Force the next probe to re-read tmux (used by tests / after a known change). */
    invalidate(): void;
    private classify;
    private ensureSnapshot;
    /**
     * One `tmux list-sessions`, retried up to probeRetries on a transient/unreachable
     * result, bounded by bootCapMs total. Returns an authoritative snapshot only when
     * tmux answered definitively (success, or a clean "no server running").
     */
    private refresh;
    private listOnce;
}
export {};
//# sourceMappingURL=SessionLivenessOracle.d.ts.map