UNPKG

aiwf

Version:

AI Workflow Framework for Claude Code with multi-language support (Korean/English)

502 lines (414 loc) 15.8 kB
#!/usr/bin/env node /** * YOLO 설정 파일 자동 생성 및 관리 * AIWF YOLO 모드의 설정을 초기화하고 관리하는 유틸리티 */ import fs from 'fs/promises'; import path from 'path'; import chalk from 'chalk'; import prompts from 'prompts'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /** * 프로젝트 루트 찾기 */ async function findProjectRoot(startDir = process.cwd()) { let currentDir = startDir; while (currentDir !== path.parse(currentDir).root) { try { await fs.access(path.join(currentDir, '.aiwf')); return currentDir; } catch { currentDir = path.dirname(currentDir); } } throw new Error('.aiwf 디렉토리를 찾을 수 없습니다. AIWF 프로젝트 내에서 실행해주세요.'); } /** * YOLO 설정 파일 생성 */ export async function createYoloConfig(options = {}) { try { const projectRoot = await findProjectRoot(); const configPath = path.join(projectRoot, '.aiwf', 'yolo-config.yaml'); const templatePath = path.join(__dirname, '..', 'config', 'yolo-config-template.yaml'); // .aiwf 디렉토리 확인 const aiwfDir = path.join(projectRoot, '.aiwf'); await fs.mkdir(aiwfDir, { recursive: true }); // 기존 설정 파일이 있는지 확인 let shouldOverwrite = false; try { await fs.access(configPath); if (!options.force) { const response = await prompts({ type: 'confirm', name: 'overwrite', message: 'YOLO 설정 파일이 이미 존재합니다. 덮어쓰시겠습니까?', initial: false }); shouldOverwrite = response.overwrite; } else { shouldOverwrite = true; } } catch { shouldOverwrite = true; } if (!shouldOverwrite) { console.log(chalk.yellow('⏭️ YOLO 설정 파일 생성을 건너뜁니다.')); return { success: false, skipped: true }; } // 템플릿 파일 복사 const templateContent = await fs.readFile(templatePath, 'utf-8'); // 옵션에 따라 설정 커스터마이징 let customizedContent = templateContent; if (options.engineeringLevel) { customizedContent = customizedContent.replace( /engineering_level: minimal/, `engineering_level: ${options.engineeringLevel}` ); } if (options.focusMode) { // 포커스 모드에 따른 규칙 조정 if (options.focusMode === 'strict') { customizedContent = customizedContent.replace( /no_gold_plating: true/, 'no_gold_plating: true\n \n # 엄격 모드 추가 규칙\n strict_requirements: true\n no_extras: true' ); } } await fs.writeFile(configPath, customizedContent); console.log(chalk.green('✅ YOLO 설정 파일이 생성되었습니다!')); console.log(`📁 위치: ${chalk.cyan(configPath)}`); return { success: true, configPath }; } catch (error) { throw new Error(`YOLO 설정 파일 생성 실패: ${error.message}`); } } /** * 대화형 YOLO 설정 생성 */ export async function createInteractiveYoloConfig() { try { console.log(chalk.bold('🛠️ YOLO 설정 마법사')); console.log(''); console.log(chalk.gray('YOLO 모드의 동작을 커스터마이징할 수 있습니다.')); console.log(''); const responses = await prompts([ { type: 'select', name: 'engineeringLevel', message: '엔지니어링 레벨을 선택하세요:', choices: [ { title: '최소 (Minimal) - 빠른 프로토타입, 최소 구현', value: 'minimal' }, { title: '균형 (Balanced) - 품질과 속도의 균형', value: 'balanced' }, { title: '완전 (Complete) - 완전한 구현, 높은 품질', value: 'complete' } ], initial: 0 }, { type: 'multiselect', name: 'focusRules', message: '포커스 규칙을 선택하세요 (스페이스바로 선택):', choices: [ { title: '요구사항 우선 (requirement_first)', value: 'requirement_first', selected: true }, { title: '간단한 해결책 (simple_solution)', value: 'simple_solution', selected: true }, { title: '골드 플레이팅 방지 (no_gold_plating)', value: 'no_gold_plating', selected: true }, { title: '트랙 유지 (stay_on_track)', value: 'stay_on_track', selected: true }, { title: '리팩토링 제한 (limit_refactoring)', value: 'limit_refactoring', selected: false } ], min: 1 }, { type: 'select', name: 'executionMode', message: '실행 모드를 선택하세요:', choices: [ { title: '빠른 모드 - 최소 검증, 빠른 실행', value: 'fast' }, { title: '스마트 모드 - 컨텍스트 기반 의사결정', value: 'smart' }, { title: '안전 모드 - 철저한 검증', value: 'safe' } ], initial: 0 }, { type: 'confirm', name: 'enableCheckpoints', message: '체크포인트 시스템을 활성화하시겠습니까?', initial: true }, { type: prev => prev ? 'number' : null, name: 'checkpointInterval', message: '체크포인트 간격 (태스크 수):', initial: 5, min: 1, max: 20 }, { type: 'confirm', name: 'autoCommit', message: '태스크 완료 시 자동 커밋을 사용하시겠습니까?', initial: false }, { type: 'number', name: 'maxFileLines', message: '최대 파일 크기 (줄 수):', initial: 300, min: 100, max: 1000 }, { type: 'number', name: 'maxFunctionLines', message: '최대 함수 크기 (줄 수):', initial: 50, min: 20, max: 200 } ]); // 응답이 중단된 경우 처리 if (!responses.engineeringLevel) { console.log(chalk.yellow('⏭️ 설정 생성이 취소되었습니다.')); return { success: false, cancelled: true }; } console.log(''); console.log(chalk.blue('🔧 YOLO 설정 파일 생성 중...')); // 커스텀 설정 파일 생성 const customConfig = await generateCustomConfig(responses); const projectRoot = await findProjectRoot(); const configPath = path.join(projectRoot, '.aiwf', 'yolo-config.yaml'); await fs.mkdir(path.dirname(configPath), { recursive: true }); await fs.writeFile(configPath, customConfig); console.log(chalk.green('✅ 커스텀 YOLO 설정이 생성되었습니다!')); console.log(`📁 위치: ${chalk.cyan(configPath)}`); console.log(''); // 설정 요약 표시 console.log(chalk.bold('📋 설정 요약:')); console.log(` 엔지니어링 레벨: ${chalk.yellow(responses.engineeringLevel)}`); console.log(` 실행 모드: ${chalk.yellow(responses.executionMode)}`); console.log(` 체크포인트: ${chalk.yellow(responses.enableCheckpoints ? '활성화' : '비활성화')}`); console.log(` 자동 커밋: ${chalk.yellow(responses.autoCommit ? '활성화' : '비활성화')}`); console.log(` 최대 파일 크기: ${chalk.blue(responses.maxFileLines)}줄`); console.log(''); console.log(chalk.green('🚀 이제 YOLO 모드를 실행할 준비가 되었습니다!')); console.log(chalk.blue('Claude Code에서 /project:aiwf:yolo 를 실행하세요.')); return { success: true, configPath, config: responses }; } catch (error) { if (error.message.includes('cancelled')) { console.log(chalk.yellow('⏭️ 설정 생성이 취소되었습니다.')); return { success: false, cancelled: true }; } throw error; } } /** * 커스텀 설정 파일 생성 */ async function generateCustomConfig(responses) { const config = `# YOLO Mode Configuration - AIWF 자율 실행 모드 설정 # 마법사로 생성된 커스텀 설정 # 엔지니어링 레벨 설정 engineering_level: ${responses.engineeringLevel} # 포커스 규칙 - 곁길로 빠지지 않도록 제어 focus_rules: ${responses.focusRules.map(rule => { switch(rule) { case 'requirement_first': return ' # 요구사항 우선 - 명시된 요구사항만 구현\n requirement_first: true'; case 'simple_solution': return ' # 간단한 해결책 선호\n simple_solution: true'; case 'no_gold_plating': return ' # 골드 플레이팅 방지 - 필요 이상의 기능 추가 금지\n no_gold_plating: true'; case 'stay_on_track': return ' # 트랙 유지 - 원래 목표에서 벗어나지 않음\n stay_on_track: true'; case 'limit_refactoring': return ' # 리팩토링 제한 - 필수적인 경우만 허용\n limit_refactoring: true'; default: return ''; } }).join('\n \n')} # 실행 모드 설정 execution: # 스마트 모드 - 컨텍스트 기반 의사결정 smart_mode: ${responses.executionMode === 'smart'} # 빠른 실행 - 최소한의 검증만 수행 fast_mode: ${responses.executionMode === 'fast'} # 안전 모드 - 철저한 검증 safe_mode: ${responses.executionMode === 'safe'} # 테스트 실행 - 각 태스크 완료 후 테스트 run_tests: true # 커밋 자동화 - 태스크 완료 시 자동 커밋 auto_commit: ${responses.autoCommit} # 브랜치 전략 branch_strategy: feature # feature, direct, worktree # 중단 조건 - 이러한 상황에서 YOLO 모드 중단 breakpoints: # 중요 파일 수정 시 critical_files: - .env - database/migrations/* - config/production.js # 테스트 실패 임계값 (%) test_failure_threshold: 10 # 데이터베이스 스키마 변경 시 schema_changes: true # 보안 관련 변경 시 security_changes: true # 외부 API 통합 시 external_api: false # 진행률 리포트 설정 reporting: # 상세 레벨 verbosity: normal # quiet, normal, verbose # 진행률 업데이트 빈도 (태스크 단위) update_frequency: 1 # 요약 리포트 생성 generate_summary: true # 메트릭 추적 track_metrics: true # 오버엔지니어링 방지 규칙 overengineering_prevention: # 최대 파일 크기 (줄) max_file_lines: ${responses.maxFileLines} # 최대 함수 크기 (줄) max_function_lines: ${responses.maxFunctionLines} # 최대 중첩 깊이 max_nesting_depth: 4 # 추상화 레벨 제한 max_abstraction_layers: 3 # 디자인 패턴 사용 제한 limit_design_patterns: true # 미래를 위한 코드 금지 no_future_proofing: true # 체크포인트 설정 checkpoint: # 체크포인트 활성화 enabled: ${responses.enableCheckpoints} # 체크포인트 간격 (태스크 수) interval: ${responses.checkpointInterval || 5} # 복구 모드 recovery_mode: auto # auto, manual, disabled # 상태 저장 위치 state_file: .aiwf/yolo-state.json # 태스크 우선순위 설정 priority: # 우선순위 가중치 weights: urgency: 0.4 importance: 0.3 dependencies: 0.2 effort: 0.1 # 의존성 우선 실행 dependency_first: true # 블로커 태스크 즉시 처리 handle_blockers: true # AI 페르소나 설정 persona: # 기본 페르소나 default: developer # 태스크별 페르소나 자동 선택 auto_select: true # 페르소나 전환 규칙 rules: - pattern: "API|백엔드|서버" persona: backend - pattern: "UI|프론트|컴포넌트" persona: frontend - pattern: "테스트|검증|QA" persona: tester # 성능 최적화 performance: # 병렬 실행 (실험적) parallel_tasks: false # 캐시 활용 use_cache: true # 불필요한 파일 읽기 스킵 skip_unchanged: true # 압축 모드 사용 compression_mode: auto # 안전 장치 safety: # 드라이런 모드 - 실제 변경 없이 시뮬레이션 dry_run: false # 백업 생성 create_backup: true # 최대 실행 시간 (분) max_runtime: 120 # 확인 프롬프트 표시 confirmation_prompts: false`; return config; } /** * 현재 YOLO 설정 확인 */ export async function showYoloConfig() { try { const projectRoot = await findProjectRoot(); const configPath = path.join(projectRoot, '.aiwf', 'yolo-config.yaml'); try { const configContent = await fs.readFile(configPath, 'utf-8'); console.log(chalk.bold('🛠️ 현재 YOLO 설정:')); console.log(`📁 위치: ${chalk.cyan(configPath)}`); console.log(''); // 주요 설정 추출 const engineeringLevel = configContent.match(/engineering_level:\s*(\w+)/)?.[1] || 'unknown'; const enabledRules = []; if (configContent.includes('requirement_first: true')) enabledRules.push('요구사항 우선'); if (configContent.includes('simple_solution: true')) enabledRules.push('간단한 해결책'); if (configContent.includes('no_gold_plating: true')) enabledRules.push('골드 플레이팅 방지'); if (configContent.includes('stay_on_track: true')) enabledRules.push('트랙 유지'); const checkpointEnabled = configContent.includes('enabled: true'); const autoCommit = configContent.includes('auto_commit: true'); console.log(chalk.bold('📋 주요 설정:')); console.log(` 엔지니어링 레벨: ${chalk.yellow(engineeringLevel)}`); console.log(` 포커스 규칙: ${chalk.blue(enabledRules.join(', '))}`); console.log(` 체크포인트: ${chalk.yellow(checkpointEnabled ? '활성화' : '비활성화')}`); console.log(` 자동 커밋: ${chalk.yellow(autoCommit ? '활성화' : '비활성화')}`); console.log(''); console.log(chalk.gray('전체 설정을 보려면 파일을 직접 확인하세요:')); console.log(chalk.blue(`cat ${configPath}`)); } catch (error) { console.log(chalk.yellow('⚠️ YOLO 설정 파일이 없습니다.')); console.log(''); console.log(chalk.gray('설정 파일을 생성하려면:')); console.log(chalk.blue('aiwf yolo-config init')); } } catch (error) { throw new Error(`YOLO 설정 확인 실패: ${error.message}`); } } /** * CLI에서 실행될 때 */ if (import.meta.url === `file://${process.argv[1]}`) { const command = process.argv[2]; switch (command) { case 'init': createYoloConfig({ force: process.argv.includes('--force') }) .catch(error => { console.error(chalk.red(`오류: ${error.message}`)); process.exit(1); }); break; case 'wizard': case 'interactive': createInteractiveYoloConfig() .catch(error => { console.error(chalk.red(`오류: ${error.message}`)); process.exit(1); }); break; case 'show': case 'status': showYoloConfig() .catch(error => { console.error(chalk.red(`오류: ${error.message}`)); process.exit(1); }); break; default: console.log(chalk.bold('🛠️ YOLO 설정 관리')); console.log(''); console.log(chalk.yellow('사용법:')); console.log(` ${chalk.blue('node yolo-config.js init')} - 기본 설정 파일 생성`); console.log(` ${chalk.blue('node yolo-config.js wizard')} - 대화형 설정 생성`); console.log(` ${chalk.blue('node yolo-config.js show')} - 현재 설정 확인`); break; } } export default { createYoloConfig, createInteractiveYoloConfig, showYoloConfig };