
    jK                        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 ddlZ ee      j                         j                  d   Z ee      e	j$                  vr"e	j$                  j'                  d ee             ddlm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 Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%ejL                  jO                  de      d        Z(ejL                  jO                  de      d        Z)ejL                  jO                  de      d        Z*ejL                  jO                  de      d        Z+ejL                  jO                  de      d        Z,d Z-d Z.d Z/d Z0d Z1d  Z2d! Z3d" Z4d# Z5d$ Z6ejL                  jO                  de      d%        Z7d& Z8y)'u  Regression tests for merge_ready_dryrun_executor (task-2633).

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

검증 범위:
- verdict 4값(PASS/HOLD/CHAIR_REQUIRED/UNKNOWN) → 3종 routing artifact 매핑 전부 커버
- 안전 불변식: actually_executed=false · executor_action WOULD_* 접두사 · 3종 schema id
- 결정적 idempotency: 동일 입력 2회 → byte-identical 출력
- auto_remediable → sub-action 매핑 (CI_PENDING / GEMINI_MEDIUM_WITHIN_EXPECTED)
- UNKNOWN → reason=INSUFFICIENT_EVIDENCE 표식
- 정적 검증: 모듈 코드에 merge/push/PR/subprocess/network/open(write) 호출 0

dev6 담당: 페룬
단일소스 스펙: memory/specs/system_merge_ready_executor_dryrun_spec_260522.md
    N)Path   )merge_ready_dryrun_executor)merge_ready_states)classify_merge_ready   fixturesmerge_ready_dryrun)pass_routinghold_routing_ci_pendinghold_routing_gemini_mediumchair_routing_critical7chair_routing_credentialunknown_routingidempotent_routingc                     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)namebaseevidenceexpecteds       H/home/jay/workspace/tests/regression/test_merge_ready_dryrun_executor.py_loadr!   5   sY    $Dzz4/1<<g<NOHzz4/1<<g<NOHX    c                 :    t        j                  | d   | d         S )Nclassifier_resultpr_identity)Edryrun_route)r   s    r    _router(   <   s    >>(#67-9PQQr"   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 ]  }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 )Nc              3   V   K   | ]!  }|j                         s|j                   # y w)N)is_dirr   ).0ps     r    	<genexpr>z4test_all_routing_fixtures_present.<locals>.<genexpr>E   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: z
>assert %(py7)spy7)r   r   zPROVENANCE.md/z missingzO
>assert %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = (%(py0)s / %(py1)s).exists
}()
}r   fn)r5   py1py4py6)r2   r   iterdirr3   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationexists)r1   @py_assert4@py_assert1@py_format6@py_format8r   r   r;   @py_assert2@py_assert3@py_assert5@py_format7s               r    !test_all_routing_fixtures_presentrR   D   s   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 @d"E 	@B2I?I%%?%'?'??D62$h)???????D???D??????2???2???%???'??????	@@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}}|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}||u }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            d x}x}}||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  }dd|iz  }	t        t	        j                  |	            d }y )Nr   schemar/   )zC%(py1)s == %(py5)s
{%(py5)s = %(py3)s.SCHEMA_AUTO_MERGE_CANDIDATE
}r&   r<   r7   r8   assert %(py7)sr9   verdict)z,%(py1)s == %(py5)s
{%(py5)s = %(py3)s.PASS
}Sexecutor_action)z:%(py1)s == %(py5)s
{%(py5)s = %(py3)s.ACTION_WOULD_MERGE
}requires_chair_activationTisz%(py1)s is %(py4)sr<   r=   assert %(py6)sr>   z%(py0)s == %(py2)sartexpr5   r6   assert %(py4)sr=   )r!   r(   r&   SCHEMA_AUTO_MERGE_CANDIDATEr@   rA   rE   rB   rC   rD   rG   rH   rX   PASSACTION_WOULD_MERGEevrb   ra   @py_assert0rJ   rN   rL   rM   rO   @py_format5rQ   rK   @py_format3s                r    (test_pass_routes_to_auto_merge_candidaterm   Q   s5   N#GB
*Cx=9A999=99999=9999=999999A999A99999999999y>#QVV#>V####>V###>######Q###Q###V####### !9Q%9%99!%99999!%9999!999999Q999Q999%99999999*+3t3+t3333+t333+333t3333333#:3#33##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}}|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t        j                  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}}||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  }dd|iz  }	t        t	        j                  |	            d }y )Nr   rT   r/   zC%(py1)s == %(py5)s
{%(py5)s = %(py3)s.SCHEMA_REMEDIATION_REQUIRED
}r&   rU   rV   r9   rW   z,%(py1)s == %(py5)s
{%(py5)s = %(py3)s.HOLD
}rX   rY   zC%(py1)s == %(py5)s
{%(py5)s = %(py3)s.ACTION_WOULD_AUTO_REMEDIATE
}
CI_PENDINGitemactionremediation_planinz%(py1)s in %(py4)sr^   r_   r>   r`   ra   rb   rc   rd   r=   )r!   r(   r&   SCHEMA_REMEDIATION_REQUIREDr@   rA   rE   rB   rC   rD   rG   rH   rX   HOLDACTION_WOULD_AUTO_REMEDIATEACTION_WOULD_WAIT_RECHECKrh   s                r    3test_hold_ci_pending_routes_to_remediation_requiredr~   [   sD   -.GB
*Cx=9A999=99999=9999=999999A999A99999999999y>#QVV#>V####>V###>######Q###Q###V####### !BQ%B%BB!%BBBBB!%BBBB!BBBBBBQBBBQBBB%BBBBBBBB A,G,GHcCPbLccHLcccccHLccccHcccLcccccccc#:3#33##r"   c                  Z   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   }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                  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   }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}}||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  }dd|iz  }	t        t	        j                  |	            d }y ) Nr   rT   r/   ro   r&   rU   rV   r9   rW   rp   rX   rY   rq   GEMINI_MEDIUM_WITHIN_EXPECTEDrs   rv   rw   ry   r^   r_   r>   loop_boundary_guard)z@%(py1)s == %(py5)s
{%(py5)s = %(py3)s.LOOP_BOUNDARY_GUARD_TEXT
}next_recheck)z;%(py1)s == %(py5)s
{%(py5)s = %(py3)s.NEXT_RECHECK_ACTION
}r`   ra   rb   rc   rd   r=   )r!   r(   r&   rz   r@   rA   rE   rB   rC   rD   rG   rH   rX   r{   r|   2ACTION_WOULD_AUTO_FIX_REGRESS_PUSH_RESOLVE_RECHECKLOOP_BOUNDARY_GUARD_TEXTNEXT_RECHECK_ACTIONrh   s                r    6test_hold_gemini_medium_routes_to_remediation_requiredr   e   s{   01GB
*Cx=9A999=99999=9999=999999A999A99999999999y>#QVV#>V####>V###>######Q###Q###V####### !BQ%B%BB!%BBBBB!%BBBB!BBBBBBQBBBQBBB%BBBBBBBB/FF ! 
	 !  
!! ! ! !  
!! ! !y ! ! !y	 ! ! ! ! ! ! ! $%C)C)CC%)CCCCC%)CCCC%CCCCCCCCCCCC)CCCCCCCC~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"77777777#:3#33##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}}|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}	}d}|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}||v}|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd|iz  }t        t	        j                  |            d x}}||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  }d#d$|iz  }
t        t	        j                  |
            d }y )%Nr   rT   r/   z=%(py1)s == %(py5)s
{%(py5)s = %(py3)s.SCHEMA_HOLD_FOR_CHAIR
}r&   rU   rV   r9   rW   z6%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CHAIR_REQUIRED
}rX   rY   zC%(py1)s == %(py5)s
{%(py5)s = %(py3)s.ACTION_WOULD_ESCALATE_CHAIR
}chair_triggersrw   )z7%(py2)s
{%(py2)s = %(py0)s.CHAIR_CRITICAL7
} in %(py5)sr5   r6   r8   C7_FORBIDDEN_PATHreport_envelopeevidence_refsry   r^   r_   r>   reasonnot inz%(py1)s not in %(py3)sra   r<   r7   assert %(py5)sr8   r`   rb   rc   rd   r=   )r!   r(   r&   SCHEMA_HOLD_FOR_CHAIRr@   rA   rE   rB   rC   rD   rG   rH   rX   CHAIR_REQUIREDACTION_WOULD_ESCALATE_CHAIRCHAIR_CRITICAL7)ri   rb   ra   rj   rJ   rN   rL   rM   rK   rO   rk   rQ   @py_format4rl   s                 r    -test_chair_critical7_routes_to_hold_for_chairr   t   s   -.GB
*Cx=3A333=33333=3333=333333A333A33333333333y>-Q--->----->---->------Q---Q----------- !BQ%B%BB!%BBBBB!%BBBB!BBBBBBQBBBQBBB%BBBBBBBB5$4 55 55555 555555515551555555 55555555I#&7"8"II"IIIII"IIIIIII"IIIIIIII8383833#:3#33##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}}|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!        j"                  |d      }
g }d}||
v}|}|sd}||
v }|}|sXt	        j
                  d|fd||
f      t	        j                  |      dt        j                         v st	        j                  |
      rt	        j                  |
      nddz  }dd|iz  }|j%                  |       |st	        j
                  dfd|
f      t	        j                  |      dt        j                         v st	        j                  |
      rt	        j                  |
      nddz  }dd|iz  }|j%                  |       t	        j&                  |d      i z  }d d!|iz  }t        t	        j                  |            d x}x}x}x}x}}||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  }d&d'|iz  }t        t	        j                  |            d }y )(Nr   rT   r/   r   r&   rU   rV   r9   rW   r   rX   rY   r   r   rw   )zM%(py2)s
{%(py2)s = %(py0)s.CHAIR_CREDENTIAL_PERMISSION_EXPANSION
} in %(py5)sr   Fensure_asciizghp-PAT-placeholderredactedr   )z%(py3)s not in %(py5)sraw)r7   r8   z%(py7)s)z%(py10)s in %(py12)s)py10py12%(py14)spy14r   zassert %(py17)spy17r`   ra   rb   rc   rd   r=   )r!   r(   r&   r   r@   rA   rE   rB   rC   rD   rG   rH   rX   r   r   %CHAIR_CREDENTIAL_PERMISSION_EXPANSIONr   dumpsappend_format_boolop)ri   rb   ra   rj   rJ   rN   rL   rM   rK   rO   r   @py_assert9@py_assert11@py_format13@py_format15@py_format16@py_format18rl   rk   s                      r    .test_chair_credential_routes_to_hold_for_chairr      s<   ./GB
*Cx=3A333=33333=3333=333333A333A33333333333y>-Q--->----->---->------Q---Q----------- !BQ%B%BB!%BBBBB!%BBBB!BBBBBBQBBBQBBB%BBBBBBBB22Kc:J6KK26KKKKK26KKKKKKK1KKK1KKK2KKK6KKKKKKKK
**Su
-C@ @ +@z@zS/@@@@@ @@@ @@@@@@@@@@@@@@@@zS@@@z@@@@@@S@@@S@@@@@@@@@@@@@@#:3#33##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}}|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   }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}}||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  }dd|iz  }	t        t	        j                  |	            d }y )Nr   rT   r/   r   r&   rU   rV   r9   rW   z/%(py1)s == %(py5)s
{%(py5)s = %(py3)s.UNKNOWN
}rX   rY   z=%(py1)s == %(py5)s
{%(py5)s = %(py3)s.ACTION_WOULD_REGATHER
}r   zD%(py1)s == %(py5)s
{%(py5)s = %(py3)s.REASON_INSUFFICIENT_EVIDENCE
}r   z%(py1)s == %(py4)sr^   r_   r>   r`   ra   rb   rc   rd   r=   )r!   r(   r&   r   r@   rA   rE   rB   rC   rD   rG   rH   rX   UNKNOWNACTION_WOULD_REGATHERREASON_INSUFFICIENT_EVIDENCErh   s                r    .test_unknown_routes_to_hold_for_chair_regatherr      s   %&GB
*Cx=3A333=33333=3333=333333A333A33333333333y>&QYY&>Y&&&&>Y&&&>&&&&&&Q&&&Q&&&Y&&&&&&& !<Q%<%<<!%<<<<<!%<<<<!<<<<<<Q<<<Q<<<%<<<<<<<<x=:A:::=:::::=::::=::::::A:::A::::::::::: &B& B&&&& B&&& &&&B&&&&&&&#:3#33##r"   r   c                 &   t        |       \  }}t        |      }|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   }	t        |	t              }
|
sd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z  }t        t        j                  |            d x}	}
y )Nactually_executedFr[   r]   r^   r_   r>   z5assert %(py5)s
{%(py5)s = %(py0)s(%(py2)s, %(py3)s)
}
isinstanceboolr4   )r!   r(   r@   rA   rE   rG   rH   r   r   rB   rC   rD   )r   ri   _ra   rj   rO   rN   rk   rQ   rK   rJ   rL   s               r    )test_invariant_actually_executed_is_falser      s    $KEB
*C"#,u,#u,,,,#u,,,#,,,u,,,,,,,-.5:.55555555:555:555.5555555555555555555r"   c                 ,   t        |       \  }}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                  }d} ||      }|st        j                  |  d|      d	z   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}}t        j                  }||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                  t              rt        j                  t              ndt        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}}y )NrY   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}r   ru   str)r5   r<   r6   r=   WOULD_z: executor_action=N
>assert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.startswith
}(%(py4)s)
}r5   r6   r=   r>   rw   )z<%(py0)s in %(py4)s
{%(py4)s = %(py2)s.ALL_EXECUTOR_ACTIONS
}r&   r5   r6   r=   r_   r>   )r!   r(   r   r   rB   rC   r@   rD   rE   rG   rH   
startswithrF   r&   ALL_EXECUTOR_ACTIONSrA   )
r   ri   r   ra   ru   rO   rk   rK   rP   rQ   s
             r    +test_invariant_executor_action_would_prefixr      s   $KEB
*C"#Ffc"""""""":""":""""""f"""f""""""c"""c""""""""""MXMX&M&MM4&0B6*(MMMMMMM6MMM6MMMMMMXMMM&MMMMMM+++6+++++6+++++++6+++6++++++Q+++Q+++++++++++r"   c                    t        |       \  }}t        |      }|d   }t        j                  t        j                  t        j
                  f}||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )NrT   rw   ry   r^   r_   r>   )r!   r(   r&   re   rz   r   r@   rA   rE   rG   rH   )	r   ri   r   ra   rj   rO   rN   rk   rQ   s	            r    %test_invariant_schema_is_one_of_threer      s    $KEB
*Cx= 	%%	%%	 =    	=    	    	     	  r"   c                 t   t        |       \  }}t        |      }|d   }|d   }g }|j                  }d} ||      }	|	}
|	sd}|}
t        |
      }||k(  }|sddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |	      dz  }|j                  |       |	s+ddt        j                        iz  }|j                  |       t        j                  |d	      i z  }t        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}x}
x}x}x}x}	x}}|d   }g }
|j                  }d} ||      }|}|sd}|}||k(  }|s3ddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }|
j                  |       |s+ddt        j                        iz  }|
j                  |       t        j                  |
d	      i z  }t        j                  d
|fd||f      t        j                  |      |dz  }dd|iz  }t        t        j                  |            dx}x}x}x}
x}x}x}}|d   }g }
|j                  }d} ||      }|}|sd}|}||k(  }|s3ddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }|
j                  |       |s+ddt        j                  |      iz  }|
j                  |       t        j                  |
d	      i z  }t        j                  d
|fd||f      t        j                  |      |dz  }dd|iz  }t        t        j                  |            dx}x}x}x}
x}x}x}}|d   }g }
|j                  }d} ||      }|}|sd}|}||k(  }|s3ddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }|
j                  |       |s+ddt        j                  |      iz  }|
j                  |       t        j                  |
d	      i z  }t        j                  d
|fd||f      t        j                  |      |dz  }dd|iz  }t        t        j                  |            dx}x}x}x}
x}x}x}}|d   }g }
|j                  }d} ||      }|}|sd}|}||k(  }|s3ddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }|
j                  |       |s+ddt        j                  |      iz  }|
j                  |       t        j                  |
d	      i z  }t        j                  d
|fd||f      t        j                  |      |dz  }dd|iz  }t        t        j                  |            dx}x}x}x}
x}x}x}}y)uJ   pr_identity 4튜플(pr,head_sha,task_id,branch)이 결정적으로 보존.r%   prr   zA%(py12)s
{%(py12)s = %(py8)s
{%(py8)s = %(py6)s.get
}(%(py10)s)
}pi)r>   py8r   r   z%(py15)spy15r   r/   )z3%(py1)s == %(py20)s
{%(py20)s = %(py3)s(%(py18)s)
}int)r<   r7   py18py20zassert %(py22)spy22Nhead_sha z@%(py11)s
{%(py11)s = %(py7)s
{%(py7)s = %(py5)s.get
}(%(py9)s)
})r8   r9   py9py11r   r   )z%(py1)s == (%(py17)s))r<   r   zassert %(py19)spy19task_idbranchts_kst)r!   r(   getr   rB   rC   r@   rD   rE   r   r   rA   rG   rH   )r   ri   r   ra   r   rj   rP   @py_assert7r   r   rJ   @py_assert14@py_assert19rN   r   r   @py_format17@py_format21@py_format23@py_assert6@py_assert8@py_assert10rO   @py_assert13@py_format12r   r   @py_format20s                               r    &test_invariant_pr_identity_passthroughr      s    $KEB
*C	M	Bt9.BFF.4.F4L.L.LA.A....9........B...B...F...4...L....L...A.........9....9.....................z?8rvv8j8vj18181R8R8?88888888r888r888v888j888188881888R888888888?888?88888888y>6bff6Y6fY/6/6/2626>66666666b666b666f666Y666/6666/6662666666666>666>66666666x=4RVV4H4VH-4-4-44=44444444R444R444V444H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x=4RVV4H4VH-4-4-44=44444444R444R444V444H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                    t        |       \  }}t        |      }t        |      }t        j                  |dd      }t        j                  |dd      }||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	z   d
|iz  }	t        t	        j                  |	            d }||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  }dd
|iz  }	t        t	        j                  |	            d }y )NFr   	sort_keysr/   r`   s1s2rc   z: non-deterministic output
>assert %(py4)sr=   a1a2rd   )r!   r(   r   r   r@   rA   rB   rC   rD   rE   rF   rG   rH   )
r   ri   r   r   r   r   r   rK   rl   rk   s
             r    test_idempotent_byte_identicalr      s
   $KEB	B	B	BUe	<B	BUe	<B88882888888288828888888888888v788888888OOO2OOOOOO2OOO2OOOOOOOOOOOOOOOOr"   c                  6   t         j                  D ]  } t        j                  }| |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                  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        j                  |    }|j                  }d	} ||      }|st	        j                  |  d
|      dz   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 )Nrw   )zB%(py0)s in %(py4)s
{%(py4)s = %(py2)s.AUTO_REMEDIABLE_ACTION_MAP
}rt   r&   r   zmissing action map: z
>assert %(py6)sr>   r   z	: action=r   ru   r   )rX   AUTO_REMEDIABLE_ORDERr&   AUTO_REMEDIABLE_ACTION_MAPr@   rA   rB   rC   rD   rE   rF   rG   rH   r   )rt   rO   rK   rk   rQ   ru   rP   s          r    /test_auto_remediable_action_map_covers_all_enumr      s@   '' I33Rt33RRRt3RRRRRRtRRRtRRRRRRqRRRqRRR3RRR7KD65RRRRRRR--d3  HH *H*HHtfIfZ,HHHHHHHvHHHvHHH HHHHHH*HHHHHHIr"   c                     dg g d} t        j                  | ddddd      }|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   }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}||u }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u   미인지 verdict (e.g. None, 'INVALID_VERDICT_STRING') → UNKNOWN/REGATHER 와 동일 처리.
    추정 금지 + 안전 불변식 유지.WAT)rW   r   blocking_reasonsr   xtbr   r   r   r   rT   r/   r   r&   rU   rV   r9   NrW   r   rX   rY   r   r   r   r   Fr[   r]   r^   r_   r>   )r&   r'   r   r@   rA   rE   rB   rC   rD   rG   rH   rX   r   r   r   )
fake_resultra   rj   rJ   rN   rL   rM   rO   rk   rQ   s
             r    0test_unrecognized_verdict_falls_back_to_regatherr      sU    $rrRK
..QCC[^&_
`Cx=3A333=33333=3333=333333A333A33333333333y>&QYY&>Y&&&&>Y&&&>&&&&&&Q&&&Q&&&Y&&&&&&& !<Q%<%<<!%<<<<<!%<<<<!<<<<<<Q<<<Q<<<%<<<<<<<<x=:A:::=:::::=::::=::::::A:::A:::::::::::"#,u,#u,,,,#u,,,#,,,u,,,,,,,r"   c                  T   t         j                  i d} 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}}|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}||u }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }dd	|iz  }t        t	        j                  |            dx}x}}y)uJ   pr_identity=None None-guard (classifier 입력 견고성 doctrine 동형).)rW   auto_merge_10_conditionsNr   r   r/   r   r^   r_   r>   r   r   r   Fr[   r]   )	rX   rf   r&   r'   r@   rA   rE   rG   rH   )r   ra   rj   rO   rN   rk   rQ   s          r    $test_none_pr_identity_does_not_crashr     s   ff"EK
..d
+Ct99>99z? b ?b    ?b   ?   b       "#,u,#u,,,,#u,,,#,,,u,,,,,,,r"   c                     t        j                  d ddddd      } | 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}}y )N   hr   r   r   rT   r/   r   r&   rU   rV   r9   rY   r   )r&   r'   r   r@   rA   rE   rB   rC   rD   rG   rH   r   )ra   rj   rJ   rN   rL   rM   s         r    2test_none_classifier_result_falls_back_to_regatherr     s   
..aSSTWX
YCx=3A333=33333=3333=333333A333A33333333333 !<Q%<%<<!%<<<<<!%<<<<!<<<<<<Q<<<Q<<<%<<<<<<<<r"   c            	         t        j                  t        t              j	                         j
                  d   dz  dz  dz  dz  j                  d            } | j                  d      xs i j                  d	      xs g }t        | t        j                  |
      }t        j                  |dd      }t        j                  |dddddd      }t        j                  |dd      }||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z   d|iz  }t+        t        j,                  |            d}y)uU   executor 는 classifier output 을 read-only 로 소비해야 한다 (변형 금지).r   r	   merge_readypass_all_greenr   r   r   scopeexpected_files)anu_keysr  FTr   ar   r   z2026-05-22T00:00:00+09:00)r   r   r   r   r   r/   r`   snapshotafterrc   z*executor must not mutate classifier_resultr   r=   N)r   r   r   __file__resolveparentsr   r   r   rX   DEFAULT_ANU_KEYSr   r&   r'   r@   rA   rB   rC   rD   rE   rF   rG   rH   )	ri   declaredresultr  r   r  rK   rl   rk   s	            r    *test_classifier_output_consumed_unmodifiedr    sD   	T(^++-55a8:EU'(*9:;D9g9;V
XBw%2**+;<BH!"q/A/ARZ[Fzz&uEH	vaSSTW+F H 	IAJJvETBEuJJJ8uJJJJJJ8JJJ8JJJJJJuJJJuJJJJJJJJJJJr"   c                  X    t        t        j                        } | j                  d      S )Nr   r   )r   r&   r  r   )paths    r    _module_sourcer    s!    

D>>7>++r"   c                     t        j                  dd|       }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }|S )	u   docstring/주석을 제거한 코드만 반환 — 정적 검증의 거짓 양성(narrative 문구 일치) 방지.
    완벽한 파서는 아니지만 forbidden 코드 패턴 탐지 목적에 충분히 안전한 휴리스틱.z"""[\s\S]*?"""z""z'''[\s\S]*?'''z''z"(?:\\.|[^"\\])*"z'(?:\\.|[^'\\])*'z#[^\n]*r   )resub)srccodes     r    _strip_strings_and_commentsr    sg     66#T3/D66#T40D66&d3D66&d3D66*b$'DKr"   c            	         t        t                     } g d}g d}||z   D ]X  }t        j                  } |||       }| }|s0t	        j
                  d|       dz   dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      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                  |      dz  }t        t	        j                  |            d	x}x}}[ y	)
u  안전 불변식 정적 검증: merge/push/PR/cron/subprocess/network/file write 코드 경로 부재.

    검사 대상 패턴(반드시 부재 — narrative 문구 제외한 실 코드 토큰):
    - subprocess / os.system / shlex.run
    - urllib / requests / httpx / socket
    - open(..., 'w'/'a') / Path.write_text / write_bytes
    - branch protection bypass / admin override execute
    )z\bimport\s+subprocess\bz\bfrom\s+subprocess\bz\bimport\s+urllib\bz\bfrom\s+urllib\bz\bimport\s+requests\bz\bfrom\s+requests\bz\bimport\s+httpx\bz\bfrom\s+httpx\bz\bimport\s+socket\bz\bfrom\s+socket\bz\bimport\s+os\bz\bfrom\s+os\bz\bimport\s+shutil\bz\bfrom\s+shutil\b)z\bsubprocess\.z\bos\.system\s*\(z\bos\.popen\s*\(z
\bshutil\.z
\burllib\.z\brequests\.z	\bhttpx\.z
\bsocket\.z\.write_text\s*\(z\.write_bytes\s*\(z\bopen\s*\(zforbidden code pattern: zW
>assert not %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.search
}(%(py3)s, %(py4)s)
}r  patr  )r5   r6   r7   r=   r>   N)r  r  r  searchr@   rF   rB   rC   rD   rE   rG   rH   )r  forbidden_importsforbidden_callsr!  rK   rP   r   rM   s           r    4test_module_has_no_subprocess_or_network_or_write_ior%  (  s     '~'78D	O !?2 J99I9S$'I''I'II+CC5)IIIIIII2III2III9IIIIIISIIISIIIIII$III$III'IIIIIIJr"   c                  $   t               } | j                         D cg c]#  }|j                         j                  d      r|% }}|D ]  }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
c c}w )u   utils.merge_ready_dryrun_executor 의 import 는 utils.merge_ready_states 만 허용.
    anu_v3/런타임/외부 의존 0 (decoupled doctrine).)zimport zfrom zutils.merge_ready_statesrw   )z%(py1)s in %(py3)slnr   zforbidden import: 
>assert %(py5)sr8   N)r  
splitlinesstripr   r@   rA   rE   rB   rC   rD   rF   rG   rH   )r  r'  import_linesrj   rN   r   rL   s          r    test_module_imports_only_statesr,  H  s     
C^^%88:  !56 	L   M)L)R/LLL)RLLL)LLLLLLRLLLRLLLL3EbV1LLLLLLLM	s   (Dc                     t        t                     } 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	)u   executor 는 classifier 함수/모듈을 호출/import 하지 않는다 (입력 소비만 — Anchor 4).
    docstring/주석의 narrative 언급은 허용 (코드 의존성 부재만 검사).r   r   r   r  r   u   classifier 함수 호출 발견r(  r8   Nmerge_ready_classifieru&   classifier 모듈 import/호출 발견)r  r  r@   rA   rE   rB   rC   rD   rF   rG   rH   )r  rj   rN   r   rL   s        r    1test_module_does_not_call_classifier_or_modify_itr/  T  s     '~'78D!P!-PPP!PPP!PPPPPPPPPPPPP/PPPPPPP#Y#4/YYY#4YYY#YYYYYY4YYY4YYYY1YYYYYYYr"   c                 ,   t        |       \  }}t        |      }t        j                  |d      }t        j                  |      }||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  }dd	|iz  }t        t        j                  |            d }y )
NFr   r/   r`   art2ra   rc   rd   r=   )r!   r(   r   r   r   r@   rA   rB   rC   rD   rE   rG   rH   )	r   ri   r   ra   sr1  rK   rl   rk   s	            r    "test_artifact_is_json_serializabler3  `  s    $KEB
*C

3U+A::a=D3;434433r"   c                  .   t               } t               }t               }t        D ]W  }t        |      \  }}t        |      }| j	                  |d          |j	                  |d          |j	                  |d          Y 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  }	dd	|	iz  }
t!        t        j"                  |
            d
x}}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  }	dd	|	iz  }
t!        t        j"                  |
            d
x}}t$        j.                  t$        j0                  t$        j2                  h}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	dd	|	iz  }
t!        t        j"                  |
            d
x}}y
)uV   ANCHOR-2: verdict 4값(PASS/HOLD/CHAIR_REQUIRED/UNKNOWN) routing 매핑 전부 커버.rW   rY   rT   r/   )z%(py0)s == %(py3)sverdicts_seen)r5   r7   r   r8   Nactions_seenschemas_seen)setr3   r!   r(   addrX   rf   r{   r   r   r@   rA   rB   rC   rD   rE   rG   rH   r&   rg   r|   r   r   re   rz   r   )r5  r6  r7  r   ri   r   ra   rN   rK   r   rL   s              r    &test_anchor2_all_four_verdicts_coveredr:  n  sV   EM5L5L (dARj#i.)./0X'( VVQVVQ-=-=qyyII=IIIII=IIIIIII=III=IIIIIIIIIII		%%	%%		 <   
 <   
  
    
    
     
   	
%%	%%	 <    	<    	  	    	    	     	 r"   )9__doc__builtinsrB   _pytest.assertion.rewrite	assertionrewriter@   r   r  syspathlibr   pytestr  r  r  _WORKTREE_ROOTr   r  insertutilsr   r&   r   rX   utils.merge_ready_classifierr   r   r3   r!   r(   rR   rm   r~   r   r   r   r   markparametrizer   r   r   r   r   r   r   r  r  r  r  r  r%  r,  r/  r3  r:   r"   r    <module>rJ     s  &   	 
   h'')11!4~chh&HHOOAs>*+ 2 ) =H~%%'//2Z?BVVR@	
	  .6 /6 ., /, . / .	5 /	5  . /I	--=
K",
J@	MZ . /r"   