
    %j                        d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	  ej                  e      ZdZdZddZ	 d	 	 	 	 	 dd	Z	 d	 	 	 	 	 dd
Zdd	 	 	 ddZy)u:  몸이 곧 신원인 인물 — **한 자리에서** 답한다 (2026-09-18).

로봇·사이보그·기계 몸·외계 생명처럼 **얼굴만 봐서는 같은 인물인지 알 수 없는**
인물이 있다. 이들은 아웃룩(덧입는 옷)이 있어도 기본 참조가 **전신**이어야 하고,
아웃룩 합성본은 그 전신을 **그대로 두고** 파생시켜야 한다.

★왜 helper 로 빼는가 — 배치 생성(reference_pipeline_orchestrator)과 **수동
 재생성**(reference_entity_service)이 **같은 판정**을 읽어야 한다. 한쪽만 알면
 손으로 다시 만든 참조가 흉상으로 돌아간다(Codex 2026-09-18 지적).

판정은 `outlook_phase1` 이 구조화해 답하고(`body_identity_chars`), 여기서는
그 답을 읽기만 한다 — 글자로 뜻을 판단하지 않는다.
    )annotationsN)Path)OptionalSetoutlook_phase1body_identity_charsc                    ddl m} t        |j                        | z  dz  dz  }|r||z  gS |j	                         sg S t        d |j                         D              S )Nr   )settingscheckpointsepisodesc              3  B   K   | ]  }|j                         s|  y wN)is_dir).0ds     L/Users/manta/Documents/Projects/TheRoad-I1/backend/app/core/body_identity.py	<genexpr>z _episode_dirs.<locals>.<genexpr>#   s     :^qxxz!^s   )app.core.configr
   r   projects_direxistssortediterdir)
project_id
episode_idr
   bases       r   _episode_dirsr      sZ    (%%&3mCjPDz!"";;=	:T\\^:::    c                   t               }t        | |      D ]  }|t        z  dz  }|j                         s 	 t	        j
                  |j                  d            j                  d      xs i }|j                  d |j                  t              xs g D                |S # t        $ r!}t        j                  d||       Y d}~d}~ww xY w)u)  이 프로젝트에서 **몸이 곧 신원**으로 판정된 인물의 short_id.

    `episode_id` 를 주면 그 화의 판정만, 안 주면 이 프로젝트의 모든 화를 합친다
    (수동 재생성은 화 맥락이 없다 — 인물의 성질이지 그 화의 성질이 아니다).
    zmanifest.jsonzutf-8)encodingdatau'   body_identity: %s 를 못 읽었다: %sNc              3  8   K   | ]  }|st        |        y wr   )str)r   ss     r   r   z*body_identity_short_ids.<locals>.<genexpr>8   s     ?$8aQ3q6$8s   )setr   _STEPr   jsonloads	read_textget	Exceptionloggerwarningupdate_KEY)r   r   outr   fr    excs          r   body_identity_short_idsr2   &   s     EC:z2I'xxz	JJq{{G{<=AA&IORD 	

?DHHTN$8b$8?? 3 J	  	NNDaM	s   8B##	C,CCc                ,   t        ||      }|s
t               S ddlm} | j	                  |      j                  |j                  |k(  |j                  dk(        j                         }|D ch c]  }|j                  |v s|j                   c}S c c}w )uY   위 판정을 **entity id** 로 옮긴다. 판정이 없으면 빈 집합(종전 동작).r   )EntityCanon	character)r2   r$   app.models.projectr4   queryfilterr   entity_typeallshort_idid)dbr   r   sidsr4   rowses          r   body_identity_entity_idsrA   <   s     #:z:Du. 		&&*4'';6
8		 	 5$Q!**"4ADD$555s   ,B BF)is_null_outlookc                   | dk(  r|s|ry| S )uo  참조 이미지를 만들 때 쓸 타입 — **전신이냐 흉상이냐를 여기서 가른다.**

    ★두 물음이 한 줄에 뭉쳐 있던 것이 이번 결함의 뿌리다:
     ①이 인물에 옷이 있나(`is_null_outlook`) ②몸이 곧 신원인가.
     로봇 주인공은 둘 다 「예」라 옷이 있다는 이유로 흉상 경로로 갔다.
    r5   character_nonhuman )base_entity_typeis_body_identityrB   s      r   reference_entity_typerH   N   s     ;&,<#r   )r   r"   r   Optional[str]returnlistr   )r   r"   r   rI   rJ   zSet[str])rF   r"   rG   boolrB   rL   rJ   r"   )__doc__
__future__r   r&   loggingpathlibr   typingr   r   	getLogger__name__r+   r%   r.   r   r2   rA   rH   rE   r   r   <module>rT      s    #     			8	$; 26!.. 6:66%266& 38
+/
<?
r   