From 9b79bf75383def10add59030592252f7fc223998 Mon Sep 17 00:00:00 2001 From: kyeongmin Date: Tue, 7 Jul 2026 13:51:00 +0900 Subject: [PATCH] =?UTF-8?q?feat(#17):=20generic=20fallback=20=ED=83=88?= =?UTF-8?q?=EC=B6=9C=20=E2=80=94=20V4=20evidence=20=ED=99=95=EC=9E=A5=20+?= =?UTF-8?q?=20renderable-aware=20provisional=20+=20=EA=B2=8C=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=9C=EC=84=9C=20=EB=B2=84=EA=B7=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. V4 evidence 확장 (pipeline_17b_extend_missing_sections.py): '결과물이 아니라 프로세스' 원칙 — pipeline_17 과 동일 평가 코드로 누락 3개 섹션(01-intro/05-1/05-2)만 평가해 v4_full32_result.yaml 병합 (기존 무접촉, blind/ANSWER_MAP 불변). 결과: 05-1 → F20 light_edit 0.77 (design-matched!), 01-intro/05-2 → all-reject (catalog gap 정직 노출 — F19 가 05 주제와 이름까지 일치하나 partial 없음 → #2 프로모션 최우선 근거) 2. renderable-aware provisional (IMP-30 u1 정밀화): rank-1 무조건 승격 → partial 존재 AND (비-reject OR verbatim builder 보유) 첫 후보 승격. reject+builder 미보유 renderable 의 mapper 네이티브 렌더는 원문 drop 위험 (F23 1-atom 손실 실측) — 원문 보존 > design 개선 우선순위. 3. 게이트 순서 버그 수정 (_apply_quality_gate_downgrades 추출): T28.5d popup 승격 후 재계산 경로에 quality gate 강등 3종(coverage/forbidden/ consistency) 미적용 → 텍스트 손실이 overall=PASS 로 통과 (mdx05 실측). 양 경로 공통 헬퍼로 통일 — mdx04 의 #16 시점 PASS 일부가 이 버그 덕이었음을 정직하게 정정 (현재 PARTIAL + frame mismatch 라벨, 텍스트는 완전). 최종 5-MDX: 전부 missing_atoms=0 (무손실) / 01·03 PASS / 02·04·05 PARTIAL(정직 frame-mismatch 라벨) / mdx01 readiness not_ready→needs_review 개선. 게이트: 1061 passed. SHA baseline 재캡처 (정당 변경). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/phase_z2_pipeline.py | 173 +- .../pipeline_17b_extend_missing_sections.py | 151 ++ tests/matching/v4_full32_result.yaml | 1472 +++++++++++++++++ .../fixtures/89a_pre_baseline_sha.json | 6 +- .../fixtures/imp95_pre_baseline_sha.json | 6 +- ...phase_z2_issue17_provisional_renderable.py | 118 ++ 6 files changed, 1868 insertions(+), 58 deletions(-) create mode 100644 tests/matching/pipeline_17b_extend_missing_sections.py create mode 100644 tests/test_phase_z2_issue17_provisional_renderable.py diff --git a/src/phase_z2_pipeline.py b/src/phase_z2_pipeline.py index 12a13a2..af1fb81 100644 --- a/src/phase_z2_pipeline.py +++ b/src/phase_z2_pipeline.py @@ -664,6 +664,21 @@ def _build_verbatim_compare_table_2col(unit) -> dict: } +# issue #17 — verbatim builder 를 보유한 template 집합 (아래 dispatch 와 동기). +# renderable-aware provisional 이 reject 라벨 후보를 승격해도 안전한지(원문 +# 무손실 코드 렌더 가능한지) 판단하는 데 사용. +_VERBATIM_BUILDER_TEMPLATE_IDS: frozenset[str] = frozenset({ + "three_parallel_requirements", + "three_persona_benefits", + "construction_goals_three_circle_intersection", + "construction_bim_three_usage", + "bim_dx_comparison_table", + "bim_issues_quadrant_four", + "sw_dependency_four_problems", + "pre_construction_model_info_stacked", +}) + + def _emergency_p4b_build_verbatim_slot_payload( unit, template_id: str, override_slot_count: Optional[int] = None, ) -> Optional[dict]: @@ -2797,16 +2812,41 @@ def lookup_v4_match_with_fallback( # trace entries are left intact (their skip reasons remain accurate). # Default-off keeps IMP-05 behavior byte-identical. if allow_provisional: - rank_1_judgment = judgments[0] + # issue #17 — renderable-aware provisional. rank 순서는 유지하되 + # 승격 가능 조건: partial HTML 존재 (IMP-95 u6 partial_exists 원칙) + # AND (비-reject 라벨 OR verbatim builder 지원). 근거 실측: + # - partial 없는 frame 승격 → mapper FitError → verbatim 복구 → + # selected_frame_not_applied 라벨 (mdx05 05-2 rank-1 F6) + # - reject 라벨 + verbatim builder 없는 frame 의 mapper 네이티브 + # 렌더는 원문 drop 위험 (mdx05 05-2 F23: 1 atom 손실 실측 — + # 원문 보존이 design 개선보다 우선) + # 조건 만족 후보가 없으면 기존대로 rank-1 (동작 보존 — verbatim + # 복구가 텍스트 무손실을 보장). + provisional_judgment = judgments[0] + provisional_rank = 1 + for _rank, _judgment in enumerate(judgments, start=1): + _tid = str(_judgment.get("template_id") or "") + if not _b4_partial_exists(_tid): + continue + _label = str(_judgment.get("label") or "") + if _label == "reject" and _tid not in _VERBATIM_BUILDER_TEMPLATE_IDS: + continue + provisional_judgment, provisional_rank = _judgment, _rank + break provisional_match = _v4_match_from_judgment( - section_id, rank_1_judgment, rank=1 + section_id, provisional_judgment, rank=provisional_rank ) - provisional_match.selection_path = "provisional_rank_1" + _prov_path = ( + "provisional_rank_1" + if provisional_rank == 1 + else f"provisional_renderable_rank_{provisional_rank}" + ) + provisional_match.selection_path = _prov_path provisional_match.fallback_reason = trace["fallback_reason"] provisional_match.provisional = True trace.update({ - "selection_path": "provisional_rank_1", - "selected_rank": 1, + "selection_path": _prov_path, + "selected_rank": provisional_rank, "selected_template_id": provisional_match.template_id, "selected_frame_id": provisional_match.frame_id, "selected_label": provisional_match.label, @@ -5870,6 +5910,63 @@ def _compute_density_gate(zones_data: list[dict], overflow: dict) -> dict: } +def _apply_quality_gate_downgrades( + slide_status: dict, + *, + rendered_text_coverage: dict, + forbidden_rendered_syntax: dict, + applied_render_consistency: dict, +) -> None: + """issue #17 — quality gate 3종의 overall 강등을 단일 헬퍼로. + + 두 slide_status 조립 경로(최초 + T28.5d popup 승격 후 재계산)가 동일한 + 강등 규칙을 공유해야 한다 — 재계산 경로에 이 블록이 없어서 텍스트 + 손실(rendered_text_coverage fail)이 overall=PASS 로 통과하는 버그가 + 있었음 (mdx05 05-2 F23 렌더 1-atom 손실 실측). + """ + if not rendered_text_coverage.get("passed"): + slide_status.setdefault("quality_gate_failures", []).append( + "rendered_text_coverage_missing" + ) + slide_status.setdefault("visual_fail_reasons", []).append( + "rendered_text_coverage_missing: " + f"{rendered_text_coverage.get('missing_atoms_count')} source text atom(s) " + "not visible in final.html" + ) + if slide_status.get("overall") == "PASS": + slide_status["overall"] = "PARTIAL_COVERAGE" + + if not forbidden_rendered_syntax.get("passed"): + slide_status.setdefault("quality_gate_failures", []).append( + "forbidden_rendered_syntax" + ) + slide_status.setdefault("visual_fail_reasons", []).append( + "forbidden_rendered_syntax: " + f"{forbidden_rendered_syntax.get('forbidden_syntax_count')} JSX/CSS/code " + "fragment(s) visible in final.html" + ) + if slide_status.get("overall") == "PASS": + slide_status["overall"] = "PARTIAL_COVERAGE" + + if not applied_render_consistency.get("passed"): + for failure in applied_render_consistency.get("failures") or []: + slide_status.setdefault("quality_gate_failures", []).append(failure) + if applied_render_consistency.get("frame_mismatch_count"): + slide_status.setdefault("visual_fail_reasons", []).append( + "selected_frame_not_applied: " + f"{applied_render_consistency.get('frame_mismatch_count')} zone(s) " + "rendered with a different template than Step 6 selected" + ) + if "final_layout_positions_mismatch" in (applied_render_consistency.get("failures") or []): + slide_status.setdefault("visual_fail_reasons", []).append( + "final_layout_positions_mismatch: " + f"expected {applied_render_consistency.get('expected_positions')} but " + f"final.html has {applied_render_consistency.get('final_positions')}" + ) + if slide_status.get("overall") == "PASS": + slide_status["overall"] = "PARTIAL_COVERAGE" + + def _compute_design_readiness( *, units: list[CompositionUnit], @@ -11310,53 +11407,17 @@ def run_phase_z2_mvp1( density_gate=density_gate, ) slide_status["design_readiness"] = design_readiness - if not rendered_text_coverage.get("passed"): - slide_status.setdefault("quality_gate_failures", []).append( - "rendered_text_coverage_missing" - ) - slide_status.setdefault("visual_fail_reasons", []).append( - "rendered_text_coverage_missing: " - f"{rendered_text_coverage.get('missing_atoms_count')} source text atom(s) " - "not visible in final.html" - ) - if slide_status.get("overall") == "PASS": - slide_status["overall"] = "PARTIAL_COVERAGE" - - # IMP-47B u8 — Surface Step 12 AI repair outcomes through slide_status. - # Composes u4 gather errors + u5 apply_status + u7 coverage_invariant - # into a single ``ai_repair_status`` axis the frontend (u11) reads to - # render human_review notifications. Auto pipeline first - # ([[feedback_auto_pipeline_first]]) — no review_queue insertion; - # explicit status enum + human_review_required flag. - if not forbidden_rendered_syntax.get("passed"): - slide_status.setdefault("quality_gate_failures", []).append( - "forbidden_rendered_syntax" - ) - slide_status.setdefault("visual_fail_reasons", []).append( - "forbidden_rendered_syntax: " - f"{forbidden_rendered_syntax.get('forbidden_syntax_count')} JSX/CSS/code " - "fragment(s) visible in final.html" - ) - if slide_status.get("overall") == "PASS": - slide_status["overall"] = "PARTIAL_COVERAGE" - - if not applied_render_consistency.get("passed"): - for failure in applied_render_consistency.get("failures") or []: - slide_status.setdefault("quality_gate_failures", []).append(failure) - if applied_render_consistency.get("frame_mismatch_count"): - slide_status.setdefault("visual_fail_reasons", []).append( - "selected_frame_not_applied: " - f"{applied_render_consistency.get('frame_mismatch_count')} zone(s) " - "rendered with a different template than Step 6 selected" - ) - if "final_layout_positions_mismatch" in (applied_render_consistency.get("failures") or []): - slide_status.setdefault("visual_fail_reasons", []).append( - "final_layout_positions_mismatch: " - f"expected {applied_render_consistency.get('expected_positions')} but " - f"final.html has {applied_render_consistency.get('final_positions')}" - ) - if slide_status.get("overall") == "PASS": - slide_status["overall"] = "PARTIAL_COVERAGE" + # IMP-47B u8 주석 이력 보존 — Surface Step 12 AI repair outcomes through + # slide_status (아래 ai_repair_status 블록). quality gate downgrade 3종은 + # issue #17 에서 _apply_quality_gate_downgrades 로 추출 (popup 승격 후 + # 재계산 경로에도 동일 적용 — 미적용 시 text 손실이 PASS 로 통과하는 + # 게이트 순서 버그가 있었음: mdx05 실측). + _apply_quality_gate_downgrades( + slide_status, + rendered_text_coverage=rendered_text_coverage, + forbidden_rendered_syntax=forbidden_rendered_syntax, + applied_render_consistency=applied_render_consistency, + ) presentation_fit = _build_presentation_fit_report( overflow=overflow, @@ -11448,6 +11509,14 @@ def run_phase_z2_mvp1( slide_status["density_gate"] = density_gate slide_status["design_readiness"] = design_readiness slide_status["presentation_fit"] = presentation_fit + # issue #17 — 재계산 경로에도 quality gate 강등 적용 (미적용 시 + # text 손실이 overall=PASS 로 통과하던 게이트 순서 버그). + _apply_quality_gate_downgrades( + slide_status, + rendered_text_coverage=rendered_text_coverage, + forbidden_rendered_syntax=forbidden_rendered_syntax, + applied_render_consistency=applied_render_consistency, + ) slide_status["technical_pass"] = bool( slide_status.get("rendered") and slide_status.get("full_mdx_coverage") diff --git a/tests/matching/pipeline_17b_extend_missing_sections.py b/tests/matching/pipeline_17b_extend_missing_sections.py new file mode 100644 index 0000000..8429870 --- /dev/null +++ b/tests/matching/pipeline_17b_extend_missing_sections.py @@ -0,0 +1,151 @@ +"""Pipeline Step 17b — V4 full-32 평가를 누락 섹션에 확장 (GitHub issue #17). + +배경: v4_full32_result.yaml (2026-04-29) 은 mdx 01~04 의 10개 섹션만 평가 — +`01-intro` / `05-1` / `05-2` 는 V4 source 자체가 없어 런타임에서 무조건 +generic fallback (design_readiness=not_ready) 이 됨 (emergency.md C3). + +원칙: "결과물을 고치지 말고 프로세스를 고친다" — yaml 손편집이 아니라 +pipeline_17 과 동일한 평가 코드(detect_mdx_analysis + compute_template_fit ++ route)로 누락 섹션만 평가해 병합한다. 기존 섹션 엔트리는 무접촉. + +실행: python tests/matching/pipeline_17b_extend_missing_sections.py +출력: v4_full32_result.yaml (기존 10 + 신규 3 = 13 sections) +""" +import datetime +import sys +from pathlib import Path + +import yaml + +HERE = Path(__file__).parent +sys.path.insert(0, str(HERE)) + +from phase_common import load_32_frames, load_frame_index +from detect_mdx import detect_mdx_analysis +from template_fit import ( + load_templates_v1, collect_anchor_vocab, compute_template_fit, route, +) +from embeddings import embed_texts, cosine +from pipeline_01_extract_nodes import MDX_DIR + +OUT_PATH = HERE / 'v4_full32_result.yaml' + +# 신규 평가 대상 — 런타임 section_id 와 동일한 키 (lookup_v4 exact match). +# 01-intro 는 heading 없는 pre-intro 블록이라 시작 라인을 본문 첫 그룹으로 지정. +NEW_SECTIONS = { + '01-intro': {'file': '01.mdx', 'start': '* **용어의 혼용**', 'end_prefix': '## 1.', + 'title': '건설산업 DX의 올바른 이해 — 도입(용어의 혼용)'}, + '05-1': {'file': '05.mdx', 'start': '## 1. 설계의 자동화', 'end_prefix': '## 2.', + 'title': None}, + '05-2': {'file': '05.mdx', 'start': '## 2. S/W 중심 설계 방식', 'end_prefix': None, + 'title': None}, +} + + +def extract_raw(cfg): + lines = (MDX_DIR / cfg['file']).read_text(encoding='utf-8').split('\n') + start = None + for i, ln in enumerate(lines): + if ln.strip() == cfg['start'].strip(): + start = i + break + if start is None: + raise RuntimeError(f"start line not found: {cfg['start']!r} in {cfg['file']}") + end = len(lines) + if cfg.get('end_prefix'): + for i in range(start + 1, len(lines)): + if lines[i].strip().startswith(cfg['end_prefix']): + end = i + break + section = lines[start:end] + title = cfg.get('title') or section[0].lstrip('#').strip() + return title, '\n'.join(section) + + +def main(): + existing = yaml.safe_load(OUT_PATH.read_text(encoding='utf-8')) + already = set(existing['mdx_sections'].keys()) + todo = {sid: cfg for sid, cfg in NEW_SECTIONS.items() if sid not in already} + if not todo: + print('신규 평가 대상 없음 — 모두 존재.') + return + + templates = load_templates_v1() + anchor_vocab = collect_anchor_vocab(templates) + frames = load_32_frames() + idx_data, frame_to_short = load_frame_index() + fids = list(frames.keys()) + frame_num_map = {fid: int(frame_to_short[fid]) for fid in fids} + frame_contents = [frames[fid].get('content', '') for fid in fids] + + print(f'[17b] 32 frame content 임베딩 중... (신규 섹션: {sorted(todo)})') + frame_vecs = embed_texts(frame_contents) + + for sid, cfg in sorted(todo.items()): + title, raw_text = extract_raw(cfg) + mdx_analysis = detect_mdx_analysis(raw_text, title, anchor_vocab=anchor_vocab) + mdx_vec = embed_texts([mdx_analysis['summary']])[0] + + judgments = [] + for i, fid in enumerate(fids): + if fid not in templates: + continue + template = templates[fid] + content_emb = max(0.0, min(1.0, float(cosine(mdx_vec, frame_vecs[i])))) + fit = compute_template_fit(mdx_analysis, template, content_emb) + label = route(fit['confidence'], fit['axes'], fit['adaptation'], fit['not_suits']) + judgments.append({ + 'frame_id': fid, + 'frame_number': frame_num_map[fid], + 'template_id': template.get('template_id'), + 'confidence': round(float(fit['confidence']), 4), + 'base': round(float(fit['base']), 4), + 'penalty': round(float(fit['total_penalty']), 4), + 'label': label, + 'content_embedding': round(content_emb, 4), + 'axes': { + 'anchor': round(float(fit['axes']['anchor']['score']), 4), + 'cardinality': round(float(fit['axes']['cardinality']), 4), + 'relation': round(float(fit['axes']['relation']), 4), + 'slot': round(float(fit['axes']['slot']), 4), + 'content': round(float(fit['axes']['content']), 4), + }, + }) + judgments.sort(key=lambda x: -x['confidence']) + for new_rank, item in enumerate(judgments, start=1): + item['v4_full_rank'] = new_rank + + existing['mdx_sections'][sid] = { + 'mdx_title': title, + 'answer_frame_number': None, # blind — ANSWER_MAP 변경 금지 (Holdout 원칙 1) + 'is_holdout': True, + 'judgments_full32': judgments, + 'usable_count': sum(1 for j in judgments if j['label'] != 'reject'), + 'reject_count': sum(1 for j in judgments if j['label'] == 'reject'), + } + top = judgments[0] + print(f" {sid}: rank1 = F{top['frame_number']} {top['template_id']} " + f"({top['label']}, {top['confidence']}) usable={existing['mdx_sections'][sid]['usable_count']}") + + meta = existing.setdefault('meta', {}) + ext = meta.setdefault('extensions', []) + ext.append({ + 'step': '17b_extend_missing_sections', + 'added_sections': sorted(todo), + 'reason': 'GitHub issue #17 — generic fallback 탈출 (C3: V4 source 누락 해소)', + 'generated_at': datetime.datetime.now().isoformat(timespec='seconds'), + }) + holdout = meta.setdefault('holdout_sections', []) + for sid in sorted(todo): + if sid not in holdout: + holdout.append(sid) + + OUT_PATH.write_text( + yaml.safe_dump(existing, allow_unicode=True, sort_keys=False, width=1000), + encoding='utf-8', + ) + print(f'병합 완료: {OUT_PATH} (총 {len(existing["mdx_sections"])} sections)') + + +if __name__ == '__main__': + main() diff --git a/tests/matching/v4_full32_result.yaml b/tests/matching/v4_full32_result.yaml index 292d5c9..daabdfd 100644 --- a/tests/matching/v4_full32_result.yaml +++ b/tests/matching/v4_full32_result.yaml @@ -15,6 +15,17 @@ meta: - 04-1 - 04-2.1 - 04-2.2 + - 01-intro + - 05-1 + - 05-2 + extensions: + - step: 17b_extend_missing_sections + added_sections: + - 01-intro + - 05-1 + - 05-2 + reason: 'GitHub issue #17 — generic fallback 탈출 (C3: V4 source 누락 해소)' + generated_at: '2026-07-07T10:15:33' mdx_sections: 01-2: mdx_title: 2. 용어간 상호관계 @@ -4886,3 +4897,1464 @@ mdx_sections: v4_full_rank: 32 usable_count: 3 reject_count: 29 + 01-intro: + mdx_title: 건설산업 DX의 올바른 이해 — 도입(용어의 혼용) + answer_frame_number: null + is_holdout: true + judgments_full32: + - frame_id: '1171281177' + frame_number: 6 + template_id: compensation_complaint_map + confidence: 0.651 + base: 0.651 + penalty: 0.0 + label: reject + content_embedding: 0.5052 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.5052 + v4_full_rank: 1 + - frame_id: '1171281182' + frame_number: 11 + template_id: construction_bim_three_usage + confidence: 0.4696 + base: 0.4696 + penalty: 0.0 + label: reject + content_embedding: 0.5232 + axes: + anchor: 1.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5232 + v4_full_rank: 2 + - frame_id: '1171281204' + frame_number: 24 + template_id: engn_sw_three_types + confidence: 0.4047 + base: 0.4047 + penalty: 0.0 + label: reject + content_embedding: 0.5318 + axes: + anchor: 0.3333 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.5318 + v4_full_rank: 3 + - frame_id: '1171281208' + frame_number: 27 + template_id: bim_adoption_central_split + confidence: 0.3994 + base: 0.3994 + penalty: 0.0 + label: reject + content_embedding: 0.5884 + axes: + anchor: 0.6667 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5884 + v4_full_rank: 4 + - frame_id: '1171281195' + frame_number: 18 + template_id: bim_dx_comparison_table + confidence: 0.374 + base: 0.574 + penalty: 0.2 + label: reject + content_embedding: 0.5451 + axes: + anchor: 1.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.5451 + v4_full_rank: 5 + - frame_id: '1171281189' + frame_number: 12 + template_id: construction_goals_three_circle_intersection + confidence: 0.3418 + base: 0.3418 + penalty: 0.0 + label: reject + content_embedding: 0.5091 + axes: + anchor: 0.5 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5091 + v4_full_rank: 6 + - frame_id: '1171281190' + frame_number: 13 + template_id: three_parallel_requirements + confidence: 0.3155 + base: 0.4155 + penalty: 0.1 + label: reject + content_embedding: 0.586 + axes: + anchor: 0.3333 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.586 + v4_full_rank: 7 + - frame_id: '1171281178' + frame_number: 7 + template_id: bigroom_system_components + confidence: 0.3143 + base: 0.3143 + penalty: 0.0 + label: reject + content_embedding: 0.4965 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.4965 + v4_full_rank: 8 + - frame_id: '1171281203' + frame_number: 23 + template_id: app_sw_package_vs_solution + confidence: 0.31 + base: 0.31 + penalty: 0.0 + label: reject + content_embedding: 0.4752 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.4752 + v4_full_rank: 9 + - frame_id: '1171281205' + frame_number: 25 + template_id: commercial_sw_four_categories + confidence: 0.2493 + base: 0.2493 + penalty: 0.0 + label: reject + content_embedding: 0.4928 + axes: + anchor: 0.1429 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.4928 + v4_full_rank: 10 + - frame_id: '1171281194' + frame_number: 17 + template_id: bim_current_problems_paired + confidence: 0.2322 + base: 0.2322 + penalty: 0.0 + label: reject + content_embedding: 0.586 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.586 + v4_full_rank: 11 + - frame_id: '1171281192' + frame_number: 15 + template_id: policy_goals_plus_execution_requirements + confidence: 0.2288 + base: 0.2288 + penalty: 0.0 + label: reject + content_embedding: 0.5691 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5691 + v4_full_rank: 12 + - frame_id: '1171281197' + frame_number: 19 + template_id: design_method_distortion_three_col + confidence: 0.2288 + base: 0.2288 + penalty: 0.0 + label: reject + content_embedding: 0.5692 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5692 + v4_full_rank: 13 + - frame_id: '1171281201' + frame_number: 21 + template_id: solution_engn_split_diagram + confidence: 0.2283 + base: 0.2283 + penalty: 0.0 + label: reject + content_embedding: 0.5664 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5664 + v4_full_rank: 14 + - frame_id: '1171281173' + frame_number: 2 + template_id: engn_sw_development_domain_knowledge + confidence: 0.2278 + base: 0.2278 + penalty: 0.0 + label: reject + content_embedding: 0.5641 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5641 + v4_full_rank: 15 + - frame_id: '1171281209' + frame_number: 28 + template_id: sw_reality_three_emphasis + confidence: 0.2228 + base: 0.3228 + penalty: 0.1 + label: reject + content_embedding: 0.5389 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.5389 + v4_full_rank: 16 + - frame_id: '1171281193' + frame_number: 16 + template_id: bim_issues_quadrant_four + confidence: 0.2201 + base: 0.2201 + penalty: 0.0 + label: reject + content_embedding: 0.5256 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5256 + v4_full_rank: 17 + - frame_id: '1171281180' + frame_number: 9 + template_id: pre_construction_model_info_stacked + confidence: 0.2195 + base: 0.3195 + penalty: 0.1 + label: reject + content_embedding: 0.5223 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.5223 + v4_full_rank: 18 + - frame_id: '1171281181' + frame_number: 10 + template_id: field_effectiveness_five_elements + confidence: 0.2184 + base: 0.2184 + penalty: 0.0 + label: reject + content_embedding: 0.5169 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5169 + v4_full_rank: 19 + - frame_id: '1171281174' + frame_number: 3 + template_id: overseas_bim_numbered_list + confidence: 0.2175 + base: 0.2175 + penalty: 0.0 + label: reject + content_embedding: 0.5123 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5123 + v4_full_rank: 20 + - frame_id: '1171281213' + frame_number: 32 + template_id: policy_achievement_five_goals + confidence: 0.2155 + base: 0.2155 + penalty: 0.0 + label: reject + content_embedding: 0.5024 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5024 + v4_full_rank: 21 + - frame_id: '1171281202' + frame_number: 22 + template_id: model_specialized_engn_sw + confidence: 0.2128 + base: 0.2128 + penalty: 0.0 + label: reject + content_embedding: 0.4889 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.4889 + v4_full_rank: 22 + - frame_id: '1171281206' + frame_number: 26 + template_id: sw_dependency_four_problems + confidence: 0.2071 + base: 0.3071 + penalty: 0.1 + label: reject + content_embedding: 0.4603 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.4603 + v4_full_rank: 23 + - frame_id: '1171281172' + frame_number: 1 + template_id: sw_development_cycle_six_nodes + confidence: 0.2057 + base: 0.2057 + penalty: 0.0 + label: reject + content_embedding: 0.4533 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.4533 + v4_full_rank: 24 + - frame_id: '1171281198' + frame_number: 20 + template_id: dx_sw_necessity_three_perspectives + confidence: 0.1923 + base: 0.3923 + penalty: 0.2 + label: reject + content_embedding: 0.5533 + axes: + anchor: 0.6667 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5533 + v4_full_rank: 25 + - frame_id: '1171281212' + frame_number: 31 + template_id: industry_characteristics_three_col + confidence: 0.1184 + base: 0.3184 + penalty: 0.2 + label: reject + content_embedding: 0.517 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.517 + v4_full_rank: 26 + - frame_id: '1171281210' + frame_number: 29 + template_id: process_product_two_way + confidence: 0.1158 + base: 0.3158 + penalty: 0.2 + label: reject + content_embedding: 0.5042 + axes: + anchor: 0.4 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5042 + v4_full_rank: 27 + - frame_id: '1171281211' + frame_number: 30 + template_id: industry_current_status_three_col + confidence: 0.1142 + base: 0.3142 + penalty: 0.2 + label: reject + content_embedding: 0.4962 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.4962 + v4_full_rank: 28 + - frame_id: '1171281191' + frame_number: 14 + template_id: three_persona_benefits + confidence: 0.0777 + base: 0.2777 + penalty: 0.2 + label: reject + content_embedding: 0.501 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.501 + v4_full_rank: 29 + - frame_id: '1171281175' + frame_number: 4 + template_id: domestic_bim_actor_relations + confidence: 0.016 + base: 0.216 + penalty: 0.2 + label: reject + content_embedding: 0.5051 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.5051 + v4_full_rank: 30 + - frame_id: '1171281176' + frame_number: 5 + template_id: compensation_complaint_side_card + confidence: 0.0102 + base: 0.3102 + penalty: 0.3 + label: reject + content_embedding: 0.4762 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.5 + content: 0.4762 + v4_full_rank: 31 + - frame_id: '1171281179' + frame_number: 8 + template_id: info_management_what_how_when + confidence: 0.0096 + base: 0.2096 + penalty: 0.2 + label: reject + content_embedding: 0.4729 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.4729 + v4_full_rank: 32 + usable_count: 0 + reject_count: 32 + 05-1: + mdx_title: 1. 설계의 자동화 + answer_frame_number: null + is_holdout: true + judgments_full32: + - frame_id: '1171281198' + frame_number: 20 + template_id: dx_sw_necessity_three_perspectives + confidence: 0.77 + base: 0.77 + penalty: 0.0 + label: light_edit + content_embedding: 0.4748 + axes: + anchor: 0.5 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.4748 + v4_full_rank: 1 + - frame_id: '1171281202' + frame_number: 22 + template_id: model_specialized_engn_sw + confidence: 0.7333 + base: 0.7333 + penalty: 0.0 + label: restructure + content_embedding: 0.604 + axes: + anchor: 0.25 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.604 + v4_full_rank: 2 + - frame_id: '1171281209' + frame_number: 28 + template_id: sw_reality_three_emphasis + confidence: 0.7265 + base: 0.7265 + penalty: 0.0 + label: reject + content_embedding: 0.57 + axes: + anchor: 0.25 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.57 + v4_full_rank: 3 + - frame_id: '1171281190' + frame_number: 13 + template_id: three_parallel_requirements + confidence: 0.7198 + base: 0.7198 + penalty: 0.0 + label: reject + content_embedding: 0.5367 + axes: + anchor: 0.25 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.5367 + v4_full_rank: 4 + - frame_id: '1171281201' + frame_number: 21 + template_id: solution_engn_split_diagram + confidence: 0.7011 + base: 0.7011 + penalty: 0.0 + label: restructure + content_embedding: 0.6431 + axes: + anchor: 0.25 + cardinality: 0.8 + relation: 1.0 + slot: 1.0 + content: 0.6431 + v4_full_rank: 5 + - frame_id: '1171281212' + frame_number: 31 + template_id: industry_characteristics_three_col + confidence: 0.6693 + base: 0.6693 + penalty: 0.0 + label: reject + content_embedding: 0.5714 + axes: + anchor: 0.5 + cardinality: 1.0 + relation: 0.4 + slot: 1.0 + content: 0.5714 + v4_full_rank: 6 + - frame_id: '1171281197' + frame_number: 19 + template_id: design_method_distortion_three_col + confidence: 0.6692 + base: 0.6692 + penalty: 0.0 + label: restructure + content_embedding: 0.6962 + axes: + anchor: 0.4 + cardinality: 1.0 + relation: 0.4 + slot: 1.0 + content: 0.6962 + v4_full_rank: 7 + - frame_id: '1171281182' + frame_number: 11 + template_id: construction_bim_three_usage + confidence: 0.6662 + base: 0.6662 + penalty: 0.0 + label: restructure + content_embedding: 0.5812 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.5812 + v4_full_rank: 8 + - frame_id: '1171281189' + frame_number: 12 + template_id: construction_goals_three_circle_intersection + confidence: 0.6622 + base: 0.6622 + penalty: 0.0 + label: restructure + content_embedding: 0.5609 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.5609 + v4_full_rank: 9 + - frame_id: '1171281176' + frame_number: 5 + template_id: compensation_complaint_side_card + confidence: 0.6537 + base: 0.6537 + penalty: 0.0 + label: reject + content_embedding: 0.5185 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.5185 + v4_full_rank: 10 + - frame_id: '1171281179' + frame_number: 8 + template_id: info_management_what_how_when + confidence: 0.6532 + base: 0.6532 + penalty: 0.0 + label: reject + content_embedding: 0.516 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.516 + v4_full_rank: 11 + - frame_id: '1171281191' + frame_number: 14 + template_id: three_persona_benefits + confidence: 0.6354 + base: 0.6354 + penalty: 0.0 + label: reject + content_embedding: 0.427 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 1.0 + content: 0.427 + v4_full_rank: 12 + - frame_id: '1171281204' + frame_number: 24 + template_id: engn_sw_three_types + confidence: 0.6314 + base: 0.6314 + penalty: 0.0 + label: reject + content_embedding: 0.5905 + axes: + anchor: 0.3333 + cardinality: 1.0 + relation: 0.4 + slot: 1.0 + content: 0.5905 + v4_full_rank: 13 + - frame_id: '1171281205' + frame_number: 25 + template_id: commercial_sw_four_categories + confidence: 0.5326 + base: 0.5326 + penalty: 0.0 + label: reject + content_embedding: 0.5735 + axes: + anchor: 0.5714 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.5735 + v4_full_rank: 14 + - frame_id: '1171281211' + frame_number: 30 + template_id: industry_current_status_three_col + confidence: 0.5324 + base: 0.5324 + penalty: 0.0 + label: reject + content_embedding: 0.5121 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 0.4 + slot: 1.0 + content: 0.5121 + v4_full_rank: 15 + - frame_id: '1171281194' + frame_number: 17 + template_id: bim_current_problems_paired + confidence: 0.471 + base: 0.471 + penalty: 0.0 + label: reject + content_embedding: 0.6677 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.6677 + v4_full_rank: 16 + - frame_id: '1171281206' + frame_number: 26 + template_id: sw_dependency_four_problems + confidence: 0.4545 + base: 0.5545 + penalty: 0.1 + label: reject + content_embedding: 0.4807 + axes: + anchor: 0.3333 + cardinality: 0.5 + relation: 1.0 + slot: 0.5 + content: 0.4807 + v4_full_rank: 17 + - frame_id: '1171281173' + frame_number: 2 + template_id: engn_sw_development_domain_knowledge + confidence: 0.3986 + base: 0.3986 + penalty: 0.0 + label: reject + content_embedding: 0.6178 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.6178 + v4_full_rank: 18 + - frame_id: '1171281174' + frame_number: 3 + template_id: overseas_bim_numbered_list + confidence: 0.3932 + base: 0.3932 + penalty: 0.0 + label: reject + content_embedding: 0.5908 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.5908 + v4_full_rank: 19 + - frame_id: '1171281172' + frame_number: 1 + template_id: sw_development_cycle_six_nodes + confidence: 0.3914 + base: 0.3914 + penalty: 0.0 + label: reject + content_embedding: 0.5818 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.5818 + v4_full_rank: 20 + - frame_id: '1171281181' + frame_number: 10 + template_id: field_effectiveness_five_elements + confidence: 0.3914 + base: 0.3914 + penalty: 0.0 + label: reject + content_embedding: 0.5822 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.5822 + v4_full_rank: 21 + - frame_id: '1171281180' + frame_number: 9 + template_id: pre_construction_model_info_stacked + confidence: 0.3856 + base: 0.4856 + penalty: 0.1 + label: reject + content_embedding: 0.553 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 1.0 + slot: 0.5 + content: 0.553 + v4_full_rank: 22 + - frame_id: '1171281193' + frame_number: 16 + template_id: bim_issues_quadrant_four + confidence: 0.3831 + base: 0.3831 + penalty: 0.0 + label: reject + content_embedding: 0.5404 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.5404 + v4_full_rank: 23 + - frame_id: '1171281213' + frame_number: 32 + template_id: policy_achievement_five_goals + confidence: 0.3785 + base: 0.3785 + penalty: 0.0 + label: reject + content_embedding: 0.5173 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.5173 + v4_full_rank: 24 + - frame_id: '1171281192' + frame_number: 15 + template_id: policy_goals_plus_execution_requirements + confidence: 0.3721 + base: 0.3721 + penalty: 0.0 + label: reject + content_embedding: 0.4855 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 1.0 + slot: 0.5 + content: 0.4855 + v4_full_rank: 25 + - frame_id: '1171281178' + frame_number: 7 + template_id: bigroom_system_components + confidence: 0.2891 + base: 0.4391 + penalty: 0.15 + label: reject + content_embedding: 0.6078 + axes: + anchor: 0.25 + cardinality: 0.5 + relation: 0.4 + slot: 0.5 + content: 0.6078 + v4_full_rank: 26 + - frame_id: '1171281175' + frame_number: 4 + template_id: domestic_bim_actor_relations + confidence: 0.2376 + base: 0.2376 + penalty: 0.0 + label: reject + content_embedding: 0.5128 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.3 + slot: 0.5 + content: 0.5128 + v4_full_rank: 27 + - frame_id: '1171281177' + frame_number: 6 + template_id: compensation_complaint_map + confidence: 0.2144 + base: 0.2144 + penalty: 0.0 + label: reject + content_embedding: 0.497 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.5 + content: 0.497 + v4_full_rank: 28 + - frame_id: '1171281208' + frame_number: 27 + template_id: bim_adoption_central_split + confidence: 0.0685 + base: 0.2685 + penalty: 0.2 + label: reject + content_embedding: 0.5674 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.4 + slot: 0.5 + content: 0.5674 + v4_full_rank: 29 + - frame_id: '1171281210' + frame_number: 29 + template_id: process_product_two_way + confidence: 0.0635 + base: 0.2635 + penalty: 0.2 + label: reject + content_embedding: 0.5425 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.4 + slot: 0.5 + content: 0.5425 + v4_full_rank: 30 + - frame_id: '1171281195' + frame_number: 18 + template_id: bim_dx_comparison_table + confidence: 0.0406 + base: 0.3906 + penalty: 0.35 + label: reject + content_embedding: 0.4992 + axes: + anchor: 0.1429 + cardinality: 0.5 + relation: 0.4 + slot: 0.5 + content: 0.4992 + v4_full_rank: 31 + - frame_id: '1171281203' + frame_number: 23 + template_id: app_sw_package_vs_solution + confidence: 0.0067 + base: 0.3567 + penalty: 0.35 + label: reject + content_embedding: 0.5084 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.4 + slot: 0.5 + content: 0.5084 + v4_full_rank: 32 + usable_count: 6 + reject_count: 26 + 05-2: + mdx_title: 2. S/W 중심 설계 방식 + answer_frame_number: null + is_holdout: true + judgments_full32: + - frame_id: '1171281177' + frame_number: 6 + template_id: compensation_complaint_map + confidence: 0.5526 + base: 0.5526 + penalty: 0.0 + label: reject + content_embedding: 0.3879 + axes: + anchor: 0.0 + cardinality: 1.0 + relation: 1.0 + slot: 0.5 + content: 0.3879 + v4_full_rank: 1 + - frame_id: '1171281197' + frame_number: 19 + template_id: design_method_distortion_three_col + confidence: 0.3993 + base: 0.3993 + penalty: 0.0 + label: reject + content_embedding: 0.5467 + axes: + anchor: 1.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5467 + v4_full_rank: 2 + - frame_id: '1171281204' + frame_number: 24 + template_id: engn_sw_three_types + confidence: 0.3487 + base: 0.3487 + penalty: 0.0 + label: reject + content_embedding: 0.6266 + axes: + anchor: 0.3333 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.6266 + v4_full_rank: 3 + - frame_id: '1171281178' + frame_number: 7 + template_id: bigroom_system_components + confidence: 0.3364 + base: 0.3364 + penalty: 0.0 + label: reject + content_embedding: 0.6697 + axes: + anchor: 0.25 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.6697 + v4_full_rank: 4 + - frame_id: '1171281206' + frame_number: 26 + template_id: sw_dependency_four_problems + confidence: 0.2968 + base: 0.3968 + penalty: 0.1 + label: reject + content_embedding: 0.4505 + axes: + anchor: 0.6667 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.4505 + v4_full_rank: 5 + - frame_id: '1171281203' + frame_number: 23 + template_id: app_sw_package_vs_solution + confidence: 0.2555 + base: 0.2555 + penalty: 0.0 + label: reject + content_embedding: 0.5773 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.5773 + v4_full_rank: 6 + - frame_id: '1171281202' + frame_number: 22 + template_id: model_specialized_engn_sw + confidence: 0.2385 + base: 0.2385 + penalty: 0.0 + label: reject + content_embedding: 0.6798 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.6798 + v4_full_rank: 7 + - frame_id: '1171281208' + frame_number: 27 + template_id: bim_adoption_central_split + confidence: 0.2334 + base: 0.2334 + penalty: 0.0 + label: reject + content_embedding: 0.5503 + axes: + anchor: 0.3333 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5503 + v4_full_rank: 8 + - frame_id: '1171281201' + frame_number: 21 + template_id: solution_engn_split_diagram + confidence: 0.2262 + base: 0.2262 + penalty: 0.0 + label: reject + content_embedding: 0.6183 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.6183 + v4_full_rank: 9 + - frame_id: '1171281190' + frame_number: 13 + template_id: three_parallel_requirements + confidence: 0.2208 + base: 0.3208 + penalty: 0.1 + label: reject + content_embedding: 0.4875 + axes: + anchor: 0.3333 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.4875 + v4_full_rank: 10 + - frame_id: '1171281205' + frame_number: 25 + template_id: commercial_sw_four_categories + confidence: 0.2174 + base: 0.2174 + penalty: 0.0 + label: reject + content_embedding: 0.5747 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5747 + v4_full_rank: 11 + - frame_id: '1171281172' + frame_number: 1 + template_id: sw_development_cycle_six_nodes + confidence: 0.2123 + base: 0.2123 + penalty: 0.0 + label: reject + content_embedding: 0.6531 + axes: + anchor: 0.1667 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.6531 + v4_full_rank: 12 + - frame_id: '1171281194' + frame_number: 17 + template_id: bim_current_problems_paired + confidence: 0.2041 + base: 0.2041 + penalty: 0.0 + label: reject + content_embedding: 0.508 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.508 + v4_full_rank: 13 + - frame_id: '1171281180' + frame_number: 9 + template_id: pre_construction_model_info_stacked + confidence: 0.1886 + base: 0.2886 + penalty: 0.1 + label: reject + content_embedding: 0.5347 + axes: + anchor: 0.1667 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.5347 + v4_full_rank: 14 + - frame_id: '1171281209' + frame_number: 28 + template_id: sw_reality_three_emphasis + confidence: 0.1877 + base: 0.2877 + penalty: 0.1 + label: reject + content_embedding: 0.4261 + axes: + anchor: 0.25 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.4261 + v4_full_rank: 15 + - frame_id: '1171281192' + frame_number: 15 + template_id: policy_goals_plus_execution_requirements + confidence: 0.1674 + base: 0.1674 + penalty: 0.0 + label: reject + content_embedding: 0.4584 + axes: + anchor: 0.1429 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.4584 + v4_full_rank: 16 + - frame_id: '1171281173' + frame_number: 2 + template_id: engn_sw_development_domain_knowledge + confidence: 0.1624 + base: 0.1624 + penalty: 0.0 + label: reject + content_embedding: 0.6121 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.6121 + v4_full_rank: 17 + - frame_id: '1171281181' + frame_number: 10 + template_id: field_effectiveness_five_elements + confidence: 0.1524 + base: 0.1524 + penalty: 0.0 + label: reject + content_embedding: 0.5622 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5622 + v4_full_rank: 18 + - frame_id: '1171281174' + frame_number: 3 + template_id: overseas_bim_numbered_list + confidence: 0.1468 + base: 0.1468 + penalty: 0.0 + label: reject + content_embedding: 0.5338 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5338 + v4_full_rank: 19 + - frame_id: '1171281182' + frame_number: 11 + template_id: construction_bim_three_usage + confidence: 0.1464 + base: 0.1464 + penalty: 0.0 + label: reject + content_embedding: 0.5318 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5318 + v4_full_rank: 20 + - frame_id: '1171281213' + frame_number: 32 + template_id: policy_achievement_five_goals + confidence: 0.1454 + base: 0.1454 + penalty: 0.0 + label: reject + content_embedding: 0.5269 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5269 + v4_full_rank: 21 + - frame_id: '1171281189' + frame_number: 12 + template_id: construction_goals_three_circle_intersection + confidence: 0.1393 + base: 0.1393 + penalty: 0.0 + label: reject + content_embedding: 0.4967 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.4967 + v4_full_rank: 22 + - frame_id: '1171281193' + frame_number: 16 + template_id: bim_issues_quadrant_four + confidence: 0.1264 + base: 0.1264 + penalty: 0.0 + label: reject + content_embedding: 0.4322 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.4322 + v4_full_rank: 23 + - frame_id: '1171281198' + frame_number: 20 + template_id: dx_sw_necessity_three_perspectives + confidence: 0.0729 + base: 0.2729 + penalty: 0.2 + label: reject + content_embedding: 0.5393 + axes: + anchor: 0.5 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.5393 + v4_full_rank: 24 + - frame_id: '1171281195' + frame_number: 18 + template_id: bim_dx_comparison_table + confidence: 0.0646 + base: 0.2646 + penalty: 0.2 + label: reject + content_embedding: 0.4445 + axes: + anchor: 0.1429 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.4445 + v4_full_rank: 25 + - frame_id: '1171281212' + frame_number: 31 + template_id: industry_characteristics_three_col + confidence: 0.0506 + base: 0.2506 + penalty: 0.2 + label: reject + content_embedding: 0.553 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.553 + v4_full_rank: 26 + - frame_id: '1171281211' + frame_number: 30 + template_id: industry_current_status_three_col + confidence: 0.0383 + base: 0.2383 + penalty: 0.2 + label: reject + content_embedding: 0.4917 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.4917 + v4_full_rank: 27 + - frame_id: '1171281179' + frame_number: 8 + template_id: info_management_what_how_when + confidence: 0.0192 + base: 0.2192 + penalty: 0.2 + label: reject + content_embedding: 0.4792 + axes: + anchor: 0.3333 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.4792 + v4_full_rank: 28 + - frame_id: '1171281210' + frame_number: 29 + template_id: process_product_two_way + confidence: 0.0115 + base: 0.2115 + penalty: 0.2 + label: reject + content_embedding: 0.545 + axes: + anchor: 0.25 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.545 + v4_full_rank: 29 + - frame_id: '1171281175' + frame_number: 4 + template_id: domestic_bim_actor_relations + confidence: 0.0 + base: 0.1312 + penalty: 0.2 + label: reject + content_embedding: 0.4559 + axes: + anchor: 0.0 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.4559 + v4_full_rank: 30 + - frame_id: '1171281176' + frame_number: 5 + template_id: compensation_complaint_side_card + confidence: 0.0 + base: 0.2282 + penalty: 0.3 + label: reject + content_embedding: 0.4408 + axes: + anchor: 0.0 + cardinality: 0.5 + relation: 0.2 + slot: 0.0 + content: 0.4408 + v4_full_rank: 31 + - frame_id: '1171281191' + frame_number: 14 + template_id: three_persona_benefits + confidence: 0.0 + base: 0.1759 + penalty: 0.2 + label: reject + content_embedding: 0.4293 + axes: + anchor: 0.2 + cardinality: 0.0 + relation: 0.2 + slot: 0.0 + content: 0.4293 + v4_full_rank: 32 + usable_count: 0 + reject_count: 32 diff --git a/tests/regression/fixtures/89a_pre_baseline_sha.json b/tests/regression/fixtures/89a_pre_baseline_sha.json index 63b1b74..6a4dee6 100644 --- a/tests/regression/fixtures/89a_pre_baseline_sha.json +++ b/tests/regression/fixtures/89a_pre_baseline_sha.json @@ -2,7 +2,7 @@ "schema_version": 2, "axis": "IMP-89 89-a u4 — final.html SHA baseline captured via FULL run_phase_z2_mvp1 pipeline (flag OFF / default)", "description": "Frozen SHA-256 of `final.html` bytes (the artifact written to disk at src/phase_z2_pipeline.py:5994-5996) captured by running the full Phase Z pipeline end-to-end for each mdx 01-05 under PHASE_Z_B4_MAPPER_SOURCE=OFF. Under flag OFF the 89-a selector `_select_mapper_template_id(plan, T)` returns `T` verbatim, so the mapper input is byte-identical to the pre-89-a legacy call shape `map_mdx_to_slots(section, unit.frame_template_id)` — the rendered HTML and therefore the final.html SHA match the pre-89-a baseline. The u4 regression test runs the same pipeline shape under flag OFF and asserts SHA equality. Regenerate only when an upstream mapper/render/template delta is deliberately reviewed and accepted.", - "captured_at_utc": "2026-07-07T00:11:02Z", + "captured_at_utc": "2026-07-07T04:43:23Z", "renderer": { "entrypoint": "src.phase_z2_pipeline.run_phase_z2_mvp1", "write_site": "src/phase_z2_pipeline.py:5994-5996", @@ -19,8 +19,8 @@ "01.mdx": { "mdx_file": "01.mdx", "run_id": "89a_baseline_01", - "final_html_size_bytes": 38731, - "sha256": "749ebb626e284a62d37b5be32af97c61ae2a5b8d4226d1c3fa90f04c843d9fef", + "final_html_size_bytes": 36240, + "sha256": "1e398a65298064e0fe653453b81e625bf2eeaec4077a78d85f8e307e58d69c80", "pipeline_exit_code": null }, "02.mdx": { diff --git a/tests/regression/fixtures/imp95_pre_baseline_sha.json b/tests/regression/fixtures/imp95_pre_baseline_sha.json index 35ea54a..91d5090 100644 --- a/tests/regression/fixtures/imp95_pre_baseline_sha.json +++ b/tests/regression/fixtures/imp95_pre_baseline_sha.json @@ -2,7 +2,7 @@ "schema_version": 1, "axis": "IMP-95 u8 — final.html SHA baseline captured via FULL run_phase_z2_mvp1 pipeline under PHASE_Z_B4_V4_EVIDENCE=OFF and PHASE_Z_B4_MAPPER_SOURCE=OFF (defaults)", "description": "Frozen SHA-256 of `final.html` bytes (production write site src/phase_z2_pipeline.py:5994-5996) for mdx 01/02/04/05 under PHASE_Z_B4_V4_EVIDENCE OFF. Under flag OFF, IMP-95 (u1~u7) is strictly no-op for final.html (planner branch falls through to legacy _select_frame at u3; u4/u5/u6 additive telemetry confined to placement_trace per the trace-only docstring at src/phase_z2_pipeline.py:86). The u8 regression test asserts SHA equality with these frozen values, so any future code change that drifts the flag-OFF render output produces a mismatch and breaks the test. mdx 03 is excluded per Stage 2 u8 scope (mdx 03 정비 LOCK). Regenerate only when an upstream delta is reviewed and accepted as the new pre-IMP-95 reference.", - "captured_at_utc": "2026-07-07T00:09:32Z", + "captured_at_utc": "2026-07-07T04:41:54Z", "renderer": { "entrypoint": "src.phase_z2_pipeline.run_phase_z2_mvp1", "write_site": "src/phase_z2_pipeline.py:5994-5996", @@ -18,8 +18,8 @@ "01.mdx": { "mdx_file": "01.mdx", "run_id": "imp95_baseline_01", - "final_html_size_bytes": 38731, - "sha256": "749ebb626e284a62d37b5be32af97c61ae2a5b8d4226d1c3fa90f04c843d9fef", + "final_html_size_bytes": 36240, + "sha256": "1e398a65298064e0fe653453b81e625bf2eeaec4077a78d85f8e307e58d69c80", "pipeline_exit_code": null }, "02.mdx": { diff --git a/tests/test_phase_z2_issue17_provisional_renderable.py b/tests/test_phase_z2_issue17_provisional_renderable.py new file mode 100644 index 0000000..9e2a0ad --- /dev/null +++ b/tests/test_phase_z2_issue17_provisional_renderable.py @@ -0,0 +1,118 @@ +"""issue #17 — renderable-aware provisional 선택 테스트. + +계약: IMP-30 u1 provisional 합성이 rank-1 을 무조건 승격하던 것을, +partial HTML 이 존재하는 첫 judgment(rank 순) 승격으로 변경 (IMP-95 u6 +partial_exists 원칙). 전부 non-renderable 이면 기존대로 rank-1 (동작 보존). + +실측 근거: mdx05 05-2 rank-1 F6(compensation_complaint_map, contract-only) +승격 → mapper FitError → verbatim 복구 → selected_frame_not_applied 라벨 +→ PARTIAL_COVERAGE. renderable rank-6 F23 선택 시 정상 경로. +""" +from __future__ import annotations + +import src.phase_z2_pipeline as _pz +from src.phase_z2_pipeline import lookup_v4_match_with_fallback + + +def _j(rank, template_id, frame_id, label, conf=0.5): + return { + "v4_full_rank": rank, + "template_id": template_id, + "frame_id": frame_id, + "frame_number": rank, + "confidence": conf, + "label": label, + } + + +def _v4(judgments): + return {"mdx_sections": {"S1": {"judgments_full32": judgments}}} + + +def test_provisional_skips_contract_only_frames(monkeypatch): + """rank1/2 는 partial 없음, rank3 존재(+verbatim builder) → rank3 승격.""" + monkeypatch.setattr( + _pz, "_b4_partial_exists", + lambda tid: tid == "T_renderable", + ) + monkeypatch.setattr( + _pz, "_VERBATIM_BUILDER_TEMPLATE_IDS", frozenset({"T_renderable"}), + ) + v4 = _v4([ + _j(1, "T_contract_only_a", "F1", "reject", 0.6), + _j(2, "T_contract_only_b", "F2", "reject", 0.5), + _j(3, "T_renderable", "F3", "reject", 0.4), + ]) + match, trace = lookup_v4_match_with_fallback( + v4, "S1", allow_provisional=True, + ) + assert match is not None + assert match.template_id == "T_renderable" + assert match.provisional is True + assert trace["selection_path"] == "provisional_renderable_rank_3" + assert trace["selected_rank"] == 3 + + +def test_provisional_rank1_when_renderable(monkeypatch): + monkeypatch.setattr(_pz, "_b4_partial_exists", lambda tid: True) + monkeypatch.setattr( + _pz, "_VERBATIM_BUILDER_TEMPLATE_IDS", frozenset({"T_a", "T_b"}), + ) + v4 = _v4([ + _j(1, "T_a", "F1", "reject", 0.6), + _j(2, "T_b", "F2", "reject", 0.5), + ]) + match, trace = lookup_v4_match_with_fallback( + v4, "S1", allow_provisional=True, + ) + assert match.template_id == "T_a" + assert trace["selection_path"] == "provisional_rank_1" + assert trace["selected_rank"] == 1 + + +def test_provisional_all_non_renderable_keeps_rank1(monkeypatch): + """전부 partial 없음 → 기존 동작 보존 (rank-1, 정직 라벨은 하류 게이트).""" + monkeypatch.setattr(_pz, "_b4_partial_exists", lambda tid: False) + v4 = _v4([ + _j(1, "T_a", "F1", "reject", 0.6), + _j(2, "T_b", "F2", "reject", 0.5), + ]) + match, trace = lookup_v4_match_with_fallback( + v4, "S1", allow_provisional=True, + ) + assert match.template_id == "T_a" + assert trace["selection_path"] == "provisional_rank_1" + + +def test_provisional_reject_without_verbatim_builder_not_promoted(monkeypatch): + """renderable 이어도 reject + verbatim builder 미보유면 승격 금지 — + mapper 네이티브 렌더의 원문 drop 위험 (mdx05 05-2 F23 1-atom 손실 실측). + 조건 만족 후보 없음 → rank-1 유지 (verbatim 복구가 무손실 보장).""" + monkeypatch.setattr(_pz, "_b4_partial_exists", lambda tid: tid == "T_renderable") + monkeypatch.setattr(_pz, "_VERBATIM_BUILDER_TEMPLATE_IDS", frozenset()) + v4 = _v4([ + _j(1, "T_contract_only", "F1", "reject", 0.6), + _j(2, "T_renderable", "F2", "reject", 0.4), + ]) + match, trace = lookup_v4_match_with_fallback( + v4, "S1", allow_provisional=True, + ) + assert match.template_id == "T_contract_only" + assert trace["selection_path"] == "provisional_rank_1" + + +def test_provisional_non_reject_renderable_promoted_without_builder(monkeypatch): + """light_edit 등 비-reject 라벨은 verbatim builder 없어도 승격 가능 + (mapper 가 정상 fit 예상 — V4 판정 자체가 사용 가능 평가).""" + monkeypatch.setattr(_pz, "_b4_partial_exists", lambda tid: tid == "T_light") + monkeypatch.setattr(_pz, "_VERBATIM_BUILDER_TEMPLATE_IDS", frozenset()) + v4 = _v4([ + _j(1, "T_contract_only", "F1", "reject", 0.6), + _j(2, "T_light", "F2", "light_edit", 0.5), + ]) + match, trace = lookup_v4_match_with_fallback( + v4, "S1", allow_provisional=True, + ) + assert match.template_id == "T_light" + # IMP-39 label-priority sort 로 light_edit 이 정렬 1위 → rank_1 경로. + assert trace["selection_path"] == "provisional_rank_1"