UNPKG

creatrip-agent-rules-builder

Version:

Unified converter for AI coding agent rules across Cursor, Windsurf, and Claude

196 lines 8.97 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCICommand = createCICommand; const commander_1 = require("commander"); const chalk_1 = __importDefault(require("chalk")); const verifiers_1 = require("../verifiers"); const build_1 = require("../build"); function createCICommand() { const command = new commander_1.Command("ci"); command .description("스마트 동기화: 자동으로 검증하고 필요시 빌드 실행") .option("-r, --recursive", "하위 디렉토리를 재귀적으로 처리") .option("--json", "JSON 형식으로 결과 출력") .action(async (options) => { const isRecursive = options.recursive || false; const isJson = options.json || false; try { const result = await runCI(isRecursive, isJson); if (isJson) { console.log(JSON.stringify(result, null, 2)); } process.exit(result.status === "pass" ? 0 : 1); } catch (error) { if (!isJson) { console.error(chalk_1.default.red(`오류: ${error instanceof Error ? error.message : "알 수 없는 오류"}`)); } process.exit(1); } }); return command; } async function runCI(isRecursive, isJson) { const rootPath = process.cwd(); if (!isJson) { console.log(chalk_1.default.blue("🔍 일관성 검증 중...")); } // 1단계: 검증 const verifyResult = await (0, verifiers_1.verifyAgents)(rootPath, "json", isRecursive); const ciResult = { status: "pass", summary: { total: 0, synced: 0, autoBuild: 0, needsReview: 0, }, message: "", }; const needsReviewList = []; // 각 위치별로 처리 for (const location of verifyResult.locations) { ciResult.summary.total++; if (location.status === "pass") { // 이미 동기화됨 ciResult.summary.synced++; if (!isJson) { const relativePath = location.path.replace(rootPath, "") || "/"; if (isRecursive) { console.log(chalk_1.default.green(`📁 ${relativePath}`)); console.log(chalk_1.default.green(" ✅ 동기화됨")); } } } else { // 패턴에 따라 처리 switch (location.diagnosis?.pattern) { case "all_outdated": // 자동 빌드 실행 if (!isJson) { const relativePath = location.path.replace(rootPath, "") || "/"; if (isRecursive) { console.log(chalk_1.default.cyan(`📁 ${relativePath}`)); console.log(chalk_1.default.yellow(" ⚠️ 오래됨 → 자동 빌드")); } else { console.log(chalk_1.default.yellow("⚠️ 모든 파일이 오래됨 (AGENTS.md가 더 최신)")); console.log(chalk_1.default.blue("🔨 자동으로 빌드를 실행합니다...")); } } // 빌드 실행 await buildRulesForLocation(location.path, isJson); ciResult.summary.autoBuild++; if (!isJson) { if (isRecursive) { console.log(chalk_1.default.green(" ✅ 빌드 완료")); } else { console.log(chalk_1.default.green("✅ 빌드 완료 - 모든 파일이 동기화되었습니다")); } } break; case "single_diverged": case "multiple_diverged": // 수동 검토 필요 ciResult.status = "fail"; ciResult.summary.needsReview++; const relativePath = location.path.replace(rootPath, "") || "/"; needsReviewList.push({ path: relativePath, issue: location.diagnosis.pattern, files: location.diagnosis.diverged, }); if (!isJson) { if (isRecursive) { console.log(chalk_1.default.red(`📁 ${relativePath}`)); if (location.diagnosis.pattern === "single_diverged") { console.log(chalk_1.default.red(` ❌ ${location.diagnosis.diverged?.[0]} 파일 수동 편집 감지`)); } else { console.log(chalk_1.default.red(` ❌ 여러 파일 수동 편집 감지`)); } } else { if (location.diagnosis.pattern === "single_diverged") { console.log(chalk_1.default.red(`❌ ${location.diagnosis.diverged?.[0]} 파일에 수동 편집 감지`)); console.log(""); console.log(chalk_1.default.yellow("수동 검토가 필요합니다:")); console.log(chalk_1.default.yellow(`- ${location.diagnosis.diverged?.[0]} 파일이 직접 수정되었습니다`)); console.log(chalk_1.default.yellow("- AGENTS.md를 수정하려던 것이 아닌지 확인하세요")); } else { console.log(chalk_1.default.red("❌ 여러 파일에서 수동 편집 감지")); console.log(""); console.log(chalk_1.default.yellow("수동 검토가 필요합니다:")); location.diagnosis.diverged?.forEach((file) => { console.log(chalk_1.default.yellow(`- ${file} 파일이 직접 수정됨`)); }); } } } break; } } if (!isJson && isRecursive) { console.log(""); // 위치 간 구분 } } // 결과 메시지 설정 if (ciResult.status === "pass") { if (ciResult.summary.autoBuild > 0) { ciResult.message = `Auto-build completed for ${ciResult.summary.autoBuild} location(s)`; } else { ciResult.message = "All files are already synchronized"; } if (!isJson) { if (isRecursive) { console.log("========================================"); console.log(chalk_1.default.green(`📊 요약: ${ciResult.summary.total}개 위치 모두 동기화됨`)); if (ciResult.summary.autoBuild > 0) { console.log(chalk_1.default.green(` (${ciResult.summary.autoBuild}개 자동 빌드됨)`)); } } else if (ciResult.summary.autoBuild === 0) { console.log(chalk_1.default.green("✅ 이미 모든 파일이 동기화되어 있습니다")); } } } else { ciResult.needsReview = needsReviewList; ciResult.message = `Manual review required for ${ciResult.summary.needsReview} location(s)`; if (!isJson && isRecursive) { console.log("========================================"); console.log(chalk_1.default.yellow(`📊 요약: ${ciResult.summary.total}개 위치 중 ${ciResult.summary.needsReview}개 수동 검토 필요`)); console.log(chalk_1.default.red("❌ CI 실패: 수동 검토가 필요한 파일이 있습니다")); console.log(""); console.log(chalk_1.default.yellow("문제 위치:")); needsReviewList.forEach((item) => { console.log(chalk_1.default.yellow(`- ${item.path}: ${item.files?.join(", ")} 파일 수동 편집`)); }); } } return ciResult; } async function buildRulesForLocation(locationPath, isJson) { // build.ts의 로직 재사용 const options = { file: `${locationPath}/AGENTS.md`, }; // 빌드 실행 (출력 억제) const originalLog = console.log; if (isJson) { console.log = () => { }; // JSON 모드에서는 출력 억제 } try { await (0, build_1.buildRules)(options); } finally { console.log = originalLog; } } //# sourceMappingURL=ci.js.map