
    LiP                     2   d Z ddlZddlmc mZ ddlZddlZddl	Z	ddl
mZ ddlZddlZ eej                  j                  dd            Zedz  dz  dz  Zg d	Zd
ede	j&                  fdZ ej*                         d
ede	j&                  fd       Z G d d      Z G d d      Zej2                  j5                  dd       ddlmZ d&dededefdZd'dede defdZ!d(dede"de"defdZ#dedededededefd Z$ G d! d"      Z%edz  d#z  Z& G d$ d%      Z'y))u  
test_3docs_e2e.py — 3문서 2유형 체계 End-to-End 통합 테스트

Phase 1~5 구현 완료된 3문서 체계(plan.md / context-notes.md / checklist.md)의
전체 흐름을 4개 그룹으로 검증한다:
  1. dispatch → 3문서 자동 생성
  2. team_prompts 3문서 지침 포함 여부
  3. QC verifier 3문서 검증 (PASS / WARN / SKIP / FAIL 시나리오)
  4. DIRECT-WORKFLOW.md 3문서 단계 존재 확인

기존 tests/test_dispatch_task_docs.py 와 독립 파일로 작성되어 충돌 없이 병렬 실행 가능.
    N)PathWORKSPACE_ROOT/home/jay/workspaceprompts	templates	task-docs)zplan.template.mdzcontext-notes.template.mdzchecklist.template.mdtmp_pathreturnc                    t        t        j                  j                  dd            }t	        |      t
        j                  vr)t
        j                  j                  dt	        |             ddl}t        t
        j                  j                               D ]  }|dk(  s	t
        j                  |=  ddl}| |_        |S )uM   dispatch 모듈을 tmp_path를 WORKSPACE로 설정하여 격리 로드한다.r   r   r   Ndispatch)r   osenvirongetstrsyspathinsertprompts.team_promptslistmoduleskeysr   	WORKSPACE)r	   	workspacer   mod_name	_dispatchs        +/home/jay/workspace/tests/test_3docs_e2e.py_load_dispatch_with_workspacer   '   s    RZZ^^$46KLMI
9~SXX%3y>*   ))+, &z!H%& ! #I    c              #   $  K   | dz  j                  dd       | dz  dz  j                  dd       | dz  dz  dz  }|j                  dd       t        D ]B  }t        |z  }|j                         s||z  j	                  |j                  d	      d	       D t        t        j                  j                  d
d            }t        j                  j                  d      }t        |       }| ||_        ||t        j                  d<   yyw)uU   격리된 WORKSPACE를 사용하는 dispatch 모듈 반환 + 템플릿 파일 복사.memoryTparentsexist_oktasksr   r   r   utf-8encodingr   r   r   N)mkdirTEMPLATE_FILESREAL_TEMPLATE_DIRexists
write_text	read_textr   r   r   r   r   r   r   r   )r	   tmpl_dirfnamesrcreal_workspace_original_dispatchmods          r   dispatch_modr4   A   s
     t<7"))$)F )#k1K?HNN4$N/ ]%'::<))#---*IT[)\]
 "**..)9;PQRN4
'
1C
I"CM%"4J &s   A0D3BDc                       e Zd ZdZdej
                  deddfdZdej
                  deddfdZdej
                  deddfdZ	y)	TestDispatchCreateTaskDocsu1   dispatch._create_task_docs() E2E 통합 테스트r4   r	   r
   Nc                    d}|j                  |d      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d	      d
z   d|iz  }t        t        j                  |            dx}}t        |t              }	|	s!t        j                  d      dz   dt        j                         v st        j
                  t              rt        j                  t              nddt        j                         v st        j
                  |      rt        j                  |      nddt        j                         v st        j
                  t              rt        j                  t              ndt        j                  |	      dz  }
t        t        j                  |
            d}	|dz  dz  dz  |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}}	|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}}	d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}}	 y)u#  level=3(critical)에서 tasks/{task_id}/ 디렉토리와 3문서 파일이 생성된다.

        _create_task_docs(task_id, level=3) 호출 후
        memory/plans/tasks/{task_id}/ 경로에 plan.md, context-notes.md,
        checklist.md 세 파일이 모두 존재해야 한다.
        	task-9001   levelN)is not)z%(py0)s is not %(py3)sresultpy0py3u>   _create_task_docs가 None을 반환했다 (Path 반환 기대)
>assert %(py5)spy5u(   반환값이 Path 타입이어야 한다z7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancer   )r?   py1py2py4r    plansr$   u(   디렉토리가 생성되지 않았다: C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}expected_dirr?   rE   rF   u4   디렉토리가 파일이 아닌 폴더여야 한다zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.is_dir
}()
}plan.mdcontext-notes.mdchecklist.mdu*   3문서 파일이 생성되지 않았다: fpath)_create_task_docs
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationrC   r   r+   is_dir)selfr4   r	   task_idr=   @py_assert2@py_assert1@py_format4@py_format6@py_assert3@py_format5rI   r/   rO   s                 r   5test_critical_level_creates_directory_and_three_fileszPTestDispatchCreateTaskDocs.test_critical_level_creates_directory_and_three_filesd   s    //q/A!cvT!cccvTccccccvcccvcccTccc#ccccccc&$'S'SS)SSSSSSSzSSSzSSSSSS&SSS&SSSSSS$SSS$SSS'SSSSSS(*W4w>H""_"$_$__(PQ]P^&_______|___|___"___$______""\"$\$\\&\\\\\\\|\\\|\\\"\\\$\\\\\\D 	XE 5(E<<W<>W>WW%OPUw#WWWWWWW5WWW5WWW<WWW>WWWWWW	Xr   c           	      
   d}|j                  |d       |dz  dz  dz  |z  }d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}}|j                  d      }
|
j                  }d} ||      }|st        j                  | d      dz   dt	        j
                         v st        j                  |
      rt        j                  |
      ndt        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}}|
j                  dd      }|
d| j                         }t        j                  |      }dD ]  }||v }|st        j                   d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  |      rt        j                  |      nddz  }t        j                  | d| d      dz   d|iz  }	t        t        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  }t        j                  | d"| d#|d          d$z   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  }t        j                  | d)      d$z   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  }t        j                  | d+      d$z   d%|iz  }t        t        j                  |            dx}}% y),u   생성된 3문서 각각의 YAML frontmatter에 필수 필드 4개가 존재한다.

        task_id, type, scope, status 필드가 있어야 하며,
        {task_id} / {date} 플레이스홀더가 실제 값으로 치환되어야 한다.
        z	task-9002r9   r:   r    rG   r$   rK   u   파일이 없다: rH   rO   rJ   Nr%   r&   z---u   : YAML frontmatter(---) 없음zN
>assert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}content)r?   rE   rF   py6)r\   typescopestatusin)z%(py0)s in %(py2)sfielddata)r?   rE   u   : 필수 YAML 필드 'u   ' 없음z
>assert %(py4)srF   r\   ==)z%(py1)s == %(py3)srD   r@   u$   : task_id 치환 실패 — 기대: u
   , 실제: rA   rB   z	{task_id})not in)z%(py1)s not in %(py3)su(   : {task_id} 플레이스홀더 미치환z{date}u%   : {date} 플레이스홀더 미치환)rP   r+   rQ   rW   rS   rT   rU   rV   rX   rY   r-   
startswithindexstripyaml	safe_loadrR   )r[   r4   r	   r\   rI   r/   rO   r^   ra   rb   re   @py_assert5@py_format7end_idx	yaml_textrm   rl   @py_format3@py_assert0r]   r_   r`   s                         r   )test_yaml_frontmatter_has_required_fieldszDTestDispatchCreateTaskDocs.test_yaml_frontmatter_has_required_fields{   s    &&wa&8(*W4w>HD 	^E 5(E<<?<>?>??%7w#???????5???5???<???>??????oowo7G%%VeV%e,V,VV7U.VVVVVVV7VVV7VVV%VVVeVVV,VVVVVVmmE1-G'*002I>>),D? V}UUUuUUUUUUuUUUuUUUUUUUUUUUUU/EeWH&UUUUUUUV 	? ?g-  ?g  I #  v   '.  I '.    '=gYjQUV_Q`Pab     c;g-ccc;gccc;ccccccgcccgcccc%8b/ccccccc]87*]]]87]]]8]]]]]]7]]]7]]]]ug5\,]]]]]]]]%	^r   c                    d}dddd}|j                  dd      }g |j                  dt        dt        d	t        ffd
}t        |d|       	 |dk\  r|j                  ||       t        |d       t              }d}||k(  }	|	st        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  }
t        j                  d      dz   d|
iz  }t        t        j                  |            dx}x}	}|dz  dz  dz  |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}x}}y# t        |d       w xY w)u  dispatch 내부 로직에서 level=2(normal)일 때는 _create_task_docs가 호출되지 않는다.

        dispatch()는 내부 레벨 정수가 3 이상일 때만 _create_task_docs를 호출한다.
        level<3 조건을 재현하여 호출 횟수가 0임을 검증한다.
        z	task-9003   r9      )normalcriticalsecurityr   tidlvr
   c                 <    j                  | |f        | |      S )N)append)r   r   calledoriginal_fns     r   _tracking_fnzaTestDispatchCreateTaskDocs.test_normal_level_does_not_call_create_task_docs.<locals>._tracking_fn   s     MM3)$sB''r   rP   r   rn   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr   )r?   rD   r@   rf   uF   normal(Lv.2) 레벨에서 _create_task_docs가 호출되면 안 된다z
>assert %(py8)spy8Nr    rG   r$   uE   normal 레벨에서 3문서 디렉토리가 생성되면 안 된다: zG
>assert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}rI   rJ   )r   rP   r   intobjectsetattrr   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r+   )r[   r4   r	   r\   _level_to_int
docs_levelr   r]   rw   @py_assert4rx   @py_format9rI   r^   ra   r`   r   r   s                   @@r   0test_normal_level_does_not_call_create_task_docszKTestDispatchCreateTaskDocs.test_normal_level_does_not_call_create_task_docs   s    #$!C"&&x3
(*"44	(c 	(s 	(v 	( 	1<@	DQ..w
CL"5{C6{iai{aiii{aiiiiiisiiisiiiiii6iii6iii{iiiaiii!iiiiiiii  (*W4w>H&& 	
&( 	
(( 	
( 	
  TT`Sab	
 	
	6	
 	
    	
 	
 		   	
 	
 		 ' 	
 	
 		 ) 	
 	
 	
 	
 	
 	
 L"5{Cs   I0 0I?)
__name__
__module____qualname____doc__types
ModuleTyper   rc   r}   r    r   r   r6   r6   a   sw    ;X!,,X8<X	X.^!,,^8<^	^B!
!,,!
8<!
	!
r   r6   c                   \    e Zd ZdZ ej
                  d      d	d       Zd	dZd	dZd	dZ	y)
TestTeamPromptsThreeDocsSectionu=   team_prompts._build_three_docs_section() E2E 통합 테스트TautouseNc                     t        t        j                  j                  dd            }t	        |      t
        j                  vr)t
        j                  j                  dt	        |             ddlm	} || _
        y)u4   _build_three_docs_section 함수를 임포트한다.r   r   r   )_build_three_docs_sectionN)r   r   r   r   r   r   r   r   r   r   _build)r[   r   r   s      r   _import_build_fnz0TestTeamPromptsThreeDocsSection._import_build_fn   sO     (8:OPQ	y>)HHOOAs9~.B/r   c                    | j                  dd      }d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }t        j                  d      d	z   d
|iz  }t        t        j                  |            dx}}y)u  level='critical'이면 반환 문자열에 '3문서 활용 지침' 텍스트가 포함된다.

        _build_three_docs_section("task-9001", "critical") 호출 결과에
        '3문서 활용 지침' 문자열이 반드시 포함되어야 한다.
        r8   r   u   3문서 활용 지침rj   z%(py1)s in %(py3)sr=   rp   uA   critical 레벨에서 '3문서 활용 지침' 텍스트가 없다rA   rB   N
r   rQ   rR   rV   rS   rT   rU   rW   rX   rY   r[   r=   r|   r]   r_   r`   s         r   4test_critical_level_contains_three_docs_guide_headerzTTestTeamPromptsThreeDocsSection.test_critical_level_contains_three_docs_guide_header   s     [*5& 	
&&0 	
 	
&& 	
 	
 		 ' 	
 	
	6	
 	
  +1 	
 	
 		 +1 	
 	
  P	
 	
 	
 	
 	
r   c                    | j                  dd      }d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }t        j                  d      d	z   d
|iz  }t        t        j                  |            dx}}y)u  level='critical'이면 '보고서 작성 전 3문서 업데이트' 문구가 포함된다.

        _build_three_docs_section("task-9001", "critical") 호출 결과에
        보고서 작성 전 3문서 업데이트를 안내하는 텍스트가 포함되어야 한다.
        r8   r   u)   보고서 작성 전 3문서 업데이트rj   r   r=   rp   uY   critical 레벨에서 '보고서 작성 전 3문서 업데이트' 안내 문구가 없다rA   rB   Nr   r   s         r   1test_critical_level_contains_update_before_reportzQTestTeamPromptsThreeDocsSection.test_critical_level_contains_update_before_report   s     [*5: 	
:fD 	
 	
:f 	
 	
 		 ; 	
 	
	6	
 	
  ?E 	
 	
 		 ?E 	
 	
  h	
 	
 	
 	
 	
r   c                    | j                  dd      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  dt        |             d	z   d
|iz  }t        t        j                  |            dx}}y)u   level='normal'이면 빈 문자열('')을 반환한다.

        normal(Lv.2) 수준 작업에서는 3문서 지침이 불필요하므로
        _build_three_docs_section 이 빈 문자열을 반환해야 한다.
        z	task-9004r    rn   )z%(py0)s == %(py3)sr=   r>   uE   normal 레벨에서 빈 문자열이 반환되어야 한다. 실제: rA   rB   N)r   rQ   rR   rS   rT   rU   rV   rW   reprrX   rY   )r[   r=   r]   r^   r_   r`   s         r   &test_normal_level_returns_empty_stringzFTestTeamPromptsThreeDocsSection.test_normal_level_returns_empty_string   s     [(3 	
v| 	
 	
v 	
 	
	6	
 	
   	
 	
 		  	
 	
 		  	
 	
  TTXY_T`Sab	
 	
 	
 	
 	
r   r
   N)
r   r   r   r   pytestfixturer   r   r   r   r   r   r   r   r      s1    GV^^D!0 "0	
	
	
r   r   z+/home/jay/workspace/teams/dev6/qc/verifiers)verifyr\   ri   c                     d|  d| d|  dS )u,   테스트용 plan.md 내용을 생성한다.---
task_id: zH
type: plan
scope: task
created: 2026-04-16
updated: 2026-04-16
status: u   
---

# 계획서: uR   

## 목표

E2E 통합 테스트 완성

## 범위

3문서 체계 전체 검증
r   )r\   ri   s     r   _make_plan_mdr      s1    9 
 ( y !)	*r   placeholderc                 &    |sdnd}d|  d|  d| dS )u5   테스트용 context-notes.md 내용을 생성한다.u   실제 결정 근거 내용u!   결정 근거: [미입력 내용]r   um   
type: context
scope: task
created: 2026-04-16
updated: 2026-04-16
status: in-progress
---

# 맥락 노트: u   

## 결정 근거


r   )r\   r   bodys      r   _make_context_notes_mdr     s9    0;(AdD9  $9 %&
	r   	completedtotalc                     g }t        |      D ]6  }||k  r|j                  d|dz            |j                  d|dz           8 dj                  |      }d|  d|  d| dS )u]   테스트용 checklist.md 내용을 생성한다. completed/total 비율로 완료율 설정.u   - [x] 항목    u   - [ ] 항목 r   r   uq   
type: checklist
scope: task
created: 2026-04-16
updated: 2026-04-16
status: in-progress
---

# 체크리스트: z

)ranger   join)r\   r   r   linesichecklist_bodys         r   _make_checklist_mdr   "  s    E5\ 2y=LL=Q01LL=Q01	2
 YYu%N9  &Yd
"		r   r   plan_contentcontext_contentchecklist_contentc                     | dz  dz  dz  |z  }|j                  dd       |dz  j                  |d       |d	z  j                  |d       |d
z  j                  |d       |S )uT   tmp workspace에 3문서 파일을 기록하고 디렉토리 경로를 반환한다.r    rG   r$   Tr!   rL   r%   r&   rM   rN   )r(   r,   )r   r\   r   r   r   docs_dirs         r   _write_three_docsr   9  s|     8#g-7'AHNN4$N/	%%lW%E""...Q**+<w*OOr   c                   `    e Zd 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)
TestQcVerifierThreeDocsuY   three_docs_check.verify() E2E 통합 테스트 — PASS / WARN / SKIP / FAIL 시나리오r	   r
   Nc                    d}t        ||t        |d      t        |d      t        |dd      	       t	        |t        |      
      }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d    d|d          dz   d|iz  }t        t        j                  |            dx}x}}y)u[  PASS 시나리오: 3문서 존재 + YAML 유효 + status!=draft + 체크리스트 50%+.

        3문서가 모두 존재하고, YAML frontmatter 필수 필드가 있으며,
        plan.md status가 draft가 아니고, checklist 완료율이 50% 이상이고,
        플레이스홀더가 없으면 결과 status가 'PASS'여야 한다.
        ztask-e2e-passin-progressri   Fr   r9   r   r   r   r   r\   r   r   r   r\   r   ri   PASSrn   z%(py1)s == %(py4)srD   rF   u=   PASS 시나리오에서 상태가 PASS여야 한다. 실제:    
메시지: message
>assert %(py6)srf   Nr   r   r   r   _three_docs_verifyr   rQ   rR   rV   rW   rX   rY   	r[   r	   r\   r=   r|   ra   r]   rb   rx   s	            r   test_pass_scenarioz*TestQcVerifierThreeDocs.test_pass_scenarioL  s     "&w}E27N0AQO	
 $Gs8}Mh 	
6 	
6) 	
 	
6 	
 	
 
	   	
 	
 
	 $* 	
 	
  LFS[L\K] ^ +,.	
 	
 	
 	
 	
 	
r   c                    d}t        ||t        |d      t        |d      t        |dd      	       t	        |t        |      
      }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d    d|d          dz   d|iz  }t        t        j                  |            dx}x}}y)u   WARN 시나리오: plan.md status=draft면 WARN이 반환된다.

        3문서가 모두 존재하더라도 plan.md의 status 필드가 'draft'이면
        결과 status가 'WARN'이어야 한다.
        ztask-e2e-warn-draftdraftr   Fr   r9   r   r   r   r   ri   WARNrn   r   r   u9   plan.md status=draft이면 WARN이어야 한다. 실제: r   r   r   rf   Nr   r   s	            r   test_warn_scenario_draft_statusz7TestQcVerifierThreeDocs.test_warn_scenario_draft_statusb  s     (&ww?27N0AQO	
 $Gs8}Mh 	
6 	
6) 	
 	
6 	
 	
 
	   	
 	
 
	 $* 	
 	
  HxHXGY Z +,.	
 	
 	
 	
 	
 	
r   c                    d}t        ||t        |d      t        |d      t        |dd      	       t	        |t        |      
      }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d    d|d          dz   d|iz  }t        t        j                  |            dx}x}}y)u   WARN 시나리오: 플레이스홀더 미치환 잔존 시 WARN이 반환된다.

        context-notes.md 본문에 '[미입력 내용]' 형태의 플레이스홀더가 남아 있으면
        결과 status가 'WARN'이어야 한다.
        ztask-e2e-warn-phr   r   Tr   r9   r   r   r   r   ri   r   rn   r   r   u<   플레이스홀더 잔존 시 WARN이어야 한다. 실제: r   r   r   rf   Nr   r   s	            r   %test_warn_scenario_placeholder_existsz=TestQcVerifierThreeDocs.test_warn_scenario_placeholder_existsw  s     %&w}E27M0AQO	
 $Gs8}Mh 	
6 	
6) 	
 	
6 	
 	
 
	   	
 	
 
	 $* 	
 	
  K6RZK[J\ ] +,.	
 	
 	
 	
 	
 	
r   c                 x   d}t        |t        |            }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|d    d	|d
          dz   d|iz  }t        t        j                  |            dx}x}}y)u   SKIP 시나리오: 3문서 디렉토리 자체가 없으면 SKIP이 반환된다.

        Lv.2 이하 작업처럼 memory/plans/tasks/{task_id}/ 디렉토리가 없으면
        결과 status가 'SKIP'이어야 한다.
        ztask-e2e-skip-nodirectoryr   ri   SKIPrn   r   r   u6   디렉토리 없을 때 SKIP이어야 한다. 실제: r   r   r   rf   N)r   r   rQ   rR   rV   rW   rX   rY   r   s	            r   test_skip_scenario_no_directoryz7TestQcVerifierThreeDocs.test_skip_scenario_no_directory  s     . $Gs8}Mh 	
6 	
6) 	
 	
6 	
 	
 
	   	
 	
 
	 $* 	
 	
  EVHEUDV W +,.	
 	
 	
 	
 	
 	
r   c                 >   d}|dz  dz  dz  |z  }|j                  dd       |dz  j                  t        |d	      d
       |dz  j                  t        |d      d
       t	        |t        |            }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d    d|d          dz   d|iz  }	t        t        j                  |	            dx}x}}y)u  FAIL 시나리오: 3문서 디렉토리는 있으나 파일 중 하나가 누락되면 FAIL이 반환된다.

        memory/plans/tasks/{task_id}/ 디렉토리는 존재하지만
        checklist.md가 없는 경우 결과 status가 'FAIL'이어야 한다.
        ztask-e2e-fail-missingr    rG   r$   Tr!   rL   r   r   r%   r&   rM   Fr   r   ri   FAILrn   r   r   u0   파일 누락 시 FAIL이어야 한다. 실제: r   r   r   rf   N)r(   r,   r   r   r   r   rQ   rR   rV   rW   rX   rY   )
r[   r	   r\   r   r=   r|   ra   r]   rb   rx   s
             r   test_fail_scenario_missing_filez7TestQcVerifierThreeDocs.test_fail_scenario_missing_file  sA    *h&07:WDtd3 
I	))'-87 	* 	
 
&	&22"7> 	3 	

 $Gs8}Mh 	
6 	
6) 	
 	
6 	
 	
 
	   	
 	
 
	 $* 	
 	
  ?vh?O>P Q +,.	
 	
 	
 	
 	
 	
r   )
r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   I  sd    c
4 
D 
,
 
 
*
d 
t 
*
 
 

 
 
r   r   zDIRECT-WORKFLOW.mdc                   \    e Zd ZdZ ej
                  d      d	d       Zd	dZd	dZd	dZ	y)
 TestDirectWorkflowThreeDocsStepsuV   DIRECT-WORKFLOW.md에 3문서 관련 단계 텍스트가 존재하는지 확인한다.Tr   Nc                    t         j                  } |       }|st        j                  dt                dz   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         j                  d      | _        y)uO   DIRECT-WORKFLOW.md 파일 내용을 읽어 인스턴스 변수에 저장한다.u%   DIRECT-WORKFLOW.md 파일이 없다: rH   DIRECT_WORKFLOW_PATHrJ   Nr%   r&   )r   r+   rQ   rW   rS   rT   rU   rV   rX   rY   r-   _content)r[   r^   ra   rb   s       r   _read_workflow_contentz7TestDirectWorkflowThreeDocsSteps._read_workflow_content  s     $** 	
*, 	
, 	
  44H3IJ	
 	
	6	
 	
  $ 	
 	
 		 $ 	
 	
 		 + 	
 	
 		 - 	
 	
 	
 	
 	
 -666Hr   c                    d}| j                   }||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            d	x}x}}y	)
u  DIRECT-WORKFLOW.md에 Step 1.2 '3문서 확인' 텍스트가 존재한다.

        워크플로우 1.2단계에 '3문서 확인' 지시가 명시되어 있어야
        팀장이 작업 시작 시 3문서를 확인한다는 것을 알 수 있다.
        u   3문서 확인rj   z0%(py1)s in %(py5)s
{%(py5)s = %(py3)s._content
}r[   rD   r@   rB   uC   DIRECT-WORKFLOW.md에 'Step 1.2 3문서 확인' 텍스트가 없다
>assert %(py7)spy7N
r   rQ   rR   rV   rS   rT   rU   rW   rX   rY   r[   r|   r   r]   r`   @py_format8s         r   %test_step_1_2_three_docs_check_existszFTestDirectWorkflowThreeDocsSteps.test_step_1_2_three_docs_check_exists  s       	
4== 	
=0 	
 	
= 	
 	
 		   	
 	
	6	
 	
  $( 	
 	
 		 $( 	
 	
 		 $1 	
 	
  R	
 	
 	
 	
 	
 	
r   c                    d}| j                   }||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            d	x}x}}y	)
u  DIRECT-WORKFLOW.md에 Step 5.2 '3문서 업데이트' 텍스트가 존재한다.

        워크플로우 5.2단계에 '3문서 업데이트' 지시가 명시되어 있어야
        작업 완료 전 3문서를 갱신하는 절차가 강제된다.
        u   3문서 업데이트rj   r   r[   r   uI   DIRECT-WORKFLOW.md에 'Step 5.2 3문서 업데이트' 텍스트가 없다r   r   Nr   r   s         r   &test_step_5_2_three_docs_update_existszGTestDirectWorkflowThreeDocsSteps.test_step_5_2_three_docs_update_exists  s     & 	
 	
%6 	
 	
% 	
 	
 		 & 	
 	
	6	
 	
  *. 	
 	
 		 *. 	
 	
 		 *7 	
 	
  X	
 	
 	
 	
 	
 	
r   c                    d}| j                   }||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            d	x}x}}y	)
u  DIRECT-WORKFLOW.md에 Step 5.3 '3문서 검증 강제' 텍스트가 존재한다.

        워크플로우 5.3단계에 '3문서 검증 강제' 지시가 명시되어 있어야
        .done 생성 전 QC verifier 검증이 강제됨을 명확히 한다.
        u   3문서 검증 강제rj   r   r[   r   uJ   DIRECT-WORKFLOW.md에 'Step 5.3 3문서 검증 강제' 텍스트가 없다r   r   Nr   r   s         r   -test_step_5_3_three_docs_verify_forced_existszNTestDirectWorkflowThreeDocsSteps.test_step_5_3_three_docs_verify_forced_exists  s     ' 	
$-- 	
&-7 	
 	
&- 	
 	
 		 ' 	
 	
	6	
 	
  +/ 	
 	
 		 +/ 	
 	
 		 +8 	
 	
  Y	
 	
 	
 	
 	
 	
r   r   )
r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s3    `V^^D!I "I


r   r   )r   )F)r9   r   )(r   builtinsrS   _pytest.assertion.rewrite	assertionrewriterQ   r   r   r   pathlibr   r   ru   r   r   REAL_WORKSPACEr*   r)   r   r   r   r4   r6   r   r   r   three_docs_checkr   r   r   r   boolr   r   r   r   r   r   r   r   r   r   <module>r     s    	 
     bjjnn%57LMN"Y.<{J D U5E5E 4 54 5E$4$4 5 5>\
 \
H,
 ,
h @ A 93   &C d s $   C .  	
  
 i
 i
` &	14HH '
 '
r   