
    ?ai-                     J   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 e	j                  j                  d e ee      j                   j                                 ej"                  d      ZdZdZdZdZd	Z ej0                  e      Z ej0                  e      Z ej0                  e      Z ej0                  e      Z ej0                  e      Zd
ededefdZd
ededefdZ  G d d      Z! G d d      Z" G d d      Z# G d d      Z$ G d d      Z% G d d      Z&y)z2Tests for token-tracker.py (TDD - RED phase first)    N)Pathztoken-trackerz{"type":"assistant","sessionId":"s1","message":{"model":"claude-sonnet-4-6","role":"assistant","usage":{"input_tokens":1000,"cache_creation_input_tokens":500,"cache_read_input_tokens":2000,"output_tokens":300}},"timestamp":"2026-03-25T10:00:00Z"}u   {"type":"user","sessionId":"s1","message":{"role":"user","content":"작업 ID: task-930.1\n팀: dev1-team\n수행하세요."},"timestamp":"2026-03-25T09:59:00Z"}u   {"type":"user","sessionId":"s2","message":{"role":"user","content":[{"type":"text","text":"작업 ID: task-930.2\n팀: dev2-team"}]},"timestamp":"2026-03-25T10:01:00Z"}z{"type":"assistant","sessionId":"s1","message":{"model":"claude-sonnet-4-6","role":"assistant","usage":{"input_tokens":200,"cache_creation_input_tokens":0,"cache_read_input_tokens":100,"output_tokens":50}},"timestamp":"2026-03-25T10:01:00Z"}zk{"type":"user","sessionId":"x","message":{"role":"user","content":"hi"},"timestamp":"2026-03-25T10:00:00Z"}tmplinesreturnc                 t    | dz  }|j                  dj                  d |D              d       t        |      S )Ns.jsonl
c              3   J   K   | ]  }t        j                  |d         yw)F)ensure_asciiNjsondumps).0ls     7/home/jay/workspace/scripts/tests/test_token_tracker.py	<genexpr>zsess.<locals>.<genexpr>   s     L4::ae<<Ls   !#zutf-8)encoding)
write_textjoinstr)r   r   ps      r   sessr      s4    iALLLeLLW^L_q6M    tasksc           	          t        d |j                         D              }t        |      }| dz  }|r||z  nd}|j                  t	        j
                  ||||dd             t        |      S )Nc              3   &   K   | ]	  }|d      yw)total_tokensN )r   ts     r   r   zledger.<locals>.<genexpr>!   s     :a.!:s   l.jsonr   )r   total_tasksavg_tokens_per_taskr   summary)sumvalueslenr   r   r   r   )r   r   totalnr   avgs         r   ledgerr+       sh    :5<<>::EE
AhA%!)aCLL

UVWps/tuv q6Mr   c                   L    e Zd ZdeddfdZdeddfdZdeddfdZdeddfdZy)TestParseSessiontmp_pathr   Nc                 v   t         j                  t        |t        t                    }|d   |d   |d   |d   |d   f}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 )Ninput_tokenscache_creation_tokenscache_read_tokensoutput_tokensmessage_count)    i  i,     ==z%(py1)s == %(py4)spy1py4assert %(py6)spy6
ttparse_sessionr   UA
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanation)selfr.   r@py_assert0@py_assert3@py_assert2@py_format5@py_format7s           r   test_aggregationz!TestParseSession.test_aggregation,   s    T(Aq12n%&!"oo
 	

	
 


 	
 	
 

	
 	
 
	
 	
 	
 
	
	
 	
 	
 	
 	
 	
 	
r   c                    t         j                  t        |t        t        t
                    }g }|d   }d}||k(  }|}|r|d   }d}	||	k(  }
|
}|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }|j                  |       |r_t        j                  d
fd
	f      t        j                  |      t        j                  |	      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            d x}x}x}x}x}x}x}
}	y )Nr0   i  r3   i^  r8   z%(py3)s == %(py6)spy3r?   %(py8)spy8z%(py11)s == %(py14)spy11py14%(py16)spy16r   assert %(py19)spy19)rA   rB   r   rC   rD   A2rE   rF   rG   append_format_booloprH   rI   )rJ   r.   rK   @py_assert1rN   @py_assert5@py_assert4rL   @py_assert10@py_assert13@py_assert12rP   @py_format9@py_format15@py_format17@py_format18@py_format20s                    r   test_multi_assistantz%TestParseSession.test_multi_assistant<   s    T(Aq"56Fq FDF D(FQ-?F3F-?3-FFFF DFFF FFFDFFFFFFF-?3FFF-?FFF3FFFFFFFFFFFFFFr   c                    t         j                  t        |t        t                    f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 )Nc              3   &   K   | ]  }|v  
 y w)Nr   )r   krK   s     r   r   z6TestParseSession.test_required_keys.<locals>.<genexpr>B   s      
 F
s   )	r0   r1   r2   r3   r4   model
session_idtask_id	timestamp,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allpy0py2r=   )rA   rB   r   rC   rD   rw   @py_builtinslocalsrE   _should_repr_global_namerG   rH   rI   )rJ   r.   rc   rM   rO   rK   s        @r   test_required_keysz#TestParseSession.test_required_keys@   s    T(Aq12


 	
s 
 
 	
 
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	
 	
 	
 
	
 	
 	
 	
 	
 	
r   c                 h   |dz  }|j                  d       t        j                  t        |            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 )
Nze.jsonl r4   r   r8   r:   r;   r>   r?   )	r   rA   rB   r   rE   rF   rG   rH   rI   rJ   r.   r   rL   rM   rN   rO   rP   s           r   test_empty_filez TestParseSession.test_empty_fileQ   sy    y 	RA'8=A=8A====8A===8===A=======r   )__name__
__module____qualname__r   rQ   rn   r~   r   r   r   r   r-   r-   +   sQ    
 
$ 
 GT Gd G
4 
D 
"> > >r   r-   c                   \    e Zd ZdeddfdZdeddfdZdeddfdZdeddfdZdeddfdZy)	TestTaskMappingr.   r   Nc                 P   t         j                  t        |t        t                    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 )Nrt   
task-930.1r8   r:   r;   r>   r?   r@   rJ   r.   rL   rM   rN   rO   rP   s          r   test_task_id_stringz#TestTaskMapping.test_task_id_stringX   sh    Xq! 45i@PLP@LPPPP@LPPP@PPPLPPPPPPPr   c                 P   t         j                  t        |t        t                    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 )Nrt   z
task-930.2r8   r:   r;   r>   r?   )
rA   rB   r   ULrD   rE   rF   rG   rH   rI   r   s          r   test_task_id_listz!TestTaskMapping.test_task_id_list[   sh    Xr1 56yAQ\QA\QQQQA\QQQAQQQ\QQQQQQQr   c                 P   t         j                  t        |t        t                    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 )Nrt   r   r8   r:   r;   r>   r?   )
rA   rB   r   UXrD   rE   rF   rG   rH   rI   r   s          r   test_no_task_idzTestTaskMapping.test_no_task_id^   sh    Xr1 56yAGRGARGGGGARGGGAGGGRGGGGGGGr   c                 P   t         j                  t        |t        t                    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 )Nrr   claude-sonnet-4-6r8   r:   r;   r>   r?   r@   r   s          r   
test_modelzTestTaskMapping.test_modela   sl    Xq! 45g>UBUU>BUUUUU>BUUUU>UUUBUUUUUUUUr   c                 P   t         j                  t        |t        t                    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 )Nru   z2026-03-25T09:59:00Zr8   r:   r;   r>   r?   r@   r   s          r   test_timestampzTestTaskMapping.test_timestampd   sl    Xq! 45kB\F\\BF\\\\\BF\\\\B\\\F\\\\\\\\r   )	r   r   r   r   r   r   r   r   r   r   r   r   r   r   W   sp    QD QT QR$ R4 RH H HV4 VD V]t ] ]r   r   c                   Z    e Zd Zddededededef
dZddZdd	Zdd
ZddZ	ddZ
ddZy)TestComputeCosticrccor   c                     ||||dS )N)r0   r2   r1   r3   r   )rJ   r   r   r   r   s        r   uzTestComputeCost.ui   s     !UWjkllr   Nc                    t         j                  }| j                  }d}d} |||      }d} |||      }d}||z
  }	t        |	      }
d}|
|k  }|st	        j
                  d|fd|
|f      dt        j                         v st	        j                  t              rt	        j                  t              ndd	t        j                         v st	        j                  t               rt	        j                  t               nd	t	        j                  |      d
t        j                         v st	        j                  |       rt	        j                  |       nd
t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |
      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}x}x}x}x}	x}
x}}y )N@B r   r   g      2@MbP?<z%(py21)s
{%(py21)s = %(py0)s((%(py16)s
{%(py16)s = %(py3)s
{%(py3)s = %(py1)s.compute_cost
}(%(py12)s
{%(py12)s = %(py6)s
{%(py6)s = %(py4)s.u
}(%(py8)s, o=%(py10)s)
}, %(py14)s)
} - %(py18)s))
} < %(py24)sabsrA   rJ   ry   r<   rU   r=   r?   rW   py10py12r[   r]   py18py21py24assert %(py26)spy26rA   compute_costr   r   rE   rF   r{   r|   r}   rG   rH   rI   rJ   rN   rd   @py_assert7@py_assert9@py_assert11rg   @py_assert15@py_assert17@py_assert19@py_assert20@py_assert23@py_assert22@py_format25@py_format27s                  r   test_sonnetzTestComputeCost.test_sonnetl   sf   ??g466g)gyg6)y#AgCVg?#ACVWgZ^gWZ^^gs^_gbgg_bggggg_bgggggggsgggsgggggg2ggg2ggg?gggggg4ggg4ggg6ggg)gggyggg#AgggCVgggWgggZ^ggg_gggbggggggggggr   c                    t         j                  }| j                  }d}d} |||      }d} |||      }d}||z
  }	t        |	      }
d}|
|k  }|st	        j
                  d|fd|
|f      dt        j                         v st	        j                  t              rt	        j                  t              ndd	t        j                         v st	        j                  t               rt	        j                  t               nd	t	        j                  |      d
t        j                         v st	        j                  |       rt	        j                  |       nd
t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |
      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}x}x}x}x}	x}
x}}y )Nr   r   zclaude-opus-4-6g     V@r   r   r   r   rA   rJ   r   r   r   r   r   s                  r   	test_opuszTestComputeCost.test_opuso   sf   ??e466e)eye6)y#AeCTe?#ACTUeX\eUX\\es\]e`ee]`eeeee]`eeeeeeeseeeseeeeee2eee2eee?eeeeee4eee4eee6eee)eeeyeee#AeeeCTeeeUeeeX\eee]eee`eeeeeeeeeer   c                    t         j                  }| j                  }d}d} |||      }d} |||      }d}||z
  }	t        |	      }
d}|
|k  }|st	        j
                  d|fd|
|f      dt        j                         v st	        j                  t              rt	        j                  t              ndd	t        j                         v st	        j                  t               rt	        j                  t               nd	t	        j                  |      d
t        j                         v st	        j                  |       rt	        j                  |       nd
t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |
      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}x}x}x}x}	x}
x}}y )Nr   r   zclaude-haiku-4-5-20251001g333333@r   r   r   r   rA   rJ   r   r   r   r   r   s                  r   
test_haikuzTestComputeCost.test_haikur   sf   ??n466n)nyn6)y#AnC^n?#AC^_nben_beensefninnfinnnnnfinnnnnnnsnnnsnnnnnn2nnn2nnn?nnnnnn4nnn4nnn6nnn)nnnynnn#AnnnC^nnn_nnnbennnfnnninnnnnnnnnnr   c                 b   t         j                  }| j                  }d} ||      }d} |||      }d}||z
  }t        |      }	d}
|	|
k  }|st	        j
                  d|fd|	|
f      dt        j                         v st	        j                  t              rt	        j                  t              ndd	t        j                         v st	        j                  t               rt	        j                  t               nd	t	        j                  |      d
t        j                         v st	        j                  |       rt	        j                  |       nd
t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |	      t	        j                  |
      dz  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}x}x}x}x}	x}}
y )Nr   )r   r   g333333?r   r   )z%(py19)s
{%(py19)s = %(py0)s((%(py14)s
{%(py14)s = %(py3)s
{%(py3)s = %(py1)s.compute_cost
}(%(py10)s
{%(py10)s = %(py6)s
{%(py6)s = %(py4)s.u
}(cr=%(py8)s)
}, %(py12)s)
} - %(py16)s))
} < %(py22)sr   rA   rJ   ry   r<   rU   r=   r?   rW   r   r   r[   r]   r_   py22assert %(py24)sr   r   rJ   rN   rd   r   r   r   rg   r   r   @py_assert18@py_assert21r   @py_format23r   s                 r   test_cache_readzTestComputeCost.test_cache_readu   sT   ??\466\Y\6Y#7\9L\?#79LM\PS\MPSS\sST\W\\TW\\\\\TW\\\\\\\s\\\s\\\\\\2\\\2\\\?\\\\\\4\\\4\\\6\\\Y\\\#7\\\9L\\\M\\\PS\\\T\\\W\\\\\\\\\\r   c                 b   t         j                  }| j                  }d} ||      }d} |||      }d}||z
  }t        |      }	d}
|	|
k  }|st	        j
                  d|fd|	|
f      dt        j                         v st	        j                  t              rt	        j                  t              ndd	t        j                         v st	        j                  t               rt	        j                  t               nd	t	        j                  |      d
t        j                         v st	        j                  |       rt	        j                  |       nd
t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |	      t	        j                  |
      dz  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}x}x}x}x}	x}}
y )Nr   )r   r   g      ?r   r   )z%(py19)s
{%(py19)s = %(py0)s((%(py14)s
{%(py14)s = %(py3)s
{%(py3)s = %(py1)s.compute_cost
}(%(py10)s
{%(py10)s = %(py6)s
{%(py6)s = %(py4)s.u
}(cc=%(py8)s)
}, %(py12)s)
} - %(py16)s))
} < %(py22)sr   rA   rJ   r   r   r   r   r   s                 r   test_cache_creationz#TestComputeCost.test_cache_creationx   sT   ??]466]Y]6Y#7]9L]?#79LM]PT]MPTT]sTU]X]]UX]]]]]UX]]]]]]]s]]]s]]]]]]2]]]2]]]?]]]]]]4]]]4]]]6]]]Y]]]#7]]]9L]]]M]]]PT]]]U]]]X]]]]]]]]]]r   c                    t         j                  }| j                  }d}d} |||      }d} |||      }d}||k(  }	|	snt        j                  d|	fd||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |      d	
z  }
d
d|
iz  }t        t        j                  |            d x}x}x}x}x}x}x}x}	}y )Nr   r   unknowng        r8   )z%(py15)s
{%(py15)s = %(py2)s
{%(py2)s = %(py0)s.compute_cost
}(%(py11)s
{%(py11)s = %(py5)s
{%(py5)s = %(py3)s.u
}(%(py7)s, o=%(py9)s)
}, %(py13)s)
} == %(py18)srA   rJ   )
ry   rz   rU   py5py7py9rZ   py13py15r   zassert %(py20)spy20)rA   r   r   rE   rF   r{   r|   r}   rG   rH   rI   )rJ   rc   re   @py_assert6@py_assert8rf   rh   @py_assert14r   @py_assert16@py_format19@py_format21s               r   test_unknown_modelz"TestComputeCost.test_unknown_model{   s   PtvvPiP9Pvi9=PyP=yIPSPISPPPPISPPPPPPrPPPrPPPPPPPPPtPPPtPPPvPPPiPPP9PPP=PPPyPPPIPPPSPPPPPPPPPr   )r   r   r   r   )r   N)r   r   r   intdictr   r   r   r   r   r   r   r   r   r   r   r   h   sT    m3 m mS m mT mhfo]^Qr   r   c                   <    e Zd ZdeddfdZdeddfdZdeddfdZy)TestDetectAnomalyr.   r   Nc                    dddddddddd}d t         j                  t        ||            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 )Nd   {Gz?r   cost_estimate_usdr6   g?t1t2t3c              3   ,   K   | ]  }|d    dk(    yw)rt   r   Nr   )r   as     r   r   z2TestDetectAnomaly.test_above_2x.<locals>.<genexpr>   s     XA1Y<4'Xs   rv   anyrx   )rA   detect_anomalyr+   r   r{   r|   rE   r}   rG   rH   rI   )rJ   r.   r   rc   rM   rO   s         r   test_above_2xzTestDetectAnomaly.test_above_2x   s     $'TB#&TB#&TB

 Y1B1B6(TUCV1WXXsXXXXXXXXXsXXXsXXXXXXXXXXXXXXr   c                    ddddddd}t         j                  }t        ||      } ||      }g }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
t        j                         v st        j                  |      rt        j                  |      nd
dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}x}x}}y )Nr   r   r   n   )r   r   r8   )z|%(py9)s
{%(py9)s = %(py2)s
{%(py2)s = %(py0)s.detect_anomaly
}(%(py7)s
{%(py7)s = %(py3)s(%(py4)s, %(py5)s)
})
} == %(py12)srA   r+   r.   r   )ry   rz   rU   r=   r   r   r   r   zassert %(py14)sr[   )rA   r   r+   rE   rF   r{   r|   r}   rG   rH   rI   )
rJ   r.   r   rc   r   r   r   rf   @py_format13rj   s
             r   test_uniform_no_anomalyz)TestDetectAnomaly.test_uniform_no_anomaly   s   #&TB#&TB
   ;!!4; !45;;5;;;;5;;;;;;r;;;r;;; ;;;;;;;;;;;;;;;;;;;;;;;;!;;;!;;;!4;;;5;;;;;;;;;;;r   c           
         |dz  }|j                  t        j                  i ddid             t        j                  }t        |      } ||      }g }||k(  }|sgt        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              ndd	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      t        j                  |      d
z  }dd|iz  }	t        t        j                  |	            d x}x}x}x}}y )Nr    r"   r   r#   r8   )zs%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s.detect_anomaly
}(%(py6)s
{%(py6)s = %(py3)s(%(py4)s)
})
} == %(py11)srA   r   r   )ry   rz   rU   r=   r?   rW   rZ   zassert %(py13)sr   )r   r   r   rA   r   r   rE   rF   r{   r|   r}   rG   rH   rI   )
rJ   r.   r   rc   rd   r   rf   r   @py_format12@py_format14s
             r   
test_emptyzTestDetectAnomaly.test_empty   s   x	TZZ":OQR9S TUV  .Q. (.B.(B....(B......r...r... ...............Q...Q......(...B........r   )r   r   r   r   r   r   r   r   r   r   r   r      s>    Yd Yt Y< < </4 /D /r   r   c                   l    e Zd ZdeddfdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	y)
TestCLICommandsr.   r   Nc                    |dz  }t         j                  t        |t        t              gt        |             d}t        j                  |j                               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 )
Nledger.json)
glob_pathsledger_pathr   r   )in)z%(py1)s in %(py4)sr;   r>   r?   )rA   scanr   rC   rD   r   r   loads	read_textrE   rF   rG   rH   rI   )rJ   r.   lprL   rM   rN   rO   rP   s           r   test_scan_creates_ledgerz(TestCLICommands.test_scan_creates_ledger   s    %
D1a01s2wGBtzz",,.9'BB|BBBBB|BBBB|BBBBBBBBBBBr   c                    ddddi}t         j                  dt        ||            }g }d }||u}|}|r|d   }d}	||	k(  }
|
}|s+t        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  }|j                  |       |r_t        j                  d
fd	f      t        j                  |      t        j                  |	      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            d x}x}x}x}x}x}
}	y )Nr   r5   皙?r   r   )is not)z%(py2)s is not %(py5)srK   )rz   r   z%(py7)sr   r8   )z%(py10)s == %(py13)s)r   r   z%(py15)sr   r   zassert %(py18)sr   )rA   get_taskr+   rE   rF   r{   r|   r}   rG   ra   rb   rH   rI   )rJ   r.   r   rK   rc   re   rM   rL   r   rh   r   @py_format6@py_format8r   @py_format16rk   r   s                    r   test_get_task_foundz#TestCLICommands.test_get_task_found   s    DsKLKKfXq&9:::q}:>!2:d:!2d!:::::q::::::q:::q::::::::::!2d:::!2:::d::::::::::::::r   c                    |dz  }|j                  t        j                  i i d             t        j                  }d}t        |      } |||      }d }||u }|s{t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      d	z  }	d
d|	iz  }
t        t        j                  |
            d x}x}x}x}x}}y )Nr    r#   z
task-999.9)is)zx%(py10)s
{%(py10)s = %(py2)s
{%(py2)s = %(py0)s.get_task
}(%(py4)s, %(py8)s
{%(py8)s = %(py5)s(%(py6)s)
})
} is %(py13)srA   r   r   )ry   rz   r=   r   r?   rW   r   r   zassert %(py15)sr   )r   r   r   rA   r  r   rE   rF   r{   r|   r}   rG   rH   rI   )rJ   r.   r   rc   rM   r   r   rh   r   r   r  s              r   test_get_task_missingz%TestCLICommands.test_get_task_missing   s   x	TZZ" <=>{{8<8Q8{<08D80D88880D888888r888r888{888<888888888888888Q888Q8888880888D88888888r   c                    |dz  }|j                  t        j                  i ddid             t        j	                  t        |            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 )
Nr    r   i  r#   r8   r:   r;   r>   r?   )r   r   r   rA   get_summaryr   rE   rF   rG   rH   rI   r   s           r   test_get_summaryz TestCLICommands.test_get_summary   s    x	TZZ".$9O PQR~~c!f%n5==5====5===5==========r   c                    dddddddddd}t         j                  t        ||            }g }t        |      }d}||k(  }|}|r|d   d	   }	d
}
|	|
k(  }|}|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }|j                  |       |r_t	        j
                  dfd	
f      t	        j                  |	      t	        j                  |
      dz  }dd|iz  }|j                  |       t	        j                  |d      i z  }dd|iz  }t        t	        j                  |            d x}x}x}x}x}x}	x}}
y )Nr   r   r   r5   r  r   r7   r   rt   r   r8   )z0%(py5)s
{%(py5)s = %(py2)s(%(py3)s)
} == %(py8)sr'   r   )rz   rU   r   rW   z%(py10)sr   )z%(py13)s == %(py16)s)r   r]   z%(py18)sr   zassert %(py21)sr   )rA   r   r+   r'   rE   rF   r{   r|   r}   rG   ra   rb   rH   rI   )rJ   r.   r   r   rc   re   r   r   rL   rh   r   r   ri   @py_format11rk   r   rm   @py_format22s                     r   test_anomaly_commandz$TestCLICommands.test_anomaly_command   s,    $'TB#&TB#'dC

 fXq126s1v66v{6qtI6$6$66666v666666s666s66666616661666v6666666666$666666$66666666666666r   c                    t        j                  d      }t        j                  d      }|dz  }|j                  t        j                  |             |dz  }|j                  t        j                  |             t        j                  t        |      t        |             t        j                  |j                               d   d   }|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}	}g }|d   }	d}|	|k(  }|}|r|d   }d}||k(  }|}|st        j                  d
|fd|	|f      t        j                  |	      t        j                  |      dz  }dd|iz  }|j                  |       |r_t        j                  d
fdf      t        j                  |      t        j                  |      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            d x}x}x}	x}x}x}x}}y )Nz\{"tasks":{"task-930.1":{"task_id":"task-930.1","team_id":"dev1-team","status":"completed"}}}z|{"tasks":{"task-930.1":{"input_tokens":1000,"output_tokens":300,"total_tokens":3800,"cost_estimate_usd":0.05}},"summary":{}}ztimers.jsonr   r   r   token_usager   i  r8   r:   r;   r>   r?   team_id	dev1-teamstatus	completedrS   rT   rV   rW   rX   rY   r\   r]   r   r^   r_   )r   r   r   r   rA   enrichr   r   rE   rF   rG   rH   rI   ra   rb   )rJ   r.   tdldtpr   taskrL   rM   rN   rO   rP   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   s                          r   test_enrichzTestCLICommands.test_enrich   s   ZZvwZZ  W  X%
djjn%%
djjn%
		#b'3r7#zz",,.)'2<@M">2:d:2d::::2d:::2:::d:::::::OtIO+O+-O$x.OKO.K2OOOO+OOOOOO+OOOOOOO.KOOO.OOOKOOOOOOOOOOOOOOr   )
r   r   r   r   r  r	  r  r  r  r  r   r   r   r   r      sz    C C$ C
;D ;T ;
9d 9t 9
> >$ >
7T 7d 7PD PT Pr   r   c                       e Zd ZdZdedefdZdeddfdZdeddfdZdeddfd	Z	deddfd
Z
deddfdZdeddfdZdeddfdZdeddfdZdeddfdZy)
TestTeamREu:   TEAM_RE 정규식 엣지 케이스 테스트 (task-1007.1)textr   c                 <    ddl }|j                  ddd|ddd      S )u<   팀 정보가 포함된 user 메시지 JSON 문자열 생성r   Nusertest)rolecontentz2026-03-25T10:00:00Z)type	sessionIdmessageru   r   )rJ   r"  _jsons      r   _make_user_msgzTestTeamRE._make_user_msg   s,    {{#$*t<3	
 	
r   r.   Nc                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|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&   dev1-team, dev2-team 등 정상 매칭r   u   task-1.1
팀: dev1-teamr	   r  r  r8   r:   r;   r>   r?   Nr   r,  _A_JSONrA   rB   r   rE   rF   rG   rH   rI   	rJ   r.   r   rK   rL   rM   rN   rO   rP   s	            r   test_dev_team_patternz TestTeamRE.test_dev_team_pattern   s    y 	T(()CDtKgUVSV$|*{*|{****|{***|***{*******r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|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   marketing 명시 패턴 매칭r   ztask-1.1
team: marketingr	   r  	marketingr8   r:   r;   r>   r?   Nr.  r0  s	            r   test_marketing_patternz!TestTeamRE.test_marketing_pattern       y 	T(()DELwVWSV$|*{*|{****|{***|***{*******r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|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   anu-direct 명시 패턴 매칭r   ztask-1.1
team_id: anu-directr	   r  z
anu-directr8   r:   r;   r>   r?   Nr.  r0  s	            r   test_anu_direct_patternz"TestTeamRE.test_anu_direct_pattern   s    y 	T(()HIDPSZZ[SV$|+|+||++++||+++|+++|+++++++r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|d   }d}||k7  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}|d   }d}||k7  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}y)uT   team_id: str, 같은 타입 어노테이션이 team_id로 캡처되지 않아야 함r   z task-4.4
team_id: str, team: strr	   r  zstr,!=z%(py1)s != %(py4)sr;   r>   r?   Nr   r.  r0  s	            r   test_str_comma_not_capturedz&TestTeamRE.test_str_comma_not_captured   s    y 	T(()LMPTTW^^_SV$|%v%|v%%%%|v%%%|%%%v%%%%%%%|$u$|u$$$$|u$$$|$$$u$$$$$$$r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|d   }d}||k7  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}y)uG   team: int 같은 타입 이름이 team_id로 캡처되지 않아야 함r   ztask-1.1
team: intr	   r  r   r9  r;  r;   r>   r?   Nr.  r0  s	            r   %test_type_annotation_int_not_capturedz0TestTeamRE.test_type_annotation_int_not_captured   s    y 	T(()>?$FPQSV$|$u$|u$$$$|u$$$|$$$u$$$$$$$r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|d   }d}||k7  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}}y)u@   team_id: Optional[str] 이 team_id로 캡처되지 않아야 함r   ztask-1.1
team_id: Optional[str]r	   r  zOptional[str]r9  r;  r;   r>   r?   Nr.  r0  s	            r   test_optional_type_not_capturedz*TestTeamRE.test_optional_type_not_captured   s    y 	T(()KLtSV]]^SV$|..|....|...|..........r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|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.   미래 팀 이름 (하이픈 포함)도 매칭r   u   task-1.1
팀: qa-teamr	   r  zqa-teamr8   r:   r;   r>   r?   Nr.  r0  s	            r   test_future_team_with_hyphenz'TestTeamRE.test_future_team_with_hyphen   s    y 	T(()ABTIGSTSV$|(y(|y((((|y(((|(((y(((((((r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|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   한글 콜론(：) 매칭r   u   task-1.1
팀：dev2-teamr	   r  z	dev2-teamr8   r:   r;   r>   r?   Nr.  r0  s	            r   test_korean_colonzTestTeamRE.test_korean_colon  r5  r   c                    |dz  }|j                  | j                  d      dz   t        z          t        j	                  t        |            }|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)uE   dev1-team, 뒤에 쉼표가 있어도 정확히 team 이름만 캡처r   z$task-1.1
team: dev1-team, other infor	   r  r  r8   r:   r;   r>   r?   Nr.  r0  s	            r    test_team_id_with_trailing_commaz+TestTeamRE.test_team_id_with_trailing_comma  s    y 	T(()PQTXX[bbcSV$|*{*|{****|{***|***{*******r   )r   r   r   __doc__r   r,  r   r1  r4  r7  r<  r>  r@  rB  rD  rF  r   r   r   r!  r!     s    D
3 
3 
+d +t ++t + +, , ,%D %T %%d %t %/ / /)T )d )+$ +4 ++ +$ +r   r!  )'rG  builtinsr{   _pytest.assertion.rewrite	assertionrewriterE   	importlibr   syspathlibr   pathinsertr   __file__parentimport_modulerA   r/  _U_JSON_UL_JSON_A2_JSON_UX_JSONr   rD   rC   r   r`   r   r   r   r+   r-   r   r   r   r   r!  r   r   r   <module>rX     sC   8      
  3tH~,,334 5Y_- C p w x DJJwDJJwTZZTZZTZZd D S  T c )> )>X] ]"Q Q./ /.+P +P\O+ O+r   