/** * Property runner input domain contracts. * * These types define how render inputs are supplied to a property run: * either as an explicit finite enumeration (determinate) or as a * generated sampled domain (sampled). The mode is always explicit. * * Invariant 6: every InputDomain carries its mode at the type level so * downstream code cannot silently switch from enumerated to generated. */ // --------------------------------------------------------------------------- // InputDomain // --------------------------------------------------------------------------- export type InputDomain = | { mode: 'enumerated'; values: unknown[] } | { mode: 'generated'; arbitrary: unknown; seed?: number; numRuns?: number } // --------------------------------------------------------------------------- // Type Guards // --------------------------------------------------------------------------- export function isEnumeratedDomain(domain: InputDomain): domain is Extract { return domain.mode === 'enumerated' } export function isGeneratedDomain(domain: InputDomain): domain is Extract { return domain.mode === 'generated' } // --------------------------------------------------------------------------- // Factory Helpers // --------------------------------------------------------------------------- export function enumeratedDomain(values: unknown[]): InputDomain { return { mode: 'enumerated', values } } export function generatedDomain(arbitrary: unknown, options?: { seed?: number; numRuns?: number }): InputDomain { return { mode: 'generated', arbitrary, seed: options?.seed, numRuns: options?.numRuns } }