
    ̦jS/                    p   d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlmZ ddlmZmZmZ ddlZ ee      j)                         j*                  d   Z ee      ej0                  vr"ej0                  j3                  d ee             ddlmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$ dddZ%d	Z&d
Z'ejP                  dd       Z)ejP                  dd       Z*ejP                  dd       Z+	 	 	 	 	 	 	 	 	 	 ddZ,	 	 	 	 	 	 	 	 	 	 	 	 ddZ-	 	 	 	 	 	 	 	 	 	 	 	 ddZ.	 	 	 	 	 	 	 	 	 	 	 	 ddZ/	 	 	 	 	 	 	 	 	 	 	 	 ddZ0y)u  tests.regression.test_owner_trigger_success_2553 — fixture 2 + 3 + 4 (task-2553).

회장 §명시 fixture:
  2. **owner trigger success** — OWNER PAT 댓글이 Gemini fresh review 도착 시뮬레이션
  3. **duplicate nudge blocked** — 같은 PR/head 2회 trigger 시 2회차 fail-fast
  4. **update-branch stale reset** — 새 head 생기면 기존 trigger 무효, 새 trigger 가능

본 regression 은 `default_audit_writer` 를 사용해 jsonl 박제까지 검증하며, dedupe
회로가 실제 파일 기반으로 동작함을 확인한다. mock fixture 로 audit_log_path 는
tmp_path 사용.

본 모듈은 `anu_v2.owner_trigger_pat` 를 **수정하지 않고** behavioral 검증만 수행한다.
    )annotationsN)Path)AnyMappingSequence   )
ALLOWED_COMMENT_BODYDECISION_PASSDECISION_REJECT!EVIDENCE_MISSING_FOR_CURRENT_HEAD
OUTCOME_OKOUTCOME_REJECTEDOWNER_PAT_ENV_NAMEOwnerTriggerPatdefault_audit_writerwrite_decision_jsonc                4    t        j                  g | ||      S )N)args
returncodestdoutstderr)
subprocessCompletedProcess)r   r   r   s      G/home/jay/workspace/tests/regression/test_owner_trigger_success_2553.py_cpr   -   s    &&B:f]cdd    ghp_TEST_FAKE_12345z2026-05-11T12:00:00+00:00c                     g S N r    r   r   gh_callsr!   5       Ir   c                     g S r   r    r    r   r   audit_callsr$   :   r"   r   c                     g S r   r    r    r   r   decision_callsr&   ?   r"   r   c                j     t        |      d fd}d	fd}d
fd}t        |||ddd       S )u   jsonl 박제까지 수행하는 trigger 인스턴스 생성.

    dedupe 회로 검증을 위해 audit_writer 가 실제 jsonl 1줄 append 도 수행.
    c                l    j                  t        |       t        |xs i       d       t               S )N)r   env)appendlistdictr   )r   r)   r!   s     r   	gh_runnerz _make_trigger.<locals>.gh_runnerP   s'    dDODEur   c                J    j                  t        |               |        y r   )r*   r,   )recordr$   file_writers    r   audit_writerz#_make_trigger.<locals>.audit_writerT   s    4<(Fr   c                j    j                  t        |       t        |      d       t        | |       y )N)payloadpath)r*   r,   strr   )r3   r4   r&   s     r   decision_writerz&_make_trigger.<locals>.decision_writerY   s(    $w-TKLGT*r   zjeon-jonghyukztaskctl-anuc                     t         S r   )	_FIXED_TSr    r   r   <lambda>z_make_trigger.<locals>.<lambda>c   s    i r   )r-   r1   r6   ownerrepoclock)r   zSequence[str]r)   zMapping[str, str]returnsubprocess.CompletedProcess)r/   Mapping[str, Any]r=   None)r3   r?   r4   r   r=   r@   )r   r   )r!   r$   r&   audit_log_pathr-   r1   r6   r0   s   ```    @r   _make_triggerrB   D   s?     '~6K
+ !' r   c                   |j                  t        t               | dz  }| dz  }t        ||||      }|j	                  dddt
        ||      }|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(  }
|
s7t        j                  d|
fd|	|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t        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}	x}
}t%        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t$              rt        j                  t$              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }|d   }dddd d!d"t&         g}
||
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*d+|iz  }t        t        j                  |            dx}}|d%   d,   }|t        k(  }|st        j                  d|fd'|t        f      t        j                  |      d(t        j                         v st        j                  t              rt        j                  t              nd(d)z  }d*d+|iz  }t        t        j                  |            dx}}t)        j*                  |j-                  d-.            }|d/   }|t.        k(  }|st        j                  d|fd'|t.        f      t        j                  |      d0t        j                         v st        j                  t.              rt        j                  t.              nd0d)z  }d*d+|iz  }t        t        j                  |            dx}}|d1   }d}
||
k(  }|slt        j                  d|fd#||
f      t        j                  |      t        j                  |
      d$z  }dd|iz  }t        t        j                  |            dx}x}}
|d2   }d3}
||
k(  }|slt        j                  d|fd#||
f      t        j                  |      t        j                  |
      d$z  }dd|iz  }t        t        j                  |            dx}x}}
t%        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t$              rt        j                  t$              ndd4t        j                         v st        j                  |      rt        j                  |      nd4t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }|d5   }|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}}|d6   }d7}
||
u }|slt        j                  d8|fd9||
f      t        j                  |      t        j                  |
      d$z  }dd|iz  }t        t        j                  |            dx}x}}
|d:   }	t%        |	      }
d;}|
|k(  }|st        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  }t        t        j                  |            dx}	x}
x}}t(        j0                  }
 |
|      }t        |v}	|	sCt        j                  d>|	fd?t        |f      d(t        j                         v st        j                  t              rt        j                  t              nd(d@t        j                         v st        j                  t(              rt        j                  t(              nd@t        j                  |
      dAt        j                         v st        j                  |      rt        j                  |      ndAt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}	x}
}y)Bu   OWNER PAT 환경에서 `/gemini review` 댓글 → gh_runner 1회 호출 + outcome=ok.

    회장 §명시 fixture 2 본질. 호출 args 가 정확히 issue comments POST 1 endpoint 이며
    body 가 `/gemini review` strict equality 임을 검증.
    zowner_trigger_audit.jsonlzowner_trigger_decision.jsonQ   fresh001r   	pr_numberhead_shaqueue_positiongemini_evidence_staterA   decision_json_path==z/%(py2)s
{%(py2)s = %(py0)s.outcome
} == %(py4)soutr   py0py2py4assert %(py6)spy6N)zS%(py2)s
{%(py2)s = %(py0)s.decision_path
} == %(py7)s
{%(py7)s = %(py4)s(%(py5)s)
}r5   decision_path)rQ   rR   rS   py5py7zassert %(py9)spy9   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr!   rQ   py1py3rU   assert %(py8)spy8r   apiz-XPOSTz3/repos/jeon-jonghyuk/taskctl-anu/issues/81/commentsz-fzbody=z%(py1)s == %(py4)sr^   rS   r)   GH_TOKENz%(py1)s == %(py3)s_FAKE_OWNER_PATr^   r_   assert %(py5)srW   GITHUB_TOKENutf-8encodingdecisionr
   rG   
dedupe_keyz81#fresh001r$   outcometoken_presentT)is)z%(py1)s is %(py4)s
token_hash   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)s)rQ   rR   rS   rX   )not in)zO%(py0)s not in %(py7)s
{%(py7)s = %(py4)s
{%(py4)s = %(py2)s.dumps
}(%(py5)s)
}jsonr/   )setenvr   rh   rB   trigger_gemini_reviewr   rq   r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationrV   r5   r\   r	   rw   loads	read_textr
   dumps)tmp_pathr!   r$   r&   monkeypatch
audit_pathrV   triggerrO   @py_assert1@py_assert3@py_format5@py_format7@py_assert6@py_format8@py_format10@py_assert2@py_assert5@py_assert4@py_format9call@py_assert0@py_format4@py_format6decision_datar/   s                             r   'test_owner_trigger_success_fresh_reviewr   h   s>    )?;77J<<MHk>:NG

'
'?!( ( C ;;$;*$$$$;*$$$$$$3$$$3$$$;$$$$$$*$$$*$$$$$$$2M 22 22222 222222232223222222222222222222M222M222 22222222x=A=A=A33xx=A A;D< tV=*+, <    	<    	    	     	  ;z"5"o5555"o555"555555o555o5555555;~&9&/9999&/999&999999/999/9999999 JJ}666HIM$5$5555$555$5555555555555555%++%++++%+++%++++++++++&7-7&-7777&-777&777-7777777 { q q    q      3   3      {   {      q       ^F)*
****
*********
***
*******/"*d*"d****"d***"***d*******l#*3#$**$****$******3***3***#***$**********"&**4*V"44?"44444?"4444444?444?444444$444$444*444444V444V444"44444444r   c                   |j                  t        t               | dz  }| dz  }t        ||||      }|j	                  dddt
        ||      }|j                  }	|	t        k(  }
|
st        j                  d|
fd|	t        f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |	      d
t        j                         v st        j                  t              rt        j                  t              nd
dz  }dd|iz  }t        t        j                  |            dx}	}
t!        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j	                  dddt
        ||      }|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$                  j'                         }g }	d}||v }|}|sd}||v }|}|sXt        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }|	j)                  |       |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  }|	j)                  |       t        j*                  |	d      i z  }d$d%|iz  }t        t        j                  |            dx}x}	x}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}}t-        j.                  |j1                  d&'            }|d(   }|t2        k(  }|st        j                  d|fd)|t2        f      t        j                  |      d*t        j                         v st        j                  t2              rt        j                  t2              nd*d+z  }d,d-|iz  }t        t        j                  |            dx}}y).u   같은 (pr, head_sha) 2회 trigger 시 2회차 outcome=rejected, reason 에 DUPLICATE 키워드.

    회장 §명시 fixture 3 + 6 허용 조건 #5: PR/head당 1회 only.
    audit.jsonldecision.json   sameheadr   rF   rL   rN   out1r   rP   rT   rU   NrZ   r[   r\   r!   r]   r`   ra   out2r   	DUPLICATEDEDUPEin)z%(py3)s in %(py5)sreason_upper)r_   rW   z%(py7)srX   )z%(py10)s in %(py12)s)py10py12z%(py14)spy14zassert %(py17)spy17rl   rm   ro   rg   r   ri   rj   rW   )rx   r   rh   rB   ry   r   rq   r   rz   r{   r|   r}   r~   r   r   r   r\   r   reasonupperr*   _format_booloprw   r   r   r   )r   r!   r$   r&   r   r   rV   r   r   r   r   r   r   r   r   r   r   r   r   r   @py_assert9@py_assert11r   r   @py_format13@py_format15@py_format16@py_format18r   r   s                                 r   test_duplicate_nudge_blockedr      s    )?;M)J.MHk>:NG ((?!( ) D <<%<:%%%%<:%%%%%%4%%%4%%%<%%%%%%:%%%:%%%%%%%x=A=A=A33xx=A ((?!( ) D <<+<+++++<+++++++4+++4+++<++++++++++++++++++;;$$&LFKFK<'FXFX-EFFFFK<FFFKFFFFFF<FFF<FFFFFFFXFFFXFFFFFFFFFFFFFFFFFFFFFFFx=A=A=A33xx=A JJ}666HIM$7$7777$777$7777777777777777r   c                ^   |j                  t        t               | dz  }| dz  }t        ||||      }|j	                  dddt
        ||      }|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   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}}
|j	                  dddt
        ||      }|j                  }	|	t        k(  }
|
st        j                  d|
fd|	t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |	      d
t        j                         v st        j                  t              rt        j                  t              nd
dz  }dd|iz  }t        t        j                  |            dx}	}
t!        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j#                  d      j%                         j'                  d       }|D cg c](  }|j%                         st)        j*                  |      * }}|D ch c]   }|j-                  d!      t        k(  s|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}}t!        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               ndd&t        j                         v st        j                  |      rt        j                  |      nd&t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j	                  dddt
        ||      }|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}}yc c}w c c}w )-u   pr=100, head=aaa 1회 trigger → head=bbb 로 변경 → 새 trigger OK.

    회장 §명시 fixture 4 + 12 필수 구현 조건 #8: update-branch 후 기존 trigger
    stale, 새 head 에 대해서만 새 trigger 가능.
    r   r   d   aaar   rF   rL   rN   r   r   rP   rT   rU   NrZ   r[   r\   r!   r]   r`   ra   r      z4/repos/jeon-jonghyuk/taskctl-anu/issues/100/commentsrd   re   bbbr   r   rl   rm   
rq   rp   z100#aaar   )z%(py1)s in %(py3)sdedupe_keysri   rj   rW   z100#bbbout3r   )rx   r   rh   rB   ry   r   rq   r   rz   r{   r|   r}   r~   r   r   r   r\   r   stripsplitrw   r   getr   )r   r!   r$   r&   r   r   rV   r   r   r   r   r   r   r   r   r   r   r   r   audit_lineslineparsedrr   r   r   r   s                              r   test_update_branch_stale_resetr      s    )?;M)J.MHk>:NG ((?!( ) D <<%<:%%%%<:%%%%%%4%%%4%%%<%%%%%%:%%%:%%%%%%%x=A=A=A33xx=AA;vq![%[[!%[[[[[!%[[[[![[[%[[[[[[[[ ((?!( ) D <<%<:%%%%<:%%%%%%4%%%4%%%<%%%%%%:%%%:%%%%%%%x=A=A=A33xx=A &&&8>>@FFtLK+6G4$**,djjGFG,2UqaeeI6F*6T1\?UKU#9####9###9#################9####9###9################{ q q    q      3   3      {   {      q        ((?!( ) D <<+<+++++<+++++++4+++4+++<++++++++++++++++++x=A=A=A33xx=A! HUs   h%h%7h*h*c                
   |j                  t        t               | dz  }| dz  }t        ||||      }d}|j	                  d|dt
        ||      }	|	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}}|}||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dz  }dd|iz  }t        t        j                  |            d}
|j	                  d|dd||      }|j                  }
|
t"        k(  }|st        j                  d|fd|
t"        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      dt        j                         v st        j                  t"              rt        j                  t"              nddz  }dd|iz  }t        t        j                  |            dx}
}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)u|  trigger → mock evidence 도착 (commit_id == current_head) → 다음 사이클 trigger 0.

    회장 §명시 12 필수 구현 조건 #10: trigger 성공 후 Gemini evidence commit_id ==
    current_head 검증. evidence 가 도착하면 같은 head 에 대해 추가 trigger 불필요.

    본 테스트는 dedupe + evidence_state 두 경로 모두 차단됨을 확인.
    r   r   ev_head_123i,  r   rF   rL   rN   r   r   rP   rT   rU   NrZ   r[   r\   r!   r]   r`   ra   )z%(py0)s == %(py2)smock_evidence_commit_idhead)rQ   rR   zassert %(py4)srS   present_for_current_headr   r   )rx   r   rh   rB   ry   r   rq   r   rz   r{   r|   r}   r~   r   r   r   r\   r   )r   r!   r$   r&   r   r   rV   r   r   r   r   r   r   r   r   r   r   r   r   @py_format3r   s                        r   ?test_gemini_evidence_arrives_for_current_head_blocks_next_cycler     s    )?;M)J.MHk>:NGD((?!( ) D <<%<:%%%%<:%%%%%%4%%%4%%%<%%%%%%:%%%:%%%%%%%x=A=A=A33xx=A #"d****"d******"***"******d***d******* ((8!( ) D <<+<+++++<+++++++4+++4+++<++++++++++++++++++x=A=A=A33xx=Ar   )r    r   )r   intr   r5   r   r5   r=   r>   )r=   list[dict[str, Any]])
r!   r   r$   r   r&   r   rA   r   r=   r   )r   r   r!   r   r$   r   r&   r   r   zpytest.MonkeyPatchr=   r@   )1__doc__
__future__r   builtinsr|   _pytest.assertion.rewrite	assertionrewriterz   rw   r   syspathlibr   typingr   r   r   pytest__file__resolveparents_WORKSPACE_ROOTr5   r4   insertanu_v2.owner_trigger_patr	   r
   r   r   r   r   r   r   r   r   r   rh   r8   fixturer!   r$   r&   rB   r   r   r   r   r    r   r   <module>r      s   #     
  ) )  x.((*2215sxx'HHOOAs?+,  e ('	       " %  )  	 
  H6565"65 &65 )	65
 $65 
65t/8/8"/8 &/8 )	/8
 $/8 
/8f=="= &= )	=
 $= 
=B00"0 &0 )	0
 $0 
0r   