# 시네마틱 재료가 어느 단계 것인가 (감사 1-H 재검토)

2026-08-27 · 과제 #93 · PR A

## 지시

> 기억하고 있지? 카메라 구도와 빛감등 시네마틱하게 만드는 부분은 i2i
> (현재 reve 2.1)로 최종이미지를 변환하는 경우와 하지 않는 경우의
> **삽입지점이 다르다**는 것.
>
> [표] 이거 보면 제대로 구현이 안되었는데? codex 와 의논하고 이 부분도
> 개발 순서 어디에서 하면 좋을지 판단하고 진행해

## 고치기 전 (실측)

프로덕션 `.env` 는 `STILL_CINE_TRANSFORM_ENABLED=true` +
`STILL_CINE_STAGE_DIRECTION_ENABLED=true` — 아래 결함이 **살아 있었다**.

| 재료 | roll (cine ON) | cine | 판정 |
|---|---|---|---|
| `- CAMERA:` 산문 | 빠짐 | 받음 | ✅ |
| `Follow exactly: angle,…` | **남음** | — | ✕ 가리킬 값이 없는 권위 |
| FRAMING SCALE / FRAME LAYOUT / KEY BG | 남음 | — | ✅ 구도는 앞 단계 |
| CINEMATIC FINISH | **남음** | 수행 | ✕ 이중 소유 |
| LIGHTING & MOOD | 남음 | 받음 | △ 값을 못 가름 |

갈래를 만드는 것은 `omit_camera_direction = cine_stage_dir_on` **한 줄뿐**
이었다. Codex 판정: 뿌리는 ㉢(게이트가 한 줄이지 단계 소유권이 아니다).

## 이 판이 고치는 둘

### ① 각도 권위가 값과 함께 빠진다

`omit_camera_direction` 이면 `- CAMERA:` 값이 빠지는데, 꼬리의
「angle 을 그대로 따르라」가 남았다.

수리 = 각도를 걷은 **별도 스템**(팩 v33). 원본 스템을 고치면 플래그와
무관하게 전 롤의 지문이 흔들려 완주한 샷이 통째로 다시 산다.

★**두 판을 각자 원본에서 만들었다.** base(v6)와 컴팩트(v22)는 본문이
다르다 — 컴팩트는 grok 8,000B 상한에 맞춰 짧다. 한 판으로 합치면 한쪽
갈래의 문안이 늘거나 줄어 그 갈래의 그림이 바뀐다.

★**금지만 남기면 그릴 재료가 없다.** 「각도를 따르라」를 그냥 지우면 그
자리가 침묵이 된다 — 「각도는 열어 뒀으니 네가 고르라」고 말해 준다.

★**실제로 뺀 값이 있을 때만** 스템을 바꾼다. 저작이 애초에
`camera_direction` 을 안 줬으면 뺀 것이 없고, 그 경우의 매달린 권위는
cine OFF 에도 똑같이 있는 별개 문제다. 여기서 같이 고치면 cine 켠 샷만
다르게 말하는 비대칭이 생긴다.

★**모르는 selector 는 KeyError 로 죽인다.** 새 camera_frame 팩을 올리고
짝을 안 만들면 조용히 옛 스템으로 돌아가 **각도 권위가 되살아난다** —
그 되살아남은 그림에서만 보이고 시험은 초록이다.

### ② 마감이 끝 단계 한 곳만 갖는다

`should_attach_cinematic_finish` 가 `True` 고정이었다 → `not cine_on`.

두 실패를 나란히 재고 갔다 — 한쪽만 보고 고치면 반대편이 되살아난다.

| | 막는 것 | 빈도(records 실측) |
|---|---|---|
| 새 지적 | cine ON 샷이 마감을 **두 번** 받는다 | 성공 샷 **100%** |
| 옛 코드 | 포기·기각이면 마감이 **어디에도 없다** | 611 중 **2** (0.3%) |

앞의 것이 표적이다. 뒤의 것은 **열어 둔 채 기록으로 드러낸다** — 사용자가
재생성을 물리셨다("어차피 후보들 중에서 판단할거아냐"). 자산 record 의
`cine_transform.finish_owner` 가 `"cine"` / `"none"` 으로 그 자리를 말한다.
안 적으면 `applied=False` 만 남아 「마감이 없다」와 「변환이 실패했다」가
안 갈린다.

★**앞 판단을 뒤집는 근거.** 앞에서는 「마감 절이 CAMERA·layout 권위를 안
건드리니 두 번 가도 무해하다」고 봤다. 그런데 **이 절이 다루는 것이 바로
미지정 선택지**고, 최종 i2i 가 하는 일도 그것이다. 같은 선택을 두 단계가
각자 하면 「끝 단계가 정한다」는 계약이 서지 않는다.

## 지문 — 여기서 두 번 틀렸다

**실제로 나가는 스템 하나만** 접는다. 그 하나를 고르는 것은
`camera_frame_stem()` 이고, **조립과 지문이 그 함수를 같이 부른다.**
백엔드 갈림도 `still_guidance_selector()` 하나로 만든다.

내가 밟은 두 함정을 적어 둔다:

| | 한 일 | 열린 것 |
|---|---|---|
| ① | base 스템만 접었다 | grok 의 **컴팩트 문안 수정이 누락** — 나가는 글은 바뀌는데 옛 그림이 남는다 |
| ② | 그래서 **둘 다** 접었다 | 반대편 — nb2 설정 그대로 컴팩트 바이트만 고쳐도 **nb2 완주 샷이 헛되이 다시 산다** |

★②의 내 근거가 틀렸다: 「`still_image_backend` 가 이미 지문에 있으니
지출이 안 는다」. 그건 **두 백엔드의 지문이 서로 다르다**는 뜻일 뿐,
안 쓰는 스템이 기여하지 않는다는 뜻이 아니다.

★팩 버전만 접으면 **같은 팩 안에서 문안을 고칠 때** 안 움직인다 — 스템
바이트를 직접 접는다.
- **마감**: 지문이 이미 `should_attach_cinematic_finish` 를 부르므로
  자동으로 갈린다. `nb2` 쪽은 「접는 조건 = 붙는 조건」으로 맞췄다 —
  안 나가는 문안을 접고 있으면 팩을 올릴 때 헛되이 전량 재실행된다.

## 지출

cine ON 으로 완주한 샷은 롤부터 다시 산다
(`compute_input_fingerprint` 가 프롬프트를 직접 접는다). 두 수정을
**같은 판에** 넣어 한 번만 치게 했다.

## 이 판이 **안** 고치는 것 — PR B

`lighting_mood` 한 칸에 장면 사실(광원이 **있다**·켜져 있다)과 연출
(대비·색조·공기)이 섞여 있다. 체크포인트 6,095 칸 실측:

| | 비율 |
|---|---|
| 사실+연출이 한 문장 | **32% 이상** |
| 평균 132자 · 최장 214자 | 6,095 칸 |

★「32%」는 **바닥값**이다. 「둘 다 안 잡힘」으로 분류된 표본이 전부 실은
둘 다 담고 있었다(`practical`·`siren`·`spill` 이 낱말표에 없었다).
정확한 비율은 글자로 못 센다 — 의미 판단은 LLM 몫이다. **결론은 비율과
무관하게 같다: 통째로 옮기면 광원 사실을 잃는다.**

풀려면 저작이 값을 둘로 나눠 줘야 한다(`lighting_facts_en` /
`lighting_treatment_en`). ★**코드가 의미로 쪼개지 않는다.**

Codex 판정(2026-08-27): `ShotStagingStep._config_hash` 가 `system.md` 와
`schema.json` 바이트를 직접 접으므로 스키마를 바꾸면 옛 CP 는 mismatch 이고
StepRunner 가 BLOCK 한다. shot_staging 은 소비자가 많아 force 는 넓은
하류 무효화를 부른다. **옛 CP 를 보존하면서 의미 분리도 얻는 무료 방법은
없다** — 옛 한 문장이 이미 섞여 있어 코드로 가르는 것이 불가능하다.
권고 기본안은 영구 호환층 없이 **clean cutover** + 작은 canary 에서 비용
확인. 별도 판에서 정한다.

## 도구

`backend/tools/prompt_measure/audit_lighting_mood_content.py` — 체크포인트
전수에서 `lighting_mood` 를 읽어 섞임 정도를 센다(무료).
