/**
 * RestartOrchestrator — single-owner state machine for lifeline self-restart.
 *
 * Multiple initiators may fire concurrently:
 *   - LifelineHealthWatchdog (tick-based)
 *   - ForwardVersionSkewError handler (event-based)
 *   - SIGTERM handler (external, e.g., `instar lifeline restart`)
 *
 * All three route through `requestRestart()`. The orchestrator serializes
 * them: only the first transition from `idle` proceeds; subsequent requests
 * are logged and suppressed.
 *
 * State machine: idle → quiescing → persisting → exiting (terminal)
 *
 * Step 1 (quiesce) halts Telegram polling, replay loops, and the watchdog
 * BEFORE any persist, so the queue snapshot is causally consistent.
 *
 * The `exitFn` is injected so tests can assert the sequence without
 * terminating the test runner. Production injects `process.exit`.
 */
import { DegradationReporter } from '../monitoring/DegradationReporter.js';
export type RestartState = 'idle' | 'quiescing' | 'persisting' | 'exiting';
export interface RestartRequest {
    reason: string;
    bucket: 'watchdog' | 'versionSkew' | 'plannedUpgrade';
    context?: Record<string, unknown>;
}
export interface OrchestratorDeps {
    /** Halt polling, replay interval, watchdog timer; abort in-flight forwards. Returns when drained. */
    quiesce: () => Promise<void>;
    /** Persist all state files atomically. Returns when all writes complete. */
    persistAll: () => Promise<void>;
    /** Called to exit the process. Production: process.exit. Tests: spy. */
    exitFn: (code: number) => void;
    /** Whether this process runs under launchd (true) or dev (false). */
    isSupervised: boolean;
    /**
     * Returns true if a shadow-install update is in progress. The orchestrator
     * will defer the restart by one tick if so, per spec §Shadow-install coordination.
     * Tests can return a fixed value.
     */
    isShadowInstallUpdating?: () => boolean;
    /** Optional DegradationReporter override for tests. */
    reporter?: DegradationReporter;
    /** Maximum ms to wait for persistAll before hard-killing. */
    persistBudgetMs?: number;
    /** Hard-kill timeout — if persist hangs this long, call exitFn(1). */
    hardKillMs?: number;
    /** Defer duration if shadow-install lockfile is present. Default 30000 (one watchdog tick). */
    shadowInstallDeferMs?: number;
}
export declare class RestartOrchestrator {
    private readonly deps;
    private _state;
    private readonly reporter;
    private readonly persistBudgetMs;
    private readonly hardKillMs;
    lastSuppressed: {
        reason: string;
        currentState: RestartState;
    } | null;
    constructor(deps: OrchestratorDeps);
    get state(): RestartState;
    /**
     * Attempt to initiate a restart. Only proceeds if currently idle.
     * Returns a promise that resolves only if the request was suppressed
     * (process didn't exit); otherwise the process exits before resolve.
     */
    requestRestart(req: RestartRequest): Promise<'suppressed' | 'proceeded'>;
    /** Test helper: reset state to idle without exiting. Only safe in tests. */
    _resetForTesting(): void;
}
//# sourceMappingURL=RestartOrchestrator.d.ts.map