v2 - decisions locked (Claude+Codex reviewed) - 2026-05-23

Reference Necessity Design

이 문서는 엔티티를 많이 추출하는 문제와 참조 이미지가 과생성되는 문제를 분리한다. 목표는 프로젝트 장기 catalog는 넓게 보존하면서, 이번 에피소드에서 실제로 필요한 참조 이미지만 지연 생성하는 구조로 바꾸는 것이다.

1. 결론

지금 문제는 "엔티티를 많이 뽑는다" 자체가 아니다. 연속 에피소드에서는 다음 회차에 중요해질 수 있으므로, 엔티티 catalog는 넓게 보존해야 한다. 실제 결함은 catalog 보존, episode별 사용량 판단, 참조 이미지 생성, scene T2I attach가 한 흐름 안에서 섞여 있다는 점이다.

핵심 설계: recurring 후보 엔티티는 지우지 않는다. 다만 그림자, 실루엣, 왜곡상처럼 명백한 transient noise는 entity_filter가 정리한다. 남은 catalog 엔티티는 각 에피소드의 selected_shot_count, visible_shot_count, required_ref_counttext_only, reference_required, reference_generated를 계산한다. 미래 중요도 추정은 deterministic state가 아니라 human/LLM 보조 메모로만 둔다.
질문 현재 답 목표 답
이 요소를 catalog에 남길까? 초기 LLM count와 필터가 결정한다. recurring 후보는 남긴다. transient noise는 정리한다.
이번 에피소드에서 이미지 참조가 필요할까? 명확한 단일 결정 지점이 없다. selected_shot_count, visible_shot_count, required_ref_count로 결정한다.
scene T2I에는 ID를 넣을까, 자연어만 넣을까? subject_reference_policy와 기본값이 주도한다. episode reference policy가 id_required 또는 text_only를 명시한다.
실제 참조 이미지는 언제 만들까? ref 단계에서 넓은 보호 union 때문에 거의 다 만든다. policy가 ID/ref 사용을 허용하고, scene_detail.required_refs 또는 selected-shot 반복성이 확인된 경우에만 만든다.

2. 현재 구조

2.1 순서 문제

현재 entity_all_character, entity_all_prop, entity_filter, entity_detail, entity_t2ishot_selection보다 앞에 있다. 따라서 최종 이미지화할 shot을 모르는 상태에서 엔티티 count와 필터가 결정된다.

entity_all_*        order 8-13
entity_merge        order 13.5
entity_relation     order 13.6
entity_filter       order 13.7
entity_detail       order 14
entity_t2i          order 15
shot_selection      order 15.5
scene_detail        order 21.70
shot_dependency_t2i order 21.71
결정: shot_selection은 재배치하지 않는다. 정밀 usage 신호 (scene_director.visible_entity_ids, shot_director.visible_entity_ids, scene_detail.required_refs)는 order 16 이후에야 생기고, reference 생성은 image 단계에서 더 뒤에 실행된다. 따라서 기존 early entity_filter는 transient noise cleanup으로 격하하고, 실제 reference/text-only 결정은 scene_detail 직전의 신규 downstream policy step이 담당한다.

2.2 참조 이미지 결정이 섞인 위치

위치 현재 역할 문제
entity_filter 초기 shot_count가 낮은 요소 제거 최종 선택 shot 기준이 아니다. 단, 역할은 recurring 후보 삭제가 아니라 transient noise 정리로 한정해야 한다.
render_prompt_card.build_asset_requirements shot별 required_refs 생성 실제 attach 계약에 가장 가깝지만 episode-wide low-use 정책을 알지 못한다.
reference_pipeline_orchestrator 참조 이미지 생성 전 low-frequency skip 계산 required_union이 너무 넓어 저빈도 skip이 무력화된다.
scene_reference_service.resolve_refs_for_prompt T2I prompt와 required_refs에 맞춰 실제 이미지 attach 이 단계는 이미 late consumer다. 여기서 텍스트 전용으로 바꾸면 늦다.

2.3 현재 attach 규칙

3. 최신 E2E 데이터에서 확인된 증거

대상 프로젝트 76212b49-bf96-45fb-8c56-cd8d8ae02dda, 에피소드 f44339e6-1bd1-4d10-8a8f-2e30e5a1d36d의 checkpoint/DB를 읽어 확인한 결과다.

요소 초기 entity_all 추정 최종 selected-shot T2I 사용량 생성된 reference 해석
C04 김형사 shot_count=11 0 2 최종 selected shot에는 안 쓰였지만 scene_director present union으로 보호됨.
C08 한국인 여성 shot_count=6 1 3 한 컷 주변 인물인데 full reference/composite 계열로 승격됨.
C09 검은 맹견 shot_count=4 2 1 실제 사용은 있으나, 보통 묘사로 충분한지 reference가 필요한지 별도 판단이 없다.
P03/P04/P08/P15/P16 2-3회 또는 그 이상으로 추정 0 1 최종 selected-shot 프롬프트에는 안 쓰였지만 scene_director present union으로 생성됨.
ref_low_freq_skip.json은 빈 배열이었다. 즉 이번 런에서는 저빈도 캐릭터/소품이 하나도 reference generation에서 skip되지 않았다.

4. 목표 구조

4.1 세 개의 개념을 분리

개념 저장/계산 단위 예시 삭제 여부
Project catalog EntityCanon 김형사, 한국인 여성, 검은 맹견, 낡은 사진 저빈도라는 이유로 삭제하지 않는다.
Episode usage selected_shot_count, visible_shot_count, required_ref_count 이번 에피소드에서 C08은 selected/visible 1컷, C04는 0컷 매 에피소드마다 재계산한다.
Reference necessity 에피소드별 asset 정책 C08=text_only, P10=reference_required 참조 생성 여부만 결정한다.

4.2 상태 모델

catalog_only
  프로젝트 사전에만 존재. 이번 에피소드 이미지 참조 없음.

text_only
  이번 에피소드 selected shot에 등장하지만 자연어 묘사로 충분.

reference_required
  selected-shot policy와 scene_detail/card가 ID/ref 사용을 요구.
  characters/nonhuman subjects: visible_shot_count >= 2 또는 required_ref_count >= 1.
  props: final gate는 required_ref_count >= 1.

reference_generated
  실제 ImageAsset reference가 생성되어 scene image stage에서 attach 가능.

human_deferred_note (optional)
  다음 에피소드 중요도 가능성 같은 미래 판단. deterministic 계산 결과가 아니라
  운영자/LLM 보조 메모이며 reference 생성 게이트로 직접 쓰지 않는다.
reference_deferred를 deterministic 초기 상태로 두지 않는다. "다음 에피소드에 중요해질 수 있음"은 미래 정보라 계산할 수 없다. 시스템이 계산하는 것은 이번 에피소드의 selected-shot usage와 required-ref 필요성이다.

4.2.1 Catalog noise와 recurring 후보 구분

분류 예시 처리
Recurring 후보 김형사, 검은 맹견, 반복 등장 가능 인물/동물 catalog 유지. 이번 에피소드에서는 selected-shot usage에 따라 text-only 또는 reference_required.
Transient noise 검은 실루엣, 그림자, 사진 속 왜곡상, 한 컷 배경 실루엣 entity_filter가 정리할 수 있다. 다음 에피소드 대비 catalog 보존 대상이 아니다.

4.3 다음 에피소드 대비

다음 에피소드에서 어떤 인물의 출현수가 늘어나면 catalog에 이미 존재하므로 새로 발견할 필요가 없다. 단지 그 에피소드의 usage 집계가 올라가고, policy가 text_only에서 reference_required로 승격된다. 이때 처음으로 참조 이미지를 생성한다.

5. 이미지 참조 vs 텍스트 설명 결정 시점

한 번에 결정하면 안 된다. 두 단계가 필요하다.

단계 시점 결정 왜 여기인가
Policy decision shot_selection, shot_director, shot_staging 이후, scene_detail 이전 이 요소를 ID/ref 기반으로 쓸지, text-only로 쓸지 scene_detail LLM이 T2I prompt를 쓰기 전에 알아야 한다. 기준 모집단은 scene이 아니라 selected shot이다.
Asset materialization scene_detail/t2i_review 이후, ref_image_gen 직전 실제로 reference image를 생성할지 최종 render_prompt_card.required_refs, selected-shot T2I prompt, prompt ID count를 볼 수 있다.
중요한 제약: scene_detail이 이미 required_refs를 만든 뒤에 reference image만 스킵하면 image stage의 validate_attached_refs가 실패한다. 따라서 text-only 결정은 scene_detail 이전 또는 render_prompt_card 내부에서 반영되어야 한다.

5.1 결정 규칙 초안

대상 reference_required text_only / catalog_only
주요 캐릭터 visible_shot_count >= 2 또는 required_ref_count >= 1. 별도 주연 하드코딩 보호는 두지 않는다. visible_shot_count=1이고 required ref가 없는 주변 인물, 이름 없는 행인, 일반 직원, generic crowd
변형 캐릭터 identity/transformation relation이 있고 그 변형이 실제 selected shot에서 쓰이는 경우. 기존 variant 보호 유지. 이번 에피소드에 쓰이지 않는 변형 후보
동물/비인간 캐릭터 캐릭터와 같은 규칙. visible_shot_count >= 2 또는 required_ref_count >= 1. 예: 검은 맹견 2샷이면 reference_required. 한 장면의 일반 동물/위협 요소. 예: 검은 고양이 1샷이면 text_only.
소품 최종 게이트는 required_ref_count >= 1. scene_detail 전 policy 단계에서는 사진/지도/표식류 + staging 2회 이상 같은 continuity-critical 휴리스틱으로 provisional 판정. required_ref_count=0인 주사기, 가위, 휴대전화 등 일반 묘사로 충분한 소품

6. 건드려야 할 코드와 프롬프트

6.1 코드

파일 현재 역할 변경 방향
backend/app/core/step_manifest.py pipeline order 정의 episode_reference_policy step을 scene_detail 전에 추가. shot_selection 자체는 재배치하지 않는다.
backend/app/core/steps/episode_reference_policy_step.py + policy service 신규 step 구현 파일 selected-shot usage, visible-shot usage, required_ref_count, relation/variant 보호를 모아 immutable episode_reference_policy checkpoint manifest를 1회 계산한다. 이 manifest가 scene_detail producer와 verify recompute의 단일 SOT가 된다.
backend/app/core/entity_protection.py 저빈도 reference skip 보호 cascade _collect_required_entity_ids의 4-source union을 catalog/audit 용도로만 두고, reference generation 보호는 scene_detail.render_prompt_card.asset_requirements.required_refs만 남긴다. scene_detail.visible_entities도 reference 보호에서는 제외한다.
backend/app/services/reference_pipeline_orchestrator.py low_freq skip 및 reference generation orchestration episode reference policy와 required-ref-only 보호 집합을 소비해 ref_low_freq_skip.json을 reason 포함 구조로 저장.
backend/app/core/steps/render_prompt_card.py shot별 asset_requirements.required_refs 생성 precomputed policy overlay를 받아 low-use text-only 대상은 required_ref를 만들지 않도록 조정.
backend/app/core/steps/detail_steps.py scene_detail 실행, card build, validator 호출 reference policy overlay를 scene_detail context/card input으로 전달. card hash 재계산 경로와 동일하게 threading.
backend/app/services/checkpoint_sync/episode_projection_service.py t2i_appearance_count 계산 count source를 selected still/selected shot 기준으로 명시하고, count가 reference necessity와 어떻게 다르는지 분리.
backend/app/services/scene_reference_service.py 실제 reference attach 가능하면 변경 최소. 이미 required_refs SOT를 소비하므로 새 정책은 upstream에서 정합시킨다.

6.2 프롬프트

프롬프트 변경 필요성 방향
prompts/_base/entity_all/* 낮음 shot_count는 최종 usage가 아니라 catalog hint임을 명확히 할 수 있다. 1차 fix는 코드 쪽이 우선.
prompts/_base/entity_filter/* 중간 recurring 후보 삭제가 아니라 transient noise cleanup임을 명시. "참조 이미지 필요성" 판단을 맡기지 않는다.
prompts/_base/scene_detail/* 낮음-중간 policy overlay가 text-only로 지정한 요소는 ID/고유명 대신 보통명사 설명을 쓰도록 보강 가능. 단 deterministic card 우선.
새 LLM prompt 초기에는 불필요 reference necessity는 먼저 결정론적 계산으로 둔다. LLM 판정은 나중에 UI/editorial 보조로만 검토.

7. 단계별 구현 계획

사용자 결정: Phase 0, Phase 1, Phase 2는 한 plan/branch로 묶는다. reference policy 하나가 required_refs 생성과 reference generation 보호를 동시에 구동해야 한다. Phase 1만 단독으로 실행하면 기존 broad union 안전망을 걷어내면서 scene_detail/card 정책은 그대로 남아 missing required ref 위험이 생긴다.

Phase 0 - 관찰 및 안전망 차집합 감사

동작 변경 없이 현재 프로젝트/에피소드에 대해 usage matrix를 산출한다. 목적은 threshold와 예외를 실제 데이터로 정하고, broad union 안전망을 걷어도 되는지 검증하는 것이다.

입력:
- entity_all shot_count
- entity_filter kept/removed
- scene_detail.visible_entities
- render_prompt_card.required_refs
- t2i_prompt ID occurrence
- ImageAsset reference rows
- EntityEpisodeLink.t2i_appearance_count

출력:
- entity_reference_usage_report.json
- table: catalog_hint_count vs selected_shot_count vs visible_shot_count
         vs prompt_id_count vs required_ref_count vs generated_refs
- safety_diff:
    broad_required_union =
      scene_director.present
      ∪ shot_validator.character_ids
      ∪ shot_director.visible_entity_ids
      ∪ scene_detail.visible_entities
      ∪ scene_detail.required_refs
    required_refs_only = scene_detail.required_refs
    audit_set = broad_required_union - required_refs_only

안전 게이트:
- audit_set의 각 character/prop이 실제 selected-shot T2I 미사용인지 확인한다.
- audit_set 안에 실제 prompt ID 사용 또는 attached ref 필요성이 있으면 Phase 1/2 진입 금지.
- audit_set에서 실제 T2I 사용 엔티티가 발견되면 required_refs SOT gap 이다.
  fallback은 broad union 유지가 아니라 required_refs 보강이다.
- gap 집합이 크거나 root가 깊으면 bundle 진입을 중단하고 required_refs 정확성을 먼저 재점검한다.
- 이 게이트 통과 후에만 broad union 안전망을 reference generation에서 제거한다.

Phase 1 - ref_image_gen 과생성 차단

catalog는 그대로 두고, 참조 이미지 생성 보호 집합을 좁힌다. 단, 이 Phase는 Phase 2와 같은 branch에서 함께 검증한다.

Phase 1 단독 실행 금지. required_refs 계약은 최근 여러 차례 버그 수정된 민감한 경로다. Phase 0의 차집합 감사와 Phase 2의 policy overlay가 함께 있어야 안전하다.

Phase 2 - scene_detail 전 policy overlay

"이미지를 넣을 것인지, 텍스트 설명만 넣을 것인지"를 scene_detail이 T2I prompt를 만들기 전에 결정한다.

Drift 방지 메커니즘: episode_reference_policyscene_detail 직전 단일 checkpoint manifest로 1회 고정 저장한다. detail_steps._analyze_one의 producer 경로와 verify_completion/render_prompt_card_hash recompute 경로는 모두 같은 manifest를 읽는다. 호출 시점마다 policy를 재계산하지 않는다. 이 immutable checkpoint가 card hash drift를 막는 실제 SOT다.
episode_reference_policy:
  C08:
    mode: text_only
    reason: selected_shot_count=1, visible_shot_count=1, required_ref_count=0, no identity continuity dependency
  C01:
    mode: reference_required
    reason: protagonist, visible_shot_count high
  P10:
    mode: reference_required
    reason: prop required_refs count high, continuity-critical photo
  P11:
    mode: text_only
    reason: selected_shot_count=1, visible_shot_count=1, required_ref_count=0

Phase 3 - DB/read model 및 UI 분리 (별도 branch)

Phase 0+1+2가 E2E에서 안정되면 UI와 DB projection에 명시적으로 노출한다. 이 단계는 read model/운영 표시 작업이므로 별도 branch로 분리한다.

8. 검증 계획

8.1 Unit / integration tests

테스트 검증 내용
policy split scene_detail.required_refs 밖의 4-source union 항목은 audit_set으로 먼저 분류되고, 통과 후 reference generation required가 아니다.
safety diff audit broad_required_union - scene_detail.required_refs 차집합의 각 엔티티가 실제 selected-shot T2I/attach 필요성이 없는지 전수 검증한다.
required_refs protection required_refs(kind="prop")가 있는 P10/P18은 count가 낮아도 스킵하지 않는다.
low-use text-only C08 같은 one-shot generic character는 catalog 유지, selected-shot policy는 text-only, reference skip.
variant protection identity/transformation relation이 있고 실제 selected shot에서 쓰이는 변형은 보호한다.
card hash stability policy overlay가 producer와 verify recompute 경로에서 동일하게 적용된다.
image-stage fail-fast required_refs를 요구하는데 ref asset이 없는 경우 기존 validator가 계속 fail-fast한다.

8.2 E2E acceptance

9. UI/운영 표시

사용자는 "요소가 존재한다"와 "참조 이미지가 쓰인다"를 구분해서 봐야 한다. 현재 UI가 대표 이미지 중심이면 저빈도 요소도 중요한 요소처럼 보이기 쉽다.

UI 필드 의미
Catalog status active / dormant / merged / removed. 프로젝트 장기 사전 상태.
Episode usage selected_shot_count, visible_shot_count, prompt ID count, required_ref_count.
Reference policy text_only / reference_required / reference_generated. Future importance는 optional human/LLM note로 별도 표시.
Actual attached refs scene image 생성 시 실제 LLM 호출에 들어간 reference image 목록.
Lineage refs visible_entities 기반 계보/후보 목록. actual attached refs와 분리해서 표시.

10. 확정된 결정

  1. 캐릭터 recurring threshold: visible_shot_count >= 2 또는 required_ref_count >= 1이면 reference_required. 별도 주요 인물 하드코딩 보호는 두지 않는다. 주연은 count가 자연히 높아 threshold로 커버된다. 단 identity/transformation relation이 있고 그 변형이 selected shot에서 실제 쓰이면 기존 variant 보호를 유지한다.
  2. 동물/비인간 subject: 캐릭터와 같은 규칙을 쓴다. entity_type만으로 prop처럼 취급하지 않는다. 동물은 정체성을 가진 depicted subject다. 예: 검은 맹견 2샷은 reference_required, 검은 고양이 1샷은 text_only.
  3. prop: 최종 게이트는 required_ref_count >= 1이다. prop attach는 required_refs 단일 SOT이므로 visible이어도 required_ref가 없으면 reference 생성은 낭비다. 단 policy 결정은 scene_detail 이전이므로, prop은 사진/지도/표식류 + staging 2회 이상 같은 continuity-critical 휴리스틱으로 provisional 판정하고, materialization 단계에서 required_ref_count로 최종 확정한다.
  4. Phase 0 audit 실패 fallback: broad_required_union - scene_detail.required_refs 차집합에서 실제 T2I 사용 엔티티가 발견되면 이는 required_refs SOT gap 이다. fallback은 required_refs 보강이며, broad union을 영구 crutch로 남기지 않는다. gap 집합이 크거나 root가 깊으면 bundle 진입을 중단하고 required_refs 정확성을 먼저 재점검한다.

11. Non-goals