UNPKG

creatrip-agent-rules-builder

Version:

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

193 lines (170 loc) 6.55 kB
import { Command } from "commander"; import { verifyAgents } from "../verifiers/index"; import { OutputFormat, VerificationSummary } from "../verifiers/types"; import chalk from "chalk"; export function createVerifyCommand(): Command { const command = new Command("verify"); command .description("원본과 생성된 파일들 간의 일관성을 검증합니다") .option( "-r, --recursive", "하위 디렉토리를 재귀적으로 탐색하여 모든 AGENTS.md 검증", ) .option("--json", "JSON 형식으로 결과 출력") .option("--quiet", "종료 코드를 제외한 모든 출력 억제") .action(async (options) => { const outputFormat: OutputFormat = options.json ? "json" : options.quiet ? "quiet" : "human"; const rootPath = process.cwd(); const isRecursive = options.recursive || false; try { const results = await verifyAgents(rootPath, outputFormat, isRecursive); if (outputFormat === "json") { console.log(JSON.stringify(results, null, 2)); } else if (outputFormat === "human") { printHumanReadableResults(results, isRecursive); } process.exit(results.status === "pass" ? 0 : 1); } catch (error) { if (!options.quiet) { console.error( chalk.red( `오류: ${error instanceof Error ? error.message : "알 수 없는 오류"}`, ), ); } process.exit(1); } }); return command; } function printHumanReadableResults( results: VerificationSummary, isRecursive: boolean, ): void { console.log(chalk.blue("에이전트 규칙 일관성 검증 중...")); if (!isRecursive) { // 단일 디렉토리 모드 (기존과 동일) const location = results.locations[0]; // 각 에이전트별 결과 출력 for (const [agentName, result] of Object.entries(location.agents)) { if (result.passed) { console.log(chalk.green(`✓ ${agentName}: 동기화됨`)); } else { const errorMsg = result.error === "content mismatch" ? "내용 불일치" : result.error === "file not found" ? "파일 없음" : result.error || "내용 불일치"; console.log(chalk.red(`✗ ${agentName}: ${errorMsg}`)); } } // 패턴 분석 결과 및 권장 사항 출력 if (location.diagnosis) { console.log(""); // 빈 줄 추가 switch (location.diagnosis.pattern) { case "all_synced": console.log(chalk.green("✓ 모든 파일이 동기화되어 있습니다")); break; case "all_outdated": console.log(chalk.yellow("→ 패턴 감지: 모든 파일이 오래됨")); console.log(chalk.yellow("→ 해결방법: 'agent-rules build' 실행")); break; case "single_diverged": const divergedFile = location.diagnosis.diverged?.[0]; console.log( chalk.yellow(`→ 패턴 감지: ${divergedFile} 파일만 불일치`), ); console.log( chalk.yellow(`→ AGENTS.md를 수정하려던 것이 아닌지 확인하세요`), ); break; case "multiple_diverged": console.log(chalk.yellow("→ 패턴 감지: 여러 파일 불일치")); console.log(chalk.yellow("→ 수동 검토가 필요합니다")); break; } } // 최종 결과 console.log(""); // 빈 줄 추가 if (location.status === "pass") { console.log(chalk.green("✓ 모든 에이전트 검증 성공")); } else { console.log( chalk.red( `✗ 검증 실패: ${location.summary.total}개 중 ${location.summary.failed}개 불일치`, ), ); } } else { // 재귀 모드 console.log(""); for (const location of results.locations) { const relativePath = location.path.replace(process.cwd(), "") || "/"; console.log(chalk.cyan(`📁 ${relativePath}`)); // 각 에이전트별 결과 출력 for (const [agentName, result] of Object.entries(location.agents)) { if (result.passed) { console.log(chalk.green(` ✓ ${agentName}: 동기화됨`)); } else { const errorMsg = result.error === "content mismatch" ? "내용 불일치" : result.error === "file not found" ? "파일 없음" : result.error || "내용 불일치"; console.log(chalk.red(` ✗ ${agentName}: ${errorMsg}`)); } } // 패턴 분석 결과 if (location.diagnosis && location.diagnosis.pattern !== "all_synced") { switch (location.diagnosis.pattern) { case "all_outdated": console.log(chalk.yellow(" → 패턴 감지: 모든 파일이 오래됨")); console.log(chalk.yellow(" → 해결방법: 'agent-rules build' 실행")); break; case "single_diverged": const divergedFile = location.diagnosis.diverged?.[0]; console.log( chalk.yellow(` → 패턴 감지: ${divergedFile} 파일만 불일치`), ); console.log( chalk.yellow(` → AGENTS.md를 수정하려던 것이 아닌지 확인하세요`), ); break; case "multiple_diverged": console.log(chalk.yellow(" → 패턴 감지: 여러 파일 불일치")); console.log(chalk.yellow(" → 수동 검토가 필요합니다")); break; } } else if (location.diagnosis?.pattern === "all_synced") { console.log(chalk.green(" ✓ 모든 파일이 동기화되어 있습니다")); } console.log(""); // 위치 간 구분 } // 전체 요약 console.log("========================================"); const failedLocations = results.locations.filter( (loc) => loc.status === "fail", ).length; if (results.status === "pass") { console.log( chalk.green( `📊 전체 요약: ${results.totalLocations}개 위치 모두 동기화됨`, ), ); console.log(chalk.green("✓ 검증 성공")); } else { console.log( chalk.yellow( `📊 전체 요약: ${results.totalLocations}개 위치 중 ${failedLocations}개 불일치`, ), ); console.log(chalk.red("✗ 검증 실패")); } } }