import { type NormalizedDefinition, type PendingRevision, type PrepareChecklistResult, type PublishRevisionResult } from "../eval/label/checklist.js"; import { type Draft } from "../eval/label/draft.js"; import type { LabelingGroup } from "../eval/label/group.js"; import type { Annotator, ChecklistRevision, DeepReadonly, FaultHook, Fields } from "../eval/label/types.js"; import type { ChecklistAnnotation, EffectiveChecklistJudgement } from "./annotations.js"; /** * What a labeling session may do to a group of runs, and nothing more. * * The store exposes no file paths, no mutable rows and no unrestricted append: * those are how the sign-off ordering gets bypassed. It hands out read-only * projections and whole idempotent operations. Locks are its business: * * - one lock per session draft (`/checklists//drafts/.lock`), * held until `close()`, so a second process cannot resume and mutate the * same draft; other annotators and other checklists are not blocked; * - one short lock around each lineage publication * (`/checklists//.publish.lock`), so two sessions cannot race * for the same revision number; * - the run's own writer lock around each append, taken by the mutation. * * There is no lock on the group as a whole. */ export declare class LabelStoreValidationError extends Error { } export type OpenLabelStoreArgs = { group: LabelingGroup; identity: LabelSessionIdentity; reportWarning(message: string): void; /** @internal Test-only interruption points inside multi-file operations. */ fault?: FaultHook; }; /** One run as the screen shows it. */ export type LabelStoreItem = { runDir: string; traceId: string; fields: Fields; }; export type LabelSessionIdentity = { sessionId: string; checklistId: string; annotator: Annotator; }; /** What one session needs to reconstruct itself: its own in-progress draft if * there is one, and this annotator's folded answers on this checklist. */ export type LabelStoreSessionSnapshot = { draft: DeepReadonly | null; judgements: Readonly>; }; export type LabelStore = { items(): readonly LabelStoreItem[]; readSession(): LabelStoreSessionSnapshot; saveDraft(draft: Draft): void; prepareChecklist(definition: NormalizedDefinition): PrepareChecklistResult; /** The lineage's newest published revision in the group, if any. */ currentRevision(checklistId: string): ChecklistRevision | undefined; syncChecklistDefinition(definitionPath: string, revision: ChecklistRevision): void; publishRevision(pending: PendingRevision, definitionPath: string): PublishRevisionResult; /** Append a completed checklist row exactly as given, to the run that holds * its trace. Idempotent: a row whose id is already on disk is a replay. */ appendAnnotation(row: ChecklistAnnotation): "appended" | "replayed"; close(): void; }; /** * Open a group for labeling, validating what labeling depends on before * returning: every checklist lineage in the group is contiguous and unedited, * and every existing checklist row in every run names a revision that exists * with the hash it recorded. Validation is fatal here where grading is * tolerant, because a label is the one artifact nothing can regenerate: a * checklist row that points at a missing revision would be labelled around * forever. The session lock is taken first and released if opening fails. */ export declare function openLabelStore(args: OpenLabelStoreArgs): LabelStore;