
    ilP                        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
mZ ddlmZmZ ddlZ ee      j"                  j"                  ZddlZedz  Zej,                  j/                  de      ZdZeeuZes ej6                  defdeef      d	 ej8                         v s ej:                  e      r ej<                  e      nd	 ej<                  e      d
z  Zddeiz  Z  e! ejD                  e             dxZZej,                  jG                  e      Z$ejJ                  ZdZ&ee&uZ'e's ej6                  de'fdee&f      d	 ej8                         v s ej:                  e      r ej<                  e      nd	 ej<                  e       ej<                  e&      dz  Z dde iz  Z( e! ejD                  e(            dxZxZ'Z&ejJ                  jS                  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_completion)is not)z%(py0)s is not %(py3)sspecpy0py3assert %(py5)spy5)z2%(py2)s
{%(py2)s = %(py0)s.loader
} is not %(py5)s)r   py2r   zassert %(py7)spy7c                   @    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                 N   |dz  }|j                   } |       }| }|sddt        j                         v st        j                  |      rt        j
                  |      ndt        j
                  |      t        j
                  |      dz  }t        t        j                  |            dx}x}}t        j                  t        dt        |            5  t        j                  dd       ddd       |j                   } |       }|sd	dt        j                         v st        j                  |      rt        j
                  |      ndt        j
                  |      t        j
                  |      dz  }t        t        j                  |            dx}}y# 1 sw Y   xY w)
u   로그 파일 자동 생성done-protocol.logzEassert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}log_pathr   r   py4NDONE_PROTOCOL_LOGz
task-010.1ztest messagezAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
})exists@py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationr   objectr   strlog_protocol)selfr   r   @py_assert1@py_assert3@py_assert5@py_format6@py_format5s           7/home/jay/workspace/scripts/tests/test_done_protocol.pytest_creates_log_filez%TestLogProtocol.test_creates_log_file%   s	   11??$?$$$$$$$$$$$8$$$8$$$?$$$$$$$$$$\\+-@#h-P 	I**<H	I         x   x             	I 	Is   FF$c                    |dz  }t        j                  t        dt        |            5  t        j	                  dd       ddd       |j                  d      }d}||v }|st        j                  d	|fd
||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d	|fd
||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d	|fd
||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}|j                         }|j                  }	d}
 |	|
      }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |	      t        j                  |
      t        j                  |      dz  }t        t        j                  |            dx}	x}
}d}||v }|st        j                  d	|fd
||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y# 1 sw Y   xY w)u5   [ISO8601] [notify-completion] task_id: message 포맷r   r   z
task-011.1u   상태 전이 완료Nutf-8encodingz[notify-completion]inz%(py1)s in %(py3)scontentpy1r   r   r   [zLassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}line)r   r   r   py6u6   ] [notify-completion] task-011.1: 상태 전이 완료)r   r#   r   r$   r%   	read_textr   _call_reprcomparer    r   r   r   r!   r"   strip
startswith)r&   r   r   r5   @py_assert0@py_assert2@py_format4r*   r9   r'   r(   r)   @py_format7s                r,   test_log_formatzTestLogProtocol.test_log_format-   sD   11\\+-@#h-P 	Q**<9OP	Q$$g$6$/$////$///$////////////////&|w&&&&|w&&&|&&&&&&w&&&w&&&&&&&%0%0000%000%0000000000000000}}#s#s########t###t######s##########GOG4OOOOG4OOOGOOOOOO4OOO4OOOOOOO	Q 	Qs   N??O	c                    |dz  }|j                  dd       t        j                  t        dt	        |            5  t        j                  dd       ddd       |j                  d      }d	}||v }|st        j                  d
|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d
|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}|j                         D cg c]  }|j!                         s| }	}t#        |	      }d}
||
k(  }|st        j                  d|fd||
f      dt        j                         v st        j                  t"              rt        j                  t"              nddt        j                         v st        j                  |	      rt        j                  |	      ndt        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}}
y# 1 sw Y   xY wc c}w )u.   기존 로그에 추가 (덮어쓰기 안 함)r   u   [기존 로그 항목]
r/   r0   r   z
task-012.1u
   새 항목Nu   [기존 로그 항목]r2   r4   r5   r6   r   r      ==)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenlinesr   r7   r   r:   zassert %(py8)spy8)
write_textr   r#   r   r$   r%   r;   r   r<   r    r   r   r   r!   r"   
splitlinesr=   rH   )r&   r   r   r5   r?   r@   rA   r*   lrI   r)   @py_assert4rB   @py_format9s                 r,   test_appends_to_existing_logz,TestLogProtocol.test_appends_to_existing_log<   s   116I\\+-@#h-P 	G**<F	G$$g$6'2'72222'7222'222222722272222222&|w&&&&|w&&&|&&&&&&w&&&w&&&&&&&#..0>qAGGI>>5zQzQzQss55zQ	G 	G
 ?s   K7
L L7L)__name__
__module____qualname____doc__r   r-   rC   rQ        r,   r   r   "   sA    0!d !t !P P P
T 
d 
rW   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           	      t   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       |j                  D cg c]*  }t        |d   d   t              s|d   d   d   dk(  s)|, }}t        |      }d}||k\  }|st        j                  d|fd||f      dt        j                          v st        j"                  t              rt        j$                  t              nddt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }	t        j&                  d      dz   d|	iz  }
t)        t        j*                  |
            dx}x}}|d   d   d   }dj-                  d |D              }d}||v }|st        j                  d|fd ||f      t        j$                  |      d!t        j                          v st        j"                  |      rt        j$                  |      nd!d"z  }t        j&                  d#      d$z   d%|iz  }t)        t        j*                  |            dx}}d&}||v }|st        j                  d|fd ||f      t        j$                  |      d!t        j                          v st        j"                  |      rt        j$                  |      nd!d"z  }t        j&                  d'      d$z   d%|iz  }t)        t        j*                  |            dx}}d(|v r|j/                  d(      nd)}|dk\  r|dz   t        |      k  r||dz      }d*}||v}|st        j                  d+|fd,||f      t        j$                  |      d-t        j                          v st        j"                  |      rt        j$                  |      nd-d"z  }t        j&                  d.      d$z   d%|iz  }t)        t        j*                  |            dx}}|dz  dz  }d/}||z  }|j0                  } |       }| }|st        j&                  d0      d1z   d2t        j                          v st        j"                  |      rt        j$                  |      nd2t        j$                  |      t        j$                  |      t        j$                  |      d3z  }
t)        t        j*                  |
            dx}x}x}x}}y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY wc c}w )4uO   정상 플로우: send_telegram_notification 호출, wake_anu_session 미호출cmdargskwargsr   c                 L   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>U        "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r]   r^   r_   resultcmd_strs        r,   side_effectzUTestDoneProtocolIntegration.test_normal_flow_sends_telegram_only.<locals>.side_effectP       [F !FFM#t$(("73"77%0W5G$(JJ%*u$`de%FM M %)JJ$/?$@FM M !%

Hd+; <MrW   memoryeventsTparentsexist_oksys.argvr   z
task-030.1
os.environCOKACDIR_KEY_ANUtest-keyWORKSPACE_ROOTNr   cokacdir   >=z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)srH   cokacdir_callsrJ   u;   send_telegram_notification(cokacdir)가 호출되어야 함
>assert %(py8)srK   rb   c              3   2   K   | ]  }t        |        y wrd   re   )rg   xs     r,   ri   zSTestDoneProtocolIntegration.test_normal_flow_sends_telegram_only.<locals>.<genexpr>p   s     #AqCF#Ark   r2   r4   cokacdir_cmd_strr6   u+   메시지에 task_id가 포함되어야 함
>assert %(py5)sr      완료u,   메시지에 '완료'가 포함되어야 함--cron
done.clearnot inz%(py1)s not in %(py3)smsgu?   wake_anu_session의 구형 프롬프트가 전송되면 안 됨ztask-030.1.done.notified-   .done.notified 파일이 생성되면 안 됨S
>assert not %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}
events_dirr   r   r   r   )r#   r   r   mkdirr   dictr   r$   maincall_args_listrx   ry   rH   r   r<   r   r   r   r    _format_assertmsgr!   r"   rz   indexr   )r&   r[   r   r   rh   r   r@   r)   rO   rB   rP   cokacdir_cmdr   r?   rA   r*   cron_idxr   r   r'   r(   @py_assert6@py_assert8s                          r,   $test_normal_flow_sends_telegram_onlyz@TestDoneProtocolIntegration.test_normal_flow_sends_telegram_onlyL   s   	V 	F 	f 	 	   +	H	x	'..td.K *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% &.%<%<w
1Q4PQ7TX@Y^_`a^bcd^efg^hlv^v!ww>"faf"a'fff"affffffsfffsffffff>fff>fff"fffafff)ffffffff &a(+A.88#AL#AA^|//^^^|/^^^|^^^^^^/^^^/^^^^1^^^^^^^[x++[[[x+[[[x[[[[[[+[[[+[[[[-[[[[[[[ 4<|3K<%%h/QSq=X\C,==x!|,Cm<s*mmm<smmm<mmmmmmsmmmsmmmm,mmmmmmm (83
!;vJ!;;v;CCvCEvEEvEvvGvvvvvvvJvvvJvvv!;vvvCvvvEvvvvvvv5	% 	% 	% 	% 	% 	% xsN   V($%V	VV&V(V5 V5/V5VVV%	 V((V2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i      5  t	        j                   t        dt        |            5  t        j                          ddd       ddd       ddd       |dz  dz  }d}||z  }|j                  } |       }| }	|	st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }
t!        t        j"                  |
            dx}x}x}x}}	|j$                  D cg c]D  }t'        |d   d   t(              r,t+        |d   d         dk\  rdt        |d   d   d         v r|F }}t+        |      }d}||k\  }|st        j,                  d|fd||f      dt        j                         v st        j                  t*              rt        j                  t*              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d       d!z   d"|iz  }
t!        t        j"                  |
            dx}x}}|j$                  D cg c]*  }t'        |d   d   t(              s|d   d   d   d#k(  s)|, }}t+        |      }d}||k\  }|st        j,                  d|fd||f      dt        j                         v st        j                  t*              rt        j                  t*              ndd$t        j                         v st        j                  |      rt        j                  |      nd$t        j                  |      t        j                  |      dz  }t        j                  d%      d!z   d"|iz  }
t!        t        j"                  |
            dx}x}}y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY wc c}w c c}w )&uZ   체인 중간: dispatch(bash) 호출, 텔레그램 알림 전송, .done.notified 미생성r]   r^   r_   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 d|v rt        j                  ddi      |_        |S d|v rt        j                  ddi      |_        |S t        j                  ddi      |_        |S t        j                  ddi      |_        |S )Nr   ra   rb   c              3   2   K   | ]  }t        |        y wrd   re   rf   s     r,   ri   zsTestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegram.<locals>.side_effect.<locals>.<genexpr>   rj   rk   rl   rm   TFz	chain-031z
task-031.2rn   nextdispatchzmemory/tasks/task-031.2.mdz	dev1-team)action	task_fileteamtask_idbashrs   
dispatchedr   rt   ru   r~   s        r,   r   z`TestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegram.<locals>.side_effect   s,   [F !FFM#t$(("73"77%0W5G$(JJ(,',(3,8	%FM2 M# (72v7H$(JJ&0)E$/'3	%FM  M w&$(JJ,/G$HFM M  7*$(JJ$/?$@FM
 M %)JJ$/?$@FM M !%

Hd+; <MrW   r   r   Tr   r   r   z
task-031.1r   r   r   r   Nztask-031.1.done.notifiedu0   체인 중간에서 .done.notified 생성 금지r   r   r   r   rE   r   r   r   r   rH   
bash_callsrJ   u-   dispatch(bash -c ...) 호출이 있어야 함r   rK   r   r   uA   체인 중간에서도 텔레그램 알림이 전송되어야 함)r#   r   r   r   r   r   r   r$   r   r   r   r   r   r   r   r    r!   r"   r   rx   ry   rH   r<   )r&   r[   r   r   r   r'   r(   rO   r   r   rP   rh   r   r@   r)   rB   r   s                    r,   /test_chain_middle_dispatches_and_sends_telegramzKTestDoneProtocolIntegration.test_chain_middle_dispatches_and_sends_telegram   sm    	V  	F  	f  	  	D  +	H	x	'..td.K *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% (83
 "<yJ!;;y;CCyCEyEEyEyyGyyyyyyyJyyyJyyy!;yyyCyyyEyyyyyyy
 ,,
!A$q'4(S1a\Q->6SQRSTQUVWQXYZQ[_C\ 

 

 :T!T!#TTT!TTTTTTsTTTsTTTTTT:TTT:TTTTTT!TTT%TTTTTTTT &.%<%<w
1Q4PQ7TX@Y^_`a^bcd^efg^hlv^v!ww>"lal"a'lll"allllllslllsllllll>lll>lll"lllalll)llllllll-	% 	% 	% 	% 	% 	%
 xsU   R$%R	RR&R,A	R,,R1R1R1R
RR	RR)c           
         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                  } |       }|st        j                  d      dz   dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      dz  }t%        t        j&                  |            dx}}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)u8   .done 파일은 notification 후에도 events/에 유지r]   r^   r_   r   c                 L   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   ra   rb   c              3   2   K   | ]  }t        |        y wrd   re   rf   s     r,   ri   zhTestDoneProtocolIntegration.test_done_file_survives_notification.<locals>.side_effect.<locals>.<genexpr>   rj   rk   rl   rm   Frn   rs   rt   ru   r~   s        r,   r   zUTestDoneProtocolIntegration.test_done_file_survives_notification.<locals>.side_effect   r   rW   r   r   Tr   ztask-033.1.donez
task-033.1	completedr   rs   r/   r0   rZ   )r   r   r   r   r   r   r   NuE   .done 파일이 notification 후에도 events/에 유지되어야 함C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}	done_pathr   )r#   r   r   rL   r{   r|   r   r   r   r$   r   r   r   r   r   r   r   r    r!   r"   )r&   r   r   r   r   r'   r(   r+   s           r,   $test_done_file_survives_notificationz@TestDoneProtocolIntegration.test_done_file_survives_notification   s   	V 	F 	f 	 	  (83
5!22	JJ<;GH 	 	
 "<	%*5|DE	% JJ|&8*%EF	% LL*,<c(mL		% ""$	% 	% 	% 	% j!j!jj#jjjjjjjyjjjyjjjjjj!jjjjjj	% 	% 	% 	% 	% 	% 	% 	%sT   3GG
%F> F2	F>G
%G2F;7F>>GG

G	GG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                  } |       }|st        j                  d      dz   dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }	t'        t        j(                  |	            dx}}|j*                  }d} ||      }
|
|k(  }|st        j,                  d|fd|
|f      dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      t        j$                  |
      dt        j                          v st        j"                  |      rt        j$                  |      nddz  }t        j                  d      d z   d!|iz  }t'        t        j(                  |            dx}x}x}
}d"}||z  }|j                  } |       }| }|st        j                  d#      d$z   d%t        j                          v st        j"                  |      rt        j$                  |      nd%t        j$                  |      t        j$                  |      t        j$                  |      d&z  }t'        t        j(                  |            dx}x}x}x}}y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y    xY w)'u4   .done 파일이 rename/삭제되지 않는지 확인r]   r^   r_   r   c                 L   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   ra   rb   c              3   2   K   | ]  }t        |        y wrd   re   rf   s     r,   ri   zrTestDoneProtocolIntegration.test_done_file_not_modified_after_notification.<locals>.side_effect.<locals>.<genexpr>   rj   rk   rl   rm   Frn   rs   rt   ru   r~   s        r,   r   z_TestDoneProtocolIntegration.test_done_file_not_modified_after_notification.<locals>.side_effect   r   rW   r   r   Tr   ztask-034.1.donez
task-034.1r   r   r/   r0   r   r   r   r   r   r   Nu$   .done 파일이 삭제되면 안 됨r   r   r   rF   )zX%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.read_text
}(encoding=%(py4)s)
} == %(py8)soriginal_content)r   r   r   r:   rK   u+   .done 파일 내용이 변경되면 안 됨z
>assert %(py10)spy10ztask-034.1.done.clearu*   .done.clear 파일이 생성되면 안 됨r   r   r   )r#   r   r   r   r{   r|   rL   r   r   r   r$   r   r   r   r   r   r   r   r    r!   r"   r;   r<   )r&   r[   r   r   r   r   r   r'   r(   r+   r)   @py_assert7rP   @py_format11rO   r   r   s                    r,   .test_done_file_not_modified_after_notificationzJTestDoneProtocolIntegration.test_done_file_not_modified_after_notification   s   	V 	F 	f 	 	   +(83
5!22	::,+&VW-@ *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% I!I!II#IIIIIIIyIIIyIIIIII!IIIIII""wGw"G4w48HHwww48Hwwwwwwywwwywww"wwwGwww4wwwwww8Hwww8HwwwwJwwwwwwww!8pJ!88p8@@p@BpBBpBppDpppppppJpppJppp!8ppp@pppBppppppp	% 	% 	% 	% 	% 	%s<   =O%O;OOOO	OO	OO(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                  } |       }| }	|	st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }
t!        t        j"                  |
            dx}x}x}x}}	y# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w)u=   .done.notified 파일이 절대 생성되지 않는지 확인r]   r^   r_   r   c                 L   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   ra   rb   c              3   2   K   | ]  }t        |        y wrd   re   rf   s     r,   ri   zaTestDoneProtocolIntegration.test_no_done_notified_created.<locals>.side_effect.<locals>.<genexpr>  rj   rk   rl   rm   Frn   rs   rt   ru   r~   s        r,   r   zNTestDoneProtocolIntegration.test_no_done_notified_created.<locals>.side_effect  r   rW   r   r   Tr   r   r   z
task-035.1r   r   r   r   Nztask-035.1.done.notifiedr   r   r   r   )r#   r   r   r   r   r   r   r$   r   r   r   r   r   r   r   r    r!   r"   )r&   r[   r   r   r   r'   r(   rO   r   r   rP   s              r,   test_no_done_notified_createdz9TestDoneProtocolIntegration.test_no_done_notified_created  so   	V 	F 	f 	 	   +(83
5 *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% "<vJ!;;v;CCvCEvEEvEvvGvvvvvvvJvvvJvvv!;vvvCvvvEvvvvvvv	% 	% 	% 	% 	% 	%s<   F1&%F%F F%(F1F"F%%F.	*F11F;c           	      R   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       |j                  D cg c]*  }t        |d   d   t              s|d   d   d   dk(  s)|, }}t        |      }d}||k\  }	|	st        j                  d|	fd||f      dt        j                          v st        j"                  t              rt        j$                  t              nddt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }
t        j&                  d      dz   d|
iz  }t)        t        j*                  |            dx}x}	}|d   d   d   }d|v r|j-                  d      nd}d}||k\  }|st        j                  d|fd||f      d t        j                          v st        j"                  |      rt        j$                  |      nd t        j$                  |      d!z  }t        j&                  d"      d#z   d$|iz  }t)        t        j*                  |            dx}}||dz      }d}||v }|st        j                  d%|fd&||f      t        j$                  |      d't        j                          v st        j"                  |      rt        j$                  |      nd'd(z  }t        j&                  d)|       d#z   d$|iz  }t)        t        j*                  |            dx}}d*}||v }|st        j                  d%|fd&||f      t        j$                  |      d't        j                          v st        j"                  |      rt        j$                  |      nd'd(z  }t        j&                  d+|       d#z   d$|iz  }t)        t        j*                  |            dx}}d,}||v}|st        j                  d-|fd.||f      t        j$                  |      d't        j                          v st        j"                  |      rt        j$                  |      nd'd(z  }t        j&                  d/|       d#z   d$|iz  }t)        t        j*                  |            dx}}d0}||v}|st        j                  d-|fd.||f      t        j$                  |      d't        j                          v st        j"                  |      rt        j$                  |      nd'd(z  }t        j&                  d1|       d#z   d$|iz  }t)        t        j*                  |            dx}}y# 1 sw Y   _xY w# 1 sw Y   dxY w# 1 sw Y   ixY wc c}w )2uT   독립 작업에서 send_telegram이 호출되고 wake_anu가 호출되지 않는지r]   r^   r_   r   c                 L   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   ra   rb   c              3   2   K   | ]  }t        |        y wrd   re   rf   s     r,   ri   zqTestDoneProtocolIntegration.test_independent_task_sends_telegram_not_wake.<locals>.side_effect.<locals>.<genexpr><  rj   rk   rl   rm   Frn   rs   rt   ru   r~   s        r,   r   z^TestDoneProtocolIntegration.test_independent_task_sends_telegram_not_wake.<locals>.side_effect7  r   rW   r   r   Tr   r   r   z
task-036.1r   r   r   r   Nr   r   r   r   r   rH   r   rJ   uE   독립 작업에서 send_telegram_notification이 호출되어야 함r   rK   r   r   )z%(py0)s >= %(py3)sr   r
   u#   cokacdir 명령에 --cron이 없음r   r   r2   r4   r   r6   u    메시지에 task_id가 없음: r   u!   메시지에 '완료'가 없음: r   r   r   u3   wake_anu_session 구형 프롬프트가 전송됨: zdone.notifiedu-   done.notified 참조 메시지가 전송됨: )r#   r   r   r   r   r   r   r$   r   r   rx   ry   rH   r   r<   r   r   r   r    r   r!   r"   r   )r&   r[   r   r   r   rh   r   r@   r)   rO   rB   rP   r   r   r'   rA   r*   r   r?   s                      r,   -test_independent_task_sends_telegram_not_wakezITestDoneProtocolIntegration.test_independent_task_sends_telegram_not_wake3  s   	V 	F 	f 	 	   +(83
5 *5|DE	%JJ|&8*%EF	% LL*,<c(mL	%
 ""$	% 	% 	% &.%<%<w
1Q4PQ7TX@Y^_`a^bcd^efg^hlv^v!ww>"pap"a'ppp"appppppspppspppppp>ppp>ppp"pppappp)pppppppp &a(+A.3;|3K<%%h/QSCx1}CCCx1CCCCCCxCCCxCCC1CCCCCCCCCC8a<(L|s"LLL|sLLL|LLLLLLsLLLsLLLL&Fse$LLLLLLLIx3IIIx3IIIxIIIIII3III3IIII"CC5 IIIIIII c|3&ccc|3ccc|cccccc3ccc3cccc*]^a]b(ccccccc`c)```c`````````c```c````-Z[^Z_+```````+	% 	% 	% 	% 	% 	% xsN   X&%X
W= X
(XX$"X$1X$=XX

X	XX!)rR   rS   rT   rU   r   r   r   r   r   r   r   r   r   rV   rW   r,   rY   rY   I   s+   K
0wY 0wRV 0w[_ 0w 0wd >m	 >m]a >mfj >m >m@$kT $kd $kL 'qy 'q\` 'qei 'q 'qR  wi  w4  wTX  w  wD -ai -a[_ -adh -a -arW   rY   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 기반)r   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&   r   r   r   r   r   escalated_paths          r,   _simulate_stale_done_escalationz4TestDoneWatcherLogic._simulate_stale_done_escalationg  sP     G9E!22	#	&AA!  "222rW   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   r   rename)r&   r   r   r   r   
acked_paths         r,   _simulate_acked_cleanupz,TestDoneWatcherLogic._simulate_acked_cleanupx  s_      WI["99
  "b dT:kwi{,CCDrW   r   Nc           
      |   |dz  dz  }|j                  dd       d}|| dz  j                  dd	       | j                  }d
} ||||      }d}||u }|sWt        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}x}x}}| j                  }d} ||||      }d}||u }|sWt        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}x}x}}y)u0   .done 파일 30분 이상 → 에스컬레이션r   r   Tr   z
task-050.1r   {}r/   r0      r   isz%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s._simulate_stale_done_escalation
}(%(py3)s, %(py4)s, age_minutes=%(py6)s)
} is %(py11)sr&   r   r   r   r   r   r   r:   rK   py11assert %(py13)spy13N<   r   rL   r   r   r<   r   r   r   r    r!   r"   r&   r   r   r   r'   r)   r   @py_assert10@py_assert9@py_format12@py_format14s              r,   test_stale_done_escalationz/TestDoneWatcherLogic.test_stale_done_escalation  s   (83
5		'	'33D73K 33`UW`3JUWX`\``X\`````X\```````t```t```3``````J```J````````````UW```X```\````````33`UW`3JUWX`\``X\`````X\```````t```t```3``````J```J````````````UW```X```\`````````rW   c           
      |   |dz  dz  }|j                  dd       d}|| dz  j                  dd	       | j                  }d
} ||||      }d}||u }|sWt        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}x}x}}| j                  }d} ||||      }d}||u }|sWt        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}x}x}}y)u2   .done 파일 30분 미만 → 아무 동작 없음r   r   Tr   z
task-051.1r   r   r/   r0      r   Fr   r   r&   r   r   r   r   r   Nr   r   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3aUWa3JUWXa\aaX\aaaaaX\aaaaaaataaataaa3aaaaaaJaaaJaaaaaaaaaaaaUWaaaXaaa\aaaaaaaa33`UV`3JUVW`[``W[`````W[```````t```t```3``````J```J````````````UV```W```[`````````rW   c           
         |dz  dz  }|j                  dd       d}|| dz  j                  dd	       || d
z  j                  dd	       | j                  }d} ||||      }d}||u }|sWt        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}x}x}}y)u/   .done.escalated 존재 시 중복 알림 없음r   r   Tr   z
task-052.1r   r   r/   r0   r   r   r   Fr   r   r&   r   r   r   r   r   Nr   r   s              r,   (test_escalated_marker_prevents_duplicatez=TestDoneWatcherLogic.test_escalated_marker_prevents_duplicate  sN   (83
5		'	'33D73K		1	1==dW=U 33aUWa3JUWXa\aaX\aaaaaX\aaaaaaataaataaa3aaaaaaJaaaJaaaaaaaaaaaaUWaaaXaaa\aaaaaaaaarW   c                    |dz  dz  }|j                  dd       |dz  dz  }d}|| dz  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}}| d}||z  }
|
j                  } |       }|st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}
x}}| 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}}| d}||z  }
|
j                  } |       }| }|st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}
x}x}}| d}||z  }
|
j                  } |       }|st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}
x}}y)u.   .done.acked 24시간 이상 → archive 이동r   r   Tr   archivez
task-053.1r   r   r/   r0      )r   Fr   )z%(py0)s is %(py3)smovedr
   r   r   Nu2   24시간 미만에는 archive 이동 없어야 함zO
>assert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}r   r   r   u7   24시간 이상이면 events/에서 제거되어야 함r   u   archive/로 이동되어야 함r   )r   rL   r   r   r<   r   r   r   r    r!   r"   r   r   )r&   r   r   r   r   r   r@   r'   rA   r*   r(   rO   r   @py_format8r   rP   s                   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u~uuu 'y4t
44t4<<t<>t>tt@ttttttt
ttt
ttt4ttt<ttt>tttttt ,,Zg_a,bu}uuu$+9K!8}J!88}8@@}@B}BB}B}}D}}}}}}}J}}}J}}}!8}}}@}}}B}}}}}}}!(	5b55b5==b=?b?bbAbbbbbbbbbbbbb5bbb=bbb?bbbbbbrW   )r   )rR   rS   rT   rU   r   r$   intboolr   r   r   r   r   r  rV   rW   r,   r   r   d  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rW   r   )-rU   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r{   ossyspathlibr   unittest.mockr   r   pytest__file__parent_SCRIPTS_DIRimportlib.util	importlib_MODULE_PATHutilspec_from_file_locationr	   r@   r'   r<   r   r   r    rA   r*   r!   r"   module_from_specr   loaderrO   r(   r  exec_moduler   rY   r   rV   rW   r,   <module>r     sg  	   	 
  *  H~$$++ 44~~--.A<P t4   t4     t   t   4      NN33D9 {{ $ {$   {$     t   t   {  $         ) *$ $NXa XavWc WcrW   