wip: phase_z2 evidence 파이프라인 + matching 실험(phase2~26) + 프론트 trace 패널 진행분 스냅샷

- src: phase_z2 composition/mapper/pipeline/placement_planner/retry, ai_fallback(prompts/schema/validate), mdx_text_atoms 신규
- Front: PipelineTracePanel 신규, FramePanel/SlideCanvas/Home/designAgentApi 등 갱신 + 테스트 4종 추가
- templates/phase_z2: catalog(component_expansion_registry, node_slot_mapping 신규), frames, families, slide_base 갱신
- tests/matching: phase2~26 매칭 실험 스크립트·리포트·온톨로지 전체 (미커밋 진행분)
- tests: b4_v4 evidence, task5~28.5 시리즈, regression(imp95 baseline) 등 신규 테스트 대량 추가
- docs/reference: MDX 구조 인벤토리, MDX→Frame 구조 계약 문서
- scripts: mdx 계약/parity/coverage/viewport 체크, gitea comment, run sync 유틸
- .gitignore: tmp*.json, chromedriver, .orchestrator, *.pkl, Front_test* 등 임시/스냅샷 제외

미완성 작업의 보존용 스냅샷 커밋 (2026-07-02)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 17:03:42 +09:00
co-authored by Claude Opus 4.8
parent 97b7833a1b
commit b836e79ee1
527 changed files with 673036 additions and 717 deletions
+146
View File
@@ -0,0 +1,146 @@
"""32 Figma frames 의 '후보 키워드' 전수 확인 + 통계.
출력:
- FIGMA_KEYWORDS_REPORT.md : 프레임별 후보 키워드 + 통계 + DF 기반 tier
용도: analysis.md 의 '후보 키워드' 필드가 어떻게 채워져 있는지 한눈 검수.
"""
import sys
import collections
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from phase_common import load_32_frames, compute_df_idf_tier, load_frame_index
HERE = Path(__file__).parent
def main():
frames = load_32_frames()
df, idf, tier, N = compute_df_idf_tier(frames)
idx_data, frame_to_short = load_frame_index()
# 프레임 순 정렬 (short_id)
ordered = sorted(frames.items(), key=lambda kv: frame_to_short.get(kv[0], "99"))
lines = []
lines.append("# Figma 32 프레임 — 후보 키워드 검수 리포트")
lines.append("")
lines.append("**출처**: 각 프레임의 `figma_to_html_agent/blocks/{frame_id}/analysis.md` 의 `## 후보 키워드` 필드")
lines.append("")
lines.append(f"**작성자**: claude-opus-4-7 (2026-04-21, `tagged_by` 메타 참조)")
lines.append("")
lines.append(f"**생성 방법**: 각 프레임의 `texts.md` (MCP 추출 원본 텍스트 전수) + `flat.md` "
f"(bottom-up 평탄화 + 이상 탐지) 를 AI 가 읽고 15~25개 어휘를 수동 태깅.")
lines.append("")
# 1. 전체 통계
lines.append("## 1. 전체 통계")
lines.append("")
total_kws = sum(len(v["keywords"]) for _, v in frames.items())
unique_kws = len(set().union(*[set(v["keywords"]) for v in frames.values()]))
avg_kws = total_kws / len(frames)
core = [kw for kw in set().union(*[set(v["keywords"]) for v in frames.values()])
if tier.get(kw) == "core"]
mid = [kw for kw in set().union(*[set(v["keywords"]) for v in frames.values()])
if tier.get(kw) == "mid"]
general = [kw for kw in set().union(*[set(v["keywords"]) for v in frames.values()])
if tier.get(kw) == "general"]
lines.append(f"- 프레임 수: **{len(frames)}**")
lines.append(f"- 총 키워드 (중복 포함): **{total_kws}**")
lines.append(f"- 고유 키워드: **{unique_kws}**")
lines.append(f"- 프레임당 평균: **{avg_kws:.1f}개**")
lines.append("")
lines.append(f"- **core** (df ≤ 10%, 1~3 프레임 등장): **{len(core)}개** — 핵심 가중치 ×1.0")
lines.append(f"- **mid** (df 10~30%): **{len(mid)}개** — 가중치 ×0.5")
lines.append(f"- **general** (df ≥ 30%): **{len(general)}개** — 가중치 ×0.1")
lines.append("")
# 2. 프레임별 리스트
lines.append("## 2. 프레임별 후보 키워드")
lines.append("")
lines.append("| # | Frame | 제목 (content 1문장) | 키워드 수 | 키워드 |")
lines.append("|---|-------|---------------------|----------|--------|")
for fid, v in ordered:
sid = frame_to_short.get(fid, "?")
content = v.get("content", "").replace("\n", " ")[:60]
kws = v["keywords"]
kws_str = ", ".join(kws)
lines.append(f"| {sid} | {fid} | {content}… | {len(kws)} | {kws_str} |")
lines.append("")
# 3. tier 별 전체 키워드
lines.append("## 3. Tier 별 전체 키워드 (매칭 가중치 분류)")
lines.append("")
def sort_by_df(kws):
return sorted(kws, key=lambda k: (-df.get(k, 0), k))
lines.append(f"### 3-1. Core ({len(core)}개, df ≤ 10% — 가중치 ×1.0)")
lines.append("")
lines.append("특정 프레임에만 등장하는 고유 어휘. 매칭에서 결정적 신호.")
lines.append("")
core_sorted = sort_by_df(core)
lines.append(", ".join(f"`{k}`({df.get(k,0)})" for k in core_sorted[:80]))
if len(core_sorted) > 80:
lines.append(f"... (총 {len(core_sorted)}개)")
lines.append("")
lines.append(f"### 3-2. Mid ({len(mid)}개, df 10~30% — 가중치 ×0.5)")
lines.append("")
mid_sorted = sort_by_df(mid)
lines.append(", ".join(f"`{k}`({df.get(k,0)})" for k in mid_sorted))
lines.append("")
lines.append(f"### 3-3. General ({len(general)}개, df ≥ 30% — 가중치 ×0.1)")
lines.append("")
lines.append("여러 프레임에 등장해 변별력이 낮은 범용어.")
lines.append("")
general_sorted = sort_by_df(general)
lines.append(", ".join(f"`{k}`({df.get(k,0)})" for k in general_sorted))
lines.append("")
# 4. 어떻게 쓰는가
lines.append("## 4. 매칭에서의 활용 (Phase 23)")
lines.append("")
lines.append("```")
lines.append("MDX 본문 →")
lines.append(" synonyms.yaml 치환 →")
lines.append(" Kiwi 형태소 분석 (명사/영문/숫자만) →")
lines.append(" 위 vocab (32개 프레임 전체 키워드 합집합) 과 교집합 →")
lines.append(" MDX 키워드 셋 확보")
lines.append("")
lines.append("각 프레임 점수 = IDF 가중 Jaccard(MDX 키워드 셋, 프레임 키워드 셋)")
lines.append(" 여기서 각 키워드 기여도는 df 기반 tier 가중치 적용")
lines.append("```")
lines.append("")
lines.append("**사용처**:")
lines.append("- Phase 23 (키워드만), 24 (+내용), 25 (+구조) — **legacy 축**")
lines.append("- Phase 26 (template-fit-v1) 는 이 키워드 리스트 대신 "
"프레임별 `anchor_sets` (구조화된 named set) 사용")
lines.append("")
# 5. 원본 확인법
lines.append("## 5. 원본 파일 직접 확인")
lines.append("")
lines.append("각 프레임의 analysis.md 에 그대로 기록:")
lines.append("")
lines.append("```bash")
lines.append("cat figma_to_html_agent/blocks/1171281190/analysis.md")
lines.append("```")
lines.append("")
lines.append("전체 검수:")
lines.append("")
lines.append("```bash")
lines.append("grep -A 2 '## 후보 키워드' figma_to_html_agent/blocks/*/analysis.md")
lines.append("```")
lines.append("")
out = HERE / "FIGMA_KEYWORDS_REPORT.md"
out.write_text("\n".join(lines), encoding="utf-8")
print(f"완료: {out}")
if __name__ == "__main__":
main()