"""Pipeline Step 12-final — r3 에 최소 수동 오버라이드 적용하고 V3 용 최종 v2 고정. 사용자 승인 사항: - Frame 04 → interrelation (관계도 기반) - Frame 05 → concept_definition (보상현황은 정책 현황이 아님) - Frame 31 → comparative_matrix (산업별 3열 비교) - Frame 13, 19, 22, 28 은 **review_queue** 에 남김 (수동 하드코딩 최소화) 출력: - structure_ontology_v2_final.yaml ← C.4 (V3 매칭 로직 v2) 에서 사용 """ import datetime import sys from pathlib import Path import yaml HERE = Path(__file__).parent sys.path.insert(0, str(HERE)) R3_PATH = HERE / 'structure_ontology_v2_r3.yaml' FINAL_PATH = HERE / 'structure_ontology_v2_final.yaml' # ============================================================ # 수동 오버라이드 (사용자 승인, 3건) # ============================================================ MANUAL_OVERRIDES = { '04': { 'content_affinity_primary': 'interrelation', 'reason': '"관계도" 가 타이틀/내용에 있어 의미상 interrelation 이 더 적합', }, '05': { 'content_affinity_primary': 'concept_definition', 'reason': '"보상현황" 의 "현황" 은 정책 현황 아님 — 민원 관리 방식 정의', }, '31': { 'content_affinity_primary': 'comparative_matrix', 'reason': '산업별 3열 table 구조는 다축 비교 매트릭스', }, } # 재검토 대기 목록 (수동 오버라이드 안 함) REVIEW_QUEUE = [ {'frame': '13', 'reason': '"필수조건" 이 comparative_matrix 로 잡힘 — capability_requirements 여야 할 가능성'}, {'frame': '19', 'reason': '"설계방식 왜곡" 이 capability_requirements 로 잡힘 — stakeholder_roles 또는 problem_diagnosis 여부 검토'}, {'frame': '22', 'reason': '"Model 특화 S/W" 가 process_steps 로 잡힘 — concept_definition 또는 capability_requirements 여부 검토'}, {'frame': '28', 'reason': '"현존 S/W 의 현실" 이 goal_axes 로 잡힘 — singleton_emphasis 또는 problem_diagnosis 여부 검토'}, ] def main(): r3 = yaml.safe_load(R3_PATH.read_text(encoding='utf-8')) templates = r3['templates_v2'] # short_id → fid 매핑 short_to_fid = {v['short_id']: k for k, v in templates.items()} # 오버라이드 적용 override_log = [] for short_id, override in MANUAL_OVERRIDES.items(): fid = short_to_fid.get(short_id) if not fid: continue entry = templates[fid] old_primary = entry['content_affinity']['primary'] new_primary = override['content_affinity_primary'] # primary 교체 (secondary 는 그대로 유지) entry['content_affinity']['primary'] = new_primary # evidence 에 오버라이드 기록 entry['content_affinity']['evidence']['primary'] = { 'source': 'manual_override', 'prior_primary': old_primary, 'reason': override['reason'], 'confidence': 1.0, } entry.setdefault('v2_meta', {})['manually_overridden'] = True override_log.append({ 'frame': short_id, 'frame_id': fid, 'field': 'content_affinity.primary', 'from': old_primary, 'to': new_primary, 'reason': override['reason'], }) # 메타 업데이트 meta = dict(r3['meta']) meta['schema_version'] = 'template-fit-v2-final' meta['generated_at'] = datetime.datetime.now().isoformat(timespec='seconds') meta['generator'] = 'pipeline_12_finalize_v2.py' meta['predecessor_drafts'] = meta.get('predecessor_drafts', []) + ['structure_ontology_v2_r3.yaml (r3)'] meta['manual_overrides'] = override_log meta['review_queue'] = REVIEW_QUEUE meta['status'] = 'locked_for_v3_matching' meta['r4_note'] = ( '3건 수동 오버라이드 (Frame 04/05/31) 적용. ' '재검토 대기 4건 (13/19/22/28) 은 review_queue 로 남김 — ' '하드코딩 최소화, 추후 샘플 확장 시 재평가.' ) out = {'meta': meta, 'templates_v2': templates} FINAL_PATH.write_text( yaml.safe_dump(out, allow_unicode=True, sort_keys=False, width=1000), encoding='utf-8', ) print('=' * 70) print('v2 final 고정 완료 (C.4 입력)') print('=' * 70) print(f' {FINAL_PATH}') print() print('수동 오버라이드:') for log in override_log: print(f" Frame {log['frame']}: {log['from']} → {log['to']}") print() print(f"review_queue ({len(REVIEW_QUEUE)} 건):") for r in REVIEW_QUEUE: print(f" Frame {r['frame']}: {r['reason']}") if __name__ == '__main__': main()