/** * The checks floor as the paint seam calls it — blueprint §7.1. * * The seam never learns to read `app.tsx`: every author's screen — our loop, * Claude Code, a person with an editor — faces the identical gauntlet here, and a * refusal is the gauntlet's own repair instructions verbatim. * * The AI reviewer is deliberately absent: it spends a model call, and this runs on * every commit. Judgement is `validate`'s (`AppsRuntime.validate`). */ import { type AppId, type Json } from "@vendoai/core"; import { type Check, type Finding, type AppFloor } from "../../contract/index.js"; import type { FloorDependencies } from "./deps.js"; import type { ScreenToolchain } from "./toolchain.js"; export interface AppFloorOptions { /** * The host surface to measure against, resolved LAZILY and once. * * Lazily because building it lists the host's tools, and a floor is * constructed per turn but called per commit; once because a turn must not * change its mind about what the host has halfway through. */ deps: () => Promise; /** The host's own plugged checks (`AppsConfig.checks`). APPENDED — a host adds * findings, never removes a built-in. They fire here for the same reason they * fire on create: the floor does not care who wrote the app. */ checks?: readonly Check[]; /** * A component screen's own queries, RUN — stage 4 of the gauntlet, which boots * the screen on the answers a tool really gave. * * Injected because this is the one thing in the gauntlet that touches the * outside world: the caller holds the guard-bound caller and the turn's ctx, so * every query rides one guard decision, this person's authority and the app * venue, exactly as `AppsRuntime.authored` resolves a tree's queries. Absent, * `component` refuses — a gate that could not execute the screen must never * answer "fine". */ runQuery?: (appId: AppId, tool: string, input?: unknown) => Promise; /** * The row half of a component screen's paint (`AppsRuntime.authoredScreen`). * * The render seam calls its `authoredApp` for a wire document and has no such * call for `app.tsx`, so the gauntlet's own `ok` — which IS the seam's paint gate * — is what calls this. That keeps "a paint is what creates the row" true for * both artifacts, which is what `create` reads the row's existence AS. * * The screen it paints rides as the SECOND argument, beside the row's own * fields rather than inside them: a component artifact has no tree to store, so * the screen's text IS the app, and this is the one call that fires only when * the gauntlet admitted it. A generic workspace diff lands the file whether or * not the screen was refused, which is how a screen the floor would not render * became the app's stored screen. */ delivered?: (input: { appId: AppId; name: string; }, source: string) => Promise; /** * The other half of the same seam: this screen was REFUSED, with the sentences * the caller is about to receive. * * A refusal has to be answerable. Without this, an `edit` whose save the floor * refused reads the unchanged row back and reports it as a clean receipt — the * person is told their change landed. Everything that could say otherwise knows * it here and nowhere else. */ refused?: (input: { appId: AppId; blocking: readonly string[]; }) => Promise; /** * What compiles, type-checks and paints a component screen (`AppsConfig.toolchain`). * * The gauntlet's three stages that cannot run in every venue, behind one slot, * so a deployment whose checks happen somewhere without esbuild, the * `typescript` package and the QuickJS build can still run every other stage * here. Passed through unresolved: the gauntlet holds the one default, so a * toolchain installed after a floor was built still reaches that floor. */ toolchain?: ScreenToolchain; /** * Whether this app's screen is the splitter's PORT of a host component — the * one dialect whose display tags take the host's `className` * (`checking/screen-typings.ts` `jsxFrame`). * * DERIVED, never carried in the screen: a model-authored screen that could * spell its own dialect would unlock `className` for itself. Composition fills * this off the row (`doors/build-surface.ts`), which is also the only way the * grade `vendo sync` ran and the grade the floor runs can agree — assembled * twice, they drifted, and a port sync blessed was refused on its first save. */ ported?: (appId: AppId) => Promise; /** * The props a PORTED screen paints with — the host's own captured * sampleProps, resolved off the row's seed the same way `ported` is, and * consulted only when `ported` answered yes. Never invented: a port whose * paint depends on props and whose baseline captured none is refused, not * blessed on made-up data. */ props?: (appId: AppId) => Promise | undefined>; } export declare const createAppFloor: ({ deps, checks, runQuery, delivered, refused, toolchain, ported, props }: AppFloorOptions) => AppFloor; /** The findings that mean "this must not reach a screen". */ export declare const blocks: (findings: readonly Finding[]) => Finding[]; //# sourceMappingURL=floor.d.ts.map