
    jbb                        d Z ddlZddlmc mZ ddl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 ddlmZ  ee      j                         j                  d   dz  d	z  Zg d
ZddgZdefdZd Zd Zd Zej@                  jC                  de      d        Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+d Z,ej@                  jC                  ddejZ                  fdej\                  fd ej^                  fd!ej`                  fd"ej`                  fd#ejb                  fd$ejd                  fg      d%        Z3d& Z4d' Z5d( Z6d) Z7d* Z8d+ Z9d, Z:d- Z;d. Z<d/ Z=ej@                  jC                  dg d0      d1        Z>d2ed3efd4Z?d5 Z@d6 ZAy)7u  Regression tests for merge_ready_classifier (task-2632).

규칙:
- 순수 함수 호출만 (merge 실행 0 · GitHub write 0 · live git status 조회 0 · subprocess 0)
- frozen fixture 만 입력 (tests/fixtures/merge_ready/) · live workspace 의존 0
- pytest 로 실행 가능

검증 범위:
- 17 fixture 각각 verdict + chair_triggers + credential_tier + critical7_hits + completeness 일치
- verdict precedence (UNKNOWN > CHAIR_REQUIRED > HOLD > PASS) 단언
- 각 verdict enum 도달 경로 커버
- credential 3계층 · Critical7 1:1 · Gemini auto-remediation · lifecycle incident 반영
- classifier 순수성(merge/write/live-git/subprocess 호출 0) 정적 검증

dev6 담당: 페룬
단일소스 스펙: memory/specs/system_merge_ready_executor_spec_260522.md
    N)Path   )classify_merge_ready)merge_ready_states   fixturesmerge_ready)pass_all_greenhold_ci_pendinghold_gemini_mediumhold_gemini_stalehold_unresolved_mediumchair_forbidden_pathchair_blocking_secretchair_net_new_identifierchair_out_of_scopechair_replacement_failchair_smoke_failchair_dependency_cyclechair_serial_collisionchair_admin_overridechair_lifecycle_incidentexisting_identifier_passthroughunknown_insufficient_evidenceutils/merge_ready_classifier.pyzutils/merge_ready_states.pynamec                     t         | z  }t        j                  |dz  j                  d            }t        j                  |dz  j                  d            }||fS )Nevidence.jsonutf-8encodingexpected.json)FIXTURE_ROOTjsonloads	read_text)r   baseevidenceexpecteds       C/home/jay/workspace/tests/regression/test_merge_ready_classifier.py_load_fixturer+   @   sY    $Dzz4/1<<g<NOHzz4/1<<g<NOHX    c                     | j                  d      xs i j                  d      xs t        }t        | t        j                  |      S )Nscopeexpected_filesanu_keysr/   )getEXPECTED_FILESr   SDEFAULT_ANU_KEYS)r(   declareds     r*   	_classifyr7   G   s<    W%+001ABTnH13E3EV^__r,   c            	         t        d t        j                         D              } t        t              }| |k(  }|sDt	        j
                  d|fd| |f      dt        j                         v st	        j                  |       rt	        j                  |       nddt        j                         v st	        j                  t               rt	        j                  t               nddt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }t	        j                  d|        d	z   d
|iz  }t        t	        j                  |            dx}}t        |       }d}||k(  }|st	        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                  |      t	        j                  |      dz  }t	        j                  dt        |              dz   d|iz  }t        t	        j                  |            dx}x}}t        D ]  }	t        |	z  }
dD ]  }|
|z  }|j                  } |       }|st	        j                  |	 d| d      dz   dt        j                         v st	        j                  |
      rt	        j                  |
      nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}x}} " y)uP   fixture 17종이 정확히 존재하고 각 dir 에 3파일이 있는지 검증.c              3   V   K   | ]!  }|j                         s|j                   # y wN)is_dirr   ).0ps     r*   	<genexpr>z2test_seventeen_fixtures_present.<locals>.<genexpr>R   s     GQAHHJ!&&Gs   ))==)z0%(py0)s == %(py5)s
{%(py5)s = %(py2)s(%(py3)s)
}dirssortedALL_FIXTURES)py0py2py3py5zfixture set mismatch: 
>assert %(py7)spy7N   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenrD   py1rF   py6zexpected 17 fixtures, got z
>assert %(py8)spy8)r   r"   zPROVENANCE.md/z missingzO
>assert %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = (%(py0)s / %(py1)s).exists
}()
}r'   fn)rD   rN   py4rO   )rB   r#   iterdirrC   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationrL   exists)rA   @py_assert4@py_assert1@py_format6@py_format8@py_assert2@py_assert5@py_format7@py_format9r   r'   rR   @py_assert3s                r*   test_seventeen_fixtures_presentrh   P   s6   G,"6"6"8GGD,'H4''HHH4'HHHHHH4HHH4HHHHHH6HHH6HHHHHH,HHH,HHH'HHH+A$)HHHHHHHt9DD9?DDD9DDDDDD3DDD3DDDDDDtDDDtDDD9DDDDDD8TDDDDDDDD @d"E 	@B2I?I%%?%'?'??D62$h)???????D???D??????2???2???%???'??????	@@r,   c                     d} t         | z  }|j                  } |       }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |       t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx} x}x}}d} t         | z  }|j                  } |       }|sddt        j                         v st	        j
                  t               rt	        j                  t               ndt	        j                  |       t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx} x}x}}t        d      \  }}t        d      \  }}|d   d   }d	}||u }	|	slt	        j                  d
|	fd||f      t	        j                  |      t	        j                  |      dz  }
dd|
iz  }t        t	        j                  |            dx}x}	}|d   d   }d}||u }	|	slt	        j                  d
|	fd||f      t	        j                  |      t	        j                  |      dz  }
dd|
iz  }t        t	        j                  |            dx}x}	}|d   d   }d	}||u }	|	slt	        j                  d
|	fd||f      t	        j                  |      t	        j                  |      dz  }
dd|
iz  }t        t	        j                  |            dx}x}	}|d   d   }d}||u }	|	slt	        j                  d
|	fd||f      t	        j                  |      t	        j                  |      dz  }
dd|
iz  }t        t	        j                  |            dx}x}	}y)uY   ANCHOR-2: chair_dependency_cycle 와 chair_serial_collision 은 분리된 별도 fixture.r   zMassert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).is_dir
}()
}r#   )rD   rE   rG   rI   Nr   	critical7dependency_cycleTis)z%(py1)s is %(py4)srN   rS   assert %(py6)srO   serial_only_collisionF)r#   r;   rW   rX   rU   rY   rZ   r\   r]   r+   rV   )r`   rg   r_   @py_assert6rb   cyc_ev_ser_ev@py_assert0rc   @py_format5re   s               r*   @test_dependency_cycle_and_serial_collision_are_separate_fixturesrw   [   sv   3=L33=3;;=;========L===L===3===;==========3=L33=3;;=;========L===L===3===;==========67IFA67IFA+12:d:2d::::2d:::2:::d:::::::+67@5@75@@@@75@@@7@@@5@@@@@@@+67?4?74????74???7???4???????+12;e;2e;;;;2e;;;2;;;e;;;;;;;r,   c                 D   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   }t        j                  }	||	v }|st        j                  d|fd||	f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |	      dz  }
t        j
                  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   }t        |      }|d   }t        |      }||k(  }|s]t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        j
                  d|  dt        |d          dt        |d                dz   d|iz  }t        t        j                  |            d
x}x}x}x}}|d   }t        |      }|d   }t        |      }||k(  }|sEt        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        j
                  d|  d|d          dz   d|iz  }t        t        j                  |            d
x}x}x}x}}|d   }t        |      }|d   }t        |      }||k(  }|s]t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        j
                  d|  d t        |d          dt        |d                dz   d|iz  }t        t        j                  |            d
x}x}x}x}}d!|v r|d!   }t        |      }|d!   }t        |      }||k(  }|s]t        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        j
                  d|  d"t        |d!          dt        |d!                dz   d|iz  }t        t        j                  |            d
x}x}x}x}}d#D ]  }||v }|st        j                  d|fd$||f      d%t        j                         v st        j                  |      rt        j                  |      nd%d&t        j                         v st        j                  |      rt        j                  |      nd&d'z  }t        j
                  d|  d(|       d)z   d*|iz  }t        t        j                  |            d
} |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}}y
).uH   각 fixture 의 evidence → classify → expected 정확 일치 검증.verdictr?   z%(py1)s == %(py4)srn   [z] verdict: got=z want=z
>assert %(py6)srO   Nin)z0%(py1)s in %(py5)s
{%(py5)s = %(py3)s.VERDICTS
}r4   rN   rF   rG   z] verdict not in enum: rH   rI   credential_tierz] credential_tier: got=evidence_completenessz] evidence_completeness: got=chair_triggers)zP%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py10)s
{%(py10)s = %(py6)s(%(py8)s)
}set)rD   rE   rS   rO   rP   py10z] chair_triggers set: got=z
>assert %(py12)spy12rL   u,   ] chair_triggers length(중복 의심): got=critical7_hitsz] critical7_hits set: got=auto_remediablez] auto_remediable set: got=)
ry   blocking_reasonsr   r   auto_merge_10_conditionsr   r   r   next_actionclassified_by)z%(py0)s in %(py2)sfieldresultrD   rE   z] missing return field: 
>assert %(py4)srS   r   zmerge-ready-classifierro   )r+   r7   rU   rV   rZ   r[   r\   r]   r4   VERDICTSrW   rX   rY   r   rB   rL   )r   r(   r)   r   ru   rg   rc   rv   re   r_   ra   rb   r`   @py_assert7@py_assert9rd   @py_format11@py_format13r   @py_format3s                       r*   #test_fixture_chairman_mapping_exactr   l   s	    't,Hhx F)  3  33   3        !4    D6	!2 5VHY<O;RS     )b

b
*bbb
bbbbbbbbbbbbbbb
bbbav5LVT]M^La,bbbbbbbb#$ 1B(C $(CC  $(C    %    )D    D6(0A)B(EVHUfLgKjk     )* h7N.O *.OO  *.O    +    /P    D6.v6M/N.Q R014	6    
 &' 3'( 9I0J C0J,K (,KK   (,K              (    )      -0    -0    1K    -L    D6+F6:J3K,L+M Nx 0123	5      &' 3'( 9I0J C0J,K (,KK   (,K              (    )      -0    -0    1K    -L    D6=fEU>V=WX      &' 3'( 9I0J C0J,K (,KK   (,K              (    )      -0    -0    1K    -L    D6+F6:J3K,L+M Nx 0123	5     
 H$+, 	
s,- 	
X>O5P 	
5P1Q 	
-1QQ 	
 	
 	
-1Q 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	 - 	
 	
 
	 . 	
 	
 
6	
 	
  25 	
 	
 
	 25 	
 	
 
	 6Q 	
 	
 
	 2R 	
 	
  v0?P8Q1R0S T8$5678:	
 	
 	
 	
 	
 	

K J IIIuIIIIIIuIIIuIIIIIIIIIIIII!D6)A% IIIIIIIJ /">&>>"&>>>>>"&>>>>">>>&>>>>>>>>r,   c                  z   t               } t        D ]-  }t        |      \  }}| j                  t	        |      d          / t
        j                  t
        j                  t
        j                  t
        j                  h}| |k(  }|st        j                  d|fd| |f      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dz  }t        j                   d|        dz   d|iz  }t#        t        j$                  |            d	x}}y	)
uC   17 fixture 가 4개 verdict enum 을 모두 도달하는지 검증.ry   r?   )z%(py0)s == %(py3)sverdictsrD   rF   znot all verdicts reached: 
>assert %(py5)srG   N)r   rC   r+   addr7   r4   PASSHOLDCHAIR_REQUIREDUNKNOWNrU   rV   rW   rX   rY   rZ   r[   r\   r]   )r   r   r(   rs   rc   r`   @py_format4ra   s           r*    test_all_four_verdicts_reachabler      s    uH 5#D)!Yx(345 (8(8!))D 8DD  8D              E    %XJ/    r,   c                  d    t        j                  t        dz  dz  j                  d            } | S )Nr
   r   r   r    )r$   r%   r#   r&   )r'   s    r*   _green_evidencer      s/    ::|&66HSS]dSefDKr,   c                     t        t                     d   } t        j                  }| |k(  }|st	        j
                  d|fd| |f      t	        j                  |       dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx} x}}y)	u'   깨끗한 evidence → PASS (terminal).ry   r?   z,%(py1)s == %(py5)s
{%(py5)s = %(py3)s.PASS
}r4   r~   assert %(py7)srI   N)r7   r   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   )ru   r_   rc   ra   rb   s        r*   test_precedence_pass_baseliner      s    _&'	2<aff<2f<<<<2f<<<2<<<<<<a<<<a<<<f<<<<<<<r,   c                     t               } d| d   d<   ddi| d   d<   t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd	||f      t	        j                  |      d
t        j                         v st	        j                  t              rt	        j                  t              nd
t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      d
t        j                         v st	        j                  t              rt	        j                  t              nd
t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)u=   auto_remediable(예: CI pending) 존재 → PASS 아닌 HOLD.Fgatesci_all_passbuildpending	ci_checksry   r?   z,%(py1)s == %(py5)s
{%(py5)s = %(py3)s.HOLD
}r4   r~   r   rI   Nr   r|   z5%(py2)s
{%(py2)s = %(py0)s.AR_CI_PENDING
} in %(py5)srD   rE   rG   )r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   AR_CI_PENDING	erru   r_   rc   ra   rb   r`   rg   s	            r*   test_precedence_hold_beats_passr      s   A %AgJ}&	2AgJ{!AY<!166!<6!!!!<6!!!<!!!!!!1!!!1!!!6!!!!!!!??2a 122?22222?222222212221222?22222222222r,   c                     t               } d| d   d<   ddi| d   d<   d| d   d	<   t        |       }|d
   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }t	        j                  d|d
          dz   d|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uP   chair trigger + auto_remediable 동시 존재 → CHAIR_REQUIRED (chair 우선).Fr   r   r   r   r   Trj   rk   ry   r?   z6%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CHAIR_REQUIRED
}r4   r~   zchair must beat hold, got rH   rI   Nr   r|   r   r   r   r   )zB%(py2)s
{%(py2)s = %(py0)s.CHAIR_DEPENDENCY_OR_SERIAL
} in %(py5)s)r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r[   r\   r]   r   CHAIR_DEPENDENCY_OR_SERIALr   s	            r*    test_precedence_chair_beats_holdr      s   A %AgJ}&	2AgJ{)-AkN%&!AY<X1++X<++XXX<+XXX<XXXXXX1XXX1XXX+XXX/I!I,-XXXXXXXX??2a 122?22222?222222212221222?22222222222''>1-=+>>'+>>>>>'+>>>>>>>1>>>1>>>'>>>+>>>>>>>>r,   c                     dddgiddid} t        | t        j                  t              }|d   }t        j                  }||k(  }|st        j                  d	|fd
||f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        j                  d|d          dz   d|iz  }t        t        j                  |            dx}x}}|d   }t        j                  }||k(  }|st        j                  d	|fd||f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }g }||k(  }|slt        j                  d	|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|d   }g }||k(  }|slt        j                  d	|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u^   core gate evidence 결핍 + chair 신호(blocking secret) 공존 → UNKNOWN (UNKNOWN 우선).zprecedence-unknown-beats-chairblocking_secret_hits<redacted-placeholder>rk   T)task_id
credentialrj   r0   ry   r?   z/%(py1)s == %(py5)s
{%(py5)s = %(py3)s.UNKNOWN
}r4   r~   zUNKNOWN must beat chair, got rH   rI   Nr   z/%(py1)s == %(py5)s
{%(py5)s = %(py3)s.MISSING
}r   r   rz   rn   ro   rO   r   )r   r4   r5   r3   r   rU   rV   rZ   rW   rX   rY   r[   r\   r]   MISSING)
r   r   ru   r_   rc   ra   rb   rg   rv   re   s
             r*   #test_precedence_unknown_beats_chairr      s    4-0H/IJ($/		A 	Q););N[AY<T199T<9$TTT<9TTT<TTTTTT1TTT1TTT9TTT(Ea	l^&TTTTTTTT$%22%2222%222%2222222222222222222$"$"$$$$"$$$$$$"$$$$$$$$"$"$$$$"$$$$$$"$$$$$$$r,   c            
         t         j                  } t         j                  }t         j                  } | ||      }|sOddt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |       dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx} x}x}}t         j                  } t         j                  }t         j                  } | ||      }|sOddt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |       dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx} x}x}}t         j                  } t         j                  }t         j                  } | ||      }|sOddt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |       dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx} x}x}}t         j                  } t         j                  }t         j                  } | ||      }| }|sOddt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |       dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx} x}x}x}}y)u]   precedence rank 헬퍼가 UNKNOWN<CHAIR<HOLD<PASS 순(우선순위 높을수록 낮은 rank).zassert %(py10)s
{%(py10)s = %(py2)s
{%(py2)s = %(py0)s.verdict_precedes
}(%(py5)s
{%(py5)s = %(py3)s.UNKNOWN
}, %(py8)s
{%(py8)s = %(py6)s.CHAIR_REQUIRED
})
}r4   )rD   rE   rF   rG   rO   rP   r   Nzassert %(py10)s
{%(py10)s = %(py2)s
{%(py2)s = %(py0)s.verdict_precedes
}(%(py5)s
{%(py5)s = %(py3)s.CHAIR_REQUIRED
}, %(py8)s
{%(py8)s = %(py6)s.HOLD
})
}zassert %(py10)s
{%(py10)s = %(py2)s
{%(py2)s = %(py0)s.verdict_precedes
}(%(py5)s
{%(py5)s = %(py3)s.HOLD
}, %(py8)s
{%(py8)s = %(py6)s.PASS
})
}zassert not %(py10)s
{%(py10)s = %(py2)s
{%(py2)s = %(py0)s.verdict_precedes
}(%(py5)s
{%(py5)s = %(py3)s.PASS
}, %(py8)s
{%(py8)s = %(py6)s.UNKNOWN
})
})r4   verdict_precedesr   r   rW   rX   rU   rY   rZ   r\   r]   r   r   )r`   r_   r   r   r   @py_assert11@py_format12s          r*   test_precedence_rank_monotonicr      s6   :aii:)9)9:i)9::::::::1:::1:::::::::a:::a:::i::::::::::::)9::::::::::7a..77.7777777717771777777777a777a777.7777777777777777777777-aff-aff-ff--------1---1---------a---a---f------a---a---f----------!!4!&&4!))4!&)44444444444q444q444!444444!444!444&444444!444!444)44444444444r,   c                  F   t               } d| d   d<   t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v}|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}y)uE   EXISTING_SYSTEM_IDENTIFIER 재사용은 fail 아님 · PASS 영향 0.Tr    existing_system_identifier_reuser   r?   )zG%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CRED_EXISTING_SYSTEM_IDENTIFIER
}r4   r~   r   rI   Nry   r   r   not in)zQ%(py2)s
{%(py2)s = %(py0)s.CHAIR_CREDENTIAL_PERMISSION_EXPANSION
} not in %(py5)sr   )r   r7   r4   CRED_EXISTING_SYSTEM_IDENTIFIERrU   rV   rZ   rW   rX   rY   r\   r]   r   %CHAIR_CREDENTIAL_PERMISSION_EXPANSIONr   s	            r*   &test_credential_existing_is_not_a_failr      s   A:>AlO67!AD1#D#DD#DDDDD#DDDDDDDDDD1DDD1DDD#DDDDDDDDY<!166!<6!!!!<6!!!<!!!!!!1!!!1!!!6!!!!!!!22M!<L:MM2:MMMMM2:MMMMMMM1MMM1MMM2MMM:MMMMMMMMr,   c                  
   t               } dg| d   d<   t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}t               }	d|	d   d<   t        |	      }
|
d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}|
d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}t        j                  }|
d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }d	d
|iz  }t        t	        j                  |            dx}x}}y)uO   BLOCKING_SECRET·NET_NEW → CHAIR_REQUIRED (credential·permission expansion).r   r   r   r   r?   z<%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CRED_BLOCKING_SECRET
}r4   r~   r   rI   Nry   r   r   r|   )zM%(py2)s
{%(py2)s = %(py0)s.CHAIR_CREDENTIAL_PERMISSION_EXPANSION
} in %(py5)sr   Tnet_new_identifier_exposure)z4%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CRED_NET_NEW
})r   r7   r4   CRED_BLOCKING_SECRETrU   rV   rZ   rW   rX   rY   r\   r]   r   r   CRED_NET_NEW)e1r1ru   r_   rc   ra   rb   r`   rg   e2r2s              r*   -test_credential_blocking_and_net_new_escalater      s   		B0H/IB|+,	2B :A$:$:: $::::: $:::: ::::::A:::A:::$::::::::i=,A,,,=,,,,,=,,,,=,,,,,,A,,,A,,,,,,,,,,,22Jb9I6JJ26JJJJJ26JJJJJJJ1JJJ1JJJ2JJJ6JJJJJJJJ		B6:B|23	2B 2ANN2 N2222 N222 222222A222A222N2222222i=,A,,,=,,,,,=,,,,=,,,,,,A,,,A,,,,,,,,,,,22Jb9I6JJ26JJJJJ26JJJJJJJ1JJJ1JJJ2JJJ6JJJJJJJJr,   c                  
   t               } dg| d   d<   d| d   d<   d| d   d<   t        |       d   }t        j                  }||k(  }|st	        j
                  d|fd	||f      t	        j                  |      d
t        j                         v st	        j                  t              rt	        j                  t              nd
t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uC   blocking + net_new 공존 시 더 위험한 BLOCKING_SECRET 채택.r   r   r   Tr   r   r   r?   r   r4   r~   r   rI   N)r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   )r   ru   r_   rc   ra   rb   s         r*   5test_credential_tier_precedence_blocking_over_net_newr     s    A/G.HAlO*+59AlO12:>AlO67Q<)*Da.D.DD*.DDDDD*.DDDD*DDDDDDaDDDaDDD.DDDDDDDDr,   zname,c7_enumr   r   r   r   r   r   r   c           	      $   t        |       \  }}t        |      }|d   }||v }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d|  d| d|d          d	z   d
|iz  }t        t        j                  |            dx}}|d   }	t        j                  }
|	|
k(  }|st        j                  d|fd|	|
f      t        j                  |	      dt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}	x}}
t        j                  }|d   }
||
v }|st        j                  d|fd||
f      dt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}}
y)u;   Critical7 신호 → 해당 C7 enum hit → CHAIR_REQUIRED.r   r|   )z%(py0)s in %(py3)sc7_enumr   r{   z] z not in r   rG   Nry   r?   r   r4   r~   r   rI   r   )z7%(py2)s
{%(py2)s = %(py0)s.CHAIR_CRITICAL7
} in %(py5)sr   )r+   r7   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r4   r   CHAIR_CRITICAL7)r   r   r(   rs   r   rc   r`   r   ra   ru   r_   rb   rg   s                r*   test_critical7_mappingr     s     %KHa(A()]7))]]]7)]]]]]]7]]]7]]])]]]QtfBwixJZH[G\+]]]]]]]Y<+1+++<+++++<++++<++++++1+++1+++++++++++3"2 33 33333 333333313331333333 33333333r,   c                  d   t               } d| d   d<   d| d   d<   d| d   d<   t        |       }t        j                  }|d   }||v }|st	        j
                  d	|fd
||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d	|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)ud   out_of_expected + replacement_pr_failure 동시 → Critical7 #2 (C7_OUT_OF_SCOPE_REPLACEMENT_FAIL).Tr.   "out_of_expected_files_modificationFexact_matchrj   replacement_pr_failurer   r|   )zH%(py2)s
{%(py2)s = %(py0)s.C7_OUT_OF_SCOPE_REPLACEMENT_FAIL
} in %(py5)sr4   r   r   rI   N)z;%(py2)s
{%(py2)s = %(py0)s.C7_REPLACEMENT_FAIL
} in %(py5)sry   r?   r   r~   )r   r7   r4    C7_OUT_OF_SCOPE_REPLACEMENT_FAILrU   rV   rW   rX   rY   rZ   r\   r]   C7_REPLACEMENT_FAILr   )	r   r   r`   r_   rg   ra   rb   ru   rc   s	            r*   -test_out_of_scope_replacement_fail_combo_c7_2r   "  s   A7;AgJ34 %AgJ}/3AkN+,!A--D3C1DD-1DDDDD-1DDDDDDD1DDD1DDD-DDD1DDDDDDDD  7A&6$77 $77777 $777777717771777 777$77777777Y<+1+++<+++++<++++<++++++1+++1+++++++++++r,   c                     t        d      \  } }t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}t        j                  }|d
   }||v }	|	st	        j
                  d|	fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}	}|d   }g }	||	k(  }|slt	        j
                  d|fd||	f      t	        j                  |      t	        j                  |	      dz  }
dd|
iz  }t        t	        j                  |            d	x}x}}	y	)uV   medium + expected_files 내부 + Critical7 0 + credential 0 → HOLD(auto_remediable).r   ry   r?   r   r4   r~   r   rI   Nr   r|   )zH%(py2)s
{%(py2)s = %(py0)s.AR_GEMINI_MEDIUM_WITHIN_EXPECTED
} in %(py5)sr   r   rz   rn   ro   rO   )r+   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]    AR_GEMINI_MEDIUM_WITHIN_EXPECTED)r(   rs   r   ru   r_   rc   ra   rb   r`   rg   rv   re   s               r*   :test_gemini_medium_within_expected_is_hold_auto_remediabler   2  sZ    45KHa(AY<!166!<6!!!!<6!!!<!!!!!!1!!!1!!!6!!!!!!!--E3D1EE-1EEEEE-1EEEEEEE1EEE1EEE-EEE1EEEEEEEE$"$"$$$$"$$$$$$"$$$$$$$r,   c                     t               } dddddg| d   d<   d| d   d	<   t        |       }|d
   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}|d   }g }||k(  }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}}y)uh   non-critical HIGH + expected_files 내부(반복 아님·scope 확장 아님) → HOLD(auto_remediable).highr   TFseveritypathwithin_expected_filesresolvedgeminigemini_findingsr   high_or_critical_unresolvedry   r?   r   r4   r~   r   rI   Nr   r|   )zR%(py2)s
{%(py2)s = %(py0)s.AR_GEMINI_NONCRITICAL_HIGH_WITHIN_EXPECTED
} in %(py5)sr   r   rz   rn   ro   rO   )r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   *AR_GEMINI_NONCRITICAL_HIGH_WITHIN_EXPECTED)r   r   ru   r_   rc   ra   rb   r`   rg   rv   re   s              r*   4test_gemini_noncritical_high_within_expected_is_holdr   ;  s   A%F"&E	;&AhK!" 23AhK-.!AY<!166!<6!!!!<6!!!<!!!!!!1!!!1!!!6!!!!!!!77O1=N;OO7;OOOOO7;OOOOOOO1OOO1OOO7OOO;OOOOOOOO$"$"$$$$"$$$$$$"$$$$$$$r,   c                     t               } dddddg| d   d<   d| d   d<   t        |       }|d	   }t        j                  }||k(  }|st	        j
                  d
|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uP   같은 함수 HIGH 반복 → auto-remediation loop boundary → CHAIR_REQUIRED.r   r   TFr   r   r   repeated_high_same_functionry   r?   r   r4   r~   r   rI   Nr   r|   )zL%(py2)s
{%(py2)s = %(py0)s.CHAIR_AUTO_REMEDIATION_LOOP_BOUNDARY
} in %(py5)sr   )r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   $CHAIR_AUTO_REMEDIATION_LOOP_BOUNDARYr   s	            r*   7test_gemini_repeated_high_same_function_escalates_chairr   I  s6   A%F"&E	;&AhK!" 26AhK-.!AY<+1+++<+++++<++++<++++++1+++1+++++++++++11HQ7G5HH15HHHHH15HHHHHHH1HHH1HHH1HHH5HHHHHHHHr,   c                     t               } dddddg| d   d<   t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd	||f      t	        j                  |      d
t        j                         v st	        j                  t              rt	        j                  t              nd
t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      d
t        j                         v st	        j                  t              rt	        j                  t              nd
t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uY   HIGH/medium 이 expected_files 밖/scope 확장 요구 → CHAIR_REQUIRED (Critical7 #3).r   zanu_v3/runtime/x.pyFr   r   r   ry   r?   r   r4   r~   r   rI   Nr   r|   )z:%(py2)s
{%(py2)s = %(py0)s.C7_SCOPE_EXPANSION
} in %(py5)sr   )r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   C7_SCOPE_EXPANSIONr   s	            r*   0test_gemini_high_out_of_expected_escalates_chairr   V  s'   A%:"'U	<&AhK!" 	!AY<+1+++<+++++<++++<++++++1+++1+++++++++++61%5#66#66666#666666616661666666#66666666r,   c                     t        d      \  } }t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}t        j                  }|d
   }||v }	|	st	        j
                  d|	fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}	}y	)uP   classification=INCIDENT → chair_trigger LIFECYCLE_INCIDENT → CHAIR_REQUIRED.r   ry   r?   r   r4   r~   r   rI   Nr   r|   z@%(py2)s
{%(py2)s = %(py0)s.CHAIR_LIFECYCLE_INCIDENT
} in %(py5)sr   )r+   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   CHAIR_LIFECYCLE_INCIDENT)
r(   rs   r   ru   r_   rc   ra   rb   r`   rg   s
             r*   'test_lifecycle_incident_escalates_chairr   f  s    :;KHa(AY<+1+++<+++++<++++<++++++1+++1+++++++++++%%<+;)<<%)<<<<<%)<<<<<<<1<<<1<<<%<<<)<<<<<<<<r,   c                     t               } d| d   d<   d| d   d<   d| d   d<   t        |       }|d   }t        j                  }||k(  }|st	        j
                  d	|fd
||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uj   closeout callback 이 ANU 가 아닌 self-key 로 fired → owner key 교차확인 → incident → CHAIR.normal	lifecycleclassification1e41a2324a3ccdd0	owner_keyTfiredry   r?   r   r4   r~   r   rI   Nr   r|   r   r   )r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   r   r   s	            r*   =test_lifecycle_self_key_fired_non_authoritative_via_owner_keyr  n  s/   A'/AkN#$"4AkN;"AkN7!AY<+1+++<+++++<++++<++++++1+++1+++++++++++%%<+;)<<%)<<<<<%)<<<<<<<1<<<1<<<%<<<)<<<<<<<<r,   c                     t               } d| d   d<   d| d   d<   t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      d	t        j                         v st	        j                  t              rt	        j                  t              nd	t	        j                  |      d
z  }dd|iz  }t        t	        j                  |            dx}x}}t        j                  }|d   }||v}|st	        j
                  d|fd||f      d	t        j                         v st	        j                  t              rt	        j                  t              nd	t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uD   ANU authoritative key 로 fired → incident 아님 → PASS 유지.c119085addb0f8b7r  r  Tr  ry   r?   r   r4   r~   r   rI   Nr   r   )zD%(py2)s
{%(py2)s = %(py0)s.CHAIR_LIFECYCLE_INCIDENT
} not in %(py5)sr   )r   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   r   r   s	            r*   &test_lifecycle_anu_key_fired_is_normalr	  z  s   A"4AkN;"AkN7!AY<!166!<6!!!!<6!!!<!!!!!!1!!!1!!!6!!!!!!!%%@Q/?-@@%-@@@@@%-@@@@@@@1@@@1@@@%@@@-@@@@@@@@r,   c                     t        d      \  } }t        |       d   }t        |t              }|sd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dt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}|j                  } |       }t        |      }t        j                  }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                  |      t        j                  |      t        j                  |      dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |	      d	z  }dd|iz  }t        t        j                  |            dx}x}x}x}
x}}	t!        |      }d}||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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}d |j#                         D        }t%        |      }|sddt	        j
                         v st        j                  t$              rt        j                  t$              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}|j"                  } |       }t%        |      }|st        j&                  d|       dz   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                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}}y)u`   auto_merge_10_conditions 는 정확히 10개 키의 bool dict · pass_all_green 은 전부 True.r
   r   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceconddict)rD   rN   rE   rS   Nr?   )z%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.keys
}()
})
} == %(py14)s
{%(py14)s = %(py9)s(%(py12)s
{%(py12)s = %(py10)s.AUTO_MERGE_10_CONDITION_KEYS
})
}rB   r4   )	rD   rN   rF   rG   rI   py9r   r   py14zassert %(py16)spy16
   rK   rL   rM   zassert %(py8)srP   c              3   <   K   | ]  }t        |t                y wr:   )r  bool)r<   vs     r*   r>   z6test_auto_merge_10_conditions_shape.<locals>.<genexpr>  s     :qz!T":s   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allrD   rE   rS   u0   pass_all_green 10조건 전부 True 여야 함: za
>assert %(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.values
}()
})
})rD   rN   rF   rG   rI   )r+   r7   r  r  rW   rX   rU   rY   rZ   r\   r]   keysrB   r4   AUTO_MERGE_10_CONDITION_KEYSrV   rL   valuesr  r[   )r(   rs   r  rg   rv   rc   r_   rq   r   @py_assert13@py_assert8@py_format15@py_format17rd   re   rf   r`   rb   s                     r*   #test_auto_merge_10_conditions_shaper    sR    01KHaX9:DdD!!!!!!!!:!!!:!!!!!!d!!!d!!!!!!D!!!D!!!!!!!!!!))H)+H6+H)G)GH&)G"HH"HHHHH"HHHHHHH6HHH6HHHHHH$HHH$HHH)HHH+HHHHHHHHH&HHH&HHHHHHHHHHHH)GHHH"HHHHHHHHHt99?933tt9:DKKM::3:::::::::3:::3::::::::::::::{{X{}X3}XXX!QRVQWXXXXXXX3XXX3XXXXXXtXXXtXXX{XXX}XXXXXXXXXr,   c                     t        d      \  } }t        |       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}|d
   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}d}|d   }||v }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            d	x}x}}d}|d   }||v }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            d	x}x}}y	)uV   UNKNOWN fixture → MISSING + 핵심 source(scope/gates) 가 missing 목록에 포함.r   ry   r?   r   r4   r~   r   rI   Nr   r   r.   missing_evidence_sourcesr|   )z%(py1)s in %(py4)srn   ro   rO   r   )r+   r7   r4   r   rU   rV   rZ   rW   rX   rY   r\   r]   r   )r(   rs   r   ru   r_   rc   ra   rb   rg   rv   re   s              r*   )test_unknown_returns_missing_core_sourcesr!    s    ?@KHa(AY<$199$<9$$$$<9$$$<$$$$$$1$$$1$$$9$$$$$$$$%22%2222%222%22222222222222222223a233733333733337333333333333a23373333373333733333333333r,   )r
   r   r   c                    t        |       \  }}t        |      }t        |      }||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|  d      dz   d	|iz  }t        t        j                  |            d }y )
Nr?   )z%(py0)s == %(py2)sabr   r{   u   ] 비결정적 결과r   rS   )r+   r7   rU   rV   rW   rX   rY   rZ   r[   r\   r]   )r   r(   rs   r#  r$  r`   r   rv   s           r*   test_determinismr%    s    %KHa(A(A62221222222122212222222222222Qtf12222222r,   srcreturnc                 L   ddl }ddl}g }|j                  |j                  |       j                        D ]]  }|j
                  |j                  |j                  fv r(|j
                  t        |dd      k(  rC|j                  |j                         _ dj                  |      S )u  문자열 리터럴/주석/f-string 텍스트를 제거하고 실제 코드 토큰만 남긴다.

    docstring·주석에서 'subprocess' 등을 '언급'하는 것은 허용하기 위함 —
    금지되는 것은 실제 import/호출 코드뿐이다.
    r   NFSTRING_MIDDLE )iotokenizegenerate_tokensStringIOreadlinetypeSTRINGCOMMENTgetattrappendstringjoin)r&  r,  r-  outtoks        r*   
_code_onlyr:    s     
C''C(8(A(AB 88)9)9::88wx)92>>

3:: 88C=r,   c            	         t         dz  } | dz  | dz  g}t        j                  d      }t        j                  d      }|D ]  }|j                  } |       }|st	        j
                  | d      dz   dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      d	z  }t        t	        j                  |            d
x}}|j                  d      }t        |      }	|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}}|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#                         d      dz   d|iz  }t        t	        j                  |            d
x}}dD ]  }||	v}|st	        j                  d|fd||	f      dt        j                         v st	        j                  |      rt	        j                  |      nddt        j                         v st	        j                  |	      rt	        j                  |	      nddz  }t	        j
                  |j                    d| d      d z   d!|iz  }t        t	        j                  |            d
}  y
)"u   classifier/states 소스에 subprocess/network/file-write/live-git/merge 호출이 없음을 정적 검증.

    docstring/주석에서 단어를 언급하는 것은 허용(코드 토큰만 검사). 금지: 실제 import/호출 구문.
    utilszmerge_ready_classifier.pyzmerge_ready_states.pyz\b(import\s+(subprocess|requests|urllib|socket|http|os|sys|pathlib)\b|from\s+(subprocess|requests|urllib|socket|http|os|sys|pathlib|anu_v3)\b)zk(subprocess\s*\.|os\s*\.\s*system|os\s*\.\s*popen|requests\s*\.|urllib\s*\.|socket\s*\.|check_output|Popen)z
 not foundzC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}fpathr  Nr   r    rl   )z%(py0)s is %(py3)sm1r   u   : 금지된 import 발견 (uA   ). classifier 는 evidence-only decoupled · I/O 0 이어야 함.r   rG   m2u%   : 금지된 I/O/merge 호출 발견 (z).)
subprocessPopencheck_outputr   )z%(py0)s not in %(py2)stokencoder   u   : 금지 코드 토큰 'u   ' 발견r   rS   )_WORKTREE_ROOTrecompiler^   rU   r[   rW   rX   rY   rZ   r\   r]   r&   r:  searchrV   r   groupstrip)	utils_dirtargetsforbidden_importforbidden_callr=  r`   rg   rv   r&  rD  r>  rc   r   ra   r?  rC  r   s                    r*   1test_classifier_sources_have_no_io_or_merge_callsrO    s   
 (I//++G zz	U ZZ	+N  ]||3|~3~33%
3333333u333u333|333~333333oowo/#$$T* 	
rTz 	
 	
rT 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	  	
 	
  zzl5bhhj6F6F6H5K LM N	
 	
 	
 	
 	
 ""4( 	
rTz 	
 	
rT 	
 	
	6	
 	
   	
 	
 		  	
 	
 		  	
 	
  zzl?
~RP	
 	
 	
 	
 	
 = 	]E$\\\5\\\\\\5\\\5\\\\\\\\\\\\\4LUGS[&\\\\\\\	]]r,   c                      ddl } ddlm} | j                  |       |j                  }t        |      }|sd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                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)uT   classifier import 만으로 부작용/네트워크/daemon 이 없음(순수 import).r   NzVassert %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.classify_merge_ready
})
}callablem)rD   rN   rF   rG   )	importlibutils.merge_ready_classifiermerge_ready_classifierreloadr   rQ  rW   rX   rU   rY   rZ   r\   r]   )rS  rR  rc   r_   ra   s        r*   -test_classifier_is_importable_without_runtimerW    s    ,Q**+8*++++++++8+++8++++++A+++A+++*++++++++++r,   )B__doc__builtinsrW   _pytest.assertion.rewrite	assertionrewriterU   r$   rF  syspathlibr   __file__resolveparentsrE  strr   insertpytestrT  r   r<  r   r4   r#   rC   r3   r+   r7   rh   rw   markparametrizer   r   r   r   r   r   r   r   r   r   r   C7_FORBIDDEN_PATHr   C7_OVERRIDEC7_DEPENDENCY_CYCLE_OR_SERIALr   C7_POST_MERGE_SMOKE_FAILr   r   r   r   r   r   r   r  r	  r  r!  r%  r:  rO  rW   r,   r*   <module>rl     s&  $   	 
  h'')11!4~chh&HHOOAs>*+  = ) H~%%'//2Z?-O( 45RS `@
<" .'? /'?\
=
3?% 5NK"E Q0011//0Q]]+q>>?q>>?q445334* 44	, %%
I	7 =	=AY4 !jk3 l3C C &!]H,r,   