UNPKG

ai-naming-standard-mcp

Version:

AI Governance Era v6.1: loungeservice-grade project initialization. Creates 8-folder structure with complete AI governance (AI_RULES.md, AI_ROLE_MATRIX.yaml, NAMING_EXCEPTIONS.md, DEVELOPMENT.md, project.md) and bridge files (.cursorrules, .windsurfrules)

911 lines (801 loc) 39.7 kB
import { getMessages, formatMessage } from '../messages/index.js'; import namingRules from '../rules/convention.js'; // ========== v4 기존 도구들 (하위 호환성) ========== // 파일명 생성 함수 (v5.0.1 ChatGPT Enhancement) export async function generateFileName({ folder = '03_ACTIVE', index = '001', layer = 'BE', domain, feature, action = 'R', detail = 'Service', env = 'DEV', ext = 'js', isTest = false, isStatic = false, staticType = null }) { const msg = getMessages(); // 02_STATIC 파일 처리 (ChatGPT Enhancement) if (folder === '02_STATIC' || isStatic) { const prefix = staticType === 'template' ? 'TEMPLATE_' : staticType === 'config' ? 'CONFIG_' : 'ASSET_'; const staticName = domain || 'file'; return { fileName: `${prefix}${staticName}.${ext}`, folder: '02_STATIC', fullPath: `02_STATIC/${prefix}${staticName}.${ext}`, description: `Static ${staticType || 'asset'} file`, requiresPrefix: true }; } // 04_TEST 파일 처리 (ChatGPT Enhancement) if (folder === '04_TEST' || isTest) { const testType = detail || 'Unit'; const testFileName = `${index}_TEST_${domain}-${feature}_${testType}_${env}.test.${ext}`; return { fileName: testFileName, folder: '04_TEST', fullPath: `04_TEST/${testFileName}`, description: `Test file for ${domain}-${feature} (${testType})`, indexedNaming: true }; } // 도메인과 기능 정규화 (03_ACTIVE 파일) const normalizedDomain = domain.charAt(0).toUpperCase() + domain.slice(1).toLowerCase(); const normalizedFeature = feature.charAt(0).toUpperCase() + feature.slice(1).toLowerCase(); // 표준 파일명 생성 (v5 패턴) const fileName = `${index}_${layer}_${normalizedDomain}-${normalizedFeature}_${action}_${detail}_${env}.${ext}`; return { fileName, folder, fullPath: `${folder}/${fileName}`, description: `${layer} ${normalizedDomain} ${normalizedFeature} ${detail} for ${env} environment`, hasDependency: index.includes('-') || index.includes('s') || /[a-z]$/.test(index) }; } // 파일명 검증 함수 (v5 업데이트) export async function validateFileName({ fileName, folder = '03_ACTIVE' }) { const msg = getMessages(); const rules = namingRules(); // v5 파일명 패턴 const pattern = /^([0-9]{3}(?:\.[0-9]+)?(?:[a-z]|s[0-9]+|-[0-9]+)?)_([A-Z]{2,6})_([A-Z][a-z]+(?:-[A-Z][a-z]+)+)_([CRUDVXSTG])_([A-Z][a-z]+)_([A-Z]{2,6})\.([a-z]+)$/; const match = fileName.match(pattern); if (!match) { return { valid: false, errors: [ msg.errors.invalidPattern || 'Invalid file name pattern', 'Correct format: [Index]_[Layer]_[Domain]-[Feature]_[Action]_[Detail]_[Env].[ext]' ], suggestion: await suggestCorrection({ fileName }) }; } const [, index, layer, domainFeature, action, detail, env, ext] = match; const errors = []; const warnings = []; // 폴더별 네이밍 규칙 체크 const folderRule = rules.standardFolders[folder]; if (folderRule && !folderRule.namingRuleRequired && folder !== '03_ACTIVE') { warnings.push(`Naming convention is optional for ${folder}`); } // Layer 검증 const validLayers = ['FE', 'BE', 'DB', 'API', 'ML', 'INFRA', 'SH']; if (!validLayers.includes(layer)) { errors.push(`Invalid layer: '${layer}'`); } // Action 검증 const validActions = ['C', 'R', 'U', 'D', 'V', 'X', 'S', 'T', 'G']; if (!validActions.includes(action)) { errors.push(`Invalid action: '${action}'`); } // Environment 검증 const validEnvs = ['DEV', 'STG', 'PROD', 'COMMON']; if (!validEnvs.includes(env)) { errors.push(`Invalid environment: '${env}'`); } return { valid: errors.length === 0, errors, warnings, components: { index, layer, domainFeature, action, detail, env, ext }, folder }; } // 파일명 설명 함수 export async function explainFileName({ fileName }) { const msg = getMessages(); const validation = await validateFileName({ fileName }); if (!validation.valid) { return { error: msg.errors.invalidPattern || 'Invalid pattern', details: validation.errors }; } const { index, layer, domainFeature, action, detail, env, ext } = validation.components; // 액션 코드 설명 const actionDescriptions = { 'C': 'Create', 'R': 'Read', 'U': 'Update', 'D': 'Delete', 'V': 'Validate', 'X': 'Execute', 'S': 'Send', 'T': 'Transform', 'G': 'Generate' }; // 레이어 설명 const layerDescriptions = { 'FE': 'Frontend', 'BE': 'Backend', 'DB': 'Database', 'API': 'API Gateway', 'ML': 'Machine Learning', 'INFRA': 'Infrastructure', 'SH': 'Shared/Common' }; return { fileName, explanation: { index: `Sequence: ${index}`, layer: `Layer: ${layerDescriptions[layer] || layer}`, domainFeature: `Domain-Feature: ${domainFeature}`, action: `Action: ${actionDescriptions[action]} (${action})`, detail: `Component: ${detail}`, environment: `Environment: ${env}`, extension: `Format: ${ext}` }, purpose: `${layerDescriptions[layer]} ${detail} that performs ${actionDescriptions[action]} operation for ${domainFeature} in ${env} environment` }; } // Layer 코드 조회 함수 export async function getLayerCodes({ category = 'all' }) { const msg = getMessages(); const layers = { frontend: [ { code: 'FE', name: 'Frontend', description: 'React, Vue, Angular' } ], backend: [ { code: 'BE', name: 'Backend', description: 'Node.js, Python, Java' } ], data: [ { code: 'DB', name: 'Database', description: 'MySQL, MongoDB, PostgreSQL' } ], infra: [ { code: 'API', name: 'API Gateway', description: 'REST, GraphQL, gRPC' }, { code: 'ML', name: 'Machine Learning', description: 'TensorFlow, PyTorch' }, { code: 'INFRA', name: 'Infrastructure', description: 'Docker, K8s, Terraform' }, { code: 'SH', name: 'Shared', description: 'Common utilities' } ] }; if (category === 'all') { return { layers: [ ...layers.frontend, ...layers.backend, ...layers.data, ...layers.infra ] }; } return { category, layers: layers[category] || [] }; } // Action 코드 조회 함수 export async function getActionCodes({ category = 'all' }) { const msg = getMessages(); const actions = { crud: [ { code: 'C', name: 'Create', description: 'Create new resource' }, { code: 'R', name: 'Read', description: 'Read data' }, { code: 'U', name: 'Update', description: 'Update existing data' }, { code: 'D', name: 'Delete', description: 'Delete resource' } ], processing: [ { code: 'V', name: 'Validate', description: 'Validate data' }, { code: 'T', name: 'Transform', description: 'Transform data' }, { code: 'X', name: 'Execute', description: 'Execute process' }, { code: 'G', name: 'Generate', description: 'Generate output' } ], communication: [ { code: 'S', name: 'Send', description: 'Send data' } ] }; if (category === 'all') { return { actions: [ ...actions.crud, ...actions.processing, ...actions.communication ] }; } return { category, actions: actions[category] || [] }; } // 프로젝트 템플릿 생성 함수 (v5 업데이트) export async function getProjectTemplate({ projectType, scale = 'mvp' }) { const msg = getMessages(); const rules = namingRules(); const template = rules.projectTemplates[projectType]; if (!template) { return { error: `Unknown project type: ${projectType}` }; } // 7개 표준 폴더 구조 const folders = [ '00_DOCS', '01_CONFIG', '02_STATIC', '03_ACTIVE', '04_TEST', '05_BUILD', '06_LOGS' ]; // 샘플 파일 생성 const sampleFiles = { '00_DOCS': ['README.md', 'API_Documentation.md', 'Architecture.md'], '01_CONFIG': ['config.dev.yml', 'config.prod.yml', '.env.example'], '02_STATIC': ['logo.png', 'favicon.ico'], '03_ACTIVE': [], '04_TEST': ['test_user_service.py', 'e2e_checkout.test.js'], '05_BUILD': [], '06_LOGS': [] }; // 03_ACTIVE에 도메인별 파일 추가 let fileIndex = 1; for (const domain of template.domains.slice(0, scale === 'mvp' ? 3 : template.domains.length)) { // Frontend sampleFiles['03_ACTIVE'].push( `${String(fileIndex).padStart(3, '0')}_FE_${domain}-List_R_Page_PROD.jsx` ); fileIndex++; // Backend sampleFiles['03_ACTIVE'].push( `${String(fileIndex).padStart(3, '0')}_BE_${domain}-Create_C_Service_PROD.py` ); fileIndex++; // Database sampleFiles['03_ACTIVE'].push( `${String(fileIndex).padStart(3, '0')}_DB_${domain}-Schema_C_Migration_PROD.sql` ); fileIndex++; } return { projectType, projectName: template.name, scale, folders, estimatedFiles: template.estimatedFiles[scale], sampleStructure: sampleFiles, domains: template.domains }; } // 일괄 파일명 생성 함수 export async function batchGenerateFileNames({ projectType, domains, count = 10 }) { const files = []; const layers = ['FE', 'BE', 'DB']; const actions = ['C', 'R', 'U', 'D']; const details = ['Page', 'Service', 'Schema', 'Controller', 'Component']; const envs = ['DEV', 'STG', 'PROD']; for (let i = 0; i < count && files.length < count; i++) { for (const domain of domains) { const layer = layers[i % layers.length]; const action = actions[Math.floor(i / layers.length) % actions.length]; const detail = details[i % details.length]; const env = envs[i % envs.length]; const index = String(i + 1).padStart(3, '0'); const ext = layer === 'FE' ? 'jsx' : layer === 'BE' ? 'py' : 'sql'; const fileName = await generateFileName({ index, layer, domain, feature: 'Main', action, detail, env, ext }); files.push(fileName); if (files.length >= count) break; } } return { projectType, count: files.length, files }; } // 파일명 수정 제안 함수 export async function suggestCorrection({ fileName }) { const msg = getMessages(); // 파일명을 언더스코어로 분리 const parts = fileName.split(/[_\.]/); const ext = parts[parts.length - 1]; const suggestions = []; // v5 형식 체크 if (parts.length < 7) { suggestions.push('Missing components. Full format: [Index]_[Layer]_[Domain]-[Feature]_[Action]_[Detail]_[Env].[ext]'); } // 추천 파일명 생성 const recommended = `001_BE_${parts[2] || 'User-Main'}_R_Service_DEV.${ext || 'js'}`; return { original: fileName, issues: suggestions, recommended: `Recommended: ${recommended}`, pattern: '[Index]_[Layer]_[Domain]-[Feature]_[Action]_[Detail]_[Env].[ext]' }; } // ========== v5.0.2 외부 파일 관리 도구들 ========== // 외부 파일 처리 도구 export async function handleExternalFile({ vendor, version, fileType = 'JS', url, fileName, license = 'Unknown' }) { const msg = getMessages(); const rules = namingRules(); // EXTERNAL_ 파일명 생성 const ext = fileName ? fileName.split('.').pop() : 'js'; const externalFileName = `EXTERNAL_${fileType}_${vendor}_${version}.${ext}`; const filePath = `02_STATIC/${externalFileName}`; // 의존성 기록 정보 const dependencyRecord = { fileName: externalFileName, version, vendor, url, dateAdded: new Date().toISOString().split('T')[0], license, path: filePath, sha256: 'TO_BE_CALCULATED', // AI가 다운로드 시 계산 importStatement: `import ${vendor} from '../../02_STATIC/${externalFileName}';` }; return { fileName: externalFileName, path: filePath, dependencyRecord, instructions: [ `1. Download file from: ${url}`, `2. Save as: ${filePath}`, `3. Calculate SHA256 hash`, `4. Update 00_DOCS/EXTERNAL_DEPENDENCIES.md`, `5. Never modify the external file`, `6. Use in code: ${dependencyRecord.importStatement}` ], message: msg.v5?.externalFileHandled || `External file registered: ${externalFileName}` }; } // 외부 파일 버전 업데이트 도구 export async function updateExternalFileVersion({ currentFileName, newVersion, newUrl }) { const msg = getMessages(); // 기존 파일명 파싱 const match = currentFileName.match(/^EXTERNAL_([^_]+)_([^_]+)_v([\d.]+)(.*)\.(.+)$/); if (!match) { return { error: 'Invalid external file name format', expected: 'EXTERNAL_[Type]_[Vendor]_[Version].[ext]' }; } const [, type, vendor, oldVersion, suffix, ext] = match; // 새 파일명 생성 const deprecatedFileName = `EXTERNAL_${type}_${vendor}_v${oldVersion}_DEPRECATED.${ext}`; const newFileName = `EXTERNAL_${type}_${vendor}_${newVersion}.${ext}`; return { actions: [ { step: 1, action: 'Rename old file', from: `02_STATIC/${currentFileName}`, to: `02_STATIC/${deprecatedFileName}` }, { step: 2, action: 'Download new version', url: newUrl, saveTo: `02_STATIC/${newFileName}` }, { step: 3, action: 'Update imports in 03_ACTIVE', oldImport: `'../../02_STATIC/${currentFileName}'`, newImport: `'../../02_STATIC/${newFileName}'` }, { step: 4, action: 'Update EXTERNAL_DEPENDENCIES.md', markAsDeprecated: deprecatedFileName, addNew: newFileName } ], oldFile: deprecatedFileName, newFile: newFileName, message: `External file update plan created: ${vendor} v${oldVersion} → ${newVersion}` }; } // 외부 의존성 목록 생성 도구 export async function generateDependencyManifest() { const msg = getMessages(); const manifestContent = `# External Dependencies\n\n` + `Generated: ${new Date().toISOString()}\n\n` + `| File Name | Version | Vendor | URL | SHA256 | Date | License | Notes |\n` + `|-----------|---------|--------|-----|--------|------|---------|-------|\n` + `| (AI will populate this table) | | | | | | | |\n`; return { fileName: 'EXTERNAL_DEPENDENCIES.md', path: '00_DOCS/EXTERNAL_DEPENDENCIES.md', content: manifestContent, instructions: [ 'Create this file in 00_DOCS/', 'Update whenever adding external files', 'Include SHA256 hash for security', 'Track all version changes', 'Mark deprecated files clearly' ], message: 'Dependency manifest template generated' }; } // ========== v5 새로운 도구들 ========== // 1. 프로젝트 구조 생성 도구 (v6.1.0 - loungeservice 수준) export async function createProjectStructure({ projectName = 'new-project', version = 'v6' }) { const msg = getMessages(); const rules = namingRules(); const structure = { projectName, version, folders: [], files: [], commands: [] }; // v6: 8개 폴더 (07_META 추가) const foldersV6 = [ '00_DOCS', '01_CONFIG', '02_STATIC', '03_ACTIVE', '04_TEST', '05_BUILD', '06_LOGS', '07_META' ]; const folders = version === 'v6' ? foldersV6 : Object.keys(rules.standardFolders); // 폴더 생성 명령 for (const folderName of folders) { const folderInfo = rules.standardFolders[folderName] || { description: 'AI Metadata', aiPermission: 'READ-WRITE' }; structure.folders.push({ name: folderName, path: `${projectName}/${folderName}`, description: folderInfo.description, aiPermission: folderInfo.aiPermission }); structure.commands.push(`mkdir ${projectName}/${folderName}`); } // v6.1.0: loungeservice 기반 완전한 거버넌스 파일 const today = new Date().toISOString().split('T')[0]; structure.files = [ // 00_DOCS { path: `${projectName}/00_DOCS/README.md`, content: `# ${projectName}\n\n**Version**: 0.1.0 \n**Created**: ${today} \n**Standard**: ai-naming-standard v6\n\nBuilt with AI Naming Convention v6.1.0\n\n## 프로젝트 개요\n\n(프로젝트 설명을 작성하세요)\n\n## 시작하기\n\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## 주요 문서\n\n- **AI 규칙**: \`07_META/AI_RULES.md\`\n- **개발 로그**: \`07_META/DEVELOPMENT.md\`\n- **변경 이력**: \`07_META/project.md\`\n` }, { path: `${projectName}/00_DOCS/CHANGELOG.md`, content: `# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n## [Unreleased]\n\n### Added\n- Project initialized with ai-naming-standard v6\n\n## [0.1.0] - ${today}\n\n### Added\n- Initial project structure\n- AI governance system\n- 8-folder architecture (00_DOCS ~ 07_META)\n` }, // 01_CONFIG { path: `${projectName}/01_CONFIG/.env.example`, content: '# Environment Variables\n# Copy to .env and fill in your values\n\n# API Keys\n# API_KEY=your_api_key_here\n\n# Database\n# DB_HOST=localhost\n# DB_PORT=5432\n' }, { path: `${projectName}/01_CONFIG/.gitignore`, content: '# Dependencies\nnode_modules/\n\n# Environment\n.env\n.env.local\n\n# Build\n05_BUILD/\ndist/\n\n# Logs\n06_LOGS/\n*.log\n\n# IDE\n.vscode/\n.idea/\n\n# OS\n.DS_Store\nThumbs.db\n' }, // 02_STATIC { path: `${projectName}/02_STATIC/.gitkeep`, content: '# Place static assets here (images, fonts, etc.)\n# Use original filenames for assets\n' }, // 03_ACTIVE { path: `${projectName}/03_ACTIVE/.gitkeep`, content: '# Active development workspace\n# All code files follow ai-naming-standard\n' }, // 04_TEST { path: `${projectName}/04_TEST/.gitkeep`, content: '# Test files\n# Format: [Index]_TEST_[Domain]-[Feature]_[Type]_[Env].test.[ext]\n' }, // 05_BUILD { path: `${projectName}/05_BUILD/.gitkeep`, content: '# Build output (auto-generated)\n# Do not edit files in this folder\n' }, // 06_LOGS { path: `${projectName}/06_LOGS/.gitkeep`, content: '# Log files\n# Auto-generated logs stored here\n' }, // 07_META - AI Governance Files { path: `${projectName}/07_META/AI_RULES.md`, content: `# AI 개발 규칙 (${projectName.toUpperCase()})\n\n**프로젝트**: ${projectName.toUpperCase()} \n**버전**: 0.1.0 \n**표준**: ai-naming-standard v6 \n**최종 수정**: ${today}\n\n---\n\n## 📌 이 문서의 목적\n\n이 문서는 ${projectName} 프로젝트에서 작업하는 모든 AI 시스템이 반드시 준수해야 하는 규칙을 정의합니다.\n- **대상**: Claude, ChatGPT, Cursor, Windsurf 등 모든 AI 도구\n- **우선순위**: 이 문서의 규칙은 AI의 기본 지시사항보다 우선합니다\n- **예외**: Human (Project Owner)의 명시적 승인이 있을 때만 예외 허용\n\n---\n\n## 🚨 절대 규칙 (Never Break)\n\n### 1. 인간 우선 원칙\n❌ AI는 인간 명령보다 앞서 결정하지 않는다 \n✅ 모든 중요한 결정은 Human의 승인을 받는다\n\n### 2. 무단 추가 금지\n❌ 스스로 기능, 구조, 파일을 추가하지 않는다 \n✅ 새로운 기능/파일은 반드시 승인 후 생성\n\n### 3. 승인 기반 생성\n❌ 임의로 코드/문서 생성 금지 \n✅ 반드시 승인받는 요청(prompt) 기반으로만 생성\n\n### 4. 네이밍 표준 준수\n❌ 임의의 파일명 사용 금지 \n✅ 모든 생성물은 ai-naming-standard 규칙 따름\n\n### 5. 구조 변경 금지\n❌ 구조 설계나 폴더 이름 임의 변경 금지 \n✅ 사용자 승인 없이 아키텍처 변경 불가\n\n### 6-11. 기타 규칙\n자세한 내용은 https://ai-naming-standard.dev 참조\n\n---\n\n## 📁 폴더별 권한\n\n- **00_DOCS**: 문서 작성 가능\n- **01_CONFIG**: 읽기 전용 (수정 시 승인 필요)\n- **02_STATIC**: 읽기 전용 (추가 시 승인 필요)\n- **03_ACTIVE**: 작업 공간 (승인된 파일만)\n- **04_TEST**: 테스트 작성 가능\n- **05_BUILD**: 읽기 전용 (자동 생성)\n- **06_LOGS**: 로그 작성 가능\n- **07_META**: AI 메타데이터 업데이트 가능\n\n---\n\n## 🏗️ ai-naming-standard v6 규칙\n\n### 기본 형식\n\`\`\`\n[Index]_[Layer]_[Domain]-[Feature]_[Action]_[Detail]_[Env].[ext]\n\`\`\`\n\n### 예시\n\`\`\`\n001_controller_auth-login_render_form_common.jsx\n001_service_user-create_process_api_common.js\n\`\`\`\n\n자세한 규칙은 \`07_META/NAMING_EXCEPTIONS.md\` 참조\n\n---\n\n**이 규칙들을 준수함으로써 우리는 안전하고 예측 가능하며 유지보수 가능한 프로젝트를 만들 수 있습니다.**\n` }, { path: `${projectName}/07_META/AI_ROLE_MATRIX.yaml`, content: `# AI Role Matrix for ${projectName.toUpperCase()} Project\n# ai-naming-standard v6\n\nproject:\n name: ${projectName.toUpperCase()}\n version: "0.1.0"\n standard: "ai-naming-standard v6"\n created: "${today}"\n\nai_roles:\n claude:\n role: "Lead Developer & Architect"\n permissions:\n 00_DOCS: ["read", "write", "modify"]\n 01_CONFIG: ["read"]\n 02_STATIC: ["read"]\n 03_ACTIVE: ["read", "write", "modify"]\n 04_TEST: ["read", "write", "modify"]\n 05_BUILD: ["read"]\n 06_LOGS: ["read", "write"]\n 07_META: ["read", "write", "modify"]\n responsibilities:\n - "프로젝트 아키텍처 설계"\n - "코드 리뷰 및 품질 관리"\n - "문서화 및 변경 이력 관리"\n constraints:\n - "사용자 승인 없이 파일 삭제 금지"\n - "모든 변경사항 07_META/project.md에 기록"\n\n cursor:\n role: "Code Assistant"\n permissions:\n 00_DOCS: ["read"]\n 01_CONFIG: ["read"]\n 02_STATIC: ["read"]\n 03_ACTIVE: ["read", "write", "modify"]\n 04_TEST: ["read", "write", "modify"]\n 05_BUILD: ["read"]\n 06_LOGS: ["read"]\n 07_META: ["read"]\n responsibilities:\n - "코드 작성 및 수정"\n - "버그 수정"\n constraints:\n - "설정 파일 수정 금지"\n\n human:\n role: "Project Owner"\n permissions:\n all_folders: ["read", "write", "modify", "delete"]\n responsibilities:\n - "최종 의사결정"\n - "AI 작업 승인"\n authority: "HIGHEST"\n\ncollaboration_rules:\n - "모든 AI는 human의 승인 없이 독단적 결정 금지"\n - "변경사항은 반드시 07_META/project.md에 기록"\n - "ai-naming-standard 규칙 엄수"\n` }, { path: `${projectName}/07_META/NAMING_EXCEPTIONS.md`, content: `# ai-naming-standard 예외 규칙\n\n## 프로젝트: ${projectName.toUpperCase()}\n**날짜**: ${today} \n**결정자**: Human (Project Owner)\n\n---\n\n## 예외 정책: 하이브리드 접근\n\n### 원칙\n- **프레임워크 필수 파일**: 표준 유지\n- **도구 설정 파일**: 각 도구의 표준 네이밍 유지\n- **자동 생성 파일**: 시스템이 생성하는 파일명 유지\n- **신규 작성 파일**: ai-naming-standard 엄격 적용\n\n---\n\n## 📁 예외 파일 목록\n\n### 프로젝트 루트\n- \`.gitignore\` - Git 표준\n- \`.cursorrules\` - Cursor AI 표준\n- \`.windsurfrules\` - Windsurf AI 표준\n- \`package.json\` - npm 표준\n\n### 00_DOCS/\n- \`*.md\` (대문자) - 문서 관습 (README, CHANGELOG 등)\n\n### 01_CONFIG/\n- 모든 설정 파일 - 프레임워크 표준 유지\n\n### 02_STATIC/\n- 이미지, 폰트 - 원본 이름 유지\n\n### 자동 생성 영역\n- \`node_modules/\` - npm 자동 생성\n- \`05_BUILD/\` - 빌드 자동 생성\n- \`06_LOGS/*.log\` - 로그 자동 생성\n\n---\n\n## 🎯 ai-naming-standard 100% 적용 영역\n\n### 03_ACTIVE/ (신규 파일)\n모든 코드 파일은 **반드시** ai-naming-standard 준수\n\n### 04_TEST/\n모든 테스트 파일은 **반드시** ai-naming-standard 준수\n\n---\n\n## 📝 파일명 규칙 예시\n\n### ✅ 올바른 예시\n\`\`\`\n001_controller_auth-login_render_form_common.jsx\n001_service_user-create_process_api_common.js\n001_helper_date-format_transform_string_common.js\n\`\`\`\n\n### ❌ 잘못된 예시\n\`\`\`\nLoginForm.jsx\nauthService.js\nformatDate.js\n\`\`\`\n` }, { path: `${projectName}/07_META/DEVELOPMENT.md`, content: `# ${projectName.toUpperCase()} 개발 로그\n\n**프로젝트**: ${projectName.toUpperCase()} \n**버전**: 0.1.0 \n**마지막 업데이트**: ${today} \n**다음 목표**: 개발 환경 구축\n\n---\n\n## 🎯 현재 상태\n\n### 프로젝트 단계\n\`\`\`\n[██░░░░░░░░░░░░░░░░] 10% - 프로젝트 초기화 완료\n\`\`\`\n\n### 최근 작업\n- 프로젝트 구조 생성 (ai-naming-standard v6)\n- AI 거버넌스 시스템 구축\n\n### 다음 작업\n- [ ] 개발 환경 설정\n- [ ] 첫 기능 개발 계획\n\n---\n\n## ✅ 완료된 기능\n\n### ${today} - 프로젝트 초기화\n\n#### 8폴더 구조 생성\n- [x] 00_DOCS - 문서\n- [x] 01_CONFIG - 설정\n- [x] 02_STATIC - 정적 자산\n- [x] 03_ACTIVE - 소스 코드\n- [x] 04_TEST - 테스트\n- [x] 05_BUILD - 빌드 결과\n- [x] 06_LOGS - 로그\n- [x] 07_META - AI 메타데이터\n\n**담당**: AI (MCP) \n**완료일**: ${today}\n\n#### AI 거버넌스 시스템\n- [x] AI_RULES.md 생성\n- [x] AI_ROLE_MATRIX.yaml 생성\n- [x] NAMING_EXCEPTIONS.md 생성\n- [x] project.md 생성\n- [x] DEVELOPMENT.md 생성 (이 파일)\n\n**담당**: AI (MCP) \n**완료일**: ${today}\n\n#### 브릿지 파일\n- [x] .cursorrules 생성\n- [x] .windsurfrules 생성\n\n**담당**: AI (MCP) \n**완료일**: ${today}\n\n---\n\n## 🔄 진행 중\n\n(현재 진행 중인 작업 없음)\n\n---\n\n## 📋 예정된 기능\n\n### Phase 1: 개발 환경 구축\n- [ ] 프로젝트 초기 설정\n- [ ] 필요한 라이브러리 선택\n- [ ] 개발 도구 설정\n\n---\n\n## 📚 참조 문서\n\n### AI용 문서\n- \`07_META/AI_RULES.md\` - AI 규칙\n- \`07_META/AI_ROLE_MATRIX.yaml\` - AI 역할/권한\n- \`07_META/NAMING_EXCEPTIONS.md\` - 네이밍 예외\n- \`07_META/project.md\` - 구조적 변경 이력\n\n### 사용자용 문서\n- \`00_DOCS/README.md\` - 프로젝트 소개\n- \`00_DOCS/CHANGELOG.md\` - 변경 이력\n\n---\n\n**마지막 업데이트**: ${today} by AI (MCP)\n` }, { path: `${projectName}/07_META/project.md`, content: `# ${projectName.toUpperCase()} Project Log\n\n## 프로젝트 정보\n- **프로젝트명**: ${projectName.toUpperCase()}\n- **생성일**: ${today}\n- **구조 표준**: ai-naming-standard v6\n- **MCP 버전**: v6.1.0\n\n## 프로젝트 구조 원칙\n- **00_DOCS**: 문서화\n- **01_CONFIG**: 설정 파일\n- **02_STATIC**: 정적 자산\n- **03_ACTIVE**: 소스 코드\n- **04_TEST**: 테스트\n- **05_BUILD**: 빌드 결과물\n- **06_LOGS**: 로그\n- **07_META**: AI 협업 메타데이터\n\n## 변경 이력\n\n### ${today} - 프로젝트 초기 설정\n- **변경자**: AI (MCP v6.1.0)\n- **승인자**: Human (Project Owner)\n- **변경 내용**:\n - ai-naming-standard v6 기반 8폴더 구조 생성\n - AI 거버넌스 시스템 완비 (AI_RULES.md, AI_ROLE_MATRIX.yaml 등)\n - 브릿지 파일 생성 (.cursorrules, .windsurfrules)\n - 기본 문서 구조 완성\n- **영향**:\n - 완전한 AI 거버넌스 시스템 확보\n - 멀티 AI 협업 준비 완료\n - ai-naming-standard v6 100% 준수 구조\n- **근거**:\n - MCP v6.1.0의 loungeservice 기반 업그레이드\n - AI-Human 협업 최적화\n - 프로젝트 확장성 확보\n\n## 개발 규칙\n1. AI는 인간 명령보다 앞서 결정하지 않는다\n2. 스스로 기능, 구조, 파일을 추가하지 않는다\n3. 반드시 승인받는 요청 기반으로만 생성\n4. 모든 생성물은 ai-naming-standard 규칙 준수\n5. 구조 변경은 사용자 승인 필수\n6. 모든 변경사항은 이 문서에 기록\n\n## 다음 단계\n- [ ] 개발 환경 구축\n- [ ] 기술 스택 선정\n- [ ] 첫 기능 개발 계획\n` }, // Bridge Files (루트) { path: `${projectName}/.cursorrules`, content: `# Cursor Rules for ${projectName.toUpperCase()}\n\n## 🎯 프로젝트 개요\n- **프로젝트**: ${projectName.toUpperCase()}\n- **표준**: ai-naming-standard v6\n- **생성일**: ${today}\n\n---\n\n## 📚 작업 시작 전 필수 확인\n\n### 1. AI 규칙\n**파일**: \`07_META/AI_RULES.md\`\n- 11개 절대 규칙 준수\n- Human 승인 없이 파일 생성/삭제 금지\n- 모든 변경사항 기록 필수\n\n### 2. 네이밍 예외\n**파일**: \`07_META/NAMING_EXCEPTIONS.md\`\n- 예외 파일 확인\n- 신규 파일: ai-naming-standard 엄격 적용\n\n### 3. 개발 현황\n**파일**: \`07_META/DEVELOPMENT.md\`\n- 완료된 작업 확인\n- 진행 중인 작업 확인\n- 다음 작업 TODO 확인\n\n---\n\n## 🚨 핵심 규칙\n\n### 1. 인간 우선\n❌ AI 혼자 결정하지 않기 \n✅ 중요한 결정은 Human 승인 받기\n\n### 2. 네이밍 표준\n신규 파일 형식:\n\`\`\`\n[Index]_[Layer]_[Domain]-[Feature]_[Action]_[Detail]_[Env].[ext]\n\`\`\`\n\n### 3. 변경사항 기록\n모든 작업 후:\n1. \`07_META/project.md\` 업데이트 (구조 변경 시)\n2. \`07_META/DEVELOPMENT.md\` 업데이트 (기능 개발 시)\n\n---\n\n## 📁 프로젝트 구조\n\n\`\`\`\n${projectName}/\n├── 00_DOCS/ # 사람용 문서\n├── 01_CONFIG/ # 설정\n├── 02_STATIC/ # 정적 자산\n├── 03_ACTIVE/ # ← 여기서 작업!\n├── 04_TEST/ # 테스트\n├── 05_BUILD/ # 빌드 결과 (자동)\n├── 06_LOGS/ # 로그\n└── 07_META/ # AI 메타데이터\n\`\`\`\n\n---\n\n## 📖 상세 문서\n\n전체 규칙: \`07_META/AI_RULES.md\` \n역할 정의: \`07_META/AI_ROLE_MATRIX.yaml\` \n개발 로그: \`07_META/DEVELOPMENT.md\` \n프로젝트 이력: \`07_META/project.md\`\n\n---\n\n**이 파일은 Cursor가 프로젝트를 열 때마다 자동으로 읽습니다.**\n` }, { path: `${projectName}/.windsurfrules`, content: `# Windsurf Rules for ${projectName.toUpperCase()}\n\n## 🎯 프로젝트 개요\n- **프로젝트**: ${projectName.toUpperCase()}\n- **표준**: ai-naming-standard v6\n- **생성일**: ${today}\n\n---\n\n## 📚 작업 시작 전 필수 확인\n\n### 1. AI 규칙\n**파일**: \`07_META/AI_RULES.md\`\n- 11개 절대 규칙 준수\n- Human 승인 없이 파일 생성/삭제 금지\n- 모든 변경사항 기록 필수\n\n### 2. 네이밍 예외\n**파일**: \`07_META/NAMING_EXCEPTIONS.md\`\n- 예외 파일 확인\n- 신규 파일: ai-naming-standard 엄격 적용\n\n### 3. 개발 현황\n**파일**: \`07_META/DEVELOPMENT.md\`\n- 완료된 작업 확인\n- 진행 중인 작업 확인\n- 다음 작업 TODO 확인\n\n---\n\n## 🚨 핵심 규칙\n\n### 1. 인간 우선\n❌ AI 혼자 결정하지 않기 \n✅ 중요한 결정은 Human 승인 받기\n\n### 2. 네이밍 표준\n신규 파일 형식:\n\`\`\`\n[Index]_[Layer]_[Domain]-[Feature]_[Action]_[Detail]_[Env].[ext]\n\`\`\`\n\n### 3. 변경사항 기록\n모든 작업 후:\n1. \`07_META/project.md\` 업데이트 (구조 변경 시)\n2. \`07_META/DEVELOPMENT.md\` 업데이트 (기능 개발 시)\n\n---\n\n## 📁 프로젝트 구조\n\n\`\`\`\n${projectName}/\n├── 00_DOCS/ # 사람용 문서\n├── 01_CONFIG/ # 설정\n├── 02_STATIC/ # 정적 자산\n├── 03_ACTIVE/ # ← 여기서 작업!\n├── 04_TEST/ # 테스트\n├── 05_BUILD/ # 빌드 결과 (자동)\n├── 06_LOGS/ # 로그\n└── 07_META/ # AI 메타데이터\n\`\`\`\n\n---\n\n## 📖 상세 문서\n\n전체 규칙: \`07_META/AI_RULES.md\` \n역할 정의: \`07_META/AI_ROLE_MATRIX.yaml\` \n개발 로그: \`07_META/DEVELOPMENT.md\` \n프로젝트 이력: \`07_META/project.md\`\n\n---\n\n**이 파일은 Windsurf가 프로젝트를 열 때마다 자동으로 읽습니다.**\n` } ]; // 전체 생성 명령 structure.createCommand = { windows: structure.commands.join(' && '), unix: structure.commands.join(' && ') }; return { ...structure, message: version === 'v6' ? `Project structure created with 8 folders (v6.1.0) - loungeservice grade governance` : msg.v5?.projectCreated || 'Project structure created with 7 standard folders', features: version === 'v6' ? [ '8-folder structure (07_META included)', '✅ Complete AI governance (AI_RULES.md, AI_ROLE_MATRIX.yaml)', '✅ Exception policy (NAMING_EXCEPTIONS.md)', '✅ Development log (DEVELOPMENT.md)', '✅ Project history (project.md)', '✅ Bridge files (.cursorrules, .windsurfrules)', '✅ loungeservice-grade quality' ] : [] }; } // 2. 폴더 권한 체크 도구 export async function checkFolderPermission({ folder, operation = 'modify' }) { const msg = getMessages(); const rules = namingRules(); const folderInfo = rules.standardFolders[folder]; if (!folderInfo) { return { valid: false, error: `Unknown folder: ${folder}`, suggestion: 'Use one of: 00_DOCS, 01_CONFIG, 02_STATIC, 03_ACTIVE, 04_TEST, 05_BUILD, 06_LOGS' }; } const permissions = { '00_DOCS': { read: true, write: false, modify: false, delete: false }, '01_CONFIG': { read: true, write: false, modify: false, delete: false }, '02_STATIC': { read: true, write: true, modify: false, delete: false }, '03_ACTIVE': { read: true, write: true, modify: true, delete: true }, '04_TEST': { read: true, write: true, modify: true, delete: false }, '05_BUILD': { read: true, write: true, modify: false, delete: true }, '06_LOGS': { read: true, write: true, modify: false, delete: false } }; const permission = permissions[folder][operation]; return { folder, operation, allowed: permission, aiPermission: folderInfo.aiPermission, description: folderInfo.description, message: permission ? `AI can ${operation} in ${folder}` : `AI cannot ${operation} in ${folder} (${folderInfo.aiPermission})` }; } // 3. v4에서 v5로 마이그레이션 도구 export async function migrateFromV4({ sourcePath = '.', dryRun = true }) { const msg = getMessages(); const rules = namingRules(); const migration = { version: 'v4 → v5', steps: [], commands: [], fileMovements: [] }; // 마이그레이션 매핑 const folderMapping = { 'docs': '00_DOCS', 'documentation': '00_DOCS', 'README.md': '00_DOCS', 'config': '01_CONFIG', 'settings': '01_CONFIG', '.env': '01_CONFIG', 'public': '02_STATIC', 'static': '02_STATIC', 'assets': '02_STATIC', 'src': '03_ACTIVE', 'lib': '03_ACTIVE', 'app': '03_ACTIVE', 'test': '04_TEST', 'tests': '04_TEST', 'spec': '04_TEST', 'dist': '05_BUILD', 'build': '05_BUILD', 'out': '05_BUILD', 'logs': '06_LOGS', 'log': '06_LOGS' }; // Step 1: 폴더 생성 migration.steps.push({ step: 1, action: 'Create 7 standard folders', commands: Object.keys(rules.standardFolders).map(f => `mkdir ${f}`) }); // Step 2: 파일 이동 계획 for (const [oldPath, newFolder] of Object.entries(folderMapping)) { migration.fileMovements.push({ from: oldPath, to: newFolder, command: `mv ${oldPath}/* ${newFolder}/` }); } // Step 3: 파일명 변환 (03_ACTIVE 내부) migration.steps.push({ step: 2, action: 'Convert file names in 03_ACTIVE', description: 'Apply v5 naming convention to all active code files' }); // 마이그레이션 스크립트 생성 if (!dryRun) { migration.executeScript = migration.fileMovements .map(m => m.command) .join('\n'); } return { ...migration, dryRun, message: dryRun ? msg.v5?.migrationPlan || 'Migration plan created (dry run)' : msg.v5?.migrationExecuted || 'Migration executed successfully' }; } // 4. 파일 폴더 제안 도구 export async function suggestFolder({ fileName, fileType, content }) { const msg = getMessages(); const rules = namingRules(); // 파일 유형별 폴더 매핑 const typeMapping = { 'documentation': '00_DOCS', 'readme': '00_DOCS', 'guide': '00_DOCS', 'config': '01_CONFIG', 'env': '01_CONFIG', 'secret': '01_CONFIG', 'image': '02_STATIC', 'font': '02_STATIC', 'template': '02_STATIC', 'css': '02_STATIC', 'code': '03_ACTIVE', 'component': '03_ACTIVE', 'service': '03_ACTIVE', 'api': '03_ACTIVE', 'test': '04_TEST', 'spec': '04_TEST', 'e2e': '04_TEST', 'build': '05_BUILD', 'dist': '05_BUILD', 'bundle': '05_BUILD', 'log': '06_LOGS', 'error': '06_LOGS', 'audit': '06_LOGS' }; // 확장자별 폴더 매핑 const extensionMapping = { 'md': '00_DOCS', 'txt': '00_DOCS', 'yml': '01_CONFIG', 'yaml': '01_CONFIG', 'env': '01_CONFIG', 'png': '02_STATIC', 'jpg': '02_STATIC', 'svg': '02_STATIC', 'js': '03_ACTIVE', 'jsx': '03_ACTIVE', 'ts': '03_ACTIVE', 'tsx': '03_ACTIVE', 'py': '03_ACTIVE', 'java': '03_ACTIVE', 'test.js': '04_TEST', 'spec.js': '04_TEST', 'min.js': '05_BUILD', 'bundle.js': '05_BUILD', 'log': '06_LOGS' }; let suggestedFolder = '03_ACTIVE'; // 기본값 let reason = 'Default for active code'; // 파일명 분석 if (fileName) { const ext = fileName.split('.').pop().toLowerCase(); // v5 네이밍 패턴 체크 if (/^[0-9]{3}_[A-Z]{2,6}_/.test(fileName)) { suggestedFolder = '03_ACTIVE'; reason = 'Follows v5 naming convention'; } else if (extensionMapping[ext]) { suggestedFolder = extensionMapping[ext]; reason = `Based on extension: .${ext}`; } else if (fileName.includes('test') || fileName.includes('spec')) { suggestedFolder = '04_TEST'; reason = 'Test file detected'; } else if (fileName.includes('config') || fileName.includes('settings')) { suggestedFolder = '01_CONFIG'; reason = 'Configuration file detected'; } } // 파일 타입으로 결정 if (fileType && typeMapping[fileType.toLowerCase()]) { suggestedFolder = typeMapping[fileType.toLowerCase()]; reason = `Based on file type: ${fileType}`; } const folderInfo = rules.standardFolders[suggestedFolder]; return { fileName, suggestedFolder, reason, folderInfo: { name: folderInfo.name, description: folderInfo.description, aiPermission: folderInfo.aiPermission, namingRuleRequired: folderInfo.namingRuleRequired }, alternativeFolders: Object.keys(rules.standardFolders).filter(f => f !== suggestedFolder), message: msg.v5?.folderSuggested || `Suggested folder: ${suggestedFolder} - ${reason}` }; } // ========== 🆕 v6.0.0 Tools Export ========== export { createAIRoleMatrix, getAIRole, naturalLanguageToFileName, addNamingWizardRule, generateDepGraph, validateDeps, checkCircularDeps, logHumanOverride, scanProject, exportConfig } from './v6-tools.js';