- add visual fit classifier, router, retry, and failure routing modules - add composition planner and catalog-driven mapper - add Phase Z pipeline orchestration and architecture docs
11 KiB
Phase Z-2 — fit_classifier / overflow_router spec
Status : v0 spec (2026-04-29). 정의만. 구현은 별도 step (사용자 승인 후).
0. 목적 / 위치
자동 파이프라인이 Selenium 으로 detect 한 overflow / clipping 을 어떤 pipeline action 으로 routing 할지 결정하는 layer 의 spec.
현재 파이프라인은 detection 까지 정상 작동 (Selenium + debug.json 으로 신호 캡처). 그러나 detection 결과를 받은 직후 sys.exit(1) 으로 abort — detection 과 action 사이의 decision layer 가 비어 있음.
parse_mdx → align → composition (v0.2: capacity_fit) → render (Jinja2)
↓
Selenium visual_runtime_check ← 기존 (detection)
↓
🆕 fit_classifier ← 신규 (사실 분류)
↓
🆕 overflow_router ← 신규 (정책 결정)
↓
action :
- zone_ratio_retry ← 신규 미구현
- layout_adjust ← 신규 미구현
- details_popup_escalation ← 신규 미구현 (CLAUDE.md 의 <details> 원칙 활성)
- frame_reselect ← 신규 미구현 (V4 top-k 활용)
- adapter_needed ← composition v0.1.1 partial
- abort ← 기존 (현재 default)
핵심 원칙 : classifier = 사실 분류 (이 overflow 가 어떤 종류인가), router = 정책 결정 (그 종류면 무엇을 할 것인가). 두 layer 분리 — 같은 분류가 context (retry 횟수 등) 에 따라 다른 action 을 요구할 수 있음.
1. fit_classifier 입력 schema
1.1 detection-side (기존 — 이미 캡처됨)
| 입력 | 출처 | 비고 |
|---|---|---|
clipped_inner: [{class_name, excess_x, excess_y, scrollWidth/Height, clientWidth/Height}] |
run_overflow_check Selenium JS |
✅ |
zone 별 overflowed, excess_y/x |
같음 | ✅ |
| slide / slide_body level overflow | 같음 | ✅ |
1.2 composition-side (기존 — composition v0.2)
| 입력 | 출처 | 비고 |
|---|---|---|
unit.frame_template_id / contract_id |
composition + pipeline | ✅ |
capacity_fit (item count, fit_status) |
mapper.compute_capacity_fit |
✅ (v0.2) |
content_truncated_count (zone 별) |
pipeline 의 mapper 호출 후 | ✅ (v0.1.1) |
zone size (height_px, min_height_px, content_weight) |
compute_zone_layout |
✅ |
1.3 신규 입력 (이번 spec 에서 정의)
| 입력 | 비고 |
|---|---|
semantic_content_type |
className → 의미적 분류. §2 registry 참조 |
line_equivalent |
excess_y / 해당 element 의 line-height (1 줄 단위로 환산) |
structural_unit_drop_count |
structural_unit 중 완전히 또는 부분적으로 잘린 개수 |
retry_budget_used (router 의 상태) |
같은 slide 에 대해 router 가 이미 시도한 retry 횟수 |
2. className → semantic content_type registry
| className 패턴 | semantic type | 설명 |
|---|---|---|
transform-block, transform-block__*, transform-row* |
structural_unit |
paired comparison (AS-IS/TO-BE 한 쌍이 의미 단위). 행 단위 자르면 의미 깨짐 |
text-line, text-line--bullet, text-line--indent-* |
text_flow |
자유 wrap, 줄 단위 자르기 가능 |
*table*, native <table> |
tabular |
행/열 단위 의미 — 행 잘리면 의미 손실 |
f29b, f13b, f16b (frame-family root) |
frame_internal |
frame 자체가 zone 안에 못 들어감 (zone level 문제) |
*__cell, *__pillar, *__quadrant 등 frame 내부 cell |
frame_internal_cell |
frame 내부 cell 단위 (cell 내부 content 가 cell 경계 초과) |
*__title, *__section-title, *__banner, *__label 등 |
frame_label |
제목/라벨 단위 (text 와 비슷하지만 wrap 제약 있음) |
<img>, <svg>, *-bg 등 |
visual_asset |
시각 자산 (cropping 가능) |
| 매칭 안 됨 | unknown |
classifier 가 보수적으로 처리 (가장 안전한 action 선택) |
본 registry 는 신규 module (예: src/phase_z2_classifier.py) 의 상수 또는 catalog yaml entry 로 구현.
3. fit_classifier 출력 taxonomy
3.1 카테고리 정의 (계산 가능한 룰)
| 카테고리 | 판정 룰 |
|---|---|
frame_capacity_mismatch |
composition 단계의 capacity_fit.fit_status ∈ {strict_mismatch, exceeds_max, below_min, exceeds_truncate}. → 이미 v0.2 가 잡고 있는 영역. 본 카테고리는 post-render 검증 / 누락된 케이스 캐치 용 |
structural_major_overflow |
content_type = structural_unit 또는 tabular AND structural_unit_drop_count ≥ 1 (1 개 이상 완전 단위 잘림) |
structural_minor_overflow |
content_type = structural_unit 또는 tabular AND structural_unit_drop_count < 1 (마지막 1 단위가 부분만 잘림, 즉 boundary spill) |
tabular_overflow |
content_type = tabular (위와 별도 — 표는 행 1개라도 잘리면 popup) |
layout_zone_mismatch |
content_type = frame_internal (frame root 자체 overflow) — zone 이 frame 을 못 담음 |
moderate_overflow |
content_type ∈ {text_flow, frame_label} AND line_equivalent ∈ (1.5, 4] |
minor_overflow |
content_type ∈ {text_flow, frame_label} AND line_equivalent ≤ 1.5 |
hard_visual_fail |
위 어디에도 매핑 안 됨 OR retry budget 소진 |
3.2 분류 우선순위 (위에서 아래로)
frame_capacity_mismatch(composition 결과 우선)tabular_overflow(표는 즉시 popup 영역)structural_major_overflow(1+ 완전 단위 잘림)layout_zone_mismatch(frame root level)structural_minor_overflow(boundary spill — 양 작음)moderate_overflowminor_overflowhard_visual_fail(fallback)
3.3 핵심 구분
- structural_minor vs structural_major : 부분만 잘렸나 (
< 1unit) vs 완전 단위가 잘렸나 (≥ 1unit). 부분 잘림은 zone 을 조금 더 주면 fit 가능. 완전 단위 잘림은 의미 손실 — popup escalation. - structural vs moderate vs minor : content type 이 구조적 의미 단위 인지 여부. 같은 px 양이라도 text_flow 는 minor, structural_unit 은 structural_minor 이상.
4. overflow_router action mapping
| 카테고리 | action | retry budget | fallback (안 풀리면) |
|---|---|---|---|
minor_overflow |
zone_ratio_retry (양보 가능 zone 식별 → compute_zone_layout 재실행) |
1 | escalate → moderate_overflow 처리 |
moderate_overflow |
layout_adjust (8-preset 중 다른 preset 검토 + zone ratio 재분배) |
1 | escalate → structural_major_overflow 처리 |
structural_minor_overflow |
zone_ratio_retry (구조 자르지 않도록 zone 키움) |
1 | escalate → structural_major_overflow 처리 |
structural_major_overflow |
details_popup_escalation (<details>/<summary> path) |
N/A | popup 미구현 시 → frame_reselect → adapter_needed |
tabular_overflow |
details_popup_escalation 또는 frame_reselect (table-friendly frame 후보) |
N/A | 없으면 adapter_needed |
frame_capacity_mismatch |
frame_reselect (V4 top-k rank 2+ 평가) |
1 | 없으면 adapter_needed |
layout_zone_mismatch |
layout_adjust 또는 zone_ratio_retry |
1 | escalate → frame_reselect |
hard_visual_fail |
abort (현재 sys.exit(1) 그대로) |
— | — |
5. current code gap
5.1 이미 있어서 재사용 할 것
- detection (Selenium
run_overflow_check) — clipped_inner / excess_y / className 모두 캡처 - composition v0.2 의
compute_capacity_fit(item count level) - composition v0.1.1 의
adapter_neededcatch (mapper FitError) - debug.json 의
slide_status/zones/candidates_summary(입력 자료원) - 8-preset layout vocabulary +
compute_zone_layout
5.2 새로 만들어야 할 것
| 신규 항목 | 비고 |
|---|---|
| content_type registry (§2) | className → semantic type. classifier 의 핵심 입력 |
fit_classifier 모듈 |
§1 입력 → §3 카테고리 |
overflow_router 모듈 |
§4 카테고리 → action |
zone_ratio_retry action 구현 |
compute_zone_layout 의 retry path |
layout_adjust action 구현 |
preset 동적 변경 |
details_popup_escalation 구현 |
<details>/<summary> runtime + slot_payload 분리 룰 (큰 작업) |
frame_reselect 구현 |
V4 top-k 사용 (rank-2+ 평가) |
5.3 정의 vs 구현 분리
본 spec 은 정의만. 위 신규 항목 중 어느 axis 부터 구현할지는 별도 step 에서 사용자 승인 후. 한꺼번에 다 만들지 X.
6. 본 spec 의 활용 — visual fix 결정의 검증 자료
본 spec 은 룰북. 향후 overflow 발생 시 :
- classifier 가 어떤 카테고리 인지 결정
- router 가 어떤 action 인지 결정
- action 이 현재 구현되어 있나 확인
- 미구현이면 → "본 spec 의 이 path 미구현이라 처리 불가" 로 명확히 보고
중요 활용 : 누군가 (Claude 든 사람이든) "padding 줄여서 끼우자" 같은 fix axis 를 제시하면 — 이 fix 가 본 spec 의 어느 action 에도 매핑되지 않음 → 자동 반려. 본 spec 을 검증 자료로 가지면 symptom-silencing fix 가 들어올 자리가 없어짐.
7. MDX 03 의 10px clipping 을 본 spec 으로 분류 (검증용 sample, fix 대상 X)
MDX 03 = sample instance. spec 룰의 작동 검증 용 — fix 대상 아님.
측정값
- excess_y = 10px (~0.6 줄, transform-row line-height 15.95px 기준)
- clipped element className =
transform-block의 마지막 row (cell 내부) - semantic content_type =
structural_unit(transform-row pair) - structural_unit_drop_count = 0.6 (1 개의 마지막 row 가 부분만 잘림 — 완전 단위 1 개가 아님)
- composition
capacity_fit.fit_status=ok
분류 적용 (§3.2 우선순위)
frame_capacity_mismatch? — capacity_fit ok → ✗tabular_overflow? — content_type 이 tabular 아님 → ✗structural_major_overflow? — drop_count< 1→ ✗layout_zone_mismatch? — frame_internal 아님 → ✗structural_minor_overflow? — content_type = structural_unit AND drop_count< 1→ ✓
카테고리 = structural_minor_overflow
Action mapping 적용 (§4)
→ zone_ratio_retry (구조 자르지 않도록 F29 zone 을 더 키움)
현재 구현 상태
→ zone_ratio_retry 는 MISSING. 따라서 본 spec 기준으로 MDX 03 은 classifier 가 정상 작동하면 structural_minor_overflow 로 분류되고 zone_ratio_retry 로 routing 되어야 하는 case 인데, 그 path 가 현재 미구현. 따라서 정직한 상태는 RENDERED_WITH_VISUAL_REGRESSION 그대로 유지.
반례 검증 (이전 잘못된 fix)
이전에 시도했던 "transform-block padding 6→4 + transform-row padding 3→2" :
- 본 spec 의 어떤 action 에도 매핑되지 X (
density_reduce같은 action 자체가 없음) - 따라서 본 spec 기준으로 자동 반려되는 fix axis — 들어올 자리 없음
이게 본 spec 이 visual fix 결정의 검증 자료 로 작동한다는 증거.
8. 다음 step (구현 우선순위 — 사용자 결정 영역)
본 spec 정의 후 구현 axis 후보 (사용자가 우선순위 결정):
- A. content_type registry + fit_classifier (분류 layer)
- B. overflow_router (정책 layer)
- C.
zone_ratio_retryaction (가장 자주 트리거될 action) - D.
details_popup_escalation(큰 작업 — 새 path) - E.
frame_reselect(V4 top-k 사용 layer)
각 axis 는 별도 step 으로 한 단위씩. 한꺼번에 묶지 X.