
    tiM                     z   d Z ddlZddlmZ ddlmZmZ  ee      j                  j                  Z	ddl
Ze	dz  Zej                  j                  de      ZeJ ej                  j!                  e      Zej$                  J ej$                  j'                  e        G d d      Z G d	 d
      Z G d d      Zy)u/  
test_done_protocol.py

.done 프로토콜 수정 검증 테스트 (task-616.1 설계 반영)

테스트 항목:
- log_protocol() 단위 테스트
- 통합 테스트 시나리오 (새 설계: send_telegram_notification 기반)
- done-watcher 로직 시뮬레이션 (새 설계: escalation/acked 기반)
    N)Path)	MagicMockpatchnotify-completion.pynotify_completionc                   @    e Zd ZdZdeddfdZdeddfdZdeddfdZy)TestLogProtocolu&   log_protocol() 함수 단위 테스트tmp_pathreturnNc                     |dz  }|j                         rJ t        j                  t        dt	        |            5  t        j                  dd       ddd       |j                         sJ y# 1 sw Y   xY w)u   로그 파일 자동 생성done-protocol.logDONE_PROTOCOL_LOGz
task-010.1ztest messageN)existsr   objectr   strlog_protocol)selfr
   log_paths      S/home/jay/workspace/.worktrees/task-2467+1-dev6/scripts/tests/test_done_protocol.pytest_creates_log_filez%TestLogProtocol.test_creates_log_file!   sl    11??$$$\\+-@#h-P 	I**<H	I   	I 	Is   A..A7c                 F   |dz  }t        j                  t        dt        |            5  t        j	                  dd       ddd       |j                  d      }d|v sJ d|v sJ d|v sJ |j                         }|j                  d	      sJ d
|v sJ y# 1 sw Y   WxY w)u5   [ISO8601] [notify-completion] task_id: message 포맷r   r   z
task-011.1u   상태 전이 완료Nutf-8encodingz[notify-completion][u6   ] [notify-completion] task-011.1: 상태 전이 완료)r   r   r   r   r   	read_textstrip
startswith)r   r
   r   contentlines        r   test_log_formatzTestLogProtocol.test_log_format)   s    11\\+-@#h-P 	Q**<9OP	Q$$g$6$///w&&&%000}}s###G4OOO	Q 	Qs   BB c                    |dz  }|j                  dd       t        j                  t        dt	        |            5  t        j                  dd       ddd       |j                  d      }d	|v sJ d|v sJ |j                         D cg c]  }|j                         s| }}t        |      d
k(  sJ y# 1 sw Y   fxY wc c}w )u.   기존 로그에 추가 (덮어쓰기 안 함)r   u   [기존 로그 항목]
r   r   r   z
task-012.1u
   새 항목Nu   [기존 로그 항목]   )

write_textr   r   r   r   r   r   
splitlinesr   len)r   r
   r   r   lliness         r   test_appends_to_existing_logz,TestLogProtocol.test_appends_to_existing_log8   s    116I\\+-@#h-P 	G**<F	G$$g$6'7222w&&&#..0>qAGGI>>5zQ	G 	G
 ?s   B9C"C9C)__name__
__module____qualname____doc__r   r   r!   r)        r   r	   r	      sA    0!d !t !P P P
T 
d 
r/   r	   c                       e Zd ZdZ ed      dededdfd       Z ed      dededdfd       Zdeddfd	Z	 ed      dededdfd
       Z
 ed      dededdfd       Z ed      dededdfd       Zy)TestDoneProtocolIntegrationuA   통합 테스트 시나리오 (새 설계: .done.notified 없음)subprocess.runmock_runr
   r   Nc           	         dt         dt         dt         dt        fd}||_        |dz  dz  j                  dd	       t	        d
ddg      5  t	        j
                  dddd      5  t	        j                   t        dt        |            5  t	        j                   t        dd      5 }t        j                          ddd       ddd       ddd       ddd       j                  dk\  sJ d       |j                  d   d   dd \  }}d|v sJ d       d|v sJ d       d|vsJ d|vsJ |dz  dz  }|dz  j                         rJ y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w) u3   정상 플로우: send_telegram_notification 호출cmd_args_kwargsr   c                 P   ~~t               }d|_        d|_        t        | t              r_dj                  d | D              }d|v r%d|v r!t        j                  ddd d d      |_        |S t        j                  d	d
i      |_        |S t        j                  d	d
i      |_        |S )Nr     c              3   2   K   | ]  }t        |        y wNr   .0cs     r   	<genexpr>zhTestDoneProtocolIntegration.test_normal_flow_sends_telegram_only.<locals>.side_effect.<locals>.<genexpr>R        "7a3q6"7   chain_manager.pycheckFin_chainis_lastchain_idnext_task_idstatusok	r   
returncodestderr
isinstancelistjoinjsondumpsstdoutr5   r6   r7   resultcmd_strs        r   side_effectzUTestDoneProtocolIntegration.test_normal_flow_sends_telegram_only.<locals>.side_effectL       w[F !FFM#t$(("73"77%0W5G$(JJ%*u$`de%FM M %)JJ$/?$@FM M !%

Hd+; <Mr/   memoryeventsTparentsexist_oksys.argvr   z
task-030.1
os.environtest-keytest-bot-tokenCOKACDIR_KEY_ANUANU_BOT_TOKENWORKSPACE_ROOTsend_telegram_notificationFreturn_valueN   u1   send_telegram_notification이 호출되어야 함r   r#   u   메시지에 task_id 포함   완료u   메시지에 '완료' 포함
done.cleardone.notifiedztask-030.1.done.notified)r   r   rY   mkdirr   dictr   r   main
call_countcall_args_listr   )r   r3   r
   rY   	mock_send_message_arg
events_dirs           r   $test_normal_flow_sends_telegram_onlyz@TestDoneProtocolIntegration.test_normal_flow_sends_telegram_onlyH   s   	V 	V 	 	9 	"  +	H	x	'..td.K *5|DE	%JJ|*Wg%hi	% LL*,<c(mL	% LL*,HW\]		% bk""$	% 	% 	% 	% ##q(]*]]( #11!4Q7;;{*I,II*;&F(FF&;...k111 (83
!;;CCEEEE+	% 	% 	% 	% 	% 	% 	% 	%sT   E.%%E"
E'E
	<EE"E.
EEEE""E+	'E..E7c           	      L   dt         dt         dt         dt        fd}||_        |dz  dz  j                  dd	       t	        d
ddg      5  t	        j
                  dddd      5  t	        j                   t        dt        |            5  t	        j                   t        dd      5 }t        j                          ddd       ddd       ddd       ddd       |dz  dz  }|dz  j                         rJ d       |j                  D cg c]2  }t        |d   d   t              rt        d |d   d   D              r|4 }}t        |      dk\  sJ d       j                  dk\  sJ d       y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY wc c}w )uW   체인 중간: dispatch.py 호출, 텔레그램 알림 전송, .done.notified 미생성r5   r6   r7   r   c                    ~~t               }d|_        d|_        t        | t              rdj                  d | D              }d|v r%d|v r!t        j                  ddd	d
d      |_        |S d|v r%d|v r!t        j                  dddd
d      |_        |S t        j                  ddi      |_        |S t        j                  ddi      |_        |S )Nr   r9   r:   c              3   2   K   | ]  }t        |        y wr<   r=   r>   s     r   rA   zsTestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegram.<locals>.side_effect.<locals>.<genexpr>   rB   rC   rD   rE   TFz	chain-031z
task-031.2rF   nextdispatchzmemory/tasks/task-031.2.mdz	dev1-team)action	task_fileteamtask_idrK   rL   rM   rV   s        r   rY   z`TestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegram.<locals>.side_effect{   s    w[F !FFM#t$(("73"77%0W5G$(JJ(,',(3,8	%FM* M (72v7H$(JJ&0)E$/'3	%FM M %)JJ$/?$@FM M !%

Hd+; <Mr/   r[   r\   Tr]   r`   r   z
task-031.1ra   rb   rc   rd   rg   rh   Fri   Nztask-031.1.done.notifiedu0   체인 중간에서 .done.notified 생성 금지r   c              3   6   K   | ]  }d t        |      v   yw)zdispatch.pyNr=   )r?   xs     r   rA   z^TestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegram.<locals>.<genexpr>   s     0ZQ#a&1H0Zs   rk   u#   dispatch.py 호출이 있어야 함uA   체인 중간에서도 텔레그램 알림이 전송되어야 함)r   r   rY   ro   r   rp   r   r   rq   r   rs   rP   rQ   anyr&   rr   )r   r3   r
   rY   rt   rw   r@   dispatch_callss           r   /test_chain_middle_dispatches_and_sends_telegramzKTestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegramw   s   	V 	V 	 	9 	>  +	H	x	'..td.K *5|DE	%JJ|*Wg%hi	% LL*,<c(mL	% LL*,HW\]		% bk""$	% 	% 	% 	% (83
 !;;CCEyGyyE  ..
!A$q'4(S0ZRSTURVWXRY0Z-Z 
 
 >"a'N)NN' ##q(m*mm(+	% 	% 	% 	% 	% 	% 	% 	%
sZ   F%%F	
E='E1	<E=F	F7F!1E:6E==FF		F	FFc           
      z   dt         dt         dt         dt        fd}|dz  dz  }|j                  dd	       |d
z  }|j                  t	        j
                  ddd      d       t        d|      5  t        dddg      5  t        j                  dddi      5  t        j                   t        dt        |            5  t        j                          ddd       ddd       ddd       ddd       |j                         sJ d       y# 1 sw Y   9xY w# 1 sw Y   =xY w# 1 sw Y   AxY w# 1 sw Y   ExY w)u8   .done 파일은 notification 후에도 events/에 유지r5   r6   r7   r   c                 P   ~~t               }d|_        d|_        t        | t              r_dj                  d | D              }d|v r%d|v r!t        j                  ddd d d      |_        |S t        j                  d	d
i      |_        |S t        j                  d	d
i      |_        |S )Nr   r9   r:   c              3   2   K   | ]  }t        |        y wr<   r=   r>   s     r   rA   zhTestDoneProtocolIntegration.test_done_file_survives_notification.<locals>.side_effect.<locals>.<genexpr>   rB   rC   rD   rE   FrF   rK   rL   rM   rV   s        r   rY   zUTestDoneProtocolIntegration.test_done_file_survives_notification.<locals>.side_effect   rZ   r/   r[   r\   Tr]   ztask-033.1.donez
task-033.1	completedr   rK   r   r   r2   )rY   r`   r   ra   re   rb   rg   NuE   .done 파일이 notification 후에도 events/에 유지되어야 함)r   r   ro   r$   rS   rT   r   rp   r   r   rq   r   )r   r
   rY   rw   	done_paths        r   $test_done_file_survives_notificationz@TestDoneProtocolIntegration.test_done_file_survives_notification   s@   	V 	V 	 	9 	" (83
5!22	JJ<;GH 	 	
 "<	%*5|DE	% JJ|&8*%EF	% LL*,<c(mL		% ""$	% 	% 	% 	% !j#jj!	% 	% 	% 	% 	% 	% 	% 	%sT   3D1D%%D D	DD%%D1DDD"D%%D.	*D11D:c           	         dt         dt         dt         dt        fd}||_        |dz  dz  }|j                  dd	       |d
z  }t	        j
                  ddd      }|j                  |d       t        dddg      5  t        j                  dddi      5  t        j                   t        dt        |            5  t        j                          ddd       ddd       ddd       |j                         sJ d       |j                  d      |k(  sJ d       |dz  j                         rJ d       y# 1 sw Y   gxY w# 1 sw Y   kxY w# 1 sw Y   oxY w)u4   .done 파일이 rename/삭제되지 않는지 확인r5   r6   r7   r   c                 P   ~~t               }d|_        d|_        t        | t              r_dj                  d | D              }d|v r%d|v r!t        j                  ddd d d      |_        |S t        j                  d	d
i      |_        |S t        j                  d	d
i      |_        |S )Nr   r9   r:   c              3   2   K   | ]  }t        |        y wr<   r=   r>   s     r   rA   zrTestDoneProtocolIntegration.test_done_file_not_modified_after_notification.<locals>.side_effect.<locals>.<genexpr>   rB   rC   rD   rE   FrF   rK   rL   rM   rV   s        r   rY   z_TestDoneProtocolIntegration.test_done_file_not_modified_after_notification.<locals>.side_effect   rZ   r/   r[   r\   Tr]   ztask-034.1.donez
task-034.1r   r   r   r   r`   r   ra   re   rb   rg   Nu$   .done 파일이 삭제되면 안 됨u+   .done 파일 내용이 변경되면 안 됨ztask-034.1.done.clearu*   .done.clear 파일이 생성되면 안 됨)r   r   rY   ro   rS   rT   r$   r   rp   r   r   rq   r   r   )r   r3   r
   rY   rw   r   original_contents          r   .test_done_file_not_modified_after_notificationzJTestDoneProtocolIntegration.test_done_file_not_modified_after_notification   sk   	V 	V 	 	9 	"  +(83
5!22	::,+&VW-@ *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% !I#II!""G"48HHwJwwH!88@@BpDppBB	% 	% 	% 	% 	% 	%s<   =E%E;D6EE6D?;EE	EEc           	         dt         dt         dt         dt        fd}||_        |dz  dz  }|j                  dd	       t	        d
ddg      5  t	        j
                  dddi      5  t	        j                   t        dt        |            5  t        j                          ddd       ddd       ddd       |dz  j                         rJ d       y# 1 sw Y   4xY w# 1 sw Y   8xY w# 1 sw Y   <xY w)u=   .done.notified 파일이 절대 생성되지 않는지 확인r5   r6   r7   r   c                 P   ~~t               }d|_        d|_        t        | t              r_dj                  d | D              }d|v r%d|v r!t        j                  ddd d d      |_        |S t        j                  d	d
i      |_        |S t        j                  d	d
i      |_        |S )Nr   r9   r:   c              3   2   K   | ]  }t        |        y wr<   r=   r>   s     r   rA   zaTestDoneProtocolIntegration.test_no_done_notified_created.<locals>.side_effect.<locals>.<genexpr>  rB   rC   rD   rE   FrF   rK   rL   rM   rV   s        r   rY   zNTestDoneProtocolIntegration.test_no_done_notified_created.<locals>.side_effect
  rZ   r/   r[   r\   Tr]   r`   r   z
task-035.1ra   re   rb   rg   Nztask-035.1.done.notifiedu-   .done.notified 파일이 생성되면 안 됨)
r   r   rY   ro   r   rp   r   r   rq   r   )r   r3   r
   rY   rw   s        r   test_no_done_notified_createdz9TestDoneProtocolIntegration.test_no_done_notified_created  s    	V 	V 	 	9 	"  +(83
5 *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% !;;CCEvGvvEE	% 	% 	% 	% 	% 	%s<   C+&%CC C(C+CCC(	$C++C4c           	         dt         dt         dt         dt        fd}||_        |dz  dz  }|j                  dd	       t	        d
ddg      5  t	        j
                  dddd      5  t	        j                   t        dt        |            5  t	        j                   t        dd      5 }t        j                          ddd       ddd       ddd       ddd       j                  dk\  sJ d       |j                  d   d   dd \  }}d|v s
J d|        d|v s
J d|        d|vs
J d|        d|vs
J d|        y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w) u_   독립 작업에서 send_telegram_notification이 호출되고 구형 프롬프트가 없는지r5   r6   r7   r   c                 P   ~~t               }d|_        d|_        t        | t              r_dj                  d | D              }d|v r%d|v r!t        j                  ddd d d      |_        |S t        j                  d	d
i      |_        |S t        j                  d	d
i      |_        |S )Nr   r9   r:   c              3   2   K   | ]  }t        |        y wr<   r=   r>   s     r   rA   zqTestDoneProtocolIntegration.test_independent_task_sends_telegram_not_wake.<locals>.side_effect.<locals>.<genexpr>4  rB   rC   rD   rE   FrF   rK   rL   rM   rV   s        r   rY   z^TestDoneProtocolIntegration.test_independent_task_sends_telegram_not_wake.<locals>.side_effect.  rZ   r/   r[   r\   Tr]   r`   r   z
task-036.1ra   rb   rc   rd   rg   rh   ri   Nrk   uE   독립 작업에서 send_telegram_notification이 호출되어야 함r   r#   u    메시지에 task_id가 없음: rl   u!   메시지에 '완료'가 없음: rm   u3   wake_anu_session 구형 프롬프트가 전송됨: rn   u-   done.notified 참조 메시지가 전송됨: )r   r   rY   ro   r   rp   r   r   rq   rr   rs   )r   r3   r
   rY   rw   rt   ru   rv   s           r   -test_independent_task_sends_telegram_not_wakezITestDoneProtocolIntegration.test_independent_task_sends_telegram_not_wake*  s   	V 	V 	 	9 	"  +(83
5 *5|DE	%JJ|*Wg%hi	% LL*,<c(mL	% LL*,HW[\		% aj""$	% 	% 	% 	% ##q(q*qq( #11!4Q7;;{*\.N{m,\\*;&Y*KK=(YY& ;.s2efqer0ss.k1p5bcnbo3pp1%	% 	% 	% 	% 	% 	% 	% 	%sT   E)'%EE)E	>EEE)E
EEEE&	"E))E2)r*   r+   r,   r-   r   r   r   rx   r   r   r   r   r   r.   r/   r   r1   r1   E   s+   K
,FY ,FRV ,F[_ ,F ,F\ :n	 :n]a :nfj :n :nx%kT %kd %kN (qy (q\` (qei (q (qT !wi !w4 !wTX !w !wF +qi +q[_ +qdh +q +qr/   r1   c                       e Zd ZdZ	 ddededededef
dZdededed	edef
d
Z	deddfdZ
deddfdZdeddfdZdeddfdZy)TestDoneWatcherLogicuR   done-watcher 새 설계 로직 시뮬레이션 테스트 (escalation/acked 기반)rw   r   age_minutesescalation_thresholdr   c                 p    || dz  }|| dz  }|j                         sy|j                         ry||k\  S )u   
        .done 파일이 age_minutes 경과했을 때 에스컬레이션 여부 반환.
        threshold(기본 30분) 이상이면 True, 미만이면 False.
        .done.escalated가 이미 존재하면 중복 방지 → False.
        .done.done.escalatedF)r   )r   rw   r   r   r   r   escalated_paths          r   _simulate_stale_done_escalationz4TestDoneWatcherLogic._simulate_stale_done_escalation\  sP     G9E!22	#	&AA!  "222r/   archive_diracked_age_hoursc                     || dz  }|j                         sy|dk\  r+|j                  dd       |j                  || dz         yy)uf   
        .done.acked가 acked_age_hours 이상이면 archive로 이동. 이동 여부 반환.
        .done.ackedF   Tr]   )r   ro   rename)r   rw   r   r   r   
acked_paths         r   _simulate_acked_cleanupz,TestDoneWatcherLogic._simulate_acked_cleanupm  s_      WI["99
  "b dT:kwi{,CCDr/   r
   Nc                     |dz  dz  }|j                  dd       d}|| dz  j                  dd	       | j                  ||d
      du sJ | j                  ||d      du sJ y)u0   .done 파일 30분 이상 → 에스컬레이션r[   r\   Tr]   z
task-050.1r   {}r   r      r   <   Nro   r$   r   r   r
   rw   r   s       r   test_stale_done_escalationz/TestDoneWatcherLogic.test_stale_done_escalationz  s    (83
5		'	'33D73K 33JUW3X\````33JUW3X\````r/   c                     |dz  dz  }|j                  dd       d}|| dz  j                  dd	       | j                  ||d
      du sJ | j                  ||d      du sJ y)u2   .done 파일 30분 미만 → 아무 동작 없음r[   r\   Tr]   z
task-051.1r   r   r   r      r   Fr   Nr   r   s       r   %test_stale_done_under_30min_no_actionz:TestDoneWatcherLogic.test_stale_done_under_30min_no_action  s    (83
5		'	'33D73K 33JUW3X\aaaa33JUV3W[````r/   c                     |dz  dz  }|j                  dd       d}|| dz  j                  dd	       || d
z  j                  dd	       | j                  ||d      du sJ y)u/   .done.escalated 존재 시 중복 알림 없음r[   r\   Tr]   z
task-052.1r   r   r   r   r   r   r   FNr   r   s       r   (test_escalated_marker_prevents_duplicatez=TestDoneWatcherLogic.test_escalated_marker_prevents_duplicate  s    (83
5		'	'33D73K		1	1==dW=U 33JUW3X\aaaar/   c                    |dz  dz  }|j                  dd       |dz  dz  }d}|| dz  j                  dd	
       | j                  |||d      }|du sJ || dz  j                         sJ d       | j                  |||d      }|du sJ || dz  j                         rJ d       || dz  j                         sJ d       y)u.   .done.acked 24시간 이상 → archive 이동r[   r\   Tr]   archivez
task-053.1r   r   r   r      )r   Fu2   24시간 미만에는 archive 이동 없어야 함r   u7   24시간 이상이면 events/에서 제거되어야 함u   archive/로 이동되어야 함N)ro   r$   r   r   )r   r
   rw   r   r   moveds         r   test_acked_cleanup_after_24hz1TestDoneWatcherLogic.test_acked_cleanup_after_24h  s   (83
5)I5		-	-99$9Q ,,Zg_a,b~~y44<<>t@tt> ,,Zg_a,b}}G9K!88@@B}D}}B	55==?bAbb?r/   )r   )r*   r+   r,   r-   r   r   intboolr   r   r   r   r   r   r.   r/   r   r   r   Y  s    \ ]_33),3;>3VY3	3"$ T TW jm rv 
a4 
aD 
a
ad 
at 
a
b 
b$ 
bcT cd cr/   r   )r-   rS   pathlibr   unittest.mockr   r   __file__parent_SCRIPTS_DIRimportlib.util	importlib_MODULE_PATHutilspec_from_file_locationspecmodule_from_specr   loaderexec_moduler	   r1   r   r.   r/   r   <module>r      s   	   * H~$$++ 44~~--.A<P NN33D9 {{    ) *$ $NQq QqhWc Wcr/   