Files
C.E.L_Slide_test2/PHASE-X-BX.md
kyeongmin 028f611070 XBX-2 수행 방향 상세화: overflow 프로세스 원인 3개 + 수행 순서
- Selenium 측정 실패 (data URI 크기 제한)
- overflow 분기에 Type B zone 없음
- calculate_fit에서 Type B 역할 인식 불가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 06:56:58 +09:00

12 KiB

Phase X-BX': 유형 B 미완료 사항 정리

최종 업데이트: 2026-04-07 전제: 유형 A 코드 절대 건드리지 않음. A는 완벽하게 동작 중. 수정도 재검증도 하지 않음. 유형 B의 code_assembled + 파이프라인만 수정. 02번 MDX 먼저 → 03번 확장 순서로 진행.


MDX 원본 위치

D:\ad-hoc\cel\src\content\docs\Civil DX\BIM과 DX의 이해\


근본 원인

Type A는 Kei가 역할명을 "배경", "본심", "첨부", "결론"으로 내려주고, 하류 코드가 containers["배경"] 처럼 역할명 글자로 매칭한다. → 동작함.

Type B는 Kei가 역할명을 "필수요건", "과정혁신" 등으로 내려주는데, 하류 코드가 여전히 containers["배경"]을 찾는다. → 키가 없어서 빈 것.

해결: Type B일 때는 역할명 글자가 아니라 containers에 있는 키를 순회하고, zone 정보(top, bottom_left 등)로 위치를 결정한다.

# Type A (기존 그대로):
for role in ["배경", "본심", "첨부", "결론"]:
    container = containers[role]

# Type B (분기 추가):
for role in containers:
    zone = containers[role].zone  # top, bottom_left, bottom_right, footer

XBX-1: 들여쓰기 계층

현상

MDX의 2단 계층(* > *)이 동일 레벨로 평탄화됨.

MDX 원본:                             현재 HTML:
- 안전과 품질 (소제목)         →      • 안전과 품질           ← 소제목인데 불릿과 동일
  - 시설물의 요구 성능을...    →      • 시설물의 요구 성능을... ← 구분 없음

목표

■ 안전과 품질              ← 소제목 (bold, 색상 구분)
    • 시설물의 요구 성능...  ← 본문 불릿 (들여쓰기)

수행 방향

1단계: normalizer에서 불릿 depth 보존

현재 src/mdx_normalizer.py의 section content:

"**안전과 품질**\n시설물의 요구 성능을..."   ← flat, depth 정보 없음

수정 후:

"- **안전과 품질**\n  - 시설물의 요구 성능을..."   ← depth 마커 보존

markdown-it의 list_item_open 토큰에 이미 indent 정보 있음 (88번째 줄). section content 수집 시 indent level을 보존하면 됨.

2단계: 조립 로직에서 depth별 스타일 분기

scripts/assemble_stage2.py _assemble_type_b + src/block_assembler.py _assemble_slide_html_type_b:

  • depth 1 (- ) → 소제목 스타일 (bold, 색상 구분, 카드)
  • depth 2 ( -) → 본문 불릿 (들여쓰기, normal weight)

검증

02번 상단 "안전과 품질/생산성 향상/소통과 신뢰" 3개 소제목이 카드로 분리, 각각의 하위 불릿 2줄이 들여쓰기되어 보임.


XBX-2: overflow → 콘텐츠 맞춤 프로세스

현상

상단 zone(255px)에 소제목 3개 + 불릿 6줄 + 이미지 → overflow. 하단 우측에 표 데이터가 너무 많아서 overflow.

프로세스 (네가 말한 것)

넘침 감지 → 최대 몇 줄까지 가능? → 몇 자 이내로 정리 → Kei에게 요약 요청 → 재수취 후 정리

왜 안 되는가 (원인 3개)

원인 1: Selenium 측정 실패

  • slide_measurer.py 144줄: 2.2MB HTML을 data: URI로 로드 → 브라우저 크기 제한
  • Type A는 ~214KB라 동작, Type B는 이미지 base64 포함 2.2MB라 실패
  • 수정: 임시 파일로 저장 후 file:// URI로 로드 (크기 제한 없음)

원인 2: overflow 분기에 Type B zone 없음

  • pipeline.py 538-553줄: sidebarbody만 처리
  • Type B zone(top, bottom)은 분기 없음 → overflow 감지돼도 무시됨
  • 수정: if layout_template == "B": 분기 추가. top/bottom overflow 시 처리

원인 3: calculate_fit에서 Type B 역할 인식 불가

  • fit_verifier.py 307줄: role_font_map = {"본심": "core", "배경": "bg", ...}
  • Type B 역할명이 이 dict에 없어서 항상 "core" fallback
  • overflow 계산이 부정확 → needs_escalation이 항상 False
  • 수정: if layout_template == "B": 분기. zone 기반 font 매핑

수행 순서

  1. Selenium 측정 수정 — data URI → 임시파일 방식 (slide_measurer.py)
  2. overflow 분기 추가 — Type B zone 처리 (pipeline.py)
  3. calculate_fit Type B 지원 — zone 기반 font 매핑 (fit_verifier.py)
  4. 에스컬레이션 → Kei 요약 요청 — 이미 있는 코드 활용 (pipeline.py 584-606)
  5. 검증 — 02번 파이프라인 돌려서 상단 overflow 해소 확인

검증

  • Selenium 측정에서 상단/하단 zone overflow 감지
  • overflow 시 Kei에게 요약 요청 → 줄어든 콘텐츠로 재조립
  • 결과 스크린샷에서 overflow 없음

XBX-3: 하단 구조 — 중제목 별도 행

현상

"DX 기반 Process 혁신에 따른 주체별 기대효과"가 별도 행 → 공간 낭비.

현재:                                      목표:
┌──────────────────────────────┐          ┌─────────────┬──────────────┐
│ DX 기반 Process 혁신에 따른...│ ← 별도행  │ 2.1 업무 수행│ 2.2 DX 시행  │
├──────────────┬───────────────┤          │ 과정의 변화  │ 주체별 기대효과│
│ 2.1 업무 수행 │ 2.2 DX 시행   │          │ (불릿)      │ (표)         │
│ 과정의 변화   │ 주체별 기대효과│          └─────────────┴──────────────┘
└──────────────┴───────────────┘          중제목은 2분할 상단에 작게 표시

수행 방향

scripts/assemble_stage2.py _assemble_type_b + src/block_assembler.py _assemble_slide_html_type_b:

  • 하단 대목차(level=2)를 별도 행으로 배치하지 않음
  • 2분할 각 칸의 상단에 작은 라벨로 표시하거나, 2분할 위에 한 줄 라벨로 통합
  • 절약된 높이를 2분할 콘텐츠에 할당

검증

하단 영역 전체가 2분할 콘텐츠로 사용됨. 중제목이 별도 행을 차지하지 않음.


XBX-4: 하단 좌/우 높이 불균형

현상

02번 컨테이너:

  • bottom_left (업무 프로세스 변화): 124px
  • bottom_right (주체별 기대효과): 321px

높이가 2.5배 차이.

수행 방향

src/space_allocator.pybuild_containers_type_b (544-556줄):

  • 현재 코드에서 height_px=bottom_h로 동일하게 주고 있음
  • 문제는 Kei가 준 weight가 다른 것 → weight에 의해 top/bottom 비율이 달라지고, 그 결과 bottom_h 자체가 줄어드는 구조인지 추적 필요
  • 하단 좌/우는 무조건 동일 높이(bottom_h)로 고정

검증

하단 좌/우 컨테이너가 동일 높이로 나옴.


XBX-5: before→filled→after 파이프라인 연결

현상

Type B의 filled HTML이 2,742 bytes (거의 빈 HTML). Type A는 214KB.

원인

하류 코드가 containers["배경"], containers["본심"] 처럼 Type A 역할명 글자로 매칭. Type B의 역할명("필수요건", "과정혁신" 등)은 이 키에 없어서 빈 것.

수행 방향

원칙: Type A 코드 그대로 두고, if layout_template == "B": 분기만 추가.

5-1. src/step_visualizer.py (9곳+)

현재:

COLORS = {"배경": "#dc2626", "본심": "#2563eb", "첨부": "#16a34a", "결론": "#7c3aed"}
for role in ["배경", "본심", "첨부", "결론"]:
    container = containers[role]

수정: Type B 분기 추가. 기존 Type A 코드는 한 글자도 안 건드림.

if layout_template == "B":
    for role in containers:
        zone = containers[role].zone
        color = ZONE_COLORS.get(zone, "#333")  # zone 기반 색상
        # ... Type B 시각화
else:
    # 기존 Type A 코드 그대로
    for role in ["배경", "본심", "첨부", "결론"]:
        ...

수정 대상 함수 (9곳):

  • _gen_stage_1_5a (271줄)
  • _gen_stage_1_5a_content (297줄)
  • _gen_stage_1_5b (334줄)
  • _gen_stage_1_7 (371줄)
  • _gen_stage_1_8_fit_before (419줄)
  • _gen_stage_1_8_fit_after (465줄)
  • _gen_stage_1_8_blocks (534줄)
  • _gen_stage_2 (650줄, 683줄)

5-2. src/fit_verifier.py

  • ROLE_ZONE_MAP (488-493줄) — 이미 부분 수정됨. containers에 zone 있으면 그걸 사용.
  • role_font_map (307줄) {"본심": "core", ...} — Type B 분기 추가: zone 기반 매핑 ("top" → "core", "bottom_left" → "core" 등)
  • role_line_height (308줄) — 동일하게 분기
  • Type A 코드 안 건드림. ROLE_ZONE_MAP, role_font_map은 그대로 두고 fallback으로만 사용.

5-3. src/renderer.py

  • _find_h fallback 이미 추가됨. Type A는 _find_h("배경") 그대로 동작.
  • Type B에서 body_row_h 계산이 맞는지 확인 필요 — Type B는 body_row가 없고 top+bottom 구조.
  • 필요시 if layout_template == "B": 분기 추가.

5-4. src/slide_measurer.py

  • CSS 클래스 area-*로 zone 탐색 → 역할명 하드코딩 없음. 수정 불필요.
  • _assemble_slide_html_type_barea-top, area-bottom, area-footer 클래스를 생성하므로 Selenium 측정이 그대로 동작.

검증

02번 MDX로 파이프라인 실행 → filled HTML이 10KB+ → Selenium 측정 정상 → after HTML 생성.


XBX-6: Sonnet HTML 재구성 프로세스 분리

현상

Stage 2(src/pipeline.py 901-957줄)에서 Sonnet(generate_with_retry)이 HTML 재구성. Type B에서는 품질 불안정.

수행 방향

src/pipeline.py stage_2 함수에 Type B 분기 추가:

async def stage_2(context: PipelineContext) -> dict:
    if context.analysis.layout_template == "B":
        # Type B: code_assembled 결과를 직접 사용, Sonnet 재구성 스킵
        from src.block_assembler import assemble_slide_html
        generated = assemble_slide_html(context)
        return {"generated_html": generated}
    
    # Type A: 기존 Sonnet 재구성 코드 그대로
    from src.content_verifier import generate_with_retry
    ...
  • Sonnet 코드 삭제하지 않음
  • Type B일 때만 스킵
  • code_assembled HTML은 assemble_slide_html(context)로 생성 (이미 동작 확인됨)

검증

  • Type A: 기존대로 Sonnet 재구성 → 결과 동일
  • Type B: code_assembled 직접 사용 → 결과가 스크린샷에서 정상

작업 순서

02번 먼저 완성 → 03번 확장:

  1. XBX-1 (들여쓰기) — normalizer depth 보존 + 조립 로직 분기
  2. XBX-3 (하단 구조) — 중제목 별도행 → 라벨로 통합
  3. XBX-4 (하단 높이) — 좌/우 균등 확인 + 수정
  4. XBX-5 (파이프라인 연결) — step_visualizer/fit_verifier/renderer Type B 분기
  5. XBX-2 (overflow) — 파이프라인 연결 후 Selenium으로 자동 확인
  6. XBX-6 (Sonnet 분리) — pipeline.py Type B 분기
  7. 03번 확장 — 03번 MDX에서도 동작 확인 (표 보존, 3단 계층 등)

02번 run 정보

  • 최신 run: data/runs/20260406_121405
  • 스크린샷: steps/code_assembled_02_2x.png
  • containers: top=255px(w=847px), bottom_left=124px, bottom_right=321px, footer=83px

핵심 원칙

  • 하드코딩 절대 금지
  • HTML 결과물 고치지 말고 파이프라인 프로세스 고칠 것
  • 제목/텍스트는 원본 MDX에서 그대로
  • 유형 A 코드 절대 건드리지 않음 — A는 완벽하게 동작 중. 수정도 재검증도 하지 않음.
  • Type B 코드는 기존 코드에 분기(if layout_template == "B") 추가로만 구현
  • 검증은 반드시 렌더링(스크린샷)으로