
    j3                    6   d Z ddlmZ ddlZddlZddl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mZ 	 ddlmZmZ ddlmZmZmZ  G d	 d
e      Zd2dZd3dZd4dZ	 d5	 	 	 	 	 	 	 d6dZ dddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d7dZ!dddddd	 	 	 	 	 	 	 	 	 	 	 	 	 d8dZ"	 	 	 	 	 	 	 	 d9dZ#d:dZ$	 d;	 	 	 	 	 	 	 d<dZ%e&dk(  rddl'Z' e'jP                  d      Z)e)jU                  dg d        e)jU                  d!d"#       e)jU                  d$d%#       e)jU                  d&d#       e)jU                  d'e+d(       e)jU                  d)d#       e)jU                  d*ejX                  j[                  d+d,      #       e)j]                         Z/e/j`                  d-k(  rc e1 ejd                   e!e/jf                  e/jh                  e/jj                  e/jl                  e/jn                  e/jp                  .      d/             ye/j`                  d0k(  r\ e1 ejd                   e"e/jf                  e/jp                  e/jj                  xs de/jl                  e/jn                  1      d/             yddl9Z9 e1 ejd                   e%d e9jr                         dz   e/jl                        d/             yy# e$ rd ej.                  j1                  dej.                  j3                  ej.                  j5                  e                   ddlmZmZ ddlmZmZmZ Y w xY w)=u~  failure_callback_dispatcher.py — task-2712 FAILURE_CALLBACK_BEFORE_EXIT_GUARD.

ANU callback 발사 enforcement (SELF_COLLECTOR_FORBIDDEN) + disk handoff /
supervisor crash marker + D1~D5 bypass defense + count-mismatch 감지.

회장 verbatim doctrine (task-2712 §6.3): 모든 cron 발사는 단일 entry point
`_fire_callback_with_enforcement()` wrapper 만 경유한다. collector_role=ANU +
collector_key/owner_key=ANU_KEY + self_key_used=false 가 아니면 fail-closed.

본 모듈은 §6.1 4-step fallback · §6.3.1 5 checkpoint · §6.3.2 D1~D5 · §6.3.3.B
detect_bypass_via_count_mismatch pseudocode 를 1:1 mirror 한다.
    )annotationsN)datetimetimezone)CallableListOptional   )ANU_KEY_verify_bot_spawn)build_envelopewrite_envelopeemit_stderr_linec                      e Zd ZdZy)CollectorViolationu+   SELF_COLLECTOR_FORBIDDEN 위반 시 발생.N)__name__
__module____qualname____doc__     `/home/jay/workspace/.worktrees/task-2721-dev1/scripts/harness/v36/failure_callback_dispatcher.pyr   r   +   s    5r   r   c                &   | j                  d      dk7  rt        d      | j                  d      t        k7  rt        dt               | j                  d      t        k7  rt        dt               | j                  d      d	urt        d
      y)u   collector_role / collector_key / owner_key / self_key_used strict 검증.

    회장 verbatim §6.3.1 1:1 mirror. ANU key(c119085addb0f8b7) 가 아닌 임의/
    self key 면 CollectorViolation 으로 fail-closed.
    collector_roleANUz/SELF_COLLECTOR_FORBIDDEN: collector_role != ANUcollector_keyz+SELF_COLLECTOR_FORBIDDEN: collector_key != 	owner_keyz'SELF_COLLECTOR_FORBIDDEN: owner_key != self_key_usedFz>SELF_COLLECTOR_FORBIDDEN: self_key_used must be explicit falseN)getr   r
   )envelopes    r   _validate_collector_strictr    0   s     ||$%. !RSS||O$/ #Nwi!XYY||K G+ #J7)!TUU||O$E1 L
 	
 2r   c                 f    t        j                  t        j                        j	                  d      S )Nz%Y-%m-%dT%H:%M:%SZ)r   nowr   utcstrftimer   r   r   _now_isor%   B   s!    <<%../CDDr   c           
     f   t        j                  |d       t        j                  t        j
                        j                  d      }t        j                  | dd      }t        j                  |j                  d            j                         }t         j                  j                  |d| d      }t        |d	d
      5 }t        j                   t#               | j%                  d      | j%                  d      | j%                  d      ||d|dd       ddd       |S # 1 sw Y   |S xY w)uI   §6.3.2 D4 runtime audit log: cron-fire-audit-<ts>.json (stack + sha256).T)exist_okz%Y%m%dT%H%M%S%fF)ensure_ascii	sort_keysutf-8zcron-fire-audit-z.jsonwencodingtask_idterminal_stater   )tsr.   r/   r   sha256caller_stack   )r(   indentN)osmakedirsr   r"   r   r#   r$   jsondumpshashlibr1   encode	hexdigestpathjoinopendumpr%   r   )r   
events_dirr2   r0   payloadshar<   fs           r   _write_auditrD   F   s    KK
T*	hll	#	,	,->	?BjjFG
..0
1
;
;
=C77<<
&6rd%$@AD	dC'	* 
a		j#<<	2"*,,/?"@"*,,/?"@ , 	

 K
 Ks   AD&&D0c                    t        |        dj                  t        j                  d            }|rt	        | ||        ||       S )u   §6.3.1 single entry point. validate → audit 박제 → cron_fn.

    D1: 모든 cron 발사는 본 wrapper 만 경유. D4: audit log 박제 (count mismatch
    감지의 분모). collector strict 위반 시 cron_fn 호출 전에 fail-closed.
        )limit)r    r=   	tracebackformat_stackrD   )r   cron_fnr@   r2   s       r   _fire_callback_with_enforcementrL   ^   s?     x(77911:;LXz<88r   rF   memory/eventsF)failure_kindr@   phase	exit_codeartifact_pathsresidual_pidcritical7_matchc               F    t        | |||||||d	      }	t        |	|d      S )u   BLOCKED / INFRA_DEFECT / API_FAIL 의 disk handoff marker 박제.

    cron 등록 실패 시 (§6.1 step 3) 또는 dispatch.py inner instrumentation
    (§5.2) 에서 호출된다. exactly-one rule 은 write_envelope 가 보장한다.
    "failure_callback_before_exit_guard)rO   rP   rN   rQ   rR   rS   registration_modefailure_handoffmarker_typer   r   )
r.   r/   rN   r@   rO   rP   rQ   rR   rS   r   s
             r   write_handoff_markerr[   n   s;    " !%!'>
H (J<MNNr   isigkill_or_oom)rP   rN   r@   rO   signal_sourcec          	     J    t        | d|||xs dd|      }t        ||d      S )zKCRASH_NO_EXIT_CODE (SIGKILL/OOM/kernel panic/trap) supervisor crash marker.CRASH_NO_EXIT_CODEr\   rU   )rO   rP   rN   rV   summarysupervisor_crashrX   rZ   )r.   rP   rN   r@   rO   r]   r   s          r   write_supervisor_crash_markerrb      s;     !5%5>H (J<NOOr   c                   | d   }t        | |d      }d}d}	 t        | ||       d}|||dS # t        $ r  t        $ r d}t	        || j                  d	d
      d|| j                  dd      | j                  dd            }|j                  dd      j                  d      r?t        || j                  d	d      | j                  dd      d| j                  dd             Y w xY w)u   §6.1 4-step fallback chain.

    1) failure envelope JSON disk 박제 (terminal marker)
    2) ANU cron 발사 시도 (enforcement wrapper 경유)
    3) cron 실패 시 disk handoff marker 박제
    4) exit (caller 가 exit_code 유지)
    r.   failure_enveloperX   not_attemptedN)r@   fired	cron_failr/   INFRA_DEFECTcron_fallbackrO   rF   rP   r	   rN   r@   rO   rP   statusFALLBACK)envelope_writecron_statushandoff)r   rL   r   	Exceptionr[   r   
startswithr   )r   rK   r@   r.   write_resultrn   handoff_results          r   fallback_chainrt      s    y!G!(JDVWL!KN''jQ. '"! +   !-LL)>:(!,,w+ll;2
 h+66zB-r2[!,Wb)s   / B5C'&C'c                h    t        j                   t        j                  j                  | |            S N)globr5   r<   r=   )r@   patterns     r   _globry      s     99RWW\\*g677r   c                H   d}d}g }ddddd}t        |d      D ]  }| t        j                  j                  |      cxk  r|k  s,n /	 t	        |d      5 }t        j                  |      }	ddd       	j                  d      dv so|d	z  }|d
xx   d	z  cc<   |j                  |d
|	j                  d      f        t        |d      D ]T  }| t        j                  j                  |      cxk  r|k  s,n /|d	z  }|dxx   d	z  cc<   |j                  |ddf       V t        |d      D ]T  }| t        j                  j                  |      cxk  r|k  s,n /|d	z  }|dxx   d	z  cc<   |j                  |ddf       V t        |d      D ]T  }| t        j                  j                  |      cxk  r|k  s,n /|d	z  }|dxx   d	z  cc<   |j                  |ddf       V t        |d      D 
cg c]/  }
| t        j                  j                  |
      cxk  r|k  rn n|
1 }}
g }|d	k\  r|d	k\  r|j                  d||d       |j                         D cg c]  \  }}|d	k\  s| }}}t        |      dk\  r|j                  d|d       t        d |D              }|r|d   d	k\  r|j                  ddi       ||z   }|t        |      kD  r|j                  d|t        |      d       |S # 1 sw Y   xY w# t        $ r i }	Y w xY wc c}
w c c}}w )u   §6.3.3.B pseudocode 1:1 mirror. terminal marker class count ↔ audit log
    count window 매칭 mismatch / multi-class concurrent / failure+done concurrent
    violation 을 감지한다.r   )rd   failure_handoff_markersupervisor_crash_markerdonez*.failure-envelope.jsonr*   r,   NrV   )normal_callbackrU   r	   rd   r/   z*.failure-handoff-marker.jsonr{   z*.supervisor-crash-marker.jsonr|   z*.doner}   SUCCESSzcron-fire-audit-*.json:EXACTLY_ONE_TERMINAL_VIOLATION_FAILURE_AND_DONE_CONCURRENT)	violationsuccess_marker_countfailure_marker_countr3   5EXACTLY_ONE_TERMINAL_VIOLATION_MULTI_CLASS_CONCURRENT)r   classesc              3  D   K   | ]  \  }}}|d k(  xr	 |xr |dk7    yw)rd   r   Nr   ).0_clsr0   s       r   	<genexpr>z3detect_bypass_via_count_mismatch.<locals>.<genexpr>  s5      'QR 	!!<b<R9_<'s    r   6EXACTLY_ONE_TERMINAL_VIOLATION_FAILURE_STATE_WITH_DONEAUDIT_LOG_MISSING_FOR_CRON_FIRE)r   total_firesaudit_entries)ry   r5   r<   getmtimer>   r7   loadrp   r   appenditemslenany)window_start
window_endr@   r   r   fire_markersclass_countsr<   rC   r   pr   
violationscnclasses_with_firesfailure_envelope_non_successr   s                     r    detect_bypass_via_count_mismatchr      s    L"##$	L j";< `277++D1?Z?$1 ,Q#yy|H, ||/0 5  %)$/0A50##T+=x||L\?]$^_` j"AB H277++D1?Z? A% 12a72'? FG	H
 j"BC I277++D1?Z? A% 23q83'@$ GH	I
 j(+ ;277++D1?Z? A%  A% vy 9:	; z#;<277++A.<*< 	
M   Jq %9Q%>Y(<(<	
 )5(:(:(<G1Q!GG
!#T-	
 $' '(' $  $V(<(ARS	
 ')==KS''>*!$]!3	
 G, , 2 Hs<   
LK:-L74L!L/L:L	?LLL__main__z%task-2712 failure callback dispatcher)descriptioncommand)ro   crashzverify-bypass)choicesz	--task-idz	task-2712)defaultz--terminal-staterh   z--failure-kindz--exit-code)typer   z--phasez--events-dir FAILURE_CALLBACK_2712_EVENTS_DIRz!/home/jay/workspace/memory/eventsro   rj   )r(   r   )rP   rN   r@   rO   )r   dictreturnNone)r   str)r   r   r@   r   r2   r   r   r   rv   )r   r   rK   Callable[[dict], object]r@   zOptional[str]r   object)r.   r   r/   r   rN   r   r@   r   rO   r   rP   intrQ   zOptional[list]rR   zOptional[int]rS   boolr   r   )r.   r   rP   r   rN   r   r@   r   rO   r   r]   r   r   r   )r   r   rK   r   r@   r   r   r   )r@   r   rx   r   )rM   )r   floatr   r   r@   r   r   z
List[dict]):r   
__future__r   rw   r9   r7   r5   sysrI   r   r   typingr   r   r   terminal_state_classifierr
   r   failure_envelope_writerr   r   r   rp   r<   insertdirnameabspath__file__r   r    r%   rD   rL   r[   rb   rt   ry   r   r   argparseArgumentParserapadd_argumentr   environr   
parse_argsar   printr8   r.   r/   rN   r@   rO   rP   timer   r   r   <module>r      s   #    	 
  ' + +E 6 6

$E2 TX5CP( %%)"&!OOO 	O
 O O O #O  O O 
OD (%PP P 	P
 P P P 
P,..%. . 
	.d8
 ?NVV%*V8;VVr z	 	 	 -T	UBOOI'LOMOOKO5OO&O?OO$bO1OOMQO7OOIrO*OO

.0S
   	AyyIDJJ$II$$!" ||''kk #
	
 
g	DJJ-IIkk!"!C3C ||'' #		
 	DJJ0IDIIK!OQ\\R"	
_ c  HHOOArwwrwwx'@ABD s   J/ /A%LL