
    Ÿ#jE                       d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m	Z	m
Z
 ddlmZmZmZ ddlmZmZmZmZmZmZmZ dZd	Zd
ZdZdZdZdZdZdZdZ dZ!ejD                  jG                  eddd      Z$dZ%d"dZ&e G d d             Z'dddddd	 	 	 	 	 	 	 d#dZ(ddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d$dZ)d%d&dZ*g d Z+e,d!k(  r e- e*             y)'u  dispatch.anu_result_pickup_runner — task-2720 P0-a callback pickup runner.

wired 후보 / active=P0-b 대기, 자가발사 0.

이 모듈은 executor 가 작성한 result.json 을 pickup 하여 ANU-owned callback
발사 request(argv)를 생성한다. crontab/systemd/inotify 설치·감시 코드 0.
실 발사는 권한 있는 ANU 세션이 수행한다 (P0-b driver 가 pickup_once 를 호출).

재사용 (중복 신설 0):
  - executor_write_result_json  : dispatch.anu_owned_callback_enforcement
  - anu_runner_pickup_and_fire  : dispatch.anu_owned_callback_enforcement
  - verify_collector_authoritative: dispatch.anu_owned_callback_enforcement
  - 상수/verdicts               : 동일 모듈

Layer A / NO-CRON: cron register/remove 0, subprocess 0, merge 0.
    )annotationsN)	dataclassfield)datetimetimezone)CallableListOptional)CANONICAL_ROOTVERDICT_NON_AUTHORITATIVEVERDICT_PENDING_OWNER_PROOFVERDICT_QUARANTINEDVERDICT_REJECTEDanu_runner_pickup_and_fireverify_collector_authoritativez$dispatch.anu_result_pickup_runner.v1
WAKE_BUILTNO_RESULT_JSONFAILSKIP_TERMINALSKIP_DEDUPE
QUARANTINEPENDING_OWNER_PROOFREJECTSEALED_KEY_MISSINGLEDGER_WRITE_FAILEDmemoryeventszcallback_4tuple_index.jsonlCOKACDIR_KEY_ANUc                     	 ddl m}   |         t        j                  j                  t              xs dj                         }|xs dS # t        $ r Y Fw xY w)u}   ANU key 는 .env.keys 의 COKACDIR_KEY_ANU 환경변수로만 로드.
    코드/argv/prompt 어디에도 키 literal 금지.r   )load_env_keys N)utils.env_loaderr    	ExceptionosenvirongetENV_ANU_KEYstrip)r    vals     T/home/jay/workspace/.worktrees/task-2729p8-dev5/dispatch/anu_result_pickup_runner.py_default_sealed_key_loaderr+   ?   sO    2 ::>>+&,"
3
3
5C;$  s   A
 
	AAc                      e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   d
ed<   ded<    ee      Zded<   dZded<   e	dd       Z
ddZy)PickupResultu   pickup_once 의 반환값.strschemaverdicttask_idresult_json_pathsha256bool
wake_builtOptional[List[str]]argvclassification)default_factoryz	List[str]reasonsNOptional[str]marker_pathc                (    | j                   t        k(  S N)r0   PICKUP_WAKE_BUILTselfs    r*   okzPickupResult.ok[   s    ||000    c                $   | j                   | j                  | j                  | j                  | j                  | j
                  | j                  t        | j                        nd | j                  t        | j                        | j                  d
S )N
r/   r0   r1   r2   r3   r5   r7   r8   r:   r<   )r/   r0   r1   r2   r3   r5   r7   listr8   r:   r<   r@   s    r*   to_jsonzPickupResult.to_json_   sl    kk|||| $ 5 5kk//'+yy'<DO$"11DLL)++
 	
rC   )returnr4   )rH   dict)__name__
__module____qualname____doc____annotations__r   rF   r:   r<   propertyrB   rG    rC   r*   r-   r-   L   sa    $KLLK
t4GY4!%K%1 1
rC   r-   r!   r1   r2   r3   r8   r:   c               N    t        t        | |||dd|t        |xs g       d
      S )u)   no-op(wake=0) PickupResult 편의 생성.FNrE   )r-   PICKUP_SCHEMArF   )r0   r1   r2   r3   r8   r:   s         r*   _failrT   n   s8     )%W]# rC   )gh_probeclocksealed_key_loaderexecutor_keyledger_pathanu_keysc                  |xs d }|xs t         }| rt        j                  j                  |       s t	        t
        t        | xs d      dg      S 	 t        | d      5 }	|	j                         }
ddd       t        j                  
j                  d            }t        |t               st	        t        | d	g      S t        |j#                  d
      xs d      j%                         }|st	        t&        | dg      S t)        j*                  |
      j-                         }t        j                  j/                  |       }t        j                  j1                  || d      }t        j                  j1                  || d      }t        j                  j3                  |      st        j                  j3                  |      rt	        t4        || |dg      S t        j                  j                  |      r	 t        |dd      5 }|D ]  }|j%                         }|s	 t        j                  |      }t        |t               s=|j#                  d      dk(  sR|j#                  d
      |k(  sg|j#                  d      |k(  s|t	        t8        || |dg      c cddd       S  	 ddd       |j#                  d      }t        |t               r/|,|j#                  d      xs |j#                  d      xs d}t;        ||||| |             }|j<                  t>        k(  r6t	        t@        || ||jB                  dgtE        |jF                        z         S |j<                  tH        k(  r6t	        tJ        || ||jB                  dgtE        |jF                        z         S |j<                  tL        tN        fv rDt	        t        || ||jB                  d|j<                   dgtE        |jF                        z         S ||ntP        } |       }|st	        tR        || |dg      S t!        | ||      }|||d <   tU        d3i |}|jV                  s7t	        t        || |tY        |d!d      d"gtE        |jF                        z         S |jZ                  tE        |jZ                        ng }t        j\                  d#d|| |       j_                         d$d%&      }	 t        j`                  t        j                  j/                  |      d'(       t        |d)d      5 }|jc                  |d*z          |je                          t        jf                  |ji                                ddd       t        j\                  tl        d|| |       j_                         d$d%&      }d}d} | d-t        jn                          }!	 t        |!d.d      5 }"|"jc                  |       |"je                          t        jf                  |"ji                                ddd       t        jp                  |!|       |}d1g}#| r|#ju                  |        tw        tl        tx        || |d'|d|#|2
      S # 1 sw Y   xY w# t        t        f$ r }t	        t        | d| g      cY d}~S d}~ww xY w# t        t6        f$ r Y w xY w# 1 sw Y   xY w# t        $ r Y (w xY w# 1 sw Y   txY w# t        $ r#}t	        tj        || |d+| d,g      cY d}~S d}~ww xY w# 1 sw Y   xY w# t        $ r7}	 t        jr                  |!       n# t        $ r Y nw xY wd/| d0} Y d}~)d}~ww xY w)4u  result.json pickup → ANU-owned callback 발사 request(argv) 생성 (순수 함수).

    처리 순서 (fail-closed):
      1. result.json 읽기 / 파싱
      2. task_id 검증 + sha256 계산
      3. terminal-marker no-op (done/acked)
      4. dedupe ledger 중복 확인
      5. collector verify (조건부, gh_probe 주입 시)
      6. sealed-key proof (ANU key 로드)
      7. wake argv 생성 (anu_runner_pickup_and_fire 재사용)
      8. dedupe ledger 기록
      9. done marker 작성
      10. WAKE_BUILT 반환
    c                 H    t        j                  t        j                        S r>   )r   nowr   utcrP   rC   r*   <lambda>zpickup_once.<locals>.<lambda>   s    x||HLL9 rC   r!   u?   result.json 부재 — executor 미작성 또는 경로 오류.)r2   r:   rbNzutf-8u"   result.json 읽기/파싱 실패: u$   result.json 이 object(dict) 아님.r1   uI   result.json task_id 없음/빈값 — 잘못된 argv 차단(fail-closed).z.pickup.donez.pickup.ackedu4   terminal marker 존재 — 이미 처리됨 (no-op).)r1   r2   r3   r:   r)encodingeventr?   r3   u6   dedupe: (task_id, sha256) 이미 기록됨 — wake 0.collector_envelopeschedule_id)r1   envelopeproberX   re   r]   uL   collector verify: QUARANTINED (self-collector) — 작업물 보존, wake 0.rQ   uD   collector verify: PENDING_OWNER_PROOF (재시도 가능) — wake 0.zcollector verify: u    — fail-closed, wake 0.us   ANU sealed key 미로드 — COKACDIR_KEY_ANU 환경변수 미설정 또는 .env.keys 부재. fail-closed (wake 0).)r2   rX   anu_keyrZ   r8   uB   anu_runner_pickup_and_fire FAIL (executor self-key refuse 포함).z+dispatch.anu_result_pickup_runner.dedupe.v1)r/   rc   r1   r3   tsFensure_asciiT)exist_oka
u1   LEDGER_WRITE_FAILED: dedupe ledger 기록 실패(uP   ) — duplicate wake 방지 위해 fail-closed (wake 0). 다음 cycle 재시도.z.tmp-wu/   MARKER_WRITE_FAILED: done marker 기록 실패(u@   ) — ledger dedupe 로 duplicate wake 차단(wake 1회 유지).u   result.json pickup 정상 → ANU-owned callback 발사 argv 생성. 실 발사는 권한 있는 ANU 세션이 수행 (자가발사 0).rE   rP   )=DEFAULT_LEDGER_PATHr$   pathisfilerT   PICKUP_NO_RESULT_JSONr.   openreadjsonloadsdecodeOSError
ValueErrorPICKUP_FAIL
isinstancerI   r&   r(   PICKUP_REJECThashlibr3   	hexdigestdirnamejoinexistsPICKUP_SKIP_TERMINAL	TypeErrorPICKUP_SKIP_DEDUPEr   r0   r   PICKUP_QUARANTINEr8   rF   r:   r   PICKUP_PENDINGr   r   r+   PICKUP_SEALED_KEY_MISSINGr   rB   getattrr7   dumps	isoformatmakedirswriteflushfsyncfilenoPICKUP_LEDGER_WRITE_FAILEDrS   getpidreplaceunlinkappendr-   r?   )$r2   rU   rV   rW   rX   rY   rZ   _clock_ledgerfh	raw_bytesresultexcr1   r3   
result_dir	done_path
acked_pathlfhlineentryrf   re   v_loaderrh   fire_kwargsra   r7   ledger_entrydone_contentdone_path_outmarker_write_failed_reasontmp_pathdfhfinal_reasonss$                                       r*   pickup_oncer      sW   0 :9F00G 277>>2B#C*&)*:*@b&A_`b 	bK"D) 	"R	I	"I$4$4W$=>
 fd#[&6DEG 	G
 &**Y'-2.446G]&6ijl 	l ^^I&002F!12J ZG9L)ABIjWI]*CDJ	ww~~i BGGNN:$>)$7G"TUW 	W 
ww~~g	gsW5 i iD::<D ! $

4 0 #5$/!IIg.2EE!IIi0G;!IIh/69$%7-46F,2.f-g	 i ii iii0 zz./H(D!h&:LL' zz-( 	
 +%#
 99++*!(*: &()(8(8k"!!))_"-. . 9933!(*: &()(8(8c"!!))_"-. . 9924DEE!(*: &()(8(81!))<UV"!!))_"-. . $5#@F`GiG.$&6"C	 	 )!K
 "*J"1[1A44[$&6"$+A/?$D]aii)* 	* 66-4<2D ::?$h  " L
BGGOOG,t<'31 	#SIIlT)*IIKHHSZZ\"	#" ::$h  " L $(M04E"))+/H
(C'2 	#cIIl#IIKHHSZZ\"	# 	

8Y'!	MM "78!)! Q	" 	" Z  K[&6 B3%HIK 	KKL '	2 ! !i i(  		z	# 	#  
 /$&6"LSE Rf f	 	
0	# 	#  

	IIh 		
 >cU CI I 	#

s/  Y:  Y-1,Y: <[ 
[$Z,9[
[[4[	[	[ )[+[ #A[, %A[-[, \( A\ \( -Y72Y: :Z)	Z$Z)$Z),Z?;[>Z??[[[ 	[[[)$[, ,	\5\\\\% \( (	](2]]#	]]#]	]##](c                   dd l }|j                  d      }|j                  dd      }|j                  d      }|j	                  dd	       |j	                  d
d       |j                  |       }|j                  dk(  r_t        |j                  |j                        }t        t        j                  |j                         d             |j                  rdS dS y)Nr   z!dispatch.anu_result_pickup_runner)progcmdT)destrequiredpickupz--result-json-path)r   z--executor-keyr!   )default)rX   Frj      )argparseArgumentParseradd_subparsers
add_parseradd_argument
parse_argsr   r   r2   rX   printrv   r   rG   rB   )r7   r   apsubpurm   ress          r*   mainr   y  s    		 	 &I	 	JB




6C		!BOO(4O8OO$bO1
dAuu
 	djjU;<FFq!!rC   )rS   r?   rs   r{   r   r   r   r   r}   r   r   rp   r'   r-   r   r   __main__)rH   r;   )r0   r.   r1   r.   r2   r.   r3   r.   r8   r.   r:   r6   rH   r-   )r2   r.   rU   zOptional[Callable[[str], dict]]rV   z Optional[Callable[[], datetime]]rW   z%Optional[Callable[[], Optional[str]]]rX   r.   rY   r;   rZ   zOptional[object]rH   r-   r>   )r7   r6   rH   int).rM   
__future__r   r~   rv   r$   dataclassesr   r   r   r   typingr   r	   r
   'dispatch.anu_owned_callback_enforcementr   r   r   r   r   r   r   rS   r?   rs   r{   r   r   r   r   r}   r   r   rq   r   rp   r'   r+   r-   rT   r   r   __all__rJ   
SystemExitrP   rC   r*   <module>r      s    #   	 ( ' + +   7 ! ( & "   &0 2  ggllHh(E 
 !	 
 
 
B +-b")-,/&2>, 15.2?C!%!%tt .t ,	t
 =t t t t tp.& z
TV
 rC   