/**
 * FindingsStore — durable persistence for AnalystFinding rows + a diff
 * helper so we can answer "what changed since the last run?" without
 * recomputing analysts.
 *
 * On-disk shape is JSONL: one finding per line, append-only, locked via
 * LockedJsonlAppender. Operators get crash-safety (no partial JSON),
 * cheap reads (sequential parse), and trivial backup (rsync the file).
 *
 * Reads are non-locking: a reader sees a consistent snapshot of all
 * fully-written lines and skips an incomplete trailing line if the
 * writer is mid-append. Cross-process locking is intentionally out of
 * scope (see locked-jsonl-appender.ts).
 *
 * The store is run-scoped: callers pass `runId` on append and on load,
 * which keeps multi-run files cleanly partitioned. The `diffFindings`
 * helper compares two run-id sets using stable `finding_id` semantics —
 * the diff is the cross-run signal the regression dashboard renders.
 */
import type { AnalystFinding } from './types';
/**
 * One persisted row. We attach `run_id` on disk so a single file can
 * hold multiple runs and the diff helper can query without re-walking
 * separate files.
 */
export interface PersistedFinding extends AnalystFinding {
    run_id: string;
}
export declare class FindingsStore {
    readonly path: string;
    private readonly appender;
    constructor(path: string);
    append(runId: string, findings: AnalystFinding[]): Promise<void>;
    /** Load every persisted finding. Discards malformed trailing lines silently. */
    loadAll(): PersistedFinding[];
    /** Filter to a single run. */
    loadRun(runId: string): PersistedFinding[];
}
export interface FindingsDiff {
    /** New finding ids in `current` that weren't in `previous`. */
    appeared: PersistedFinding[];
    /** Finding ids in `previous` that aren't in `current`. */
    disappeared: PersistedFinding[];
    /** Same finding id present in both runs and unchanged per the materiality test. */
    persisted: PersistedFinding[];
    /**
     * Same finding id in both runs but at least one non-identity field
     * shifted per `DiffPolicy.isMaterial`. Reported as [previous, current].
     */
    changed: Array<{
        previous: PersistedFinding;
        current: PersistedFinding;
    }>;
}
export interface DiffPolicy {
    /**
     * Predicate that decides whether two findings (same finding_id) count
     * as a material change. Defaults to {@link defaultIsMaterial}: severity
     * shift, confidence Δ > 0.05, or evidence count change. Compliance /
     * perf consumers MAY supply a stricter predicate (e.g. rationale text
     * diff, metric Δ thresholds).
     */
    isMaterial?: (previous: AnalystFinding, current: AnalystFinding) => boolean;
}
/**
 * Default materiality test. Deliberately narrow so LLM-reword churn
 * doesn't flood the diff. Stricter tests are opt-in via DiffPolicy.
 */
export declare function defaultIsMaterial(a: AnalystFinding, b: AnalystFinding): boolean;
/**
 * Diff two findings sets by stable finding_id. Callers typically load
 * the two run-id slices from the same store and pass them in.
 */
export declare function diffFindings(previous: PersistedFinding[], current: PersistedFinding[], policy?: DiffPolicy): FindingsDiff;
//# sourceMappingURL=findings-store.d.ts.map