
    i8G                        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mZmZ ddlmZ ddlZ ee      j$                  j$                  Ze
j(                  j+                  d ee             edz  Zej0                  j3                  de      ZdZeeuZes ej:                  defdeef      d	 ej<                         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jH                  e"            dxZZej0                  jK                  e      Z&ejN                  ZdZ(ee(uZ)e)s ej:                  de)fdee(f      d	 ej<                         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jH                  e*            dxZxZ)Z(ejN                  jW                  e&       de,dedefdZ-de,dedefdZ.dededefdZ/defdZ0de1defdZ2 G d d      Z3 G d d      Z4 G d  d!      Z5 G d" d#      Z6 G d$ d%      Z7 G d& d'      Z8y)(uw  
test_whisper_save_guidance.py

scripts/whisper-save-guidance.py 단위 테스트

테스트 항목:
- 빈 상태 → 기본 guidance 생성
- active 작업 있음 → guidance에 포함
- done 파일 있음 → pending_dispatches에 포함
- idle 팀 있음 → idle_teams에 포함
- 기존 session-guidance.json 존재 시 덮어쓰기
- 파일 손상 시 graceful 처리
    N)datetime	timedeltatimezone)Pathzwhisper-save-guidance.pywhisper_save_guidance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py7bots	base_pathreturnc                     |dz  }|j                  dd       |dz  }|j                  t        j                  d| i      d       |S )u*   bot-activity.json 픽스처 파일 생성.eventsTparentsexist_okbot-activity.jsonr   utf-8encoding)mkdir
write_textjsondumps)r   r   
events_dirpaths       ?/home/jay/workspace/scripts/tests/test_whisper_save_guidance.pymake_bot_activityr&   )   sL    X%JTD1++DOODJJ~.OAK    tasksc                 `    |dz  }|j                  t        j                  d| i      d       |S )u)   task-timers.json 픽스처 파일 생성.task-timers.jsonr(   r   r   )r    r!   r"   )r(   r   r$   s      r%   make_task_timersr+   2   s0    ))DOODJJ/07OCKr'   task_idc                 l    |dz  }|j                  dd       ||  dz  }|j                  dd       |S )u   *.done 픽스처 파일 생성.r   Tr   z.done r   r   )r   r    )r,   r   r#   	done_paths       r%   make_done_filer0   9   sI    X%JTD1y..Ig.r'   c                  d    t        j                  t        j                        j	                         S )N)r   nowr   utc	isoformat r'   r%   now_isor6   B   s    <<%//11r'   hoursc                     t        j                  t        j                        t	        |       z
  }|j                         S )N)r7   )r   r2   r   r3   r   r4   )r7   dts     r%   hours_ago_isor:   F   s*    	hll	#ie&<	<B<<>r'   c                   @    e Zd ZdZdefdZdefdZdefdZdefdZy)TestLoadBotActivityu,   load_bot_activity() 함수 단위 테스트.tmp_pathc                 |   t         j                  |      }i }||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}}y)	uE   events 디렉토리가 없어도 빈 dict 반환 (graceful fallback).base_dir==z%(py0)s == %(py3)sresultr   r   r   N)
r   load_bot_activity
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationselfr=   rD   @py_assert2@py_assert1@py_format4@py_format6s          r%   !test_empty_dir_returns_empty_dictz5TestLoadBotActivity.test_empty_dir_returns_empty_dictS   sm    &88(8Kv|vvvr'   c                    ddt               di}t        ||       t        j                  |      }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   d   }d}||k(  }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}}y)u    정상 bot-activity.json 파싱.dev1idlestatussincer?   inz%(py1)s in %(py3)srD   py1r   r   r   NrY   rA   z%(py1)s == %(py4)sr_   py4assert %(py6)spy6)r6   r&   r   rE   rF   rG   rK   rH   rI   rJ   rL   rM   )rO   r=   r   rD   @py_assert0rP   rR   rS   @py_assert3@py_format5@py_format7s              r%   test_valid_file_parsedz*TestLoadBotActivity.test_valid_file_parsedX   s    6GI>?$)&88(8Kvvvf~h'161'61111'6111'11161111111r'   c                    |dz  }|j                  d       |dz  j                  dd       t        j                  |      }i }||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}}y)u*   손상된 JSON 파일 → 빈 dict 반환.r   Tr   r   z
NOT_JSON{{r   r   r?   rA   rC   rD   r   r   r   N)r   r    r   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rO   r=   r#   rD   rP   rQ   rR   rS   s           r%   &test_corrupted_file_returns_empty_dictz:TestLoadBotActivity.test_corrupted_file_returns_empty_dict`   s    (
&	)	)55lW5U&88(8Kv|vvvr'   c                     |dz  }|j                  d       |dz  j                  t        j                  ddi      d       t        j                  |	      }i }||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}}y)u,   bots 키가 없는 JSON → 빈 dict 반환.r   Trk   r   other   r   r   r?   rA   rC   rD   r   r   r   N)r   r    r!   r"   r   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rl   s           r%   (test_missing_bots_key_returns_empty_dictz<TestLoadBotActivity.test_missing_bots_key_returns_empty_dicth   s    (
&	)	)55djj'16NY`5a&88(8Kv|vvvr'   N)	__name__
__module____qualname____doc__r   rT   ri   rm   rq   r5   r'   r%   r<   r<   P   s5    6$ 
2t 2t  r'   r<   c                   @    e Zd ZdZdefdZdefdZdefdZdefdZy)TestLoadTaskTimersu+   load_task_timers() 함수 단위 테스트.r=   c                 |   t         j                  |      }i }||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}}y)	u+   task-timers.json 없으면 빈 dict 반환.r?   rA   rC   rD   r   r   r   N)
r   load_task_timersrF   rG   rH   rI   rJ   rK   rL   rM   rN   s          r%   $test_missing_file_returns_empty_dictz7TestLoadTaskTimers.test_missing_file_returns_empty_dicty   sm    &777Jv|vvvr'   c                    ddddt               dddi}t        ||       t        j                  |      }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)u/   running 상태 작업이 반환 dict에 포함.
task-565.1	dev1-teamu   테스트 작업Nrunning)r,   team_iddescription
start_timeend_timerY   r?   r[   r]   rD   r^   r   r   )r6   r+   r   ry   rF   rG   rK   rH   rI   rJ   rL   rM   )rO   r=   r(   rD   re   rP   rR   rS   s           r%   test_running_task_includedz-TestLoadTaskTimers.test_running_task_included~   s     '&1%i #	
 	)&777J%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%r'   c                    |dz  j                  dd       t        j                  |      }i }||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}}y)u   손상된 JSON → 빈 dict.r*   z	{bad jsonr   r   r?   rA   rC   rD   r   r   r   N)r    r   ry   rF   rG   rH   rI   rJ   rK   rL   rM   rN   s          r%   rm   z9TestLoadTaskTimers.test_corrupted_file_returns_empty_dict   s    	&	&22;2Q&777Jv|vvvr'   c                    |dz  j                  t        j                  di i      d       t        j	                  |      }i }||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}}y)u   tasks 키 없으면 빈 dict.r*   ro   r   r   r?   rA   rC   rD   r   r   r   N)r    r!   r"   r   ry   rF   rG   rH   rI   rJ   rK   rL   rM   rN   s          r%   )test_missing_tasks_key_returns_empty_dictz<TestLoadTaskTimers.test_missing_tasks_key_returns_empty_dict   s    	&	&224::wm3LW^2_&777Jv|vvvr'   N)	rr   rs   rt   ru   r   rz   r   rm   r   r5   r'   r%   rw   rw   v   s5    5T 
&4 & t $ r'   rw   c                   @    e Zd ZdZdefdZdefdZdefdZdefdZy)TestScanDoneFilesu*   scan_done_files() 함수 단위 테스트.r=   c                 |   t         j                  |      }g }||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}}y)	u,   events 디렉토리 없으면 빈 리스트.r?   rA   rC   rD   r   r   r   N)
r   scan_done_filesrF   rG   rH   rI   rJ   rK   rL   rM   rN   s          r%   %test_no_events_dir_returns_empty_listz7TestScanDoneFiles.test_no_events_dir_returns_empty_list   sm    &666Iv|vvvr'   c                    t        d|       t        j                  |      }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	)
uA   *.done 파일이 있으면 task_id가 반환 리스트에 포함.
task-564.1r?   r[   r]   rD   r^   r   r   Nr0   r   r   rF   rG   rK   rH   rI   rJ   rL   rM   rO   r=   rD   re   rP   rR   rS   s          r%   test_done_file_detectedz)TestScanDoneFiles.test_done_file_detected   sx    |X.&666I%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%r'   c                     |dz  }|j                  d       |dz  j                  dd       |dz  j                  d	d       t        j                  |
      }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)u#   *.done 이 아닌 파일은 무시.r   Trk   r   z{}r   r   ztask-100.done.clearr.   r?   ztask-100not inz%(py1)s not in %(py3)srD   r^   r   r   N)r   r    r   r   rF   rG   rK   rH   rI   rJ   rL   rM   )rO   r=   r#   rD   re   rP   rR   rS   s           r%   test_non_done_files_ignoredz-TestScanDoneFiles.test_non_done_files_ignored   s    (
&	)	)55dW5M	+	+77W7M&666I'z''''z'''z''''''''''''''''r'   c                    t        d|       t        d|       t        j                  |      }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}}y
)u%   여러 .done 파일이 모두 포함.r   r|   r?   r[   r]   rD   r^   r   r   Nr   r   s          r%   test_multiple_done_filesz*TestScanDoneFiles.test_multiple_done_files   s    |X.|X.&666I%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%r'   N)	rr   rs   rt   ru   r   r   r   r   r   r5   r'   r%   r   r      s5    4d 
& &(D (& &r'   r   c                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)TestGenerateGuidanceu,   generate_guidance() 함수 단위 테스트.c                    t         j                  i i g       }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}}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}}y	)u,   빈 상태에서도 출력 구조가 완전.r   r(   done_task_idslast_sessionr[   r]   rD   r^   r   r   Nguidancepending_dispatches
idle_teamsactive_tasks)
r   generate_guidancerF   rG   rK   rH   rI   rJ   rL   rM   )rO   rD   re   rP   rR   rS   s         r%   (test_empty_state_returns_valid_structurez=TestGenerateGuidance.test_empty_state_returns_valid_structure   s   &88 9 

 '~''''~'''~''''''''''''''''#zV####zV###z######V###V########-#v----#v---#------v---v-------%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%'~''''~'''~''''''''''''''''r'   c                 V   dddddt               ddi}t        j                  i |g       }d}|d   }||v }|slt        j                  d	|fd
||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}d}|d   }||v }|slt        j                  d	|fd
||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)u?   running 작업이 guidance 텍스트와 active_tasks에 포함.r|   r}   	   테스트r~   Nr,   r   r   rY   r   r   r   r   r[   z%(py1)s in %(py4)sra   rc   rd   r   )r6   r   r   rF   rG   rK   rL   rM   rO   r(   rD   re   rf   rP   rg   rh   s           r%   $test_active_task_appears_in_guidancez9TestGenerateGuidance.test_active_task_appears_in_guidance   s     '&*#%i 	
 '88 9 

 5vn55|55555|5555|555555555551vj11|11111|1111|11111111111r'   c                    t         j                  i i dg      }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}|d   }||v }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u4   done 파일 task_id가 pending_dispatches에 포함.r   r    r   r[   r]   pending_textr^   r   r   Nr   r   ra   rc   rd   )r   r   joinrF   rG   rK   rH   rI   rJ   rL   rM   )
rO   rD   r   re   rP   rR   rS   rf   rg   rh   s
             r%   ,test_done_task_appears_in_pending_dispatcheszATestGenerateGuidance.test_done_task_appears_in_pending_dispatches   s    &88'. 9 
 xx'; <=+||++++||+++|++++++|+++|+++++++1vj11|11111|1111|11111111111r'   c                    ddt        d      di}t        j                  |i g       }d |d   D        }t        |      }|sdd	t	        j
                         v st        j                  t              rt        j                  t              nd	t        j                  |      t        j                  |      d
z  }t        t        j                  |            dx}}y)u3   3시간 이상 idle인 팀이 idle_teams에 포함.dev2rW      rX   r   c              3   $   K   | ]  }d |v  
 yw)r   Nr5   .0ts     r%   	<genexpr>zFTestGenerateGuidance.test_idle_team_3h_plus_appears.<locals>.<genexpr>  s     =16Q;=   r   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr   r   rb   Nr:   r   r   r   rH   rI   rF   rJ   rK   rL   rM   )rO   r   rD   rQ   rf   rg   s         r%   test_idle_team_3h_plus_appearsz3TestGenerateGuidance.test_idle_team_3h_plus_appears   s      &q)
 '88 9 

 >|(<==s=========s===s==============r'   c                    ddt        d      di}t        j                  |i g       }d |d   D        }t        |      }| }|sdd	t	        j
                         v st        j                  t              rt        j                  t              nd	t        j                  |      t        j                  |      d
z  }t        t        j                  |            dx}x}}y)u9   3시간 미만 idle은 idle_teams에 포함되지 않음.rV   rW   rp   rX   r   c              3   $   K   | ]  }d |v  
 ywrV   Nr5   r   s     r%   r   zHTestGenerateGuidance.test_idle_team_under_3h_excluded.<locals>.<genexpr>       Aqv{Ar   r   0assert not %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}r   r   Nr   rO   r   rD   rQ   rf   @py_assert5rS   s          r%    test_idle_team_under_3h_excludedz5TestGenerateGuidance.test_idle_team_under_3h_excluded  s      &q)
 '88 9 

 BF<,@AA3AAAAAAAAAAAA3AAA3AAAAAAAAAAAAAAr'   c                    ddt        d      di}t        j                  |i g       }d |d   D        }t        |      }| }|sdd	t	        j
                         v st        j                  t              rt        j                  t              nd	t        j                  |      t        j                  |      d
z  }t        t        j                  |            dx}x}}y)u;   processing 상태 봇은 idle_teams에 포함되지 않음.rV   
processing
   rX   r   c              3   $   K   | ]  }d |v  
 ywr   r5   r   s     r%   r   zMTestGenerateGuidance.test_processing_bot_not_in_idle_teams.<locals>.<genexpr>!  r   r   r   r   r   r   Nr   r   s          r%   %test_processing_bot_not_in_idle_teamsz:TestGenerateGuidance.test_processing_bot_not_in_idle_teams  s     &&r*
 '88 9 

 BF<,@AA3AAAAAAAAAAAA3AAA3AAAAAAAAAAAAAAr'   c                    t         j                  i i g       }t        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}}y)
u&   last_session 필드가 ISO8601 형식.r   r   Nr   r
   r9   r   r   r   )r   r   r   fromisoformatrF   rG   rH   rI   rJ   rK   rL   rM   )rO   rD   r9   rP   rQ   rR   rS   s          r%   test_last_session_is_iso_formatz4TestGenerateGuidance.test_last_session_is_iso_format#  s    &88 9 
 ##F>$:;r~rrrr'   c           	      l   dddddt        d      t        d      di}t        j                  i |g       }d}|d	   }||v}|slt        j                  d
|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)u?   completed 상태 작업은 active_tasks에 포함되지 않음.z
task-500.1r}   u   완료된 작업	completed   rp   r   r   r   r   )z%(py1)s not in %(py4)sra   rc   rd   N)r:   r   r   rF   rG   rK   rL   rM   r   s           r%   'test_completed_task_not_in_active_tasksz<TestGenerateGuidance.test_completed_task_not_in_active_tasks.  s     '&1%+A.)!,	
 '88 9 

 96.#99|#99999|#9999|999#99999999r'   N)rr   rs   rt   ru   r   r   r   r   r   r   r   r   r5   r'   r%   r   r      s/    6(2(
2>BB	:r'   r   c                   @    e Zd ZdZdefdZdefdZdefdZdefdZy)TestSaveGuidanceu(   save_guidance() 함수 단위 테스트.r=   c                    ddg g g d}t         j                  ||       |dz  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}}y
)u*   session-guidance.json 파일이 생성됨.2026-03-15T02:05:00u   테스트 가이던스r   r   r   r   r   r?   whispersession-guidance.jsonAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}out_pathr   N)
r   save_guidanceexistsrH   rI   rF   rJ   rK   rL   rM   )rO   r=   datar   rQ   rf   rg   s          r%   test_creates_filez"TestSaveGuidance.test_creates_fileJ  s     20"$
 	++D8+Di'*AA         x   x             r'   c                 @   dddgdgdgd}t         j                  ||       |dz  d	z  }t        j                  |j	                  d
            }||k(  }|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  }dd|iz  }t        t        j                  |            d}y)u   저장된 파일이 valid JSON.r   r   u   task-1 확인 필요z	dev2-teamr|   r   r?   r   r   r   r   rA   )z%(py0)s == %(py2)sloadedr   )r   r   zassert %(py4)srb   N)r   r   r!   loads	read_textrF   rG   rH   rI   rJ   rK   rL   rM   )rO   r=   r   r   r   rQ   @py_format3rg   s           r%   "test_written_content_is_valid_jsonz3TestSaveGuidance.test_written_content_is_valid_jsonW  s     2##9":&-)N
 	++D8+Di'*AAH...@A~vvvr'   c                 ^   |dz  }|j                  d       |dz  }|j                  t        j                  ddi      d       d	d
g g g d}t        j                  ||       t        j                  |j                  d            }|d   }d
}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	i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)u4   기존 session-guidance.json이 있으면 덮어씀.r   Trk   r   oldr   r   r   z2026-03-15T09:00:00u   새 가이던스r   r?   r   rA   r`   ra   rc   rd   Nr   r   r   r^   r   r   )r   r    r!   r"   r   r   r   r   rF   rG   rK   rL   rM   rH   rI   rJ   )rO   r=   whisper_dirr   new_datar   re   rf   rP   rg   rh   rR   rS   s                r%   test_overwrites_existing_filez.TestSaveGuidance.test_overwrites_existing_filee  s@   *$'!88DJJv7'J 2*"$
 	++Hx+HH...@Aj!7%77!%77777!%7777!777%77777777"uF""""uF"""u""""""F"""F"""""""r'   c                    ddg g g d}t         j                  ||       d}||z  }|j                  } |       }|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}x}}y	)
u0   whisper 디렉토리가 없으면 자동 생성.r   r.   r   r?   r   zMassert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).is_dir
}()
}r=   )r   r   r   r   N)
r   r   is_dirrH   rI   rF   rJ   rK   rL   rM   )rO   r=   r   rQ   rf   @py_assert4@py_assert6@py_format8s           r%   #test_creates_whisper_dir_if_missingz4TestSaveGuidance.test_creates_whisper_dir_if_missingx  s     2"$
 	++D8+D$.9$.$,,.,..............9...,..........r'   N)	rr   rs   rt   ru   r   r   r   r   r   r5   r'   r%   r   r   G  s5    2!$ !4 #d #&
/D 
/r'   r   c                   X    e Zd ZdZdefdZdefdZdefdZdefdZdefdZ	defdZ
y	)
TestIntegrationu(   전체 파이프라인 통합 테스트.r=   c                     t         j                  |       |dz  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}}t        j                  |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}}y)uF   모든 입력 파일 없어도 정상 완료 및 출력 파일 생성.r?   r   r   r   r   r   Nr   r   r   r[   r]   r   r^   r   r   )r   runr   rH   rI   rF   rJ   rK   rL   rM   r!   r   r   rG   )rO   r=   r   rQ   rf   rg   r   re   rP   rR   rS   s              r%   test_empty_state_no_crashz)TestIntegration.test_empty_state_no_crash  s    !!8!4i'*AA         x   x             zz(,,g,>?!zT!!!!zT!!!z!!!!!!T!!!T!!!!!!!r'   c                    dddddt               ddi}t        ||       t        j                  |       |dz  d	z  }t	        j
                  |j                  d
            }d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u,   active 작업이 있으면 출력에 포함.r|   r}   u   구현 작업r~   Nr   r?   r   r   r   r   r   r[   r   ra   rc   rd   r   )r6   r+   r   r   r!   r   r   rF   rG   rK   rL   rM   
rO   r=   r(   r   r   re   rf   rP   rg   rh   s
             r%   test_active_task_in_outputz*TestIntegration.test_active_task_in_output  s    '&.#%i 	
 	)!!8!4i'*AAzz(,,g,>?3tN33|33333|3333|33333333333/tJ//|/////|////|///////////r'   c                    t        d|       t        j                  |       |dz  dz  }t        j                  |j                  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}}y)u6   done 파일이 있으면 pending_dispatches에 포함.r   r?   r   r   r   r   r   r   r[   r]   r   r^   r   r   N)r0   r   r   r!   r   r   r   rF   rG   rK   rH   rI   rJ   rL   rM   )	rO   r=   r   r   r   re   rP   rR   rS   s	            r%   test_done_file_in_outputz(TestIntegration.test_done_file_in_output  s    |X.!!8!4i'*AAzz(,,g,>?xx%9 :;+||++++||+++|++++++|+++|+++++++r'   c                 &   ddt        d      di}t        ||       t        j                  |       |dz  dz  }t	        j
                  |j                  d	            }d
 |d   D        }t        |      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u0   3시간 이상 idle 팀이 idle_teams에 포함.dev3rW      rX   r?   r   r   r   r   c              3   $   K   | ]  }d |v  
 yw)r   Nr5   r   s     r%   r   z;TestIntegration.test_idle_team_in_output.<locals>.<genexpr>  s     ;16Q;;r   r   r   r   r   N)r:   r&   r   r   r!   r   r   r   rH   rI   rF   rJ   rK   rL   rM   )rO   r=   r   r   r   rQ   rf   rg   s           r%   test_idle_team_in_outputz(TestIntegration.test_idle_team_in_output  s     va0@A
 	$)!!8!4i'*AAzz(,,g,>?;\(:;;s;;;;;;;;;s;;;s;;;;;;;;;;;;;;r'   c                    t         j                  |       dddddt               ddi}t        ||       t         j                  |       |dz  d	z  }t	        j
                  |j                  d
            }d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u*   기존 session-guidance.json 덮어쓰기.r?   z
task-999.1r}   u
   새 작업r~   Nr   r   r   r   r   r   r[   r   ra   rc   rd   )r   r   r6   r+   r!   r   r   rF   rG   rK   rL   rM   r   s
             r%    test_overwrite_existing_guidancez0TestIntegration.test_overwrite_existing_guidance  s     	!!8!4 '&+#%i 	
 	)!!8!4i'*AAzz(,,g,>?3tN33|33333|3333|33333333333r'   c                    |dz  }|j                  d       |dz  j                  dd       |dz  j                  dd       t        j                  |	       |d
z  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}}y)u6   손상된 입력 파일들이 있어도 정상 완료.r   Trk   r   zCORRUPT{{{{r   r   r*   r?   r   r   r   r   r   N)r   r    r   r   r   rH   rI   rF   rJ   rK   rL   rM   )rO   r=   r#   r   rQ   rf   rg   s          r%   test_corrupted_inputs_gracefulz.TestIntegration.test_corrupted_inputs_graceful  s    (
&	)	)55mg5V	&	&22=72S!!8!4i'*AA         x   x             r'   N)rr   rs   rt   ru   r   r   r   r   r   r   r  r5   r'   r%   r   r     sM    2"$ "04 0&, ,	< 	<4 4.	!t 	!r'   r   )9ru   builtinsrH   _pytest.assertion.rewrite	assertionrewriterF   importlib.util	importlibr!   sysr   r   r   pathlibr   pytest__file__parent_SCRIPTS_DIRr$   insertstr_MODULE_PATHutilspec_from_file_locationr   rP   rQ   rG   rI   rJ   rK   rR   rS   rL   rM   module_from_specr   loaderr   rf   r   exec_moduledictr&   r+   r0   r6   floatr:   r<   rw   r   r   r   r   r5   r'   r%   <module>r     s	       
 2 2   H~$$++ 3|$ % 88~~--.E|T t4   t4     t   t   4      !77= {{ $ {$   {$     t   t   {  $         - .D T d D T d C D T 2 2 3  L" "T& &Ly: y:B;/ ;/FR! R!r'   