
    >;#jlN                    ,   d Z ddlmZ ddl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 ddlZ ee      j%                         j&                  d   Z ee      e	j,                  vr"e	j,                  j/                  d ee             edz  dz  Ze	j2                  j5                  d      Ze eedd	      xs d	 ee      k7  r ee	j2                        D  cg c]  } | dk(  s| j=                  d
      s|  c} D ]  Ze	j2                  e=   ej@                  de eedz        g      Z!e!e!jD                  J  ejF                  e!      Z$e$e	j2                  d<   e!jD                  jK                  e$       ddl&m'Z( d3dZ) e)dd        e)dd        e)dd      Z* e)dd      Z+e*jX                  Z-dZ.ddddddddZ/d4dZ0d5dZ1d6d7d Z2d8d!Z3d9d:d"Z4d# Z5d;d<d$Z6d=d<d%Z7d& Z8d>d'Z9d( Z:d) Z;d* Z<d+ Z=d, Z>d- Z?d. Z@d/ ZAd0 ZBd1 ZCd2 ZDyc c} w )?u'  task-2729+7 P0-b pickup activation hardening — regression (10).

대상:
  - dispatch.anu_pickup_driver  : D1(MAX_FILES bounded scan) + D2(legacy cutoff)
  - dispatch.anu_result_pickup_runner : D3(ledger/marker write 실패 fail-closed/관측)

절대 제약 (test_anu_pickup_driver_2721 / test_anu_result_pickup_runner_2720 동일):
  - ANU key literal 'c119085...' 를 테스트 코드에 절대 쓰지 않는다 (완성 literal 0건).
    검증용으로만 분할 조합("c119085" + "addb0f8b7") 사용.
  - pickup_once 실호출은 mock(pickup_fn/verify_fn) 주입 또는 sealed_key_loader fake + gh_probe 미주입.
    실제 wake/cron/spawn 0.
  - canonical memory(/home/jay/workspace/memory/**) 쓰기 0 — tmp_path / tempfile 만.

회장 verbatim 검증 10항목 + 핵심 시나리오 커버.
    )annotationsN)Path   dispatchz__init__.py__file__ z	dispatch.)submodule_search_locations)anu_pickup_driverc                0   | t         j                  v rt         j                  |    S t        j                  | t        |z        }||j
                  J t        j                  |      }|t         j                  | <   |j
                  j                  |       |S )uE   runner 테스트(2720) 의 _load 패턴 — 의존 모듈 실 로드.)sysmodules_iluspec_from_file_location_ROOTloadermodule_from_specexec_module)modnamerelpathspecmods       ?tests/regression/test_anu_pickup_activation_hardening_2729p7.py_loadr   6   s}    #++{{7##''AD 777



%CCKKKKC J    z dispatch.callback_owner_enforcerz#dispatch/callback_owner_enforcer.pyz(dispatch.normal_fallback_callback_helperz+dispatch/normal_fallback_callback_helper.pyz'dispatch.anu_owned_callback_enforcementz*dispatch/anu_owned_callback_enforcement.pyz!dispatch.anu_result_pickup_runnerz$dispatch/anu_result_pickup_runner.py7943afbe12c12f7dtask-999EXECUTOR_RESULT_WRITTENsch-1task_idschedule_idzr.mdabc)r    completion_signalcollector_envelopereport_pathsha256c                j    | dz  dz  j                  dd       | dz  dz  j                  dd       | S )NmemoryeventsTparentsexist_okstate)mkdir)tmp_paths    r   
_make_dirsr0   \   sA    8#**4$*G7"))$)FOr   c                    | dz  dz  S )Nr(   r)    )roots    r   _events_dirr4   b   s    (?X%%r   c                ~    t        |       |z  }|t        }|j                  t        j                  |      d       |S )Nutf-8encoding)r4   VALID_PAYLOAD
write_textjsondumps)r3   namepayloadps       r   _write_resultr@   f   s9    DD ALLG$wL7Hr   c                    | dz  dz  dz  }|j                   j                  dd       |j                  t        j                  dz   d       y )	Nr(   r-   p0b_driver_enabledTr*   
r6   r7   )parentr.   r:   drvACTIVATION_ENABLED)r3   flags     r   _enable_activationrH   n   sH    (?W$';;DKKdT2OOC**T1GODr   c                t    t        j                         |z
  }t        j                  t	        |       ||f       y)u[   mtime/atime 을 과거로 설정 — readiness aged 게이트 통과 + legacy mtime 모사.N)_timetimeosutimestr)pathsecondspasts      r   _agerR   t   s(    ::<'!DHHSYt%r   c                      y Nr2   aks     r   <lambda>rX   z       r   c                (     g  fd}|_         |S )u?   pickup_fn mock — 호출 인자 calls 기록, 실 wake/cron 0.c                 f    j                  | |f       t        j                  dk(  dgdg       S )N
WAKE_BUILTxr   )verdictokargvr    reasonsappendtypesSimpleNamespaceargskwargscallsr^   s     r   _pickupz!make_pickup_mock.<locals>._pickup   s<    dF^$$$<'
 	
r   ri   )r^   rj   ri   s   ` @r   make_pickup_mockrl   }   s    E
 GMNr   c                (     g  fd}|_         |S )Nc                 b    j                  | |f       t        j                  dk(  dg       S )NAUTHORITATIVEr   )r^   r_   classificationra   rb   rf   s     r   _verifyz!make_verify_mock.<locals>._verify   s7    dF^$$$?*	
 	
r   rk   )r^   rq   ri   s   ` @r   make_verify_mockrr      s    E
 GMNr   c                     t         S )uC   ANU key fake 로더 — literal 노출 없이 모듈 상수 반환.)_ANU_KEYr2   r   r   _sealed_key_loaderru      s    Or   c                    |ddd}t         j                  j                  | | d      }t        |dd      5 }t	        j
                  ||d	       d
d
d
       |S # 1 sw Y   |S xY w)uJ   runner 용 정상 result.json (collector_envelope 없음 → verify skip).donedeadbeef)r    summaryr&   .result.jsonwr6   r7   F)ensure_asciiN)rL   rO   joinopenr;   dump)
result_dirr    r>   rO   fhs        r   _write_runner_resultr      sa    !f
KG77<<
wi|$<=D	dC'	* 3b		'2E23K3Ks   AA%c           	     z   t        |       }t        |       t               }t               }t	        |      }t        |d       t        j                         }t        j                  t        |      |||d|t              }|j                  t        j                  k(  sJ |j                  dk(  sJ |j                  du sJ t!        |j"                        dk(  sJ t!        |j"                        dk(  sJ |j%                         sJ |dz  d	z  d
z  j%                         rJ |dz  d	z  dz  j%                         rJ y)u   activation 활성 + epoch=now, result mtime 이 epoch 보다 과거(10s 전) →
    NOOP_LEGACY_SKIP("pre_activation_epoch"). pickup/verify 미호출, 파일 잔류,
    quarantine/processed 디렉토리 미생성.
   rP   Tr3   	pickup_fn	verify_fnlegacy_cutoffactivation_epochsleep_fnpre_activation_epochFr   r(   	p0b_state
quarantine	processedN)r0   rH   rl   rr   r@   rR   rJ   rK   rE   process_onerN   	_NO_SLEEPr^   VERDICT_NOOP_LEGACY_SKIPquarantine_reasonquarantinedlenri   existsr/   r3   pickupverifyr?   epochrecs          r   test_legacy_skip_before_epochr      s)    hDtFFdABJJLE
//ATFU	C ;;#66666  $::::??e###v||!!!v||!!!88::x+-<DDFFFx+-;CCEEEEr   c           	        t        |       }t        |       t        d      }t        d      }t	        |      }t        |d       t        j                         dz
  }t        j                  t        |      |||d|t              }|j                  t        j                  k(  sJ t        |j                        d	k(  sJ y
)u   epoch 을 충분히 과거(now-100s)로 두고 파일은 aged(now-10s) → mtime >= epoch.
    legacy_cutoff=True 라도 정상 decision path 진입 → WAKE_BUILT, pickup 1회.r\   r^   ro   r   r   d   Tr      N)r0   rH   rl   rr   r@   rR   rJ   rK   rE   r   rN   r   r^   VERDICT_WAKE_BUILTr   ri   r   s          r   test_post_epoch_proceeds_waker      s     hDtl3Fo6FdABJJL3E
//ATFU	C ;;#00000v||!!!r   c           	        t        |       }t        |       t               }t               }t	        |      }t        |d       t        j                  t        |      |||ddt              }|j                  t        j                  k(  sJ |j                  dk(  sJ t        |j                        dk(  sJ t        |j                        dk(  sJ |j                         sJ y)u   legacy_cutoff=True + activation_epoch=None → NOOP_LEGACY_SKIP("epoch_absent").
    fail-open 금지 입증 — pickup 미호출.r   r   TNr   epoch_absentr   )r0   rH   rl   rr   r@   rR   rE   r   rN   r   r^   r   r   r   ri   r   r/   r3   r   r   r?   r   s         r   test_epoch_absent_fail_closedr      s     hDtFFdAB
//ATFT	C ;;#66666  N222v||!!!v||!!!88::r   c                   t        |       }|dz  dz  dz  }d}|j                  t        |      d       t        j                  t        |            t        j                  |      k(  sJ |j                  dd       t        j                  t        |            J |j                          t        j                  t        |            J t        j                  t        |      d	 
      t        j                  d      k(  sJ y)u   epoch 마커(memory/state/p0b_activation_epoch) str(float) → float 반환.
    부재 → None. invalid("abc") → None. epoch_reader 주입 → 파싱값.r(   r-   p0b_activation_epochg   2Ar6   r7   r"   Nc                      y)Nz123.5r2   r2   r   r   rX   z2test_read_activation_epoch_parse.<locals>.<lambda>  rY   r   )epoch_readerg     ^@)r0   r:   rN   rE   read_activation_epochpytestapproxunlink)r/   r3   
epoch_pathvals       r    test_read_activation_epoch_parser      s     hD7*-CCJ C#c(W5$$SY/6==3EEEE %'2$$SY/777 $$SY/777 $$SY_MQWQ^Q^_dQeeeer   c                P   t        |       }t        |       t        d      }t        d      }t	        |      }t        |d       t        j                  t        |      |||t              }|j                  t        j                  k(  sJ t        |j                        dk(  sJ y)	u]   legacy_cutoff 기본 False(미지정) → 기존 동작(WAKE_BUILT) 유지. 회귀 무영향.r\   r   ro   r   r   )r3   r   r   r   r   N)r0   rH   rl   rr   r@   rR   rE   r   rN   r   r^   r   r   ri   r   s         r   !test_legacy_cutoff_off_unaffectedr     s    hDtl3Fo6FdAB
//ATFC
 ;;#00000v||!!!r   c           	        t        |       }t        |       t        d      }t        d      }g }t	        d      D ]]  }t        t              }d| |d<   d| dd|d	<   t        |d| d
|      }t        |d       |j                  t        |             _ t        j                  ||d||dt              }|D 	cg c]"  }	|	j                  t        j                  k(  s!|	$ }
}	|D 	cg c]"  }	|	j                  t        j                  k7  s!|	$ }}	t!        |
      dk(  sJ |
d   j"                  dk(  sJ t!        |      dk(  sJ yc c}	w c c}	w )u   result 60개 + max_files=50 → process_one 50건 처리 + defer record 정확히 1건
    (quarantine_reason=="max_files_defer:10"). legacy_cutoff 미지정 → 정상 경로.r\   r   ro   <   task-r    r   r   r$   rz   r=   r>   r   r   2   Fpaths	max_filesr   r   write_evidencer   r   r   zmax_files_defer:10N)r0   rH   rl   rr   rangedictr9   r@   rR   rc   rN   rE   	scan_oncer   r^   VERDICT_NOOP_MAX_FILES_DEFERr   r   )r/   r3   r   r   r   ir>   r?   recordsrdeferr   s               r   test_max_files_boundedr   +  sT    hDtl3Fo6FE2Y }%$QC[	6;A3KPW(X$%$uQC|%<gNQSV mmEFy	G  Q11990P0P#PQQEQ#UqqyyC4T4T'TUIUu:??8%%)====y>R	 RUs    "E#E-"EEc           	        t        |       }t        |       t        d      }t        d      }g }t	        d      D ]]  }t        t              }d| |d<   d| dd|d	<   t        |d| d
|      }t        |d       |j                  t        |             _ t        j                  ||d||dt              }|D 	cg c]"  }	|	j                  t        j                  k(  s!|	$ }
}	t!        |
      dk(  sJ yc c}	w )u1   파일 3개 + max_files=50 → defer record 0건.r\   r   ro      r   r    r   r   r$   rz   r   r   r   r   Fr   r   N)r0   rH   rl   rr   r   r   r9   r@   rR   rc   rN   rE   r   r   r^   r   r   )r/   r3   r   r   r   r   r>   r?   r   r   r   s              r   #test_max_files_under_limit_no_deferr   J  s    hDtl3Fo6FE1X }%$QC[	6;A3KPW(X$%$uQC|%<gNQSV mmEFy	G  Q11990P0P#PQQEQu:?? Rs    "C:#C:c                   t        j                  dt        |             }t        j                  j                  t        |       d      }t        |d      }d }|j                  t        j                  d|       t        j                  |t        d |      }|j                  t        j                  k(  sJ |j                  d	u sJ |j                  J t        d |j                   D              sJ y
)u   정상 WAKE_BUILT 직전까지 진행 + ledger write(Step8 os.makedirs) 만 실패시킴 →
    PICKUP_LEDGER_WRITE_FAILED, wake_built False, argv None, reasons 에 LEDGER_WRITE_FAILED.zt2729p7-led-prefixdirzledger_led.jsonlztask-2729ledc                     t        d      )Nz!simulated ledger makedirs failureOSErrorrU   s     r   boomz2test_ledger_write_failed_fail_closed.<locals>.boomn  s    9::r   makedirsc                 "    t         j                  S rT   M_enfANU_KEYr2   r   r   rX   z6test_ledger_write_failed_fail_closed.<locals>.<lambda>v  
    %-- r   executor_keysealed_key_loaderledger_pathFNc              3  $   K   | ]  }d |v  
 yw)LEDGER_WRITE_FAILEDNr2   .0r   s     r   	<genexpr>z7test_ledger_write_failed_fail_closed.<locals>.<genexpr>|       ?a$)?   )tempfilemkdtemprN   rL   rO   r}   r   setattrMpickup_once_DEV_KEYr^   PICKUP_LEDGER_WRITE_FAILED
wake_builtr`   anyra   )r/   monkeypatchrdirledgerrO   r   ress          r   $test_ledger_write_failed_fail_closedr   g  s     >s8}EDWW\\#h-);<Fn5D; j$/
--/	  C ;;!66666>>U"""88?3;;????r   c                   t        j                  dt        |             }t        j                  j                  t        |       d      }t        |d      }d }|j                  t        j                  d|       t        j                  |t        d |      }|j                  t        j                  k(  sJ |j                  d	u sJ |j                  J t        d |j                   D              sJ |j#                          t        j                  |t        d |      }|j                  t        j$                  k(  sJ |j                  du sJ y
)u   ledger 정상 + done marker(os.replace) 만 실패 → PICKUP_WAKE_BUILT, wake_built True,
    marker_path None, reasons 에 MARKER_WRITE_FAILED. ledger 기록됨 → 2회차 SKIP_DEDUPE.zt2729p7-mrk-r   zledger_mrk.jsonlztask-2729mrkc                     t        d      )Nz#simulated marker os.replace failurer   rU   s     r   boom_oserrorz8test_marker_write_failed_wake_kept.<locals>.boom_oserror  s    ;<<r   replacec                 "    t         j                  S rT   r   r2   r   r   rX   z4test_marker_write_failed_wake_kept.<locals>.<lambda>  r   r   r   TNc              3  $   K   | ]  }d |v  
 yw)MARKER_WRITE_FAILEDNr2   r   s     r   r   z5test_marker_write_failed_wake_kept.<locals>.<genexpr>  r   r   c                 "    t         j                  S rT   r   r2   r   r   rX   z4test_marker_write_failed_wake_kept.<locals>.<lambda>  r   r   F)r   r   rN   rL   rO   r}   r   r   r   r   r   r^   PICKUP_WAKE_BUILTr   marker_pathr   ra   undoPICKUP_SKIP_DEDUPE)r/   r   r   r   rO   r   r   res2s           r   "test_marker_write_failed_wake_keptr     s(    >s8}EDWW\\#h-);<Fn5D= i6
--/	  C ;;!----->>T!!!??"""?3;;???? ==/	  D <<1/////??e###r   c           
        t        |       }t        |       t        d      }t        d      }d}t	        |      D ]C  }t        t              }d| |d<   d| dd|d	<   t        |d| d
|      }t        |d       E t        j                         }t        j                  |d|d||dt              }	|	D 
cg c]"  }
|
j                  t        j                  k(  s!|
$ }}
t!        |      dk(  sJ |	D 
cg c]"  }
|
j                  t        j                  k7  s!|
$ }}
t!        |      |k(  sJ t#        d |D              sJ t#        d |D              sJ t!        |j$                        dk(  sJ t!        |j$                        dk(  sJ t'        j&                  t)        t+        |      dz              }t!        |      |k(  sJ |dz  dz  dz  j-                         rJ |dz  dz  dz  j-                         rJ yc c}
w c c}
w )u  isolated tmp root 에 126개 legacy result.json(terminal marker 0, 고유 task_id,
    모두 aged mtime). activation 활성, epoch=now → 모든 파일 mtime < epoch.
    scan_once(legacy_cutoff=True, max_files=200):
      - 모든 처리 record verdict == NOOP_LEGACY_SKIP (126/126)
      - pickup_fn/verify_fn 호출 0
      - canonical delta 0: events 126 파일 잔류, quarantine 미생성, processed 미생성
      - max_files=200 → defer record 없음 (순수 legacy skip).r\   r   ro   ~   ztask-legacy-r    r   r   r$   rz   r      r   T   F)r   r   r   r   r   r   r   r   c              3  V   K   | ]!  }|j                   t        j                  k(   # y wrT   )r^   rE   r   r   s     r   r   zDtest_126_legacy_isolated_sim_canonical_delta_zero.<locals>.<genexpr>  s     LQqyyC888Ls   ')c              3  :   K   | ]  }|j                   d k(    yw)r   N)r   r   s     r   r   zDtest_126_legacy_isolated_sim_canonical_delta_zero.<locals>.<genexpr>  s     Pq""&<<Ps   ztask-*.result.jsonr(   r   r   r   N)r0   rH   rl   rr   r   r   r9   r@   rR   rJ   rK   rE   r   r   r^   r   r   allri   globrN   r4   r   )r/   r3   r   r   Nr   r>   r?   r   r   r   r   r   	remainings                 r   1test_126_legacy_isolated_sim_canonical_delta_zeror    s    hDtl3Fo6FA1X }%+A3/	6B1#4FW^(_$%$|A3l%CWUQ JJLEmmUFyG  Q11990P0P#PQQEQu:?? $UqqyyC4T4T'TUIUy>QL)LLLLPiPPPP v||!!!v||!!! 		#k$/2FFGHIy>Qx+-<DDFFFx+-;CCEEEE# R Vs   ;"G>G>8"HHc                 r    t        t              j                  d      } d}| j                  |      dk(  sJ y)u;   이 테스트 파일 소스에 완성 ANU key literal 0건.r6   r7   c119085addb0f8b7r   N)r   r   	read_textcount)src	forbiddens     r   $test_no_anu_key_literal_in_this_filer    s5    
x.
"
"G
"
4C'I99Y1$$$r   )r   rN   r   rN   )r/   r   returnr   )r3   r   r  r   )ztask-999.result.jsonN)r3   r   r=   rN   r  r   )r3   r   r  None)g      $@)rP   floatr  r  )r\   )r^   rN   )ro   )r   rN   r    rN   r  rN   )E__doc__
__future__r   r  importlib.utilutilr   r;   rL   r   r   rK   rJ   rd   pathlibr   r   r   resolver+   r   rN   rO   insert
_real_initr   get_cachedgetattrlist
startswith_kr   _specr   r   _pkgr   r   r
   rE   r   r   r   r   rt   r   r9   r0   r4   r@   rH   rR   r   rl   rr   ru   r   r   r   r   r   r   r   r   r   r   r  r  )rW   s   0r   <module>r#     sK   #    	 
      	X ((+u:SXXHHOOAs5z" Z-/

++//*
%
?ww
B7=2#j/Qs{{+\QqJ!,,{B[q\ KKO(D((JC
@R<S;TE !999 4  'D"CKK
	LLT" -	 (*O P 0357:	<	
-
02 == 2&0I&E& !	$"
F>",0f.", >:@0 $L1Fn%g ]s   H:H