#!/usr/bin/env python # -*- coding: utf-8 -*- """ tools/validate_enterprise_crud_specification_v1.py OMS·WMS·ERP CRUD 화면 및 입력 컴포넌트 상용화 지침 명세(docs/ENTERPRISE_CRUD_DESIGN_SPECIFICATION.md) 및 11대 표준 템플릿(TPL-LIST-01~TPL-HISTORY-01) 자동 검증 하네스 CLI. 검증 항목: 1. docs/ENTERPRISE_CRUD_DESIGN_SPECIFICATION.md 명세 문서 및 25개 표준 섹션 파싱 검증. 2. 11대 표준 템플릿 ID(TPL-LIST-01 ~ TPL-HISTORY-01) 문서 표출 검증. 3. docs/ROADMAP_ENTERPRISE_TEMPLATES_WBS.md 로드맵 WBS 파일 존재 검증. 4. src/frontend/src/types/enterpriseTemplateContracts.ts 타입 계약 파일 존재 검증. 5. AGENTS.md 운영 헌법 매핑 검증. 6. Temp/enterprise_crud_validation_report_v1.json 및 Temp/enterprise_crud_validation_report_v1.md 검증 결과 패킷 생성. """ import sys import os import json from pathlib import Path # Windows UTF-8 강제 if sys.platform == "win32": sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") REPO_ROOT = Path(__file__).resolve().parent.parent SPEC_FILE = REPO_ROOT / "docs" / "ENTERPRISE_CRUD_DESIGN_SPECIFICATION.md" WBS_FILE = REPO_ROOT / "docs" / "ROADMAP_ENTERPRISE_TEMPLATES_WBS.md" TYPES_FILE = REPO_ROOT / "src" / "frontend" / "src" / "types" / "enterpriseTemplateContracts.ts" AGENTS_FILE = REPO_ROOT / "AGENTS.md" TEMP_DIR = REPO_ROOT / "Temp" REQUIRED_TEMPLATE_IDS = [ "TPL-LIST-01", "TPL-CREATE-01", "TPL-CREATE-02", "TPL-CREATE-03", "TPL-DETAIL-01", "TPL-EDIT-01", "TPL-BULK-01", "TPL-DELETE-01", "TPL-CANCEL-01", "TPL-APPROVAL-01", "TPL-HISTORY-01" ] REQUIRED_SECTIONS_COUNT = 25 def run_harness_validation(): results = { "status": "PASS", "spec_document": False, "wbs_document": False, "types_contract": False, "agents_integration": False, "parsed_sections_count": 0, "verified_templates_count": 0, "missing_templates": [], "checks": [] } print("======================================================================") print(" OMS·WMS·ERP CRUD & Template Specification Harness Validator v2.0") print("======================================================================\n") # 1. Spec Document Verification if not SPEC_FILE.exists(): results["status"] = "FAIL" results["checks"].append({"rule": "SPEC_FILE_EXISTS", "passed": False, "message": f"Spec file missing: {SPEC_FILE}"}) print(f"[FAIL] Spec file not found: {SPEC_FILE}") else: results["spec_document"] = True results["checks"].append({"rule": "SPEC_FILE_EXISTS", "passed": True, "message": "Spec file exists."}) print(f"[PASS] Found specification document: {SPEC_FILE}") content = SPEC_FILE.read_text(encoding="utf-8") # Check Section Count section_headers = [line for line in content.splitlines() if line.startswith("## ")] results["parsed_sections_count"] = len(section_headers) if len(section_headers) >= REQUIRED_SECTIONS_COUNT: results["checks"].append({"rule": "ALL_25_SECTIONS_PRESENT", "passed": True, "message": f"Verified {len(section_headers)} sections."}) print(f"[PASS] All {REQUIRED_SECTIONS_COUNT} mandatory specification sections verified ({len(section_headers)}/25).") else: results["status"] = "FAIL" results["checks"].append({"rule": "ALL_25_SECTIONS_PRESENT", "passed": False, "message": f"Section count mismatch: {len(section_headers)}/25"}) print(f"[FAIL] Missing sections in specification ({len(section_headers)}/25).") # Check 11 Template IDs found_templates = [tpl for tpl in REQUIRED_TEMPLATE_IDS if tpl in content] results["verified_templates_count"] = len(found_templates) missing_tpls = [tpl for tpl in REQUIRED_TEMPLATE_IDS if tpl not in content] results["missing_templates"] = missing_tpls if len(found_templates) == len(REQUIRED_TEMPLATE_IDS): results["checks"].append({"rule": "ALL_11_TEMPLATES_VERIFIED", "passed": True, "message": "All 11 standard template IDs present."}) print(f"[PASS] All 11 standard template IDs verified ({len(found_templates)}/11).") else: results["status"] = "FAIL" results["checks"].append({"rule": "ALL_11_TEMPLATES_VERIFIED", "passed": False, "message": f"Missing templates: {missing_tpls}"}) print(f"[FAIL] Missing template IDs: {missing_tpls}") # 2. WBS Roadmap Document Check if not WBS_FILE.exists(): results["status"] = "FAIL" results["checks"].append({"rule": "WBS_ROADMAP_EXISTS", "passed": False, "message": f"WBS file missing: {WBS_FILE}"}) print(f"[FAIL] WBS Roadmap missing: {WBS_FILE}") else: results["wbs_document"] = True results["checks"].append({"rule": "WBS_ROADMAP_EXISTS", "passed": True, "message": "WBS Roadmap exists."}) print(f"[PASS] Found WBS Roadmap document: {WBS_FILE}") # 3. TypeScript Contracts Check if not TYPES_FILE.exists(): results["status"] = "FAIL" results["checks"].append({"rule": "TYPES_CONTRACT_EXISTS", "passed": False, "message": f"Types contract missing: {TYPES_FILE}"}) print(f"[FAIL] Types contract file missing: {TYPES_FILE}") else: results["types_contract"] = True types_code = TYPES_FILE.read_text(encoding="utf-8") if "EnterpriseTemplateId" in types_code and "FieldStatus" in types_code: results["checks"].append({"rule": "TYPES_CONTRACT_VALID", "passed": True, "message": "EnterpriseTemplateId & FieldStatus contract types verified."}) print("[PASS] TypeScript contract file enterpriseTemplateContracts.ts verified.") else: results["status"] = "FAIL" results["checks"].append({"rule": "TYPES_CONTRACT_VALID", "passed": False, "message": "Missing types in enterpriseTemplateContracts.ts"}) # 4. AGENTS.md Integration Check if not AGENTS_FILE.exists(): results["status"] = "FAIL" results["checks"].append({"rule": "AGENTS_FILE_EXISTS", "passed": False, "message": "AGENTS.md missing."}) else: agents_content = AGENTS_FILE.read_text(encoding="utf-8") if "ENTERPRISE_CRUD_DESIGN_SPECIFICATION.md" in agents_content: results["agents_integration"] = True results["checks"].append({"rule": "AGENTS_AUTHORITY_MAPPED", "passed": True, "message": "AGENTS.md mapped with authority."}) print("[PASS] AGENTS.md authority mapping verified.") else: results["status"] = "FAIL" results["checks"].append({"rule": "AGENTS_AUTHORITY_MAPPED", "passed": False, "message": "AGENTS.md lacks specification mapping."}) # Generate Audit Artifacts in Temp/ TEMP_DIR.mkdir(parents=True, exist_ok=True) json_packet = TEMP_DIR / "enterprise_crud_validation_report_v1.json" md_summary = TEMP_DIR / "enterprise_crud_validation_report_v1.md" with open(json_packet, "w", encoding="utf-8") as jf: json.dump(results, jf, indent=2, ensure_ascii=False) md_text = f"""# Enterprise OMS/WMS/ERP CRUD & Template Specification Harness Report * **Validation Status**: `{results['status']}` * **Specification File**: `{SPEC_FILE}` * **WBS Roadmap File**: `{WBS_FILE}` * **Parsed Sections Count**: `{results['parsed_sections_count']}/25` * **Verified Templates**: `{results['verified_templates_count']}/11` * **AGENTS.md Integration**: `{results['agents_integration']}` ## Verified Checks """ for chk in results["checks"]: symbol = "✅ PASS" if chk["passed"] else "❌ FAIL" md_text += f"- **[{symbol}] {chk['rule']}**: {chk['message']}\n" md_summary.write_text(md_text, encoding="utf-8") print("\n----------------------------------------------------------------------") print(f" Harness Execution Result: {results['status']}") print(f" JSON Packet Saved: {json_packet}") print(f" Summary MD Saved: {md_summary}") print("----------------------------------------------------------------------\n") if results["status"] != "PASS": sys.exit(1) if __name__ == "__main__": run_harness_validation()