import { type VendoRouteMap } from "../../contract/index.js"; import { type FlatTree } from "../../contract/genui/component/index.js"; import { type HostToolInfo } from "./deps.js"; import { type ScreenCatalogEntry } from "./screen-typings.js"; import { type ScreenToolchain } from "./toolchain.js"; /** One thing wrong with the screen. `code` is the class, for a caller that * routes; `message` is the repair instruction, for the model that reads it. */ export interface ComponentScreenIssue { code: string; message: string; /** …except this one is not about the screen at all: one of the three machines * this gauntlet needs could not RUN here, so nothing was read and no rewrite * can help. Set where the refusal is minted, because that is the only place * that knows which happened, and carried out through the floor * (`ComponentPaintResult.environment`) so a writing loop gives up instead of * spending its budget repairing a screen nothing ever checked. */ environment?: true; } /** One `useQuery` call, as the check will execute it. Structurally the engine's * own `ScreenQuery`, because a plan entry and a miss are the same ask. */ export interface QueryPlanEntry { tool: string; input?: unknown; } export type ComponentScreenCheck = { ok: boolean; issues: ComponentScreenIssue[]; /** post-esbuild JS — what the engine evaluates. */ compiled?: string; /** Every read the screen makes: the ones a literal input made plannable, plus * the ones its own paint asked for. The surface re-reads exactly this list. */ queryPlan?: QueryPlanEntry[]; initialTree?: FlatTree; /** What each query REALLY returned, keyed by `queryKey` — the answers stage 4 booted * the screen on. Handed back because the two things that need them cannot get * them anywhere else: the paint carries them so the renderer boots the same * screen this check rendered, and the AI reviewer judges the numbers on screen * against them. Present on a passing check; a refusal earlier than stage 4 ran * no queries at all. */ queries?: Record; }; export interface ComponentScreenOptions { /** The TSX, verbatim. */ source: string; /** The host tools a query or a handler may name. */ hostTools: readonly HostToolInfo[]; /** The components the screen may import from `@vendo/screen` — {@link screenCatalog}. * A bare name is a component whose props nobody declared. */ catalog: readonly ScreenCatalogEntry[]; /** The pages a `` may name. Absent → the host registered no registry * and stage 5 measures no link against one. */ routes?: VendoRouteMap; /** This source is the splitter's PORT of a host component, not a screen a model * authored — the one dialect whose display tags take the host's `className`. * Set from OUTSIDE the source in both places that grade a port * ({@link PORTED_SCREEN_DIALECT}); a screen that could spell its own dialect * would unlock `className` for itself. */ ported?: boolean; /** The props the screen's component renders with — a PORT's paint can depend * on what its host call site passed, and a query resolves before the render, * so nothing in the source can carry them. JSON only, by the same law as * every value that crosses into the VM, and never invented: the caller hands * the host's own captured sampleProps or nothing — a screen that paints * nothing without props is refused, not blessed on made-up data. */ props?: Record; /** The trusted executor, injected by the caller: this check runs the screen's * queries for real, and it is the caller who holds the guard-bound registry. */ runQuery: (tool: string, input?: unknown) => Promise; /** The wall stage 4 paints on — the locale and the IANA zone the screen's * `Intl` and `toLocale*` calls DEFAULT to. Unset is `"en-US"` and `"UTC"`, * the same as the surface's. A host whose people read another one passes it * here as well as to the surface, so the dates this gate judged are the dates * the person is shown. */ locale?: string; timeZone?: string; /** What compiles, type-checks and paints the screen — the one thing in this * gauntlet that cannot run in every venue. Unset, this process's own * ({@link defaultToolchain}); the floor names it one layer up. */ toolchain?: ScreenToolchain; } /** The dialect a PORT is graded in, spelled ONCE: `vendo sync` grades a port * with it and the runtime floor grades the same bytes with it again, and two * hand-assembled copies is exactly how a port sync blessed came to be refused * on its first save. */ export declare const PORTED_SCREEN_DIALECT: { readonly ported: true; }; /** * Run every stage over one screen. Fail-fast: the returned `issues` are the * first stage's that found any, so a repair round is never handed a list of * consequences of a break it has not fixed yet. */ export declare function checkComponentScreen(opts: ComponentScreenOptions): Promise; /** * The name a screen gives itself: its default-exported component's, split on camel * case (`PendingTransfers` → "Pending transfers"). * * A component file has no `` to read — the function's name is the * only title in it — and this name is what the person's app list shows, so an * anonymous default export gets "Screen" rather than a blank row. Presentation * only: nothing decides anything on it. * * Read with a regex rather than off the scan's AST because both callers ask BEFORE * a parse is guaranteed (the receipt's title on any save that landed, the app row's * name on the save that painted), and a title is never a reason to fail. */ export declare function screenName(source: string): string; /** The first paint, and the surface it lands on. */ export interface PaintedScreen { /** Stage 4's tree — the screen rendered against the data its queries really * returned. */ tree: FlatTree; /** * The CSS pixels the screen renders into, as the host measured them. * * Its own fact, and it travels on its own: a FOLD cannot be judged against a * frame nobody measured, so without one the paint outline is not written at * all — but what the paint left unshown is true at every size, so the tree * still comes through alone and {@link leftoversSection} still reads it. */ viewport?: { width: number; height: number; }; } /** * What the AI reviewer reads: the TSX itself, what the screen drew with it, what * each query really returned — truncated by the same rule the wire reviewer uses * (reviewer.ts) so one long table cannot crowd the screen out of the prompt — and * which of those fields the screen never showed. * * The TSX comes FIRST and whole: it is the thing being judged, and unlike the * wire artifact there is nothing to print — the file the model wrote is the file * the reviewer reads. LEFTOVERS comes LAST, after the rows it is about: it names * fields of the data the reader has just been shown, and the rows may have been * cut short before reaching them. */ export declare function reviewComponentScreenInput(input: { source: string; queryResults: Readonly>; /** The paint, and the surface it lands on when the caller knows one. Absent, * this reads byte for byte as it always did. */ painted?: PaintedScreen; }): string; //# sourceMappingURL=component-screen.d.ts.map