
    il                     4   d 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	m
Z
 ddlZej                  j                  d e ee      j!                         j"                  j"                               ddlmZmZmZmZmZmZmZ  ee      j!                         j"                  j"                  j"                  Z eedz  dz        Zdee   d	eeee
f   ef   fd
Z  ejB                         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'i ejP                  dddddZ)dededed	d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)      Z0 G d* d+      Z1 G d, d-      Z2y).u|   worktree_manager.py 통합 테스트.

임시 git repo를 생성하여 create/finish/list/status 명령어를 검증한다.
    N)Path)Any)_auto_fix_high_comments_classify_medium_comments_log_medium_comments_parse_gemini_comments_resolve_task_level
cmd_create
cmd_finishscriptszworktree_manager.pyargsreturnc                     t        j                  dt        g| dd      }t        j                  |j
                        |j                  fS )u:   worktree_manager.py를 실행하고 JSON 결과를 반환.python3Tcapture_outputtext)
subprocessrunSCRIPTjsonloadsstdout
returncode)r   results     T/home/jay/workspace/.worktrees/task-2116-dev1/scripts/tests/test_worktree_manager.py_run_wtr       sC    ^^	F"T"F
 ::fmm$f&7&777    tmp_pathc                    | dz  }|j                          t        j                  ddgt        |      dd       t        j                  g dt        |      dd       |dz  }|j	                  d       t        j                  g d	t        |      dd       t        j                  g d
t        |      ddi t
        j                  ddddd       |S )u/   초기 커밋이 있는 임시 git repo 생성.repogitinitTcwdcheckr   )r"   checkoutz-bmainz	README.mdhellor"   add.)r"   commit-mr#   testt@tGIT_AUTHOR_NAMEGIT_COMMITTER_NAMEGIT_AUTHOR_EMAILGIT_COMMITTER_EMAILr%   r&   r   env)mkdirr   r   str
write_textosenviron)r   r!   readmes      r   git_repor>   *   s     fDJJLNNE6?D	dSNN4#d)4`deKF
gNN&CITRVWNN'I
jj
%"( %#(
 Kr   c                   4    e Zd ZdeddfdZdeddfdZddZy)
TestCreater>   r   Nc                     t        dt        |      ddg      \  }}|dk(  sJ |d   dk(  sJ |d   dk(  sJ t        |d	         j                         sJ y )
Ncreate
task-330.1dev2r   statuscreatedbranchztask/task-330.1-dev2worktree_path)r   r9   r   is_dirselfr>   datarcs       r   test_create_newzTestCreate.test_create_newE   si    Hc(m\6JKbQwwH~***H~!7777D)*11333r   c                     t        dt        |      ddg       t        dt        |      ddg      \  }}|dk(  sJ |d   dk(  sJ y )NrB   rC   rD   r   rE   reusedr   r9   rJ   s       r   test_create_reusezTestCreate.test_create_reuseL   sO    3x=,?@Hc(m\6JKbQwwH~)))r   c                 F    t        g d      \  }}|dk(  sJ |d   dk(  sJ y )N)rB   z/nonexistent/pathztask-999dev3   rE   error)r   )rK   rL   rM   s      r   test_create_invalid_pathz#TestCreate.test_create_invalid_pathR   s.    NObQwwH~(((r   r   N)__name__
__module____qualname__r   rN   rR   rW    r   r   r@   r@   D   s-    4 4 4*$ *4 *)r   r@   c                   ,    e Zd ZdeddfdZdeddfdZy)TestListr>   r   Nc                 J    t        dt        |      g      \  }}|d   g k(  sJ y )Nlist	worktreesrQ   rK   r>   rL   _s       r   test_list_emptyzTestList.test_list_emptyY   s,    63x=12aK B&&&r   c                     t        dt        |      ddg       t        dt        |      g      \  }}t        |d         dk(  sJ |d   d   }|d   dk(  sJ |d	   dk(  sJ y )
NrB   rC   rD   r`   ra   rU   r   task_idteam_id)r   r9   len)rK   r>   rL   rc   wts        r   test_list_with_worktreez TestList.test_list_with_worktree]   sy    3x=,?@63x=12a4$%***+q!)},,,)}&&&r   )rY   rZ   r[   r   rd   rj   r\   r   r   r^   r^   X   s(    ' ' '' ' 'r   r^   c                   ,    e Zd ZdeddfdZdeddfdZy)
TestStatusr>   r   Nc                     t        dt        |      ddg       |dz  dz  }|dz  j                  d       t        dt        |      dg      \  }}|d	   d
   d   dk\  sJ y )NrB   rC   rD   
.worktreestask-330.1-dev2znew.txtr/   rE   ra   r   changed_filesrU   )r   r9   r:   )rK   r>   wt_pathrL   rc   s        r   test_status_changed_filesz$TestStatus.test_status_changed_filesg   sp    3x=,?@\),==	9	((08S]LABaK #O4999r   c                 L    t        dt        |      dg      \  }}|d   g k(  sJ y )NrE   ztask-nonexistentra   rQ   rb   s       r   test_status_no_matchzTestStatus.test_status_no_matchn   s/    8S]4FGHaK B&&&r   )rY   rZ   r[   r   rr   rt   r\   r   r   rl   rl   f   s(    :$ :4 :'T 'd 'r   rl   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)
TestFinishr>   r   Nc                     t        dt        |      ddg       t        dt        |      ddddg      \  }}|dk(  sJ |d   d	k(  sJ y )
NrB   rC   rD   finish--actionkeepr   rE   keptrQ   rJ   s       r   test_finish_keepzTestFinish.test_finish_keept   sT    3x=,?@Hc(m\6:W]^_bQwwH~'''r   c                    t        dt        |      ddg       |dz  dz  }|dz  j                  d       t        j                  g dt        |      d	d	
       t        j                  g dt        |      d	d	i t
        j                  ddddd       t        dt        |      ddddg      \  }}|dk(  sJ |d   dk(  sJ |dz  dz  j                         rJ |dz  j                         sJ y )NrB   rC   rD   rn   ro   z
merged.txtmergedr*   Tr$   )r"   r-   r.   zadd merged.txtr/   r0   r1   r6   rx   ry   merger   rE   )r   r9   r:   r   r   r;   r<   existsrK   r>   rq   rL   rM   s        r   test_finish_mergezTestFinish.test_finish_mergez   s   3x=,?@\),==	<	++H5*GDY]^5G**#)&,$)',	
 Hc(m\6:W^_`bQwwH~)))|+.??GGIII<'//111r   c                     t        dt        |      ddg       |dz  dz  }|dz  j                  d       t        dt        |      ddd	dg      \  }}|d
k(  sJ |d   dk(  sJ |dz  dz  j                         rJ y )NrB   z
task-330.2dev1rn   ztask-330.2-dev1zdiscard.txtdiscardrx   ry   r   rE   	discarded)r   r9   r:   r   r   s        r   test_finish_discardzTestFinish.test_finish_discard   s    3x=,?@\),==	=	 ,,Y7Hc(m\6:W`abbQwwH~,,,|+.??GGIIIIr   )rY   rZ   r[   r   r|   r   r   r\   r   r   rv   rv   s   s>    ( ($ (2$ 24 20JD JT Jr   rv   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)TestFinishPrr>   r   Nc                     t        dt        |      ddg       t        dt        |      ddddg      \  }}|dk7  s|d   d	k(  sJ y
y
)u?   pr 액션에서 remote가 없으면 gh 실패로 에러 처리.rB   
task-330.3r   rx   ry   prr   rE   rV   NrQ   rJ   s       r   test_finish_pr_no_remotez%TestFinishPr.test_finish_pr_no_remote   sT    3x=,?@Hc(m\6:W[\]bQw$x.G3333wr   c                     t        j                  dt        dt        |      ddddddd	d
ddgdd      }d|j                  vsJ y)u#   pr 액션 CLI 인자 파싱 검증.r   rx   r   r   ry   r   z
--pr-titlezTest PRz	--pr-bodyz	Test bodyz--gemini-timeout60Tr   zunrecognized argumentsN)r   r   r   r9   stderrrK   r>   r   s      r   test_finish_pr_cli_argsz$TestFinishPr.test_finish_pr_cli_args   s_    H"   %
, (v}}<<<r   c           
          t        j                  dt        dt        |      ddddgdd      }|j                  d	k7  sJ d
|j
                  v sJ y)u$   잘못된 action은 argparse 에러.r   rx   r   r   ry   invalidTr   r   zinvalid choiceN)r   r   r   r9   r   r   r   s      r   test_finish_pr_invalid_actionz*TestFinishPr.test_finish_pr_invalid_action   sa    H	  
   A%%%6==000r   )rY   rZ   r[   r   r   r   r   r\   r   r   r   r      s;    4 4$ 4= = =41d 1t 1r   r   r/   r0   r1   r>   rf   rg   c           	         | dz  | d| z  }|| dz  j                  d|        t        j                  g dt        |      dd       t        j                  dd	d
d| gt        |      ddt               t        j                  g dt        |       dd       t        j                  dddd| d| gt        |       ddt               y)uM   워크트리 브랜치를 main에 머지하는 헬퍼 (cleanup 테스트용).rn   -z.txtz
work from r*   Tr$   r"   r-   r.   zwork on r6   )r"   r'   r(   r   z--no-ffztask/N)r:   r   r   r9   _GIT_ENV)r>   rf   rg   rq   s       r   _merge_worktree_to_mainr      s    %7)1WI(>>G'$++j	,BCNN&CLUYZNN	$(7) 45L NN.CM^bcNN	eG9AgY$?@M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y)TestCleanupr>   r   Nc                    t        dt        |      ddg       t        |dd       t        dt        |      g      \  }}|dk(  sJ t        |d         dk(  sJ |d   d   d   dk(  sJ |d	z  d
z  j	                         rJ y)u1   머지된 워크트리만 정리되는지 확인.rB   z
task-400.1r   cleanupr   cleanedrU   rf   rn   ztask-400.1-dev1N)r   r9   r   rh   r   rJ   s       r   test_cleanup_removes_mergedz'TestCleanup.test_cleanup_removes_merged   s    3x=,?@,?Is8}56bQww4	?#q(((Iq!),<<<|+.??GGIIIIr   c                    t        dt        |      ddg       |dz  dz  }|dz  j                  d       t        j                  g dt        |      d	d	
       t        j                  g dt        |      d	d	t
               t        dt        |      g      \  }}|dk(  sJ t        |d         dk(  sJ t        |d         dk(  sJ |d   d   d   dk(  sJ |dz  dz  j                         sJ y)uB   머지되지 않은 워크트리는 건드리지 않는지 확인.rB   z
task-400.2rD   rn   ztask-400.2-dev2zwip.txtzwork in progressr*   Tr$   )r"   r-   r.   wipr6   r   r   r   skippedrU   reason
not_mergedN)r   r9   r:   r   r   r   rh   r   r   s        r   test_cleanup_skips_unmergedz'TestCleanup.test_cleanup_skips_unmerged   s    3x=,?@\),==	9	(();<*GDY]^*G	
 Is8}56bQww4	?#q(((4	?#q(((Iq!(+|;;;<'*;;CCEEEr   c                 <   t        dt        |      ddg       t        |dd       t        dt        |      ddg       |dz  dz  }|dz  j                  d	       t	        j
                  g d
t        |      dd       t	        j
                  g dt        |      ddt               t        dt        |      g      \  }}|dk(  sJ t        |d         dk(  sJ t        |d         dk(  sJ |dz  dz  j                         rJ |dz  dz  j                         sJ y)uC   머지된 것은 정리, 미머지는 보존 (혼합 시나리오).rB   z
task-400.3r   z
task-400.4rD   rn   ztask-400.4-dev2z
active.txtactiver*   Tr$   )r"   r-   r.   zactive workr6   r   r   r   rU   r   ztask-400.3-dev1N)	r   r9   r   r:   r   r   r   rh   r   r   s        r   test_cleanup_mixedzTestCleanup.test_cleanup_mixed  s     	3x=,?@,?3x=,?@\),==	<	++H5*GDY]^2G	
 Is8}56bQww4	?#q(((4	?#q(((|+.??GGIII<'*;;CCEEEr   c                 l    t        dt        |      g      \  }}|dk(  sJ |d   g k(  sJ |d   g k(  sJ y)u*   정리 대상이 없을 때 정상 동작.r   r   r   r   NrQ   rJ   s       r   test_cleanup_no_targetsz#TestCleanup.test_cleanup_no_targets/  sH    Is8}56bQwwI"$$$I"$$$r   )rY   rZ   r[   r   r   r   r   r   r\   r   r   r   r      sW    	JD 	JT 	JFD FT F,F4 FD F2% % %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)TestSafetyDecoratorr>   r   Nc                     |dz  }|j                         rd|j                         vsJ t        t        |      dd      }|j	                  d      du sJ |j                         sJ d|j                         v sJ y)uF   .gitignore에 .worktrees/가 없을 때 자동 추가되는지 확인.
.gitignore.worktrees/ztask-safety-1r   gitignore_updatedTN)r   	read_textr
   r9   getrK   r>   gitignore_pathr   s       r   test_gitignore_auto_updatez.TestSafetyDecorator.test_gitignore_auto_update8  s     "L0!((*m>C[C[C].]]]CM?FCzz-.$666$$&&& 8 8 ::::r   c                     |dz  }|j                  d       t        t        |      dd      }d|vsJ |j                         j	                  d      dk(  sJ y)	uJ   이미 .gitignore에 .worktrees/가 있으면 추가 안 되는지 확인.r   z.worktrees/
ztask-safety-2r   r   r   rU   N)r:   r
   r9   r   countr   s       r   test_gitignore_already_presentz2TestSafetyDecorator.test_gitignore_already_presentD  s^     "L0!!/2CM?FC"&000'')//>!CCCr   r   c                 n    |dz  }|j                          t        t        |      dd      }|d   dk(  sJ y)u;   git repo가 아닌 디렉토리에서 에러 반환 확인.
not_a_repoztask-safety-3r   rE   rV   N)r8   r
   r9   )rK   r   non_repor   s       r   test_non_git_repo_errorz+TestSafetyDecorator.test_non_git_repo_errorO  s=     l*CM?FCh7***r   )rY   rZ   r[   r   r   r   r   r\   r   r   r   r   7  s>    
;4 
;D 
;	Dt 	D 	D+ + +r   r   c                       e Zd ZdeddfdZy)TestFinishPrUnitr>   r   Nc                     t        j                  t        d      5  t        t	        |      ddd       ddd       y# 1 sw Y   yxY w)u3   pr 액션에서 worktree가 없으면 RuntimeError.zworktree not found)matchz
task-999.9r   r   N)pytestraisesRuntimeErrorr   r9   )rK   r>   s     r   !test_pr_action_worktree_not_foundz2TestFinishPrUnit.test_pr_action_worktree_not_found[  s<    ]]</CD 	Bs8}lFDA	B 	B 	Bs	   =A)rY   rZ   r[   r   r   r\   r   r   r   r   Z  s    B$ B4 Br   r   c                   H    e Zd ZdZdeddfdZdeddfdZd
dZd
dZd
d	Z	y)TestResolveTaskLevelu,   _resolve_task_level 함수 단위 테스트.r   r   Nc                     ddl |dz  dz  j                  d       dz  }|j                  d       d	t        d
t        ffd} |d      }|dk(  sJ y)u;   YAML frontmatter에서 level 필드를 정확히 읽는다.r   NmemorytasksTparentsztask-test-1.mdz2---
task_id: task-test-1
level: 3
---
# Test task
rf   r   c                    t        j                  |  d            t        j                  |  d            z   }|D ]{  }	 |j                  d      }|j                  d      rU|j	                  dd      }|dkD  r>j                  d|d| j                        }|rt        |j                  d	            c S } y# t        t        t        f$ r Y w xY w)
Nz.mdz*.mdutf-8encoding---   r   z^level:\s*(\d+)rU   )r`   globr   
startswithfindsearch	MULTILINEintgroupOSError
ValueError	TypeError)rf   
candidatespr   end_idxmre	tasks_dirs         r   patched_resolvezITestResolveTaskLevel.test_yaml_frontmatter_level.<locals>.patched_resolven  s    inny_=>innX_W``dUeFfAggJ 
	;;;8Du-"&))E1"5"Q; "		*<d1Wor|| \A '*1771: 6
   Y7 s   A5B>>CCztask-test-1r   )r   r8   r:   r9   r   )rK   r   	task_filer   r   r   r   s        @@r   test_yaml_frontmatter_levelz0TestResolveTaskLevel.test_yaml_frontmatter_leveld  sh    x''1	% 00	VW	S 	S 	 !/{{r   c                     |dz  dz  }|j                  d       |dz  }|j                  d       |j                  d      }|j                  d	      rJ y
)u4   frontmatter 없는 task 파일은 0을 반환한다.r   r   Tr   ztask-nolevel.mdz$# No frontmatter task
Just content.
r   r   r   N)r8   r:   r   r   )rK   r   r   r   r   s        r    test_no_frontmatter_returns_zeroz5TestResolveTaskLevel.test_no_frontmatter_returns_zero  sa    x''1	% 11	EF""G"4??5))))r   c                 (    t        d      }|dk(  sJ y)u1   실제 task-1283.1.md에서 level 2를 읽는다.ztask-1283.1   Nr	   rK   r   s     r   test_real_task_with_levelz.TestResolveTaskLevel.test_real_task_with_level  s    $]3{{r   c                 (    t        d      }|dk(  sJ y)u1   존재하지 않는 task ID는 0을 반환한다.ztask-does-not-exist-99999r   Nr   r   s     r   "test_nonexistent_task_returns_zeroz7TestResolveTaskLevel.test_nonexistent_task_returns_zero  s    $%@A{{r   c                 L    t        d      }t        |t              sJ |dk\  sJ y)uC   level 필드가 없는 task 파일은 0 또는 work_level fallback.z	task-1866r   N)r	   
isinstancer   r   s     r   test_task_without_level_fieldz2TestResolveTaskLevel.test_task_without_level_field  s(    $[1&#&&&{{r   rX   )
rY   rZ   r[   __doc__r   r   r   r   r   r   r\   r   r   r   r   a  s:    6D T 8	* 	*$ 	*

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)	TestParseGeminiCommentsr   r   Nc           	      d   t        j                  ddiddddg      }t        j                  j	                  d      5 }t        j                  g d|d	
      |_        t        dddt        |            }ddd       t              dk(  sJ |d   d   dk(  sJ |d   d   dk(  sJ y# 1 sw Y   4xY w)u?   HIGH severity 코멘트가 올바르게 파싱되는지 확인.logingemini-code-assist[bot]z=severity: high
SQL injection vulnerability in query parameterz	app/db.py*   userbodypathlineworktree_manager._runr    r   r   r   r   1ownerr!   NrU   severityhighr   r   dumpsunittestmockpatchr   CompletedProcessreturn_valuer   r9   rh   rK   r   mock_commentsmock_runr   s        r   test_parse_high_severityz0TestParseGeminiComments.test_parse_high_severity  s    

 %&?@\'		
 ]]  !89 	QX$.$?$?RTU^ktv$wH!+C&#h-PF	Q 6{aay$...ay K///	Q 	Qs   6B&&B/c           	      J   t        j                  ddiddddg      }t        j                  j	                  d      5 }t        j                  g d|d	
      |_        t        dddt        |            }ddd       t              dk(  sJ |d   d   dk(  sJ y# 1 sw Y   'xY w)u!   MEDIUM severity 코멘트 파싱.r   r   u8   severity: medium
⚠️ Consider adding input validationz
app/api.py
   r   r   r   r   r   r   r  r!   NrU   r  mediumr  r  s        r   test_parse_medium_severityz2TestParseGeminiComments.test_parse_medium_severity  s    

 %&?@W(		
 ]]  !89 	QX$.$?$?RTU^ktv$wH!+C&#h-PF	Q 6{aay$000		Q 	Qs   6BB"c           	      0   t        j                  ddiddddg      }t        j                  j	                  d      5 }t        j                  g d|d	
      |_        t        dddt        |            }ddd       t              dk(  sJ y# 1 sw Y   xY w)u2   Gemini가 아닌 사용자의 코멘트는 무시.r   zhuman-reviewerz$severity: high
This is a big problemzapp/main.pyrU   r   r   r   r   r   r   r  r!   Nr  r  s        r   test_parse_ignores_non_geminiz5TestParseGeminiComments.test_parse_ignores_non_gemini  s    

 %&67C)		
 ]]  !89 	QX$.$?$?RTU^ktv$wH!+C&#h-PF	Q 6{a	Q 	Qs   6BBc           	          t         j                  j                  d      5 }t        j                  g ddd      |_        t        dddt        |            }d	d	d	       g k(  sJ y	# 1 sw Y   xY w)
u$   API 실패 시 빈 리스트 반환.r   rU   r   rV   r   r   r  r!   N)r  r  r  r   r	  r
  r   r9   )rK   r   r  r   s       r   test_parse_api_failurez.TestParseGeminiComments.test_parse_api_failure  sn    ]]  !89 	QX$.$?$?RTU^`ip$qH!+C&#h-PF	Q ||	Q 	Qs   6A&&A/c           	         t        j                  ddiddddddiddd	dddid
dddg      }t        j                  j	                  d      5 }t        j                  g d|d      |_        t        dddt        |            }ddd       t              dk(  sJ |D cg c]  }|d   	 }}|g dk(  sJ y# 1 sw Y   5xY wc c}w )u,   HIGH + MEDIUM + LOW 혼합 코멘트 파싱.r   r   u   HIGH severity issue 🔴a.pyrU   r   u   MEDIUM severity ⚠️b.pyr   zMinor suggestionc.pyr   r   r   r   r   r   r  r!   Nr  )r  r  lowr  )rK   r   r  r  r   c
severitiess          r   test_parse_mixed_severitiesz3TestParseGeminiComments.test_parse_mixed_severities  s    

 %&?@6"	 "#<=G_ioyz{!#<=GYcistu	
 ]]  !89 	QX$.$?$?RTU^ktv$wH!+C&#h-PF	Q 6{a-34a
m4
46666	Q 	Q 5s   6B7C7C )	rY   rZ   r[   r   r  r  r  r  r  r\   r   r   r   r     sa    0 0$ 0&14 1D 1$ d  t  "t  7D 7T 7r   r   c                   D    e Zd Zd	dZd	dZd	dZd	dZd	dZd	dZd	dZ	y)
TestClassifyMediumCommentsNc                     ddddddddddg}t        |d	
      }t        |      dk(  sJ t        d |D              sJ t        d |D              sJ y)u5   수집 모드에서 모든 MEDIUM이 DEFER로 분류.r  zsql injection riskr  r   r  r   r   r   znaming convention issuer  2Tcollect_moder   c              3   ,   K   | ]  }|d    dk(    yw)classificationDEFERNr\   .0r  s     r   	<genexpr>zITestClassifyMediumComments.test_collect_mode_all_defer.<locals>.<genexpr>  s     Ba1%&'1B   c              3   ,   K   | ]  }|d    dk(    yw)pattern_matchedr%  Nr\   r)  s     r   r+  zITestClassifyMediumComments.test_collect_mode_all_defer.<locals>.<genexpr>  s     Ja1&'>9Jr,  Nr   rh   allrK   commentsr   s      r   test_collect_mode_all_deferz6TestClassifyMediumComments.test_collect_mode_all_defer  so     "+?Y\]!+Df^ab
 +8$G6{aB6BBBBJ6JJJJr   c                     dddddddddddd	d
ddg}t        |d      }t        |      dk(  sJ t        d |D              sJ |d   d   dk(  sJ |d   d   dk(  sJ |d   d   dk(  sJ y)u.   FIX 패턴 매칭 확인 (collect_mode=False).r  z$Possible sql injection in user inputdb.py10r"  zXSS vulnerability in templateztmpl.py20z race condition in counter updatez
counter.py30Fr$  r   c              3   ,   K   | ]  }|d    dk(    ywr'  FIXNr\   r)  s     r   r+  zETestClassifyMediumComments.test_fix_classification.<locals>.<genexpr>       @A1%&%/@r,  r   r.  sql injectionrU   xssr   race conditionNr/  r1  s      r   test_fix_classificationz2TestClassifyMediumComments.test_fix_classification  s     "+Q[blpq!+JT]gkl!+MWcmqr

 +8%H6{a@@@@@ay*+>>>ay*+u444ay*+/????r   c                     dddddddddddd	d
ddg}t        |d      }t        |      dk(  sJ t        d |D              sJ y)u/   SKIP 패턴 매칭 확인 (collect_mode=False).r  z!naming convention: use snake_caser  r   r"  zMissing docstring for functionr  r#  zcode style: trailing whitespacer  3Fr$  r   c              3   ,   K   | ]  }|d    dk(    ywr'  SKIPNr\   r)  s     r   r+  zFTestClassifyMediumComments.test_skip_classification.<locals>.<genexpr>       AQ1%&&0Ar,  Nr/  r1  s      r   test_skip_classificationz3TestClassifyMediumComments.test_skip_classification
  sl     "+NX^hkl!+KU[ehi!+LV\fij

 +8%H6{aA&AAAAr   c                     dddddg}t        |d      }t        |      dk(  sJ |d	   d
   dk(  sJ |d	   d   dk(  sJ y)u   패턴 미매칭은 DEFER.r  z*Consider refactoring this loop for clarityzx.pyr   r"  Fr$  rU   r   r'  r(  r.  r   Nr   rh   r1  s      r   test_defer_classificationz4TestClassifyMediumComments.test_defer_classification  sj     "+Wagqtu
 +8%H6{aay)*g555ay*+r111r   c                 Z    ddddddddd	dg}t        |d
      }t        |      dk(  sJ y)u%   MEDIUM이 아닌 코멘트는 무시.r  r=  r  r   r"  r  zminor styler  r#  Fr$  r   NrI  r1  s      r   test_ignores_non_mediumz2TestClassifyMediumComments.test_ignores_non_medium  sD      &RUVvsS
 +8%H6{ar   c           
         g d}t        |      D cg c]  \  }}dd| dd| dt        |      d }}}t        |d	      }t        |      d
k(  sJ t	        d |D              s J d|D cg c]  }|d   |d   f c}        |D cg c]  }|d   	 }}|D ]  }||v rJ d| d        yc c}}w c c}w c c}w )u6   MEDIUM_FIX_PATTERNS 15개 패턴 전체 매칭 확인.)r=  r>  csrfauth
permissionznull pointerr?  deadlockz	data loss
corruptionzenv variableconfigaccessibilitya11y
responsiver  Issue about z	 detectedfile_.pyr"  Fr$     c              3   ,   K   | ]  }|d    dk(    ywr:  r\   r)  s     r   r+  zCTestClassifyMediumComments.test_all_fix_patterns.<locals>.<genexpr>7  r<  r,  zExpected all FIX, got: r.  r'  z	Pattern 'z' not matchedN	enumerater9   r   rh   r0  )rK   fix_patternsir   r2  r   r  matched_patternss           r   test_all_fix_patternsz0TestClassifyMediumComments.test_all_fix_patterns(  s   
 ",/
1 "\!I+FRWXYWZZ]P^hklmhno
 
 +8%H6{b   @@@ 	
%\b&cWX*;(<a@P>Q'R&c%de	
@ ;AAQA/0AA 	GA((FIaS*FF(	G
 'dAs   "B0-B6B;c           
      &   g d}t        |      D cg c]  \  }}dd| dd| dt        |      d }}}t        |d	      }t        |      d
k(  sJ t	        d |D              s J d|D cg c]  }|d   |d   f c}        yc c}}w c c}w )u6   MEDIUM_SKIP_PATTERNS 6개 패턴 전체 매칭 확인.)znaming conventionz
code style
formatting
whitespaceztype annotation	docstringr  rW  z in coderX  rY  r"  Fr$     c              3   ,   K   | ]  }|d    dk(    ywrD  r\   r)  s     r   r+  zDTestClassifyMediumComments.test_all_skip_patterns.<locals>.<genexpr>J  rF  r,  zExpected all SKIP, got: r.  r'  Nr\  )rK   skip_patternsr_  r   r2  r   r  s          r   test_all_skip_patternsz1TestClassifyMediumComments.test_all_skip_patterns>  s    
 "-0
1 "\!H+EQVWXVYY\~gjklgmn
 
 +8%H6{aA&AA 	
&]c'dXY+<)=qAQ?R(S'd&ef	
A
 (es   "B-BrX   )
rY   rZ   r[   r3  r@  rG  rJ  rL  ra  ri  r\   r   r   r   r     s)    	K@	B2 G,
r   r   c                       e Zd ZddZy)TestLogMediumCommentsNc                 d   t        t              j                         j                  j                  j                  dz  dz  dz  }g }|j	                         r$	 t        j                  |j                               }t        |      }dddddg}t        |       t        j                  |j                               }t        |      |d	z   k(  sJ |d
   d   dk(  sJ |d
   d   dk(  sJ |j                  t        j                  |dd             y# t
        j                  t        f$ r g }Y w xY w)uT   _log_medium_comments가 실제 로그 파일에 엔트리를 기록하는지 확인.	dashboardrL   zmedium-comments-log.jsonr(  ztest entry from unit testztest.pyr%  )r'  r   r   r.  rU   r   r'  r   F)indentensure_asciiN)r   __file__resolveparentr   r   r   r   JSONDecodeErrorr   rh   r   r:   r  )rK   log_pathexisting_dataoriginal_count
classifiedupdated_datas         r   test_log_writes_entriesz-TestLogMediumComments.test_log_writes_entriesP  s1   >))+2299@@;NQWWZtt.0??# $

8+=+=+? @ ]+ #*3!#1	

 	Z(zz("4"4"67< NQ$6666B'+FFFFB 01W<<< 	DJJ}QUST) (('2 # "#s   #D D/.D/rX   )rY   rZ   r[   rz  r\   r   r   rk  rk  O  s    Ur   rk  c                   ,    e Zd ZddZddZddZddZy)TestAutoFixHighCommentsNc                     dddddg}t        |dd      }|d	   d
u sJ t        |d         dk(  sJ d|d   d   v sJ |d   dk(  sJ y)uC   수집 모드에서는 프롬프트만 생성, 실행하지 않음.r  SQL injection in queryr5  42r"  	/tmp/fakeTr$  executedFpromptsrU   r   	diff_statr   Nr   rh   r1  s      r   test_collect_mode_no_executionz6TestAutoFixHighComments.test_collect_mode_no_executionp  s      )A7\`a
 );TRj!U***6)$%***&+A....k"b(((r   c                 V    dddddg}t        |dd      }|d	   g k(  sJ |d
   du sJ y)u'   HIGH 코멘트가 없으면 빈 결과.r  zstyle issuer  r   r"  r  Tr$  r  r  FN)r   r1  s      r   test_no_high_commentsz-TestAutoFixHighComments.test_no_high_comments{  sN     "=&RUV
 );TRi B&&&j!U***r   c                 b    ddddddddddg}t        |d	d
      }t        |d         dk(  sJ y)u7   여러 HIGH 코멘트에서 각각 프롬프트 생성.r  zIssue 1r  r6  r"  zIssue 2r  r7  r  Tr$  r  r   Nr  r1  s      r   #test_multiple_high_comments_promptsz;TestAutoFixHighComments.test_multiple_high_comments_prompts  sK      FDQFDQ
 );TR6)$%***r   c                    dddddg}t         j                  j                  d      5 }t        j                  g ddd	
      |_        t        |dd      }ddd       d   du sJ t        |d         dk(  sJ j                  D cg c]  }t        |       }}t        d |D              sJ d       t        d |D              sJ d       y# 1 sw Y   zxY wc c}w )uK   실행 모드에서 Claude CLI 호출 + git push가 실행되는지 확인.r  r~  r5  r  r"  r   r   z1 file changedr   r   r  Fr$  Nr  Tr  rU   c              3   $   K   | ]  }d |v  
 yw)claudeNr\   r*  ss     r   r+  zKTestAutoFixHighComments.test_execution_mode_calls_claude.<locals>.<genexpr>  s     4Q8q=4   zClaude CLI should be calledc              3   $   K   | ]  }d |v  
 yw)pushNr\   r  s     r   r+  zKTestAutoFixHighComments.test_execution_mode_calls_claude.<locals>.<genexpr>  s     216Q;2r  zgit push should be called)r  r  r  r   r	  r
  r   rh   call_args_listr9   any)rK   r2  r  r   r  	call_strss         r    test_execution_mode_calls_claudez8TestAutoFixHighComments.test_execution_mode_calls_claude  s      )A7\`a
 ]]  !89 	XX$.$?$?RTU^nwy$zH!,X{QVWF	X j!T)))6)$%***%-%<%<=SV=	=4)44S6SS42	22O4OO2	X 	X >s   -CCCrX   )rY   rZ   r[   r  r  r  r  r\   r   r   r|  r|  o  s    	)++Pr   r|  )3r   r   r;   r   sysunittest.mockr  pathlibr   typingr   r   r   insertr9   rq  rr  rs  worktree_managerr   r   r   r   r	   r
   r   _WORKSPACE_ROOTr   r`   tupledictr   r   fixturer>   r@   r^   rl   rv   r   r<   r   r   r   r   r   r   r   r   rk  r|  r\   r   r   <module>r     s  
  	  
     3tH~--/66==> ?   x.((*1188??	_y(+@@	A8$s) 8d38nc&9 : 8 t   2) )(' '
' 
'&J &JR31 31njj  d S 3 4 0@% @%F +  +FB B8 8vQ7 Q7h\
 \
~U U@+P +Pr   