
    jajU5                    $   d Z ddlmZ ddlZddlmZ ddlmZmZm	Z	m
Z
mZmZmZ dZdZddZ	 	 	 	 	 	 dd	Z	 	 	 	 	 	 	 	 dd
Z	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZddZddZ	 	 	 	 	 	 ddZy)uc  표적 씬 실행 scope — 씬 이미지 슬라이스 실행 결정론 계약 (2026-07-23).

사용자 지시(슬라이스 E)의 범용화: 에피소드 전체가 아니라 표적 씬
부분집합만 씬 이미지(스틸)를 생성한다. Codex 설계 합의 조건:

- BLOCKING-1: 전체 stills/stills_orm 은 컨텍스트 SOT 로 끝까지 유지
  (월드 가이드·프롬프트 population·groupbg 컨텍스트/group_sig·canonical
  origin 전부 전체 목록 전제) — **생성 실행 루프만** effective allowlist
  로 제한한다(recipe ordered loop / legacy scene_batch).
- BLOCKING-2: 의존 클로저=소비 경로별 **최종 그래프의 재귀 고정점**.
  legacy=base+zoom+composition+immobilized edge 합산 그래프,
  recipe=shot_ref_classify+background_share_plan 적용 후 effective
  prev 체인. cycle/결손=fail-closed.
- HIGH-3: requested→dependency→effective 를 이 모듈의 순수 함수가
  단일 산출하고 audit(requested_scenes/requested_ids/dependency_added/
  effective_ids)을 영속 — 서비스 실행·스텝 카운트·verify 가 동일 audit
  을 소비(독자 필터 드리프트 금지). 표적 씬이 selected still 0개면
  fail-fast(오타/재세그먼트 mismatch).
- 빈 설정("")=전체 생성 — 모든 소비처 byte-identical.

시나리오 의존 없음 — 씬 index 는 범용 정수 목록이다.
    )annotationsN)Path)AnyDictListMappingSequenceSetTuplezscene_target_scope.json   c                   t        | xs d      j                         }|syt               }|j                  d      D ]r  }|j                         }|s|j	                  d      j                         st        d|d      t        |      }|dk  rt        d|       |j                  |       t |st        d	|       t        t        |            S )
u  설정 문자열 → 정규화 씬 튜플 (정렬·중복 제거).

    ""/None = () (표적 미설정 — 전체 생성). 정수 아닌 토큰/음수 =
    ValueError fail-closed (조용한 무시 금지 — 오타가 전체 생성으로
    조용히 확장되는 경로 차단).
      ,-u)   scene_image_target_scenes 파싱 실패: u    (정수 목록 필요)r   u,   scene_image_target_scenes 음수 씬 index: uC   scene_image_target_scenes 비어 있지 않은데 유효 씬 0개: )strstripsetsplitlstripisdigit
ValueErrorintaddtuplesorted)rawtextouttokvals        \/Users/manta/Documents/Projects/TheRoad-I1/backend/app/modules/pipeline/scene_image_scope.pyparse_target_scenesr#   !   s     syb>!DECzz#iikzz#&&(;C7BYZ\ \#h7>seDF F  QRUQXY[ 	[    c                   t        |      }|D ci c]  }|g  }}| D ][  }|j                  d      }t        |t              s%||v s*|j                  d      s<||   j	                  t        |d                ] t        d |j                         D              }|rt        d|       g }t        |      D ]  }|j                  ||           |S c c}w )u   표적 씬의 생성 대상 still id 목록 (stills=selected·non-stale 우주).

    표적 씬 중 still 0개인 씬 존재 = ValueError fail-fast (Codex HIGH-3:
    completed=0 위장 금지 — 오타/재세그먼트 mismatch 신호).
    scene_indexidc              3  ,   K   | ]  \  }}|r	|  y wNr   ).0tidss      r"   	<genexpr>z&requested_still_ids.<locals>.<genexpr>M   s     ?#3C31#3s   
u}   표적 씬에 생성 대상 still 이 없음 — 씬 번호 오타 또는 재세그먼테이션 mismatch (fail-fast): scenes=)
r   get
isinstancer   appendr   r   itemsr   extend)	stillstarget_scenestargetsr+   by_scenessiemptyr   s	            r"   requested_still_idsr:   >   s     - G5<%=WaeWH%=UU=!b#2=QUU4[RLAdG-  ?8>>#3??EBBGJK 	K CH

8A; J &>s   
Cc           
        t        |       D ci c]$  \  }}|t        |j                  d      xs d      & c}}j                         D ci c]  \  }}|s	|| }}}|D cg c]	  }||vs| }	}|	rt	        d|	dd        t               }
|D cg c]  }||   	 }}|rv|j                         }||
v r|
j                  |       |j                  |d      D ]8  }||
vsj                  |      st	        d| d      |j                  |       : |rvt        |      t        fd	|
D              }t        fd
|D              }||fS c c}}w c c}}w c c}w c c}w )uC  (legacy 경로) 최종 합산 dep 그래프의 재귀 클로저.

    deps=stills 인덱스 기반 target→source 그래프 (base+zoom+composition+
    immobilized edge 가 전부 합쳐진 뒤 호출 — Codex BLOCKING-2).
    반환=(effective_ids, dependency_added_ids). 미해석 인덱스=결손
    fail-closed.
    r'   r   u;   requested still 이 stills 우주에 없음 (fail-closed): N   r   zdep source still[u   ] id 결손 (fail-closed)c              3  (   K   | ]	  }|     y wr)   r   )r*   i	id_by_idxs     r"   r-   z+closure_over_index_graph.<locals>.<genexpr>y   s     2Ty|Ts   c              3  ,   K   | ]  }|vs|  y wr)   r   )r*   x	requesteds     r"   r-   z+closure_over_index_graph.<locals>.<genexpr>z        >i1I+=1i   	)
	enumerater   r.   r1   r   r   popr   r0   r   )r3   requested_idsdepsr>   r7   kv	idx_by_idridmissingseenstacksrc	effectiveaddedr?   rB   s                  @@r"   closure_over_index_graphrS   X   s    8A7HI7Htq!Cd)r**7HII"+//"39"3$!QqA"3I9+Dmss)/CsmGDIr{m 	 UD'45}Ys^}E5
IIK988Ar?C$ }}S)$+C50IJL LS! #  M"I2T22I>i>>Ee/ J9D 6s#   )E
EE(	E"2E"E'c                    ddl m} i }| D ]S  }|j                  |      xs i j                  d      }|j                  |      }|r	 |||      }|sFt        |      ||<   U |S )u  (recipe 경로) tag→effective prev tag — 실행 루프와 동일 해석.

    shot_ref_classify 의 prev 에 background_share_plan 의
    apply_share_plan_prev 를 적용한 값 (Codex BLOCKING-2: 두 CP 적용
    후의 effective prev 를 클로저 입력으로). 보수적 상한 — 실행 루프의
    bg_only 등 조건 분기로 prev 를 안 쓸 수 있으나, 클로저는 초과
    포함이 안전하고 미포함이 결손이다.
    r   )apply_share_plan_prevprev)!app.modules.pipeline.still_reciperU   r.   r   )tagsclassify_shotsshare_plansrU   r   tagrV   plans           r"   build_effective_prev_mapr]   ~   sk     HC""3'-2226:s#(t4D4yCH  Jr$   c                j   t               }| D ]x  }t               }|}|s||v rt        d| d| d      |j                  |       ||vrt        d| d| d      ||v rT|j                  |       |j                  |      }|rgz t        |       t	        fd|D              }t	        |      |fS )u   (recipe 경로) effective prev 체인 재귀 클로저.

    반환=(effective_tags 정렬, dependency_added_tags). prev 가 known
    (스틸 우주) 밖=결손 fail-closed, cycle=fail-closed.
    u(   prev 체인 cycle 감지 (fail-closed): u	    (시작 )u:   prev 체인이 스틸 우주 밖을 참조 (fail-closed): c              3  ,   K   | ]  }|vs|  y wr)   r   )r*   r+   rB   s     r"   r-   z*closure_over_prev_chain.<locals>.<genexpr>   rC   rD   )r   r   r   r.   r   )	requested_tagsprev_of
known_tagsrQ   startpathcurrR   rB   s	           @r"   closure_over_prev_chainrg      s     %Id{ >se9UGSTUW WHHSM*$ Pe9UG1./ / iMM#++c"C     N#I>i>>E)e##r$   c           
         t        h ||      }t        |t        t        d | D                    t        t        d |D                    t        t        d |D                    |dS )uN   audit 레코드 — 서비스 실행·스텝 카운트·verify 의 단일 SOT.c              3  2   K   | ]  }t        |        y wr)   r   r*   rA   s     r"   r-   z$build_scope_audit.<locals>.<genexpr>   s     &E}!s1v}   c              3  2   K   | ]  }t        |        y wr)   r   rk   s     r"   r-   z$build_scope_audit.<locals>.<genexpr>   s     #BMqCFMrl   c              3  2   K   | ]  }t        |        y wr)   rn   rk   s     r"   r-   z$build_scope_audit.<locals>.<genexpr>   s     &L7K!s1v7Krl   )contract_version	path_kindrequested_scenesrG   dependency_addedeffective_ids)r   SCOPE_CONTRACT_VERSIONr   )r4   rG   dependency_added_idsrq   rQ   s        r"   build_scope_auditrw      sg     >>)=>?I2"3&E}&E#EF#BM#B BC"3&L7K&L#LM" r$   c                   | j                  d      xs g D ch c]  }t        |       c}t        fd|j                         D              }t        | j                  d      xs g       |k7  r.t	        dt        | j                  d      xs g       d|d      t        | j                  d      xs g       t        |      z
  }|rt	        dt        |      d	d
       y	c c}w )u  소비 직전 — audit 를 **현재 selected-still 우주**와 결합 검증.

    Codex 재재리뷰 HIGH-1: expected_scenes 대조만으로는 같은 씬 번호의
    stale audit(스틸 세대 교체 후 old id)가 로더를 통과하고, 소비측
    교집합이 0 이 되어 false CLEAN 이 가능했다. 잠금 2건:
    - 현재 우주에서 재구성한 표적 씬 selected id 집합 == audit.
      requested_ids (동등성 — 표적 씬 선택 샷 일부 누락도 검출)
    - audit.effective_ids ⊆ 현재 우주 (unknown dependency id 조용한
      드롭 차단)
    위반=ValueError fail-closed (표적 씬 이미지 재실행 필요 신호).
    universe_scene_by_id = 현재 selected·non-stale still id→scene_index.
    rr   c              3  P   K   | ]  \  }}t        |t              r|v r|  y wr)   )r/   r   )r*   sidr8   r5   s      r"   r-   z'check_scope_universe.<locals>.<genexpr>   s-       27Rb#2= 	7s   #&rG   u   표적 scope audit 이 현재 selected-still 우주와 불일치 — 스틸 세대 교체/선택 변경 후 stale audit (fail-closed): audit.requested=u    vs 현재 표적 씬 selected=u#    — 씬 이미지 재실행 필요rt   ub   표적 scope audit effective 에 현재 우주 밖 still id — unknown dependency (fail-closed): Nr<   )r.   r   r   r1   r   r   )audituniverse_scene_by_idrA   expected_requestedunknownr5   s        @r"   check_scope_universer      s      %yy);<BBCB!s1vBCG  2/557 2 2 eii(.B/3EE%eii&@&FBGJ K--?,B C--. 	. %))O,23c7 G117!1D0GIJ 	J  Ds   C&c                >    t        |       |z  dz  dz  |z  t        z  S )Ncheckpointsimages)r   AUDIT_FILENAME)projects_dir
project_id
episode_ids      r"   scope_audit_pathr      s0     	\Z'-7(B
	%	&r$   c                    ddl }| j                  j                  dd       | j                  d      }|j	                  t        j                  t        |      ddd      d	
       |j                  ||        y)u   atomic replace 저장 — 크래시 창에서 절단 파일이 fail-closed 로더를
    영구 막는 것 방지 (Codex 재리뷰 HIGH-3).r   NT)parentsexist_okz	.json.tmpFr   )ensure_asciiindent	sort_keysutf-8encoding)	osparentmkdirwith_suffix
write_textjsondumpsdictreplace)re   r{   r   tmps       r"   save_scope_auditr      sh     KKdT2


;
'CNN

4;U1M   JJsDr$   c                   | j                  |      }t        |t              rt        d |D              rt	        d| d|       t        t        |            t        |      k7  rt	        d| d|       t        |      S )Nc              3  d   K   | ](  }t        |t               xs |j                           * y wr)   )r/   r   r   rk   s     r"   r-   z#_require_id_list.<locals>.<genexpr>  s/      )C=A
1c""3!'')m3Ts   .0u   표적 scope audit u    형상 오류 (fail-closed): u    중복 id (fail-closed): )r.   r/   listanyr   lenr   )datakeyre   valss       r"   _require_id_listr     s    88C=DdD!S )C=A)C &C!#&DTFKM 	M
3t9~T"!#&@GI 	I:r$   c          	     X   | j                         st        d|  d      t        j                  | j	                  d            }t        |t              st        d|        |j                  d      t        k7  r(t        d|j                  d      dt         d	|  d
      |j                  d      dvr!t        d|j                  d      d	|  d
      |j                  d      }t        t        d |D                    }||k7  rt        d|d|d	|  d      t        |d|       }t        |d|       }t        |d|       }|st        d|        t        |      t        |      k  st        d|        t        |      t        |      z  t        |      k7  rt        d|        |S )u<  audit 로드 — 부재/형상/정합 오류=ValueError fail-closed.

    표적이 설정된 스텝 카운트/verify 는 반드시 실행이 남긴 audit 과 동일
    scope 를 소비해야 한다(독자 필터 재구현 금지 — Codex HIGH-3). 검증:
    contract_version 정확 일치, path_kind enum, requested_scenes=현재
    정규화 표적과 정확 일치(다른 표적의 stale audit 소비 차단), id 목록=
    비공백 문자열·중복 없음, requested 비어 있지 않음, requested⊆effective,
    requested∪dependency_added==effective.
    u)   표적 scope audit 부재 (fail-closed): uH    — 표적 설정 상태에서 씬 이미지 실행이 선행돼야 함r   r   u0   표적 scope audit 형상 오류 (fail-closed): rp   u=   표적 scope audit contract_version 불일치 (fail-closed): z != z (r_   rq   )recipebatchu3   표적 scope audit path_kind 오류 (fail-closed): rr   c              3  2   K   | ]  }t        |        y wr)   rj   rk   s     r"   r-   z#load_scope_audit.<locals>.<genexpr>.  s     ?!s1vrl   uv   표적 scope audit 이 현재 표적과 불일치 — 다른 표적의 stale audit 소비 차단 (fail-closed): audit=u    vs 현재=u$   ) — 씬 이미지 재실행 필요rG   rs   rt   u;   표적 scope audit requested_ids 빈 목록 (fail-closed): u8   표적 scope audit requested⊄effective (fail-closed): uL   표적 scope audit requested∪dependency_added != effective (fail-closed): )existsr   r   loads	read_textr/   r   r.   ru   r   r   r   )re   expected_scenesr   scenesexpected_normrB   	dep_addedrQ   s           r"   load_scope_auditr     s    ;;=7v >R RS 	S ::dnngn67DdD!KD6RSSxx"#'==Kxx*+.d3I2J KvQ 	 xx$77Axx$'r$q23 	3 XX()F3???@M88>z B#&b.RTU 	U !=I '94@I =II$PR 	Ry>S^+FtfMO 	O
9~I&#i.8"V%& 	& Kr$   )r   r   returnzTuple[int, ...])r3   Sequence[Mapping[str, Any]]r4   Sequence[int]r   	List[str])r3   r   rG   Sequence[str]rH   zMapping[int, Set[int]]r   Tuple[List[str], List[str]])rX   r   rY   Mapping[str, Mapping[str, Any]]rZ   r   r   zDict[str, str])ra   r   rb   zMapping[str, str]rc   zSet[str]r   r   )
r4   r   rG   r   rv   r   rq   r   r   Dict[str, Any])r{   Mapping[str, Any]r|   zMapping[str, int]r   None)r   z
str | Pathr   r   r   r   r   r   )re   r   r{   r   r   r   )r   r   r   r   re   r   r   r   )re   r   r   r   r   r   )__doc__
__future__r   r   pathlibr   typingr   r   r   r   r	   r
   r   r   ru   r#   r:   rS   r]   rg   rw   r   r   r   r   r   r   r$   r"   <module>r      so  , #   A A A* :'  4#'# # !# !	#L
3 1 	4$!$$ $ !	$@  ! (	
  & J J+ J 
 JF*-;>		0
0$100r$   