
    g2iH-                    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 ej                  j                  d e
 ee      j                         j                               ddlmZmZmZmZmZmZmZmZmZ  e       Zed   ZddZdd	Zdd
Z	 	 	 	 	 	 	 	 ddZedk(  r ej>                   e              yy)u  G4.4 canary — STRICT atmosphere_reference no-layout-import detection (Task 4.3).

Detects 7 furniture / wall / layout tokens (`furniture` / `wall position` /
`room layout` / `same chair` / `same table` / `same wall` / `same window`)
inside `t2i_prompt` of shots with at least one
`previous_shot_refs[i].ref_usage == "atmosphere_reference"` (Override O-11
multi-ref filter — atmosphere co-presence with `exact_background` still
triggers; false-positive baseline >0 → P1 follow-up).

Token list imported from
`render_prompt_card._CONTINUITY_FURNITURE_LAYOUT_TOKENS` (Trap #8 —
module-level constant single source).

Override O-17 — regex brittleness: this regex/substring-based detector is a
1차 detector only. If baseline >0 (e.g. natural usage like "the wall position
is preserved" — a rationale, not an import), escalate to LLM-validator
(gpt-5.4-mini judge) as P1 follow-up. `feedback_no_regex_postprocessing.md`
carry.

Scope: shots where `any(ref.ref_usage == "atmosphere_reference" for ref in
previous_shot_refs)` (R2-B4 carry / Override O-11).

Exit criteria (analyzer, OUT-OF-BAND):
  candidate.metrics.atmosphere_layout_import_count == 0  (STRICT, Override O-1)

Usage (config mode):
    python scripts/canary/g4_4_atmosphere_no_layout_import.py \
        --config canary_config.json \
        --cp-root data/projects/<pid>/checkpoints/scene_detail \
        --prompt-version 19.<timestamp> \
        --role candidate \
        --output results/atmosphere_candidate.json
    )annotationsN)datetime)Path)	_load_scenes_or_fail_validate_scene_preflightbuild_pinning_scene_setemit_outputload_cp_manifestload_pinning_from_argsrender_prompt_card_importsresolve_cp_rootvalidate_pinning#_CONTINUITY_FURNITURE_LAYOUT_TOKENSc                 L    t        j                         j                         dz   S )NZ)r   utcnow	isoformat     2scripts/canary/g4_4_atmosphere_no_layout_import.pyiso8601_nowr   >   s    ??&&(3..r   c                    g }| j                         }t        D ]&  }|j                         |v s|j                  |       ( |S )u   7 furniture/layout token 중 prompt 안 등장 list 반환.

    Case-insensitive literal substring match — full-text scan
    (CLAUDE.md no-truncation carry). Override O-17: 1차 detector only —
    LLM-validator escalation P1 follow-up.
    )lowerr   append)promptfoundprompt_lowertokens       r   find_layout_importsr   B   s?     E<<>L4;;=L(LL 5 Lr   c                 	   t        j                  d      } | j                  dt        d        | j                  dt        d        | j                  dt        d        | j                  dt        d	       | j                  d
t        dddg       | j                  dt        d        | j                  dt        d        | j                  dt        d        | j                  dt        d g d       | j                  dt        d        | j                  dt        d        | j                  dt        d	       | j	                         }t        |      }t        |       t        |      }t        |      }g }t        ||      }|t        |||      }t        ||       yt        |      }t               }	d}
d}d}i }g }|D ]Q  }t        |t              s|j!                  d       &|j#                  d      }|j#                  d      }||Mt%        |      }t%        |      }||f|vrj|	j'                  ||f       t)        ||||      }||d   }|d   }d|vr|j!                  d| d| d        |d   }t        |t*              s|j!                  d| d| d!       t-        d" |D              }t-        d# |D              }t/        |D ch c]B  }t        |t              r0t        |j#                  d$      t              r|j#                  d$      D c}      }|j!                  |||||d%       |sy|
dz  }
|r|dz  }d}g }t1        |      D ]  \  }}t        |t              s|j!                  d| d| d&| d'       2|j#                  d(      } t        | t              r| j3                         s|j!                  d| d| d&| d)       t5        |       }!|t7        |!      z  }|j9                  |!        ||z  }|||d*|| d+| <   T |D ]$  \  }}||f|	vs|j!                  d,| d| d-       & t;               |j<                  |j>                  |||
|||t+        t@              d.|d| xr |dk(  d/d0id1
}t        ||       tC        d2|j>                   d3|j<                   d4|
 d5| d6| d7t7        |       d8tD        jF                  9       |ry|j>                  dk(  r|dkD  ryyc c}w ):Nu   G4.4 canary: atmosphere_reference no-layout-import detection (Override O-11 multi-ref filter — Override O-17 regex 1차 only).)descriptionz--config)typedefaultz--pidz	--cp-rootz--prompt-versionT)r"   requiredz--role	candidatebaseline)r"   r#   choicesz--scene-index-listz--shot-index-list-per-scenez--model-routingz--prompt-source-mode)Nfiledbz--card-commit-hashz--continuity-card-snapshot-hashz--output   r   zscene entry is not dictscene_index_shot_indexrender_prompt_cardcontinuity_elements_usedprevious_shot_refss_shz9: continuity_elements_used.previous_shot_refs key missingz6: continuity_elements_used.previous_shot_refs not listc              3  h   K   | ]*  }t        |t              xr |j                  d       dk(   , yw)	ref_usageatmosphere_referenceN
isinstancedictget.0rs     r   	<genexpr>zmain.<locals>.<genexpr>   s=      
  q$ =k"&<<=   02c              3  h   K   | ]*  }t        |t              xr |j                  d       dk(   , yw)r3   exact_backgroundNr5   r9   s     r   r<   zmain.<locals>.<genexpr>   s6      '
 q$LAEE+$6:L$LLr=   r3   )r+   
shot_indexhas_atmosphere_referenceexact_bg_co_presentref_usage_signature_vz: variation not a dict
t2i_promptz': t2i_prompt missing, empty, or not str)counttokensrB   _z
pinning (sz ): not present in CP data.scenes total_atmosphere_reference_shotsatmosphere_multi_ref_shotsatmosphere_layout_import_count!atmosphere_layout_import_per_shotfurniture_layout_tokens_usedatmosphere_no_layout_importu   scripts/canary/g4_4_atmosphere_no_layout_import.py (atmosphere_reference shots only — Override O-11 multi-ref filter, Override O-17 regex 1차 only)
	timestampprompt_versionrolepinning	scene_setmetricsmeasurement_failuresexit_criteria_thresholdexit_criteria_passmeasurement_scriptsz([g4_4_atmosphere_no_layout_import] role=z prompt_version=z$
  total_atmosphere_reference_shots=z
  atmosphere_multi_ref_shots=z7 (P1 follow-up if >0)
  atmosphere_layout_import_count=z
  measurement_failures: zN
Exit criteria (STRICT): candidate.metrics.atmosphere_layout_import_count == 0)r(   )$argparseArgumentParseradd_argumentstr
parse_argsr   r   r   r
   r   _empty_outputr	   r   setr6   r7   r   r8   intaddr   listanysorted	enumeratestripr   lenextendr   rR   rS   r   printsysstderr)"parserargsrT   cp_rootcprW   scenesoutpinning_set
seen_in_cptotal_atmosphere_shotsrK   rL   rM   scene_set_outscenesishisi_intshi_int
variationsrpccerefshas_atmospherehas_exact_bg_co_presencer;   rC   
shot_countshot_layout_tokensvivarr   layoutss"                                     r   mainr   R   s   $$RF 
d;
c48
#t<
*tD
[)	   ,3E
5CN
)TB
$	   ,3E
)T   
t<D$T*GWd#G	'	"B&(!"&:;F~D'+?@C)'2K'*uJ!"%&"9;% "M%& ''(ABYY}%ii&:Rc(GK/().67$8

 ()+,r) ''F83wi (1 2 &'$% ''F83wi (. /   
 
 

 $' '
'
 $
  %&
!T"z!%%2Dc'J EE+&
  	!!(6#;#6
 	 !## '!+&
(* ,GBc4($++xs7)2bT1GH WW\*Ffc*&,,.$++xs7)2bT 2( ) )&1G#g,&J%%g. -" 	'*4&(#;D
)VHAgY*?@u B !	S9J& ''RDC5(HI ! !]--		"0F*D.L1,03-

 !5#$$$L)G1)L *9 
-C> T	
2499+ >--. /..D-E F((B'C D, *
* +##&';#<"= >@		A ZZ yyK$BQ$FW&
s   AS8
c                ~    t               | j                  | j                  |g dddi t        t              d|ddddid
S )Nr   rI   FrO   uf   scripts/canary/g4_4_atmosphere_no_layout_import.py (atmosphere_reference shots only — Override O-11)rP   )r   rR   rS   rd   r   )ro   rT   rW   s      r   r`   r`   %  s^     !]--		01*+./13,03-
 !5#$#)F 
% r   __main__)returnr^   )r   r^   r   z	list[str])r   rb   )ro   zargparse.NamespacerT   r7   rW   rd   r   r7   ) __doc__
__future__r   r[   rl   r   pathlibr   pathinsertr^   __file__resolveparent_g4_4_commonr   r   r   r	   r
   r   r   r   r   _CONSTSr   r   r   r   r`   __name__exitr   r   r   <module>r      s    B #  
   3tH~--/667 8
 
 
 %
&&-)' #
/ Pf
  
	@ zCHHTV r   