
    jAP                        d Z ddlmZ ddlZddlmc mZ ddl	m
Z
 ddlZddl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mZ ddlmZmZ ddlm Z m!Z!m"Z" d	Z#d
Z$dZ%de#dddd	 	 	 	 	 	 	 	 	 	 	 	 	 d:dZ&d;dZ'd<dZ(d=dZ)d>dZ*d Z+d?dZ,d@dZ-dde-d	 dAdZ.d Z/d Z0d Z1d Z2d Z3d  Z4d! Z5d" Z6d# Z7d$ Z8d% Z9d& Z:d' Z;d( Z<d) Z=ej|                  j                  d*ddidd+idd,id-d.id-d/id0d1id0d2id3d1id3d4ig	      d5        Z@d6 ZAd7 ZBd8 ZCd9 ZDy)Bur  tests.regression.test_owner_gemini_trigger_router — task-2641 Track A.

회장 verbatim 12 (2026-05-23) 1:1 정합 — router state machine + return enum 회귀.

본 회귀는 Layer A / NO-CRON: subprocess / cokacdir / merge / cron / live gh 호출 0.
freshness_checker / invoke_scheduler / github_api / permission diagnostics provider
모두 callable inject (mock).
    )annotationsN)Any)FreshnessResultRESULT_FRESHRESULT_STALE)DEFAULT_FRESH_REVIEW_TIMEOUT_SNUDGE_HARD_LIMIT_PER_PR_HEADOwnerGeminiTriggerRouter(ROUTER_RESULT_CHAIR_UI_FALLBACK_REQUIREDROUTER_RESULT_FRESH+ROUTER_RESULT_GEMINI_EXTERNAL_TRIGGER_STALE ROUTER_RESULT_NOT_GEMINI_TRIGGERROUTER_RESULT_NUDGE_DEDUPED%ROUTER_RESULT_NUDGE_PERMISSION_DENIEDROUTER_RESULT_NUDGE_POSTEDRouterContractError)AUDIT_SCHEMAOwnerGeminiTriggerRouterAudit)RESULT_DEDUPEDRESULT_FAILEDRESULT_POSTED(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(cccccccccccccccccccccccccccccccccccccccc      test)	pr_numberheadgemini_commit_id	inspectedreasonr   c                $    t        | |||||      S )N)statusr   current_head_shagemini_commit_id_observedreviews_inspectedr"   )r   )r$   r   r   r    r!   r"   s         H/home/jay/workspace/tests/regression/test_owner_gemini_trigger_router.py_make_freshnessr)   5   s#     "2#     c                      fd}|S )Nc                     S N )_kwargsresults    r(   _checkerz!_stub_freshness.<locals>._checkerI   s    r*   r.   )r0   r1   s   ` r(   _stub_freshnessr2   H   s     Or*   c                      ddi fd}|S )uC   multi-call freshness — 첫 호출과 post-nudge 재호출 분리.ir   c                 T    d   }|dz   d<   t        |t              dz
           S )Nr4   r   )minlen)r/   idxresultsstates     r(   r1   z'_stub_freshness_queue.<locals>._checkerS   s4    Cj1Wc
s3Gq 0122r*   r.   )r9   r1   r:   s   ` @r(   _stub_freshness_queuer;   O   s    !HE3
 Or*   c                (     g  fd}|_         |S )Nc                 *    j                  |        S r-   )append)kwargscapturedr$   s    r(   _invokez_stub_invoke.<locals>._invoke^   s    r*   )r@   )r$   rA   r@   s   ` @r(   _stub_invokerB   [   s    H  GNr*   c                      fd}|S )Nc                     r-   r.   )r/   excs    r(   rA   z$_stub_invoke_raises.<locals>._invokeg   s    	r*   r.   )rE   rA   s   ` r(   _stub_invoke_raisesrF   f   s     Nr*   c                      y r-   r.   r.   r*   r(   _no_diagrH   m   s    r*   c                      fd}|S )Nc                      S r-   r.   )payloads   r(   	_providerz_stub_diag.<locals>._providerr   s    r*   r.   )rK   rL   s   ` r(   
_stub_diagrM   q   s     r*   c                    g S r-   r.   )methodpaths     r(   _dummy_github_apirQ   x   s    Ir*   )permission_diagnostics_providertoken_provider
github_apic          	     L    t        |       }t        | |||xs t        |||      S )N)workspace_rootfreshness_checkerinvoke_schedulerrR   rS   auditrT   )r   r
   rH   )tmp_pathrW   rX   rR   rS   rT   rY   s          r(   _make_routerr[   |   s5     *(3E#+)+7x%
 
r*   c                ^   t        | t        t        t                    t	        t
                    }ddddddid	}|j                  d
t        dd|d       }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      nd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}}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}}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 ) Nr$   rW   rX   l   O review	COMMENTED loginJeon-Jonghyuk)idkindr:   bodyuserr   orr   r%   ownerrepoobserved_commentdecision_path==z3%(py2)s
{%(py2)s = %(py0)s.final_state
} == %(py4)sr0   r   py0py2py4assert %(py6)spy6Fisz7%(py2)s
{%(py2)s = %(py0)s.nudge_attempted
} is %(py5)srs   rt   py5assert %(py7)spy7z	PR Reviewin)z.%(py1)s in %(py5)s
{%(py5)s = %(py3)s.reason
}py1py3r|   z	task-2640)r[   r2   r)   r   rB   r   route_for_prHEAD_Afinal_stater   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationnudge_attemptedr"   )rZ   routerobservedr0   @py_assert1@py_assert3@py_format5@py_format7@py_assert4@py_format6@py_format8@py_assert0@py_assert2s                r(   )test_pr_review_empty_body_blocks_misrouter      s=   )/*NO%m4F /*H   ! ! F A!AAAAA!AAAAAAA6AAA6AAAAAAAAA!AAAA!AAAAAAAA!!*U*!U****!U******6***6***!***U*******'&--';-'''';-''';''''''&'''&'''-''''''''&--';-'''';-''';''''''&'''&'''-'''''''r*   c           	     H   t        | t        t        t        t                    t        t                    }ddddid}|j                  dt        d	d
|d      }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      nd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}}y)uO   issue_comment "/gemini review" 는 short-circuit 0 → freshness 평가 진행.r$   r    r^   issue_commentz/gemini reviewrb   rc   )re   rf   rg   r   rh   ri   Nrj   ro   rq   r0   r   rr   rv   rw   Frx   rz   r{   r}   r~   )r[   r2   r)   r   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   )rZ   r   r   r0   r   r   r   r   r   r   r   s              r(   4test_issue_comment_exact_body_does_not_short_circuitr      sd   )<&I
 &m4F   /*H
   ! ! F 4!44444!444444464446444444444!4444!44444444!!*U*!U****!U******6***6***!***U*******r*   c           	     8   t        | t        t        t        t                    t        t                    }|j                  dt        ddd       }|j                  }|t        k(  }|st        j                  d|fd|t        f      d	t        j                         v st        j                  |      rt        j                  |      nd	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 )Nr   r^   r   rh   ri   r   r%   rk   rl   rn   ro   rq   r0   r   rr   rv   rw   Frx   rz   r{   r}   r~   )zA%(py2)s
{%(py2)s = %(py0)s.gemini_commit_id_observed
} == %(py4)sr   )r[   r2   r)   r   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r&   
rZ   r   r0   r   r   r   r   r   r   r   s
             r(   )test_freshness_fresh_passes_without_nudger      s   )<&I
 &m4F    ! F 4!44444!444444464446444444444!4444!44444444!!*U*!U****!U******6***6***!***U*******++5+v5555+v55555565556555+555555v555v5555555r*   c           
     X
   t        t              }t        | t        t	        t
        t              t	        t        t                    |      }|j                  dt        dddd      }|j                  }|t        k(  }|st        j                  d	|fd
|t        f      dt        j                         v st        j                   |      rt        j"                  |      nd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}}|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   d   }|t        k(  }|st        j                  d	|fd |t        f      t        j"                  |      d!t        j                         v st        j                   t              rt        j"                  t              nd!d"z  }d#d$|iz  }	t%        t        j&                  |	            d x}}y )%Nr   r^   r   rh   ri   memory/decisions/d.jsonTr   r%   rk   rl   rn   fresh_review_arrived_post_nudgero   rq   r0   r   rr   rv   rw   rx   rz   r{   r}   r~   z4%(py2)s
{%(py2)s = %(py0)s.nudge_result
} == %(py4)sr   r   )zN%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.captured
})
} == %(py8)sr7   invokers   r   r   r|   py8assert %(py10)spy10r   current_head_actualz%(py1)s == %(py3)sr   r   r   assert %(py5)sr|   )rB   r   r[   r;   r)   r   HEAD_Br   r   r   r   r   r   r   r   r   r   r   r   r   r   nudge_resultr@   r7   )rZ   r   r   r0   r   r   r   r   r   r   r   r   @py_assert7@py_assert6@py_format9@py_format11r   @py_format4s                     r(   0test_stale_then_posted_then_fresh_review_arrivesr      s   -(F/<&I<&I
  F   /(, ! F 4!44444!444444464446444444444!4444!44444444!!)T)!T))))!T))))))6)))6)))!)))T)))))))/-////-//////6///6/////////-///-///////$3$1$1$$$$1$$$$$$3$$$3$$$$$$v$$$v$$$$$$$$$1$$$$$$$??134>4>>>>4>>>4>>>>>>>>>>>>>>>>r*   c           
     b   t        | t        t        t        t              t        t        t                    t        t                    }|j                  dt        dddd      }|j                  }|t        k(  }|st        j                  d	|fd
|t        f      dt        j                         v st        j                  |      rt        j                   |      nd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 )Nr   r^   r   rh   ri   r   Tr   ro   rq   r0   r   rr   rv   rw   rx   rz   r{   r}   r~   r   r   )r[   r;   r)   r   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s
             r(   5test_stale_then_posted_no_fresh_review_classify_staler     s   /<&I<&I
 &m4F   /(, ! F L!LLLLL!LLLLLLL6LLL6LLLLLLLLL!LLLL!LLLLLLLL!!)T)!T))))!T))))))6)))6)))!)))T)))))))/-////-//////6///6/////////-///-///////r*   c           	     8   t        | t        t        t        t                    t        t                    }|j                  dt        dddd      }|j                  }|t        k(  }|st        j                  d	|fd
|t        f      dt        j                         v st        j                  |      rt        j                   |      nd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}}y )Nr   r^   r   rh   ri   r   Fr   ro   rq   r0   r   rr   rv   rw   Trx   rz   r{   r}   r~   )r[   r2   r)   r   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s
             r(   Etest_stale_then_posted_without_post_nudge_signal_returns_nudge_postedr     sM   )<&I
 &m4F   /(- ! F ;!;;;;;!;;;;;;;6;;;6;;;;;;;;;!;;;;!;;;;;;;;!!)T)!T))))!T))))))6)))6)))!)))T)))))))r*   c                N   t        |       }|j                  ddt        dt        dt        ddddddd	       t        t              }t        | t        t        t        t        
            |t        |t              }|j                  dt        ddd      }|j                  }|t        k(  }|st        j                   d|fd|t        f      dt#        j$                         v st        j&                  |      rt        j(                  |      nd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}}	|j0                  }|t2        k(  }|st        j                   d|fd|t2        f      dt#        j$                         v st        j&                  |      rt        j(                  |      ndt        j(                  |      dt#        j$                         v st        j&                  t2              rt        j(                  t2              nddz  }dd|iz  }t+        t        j,                  |            dx}}|j4                  }g }	||	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) uK   audit 에 prior nudge_attempted=true 가 1건 있으면 2회째는 DEDUPED.priorr   STALETN0123456789abFNUDGE_POSTED)task_idr   r%   freshness_stater&   r   r   permission_header_diagnosticstoken_presenttoken_hash_prefixtoken_value_loggedr   r"   r   rV   rW   rX   rR   rY   rT   rh   ri   r   r   ro   rq   r0   r   rr   rv   rw   rx   rz   r{   r}   r~   r   r   )z0%(py2)s
{%(py2)s = %(py0)s.captured
} == %(py5)sr   )r   r>   r   r   r   rB   r
   r2   r)   r   rH   rQ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r@   )rZ   rY   r   r   r0   r   r   r   r   r   r   r   s               r(   *test_nudge_limit_dedupe_blocks_second_callr   /  s   )(3E	LL &&)/#)-1!!/"')	
" -(F%)<&I
  (0$	F   / ! F <!<<<<<!<<<<<<<6<<<6<<<<<<<<<!<<<<!<<<<<<<<!!*U*!U****!U******6***6***!***U*******0.0000.00000060006000000000.000.0000000?? b ?b    ?b      6   6   ?   b       r*   c                 p   d} t         | k(  }|st        j                  d|fdt         | f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |       dz  }dd|iz  }t        t        j                  |            d x}} y )Nr   ro   )z%(py0)s == %(py3)sr	   rs   r   r   r|   )	r	   r   r   r   r   r   r   r   r   r   r   r   r   s       r(   $test_nudge_hard_limit_default_is_oner   ]  s_    +,,'1,,,,'1,,,,,,',,,',,,1,,,,,,,r*   c                 p   d} t         | kD  }|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 )Nr   )>)z%(py0)s > %(py3)sr   r   r   r|   )	r   r   r   r   r   r   r   r   r   r   s       r(   ,test_default_fresh_review_timeout_s_positiver   a  s_    ,--)A----)A------)---)---A-------r*   c           	     L   dddd}t        | t        t        t        t                    t        t              t        |            }|j                  dt        dd	d
      }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                   |      rt        j"                  |      nd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}}|j,                  }t/        |t0              }|sddt        j                         v st        j                   t.              rt        j"                  t.              nddt        j                         v st        j                   |      rt        j"                  |      nddt        j                         v st        j                   t0              rt        j"                  t0              ndt        j"                  |      dz  }t%        t        j&                  |            d }d }||v }|st        j                  d!|fd"||f      t        j"                  |      dt        j                         v st        j                   |      rt        j"                  |      ndd#z  }d$d%|iz  }	t%        t        j&                  |	            d x}}d&}||v }|st        j                  d!|fd"||f      t        j"                  |      dt        j                         v st        j                   |      rt        j"                  |      ndd#z  }d$d%|iz  }	t%        t        j&                  |	            d x}}d'}||v}|st        j                  d(|fd)||f      t        j"                  |      dt        j                         v st        j                   |      rt        j"                  |      ndd#z  }d$d%|iz  }	t%        t        j&                  |	            d x}}d*d l}|j5                  |      }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 ).Nz!issues=write; pull_requests=write4321zBearer ghp_LEAK_NEVER)X-Accepted-GitHub-PermissionsX-RateLimit-RemainingAuthorizationr   rW   rX   rR   k   rh   ri   r   r   ro   rq   r0   r   rr   rv   rw   Trx   rz   r{   r}   r~   r   r   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancediagdict)rs   r   rt   ru   x-accepted-github-permissionsr   z%(py1)s in %(py3)sr   r   r|   zx-ratelimit-remainingauthorizationnot inz%(py1)s not in %(py3)sr   ghp_
serialisedzBearer )r[   r2   r)   r   r   rB   r   rM   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   jsondumps)rZ   headers_403r   r0   r   r   r   r   r   r   r   r   r   r   r   _jsonr   s                    r(   @test_failed_invoke_with_403_headers_classifies_permission_deniedr   h  sL   )L!'0K
 )<&I
 &m4(2;(?F   / ! F F!FFFFF!FFFFFFF6FFF6FFFFFFFFF!FFFF!FFFFFFFF!!)T)!T))))!T))))))6)))6)))!)))T)))))))/-////-//////6///6/////////-///-/////////DdD!!!!!!!!:!!!:!!!!!!d!!!d!!!!!!D!!!D!!!!!!!!!!*2*d2222*d222*222222d222d2222222"*"d****"d***"******d***d*******&?$&&&&?$&&&?&&&&&&$&&&$&&&&&&&T"J#6####6###6################&9J&&&&9J&&&9&&&&&&J&&&J&&&&&&&r*   c           	        ddd}t        | t        t        t        t                    t        t        d            t        |            }|j                  dt        dd	d
      }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                   |      rt        j"                  |      nd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)ua   invoke_scheduler 가 직접 예외를 던져도 diagnostics provider 가 403 회수하면 분류.issues=writepublic_repo)r   zX-OAuth-Scopesr   403r   r   rh   ri   r   r   ro   rq   r0   r   rr   rv   rw   N)r[   r2   r)   r   r   rF   RuntimeErrorrM   r   r   r   r   r   r   r   r   r   r   r   r   )rZ   r   r   r0   r   r   r   r   s           r(   @test_invoke_raises_with_403_headers_classifies_permission_deniedr     s     *8'K )<&I
 -\%-@A(2;(?F   / ! F F!FFFFF!FFFFFFF6FFF6FFFFFFFFF!FFFF!FFFFFFFFr*   c           	        t        | t        t        t        t                    t        t              t              }|j                  dt        ddd      }|j                  }|t        k(  }|st        j                  d|fd	|t        f      d
t        j                         v st        j                   |      rt        j"                  |      nd
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)uR   diagnostics provider 가 None 반환 → CHAIR_UI_FALLBACK_REQUIRED 최후 수단.r   r   r   rh   ri   r   r   ro   rq   r0   r   rr   rv   rw   N)r[   r2   r)   r   r   rB   r   rH   r   r   r   r   r   r   r   r   r   r   r   r   rZ   r   r0   r   r   r   r   s          r(   =test_failed_invoke_without_403_headers_falls_back_to_chair_uir     s    )<&I
 &m4(0F   / ! F I!IIIII!IIIIIII6III6IIIIIIIII!IIII!IIIIIIIIr*   c           	        t        | t        t        t        t                    t        t        d            t              }|j                  dt        ddd      }|j                  }|t        k(  }|st        j                  d	|fd
|t        f      dt        j                         v st        j                   |      rt        j"                  |      nd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 )Nr   z
token goner   r   rh   ri   r   r   ro   rq   r0   r   rr   rv   rw   )r[   r2   r)   r   r   rF   r   rH   r   r   r   r   r   r   r   r   r   r   r   r   r   s          r(   =test_invoke_raises_without_diagnostics_falls_back_to_chair_uir     s    )<&I
 -\,-GH(0F   / ! F I!IIIII!IIIIIII6III6IIIIIIIII!IIII!IIIIIIIIr*   c           	        t        | t        t        t        t                    t        t                    }|j                  dt        ddd      }|j                  }|t        k(  }|st        j                  d|fd	|t        f      d
t        j                         v st        j                  |      rt        j                   |      nd
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 )Nr   r^   r   rh   ri   r   r   ro   rq   r0   r   rr   rv   rw   )r[   r2   r)   r   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s          r(   5test_invoke_returns_deduped_classifies_router_dedupedr     s    )<&I
 &n5F   / ! F <!<<<<<!<<<<<<<6<<<6<<<<<<<<<!<<<<!<<<<<<<<r*   c           	        t        | t        t        t        t                    t        t                    }t        j                  t              5  |j                  dt        ddd        d d d        y # 1 sw Y   y xY w)Nr   r^   r   rh   ri   r   )r[   r2   r)   r   r   rB   r   pytestraisesr   r   r   )rZ   r   s     r(   6test_stale_without_decision_path_raises_contract_errorr     sq    )<&I
 &m4F 
*	+ 
# 	 	

 
 
s   A55A>r?   Tr%   short(ggggggggggggggggggggggggggggggggggggggggrk   ra   z
with/slashrl   zx/yc                "   t        | t        t        t                    t	        t
                    }dt        dddd}|j                  |       t        j                  t              5   |j                  di | d d d        y # 1 sw Y   y xY w)	Nr]   r^   r   rh   ri   xr   r.   )r[   r2   r)   r   rB   r   r   updater   r   r   r   )rZ   r?   r   bases       r(   (test_input_validation_rejects_bad_kwargsr    s     )/*NO%m4F "D 	KK	*	+ $#d#$ $ $s   )BBc                x   dd l }t        |       }t        | t        t	        t
        t                    t        t              t        ddddd      |t              }|j                  d	t        d
dd      }|j                  }|t        k(  }|st        j                   d|fd|t        f      dt#        j$                         v st        j&                  |      rt        j(                  |      nd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.                  j1                  d      j3                         }	|j5                  |	j7                         d         }
|
d   }|t8        k(  }|st        j                   d|fd|t8        f      t        j(                  |      dt#        j$                         v st        j&                  t8              rt        j(                  t8              nddz  }dd|iz  }t+        t        j,                  |            d x}}|
d   }|t        k(  }|st        j                   d|fd|t        f      t        j(                  |      dt#        j$                         v st        j&                  t              rt        j(                  t              nddz  }dd|iz  }t+        t        j,                  |            d x}}|
d   }d }||u }|slt        j                   d!|fd"||f      t        j(                  |      t        j(                  |      d#z  }dd|iz  }t+        t        j,                  |            d x}x}}|
d$   }|t        k(  }|st        j                   d|fd|t        f      t        j(                  |      d%t#        j$                         v st        j&                  t              rt        j(                  t              nd%dz  }dd|iz  }t+        t        j,                  |            d x}}|
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)}||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 )0Nr   r   r   rl   1zBearer ghp_NEVER)r   zX-Accepted-OAuth-Scopesr   r   r   r   rh   ri   dr   ro   rq   r0   r   rr   rv   rw   utf-8encodingr   schemar   r   r   r   r|   r   r   Trx   z%(py1)s is %(py4)sr   ru   r   r   r   Fr   r   r   r   r   r   r   r   )r   r   r
   r2   r)   r   r   rB   r   rM   rQ   r   r   r   r   r   r   r   r   r   r   r   r   rP   	read_textstriploads
splitlinesr   )rZ   r   rY   r   r0   r   r   r   r   textrowr   r   r   r   r   s                   r(   =test_audit_jsonl_records_final_state_and_redacted_diagnosticsr    s   )(3E%)<&I
 &m4(21?+1),!3	)
 $F"    ! F F!FFFFF!FFFFFFF6FFF6FFFFFFFFF!FFFF!FFFFFFFF::1779D
++doo'+
,Cx=(=L((((=L(((=((((((L(((L(((((((}F!FFFFF!FFFFFFFFFF!FFFF!FFFFFFFF !)T)!T))))!T)))!)))T)))))))~/-////-/////////-///-///////#$--$----$---$----------./D*2*d2222*d222*222222d222d2222222&?$&&&&?$&&&?&&&&&&$&&&$&&&&&&&r*   c                `   dt        | t        t        t                    t	        t
              fd      }|j                  dt        dd      }|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%        |      }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"                  }|v}|st        j                  d|fd|f      dt        j                         v st        j                        rt        j                        nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                   |            d x}}dd l}|j(                  j*                  j-                  d      }|v}|st        j                  d|fd |f      dt        j                         v st        j                        rt        j                        ndd!t        j                         v st        j                  |      rt        j                  |      nd!d"z  }d#d$|iz  }t        t        j                   |            d }|j/                  |j1                         j3                         d%         }|d&   }|j"                  }||k(  }|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}}|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 )-N ghp_super_secret_token_value_xyzr]   c                      S r-   r.   )secret_tokens   r(   <lambda>z>test_token_provider_records_only_hash_prefix.<locals>.<lambda>O  s    | r*   rW   rX   rS   r   rh   ri   r   r%   rk   rl   Trx   z5%(py2)s
{%(py2)s = %(py0)s.token_present
} is %(py5)sr0   r{   r}   r~      ro   )zW%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.token_hash_prefix
})
} == %(py8)sr7   r   r   r   r   )z=%(py0)s not in %(py4)s
{%(py4)s = %(py2)s.token_hash_prefix
}r  rr   rv   rw   r   r  r  )z%(py0)s not in %(py2)sr  )rs   rt   zassert %(py4)sru   r   r   )z9%(py1)s == %(py5)s
{%(py5)s = %(py3)s.token_hash_prefix
}r   r   Fr	  r
  )r[   r2   r)   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r7   r   _auditrP   r  r  r  r  )rZ   r   r0   r   r   r   r   r   r   r   r   r   r   r   r   r   r  @py_format3r  r   r  s                       @r(   ,test_token_provider_records_only_hash_prefixr  I  se   5L)/*NO%m4+	F   	 ! F '4'4''''4''''''6'''6''''''4'''''''''.3'(.B.(B....(B......3...3......v...v...'...(...B.......%777<77777<7777777<777<777777v777v77777777777=='''9Dt####<t######<###<######t###t#######
++djjl--/3
4C"#?v'?'??#'?????#'????#??????v???v???'????????#$--$----$---$----------r*   c                   d }t        | t        t        t                    t	        t
              |      }|j                  dt        dd      }|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"                  }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 )Nc                     t        d      )Nztoken unavailable)r   r.   r*   r(   
_bad_tokenzJtest_token_provider_failure_yields_token_present_false.<locals>._bad_tokene  s    .//r*   r]   r  r   rh   ri   r  Frx   r  r0   r{   r}   r~   ra   ro   )z9%(py2)s
{%(py2)s = %(py0)s.token_hash_prefix
} == %(py5)s)r[   r2   r)   r   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   )	rZ   r   r   r0   r   r   r   r   r   s	            r(   6test_token_provider_failure_yields_token_present_falser!  d  s7   0 )/*NO%m4!	F   	 ! F (5(5((((5((((((6(((6((((((5(((((((##)r)#r))))#r))))))6)))6)))#)))r)))))))r*   c                 n   t         t        t        t        t        t
        t        h} 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 )	N   ro   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr7   states)rs   r   r   rw   zassert %(py8)sr   )r   r   r   r   r   r   r   r7   r   r   r   r   r   r   r   r   )r$  r   @py_assert5r   r   r   s         r(   'test_router_result_enum_distinct_statesr&  {  s    "#30-(F v;!;!;!33vv;!r*   )r$   strr   intr   r'  r    z
str | Noner!   r(  r"   r'  returnr   )r0   r   )r9   r   )r$   r'  )rE   	Exception)rK   zdict | None)rO   r'  rP   r'  r)  r   )r)  r
   )E__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   typingr   r   (anu_v2.gemini_evidence_freshness_checkerr   r   r   "anu_v2.owner_gemini_trigger_routerr   r	   r
   r   r   r   r   r   r   r   r   (anu_v2.owner_gemini_trigger_router_auditr   r   anu_v2.owner_trigger_auditr   r   r   r   r   HEAD_Cr)   r2   r;   rB   rF   rH   rM   rQ   r[   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   markparametrizer  r  r  r!  r&  r.   r*   r(   <module>r9     s   #      
     
		 #'  	
 !   &	 %)  4(6+:6.?:0,*.+!\-."'JG0J(J,=*
* 	a	b	d	W%	X&	"	,		
$$*''Z.6*.
r*   