import type { InteractiveStates } from './interactiveStates.js'; import type { RegistryPropValue } from './registry.js'; import { type ScreenCards } from './screenCards.js'; import { type ScreenLists } from './screenLists.js'; import type { EditorStore } from './store.js'; import type { ViewportPresets } from './viewportPresets.js'; export type ScenarioCoverageClaim = { scenarioId: string; kind: 'frame'; screenId: string; reason?: string; } | { scenarioId: string; /** A folded screen-state sibling demonstrates the scenario. */ kind: 'screen-state'; screenId: string; reason?: string; } | { scenarioId: string; /** A registry-typed component prop on the screen demonstrates it. */ kind: 'component-state'; screenId: string; componentName: string; prop: string; value: RegistryPropValue; reason?: string; } | { scenarioId: string; /** A named viewport preset on the screen demonstrates it. */ kind: 'viewport'; screenId: string; /** ViewportPresetDef label, e.g. "Minimum". */ preset: string; reason?: string; } | { scenarioId: string; /** * A component catalog sheet demonstrates it — the surface for preview * adapters whose product DOM is unstamped plain markup, so no screen * instance exists to toggle. */ kind: 'catalog'; screenId: string; reason?: string; } | { scenarioId: string; /** * A declared interactive axis demonstrates it: the scenario is one * gesture away from the captured screen (a folded sidebar, a hover), * so it needs a control rather than a frame of its own. */ kind: 'interactive-state'; /** InteractiveStateDef id. */ interaction: string; /** InteractiveStateOption id within that axis. */ option: string; screenId: string; reason?: string; } | { scenarioId: string; /** * A badge composition on the screen's repeated card demonstrates it — * which chips a row carries is a slot decision, not a screen. */ kind: 'card-slot'; /** ScreenCardDef id. */ card: string; /** CardSlotDef id within that card. */ slot: string; /** CardBadgeOption id within that slot. */ option: string; screenId: string; reason?: string; } | { scenarioId: string; /** A row count on the screen's declared list demonstrates it. */ kind: 'list-length'; /** ScreenListDef id. */ list: string; count: number; screenId: string; reason?: string; } | { scenarioId: string; kind: 'behavior'; reason: string; } | { scenarioId: string; kind: 'todo'; reason: string; }; /** * What a diagnostic is about, as a value. `unknown-*` codes name a target * the claim referenced that the context does not declare; `target` carries * the referenced id so the host joins it back without parsing the message. */ export type ScenarioCoverageDiagnosticCode = 'unknown-scenario' | 'insufficient-reason' | 'unknown-screen' | 'not-a-state-group' | 'unknown-component' | 'unknown-prop' | 'unknown-value' | 'unknown-preset' | 'unknown-axis' | 'unknown-option' | 'base-option' | 'unknown-card' | 'unknown-slot' | 'unknown-list' | 'count-out-of-range' | 'duplicate-claim' | 'unclaimed'; export interface ScenarioCoverageDiagnostic { severity: 'error' | 'warning'; code: ScenarioCoverageDiagnosticCode; scenarioId: string; /** The claim's kind, when the diagnostic is about one claim. */ kind?: ScenarioCoverageClaim['kind']; /** The screen the claim named, when it named one. */ screenId?: string; /** The declaration the claim referenced and the context lacks. */ target?: string; message: string; } export interface ScenarioCoverageContext { /** The scenario inventory every claim must classify exactly once. */ scenarios: readonly { id: string; }[]; /** Screen catalog with state-group metadata. */ screens: readonly { id: string; scenario?: string; state?: string; }[]; /** Registry prop declarations, for component-state claims. */ registry: Readonly>; }>>; /** Host-declared viewport presets, for viewport claims. */ viewportPresets: readonly { label: string; }[]; /** Catalog sheet pages, for catalog claims. */ catalogPages?: readonly { id: string; }[]; /** Host-declared interactive axes, for interactive-state claims. */ interactiveStates?: readonly { id: string; options: readonly { id: string; steps?: readonly unknown[]; }[]; }[]; /** Host-declared card compositions, for card-slot claims. */ screenCards?: readonly { id: string; slots: readonly { id: string; options: readonly { id: string; }[]; }[]; }[]; /** Host-declared list axes, for list-length claims. */ screenLists?: readonly { id: string; min?: number; max?: number; }[]; } /** * Validates the ledger: every scenario classified exactly once, and every * claim's target actually exists — screen in the catalog, state in a group, * prop and value in the registry, preset among the host's declarations. */ export declare function validateScenarioCoverage(claims: readonly ScenarioCoverageClaim[], context: ScenarioCoverageContext): ScenarioCoverageDiagnostic[]; /** * Counts by outcome, over the scenario inventory. * * A scenario is `covered` only when its one claim reproduces a reviewed * state and validates clean. `behavior` and `todo` are visible in their own * counts and never in `covered` — a todo is an admission, not a * verification. A scenario whose claims carry an error (an unknown target, * a duplicate) is `invalid`, again never `covered`. Claims naming scenarios * the inventory lacks are listed under `unknownIds`; they are outside `total`. */ export interface ScenarioCoverageSummary { total: number; covered: number; behavior: number; todo: number; invalid: number; unclaimed: number; behaviorIds: string[]; todoIds: string[]; invalidIds: string[]; unclaimedIds: string[]; unknownIds: string[]; } export declare function summarizeScenarioCoverage(claims: readonly ScenarioCoverageClaim[], context: ScenarioCoverageContext): ScenarioCoverageSummary; export interface ApplyCoverageResult { status: 'applied' | 'pending-import' | 'failed'; message?: string; } /** One editor's scenario coverage claims, validated against its other declarations. */ export declare function createScenarioCoverage(deps: Pick & Pick & Pick & Pick): { applyScenarioCoverageClaim: (editor: EditorStore, claim: ScenarioCoverageClaim) => ApplyCoverageResult; setScenarioCoverageClaims: (claims: readonly ScenarioCoverageClaim[]) => void; getScenarioCoverageClaims: () => readonly ScenarioCoverageClaim[]; coverageClaimsForScreen: (screenId: string) => readonly ScenarioCoverageClaim[]; coverageBadgesForComponentProp: (screenId: string, componentName: string, prop: string) => readonly string[]; }; export type ScenarioCoverage = ReturnType;