
    + jb9                       d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
Z
 e e	e      j                         j                  d         Zeej                   vrej                   j#                  de       ddlmZmZmZmZmZmZmZ e
j4                  d        Ze
j4                  d        Ze
j4                  d	        Zdd
ZddZ	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ dddZ!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+y)u  task-2534 회귀 테스트: data_loader 자동머지 시그널 병합 (traffic_light_fix_b)

회장 §결정(2026-05-10) 신호등 sync fix B — dashboard/data_loader.py가 task-timers.json만이
아니라 cron schedule_history + events/*.merge-queue.json 시그널을 병합해 활성/유휴 판정.

검증 포인트 (회귀 8건):
    1. timers running → 작업중 (heartbeat fresh + PID alive)
    2. cron 발사 후 timers stale → 작업중 (cron 시그널이 idle 덮어씀)
    3. merge-queue HEAD 있음 → 작업중
    4. 모든 시그널 부재 → 유휴
    5. heartbeat 가장 최근 source 우선 (cron > mq > heartbeat priority 검증)
    6. chat=6937032012 격리 (다른 chat schedule_history 무시)
    7. token raw 0 (prompt/response/schedule_id 절대 결과 dict에 노출 X)
    8. task-2528+1 / task-2530 / task-2531 fixture 회귀 (회장 발견 사례 3건 박제)
    )annotationsN)Path   )DASHBOARD_CHAT_IDHEARTBEAT_FRESH_SECONDSSIGNAL_FRESHNESS_SECONDS_PidLivenessProvider_collect_cron_schedule_signals_collect_merge_queue_signals_compute_member_statusc               #  x   K   t        j                         5 } t        |        d d d        y # 1 sw Y   y xY wwNtempfileTemporaryDirectoryr   tmps    I/home/jay/workspace/tests/dashboard/test_data_loader_signal_merge_2534.pytmp_heartbeat_dirr   .   1     		$	$	& #3i     :.	:7:c               #  x   K   t        j                         5 } t        |        d d d        y # 1 sw Y   y xY wwr   r   r   s    r   tmp_schedule_history_dirr   4   r   r   c               #  x   K   t        j                         5 } t        |        d d d        y # 1 sw Y   y xY wwr   r   r   s    r   tmp_events_dirr   :   r   r   c                0    | |z  }|j                          |S r   )touch)dir_namefs      r   _touch_freshr!   @   s    tAGGIH    c                    | |z  }|j                          t        j                         |z
  }t        j                  |||f       |S r   )r   timeosutime)r   r   age_secr    pasts        r   _touch_with_ager)   F   s;    tAGGI99; DHHQtHr"   c           	         | | dz  }|||d|dddd}|j                  t        j                  |d      d	z   d
       |dkD  r/t        j                         |z
  }t	        j
                  |||f       |S )u-   schedule_history JSONL 1라인 파일 생성.z.logz
(redacted)z2026-05-10T03:00:00.000+09:00oki  )schedule_idchat_idpromptresponseworkspace_pathtsstatusduration_msFensure_ascii
utf-8encodingr   
write_textjsondumpsr$   r%   r&   )	r   r,   r-   r.   r0   r'   r    recr(   s	            r   _write_schedule_logr?   N   s     	+d##A" (-	C LLCe4t;gLN{yy{W$
T4L!Hr"   c                    | | dz  }d|ddd}|j                  t        j                  |d      d	       |d
kD  r/t        j                         |z
  }t	        j
                  |||f       |S )Nz.merge-queue.jsonWAITING_FOR_PREDECESSORc   z2026-05-10T03:10:26Z)decisiontask_id	pr_number	timestampFr4   r7   r8   r   r:   )r   rD   r'   r    payloadr(   s         r   _write_merge_queuerH   i   sr    '+,,A-+	G LLG%87LK{yy{W$
T4L!Hr"   c                    t        | d       t               }|j                  ddi       t        dddd| |i i       }|dk(  sJ y	)
uP   timers running + heartbeat fresh + PID alive → working (기존 경로 회귀).ztask-A.heartbeatzsched-ATztask-Arunningr2   r,   cron_signalsmerge_queue_signalsworkingN)r!   r	   set_overrider   r   presults      r   2test_signal_merge_1_timers_running_returns_workingrT   {   sX    "$67ANNIt$%#Y7	F Yr"   c                    t               }|j                  i        dt        j                         dz
  i}t        dddi| ||i       }|dk(  sJ y)u   timers status=completed(또는 hb stale)이지만 cron 시그널 fresh → 작업중.

    회장 발견 사례 핵심 — cron --session으로 봇이 실 작업 중이지만 timers는 'idle'.
    task-2528+1      N@r2   	completedrL   rO   Nr	   rP   r$   r   )r   rR   rM   rS   s       r   /test_signal_merge_2_cron_overrides_stale_timersrZ      s^    
 	ANN2!499;#56L#	;	!F Yr"   c                    t               }|j                  i        dt        j                         dz
  i}t        di | |i |      }|dk(  sJ y)u?   merge-queue HEAD에 fresh 진입 → 작업중 (timers 무관).	task-2530      >@rL   rO   NrY   )r   rR   
mq_signalsrS   s       r   4test_signal_merge_3_merge_queue_head_returns_workingr_      sW    ANN2tyy{T12J#
	&F Yr"   c                p    t               }|j                  i        t        dddd| |i i       }|dk(  sJ y)uC   cron 부재 + merge-queue 부재 + timers stale/completed → idle.ztask-XYZrX   nonerK   rL   idleN)r	   rP   r   rQ   s      r   +test_signal_merge_4_no_signals_returns_idlerc      sG    ANN2#v6	F Vr"   c           
     j   t               }|j                  ddi       t        | d       t        dddd| |dt	        j                         t
        z
  dz
  idt	        j                         t
        z
  dz
  i      }|d	k(  sJ t        | d
t        dz          t        dddd| |dt	        j                         dz
  idt	        j                         t
        z
  dz
  i      }|d	k(  sJ t        | dt        dz          t        dddd| |dt	        j                         t
        z
  dz
  idt	        j                         dz
  i      }|d	k(  sJ t        | dt        dz          t        dddd| |dt	        j                         t
        z
  dz
  idt	        j                         t
        z
  dz
  i      }|dk(  sJ y)u4  priority: cron > merge-queue > timers heartbeat.

    검증 1: cron stale + mq stale + hb fresh+alive → working (heartbeat path)
    검증 2: cron fresh + 나머지 stale → working (cron path)
    검증 3: cron stale + mq fresh + hb stale → working (mq path)
    검증 4: 모두 stale → idle
    zsched-XTztask-X.heartbeatztask-XrJ   rK   <   rL   rO   ztask-Y.heartbeatztask-Yzsched-Yr]   ztask-Z.heartbeatztask-Zzsched-ZrW   ztask-W.heartbeatztask-Wzsched-Wrb   N)r	   rP   r!   r   r$   r   r)   r   )r   rR   result1result2result3result4s         r   8test_signal_merge_5_priority_cron_over_mq_over_heartbeatrj      s    	ANNIt$% "$67$Y7			.F F KL%tyy{5M'MPR'RSG i %'9;RUW;WX$Y7			d 23%tyy{5M'MPR'RSG i %'9;RUW;WX$Y7			.F F KL%tyy{T'9:G i %'9;RUW;WX$Y7			.F F KL%tyy{5M'MPR'RSG fr"   c                    t        | dt        d       t        | ddd       t        | t              }d|v sJ d	|vsJ y
)u~   다른 chat의 schedule_history 라인은 결과에 포함 X.

    회장 §명시: chat=6937032012 외 라인은 무시.
    ABCD0001u   task-100 진행r-   r.   ABCD0002l   c(	 u   task-200 진행r-   ztask-100ztask-200N)r?   r   r
   )r   signalss     r   "test_signal_merge_6_chat_isolationrq     s^      ! 	   	 - !G    W$$$r"   c                    t        | dt        dd       t        | t              }t        d |j	                         D              sJ t        j                  |      }d|vsJ d|vsJ d|vsJ y	)
uW   반환 dict에는 task_id/mtime만 — prompt/response/schedule_id raw 절대 노출 X.FF00FF00u$   task-300 비밀 토큰 ABC123 포함z&/home/jay/.cokacdir/workspace/FF00FF00r-   r.   r0   ro   c              3  <   K   | ]  }t        |t                y wr   )
isinstancefloat).0vs     r   	<genexpr>z5test_signal_merge_7_token_raw_zero.<locals>.<genexpr>6  s     >z!U#>s   ABC123u   비밀 토큰N)r?   r   r
   allvaluesr<   r=   )r   rp   
serializeds      r   "test_signal_merge_7_token_raw_zeror   '  s     !5? - !G
 >W^^-=>>>>G$J:%%%Z'''*,,,r"   c                    t        |dt        dd       t        |d       t        |t              }t	        |      }d|v sJ d|v sJ t               }|j                  i        t        di | |||      }|dk(  sJ y	)
u   회장 §발견 fixture: task-2528+1 dev1 — cron+merge-queue 모두 fresh, timers entry 0.

    audit fix B 본질 — task-timers는 entry 0이지만 cron schedule_history와
    merge-queue.json이 모두 살아있음 → 'working' 판정 보장.
    B9792045z&[task-2528+1] worktree timer reconcilez-/home/jay/workspace/.worktrees/task-2528-dev1rt   rV   ro   rL   rO   N)r?   r   rH   r
   r   r	   rP   r   r   r   r   rM   r^   rR   rS   s          r   0test_signal_merge_8_chairman_fixture_2528_plus_1r   A  s      !7F ~}51 !L .n=JL(((J&&&ANN2#
	!&F Yr"   c                    t        |dt        dd       t        |t              }t        |      }d|v sJ d|vsJ t	               }|j                  i        t        dddi| |||	      }|d
k(  sJ y)u   회장 §발견 fixture: task-2530 dev7 — cron 발사 26m43s 진행, timers idle 표시.

    audit fix B 본질 — cron 시그널만으로도 working 판정.
    5AFBFD82uA   [task-2530] composite ③ cross-cutting agent 페르소나 합성z-/home/jay/workspace/.worktrees/task-2530-dev7rt   ro   r\   r2   rX   rL   rO   Nr?   r   r
   r   r	   rP   r   r   s          r   )test_signal_merge_8_chairman_fixture_2530r   h  s      !RF 2 !L .n=J,&&&j(((ANN2#	;	!&F Yr"   c                    t        |dt        d       t        |t              }t        |      }d|vsJ d|vsJ t	               }|j                  i        t        dddi| |||      }|d	k(  sJ y
)u   회장 §발견 fixture: task-2531 dev4 — 표시=유휴(cron 미발견).

    audit fix B 본질 — cron 미발견이면 적법하게 idle 판정 (over-trigger 금지).
    이 경계 케이스를 fixture로 박제해 회귀 보호.
    298A007Bu   [task-2999] 다른 작업rm   ro   z	task-2531r2   rX   rL   rb   Nr   r   s          r   )test_signal_merge_8_chairman_fixture_2531r     s      !*	 2 !L .n=Jl***j(((ANN2#	;	!&F Vr"   )r   r   r   strreturnr   )r   r   r   r   r'   rw   r   r   )         )r   r   r,   r   r-   intr.   r   r0   r   r'   rw   r   r   )r   )r   r   rD   r   r'   rw   r   r   ),__doc__
__future__r   r<   r%   sysr   r$   pathlibr   pytestr   __file__resolveparents_PROJECT_ROOTpathinsertdashboard.data_loaderr   r   r   r	   r
   r   r   fixturer   r   r   r!   r)   r?   rH   rT   rZ   r_   rc   rj   rq   r   r   r   r    r"   r   <module>r      sP    #  	 
     DN**,44Q78 HHOOA}%    
  
  
 
  	
   
6$&,&$9~%>-4$N#L#r"   