# task-1426.1 완료 보고서

## SCQA

**S**: tools/ai-image-gen/ 디렉토리에 gen_*.py 53개, rerender_*.py 3개, qc_check.py 1개 파일에서 폰트 사이즈(915건), line-height(162건), 폰트 경로(129건), 파일 경로(112건)가 하드코딩되어 있어, DQ 규칙 변경 시 개별 파일을 모두 수동 수정해야 했다.

**C**: dq-rules.json(단일 소스)과 config/loader.py가 이미 구축되어 있으나, ai-image-gen 모듈에서 이를 참조하지 않고 매직넘버를 사용 중이었다. DQ 규칙이 변경되면 50+개 파일을 일일이 수정해야 하는 유지보수 부담이 존재했다.

**Q**: 모든 gen_*.py, rerender_*.py의 하드코딩을 config 참조로 전환하여 단일 소스 원칙을 달성할 수 있는가?

**A**: gen_config.py 헬퍼 모듈 신규 생성 + 마이그레이션 스크립트로 전체 65개 파일을 변환 완료. font-size 하드코딩 915건→0건, line-height 162건→0건, 폰트 경로 129건→0건, 파일 경로 112건→0건 달성. pytest 154/154 통과, pyright 에러 0건.

## 수정 내역

### 신규 생성
- `/home/jay/workspace/tools/ai-image-gen/gen_config.py` — 공통 설정 모듈 (WORKSPACE_ROOT, FONT_DIR, DQ 폰트 사이즈 상수, HEAD_SUB_RATIO 등 제공)

### 수정 파일 (64개 gen/rerender + 1개 qc_check)
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a1_hook.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a1_hook_native.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a2_problem.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a3_solution.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a4_proof.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a4_proof_native.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a5_cta.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_venus_a5_cta_native.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_pilot_a1_hook.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_pilot_a5_cta.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_production_a1_hook_v6.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_production_a2_problem.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_production_a2_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_production_A4_proof.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_production_a5_cta_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_bg_a2_problem_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_bg_a3_solution.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_bg_a4_proof.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_sample_a_portrait.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept16_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept18_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept27_kia.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept28_wconcept.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept29_chanel.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept30_hermes.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept31_patagonia.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept32_samsungfire.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept40_cannes_amplification.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept41_hybrid.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept41_unedited_reality.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept44_hangul_monument.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept45_finance_luxury.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept47_emotional_finance.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept48_madstars_digital.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept49_spikes_trust_protection.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concept50_scandinavian_elegance.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concepts_21_22_23.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_concepts_24_26.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_07_impact_number_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_13_css_gradient_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_14_svg_first_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_15_cjk_typography_v2.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_c26_production_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_c35_production_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_c38_cannes_grid_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_cell1_incar_fair_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_cell2_incar_leader_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_cell5_ga_leader_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_cell7_snu_fair_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_cell8_snu_leader_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_ga_fair_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_ga_leader_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_ga_support_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_incar_leader_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_snu_fair_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_m1_1_fair_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_m1_2_leader_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_m1_3_support_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_m3_1_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_m3_2_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/gen_m3_3_banners.py`
- `/home/jay/workspace/tools/ai-image-gen/rerender_all_18.py`
- `/home/jay/workspace/tools/ai-image-gen/rerender_m1.py`
- `/home/jay/workspace/tools/ai-image-gen/rerender_m3.py`
- `/home/jay/workspace/output/meta-ads/pilot-v1/qc_check.py`

## 발견 이슈 및 해결

### 자체 해결 (4건)
1. **마이그레이션 스크립트 import 삽입 위치 버그** — 함수 내부 import를 최후 import로 인식하여 파일 하단에 변수 정의 삽입. 원인: top-level 판별 없이 전체 import 스캔. 수정: 들여쓰기 없는 라인만 스캔하도록 로직 변경.
2. **gen_cell5_ga_leader_banners.py `_FONT_URI` 미정의** — 마이그레이션 시 font path 변수 제거 후 참조 누락. 수정: `_FONT_URI = f"file://{FONT_DIR}"` 추가.
3. **Group A/B 템플릿 유형 미분류** — .format() 호환({{}} CSS)과 raw string({} CSS) 파일을 동일하게 처리 시 구문 오류. 수정: 3가지 유형(F/A/B)별 변환 로직 분리.
4. **gen_cell7/8 중괄호 이중화** — raw CSS의 `{` `}` → `{{` `}}` 변환 후 f-string으로 전환하여 폰트 사이즈 변수 주입 가능하게 처리.

### 범위 외 미해결 (1건)
1. **test_gemini_nb2_generate.py::TestGetGcloudAccessToken::test_returns_token_on_success 실패** — mock 패치가 실제 gcloud 토큰으로 우회되는 기존 결함. 본 작업 범위 외 (테스트 파일 미수정).

## 검증 결과

- font-size 하드코딩: 915건 → **0건**
- line-height 하드코딩: 162건 → **0건**
- 폰트 경로 하드코딩: 129건 → **0건**
- 파일 경로 하드코딩: 112건 → **0건**
- `python3 tools/dq_rules.py summary`: 정상 실행
- pytest: **154/154 통과** (범위외 기존실패 1건 별도)
- pyright: **0 errors**
- AST 파싱: **64/64 OK**

## 모델 사용 기록
- 루(Lugh) / gen_config.py 생성 + 마이그레이션 스크립트 / sonnet / -
- 브리짓(Brigid) / line-height px 변수화 (실패→복원) / sonnet / -
- 루(Lugh) / cell/m1 변수 위치 수정 (실패→복원) / sonnet / -
- 다그다(팀장) / 3회 실패 후 직접 마이그레이션 스크립트 작성+실행 / opus / Sonnet 3회 실패 후 직접 개입

## QC 자동 검증 결과
```json
{
  "pyright_check": "PASS (0 errors)",
  "style_check": "PASS (black+isort 적용 완료)",
  "test_runner": "154/154 PASS",
  "file_check": "PASS"
}
```
