
    zXj                    (   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
 ddlmZmZ  ej                  e      ZdZdZd	d
iZddZddZdZd	d	 	 	 	 	 	 	 	 	 	 	 ddZddd	dd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddd	dd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy)uP  conti_ab — 콘티 사용/미사용 A/B 외부 판정 (E2E6 피드백 ⑧, 2026-07-16).

일반(non-lane·non-prev·비 bgonly) 콘티 사용 샷에서 A(콘티 참조 포함)/
B(미포함) 두 완결 파이프 산출(_sel)을 outer VLM 이 비교해 우세본을
채택한다. Codex 설계 합의:
  - 첫 production acceptance = 풀 3롤×2 (1롤 프로브는 생성 분산을 모드
    효과로 오인 — 부적합).
  - 블라인드(내부 선택지 노출 금지) + 입력 순서 뒤집기 2회 판정 —
    불일치=동점, 동점=콘티 사용본(기존 파이프 연속성).
  - 1차 범위=일반 shot_conti_light 콘티 샷만 (lane1 스케치=동등한
    무스케치 앵커 없어 불공정, lane2 direct_seed=스케치 자체 없음).
판정 계약=프레이밍 최상위(multiroll_judge v2 와 동일 원칙, S23sh1 교훈).
    )annotationsN)Path)AnyCallableDictOptional)load_promptload_schemaconti_ab_judgez
gemini-pro1z1.202607161800c           	     n    	 t         |    S # t        $ r  t        d| dt        t                d      w xY w)Nz/unknown conti_ab_judge prompt version selector z	 (known: ))PROMPT_VERSION_MAPKeyError
ValueErrorsorted)selectors    S/Users/manta/Documents/Projects/TheRoad-I1/backend/app/modules/pipeline/conti_ab.pyresolve_prompt_versionr       sK    
!(++ 
=l)F+=$>#?qB
 	

s    )4c                    | D ch c]  }|j                  d       }}t        |       dk(  r|dhdhfv r| d   d   S yc c}w )u   순서 뒤집기 2회 판정 → 'A'|'B'|'tie' (불일치=tie).

    verdicts=[{"order": "AB"|"BA", "winner_branch": "A"|"B", ...}].
    순수 함수 — 동점 시 콘티 사용본(A) 채택은 caller 정책.
    winner_branch   ABr   tie)getlen)verdictsvbranchess      r   decide_winnerr!   *   sS     1991o&H9
8}hC53%.8{?++ :s   >tie_keeps_conti_v1)prompt_versionc                   ddl }ddl}| |j                  t        |      j	                               j                         |j                  t        |      j	                               j                         t        |      |t        d}|j                  |j                  |d      j                  d            j                         dd S )u  outer 결정의 내구 지문 (Codex 8e70d4c0 BLOCKING-1).

    prompt + 양 branch sel **내용 해시** + outer 팩 해석값 + 물리 판정
    모델 + tie 정책. 일치=재판정 0콜로 동일 winner 재사용, 어느 하나
    변경=재판정.
    r   N)prompt	sel_a_sha	sel_b_sha
outer_packjudge_model_physical
tie_policyT)	sort_keyszutf-8   )
hashlibjsonsha256r   
read_bytes	hexdigestr   
TIE_POLICYdumpsencode)r%   sel_asel_br)   r#   r-   _jsonpayloads           r   decision_fingerprintr9   9   s      ^^DK$:$:$<=GGI^^DK$:$:$<=GGI,^< 4 G >>Gt,33G<ik#2     )call_structured_fnproject_configr#   opik_metadatac        	   	         t        | ||||      }	t        |t              r/|j                  d      |	k(  r|j                  d      dv ri |ddiS t	        | ||||||      }
|
d   dk7  r|
d   nd	}|	||
d
dS )u  durable 결정 resolve — 지문 일치=outer 0콜 재사용, 아니면 판정.

    반환 {fingerprint, winner("A"|"B" — tie 정책 적용 후), outer, judged}.
    판정 실패는 raise — 사전 결정이 없을 때의 fail-open(A 고착)은
    durable 결정 도입으로 불필요, 샷 단위 실패 격리 후 resume 재판정이
    안전측 (Codex B1: 기존 B 승리가 일시 오류로 A 로 뒤집히던 창 제거).
    )r%   r5   r6   r)   r#   fingerprintwinner)r   r   judgedF)r%   r5   r6   r;   r<   r#   r=   r   r   T)r?   r@   outerrA   )r9   
isinstancedictr   run_conti_ab_outer_judge)r%   r5   r6   prior_decisionr)   r;   r<   r#   r=   fprB   r@   s               r   resolve_or_run_outerrH   W   s    & 
U%1%
B 	>4(}-3x(J62.2(E22$U%-%%#E !&h5 8U8_cF	 r:   c           
     2   ddl m} |ddlm} |}t	        |      }	t        t        d|	      }
t        t        dd|	      }i |xs i t         dt        ii}g }d	||ffd
||fffD ]  \  }\  }}dd| z   dddd ||      ddd ||      g} |t        |
|||t        |      }|j                  d      xs dj                         }|d	k(  r
|dk(  rdnd}n	|dk(  rdnd}|j                  ||||j                  d      xs dd        t        |      |dS )u   블라인드 2회(순서 뒤집기) outer 판정 → {"winner": "A"|"B"|"tie",
    "verdicts": [...]}. 라벨은 항상 "1"/"2" — 어느 쪽이 콘티 사용본인지
    판정자에게 노출하지 않는다(블라인드).
    r   )png_partN)call_structuredjudge_system)versionjudge_schemamodelABBAtextz7THE PROMPT (both candidates were generated from this):
)typerR   zCandidate 1:zCandidate 2:)r<   schema_namer=   r@    r   r   r   	reason_ko)orderwinner_labelr   rV   )r@   r   )%app.modules.pipeline.multiroll_geminirJ   app.modules.llm.llm_clientrK   r   r	   _MODULEr
   AB_JUDGE_MODELr   stripappendr!   )r%   r5   r6   r;   r<   r#   r=   rJ   rK   resolved	judge_sysrN   pcr   rW   firstsecondpartsreslabelr   s                        r   rE   rE      sq    ?!>,%n5HG^XFIw'/1L
3^!r 
3I.1
3B H	u~	u~#v
 !#)*+ ^4UO^4V
 !Y|7'

 "(b//1D=#(C<CSM#(C<CSM!*-3	
 	/#: $H-8DDr:   )r   strreturnrg   )r   listrh   rg   )r%   rg   r5   r   r6   r   r)   rg   r#   rg   rh   rg   )r%   rg   r5   r   r6   r   rF   Optional[Dict[str, Any]]r)   rg   r;   'Optional[Callable[..., Dict[str, Any]]]r<   rj   r#   rg   r=   rj   rh   Dict[str, Any])r%   rg   r5   r   r6   r   r;   rk   r<   rj   r#   rg   r=   rj   rh   rl   )__doc__
__future__r   loggingpathlibr   typingr   r   r   r   app.modules.prompt_loaderr	   r
   	getLogger__name__loggerr[   r\   r   r   r!   r2   r9   rH   rE    r:   r   <module>rw      s   #   0 0 >			8	$
 	 

	 "
   	
   	J CG/3.2++ + 	+
 -+ + @+ -+ + ,+ +f CG/3.2:E:E :E 	:E
 @:E -:E :E ,:E :Er:   