Files
C.E.L_Slide_test2/figma_to_html_agent/HARNESS.md
kyeongmin 9fbe3ac90c add: figma_to_html_agent/blocks/ + 변환 도구 docs 갱신
전체 401 files (397 추가 + 4 수정), 14304 insertions.

추가:
- figma_to_html_agent/blocks/ — Figma 변환 결과 (32 frame, ~79MB).
  각 frame folder = {analysis.md, flat.md, texts.md, index.html, assets/,
  _renders/, _render.py, RELATIONSHIPS.md / STATUS.md / classification.md
  (일부 frame)}.
  Phase Z 의 *figma source layer* — runtime 에서 직접 사용 X, contract /
  partial / builder adapter (미래 axis A) 의 source.
- figma_to_html_agent/DISCUSSION-SUMMARY-20260411.md — 변환 설계 회의 기록.
- figma_to_html_agent/HARNESS.md — 변환 검증 harness.
- figma_to_html_agent/scripts/fetch_figma_screenshots.py — Figma 스크린샷 자동 수집.

수정:
- figma_to_html_agent/PROCESS-CONTROL.md / PROCESS.md / RULES.md —
  변환 프로세스 / 룰 갱신 (R8/R9 lock 강화 등).
- figma_to_html_agent/blocks_index.md — 32 frame 인덱스 갱신.

Phase Z 영향 0 (figma_to_html_agent/blocks/ 가 V4 catalog +
templates/phase_z2/families adapter 의 source — runtime 에서 직접 import X).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:41:05 +09:00

295 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 변환 하네스 (Conversion Harness)
> **이 체크리스트의 모든 항목을 순서대로 통과해야 한다. 건너뛰기 금지.**
> 각 항목에서 "확인"이 안 되면 다음으로 넘어가지 않는다.
> **2층 구조: 1층(행동 통제) → 2층(구현)**. 1층을 통과하지 않으면 2층 진입 금지.
---
# ═══ 1층: 행동 통제 하네스 ═══
## A. 사용자 요청 해석
- [ ] 사용자가 실제로 말한 문제를 **한 문장으로** 다시 적었는가?
- [ ] 내가 하려는 수정이 **그 문제에 직접 대응**하는가?
- [ ] 사용자가 말하지 않은 구조 변경을 하려면 **사전 합의**가 필요한가?
- [ ] "이것도 같이 바꾸면 좋겠다"는 생각이 들면 → **멈추고 물어본다**
## B. 블록 분류 (patch / rewrite / hold)
작업 시작 전 반드시 분류하고 근거를 3줄로 적는다.
```
이 블록은 무엇인가?
├── patch — 구조는 살아 있고 특정 부분만 수정하면 됨
│ 근거: ___
├── rewrite — 구조 자체가 틀어져서 처음부터 다시 해야 함
│ 근거: ___
└── hold — 지금 건드리지 않고 보류
근거: ___
```
- [ ] 분류 결정함 → `blocks/{id}/classification.md`에 기록
- [ ] 근거 3줄 적음
- [ ] **patch가 아닌 블록에 임의 구조 전환 금지**
- [ ] **rewrite 블록은 사용자 확인 후에만 착수**
## C. 변경 범위 제한
- [ ] **이번 수정의 단일 목표**를 한 문장으로 적었는가?
- [ ] 이번 수정에서 바꾸는 축은 **1개**인가?
- 예: spacing만 / bullet model만 / gradient CSS 변환만
- [ ] 다른 축은 건드리지 않았는가?
- [ ] 현재 정상 동작하는 요소를 **변경 금지 목록**으로 적었는가?
```
변경 대상: ___
변경하지 않는 것: ___
```
## D. 변경 전 기록
- [ ] 수정 전 현재 값/구조 기록 (되돌릴 수 있도록)
- [ ] 변경 전 렌더링 스크린샷 baseline 저장
## E. 중단 조건
아래 상황 발생 시 **즉시 멈추고 사용자에게 보고**:
- [ ] 인코딩 깨짐 발견
- [ ] MCP 좌표와 렌더 결과가 크게 다름 (30px+ 이상 차이)
- [ ] 패치하려던 블록이 구조 붕괴 상태
- [ ] 한 군데 고치니 다른 곳이 깨짐 (cascade failure)
- [ ] 사용자 요청과 다른 방향으로 가고 있음을 인지
→ patch 중단
→ rewrite required로 분류 전환
`blocks/{id}/STATUS.md` 남기고 다음 블록으로
## F. 완료 판정
patch 또는 rewrite가 끝났다고 판단하기 전에:
- [ ] 사용자가 지적한 문제가 **실제로 사라졌는가** (렌더링 확인)
- [ ] 새로 생긴 **부작용이 없는가**
- [ ] baseline 대비 **더 나빠진 요소가 없는가**
- [ ] 아래 4개 산출물을 남겼는가:
- before screenshot
- after screenshot
- 변경 요약 3줄
- classification 결과 (patch/rewrite/hold)
위 전부 통과해야 "완료". 하나라도 안 되면 미완료.
---
# ═══ 2층: 구현 하네스 ═══
> **1층 A~F를 모두 통과한 후에만 아래 진행**
## 0. 시작 전 — 규칙 파일 읽기 + 행동 원칙 확인
- [ ] RULES.md 읽음 (R1~R19 전부)
- [ ] PROCESS-CONTROL.md 읽음 (규칙 1~8)
- [ ] PROCESS.md 읽음 (STEP 0~10)
- [ ] HARNESS.md 읽음 (이 파일)
- [ ] blocks_index.md 읽음 (기존 패턴 확인)
### 행동 원칙 (PROCESS-CONTROL에서, 매 작업 전 상기)
- [ ] **소스는 Figma 데이터다** — PNG를 보고 판단하지 않음 (규칙1)
- [ ] **이미지 해석 금지** — 멀티모달로 gradient 방향 추측 안 함 (규칙2)
- [ ] **작동하는 것은 건드리지 않는다** — A만 문제면 A만 수정 (규칙3)
- [ ] **한 번에 하나만 바꾼다** — gradient 각도와 border-radius 동시 변경 금지 (규칙4)
- [ ] **사용자가 말한 것만 한다** — 자의적 해석 금지 (규칙5)
- [ ] **찍어맞추기 금지** — 값을 바꾸기 전에 WHY를 먼저 설명 (규칙6)
- [ ] **쉬운 전면 재작성 금지** — 80점에서 2개 고칠 때 구조를 갈아엎지 않음 (규칙7)
- [ ] **MCP 데이터 전수 반영** — "핵심만", "단순화" 금지 (규칙8)
---
## 1. MCP 데이터 수집
- [ ] get_metadata 호출 → 모든 노드 ID, 위치, 크기 확보
- [ ] get_design_context 호출 → gradient, font, style, rotation 확보
- [ ] 에셋 URL 목록 추출
---
## 2. 에셋 분류 — R9 CSS vs 이미지 판정 (에셋마다 반드시 수행)
각 에셋에 대해:
```
이 에셋이 뭔가?
├── 단순 사각형 + gradient → CSS linear-gradient + border-radius [R9]
├── 단순 원 + gradient → CSS border-radius:50% + linear-gradient [R9]
├── 단순 직선/점선 → CSS border [R9]
├── 단색 사각형 → CSS background-color [R9]
├── plus-darker blend → multiply로 교체 [R10]
└── 복잡 path / 사진 / 아이콘 / 곡선 → 이미지 유지
```
- [ ] 모든 에셋 분류 완료
- [ ] CSS 대체 가능한 에셋은 다운로드하지 않음
- [ ] 이미지 유지 에셋만 다운로드
---
## 3. gradient 변환 — R9 CSS 대체 에셋
CSS로 대체하기로 한 에셋마다:
- [ ] SVG 파일을 열어 linearGradient 데이터 추출
- [ ] gradient_math.py로 CSS linear-gradient 변환 (인라인 복사 금지)
- [ ] viewBox padding이 있으면 R12 remap 적용
- [ ] 변환 결과 기록
---
## 4. 구조 결정 — R17 레이아웃 타입
```
이 블록의 레이아웃은?
├── 순차 행 (비교표, 이슈 목록, 불릿 리스트)
│ → flex column (행 간) + flex row (행 내부) [R17]
│ → 텍스트 늘면 행이 밀림
├── 표 (행×열 구조)
│ → CSS grid [R17]
│ → border가 곧 그리드 라인
│ → 셀 높이 auto
├── 2D 다이어그램 (원, 노드, 겹침)
│ → absolute + 명시 height + zoom [R19]
│ → 겹침이 있으므로 flex 불가
└── 좌우 분할 (좌:이미지 / 우:목록)
→ display:flex (좌:flex-none / 우:flex column)
```
- [ ] 레이아웃 타입 결정
- [ ] zoom 적용 (transform:scale 금지) [R19]
---
## 5. HTML 작성 — 요소별 체크
### 5-A. DOM 순서
- [ ] MCP metadata 순서 = HTML DOM 순서 (나중 요소가 위에 렌더)
- [ ] z-index 별도 지정 필요 없음 (DOM 순서로 해결)
### 5-B. 텍스트 요소
- [ ] 본문 텍스트에 position:absolute 사용 안 함 [R17]
- [ ] overflow:hidden으로 텍스트 숨기기 안 함 [R17]
- [ ] 고정 height로 텍스트 제한 안 함 [R17]
- [ ] word-break: keep-all 적용 [R14]
- [ ] descender 보정 필요한가? [R1]
- line-height / font-size < 1.448 (Noto Sans KR) → padding-bottom 계산
- [ ] gradient 텍스트인가? → background-clip: text [R4]
- [ ] 다중 fills인가? → 첫 번째 불투명 fill만 사용 [R5]
- [ ] 중복 노드인가? (동일 좌표 + 동일 내용) → 1개만 렌더 [R6]
- [ ] 세로 텍스트인가? (width < fontSize × 0.8) → `<br>` 줄바꿈, writing-mode 사용 금지 [R3]
- [ ] vertical center 정렬이 필요한가? → flex justify-center [R15]
- [ ] 불필요한 `<br>` 삽입 안 함 (자연 wrap에 맡김)
### 5-C. 불릿/마커 리스트 [R13]
- [ ] `<ul><li>` 사용 안 함
- [ ] R13 flex pair 구조 사용:
```html
<div class="bullet-row">
<span class="marker">•</span>
<span class="text">내용</span>
</div>
```
- [ ] 2줄째가 첫째 줄 텍스트 시작점에 정렬되는가?
- [ ] level 2 (- dash)는 padding-left로 한 단계 더 들여쓰기
- [ ] 우측 배치: bullet-row 자체는 좌→우 읽기, 컨테이너가 우측 정렬
### 5-D. 회전 요소 [R2]
- [ ] MCP bbox가 회전된 상태인가? (width > height × 1.5 for 단일 문자)
- [ ] 회전 bbox의 x좌표를 그대로 left에 넣지 않음 [R2 addendum]
- [ ] 같은 축 요소들의 center_x를 기준으로 정렬
- [ ] design_context의 center 좌표 + translate(-50%,-50%) 사용
### 5-E. 이미지 프레임 [R16]
- [ ] overflow:hidden + left/width로 부분 표시
- [ ] rotate(180deg) 하단은 이미지 배치 반전
- [ ] crop variant와 label position 분리 [R18]
- [ ] pill 접합이 있는 경우: seam 메타데이터 기록 (pill_seam_meta.md)
- left_seam, right_seam, flat_start, flat_end 측정
- label anchor는 현재 designer-tuned fallback, 장기 computed
### 5-F. CSS gradient/도형 [R9]
- [ ] 단순 도형은 CSS div + border-radius + linear-gradient
- [ ] gradient_math.py 결과값 사용 (감으로 넣지 않음)
- [ ] stroke: border로 변환 [R11 케이스A/B]
### 5-G. 배경/장식
- [ ] .slide 배경은 항상 #fff [R7]
- [ ] 장식 요소(배경 텍스처, 아크 등)는 absolute OK
- [ ] 장식 요소의 mix-blend-mode 반영 (multiply 등)
---
## 6. Flexible 구조 검증
- [ ] 텍스트를 2배로 늘렸을 때 겹치지 않는가?
- [ ] 텍스트를 절반으로 줄였을 때 빈 공간이 방치되지 않는가?
- [ ] 불릿 항목을 추가했을 때 아래 요소가 자연스럽게 밀리는가?
- [ ] 표의 경우: 셀 텍스트 늘면 행이 늘고 border가 따라가는가?
---
## 7. 산출물 작성
- [ ] texts.md — 콘텐츠 텍스트만 (TF-IDF용)
- 구조 메타(노드 ID, 블릿 개수, 역할 설명) 넣지 않음
- 섹션별 그룹핑은 가독성 위해 OK
- 한자/괄호/장식 문자 제외
- [ ] flat.md — 모든 노드 좌표/크기/속성, 변형 축, sub-pattern
- "간략하게" 금지 — 실측 기록부에 간략은 없다
- 이상 탐지 결과 포함 (회전, 세로 텍스트, 중복)
- [ ] index.html — 위 체크 모두 통과한 HTML
---
## 8. 검증
- [ ] Selenium 스크린샷
- [ ] Figma 원본과 시각 비교
- [ ] texts.md의 모든 텍스트가 index.html에 존재
- [ ] flat.md의 모든 시각 요소가 index.html에 반영
- [ ] CSS 대체한 에셋의 assets/ 폴더에서 삭제 확인
---
## 9. 완료 후
- [ ] blocks_index.md에 1줄 추가 (STEP 10)
- [ ] 기존 패턴과 비교 — 2번째 등장이면 templates_staging 진행 여부 확인
---
## 수정 시 추가 체크 (기존 블록 수정할 때)
- [ ] 수정 전 현재 값 기록 (변경 전)
- [ ] 수정 후 변경한 값 기록 (변경 후)
- [ ] 되돌려야 할 때 어디로 돌아가는지 알아야 한다 (PROCESS-CONTROL 규칙3)
- [ ] A만 문제면 A만 수정 — B, C를 "같은 이유로 틀릴 것 같다"고 함께 바꾸지 않음
- [ ] 구조 변경이 불가피하면 사전에 영향 범위 분석 + 사용자 확인 후 진행
---
## 절대 하지 말 것 (매번 확인)
- [ ] PNG/SVG를 CSS로 안 바꾸고 img src로 넣기 [R9 위반]
- **단순 gradient bar, rectangle, circle, line은 기본적으로 CSS다.**
- **이미지 유지가 필요하면 "왜 CSS 불가인지"를 먼저 적고 진행한다.**
- [ ] 본문 텍스트를 absolute로 배치 [R17 위반]
- [ ] overflow:hidden으로 텍스트 숨기기 [R17 위반]
- [ ] transform:scale 사용 (zoom 사용) [R19 위반]
- [ ] `<ul><li>` 불릿 사용 (flex pair 사용) [R13 위반]
- [ ] gradient 값을 감으로 넣기 (gradient_math.py 사용)
- [ ] MCP 회전 bbox x좌표를 그대로 left에 넣기 [R2 위반]
- [ ] 규칙 파일 안 읽고 작업 시작