
    j                    h   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 ej                   j#                  d e ee      j)                         j*                  d                ddlZddlmZmZmZmZmZmZmZmZm Z m!Z!m"Z" d Z#d	 Z$d
 Z%d Z&d Z'd Z(d Z)d Z*d Z+d Z,d Z-d Z.y)u   task-2673 RS-2670-C — callback registrar invariants.

수정 목표 3: terminal state 도달 시 ANU normal callback 발사 보장.
spec §11: envelope UTF-8 ≤ 3900 bytes / absolute timestamp / ANU key 단일출처.
    )annotationsN)PathSimpleNamespace   )ANU_CHAT_ID_DEFAULTANU_KEY_DEFAULTCALLBACK_DELAY_SECCOKACDIR_BINENVELOPE_MAX_BYTESHOLD_FOR_CHAIRLOOP_BOUNDARYMERGE_READYTERMINAL_STATESbuild_callback_enveloperegister_terminal_callbackc                     t        ddd      S )Nr   ok 
returncodestdoutstderrr   )_args_kwargss     Y/home/jay/workspace/tests/pr_watcher_terminal_state_classifier/test_callback_registrar.py_okr   "   s    aR@@    c                     i fd} | fS )Nc                4    | d<   |d<   t        ddd      S )Ncmdkwargsr   r   r   r   r   )r!   r"   captureds     r   runnerz_capture.<locals>.runner)   s%    #!DDDr    )r$   r#   s    @r   _capturer&   &   s    HE
 8r   c                 \   t         D ]  } t        dd| ddddddd	d
id      }|j                  }d} ||      }t        |      }|t        k  }|st        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  |       dz   d|iz  }t        t        j                  |            dx}x}x}x}}| |v }	|	st        j                  d|	fd| |f      dt        j                         v st        j                  |       rt        j                  |       nddt        j                         v st        j                  |      rt        j                  |      nddz  }
dd|
iz  }t        t        j                  |            d}	 y)u4   envelope UTF-8 ≤ ENVELOPE_MAX_BYTES (모든 enum).2667   z<test reason test reason test reason test reason test reason    8  TBLOCKED   submittedAtz2026-05-25T13:39:36Z)head_match_expectedmergeStateStatusunresolved_thread_countlatest_gemini_review)task_id	pr_numberterminal_statereasonpolls_completedelapsed_seclast_snapshotutf-8<=zk%(py9)s
{%(py9)s = %(py0)s(%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.encode
}(%(py5)s)
})
} <= %(py11)slenenvr   py0py1py3py5py7py9py11z
>assert %(py13)spy13Nin)z%(py0)s in %(py2)sstate)rA   py2zassert %(py4)spy4)r   r   encoder>   r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanation)rK   r?   @py_assert2@py_assert4@py_assert6@py_assert8@py_assert10@py_format12@py_format14@py_assert1@py_format3@py_format5s               r   .test_envelope_within_byte_limit_for_all_statesrb   1   s     % %'+$-+,)68N(O	
 ::DgD:g&Ds&'D'+==DDD'+=DDDDDDsDDDsDDDDDD3DDD3DDD:DDDgDDD&DDD'DDDDDD+=DDD+=DDDDuDDDDDDD|uuu!r   c            
        t        d      D  ci c]  } d|  d
 }} t        ddt        ddd|      }|j                  }d	} ||      }t	        |      }|t
        k  }|skt        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                  |      rt        j                  |      ndt        j                  |      t        j                  |      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}x}x}}yc c} w )u9   extras 가 거대해도 잘려서 ≤ ENVELOPE_MAX_BYTES.(   kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxr(   r)   x   )r3   r4   r5   r6   r7   r8   extrasr:   r;   r=   r>   r?   r   r@   zassert %(py13)srH   N)ranger   r   rN   r>   r   rO   rP   rQ   rR   rS   rT   rV   rW   )
iri   r?   rX   rY   rZ   r[   r\   r]   r^   s
             r   ,test_envelope_truncates_when_extras_oversizerl   F   s+   */)4Q!gy 4F4
!%C zz9'9z'"93"#9#'99999#'999999939993999999s999s999z999'999"999#999999'9999'999999999 5s   Gc            	         t        j                  t              5  t        dddddd       d d d        y # 1 sw Y   y xY w)Nr(   r)   MERGE_GREEN_LIGHTrg   rh   r3   r4   r5   r6   r7   r8   )pytestraises
ValueErrorr   r%   r   r   #test_envelope_rejects_invalid_staters   U   s=    	z	" 
.	

 
 
s   5>c                 b   t               \  } }t        ddt        ddd      }t        |t        t
        |       }|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                  }|j                   }	d}
 |	|
      }t#        |      }||k(  }|sst        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                  |	      t        j                  |
      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}	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 }||k(  }|slt        j                  d|fd!||f      t        j                  |      t        j                  |      d"z  }d#d$|iz  }t        t        j                  |            dx}x}}|d%   }||k(  }|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+}||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}}|j'                  d*      }||dz      }|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}}|j'                  d)      }||dz      }t)        t
              }||k(  }|st        j                  d|fd-||f      t        j                  |      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                  |      d0z  }d1d2|iz  }t        t        j                  |            dx}x}}y)3u.   RS-2670-C 본체 — subprocess 인자 검증.r(   r)   poll_12_silent_fall_throughr*   r+   ro   envelopeanu_keychat_idr$   Tisz-%(py2)s
{%(py2)s = %(py0)s.fired
} is %(py5)sresultrA   rL   rD   assert %(py7)srE   Nr:   ==)z%(py2)s
{%(py2)s = %(py0)s.envelope_bytes
} == %(py13)s
{%(py13)s = %(py4)s(%(py11)s
{%(py11)s = %(py7)s
{%(py7)s = %(py5)s.encode
}(%(py9)s)
})
}r>   r?   )rA   rL   rM   rD   rE   rF   rG   rH   zassert %(py15)spy15r!   r   z%(py1)s == %(py3)sr   rB   rC   assert %(py5)srD   rh   z--cron)z%(py1)s == %(py4)s)rB   rM   assert %(py6)spy6r   --atrI   )z%(py1)s in %(py3)sz--chat--keyz--oncer	   )z0%(py1)s == %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}strr   )rB   rC   rM   r   zassert %(py8)spy8)r&   r   r   r   r	   r   firedrO   rP   rQ   rR   rS   rT   rV   rW   envelope_bytesrN   r>   r   indexr   )r$   r#   r?   r}   r_   rY   @py_assert3@py_format6@py_format8rZ   r[   r\   @py_assert12r^   @py_format16r!   @py_assert0rX   @py_format4ra   @py_format7key_idxchat_idx@py_assert5@py_format9s                            r   /test_register_calls_cokacdir_with_required_argsr   a   s9   zFH
!%,C (#	F <<4<4<466<4  <

<7<
7(;<C(;$<< $<<<<< $<<<<<<<6<<<6<<< <<<<<<C<<<C<<<<<<<<<<<<
<<<7<<<(;<<<$<<<<<<<<<
5/Cq6!6\!!!!6\!!!6!!!!!!\!!!\!!!!!!!q6X6X6X6Xq66S=6S6SS6S=6S6SS8s?8s8ss7c>7c7cc8s?8s8ss ii Gw{........................yy"Hx!|8$7 88 88888 8888888888888888888$7888$7888 88888888r   c                    t               \  } }t        ddt        ddd      }t        |t        t
        t        |       }|d   j                  d	      }|d   |d
z      }t        j                  }d} |||      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        t        j                   |	            dx}x}}|j"                  }d} ||      }
|
 }|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}x}
}|j"                  }d} ||      }
|
 }|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}x}
}|j$                  }||k(  }|st        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                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                   |            dx}}y)u=   task-2661 Phase 2b — absolute "YYYY-MM-DD HH:MM:SS" 강제.r(   r)   zelapsed 3600s     ro   )rw   rx   ry   delay_secondsr$   r!   r   rh   z%^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$zPassert %(py7)s
{%(py7)s = %(py2)s
{%(py2)s = %(py0)s.match
}(%(py4)s, %(py5)s)
}refire_at)rA   rL   rM   rD   rE   NszNassert not %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.endswith
}(%(py4)s)
})rA   rL   rM   r   mr   )z/%(py2)s
{%(py2)s = %(py0)s.fire_at
} == %(py4)sr}   )rA   rL   rM   r   r   )r&   r   r   r   r	   r   r
   r   r   matchrQ   rR   rO   rS   rT   rV   rW   endswithr   rP   )r$   r#   r?   r}   at_idxr   r_   r   rZ   r   r   @py_assert7ra   r   s                 r   2test_register_uses_absolute_timestamp_not_relativer      sk   zFH
!$C (#(F e_""6*Fuofqj)G88F<F8<gFFFFFFFF2FFF2FFF8FFF<FFFFFFgFFFgFFFFFFFFFF$$$$$$$$$$$$$w$$$w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w$$$w$$$$$$$$$$$$$$$$>>$>W$$$$>W$$$$$$6$$$6$$$>$$$$$$W$$$W$$$$$$$r   c                    t               \  } }t        dt        t        |       }|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}}d}||v}	|	st        j                  d|	fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }
dd|
iz  }t        t        j                  |            d x}}	y )Nr   rv   Frz   r|   r}   r~   r   rE   empty_enveloper   z6%(py2)s
{%(py2)s = %(py0)s.skipped_reason
} == %(py5)sr!   not inz%(py1)s not in %(py3)sr#   r   r   rD   )r&   r   r	   r   r   rO   rP   rQ   rR   rS   rT   rV   rW   skipped_reason)r$   r#   r}   r_   rY   r   r   r   r   rX   r   s              r   'test_register_skips_when_envelope_emptyr      sb   zFH'#	F << 5 <5    <5      6   6   <   5         4$44 $44444 $444444464446444 444$44444444 5    5   5                r   c                    t               \  } }dt        dz   z  }t        |t        t        |       }|j
                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}x}}d}	|j                  }|	|v }
|
st        j                  d|
fd|	|f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            d x}	x}
}d}	|	|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 )Nrg   d   rv   Frz   r|   r}   r~   r   rE   envelope_oversizerI   z6%(py1)s in %(py5)s
{%(py5)s = %(py3)s.skipped_reason
}rB   rC   rD   r!   r   r   r#   r   r   rD   )r&   r   r   r	   r   r   rO   rP   rQ   rR   rS   rT   rV   rW   r   )r$   r#   oversizer}   r_   rY   r   r   r   r   rX   r   s               r   *test_register_skips_when_envelope_oversizer      sq   zFH(3./H'#	F << 5 <5    <5      6   6   <   5       7&"7"77"77777"7777777777&777&777"77777777 5    5   5                r   c                 ~   d } t        ddt        ddd      }t        |t        t        |       }|j
                  }d	}||u }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}d}|j                  }||v }	|	st        j                  d|	fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}	}y)u?   RS-2670-C-fail — timeout/exception 시 watcher 정상 종료.c                 0    t        j                  dd      )Ncokacdirr   )r!   timeout)
subprocessTimeoutExpired_a_ks     r   
bad_runnerz@test_register_silent_on_subprocess_exception.<locals>.bad_runner   s    ''JCCr   r(   r)   r      i  ro   rv   Frz   r|   r}   r~   r   rE   Nr   rI   r   r   )r   r   r   r	   r   r   rO   rP   rQ   rR   rS   rT   rV   rW   r   )
r   r?   r}   r_   rY   r   r   r   r   rX   s
             r   ,test_register_silent_on_subprocess_exceptionr      s"   D ""C (#	F << 5 <5    <5      6   6   <   5       4v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                  dd       t               \  }}t        ddt        ddd      }t	        |d	t
        |
      }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d	x}x}}|d   j                  d      }
|d   |
dz      }|t         k(  }|st        j                  d|fd|t         f      t        j                  |      dt        j                         v st        j                  t               rt        j                  t               nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u   ANU key fail-closed default — explicit/env 모두 없으면 ANU_KEY_DEFAULT
    로 fallback (spec §11 "ANU key 단일출처 유지" 정합).
    ANU_KEYF)raisingr(   r)   rg   rh   ro   Nrv   Trz   r|   r}   r~   r   rE   r!   r   r   r   r	   r   r   rD   )delenvr&   r   r   r   r   r   rO   rP   rQ   rR   rS   rT   rV   rW   r   r	   )monkeypatchr$   r#   r?   r}   r_   rY   r   r   r   r   r   rX   r   s                 r   <test_register_uses_default_key_when_env_and_explicit_missingr      sC    y%0zFH
!%C (#	F <<4<4<466<4uo##G,GE?7Q;':'?::::'?:::'::::::?:::?:::::::r   c                    d } t        ddt        ddd      }t        |t        t        |       }|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}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nc                     t        ddd      S )Nrh   r   errr   r   r   s     r   r$   z;test_register_non_zero_returncode_not_fired.<locals>.runner   s    !BuEEr   r(   r)   rg   r   r   ro   rv   Frz   r|   r}   r~   r   rE   non_zero_exitr   r   rh   )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)s)r   r   r   r	   r   r   rO   rP   rQ   rR   rS   rT   rV   rW   r   r   )r$   r?   r}   r_   rY   r   r   r   s           r   +test_register_non_zero_returncode_not_firedr      s   F "$C (#	F << 5 <5    <5      6   6   <   5         3O3 O3333 O33333363336333 333O3333333!!!!!!!!!!!!6!!!6!!!!!!!!!!!!!r   )/__doc__
__future__r   builtinsrQ   _pytest.assertion.rewrite	assertionrewriterO   r   r   syspathlibr   typesr   pathinsertr   __file__resolveparentsrp   *utils.pr_watcher_terminal_state_classifierr   r	   r
   r   r   r   r   r   r   r   r   r   r&   rb   rl   rs   r   r   r   r   r   r   r   r%   r   r   <module>r      s   
 #   	  
  ! 3tH~--/77:; <    A*:	
!9H%:
!!50;2"r   