
    3j+P                       U 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	 ddl
mZmZmZmZmZmZ dZded	<   d
Zded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   de d Zded!<    G d" d#e      Z  G d$ d%e!      Z"	 	 	 	 d1d&Z#e G d' d(             Z$dd)	 	 	 	 	 d2d*Z%e G d+ d,             Z&d3d-Z'd4d.Z(d5d/Z)g d0Z*y)6uk	  anu_v3.coordinator_profile_binding — batch coordinator ← profile decision output 소비 seam.

task-2553+39 TRACK B (회장 GO 병렬 4트랙 Track B, 9-R.1 우선).

목표 (회장 verbatim §1):
  batch coordinator 가 policy profile engine 의 decision output
  (gate / HOLD / allowed / forbidden / completion-packet / evidence schema)을
  직접 소비하여 track 판단·통합에 활용한다.

9-R.1 (HIGH 해소, 본문 우선):
  "직접 소비" 의 결선 산물 = **이 신규 additive 모듈 자체가
  coordinator-consumable binding seam(파일레벨 contract)**. +37 entrypoint·
  +29/+30 별도모듈 선례 동일 패턴 — 신규 binding 모듈이 곧 소비 연결점이며
  frozen ``parallel_batch_coordinator.py`` / +29 registry / +30 generic
  coordinator 의 in-place 편집·import 결합 불요. "직접 소비" 달성 =
  binding 모듈 존재 + 파일레벨 contract + regression 으로
  coordinator → engine output 소비 경로 입증. 기존 coordinator 가 이 binding
  을 실 호출하는 in-place adoption 은 별도 운영단계.

설계 invariant (§3 / §5):
  - 신규 별도 모듈 (additive). engine·+29·+30·frozen coordinator 원본
    무수정. **import 결합 0** — anu_v3 import 전무, 순수 stdlib only.
  - engine decision output 은 **파일레벨 contract** 로만 소비:
    ``anu_v3.policy_profile_engine.decision.v1`` JSON 형태(파일 or dict)를
    read-only 입력으로 받는다 (engine 모듈 import·호출·mutation 0).
  - coordinator = 판단보조 소비만. closeout / merge **자동확정 0** —
    binding output 은 어떤 입력에서도 ``closeout_authority`` /
    ``merge_authority`` / ``auto_confirm`` 를 절대 True 로 내지 않는다
    (hard-pinned False, fail-closed).
  - engine 부재 / schema mismatch → fail-closed 안전 (자동확정 0,
    coordinator 가 settle 못 하도록 HOLD/UNAVAILABLE 신호).
  - fallback safety path / callback mandatory rule / runtime checkpoint
    recovery layer 약화·격상·대체 0 (이 모듈은 그 경로를 만지지 않는다).
  - 모든 decision-logic 메서드 = derive / propose / read only. 파일 I/O 는
    decision 경계 밖의 명시 hard-guarded helper 1개(`emit_binding`)에 한정.
  - NO-SCHEDULER: 스케줄러/외부 dispatch tooling 호출 0 (decision 경계 밖
    I/O 는 hard-guarded helper 1개 한정, 그 외 부작용 전무).
    )annotationsN)	dataclassfield)Path)AnyDictFinalListMappingOptionalz"anu_v3.coordinator_profile_bindingz
Final[str]BINDING_MODULEztask-2553+39.B.v1BINDING_VERSIONz%anu_v3.coordinator_profile_binding.v1BINDING_SCHEMAz(anu_v3.policy_profile_engine.decision.v1ACCEPTED_DECISION_SCHEMARESOLVED_DECISION_RESOLVEDHOLD_FOR_CHAIR_DECISION_HOLD
CONSUME_OKENGINE_DECISION_HOLDCONSUME_HOLD_ENGINERUNTIME_HOLD_OBSERVEDCONSUME_HOLD_RUNTIMEDECISION_UNAVAILABLECONSUME_UNAVAILABLEz#task-2553.parallel-batch-state.json_FROZEN_DURABLE_V1z!.coordinator-profile-binding.json_DELIVERABLE_SUFFIXz"binding_schema": ""_DELIVERABLE_MARKERc                  $     e Zd ZdZd fdZ xZS )CoordinatorProfileBindingErroruJ   binding 소비 실패. ``self.code`` = 실패 사유 코드 (fail-closed).c                L    t         |   d| d|        || _        || _        y )N[] )super__init__codemessage)selfr'   r(   	__class__s      9/home/jay/workspace/anu_v3/coordinator_profile_binding.pyr&   z'CoordinatorProfileBindingError.__init__K   s+    1TF"WI./	    )r'   strr(   r-   returnNone)__name__
__module____qualname____doc__r&   __classcell__)r*   s   @r+   r!   r!   H   s    T r,   r!   c                      e Zd ZdZy)FrozenWriteRefusedu   chair durable v1 / git-tracked / unrelated untracked 파일 write 거부.
    binding authority 는 별도 NEW untracked deliverable 이어야 한다 (§4/§5).N)r0   r1   r2   r3    r,   r+   r6   r6   Q   s    Zr,   r6   c                   t        | t              rt        |       }n4t        |       }	 |j	                  d      }	 t        j                  |      }t        |t              s"t        d	d
t        |      j                         |j                  d      }|t        k7  rt        ddt        d|d      |S # t
        $ r}t        dd| d|       |d}~ww xY w# t        j                  $ r}t        dd| d|       |d}~ww xY w)u=  C1 engine 의 decision output(``decision.v1``)을 read-only 소비.

    source = 파일 경로 또는 이미 로드된 dict (engine 모듈 import·호출 0 —
    파일레벨 contract 만). schema marker mismatch / 파일 부재 / 파싱 실패 =
    fail-closed (CoordinatorProfileBindingError, code 보존).
    utf-8encodingdecision_source_unreadableu,   engine decision output 부재/읽기 실패 z: Ndecision_source_unparsableu*   engine decision output JSON 파싱 실패 decision_not_objectu)   decision output 최상위 object 아님: schemadecision_schema_mismatchz*engine decision schema mismatch: expected z, got u@    (engine 부재/버전 mismatch — fail-closed, 자동확정 0))
isinstancer   dictr   	read_textOSErrorr!   jsonloadsJSONDecodeErrortyper0   getr   )sourceobjprawer?   s         r+   load_profile_decisionrO   Y   s6    &'"<L	++w+/C	**S/C c4 ,!7S	8J8J7KL
 	
 WWXF)),&8'*&
 ;NO
 	
 J3  	0,>qcA3G 	 ## 	0,<QCr!E 	s.   B6 C 6	C?CCD-D  Dc                      e Zd ZU dZded<   ddZddZddZddZddZ	dd	Z
dd
ZddZddZddZ	 d	 	 	 ddZddZ	 d	 	 	 ddZ	 d	 	 	 ddZy)CoordinatorProfileBindinguB  engine decision output 을 batch coordinator 가 track 판단·통합에
    그대로 소비할 수 있는 평면 contract 로 변환하는 read-only seam.

    어떤 입력에서도 closeout/merge 를 자동 확정하지 않는다 — coordinator 는
    판단보조 소비만 (확정 권한은 chair/ANU out-of-band).Dict[str, Any]decisionc                L    t        | j                  j                  dd            S )Ngoal_id r-   rS   rI   r)   s    r+   rU   z!CoordinatorProfileBinding.goal_id   s    4==$$Y344r,   c                L    t        | j                  j                  dd            S )N	goal_typerV   rW   rX   s    r+   rZ   z#CoordinatorProfileBinding.goal_type   s    4==$$["566r,   c                L    t        | j                  j                  dd            S )N
profile_idrV   rW   rX   s    r+   r\   z$CoordinatorProfileBinding.profile_id   s    4==$$\2677r,   c                L    t        | j                  j                  dd            S )NstatusrV   rW   rX   s    r+   engine_statusz'CoordinatorProfileBinding.engine_status   s    4==$$Xr233r,   c           	         g }| j                   j                  dg       xs g D ]O  }t        |t              s|j	                  t        |j                  dd            |j                  d      d       Q |S )NgatenamerV   expected)rb   rc   )rS   rI   rA   r   appendr-   )r)   outgs      r+   gate_conditionsz)CoordinatorProfileBinding.gate_conditions   sl    $&""62.4" 	<A!W%

Cfb(9$:()j(9; <	< 
r,   c                z    | j                   j                  dg       xs g D cg c]  }t        |       c}S c c}w )Nhold_trigger_conditionsrS   rI   r-   )r)   hs     r+   ri   z1CoordinatorProfileBinding.hold_trigger_conditions   s=    ""#<bAGRJ1A J 	J J   8c                z    | j                   j                  dg       xs g D cg c]  }t        |       c}S c c}w )Nallowed_actionsrj   r)   as     r+   rn   z)CoordinatorProfileBinding.allowed_actions   s=    ""#4b9?RB1A B 	B Brl   c                z    | j                   j                  dg       xs g D cg c]  }t        |       c}S c c}w )Nforbidden_actionsrj   ro   s     r+   rr   z+CoordinatorProfileBinding.forbidden_actions   s=    ""#6;ArD1A D 	D Drl   c                    | j                   j                  d      xs i }t        |t              r |j                  d      }|t	        |      S d S y )Ncompletion_packet_schemameta_schema_refrS   rI   rA   r   r-   )r)   cpsrefs      r+   completion_packet_meta_refz4CoordinatorProfileBinding.completion_packet_meta_ref   sK    mm :;Arc7#''+,C"3s88D8r,   c                    | j                   j                  d      xs i }t        |t              r |j                  d      }|t	        |      S d S y )Nevidence_schemaru   rv   )r)   evsrx   s      r+   evidence_meta_refz+CoordinatorProfileBinding.evidence_meta_ref   sK    mm 128bc7#''+,C"3s88D8r,   Nc                    | j                         }|xs i }|D cg c]  }|j                  |      s| }}| j                         t        k(  }|||t	        |xs |      ddS c c}w )Nu   engine HOLD 의미 미러 — enabled trigger 는 정의-시점 enablement, ANY trigger 런타임 관측 시 HOLD(action 0). binding 은 HOLD 판정을 전파만 하며 자동확정 0.)engine_status_holdenabled_hold_triggersruntime_fired_triggershold	semantics)ri   rI   r_   r   bool)r)   runtime_signalstriggerssigcfiredengine_holds          r+   evaluate_holdz'CoordinatorProfileBinding.evaluate_hold   sw     //1#$3q
33((*n<"-%-&+-.N

 
	
 4s
   A$A$c                j   | j                         | j                         | j                         | j                         | j	                         D cg c]  }|d   	 c}d| j                         | j                         | j                         | j                         | j                         dddddS c c}w )u  batch coordinator 가 track 별 gate/hold/allowed/forbidden/
        packet/evidence 를 그대로 소비할 수 있는 평면 표현.

        **자동확정 0 invariant**: closeout_authority / merge_authority /
        auto_confirm 는 입력과 무관하게 hard-pinned False. coordinator 는
        이 view 를 판단보조로만 쓰고 settle/merge 권한은 갖지 않는다.rb   u)   AND — ALL conditions must hold for PASSdecision_consumer_onlyF)rU   rZ   r\   r_   gate_condition_namesgate_semanticsri   rn   rr   ry   r}   coordinator_rolecloseout_authoritymerge_authorityauto_confirm)
rU   rZ   r\   r_   rg   ri   rn   rr   ry   r}   )r)   rf   s     r+   track_consumption_viewz0CoordinatorProfileBinding.track_consumption_view   s     ||~)//+!//18<8L8L8N$O1QvY$OI'+'C'C'E#335!%!7!7!9*.*I*I*K!%!7!7!9 8"'$!!
 	

 %Ps   B0c                    | j                  |      }| j                         }|d   r	t        }d}n3|d   rt        }d|d    d}n|t        k(  r	t
        }d}nt        }d|d}||d	d
d
d
|dS )u%  engine decision output 소비 결과를 coordinator 판단보조 신호로
        derive. 어떤 경로에서도 auto_confirm/merge/closeout 확정 0.

        - engine status HOLD_FOR_CHAIR  → ENGINE_DECISION_HOLD (안전)
        - 런타임 HOLD trigger 관측        → RUNTIME_HOLD_OBSERVED (안전)
        - 그 외 RESOLVED                  → CONSUME_OK (판단보조 소비 가능,
          그래도 closeout/merge 자동확정은 절대 0)
        - status 미상                     → DECISION_UNAVAILABLE (fail-closed)
        r   uE   engine decision status = HOLD_FOR_CHAIR — coordinator 소비 보류r   u   runtime HOLD trigger 관측: u    — coordinator 소비 보류u   engine RESOLVED — coordinator 가 gate/allowed/forbidden 을 판단보조로 소비 가능 (closeout/merge 자동확정은 여전히 0)u   engine decision status 미상(u,   ) — fail-closed, coordinator settle 불가judgment_assist_onlyFsignalreason	authorityr   r   r   r   )r   r_   r   r   r   r   r   )r)   r   r   r^   r   r   s         r+   consumption_decisionz.CoordinatorProfileBinding.consumption_decision   s     !!/2##%$%(F\F*+)F/5M0N/O P0 1  ))F] 
 )F0
 ;, - 
 /!"'$
 	
r,   c                    t         t        t        t        d| j                  j                  d      | j                  j                  d      | j                         | j                  |      dd
S )Nz\read-only: derive/propose/read only; zero execute/confirm/write/merge/cron/closeout (9-R.1).engineengine_versionul   coordinator=판단보조 소비만; closeout/merge 자동확정 0 (hard-pinned, 모든 입력에서 불변).)
binding_schemabinding_modulebinding_versionconsumed_decision_schemadecision_logicsource_enginesource_engine_versionr   r   auto_confirm_invariant)r   r   r   r   rS   rI   r   r   )r)   r   s     r+   build_bindingz'CoordinatorProfileBinding.build_binding  sf     -,.(@E "]]..x8%)]]%6%67G%H&*&A&A&C$($=$=o$N=
 	
r,   )r.   r-   )r.   zList[Dict[str, Any]])r.   z	List[str])r.   zOptional[str])N)r   Optional[Mapping[str, Any]]r.   rR   )r.   rR   )r0   r1   r2   r3   __annotations__rU   rZ   r\   r_   rg   ri   rn   rr   ry   r}   r   r   r   r   r7   r,   r+   rQ   rQ      s    H 5784JBD >B
:
	
(
8 >B+
:+
	+
^ >B
:
	
r,   rQ   )r   c               .   	 t        |       }t        |      j                  |      S # t        $ rd}t        t        t        t
        dddddddddt        d|j                   d|j                   d	ddddg g dd
ddd|j                  dcY d}~S d}~ww xY w)u  batch coordinator → profile decision output 소비의 단일 callable
    entrypoint. engine decision output(파일레벨 contract)을 read-only 로
    소비해 coordinator-consumable binding contract 를 반환한다.

    engine 부재/mismatch 는 fail-closed safe binding 으로 변환(예외를
    coordinator 가 settle 신호로 오인하지 않도록 DECISION_UNAVAILABLE).
    u/   read-only fail-closed (engine 부재/mismatch).Nr   FUNAVAILABLE)r   r   r   r   r_   r#   r$   r   )r   r   r   r   r   ug   coordinator=판단보조 소비만; closeout/merge 자동확정 0 (fail-closed 경로에서도 불변).T)r   r   r   r   r   r   r   r   r   r   fail_closed
error_code)rO   r!   r   r   r   r   r   r'   r(   rQ   r   )rJ   r   rS   rN   s       r+   consume_for_coordinatorr   9  s    "
(0D %X.<<_MMC *  
,,.(@O!%)$<&+#( %!.' .affXR		{33 %&+#(!&35UT	%8  &&=
 	
 
s   ' 	BAB	BBc                  4    e Zd ZU ded<    ee      Zded<   y)BindingFixturerR   rS   )default_factoryr   N)r0   r1   r2   r   r   rB   r   r7   r,   r+   r   r   n  s    &+D&AO^Ar,   r   c           	         t        j                  t        |       j                  d            }t	        t        |d         t        |j                  di                   S )Nr9   r:   rS   r   )rS   r   )rE   rF   r   rC   r   rB   rI   )fixture_pathdatas     r+   load_binding_fixturer   t  sQ    ::d<(22G2DEDd:&'TXX&7<= r,   c                ^   	 t        j                  ddt        | j                        ddgdd      }|j                  dk7  ry|j
                  j                         }t        j                  dd|d	d
t        | j                               gdd      }|j                  dk(  S # t        $ r Y yw xY w)Ngitz-Cz	rev-parsez--show-toplevelT)capture_outputtextr   Fzls-filesz--error-unmatch)	
subprocessrunr-   parent
returncodestdoutstripresolve	Exception)rL   topreporcs       r+   _is_git_trackedr     s    nnD#ahh-6GHd
 >>Qzz!^^D$
,=s199;?OPd
 }}!! s   ?B  AB   	B,+B,c                   t        |      }|j                  t        k(  rt        d      t	        |      rt        d| d      |j                         rK|j                  j                  t              }|s	 t        |j                  d      v }|st        d| d      |j                  j                  d	d	
       |j                  t        j                   | dd      dz   d       |S # t        t        f$ r d}Y ow xY w)uY  NEW untracked binding authority 파일 write. decision component 아님 —
    runner/ANU 가 수행하는 명시 I/O (9-R.1 경계 밖).

    Hard write-guard (§4/§5 — +30 가드 미러, 무관 파일 절대 clobber 0):
      * chair durable v1 name              -> REFUSE (byte-0 immutable)
      * git-tracked path                   -> REFUSE (tracked HEAD invariant)
      * untracked & non-existent           -> ALLOW  (NEW deliverable)
      * untracked & existing sanctioned    -> ALLOW  (idempotent re-emit)
      * untracked & existing non-deliver.  -> REFUSE (무관 파일 보호)
    uo   refusing to write chair durable v1 (§5 byte-0); binding authority MUST be a separate NEW untracked deliverablez#refusing to write git-tracked path uA    (§5 tracked HEAD invariant — only NEW untracked deliverables)r9   r:   Fz9refusing to overwrite existing untracked non-deliverable zR (only a NEW untracked path or this seam's own binding deliverable may be written)T)parentsexist_ok   )ensure_asciiindent
)r   rb   r   r6   r   existsendswithr   r   rC   rD   UnicodeDecodeErrorr   mkdir
write_textrE   dumps)bindingout_pathre   
sanctioneds       r+   emit_bindingr     s$    x.C
xx%% E
 	
 s 1# 7= =
 	
 zz|XX&&':;
#0CMM$ 5B 5 

 $K% 67 
 JJTD1NN

7q9D@   J /0 #"
#s   6C* *C>=C>)r   r   r   r   r   r   r   r   r!   r6   rQ   r   rO   r   r   r   )rJ    'str | Path | Mapping[str, Any]'r.   rR   )rJ   r   r   r   r.   rR   )r   'str | Path'r.   r   )rL   r   r.   r   )r   zMapping[str, Any]r   r   r.   r   )+r3   
__future__r   rE   r   dataclassesr   r   pathlibr   typingr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   
ValueErrorr!   RuntimeErrorr6   rO   rQ   r   r   r   r   r   __all__r7   r,   r+   <module>r      sk  %L #   (  < <A
 A1 1D
 D (R * Q ", J +-
 - &
J %"8 Z 8#: j :"8 Z 8 "G J F"E Z E$77Gq"I Z IZ Z Z(,((\ k
 k
 k
h 48/N,/N 1/N 	/Nj B B B
$*Zr,   