Add Phase Z matching architecture anchor doc
- consolidate evidence-based principles for Step 5/6/7 and B-axis matching layer - record CompositionUnit, candidate-based composition, and 4-tier terminology - defer bridge architecture and slot_payload evolution as scope-locked open items
This commit is contained in:
206
docs/architecture/PHASE-Z-MATCHING-ARCHITECTURE.md
Normal file
206
docs/architecture/PHASE-Z-MATCHING-ARCHITECTURE.md
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
# Phase Z 매칭 아키텍처 — 원칙 anchor
|
||||||
|
|
||||||
|
> 22-step pipeline 의 *매칭 layer* (Step 5/6/7 + B-axis Step 9/10/11) 를 다루는 *원칙 anchor* doc.
|
||||||
|
>
|
||||||
|
> 본 문서는 *새 디자인 생성* 이 아니라 *기존 코드 / 과거 docs / 관찰 사례 / session 인사이트* 를 근거로 한 *forward improvement consolidation*.
|
||||||
|
>
|
||||||
|
> 관련 anchors :
|
||||||
|
> - `docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md` (D1, 22-step pipeline)
|
||||||
|
> - `docs/architecture/PHASE-Z-CONTENT-OBJECT-SUBZONE-SPEC.md` (D2, Layer A/B SPEC)
|
||||||
|
> - `docs/architecture/PHASE-Z-CONTENT-OBJECT-SUBZONE-PLAN.md` (D3, schema completion plan)
|
||||||
|
> - `docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md` (D4, 현재 status)
|
||||||
|
|
||||||
|
|
||||||
|
## §0. 본 문서의 작성 방법론 (P0)
|
||||||
|
|
||||||
|
**evidence-based forward improvement** — 매번 *4 source* 를 거쳐 도출 :
|
||||||
|
|
||||||
|
1. 과거 docs (D1 / D2 / D3 / D4) — *원래 의도*
|
||||||
|
2. 현재 코드 (`src/phase_z2_*.py` / `templates/phase_z2/catalog/frame_contracts.yaml`) — *실제 동작*
|
||||||
|
3. 관찰된 혼선 / 실패 사례 — *경험적 evidence*
|
||||||
|
4. session 인사이트 — *최근 정리된 mental model*
|
||||||
|
|
||||||
|
이걸 *관찰 → 혼선 → 도출 원칙 → 개선 방향* form 으로 표면화. *과거 회귀* 가 아니라 *과거를 근거로 한 개선*. *감으로 결정* / *가장 쉬운 선택* 금지.
|
||||||
|
|
||||||
|
|
||||||
|
## §1. 현재 코드 상태 (관찰)
|
||||||
|
|
||||||
|
### 1.1 매칭 단위 — `CompositionUnit`
|
||||||
|
|
||||||
|
매칭의 *atomic unit* 은 section 이 아니라 `CompositionUnit`. `src/phase_z2_composition.py` 의 `collect_candidates` 가 *3 종 candidate type* 을 동시 생성 :
|
||||||
|
|
||||||
|
- `single` — `src/phase_z2_composition.py:230-243` (1 section 단독)
|
||||||
|
- `parent_merged` — `src/phase_z2_composition.py:260-273` (parent 자체가 V4 매칭, children 묶음)
|
||||||
|
- `parent_merged_inferred` — `src/phase_z2_composition.py:352-368` (children rep_match 기반 inferred merge)
|
||||||
|
|
||||||
|
각 candidate 는 `source_section_ids[]` + `merge_type` (line 232 / 262 / 354) 로 *어떤 section 들을 어떻게 묶었는지* 표현.
|
||||||
|
|
||||||
|
### 1.2 frame 선택 — render path authority = V4 rank-1
|
||||||
|
|
||||||
|
현재 render path 의 `frame_template_id` 는 composition planner 의 *V4 rank-1* 기반 :
|
||||||
|
- `lookup_v4_match()` in `src/phase_z2_pipeline.py` (D1:212 명시) — rank-1 만 반환
|
||||||
|
- composition planner 가 V4 결과로 candidate 생성
|
||||||
|
|
||||||
|
B4 (`src/phase_z2_placement_planner.py:90-107` 의 `_select_frame`) 도 frame selection 을 *수행* 하지만 *trace-only* — render path authority 는 V4 rank-1.
|
||||||
|
|
||||||
|
V4 = `top-k` 선언만 됐고 *rank-1 사용* 만 활성. D4 의 ⚠ partial.
|
||||||
|
|
||||||
|
### 1.3 binding — `phase_z2_mapper.map_with_contract` (Layer 1)
|
||||||
|
|
||||||
|
`src/phase_z2_mapper.py:584-609` 의 `map_with_contract(section, contract)` 는 contract 에서 *오직* 두 field 만 read :
|
||||||
|
- `contract["source_shape"]` (split 규칙)
|
||||||
|
- `contract["payload"]["builder"]` (named PAYLOAD_BUILDERS dispatch)
|
||||||
|
|
||||||
|
`accepted_content_types` / `sub_zones` 등 Layer 2 field 는 *접근 X*. 즉 mapper 는 *Layer 1 binder* 로 격리.
|
||||||
|
|
||||||
|
### 1.4 placement — `phase_z2_placement_planner` (Layer 2 reader, trace-only)
|
||||||
|
|
||||||
|
`src/phase_z2_placement_planner.py` :
|
||||||
|
- `_select_frame` (90-107) — `accepted_content_types ⊇ content_type_set` cover + declaration order first
|
||||||
|
- `_assign_region_to_sub_zone` (113-151) — `sub_zones` 의 narrowest-accepts first
|
||||||
|
- `plan_placement` (157+) — Stage A (B2 internal regions) + Stage B (region ↔ sub_zone) 통합
|
||||||
|
|
||||||
|
B4 는 *Layer 2 reader* 이지만 `src/phase_z2_pipeline.py:1060-1145` 에서 *trace-only* 로만 호출. render path (slot_payload 생성) 미연결. D4:78-83 의 *render path placement_trace 미사용* 과 일치.
|
||||||
|
|
||||||
|
### 1.5 capacity / fit — classifier (post-render telemetry)
|
||||||
|
|
||||||
|
`src/phase_z2_classifier.py` 의 `classify_visual_runtime_check` — *render 후* visual measurement 기반 fit 판정. *Architectural reframe* (D2:16-33 의 PLANNING / RENDER / POST-RENDER 3-layer) : A1~A4 = *post-render telemetry layer*. *덜 중요* 가 아니라 *위치가 다름*. 매칭 결정 자체에는 직접 입력 X (현재).
|
||||||
|
|
||||||
|
|
||||||
|
## §2. 확인된 혼선 (resolution)
|
||||||
|
|
||||||
|
### 2.1 Sub-zone 용어 4-방향 충돌 → 4-tier 분리 (P5'')
|
||||||
|
|
||||||
|
session 안 누적 혼선 :
|
||||||
|
- D1 의 "Zone (top / bottom_l / bottom_r 등)"
|
||||||
|
- composition.py 의 child unit 분리 (single / parent_merged 등)
|
||||||
|
- yaml 의 `sub_zones` field
|
||||||
|
- 사용자 mental model 의 "### split"
|
||||||
|
|
||||||
|
→ *4 tier 별 명칭 lock* :
|
||||||
|
|
||||||
|
| Tier | 명칭 | 위치 | 정체 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | **Layout** | slide-level | slide-body 안 zone topology (8-preset vocabulary) |
|
||||||
|
| 2 | **Zone** | layout 안 | 콘텐츠 구역 (top / bottom_l / bottom_r 등). 1 frame 매칭 단위 |
|
||||||
|
| 3 | **Split Zone (Child Unit)** | zone 안 | composition planner 가 만든 child unit (parent_merged 의 분리 단위) |
|
||||||
|
| 4 | **Frame Slot** | frame 안 | yaml 의 `sub_zones` = Layer B placement target. region 매칭 대상 |
|
||||||
|
|
||||||
|
이후 본 문서 / 후속 doc 은 *위 명칭 어휘* 만 사용. yaml field `sub_zones` 는 *기존 이름 유지하되 의미 = Frame Slot* 으로 lock (mechanical rename 은 D3 plan).
|
||||||
|
|
||||||
|
### 2.2 composition tie-break ≠ Frame Slot tie-break
|
||||||
|
|
||||||
|
scope-lock 단계에서 *D2:524-533 의 tie-break* 을 *composition tie-break evidence* 로 잘못 분류. 실제로는 :
|
||||||
|
- D2:524-533 = *Frame Slot 단위* tie-break (Stage B 안, frame 이미 선택된 후)
|
||||||
|
- composition tie-break = `composition.py:433-441` (sort + greedy + coverage)
|
||||||
|
|
||||||
|
두 layer 가 다름. P7 evidence 는 *composition layer* 만, *Frame Slot layer* 는 별개 location.
|
||||||
|
|
||||||
|
### 2.3 "Layer 2 미사용" framing 오류
|
||||||
|
|
||||||
|
scope-lock 초안의 *"mapper 가 Layer 2 를 consume 안 함"* framing 은 암묵적으로 *mapper 가 Layer 2 reader 가 돼야 한다* 의 fix direction 함의. 실제 architectural intent :
|
||||||
|
- mapper = Layer 1 binder (의도된 격리)
|
||||||
|
- B4 = Layer 2 reader (의도된 분리)
|
||||||
|
|
||||||
|
*문제* 는 *Layer 2 unconsumed* 가 아니라 *B4 의 Layer 2 read 가 trace-only 라 render path 까지 안 닿음*. *bridge* 가 답이지 *mapper 확장* 이 아님.
|
||||||
|
|
||||||
|
### 2.4 Step 4/5/9 분리 미완
|
||||||
|
|
||||||
|
현재 구현은 D1 이 의도한 *Step 4 → Step 5 → Step 9* 분리가 완성되지 않음 :
|
||||||
|
- Step 4 (composition planning input — section_layout_signature / content_object 구조) = *partial/dormant* (D4:73 의 ⚠ partial transition)
|
||||||
|
- Step 5 evidence 와 Step 9 final selection = *conflate* (D1:255)
|
||||||
|
|
||||||
|
D1:185 가 명시적으로 *Step 4 가 frame matching 보다 먼저 와야 함* 을 지적.
|
||||||
|
|
||||||
|
|
||||||
|
## §3. 도출된 원칙
|
||||||
|
|
||||||
|
### P1 : 매칭 단위 = `CompositionUnit` (section 아님)
|
||||||
|
|
||||||
|
- *근거* : `composition.py:230-243` (single) / `:260-273` (parent_merged) / `:352-368` (parent_merged_inferred). 각 line `:232` / `:262` / `:354` 가 `merge_type` signal
|
||||||
|
- *함의* : *MDX section* 을 1:1 zone 매칭 단위로 가정하는 코드 / doc 는 모두 *추상화 누락*. *CompositionUnit* 으로 통일.
|
||||||
|
|
||||||
|
### P3 : frame 선택 / content binding *layer 분리*
|
||||||
|
|
||||||
|
- *근거* : 현재 코드의 *de facto* 분리 (mapper §1.3 + placement_planner §1.4)
|
||||||
|
- *원칙* : frame *선택* (어떤 frame 을 쓸지) 과 content *binding* (선택된 frame 에 콘텐츠를 어떻게 채울지) 는 *별개 axis*. 함께 결정하면 search space 가 곱셈으로 폭발 + 실패 격리 불가.
|
||||||
|
- *함의* : 어떤 axis 가 frame 을 *결정* 하는지 + 어떤 axis 가 *binding* 하는지 *명시적 분리* — 한 module 이 둘 다 하면 회귀 위험.
|
||||||
|
|
||||||
|
### P5'' : 4-tier terminology lock
|
||||||
|
|
||||||
|
§2.1 표 그대로. *후속 doc / commit message / 코드 docstring* 모두 4-tier 어휘만 사용.
|
||||||
|
|
||||||
|
### P7 : candidate-based composition (sequential A/B 아님)
|
||||||
|
|
||||||
|
- *근거* :
|
||||||
|
- 원리 : `docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md:216-218` ("child 따로 / sibling 묶기 / parent 단위" + scoring inputs)
|
||||||
|
- 구현 : `composition.py:230-243` / `:260-273` / `:352-368` (3 candidate type 동시 생성)
|
||||||
|
- 선택 : `composition.py:433-441` (`(score desc, source_section_ids count desc)` + greedy covered skip)
|
||||||
|
- *원칙* : composition 은 "## → fail → ### split → re-merge" sequential 이 아니라 *3 candidate type 을 동시 생성 → score + coverage tie-break* 의 *parallel evaluation*.
|
||||||
|
- D2:524-533 은 *Frame Slot tie-break (Stage B)* 로 본 P7 evidence 와 *별도 layer*.
|
||||||
|
|
||||||
|
### P8 : staged migration — frame 선택 authority + binding 진화 분리
|
||||||
|
|
||||||
|
#### P8-a (near-term)
|
||||||
|
|
||||||
|
- *목표* : frame selection authority 정리 (V4 rank-1 단독 → B4 informant 또는 B4-mediated 의 *어떤 형태*)
|
||||||
|
- *유지* : mapper binding channel (PAYLOAD_BUILDERS) — 현재 working channel 안전
|
||||||
|
- *open* : B4 결과를 render path frame selection 에 *어떻게 반영* 할지의 bridge 형태 → §5 의 Q-V4B4 / Q-LB 에서 별도 scope-lock
|
||||||
|
|
||||||
|
#### P8-b (longer-term, *지금 결정 X*)
|
||||||
|
|
||||||
|
- region / Frame Slot-aware slot_payload 진화
|
||||||
|
- PLACEMENT_PAYLOAD_BUILDERS 등 별도 namespace 가능성
|
||||||
|
- *DC2 Open question (Q-LB) 해결 후* 결정. 본 문서 시점에서는 *deferred*.
|
||||||
|
|
||||||
|
|
||||||
|
## §4. 코드 변경 결정 지점
|
||||||
|
|
||||||
|
### DC1 : Step 4/5/9 분리 미완
|
||||||
|
|
||||||
|
- *현 상태* : D1 의도한 Step 4 → Step 5 → Step 9 분리가 완성되지 않음. Step 4 (composition planning input — section_layout_signature / content_object 구조) 는 *partial/dormant* (D4:73 의 ⚠ partial), Step 5 evidence 와 Step 9 final selection 은 *conflate* (D1:255).
|
||||||
|
- *결정 지점* :
|
||||||
|
- Step 4 가 frame matching *전* 에 composition candidate 평가 input 으로 흘러야 (D1:185 명시적 지적)
|
||||||
|
- Step 5 evidence layer 와 Step 9 final selection layer 의 *명시적 분리* 필요
|
||||||
|
- *영향 module* : `src/phase_z2_pipeline.py` orchestrator + `src/phase_z2_composition.py` (input 확장)
|
||||||
|
|
||||||
|
### DC2-a : `phase_z2_mapper` = Layer 1 working channel
|
||||||
|
|
||||||
|
- *현 상태* : `src/phase_z2_mapper.py:584-609` 가 `source_shape` + `payload.builder` 만 read. *현재 render path 의 유일 working channel*.
|
||||||
|
- *결정 지점* : *Layer 1 격리 유지*. mapper 에 Layer 2 read 를 추가하는 방향은 *반대* — 실제 의도는 별 axis (DC2-b + Open question Q-LB).
|
||||||
|
|
||||||
|
### DC2-b : `phase_z2_placement_planner` = Layer 2 reader, render path 미연결
|
||||||
|
|
||||||
|
- *현 상태* : `src/phase_z2_placement_planner.py:90-107` (accepted_content_types) + `:113-151` (sub_zones) — Layer 2 read 활성. 그러나 `src/phase_z2_pipeline.py:1060-1145` 에서 *trace-only*. final render 미연결.
|
||||||
|
- *결정 지점* : Layer 2 read 결과를 render path 에 *어떻게 합류시킬지* 의 bridge 결정 — §5 의 Q-LB 에서 별도 scope-lock.
|
||||||
|
|
||||||
|
### DC3 : Internal Region runtime — trace-only partial
|
||||||
|
|
||||||
|
- *현 상태* : SPEC v1 (D2) 가 Internal Region (Layer A) / Frame Slot (Layer B) 의 layered placement 정의. Layer A runtime 은 *trace-only partial* — `src/phase_z2_placement_planner.py:157+` 의 `plan_placement` 가 Stage A 호출 (`:192-197` 의 `plan_internal_regions` call) 수행하지만, 결과가 render path 미합류. *부재* 가 아니라 *render path authority 미연결*. D4:73 의 ⚠ partial 분류와 일치.
|
||||||
|
- *결정 지점* : Layer A planning telemetry 활성 단계 → render path 합류 단계의 *separate axis*. P8-b 와 연관 (slot_payload 진화 이전 단계).
|
||||||
|
|
||||||
|
|
||||||
|
## §5. open scope-lock questions
|
||||||
|
|
||||||
|
본 axis 범위 *밖* 의 deferred 결정. 후속 axis 에서 각각 별도로 lock.
|
||||||
|
|
||||||
|
### Q-FW : 4 filter score weight / threshold
|
||||||
|
- F1 frame internal fit / F2 child frame divergence / F3 content type-structure match / F4 content loss risk 의 *score weight* 와 *auto vs review threshold* 결정 필요.
|
||||||
|
|
||||||
|
### Q-CO : candidate priority tie-break
|
||||||
|
- composition.py:433 의 `(score, source_section_ids count)` 외에 *추가 axis* (cardinality_fit / hierarchy_coherence / density) 도입 시점.
|
||||||
|
|
||||||
|
### Q-RT : review / adapter_needed threshold
|
||||||
|
- W1/W2/W3 신호 + auto_selectable=False candidate 의 review surface 정책.
|
||||||
|
|
||||||
|
### Q-V4B4 : V4 → B4 frame selection authority transition timing
|
||||||
|
- P8-a 의 *언제* — V4 단독 / B4 informant / B4-mediated 의 단계.
|
||||||
|
|
||||||
|
### Q-LB : Layer 1 ↔ Layer 2 bridge architecture
|
||||||
|
- DC2-b 의 *어떻게* — mapper direct consume / B4-mediated integration / 별도 translator. Q-V4B4 와 연관되나 *별개 layer* (frame 선택 timing vs Layer 2 → render path bridge 구조).
|
||||||
|
|
||||||
|
### Q-CE : catalog extension surface
|
||||||
|
- frame_contracts.yaml 에 신규 frame 추가 시 *어떤 layer 부터 채워야 self-consistent* 인지의 declarative form.
|
||||||
|
|
||||||
|
### Q-DT : decision trace 표준 form
|
||||||
|
- composition / placement / fit_classification 의 trace 통합 schema. 현재 각각 다른 dict 구조.
|
||||||
Reference in New Issue
Block a user