/** * cli:scaffold-component — preflight.ts * * Fail-closed primitive preflight: every `@/components/ui/
` import the
* generated output carries must resolve on disk (or be written by THIS
* invocation). The historical hole: `ss upgrade` never re-runs
* scaffold-ui-primitives, so a page importing a NEWER primitive (SectionCard)
* compiled against nothing — and the imports-resolve gate then pushed
* auto-heal into improvising the markup by hand (the « formulaire empilé sous
* la fiche » shape DEV-UI-045 now flags). Refusing up front, with the
* remediation named, is the only exit that keeps the read-first contract.
*/
export interface PreflightMiss {
primitive: string
expected: string
}
const UI_IMPORT_RE = /from '@\/components\/ui\/([A-Za-z0-9]+)'/g
/**
* Pure check — `exists` is injected so tests need no disk. `files` are the
* generation output (path + content); a primitive written by this very
* invocation never counts as missing.
*/
export function checkPrimitivePreflight(
outdirAbs: string,
files: ReadonlyArray<{ path: string; content: string }>,
exists: (abs: string) => boolean,
joinPath: (...parts: string[]) => string,
): PreflightMiss[] {
const needed = new Set