
    vjS                       d Z ddlmZ ddlmZmZ ddlmZmZ ddl	m
Z
mZ ddlmZmZmZmZ dZdZd	Z eeeh      Ze G d
 d             ZddZ	 	 	 	 ddZddddd	 	 	 	 	 	 	 	 	 	 	 ddZddddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddedddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d dZddd	 	 	 d!dZdddddddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d"dZy)#u  dispatch.cron_dispatch_guard — cron-direct path callback fail-closed guard.

task-2553+44 (구현목표 A). Standalone, pure stdlib + same-package imports of
the existing (byte-0) executor_completion_contract / spec_template_validator.

Problem (회장 §2.3 / diagnosis report_items.7/9): the +32 mandatory
executor-completion-callback contract exists in code, but the ACTUAL dispatch
entry used for +41/+42/+43 is the ``cokacdir --cron`` direct path
(dispatch.py shim / dispatch.core.main is bypassed). The contract was never
called there — §8 held only by task-md text + bot self-compliance, NOT by a
code-level fail-closed gate.

This guard is the fail-closed gate for BOTH paths:
  * ``dispatch.py`` / dispatch.core.main, and
  * the ``cokacdir --cron`` direct path (legacy/bot-driven).

It validates the mandatory normal-completion-callback clause + the durable
4-tuple, records the 4-tuple to the durable ledger, and returns
PASS / FAIL / HOLD_FOR_CHAIR. A cron-direct dispatch that bypasses the
contract -> FAIL (regression 6).

Layer A / NO-CRON (9-R.1): the guard VALIDATES, RECORDS (append-only ledger),
and FAILs/HOLDs only. It performs ZERO cron register/remove, ZERO dispatch,
ZERO ``cokacdir``/``subprocess`` exec. The executor's own normal completion
callback (Layer B, §10) is a designed lifecycle signal — NOT a registry-added
ad-hoc cron — and is therefore explicitly NOT a "cron 신규 등록" breach.
    )annotations)	dataclassfield)ListOptional)Callback4Tuplevalidate_4tuple)FAILHOLDPASSspec_has_normal_callback_clausez&dispatch.cron_dispatch_guard_result.v1zdispatch.core.maincokacdir_cron_directc                      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)CronDispatchGuardResultstrschemaverdict
entry_pathboolclause_presenttuple_validno_fallback_contractrecorded_to_ledger)default_factory	List[str]reasonsc                (    | j                   t        k(  S )N)r   r   selfs    dispatch/cron_dispatch_guard.pyokzCronDispatchGuardResult.ok@   s    ||t##    c           
         | j                   | j                  | j                  | j                  | j                  | j
                  | j                  t        | j                        dS )Nr   r   r   r   r   r   r   r   )	r   r   r   r   r   r   r   listr   r   s    r    to_jsonzCronDispatchGuardResult.to_jsonD   sQ    kk||//"11++$($=$="&"9"9DLL)	
 		
r"   N)returnr   )r'   dict)
__name__
__module____qualname____annotations__r   r%   r   propertyr!   r&    r"   r    r   r   5   sO    KLOt4GY4$ $

r"   r   c                .    d| xs dj                         v S )a  A NO-CRON label applies to registry/checkpoint cron-ban ONLY.

    It does NOT exempt the executor's own normal completion callback
    (regression 5). This helper exists only to make the carve-out explicit;
    the clause requirement is enforced regardless of NO-CRON labelling.
    zNO-CRON )upper)	spec_texts    r    #is_no_cron_registry_checkpoint_taskr3   Q   s     b//111r"   c           
     J   g }	 ddl m} 	  ||       }|r|j                  d |D               |	 | j                         }|j                  |j                  |j                  |j                  d	}|j                         D ]D  \  }}	|j                  |      |	k7  s|j                  d
| d|j                  |      d|	d       F |S # t        $ r	 |dgz   cY S w xY w# t        $ r'}|dt	        |      j
                   dgz   cY d}~S d}~ww xY w# t        $ r	 |dgz   cY S w xY w)a$  Validate the durable record and reconcile it with the 4-tuple.

    Returns FAIL reasons (empty == consistent). Pure check: ZERO cron /
    process / dispatch (Layer A). The registry's own ``validate_record`` is
    imported lazily so this module keeps zero module-level anu_v3 coupling.
    r   )validate_recorduw   registry validate_record unavailable — cannot fail-closed-verify ledger record; refusing durable write (fail-closed).z ledger record validation raised u>    — treated as invalid, refusing durable write (fail-closed).Nc              3  &   K   | ]	  }d |   yw)zledger record invalid: Nr.   ).0xs     r    	<genexpr>z+_reconcile_ledger_record.<locals>.<genexpr>{   s     A04As   z#ledger record exposes no identity())task_iddispatch_cron_idnormal_collector_cron_idfallback_callback_cron_idzledger/4-tuple mismatch on z	: record=z tuple=z (fail-closed).)anu_v3.callback_4tuple_registryr5   ImportError	Exceptiontyper)   extendidentityr:   r;   r<   r=   itemsgetappend)
ledger_recordtuple_r   _vrrrexcidentexpectedkvs
             r    _reconcile_ledger_recordrP   [   sr    G
	

 
AbAA	E!**,E ~~ & 7 7(.(G(G)/)I)I	
 NN$ 	DAqyy|q 1! 5#iil-WQEJ	 NA  
J
 
 	

  
.tCy/A/A.B CH I
 
 	

  	ECDDD	Es?   C C D CC	D&DDDD"!D"FTN)r   spec_location_knownledgerrG   c           
     <   g }|st        t        t        |dd|ddg      S |t        vr|j	                  d|d       t        |       }|s|j	                  d       d}	||j	                  d       n6t        |      }
|r|
D cg c]  }d|vr|
 }
}|
r|j                  |
       nd	}	|s
|r|	rt        nt        }d}|t        k(  r=|;|9t        ||      }|r|j                  |       t        }n|j	                  |       d	}t        t        ||||	|||      S c c}w )
u5  Fail-closed gate for an executor dispatch (any entry path).

    Verdict logic (§3.A):
      * spec/template location unresolvable        -> HOLD_FOR_CHAIR (§8)
      * unknown / unrecognised entry path          -> FAIL (cron-direct
                                                       bypass, regression 6)
      * normal completion callback clause missing  -> FAIL (regression 2)
      * 4-tuple absent                             -> FAIL
      * normal_collector_cron_id missing           -> FAIL (regression 3)
      * fallback_callback_cron_id missing AND no
        explicit no-fallback contract              -> FAIL (regression 4)
      * else                                       -> PASS, and the 4-tuple
                                                       is appended to the
                                                       durable ledger.

    ``ledger`` (Callback4TupleRegistry) + ``ledger_record``
    (Callback4TupleRecord) are optional; when both are supplied a PASS
    appends the durable record (§3.A / §3.B). The guard NEVER touches cron.
    Fu|   dispatch/spec template location unresolvable — cannot code-enforce the cron-direct callback contract (§8 HOLD_FOR_CHAIR).r$   zentry_path u    not a recognised gated path — a cron-direct dispatch that bypasses the executor completion contract is FAIL (§3.A / regression 6).u   executor normal completion callback clause MISSING — every executor dispatch (incl. the cokacdir --cron direct path) MUST carry it. NO-CRON does not exempt this (registry/checkpoint cron-ban only, regression 2/5).u    callback 4-tuple absent (§3.A).r=   T)r   GUARD_SCHEMAr   KNOWN_PATHSrF   r   r	   rB   r   r
   rP   )r2   r   rH   r   rQ   rR   rG   r   r   r   	t_reasonsrr   recordedrec_reasonss                  r    guard_dispatchrZ      sk   : G&! !5$(
 	
 $* (7 7	
 5Y?N.	
 K~9:#F+	  $.a7 I  NN9%K ;   H$6--2K.}fENN;'GMM-(H"%1#	 	7s   Dr0   )chat_idprompt_claims_anu_collectorr   rQ   anu_keysanu_keys_resolvablerR   rG   c                   ddl m}m}m}m} ddl m} t        | ||||||      } |||j                  nd||||||	||
|||t        |      n
t        |      ||      }|j                  t        k(  s|j                  |k(  rt        }nct        |j                  |j                  fv s|j                  |k(  rt        }n/|j                  t        k(  r|j                  |k(  rt        }nt        }|||fS )u  task-2553+49 §2/§8 composite fail-closed gate.

    Runs the byte-0 ``guard_dispatch`` (clause + 4-tuple + ledger integrity)
    AND the ``callback_owner_enforcer`` owner pin (owner == independent ANU
    key, collector_role == ANU, executor_key != collector_key, prompt-says-
    ANU-but-owner-is-executor, 4-tuple owner-valid). The composite verdict is
    the strictest of the two: any FAIL -> FAIL, any HOLD with no FAIL -> HOLD,
    else PASS. Returns ``(guard_result, owner_result, composite_verdict)``.

    Layer A: ZERO cron/dispatch/subprocess (both components are pure
    validation; the only optional write is the +44 append-only ledger via the
    existing guard, unchanged).
    r   )r
   r   r   enforce_callback_ownerDEFAULT_ANU_KEYS)r2   r   rH   r   rQ   rR   rG   r0   r:   executor_keycollector_keycollector_owner_keycollector_roler<   r=   r;   r[   r\   r   r]   no_fallbackr^   )
 dispatch.callback_owner_enforcerr
   r   r   r`   rb   rZ   r:   tupler   )r2   r   rH   rd   re   rf   rg   r;   r<   r=   r[   r\   r   rQ   r]   r^   rR   rG   
OWNER_FAIL
OWNER_HOLD
OWNER_PASSr`   rb   baseowner	composites                             r    guard_dispatch_with_ownerrq     s    D  1/#D ##)#52!#/%!9";)$?'3E(O'((/#E& ||tu}}
:		$,,.	.%--:2M			%--:"=			!!r"   )r[   r\   r   r]   rh   r^   	actor_keyis_executor_self_sessionc                   ddl m}m} ddlm} ddlm} |t        |      n
t        |      } || |||||||||	|
|||      } ||||||      }|j                  t        k(  xr |j                  t        k(  }|j                  t        k(  r0|j                  t        k7  rddl m
} |s |d|j                          ||       |||fS )	u!  §5.C callback registration helper guard — 등록 직전 fail-closed.

    The normal/fallback callback registration path MUST route through this
    gate before any ``cokacdir --cron`` is issued (9-R.1 mediated-call). It
    chains the anu_v3 runtime owner validator (owner/key/role) AND the
    self-collector runtime guard (executor self-session owning its own
    collector). On a non-PASS verdict it BOTH returns blocked AND raises
    ``CallbackRegistrationBlocked`` via ``assert_registration_permitted`` so a
    caller that ignores the return value still cannot register a self-owned
    callback (§5.C "mismatch -> 등록 안 함" — structural, not advisory).

    Returns ``(validation_result, self_guard_result, registration_allowed)``.
    Layer A: ZERO cron/dispatch/subprocess.
    r   )assert_registration_permittedvalidate_callback_owner_runtime)guard_self_collector_sessionra   rc   rd   re   rr   rg   rs   )CallbackRegistrationBlockedz7callback registration blocked by self-collector guard: )anu_v3.callback_owner_validatorru   rv   anu_v3.self_collector_guardrw   ri   rb   rj   r   r   ry   classification)r:   rd   re   rf   rg   r;   r<   r=   r[   r\   r   r]   rh   r^   rr   rs   ru   rv   rw   rb   keysval
self_guardregistration_allowedry   s                            r    guard_callback_registrationr   i  s    B IA&25?>N8OD
)!#/%!9";)$?/C  .!#%!9J 	t:
 2 2d :  {{dz11T9	
 $-I,,-/  "#&
000r"   )r]   r^   c               b    ddl m} ddlm} |t	        |      n
t	        |      } || |||      S )ur  §5.D authoritative verdict selector 실 runtime 결선.

    Collector 회수단계가 verdict 를 확정하기 직전 반드시 경유한다. self-chain
    verdict 는 QUARANTINED·영구 비권위, independent ANU verdict 만
    authoritative (회장 §2.5/§2.6/§5.D). Returns the
    ``AuthoritativeSelectionResult``. Layer A: ZERO cron/dispatch/subprocess.
    r   )select_authoritative_verdictra   )r:   r]   r^   )%anu_v3.authoritative_verdict_selectorr   ri   rb   rj   )recordsr:   r]   r^   r   rb   r}   s          r    $select_runtime_authoritative_verdictr     s<     B&25?>N8OD'/	 r"   )r[   r\   r   rQ   r]   r^   rR   rG   rr   rs   is_followup_dispatchc                   ddl m}m} t        di d| d|d|d|d|d|d	|d
|d|d|	d|
d|d|d|d|d|d|d|\  }}} ||||||      } |||||      }t        ||j
                  |j
                  fv rt        }nL|t        k(  rt        }n<|t        k(  r-|j
                  t        k(  r|j
                  t        k(  rt        }nt        }|||||fS )up  §4 우선순위 2~5 통합 실 dispatch-path runtime gate.

    Chains: byte-0 ``guard_dispatch`` (clause+4-tuple+ledger) ->
    ``guard_dispatch_with_owner`` owner pin -> anu_v3 self-collector +
    self-dispatch runtime guards. Any FAIL -> FAIL; any HOLD w/o FAIL ->
    HOLD; else PASS. Returns
    ``(base, owner, self_collector, self_dispatch, composite)``.
    r   )rw   guard_self_dispatchr2   r   rH   rd   re   rf   rg   r;   r<   r=   r[   r\   r   rQ   r]   r^   rR   rG   rx   )rd   rr   r   rs   r.   )r{   rw   r   rq   r
   r   r   r   )r2   r   rH   rd   re   rf   rg   r;   r<   r=   r[   r\   r   rQ   r]   r^   rR   rG   rr   rs   r   rw   r   rn   ro   rp   scsdfinals                                r    $guard_dispatch_runtime_authoritativer     sc   @
 7   "	
 $ 0 & * ": #<  %@ 2 0   0!" #$ $%D%( 
&!#%!9
B 
!1!9	
B 	2::rzz22	d		d	rzzT1bjjD6HB%%r"   )r2   r   r'   r   )rH   Optional[Callback4Tuple]r'   r   )r2   r   r   r   rH   r   r   r   rQ   r   r'   r   )r2   r   r   r   rH   r   rd   r   re   r   rf   Optional[str]rg   r   r;   r   r<   r   r=   r   r[   r   r\   r   r   r   rQ   r   r^   r   )r:   r   rd   r   re   r   rf   r   rg   r   r;   r   r<   r   r=   r   r[   r   r\   r   r   r   rh   r   r^   r   rr   r   rs   Optional[bool])r:   r   r^   r   )"r2   r   r   r   rd   r   re   r   rf   r   rg   r   r;   r   r<   r   r=   r   r[   r   r\   r   r   r   rQ   r   r^   r   rr   r   rs   r   r   r   )__doc__
__future__r   dataclassesr   r   typingr   r   %dispatch.executor_completion_contractr   r	    dispatch.spec_template_validatorr
   r   r   r   rT   PATH_DISPATCH_PYPATH_CRON_DIRECT	frozensetrU   r   r3   rP   rZ   rq   r   r   r   r.   r"   r    <module>r      s_  6 # ( !  8 ( ) )+;<= 
 
 
623333v "' $kk k %	k
 k k kL (-!& $ $'P"P" P" %	P"
 P" P" 'P" P" P" ,P"  -P" P" "&P" P" P"" #P"P (-& $#/3#O1O1 O1 	O1
 'O1 O1 O1 ,O1  -O1 O1 "&O1 O1 O1 O1  !O1" -#O1l  $ 
 P (-!& $ $#/3!&-N&N& N&
 N& N& 'N& N& N& ,N&  -N& N& "&N& N& N&" #N&( )N&* -+N&, -N&r"   