
    4jN                     X   d Z ddlZddlmc 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ZddlmZ  ee      j%                         j&                  d   Z ee      ej,                  vr"ej,                  j/                  d ee             dedefdZ edd	      Zeej4                  d
<    edd      Zeej4                  d<    edd      Zeej4                  d<    edd      Zej<                  Zej>                  Zej@                  Z ejB                  Z!ejD                  Z"ejF                  Z#ejH                  Z$ejJ                  Z%ejL                  Z&ejN                  Z'ejP                  Z)edz  dz  edz  dz  edz  dz  edz  dz  gZ*edz  dz  Z+edz  dz  dz  Z,edz  dz  Z-dZ.d Z/d!Z0d"Z1 ejd                  e-jg                               ji                         Z5edz  d#z  d$z  Z6edz  d#z  d%z  Z7d&ed'efd(Z8d)ed'efd*Z9 G d+ d,ejt                        Z;e<d-k(  r ejz                  d.       yy)/u  Regression — task-2553+44 dispatch/cron-direct callback guard + durable
4-tuple registry.

Covers §5 verbatim items 1~9, 13~15, 17, 18 + §5/§8/9-R invariants. The
cron-direct (cokacdir --cron) path is now a code-level fail-closed gate, and
a durable append-only 4-tuple ledger makes a consumed normal callback
re-confirmable from a later session (회장 §2.1/§2.3).

9-R.1 Layer A: cron_dispatch_guard / callback_4tuple_registry perform ZERO
cron register/remove (validate + append-only record only). Layer B (the
executor's own normal completion callback, §10) is a designed lifecycle
signal and is asserted preserved, executed 0 here.
    N)Path   modnamerelpathc                     t         j                  j                  | t        |z        }t         j                  j	                  |      }|t
        j                  | <   |j                  j                  |       |S )zEHermetic file-path import (collision-proof vs tests/dispatch shadow).)		importlibutilspec_from_file_location_ROOTmodule_from_specsysmodulesloaderexec_module)r   r   specmods       P/home/jay/workspace/tests/regression/test_callback_4tuple_registry_2553plus44.py_loadr      sU    >>11'57?KD
..
)
)$
/CCKKKKC J    _p44_eccz(dispatch/executor_completion_contract.pyz%dispatch.executor_completion_contract_p44_stvz#dispatch/spec_template_validator.pyz dispatch.spec_template_validator_p44_regz"anu_v3/callback_4tuple_registry.pyzanu_v3.callback_4tuple_registry
_p44_guardzdispatch/cron_dispatch_guard.pydispatchzcron_dispatch_guard.pyanu_v3zcallback_4tuple_registry.pyzartifact_root_resolver.pyzcollector_artifact_lookup.pyutilsz%anu_delegation_completion_callback.pymemoryeventsz#task-2553.parallel-batch-state.jsonzexecutor_completion_contract.py(20456b5f83fc039f2fd6f50f4b94095c29b41bfbz%task/task-2553p1-f1-clean-replacement@83b3e307c8207c76a3e311c408aab4951373bd317896e51687d3007907b0c3d4@fe705d84274e8ae367aaa88c77df763b46bdf4c936efaa1dae78458aedd2a3bcfixturesz-task-2553plus42.normal-callback-consumed.jsonz-task-2553plus43.normal-callback-consumed.jsonpreturnc                 d    t        j                  | j                               j                         S N)hashlibsha256
read_bytes	hexdigest)r#   s    r   _shar+   Y   s     >>!,,.)3355r   argsc                      t        j                  ddt        t              g| ddd      j                  j                         S )Ngit-CT)capture_outputtextcheck)
subprocessrunstrr   stdoutstrip)r,   s    r   _gitr8   ]   s:    >>	c%j(4($d fUUWr   c                       e Zd Zed        ZddZd Zd Zd Zd Z	d Z
d Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)CronDispatchGuardAndRegistryc                     t        j                  t        j                  d            | _        t        j                  t
        j                  d            | _        y )Nutf-8encoding)jsonloadsFX42	read_textfx42FX43fx43)clss    r   
setUpClassz'CronDispatchGuardAndRegistry.setUpClasse   s8    ::dnngn>?::dnngn>?r   c                     t        |ddd      S )NDNF)Callback4Tuple)selftids     r   _good_tuplez(CronDispatchGuardAndRegistry._good_tuplej   s    c3S11r   c                     t        t        t        | j                               }| j	                  |j
                  d       | j                  |j                         y )N	spec_text
entry_pathtuple_PASS)guard_dispatch_MANDATORY_CLAUSEPATH_CRON_DIRECTrO   assertEqualverdict
assertTrueokrM   rs     r   test_01_clause_present_passz8CronDispatchGuardAndRegistry.test_01_clause_present_passn   sD    ''##%

 	F+r   c                     t        dt        | j                               }| j                  |j                  d       | j                  t        d |j                  D                     y )Nu2   executor 는 작업 후 result.json 을 남긴다.rQ   FAILc              3   $   K   | ]  }d |v  
 yw)zclause MISSINGN .0xs     r   	<genexpr>zKCronDispatchGuardAndRegistry.test_02_clause_missing_fail.<locals>.<genexpr>   s     Ea,1E   )rV   rX   rO   rY   rZ   r[   anyreasonsr]   s     r   test_02_clause_missing_failz8CronDispatchGuardAndRegistry.test_02_clause_missing_failx   sO    J'##%

 	F+E199EEFr   c           
          t        t        t        t        ddd d            }| j	                  |j
                  d       | j                  t        d |j                  D                     y )NtrI   rK   rQ   ra   c              3   $   K   | ]  }d |v  
 yw)z normal_collector_cron_id missingNrc   rd   s     r   rg   zUCronDispatchGuardAndRegistry.test_03_missing_normal_collector_fail.<locals>.<genexpr>   s     KA2a7Krh   )	rV   rW   rX   rL   rY   rZ   r[   ri   rj   r]   s     r   %test_03_missing_normal_collector_failzBCronDispatchGuardAndRegistry.test_03_missing_normal_collector_fail   sT    ''!#sD#6

 	F+KKK	
r   c           
      |   t        t        t        t        dddd            }| j	                  |j
                  d       t        t        t        t        dddd      d      }| j	                  |j
                  d	       t        t        t        t        ddd d      d      }| j	                  |j
                  d       y )
Nrm   rI   rJ    rQ   ra   T)rR   rS   rT   no_fallback_contractrU   )rV   rW   rX   rL   rY   rZ   )rM   r_failr_okr_stills       r   4test_04_missing_fallback_fail_or_explicit_nofallbackzQCronDispatchGuardAndRegistry.test_04_missing_fallback_fail_or_explicit_nofallback   s    ''!#sC4

 	0''!#sC4!%	
 	v. ''!#sD"5!%	
 	&1r   c                     d}t        |t        | j                               }| j                  |j                  d       y )Nu   NO-CRON variant (registry/checkpoint cron 0). 그래도 executor 는 완료 직후 normal completion callback 을 반드시 발사한다 (mandatory).rQ   rU   )rV   rX   rO   rY   rZ   )rM   r   r^   s      r   'test_05_no_cron_keeps_executor_callbackzDCronDispatchGuardAndRegistry.test_05_no_cron_keeps_executor_callback   s@     	
 '##%

 	F+r   c                 R   t        t        d| j                               }| j                  |j                  d       | j                  t        d |j                  D                     t        t        t        | j                               }| j                  |j                  d       y )Nlegacy_bot_raw_cokacdirrQ   ra   c              3   $   K   | ]  }d |v  
 yw)bypassNrc   rd   s     r   rg   zPCronDispatchGuardAndRegistry.test_06_unknown_path_bypass_fail.<locals>.<genexpr>   s     =aHM=rh   rU   )	rV   rW   rO   rY   rZ   r[   ri   rj   rX   )rM   r^   rt   s      r    test_06_unknown_path_bypass_failz=CronDispatchGuardAndRegistry.test_06_unknown_path_bypass_fail   s    '0##%

 	F+=199==>''##%

 	v.r   c                 T   t        j                         5 }t        t        |      dz        }|j	                  | j
                  d   d   | j
                  d         }| j                  |t               | j                  || j
                  d   d          d d d        y # 1 sw Y   y xY w)Nledger.jsonlgap_casetask_idchat_idr   expected_chat_id classify_expected_without_ledger)tempfileTemporaryDirectoryCallback4TupleRegistryr   classifyrC   rY   NO_LEDGER_RECORD)rM   dledvs       r   test_07_plus42_gap_reproducedz:CronDispatchGuardAndRegistry.test_07_plus42_gap_reproduced   s    ((* 		a(a>)ABC		*-i8!%9!5  A Q 01499Z()KL		 		 		s   B BB'c                     t        j                         5 }t        t        |      dz        }| j                  d   d   }t        |d   |d   |d   |d   |d   |d	   |d
   |d   d|d   
      }| j                  t        |      g        |j                  |       |j                  |d   |d   |d         }| j                  |t               | j                  t        |j                  |d               d       d d d        y # 1 sw Y   y xY w)Nr   resolved_caseledger_recordr   dispatch_iddispatch_cron_idexecutorr   normal_collector_cron_idfallback_callback_cron_idrole	COMPLETEDts_kst
r   r   r   r   r   r   r   r   statusr   )r   expected_dispatch_idr      )r   r   r   r   rC   make_recordrY   validate_recordappendr   NORMAL_CALLBACK_COMPLETEDlenhistory_for)rM   r   r   rcrecr   s         r   test_08_plus42_fixed_completedz;CronDispatchGuardAndRegistry.test_08_plus42_fixed_completed   s   ((* 	Ea(a>)ABC?+O<B92m3D!#$6!7JI)+,F)G*,-H*IZBxLC _S126JJsO9%'%6!#I  A
 Q 9:SI!?@!D)	E 	E 	Es   C&DDc                    t        j                         5 }t        t        |      dz        }| j                  d   d   }t        |d   |d   |d   |d   |d   |d	   |d
   |d   d|d   
      }|j                  |       | j                  |j                  |d   |d         t               d d d        y # 1 sw Y   y xY w)Nr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   rE   r   r   rY   r   r   )rM   r   r   r   r   s        r   test_09_plus43_fixed_completedz;CronDispatchGuardAndRegistry.test_09_plus43_fixed_completed   s    ((* 	a(a>)ABC?+O<B92m3D!#$6!7JI)+,F)G*,-H*IZBxLC JJsOR	].0m  =)	 	 	s   BB66B?c                    t        j                         5 }t        t        |      dz        }|j	                  t        ddddddddd	
	             | j                  |j                  d      t               | j                  |j                  dd      t               |j                  dddddd      \  }}| j                  |       | j                  |t               d d d        y # 1 sw Y   y xY w)Nr   task-2553+427A4D1633rf   
69370320120B466540FBr   r   	r   r   r   r   r   r   r   r   r   ztask-2553+99)r   ztask-2553+OTHER)r   expected_task_id)r   r   r   r   )r   r   r   r   r   r   rY   r   r   TRACK_MISMATCHvalidate_identityassertFalse)rM   r   r   r\   rF   s        r   test_13_task_id_mismatchz5CronDispatchGuardAndRegistry.test_13_task_id_mismatch   s    ((* 	2a(a>)ABCJJ{&J!+c$z*.Z"  ^46F
 *%6    ++*
-7.24GB R S.1=	2 	2 	2s   C	C''C0c                    t        j                         5 }t        t        |      dz        }|j	                  t        ddddddddd	
	             | j                  |j                  dd      t               d d d        y # 1 sw Y   y xY w)Nr   r   r   rf   r   r   r   r   r   r   DEADBEEF)r   r   	r   r   r   r   r   r   rY   r   r   rM   r   r   s      r   test_14_dispatch_id_mismatchz9CronDispatchGuardAndRegistry.test_14_dispatch_id_mismatch!  s    ((* 	a(a>)ABCJJ{&J!+c$z*.Z"  ^2<  >	 	 	   A"B  B	c                    t        j                         5 }t        t        |      dz        }|j	                  t        ddddddddd	
	             | j                  |j                  dd      t               d d d        y # 1 sw Y   y xY w)Nr   r   r   rf   r   r   r   r   r   r   
9999999999r   r   r   s      r   test_15_chat_id_mismatchz5CronDispatchGuardAndRegistry.test_15_chat_id_mismatch2  s    ((* 	a(a>)ABCJJ{&J!+c$z*.Z"  ^.:  <	 	 	r   c                    t        j                         5 }t        t        |      dz        }t	        dddd      }t        ddddd	ddd
      }t        t        t        |||      }| j                  |j                  d       | j                  |j                         | j                  t        d |j                  D                     | j                  |j!                  d      g        t        ddddd	ddd
d	      }t        t        t        |||      }| j                  |j                  d       | j                  |j                         | j                  |j#                  dd	      t$               d d d        y # 1 sw Y   y xY w)Nr   ztask-2553+44_46DISPNORMr   DIDz
WRONG-DISPanur   r   )r   r   r   r   r   r   r   r   rR   rS   rT   ledgerr   ra   c              3   $   K   | ]  }d |v  
 yw)zledger/4-tuple mismatchNrc   rd   s     r   rg   z`CronDispatchGuardAndRegistry.test_06b_guard_ledger_reconciliation_fail_closed.<locals>.<genexpr>X  s     Jq-2Jrh   r   r   rU   r   )r   r   r   r   rL   r   rV   rW   rX   rY   rZ   r   recorded_to_ledgerr[   ri   rj   r   r   r   )rM   r   r   
good_tuplebad_recr_badok_recrt   s           r   0test_06b_guard_ledger_reconciliation_fail_closedzMCronDispatchGuardAndRegistry.test_06b_guard_ledger_reconciliation_fail_closedD  ss   ((* (	a(a>)ABC'!664J ")u!-$v*.Z	G #+8H!#WE U]]F3U556OOJEMMJJ S__->?D )u!'%$v*.Z"F "+8H!#VD T\\62OOD334%6.:  <)I(	 (	 (	s   EE<<Fc                     G d d      }t        j                         5 }t        t        |      dz        }t	        t
        t        t        dddd      | |             }| j                  |j                  d	       | j                  |j                         | j                  t        d
 |j                  D              |j                         | j                  t        |      dz  j                                d d d        y # 1 sw Y   y xY w)Nc                       e Zd Zd Zy)]CronDispatchGuardAndRegistry.test_06c_guard_validation_unrunnable_fail_closed.<locals>._Bogusc                     i S r&   rc   rM   s    r   identityzfCronDispatchGuardAndRegistry.test_06c_guard_validation_unrunnable_fail_closed.<locals>._Bogus.identitys  s    	r   N)__name__
__module____qualname__r   rc   r   r   _Bogusr   r  s    r   r   r   rm   rI   rJ   rK   r   ra   c              3   $   K   | ]  }d |v  
 yw)zfail-closedNrc   rd   s     r   rg   z`CronDispatchGuardAndRegistry.test_06c_guard_validation_unrunnable_fail_closed.<locals>.<genexpr>  s     :1MQ&:rh   )r   r   r   r   rV   rW   rX   rL   rY   rZ   r   r   r[   ri   rj   exists)rM   r   r   r   r^   s        r   0test_06c_guard_validation_unrunnable_fail_closedzMCronDispatchGuardAndRegistry.test_06c_guard_validation_unrunnable_fail_closedq  s    	 	 ((* 	Ba(a>)ABC+8H%c3S9&(A
 QYY/Q112OO:		::		 d1g6>>@A	B 	B 	Bs   CDD
c                     t        j                  t        j                  t	        t
        dz        dgddt	        t
                    }| j                  |j                  d|j                  dd         y )Nzdispatch.pyz--helpTr0   r1   cwdr   i)	r3   r4   r   
executabler5   r   rY   
returncodestderrr]   s     r   test_17_dispatch_py_smokez6CronDispatchGuardAndRegistry.test_17_dispatch_py_smoke  sU    NN^^S!67BdE

 	q!((45/:r   c                     t        j                  t        j                  ddddgddt	        t
                    }| j                  |j                  d|j                  |j                  z   dd         y )	Nz-mpytestz-qzJtests/regression/test_executor_completion_callback_mandatory_2553plus32.pyTr   r   i$)
r3   r4   r   r   r5   r   rY   r   r6   r   r]   s     r   test_18_plus32_no_regressionz9CronDispatchGuardAndRegistry.test_18_plus32_no_regression  s]    NN^^T8TY[dE


 	q188ahh+>*GHr   c           
      6   t        t        t        | j                               }| j	                  |j
                         | j                  |j                  d       t        t        t        t        dddd            }| j                  |j                  d       y )NrQ   rU   rm   rI   rJ   rq   ra   )	rV   rW   PATH_DISPATCH_PYrO   r   rr   rY   rZ   rL   )rM   r^   r2s      r   test_19_structure_preservedz8CronDispatchGuardAndRegistry.test_19_structure_preserved  s~    '4D##%
 	//0F+ '4D!#sC4
 	V,r   c                     | j                  t        dd      t               | j                  t        ddd      t               y )Nz	rev-parseHEADz--abbrev-ref)rY   r8   GIT_HEAD_PREGIT_BRANCH_PREr   s    r   test_inv_git_head_branch_equalz;CronDispatchGuardAndRegistry.test_inv_git_head_branch_equal  s5    k62LAnf5~	
r   c                     | j                  t        t              t               | j                  t        t              t
               y r&   )rY   r+   FROZEN_ANCHORFROZEN_ANCHOR_SHA
DURABLE_V1DURABLE_V1_SHAr   s    r   (test_inv_frozen_anchor_durable_unmutatedzECronDispatchGuardAndRegistry.test_inv_frozen_anchor_durable_unmutated  s-    m,.?@j)>:r   c                 J    | j                  t        t              t               y r&   )rY   r+   ECCECC_SHAr   s    r   test_inv_ecc_byte0_unmutatedz9CronDispatchGuardAndRegistry.test_inv_ecc_byte0_unmutated  s     	cG,r   c                     t         D ]s  }t        j                  ddt        t              ddt        |j                  t                    gdd      j                  }| j                  |d|j                   d       u y )	Nr.   r/   zls-filesz--error-unmatchT)r0   r1   r   u&    must be git-untracked (§8 invariant))	NEW_MODULESr3   r4   r5   r   relative_tor   assertNotEqualname)rM   mr   s      r   "test_inv_new_modules_git_untrackedz?CronDispatchGuardAndRegistry.test_inv_new_modules_git_untracked  sw     	Ac%j*6GQ]]5)*,#$ j	 
 A!&&!GH	r   c           
          d}t         D ]>  }|j                  d      }|D ]%  }| j                  |||j                   d|d       ' @ y )N)zimport subprocesszsubprocess.runzsubprocess.Popenzsubprocess.callzsubprocess.checkz
os.system(z	os.popen(z.Popen(z"--cronz'--cronz"--cron-removez'--cron-remover<   r=   z* (Layer A) must not execute cron/process (u   ) — 9-R.1)r   rB   assertNotInr   )rM   exec_syntaxr   txttoks        r   $test_inv_layer_a_no_cron_side_effectzACronDispatchGuardAndRegistry.test_inv_layer_a_no_cron_side_effect  sf    
  	A++w+/C"   vvh wk+	r   N)rm   )r   r   r   classmethodrG   rO   r_   rk   ro   rv   rx   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  rc   r   r   r:   r:   d   s    @ @2G	
22,/"
E0(2D"$)ZB*;I-"
;-
	r   r:   __main__)	verbosity)>__doc__builtins@py_builtins_pytest.assertion.rewrite	assertionrewrite
@pytest_arr'   importlib.utilr   r?   r3   r   r   unittestpathlibr   __file__resolveparentsr   r5   pathinsertr   _eccr   _stv_reg_guardrL   rV   rX   r   r   r   r   r   r   r   MANDATORY_CALLBACK_CLAUSErW   r   r   r   r   r   r   r   r   r(   r)   r*   r   rA   rD   r+   r8   TestCaser:   r   mainrc   r   r   <module>r     s        
   X ((+u:SXXHHOOAs5z"3   : 8<3 4Z>?26. /Z=>15- .	|>	?$$&&** ** 44 && :: (( $$22  
J11	H44	H22	H55	 "IIX(+PP
j<<98F  G 
 '..)
*
4
4
6x*$'VVx*$'VV6D 6S 6  p8#4#4 pf zHMMA r   