
    4jJA                       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Z ee      j#                         j$                  j$                  j$                  Z ee      ej*                  v r!ej*                  j-                   ee             ej*                  j/                  d ee             ddlmZ ddlmZ ddlmZmZ edz  d	z  Zd(d
Z d)dZ! G d d      Z" G d d      Z# ejH                  d      d        Z%d Z& ejH                  d      d        Z'd*dZ(d Z)d Z*d Z+d Z,d Z-d Z.d Z/d Z0d Z1d Z2d  Z3d! Z4d" Z5d# Z6d$ Z7d% Z8e9d&k(  r e: ejv                  ed'g            y)+u  tests/regression/test_callback_cancel_operational_integration_2553plus23.py

task-2553+23 — CALLBACK_CANCEL_ON_SUCCESS_OPERATIONAL_INTEGRATION regression.

§7 필수 12 (회장 verbatim 10 + 9-R.2/9-R.3 추가 2) — 전건 PASS.

100% offline. 실 callback cron / cokacdir subprocess / network / git mutation 0.
모든 cron-list 는 **주입 fake lister**, 모든 cron-remove 는 **주입 fake
remover**. 실 subprocess 호출 시 테스트 즉시 FAIL(차단 spy).

frozen anchor utils/anu_delegation_completion_callback.py 는 본 테스트·seam·
verifier 어디에서도 import/호출하지 않는다 — AST 정적 증명(§3, §6).

live `/home/jay/workspace` git tracked HEAD/branch/ref 는 테스트 전후
assertEqual (§6) — 본 task 산출물은 git-untracked batch-internal.
    )annotationsN)Path)RemoverResult)run_operational_cancel_seam)LiveVerifyClassificationverify_live_cron_statememoryfixturesc                `    t        j                  t        |  dz  j                  d            S )Nz.jsonutf-8encoding)jsonloadsFIXDIR	read_text)names    _/home/jay/workspace/tests/regression/test_callback_cancel_operational_integration_2553plus23.py_fxr   ,   s*    ::v4&.9979KLL    c                F   i }|| d    dz  }|j                  t        j                  | d         d       ||d<   || d    dz  }|j                  t        j                  | d         d       ||d	<   || d    d
z  }|j                  | j                  dd      d       ||d<   || d    dz  }| j                  dd      r-d| v r)|j                  t        j                  | d         d       ||d<   || d    dz  |d<   || d    dz  |d<   || d    dz  |d<   |S )Ntask_idz.dispatch-fired.jsondispatch_fired_markerr   r   dispatch_fired_marker_pathz.result.jsonresult_jsonresult_json_pathz
.report.mdreport_text report_pathz.collector-result.jsoncollector_result_marker_presentTcollector_result_markercollector_result_marker_pathz.fallback-cancelled.jsonfallback_cancelled_marker_pathz.cancel.lockcancel_lock_pathz.cancel-audit.json
audit_path)
write_textr   dumpsget)fxtmppathsdfmrjrepcrms          r   _materializer0   0   sn   E
2i=/!56
6CNN4::b!89:WNM*-E
&'	"Y--	-BMM$**R./'MB "E

2i=/,
,CNN266-,wN?E-
2i=/!78
8C	vv/6;TXZ;Ztzz"%>"?@7S,/E
().1r)}oE]4^.^E
*+ #I|&D DE
2i=/1C DDE,Lr   c                       e Zd ZdZddZddZy)FakeCronListeruP   주입 fake — fixture live_cron_entries 를 정규화 형태로 반환. 실 0.c                .    || _         || _        d| _        y )Nr   )entriesstatuscalls)selfr4   r5   s      r   __init__zFakeCronLister.__init__L   s    
r   c                    | xj                   dz  c_         | j                  dk7  r| j                  g i dS dt        | j                        ddidS )N   ok)r5   r4   rawfakeT)r6   r5   listr4   )r7   s    r   __call__zFakeCronLister.__call__Q   sF    

a
;;$"kkbDD4+=vtnUUr   N)r;   )returndict__name__
__module____qualname____doc__r8   r?    r   r   r2   r2   I   s    Z
Vr   r2   c                  (    e Zd ZdZdddZddd	dZy)

SpyRemoveruF   주입 fake remover — 호출 인자/횟수 기록. 실 subprocess 0.c                     || _         g | _        y )N)r5   r6   )r7   r5   s     r   r8   zSpyRemover.__init__[   s    
r   T)dry_runc                   | j                   j                  ||d       t        | j                  d| j                         S )Ncron_idrK   zfake:)r5   detail)r6   appendr   r5   )r7   rN   rK   s      r   r?   zSpyRemover.__call___   s5    

g'BCDKK%}8MNNr   N)removed)r5   str)rN   rR   rK   boolr@   r   rB   rG   r   r   rI   rI   X   s    P 9= Or   rI   T)autousec                8    d }| j                  t        d|       y)uU   어떤 테스트에서도 실 subprocess (--cron-list/--cron-remove) 호출 0 강제.c                     t        d      )NuR   실 subprocess 호출 금지 (§6 9-R.4) — 주입 fake lister/remover 만 허용)AssertionError)aks     r   _boomz%_block_real_subprocess.<locals>._boomh   s    `
 	
r   runN)setattr
subprocess)monkeypatchrZ   s     r   _block_real_subprocessr_   d   s    

 
E51r   c                 R   t         dz  } | dz  j                  d      j                         }|j                  d      r|j	                  dd      d   n|}|j                  d      r| |z  nd}|r3|j                         r#| |z  j                  d      j                         n|}|||fS )	u   live workspace git tracked HEAD/branch/ref (read-only — mutation 0).

    subprocess 가 차단되어 있으므로 git CLI 대신 .git 파일을 직접 읽는다.
    z.gitHEADr   r   zref:zref: r:   N)	WORKSPACEr   strip
startswithsplitexists)git_dirhead_txtbranchref_pathshas        r   _git_refrl   p   s    
 & G& ++W+=CCEH.6.A.A&.IX^^GQ'*xF#+#6#6v#>wDH ) 
6	$$g$6<<> 
 fc""r   c               #  B  K   t               } d t               }|| k(  }|st        j                  d|fd|| f      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z  }t        j                  d      dz   d	|iz  }t        t        j                  |            dx}}yw)
uA   §6 — 테스트 전후 git tracked HEAD/branch/ref assertEqual.N==)z)%(py2)s
{%(py2)s = %(py0)s()
} == %(py4)srl   beforepy0py2py4u.   git HEAD/branch/ref 변경 감지 (§6 위반)z
>assert %(py6)spy6)
rl   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgrW   _format_explanation)rp   @py_assert1@py_assert3@py_format5@py_format7s        r   _git_ref_invariantr      s      ZF	:Q:QQQ:QQQQQQ8QQQ8QQQ:QQQQQQQQQQQQQ!QQQQQQQs   DDc          
     h    t        | |      }t        d| d   | d   | j                  d      ||dd|S )Nr   target_cron_idcallback_contractF)r   r   r   cron_listerremoveroperationalrG   )r0   r   r(   )r)   r*   r   listerr+   s        r   _seamr      sP    S!E& 9*+&&!45  r   c                Z   t        d      }t        d      }t        |d         }t        || ||      }|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}||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ddg}||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}||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}||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)uC   1. normal success + live ownership VERIFIED → cron-remove called.task-2553+23.live-verifiedrQ   live_cron_entriesr   r   PLUS9A_CANCELLEDrn   z;%(py2)s
{%(py2)s = %(py0)s.seam_classification
} == %(py5)soutrr   rs   py5assert %(py7)spy7NTisz;%(py2)s
{%(py2)s = %(py0)s.cron_remove_invoked
} is %(py5)s)z:%(py2)s
{%(py2)s = %(py0)s.fallback_cancelled
} is %(py5)szG%(py2)s
{%(py2)s = %(py0)s.remove_allowed_by_live_verifier
} is %(py5)sz	FB23-0001rM   z-%(py2)s
{%(py2)s = %(py0)s.calls
} == %(py5)sspyz@%(py2)s
{%(py2)s = %(py0)s.normal_success_preserved
} is %(py5)sr:   r   )r   rI   r2   r   seam_classificationrv   rw   rx   ry   rz   r{   rW   r}   cron_remove_invokedfallback_cancelledremove_allowed_by_live_verifierr6   normal_success_preserved
tmp_pathr)   r   r   r   r~   @py_assert4r   @py_format6@py_format8s
             r   test_01_verified_remove_calledr      sZ   	)	*B
Y
CB234F
Hc&
9C""8&88"&88888"&888888838883888"888&88888888""*d*"d****"d******3***3***"***d*******!!)T)!T))))!T))))))3)))3)))!)))T)))))))..6$6.$6666.$66666636663666.666$666666699C[TBCC9CCCCC9CCCCCCC3CCC3CCC9CCCCCCCCCCC''/4/'4////'4//////3///3///'///4///////<<1<1<166<1r   c           	        t        d      }t        d      }t        || |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}||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                  }g }||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}||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)uI   2. normal success + live cron missing → cancel skipped, success 유지.task-2553+23.live-missingrQ   r   r   SKIP_LIVE_SKIP_ALREADY_REMOVEDrn   r   r   r   r   r   NFr   r   r   r   Tr   r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r   r6   r   	r   r)   r   r   r~   r   r   r   r   s	            r   +test_02_live_missing_skip_success_preservedr      s   	(	)B
Y
C
Hc.DWAX2Y
ZC""F&FF"&FFFFF"&FFFFFFF3FFF3FFF"FFF&FFFFFFFF""+e+"e++++"e++++++3+++3+++"+++e+++++++999?9339''/4/'4////'4//////3///3///'///4///////r   c           	     ,   t        d      }t        d      }t        || |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   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}
}|j                  }g }||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}||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)u8   3. normal success + task_id mismatch → cancel skipped.task-2553+23.task-id-mismatchrQ   r   r   SKIP_LIVE_SKIP_MISMATCHrn   r   r   r   r   r   Nchecksc1_task_id_matchFr   z%(py1)s is %(py4)spy1rt   assert %(py6)sru   r   r   Tr   )r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   live_verificationr6   r   r   r)   r   r   r~   r   r   r   r   @py_assert0@py_assert2r   r   s                r   test_03_task_id_mismatch_skipr      s   	,	-B
Y
C
Hc.DWAX2Y
ZC""?&??"&?????"&???????3???3???"???&????????  *+=>G%G>%GGGG>%GGG>GGG%GGGGGGG999?9339''/4/'4////'4//////3///3///'///4///////r   c           	        t        d      }t        d      }t        || |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   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}
}|j                  }g }||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)u8   4. normal success + chat_id mismatch → cancel skipped.task-2553+23.chat-id-mismatchrQ   r   r   r   rn   r   r   r   r   r   Nr   c2_chat_id_ownedFr   r   r   r   ru   r   r   r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r   r6   r   s                r   test_04_chat_id_mismatch_skipr      sr   	,	-B
Y
C
Hc.DWAX2Y
ZC""?&??"&?????"&???????3???3???"???&????????  *+=>G%G>%GGGG>%GGG>GGG%GGGGGGG999?9339r   c           	        t        d      }t        d      }t        || |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   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}
}|j                  }g }||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)u9   5. normal success + role not fallback → cancel skipped.task-2553+23.role-not-fallbackrQ   r   r   r   rn   r   r   r   r   r   Nr   c3_role_fallbackFr   r   r   r   ru   r   r   r   r   s                r   test_05_role_not_fallback_skipr      sr   	-	.B
Y
C
Hc.DWAX2Y
ZC""?&??"&?????"&???????3???3???"???&????????  *+=>G%G>%GGGG>%GGG>GGG%GGGGGGG999?9339r   c                6   t        d      }t        d      }t        |d         }t        || ||      }|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}||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                  }g }||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}}|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)uB   6. normal failed/HOLD/partial → cancel skipped, fallback 보존.ztask-2553+23.normal-failedrQ   r   r   SKIP_DURABLE_NOT_SATISFIEDrn   r   r   r   r   r   NFr   r   r   r   r   r   Tr   )r   rI   r2   r   r   rv   rw   rx   ry   rz   r{   rW   r}   r   r6   r   r   s
             r   -test_06_normal_failed_skip_fallback_preservedr      sj   	)	*B
Y
CB234F
Hc&
9C""B&BB"&BBBBB"&BBBBBBB3BBB3BBB"BBB&BBBBBBBB""+e+"e++++"e++++++3+++3+++"+++e+++++++999?9339<<1<1<166<1''/4/'4////'4//////3///3///'///4///////r   c           	        t        d      }t        d      }t        || |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}||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                  }g }||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}||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;   7. fallback already fired → idempotent no-op, no failure.task-2553+23.already-firedrQ   r   r   SKIP_LIVE_SKIP_ALREADY_FIREDrn   r   r   r   r   r   NFr   r   r   r   Tr   r   r   s	            r   %test_07_already_fired_idempotent_noopr      s   	)	*B
Y
C
Hc.DWAX2Y
ZC""D&DD"&DDDDD"&DDDDDDD3DDD3DDD"DDD&DDDDDDDD""+e+"e++++"e++++++3+++3+++"+++e+++++++999?9339''/4/'4////'4//////3///3///'///4///////r   c                   ddl }t        j                  j                  dt	        t
        dz  dz               |j                  d      }|j                         }| dz  }|j                  |j                  |      ||j                        }|j                  |j                  |      ||j                        }|j                  }|j                  }|j                  }	||	k(  }
|
st        j                   d|
fd	||	f      d
t#        j$                         v st        j&                  |      rt        j(                  |      nd
t        j(                  |      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}
x}}	|j                  }|j                  }|j.                  }	||	k(  }
|
st        j                   d|
fd||	f      dt#        j$                         v st        j&                  |      rt        j(                  |      ndt        j(                  |      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}
x}}	|j0                  }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   8. +9a/+16 DUPLICATE_CALLBACK_IGNORED 경로 무회귀.

    기존 dedup regression 모듈을 재실행하여 본 +23 seam/verifier 추가가 기존
    duplicate-callback 경로를 회귀시키지 않음을 입증한다.
    r   Ntests
regression8test_completion_callback_dup_ignored_realworld_2553plus1zdup.callback-ack.json)post_result_review_fnrn   )zt%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.Classification
}.PASS
}firstdup)rr   rs   rt   ru   py8assert %(py10)spy10)z%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.Classification
}.DUPLICATE_CALLBACK_IGNORED
}secondFr   )z:%(py2)s
{%(py2)s = %(py0)s.closeout_candidate
} is %(py5)sr   r   r   )	importlibsyspathinsertrR   rb   import_module_fixture!run_completion_callback_collector_normal_input_mock_review_advisory_fallback_inputclassificationClassificationPASSrv   rw   rx   ry   rz   r{   rW   r}   DUPLICATE_CALLBACK_IGNOREDcloseout_candidate)r   r   r   fxdackpr   r   r~   @py_assert5@py_assert7r   @py_format9@py_format11r   r   r   s                   r   -test_08_duplicate_callback_path_no_regressionr      s    HHOOAs9w.=>?

!
!BC ,,.C--D11#C<U<U 2 E 22C $c>W>W 3 F :3#5#5:#5#:#::#:::::#:::::::5:::5:::::::::3:::3:::#5:::#::::::::  QC$6$6Q$6$Q$QQ $QQQQQ $QQQQQQQ6QQQ6QQQ QQQQQQCQQQCQQQ$6QQQ$QQQQQQQQ$$--$----$------6---6---$----------r   c           
     R   g d}|D ]  }t        |      }t        d      }t        || |t        |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  }	t        j                  |      d
z   d|	iz  }
t        t        j                  |
            dx}x}}|j                  }g }||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  }	t        j                  | d      d
z   d|	iz  }
t        t        j                  |
            dx}x}} t        d      }t        d      }t        || |t        |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                  }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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)u   9. 실 remove 호출은 verifier PASS 일 때만 가능.

    verifier SKIP 계열 전수 → remover 절대 미호출. VERIFIED 1건만 호출.
    )r   r   r   r   r   task-2553+23.marker-id-mismatchtask-2553+23.already-removedrQ   r   r   Fr   r   r   r   z
>assert %(py7)sr   Nrn   r   r   u(   : verifier SKIP 인데 remover 호출됨r   Tr   r:   )zK%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.calls
})
} == %(py8)slen)rr   r   py3r   r   r   r   )r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   r|   rW   r}   r6   r   )r   skip_fixturesr   r)   r   r   r~   r   r   r   r   r   r   @py_assert6r   r   s                   r   +test_09_real_remove_only_when_verifier_passr     s   
M  RY##nR@S=T.U
 22AeA2e;AAA2eAAAAAAsAAAsAAA2AAAeAAATAAAAAAAyyQBQyBQQQyBQQQQQQsQQQsQQQyQQQBQQQ4&(P QQQQQQQQR 
)	*B
Y
C
Hc.DWAX2Y
ZC..6$6.$6666.$66666636663666.666$6666666yy3y>Q>Q>Q33ssy>Qr   c           	     4   t        d      }d|d   dddddg|d<   t        d	      }t        || |t        |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                  }g }||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   10. wrong cron id 제거 시도 0.

    live 목록에 target 과 다른 id 만 존재 → 어떤 경우에도 그 id 로 remove 0.
    r   zWRONG-OTHER-IDr   l   L5: fallbackF)idr   chat_idrolefiredrQ   r   rQ   r   r   r   r   r   r   r   Nrn   r   r   r   r   )r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r6   r   r   s	            r   #test_10_wrong_cron_id_never_removedr   !  s   
 
)	*BByMje	?B Y
C
Hc.DWAX2Y
ZC""+e+"e++++"e++++++3+++3+++"+++e+++++++999?9339""F&FF"&FFFFF"&FFFFFFF3FFF3FFF"FFF&FFFFFFFFr   c           	     ,   t        d      }t        d      }t        || |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   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}
}|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                  }g }||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^   11. dispatch-fired marker fallback_cron_id 불일치 → cancel skipped, 실 remove 0 (9-R.2).r   rQ   r   r   r   rn   r   r   r   r   r   Nr   c4_marker_id_crosscheckFr   r   r   r   ru   r   r   r   )r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r   r   r6   r   s                r   -test_11_marker_fallback_cron_id_mismatch_skipr   2  s   	.	/B
Y
C
Hc.DWAX2Y
ZC""?&??"&?????"&???????3???3???"???&????????  *+DENNENNNNENNNENNNNNNNNNN""+e+"e++++"e++++++3+++3+++"+++e+++++++999?9339r   c           	        t        d      }t        d      }t        || |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}||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                  }g }||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}||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   }	d}|	|k(  }
|
slt        j                  d|
fd|	|f      t        j                  |	      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}	x}
}y)ub   12. fallback already removed → idempotent no-op, 이중 remove 0, normal success 불변 (9-R.3).r   rQ   r   r   r   rn   r   r   r   r   r   NFr   r   r   r   Tr   r   SKIP_ALREADY_REMOVEDz%(py1)s == %(py4)sr   r   ru   )r   rI   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r   r6   r   r   r   s                r   'test_12_already_removed_idempotent_noopr  =  sU   	+	,B
Y
C
Hc.DWAX2Y
ZC""F&FF"&FFFFF"&FFFFFFF3FFF3FFF"FFF&FFFFFFFF""+e+"e++++"e++++++3+++3+++"+++e+++++++999?9339''/4/'4////'4//////3///3///'///4///////  !12L6LL26LLLLL26LLLL2LLL6LLLLLLLLr   c                 V   dD ]  } t         dz  |  dz  j                  d      }t        j                  |      }g }t        j                  |      D ]~  }t        |t        j                        r(||j                  D cg c]  }|j                   c}z  }Et        |t        j                        s`|j                  |j                  xs d        d |D        }t        |      }| }|st        j                  |  d|       d	z   d
t        j                          v st        j"                  t              rt        j$                  t              nd
t        j$                  |      t        j$                  |      dz  }	t'        t        j(                  |	            dx}x}} yc c}w )uT   seam/verifier 가 frozen orchestrator 를 import/호출하지 않음 — AST 증명.)+completion_callback_operational_cancel_seamlive_cron_state_verifierutilsz.pyr   r   r   c              3  ,   K   | ]  }d |xs dv   yw)"anu_delegation_completion_callbackr   NrG   ).0ms     r   	<genexpr>z6test_aux_frozen_anchor_not_imported.<locals>.<genexpr>[  s      
BC0QW"=
s   u+   : frozen orchestrator import 결합 발견 z2
>assert not %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyrq   N)rb   r   astparsewalk
isinstanceImportnamesr   
ImportFromrP   moduler  rv   r|   rx   ry   rz   r{   rW   r}   )
modsrctreeimportednoderX   r~   r   r   r   s
             r   #test_aux_frozen_anchor_not_importedr  M  s    I 7"uC[0;;W;Myy~HHTN 	3D$

+TZZ8QVV88D#..1 1r2		3

GO
 	I3 
 
 	I 
 
 	I 
 	I7H7HcU=hZH	I 	IBH&	I 	I0H0H  	I 	I?Hy  	I 	I?Hy
 	I 	I?Hy
 	I 	I 	I5H5H	I 	I 	II 9s   >F&
c           	     D   t        d      }t        ||       }t        |d   |d   |d   t        g d            }|j                  }t
        j                  }||k(  }|st        j                  d|fd	||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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)uK   live 조회 실패 → SKIP_QUERY_FAILED, remove_allowed=False (fail-safe).r   r   r   r   error)r5   )r   r   r   r   rn   )z]%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.SKIP_QUERY_FAILED
}lvr   )rr   rs   rt   ru   zassert %(py8)sr   NFr   )z6%(py2)s
{%(py2)s = %(py0)s.remove_allowed
} is %(py5)sr   r   r   )r   r0   r   r2   r   r   SKIP_QUERY_FAILEDrv   rw   rx   ry   rz   r{   rW   r}   remove_allowed)r   r)   r+   r  r~   r   r   r   r   r   r   r   s               r   $test_aux_query_failed_skips_preserver   `  sW   	)	*BX&E	9*+#()E#F"2g6	
B J 8 J JJ JJJJJ JJJJJJJ2JJJ2JJJJJJJJJ 8JJJ 8JJJ JJJJJJJJ%%%%%%%%%%%%2%%%2%%%%%%%%%%%%%r   c           	     $   t        d      }t        d      }t        ||       }t        d|d   |d   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}}t        j                   t#        |j                        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   }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)uS   디커플 + audit: remove skip 이어도 normal success 유지 + audit JSON 기록.r   rQ   r   r   r   F)r   r   r   r   r   Tr   r   r   r   r   r   Nis notz6%(py2)s
{%(py2)s = %(py0)s.audit_path
} is not %(py5)sr   r   schematask-2553+23.cancel-audit_v1rn   r  r   r   ru   decisionr   r   rG   )r   rI   r0   r   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r%   r   r   r   r   )r   r)   r   r+   r   r~   r   r   r   r   recr   r   r   r   s                  r   test_aux_decouple_audit_writtenr)  n  sa   	,	-B
Y
CX&E
% 9*+"2&9#:; C ''/4/'4////'4//////3///3///'///4///////>>%%>%%%%>%%%%%%3%%%3%%%>%%%%%%%%%%
**T#..)33W3E
FCx=:::=:::::=::::=:::::::::::y>*R	]*>]****>]***>***]*******z?01:U:1U::::1U:::1:::U:::::::r   c                D   t        d      }t        d      }t        ||       }dd}t        d|d   |d   |j	                  d      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}}t!        j"                  t%        |j                        j'                  d            }|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)u   디커플 절대불변: 주입 now_fn 이 예외를 던져도 collector 비전파,
    normal_success_preserved=True, audit 기록 (independent-review MED fix).r   rQ   c                     t        d      )Nzclock failure injected)RuntimeErrorrG   r   r   	_boom_nowz;test_aux_raising_now_fn_never_propagates.<locals>._boom_now  s    344r   r   r   r   r   F)r   r   r   r   r   r   now_fnTr   r   r   r   r   r   Nr"  r$  r   r   r%  r&  rn   r  r   r   ru   )r@   rR   rG   )r   rI   r0   r   r(   r2   r   rv   rw   rx   ry   rz   r{   rW   r}   r%   r   r   r   r   )r   r)   r   r+   r-  r   r~   r   r   r   r   r(  r   r   r   r   s                   r   (test_aux_raising_now_fn_never_propagatesr/    s    
)	*B
Y
CX&E5 & 	9*+&&!45"2&9#:;	 	C ''/4/'4////'4//////3///3///'///4///////>>%%>%%%%>%%%%%%3%%%3%%%>%%%%%%%%%%
**T#..)33W3E
FCx=:::=:::::=::::=:::::::::::r   __main__z-q)r   rR   r@   rA   )r)   rA   r*   r   r@   rA   )r)   rA   r*   r   )<rF   
__future__r   builtinsrx   _pytest.assertion.rewrite	assertionrewriterv   r  r   r]   r   pathlibr   pytest__file__resolveparentrb   rR   r   remover   )utils.completion_callback_fallback_cancelr   1utils.completion_callback_operational_cancel_seamr   utils.live_cron_state_verifierr   r   r   r   r0   r2   rI   fixturer_   rl   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r)  r/  rC   
SystemExitmainrG   r   r   <module>rB     s    #   
   
  N""$++2299	y>SXXHHOOC	N# 3y> " C
 
X	
	*M2V V	O 	O 2 2#" R R
 00
00.2<G"
M I&&;*;4 z
[V[[(D!12
33 r   