
    3j                    D   d Z ddlmZ ddlZddlmZmZ ddlmZ ddlm	Z	m
Z
 dZdZd	ZeD  ci c]  } | d c} Zdd
ZddZdddddddddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZddZdd	 	 	 	 	 	 	 ddZg dZyc c} w )uq  anu_v3.cancel_audit_writer — cancel-on-success audit record builder/writer.

task-2553+45 (회장 지시 2 §3/§5). Standalone, pure stdlib, strict-additive.

회장 §3 verbatim: "cancel-audit JSON 을 생성한다." 본 모듈은 live
cancel-on-success 경로(``anu_v3.cancel_on_success_live_wiring``)가 산출한
관측을 ``schemas/cancel_on_success_audit.schema.json`` 에 정합하는 단일
레코드로 빌드하고, 단일 디렉터리 IO 실패가 산출 손실로 이어지지 않도록
다중 후보에 보장 기록한다 (+37 ``_guaranteed_write_audit`` /
``_normalize_cancel_audit`` 의 회장 승인·frozen 동일 패턴을 standalone
신규 모듈로 재현 — 기존 +25/+37 산출물 무수정).

Layer A / NO-CRON (9-R.1): 본 모듈은 ZERO cron register/remove, ZERO
dispatch, ZERO merge, ZERO ``cokacdir``/``subprocess`` exec. audit dict 를
빌드하고 파일로 쓰기만 한다. 감사기록 파일 IO 실패는 raise 로 전파하지
않는다 — 디커플 의무(§3: "cron-remove 실패/skip/exception 이 normal
collector success 를 실패로 바꾸지 않게 decouple") 및 +25/+37 동일 계약.
    )annotationsN)datetimetimezone)Path)ListOptionalz'task-2553+45.cancel-on-success-audit_v1)schemaevent_idtask_idtarget_cron_idlookup_sourcelookup_statusfive_condition_resultsremove_attemptedremove_resultseam_invokedskip_reasonalready_removed_or_missingnormal_success_unchanged&wired_via_operational_collector_wiring)c1_task_id_matchc2_chat_id_ownedc3_role_fallbackc4_marker_id_crosscheck c5_pending_not_fired_not_removedc                 f    t        j                  t        j                        j	                  d      S )Nz%Y-%m-%dT%H:%M:%SZ)r   nowr   utcstrftime     1/home/jay/workspace/anu_v3/cancel_audit_writer.py_now_utcr#   ;   s!    <<%../CDDr!   c                t    t        t              }t        | t               rt        D ]  }|| v s| |   ||<    |S )uJ   5조건 결과를 schema 정합 형태로 정규화 (누락 키 → None).)dict_EMPTY_FIVE
isinstance_FIVE_CONDITION_KEYS)fiveoutks      r"   normalize_five_conditionsr,   ?   s@    
{
C$% 	!ADyaA	! Jr!   durable_4tuple_registryFNOT_ATTEMPTED T)r   r   r   r   fallback_cancelledr   r   r   canonical_rootledger_pathr   notests_utcc                   i dt         d| d|d|d|d|dt        |	      dt        |      d	|d
t        |      dt        |      d|
dt        |      dddt        |      d|d|t        |xs g       |xs
 t	               dS )u   단일 cancel-on-success audit 레코드 (schema 정합).

    ``normal_success_unchanged`` 는 디커플 절대불변 — 무엇이 와도 True
    (회장 §3: cancel 실패/skip/exception 이 normal success 를 뒤집지 않음).
    r	   r
   r   r   r   r   r   r   r   r0   r   r   r   r   Tr   r1   r2   )r3   r4   )CANCEL_ON_SUCCESS_AUDIT_SCHEMAr,   boollistr#   )r
   r   r   r   r   r   r   r   r0   r   r   r   r1   r2   r   r3   r4   s                    r"   build_cancel_on_success_auditr9   I   s   20H 	7 	.	
 	 	 	!";"#
 	D!12 	 	d#56 	\* 	{ 	%d+E&F" 	#D#$ 	1$23
%* 	.+, 	{-. ekr"&HJ1 r!   c                   t        | t              rt        |       ni }|j                  dt               |j                  d|       |j                  d|       |j                  d|       |j                  dd       |j                  dd       t	        |j                  d	            |d	<   |j                  d
d       |j                  dd       |j                  dd       |j                  dd       |j                  dd       |j                  dd       d|d<   |j                  dd       |j                  dd       |j                  dd       |j                  dg        |j                  dt                      |S )u   필수 필드 전수 보장 — 누락 시 안전 기본값 backfill.

    디커플 불변: ``normal_success_unchanged`` 는 무엇이 와도 True.
    r	   r
   r   r   r   r-   r   NOT_INVOKEDr   r   Fr   r.   r0   r   r   r/   r   Tr   r   r1   Nr2   r3   r4   )r'   r%   
setdefaultr6   r,   getr#   )auditr
   r   r   as        r"   normalize_auditr@   ~   s?    "%.UBALL9:LLX&LLG$LL!>2LL";<LL-0";	&'#A LL#U+LL/2LL%u-LL'LL#LL-u5$(A !LL94@LL!4(LL%LL"LL8:&Hr!   c                X     t         t              xr t         fdt        D              S )u;   필수 필드 누락 0 여부 (regression 8 로컬 강제).c              3  &   K   | ]  }|v  
 y w)Nr    ).0r+   r>   s     r"   	<genexpr>z$audit_is_complete.<locals>.<genexpr>   s      +U
+s   )r'   r%   allREQUIRED_AUDIT_FIELDS)r>   s   `r"   audit_is_completerG      s+    eT" s +1+ ( r!   )	fallbacksc                  t        j                  | dd      }|g|xs g D cg c]  }||	 }}|D ]?  }	 |j                  j                  dd       |j	                  |d       t        |      c S  yc c}w # t        $ r Y Sw xY w)	u  cancel-audit JSON on-disk 산출 보장 (다중 후보 순차 시도).

    단일 디렉터리 실패가 artifact 손실로 이어지지 않게 primary →
    fallback 후보에 순차 기록을 시도한다. 반환 = 최초 성공 경로(전부
    실패해도 in-memory audit dict 는 호출자 result/decision JSON 으로
    영속되어 산출 보장). OSError 를 raise 로 전파하지 않음 = 디커플 의무.
    F   )ensure_asciiindentNT)parentsexist_okzutf-8)encoding)jsondumpsparentmkdir
write_textstrOSError)r>   primaryrH   bodypcandscands          r"   guaranteed_write_auditr\      s     ::e%:D 5IO5G1QGEG 	KKdT:OOD7O3t9	  H  		s   A7A7:A<<	BB)r6   rF   r,   r9   r@   rG   r\   )returnrU   )r)   Optional[dict]r]   r%   )$r
   rU   r   rU   r   rU   r   rU   r   rU   r   r7   r   r7   r   rU   r0   r7   r   r^   r   rU   r   r7   r1   Optional[str]r2   r_   r   r7   r3   zOptional[List[str]]r4   r_   r]   r%   )
r>   r%   r
   rU   r   rU   r   rU   r]   r%   )r>   r%   r]   r7   )r>   r%   rW   zOptional[Path]rH   zOptional[List[Path]]r]   r_   )__doc__
__future__r   rP   r   r   pathlibr   typingr   r   r6   rF   r(   r&   r#   r,   r9   r@   rG   r\   __all__)r+   s   0r"   <module>re      s  $ #  '  ! "K  "  !551q$w5E  3"($-1',$(!%37!% %22 2 	2
 2 2 2 2 2 2 +2 2 !%2 "2 2  -1!2" #2$ %2& 
'2j!,/AD	@ '+	  $	
 2M 6s   
B