
    jr                    :   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ZddlmZ ddl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 ddlmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' ddl(m)Z) dd	l*m+Z+ dd
l,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2 ddl3m4Z4  ee      j#                         j$                  d   dz  Z5e5dz  Z6e5dz  Z7e5dz  Z8dZ9dZ:dZ;dZ<e<dz   Z=dZ>d8dZ?dd	 	 	 	 	 	 	 	 	 d9dZ@e=dd	 	 	 	 	 	 	 	 	 d:dZAdddd 	 	 	 	 	 	 	 	 	 	 	 	 	 d;d!ZBdd"	 	 	 	 	 	 	 	 	 d<d#ZCd$ ZDd% ZEd& ZFd' ZGd( ZHd) ZId* ZJd+ ZKd, ZLd- ZMd. ZNd/ ZOd0 ZPd1 ZQd2 ZRd3 ZSd4 ZTd5 ZUd6 ZVd7 ZWy)=u}  task-2563 OWNER_TRIGGER_ONLY_CAPABILITY hardening 통합 회귀.

회장 §명시 2026-05-13 KST (task-2563 본질 1:1):
  capability 실전 활용 7회 경험 기반 3건 통합 hardening.

본 파일 커버 (회장 §명시 11 완료 조건 1:1):
  §1 FIRST_TRIGGER_PENDING vs FIRST_GEMINI_TRIGGER_MISSING 상태 구분 (test 1~5)
  §1 owner_trigger_fast_path=false 시 조기 trigger 차단 (test 6)
  §1 owner_trigger_fast_path=true 시 조기 trigger 허용 (test 7)
  §2 http_post signature 3 caller path 동일성 회귀 (test 8~10)
  §3 logger.exception + secret masking (test 11~14)
  §3 fail-closed 속성 유지 (test 15)

fixture (3 종):
  - first_trigger_pending_window.json
  - owner_trigger_signature_mismatch_repro.json
  - owner_trigger_failure_path_logger_exception.json

본 회귀는 anu_v2/* 모듈만 import (one-way isolation). 외부 deps 0 — stdlib + pytest.
    )annotationsN)Path   )!ACTION_FIRST_TRIGGER_PENDING_SKIPACTION_OWNER_TRIGGER_DISPATCHEDACTION_WITHIN_GRACEDISPATCH_DECISION_FAST_PATH_KEYExecutorScheduler)

ALL_STATES$FIRST_TRIGGER_PENDING_WINDOW_SECONDSGRACE_PERIOD_SECONDSGeminiReviewMetaIdlePRDiagnoserIdlePRSnapshotOWNER_TRIGGER_INVOKING_STATES"STATE_FIRST_GEMINI_TRIGGER_MISSINGSTATE_FIRST_TRIGGER_PENDINGSTATE_WITHIN_GRACE_PERIOD)MergeQueueExecutor)OwnerTriggerAudit)ALLOWED_ACTIONCOMMENT_BODYOwnerTriggerOnly_collect_http_diagnostics_redact_diagnosticsinvoke_from_scheduler)FIRST_TIMEOUT_SECONDS   fixturesz!first_trigger_pending_window.jsonz+owner_trigger_signature_mismatch_repro.jsonz0owner_trigger_failure_path_logger_exception.json(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(ccccccccccccccccccccccccccccccccccccccccghp_#MY_SECRET_TOKEN_VALUE_2563_xxxxxxxxMY_SECRET_TOKEN_VALUE_2563c                L    t        j                  | j                  d            S )Nutf-8encoding)jsonloads	read_text)paths    [/home/jay/workspace/scripts/../anu_v2/tests/test_owner_trigger_invocation_hardening_2563.py_load_fixturer/   X   s    ::dnngn677    	task-2563)task_idc                   d|||dddddddd}| d| d	z  }|j                  t        j                  |      d
       |S )Nz anu_v2.owner_trigger_decision.v1TFr   "POST_GEMINI_REVIEW_TRIGGER_COMMENT/gemini review)schemar2   prcurrent_head
queue_headcurrent_head_confirmedgemini_evidence_freshnudge_count_for_pr_headallowed_actioncomment_bodyallowed	decision_z.jsonr'   r(   )
write_textr*   dumps)tmp_pathr7   headr2   decisionr-   s         r.   _write_decisionrF   \   s_     5"&!&#$>(H 	"U++DOODJJx(7O;Kr0   )token	raise_excc               L    dfd}t        | |fdt        |             S )u4   OwnerTriggerOnly 인스턴스 + recording http_post.c                T    j                  | ||t        |      d       dddS )Nmethodr-   bodyheaders   i'  statusidappenddict)rL   r-   rM   rN   
http_callsrH   s       r.   	http_postz _build_runner.<locals>.http_post~   s>     =		
  OT**r0   c                      S N )rG   s   r.   <lambda>z_build_runner.<locals>.<lambda>   s    u r0   workspace_rootrW   token_provideraudit
rL   strr-   ra   rM   rU   rN   rU   returnrU   )r   r   )rC   rV   rG   rH   rW   s    ``` r.   _build_runnerrc   u   s(    + $)	 r0   ztask/task-2563-dev6rZ   T)head_refreviewsci_passc                $    t        | |||||      S )N)numberhead_shard   
created_atgemini_reviewsci_required_all_success)r   )rh   ri   rj   rd   re   rf   s         r.   	_snapshotrm      s#      ' r0   )decision_dirc          	         || dz  dz  }|j                  dd       t        | |      }t        d d d d	 | 
      }t        | |fd||dd      S )NmemoryeventsTparentsexist_okrV   c                    i S rY   rZ   )aes     r.   r[   z"_build_scheduler.<locals>.<lambda>   s    r r0   c                     y)N rZ   )rw   s    r.   r[   z"_build_scheduler.<locals>.<lambda>       r0   c                     y)Nr   rZ   ps    r.   r[   z"_build_scheduler.<locals>.<lambda>   r{   r0   c                     y rY   rZ   r}   s    r.   r[   z"_build_scheduler.<locals>.<lambda>   r{   r0   )	gh_runner
git_runnerpytest_runneraudit_writertask_md_rootc                      S rY   rZ   )	snapshotss   r.   r[   z"_build_scheduler.<locals>.<lambda>   s    ) r0   
test-owner	test-repo)r]   rn   snapshot_providerowner_triggermerge_executorownerrepo)mkdirrc   r   r
   )rC   r   rV   rn   runnerr   s    `    r.   _build_schedulerr      sv     (*X5td38
;F'!!#N !+% r0   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}} t         t        v }|st        j                  d	|fd
t         t        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dz  }dd|iz  }t        t        j                  |            d}t         t        v}|st        j                  d|fdt         t        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dz  }dd|iz  }t        t        j                  |            d}t        t        v }|st        j                  d	|fd
t        t        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dz  }dd|iz  }t        t        j                  |            d}y)uT   task-2563 §1 1:1: STATE_FIRST_TRIGGER_PENDING 상수가 정의 + ALL_STATES 포함.FIRST_TRIGGER_PENDING==%(py0)s == %(py3)sr   py0py3assert %(py5)spy5Ninz%(py0)s in %(py2)sr   r   py2assert %(py4)spy4not inz%(py0)s not in %(py2)sr   r   )r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   r   r   )@py_assert2@py_assert1@py_format4@py_format6@py_format3@py_format5s         r.   4test_1_state_first_trigger_pending_constant_exportedr      s   *AA&*AAAAA&*AAAAAAA&AAA&AAA*AAAAAAAA&*4444&*444444&444&444444*444*4444444&.KKKKK&.KKKKKKK&KKK&KKKKKK.KKKK.KKKKKKKK-1NNNNN-1NNNNNNN-NNN-NNNNNN1NNNN1NNNNNNNNr0   c                    d} d}| |z  }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                  |       t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x} x}}t         t        k  }|st        j                  d
|fdt         t        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dz  }dd|iz  }t        t        j                  |            d	}t        t        k(  }d}t        |k(  } |r| st        j                  d|| fdt        t        |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                  |      dz  }dd|iz  }	t        t        j                  |	            d	x}x} }y	)u^   task-2563 §1 1:1: pending_window 가 FIRST_TIMEOUT_SECONDS 보다 작아야 의미가 있다.   <   r   )z%(py0)s == (%(py3)s * %(py5)s)r   )r   r   r   assert %(py8)spy8N)<)z%(py0)s < %(py2)sr   r   r   r   i  r   r   )r   z%(py3)s == %(py5)sr   assert %(py7)spy7)r   r   r   r   r   r   r   r   r   r   r   )
r   @py_assert4@py_assert6r   @py_format7@py_format9r   r   r   @py_format8s
             r.   ;test_2_pending_window_constant_separates_from_first_timeoutr      sv   349r91r69/69999/6999999/999/9991999r9999999/2GGGGG/2GGGGGGG/GGG/GGGGGG2GGGG2GGGGGGGG#8@@D@#8D@@@@@#8D@@@@@@@@@@@@@@@#8@@@#8@@@D@@@@@@@r0   c                    t        t              } | d   d   }t        |d   |d   |d   |d         }t               j	                  ||d   	      }|j
                  }|d
   }||k(  }|t        k(  }|r|st        j                  d||fd||t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      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}x}x}}|j                  }|d   }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            dx}x}}|j                   }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)uB   fixture PR 8101 — 200s elapsed (< 300s) → WITHIN_GRACE_PERIOD.r   r   rh   ri   rj   rd   rh   ri   rj   rd   nowr   expected_stater   )z-%(py2)s
{%(py2)s = %(py0)s.state
} == %(py6)sz%(py6)s == %(py7)sdiagr   )r   r   py6r   assert %(py9)spy9Nelapsed_secondsr   zE%(py2)s
{%(py2)s = %(py0)s.elapsed_since_created_seconds
} == %(py5)sr   r   r   r   r   Fisz>%(py2)s
{%(py2)s = %(py0)s.requires_owner_trigger
} is %(py5)s)r/   FIXTURE_PENDING_WINDOWrm   r   diagnosestater   r   r   r   r   r   r   r   r   elapsed_since_created_secondsrequires_owner_trigger)fixture	snap_dictsnapr   r   @py_assert5@py_assert3r   r   @py_format10r   s              r.   5test_3_diagnoser_classifies_within_short_grace_windowr      s   23G$Q'I":&\*:&	D %%d	%0@%AD::Q#34Q:4QQ48QQQQQQ:48QQQQQQQ4QQQ4QQQ:QQQ4QQQQQQ8QQQQ8QQQQQQQQ--M;L1MM-1MMMMM-1MMMMMMM4MMM4MMM-MMM1MMMMMMMM&&/%/&%////&%//////4///4///&///%///////r0   c                    t        t              } | d   d   }t        |d   |d   |d   |d         }t               j	                  ||d   	      }|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}}|j                  }d}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|j                   }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)uV   fixture PR 8102 — 900s elapsed (300s ~ 1800s) + reviews 0 → FIRST_TRIGGER_PENDING.r   r   rh   ri   rj   rd   r   r   r   r   z-%(py2)s
{%(py2)s = %(py0)s.state
} == %(py4)sr   r   r   r   r   assert %(py6)sr   Ni  r   r   r   r   Fr   r   )r/   r   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s              r.   Ktest_4_diagnoser_classifies_pending_after_short_window_before_first_timeoutr      s   23G$Q'I":&\*:&	D %%d	%0@%AD::4:44444:444444444444444:444444444444444444--44-4444-44444444444444-4444444444&&/%/&%////&%//////4///4///&///%///////r0   c                 D   t        t              } | d   dd D ]  }t        |d   |d   |d   |d         }t               j	                  ||d	   
      }|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}}|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                   }|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}} y)ub   fixture PR 8103/8104 — first_timeout 경과 + reviews 0 → FIRST_GEMINI_TRIGGER_MISSING 확정.r   r   Nrh   ri   rj   rd   r   r   r   r   r   r   r   r   r   r   Tr   r   r   r   r   >=)zE%(py2)s
{%(py2)s = %(py0)s.elapsed_since_created_seconds
} >= %(py4)sr   )r/   r   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s              r.   7test_5_diagnoser_classifies_missing_after_first_timeoutr      s   23G[)!"- 
K	X&z* .z*	
  ))$Ie4D)Ezz?z?????z???????t???t???z??????????????????**2d2*d2222*d222222t222t222*222d222222211J15JJJJJ15JJJJJJJtJJJtJJJ1JJJJJJ5JJJJ5JJJJJJJJ
Kr0   c                
   t        t              }|d   d   }t        |d   |d   |d   |d         }g }t        | |g|      }|j	                  d	t
        i|d
         }|j                  }t        |      }d}	||	k(  }
|
s
t        j                  d|
fd||	f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |	      dz  }dd|iz  }t        t        j                  |            dx}x}x}
}	|j                  d   }|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}}|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}}|j(                  }d}||k(  }|st        j                  d|fd"||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d#z  }d$d%|iz  }t        t        j                  |            dx}x}}y)&uU   task-2563 §1 + 완료 조건 2: fast_path=false (default) 시 조기 trigger 차단.r   r   rh   ri   rj   rd   r   ru   OWNER_GEMINI_TRIGGER_TOKENr   envr   r   zP%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.pr_actions
})
} == %(py8)slenresultr   py1r   r   r   assert %(py10)spy10Nr   r   actionr   r   r   r   z.%(py2)s
{%(py2)s = %(py0)s.action
} == %(py4)sr   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)srV   r   r   r   r   r   r   )z:%(py2)s
{%(py2)s = %(py0)s.chat_notifications
} == %(py5)sr   r   r   )r/   r   rm   r   run_one_cycle_FAKE_OWNER_TOKEN
pr_actionsr   r   r   r   r   r   r   r   r   r   r   r   r   chat_notifications)rC   r   r   r   rV   	schedulerr   r   r   @py_assert7r   r   @py_format11r   r   r   r   r   r   r   r   s                        r.   :test_6_pending_default_skips_dispatch_when_fast_path_falser     s;   23G$Q'I":&\*:&	D J D6jII$$)+<=e % F
   &3 !&Q&!Q&&&&!Q&&&&&&3&&&3&&&&&&v&&&v&&& &&&!&&&Q&&&&&&&q!F<<6<66666<666666666666666<666666666666666666=================6===6======================z?a?a?a33zz?a$$))$))))$))))))6)))6)))$))))))))))r0   c           
         t        t              }|d   d   }t        |d   |d   |d   |d         }| dz  d	z  }|j                  d
d
       d}|| dz  }|j	                  t        j                  ddd|t        d
i      d       g }t        | |g||      }|j                  dt        i|d         }	|	j                  }
t        |
      }d}||k(  }|s
t        j                  d|fd||f      dt        j                          v st        j"                  t              rt        j$                  t              nddt        j                          v st        j"                  |	      rt        j$                  |	      ndt        j$                  |
      t        j$                  |      t        j$                  |      dz  }dd|iz  }t'        t        j(                  |            dx}
x}x}}|	j                  d   }|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}}|j.                  }|t0        k(  }|st        j                  d|fd&|t0        f      d!t        j                          v st        j"                  |      rt        j$                  |      nd!t        j$                  |      d't        j                          v st        j"                  t0              rt        j$                  t0              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}}|d   d-   }d-d.i}||k(  }
|
slt        j                  d|
fd/||f      t        j$                  |      t        j$                  |      d0z  }d$d%|iz  }t'        t        j(                  |            dx}x}
}y)1uJ   task-2563 §1 + 완료 조건 3: fast_path=true 시 조기 trigger 허용.r   r   rh   ri   rj   rd   r   rp   rq   Trr   r1   z.dispatch-decision.jsonr6   zanu_v2.dispatch_decision.v1r2   r'   r(   )rV   rn   r   r   r   r   r   r   r   r   r   r   Nr   r   r   r   r   r   r   r   r   r   rV   r   r   r   rM   r5   z%(py1)s == %(py4)sr   r   )r/   r   rm   r   rA   r*   rB   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rC   r   r   r   rn   r2   dispatch_decision_pathrV   r   r   r   r   r   r   r   r   r   r   r   r   r   r   @py_assert0s                          r.   ;test_7_pending_with_fast_path_true_dispatches_owner_triggerr  #  s   23G$Q'I":&\*:&	D h&1Ltd3 G)wi7N,OO%%

77/	
  & 	 J 4&ZlI $$)+<=e % F
   &3 !&Q&!Q&&&&!Q&&&&&&3&&&3&&&&&&v&&&v&&& &&&!&&&Q&&&&&&&q!F<<6<66666<666666666666666<666666666666666666==;=;;;;;=;;;;;;;6;;;6;;;=;;;;;;;;;;;;;;;;;;z?a?a?a33zz?aa= >V-=$>> $>>>>> $>>>> >>>$>>>>>>>>r0   c                   t        t              d   }t        | dt              }g fd}t	        | |d t        |             }|j                  |ddt        	      }|j                  }d
}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      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   d   }i }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j"                  d      dz   d |iz  }t        t        j                  |            dx}x}}t!        |      }|d!   }||k(  }d"}||k(  }|r|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                  |      d%z  }d&d'|iz  }t        t        j                  |            dx}x}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}}|j$                  }d.} ||      }|sd/d0t        j                         v st        j                  |      rt        j                  |      nd0t        j                  |      t        j                  |      t        j                  |      d1z  }t        t        j                  |            dx}x}}d2d3i}||k(  }|st        j                  d|fd)||f      d2t        j                         v st        j                  |      rt        j                  |      nd2t        j                  |      d+z  }d,d-|iz  }	t        t        j                  |	            dx}}|d4   d5   d6   D ]  }||v }|st        j                  d7|fd8||f      d9t        j                         v st        j                  |      rt        j                  |      nd9d:t        j                         v st        j                  |      rt        j                  |      nd:d;z  }d<d=|iz  }t        t        j                  |            d} y)>u^   fixture path_1 — OwnerTriggerOnly.trigger_gemini_review() 직접 호출 signature 어셀션.signature_contracti	   r7   rD   c                 H    j                  | t        |      d       dddS )NargskwargsrO   r   rP   rS   r  r  captureds     r.   signature_strict_http_postz_test_8_direct_call_invokes_http_post_with_4_positional_args.<locals>.signature_strict_http_post\  #    f>?Q''r0   c                     t         S rY   r   rZ   r0   r.   r[   zMtest_8_direct_call_invokes_http_post_with_4_positional_args.<locals>.<lambda>c      0 r0   r\   r   r   decision_pathr   r   current_head_actualPOSTEDr   z.%(py2)s
{%(py2)s = %(py0)s.status
} == %(py5)sr   r   r   r   Nr   r   r   r  r   r   r   r   r  r  r  r  u/   keyword args 사용 금지 (signature contract)
>assert %(py6)sr   positional_args_count   r   0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py7)sz%(py7)s == %(py9)sr   r   r   r   r   assert %(py11)spy11POSTr   rL   r   r   r   z/issues/8201/commentsJassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.endswith
}(%(py4)s)
}r-   r   r   r   r   rM   r5   positional_args   required_keysr   r   keyrN   r   r   r   )r/   FIXTURE_SIGNATURE_REPROrF   _HEAD_SIGNATUREr   r   trigger_gemini_reviewrQ   r   r   r   r   r   r   r   r   r   _format_assertmsgendswith)rC   contractr  r  r   r   r   r   r   r   r   r   r   r   r   r  r  r   r   @py_assert8r   @py_format12rL   r-   rM   rN   r   r'  r   r  s                                @r.   ;test_8_direct_call_invokes_http_post_with_4_positional_argsr0  T  sL   456JKH#HOLM H( ,0)	F ))#+	 * F ==$H$=H$$$$=H$$$$$$6$$$6$$$=$$$H$$$$$$$x=A=A=A33xx=AA;vDA;x YBY B&YYY BYYY YYYBYYY(YYYYYYYYt9>!89>99>>Q>9Q>>>>>99Q>>>>>>3>>>3>>>>>>t>>>t>>>9>>>9>>>Q>>>>>>>"&FD$6V6V66V==101=01111111141114111=11101111111111,--4-----4-------4---4-----------)*1-o> g~sgssggr0   c                   t        | dt              }g fd}t        | |d t        |             }t	        ||ddt              }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   d   }i }||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}	||	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}}|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&d'i}||k(  }|st        j                  d
|fd||f      d&t        j                         v st        j                  |      rt        j                  |      nd&t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}d(}||v }|st        j                  d)|fd*||f      t        j                  |      d+t        j                         v st        j                  |      rt        j                  |      nd+d,z  }dd|iz  }t        t        j                  |            dx}}y)-uP   fixture path_2 — invoke_from_scheduler() 어댑터 경유 signature 어셀션.i
   r  c                 H    j                  | t        |      d       dddS )Nr
  rO   r   rP   rS   r  s     r.   r  zUtest_9_scheduler_invoke_uses_same_4_arg_signature.<locals>.signature_strict_http_post  r  r0   c                     t         S rY   r  rZ   r0   r.   r[   zCtest_9_scheduler_invoke_uses_same_4_arg_signature.<locals>.<lambda>  r  r0   r\   r   r   r  r  r   r   
result_strr   r   r   Nr   r   r   r  r   r   r   r   r  r  r  r  r   r   r  r!  rL   z/issues/8202/commentsr"  r-   r#  rM   r5   Authorizationr   z%(py1)s in %(py3)srN   r   r   )rF   r)  r   r   r   r   r   r   r   r   r   r   r   r   r,  )rC   r  r  r   r4  r   r   r   r   r   r   r   r   r  r  r   r   rL   r-   rM   rN   r  s                        @r.   1test_9_scheduler_invoke_uses_same_4_arg_signaturer8  y  s   #HOLMH( ,0)	F '#+J "!:!!!!:!!!!!!:!!!:!!!!!!!!!!x=A=A=A33xx=AA;vDA;x &B& B&&&& B&&& &&&B&&&&&&&t99>933tt9"&FD$6V6V66V==101=01111111141114111=11101111111111,--4-----4-------4---4-----------%?g%%%%?g%%%?%%%%%%g%%%g%%%%%%%r0   c           
     N   t        | dt              }g d/fdg d/fd}t        j                  |      }|j                  j                         D cg c]D  }|j                  t        j                  j                  t        j                  j                  fv r|F }}t        |      }d}||k(  }|st        j                  d	|fd
||f      dt        j                         v st        j                  t              rt        j                   t              nddt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }	t        j"                  dt        |             dz   d|	iz  }
t%        t        j&                  |
            dx}x}}t)        | |d t+        |             }|j-                  |ddt              }|j.                  }d}||k(  }|st        j                  d	|fd||f      dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }dd|iz  }t%        t        j&                  |            dx}x}}t              }d}||k(  }t              }||k(  }|r|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t        j                         v st        j                  t              rt        j                   t              ndd!t        j                         v st        j                        rt        j                         nd!t        j                   |      d"z  }d#d$|iz  }t%        t        j&                  |            dx}x}x}x}}d%   d   }d&}||k(  }|slt        j                  d	|fd'||f      t        j                   |      t        j                   |      d(z  }d)d*|iz  }	t%        t        j&                  |	            dx}x}}d%   d   }dd+i}||k(  }|slt        j                  d	|fd'||f      t        j                   |      t        j                   |      d(z  }d)d*|iz  }	t%        t        j&                  |	            dx}x}}d,}d%   d   }||v }|slt        j                  d-|fd.||f      t        j                   |      t        j                   |      d(z  }d)d*|iz  }	t%        t        j&                  |	            dx}x}}yc c}w )0u`   fixture path_3 — wrapper/DI mock 으로 http_post 를 감싸도 동일 4-arg signature 보장.i   r  rL   rM   rN   c                L    j                  | ||t        |      d       dddS )NrK   rO   r%  rP   rS   )rL   r-   rM   rN   
base_callss       r.   base_http_postzOtest_10_wrapper_di_mock_propagates_same_4_arg_signature.<locals>.base_http_post  s,    VT4TXY`TabcQ''r0   c                D    j                  d| |d        | |||      S )Nr  )
args_countrL   r-   rT   )rL   r-   rM   rN   r<  wrapper_callss       r.   wrapper_http_postzRtest_10_wrapper_di_mock_propagates_same_4_arg_signature.<locals>.wrapper_http_post  s)    ANOfdD'::r0   r  r   r   r   positional_paramsr   z5wrapper http_post must accept 4 positional args; got z
>assert %(py8)sr   Nc                     t         S rY   r  rZ   r0   r.   r[   zItest_10_wrapper_di_mock_propagates_same_4_arg_signature.<locals>.<lambda>  r  r0   r\   r   r   r  r  r  r   r   r   r   r   r   )r  z2%(py7)s == %(py11)s
{%(py11)s = %(py8)s(%(py9)s)
}r@  r;  )r   r   r   r   r   r   r   zassert %(py13)spy13r   r!  r  r  r   r   r5   r5  r   )z%(py1)s in %(py4)sr`   )rF   r)  inspect	signature
parametersvalueskind	ParameterPOSITIONAL_ONLYPOSITIONAL_OR_KEYWORDr   r   r   r   r   r   r   r+  r   r   r   r   r*  rQ   )rC   r  rA  sigr~   rB  r   r   r   r   r   r   r   r   r   r   r   r   @py_assert10r/  @py_format14r  r   r;  r<  r@  s                          @@@r.   7test_10_wrapper_di_mock_propagates_same_4_arg_signaturerP    s   #HOLM  J(
 !#M;
 

-
.C &&(66--33

 	
   !xQx!Q&xxx!Qxxxxxx3xxx3xxxxxx xxx xxx!xxxQxxx*_`cdu`v_w(xxxxxxxx#0)	F ))#+	 * F ==$H$=H$$$$=H$$$$$$6$$$6$$$=$$$H$$$$$$$}5555c*o5o55555o55555535553555555}555}555555555555c555c555555*555*555o5555555H%//%////%///%//////////a= >V-=$>> $>>>>> $>>>> >>>$>>>>>>>>6jmI66?66666?6666?666666666667s   A	X"c                    t        | dt              }d
d}t        | |d t        |             }t	        j
                  t              5  |j                  |ddt               d	d	d	       y	# 1 sw Y   y	xY w)ub   signature 가 4-arg 가 아니면 (3-arg / 5-arg) TypeError 등으로 fail — silent fail 방지.i   r  c                
    ddiS )NrQ   rO   rZ   )rL   r-   rM   s      r.   broken_http_post_3argzStest_11_signature_mismatch_breaks_owner_trigger_call.<locals>.broken_http_post_3arg  s    #r0   c                     t         S rY   r  rZ   r0   r.   r[   zFtest_11_signature_mismatch_breaks_owner_trigger_call.<locals>.<lambda>  r  r0   r\   r   r   r  N)rL   ra   r-   ra   rM   rU   rb   rU   )rF   r)  r   r   pytestraises	TypeErrorr*  )rC   r  rS  
runner_bads       r.   4test_11_signature_mismatch_breaks_owner_trigger_callrY    st    #HOLM "'0)	J 
y	! 
((' /	 	) 	

 
 
s   	A,,A5c                    dddt         z   dddddd	d
ddddig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}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   d   }d
}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d    d!   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d    d"   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}t        j                  |      }t         |v}|st        j                  d#|fd$t         |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&d'z  }	d(d)|	i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)/uT   `_redact_diagnostics` 가 token/authorization/api_key/secret/password 키를 redact.i  MY_RAW_TOKEN_xxxxxxxxxxxxxxxxxxBearer 
SECRET_KEYALSO_SECRETzp@ssinternalzABC:DEF:123:456inner_token_xxxi  )rG   status_codesaferG   list_secret)
rQ   rG   r5  api_keyAPI-KEYpasswordsecret_valuex-github-request-idnested
list_field
<redacted>r   r  r  r   r   Nr5  rd  re  rf  rg  rQ   rh  ri  ra  rj  r   r   r   r   _SENTINEL_SECRET
serialisedr   r   r   MY_RAW_TOKENz%(py1)s not in %(py3)sr7  r   r   )rl  r   r   r   r   r   r   r*   rB   r   r   r   )sampleredactedr  r   r   r   r   rm  r   r   r   r   s               r.   ,test_12_redact_diagnostics_masks_secret_keysrr    sr    2"%55 "0&
 78F #6*HG,,,,,,,,,,,,,,,,,,,O$44$4444$444$4444444444I.,.,....,......,.......I.,.,....,......,.......J/</<////<//////<///////N#3|3#|3333#|333#333|3333333H$$$$$$$$$$$$$$$$$$$)*?.??*.?????*.????*???.????????Hg&6,6&,6666&,666&666,6666666Hm,33,3333,333,3333333333L!!$..$....$...$..........L!!$W-==-====-===-========== H%J:----:---------------:---:-------+>++++>+++>++++++++++++++++)<z))))<z)))<))))))z)))z)))))))r0   c                 B   dt         z   t        dz   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}}|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)uO   key 가 일반적이어도 값에 Bearer / ghp_ 등 sentinel 포함 시 redact.r\  rawtokenvaluezregular text)msganotherharmlessru  rk  r   r  r  r   r   Nrv  rw  )rl  _FAKE_OWNER_TOKEN_PREFIXr   r   r   r   r   r   )rp  rq  r  r   r   r   r   s          r.   0test_13_redact_diagnostics_masks_value_sentinelsry    s    +++o="F
 #6*HE?*l*?l****?l***?***l*******I.,.,....,......,.......J1>1>1111>111111>1111111r0   c                  !"# t        t              }|d   d   ##d   }|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        | dt              } G d dt              !g "!"#fd}t        | |d t        |             }	|j!                  t"        j$                  d      5  t'        j(                  t              5  |	j+                  |ddt               ddd       ddd       |j,                  D 
cg c]/  }
|
j.                  t"        j$                  k(  s!|
j0                  .|
1 }}
t3        |      }#d   }||k(  }d}||k(  }|r|st        j                  d||fd|||f      dt        j                         v st        j                  t2              rt        j                  t2              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd |iz  }t        t        j                  |            dx}x}x}x}}|d   }|j5                         }t        |v}|st        j                  d!|fd"t        |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#dz  }d	d
|iz  }t        t        j                  |            d}t6        |v}|st        j                  d!|fd"t6        |f      d$t        j                         v st        j                  t6              rt        j                  t6              nd$d#t        j                         v st        j                  |      rt        j                  |      nd#dz  }d	d
|iz  }t        t        j                  |            d}t8        |v}|st        j                  d!|fd"t8        |f      d%t        j                         v st        j                  t8              rt        j                  t8              nd%d#t        j                         v st        j                  |      rt        j                  |      nd#dz  }d	d
|i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}}g }d+}||v }|}|sd,}||v }|}|sXt        j                  d-|fd.||f      t        j                  |      d#t        j                         v st        j                  |      rt        j                  |      nd#d/z  }d0d1|iz  }|j;                  |       |st        j                  d-fd2|f      t        j                  |      d#t        j                         v st        j                  |      rt        j                  |      nd#d3z  }d4d5|iz  }|j;                  |       t        j<                  |d      i z  }d6d7|iz  }t        t        j                  |            dx}x}x}x}x}}#d8   d9   }||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}}t3        "      }d}||k(  }|st        j                  d|fd;||f      dt        j                         v st        j                  t2              rt        j                  t2              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# 1 sw Y   xY wc c}
w )@u_   task-2563 §3 + 완료 조건 5: logger.exception 호출 + token raw value 미노출 어셀션.exception_scenariosr   secret_must_not_appear_in_logr   )z%(py0)s == %(py2)ssentinelrl  r   r   r   Nim   r  c                        e Zd Zd fdZ xZS )`test_14_logger_exception_called_on_http_post_failure_no_token_leak.<locals>.HttpErrorWithHeadersc               @    t         |   |       || _        || _        y rY   super__init__rQ   response_headers)selfru  rQ   r  	__class__s       r.   r  zitest_14_logger_exception_called_on_http_post_failure_no_token_leak.<locals>.HttpErrorWithHeaders.__init__*  s    GS! DK$4D!r0   )ru  ra   rQ   intr  rU   rb   None__name__
__module____qualname__r  __classcell__r  s   @r.   HttpErrorWithHeadersr  )  s    	5 	5r0   r  c                T    j                  | |d        d   d   d         )NrL   r-   exc_messagerQ   r  )rQ   r  r?  )rL   r-   rM   rN   r  rV   scenarios       r.   failing_http_postz]test_14_logger_exception_called_on_http_post_failure_no_token_leak.<locals>.failing_http_post1  s<    VT:;"]#H%%&89
 	
r0   c                     t         S rY   r  rZ   r0   r.   r[   zTtest_14_logger_exception_called_on_http_post_failure_no_token_leak.<locals>.<lambda><  r  r0   r\   anu_v2.owner_trigger_onlyloggerr   r   r  expected_logger_callsr   r   r  r   exception_recordsr  r  r   r   r   ru  r   rx  r\  ro  r7  r   r   8301z/issues/8301/commentsr   )z%(py3)s in %(py5)s)r   r   z%(py7)sr   )z%(py10)s in %(py12)s)r   py12z%(py14)spy14zassert %(py17)spy17r  rh  r6  r   rV   r   r   r   )r/   FIXTURE_LOGGER_EXCEPTIONrl  r   r   r   r   r   r   r   r   rF   
_HEAD_FAILRuntimeErrorr   r   at_levelloggingERRORrU  rV  r*  recordslevelnoexc_infor   
getMessager   rx  rT   _format_boolop)$rC   caplogr   r}  r   r   r   r  r  r   rr  r   r   r   r.  r   r   r/  recordru  r  r   r   @py_assert9@py_assert11r   @py_format13@py_format15@py_format16@py_format18r   r   r  rV   r  s$                                    @@@r.   Btest_14_logger_exception_called_on_http_post_failure_no_token_leakr    s   45G,-a0H78H'''''8'''''''8'''8''''''''''''''''''#HJGM5| 5 J
 #0)	F 
/J	K ]]<( 	((+" $.	 ) 	 >>QYY'--%?AJJDZ   !KX.E%FK!%FKK!K%F!KKKKK!%F!KKKKKK3KKK3KKKKKK KKK KKK!KKK%FKKK!KKKKKKKq!F



C 3&&&&3&&&&&&&&&&&&&&&3&&&3&&&&&&&C''''C'''''''''''''''C'''C'''''''#3....#3......#...#......3...3.......9C9C9CC ;6:6S=:3:3s:::::6S:::6::::::S:::S:::::::3s:::3::::::s:::s::::::::::::::&'(=>E>#EEEE>#EEE>EEEEEE#EEE#EEEEEEE z?a?a?a33zz?a9	 	 s6   #f:=f-f:5"gg%g-f7	2f::gc                   t        t              }t        | dt              } G d dt              g fd}t        | |d t        |             }|j                  t        j                  d	      5  t        j                  t              5  |j                  |d
dt               ddd       ddd       | dz  dz  dz  }|j                  } |       }|sddt        j                         v st!        j"                  |      rt!        j$                  |      ndt!        j$                  |      t!        j$                  |      dz  }	t'        t!        j(                  |	            dx}}|j+                  d      j-                         D 
cg c]  }
|
rt/        j0                  |
       }}
|D cg c]  }|d   	 }}d}||v }|st!        j2                  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!        j2                  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}}t5        d |D              }|d    }d!}||u }|slt!        j2                  d"|fd#||f      t!        j$                  |      t!        j$                  |      d$z  }	d%d&|	iz  }t'        t!        j(                  |            dx}x}}d'}||v }|st!        j2                  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'   }t7        |      }d)}||k(  }|st!        j2                  d*|fd+||f      d,t        j                         v st!        j"                  t6              rt!        j$                  t6              nd,t!        j$                  |      t!        j$                  |      t!        j$                  |      d-z  }d.d/|iz  }t'        t!        j(                  |            dx}x}x}}|d0   }d1}||k(  }|slt!        j2                  d*|fd2||f      t!        j$                  |      t!        j$                  |      d$z  }	d%d&|	iz  }t'        t!        j(                  |            dx}x}}|d3   }|t8        k(  }|st!        j2                  d*|fd4|t8        f      t!        j$                  |      d5t        j                         v st!        j"                  t8              rt!        j$                  t8              nd5dz  }dd|iz  }t'        t!        j(                  |            dx}}|j+                  d      }t:        |v}|st!        j2                  d6|fd7t:        |f      d8t        j                         v st!        j"                  t:              rt!        j$                  t:              nd8d9t        j                         v st!        j"                  |      rt!        j$                  |      nd9d:z  }d;d<|iz  }	t'        t!        j(                  |	            d}t<        |v}|st!        j2                  d6|fd7t<        |f      d=t        j                         v st!        j"                  t<              rt!        j$                  t<              nd=d9t        j                         v st!        j"                  |      rt!        j$                  |      nd9d:z  }d;d<|iz  }	t'        t!        j(                  |	            d}d>}||v}|st!        j2                  d6|fd?||f      t!        j$                  |      d9t        j                         v st!        j"                  |      rt!        j$                  |      nd9dz  }dd|iz  }t'        t!        j(                  |            dx}}t7              }d@}||k(  }|st!        j2                  d*|fdA||f      d,t        j                         v st!        j"                  t6              rt!        j$                  t6              nd,dBt        j                         v st!        j"                        rt!        j$                        ndBt!        j$                  |      t!        j$                  |      dCz  }dDdE|iz  }t'        t!        j(                  |            dx}x}}dFj?                  dG |j@                  D              }t:        |v}|st!        j2                  d6|fd7t:        |f      d8t        j                         v st!        j"                  t:              rt!        j$                  t:              nd8dHt        j                         v st!        j"                  |      rt!        j$                  |      ndHd:z  }d;d<|iz  }	t'        t!        j(                  |	            d}t<        |v}|st!        j2                  d6|fd7t<        |f      d=t        j                         v st!        j"                  t<              rt!        j$                  t<              nd=dHt        j                         v st!        j"                  |      rt!        j$                  |      ndHd:z  }d;d<|iz  }	t'        t!        j(                  |	            d}y# 1 sw Y   xY w# 1 sw Y   !xY wc c}
w c c}w )Iuc   task-2563 §3 + 완료 조건 6: fail-closed 속성 유지 (audit FAILED + POST 0 + side-effect 0).in   r  c                      e Zd Zy)`test_15_logger_exception_audit_failed_preserved_token_value_not_logged.<locals>.HttpErrorMinimalN)r  r  r  rZ   r0   r.   HttpErrorMinimalr  e  s    r0   r  c                <    j                  | |d        d      )Nr  u%   403 forbidden — insufficient scopesr?  )rL   r-   rM   rN   r  rV   s       r.   r  zatest_15_logger_exception_audit_failed_preserved_token_value_not_logged.<locals>.failing_http_postj  s"    VT:;FGGr0   c                     t         S rY   r  rZ   r0   r.   r[   zXtest_15_logger_exception_audit_failed_preserved_token_value_not_logged.<locals>.<lambda>q  r  r0   r\   r  r  r   r   r  Nrp   rq   zowner-trigger-audit.jsonlzAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}
audit_pathr   r'   r(   r   PENDINGr   r6  resultsr7  r   r   FAILEDc              3  2   K   | ]  }|d    dk(  s|  yw)r   r  NrZ   .0r  s     r.   	<genexpr>zYtest_15_logger_exception_audit_failed_preserved_token_value_not_logged.<locals>.<genexpr>  s     AA8)@aAs   token_value_loggedFr   z%(py1)s is %(py4)sr  r   r   token_hash_prefix
failed_row   r   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   )r   r   r   r   r   r   
error_codeHTTP_POST_FAILr  r   z%(py1)s == %(py3)sr   r   r   rl  
audit_textr   r   r   r   r\  ro  r   r   rV   r   r   r   
c              3  <   K   | ]  }|j                           y wrY   )r  r  s     r.   r  zYtest_15_logger_exception_audit_failed_preserved_token_value_not_logged.<locals>.<genexpr>  s     EallnEs   full_log_text)!r/   r  rF   r  r  r   r   r  r  r  rU  rV  r*  existsr   r   r   r   r   r   r   r,   
splitlinesr*   r+   r   nextr   r   rl  r   joinr  )rC   r  r   r  r  r   r  r   r   r   linerowsr  r  r  r   r   r   r  r   r   r   r   r   r  r   r   r   r  r  rV   s                                @@r.   Ftest_15_logger_exception_audit_failed_preserved_token_value_not_loggedr  `  s   45G#HJGM<  JH #0)	F 
/J	K ]]<( 	((+" $.	 ) 	 H$x/2MMJ:: (('(:EEG 	

4D 
 %))qq{)G)9998w8w8wwAAAJ*+4u4+u4444+u444+444u4444444,*,,,,*,,,,,,,,,*,,,*,,,,,,,-.43./414/14444/144444434443444.444/44414444444l#7'77#'77777#'7777#777'77777777h1>1111>111111111>111>1111111 %%w%7J:----:---------------:---:-------J....J...............J...J.......&9J&&&&9J&&&9&&&&&&J&&&J&&&&&&& z?a?a?a33zz?a IIEfnnEEM=0000=000000000000000=000=0000000M1111M111111111111111M111M1111111S	 	 
 *s0   5oo)oo0o"o	ooc                 B    G d dt               } 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}}|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
)u   `_collect_http_diagnostics` 가 status / x-github-request-id / x-accepted-permissions /
    documentation_url 을 안전하게 수집.c                        e Zd Zd fdZ xZS )Htest_16_collect_http_diagnostics_extracts_github_fields.<locals>.StubExcc                H    t         |   d       d| _        dddd| _        y )Nstub  REQ-1234issues=writehttps://docs.github.com/x)zX-GitHub-Request-IdzX-Accepted-GitHub-Permissionsdocumentation_urlr  )r  r  s    r.   r  zQtest_16_collect_http_diagnostics_extracts_github_fields.<locals>.StubExc.__init__  s*    GV$DK'11?%@%D!r0   )rb   r  r  r  s   @r.   StubExcr    s    	 	r0   r  rQ   r  r   r  r  r   r   Nrh  r  zx-accepted-github-permissionsr  r  r  )r  r   r   r   r   r   r   )r  r   r  r   r   r   r   s          r.   7test_16_collect_http_diagnostics_extracts_github_fieldsr    sg   ,  %WY/D> S >S    >S   >   S       %&4*4&*4444&*444&444*4444444/0BNB0NBBBB0NBBB0BBBNBBBBBBB#$C(CC$(CCCCC$(CCCC$CCC(CCCCCCCCr0   c                    t        j                  t        j                        } | j                  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}}t        |j                        }d	}||v }|st        j                  d
|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d}||v }|st        j                  d
|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}|j                   }d	} ||      }	d}
|	|
k\  }|st        j                  d|fd|	|
f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}x}	x}}
|j                   }d} ||      }	d}
|	|
k\  }|st        j                  d|fd|	|
f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}x}	x}}
y)u   meta-test: OwnerTriggerOnly.__init__ 의 http_post 파라미터 annotation 이 4-arg signature.

    runtime 에서 처음 signature drift 가 발견되지 않도록 정적 회귀.rW   N)is not)z%(py0)s is not %(py3)shttp_post_paramr   r   r   ra   r   r6  annotation_strr7  rU   r   r   )zK%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.count
}(%(py4)s)
} >= %(py9)s)r   r   r   r   r   r  r   r%  )rE  rF  r   r  rG  getr   r   r   r   r   r   r   r   ra   
annotationcount)rM  r  r   r   r   r   r  r  r   r   r.  r   r   r/  s                 r.   ,test_17_signature_callable_annotation_4_argsr    s    

,55
6Cnn((5O"&&?$&&&&?$&&&&&&?&&&?&&&$&&&&&&&334N"5N""""5N"""5""""""N"""N"""""""#6^####6^###6######^###^#######++&+!+&!++++&!++++++>+++>+++++++++&+++!+++++++,,',1,'1,,,,'1,,,,,,>,,,>,,,,,,,,,',,,1,,,,,,,,r0   c                 "   t        t              } | 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}}| 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}}| d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}| d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}| d
   d   }d}||u }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)uH   fixture 자체 sanity check — schema invariants + constants 일관성.	constantsr   r   r  r7  r   r   Nr   expected_invariantsr   r   r  r  r   r   long_polling3pending_state_does_not_invoke_owner_trigger_defaultTr   r  )r/   r   r   r   r   r   r   r   r   r   r   r   )r   r  r   r   r   r   r   r   s           r.   6test_18_pending_window_fixture_loadable_and_invariantsr    s   23G; FGoGKoooooGKooooGooooooKooooKoooooooo; 78Q8<QQQQQ8<QQQQ8QQQQQQ<QQQQ<QQQQQQQQ()*>?D1D?1DDDD?1DDD?DDD1DDDDDDD().9>Q>9Q>>>>9Q>>>9>>>Q>>>>>>>()*_`hdhh`dhhhhh`dhhhh`hhhdhhhhhhhhr0   c                    t        t              d   } | d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}| d
   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}| d   D cg c]  }|d   	 }}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}}| d   d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}| d   d   d   }dt        i}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	c c}w )u=   fixture signature contract == 실제 callable annotation 1:1.r  r  r  r   r  r  r   r   Nkeyword_args_countr   r$  namerK   r   namesr   r   r   expected_valuer!  r   rM   )r/   r(  r   r   r   r   r   r   r   r   r   )r-  r  r   r   r   r   rw   r  r   r   r   s              r.   >test_19_signature_fixture_contract_matches_callable_annotationr    s   456JKH+,11,1111,111,1111111111().Q.)Q....)Q...)...Q....... (): ;<1QvY<E<99599999599999995999599999999999%&q)*:;EvE;vEEEE;vEEE;EEEvEEEEEEE%&q)*:;U?UU;?UUUUU;?UUUU;UUU?UUUUUUUU =s   K#c                    t        t              } | d   }|d   D ]  }|dz   }t        d|i      }|d   }d}||k(  }|st        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }t        j                  d	|d
      dz   d|iz  }	t        t        j                  |	            dx}x}} dD ]  }
t        |
di      }||
   }d}||k(  }|st        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }t        j                  d|
d
      dz   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   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}}| d   d   }d}||u }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)uF   fixture 의 redaction_contract 가 module 의 실제 패턴과 일관.redaction_contractredact_value_sentinelsRAW_TOKEN_VALUE_xxxxxsafe_keyrk  r   r  r  z	sentinel z not redactedr  r   N)rG   r5  rd  re  secretrf  valuezkey fail_closed_invariantsaudit_failed_recordedTr   r  r   audit_token_value_loggedFhttp_post_extra_side_effectsr   &logger_called_before_txn_record_failed)	r/   r  r   r   r   r   r+  r   r   )r   r-  r}  
text_valueoutr  r   r   r   r   r'  s              r.   =test_20_logger_exception_fixture_redaction_pattern_consistentr    s   45G+,H56 V 77
!:z":;:U,U,.UUU,UUUUUU,UUU)H<}0UUUUUUUUV V E!3.13xD<Dx<'DDDx<DDDxDDD<DDD4wm)DDDDDDDDE
 +,-DEMMEMMMMEMMMEMMMMMMMMMM+,-GHQEQHEQQQQHEQQQHQQQEQQQQQQQ+,-KLQPQQLPQQQQQLPQQQQLQQQPQQQQQQQQ+,-UV^Z^^VZ^^^^^VZ^^^^V^^^Z^^^^^^^^r0   )r-   r   rb   rU   )
rC   r   r7   r  rD   ra   r2   ra   rb   r   )
rC   r   rV   listrG   ra   rH   zException | Nonerb   r   )rh   r  ri   ra   rj   ra   rd   ra   re   ztuple[GeminiReviewMeta, ...]rf   boolrb   r   )
rC   r   r   zlist[IdlePRSnapshot]rV   r  rn   zPath | Nonerb   r
   )X__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   rE  r*   r  syspathlibr   rU  __file__resolvers   WORKSPACE_ROOTra   r-   insertanu_v2.executor_schedulerr   r   r   r	   r
   anu_v2.idle_pr_diagnoserr   r   r   r   r   r   r   r   r   r   anu_v2.merge_queue_executorr   anu_v2.owner_trigger_auditr   anu_v2.owner_trigger_onlyr   r   r   r   r   r   anu_v2.polling_policyr   FIXTURES_DIRr   r(  r  _HEAD_PENDINGr)  r  rx  r   rl  r/   rF   rc   rm   r   r   r   r   r   r   r   r  r0  r8  rP  rY  rr  ry  r  r  r  r  r  r  r  rZ   r0   r.   <module>r     s  * #      
   h'')11!4~chh&HHOOAs>*+    ; 8  8 H~%%'//2Z?%(KK &)VV '*\\  
 ' ,/TT / 8  	 	
  
: #"&  	
   F *,.  	
  *  0 !%# 	
  @OA0 0"K *6+?b"J &F/7d
6&*R
2> B?2DD*-"iV_r0   