
    3jj                       d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	 ddl
mZ ddlmZmZmZmZ ddlZdZdZd	Zd
ZdZdZdZdZeeeeeeefZdZdZdZeZdZ e eeh      Z! ed       G d d             Z"e G d d             Z#e G d d             Z$d$dZ%ef	 	 	 	 	 d%dZ&ef	 	 	 	 	 d&dZ'd'dZ(d(dZ)d)d Z*d*d+d!Z+g d"Z,e-d#k(  r e. e+             y),u	  anu_v3.batch_hold_adjudicator — batch-level consolidated HOLD adjudicator
(회장 BATCH_LEVEL_HOLD_ADJUDICATION 시스템화 Track A · task-2610).

회장 verbatim 목표:

  병렬 작업 중 Codex HIGH/HOLD 가 발생해도 개별 track 만 보고 회장에게
  멈추지 말고, batch 전체 context 를 모은 뒤 Critical7 인지 non-critical
  remediation 인지 자동 분류하고, Critical7 이 아니면 ANU-Codex loop 로
  자동 remediation 하여 all-settled 까지 진행한다.

본 모듈의 단일 책임 (Track A):

  * 모든 track 의 상태(collector 기록·independent-ANU verdict·Track B
    Critical7 분류·dependency·dispatch)를 **하나로 모아** consolidated
    adjudication 을 수행한다.
  * 분류 taxonomy (회장 verbatim 7종):

      AUTHORITATIVE_PASS · HOLD_CANDIDATE · AUTO_REMEDIATION_HOLD ·
      CHAIR_HOLD · WAITING_FOR_DEPENDENCY · NOT_STARTED_BY_DESIGN ·
      DISPATCH_NOT_RECEIVED

  * **개별 collector 는 HOLD_CANDIDATE 만 기록**한다. collector 가 최종
    분류(AUTHORITATIVE_PASS/CHAIR_HOLD 등)를 자칭하면 그 자칭은 *무시* 되고
    본 batch-level adjudicator 가 재도출한다 (collector self-finalization
    금지 — §3/§5).
  * **최종 분류는 본 batch-level adjudicator 만** 권위가 있다.
  * Track B classifier 결과(Critical7 여부)를 입력으로 받아
    **CHAIR_HOLD vs AUTO_REMEDIATION_HOLD** 를 확정한다. classifier
    결과가 없으면 HOLD_CANDIDATE 로 fail-closed (자동 PASS·자동 수렴 금지).
  * shared invariant 파손 또는 Critical7 = 전체 CHAIR_HOLD (회장 보고).
    그 외 non-Critical HOLD 는 AUTO_REMEDIATION_HOLD 로 자동 수렴 —
    회장 보고 0.
  * independent-ANU verdict 만 authoritative. self-chain PASS 자칭만으로
    AUTHORITATIVE_PASS 부여 금지(§5.D fail-closed → HOLD_CANDIDATE).

Layer A / NO-CRON: 순수 분류 함수. ZERO cron / dispatch / subprocess /
cokacdir / network / 파일 쓰기(엔트리포인트 CLI 의 --output 명시 경로 제외).
회수·발사·등록·remediation 실행 0 — *판정만* 한다. callback owner=독립 ANU
key (executor self key 금지·+49 정본) 는 본 모듈이 강제하지 않고
``anu_v3.callback_owner_validator`` 가 등록 직전 강제한다(중복 구현 금지).
    )annotationsN)asdict	dataclassfield)Path)DictListOptionalSequencez!anu_v3.batch_hold_adjudication.v1AUTHORITATIVE_PASSHOLD_CANDIDATEAUTO_REMEDIATION_HOLD
CHAIR_HOLDWAITING_FOR_DEPENDENCYNOT_STARTED_BY_DESIGNDISPATCH_NOT_RECEIVEDPASSFAILHOLD_FOR_CHAIR)c119085addb0f8b7T)frozenc                     e Zd ZU dZded<   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Zded<   dZded<   dZded<   dZded<   dZded<   y)TrackHoldInputuX  One track's consolidated raw state fed to the adjudicator.

    Every signal is *evidence*, never a final verdict — the adjudicator
    re-derives the classification. ``collector_recorded`` carries only what
    an individual collector is permitted to emit (HOLD_CANDIDATE); any other
    self-finalization claim is recorded and ignored.
    strtrack_idtask_idTbooldispatch_receivedFnot_started_by_designdependency_unmetshared_invariant_breachhold_candidateNzOptional[str]collector_recorded collector_keyexecutor_keycollector_role"collector_session_is_executor_selfauthoritative_verdict authoritative_is_independent_anuclassifier_presentclassifier_is_critical7classifier_categorydetail)__name__
__module____qualname____doc____annotations__r   r   r    r!   r"   r#   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.        4/home/jay/workspace/anu_v3/batch_hold_adjudicator.pyr   r   Z   s     ML"t""'4'"d"$)T) ND (,,M3L#NC/4&4 ,0=/-2$d2  %$$)T)!!FCr5   r   c                  f    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<    ee	      Zd
ed<   y)TrackAdjudicationr   r   r   classificationr   chair_escalationauto_remediationsettleddefault_factory	List[str]reasonsN)r/   r0   r1   r3   r   listr@   r4   r5   r6   r8   r8   }   s2    MLMt4GY4r5   r8   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<    ee      Zded<   ddZdddZy)BatchHoldAdjudicationr   schemaverdictbatch_classificationr   all_settledchair_escalation_requiredauto_remediation_requiredcritical7_presentr!   inttrack_countzDict[str, int]classification_countszList[TrackAdjudication]tracksr=   r?   r@   c                    t        |       }|S N)r   )selfds     r6   to_dictzBatchHoldAdjudication.to_dict   s    4Lr5   c                N    t        j                  | j                         d|      S )NF)ensure_asciiindent)jsondumpsrS   )rQ   rV   s     r6   to_jsonzBatchHoldAdjudication.to_json   s    zz$,,.uVLLr5   N)returndict)   )rV   rK   rZ   r   )	r/   r0   r1   r3   r   rA   r@   rS   rY   r4   r5   r6   rC   rC      s\    KL####!!))##t4GY4Mr5   rC   c                l   |D ch c]  }|s|	 }}t        | j                        xrI | j                  |v xr9 | j                  | j                  k7  xr | j                  dk(  xr | j                   }| j                  s| j                  s| j                  rt        | j
                        xr |S yc c}w )u  Re-derive independence from owner identity — claim is never trusted.

    Independent iff: track flags it independent AND collector_key is a
    configured ANU key AND collector_key != executor_key AND role==ANU AND
    the session is NOT the executor self-session (§5.D / +49 정본). A bare
    ``authoritative_is_independent_anu=True`` claim without a provable owner
    identity is downgraded to self-chain (fail-closed).
    ANUF)r   r%   r&   r'   r(   r*   )tanu_keyskkeysetowner_provens        r6   _independent_anurd      s     "'AQa'F'Q__ 	5OOv%	5OOq~~-	5 %	5 444  	!..A,<,<A667HLH (s
   B1B1c           	        g }| j                   2| j                   t        k7  r|j                  d| j                   d       | j                  r;|j                  d       t	        | j
                  | j                  t        ddd|      S | j                  s;|j                  d       t	        | j
                  | j                  t        ddd|      S | j                  r;|j                  d       t	        | j
                  | j                  t        ddd|      S | j                  r;|j                  d	       t	        | j
                  | j                  t        ddd|      S t        | |      }| j                  xs d
j!                         }| j"                  xs | j                   t        k(  xs |xr |dv }|r| j$                  s;|j                  d       t	        | j
                  | j                  t&        ddd|      S | j(                  rM|j                  d| j*                  xs dd       t	        | j
                  | j                  t        ddd|      S |j                  d| j*                  xs dd       t	        | j
                  | j                  t,        ddd|      S |dk(  rx|r;|j                  d       t	        | j
                  | j                  t.        ddd|      S |j                  d       t	        | j
                  | j                  t&        ddd|      S |j                  d       t	        | j
                  | j                  t&        ddd|      S )a  Re-derive the authoritative classification for a single track.

    Precedence is fail-closed: a track only reaches AUTHORITATIVE_PASS via a
    provable independent-ANU PASS; everything ambiguous degrades to
    HOLD_CANDIDATE rather than silently passing.
    zcollector self-finalization u    IGNORED — individual collector may record only HOLD_CANDIDATE; final classification is re-derived by the batch-level adjudicator (회장 §3/§5).ui   shared invariant breach detected -> CHAIR_HOLD (회장 §6: shared invariant 파손 = 전체 CHAIR_HOLD).TF)r:   r;   r<   r@   uq   dispatch not received — track has no executor session; DISPATCH_NOT_RECEIVED (NOT a HOLD, NOT chair-escalated).u   track is NOT_STARTED_BY_DESIGN (event-gated / by-design idle) — terminal-good, counts toward all-settled, no chair, no remediation.u   dependency unmet — predecessor durable-success EVENT absent; WAITING_FOR_DEPENDENCY (event-driven, NOT fixed-time, NOT chair-escalated).r$   )r   HOLDr   u   HOLD detected but Track B critical7/codex-high classifier result ABSENT — cannot finalize CHAIR vs AUTO; remains HOLD_CANDIDATE (fail-closed: NO auto-pass, NO auto-converge without classifier).z(Track B classifier: Critical7 (category=unspecifieduK   ) -> CHAIR_HOLD (회장 §6: Critical7 = 전체 CHAIR_HOLD, 회장 보고).z+Track B classifier: non-Critical (category=u^   ) -> AUTO_REMEDIATION_HOLD — ANU-Codex loop 자동 수렴 (회장 §3/§6: 회장 보고 0).r   uh   independent-ANU authoritative verdict = PASS -> AUTHORITATIVE_PASS (회장 §5.D: independent ANU only).u   PASS claimed by self-chain (no provable independent-ANU ownership) — confirming PASS from a self-chain verdict alone is FORBIDDEN (§5.D); degrades to HOLD_CANDIDATE (fail-closed).u   no provable independent-ANU PASS and no resolved HOLD signal — fail-closed default HOLD_CANDIDATE (final classification deferred to a later batch-level adjudication once evidence arrives).)r#   COLLECTOR_SIGNAL_HOLD_CANDIDATEappendr!   r8   r   r   r   r   r   r   r   r    r   rd   r)   upperr"   r+   r   r,   r-   r   r   )r_   r`   r@   independentav	hold_paths         r6   adjudicate_trackrn      sy    G 	
(  $CC*1+?+?*B C   	
 	  <	
 !JJ		:!E7
 	
 G	
 !JJ		#8"U7
 	
 		

 !JJ		#8"U'
 	
 	 	

 !JJ		#9"U7
 	
 #1h/K

!
!
'R	.	.	0B
 	
 	F#BB	FDB"DD 
 ##NN' %

AII~!&w 
 $$NN:((9M< =NN
 %

AIIz!%w 
 	9$$58 9  	
 !JJ		#8"T7
 	
 
V|NNK %

AII'9!&g 
 	K	

 !JJ		>"U7
 	
 NN	F
 	

AII~w r5   c                J   | D cg c]  }t        ||       }}t        D ci c]  }|d }}|D ].  }|j                  |j                  d      dz   ||j                  <   0 t	        d | D              t	        fd|D              xs t	        d | D              }t	        d |D              }t	        d |D              }	t        |      xr t        d |D              }
g }|s|sr3t        }t        }r|j                  d	       |ro|j                  d
       n]|
rt        }t        }|j                  d       n=|	rt        }t        }|j                  d       nt        }t        }|j                  d       t        t         |||
||	|t#        |      |||      S c c}w c c}w )u1  Consolidated batch adjudication over ALL track states.

    회장 §6: shared invariant 파손 또는 Critical7 = 전체 CHAIR_HOLD.
    그 외 non-Critical HOLD 는 AUTO_REMEDIATION_HOLD 자동 수렴(회장 보고 0).
    all-settled = 모든 track 이 AUTHORITATIVE_PASS / NOT_STARTED_BY_DESIGN.
    r      c              3  4   K   | ]  }|j                     y wrP   )r!   .0r_   s     r6   	<genexpr>z#adjudicate_batch.<locals>.<genexpr>g  s      &'!!   c              3  N   K   | ]  }|j                   t        k(  xr    y wrP   )r9   r   )rs   tashared_breachs     r6   rt   z#adjudicate_batch.<locals>.<genexpr>j  s/       	Z'=,==s   "%c              3  P   K   | ]  }|j                   xr |j                     y wrP   )r+   r,   rr   s     r6   rt   z#adjudicate_batch.<locals>.<genexpr>m  s$     PAQ!!?a&?&??Ps   $&c              3  4   K   | ]  }|j                     y wrP   )r:   rs   rw   s     r6   rt   z#adjudicate_batch.<locals>.<genexpr>n  s     A,,Aru   c              3  4   K   | ]  }|j                     y wrP   )r;   r{   s     r6   rt   z#adjudicate_batch.<locals>.<genexpr>o  s     @++@ru   c              3  @   K   | ]  }|j                   t        v   y wrP   )r9   _SETTLED_GOODr{   s     r6   rt   z#adjudicate_batch.<locals>.<genexpr>p  s       */1]**s   u]   shared invariant 파손 track 존재 -> 전체 CHAIR_HOLD (회장 §6). 회장 보고 필요.uw   Critical7 track 존재 -> 전체 CHAIR_HOLD (회장 §6). 회장 보고 필요. 그 외 non-Critical 은 자동 수렴.u^   모든 track AUTHORITATIVE_PASS / NOT_STARTED_BY_DESIGN — batch all-settled. chair 보고 0.u   non-Critical HOLD 존재 -> AUTO_REMEDIATION_HOLD 자동 수렴 (ANU-Codex loop). Critical7 0 · 회장 보고 0 · 진행 트리거는 event-driven (fallback/dead-man/fixed-time 아님).u   미해결 HOLD_CANDIDATE / WAITING_FOR_DEPENDENCY / DISPATCH_NOT_RECEIVED 존재 — batch 미정착이나 chair-escalation 불요(Critical7·invariant 파손 0). 추가 evidence(EVENT) 도착 시 재-adjudication.)rD   rE   rF   rG   rH   rI   rJ   r!   rL   rM   rN   r@   )rn   CLASSIFICATIONSgetr9   anyr   allr   r   ri   r   r   r   r   r   rC   ADJUDICATION_SCHEMAlen)rN   r`   r_   	per_trackccountsrw   	critical7chair_requiredauto_requiredrG   r@   rE   rF   rx   s                 @r6   adjudicate_batchr   W  s    9??1!!X.?I?,;<qad<F< I$*JJr/@/@!$Dq$Hr  !I  +1 M    Q 
PP	P  AyAAN@i@@My/ c *5>* 'K Gm )NN6 NNP 
11	
 
4B	
 - 	
 !"1"0"/# -	N$ w @<s
   F
F c           
         t         j                  j                         }t        di | j                         D ci c]  \  }}||v s|| c}}S c c}}w )Nr4   )r   __dataclass_fields__keysitems)rR   allowedra   vs       r6   _track_from_dictr     sF    11668GIaggiHda1<QTHIIHs   AAc                    | j                  dg       D cg c]  }t        |       }}| j                  d      xs t        }t        ||      S c c}w )zReal entrypoint: a {"tracks":[...], "anu_keys":[...]} payload in,
    a validated BatchHoldAdjudication out. No mocks, no I/O side effects.rN   r`   )r   r   DEFAULT_ANU_KEYSr   )payloadxrN   r`   s       r6   adjudicate_from_payloadr     sO     ,3;;x+DEaq!EFE{{:&:*:HFH-- Fs   Ac                   
 g 
	 	 	 	 dG
fd} dg}d} | d|ddddd|d	d
gdt         t        dd        | d|dddddddgdt        t        ddd        | d|dddddddddddd|d	d
gdt        t
        dd        | d|ddddgdt        t
        dd        | d|dddddgdt        t        dd         | d!|dddd||d	dd"gdt        t        d#        | d$|d%d&dd'd(d)dd*d+d,dd-gdt        t        dd.       t        |ddd/d0gd      }|j                  t        k7  r
j                  d1|j                           | d2|d3dddd4gdt        t
        dd        | d5|ddddd6gdt        t        dd.       t        t              j                         j                  j                  d7z  d8z  }t        j                  |j!                  d9:            }t        |dddddddgd      j#                         }	 t%        j&                  ||       t-        |      }d=|d><   d?|d@<   	 t%        j&                  ||       
j                  dA       
r-
D ]'  }	t.        j0                  j3                  dB|	z   dCz          ) yDt.        j0                  j3                  dE       yF# t$        j(                  $ r(}
j                  d;|j*                          Y d<}~d<}~ww xY w# t$        j(                  $ r Y w xY w)Hu   Drive the REAL entrypoint over real cases (no mocks). Non-zero exit on
    any mismatch — this is the regression backstop callable in-allowlist
    (Track E owns tests/regression/test_batch_hold_adjudication.py).c                Z   t        |      }|j                  |k7  s|j                  |k7  r3j                  |  d|j                   d|j                   d| d| 	       |j	                         D ];  \  }}t        ||      |k7  sj                  |  d| dt        ||      d|       = y )Nz: got verdict=/z want z: =)r   rE   rF   ri   r   getattr)	namer   want_verdict
want_classwantrra   r   failuress	           r6   expectz_selfcheck.<locals>.expect  s    #G,99$(>(>*(LOO&qyyk13I3I2J K$~Qzl4 JJL 	MDAqq!}!4&1#Qwq!}.?vaU KL	Mr5   r   c38fb9955616e24dall_passAz	task-2610r   Tr^   )r   r   r)   r*   r%   r&   r'   )r`   rN   F)rG   rH   non_critical_autoBz	task-2611test_harness_invariant)r   r   r"   r+   r,   r-   )rI   rH   rJ   critical7_chairCz	task-2612
credential)rH   rJ   invariant_chairDz	task-2613)r   r   r!   )rH   r!   hold_no_classifier)r   r   r"   r+   )rH   rI   self_chain_pass_quarantined)r   r   r)   r*   r%   r&   r'   r(   )rH   dep_and_designEz	task-2614)r   r   r    Fz	task-2615)r   r   r   Gz	task-2999)r   r   r   )rH   rG   r   )r   r   r#   z@collector_self_final: claimed AUTHORITATIVE_PASS not ignored ->  critical7_flag_no_pertrack_chairX)r   r   r+   r,   #bare_independence_claim_fail_closed)r   r   r)   r*   schemasz#batch_hold_adjudication.schema.jsonutf-8encodingz;schema_valid_c7: real critical7 output rejected by schema: Nr   rE   r   rF   zschema_reject_invariant_violation: invariant-violating output (critical7_present=true, verdict=FAIL) was NOT rejected by schemazSELFCHECK FAIL: 
rp   z)SELFCHECK PASS: 11 real-entrypoint cases
r   )
r   r   r   r[   r   r   r   r   rZ   None)r   r   r   r   r   r   r   r   rF   ri   r   __file__resolveparentrW   loads	read_textrS   
jsonschemavalidateValidationErrormessager[   sysstderrwrite)r   anu	exec_selfr8_schema_path_schema	_valid_c7e_badfr   s             @r6   
_selfcheckr     s4    H
M
M+/
M 
C"I &,150)$	&%
 	 	 d"' #4(-$<>%
 	 	#"&% #4(,$02 &,150)$	&
%
 
	 	
"&$$ (,.%
 	 	
"& #5B%
 	 	n"'5 %&,15'$379%
 	 	n !%'&*,"')%
 	 	n"'U 
!c[3	5> " 
B 
.0))*,	
 *#'DJ%
 	 	
"'4 -&,157%
 	
 	n"'U	 >))+22999:Ljj///ABG'S[t$( ,	.E ) 
 		 
Iw/
 	?DDO#:D	 D'*P	
  	<AJJ/!3d:;	<JJAB+ %% 
I!))U	
 	

 %% s*   J- 7'K+ -K( K##K(+L Lc                n   t        j                  dd      }|j                  dd       |j                  dd       |j                  d	d
d       |j                  |       }|j                  r
t               S |j                  s|j                  d       t        j                  t        |j                        j                  d            }t        |      }|j                         }|j                  rddlm}  ||j                  |dz   d        yt"        j$                  j'                  |dz          y)Nzanu_v3.batch_hold_adjudicatorz4batch-level consolidated HOLD adjudicator (Track A).)progdescriptionz--inputz"path to a batch-state JSON payload)helpz--outputz#path to write the adjudication JSONz--selfcheck
store_truez$run real-entrypoint regression cases)actionr   z--input or --selfcheck requiredr   r   r   )atomic_guarded_writer   )r   )argparseArgumentParseradd_argument
parse_args	selfcheckr   inputerrorrW   r   r   r   r   rY   outputanu_v3.cli_output_path_guardr   r   stdoutr   )argvpar   resultoutr   s          r6   _mainr   |  s   ,J	A NN9#GNHNN:$INJNN=>  @	TA{{|77	12jjagg00'0BCG$W-F
..
Cxx 	FQXXsTz4@  	

t$r5   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r8   rC   rn   r   r   __main__)r_   r   r`   Sequence[str]rZ   r   )r_   r   r`   r   rZ   r8   )rN   zSequence[TrackHoldInput]r`   r   rZ   rC   )rR   r[   rZ   r   )r   r[   rZ   rC   )rZ   rK   rP   )r   zOptional[Sequence[str]]rZ   rK   )/r2   
__future__r   r   rW   r   dataclassesr   r   r   pathlibr   typingr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rh   r   	frozensetr~   r   r8   rC   rd   rn   r   r   r   r   r   __all__r/   
SystemExitr4   r5   r6   <module>r      s  (R #   
 0 0  1 1 9  * !/ 
1 / /   ! #1  )  -/DEF $  D 5 5 5 M M M,6 /\\\ \B /R$RR RlJ
.D:. z
UW
 r5   