/** * Declared row identity (T12341): which syncing tables carry a uid and how it * is made. Data only, with type-only imports, so the Gate B scripts * (`scripts/fingerprint-store.mjs`) load it straight from source, like the * Gate A registry. The uid recipes and the fill live in `row-identity.ts`. * Spec: `cleo docs fetch t12341-uid-scheme`. * * @module * @task T12341 * @task T12897 * @epic T12323 */ import type { RowIdentitySpec, TableScope } from '@cleocode/contracts'; /** Physical name of every uid column. */ export declare const UID_COLUMN = "uid"; /** * The rows of a declared table that should carry a uid but lack one (a SQL * predicate over `main.`): not kept local by a NULL key column * (`localWhenNull`), nor by an earlier row holding the same natural key * (`localUnlessFirst`, T13777). * * @param spec - A declared table's spec. * @returns The predicate, for a `WHERE` over `main.
`. */ export declare function uidMissingWhere(spec: RowIdentitySpec): string; /** * The rows of a declared table that sync (T13777): every row with a uid, and * the rows still waiting for one. A row local by spec ({@link uidMissingWhere}) * is not one of them. `null` for a table with no local rule (all rows sync). * * @param spec - A declared table's spec. * @returns The predicate, for a `WHERE` over `main.
`, or `null`. */ export declare function syncedRowsWhere(spec: RowIdentitySpec): string | null; /** Physical name of the birth fingerprint column of every minted table. */ export declare const BIRTH_FP_COLUMN = "birth_fp"; /** * Declared row identity, per scope. Every syncing table is either declared * here or exempt with a reason in {@link ROW_IDENTITY_EXEMPT} (T12897); the * row-identity coverage gate fails on a table in neither. * * Tables whose bare twin is still the live write target (attachments, ADRs, * token usage, …) are declared when their twin collapse lands (spec §10). * * `content` and `birthFacts` lists are FROZEN for recipe v1: changing one is a * new recipe version, never an edit here. */ export declare const ROW_IDENTITY: Readonly>; /** * Tables that exist only to support row identity (added by the uid migration * itself). A replay of a store from before that migration leaves them out, * with the identity columns (`fingerprint-store.mjs --omit-row-identity`). * Includes the local-only AC uid graveyard (spec §6.5). */ export declare const ROW_IDENTITY_TABLES: Readonly>; /** * Why a syncing table syncs without declared row identity (T12897). * * - `planned` — a filed task gives the table its uid; it syncs without one * until then. * - `twin-collapse` — one of a live exodus twin pair that both sync, or a * table the collapse must change first; the uid goes on the survivor once * T12535 collapses the pair (spec §10). * - `not-row-replicated` — the table does not travel as rows at all. * * @task T12897 */ export type RowIdentityExemptionCategory = 'planned' | 'twin-collapse' | 'not-row-replicated'; /** * A syncing table's declared reason for having no {@link ROW_IDENTITY} entry. * * @task T12897 */ export interface RowIdentityExemption { /** Kind of reason. */ readonly category: RowIdentityExemptionCategory; /** Why the table syncs without row identity, and what ends the exemption. */ readonly reason: string; /** The task that ends the exemption; it must exist and be open. */ readonly task: string; } /** * Bare tables the twin collapse DRAINS into their prefixed twin (T13115, * T13777), bare name → twin name. Kept here, a module every open already loads, so * the bare-twin strand check (`sync/flags.ts`) adds nothing to the CLI's * startup graph (gate 39). * * A drained bare table is the inbox of rows an older build writes: every open * moves them into the twin losslessly, and a row the drain must leave behind * is reported by `cleo doctor twin-collapse`. So its rows are never a legacy * strand that should refuse capture or sealing: the next open carries them. * * @task T13777 */ export declare const DRAINED_TWINS: Readonly>; /** * Every syncing table WITHOUT a {@link ROW_IDENTITY} entry, with the reason it * syncs without one. A syncing table in neither place fails the row-identity * coverage gate (`scripts/lint-row-identity-coverage.mjs` against the * classification registry, `__tests__/row-identity-gate.test.ts` against * fresh stores), and so does an exemption whose table is declared, no longer * exists or no longer syncs. Declaring a table drops its exemption in the * same change. * * @task T12897 */ export declare const ROW_IDENTITY_EXEMPT: Readonly>>>; /** * The exemption count per scope. Only ever lowered: a change that declares * tables lowers it in the same change, so the allowance cannot be spent again, * and a new syncing table is declared rather than exempted unless the change * raises this on purpose. * * Since T12894 declared the brain text-keyed tables (11 project, 12 global), * T12895 the brain natural-key tables (3 project, 3 global) and T12896 the * brain integer-keyed tables (6 project, 6 global), T12915 declared the * agent registry (1 global; 6 more reclassified derived or local-only), * T13354 declared the re-keyed conduit doc family (5 project, dropping 4 * exemptions — contributors became derived and not syncing), T13467 the * credential tables (4 global), and T12919 the doc registry and its refs * (2 project; docs_wikilinks became derived and not syncing), and T13729 * reclassified brain_embeddings derived in both scopes (owner decision * 2026-10-14: vectors are a local cache), closing the T12918 blob exemption, * and T12914 the lifecycle, release, PR and commit tables (16 project), * and T13777 declared the command logs (3 project: the audit log, token * usage, handoff entries; 1 global: the Nexus audit log), * and T12535 the project sticky tables and the playbook tables (2 + 4 * project: the bare playbook twins became frozen-legacy and not syncing) * ({@link rowIdentityExemptionSummary} prints the live numbers): * * | category | task | project | global | * |----------------------|--------|---------|--------| * | planned | T12894 | 0 | 0 | * | planned | T12895 | 0 | 0 | * | planned | T12896 | 2 | 1 | * | planned (conduit) | T12913 | 8 | 0 | * | planned (lifecycle…) | T12914 | 0 | 0 | * | planned (nexus) | T12916 | 0 | 7 | * | planned (skills) | T12917 | 0 | 4 | * | planned (misc) | T12920 | 11 | 0 | * | twin-collapse | T12535 | 22 | 0 | * | total | | 41 | 11 | * * @task T12897 */ export declare const ROW_IDENTITY_EXEMPT_PINNED: Readonly>; /** * sha256 of each scope's sorted exempt table names * ({@link rowIdentityExemptDigest}), pinned with the count so swapping one * exempt table for another fails too (#1764 review L4). Update it in the same * change that drops an exemption; the gate prints the new value. * * @task T12897 */ export declare const ROW_IDENTITY_EXEMPT_NAMES_SHA256: Readonly>; /** * sha256 (hex) of a set of table names, sorted and newline-joined. * * @param names - Table names. * @returns The hex digest. * @task T12897 */ export declare function rowIdentityExemptDigest(names: Iterable): string; /** * Exemption counts of one scope, by category and by `category task`. * * @param scope - Store scope. * @returns `total`, `byCategory` and `byTask` (key ` `), * keys sorted. * @task T12897 */ export declare function rowIdentityExemptionSummary(scope: TableScope): { total: number; byCategory: Record; byTask: Record; }; /** * One problem the row-identity coverage gate reports. * * - `missing` — a syncing table with neither a declared uid nor an exemption. * - `stale` — an exemption whose table is not a syncing table (gone, or * reclassified to a class that does not sync). * - `declared` — an exemption whose table is also declared. * - `invalid` — an exemption without a reason or a `T` task. * - `pinned` — the exemption count or the digest of the exempt names differs * from its pin. * * @task T12897 */ export interface RowIdentityCoverageProblem { readonly kind: 'missing' | 'stale' | 'declared' | 'invalid' | 'pinned'; readonly table?: string; readonly message: string; } /** * Check that every syncing table is declared or exempt, and that every * exemption still names an undeclared syncing table. Pure: the caller supplies * the syncing set (from the classification registry or a physical store). * * @param input - `syncing`: the scope's syncing tables; `declared`: tables * with a {@link ROW_IDENTITY} entry; `exempt`: the scope's exemptions; * `pinned`: the expected exemption count (omit to skip); `pinnedDigest`: * the expected {@link rowIdentityExemptDigest} of the exempt names (omit to * skip); `mayBeAbsent`: * exempt tables allowed to be missing from `syncing` (a fresh store leaves * out optional-transient tables). * @returns The problems; empty when every syncing table is covered. * @task T12897 */ export declare function checkRowIdentityCoverage(input: { readonly syncing: Iterable; readonly declared: Iterable; readonly exempt: Readonly>; readonly pinned?: number; readonly pinnedDigest?: string; readonly mayBeAbsent?: Iterable; }): RowIdentityCoverageProblem[]; /** * The declared identity of a table, or `undefined` when it has none (yet). * * @param scope - Store scope. * @param table - Physical table name. * @returns The spec, or `undefined`. */ export declare function rowIdentitySpec(scope: TableScope, table: string): RowIdentitySpec | undefined; /** * The identity columns of a table: `uid`, `birth_fp` (minted tables) and its * stored reference facts. Replay comparisons of a store before and after the * uid migration leave these out (`fingerprint-store.mjs --omit-row-identity`). * * @param scope - Store scope. * @param table - Physical table name. * @returns Column names; empty for an undeclared table. */ export declare function rowIdentityColumns(scope: TableScope, table: string): string[]; //# sourceMappingURL=row-identity-registry.d.ts.map