wip: phase_z2 evidence 파이프라인 + matching 실험(phase2~26) + 프론트 trace 패널 진행분 스냅샷

- src: phase_z2 composition/mapper/pipeline/placement_planner/retry, ai_fallback(prompts/schema/validate), mdx_text_atoms 신규
- Front: PipelineTracePanel 신규, FramePanel/SlideCanvas/Home/designAgentApi 등 갱신 + 테스트 4종 추가
- templates/phase_z2: catalog(component_expansion_registry, node_slot_mapping 신규), frames, families, slide_base 갱신
- tests/matching: phase2~26 매칭 실험 스크립트·리포트·온톨로지 전체 (미커밋 진행분)
- tests: b4_v4 evidence, task5~28.5 시리즈, regression(imp95 baseline) 등 신규 테스트 대량 추가
- docs/reference: MDX 구조 인벤토리, MDX→Frame 구조 계약 문서
- scripts: mdx 계약/parity/coverage/viewport 체크, gitea comment, run sync 유틸
- .gitignore: tmp*.json, chromedriver, .orchestrator, *.pkl, Front_test* 등 임시/스냅샷 제외

미완성 작업의 보존용 스냅샷 커밋 (2026-07-02)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 17:03:42 +09:00
co-authored by Claude Opus 4.8
parent 97b7833a1b
commit b836e79ee1
527 changed files with 673036 additions and 717 deletions
+143
View File
@@ -0,0 +1,143 @@
"""domain_terms.yaml (Phase 23b 갱신판) → DOMAIN_TERMS_REPORT.md"""
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 / "domain_terms.yaml", encoding="utf-8") as f:
data = yaml.safe_load(f)
lines = []
lines.append("# Phase 23b — Domain Terms 검수 리포트 (정제판)")
lines.append("")
lines.append("> **개선 범위**: 노이즈 필터 강화 · safe_normalization 자동 분류 · 약어 regex 확장 · corpus 설명 정확화.")
lines.append("> **synonyms.yaml은 6개 canonical로 동결** — 본 리포트 결과로 즉시 변경 안 함.")
lines.append("")
meta = data.get("meta", {})
lines.append("## 0. 메타")
lines.append("")
lines.append(f"- **Phase**: {meta.get('phase')}")
lines.append(f"- **Purpose**: {meta.get('purpose')}")
cb = meta.get("corpus_breakdown", {})
lines.append("- **Corpus 구성**:")
for k, v in cb.items():
lines.append(f" - {k}: {v}")
lines.append(f"- **노이즈 필터 후 2회+ 등장 용어**: {meta.get('total_terms_2plus_after_noise_filter')}")
lines.append(f"- **Note**: {meta.get('note')}")
lines.append("")
# 1. 고빈도 용어 Top 50
lines.append("## 1. 반복 등장 상위 용어 (노이즈 제거 후)")
lines.append("")
lines.append("| 순위 | 용어 | 등장 횟수 | 소스 다양성 |")
lines.append("|-----|------|----------|------------|")
for i, item in enumerate(data.get("top_terms_by_frequency", [])[:50], 1):
lines.append(f"| {i} | `{item['term']}` | {item['count']} | {item['sources']}개 |")
lines.append("")
# 2. Safe normalization (자동 분류됨)
sn = data.get("safe_normalization", {})
lines.append("## 2. Safe Normalization — 승격/보류/폐기 자동 분류")
lines.append("")
lines.append(f"### 2-1. Promote 후보 ({len(sn.get('promote', []))}개) — synonyms.yaml 승격 검토 가능")
lines.append("")
if sn.get("promote"):
lines.append("| Canonical | Variants | 사유 | 검수 |")
lines.append("|-----------|----------|------|------|")
for item in sn["promote"]:
vars_str = ", ".join(f"`{v}`" for v in item["variants"])
lines.append(f"| `{item['canonical']}` | {vars_str} | {item['reason']} | ⬜ 승격 / ⬜ 보류 |")
else:
lines.append("_(없음)_")
lines.append("")
lines.append(f"### 2-2. Hold ({len(sn.get('hold', []))}개) — 고유 제품명/브랜드, 치환 위험")
lines.append("")
if sn.get("hold"):
lines.append("| Variants | 사유 |")
lines.append("|----------|------|")
for item in sn["hold"]:
vars_str = ", ".join(f"`{v}`" for v in item["variants"])
lines.append(f"| {vars_str} | {item['reason']} |")
lines.append("")
lines.append(f"### 2-3. Discard ({len(sn.get('discard', []))}개) — 노이즈/메타 조각")
lines.append("")
if sn.get("discard"):
lines.append("| Variants | 사유 |")
lines.append("|----------|------|")
for item in sn["discard"]:
vars_str = ", ".join(f"`{v}`" for v in item["variants"])
lines.append(f"| {vars_str} | {item['reason']} |")
lines.append("")
# 3. 약어 풀네임 (확장 regex)
lines.append("## 3. 약어-풀네임 후보 (확장 regex)")
lines.append("")
lines.append("**주의**: 상위 몇 개는 신뢰 가능. 하위는 regex가 주변 문맥 잘못 잡은 경우 포함 → 수동 검수 필수.")
lines.append("")
abbr = data.get("abbrev_fullname_candidates", [])
if abbr:
lines.append("| 약어 | 풀네임 | 등장 횟수 | 관계 분류 (검수) |")
lines.append("|------|--------|----------|----------------|")
for item in abbr:
lines.append(f"| `{item['abbr']}` | `{item['full']}` | {item['count']} | ⬜ 동의어 / ⬜ 번역 / ⬜ 노이즈 |")
lines.append("")
# 4. 한영 병기 (evidence only)
lines.append("## 4. 한영 병기 패턴 (evidence only — 신뢰도 낮음)")
lines.append("")
lines.append("**주의**: regex가 주변 문맥까지 삼키는 경우 많음. 그대로 synonym 하면 안 됨.")
lines.append("")
ke = data.get("ko_en_paren_pairs_evidence_only", [])
if ke:
lines.append("| 한글 | 영문 | 등장 횟수 | 분류 (검수) |")
lines.append("|------|------|----------|------------|")
for item in ke[:30]:
lines.append(f"| `{item['ko']}` | `{item['en']}` | {item['count']} | ⬜ 동의어 / ⬜ 번역 / ⬜ 설명 / ⬜ 노이즈 |")
lines.append("")
# 5. 명시적 수동 검수
lines.append("## 5. 명시적 수동 검수 필요 (관계 모호)")
lines.append("")
nhr = data.get("needs_human_review", [])
for item in nhr:
lines.append(f"- ⬜ {item}")
lines.append("")
# 6. 검수 후 분기
lines.append("---")
lines.append("")
lines.append("## 6. 검수 후 분기")
lines.append("")
lines.append("| 분류 | 반영 위치 |")
lines.append("|------|----------|")
lines.append("| Promote 승격 | `synonyms.yaml` (production) |")
lines.append("| Hold / Discard | 폐기 또는 보류, synonyms.yaml에 넣지 않음 |")
lines.append("| 약어-풀네임 확정 | `synonyms.yaml` 추가 (매칭 영향 확인 후) |")
lines.append("| 한영 병기 확정 | 동일 |")
lines.append("| 근접어 / 기관vs역할 | `hierarchy.yaml` (Phase 25 연동 예정) |")
lines.append("| 상하위 관계 (Engineering S/W 계열) | `hierarchy.yaml` (taxonomy 구축) |")
lines.append("")
lines.append("**Production 승격 체크리스트:**")
lines.append("")
lines.append("1. ✅ 실데이터 증거 (corpus 등장)")
lines.append("2. ✅ 치환해도 의미 불변 (문맥 독립)")
lines.append("3. ✅ Phase 19 재실행 시 점수 불변 or 개선 (악화 없음)")
lines.append("4. ✅ 사람 검수 통과")
lines.append("")
out = HERE / "DOMAIN_TERMS_REPORT.md"
out.write_text("\n".join(lines), encoding="utf-8")
print(f"완료: {out}")
if __name__ == "__main__":
main()