# Phase M: 비중 시스템 + 역할-블록 매핑 + 블록 안전성 + 원본 보존 > 상태: ✅ 완료 — Kei 비중 시스템 구축. Phase O에서 컨테이너 시스템으로 발전. > > Phase I~L에서 코드 정합성, 블록 선택 권한, 프롬프트 원칙, 렌더링 측정을 다뤘지만 > **근본 문제가 해결되지 않음: "이 페이지의 본심이 뭔지" 판단이 없음.** > Kei가 콘텐츠마다 본심/배경/첨부/결론을 판단하고, 비중(weight)을 결정해야 함. > 코드 상수(하드코딩)가 아닌 **Kei의 매번 판단**. > > **후속 변경 (Phase O):** > - pipeline.py의 Phase M 공간 할당 코드 → Phase O `calculate_container_specs()`로 교체 > - `PURPOSE_WEIGHT` 상수 → 삭제 (Kei weight 직접 사용) > - `allocate_height_budget()` → `calculate_container_specs()` + `finalize_block_specs()`로 교체 --- ## 문제점 전체 리스트 (9건) ### P-1: 비중(weight) 개념 부재 **현상:** Kei가 꼭지 5개를 분류하면, 팀장이 5개를 동등하게 1:1 배치. "본심이 60%, 배경이 15%"라는 공간 비중 개념이 파이프라인 어디에도 없음. **예시:** DX vs BIM 비교(본심)와 용어 정의(첨부)가 동일한 크기의 블록을 받음. **영향:** 핵심 메시지가 묻히고, 보조 정보가 과도한 공간 차지. **위치:** 1단계(Kei) 출력 → 2단계(팀장) 입력 사이. **Phase I~L에서 한 것:** Phase K에서 PURPOSE_WEIGHT 상수 추가, Phase L에서 allocate_height_budget() 함수 추가. **문제:** 하드코딩된 고정 비율. 콘텐츠마다 다른데 코드가 일괄 적용. --- ### P-2: 편집자적 구조 판단 부재 **현상:** Kei가 꼭지를 "나열"만 함. 아래와 같은 편집 구조를 잡지 못함: ``` (배경/목적) 왜 이 페이지가 필요한가 (본심) 이 페이지가 말하려는 핵심 (첨부) 본심을 이해하기 위한 보조 정보 (잊지마) 절대 잊으면 안 되는 결론 ``` **현재:** purpose와 layer가 있지만 "이 페이지의 본심은 꼭지2이고 나머지는 보조다"라는 판단이 없음. **영향:** 모든 꼭지가 동등하게 취급됨. 스토리라인은 있으나 강약이 없음. **위치:** 1단계 KEI_PROMPT. **Phase I~L에서 한 것:** Phase K에서 인지 흐름 원칙 추가. **문제:** 원칙만 줬지 Kei 출력 스키마에 "본심/배경/첨부/결론" 구분이 없음. --- ### P-3: 블록 선택이 "콘텐츠 역할"이 아닌 "데이터 타입"으로 결정됨 **현상:** 팀장(Sonnet)이 블록을 고를 때 "텍스트 → 텍스트 블록, 표 → 표 블록"으로 데이터 형식만 보고 선택. "이것이 본심이니까 정보 밀도 높은 블록" 판단 안 함. **올바른 선택 기준:** ``` 본심(핵심전달) → 정보형 블록 (compare-2col-split 등) → 공간 최대 배경(문제제기) → 컴팩트 블록 (topic-left-right 등) → 공간 최소 첨부(용어정의) → 참조형 블록 (card-numbered 등) → sidebar 결론(강조) → 선언형 블록 (banner-gradient) → footer ``` **위치:** 2단계 STEP_B_PROMPT + FAISS 검색. **Phase I~L에서 한 것:** Phase K에서 purpose별 허용/금지 블록 규칙 추가. **문제:** purpose 기반이지 "본심/배경" 기반이 아님. Kei가 비중을 출력해야 팀장이 비중대로 블록 크기 결정. --- ### P-4: 공간 배분 로직 부재 **현상:** 팀장이 zone별 height_cost만 검증하고, "이 꼭지에 몇 px를 줘야 하는가"는 계산하지 않음. **현재 로직:** 블록 선택 → height_cost 합산 확인 → 초과하면 교체 **필요한 로직:** 비중(weight) 확인 → weight에 따라 zone 예산 배분 → 배분된 px에 맞는 블록 선택 **위치:** 2단계 create_layout_concept(). **Phase I~L에서 한 것:** Phase L에서 allocate_height_budget() + max-height CSS 적용. **문제:** PURPOSE_WEIGHT가 하드코딩. Kei가 판단한 weight를 사용해야 함. --- ### P-5: Figma 비추출 블록 사용 **현상:** 38개 블록 중 9개가 Figma 디자인 없이 코드로 만든 블록. 디자인 품질 미검증. **비-Figma 블록 (9개):** - topic-numbered, card-numbered, table-simple-striped - venn-diagram, process-horizontal - comparison-2col, callout-warning - divider-text, image-before-after **영향:** 시각적 통일성 저하. **위치:** 2단계 블록 선택 시 필터링 없음. **Phase I~L에서 한 것:** 안 다룸. --- ### P-6: 블록-zone 적합성 검증 부재 **현상:** sidebar(35%)에 full-width 전용 블록을 배치하면 찌그러짐. 블록이 어떤 zone에서 작동하는지 검증 없음. **full-width 전용 블록 (15개):** - card-icon-desc, card-compare-3col, comparison-2col - topic-left-right, compare-pill-pair, process-horizontal 등 **영향:** sidebar에서 블록 깨짐, 텍스트 한 글자씩 줄바꿈. **위치:** 2단계 블록 선택 후 검증. **Phase I~L에서 한 것:** Phase J에서 sidebar 1열 강제(column_override). 불완전. --- ### P-7: 블록별 글자 수용량 미정의 **현상:** 블록에 텍스트를 넣을 때 "얼마나 들어가는지" 기준 없음. char_guide 참고하지만 실제 렌더링과 괴리. **결과:** 텍스트 과다 → overflow / 텍스트 과소 → 빈 페이지. **위치:** catalog.yaml에 schema 미정의. 3단계 편집자 프롬프트. **Phase I~L에서 한 것:** Phase I에서 slot_desc 추가, Phase K에서 분량 가이드라인 추가. 실제 수용량은 미정의. --- ### P-8: 내부 스크롤 미감지 **현상:** 5단계 검수에서 area 레벨 overflow만 체크. 블록 내부의 overflow: auto/hidden으로 인한 내부 스크롤/잘림은 감지 못함. **예시:** compare-3col-badge는 overflow: auto여서 area는 OK인데 블록 안에서 스크롤 발생. **영향:** "검증 통과"했는데 실제로는 내용 잘림. **위치:** 5단계 검수. **Phase I~L에서 한 것:** Phase L에서 Selenium 측정 추가. 하지만 블록 내부 overflow까지 체크하는지 미확인. --- ### P-9: 원본 텍스트 임의 재작성 **현상:** 3단계 편집자가 원본을 "편집"이 아닌 "재작성". 원본 문구, 출처, 수치 변경/누락. **영향:** 정보 정확도 저하, 출처 누락. **위치:** 3단계 편집자 프롬프트 + Kei API 응답 품질. **Phase I~L에서 한 것:** Phase J에서 source 슬롯 규칙 추가, EDITOR_PROMPT에 보존 원칙. 강제력 부족. --- ## 개선 방향 (4가지) ### 방향 1: 비중(weight) 시스템 — P-1, P-2, P-4 해결 [긴급] **핵심:** Kei가 콘텐츠마다 본심/배경/첨부/결론을 판단하고 weight를 출력. **KEI_PROMPT 출력 스키마 변경:** ```json { "title": "건설산업 DX의 올바른 이해", "core_message": "BIM은 DX의 기초적 일부분이다", "page_structure": { "본심": {"topic_ids": [2, 3], "weight": 0.60}, "배경": {"topic_ids": [1], "weight": 0.15}, "첨부": {"topic_ids": [4], "weight": 0.15}, "결론": {"topic_ids": [5], "weight": 0.10} }, "topics": [...] } ``` **파이프라인 반영:** - 1단계: Kei가 page_structure + weight 출력 (콘텐츠마다 다름, 하드코딩 아님) - 2단계: weight → px 변환 (body 490px × 0.6 = 294px → 본심) - 2단계: 배분된 px에 맞는 블록 선택 - 배치: 본심 비중이 결정하면 가로/세로/구조화 방식도 자연스럽게 따라옴 - Phase L의 PURPOSE_WEIGHT 하드코딩 제거 → Kei 출력 weight 사용 --- ### 방향 2: 역할-블록 매핑 체계 — P-3 해결 [중요] **콘텐츠 역할 × 콘텐츠 성격 → 블록 결정:** ``` 본심 + 비교 → compare-2col-split, compare-3col-badge 본심 + 구조 → keyword-circle-row, card-step-vertical 본심 + 정의 → card-numbered (large), dark-bullet-list (large) 배경 + 문제 → topic-left-right (compact), quote-question (compact) 배경 + 사례 → callout-warning (compact), quote-big-mark (compact) 첨부 + 정의 → card-numbered (sidebar), dark-bullet-list (sidebar) 결론 → banner-gradient (footer) ``` **반영 위치:** STEP_B_PROMPT — 현재 purpose별 허용/금지를 "역할 × 성격" 매트릭스로 확장. --- ### 방향 3: 블록 안전성 인프라 — P-5, P-6, P-7, P-8 해결 [중요] | 항목 | 내용 | 해결 방법 | |------|------|----------| | P-5 Figma 블록 필터 | 비-Figma 9개 블록 식별 | 블록 선택 시 Figma 블록 우선 또는 비-Figma 경고 | | P-6 블록-zone 적합성 | full-width 15개 블록 식별 | zone별 허용 블록 맵 (코드 검증) | | P-7 글자 수용량 | 블록별 max chars | catalog.yaml에 zone별 max_chars 추가 | | P-8 내부 스크롤 | 블록 내부 overflow 감지 | Selenium 측정 시 블록 내부까지 scrollHeight 체크 | --- ### 방향 4: 원본 보존 강화 — P-9 해결 [보통] **3단계 편집자에게 source_text 직접 전달:** - 현재: 원본 콘텐츠 전체를 주고 "여기서 가져와라" - 변경: 각 꼭지별로 Kei가 source_hint에 명시한 원본 텍스트를 **직접 추출하여** 편집자에게 전달 - "이 텍스트에서 추출하라. 새로 쓰지 마라. 축약만 허용." --- ## 우선순위 ``` [긴급] P-1 + P-2 + P-4 → 방향 1: 비중 시스템 ← 이것이 없으면 나머지를 해도 의미 없음 ← Kei가 판단. 하드코딩 아님. ← 비중이 결정되면 배치, 블록 크기, 가로/세로 흐름이 자동으로 따라옴 [중요] P-3 → 방향 2: 역할-블록 매핑 ← 비중 시스템 위에서 역할별 블록 정확 매칭 [중요] P-7 + P-8 → 방향 3-a: 스키마 + 검증 ← 글자 수용량 정의 + 내부 overflow 감지 [보통] P-5 + P-6 → 방향 3-b: 필터링 ← Figma 블록 우선 + zone 적합성 검증 [보통] P-9 → 방향 4: 편집자 원본 보존 ``` --- ## Phase I~L과의 관계 | 기존 Phase | Phase M에서 변경 | |-----------|----------------| | Phase K PURPOSE_WEIGHT 하드코딩 | **제거** → Kei 출력 weight 사용 | | Phase K purpose 가이드 | **유지** + 역할×성격 매트릭스로 확장 | | Phase L allocate_height_budget() | **유지** + 입력을 PURPOSE_WEIGHT 대신 Kei weight로 변경 | | Phase L measure_rendered_heights() | **유지** + 블록 내부 overflow 체크 추가 (P-8) | | Phase L calculate_trim_chars() | **유지** | | Phase J Opus 존중 규칙 | **유지** | | Phase J Kei 최종 검수 | **유지** + 비중 기반 검수 항목 추가 | | Phase I slot_desc | **유지** | | Phase I SSE 공통 유틸 | **유지** | **회귀 없음.** 기존 인프라(측정, 계산, 검수) 위에 비중 시스템을 추가. **제거 대상:** PURPOSE_WEIGHT 하드코딩 상수만. --- ## 실행 순서 ### M-Step 1: Kei 비중 시스템 (P-1 + P-2 + P-4) [긴급] 1. KEI_PROMPT 출력 스키마에 page_structure 추가 2. Kei가 본심/배경/첨부/결론 + weight를 출력하도록 프롬프트 수정 3. pipeline.py에서 Kei 출력의 weight를 읽어서 allocate_height_budget()에 전달 4. PURPOSE_WEIGHT 하드코딩 제거 5. STEP_B_PROMPT에 weight 기반 블록 크기 지시 추가 ### M-Step 2: 역할-블록 매핑 (P-3) 6. STEP_B_PROMPT purpose 가이드를 역할×성격 매트릭스로 재구성 7. Kei 출력의 relation_type + 역할(본심/배경/첨부)로 블록 결정 ### M-Step 3: 블록 안전성 (P-5 + P-6 + P-7 + P-8) 8. P-5: catalog.yaml에 figma_source 필드 추가 (Figma 블록 식별) 9. P-6: 블록-zone 적합성 맵 정의 + 코드 검증 추가 10. P-7: catalog.yaml에 zone별 max_chars 추가 11. P-8: slide_measurer.py에서 블록 내부 overflow까지 체크 ### M-Step 4: 원본 보존 (P-9) 12. 편집자에게 꼭지별 source_text 직접 전달 13. "추출만. 재작성 금지." 강화 --- ## 기술 조사 결과 ### M-Step 1에 필요한 것 | 항목 | 현재 | 변경 | 도구 | |------|------|------|------| | KEI_PROMPT 출력 | topics만 | + page_structure (본심/배경/첨부/결론 + weight) | 프롬프트 수정 | | page_structure 파싱 | 없음 | `analysis.get("page_structure")` | 코드 추가 | | PURPOSE_WEIGHT 상수 | 하드코딩 (space_allocator.py) | **제거** → Kei weight 사용 | 코드 수정 | | allocate_height_budget() | PURPOSE_WEIGHT 참조 | weight_override 파라미터 추가 | 함수 시그니처 변경 | | STEP_B_PROMPT | purpose별 규칙만 | + weight 기반 블록 크기 지시 | 프롬프트 수정 | **충돌:** 없음. page_structure는 새 필드. PURPOSE_WEIGHT 제거는 개선. **Kei vs Sonnet:** Kei가 weight 판단. Sonnet은 weight를 **받아서** 블록 크기 결정. --- ### M-Step 2에 필요한 것 | 항목 | 현재 | 변경 | 도구 | |------|------|------|------| | FAISS 쿼리 | title+summary+role+layer | + purpose + relation_type + expression_hint | block_search.py `_build_query()` 수정 | | STEP_B_PROMPT 가이드 | purpose 6종 허용/금지 | 역할(본심/배경/첨부) × 성격(비교/정의/구조) 매트릭스 | 프롬프트 확장 | **충돌:** Phase K purpose 가이드 **위에** 매트릭스 확장. 기존 규칙 유지. --- ### M-Step 3에 필요한 것 | 항목 | 현재 | 변경 | 도구 | |------|------|------|------| | P-5 Figma 식별 | 구분 없음 | catalog.yaml에 `figma_source` 필드 | YAML 수정 | | P-6 zone 적합성 | sidebar 1열만 (J-6) | **블록-zone 적합성 맵** 코드 검증 | 신규 상수 + 검증 로직 | | P-7 글자 수용량 | slot_desc 의미만 | catalog.yaml에 **zone별 max_chars** | YAML + 편집자 연동 | | P-8 내부 overflow | zone 레벨만 측정 | **블록 내부** scrollHeight 체크 | slide_measurer.py JS 확인 | **P-6 블록-zone 적합성 맵:** ```python # 신규 상수 (design_director.py 또는 별도 모듈) SIDEBAR_SAFE_BLOCKS = { "card-numbered", "card-step-vertical", "banner-gradient", "callout-solution", "callout-warning", "dark-bullet-list", "divider-text", "highlight-strip", "quote-question", "tab-label-row", "topic-left-right", "topic-numbered", "table-simple-striped", "process-horizontal", "image-before-after", "image-grid-2x2", "image-row-2col", } FULL_WIDTH_ONLY_BLOCKS = { "card-compare-3col", "card-dark-overlay", "card-icon-desc", "card-image-3col", "card-image-round", "card-stat-number", "card-tag-image", "section-title-with-bg", "section-header-bar", "topic-center", "quote-big-mark", "image-full-caption", "compare-2col-split", "compare-pill-pair", "comparison-2col", } ``` **충돌:** Phase J의 sidebar 1열 강제와 **보완 관계.** J-6은 열 수 제한, M-Step 3은 블록 자체 제한. --- ### M-Step 4에 필요한 것 | 항목 | 현재 | 변경 | 도구 | |------|------|------|------| | 원본 전달 | 전체 content 한 번에 | **토픽별 source_text 추출하여 전달** | fill_content() 수정 | | source_hint | 정의됨, 사용 안 됨 | **편집자에게 전달** | 프롬프트 수정 | | source_data | 텍스트 설명만 | **실제 원본 텍스트 추출 참조** | 코드 추가 | | 재작성 방지 | "보존" 원칙만 | **"추출만. 재작성 금지."** 절대 규칙 | 프롬프트 강화 | **충돌:** Phase J source 규칙 **유지 + 보강.** --- ## 실행 방안 상세 ### M-Step 1: Kei 비중 시스템 #### M-1a: KEI_PROMPT 출력 스키마 변경 **위치:** `src/kei_client.py` KEI_PROMPT (20~79행) **추가할 출력 필드:** ```json { "title": "...", "core_message": "...", "page_structure": { "본심": {"topic_ids": [2, 3], "weight": 0.60}, "배경": {"topic_ids": [1], "weight": 0.15}, "첨부": {"topic_ids": [4], "weight": 0.15}, "결론": {"topic_ids": [5], "weight": 0.10} }, "topics": [...] } ``` **프롬프트에 추가할 지시:** ``` ## 4단계: 페이지 구조 판단 콘텐츠를 분석하여 이 페이지의 구조를 판단하라: - **본심**: 이 페이지가 말하려는 핵심. 가장 큰 공간을 차지해야 함. - **배경**: 본심을 이해하기 위한 도입/배경. 간결하게. - **첨부**: 본심을 보조하는 참조 정보 (용어 정의 등). sidebar 배치. - **결론**: 절대 잊으면 안 되는 핵심 한 줄. footer. 각 역할에 해당하는 topic_ids와 공간 비중(weight, 합계 1.0)을 결정하라. 콘텐츠에 따라 비중은 매번 달라진다. 고정값이 아니다. ``` **충돌:** 없음. 기존 출력 필드에 page_structure 추가만. `.get()` 방식이라 무시 가능. #### M-1b: pipeline.py에서 Kei weight 읽기 **위치:** `src/pipeline.py` Phase L 공간 할당 부분 (현재 132~165행) **변경:** PURPOSE_WEIGHT 대신 Kei 출력 weight 사용 ```python # 현재 (Phase L 하드코딩): allocation = allocate_height_budget(zone_blocks, zone_info.get("budget_px", 490)) # 변경 (Phase M Kei 판단): page_struct = analysis.get("page_structure", {}) weight_map = {} for role_name, role_info in page_struct.items(): for tid in role_info.get("topic_ids", []): weight_map[tid] = role_info.get("weight", 0.25) allocation = allocate_height_budget( zone_blocks, zone_info.get("budget_px", 490), weight_override=weight_map ) ``` #### M-1c: allocate_height_budget() 시그니처 변경 **위치:** `src/space_allocator.py` (42~75행) **변경:** `weight_override` 파라미터 추가 ```python def allocate_height_budget( blocks, zone_budget_px, gap_px=20, weight_override=None, # {topic_id: weight} — Kei 판단 기반 ): # weight_override 있으면 사용, 없으면 PURPOSE_WEIGHT fallback for block in blocks: tid = block.get("topic_id") if weight_override and tid in weight_override: weight = weight_override[tid] else: purpose = block.get("purpose", "") weight = PURPOSE_WEIGHT.get(purpose, 0.25) weights.append(weight) ``` **PURPOSE_WEIGHT:** fallback으로 유지 (Kei가 page_structure 안 줬을 때). 하드코딩 → fallback 강등. #### M-1d: STEP_B_PROMPT에 weight 전달 **위치:** `src/design_director.py` STEP_B_PROMPT user_prompt 구성부 **추가:** Kei가 판단한 비중을 팀장에게 전달 ``` ## 페이지 구조 (Kei 실장 판단) - 본심 (꼭지 2, 3): 공간 비중 60% — body에서 가장 크게 - 배경 (꼭지 1): 공간 비중 15% — compact 도입부 - 첨부 (꼭지 4): 공간 비중 15% — sidebar 참조 - 결론 (꼭지 5): 공간 비중 10% — footer 한 줄 본심에 가장 큰 블록을, 배경에 가장 작은 블록을 배정하라. 비중을 무시하고 동등하게 배치하지 마라. ``` --- ### M-Step 2: 역할-블록 매핑 #### M-2a: FAISS 쿼리 강화 **위치:** `src/block_search.py` `_build_query()` (178~188행) **변경:** purpose + relation_type + expression_hint 추가 ```python def _build_query(topic): parts = [ topic.get("title", ""), topic.get("summary", ""), f"역할: {topic.get('role', 'flow')}", f"레이어: {topic.get('layer', 'core')}", f"목적: {topic.get('purpose', '')}", # 추가 f"관계: {topic.get('relation_type', '')}", # 추가 f"표현: {topic.get('expression_hint', '')}", # 추가 ] if topic.get("content_type"): parts.append(f"콘텐츠: {topic['content_type']}") return ". ".join(p for p in parts if p) ``` #### M-2b: STEP_B_PROMPT 역할×성격 매트릭스 **위치:** `src/design_director.py` purpose 가이드 섹션 **기존 Phase K 규칙 유지 + 아래 매트릭스 추가:** ``` ## 역할 × 콘텐츠 성격 블록 매트릭스 | 역할 | 비교(comparison) | 구조(hierarchy/inclusion) | 정의(definition) | 흐름(sequence) | |------|-----------------|------------------------|-----------------|---------------| | 본심 | compare-2col-split, compare-3col-badge | keyword-circle-row, venn-diagram | card-numbered(large) | process-horizontal, flow-arrow-horizontal | | 배경 | topic-left-right(compact) | topic-left-right(compact) | quote-question(compact) | topic-left-right(compact) | | 첨부 | card-numbered(sidebar) | card-numbered(sidebar) | card-numbered(sidebar), dark-bullet-list(sidebar) | card-numbered(sidebar) | | 결론 | banner-gradient | banner-gradient | banner-gradient | banner-gradient | ``` --- ### M-Step 3: 블록 안전성 #### M-3a: catalog.yaml figma_source 필드 (P-5) **추가할 필드:** 각 블록에 `figma_source: true/false` #### M-3b: zone 적합성 검증 (P-6) **위치:** `src/design_director.py` `_validate_height_budget()` 내 **추가:** sidebar에 FULL_WIDTH_ONLY_BLOCKS 배치 시 교체/경고 #### M-3c: 글자 수용량 (P-7) **위치:** `templates/catalog.yaml` **추가:** 각 블록에 zone별 max_chars ```yaml - id: compare-2col-split max_chars: body: {left: 200, right: 200, criteria: 30} # 65% 너비 기준 sidebar: null # sidebar 사용 불가 ``` #### M-3d: 내부 overflow 감지 (P-8) **위치:** `src/slide_measurer.py` _MEASURE_SCRIPT **확인:** 현재 JS가 블록 내부 `scrollHeight > clientHeight + 2` 이미 체크 중. `overflow: auto` 블록(compare-3col-badge)의 수평 스크롤도 `scrollWidth > clientWidth` 체크 추가. --- ### M-Step 4: 원본 보존 #### M-4a: 토픽별 source_text 추출 **위치:** `src/pipeline.py` Stage 3 호출 전 **추가:** Kei가 출력한 source_hint + source_data를 기반으로 원본에서 텍스트 추출 ```python # 토픽별 원본 텍스트 매핑 구성 topic_sources = {} for topic in analysis.get("topics", []): source_hint = topic.get("source_hint", "") source_data = topic.get("source_data", "") topic_sources[topic["id"]] = { "hint": source_hint, "data": source_data, } ``` #### M-4b: fill_content() 프롬프트에 토픽별 source 전달 **위치:** `src/content_editor.py` fill_content() user_prompt 구성부 **추가:** ``` ## 토픽별 원본 데이터 (이 텍스트에서 추출하라. 재작성 금지.) - 토픽 1: [source_hint 내용] - 토픽 2: [source_hint 내용] ``` --- ## 충돌/회귀/하드코딩 최종 검증 | Step | 충돌 | 회귀 | 하드코딩 | Kei/Sonnet | |------|:---:|:---:|:------:|:----------:| | M-1a KEI_PROMPT | 없음 | 없음 | **Kei 판단** | Kei | | M-1b pipeline weight | 없음 | Phase L 개선 | **Kei weight** | — | | M-1c allocate 시그니처 | 없음 | 없음 | fallback만 | — | | M-1d STEP_B weight | 없음 | 없음 | **Kei → 팀장** | Sonnet(기존) | | M-2a FAISS 쿼리 | 없음 | 없음 | 없음 | — | | M-2b 매트릭스 | Phase K 위에 확장 | 없음 | 없음 | Sonnet(기존) | | M-3a Figma | 없음 (신규) | 없음 | 없음 | — | | M-3b zone맵 | Phase J 보강 | 없음 | 상수(범용) | — | | M-3c max_chars | Phase I 보강 | 없음 | 없음 | — | | M-3d 내부overflow | Phase L 확장 | 없음 | 없음 | — | | M-4a source 추출 | 없음 (신규) | 없음 | 없음 | — | | M-4b 편집자 강화 | Phase J 보강 | 없음 | 없음 | Kei(편집자) | --- ## 이력 | 날짜 | 내용 | |------|------| | 2026-03-26 | Phase I~L 전체 실행 후 결과물 분석. 외부 진단(P-1~P-9) 수용. 비중 시스템(Kei 판단, 하드코딩 아님) 기반 전면 재설계. Phase M 계획 수립. | | 2026-03-26 | 기술 조사 + 충돌/회귀 정밀 검토 완료. M-Step 1~4 실행 방안 상세 확정. |