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
JavaScript
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';