import { type ChecklistCurrent, type ChecklistDefinition, type ChecklistQuestion, type ChecklistRevision, type FaultHook } from "./types.js"; /** A definition with its identities allocated. Declared standalone rather than * as an intersection with `ChecklistDefinition`: intersecting the two makes * `questions` the intersection of the loose and strict element types, so * mapping over it infers back to the loose one. Still assignable to * `ChecklistDefinition`, which is all callers need. */ export type NormalizedDefinition = { name: string; checklistId: string; version?: number; hash?: string; questions: ChecklistQuestion[]; }; /** @internal Prepared but not yet durable. Carries the parent it was computed * against so publication can refuse to land on a lineage that moved. */ export type PendingRevision = { revision: ChecklistRevision; expectedParentVersion: number | null; expectedParentHash: string | null; }; /** @internal */ export type PublishRevisionResult = { revision: ChecklistRevision; replayed: boolean; }; export type PrepareChecklistResult = { kind: "current"; revision: ChecklistRevision; } | { kind: "refresh-definition"; revision: ChecklistRevision; } | { kind: "publish"; pending: PendingRevision; }; /** * Fill in the identities and defaults a definition may omit. * * Allocating ids is separated from publishing so it can happen once, before a * session id is derived from the checklist lineage. A crash after this write * leaves a complete definition nobody has published yet, which the next open * simply publishes. */ export declare function normalizeDefinition(definition: ChecklistDefinition): NormalizedDefinition; /** Build the revision a definition describes, sealed with its content hash. */ export declare function revisionFromDefinition(args: { definition: NormalizedDefinition; version: number; parentVersion: number | null; createdAt: string; }): ChecklistRevision; /** * Decide what an external definition means relative to the published lineage. * * Four outcomes, and the interesting one is the refusal. A definition based on * an older revision AND edited is ambiguous: publishing it would silently * discard whatever changed in between. There is no safe automatic answer, so * it stops. */ export declare function prepareRevision(args: { definition: NormalizedDefinition; current: ChecklistRevision | undefined; now?: string; }): PrepareChecklistResult; /** * Make a prepared revision durable, idempotently. * * Order matters and is owned here alone: immutable revision file, then the * current pointer, then the external definition. Re-running after a crash at * any point converges, because each step accepts an identical existing result * as a replay. */ export declare function publishPendingRevision(args: { dir: string; pending: PendingRevision; definitionPath: string; fault?: FaultHook; }): PublishRevisionResult; /** Bring the external file in line with a published revision. */ export declare function syncChecklistDefinition(args: { definitionPath: string; revision: ChecklistRevision; }): void; export declare function readCurrentPointer(dir: string, checklistId: string): ChecklistCurrent | undefined; /** * Read a published revision and prove it is the one the path claims. * * Schema parsing alone trusts the file: a revision could name a different * version than its filename, or carry a hash that no longer matches its own * questions. Annotations bind to `(version, hash)`, so a schema-valid edit * would otherwise change what old answers mean while still matching the * hash those annotations recorded. */ export declare function readRevision(dir: string, checklistId: string, version: number): ChecklistRevision; /** * Check a whole lineage: contiguous versions from 1, and every adjacent pair * obeying the same evolution rules publication enforces. * * Without the contiguity check, `1.json` and `3.json` pass while `2.json` is * missing, because each file's recorded parent still lines up with the * previous one present. Without re-applying the evolution rules, a text edit * introduced between two revisions is never noticed on read. */ export declare function validateLineageContinuity(dir: string, checklistId: string, versions: number[]): void; /** Every published revision id for a lineage, ascending. Used by label-store * validation to check lineage continuity. */ export declare function listRevisionVersions(dir: string, checklistId: string): number[];