
    ̦jt0                       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
Z
ddlZddlmZ ddlmZmZmZ ddlZ ee      j)                         j*                  d   Z ee      ej0                  vr"ej0                  j3                  d ee             ddlmZmZmZmZmZ dddZ d	Z!ed
	 	 	 	 	 	 	 	 	 ddZ"ddZ#ddZ$	 	 	 	 	 	 ddZ%	 	 	 	 ddZ&	 	 	 	 	 	 ddZ'ddZ(	 	 	 	 	 	 ddZ)y)u^  tests.regression.test_bot_trigger_fail_2553 — 회장 §명시 fixture 1 (task-2553).

fixture 1: **bot trigger fail** — BOT_GITHUB_TOKEN 댓글이 Gemini auto trigger
작동 안 함 어설션.

회장 dec_1 (2026-05-11) 승인 근거 1:
  - bot 댓글 trigger 0/5 (0%) 미작동 실증 (task-2552 사전조사 5/5 fail 박제)
  - evidence path: memory/events/task-2552.trigger_evidence_audit_24h.json

본 regression 의 핵심 어설션 (정적 + behavioral):
  1. OwnerTriggerPat 의 기본 `token_env` 가 OWNER_GEMINI_TRIGGER_PAT 으로 박제됨
     → BOT_GITHUB_TOKEN 으로 동작하지 않음 (doctrine 박제).
  2. BOT_GITHUB_TOKEN 만 설정된 환경에서 trigger 호출 시 token_missing 으로
     REJECT 됨 → bot token 으로는 절대 `/gemini review` 댓글 작성되지 않음.
  3. 5/5 bot-trigger fail 시나리오 시뮬레이션 — bot 이 댓글을 작성해도 Gemini
     evidence 가 도착하지 않는 모델을 mock 으로 재현.

본 모듈은 `anu_v2.owner_trigger_pat` 를 **수정하지 않고** 외부에서 정적/동적
박제만 수행한다 (read-only regression).
    )annotationsN)Path)AnyMappingSequence   )!EVIDENCE_MISSING_FOR_CURRENT_HEAD
OUTCOME_OKOUTCOME_REJECTEDOWNER_PAT_ENV_NAMEOwnerTriggerPatc                4    t        j                  g | ||      S )N)args
returncodestdoutstderr)
subprocessCompletedProcess)r   r   r   s      B/home/jay/workspace/tests/regression/test_bot_trigger_fail_2553.py_cpr   /   s    &&B:f]cdd    z2026-05-11T12:00:00+00:00	token_envc          	     R     d fd}d	fd}d
fd}t        |||ddd |      S )Nc                l    j                  t        |       t        |xs i       d       t               S )N)r   env)appendlistdictr   )r   r   gh_callss     r   	gh_runnerz _make_trigger.<locals>.gh_runner=   s'    dDODEur   c                :    j                  t        |              y N)r   r   )recordaudit_callss    r   audit_writerz#_make_trigger.<locals>.audit_writerA   s    4<(r   c                   j                  t        |       t        |      d       t        |      j                  j                  dd       t        |      j                  t        j                  t        |       ddd      d       y )	N)payloadpathT)parentsexist_okFr   )ensure_ascii	sort_keysindentzutf-8)encoding)	r   r   strr   parentmkdir
write_textjsondumps)r(   r)   decision_callss     r   decision_writerz&_make_trigger.<locals>.decision_writerD   sl    $w-TKLT
t<T
JJtG}5DQRS 	 	
r   zjeon-jonghyukztaskctl-anuc                     t         S r#   )	_FIXED_TS r   r   <lambda>z_make_trigger.<locals>.<lambda>R   s    i r   )r!   r&   r7   ownerrepoclockr   )r   zSequence[str]r   zMapping[str, str]returnsubprocess.CompletedProcess)r$   Mapping[str, Any]r?   None)r(   rA   r)   r   r?   rB   )r   )r    r%   r6   r   r!   r&   r7   s   ```    r   _make_triggerrC   6   s6    )
 !' r   c                    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}} d	} t         | k7  }|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}} d} t         | k7  }|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}} d} t         | k7  }|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  OwnerTriggerPat 의 기본 token_env 가 OWNER_GEMINI_TRIGGER_PAT 인지 정적 검증.

    회장 §명시 박제: BOT_GITHUB_TOKEN 으로 `/gemini review` 댓글 작성 doctrine 위반.
    본 모듈의 token_env 는 OWNER 전용 secret 이름으로 박제되어야 한다.
    OWNER_GEMINI_TRIGGER_PAT==z%(py0)s == %(py3)sr   py0py3assert %(py5)spy5NBOT_GITHUB_TOKEN)!=)z%(py0)s != %(py3)sGH_TOKENGITHUB_TOKEN)	r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)@py_assert2@py_assert1@py_format4@py_format6s       r   <test_bot_trigger_fail_default_token_env_is_owner_pat_not_botr^   X   s~    "<;!;;;;;!;;;;;;;;;;;;;!;;;;;;;;!33!33333!3333333333333!33333333!+++++++++++++++++++++++++!/////////////////////////r   c                    t         j                  } d} | |      }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |       t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx} x}}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}|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}|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}}y)u   OWNER PAT env 이름이 별도 secret (BOT 과 분리) 으로 박제되어 있는지 정적 어설션.

    회장 §명시 12 필수 구현 조건 #2: token 은 별도 secret 으로 저장
    (`.env.keys` 등 BOT_GITHUB_TOKEN 과 분리).
    OWNER_Lassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}r   rJ   py2py4py6NGEMINIinz%(py1)s in %(py3)spy1rK   rL   rM   TRIGGERPAT)
r   
startswithrT   rU   rR   rV   rW   rX   rY   rS   )r[   @py_assert3@py_assert5@py_format7@py_assert0rZ   r\   r]   s           r   ;test_bot_trigger_fail_owner_pat_env_name_is_isolated_secretrs   e   s    ((22(22222222222222(2222222222222)8)))))8))))8))))))))))))))))))*9*****9****9******************&5&&&&&5&&&&5&&&&&&&&&&&&&&&&&&r   c           	     
   |j                  t        d       |j                  dd       |j                  dd       |j                  dd       g }g }g }t        |||      }|j	                  ddd	t
        | d
z  | dz        }|j                  }|t        k(  }|st        j                  d|fd|t        f      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dz  }	dd|	iz  }
t        t        j                  |
            dx}}d}|j                   }||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }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}||u }|slt        j                  d#|fd$||f      t        j                  |      t        j                  |      d%z  }	dd|	iz  }
t        t        j                  |
            dx}x}}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}|j                   }||v}|st        j                  d&|fd,||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)-u  BOT_GITHUB_TOKEN 만 있고 OWNER_GEMINI_TRIGGER_PAT 누락 시 trigger REJECT.

    회장 §명시 15 금지 #14 (default GH_TOKEN fallback) + #15 (BOT_GITHUB_TOKEN
    대신 OWNER PAT 사용) 박제. fallback X — bot token 으로는 trigger 불가.
    FraisingrN   ghp_BOT_FAKE_TOKENrP   rQ   Q   
botfakeSHAr   audit.jsonldecision.json	pr_numberhead_shaqueue_positiongemini_evidence_stateaudit_log_pathdecision_json_pathrF   z/%(py2)s
{%(py2)s = %(py0)s.outcome
} == %(py4)soutr   rJ   rc   rd   assert %(py6)sre   Ntoken_missingrg   )z.%(py1)s in %(py5)s
{%(py5)s = %(py3)s.reason
})rk   rK   rM   zassert %(py7)spy7z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr    rJ   rk   rK   re   assert %(py8)spy8token_presentisz%(py1)s is %(py4)srk   rd   not in)z%(py1)s not in %(py3)srecord_textrj   rL   rM   )z2%(py1)s not in %(py5)s
{%(py5)s = %(py3)s.reason
})delenvr   setenvrC   trigger_gemini_reviewr	   outcomer   rR   rS   rT   rU   rV   rW   rX   rY   reasonr   r4   r5   )tmp_pathmonkeypatchr    r%   r6   triggerr   r[   ro   @py_format5rq   rr   @py_assert4rZ   r]   @py_format8rp   @py_format9r   r\   s                       r   8test_bot_trigger_fail_bot_token_only_env_rejects_triggerr   s   sI    )59)+?@z#78~';<%'H(*K+-NHk>BG

'
'?-/#o5 ( C ;;*;*****;*******3***3***;******************(cjj(?j((((?j(((?((((((c(((c(((j(((((((x=A=A=A33xx=Ar??+4u4+u4444+u444+444u4444444**[_-K2{2222{222222222{222{22222221szz1z1111z111111111s111s111z1111111r   c                ,   | j                  t        d       | j                  dd       g }g }g }t        j                  t        t              5  t        |||d       ddd       t        |      }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  t              rt        j                  t              nd
dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}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# 1 sw Y   +xY w)u  token_env=BOT_GITHUB_TOKEN 등 OWNER PAT 외 env 이름으로 직접 인스턴스화 시도 시 차단.

    회장 Codex G1 round 2 High — token_env override 화이트리스트 강제 (constructor
    레벨 차단). 호출부가 BOT_GITHUB_TOKEN 같은 env 이름을 token_env 로 넘기면
    `OwnerTriggerPat.__init__` 단계에서 즉시 `ValueError` 발생. doctrine 위반
    시나리오 (OWNER PAT 위치에 BOT 토큰 사용) 를 API 수준에서 차단.
    Fru   BOT_GITHUB_TOKEN_ABSENT)matchr   Nr   rF   r   r   r    r   r   r   r%   )r   r   pytestraises
ValueErrorrC   r   rR   rS   rT   rU   rV   rW   rX   rY   )	r   r    r%   r6   rZ   rp   r   rq   r   s	            r   9test_bot_trigger_fail_explicit_bot_token_env_also_rejectsr      s    )590%@%'H(*K+-N 
z);	< 
k>/	

 x=A=A=A33xx=A{ q q    q      3   3      {   {      q       
 
s   J		Jc                   |j                  t        d       |j                  dd       g }g }g }t        |||      }d}d}t	        d      D ]K  }|j                  d|z   d|d	dt        | d
| dz  | d| dz        }	|	j                  t        k(  sG|dz  }M d}
||
k(  }|st        j                  d|fd||
f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      dz  }dd|iz  }t        t        j                   |            dx}}
t#        |      }
d}|
|k(  }|st        j                  d|fd|
|f      dt        j                         v st        j                  t"              rt        j                  t"              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                   |            dx}
x}}d}
||
k(  }|st        j                  d|fd||
f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      dz  }dd|iz  }t        t        j                   |            dx}}
t#        |      }
d}|
|k(  }|st        j                  d|fd|
|f      dt        j                         v st        j                  t"              rt        j                  t"              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                   |            dx}
x}}|D ]  }|d   }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$        j&                  } ||      }||v}
|
s
t        j                  d%|
fd&||f      t        j                  |      d't        j                         v st        j                  t$              rt        j                  t$              nd't        j                  |      d(t        j                         v st        j                  |      rt        j                  |      nd(t        j                  |      d)z  }d*d+|iz  }t        t        j                   |            dx}x}
x}} y),u  task-2552 사전조사 결과 박제: bot 댓글 5건 작성 시도 → Gemini review 0건.

    본 시뮬레이션은 bot 이 어떻게든 댓글을 작성했다고 가정하더라도 (이는 OwnerTriggerPat
    이 거부할 시나리오), Gemini evidence 가 도착하지 않는 결과를 mock 으로 재현한다.
    5건 trigger 시도 → 5건 모두 REJECT (token_missing) → gh 호출 0 → Gemini evidence 0.

    회장 §명시 승인 근거 1: bot 댓글 trigger 0/5 (0%) 미작동 실증.
    Fru   rN   ghp_BOT_SIM_TOKENr      d   sim03daudit_z.jsonl	decision_.jsonr|      rF   rH   
fail_countrI   rL   rM   Nr   r   r    r   r   r   gemini_evidence_arrivalsr%   r   r   r   r   r   re   r   )zO%(py1)s not in %(py8)s
{%(py8)s = %(py5)s
{%(py5)s = %(py3)s.dumps
}(%(py6)s)
}r4   r$   )rk   rK   rM   re   r   zassert %(py10)spy10)r   r   r   rC   ranger   r	   r   r   rR   rS   rT   rU   rV   rW   rX   rY   r   r4   r5   )r   r   r    r%   r6   r   r   r   attemptr   rZ   r[   r\   r]   rp   r   rq   r   r$   rr   ro   r   @py_assert7@py_format11s                           r   9test_bot_trigger_fail_simulated_5_of_5_no_gemini_evidencer      s    )59)+>?%'H(*K+-NHk>BG  !J8 
++Gm73-("C#wiv&>>'IgYe*DD , 
 ;;**!OJ
 :?:::x=A=A=A33xx=A'((#q((((#q((((((#(((#(((q((((((({ q q    q      3   3      {   {      q        =o&/%/&%////&%///&///%///////"<$**<*V*<<"*<<<<<"*<<<<"<<<<<<$<<<$<<<*<<<<<<V<<<V<<<*<<<<<<<<=r   c                 `   d} | D ]&  }|j                   }d} ||      }|sddt        j                         v st        j                  |      rt        j
                  |      ndt        j
                  |      t        j
                  |      t        j
                  |      dz  }t        t        j                  |            dx}x}}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}}|j                  }d} ||      }|sddt        j                         v st        j                  |      rt        j
                  |      ndt        j
                  |      t        j
                  |      t        j
                  |      dz  }t        t        j                  |            dx}x}}) y)u|  task-2552 사전조사 evidence path 문서화 박제.

    본 regression 의 doctrine 근거는 다음 evidence path 에 있다 (회장 §명시):
      - memory/events/task-2552.trigger_evidence_audit_24h.json (또는 동일 명칭의
        evidence). 본 테스트는 path string 자체를 박제하여 향후 path 변경 시
        regression 이 깨지도록 한다.
    )z7memory/events/task-2552.trigger_evidence_audit_24h.jsonzmemory/events/ra   prb   Nz	task-2552rg   ri   rj   rL   rM   r   zJassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.endswith
}(%(py4)s)
})
rn   rT   rU   rR   rV   rW   rX   rY   rS   endswith)
expected_evidence_pathsr   r[   ro   rp   rq   rr   rZ   r\   r]   s
             r   3test_bot_trigger_fail_evidence_path_doctrine_pinnedr      sO    % #||-,-|,--------q---q---|---,----------{a{a{aazz"'"z'""""""""q"""q"""z"""'""""""""""#r   c           	        |j                  t        d       g }g }g }t        |||      }|j                  dddt        | dz  | dz        }|j
                  }|t        k(  }|st        j                  d|fd	|t        f      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dz  }	dd|	iz  }
t        t        j                  |
            dx}}t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            dx}x}}y)u#  대조군: OWNER PAT 환경에서는 동일 trigger 가 OK 됨 (회장 §명시 10/10 박제 mirror).

    bot trigger fail 의 의미는 "bot 만으로 안 됨" 이지 "모든 trigger 가 안 됨" 이
    아니다. OWNER PAT 환경에서는 정상 동작해야 한다 (대조 검증).
    ghp_OWNER_FAKE_FOR_CONTRASTrx   	ownerheadr   rz   r{   r|   rF   r   r   r
   r   r   re   Nr   r   r   r    r   r   r   )r   r   rC   r   r	   r   r
   rR   rS   rT   rU   rV   rW   rX   rY   r   )r   r   r    r%   r6   r   r   r[   ro   r   rq   rZ   rp   r   r   s                  r   5test_bot_trigger_fail_owner_pat_succeeds_for_contrastr     sn    )+HI%'H(*K+-NHk>BG

'
'?-/#o5 ( C ;;$;*$$$$;*$$$$$$3$$$3$$$;$$$$$$*$$$*$$$$$$$x=A=A=A33xx=Ar   )r    r   )r   intr   r0   r   r0   r?   r@   )
r    list[dict[str, Any]]r%   r   r6   r   r   r0   r?   r   )r?   rB   )r   r   r   pytest.MonkeyPatchr?   rB   )r   r   r?   rB   )*__doc__
__future__r   builtinsrT   _pytest.assertion.rewrite	assertionrewriterR   r4   r   syspathlibr   typingr   r   r   r   __file__resolver*   _WORKSPACE_ROOTr0   r)   insertanu_v2.owner_trigger_patr	   r
   r   r   r   r   r9   rC   r^   rs   r   r   r   r   r   r:   r   r   <module>r      sB  * #     
  ) )  x.((*2215sxx'HHOOAs?+, e (	 ("% )
  D
0
'&2&2#&2 
&2R!#!	!>2=2=#2= 
2=l#&# 
r   