
    wj3                       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 ddlZ ee      j                         j                   d   Z ee      e
j&                  vr"e
j&                  j)                  d ee             ddlmZmZmZmZmZmZmZ ddlmZ ddlm Z  d	Z!d
Z"de!ddddddddd
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d#dZ#ddd	 	 	 	 	 d$dZ$d Z%d Z&d Z'd Z(d Z)d Z*d Z+d Z,d Z-d Z.d  Z/d! Z0d" Z1y)%u  anu_v2.tests.test_owner_trigger_only_2554 — OWNER_TRIGGER_ONLY_CAPABILITY core 회귀 (task-2554).

회장 §명시 14장 §10 1:1 박제 (2026-05-11 KST). 본 파일은 system spec §10의 14건 중
1~9, 13~14 (10건)을 다룬다. 나머지는 다음 파일들로 분리:
  - test_owner_trigger_decision_schema_2554.py
  - test_owner_trigger_dedupe_2554.py
  - test_owner_trigger_security_boundaries_2554.py
  - test_owner_trigger_merge_path_separation_2554.py

본 회귀는 anu_v2/* 모듈만 import 한다 (one-way isolation).
    )annotationsN)Path   )ALLOWED_ACTIONCommentBodyViolationForbiddenEndpointErrorOwnerTriggerOnlyTokenBoundaryViolationTriggerResultassert_endpoint_allowed)OwnerTriggerAudit)DecisionInvalidError(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg   TF"POST_GEMINI_REVIEW_TRIGGER_COMMENT/gemini review	task-2554)
prhead
queue_headcurrent_head_confirmedgemini_evidence_freshnudge_count_for_pr_headallowed_actioncomment_bodyallowedtask_idc       
        x    d|
|||||||||	d}| dz  }|j                  t        j                  |      d       |S )N anu_v2.owner_trigger_decision.v1schemar   r   current_headr   r   r   r   r   r   r   zdecision.jsonutf-8encoding)
write_textjsondumps)tmp_pathr   r   r   r   r   r   r   r   r   r   decisionpaths                @/home/jay/workspace/anu_v2/tests/test_owner_trigger_only_2554.py_write_decisionr.   *   sV     5 "8!6#:($H o%DOODJJx(7O;K    z$dummy-token-VALUE-MUST-NOT-LEAK-1234)poststokenc               f    g dfd}dfd}t        |       }t        | |||      }||fS )u   OwnerTriggerOnly 인스턴스 + 호출 캡처 stubs.

    token raw value 인자가 절대 audit/로그에 노출되지 않음을 검증하기 위해 sentinel
    포함 (``MUST-NOT-LEAK``).
    c                :    j                  | |||d       dddS )N)methodr,   bodyheaders   i )statusid)append)r4   r,   r5   r6   r0   s       r-   	http_postz _build_module.<locals>.http_postX   s#    dwWXW--r/   c                      S )N r1   s   r-   token_providerz%_build_module.<locals>.token_provider\   s    r/   )workspace_root)r@   r;   r?   audit)
r4   strr,   rB   r5   dictr6   rC   returnrC   )rD   rB   )r   r	   )r*   r0   r1   r;   r?   rA   mods    ``    r-   _build_modulerF   J   sJ     }. X6E
%	C ur/   c                
   t        |       }t        |       \  }}}|j                  |ddt              }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	d	d
|	iz  }
t        t        j                  |
            d x}x}}|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            d x}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	d	d
|	iz  }
t        t        j                  |
            d x}x}}|j                   }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	d	d
|	iz  }
t        t        j                  |
            d x}x}}t#        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t"              rt        j                  t"              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|d   }|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|d    }|j$                  }d!} ||      }|std"t        j                  |      t        j                  |      t        j                  |      t        j                  |      d#z  }
t        t        j                  |
            d x}x}x}}|d$   }d$di}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|j&                  }|j(                  } |       }|sd%d&t        j                         v st        j                  |      rt        j                  |      nd&t        j                  |      t        j                  |      t        j                  |      d'z  }t        t        j                  |            d x}x}}|j&                  j+                  d()      j-                         D cg c]  }|st/        j0                  |       }}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,   }|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/d0|iz  }	t        t        j                  |	            d x}}|d   d   }d1}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|d   d,   }|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/d0|iz  }	t        t        j                  |	            d x}}|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|d   d2   }d3}||u }|slt        j                  d4|fd5||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}g }d6}|d   }||v }|}|r|d   d6   }t#        |      }d7}||k(  }|}|s[t        j                  d8|fd9||f      t        j                  |      t        j                  |      d:z  }d;d|iz  }|j3                  |       |rt        j                  dfd<f      dt        j                         v st        j                  t"              rt        j                  t"              ndt        j                        t        j                  |      t        j                  |      d=z  }d>d?|iz  }|j3                  |       t        j4                  |d      i z  }d@dA|iz  }t        t        j                  |            d x}x}x}x}x}x}x}x}}y c c}w )BNJeon-Jonghyukdev_workspacedecision_pathownerrepocurrent_head_actualPOSTED==z.%(py2)s
{%(py2)s = %(py0)s.status
} == %(py5)sresultpy0py2py5assert %(py7)spy7)z.%(py2)s
{%(py2)s = %(py0)s.action
} == %(py4)sr   )rU   rV   py4zassert %(py6)spy6r   )z4%(py2)s
{%(py2)s = %(py0)s.comment_body
} == %(py5)sz6/repos/Jeon-Jonghyuk/dev_workspace/issues/103/comments)z0%(py2)s
{%(py2)s = %(py0)s.endpoint
} == %(py5)s   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr0   rU   py1py3r[   assert %(py8)spy8r   r4   POST)z%(py1)s == %(py4)s)r`   rZ   r,   z/issues/103/commentszJassert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.endswith
}(%(py5)s)
})r`   ra   rW   rY   r5   z[assert %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.path
}.exists
}()
}rA   )rU   rV   rZ   r[   r$   r%   r   rowsaction)z%(py1)s == %(py3)s)r`   ra   assert %(py5)srW   PENDINGtoken_value_loggedF)is)z%(py1)s is %(py4)stoken_hash_prefix   )in)z%(py3)s in %(py6)s)ra   r[   z%(py8)s)z5%(py14)s
{%(py14)s = %(py10)s(%(py12)s)
} == %(py17)s)py10py12py14py17z%(py19)spy19zassert %(py22)spy22)r.   rF   trigger_gemini_review_HEAD_Ar8   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationrf   r   r   endpointr^   endswithr,   exists	read_text
splitlinesr(   loadsr:   _format_boolop)r*   rK   rE   r0   rA   rS   @py_assert1@py_assert4@py_assert3@py_format6@py_format8@py_format5@py_format7@py_assert2@py_assert5@py_format9call@py_assert0@py_assert6linere   @py_format4@py_assert11@py_assert13@py_assert16@py_assert15@py_format18@py_format20@py_format21@py_format23s                                 r-   6test_allowed_decision_posts_gemini_review_comment_onlyr   k   s   #H-M%h/C55##	 6 F ==$H$=H$$$$=H$$$$$$6$$$6$$$=$$$H$$$$$$$==*=N****=N******6***6***=******N***N*******2"22"22222"222222262226222222"22222222??VVV?VVVVV?VVVVVVV6VVV6VVV?VVVVVVVVVVVu::?:33uu:8D>#V#>V####>V###>###V#######<8<  8!78 !788888<888 888!78888888888<5F$455<55555<5555<55555555555:::55:).)=)=w)=)O)Z)Z)\e`dDJJteDet99>933tt978........................78)	)	))))	))))))	)))))))78........................78(((((((((((((((((((7'(1E1(E1111(E111(111E1111111TT$q'T')T$q':M2NTc2N.OTSTT.OST.TTTTT'TTTTTT'TTTTTTT.OSTTTTTTTcTTTcTTT2NTTT.OTTTSTTTTTTTTTTTTTTTT fs   1t 9t c                   t        | d      }t        |       \  }}}t        j                  t              5 }|j                  |ddt               d d d        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}	}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}}y # 1 sw Y   xY w)Nz/gemini approve)r   rH   rI   rJ   E_COMMENT_BODYrP   zG%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.code
} == %(py7)sexcrU   rV   rZ   rY   assert %(py9)spy9z%(py0)s == %(py3)sr0   rU   ra   rg   rW   r.   rF   pytestraisesr   rt   ru   valuecoderv   rw   rx   ry   rz   r{   r|   r}   r*   rK   rE   r0   _r   r   r   r   r   r   @py_format10r   r   r   s                  r-   'test_comment_body_mismatch_fails_closedr      sA   #H;LMM!(+MC	+	, 
!!'!  '	 	" 	

 99-9>>--->----->-------3---3---9--->-----------5B;5B55B
 
   G))G3c                   t        |       }t        |       \  }}}t        j                  t              5  |j                  |ddt        d       d d d        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}}y # 1 sw Y   xY w)NrH   rI   zhello world)rK   rL   rM   rN   r   rP   r   r0   r   rg   rW   )r.   rF   r   r   r   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   	r*   rK   rE   r0   r   r   r   r   r   s	            r-   5test_caller_provided_comment_body_must_match_constantr      s    #H-M!(+MC	+	, 
!!'!  '& 	" 	

 5B;5B55B
 
s   C>>Dc                   t        | d      }t        |       \  }}}t        j                  t              5 }|j                  |ddt               d d d        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}	}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}}y # 1 sw Y   xY w)NF)r   rH   rI   rJ   E_QUEUE_HEADrP   r   r   r   r   r   r   r0   r   rg   rW   r   r   s                  r-    test_non_queue_head_fails_closedr      s<   #H?M!(+MC	+	, 
!!'!  '	 	" 	

 99+9>>+^+>^++++>^++++++3+++3+++9+++>+++^+++++++5B;5B55B
 
r   c                   t        | t              }t        |       \  }}}t        j                  t
              5 }|j                  |ddt               d d d        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}	}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}}y # 1 sw Y   xY w)N)r   rH   rI   rJ   E_HEAD_MISMATCHrP   r   r   r   r   r   r   r0   r   rg   rW   )r.   ru   rF   r   r   r   rt   _HEAD_Br   r   rv   rw   rx   ry   rz   r{   r|   r}   r   s                  r-   'test_current_head_mismatch_fails_closedr      s@   #H7;M!(+MC	+	, 
!!'!  '	 	" 	

 99.9>>...>.....>.......3...3...9...>...........5B;5B55B
 
s   G--G7c                   t        | d      }t        |       \  }}}t        j                  t              5 }|j                  |ddt               d d d        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}	}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}}y # 1 sw Y   xY w)NT)r   rH   rI   rJ   E_GEMINI_FRESHrP   r   r   r   r   r   r   r0   r   rg   rW   r   r   s                  r-   'test_gemini_evidence_fresh_fails_closedr      s@   #HDIM!(+MC	+	, 
!!'!  '	 	" 	

 99-9>>--->----->-------3---3---9--->-----------5B;5B55B
 
r   c                   t        | d      }t        |       \  }}}t        j                  t              5 }|j                  |ddt               d d d        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}	}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}}y # 1 sw Y   xY w)NF)r   rH   rI   rJ   E_HEAD_NOT_CONFIRMEDrP   r   r   r   r   r   r   r0   r   rg   rW   r   r   s                  r-   .test_update_branch_before_trigger_fails_closedr      s@   #HUKM!(+MC	+	, 
!!'!  '	 	" 	

 9939>>333>33333>3333333333333339333>333333333335B;5B55B
 
r   c                   t        | dd      }t        |       \  }}}t        j                  t              5 }|j                  |ddt               d d d        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}	}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}}y # 1 sw Y   xY w)Nr\   T)r   r   rH   rI   rJ   E_NUDGE_COUNTrP   r   r   r   r   r   r   r0   r   rg   rW   r   r   s                  r-   9test_attempting_to_trigger_non_queue_head_pr_fails_closedr      s?   #HaTXYM!(+MC	+	, 
!!'!  '	 	" 	

 99,9>>,_,>_,,,,>_,,,,,,3,,,3,,,9,,,>,,,_,,,,,,,5B;5B55B
 
s   G**G4c                     g d} | D ]3  \  }}t        j                  t              5  t        ||       d d d        5 y # 1 sw Y   @xY w)N)
)rd   z/repos/o/r/pulls/103/merge)rd   z/repos/o/r/pulls/103/reviews)rd   z/repos/o/r/git/refs/heads/x)PUTz/repos/o/r/contents/x.py)PATCHz/repos/o/r/issues/103)rd   z/repos/o/r/issues/103/labels)DELETEz/repos/o/r/branches/main)rd   z/repos/o/r/actions/runs/1/rerun)rd   z!/repos/o/r/check-runs/1/rerequest)r   z/repos/o/r/pulls/103)r   r   r   r   )	forbiddenr4   r,   s      r-   /test_forbidden_endpoints_raise_permission_errorr     sO    I " 2]]12 	2#FD1	2 	22	2 	2s	   >A	c                     t        dd       y )Nrd   z/repos/o/r/issues/103/comments)r   r=   r/   r-   6test_allowed_endpoint_only_post_issues_comments_passesr     s    F$DEr/   c                "   t        |       \  }}}t        j                  t              5  |j	                  d       d d d        t        j                  t              5  |j                  d       d d d        t        j                  t              5  |j                  d       d d d        t        j                  t              5  |j                  d       d d d        y # 1 sw Y   xY w# 1 sw Y   ~xY w# 1 sw Y   VxY w# 1 sw Y   y xY w)Nr   )r   )rF   r   r   PermissionErrormergeapproveclosereopen)r*   rE   r   s      r-   2test_module_class_does_not_expose_merge_or_approver     s    h'ICA		' 		S			' s		' 		S			' 

c
     s/   C!C-C9D!C*-C69DDc                   | dz  }|j                  t        j                  dddt        dddddd	dd
      d       t	        |       \  }}}|j                  |ddt              }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}| dz  }|j                  t        j                  dddt        dddddd	dd
      d       |j                  |ddt              }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}t!        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y ) Nzdecision_a.jsonr    r   r   TFr   r   r   r!   r$   r%   orrJ   rO   rP   rR   r1rT   rX   rY   zdecision_b.jsonr2r   r]   r^   r0   r_   rb   rc   )r'   r(   r)   ru   rF   rt   r8   rv   rw   rx   ry   rz   r{   r|   r}   r   r^   )r*   decision_path_arE   r0   r   r   r   r   r   r   r   decision_path_br   r   r   r   r   s                    r-   5test_head_change_allows_new_trigger_after_stale_resetr   ,  sm   !22O

<& '"*.).+,"F 0	
 !  $ "(+MC		"	"%#	 
# 
B 99  9    9      2   2   9           !22O

<& '"*.).+,"F 0	
 !  $ 
	"	"%#	 
# 
B 99  9    9      2   2   9          u::?:33uu:r/   c                   t        |       }t        | d      \  }}}t        j                  t              5  |j                  |ddt               d d d        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}}y # 1 sw Y   xY w)N r>   r   r   rJ   rP   r   r0   r   rg   rW   )r.   rF   r   r   r
   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r   s	            r-   0test_token_provider_returning_empty_fails_closedr   j  s    #H-M!("5MC	-	. 
!!' '	 	" 	

 5B;5B55B
 
s   C??D)r*   r   r   intr   rB   r   boolr   r   r   r   r   r   r   rB   r   rB   r   r   r   rB   rD   r   )r*   r   r0   zlist[dict] | Noner1   rB   )2__doc__
__future__r   builtinsrx   _pytest.assertion.rewrite	assertionrewriterv   r(   syspathlibr   r   __file__resolveparentsWORKSPACE_ROOTrB   r,   insertanu_v2.owner_trigger_onlyr   r   r   r	   r
   r   r   anu_v2.owner_trigger_auditr   anu_v2.owner_trigger_decisionr   ru   r   r.   rF   r   r   r   r   r   r   r   r   r   r   r   r   r   r=   r/   r-   <module>r      s  
 #    
  h'')11!4~chh&HHOOAs>*+   9 > 
 #'"'#$>( 	 	
  !   !     
F  $7	  	BUF"""$$$2$F

9|
r/   