From 565e6b092e552b9aa5ef54774e96b0287e8969ad Mon Sep 17 00:00:00 2001 From: kyeongmin Date: Mon, 4 May 2026 17:40:21 +0900 Subject: [PATCH] Add Phase Z classifier placement diagnostics - consume debug_zones[i].placement_trace in classify_visual_runtime_check - surface per-zone diagnostic in fit_classification.placement_diagnostics - preserve canonical render SHA and existing classifier output schema --- src/phase_z2_classifier.py | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/phase_z2_classifier.py b/src/phase_z2_classifier.py index a0a76fb..a4c3160 100644 --- a/src/phase_z2_classifier.py +++ b/src/phase_z2_classifier.py @@ -288,6 +288,51 @@ def classify_overflow( # ─── visual_runtime_check 결과 → 전체 fit_classification trace ──── +def _build_placement_diagnostic_for_zone( + zone_position: str, + placement_trace: Optional[dict], + mapper_template_id: Optional[str], +) -> dict: + """zone 별 placement diagnostic 빌더 — placement_trace from B4 → 진단 dict. + + phase_z2_pipeline.py 의 trace-only B1→B2→B4 chain 결과 (debug_zones[i].placement_trace) + 를 per-zone surface 한 진단. classifier 는 *consume only* — placement_trace + raw 구조는 미변경. + + Args: + zone_position : zone position ("top" / "bottom_l" 등) + placement_trace : phase_z2_pipeline.py 의 placement_trace dict 또는 None + mapper_template_id : 기존 mapper / V4 가 선택한 frame template_id + (placement_trace 에 mapper_frame_template_id 누락 시 fallback) + + Returns: + per-zone placement diagnostic dict (shape-stable, missing fields = None / 0). + """ + if placement_trace is None: + return { + "zone_position": zone_position, + "mapper_frame_template_id": mapper_template_id, + "b4_selected_template_id": None, + "frame_selection_matches_mapper": None, + "frame_selection_match_note": "no placement_trace recorded", + "region_count": 0, + "slot_assignment_count": 0, + "rejection_count": 0, + } + return { + "zone_position": zone_position, + "mapper_frame_template_id": ( + placement_trace.get("mapper_frame_template_id") or mapper_template_id + ), + "b4_selected_template_id": placement_trace.get("selected_template_id"), + "frame_selection_matches_mapper": placement_trace.get("frame_selection_matches_mapper"), + "frame_selection_match_note": placement_trace.get("frame_selection_match_note"), + "region_count": len(placement_trace.get("internal_regions") or []), + "slot_assignment_count": len(placement_trace.get("slot_assignments") or []), + "rejection_count": len(placement_trace.get("rejection") or []), + } + + def classify_visual_runtime_check(overflow: dict, debug_zones: list[dict]) -> dict: """Selenium overflow + composition 의 zone debug → 전체 fit_classification 산출. @@ -304,7 +349,21 @@ def classify_visual_runtime_check(overflow: dict, debug_zones: list[dict]) -> di summary : 텍스트 요약 (n events, categories seen) categories_seen : 등장한 카테고리 unique list unclassified_signals : 미분류 신호 (raw Selenium 결과 중 분류 안 된 것) + placement_diagnostics : per-zone placement_trace 진단 (B4 vs mapper + divergence + region / slot_assignment / rejection + count) — passed 여부 무관 항상 surface """ + # placement_diagnostics — debug_zones[i].placement_trace 를 per-zone diagnostic 으로 surface. + # passed 여부 무관 항상 빌드 (B4 vs mapper divergence 가 passed 에서도 진단 가치). + placement_diagnostics = [ + _build_placement_diagnostic_for_zone( + zone_position=dz.get("position", "?"), + placement_trace=dz.get("placement_trace"), + mapper_template_id=dz.get("v4_template_id"), + ) + for dz in (debug_zones or []) + ] + if overflow.get("passed", False): return { "visual_check_passed": True, @@ -312,6 +371,7 @@ def classify_visual_runtime_check(overflow: dict, debug_zones: list[dict]) -> di "summary": "visual check passed — no overflow to classify", "categories_seen": [], "unclassified_signals": [], + "placement_diagnostics": placement_diagnostics, } # zone position → debug_zones 매핑 (capacity_fit_status 추출용) @@ -392,4 +452,5 @@ def classify_visual_runtime_check(overflow: dict, debug_zones: list[dict]) -> di ), "categories_seen": categories, "unclassified_signals": unclassified, + "placement_diagnostics": placement_diagnostics, }