# TheRoad Scene Lab v10 — Pipeline Architecture

> 2026-04-15 보정: v10codex 개발기획서([docs/v10codex/00-development-plan.md](../v10codex/00-development-plan.md))의 보정 사항을 반영했다. 원본 v10 초안의 방향성은 유지하되, 현재 코드 기준 사실과 어긋나는 항목은 수정했다.

## 1. 개요

시나리오(PDF) → 분석 → 이미지 생성 → 웹북/PDF export까지 자동화하는 멀티스테이지 파이프라인.
프로젝트 단위 세계관 + 에피소드 단위 시나리오 구조. shot 단위 이미지 생성과 교차 shot 일관성 유지 제공.

단계 수: manifest에 active/legacy/disabled/on_demand/auxiliary 합쳐 40+ 엔트리가 있다. "핵심 active 경로"는 약 30단계.

## 2. 기술 스택

| 레이어 | 기술 |
|--------|------|
| Backend | FastAPI + SQLAlchemy |
| DB | PostgreSQL |
| Frontend | Vite + React 19 + React Router SPA |
| LLM Routing | LiteLLM Router |
| Text LLM | GPT-5.5 (분석 주력), Gemini 3.1 Pro (감독/beat/shot/consistency) |
| Image LLM | Gemini 3.1 Flash Image Preview |
| Tracking | Opik (LiteLLM callback) |
| Config | pydantic-settings (.env) |
| Job Runtime | Python threading (`job_manager.py`) |
| Export | HTML/PDF export service |

### 2.1 주 실행 경로
- 분석 파이프라인 기준 경로: `StepRunner + /steps API`
- Legacy `AnalysisService` + `/episodes/{id}/analyze`는 호환 레이어 (장기적으로 step graph로 흡수)
- 이미지 생성: step class + `ImageService` 공존
- 신규 기능은 Step API에 먼저 붙인다

## 3. LLM 모델 배정 원칙

| 모델 | 별칭 | 용도 |
|------|------|------|
| `gpt-5.5` | gpt | 텍스트 분석 주력 (요소 추출, 씬 상세, 아웃룩 등) |
| `gpt-5.5-mini` | gpt-mini | 보조 (요약, T2I, 필터링, shot_dependency_t2i) |
| `gemini-3.1-pro-preview` | gemini-pro | scene_director, beat/shot 추출, scene_consistency |
| `gemini-3-flash-preview` | gemini-flash | 씬 세그먼테이션, t2i_review |
| `gemini-3.1-flash-lite-preview` | gemini-lite | text_cleanup |
| `gemini-3.1-flash-image-preview` | gemini-image | 모든 이미지 생성 |

**scene_director는 반드시 Gemini Pro** — GPT-5.5는 비물리적 존재(소울라이드/빙의) 판별 부정확.

## 4. 파이프라인 v4 전체 흐름

```
[텍스트 전처리]
  text_cleanup(1) → scene_segmentation(2) → scene_save(6)
  episode_summary(3) → visual_world_rules(4)

[Beat/Shot 분해]
  entity_character_list(6.5) → beat_extract(7.1) → shot_extract(7.2) → shot_selection(15.5)

[요소 추출 3단계]
  entity_all_character(8) → entity_extract_character(9)
  entity_all_location(10) → entity_extract_location(11)
  entity_all_prop(12) → entity_extract_prop(13)
  → entity_merge(13.5) → entity_relation(13.6) → entity_filter(13.7)
  → entity_detail(14) → entity_t2i(15)

[씬/샷 감독]
  scene_director(16) → shot_director(16.5)
  shot_dependency(18.1)
  outlook_phase1(19) → phase2(19.1) → phase3(19.2)

[촬영 설계]
  shot_staging(19.5) — DP 연출 (카메라/조명/인물배치)
  set_design(19.7) — 배경 참조 이미지 사전 생성
  scene_consistency(19.9) — 교차 샷 시각적 일관성 (NEW)

[상세 분석 + 검수]
  scene_detail(20) — 샷별 T2I 프롬프트 생성
  shot_dependency_t2i(20.5) — T2I 기반 배경 참조 재계산
  t2i_review(20.7) — T2I 프롬프트 검수

[이미지 생성]
  world_guide(22) → ref_image_gen(23) → composite_image_gen(24)
  → character_state_variant(24.5) → scene_image_pipeline(25)
```

## 5. 핵심 데이터 흐름

### 체크포인트 시스템
- 경로: `{projects_dir}/{project_id}/checkpoints/episodes/{episode_id}/{step_id}/manifest.json`
- 원자적 저장: tmp 파일 → os.replace()
- 아카이빙: 이전 버전 `manifest_{timestamp}_{uuid}.json`으로 보관
- force 모드: 하위 의존 step 체크포인트 삭제 + stale 처리

### Short ID 체계
- 인물: `C01`, `C02`, ... (entity_all_character에서 자동 배정)
- 배경: `L01`, `L02`, ...
- 소품: `P01`, `P02`, ...
- 아웃룩: `O01`, `O02`, ... (O00 = Null Outlook, 비인간형)
- T2I에서 복합 ID: `C01O02` (인물+아웃룩) — LLM에게 요구하지 않고 코드에서 조합

### 씬 → Beat → Shot 계층
```
씬 (scene_save)
  └─ Beat (beat_extract) — 상태 변화 단위 (before → after)
       └─ Shot (shot_extract) — 스틸 이미지 단위
            └─ Selected Shot (shot_selection) — 최대 5개 선별
                 └─ T2I Variation (scene_detail) — 카메라 구도별 변형
```

## 6. DB 핵심 테이블

| 테이블 | 범위 | 용도 |
|--------|------|------|
| `episode` | episode | 시나리오 메타 (fulltext, summary) |
| `entity_canon` | **project 전역** | 엔티티 정의 (short_id, entity_type, name, t2i_prompt) |
| `entity_episode_link` | episode | canon ↔ episode 출현 연결 |
| `character_outlook` | **project 전역** | 인물 ↔ 아웃룩 매핑 |
| `scene_still` | episode | 샷별 메타 (scene_index, shot_index, t2i_prompt, visible_entities_json) |
| `image_asset` | project | 생성 이미지 (asset_type: reference/scene, entity_id/still_id 참조) |
| `relation_fact` + `relation_participant` | project | 변형 관계 (원본↔변형) |
| `step_run` | episode | 단계 실행 상태 (status, completed_count, failed_count) |

### 6.1 데이터 소유권 규칙 (중요)
- `EntityCanon`은 프로젝트 전역 canon이다
- `EntityEpisodeLink`는 에피소드별 연결/출현 카운트다
- `CharacterOutlook`은 프로젝트 전역 매핑이다
- `SceneStill`은 에피소드 단위 분석 결과다
- `ImageAsset`은 `entity_id` 또는 `still_id`로 자산을 참조한다

### 6.2 설계 원칙 (절대 규칙)
- **에피소드 재분석은 프로젝트 전역 canon을 삭제해서는 안 된다**
- **still 재분석은 기존 이미지 자산의 FK를 일괄 해제해서는 안 된다**
- checkpoint는 DB의 보조 저장소가 아니라 step 실행의 공식 산출물이다
- DB sync는 항상 **UPSERT + stale marking** 원칙으로 동작한다
- episode-scoped delete는 허용, project-scoped destructive delete는 금지

## 7. 절대 규칙

1. **LLM에 전달하는 데이터를 절대 자르지 마라** ([:400] 등 금지)
2. **프롬프트 파일 덮어쓰기 금지** — 새 버전 디렉토리로 관리
3. **버전 형식**: `2.202603171200` (버전.YYYYMMDDHHmm)
4. **작품 고유명사 코드/프롬프트에 넣지 말 것** — 범용 적용
5. **T2I에서 복합 ID 금지** — LLM은 bare C## 사용, 코드에서 C##O## 조합
6. **scene_still sync는 UPSERT** — DELETE→INSERT 금지, 유휴 still은 soft stale 마킹
7. **DB/프로젝트 파일 삭제 금지** (project-wide destructive delete 특히 금지)
8. **checkpoint는 소유자만 쓴다** — 다른 step의 manifest를 직접 write하지 않는다
9. **checkpoint 저장 실패는 step failure로 승격** — 조용히 무시하지 않는다
10. **단계 정의의 단일 진실 소스는 `step_manifest`** — `llm_client.PIPELINE_STEPS`는 정합성 검증 대상

## 8. SSOT 및 상태 모델 원칙

- 단계 정의 SSOT: `step_manifest.py`
- 모델 alias 해석: `llm_client.PIPELINE_STEPS`(manifest에서 파생 또는 정합성 검증)
- step 상태 semantic (`pending`, `blocked`, `runnable`, `running`, `completed`, `partial`, `failed`, `not_applicable`, `stale`, `cancelled`)은 runner/API/UI에서 동일해야 한다
- `partial` upstream도 downstream 실행 허용 (runner 기준)
