
    MjK4                    P   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	m
Z
mZ ddlmZmZmZ dZdZd	Zd
ZdZdZ ed       G d d             Z ed       G d d             ZddZddZeedddd	 	 	 	 	 	 	 	 	 	 	 	 	 ddZeedddd	 	 	 	 	 	 	 	 	 	 	 	 	 ddZd dZd!dZg dZy)"um  utils.dispatch_spawn_verifier — task-2645 spawn verification gate.

회장 verbatim (2026-05-24 task-2644 사고 박제 §17.11):
spawn verification 은 4 항목으로 구성된다.

  1) workspace dir 존재 : ``/home/jay/.cokacdir/workspace/<cron_id>/`` 가 생성됐는가
  2) executor process or first activity signal : ``ps -ef | grep claude`` 또는
     workspace dir 내부 활동 흔적 (파일/디렉토리 ≥1)
  3) schedule visibility OR schedule accepted marker : cron-list 에 노출되거나
     1회성 자동삭제 schedule 의 경우 ``schedule_history`` 에 accepted marker
  4) schedule_history 부재 = 3 상태 분리 (in-progress / 종료 / silent drop)
     단독 "log 미존재" 단정 금지 — 다른 신호와 교차 판정

silent drop 확정 조건 (회장 verbatim 4신호 모두 hit):
  - workspace dir 빈 채 (생성됐어도 활동 0)
  - schedule_history log 부재
  - 봇 process 없음
  - cron-list 0 개

본 모듈은 가급적 stdlib 만 사용 + pure helper. dispatch.py / regression 양쪽에서
공유 가능하도록 dataclass 결과 + JSON dump 인터페이스를 제공한다.
    )annotations)	dataclassfield)Path)ListOptionalSequence)DISPATCH_SILENT_DROP_HOLDDISPATCH_SUBMITTED_UNVERIFIEDDISPATCH_VERIFIED_SPAWNz/home/jay/.cokacdir/workspacez$/home/jay/.cokacdir/schedule_historyHISTORY_ABSENT_IN_PROGRESSHISTORY_ABSENT_AFTER_COMPLETIONHISTORY_ABSENT_SILENT_DROPHISTORY_PRESENTT)frozenc                  V    e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded<   dd	Zy
)SpawnSignalsu8   spawn verifier 입력 신호 (회장 verbatim 4 항목).boolworkspace_dir_existsworkspace_dir_has_activityexecutor_process_presentschedule_visible_in_cron_list schedule_accepted_marker_presentschedule_history_log_presentc                    | j                   | j                  | j                  | j                  | j                  | j
                  dS )Nr   r   r   r   r   r   r   selfs    N/home/jay/workspace/.worktrees/task-2645-dev2/utils/dispatch_spawn_verifier.pyto_jsonzSpawnSignals.to_json;   sB    $($=$=*.*I*I(,(E(E-1-O-O040U0U,0,M,M
 	
    Nreturndict)__name__
__module____qualname____doc____annotations__r     r!   r   r   r   0   s.    B $$""#''&**"&&
r!   r   c                  r    e Zd ZU dZ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y)SpawnVerificationResultu+   spawn 확인 결과 + 천이 후보 status.strcron_idr   signalsr   verifiedsilent_drophistory_statenext_status)default_factoryz	List[str]reasonsc           
         d| j                   | j                  j                         | j                  | j                  | j
                  | j                  t        | j                        dS )Nz%dispatch.spawn_verification_result.v1)schemar.   r/   r0   r1   r2   r3   r5   )	r.   r/   r    r0   r1   r2   r3   listr5   r   s    r   r    zSpawnVerificationResult.to_jsonR   sT    =||||++-++!//++DLL)	
 		
r!   Nr"   )	r%   r&   r'   r(   r)   r   r8   r5   r    r*   r!   r   r,   r,   F   s;    5LNt4GY4

r!   r,   c                    | j                   rt        S | j                  r| j                  rt        S | j                  s| j                  st
        S | j                  r| j                  st        S t        S )u  schedule_history 부재의 3 상태 분리 판정.

    회장 verbatim: "schedule_history 부재는 작업 중/종료 후/미발사(silent drop) 로
    분리 판정 — 단독 'log 미존재' 단정 금지".

    교차 신호:
      - log present                                                 => HISTORY_PRESENT
      - log absent + workspace activity + executor process          => IN_PROGRESS
      - log absent + workspace dir exists + no activity + no proc   => SILENT_DROP candidate
      - log absent + cron 비가시 + workspace 부재                    => SILENT_DROP candidate
      - log absent + 부분적 신호                                     => AFTER_COMPLETION
        (1회성 자동삭제 마커 hit 면 종료 후로 본다)
    )	r   r   r   r   r   r   r   r   r   )r/   s    r   _classify_history_stater:   _   sa     ++))g.N.N)) ..00))//8]8]..**r!   c           	        g }t        |      }|j                   xs |j                   }|j                   }|j                   }|j
                   xr |j                   }|xr
 |xr |xr |}|r'|j                  d       t        | |dd|t        |      S |j                  s|j                  rU|j                  d|j                  rdndz          |j                  r|j                  d       t        | |dd|t        |      S |j                  d	       |j
                  r|j                  d
       |j                  r|j                  d       t        | |dd|t        |      S )u:  4 항목 + 4신호 silent drop 판정.

    silent drop 확정 (회장 verbatim) — 4신호 모두 hit:
      ① workspace dir 빈 채 (exists True + activity False)  ← 또는 exists False
      ② schedule_history log 부재
      ③ 봇 process 없음
      ④ cron-list 0 개 (visible False) 또는 accepted marker 부재

    위 4 신호 동시 hit ⇒ DISPATCH_SILENT_DROP_HOLD.
    workspace 활동 또는 executor process ≥1 hit ⇒ DISPATCH_VERIFIED_SPAWN.
    그 외 (부분 신호 + 판정 보류) ⇒ DISPATCH_SUBMITTED_UNVERIFIED (재폴링).
    u   silent drop 확정: workspace 빈 채 + history log 부재 + executor process 부재 + cron 비가시/accepted marker 부재 — 4신호 모두 hit.FT)r.   r/   r0   r1   r2   r3   r5   zspawn verified: zworkspace activity hitzexecutor process hitu%   schedule_history log present (보강)u_   verification 부족: 활동/process 신호 둘 다 0 — submitted_unverified 재폴링 필요.u*   cron-list 가시 — 발사 직후 가능.u/   schedule accepted marker hit — 등록 인정.)r:   r   r   r   r   r   r   appendr,   r
   r   r   )	r.   r/   r5   r2   workspace_emptyhistory_absent
no_process
not_listedr1   s	            r   evaluate_signalsrA   ~   s    G+G4M #777dAcAc=cO ===N555J111 	9888 
 "RnRR
KN	
 ''1
 	
 ))W-M-M 55 )+		
 //NNBC&'/
 	
 NNi ,,CD//HI"#1 r!   Nworkspace_rootschedule_history_rootcron_list_idsexecutor_process_idsaccepted_marker_idsc               f   t        |      | z  }|j                         }d}|r	 t        |j                               }t        |      |  dz  }	|	j                         }
t        |      xr | |v }t        |      xr | |v }t        |      xr | |v }t        ||||||
      S # t        $ r d}Y rw xY w)uZ  live 파일시스템 (옵션) + caller 제공 정보로 신호 수집.

    Pure 함수가 아닌 부분: workspace_root / schedule_history_root 디렉토리를 stat.
    caller 가 의존성을 모두 주입하면 (모든 인자 명시) 순수 함수처럼 동작 — regression
    fixture 에서 그대로 활용 가능.

    Args:
        cron_id: cokacdir cron schedule id (예: ``"673AA5A6"``).
        workspace_root: cokacdir workspace 루트 디렉토리.
        schedule_history_root: schedule_history 루트 디렉토리.
        cron_list_ids: ``cokacdir --cron-list`` 결과의 id 목록. None 이면 측정 불가
            로 보고 visible=False 처리.
        executor_process_ids: cron_id 와 매칭되는 process id 목록 (외부 수집).
        accepted_marker_ids: 1회성 자동삭제 schedule 의 accepted marker id 목록.
    Fz.logr   )r   is_diranyiterdirOSErroris_filer   r   )r.   rC   rD   rE   rF   rG   ws_dirr   r   hist_logr   r   schedule_visibleaccepted_marker_presents                 r   collect_signalsrR      s    0 .!G+F!==?!&	/),V^^-=)>& )*y-==H#+#3#3#5 #$89_wJ^?^M*I=0H"#67\WH[=[1#=!9&6)@%A   	/).&	/s   B" "B0/B0c               <    t        | |||||      }t        | |      S )u*   signal 수집 + 평가 합성 entry-point.rB   )rR   rA   )r.   rC   rD   rE   rF   rG   r/   s          r   verify_spawnrT     s/     %3#1/G GW--r!   c                D    | j                   xr | j                  t        k(  S )u;   silent drop 확정 여부 — 회장 보고 hold 게이트.)r1   r3   r
   )results    r   is_silent_drop_confirmedrW     s    Q&"4"48Q"QQr!   c                p    t        | t              sy| j                  d      }|t        k(  ry|dk(  rd| vryy)uE  ``dispatch.py`` 반환 dict 가 SUBMITTED_UNVERIFIED 단계인지 확인.

    회장 verbatim ANCHOR-1: cron_response.status="ok" 만으로 final success 보지 않는다.
    legacy dict {"status": "dispatched", "cron_response": {"status":"ok",...}} 도
    spawn verification 전까지는 UNVERIFIED 로 간주한다.
    FstatusT
dispatchedspawn_verification)
isinstancer$   getr   )dispatched_dictrY   s     r   dispatched_dict_is_unverifiedr_     sC     ot,  *F..6r!   )COKACDIR_WORKSPACE_ROOT_DEFAULTSCHEDULE_HISTORY_ROOT_DEFAULTr   r   r   r   r   r,   rA   rR   rT   rW   r_   )r/   r   r#   r-   )r.   r-   r/   r   r#   r,   )r.   r-   rC   r-   rD   r-   rE   Optional[Sequence[str]]rF   rb   rG   rb   r#   r   )r.   r-   rC   r-   rD   r-   rE   rb   rF   rb   rG   rb   r#   r,   )rV   r,   r#   r   )r^   objectr#   r   )r(   
__future__r   dataclassesr   r   pathlibr   typingr   r   r	   utils.dispatch_status_enumr
   r   r   r`   ra   r   r   r   r   r   r,   r:   rA   rR   rT   rW   r_   __all__r*   r!   r   <module>rj      s\  , # (  + +  #B  F  : "C 9 # $
 
 
* $
 
 
0+>Pn :!>-14837// / 	/
 +/ 2/ 1/ /j :!>-14837.. . 	.
 +. 2. 1. .*R
&r!   