
    >jVr                    p   d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
mZ ddlmZmZ  ee      j!                         j"                  d   Z ee      e	j(                  vr"e	j(                  j+                  d ee             ddlmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" dZ#ddd	ed
d	 	 	 	 	 	 	 d/dZ$d0dZ%d0dZ&d0dZ'd0dZ(d0dZ)d0dZ*d0dZ+d0dZ,d0dZ-d0dZ.d0dZ/d0dZ0d0dZ1d0dZ2d0dZ3d0dZ4d0dZ5d0dZ6d0dZ7d0d Z8d0d!Z9d0d"Z:d0d#Z;d0d$Z<d0d%Z=d0d&Z>d0d'Z?d0d(Z@d0d)ZAd0d*ZBd0d+ZCd0d,ZDd- ZEd. ZFy)1u  anu_v2.tests.test_auto_gemini_triage_2538 — 9 회귀 (회장 §명시 1:1 박제).

회귀 케이스 (회장 §명시):
  1. false_positive dismiss              — 회귀 fixture 매칭 시 dismiss
  2. style_only dismiss                  — 코드 동작 무관 style 권고 dismiss
  3. minor_fix_in_scope auto_apply       — expected_files 내부 minor fix 자동 적용
  4. scope_expansion escalate            — expected_files 밖 수정 요구 → Critical
  5. Security-High in scope              — Security 권고는 minor 무관 적용 (단 scope 내부)
  6. Security-High out of scope          — escalate
  7. interface contract                  — applied/dismissed/escalated 3 키 제공
  8. token raw 0                         — finding 처리 후 raw 토큰 노출 0
  9. chat=6937032012 격리                 — 다른 chat record 노출 0

본 회귀는 anu_v2/* 모듈만 import 한다 (one-way isolation).
    )annotationsN)Path)AnyMapping   )ACTION_AUTO_APPLY_MINOR_FIXACTION_DISMISS_FALSE_POSITIVEACTION_DISMISS_STYLE_ONLYACTION_ESCALATE_SCOPE_EXPANSIONACTIONSCRITICAL_GEMINI_SCOPE_EXPANSIONDEFAULT_CHAT_IDTOKEN_KEY_HINTSAutoGeminiTriageFalsePositiveFixtureTriageResult_redact_tokens)anu_v2/auto_gemini_triage.pyz,anu_v2/tests/test_auto_gemini_triage_2538.py z	task-2538)audit_callsfix_applierfixtureschat_idtask_idc                6      g   fd}t        |||||      S )Nc                :    j                  t        |              y Nappenddictrecr   s    @/home/jay/workspace/anu_v2/tests/test_auto_gemini_triage_2538.pyaudit_writerz"_make_triage.<locals>.audit_writer>       49%    )r$   r   false_positive_fixturesr   r   )r   )r   r   r   r   r   r$   s   `     r#   _make_triager(   3   s3     & ! ( r&   c                 @   g } t        dd      f}t        | |      }dddddd	d
}|j                  |t              \  }}|t        k(  }|st        j                  d|fd|t        f      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dz  }dd|iz  }t        t        j                  |            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}}
y )Nzunused-importzvendored stubrule_idreason)r   r   Lowstyler   zF401 unused importzmodule-level import not usedr+   severitycategorypathtitlebody==z%(py0)s == %(py2)sactionr	   py0py2assert %(py4)spy4r+   z%(py1)s == %(py4)spy1r=   assert %(py6)spy6fixture_reasonr   r(   classify_evidenceEXPECTED_FILES_DEFAULTr	   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)auditr   triagefindingr8   details@py_assert1@py_format3@py_format5@py_assert0@py_assert3@py_assert2@py_format7s                r#   )test_1_false_positive_dismiss_via_fixturerZ   K   sk   %'E__MH eh?F #.%.G ..w8NOOFG22222622222226222622222222222222222290000000000000000000#$77$7777$777$7777777777r&   c                 .   t        ddd      f} t        |       }ddd}ddd}|j                  |t              \  }}|j                  |t              \  }}|t        k(  }|st        j                  d	|fd
|t        f      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dz  }dd|iz  }	t        t        j                  |	            d }|t        k7  }|st        j                  d|fd|t        f      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dz  }dd|iz  }	t        t        j                  |	            d }y )Nzredundant-castzint\(int_value\)zPython 3 idiomr+   	signaturer,   r   zint(int_value) is redundant)r+   r4   zdifferent body contentr5   r7   a1r	   r9   r<   r=   )!=)z%(py0)s != %(py2)sa2rD   )
r   rP   matchingnon_matchingr_   _ra   rS   rT   rU   s
             r#   +test_1_false_positive_signature_regex_matchre   `   sB   $)#	
H 8,F+5RSH/9QRL$$X/EFEB$$\3IJEB.....2.......2...2.......................2.......2...2..................r&   c                    t               } ddddddd}| j                  |t              \  }}|t        k(  }|st	        j
                  d|fd	|t        f      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dz  }dd|iz  }t        t	        j                  |            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 )Nzindent-not-multiple-of-fourr-   r.   r   indentationzuse 4-space indentr/   r5   r7   r8   r
   r9   r<   r=   r1   r>   r?   rA   rB   r(   rE   rF   r
   rG   rH   rI   rJ   rK   rL   rM   rN   rP   rQ   r8   rR   rS   rT   rU   rV   rW   rX   rY   s              r#   test_2_style_only_dismissrj   u   s    ^F0.$G ..w8NOOFG.....6.......6...6..................:)')'))))'))))))')))))))r&   c                    t               } dddddd}| j                  |t              \  }}|t        k(  }|st	        j
                  d|fd|t        f      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
dz  }dd|iz  }t        t	        j                  |            d}y)uK   style 권고는 path 가 scope 밖이어도 dismiss (코드 동작 무관).ztrailing-whitespacer-   r.   zutils/some_other.pyztrailing whitespacer+   r0   r1   r2   r3   r5   r7   r8   r
   r9   r<   r=   Nrh   )rP   rQ   r8   rd   rS   rT   rU   s          r#   0test_2_style_only_dismiss_even_when_out_of_scoperm      s    ^F(%&G ((2HIIFA.....6.......6...6..................r&   c                 f   g } t        |       }dddddd}|j                  |t              \  }}|t        k(  }|st	        j
                  d|fd	|t        f      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dz  }dd|iz  }t        t	        j                  |            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}
}	|j                  |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}
}	|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}
}	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 )$Nr   zmissing-type-annotationMediumbugr   zadd type hintrl   r5   r7   r8   r   r9   r<   r=   r2   r>   r?   rA   rB   appliedTisz%(py1)s is %(py4)s	escalatedF   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenrO   r:   r@   py3rB   assert %(py8)spy8r   kindauto_apply_minor_fix)r(   rE   rF   r   rG   rH   rI   rJ   rK   rL   rM   rN   apply_minor_fixry   )rO   rP   rQ   r8   rR   rS   rT   rU   rV   rW   rX   rY   r"   @py_assert5@py_assert4@py_format9s                   r#   $test_3_minor_fix_in_scope_auto_applyr      s   %'Ee,F,. G ..w8NOOFG0000060000000600060000000000000000006?<<<?<<<<<?<<<<?<<<<<<<<<<<

 
 *H
ICy>!T!>T!!!!>T!!!>!!!T!!!!!!!{$u$u$$$$u$$$$$$u$$$$$$$u::?:33uu:8F55555555555555555555555r&   c                 ^   g } dd}t        | |      }ddddd}|j                  |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}}|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   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)uP   fix_applier 가 False 반환 시 record 가 escalate 로 전환되어야 한다.c                    | |f}y)NFr   )rQ   target_filerd   s      r#   failing_applierzAtest_3_minor_fix_apply_failure_escalates.<locals>.failing_applier   s    k"r&   )r   r   xrp   rq   r   r+   r0   r1   r2   rr   Frs   ru   r?   rA   rB   Nrv   Tr   r~   auto_apply_failed_escalatedr5   r>   )rQ   zMapping[str, Any]r   strreturnbool)r(   r   rG   rH   rL   rM   rN   )
rO   r   rP   rQ   r"   rV   rW   rX   rU   rY   s
             r#   (test_3_minor_fix_apply_failure_escalatesr      s<   %'E eIF.	G 
 
 *H
ICy>"U">U"""">U""">"""U"""""""{#t#t####t######t#######8F<<<<<<<<<<<<<<<<<<<<<<<r&   c                 ,   g } t        |       }dddddd}|j                  |t              \  }}|t        k(  }|st	        j
                  d|fd	|t        f      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dz  }dd|iz  }t        t	        j                  |            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}
}	|j                  |      }|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}}
|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   }|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 )Nro   zmissing-validationrp   rq   zutils/external_module.pyzadd input validationrl   r5   r7   r8   r   r9   r<   r=   r,   scope_expansion_requiredr>   r?   rA   rB   critical_codez%(py1)s == %(py3)sr   r@   r{   assert %(py5)spy5r~   scope_expansion_criticalr   r(   rE   rF   r   rG   rH   rI   rJ   rK   rL   rM   rN   escalate_scope_expansionr   rO   rP   rQ   r8   rR   rS   rT   rU   rV   rW   rX   rY   r"   @py_format4@py_format6s                  r#   (test_4_scope_expansion_escalate_criticalr      s2   %'Ee,F'*'G ..w8NOOFG4444464444444644464444444444444444448: :: ::::: ::::::: ::::::::

)
)'
2CB#BBBBB#BBBBBBBBBB#BBBB#BBBBBBBBv;444;44444;4444;444444444448O$G$(GGGGG$(GGGG$GGGGGG(GGGG(GGGGGGGGr&   c                    t               } dddddd}| j                  |t              \  }}|t        k(  }|st	        j
                  d|fd|t        f      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
dz  }dd|iz  }t        t	        j                  |            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)uX   Security-High 권고는 style/minor 분류와 무관하게 우선 적용 (scope 내부).zowasp-a02-injectionHighsecurityr   zSQL-like string concatenationrl   r5   r7   r8   r   r9   r<   r=   Nr,   security_high_in_scoper>   r?   rA   rB   )r(   rE   rF   r   rG   rH   rI   rJ   rK   rL   rM   rN   ri   s              r#   *test_5_security_high_in_scope_auto_appliesr      s    ^F(.0G ..w8NOOFG00000600000006000600000000000000000088 88 88888 8888888 88888888r&   c                    g } t        |       }dddddd}|j                  |t              \  }}|t        k(  }|st	        j
                  d|fd	|t        f      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dz  }dd|iz  }t        t	        j                  |            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}
}	|j                  |      }|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)uN   Security-High 라도 scope 밖이면 절대 자동 적용 X — 회장 보고.ro   zowasp-a01-broken-accessr   r   zutils/auth.pyzauth bypassrl   r5   r7   r8   r   r9   r<   r=   Nr,   security_high_out_of_scoper>   r?   rA   rB   r   r   r   r   r   r   r   r   s                  r#   +test_6_security_high_out_of_scope_escalatesr      sw   %'Ee,F,G ..w8NOOFG4444464444444644464444444444444444448< << <<<<< <<<<<<< <<<<<<<<

)
)'
2CB#BBBBB#BBBBBBBBBB#BBBB#BBBBBBBBr&   c            	     4
   t        t        dd      f      } dddddd	d
ddddddddddddddg}| j                  |t              }|j                  } |       }t        |      }h 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                  |      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}x}x}}|d   }
t        |
      }d}||k(  }|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!   }
t        |
      }d"}||k(  }|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#   }
t        |
      }d"}||k(  }|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        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 )+Nzknown-fpfixturer*   r^   r-   r.   r   r   r+   r0   r1   r2   r4   indentr   z	type-hintrp   rq   zperf-xperformancezutils/perf.py>   rr   	dismissedrv   r5   )zb%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.keys
}()
})
} == %(py10)ssetout)r:   r@   r{   r   py7py10assert %(py12)spy12r   r   z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sry   r:   r;   r=   r   assert %(py9)spy9rr   rw   rv   r   r   r   r   r   r   r   )r(   r   triage_batchrF   keysr   rG   rH   rI   rJ   rK   rL   rM   rN   ry   r   )rP   findingsr   rX   r   @py_assert6@py_assert9@py_assert8@py_format11@py_format13rS   rW   r   @py_format8@py_format10rV   r   r   s                     r#   +test_7_triage_batch_interface_contract_keysr      s7   &z)LNF
 Ew/	> %W/	1  X5/	1 ( 	"H 

h(>
?C xxCxzC3z?CCC?CCCCC?CCCCCCC3CCC3CCCCCCsCCCsCCCxCCCzCCC?CCCCCCCCCCC;%3 %A% A%%%% A%%%%%%3%%%3%%%%%% %%%A%%%%%%%9~#3~#!#!####!######3###3###~######!#######;%3 %A% A%%%% A%%%%%%3%%%3%%%%%% %%%A%%%%%%%{A/R/3RRRRR/3RRRR/RRRRRR3RRRR3RRRRRRRRr&   c                    t               } | j                  g t              }g g 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}}y )N)rr   r   rv   r5   %(py0)s == %(py3)sr   r:   r{   r   r   )r(   r   rF   rG   rH   rI   rJ   rK   rL   rM   rN   )rP   r   rX   rS   r   r   s         r#   6test_7_triage_batch_empty_findings_returns_empty_listsr     s    ^F


b"8
9C rCC3CCCCC3CCCCCCC3CCC3CCCCCCCCCCCr&   c                 v   t               } | j                  }d}||u }|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                  d	t        i       | j                  }d
}||u }|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}}y)uI   has_escalation 은 Critical 보고 대상 존재 여부를 즉시 반환.Frs   )z6%(py2)s
{%(py2)s = %(py0)s.has_escalation
} is %(py5)sr)r:   r;   r   zassert %(py7)sr   Nr   T)r   has_escalationrG   rH   rI   rJ   rK   rL   rM   rN   rv   r   r   )r   rS   r   rW   r   r   s         r#   (test_7_triage_result_has_escalation_flagr     s   A$u$u$$$$u$$$$$$1$$$1$$$$$$u$$$$$$$KK)HIJ#t#t####t######1###1######t#######r&   c            	        g } t        |       }dddddddd	d
id}|j                  |gt              }t        |      t        |       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}}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}}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)uc   finding 안에 BOT_GITHUB_TOKEN raw 가 박혀 들어와도 audit/결과에 노출되지 않는다.ro   zleak-xrp   rq   r   zToken leak in logz#found GH_TOKEN=ghs_LEAKED1234567890ghs_should_be_redacted_xxxxxgithub_token ghp_owner_pat_should_be_redacted)r+   r0   r1   r2   r3   r4   BOT_GITHUB_TOKENevidenceghs_should_be_redactednot inz%(py1)s not in %(py3)sblobr   r   r   Nghp_owner_patghs_LEAKED1234567890***REDACTED***inz%(py1)s in %(py3)s)r(   r   rF   reprrG   rH   rL   rI   rJ   rK   rM   rN   )	rO   rP   leaked_findingr   r   rV   rX   r   r   s	            r#   )test_8_token_raw_zero_in_audit_and_resultr   #  s   %'Ee,F.$5:#%GH	N 

~.0F
GC 9tE{"D#/#4////#4///#//////4///4///////&?$&&&&?$&&&?&&&&&&$&&&$&&&&&&&!-!----!---!----------------#t####t#########t###t#######r&   c                 $   ddddiddgd} t        |       }t        |      }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}}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   }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 )NTghs_RAW_TOKEN_xxxxz	x-api-keyghp_xxxxxxxxxxxxxxxxxxxxfineghs_inside_string_value)okGITHUB_TOKENnested
list_fieldghs_RAW_TOKENr   r   sr   r   r   r   r   r5   r>   r?   rA   rB   )
r   r   rG   rH   rL   rI   rJ   rK   rM   rN   )
rawredactedr   rV   rX   r   r   rW   rU   rY   s
             r#   5test_8_redact_tokens_helper_handles_nested_structuresr   <  s   , :;89	C c"HXA#?!####?!###?######!###!#######%.%Q....%Q...%......Q...Q.......$-$A----$A---$------A---A-------N#7'77#'77777#'7777#777'77777777r&   c                 Z   t        d      } ddddddddddd	ddd
dg}| 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 ch c]  }|d   	 }	}dd	h}
|	|
k(  }|slt        j                  d|fd|	|
f      t        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}	x}}
t        |      }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c c}w )"uH   list_chat_audit 가 본 인스턴스 chat_id 외 record 를 0건 노출.
6937032012)r   r   a)r   r~   r+   
9999999999br   cd)r~   r+   r   r5   rx   ry   visiblerz   r|   r}   Nr+   r>   r?   rA   rB   z"b"r   r   r   r   r   r   z'b')r(   list_chat_auditry   rG   rH   rI   rJ   rK   rL   rM   rN   r   )rP   mixed_recordsr   rX   r   r   rY   r   r   rV   rW   rU   r   r   r   s                  r#   0test_9_chat_isolation_filters_other_chat_recordsr   L  s   ,/F *@SQ *@SQ *DQTU'C8M $$]3Gw<1<1<133ww<1")*QAiL*8*sCj8*j8888*j888*888j8888888=D555555	 +s   L(c                    g } t        | d      }ddddd}|j                  |gt               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]   audit_writer 호출 시점에 chat_id 가 박혀 있어야 list_chat_audit 가 격리 가능.r   )r   r   zrp   rq   r   r   c              3  D   K   | ]  }|j                  d       dk(    yw)r   r   N)get).0r   s     r#   	<genexpr>zItest_9_audit_records_tagged_with_chat_id_at_write_time.<locals>.<genexpr>i  s     ?AquuY</?s    z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}all)r:   r;   r=   N)r(   r   rF   r   rI   rJ   rG   rK   rL   rM   rN   )rO   rP   rQ   rS   rW   rU   s         r#   6test_9_audit_records_tagged_with_chat_id_at_write_timer   _  s    %'Ee\BFH%.G 	#9:???3?????????3???3??????????????r&   c                 p   d} t         | k(  }|st        j                  d|fdt         | f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |       dz  }dd|iz  }t        t        j                  |            dx}} y)	u)   회장 §명시: default chat=6937032012.r   r5   r   r   r   r   r   N)	r   rG   rH   rI   rJ   rK   rL   rM   rN   )rX   rS   r   r   s       r#   'test_9_default_chat_id_is_chairman_chatr   l  s[    **?l****?l******?***?***l*******r&   c                 b   t        t        t        t        t        h      } | j
                  } |t              }|sddt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            dx}}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                  t              rt        j                  t              ndt        j                  |      t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}}y)u  회장 §명시 v0 4 분류는 보존 (제거/이름 변경 금지).

    task-2558 §명시 (2026-05-12) 가 ACTIONS 를 5번째 분류 (minor_in_expected_files) +
    cascade reply+resolve 용으로 확장. v0 doctrine 4 action 자체는 변형 0 이어야 함.
    zJassert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.issubset
}(%(py3)s)
}
v0_actionsr   )r:   r;   r{   r   N   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sry   rz   r|   r}   )	frozensetr	   r
   r   r   issubsetr   rI   rJ   rG   rK   rL   rM   rN   ry   rH   )r  rS   r   r   rX   r   rY   r   s           r#    test_actions_set_is_exactly_fourr  r  s,    %!#'	 J 'w'''''''':''':'''''''''w'''w''''''''''w<1<1<133ww<1r&   c            	        t               } ddh}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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}}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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}}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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}}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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}}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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)uH   expected_files 가 glob 패턴인 경우도 매칭 정확 (`anu_v2/**`).z	anu_v2/**ztests/**/*.pyr   Trs   z[%(py7)s
{%(py7)s = %(py2)s
{%(py2)s = %(py0)s.is_in_scope
}(%(py4)s, %(py5)s)
} is %(py10)srP   expectedr:   r;   r=   r   r   r   r   r   Nzanu_v2/sub/x.pyztests/regression/test_x.pyzutils/forbidden.pyF 
r(   is_in_scoperG   rH   rI   rJ   rK   rL   rM   rN   )	rP   r
  rS   rW   r   r   r   r   r   s	            r#   &test_is_in_scope_handles_glob_patternsr    s   ^F_-HO<O<hGO4OG4OOOOG4OOOOOO6OOO6OOOOOO<OOOOOOhOOOhOOOGOOO4OOOOOOOB/B/:BdB:dBBBB:dBBBBBB6BBB6BBBBBB/BBBBBBBBBBBB:BBBdBBBBBBBM:M:HEMMEMMMMEMMMMMM6MMM6MMMMMM:MMMMMMHMMMHMMMEMMMMMMMMMMF2F2H=FF=FFFF=FFFFFF6FFF6FFFFFF2FFFFFFHFFFHFFF=FFFFFFFFFF4b4b(+4u4+u4444+u44444464446444444b444444(444(444+444u44444444r&   c                 H   t               } ddddddddd	dd
ddd	ddddddg}|D ]  }| j                  |t              \  }}|t        v }|st	        j
                  d|fd|t        f      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dz  }dd|iz  }t        t	        j                  |            d} y)uJ   모든 분류 결과가 ACTIONS 집합 내부 값만 반환 (typo 방지).r   r-   r.   za/b.pyr   yrp   rq   r   r   r   r   wr   zexternal/x.pyr   )z%(py0)s in %(py2)sr8   r   r9   r<   r=   N)r(   rE   rF   r   rG   rH   rI   rJ   rK   rL   rM   rN   )rP   r   fr8   rd   rS   rT   rU   s           r#   1test_classify_evidence_returns_only_known_actionsr    s    ^FURX5/	1V/	1X= 	"H  !,,Q0FG	    v      v   v                !r&   c                    t               } | j                  g t              }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}}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}}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}}|j                         D ]#  }
t        |
t              }|sd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}& y)uC   task-2531 executor 가 기대하는 dict 형식 (3 키) 1:1 박제.rr   r   r   r   r   r   r   Nr   rv      r5   rx   ry   rz   r|   r}   5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancevlistr:   r@   r;   r=   )r(   r   rF   rG   rH   rL   rI   rJ   rK   rM   rN   ry   valuesr  r  )rP   r   rV   rX   r   r   r   r   rY   r   r  rW   rU   s                r#   7test_executor_contract_dict_signature_matches_task_2531r    sO   ^F


b"8
9C999;#;#;##;#;#;##s8q8q=8q33ss8qZZ\ #!T""""""""z"""z""""""!"""!""""""T"""T""""""""""#r&   c                    d} | t         v }|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} }d	d
i}t        |      }|d	   } d}| |k(  }|slt        j                  d|fd| |f      t        j                  |       t        j                  |      dz  }dd|iz  }t        t        j                  |            dx} x}}y)u   Gemini medium #1: TOKEN_KEY_HINTS 에 `github_pat_` 포함 박제.

    회귀 박제: dict 키 기반 마스킹과 문자열 값 기반 마스킹의 일관성.
    Gemini 6차 Security-High 이후로 key 자체에도 redact 적용됨.
    github_pat_r   r   r   r   r   r   Nmy_github_token_fieldgithub_pat_LEAKED_xxxxxxxxxxxxr   r5   r>   r?   rA   rB   )
r   rG   rH   rL   rI   rJ   rK   rM   rN   r   )	rV   rX   r   r   r   r   rW   rU   rY   s	            r#   2test_gemini_medium_token_hints_includes_github_patr"    s     +=O++++=O+++=++++++O+++O+++++++"$D
ECc"H+,@0@@,0@@@@@,0@@@@,@@@0@@@@@@@@r&   c                    t               } d}t        | |      }| }|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                  |      dz  }t        t	        j                  |            dx}x}}y)u   Gemini medium #2: audit_dir 인자 제거 박제 — 미사용 속성 0건.

    회귀: AutoGeminiTriage 인스턴스에 _audit_dir 속성이 존재하지 않음을 확인.
    
_audit_dirz9assert not %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrrP   )r:   r@   r{   r   N)	r(   r%  rI   rJ   rG   rK   rL   rM   rN   )rP   rX   r   r   rY   s        r#   0test_gemini_medium_no_unused_audit_dir_attributer&    s    
 ^F+,wv|,,,,,,,,,,,w,,,w,,,,,,v,,,v,,,|,,,,,,,,,,r&   c            	     J   t               } dh}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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}}| j                  }d} |||      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      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}}| j                  }d}d}	 |||	      }
d}|
|u }|st        j                  d|fd|
|f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |	      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d
x}x}x}	x}
x}}y
)u   Gemini medium #3: is_in_scope 가 이미 set 인 expected_files 재정규화 생략.

    회귀: 동일 set 인스턴스를 반복 전달해도 복사가 일어나지 않음 (id 비교).
    `triage_batch` 핫패스 최적화의 박제.
    r   Trs   r	  rP   expected_setr  r   r   Nz
utils/x.pyF)z   anu_v2/auto_gemini_triage.py  )z[%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s.is_in_scope
}(%(py4)s, %(py6)s)
} is %(py11)s)r:   r;   r=   rB   r}   py11zassert %(py13)spy13r  )rP   r(  rS   rW   r   r   r   r   r   r   @py_assert7@py_assert10@py_format12@py_format14s                 r#   7test_gemini_medium_is_in_scope_skips_renormalize_on_setr/    s    ^F<=L S<S<lKStSKtSSSSKtSSSSSS6SSS6SSSSSS<SSSSSSlSSSlSSSKSSStSSSSSSSBlBlL9BUB9UBBBB9UBBBBBB6BBB6BBBBBBlBBBBBBLBBBLBBB9BBBUBBBBBBB &-&-  
  
    
  v      I    I    I 	'  I 	.  I   I      r&   c                    t               } dddddd}| j                  |t              \  }}|t        k(  }|st	        j
                  d|fd|t        f      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
dz  }dd|iz  }t        t	        j                  |            d}i |ddi}| j                  |t              \  }}|t        k(  }|st	        j
                  d|fd|t        f      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
dz  }dd|iz  }t        t	        j                  |            d}y)u   Gemini 2차 medium #1: STYLE_ONLY_CATEGORIES 에 `docs` 포함 박제.

    docs 는 코드 동작 무관 → low/medium severity 일 때 dismiss.
    Security-High 우선 분기가 high docs 케이스를 먼저 차단하므로 안전.
    zmissing-docstringr-   docsr   zmodule-level docstring missingrl   r5   r7   r8   r
   r9   r<   r=   Nr0   rp   rh   )rP   docs_findingr8   rd   rS   rT   rU   docs_meds           r#   8test_gemini_medium_docs_category_dismissed_as_style_onlyr4    s>    ^F '.1L ((7MNIFA.....6.......6...6.................. 6,5
H5H((3IJIFA.....6.......6...6..................r&   c                    t               } dh}ddddd}| j                  ||      \  }}|t        k(  }|st        j                  d|fd|t        f      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	d
z  }dd|iz  }t        t        j                  |            d}| j                  ||      \  }}| j                  ||      \  }	}||	k(  }|	t        k(  }
|r|
st        j                  d||
fd||	t        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	t        j                         v st        j                  t              rt        j                  t              nd	dz  }dd|iz  }t        t        j                  |            dx}}
dh}
||
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   Gemini 2차 medium #2: classify_evidence 도 set 입력 재정규화 생략 박제.

    `triage_batch` 가 한 번 정규화한 set 을 매 finding 처리에 그대로 전달하므로
    재정규화 비용 0 — 핫패스 최적화.
    r   r  rp   rq   r   r5   r7   r8   r   r9   r<   r=   N)r6   r6   )r   z%(py3)s == %(py4)saction2action3)r:   r{   r=   rA   rB   r   pre_normalizedr   r   r   )r(   rE   r   rG   rH   rI   rJ   rK   rL   rM   rN   )rP   r8  rQ   r8   rd   rS   rT   rU   r6  r7  rX   rY   r   r   s                 r#   =test_gemini_medium_classify_evidence_skips_renormalize_on_setr9    s    ^F >?NH%.G
 ((.AIFA000006000000060006000000000000000000 ))'>BJGQ))'>BJGQg<<g!<<<<<<7g!<<<<<<<7<<<7<<<<<<g<<<g<<<<<<!<<<<!<<<<<<<<<==>=====>=======>===>===========r&   c                 
	   d} t        |       }d}||k(  }|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
} t        |       }d}||k(  }|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} t        |       }d}||k(  }|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} t        |       }d}||k(  }|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} t        |       }d}||k(  }|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}}y	)u   Gemini 3차 medium #1: _redact_tokens 가 value.lower() 를 루프당 1회만 호출.

    회귀 fixture: prefix 검출 결과는 동일하되, 동일 결과를 보장.
    ghp_TEST_abc123r   r5   r   r   r   r   r   NGHP_UPPERCASE_xxgithub_pat_TESTnormal textghs_BOT_session_)	r   rG   rH   rI   rJ   rK   rL   rM   rN   )rS   rW   r   r   r   r   s         r#   +test_gemini_medium_redact_lowers_value_oncer@    s    ,@>+,@0@@,0@@@@@,0@@@@@@@>@@@>@@@+@@@,@@@0@@@@@@@@,A>,-A1AA-1AAAAA-1AAAAAAA>AAA>AAA,AAA-AAA1AAAAAAAA+@>+,@0@@,0@@@@@,0@@@@@@@>@@@>@@@+@@@,@@@0@@@@@@@@'9>-(9M9(M9999(M999999>999>999-999(999M9999999,A>,-A1AA-1AAAAA-1AAAAAAA>AAA>AAA,AAA-AAA1AAAAAAAAr&   c                    ddi} t        |       }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}}t        |      }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  Gemini 6차 Security-High #1: dict key 자체에 박힌 raw token 도 redact.

    예전 동작: 끼='ghp_TOKEN' 인 경우 끼는 raw 그대로 노출 (token leak).
    수정 후: key 자체에 _redact_tokens 재귀 → '***REDACTED***' 로 마스킹.
    ghp_LEAKED_KEY_NAMEzok-valuer   r   r   r   r   r   Nr   r   r   r   )
r   rG   rH   rL   rI   rJ   rK   rM   rN   r   )r   r   rV   rX   r   r   r   s          r#   5test_gemini_security_high_dict_key_itself_is_redactedrC    s5    !*
-Cc"H 0 0000 000 0000000000000000'x''''x'''''''''x'''x'''''''>D , ,,,, ,,, ,,,,,,,,,,,,,,,,r&   c                 H   ddl m}   |        }d|d<   d|d<   t        |      }|d   }d}||k(  }|slt        j                  d|fd	||f      t        j
                  |      t        j
                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}}|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)uS   Gemini 6차 Security-High #2: dict 외 Mapping (OrderedDict 등) 도 동일 처리.r   )OrderedDictghs_LEAKED_xxxr   r   
safe_fieldr   r5   r>   r?   rA   rB   N)collectionsrE  r   rG   rH   rL   rM   rN   )rE  r   r   rV   rW   rX   rU   rY   s           r#   6test_gemini_security_high_supports_ordereddict_mappingrI  (  s    '
-C*CCc"HN#7'77#'77777#'7777#777'77777777L!)T)!T))))!T)))!)))T)))))))r&   c                 .   ddl m}  | j                  }d} ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}x}}| j                  }d} ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}x}}| j                  }d} ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}x}}| j                  }d} ||      }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}x}}| j                  }d} ||      }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}x}}ddz  dz   ddz  z   }t        |      }	d}|	|k(  }
|
st        j                  d|
fd|	|f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |	      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}	x}
}y)u   Gemini 5차 medium: _TOKEN_VALUE_RE 컴파일 IGNORECASE 정규식 박제.

    re.IGNORECASE + compiled regex 로 lower() 복사본 생성 + substring 루프 제거.
    동작 회귀: case-insensitive 매칭 결과는 동일.
    r   )_TOKEN_VALUE_REghp_xxxN)is not)zP%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.search
}(%(py4)s)
} is not %(py9)srK  )r:   r;   r=   rB   r   zassert %(py11)sr)  GHP_UPPER_xxxGhs_Mixed_Casegithub_PAT_xxxr>  rs   )zL%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.search
}(%(py4)s)
} is %(py9)szPREFIX i  GHP_LEAKED_xxxz SUFFIX r   r5   rx   r   big_bodyrz   r|   r}   )anu_v2.auto_gemini_triagerK  searchrG   rH   rI   rJ   rK   rL   rM   rN   r   )rK  rS   rW   r   r   r+  r   r-  rR  rX   r   rY   r   s                r#   8test_gemini_medium_redact_uses_compiled_regex_ignorecaserU  5  s    :!!8)8!),8D8,D8888,D888888?888?888!888)888,888D8888888!!>/>!/2>$>2$>>>>2$>>>>>>?>>>?>>>!>>>/>>>2>>>$>>>>>>>!!?"2?!"23?4?34????34??????????????!???"2???3???4???????!!?"2?!"23?4?34????34??????????????!???"2???3???4???????!!8-8!-08D80D88880D888888?888?888!888-8880888D88888884"22Z$5FFH(#7'77#'77777#'7777777>777>777777(777(777#777'77777777r&   c                 N   t        dd      t        dd      f} t        |       }dddd	d
}|j                  |t              \  }}|t        k(  }|st        j                  d|fd|t        f      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dz  }dd|iz  }t        t        j                  |            d}y)u   Gemini 4차 medium: signature=None fixture 만 있을 때 body 문자열 생성 생략 박제.

    body 가 lazy init 라도 분류 결과는 정확해야 한다.
    zrule-only-1u   signature 없음r*   zrule-only-2u   signature 없음 2r^   rp   rq   r   r   r5   r7   r8   r	   r9   r<   r=   NrD   )r   rP   rQ   r8   rd   rS   rT   rU   s           r#   Etest_gemini_medium_match_fp_lazy_body_init_with_no_signature_fixturesrW  G  s     	];MN];OPH 8,F .	G ((2HIIFA222226222222262226222222222222222222r&   c                 T   t        ddd      t        ddd      f} t        |       }dd	d
ddd}|j                  |t              \  }}|t        k(  }|st        j                  d|fd|t        f      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dz  }dd|iz  }t        t        j                  |            d}dd	d
ddd}|j                  |t              \  }	}|	t        k(  }|st        j                  d|fd|	t        f      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dz  }dd|iz  }t        t        j                  |            d}y)u   Gemini 3차 medium #2: fp.signature == "" 가 모든 finding 매칭하지 않게 가드.

    빈 문자열 signature 는 re.search 가 항상 매칭하는 함정 회귀 박제.
    zempty-sig-ruler  emptyr\   zreal-fpNz	rule-onlyr^   rp   rq   r   zany random body contentr   r5   r7   r8   r   r9   r<   r=   anythingr6  r	   )r   r(   rE   rF   r   rG   rH   rI   rJ   rK   rL   rM   rN   r	   )
r   rP   	candidater8   rd   rS   rT   rU   
candidate2r6  s
             r#   5test_gemini_medium_empty_signature_does_not_match_allr]  \  sj    	%5GTY${SH 8,F $.)I ((4JKIFA000006000000060006000000000000000000 .J ))*6LMJGQ333337333333373337333333333333333333r&   c                  
   ddl m}   | dddhi      }|d   }t        |t              }|sd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}||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}} | t        ddh            }	t        |	t              }|sd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}||	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)uW   Gemini 7차 medium #1 박제: set/frozenset 안의 token 도 마스킹되어야 한다.r   )r   r   ghp_LEAKsafer  r  redacted_listr  r  Nr   r   r   r   r   r   r   r   	ghs_TOKENr   fset_result)rS  r   r  r  rI   rJ   rG   rK   rL   rM   rN   rH   r  )
r   resultra  rW   rU   rV   rX   r   r   rc  s
             r#   @test_gemini_7_medium_redact_set_and_frozenset_normalizes_to_listre    s   8Vj&%9:;F6NMmT********:***:******m***m******T***T**********,},,,,},,,,,,,,,},,,},,,,,,,*:]****:]***:******]***]******* K+>!?@Kk4((((((((:(((:((((((k(((k((((((4(((4((((((((((*{****{*********{***{*******);k))));k)));))))))k)))k)))))))r&   c                 d   ddl m} m} g fd} | |d      } |dd      f|_        dd	d
d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  }dd|iz  }	t        t        j                  |	            dx}}D 
cg c]  }
|
j                  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  }dd|iz  }	t        t        j                  |	            dx}}yc c}
w )uP   Gemini 7차 medium #2 박제: 잘못된 regex fixture 는 audit 로깅 후 skip.r   )r   r   c                :    j                  t        |              y r   r   r!   s    r#   r$   zQtest_gemini_7_medium_fixture_regex_error_emits_audit_record.<locals>.audit_writer  r%   r&   l   L5: )r$   r   zbad-rulez	(unclosed)r+   r]   zany bodyz	any titler   )r+   r4   r3   r2   Nrs   )z%(py0)s is %(py3)smatchedr   r   r   r~   fixture_regex_errorr   r   kindsr   )rS  r   r   	_fixtures_match_false_positiverG   rH   rI   rJ   rK   rL   rM   rN   r   )r   r   r$   rP   rQ   rh  rX   rS   r   r   r"   rj  rV   r   s                @r#   ;test_gemini_7_medium_fixture_regex_error_emits_audit_recordrm    s7   P K& !F 	Z;GF
 .	G **:w?G7d?7d77d )44SWWV_4E4 ) E)))) E))) ))))))E)))E))))))) 5s   -F-)r   zlist[Mapping[str, Any]] | Noner   r   r   r   r   r   )r   None)G__doc__
__future__r   builtinsrI   _pytest.assertion.rewrite	assertionrewriterG   syspathlibr   typingr   r   __file__resolveparentsWORKSPACE_ROOTr   r2   insertrS  r   r	   r
   r   r   r   r   r   r   r   r   r   rF   r(   rZ   re   rj   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r"  r&  r/  r4  r9  r@  rC  rI  rU  rW  r]  re  rm  r   r&   r#   <module>r}     sm    #   
   h'')11!4~chh&HHOOAs>*+   "  37"/
   08*/**/6,=,H*9 C(S8D$$28 &
@+$	5!"# A-(/0>0
B-
*8$3* 4H*"*r&   