/**
 * GuardLatchStore — pool-visible kill-switch + marker latches for guarded
 * autonomous authorities (green-pr-automerge-enforcement R9/R7).
 *
 * Two independent gate families decide whether the GreenPrAutoMerger may act:
 *   - `rollback`        — set by POST /green-pr-automerge/rollback, cleared by
 *                         POST /green-pr-automerge/enable (PIN-gated re-arm)
 *   - `emergency-pause` — set by the MessageSentinel emergency stop, cleared by
 *                         its own resume path
 * BOTH must be open for a merge. A third family, `pool-armed`, is a posture
 * MARKER (not a gate): its presence makes a lease holder whose local config is
 * disabled grade `diverged-from-default` instead of healthy dark-default.
 *
 * Why a store and not a flag (round-2 finding): execution follows the lease, so
 * a machine-LOCAL latch would silently resurrect the watcher on a lease move.
 * Each transition is therefore written BOTH to a durable local file (authoritative
 * for this machine's own writes, present regardless of the journal feature flag)
 * AND to the replicated `guard-latch` coherence-journal kind, so a peer that
 * takes the lease reads the same disabled state.
 *
 * ABSORBING disable (round-4): a `rollback` set always wins ordering conflicts
 * regardless of epoch — "a stale-epoch standby's STOP can never be out-ordered
 * by an earlier /enable from a higher epoch." This is achieved structurally, not
 * by clock comparison: every `set` mints a FRESH globally-unique latchId
 * (`<machineId>:<seq>`), and `/enable` clears ONLY the specific latchId(s) it
 * names. A new STOP therefore introduces a latchId no prior enable could have
 * named, so it can never be pre-cleared. Ordering within a single latchId is by
 * (epoch, seq), NEVER wall-clock.
 *
 * arrive-disabled-on-unreadable (round-3): if the merged peer view cannot be
 * read, `isMergeAllowed()` returns false — absence of evidence is not "armed."
 */
import type { CoherenceJournal, GuardLatchAction } from '../core/CoherenceJournal.js';
/** A single latch transition (own or peer), as merged for resolution. */
export interface GuardLatchEntry {
    machine: string;
    latchKind: string;
    latchId: string;
    action: GuardLatchAction;
    epoch: number;
    seq: number;
    reason?: string;
    ts?: string;
}
export type MergeGateReason = 'allowed' | 'rollback' | 'emergency-pause' | 'unreadable-peers';
export interface MergeGateVerdict {
    allowed: boolean;
    reason: MergeGateReason;
    /** Active latch ids per blocking family (for the status surface / audit). */
    activeLatchIds: Record<string, string[]>;
}
/** Latch family names. */
export declare const ROLLBACK_FAMILY = "rollback";
export declare const EMERGENCY_PAUSE_FAMILY = "emergency-pause";
export declare const POOL_ARMED_FAMILY = "pool-armed";
/** The fixed, pool-shared latchId for the single pool-armed marker. */
export declare const POOL_MARKER_ID = "pool";
export interface GuardLatchStoreConfig {
    /** Absolute path to the agent's `.instar/` directory. */
    stateDir: string;
    /** Stable id for THIS machine. */
    machineId: string;
    /** Replication writer (optional — single-machine installs pass none). */
    journal?: Pick<CoherenceJournal, 'emitGuardLatch'>;
    /** Current lease epoch (monotonic; stamped on every transition). */
    leaseEpoch: () => number;
    /**
     * Merged peer view: the latest guard-latch transition per (machine, kind, id)
     * from replicated peer streams. Throwing signals UNREADABLE → arrive-disabled.
     * Single-machine installs pass `() => []`.
     */
    readPeerEntries?: () => GuardLatchEntry[];
    now?: () => Date;
    logger?: (msg: string) => void;
}
export declare class GuardLatchStore {
    private readonly stateDir;
    private readonly machineId;
    private readonly journal?;
    private readonly leaseEpoch;
    private readonly readPeerEntries;
    private readonly now;
    private readonly logger?;
    private local;
    constructor(cfg: GuardLatchStoreConfig);
    /**
     * Set (mint) a latch in `latchKind`. Returns the fresh, globally-unique
     * latchId. Use for the absorbing families (rollback, emergency-pause): every
     * call introduces a NEW latchId that no prior clear could have named.
     */
    set(latchKind: string, reason?: string): string;
    /** Clear the SPECIFIC named latchId(s) in `latchKind` (the /enable semantics). */
    clear(latchKind: string, latchIds: string[], reason?: string): void;
    /** Set/clear a FIXED-id marker (pool-armed): last-(epoch,seq)-wins, not absorbing. */
    setMarker(latchKind: string, latchId: string, on: boolean, reason?: string): void;
    private record;
    /**
     * Resolve a family to the winning action per latchId across own + peers.
     * Within one latchId, the highest (epoch, seq) transition wins. Distinct
     * latchIds are independent — that is what makes `set` absorbing for the
     * fresh-id families.
     * @throws if the peer view is unreadable (caller maps to arrive-disabled).
     */
    resolveFamily(latchKind: string): Map<string, GuardLatchEntry>;
    /** Active (currently-set) latch ids in a family. */
    activeLatchIds(latchKind: string): string[];
    /**
     * The dual-latch gate (R9): both rollback and emergency-pause must be open.
     * An unreadable peer view arrives DISABLED (absence of evidence ≠ armed).
     */
    isMergeAllowed(): MergeGateVerdict;
    markPoolArmed(): void;
    /** PIN-gated disarm: superseding entry, grades back to healthy dark-default. */
    markPoolDisarmed(): void;
    /**
     * Is this pool deliberately armed (per the replicated marker)? Used by guard
     * posture to grade a local-disabled + pool-armed machine `diverged-from-default`.
     * Unreadable peers → false (we never INVENT a divergence alarm on a read error).
     */
    isPoolArmed(): boolean;
    /** Snapshot for the status route + posture grading. Never throws. */
    snapshot(): {
        rollback: string[];
        emergencyPause: string[];
        poolArmed: boolean;
        mergeAllowed: boolean;
        reason: MergeGateReason;
    };
    private filePath;
    private load;
    private persist;
    private log;
}
//# sourceMappingURL=GuardLatchStore.d.ts.map