# Phase I (옥탑방 시신 V2) — Dependency Inventory

> 작성 2026-06-28. 목적: Phase I 구현 착수 전 의존성 고정. **통째 stash pop 금지**, 필요 hunk만
> HEAD 기준 narrow 재구현. **Phase I 커밋과 Phase II(정류장) 커밋 절대 분리.**
> 출처 메모리: [[session-20260628-corpse-outdoor-production-plan]] / [[session-20260620-p8-immobilized-continuity]]
> / [[session-20260627-twod5-bfirst-poc]] (corpse_human V2) / [[session-20260627-registered-pose-guide-handfloat]].

---

## 0. 현재 git 상태 (2026-06-28)

- branch: `feat/w19-w20-bg-planning-cleanup`, HEAD = `2e7eb423` (P8 코드 **0** — 전부 stash).
- **stash@{0}** = `P8 immobilized continuity (Inc1/2a/2b/3a/3b) — withdrawn 2026-06-25`.
  13파일 +1586/-75. **Inc1~Inc3-B 한 덩어리로 섞임** — 통째 pop = 폐기된 Inc3-B(white-bg) 포함.
- working tree 변경 = untracked만(docs/w21b-*, geom_bird_v7/, *.pdf) → **전부 Phase I 무관**.
- stash@{1}/{2} = 옛 pipeline-v3 WIP, 무관.

### Phase I 관련 / 무관 분리

| 항목 | 분류 |
|---|---|
| stash@{0} (P8 13파일) | **Phase I 선행 소스** (narrow 재구현 대상) |
| stash@{1}, stash@{2} | 무관 (옛 브랜치 WIP) |
| untracked docs/w21b-*, geom_bird_v7/, *.pdf | 무관 (Phase I 미접촉) |
| `~/tmp/geum_panel_sheet/*` (twod5_poc 등) | 무관·**절대 커밋 금지** (PoC 출처일 뿐) |

---

## 1. HEAD에 **이미 커밋된** 선행 기반 (재구현 불필요)

P8는 zero에서 시작하지 않는다. 아래는 HEAD에 있으므로 Phase I이 **그 위에 얹는다**.

| 기반 | HEAD 위치 | 출처 커밋 | Phase I 의미 |
|---|---|---|---|
| `is_immobilized_state` / `IMMOBILIZED_STATES{unconscious,dead,severely_injured}` | `app/core/subject_state.py:16,25` | (기존) | Inc1 seed detector가 import |
| 기존 immobilized lock (구 feedback6-C) | `prompt_service.py:253` "keeps EXACTLY the same pose…" | `acdadba5 W21B-W7 W1` | Inc3-A가 **이 위 델타** |
| `immobilized_subjects` ref_role_metadata 소비 | `prompt_service.py` + `scene_reference_service.py:1346` | `acdadba5` | Inc3-A/B가 이 메타 활용 |
| `character_state_ref` ref role + enum + render branch | `prompt_service.py:36,365` / `scene_reference_service.py:531` (section 1 composite state-variant) | `48dc2564 area-11 W2` | Inc2-b가 **이 role 재사용** |
| 기반 VCA (zoom + printed_prop anchor) | `visual_continuity_anchor_{plan,provider}.py` (`app/modules/pipeline/`), `_step.py` (`app/core/steps/`) | (기존) | Inc1이 신규 anchor_type 추가 |
| `build_image_index` (★**regex-only** 라벨링, line 99) | `scene_reference_service.py:99` | (기존) | **I-2 의존 핵심** ↓ |

> ★**결정적 사실**: HEAD `build_image_index`는 sidecar role을 **라벨링에 안 쓰고** regex(`character\s+(C\d…)`)
> 로만 라벨을 만들며 `t2i_prompt`(passport) 우선. 따라서 Inc2-b가 붙이는 dead 라벨
> `"character C04 — dead state reference"` 도 regex가 잡아 **passport를 주입** → 시신이 alive 여권사진 받음.
> ⇒ **I-2(Inc2-b)는 Inc2-a(descriptor 재작성)에 의존**한다.

---

## 2. stash@{0} 증분별 매핑 (= narrow 재구현 소스, HEAD 기준 델타)

| Inc | 무엇 | stash 파일·hunk | 이전 판정 | Phase I 역할 |
|---|---|---|---|---|
| **Inc1** | 공유 포즈/상태 **텍스트** 계약 | `config.py`(immobilized flags), `plan.py`(ANCHOR_TYPE_IMMOBILIZED, detect/select/build_…seeds, validator), `provider.py`(IMMOBILIZED_SUBJECT_SCHEMA/SYSTEM, extract_…), `_step.py`(load_…context, _execute seed/LLM, _immobilized_body_pose, _related_zoom_evidence), `detail_steps.py`(주입 블록), test_plan(+7) | **acceptance PASS** | **기반 — 필수, 그대로** |
| **Inc2-a** | 식별 descriptor 라벨 (build_image_index 재작성, **전샷 영향**) | `scene_reference_service.py`(`_identity_descriptor` + build_image_index 재작성), test_scene_ref | **APPROVED** | **I-2 선행 의존** (라벨 passport 제거) |
| **Inc2-b** | bare C## **dead-state passport ref** | `scene_reference_service.py`(section 2.5 state-variant 분기), `ref_contract_validator.py`(step 3b), test | **acceptance PASS** | **= I-2** |
| **Inc3-A** | prompt pose-lock (텍스트) | `prompt_service.py`(W3 standing/moving 한정 + lock 강화: support surface/contact/"image wins") | 부분개선 (prompt-only 천장) | **I-3 일부** |
| **Inc3-B** | **white-bg** 마네킹 pose sketch (시각 anchor) | `config.py`(pose_sketch flags), `provider.py`(IMMOBILIZED_SKETCH_PROMPT/TECH, build_…prompt, generate_…sketch=**text-only** `generate_floor_plan_image`), `_step.py`(생성 hook, _resolve client, attach_…ref, IMMOBILIZED_POSE_GUIDE_LABEL), `prompt_service.py`(immobilized_pose_guide REF_ROLE + render branch + pose_guide_present), `scene_generation_coordinator.py`(single+batch attach), test_payload | **2026-06-25 강등** (마네킹 anchor ≠ establishing 포즈; white-bg가 지지면 발명) | **플러밍 재사용 + 생성부만 I-1로 교체** |

---

## 3. Phase I (V2) 목표 ↔ 증분 대응

V2 = corpse_human PoC 검증형: **bg-aware 등록 가이드 + dead passport + real-human 단언 + pose-only 라벨**.

### I-1 — 배경-aware 등록 pose 가이드 (NEW, Inc3-B 대체/연장)
- Inc3-B의 **플러밍 전부 재사용**: `immobilized_pose_guide` REF_ROLE, `attach_immobilized_pose_sketch_ref`,
  prompt_service render branch, loader `pose_sketch_path` 노출, `_execute` 생성 hook, coordinator attach.
- **교체 지점 1개**: `generate_immobilized_pose_sketch` 가 현재 `generate_floor_plan_image(text-only,
  흰배경)` → **bg plate underlay 위 등록**(`gpt-image-2 images.edit`, PoC `make_underlay`+edit). has_bg 분기.
- **게이트 강화(Codex refined)**: VCA immobilized group + shared_state_contract/support/contact 존재
  + 멤버에 **실제 bg/space/background plate bytes** 존재 + 그 bg가 target location/space env ref —
  **전부 충족 시에만** 등록 가이드. 실패 → **non-blocking diagnostic + Inc3-B white-bg/old path fallback**
  (즉 Inc3-B는 폐기 아니라 **fallback 경로로 강등 보존**). close/insert = registered master **ROI crop**,
  wide/medium = whole master.
- role 분리 명확: 등록 guide=pose/contact/support SOT, bg plate=environment/material SOT,
  character_state/dead ref=identity/state SOT.

### I-2 — dead-state passport identity ref
- = **Inc2-b** (section 2.5 분기 + validator step 3b) **+ 선행으로 Inc2-a 필요**(§1 regex 사실).
- ★scope 결정 필요(Codex): Inc2-a를 (a) 통째(전샷 descriptor) vs (b) character_state_ref 라벨 경로만 narrow.

### I-3 — real-human 단언 + pose-only 라벨 (+ humanize?)
- Inc3-A(pose-lock) + Inc3-B render branch에 **이미** "render as the real clothed person… NEVER from
  the mannequin" + "do NOT draw mannequin/joints/construction lines" 존재 → **상당 부분 기존 플러밍에 있음**.
- 추가 후보: `REAL_HUMAN_ASSERT`(실인간 positive + mannequin/doll/statue negative)를 **final consumer
  label/prompt에만**. ★humanize(마네킹어→인간어)는 production `shared_state_contract`가 IMMOBILIZED_SUBJECT_SYSTEM
  으로 **이미 human-phrased**(이름0·구조적 묘사)면 **불필요** — 확인 후 결정. gore 증가 금지.
- ★Codex 합의: real-human 단언은 anchor extraction/shared_state_contract에 **넣지 않음**, final render만.

---

## 4. Phase I 의존 체인 (구현 순서)

```
Inc1 (텍스트 계약 기반)
  → Inc2-a (descriptor 라벨; I-2 선행)
    → Inc2-b (= I-2 dead passport)
  → Inc3-A (pose-lock 텍스트; I-3 일부)
    → Inc3-B 플러밍 (REF_ROLE/attach/render/loader/생성hook)
      → I-1 (생성부 bg-aware 교체 + 게이트 강화 + ROI crop)   ← NEW
      → I-3 (REAL_HUMAN_ASSERT + pose-only 라벨 강화)          ← NEW (대부분 기존 플러밍)
```

flag (전부 default OFF, 단계 게이트):
`visual_continuity_anchor_enabled` AND `immobilized_subject_continuity_enabled`
AND `immobilized_pose_sketch_enabled` (+ I-1용 신규 bg-aware sub-flag 후보).

---

## 5. ★ 결정 포인트 — Codex 리뷰 완료 + 합의 (2026-06-28)

| DP | 결론 (Codex 권고 + Claude 수용) |
|---|---|
| **DP1 재구현 방식** | **B = patch-assisted narrow reimplementation.** stash 를 SOT patch 로 두고 Inc별 필요 hunk 만 HEAD 에 기계 선별 적용. **stash pop 금지.** Inc3-B 는 **plumbing 만** 재구현, **생성부(white-bg)는 살리지 않음.** Inc별 logical commit 후보로 stage, 커밋은 GO 전 보류. |
| **DP2 Inc2-a scope** | **full descriptor 버전**(이전 APPROVED). 라벨 SOT 를 sidecar/ref_role_metadata 로 (character/prop/outfit/state 전체). 단 **"descriptor label prerequisite" 로 분리** — Phase I 본체와 별 commit + 샘플 prompt_used 재확인. (HEAD section1 composite state-variant 도 현재 regex→passport 누출 → Inc2-a 가 이 잠재 결함도 고침.) |
| **DP3 humanize** | **별도 humanize 변환기 생략.** shared_state_contract 는 이미 human-phrased(이름0·구조적) → anchor/contract 미변경. real-human/pose-only 지시는 **final consumer = prompt_service role branch 에만**: "pose guide=pose/contact/support 만, 인물은 character_state ref+prompt 따라 실제 사람, mannequin/doll/statue/sketch/guide lines 복사 금지". |
| **DP4 sub-flag + fallback** | **신규 sub-flag** `immobilized_registered_pose_guide_enabled` (게이트: `visual_continuity_anchor_enabled` AND `immobilized_subject_continuity_enabled` AND `immobilized_pose_sketch_enabled` AND 본 flag). ★**Codex 정정 수용**: bg-aware prerequisite 실패 시 fallback = **white-bg 자동 부착 금지** → **no visual guide + text contract/dead state ref** (non-blocking diagnostic). white-bg 는 지지면 발명으로 강등된 경로라 silent fallback = harm 재유발. legacy white-bg 는 실험/A-B flag·diagnostic path 로만 ("guide is not default" 원칙). |

---

## 6. ★ Phase I 최소 구현 확정안 (GO 대기) — patch-assisted narrow, 5 logical commits

전부 flag **default OFF**, 하드코딩 0, **Phase II 와 커밋 절대 분리**, 커밋은 **사용자 GO 후에만**.
방식: `stash@{0}` diff 를 Inc별로 export → 필요 hunk 만 HEAD 에 적용(stash pop ❌).

| # | logical commit 후보 | 적용 hunk (stash 출처) | flag | 검증 |
|---|---|---|---|---|
| **A** | **Inc1** 텍스트 연속성 계약 | config(immobilized flags), plan(seeds/select/build/validator), provider(SCHEMA/SYSTEM/extract), step(loader+execute+helpers), detail_steps(주입), test_plan(+7) | `immobilized_subject_continuity_enabled` | 단위(seed gate) + dry-run(이름0·계약 일관) |
| **B** | **Inc2-a** descriptor label **(prerequisite, 전샷영향)** | scene_reference_service(`_identity_descriptor`+build_image_index 재작성), test | (flag 무관, 전샷) | 샘플 prompt_used 3샷(passport/이중prefix 0) |
| **C** | **Inc2-b = I-2** dead passport ref | scene_reference_service(section2.5 state-variant 분기), ref_contract_validator(step3b), test | (B 위) | regen: dead variant bytes + ref_contract 통과 |
| **D** | **Inc3-A** pose-lock 텍스트 | prompt_service(W3 standing/moving 한정 + support/contact/"image wins") | (immobilized meta gate) | prompt_used 문구 확인 |
| **E** | **I-1 registered pose guide** (Inc3-B plumbing 재구현 + bg-aware 생성 + I-3 label) | config(신규 sub-flag), step(REF_ROLE 부착 helper/loader pose_sketch_path/생성 hook), prompt_service(immobilized_pose_guide render branch + real-human/pose-only=I-3), coordinator(attach single+batch). **생성부=bg plate underlay `gpt-image-2 edit`**(white-bg 대체), 게이트(VCA imm group + contract/support/contact + **bg plate bytes 존재** + bg=target location env ref), close/insert=ROI crop·wide/medium=whole master, **실패=no-guide diagnostic** | `immobilized_registered_pose_guide_enabled` | canary(가이드 생성/부착 dry-run) + 육안 갤러리 8898 |

### 구현 전 확인할 implementation-time 항목 (blocker 아님)
- **bg plate bytes 가용 시점**: VCA(visual_continuity_anchor) step 생성 시점에 target location/space
  background plate bytes 가 이미 존재하는지 확인. 없으면 게이트가 영구 미발동 → no-guide fallback(안전하나
  registered guide 가 무의미). 필요 시 부착을 scene_generation 시점(plate 존재 보장)으로 옮길지 검토.
- **ROI crop 좌표**: insert 샷의 contact ROI 를 anchor 의 per_shot_visible_focus / framing enum 에서
  구조적으로 도출(좌표 하드코딩 0). PoC 의 eyeball ROI 는 production 미반영.

> Phase II(정류장 shared-model)는 본 인벤토리 범위 밖. outdoor 경로:
> `app/core/steps/outdoor_site_layout_step.py`, `app/modules/pipeline/outdoor_site_layout_{plan,provider}.py`.
> **Phase I 커밋과 절대 분리.**

---

## 7. ★ Commit E (I-1 registered pose guide) 구체 설계 — ★구현 전 Codex 리뷰 대상

### 진행 상태 (2026-06-28)
- **A/B/C/D 적용 + 결정론 검증 완료**(미커밋): A(Inc1) 단위 25+45+24 green / B(Inc2-a) 103 green
  / C(Inc2-b) 신규4+186 green / D(Inc3-A) 20 green. 전부 flag OFF, scope 클린.
- **E = 신규 설계**(stash 재구현 아님). 아래 ★아키텍처 변경이 stash Inc3-B 와 달라 Codex 리뷰 필요.

### ★ 결정적 발견 — 생성 시점을 옮겨야 함
step order 실측: `visual_continuity_anchor`=**21.66**(analysis) / `background_render`=**24.72**(image)
/ `scene_image_pipeline`=**25**. → **VCA step(21.66) 시점엔 bg plate 가 아직 없다.** stash Inc3-B 는
white-bg 라 VCA step 에서 text-only 생성했지만, **bg-aware 등록 가이드는 plate 가 존재하는 image phase
(≥24.72)에서 생성해야 한다.** 따라서 생성을 `scene_generation_coordinator`(이미 bg plate 보유)로 이동.

### E 아키텍처 (확정 제안)
1. **VCA step(21.66)**: Inc1 텍스트 계약만(commit A 그대로). **sketch 생성 hook 미복원**(plate 부재).
   loader 는 anchors_by_group(shared_state_contract+locked_elements+per_shot_visible_focus) 제공.
2. **scene_generation_coordinator(image time)**: 멤버 샷 렌더 시 —
   - 이 샷의 target location/space **bg plate bytes 해결**(coordinator 가 이미 background_chain 으로 보유).
   - **게이트**: `immobilized_registered_pose_guide_enabled` ON AND 이 샷이 immobilized group 멤버 AND
     계약에 support/contact 존재 AND **bg plate bytes 실재**. 하나라도 불충족 → **no-guide(diagnostic)**.
   - **첫 멤버 샷**에서 등록 가이드 생성(`make_underlay(bg_plate)`[PoC PIL faint underlay] +
     `build_registered_guide_prompt(subject_anchor)`[contract+locked desc, 마네킹 등록·gore0·text0] +
     `gpt-image-2 images.edit`) → group_id 로 **디스크 캐시**(`images/immobilized_pose_guides/<gid>.png`).
     이후 멤버 샷은 캐시 재사용.
   - **close/insert**: 캐시 master 의 **ROI crop**(per_shot_visible_focus/framing enum 기반, 좌표 하드코딩0).
     wide/medium: whole master.
   - `immobilized_pose_guide` ref 부착(Inc3-B plumbing 재구현).
   - ★**no-white-bg fallback**(DP4): 등록 실패 시 white-bg 자동 부착 금지 → 가이드 생략 + diagnostic.
3. **prompt_service**: `immobilized_pose_guide` REF_ROLE + render branch(Inc3-B 재구현) + **I-3 REAL_HUMAN_ASSERT
   강화**(pose/contact/support 만 차용, 마네킹/관절선/wooden look 복사금지, 실인간 렌더=identity ref+본문) +
   zoomed-frame lock 의 pose_guide_present 정렬(D 의 `_has_immobilized` lock 을 가이드와 정렬).

### E 파일 (전부 신규 sub-flag `immobilized_registered_pose_guide_enabled` 게이트, default OFF)
- `config.py`: 신규 sub-flag(+ underlay variant/model 등 필요 최소).
- `visual_continuity_anchor_provider.py`(또는 신규 helper 모듈): `make_underlay`(PIL)+
  `build_registered_pose_guide_prompt`+`generate_registered_pose_guide`(gpt-image-2 edit). PoC 헬퍼 generic 이식.
- `visual_continuity_anchor_step.py`: `IMMOBILIZED_POSE_GUIDE_LABEL`(=PoC CORPSE_HUMAN_GUIDE_LABEL, pose-only)
  + `attach_immobilized_pose_sketch_ref`(Inc3-B plumbing 재구현).
- `scene_generation_coordinator.py`: 멤버 샷 렌더 시 생성/캐시/ROI crop/attach(위 2).
- `prompt_service.py`: REF_ROLE + render branch + I-3 + pose_guide_present 정렬.
- 신규 test(유실분 재작성): label routing / attach / ref_contract 방어 / REF_ROLE_VALUES invariant.

### ★ E v1 확정 scope (Codex 리뷰 2026-06-28 반영 — 전부 수용)
1. **생성 시점 이동 = 타당.** 단 생성 책임을 coordinator 에 직접 넣지 말고 **신규 `registered_pose_guide_service`**
   (pure-ish helper)로 분리: gate / cache path / underlay / gpt-image-2 edit / diagnostic 담당. coordinator 는
   **이 샷에 실제 attach 되는 bg bytes + anchor ctx 만 넘김**(별도 loader 로 location 재추론 금지 → subspace
   mismatch 방지).
2. **ROI crop → v2 로 분리.** v1 = **whole registered master attach** + prompt label 에 "match only the visible
   portion relevant to this shot; do not force full body" 강화. (focus 텍스트로 픽셀 ROI 고르면 또 다른
   LLM/VLM 추정 문제 → 첫 wave 에서 배제. close/insert 반복 손-들림 재발 시 별도 좁은 wave 로 explicit bbox/VLM.)
3. **hash cache (silent reuse 금지).** 파일명 `<gid>_<short_hash>.png` 또는 manifest hash. hash = group_id +
   bg asset id/hash + subject_anchor hash(shared_state_contract+locked_elements+visible_focus) + prompt/model/
   version + underlay variant (+ member set). force regen→overwrite, normal resume→matching hash reuse,
   mismatch→regen or no-guide. **temp→rename atomic write**(concurrent batch 같은 gid 동시생성 대비).
4. **underlay variant = original 기본**(PoC support surface 최강) + "registration underlay only, do not copy
   people/story marks" 유지. 과복사/실사화 시 blur_gray fallback 실험.
5. **no-guide fallback = 정답**(white-bg harm 실측). fallback 상태 prompt_used/diagnostic 기록 + 그 경로
   테스트 잠금.

### ★ E v1 추가 가드 (Codex)
- flag OFF → coordinator path **byte-identical/no-op** 테스트 잠금.
- registered guide ref 는 **required_refs 미충족**(ref_contract 방어 테스트) — character/bg/prop required 는
  기존 refs 가 충족.
- **image call budget/cap** 이 이 helper 호출(gpt-image-2 edit, coordinator worker thread)을 잡는지 확인 —
  budget context/thread propagation.
- **fail → no-white-bg** 를 테스트/라이브 로그로 잠금.

> E v1 = "whole registered master attach + no white fallback + idempotent hash cache + final label humanize".
> ROI crop 은 v2 별도 subfeature.
