
    Fi7                       d Z ddlm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ddZ edd      Z eed	       Zd
Zes.ddlZ ej(                  ej*                        Zdej.                  vZe	j0                  j3                  ed      Ze	j0                  j3                  exs ed      Z eedz  dz        Zd d!dZd"d!dZed#d       Z ed#d       Z!ed#d       Z"ed#d       Z#ed#d       Z$ed#d       Z%ed$d       Z&ed#d       Z'ed#d       Z(e	 	 	 	 	 	 d%d       Z)ed#d       Z*d$dZ+y)&u  tests/regression/test_done_escalated_conflict.py — task-2471+1 F4 회귀 테스트 (Test 1).

``check_done_escalated_conflict`` 함수와 ``verify_done_preconditions`` 통합 검증.

토르(개발1팀)의 utils/silent_corruption_guard.py 수정을 영구 차단한다.
함수 시그니처:
    check_done_escalated_conflict(task_id: str, *, events_dir: Optional[str] = None) -> dict
    verify_done_preconditions(pr_number, repo, *, base_branch, gh_cmd, cwd, task_id, events_dir) -> dict

각 반환값: {"ok": bool, "reason": str, "detail": dict}
fail-closed 패턴: 파일 시스템 오류 시 ok=False.

헤임달(개발2팀 테스터) 작성 — task-2471+1 F4.
    )annotationsN)Path   c                <   t         |z  }t        j                  j                  | t	        |            }||j
                  t        d|       t        j                  j                  |      }|t        j                  | <   |j
                  j                  |       |S )u8   절대 경로로 모듈 로드 (sys.path 오염 방지).zcannot load spec for )	WORKSPACE	importlibutilspec_from_file_locationstrloaderImportErrormodule_from_specsysmodulesexec_module)mod_namefile_rel	file_pathspecmodules        D/home/jay/workspace/tests/regression/test_done_escalated_conflict.py_load_moduler      s    H$I>>11(C	NKD|t{{*1)=>>^^,,T2F"CKKKKF#M    &silent_corruption_guard_conflict_aliasz utils/silent_corruption_guard.pycheck_done_escalated_conflictFtask_iduA   check_done_escalated_conflict 미구현 (토르 작업 미완료))reasonuR   verify_done_preconditions task_id 파라미터 미구현 (토르 작업 미완료)memoryeventsc                <    | | dz  }|j                  |d       |S )u+   events_dir에 <task_id>.done 파일 생성.z.doneutf-8encoding
write_text
events_dirr   contentps       r   
_make_doner*   F   s(    y&&ALL7L+Hr   c                <    | | dz  }|j                  |d       |S )u5   events_dir에 <task_id>.done.escalated 파일 생성.z.done.escalatedr!   r"   r$   r&   s       r   _make_escalatedr,   M   s(    y00ALL7L+Hr   c                    t        | d       t        j                  dt        |             }t	        |t
              sJ d       |d   du sJ d|v sJ d|v sJ y)	uJ   .done 만 있고 .done.escalated 없으면 ok=True (정상 완료 상태).z	task-9001r'   u   반환값이 dict 이어야 함okTr   detailNr*   scgr   r   
isinstancedicttmp_pathresults     r   test_done_only_okr8   W   sk     x%..{s8}.UFfd#F%FF#$<4vvr   c           	         t        | dt        j                  ddd             t        j	                  dt        |             }|d   du sJ y	)
uV   .done.escalated 만 있고 .done 없으면 ok=True (에스컬레이션 완료 상태).z	task-9002tr)triggerr   r(   r.   r/   TN)r,   jsondumpsr2   r   r   r5   s     r   test_escalated_only_okr@   e   sJ     Hk4::#Y\>]3^_..{s8}.UF$<4r   c                V    t         j                  dt        |             }|d   du sJ y)uS   .done / .done.escalated 모두 없으면 ok=True (미완료 상태, 충돌 없음).z	task-9003r.   r/   TN)r2   r   r   r5   s     r   test_both_absent_okrB   p   s/     ..{s8}.UF$<4r   c                    t        | dd       t        | dd       t        j                  dt	        |             }|d   du sJ d|d	   j                         v sJ d
|d	          y)ud   정상 .done + 빈 .done.escalated 동시 존재 → conflict → ok=False, reason='coexist' 포함.z	task-9004doner=    r.   r/   Fcoexistr      reason에 'coexist' 없음: N)r*   r,   r2   r   r   lowerr5   s     r   &test_done_and_empty_escalated_conflictrI   z   sz     xf5Hk26..{s8}.UF$<5   x(..00 
&vh'7&:;0r   c           
         t        | dd       t        j                  ddddt        | dz        d	d
d      }t	        | d|       t
        j                  dt        |             }|d   du sJ d       y)uV   정상 .done + 정상 payload .done.escalated 동시 존재 → conflict → ok=False.z	task-9005rD   r=   z done-watcher.sh:stale_done_30minz2026-05-07T00:00:00Zzscripts/done-watcher.shtesthostztask-9005.doneil  zstale .done >= 1800s)r<   tssourcehost	done_pathage_secondsr   r.   r/   FuM   정상 .done + 정상 .done.escalated 동시 존재는 conflict 이어야 함N)r*   r>   r?   r   r,   r2   r   )r6   valid_payloadr7   s      r   &test_done_and_valid_escalated_conflictrR      s     xf5JJ5$+$445(  M Hk=A..{s8}.UF$<5 q"qq r   c                    t        | d       | dz  }|j                          t        j                  dt	        |            }|d   du sJ t        j                  dt	        |             }|d   du sJ y)uF   events_dir=str(tmp_path) 명시 시 해당 경로에서 파일 탐색.z	task-9006otherr.   r/   TN)r*   mkdirr2   r   r   )r6   	other_dirresult_other	result_oks       r   !test_events_dir_explicit_tmp_pathrY      s     x%7"IOO44I 5 L %%% 11H 2 I T?d"""r   c                 @    t         j                  d      } | d   du sJ y)u  events_dir 미지정 시 /home/jay/workspace/memory/events 기본값 사용 확인.

    기본 이벤트 디렉토리가 실제로 존재하지 않아도 ok=True (파일 없음 = 충돌 없음).
    task_id가 실제 .done을 생성하지 않으면 ok=True를 반환해야 한다.
    z#task-nonexistent-heimdall-test-9007r/   TN)r2   r   )r7   s    r   test_events_dir_default_pathr[      s'     ../TUF$<4r   c                   t        | d       t        j                  dt        |             }|j	                  di       }h d}|t        |j                               z
  }|rJ d|d|       |d   dk(  sJ |d   d	u sJ |d
   du sJ y)u_   detail dict에 task_id, done_path, escalated_path, done_exists, escalated_exists 포함 검증.z	task-9008r.   r0   >   r   rO   done_existsescalated_pathescalated_existsu   detail에 누락된 키: u   
실제 detail: r   r]   Tr_   FN)r*   r2   r   r   getsetkeys)r6   r7   r0   required_keysmissings        r   'test_detail_dict_contains_required_keysre      s     x%..{s8}.UFZZ"%FaMc&++-00GZ3G;>OPVzZZ;)+++- D((($%...r   c                .   t        | d       t        | dd       t        j                  dt	        |             }|d   du sJ |j                  di       }|j                  d      d	u sJ |j                  d
      d	u sJ |j                  d      dk(  sJ y)uP   충돌 케이스에서 detail에 done_exists=True, escalated_exists=True 검증.z
task-9008brE   r=   r.   r/   Fr0   r]   Tr_   r   N)r*   r,   r2   r   r   r`   )r6   r7   r0   s      r   test_detail_dict_conflict_caserg      s     x&HlB7..|H.VF$<5   ZZ"%F::m$,,,::()T111::i L000r   c           	        t        | d       t        | dd       t        j                  dt	        |             }|d   du sJ d       d|d	   j                         v sJ d
|d	          d }|j                  t        d|       t        t        d      r"|j                  t        j                  dd        t        j                  ddddt	        |             }|d   du s
J d|       y)uU  verify_done_preconditions(task_id=...) 호출 시 conflict 검사 통합 검증.

    .done + .done.escalated 충돌 상황에서 verify_done_preconditions가
    check_done_escalated_conflict를 내부적으로 호출하여 ok=False를 반환해야 한다.
    PR 검사는 monkeypatch로 우회하지 않고, 대신 conflict가 먼저 감지되어
    PR 검사 전에 실패하는 경우를 검증한다.

    Note: conflict 검사가 PR 검사보다 먼저 실행되는 구현을 가정.
          만약 PR 검사가 먼저라면 PR 검사 실패 후 conflict도 포함된 detail 검증.
    z	task-9009rE   r=   r.   r/   Fu=   check_done_escalated_conflict가 conflict를 감지해야 함rF   r   rG   c                      ~ ~y)N)rE   zgh: not available in test )_args_kwargss     r   	_fake_runzKtest_verify_done_preconditions_task_id_conflict_detected.<locals>._fake_run  s
    74r   _runtimesleepc                     y )Nrk   )_s    r   <lambda>zJtest_verify_done_preconditions_task_id_conflict_detected.<locals>.<lambda>  s    r   i  z
owner/repomain)	pr_numberrepobase_branchr   r'   uI   conflict 상황에서 verify_done_preconditions가 ok=True를 반환함: N)
r*   r,   r2   r   r   rH   setattrhasattrrp   verify_done_preconditions)r6   monkeypatchconflict_resultrn   r7   s        r   8test_verify_done_preconditions_task_id_conflict_detectedr~      s    x%Hk26 77H 8 O 4 E) G) 17799 
&x'@&CD95 VY/sFCHHg~>**x= + F $<5  
STZS]^ r   c                    d}t        | |       t        j                  |t        |             }t	        |t
              sJ d|v sJ |d   du sJ y)uR   task_id에 '+' 등 특수문자 포함 시 정상 처리 (파일시스템 안전).ztask-2471+1r.   r/   TNr1   )r6   r   r7   s      r   'test_task_id_with_special_chars_handledr   %  sZ     Gx!..w3x=.QFfd###6>>$<4r   c                 2    t        t        d      sJ d       y)u   check_done_escalated_conflict 함수가 silent_corruption_guard에 존재해야 함.

    토르 작업 미완료 시 이 테스트가 FAIL하여 CI에서 즉시 감지 가능.
    r   uk   check_done_escalated_conflict 함수 미존재 — 토르의 utils/silent_corruption_guard.py 수정 필요N)rz   r2   rk   r   r   /test_smoke_check_done_escalated_conflict_existsr   3  s    
 378 u8r   )r   r   r   r   )rD   )r'   r   r   r   r(   r   returnr   )rE   )r6   r   r   None)r   r   )r6   r   r|   zpytest.MonkeyPatchr   r   ),__doc__
__future__r   importlib.utilr   r>   r   pathlibr   pytest__file__resolveparentsr   r   r2   rz   CONFLICT_FN_MISSINGVERIFY_EXTENDED_MISSINGinspect	signaturer{   _verify_sig
parametersmarkskipifSKIP_CONFLICTSKIP_VERIFY_EXTENDEDr   DEFAULT_EVENTS_DIRr*   r,   r8   r@   rB   rI   rR   rY   r[   re   rg   r~   r   r   rk   r   r   <module>r      s    #   
  
 N""$,,Q/		 ,& "#'FGG  #'##C$A$ABK'{/E/EE""N #  {{))22_ *  
 X-89            	 	 r r* # #. 	  	  / /& 1 1" 00!30	0 0l    r   