/**
 * Historical backfill helper for the compliance scorecard.
 *
 * Early Neotoma deployments collected `conversation_message` and tool
 * traffic for months before the per-turn `turn_compliance` entity was
 * introduced. To give those operators meaningful numbers without
 * re-running historical traffic through the hooks, this module
 * synthesizes `turn_compliance` snapshots from existing
 * `conversation_message` + tool-invocation history.
 *
 * The heuristic, in plain English:
 *   - Group `conversation_message{role:'user'}` rows by their
 *     `(conversation_id, turn_id)` (or, when missing, by `turn_key`).
 *   - For each user message, look for an `conversation_message{role:'assistant'}`
 *     in the same turn. When found, look for a `store_structured` call
 *     attributable to that turn (best-effort: any `agent_message`
 *     observation or `entity` whose creation timestamp falls in the same
 *     ±15min window and whose source/agent matches).
 *   - When no such call is found, mark the turn as
 *     `status: "backfilled_by_hook"` with `missed_steps:
 *     ["store_structured (estimated)"]`.
 *
 * Each synthesized row carries `estimated: true`, so the scorecard
 * renderer dims the row and the operator knows the number is an estimate.
 *
 * The helper is idempotent: it never touches turns that already have a
 * `conversation_turn` / `turn_compliance` / `turn_activity` row. Re-running
 * is safe.
 *
 * This is NOT a long-term fix: the right answer is to install hooks. The
 * helper merely provides day-zero numbers; subsequent live traffic will
 * naturally replace estimates with real measurements.
 */
export interface HistoricalBackfillOptions {
    user_id: string;
    /** Inclusive lower bound on user message timestamps (ISO). */
    since?: string | null;
    /** Inclusive upper bound on user message timestamps (ISO). */
    until?: string | null;
    /**
     * If true, perform the analysis but do not write any rows. Default
     * false. The dry-run report includes per-turn estimates so operators
     * can sanity-check before running for real.
     */
    dry_run?: boolean;
    /**
     * Default model label when the source rows do not carry one. Operators
     * may override per-deployment.
     */
    default_model?: string;
    /**
     * Default harness label. Defaults to `historical-estimate` so synthetic
     * rows are visually distinct in the scorecard.
     */
    default_harness?: string;
    /** Limit the number of turns processed (safety rail). */
    max_turns?: number;
}
export interface HistoricalBackfillResult {
    examined_turns: number;
    estimated_backfilled: number;
    estimated_compliant: number;
    written: number;
    dry_run: boolean;
    warnings: string[];
}
/**
 * Re-derive `conversation_turn` rows from existing
 * `conversation_message` data when no per-turn entity exists. Returns a
 * summary; throws on hard failures (e.g. DB unreadable). Soft warnings
 * (e.g. cannot resolve a particular turn) are aggregated in the result.
 */
export declare function synthesizeHistoricalTurnCompliance(options: HistoricalBackfillOptions): HistoricalBackfillResult;
//# sourceMappingURL=historical_backfill.d.ts.map