
    i#                       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	Z	 ee
      j                         j                  d   Z e	j                  d      d        Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)uM  tests/regression/test_chairman_audit.py — task-2471 회귀 테스트.

헤임달이 task-2471 1차 hardening 의 일환으로 신설한
``utils/audit_chairman_recovery.py`` 의 schema + atomic append 동작 검증.

- ``AUDIT_JSONL_PATH`` 경로 상수가
  ``memory/orchestration-audit/chairman-manual-recovery.jsonl`` 인지 확인.
- ``RECOVERY_RECORD_KEYS`` schema 6 키 모두 정의.
- ``append_recovery`` atomic append 동작 (디렉토리 자동 생성, JSONL 직렬화).
- ``read_recoveries`` 파일 부재 시 graceful (빈 리스트).

헤임달(개발2팀 테스터) 작성.
    )annotationsN)Path   module)scopec                    t         dz  dz  } | j                         st        j                  d       t        j
                  j                  dt        |             }||j                  J t        j
                  j                  |      }|t        j                  |j                  <   |j                  j                  |       |S )u:   ``utils/audit_chairman_recovery.py`` 절대 경로 로드.utilszaudit_chairman_recovery.pyuM   utils/audit_chairman_recovery.py 미작성 — 헤임달 신규 모듈 대기"audit_chairman_recovery_test_alias)	WORKSPACEexistspytestskip	importlibutilspec_from_file_locationstrloadermodule_from_specsysmodulesnameexec_module)	file_pathspecmods      ;/home/jay/workspace/tests/regression/test_chairman_audit.pyacrr      s     G#&BBI[	
 >>11,c)nD  777
..
)
)$
/C CKK		KKC J    c                    t        | d      sJ | j                  }t        |t              sJ |j                  }d|v sJ |d   dk(  sJ d|v sJ y)u:   AUDIT_JSONL_PATH 가 정확한 상대 경로인지 검증.AUDIT_JSONL_PATHzorchestration-auditzchairman-manual-recovery.jsonlmemoryN)hasattrr    
isinstancer   parts)r   pr%   s      r   test_audit_jsonl_path_constantr'   1   sf    3*+++AaGGE E)))98888ur   c                t    t        | d      sJ t        | j                        }h d}||z
  }|r
J d|        y)u   6 schema 키 모두 정의.RECOVERY_RECORD_KEYS>   tsreasontask_idto_state
from_stateevidence_pathsu   누락된 schema 키: N)r#   setr)   )r   keysexpectedmissings       r    test_recovery_record_keys_schemar4   =   sH    3.///s''(DVHoG:0	::;wr   c                    | j                  dddddg|      }|j                         sJ |j                         sJ |j                  j	                         sJ y)u-   디렉토리/파일 부재 시 자동 생성.	task-2471RECOVERABLE_BLOCKEDMERGINGu   branch protection 해제 확인z'.tasks/evidence/task-2471/recovery.jsonr,   r.   r-   r+   r/   	workspaceN)append_recoveryr   is_fileparentis_dir)r   tmp_pathout_paths      r   /test_append_recovery_creates_directory_and_filerA   K   sf    ""(0AB # H ????!!###r   c                   | j                  ddddddg|       || j                  z  }|j                  d	      j                         j	                         }t        |      d
k(  sJ t        j                  |d         }h d}|t        |j                               k  sJ |d   dk(  sJ |d   dk(  sJ |d   dk(  sJ |d   ddgk(  sJ y)u9   append 된 JSONL 라인이 6 schema 키를 모두 포함.r6   r7   r8   okza.jsonzb.jsonr9   utf-8encoding   r   >   r*   r+   r,   r-   r.   r/   r,   r.   r-   r/   N)
r;   r    	read_textstrip
splitlineslenjsonloadsr0   r1   )r   r?   targetcontentrecordexpected_keyss         r   "test_append_recovery_record_schemarR   [   s    ( (+   ,,,F0668CCEGw<1ZZ
#FM C....)+++,#8888****"#(';;;;r   c           	     ^   t        d      D ]  }| j                  d| ddd| g |       ! || j                  z  }|j                  d      j	                         j                         }t        |      dk(  sJ |D cg c]  }t        j                  |      d	    }}|g d
k(  sJ yc c}w )u>   동일 파일에 2회 append 시 라인 2개 (덮어쓰기 X).   ztask-r7   r8   zreason-r9   rD   rE   r,   )ztask-0task-1task-2N)	ranger;   r    rH   rI   rJ   rK   rL   rM   )r   r?   irN   linesltask_idss          r   +test_append_recovery_appends_not_overwritesr\   t   s    1X 
A3K,QC= 	 	

 ,,,Fg.446AACEu:??278Q

1i(8H85555 9s   ?B*c           	         d}| j                  ddddg ||       || j                  z  }t        j                  |j	                         j                         j                         d         }|d   |k(  sJ y	)
u+   ``ts`` 인자가 그대로 기록되는지.z2026-05-07T01:23:45Zztask-XABt)r,   r.   r-   r+   r/   r*   r:   r   r*   Nr;   r    rL   rM   rH   rI   rJ   )r   r?   	custom_tsrN   rP   s        r    test_append_recovery_explicit_tsrc      s    &I   ,,,FZZ((*002==?BCF$<9$$$r   c                   | j                  ddddg |       || j                  z  }t        j                  |j	                         j                         j                         d         }|d   }|j                  d      sJ d	|v sJ y
)u)   ``ts`` 미지정 시 ISO 8601 UTC 형식.ztask-Yr^   r_   r`   r9   r   r*   ZTN)r;   r    rL   rM   rH   rI   rJ   endswith)r   r?   rN   rP   r*   s        r   'test_append_recovery_default_ts_iso8601rh      s       ,,,FZZ((*002==?BCF	B;;s"99r   c           	         t        j                  t              5  | j                  ddddg |       d d d        y # 1 sw Y   y xY w)N r^   r_   xr9   r   raises
ValueErrorr;   r   r?   s     r   *test_append_recovery_rejects_empty_task_idrp      sH    	z	" 
 	 	

 
 
	   ;Ac           	         t        j                  t              5  | j                  ddddg |       d d d        y # 1 sw Y   y xY w)NrU   rj   r_   rk   r9   rl   ro   s     r   -test_append_recovery_rejects_empty_from_staters      sH    	z	" 
 	 	

 
 
rq   c           	         t        j                  t              5  | j                  ddddg |       d d d        y # 1 sw Y   y xY w)NrU   r^   rj   rk   r9   rl   ro   s     r   +test_append_recovery_rejects_empty_to_stateru      sH    	z	" 
 	 	

 
 
rq   c                6    | j                  |      }|g k(  sJ y)u2   파일 부재 시 빈 리스트 반환 (graceful).r:   N)read_recoveriesr   r?   outs      r   4test_read_recoveries_missing_file_returns_empty_listr{      s!    




1C"99r   c                    | j                  dddddg|       | j                  ddddd	g|       | j                  |
      }t        |      dk(  sJ |d   d   dk(  sJ |d   d   dk(  sJ y)u0   append 한 다음 read 로 동일 record 회수.ztask-AXYr1e1r9   ztask-Br2e2rw   r   r   r,   rG   N)r;   rx   rK   ry   s      r   test_read_recoveries_round_tripr      s    v   v   



1Cs8q==q6)(((q6)(((r   c                   || j                   z  }|j                  j                  dd       |j                  dd       | j	                  |      }t        |      dk(  sJ |D cg c]  }|d   	 c}d	d
gk(  sJ yc c}w )u!   JSON parse 실패 라인은 skip.T)parentsexist_okz{"task_id": "task-1", "ts": "T", "from_state": "A", "to_state": "B", "reason": "x", "evidence_paths": []}
garbage line not json
{"task_id": "task-2", "ts": "T", "from_state": "A", "to_state": "B", "reason": "y", "evidence_paths": []}
rD   rE   rw   r   r,   rU   rV   N)r    r=   mkdir
write_textrx   rK   )r   r?   rN   rz   rs        r   *test_read_recoveries_skips_malformed_linesr      s    ,,,F
MMt4
	B
    



1Cs8q=="%&QAiL&8X*>>>>&s   &A=c                    | j                  ddddg |       || j                  z  }t        j                  |j	                         j                         j                         d         }|d   g k(  sJ y)	uD   evidence_paths=None 또는 빈 sequence 시 빈 리스트 직렬화.ztask-Zr^   r_   rk   r9   r   r/   Nra   )r   r?   rN   rP   s       r   +test_evidence_paths_none_becomes_empty_listr     s{       ,,,FZZ((*002==?BCF"#r)))r   )__doc__
__future__r   importlib.utilr   rL   r   pathlibr   r   __file__resolver   r   fixturer   r'   r4   rA   rR   r\   rc   rh   rp   rs   ru   r{   r   r   r    r   r   <module>r      s    #   
  N""$,,Q/	 h  ,	;$ <26&%".	
	
	
")2?.*r   