/**
 * importIntegrity.ts — the integrity-safe import core (spec §2.4).
 *
 * "Row counts + spot-check" is too weak to catch silent corruption of the irreplaceable
 * curated state. This module is the pure, deterministic core of the AS-IS import gate;
 * the real Prisma adapter wraps these in one transaction (parent-before-child FK order)
 * and runs the synthetic post-import insert. Keeping the logic pure makes the Phase-2
 * gate fully unit-testable without a database.
 *
 * The gate (spec §2.4): per-row curated-field checksums match (in vs out) + pre-import
 * fingerprint-uniqueness resolved + schema-equivalence holds + FK referential integrity
 * + a sequence reset computed so the next post-cutover insert cannot collide (P2002).
 */
import type { Cluster, FeedbackItem } from '../processor/types.js';
/**
 * Curated cluster fields whose exact preservation the checksum guards. The cluster table
 * is curated human/LLM judgment, not a cache — every one of these must survive AS-IS.
 */
export declare const CURATED_CLUSTER_FIELDS: readonly ["clusterId", "title", "description", "type", "status", "fingerprint", "recurrenceCount", "reportCount", "createdAt", "fixedInVersion", "fixAppliedAt", "dispatchedAt", "governanceNotes", "processingNotes", "actionTaken", "researchNotes", "chronicCount"];
/** Curated feedback fields (the report rows linked to clusters). */
export declare const CURATED_FEEDBACK_FIELDS: readonly ["feedbackId", "title", "description", "type", "status", "receivedAt", "instarVersion"];
/** Deterministic checksum over the named fields of a row (field order fixed by `fields`). */
export declare function curatedChecksum(row: Record<string, unknown>, fields: readonly string[]): string;
export declare function clusterChecksum(cluster: Cluster): string;
export declare function feedbackChecksum(item: FeedbackItem): string;
export interface ChecksumMismatch {
    id: string;
    kind: 'cluster' | 'feedback';
    reason: 'missing-in-target' | 'extra-in-target' | 'checksum-differs';
    sourceChecksum?: string;
    targetChecksum?: string;
}
/**
 * Compare source rows (Dawn's export) against imported rows (canonical instance) by id,
 * field-by-field via checksum. Returns every divergence — empty array == clean import.
 */
export declare function verifyImportChecksums(source: {
    clusters: Cluster[];
    feedback: FeedbackItem[];
}, target: {
    clusters: Cluster[];
    feedback: FeedbackItem[];
}): ChecksumMismatch[];
/** A set of clusters that collide on `fingerprint` (the @unique constraint would abort the import). */
export interface FingerprintCollision {
    fingerprint: string;
    clusterIds: string[];
}
/**
 * Pre-import uniqueness scan on the SOURCE: curated history may hold two clusters sharing a
 * fingerprint (after manual merges/edits). An AS-IS import would abort on @unique mid-txn or
 * silently collapse them — detect + surface BEFORE importing so a human resolves it.
 */
export declare function scanFingerprintUniqueness(clusters: Cluster[]): FingerprintCollision[];
/** A field whose value-domain differs between Dawn's schema and the canonical instance. */
export interface SchemaDivergence {
    field: string;
    kind: 'unknown-status-value' | 'type-mismatch' | 'missing-field';
    detail: string;
}
export interface SchemaDescriptor {
    /** Allowed lifecycle status values (enum or string union). */
    statusValues: string[];
    /** Field → declared type, for the fields the processor reads. */
    fieldTypes: Record<string, string>;
}
/**
 * Schema-equivalence assertion: every status value the SOURCE uses must be accepted by the
 * TARGET, and the field types must line up. Mismatched enums or a status the target rejects
 * would corrupt the import silently — surface it before the transaction.
 */
export declare function assertSchemaEquivalence(source: SchemaDescriptor, target: SchemaDescriptor): SchemaDivergence[];
/** A feedback row pointing at a cluster that does not exist in the import set. */
export interface DanglingRef {
    feedbackId: string;
    clusterId: string;
}
/**
 * FK referential-integrity check (not just row counts): every feedback row that claims a
 * clusterId must resolve to an imported cluster. Run AFTER the parent-before-child import
 * to prove no dangling references survived.
 */
export declare function checkReferentialIntegrity(clusters: Cluster[], feedback: FeedbackItem[]): DanglingRef[];
/**
 * The next auto-increment value to set after importing explicit PKs, so the next NEW
 * post-cutover insert cannot collide (P2002). Returns maxNumericId + 1, or 1 if no numeric
 * ids were imported. Non-numeric ids are ignored (cuid/uuid PKs need no sequence reset).
 */
export declare function planSequenceReset(importedIds: Array<string | number>): number;
export interface IntegrityReport {
    fingerprintCollisions: FingerprintCollision[];
    schemaDivergences: SchemaDivergence[];
    checksumMismatches: ChecksumMismatch[];
    danglingRefs: DanglingRef[];
    sequenceResetTo: number;
    /** True only when EVERY check is clean — the Phase-2/4 import gate. */
    passed: boolean;
}
/**
 * Run the full integrity gate over a source export and its imported copy. `passed` is the
 * single Phase-2/4 gate boolean; any non-empty divergence list fails it.
 */
export declare function runIntegrityGate(source: {
    clusters: Cluster[];
    feedback: FeedbackItem[];
    schema: SchemaDescriptor;
}, target: {
    clusters: Cluster[];
    feedback: FeedbackItem[];
    schema: SchemaDescriptor;
}): IntegrityReport;
//# sourceMappingURL=importIntegrity.d.ts.map