/** * Periodic reconciliation scanner for the System_State projection. * * SQLite is the canonical state; the Sheet is a projection that may drift when * the fast-append path skips per-effect CAS, when a spreadsheet owner edits a * protected tab, or when a response is lost. This scanner compares the durable * desired state against one provider snapshot per scan and, for every drift, it * enqueues a normal system_projection effect on the existing outbox. The effect * worker then applies the correction through the same slow path (with CAS) used * by regular writes, so reconciliation never writes to the Sheet directly. * * Scope is intentionally limited to System_State in v1: that projection is * protected and hidden, so the canonical state is always authoritative and a * drift is always a repair target. User_Input reconciliation remains the * responsibility of the candidate/conflict pipeline. * * This module owns the scan lifecycle and orchestration only. Drift detection * lives in diff.ts, correction effect generation in repair.ts, and the shared * contracts/SQL helpers in shared.ts. */ import type { SqlStorageAdapter } from "../../../../contracts/storage/sql.js"; import { type SyncSheetsProvider } from "../../../../contracts/sheets/syncSheets.js"; import { type ReconciliationIdFactory } from "./shared.js"; export type { ReconciliationIdFactory } from "./shared.js"; /** Construction options for a single reconciliation scan. */ export interface RunReconciliationScanOptions { readonly storage: SqlStorageAdapter; readonly provider: SyncSheetsProvider; /** Physical sheet id of the System_State projection to reconcile. */ readonly physicalSheetId: string; /** Logical sheet id owning the entity row bindings. */ readonly logicalSheetId: string; /** * Schema-declared field list for the System_State projection. The scanner * reads exactly these fields per row and ignores anything else in the Sheet. */ readonly systemFields: readonly string[]; /** * Field name that encodes a tombstone (soft delete) on the System_State * projection. Defaults to `_deleted`; tombstoned rows are dropped from the * desired state and re-created if the Sheet still exposes them. */ readonly tombstoneField?: string; /** Schema version shared by every System_State effect produced here. */ readonly schemaVersion: number; /** Reconciler writer identity. */ readonly writerId: string; /** Injectable clock and id source for deterministic tests. */ readonly now?: () => number; readonly createId?: ReconciliationIdFactory; /** Override the reconciler lease role or duration. */ readonly writerRole?: string; readonly leaseDurationMs?: number; /** Observability hook invoked once after the scan settles. */ readonly onReport?: (report: ReconciliationScanReport) => void; } /** Observable outcome of one reconciliation scan. */ export interface ReconciliationScanReport { readonly physicalSheetId: string; readonly snapshotRowsScanned: number; readonly desiredRowsScanned: number; readonly matchedRows: number; readonly driftedRows: number; readonly missingRows: number; readonly extraRows: number; readonly effectsEnqueued: number; readonly fenceClaimed: boolean; } /** * Runs one reconciliation scan and enqueues correction effects for drift. * * The scan never writes to the Sheet. It only reads a snapshot and inserts * effects into the durable outbox; the existing effect worker applies them. */ export declare function runReconciliationScan(options: RunReconciliationScanOptions): Promise; export declare const RECONCILIATION_DEFAULTS: { readonly ROLE: "typed-sheets-reconciler"; readonly LEASE_MS: 60000; readonly TOMBSTONE_FIELD: "_deleted"; }; //# sourceMappingURL=ReconciliationScanner.d.ts.map