Files
Imhotep/packages/imhotep-reporter/src/codes.ts
T

1342 lines
48 KiB
TypeScript

/**
* Canonical diagnostic code registry for Imhotep.
*
* Every diagnostic code in the system is declared here with its
* canonical severity, category, and human-readable message template.
*
* Invariant: no package may invent a diagnostic code that is not
* registered in this file. Adding a new code requires adding it
* here first.
*
* NOTE: This file is kept for backward compatibility. The canonical
* type definition lives in imhotep-core/src/diagnostics.ts.
*/
import type { DiagnosticCode } from 'imhotep-core';
export type Severity = 'error' | 'warning' | 'info';
export type Category =
| 'parse-error'
| 'validation-error'
| 'resolution-error'
| 'extraction-error'
| 'contract-failure'
| 'indeterminate-result'
| 'internal-error';
export interface CodeEntry {
code: DiagnosticCode;
severity: Severity;
category: Category;
message: string;
fixHints: string[];
}
// ---------------------------------------------------------------------------
// Parse errors
// ---------------------------------------------------------------------------
export const IMH_PARSE_UNEXPECTED_TOKEN = 'IMH_PARSE_UNEXPECTED_TOKEN' as const;
export const IMH_PARSE_INVALID_SYNTAX = 'IMH_PARSE_INVALID_SYNTAX' as const;
export const IMH_PARSE_UNTERMINATED_BLOCK = 'IMH_PARSE_UNTERMINATED_BLOCK' as const;
export const IMH_PARSE_ERROR = 'IMH_PARSE_ERROR' as const;
export const IMH_PARSE_IS_KEYWORD = 'IMH_PARSE_IS_KEYWORD' as const;
export const IMH_PARSE_MISSING_QUOTES = 'IMH_PARSE_MISSING_QUOTES' as const;
export const IMH_PARSE_WRONG_QUOTE_STYLE = 'IMH_PARSE_WRONG_QUOTE_STYLE' as const;
export const IMH_PARSE_MISSING_UNIT = 'IMH_PARSE_MISSING_UNIT' as const;
// ---------------------------------------------------------------------------
// Validation errors
// ---------------------------------------------------------------------------
export const IMH_VALID_ILLEGAL_RELATION_OPTION = 'IMH_VALID_ILLEGAL_RELATION_OPTION' as const;
export const IMH_VALID_INVALID_UNIT = 'IMH_VALID_INVALID_UNIT' as const;
export const IMH_VALID_INVALID_STATE_TIMELINE = 'IMH_VALID_INVALID_STATE_TIMELINE' as const;
export const IMH_VALID_INVALID_ENV_GUARD = 'IMH_VALID_INVALID_ENV_GUARD' as const;
export const IMH_VALID_INVALID_QUANTIFIER_NESTING = 'IMH_VALID_INVALID_QUANTIFIER_NESTING' as const;
export const IMH_VALID_CONTRADICTION = 'IMH_VALID_CONTRADICTION' as const;
// ---------------------------------------------------------------------------
// Resolution errors
// ---------------------------------------------------------------------------
export const IMH_SELECTOR_ZERO_MATCHES = 'IMH_SELECTOR_ZERO_MATCHES' as const;
export const IMH_SELECTOR_AMBIGUOUS = 'IMH_SELECTOR_AMBIGUOUS' as const;
export const IMH_SELECTOR_NO_MATCH = 'IMH_SELECTOR_NO_MATCH' as const;
export const IMH_SELECTOR_RESOLUTION_FAILED = 'IMH_SELECTOR_RESOLUTION_FAILED' as const;
export const IMH_FRAME_AMBIGUOUS = 'IMH_FRAME_AMBIGUOUS' as const;
export const IMH_FRAME_UNSUPPORTED = 'IMH_FRAME_UNSUPPORTED' as const;
export const IMH_TOPOLOGY_UNSUPPORTED = 'IMH_TOPOLOGY_UNSUPPORTED' as const;
export const IMH_STATE_MATERIALIZATION_FAILED = 'IMH_STATE_MATERIALIZATION_FAILED' as const;
// ---------------------------------------------------------------------------
// Extraction errors
// ---------------------------------------------------------------------------
export const IMH_EXTRACT_PARTIAL = 'IMH_EXTRACT_PARTIAL' as const;
export const IMH_EXTRACT_UNAVAILABLE_FACT = 'IMH_EXTRACT_UNAVAILABLE_FACT' as const;
export const IMH_EXTRACT_PROTOCOL_ERROR = 'IMH_EXTRACT_PROTOCOL_ERROR' as const;
// ---------------------------------------------------------------------------
// CDP errors
// ---------------------------------------------------------------------------
export const IMH_CDP_SESSION_ATTACH_FAILED = 'IMH_CDP_SESSION_ATTACH_FAILED' as const;
export const IMH_DOM_EXTRACTION_FAILED = 'IMH_DOM_EXTRACTION_FAILED' as const;
export const IMH_SELECTOR_RESOLUTION_FAILED_CDP = 'IMH_SELECTOR_RESOLUTION_FAILED' as const;
export const IMH_BOX_MODEL_PARTIAL = 'IMH_BOX_MODEL_PARTIAL' as const;
export const IMH_BOX_MODEL_FAILED = 'IMH_BOX_MODEL_FAILED' as const;
export const IMH_VISUAL_BOX_PARTIAL = 'IMH_VISUAL_BOX_PARTIAL' as const;
export const IMH_VISUAL_BOX_FAILED = 'IMH_VISUAL_BOX_FAILED' as const;
export const IMH_FRAGMENT_PARTIAL = 'IMH_FRAGMENT_PARTIAL' as const;
export const IMH_FRAGMENT_FAILED = 'IMH_FRAGMENT_FAILED' as const;
export const IMH_TRANSFORM_PARTIAL = 'IMH_TRANSFORM_PARTIAL' as const;
export const IMH_TRANSFORM_FAILED = 'IMH_TRANSFORM_FAILED' as const;
export const IMH_STYLE_PARTIAL = 'IMH_STYLE_PARTIAL' as const;
export const IMH_STYLE_FAILED = 'IMH_STYLE_FAILED' as const;
export const IMH_TOPOLOGY_PARTIAL = 'IMH_TOPOLOGY_PARTIAL' as const;
export const IMH_TOPOLOGY_FAILED = 'IMH_TOPOLOGY_FAILED' as const;
// ---------------------------------------------------------------------------
// Extractor planner errors
// ---------------------------------------------------------------------------
export const IMH_EXTRACTOR_EMPTY_SELECTOR = 'IMH_EXTRACTOR_EMPTY_SELECTOR' as const;
export const IMH_EXTRACTOR_MISSING_ENV_GUARD = 'IMH_EXTRACTOR_MISSING_ENV_GUARD' as const;
export const IMH_EXTRACTOR_UNRESOLVED_ENV_GUARD = 'IMH_EXTRACTOR_UNRESOLVED_ENV_GUARD' as const;
export const IMH_EXTRACTOR_MISSING_STATE = 'IMH_EXTRACTOR_MISSING_STATE' as const;
export const IMH_EXTRACTOR_UNRESOLVED_STATE = 'IMH_EXTRACTOR_UNRESOLVED_STATE' as const;
export const IMH_EXTRACTOR_UNSUPPORTED_STATE = 'IMH_EXTRACTOR_UNSUPPORTED_STATE' as const;
export const IMH_EXTRACTOR_NON_STATIC_TIMELINE = 'IMH_EXTRACTOR_NON_STATIC_TIMELINE' as const;
export const IMH_EXTRACTOR_UNSUPPORTED_CLAUSE_TYPE = 'IMH_EXTRACTOR_UNSUPPORTED_CLAUSE_TYPE' as const;
// ---------------------------------------------------------------------------
// Contract failures
// ---------------------------------------------------------------------------
export const IMH_RELATION_LEFT_OF_FAILED = 'IMH_RELATION_LEFT_OF_FAILED' as const;
export const IMH_RELATION_RIGHT_OF_FAILED = 'IMH_RELATION_RIGHT_OF_FAILED' as const;
export const IMH_RELATION_ABOVE_FAILED = 'IMH_RELATION_ABOVE_FAILED' as const;
export const IMH_RELATION_BELOW_FAILED = 'IMH_RELATION_BELOW_FAILED' as const;
export const IMH_RELATION_ALIGNED_FAILED = 'IMH_RELATION_ALIGNED_FAILED' as const;
export const IMH_RELATION_CENTERED_FAILED = 'IMH_RELATION_CENTERED_FAILED' as const;
export const IMH_RELATION_INSIDE_FAILED = 'IMH_RELATION_INSIDE_FAILED' as const;
export const IMH_RELATION_CONTAINS_FAILED = 'IMH_RELATION_CONTAINS_FAILED' as const;
export const IMH_RELATION_OVERLAPS_FAILED = 'IMH_RELATION_OVERLAPS_FAILED' as const;
export const IMH_RELATION_BESIDE_FAILED = 'IMH_RELATION_BESIDE_FAILED' as const;
export const IMH_RELATION_ADJACENT_FAILED = 'IMH_RELATION_ADJACENT_FAILED' as const;
export const IMH_RELATION_NEAR_FAILED = 'IMH_RELATION_NEAR_FAILED' as const;
export const IMH_RELATION_FAILED = 'IMH_RELATION_FAILED' as const;
export const IMH_ALIGNMENT_FAILED = 'IMH_ALIGNMENT_FAILED' as const;
export const IMH_SIZE_AT_LEAST_FAILED = 'IMH_SIZE_AT_LEAST_FAILED' as const;
export const IMH_SIZE_AT_MOST_FAILED = 'IMH_SIZE_AT_MOST_FAILED' as const;
export const IMH_SIZE_BETWEEN_FAILED = 'IMH_SIZE_BETWEEN_FAILED' as const;
export const IMH_TOPOLOGY_CLIPPED_FAILED = 'IMH_TOPOLOGY_CLIPPED_FAILED' as const;
export const IMH_TOPOLOGY_STACKING_FAILED = 'IMH_TOPOLOGY_STACKING_FAILED' as const;
export const IMH_VISIBILITY_FAILED = 'IMH_VISIBILITY_FAILED' as const;
export const IMH_PREDICATE_FAILED = 'IMH_PREDICATE_FAILED' as const;
// ---------------------------------------------------------------------------
// Cardinality failures
// ---------------------------------------------------------------------------
export const IMH_CARDINALITY_EXACTLYONE_FAILED = 'IMH_CARDINALITY_EXACTLYONE_FAILED' as const;
export const IMH_CARDINALITY_ATLEASTN_FAILED = 'IMH_CARDINALITY_ATLEASTN_FAILED' as const;
export const IMH_CARDINALITY_ATMOSTN_FAILED = 'IMH_CARDINALITY_ATMOSTN_FAILED' as const;
// ---------------------------------------------------------------------------
// Indeterminate results
// ---------------------------------------------------------------------------
export const IMH_INDETERMINATE_MISSING_FACT = 'IMH_INDETERMINATE_MISSING_FACT' as const;
export const IMH_INDETERMINATE_UNSTABLE_INPUT = 'IMH_INDETERMINATE_UNSTABLE_INPUT' as const;
// ---------------------------------------------------------------------------
// Internal errors
// ---------------------------------------------------------------------------
export const IMH_INTERNAL_UNKNOWN_CLAUSE_KIND = 'IMH_INTERNAL_UNKNOWN_CLAUSE_KIND' as const;
export const IMH_INTERNAL_EVALUATION_EXCEPTION = 'IMH_INTERNAL_EVALUATION_EXCEPTION' as const;
export const IMH_FEATURE_NOT_YET_IMPLEMENTED = 'IMH_FEATURE_NOT_YET_IMPLEMENTED' as const;
export const IMH_UNKNOWN_FAILURE = 'IMH_UNKNOWN_FAILURE' as const;
// ---------------------------------------------------------------------------
// Solver / logic errors
// ---------------------------------------------------------------------------
export const IMH_LOGIC_UNKNOWN_FORMULA_KIND = 'IMH_LOGIC_UNKNOWN_FORMULA_KIND' as const;
export const IMH_LOGIC_DOMAIN_UNRESOLVED = 'IMH_LOGIC_DOMAIN_UNRESOLVED' as const;
export const IMH_LOGIC_VACUOUS_FORALL = 'IMH_LOGIC_VACUOUS_FORALL' as const;
export const IMH_LOGIC_EMPTY_DOMAIN_EXISTS = 'IMH_LOGIC_EMPTY_DOMAIN_EXISTS' as const;
export const IMH_LOGIC_PREDICATE_MISSING = 'IMH_LOGIC_PREDICATE_MISSING' as const;
export const IMH_LOGIC_UNBOUND_VARIABLE = 'IMH_LOGIC_UNBOUND_VARIABLE' as const;
export const IMH_LOGIC_UNSUPPORTED_TERM = 'IMH_LOGIC_UNSUPPORTED_TERM' as const;
export const IMH_LOGIC_UNKNOWN_NODE = 'IMH_LOGIC_UNKNOWN_NODE' as const;
export const IMH_LOGIC_ARITY_MISMATCH = 'IMH_LOGIC_ARITY_MISMATCH' as const;
export const IMH_LOGIC_UNKNOWN_PREDICATE = 'IMH_LOGIC_UNKNOWN_PREDICATE' as const;
export const IMH_LOGIC_FREE_VARIABLE = 'IMH_LOGIC_FREE_VARIABLE' as const;
export const IMH_LOGIC_EMPTY_DOMAIN = 'IMH_LOGIC_EMPTY_DOMAIN' as const;
// ---------------------------------------------------------------------------
// Solver engine errors
// ---------------------------------------------------------------------------
export const IMH_EVALUATOR_MISSING = 'IMH_EVALUATOR_MISSING' as const;
export const IMH_EVALUATOR_EXCEPTION = 'IMH_EVALUATOR_EXCEPTION' as const;
// ---------------------------------------------------------------------------
// Quantifier errors
// ---------------------------------------------------------------------------
export const IMH_QUANTIFIER_NO_SUBCLAUSES = 'IMH_QUANTIFIER_NO_SUBCLAUSES' as const;
export const IMH_PAIRWISE_INSUFFICIENT = 'IMH_PAIRWISE_INSUFFICIENT' as const;
export const IMH_UNKNOWN_QUANTIFIER = 'IMH_UNKNOWN_QUANTIFIER' as const;
// ---------------------------------------------------------------------------
// Fact observation diagnostics (used for rich contract-failure messages)
// ---------------------------------------------------------------------------
export const IMH_FACT_OBSERVED_GAP = 'IMH_FACT_OBSERVED_GAP' as const;
export const IMH_FACT_OBSERVED_SIZE = 'IMH_FACT_OBSERVED_SIZE' as const;
export const IMH_FACT_OBSERVED_TOPOLOGY = 'IMH_FACT_OBSERVED_TOPOLOGY' as const;
// ---------------------------------------------------------------------------
// Property-run diagnostics
// ---------------------------------------------------------------------------
export const IMH_ENUMERATED_RUN_ERROR = 'IMH_ENUMERATED_RUN_ERROR' as const;
export const IMH_SAMPLED_RUN_ERROR = 'IMH_SAMPLED_RUN_ERROR' as const;
export const IMH_PROPERTY_RUN_FAILED = 'IMH_PROPERTY_RUN_FAILED' as const;
export const IMH_PROPERTY_PASSED = 'IMH_PROPERTY_PASSED' as const;
export const IMH_PROPERTY_FAILED = 'IMH_PROPERTY_FAILED' as const;
export const IMH_PROPERTY_REPLAY = 'IMH_PROPERTY_REPLAY' as const;
export const IMH_PROPERTY_SHRUNK = 'IMH_PROPERTY_SHRUNK' as const;
export const IMH_ENUMERATED_PASSED = 'IMH_ENUMERATED_PASSED' as const;
export const IMH_ENUMERATED_FAILED = 'IMH_ENUMERATED_FAILED' as const;
// ---------------------------------------------------------------------------
// Reporter internal diagnostics
// ---------------------------------------------------------------------------
export const IMH_FRAME_CONTEXT = 'IMH_FRAME_CONTEXT' as const;
export const IMH_WITNESS_ENV = 'IMH_WITNESS_ENV' as const;
export const IMH_WITNESS_SNAPSHOT = 'IMH_WITNESS_SNAPSHOT' as const;
// ---------------------------------------------------------------------------
// Registry
// ---------------------------------------------------------------------------
const REGISTRY: Map<string, CodeEntry> = new Map([
// Parse
[IMH_PARSE_UNEXPECTED_TOKEN, {
code: IMH_PARSE_UNEXPECTED_TOKEN,
severity: 'error',
category: 'parse-error',
message: 'Unexpected token in input.',
fixHints: [
'Check for misplaced punctuation or keywords.',
'Selectors must be single-quoted strings, e.g. \'[data-testid="x"]\'.',
'Use relation keywords directly without "is": e.g. \'a\' leftOf \'b\'.',
],
}],
[IMH_PARSE_INVALID_SYNTAX, {
code: IMH_PARSE_INVALID_SYNTAX,
severity: 'error',
category: 'parse-error',
message: 'Invalid syntax.',
fixHints: [
'Ensure selectors are wrapped in single quotes.',
'Use valid relation keywords: leftOf, rightOf, above, below, alignedWith, centeredWithin, inside, contains, overlaps.',
'Gap values require units: e.g. gap 8px or gap 8px..16px.',
'Remove the keyword "is": write \'.a\' leftOf \'.b\' instead of \'.a\' is leftOf \'.b\'.',
],
}],
[IMH_PARSE_UNTERMINATED_BLOCK, {
code: IMH_PARSE_UNTERMINATED_BLOCK,
severity: 'error',
category: 'parse-error',
message: 'Unterminated block.',
fixHints: [
'Close the block with proper indentation (2 or 4 spaces).',
'Ensure every opening keyword (all, any, none, forAll, exists) has a matching body.',
'Example: all \'.item\' leftOf \'.sidebar\'',
],
}],
[IMH_PARSE_ERROR, {
code: IMH_PARSE_ERROR,
severity: 'error',
category: 'parse-error',
message: 'Parse error.',
fixHints: [
'Selectors must be single-quoted strings, e.g. \'[data-testid="x"]\'.',
'Use relation keywords directly without "is": e.g. \'a\' leftOf \'b\'.',
'Gap values require units: e.g. gap 8px.',
],
}],
[IMH_PARSE_IS_KEYWORD, {
code: IMH_PARSE_IS_KEYWORD,
severity: 'error',
category: 'parse-error',
message: 'Unexpected keyword "is".',
fixHints: [
'Remove "is" and write the relation directly, e.g. \'.a\' leftOf \'.b\'.',
],
}],
[IMH_PARSE_MISSING_QUOTES, {
code: IMH_PARSE_MISSING_QUOTES,
severity: 'error',
category: 'parse-error',
message: 'Selector must be wrapped in single quotes.',
fixHints: [
'Wrap selectors in single quotes: \'.class\' instead of .class.',
],
}],
[IMH_PARSE_WRONG_QUOTE_STYLE, {
code: IMH_PARSE_WRONG_QUOTE_STYLE,
severity: 'error',
category: 'parse-error',
message: 'Double quotes are not allowed.',
fixHints: [
'Use single quotes: \'value\' instead of "value".',
],
}],
[IMH_PARSE_MISSING_UNIT, {
code: IMH_PARSE_MISSING_UNIT,
severity: 'error',
category: 'parse-error',
message: 'Missing unit on gap value.',
fixHints: [
'Add a unit, e.g. gap 8px or gap 8px..16px.',
],
}],
// Validation
[IMH_VALID_ILLEGAL_RELATION_OPTION, {
code: IMH_VALID_ILLEGAL_RELATION_OPTION,
severity: 'error',
category: 'validation-error',
message: 'Illegal relation option.',
fixHints: [
'Check the options passed to the relation.',
'Common options: minGap, maxGap, tolerance, axis, inStackingContext.',
],
}],
[IMH_VALID_INVALID_UNIT, {
code: IMH_VALID_INVALID_UNIT,
severity: 'error',
category: 'validation-error',
message: 'Invalid unit.',
fixHints: [
'Valid units: px, em, rem, %, jnd, vw, vh.',
'Example: gap 8px, tolerance 2jnd.',
'Ensure the unit is appended directly to the number without spaces.',
],
}],
[IMH_VALID_INVALID_STATE_TIMELINE, {
code: IMH_VALID_INVALID_STATE_TIMELINE,
severity: 'error',
category: 'validation-error',
message: 'Invalid state or timeline reference.',
fixHints: [
'Valid states: default, hover, focus, focusVisible, active.',
'Use the exact state name; focus-visible kebab-case is not supported (use focusVisible).',
],
}],
[IMH_VALID_INVALID_ENV_GUARD, {
code: IMH_VALID_INVALID_ENV_GUARD,
severity: 'error',
category: 'validation-error',
message: 'Invalid environment guard.',
fixHints: [
'Valid environment axes: viewport, colorScheme, pointer, reducedMotion, deviceScaleFactor, locale, writingMode.',
'Example: guard viewport width >= 768.',
],
}],
[IMH_VALID_INVALID_QUANTIFIER_NESTING, {
code: IMH_VALID_INVALID_QUANTIFIER_NESTING,
severity: 'error',
category: 'validation-error',
message: 'Invalid quantifier nesting.',
fixHints: [
'Flatten nested quantifiers or restructure the assertion.',
'Use inline quantifiers: all, any, none before the assertion.',
'Example: all \'.item\' leftOf \'.sidebar\'',
],
}],
[IMH_VALID_CONTRADICTION, {
code: IMH_VALID_CONTRADICTION,
severity: 'error',
category: 'validation-error',
message: 'Contradiction detected.',
fixHints: [
'minGap cannot be greater than maxGap.',
'Adjust the bounds so that minGap <= maxGap.',
'Example: gap 8px..16px (minGap=8, maxGap=16).',
],
}],
// Resolution
[IMH_SELECTOR_ZERO_MATCHES, {
code: IMH_SELECTOR_ZERO_MATCHES,
severity: 'error',
category: 'resolution-error',
message: 'Selector matched 0 elements.',
fixHints: [
'Check that the selector is valid and matches an element in the DOM.',
'Use ui.extract(selector) to verify the selector resolves to at least one element.',
'Ensure the page is fully loaded before running assertions.',
],
}],
[IMH_SELECTOR_AMBIGUOUS, {
code: IMH_SELECTOR_AMBIGUOUS,
severity: 'warning',
category: 'resolution-error',
message: 'Selector is ambiguous.',
fixHints: [
'Make the selector more specific (e.g. add a parent class or use an attribute).',
'Consider using getByTestId("unique-id") for stable element references.',
'Example: \'[data-testid="submit-button"]\' instead of \'.button\'.',
],
}],
[IMH_SELECTOR_NO_MATCH, {
code: IMH_SELECTOR_NO_MATCH,
severity: 'warning',
category: 'resolution-error',
message: 'Selector matched 0 elements.',
fixHints: [
'Check that the selector is valid and matches an element in the DOM.',
'Use ui.extract(selector) to verify the selector resolves to at least one element.',
],
}],
[IMH_SELECTOR_RESOLUTION_FAILED, {
code: IMH_SELECTOR_RESOLUTION_FAILED,
severity: 'error',
category: 'resolution-error',
message: 'Selector resolution failed.',
fixHints: [
'Use valid CSS selector syntax.',
'Avoid complex pseudo-selectors that CDP cannot resolve.',
'Test the selector in browser DevTools first.',
],
}],
[IMH_FRAME_AMBIGUOUS, {
code: IMH_FRAME_AMBIGUOUS,
severity: 'warning',
category: 'resolution-error',
message: 'Frame reference is ambiguous.',
fixHints: [
'Use a more specific frame selector.',
'Supported frames: viewport, document, element, nearestPositionedAncestor, containingBlock, scrollContainer, namedGridArea, landmark, stackingContextRoot.',
],
}],
[IMH_FRAME_UNSUPPORTED, {
code: IMH_FRAME_UNSUPPORTED,
severity: 'error',
category: 'resolution-error',
message: 'Unsupported frame kind.',
fixHints: [
'Supported frame types: viewport, document, element, nearestPositionedAncestor, containingBlock, scrollContainer, namedGridArea, landmark, stackingContextRoot.',
'Use viewport as the default frame if unsure.',
],
}],
[IMH_TOPOLOGY_UNSUPPORTED, {
code: IMH_TOPOLOGY_UNSUPPORTED,
severity: 'error',
category: 'resolution-error',
message: 'Unsupported topology query.',
fixHints: [
'Supported topology assertions: clippedBy, attachedToScrollContainer, escapeClippingChainOf, inStackingContext.',
],
}],
[IMH_STATE_MATERIALIZATION_FAILED, {
code: IMH_STATE_MATERIALIZATION_FAILED,
severity: 'error',
category: 'resolution-error',
message: 'State materialization failed.',
fixHints: [
'Check that the element exists before applying a state.',
'Ensure the state is supported: default, hover, focus, focusVisible, active.',
'Some states (disabled, checked, expanded) are not yet materializable.',
],
}],
// Extractor planner
[IMH_EXTRACTOR_EMPTY_SELECTOR, {
code: IMH_EXTRACTOR_EMPTY_SELECTOR,
severity: 'error',
category: 'resolution-error',
message: 'Empty selector in extraction plan.',
fixHints: [
'Ensure all assertions have a non-empty subject selector.',
],
}],
[IMH_EXTRACTOR_MISSING_ENV_GUARD, {
code: IMH_EXTRACTOR_MISSING_ENV_GUARD,
severity: 'error',
category: 'resolution-error',
message: 'Missing environment guard.',
fixHints: [
'Add a valid environment guard or remove the conditional assertion.',
],
}],
[IMH_EXTRACTOR_UNRESOLVED_ENV_GUARD, {
code: IMH_EXTRACTOR_UNRESOLVED_ENV_GUARD,
severity: 'error',
category: 'resolution-error',
message: 'Unresolved environment guard.',
fixHints: [
'Check the environment axis name and comparator.',
],
}],
[IMH_EXTRACTOR_MISSING_STATE, {
code: IMH_EXTRACTOR_MISSING_STATE,
severity: 'error',
category: 'resolution-error',
message: 'Missing state reference.',
fixHints: [
'Ensure the state is defined in the state timeline.',
],
}],
[IMH_EXTRACTOR_UNRESOLVED_STATE, {
code: IMH_EXTRACTOR_UNRESOLVED_STATE,
severity: 'error',
category: 'resolution-error',
message: 'Unresolved state reference.',
fixHints: [
'Use a supported state name.',
],
}],
[IMH_EXTRACTOR_UNSUPPORTED_STATE, {
code: IMH_EXTRACTOR_UNSUPPORTED_STATE,
severity: 'error',
category: 'resolution-error',
message: 'Unsupported state.',
fixHints: [
'Supported states: default, hover, focus, focusVisible, active.',
],
}],
[IMH_EXTRACTOR_NON_STATIC_TIMELINE, {
code: IMH_EXTRACTOR_NON_STATIC_TIMELINE,
severity: 'error',
category: 'resolution-error',
message: 'Non-static timeline reference.',
fixHints: [
'Timeline references must be static strings.',
],
}],
[IMH_EXTRACTOR_UNSUPPORTED_CLAUSE_TYPE, {
code: IMH_EXTRACTOR_UNSUPPORTED_CLAUSE_TYPE,
severity: 'error',
category: 'resolution-error',
message: 'Unsupported clause type for extraction.',
fixHints: [
'Use a supported relation or assertion type.',
],
}],
// Extraction
[IMH_EXTRACT_PARTIAL, {
code: IMH_EXTRACT_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Partial extraction; some facts may be missing.',
fixHints: [
'Check that the page is fully loaded before running assertions.',
'Verify selectors are valid CSS selectors or semantic references.',
'Use ui.extract(selector) to debug selector resolution.',
],
}],
[IMH_EXTRACT_UNAVAILABLE_FACT, {
code: IMH_EXTRACT_UNAVAILABLE_FACT,
severity: 'error',
category: 'extraction-error',
message: 'Required fact is unavailable.',
fixHints: [
'Run validate() before assertions to check for unsupported relations or missing elements.',
'Ensure the page is loaded and selectors resolve correctly.',
],
}],
[IMH_EXTRACT_PROTOCOL_ERROR, {
code: IMH_EXTRACT_PROTOCOL_ERROR,
severity: 'error',
category: 'extraction-error',
message: 'Extraction protocol error.',
fixHints: [
'Verify the page is fully loaded before running assertions.',
'Check that selectors are valid CSS selectors or semantic references.',
'Use ui.extract(selector) to debug selector resolution.',
],
}],
// CDP
[IMH_CDP_SESSION_ATTACH_FAILED, {
code: IMH_CDP_SESSION_ATTACH_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Failed to attach CDP session.',
fixHints: [
'Restart the browser process.',
'Check that the Playwright version matches the browser version.',
'Ensure the page was launched with a Chromium-based browser.',
],
}],
[IMH_DOM_EXTRACTION_FAILED, {
code: IMH_DOM_EXTRACTION_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'DOM extraction failed.',
fixHints: [
'Check that the page is fully loaded.',
'Wait for dynamic content to render before running assertions.',
],
}],
[IMH_BOX_MODEL_PARTIAL, {
code: IMH_BOX_MODEL_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Box model partially extracted.',
fixHints: [
'Check that the element is visible and not display:none.',
'Ensure the element is in the DOM and not detached.',
],
}],
[IMH_BOX_MODEL_FAILED, {
code: IMH_BOX_MODEL_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Box model extraction failed.',
fixHints: [
'Check that the element is visible (not display:none or visibility:hidden).',
'Ensure the element is attached to the DOM.',
'Try scrolling the element into view before asserting.',
],
}],
[IMH_VISUAL_BOX_PARTIAL, {
code: IMH_VISUAL_BOX_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Visual box partially extracted.',
fixHints: [
'Check that the element is visible and not display:none.',
],
}],
[IMH_VISUAL_BOX_FAILED, {
code: IMH_VISUAL_BOX_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Visual box extraction failed.',
fixHints: [
'Check that the element is visible and attached to the DOM.',
],
}],
[IMH_FRAGMENT_PARTIAL, {
code: IMH_FRAGMENT_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Fragment partially extracted.',
fixHints: [
'Check that the element has visible text content.',
],
}],
[IMH_FRAGMENT_FAILED, {
code: IMH_FRAGMENT_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Fragment extraction failed.',
fixHints: [
'Check that the element is visible and has text content.',
],
}],
[IMH_TRANSFORM_PARTIAL, {
code: IMH_TRANSFORM_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Transform partially extracted.',
fixHints: [
'Check CSS transform properties on the element.',
],
}],
[IMH_TRANSFORM_FAILED, {
code: IMH_TRANSFORM_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Transform extraction failed.',
fixHints: [
'Check CSS transform properties on the element.',
],
}],
[IMH_STYLE_PARTIAL, {
code: IMH_STYLE_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Style partially extracted.',
fixHints: [
'Check that computed styles are accessible for the element.',
],
}],
[IMH_STYLE_FAILED, {
code: IMH_STYLE_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Style extraction failed.',
fixHints: [
'Check that computed styles are accessible for the element.',
],
}],
[IMH_TOPOLOGY_PARTIAL, {
code: IMH_TOPOLOGY_PARTIAL,
severity: 'warning',
category: 'extraction-error',
message: 'Topology partially extracted.',
fixHints: [
'Check CSS properties that affect topology (position, overflow, contain, z-index).',
],
}],
[IMH_TOPOLOGY_FAILED, {
code: IMH_TOPOLOGY_FAILED,
severity: 'error',
category: 'extraction-error',
message: 'Topology extraction failed.',
fixHints: [
'Check CSS properties that affect topology (position, overflow, contain, z-index).',
],
}],
// Contract failures
[IMH_RELATION_LEFT_OF_FAILED, {
code: IMH_RELATION_LEFT_OF_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'leftOf relation failed.',
fixHints: [
'Inspect the layout in browser devtools and adjust element positions or gap thresholds.',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_RIGHT_OF_FAILED, {
code: IMH_RELATION_RIGHT_OF_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'rightOf relation failed.',
fixHints: [
'Inspect the layout in browser devtools and adjust element positions or gap thresholds.',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_ABOVE_FAILED, {
code: IMH_RELATION_ABOVE_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'above relation failed.',
fixHints: [
'Inspect the layout in browser devtools and adjust element positions or gap thresholds.',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_BELOW_FAILED, {
code: IMH_RELATION_BELOW_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'below relation failed.',
fixHints: [
'Inspect the layout in browser devtools and adjust element positions or gap thresholds.',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_ALIGNED_FAILED, {
code: IMH_RELATION_ALIGNED_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'aligned relation failed.',
fixHints: [
'Check that the elements share the same alignment axis (left, right, top, bottom).',
'Use ui.extract() to verify element positions.',
],
}],
[IMH_RELATION_CENTERED_FAILED, {
code: IMH_RELATION_CENTERED_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'centered relation failed.',
fixHints: [
'Check that the subject element is centered within the reference container.',
'Verify margins, padding, and container dimensions with ui.extract().',
],
}],
[IMH_RELATION_INSIDE_FAILED, {
code: IMH_RELATION_INSIDE_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'inside relation failed.',
fixHints: [
'Check that the subject fits entirely within the reference container.',
'Verify padding, border, and overflow settings on the container.',
'Use ui.extract() to compare subject and container rects.',
],
}],
[IMH_RELATION_CONTAINS_FAILED, {
code: IMH_RELATION_CONTAINS_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'contains relation failed.',
fixHints: [
'Check that the container is large enough to fully contain the subject.',
'Verify padding, border, and overflow settings.',
],
}],
[IMH_RELATION_OVERLAPS_FAILED, {
code: IMH_RELATION_OVERLAPS_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'overlaps relation failed.',
fixHints: [
'Check that the elements actually overlap in the layout.',
'Verify z-index and positioning if elements should stack.',
],
}],
[IMH_RELATION_BESIDE_FAILED, {
code: IMH_RELATION_BESIDE_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'beside relation failed.',
fixHints: [
'Check that the elements are positioned beside each other (leftOf or rightOf).',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_ADJACENT_FAILED, {
code: IMH_RELATION_ADJACENT_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'adjacent relation failed.',
fixHints: [
'Check that the elements are touching or very close to each other.',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_NEAR_FAILED, {
code: IMH_RELATION_NEAR_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'near relation failed.',
fixHints: [
'Check that the elements are within the expected proximity.',
'Use ui.extract() to verify element rects.',
],
}],
[IMH_RELATION_FAILED, {
code: IMH_RELATION_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Relation assertion failed.',
fixHints: [
'Verify the expected layout and consider adjusting thresholds.',
'Check element positions using ui.extract(selector) to inspect actual geometry.',
],
}],
[IMH_ALIGNMENT_FAILED, {
code: IMH_ALIGNMENT_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'alignment assertion failed.',
fixHints: [
'Check the axis option (centerX, centerY, left, right, top, bottom).',
'Verify element positions with ui.extract().',
],
}],
[IMH_SIZE_AT_LEAST_FAILED, {
code: IMH_SIZE_AT_LEAST_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'size at-least assertion failed.',
fixHints: [
'Check the element dimensions with ui.extract() and adjust the expected size or CSS.',
'For touch targets, ensure width and height are at least 44px.',
],
}],
[IMH_SIZE_AT_MOST_FAILED, {
code: IMH_SIZE_AT_MOST_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'size at-most assertion failed.',
fixHints: [
'Check the element dimensions with ui.extract() and adjust the expected size or CSS.',
'Verify the element is not growing unexpectedly due to content.',
],
}],
[IMH_SIZE_BETWEEN_FAILED, {
code: IMH_SIZE_BETWEEN_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'size between assertion failed.',
fixHints: [
'Check the element dimensions with ui.extract().',
'Ensure the size falls within the specified min and max bounds.',
],
}],
[IMH_TOPOLOGY_CLIPPED_FAILED, {
code: IMH_TOPOLOGY_CLIPPED_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'clipping topology assertion failed.',
fixHints: [
'Check overflow and clip properties on ancestor containers.',
'Verify the element is not clipped by a parent with overflow:hidden.',
],
}],
[IMH_TOPOLOGY_STACKING_FAILED, {
code: IMH_TOPOLOGY_STACKING_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'stacking context assertion failed.',
fixHints: [
'Check z-index and positioning (relative, absolute, fixed) of the element and its ancestors.',
'Ensure a new stacking context is created when expected (e.g. opacity < 1, transform, isolation).',
],
}],
[IMH_VISIBILITY_FAILED, {
code: IMH_VISIBILITY_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'visibility assertion failed.',
fixHints: [
'Check that the element is not hidden by display:none, visibility:hidden, or opacity:0.',
'Ensure the element is in the viewport and not clipped.',
],
}],
[IMH_PREDICATE_FAILED, {
code: IMH_PREDICATE_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Predicate evaluation failed.',
fixHints: [
'Verify the expected layout and consider adjusting thresholds.',
'Check element positions using ui.extract(selector) to inspect actual geometry.',
],
}],
// Cardinality
[IMH_CARDINALITY_EXACTLYONE_FAILED, {
code: IMH_CARDINALITY_EXACTLYONE_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Cardinality exactly-one assertion failed.',
fixHints: [
'Verify the selector matches exactly one element.',
'Use a more specific selector or adjust the cardinality bound.',
],
}],
[IMH_CARDINALITY_ATLEASTN_FAILED, {
code: IMH_CARDINALITY_ATLEASTN_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Cardinality at-least-N assertion failed.',
fixHints: [
'Verify the selector matches at least the expected number of elements.',
'Use a more specific selector or adjust the cardinality bound.',
],
}],
[IMH_CARDINALITY_ATMOSTN_FAILED, {
code: IMH_CARDINALITY_ATMOSTN_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Cardinality at-most-N assertion failed.',
fixHints: [
'Verify the selector matches at most the expected number of elements.',
'Use a more specific selector or adjust the cardinality bound.',
],
}],
// Indeterminate
[IMH_INDETERMINATE_MISSING_FACT, {
code: IMH_INDETERMINATE_MISSING_FACT,
severity: 'warning',
category: 'indeterminate-result',
message: 'Result is indeterminate because a required fact is missing.',
fixHints: [
'Check that selectors resolve and the page is loaded.',
'Run validate() to verify the assertion is supported.',
],
}],
[IMH_INDETERMINATE_UNSTABLE_INPUT, {
code: IMH_INDETERMINATE_UNSTABLE_INPUT,
severity: 'warning',
category: 'indeterminate-result',
message: 'Result is indeterminate because input is unstable.',
fixHints: [
'Wait for animations, lazy-loaded content, or async data to settle before asserting.',
'Use a stable selector that does not depend on dynamic content.',
],
}],
// Internal
[IMH_INTERNAL_UNKNOWN_CLAUSE_KIND, {
code: IMH_INTERNAL_UNKNOWN_CLAUSE_KIND,
severity: 'error',
category: 'internal-error',
message: 'Unknown clause kind.',
fixHints: [
'Update Imhotep to the latest version.',
'Use a supported relation or predicate.',
'Supported relations: leftOf, rightOf, above, below, alignedWith, centeredWithin, inside, contains, overlaps.',
],
}],
[IMH_INTERNAL_EVALUATION_EXCEPTION, {
code: IMH_INTERNAL_EVALUATION_EXCEPTION,
severity: 'error',
category: 'internal-error',
message: 'Evaluation exception.',
fixHints: [
'Report this as a bug with a minimal reproduction.',
'Try simplifying the assertion or splitting it into smaller parts.',
],
}],
[IMH_FEATURE_NOT_YET_IMPLEMENTED, {
code: IMH_FEATURE_NOT_YET_IMPLEMENTED,
severity: 'error',
category: 'internal-error',
message: 'Feature not yet implemented.',
fixHints: [
'This assertion uses a relation that is documented but not yet implemented.',
'Use a supported relation such as leftOf, rightOf, above, below, inside, overlaps, alignedWith, or centeredWithin.',
],
}],
[IMH_UNKNOWN_FAILURE, {
code: IMH_UNKNOWN_FAILURE,
severity: 'error',
category: 'internal-error',
message: 'Unknown failure.',
fixHints: [
'Report this as a bug with a minimal reproduction.',
],
}],
// Solver / logic
[IMH_LOGIC_UNKNOWN_FORMULA_KIND, {
code: IMH_LOGIC_UNKNOWN_FORMULA_KIND,
severity: 'error',
category: 'internal-error',
message: 'Unknown formula kind encountered by solver.',
fixHints: [
'Simplify the assertion to use basic relations.',
'Avoid compound formulas with and/or/implications until supported.',
],
}],
[IMH_LOGIC_DOMAIN_UNRESOLVED, {
code: IMH_LOGIC_DOMAIN_UNRESOLVED,
severity: 'error',
category: 'internal-error',
message: 'Solver could not resolve a formula domain.',
fixHints: [
'Check that selectors are valid and resolve to at least one element.',
'Use ui.extract(selector) to verify selector resolution.',
],
}],
[IMH_LOGIC_VACUOUS_FORALL, {
code: IMH_LOGIC_VACUOUS_FORALL,
severity: 'info',
category: 'internal-error',
message: 'Forall over empty domain is vacuously true.',
fixHints: [
'Verify the selector is intended to match an empty set.',
],
}],
[IMH_LOGIC_EMPTY_DOMAIN_EXISTS, {
code: IMH_LOGIC_EMPTY_DOMAIN_EXISTS,
severity: 'info',
category: 'internal-error',
message: 'Exists over empty domain is false.',
fixHints: [
'Verify the selector is intended to match an empty set.',
],
}],
[IMH_LOGIC_PREDICATE_MISSING, {
code: IMH_LOGIC_PREDICATE_MISSING,
severity: 'error',
category: 'internal-error',
message: 'Solver predicate is missing or unsupported.',
fixHints: [
'Use a supported predicate.',
'Supported predicates: leftOf, rightOf, above, below, alignedWith, centeredWithin, inside, contains, overlaps, atLeast, atMost, between.',
],
}],
[IMH_LOGIC_UNBOUND_VARIABLE, {
code: IMH_LOGIC_UNBOUND_VARIABLE,
severity: 'error',
category: 'internal-error',
message: 'Unbound variable in formula.',
fixHints: [
'Check formula syntax and ensure all variables are bound by a quantifier.',
],
}],
[IMH_LOGIC_UNSUPPORTED_TERM, {
code: IMH_LOGIC_UNSUPPORTED_TERM,
severity: 'error',
category: 'internal-error',
message: 'Unsupported term type in formula.',
fixHints: [
'Simplify the assertion to use basic relations.',
],
}],
[IMH_LOGIC_UNKNOWN_NODE, {
code: IMH_LOGIC_UNKNOWN_NODE,
severity: 'error',
category: 'internal-error',
message: 'Unknown node type in formula.',
fixHints: [
'Simplify the assertion to use basic relations.',
],
}],
[IMH_LOGIC_ARITY_MISMATCH, {
code: IMH_LOGIC_ARITY_MISMATCH,
severity: 'error',
category: 'internal-error',
message: 'Predicate arity mismatch.',
fixHints: [
'Check the number of arguments passed to the predicate.',
],
}],
[IMH_LOGIC_UNKNOWN_PREDICATE, {
code: IMH_LOGIC_UNKNOWN_PREDICATE,
severity: 'error',
category: 'internal-error',
message: 'Unknown predicate.',
fixHints: [
'Use a supported predicate.',
],
}],
[IMH_LOGIC_FREE_VARIABLE, {
code: IMH_LOGIC_FREE_VARIABLE,
severity: 'error',
category: 'internal-error',
message: 'Free variable in formula.',
fixHints: [
'Bind all variables with quantifiers (forAll, exists).',
],
}],
[IMH_LOGIC_EMPTY_DOMAIN, {
code: IMH_LOGIC_EMPTY_DOMAIN,
severity: 'info',
category: 'internal-error',
message: 'Empty domain in formula.',
fixHints: [
'Verify the selector is intended to match an empty set.',
],
}],
// Solver engine
[IMH_EVALUATOR_MISSING, {
code: IMH_EVALUATOR_MISSING,
severity: 'error',
category: 'internal-error',
message: 'Evaluator is missing for clause kind.',
fixHints: [
'Use a supported clause type.',
],
}],
[IMH_EVALUATOR_EXCEPTION, {
code: IMH_EVALUATOR_EXCEPTION,
severity: 'error',
category: 'internal-error',
message: 'Evaluator threw an exception.',
fixHints: [
'Report this as a bug with a minimal reproduction.',
'Try simplifying the assertion.',
],
}],
// Quantifier
[IMH_QUANTIFIER_NO_SUBCLAUSES, {
code: IMH_QUANTIFIER_NO_SUBCLAUSES,
severity: 'error',
category: 'internal-error',
message: 'Quantifier has no subclauses.',
fixHints: [
'Add at least one subclause to the quantifier block.',
],
}],
[IMH_PAIRWISE_INSUFFICIENT, {
code: IMH_PAIRWISE_INSUFFICIENT,
severity: 'error',
category: 'internal-error',
message: 'Insufficient elements for pairwise quantifier.',
fixHints: [
'Ensure the domain has at least two elements for pairwise comparison.',
],
}],
[IMH_UNKNOWN_QUANTIFIER, {
code: IMH_UNKNOWN_QUANTIFIER,
severity: 'error',
category: 'internal-error',
message: 'Unknown quantifier kind.',
fixHints: [
'Use a supported quantifier: all, any, none, forAll, exists.',
],
}],
// Fact observation
[IMH_FACT_OBSERVED_GAP, {
code: IMH_FACT_OBSERVED_GAP,
severity: 'info',
category: 'contract-failure',
message: 'Observed gap between elements.',
fixHints: ['This is an informational observation, no action needed.'],
}],
[IMH_FACT_OBSERVED_SIZE, {
code: IMH_FACT_OBSERVED_SIZE,
severity: 'info',
category: 'contract-failure',
message: 'Observed size of element.',
fixHints: ['This is an informational observation, no action needed.'],
}],
[IMH_FACT_OBSERVED_TOPOLOGY, {
code: IMH_FACT_OBSERVED_TOPOLOGY,
severity: 'info',
category: 'contract-failure',
message: 'Observed topology fact.',
fixHints: ['This is an informational observation, no action needed.'],
}],
// Property run
[IMH_ENUMERATED_RUN_ERROR, {
code: IMH_ENUMERATED_RUN_ERROR,
severity: 'error',
category: 'contract-failure',
message: 'Enumerated property run error.',
fixHints: [
'Check that the property callback does not throw for the reported input.',
],
}],
[IMH_SAMPLED_RUN_ERROR, {
code: IMH_SAMPLED_RUN_ERROR,
severity: 'error',
category: 'contract-failure',
message: 'Sampled property run error.',
fixHints: [
'Check that the property callback does not throw for the reported input.',
],
}],
[IMH_PROPERTY_RUN_FAILED, {
code: IMH_PROPERTY_RUN_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Property run failed.',
fixHints: [
'Review the failing counterexample and replay with the same seed.',
],
}],
[IMH_PROPERTY_PASSED, {
code: IMH_PROPERTY_PASSED,
severity: 'info',
category: 'contract-failure',
message: 'Property passed.',
fixHints: ['No action needed; the property holds for all tested inputs.'],
}],
[IMH_PROPERTY_FAILED, {
code: IMH_PROPERTY_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Property failed.',
fixHints: [
'Review the counterexample and failing clause.',
'Use the reported seed to reproduce the exact failure.',
],
}],
[IMH_PROPERTY_REPLAY, {
code: IMH_PROPERTY_REPLAY,
severity: 'info',
category: 'internal-error',
message: 'Replay metadata.',
fixHints: ['Use the provided seed and case ID to replay this exact run.'],
}],
[IMH_PROPERTY_SHRUNK, {
code: IMH_PROPERTY_SHRUNK,
severity: 'error',
category: 'contract-failure',
message: 'Counterexample shrunk.',
fixHints: [
'The failure was minimized to the smallest reproducible case.',
'Use the reported seed and run index to replay.',
],
}],
[IMH_ENUMERATED_PASSED, {
code: IMH_ENUMERATED_PASSED,
severity: 'info',
category: 'contract-failure',
message: 'Enumerated property passed.',
fixHints: ['No action needed; all enumerated cases passed.'],
}],
[IMH_ENUMERATED_FAILED, {
code: IMH_ENUMERATED_FAILED,
severity: 'error',
category: 'contract-failure',
message: 'Enumerated property failed.',
fixHints: [
'Review the failing case in the enumerated matrix.',
'Use the reported environment case ID to reproduce.',
],
}],
// Reporter internal
[IMH_FRAME_CONTEXT, {
code: IMH_FRAME_CONTEXT,
severity: 'info',
category: 'internal-error',
message: 'Frame context.',
fixHints: ['This is an informational observation, no action needed.'],
}],
[IMH_WITNESS_ENV, {
code: IMH_WITNESS_ENV,
severity: 'info',
category: 'internal-error',
message: 'Witness environment.',
fixHints: ['This is an informational observation, no action needed.'],
}],
[IMH_WITNESS_SNAPSHOT, {
code: IMH_WITNESS_SNAPSHOT,
severity: 'info',
category: 'internal-error',
message: 'Witness snapshot.',
fixHints: ['This is an informational observation, no action needed.'],
}],
]);
/**
* Look up a canonical code entry by its string code.
*/
export function lookupCode(code: string): CodeEntry | undefined {
return REGISTRY.get(code);
}
/**
* Return all registered codes.
*/
export function listCodes(): CodeEntry[] {
return Array.from(REGISTRY.values());
}
/**
* Build a human-readable message for a code, substituting placeholders.
*
* Supported placeholders:
* {selector} — CSS selector string
* {relation} — relation name (leftOf, above, etc.)
* {expected} — expected value
* {observed} — observed / measured value
* {frame} — frame identifier
*/
export function formatMessage(
code: string,
placeholders: Record<string, string | number>,
): string {
const entry = lookupCode(code);
let message = entry?.message ?? code;
for (const [key, value] of Object.entries(placeholders)) {
message = message.replace(new RegExp(`\\{${key}\\}`, 'g'), String(value));
}
return message;
}