Files
C.E.L_Slide_test2/docs/architecture/PHASE-Q-AUDIT.md

1369 lines
132 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.
# Phase Q Audit & Salvage
**작성일**: 2026-05-08 (frontend 통합 session 직후 첫 번째 audit axis)
**문서 역할**: Phase Z 보완 항목을 *기준 (lens)* 으로 기존 Phase Q 코드의 **Salvage Candidate / Reference Only / Archive Candidate** 분류 (§0-0 기준). audit 판정 = *후보 분류*, 적용 결정 ≠ §3 / §4 단계.
**진행 상태**: §1 Audit Lens 채움 — §2 모듈별 audit / §3 Salvage Plan / §4 우선순위 재정렬은 후속 turn 에서 채움.
---
## 0. 목적
Phase Z 가 fresh rewrite 처럼 진행되면서 Phase Q 의 기존 자산 (mdx_normalizer / section_parser / fit_verifier / slide_measurer / content_editor 등) 을 충분히 흡수하지 못한 부분을 정리한다.
이번 frontend 통합 session 에서 *frontend 가 임시로 채운 영역* (§7-B 표) 이 사실은 Phase Q 에 비슷한 코드가 있었을 가능성이 큼. **무엇을 새로 만들고 / 무엇을 가져오고 / 무엇을 참고만 하고 / 무엇을 archive 후보로 분류할지** 분류하는 것이 본 audit 의 목적 (적용 결정은 §3 / §4 단계).
진행 방식:
1. **§1 Audit Lens** — Phase Z 보완 항목 (§7-B 의 A/B/D 그룹) 별 *목적 / input / output / Phase Q 후보 파일* 정리. 이게 audit 의 기준.
2. **§2 모듈별 Audit** — Phase Q 모듈 10 개를 § 1 의 lens 로 검토. audit 판정 = Salvage Candidate / Reference Only / Archive Candidate (§0-0).
3. **§3 Salvage Plan** — §1 항목별 *어떤 Phase Q 자산을 어떤 방식으로 가져올지* 매핑.
4. **§4 우선순위 재정렬** — audit 결과로 [`PHASE-Z-ROADMAP.md`](PHASE-Z-ROADMAP.md) §5 / §7-B 우선순위 재조정.
> §7-B 의 **C 그룹 (Frontend 일관성 정리)** 은 Phase Q 와 무관하므로 본 audit 대상 외. 별도 axis 에서 처리.
> **중요: audit 판정 ≠ 적용 결정**.
> 본 문서의 Salvage Candidate / Reference Only / Archive Candidate 판정은 *후보 분류* 이며 즉시 통합 결정을 의미하지 않는다. 실제 적용 여부는 [§3 Salvage Plan](#3-salvage-plan) 과 [§4 우선순위 재정렬](#4-우선순위-재정렬) 에서 Phase Z 22-step 기준으로 다시 결정한다. §2.X audit 결과 = *후보 list*, *결정 list 아님*.
### 0-0. 자산 분류 기준 (Salvage / Reference Only / Archive)
| 분류 | 기준 | §3 단계 |
|---|---|---|
| **Salvage Candidate** | 결정론적 함수 + AI/Kei 무관 + Phase Z 22-step path 와 일관 | adapter / dual-write 전제로 §3 에서 재검토 가능 |
| **Reference Only** | 결정론적 함수 + Phase Z 와 직접 연결 시 dual path 위험 (예: 예측 vs 측정 / schema vs V4 / role/zone vs unit/zone) | 설계 참고만 가능. 직접 통합 X |
| **Archive Candidate** | AI/Kei 흐름 의존 (Kei 비중 / 역할 / 강조 판단 / 텍스트 압축 / reviewer prompt 전제) + Phase Z normal path 또는 AI 격리 contract 와 충돌 | 본 audit pass 에서 Salvage / Reference Only 후보 아님. *영구 폐기 확정 X*. 별도 axis 활성 시 새 기준으로 재검토 가능 |
> **AI 격리 invariant (Phase Z 본체 기준)**:
> Phase Z 에서 AI 는 정상 경로 (normal path) 가 아니라 *fallback / repair / restructure* (예: Step 12 light_edit/restructure) 에서만 사용한다.
>
> **단, 이 AI repair fallback 은 slot payload / 표현 / 분량을 *의미 보존* 하며 재정리하는 fallback step 이며, 꼭지 / 대목차 / 구조 / 강조 / bold / 차용 / 분량 예산 결정 흐름이 아니다.** 따라서 Phase Q 의 Kei persona / reviewer / prompt orchestration 자산 (꼭지 결정 / 구조 결정 / 강조 판단 / Kei 입력 기반 예산 산정 등) 은 *Phase Z 본체 도 AI repair fallback 도 salvage 대상이 아니다*. 이 자산들은 자동으로 **Archive Candidate** 로 분류된다. AI repair fallback 의 input / logic 은 Phase Q 자산과 *단절* — 별도 axis 에서 새 기준으로 설계한다.
>
> **별 axis nuance**: deterministic retry / visual check 보강 / frame preview 일관성 / catalog 확장 같은 *deterministic* 별 axis 는 정상. *Kei / AI revival* 을 implicit 하게 여는 별 axis framing 은 forbidden.
---
## 0-A. Phase Q Salvage 원칙 (lock)
Phase Z 는 본체이고, Phase Q 는 부품 창고 / 참고 자산이다. Phase Q 의 *전체 흐름* 을 Phase Z 위에 덮어쓰지 않는다. Phase Z 의 22-step 도면 / step artifact / V4 catalog / frame contract / visual check / status board 가 *기준 구조*. Phase Q 의 빈 부분만 부품 단위로 가져온다.
본 audit / salvage 의 모든 결정 (§1 lens / §2 module / §3 salvage / §4 reorder) 은 아래 10 원칙을 따른다.
1. **Phase Z 22-step 구조는 유지한다.**
2. **Phase Q 코드는 Step 단위 빈칸을 채울 때만 가져온다.**
3. **가져올 때는 adapter 를 둔다.**
4. **기존 Phase Z artifact schema 를 깨지 않는다.**
5. **모든 migration 은 one-axis 단위로 한다.**
6. **MDX03 regression 을 매번 확인한다.**
7. **HTML-heavy MDX 는 신규 케이스로 별도 확인한다.**
8. **Reference 판정된 코드는 직접 연결하지 않는다.**
9. **Salvage Candidate 적용 검토 시 dual-write / shadow 검증을 먼저 한다.**
10. **Reference 항목은 활성화 axis 가 없으면 나중에 Delete 후보로 재분류한다.**
> 꼬임 방지의 핵심 = **3 (adapter)** + **4 (artifact schema 보존)** + **9 (dual-write 검증)**. 나머지 7 개는 그 위의 안전장치.
---
## 0-B. Audit 범위 lock (2026-05-11)
**핵심 lock (3 lines):**
1. 이번 audit 은 Phase Z 22-step normal path 기준이다.
2. AI repair / restructure fallback 은 이번 audit 밖이다 (별도 axis 에서 새 기준으로 설계).
3. Phase Q 의 Kei persona / reviewer / prompt orchestration 흐름은 Phase Z normal path 뿐 아니라 AI repair fallback 의 salvage 대상도 아니다.
**포함 (이번 audit 평가 대상):**
- MDX 정규화
- section parsing
- visual measurement (브라우저 측정)
- deterministic layout / geometry / overflow handling
- frame contract / catalog 참고
- deterministic retry 계산 (glue / font compression / px redistribute)
**제외 (이번 audit 평가 외 — 별도 axis):**
- frame reject 이후 AI repair / restructure 구현
- Kei persona / reviewer / prompt orchestration
- AI 가 꼭지 / 대목차 / 구조 / 강조 / bold / 차용 여부를 판단하는 흐름
- AI 콘텐츠 생성용 글자수 예산 / AI 텍스트 압축 흐름
> 본 lock 은 §0-0 분류 기준 + AI 격리 invariant + §0-A 10 원칙 모두 따른다. 미끄러짐 차단의 *visual anchor*.
---
## 1. Audit Lens — Phase Z 보완 항목별 목적 / input / output
각 항목은 [`PHASE-Z-ROADMAP.md`](PHASE-Z-ROADMAP.md) §7-B 와 1:1 매핑.
| id | 보완 항목 | 목적 | input | output | Phase Q 후보 파일 | 우선순위 |
|---|---|---|---|---|---|---|
| **A-1** | Stage 0 normalize 통합 | HTML-heavy / 비정형 raw MDX 를 Phase Z canonical input 으로 변환 | raw MDX text | `{clean_text, title, images, popups, tables, sections}` (frontmatter / 코드블록 보호 / list/table HTML 변환 / AST 구조 추출) | `mdx_normalizer.py`, `section_parser.py` | 높음 |
| **A-2** | Catalog 확장 (frame_contracts + frame_partials) | V4 32 후보 중 backend 적용 가능한 frame 수 증가 (현재 3 → 32 목표) | `figma_to_html_agent/blocks/{frame_id}/` 의 index.html / assets / analysis.md | `templates/phase_z2/catalog/frame_contracts.yaml` entry + `templates/phase_z2/frames/{template_id}.html` partial | `block_reference.py`, `block_selector.py` (간접 — catalog 로딩 / block 검색 패턴 reference; A-2 main = frame_contracts.yaml + frame_partials 신규 구축, Phase Q catalog schema ≠ Phase Z) | 높음 |
| **A-3** | Frame preview png 일관성 | 모든 catalog frame 의 일관된 preview.png 자동 생성 (현재 figma_previews 우회) | frame partial HTML + assets | `figma_to_html_agent/blocks/{frame_id}/preview.png` | `slide_measurer.capture_slide_screenshot` (main), `renderer.py` (간접 — render-path 자료) | 중 |
| **A-4** | slide-base.html iframe-friendly mode | iframe embed 시 body padding / centering / min-height 미적용 (frontend CSS injection 제거) | slide-base.html template + query string `?embedded=1` 같은 시그널 | conditional CSS (standalone vs embedded) | `renderer.py` (legacy `slide-base.html` 호출 지점 보유, embedded/standalone CSS 분기 미구현) | 중 |
| **A-5** | V4 후보 자동 fallback | rank-1 capacity / cardinality / structure mismatch 시 자동 rank-2/3 시도 | V4 후보 list + 각 frame contract 의 cardinality + 추출된 content items | 통과한 frame template_id (모두 fail 시 filtered_capacity) | `fit_verifier.py` | 높음 |
| **A-6** | Zone DOM 좌표 export | backend 가 zone 절대 px 좌표를 step08 / 별도 step 에 export (frontend 측정 우회) | layout_css + slide-base 좌표 | `zone_geometries_px: [{position, x, y, w, h}]` | `slide_measurer.py` | 중 |
| **B-1** | Zone-section assignment override | 사용자 drag drop 결과를 backend 가 받아 composition planner 의 자동 결정 강제 변경 | `--override-section-assignment ZONE_ID=section_id,section_id` (CLI multi) | units 배치가 사용자 매핑 따름 | `pipeline.py` (간접 — orchestration entry, Stage Y page_structure 생성 흐름 보유) | 중 |
| **B-2** | Edited HTML → MDX 역변환 | frontend 편집 모드의 텍스트 변경이 새 final.html 에 반영 | edited HTML (iframe contentDocument outerHTML) | 새 MDX text 또는 patched mapper input | 글벗 `fmt_slide.py html_to_slide_mdx` | 중 |
| **B-3** | Sub-section (### 단위) drag drop backend 처리 | backend 가 sub-section id 를 인식해서 zone 에 sub-section 단위로 매핑 | sub-section id (e.g., "03-1-sub-2") + zone_id | 그 sub-content 단위로 unit 분할 | `section_parser.py` | 낮 |
| **B-4** | 다른 layout 의 zone-geometry override 확장 | top-1-bottom-2 / top-2-bottom-1 / left-1-right-2 / left-2-right-1 / grid-2x2 도 사용자 ratio override 적용 (현재 horizontal-2 / vertical-2 만) | `--override-zone-geometry` 인자 + 새 layout_preset 분기 | build_layout_css 의 grid 표현 (areas / cols / rows) | `space_allocator.py` | 낮 |
| **D-1** | filtered_section_reasons 노출 UI | 사용자가 어떤 섹션이 왜 빠졌는지 즉시 인지 (Step 8 coverage UI) | `step20_slide_status.json.data.filtered_section_reasons` | frontend header / 패널 UI | N/A (frontend 만) — Phase Q audit 외 | 중 |
| **D-2** | Zone resize 시 frame min_height 한계 표시 | pendingLayout 모드 resize 시 frame 한계 인지 + visual hint | frame_contracts.yaml `min_height_px` → step09 trace | frontend resize limit + 한계 도달 시 붉은 outline | `fit_verifier.py` (간접 참고) | 낮 |
| **D-3** | 데모 / 업로드 흐름 시각 차별 | 자동 mdx03 vs 사용자 직접 업로드 구분 표시 | uploadedFile state 의 origin (auto-loaded vs user) | 헤더 / 좌측 패널 표시 | N/A (frontend 만) | 낮 |
| **D-4** | Step 20 status badge 의미 안내 | PASS / RENDERED_WITH_VISUAL_REGRESSION / PARTIAL_COVERAGE 의 사용자 친화 설명 | runMeta.status | tooltip / popup | N/A (frontend 만) | 낮 |
**우선순위 분포**:
- **높음** (4): A-1, A-2, A-5 + (보고 후 결정)
- **중** (6): A-3, A-4, A-6, B-1, B-2, D-1
- **낮** (4): B-3, B-4, D-2, D-3, D-4
**§2 audit 대상이 되는 Phase Q 후보 파일** (위 표에서 추출, 중복 제거):
1. `mdx_normalizer.py` (A-1)
2. `section_parser.py` (A-1, B-3)
3. `slide_measurer.py` (A-6)
4. `fit_verifier.py` (A-5, D-2 간접)
5. `space_allocator.py` (B-4)
6. `content_editor.py`
7. `content_verifier.py` (검증 — B-2 후속)
8. `renderer.py` (A-3, A-4)
9. `html_generator.py` (A-3, A-4)
10. `block_reference.py` / `block_selector.py` (A-2)
11. (마지막) `pipeline.py` / `pipeline_context.py` (orchestration 큼 — 처음부터 보면 피곤. 1~10 보고 마지막에)
---
## 2. Phase Q 모듈별 Audit
> 후속 turn 에서 1 모듈씩 채움. 형식 :
>
> ```
> ### 2.X {파일명}
> - **역할** : ...
> - **관련 §7-B 항목** : ...
> - **현재 Phase Z 와 겹치는 영역** : ...
> - **재사용 가능성** : ...
> - **분류** : Salvage Candidate / Reference Only / Archive Candidate (§0-0 기준)
> - **후속 작업** : ...
> ```
### 2.1 `mdx_normalizer.py`
#### 역할
Stage 0 — raw MDX 를 4 Layer 파서로 정규화하여 `{clean_text, title, images, popups, tables, sections}` 반환. `normalize_mdx_content(raw_mdx) -> dict` 단일 entry. 동반 `validate_stage0(result, raw_mdx) -> list[errors]` 검증 함수.
| Layer | 역할 | 핵심 처리 |
|---|---|---|
| L1 | frontmatter 분리 | `python-frontmatter` 로 YAML metadata + title 추출 |
| L2 | 코드블록 보호 + MDX 전용 패턴 처리 | (1) backtick 10→3 순서로 fenced code 보호 + inline code 보호 (placeholder 치환) → 후처리 후 복원. (2) `<details><summary>` → popups 추출 + 마커 (`[팝업: 제목]`). (3) `:::note[...]` directive → `[핵심요약: ...]` 또는 `## 승격`. (4) **markdown list (`* / - `) → HTML `<ul><li>` 변환** (`_convert_md_list_to_html`, 들여쓰기 2~4 칸 감지로 중첩 처리). (5) **markdown table (`\| col \|`) → HTML `<table>` 변환** (`_convert_md_table_to_html` + `_render_md_table`, 셀 내 `<br/>` 보존). (6) `import` / `export` 문 제거, `<br/>` 제거, JSX `<div style={{...}}>` 태그 제거, 커스텀 컴포넌트 `<Component />` 제거. (7) 헤딩 번호 정규화 (`## N.``## `, `### N.N``### `). (8) 도입부 `* **제목**``## 승격`. (9) 이탤릭 출처 → `출처: ...`. |
| L3 | AST 파싱 (markdown-it-py) | `js-default` preset (table 기본 포함). (1) `image` 토큰 → `images: [{alt, path}]`. (2) `table_open` 토큰 → `tables: [{headers, rows}]`. (3) `heading_open h2/h3``sections: [{level, title, content}]` (level 2 + level 3 평행 list, bullet_depth 추적해서 content 에 `D1: / D2: / D3:` prefix). |
| L4 | 텍스트 정리 | `![alt](path)``[이미지: alt]` 마커. 남은 HTML 태그 제거. 연속 빈 줄 정리. |
검증 (`validate_stage0`):
- `clean_text` 비어있음 = FATAL
- 원본 대비 텍스트 보존율 < 30% = FATAL
- 이미지 수 / popup 수 대조 = ADJUSTABLE
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **A-1** Stage 0 normalize 통합 | **직접** | 본 모듈은 A-1 보완 후보 중 하나 (§3 검토 대상). frontend 의 `## __ROOT__` prefix 임시 우회 제거 가능 |
| A-3 Frame preview 일관성 | 간접 | popups / images 가 normalized 에 있으니 backend visual_check 가 활용 가능 (현재 Phase Z 는 popup 처리 없음) |
| B-3 Sub-section drag drop | 간접 | L3 가 level 2 + level 3 sections 둘 다 평행 list 로 추출 — Phase Z 의 sub_sections 와 schema 다르지만 변환 어댑터로 매핑 가능 |
| D-1 filtered_section_reasons UI | 간접 | `validate_stage0` 의 검증 패턴 (FATAL / ADJUSTABLE) 이 Phase Z 의 status board 와 일관 정리 가능 |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q | Phase Z | 비교 |
|---|---|---|
| `mdx_normalizer.normalize_mdx_content` | `phase_z2_pipeline.parse_mdx` (line 157) | Phase Z = 단순 `^##\s+\d+\.\s+` 정규식으로 ## 단위 sections 분리 + raw_content 통째 보존. *HTML / list / table 변환 / popup 추출 / image 추출 모두 없음*. mdx_normalizer 가 압도적으로 풍부 |
| `mdx_normalizer.normalize_mdx_content` | `phase_z2_content_extractor.extract_content_objects` | Phase Z = section.raw_content → 1~2 ContentObject (text_block 또는 transform_table). v0 minimal 명시. mdx_normalizer 가 이미 list/table HTML 분해 + AST tables 추출 결과를 가짐 → Phase Z 의 extract_content_objects 가 그것을 받으면 v0 한계 (1 ContentObject 로 뭉침) 자연 해소 |
| `validate_stage0` | (Phase Z 미존재) | Phase Z 의 step02 / step03 에 검증 단계 없음. 문제 발견이 Step 14 visual_check 까지 가서야 잡힘. mdx_normalizer 의 검증 패턴이 step02 검증으로 통합 가능 |
#### 재사용 가능성
**매우 높음**. `normalize_mdx_content()` 는 self-contained (외부 의존 = `frontmatter`, `markdown-it-py` 만 — 둘 다 표준 lib). 호출 site 만 바꾸면 됨. 단 schema 변환 어댑터 필요:
- mdx_normalizer 의 `sections = [{level: 2|3, title, content}]` (평행 list)
- Phase Z 의 `MdxSection = (section_id, section_num, title, raw_content)` (level 2 만, sub 없음)
- 어댑터: level 2 = root MdxSection / level 3 = 그 root 의 sub_sections (parent 가 가장 가까운 level 2). frontend 의 `parseMdxText` 와 동일한 hierarchy 로직.
추가 lift (Phase Z 에 새로 들어오는 정보):
- `popups: [{title, content}]` — 현재 Phase Z 는 popup 처리 없음. Step 17 details_popup_escalation 의 진짜 input
- `images: [{alt, path}]` — Phase Z 의 missing image count 검증 강화
- `tables: [{headers, rows}]` — Step 3 의 transform_table 추출이 정확해짐
- L4 `clean_text` — Step 14 visual_check 의 텍스트 보존율 검증 input
#### audit 판정
**Salvage Candidate** (전체 `normalize_mdx_content` + 4 Layer 흐름).
근거 (후보 판정 근거 — *적용 결정 아님*):
1. Phase Z 의 `parse_mdx` 가 단순 — A-1 빈칸 영역
2. mdx_normalizer 가 *self-contained + AI/Kei 무관* (frontmatter + markdown-it + regex). §0-0 의 Salvage Candidate 기준 충족
3. schema 어댑터를 둘 수 있으면 §0-A 원칙 3 (adapter) + 원칙 4 (artifact schema 보존) 안에서 검토 가능
4. popups / images / tables 추출은 Phase Z step03 보강의 *참고 input* — 단 통합 효과는 dual-write 검증 후 확인
#### 후속 참고 사항 (§3 Salvage Plan 에서 적용 여부 결정)
본 항목들은 §3 Salvage Plan 에서 *재검토* 한 뒤 §4 우선순위 재정렬 에서 적용 axis 가 정해진 경우에만 진행. 지금은 *참고 list*.
B1. **import 검토**`phase_z2_pipeline.py``from mdx_normalizer import normalize_mdx_content, validate_stage0` 가능성
B2. **schema 어댑터 검토**`_adapt_normalized_to_mdx_sections(normalized) -> list[MdxSection]`. level 2 = root, level 3 = sub_sections. MdxSection 에 `sub_sections: list[MdxSection]` 필드 추가 검토
B3. **`parse_mdx` 호출 site 검토** — 단순 정규식 path 대체 가능성
B4. **step02 artifact 확장 검토**`popups`, `images`, `tables`, `clean_text` trace 추가 가능성 + `validate_stage0` 결과 step02 errors 기록 검토
B5. **Frontend `## __ROOT__` 우회 제거 검토** — backend section.raw_content 가 정리된 상태로 들어오면 frontend `parseMdxText` 의 prefix hack 제거 가능
B6. **Step 3 `extract_content_objects` 보강 검토** — normalized 의 `tables` / `images` 를 ContentObject 로 변환. bullet_list_open/close + depth 정보 활용 N items 분할 — 03-1 같은 case 의 *가능성*. **별 axis**
B7. **A-1 임시 우회 제거 + memory `project_phase_z_normalize_gap.md` 업데이트** — §3 결정 후
B8. **검증 — dual-write 기준** (§0-A 원칙 9): MDX 03 fresh run regression check + HTML-heavy 03 case. step02 의 sections / sub_sections title / level 비교
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- step02 sections / sub_sections 의 title / level 이 baseline 과 동일 (또는 어댑터 변환 후 schema-equivalent)
- step20 overall status 가 baseline 과 동일 (regression 없음)
- popup / image / table 추출 결과의 미시 변경은 audit trace 로 기록
> ⚠ **본 audit 판정은 후보 판정이며 즉시 통합 결정 아님**. Phase Z 22-step 구조와 artifact schema 를 깨지 않는 경우에만 §3 Salvage Plan 단계에서 적용 여부 재검토. §0-A 의 10 원칙 + §0-0 의 분류 기준 + AI 격리 invariant 모두 따름.
### 2.2 `section_parser.py`
#### 역할
Phase Y — `mdx_normalizer.normalize_mdx_content` 출력을 받아 *대목차 (## level 2) 단위 + sub_titles 그룹 + group_schema 분류 + sub_types 점수 + recipe 매핑* 까지 진행하는 후속 layer. mdx_normalizer 와 **chained 구조** (mdx_normalizer 가 producer, section_parser 가 consumer + classifier).
| 함수 | 역할 |
|---|---|
| `extract_major_sections(normalized_sections)` | level=2 (빈 content) = 대목차 헤더, level=2 (content 있음) = 소목차, level=3 = 소목차로 묶어서 `[{title, content, sub_titles}]` 반환. 즉 *Phase Z 의 sub_sections 와 동일한 hierarchy 정보를 이미 만듦* |
| `detect_component_popups(raw_content, base_path)` | Y-14 — Astro 컴포넌트 (`import X from 'components/...'` + `<X />`) 자동 감지 → popup 등록 |
| `_classify_sub_types(sub_titles, content, ...)` | B-1 — 각 sub_title 의 *콘텐츠 유형* 점수 산정 : `parallel_card_candidate / text_list_candidate / visual_detail_candidate / table_heavy_candidate`. D1/D2 패턴 밀도 + content 길이 + table 존재 + popup 매칭 등으로 점수 |
| `classify_group_relations(major_sections)` | Y-13b — 대목차의 sub_titles 간 관계로 `group_schema` 부여 : `parallel_cluster` (3 sub) / `compare_paired` / `compare_asymmetric_paired` / `sequence_list` / `sequence_plus_visual` / `single_block` (1 sub) / `card_cluster_N` (4+) + `_plus_visual` suffix |
| `SCHEMA_RECIPE_MAP` / `get_recipe_for_schema` | schema → recipe 매핑. recipe = `{recipe (layout 종류), block_kind, blocks (후보 list), [left_kind/right_kind/ratio]}` |
| `KIND_SUBTYPE_COMPAT` / `check_kind_compatibility` | recipe_kind 가 실제 sub_type 과 호환되는지 검증 |
| `map_topics_to_sections(topics, sections)` | Kei 꼭지 → 대목차 매핑. score 기반 (title 매칭 / sub_title 매칭 / source_hint 매칭) |
| `extract_conclusion_text(raw_content)` | `:::note[핵심 요약]` 추출 |
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **B-3** Sub-section drag drop backend 처리 | **직접** | `extract_major_sections` 가 이미 sub_titles 그룹화 결과를 만듦. backend 가 sub-section id 를 인식하려면 이 layer 가 첫 후보. Phase Z `MdxSection` 에 sub_titles + sub_sections 로 통합 |
| **A-1** Stage 0 normalize 통합 | **직접** (mdx_normalizer 와 chained) | mdx_normalizer 의 출력을 *consume 하는 layer* — A-1 통합 시 둘이 같이 와야 함. 따로 통합하면 schema 가 또 꼬임 (사용자 지적 그대로) |
| (별 axis 잠재) **Phase Q schema/recipe path** | 잠재 추가 layer | Phase Z 는 V4 매칭만으로 frame 결정. section_parser 는 *content 구조 기반* schema → recipe → blocks 결정 path. 두 path 가 orthogonal. 결합 시 robust 할 수 있음 (V4 점수 + schema 호환 점수) |
| (별 axis 잠재) **A-2 Catalog 확장** | 간접 | `SCHEMA_RECIPE_MAP` 의 blocks 후보 list (`prerequisites-3col / card-icon-desc / compare-detail-gradient / process-product-2col / ...`) 가 Phase Q 의 frame 카탈로그 식별자 — Phase Z catalog 확장 시 reference |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q | Phase Z | 비교 |
|---|---|---|
| `extract_major_sections` | (없음 — Phase Z 의 `parse_mdx` 가 단순 ## 단위 분리) | Phase Z 가 sub_titles 그룹화를 *통째로 빠뜨림*. frontend 의 `parseMdxText` 가 임시로 채운 부분이 사실 여기 |
| `classify_group_relations` (Y-13b) + sub_types | `align_sections_to_v4_granularity` (Phase Z) | 둘 다 section 의 *구조 분류* 시도. Phase Z = V4 evidence 의 granularity hint 만 사용. Phase Q = content 분석 기반 schema 자체 결정. **orthogonal path** |
| `SCHEMA_RECIPE_MAP` | `LAYOUT_PRESETS` (Phase Z `phase_z2_composition`) | Phase Z = 8 preset (single / horizontal-2 / vertical-2 / ...) 의 *zone 위상*만. Phase Q = schema → recipe → blocks 까지 결정. Phase Q 가 한 단계 더 깊음 |
| `_classify_sub_types` (B-1) | (없음 — Phase Z 의 step03 `extract_content_objects` 가 v0 minimal) | Phase Z step03 v0 minimal 보완 시 참고 후보 (§3 검토 대상). sub_type 점수가 그대로 ContentObject role 로 매핑 가능 |
| `detect_component_popups` (Y-14) | mdx_normalizer 의 popups | 중복 — mdx_normalizer 가 `<details>` 처리. Y-14 는 Astro `<X />` 처리 (별도 path). 둘이 union 으로 동작 |
| `map_topics_to_sections` | (없음 — Phase Z 는 V4 매칭) | Archive — Kei persona 꼭지/대목차 매핑 결정 흐름. Phase Z 본체도 AI repair fallback 도 salvage 대상 아님 |
#### 재사용 가능성
**chained 통합 필수 — `mdx_normalizer + section_parser` 둘이 한 axis**.
분류:
| 함수 | 분류 | 근거 |
|---|---|---|
| `extract_major_sections` | **Salvage Candidate** | 결정론적 + AI/Kei 무관 (normalized.sections 단순 grouping). mdx_normalizer 와 chained 검토 후보 |
| `extract_conclusion_text` | **Salvage Candidate** | 작은 utility. `:::note` 추출 결정론적 |
| `classify_group_relations` (Y-13b) | **Reference Only** | 결정론적. 단 Phase Q content 분석 기반 schema 결정 = Phase Z V4 path 와 *대체 path*. dual path 위험 — 직접 연결 X (§0-A 원칙 8) |
| `_classify_sub_types` (B-1) | **Reference Only** | 같은 이유 — Phase Z V4 + frame contract path 와 *대체*. 설계 참고만 |
| `SCHEMA_RECIPE_MAP` / `KIND_SUBTYPE_COMPAT` | **Reference Only** | Phase Q 의 frame 카탈로그 mapping. Phase Z catalog 와 다른 path |
| `detect_component_popups` (Y-14) | **Archive Candidate** | Astro 컴포넌트 (`<X />`) 감지. Phase Z 표준 input 영역 외. mdx_normalizer 의 popups path 와 별. Phase Z 본체 salvage 대상 외 |
| `map_topics_to_sections` | **Archive Candidate** | **Kei 꼭지 → 대목차 매핑** = Kei AI 입력 의존. §0-0 의 Archive 기준 (Kei 흐름) + AI 격리 invariant 따라 Archive |
#### audit 판정
**Mixed (Salvage Candidate + Reference Only + Archive Candidate)**.
- **Salvage Candidate**: `extract_major_sections`, `extract_conclusion_text`
- **Reference Only**: `classify_group_relations`, `_classify_sub_types`, `SCHEMA_RECIPE_MAP`, `KIND_SUBTYPE_COMPAT`
- **Archive Candidate**: `detect_component_popups`, `map_topics_to_sections`
**핵심 통찰** (mdx_normalizer 와 chained): mdx_normalizer 와 section_parser 의 *Salvage Candidate 두 자산* (`extract_major_sections` + `extract_conclusion_text`) 은 chained 흐름이라 §3 Salvage Plan 에서 *같이* 검토. 따로 검토하면 schema 충돌 위험.
#### 후속 참고 사항 (§3 Salvage Plan 에서 적용 여부 결정)
본 항목들은 후보 참고 사항. §3 Salvage Plan 에서 재검토 후 §4 우선순위 재정렬 에서 적용 axis 가 정해진 경우에만 진행.
C1. **mdx_normalizer + section_parser chained 검토** — Phase Z `parse_mdx` 를 normalize_mdx_content + extract_major_sections + extract_conclusion_text 의 chained 흐름으로 재구성 *가능성*. 어댑터 작성 가능성 (§0-A 원칙 3).
C2. **`MdxSection` schema 확장 검토** — `sub_sections: list[MdxSection]` + `sub_titles: list[str]` 필드 추가 가능성. *Reference Only 항목 (group_schema / sub_types) 의 schema 자리 추가 검토* — 단 활성 X (별 axis 활성 시).
C3. **step02 artifact 확장 검토**`popups`, `images`, `tables`, `clean_text`, `major_sections` trace 추가 가능성 (§0-A 원칙 4: 기존 schema 깨지 않음).
C4. **Frontend `## __ROOT__` 우회 제거 검토** + `loadRun` 의 sub_sections 매핑.
C5. **B-3 sub-section drag drop backend 처리 검토** — V4 sub-section 단위 평가도 필요. **별 axis**.
C6. (제거) — schema/recipe path 는 Reference Only 이며 별 axis 활성 결정 자체가 별 검토. 현재 audit 단계에서 검토 대상 외.
C7. **검증 — dual-write 기준** (§0-A 원칙 9): MDX 03 fresh run regression + HTML-heavy 03 case. step02 의 sub_sections / sub_titles 가 frontend 의 임시 우회 결과와 schema-equivalent.
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- mdx_normalizer + extract_major_sections chained 결과의 sections / sub_sections title / level 이 baseline 과 동일
- footer (extract_conclusion_text) 결과가 baseline 과 동일
- step20 overall status PASS 유지
> ⚠ **본 audit 판정은 후보 판정이며 즉시 통합 결정 아님**. Phase Z 22-step 구조와 artifact schema 를 깨지 않는 경우에만 §3 Salvage Plan 단계에서 적용 여부 재검토. §0-A 의 10 원칙 + §0-0 의 분류 기준 + AI 격리 invariant 모두 따름. **Archive Candidate 자산 (`detect_component_popups`, `map_topics_to_sections`) 은 §3 검토 대상 외 — Phase Z 본체 salvage 대상이 아님**.
### 2.3 `slide_measurer.py`
#### 역할
Phase L — Selenium headless Chrome 으로 HTML 렌더 후 각 `.slide` / `[class*="area-"]` / `[class*="zone-"]` / `[class*="container-"]` / `[class*="block-"]`*실제 px 높이* 측정 (LLM 추정 X, 브라우저 엔진 측정 — 결정론적). 4 개 함수 + 1 measurement script.
| 함수 / 자산 | 역할 |
|---|---|
| `_MEASURE_SCRIPT` (JavaScript) | `.slide` 와 zone (area-/zone-) / container (container-) / block (block-) selector 를 enumerate 해서 `{scrollHeight, clientHeight, overflowed, excess_px}` 측정. *정점 — 핵심 자산* |
| `measure_rendered_heights(html)` | HTML → tempfile 저장 → file:// URI 로 Chrome 로드 → `_MEASURE_SCRIPT` execute_script → 결과 dict 반환. viewport = `settings.slide_width × (slide_height + 200)`. 폰트 로딩 대기 (`document.fonts.ready`) |
| `format_measurement_for_kei(measurement, allocation)` | Kei 검수 전달용 텍스트 포맷 (zone / block 별 px + overflow + zone 내 비중 %) |
| `measure_candidate_block(html)` (Phase P) | 단일 후보 블록 렌더 + 측정 + base64 PNG 스크린샷. `.candidate-container` selector |
| `capture_slide_screenshot(html)` (Phase N-4) | 슬라이드 전체 스크린샷 base64 PNG. `.slide` selector 의 `screenshot_as_base64` |
| `_log_measurement(result)` | 측정 결과 logger.info 출력 |
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **A-6** Zone DOM 좌표 export | **직접** | `_MEASURE_SCRIPT` 의 JS 에 `getBoundingClientRect()` 추가하면 zone bbox 도 측정 가능. backend step08 또는 step14 artifact 에 `zone_geometries_px: [{position, x, y, w, h}]` export → frontend 의 iframe boundingClientRect 측정 우회 (현재 SlideCanvas onLoad 측정 path) 폐기 가능 |
| (A-6 인접) Step 14 visual_check 보강 | 간접 | Phase Z 의 visual_check 가 *zone overflow* 만 검사 (현재 코드). slide_measurer 의 block / container 단위 측정이 더 풍부 — visual_check 에 차용 시 정밀 검출 가능 (`block` 단위 overflow 까지) |
| **A-3** frame preview 일관성 | 간접 | `capture_slide_screenshot` / `measure_candidate_block``screenshot_as_base64` path 가 frame 별 preview.png 자동 생성에 직접 활용 가능. `figma_to_html_agent/blocks/{frame_id}/preview.png` 일관 생성 path |
| (별 axis 잠재) Phase P 다후보 비교 path | 잠재 | `measure_candidate_block` 이 Phase P 다후보 비교 시기의 산물. ROADMAP 에 Phase P 폐기 기록 — 본 함수는 향후 다후보 비교 axis 재활성 시 Reference |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `slide_measurer` | Phase Z `phase_z2_pipeline` | 비교 |
|---|---|---|
| `measure_rendered_heights` (selenium + JS measure) | Step 14 `visual_check` 단계 (selenium 사용 — phase_z2_pipeline.py line 720~ 부근의 Chrome options 흔적) | **두 path 모두 selenium 호출** — 같은 일 병렬 존재. 명확한 dual path |
| `_MEASURE_SCRIPT` 의 zone/block 측정 | Phase Z visual_check 의 zone overflow 측정 | Phase Q = block / container 단위까지 측정 (더 풍부). Phase Z = zone 단위 overflow + clipping 정도 (현재 visual_check 의 명시적 출력) |
| `capture_slide_screenshot` | Phase Z 의 preview.png 생성 흔적 | Phase Z 가 preview.png 를 어떻게 만드는지 이번 audit 에서 명시 확인 안 됨 — slide_measurer 의 screenshot path 가 더 명시적. dual path 가능성 |
| `measure_candidate_block` (Phase P) | (Phase Z 미존재 — Phase P 다후보 폐기) | Reference 만 |
| viewport 크기 — `settings.slide_width × (slide_height + 200)` | Phase Z 도 비슷 (`SLIDE_W = 1280`, `SLIDE_H = 720`) | 일관 |
→ slide_measurer 는 *Phase L 의 더 정밀한 측정 layer*. Phase Z visual_check 가 그 일부를 자체 구현했지만, 더 자세한 측정 (block / container) + 스크린샷 path 는 Phase Q 가 풍부.
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `_MEASURE_SCRIPT` (JS) — `getBoundingClientRect()` 추가 검토 | **Salvage Candidate** | 결정론적 + AI 무관. Phase Z visual_check JS 보강 검토 후보 (A-6) |
| `measure_rendered_heights` (전체 함수) | **Reference Only** | Phase Z visual_check 가 이미 selenium 호출. 통째 통합 시 dual path 위험 (§0-A 원칙 8). JS 만 검토 |
| `capture_slide_screenshot` | **Salvage Candidate** | 결정론적 + AI 무관. A-3 frame preview 일관성 검토 후보 (별 axis 활성 시) |
| `measure_candidate_block` (Phase P) | **Archive Candidate** | Phase P 다후보 비교 path 폐기 (ROADMAP). 현재 Phase Z 와 무관 |
| `format_measurement_for_kei` | **Archive Candidate** | **Kei 전용 텍스트 포맷** — Kei 흐름 의존. AI 격리 invariant 따라 Archive |
| `_log_measurement` | **Reference Only** | log 패턴 utility |
#### audit 판정
**Mixed (Salvage Candidate + Reference Only + Archive Candidate)**.
- **Salvage Candidate**: `_MEASURE_SCRIPT` JS extension (A-6 검토 후보), `capture_slide_screenshot` (A-3 검토 후보)
- **Reference Only**: `measure_rendered_heights`, `_log_measurement`
- **Archive Candidate**: `measure_candidate_block`, `format_measurement_for_kei`
핵심 통찰:
1. Phase Z visual_check 가 *이미 selenium 호출 path*. slide_measurer 통째 통합 시 dual path (§0-A 원칙 8 위반). 통째 통합 X.
2. `_MEASURE_SCRIPT` 의 JS 만 *부분 참고 후보*`getBoundingClientRect` 추가로 zone bbox export 가능성. A-6 검토 시 §3 Salvage Plan 에서.
3. `capture_slide_screenshot` 은 별 axis (A-3 frame preview 일관성) 활성 시 §3 검토 대상.
4. `measure_candidate_block` (Phase P 폐기) + `format_measurement_for_kei` (Kei 흐름) = **Archive Candidate**.
§0-A 원칙 9 (dual-write 검증) 적용 — *§3 Salvage Plan 에서 적용 검토 시*:
- A-6 검토 시 frontend iframe `boundingClientRect` 측정 path 와 backend export path 결과 비교 → MDX 03 의 zone bbox 가 ± 0.005 normalized (±1~2 px) 일치 확인 후 frontend path 정리 가능성
#### 후속 참고 사항 (§3 Salvage Plan 에서 적용 여부 결정)
D1. **Phase Z visual_check 위치 확인 + slide_measurer 비교 sub-audit** — phase_z2_pipeline.py 의 selenium 호출 path 와 slide_measurer 의 함수 비교. Phase Z 본체 path 가 master 라는 가설 검증.
D2. **A-6 검토 후보 — JS extension** (§3 결정 후) :
- Phase Z visual_check `_MEASURE_SCRIPT``getBoundingClientRect` 추가 검토 (zone / `.slide-body` bbox 측정)
- step14 (또는 별 step) artifact 에 `zone_geometries_px` + `slide_body_bbox_px` 추가 검토 (§0-A 원칙 4: 새 필드만)
D3. **frontend SlideCanvas 의 iframe 측정 우회 정리 검토** :
- D2 의 backend export 와 frontend 측정 dual-write 검증 후 정리 가능성
- SlideCanvas 의 `measuredZones` / `measuredSlideBody` state 정리 검토
D4. **A-3 frame preview 일관성 검토** (별 axis) :
- `capture_slide_screenshot` Salvage Candidate. Phase Z 가 frame partial 단독 렌더 + 캡처 path 추가 검토
- frontend `/frame-preview/{frame_number}` endpoint 의 figma_previews fallback 대체 검토
D5. (제거) — block / container 측정 보강은 Reference Only 영역. 별 axis 활성 결정 자체가 별 검토.
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- D2 검토 시 (A-6) : MDX 03 의 backend export `zone_geometries_px` 가 frontend `measuredZones` 와 ± 0.005 normalized (1~2 px) 일치
- iframe `.slide-body` bbox 와 backend `slide_body_bbox_px` 도 ± 0.005 일치
- Step 20 overall status PASS 유지
> ⚠ **본 audit 판정은 후보 판정이며 즉시 통합 결정 아님**. §3 Salvage Plan 단계에서 적용 여부 재검토. §0-A 의 10 원칙 + §0-0 의 분류 기준 + AI 격리 invariant 모두 따름. **Archive Candidate 자산 (`measure_candidate_block`, `format_measurement_for_kei`) 은 §3 검토 대상 외**.
### 2.4 `fit_verifier.py`
#### 역할
Phase V (Stage 1.8) — *꼭지별 블록 선택 후* 각 컨테이너에 콘텐츠가 실제로 들어가는지 **예측 기반 (pre-render calculation)** 검증. 안 들어가면 재배분 → Kei 에스컬레이션. 1048 줄, 모듈로서는 큰 편.
| 분류 | 함수 / 자산 | 역할 |
|---|---|---|
| **token / measure** | `_load_design_tokens` | tokens.css 의 spacing 변수 cache |
| | `estimate_text_height(chars, font_size, width, line_h)` | 폰트 메트릭 (`CHAR_WIDTH_RATIO=0.947`) 으로 텍스트 높이 px 예측 |
| | `estimate_block_overhead(block_id, catalog_entry, item_count)` | catalog 의 `padding_overhead_px` + 카드형 per-item 오버헤드 |
| | `estimate_image_height(source_data, width, image_sizes)` | 이미지 비례 / 시각화 catalog `min_height_px` 기반 |
| | `estimate_keymsg_height(message, font_size)` | key-msg 배너 높이 |
| | `count_items_in_topic` + `_count_items_from_source` | source_data 패턴으로 항목 수 추정 (괄호+쉼표 / 불릿 / 쉼표) |
| | `get_actual_text_chars(topic, normalized, role)` | structured_text 우선, fallback source_data + popup 링크 추가 |
| **data** | `TopicFit`, `RoleFit`, `FitAnalysis` | 꼭지 / 역할 / 전체 fit 분석 결과 |
| **V-2 fit** | `calculate_fit(topics, page_structure, containers, references, font_hierarchy, normalized, core_message)` | 메인 — 꼭지별 required height + role 별 OK / TIGHT / OVERFLOW 판정 |
| **V-3 redistribute** | `ROLE_ZONE_MAP`, `redistribute(analysis, containers, min_margin_px)` | 같은 zone 내 deficit / surplus role 사이 px 재배분 + `can_redistribute` / `needs_escalation` |
| | `build_escalation_report` | Kei 에스컬레이션 텍스트 |
| **V-7~V-10** | `Enhancement`, `SupplementBlock`, `EnhancementAnalysis` | 콘텐츠 품질 강화 데이터 |
| | `analyze_enhancements` | V-7 종속 꼭지 / V-8 여유 공간 보충 / V-9 강조 블록 / V-10 bold 키워드 |
| | `apply_enhancements`, `build_enhancement_report` | Kei 확정 후 보충 블록 + 보고서 |
| **Step 7 sub-layout** | `SubContainer`, `ContainerLayout`, `calculate_sub_layout` | 메인 컨테이너 안 이미지 / 텍스트 / 표 / key-msg 동적 배치 |
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **A-5** V4 후보 자동 fallback | **간접** | fit_verifier 의 *fit 판단 함수 (OK/TIGHT/OVERFLOW) 패턴* 을 차용 가능. 단 *V4 rank loop 자체는 fit_verifier 안에 없음* — 별 layer (Phase Z Step 9 application_plan 또는 Step 16 router 확장). 즉 A-5 의 *기준 함수* 만 Reference |
| **D-2** Frame min_height / resize limit | 간접 | fit_verifier 가 catalog 의 `min_height_px` 를 직접 참조. Phase Z 도 catalog 직접 읽으면 됨 — fit_verifier 통합 불필요. D-2 는 fit_verifier 와 무관하게 step09 trace 에 `min_height_px` 추가하는 작은 작업 |
| (별 axis 잠재) Step 16/17 retry path 정밀화 | 강 | `redistribute` 의 zone 안 role 간 px 재배분 패턴이 Phase Z 의 `zone_ratio_retry` action 의 실제 구현 후보 — Salvage Candidate (별 axis — deterministic retry) |
| (별 axis 잠재) Step 8 zone/region 비율 정밀화 | 중 | `estimate_text_height` 등 예측 함수가 Step 8 의 사전 (pre-allocation) 검증에 활용 가능 |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `fit_verifier` | Phase Z (현재) | 비교 |
|---|---|---|
| `calculate_fit` (예측 기반 fit 판단) | Step 14 `visual_check` (selenium 측정 기반 overflow) | **두 path 가 orthogonal — 시점 다름**. Phase Q = pre-render calculation (mapper 호출 전), Phase Z = post-render measurement (mapper 호출 후 실제 DOM 측정). 둘 다 가질 수 있지만 §0-A 원칙 8 (Reference 직접 연결 X) 적용 — **dual path 위험**. 통째 Migrate 금지 |
| `redistribute` (영역 간 px 재배분) | Step 16 `router_decision``zone_ratio_retry` action | Phase Z 는 router action 의 *이름만* 정의 (현재 placeholder 추정). 실제 px redistribute 로직은 약함. fit_verifier 의 redistribute 패턴이 *Salvage Candidate* (별 axis — deterministic retry) |
| `analyze_enhancements` V-7~V-10 (popup 차용 / 강조 / bold) | (Phase Z 미존재) | Archive — Kei AI 흐름 (강조/bold/popup 차용 판단). Phase Z 미존재 + AI repair fallback salvage 대상 아님 |
| `calculate_sub_layout` (이미지+텍스트+표+keymsg 크기) | Phase Z Layer A (Internal Region — frame contract 의 declared placement) | 다른 abstraction layer. Phase Z 의 sub_zones path 가 master |
| `count_items_in_topic` / `_count_items_from_source` | Phase Z Step 3 `extract_content_objects` (v0 minimal — 1~2 ContentObject 로 뭉침) | Phase Q 의 item count 추정이 Phase Z step03 보강에 차용 가능 — 단 mdx_normalizer (§2.1) + section_parser (§2.2) 의 sub_titles / D1/D2 패턴이 더 정밀. fit_verifier 의 `_count_items_from_source`*덜 정확* (괄호+쉼표 패턴) |
| `_load_design_tokens` | Phase Z 의 자체 token system | 별 path |
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `calculate_fit` (전체 함수) | **Reference Only** | 결정론적. Phase Z visual_check 와 dual path (예측 vs 측정). 직접 연결 X (§0-A 원칙 8) |
| `redistribute` | **Salvage Candidate** | 결정론적 + AI 무관. Phase Z Step 16/17 retry 보완 후보 (별 axis 검토 시) |
| `estimate_text_height` / `estimate_block_overhead` / `estimate_image_height` / `estimate_keymsg_height` | **Reference Only** | 결정론적 예측 함수. Phase Z 측정 path master. 예측 layer 는 dual path |
| `count_items_in_topic` / `_count_items_from_source` / `get_actual_text_chars` | **Reference Only** | mdx_normalizer / section_parser 가 master. fit_verifier 의 패턴은 보조 참고만 |
| `TopicFit / RoleFit / FitAnalysis` data classes | **Reference Only** | Phase Q 자체 schema (role / topic). Phase Z unit / zone schema 와 abstraction 다름 |
| `analyze_enhancements` (V-7~V-10) | **Archive Candidate** | **Kei 강조 / bold / popup 차용 판단** = Kei AI 흐름. §0-0 분류 기준 + AI 격리 invariant 따라 Archive |
| `apply_enhancements`, `build_enhancement_report` | **Archive Candidate** | Kei 확정 / 보고서. Kei 흐름 의존 |
| `calculate_sub_layout` | **Reference Only** | Phase Z Layer A (Internal Region) master. role-specific 패턴은 별 path |
| `build_escalation_report` | **Archive Candidate** | Kei 에스컬레이션 — Phase Q glue, Phase Z 본체 무관 |
| `_load_design_tokens` | **Reference Only** | Phase Z 자체 token system |
#### audit 판정
**Mixed (Salvage Candidate + Reference Only + Archive Candidate)**.
- **Salvage Candidate**: `redistribute` (별 axis Step 16/17 retry 보완 후보)
- **Reference Only**: `calculate_fit`, `estimate_*`, `count_items_*`, `get_actual_text_chars`, `TopicFit/RoleFit/FitAnalysis`, `calculate_sub_layout`, `_load_design_tokens`
- **Archive Candidate**: `analyze_enhancements`, `apply_enhancements`, `build_enhancement_report`, `build_escalation_report`
핵심 통찰:
1. **fit_verifier = 예측 (pre-render) layer** vs **Phase Z = 측정 (post-render selenium) layer**. 시점 다른 dual path — 통째 통합 X (§0-A 원칙 8).
2. **A-5 V4 후보 자동 fallback 의 보완 path** = fit_verifier 와 무관. Phase Z 의 Step 9 application_plan 또는 Step 16 router 확장이 master. fit_verifier 의 fit 판단 패턴은 *설계 참고만*.
3. **D-2 frame min_height** = catalog `min_height_px` 직접 참조 (fit_verifier 무관). Step 9 trace 보강은 별 작업.
4. **V-3 redistribute** = 결정론적 + AI 무관 → **Salvage Candidate**. Phase Z Step 16/17 의 `zone_ratio_retry` 보완 후보 (§3 검토 대상).
5. **V-7~V-10 enhancement = Archive Candidate** — Kei AI 흐름. AI 격리 invariant 따라 Phase Z 본체 salvage 대상 외.
#### 후속 참고 사항 (§3 Salvage Plan 에서 적용 여부 결정)
E1. **Phase Z visual_check 와 fit_verifier 의 dual path 검토** (sub-axis) — Phase Z 가 *측정 master* 라는 가설. fit_verifier 의 calculate_fit 은 Reference Only 보존 결정 확인.
E2. **A-5 V4 fallback path 검토** (별 axis) — fit_verifier 통합 X. Phase Z Step 9 application_plan 또는 Step 16 router 에 V4 rank loop 추가 가능성. fit_verifier 의 fit 판단 패턴 (OK/TIGHT/OVERFLOW) 만 *Reference Only* 참고.
E3. **D-2 catalog min_height_px → step09 trace 검토** — fit_verifier 무관 (catalog 직접):
- phase_z2_pipeline 의 lookup_v4_all_judgments 에서 each frame 의 catalog `min_height_px` 추가 가능성
- frontend FrameCandidate 에 `minHeightPx` 받아 SlideCanvas resize limit 반영 가능성
E4. **V-3 redistribute Salvage Candidate 검토** (별 axis, 큼) — *§3 결정 후*:
- Phase Z Step 16 `router_decision``zone_ratio_retry` action 을 실제 px redistribute 로 구현 가능성
- fit_verifier 의 `redistribute` 패턴 (zone 안 deficit/surplus role 간 transfer) 어댑터 작성 (§0-A 원칙 3)
- Step 17 `retry_trace` 에 redistribute 결과 trace 가능성
- Phase Z 의 schema (zone / unit) 와 Phase Q 의 schema (role / container) 차이 — adapter 필수
E5. (제거) — V-7~V-10 enhancement 는 **Archive Candidate** 로 재분류. §3 검토 대상 외.
E6. **fit_verifier 의 item count 패턴 (`_count_items_from_source`) Reference Only** — Phase Z step03 보강 시 mdx_normalizer / section_parser 가 master. fit_verifier 패턴은 *설계 참고만*.
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **E2 검토 시 (A-5 V4 fallback)** : rank-1 fit OK case 의 MDX 03 baseline regression 0 (`overall=PASS` + `aligned_section_ids` 동일). rank-1 fail 시 rank-2/3 시도 case 1 개 이상 살아남는지
- **E3 검토 시 (D-2 min_height_px trace)** : step09 v4_all_judgments 각 entry 에 `min_height_px` 필드 + frontend FrameCandidate.minHeightPx 동일값
- **E4 검토 시 (redistribute)** : `zone_ratio_retry` 적용 후 visual_check OK 되는 retry case 1 개 이상 + 미적용 baseline 결과 무변
> ⚠ **본 audit 판정은 후보 판정이며 즉시 통합 결정 아님**. §3 Salvage Plan 단계에서 적용 여부 재검토. §0-A 의 10 원칙 + §0-0 의 분류 기준 + AI 격리 invariant 모두 따름. **Archive Candidate 자산 (`analyze_enhancements`, `apply_enhancements`, `build_enhancement_report`, `build_escalation_report`) 은 §3 검토 대상 외 — Kei AI 흐름이라 Phase Z 본체 salvage 대상 아님**.
### 2.5 `space_allocator.py`
#### 역할
Phase O + Phase Q — Kei 비중 → 컨테이너 px 확정 → 블록 제약 계산 → 글자수 예산 → overflow 시 glue / font compression. 1012 줄. 결정론적 (LLM 추정 X).
| 분류 | 함수 / 자산 | 역할 |
|---|---|---|
| **height_cost catalog** | `_get_height_cost_px_range` | catalog block min_height_px → height_cost 범위 (compact/medium/large/xlarge) |
| **폰트 위계 + 동적 ratio (Phase T-5)** | `calculate_font_hierarchy(role_text_lengths, available_width)` | 역할별 폰트 크기 텍스트 양 기반 결정. 위계 강제 (핵심 > 본심 ≥ 배경 > 첨부) |
| | `calculate_dynamic_ratio(role_text_lengths, ...)` | sidebar 텍스트 양에서 body:sidebar 비율 *역산* |
| **design budget** | `calculate_design_budget(container_h, container_w, block_schema, font_size)` | 블록 schema 기반 디자인 요소 (이미지/원형/표) 가용 크기 역산 |
| **data** | `ContainerSpec` (role / zone / topic_ids / weight / height_px / width_px / max_height_cost / block_constraints) | 역할별 컨테이너 스펙 |
| **O-1 메인** | `calculate_container_specs(page_structure, topics, preset, ...)` | Kei 비중 → 역할별 ContainerSpec. zone 별 weight 비율로 height 할당 |
| **X-B 유형 B** | `build_containers_type_b(page_structure, ...)` | **B-4 lens 와 매우 관련** — top + bottom (bottom_left/bottom_right) + footer layout 의 동적 height/width 계산. 이미지 있으면 textcol+imgcol 분할 |
| **O-3 블록 스펙** | `finalize_block_specs(blocks, container_specs)` | 블록의 내부 max_items / max_chars / font_size / padding 확정 |
| **Q-3 글자수 예산** | `calculate_char_budget(block_type, container_spec, block_def)` | 블록이 컨테이너 에서 수용 가능한 최대 글자수. *AI 콘텐츠 생성의 하드 제약* |
| | `calculate_budgets_for_candidates(candidates, container_spec)` | 후보 블록 list 별 예산 일괄 계산 |
| **Q-7 glue 모델** | `GlueSpec` (natural / stretch / shrink), `SPACING_GLUE` | LaTeX glue 모델 — 유연한 간격 정의 |
| | `calculate_glue_absorption(block_count)` | 글루 모델로 흡수 가능한 최대 px |
| | `compute_glue_css_overrides(excess_px, block_count)` | overflow 흡수용 CSS 변수 (`--spacing-block` / `--spacing-inner` 등) 오버라이드 |
| **font compression** | `find_fitting_font_size(current_px, excess_after_glue, lines, chars)` | 폰트 축소 단계 (`FONT_SIZE_STEPS = [15.2, 14, 13, ..., 8]`) 이진 탐색 |
| **유틸** | `calculate_trim_chars(excess_px, container_w, font_size, ...)` | overflow 시 삭제 글자 수 계산 |
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **B-4** 다른 layout (top-1-bottom-2 / left-1-right-2 / grid-2x2 등) zone-geometry 확장 | **간접** | `build_containers_type_b` 는 Archive Candidate (Kei page_structure 입력 의존, Phase Z normal path 에 입력 source 없음). B-4 fix path 는 Phase Z `build_layout_css`*해당 preset 확장* (space_allocator 무관) |
| (별 axis 잠재) **Step 16/17 retry 정밀화** | **강** | `compute_glue_css_overrides` + `calculate_glue_absorption` + `find_fitting_font_size` 가 Phase Z router action 의 실 구현 후보. fit_verifier 의 `redistribute` 와 같이 묶어서 *retry 정밀화 axis* (deterministic retry — Salvage Candidate) |
| (별 axis 잠재) **frame slot capacity 검증** | 잠재 | `calculate_design_budget` 가 블록 schema 기반 디자인 요소 capacity. Reference Only — frame contract slot capacity validation 참고 가능 |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `space_allocator` | Phase Z (현재) | 비교 |
|---|---|---|
| `calculate_container_specs` (O-1) | `build_layout_css` (phase_z2_pipeline) | Phase Q = 역할 (본심/배경/첨부/결론) → zone (body/sidebar/footer) → **weight 비율 height**. Phase Z = unit → zone position → layout_preset 기반 **grid_template_rows CSS string**. **abstraction 완전 다름** |
| `build_containers_type_b` (X-B) | `build_layout_css` 의 top-1-bottom-2 mapping (현재 fr default) | Archive — Kei page_structure 입력 의존. Phase Z normal path 에 입력 source 없음. abstraction 도 다름 (role/zone vs unit/zone-position/preset) |
| `calculate_font_hierarchy` + `calculate_dynamic_ratio` | (Phase Z 미존재) | Archive — Kei 역할별 텍스트 길이 입력 없음. Phase Z = frame contract fixed font |
| `calculate_design_budget` | (Phase Z 미존재) | Reference Only — frame contract slot capacity validation 참고 가능 |
| `calculate_char_budget` (Q-3) | (Phase Z 일부 — step03 / step12) | Reference Only — container px → max chars 결정론적 계산. Phase Z normal path overflow 예측 / pre-render fit check 참고 가능. AI 콘텐츠 생성 / repair axis 근거 X |
| `compute_glue_css_overrides` (Q-7) | Phase Z Step 16 `router_decision``zone_ratio_retry` action | Phase Z router 가 action 이름만, glue 실 구현 X. **Salvage Candidate** — Step 16/17 retry 정밀화 axis 보완 후보 |
| `find_fitting_font_size` | Phase Z Step 16 (미존재 action) | **Salvage Candidate** — font compression retry action 신설 후보 |
| `calculate_trim_chars` | (Phase Z 미존재) | Reference Only — excess px → chars 결정론적 계산. retry 판단 참고 가능. AI 텍스트 압축 흐름과 분리 |
| `finalize_block_specs` (O-3) | Phase Z step11 / step12 (slot_mapping / slot_payload) | abstraction 다름 — Reference |
| `ContainerSpec` data class | Zone / unit schema | 다른 schema |
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `calculate_container_specs` (O-1) | **Archive Candidate** | **Kei 가 `page_structure` (역할별 weight) 결정 입력** 필요. Kei 흐름 의존. AI 격리 invariant 따라 Archive |
| `build_containers_type_b` (X-B) | **Archive Candidate** | 같은 이유 — Kei page_structure 입력 의존 |
| `calculate_font_hierarchy` | **Archive Candidate** | **Kei 가 결정한 역할별 텍스트 길이** 입력. Kei 흐름. Phase Z 는 frame contract 의 fixed font |
| `calculate_dynamic_ratio` | **Archive Candidate** | 같은 이유 — Kei 텍스트 길이 입력 |
| `calculate_design_budget` | **Reference Only** | 결정론적 block schema capacity 계산. Phase Z frame contract slot capacity validation 참고 가능. AI 콘텐츠 생성 / repair axis 근거 X |
| `calculate_char_budget` (Q-3) | **Reference Only** | 결정론적 container px → max chars 계산. Phase Z normal path overflow 예측 / pre-render fit check 참고 가능. AI 콘텐츠 생성 / repair axis 근거 X |
| `calculate_budgets_for_candidates` | **Reference Only** | calculate_char_budget wrapper. base 와 동일 |
| `compute_glue_css_overrides` + `calculate_glue_absorption` (Q-7) | **Salvage Candidate** | 결정론적 + AI 무관. Phase Z Step 16/17 retry 보완 후보 (별 axis 검토 시) |
| `find_fitting_font_size` | **Salvage Candidate** | 결정론적 + AI 무관. font compression retry 보완 후보 (별 axis 검토 시) |
| `calculate_trim_chars` | **Reference Only** | 결정론적 excess px → chars 계산. Phase Z retry 판단 참고 가능. AI 텍스트 압축 흐름과 분리 |
| `finalize_block_specs` (O-3) | **Reference Only** | abstraction 다름. Phase Z step11/step12 master |
| `SPACING_GLUE`, `GlueSpec`, `FONT_SIZE_STEPS` | **Salvage Candidate** | glue / font compression 과 함께 검토 |
| `ContainerSpec` / `ROLE_ZONE_MAP` | **Reference Only** | Phase Q schema (role / zone). Phase Z 와 abstraction 다름 |
#### audit 판정
**Mixed (Salvage Candidate + Reference Only + Archive Candidate)**.
- **Salvage Candidate**: `compute_glue_css_overrides` + `calculate_glue_absorption` (Q-7), `find_fitting_font_size`, `SPACING_GLUE / GlueSpec / FONT_SIZE_STEPS` (별 axis Step 16/17 retry 보완 후보 — deterministic retry)
- **Reference Only**: `finalize_block_specs`, `ContainerSpec`, `ROLE_ZONE_MAP`, `calculate_design_budget`, `calculate_char_budget`, `calculate_budgets_for_candidates`, `calculate_trim_chars`
- **Archive Candidate**: `calculate_container_specs`, `build_containers_type_b`, `calculate_font_hierarchy`, `calculate_dynamic_ratio`
핵심 통찰:
1. **B-4 보완 path 는 space_allocator 통합 아님** — Phase Z `build_layout_css` 가 layout preset 별 zone-geometry override 를 다른 preset 도 받게 확장. abstraction 차이 (role/zone vs unit/zone-position) 로 통째 통합 X. Phase Q `build_containers_type_b` = *Archive Candidate* (Kei page_structure 입력 의존, Phase Z normal path 입력 source 없음).
2. **Salvage Candidate = glue + font compression** (별 axis):
- `compute_glue_css_overrides` + `calculate_glue_absorption` + `find_fitting_font_size` 가 결정론적 + AI 무관 → Phase Z Step 16/17 retry 보완 후보
- fit_verifier 의 `redistribute` (§2.4 Salvage Candidate) 와 같이 *Step 16/17 retry 정밀화* 별 axis (deterministic retry) 로 묶음
3. **Kei 입력 의존 자산 = Archive Candidate** (Phase Z normal path 에 입력 source 없음):
- `calculate_container_specs` (Kei weight)
- `build_containers_type_b` (Kei page_structure)
- `calculate_font_hierarchy` (Kei 역할별 텍스트)
- `calculate_dynamic_ratio` (Kei 텍스트 길이)
- **Phase Z 본체 도 AI repair fallback 도 salvage 대상 아님**
4. **결정론적 capacity / budget 계산 자산 = Reference Only** (Phase Z normal path 활성 가능 axis 존재):
- `calculate_design_budget` (block schema capacity → frame contract slot validation)
- `calculate_char_budget` / `calculate_budgets_for_candidates` (container px → max chars → overflow 예측 / pre-render fit check)
- `calculate_trim_chars` (excess px → chars → retry 판단)
- **AI 콘텐츠 생성 / repair axis 근거 X**. §3 adapter / dual-write 검토 가능
#### 후속 참고 사항 (§3 Salvage Plan 에서 적용 여부 결정)
F1. **B-4 보완 path 검토** — Phase Z `build_layout_css` 확장 검토 (별 axis):
- horizontal-2 / vertical-2 외 다른 preset (top-1-bottom-2 / top-2-bottom-1 / left-1-right-2 / left-2-right-1 / grid-2x2) 도 zone-geometry override 받게 확장 가능성
- 각 preset 별 grid_template_rows / grid_template_cols 변환 로직 검토
- space_allocator `build_containers_type_b`*Archive Candidate* (Kei 입력 의존) — 본 검토에서 참고하지 않음. 변환 로직은 Phase Z 본체 자체 설계
F2. **Step 16/17 retry 정밀화 axis 검토** (별 axis, 큼) — fit_verifier §2.4 E4 와 같이:
- `compute_glue_css_overrides` + `calculate_glue_absorption` Salvage Candidate → `zone_ratio_retry` 보완 또는 `glue_compression` action 검토
- `find_fitting_font_size` Salvage Candidate → `font_size_retry` action 검토
- `redistribute` (fit_verifier Salvage Candidate) → zone 안 role 재배분 검토
- 세 retry action 어댑터 작성 + dual-write 검증 (§0-A 원칙 3 + 9)
F3. (제거) — `calculate_font_hierarchy` / `calculate_dynamic_ratio`**Archive Candidate** (Kei 역할별 텍스트 입력 의존, Phase Z normal path 입력 source 없음). Step 8 보강은 별 path 로 설계 (Phase Z 자체 결정).
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **F1 (B-4 build_layout_css 확장 검토)**: 각 layout preset 의 override 결과가 자동 결정 결과와 일치. MDX 03 의 horizontal-2 baseline `heights_px=[228, 343]` 유지 (regression 0).
- **F2 (glue / font compression 검토)**: glue 흡수 case 1 개 이상 (visual_check fail → glue 적용 후 PASS) + font size retry case 1 개 이상. 미적용 baseline regression 0.
- **Reference Only 자산 §3 검토 기준**: `calculate_design_budget` / `calculate_char_budget` / `calculate_budgets_for_candidates` / `calculate_trim_chars` 는 결정론적 capacity / budget 계산. §3 adapter / dual-write 검토 가능 (frame contract slot validation / pre-render fit check / retry 판단 참고 axis). **AI 콘텐츠 생성 / repair axis 근거로는 다루지 않음**.
> ⚠ **본 audit 판정은 후보 판정이며 즉시 통합 결정 아님**. §3 Salvage Plan 단계에서 적용 여부 재검토. §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름.
>
> **Archive Candidate 자산은 Kei 입력 / page_structure / role_text_lengths 의존 자산으로 한정**: `calculate_container_specs`, `build_containers_type_b`, `calculate_font_hierarchy`, `calculate_dynamic_ratio`. Phase Z normal path 에 입력 source 없음. §3 검토 대상 외.
### 2.6 `content_editor.py`
#### 역할
Phase Q normal pipeline 의 3 단계 — Kei 텍스트 편집자. `layout_concept` 의 모든 page / block 의 slot 을 Kei API 직접 호출로 채움. fallback 없음 (Kei API 가 응답할 때까지 무한 retry, `RETRY_INTERVAL=10s`). 475 lines, 4 함수 + 1 상수 (`EDITOR_PROMPT`).
핵심 함수:
- `fill_content` — main entry. async. 모든 page / block 의 slot fill. retry max 3.
- `_call_kei_editor_with_retry` — Kei API 직접 호출 (`httpx` + SSE streaming). 무한 retry.
- `fill_candidates` — Phase P (다후보) — 1 topic 의 3 후보 blocks 한꺼번에 Kei fill.
- `_parse_json` — Kei response JSON 추출 (마크다운 prefix 제거 + 3 pattern 정규식).
- `EDITOR_PROMPT` (상수) — Kei persona system prompt (도메인 전문가 텍스트 편집자).
Phase Q-3 글자수 예산 input (`_char_budget`) 은 §2.5 의 `calculate_char_budget` 출력과 연결된다. 다만 여기서는 Kei AI 호출의 hard constraint 로 사용되므로, Phase Z normal path 의 Reference 판단 (§2.5 SoT) 과는 분리한다.
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **B-1** Zone-section assignment override (§1 매핑) | (부정확) | §1 lens 표에 `content_editor.py` 가 B-1 후보 파일로 listed 단 *실제 매핑 X* — zone-section override 는 `pipeline.py` / composition planner 영역. content_editor 는 *block 안 slot 채우기*. §1 정정 별 axis 후보 (G2) |
| **B-2** Edited HTML → MDX 역변환 (§1 매핑) | (부정확) | §1 표 매핑 단 *forward direction* (text → slot fill) 인 content_editor 는 *역변환* 과 반대. 글벗 `html_to_slide_mdx` 가 B-2 main. §1 정정 별 axis 후보 (G2) |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `content_editor` | Phase Z (현재) | 비교 |
|---|---|---|
| `fill_content` (Kei AI 전체 slot fill) | (Phase Z normal path 미존재 — AI 격리 invariant) | Phase Z = Step 11 `slot_mapping`*결정론적 mapper* (frame contract slot ↔ content_object). AI 호출 X. **abstraction 완전 다름** |
| `_call_kei_editor_with_retry` (Kei API infra) | (Phase Z normal path 미존재) | Phase Z 본체 AI 호출 X. Step 12 light_edit/restructure 는 *AI repair fallback path* + 별 인프라. **본 audit 범위 외 (L3)** |
| `fill_candidates` (Phase P 다후보) | (Phase P 폐기) | Phase P era artifact. Phase Z 단일 path master |
| `_parse_json` (response parsing) | (Phase Z normal path 미존재) | AI 호출 없으므로 parsing 도 없음 |
| `EDITOR_PROMPT` | (Phase Z normal path 미존재) | Kei persona 자체 = Phase Z 본체 외 |
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `fill_content` | **Archive Candidate** | Kei AI 슬롯 fill flow. Phase Z normal path 의 Salvage / Reference 대상은 아님 |
| `_call_kei_editor_with_retry` | **Archive Candidate** | Kei API 직접 호출 인프라. Phase Z normal path 의 Salvage / Reference 대상은 아님. AI repair fallback 은 본 audit 범위 밖이며, 별도 axis 활성 시 새 기준으로 재검토 |
| `fill_candidates` | **Archive Candidate** | Phase P 다후보 era + Kei AI 의존 |
| `_parse_json` | **Archive Candidate** | 결정론적 utility 단 Phase Z normal path 활성 axis 부재. AI response parsing 영역은 본 audit 밖, 별도 axis 활성 시 새 기준으로 재검토 |
| `EDITOR_PROMPT` (상수) | **Archive Candidate** | Kei persona prompt — Phase Z 본체 외 |
#### audit 판정
**Archive Candidate (module-level)**.
- 이유: Kei AI direct slot-fill flow, Phase Z normal path 와 abstraction 불일치 (AI 격리 invariant + §0-B Audit 범위 lock 따름)
- §3 Salvage Plan 대상: **없음**
- 별도 surface:
- §1 audit lens 표의 B-1 / B-2 후보 파일 매핑 정정 필요 (G2 별 axis)
- AI repair fallback 의 infrastructure 참고 (`httpx` + SSE + retry + JSON parse) 여부는 본 audit 밖, 별도 axis 활성 시 재검토 (G3 별 axis)
#### 후속 참고 사항 (본 audit 밖 surface)
G1. (제거) — `content_editor.py` 모든 자산 Archive Candidate. Phase Z normal path 의 Salvage / Reference 대상은 아님. §3 검토 대상 외.
G2. (별 axis 후보, 본 audit 외) — §1 audit lens 표의 B-1 / B-2 column 에 `content_editor.py` 매핑 부정확. content_editor 는 B-1 zone-section override / B-2 HTML→MDX 역변환 에 직접 관여 X. §1 정정 별 axis 검토.
G3. (별 axis 후보, 본 audit 외) — AI repair fallback (Phase Z step12 light_edit/restructure) 설계 axis 활성 시, content_editor 의 *infrastructure pattern* (`httpx` + SSE streaming + retry + JSON parse) 이 reference 가능. 단 §0-B Audit 범위 lock (L3) 따라 *별 axis 활성 시 새 기준으로 재검토* — 본 audit 에서는 평가 X.
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
**없음** — 모든 자산 Archive Candidate. §3 검토 대상 외.
> ⚠ **본 §2.6 audit 판정은 Phase Z normal path 기준의 후보 분류이며, `content_editor.py` 자산은 현재 §3 Salvage Plan 대상 외로 둔다.** §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름. **AI repair fallback 의 평가 여부는 본 audit 밖 — 별도 axis 활성 시 새 기준으로 재검토**.
### 2.7 `content_verifier.py`
#### 역할
Phase Q normal pipeline 의 verification step. 헤더는 5-layer 검증을 선언하지만, **이 파일의 실제 구현은 L1 텍스트 보존 / L2 금지 콘텐츠 / L3 구조 검증 + Kei HTML generation retry loop 중심**이다. L4 Selenium overflow / L5 Opus vision 은 헤더 주석상 *계획 또는 외부 layer (`slide_measurer.py` / `kei_client.py` reuse)* 로 언급되지만, **본 파일에서 직접 구현되지는 않음**.
678 lines, 12 함수 + 2 classes (`VerificationResult`, `_TextExtractor`).
핵심 함수:
- `VerificationResult` (dataclass), `_TextExtractor` / `extract_text_from_html`: HTML text 추출
- `normalize_for_comparison` + `_PARTICLES` + `_ENDING_NORMALIZE`: 한국어 정규화 (조사 stripping + 개조식 → 서술형 변환)
- `extract_keywords` / `strip_meta_lines` / `split_into_sentences`: 텍스트 처리 utility
- `verify_text_preservation` (L1) + `detect_invented_text`: 텍스트 보존 / 발명 텍스트 검증
- `verify_no_forbidden_content` (L2) + `FORBIDDEN_KEI_MEMOS` + `FORBIDDEN_LABELS_IN_KEYMSG`: Kei prompt leak / label 검출
- `verify_structure` (L3) + `REQUIRED_PATTERNS`: per-area CSS/HTML 필수 패턴 + 폰트 위계 검사
- `verify_area` / `verify_all_areas`: orchestrator (L1+L2+L3 합성)
- `generate_with_retry` (async): full retry loop — `html_generator.generate_slide_html` (Kei AI) + `html_validator.validate_and_clean_html` + `verify_all_areas`
import 으로 본 file 직접 호출: `html_generator` + `html_validator`. `slide_measurer` / `kei_client` import X.
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| (없음) — main role 매핑 | (해당 없음) | content_verifier 의 main role 은 *Kei AI 생성 HTML 의 정확도 verification* (forward direction post-check). §1 audit lens 의 직접 매핑 항목 없음 |
| **B-2** Edited HTML → MDX 역변환 (§1 §2 audit list 매핑) | (간접) | §1 §2 audit list 에 "B-2 후속" 으로 listed. main role 과 직접 매핑 X — *B-2 axis 활성 시 verification 보조* 의 간접 정도 (§2.6 만큼 부정확하지는 않음) |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `content_verifier` | Phase Z (현재) | 비교 |
|---|---|---|
| `verify_text_preservation` (L1) | (Phase Z normal path 미존재) | Phase Z mapper *by construction* 텍스트 보존 (Step 11 slot_mapping). L1 검증 활성 axis 부재 |
| `verify_no_forbidden_content` (L2) | (Phase Z normal path 미존재) | Phase Z 본체 Kei AI 호출 X → Kei prompt leak 가능성 부재 |
| `verify_structure` (L3) + `REQUIRED_PATTERNS` | (Phase Z normal path 일부 — frame contract validation 영역) | Phase Q `REQUIRED_PATTERNS` = body_bg/core/sidebar/footer Phase Q area. Phase Z = unit/zone/preset/frame contract — **abstraction 다름** |
| Layer 4 Selenium overflow (헤더 언급) | Phase Z Step 14 `visual_check` | §2.3 `slide_measurer` 영역 — 본 파일 직접 구현 부재 |
| Layer 5 Opus vision (헤더 언급) | (Phase Z normal path 미존재 — AI 격리 invariant) | AI 호출. AI repair fallback 영역 (본 audit 외, L3 lock) — 본 파일 직접 구현 부재 |
| utility 함수들 | (Phase Z 미존재) | 결정론적 + AI 무관 + 일반 utility. Phase Z normal path *직접 빈칸 채움 X* — 별 axis 활성 시 참고 가능 |
| `generate_with_retry` | (Phase Z normal path 미존재) | html_generator (Kei AI) generation retry loop |
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `VerificationResult` (dataclass) | **Reference Only** | 결과 구조 참고. Phase Z artifact/status 구조와 직접 통합은 별도 판단 |
| `_TextExtractor` / `extract_text_from_html` | **Reference Only** | HTML text extraction utility. B-2 / verification 보강 별 axis 활성 시 참고 |
| `normalize_for_comparison` + `_PARTICLES` + `_ENDING_NORMALIZE` | **Reference Only** | 한국어 비교 정규화 utility. Phase Z normal path 직접 slot 없음 |
| `extract_keywords` | **Reference Only** | keyword 비교 utility. Phase Z path 활성 axis 부재 |
| `strip_meta_lines` | **Reference Only** | AI/Kei meta 제거 성격 — normal path 직접 대상 X |
| `split_into_sentences` | **Reference Only** | 일반 utility. 참고 가능 |
| `verify_text_preservation` (L1) | **Reference Only** | 결정론적이나 Phase Z mapper *by construction* 텍스트 보존. 검증 보강 별 axis 참고 |
| `detect_invented_text` | **Reference Only** | AI 생성 결과 검증 성격. normal path 직접 대상 X |
| `verify_structure` (L3) | **Reference Only** | CSS pattern 검사 방식 참고 |
| `REQUIRED_PATTERNS` (constant) | **Reference Only** | 구조 참고. 값은 Phase Q area abstraction — Phase Z 다름 |
| `verify_area` / `verify_all_areas` | **Reference Only** | orchestrator pattern 참고. 직접 통합 X |
| `verify_no_forbidden_content` + `FORBIDDEN_KEI_MEMOS` + `FORBIDDEN_LABELS_IN_KEYMSG` | **Archive Candidate** | Kei prompt leak / label 검출. Phase Z normal path 에 Kei 없음 |
| `generate_with_retry` (async) | **Archive Candidate** | html_generator (Kei AI) generation retry loop. Phase Z normal path 미존재 |
#### audit 판정
**Mixed (Reference Only + Archive Candidate)**.
`content_verifier.py` 는 결정론적 검증 utility 가 많지만, *Phase Z normal path 의 직접 Salvage 후보 (특정 빈칸 채움) 는 없다*. 대부분은 future verification / visual_check 보강 / B-2 검증 별 axis 활성 시 참고 가능한 **Reference Only** 이며, Kei artifact 검출과 AI generation retry loop 는 **Archive Candidate** 다. **L4 Selenium / L5 Opus vision 은 헤더 documentation only — 본 파일 구현 없음**.
- §3 Salvage 적용 대상: **없음** (Salvage Candidate 0). Reference Only 자산은 future verification / visual_check / B-2 검증 별 axis 활성 시 *참고 여부만 별도 판단* (직접 통합 X)
- 별도 surface:
- §1 audit lens 의 "B-2 후속" 매핑은 *간접* — main role 은 Kei AI 생성 HTML verification (forward direction)
- L4/L5 implementation 부재 — header documentation 과 실 구현 분리
- Reference Only 자산의 활성 axis 결정 = 별 axis (visual_check 보강 / B-2 검증 / future verification axis)
- AI repair fallback 의 Layer 5 (Opus vision) reuse 여부 = 본 audit 밖
#### 후속 참고 사항 (본 audit 밖 surface)
H1. (별 axis 후보) — Phase Z visual_check (Step 14) 보강 axis 활성 시, content_verifier 의 *generic utilities* (text 추출 / 정규화 / sentence split / keyword 추출 / `VerificationResult`) 가 **Reference Only 참고 후보**. *직접 통합 X* — adapter / dual-write 검증은 별 axis 활성 시 새 기준으로 결정.
H2. (별 axis 후보) — Phase Z frame contract validation 별 axis 활성 시 `verify_structure` 패턴 (CSS pattern 검사 + 폰트 위계 검사) 이 Reference Only 참고. 단 `REQUIRED_PATTERNS` 값은 Phase Q area 특화 → Phase Z 자체 pattern dict 설계 필요.
H3. (별 axis 후보) — B-2 (Edited HTML → MDX 역변환) axis 활성 시 utility 함수 (text 추출 / 정규화 / 비교) 가 verification 보조로 Reference Only 참고 가능. 직접 통합 X. main role 매핑은 *간접*.
H4. (Archive marker) — `verify_no_forbidden_content` + `FORBIDDEN_KEI_MEMOS` 등 Kei artifact 검출 자산은 Archive Candidate. Phase Z 본체에 Kei AI 호출 없음. §3 검토 대상 외.
H5. (Archive marker) — `generate_with_retry` 는 Kei AI generation retry loop. Phase Z 본체 미존재. AI repair fallback axis 활성 시도 retry loop 자체 설계는 별 axis. §3 검토 대상 외.
H6. (factual note) — 헤더의 L4 (Selenium) / L5 (Opus vision) layer 는 *문서적 계획*. 본 파일의 실 구현은 L1~L3 + retry loop. L4 는 §2.3 `slide_measurer.py` 영역 / L5 는 AI repair fallback axis (본 audit 외).
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **Salvage Candidate**: 없음
- **Reference Only** 자산: §0-A 원칙 10 따라 활성 axis 결정 = *별 axis*. 활성 시 그 axis 의 SoT 따라 adapter / dual-write 기준 별도 결정. 본 §2.7 audit 단계의 dual-write 기준 적용 X.
- **Archive Candidate** 자산: §3 검토 대상 외.
> ⚠ **본 §2.7 audit 판정은 Phase Z normal path 기준의 후보 분류이며, `content_verifier.py` 는 §3 Salvage 적용 대상이 없다 (Salvage Candidate 0).** §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름. Reference Only 자산은 future verification / visual_check 보강 / B-2 검증 별 axis 활성 시 *참고 여부만 별도 판단* (직접 통합 X). **L4 Selenium / L5 Opus vision 은 본 파일 구현 부재 — header documentation only**.
### 2.8 `renderer.py`
#### 역할
**헤더**: "DA-11 + DA-21: 슬라이드 조합 렌더러" — 블록 배치 명세(JSON)를 받아 Jinja2 로 HTML 생성. 다중 페이지 지원 / 카테고리 경로 (`blocks/{category}/{name}.html`) / `_legacy` fallback / area 블록 그룹핑.
**687 lines, 11 함수 (class 없음).**
핵심 함수:
- `_load_catalog_map` / `_load_catalog_map_with_variants``catalog.yaml` → block id → template 매핑 (mtime check + 캐시, Phase R variant 포함)
- `create_jinja_env` — Jinja2 Environment 생성 (FileSystemLoader)
- `_resolve_template_path` — block_type + variant → template path 해결 (catalog → 카테고리 검색 → `_legacy` fallback)
- `_preprocess_svg_data` — Phase P2-B SVG 시각화 블록 좌표 사전 계산 (결정론적)
- `_group_blocks_by_area` — 같은 area 블록 그룹핑 + Phase O 비중 기반 컨테이너
- `render_multi_page` — 다중 페이지 슬라이드 HTML 생성 (DA-21 카테고리 경로 + `slide-base.html` + `tokens.css` + `base.css` 인라인)
- `render_slide` — 하위 호환 단일 페이지 (pages 구조 있으면 `render_multi_page` 위임)
- `render_block_in_container`**Phase P 다후보** era — 단일 블록 + 컨테이너 HTML (Selenium 스크린샷 캡처용)
- **`render_slide_from_html`** — **Phase R'** — AI 가 생성한 HTML 조각 (body/sidebar/footer) → slide-base 프레임 삽입
- `render_standalone_block` — 단일 블록 독립 HTML (테스트/미리보기)
#### 관련 §7-B 항목
| §7-B | 직간접 | 영향 |
|---|---|---|
| **A-3** Frame preview png 일관성 | (간접) | A-3 main = *preview.png 자동 생성 path*. `render_block_in_container` 가 Selenium 스크린샷 캡처용 HTML 생성 — preview render layer 의 1 component. Selenium 호출 자체는 별 module |
| **A-4** slide-base.html iframe-friendly mode | (영향면 있음, 구현 부재) | renderer.py 는 `slide-base.html` 사용 호출 지점 있음 (`render_multi_page` / `render_slide` / `render_slide_from_html`) — **A-4 영향면 보유**. 단 *embedded / standalone conditional CSS 분기* 는 구현하지 않음. A-4 자체는 *향후 보강 target* |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `renderer` | Phase Z (현재) | 비교 |
|---|---|---|
| `_load_catalog_map` + `_load_catalog_map_with_variants` (catalog.yaml) | Phase Z = `templates/phase_z2/catalog/frame_contracts.yaml` | **catalog schema 다름**. Phase Q = block id → variant template. Phase Z = frame contract + frame_partials |
| `create_jinja_env` (Jinja2 env) | Phase Z 자체 wrapper (`phase_z2_pipeline`) | Jinja2 공통 사용 단 wrapper 다름 |
| `_resolve_template_path` (catalog + 카테고리 + fallback) | Phase Z = frame_id → frame_partial path 직접 매핑 | **abstraction 다름** (block category vs frame contract id) |
| `_preprocess_svg_data` (SVG 좌표 사전 계산) | (Phase Z normal path 미존재 — frame_partials 안에 좌표 박힘) | Phase Z 의 SVG 는 frame_partial 안에 미리 박혀 있어 preprocess 불필요 |
| `_group_blocks_by_area` (area 비중 grouping) | Phase Z = zone/unit/preset (별 abstraction) | **abstraction 완전 다름** (Phase Q area + 비중 vs Phase Z zone preset) |
| `render_multi_page` / `render_slide` (orchestrator) | Phase Z = `phase_z2_pipeline` 의 final HTML 생성 | Phase Z 자체 orchestrator master |
| `render_block_in_container` (Selenium 캡처용) | (Phase Z normal path 미존재 — A-3 구현 axis) | Phase P 다후보 era artifact. A-3 구현 axis 활성 시 reference |
| **`render_slide_from_html`** (Phase R') | **(Phase Z 에서 명시 폐기)** | CLAUDE.md: *"Phase R' 의 역할 분리 (AI 가 HTML 구조 직접 생성) 는 Phase Z 에서 폐기"* — Archive |
| `render_standalone_block` (테스트 utility) | (Phase Z 미존재 — 별 axis 활성 시 reference) | 단일 블록 utility |
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `_load_catalog_map` / `_load_catalog_map_with_variants` | **Reference Only** | catalog 로드 + mtime 캐시 패턴 참고 가능. Phase Q catalog schema 와 Phase Z frame_contracts schema 다름 → 직접 통합 X |
| `create_jinja_env` | **Reference Only** | Jinja2 env 생성 wrapper. Phase Z 자체 wrapper 있음 |
| `_resolve_template_path` | **Reference Only** | catalog ID → template path 패턴 참고. Phase Q schema 특화 |
| `_preprocess_svg_data` | **Reference Only** | SVG 좌표 사전 계산 패턴. Phase Z SVG 는 frame_partial 안 — 직접 활용 axis 부재 |
| `_group_blocks_by_area` | **Reference Only** | area 비중 grouping 패턴 참고. abstraction (Phase Q area vs Phase Z zone) 다름 |
| `render_multi_page` / `render_slide` | **Reference Only** | orchestrator 패턴 참고. Phase Q layout_concept schema 특화 |
| `render_block_in_container` (Phase P + Selenium 캡처용) | **Reference Only** | A-3 구현 axis 활성 시 reference (HTML wrapper partial helper — end-to-end preview 구현은 별 layer). 직접 통합 X |
| **`render_slide_from_html`** (Phase R') | **Archive Candidate** | Phase R' 명시 폐기 (CLAUDE.md). AI 가 HTML 구조 직접 생성하는 흐름 — Phase Z 에서 거부됨 |
| `render_standalone_block` | **Reference Only** | 단일 블록 테스트 utility. 별 axis 활성 시 reference |
#### audit 판정
**Mixed (Reference Only + Archive Candidate)**.
`renderer.py` 는 결정론적 Jinja2 rendering utility 가 많지만, *Phase Z normal path 의 직접 Salvage 후보는 없다*. catalog schema / area abstraction / orchestrator 모두 Phase Q 특화 — Phase Z 와 abstraction 다름. 단 `render_slide_from_html` (Phase R' artifact) 는 **Archive Candidate** — CLAUDE.md 가 명시 폐기.
- §3 Salvage 적용 대상: **없음** (Salvage Candidate 0). Reference Only 자산은 *A-3 구현 axis / A-4 보강 axis / Phase Z SVG 보강 axis* 활성 시 참고 여부만 별도 판단 (직접 통합 X)
- 별도 surface:
- §1 audit lens 의 A-3 매핑은 *간접* (preview render component 의 1 part)
- A-4 iframe-friendly mode: renderer.py 가 `slide-base.html` *영향면 보유* (사용 호출 지점 있음). 단 *embedded/standalone conditional CSS 분기* 구현 부재 — A-4 는 *향후 보강 target*
- **`render_slide_from_html` (Phase R') = Archive 명확** (CLAUDE.md 명시 폐기 — AI 가 HTML 구조 직접 생성하는 흐름 금지) — 가장 중요한 배제 결정
#### 후속 참고 사항 (본 audit 밖 surface)
I1. (별 axis 후보) — A-3 구현 axis 활성 시, `render_block_in_container` 의 Selenium 캡처용 HTML 생성 pattern 이 **Reference Only 참고 후보**. 직접 통합 X — adapter / dual-write 검증은 별 axis 활성 시 새 기준으로 결정.
I2. (별 axis 후보 — A-4 영향면 보유, 구현 부재) — renderer.py 가 `slide-base.html` 사용 호출 지점은 있어 *A-4 영향면 보유*. 단 *embedded/standalone conditional CSS 분기* 는 구현 없음. Phase Z 본체 또는 A-4 보강 axis 에서 *새 설계* 필요 (renderer.py 의 slide-base 사용 pattern 만 Reference).
I3. (별 axis 후보) — `_preprocess_svg_data` (SVG 좌표 사전 계산) 가 Phase Z SVG 보강 axis 활성 시 Reference Only 참고. 단 Phase Z frame_partials 에 좌표 박힘 — 활성 axis 자체 검토 필요.
I4. (별 axis 후보) — `_group_blocks_by_area` (area 비중 grouping + Phase O 컨테이너) 가 Phase Z zone 비중 분배 axis 활성 시 Reference Only. abstraction 다름 — 직접 통합 X.
I5. (Archive marker) — **`render_slide_from_html` 는 Phase R' artifact**. CLAUDE.md 가 *"Phase R' 의 역할 분리 (AI 가 HTML 구조 직접 생성) 는 Phase Z 에서 폐기"* 명시. §3 검토 대상 외. Phase Z 의 *결정론적 mapper* path 와 직접 충돌.
I6. (factual note) — §1 audit lens 의 A-3 / A-4 매핑 정확도:
- A-3: *간접* (renderer 는 preview render component 의 1 part, Selenium 호출은 별 module)
- A-4: renderer.py 가 `slide-base.html` 사용 호출 지점 있음 → *영향면 보유*. 단 *embedded/standalone conditional CSS 분기 구현 부재* — A-4 자체는 *향후 보강 target*
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **Salvage Candidate**: 없음
- **Reference Only** 자산: §0-A 원칙 10 따라 활성 axis 결정 = *별 axis* (A-3 구현 axis / A-4 보강 axis / Phase Z SVG 보강 axis 등). 활성 시 그 axis 의 SoT 따라 adapter / dual-write 기준 별도 결정. 본 §2.8 audit 단계의 dual-write 기준 적용 X.
- **Archive Candidate** (`render_slide_from_html`, Phase R'): §3 검토 대상 외.
> ⚠ **본 §2.8 audit 판정은 Phase Z normal path 기준의 후보 분류이며, `renderer.py` 는 §3 Salvage 적용 대상이 없다 (Salvage Candidate 0).** §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름. Reference Only 자산은 A-3 구현 axis / A-4 보강 axis / Phase Z SVG 보강 axis 활성 시 *참고 여부만 별도 판단* (직접 통합 X). **`render_slide_from_html` (Phase R') = Archive 명확 (CLAUDE.md 명시 폐기)**.
### 2.9 `html_generator.py`
#### 역할
**헤더**: "Phase T: AI HTML 생성기 — 동적 프롬프트 생성"
> 영역별 개별 호출. Phase T context (폰트 위계, 블록 레퍼런스, 디자인 예산) 에서 모든 수치를 동적으로 가져와 프롬프트 조립.
> **역할 분리**: Kei (1단계) = 콘텐츠 분석. **Claude Sonnet (이 모듈) = HTML 코드 생성**.
**1069 lines, 13 함수 (class 없음) + 2 legacy prompt 상수**.
**이 모듈 자체가 *Phase R' (AI HTML 직접 생성) main implementation***:
- `import anthropic` + `_call_claude` → Anthropic Claude Sonnet API 직접 호출
- `generate_slide_html` (async) — main entry, 4 영역 (배경/본심/sidebar/footer) 각각 Claude 호출
- `regenerate_area` (async) — failed area retry + error feedback
- `build_area_prompt` — Phase T 동적 prompt 조립
§2.8 의 `render_slide_from_html` (renderer.py 의 Phase R' helper) 가 *consume 하는 main path* — html_generator 가 Phase R' 의 *core implementation*.
핵심 함수:
| 함수 | line | 역할 | AI 의존 |
|---|---|---|---|
| `_calc_indent` | 49 | 폰트 크기 기반 들여쓰기 px 계산 | deterministic |
| `build_area_prompt` | 59 | 영역별 Claude prompt 동적 조립 (Phase T) | AI prompt 조립 |
| `_build_phase_t_supplement` | 532 | Phase T context supplement | AI prompt 보조 |
| `generate_slide_html` (async) | 594 | **main entry** — 4 영역 Claude API 호출 | Claude API 직접 호출 |
| `normalize_mdx` | 752 | MDX 정규화 | deterministic |
| `_slice_mdx_sections` | 830 | MDX section slicing | deterministic |
| `_map_sections_for_role` | 858 | role-section 매핑 | deterministic |
| `_extract_keywords_from_hints` | 906 | source_hint keyword 추출 | deterministic |
| `_get_definitions` | 930 | 용어 정의 추출 | deterministic |
| `_get_conclusion` | 943 | 결론 추출 | deterministic |
| `_call_claude` (async) | 963 | Claude Sonnet API call + HTML 추출 | Claude API 인프라 |
| `regenerate_area` (async) | 989 | failed area Claude 재호출 + error feedback | Claude API 재호출 |
| `_replace_img_placeholder` | 1056 | placeholder 이미지 → base64 교체 | deterministic |
상수: `_LEGACY_SIDEBAR_PROMPT` / `_LEGACY_FOOTER_PROMPT` (regenerate_area 에서 사용 — legacy prompt 폴백).
#### 관련 §7-B 항목
**§1 §2 audit list**: `html_generator.py` (A-3, A-4)
| §7-B | 직간접 | 영향 |
|---|---|---|
| **A-3** Frame preview png 일관성 | (부정확) | A-3 main = preview.png 자동 생성. html_generator 는 *full slide HTML 의 AI 생성* — preview 생성 component 와 직접 매핑 X. §1 의 "(selenium 캡처 흔적 추정)" 부연도 부정확 (html_generator 에 Selenium import 부재). §1 정정 후보 |
| **A-4** slide-base.html iframe-friendly mode | (부정확) | html_generator 는 area HTML 만 반환 (body/sidebar/footer separately). slide-base 사용은 renderer.py — html_generator 는 slide-base 호출 부재. §1 정정 후보 |
→ §1 매핑 = §2.8 renderer.py 와 같은 패턴으로 부정확. 별 axis 정정 후보 (J5).
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `html_generator` | Phase Z (현재) | 비교 |
|---|---|---|
| `generate_slide_html` (AI HTML generation main) | **(Phase Z 에서 명시 폐기 — Phase R')** | CLAUDE.md: *"Phase R' 의 역할 분리 (AI 가 HTML 구조 직접 생성) 는 Phase Z 에서 폐기"*. Phase Z = 결정론적 mapper |
| `_call_claude` (Claude API infra) | (Phase Z normal path 미존재 — AI 격리 invariant) | Phase Z 본체 AI 호출 X. AI repair fallback 영역 (본 audit 외, L3 lock) |
| `regenerate_area` (Claude 재호출 + error feedback) | (Phase Z 폐기) | retry loop 자체가 Phase R' 의 part |
| `build_area_prompt` + `_build_phase_t_supplement` (Phase T 동적 prompt) | (Phase Z 폐기) | Phase T → Phase R' 흐름 — Phase Z 에서 거부됨 |
| `normalize_mdx` (line 752) | §2.1 `mdx_normalizer.py``normalize_mdx_content` | **중복 implementation** (§2.1 에 더 직접적인 SoT 후보 존재) |
| `_slice_mdx_sections` / `_map_sections_for_role` | §2.2 `section_parser.py` 의 extract 함수들 | **중복 implementation** (§2.2 에 더 직접적인 SoT 후보 존재) |
| `_get_definitions` / `_get_conclusion` | §2.2 `extract_conclusion_text` 등 | 부분 중복 (§2.2 에 더 직접적인 SoT 후보 존재) |
| `_extract_keywords_from_hints` | (Phase Z 미존재 — keyword 추출 utility) | 일반 utility |
| `_replace_img_placeholder` | (Phase Z 미존재 — base64 image utility) | 일반 utility |
| `_calc_indent` | (Phase Z 미존재 — typography utility) | 일반 utility |
#### 재사용 가능성
| 자산 | 분류 | 근거 |
|---|---|---|
| `_calc_indent` | **Reference Only** | typography utility. Phase Z normal path 직접 활성 axis 부재 |
| `build_area_prompt` | **Archive Candidate** | Claude prompt 조립 — AI HTML generation flow. Phase R' main path |
| `_build_phase_t_supplement` | **Archive Candidate** | Phase T → Phase R' Claude prompt 보조. AI flow |
| **`generate_slide_html`** (async) | **Archive Candidate** | **Phase R' main entry** — Claude API 직접 호출. CLAUDE.md 명시 폐기 |
| `normalize_mdx` | **Reference Only** | §2.1 `normalize_mdx_content` 와 중복 (§2.1 에 더 직접적인 SoT 후보 존재). Phase Z normal path 직접 활성 axis 부재. Phase R' cleanup 시 별도 판단 |
| `_slice_mdx_sections` | **Reference Only** | §2.2 `extract_major_sections` 영역 중복 (§2.2 에 더 직접적인 SoT 후보 존재). Phase Z normal path 직접 활성 axis 부재. Phase R' cleanup 시 별도 판단 |
| `_map_sections_for_role` | **Reference Only** | role-section 매핑 utility. Phase Z = V4 매칭 path master |
| `_extract_keywords_from_hints` | **Reference Only** | keyword utility |
| `_get_definitions` | **Reference Only** | 용어 정의 추출 utility |
| `_get_conclusion` | **Reference Only** | §2.2 `extract_conclusion_text` 와 부분 중복 (§2.2 에 더 직접적인 SoT 후보). Phase R' cleanup 시 별도 판단 |
| **`_call_claude`** (async) | **Archive Candidate** | Claude API 직접 호출 infrastructure. AI HTML generation flow |
| **`regenerate_area`** (async) | **Archive Candidate** | failed area Claude 재호출 + error feedback. AI flow + retry loop |
| `_replace_img_placeholder` | **Reference Only** | base64 image utility |
| `_LEGACY_SIDEBAR_PROMPT` / `_LEGACY_FOOTER_PROMPT` (상수) | **Archive Candidate** | legacy Claude prompt 상수. Phase R' artifact |
#### audit 판정
**Mixed (Archive heavy — Phase R' core)**.
`html_generator.py`*Phase R' (AI HTML 직접 생성) 의 main implementation*. CLAUDE.md 가 명시 폐기. **Salvage Candidate 0**. 대부분의 AI HTML generation path (`generate_slide_html` / `_call_claude` / `regenerate_area` / `build_area_prompt` / Phase T supplement / `_LEGACY_*` prompts) = **Archive Candidate**. 일부 deterministic helper (`normalize_mdx` / `_slice_mdx_sections` / `_get_definitions` / `_get_conclusion` / `_calc_indent` / `_replace_img_placeholder` 등) = **Reference Only** (§2.1 / §2.2 에 더 직접적인 SoT 후보 존재).
- §3 Salvage 적용 대상: **없음** (Salvage Candidate 0)
- 별도 surface:
- §1 audit lens 의 A-3 / A-4 매핑 *부정확* — html_generator 는 *AI HTML generation main* 으로 A-3 (preview) / A-4 (iframe mode) 와 직접 관계 X (§2.6 / §2.8 patterns 누적)
- **html_generator 가 Phase R' 의 *core implementation***. §2.8 의 `render_slide_from_html`*consume 하는 main path* — Phase R' Archive 영역의 *주축*
- utility 함수 중복 (§2.1 / §2.2 자산과) — *Phase R' cleanup 시 별 axis* 후보
#### 후속 참고 사항 (본 audit 밖 surface)
J1. (Archive marker — 핵심) — **`html_generator.py` 가 Phase R' (AI HTML 직접 생성) main implementation**. `generate_slide_html` / `_call_claude` / `regenerate_area` / `build_area_prompt` / `_build_phase_t_supplement` / `_LEGACY_*` prompts 모두 Archive Candidate. CLAUDE.md 명시 폐기. §3 검토 대상 외.
J2. (별 axis 후보 — §2.8 와 연결) — §2.8 의 `render_slide_from_html` (Phase R' helper) 가 *consume* 하는 main implementation. **§2.8 + §2.9 양쪽이 Phase R' archive 영역의 공동 core**. §3 Salvage Plan 에서 *Phase R' 영역 전체* 별 axis 로 묶어 표시 가능.
J3. (별 axis 후보 — cleanup) — utility 함수 중복: `normalize_mdx` (vs §2.1 `mdx_normalizer.normalize_mdx_content`) / `_slice_mdx_sections` (vs §2.2 `extract_major_sections`) / `_get_definitions` / `_get_conclusion` (vs §2.2 `extract_conclusion_text`). §2.1 / §2.2 에 이미 더 직접적인 SoT 후보가 있으므로, 본 모듈 안의 중복 helper 는 Reference Only. Phase R' cleanup 시 제거/보존 여부를 별도 판단.
J4. (별 axis 후보) — `_calc_indent` / `_extract_keywords_from_hints` / `_replace_img_placeholder`*일반 utility* 는 future verification / rendering 보강 axis 활성 시 Reference Only 참고.
J5. (factual note — §1 매핑 누적) — §1 audit lens 의 A-3 / A-4 매핑 정확도:
- A-3: 부정확 — html_generator 는 *AI HTML generation main*, preview render component 아님. §1 의 "(selenium 캡처 흔적 추정)" 부연도 부정확 (Selenium import 부재)
- A-4: 부정확 — html_generator 는 *area HTML separately 반환*, slide-base 사용 부재 (renderer.py 가 slide-base 사용)
- §2.6 / §2.8 / §2.9 의 §1 매핑 부정확 패턴 누적 — §1 정정 별 axis weight ↑ (단 본 audit 에서는 직접 정정 X — 별 axis 로 deferred)
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **Salvage Candidate**: 없음
- **Reference Only** 자산 (deterministic helpers): §0-A 원칙 10 따라 활성 axis 결정 = *별 axis*. Phase Q utility 중복 자체가 cleanup 별 axis 영역. §2.1 / §2.2 에 더 직접적인 SoT 후보가 있으므로 본 모듈 중복 helper 는 *Phase R' cleanup 시 별도 판단*
- **Archive Candidate** (Phase R' core + Claude prompt 상수): §3 검토 대상 외
> ⚠ **본 §2.9 audit 판정은 Phase Z normal path 기준의 후보 분류이며, `html_generator.py` 는 Phase R' (AI HTML 직접 생성) main implementation 으로 §3 Salvage 적용 대상이 없다.** §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름. Reference Only 자산은 §2.1 / §2.2 에 더 직접적인 SoT 후보가 있으므로 Phase R' cleanup 시 별도 판단. **`html_generator.py` = Phase R' core Archive 명확 (CLAUDE.md 명시 폐기 — AI 가 HTML 구조 직접 생성하는 흐름 금지)**.
### 2.10 `block_reference.py` / `block_selector.py`
#### 역할
두 모듈 모두 *block catalog + selection logic* 영역이나 **시기와 사용처가 다름**:
- **`block_reference.py`** (Phase T-3, 755 lines): "참고 블록 선택 + 디자인 레퍼런스 HTML 생성". Stage 1.7 호출. *블록을 "참고할 디자인"* 으로 제공 (Phase R' AI 의 reference path). 8 함수 + 1 상수
- **`block_selector.py`** (Phase Q-2, 267 lines): "제약 기반 블록 선택 엔진". relation_type → 카테고리 + 컨테이너 제약 필터링. "AI 에게 불가능한 선택지를 주지 않는다" (Beautiful.ai 원칙). 5 함수 + 3 상수. **pipeline.py 에서 unused** (Phase T 가 block_reference 로 대체) 단 `format_candidates_for_prompt``kei_client.py` 에서 사용
핵심 함수 (block_reference):
- `_get_jinja_env`, `_load_catalog`, `_get_block_by_id`: utility (Jinja2 / catalog / block 검색)
- `_match_visual_type` (line 136): expression_hint 키워드 매칭 (deterministic pattern)
- `_match_by_tags` (line 152): tag 기반 매칭 (deterministic). **pipeline.py 도 직접 호출 (line 228 — Phase R' 전용 아님)**
- `select_reference_block` (line 237): Phase T-3 main reference block 선택
- `generate_design_reference` (line 448): design reference HTML 생성
- `select_and_generate_references` (line 522): pipeline Stage 1.7 entry
- `VISUAL_TYPE_KEYWORDS` (상수): 시각 유형별 매칭 keyword
핵심 함수 (block_selector):
- `load_catalog`, `_get_block_by_id`: utility
- `select_block_candidates` (line 89): Phase Q-2 main filtering — relation_type / 컨테이너 제약 / catalog 검증
- `select_fallback_candidates` (line 193): fallback
- `format_candidates_for_prompt` (line 236): Kei prompt formatter — `kei_client.py` 에서 사용
- `RELATION_TO_CATEGORIES`, `SIDEBAR_FORBIDDEN_CATEGORIES`, `BLOCKS_FORCING_FORMAT_CHANGE` (상수): Phase Q schema 매핑
#### 관련 §7-B 항목
**§1 §2 audit list**: `block_reference.py` / `block_selector.py` (A-2)
| §7-B | 직간접 | 영향 |
|---|---|---|
| **A-2** Catalog 확장 (frame_contracts + frame_partials) | (간접) | Phase Q `catalog.yaml` 로딩 / block 검색 패턴이 Phase Z catalog 확장 시 reference. 단 Phase Q catalog (block id + variant) vs Phase Z catalog (frame contract + frame partial) — schema 다름 |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `block_reference` / `block_selector` | Phase Z (현재) | 비교 |
|---|---|---|
| `_load_catalog` / `load_catalog` (catalog.yaml 로드 + mtime 캐시) | `frame_contracts.yaml` 로드 (Phase Z 자체) | **catalog schema 다름** (block id vs frame contract). Phase Z 자체 wrapper |
| `_get_block_by_id` (block_reference + block_selector 양쪽 중복) | frame_id → frame_contract 검색 (Phase Z) | abstraction 다름 |
| `_match_visual_type` / `VISUAL_TYPE_KEYWORDS` (expression_hint matching) | (Phase Z normal path 미존재) | Phase T-3 schema 특화. Phase Z 의 V4 evidence 매칭 path 와 *대체 path* |
| `_match_by_tags` (tag 매칭) | (Phase Z normal path 미존재) | deterministic catalog utility. pipeline.py 도 직접 호출 — Phase R' 전용 아님 |
| `select_reference_block` / `generate_design_reference` / `select_and_generate_references` | (Phase Z 에서 명시 폐기 — Phase R' reference path) | Phase R' AI 의 reference 자료 제공 — §2.8 `render_slide_from_html` / §2.9 `html_generator` 와 같은 Phase R' archive 영역 |
| `select_block_candidates` / `select_fallback_candidates` (Phase Q-2 filtering) | Phase Z V4 매칭 (master) | **dual path 위험** (Phase Q content 분석 기반 schema vs Phase Z V4 evidence). pipeline.py 에서 unused — Phase Q-2 legacy |
| `format_candidates_for_prompt` (Kei prompt formatter) | (Phase Z normal path 미존재 — AI 격리) | Kei flow integration utility. `kei_client.py` 에서 사용 |
#### 재사용 가능성
**block_reference.py**:
| 자산 | 분류 | 근거 |
|---|---|---|
| `_get_jinja_env` | **Reference Only** | Jinja2 env utility |
| `_load_catalog` | **Reference Only** | catalog 로드 + mtime 캐시 utility. block_selector / §2.8 renderer 와 중복. Phase Z catalog schema 다름 |
| `_get_block_by_id` | **Reference Only** | catalog 검색 utility. block_selector 와 중복 |
| `_match_visual_type` | **Reference Only** | deterministic pattern matching utility. Phase T-3 schema 특화이나 함수 자체는 결정론적 |
| `_match_by_tags` | **Reference Only** | deterministic catalog/tag matching utility. **pipeline.py 도 직접 호출 (line 228) — Phase R' 전용 아님** |
| `select_reference_block` | **Archive Candidate** | **high-level Phase R' reference path entry** — AI 가 reference 로 사용. CLAUDE.md 명시 폐기 영역 |
| `generate_design_reference` | **Archive Candidate** | Phase R' reference HTML 생성 high-level entry |
| `select_and_generate_references` | **Archive Candidate** | pipeline Stage 1.7 main entry — Phase R' orchestration |
| `VISUAL_TYPE_KEYWORDS` (상수) | **Reference Only** | deterministic matching table |
**block_selector.py**:
| 자산 | 분류 | 근거 |
|---|---|---|
| `load_catalog` | **Reference Only** | catalog 로드 utility. block_reference / §2.8 renderer 와 중복 |
| `_get_block_by_id` | **Reference Only** | catalog 검색 utility. block_reference 와 중복 |
| `select_block_candidates` | **Reference Only** | Phase Q-2 main filtering — 결정론적 + AI 무관. pipeline.py 에서 unused. Phase Z V4 매칭과 dual path 위험 — 직접 통합 X |
| `select_fallback_candidates` | **Reference Only** | fallback filtering. 같은 이유 |
| `format_candidates_for_prompt` | **Archive Candidate** | Kei prompt formatter — `kei_client.py` 에서 사용. deterministic 단 *Kei flow integration utility* (output 이 Kei AI input) |
| `RELATION_TO_CATEGORIES` / `SIDEBAR_FORBIDDEN_CATEGORIES` / `BLOCKS_FORCING_FORMAT_CHANGE` (상수) | **Reference Only** | Phase Q schema 매핑 dict. Phase Z V4 evidence 와 abstraction 다름 |
#### audit 판정
**Mixed (Reference Only heavy + 일부 high-level Phase R' / Kei prompt entries Archive)**.
§2.10 의 두 모듈 (block_reference + block_selector) = *block catalog + selection logic* 영역. 대부분 *결정론적 utility / pattern matching helper / catalog schema 매핑* 으로 **Reference Only**. Archive 영역은 *high-level Phase R' reference path entries* (block_reference 의 3 자산: `select_reference_block`, `generate_design_reference`, `select_and_generate_references`) + *Kei prompt formatter* (block_selector 의 `format_candidates_for_prompt`).
- §3 Salvage 적용 대상: **없음** (Salvage Candidate 0). Reference Only 자산은 Phase Z catalog 확장 / V4 매칭 보강 / Phase R' cleanup 등 별 axis 활성 시 *참고 여부만 별도 판단*
- 별도 surface:
- §1 audit lens 의 A-2 매핑은 *간접* (catalog 로딩 / block 검색 패턴 reference 정도)
- **block_reference 의 high-level entries = Phase R' archive 영역의 reference path** (§2.8 / §2.9 와 같은 Phase R' core 그룹)
- block_selector 는 **pipeline 에서 unused** (Phase Q-2 legacy) 단 `format_candidates_for_prompt``kei_client.py` 에서 used
- catalog 로드 + `_get_block_by_id` 중복 (block_reference + block_selector + §2.8 renderer 3 module) — cleanup 별 axis 후보
#### 후속 참고 사항 (본 audit 밖 surface)
K1. (Archive marker — Phase R' 영역) — block_reference 의 high-level entries (`select_reference_block` / `generate_design_reference` / `select_and_generate_references`) = Phase R' AI reference path. §2.8 / §2.9 와 같은 Phase R' archive 영역의 *reference 제공 layer*. §3 검토 대상 외.
K2. (Archive marker — Kei flow integration) — block_selector 의 `format_candidates_for_prompt` = Kei prompt formatter (`kei_client.py` 에서 used). Kei flow integration utility. §3 검토 대상 외.
K3. (Reference Only — legacy unused / dual path) — block_selector 의 main filtering (`select_block_candidates` / `select_fallback_candidates`) 는 pipeline.py 에서 unused (Phase T 가 block_reference 로 대체). Phase Z V4 매칭과 *dual path 위험*. 직접 통합 X 단 *결정론적 filtering 패턴* reference 가능.
K4. (Reference Only — deterministic utilities) — `_match_visual_type` / `_match_by_tags` / `VISUAL_TYPE_KEYWORDS` 등 deterministic pattern matching utilities. `_match_by_tags` 는 pipeline.py 에서 직접 호출 (line 228) — Phase R' 전용 아님. 별 axis 활성 시 reference.
K5. (cleanup 별 axis 후보) — catalog 로드 + `_get_block_by_id` 중복 (block_reference / block_selector / §2.8 renderer 3 module). Phase R' cleanup 또는 Phase Z catalog 확장 axis 활성 시 *중복 제거 별도 판단*.
K6. (factual note) — §1 audit lens 의 A-2 매핑 정확도: *간접* (catalog 로딩 / block 검색 패턴 reference 정도). §1 직접 정정은 별 axis (G2 + I6 + J5 누적 + K6).
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **Salvage Candidate**: 없음
- **Reference Only** 자산 (utilities + matching helpers + Phase Q-2 filtering + 상수): §0-A 원칙 10 따라 활성 axis 결정 = *별 axis* (Phase Z catalog 확장 / Phase R' cleanup / V4 매칭 보강 등). 활성 시 그 axis 의 SoT 따라 adapter / dual-write 기준 별도 결정. 본 §2.10 audit 단계의 dual-write 기준 적용 X.
- **Archive Candidate** (Phase R' reference path entries + Kei prompt formatter): §3 검토 대상 외.
> ⚠ **본 §2.10 audit 판정은 Phase Z normal path 기준의 후보 분류이며, `block_reference.py` / `block_selector.py` 는 §3 Salvage 적용 대상이 없다 (Salvage Candidate 0).** §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름. Reference Only 자산 (deterministic utility / matching helper / Phase Q-2 filtering / 상수) 은 별 axis 활성 시 *참고 여부만 별도 판단*. **block_reference 의 high-level entries (3 자산) = Phase R' archive 영역의 reference 제공 layer (§2.8 / §2.9 와 같은 Phase R' core 그룹). block_selector 의 `format_candidates_for_prompt` = Kei flow integration utility (Archive)**.
### 2.11 `pipeline.py` / `pipeline_context.py` (마지막)
#### 역할
§2 audit 의 *마지막 모듈* — Phase Q normal pipeline 의 **master orchestrator** 영역.
- **`pipeline.py`** (2096 lines): "Phase T: 11-Stage 파이프라인" — Stage 0 (MDX 표준화) ~ Stage 5 (서빙) orchestration. `generate_slide` (Phase T 현재) + `generate_slide_legacy` (Phase S 보존). Kei API + Claude Sonnet + Opus Vision 모두 호출
- **`pipeline_context.py`** (340 lines): "Phase T-0: 파이프라인 누적 컨텍스트 객체" — 12 Pydantic BaseModel + StageFailure + build_retry_feedback + create_context
**핵심 — pipeline.py 가 §2.1 ~ §2.10 모든 audit 모듈을 import / consume**:
- §2.1 `mdx_normalizer` (Stage 0)
- §2.2 `section_parser` (Stage 1A 후속)
- §2.3 `slide_measurer` (Stage 4 측정)
- §2.4 `fit_verifier` (Stage 1.5b retry)
- §2.5 `space_allocator` (Stage 1.5a container)
- §2.6 `content_editor.fill_content` (legacy Stage 3 slot fill)
- §2.7 `content_verifier.generate_with_retry` (Stage 4 검증 retry loop)
- §2.8 `renderer.render_slide_from_html` (Phase R' helper)
- §2.9 `html_generator` (transitively via §2.7 content_verifier)
- §2.10 `block_reference.select_and_generate_references` (Stage 1.7 entry) + `block_reference._match_by_tags` / `_load_catalog` (line 228 direct)
**pipeline.py = Phase Q + Phase R' + Phase T 의 *central orchestrator***. Phase Z 22-step normal path 와 *abstraction 완전 다름* (Phase Z = 결정론적 mapper, Phase Q/T = 11-stage AI orchestration).
핵심 함수 (pipeline.py):
- `run_stage` (line 52): 공통 stage 실행 패턴 (transform / validate / update / snapshot)
- `generate_slide` (line 120): Phase T 11-Stage main entry
- `_retry_kei` (line 1518): Kei API retry helper (P0 무한 루프 방지)
- `_save_step` (line 1551): step output JSON 저장
- `generate_slide_legacy` (line 1563): Phase S 보존 pipeline
- `_adjust_design` (line 1767): Kei AI 기반 design 조정
- `_review_balance` (line 1869): Kei AI 기반 balance 검토
- `_apply_adjustments` (line 1940): Kei judgment 기반 adjustments 적용
- `_build_overflow_context` (line 2012): overflow context dict 빌더
- `_convert_kei_judgment` (line 2044): Kei judgment → 내부 format 변환
- `_parse_json` (line 2082): Claude/Kei response JSON 파싱 (§2.6 / §2.9 와 중복 implementation)
핵심 자산 (pipeline_context.py):
- 12 Pydantic BaseModel: `PopupItem`, `NormalizedContent`, `Topic`, `PageStructure`, `Analysis`, `TextBudget`, `DesignBudget`, `ContainerInfo`, `FontHierarchy`, `BlockReference`, `StageError`, `PipelineContext`
- `PipelineContext` BaseModel + lifecycle methods (예: `save_snapshot` / `log_error` / `get_run_dir` / `get_role_content` 등)
- `StageFailure` (Exception)
- `build_retry_feedback`, `create_context` (functions)
#### 관련 §7-B 항목
**§1 §2 audit list**: `pipeline.py` (B-1), `pipeline_context.py` (audit list 직접 매핑 없음)
| §7-B | 직간접 | 영향 |
|---|---|---|
| **B-1** Zone-section assignment override | (간접 surface) | pipeline.py 가 orchestration entry — Stage Y 에서 page_structure 생성 흐름 보유. 단 *실제 composition planner / zone-section assignment override implementation* 영역과는 다름. *direct implementation* 아님 |
#### 현재 Phase Z 와 겹치는 영역
| Phase Q `pipeline.py` / `pipeline_context.py` | Phase Z (현재) | 비교 |
|---|---|---|
| `generate_slide` (Phase T 11-Stage main) | Phase Z = `phase_z2_pipeline` 22-step 결정론적 mapper | **abstraction 완전 다름**. Phase Q = AI orchestration (Kei + Claude + Opus). Phase Z = 결정론적 mapper. *fundamentally 다른 path* |
| `generate_slide_legacy` (Phase S 보존) | (Phase Z 폐기) | 더 오래된 AI orchestration |
| `run_stage` (common stage executor) | Phase Z 자체 stage runner | abstraction 다름 (transform/validate/update/snapshot pattern은 generic 단 PipelineContext schema 특화) |
| `_retry_kei` / `_adjust_design` / `_review_balance` / `_apply_adjustments` / `_convert_kei_judgment` | (Phase Z normal path 미존재 — AI 격리) | Kei AI 호출 기반 — Phase Z 본체 외 |
| `_save_step` / `_build_overflow_context` | Phase Z 자체 step artifact 저장 path / overflow context | abstraction 다름 (PipelineContext 기반) |
| `_parse_json` (line 2082) | (Phase Z 미존재 — AI 응답 parsing 영역) | §2.6 content_editor + §2.9 html_generator 와 중복 implementation |
| `pipeline_context.py` 12 BaseModel + `PipelineContext` lifecycle methods | Phase Z 자체 artifact schema | **abstraction 완전 다름**. Pydantic schema 자체는 deterministic 단 Phase T schema 특화 |
#### 재사용 가능성
**pipeline.py**:
| 자산 | 분류 | 근거 |
|---|---|---|
| `run_stage` (common stage executor) | **Reference Only** | transform/validate/update/snapshot pattern. Phase Z 자체 stage runner 있음. 직접 통합 X 단 *generic execution pattern* reference 가능 |
| `generate_slide` (Phase T 11-Stage main) | **Archive Candidate** | **Phase Q+R'+T master orchestrator**. Kei + Claude + Opus AI orchestration. Phase Z 22-step normal path 와 abstraction 완전 다름 |
| `_retry_kei` | **Archive Candidate** | Kei AI 호출 retry 인프라 |
| `_save_step` | **Reference Only** | step output JSON 저장 utility. Phase Z 자체 artifact saving path |
| `generate_slide_legacy` (Phase S 보존) | **Archive Candidate** | 더 오래된 Phase S AI orchestration |
| `_adjust_design` | **Archive Candidate** | Kei AI 기반 design 조정 |
| `_review_balance` | **Archive Candidate** | Kei AI 기반 balance 검토 |
| `_apply_adjustments` | **Archive Candidate** | Kei judgment 기반 adjustments 적용 |
| `_build_overflow_context` | **Reference Only** | overflow context dict 빌더. Phase Z 자체 overflow context 있음 |
| `_convert_kei_judgment` | **Archive Candidate** | Kei judgment 변환 — Kei flow 의존 |
| `_parse_json` | **Reference Only** | JSON parsing utility (§2.6 / §2.9 와 중복 implementation). Phase Z 직접 활성 axis 부재 |
**pipeline_context.py**:
| 자산 | 분류 | 근거 |
|---|---|---|
| `PopupItem` / `NormalizedContent` / `Topic` / `PageStructure` / `Analysis` / `TextBudget` / `DesignBudget` / `ContainerInfo` / `FontHierarchy` / `BlockReference` / `StageError` (11 BaseModel) | **Reference Only** | Phase T pipeline schema. Pydantic BaseModel. Phase Z 도 자체 artifact schema (별 schema, abstraction 다름) — 직접 통합 X. *schema 설계 패턴* reference 가능 |
| `PipelineContext` BaseModel + lifecycle methods (`save_snapshot` / `log_error` / `get_run_dir` / `get_role_content` 등) | **Reference Only** | Phase T pipeline 의 aggregate context + lifecycle methods. Phase Z 도 자체 status board / artifact path 있음. 직접 통합 X 단 *aggregate context 설계 패턴* reference 가능 |
| `StageFailure` (Exception) | **Reference Only** | stage failure 표현. Phase Z 도 자체 status board / failure recording. 직접 통합 X |
| `build_retry_feedback` | **Reference Only** | retry feedback message builder. Phase Z 자체 retry context 있음 |
| `create_context` | **Reference Only** | context factory. Phase T schema 특화 |
#### audit 판정
**Mixed (Archive heavy — Phase Q+R'+T master orchestrator + utility Reference Only + Phase T schema framework Reference Only)**.
`pipeline.py`*Phase Q / Phase R' / Phase T 의 master orchestrator* — §2.1 ~ §2.10 모든 audit 모듈을 import / consume. *Phase Z 22-step normal path 와 abstraction 완전 다름* (결정론적 mapper vs AI orchestration). Main orchestration 함수 (`generate_slide` / `generate_slide_legacy` / `_retry_kei` / `_adjust_design` / `_review_balance` / `_apply_adjustments` / `_convert_kei_judgment`) = **Archive Candidate**. Utility 함수 (`run_stage` / `_save_step` / `_build_overflow_context` / `_parse_json`) = **Reference Only**.
`pipeline_context.py`*Phase T pipeline 의 schema framework* — Pydantic BaseModel + `PipelineContext` lifecycle methods. Phase Z 도 자체 artifact schema 있음 (abstraction 다름) — 직접 통합 X 단 *schema 설계 패턴* reference 가능. 전체 **Reference Only**.
- **§3 Salvage 적용 대상: 없음** (Salvage Candidate 0)
- 별도 surface:
- §1 audit lens 의 B-1 매핑은 *간접 surface* — pipeline.py 가 orchestration entry (Stage Y page_structure 생성 흐름 보유). 단 *실제 composition planner / zone-section assignment override* 와는 다름. *direct implementation* 아님
- **pipeline.py = Phase Q+R'+T master orchestrator** (§2.1~§2.10 모든 audit 모듈 consume). Phase Z 본체 와는 *fundamentally 다른 abstraction path*
- 누적 §1 매핑 정정 weight (§2.6 + §2.8 + §2.9 + §2.10 + §2.11) — §1 정정 별 axis trigger 충분
- utility 중복 (`_parse_json` 등) cleanup 별 axis 후보
#### 후속 참고 사항 (본 audit 밖 surface)
L1. (Archive marker — 핵심) — **pipeline.py = Phase Q+R'+T master orchestrator**. 11-Stage AI orchestration (Kei + Claude + Opus). Main orchestration 함수 (`generate_slide` / `generate_slide_legacy` / `_retry_kei` / `_adjust_design` / `_review_balance` / `_apply_adjustments` / `_convert_kei_judgment`) 모두 Archive Candidate. CLAUDE.md 의 AI 격리 invariant + Phase Z 22-step normal path 와 abstraction 완전 다름. §3 검토 대상 외.
L2. (별 axis 후보 — utility reference) — pipeline.py 의 deterministic utility (`run_stage` / `_save_step` / `_build_overflow_context` / `_parse_json`) 는 Reference Only. Phase Z 자체 stage runner / artifact saving / overflow context 있어 직접 통합 X 단 *generic pattern* reference 가능.
L3. (별 axis 후보 — schema framework reference) — pipeline_context.py 의 Pydantic BaseModel framework + `PipelineContext` lifecycle methods (`save_snapshot` / `log_error` / `get_run_dir` / `get_role_content` 등) 는 Reference Only. Phase T schema 특화 단 *aggregate context + lifecycle 설계 패턴* reference 가능. Phase Z 도 자체 artifact schema 있음 — 직접 통합 X.
L4. (cleanup 별 axis 후보) — `_parse_json` utility 가 pipeline.py + §2.6 content_editor + §2.9 html_generator 3 module 에 중복 implementation. Phase R' cleanup 또는 Phase Z utility 통합 axis 활성 시 *중복 제거 별도 판단*. 누적 cleanup 별 axis (§2.10 의 catalog 로드 + `_get_block_by_id` 중복과 같은 패턴).
L5. (factual note — §1 매핑 누적) — §1 audit lens 의 B-1 매핑 정확도:
- pipeline.py: *간접 surface* — orchestration entry 로 page_structure 생성 흐름 보유. 단 *실제 composition planner / zone-section assignment override* 와는 다름. *direct implementation* 아님
- 누적 §1 매핑 정정 weight: §2.6 (B-1/B-2 content_editor) + §2.8 (A-3/A-4 renderer) + §2.9 (A-3/A-4 html_generator) + §2.10 (A-2 block_ref/selector) + §2.11 (B-1 pipeline) — §1 정정 별 axis 의 trigger 충분
#### Salvage Plan 검토 대상 dual-write 기준 (§3 에서 재확정)
- **Salvage Candidate**: 없음
- **Reference Only** 자산 (utility + pipeline_context schema framework): §0-A 원칙 10 따라 활성 axis 결정 = *별 axis* (Phase Z stage runner 확장 / artifact saving 보강 / Pydantic schema 패턴 reference 등). 활성 시 그 axis 의 SoT 따라 adapter / dual-write 기준 별도 결정. 본 §2.11 audit 단계의 dual-write 기준 적용 X
- **Archive Candidate** (Phase Q+R'+T master orchestration): §3 검토 대상 외
> ⚠ **본 §2.11 audit 판정은 Phase Z normal path 기준의 후보 분류이며, `pipeline.py` 는 §3 Salvage 적용 대상이 없다 (Salvage Candidate 0).** §0-A 의 10 원칙 + §0-0 의 분류 기준 + §0-B Audit 범위 lock + AI 격리 invariant 모두 따름. Reference Only 자산 (deterministic utility + Phase T schema framework) 은 별 axis 활성 시 *참고 여부만 별도 판단* (직접 통합 X). **`pipeline.py` = Phase Q+R'+T master orchestrator (§2.1~§2.10 consume) — Phase Z 22-step normal path 와 abstraction 완전 다름**.
---
## 3. Salvage Plan
> 모든 Salvage Plan 은 **§0-A 원칙** 을 따른다. 특히 **Salvage Candidate 적용 항목은 adapter + dual-write 검증 (원칙 3 + 9) 을 통과한 뒤** 기존 path 를 대체한다. 각 Salvage Candidate 적용 항목별 *dual-write 통과 기준* (어떤 artifact 필드가 일치해야 하는지) 은 적용 axis 활성 시 별 turn 에서 확정.
>
> §2.1~§2.11 audit (2026-05-12 완료) 합산 — Salvage Candidate = **8 후보 묶음** (§2.1~§2.5 SoT, §2.6~§2.11 = 0). §1 lens 직접 매핑 4 묶음 + A-3 conditional 1 묶음 + 별 axis Step 16/17 retry 3 묶음. AI / Kei / Phase R' 흐름 자산은 §2.X audit 에서 Archive Candidate 분류 — 본 §3 적용 대상 외.
### 3-A. §1 lens 항목별 Phase Q 자산 정리
| Phase Z 항목 | 가져올 Phase Q 자산 | 방식 | 후속 axis |
|---|---|---|---|
| **A-1** Stage 0 normalize | `mdx_normalizer.normalize_mdx_content` (전체 4 Layer) + `section_parser.extract_major_sections` + `extract_conclusion_text` (chained — §2.1 + §2.2 SoT) | **Salvage** (adapter + dual-write 검증 전제) | A-1 통합 axis |
| **A-2** Catalog 확장 | 없음 (§2.10 Salvage 0) | **새로 만들기** (frame_contracts + frame_partials catalog) | A-2 catalog 구축 axis |
| **A-3** Frame preview 일관성 | `slide_measurer.capture_slide_screenshot` | **Salvage 후보** (A-3 구현 axis 활성 시 dual-write 검증) | A-3 구현 axis |
| **A-4** slide-base iframe mode | 없음 (§2.9 Salvage 0) | **새로 만들기** (slide-base.html conditional CSS — embedded vs standalone) | A-4 보강 axis |
| **A-5** V4 fallback | 없음 (§2.4 `calculate_fit` 통째 Migrate 금지 — dual path 위험) | **새로 만들기** (Phase Z Step 9 / Step 16 확장) | A-5 V4 fallback axis |
| **A-6** Zone 좌표 export | `slide_measurer._MEASURE_SCRIPT` JS extension (`getBoundingClientRect()`) | **Salvage** (Phase Z visual_check JS 보강 + dual-write 검증) | A-6 JS 보강 axis |
| **B-1** Zone-section override | 없음 (§2.11 / §2.6 Salvage 0) | **새로 만들기** (CLI 인자 + pipeline override path) | B-1 신설 axis |
| **B-2** Edited HTML → MDX | 없음 (§2.7 Salvage 0) | **새로 만들기** (글벗 `fmt_slide.html_to_slide_mdx` 참조 가능) | B-2 신설 axis |
| **B-3** Sub-section drag drop | 없음 (§2.2 sub-section schema 는 Reference Only — dual path 위험) | **새로 만들기** (Phase Z section_id schema 확장) | B-3 신설 axis |
| **B-4** 다른 layout zone-geometry | 없음 (§2.5 `calculate_container_specs` 등 Reference Only — dual path 위험) | **새로 만들기** (build_layout_css 분기 확장) | B-4 보강 axis |
| **D-1** filtered_section_reasons UI | Phase Q audit 외 — frontend 신규 구현 | — | D-1 frontend axis |
| **D-2** Frame min_height 표시 | 없음 (§2.4 fit_verifier 간접) | **새로 만들기** (catalog `min_height_px` 직접 참조 + frontend resize hint) | D-2 frontend axis (catalog 참조) |
### 3-B. 별 axis — Step 16/17 retry 정밀화 (22-step 안 deterministic 보강)
> §1 lens 외 항목 (Phase Z Step 16 `router_decision` retry action 의 실 구현 후보). **AI fallback 아님** — Step 16 router / Step 17 retry trace 의 *deterministic* 보강 path. 22-step 안. AI 격리 invariant 안 (AI 호출 X).
| 별 axis action | 가져올 Phase Q 자산 | 방식 | 후속 axis |
|---|---|---|---|
| Step 16 `zone_ratio_retry` 실 구현 | `fit_verifier.redistribute` (zone 안 role 간 px 재배분) | **Salvage** (deterministic) | Step 16/17 retry 정밀화 axis |
| Step 16 `glue_compression` action (신설) | `space_allocator.compute_glue_css_overrides` + `calculate_glue_absorption` + `SPACING_GLUE`/`GlueSpec` (LaTeX 글루 모델) | **Salvage** (deterministic) | Step 16/17 retry 정밀화 axis |
| Step 16 `font_size_retry` action (신설) | `space_allocator.find_fitting_font_size` + `FONT_SIZE_STEPS` (이진 탐색) | **Salvage** (deterministic) | Step 16/17 retry 정밀화 axis |
---
## 4. 우선순위 재정렬
> **검증 기준**: 특정 MDX / 특정 frame 결과를 고정하지 않는다. backend 보강 axis 는 샘플별 PASS/FAIL, coverage, trace 설명 가능성을 확인한다. catalog 확장이나 V4 개선으로 선택 frame 이 바뀌는 것은 허용하며, 하드코딩된 MDX 03 baseline 으로 변화를 막지 않는다. 검증 대상 sample 은 axis 적용 시 별 turn 에서 결정.
>
> audit 결과 → 어느 항목이:
> - **Salvage 적용 시 빠르게 끝남** (작은 작업) → 우선순위 ↑
> - **새로 만들기** (큰 작업) → 우선순위 ↓ 또는 분해
> - **별 axis** (§1 lens 밖, deterministic 보강) → 별도 그룹
>
> 후속 작업 = [`PHASE-Z-ROADMAP.md`](PHASE-Z-ROADMAP.md) §5 / §7-B 반영.
### 4-A. 우선순위 ↑ (Salvage 적용 시 빠르게 — 작은 작업)
- **A-1 Stage 0 normalize 통합** — §2.1+§2.2 chained Salvage (adapter + dual-write 검증)
- **A-6 Zone 좌표 export** — §2.3 `_MEASURE_SCRIPT` JS extension Salvage (`getBoundingClientRect()` 추가 + step08 export 1 layer)
### 4-B. 우선순위 중 (새로 만들기 — 핵심 path)
- **A-2 Catalog 확장 (핵심 unblocker — 작업량 큼)** — frame_contracts + frame_partials 32 frame 등록. 다른 axis unblock. *risk note: catalog 확장 시 frame 선택 변경 허용 — 단 기존 성공 샘플이 FAIL 로 떨어지는지와 trace 설명 가능성 확인*
- **A-5 V4 fallback** — Phase Z Step 9 / Step 16 확장 (`calculate_fit` 통째 Migrate 금지 — dual path 위험). *risk note: fallback path 추가 시 status semantics 일관성 검토 — 신설 status 의미 명시*
- **B-1 Zone-section override** — CLI 인자 + pipeline override path (backend path)
- **B-2 Edited HTML → MDX** — 글벗 `fmt_slide.html_to_slide_mdx` 참조 가능 (backend path)
### 4-C. 우선순위 ↓ (새로 만들기 — 별 axis 활성 시 또는 분해)
- **A-3 Frame preview 일관성** — §2.3 `capture_slide_screenshot` Salvage 후보 (A-3 구현 axis 활성 시)
- **A-4 slide-base iframe mode** — 새로 만들기 conditional CSS (embedded vs standalone)
- **B-3 Sub-section drag drop** — Phase Z section_id schema 확장 (backend schema)
- **B-4 다른 layout zone-geometry** — build_layout_css 분기 확장 (backend layout)
- **D-1 filtered_section_reasons UI** — frontend 신규 (D-1 frontend axis)
- **D-2 Frame min_height 표시** — catalog `min_height_px` 직접 참조 + frontend resize hint
### 4-D. 별 axis — Step 16/17 retry 정밀화 (22-step 안 deterministic 보강)
- §2.4 `redistribute` + §2.5 glue (`compute_glue_css_overrides` + `calculate_glue_absorption` + `SPACING_GLUE`/`GlueSpec`) + §2.5 font compression (`find_fitting_font_size` + `FONT_SIZE_STEPS`) — 3 묶음 Salvage (deterministic)
- A-5 V4 fallback 과 분리 — Step 16 `router_decision` action 의 실 구현
- **AI fallback 아님** — AI 격리 invariant 안 (AI 호출 X)
---
## 5. 진행 로그
### 5-0. 진행 로그 정책 (2026-05-11 lock)
본 §5 진행 로그는 audit 진행 history 의 **불가역 record** 로 보존된다.
- **과거 entry 표현 보존**: 2026-05-11 이전 entry 의 표현 (`Migrate` / `Mixed (Migrate + Reference)` / `진짜 fix` / `적극 통합` 등) 은 *당시 audit 표현* 그대로 보존. **수정 X**.
- **재분류는 인라인 태그로**: 각 과거 entry 옆에 *현재 분류 기준 (§0-0) 으로의 재매핑 태그* 만 추가 (2-f 에서 실행).
- **본 entry 는 정정 pass 후 갱신됨 ↓ 같은 호환 marker** 도 보존 (의미 — 후속 entry 가 갱신본 의미).
- **재분류 매핑 (legacy → §0-0 분류)**:
| legacy 표현 | §0-0 분류 | 비고 |
|---|---|---|
| `Migrate` (결정론적 + AI 무관) | **Salvage Candidate** | 적용 시 dual-write 전제. §3 검토 후보. *결정 ≠ 통합* |
| `Migrate` (Kei / AI 흐름 의존) | **Archive Candidate** | AI 격리 invariant. Phase Z 본체 도 AI repair fallback 도 salvage 대상 아님 (Phase Q Kei 자산과 단절) |
| `Mixed (Migrate + Reference)` | 자산별 분류 | Salvage / Reference Only / Archive 자산 mix. 각 §2 module 의 "재사용 가능성" 표 참조 |
| `진짜 fix` | "적용 시 path 후보" | audit 판정 ≠ 적용 결정. *후보* 의미로 해석 |
| `적극 통합` | "Salvage Candidate (적용 시 dual-write)" | 적용 결정은 §3 |
| `통째 Migrate 금지` | "dual path 위험 — 통째 적용 X" | §0-A 원칙 8 (Reference 직접 연결 X) 적용 |
| `Kei 통합` / `Kei 통합 path` | **Archive Candidate** | Kei persona 꼭지 / 구조 / 강조 결정 흐름. Phase Z 본체 도 AI repair fallback 도 salvage 대상 아님 |
- **본 정책은 §0-A 10 원칙 + §0-0 분류 기준 + AI 격리 invariant 모두 따른다.**
### 5-1. 진행 로그
| 날짜 | axis | 상태 |
|---|---|---|
| 2026-05-08 | §0 / §1 작성 | 완료 |
| 2026-05-08 | §2.1 mdx_normalizer.py audit | 완료 — **Migrate**. B1~B8 후속 작업 정의 *[재분류: Migrate → Salvage Candidate (결정론적 + AI 무관, §2.1 SoT)]* |
| 2026-05-08 | §2.2 section_parser.py audit | 완료 — **Mixed (Migrate + Reference)**. C1~C7 후속 작업 정의. mdx_normalizer 와 chained 통합 결정 *[재분류: Mixed → 자산별 분류 (§2.2 SoT — Salvage + Reference Only + Archive)]* |
| 2026-05-08 | §0-A Salvage 원칙 lock (10 원칙) + §3 머리글 + ROADMAP §5 link | 완료 — 정책 lock |
| 2026-05-09 | §2.3 slide_measurer.py audit | 완료 — **Mixed (Migrate JS only + Reference)**. JS 의 `getBoundingClientRect` 추가가 A-6 핵심. D1~D5 후속 작업 정의. dual path 회피 — 통째 Migrate 금지 *[재분류: Mixed → 자산별 분류 (§2.3 SoT). "통째 Migrate 금지" = dual path 위험 (§0-A 원칙 8)]* |
| 2026-05-09 | §2.4 fit_verifier.py audit | 완료 — **Reference (대부분) + Migrate (별 axis 1: V-3 redistribute)**. E1~E6 후속 작업. dual path 회피 — calculate_fit 통째 Migrate 금지. A-5 V4 fallback 의 진짜 fix 는 Phase Z Step 9/16 확장 (fit_verifier 무관). D-2 는 catalog min_height_px 직접 참조 (작은 작업) *[재분류: Reference + Migrate → 자산별 분류 (§2.4 SoT). "진짜 fix" = 적용 시 path 후보. "통째 Migrate 금지" = dual path 위험]* |
| 2026-05-11 | §2.5 space_allocator.py audit | 완료 (초안) — Reference (대부분) + Migrate 강 후보 (별 axis: glue + font compression). 본 entry 는 정정 pass 후 갱신됨 ↓ *[재분류: Migrate 강 후보 → Salvage Candidate (별 axis Step 16/17 retry, deterministic). 상세 정정은 2026-05-11 재분류 pass entry 참조]* |
| 2026-05-11 | **audit wording + AI isolation 재분류 pass** | 완료 — §0-0 자산 분류 기준 추가 (Salvage / Reference Only / Archive Candidate) + AI 격리 invariant 명시 + audit 판정 ≠ 적용 결정 명시. §2.1 / §2.2 / §2.3 / §2.4 / §2.5 모두 정정: "Migrate / Migrate 강 후보 / 적극 통합 / 진짜 fix / 결정" 표현 제거. Kei AI 흐름 의존 자산 (`map_topics_to_sections`, `format_measurement_for_kei`, `analyze_enhancements` V-7~V-10 / `build_escalation_report`, `calculate_container_specs` / `build_containers_type_b` / `calculate_font_hierarchy` / `calculate_dynamic_ratio` / `calculate_design_budget` / `calculate_char_budget` / `calculate_trim_chars`, `measure_candidate_block`, `detect_component_popups`) 을 모두 **Archive Candidate** 로 재분류. Salvage Candidate 는 8 개 자산 (`normalize_mdx_content`, `extract_major_sections`, `extract_conclusion_text`, `_MEASURE_SCRIPT` JS extension, `capture_slide_screenshot`, `redistribute`, `compute_glue_css_overrides`+`calculate_glue_absorption`, `find_fitting_font_size`) — 모두 §3 검토 후보 *[후속 갱신: 2-c hygiene fix 2 의 F-3 함수별 재분류 (2026-05-11) 에 따라 `calculate_design_budget` / `calculate_char_budget` / `calculate_budgets_for_candidates` / `calculate_trim_chars` 는 Reference Only 로 재분류됨. §2.5 SoT 참조]* |
| 2026-05-11 | 정정 pass 2 계획 확정 | 대기 — B-1~B-5 결정 적용. sub-axis a~g 로 진행. 실행은 다음 turn |
| 2026-05-11 | 정정 pass 2 본체 실행 (2-c hygiene fix 2 + 2-d / 2-e / 2-f / 2-g) | 완료 — L1~L4 boundary lock 반영. §0-B Audit 범위 lock 추가, §2.5 F-3 함수별 재분류 반영 (`calculate_design_budget` / `calculate_char_budget` / `calculate_budgets_for_candidates` / `calculate_trim_chars` → Reference Only), §3 / §4 legacy 용어 정리, §5-1 인라인 재분류 태그 5 entry append, 13 pattern context-aware grep 검증 수행. 산출 추가: `PHASE-Q-AUDIT-PASS-2-EXECUTION-PLAN.md`, `memory/feedback_scope_qualified_verification.md` |
| 2026-05-12 | §2.6 content_editor.py audit | 완료 — Archive Candidate (module-level). Kei AI direct slot-fill flow. §3 검토 대상 외. 별도 surface: §1 B-1/B-2 매핑 부정확 (G2 별 axis), AI repair fallback infra reference 여부 별 axis (G3) |
| 2026-05-12 | §2.7 content_verifier.py audit | 완료 — Mixed (Reference Only + Archive Candidate). Salvage Candidate 0. utility 다수 결정론적이나 Phase Z normal path 직접 빈칸 채움 부재 → Reference Only. Kei artifact 검출 + Kei AI generation retry loop = Archive. L4 Selenium / L5 Opus vision = 본 파일 구현 부재 (header documentation only). §3 적용 대상 없음. 별도 surface: §1 B-2 후속 매핑 간접, H1~H3 reference axis 후보, H4~H5 Archive marker, H6 L4/L5 factual note |
| 2026-05-12 | §2.8 renderer.py audit | 완료 — Mixed (Reference Only + Archive Candidate). **`render_slide_from_html` (Phase R') = Archive (CLAUDE.md 명시 폐기 — AI 가 HTML 구조 직접 생성 금지)**. Salvage Candidate 0. 나머지 Jinja2 rendering utility / catalog 로드 / template resolution = Reference Only (Phase Q schema 특화, abstraction 다름). §3 적용 대상 없음. 별도 surface: §1 A-3 간접 / A-4 영향면 있으나 conditional CSS 분기 구현 부재, I1~I4 구현/보강 axis 후보, I5 Phase R' Archive marker, I6 §1 매핑 정확도 factual note |
| 2026-05-12 | §2.9 html_generator.py audit | 완료 — Mixed (Archive heavy — Phase R' core). **`html_generator.py` = Phase R' (AI HTML 직접 생성) main implementation (CLAUDE.md 명시 폐기)**. Salvage Candidate 0. AI HTML generation path (`generate_slide_html` / `_call_claude` / `regenerate_area` / `build_area_prompt` / Phase T supplement / `_LEGACY_*` prompts) = Archive Candidate. deterministic helpers (`normalize_mdx` / `_slice_mdx_sections` / `_get_definitions` / `_get_conclusion` / `_calc_indent` / `_replace_img_placeholder` 등) = Reference Only (§2.1 / §2.2 에 더 직접적인 SoT 후보 존재). §3 적용 대상 없음. 별도 surface: §1 A-3/A-4 매핑 부정확, J1 Phase R' core Archive marker, J2 §2.8 연결, J3 utility 중복 cleanup axis, J4 general helper reference axis, J5 §1 매핑 factual note |
| 2026-05-12 | §2.10 block_reference.py / block_selector.py audit | 완료 — Mixed (Reference Only heavy + 일부 high-level Phase R' / Kei prompt entries Archive). Salvage Candidate 0. block_reference utilities (`_get_jinja_env` / `_load_catalog` / `_get_block_by_id` / `_match_visual_type` / `_match_by_tags` / `VISUAL_TYPE_KEYWORDS`) + block_selector utilities + filtering (`load_catalog` / `_get_block_by_id` / `select_block_candidates` / `select_fallback_candidates` / 상수) = Reference Only. **block_reference high-level entries (`select_reference_block` / `generate_design_reference` / `select_and_generate_references`) = Phase R' reference path Archive (§2.8 / §2.9 와 같은 Phase R' core 그룹)**. block_selector `format_candidates_for_prompt` = Kei prompt formatter Archive (`kei_client.py` used). §3 적용 대상 없음. 별도 surface: §1 A-2 매핑 간접, K1 Phase R' reference path Archive marker, K2 Kei prompt formatter Archive marker, K3 block_selector legacy unused + dual path, K4 deterministic utilities reference axis, K5 catalog/_get_block_by_id 중복 cleanup axis, K6 §1 매핑 factual note |
| 2026-05-12 | §2.11 pipeline.py / pipeline_context.py audit (마지막) | 완료 — Mixed (Archive heavy — Phase Q+R'+T master orchestrator + utility Reference Only). **pipeline.py = Phase T 11-Stage AI orchestration main implementation (Phase Q+R'+T 모듈 모두 consume)**. Salvage Candidate 0. Main orchestration (`generate_slide` / `generate_slide_legacy` / `_retry_kei` / `_adjust_design` / `_review_balance` / `_apply_adjustments` / `_convert_kei_judgment`) = Archive. utility (`run_stage` / `_save_step` / `_build_overflow_context` / `_parse_json`) = Reference Only. pipeline_context.py = Reference Only (Pydantic schema + PipelineContext lifecycle methods). §3 적용 대상 없음. 별도 surface: §1 B-1 매핑 간접 (pipeline orchestration entry, direct composition planner 아님), 누적 §1 매핑 정정 axis weight ↑, utility 중복 (_parse_json 등) cleanup axis, L1 master orchestrator Archive marker, L2~L3 utility/schema reference axis, L4 cleanup axis, L5 §1 factual note |
| 2026-05-12 | §3 Salvage Plan 작성 | 완료 — §2.1~§2.11 audit 합산. Salvage Candidate **8 후보 묶음** lock: §1 lens 직접 매핑 4 (§2.1+§2.2 A-1 chained / §2.3 A-6) + A-3 conditional 1 (§2.3 `capture_slide_screenshot`) + 별 axis Step 16/17 retry 3 (§2.4 `redistribute` + §2.5 glue + §2.5 font compression). 구조 = §3-A (§1 lens 12 rows) + §3-B (별 axis 3 rows) — (γ) 중간안. 3-C Archive 명시 제외 / 3-D dual-write 상세는 §2 결론 중복 + 적용 axis 활성 시 작업 (over-engineering 회피). prelude 1 줄 — 8 후보 묶음 inventory |
| 2026-05-12 | §4 우선순위 재정렬 + ROADMAP 갱신 | 완료 — guardrail 박힘 (특정 MDX / frame 고정 금지, process 기준 — PASS/FAIL + coverage + trace 설명 가능성). 4 그룹 분류: **4-A ↑** (A-1 + A-6 Salvage 빠른) / **4-B 중** (A-2 핵심 unblocker — 작업량 큼 + A-5 + B-1 + B-2 새로 만들기 핵심) / **4-C ↓** (A-3 + A-4 + B-3 + B-4 + D-1 + D-2) / **4-D 별 axis** Step 16/17 retry deterministic 보강. A-2/A-5 risk note 박힘 (frame 변경 허용 + trace 설명 / fallback status semantics 명시). PHASE-Z-ROADMAP.md §5 inline (audit 결과) + §7-B mini summary table (12 lens + Step 16/17 retry 한 줄) |
### 정정 pass 2 실행 원칙
- 과거 log는 보존하고 재분류 태그만 추가
- "적용 시" dual-write 표현으로 정정
- negation context는 보존
- grep은 positive misuse만 확인
- Kei persona 흐름 자산 = Archive (Phase Z 본체 도 AI repair fallback 도 salvage 대상 아님). AI repair fallback 은 별도 axis 에서 새 설계, Phase Q 자산과 단절
### 정정 pass 2 sub-axis (진행 상태)
- a. 진행 로그 정책 반영 ✅ 완료 (2026-05-11, §5-0)
- b. §0 / §0-A / §1 용어 정리
- c. §2.1 / §2.2 stale wording 정리
- d. §2.3 / §2.4 / §2.5 stale wording 정리
- e. §3 / §4 용어 정리
- f. 진행 로그 재분류 태그 추가
- g. context-aware grep 검증