/**
 * QueueScheduler — background mission queue poller for the autonomous
 * daemon profile.
 *
 * Story 6.3 — OpenLife v1.2 Royal Stack.
 *
 * Reads `.openlife/agent-queue.json`, picks the next `pending` mission,
 * acquires a per-mission DistributedLock, marks it `running`, runs an
 * injected MissionExecutor, marks the terminal state, and persists the
 * queue via AtomicWriter. Concurrency capped by maxConcurrent (default 3).
 *
 * Opt-in via OPENLIFE_QUEUE_POLL_INTERVAL_MS env var or explicit
 * `start({pollIntervalMs})`. Off by default — `start --daemon` gateway
 * passes `--enable-queue` to flip it on. Keeps the existing Gateway
 * event-driven path unchanged.
 *
 * Crash semantics: a process restart finds `running` items orphaned (no
 * lock holder, no executing process). `reconcileOrphans()` on start
 * resets those back to `pending` so the next worker picks them up.
 */
import { DistributedLock } from './util/DistributedLock';
export type MissionStatus = 'pending' | 'running' | 'completed' | 'failed';
export interface MissionSpec {
    id: string;
    goal: string;
    source?: 'cli' | 'telegram' | 'webhook' | 'workflow' | 'test';
    enqueuedAt: string;
    startedAt?: string;
    completedAt?: string;
    status: MissionStatus;
    attempts: number;
    lastError?: string;
    context?: Record<string, unknown>;
}
export interface MissionExecutionResult {
    status: 'completed' | 'failed';
    error?: string;
    /**
     * When false, a failed mission is NOT re-queued — it goes straight to
     * terminal 'failed' regardless of attempts remaining. Used for failures
     * that would deterministically recur (governance block, invalid goal).
     * Defaults to true (retry up to maxAttempts).
     */
    retryable?: boolean;
}
export interface MissionExecutor {
    execute(mission: MissionSpec): Promise<MissionExecutionResult>;
}
export interface QueueSchedulerOptions {
    /** Default: <stateDir>/agent-queue.json */
    queueFile?: string;
    /** Default: 10_000 ms (10s). */
    pollIntervalMs?: number;
    /** Default: 3 */
    maxConcurrent?: number;
    /** Injected executor; default is a NoopMissionExecutor for tests. */
    executor?: MissionExecutor;
    /** Default: shared DistributedLock under <stateDir>/locks */
    lock?: DistributedLock;
    /** Default: 5 — past this attempts count, a failed mission stays failed (no retry). */
    maxAttempts?: number;
}
export declare class NoopMissionExecutor implements MissionExecutor {
    execute(): Promise<MissionExecutionResult>;
}
export declare class QueueScheduler {
    private readonly queueFile;
    private readonly pollIntervalMs;
    private readonly maxConcurrent;
    private readonly executor;
    private readonly lock;
    private readonly maxAttempts;
    private timer;
    private running;
    private inFlight;
    private pollPromise;
    private shuttingDown;
    constructor(opts?: QueueSchedulerOptions);
    /** Add a mission to the queue. Atomic. */
    enqueue(spec: Omit<MissionSpec, 'enqueuedAt' | 'status' | 'attempts'>): MissionSpec;
    /** Inspect the queue without modification. */
    list(): MissionSpec[];
    /**
     * Reset any 'running' missions back to 'pending'. Call on boot to
     * recover from a previous crash that left missions mid-flight.
     */
    reconcileOrphans(): number;
    /**
     * Start the poll loop. Performs an immediate reconcileOrphans() then
     * schedules periodic ticks. Idempotent.
     */
    start(): void;
    /**
     * Gracefully stop. Always awaits the current tick to settle (no new
     * picks). With `{ drain: true }`, also waits for in-flight missions to
     * finish, bounded by `timeoutMs` (default 2500ms) — past the deadline,
     * remaining missions keep running on their own promises but the daemon
     * proceeds to exit (they'll be reconciled as orphans on next boot).
     * Idempotent.
     */
    stop(opts?: {
        drain?: boolean;
        timeoutMs?: number;
    }): Promise<void>;
    /** In-flight mission count. Exposed for tests + observability. */
    inFlightCount(): number;
    /** Force one poll iteration (used by tests). */
    tick(): Promise<void>;
    private poll;
    private runMission;
    private read;
    private write;
    private writeItems;
    /** Exposed for tests. */
    _queueFile(): string;
}
