/**
 * CollaborationRedriveEngine — proactively re-engage a COUNTERPART that has
 * gone silent on an unfinished cross-agent objective.
 *
 * Spec: docs/specs/collaboration-redrive-on-counterpart-silence.md (v3,
 * Justin-approved 2026-05-28). Fills the verified residual gap in the shipped
 * Threadline Conversation Keystone: loop-safety + continuity + done-detection
 * exist, but everything is inbound-reactive or operator-facing — nothing
 * proactively pokes the counterpart when they go silent. This engine sends a
 * bounded number of follow-up nudges, then escalates to the operator and
 * STOPS.
 *
 * Termination guarantee (load-bearing, the round-1 adversarial fix):
 *  - `redriveCount` is a DURABLE, MONOTONIC, REPLY-INDEPENDENT per-commitment
 *    counter on the Commitment record. A counterpart reply updates
 *    `lastReplyAt` (silence clock) but NEVER touches `redriveCount`. So even
 *    when two agents both run this engine pointed at each other, each side
 *    fires ≤ maxRedrives nudges on a given objective and then is permanently
 *    re-drive-ineligible. Multi-objective amplification is capped by the
 *    per-peer 24h cap and the engine-wide daily fuse.
 *  - The novelty guard is a DECORATIVE tiebreaker, not a bound. The durable
 *    cap is the only termination guarantee.
 *
 * The engine runs its OWN low-frequency sweep — it does NOT piggyback the
 * PromiseBeacon tick (the beacon only schedules `beaconEnabled && pending`
 * commitments, and most threadline-reply commitments are not beacon-enabled).
 *
 * Ships OFF by default (`monitoring.collaborationRedrive.enabled: false`).
 */
import type { CommitmentTracker, Commitment } from './CommitmentTracker.js';
import type { CompletionEvaluator } from '../core/CompletionEvaluator.js';
import type { ThreadlineClient } from '../threadline/client/ThreadlineClient.js';
import type { CollaborationSurfacer } from '../threadline/CollaborationSurfacer.js';
export interface CollaborationRedriveConfig {
    enabled: boolean;
    sweepIntervalMs: number;
    silenceThresholdMs: number;
    maxRedrives: number;
    perPeerDailyCap: number;
    maxRedriveSendsPerDay: number;
    maxRedrivesPerTick: number;
    trustFloor: string;
    dedupeJaccard: number;
    /**
     * Dogfood fix (2026-05-28): an unresolvable peer name is a STABLE condition
     * (the name is missing from known-agents.json — it doesn't fix itself on
     * the next sweep). Without a cooldown, the engine escalated to the
     * Attention queue every few sweeps for every such peer → notification
     * flood on Echo, observed live. After this many ms since the last
     * unreachable-peer escalation for a given peer, the engine may escalate
     * again. Default 24h. Cooldown is durable (persisted to disk), so it
     * survives restart.
     */
    unreachableEscalationCooldownMs: number;
}
export declare const DEFAULT_REDRIVE_CONFIG: CollaborationRedriveConfig;
export interface CollaborationRedriveDeps {
    commitmentTracker: CommitmentTracker;
    completionEvaluator: CompletionEvaluator;
    relayClient?: ThreadlineClient;
    surfacer?: CollaborationSurfacer;
    raiseAttention?: (item: {
        title: string;
        body: string;
        priority?: 'low' | 'medium' | 'high';
        source?: string;
    }) => Promise<unknown>;
    knownAgentsPath: string;
    /**
     * Where to persist the per-peer "last unreachable escalation" timestamp
     * log (dogfood fix). Defaults next to `knownAgentsPath` if not set.
     */
    escalationLogPath?: string;
    now?: () => number;
    log?: {
        log: (m: string) => void;
        warn: (m: string) => void;
    };
}
export interface TickResult {
    sent: number;
    skipped: Record<string, string>;
    dailyCountBefore: number;
    disabled: boolean;
}
export declare class CollaborationRedriveEngine {
    private readonly cfg;
    private readonly deps;
    private readonly now;
    private readonly log;
    private sweepTimer;
    /** Resolved path to the durable per-peer unreachable-escalation log. */
    private readonly escalationLogPath;
    /** In-memory cache of the on-disk escalation log; lazy-loaded. */
    private escalationLogCache;
    constructor(deps: CollaborationRedriveDeps, cfg?: Partial<CollaborationRedriveConfig>);
    /**
     * Has it been at least `unreachableEscalationCooldownMs` since we last
     * escalated "can't reach <peer>" for this peer? Reads from the durable
     * log; if the cooldown has elapsed (or there's no record), the engine
     * may escalate again. Persistent across restart by design.
     */
    private shouldEscalateUnreachable;
    private recordUnreachableEscalation;
    private loadEscalationLog;
    start(): void;
    stop(): void;
    tick(): Promise<TickResult>;
    checkEligibility(c: Commitment, nowMs: number): {
        eligible: true;
    } | {
        eligible: false;
        reason: string;
    };
    private checkCompletion;
    private resolveFingerprint;
    /**
     * `relatedAgent` looks like a Threadline fingerprint if it is exactly 32
     * hex characters (the format `computeFingerprint` produces — first 16
     * bytes of the Ed25519 public key, hex-encoded). Matched
     * case-insensitively; the resolver normalises to lowercase before use.
     */
    static looksLikeFingerprint(s: string): boolean;
    private buildNudge;
    private escalateCapHit;
}
export declare function referenceMs(c: Commitment): number;
export declare function isWithin24h(iso: string | undefined, dayAgoMs: number): boolean;
export declare function jaccard3gram(a: string, b: string): number;
//# sourceMappingURL=CollaborationRedriveEngine.d.ts.map