# Rooftop Spatial Pipeline Plan — plan v1 (Codex APPROVED)

> Codex sanity 2026-05-23 → APPROVED_FOR_DRY_RUN_IMPLEMENTATION.
> Q1: JSON nodes/edges SOT, HTML 단순 table. mermaid 선택.
> Q2: classify_sub_space / assign_camera_slot 등 기존 함수 재사용 (local adapter, generation/client path X).
> Q3: recommended_base_plate_count + current 4 비교 (delta + reason) 자동 산출.
> Q4: 9-grid enum (foreground/midground/background × left/center/right).
> Q5: placeholder enum {dotted_box, translucent_shape, color_box, none} — 인체=translucent_shape (design reco only, 이번 wave render X), 소품=color_box, 클로즈업/위험 시 none.
> 추가: camera_slot_plan 에 `slot_role` ∈ {shared_base, shot_specific, rejected_manual_review}.


> **목적**: 옥탑방 배경 이미지 한 장이 아니라, **end-to-end 정보 흐름 검증**. 어떤 단계에서 어떤 형태로 공간/카메라/엔티티 정보가 추출·전달되어야 최종 배경 이미지까지 일관성 있게 도달하는지 dry-run plan.
>
> 이미지 생성 / Gemini 추가 호출 0. 기존 산출물 (source grounding + spatial bg) 만 소비.

## 0. 절대 규칙
- standalone (`backend/scripts/experiment_rooftop_spatial_pipeline_plan.py`). production 0 수정.
- 이미지 생성 0, Gemini 호출 0, DB write 0.
- 출력: `scripts_output/rooftop_spatial_pipeline_plan/<run_id>/`
- 기존 base plate 이미지는 copy 해서 inline.
- HTML quote limit 140 (이전 wave 와 동일 규칙).

## 1. 입력 (Phase η 확정)

| source | path | found |
|---|---|---|
| source grounding bible | `scripts_output/rooftop_source_grounding/codex_entry_sanity_gemini_ok/gemini_rooftop_bible.json` (15 필드 완전) | ✅ |
| source evidence | `.../source_evidence.tsv` (241 rows) + `.json` | ✅ |
| spatial bg base plate | `scripts_output/rooftop_spatial_bg_experiment/20260523_1956_d22e35/base_plates/*.png` (4) | ✅ |
| LVM realized card | `.../realized_spatial_cards/*.json` (4, 모두 trusted) | ✅ |
| 14 L05 selected shots | `SceneStill` DB read-only (project 6cb862d9, episode 08ad2cd3) | ✅ |

기본값: source = `codex_entry_sanity_gemini_ok`, spatial = `20260523_1956_d22e35`. CLI 로 override 가능.

## 2. Stage A — Related info / inference cards

Gemini bible 그대로 쓰지 않고 5 cards 로 변환 (사용자 명세).

### A-1. set_identity_card
- name: 옥탑방 내부 (L05)
- tone: bible.socioeconomic_tone (서민적·소박)
- scale_density: bible.scale_density (거실 겸 주방 + 방 두 개 + 욕실 — 밀집된 좁고 한정)
- condition_age: bible.condition_age (오래된)
- evidence_quotes: bible 각 필드의 evidence 합산
- confidence: bible 의 confidence_band 다수결

### A-2. set_topology_card (graph)
- **nodes**: bible.sub_spaces + 외부 노드 (rooftop_outer, entry_door)
  - id, label, kind=`{living_kitchen, bedroom, bathroom, entry, outer}`, confidence, evidence
- **edges**: bible.layout_relations + doors_windows 로 보강
  - from, to, kind=`{door, opening, window_view, stairs}`, confidence=`{direct, inferred, unknown}`, evidence
- known / inferred / unknown 분리 — confidence 별로.

### A-3. production_design_inference_card
- bible.required_visual_cues + bible.furniture + bible.materials 합쳐 미술감독 방어 가능 inference items:
  - item_id, category=`{door, window, fixture, furniture, finish, lighting, prop}`, description (qualitative), source_evidence_ids[], confidence=`{direct, strong_inference, weak_inference, unknown}`, derived_from
- 예: 작은 창문 → "small single-pane window with daylight only" (direct), 낡은 철문 → "weathered steel door, faded paint" (strong_inference from "바람에 덜커덩거리는 낡은 현관 철문")

### A-4. forbidden_drift_card
- bible.forbidden_luxury_cues + 추가 deterministic luxury list
- 각 item 에 reason (왜 source 와 어긋나는지 evidence quote)

### A-5. state_overlay_card
- bible.state_variants (4: normal / corpse_blood / cleaned / vandalized)
- 각 state 의 환경 마감 (silhouette/시신 metallic — 인체 0, Phase D Codex Blocking 2 그대로)
- 공간 identity 와 분리 — overlay 만 변함, 공간 그대로

산출: `inference_cards.json` (5 cards in 1 file).

## 3. Stage B — Camera slot planning

14 L05 shot 의 camera slot 을 clustering. 기존 `experiment_rooftop_spatial_bg.py` 의 classifier (sub_space + framing) 직접 재사용 또는 import.

각 slot:
- slot_id (e.g. `slot_main_room_eye_level_wide`)
- used_by_shots (shot label list)
- base_space_node (topology 의 노드 id)
- camera_anchor (qualitative — "거실 중앙 standing eye-level")
- looking_toward (qualitative — "식탁/주방 정면", "방 입구 안쪽")
- visible_nodes[] (topology nodes 가 frame 안에 보임)
- offscreen_nodes[] (인접하지만 frame 밖)
- preserve_constraints[] (이 slot 의 모든 shot 이 공유해야 할 layout 제약 — 예: "수리영 방 침대는 항상 왼쪽 벽")
- reason / evidence
- confidence

**핵심 원칙** (사용자 명시): camera slot 없이 base plate 생성 X — 방향성 부재.

산출: `camera_slot_plan.json` + TSV.

clustering rule (deterministic):
- 같은 sub_space + 같은 framing 키워드 → 같은 slot
- close 변종 (식탁 close vs 욕실 거울 close) 은 별도 slot (사용 가구가 다름)
- 사용자 정의 override slot (CLI 옵션) 가능

## 4. Stage C — Base plate plan

camera slot clustering 결과로 필요한 base plate 산출:
- 같은 base_space_node + 인접 slot 들이 같은 camera anchor 면 하나의 base plate 로 통합 가능
- 다른 looking_toward 면 별도 base plate 필요

각 base plate:
- base_plate_id (e.g. `bp_main_room_eye_level_wide_west`)
- covers_nodes[] (해당 plate 가 보여주는 topology nodes)
- camera_slot_ids[] (이 plate 가 서비스하는 slot 들)
- must_show (production_design_inference 의 must items)
- must_not_show (forbidden_drift_card 의 items)
- shared_consistency_constraints (예: "식탁 위치는 항상 화면 중앙", "창문은 항상 왼쪽 벽")
- overlap_with_other_base_plates (어느 nodes 가 다른 plate 와 겹치는지 — 일관성 검증용)
- generation_prompt_payload (실 호출 X, draft 만 — Stage D 의 source)

산출: `base_plate_plan.json` + TSV.

**base plate 수**: 4 무조건 아님 — clustering 결과로 제안. 현재 spatial bg run 4 plate (main_room×2, bedroom, bathroom) 와 비교 표시.

## 5. Stage D — Shot background payload

14 shot 각각:
- shot_id (S5_S2 등)
- camera_slot_id (Stage B 의 slot)
- base_plate_id (Stage C 의 plate)
- state_overlay (state_overlay_card 의 한 state)
- visible_entities[] (DB visible_entities_json 그대로)
- entity_layout_markers[]:
  - entity_id, kind (`character | prop`), approximate_zone (foreground_left 등 9-grid), scale_hint (qualitative), contact_surface (`floor | bed | table | wall`), pose_hint (qualitative), render_as_placeholder (boolean)
- i2i_background_prompt_payload (draft):
  - preserve_layout (base plate 의 무엇을 보존)
  - may_change_state_overlay (어느 state element 변경)
  - must_not_change (Stage C 의 shared_consistency_constraints 상속)
  - remove_placeholder_instruction (silhouette/placeholder 처리 텍스트)

**placeholder 처리 결정**: shot 별 추천 (점선 박스 / 반투명 silhouette / 색 박스 / 없음). 인체 silhouette 자체는 final scene 단계로 미룸 (Phase D Codex Blocking 2 정책 유지).

산출: `shot_background_payloads.json` + TSV (각 shot 의 entity_layout_markers 표).

## 6. Stage E — HTML report (7 sections)

1. **Source grounding summary** — bible 15 필드 요약 (이전 wave 산출물 inline link)
2. **5 inference cards** — set_identity / topology graph (table 또는 mermaid) / production_design_inference (item table) / forbidden_drift / state_overlay
3. **camera slot plan** — table: slot_id / shots / anchor / visible / preserve / confidence
4. **base plate plan + existing thumbnails** — 기존 4 base plate copy + plan 의 base_plate_id 매핑 (현재 4 vs 제안 N 비교)
5. **shot background payloads** — base_plate_id 기준 grouping, 각 shot 의 entity_layout_markers 표
6. **entity layout marker table** — 14 shot × entity rows
7. **open questions / unknowns / risks** — bible.unknowns + bible.inference_limits + clustering 의 confidence 낮은 항목

기존 base plate PNG + LVM JSON 은 `base_plate_assets/<spatial_run_id>/` 로 copy.

## 7. CLI

```
backend/scripts/experiment_rooftop_spatial_pipeline_plan.py
  --run-id <id>
  --source-grounding-dir <path>  # default 최근 또는 codex_entry_sanity_gemini_ok
  --spatial-bg-dir <path>        # default 20260523_1956_d22e35
  --no-serve / --serve-port 8768 / --bind 127.0.0.1
  --estimate-only
```

`--generate` 옵션 없음 — 이번 wave 는 dry-run only (이미지/Gemini 호출 0).

## 8. Tests
- source bible → 5 cards transform unit (각 card 의 필수 필드 / evidence 연결)
- camera slot clustering deterministic 4 케이스:
  - S5_S2/S5_S6 → main_room eye_level_table_close
  - S12_S4/S12_S6/S12_S14 → bedroom eye_level_doorway_wide
  - S18_S5/S18_S9 → bathroom eye_level_mirror_close
  - S27_S1/S27_S4 → main_room eye_level_wide (Phase C v2 분류 그대로)
- base plate plan: shared_consistency_constraints emit (예: 식탁 위치)
- shot payload: visible_entities + placeholder recommendation 포함
- HTML 7 sections 모두 포함
- inline assets copy (base_plate_assets/<spatial_run_id>/ 안에 PNG 존재)

## 9. import 범위
- `app.core.database.SessionLocal`, `app.models.project.SceneStill`
- 기존 산출물 path read-only
- (선택) `backend/scripts/experiment_rooftop_spatial_bg.py` 의 classifier 함수 import 재사용 — 코드 중복 회피 (sys.path 통해)

비 import:
- production scene_image_pipeline / scene_generation_coordinator
- ImageReviewService
- GeminiTextClient / OpenAI client (이번 wave 호출 0)

## 10. Out of scope
- 실 이미지 생성 (Phase D 별도 결정)
- production prompt 변경
- DB schema 변경
- Gemini bible 재호출 (기존 산출물 재사용)
- chain_bg / floor_plan 재설계 (별도 wave)

## 11. Codex 결정 요청 (Phase θ)

Q1. 5 cards 의 set_topology_card 표현 — JSON nodes/edges + HTML 에 mermaid graph? 아니면 단순 table?
Q2. camera slot clustering — 기존 `experiment_rooftop_spatial_bg.py` 의 classifier 함수 (sys.path import) 재사용 vs 새 함수 작성? 의존 가시화 vs 단순성.
Q3. base plate 수 — 현재 4 와 비교 후 줄이거나 늘리는 권고를 자동 산출하나? 또는 그냥 같은 수 + clustering 만 표시?
Q4. shot payload 의 entity_layout_markers approximate_zone enum — Phase D LVM 의 9 grid (foreground/midground/background × left/center/right) 그대로?
Q5. placeholder recommendation rule — 인체 0 정책 유지 (silhouette 도 X) 그대로? 즉 placeholder 종류는 "dotted_box | translucent_shape | color_box | none" 4 enum?
