
    +jf                    N   d Z ddlm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ZddlZddlmZmZ ddlmZ  ee      j1                         j2                  d   Z ee      ej8                  vr"ej8                  j;                  d ee             ddlmZ  edz  dz  Z!ejD                  jG                  d      Z$e$ e%e$d	d
      xs d
 ee!      k7  r e&ejD                        D  cg c]  } | dk(  s| jO                  d      s|  c} D ]  Z(ejD                  e(=   e jR                  de! eedz        g      Z*g Z+dZ,e*e,uZ-e-Z.e-re*j^                  Z0dZ1e0e1uZ2e2Z.e.sB ejf                  de-fde*e,f      d ejh                         v s ejj                  e*      r ejl                  e*      nd ejl                  e,      dz  Z7dde7iz  Z8e+js                  e8       e-r ejf                  de2fde0e1f      d ejh                         v s ejj                  e*      r ejl                  e*      nd ejl                  e0       ejl                  e1      dz  Z:dde:iz  Z;e+js                  e;        ejx                  e+d      i z  Z=dde=iz  Z> e? ej                  e>            dxZ.xZ+xZ-xZ,xZ0xZ2Z1 e j                  e*      ZBeBejD                  d<   e*j^                  j                  eB       ddlDmEZF ddlDmGZH edz  dz  dz  ZIedz  dz  dz  ZJedz  d z  ZKd! ZLd" ZMd#d$d#d%d&d'd(d)ZNdEd*ZOdEd+ZPdFd,ZQdFd-ZRdGdHd.ZSdIdJd/ZTdKd0ZUdLd1ZV G d2 d3      ZW G d4 d5ej                        ZY G d6 d7ej                        ZZ G d8 d9ej                        Z[ G d: d;ej                        Z\ G d< d=ej                        Z] G d> d?ej                        Z^ G d@ dAej                        Z_ G dB dCej                        Z`eadDk(  r ej                          yyc c} w )Mu3  task-2733 — P0B_MINIMUM event strategy 보정(전용 inbox) 회귀.

회장 재정의 범위(P0B_MINIMUM) 내 event strategy 결함 수정 검증:
  ① systemd anu-pickup.path 가 전용 inbox(memory/events/p0b_inbox/task-*.result.json)만
     watch 하고 memory/events 직속 legacy 를 watch 하지 않는다(잔존 폭주 0, 설계 검증).
  ② driver scan 기본 glob 이 inbox 만 대상으로 한다(INBOX_DIR_REL).
  ③ memory/events 직속 legacy result.json 은 scan 후에도 byte-identical 무변경
     (이동/삭제 0 — ANCHOR-2).
  ④ 처리(CLOSEOUT_DONE) 후 result.json 이 inbox 밖(processed)으로 이동 → inbox 의
     *.result.json 0건(재트리거 0 — 설계 검증).
  ⑤ reporting path(task-2732) 재사용: driver record → PASS/HOLD/CALLBACK_MISSING.
  ⑥ launcher_fn=None 기본(wake/real launch 0) 회귀 · ANU key literal 0.

네트워크 0, 전부 isolated tmp root + fake sender/mock. canary(실제 inbox 작성)·systemd
설치·merge 는 회장 승인 전 금지 — 본 테스트는 설계/dry-run 만 검증한다.
    )annotationsN)datetimetimezone)Path   dispatchz__init__.py__file__ z	dispatch.)submodule_search_locationsis not)z%(py2)s is not %(py5)s_spec)py2py5z%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16zassert %(py19)spy19)anu_pickup_driver)anu_pickup_reporterdeploysystemdzanu-pickup.pathzanu-pickup.servicedocszp0b_driver_runbook_260601.mdc            	     B    t        ddddddt        j                        S )Ni        r   )tzinfo)r   r   utc     7/home/jay/workspace/tests/test_anu_pickup_inbox_2733.py<lambda>r$   =   s    $2q!Qx||D r"   c                      y Nr!   )aks     r#   r$   r$   >   s    r"   task-999EXECUTOR_RESULT_WRITTENzsch-1)task_idschedule_idzr.mddeadbeefcafe0000)r+   completion_signalcollector_envelopereport_pathsha256c                F    t         j                  j                  | ddd      S )Nmemoryevents	p0b_inboxospathjoinroots    r#   _inboxr<   J   s    77<<h+>>r"   c                D    t         j                  j                  | dd      S )Nr3   r4   r6   r:   s    r#   _eventsr>   N   s    77<<h11r"   c                    t        j                  t        |       d       t        j                  t         j                  j	                  | dd      d       y )NTexist_okr3   state)r7   makedirsr<   r8   r9   r:   s    r#   
_make_dirsrD   R   s3    KKtt,KKT8W5Er"   c                    t         j                  j                  | ddd      }t        |dd      5 }|j	                  d       d d d        y # 1 sw Y   y xY w)Nr3   rB   p0b_driver_enabledwutf-8encodingzenabled
)r7   r8   r9   openwrite)r;   flagfhs      r#   _enablerO   W   sJ    77<<h1EFD	dC'	* b
  s   AAc                    t        j                  | d       t         j                  j                  | |      }t	        |dd      5 }t        j                  |t        n||       d d d        |S # 1 sw Y   |S xY w)NTr@   rG   rH   rI   )r7   rC   r8   r9   rK   jsondumpVALID_PAYLOAD)dir_pathnamepayloadprN   s        r#   _writerX   ]   sc    KK4(
Xt$A	aw	' E2		7?-DEHEHs   A//A9c                j    t               j                         |z
  }t        j                  | ||f       y r&   )_CLOCK	timestampr7   utime)r8   secondspasts      r#   _ager_   e   s+     8')DHHTD$< r"   c                (     g  fd}|_         |S )Nc                 `    j                  | |f       t        j                  ddgdg       S )NTxr)   )verdictokargvr+   reasons)appendtypesSimpleNamespace)r'   r(   callsrc   s     r#   _pz_pickup_mock.<locals>._pr   s3    aV$$C5*b
 	
r"   )rj   )rc   rk   rj   s   ` @r#   _pickup_mockrl   o   s    E
 BHIr"   c                      fd}|S )Nc                 6    t        j                  ddg       S )NTr
   )rc   rd   classificationrf   )rh   ri   )r'   r(   rc   s     r#   _vz_verify_mock.<locals>._v}   s    $$WbZ\]]r"   r!   )rc   rp   s   ` r#   _verify_mockrq   |   s    ^ Ir"   c                      e Zd ZddZd Zy)_FakeSenderc                     || _         g | _        y r&   )rd   rj   )selfrd   s     r#   __init__z_FakeSender.__init__   s    
r"   c                    	 t        |dd      5 }|j                         }d d d        | j                  j	                  |f       | j
                  S # 1 sw Y   2xY w# t        $ r d}Y Bw xY w)NrrH   rI   r
   )rK   readOSErrorrj   rg   rd   )ru   	file_pathrN   contentss       r#   __call__z_FakeSender.__call__   sj    	iw7 %2779% 	

9h/0ww% % 	H	s'   A AA AA A,+A,N)T)__name__
__module____qualname__rv   r}   r!   r"   r#   rs   rs      s    r"   rs   c                      e Zd Zd Zy)TestSystemdPathInboxOnlyc                   t         j                  d      }|j                         D cg c]1  }|j                         j	                  d      r|j                         3 }}| j                  |dgd       | j                  d|       y c c}w )NrH   rI   PathExistsGlob=FPathExistsGlob=%h/workspace/memory/events/p0b_inbox/task-*.result.jsonuT   anu-pickup.path 의 활성 PathExistsGlob 은 전용 inbox 하나뿐이어야 한다<PathExistsGlob=%h/workspace/memory/events/task-*.result.json
_PATH_FILE	read_text
splitlinesstrip
startswithassertEqualassertNotInru   contentln
directivess       r#   !test_path_watches_inbox_glob_onlyz:TestSystemdPathInboxOnly.test_path_watches_inbox_glob_only   s    &&&8 ")!3!3!5
xxz$$%67 HHJ

 
 	UVb	
 	J	

   6BN)r~   r   r   r   r!   r"   r#   r   r      s    
r"   r   c                      e Zd Zd Zd Zy)TestScanGlobsInboxOnlyc                   | j                  t        j                  d       | j                  t        j                  d       | j	                  t        j                  j                  d             | j                  t        j                  j                  d             | j                  t        j                  j                  d             y )Nmemory/events/p0b_inboxzmemory/eventszmemory/events/)	r   drvINBOX_DIR_RELEVENTS_DIR_REL
assertTruer   assertFalseQUARANTINE_DIR_RELPROCESSED_DIR_REL)ru   s    r#   test_inbox_dir_constantz.TestScanGlobsInboxOnly.test_inbox_dir_constant   s    **,EF++_=))445EFG//::?KL..99/JKr"   c           	        t        j                         5 }t        |       t        |       t	        t        |      d      }t        |       t	        t        |      d      }t        |       t        j                  |t        d      t               dt        t              }|D cg c]  }|j                  s| }}| j                  t!        |      d       | j#                  |d   j                  j%                  t&        j(                  j+                  dd                   | j-                  d	d
j+                  d |D                     d d d        y c c}w # 1 sw Y   y xY w)Ntask-999.result.jsonztask-legacy-1.result.jsonCLOSEOUT_DONEF	pickup_fn	verify_fnwrite_evidenceclocksleep_fnr   r   r5   ztask-legacy-1 c              3  4   K   | ]  }|j                     y wr&   )result_path).0rx   s     r#   	<genexpr>zTTestScanGlobsInboxOnly.test_scan_default_targets_inbox_not_legacy.<locals>.<genexpr>   s     818s   )tempfileTemporaryDirectoryrD   rO   rX   r<   r_   r>   r   	scan_oncerl   rq   rZ   	_NO_SLEEPr   r   lenr   endswithr7   r8   r9   r   )ru   tdinbox_plegacy_precordsrx   scanneds          r#   *test_scan_default_targets_inbox_not_legacyzATestScanGlobsInboxOnly.test_scan_default_targets_inbox_not_legacy   s   ((* 	brNBKVBZ)?@GMgbk+FGHNmm&7&.$"G #*;QQ]]q;G;S\1-OOGAJ22;;[*@AC D888-	 	" <#	 	s%   BE$E6E:BEEE!N)r~   r   r   r   r   r!   r"   r#   r   r      s    Lr"   r   c                      e Zd Zd Zy)TestLegacyUntouchedc                   t        j                         5 }t        |       t        |       i }t	        d      D ]Z  }t        t              }d| |d<   t        t        |      d| d|      }t        |       t        |      j                         ||<   \ t        t        j                  t        |                  }t        j                   |t#        d      t%               dt&        t(               | j+                  t        t        j                  t        |                  |       |j-                         D ]d  \  }}| j/                  t        j0                  j3                  |      d|        | j+                  t        |      j                         |d	|        f | j5                  t        j0                  j3                  t        j0                  j7                  |d
dd                   | j5                  t        j0                  j3                  t        j0                  j7                  |d
dd                   d d d        y # 1 sw Y   y xY w)N   ztask-legacy-r+   z.result.jsonr   Fr   u   legacy 삭제됨: u   legacy 변형됨: r3   	p0b_state	processed
quarantine)r   r   rD   rO   rangedictrS   rX   r>   r_   r   
read_bytessortedr7   listdirr   r   rl   rq   rZ   r   r   itemsr   r8   existsr   r9   )ru   r   legacyirV   rW   beforer   s           r#   ,test_legacy_events_byte_identical_after_scanz@TestLegacyUntouched.test_legacy_events_byte_identical_after_scan   s   ((* 	dbrNBKF2Y 1}-'3A3%7	"72;,qc(FPQ G..0q	1 BJJwr{34FMM&7&.$" VBJJwr{$;<fE$lln Z
7q 15Gs3KL  a!3!3!5wBTUVTW@XYZ RWW^^BGGLLX{T_,`abRWW^^BGGLLX{T`,abc;	d 	d 	ds   H&IIN)r~   r   r   r   r!   r"   r#   r   r      s    dr"   r   c                      e Zd Zd Zd Zy)TestInboxEmptiedNoRetriggerc           
        t        j                         5 }t        |       t        |       t	        t        |      d      }t        |       t        j                  |t        d      t               dt        t              }| j                  |d   j                  t        j                         t!        j"                  t$        j&                  j)                  t        |      d            }| j                  |g d|        t!        j"                  t$        j&                  j)                  |dd	d
d            }| j                  t+        |      d       d d d        y # 1 sw Y   y xY w)Nr   r   Fr   r   z*.result.jsonu   inbox 에 result.json 잔존: r3   r   r   ztask-999.result.json*r   )r   r   rD   rO   rX   r<   r_   r   r   rl   rq   rZ   r   r   rc   VERDICT_CLOSEOUT_DONE_globglobr7   r8   r9   r   )ru   r   rW   r   	remainingr   s         r#   *test_inbox_no_result_json_after_processingzFTestInboxEmptiedNoRetrigger.test_inbox_no_result_json_after_processing   s   ((* 	0brNBKvbz#9:AGmm&7&.$"G WQZ//1J1JK 

277<<r
O#LMIY.LYK,XY

277<<Hk;8O$Q RIS^Q/-	0 	0 	0s   D;EE"c           	        t        j                         5 }t        |       t        |       t	        t        |      d      }t        |       t        j                  |t        d      t               dt        t               t        j                  |t        d      t               dt        t              }| j                  |D cg c]  }|j                  s| c}g        d d d        y c c}w # 1 sw Y   y xY w)Nr   r   Fr   )r   r   rD   rO   rX   r<   r_   r   r   rl   rq   rZ   r   r   r   )ru   r   rW   records2rx   s        r#   (test_second_scan_idempotent_zero_recordszDTestInboxEmptiedNoRetrigger.test_second_scan_idempotent_zero_records  s    ((* 	IbrNBKvbz#9:AGMM"_(E$0N5 &< }}R<3P/;~e+1IGH CAQ]]aCRH	I 	I D	I 	Is$   B.C/C*
C*
C/*C//C8N)r~   r   r   r   r   r!   r"   r#   r   r      s    02Ir"   r   c                      e Zd Zd Zd Zd Zy)TestReportingPathReusedc           	        t        j                         5 }t        |       t        |       t	        t        |      d      }t        |       t        j                  |t        d      t               dt        t              }t        d      }t        j                  |||t              }|D cg c]"  }|j                   t        j"                  k(  s!|$ }}| j%                  t'        |      d       | j)                  |d	   j*                         | j-                  d
|j.                  d	   d          d d d        y c c}w # 1 sw Y   y xY w)Nr   r   Fr   Trd   )r;   senderr   r   r   ztask-999: PASS)r   r   rD   rO   rX   r<   r_   r   r   rl   rq   rZ   r   rs   rptreport_recordsdecisionREPORT_PASSr   r   r   sentassertInrj   )ru   r   rW   r   r   	decisionsdr   s           r#   !test_closeout_record_maps_to_passz9TestReportingPathReused.test_closeout_record_maps_to_pass)  s   ((* 	@brNBKvbz#9:AGmml?;|~$FYHG !D)F**7FRXYI(J!AJJ#//,IAJDJSY*OODGLL)MM*FLLOA,>?	@ 	@ K	@ 	@s%   BD?-"D:D:AD?:D??Ec           	        t        j                         5 }t        d      }t        j                  t
        j                  t        j                  j                  t        |      d      ||i t              }| j                  |j                  t        j                         | j                  d|j                   d   d          d d d        y # 1 sw Y   y xY w)NTr   ztask-77.result.jsonr;   r   result_datar   ztask-77: HOLDr   r   )r   r   rs   r   
report_oner   VERDICT_QUARANTINEr7   r8   r9   r<   rZ   r   r   REPORT_HOLDr   rj   ru   r   r   decs       r#   #test_quarantine_record_maps_to_holdz;TestReportingPathReused.test_quarantine_record_maps_to_hold9  s    ((* 	?b D)F..&&VBZ)>?BfFC S\\3??;MM/6<<?1+=>	? 	? 	?s   B-CCc           	        t        j                         5 }t        d      }t        j                  t
        j                  t        j                  j                  t        |      d      ||ddit              }| j                  |j                  t        j                         | j                  d|j                   d   d          d d d        y # 1 sw Y   y xY w)	NTr   ztask-88.result.jsoncallback_schedule_createdr   ztask-88: CALLBACK_MISSINGr   r   )r   r   rs   r   r   r   r   r7   r8   r9   r<   rZ   r   r   REPORT_CALLBACK_MISSINGr   rj   r   s       r#   test_callback_missing_mappingz5TestReportingPathReused.test_callback_missing_mappingC  s    ((* 	Kb D)F..))VBZ)>?8$?v	OC
 S\\3+F+FGMM5v||Aq7IJ	K 	K 	Ks   B/CCN)r~   r   r   r   r   r   r!   r"   r#   r   r   (  s    @ ?	Kr"   r   c                      e Zd Zd Zy)TestWakeZeroDefaultc           	        t        j                         5 }t        |       t        |       t	        t        |      d      }t        |       t        j                  |t        d      t               dt        t              }|D cg c]"  }|j                  t        j                  k(  s!|$ }}| j                  t!        |      d       | j#                  |d   j$                  d       d d d        y c c}w # 1 sw Y   y xY w)Nr   
WAKE_BUILTFr   r   r   u8   launcher_fn=None 인데 real launch(fire_cron_id) 발생)r   r   rD   rO   rX   r<   r_   r   r   rl   rq   rZ   r   rc   VERDICT_WAKE_BUILTr   r   assertIsNonefire_cron_id)ru   r   rW   r   rx   wakes         r#    test_scan_default_no_real_launchz4TestWakeZeroDefault.test_scan_default_no_real_launchS  s    ((* 	ZbrNBKvbz#9:AG mml<8LN$FYHG  'N!!))s7M7M*MANDNSY*d1g22XZ	Z 	Z O	Z 	Zs$   A/C5"C0'C0+<C50C55C>N)r~   r   r   r   r!   r"   r#   r   r   R  s    Zr"   r   c                      e Zd Zd Zy)TestNoKeyLiteralc                t    d}dD ]1  }t         |z  j                  d      }| j                  ||| d       3 y )Nc119085addb0f8b7)zdispatch/anu_pickup_driver.pyzdeploy/systemd/anu-pickup.pathz#tests/test_anu_pickup_inbox_2733.pyrH   rI   u    에 ANU key literal 노출)
_REPO_ROOTr   r   )ru   	forbiddenrelsrcs       r#   "test_no_anu_key_literal_in_sourcesz3TestNoKeyLiteral.test_no_anu_key_literal_in_sourcesh  sN    +	; 	RC #...@CYu4O-PQ		Rr"   N)r~   r   r   r  r!   r"   r#   r   r   g  s    Rr"   r   c                  *    e Zd Zd Zd Zd Zd Zd Zy)TestInboxDirPreflightc                   t         j                  d      }|j                  d      }| j                  |dd       t	        d |j                         D        d      }| j                  |d       d}||u}|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}|j                  d      }| j                  |dd       |j                  |      }	| j                  |	|d       y)u1  런북 enable 절차에 inbox mkdir preflight 가 path enable 보다 앞서 존재한다.

        path 유닛 시작(systemctl enable --now anu-pickup.path) 시점에 부모 디렉토리
        (memory/events/p0b_inbox)가 존재하도록, 그 직전에 mkdir -p preflight 가 명시돼야 함.
        rH   rI   mkdir -pu0   런북에 inbox mkdir preflight 가 없습니다c              3  0   K   | ]  }d |v rd|v r|  ywr  r   Nr!   r   r   s     r#   r   zXTestInboxDirPreflight.test_runbook_mkdir_preflight_before_path_enable.<locals>.<genexpr>  s)      FBb %>"%D  F   NuW   런북 mkdir preflight 가 memory/events/p0b_inbox 를 대상으로 하지 않습니다r   z%(py0)s is not %(py3)s
mkdir_linepy0py3assert %(py5)sr   zenable --now anu-pickup.pathu,   런북에 path enable 절차가 없습니다up   런북에서 inbox mkdir preflight 가 path enable 보다 뒤에 있습니다(부모 디렉토리 보장 실패))_RUNBOOK_FILEr   findassertNotEqualnextr   assertIsNotNone
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation
assertLess)
ru   text	mkdir_idxr  @py_assert2@py_assert1@py_format4@py_format6
enable_idxinbox_mkdir_idxs
             r#   /test_runbook_mkdir_preflight_before_path_enablezETestInboxDirPreflight.test_runbook_mkdir_preflight_before_path_enablew  s    &&&8IIj)	Ir+]^F$//+ F


 	q	s!%%z%%%%z%%%%%%z%%%z%%%%%%%%%%YY=>
J,Z[))J/Z~	@r"   c                   t         j                  d      }|j                         D cg c]1  }|j                         j	                  d      r|j                         3 }}| j                  |d       | j                  t        d |D              d|        |j                  d      }|j                  d      }| j                  ||d       y	c c}w )
uT   service 유닛에 inbox 를 mkdir -p 하는 ExecStartPre 보조 안전망이 있다.rH   rI   zExecStartPre=uD   anu-pickup.service 에 ExecStartPre 보조 안전망이 없습니다c              3  0   K   | ]  }d |v xr d|v   ywr  r!   r  s     r#   r   zPTestInboxDirPreflight.test_service_execstartpre_creates_inbox.<locals>.<genexpr>  s#     S
b D%>"%DDSr  u?   ExecStartPre 가 inbox mkdir -p 를 수행하지 않습니다: zExecStart=/bin/bashu>   ExecStartPre 가 ExecStart 보다 뒤에 정의되었습니다N)	_SERVICE_FILEr   r   r   r   r   anyr  r!  )ru   r   r   preexec_pre_idxexec_start_idxs         r#   'test_service_execstartpre_creates_inboxz=TestInboxDirPreflight.test_service_execstartpre_creates_inbox  s    ))7);!(!3!3!5
xxz$$_5 HHJ
 
 	cdSsSSMcUS	U ||O4 &;<nX	Z
s   6Cc           	        t         j                  d      }t        j                  d|t        j                        }| j                  |d       d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}}|j                  d      }| j                  d|       t!        j"                         5 }t%        j&                  t$        j(                  j+                  |ddd      d       |j-                  d|      }	t$        j(                  j+                  |dddd      }
| j/                  t$        j(                  j1                  |
      d       t3        j4                  dd|	gd      }| j7                  |j8                  dd|j:                         | j=                  t$        j(                  j?                  |
      d       t3        j4                  dd|	gd      }| j7                  |j8                  dd|j:                         | j=                  t$        j(                  j?                  |
             ddd       y# 1 sw Y   yxY w)u\  부모 디렉토리 부재 상태에서 service ExecStartPre mkdir 명령이 inbox 를 생성한다(기능 검증).

        service 유닛에서 ExecStartPre mkdir 경로를 추출, %h 를 tmp HOME 으로 치환한 뒤 실제
        실행하여 p0b_inbox 가 absent → 생성됨을 확인. 재실행 시 idempotent(에러 0)도 확인.
        rH   rI   z)^ExecStartPre=/bin/mkdir\s+-p\s+(\S+)\s*$u=   ExecStartPre mkdir -p <path> 형식을 찾지 못했습니다Nr   r  mr  r  r   r   z$%h/workspace/memory/events/p0b_inbox	workspacer3   r4   Tr@   z%hr5   u3   사전조건: inbox 가 미리 존재하면 안 됨z
/bin/mkdirz-p)capture_outputr   u   mkdir 실패: u@   preflight 후 inbox 디렉토리가 생성되지 않았습니다u+   재실행 mkdir 실패(idempotent 위반): ) r-  r   research	MULTILINEr  r  r  r  r  r  r  r  r   groupr   r   r   r7   rC   r8   r9   replacer   r   
subprocessrunr   
returncodestderrr   isdir)ru   r   r4  r$  r%  r&  r'  target_tmplhometargetinboxr1r2s                r#   /test_preflight_creates_inbox_from_absent_parentzETestInboxDirPreflight.test_preflight_creates_inbox_from_absent_parent  s     ))7);IIBGR\\ZQ _`q}qqqggaj<kJ((* 	2dKKT;(KVZ[ ((t4FGGLL{HhTERWW^^E24ij tV <TRBR]]A		}/MNOOBGGMM%02tu tV <TRBR]]A1\]_]f]f\i/jkOOBGGMM%01	2 	2 	2s   *FJ44J=c                   t         j                  d      }t        d |j                         D        d      }| j	                  |d       d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}}t        j                         5 }t        j                   j#                  |dddd      }| j%                  t        j                   j'                  |             t)        t        j*                  |      }	t-        j.                  dd|gd|	      }
| j1                  |
j2                  dd|
j4                         | j7                  t        j                   j9                  |      d       ddd       y# 1 sw Y   yxY w)ul   런북에 적힌 mkdir 명령(~/workspace/...)을 HOME=tmp 로 실행해 inbox 생성 보장(기능 검증).rH   rI   c              3     K   | ]7  }|j                         j                  d       rd|v r|j                          9 ywr  )r   r   r  s     r#   r   zQTestInboxDirPreflight.test_runbook_mkdir_command_creates_inbox.<locals>.<genexpr>  s9      2B
%%j1*b0 XXZ 2s   =?NuF   런북 코드블록에서 inbox mkdir 명령을 찾지 못했습니다r   r  cmdr  r  r   r5  r3   r4   r5   )HOMEz	/bin/bashz-cT)r6  envr   u   런북 mkdir 명령 실패: uE   런북 mkdir 명령 실행 후 inbox 가 생성되지 않았습니다)r  r   r  r   r  r  r  r  r  r  r  r  r   r   r   r7   r8   r9   r   r   r   environr<  r=  r   r>  r?  r   r@  )ru   r"  rJ  r$  r%  r&  r'  rB  rD  rL  rx   s              r#   (test_runbook_mkdir_command_creates_inboxz>TestInboxDirPreflight.test_runbook_mkdir_command_creates_inbox  si   &&&82$//"3 2 	
 	S"jks$s$ss$((* 	edGGLL{HhTERWW^^E23rzz-CT37RUVAQ\\10LQXXL.YZOOBGGMM%0ce	e 	e 	es   C!G--G6c                   t         j                  d      }|j                         D cg c]1  }|j                         j	                  d      r|j                         3 }}| j                  |dgd       | j                  d|       yc c}w )u]   preflight 추가 후에도 PathExistsGlob 은 여전히 inbox 전용(legacy 직속 감시 0).rH   rI   r   r   uU   preflight 보정이 PathExistsGlob 을 변경했습니다(inbox 전용 불변 위반)r   Nr   r   s       r#   #test_path_glob_unchanged_inbox_onlyz9TestInboxDirPreflight.test_path_glob_unchanged_inbox_only  s    &&&8!(!3!3!5
xxz$$%67 HHJ

 
 	UVc	e 	JG	U
r   N)r~   r   r   r*  r2  rG  rN  rP  r!   r"   r#   r  r  v  s    @8Z"2<e,Ur"   r  __main__)r;   strreturnrR  )r;   rR  rS  Noner&   )rT   rR  rU   rR  rS  rR  )g      >@)r8   rR  r]   floatrS  rT  )r   )AUTHORITATIVE)c__doc__
__future__r   builtinsr  _pytest.assertion.rewrite	assertionrewriter  r   r   rQ   r7   r7  r<  sysr   rh   unittestr   r   pathlibr   r	   resolveparentsr   rR  r8   insertimportlib.utilutil_ilu
_real_initmodulesget_cachedgetattrlistr   _kspec_from_file_locationr   r%  @py_assert4@py_assert3@py_assert0loader@py_assert10@py_assert13@py_assert12r  r  r  r  r'  @py_format8rg   @py_format15@py_format17_format_boolop@py_format18@py_format20r  r   module_from_spec_pkgexec_moduler   r   r   r   r   r   r-  r  rZ   r   rS   r<   r>   rD   rO   rX   r_   rl   rq   rs   TestCaser   r   r   r   r   r   r   r  r~   main)r(   s   0r#   <module>r     s}    #      	 	  
    ' (^##%--a0
z?#(("HHOOAs:'
 *$}4

++//*
%
?ww
B7=2#j/Qs{{+\QqJ!,,{B[q\ KKO(D((JC
Z@W<X;YE :9599T9T!9999599999599959999999999T9999999999999T9999999999999 4  'D"CKK
	LLT" - /("Y.1BB
X%	14HHV#&DD	D 	 2&0I ?2F
!
 $
x00 
.$X.. $Td(++ dJ'I("3"3 'IZ$Kh// $KTZ(++ Z*Rx(( RnUH-- nUb zHMMO w ]s   8P"P"