/**
 * UsherSignalStore — durable, read-only-from-the-outside store of the Usher's
 * re-surface signals + its precision metrics (rung 4 of continuous-working-awareness).
 *
 * Signal-only: the Usher writes suggestions here; consumers PULL them
 * (GET /usher/signals). It never injects. The metrics (fired / acted) — paired
 * with the HumanAsDetectorLog miss-map — are the precision read that gates rung 5.
 *
 * File-backed per topic at {stateDir}/usher/<topicId>.json. Atomic writes
 * (temp+rename); best-effort (metering/signalling must never throw into the
 * message path). Spec: docs/specs/cwa-usher.md §3–4.
 */
export interface UsherSignal {
    id: string;
    /** The faded context ref the turn re-activated. */
    contextRef: string;
    /** The ref's proposition text (for the pull surface). */
    contextText: string;
    /** Why this turn re-activates it (one line, LLM-produced). */
    reason: string;
    /** The user-turn at which it fired. */
    turn: number;
    at: string;
    /** True once the re-surfaced context was actually used (precision numerator). */
    acted: boolean;
    /**
     * Which path confirmed the signal was useful (set when `acted` flips true):
     *   'use'  — the agent's next reply actually used the re-surfaced context.
     *   'miss' — the user later had to correct the agent on that same context, so
     *            the nudge was a genuine catch the agent ignored.
     * Optional for backward-compat with signals/callers that pre-date the split.
     */
    actedVia?: 'use' | 'miss';
    /** ISO timestamp when the signal was marked acted. */
    actedAt?: string;
}
export interface UsherMetrics {
    fired: number;
    acted: number;
    last_fired_at: string | null;
    /** Precision numerator, split by which path confirmed usefulness (observability). */
    acted_by_use?: number;
    acted_by_miss?: number;
}
interface UsherTopicFile {
    topicId: number;
    signals: UsherSignal[];
    metrics: UsherMetrics;
    schemaVersion: 1;
}
export declare class UsherSignalStore {
    private dir;
    constructor(stateDir: string);
    private filePath;
    load(topicId: number): UsherTopicFile;
    private save;
    /** Record a fired signal (best-effort; never throws). Returns the signal id, or null. */
    recordSignal(topicId: number, s: {
        contextRef: string;
        contextText: string;
        reason: string;
        turn: number;
        at?: string;
    }): string | null;
    /**
     * Mark a signal as acted-on (precision numerator). Best-effort, idempotent
     * (a second call on the same signal is a no-op returning false).
     *
     * `opts.via` records WHICH correlation path confirmed usefulness ('use' =
     * the agent used it in a reply; 'miss' = the user had to correct on it) and
     * is reflected in the split metrics. `opts.at` lets callers stamp a
     * deterministic timestamp (tests); defaults to now.
     */
    markActed(topicId: number, signalId: string, opts?: {
        via?: 'use' | 'miss';
        at?: string;
    }): boolean;
    getSignals(topicId: number, limit?: number): UsherSignal[];
    getMetrics(topicId: number): UsherMetrics;
}
export {};
//# sourceMappingURL=UsherSignalStore.d.ts.map