
    jG                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
mZ ddlZddlmZmZ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m Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ ddl,m-Z-m.Z.m/Z/m0Z0m1Z1 dZ2d-d	Z3d.d
Z4d/dZ5d0dZ6dddddd	 	 	 	 	 	 	 	 	 	 	 	 	 d1dZ7d Z8d Z9ejt                  jw                  de&dfe"dfe%dfe(dfg      d        Z<d Z=d Z>d Z?d Z@d ZAd ZBd ZCd  ZDd! ZEd" ZFd# ZGd$ ZHd% ZId& ZJd' ZKd( ZLd) ZMd* ZNd+ ZOd, ZPy)2um  tests.regression.test_ci_watch_handoff_runner — task-2642.

회장 verbatim (2026-05-23 19:38 KST) — CI_WATCH_HANDOFF state machine + terminal
classification 1:1 회귀.

Layer A / NO-CRON: subprocess / cokacdir / merge / cron / live gh 호출 0.
모든 inject 는 in-memory mock (ci_status_fn / gemini_router_call_fn /
auto_remediation_fn / callback_send_fn).
    )annotationsN)Iterator)CiWatchHandoffAuditEVENT_AUTO_REMEDIATEEVENT_CALLBACK_FIREDEVENT_HANDOFF_RECEIVEDEVENT_OWNER_NUDGEEVENT_POLL_TICKEVENT_TERMINAL_REACHED)ANU_COLLECTOR_KEYCALLBACK_ENVELOPE_BYTE_LIMITCANONICAL_ROOTCI_STATUS_FAILCI_STATUS_PASSCI_STATUS_PENDINGCiWatchHandoffRunnerCIStatusSnapshotREMEDIATE_APPLIEDREMEDIATE_FORBIDDEN_HITREMEDIATE_LOOP_BOUNDARYREMEDIATE_NON_REMEDIABLEROUTER_CHAIR_UI_FALLBACKROUTER_FRESHROUTER_NUDGE_DEDUPEDROUTER_NUDGE_FAILEDROUTER_NUDGE_PERMISSION_DENIEDROUTER_NUDGE_POSTEDROUTER_NOT_GEMINI_TRIGGERROUTER_STALERouterCallResultRunnerContractError)TERMINAL_CHAIR_REQUIRED!TERMINAL_CI_FAILED_NON_REMEDIABLE&TERMINAL_GEMINI_EXTERNAL_TRIGGER_STALETERMINAL_LOOP_BOUNDARYTERMINAL_MERGE_READY(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac                 j    dt         ddgddgdddd	d
ddd	g ddd	g dd}|j                  |        |S )N   ztask/task-2642-runnerz utils/ci_watch_handoff_runner.pyzscripts/finish-task.shzcokacdir/**dev6-cron-watcherx   <   T   report)enabledmax_nudges_per_pr_headon_403)mediumstylequalitynon-critical-high)r/   allow_severities)MERGE_READYCHAIR_REQUIREDGEMINI_EXTERNAL_TRIGGER_STALECI_FAILED_NON_REMEDIABLELOOP_BOUNDARY)	pr_numberhead_shabranchexpected_filesforbidden_pathswatcher_ownermax_watch_minutespoll_interval_secondsgemini_nudge_policyauto_remediation_policycallback_on_terminal_stateterminal_states)HEADupdate)	overridesbases     D/home/jay/workspace/tests/regression/test_ci_watch_handoff_runner.py_canonical_handoffrM   ?   sk    ).
 %
 - !#&' 
  S$
 '+
1D@ 	KK	K    c                *    t        |       dfd}|S )Nc                    t              S Nnext_handoffits    rL   fnz_sequence_ci.<locals>.fng       BxrN   )rU   dictreturnr   itervaluesrW   rV   s     @rL   _sequence_cir_   d       %)&\B IrN   c                *    t        |       dfd}|S )Nc                    t              S rQ   rR   rT   s    rL   rW   z_sequence_router.<locals>.fnp   rX   rN   )rU   rY   rZ   r    r[   r]   s     @rL   _sequence_routerrc   m   r`   rN   c                *    t        |       dfd}|S )Nc                    t              S rQ   rR   )rU   _ci_snaprV   s     rL   rW   z_sequence_remediate.<locals>.fny   rX   rN   )rU   rY   rf   r   rZ   strr[   r]   s     @rL   _sequence_remediaterh   v   s    	fB IrN         )
router_seqremediate_seqcallback_capture	max_pollsloop_boundary_attemptsc          
         t        |       }dfd}t        | t        |      t        |xs g       |rt	        |      nd ||||      }	|	|fS )Nc                ^    j                  |        t        | j                  d            S )Nutf-8)appendlenencode)enveloperm   s    rL   callback_send_fnz'_build_runner.<locals>.callback_send_fn   s+    '##H-8??7+,,rN   )workspace_rootci_status_fngemini_router_call_fnauto_remediation_fnrw   auditrn   ro   )rv   rg   )r   r   r_   rc   rh   )
tmp_pathci_seqrk   rl   rm   rn   ro   r|   rw   runners
       `     rL   _build_runnerr      s^      )E-
 "!&).z/?R@BO/>UY)5	F 5=rN   c                P   g }t        | t        t              gt        t        d      g|      \  }}|j                  t               dd      }|j                  }|j                  }|t        k(  }|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}}|j                  }|j$                  }|t        k(  }|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}}|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}
||
kD  }|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}}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%}||v }|st        j                  d&|fd'||f      t        j                  |      d(t        j                         v st        j                  |      rt        j                  |      nd(d)z  }d*d+|iz  }t!        t        j"                  |            d x}}d,}||v }|st        j                  d&|fd'||f      t        j                  |      d(t        j                         v st        j                  |      rt        j                  |      nd(d)z  }d*d+|iz  }t!        t        j"                  |            d x}}d-}||v }|st        j                  d&|fd'||f      t        j                  |      d(t        j                         v st        j                  |      rt        j                  |      nd(d)z  }d*d+|iz  }t!        t        j"                  |            d x}}d.}||v }|st        j                  d&|fd'||f      t        j                  |      d(t        j                         v st        j                  |      rt        j                  |      nd(d)z  }d*d+|iz  }t!        t        j"                  |            d x}}d/t.         }||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}}d0t0         }||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 )1Nstatusfresh)final_statereasonr~   rk   rm   t-2642sched-1task_idwatcher_schedule_id==zT%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.decision
}.terminal_state
} == %(py6)sresultr&   py0py2py4py6assert %(py8)spy8)zX%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.decision
}.router_final_state
} == %(py6)sr   Tisz6%(py2)s
{%(py2)s = %(py0)s.callback_fired
} is %(py5)sr   r   py5assert %(py7)spy7r   )>)z<%(py2)s
{%(py2)s = %(py0)s.callback_prompt_bytes
} > %(py5)s<=)z=%(py2)s
{%(py2)s = %(py0)s.callback_prompt_bytes
} <= %(py4)sr   r   r   r   assert %(py6)sr   r-   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)srt   capture)r   py1py3r   z[CI_WATCH_HANDOFF_TERMINAL]in)z%(py1)s in %(py3)senv)r   r   assert %(py5)sr   zterminal_state=MERGE_READYzwatcher_owner=dev6-cron-watcherzwatcher_schedule_id=sched-1zcanonical_root=z
owner_key=)r   r   r   r    r   runrM   decisionterminal_stater&   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationrouter_final_statecallback_firedcallback_prompt_bytesr   rt   r   r   )r}   r   r   r|   r   @py_assert1@py_assert3@py_assert5@py_format7@py_format9@py_assert4@py_format6@py_format8@py_format5@py_assert2r   @py_assert0@py_format4s                     rL   0test_run_ci_pass_router_fresh_yields_merge_readyr      s   G! 78$gNO 	MFE ZZ*,hT]Z^F??A?))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AAA??=?--=-====-======6===6===?===-================  (D( D(((( D((((((6(((6((( (((D(((((((''+!+'!++++'!++++++6+++6+++'+++!+++++++''G'+GGGGG'+GGGGGGG6GGG6GGG'GGGGGG+GGGG+GGGGGGGGw<1<1<133ww<1
!*C(/(C////(C///(//////C///C///////'.'3....'3...'......3...3.......,3,3333,333,3333333333333333(/(C////(C///(//////C///C///////^,-4-4444-444-4444444444444444)*+2+s2222+s222+222222s222s2222222rN   c                   t        | t        t              gt        t              g      \  }}|j                  t                     }|j                  }|j                  }|t        k(  }|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}}d}	|j                  }
|
j$                  }|	|v }|st        j                  d|fd|	|f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }t!        t        j"                  |            d x}	x}x}
}y )Nr   r   r~   rk   r   r   r   r$   r   r   r   u   OWNER nudge 1회 hard limitr   zL%(py1)s in %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.decision
}.reason
}r   r   r   r   assert %(py9)spy9)r   r   r   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   @py_assert6r   r   @py_format10s                  rL   7test_router_stale_maps_to_gemini_external_trigger_staler      s_    78$>?IFA
 ZZ*,-F??S?))S)-SSSSS)-SSSSSSS6SSS6SSS?SSS)SSSSSS-SSSS-SSSSSSSS(BFOOBO,B,BB(,BBBBB(,BBBB(BBBBBBFBBBFBBBOBBB,BBBBBBBBrN   z%router_state,expected_reason_fragmentNUDGE_PERMISSION_DENIEDCHAIR_UI_FALLBACK_REQUIREDNUDGE_FAILEDNOT_GEMINI_TRIGGERc                   t        | t        t              gt        |      g      \  }}|j	                  t                     }|j                  }|j                  }|t        k(  }|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}}|j                  }|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                  |      t        j                  |      dz  }	d	d
|	iz  }
t        t        j                   |
            d x}x}}y )Nr   r   r   r   r   r   r"   r   r   r   r   )zL%(py0)s in %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s.decision
}.reason
}expected_reason_fragment)r   r   r   r    r   rM   r   r   r"   r   r   r   r   r   r   r   r   r   )r}   router_stater   r   r   r   r   r   r   r   r   s              rL   1test_router_critical_states_map_to_chair_requiredr      sq     78$>?IFA
 ZZ*,-F??D?))D)-DDDDD)-DDDDDDD6DDD6DDD?DDD)DDDDDD-DDDD-DDDDDDDD'-='='==#'=====#'=======#===#======v===v======'========rN   c                   t        | t        t              t        t              gt        t              t        t
              g      \  }}|j                  t                     }|j                  }|j                  }|t        k(  }|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}}|j                  }|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                   |      t        j                   |	      dz  }
dd|
iz  }t#        t        j$                  |            d x}x}x}}	y )Nr   r   r   r   r   r   r&   r   r   r      zU%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.decision
}.loop_iterations
} == %(py7)sr   r   r   r   r   r   )r   r   r   r    r   r   r   rM   r   r   r&   r   r   r   r   r   r   r   r   loop_iterationsr}   r   r   r   r   r   r   r   r   r   r   r   s               rL   *test_router_nudge_posted_continues_pollingr      ss   N3N3

 )<=6

IFA ZZ*,-F??A?))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AAA??/?**/a/*a////*a//////6///6///?///*///a///////rN   c                   t        | t        t              t        t              gt        t              t        t
              g      \  }}|j                  t                     }|j                  }|j                  }|t        k(  }|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}}y )Nr   r   r   r   r   r   r&   r   r   r   )r   r   r   r    r   r   r   rM   r   r   r&   r   r   r   r   r   r   r   r   	r}   r   r   r   r   r   r   r   r   s	            rL   +test_router_nudge_deduped_continues_pollingr      s    N3N3

 )=>6

IFA ZZ*,-F??A?))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AAArN   c                   t        | t        t        d      t        t              gt	        t
              gt        g      \  }}|j                  t                     }|j                  }|j                  }|t        k(  }|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}}|j                  }|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"                  |      t        j"                  |	      dz  }
dd|
iz  }t%        t        j&                  |            d x}x}x}}	y )Nr2   r   severityr   r   )r~   rk   rl   r   r   r   r&   r   r   r   r-   z_%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.decision
}.auto_remediation_attempts
} == %(py7)sr   r   r   )r   r   r   r   r    r   r   r   rM   r   r   r&   r   r   r   r   r   r   r   r   auto_remediation_attemptsr   s               rL   8test_ci_fail_remediation_applied_recovers_to_merge_readyr      sp   NXFN3
 %>?()IFA ZZ*,-F??A?))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AAA??9?449949999499999969996999?99949999999999rN   c                   t        | t        t        dd      gt        g      \  }}|j	                  t                     }|j                  }|j                  }|t        k(  }|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}}d}	|j                  }
|
j"                  }|	|v }|st        j                  d|fd|	|f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                   |            d x}	x}x}
}y )Ncritical)ztest-x)r   r   failing_checksr~   rl   r   r   r   r#   r   r   r   znon-remediabler   r   r   r   r   )r   r   r   r   r   rM   r   r   r#   r   r   r   r   r   r   r   r   r   r   s                  rL   0test_ci_fail_remediation_non_remediable_terminalr     s_    \ghi/0IFA
 ZZ*,-F??N?))N)-NNNNN)-NNNNNNN6NNN6NNN?NNN)NNNNNN-NNNN-NNNNNNNN5v5555555555555555555v555v55555555555555rN   c                   t        | t        t        d      gt        g      \  }}|j	                  t                     }|j                  }|j                  }|t        k(  }|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}}y )Nr2   r   r   r   r   r   r"   r   r   r   )r   r   r   r   r   rM   r   r   r"   r   r   r   r   r   r   r   r   r   s	            rL   6test_ci_fail_remediation_forbidden_hit_escalates_chairr     s     JK./IFA
 ZZ*,-F??D?))D)-DDDDD)-DDDDDDD6DDD6DDD?DDD)DDDDDD-DDDD-DDDDDDDDrN   c                   t        | t        t        d      gt        g      \  }}|j	                  t                     }|j                  }|j                  }|t        k(  }|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}}y )Nhighr   r   r   r   r   r%   r   r   r   )r   r   r   r   r   rM   r   r   r%   r   r   r   r   r   r   r   r   r   s	            rL   .test_ci_fail_remediation_loop_boundary_outcomer   #  s     HI./IFA
 ZZ*,-F??C?))C)-CCCCC)-CCCCCCC6CCC6CCC?CCC)CCCCCC-CCCC-CCCCCCCCrN   c                   t        | t        t        dd      t        t        dd      t        t        dd      t        t        dd      gt        t        t        gd      \  }}|j	                  t                     }|j                  }|j                  }|t        k(  }|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}}|j                  }|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                  |      t        j                  |	      dz  }
dd|
iz  }t        t        j                   |            dx}x}x}}	|j                  }|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                  |      t        j                  |	      dz  }
dd|
iz  }t        t        j                   |            dx}x}x}}	y)uV   3회 attempt + same_function_high_repeated=True → 4번째 poll 에서 LOOP_BOUNDARY.r5   T)r   r   same_function_high_repeatedrj   )r~   rl   ro   r   r   r   r%   r   r   r   Nr   r   r   r      r   )r   r   r   r   r   rM   r   r   r%   r   r   r   r   r   r   r   r   r   r   r   s               rL   )test_loop_boundary_same_function_repeatedr   -  s   N=PnrsN=PnrsN=PnrsN=Pnrs	
 )*;=NO 
IFA ZZ*,-F??C?))C)-CCCCC)-CCCCCCC6CCC6CCC?CCC)CCCCCC-CCCC-CCCCCCCC??9?449949999499999969996999?99949999999999??/?**/a/*a////*a//////6///6///?///*///a///////rN   c                d   t        | t        t        dd      g      \  }}|j                  t	                     }|j
                  }|j                  }|t        k(  }|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}}d}	|j
                  }
|
j                   }|	|v }|st        j                  d|fd|	|f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}	x}x}
}|j
                  }|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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}x}}y )Nr   T)r   r   forbidden_path_touchedr~   r   r   r   r"   r   r   r   r@   r   r   r   r   r   r   r   r   )r   r   r   r   rM   r   r   r"   r   r   r   r   r   r   r   r   r   r   r   s                  rL   4test_forbidden_path_touched_immediate_chair_requiredr   C  s   NZ`de
IFA ZZ*,-F??D?))D)-DDDDD)-DDDDDDD6DDD6DDD?DDD)DDDDDD-DDDD-DDDDDDDD66 6 66 66666 6666666666666666666 66666666??9?449949999499999969996999?99949999999999rN   c                   t        | t        t              t        t              t        t              gt	        t
              g      \  }}|j                  t                     }|j                  }|j                  }|t        k(  }|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}}|j                  }|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                   |      t        j                   |	      dz  }
dd|
iz  }t#        t        j$                  |            d x}x}x}}	y )Nr   r   r   r   r   r   r&   r   r   r   rj   r   r   r   r   )r   r   r   r   r    r   r   rM   r   r   r&   r   r   r   r   r   r   r   r   r   r   s               rL   !test_pending_ci_continues_pollingr   T  sr   $56$56N3

 %>?IFA ZZ*,-F??A?))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AAA??/?**/a/*a////*a//////6///6///?///*///a///////rN   c                   t        | t        t              gdz  d      \  }}|j                  t	                     }|j
                  }|j                  }|t        k(  }|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}}d}	|j
                  }
|
j                   }|	|v }|st        j                  d|fd|	|f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}	x}x}
}y )Nr      )r~   rn   r   r   r   r"   r   r   r   rn   r   r   r   r   r   )r   r   r   r   rM   r   r   r"   r   r   r   r   r   r   r   r   r   r   s                  rL   ,test_max_polls_timeout_yields_chair_requiredr   f  sZ    (9:;a?IFA
 ZZ*,-F??D?))D)-DDDDD)-DDDDDDD6DDD6DDD?DDD)DDDDDD-DDDD-DDDDDDDD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00000000rN   c                t   g }t        | t        t              gt        t              g|      \  }}|j                  t                     }t        |d   j                  d            }|j                  }||k(  }|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}}|t$        k  }|st        j                  d|fd|t$        f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t$              rt        j                  t$              nddz  }
dd|
iz  }t!        t        j"                  |            d }y )Nr   r   r   r   rr   r   )z=%(py0)s == %(py4)s
{%(py4)s = %(py2)s.callback_prompt_bytes
}measuredr   r   r   r   r   )z%(py0)s <= %(py2)sr   r   r   assert %(py4)sr   )r   r   r   r    r   r   rM   rt   ru   r   r   r   r   r   r   r   r   r   r   )r}   r   r   r   r   r  r   r   r   r   @py_format3s              rL   %test_envelope_byte_count_within_limitr  t  sK   G 78$>? 	IFA ZZ*,-F71:$$W-.H3338333338333333383338333333v333v33333333333333338333333383338333333333333333333rN   c                   t        ddg      }t        | t        t              gt	        t
              g      \  }}|j                  |      }|j                  }|j                  }|t        k(  }|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}}d}
|j                  }|j$                  }|
|v }|st        j                  d|fd|
|f      t        j                  |
      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      dz  }dd|iz  }t!        t        j"                  |            dx}
x}x}}y)uC   handoff.terminal_states 에 MERGE_READY 가 빠진 경우 escalate.r8   r;   )rG   r   r   r   r   r   r   r"   r   r   r   Nsubsetr   r   r   r   r   )rM   r   r   r   r    r   r   r   r   r"   r   r   r   r   r   r   r   r   r   )r}   handoffr   r   r   r   r   r   r   r   r   r   r   r   r   r   s                   rL   8test_terminal_outside_subset_escalates_to_chair_requiredr
    sh    2BO1TUG 78$>?IFA
 ZZ F??D?))D)-DDDDD)-DDDDDDD6DDD6DDD?DDD)DDDDDD-DDDD-DDDDDDDD-v----8-----8----8------v---v--------------rN   c                	   g }t        d      }t        | t        t              gt	        t
              g|      \  }}|j                  |      }|j                  }|j                  }|t        k(  }|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}}|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}}g }||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(                  j+                  d      j-                         j/                         }|D cg c]  }t1        j2                  |      d    }}t4        |v}|st        j                  d|fdt4        |f      dt        j                         v st        j                  t4              rt        j                  t4              nddt        j                         v st        j                  |      rt        j                  |      ndd z  }d!d"|iz  }t!        t        j"                  |            d }y c c}w )#NF)rF   r   r   r   r   r   r   r&   r   r   r   r   r   r   r   r   r   )z=%(py2)s
{%(py2)s = %(py0)s.callback_prompt_bytes
} == %(py5)sz%(py0)s == %(py3)sr   r   r   r   r   rr   encodingevent)not in)z%(py0)s not in %(py2)sr   eventsr  r  r   )rM   r   r   r   r    r   r   r   r   r&   r   r   r   r   r   r   r   r   r   r   path	read_textstrip
splitlinesjsonloadsr   )r}   r   r	  r   r|   r   r   r   r   r   r   r   r   r   r   r   lineslr  r  r   s                        rL   $test_callback_disabled_does_not_firer    s   G EBG! 78$>? 	MFE ZZ F??A?))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AAA  )E) E)))) E))))))6)))6))) )))E)))))))'',1,'1,,,,'1,,,,,,6,,,6,,,',,,1,,,,,,,7b=7b77bJJ  ' 288:EEGE.34djjmG$4F4v----v---------------v---v------- 5s   $S$c                   t        | t        t              gt        t              g      \  }}|j                  t               dd       |j                  j                  d      j                         j                         }|D cg c]  }t        j                  |      d	    }}t        t        t        t         t"        g}||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  }	t1        t%        j2                  |	            d x}}y c c}w )Nr   r   r   r   r   r   rr   r  r  r   r  r  r  r   r   )r   r   r   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  r   r   r   r   s
             rL   %test_audit_event_sequence_merge_readyr    s2   ! 78$>?MFE
 JJ!#X9JUJJ  ' 288:EEGE.34djjmG$4F4 6    6                     5s   E)c                   t        | t        t              gt        t              g      \  }}|j                  t               dd       |j                  dt              }d	 |D        }t        |      }|sd
dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                   |            d x}}d |D        }t        |      }|sd
dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                   |            d x}}y )Nr   r   r   r   	sched-xyzr   r)   )r<   headc              3  D   K   | ]  }|j                  d       dk(    yw)r   r  Nget.0rs     rL   	<genexpr>z9test_audit_records_watcher_schedule_id.<locals>.<genexpr>  s     Iqquu*+{:I    z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr   c              3  D   K   | ]  }|j                  d       dk(    yw)rA   r*   Nr"  r$  s     rL   r'  z9test_audit_records_watcher_schedule_id.<locals>.<genexpr>  s     Kquu_%)<<Kr(  )r   r   r   r    r   r   rM   records_for_pr_headrH   r)  r   r   r   r   r   r   r   )r}   r   r|   rowsr   r   r   s          rL   &test_audit_records_watcher_schedule_idr-    s   ! 78$>?MFE
 JJ!#X;JW$$s$>DIDII3IIIIIIIII3III3IIIIIIIIIIIIIIKdKK3KKKKKKKKK3KKK3KKKKKKKKKKKKKKrN   c                    t        j                  t        d      5  t        | d d        d d d        y # 1 sw Y   y xY w)Nry   matchc                "    t        t              S Nr   r    r   hs    rL   <lambda>z:test_runner_rejects_missing_ci_status_fn.<locals>.<lambda>      ,<,V rN   rx   ry   rz   pytestraisesr!   r   r}   s    rL   (test_runner_rejects_missing_ci_status_fnr=    s7    	*.	A 
#"V	

 
 
   5>c                    t        j                  t        d      5  t        | d d        d d d        y # 1 sw Y   y xY w)Nrz   r/  c                "    t        t              S Nr   r   r   r4  s    rL   r6  zCtest_runner_rejects_missing_gemini_router_call_fn.<locals>.<lambda>      #3>#J rN   r8  r9  r<  s    rL   1test_runner_rejects_missing_gemini_router_call_fnrD    s8    	*2I	J 
#J"&	

 
 
r>  c                    t        j                  t        d      5  t        | d d d       d d d        y # 1 sw Y   y xY w)Nrn   r/  c                "    t        t              S rA  rB  r4  s    rL   r6  z7test_runner_rejects_invalid_max_polls.<locals>.<lambda>  rC  rN   c                "    t        t              S r2  r3  r4  s    rL   r6  z7test_runner_rejects_invalid_max_polls.<locals>.<lambda>  r7  rN   r   )rx   ry   rz   rn   r9  r<  s    rL   %test_runner_rejects_invalid_max_pollsrH    s:    	*+	> 
#J"V		

 
 
s	   7A c                    dd}t        | t        t              g      \  }}||_        t	        j
                  t        d      5  |j                  t                      d d d        y # 1 sw Y   y xY w)Nc                    t        d      S )NUNKNOWNr   )r   )_hs    rL   	bad_ci_fnz?test_runner_rejects_invalid_ci_status_return.<locals>.bad_ci_fn  s    y11rN   r   r   zinvalid statusr/  )rL  rY   )	r   r   r   _ci_status_fnr:  r;  r!   r   rM   )r}   rM  r   r   s       rL   ,test_runner_rejects_invalid_ci_status_returnrO    sd    2  78IFA %F	*2B	C )

%'() ) )s   A))A2c                    t        | t        t        d      gdg      \  }}t        j                  t
        d      5  |j                  t                      d d d        y # 1 sw Y   y xY w)Nr2   r   BOGUS_OUTCOMEr   zinvalid outcomer/  )r   r   r   r:  r;  r!   r   rM   )r}   r   r   s      rL   /test_runner_rejects_invalid_remediation_outcomerR    s]     JK&'IFA
 
*2C	D )

%'() ) )s   A!!A*)rZ   rY   )r^   list[CIStatusSnapshot])r^   zlist[RouterCallResult])r^   z	list[str])r~   rS  rk   zlist[RouterCallResult] | Nonerl   zlist[str] | Nonerm   zlist | Nonern   intro   rT  rZ   z0tuple[CiWatchHandoffRunner, CiWatchHandoffAudit])Q__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r  typingr   r:  utils.ci_watch_handoff_auditr   r   r   r   r	   r
   r   utils.ci_watch_handoff_runnerr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   utils.ci_watch_handoff_schemar"   r#   r$   r%   r&   rH   rM   r_   rc   rh   r   r   r   markparametrizer   r   r   r   r   r   r   r   r   r   r   r  r
  r  r  r-  r=  rD  rH  rO  rR   rN   rL   <module>rb     s   #            0  "J 15&*$("# # .	
 $ "    6B38C +	')BC	!#?@	n-	"$89	>>0"B&:6ED0,:"0$14$
. ..$	L



))rN   