
    8#j1                        d Z ddlmZ ddlmZ ddlmZmZmZ ddl	m
Z
mZmZmZmZ dZdZe G d d	             Zdd
ZddZddZddZddZy)u#  utils.anu_callback_fallback — fallback cancel-on-success signal decider.

task-2635 — normal callback registration enforcement (Core hardening).
task-2635+1 — 5축 schema 인식 (registration_result_status 우선, legacy alias fallback).

Spec: memory/specs/system_normal_callback_registration_implementation_spec_260523.md
sha256: 0fbd1dad1e110c49474dfbdf13a21fb3bdd9c7f094128004dba8472840bb832d

회장 verbatim (task-2635 §3.4):
    ANU fallback cron 의 cancel-on-success signal =
      ``normal_callback_registration_status == REGISTERED`` +
      collector durable-success 마커 생성
    단순 envelope sendfile 또는 result.json 존재 만으로는 cancel 안 함
    (false cancel 차단)

ANCHOR-4: fallback cancel-on-success = REGISTERED status +
collector durable-success 마커.
    )annotations)	dataclass)AnyListOptional) NormalCallbackRegistrationStatusRegistrationResultStatusis_callback_completeis_success_statusnormalize_statuszutils.anu_callback_fallback.v2) collector_durable_success_markercollector_done_marker_pathc                  D    e Zd ZU ded<   ded<   ded<   ded<   dZded	<   y)
FallbackDecisionboolcancel_fallbackstrreasondurable_success_marker_presentstatusNzOptional[str]schedule_id)__name__
__module____qualname____annotations__r        N/home/jay/workspace/.worktrees/task-2729+7-dev1/utils/anu_callback_fallback.pyr   r   +   s"    K$((K!%K%r   r   c                    t        | t              st        j                  j                  S d| v rt        | j                  d            S t        | j                  d            S )u:   task-2635+1 — read axis-3 with backward-compat fallback.registration_result_statusregistration_status)
isinstancedictr	   NOT_REGISTEREDvaluer   getenvelopes    r   _read_axis_3r)   4   sP    h%'66<<<#x/-I JKKHLL)>?@@r   c                    t        | t              sy| j                  d      du ry| j                  d      }t        |t              r|j	                         ryy)zTrue iff the envelope carries an authoritative collector durable-success
    marker. Either an explicit boolean (preferred) or a non-empty path.
    Fr   Tr   )r"   r#   r&   r   strip)r(   paths     r   has_durable_success_markerr-   =   sM     h%||674?<<45D$r   c                R   t        | t              s't        dddt        j                  j
                        S t        |       }| j                  d      xs d}t        |       }|t        j                  j
                  k(  rD| j                  d      r#| j                  d      du rt        dd	|||
      S t        dd|||
      S |t        j                  j
                  k7  rt        dd|d|||
      S |st        dd||d
      S |st        ddd||
      S t        ddd||
      S )a0  Decide whether to cancel the fallback safety-net cron.

    Returns ``cancel_fallback=True`` ONLY when:
      * registration_result_status == REGISTERED   (real cron fired)
      * cron_schedule_id present                   (recovered from registrar)
      * collector durable-success marker present
    Fenvelope is not a dict)r   r   r   r   cron_schedule_idNexplicit_skip_reason(explicit_skip_authorizes_fallback_cancelTz;skipped with explicit reason + pre-approved fallback cancel)r   r   r   r   r   u\   skipped status but explicit_skip_authorizes_fallback_cancel not set — fallback stays armedstatus z != REGISTERED (fail-closed)u@   REGISTERED but cron_schedule_id missing — false cancel blockedz>REGISTERED + schedule_id present but no durable-success markerz;REGISTERED + schedule_id + collector durable-success marker)r"   r#   r   r   r$   r%   r)   r&   r-   r	   SKIPPED_WITH_EXPLICIT_REASON
REGISTERED)r(   r   r   durables       r   decide_fallback_cancelr7   K   sr    h%!++03BBHH	
 	
 (#F,,12:dK(2G)FFLLL<<./HLL65
5 $ $T/6'   !3 ,3#	
 		
 )44:::!VJ&BC+2#
 	
 !U+2
 	
 !S+0#
 	
 L'+ r   c                *    t        t        |             S )u   True iff a real normal callback was registered (REGISTERED + schedule_id).
    SKIPPED / NOT_REGISTERED / SENDFILE_ONLY / REGISTER_FAILED → False.
    )r   r
   r'   s    r   expected_collector_spawnr9      s     $X.//r   c                <   t        | t              sdgS g }t        |       }t        |      s|j	                  d|d       |t
        j                  j                  k(  r"| j                  d      s|j	                  d       t        |       s|j	                  d       |S )Nr/   r3   z is fail-closedr0   z'REGISTERED but cron_schedule_id missingz'no collector durable-success marker yet)
r"   r#   r)   r   appendr	   r5   r%   r&   r-   )r(   reasonsr   s      r   explain_fail_closedr=      s    h%())G(#FV$
/:;)44:::8<<D 	@A%h/@ANr   N)r(   r   returnr   )r(   r   r>   r   )r(   r   r>   r   )r(   r   r>   z	List[str])__doc__
__future__r   dataclassesr   typingr   r   r   utils.callback_envelope_schemar   r	   r
   r   r   FALLBACK_DECIDER_SCHEMADURABLE_SUCCESS_MARKER_KEYSr   r)   r-   r7   r9   r=   r   r   r   <module>rF      sg   $ # ! & &  ;   & & &AK\0r   