
    9j                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlmZ  ee      j                         j                  d   Z ee      e
j$                  vr"e
j$                  j'                  d ee             ddlmZmZmZ ddlmZmZmZmZmZ ddlmZ dd	l m!Z! dd
l"m#Z# dZ$dZ%de$dfdZ&ddddZ'ddZ(d Z)d Z*d Z+d Z,d Z-y)ul  task-2556 §4 — follow-up commit 후 GEMINI_STALE_ON_HEAD 자동 trigger 회귀.

회장 §명시 2026-05-12 §4:
  PR head SHA != Gemini review commit_id → GEMINI_STALE_ON_HEAD → owner trigger 필요.

검증 포인트:
  1. head_sha 와 latest review commit_id 가 다르면 STALE.
  2. scheduler 가 OWNER_TRIGGER_DISPATCHED.
  3. decision.json 의 current_head 가 새 head_sha (review commit_id 가 아님).
  4. fresh review 가 head 와 일치하면 GEMINI_FRESH_ON_HEAD → SKIP.
  5. 여러 reviews 중 마지막 (최신) 만 비교 대상.
  6. fixture (gemini_stale_on_head_2556.json) 결과 어셀션.
    )annotationsN)Path   )ACTION_FRESH_RESUMEACTION_OWNER_TRIGGER_DISPATCHEDExecutorScheduler)GeminiReviewMetaIdlePRDiagnoserIdlePRSnapshotSTATE_GEMINI_FRESH_ON_HEADSTATE_GEMINI_STALE_ON_HEAD)MergeQueueExecutor)OwnerTriggerAudit)OwnerTriggerOnly(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa l   c           	     6    t        ||ddt        |       d      S )Nztask/task-2556-dev5z2026-05-12T10:00:00+00:00Tnumberhead_shahead_ref
created_atgemini_reviewsci_required_all_success)r   tuple)reviewsheadr   s      F/home/jay/workspace/anu_v2/tests/test_executor_gemini_stale_on_head.py	_snapshotr!   /   s%    &.W~ $     ghp_token_fake_xxxxxxtokenc               F    fd}t        | |fdt        |             S )Nc                6    j                  | ||d       ddiS )N)methodpathbodyid   )append)r(   r)   r*   headers
http_callss       r    	http_postz_make_runner.<locals>.http_post;   s"    VT4HIayr"   c                      S Nr   r$   s   r    <lambda>z_make_runner.<locals>.<lambda>A   s    u r"   )workspace_rootr0   token_provideraudit)r   r   )tmp_pathr/   r%   r0   s    `` r    _make_runnerr8   :   s(     $)	 r"   c               t    t        | | dz  dz  fdt        | |      t        d d d d | 	      d
d      S )Nmemoryeventsc                      S r2   r   )	snapshotss   r    r3   z!_make_scheduler.<locals>.<lambda>J   s    ) r"   r/   c                    i S r2   r   )aes     r    r3   z!_make_scheduler.<locals>.<lambda>M   s    2 r"   c                     y)N r   )r@   s    r    r3   z!_make_scheduler.<locals>.<lambda>N       r"   c                     y)Nr   r   ps    r    r3   z!_make_scheduler.<locals>.<lambda>O   rD   r"   c                     y r2   r   rF   s    r    r3   z!_make_scheduler.<locals>.<lambda>P   rD   r"   )	gh_runner
git_runnerpytest_runneraudit_writertask_md_rootor)r4   decision_dirsnapshot_providerowner_triggermerge_executorownerrepo)r   r8   r   )r7   r=   r/   s    ` r    _make_schedulerrV   F   sL    (83+"8
C)%#%'!
  r"   c                    t        t        d      } t               j                  t	        | f      d      }|j
                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
z  }dd|iz  }t        t        j                  |            dx}}|j                  }|t         k(  }|st        j                  d|fd|t         f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t               rt        j                  t               ndd
z  }dd|iz  }t        t        j                  |            dx}}|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)u.   latest review commit_id != head_sha → STALE.2026-05-12T10:15:00+00:00	commit_idsubmitted_atr   2026-05-12T12:00:00+00:00now==z-%(py2)s
{%(py2)s = %(py0)s.state
} == %(py4)sdiagr   py0py2py4assert %(py6)spy6N)z0%(py2)s
{%(py2)s = %(py0)s.head_sha
} == %(py4)s	_HEAD_NEWz?%(py2)s
{%(py2)s = %(py0)s.latest_gemini_commit_id
} == %(py4)s	_HEAD_OLDTisz>%(py2)s
{%(py2)s = %(py0)s.requires_owner_trigger
} is %(py5)sre   rf   py5assert %(py7)spy7)r	   rl   r
   diagnoser!   stater   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   rj   latest_gemini_commit_idrequires_owner_trigger)	reviewrc   @py_assert1@py_assert3@py_format5@py_format7@py_assert4@py_format6@py_format8s	            r    1test_stale_review_classified_gemini_stale_on_headr   X   s%   	@[\F%%6)$' & D ::3:33333:333333343334333:333333333333333333==%=I%%%%=I%%%%%%4%%%4%%%=%%%%%%I%%%I%%%%%%%''4'94444'944444444444444'444444944494444444&&.$.&$....&$......4...4...&...$.......r"   c                
   g }t        t        d      }t        |fd      }t        | |g|      }|j	                  ddid	      }|j
                  d
   }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }	dd|	iz  }
t        t        j                  |
            d x}}|j                   }|t"        k(  }|st        j                  d|fd|t"        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t"              rt        j                  t"              nddz  }	dd|	iz  }
t        t        j                  |
            d x}}| dz  dz  dz  }t%        j&                  |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}}|d   }d }||u }|slt        j                  d!|fd"||f      t        j                  |      t        j                  |      d#z  }	dd|	iz  }
t        t        j                  |
            d x}x}}t-        |      }d$}||k(  }|st        j                  d|fd%||f      d&t        j                         v st        j                  t,              rt        j                  t,              nd&d't        j                         v st        j                  |      rt        j                  |      nd't        j                  |      t        j                  |      d(z  }
d)d*|
iz  }t        t        j                  |            d x}x}}|d
   d+   }d,}||k(  }|slt        j                  d|fd-||f      t        j                  |      t        j                  |      d#z  }	dd|	iz  }
t        t        j                  |
            d x}x}}y ).NrX   rY   r   )r   r   r>   OWNER_GEMINI_TRIGGER_TOKENghp_xxxxxxxxxxxxxxxxxxxxxxxxz2026-05-12T12:30:00+00:00envr_   r   r`   rb   actionr   rd   rh   ri   )z.%(py2)s
{%(py2)s = %(py0)s.action
} == %(py4)sr   r:   r;   z%task-2556.owner_trigger_decision.jsonutf-8encodingcurrent_head)z%(py1)s == %(py3)srj   )py1py3zassert %(py5)srq   gemini_evidence_freshFrm   )z%(py1)s is %(py4)s)r   rg   r,   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr/   re   r   r   ri   assert %(py8)spy8r)   z/repos/o/r/issues/108/comments)z%(py1)s == %(py4)s)r	   rl   r!   rV   run_one_cycle
pr_actionsru   r   rv   rw   rx   ry   rz   r{   r|   r}   r   r   jsonloads	read_textrj   r   )r7   r/   r   snap	schedulerresultr   r   r   r   r   decision_pathdecision@py_assert0@py_assert2@py_format4r   @py_assert5r   @py_format9s                       r    4test_scheduler_dispatches_owner_trigger_for_stale_prr   e   s0   J	@[\FfYs3D4&ZHI$$)+IJ' % F
 q!F<<5<55555<555555565556555<555555555555555555==;=;;;;;=;;;;;;;6;;;6;;;=;;;;;;;;;;;;;;;;;;x'(25\\Mzz-1171CDHN#0#y0000#y000#000000y000y0000000+,55,5555,555,5555555555z?a?a?a33zz?aa= D$DD $DDDDD $DDDD DDD$DDDDDDDDr"   c                    t        dd      } t        t        d      }t               j                  t	        | |f      d      }|j
                  }|t        k(  }|st        j                  d|fd	|t        f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            dx}}|j                  }|t        k(  }|st        j                  d|fd|t        f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            dx}}y)uD   여러 review 중 마지막 (최신) 만 비교 대상이어야 함.(ccccccccccccccccccccccccccccccccccccccccz2026-05-12T10:10:00+00:00rY   z2026-05-12T10:20:00+00:00r\   r]   r^   r`   rb   rc   r   rd   rh   ri   Nrk   rl   )r	   rl   r
   rt   r!   ru   r   rv   rw   rx   ry   rz   r{   r|   r}   r~   )oldernewerrc   r   r   r   r   s          r    &test_multiple_reviews_uses_latest_onlyr   ~   sF   x>YZEy?Z[E%%5%.)' & D ::3:33333:333333343334333:333333333333333333''4'94444'944444444444444'444444944494444444r"   c                <   t        t        d      }t        |f      }t               j	                  |d      }|j
                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
z  }dd|iz  }t        t        j                  |            d x}}|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}g }t!        | |g|      }|j#                  ddid      }|j$                  d   }|j&                  }|t(        k(  }|st        j                  d|fd|t(        f      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}}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 )!Nz2026-05-12T11:00:00+00:00rY   r\   r]   r^   r`   rb   rc   r   rd   rh   ri   Frm   ro   rp   rr   rs   r>   r   r   r   r   )z.%(py3)s
{%(py3)s = %(py1)s.action
} == %(py5)sr   )r   r   rq   r   r   r/   r   r   r   )r	   rj   r!   r
   rt   ru   r   rv   rw   rx   ry   rz   r{   r|   r}   r   rV   r   r   r   r   r   )r7   r   r   rc   r   r   r   r   r   r   r   r/   r   r   r   r   r   r   s                     r    1test_fresh_review_classified_gemini_fresh_on_headr      sm   	@[\FfY'D%%d0K%LD::3:33333:333333343334333:333333333333333333&&/%/&%////&%//////4///4///&///%///////J4&ZHI$$)+IJ' % F Q=&&=&*=====&*=======&======*====*========z?a?a?a33zz?ar"   c            	     2   t        t              j                         j                  d   dz  dz  } t	        j
                  | j                  d            }|d   }t        d |d   D              }t        |d	   |d
   |d   |d   ||d         }t               j                  ||d         }|j                  }|d   d   }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      dz  }	dd|	iz  }
t%        t        j&                  |
            d x}x}}|j(                  }|d   d
   }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      dz  }	dd|	iz  }
t%        t        j&                  |
            d x}x}}|j*                  }|d   d   }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      dz  }	dd|	iz  }
t%        t        j&                  |
            d x}x}}y )Nr,   fixtureszgemini_stale_on_head_2556.jsonr   r   snapshotc              3  B   K   | ]  }t        |d    |d           yw)rZ   r[   rY   N)r	   ).0rO   s     r    	<genexpr>z>test_stale_fixture_matches_diagnoser_output.<locals>.<genexpr>   s+       	1[>.@QRRs   r   r   r   r   r   r   r   r_   r^   expected_diagnosisru   r`   )z-%(py2)s
{%(py2)s = %(py0)s.state
} == %(py5)src   rp   rr   rs   )z0%(py2)s
{%(py2)s = %(py0)s.head_sha
} == %(py5)sr~   )z?%(py2)s
{%(py2)s = %(py0)s.latest_gemini_commit_id
} == %(py5)s)r   __file__resolveparentsr   r   r   r   r   r
   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r   r~   )fixture_pathfixture	snap_dictr   r   rc   r   r   r   r   r   s              r    +test_stale_fixture_matches_diagnoser_outputr      s   X ((+j8;[[  jj///ABG
#I +, G ":&:&\* )*C DD %%d%?D::?!56w??:?????:???????4???4???:???????????==EG$89*EE=EEEEE=EEEEEEE4EEE4EEE=EEEEEEEEEEE$$'()BC$C	D $C     	   	   	%   D      r"   )r7   r   r/   listr%   str)r7   r   r/   r   ).__doc__
__future__r   builtinsrx   _pytest.assertion.rewrite	assertionrewriterv   r   syspathlibr   r   r   r   WORKSPACE_ROOTr   r)   insertanu_v2.executor_schedulerr   r   r   anu_v2.idle_pr_diagnoserr	   r
   r   r   r   anu_v2.merge_queue_executorr   anu_v2.owner_trigger_auditr   anu_v2.owner_trigger_onlyr   rj   rl   r!   r8   rV   r   r   r   r   r   r   r"   r    <module>r      s    #    
  h'')11!4~chh&HHOOAs>*+ 
  ; 8 6 		 y  D[ 	$
/E2	5 "r"   