/** Live inputs sampled once per tick. All timestamps are epoch ms. */
export interface SleepInput {
    now: number;
    /** Active Claude/codex sessions. Any > 0 ⇒ never sleep. */
    runningSessions: number;
    /** Last inbound user/agent message timestamp, or null if never. */
    lastInboundAt: number | null;
    /** Last any-activity timestamp (session output, outbound, tick work), or null. */
    lastActivityAt: number | null;
    /** This machine currently holds the multi-machine serving lease. */
    holdsLease: boolean;
    /** Multi-machine lease coordination is active at all (single-machine ⇒ false). */
    leaseActive: boolean;
    /** Any in-flight forward, recovery, or queued/undelivered message. */
    inflightWork: boolean;
    /** Next scheduled cron job fire time (epoch ms), or null if none scheduled. */
    nextScheduledJobAt: number | null;
}
export interface SleepThresholds {
    /** Time since last activity to count as "idle" at all. */
    idleGraceMs: number;
    /** Continuous idle time before deep-idle ⇒ a sleep candidate. */
    deepIdleMs: number;
    /** Don't sleep if a scheduled job fires within this lead window. */
    wakeLeadMs: number;
}
export type SleepDecision = 'awake' | 'idle-shallow' | 'keep-awake' | 'would-sleep';
export interface SleepVerdict {
    decision: SleepDecision;
    reason: string;
    /** Idle duration in ms at evaluation time (Infinity if never any signal). */
    idleForMs: number;
}
export declare const DEFAULT_SLEEP_THRESHOLDS: SleepThresholds;
/**
 * Decide whether the agent may hard-sleep. Pure; no I/O. The guards are ordered
 * so the returned reason names the FIRST blocking condition — easiest to read in
 * an audit trail.
 */
export declare function evaluateSleep(input: SleepInput, t: SleepThresholds): SleepVerdict;
export interface SleepAuditEntry {
    ts: string;
    decision: SleepDecision;
    reason: string;
    idleForMs: number;
    dryRun: boolean;
}
export type SleepAuditSink = (entry: SleepAuditEntry) => void;
/**
 * Append-only JSONL audit sink at `logs/agent-sleep-events.jsonl`. Only writes on
 * a decision CHANGE (transition), never every tick — the same low-noise pattern as
 * the reaper audit, so a deep-idle agent doesn't spam the log every cadence.
 */
export declare function sleepAuditSink(stateDir: string): SleepAuditSink;
/**
 * Live-mode `requestSleep` impl (Stage B mechanism): writes
 * `state/sleep-requested.json` for the ServerSupervisor to honor (it stops the
 * server). Only ever called by the SleepController in live mode (enabled &&
 * !dryRun), so a dark / dry-run agent never writes it. TTL-stamped so a stale
 * request can't sleep a server long after it was queued.
 */
export declare function sleepRequestWriter(stateDir: string, ttlMs?: number): (verdict: SleepVerdict) => void;
export interface SleepControllerOptions {
    enabled: boolean;
    /** When true (default), evaluate + audit but NEVER write the sleep-request flag. */
    dryRun: boolean;
    thresholds?: Partial<SleepThresholds>;
}
export interface SleepControllerDeps {
    sample: () => SleepInput;
    audit?: SleepAuditSink;
    /** Live-mode only (dryRun=false): request the supervisor to sleep the server. */
    requestSleep?: (verdict: SleepVerdict) => void;
}
/**
 * Ticks the sleep decision on a cadence. Records every TRANSITION to the audit
 * sink; in live mode (dryRun=false) calls `requestSleep` on a fresh would-sleep.
 * In dry-run it is pure observability — the foundation slice ships this way.
 */
export declare class SleepController {
    private readonly deps;
    private readonly opts;
    private readonly thresholds;
    private lastDecision;
    private lastVerdict;
    private sleepRequested;
    private timer;
    constructor(deps: SleepControllerDeps, opts: SleepControllerOptions & {
        tickIntervalMs?: number;
    });
    /** Begin ticking on the configured cadence. No-op when not enabled (the audit
     *  still works in dry-run-but-enabled; a fully disabled controller never ticks). */
    start(): void;
    stop(): void;
    /** Evaluate once. Returns the verdict (also used by tests + a status route). */
    tick(): SleepVerdict;
    /** Current latched state — for a status route / tests. */
    get state(): {
        lastDecision: SleepDecision | null;
        sleepRequested: boolean;
    };
    /** Read-only status for GET /sleep. Ticks once so the verdict is fresh. */
    snapshot(): {
        enabled: boolean;
        dryRun: boolean;
        thresholds: SleepThresholds;
        verdict: SleepVerdict;
        sleepRequested: boolean;
    };
}
//# sourceMappingURL=SleepController.d.ts.map