
    jS4                        d Z ddlZddlmc mZ ddlZddlZddl	m
Z
  e
e      j                         j                  d   Z ee      ej                   vr"ej                   j#                  d ee             ddlZddlmZ  e
e      j                         j                  d   dz  dz  Zd	efd
Zej.                  j1                  dg d      d        Zd Zd Zd Zd Zd Zy)u|  Regression tests for callback_lifecycle_classifier.

규칙:
- 순수 함수 호출만 (실 cron 0, 실 발사 0, subprocess 0, live workspace 의존 0)
- frozen fixture 만 입력 (tests/fixtures/callback_lifecycle/)
- pytest 로 실행 가능

dev6 담당: 벨레스 (fixture 구성 + regression 테스트)
classifier core: 스바로그 (utils/callback_lifecycle_classifier.py)
    N)Path   )classify_callback_lifecycle   fixturescallback_lifecyclefixture_dir_namec                     t         | z  }t        j                  |dz  j                  d            }t        j                  |dz  j                  d            }||fS )u5   evidence.json 과 expected.json 을 로드해 반환.zevidence.jsonutf-8encodingzexpected.json)FIXTURE_ROOTjsonloads	read_text)r	   baseevidenceexpecteds       J/home/jay/workspace/tests/regression/test_callback_lifecycle_classifier.py_load_fixturer   !   sZ    **Dzz4/1<<g<NOHzz4/1<<g<NOHX    fixture_dir)	task-2625z	task-2628ztask-2628_plus_1c           
         t        |       \  }}t        |      }|d   }|d   }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|  d|d   d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }|d   }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|  d|d   d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }|d   }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|  d|d   d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }|d   }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|  d|d   d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }	|d   }
t        |	      }t        |
      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |	      rt        j                  |	      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      dz  }t        j
                  d|  dt        |	       dt        |
             dz   d|iz  }t        t        j                  |            d
x}x}}t        |	      }t        |
      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |	      rt        j                  |	      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      dz  }t        j
                  d|  d|	 d|
       dz   d|iz  }t        t        j                  |            d
x}x}}y
)u   각 fixture 의 evidence → classify → expected 정확 일치 검증.

    - delivery_outcome, normal_callback_miss_cause, evidence_completeness, classification: == 정확 일치
    - root_cause_tags: 순서 무관 집합 동치 (set 동치 + len 동치 → 중복 없음 보장)
    delivery_outcome==z%(py1)s == %(py4)spy1py4[z!] delivery_outcome mismatch: got=z, want=
>assert %(py6)spy6Nnormal_callback_miss_causez+] normal_callback_miss_cause mismatch: got=evidence_completenessz&] evidence_completeness mismatch: got=classificationz] classification mismatch: got=root_cause_tags)zN%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py8)s
{%(py8)s = %(py5)s(%(py6)s)
}setresult_tagsexpected_tags)py0r    py3py5r$   py8z$] root_cause_tags set mismatch: got=z
>assert %(py10)spy10lenu7   ] root_cause_tags length mismatch (중복 의심): got=)r   r   
@pytest_ar_call_reprcompare	_saferepr_format_assertmsgAssertionError_format_explanationr)   @py_builtinslocals_should_repr_global_namesortedr1   )r   r   r   result@py_assert0@py_assert3@py_assert2@py_format5@py_format7r*   r+   @py_assert7@py_assert4@py_format9@py_format11s                  r   test_chairman_mapping_exactrF   -   s!    '{3Hh(2F $% 2D)E %)EE  %)E    &    *F    K= (),GH=O4P3S	U     ./ 8<X3Y /3YY  /3Y    0    4Z    K= 236ghGc>d=g	i     )* h7N.O *.OO  *.O    +    /P    K= -.1BY9Z8]	_     "# x0@'A #'AA  #'A    $    (B    K= &'*'(;K2L1O	Q     *+K./M{ s=1 11   1                               #     #      $1    $1     2    K= k"#76-+@*A	C     { s=1 11   1                               #     #      $1    $1     2    K= m7=/	3     r   c                  	   t        d      \  } }t        |       }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|d   }g }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j
                  d|d         dz   d	|iz  }t        t        j                  |            d
x}x}}|j                  dg       }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j
                  d|       dz   d|	iz  }
t        t        j                  |
            d
x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j
                  d|       dz   d|	iz  }
t        t        j                  |
            d
x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j
                  d|       dz   d|	iz  }
t        t        j                  |
            d
x}}y
)uG   core evidence 부재 시 추정 없이 UNKNOWN + MISSING 반환 검증.unknown_insufficientr   UNKNOWN_INSUFFICIENT_EVIDENCEr   r   r   zdelivery_outcome: got=r#   r$   Nr%   z normal_callback_miss_cause: got=r&   MISSINGzevidence_completeness: got=r(   z%root_cause_tags should be empty, got=missing_evidence_sourcesresult_json)in)z%(py1)s in %(py3)smissing_srcs)r    r-   z/'result_json' not in missing_evidence_sources: 
>assert %(py5)sr.   
collectorsz.'collectors' not in missing_evidence_sources: schedule_historyz4'schedule_history' not in missing_evidence_sources: )r   r   r2   r3   r4   r5   r6   r7   getr8   r9   r:   )r   _r<   r=   r>   r?   r@   rA   rN   @py_format4@py_format6s              r   "test_unknown_insufficient_evidencerV   ^   so    67KHa(2F$% )H %)HH  %)H    &    *I    !(:!; >?     ./ 3R /3RR  /3R    0    4S    +62N+O*RS     )* i *i7  *i    +    /8    &f-D&E%HI     #$  $*  $    %    )+    07H0I/LM    
 ::8"=L =L(  =L          )    )    :,H      <<'  <<          (    (    9G      -            ".    ".    ?|nM    r   c                     dddddddddddd	d
d
d	ddd
d
dd	d	d
d	dd	d	d	d	ddd	iddg d	dddd	dd} t        |       }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d         dz   d|iz  }t        t        j                  |            d
x}x}}y
)u\   ANU key cron FIRED + collector 부재 + BEFORE_FIRE 원인 전무 → CALLBACK_DELIVERY_GAP.zinline-delivery-gap-positiveFIREDAAAA1111c119085addb0f8b7,  callback_registration_statuscallback_cron_id	owner_keyenvelope_utf8_bytesTcron_idr_   firedargv_presentFN
registeredrb   r_   rc   normal_callbackfallbackreasonsourcepresentr_   authoritativern   normal_callback_receivedno_opro   rn   normal_collection_ackself_collectionfallback_collectormanual_anu_reverifyr   foreign_dirtygit_gate_blockedtask_idrL   rQ   escalaterP   applied_countgitreflection_mergedbot_app_token_presentself_key_fail_closedenvelope_onlyr%   CALLBACK_DELIVERY_GAPr   r   r   z$expected CALLBACK_DELIVERY_GAP, got=r#   r$   r   r2   r3   r4   r5   r6   r7   r   r<   r=   r>   r?   r@   rA   s          r   #test_callback_delivery_gap_positiver      s<    2,3 *+#&	
 &/ $	  (-D[`a
  $t4%*+0tV[\.3QVafy~"$-u#5	
 !#?!!% %;H> )2F./ 3J /3JJ  /3J    0    4K    /v6R/S.VW     r   c                     ddddddddddd	ddddd
ddddddddddddddddiddg ddddddd} t        |       }|d   }d}||k7  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|d         dz   d|iz  }t        t        j                  |            dx}x}}|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d |d         dz   d|iz  }t        t        j                  |            dx}x}}y)!uj   BEFORE_FIRE 원인(self-key fail-closed) 존재 → DELIVERY_GAP 아님, SELF_KEY_FAIL_CLOSED_BEFORE_FIRE.zinline-delivery-gap-negativeENVELOPE_PREPARED_NOT_FIREDNrZ   r[   r\   1e41a2324a3ccdd0Fra   re   rg   rj   rm   rp   rn   rs   r   rx   Tr{   r%   r   )!=)z%(py1)s != %(py4)sr   zGshould not be CALLBACK_DELIVERY_GAP when BEFORE_FIRE cause exists, got=r#   r$    SELF_KEY_FAIL_CLOSED_BEFORE_FIREr   r   z/expected SELF_KEY_FAIL_CLOSED_BEFORE_FIRE, got=r   r   s          r   8test_callback_delivery_gap_negative_self_key_fail_closedr      s    2,I $+#&	
  / %	  (-D[`a
  $t4%*+0tV[\.3QVafy~"$-u#5	
 !#?!!% $;H> )2F./ 3J /3JJ  /3J    0    4K   236	8     ./ 3U /3UU  /3U    0    4V    :&A]:^9ab     r   c                     t        d      \  } }t        |       }t        |       }|d   }|d   }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d	   }|d	   }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d
   }|d
   }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }|d   }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }|d   }||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}y)u]   task-2625 frozen fixture 로 2회 분류 → 동일 결과 (live 비의존 결정적 증명).r   r   r   r   r   zassert %(py6)sr$   Nr%   r&   r'   r(   uI   root_cause_tags 순서까지 동일해야 결정적 (deterministic order)r#   )r   r   r2   r3   r4   r6   r7   r5   )	r   rS   result_aresult_br=   r>   r?   r@   rA   s	            r   test_determinism_task_2625r      s)   ,KHa*84H*84H&'G84F+GG'+GGGGG'+GGGG'GGG+GGGGGGGG01[X>Z5[[15[[[[[15[[[[1[[[5[[[[[[[[+,Q9P0QQ,0QQQQQ,0QQQQ,QQQ0QQQQQQQQ$%C2B)CC%)CCCCC%)CCCC%CCC)CCCCCCCC%& (3D*E &*EE  &*E    '    +F    	T     r   c                     ddl } t        dz  }|dz  |dz  g}| j                  d| j                        }|D ]?  }|j	                         s"t        j                  |j                   d       |j                  d	      }|j                  |      }d}||u }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	t        j                   |j                   d|j#                         j%                         d      dz   d|	iz  }
t'        t        j(                  |
            dx}}B y)u  classifier 및 states 소스 파일에 'import anu_v3' 구문이 없음을 정적 검증.

    주의: docstring/주석에서 'anu_v3' 문자열을 언급하는 것은 허용.
    금지되는 것은 실제 import 구문 (import anu_v3 / from anu_v3 ...).
    r   Nutilsz callback_lifecycle_classifier.pyzcallback_lifecycle_states.pyz%^\s*(import\s+anu_v3|from\s+anu_v3\b)u<    아직 미생성 — classifier 완성 후 재실행 필요r   r   )is)z%(py0)s is %(py3)smatch)r,   r-   u8    에 실제 anu_v3 import 구문 발견 (line contains: uP   ) — 금지된 의존성. classifier 는 evidence-only decoupled 이어야 함.rO   r.   )re_WORKTREE_ROOTcompile	MULTILINEexistspytestskipnamer   searchr2   r3   r8   r9   r:   r4   r5   groupstripr6   r7   )r   	utils_dirtarget_files_IMPORT_ANU_V3_PATTERNfpathsource_textr   r?   @py_assert1rT   rU   s              r   +test_no_anu_v3_import_in_classifier_sourcesr      sc    (I6622L
  ZZ(PRTR^R^_ 	
||~KK5::,&bcdoowo7&--k: 	
u} 	
 	
u 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	  	
 	
  zzlRSXS^S^S`SfSfShRk lY Z	
 	
 	
 	
 	
	
r   )__doc__builtinsr8   _pytest.assertion.rewrite	assertionrewriter2   r   syspathlibr   __file__resolveparentsr   strpathinsertr   #utils.callback_lifecycle_classifierr   r   r   markparametrizerF   rV   r   r   r   r    r   r   <module>r      s   	   
  h'')11!4~chh&HHOOAs>*+  K H~%%'//2Z?BVVC   ) 
%
%XF$N(^(
r   