/**
 * WikiReflectTriggerService — periodic nudge that pings ORC when no
 * `wiki-queue-add` has fired against a vault recently.
 *
 * Rationale (2026-05-24):
 *   The wiki infrastructure (queue, ingest, process, bookkeep) is shipped
 *   and instrumented, but `wiki-queue-add` fire-rate is effectively zero —
 *   the per-turn discipline in the role prompts is soft and rarely runs
 *   in practice. This trigger raises a hard nudge: every `intervalMs`,
 *   per vault, if no queue-add happened in the last `quietWindowMs`,
 *   fire a `[REFLECT-WIKI] vault=…` message via the caller-injected
 *   `fireFn`. ORC then either queues recent worth-saving items or no-ops.
 *
 * Mechanism mirrors `WikiBookkeepTriggerService` so they coexist cleanly:
 *   - scan vaults via `discoverWikiVaults`
 *   - per vault: count queue items added within `quietWindowMs`
 *   - if zero AND debounce window has elapsed → fire
 *
 * @module services/wiki/wiki-reflect-trigger.service
 */
import { WikiQueueService } from './wiki-queue.service.js';
export interface WikiReflectFireMeta {
    /** vault path being nudged. */
    vaultPath: string;
    /** ms since the last queued item (Infinity if none). */
    msSinceLastQueueAdd: number;
    /** queue items added within `quietWindowMs`. */
    recentQueueAdds: number;
    /** total queue items (any status) currently in the vault. */
    totalQueueItems: number;
}
export type WikiReflectFireFn = (meta: WikiReflectFireMeta) => Promise<void> | void;
export interface WikiReflectTriggerOptions {
    /** Interval between scans, ms. Default 60 minutes. */
    intervalMs?: number;
    /** "Quiet" window — fire only when no add happened in this window. Default 4 hours. */
    quietWindowMs?: number;
    /** Minimum gap between fires for the same vault, ms. Default 4 hours. */
    debounceMs?: number;
    /** Caller-injected notifier (e.g. enqueue `[REFLECT-WIKI]` chat to ORC). */
    fireFn: WikiReflectFireFn;
    /** Optional discovery override (tests). */
    discoverRoots?: () => Promise<string[]>;
    /** Optional queue service override (tests). */
    queueService?: WikiQueueService;
    /** Optional time override (tests). */
    now?: () => number;
    /**
     * Where to persist the per-vault debounce ledger. Defaults to
     * `~/.crewly/wiki-reflect-trigger-state.json`. Pass `null` to disable
     * persistence (tests). Without persistence the ledger resets on every
     * restart, so the next tick re-fires for every idle vault at once.
     */
    statePath?: string | null;
}
/**
 * Reflect-trigger service. Start at boot, stop at shutdown.
 */
export declare class WikiReflectTriggerService {
    private static instance;
    private readonly logger;
    private readonly intervalMs;
    private readonly quietWindowMs;
    private readonly debounceMs;
    private readonly fireFn;
    private readonly discoverRoots;
    private readonly queueService;
    private readonly nowFn;
    private timer;
    /** vaultPath → last fired timestamp (ms since epoch). */
    private readonly lastFiredAt;
    /** Per-vault locks so overlapping ticks don't double-fire. */
    private readonly inflight;
    private readonly statePath;
    private stateLoaded;
    constructor(opts: WikiReflectTriggerOptions);
    /** Load the persisted debounce ledger (once) so restarts don't re-burst. */
    private loadStateFromDisk;
    /** Persist the debounce ledger (best-effort; failures logged, not thrown). */
    private saveStateToDisk;
    static getInstance(): WikiReflectTriggerService | null;
    static setInstance(next: WikiReflectTriggerService | null): void;
    start(): void;
    stop(): void;
    /**
     * Run one scan. Returns the per-vault outcome for observability + tests.
     */
    tick(opts?: {
        ignoreDebounce?: boolean;
    }): Promise<{
        scanned: string[];
        fired: string[];
        skippedByActivity: string[];
        skippedByDebounce: string[];
    }>;
    /**
     * Test affordance — clear the in-memory debounce ledger. Leaves `stateLoaded`
     * set so a subsequent `tick()` does NOT reload the persisted ledger (which
     * would undo the clear). To force a real fire past debounce in production,
     * use `tick({ ignoreDebounce: true })` instead of this.
     */
    _resetDebounceForTesting(): void;
}
//# sourceMappingURL=wiki-reflect-trigger.service.d.ts.map