docs: start Phase Q audit and lock salvage policy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
344
docs/architecture/PHASE-Q-AUDIT.md
Normal file
344
docs/architecture/PHASE-Q-AUDIT.md
Normal file
@@ -0,0 +1,344 @@
|
||||
# Phase Q Audit & Salvage
|
||||
|
||||
**작성일**: 2026-05-08 (frontend 통합 session 직후 첫 번째 audit axis)
|
||||
**문서 역할**: Phase Z 보완 항목을 *기준 (lens)* 으로 기존 Phase Q 코드의 **Keep / Migrate / Reference / Delete** 결정.
|
||||
**진행 상태**: §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 에 비슷한 코드가 있었을 가능성이 큼. **무엇을 새로 만들고 / 무엇을 가져오고 / 무엇을 참고만 하고 / 무엇을 버릴지** 결정하는 것이 본 audit 의 목적.
|
||||
|
||||
진행 방식:
|
||||
1. **§1 Audit Lens** — Phase Z 보완 항목 (§7-B 의 A/B/D 그룹) 별 *목적 / input / output / Phase Q 후보 파일* 정리. 이게 audit 의 기준.
|
||||
2. **§2 모듈별 Audit** — Phase Q 모듈 10 개를 § 1 의 lens 로 검토. 결정 = Keep / Migrate / Reference / Delete.
|
||||
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 에서 처리.
|
||||
|
||||
---
|
||||
|
||||
## 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. **Migrate 시 dual-write / shadow 검증을 먼저 한다.**
|
||||
10. **Reference 항목은 활성화 axis 가 없으면 나중에 Delete 후보로 재분류한다.**
|
||||
|
||||
> 꼬임 방지의 핵심 = **3 (adapter)** + **4 (artifact schema 보존)** + **9 (dual-write 검증)**. 나머지 7 개는 그 위의 안전장치.
|
||||
|
||||
---
|
||||
|
||||
## 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` | 높음 |
|
||||
| **A-3** | Frame preview png 일관성 | 모든 catalog frame 의 일관된 preview.png 자동 생성 (현재 figma_previews 우회) | frame partial HTML + assets | `figma_to_html_agent/blocks/{frame_id}/preview.png` | `renderer.py`, `html_generator.py` (selenium 캡처 흔적 추정) | 중 |
|
||||
| **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) | `html_generator.py` | 중 |
|
||||
| **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`, `content_editor.py` | 중 |
|
||||
| **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`, `content_editor.py` | 중 |
|
||||
| **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` (B-1, B-2)
|
||||
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 와 겹치는 영역** : ...
|
||||
> - **재사용 가능성** : ...
|
||||
> - **결정** : Keep / Migrate / Reference / Delete
|
||||
> - **후속 작업** : ...
|
||||
> ```
|
||||
|
||||
### 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]` 마커. 남은 HTML 태그 제거. 연속 빈 줄 정리. |
|
||||
|
||||
검증 (`validate_stage0`):
|
||||
- `clean_text` 비어있음 = FATAL
|
||||
- 원본 대비 텍스트 보존율 < 30% = FATAL
|
||||
- 이미지 수 / popup 수 대조 = ADJUSTABLE
|
||||
|
||||
#### 관련 §7-B 항목
|
||||
|
||||
| §7-B | 직간접 | 영향 |
|
||||
|---|---|---|
|
||||
| **A-1** Stage 0 normalize 통합 | **직접** | 본 모듈 자체가 A-1 의 *진짜 fix*. 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
|
||||
|
||||
#### 결정
|
||||
|
||||
**Migrate (적극 통합)**.
|
||||
|
||||
이유:
|
||||
1. Phase Z 의 `parse_mdx` 가 *너무 단순* — A-1 문제의 직접 원인
|
||||
2. mdx_normalizer 가 *self-contained + 검증 통과* (Phase Q 에서 정상 동작 흔적). 새로 만들 이유 0
|
||||
3. schema 어댑터만 작성하면 frontend 의 `## __ROOT__` 임시 우회 즉시 제거
|
||||
4. popup / image / table 추출은 Phase Z 의 *현재 약한 영역* (Step 3/4) 의 진짜 input. 통합 시 Step 3/4 진행률 자연 상승
|
||||
|
||||
#### 후속 작업 (B 가 §3 Salvage Plan 으로 넘어감)
|
||||
|
||||
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 (현재 frontend `parseMdxText` 와 동일 로직). MdxSection 에 `sub_sections: list[MdxSection]` 필드 추가
|
||||
B3. **`parse_mdx` 호출 site 변경** — 단순 정규식 path 폐기. `normalized = normalize_mdx_content(text)` 호출 후 어댑터로 sections 변환
|
||||
B4. **step02 artifact 확장** — `popups`, `images`, `tables`, `clean_text` trace 추가. `validate_stage0` 결과를 step02 의 errors 로 기록
|
||||
B5. **Frontend `## __ROOT__` 우회 제거** — backend section.raw_content 가 이미 정리된 상태로 들어오니 frontend `parseMdxText` 의 prefix hack 제거. `loadRun` 의 `subParsed` 도 backend 의 sub_sections 를 직접 받음
|
||||
B6. **Step 3 `extract_content_objects` 보강** — normalized 의 `tables` / `images` 도 ContentObject 로 변환 (transform_table / image_block). list 항목은 markdown_it AST 의 bullet_list_open/close + depth 정보 활용해서 *N items 로 분할*. 이로 03-1 같은 case (3 bullet → 3 items) 가 자동 통과
|
||||
B7. **A-1 임시 우회 제거 → memory 의 `project_phase_z_normalize_gap.md` 업데이트** (해소 표시)
|
||||
B8. **검증 — MDX 03 fresh run regression check + samples/uploads 의 HTML-heavy 03 으로 fresh run** (이전에 PARTIAL_COVERAGE 였던 case 가 PASS 로 바뀌는지)
|
||||
|
||||
작업 분량: B1+B2+B3 = 한 axis (작음). B4+B5 = 한 axis (작음). B6 = 별도 axis (Step 3 본격 보강 — 큼). B7+B8 = 검증 axis.
|
||||
|
||||
### 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 |
|
||||
| (별 axis 잠재) Kei 꼭지 통합 | 잠재 | `map_topics_to_sections` — Kei 통합 시 사용 가능 |
|
||||
|
||||
#### 현재 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 이 1~2 ContentObject 로 뭉치는 것의 *진짜 fix* 가 여기. 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 매칭) | Kei 통합 시 사용 |
|
||||
|
||||
#### 재사용 가능성
|
||||
|
||||
**chained 통합 필수 — `mdx_normalizer + section_parser` 둘이 한 axis**.
|
||||
|
||||
분류:
|
||||
| 함수 | 결정 |
|
||||
|---|---|
|
||||
| `extract_major_sections` | **Migrate** — Stage 0 통합 시 mdx_normalizer 와 같이 통합 |
|
||||
| `classify_group_relations` (Y-13b) | **Reference** — V4 path 와 orthogonal. 별 axis 에서 V4 + schema 점수 결합 시 활용 |
|
||||
| `_classify_sub_types` (B-1) | **Reference (강력 후보)** — Phase Z step03 보강 시 그대로 활용 가능 |
|
||||
| `SCHEMA_RECIPE_MAP` / `KIND_SUBTYPE_COMPAT` | **Reference** — Phase Z catalog 확장 (A-2) 의 reference |
|
||||
| `detect_component_popups` (Y-14) | **Reference** — mdx_normalizer 의 popups 과 union. Astro 컴포넌트 처리 시 |
|
||||
| `map_topics_to_sections` | **Reference** — Kei 통합 별 axis |
|
||||
| `extract_conclusion_text` | **Migrate** — 작은 utility. Phase Z 의 `parse_mdx` 가 footer 추출 흐름과 겹침 (Phase Z line 172). 정리 |
|
||||
|
||||
#### 결정
|
||||
|
||||
**Mixed (Migrate + Reference)**.
|
||||
|
||||
- **Migrate**: `extract_major_sections`, `extract_conclusion_text`
|
||||
- **Reference**: `classify_group_relations`, `_classify_sub_types`, `SCHEMA_RECIPE_MAP`, `KIND_SUBTYPE_COMPAT`, `detect_component_popups`, `map_topics_to_sections`
|
||||
|
||||
**핵심 통찰** (사용자 지적 그대로): mdx_normalizer 와 section_parser 를 *따로 이식하면 schema 가 또 꼬인다*. 둘 다 같이 보고 Stage 0 통합 설계 단계 후 B1~B8 + 본 audit 결과 합쳐 통합.
|
||||
|
||||
#### 후속 작업
|
||||
|
||||
C1. **mdx_normalizer + section_parser chained 흐름** — Phase Z `parse_mdx` 를 다음과 같이 재구성:
|
||||
```python
|
||||
def parse_mdx(mdx_path):
|
||||
text = mdx_path.read_text(encoding="utf-8")
|
||||
normalized = normalize_mdx_content(text) # mdx_normalizer
|
||||
major_sections = extract_major_sections( # section_parser
|
||||
normalized["sections"]
|
||||
)
|
||||
footer = extract_conclusion_text(text) # section_parser
|
||||
return _adapt_to_mdx_sections(normalized, major_sections, footer)
|
||||
```
|
||||
|
||||
C2. **`MdxSection` schema 확장**:
|
||||
```python
|
||||
@dataclass
|
||||
class MdxSection:
|
||||
section_id: str
|
||||
section_num: int
|
||||
title: str
|
||||
raw_content: str
|
||||
sub_sections: list[MdxSection] = field(default_factory=list) # NEW — level 3
|
||||
sub_titles: list[str] = field(default_factory=list) # NEW — section_parser
|
||||
# 아래는 Reference 로 두지만 schema 자리는 채움 (별 axis 활성 시 채워짐)
|
||||
group_schema: Optional[str] = None
|
||||
sub_types: list[dict] = field(default_factory=list)
|
||||
```
|
||||
|
||||
C3. **step02 artifact 확장** — `popups`, `images`, `tables`, `clean_text`, `major_sections`, `group_schema`, `sub_types` trace.
|
||||
|
||||
C4. **Frontend `## __ROOT__` 우회 제거** + **`loadRun` 의 sub_sections 매핑** — backend 가 이미 sub_sections 를 정리한 상태로 들어오니 frontend 의 `parseMdxText` re-parse 도 불필요해짐. 직접 sub_sections / sub_titles 사용.
|
||||
|
||||
C5. **B-3 sub-section drag drop backend 처리** — `extract_major_sections` 의 sub_titles 가 이미 hierarchy 정보를 가지므로, frontend drag drop 이 sub-section id (e.g., `03-1-sub-2`) 를 보내면 backend 가 그 sub-content 를 unit 단위로 promote 가능. 단 V4 매칭이 sub-section 단위 안 함 → V4 도 sub-section 단위 평가 필요 (별 axis, 큼).
|
||||
|
||||
C6. **schema/recipe path Reference 활용** (별 axis) — Phase Z V4 path 와 Phase Q schema/recipe path 의 결과 비교 audit. V4 가 약한 case (catalog 미등록 / capacity mismatch) 에서 schema 점수가 backup 으로 의미 있는지.
|
||||
|
||||
C7. **검증** — MDX 03 fresh run regression check + samples/uploads HTML-heavy 03 으로 fresh run + sub_sections 가 step02 artifact 에 정상 등장하는지.
|
||||
|
||||
작업 분량: C1+C2+C3 = 한 axis (Stage 0 chained 통합, 큼). C4 = 한 axis (frontend cleanup). C5 = 별 axis (V4 sub-section 단위 평가, 큼). C6 = 별 axis (schema/recipe Reference 활성화).
|
||||
|
||||
### 2.3 `slide_measurer.py` — *후속 turn*
|
||||
|
||||
### 2.4 `fit_verifier.py` — *후속 turn*
|
||||
|
||||
### 2.5 `space_allocator.py` — *후속 turn*
|
||||
|
||||
### 2.6 `content_editor.py` — *후속 turn*
|
||||
|
||||
### 2.7 `content_verifier.py` — *후속 turn*
|
||||
|
||||
### 2.8 `renderer.py` — *후속 turn*
|
||||
|
||||
### 2.9 `html_generator.py` — *후속 turn*
|
||||
|
||||
### 2.10 `block_reference.py` / `block_selector.py` — *후속 turn*
|
||||
|
||||
### 2.11 (마지막) `pipeline.py` / `pipeline_context.py` — *후속 turn*
|
||||
|
||||
---
|
||||
|
||||
## 3. Salvage Plan
|
||||
|
||||
> 모든 Salvage Plan 은 **§0-A 원칙** 을 따른다. 특히 **Migrate 항목은 adapter + dual-write 검증 (원칙 3 + 9) 을 통과한 뒤** 기존 path 를 대체한다. 각 Migrate 항목별 *dual-write 통과 기준* (어떤 artifact 필드가 일치해야 하는지) 은 항목별로 §3 안에 명시.
|
||||
>
|
||||
> §2 결과를 합산해 §1 의 lens 항목별 *어떤 Phase Q 자산을 어떤 방식으로 가져올지* 결정. *후속 turn*.
|
||||
|
||||
| Phase Z 항목 | 가져올 Phase Q 자산 | 방식 (Migrate / Reference / 새로 만들기) | 후속 axis |
|
||||
|---|---|---|---|
|
||||
| A-1 Stage 0 normalize | (TBD) | (TBD) | (TBD) |
|
||||
| A-2 Catalog 확장 | (TBD) | (TBD) | (TBD) |
|
||||
| A-3 Frame preview 일관성 | (TBD) | (TBD) | (TBD) |
|
||||
| A-4 slide-base iframe mode | (TBD) | (TBD) | (TBD) |
|
||||
| A-5 V4 fallback | (TBD) | (TBD) | (TBD) |
|
||||
| A-6 Zone 좌표 export | (TBD) | (TBD) | (TBD) |
|
||||
| B-1 Zone-section override | (TBD) | (TBD) | (TBD) |
|
||||
| B-2 Edited HTML → MDX | (TBD) | (TBD) | (TBD) |
|
||||
| B-3 Sub-section drag drop | (TBD) | (TBD) | (TBD) |
|
||||
| B-4 다른 layout zone-geometry | (TBD) | (TBD) | (TBD) |
|
||||
| D-1 filtered_section_reasons UI | (TBD) | (TBD) | (TBD) |
|
||||
| D-2 Frame min_height 표시 | (TBD) | (TBD) | (TBD) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 우선순위 재정렬
|
||||
|
||||
> §1 / §3 결과를 [`PHASE-Z-ROADMAP.md`](PHASE-Z-ROADMAP.md) §5 / §7-B 에 반영. *후속 turn*.
|
||||
|
||||
audit 결과 → 어느 항목이:
|
||||
- **Migrate 로 빠르게 끝남** (작은 작업) → 우선순위 ↑
|
||||
- **새로 만들기 + Reference 만 가능** (큰 작업) → 우선순위 ↓ 또는 분해
|
||||
- **Delete** (Phase Q 에 없음 또는 무관) → §1 표에서 제외
|
||||
|
||||
후속 작업 = ROADMAP §5 / §7-B 갱신.
|
||||
|
||||
---
|
||||
|
||||
## 5. 진행 로그
|
||||
|
||||
| 날짜 | axis | 상태 |
|
||||
|---|---|---|
|
||||
| 2026-05-08 | §0 / §1 작성 | 완료 |
|
||||
| 2026-05-08 | §2.1 mdx_normalizer.py audit | 완료 — **Migrate**. B1~B8 후속 작업 정의 |
|
||||
| 2026-05-08 | §2.2 section_parser.py audit | 완료 — **Mixed (Migrate + Reference)**. C1~C7 후속 작업 정의. mdx_normalizer 와 chained 통합 결정 |
|
||||
| 2026-05-08 | §0-A Salvage 원칙 lock (10 원칙) + §3 머리글 + ROADMAP §5 link | 완료 — 정책 lock |
|
||||
| (next) | §2.3 slide_measurer.py audit | (대기) |
|
||||
| ... | §2.10 까지 1 모듈씩 | (대기) |
|
||||
| (last) | §2.11 pipeline.py / pipeline_context.py | (대기) |
|
||||
| (then) | §3 Salvage Plan | (대기) |
|
||||
| (then) | §4 우선순위 재정렬 → ROADMAP 갱신 | (대기) |
|
||||
Reference in New Issue
Block a user