import fs from 'node:fs'; import path from 'node:path'; import { execFileSync } from 'node:child_process'; const root = process.cwd(); const out = path.join(root, 'HMDesignSystem-AI-Reference-Test'); const zip = path.join(root, 'HMDesignSystem-AI-Reference-Test.zip'); fs.rmSync(out, { recursive: true, force: true }); fs.rmSync(zip, { force: true }); fs.mkdirSync(out, { recursive: true }); const copy = (from, to, options = {}) => { const src = path.join(root, from); if (!fs.existsSync(src)) return false; const dest = path.join(out, to); fs.mkdirSync(path.dirname(dest), { recursive: true }); fs.cpSync(src, dest, { recursive: true, force: true, ...options }); return true; }; // Preserve repository-relative paths for source references and imports. copy('packages/ui/src', 'source/packages/ui/src'); copy('packages/ui/package.json', 'source/packages/ui/package.json'); copy('packages/ui/tsconfig.json', 'source/packages/ui/tsconfig.json'); copy('packages/ui/tsconfig.build.json', 'source/packages/ui/tsconfig.build.json'); copy('packages/ui/components.json', 'source/packages/ui/components.json'); copy('packages/center-graphic/src', 'source/packages/center-graphic/src'); copy('packages/center-graphic/package.json', 'source/packages/center-graphic/package.json'); copy('packages/center-graphic/tsconfig.json', 'source/packages/center-graphic/tsconfig.json'); copy('packages/center-graphic/tsconfig.build.json', 'source/packages/center-graphic/tsconfig.build.json'); copy('.storybook', 'storybook/config'); copy('src', 'storybook/source'); copy('storybook-static', 'storybook/static'); copy('dist', 'packages/app-build'); copy('dist-dashboard', 'packages/dashboard-export-build'); copy('packages/ui/dist', 'packages/ui-dist'); copy('packages/center-graphic/dist', 'packages/center-graphic-dist'); copy('theme-dist', 'theme/generated'); copy('themes', 'theme/source'); copy('packages/ui/src/theme.css', 'theme/source/packages-ui-theme.css'); copy('packages/ui/src/theme', 'theme/source/packages-ui-theme'); copy('docs', 'docs/source'); copy('AGENTS.md', 'docs/AGENTS.md'); copy('CLAUDE.md', 'docs/CLAUDE.md'); copy('README.md', 'docs/README.md'); copy('package.json', 'docs/root-package.json'); copy('package-lock.json', 'docs/package-lock.json'); copy('src/exports', 'examples/react-and-html/src/exports'); copy('src/exports/dashboard', 'examples/react-and-html/src/exports/dashboard'); copy('index.html', 'examples/react-and-html/index.html'); copy('vite.dashboard-export.config.ts', 'examples/react-and-html/vite.dashboard-export.config.ts'); copy('scripts/finalize-dashboard-export.mjs', 'examples/react-and-html/finalize-dashboard-export.mjs'); copy('public/fonts', 'assets/fonts'); copy('packages/center-graphic/src/assets', 'assets/center-graphic'); const files = (dir) => fs.existsSync(dir) ? fs.readdirSync(dir, { recursive: true }).filter((p) => fs.statSync(path.join(dir, p)).isFile()).length : 0; const countFiles = (rel, suffix) => { const dir = path.join(root, rel); if (!fs.existsSync(dir)) return 0; return fs.readdirSync(dir, { recursive: true }).filter((p) => String(p).endsWith(suffix)).length; }; const publicComponentFiles = countFiles('packages/ui/src/components', '.tsx'); const patternFiles = countFiles('packages/ui/src/patterns', '.tsx'); const storyFiles = ['.stories.tsx', '.stories.ts', '.stories.jsx', '.stories.js'].reduce((n, s) => n + countFiles('src', s), 0); const generatedAt = new Date().toISOString(); const startHere = `# HM Design System AI Reference 이 ZIP은 빌드 패키지만이 아니라 HM Design System의 실제 구현·Storybook·Theme·문서를 함께 참조하기 위한 테스트 배포본입니다. ## AI 참조 순서 1. \`docs/AGENTS.md\`와 \`docs/README.md\`를 읽습니다. 2. \`docs/source/components\`, \`docs/source/patterns\`, \`docs/source/guidelines\`에서 사용 규칙을 확인합니다. 3. \`source/packages/ui/src\`와 \`source/packages/center-graphic/src\`의 실제 TSX 구현을 재사용합니다. 4. \`storybook/source\`의 Story에서 상태·조합·레이아웃을 확인합니다. 5. \`theme/source\` 및 \`theme/generated\`의 Token/CSS Custom Properties를 사용합니다. 6. \`packages/ui-dist\`와 declarations는 소비자 Export 형태를 확인할 때 사용합니다. 임의의 색상·spacing·radius·Typography 값을 추가하거나 디자인을 재해석하지 않습니다. 신규 화면은 기존 공개 Component/Pattern과 Theme 계약을 우선 재사용합니다. ## 구조 - \`source/\`: 원본 공개 패키지 구현 및 내부 의존 코드 - \`storybook/\`: Storybook 설정, Story/Pattern/Foundation 소스, 정적 Storybook - \`packages/\`: 기존 빌드 산출물 및 TypeScript declarations - \`theme/\`: Token 원본, Generated CSS, Runtime Theme 자료 - \`docs/\`: 원본 사용 규칙, AI 공통 가이드, 컴포넌트·패턴 문서 - \`examples/\`: React/HTML export 관련 예제 및 계약 - \`assets/\`: Font와 Center Graphic asset ## 재현 범위 React는 기존 공개 패키지를 직접 import하는 방식을 우선합니다. HTML은 \`examples/react-and-html\`의 기존 export와 Runtime 계약을 먼저 확인합니다. 이 배포본 자체에서 무료 AI에 의한 신규 화면 생성이나 브라우저 시각 검증은 수행하지 않았습니다. `; fs.writeFileSync(path.join(out, 'AI_START_HERE.md'), startHere, 'utf8'); const manifest = { package: 'HMDesignSystem-AI-Reference-Test', generatedAt, source: { publicComponentSourceFiles: publicComponentFiles, centerGraphicSourceFiles: files(path.join(out, 'source/packages/center-graphic/src')) }, storybook: { storyFiles, sourceFiles: files(path.join(out, 'storybook/source')), staticIncluded: fs.existsSync(path.join(out, 'storybook/static')) }, patterns: { patternSourceFiles: patternFiles }, theme: { sourceIncluded: fs.existsSync(path.join(out, 'theme/source')), generatedIncluded: fs.existsSync(path.join(out, 'theme/generated')) }, assets: { fontFiles: files(path.join(out, 'assets/fonts')), centerGraphicAssetFiles: files(path.join(out, 'assets/center-graphic')) }, verification: { aiReproduction: 'NOT_RUN', browserVisualVerification: 'NOT_RUN', sourceMutation: 'NOT_RUN (packaging-only)' } }; fs.writeFileSync(path.join(out, 'MANIFEST.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf8'); execFileSync('tar', ['-a', '-c', '-f', zip, '-C', root, path.basename(out)], { stdio: 'inherit' }); console.log(JSON.stringify({ out, zip, manifest }, null, 2));