
    iFg                    .   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mZ  ed      ZddZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZddZ	 	 d 	 	 	 	 	 	 	 	 	 d!d	Zd"d#d
Zd$dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%y)%u~  
tests/test_watchdog_chairman_definition.py

task-2405 회귀 테스트 — 회장 정의 FALSE positive 5 case 알람 0건 보장
session-watchdog.sh 4 fix(A/B/C/D) 기반

회장 정의 (2026-05-03): TRUE positive(진짜 죽음)만 알람
FALSE positive 절대 0건 5 case:
  1. 진행 중 작업 (long-running)
  2. 완료 작업 (.done 발급)
  3. 회장 인지 (.escalate / .escalate.acked 발급)
  4. 후속 task 위임됨 (.superseded_by 마커 또는 다른 task md 언급)
  5. 진행 마커 (codex-gate, qc-done, done.merging, pr-creating, external-running)

시나리오:
  OK 케이스 (skip 검증, 알람 0건):
   1. test_escalate_marker_skips_chairman_def
   2. test_escalate_acked_skips_chairman_def
   3. test_escalate_and_acked_both_skips
   4. test_done_file_skips_and_status_promoted
   5. test_done_acked_skips_and_status_promoted
   6. test_done_notified_skips_and_status_promoted
   7. test_done_clear_skips
   8. test_superseded_by_marker_skips
   9. test_other_task_md_mentions_original_skips
  10. test_progress_marker_codex_gate_skips
  11. test_progress_marker_qc_done_skips
  12. test_progress_marker_done_merging_skips
  13. test_progress_marker_pr_creating_skips
  14. test_progress_marker_external_running_skips

  NG 케이스 (TRUE positive 검증, 알람 1건):
  15. test_truly_stalled_no_marker_alerts

  종합 검증:
  16. test_chairman_5_ng_cases_all_zero_alarm
    )annotationsN)Pathz//home/jay/workspace/scripts/session-watchdog.shc                
    d| iS )u   task-timers.json 포맷.tasks )r   s    >/home/jay/workspace/tests/test_watchdog_chairman_definition.py_build_timersr	   6   s    U    c                    t        j                  dt        j                  t        j                          |z               }| |d||dddS )uI   status=running 태스크 항목. start_time은 현재 - start_offset 초.z%Y-%m-%dT%H:%M:%S.000000runningr      )task_idteam_idstatus
start_time	task_fileretry_count	max_retry)timestrftime	localtime)r   r   r   start_offsetstart_tss        r   _running_taskr   ;   sM     }}"tyy{\12H
  r
   c                   dD ]  }| |z  j                  dd        | dz  dz  j                  t        j                  |      d       | dz  j                  d	d       | dz  d
z  j                  dd       t        j                  d      }|j                  dd|  d      }| dz  dz  }|j                  |d       |j                  d       |S )u   
    tmp_path 아래 필수 디렉토리·파일을 생성하고
    WORKSPACE가 tmp_path를 가리키도록 패치된 스크립트를 반환.
    )zmemory/eventszmemory/heartbeatszmemory/taskslogsscriptsT)parentsexist_okmemorytask-timers.jsonutf-8encodingz	.env.keyszANU_BOT_TOKEN=dummy
ztask-timer.pyz#!/usr/bin/env python3
zWORKSPACE="/home/jay/workspace"zWORKSPACE=""r   zsession-watchdog.shi  )mkdir
write_textjsondumpsORIG_SCRIPT	read_textreplacechmod)tmp_pathtimersdorigpatchedscript_paths         r   setup_workspacer4   Q   s   
 : 
ATD9: --99

6W : 
 ''(?''R ?*66"W 7 
   ' 2Dll)
hZq!G Y&)>>K7W5er
   c           	     H   t         j                  j                         }d|d<   |r|j                  |       t	        j
                  dt        |       gddt        |xs |      |d      }|dz  dz  }|j                         r|j                  d	
      nd}|j                  |fS )uZ   
    WATCHDOG_DRY_RUN=1로 스크립트 실행 후 (returncode, log_contents) 반환.
    1WATCHDOG_DRY_RUNbashT   )capture_outputtextcwdenvtimeoutr   zsession-watchdog.logr"   r#    )
osenvironcopyupdate
subprocessrunstrexistsr+   
returncode)r3   r.   	extra_envr<   r=   resultlog_filelog_contents           r   run_watchdogrM   y   s     **//
C!C

9^^	[!"x F & #99H:B//:K($$g$6QSKk))r
   c                    | j                          |dkD  r0t        j                         |z
  }t        j                  | ||f       yy)u<   파일 생성 후 mtime을 (현재 - age_seconds)로 설정.r   N)touchr   r@   utime)pathage_secondsts      r   
touch_filerT      s9    JJLQIIK+%
1v r
   c                t    t        j                  | j                               d   |   j                  dd      S )uM   task-timers.json에서 특정 task의 status 읽기 (Fix B 박제 검증용).r   r   r   )r(   loadsr+   get)timers_filetids     r   _read_statusrZ      s1    ::k++-.w7<@@9UUr
   c                	   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}}g }d}||v }|}|sd}||v }|}|sqt        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  }|j                  |       |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  }|j                  |       t        j                  |d      i z  }t        j                  d|       d z   d!|iz  }t        t        j                  |            dx}x}x}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  }	t        j                  d&|       d'z   d|	iz  }
t        t        j                  |
            dx}}g }d(}||v }|}|s| d"}||v}|}|sqt        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  }|j                  |       |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  }|j                  |       t        j                  |d      i z  }t        j                  d*|       d z   d!|iz  }t        t        j                  |            dx}x}x}x}x}}y)+u   
    task-2405 회장 정의 Fix A:
    .escalate 단독 마커 존재 → skip, 로그에 '알람 억제' 포함 (알람 0건).
    회장 승인 대기 상태에서는 절대 알람 없음.
    z
task-cd001	dev2-teamr    
heartbeats
.heartbeat  rR   events	.escalater   ==z%(py0)s == %(py3)srcpy0py3assert %(py5)spy5Nu   알람 억제u   회장 승인 대기in)z%(py3)s in %(py5)slog)ri   rk   z%(py7)spy7)z%(py10)s in %(py12)s)py10py12z%(py14)spy14   u   escalate 억제 로그 없음: z
>assert %(py17)spy17(team=not inz%(py1)s not in %(py3)spy1ri   uK   escalate 단독 상태에서 stalled 알람 발생 (회장 정의 위반): 
>assert %(py5)su   알람 없음)z%(py10)s not in %(py12)su    알람 발생 (FALSE positive): )r	   r   r4   rT   rM   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationappend_format_boolop_format_assertmsg)r.   rY   r/   r3   hbrf   rn   @py_assert2@py_assert1@py_format4@py_format6@py_assert4@py_assert0@py_assert9@py_assert11@py_format8@py_format13@py_format15@py_format16@py_format18s                       r   'test_escalate_marker_skips_chairman_defr      sk    CCsK!@ABF!(F3K 
H	|	+Z.@	@Brt$ x("X-3%y0AAB;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN0? 0?c! 0%; 0%;s%B 0 0//0?c 0 0&/i  0 0)/0 0// " 0 0&/i " 0 0 0)/0)/0//0%;s 0 0&/i &< 0 0)/0 0// @C 0 0&/i @C 0 0 0)/0)/0!/0 0//
)#/0 0 0//0 0 0U&> \>$ \J[J[\> \ \R[R[  \ \U[U[\ \C[C[ "% \ \R[R[ "% \ \J[J[
UVYUZ[\ \ \H[H[\ \1? 1?c! 1uF^ 1^3%> 1 1001?c 1 1'0y  1 1*0&1 100 " 1 1'0y " 1 1 1*0&1*01001^3 1 1'0y &4 1 1*0&1 100 <? 1 1'0y <? 1 1 1*0&1*01"0.1 100
*3%01 1 1001 1 1r
   c                H   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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      d   }||v}|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}}yy)u   
    task-2405 회장 정의 Fix A 핵심:
    .escalate.acked 존재 → 회장이 이미 인지 = 알람 그만 → skip.
    acked = 회장 인지 = 더 이상 알람 불필요.
    z
task-cd002r\   r    r]   r^   r_   r`   ra   .escalate.ackedr   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   uQ   escalate.acked 상태에서 stalled 알람 발생 (회장 정의 핵심 위반): r{   DRY_RUNrs   )z%(py0)s not in %(py3)srY   u9   DRY_RUN 알람 본문에 tid 포함됨 (FALSE positive): )r	   r   r4   rT   rM   r|   r}   r~   r   r   r   r   r   r   splitr.   rY   r/   r3   r   rf   rn   r   r   r   r   r   s               r   &test_escalate_acked_skips_chairman_defr      sa    CCsK!@ABF!(F3K 
H	|	+Z.@	@Brt$ x("X-3%0GGH;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> b>$ bPaPab> b bXaXa  b b[a[ab bIaIa "% b bXaXa "% b bPaPa
[\_[`ab b bNaNab b C))I.q1 	Ns11 	N<M<M	Ns1 	N 	NGMv	N 	N5M5M  	N 	NDMI  	N 	NDMI 2 	N 	N<M<MGuM	N 	N 	N:M:M	N 	N r
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       | dz  dz  }t        || d	z         t        || d
z         t	        ||       \  }}d}||k(  }	|	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}||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}}y)ur   
    task-2405 회장 정의 Fix A:
    .escalate + .escalate.acked 둘 다 있어도 → skip (알람 0건).
    z
task-cd003r\   r    r]   r^   r_   r`   ra   rb   r   r   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   uN   escalate+acked 모두 있는데 stalled 알람 발생 (회장 정의 위반): r{   r	   r   r4   rT   rM   r|   r}   r~   r   r   r   r   r   r   )r.   rY   r/   r3   r   
events_dirrf   rn   r   r   r   r   r   s                r   "test_escalate_and_acked_both_skipsr      s   
 CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$H$x/Jzse9--.zse?334;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> _>$ _M^M^_> _ _U^U^  _ _X^X^_ _F^F^ "% _ _U^U^ "% _ _M^M^
XY\X]^_ _ _K^K^_ _r
   c                F   d}t        |t        |d      i      }t        | |      }| dz  dz  }| dz  dz  | dz  }t        |d       t        | dz  d	z  | d
z         t	        ||       \  }}d}||k(  }	|	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}||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}}t        ||      }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      dz   d|
iz  }t        t        j                  |            dx}	}y)u   
    task-2405 회장 정의 Fix B:
    .done 파일 존재 → 완료 처리 skip + task-timers.json에 status=escalated 박제.
    z
task-cd004r\   r    r!   r]   r^   r_   r`   ra   .doner   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   u>   .done 있는데 stalled 알람 발생 (회장 정의 위반): r{   	escalatedstatus_afteru;   .done 후 status 박제 실패 (기대: escalated, 실제: )r	   r   r4   rT   rM   r|   r}   r~   r   r   r   r   r   r   rZ   r.   rY   r/   r3   rX   r   rf   rn   r   r   r   r   r   r   s                 r   (test_done_file_skips_and_status_promotedr   
  s[   
 CCsK!@ABF!(F3KX%(::K	H	|	+Z.@	@Brt$ x("X-3%u=>;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> O>$ O=N=NO> O OENY  O OHNO O6N6N "% O OENY "% O O=N=N
HNO O O;N;NO O  S1L& V<;& VDUDUV<; V VOUvV V=U=U  V VLUI  V VLUI ' V VDUDU
El^STUV V VBUBUV Vr
   c                D   d}t        |t        |d      i      }t        | |      }| dz  dz  }| dz  dz  | dz  }t        |d       t        | dz  d	z  | d
z         t	        ||       \  }}d}||k(  }	|	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}||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}}t        ||      }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}	}y)uc   
    task-2405 회장 정의 Fix B:
    .done.acked 존재 → skip + status=escalated 박제.
    z
task-cd005r\   r    r!   r]   r^   r_   r`   ra   z.done.ackedr   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   u-   .done.acked 있는데 stalled 알람 발생: r{   r   r   u&   .done.acked 후 status 박제 실패: r   r   s                 r   )test_done_acked_skips_and_status_promotedr   +  sE   
 CCsK!@ABF!(F3KX%(::K	H	|	+Z.@	@Brt$x("X-3%{0CCD;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> >>$ >,=,=>> > >4=I  > >7=v> >%=%= "% > >4=I "% > >,=,=
7u=> > >*=*=> >  S1L& @<;& @.?.?@<; @ @9?@ @'?'?  @ @6?i  @ @6?i ' @ @.?.?
0?@ @ @,?,?@ @r
   c                D   d}t        |t        |d      i      }t        | |      }| dz  dz  }| dz  dz  | dz  }t        |d       t        | dz  d	z  | d
z         t	        ||       \  }}d}||k(  }	|	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}||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}}t        ||      }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}	}y)u   
    task-2405 회장 정의 Fix B 신규 마커:
    .done.notified 존재 → skip + status=escalated 박제.
    notified = 완료 알림 발송됨 = 알람 불필요.
    z
task-cd006r\   r    r!   r]   r^   r_   r`   ra   z.done.notifiedr   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   uP   .done.notified 있는데 stalled 알람 발생 (Fix B 신규 마커 미처리): r{   r   r   u)   .done.notified 후 status 박제 실패: r   r   s                 r   ,test_done_notified_skips_and_status_promotedr   J  s^    CCsK!@ABF!(F3KX%(::K	H	|	+Z.@	@Brt$ x("X-3%~0FFG;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> a>$ aO`O`a> a aW`W`  a aZ`Z`a aH`H` "% a aW`W` "% a aO`O`
Z[^Z_`a a aM`M`a a  S1L& C<;& C1B1BC<; C C<BFC C*B*B  C C9B  C C9B ' C C1B1B
3L>BC C C/B/BC Cr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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}}y)ue   
    task-2405 회장 정의 Fix B:
    .done.clear 존재 → 완료 처리 skip (알람 0건).
    z
task-cd007r\   r    r]   r^   r_   r`   ra   z.done.clearr   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   u-   .done.clear 있는데 stalled 알람 발생: r{   r   r   s               r   test_done_clear_skipsr   k  sm   
 CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$x("X-3%{0CCD;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> >>$ >,=,=>> > >4=I  > >7=v> >%=%= "% > >4=I "% > >,=,=
7u=> > >*=*=> >r
   c                D   d}t        |t        |d      i      }t        | |      }| dz  dz  }| dz  dz  | dz  }t        |d       t        | dz  d	z  | d
z         t	        ||       \  }}d}||k(  }	|	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}||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}}t        ||      }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}	}y)u   
    task-2405 회장 정의 Fix C:
    <task_id>.superseded_by 마커 존재 → 후속 task에 위임됨 → skip + 박제.
    z
task-cd008r\   r    r!   r]   r^   r_   r`   ra   .superseded_byr   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   uF   .superseded_by 마커 있는데 stalled 알람 발생 (Fix C 위반): r{   r   r   u)   .superseded_by 후 status 박제 실패: r   r   s                 r   test_superseded_by_marker_skipsr     s\   
 CCsK!@ABF!(F3KX%(::K	H	|	+Z.@	@Brt$ x("X-3%~0FFG;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> W>$ WEVEVW> W WMVY  W WPVPVW W>V>V "% W WMVY "% W WEVEV
PQTPUVW W WCVCVW W  S1L& C<;& C1B1BC<; C C<BFC C*B*B  C C9B  C C9B ' C C1B1B
3L>BC C C/B/BC Cr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  }| dz  dz  | dz  }t        |d       | dz  d	z  | d
z  j	                  dd       | dz  d	z  dz  j	                  d| dd       t        ||       \  }}d}||k(  }	|	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}||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}}t        ||      }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}	}y)#u   
    task-2405 회장 정의 Fix C 2순위:
    후속 task md 본문에 원본 task_id 언급 → 후속 위임됨으로 판단 → skip + 박제.
    z
task-cd009r\   r    r!   r]   r^   r_   r`   r   z.mdu6   # Original task
---
team: dev2-team
---
작업 내용
r"   r#   ztask-9999.mdu    # 후속 task
## 배경
원본: u    실패 후 재작업
r   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   uJ   후속 task md 언급인데 stalled 알람 발생 (Fix C 2순위 위반): r{   r   r   u0   후속 task md 언급 후 status 박제 실패: )r	   r   r4   rT   r'   rM   r|   r}   r~   r   r   r   r   r   r   rZ   r   s                 r   *test_other_task_md_mentions_original_skipsr     s   
 CCsK!@ABF!(F3KX%(::K	H	|	+Z.@	@Brt$ 7"uC[0<<
E =  7"^3??
,SE1HI @ 
 ;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNU&> [>$ [IZIZ[> [ [QZQZ  [ [TZTZ[ [BZBZ "% [ [QZQZ "% [ [IZIZ
TUXTYZ[ [ [GZGZ[ [  S1L& J<;& J8I8IJ<; J JCI6J J1I1I  J J@I	  J J@I	 ' J J8I8I
:<.IJ J J6I6IJ Jr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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}}y)u   
    task-2405 회장 정의 5번 (진행 마커):
    events/<tid>.codex-gate 존재 + heartbeat 노후 → alive (알람 0건).
    long-running 단계 보호 — Codex G1/G2 검증 중.
    z
task-cd010r\   r    r]   r^   r_   r`   ra   .codex-gater   rc   re   rf   rg   rj   rk   Nalive (long-running)rl   z%(py1)s in %(py3)srn   ry   u'   codex-gate 마커 alive 로그 없음: r{   ru   rv   rx   u6   codex-gate 진행 마커인데 stalled 알람 발생: r   r   s               r   %test_progress_marker_codex_gate_skipsr     s)    CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$x("X-3%{0CCD;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN! 8!S( 8&7&78!S 8 8.7i " 8 8178 877 &) 8 8.7i &) 8 8&7&7
1#78 8 8$7$78 8U&> G>$ G5F5FG> G G=FY  G G@FG G.F.F "% G G=FY "% G G5F5F
@FG G G3F3FG Gr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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}}y)u   
    task-2405 회장 정의 5번:
    events/<tid>.qc-done 존재 + heartbeat 노후 → alive (알람 0건).
    QC 진행 중 단계 보호.
    z
task-cd011r\   r    r]   r^   r_   r`   ra   z.qc-doner   rc   re   rf   rg   rj   rk   Nr   rl   r   rn   ry   u$   qc-done 마커 alive 로그 없음: r{   ru   rv   rx   u3   qc-done 진행 마커인데 stalled 알람 발생: r   r   s               r   "test_progress_marker_qc_done_skipsr     s)    CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$x("X-3%x0@@A;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN! 5!S( 5#4#45!S 5 5+49 " 5 5.4f5 544 &) 5 5+49 &) 5 5#4#4
.se45 5 5!4!45 5U&> D>$ D2C2CD> D D:C)  D D=CVD D+C+C "% D D:C) "% D D2C2C
=cUCD D D0C0CD Dr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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}}y)u   
    task-2405 회장 정의 5번:
    events/<tid>.done.merging 존재 + heartbeat 노후 → alive (알람 0건).
    G3 머지 진행 중 단계 보호.
    z
task-cd012r\   r    r]   r^   r_   r`   ra   z.done.mergingr   rc   re   rf   rg   rj   rk   Nr   rl   r   rn   ry   u)   done.merging 마커 alive 로그 없음: r{   ru   rv   rx   u8   done.merging 진행 마커인데 stalled 알람 발생: r   r   s               r   'test_progress_marker_done_merging_skipsr   	  s)    CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$x("X-3%}0EEF;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN! :!S( :(9(9:!S : :09	 " : :396: :!9!9 &) : :09	 &) : :(9(9
3C59: : :&9&9: :U&> I>$ I7H7HI> I I?Hy  I IBH&I I0H0H "% I I?Hy "% I I7H7H
B3%HI I I5H5HI Ir
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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}}y)u   
    task-2405 회장 정의 5번:
    events/<tid>.pr-creating 존재 + heartbeat 노후 → alive (알람 0건).
    PR 생성 중 단계 보호 (신규 마커).
    z
task-cd013r\   r    r]   r^   r_   r`   ra   z.pr-creatingr   rc   re   rf   rg   rj   rk   Nr   rl   r   rn   ry   u(   pr-creating 마커 alive 로그 없음: r{   ru   rv   rx   u7   pr-creating 진행 마커인데 stalled 알람 발생: r   r   s               r   &test_progress_marker_pr_creating_skipsr   &  s)    CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$x("X-3%|0DDE;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN! 9!S( 9'8'89!S 9 9/8y " 9 928&9 9 8 8 &) 9 9/8y &) 9 9'8'8
23%89 9 9%8%89 9U&> H>$ H6G6GH> H H>Gi  H HAGH H/G/G "% H H>Gi "% H H6G6G
A#GH H H4G4GH Hr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t        | dz  dz  | d	z         t	        ||       \  }}d
}||k(  }|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}||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}}y)u   
    task-2405 회장 정의 5번:
    events/<tid>.external-running 존재 + heartbeat 노후 → alive (알람 0건).
    외부 CLI 호출 중 단계 보호 (신규 마커).
    z
task-cd014r\   r    r]   r^   r_   r`   ra   .external-runningr   rc   re   rf   rg   rj   rk   Nr   rl   r   rn   ry   u-   external-running 마커 alive 로그 없음: r{   ru   rv   rx   u<   external-running 진행 마커인데 stalled 알람 발생: r   r   s               r   +test_progress_marker_external_running_skipsr   C  s*    CCsK!@ABF!(F3K	H	|	+Z.@	@Brt$x("X-3%7H0IIJ;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN! >!S( >,=,=>!S > >4=I " > >7=v> >%=%= &) > >4=I &) > >,=,=
7u=> > >*=*=> >U&> M>$ M;L;LM> M MCL9  M MFLfM M4L4L "% M MCL9 "% M M;L;L
FseLM M M9L9LM Mr
   c                   d}t        |t        |d      i      }t        | |      }| dz  dz  | dz  }t        |d       t	        ||       \  }}d}||k(  }|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}||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}}||v }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nd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}y)u  
    task-2405 회장 정의 TRUE positive:
    모든 마커 부재 + heartbeat 노후 + events 노후 + PR/worktree 부재 → 알람 1건.
    ★ 이 케이스만이 진짜 죽음 = 알람이 발생해야 정상.

    조건:
    - .escalate 없음
    - .escalate.acked 없음
    - .done 계열 없음
    - .superseded_by 없음
    - 진행 마커 없음
    - heartbeat 2000s 노후 (임계 초과)
    - events 파일 없음 (activity 없음)
    - gh/git worktree 없음 (DRY_RUN 환경)
    z
task-cd015	dev1-teamr    r]   r^   r_   r`   r   rc   re   rf   rg   rj   rk   NSTALLEDrl   r   rn   ry   u5   TRUE positive 케이스에서 STALLED 판정 없음: r{   r   uH   TRUE positive 케이스에서 알람 미발생 (watchdog 무력화됨): )z%(py0)s in %(py2)srY   )rh   py2u.   TRUE positive tid가 알람 본문에 없음: z
>assert %(py4)spy4r   )r.   rY   r/   r3   r   rf   rn   r   r   r   r   r   @py_format3@py_format5s                 r   #test_truly_stalled_no_marker_alertsr   e  s     CCsK!@ABF!(F3K 
H	|	+Z.@	@Brt$ ;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNNZ9ZZZ9ZZZ9ZZZZZZZZZZZZZTUXTYZZZZZZZm9mmm9mmm9mmmmmmmmmmmmmghkglmmmmmmm#:MMM3#MMMMMM3MMM3MMMMMM#MMM#MMMMGuMMMMMMMr
   c                d   d}d}d}d}d}t        |t        |d      |t        |d      |t        |d      |t        |d      |t        |d      i      }t        | |      }| dz  dz  }| dz  d	z  }	|||||fD ]  }
t        |	|
 d
z  d        t        || dz         t        || dz         t        || dz         t        || dz         t        || dz         t	        ||       \  }d}||k(  }|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}}|||||f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        d!z   d|iz  }t        t        j                  |            dx}} d"v rd"v rj                  d"      d#   nd$}|||||f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'       d!z   d|iz  }t        t        j                  |            dx}} t        fd(|||||f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+       d!z   d|iz  }t        t        j                  |            dx}}y),u  
    task-2405 회장 정의 종합 검증:
    5가지 FALSE positive 케이스를 5개 task로 한번에 실행 → 총 알람 0건.

    task-cd020: 진행 중 작업 (long-running, codex-gate 마커)
    task-cd021: 완료 작업 (.done 발급)
    task-cd022: 회장 인지 (.escalate.acked)
    task-cd023: 후속 task 위임됨 (.superseded_by)
    task-cd024: 진행 마커 (external-running)
    z
task-cd020z
task-cd021z
task-cd022z
task-cd023z
task-cd024r\   r    ra   r]   r^   r_   r`   r   r   r   r   r   r   rc   re   rf   rg   rj   rk   Nru   rv   rx   rn   ry   u   [종합검증] u:    알람 발생 (FALSE positive — 회장 정의 위반): r{   r   rs   r?   dry_run_sectionu(   [종합검증] DRY_RUN 알람 본문에 u    포함됨 (FALSE positive): c              3  F   K   | ]  }j                  | d         yw)ru   N)count).0rY   rn   s     r   	<genexpr>z:test_chairman_5_ng_cases_all_zero_alarm.<locals>.<genexpr>  s(       			SE.!s   !stalled_countu)   [종합검증] 5 FALSE positive case 중 u   건 알람 발생: )r	   r   r4   rT   rM   r|   r}   r~   r   r   r   r   r   r   r   sum)r.   tid_long_runningtid_done	tid_ackedtid_supersededtid_progressr/   r3   r   hb_dirrY   rf   r   r   r   r   r   r   r   rn   s                      @r   'test_chairman_5_ng_cases_all_zero_alarmr     sq    $HI!NL-(8+F-+6=K8nkBmL+> F "(F3KH$x/J </F !(I~|T B6se:..DAB z/0<<= zxj../ zyk99: z~.n==> z|n,=>>?;1GBN27NNN2NNNNNN2NNN2NNNNNNNNNN !(I~|T cf~ 	c~S( 	cQbQb	c~S 	c 	cYbYb  	c 	c\b\b	c 	cJbJb &) 	c 	cYbYb &) 	c 	cQbQbocU"\]`\ab	c 	c 	cObOb	c 	cc
 C5>#5E#))I.q12$h	><X 	cCU&> c>8 cQbQbc> c cYbYb " c c\b\bc cJbJb *9 c cYbYb *9 c cQbQb:3%?\]`\abc c cObObc c	c
  $h	><X M  \=A \J[J[\=A \ \U[U[\ \C[C[  \ \R[R[  \ \R[R[  \ \J[J[
3M?BUVYUZ[\ \ \H[H[\ \r
   )r   dictreturnr   )r   r?   i)
r   rF   r   rF   r   rF   r   intr   r   )r.   r   r/   r   r   r   )NN)
r3   r   r.   r   rI   zdict | Noner<   zPath | Noner   ztuple[int, str])r   )rQ   r   rR   r   r   None)rX   r   rY   rF   r   rF   )&__doc__
__future__r   builtinsr~   _pytest.assertion.rewrite	assertionrewriter|   r(   r@   rD   r   pathlibr   r*   r	   r   r4   rM   rT   rZ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
   r   <module>r      s&  $L #    	    DE 	  	
 
,%V "	*** * 
	*
 *8V1BNB_8VB@>CB>4CB!JRG:D:I:H:MD"N^F\r
   