
     jp                    H   U d Z ddlm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ZddlmZ ddlmZ ddlmZmZmZ  ee      j/                         j0                  j0                  j0                  Z ee      ej6                  v r!ej6                  j9                   ee             ej6                  j;                  d ee             ddlmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z* ddl+m,Z,m-Z-m.Z. dd	l/m0Z0m1Z1m2Z2 dDdEd
Z3dFdZ4ddddddddde"ddZ5de6d<   ddddddddd Z7de6d!<   d"ddddd#d$dd Z8de6d%<   d&ddddd'd(dd Z9de6d)<   d*ddddd+d,dd Z:de6d-<   d.ddddd/d0dd Z;de6d1<   d2Z<d3Z=d4Z>d5 Z?d6 Z@d7 ZAd8 ZBd9 ZCd: ZDd; ZEd< ZFd= ZGd> ZHd? ZId@ ZJdA ZKdB ZLdC ZMy)Gu  tests/regression/test_bot_merge_identity_regression_2523.py

회귀 테스트 — task-2523 bot merge identity regression / autonomy proof harness.

회장 §본질:
  task-2522 BOT_MERGE_IDENTITY_SUCCESS path를 **회귀로 고정**한다.
  PR #73 (mergeCommit b7a37521..., mergedBy=app/jeon-jonghyuk-taskctl-bot,
  token_source=GITHUB_APP_INSTALLATION_TOKEN) 가 1회성 우연이 아니라 향후 PR에서도
  반복 가능한 표준 path 임을 박제한다.

회장 §명시 8 검증 (정확히 8개):
  1. GH_TOKEN process-local injection이 owner PAT보다 우선
  2. gh auth=owner여도 merge token_source=GITHUB_APP_INSTALLATION_TOKEN 기록
  3. mergedBy=app/jeon-jonghyuk-taskctl-bot → BOT_MERGE_IDENTITY_SUCCESS 분류
  4. mergedBy=JonghyukJeon → owner_pat fallback 분류
  5. token raw value 로그 0건
  6. branch cleanup도 bot token으로 가능
  7. smoke + reconcile 정상
  8. audit JSONL에 token_source / mergedBy / owner_pat_used / expected_bot_identity 4 필드 존재

replay fixture:
  - PR #73 BOT_MERGE_IDENTITY_SUCCESS (mergedBy=app/jeon-jonghyuk-taskctl-bot,
    mergeCommit=b7a37521c8f189bfd98b8ea047ebaa5c5fe684aa, mergedAt=2026-05-09T09:01:27Z)
  - PR #68/#69/#70/#71/#72 owner_pat fallback 5건 (autonomy capability gap 박제)

회장 §보안:
  - raw token value 절대 출력/저장 X (정적 grep 검증 포함)
  - gh api 실호출 X — 모두 runner mock / dataclass 직접 주입
  - subprocess 실행 X — 모든 경로는 fixture replay
    )annotationsN)fields)Path)AnyDictList)DEFAULT_AUDIT_JSONL_PATHMergeIdentityAuditRecordREQUIRED_AUDIT_FIELDS_2523TOKEN_SOURCE_GITHUB_APPTOKEN_SOURCE_OWNER_PATTOKEN_SOURCE_UNKNOWNappend_audit_jsonlbuild_audit_recordclassify_token_sourcecompute_autonomy_score_deltaexpected_bot_identity_for_actor'verify_branch_cleanup_token_inheritance)OWNER_PAT_FALLBACK_BLOCKEDexecute_squash_mergeselect_merge_token_decision)BlockedReasonclassify_capability_gapprobe_bot_merge_identityc                4    t        j                  g | ||      S )N)args
returncodestdoutstderr)
subprocessCompletedProcess)r   r   r   s      O/home/jay/workspace/tests/regression/test_bot_merge_identity_regression_2523.pycpr#   O   s    &&B:f]cdd    c                     dd fd}|S )u@   gh pr view <N> --json ... 호출에 응답하는 runner factory.c                (   ~~t        |       dk  s
| dd g dk7  rt        ddd      S 	 t        | d         }j	                  |      }|t        ddd	      S t        dt        j                  |      d      S # t        $ r t        ddd      cY S w xY w)
N   r      )ghprview    zunexpected callzbad pr numberz	Not Found)lenr#   int
ValueErrorgetjsondumps)r   cwdkwargsnpayloadpr_payloadss        r"   runnerz#make_pr_view_runner.<locals>.runnerV   s    t9q=D1I)==a.//	.DGA //!$?a[))!TZZ("--  	.a_--	.s   A8 8BB)N)r   	List[str]r4   r   returnsubprocess.CompletedProcess )r8   r9   s   ` r"   make_pr_view_runnerr>   S   s    . Mr$   I   app/jeon-jonghyuk-taskctl-botBotT)logintypeis_botztask/task-2522-dev2	task-25222026-05-09T09:01:27Z(b7a37521c8f189bfd98b8ea047ebaa5c5fe684aa)task_idmergedAtmergeCommitexpected_token_source)numbermergedByheadRefName_metazDict[str, Any]PR_73_FIXTURED   JonghyukJeonUserFz	task-2517z2026-05-09T00:53:24Z)rH   rI   )rL   rM   rO   PR_68_FIXTUREE   z	task-2519z2026-05-09T02:04:50ZPR_69_FIXTUREF   z	task-2518z2026-05-09T04:50:46ZPR_70_FIXTUREG   z	task-2520z2026-05-09T06:31:34ZPR_71_FIXTUREH   	task-2521z2026-05-09T13:30:00ZPR_72_FIXTUREghs_botFIXTUREsuffixghp_ownerFIXTUREsuffix)botFIXTUREsuffixownerFIXTUREsuffixc                    t         t        d} t        t        |       }|j                  }|t        k(  }|s	t        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  d|j                         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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j                  }t        dd }||k(  }|st        j                  d|fd||f      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}}t!        j"                  |j%                               }	t&        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z   d|iz  }t        t        j                  |            d} y)u7  (1) env에 owner PAT + GH_TOKEN=$BOT_GITHUB_TOKEN 동시 존재 →
    classify가 GH_TOKEN(ghs_) 값을 우선 분류 = GITHUB_APP_INSTALLATION_TOKEN.

    회장 §본질: process-local GH_TOKEN injection 패턴 (task-2522에서 PR #73 머지 시
    실제로 사용된 패턴) 이 owner PAT 보다 우선 적용되는지 회귀 박제.
    classify_token_source(token_value=...) 에 inject 된 token 값을 직접 전달하면
    그 prefix가 ghs_ 인 경우 GitHub App 으로 분류된다 — env에 owner PAT가
    동시에 존재해도 영향 없음.
    )
GITHUB_PATGH_TOKENtoken_valueenv==z4%(py2)s
{%(py2)s = %(py0)s.token_source
} == %(py4)sprober   py0py2py4u9   GH_TOKEN process-local injection이 우선되지 않음: 
>assert %(py6)spy6NTis)z;%(py2)s
{%(py2)s = %(py0)s.installation_signal
} is %(py5)srm   rn   py5assert %(py7)spy7   )z=%(py2)s
{%(py2)s = %(py0)s.token_prefix_observed
} == %(py5)snot inz%(py0)s not in %(py2)sneedle
serialisedrm   rn   zraw token leaked: 
>assert %(py4)sro   )_FIXTURE_OWNER_PAT_PREFIX _FIXTURE_BOT_INSTALLATION_PREFIXr   token_sourcer   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationinstallation_signaltoken_prefix_observedr2   r3   to_dict_RAW_LEAK_NEEDLES)env_with_bothrk   @py_assert1@py_assert3@py_format5@py_format7@py_assert4@py_format6@py_format8r}   r|   @py_format3s               r"   <test_v1_gh_token_process_local_injection_overrides_owner_patr      s    04M "4E  !88   !8                    "9    "9    DEDVDVCWX     $$,,$,,,,$,,,,,,5,,,5,,,$,,,,,,,,,,&&N*J2A*NN&*NNNNN&*NNNNNNN5NNN5NNN&NNN*NNNNNNNNEMMO,J# IZ'HHHvZHHHHHHvHHHvHHHHHHZHHHZHHHH+=fZ)HHHHHHHIr$   c                 t   t        t        dt        i      } | j                  }|t        k(  }|st	        j
                  d|fd|t        f      dt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              nddz  }dd	|iz  }t        t	        j                  |            d
x}}t        d| dddd      }|j                  }|t        k(  }|st	        j
                  d|fd|t        f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              nddz  }d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                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d
x}x}}|j                  }d}||u }|st	        j
                  d|fd||f      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}}y
)u  (2) gh auth status는 JonghyukJeon (owner_pat) 이지만, merge 실행 직전
    GH_TOKEN 으로 installation token이 주입된 상황 → audit record가
    token_source=GITHUB_APP_INSTALLATION_TOKEN 으로 기록되어야 한다.

    회장 §본질: gh CLI의 stored auth는 owner PAT 일 수 있지만, 자동화의 진짜
    실행 토큰은 process-local GH_TOKEN injection이다. audit는 후자를 기록한다.
    rd   re   rh   rj   rk   r   rl   assert %(py6)srq   Nr?   r@   rA   rG   rE   	pr_numbertoken_probemergedBy_loginmergedBy_typemerge_commit_sharH   z9%(py2)s
{%(py2)s = %(py0)s.token_source_used
} == %(py4)srecordFrr   z6%(py2)s
{%(py2)s = %(py0)s.owner_pat_used
} is %(py5)srt   rv   rw   z?%(py2)s
{%(py2)s = %(py0)s.autonomy_capability_gap
} is %(py5)s)r   r   r   r   r   r   r   r   r   r   r   r   r   token_source_usedowner_pat_usedautonomy_capability_gap)	rk   r   r   r   r   r   r   r   r   s	            r"   >test_v2_gh_auth_owner_but_merge_records_app_installation_tokenr      s*    "48
E 8!88888!888888858885888888888!8888!888888886CF ##>#'>>>>>#'>>>>>>>6>>>6>>>#>>>>>>'>>>>'>>>>>>>>  )E) E)))) E))))))6)))6))) )))E)))))))))2U2)U2222)U22222262226222)222U2222222r$   c            	     N   t         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}}t         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}}t         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}}t        t        dt        i      }t        t         d   |t         d   d   t         d   d   t         d   d   t         d   d         }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }d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                  |      t        j                  |      dz  }	dd|	iz  }
t	        t        j
                  |
            d	x}x}}|j                  }d}||u }|st        j                  d|fd||f      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}}|j                   }d }||u }|st        j                  d|fd!||f      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}}|j"                  }d }||u }|st        j                  d|fd"||f      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}}t%        d#|$      }|j&                  }d%}||k(  }|st        j                  d|fd&||f      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}}|j(                  }d(}||k(  }|st        j                  d|fd)||f      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}}y	)*u:  (3) PR #73 fixture replay (mergedBy=app/jeon-jonghyuk-taskctl-bot,
    mergeCommit=b7a37521..., is_bot=true) → autonomy_capability_gap=False,
    expected_bot_identity=True, owner_pat_used=False = BOT_MERGE_IDENTITY_SUCCESS.

    회장 §본질: 본 task의 회귀 핵심 — task-2522 success path 박제.
    rM   rB   r@   rh   z%(py1)s == %(py4)spy1ro   r   rq   NrD   Trr   z%(py1)s is %(py4)srO   rJ   rG   rd   re   rL   rC   rH   r   r   r   r   rl   z7%(py2)s
{%(py2)s = %(py0)s.mergedBy_is_bot
} is %(py5)srt   rv   rw   z=%(py2)s
{%(py2)s = %(py0)s.expected_bot_identity
} is %(py5)sFr   r      previous_scorer   r,   )z-%(py2)s
{%(py2)s = %(py0)s.delta
} == %(py5)sdelta	   )z1%(py2)s
{%(py2)s = %(py0)s.new_score
} == %(py5)s)rP   r   r   r   r   r   r   r   r   r   r   r   r   r   mergedBy_is_botexpected_bot_identityr   r   r   r   	new_score)@py_assert0r   @py_assert2r   r   rk   r   r   r   r   r   r   s               r"   Gtest_v3_pr_73_mergedBy_app_bot_classified_as_bot_merge_identity_successr      s    $W-P1PP-1PPPPP-1PPPP-PPP1PPPPPPPP$X.6$6.$6666.$666.666$6666666!-0 202  02   1    	3      "49:E  )$Z09#J/7&w/>g&y1F ##>#'>>>>>#'>>>>>>>6>>>6>>>#>>>>>>'>>>>'>>>>>>>>!!)T)!T))))!T))))))6)))6)))!)))T)))))))''/4/'4////'4//////6///6///'///4///////))2U2)U2222)U22222262226222)222U2222222  )E) E)))) E))))))6)))6))) )))E)))))))(&IE;;!;!;!55;!??a?a?a55?ar$   c            	     d   dt         fdt        fdt        fdt        fdt        fg} | D ]  \  }}t        t        dt        i      }t        |||d   d	   |d   d
   |d   d         }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        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                  |      t        j                  |	      dz  }
t        j                   d|       dz   d|
iz  }t#        t        j$                  |            dx}x}}	|j(                  }d}	||	u }|st        j                  d|fd||	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |	      dz  }
t        j                   d|       dz   d|
iz  }t#        t        j$                  |            dx}x}}	|j*                  }d}	||	u }|st        j                  d|fd||	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |	      dz  }
t        j                   d|       dz   d|
iz  }t#        t        j$                  |            dx}x}}	|j,                  }d}	||	u }|st        j                  d|fd ||	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |	      dz  }
t        j                   d|       dz   d|
iz  }t#        t        j$                  |            dx}x}}	 t/        t         t        t        t        t        d!      }t1        d"d#g d!|$      }|j2                  }d}	||	u }|st        j                  d|fd%||	f      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}}	|j4                  }d}	||	u }|st        j                  d|fd(||	f      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}}	t7        |      }t8        j:                  }||k(  }	|	s?t        j                  d|	fd)||f      d*t        j                         v st        j                  t6              rt        j                  t6              nd*d&t        j                         v st        j                  |      rt        j                  |      nd&t        j                  |      d+t        j                         v st        j                  t8              rt        j                  t8              nd+t        j                  |      d,z  }d-d.|iz  }t#        t        j$                  |            dx}x}	}y)/u%  (4) PR #68~#72 5건 fixture replay (mergedBy=JonghyukJeon) → 모두
    owner_pat fallback (autonomy_capability_gap=True, owner_pat_used=True).

    회장 §본질: task-2522 직전 5 연속 owner_pat 패턴이 회귀로 고정되어
    "성공 path"로 위장되지 않음을 박제.
    rQ   rU   rW   rY   r[   rc   re   rM   rB   rC   rO   rH   r   r   r   r   rH   rh   r   r   r   rl   zPR #rp   rq   NTrr   r   rt   z
>assert %(py7)srw   r   Fr   r   )rQ   rU   rW   rY   r[   zJeon-Jonghyukdev_workspace)r9   )zH%(py2)s
{%(py2)s = %(py0)s.fallback_to_owner_token_detected
} is %(py5)sidentityrv   )z<%(py2)s
{%(py2)s = %(py0)s.bot_can_merge_as_app
} is %(py5)s)z_%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py7)s
{%(py7)s = %(py5)s.AUTOMATION_CAPABILITY_GAP
}r   r   )rm   r   py3ru   rw   zassert %(py9)spy9)rT   rV   rX   rZ   r]   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r>   r    fallback_to_owner_token_detectedbot_can_merge_as_appr   r   AUTOMATION_CAPABILITY_GAP)fixturespr_numfixrk   r   r   r   r   r   r   r   r   r9   r   r   @py_assert6@py_format10s                    r"   Ctest_v4_pr_68_to_72_mergedBy_owner_classified_as_owner_pat_fallbackr     s    
]	]	]	]	]H   F%189
 $z?73j/&1L+
 ''R'+AARRR'+ARRRRRRvRRRvRRR'RRRRRR+ARRR+ARRRRT&?RRRRRR$$==$,===$======v===v===$======VHo=======--FF-5FFF-FFFFFFvFFFvFFF-FFFFFFfXFFFFFFF%%??%.???%??????v???v???%??????$vh???????++EuE+u4EEE+uEEEEEEvEEEvEEE+EEEuEEEVHoEEEEEEE!F& !}-}" F (*>vH 44<<4<<<<4<<<<<<8<<<8<<<4<<<<<<<<<<((1E1(E1111(E11111181118111(111E1111111"8,W0W0WW,0WWWWW,0WWWWWWW"WWW"WWWWWW8WWW8WWW,WWWWWWWWWWWW0WWWWWWWWr$   c                    d} d}| |fD ]r  }t        |d|i      }t        d|ddd	      }t        j                  |j	                         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}}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}}|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  }dd|iz  }	t        t        j                  |	            dx}}t        dz  dz  dz  }
|
j                         r|
j!                          t#        ||
       |
j%                  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  }d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  }dd|iz  }	t        t        j                  |	            dx}}t'        d!|"      }t        j                  |j(                        }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}}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}}|
j!                  d$%       u t        d&z  d'z  j%                  d      }t*        j,                  }d(} |||      }| }|s t        j                  d)      d*z   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                  |      rt        j                  |      nd,t        j                  |      d-z  }t        t        j                  |            dx}x}x}}t*        j,                  }d.} |||      }| }|s t        j                  d/      d*z   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                  |      rt        j                  |      nd,t        j                  |      d-z  }t        t        j                  |            dx}x}x}}y)0u   (5) audit record + JSONL 라인 + delta 출력 전부에서 raw token suffix
    노출 0건. 정적 grep + JSON 직렬화 검사.

    회장 §보안: token raw value 출력 절대 금지. prefix 5자 + sha256 첫 8 hex만.
    0ghs_PUBLICprefixULTRASECRETappBotSuffixDoNotLeak2ghp_PUBLICprefixULTRASECRETownerPatSuffixDoNotLeakrd   re     r@   rA   (deadbeefdeadbeefdeadbeefdeadbeefdeadbeef)r   r   r   r   r   F)ensure_asciiULTRASECRETry   z%(py1)s not in %(py3)sr}   r   r   zraw token leaked into record: z
>assert %(py5)sru   N	DoNotLeakassert %(py5)srx   inz%(py1)s in %(py3)smemoryeventsztest_2523_v5_tmp.jsonl
audit_pathutf-8encodingliner   r   
delta_jsonT
missing_okutilszbot_merge_identity.pyzghs_[A-Za-z0-9]{30,}z!long ghs_ token literal in sourcezW
>assert not %(py7)s
{%(py7)s = %(py2)s
{%(py2)s = %(py0)s.search
}(%(py4)s, %(py5)s)
}resrc)rm   rn   ro   ru   rw   zghp_[A-Za-z0-9]{30,}z!long ghp_ token literal in source)r   r   r2   r3   r   r   r   r   r   r   r   r   r   r   _WORKTREE_ROOTexistsunlinkr   	read_textr   __dict__r   search)secret_token_appsecret_token_pattokrk   r   r}   r   r   @py_format4r   tmpr   r   r   r   r   r   r   @py_assert8@py_format9s                       r"   5test_v5_no_raw_token_value_in_any_audit_or_log_outputr   A  s    OP "23 $%#J;LM#:+
 ZZ 0uE
_}J.___}J___}______J___J____2PQ[P^0_______,{*,,,,{*,,,{,,,,,,*,,,*,,,,,,,2Aw$w*$$$$w*$$$w$$$$$$*$$$*$$$$$$$ x'(25MM::<JJL6c2}}g}.(}D((((}D(((}((((((D(((D(((((((&{$&&&&{$&&&{&&&&&&$&&&$&&&&&&&,AfMZZ/
.}J....}J...}......J...J.......,{*,,,,{*,,,{,,,,,,*,,,*,,,,,,,

d
#;$@ G#&==
H
HRY
H
ZCyy[0[y0#6[66[6[[8[[[[[[[r[[[r[[[y[[[0[[[[[[#[[[#[[[6[[[[[[yy[0[y0#6[66[6[[8[[[[[[[r[[[r[[[y[[[0[[[[[[#[[[#[[[6[[[[[[r$   c                    g d%fd} t        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}}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      dz   d|iz  }	t	        t        j
                  |	            d
x}x}}d   }
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   }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}||u }|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}}|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}||
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}}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}}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}}g d$}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}}y
)&u  (6) `gh pr merge --squash --delete-branch` 한 번의 호출 안에서 머지+삭제가
    수행되므로, GH_TOKEN process-local injection이 branch cleanup에도 그대로
    상속된다. PR #73 branch `task/task-2522-dev2` delete가 이 패턴으로 가능했음을
    정적으로 검증.

    회장 §본질: branch cleanup이 별도 호출 / 별도 token으로 분리되면 fallback
    위험이 생긴다. 동일 호출 안에 묶여 있어야 한다.
    c                T    ~j                  t        |              t        ddd      S )Nr   zMerged.r-   appendlistr#   )r   r5   captureds     r"   r9   zLtest_v6_branch_cleanup_inherits_bot_token_in_same_merge_call.<locals>.runner  s%    T
#!Y##r$   r?   r   r   rh   r   r   r   rq   Nr,   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr.   r   rm   r   r   rq   u0   merge+cleanup은 정확히 1 호출이어야 함z
>assert %(py8)spy8merge_command_presentTrr   r   delete_branch_flag_presentbranch_cleanup_in_same_callforbidden_flags_detected%token_inherits_process_local_gh_token--adminry   r   issuedr   r   ru   --forcerebase)r)   r*   merge73--squash--delete-branchr   r:   r;   r<   )r   r   r   r   r   r   r.   r   r   r   r   r   )r9   resultr   r   r   r   r   @py_assert5r   r   r  cleanupr   r   	pr73_args
cleanup_73r   s                   @r"   <test_v6_branch_cleanup_inherits_bot_token_in_same_merge_callr  u  s-    !#H$
 ""f-F,$1$1$$$$1$$$$$$1$$$$$$$x=QAQ=AQQQ=AQQQQQQ3QQQ3QQQQQQxQQQxQQQ=QQQAQQQQQQQQQQQa[F 6f=G*+3t3+t3333+t333+333t3333333/08D80D88880D8880888D8888888019T91T99991T9991999T9999999-.4"4."4444."444.444"4444444:;CtC;tCCCC;tCCC;CCCtCCCCCCC "9F""""9F"""9""""""F"""F""""""""9F""""9F"""9""""""F"""F"""""""!86!!!!86!!!8!!!!!!6!!!6!!!!!!! KI8CJ=>F$F>$FFFF>$FFF>FFF$FFFFFFFr$   c                    ddl m}  g d5fd} | g 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}}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dlm}m}m} d}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}}	d}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}}	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                  |      dz  }t        t        j                  |            d}t#        t$        dt$        i       }t'        d!|d"d#d$d%&      }|j(                  }d'}	||	u }|st        j                  d(|fd)||	f      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}}	g }|d   }d}||k(  }	|	}|	r|j(                  }| }|}|st        j                  d|	fd.||f      t        j                  |      t        j                  |      d/z  }d0d|iz  }
|j+                  |
       |	rld1d*t        j                         v st        j                  |      rt        j                  |      nd*t        j                        d2z  }|j+                  |       t        j,                  |d      i z  }d3d4|iz  }t        t        j                  |            dx}x}x}x}	x}x}}y)6u  (7) PR #73 (mergedBy=bot) 머지 후 post-merge smoke 와 lifecycle reconcile
    이 정상 수행됨을 fixture replay 로 박제.

    회장 §본질: bot 머지 후에도 standard automation flow (smoke + reconcile)이
    동일하게 작동해야 함 — bot 머지가 후행 단계를 깨뜨리지 않는다.

    실호출 X — runner mock으로 smoke=PASS, reconcile=APPLIED 시뮬레이션.
    r   )run_post_merge_smokec                T    ~j                  t        |              t        ddd      S )Nr   zsmoke okr-   r   )r   r5   smoke_callss     r"   smoke_runnerzZtest_v7_post_merge_smoke_and_reconcile_pass_after_bot_identity_merge.<locals>.smoke_runner  s'    4:&!Z$$r$   )python3z-czprint('smoke ok')statusPASSrh   r   r   r   rq   Nr,   r   r.   r  r   assert %(py8)sr   )LifecycleStateStuckReason	reconcile__members__z5assert %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrr  )rm   r   r   ru   r  z,assert %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}callabler  )rm   r   r   rd   re   r?   r@   rA   rG   rE   r   Frr   r   r   rt   rv   rw   )z%(py3)s == %(py6)s)r   rq   z%(py8)sz;not %(py12)s
{%(py12)s = %(py10)s.autonomy_capability_gap
})py10py12zassert %(py16)spy16r  )utils.merge_queue_executorr  r   r   r   r   r   r.   r   r   r   &utils.lifecycle_reconciliation_managerr  r  r  r  r   r   r   r   r   r   _format_boolop)r  r  smoke_resultr   r   r   r   r   r  r   r   r  r  r  r   r   rk   r   r   r   @py_assert11@py_assert13@py_format14@py_format15@py_format17r  s                            @r"   Dtest_v7_post_merge_smoke_and_reconcile_pass_after_bot_identity_merger-    s    @ $&K%
 (.L !+V+!V++++!V+++!+++V+++++++{ q q    q      3   3      {   {      q         $117>=1111111171117111111>111>111=1111111111 -.7;........7...7......;...;.............I88II "49:E  6CF ))2U2)U2222)U22222262226222)222U2222222R<!RVR!V+RF4R4RR4R0RR0RRRR!VRRR!RRRVRRRRRRRRRRFRRRFRRR4RRRRRRRRRRRRRRr$   c            	     4   t         dz  dz  dz  } | j                         r| j                          t        t        dt        i      }t        d|ddd	d
      }t        ||        t        t        dt        i      }t        d|ddd      }t        ||        | j                  d      j                         j                         }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 ]  }t)        j*                  |      }t,        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'}||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}}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}}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}}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}} t)        j*                  |d/         }|d'   }|t0        k(  }|st        j                  d|fd0|t0        f      t        j"                  |      d1t        j                         v st        j                   t0              rt        j"                  t0              nd1d)z  }d*d+|iz  }t%        t        j&                  |            dx}}|d,   }d}||k(  }|slt        j                  d|fd2||f      t        j"                  |      t        j"                  |      d3z  }d4d5|iz  }	t%        t        j&                  |	            dx}x}}|d-   }d6}||u }|slt        j                  d7|fd8||f      t        j"                  |      t        j"                  |      d3z  }d4d5|iz  }	t%        t        j&                  |	            dx}x}}|d.   }d9}||u }|slt        j                  d7|fd8||f      t        j"                  |      t        j"                  |      d3z  }d4d5|iz  }	t%        t        j&                  |	            dx}x}}t)        j*                  |d:         }|d'   }|t2        k(  }|st        j                  d|fd0|t2        f      t        j"                  |      d;t        j                         v st        j                   t2              rt        j"                  t2              nd;d)z  }d*d+|iz  }t%        t        j&                  |            dx}}|d,   }d}||k(  }|slt        j                  d|fd2||f      t        j"                  |      t        j"                  |      d3z  }d4d5|iz  }	t%        t        j&                  |	            dx}x}}|d-   }d9}||u }|slt        j                  d7|fd8||f      t        j"                  |      t        j"                  |      d3z  }d4d5|iz  }	t%        t        j&                  |	            dx}x}}|d.   }d6}||u }|slt        j                  d7|fd8||f      t        j"                  |      t        j"                  |      d3z  }d4d5|iz  }	t%        t        j&                  |	            dx}x}}| j                  d      }t4        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  }d@d&|iz  }t%        t        j&                  |            d} | j                  d6A       y)Bu	  (8) audit JSONL의 마지막 라인에 4 필드 모두 존재 검증:
    token_source_used / mergedBy_login / owner_pat_used / expected_bot_identity.

    회장 §"audit JSONL에 token_source/mergedBy/owner_pat_used/expected_bot_identity
    4 필드 존재"
    r   r   ztest_2523_v8_audit_tmp.jsonlrd   re   r?   r@   rA   rG   rE   r   r   rc   r[   rR   rS   r\   r   r   r      rh   r   r.   linesr   r  r   Nr   )z%(py0)s in %(py2)srequiredr7   r~   zmissing required field z in r   ro   r   r   r   r   ru   r   r   r   z%(py1)s == %(py3)sr   r   r   r   rq   Trr   r   Fr   r   ry   r{   r|   fullzassert %(py4)sr   )r   r   r   r   r   r   r   r   r   strip
splitlinesr.   r   r   r   r   r   r   r   r   r2   loadsr   r   r   r   r   )r   	probe_apprecord_success	probe_patrecord_fallbackr0  r   r  r   r   r   r   r7   r1  r   r   r   r   r   r   lastr   firstr4  r|   s                            r"   7test_v8_audit_jsonl_contains_required_4_fields_contractr>    s    8
#h
.1O
OC
zz|

%49:I (6CN ~#6 &-45I )%O 37 MM7M+113>>@Eu::?:33uu: 2**T"2 	\Hw&[[[8w[[[[[[8[[[8[[[[[[w[[[w[[[[*A(TRYQZ([[[[[[[	\ #-"g----"g---"------g---g-------*7****7*********7***7********7****7*********7***7*******&1&'1111&'111&111111'111'11111112 ::eBi D#$>$(>>>>>$(>>>>$>>>>>>(>>>>(>>>>>>>> !3^3!^3333!^333!333^3333333 !)T)!T))))!T)))!)))T)))))))'(1E1(E1111(E111(111E1111111 JJuQx E$%@%)@@@@@%)@@@@%@@@@@@)@@@@)@@@@@@@@!"E&EE"&EEEEE"&EEEE"EEE&EEEEEEEE!"+e+"e++++"e+++"+++e+++++++()1T1)T1111)T111)111T1111111 =='=*D# "T!!!!vT!!!!!!v!!!v!!!!!!T!!!T!!!!!!!" JJ$Jr$   c                 x   t        t              } h 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                  t              rt        j                  t              ndt        j                  |       t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x} x}}t        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                  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   REQUIRED_AUDIT_FIELDS_2523 는 정확히 4종.
    {token_source_used, mergedBy_login, owner_pat_used, expected_bot_identity}.
    >   r   r   r   r   rh   r   setr   r   r  r   Nr'   r.   )r@  r   r   r   r   r   r   r   r   r   r.   )r   r  r   r   r   s        r"   3test_sanity_required_audit_fields_contract_constantrA  -  s    )*  / * /  
 * /  
  
    
    
  
  *  
  *  
  +  
 /    
   )*/a/*a////*a//////3///3//////)///)///*///a///////r$   c                    t        t              D  ch c]  } | j                   }} 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}}yc c} w )	uO   MergeIdentityAuditRecord.owner_pat_used 필드 존재 — task-2523 §검증 8.r   r   r   field_namesr   r   ru   N)_fieldsr
   namer   r   r   r   r   r   r   r   )frC  r   r   r   r   s         r"   5test_sanity_owner_pat_used_field_present_in_dataclassrG  :  s    #*+C#DEa166EKE*{****{*********{***{******* Fs   C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	   }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}}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        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            d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   select_merge_token_decision: GITHUB_APP_INSTALLATION_TOKEN → allow_merge=True.
    회장 §"GH_TOKEN process-local injection이 owner PAT보다 우선" 의 후속 결정.
    allow_mergeTrr   r   r   r   rq   NdecisionAPP_TOKEN_OKrh   r   capability_gapFr3  r   r   r   ru   )r   r   r   r   r   r   r   r   r   r   r   r   )	decision_appr   r   r   r   r   decision_patr   r   s	            r"   >test_sanity_select_merge_token_decision_app_token_allows_mergerO  @  s    //FGL&.$.&$....&$...&...$.......
#5~5#~5555#~555#555~5555555()2U2)U2222)U222)222U2222222 //EFL&/%/&%////&%///&///%///////
#A#'AAAAA#'AAAA#AAAAAA'AAAA'AAAAAAAA()1T1)T1111)T111)111T1111111r$   c            	     p   t        t              } | j                  }d} ||      }|s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                  |       t        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx} x}x}}y)uH   task-2523에서 default audit path 변경 X — task-2522 결정 유지.zbot-merge-identity.jsonlzhassert %(py9)s
{%(py9)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.endswith
}(%(py7)s)
}strr	   )rm   r   r   ru   rw   r   N)
rQ  r	   endswithr   r   r   r   r   r   r   )r   r   r   r   r   s        r"   .test_sanity_default_audit_jsonl_path_unchangedrS  P  s    '(M(11M2LM12LMMMMMMMM3MMM3MMMMMM'MMM'MMM(MMM1MMM2LMMMMMMMMMMr$   c                    t         d   } d}| |k(  }|slt        j                  d|fd| |f      t        j                  |       t        j                  |      dz  }dd|iz  }t	        t        j
                  |            dx} x}}t         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}}t         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}}t         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}}t         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}}t         d   d   } | t        k(  }|st        j                  d|fd| t        f      t        j                  |       dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t	        t        j
                  |            dx} }t         d	   d
   }t         d	   d   }t        ||      }d}	||	u }
|
st        j                  d|
fd||	f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      t        j                  |	      dz  }dd |iz  }t	        t        j
                  |            dx}x}x}x}
}	y)!u   PR #73 fixture는 BOT_MERGE_IDENTITY_SUCCESS 의 immutable replay 입력.
    회장 §"replay fixture 필수 — PR #73 (mergedBy=app/jeon-jonghyuk-taskctl-bot
    mergeCommit=b7a37521)".
    rL   r?   rh   r   r   r   rq   NrM   rB   r@   rD   Trr   r   rO   rJ   rG   rI   rF   rK   r3  r   r   r   ru   rC   )z9%(py6)s
{%(py6)s = %(py0)s(%(py2)s, %(py4)s)
} is %(py9)sr   )rm   rn   ro   rq   r   zassert %(py11)spy11)rP   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r  r   @py_assert7r   @py_format12s                r"   7test_sanity_pr_73_fixture_immutable_bot_identity_replayrX  U  sq   
 "(b("b(((("b((("(((b((((((($W-P1PP-1PPPPP-1PPPP-PPP1PPPPPPPP$X.6$6.$6666.$666.666$6666666!-0 202  02   1    	3      !*-G1GG-1GGGGG-1GGGG-GGG1GGGGGGGG!"9:U:>UUUUU:>UUUU:UUUUUU>UUUU>UUUUUUUU 	j!'*j!&)**)  
  
    
  v   +   I +   I 	+  I 	*  I   I      r$   c                 T   g d} t        |       }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}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t	        t        j
                  |            d	x}x}}g d}t        |      }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}}g d}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   }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   verify_branch_cleanup_token_inheritance — admin/force 플래그 검출.
    회장 §금지 18종 중 admin override / force 적용 회귀 박제.
    )r)   r*   r  r  r	  r
  r  r  r  r   )z%(py1)s in %(py4)sr   r   rq   Nr  Frr   r   )r)   r*   r  r  r	  r
  r  r  )r)   r*   r  r  r	  r   r   )r   r   r   r   r   r   )		bad_adminresr   r   r   r   r   	bad_force
no_cleanups	            r"   Gtest_sanity_verify_branch_cleanup_token_inheritance_rejects_admin_forcer^  i  s    VI
1)
<C76779777779777797777777777767@5@75@@@@75@@@7@@@5@@@@@@@UI
1)
<C767797777797777977777777777 9J
1*
=C,-66-6666-666-6666666666+,55,5555,555,5555555555r$   c                 t   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	   }d
}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}t        di       }|j                  }|t        k(  }|st        j                  d|fd|t        f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            dx}}t        d|dd      }|j                  }d
}	||	u }|st        j                  d|fd||	f      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}}	|j                  }d}	||	u }|st        j                  d|fd||	f      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}}	y)u   token_source=UNKNOWN → fail-closed (allow_merge=False, capability_gap=True).
    process-local injection이 실패한 경우의 안전망.
    rI  Frr   r   r   r   rq   NrL  Tre   rh   rj   rk   r   rl   r   r-   )r   r   r   r   r   r   rt   rv   rw   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rJ  r   r   r   r   r   rk   r   r   r   r   r   s               r"   .test_sanity_unknown_token_source_is_failclosedr`  }  sA    ++?@HM"+e+"e++++"e+++"+++e+++++++$%--%----%---%----------!d;E5!55555!555555555555555555555!5555!55555555	F ))1T1)T1111)T11111161116111)111T1111111  )E) E)))) E))))))6)))6))) )))E)))))))r$   )r   r-   r-   )r   r/   r   rQ  r   rQ  r;   r<   )r8   zDict[int, Any])N__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r2   r   r    sysdataclassesr   rD  pathlibr   typingr   r   r   __file__resolveparentr   rQ  pathremoveinsertutils.bot_merge_identityr	   r
   r   r   r   r   r   r   r   r   r   r   r$  r   r   r   utils.repository_policy_adapterr   r   r   r#   r>   rP   __annotations__rT   rV   rX   rZ   r]   r   r   r   r   r   r   r   r   r  r-  r>  rA  rG  rO  rS  rX  r^  r`  r=   r$   r"   <module>rt     s  < #    	  
 )  " "
 h'')0077>>~#(("HHOOC'( 3~& '    
 e< 95TXY(*A!8		
!~ 
 (&EJ$2HI!~  (&EJ$2HI!~  (&EJ$2HI!~  (&EJ$2HI!~  (&EJ$2HI!~  $:  4 > ID3H# T*Xb-\h&GZ4SvH `
0+2 N
(6(*r$   