/** * Layout Critic — scores already-generated page output against qualitative * design criteria (hierarchy, spacing rhythm, consistency, tenet risk), * grounded in memi's own UX_TRAPS taxonomy. * * This is genuine judgment — an LLM reading generated JSX and reasoning * about it — categorically different from auditGeneratedFiles' regex * rule-checker. It is advisory only: nothing it returns blocks a write. * Returns null (never throws) when no AI key is configured or the call * fails, so callers can treat null as "no critique available". */ import { z } from "zod"; import { type UxTrapId } from "../ux/tenets-traps.js"; import type { PageSpec } from "../specs/types.js"; import type { CodegenContext } from "./generator.js"; export declare const LayoutCritiqueSchema: z.ZodObject<{ score: z.ZodNumber; hierarchy: z.ZodObject<{ verdict: z.ZodEnum<["strong", "adequate", "weak"]>; notes: z.ZodString; }, "strip", z.ZodTypeAny, { notes: string; verdict: "strong" | "adequate" | "weak"; }, { notes: string; verdict: "strong" | "adequate" | "weak"; }>; spacingRhythm: z.ZodObject<{ verdict: z.ZodEnum<["consistent", "uneven"]>; notes: z.ZodString; }, "strip", z.ZodTypeAny, { notes: string; verdict: "consistent" | "uneven"; }, { notes: string; verdict: "consistent" | "uneven"; }>; consistency: z.ZodObject<{ verdict: z.ZodEnum<["consistent", "inconsistent"]>; notes: z.ZodString; }, "strip", z.ZodTypeAny, { notes: string; verdict: "consistent" | "inconsistent"; }, { notes: string; verdict: "consistent" | "inconsistent"; }>; tenetRisks: z.ZodArray; note: z.ZodString; }, "strip", z.ZodTypeAny, { note: string; trapId: UxTrapId; }, { note: string; trapId: UxTrapId; }>, "many">; summary: z.ZodString; }, "strip", z.ZodTypeAny, { summary: string; consistency: { notes: string; verdict: "consistent" | "inconsistent"; }; score: number; hierarchy: { notes: string; verdict: "strong" | "adequate" | "weak"; }; spacingRhythm: { notes: string; verdict: "consistent" | "uneven"; }; tenetRisks: { note: string; trapId: UxTrapId; }[]; }, { summary: string; consistency: { notes: string; verdict: "consistent" | "inconsistent"; }; score: number; hierarchy: { notes: string; verdict: "strong" | "adequate" | "weak"; }; spacingRhythm: { notes: string; verdict: "consistent" | "uneven"; }; tenetRisks: { note: string; trapId: UxTrapId; }[]; }>; export type LayoutCritique = z.infer; /** * Critique already-generated page content. Never throws — returns null when * no AI key is present, when MEMOIRE_DISABLE_LAYOUT_AI=1, or when the AI * call/validation fails, since critique is advisory and a missing critique * must be indistinguishable from "no AI key" to the caller. */ export declare function critiquePage(pageContent: string, spec: PageSpec, ctx: CodegenContext): Promise;