
    *jX!              	          d Z ddlZddlmc mZ ddlZddl	Z	e	j                  j                  e	j                  j                  e      dddddd      Zej                  j!                  de      Zej                  j%                  e      Zej(                  j+                  e       ej,                  Zej.                  Zej2                  Zg d	Zg d
Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+d Z,d Z-y)u   task-2716 — PR Diff Hygiene Guard 회장 지정 10 테스트 + 모듈 단위.

회귀 고정: PR #156 / PR #161 evidence md 혼입.
fixture 는 실제 PR #161 파일목록(ea2eb02a / 4aa779ec) 기반.
    Nz..scriptsharnessv36zpr_diff_hygiene_guard.pypr_diff_hygiene_guard)dispatch.py1memory/reports/task-2712+2-gemini-fix-evidence.mdscripts/finish-task.sh-scripts/harness/v36/before_exit_guard_hook.sh2scripts/harness/v36/failure_callback_dispatcher.py)r   r	   r
   r   c                     ddg} t        | |       }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   d
|iz  }t        t        j                  |            dx}}|d   }g }||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(   1. clean runtime diff(code만) → PASS.r   zscripts/harness/v36/guard.pyexpected_filesstatus==z%(py1)s == %(py3)sPASSpy1py3
>assert %(py5)spy5Nblockedz%(py1)s == %(py4)sr   py4assert %(py6)spy6classifyr   
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_name_format_assertmsgAssertionError_format_explanation	changedr@py_assert0@py_assert2@py_format4@py_format6@py_assert3@py_format5@py_format7s	            C/home/jay/workspace/tests/harness/test_v36_pr_diff_hygiene_guard.py)test_01_clean_runtime_diff_code_only_passr5   /   s    <=G1AX;!;$!!!;$!!!;!!!!!!$!!!$!!!!!!!!!!Y<2<2<2<2    c                     ddg} ddg}t        | |      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   d
|iz  }t        t        j                  |            dx}}|d   }g }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)uE   2. expected_files 에 명시된 memory/reports/task-2712.md → PASS.scripts/foo.pyzmemory/reports/task-2712.mdr   r   r   r   r   r   r   r   Nr   r   r   r   r   r   
r+   expectedr,   r-   r.   r/   r0   r1   r2   r3   s
             r4   &test_02_declared_report_task_2712_passr;   7   s    !>?G "?@H2AX;!;$!!!;$!!!;!!!!!!$!!!$!!!!!!!!!!Y<2<2<2<2r6   c                     ddg} dg}t        | |      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   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)u9   3. 미선언 memory/reports/...fix-evidence.md → BLOCK.r8   z(memory/reports/task-2712-fix-evidence.mdr   r   r   r   CONTAMr   r   r   Nr   inz%(py1)s in %(py4)sr   r   r   r    r=   r!   r"   r#   r$   r%   r&   r'   r(   r)   r9   s
             r4   (test_03_undeclared_fix_evidence_md_blockrB   @   s    !KLG !H2AX;#;& ###;&###;######&###&####!######5E9E5EEEE5EEE5EEEEEEEEEEr6   c                     ddg} t        | dg      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   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"   4. memory/events/*.json → BLOCK.r8   z!memory/events/task-2712.done.jsonr   r   r   r   r=   r   r   r   Nr   r>   r@   r   r   r   rA   r*   s	            r4   +test_04_undeclared_memory_events_json_blockrD   I   s    !DEG*:);<AX;#;& ###;&###;######&###&####!######.>!I,>.,>>>>.,>>>.>>>,>>>>>>>r6   c                     ddg} t        | dg      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   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!   5. memory/artifacts/** → BLOCK.r8   /memory/artifacts/task-2716-evidence/packet.jsonr   r   r   r   r=   r   r   r   Nr   r>   r@   r   r   r   rA   r*   s	            r4   )test_05_undeclared_memory_artifacts_blockrG   Q       !RSG*:);<AX;#;& ###;&###;######&###&####!######<L)L<LLLL<LLL<LLLLLLLLLLr6   c                     ddg} t        | dg      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   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%   6. *callback-envelope.json → BLOCK.r8   /memory/reports/task-2716-callback-envelope.jsonr   r   r   r   r=   r   r   r   Nr   r>   r@   r   r   r   rA   r*   s	            r4   /test_06_undeclared_callback_envelope_json_blockrK   Y   rH   r6   c                     ddg} t        | dg      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   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)u3   7. *auth*marker*.json (auth-path-marker) → BLOCK.r8   -memory/events/task-2716.auth-path-marker.jsonr   r   r   r   r=   r   r   r   Nr   r>   r@   r   r   r   rA   r*   s	            r4   )test_07_undeclared_auth_marker_json_blockrN   a   s    !PQG*:);<AX;#;& ###;&###;######&###&####!######:Ja	lJ:lJJJJ:lJJJ:JJJlJJJJJJJr6   c                     g d} dg| z   }t        ||      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   d
|iz  }t        t        j                  |            dx}}|d   }g }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)uG   8. allowlist(expected_files)에 포함되면 위 패턴도 예외 PASS.)z!memory/events/task-2716.done.jsonrF   rJ   rM   z(memory/reports/task-2716-fix-evidence.mdr8   r   r   r   r   r   r   r   r   Nr   r   r   r   r   r   )
	artifactsr+   r,   r-   r.   r/   r0   r1   r2   r3   s
             r4   6test_08_allowlisted_artifact_pattern_is_exception_passrQ   i   s    I   9,G1AX;!;$!!!;$!!!;!!!!!!$!!!$!!!!!!!!!!Y<2<2<2<2r6   c                  d   t         } t        t        |       }|d   }|t        k(  }|st	        j
                  d|fd|t        f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              nddz  }t	        j                  |      dz   d|iz  }t        t	        j                  |            d	x}}|d
   }dg}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }t	        j                  |      dz   d|iz  }t        t	        j                  |            d	x}x}}t         D ]  }	|d
   }|	|v}
|
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	)uI   9. PR #161 ea2eb02a(4 code + evidence md) → BLOCK (evidence md 지목).r   r   r   r   r=   r   r   r   Nr   r   r   r   z
>assert %(py6)sr   )not in)z%(py0)s not in %(py3)scode)py0r   assert %(py5)s)PR161_CLEAN_CODE_ONLYr    PR161_CONTAMINATEDr=   r!   r"   r#   r$   r%   r&   r'   r(   r)   )r:   r,   r-   r.   r/   r0   r1   r2   r3   rT   @py_assert1s              r4   4test_09_pr161_contaminated_fixture_block_evidence_mdrZ   y   sI   $H#H=AX;#;& ###;&###;######&###&####!######Y<SOPS<PPSSS<PSSS<SSSPSSSRSSSSSSSS% (Y<'t<''''t<''''''t'''t'''<'''''''(r6   c                     t        t        t              } | d   }|t        k(  }|st        j                  d|fd|t        f      t        j
                  |      dt        j                         v st        j                  t              rt        j
                  t              nddz  }t        j                  |       dz   d|iz  }t        t        j                  |            d	x}}| d
   }g }||k(  }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)u5   10. PR #161 4aa779ec 결과 diff(code-only) → PASS.r   r   r   r   r   r   r   r   Nr   r   r   r   r   )r    rW   r   r!   r"   r#   r$   r%   r&   r'   r(   r)   )r,   r-   r.   r/   r0   r1   r2   r3   s           r4   ,test_10_pr161_cleanup_code_only_fixture_passr\      s    &7LMAX;!;$!!!;$!!!;!!!!!!$!!!$!!!!!!!!!!Y<2<2<2<2r6   c                  ~   t        t        t              } | d   D ]  }g }| d   }||v }|}|r
| d   |   }|}|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  }|j                  |       |r+d
dt        j                        iz  }	|j                  |	       t        j                  |d      i z  }
dd|
iz  }t        t        j                  |            dx}x}x}x}}" y)uB   차단된 모든 파일은 reasons 에 사유가 있어야 한다.r   r   reasonsr>   )z%(py2)s in %(py5)spath)py2r   z%(py7)spy7z%(py10)spy10r   zassert %(py13)spy13N)r    rX   rW   r!   r"   r$   r%   r&   r#   append_format_boolopr(   r)   )r,   r_   rY   @py_assert4r1   r-   @py_assert9r0   @py_format8@py_format11@py_format12@py_format14s               r4   %test_reasons_present_for_each_blockedrl      s    #4IJA) ;:q|:t|#:)T(::(::::t|::::::t:::t:::|:::::::(::::::::::::::;r6   c                     dg} t        | dg      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      d	z   d
|iz  }t        t        j                  |            dx}}y)u>   expected_files glob 선언으로 artifact 디렉터리 통과.rF   z&memory/artifacts/task-2716-evidence/**r   r   r   r   r   r   r   r   Nr   )r+   r,   r-   r.   r/   r0   s         r4   test_allowlist_glob_declarationrn      s    @AG*R)STAX;!;$!!!;$!!!;!!!!!!$!!!$!!!!!!!!!!r6   c                     t        dgd      } | d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |       d	z   d
|iz  }t        t        j                  |            dx}}y)uK   allowlist 미제공 시 artifact 는 차단(하드코딩된 통과 없음).memory/events/x.jsonNr   r   r   r   r=   r   r   r   rA   )r,   r-   r.   r/   r0   s        r4   :test_no_hardcoded_allowlist_empty_expected_blocks_artifactrq      sz    ()$?AX;#;& ###;&###;######&###&####!######r6   c                     t         j                  t        t              } | 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}}| d	   }|t        k(  }|st	        j
                  d
|fd|t        f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              nddz  }dd|iz  }t        t	        j                  |            dx}}y)u>   detect_contamination 은 read-only(detection_only=True) alias.detection_onlyT)is)z%(py1)s is %(py4)sr   r   r   Nr   r   r   r=   r   rV   r   )guarddetect_contaminationrX   rW   r!   r"   r#   r(   r)   r=   r$   r%   r&   )r,   r-   r1   r.   r2   r3   r/   r0   s           r4   &test_detection_only_is_read_only_aliasrw      s    ""#57LMA&$&$&&&&$&&&&&&$&&&&&&&X; ;&    ;&   ;      &   &       r6   c                     d} t         j                  |       }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)uL   task md expected_files 블록 파싱(하드코딩 금지 — 동적 수집).u   ## 9. Affected Files

  expected_files:
    - scripts/harness/v36/pr_diff_hygiene_guard.py
    - tests/harness/test_v36_pr_diff_hygiene_guard.py

## 다음 섹션
z,scripts/harness/v36/pr_diff_hygiene_guard.pyr>   )z%(py1)s in %(py3)sgotr   rV   r   Nz/tests/harness/test_v36_pr_diff_hygiene_guard.py)
ru   extract_expected_filesr!   r"   r#   r$   r%   r&   r(   r)   )mdry   r-   r.   r/   r0   s         r4   .test_extract_expected_files_from_task_md_blockr|      s    	  
&
&r
*C9@9S@@@@9S@@@9@@@@@@S@@@S@@@@@@@<C<CCCC<CCC<CCCCCCCCCCCCCCCCr6   c                     dg} t        | g       }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |      dz   d	|iz  }t        t        j                  |            d
x}}|d   }g }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d
x}x}}y
)uU   ★ .github/workflows/** 는 본 가드가 절대 차단하지 않는다(범위 외).z.github/workflows/ci.ymlr   r   r   r   r   r   r   r   Nr   r   r   r   r   r   r*   s	            r4   /test_github_workflows_never_treated_as_artifactr~      s    )*G,AX;!;$!!!;$!!!;!!!!!!$!!!$!!!!!!!!!!Y<2<2<2<2r6   c                 r   ddl }ddl}|j                  |j                  t        ddddg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  }t        j                  |j                        dz   d|iz  }t        t        j                  |            dx}x}}|j                  |j                  t        dddg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  }t        j                  |	j                        dz   d|iz  }t        t        j                  |            dx}x}}|j                  |j                  t        ddddg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  }t        j                  |
j                        dz   d|iz  }t        t        j                  |            dx}x}}y)z.CLI: PASS=0, CONTAMINATED=1, detection-only=0.r   Nz	--changedrp   z
--expectedzscripts/a.pyT)capture_outputtext   r   )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sp)rU   r`   r   z
>assert %(py7)sra   z--detection-onlyp2p3)
subprocesssysrun
executable_MODULE_PATH
returncoder!   r"   r$   r%   r&   r#   r'   stderrr(   r)   )tmp_pathr   r   r   rY   rf   r1   r0   rh   r   r   s              r4   test_cli_exit_codesr      s    			,lN	L$ 	 	A
 <<&1&<1&&&<1&&&&&&1&&&1&&&<&&&1&&&ahh&&&&&&& 
		,.@	B$ 
 
B
 ==(A(=A(((=A((((((2(((2(((=(((A(((ryy((((((( 
		nlN	D$ 
 
B
 ==(A(=A(((=A((((((2(((2(((=(((A(((ryy(((((((r6   ).__doc__builtinsr$   _pytest.assertion.rewrite	assertionrewriter!   importlib.util	importlibosr_   joindirname__file__r   utilspec_from_file_location_specmodule_from_specru   loaderexec_moduler   PR_DIFF_CONTAMINATEDr=   classify_pr_diffr    rX   rW   r5   r;   rB   rD   rG   rK   rN   rQ   rZ   r\   rl   rn   rq   rw   r|   r~   r    r6   r4   <module>r      s  
    	ww||GGOOH	 	../FU''.    zz		#	#!!
  F?MMK (;"$!D)r6   