
    j.                       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 dZdZdZd	Zd
ZdZdZdZg dZg dZg dZg dZddZddZdddZddZd dZ	 	 	 	 	 	 	 	 	 	 	 	 d!dZd"d#dZd$dZe dk(  r e! e             y)%u  hooks/session_start_anu_callback_collector.py — SessionStart hook (STAGED · live 미적용).

task-2644 ANU_CALLBACK_COLLECTOR_CONTROL_PLANE (회장 verbatim 우선순위 1).
spec: memory/specs/system_anu_callback_collector_control_plane_spec_260524.md
spec sha256: b27da557d4245bce476cd63f4ab174aefc8a25d2da07ec2c8d2c83b01ee96153

★ 본 hook 은 staged template only · ~/.claude/settings.json 에 등록되지 않은 상태.
★ live 등록은 별도 HARNESS_ENFORCED task 에서 회장 verbatim signature 후 진행.

회장 verbatim flow (spec §1.2):
    cokacdir 가 ANU collector 세션 spawn
        → SessionStart hook (본 모듈) 이 ANU_CALLBACK_COLLECTOR 모드 강제
        → collector 가 task/spec/.anu_state/frozen anchor 로 context recovery

회장 verbatim 7 단계 (spec §3):
    1. envelope parse
    2. context recovery (task md / spec md / .anu_state.json / frozen anchor)
    3. terminal_state classify
    4. next_action decide
    5. auto action OR chair telegram
    6. .callback ledger write
    7. source attribution + exit

본 모듈 책임 (1~2 단계 + 의무 prompt 주입):
    - ENV COKACDIR_MODE 검사
    - envelope 파싱 (stdin JSON 또는 ENV path)
    - task md / spec md / .anu_state 자동 로드
    - frozen anchor 본문 + forbidden/allowed action list + 7 단계 의무 주입
    - 3~6 단계는 collector 본체가 utils.callback_adjudicator + callback_next_action_runner
      로 수행 · 7 단계 (source attribution + exit) 는 Stop hook 이 검증

Claude Code SessionStart hook 계약 (참고):
    - stdin: {"session_id":..., "transcript_path":..., "hook_event_name":"SessionStart"}
    - stdout: additionalContext 로 주입 가능 (JSON)
    - exit 0: continue · non-zero: block
    )annotationsN)Path)AnyDictOptionalz-hooks.session_start_anu_callback_collector.v1COKACDIR_MODEANU_CALLBACK_COLLECTORANU_CALLBACK_ENVELOPE_PATHANU_CALLBACK_ENVELOPE_JSONzmemory/system/.anu_state.jsonANU_WORKSPACE_ROOTz/home/jay/workspace))zANCHOR-1uR   본 task = ANU collector 자율 처리 + 다음 action 자동 진행 control plane)zANCHOR-2uI   Harness 단독 불가능 · Harness + cokacdir + file-state 결합 필수)zANCHOR-3u/   8 우선순위 + 15 필수 산출물 1:1 박제)zANCHOR-4uP   SessionStart = collector mode 강제 / Stop = 의무 미완·거짓표현 차단)zANCHOR-5u8   next_action 11 enum + 자동 허용 8 + 자동 금지 11)zANCHOR-6uB   RUNTIME_GUARDED 까지만 본 task · HARNESS_ENFORCED 별도 task)zANCHOR-7uB   본 ANU 대화 세션 hook = 이중 안전망 · 주 경로 아님)zANCHOR-8u;   PR #146 task-2643 와 격리 · 별도 worktree / 별도 PR)zANCHOR-9uB   거짓말 패턴 (수신 vs 사후 조회) Stop hook 사전 차단)z	ANCHOR-10u3   본 ANU 직접 polling 0 · 회장 verbatim dogfood)z	ANCHOR-11uD   source attribution enum 8 · CALLBACK_COLLECTOR_PROCESSED 주 경로)z	ANCHOR-12uK   next_action 3 분기 mutually exclusive · Telegram = chair-required 한정)z	ANCHOR-13uP   merge execution 0 hardcoded · MERGE_READY → REQUEST_CHAIR_MERGE_APPROVAL only)z	ANCHOR-14uB   .anu_state freshness state_version 검증 · stale 시 fail-closed)z	ANCHOR-15uH   Stop hook = decided + attempted + result + evidence_path 4 필드 검증)u   merge 실행u#   live ~/.claude/settings.json 적용u   live cokacdir 수정u   BOT App token 사용u   chair_authorization 발급zPR #141 pilotz"production PR lifecycle activationu   expected_files 밖 수정zcredential/permission expansionzadmin overridez'destructive git / foreign dirty cleanup)u.   expected_files 내부 non-critical remediationzphase3 timing race rerunz)allowed OWNER_GEMINI_TRIGGER_ROUTER nudgezbatch sibling callback waitzall-settled batch adjudicationzfollow-up task spec/preflightzregression rerunzcallback ack/ledger update)zenvelope parsezFcontext recovery (task md / spec md / .anu_state.json / frozen anchor)z4terminal_state classify (utils.callback_adjudicator)uA   next_action decide (utils.callback_next_action_runner · 11 enum)u;   auto action OR chair telegram (3 분기 mutually exclusive)z8.callback ledger write (schemas/callback_ledger_v1.json)uD   source attribution + exit (utils.source_attribution_guard · 8 enum)c                     	 t         j                  j                         ri S t         j                  j                         } | j	                         si S t        j                  |       S # t        $ r i cY S w xY wN)sysstdinisattyreadstripjsonloads	Exception)raws    -hooks/session_start_anu_callback_collector.py_read_stdinr   p   s\    99Iiinnyy{Izz# 	s   A' /A' A' 'A54A5c                    t         j                  j                  t              } | rHt	        |       j                         r/	 t        j                  t	        |       j                  d            S t         j                  j                  t              }|r	 t        j                  |      S y # t        $ r Y y w xY w# t        $ r Y y w xY wNutf-8)encoding)osenvirongetENVELOPE_PATH_ENVr   is_filer   r   	read_textr   ENVELOPE_INLINE_ENV)pathinlines     r   _load_enveloper'   |   s    ::>>+,DT
""$	::d4j22G2DEE ZZ^^/0F	::f%%   		  		s$    -B* B9 *	B65B69	CCc                    	 | j                         sy | j                         }t        |      |kD  r|d | }|j                  dd      S # t        $ r Y y w xY w)Nr   replace)errors)r"   
read_byteslendecoder   )r%   	max_bytesdatas      r   _safe_read_textr0      s\    ||~ t9y 
#D{{79{55 s   A	 5A	 		AAc                    | t         z  }|j                         sy 	 t        j                  |j	                  d            S # t
        $ r Y y w xY wr   )ANU_STATE_PATH_DEFAULTr"   r   r   r#   r   )workspace_rootps     r   _load_anu_stater5      sJ    //A99;zz!++w+788 s   $A 	AAc                     t         j                  j                  t        d      j	                         j                         } | t        k(  ryt               d uS )N T)r   r   r    COLLECTOR_MODE_ENVr   upperCOLLECTOR_MODE_VALUEr'   )modes    r   is_collector_moder<      sC    ::>>,b1779??AD##4''    c                   g }|j                  d       |j                  d       |j                  d| d       |j                  d       |j                  d       |j                  d       t        D ]  \  }}|j                  d| d|         |j                  d       |j                  d	       t        D ]  }|j                  d
|         |j                  d       |j                  d       t        D ]  }|j                  d
|         |j                  d       |j                  d       t	        t
        d      D ]  \  }	}
|j                  |	 d|
         |j                  d       |j                  d       | |j                  d       n| j                  dd      }| j                  dd      }| j                  dd      }| j                  d      xs | j                  d      xs d}|j                  d| d       |j                  d| d       |j                  d| d       |j                  d| d       |j                  d| j                  dt               d       |j                  d       |j                  d       ||j                  d       nl|j                  d |j                  d       d       |j                  d!|j                  d"       d       |j                  d#|j                  d$       d       |j                  d       |rG|j                  d%       |j                  d&       |j                  |dd'        |j                  d(       |rG|j                  d)       |j                  d&       |j                  |dd'        |j                  d(       |j                  d       |j                  d*       |j                  d+       d,j                  |      S )-u8   collector 본체에 주입할 system context (markdown).u>   # ANU_CALLBACK_COLLECTOR_CONTROL_PLANE — SessionStart 주입r7   z**workspace_root**: ``u;   **모드**: ANU_CALLBACK_COLLECTOR (envelope 자율 처리)z## frozen anchor (15)z- **z**: u+   ## 자동 진행 허용 8 (회장 verbatim)z- u,   ## 자동 진행 금지 11 (회장 verbatim)u/   ## collector 의무 7 단계 (Stop hook 검증)   z. z## envelope (parsed)NuG   - ⚠ envelope 미수신 — SAFE_DEGRADED_MODE / HOLD_FOR_CHAIR 강제callback_idz	<missing>task_id	pr_numberdispatch_state_snapshot_idsnapshot_idz- callback_id: `z- task_id: `z- pr_number: `z- dispatch_state_snapshot_id: `z- canonical_root: `canonical_rootu'   ## .anu_state (freshness 검증 입력)uU   - ⚠ .anu_state 미로드 → state_freshness=MISSING → HOLD_FOR_CHAIR fail-closedz- snapshot_id: `z- state_version: `state_versionz- updated_at: `
updated_atu   ## task md 발췌 (top 4KB)z```markdowni  z```u   ## spec md 발췌 (top 4KB)u   ## 다음 명령u  collector 는 envelope + anchor + state 를 기반으로 callback_adjudicator → callback_next_action_runner 를 호출하고 .callback ledger 에 결과를 기록한 뒤 source attribution 을 명시하고 종료한다. Stop hook 이 10 조건을 검증한다.
)	appendFROZEN_ANCHORSALLOWED_AUTO_ACTIONSFORBIDDEN_ACTIONS	enumerateCOLLECTOR_DUTY_7_STEPSr    WORKSPACE_ROOT_DEFAULTjoin)envelopetask_md_excerptspec_md_excerpt	anu_stater3   linestagbodyaidxstepcb_idrB   prsnaps                  r   build_additional_contextr_      s    E	LLQR	LL	LL((8:;	LLNO	LL	LL()# -	TtC5TF+,-	LL	LL>?! r!X	LL	LL?@ r!X	LL	LLBC5q9 '	TuBtf%&'	LL	LL'(^_]K8,,y+6\\+t,||89gX\\-=Xg\g'wa01|G9A./~bT+,6tfA>?*8<<8HJ`+a*bbcde	LL	LL:;lm'	m(D'EQGH))--*H)IKLy}}\'B&C1EF	LL23]#_Ud+,U23]#_Ud+,U	LL	LL#$	LL	e
 99Ur=   c                b   | | n	t               }t        t        j                  j	                  t
        t                    }t               s
t        dddS t               }|xs i j	                  d      xs t        j                  j	                  d      }d}|rt        |dz  dz  | dz        }t        |dz  d	z  d
z        }t        |      }t        |||||      }t        d|du|du|du|dut        t              t        t              t        t               t        t"              d|dd}	|	S )uI   SessionStart hook 본체. stdout 으로 JSON 반환 (Claude Code 계약).NF)schemacollector_modeadditionalContextrB   ANU_TASK_IDmemorytasksz.mdspecsz:system_anu_callback_collector_control_plane_spec_260524.md)rR   rS   rT   rU   r3   TSessionStart)hookEventNamerc   )ra   rb   envelope_parsedtask_md_loadedspec_md_loadedanu_state_loadedanchors_injectedforbidden_actions_injectedallowed_auto_actions_injectedduty_steps_injectedhookSpecificOutput)r   r   r   r   r    WORKSPACE_ROOT_ENVrP   r<   SCHEMAr'   r0   r5   r_   r,   rK   rM   rL   rO   )
stdin_payload_r3   rR   rB   task_mdspec_mdrU   ctxouts
             r   runr{      sI   &2A"**..);=STUN EPTUUH~2""9-N1NGG!.8";g"E7)SV"WX
	
	 G	GG  /I
"%C #4/!-!-%T1/&)*;&<),-A)B"#9: ,!$
C" Jr=   c                 0   	 t               } t        j
                  j	                  t        j                  | d             t        j
                  j                          y# t        $ r-}t        j                  j	                  d| d       Y d }~yd }~ww xY w)Nz.[session_start_anu_callback_collector] error: rI   r   F)ensure_ascii)	r{   r   r   stderrwritestdoutr   dumpsflush)resultexcs     r   mainr   $  sq     JJTZZU;<JJ  

I#bQRs   
A 	B(#BB__main__)returnDict[str, Any])r   Optional[Dict[str, Any]])i }  )r%   r   r.   intr   Optional[str])r3   r   r   r   )r   bool)rR   r   rS   r   rT   r   rU   r   r3   r   r   strr   )ru   r   r   r   )r   r   )"__doc__
__future__r   r   r   r   pathlibr   typingr   r   r   rt   r8   r:   r!   r$   r2   rs   rP   rK   rM   rL   rO   r   r'   r0   r5   r<   r_   r{   r   __name__
SystemExit r=   r   <module>r      s   #H #  	 
  & & 
9$ / 0 2 8 ) . $ 	  	 	(F&F #F #	F
 (F F 	FR/d z
TV
 r=   