
    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ZddlZddlZddlZ ej                   e      j%                         j&                  d   Zedz  dz  Zej,                  Z e       Zes ej2                  de       dz   d	 ej4                         v s ej6                  e      r ej8                  e      nd	 ej8                  e       ej8                  e      d
z  Z e ej>                  e            dxZZej@                  r\ej@                  d    e!e      k7  rD	 ej@                  jE                   e!e             ej@                  jI                  d e!e              e%ejL                  jO                               D ]&  Z(e(dk(  se(jS                  d      sejL                  e(= ( dZ*e
jV                  jY                  e* e!e            Z-g ZdZ.e-e.uZeZ/ere-j`                  Z1dZ2e1e2uZ3e3Z/e/sB ejh                  defde-e.f      d ej4                         v s ej6                  e-      r ej8                  e-      nd ej8                  e.      dz  Z5dde5iz  Z6ejo                  e6       er ejh                  de3fde1e2f      d ej4                         v s ej6                  e-      r ej8                  e-      nd ej8                  e1       ej8                  e2      dz  Z8dde8iz  Z9ejo                  e9        ejt                  ed      i z  Z;dde;iz  Z< e ej>                  e<            dxZ/xZxZxZ.xZ1xZ3Z2e
jV                  j{                  e-      Z>e>ejL                  e*<   e-j`                  j                  e>       e>j                  Z@e>j                  ZAe>j                  ZBe>j                  ZCe>j                  ZDe>j                  ZEe>j                  ZFe>j                  ZGe>j                  ZHe>j                  ZIe>j                  ZKe>j                  ZLedz  dz  ZM G d dej                        ZO G d dej                        ZP G d d ej                        ZQ G d! d"ej                        ZR G d# d$ej                        ZS G d% d&ej                        ZTeUd'k(  r ej                          yy# e#$ r Y }w xY w)(u  task-2660 Phase 2 callback fire delay remediation — regression 6.

회장 verbatim regression 6 (task-2660 md):
  R1: normal callback default fire delay <= 30s
  R2: scripts/finish-task.sh normal callback 호출 시 <= 30s 사용 확인
  R3: fallback/dead-man callback delay >= 600s 또는 기존 동작 유지 (Phase 3 변경 0)
  R4: delay > 60s normal callback 에 reason 없으면 lint warning (최소 lint · enforce 아님)
  R5: task-2659 timing 재발 금지 fixture (.done 14:10대 → 30s 이내 fire)
  R6: existing callback envelope byte limit (UTF-8 <= 3900) 유지

Phase 4 enforce 아님 — R4 는 verdict 변경 0, stderr warning 만 검증.
    )annotationsN   dispatchz"normal_fallback_callback_helper.pyzmissing helper: zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}_HELPER_PATH)py0py2py4z	dispatch."dispatch_helper_worktree_task_2660)is not)z%(py2)s is not %(py5)s_spec)r   py5z%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16zassert %(py19)spy19scriptszfinish-task.shc                       e Zd ZdZddZddZy)!R1NormalDefaultUnderThirtySecondsz.R1: normal callback default fire delay <= 30s.c           	         t        t              }| j                  |dt        d       | j                  |ddt        d| d       y )NzDEFAULT_AT_NORMAL=u    파싱 실패    -> s, must be <= 30s)parse_at_secondsDEFAULT_AT_NORMALassertIsNotNoneassertLessEqualselfsecss     h/home/jay/workspace/.worktrees/task-2660-dev1/tests/callback_fire_delay_remediation/test_regression_6.py)test_default_at_normal_constant_under_30szKR1NormalDefaultUnderThirtySeconds.test_default_at_normal_constant_under_30sG   sQ     12T%78I7LN#[\" !2 5T$?PQ	
    c           	     6   g d}t        j                         }t        j                         }t        j                  t        j                  }}||ct        _        t        _        	 t        |      }||ct        _        t        _        | j                  |dd| d|j                                ddl}|j                  |j                               }| j                  |d   d       |j                  d      xs g }	d}
t        |	      D ]&  \  }}|d	k(  s|d
z   t        |	      k  s|	|d
z      }
 n | j                  |
d|	        t        |
      }| j                  |d|
d       | j                  |dd| d       y# ||ct        _        t        _        w xY w)uS   argparse default 미지정 시 normal kind 의 effective --at <= 30s 인지 확인.)launch--kindnormal	--task-idztask-2660-r1--executor-keyzexecutor-r1--owner-keyc119085addb0f8b7	--chat-id
6937032012--promptzztask_id=task-2660-r1
collector_role=ANU
callback_kind=normal
owner_key=c119085addb0f8b7
canonical_root=/home/jay/workspace--canonical-root/home/jay/workspacer   helper_main returned 	; stderr=Nkindr(   argv--at   argv missing --at: --at=	 unparsedr   znormal default --at -> r   )ioStringIOsysstdoutstderrhelper_mainassertEqualgetvaluejsonloadsget	enumeratelenr   r   r   r    r5   buferr	saved_out	saved_errrcrC   decargv_outat_valueitokr!   s                 r"   .test_helper_main_normal_kind_default_under_30szPR1NormalDefaultUnderThirtySeconds.test_helper_main_normal_kind_default_under_30sO   sv   
 kkmkkm"zz3::9	!$c
CJ	:T"B%.	"CJ
Q"7t9S\\^DV WXjj(Vh/776?(b) 	FAsf}QX!6#AE?	 	X)<XJ'GH)TU8,i#@AT2)@FW'XY &/	"CJ
s   %E? ?FNreturnNone)__name__
__module____qualname____doc__r#   rS    r$   r"   r   r   D   s    8
#Zr$   r   c                       e Zd ZdZddZddZy)'R2FinishTaskShNormalCallSiteUnderThirtyu=   R2: scripts/finish-task.sh normal callback 호출 시 <= 30s.c           	     n   | j                  t        j                         dt                t        j                  d      }t	        j
                  d|      }| j                  |d       |j                  d      }t        |      }| j                  |d|d       | j                  |d	d
|d| d       y )Nzmissing utf-8encodingJ--kind normal[\s\S]*?--prompt\s+\"\$T2626_ENVELOPE\"\s+--at\s+\"([^\"]+)\"u4   finish-task.sh normal callback --at 패턴 미발견r7   r9   r:   r   z#scripts/finish-task.sh normal --at=r   u>   s, must be <= 30s (★ task-2659 14:25 idle gap 재발 금지))

assertTrueFINISH_TASK_SHexists	read_textresearchr   groupr   r   )r    textmat_tokenr!   s        r"   0test_finish_task_sh_normal_callback_at_under_30szXR2FinishTaskShNormalCallSiteUnderThirty.test_finish_task_sh_normal_callback_at_under_30sx   s    --/8N;K1LM'''9 IIY
 	Q VW771:)TU8,i#@A"1(T$ H; <	
r$   c                    t         j                  d      }t        j                  d|      }| j	                  |d       y)uM   smoking gun: --at "10m" 가 normal kind 옆에 남아있지 않은지 확인.r_   r`   z)--kind normal[\s\S]{0,400}?--at\s+\"10m\"u~   scripts/finish-task.sh 의 normal callback 옆에 '--at "10m"' 가 잔존 — 회장 verbatim 위반 (task-2659 timing 재발)N)rd   rf   rg   rh   assertIsNone)r    rj   rk   s      r"   /test_finish_task_sh_does_not_use_10m_for_normalzWR2FinishTaskShNormalCallSiteUnderThirty.test_finish_task_sh_does_not_use_10m_for_normal   sA    '''9II8
 	?	
r$   NrT   )rW   rX   rY   rZ   rm   rp   r[   r$   r"   r]   r]   u   s    G
&
r$   r]   c                       e Zd ZdZddZddZy)R3FallbackUnchangeduG   R3: fallback/dead-man callback 기존 동작 유지 (Phase 3 변경 0).c                ~    | j                  t        dd       t        t              }| j                  |dd| d       y )N10muO   fallback default 변경 금지 — 회장 verbatim Phase 3 별도 승인 강제X  zfallback default -> z+s, must be >= 600s (recovery-only dead-man))rA   DEFAULT_AT_FALLBACKr   assertGreaterEqualr   s     r"   &test_default_at_fallback_unchanged_10mz:R3FallbackUnchanged.test_default_at_fallback_unchanged_10m   sE    ]	
   34#"4&(ST	
r$   c           	     
   g d}t        j                         }t        j                         }t        j                  t        j                  }}||ct        _        t        _        	 t        |      }||ct        _        t        _        | j                  |dd| d|j                                dd l}|j                  |j                               }| j                  |d   d       |j                  d      xs g }	d }
t        |	      D ]&  \  }}|dk(  s|d	z   t        |	      k  s|	|d	z      }
 n | j                  |
d
|	        t        |
      }| j                  |dd| d       y # ||ct        _        t        _        w xY w)N)r&   r'   fallbackr)   ztask-2660-r3r*   zexecutor-r3r+   r,   r-   r.   r/   z|task_id=task-2660-r3
collector_role=ANU
callback_kind=fallback
owner_key=c119085addb0f8b7
canonical_root=/home/jay/workspacer0   r1   r   r2   r3   r4   rz   r5   r6   r7   r8   ru   zfallback default --at -> u(   s, must be >= 600s (★ 변경 0 anchor))r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   r   r   rw   rH   s                 r"   3test_helper_main_fallback_kind_default_at_unchangedzGR3FallbackUnchanged.test_helper_main_fallback_kind_default_at_unchanged   s`   
 kkmkkm"zz3::9	!$c
CJ	:T"B%.	"CJ
Q"7t9S\\^DV WXjj(Vj1776?(b) 	FAsf}QX!6#AE?	 	X)<XJ'GH)#'v-UV	
 &/	"CJ
s   %E) )FNrT   )rW   rX   rY   rZ   rx   r{   r[   r$   r"   rr   rr      s    Q	
$
r$   rr   c                  8    e Zd ZdZddZddZddZddZddZy)	R4NormalDelayReasonLintuQ   R4: normal callback delay > 60s + reason 없으면 lint warning (enforce 아님).c                    t        dd      }| j                  |d   d|       | j                  |d   d       | j                  |d   d       y )	Nr(   rt   warningzexpected warning, got codeNORMAL_DELAY_REASON_REQUIREDdelay_secondsru   )lint_normal_callback_delayrc   rA   r    outs     r"   <test_lint_warns_when_normal_delay_exceeds_60s_without_reasonzTR4NormalDelayReasonLint.test_lint_warns_when_normal_delay_exceeds_60s_without_reason   sR    (59I*@(HIV&DE_-s3r$   c                z    t        ddd      }| j                  |d   d|       | j                  |d   d       y )	Nr(   rt   zpost-cron CI sync needed)reasonr   zexpected silent, got r   REASON_PROVIDEDr   assertFalserA   r   s     r"   %test_lint_silent_when_reason_providedz=R4NormalDelayReasonLint.test_lint_silent_when_reason_provided   sG    (e$>
 	Y+@)HIV&78r$   c                    t        dd      }| j                  |d          | j                  |d   d       | j                  |d   t               y )Nr(   10sr   r   WITHIN_THRESHOLDr   )r   r   rA   r   %NORMAL_DELAY_REASON_THRESHOLD_SECONDSr   s     r"   !test_lint_silent_within_thresholdz9R4NormalDelayReasonLint.test_lint_silent_within_threshold   sK    (59Y(V&89S13XYr$   c                p    t        dd      }| j                  |d   d       | j                  |d   d       y )Nrz   rt   r   u$   fallback kind 은 lint 대상 아님r   SKIP_NON_NORMALr   r   s     r"    test_lint_skip_for_fallback_kindz8R4NormalDelayReasonLint.test_lint_skip_for_fallback_kind   s8    (U;Y)OPV&78r$   c                   g d}t        j                         }t        j                         }t        j                  t        j                  }}||ct        _        t        _        	 t        |      }||ct        _        t        _        | j                  |dd       | j                  d|j                                | j                  d|j                                y# ||ct        _        t        _        w xY w)uD   enforce 아님 — verdict/return code 변경 0, stderr warning 만.)r&   r'   r(   r)   ztask-2660-r4r*   zexecutor-r4r+   r,   r-   r.   r/   zztask_id=task-2660-r4
collector_role=ANU
callback_kind=normal
owner_key=c119085addb0f8b7
canonical_root=/home/jay/workspacer6   rt   r0   r1   r   u1   lint warning 은 enforce 아님 — return code 0z[task-2660 lint warning]u   reason 누락N)	r;   r<   r=   r>   r?   r@   rA   assertInrB   )r    r5   rI   rJ   rK   rL   rM   s          r"   :test_helper_main_emits_warning_to_stderr_but_does_not_failzRR4NormalDelayReasonLint.test_helper_main_emits_warning_to_stderr_but_does_not_fail   s    
 kkmkkm"zz3::9	!$c
CJ	:T"B%.	"CJ
Q ST0#,,.Aos||~6 &/	"CJ
s   %C C4NrT   )	rW   rX   rY   rZ   r   r   r   r   r   r[   r$   r"   r}   r}      s    [49Z9
7r$   r}   c                       e Zd ZdZddZddZy)R5Task2659TimingRegressionGuarduf   R5: task-2659 timing fixture — .done 14:10대 → normal callback 14:25 같은 지연 재발 금지.c           	         d}d}t        t              }| j                  |       ||z   }|dz   }||z
  }||z
  }| j                  |dd       | j	                  ||dz  d| d| d	       | j                  ||z
  d
d       y)u  task-2659 chronology fixture (audit packet 박제):
          14:10:51 봇 .done emit
          14:15:00 봇 finish-task.sh callback register (--at 하드코딩 기준)
          14:25:00 ANU callback cron fire (register + 10m = idle gap)

        post-remediation: normal default '10s' 적용 시 register + <=30s
        => 14:15:30 이내 fire (★ 14:25 14분 gap 재발 금지).
        ik  id  ru   iH  uD   fixture sanity: pre-remediation 은 약 14분 gap (task-2659 박제)r   zpost-remediation idle gap z$s must be < half of pre-remediation u"   s (task-2659 timing 재발 금지)r   uK   register → fire 는 30s 이내여야 함 (normal callback 진행 trigger)N)r   r   r   rw   
assertLessr   )r    done_emit_epochregister_epochr!   post_remediation_fire_epochpre_remediation_fire_epochidle_gap_postidle_gap_pres           r"   =test_task_2659_replay_normal_default_fires_within_30s_of_donez]R5Task2659TimingRegressionGuard.test_task_2659_replay_normal_default_fires_within_30s_of_done  s     30 12T"&4t&;#%3g%="3oE1OC'R	
 	<1,( 8+n,NP	
 	'.8"Y	
r$   c                   t         j                  d      }t        j                  d|      }| j	                  |       t        |j                  d            }| j	                  |       | j                  |dd| d       y)	uF   finish-task.sh 호출 시점에서 normal callback fire 까지 <= 30s.r_   r`   rb   r7   r   u   register→fire u#   s > 30s — task-2659 재발 위험N)rd   rf   rg   rh   r   r   ri   r   )r    rj   rk   r!   s       r"   .test_finish_task_sh_register_to_fire_under_30szNR5Task2659TimingRegressionGuard.test_finish_task_sh_register_to_fire_under_30s-  sv    '''9IIY
 	Q
+T"T2)9$?b'cdr$   NrT   )rW   rX   rY   rZ   r   r   r[   r$   r"   r   r     s    p#
J
er$   r   c                  (    e Zd ZdZddZddZddZy)R6EnvelopeByteLimitMaintaineduA   R6: existing callback envelope byte limit (UTF-8 <= 3900) 유지.c                2    | j                  t        dd       y )Ni<  u;   CALLBACK_PROMPT_MAX_BYTES 변경 금지 (회장 §5.5/§10))rA   CALLBACK_PROMPT_MAX_BYTESr    s    r"   1test_callback_prompt_max_bytes_constant_unchangedzOR6EnvelopeByteLimitMaintained.test_callback_prompt_max_bytes_constant_unchanged=  s    %tI	
r$   c           	         d}t        |      }| j                  |t        d| dt         d       | j                  t	        |      d       y)uP   finish-task.sh 의 T2626_ENVELOPE 가 라벨 보강 후에도 3900 bytes 이내.a3  task_id=task-9999-very-long-task-identifier-padded-for-margin
result_path=memory/events/task-9999.result.json
report_path=memory/reports/task-9999.md
collector_role=ANU
callback_kind=normal
source_attribution=FINISH_TASK_SH_BOT_COMPLETION_NORMAL
owner_key=c119085addb0f8b7
canonical_root=/home/jay/workspacez	envelope z	 bytes > u    — 회장 §5.5 위반u3   라벨 보강 후에도 envelope-only 유지 필요N)callback_prompt_utf8_bytesr   r   rc   is_envelope_only)r    envelope_templateutf8s      r"   -test_finish_task_sh_envelope_under_3900_byteszKR6EnvelopeByteLimitMaintained.test_finish_task_sh_envelope_under_3900_bytesC  s\    1 	 **;<+vY'@&AAYZ	

 	./A	
r$   c                ^    | j                  dt        d       | j                  dt               y)uE   task-2660 Phase 2 라벨링 보강 — source_attribution 키 허용.source_attributionuD   source_attribution 라벨링 키가 ENVELOPE_ALLOWED_KEYS 에 없음callback_kindN)r   ENVELOPE_ALLOWED_KEYSr   s    r"   6test_source_attribution_label_in_envelope_allowed_keyszTR6EnvelopeByteLimitMaintained.test_source_attribution_label_in_envelope_allowed_keys[  s(     "7R	

 	o'<=r$   NrT   )rW   rX   rY   rZ   r   r   r   r[   r$   r"   r   r   :  s    K

0>r$   r   __main__)VrZ   
__future__r   builtins@py_builtins_pytest.assertion.rewrite	assertionrewrite
@pytest_arimportlib.util	importlibr;   pathlibrg   r=   unittestPath__file__resolveparents	REPO_ROOTr   re   @py_assert1@py_assert3_format_assertmsglocals_should_repr_global_name	_saferepr@py_format5AssertionError_format_explanationpathstrremove
ValueErrorinsertlistmoduleskeys_mod
startswith	_MOD_NAMEutilspec_from_file_locationr   @py_assert4@py_assert0loader@py_assert10@py_assert13@py_assert12_call_reprcompare@py_format6@py_format8append@py_format15@py_format17_format_boolop@py_format18@py_format20module_from_spec_helper_moduleexec_moduleCALLBACK_KIND_FALLBACKCALLBACK_KIND_NORMALr   rv   r   r   r   r   r   r   mainr@   r   rd   TestCaser   r]   rr   r}   r   r   rW   r[   r$   r"   <module>r      s   #     	  	 
  GLL"**,44Q7	 :%(LL ? ? ? ? 0? ? ? ? ? ?| ? ? ?| ? ? ? ? ? ? ? ? ? ?88s9~-I' HHOOAs9~&!!#$ DzT__[9KK 1	..y#l:KL 5D 5uD 5U\\ 5 5\5 5 5 5uD 5 5 5 5 5u 5 5 5u 5 5 5D 5 5 5 5 5 5 5\ 5 5 5 5 5U 5 5 5U 5 5 5\ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5007'I     ('>> %:: *DD $88 "44 &<< 88 & ,FF !22 +FF !!!22  Y&)99.Z(9(9 .Zb!
h.?.? !
H2
(++ 2
j47h// 47n2eh&7&7 2ej(>H$5$5 (>V zHMMO I
  s   /!S SS