
    j@                       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 ejB                  jE                  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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     R/home/jay/workspace/.worktrees/task-2723-dev2/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)r/   PICKUP_WAKE_BUILTselfs    r)   okzPickupResult.okZ   s    ||000    c                $   | j                   | j                  | j                  | j                  | j                  | j
                  | j                  t        | j                        nd | j                  t        | j                        | j                  d
S )N
r.   r/   r0   r1   r2   r4   r6   r7   r9   r;   )r.   r/   r0   r1   r2   r4   r6   listr7   r9   r;   r?   s    r)   to_jsonzPickupResult.to_json^   sl    kk|||| $ 5 5kk//'+yy'<DO$"11DLL)++
 	
rB   )returnr3   )rG   dict)__name__
__module____qualname____doc____annotations__r   rE   r9   r;   propertyrA   rF    rB   r)   r,   r,   K   sa    $KLLK
t4GY4!%K%1 1
rB   r,   r    r0   r1   r2   r7   r9   c               N    t        t        | |||dd|t        |xs g       d
      S )u)   no-op(wake=0) PickupResult 편의 생성.FNrD   )r,   PICKUP_SCHEMArE   )r/   r0   r1   r2   r7   r9   s         r)   _failrS   m   s8     )%W]# rB   )gh_probeclocksealed_key_loaderexecutor_keyledger_pathanu_keysc               L   |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        d/i |}|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\                  tj        d|| |       j_                         d$d%&      }d}| d+t        jl                          } 	 t        | d,d      5 }!|!jc                  |       |!je                          t        jf                  |!ji                                ddd       t        jn                  | |       |}ts        tj        tt        || |d'|dd-g|.
      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   ]xY w# t        $ r Y lw xY w# 1 sw Y   xY w# t        $ r) 	 t        jp                  |        n# t        $ r Y nw xY wY w xY w)0u  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   utcrO   rB   r)   <lambda>zpickup_once.<locals>.<lambda>   s    x||HLL9 rB   r    u?   result.json 부재 — executor 미작성 또는 경로 오류.)r1   r9   rbNzutf-8u"   result.json 읽기/파싱 실패: u$   result.json 이 object(dict) 아님.r0   uI   result.json task_id 없음/빈값 — 잘못된 argv 차단(fail-closed).z.pickup.donez.pickup.ackedu4   terminal marker 존재 — 이미 처리됨 (no-op).)r0   r1   r2   r9   r)encodingeventr>   r2   u6   dedupe: (task_id, sha256) 이미 기록됨 — wake 0.collector_envelopeschedule_id)r0   envelopeproberW   rd   r\   uL   collector verify: QUARANTINED (self-collector) — 작업물 보존, wake 0.rP   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).)r1   rW   anu_keyrY   r7   uB   anu_runner_pickup_and_fire FAIL (executor self-key refuse 포함).z+dispatch.anu_result_pickup_runner.dedupe.v1)r.   rb   r0   r2   tsFensure_asciiT)exist_oka
z.tmp-wu   result.json pickup 정상 → ANU-owned callback 발사 argv 생성. 실 발사는 권한 있는 ANU 세션이 수행 (자가발사 0).rD   rO   );DEFAULT_LEDGER_PATHr#   pathisfilerS   PICKUP_NO_RESULT_JSONr-   openreadjsonloadsdecodeOSError
ValueErrorPICKUP_FAIL
isinstancerH   r%   r'   PICKUP_REJECThashlibr2   	hexdigestdirnamejoinexistsPICKUP_SKIP_TERMINAL	TypeErrorPICKUP_SKIP_DEDUPEr   r/   r   PICKUP_QUARANTINEr7   rE   r9   r   PICKUP_PENDINGr   r   r*   PICKUP_SEALED_KEY_MISSINGr   rA   getattrr6   dumps	isoformatmakedirswriteflushfsyncfilenorR   getpidreplaceunlinkr,   r>   )"r1   rT   rU   rV   rW   rX   rY   _clock_ledgerfh	raw_bytesresultexcr0   r2   
result_dir	done_path
acked_pathlfhlineentryre   rd   v_loaderrg   fire_kwargsr`   r6   ledger_entrydone_contentdone_path_outtmp_pathdfhs"                                     r)   pickup_oncer      s   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 $(ME"))+/H(C'2 	#cIIl#IIKHHSZZ\"	# 	

8Y'! !)Q
 " e	" 	" Z  K[&6 B3%HIK 	KKL '	2 ! !i i(  		z	# 	#  	# 	#  	IIh 		s#  Y#  Y1,Y# <Z8 
Z+$Z9Z+
Z+Z+4Z+	Z+	Z8 )Z++Z8 #A[ %A[-[ [1 A[% [1 Y Y# #Z2ZZZZ($Z+'Z((Z++Z50Z8 8	[[[[ 	["!["%[.*[1 1	\#;\\#	\\#\\#"\#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)rW   Fri      )argparseArgumentParseradd_subparsers
add_parseradd_argument
parse_argsr   r   r1   rW   printru   r   rF   rA   )r6   r   apsubpurl   ress          r)   mainr   e  s    		 	 &I	 	JB




6C		!BOO(4O8OO$bO1
dAuu
 	djjU;<FFq!!rB   )rR   r>   rr   rz   r   r   r   r   r|   r   ro   r&   r,   r   r   __main__)rG   r:   )r/   r-   r0   r-   r1   r-   r2   r-   r7   r-   r9   r5   rG   r,   )r1   r-   rT   zOptional[Callable[[str], dict]]rU   z Optional[Callable[[], datetime]]rV   z%Optional[Callable[[], Optional[str]]]rW   r-   rX   r:   rY   zOptional[object]rG   r,   r=   )r6   r5   rG   int)-rL   
__future__r   r}   ru   r#   dataclassesr   r   r   r   typingr   r	   r
   'dispatch.anu_owned_callback_enforcementr   r   r   r   r   r   r   rR   r>   rr   rz   r   r   r   r   r|   r   rp   r   ro   r&   r*   r,   rS   r   r   __all__rI   
SystemExitrO   rB   r)   <module>r      s    #   	 ( ' + +   7 ! ( & "   &0  ggllHh(E 
 !	 
 
 
B +-b")-,/&2>, 15.2?C!%!%aa .a ,	a
 =a a a a aJ.$ z
TV
 rB   