import type { Manifest, TableDeltas, TxnRef } from '@cleocode/contracts/cloud'; /** * 3 for a manifest with the §2.11 accounting fields (checkpoint/v3), else 2. The server's copy is in * its wire contract; contracts export no runtime helpers here (arch gate 10), so it lives beside the * rules. * * @param m - A checkpoint manifest. * @returns The manifest format, which picks the checkpoint signing domain. */ export declare function manifestVersion(m: Manifest): 2 | 3; /** The v2 verdict on a checkpoint manifest: accepted, a row regression, or a schema too new. */ export type ManifestVerdict = { ok: true; } | { ok: false; code: 'E_REGRESSION'; tables: RegressionFinding[]; } | { ok: false; code: 'E_SCHEMA_AHEAD'; schemaVersion: number; maxAccepted: number; }; /** One table whose rows do not reconcile with the parent and the journal. */ export interface RegressionFinding { table: string; parentRows: number; created: number; deleted: number; expectedRows: number; actualRows: number; reason: 'missing-table' | 'count-mismatch'; } /** Sum the per-table deltas of every segment folded into a checkpoint. */ export declare function sumDeltas(deltas: readonly TableDeltas[]): TableDeltas; /** * Decide whether a new checkpoint manifest may replace its parent. * * The rule is exact, not a heuristic: for every table either side names, * `next.rows === parent.rows + created - deleted`, summed over the segments between the two * checkpoints. Every shrink therefore needs a tombstone op to back it, and every new table's rows * need declared creates. A table with rows in the parent must still be present, even with 0 rows. * * With no parent (genesis), only the schema version is checked. */ export declare function checkManifest(parent: Manifest | null, next: Manifest, between: TableDeltas, maxAcceptedSchemaVersion: number): ManifestVerdict; /** * Whether a manifest key is snapshot-authoritative (T12999): the cloud vault's plain-file inventory * (`zz_vault_files`) and its other databases (`zz_vault_db_*`). The change journal never carries * them, so no segment declares their rows: the snapshot alone says what they hold, and the v3 row rule * does not reconcile them against the parent and the window. * * @param key - A manifest table key. * @returns `true` for a key the snapshot alone decides. */ export declare function isSnapshotAuthoritativeKey(key: string): boolean; /** A transaction and its declared (or remaining voided) per-table counts. */ export interface DeclaredTxn { readonly ref: TxnRef; readonly deltas: TableDeltas; } /** A seq in a checkpoint window at which the highest segment schemaVersion seen so far rises. */ export interface SchemaRise { readonly seq: number; readonly schemaVersion: number; } /** What the server knows about a checkpoint's window, the segments in (parent.coversSeq, coversSeq]. */ export interface CheckpointWindow { /** The declared deltas of every transaction in the window: the sum of its segments' `deltas`. */ readonly deltas: TableDeltas; /** * Declared transactions of the window: at least every one the manifest names in `pending` or * `voided` (the server loads only those). A named ref missing here is not in the window. */ readonly txns: readonly DeclaredTxn[]; /** Each window segment's seq and schemaVersion, in seq order. */ readonly schemaVersions: readonly SchemaRise[]; } /** A window built from all of its transactions (and segment schema versions), for small windows and tests. */ export declare function windowOf(txns: readonly DeclaredTxn[], schemaVersions?: readonly SchemaRise[]): CheckpointWindow; /** * The transition points of a replay pin (journal spec §2.11 §7): each seq at which the highest * schemaVersion seen so far rises above everything before it, starting from `baseline` (the parent * checkpoint's schemaVersion). */ export declare function schemaRises(baseline: number, schemaVersions: readonly SchemaRise[]): SchemaRise[]; /** Why a v3 manifest's accounting lists are refused. */ export type AccountingFinding = { reason: 'genesis-not-empty'; } | { reason: 'duplicate-ref'; list: 'pending' | 'voided' | 'revived'; ref: TxnRef; } | { reason: 'pending-not-in-window'; ref: TxnRef; } | { reason: 'pending-unresolved'; ref: TxnRef; } | { reason: 'transitions-mismatch'; expected: SchemaRise[]; actual: SchemaRise[]; } | { reason: 'schema-version-below-floor'; schemaVersion: number; floor: number; } | { reason: 'voided-not-applied'; ref: TxnRef; } | { reason: 'voided-exceeds-declared'; ref: TxnRef; table: string; } | { reason: 'revived-not-voided'; ref: TxnRef; } | { reason: 'revived-exceeds-voided'; ref: TxnRef; table: string; } | { reason: 'pruned-out-of-range'; table: string; pruned: number; max: number; } | { reason: 'authoritative-not-normal'; } | { reason: 'authoritative-grew'; table: string; } | { reason: 'authoritative-declared'; table: string; } | { reason: 'authoritative-omitted'; } | { reason: 'authoritative-vault-key'; table: string; }; /** The v3 verdict: the v2 outcomes, accounting refusals, or the stream's v3 ratchet. */ export type ManifestVerdictV3 = ManifestVerdict | { ok: false; code: 'E_MANIFEST_ACCOUNTING'; findings: AccountingFinding[]; } | { ok: false; code: 'E_STREAM_VERSION'; reason: 'stream-v3'; parentVersion: 3; nextVersion: 2; }; /** The key of a transaction ref in maps. */ export declare function txnRefKey(r: TxnRef): string; /** * Decide whether a v3 checkpoint manifest may replace its parent (journal spec §2.11 §4). Exact: * no aggregate slack for pending and no age bound. With `A` = (window transactions ∪ the parent's * pending) − the new pending, every table must hold * * rows = parent.rows + Decl(A).created − Decl(A).deleted * − Σ voided.created + Σ voided.deleted * + Σ revived.created − Σ revived.deleted * − pruned * * and: pending ⊆ window ∪ parent.pending; every voided ref ∈ A with counts ≤ its declared counts; * every revived ref in the stream's cumulative voided set with counts ≤ what is still voided there; * 0 ≤ pruned ≤ parent.rows + Decl(A).created; the replay pin's transitions are exactly the window's * schema rise points from the parent's schemaVersion, and the manifest's schemaVersion is at least the * parent's and the last of those rises (T090), so the next window's baseline never sits below what * the replay already reached. Decl(A) is computed from the window's sum, so * only the named transactions need loading: Decl(window) + Decl(parent.pending) − Decl(pending). * The snapshot-authoritative keys ({@link isSnapshotAuthoritativeKey}: the vault's files and other * databases) are not reconciled: no segment declares their rows (T12999). * Neither are the tables `next.snapshotAuthoritative` lists (T13777): sorted and unique, never a vault * key, a subset of the parent's list and never omitted after it when the parent has one, and never a * table any segment at or below coversSeq ever declared rows for ({@link input.journaledTables}), nor one * the window or the parent's pending declare. * A v2 manifest is the v3 one with empty lists; a v2 segment is one transaction (txn 0) with the * segment's deltas. Once a stream has a v3 checkpoint, a v2 one is refused (E_STREAM_VERSION): the * lineage is linear, so checking the parent ratchets the whole stream. * * @param input.window - The window's deltas sum, its named transactions and its segment versions. * @param input.parentPending - The declared deltas of the parent manifest's pending refs. Each of * them must be here (`pending-unresolved` otherwise). * @param input.voidedBefore - The stream's cumulative voided set before this checkpoint: at least * the entries of every ref `next.revived` names. * @param input.journaledTables - Of the tables `next.snapshotAuthoritative` lists, those any segment of * the stream at or below coversSeq has ever declared rows for (T13777). The server computes it from the * stored segments; omitted, only the window and the parent's pending are checked. */ export declare function checkManifestV3(input: { readonly parent: Manifest | null; readonly next: Manifest; readonly window: CheckpointWindow; readonly parentPending: readonly DeclaredTxn[]; readonly voidedBefore: readonly DeclaredTxn[]; readonly maxAcceptedSchemaVersion: number; readonly journaledTables?: readonly string[]; }): ManifestVerdictV3; /** * The stream's cumulative voided set after an accepted checkpoint: the set before it, plus this * window's `voided`, minus its `revived`, per ref and table; refs left with nothing are dropped. */ export declare function nextVoidedSet(before: readonly DeclaredTxn[], voided: readonly DeclaredTxn[], revived: readonly DeclaredTxn[]): DeclaredTxn[]; //# sourceMappingURL=manifest-check.d.ts.map