
    Aej                    v   d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	m
Z
mZ ddlmZmZmZmZmZmZ dZ ej(                  d      Zd	Zd
ZdZdZ eeeeeh      ZdQdZ	 dRed	 	 	 	 	 dSdZddlmZ m!Z" ddl#m$Z%m&Z' ddl(m)Z*m+Z, dZ-dZ.dZ/ ee.e/h      Z0e G d d             Z1ddddddd e2e      dddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dTdZ3e G d d              Z4 e2e      d!	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dUd"Z5d#Z6d$Z7d%Z8d&Z9d'Z:d(Z;d)Z<d*Z=d+Z>d,Z?d-Z@d.ZAd/ZBd0ZCd1ZD eh d2      ZEeBfdd3	 	 	 dVd4ZFdWd5ZGd6ZHdXd7ZIdd3dWd8ZJdeDdd9	 	 	 	 	 	 	 	 	 dYd:ZKdZd;ZLd[d<ZMdd=d\d>ZNe G d? d@             ZO	 	 	 	 	 	 	 	 d]dAZPe G dB dC             ZQ e2e      d!	 	 	 	 	 	 	 	 	 	 	 	 	 d^dDZRddddddd e2e      ddE		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d_dFZSdGZTd+ZUdHZVdIZWe G dJ dK             ZXdddddddL	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d`dMZYg dNZZdRdadOZ[e\dPk(  r e] e[             y)bu  dispatch.normal_fallback_callback_helper — ANU-owned normal/fallback
callback registration helper + post-registration owner cross-check.

task-2553+49 (§8 / §10 / 9-R.1 — 코드/파일 자동화).

The actual normal/fallback callback cron is registered via the external
``cokacdir --cron`` tool (a cron-direct path that ANU cannot file-patch,
9-R.1). So the owner=ANU-key pin is enforced at the **ANU control layer**,
which IS code-patchable:

  1. ``build_anu_owned_callback_request`` — the dispatch prompt generator /
     4-tuple registration step builds the callback registration request HERE.
     It is **fail-closed**: an owner key equal to the executor self key, or
     not a configured independent ANU key, or a non-ANU collector role, makes
     the request INVALID and NO command argv is produced (회장 §2/§8/§10).
  2. ``verify_post_registration_owner`` — after ``cokacdir --cron`` returns,
     the ANU control layer re-reads the schedule_history / registry owner
     binding and cross-checks key/chat/role. An owner that resolved to the
     executor key (or any non-ANU key) at registration time -> FAIL (회장 §8
     "등록 후 schedule_history/registry 에서 chat_id·key·role binding 교차
     검증").

Standalone, zero-mutation, Layer A / NO-CRON (9-R.1): this module performs
ZERO cron register/remove, ZERO dispatch, ZERO ``subprocess`` / ``cokacdir``
exec. It only *builds a request descriptor* and *validates* an owner binding.
The authorized session executes the (ANU-keyed) cron outside this module.
    )annotationsN)	dataclassfield)ListOptionalSequence)DEFAULT_ANU_KEYSENFORCER_SCHEMAFAILPASSenforce_callback_owner
is_anu_keyANU_CHAIR_FACING_SIDzM^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$*AUTHORITATIVE_CALLBACK_COLLECTOR_PROCESSED'AUTHORITATIVE_BUT_SESSION_DISCONTINUITY NON_AUTHORITATIVE_SELF_COLLECTORSESSION_PROPAGATION_GAPc                    | rt        | t              syt        t        j	                  | j                                     S )uL   cokacdir --session 옵션이 받는 UUID 8-4-4-4-12 hex 형태인지 검증.F)
isinstancestrbool_SESSION_ID_PATTERNmatchstrip)sids    +dispatch/normal_fallback_callback_helper.pyis_valid_session_idr   D   s.    jc*#))#))+677    )env_namec                   t        | t              r| nd}|st        j                  j	                  |      }|sy|j                         }|syt        |      r|S dS )u   chair-facing SID 해석: 명시값 > 환경변수 > None.

    값이 유효한 session UUID 가 아니면 None 을 반환 (★ 빈 문자열·미설정 동일 처리).
    N)r   r   osenvirongetr   r   )explicitr   	candidates      r   resolve_chair_facing_sidr&   K   sS     'x54IJJNN8,	!I+I69@D@r   )ExecutorSelfKeyForbidden'assert_collector_key_is_independent_anu)ANU_KEYvalidate_callback_registration)DEFAULT_EVENTS_DIRemit_not_registered_markerz+dispatch.normal_fallback_callback_helper.v1normalfallbackc                      e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded<   d	ed
<   ded<   ded<    ee      Zded<   edd       Z	ddZ
y)CallbackRequestu  An owner-validated callback registration request descriptor.

    ``argv`` is the (data-only) ``cokacdir --cron`` argument vector an
    authorized session would execute. It is produced ONLY when the owner
    binding is fail-closed valid (owner == an independent ANU key, not the
    executor self key). On FAIL, ``argv`` is None — no registration is
    possible (회장 §2/§8/§10).
    r   schemaverdictkindtask_id	owner_keychat_idOptional[str]cron_idOptional[List[str]]argvdictenforcementdefault_factory	List[str]reasonsc                (    | j                   t        k(  S Nr2   r   selfs    r   okzCallbackRequest.ok       ||t##r   c                $   | j                   | j                  | j                  | j                  | j                  | j
                  | j                  | j                  t        | j                        nd | j                  t        | j                        d
S )N
r1   r2   r3   r4   r5   r6   r8   r:   r<   r@   )r1   r2   r3   r4   r5   r6   r8   r:   listr<   r@   rD   s    r   to_jsonzCallbackRequest.to_json   sh    kk||II||||||'+yy'<DO$++DLL)
 	
r   Nreturnr   rM   r;   )__name__
__module____qualname____doc____annotations__r   rJ   r@   propertyrF   rK    r   r   r0   r0      s_     KL
ILNL
t4GY4$ $
r   r0    ANUTcokacdir_cron_directF)r8   dispatch_cron_idnormal_collector_cron_idfallback_callback_cron_idcollector_roleprompt_claims_anu_collector
entry_pathanu_keysno_fallbackanu_keys_resolvablechair_facing_session_idc                |   | t         vr2t        t        t        | ||t	        |      |di d| dt          dg
      S 	 t        |       t        ||||||	|	n| t        k(  r|nd|
|
n| t        k(  r|nd|t	        |      |||||      }|j                  t        k7  rQt        t        |j                  | ||t	        |      |d|j                         dgt        |j                        z   
      S d	d
|d|dt	        |      d|dg
}dg}t        |      }|r)|j!                  d|g       |j#                  d| d       n|j#                  d       t        t        t        | ||t	        |      |||j                         |
      S # t        $ r4}t        t        t        | ||t	        |      |di d| g
      cY d}~S d}~ww xY w)u  Build a fail-closed normal/fallback callback registration request.

    The owner pin is enforced via ``enforce_callback_owner`` BEFORE any argv
    is produced. If the owner is the executor self key / not an independent
    ANU key / collector role != ANU -> verdict FAIL and ``argv=None`` (the
    cron-direct path therefore CANNOT register an executor-owned callback,
    회장 §2/§8/§10). HOLD propagates (§6 conditional escalation).

    task-2686 ★ chair-facing session propagation: ``chair_facing_session_id``
    이 명시되거나 환경변수 ``ANU_CHAIR_FACING_SID`` 가 유효 UUID 면 PASS argv
    에 ``--session <SID>`` 을 자동 첨부 (회장 verbatim 1번 / ANCHOR-5 dogfood).
    Nzunknown callback kind z (expected )rI   u   dispatch_callback_contract.assert_collector_key_is_independent_anu fail-closed — owner_key 가 독립 ANU key (c119085addb0f8b7) 가 아님: )r4   executor_keycollector_keycollector_owner_keyr\   rZ   r[   rY   r6   r]   r^   r_   r`   ra   ui   owner enforcement did not PASS — no cron-direct registration argv produced (fail-closed, §2/§8/§10).cokacdirz--cron--atz--chatz--keyz--onceu4   owner=independent ANU key — fail-closed gate PASS.z	--sessionzchair_facing_session_id=uS    → --session argv 자동 추가 (★ task-2686 회장 verbatim 1번 propagation).u   chair_facing_session_id 미해석 (명시값/환경변수 모두 invalid) — --session argv 미첨부, fresh session spawn 가능성 잔존 (★ task-2686 SESSION_PROPAGATION_GAP 후보).)VALID_KINDSr0   HELPER_SCHEMAr   r   _dcc_assert_independent_anu_DCC_ExecutorSelfKeyForbiddenr   CALLBACK_KIND_NORMALCALLBACK_KIND_FALLBACKr2   r   rK   rJ   r@   r&   extendappend)r3   r4   re   r5   r6   promptatr8   rY   rZ   r[   r\   r]   r^   r_   r`   ra   rb   _dcc_excenfr:   propagation_reasonsresolved_sids                          r    build_anu_owned_callback_requestrx      s:   B ; L-dX[QOP
 	
(
#I.& !!%% (3 %!%99't )4 &!%;;')G$?/-C2 {{d KKLK Ls{{#$
 	
( 	
GD" ']%]+,CDL[,/0""&|n 5@ @	

 	"">	

 GKKM# } ) 
 L22:=
 	

s   E> >	F;)F60F;6F;c                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded	<    ee
      Zded<   edd       ZddZ	y)PostRegistrationOwnerCheckr   r1   r2   r4   r   expected_owner_is_anuobserved_owner_keyobserved_chat_idobserved_roler=   r?   r@   c                (    | j                   t        k(  S rB   rC   rD   s    r   rF   zPostRegistrationOwnerCheck.okX  rG   r   c           
         | j                   | j                  | j                  | j                  | j                  | j
                  | j                  t        | j                        dS )Nr1   r2   r4   r{   r|   r}   r~   r@   )	r1   r2   r4   r{   r|   r}   r~   rJ   r@   rD   s    r   rK   z"PostRegistrationOwnerCheck.to_json\  sQ    kk||||%)%?%?"&"9"9 $ 5 5!//DLL)	
 		
r   NrL   rN   )
rO   rP   rQ   rS   r   rJ   r@   rT   rF   rK   rU   r   r   rz   rz   M  sO    KLLt4GY4$ $

r   rz   )r_   c           
        g }t        ||      }|r||k(  r|j                  d       |s|j                  d|d       t        |      t        |      k7  r|j                  d|d|d       |dk7  r|j                  d|d	       |st        nt        }	|	t        k(  r|j                  d
       t        t        |	| ||t        |      ||      S )u)  회장 §8 — 등록 후 schedule_history/registry owner 교차검증.

    After ``cokacdir --cron`` registers the callback, the ANU control layer
    re-reads the owning schedule's key/chat/role and asserts it is an
    independent ANU binding. An owner that resolved to the executor key (or
    any non-ANU key), a chat mismatch, or a non-ANU role -> FAIL (a
    registered executor-self callback is detected post-hoc and rejected).
    Read-only; the observed values are supplied by the caller from
    schedule_history / the durable registry.
    u   post-registration owner key == executor self key — a cron-direct executor-self callback slipped through and is rejected (§8 post-reg owner cross-check / §2).zpost-registration owner key uA    is not a configured independent ANU key (§8 owner cross-check).zchat_id mismatch: registered=z
 expected=u    (§8 binding cross-check).rW   zregistered collector role=u5    != 'ANU' (§8 owner cross-check / §2 regression 5).ux   post-registration owner binding is an independent ANU key with matching chat_id and ANU role — cross-check PASS (§8).r   )r   rq   r   r   r   rz   rk   )
r4   re   r|   r}   r~   expected_chat_idr_   r@   owner_is_anur2   s
             r   verify_post_registration_ownerr   i  s   ( G0(;L0L@6	

 *+=*@ AF F	
 $4 55+,<+? @(++FH	
 ((9 :: :	
 "dtG$M	
 &*--.#	 	r   z/home/jay/workspacei<  z4dispatch.normal_fallback_callback_helper.launcher.v1ANU_OWNED_READYSELF_KEY_FAIL_CLOSEDCALLBACK_PROMPT_TOO_LARGECANONICAL_ROOT_INVALIDOWNER_ENFORCEMENT_FAILEDr   FAIL_CLOSEDCOLLECTOR_ANU%RECOVERY_ONLY_NO_FINAL_REPORT_TRIGGER   10m<   >   rs   sha256r6   summaryr4   r5   report_pathresult_pathcallback_kindcanonical_rootr\   source_attributionnowc          	         ddl }||n|j                   j                         }||j                  t        dt	        |                   z   }|j                  d      S )u"  (now + delay_seconds) → cokacdir-compatible absolute timestamp.

    Returns ``"YYYY-MM-DD HH:MM:SS"`` (local time, naive — matches cokacdir
    server local timezone). ``now`` accepts a ``datetime`` for testability;
    defaults to ``datetime.now()`` (no tz conversion — cokacdir parses server
    local time).

    task-2661 Phase 2b: cokacdir live runtime rejects second-suffix `--at`
    values (e.g. ``"10s"``) — absolute timestamp is the only sub-minute form
    accepted. Fallback (``DEFAULT_AT_FALLBACK="10m"``) is untouched.
    r   N)seconds%Y-%m-%d %H:%M:%S)datetimer   	timedeltamaxintstrftime)delay_secondsr   _dtbasetargets        r   "build_absolute_at_for_normal_delayr     sP       #S\\5E5E5GDCMM#a]1C*DMEEF??.//r   c                   | rt        | t              sy| j                         }|syd|v r	d|v rd|v ry|j                         ry|d   j	                         }|dd }|r!|j                  ddd      j                         sy	 t        |      }|d	k(  rt        |      S |d
k(  rt        |dz        S |dk(  rt        |dz        S |dk(  rt        |dz        S y# t        $ r Y yw xY w)uK   cokacdir relative-time string → seconds. Absolute / unparseable → None.N -:.rV      smr   hi  diQ )	r   r   r   isdigitlowerreplacefloat
ValueErrorr   )rs   r   unitbodyns        r   parse_at_secondsr     s    ZC(

A
axC1H 	yy{R5;;=DSb6Dt||CQ/779$K s{1vs{1r6{s{1t8}s{1u9~  s   C 	C#"C#r   c                    | rt        | t              syddl}	 |j                  j                  | j	                         t
               y# t        $ r Y yw xY w)z6True iff ``at`` parses as cokacdir absolute timestamp.Fr   NT)r   r   r   strptimer   _ABSOLUTE_AT_PATTERNr   )rs   r   s     r   is_absolute_atr     sI    ZC(bhhj*>? s   .A 	AAc                   t        |       syddl}||n|j                  j                         }|j                  j                  | j	                         t
              }t        ||z
  j                               S )zHSeconds from ``now`` to absolute ``at``. None if ``at`` is not absolute.Nr   )r   r   r   r   r   r   r   total_seconds)rs   r   r   r   r   s        r   absolute_at_delay_secondsr     s]    " #S\\5E5E5GD\\""288:/CDF,,.//r   )reasonthreshold_secondsr   c               b   t        |      rt        ||      }nt        |      }dd|| dd}| t        k7  rd|d<   |S |d|d<   |S t        |      s|d	k  rd
|d<   d|d<   d|d|d<   |S ||k  rd|d<   |S |r t	        |      j                         rd|d<   |S d
|d<   d|d<   d| d| d|d<   |S )u   normal kind + delay>threshold + reason 없음 → warning 발급.

    절대시각 ``at`` 도 (target - now) 로 환산하여 lint 한다.
    fallback kind / threshold 이내 / reason 제공 시 warning=False.
    r   FOKrV   )warningcoder   r3   messageSKIP_NON_NORMALr   SKIP_UNPARSEDr   Tr   %UNSUPPORTED_SUB_MINUTE_RELATIVE_DELAYznormal callback delay z^ (< 60s) must use absolute timestamp (cokacdir live runtime rejects relative sub-minute forms)r   WITHIN_THRESHOLDREASON_PROVIDEDNORMAL_DELAY_REASON_REQUIREDzs > uL   s threshold · reason 누락 (★ task-2661 Phase 2b lint · enforce 아님))r   r   r   rn   r   r   )r3   rs   r   r   r   secsouts          r   lint_normal_callback_delayr   &  s    b(5#C ##'F
|%F
 "$)I=F$RF +H I 	I 
  (F
#f+##%'F
C	N0CK
 d+<*= >: 	; 	N Jr   c                >    t        | xs dj                  d            S )u&   callback prompt 의 UTF-8 byte 길이.rV   zutf-8)lenencode)rr   s    r   callback_prompt_utf8_bytesr   ]  s    "$$W-..r   c                   | xs dj                         D cg c]#  }|j                         s|j                         % }}|sy|D ]5  }d|vr y|j                  dd      d   j                         }|t        vs5 y yc c}w )u   prompt 가 envelope-only 인가 — 모든 비공백 line 이
    `key=value` 형태이고 key 가 ENVELOPE_ALLOWED_KEYS 에 속하면 True
    (자유 지시문 금지, 회장 §5.6 envelope-only).rV   F=r   r   T)
splitlinesr   splitENVELOPE_ALLOWED_KEYS)rr   lnlineskeys       r   is_envelope_onlyr   b  s     $*<R";";"=LBRXXZLEL b=hhsAq!'')++  Ms
   A?A?require_envelopec                  t        |       }t        | xs d      }|t        kD  }t        |       }g }d}d}|r$d}t        }|j                  d| dt         d       |r|sd}|dk(  rd}|j                  d	       |||||||d
S )u   callback prompt 검증: UTF-8 ≤3900 bytes + envelope-only.
    반환 dict: ok, utf8_bytes, chars, too_large, envelope_only, status, reasons.rV   r   TFzcallback prompt z	 bytes > u5    (CALLBACK_PROMPT_TOO_LARGE fail-closed, §5.5/§10).ENVELOPE_VIOLATIONu5   callback prompt 가 envelope-only 가 아님 (§5.6).)rF   
utf8_byteschars	too_largeenvelope_onlystatusr@   )r   r   CALLBACK_PROMPT_MAX_BYTESr    STATUS_CALLBACK_PROMPT_TOO_LARGErq   )	rr   r   utf8r   r   env_onlyr@   r   rF   s	            r   validate_callback_promptr   r  s     &f-D"E00I'HGF	B1tfI.G-H IC C	
 T>)FNOuW r   c                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   dZded<    ee      Zded<   edd       Z	ddZ
y)LaunchDecisionr   r1   r2   r   r3   r4   r5   r6   r   r   canonical_root_correctedr9   r:   r;   contract_fieldsNzOptional[dict]requestr=   r?   r@   c                (    | j                   t        k(  S rB   )r2   LAUNCH_PASSrD   s    r   rF   zLaunchDecision.ok  s    ||{**r   c                x   | j                   | j                  | j                  | j                  | j                  | j
                  t        | j                        | j                  | j                  | j                  t        | j                        nd | j                  | j                  t        | j                        dS )Nr1   r2   r   r3   r4   r5   r6   r   r   r:   r   r   r@   )r1   r2   r   r3   r4   r5   r   r6   r   r   r:   rJ   r   r   r@   rD   s    r   rK   zLaunchDecision.to_json  s    kk||kkII||4<<("11(,(E(E'+yy'<DO$#33||DLL)
 	
r   rL   rN   )rO   rP   rQ   rS   r   r   rJ   r@   rT   rF   rK   rU   r   r   r   r     sm    KLK
ILNL""
"G^"t4GY4+ +
r   r   c           
         t        |       t        | xs d      ||t        t        |      t        |xs d      t        |      t        d	S )u'   회장 §10 callback contract 9 fields.rV   )	r   callback_prompt_charscallback_cron_idcallback_registration_statuscallback_roleenvelope_only_compliancefallback_prompt_utf8_bytesfallback_safety_net_registered'fallback_safety_net_role_single_purpose)r   r   CALLBACK_ROLE_COLLECTOR_ANUr   FALLBACK_ROLE_SINGLE_PURPOSEcallback_promptr3   r8   r   r   fallback_promptfallback_registereds          r   _contract_fieldsr    sO    
 'A&Q!$_%:!;#(.4$($7&@AVTV&W*./B*C3O
 
r   c                  r    e Zd ZU dZded<   ded<   ded<   ded<   ded<   d	ed
<    ee      Zded<   ddZy)SessionPropagationVerdictu  task-2686 ★ classifier 4 enum 출력 데이터클래스.

    회장 verbatim 6번: envelope chair_facing_session_id / collector_session_id /
    delivery_session_id 3 field 정합성 + ANU owner 검증 mismatch 시
    AUTHORITATIVE_BUT_SESSION_DISCONTINUITY 강제 분류.
    r   r1   classificationr7   rb   collector_session_iddelivery_session_idr   observed_owner_is_anur=   r?   r@   c           	         | j                   | j                  | j                  | j                  | j                  t        | j                        t        | j                        dS )Nr1   r  rb   r	  r
  r  r@   )	r1   r  rb   r	  r
  r   r  rJ   r@   rD   s    r   rK   z!SessionPropagationVerdict.to_json  sQ    kk"11'+'C'C$($=$=#'#;#;%)$*D*D%EDLL)
 	
r   NrN   )	rO   rP   rQ   rR   rS   r   rJ   r@   rK   rU   r   r   r  r    s@     K**''&&t4GY4	
r   r  c           	        g }t        | t              r | j                         r| j                         nd}t        |t              r |j                         r|j                         nd}t        |t              r |j                         r|j                         nd}	t        |t              rt        ||      nd}
|r0||k(  r+|j	                  d       t        t        t        |||	d|      S |
s/|j	                  d|d       t        t        t        |||	d|      S |rt        |      s+|j	                  d       t        t        t        |||	d|      S g }|r||k7  r|j	                  d	| d
|        |	r|	|k7  r|j	                  d|	 d
|        |rN|j	                  ddj                  |      z          |j	                  d       t        t        t        |||	d|      S |j	                  d       t        t        t        |||	d|      S )u  envelope 3 session field + owner 관측치를 4 enum 으로 분류.

    분류 우선순위 (회장 verbatim 6번 강제):
      1. observed_owner_key == executor_key → ``NON_AUTHORITATIVE_SELF_COLLECTOR``
      2. observed_owner_key ∉ anu_keys → ``NON_AUTHORITATIVE_SELF_COLLECTOR``
         (★ self-key 가 아니더라도 ANU 가 아니면 동일 분류 — task-2680 doctrine)
      3. chair_facing_session_id 누락 또는 invalid → ``SESSION_PROPAGATION_GAP``
      4. envelope 3 SID 중 하나라도 chair_facing 과 불일치 (collector/delivery
         가 명시되었으나 chair_facing 과 다른 UUID) → ``AUTHORITATIVE_BUT_
         SESSION_DISCONTINUITY``
      5. 그 외 ANU + 3 SID 일치 → ``AUTHORITATIVE_CALLBACK_COLLECTOR_PROCESSED``
    NFu   observed_owner_key == executor_key — self-key callback (ANCHOR-2 key authority ≠ session continuity, but self-key 우선 분류).r  zobserved_owner_key=uH    ∉ anu_keys — NON_AUTHORITATIVE_SELF_COLLECTOR (task-2680 doctrine).u   chair_facing_session_id 누락/invalid — fresh collector session spawn 가능성 (SESSION_PROPAGATION_GAP, task-2686 ANCHOR-1).Tzcollector_session_id=z != chair_facing_session_id=zdelivery_session_id=zSsession id mismatch detected (ANU key authoritative but session routing diverged): ; u   → AUTHORITATIVE_BUT_SESSION_DISCONTINUITY (회장 verbatim 6번 강제 분류, ANCHOR-1 key authority ≠ session continuity).u   ANU owner + chair_facing_session_id 일치 (collector/delivery 가 있다면 동일) — AUTHORITATIVE_CALLBACK_COLLECTOR_PROCESSED.)r   r   r   r   rq   r  rk   SESSION_PROPAGATION_SELF_KEYr   r   join!SESSION_PROPAGATION_DISCONTINUITYSESSION_PROPAGATION_OK)rb   r	  r
  r|   re   r_   r@   	chair_sidcollector_siddelivery_sidobserved_is_anu
mismatchess               r   classify_session_propagationr    sl   * G3=>UWZ3[`w`}`}`'--/  FJI4>?SUX4Y^r^x^x^z(..0  AEM2<=PRU2V[n[t[t[v&,,.  }ALBLM_adBej!3X>kpO0L@Q	
 ) 7$-!. ,"'
 	
 !"4!7 8E E	
 ) 7$-!. ,"'
 	
 /	:M	
 ) 2$-!. ,"&
 	
 J)3#M?2NykZ	
 	1"<.0LYKX	
 *,0IIj,AB	
 	M	
 ) <$-!. ,"&
 	
 NN	L %- )*(" r   )	r   r8   rY   rZ   r[   r  r   r_   rb   c                4   g }d}|st         }d}|j                  d       nd|t         k7  r[t        || |t        t	        |      |xs dd      }t        t        t        t        | ||t        |      |dd|d|dt         d	g
      S t        ||      }|d   rLt        || |t        |d   |xs dd      }t        t        t        t        | ||t        |      ||d||d   
      S |	xs | d}	|
xs | d}
|xs | d}|| t        k(  r|
n|}t        | |||t        |      ||||	|
|||      }| t        k(  xr |j                  }|j                  rt        }t         }|j                  d       nUt        }||k(  rt"        }|j                  d       nt$        }|j                  d       |j'                  |j(                         t        || |||d   |xs d|      }t        t        ||| ||t        |      |||j*                  ||j-                         |      S )uo  단일 callback/fallback 런타임 launcher (회장 §3 launcher 단일화).

    fail-closed 순서: canonical root → prompt byte/envelope → owner enforce
    (build_anu_owned_callback_request 경유). owner==executor self-key 면
    SELF_KEY_FAIL_CLOSED (argv=None). ANU key 만 PASS.
    실 cron 발사/ subprocess 0 — argv(데이터)만 생성한다.
    FTu<   canonical_root 미지정 → /home/jay/workspace 로 교정.rV   r  Nzcanonical_root=z != u    → fail-closed (§5.9).)r1   r2   r   r3   r4   r5   r6   r   r   r:   r   r@   r   r   r   r@   z
::dispatchz::normalz
::fallback)r3   r4   re   r5   r6   rr   rs   r8   rY   rZ   r[   r_   rb   u7   owner=ANU key — launcher PASS, ANU-owned argv 생성.uK   owner_key == executor self key → SELF_KEY_FAIL_CLOSED (argv=None, §5.3).u3   owner enforcement FAIL → fail-closed (argv=None).r   )CANONICAL_ROOTrq   r  STATUS_CANONICAL_ROOT_INVALIDr   r   LAUNCHER_SCHEMALAUNCH_FAIL_CLOSEDr   r   r   rn   rx   ro   rF   STATUS_ANU_OWNED_READYr   STATUS_SELF_KEY_FAIL_CLOSEDSTATUS_OWNER_ENFORCEMENT_FAILEDrp   r@   r:   rK   )r3   r4   re   r5   r6   rr   rs   r   r8   rY   rZ   r[   r  r   r_   rb   r@   root_correctedcfpvreqr  r   r2   s                           r   launch_callbackr&  [  sv   4 G N'UV	>	)"w0*62+1ru	N
 ",>0tWW)Er&~&8^<N O0 0 12 	2 
"&;K	LB	+"w3_-+1ru	N
 ",>3$W)Nr2i=B 	B (AgYj+A7OgYh;O 9 Sy
=S/37K/K+1 	
 +7S\&R*:!9"; 7C  #99Dcff
vv'PQ$$0FNNhi4FNNPQs{{#	T76)?;Pb/
1B T9c'l%XXr3;;='	S Sr   z3dispatch.normal_fallback_callback_helper.enforce.v1r   NON_AUTHORITATIVEc                      e Zd ZU ded<   ded<   ded<   ded<   ded<    ee      Zd	ed
<   dZded<    ee      Z	ded<    ee      Z
ded<   edd       ZddZy)EnforceResultr   r1   r2   r4   envelope_pathr7   schedule_idr=   z'dict[str, str]'sources_checkedNmarker_pathr?   r@   z'dict[str, object]'evidencec                (    | j                   t        k(  S rB   )r2   ENFORCE_PASSrD   s    r   rF   zEnforceResult.ok  s    |||++r   c                   | j                   | j                  | j                  | j                  | j                  t        | j                        | j                  t        | j                        t        | j                        d	S )N	r1   r2   r4   r*  r+  r,  r-  r@   r.  )r1   r2   r4   r*  r+  r;   r,  r-  rJ   r@   r.  rD   s    r   rK   zEnforceResult.to_json  sb    kk||||!//++#D$8$89++DLL)T]]+

 
	
r   rL   rN   )rO   rP   rQ   rS   r   r;   r,  r-  rJ   r@   r.  rT   rF   rK   rU   r   r   r)  r)    sm    KLL(-d(CO%C!%K%t4GY4$)$$?H!?, ,
r   r)  )re   anu_key
events_direxpected_chair_facing_sidrequire_chair_facing_sid_matchemit_marker_on_failc                   |xs t         }|xs t        }	t        | |||||      }
d}|
j                  so|rmt	        | dj                  |
j                        xs d|
j                   t        |
j                        |t        |
j                        |	      }|j                  }t        t        |
j                  | ||
j                  t        |
j                        |t        |
j                        t        |
j                        	      S )uC  Helper API layer: validator 호출 + FAIL시 marker 발행.

    회장 verbatim 필수 구현 4번: 'actual cokacdir schedule_id 확인 전 callback PASS 금지'
    회장 verbatim 필수 구현 8번: '실패 시 NORMAL_CALLBACK_NOT_REGISTERED marker + HOLD_FOR_CHAIR'

    - Zero subprocess / Zero cokacdir exec (Layer A 원칙 유지)
    - validator 가 envelope/schedule_history/inbound 파일만 read-only 접근
    - FAIL/NON_AUTHORITATIVE 시 marker 자동 발행 (.done.escalated 대체 정책)

    Returns:
        EnforceResult — .ok True iff verdict == PASS
    )r4   r*  re   r3  r5  r6  Nr  z4-source validator verdict=)r4   r   r,  r*  r.  r4  r2  )_ENFORCE_ANU_KEY_ENFORCE_DEFAULT_EVENTS_DIR'_enforce_validate_callback_registrationrF   #_enforce_emit_not_registered_markerr  r@   r2   r;   r,  r.  r-  r)  ENFORCE_SCHEMAr+  rJ   )r4   r*  re   r3  r4  r5  r6  r7  _anu_key_events_dirvresr-  ems                r   *assert_normal_callback_actually_registeredrB    s    . **H; ;K2#!";'ED "&K77*099T\\*Z0KDLL>.Z !5!56'$--("
 nn#$$T112T\\"dmm$
 
r   )2rk   r
   rn   ro   rj   r0   rx   rz   r   r  r   r  r   r&  r   r   r   r  r   r   r  r   r  r   r   DEFAULT_AT_NORMAL_DELAY_SECONDSDEFAULT_AT_FALLBACK%NORMAL_DELAY_REASON_THRESHOLD_SECONDSr   r   r   r   r   ANU_CHAIR_FACING_SID_ENVr  r  r  r   SESSION_PROPAGATION_ENUMr   r&   r  r  rB  r)  r=  r0  ENFORCE_FAILENFORCE_NON_AUTHORITATIVEmainc                   dd l }dd l}dd l}|j                  d      }|j	                  dd      }|j                  d      }|j                  ddt        t              	       |j                  d
d       |j                  dd       |j                  dd       |j                  dd       |j                  dd       |j                  dd        |j                  dd        d}|j                  |dd        |j                  dd       |j                  dd d       |j                  ddd d       |j                  d       }|j                  d
d       |j                  d!d       |j                  dd"       |j                  d#d        |j                  d$d        |j                  d%d        |j                  d&d       |j                  d'd       |j                  |       }	|	j                  d k(  rt        |	j                  |	j                  |	j                  |	j                  |	j                   |	j"                  |	j$                  |	j&                   (      }
t)        |j+                  |
j-                         d)*             |
j.                  rdS d+S |	j0                  }|)|	j2                  t4        k(  rt7        t8              }nt:        }t=        |	j2                  ||	j>                  ,      }|jA                  d-      r/|jB                  jE                  d.|jA                  d/d"       d0       tG        |	j2                  |	j                  |	j                  |	jH                  |	jJ                  |	jL                  ||	jN                  |	jP                  |	jR                   |	jT                  1      }t)        |j+                  |j-                         d)*             |j.                  rdS d+S )2Nr   z(dispatch.normal_fallback_callback_helper)progcmdT)destrequiredlaunchz--kind)rO  choicesz	--task-id)rO  z--executor-keyz--owner-keyz	--chat-idz--promptri   )defaultz--canonical-rootz	--cron-idr8   )rN  rR  z--no-require-envelope
store_true)actionz--delay-reasonuP   normal callback delay>60s 시 lint warning 억제용 reason (★ enforce 아님))rR  helpz--chair-facing-sidrb   u@   ANU 본 세션 SID (cokacdir --session 옵션에 자동 첨부).)rN  rR  rU  enforcez--envelope-pathrV   z	--anu-keyz--events-dirz--expected-chair-facing-sidz --require-chair-facing-sid-matchz--no-marker-on-fail)r4   r*  re   r3  r4  r5  r6  r7  F)ensure_ascii   )r   r   z[task-2661 lint warning] r   
)r3   r4   re   r5   r6   rr   rs   r   r8   r   rb   )+argparsejsonsysArgumentParseradd_subparsers
add_parseradd_argumentsortedrj   
parse_argsrM  rB  r4   r*  re   r3  r4  r5  r6  no_marker_on_failprintdumpsrK   rF   rs   r3   rn   r   rC  rD  r   delay_reasonr#   stderrwriter&  r5   r6   rr   r   r8   no_require_enveloperb   )r:   rZ  _json_sysapsublp
_cron_flagepaeresat_valuelintdecs                 r   rJ  rJ  l  sQ   //		 	 &P	 	QB




6C		!BOOHtVK5HOIOOK$O/OO$tO4OOMDO1OOK$O/OOJO. OOFDO)OO&O5&JOOJYO=OO+LOAOO$dk  m OO&O	   
		"BOOK$O/OO%O5OO$bO1OOKO.OONDO1OO14O@OO6|OLOO),O?
dAuu	9II//II||&'&A&A+,+K+K$%$7$7 7	
 	ekk$,,.uk=>GGq""ttH66))9:YZH*H%affhq~~NDxx	'2(>'?rB	
 VVQYYQ^^++qyyh''222 ! 9 9;C 
%++ckkm%+
891Ar   __main__)r   r7   rM   r   rB   )r$   r7   r   r   rM   r7   )&r3   r   r4   r   re   r   r5   r   r6   r   rr   r   rs   r   r8   r7   rY   r   rZ   r7   r[   r7   r\   r   r]   r   r^   r   r_   Sequence[str]r`   r   ra   r   rb   r7   rM   r0   )r4   r   re   r   r|   r   r}   r   r~   r   r   r   r_   rw  rM   rz   )r   r   rM   r   )rs   r   rM   zOptional[int])rs   r   rM   r   )
r3   r   rs   r   r   r7   r   r   rM   r;   )rr   r   rM   r   )rr   r   rM   r   )rr   r   r   r   rM   r;   )r  r   r3   r   r   r   r   r   r  r   r  r   rM   r;   )rb   r7   r	  r7   r
  r7   r|   r   re   r   r_   rw  rM   r  )"r3   r   r4   r   re   r   r5   r   r6   r   rr   r   rs   r   r   r7   r8   r7   rY   r7   rZ   r7   r[   r7   r  r7   r   r   r_   rw  rb   r7   rM   r   )r4   r   r*  r   re   r   r3  r7   r4  r7   r5  r7   r6  r   r7  r   rM   r)  )r:   r9   rM   r   )^rR   
__future__r   r!   redataclassesr   r   typingr   r   r    dispatch.callback_owner_enforcerr	   r
   r   r   r   r   rF  compiler   r  r  r  r   	frozensetrG  r   r&   !anu_v3.dispatch_callback_contractr'   rm   r(   rl   ,utils.normal_callback_registration_validatorr)   r9  r*   r;  "utils.callback_registration_markerr+   r:  r,   r<  rk   rn   ro   rj   r0   tuplerx   rz   r   r  r   r  r  r   r   r  r!  r   r  r   r   rC  rD  rE  r   r   r   r   r   r   r   r   r   r   r   r  r  r  r&  r=  r0  rH  rI  r)  rB  __all__rJ  rO   
SystemExitrU   r   r   <module>r     s  6 # 	 	 ( + +  2  !bjj'  F $M !A 3 $% 	&  8 #A -AA A 	A:
 > # -/EFG %
 %
 %
b ".2/3(,,#$45 $-1'a
a a 	a
 a a a 	a a a ,a  -a a "&a a  !a" #a$ %a& +'a( )aH 
 
 
F $$45:: : 	:
 : : : :  :D '  H + 4 #>   8 "< " - F  #%  (* % " #   90 	00 		06D + 	 /3 0" !B4
44 	4
 4 
4n/
  GK : "
 "
 "
J$(;>*.37" 
 
 
F $$45u*u (u '	u
 u u u uB %)!&*.2/3%)!#$45-1#jS
jS jS 	jS
 jS jS jS 	jS "jS jS $jS ,jS  -jS #jS jS  !jS" +#jS$ %jSn G/  
 
 
B ! $/3+0 $99 9 	9
 9 9  -9 %)9 9 9x6rJZ z
TV
 r   