/** * Drift lock: the `uiDesign` overlay shape is canonical in * `lib/ui-design-overlay.ts`. Its WRITER (ui-design/cli/apply-form-directives) * and READER (development/frontend/component/cli/scaffold-component) used to * carry hand-duplicated `interface UiDesignOverlay` copies guarded only by a * "keep in sync" comment. This suite fails if a local re-declaration * reappears in either CLI, or if either stops importing the shared module. */ import { readFileSync } from 'node:fs' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' const skillsRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..') const CARRIERS = [ { name: 'scaffold-component (reader)', files: [ // The reader logic lives in render/ since the 1.0 module split // (generate.ts is a thin orchestrator): context.ts resolves the overlay, // form.ts renders under it, shared.ts applies the per-field directives. 'development/frontend/component/cli/scaffold-component/render/context.ts', 'development/frontend/component/cli/scaffold-component/render/form.ts', 'development/frontend/component/cli/scaffold-component/render/shared.ts', 'development/frontend/component/cli/scaffold-component/types.ts', ], }, { name: 'apply-form-directives (writer)', files: [ 'ui-design/cli/apply-form-directives/types.ts', 'ui-design/cli/apply-form-directives/execute.ts', ], }, ] function read(rel: string): string { return readFileSync(join(skillsRoot, rel), 'utf8') } describe.each(CARRIERS)('uiDesign overlay drift — $name', ({ files }) => { it('declares NO local UiDesignOverlay shape (interface or type alias)', () => { for (const rel of files) { const src = read(rel) // A DECLARATION is `interface X {` or `type X =` — an `import { type X }` // specifier must not trip the lock. expect(src, `${rel} re-declares UiDesignOverlay — import lib/ui-design-overlay instead`) .not.toMatch(/\binterface\s+UiDesignOverlay\b|\btype\s+UiDesignOverlay\s*=/) } }) it('imports the canonical shape from lib/ui-design-overlay', () => { const imports = files.some(rel => /from\s+'(?:\.\.\/)+lib\/ui-design-overlay\.js'/.test(read(rel))) expect(imports, `none of ${files.join(', ')} imports lib/ui-design-overlay.js`).toBe(true) }) })