import { JsonObject, DataContract } from '@ggui-ai/protocol'; /** * 3-state outcome. Internal to runtime-render. * The adapter maps this to existing EvalIssue shapes: * verified → no issue * failed → fail * unverified → warn * skipped → no issue */ type CheckOutcome = "verified" | "failed" | "unverified" | "skipped"; interface RenderCheckIssue { readonly check: "render-no-throw" | "action-wiring" | "selection-identity" | "prop-coverage" | "prop-sensitivity" | "stream-rerender" | "optional-props-omitted"; readonly outcome: CheckOutcome; readonly subject?: string; readonly reason: string; /** Optional element description ("button[aria-label='Save']") for action-wiring failures. */ readonly elementHint?: string; /** * Diagnostic context from probe + AST analysis. Populated for richer feedback * to the coding agent (which native props the callback flows into, what the * probe observed firing, etc.). */ readonly diagnostics?: { readonly observedJsxElements?: readonly string[]; readonly observedNativeProps?: readonly string[]; readonly observedCustomProps?: readonly string[]; /** For action-wiring: which actions DID fire from probe clicks (helps surface mis-wiring). */ readonly actionsFiredFromClicks?: readonly string[]; /** Surfaced to the agent: prop sourceTool hints from the contract (only if present). */ readonly sourceToolHints?: Readonly>; }; } interface RenderCheckResult { readonly ok: boolean; readonly issues: readonly RenderCheckIssue[]; readonly stats: { readonly actionsChecked: number; readonly streamsChecked: number; readonly renderMs: number; }; } interface RunRenderCheckInput { readonly sourceCode: string; readonly mockupProps: JsonObject; readonly contract?: DataContract; } /** * Run the in-loop runtime render check. * * Isolation dispatcher (#592): when the CALLING environment already * owns a DOM (`window` + `document` on `globalThis` — e.g. a vitest * `happy-dom` environment, where the environment owner installed the * globals deliberately), the check runs in-process exactly as before. * In a plain Node process it runs in an ISOLATED SUBPROCESS * (`render-check-host.ts` → `render-check-worker.ts`), because the * in-process path installs happy-dom globals on `globalThis` * process-wide — a TOCTOU hazard for anything that sniffs `window` * concurrently (provider SDKs throw "browser-like environment" at * client construction; two overlapping checks corrupt each other's * teardown). See #592 for the measured incident (4 bench cells hard- * failed on the 2026-08-19 run). * * The host is loaded lazily so the worker bundle (which imports this * module for `runRenderCheckInProcess`) never drags in the sandbox * spawn machinery. */ declare function runRenderCheck(input: RunRenderCheckInput): Promise; export { type RenderCheckIssue as R, type RenderCheckResult as a, runRenderCheck as r };