
    X"j                        U d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
mZmZ  ej                  e      ZdZded<   	 dd	lmZmZ ddZddZdddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy# e$ r dZd
Zded<   Y =w xY w)u  utils/owner_gemini_trigger.py — task-2729 Phase 2 결함6 전용 entrypoint.

OWNER /gemini review 자동 발사 전용 모듈.

정책 (회장 2026-06-03 verbatim):
  - request-only /gemini review 자동 발사만 허용.
  - thread resolve / 판단대행 / merge approval / merge 실행은 절대 하지 않음.
  - head-lock 검증 + dedupe(중복 발사 차단) 필수.
  - raw token 노출 금지 — sha256 앞 12자(token_hash_prefix)만 기록.
  - ACTIVE=false 골격: production 전환 없이 구조·결선만 제공.
  - 실제 gh 네트워크 호출 0: router 주입 시만 router.route_for_pr() 통해 발사,
    router=None이면 REQUEST_PREPARED 반환(network 0).

dedupe 전략:
  - already_fired_heads(set, 주입 가능)에 current_head_sha가 있으면 DEDUPED 반환.
  - NUDGE_HARD_LIMIT_PER_PR_HEAD 기반 nudge limit 정책 적용(router 위임).
  - dedupe key = (pr_number, current_head_sha) 조합으로 중복 발사 차단.
    )annotationsN)Path)AnyCallableOptionalSetz/gemini reviewstrOWNER_GEMINI_REVIEW_BODY)OwnerGeminiTriggerRouterNUDGE_HARD_LIMIT_PER_PR_HEAD   intr   c                    t        | t              r t        |       dk7  st        d | D              st	        d|       y)u   head_sha가 40자 16진수 문자열인지 검증.

    형식 불일치 시 ValueError 발생 — caller가 잘못된 SHA로 dedupe/발사하는 것을 원천 차단.
    (   c              3  $   K   | ]  }|d v  
 yw)0123456789abcdefABCDEFN ).0cs     M/home/jay/workspace/.worktrees/task-2729+1-dev6/utils/owner_gemini_trigger.py	<genexpr>z&_validate_head_lock.<locals>.<genexpr>7   s     CQ100Cs   z,head_sha must be a 40-char hex string, got: N)
isinstancer	   lenall
ValueError)head_shas    r   _validate_head_lockr   /   sE     x%x=BC(CC:8,G
 	
 D    c                V   | y	 t        |       }|j                  j                  dd       |j                  dd      5 }|j	                  t        j                  |d      d	z          ddd       y# 1 sw Y   yxY w# t        $ r }t        j                  d
|       Y d}~yd}~ww xY w)up   audit_path에 record를 UTF-8 JSONL 한 줄로 append.

    audit_path가 None이면 skip(audit 비활성).
    NT)parentsexist_okautf-8)encodingF)ensure_ascii
z,owner_gemini_trigger audit append failed: %s)
r   parentmkdiropenwritejsondumps	Exceptionloggerwarning)
audit_pathrecordpfhexcs        r   _audit_appendr5   A   s    
 L	td3VVC'V* 	DbHHTZZU;dBC	D 	D 	D LEsKKLs5   ;A?  *A3*A? 3A<8A? <A? ?	B(B##B( T)task_idobserved_commentr0   routerrequest_onlytoken_provideralready_fired_headsc           
        t        |       d}|	?	  |	       }|r5t        j                  |j                  d            j	                         dd }|
A||
v r=ddt        | |dd|dd	}t        j                  d	| |       t        |d
di|d|i       |S |A	 |j                  | |||||t              }t        |dd      }t        t        |dd            }nd}d}||t        | |dd|dd	}t        |d
di|d|i       t        j                  d| |||       |S # t
        $ r }t        j                  d|       Y d}~d}~ww xY w# t
        $ r:}t        j                  d|       d}dt        |      j                    }Y d}~d}~ww xY w)u`  OWNER /gemini review 자동 발사 전용 entrypoint.

    정책:
      - request_only=True 고정 (request-only 자동발사 정책).
      - thread resolve / 판단대행 / merge approval / merge 실행 절대 하지 않음.
      - head-lock 검증 → dedupe 체크 → router 발사(또는 골격 반환).
      - ACTIVE=false: router=None이면 실 gh 네트워크 호출 0.

    dedupe:
      - already_fired_heads(set) 안에 current_head_sha가 있으면 DEDUPED 반환.
      - 중복 발사 차단은 dedupe set 주입으로 외부에서도 제어 가능.

    Args:
      pr_number: PR 번호.
      current_head_sha: 현재 PR head SHA (40자 hex, head-lock 검증).
      owner: 저장소 owner.
      repo: 저장소 이름.
      task_id: 태스크 ID (audit 기록용).
      observed_comment: 관측된 최근 코멘트 본문 (router에 전달).
      audit_path: audit JSONL 경로 (None이면 skip).
      router: OwnerGeminiTriggerRouter 인스턴스 (None이면 ACTIVE=false 골격).
      request_only: True 고정 (변경 금지).
      token_provider: OWNER PAT 토큰 provider callable (None이면 token_hash_prefix=None).
      already_fired_heads: 이미 발사한 head SHA set (dedupe용, 주입 가능).

    Returns:
      dict: fired, status, body, pr_number, head_sha, dedupe, request_only,
            token_hash_prefix, active 포함.
    Nr#      z.owner_gemini_trigger token_provider failed: %sFDEDUPEDT)	firedstatusbody	pr_numberr   deduper:   token_hash_prefixactivezHowner_gemini_trigger DEDUPED: pr=%s head=%s (already_fired_heads dedupe)eventr7   )rC   current_head_shaownerrepor7   r8   nudge_hard_limitr@   final_stateROUTER_RESULTz3owner_gemini_trigger router.route_for_pr failed: %szROUTER_ERROR: REQUEST_PREPAREDFIRE_ATTEMPTzCowner_gemini_trigger: pr=%s head=%s fired=%s status=%s active=False)r   hashlibsha256encode	hexdigestr-   r.   r/   r
   infor5   route_for_prr   getattrr	   type__name__)rC   rH   rI   rJ   r7   r8   r0   r9   r:   r;   r<   rE   	token_rawr4   resultrouter_resultr@   rA   s                     r   fire_owner_gemini_reviewr\   T   s   X () (,!	R&(I$+NN$$W-%)+cr%#! &+;?R+R,"( !2

 	V'	
 	j7I"T"TG"TU 	;"//#!1!1!= 0 M M7E:EOPF # ($.
F 	.?F?Iw? KKM#UF MI  	RNNKSQQ	RL  	;NNPRUVE%d3i&8&8%9:F	;s/   >D ?E 	E!D<<E	F0FF)r   r	   returnNone)r0   Optional[Any]r1   dictr]   r^   )rC   r   rH   r	   rI   r	   rJ   r	   r7   r	   r8   zOptional[str]r0   r_   r9   r_   r:   boolr;   zOptional[Callable[[], str]]r<   zOptional[Set[str]]r]   r`   )__doc__
__future__r   rP   r+   loggingpathlibr   typingr   r   r   r   	getLoggerrX   r.   r
   __annotations__"anu_v2.owner_gemini_trigger_routerr   r   ImportErrorr   r5   r\   r   r   r   <module>rk      s  $ #     / /			8	$ !1 # 0*
$L2 &* $ 26.2{{ { 	{
 { { ${ { { { 0{ ,{ 
{[  *#() #)*s   A7 7BB