/**
 * JsonlFeedbackStore.ts — the DURABLE canonical FeedbackStore for the operated
 * instance (post-cutover authority under the migration spec's Option B: Echo's
 * instance keeps its OWN canonical copy; Portal never opens a write door).
 *
 * Backing format: newline-delimited JSON, one file per entity family
 * (`feedback.jsonl`, `clusters.jsonl`, `dispatches.jsonl`) under a caller-supplied
 * directory. The format is DELIBERATELY the same shape `PersistedShadowImportTarget`
 * writes (one full row per line, keyed by feedbackId/clusterId), so the proven AS-IS
 * import artifact seeds this store directly — the cutover import output IS the
 * canonical store, no translation step (fewer integrity risks at the one-way door).
 *
 * Mutation model: append-only log with LAST-WRITE-WINS on load. Every mutation
 * appends the FULL updated row; on construction all lines are folded into a Map by
 * id (later lines supersede earlier). A file with one row per entity — exactly what
 * the import produces — is therefore a valid, already-compact log. When superseded
 * lines pile up past a threshold the file is compacted at construction time via an
 * atomic temp+rename rewrite (crash mid-compaction leaves the original intact).
 *
 * JSONL (not SQLite) for the same reason as PersistedShadowImportTarget: dependency-
 * free, no native module, trivially inspectable, and append durability is a plain
 * appendFileSync. Volume is fleet feedback — low write rate; the import's measured
 * 148k-row artifact parses in well under a second.
 */
import type { FeedbackItem, Cluster } from '../processor/types.js';
import type { ReopenDecision } from '../processor/reopen.js';
import type { DispatchRecord } from '../dispatch/dispatch.js';
import type { FeedbackStore, FeedbackMetrics } from './FeedbackStore.js';
export declare class JsonlFeedbackStore implements FeedbackStore {
    private readonly dir;
    private readonly feedbackPath;
    private readonly clustersPath;
    private readonly dispatchesPath;
    private feedback;
    private clusters;
    private dispatches;
    private counts;
    constructor(dir: string);
    private loadAndMaybeCompact;
    private appendFeedback;
    private appendCluster;
    getUnprocessedFeedback(): FeedbackItem[];
    getActiveClusters(): Cluster[];
    getCluster(clusterId: string): Cluster | undefined;
    upsertClusterFromItem(clusterId: string, item: FeedbackItem): void;
    mergeIntoCluster(clusterId: string, _item: FeedbackItem): void;
    applyReopen(clusterId: string, decision: ReopenDecision): void;
    markProcessed(feedbackId: string, clusterId: string): void;
    hasFeedback(feedbackId: string): boolean;
    addFeedback(item: FeedbackItem): void;
    listDispatches(filter?: {
        since?: string;
        type?: string;
    }): DispatchRecord[];
    findDispatchByTitle(title: string): DispatchRecord | undefined;
    createDispatch(record: DispatchRecord): void;
    metrics(): FeedbackMetrics;
    /** Read-only size snapshot for the status surface. */
    sizes(): {
        feedback: number;
        clusters: number;
        dispatches: number;
    };
}
//# sourceMappingURL=JsonlFeedbackStore.d.ts.map