/**
* Schema-derived TypeScript declarations for one screen — the static half of
* the checks floor.
*
* The floor already knows every type a screen file can name: the Kit's props
* are zod (`core` `kit/specs.ts`), a host component's props are the JSON Schema
* derived once at composition (`NormalizedCatalogEntry.propsJsonSchema`), and a
* query's result is the tool's declared `outputSchema`. This module turns all
* of that into ambient declaration text so `tsc` — the real compiler, not a
* bespoke walker — decides whether a screen names components that exist, sets
* props that exist with types that fit, reaches fields the data really carries,
* and aggregates over field names the rows really have.
*
* Everything here is DERIVED. No hand-written component list, no hand-written
* prop list: the component vocabulary comes from `KIT_SCREEN_COMPONENT_NAMES` + the
* catalog. There is no CALL vocabulary to declare any more — a `{...}` gap is a
* JavaScript expression, so `invoices.data.reduce((t, r) => t + r.amount, 0)`
* type-checks against the query's own declared result type with nothing
* ambient in the way. The old `sum`/`count`/`group_by`/`pick` declarations
* existed only to give tsc a shape for a closed dialect that no longer exists;
* shipping them now would type-check calls the renderer cannot evaluate.
*
* Pure and deterministic: same input, byte-identical output. No compiler, no
* I/O — {@link screenTscFindings} in screen-tsc.ts is the half that runs one.
*/
import { type JsonSchema } from "@vendoai/core";
import { type NormalizedCatalog } from "../../contract/index.js";
import type { ZodTypeAny } from "zod";
import { type HostToolInfo } from "./deps.js";
/**
* Where a construct neither printer can model is announced.
*
* Both printers degrade an unknown construct to `any` — never to an error,
* because a prop we cannot type precisely must not become a false finding. The
* cost is invisible: the gate quietly stops checking that prop. A caller that
* passes a sink learns which ones went dark; one that passes nothing keeps the
* old silence.
*/
export type TypeNote = (reason: string) => void;
/** One query a screen declares: ``.
* Structurally the floor's own `tree.queries` entry. */
export interface ScreenQueryDeclaration {
readonly name: string;
readonly tool: string;
}
export interface ScreenTypingsInput {
/** The host catalog. A schema-less entry is LEGAL (01-core §14) and gets a
* permissive type — never an error. */
readonly catalog: NormalizedCatalog;
/** The screen's declared queries, in source order. */
readonly queries: readonly ScreenQueryDeclaration[];
/**
* tool name → the tool's DECLARED output JSON Schema
* (`ToolDescriptor.outputSchema`). The only source: a declaration is the
* host's contract, and nothing samples the host anymore.
*/
readonly toolOutputSchemas?: Readonly>;
}
/** The virtual path the declarations occupy in the check's program. */
export declare const SCREEN_TYPINGS_FILE = "/vendo-screen-typings.d.ts";
/**
* What a slot may hold — an element tree, or a function that returns one.
*
* One law for every slot: the element, or the function that makes it. The VM
* calls whichever it was given (`genui/component/vm-program.ts` `emitSlot`) and
* emits the result where the slot sits, so `header={() => }` is as real as
* `header={}`.
*
* The ARITY is the only thing that differs, and it is what this alias states: a
* slot painted ONCE has no row to be a function of, so its function takes
* nothing. A `(row) => …` written here would be called with no row and read a
* field off `undefined` — the compiler is the only thing that can refuse it, and
* {@link ROW_SLOT_TYPE} is the other arity.
*
* The wire printer keeps the permissive alias: a stored document's slot holds a
* SERIALIZED element (an `$element`-sigilled object) that no type here
* describes, and JSON cannot carry a closure, so neither form reaches it.
*/
export declare const SLOT_TYPE = "VendoSlot";
/**
* The same law at the other arity: a slot the Kit paints once PER ROW, whose
* function is handed the row.
*
* A per-row slot is painted once for every row, so a function of the row is the
* only way to say something different in each — and it is what React trains
* anyone to write. The VM calls it once per row and hands the component that
* row's own element (`vm-program.ts` `emitSlot`), so the closure is real: the
* handler inside `rowActions={(row) =>