/** * Layout Composer — chooses a PageSpec's layout template and each section's * arrangement/order using design judgment grounded in memi's own UX tenets * and traps, instead of requiring the spec author to hardcode them. * * This does NOT invent arbitrary novel React/JSX. Output stays deterministic * shadcn/Tailwind assembled by page-generator.ts's existing LAYOUT_TEMPLATES * and layoutToGridClass() lookup tables — composition only picks WHICH of * those already-safe options to use, and in what order. When no AI key is * present, or the spec sets layoutLocked, this falls back to a deterministic * keyword heuristic (or is skipped entirely) — never a hard dependency. */ import type { PageSpec } from "../specs/types.js"; import type { CodegenContext } from "./generator.js"; export interface LayoutComposition { layout: PageSpec["layout"]; sectionOrder: string[]; sectionLayouts: Record; rationale: string; source: "ai" | "heuristic"; } /** * Compose a layout for the given page spec. Respects spec.layoutLocked * (skips entirely, returns the spec's own values verbatim) and * MEMOIRE_DISABLE_LAYOUT_AI (forces the heuristic path so CI/batch * `generate --all` jobs can opt out of the added LLM round-trip). */ export declare function composeLayout(spec: PageSpec, ctx: CodegenContext): Promise; /** * Pure, deterministic, zero-I/O fallback. Maps purpose/section-name keywords * onto the same enums PageSpecSchema already defines, so its output always * validates against the existing schema with no new failure modes. Never * reorders sections (no reliable signal to reorder by without AI judgment) — * only fills in layout choices. */ export declare function heuristicComposeLayout(spec: PageSpec): LayoutComposition; /** * Apply a composition to a spec, producing a new PageSpec with layout/section * arrangement filled in. Only overwrites fields that still equal their Zod * schema default ("full-width" for both spec.layout and section.layout) — * this is a heuristic proxy for "the author never set this explicitly", not * a true one (a spec author who deliberately chose full-width is indistinguishable * from one who left it at the default), and is the documented tradeoff that * keeps this feature safe-by-default rather than silently overriding authored * intent in the common case where a field truly was set on purpose. */ export declare function applyComposition(spec: PageSpec, composition: LayoutComposition): PageSpec;