
    aj[                       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 ddl	m
Z
 ddlmZmZ dZd	Zd
ZdZdZdZ G d dee
      Z G d dee
      Z G d dee
      Z G d dee
      Z G d de      Ze G d d             Zd,dZd-dZd.dZd.dZd/dZ d0dZ!d1d Z"d1d!Z#d1d"Z$d2d#Z%e G d$ d%             Z&d3d&Z'e G d' d(             Z(e G d) d*             Z)g d+Z*y)4u  utils/anu_codex_bounded_loop.py — task-2592 Phase 2 구현.

ANU_CODEX_CC_BOUNDED_REVIEW_EXECUTION_GATE 의 실행 코드.

Phase 1 LOCKED spec: memory/tasks/task-2592.md (v4 LOCKED,
sha256 23d0bc4d74793e1f4886020f5528d01a28d562a9efbd60088c4510df532a91bc).

본 모듈은 spec §2~§9 정의를 코드로 구현한다:

* §2  bounded loop state machine (S0~S7, max_review_rounds=2 / max_repair_rounds=1)
* §3  decision digest JSON schema (anu_codex_decision_digest_v1) + validation
* §4  Codex CC review request schema (anu_codex_review_request_v1) + validation
* §5  Codex CC review response schema (anu_codex_review_response_v1) + validation
* §6  Critical 7 classifier mapping (feedback_critical_escalation_only_260508 verbatim)
* §7  auto_execute_allowed 11조건 AND
* §8  HOLD_FOR_CHAIR 16조건 OR
* §9  기존 자동화 모듈 호출 경계 (6 후보, 새 권한 X)

경계 (회장 §7 / Phase 2 §5 verbatim):

* Codex CC 는 실행하지 않는다 — 검토 / 판정 / 제안만. ``review_response``
  의 ``execution_performed`` 은 항상 False 여야 하며 True 발견 시 즉시 HOLD.
* ANU 만 기존 자동화 모듈을 실행한다 (state ``S5_AUTO_EXECUTE``).
* Phase 2 는 구현·검증 task다. 실제 자동화 모듈 (replacement_pr_runner /
  merge_queue_executor / auto_gemini_triage / post_merge_smoke_runner /
  critical_escalation_reporter / dispatch·recovery marker generation) 은
  **실제 실행하지 않는다**. 기본 invoker 는 실제 모듈을 import 하지도,
  실행하지도 않으며 ``NoRealExecutionError`` 를 raise 한다. 검증은 mock /
  fixture invoker 로만 수행한다.

이 파일은 신규 파일이며 forbidden_write_targets (finish-task.sh, dispatch.py,
replacement_pr_runner.py, post-tool-use.sh 등) 를 일절 수정하지 않는다.
    )annotationsN)	dataclassfield)datetimetimezone)Enum)CallableOptionalanu_codex_decision_digest_v1anu_codex_review_request_v1anu_codex_review_response_v1      )/replacement_pr_runner_dry_run_operational_pilotmerge_queue_executorauto_gemini_triagepost_merge_smoke_runnercritical_escalation_reporter,dispatch_recovery_decision_marker_generationc                  0    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zy
)Stateu7   spec §2.1 — bounded loop state machine 의 8 상태.S0_PROPOSALS1_CODEX_REVIEWS2_ANU_REVISIONS3_CODEX_RE_REVIEWS4_CLASSIFYS5_AUTO_EXECUTES6_HOLD_FOR_CHAIRS7_DONEN)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r        3/home/jay/workspace/utils/anu_codex_bounded_loop.pyr   r   C   s/    AK'O'O-K'O+Gr%   r   c                  ,    e Zd ZdZdZdZdZdZdZdZ	dZ
y	)
	Critical7uL   spec §6 — Critical Escalation 7종. classifier mapping 의 canonical key.FORBIDDEN_PATH_INTRUSION9REPLACEMENT_PR_AUTO_CREATION_FAILED_FOR_CONTAMINATED_DIFF(GEMINI_REAL_BUG_REQUIRES_SCOPE_EXPANSION.BLOCK_OVERRIDE_REQUIRED_OR_REASON_INSUFFICIENT)DEPENDENCY_CYCLE_OR_SERIAL_ONLY_COLLISIONREPLACEMENT_PR_FAILEDPOST_MERGE_SMOKE_FAILEDN)r    r!   r"   r#   C1_FORBIDDEN_PATH_INTRUSION<C2_REPLACEMENT_PR_AUTO_CREATION_FAILED_FOR_CONTAMINATED_DIFF+C3_GEMINI_REAL_BUG_REQUIRES_SCOPE_EXPANSION1C4_BLOCK_OVERRIDE_REQUIRED_OR_REASON_INSUFFICIENT,C5_DEPENDENCY_CYCLE_OR_SERIAL_ONLY_COLLISIONC6_REPLACEMENT_PR_FAILEDC7_POST_MERGE_SMOKE_FAILEDr$   r%   r&   r(   r(   T   s@    V"<C A 	3 0 	9 6 	4 1  7!:r%   r(   c                      e Zd ZdZdZdZdZy)ReviewVerdictu.   spec §5 — Codex CC review response verdict.PASSNEEDS_REVISIONHOLD_FOR_CHAIRN)r    r!   r"   r#   r9   r:   r;   r$   r%   r&   r8   r8   h   s    8D%N%Nr%   r8   c                      e Zd ZdZdZdZy)LoopVerdictu,   spec §3 — decision digest 최종 verdict.AUTO_EXECUTEr;   N)r    r!   r"   r#   r>   r;   r$   r%   r&   r=   r=   p   s    6!L%Nr%   r=   c                      e Zd ZdZy)NoRealExecutionErroru   기본 invoker 호출 시 raise.

    Phase 2 는 구현·검증 task이므로 실제 자동화 모듈을 실행하지 않는다
    (회장 Phase 2 §5 verbatim). 실 실행이 필요하면 명시적 invoker 주입 필요.
    N)r    r!   r"   r#   r$   r%   r&   r@   r@   w   s    r%   r@   c                     e Zd ZU d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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)SignalsuE   spec §3 ``signals`` 블록. critical_7 은 classifier 가 채운다.r   intforbidden_path_countTboolexpected_files_matchFcontract_mismatchscope_expansionpermission_escalation$forbidden_write_target_change_neededreal_write_mode_neededgithub_write_neededgit_mutation_neededdev_bot_reactivation_neededreplacement_pr_failedgemini_real_bugblock_override_neededoverride_reason_insufficientdependency_cycleserial_only_collisionpost_merge_smoke_failedloop_limit_exceededverdict_disagreement_persistentN)r    r!   r"   r#   rD   __annotations__rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   r$   r%   r&   rB   rB      s    O !#!!%$%#t#!OT!"'4'16($6#(D( %% %%(--"'4'!OT!"'4'). $."d""'4'$)T) %%,1#T1r%   rB   c                   t         j                  | j                  dkD  t         j                  | j                  xr | j
                  t         j                  | j                  xr | j                   xs | j                  t         j                  | j                  xs | j                  t         j                  | j                  xs | j                  t         j                   | j
                  t         j"                  | j$                  iS )u]  spec §6 표 verbatim 매핑.

    1 forbidden_path_count > 0
    2 contract_mismatch && replacement_pr_failed
    3 gemini_real_bug && (!expected_files_match || scope_expansion)
    4 block_override_needed || override_reason_insufficient
    5 dependency_cycle || serial_only_collision
    6 replacement_pr_failed
    7 post_merge_smoke_failed
    r   )r(   r0   rD   r1   rG   rO   r2   rP   rF   rH   r3   rQ   rR   r4   rS   rT   r5   r6   rU   ss    r&   classify_critical_7r\      s     	--q/E/E/INN;A$;$;== D,,,B1B1BCC##Eq'E'E>>9!"9"9**A,C,C,,a.G.G! r%   c                    t        |       j                         D cg c]  \  }}|s	|j                   c}}S c c}}w )u3   Critical 7 중 hit 된 항목 enum value 리스트.)r\   itemsvalue)r[   chits      r&   critical_7_hitsrb      s.    "5a"8">">"@H3CAGGHHHs   
::c                F    t        t        |       j                               S N)anyr\   valuesrZ   s    r&   any_critical_7rg      s    "1%,,.//r%   c                4   t        t        |        | j                  dk(  | j                  du | j                  du | j
                  du | j                  du | j                  du | j                  du | j                  du | j                  du | j                  du g      S )u  spec §7 — 11조건 전부 true(만족) 시에만 True. 1건이라도 위반이면 False.

    조건 (회장 §8 verbatim):
    Critical 7 false / forbidden path 0 / expected_files 일치 /
    contract mismatch false / scope expansion false / 권한 확대 없음 /
    forbidden_write_target 수정 필요 없음 / real write mode 전환 없음 /
    GitHub write 필요 없음 / branch·commit·push·PR open·merge 필요 없음 /
    dev bot 재가동 필요 없음.
    r   TF)allrg   rD   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rZ   s    r&   auto_execute_allowedrj      s     q!!""a'""d*5(&##u,22e;$$-!!U*!!U*))U2	
 r%   c           	        g }t        |       }|j                         D ]&  \  }}|s	|j                  d|j                          ( | j                  | j
                  | j                  | j                  | j                  | j                  | j                  | j                  d}|j                         D ]  \  }}|s	|j                  |        t        |      dkD  |fS )u   spec §8 — 16항목 OR. 1건이라도 true면 (True, [사유…]).

    Critical 7 (1~8 은 Critical 7 과 1:1 대응) + 권한/write/dev재가동/
    loop한도/verdict불일치 확장 트리거.
    zcritical_7:)rJ   rI   rK   rL   rM   rN   rV   rW   r   )r\   r^   appendr_   rJ   rI   rK   rL   rM   rN   rV   rW   len)r[   reasonsc7r`   ra   extranames          r&   hold_for_chairrr      s     G	Q	B((* 43NN[	234
 120V0V!"!8!8"#":": 44 44'('D'D 44+,+L+L	E [[] !	cNN4 ! L1g&&r%   c                <    |D cg c]  }|| vsd|  c}S c c}w )Nzmissing:r$   )dkeysks      r&   _missingrw     s"    $(7qAQJhqcN777s   	c                   g }| j                  d      t        k7  r|j                  dt                |t        | d      z  }| j                  di       }t	        |t
              r|t        |d      z  }| j                  di       }t	        |t
              ri|t        |d      z  }|j                  d      }||t        vr|j                  d	|        |j                  d
      }||dvr|j                  d|        | j                  d      }|J|t        j                  j                  t        j                  j                  fvr|j                  d|        |S )uX   spec §3 anu_codex_decision_digest_v1 구조 검증. errors 리스트 반환 (빈=PASS).schemaschema!=)ts_utcloop_idroundproposalsignalsclassificationverdictevidence_pathsr}   review_roundrepair_roundr~   )intenttarget_modulemodeexpected_filesr   u*   proposal.target_module not in §9 6후보:r   )zdry-runmockzproposal.mode invalid:r   verdict invalid:)getSCHEMA_DECISION_DIGESTrl   rw   
isinstancedictALLOWED_AUTOMATION_MODULESr=   r>   r_   r;   )rt   errorsrndproptmr   r   s          r&   validate_decision_digestr     s_   FuuX00!7 89:
h			
 F %%
C#t(3 @AA55R D$(G
 	
 XXo&>b(BBMMFrdKLxx,? ?MM24&9:eeIGw  &&""((/   	(	23Mr%   c                \   g }| j                  d      t        k7  r|j                  dt                |t        | d      z  }| j                  di       }t	        |t
              rH|j                  d      dur|j                  d       |j                  d      dur|j                  d	       |S )
u3   spec §4 anu_codex_review_request_v1 구조 검증.ry   rz   )r{   r|   r}   digestreview_scopeconstraints_reminderr   codex_no_executionTz4constraints_reminder.codex_no_execution must be trueanu_only_executesz3constraints_reminder.anu_only_executes must be true)r   SCHEMA_REVIEW_REQUESTrl   rw   r   r   )rt   r   crs      r&   validate_review_requestr   4  s    FuuX//!6 789
h	X F 
%r	*B"d66&'t3MMPQ66%&d2MMOPMr%   c                   g }| j                  d      t        k7  r|j                  dt                |t        | d      z  }| j                  d      }|c|t        j
                  j                  t        j                  j                  t        j                  j                  fvr|j                  d|        | j                  d      dur|j                  d       |S )	u   spec §5 anu_codex_review_response_v1 구조 검증.

    회장 §7 verbatim — Codex CC 는 실행하지 않는다. ``execution_performed``
    이 False 가 아니면 §12 HOLD trigger (boundary violation).
    ry   rz   )r{   r|   r}   r   critical_7_assessmentcodex_anu_verdict_agreementexecution_performedr   r   r   FuA   BOUNDARY_VIOLATION:execution_performed must be false (회장 §7))	r   SCHEMA_REVIEW_RESPONSErl   rw   r8   r9   r_   r:   r;   )rt   r   r   s      r&   validate_review_responser   G  s     FuuX00!7 89:
h		
 F eeIGw  $$**$$**/  
 	(	23uu"#50O	
 Mr%   c                (    | j                  d      du S )uQ   회장 §7 — Codex CC 실행 금지. execution_performed False 일 때만 True.r   F)r   )review_responses    r&   codex_boundary_okr   j  s    45>>r%   c                  6    e Zd ZU ded<   ded<   ded<   ded<   y)ModuleInvocationstrmoduler   rE   	performednoteN)r    r!   r"   rX   r$   r%   r&   r   r   r  s    K
IO
Ir%   r   c                &    t        d|  d| d      )u  기본 invoker — 실제 자동화 모듈을 import 도 실행도 하지 않는다.

    Phase 2 는 구현·검증 task (회장 §5). 실제 실행 금지. 따라서 항상
    ``NoRealExecutionError`` 를 raise 한다. 검증은 mock invoker 로만.
    u.   Phase 2 = 구현·검증 task. 실제 모듈 'z' (mode=uU   ) 실행 금지 (회장 Phase 2 §5 verbatim). mock/fixture invoker 를 주입하라.)r@   )r   r   s     r&   no_real_execution_invokerr   z  s+     
8 OW 	X r%   c                      e Zd ZU ded<   ded<   ded<    ee      Zded	<    ee      Zded
<    ee      Zded<   dZ	ded<   y)
LoopResultr   final_stater=   r   r   r   )default_factory	list[str]hold_reasonscritical_7_hittransitionsNzOptional[ModuleInvocation]module_invocation)
r    r!   r"   rX   r   listr   r   r   r   r$   r%   r&   r   r     sL    L#D9L)9 %d ;NI;"48K84818r%   r   c                      e Zd ZU dZded<   ded<   ded<   eZded	<   eZd
ed<   e	Z
d
ed<   ddZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZy)BoundedReviewLoopu  spec §2 — ANU proposal → Codex review → revision → re-review →
    classify → (auto execute | HOLD).

    주입 함수:

    * ``propose_fn() -> (Signals, proposal_dict)`` : ANU 가 decision digest
      proposal 생성 (S0).
    * ``codex_review_fn(digest_dict, review_round) -> review_response_dict`` :
      Codex CC 검토 (S1/S3). **검토·판정·제안만** — module invoker 미전달.
    * ``anu_revise_fn(signals, review_response) -> Signals`` : ANU revision
      (S2). mid-correction 이 아닌 새 round 로 처리.
    * ``module_invoker(module, mode) -> ModuleInvocation`` : ANU 전용 실행
      (S5). 기본값은 실제 실행 금지 invoker.
    z"Callable[[], tuple[Signals, dict]]
propose_fnzCallable[[dict, int], dict]codex_review_fnz"Callable[[Signals, dict], Signals]anu_revise_fnz&Callable[[str, str], ModuleInvocation]module_invokerrC   max_review_roundsmax_repair_roundsc                f    t        j                  t        j                        j	                  d      S )Nz%Y-%m-%dT%H:%M:%SZ)r   nowr   utcstrftime)selfs    r&   _nowzBoundedReviewLoop._now  s!    ||HLL)223GHHr%   c	                t   t        d      D 	ci c]4  }	t        |	dz         t        t        |      j	                               |	   6 }
}	t        j                  |      }|
|d<   t        | j                         |||d|||t        j                  k(  |t        j                  k(  ||d|j                  g d	S c c}	w )N   r   
critical_7r   )rj   rr   r   r   )	ry   r{   r|   r}   r~   r   r   r   r   )ranger   r   r\   rf   dataclassesasdictr   r   r=   r>   r;   r_   )r   r|   r   r   r   r~   r   r   c7_hitic7mapsigs               r&   _build_digestzBoundedReviewLoop._build_digest  s     1X
 AJ09@@BCAFF
 
   )!L,iik&2LQ (/;3K3K(K")[-G-G"G ,"(	 }} 
 	

s   9B5c           	         t        t        j                               g ddj                  t        j
                  j                          j                         \  d fddfd}t        j                  }	  j                  k\  rd_
         |t        j                  dg      S dz  j                  |j                          t        j                  g t                    } j                  |      }t!        |      s |t        j                  dg      S |j#                  d      }|j#                  d	d      }|t$        j                  j                  k(  r |t        j                  d
g      S |t$        j&                  j                  k(  rn|s	  j(                  k\  r5| _        dg}|s|j                  d        |t        j                  |      S dz  j                  t        j,                  j                          j/                  |      t        j0                  }j                  t        j2                  j                         t5              \  }}t7              }	|s|	s|sdg} |t        j                  |      S j                  t        j8                  j                         j#                  d      }
|
t:        vr |t        j                  d|
 g      S 	  j=                  |
j#                  dd            }|j@                  s |t        j                  dg      S j                  t        jB                  j                         tE        t        jB                  t        jF                   t        jF                  g g       g g |      S # t>        $ r%} |t        j                  d| g      cY d }~S d }~ww xY w)Nr   r   c           
     4    j                  | ||      S rd   )r   )	r   holdro   r|   r~   r   r   r   r   s	      r&   emitz#BoundedReviewLoop.run.<locals>.emit  s.    %%	 	r%   c           	         j                  | j                         t              }t        t        j
                  t        j                   t        j                  ||      ||      S )N)r   r   r   r   r   r   )rl   r_   rb   r   r   r   r=   r;   )r   rn   ro   r   r   r   s      r&   r   z#BoundedReviewLoop.run.<locals>.hold  s[    {001 )B!33#22K66D$!' r%   TrV   r   z,BOUNDARY_VIOLATION:codex_execution_performedr   codex_verdict_hold_for_chairrW   )auto_execute_conditions_not_all_satisfiedr   u!   target_module_not_in_§9_6후보:r   r   zno_real_execution:module_invocation_not_performed)r   r   r   r   r   r   r   )r   r=   r   r   ro   r   returnr   )r   r   rn   r   r   r   )$r   uuiduuid4rl   r   r   r_   r   r   r   rV   r   r=   r;   rb   r   r   r   r8   r9   r   rW   r   r   r   r   rr   rj   r   r   r   r@   r   r   r   r>   )r   r   in_statedigest_for_reviewrespr   	agreementrn   heldallowedtargetinvexcr   r|   r~   r   r   r   r   s   `            @@@@@@@r&   runzBoundedReviewLoop.run  s~   djjl#!# 	5,,223 OO-
	 
	
	 ((t555.2+E336K5LMMALx~~. $**B0H! ''(9<HD %T*++CD 
 hhy)G!>EI-66<<<E336T5UVV-,,222 t555>G-701 NN#DEE33W== ALu44::;(($7G//HY ^ 	5,,223&w/g&w/wFG//99 	500667o.33''4VH=> 	O%%fhll66.JKC }}//2S1TUU 	5==../,,00"b9#!
 	
 $ 	O//4Fse2L1MNN	Os   ?"N2 2	O ;OO O N)r   r   )r|   r   r   rC   r   rC   r   rB   r~   r   r   r=   r   r   r   r   r   r   )r   r   )r    r!   r"   r#   rX   r   r   DEFAULT_MAX_REVIEW_ROUNDSr   DEFAULT_MAX_REPAIR_ROUNDSr   r   r   r   r$   r%   r&   r   r     s     320055=VN:V6s66s6I 
 
  
 	 

  
  
  
   
  
 
 
Dx
r%   r   )r   r(   r8   r=   rB   r@   r   r   r   r\   rb   rg   rj   rr   r   r   r   r   r   r   r   r   )r[   rB   r   zdict[Critical7, bool])r[   rB   r   r   )r[   rB   r   rE   )r[   rB   r   ztuple[bool, list[str]])rt   r   ru   ztuple[str, ...]r   r   )rt   r   r   r   )r   r   r   rE   )r   r   r   r   r   r   )+r#   
__future__r   r   r   r   r   r   r   enumr   typingr	   r
   r   r   r   r   r   r   r   r   r(   r8   r=   RuntimeErrorr@   rB   r\   rb   rg   rj   rr   rw   r   r   r   r   r   r   r   r   __all__r$   r%   r&   <module>r      s8   D #   ( '  %7 5 7     
C 
";T ;(&C &&#t &<  2 2 26>I
0<'@8&R& F?   	 9 9 9 t
 t
 t
nr%   