+
    !i6                       R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RIHt ^ RI	H
t
HtHtHtHt ]! ]4      P!                  4       P"                  ^,          t]R,          t]! ]4      ]P*                  9  d#   ]P*                  P-                  ^ ]! ]4      4       R R ltRR	 R
 lltR R ltR R ltR R ltR R ltR R ltR R lt]R8X  d   ]P@                  ! ]! 4       4       R# R# )u  G4.2 canary — owned-violation cumulative count (G3.2 sentinel CP read).

Reads pre-computed `t2i_variations[*].owned_validation` sentinel objects from
the scene_detail checkpoint. Each sentinel `violations` list length is summed
per shot (and per scene_set). NO LLM calls. Uses the strict shape validator
from `app.core.steps._owned_helpers.assert_owned_sentinel_shape` (plan-R2-I5).

Exit criteria (analyzer):
  candidate.metrics.owned_violations_total <= baseline.metrics.owned_violations_total
  AND both runs' measurement_failures lists are empty.

Usage (config mode):
    python scripts/canary/g4_2_owned_violations.py \
        --config canary_config.json --role candidate \
        --output results/owned_violations_candidate.json
)annotationsN)datetime)Path)AnyDictListOptionalTuplebackendc                   V ^8  d   QhRR/# )   returnstr )formats   "'scripts/canary/g4_2_owned_violations.py__annotate__r   #   s     / /S /    c                 V    \         P                  ! 4       P                  4       R ,           # )Z)r   utcnow	isoformatr   r   r   iso8601_nowr   #   s    ??&&(3..r   c               $    V ^8  d   QhRRRRRR/# )r   msgr   codeintr   Noner   )r   s   "r   r   r   '   s!      s # d r   c                n    \        R V  2\        P                  R7       \        P                  ! V4       R# )z[g4_2_owned_violations] ERROR: fileN)printsysstderrexit)r   r   s   &&r   _failr%   '   s#    	+C5
1

CHHTNr   c                    V ^8  d   QhRRRR/# )r   argszargparse.Namespacer   Dict[str, Any]r   )r   s   "r   r   r   ,   s     % %) %n %r   c                   V P                   '       d   \        V P                   4      pVP                  4       '       g   \        R V 24        VP	                  RRR7      ;_uu_ 4       p\
        P                  ! V4      pRRR4       RXP                  R4      RTP                  R4      RTP                  R4      R	TP                  R	4      R
TP                  R
4      RTP                  R4      RTP                  R4      /#  V P                  '       d!   \
        P                  ! V P                  4      MRpV P                  '       d!   \
        P                  ! V P                  4      MRpRV P                  RXRXR	V P                  R
V P                  RV P                  RV P                   /#   + '       g   i     EL5; i  \         d   p\        RT 24        Rp?ELWRp?ii ; i  \         d   p\        RT 24        Rp?LRp?ii ; i)z--config file not found: rutf-8encodingNz--config parse error: pidscene_index_listshot_index_list_per_scenemodel_routingprompt_source_modecard_commit_hashchain_bg_card_snapshot_hashz%failed to parse list/dict JSON args: )configr   existsr%   openjsonload	Exceptiongetr/   loadsr0   r.   r1   r2   r3   r4   )r'   cfg_pathfpcfgexcr/   r0   s   &      r   load_pinningrA   ,   s   {{{$  -hZ89	2sW55iim 6
 3775>(: ;'1L)MSWW_5 #''*>"?(: ;)3773P+Q
 	
	=151F1F1FDJJt,,-D 	
 --- JJt55637 	" 	txx,#%>++d55D11%t'G'G / 655 	2*3%011	2&  =5cU;<<=sZ   F? (F+?F? G& 3G& "G& +F<	6F? <F? ?G#
GG#&H	1HH	c                    V ^8  d   QhRRRR/# )r   pinningr(   r   r   r   )r   s   "r   r   r   T   s     P Pn P Pr   c                :   . ROpV Uu. uF  q P                  V4      R	9   g   K  VNK  	  ppV'       d   \        RV R24       \        V R,          \        4      '       g   \        R4       \        V R,          \        4      '       g   \        R4       R# R# u upi )
r.   r/   r0   Nz#pinning missing required field(s): zF. Provide via --config <json> or individual flags. NO silent defaults.z*pinning.scene_index_list must be list[int]z>pinning.shot_index_list_per_scene must be dict[str, list[int]])r.   r/   r0   r1   r2   r3   r4   )N )r;   r%   
isinstancelistdict)rC   requiredkmissings   &   r   validate_pinningrL   T   s    H
 #C(Qkk!n
&Bqq(GC1' ;S T	
 g01488:;g9:DAANO B Ds
   BBc                    V ^8  d   QhRRRR/# )r   rC   r(   r   zList[Tuple[int, int]]r   )r   s   "r   r   r   f   s      ^ 8M r   c           	        . pV R,          pV R,           F  p\        V4      pVP                  \        V4      4      pVf   VP                  V4      pVf   \        RV R24       \	        V\
        4      '       g&   \        RV R\        V4      P                   R24       V'       g   \        RV R24       V F  pVP                  V\        V4      34       K!  	  K  	  V# )	u  Cartesian (scene_index, shot_index) tuples from pinning block.

Strict — pinning enumerates EXACT (si, shi) tuples. A scene_index without
a corresponding shot_index_list entry (or with a non-list / empty list)
is a contract violation, not a silent default. fail-fast via _fail.
r0   r/   z(pinning.scene_index_list contains scene zF but shot_index_list_per_scene has no entry for it. NO silent default.z"pinning.shot_index_list_per_scene[z] must be list[int], got z. NO silent default.uR   ] is empty — a pinned scene must enumerate at least one shot. NO silent default.)	r   r;   r   r%   rF   rG   type__name__append)rC   outshot_mapsisi_int	raw_shotsshis   &      r   build_pinning_scene_setrX   f   s     "$C23H())RLLV-	 V,I:6( CT U )T**4VH =I//00DF 4VH =V W CJJC)* ) *, Jr   c                    V ^8  d   QhRRRR/# )r   cp_rootr   r   r(   r   )r   s   "r   r   r      s     3 3d 3~ 3r   c                L   V R ,          pVP                  4       '       g   \        RV 24        VP                  RRR7      ;_uu_ 4       p\        P                  ! V4      uuRRR4       #   + '       g   i     R# ; i  \
         d   p\        RT 24        Rp?R# Rp?ii ; i)zmanifest.jsonzmanifest.json not found at r*   r+   r,   Nzmanifest.json parse error: )r6   r%   r7   r8   r9   r:   )rZ   manifest_pathr>   r@   s   &   r   load_cp_manifestr]      s    o-M!!+M?;<3g66"99R= 7666 3+C51223s5   A? 
A+ 
A? +A<	6A? <A? ?B#
BB#c                    V ^8  d   QhRRRR/# )r   scener(   r   zTuple[bool, Optional[str]]r   )r   s   "r   r   r      s      N /I r   c                   V P                  R4      p\        V\        4      '       g   R# VP                  R4      p\        V\        4      '       g   R# VP                  R4      R8X  d   R	# VP                  R4      RJ d   R	# R
# )u  Return (cf_flag, error_message).

Reads from `scene["render_prompt_card"]["background_binding"]` — the actual
CP shape produced by detail_steps.py (scene["background_binding"] does NOT
exist as a flat field). When the scene record is missing the
`render_prompt_card` envelope or its `background_binding` field, returns
(False, reason) so the caller can append to measurement_failures
(NO silent absorb — Codex C1 fix).

error_message is None on success.
render_prompt_cardbackground_bindingmodeskipped_close_framingT"close_framing_skips_background_ref)Fz&render_prompt_card missing or not dict)Fz9render_prompt_card.background_binding missing or not dict)TN)FN)r;   rF   rH   )r_   rpcbbs   &  r   is_close_framingrh      s}     ))(
)Cc4  @@	%	&Bb$SS	vvf~00	vv23t;r   c                   V ^8  d   QhRR/# )r   r   r   r   )r   s   "r   r   r      s     h hc hr   c                    \         P                  ! R R7      p V P                  R\        RR7       V P                  R\        RR7       V P                  R\        RR7       V P                  R\        RRR	7       V P                  R
\        RR7       V P                  R\        RRR.R7       V P                  R\        RR7       V P                  R\        RR7       V P                  R\        RR7       V P                  R\        R. RQOR7       V P                  R\        RR7       V P                  R\        RR7       V P                  R\        RR7       V P	                  4       p\        V4      p\        V4        ^ RIHp RpVP                  '       d_   \        VP                  4      P                  RRR7      ;_uu_ 4       p\        P                  ! V4      pRRR4       XP!                  R4      pV'       g   VP"                  pV'       g   \        R4       \        V4      pVP%                  4       '       g   \        R V 24       \'        V4      p	V	P!                  R!4      p
\)        V
\*        4      '       g   \        R"4       V
P!                  R#4      p\)        V\,        4      '       g   \        R$4       \/        \1        V4      4      p\/        4       p^ p/ p. p. p^ pV EF  p\)        V\*        4      '       g   K  VP!                  R%4      pVP!                  R&4      pVe   Vf   KH  VV3V9  d   KS  VP3                  \5        V4      \5        V4      34       V^,          p\7        V4      w  ppV'       d   VP9                  R'V R(V R)V 24       VP9                  R%VR*VR+V/4       VP!                  R,4      p\)        V\,        4      '       d	   V'       g   VP9                  R'V R(V R-24       EK  ^ pV Fp  pVP!                  R.4      pVf   VP9                  R'V R(V R/24       K2   X! VR0V R(V 2R17       TP!                  R34      ;'       g    . pT\=        T4      ,          pKr  	  VV,          pVVV R4V 2&   EK  	  V F)  w  ppVV3V9  g   K  VP9                  R5V R(V R624       K+  	  R7\?        4       R8VP@                  R9VPB                  R:VR;VR<R=VR>VR?V/R@VRARBRC//pVPD                  RD8X  dJ   \        PF                  ! V\H        PJ                  RE^RRF7       \H        PJ                  PM                  RG4       Mq\        VPD                  4      pVPN                  PQ                  RRRH7       VP                  RIRR7      ;_uu_ 4       p\        PF                  ! VVRE^RRF7       RRR4       \S        RJVPB                   RKVP@                   RLV RMV RN\=        V4       RO2\H        PT                  RP7       V'       d   ^# ^ #   \         d   p\        RT R24        Rp?ELRp?ii ; i  + '       g   i     EL_; i  \:         d'   pTP9                  R'T R(T R2T 24        Rp?EKx  Rp?ii ; i  + '       g   i     L; i)RzFG4.2 canary: owned-violation cumulative count (G3.2 sentinel CP read).)descriptionz--configN)rO   defaultz--pidz	--episodez	--cp-rootz/Directory containing scene_detail manifest.json)rO   rl   helpz--prompt-versionT)rO   rI   z--role	candidatebaseline)rO   rl   choicesz--scene-index-listz--shot-index-list-per-scenez--model-routingz--prompt-source-modez--card-commit-hashz--chain-bg-card-snapshot-hashz--output)assert_owned_sentinel_shapezHCannot import app.core.steps._owned_helpers (backend not on sys.path?): z6. Run from repo root or set PYTHONPATH=<repo>/backend.r*   r+   r,   rZ   z)--cp-root (or config.cp_root) is requiredz--cp-root path does not exist: dataz!cp['data'] is missing or not dictscenesz+cp['data']['scenes'] is missing or not listscene_index_shot_indexs_shz: 
shot_indexrh   t2i_variationsz,: t2i_variations missing, empty, or not listowned_validationu"   : owned_validation sentinel 부재zcanary.owned_violations s)whereu   : sentinel shape 위반 — 
violations_z
pinning (sz ): not present in CP data.scenes	timestampprompt_versionrolerC   	scene_setmetricstotal_shotsowned_violations_totalowned_violations_per_shotmeasurement_failuresmeasurement_scriptsowned_violationsuN   scripts/canary/g4_2_owned_violations.py (G3.2 sentinel CP read — plan-R1-B2)-F)ensure_asciiindent	sort_keys
)parentsexist_okwz[g4_2_owned_violations] role=z prompt_version=z
  total_shots=z  owned_violations_total=z
  measurement_failures: z
Exit criteria:
  candidate.metrics.owned_violations_total <= baseline.metrics.owned_violations_total
  AND both runs' measurement_failures must be empty.r   )Nr    db)+argparseArgumentParseradd_argumentr   
parse_argsrA   rL   app.core.steps._owned_helpersrq   ModuleNotFoundErrorr%   r5   r   r7   r8   r9   r;   rZ   r6   r]   rF   rH   rG   setrX   addr   rh   rQ   r:   lenr   r   r   outputdumpr"   stdoutwriteparentmkdirr!   r#   )parserr'   rC   rq   r@   cp_root_strr>   r?   rZ   cprr   rs   pinning_scene_set
seen_in_cpr   r   r   scene_set_outr   r_   rT   rW   cfcf_err
variations
shot_countvarsentinelr|   rR   out_paths                                  r   mainr      se   $$\F 
d;
c48
#t<
#tN  P
*tD
sK!+[ 9  ;
,3E
5CN
)TB
.S$ 4  6
,3E
7c4P

t<D4 GW
M #K{{{$++##C'#::b))B-C ;ggi(ll9:;G>>/y9:	'	"B 66&>DdD!!12XXhFfd##;<3G<='*uJ02&(*,MK%&&YY}%ii&:9--BS*+q%e,
F ''B4s3%r&* 	2|S2Db
 	 YY/0
*d++: ''B4s3%KL 
Cww12H$++t3se#EF +&?t3se$L "l399rJ#j/)J# $ 	*,3=!RD#-0c l '	S9J& ''RDC5(HI ' 	[]$--		7];$&<')B

 	 4 p 
C" {{c		#szza4P

$dT:]]3]11RIIc2E!tL 2 

'		{2B4CVCVBW X$%>?U>V W##&';#<"= >?	@ ZZ Y  
VWZV[ \C D	
 	

 ;::P  $++t3se#?uE 	T 21sH   >X X3.YY;X0X++X03Y	Y8Y33Y8;Z	__main__)   )!__doc__
__future__r   r   r8   r"   r   pathlibr   typingr   r   r   r   r	   __file__resolver   
_REPO_ROOT_BACKEND_PATHr   pathinsertr   r%   rA   rL   rX   r]   rh   r   rP   r$   r   r   r   <module>r      s     #   
   3 3 (^##%--a0
Y&}SXX%HHOOAs=)*/
%PP$D32hV zHHTV r   