"""synonyms 관리 기준 리포트 — production + candidate 이원화""" import sys from pathlib import Path import yaml sys.path.insert(0, str(Path(__file__).parent)) HERE = Path(__file__).parent def main(): with open(HERE / "synonyms.yaml", encoding="utf-8") as f: prod = yaml.safe_load(f)["synonyms"] with open(HERE / "synonyms_candidates.yaml", encoding="utf-8") as f: cand = yaml.safe_load(f)["candidates"] lines = [] lines.append("# Synonym 사전 관리 기준 — 이원화") lines.append("") lines.append("> **초안 검수 결과 반영 판**: 기준과 실제 사전의 모순을 해소하기 위해 " "production/candidate로 분리.") lines.append("") # 1. 운영 원칙 lines.append("## 1. 운영 원칙 (v2)") lines.append("") lines.append("- **이원화**: `synonyms.yaml` (production, 최소본) + `synonyms_candidates.yaml` (검수 대기)") lines.append("- **production 진입 기준 (엄격)**:") lines.append(" 1. 실제 데이터(MDX + Figma)에 **등장 확인**") lines.append(" 2. **매칭 케이스에 직접 영향** 확인") lines.append(" 3. **일반 용어/유의어 아님** (엄밀 동의어)") lines.append("- **candidate 승격 프로세스**:") lines.append(" 1. 실패 케이스 분석") lines.append(" 2. candidate에서 해당 항목 확인") lines.append(" 3. 회귀 테스트 통과 시 production으로 이동") lines.append("- 일반 용어는 **영구적으로 제외** (reject 처리)") lines.append("") # 2. Production 사전 lines.append(f"## 2. Production 사전 ({len(prod)}개 canonical)") lines.append("") lines.append("실전 매칭에 사용. 변경은 회귀 테스트 필수.") lines.append("") lines.append("| Canonical | Variants | 등록 이유 |") lines.append("|-----------|----------|-----------|") reasons = { "필수조건": "MDX03-1 정답 매칭에 필수", "DX": "MDX/Figma 전반 빈번", "과정혁신": "MDX03-2 정답 매칭에 필수", "결과혁신": "MDX03-2 정답 매칭에 필수", "3D모델": "MDX 전반 띄어쓰기 혼용", "2D도면": "MDX 전반 띄어쓰기 혼용", } for canonical, variants in prod.items(): reason = reasons.get(canonical, "-") lines.append(f"| `{canonical}` | {', '.join('`' + v + '`' for v in variants)} | {reason} |") lines.append("") total_prod_v = sum(len(v) for v in prod.values()) lines.append(f"**총 variants {total_prod_v}개** (데이터 기반 검증 완료)") lines.append("") # 3. Candidate 사전 eo = [(c, d) for c, d in cand.items() if d.get("status") == "evidence_only"] rj = [(c, d) for c, d in cand.items() if d.get("status") == "reject"] lines.append(f"## 3. Candidate 사전 (검수 대기: {len(eo)}개, 거부: {len(rj)}개)") lines.append("") lines.append(f"### 3-1. Evidence Only (데이터 등장 확인, production 승격 여부 검토)") lines.append("") lines.append("| Canonical | Variants | 등장 위치 | 상태 | 메모 |") lines.append("|-----------|----------|----------|------|------|") for c, d in eo: variants = ", ".join('`' + v + '`' for v in d.get("variants", [])) ev = ", ".join(d.get("evidence", [])[:2]) note = d.get("note", "") lines.append(f"| `{c}` | {variants} | {ev} | evidence_only | {note} |") lines.append("") lines.append(f"### 3-2. Reject (등록 기준 위반, 사전에서 제외)") lines.append("") lines.append("| Canonical | 이유 |") lines.append("|-----------|------|") for c, d in rj: lines.append(f"| `{c}` | {d.get('note', '')} |") lines.append("") # 4. 이전 대비 변경 요약 lines.append("## 4. 초안 대비 변경 요약") lines.append("") lines.append("| 항목 | 초안 | 수정판 |") lines.append("|------|------|--------|") lines.append("| 총 canonical | 22 | 6 (production) + 16 (candidate 대기/거부) |") lines.append("| 총 variants | 55 | 10 (production) + 나머지는 candidate |") lines.append("| 일반 용어 포함 여부 | ❌ 기준 위반 포함됨 | ✓ production 제외, candidate에서 reject |") lines.append("| 데이터 검증 | ❌ 55개 중 31개 미검증 | ✓ production은 전부 데이터 검증 완료 |") lines.append("") # 5. 다음 액션 lines.append("## 5. 다음 액션") lines.append("") lines.append("1. **Phase 18~22 재실행** — production 최소본으로 돌려서 점수 변화 확인") lines.append("2. **candidate evidence_only 9개 검토** — 매칭 실패 케이스 발생 시 승격") lines.append("3. **data mining 스크립트 준비** — 놓친 variants 자동 발굴 (다음 단계)") lines.append("") out = HERE / "SYNONYMS_REPORT.md" out.write_text("\n".join(lines), encoding="utf-8") print(f"완료: {out}") if __name__ == "__main__": main()