
    -{iAt                        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
Z
ddlmZ ddlZe
j                  j                  dd       ddlZdZdZdZded	ed
edefdZde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 G d d      Z G d d      Z G d d       Z  G d! d"      Z! G d# d$      Z"y)%u   
test_g3_verifier.py — g3_independent_verifier.py 유닛/통합 테스트
작성자: 닌기르수 (개발5팀 테스터)
태스크: task-1883
    N)Pathz/home/jay/workspace/scriptsz6/home/jay/workspace/scripts/g3_independent_verifier.pyu   # task-1883 작업 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/sample.py | 핵심 기능 추가 | grep "MAGIC_KEYWORD" OK | verified |
u  # task-1883 작업 보고서 (Lv.2)

**S**: 현재 문서 체계가 정비되지 않아 가이드라인이 누락되어 있다.

**C**: 이로 인해 신규 팀원의 온보딩 시간이 증가하고 있다.

## 개요
이 작업은 문서 수정만 포함합니다. 추가 내용을 채워 분량을 확보합니다.
작업 범위는 README 및 가이드 문서 갱신이며 코드 변경은 없습니다.
관련 이슈 없음. 단순 문서화 작업으로 완료됩니다.
tmp_pathtask_idcontentreturnc                 r    | dz  dz  }|j                  dd       || dz  }|j                  |d       |S )uJ   보고서 파일을 tmp_path/memory/reports/{task_id}.md 에 생성한다.memoryreportsTparentsexist_okz.mdutf-8encoding)mkdir
write_text)r   r   r   reports_dirreport_files        -/home/jay/workspace/tests/test_g3_verifier.pymake_reportr   1   sM    X%	1KdT27)3/K7W5    rel_pathc                 p    | |z  }|j                   j                  dd       |j                  |d       |S )uA   소스 파일을 tmp_path 하위 rel_path 위치에 생성한다.Tr   r   r   )parentr   r   )r   r   r   targets       r   make_source_filer   :   s;     F
MMt4
g0Mr   c                   *    e Zd Zd Zd Zd Zd Zd Zy)TestParseVerificationTablec                    t        j                  t              }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,   테이블 없는 보고서 → 빈 리스트==z%(py0)s == %(py3)sresultpy0py3assert %(py5)spy5N)g3vparse_verification_tableREPORT_WITHOUT_TABLE
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)selfr#   @py_assert2@py_assert1@py_format4@py_format6s         r    test_returns_empty_when_no_tablez;TestParseVerificationTable.test_returns_empty_when_no_tableH   sk    --.BCv|vvvr   c                 `   t        j                  t              }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                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}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}}	|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   }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	)u2   테이블이 있는 보고서 → 엔트리 파싱   r    z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr#   r%   py1r&   py6assert %(py8)spy8Nr   	file_pathscripts/sample.pyz%(py1)s == %(py4)sr?   py4assert %(py6)sr@   keywordMAGIC_KEYWORDstatusverified)r)   r*   REPORT_WITH_TABLEr=   r,   r-   r.   r/   r0   r1   r2   r3   )r4   r#   r5   @py_assert5@py_assert4@py_format7@py_format9entry@py_assert0@py_assert3@py_format5s              r   test_parses_verified_entryz5TestParseVerificationTable.test_parses_verified_entryM   s   --.?@6{a{a{ass66{aq	[!8%88!%88888!%8888!888%88888888Y2?2?2222?222222?2222222X,*,*,,,,*,,,,,,*,,,,,,,r   c                    d}t        j                  |      }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}}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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}y)u9   헤더 행이 엔트리로 포함되지 않아야 한다.u   ## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/a.py | 변경 | grep "FOO" OK | verified |
c              3   ,   K   | ]  }|d    dk7    yw)rC   u   파일N ).0es     r   	<genexpr>zCTestParseVerificationTable.test_skips_header_row.<locals>.<genexpr>a   s     >!1[>X->s   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr%   py2rG   Nr;   r    r<   r=   r#   r>   rA   rB   )r)   r*   r^   r.   r/   r,   r0   r1   r2   r3   r=   r-   )r4   reportr#   r6   rT   rU   r5   rN   rO   rP   rQ   s              r   test_skips_header_rowz0TestParseVerificationTable.test_skips_header_rowV   s    --f5>v>>s>>>>>>>>>s>>>s>>>>>>>>>>>>>>6{a{a{ass66{ar   c                 V   d}t        j                  |      }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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}|d   d   }d
}	||	u }|slt        j                  d|fd||	f      t        j                  |      t        j                  |	      dz  }
dd|
iz  }t        t        j                  |            d
x}x}}	y
)u@   grep 검증 컬럼에 키워드 패턴이 없으면 keyword=Noneu   ## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/b.py | 변경 | 없음 | verified |
r;   r    r<   r=   r#   r>   rA   rB   Nr   rI   )is)z%(py1)s is %(py4)srF   rH   r@   r)   r*   r=   r,   r-   r.   r/   r0   r1   r2   r3   r4   ra   r#   r5   rN   rO   rP   rQ   rS   rT   rU   s              r   #test_no_keyword_when_grep_col_emptyz>TestParseVerificationTable.test_no_keyword_when_grep_col_emptyd   s     --f56{a{a{ass66{aay#+t+#t++++#t+++#+++t+++++++r   c                 ^   d}t        j                  |      }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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}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}}	|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   여러 엔트리 파싱u   ## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/a.py | 변경A | grep "KEY_A" OK | verified |
| scripts/b.py | 변경B | grep "KEY_B" OK | verified |
   r    r<   r=   r#   r>   rA   rB   Nr   rI   KEY_ArE   rF   rH   r@   r;   KEY_Bre   rf   s              r   test_multiple_entriesz0TestParseVerificationTable.test_multiple_entriesq   sS    --f56{a{a{ass66{aay#.w.#w....#w...#...w.......ay#.w.#w....#w...#...w.......r   N)__name__
__module____qualname__r9   rV   rb   rg   rl   rY   r   r   r   r   G   s    
- ,/r   r   c                       e Zd Zd Zd Zd Zy)TestResolveFilePathc                 |   |j                  t        dd       t        j                  d      }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                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}y)u!   절대 경로는 그대로 반환WORKSPACE_ROOTz/tmp/wsz/absolute/path/file.pyr    r<   strr#   r>   rA   rB   N)setattrr)   resolve_file_pathrt   r,   r-   r.   r/   r0   r1   r2   r3   )r4   monkeypatchr#   r5   rN   rO   rP   rQ   s           r   test_absolute_path_unchangedz0TestResolveFilePath.test_absolute_path_unchanged   s    C!19=&&'?@6{666{66666{6666666s666s66666666666666{66666666666r   c                    |j                  t        dt        |             t        j                  d      }d}||z  }d}||z  }||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t	        j                  |      t	        j                  |      d	z  }	d
d|	iz  }
t        t	        j                  |
            dx}x}x}x}}y)uA   상대 경로는 WORKSPACE_ROOT 기준으로 절대 경로 변환rs   rD   scripts	sample.pyr    )z*%(py0)s == ((%(py2)s / %(py4)s) / %(py7)s)r#   r   r%   r`   rG   py7zassert %(py10)spy10N)ru   r)   rt   rv   r,   r-   r.   r/   r0   r1   r2   r3   )r4   rw   r   r#   rT   rN   @py_assert6@py_assert8r6   rQ   @py_format11s              r   /test_relative_path_prefixed_with_workspace_rootzCTestResolveFilePath.test_relative_path_prefixed_with_workspace_root   s    C!13x=A&&':;$-;I-;;-;;v;;;;;v;;;;;;;v;;;v;;;;;;;;;;;;I;;;;;;;;;;;r   c           	         |j                  t        dt        |             t        j                  d      }t        |      }|j                  }d} ||      }|sd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                  |      t        j                  |      dz  }t        t        j                  |            dx}x}x}}d	}	t        |      }
|	|
v}|st        j                  d
|fd|	|
f      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                  |
      dz  }dd|iz  }t        t        j                  |            dx}	x}}
y)u4   경로:라인번호 형식에서 라인번호 제거rs   zscripts/sample.py:42rD   zhassert %(py9)s
{%(py9)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.endswith
}(%(py7)s)
}rt   r#   )r%   r?   r&   r(   r}   py9Nz:42)not in)z4%(py1)s not in %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
})r?   r&   rG   r@   rA   rB   )ru   r)   rt   rv   endswithr.   r/   r,   r0   r1   r2   r3   r-   )r4   rw   r   r#   r5   rO   r   r   @py_format10rS   rN   rP   rQ   s                r   test_strips_line_number_suffixz2TestResolveFilePath.test_strips_line_number_suffix   s\   C!13x=A&&'=>6{8{##8$78#$788888888s888s88888868886888{888#888$78888888888'CK'uK''''uK'''u''''''C'''C''''''''''''K'''''''r   N)rm   rn   ro   rx   r   r   rY   r   r   rq   rq      s    7<(r   rq   c                       e Zd Zd Zd Zy)TestCheckFileExistencec                    |j                  t        dt        |             |dz  dz  }|j                  j	                  dd       |j                  d       ddig}t        j                  |      \  }}d	}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}}g }||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"   모든 파일이 존재하면 PASSrs   rz   r{   Tr   z# existsrC   rD   PASSr    r"   rK   r$   r'   r(   Nmissing)ru   r)   rt   r   r   r   check_file_existencer,   r-   r.   r/   r0   r1   r2   r3   )r4   rw   r   r   entriesrK   r   r5   r6   r7   r8   s              r   test_pass_when_all_files_existz5TestCheckFileExistence.test_pass_when_all_files_exist   s    C!13x=AI%3D48*%!456227;vvvvw"}w"ww"r   c                    |j                  t        dt        |             ddig}t        j                  |      \  }}d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }d	d
|iz  }	t        t	        j                  |	            dx}}d}
|
|v }|st	        j
                  d|fd|
|f      t	        j                  |
      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }	t        t	        j                  |	            dx}
}y)u+   파일이 없으면 FAIL + 파일명 반환rs   rC   zscripts/nonexistent.pyFAILr    r"   rK   r$   r'   r(   Ninz%(py1)s in %(py3)sr   r?   r&   )ru   r)   rt   r   r,   r-   r.   r/   r0   r1   r2   r3   )r4   rw   r   r   rK   r   r5   r6   r7   r8   rS   s              r   test_fail_when_file_missingz2TestCheckFileExistence.test_fail_when_file_missing   s    C!13x=A!9:;227;vvvv'2'72222'7222'222222722272222222r   N)rm   rn   ro   r   r   rY   r   r   r   r      s    
3r   r   c                   $    e Zd Zd Zd Zd Zd Zy)TestRunGrepVerificationc                    |j                  t        dt        |             |dz  dz  }|j                  j	                  dd       |j                  d       ddd	d
g}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}}g }||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(   키워드가 파일에 존재하면 PASSrs   rz   r{   Tr   def MAGIC_KEYWORD(): pass
rD   rJ   rL   rC   rI   rK   r   r    r"   rK   r$   r'   r(   Nfailedru   r)   rt   r   r   r   run_grep_verificationr,   r-   r.   r/   r0   r1   r2   r3   r4   rw   r   srcr   rK   r   r5   r6   r7   r8   s              r   test_pass_when_keyword_foundz4TestRunGrepVerification.test_pass_when_keyword_found   s*   C!13x=A"[0

545 1*$
 227;vvvvv|vvvr   c                 X   |j                  t        dt        |             |dz  dz  }|j                  j	                  dd       |j                  d       ddd	d
g}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}}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                  |      rt        j                  |      nd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%   키워드가 파일에 없으면 FAILrs   rz   r{   Tr   def other_function(): pass
rD   rJ   rL   r   r   r    r"   rK   r$   r'   r(   Nr;   r<   r=   r   r>   rA   rB   r   r   z%(py1)s in %(py4)srF   rH   r@   )ru   r)   rt   r   r   r   r   r,   r-   r.   r/   r0   r1   r2   r3   r=   )r4   rw   r   r   r   rK   r   r5   r6   r7   r8   rN   rO   rP   rQ   rS   rT   rU   s                     r   test_fail_when_keyword_missingz6TestRunGrepVerification.test_fail_when_keyword_missing   s   C!13x=A"[0

556 1*$
 227;vvvv6{a{a{ass66{a+&)+)++++)++++++)+++++++r   c                    |j                  t        dt        |             ddddg}t        j                  |      \  }}d}||k(  }|st	        j
                  d|fd||f      d	t        j                         v st	        j                  |      rt	        j                  |      nd	t	        j                  |      d
z  }dd|iz  }	t        t	        j                  |	            dx}}g }||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)u9   status가 verified가 아닌 항목은 grep 검사 스킵rs   rD   rJ   pendingr   r   r    r"   rK   r$   r'   r(   Nr   )ru   r)   rt   r   r,   r-   r.   r/   r0   r1   r2   r3   )
r4   rw   r   r   rK   r   r5   r6   r7   r8   s
             r   test_skips_non_verified_entriesz7TestRunGrepVerification.test_skips_non_verified_entries   s    C!13x=A 1*#
 227;vvvvv|vvvr   c                    |j                  t        dt        |             |dz  dz  }|j                  j	                  dd       |j                  d       ddd	d
g}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}}g }||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!   keyword가 None이면 grep 스킵rs   rz   r{   Tr   zdef func(): pass
rD   NrL   r   r   r    r"   rK   r$   r'   r(   r   r   r   s              r    test_skips_entry_without_keywordz8TestRunGrepVerification.test_skips_entry_without_keyword   s*   C!13x=A"[0

5+, 1$
 227;vvvvv|vvvr   N)rm   rn   ro   r   r   r   r   rY   r   r   r   r      s    $,&r   r   c                   4    e Zd ZdZd Zd Zd Zd Zd Zd Z	y)	TestG3VerifierIntegrationu   
    subprocess로 g3_independent_verifier.py를 직접 실행하거나,
    monkeypatch로 WORKSPACE_ROOT를 교체하여 main()을 호출하는 통합 테스트.
    c                 P   |j                  t        dt        |             |j                  t        ddd|g       t	        j
                  t              5 }t        j                          ddd       |j                  j                  S # 1 sw Y   j                  j                  S xY w)u   
        main()을 직접 호출하고 exit code를 캡처한다.
        sys.argv와 WORKSPACE_ROOT를 monkeypatch로 교체한다.
        rs   argvg3_independent_verifier.py	--task-idN
ru   r)   rt   syspytestraises
SystemExitmainvaluecoder4   rw   r   r   exc_infos        r   _run_main_with_argsz-TestG3VerifierIntegration._run_main_with_args  s}    
 	C!13x=AC*FU\)]^]]:& 	(HHJ	~~"""	~~"""   BB%c                    d}d}t        |||       t        |dd       | j                  |||      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }	t        t        j                  |	            dx}}y)uC   정상 보고서 + 키워드가 존재하는 파일 → exit code 0z	task-9001u   # task-9001 작업 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/sample.py | 핵심 기능 추가 | grep "MAGIC_KEYWORD" OK | verified |
rD   r   r   r    r"   	exit_coder$   r'   r(   Nr   r   r   r,   r-   r.   r/   r0   r1   r2   r3   
r4   r   rw   r   report_contentr   r5   r6   r7   r8   s
             r   test_pass_with_valid_reportz5TestG3VerifierIntegration.test_pass_with_valid_report  s     	Hg~6 	#68UV ,,[(GL	yA~yAyyAr   c                    d}d}t        |||       t        |dd       | j                  |||      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }d
d|iz  }	t        t        j                  |	            dx}}|dz  dz  | dz  }
|
j                  } |       }|st        j                  d      dz   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   }||k(  }|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   }t!        |      }d}||kD  }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      dz  }dd |iz  }t        t        j                  |            dx}x}x}}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)$ue   보고서에 verified 키워드가 있으나 실제 파일에 없음 → exit code 1 + g3-fail 생성z	task-9002u   # task-9002 작업 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/sample.py | 핵심 기능 추가 | grep "MISSING_SYMBOL" OK | verified |
rD   r   r;   r    r"   r   r$   r'   r(   Nr	   events.g3-failu(   g3-fail 파일이 생성되어야 한다zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}	fail_filer_   r   r   r   )z%(py1)s == %(py3)sr   fail_reasonsr   )>)z/%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} > %(py7)sr=   r|   assert %(py9)sr   c              3   $   K   | ]  }d |v  
 yw)MISSING_SYMBOLNrY   rZ   rs     r   r\   zFTestG3VerifierIntegration.test_fail_missing_keyword.<locals>.<genexpr>R  s     LQ#q(L   r]   any)r   r   r   r,   r-   r.   r/   r0   r1   r2   r3   exists_format_assertmsgjsonloads	read_textr=   r   )r4   r   rw   r   r   r   r5   r6   r7   r8   r   rT   rU   	fail_datarS   r   rN   @py_format8r   s                      r   test_fail_missing_keywordz3TestG3VerifierIntegration.test_fail_missing_keyword6  s    	Hg~6 	#68VW,,[(GL	yA~yAyyA x'(2y5II	M!M!MM#MMMMMMMyMMMyMMMMMM!MMMMMMJJy22G2DE	#.#w....#w...#......w...w.......^,1s,-11-1111-111111s111s111,111-1111111111L)N2KLLsLLLLLLLLLsLLLsLLLLLLLLLLLLLLr   c                    d}|dz  dz  j                  dd       |j                  t        dt        |             |j                  t        ddd	|g       d
dl}g |j                  fd}|j                  |d|       t        j                  t              5 }t        j                          ddd       j                  }|j                  }d}	||	k(  }
|
st        j                  d|
fd||	f      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}
}	d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# 1 sw Y   xY w)uY   보고서 파일이 없으면 exit code 1 + 에러 메시지에 'report not found' 포함z	task-9003r	   r
   Tr   rs   r   r   r   r   Nc                  h    dj                  d | D              }j                  |        | i | y )N c              3   2   K   | ]  }t        |        y wNrt   rZ   as     r   r\   zYTestG3VerifierIntegration.test_fail_no_report.<locals>.capturing_print.<locals>.<genexpr>f       1qCF1   joinappendargskwargslineoriginal_printoutput_liness      r   capturing_printzFTestG3VerifierIntegration.test_fail_no_report.<locals>.capturing_printe  2    881D11D%D+F+r   printr;   r    )zG%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.code
} == %(py7)sr   r|   r   r   
report not foundr   r   
all_outputr   r'   r(   )r   ru   r)   rt   r   builtinsr   r   r   r   r   r   r   r,   r-   r.   r/   r0   r1   r2   r3   r   )r4   r   rw   r   r   r   r   r6   rT   r   rN   r   r   r   rS   r5   r7   r8   r   r   s                     @@r   test_fail_no_reportz-TestG3VerifierIntegration.test_fail_no_reportW  s   	H	y	(//t/LC!13x=AC*FU\)]^!	,
 	Hg?]]:& 	(HHJ	 ~~'~""'a'"a''''"a''''''x'''x'''~'''"'''a''''''' YY|,
!/!Z////!Z///!//////Z///Z///////	 	s   II$c                    d}t        ||t               | j                  |||      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}y	)
u;   테이블 없는 보고서 → PASS with SKIP (exit code 0)z	task-9004r   r    r"   r   r$   r'   r(   N)r   r+   r   r,   r-   r.   r/   r0   r1   r2   r3   )	r4   r   rw   r   r   r5   r6   r7   r8   s	            r   test_skip_lv2_no_tablez0TestG3VerifierIntegration.test_skip_lv2_no_tablex  s    Hg';<,,[(GL	yA~yAyyAr   c                    t         j                  j                         }t        |      |d<   |dz  dz  j	                  dd       t        j                  dt        ddgdd|d	
      }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                   |            dx}x}}|j"                  |j$                  z   }	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)uJ   subprocess로 스크립트를 실행 — 보고서 없음 → returncode 1rs   r	   r
   Tr   python3r   ztask-subprocess-test   )capture_outputtextenvtimeoutr;   r    )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sr#   )r%   r`   r(   zassert %(py7)sr}   Nr   r   r   outputr   r'   r(   )osenvironcopyrt   r   
subprocessrunSCRIPT_PATH
returncoder,   r-   r.   r/   r0   r1   r2   r3   stdoutstderr)r4   r   r   r#   r6   rO   rT   r8   r   r   rS   r5   r7   s                r   test_subprocess_no_reportz3TestG3VerifierIntegration.test_subprocess_no_report  sG   jjoo #H	H	y	(//t/L[2HI
   %A% A%%%% A%%%%%%v%%%v%%% %%%A%%%%%%%.!+!V++++!V+++!++++++V+++V+++++++r   N)
rm   rn   ro   __doc__r   r   r   r   r   r  rY   r   r   r   r     s(    
	#4MB0B,r   r   c                   $    e Zd Zd Zd Zd Zd Zy)TestCheckPlannedItemsc                    ddddddddd	dg}t        j                  |      \  }}d
}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}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                  |      rt        j                  |      nd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}}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'   planned 상태 항목이 있으면 FAILscripts/a.py   변경ANplannedrC   descriptionrI   rK   scripts/b.py   변경Brk   rL   r   r    r"   rK   r$   r'   r(   r;   r<   r=   detailsr>   rA   rB   u   1건r   r   r   rF   rH   r@   )r)   check_planned_itemsr,   r-   r.   r/   r0   r1   r2   r3   r=   )r4   r   rK   r  r5   r6   r7   r8   rN   rO   rP   rQ   rS   rT   rU   s                  r   "test_fail_when_planned_items_existz8TestCheckPlannedItems.test_fail_when_planned_items_exist  s    )t_hi(wblm
 11':vvvv7| q |q    |q      s   s      7   7   |   q       ##v####v###v##########++~++++~+++~++++++++++r   c                    dddddg}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      d	t	        j
                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}}g }||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    planned 항목이 없으면 PASSr  r  rj   rL   r  r   r    r"   rK   r$   r'   r(   Nr  
r)   r  r,   r-   r.   r/   r0   r1   r2   r3   )r4   r   rK   r  r5   r6   r7   r8   s           r   test_pass_when_no_planned_itemsz5TestCheckPlannedItems.test_pass_when_no_planned_items  s     )wblm
 11':vvvvw"}w"ww"r   c                    ddddddddg}t        j                  |      \  }}d}||k(  }|st        j                  d|fd	||f      d
t	        j
                         v st        j                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}d}|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=   planned 항목 여러 개 → 모두 FAIL 메시지에 포함r  r  r  )rC   r  rK   r  r  r   r    r"   rK   r$   r'   r(   Nu   2건r   r   r   rF   rH   r@   r  )r4   r   rK   r  r5   r6   r7   r8   rS   rT   rU   rP   s               r   test_fail_with_multiple_plannedz5TestCheckPlannedItems.test_fail_with_multiple_planned  s     )iX(iX
 11':vvvv##v####v###v##########r   c                    t        j                  g       \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}g }||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   빈 entries → PASSr   r    r"   rK   r$   r'   r(   Nr  r  )r4   rK   r  r5   r6   r7   r8   s          r   test_pass_when_empty_entriesz2TestCheckPlannedItems.test_pass_when_empty_entries  s    11"5vvvvw"}w"ww"r   N)rm   rn   ro   r  r  r  r  rY   r   r   r
  r
    s    
,$r   r
  c                       e Zd Zd Zd Zd Zy) TestG3VerifierPlannedIntegrationc                 P   |j                  t        dt        |             |j                  t        ddd|g       t	        j
                  t              5 }t        j                          d d d        |j                  j                  S # 1 sw Y   j                  j                  S xY wNrs   r   r   r   r   r   s        r   r   z4TestG3VerifierPlannedIntegration._run_main_with_args  {    C!13x=AC*FU\)]^]]:& 	(HHJ	~~"""	~~"""r   c                    d}d}t        |||       t        |dd       t        |dd       | j                  |||      }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}}|dz  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 |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)u2   보고서에 planned 항목 포함 → exit code 1z	task-9010u  # task-9010 작업 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/done.py | 완료된 변경 | grep "DONE_KEY" OK | verified |
| scripts/todo.py | 미완료 변경 | 없음 | planned |
zscripts/done.pyzDONE_KEY = True
zscripts/todo.pyz# not done yet
r;   r    r"   r   r$   r'   r(   Nr	   r   r   Aassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}r   r_   r   r   c              3   @   K   | ]  }d |j                         v   yw)r  N)lowerr   s     r   r\   zTTestG3VerifierPlannedIntegration.test_fail_with_planned_in_report.<locals>.<genexpr>  s     Ma9	)Ms   r   r]   r   )r   r   r   r,   r-   r.   r/   r0   r1   r2   r3   r   r   r   r   r   )r4   r   rw   r   r   r   r5   r6   r7   r8   r   rT   rU   r   s                 r    test_fail_with_planned_in_reportzATestG3VerifierPlannedIntegration.test_fail_with_planned_in_report  s   	 	Hg~6#46IJ#46HI,,[(GL	yA~yAyyA x'(2y5II	!!!!!!!!!y!!!y!!!!!!!!!!!!!JJy22G2DE	M9^3LMMsMMMMMMMMMsMMMsMMMMMMMMMMMMMMr   c                    d}d}t        |||       t        |dd       t        |dd       | j                  |||      }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}}y)u)   모든 항목이 verified → exit code 0z	task-9011u  # task-9011 작업 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/a.py | 변경 A | grep "KEY_A" OK | verified |
| scripts/b.py | 변경 B | grep "KEY_B" OK | verified |
r  zKEY_A = True
r  zKEY_B = True
r   r    r"   r   r$   r'   r(   Nr   r   s
             r   test_pass_with_all_verifiedz<TestG3VerifierPlannedIntegration.test_pass_with_all_verified  s    	 	Hg~6>3CD>3CD,,[(GL	yA~yAyyAr   N)rm   rn   ro   r   r&  r(  rY   r   r   r  r    s    #N4r   r  c                   0    e Zd Zd Zd Zd Zd Zd Zd Zy)TestCheckReportQualityc                    d}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            d	x}x}	}y	)u;   1줄짜리 보고서 → FAIL (SCQA 부족 + 분량 부족)u   # task-xxx
끝.r   r    r"   rK   r$   r'   r(   Nr;   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr=   issuesr>   rA   rB   )r)   check_report_qualityr,   r-   r.   r/   r0   r1   r2   r3   r=   )r4   ra   rK   r-  r5   r6   r7   r8   rN   rO   rP   rQ   s               r   test_fail_minimal_reportz/TestCheckReportQuality.test_fail_minimal_report  s    #11&9vvvv6{a{a{ass66{ar   c                    d}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}d
 |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	)u$   200자 미만 + SCQA 없음 → FAILu5   짧은 보고서입니다.
내용이 부족합니다.r   r    r"   rK   r$   r'   r(   Nc              3   0   K   | ]  }d |v xs d|v   yw)SCQA   분량NrY   rZ   is     r   r\   zATestCheckReportQuality.test_fail_short_no_scqa.<locals>.<genexpr>  s      @A6Q;/(a-/@s   r]   r   r_   r)   r.  r,   r-   r.   r/   r0   r1   r2   r3   r   
r4   ra   rK   r-  r5   r6   r7   r8   rT   rU   s
             r   test_fail_short_no_scqaz.TestCheckReportQuality.test_fail_short_no_scqa  s    I11&9vvvv@@@s@@@@@@@@@s@@@s@@@@@@@@@@@@@@r   c                    d}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}g }||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)   SCQA 2개 이상 + 200자 이상 → PASSu.  # 보고서

**S**: 현재 상황입니다. 시스템이 정상 동작 중입니다.

**C**: 문제가 발생했습니다. 특정 기능이 작동하지 않습니다.

추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 추가내용 r   r    r"   rK   r$   r'   r(   Nr-  
r)   r.  r,   r-   r.   r/   r0   r1   r2   r3   r4   ra   rK   r-  r5   r6   r7   r8   s           r   test_pass_scqa_with_lengthz1TestCheckReportQuality.test_pass_scqa_with_length  s     Y11&9vvvvv|vvvr   c                    d}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}d
 |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	)u:   SCQA 1개만 존재 + 200자 이상 → FAIL (SCQA 부족)u  # 보고서

**S**: 현재 상황입니다.

내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. 내용을 채우기 위한 텍스트입니다. r   r    r"   rK   r$   r'   r(   Nc              3   $   K   | ]  }d |v  
 yw)r2  NrY   r4  s     r   r\   zATestCheckReportQuality.test_fail_scqa_only_one.<locals>.<genexpr>  s     /16Q;/r   r]   r   r_   r6  r7  s
             r   test_fail_scqa_only_onez.TestCheckReportQuality.test_fail_scqa_only_one  s    }11&9vvvv///s/////////s///s//////////////r   c                    d}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}g }||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*   '## S -', '## C -' 형식의 SCQA → PASSu  # 보고서

## S - 상황
현재 상황 설명입니다.

## C - 문제
문제 설명입니다.

내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 내용 r   r    r"   rK   r$   r'   r(   Nr-  r:  r;  s           r    test_pass_with_header_style_scqaz7TestCheckReportQuality.test_pass_with_header_style_scqa   s     O11&9vvvvv|vvvr   c                    d}t        j                  |      \  }}d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}d
 |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	)u%   SCQA 있지만 200자 미만 → FAILu   **S**: 상황.
**C**: 문제.r   r    r"   rK   r$   r'   r(   Nc              3   $   K   | ]  }d |v  
 yw)r3  NrY   r4  s     r   r\   zDTestCheckReportQuality.test_fail_length_under_200.<locals>.<genexpr>,  s     1Q8q=1r   r]   r   r_   r6  r7  s
             r   test_fail_length_under_200z1TestCheckReportQuality.test_fail_length_under_200'  s    111&9vvvv1&11s111111111s111s11111111111111r   N)	rm   rn   ro   r/  r8  r<  r?  rA  rD  rY   r   r   r*  r*    s!     A02r   r*  c                   $    e Zd Zd Zd Zd Zd Zy)TestParseVerificationTableV9c                 X   d}t        j                  |      }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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}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^   '수정 파일별 검증 상태' 섹션의 테이블만 파싱, 다른 섹션 테이블 무시u  ## 시나리오 목록

| 시나리오 | 설명 | 결과 | 비고 |
|----------|------|------|------|
| 로그인 테스트 | 로그인 동작 확인 | 성공 | 없음 |

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/auth.py | 인증 로직 수정 | grep "validate_token" OK | verified |

## 결론

| 항목 | 상태 |
|------|------|
| 전체 | 완료 |
r;   r    r<   r=   r#   r>   rA   rB   Nr   rC   scripts/auth.pyrE   rF   rH   r@   re   rf   s              r   %test_only_parses_verification_sectionzBTestParseVerificationTableV9.test_only_parses_verification_section5  s   & --f56{a{a{ass66{aay%:)::%):::::%)::::%:::)::::::::r   c                 X   d}t        j                  |      }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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}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,   파일 경로 패턴이 아닌 행은 무시u4  ## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/real.py | 실제 파일 | grep "KEY" OK | verified |
| 로그인 테스트 | 시나리오 설명 | 성공 | verified |
| 사용자 조회 | API 설명 | 통과 | verified |
r;   r    r<   r=   r#   r>   rA   rB   Nr   rC   zscripts/real.pyrE   rF   rH   r@   re   rf   s              r   test_ignores_non_file_rowsz7TestParseVerificationTableV9.test_ignores_non_file_rowsN  s    --f56{a{a{ass66{aay%:)::%):::::%)::::%:::)::::::::r   c                 R   d}t        j                  |      }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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}y
)u.   절대 경로(/로 시작)도 파일로 인식u   ## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| /home/jay/workspace/scripts/test.py | 수정 | grep "KEY" OK | verified |
r;   r    r<   r=   r#   r>   rA   rB   Nre   r4   ra   r#   r5   rN   rO   rP   rQ   s           r   test_accepts_absolute_pathsz8TestParseVerificationTableV9.test_accepts_absolute_paths]  s     --f56{a{a{ass66{ar   c                 R   d}t        j                  |      }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                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}y
)u!   다양한 확장자 파일 인식u  ## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| src/app.tsx | 컴포넌트 수정 | grep "Component" OK | verified |
| config/settings.yaml | 설정 변경 | grep "timeout" OK | verified |
ri   r    r<   r=   r#   r>   rA   rB   Nre   rM  s           r   test_accepts_various_extensionsz<TestParseVerificationTableV9.test_accepts_various_extensionsi  s     --f56{a{a{ass66{ar   N)rm   rn   ro   rI  rK  rN  rP  rY   r   r   rF  rF  4  s    ;2;
  r   rF  c                   "    e Zd ZdZd Zd Zd Zy)TestG3VerifierV5Integrationu7   V-5 통합 테스트: 빈 보고서로 g3 통과 방지c                 P   |j                  t        dt        |             |j                  t        ddd|g       t	        j
                  t              5 }t        j                          d d d        |j                  j                  S # 1 sw Y   j                  j                  S xY wr   r   r   s        r   r   z/TestG3VerifierV5Integration._run_main_with_args  r!  r   c                     d}d}t        |||       | j                  |||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd	|iz  }	t        t        j                  |	            d
x}}|dz  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
)u7   검증 시나리오 1: 1줄짜리 보고서 → g3 FAILz	task-9020u   # task-9020
끝.r;   r    r"   r   r$   r'   r(   Nr	   r   r   r#  r   r_   )r   r   r,   r-   r.   r/   r0   r1   r2   r3   r   )r4   r   rw   r   r   r   r5   r6   r7   r8   r   rT   rU   s                r   test_fail_one_line_reportz5TestG3VerifierV5Integration.test_fail_one_line_report  s    ,Hg~6,,[(GL	yA~yAyyA x'(2y5II	!!!!!!!!!y!!!y!!!!!!!!!!!!!r   c                    d}d}t        |||       | j                  |||      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd	|iz  }	t        t        j                  |	            d
x}}y
)uR   검증 시나리오 2: SCQA 포함 + 테이블 없는 조사 보고서 → g3 PASSz	task-9021u  # task-9021 조사 보고서

**S**: 현재 시스템은 정상 운영 중이며, 데이터 파이프라인이 안정적으로 동작하고 있다.

**C**: 그러나 최근 데이터 지연이 간헐적으로 발생하여 사용자 불만이 증가하고 있다.

**Q**: 데이터 지연의 근본 원인은 무엇이며 해결 가능한가?

**A**: 조사 결과 캐시 만료 정책이 원인으로 확인되었고, TTL 조정으로 해결 가능하다.

상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. 상세 내용입니다. r   r    r"   r   r$   r'   r(   N)
r   r   r,   r-   r.   r/   r0   r1   r2   r3   r   s
             r   test_pass_scqa_no_tablez3TestG3VerifierV5Integration.test_pass_scqa_no_table  s    . 	 	Hg~6,,[(GL	yA~yAyyAr   N)rm   rn   ro   r  r   rU  rW  rY   r   r   rR  rR  |  s    A#"r   rR  c                       e Zd ZdZd Zd Zy)TestG3VerifierV9IntegrationuY   V-9 통합 테스트: 여러 테이블이 있는 보고서 → 검증 테이블만 파싱c                    |j                  t        dt        |             |j                  t        ddd|g       dd l}g |j
                  fd}|j                  |d|       t        j                  t              5 }t        j                          d d d        j                  j                  dj                        fS # 1 sw Y   0xY w)	Nrs   r   r   r   r   c                  h    dj                  d | D              }j                  |        | i | y )Nr   c              3   2   K   | ]  }t        |        y wr   r   r   s     r   r\   z[TestG3VerifierV9Integration._run_main_with_args.<locals>.capturing_print.<locals>.<genexpr>  r   r   r   r   s      r   r   zHTestG3VerifierV9Integration._run_main_with_args.<locals>.capturing_print  r   r   r   r   )ru   r)   rt   r   r   r   r   r   r   r   r   r   r   )	r4   rw   r   r   r   r   r   r   r   s	          @@r   r   z/TestG3VerifierV9Integration._run_main_with_args  s    C!13x=AC*FU\)]^!	, 	Hg?]]:& 	(HHJ	~~""DIIl$;;;	 	s   CCc                    d}d}t        |||       t        |dd       | j                  |||      \  }}d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }	d
d|	iz  }
t        t        j                  |
            dx}}t        j                  |      }|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}}y)u_   검증 시나리오 3: 여러 테이블 → 검증 테이블만 파싱, 정보 테이블 무시z	task-9030ug  # task-9030 작업 보고서

**S**: 현재 인증 모듈에 보안 취약점이 보고되었다.

**C**: 토큰 만료 검증 로직이 누락되어 만료된 토큰으로 접근이 가능하다.

**Q**: 토큰 검증 로직을 추가하여 보안 취약점을 해결할 수 있는가?

**A**: validate_token 함수에 만료 검증 추가로 해결 완료. pytest 5 passed, 0 failed.

## 시나리오 목록

| 시나리오 | 설명 | 결과 | 비고 |
|----------|------|------|------|
| 만료 토큰 | 만료된 토큰 거부 | 성공 | 핵심 시나리오 |
| 유효 토큰 | 정상 토큰 허용 | 성공 | 기본 동작 |

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/auth.py | 토큰 검증 추가 | grep "validate_token" OK | verified |

## 결론

전체 작업 완료.
rH  zdef validate_token(): pass
r   r    r"   r   r$   r'   r(   Nchecksreport_parseentries_foundr;   rE   rF   rH   r@   )r   r   r   r,   r-   r.   r/   r0   r1   r2   r3   r   r   )r4   r   rw   r   r   r   r   r5   r6   r7   r8   r#   rS   rT   rU   rP   s                   r   test_multi_table_reportz3TestG3VerifierV9Integration.test_multi_table_report  s   8 	Hg~6#46TU 44[(GT	6yA~yAyyA F#h/@EAE@AEEEE@AEEE@EEEAEEEEEEEr   N)rm   rn   ro   r  r   ra  rY   r   r   rY  rY    s    c<'Fr   rY  )#r  r   r.   _pytest.assertion.rewrite	assertionrewriter,   r   r   r  r   pathlibr   r   pathinsertg3_independent_verifierr)   r  rM   r+   rt   r   r   r   rq   r   r   r   r
  r  r*  rF  rR  rY  rY   r   r   <module>ri     s     	  
   0 1 % G  $  s t t s S T 7/ 7/~( (43 36E EZK, K,f$ $X4 4x)2 )2b@  @ P% %Z9F 9Fr   