/**
 * OutstandingPromptTracker — anti-ping-pong invariant for the mentor live loop.
 *
 * Spec: MENTOR-LIVE-READINESS §Fix 2b "Implementation surface" item 4 + Justin's original
 * concern (the rebuilt-slow ping-pong: a 15-min mentor tick + a Codey reply that takes
 * 16+ min = naive next-tick re-sends while the prior is in flight → loop).
 *
 * Justin's user-fidelity correction made this THE real cadence gate (Fix 1 idle-probe
 * was removed; users don't probe). The mentor refuses to send a new prompt while any
 * prior prompt is outstanding within `replyTimeoutMs`. On timeout expiry without a reply
 * → degradation event + Attention entry (silent reply-loss is observable).
 *
 * Pure in-memory + a small persistence shim so a server restart doesn't lose the "I'm
 * waiting on a reply" state (would otherwise re-send + double-prompt Codey).
 *
 * Keyed per-mentee. The same `corr` round-trips: mark on send, clear on matching reply.
 */
export interface OutstandingPromptTrackerOptions {
    /** Absolute path to the JSON file backing the tracker (per-mentee state). */
    filePath: string;
    /** A reply that doesn't arrive within this window is treated as orphaned. */
    replyTimeoutMs?: number;
    /** Injected for testability. */
    now?: () => number;
}
export type CheckResult = {
    ok: true;
} | {
    ok: false;
    reason: 'prior-prompt-in-flight';
    outstandingCorr: string;
    sentAt: number;
};
export declare class OutstandingPromptTracker {
    private readonly filePath;
    private readonly replyTimeoutMs;
    private readonly now;
    private entries;
    /** Per-(reason,day) dedup for the orphan-degradation notification. */
    private orphanedNotifiedFor;
    constructor(opts: OutstandingPromptTrackerOptions);
    /**
     * Returns `{ok: true}` if the mentor can send a new prompt to this mentee; otherwise
     * `{ok: false, reason: 'prior-prompt-in-flight'}` (the tick must refuse the send). An
     * EXPIRED outstanding (past replyTimeoutMs) is automatically swept here and does NOT
     * block — the caller can also call sweepExpired() explicitly to surface orphans.
     */
    canSendTo(mentee: string): CheckResult;
    /** Record that a prompt with this `corr` was sent to this mentee at now(). */
    markSent(corr: string, mentee: string): void;
    /**
     * Clear an outstanding prompt by `corr` (called when the matching reply arrives).
     * Returns true if an outstanding entry existed (legitimate reply); false if not
     * (a reply with no outstanding match — possibly a late reply after orphan-sweep,
     * or a spurious reply; the caller may want to log this).
     */
    clearByCorr(corr: string): boolean;
    /**
     * Find + remove orphans (sentAt + replyTimeoutMs < now). Returns the list. Caller
     * decides whether to fire DegradationReporter / Attention. The dedup field stays
     * across calls so the same orphan-episode doesn't re-fire repeatedly.
     */
    sweepExpired(): Array<{
        corr: string;
        mentee: string;
        sentAt: number;
        ageMs: number;
    }>;
    /** Idempotent: once an orphan-notify has fired for a (corr), don't re-fire. */
    recordOrphanNotified(corr: string): boolean;
    /** Test helper. */
    size(): number;
    /** Test helper. */
    list(): Array<{
        corr: string;
        mentee: string;
        sentAt: number;
    }>;
    private load;
    private persist;
}
//# sourceMappingURL=OutstandingPromptTracker.d.ts.map