/**
 * Shared batch-correction backend used by both Inspector Edit mode (Phase 4)
 * and the `neotoma edit` CLI one-shot (Phase 4b).
 *
 * Why a shared module:
 *   The plan deliberately replaces the post's free-form markdown-diff editor
 *   with two surfaces that speak structured fields. Both surfaces compute a
 *   field diff against the loaded snapshot and must apply corrections with
 *   identical semantics — optimistic concurrency, atomic pre-validation,
 *   deterministic ordering — so users can't get one behavior from the UI and
 *   a different one from the terminal.
 *
 * Semantics:
 *   - Callers pass the `last_observation_at` they saw when they loaded the
 *     snapshot. Before writing anything, we refetch the current snapshot and
 *     compare. If it has moved, we either abort with a structured conflict or
 *     (when overwrite=true) proceed anyway.
 *   - All field changes are pre-validated against the active schema before any
 *     write lands. If any field fails, nothing is written — the UI/CLI sees a
 *     single validation error and the draft is preserved upstream.
 *   - Corrections are applied in deterministic (alphabetical) field order so
 *     Inspector and CLI produce the same observation sequence for the same
 *     diff.
 *
 * Out of scope:
 *   - Multi-entity batching (the post's "rewrite many files" path). Each
 *     batch targets one entity_id.
 *   - Bidirectional mirror-file sync. The mirror stays a derived artifact.
 */
import { db } from "../db.js";
export interface BatchCorrectionFieldChange {
    field: string;
    value: unknown;
}
export interface BatchCorrectionOptions {
    /** Target entity id (required; batches are scoped to one entity). */
    entity_id: string;
    /** Observed entity_type at load time; compared against the current snapshot. */
    entity_type?: string;
    /** Authenticated user applying the corrections. */
    user_id: string;
    /**
     * `last_observation_at` the caller read when loading the snapshot. Used for
     * optimistic concurrency. When provided, a conflict is reported (or
     * overwritten per `overwrite`) if the stored value has moved.
     */
    expected_last_observation_at?: string | null;
    /**
     * If true, proceed even when the snapshot has moved. Maps to the CLI
     * `--force` flag and the Inspector "overwrite" button. When false (default),
     * callers get a structured conflict back and must re-fetch.
     */
    overwrite?: boolean;
    /**
     * Field diff to apply. The caller is responsible for only including fields
     * that actually changed; the backend applies them as-is.
     */
    changes: BatchCorrectionFieldChange[];
    /** Optional base key used to build deterministic idempotency keys. */
    idempotency_prefix?: string;
}
export type BatchCorrectionStatus = "applied" | "conflict" | "validation_error";
export interface BatchCorrectionValidationError {
    field: string;
    message: string;
}
export interface BatchCorrectionConflict {
    stored_last_observation_at: string | null;
    expected_last_observation_at: string | null;
    conflicting_fields: string[];
}
export interface BatchCorrectionApplied {
    observation_id: string;
    field: string;
    value: unknown;
}
export interface BatchCorrectionResult {
    status: BatchCorrectionStatus;
    entity_id: string;
    entity_type: string;
    applied: BatchCorrectionApplied[];
    validation_errors?: BatchCorrectionValidationError[];
    conflict?: BatchCorrectionConflict;
    snapshot?: Record<string, unknown> | null;
    last_observation_at?: string | null;
}
/**
 * Compute a diff of desired field values against the current snapshot. Useful
 * for callers (Inspector, CLI) that accept whole-object edits and want to
 * reduce to a minimal change set before applying.
 */
export declare function diffSnapshotFields(desired: Record<string, unknown>, current: Record<string, unknown> | null | undefined): BatchCorrectionFieldChange[];
/**
 * Validate each change against the active schema for the entity type. Only
 * checks type-compatibility and enum membership; does not enforce required
 * fields (corrections can clear values intentionally). Exported for tests.
 */
export declare function validateChangesAgainstSchema(changes: BatchCorrectionFieldChange[], schema: {
    schema_definition?: {
        fields?: Record<string, {
            type?: string;
            enum?: unknown[];
        }>;
    };
} | null): BatchCorrectionValidationError[];
/**
 * Apply a batch of field corrections to one entity. The flow is:
 *
 *   1. Resolve entity snapshot and schema.
 *   2. Optimistic concurrency check against `expected_last_observation_at`.
 *   3. Schema validation across all changes (fail-fast).
 *   4. Alphabetical application via createCorrection; snapshot recomputes
 *      on the final correction (recomputeSnapshot is idempotent).
 */
export declare function applyBatchCorrection(options: BatchCorrectionOptions): Promise<BatchCorrectionResult>;
/**
 * Lightweight helper used by both surfaces to fetch the current snapshot
 * plus its `last_observation_at` marker for concurrency tracking. Avoids
 * callers pulling in `getEntityWithProvenance` directly.
 */
export declare function loadEntityForEdit(entity_id: string): Promise<{
    entity_id: string;
    entity_type: string;
    schema_version: string;
    snapshot: Record<string, unknown>;
    last_observation_at: string | null;
} | null>;
export { db };
//# sourceMappingURL=batch_correction.d.ts.map