/** Authored token state. Source paths, CSS names, and codecs belong to the host baseline. */ export interface TokenLibraryDocument { schemaVersion: 1; id: string; sourceRevision: string; collections: Record; tokens: Record; } export interface TokenCollection { id: string; name: string; defaultModeId: string; modes: TokenMode[]; } export interface TokenMode { id: string; name: string; /** An absent authored value may inherit from this mode. Empty text is still authored. */ fallbackModeId?: string; } export interface LibraryToken { /** Stable across rename, draft persistence, and source regeneration. */ id: string; collectionId: string; name: string; /** The host's declared value type, preserved without inferring it from text. */ type: string; valuesByMode: Record; } export interface TokenReferenceSpan { /** Non-overlapping UTF-16 offsets in the exact authored text. Syntax belongs to the codec. */ start: number; end: number; tokenId: string; /** Omission keeps the requested evaluation mode, including through inherited values. */ modeId?: string; } export interface TokenValue { kind: 'literal' | 'alias' | 'expression' | 'opaque'; /** Exact authored value text; codecs preserve delimiters, units, and embedded expressions. */ text: string; /** An opaque host codec identity. The core never parses or formats this syntax. */ format: string; references: TokenReferenceSpan[]; } export interface ResolvedTokenReference extends TokenReferenceSpan { modeId: string; } /** Resolves authorship and graph edges, not host value syntax or computed CSS. */ export interface TokenValueResolution { tokenId: string; collectionId: string; modeId: string; authoredModeId: string; inherited: boolean; value: TokenValue; references: ResolvedTokenReference[]; } export interface TokenLibraryDiagnostic { code: string; message: string; tokenId?: string; collectionId?: string; modeId?: string; } export interface TokenLibraryValidationResult { valid: boolean; diagnostics: readonly TokenLibraryDiagnostic[]; } export interface TokenValueEditability { editable: boolean; reason?: 'opaque-value'; } export interface TokenLibraryTransaction { createCollection(collection: TokenCollection): void; renameCollection(collectionId: string, name: string): void; /** Only an empty collection may be removed. */ removeCollection(collectionId: string): void; addMode(collectionId: string, mode: TokenMode): void; renameMode(collectionId: string, modeId: string, name: string): void; /** Referenced/default modes must be retargeted explicitly before removal. */ removeMode(collectionId: string, modeId: string): void; setDefaultMode(collectionId: string, modeId: string): void; setModeFallback(collectionId: string, modeId: string, fallbackModeId: string | null): void; create(token: LibraryToken): void; /** Creates an authored override when this mode previously inherited a value. */ setValue(tokenId: string, modeId: string, value: TokenValue): void; /** Removes an authored override; validation requires every mode to remain resolvable. */ clearValue(tokenId: string, modeId: string): void; /** Stable references remain attached to the same token; the host formats source names. */ rename(tokenId: string, name: string): void; /** Referenced tokens, including references in inactive modes, cannot be removed. */ remove(tokenId: string): void; /** Restores a same-library, same-source snapshot as one undoable transaction. */ replaceDocument(document: TokenLibraryDocument): void; } export interface TokenLibraryEngineOptions { historyLimit?: number; /** Pure host policy checks run before the entire transaction commits. */ preflight?(input: { before: TokenLibraryDocument; after: TokenLibraryDocument; operations: readonly string[]; }): readonly TokenLibraryDiagnostic[]; } export interface TokenLibraryEngine { readonly snapshot: TokenLibraryDocument; readonly revision: number; readonly canUndo: boolean; readonly canRedo: boolean; transact(label: string, apply: (transaction: TokenLibraryTransaction) => void): boolean; undo(): boolean; redo(): boolean; /** Serializes the library only; the internal history envelope is not a public format. */ serialize(): string; subscribe(listener: () => void): () => void; }