
    ajh                       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mZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z* edz  dz  jW                  d	
      Z,d,dZ-d,dZ.d-dZ/d Z0d Z1d Z2d Z3d Z4d Z5d Z6d Z7d Z8d Z9d Z:d Z;d Z<d Z=d Z>d.dZ?d Z@d ZAd  ZBd! ZCd" ZDd/d#ZEd$ ZFd% ZGd& ZHd' ZId( ZJd) ZKeLd*k(  r% ej                   ej                  ed+g             yy)0u2  tests/regression/test_anu_delegation_completion_callback_2595.py
— task-2595 Phase 2 회귀.

Phase 1 LOCKED spec: memory/tasks/task-2595.md
(locked content sha256 = c151030d719762da35eb5cafc34a9f4c74df4ba4c5085e077bb109120ae050d5).

회장 Phase 2 §7 필수 검증 10항목 + §7 검증 시나리오 7건:

1. normal completion callback fixture PASS
2. fallback stale callback fixture PASS (BOT_STALE / CALLBACK_MISSING / HOLD 단일 분기)
3. duplicate callback dedupe PASS
4. ack single-winner PASS
5. BOT_STALE / CALLBACK_MISSING / RESULT_MISSING 분류 PASS
6. Critical 7 → CRITICAL_7 / HOLD_FOR_CHAIR 분류 PASS
7. PASS case result summary marker 생성 PASS
8. ANU-Codex post-result review hook mock PASS (advisory, 자동 closeout 권한 X)
9. watcher/polling/daemon 없음 검증 PASS (source 정적 grep)
10. dispatch.py/task-timer.py forbidden_write_targets 변경 0 (별도 marker 증빙)

모든 테스트 100% offline — 실제 callback cron 등록 / 실제 codex 호출 /
network / git 호출 0건. tmp_path 만 사용 (live memory/events 미오염).
    )annotationsN)Path)Signals)ANU_CALLBACK_CHAT_IDCallbackInputCallbackTypeClassificationForbiddenActionPostcheckNoRealCodexReviewErrorPostResultReviewStaleDistinctionEvidence"build_completion_callback_contractcompute_fallback_stale_at_epoch no_real_codex_post_result_review!run_completion_callback_collectortry_acquire_ackvalidate_callback_ack_dedupe%validate_completion_callback_contractvalidate_delegation_resultutilsz%anu_delegation_completion_callback.pyutf-8encodingc                L    t        |t        j                  k(  rdnddddd      S )NPASSADVISORYTFu1   mock codex:codex-rescue advisory — 실 실행 0verdictadvisoryexecution_performedauto_closeout_authority_grantednote)r   r	   r   delegation_resultclassifications     T/home/jay/workspace/tests/regression/test_anu_delegation_completion_callback_2595.pymock_review_passr'   D   s-    (N,?,??Z!(-@     c                "    t        ddddd      S )Nr   TFzboundary violation fixturer   )r   r#   s     r&   mock_review_boundary_violationr*   N   s     (-) r(   c                    t        d i dddddddt        j                  dd	d
ddddddt        dd	dddd      ddgdddidt	               dddddddt               dd}|j                  |        t        d i |S )!Ntask_idz	task-9001executorz	dev2 Odindispatch_cron_idzcron-disp-9001callback_typecallback_cron_idzcron-cb-normal-9001cron_statusoktask_status	completedcron_duration_ming333333?stale_distinction_evidenceTFartefact)normal_callback_registerednormal_callback_cron_idfallback_firedttl_exceededbot_liveness_signalbot_liveness_observedoutput_markersz#memory/events/task-9001.result.jsonrequired_closeout_markersztask-9001.result.jsonforbidden_action_postcheck
dev_sunsetpreservation_anchorsmatch)post_tool_use_shguardsignalschair_gated )dictr   NORMALr   r
   r   updater   )overbases     r&   
good_inputrN   Y   s      * #))	
 /     $<'+$9  *"&$
" >>#$ $;D"A%& $<#='( )* 3:GL+, 	-. /D2 	KK 4  r(   c           	     b   | dz  }t        t               |t              }|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}}|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"                  }t%        |      }g }||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}}|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}}|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}}d }t&        j(                  }|j"                  } ||      }||v}|st        j                  d!|fd"||f      t        j                  |      d#t        j                         v st        j                  t&              rt        j                  t&              nd#t        j                  |      d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}x}}y )'Nztask-9001.callback-ack.jsonpost_result_review_fn==zP%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.PASS
}resr	   py0py2py4py6assert %(py8)spy8Tisz4%(py2)s
{%(py2)s = %(py0)s.ack_acquired
} is %(py5)srW   rX   py5assert %(py7)spy7z:%(py2)s
{%(py2)s = %(py0)s.closeout_candidate
} is %(py5)sFz=%(py2)s
{%(py2)s = %(py0)s.chair_report_required
} is %(py5)szW%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.delegation_result
})
} == %(py8)sr   rW   py1py3ra   r\   assert %(py10)spy10r%   r   z%(py1)s == %(py4)srh   rY   assert %(py6)srZ   schemaanu_delegation_result_v1zfinish-tasknot in)zx%(py1)s not in %(py10)s
{%(py10)s = %(py5)s
{%(py5)s = %(py3)s.dumps
}(%(py8)s
{%(py8)s = %(py6)s.delegation_result
})
}json)rh   ri   ra   rZ   r\   rk   zassert %(py12)spy12)r   rN   r'   r%   r	   r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationack_acquiredcloseout_candidatechair_report_requiredr$   r   rs   dumps)tmp_pathackrU   @py_assert1@py_assert5@py_assert3@py_format7@py_format9@py_assert4@py_format6@py_format8@py_assert2@py_assert7@py_assert6@py_format11@py_assert0@py_format5@py_assert9@py_format13s                      r&   test_normal_completion_passr   z   s2   
2
2C
+c1AC 4!4!44!44444!444444434443444444444444444!44444444#t#t####t######3###3######t#######!!)T)!T))))!T))))))3)))3)))!)))T)))))))$$--$----$------3---3---$----------&)&;&;B%&;<BB<BBBB<BBBBBB%BBB%BBBBBBcBBBcBBB&;BBB<BBBBBBBBBB  !12<f<2f<<<<2f<<<2<<<f<<<<<<<  *H.HH*.HHHHH*.HHHH*HHH.HHHHHHHHA

A3+@+@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AA3AAA3AAA+@AAA AAAAAAAAAr(   c                n   | dz  }t        dt        j                  dt        ddddd            }t	        ||t
        	      }|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}}	|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 )Nztask-9002.callback-ack.jsonz	task-9002zcron-cb-fallback-9002FTnoner8   r:   r;   r<   r=   r,   r/   r0   r6   rP   rR   )zU%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.BOT_STALE
}rU   r	   rV   r[   r\   r]   re   r`   rb   rc   stale_distinctionbranchu&   no_normal_cb + no_liveness→BOT_STALErl   rm   rn   rZ   )rN   r   FALLBACK_STALEr   r   r'   r%   r	   	BOT_STALEru   rv   rw   rx   ry   rz   r{   r|   r   classification_evidence)r   r   inprU   r   r   r   r   r   r   r   r   r   r   r   s                  r&   test_fallback_bot_staler      s   
2
2C
"110#;', &"'$
	C ,S(8C 9!9!99!99999!999999939993999999999999999!99999999$$,,$,,,,$,,,,,,3,,,3,,,$,,,,,,,,,,##$78B3B3	4 B3   	C   4      r(   c                   | dz  }t        dt        j                  dt        ddddd            }t	        ||t
        	      }|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   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 )Nztask-9003.callback-ack.jsonz	task-9003zcron-cb-fallback-9003FTworktree_mtimer   r   rP   rR   )z\%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.CALLBACK_MISSING
}rU   r	   rV   r[   r\   r   r   u*   no_normal_cb + liveness→CALLBACK_MISSINGrl   rm   rn   rZ   )rN   r   r   r   r   r'   r%   r	   CALLBACK_MISSINGru   rv   rw   rx   ry   rz   r{   r|   r   )r   r   r   rU   r   r   r   r   r   r   r   r   s               r&   test_fallback_callback_missingr      s{   
2
2C
"110#;', 0"&$
	C ,S(8C @!@!@@!@@@@@!@@@@@@@3@@@3@@@@@@@@@@@@@@@!@@@@@@@@##$78B7B7	8 B7   	C   8      r(   c                V   | dz  }t        dt        j                  dt        dddddd            }t	        ||t
        	      }|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}}d}	|j"                  }
|	|
v }|st        j                  d|fd|	|
f      t        j                  |	      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |
      dz  }dd|iz  }t        t        j                   |            d x}	x}}
y )Nztask-9004.callback-ack.jsonz	task-9004zcron-cb-fallback-9004FTr   )r8   r:   r;   r<   r=   evidence_collection_failedr   rP   rR   zZ%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.HOLD_FOR_CHAIR
}rU   r	   rV   r[   r\   &fallback_stale_evidence_undeterminableinz4%(py1)s in %(py5)s
{%(py5)s = %(py3)s.hold_reasons
}rh   ri   ra   rb   rc   )rN   r   r   r   r   r'   r%   r	   HOLD_FOR_CHAIRru   rv   rw   rx   ry   rz   r{   r|   hold_reasonsr   r   r   rU   r   r   r   r   r   r   r   r   r   r   s                 r&   +test_fallback_evidence_undeterminable_holdsr      se   
2
2C
"110#;', &"''+$
	C ,S(8C >!>!>>!>>>>>!>>>>>>>3>>>3>>>>>>>>>>>>>>>!>>>>>>>>3Gs7G7GG37GGGGG37GGGG3GGGGGGsGGGsGGG7GGGGGGGGr(   c                F   | dz  }t        dd      }t        dt        j                  d      }t        ||t              }t        ||t              }|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        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}}|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}}d}|j&                  d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}|j&                  }t)        |      }g }||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 )%Nztask-9005.callback-ack.jsonz	task-9005zcron-normal-9005)r,   r0   zcron-fallback-9005)r,   r/   r0   rP   Tr]   r_   firstr`   rb   rc   rR   rT   r	   rV   r[   r\   Fsecond)zf%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.DUPLICATE_CALLBACK_IGNORED
}rd   DUPLICATE_CALLBACK_IGNOREDduplicate_resolutionr   )z%(py1)s in %(py4)srm   rn   rZ   )zP%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.ack_dedupe
})
} == %(py8)sr   rg   rj   rk   )rN   r   r   r   r'   r}   ru   rv   rw   rx   ry   rz   r{   r|   r%   r	   r   r   r~   
ack_deduper   )r   r   inp1inp2r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                       r&   test_duplicate_callback_ignoredr      s   
2
2Ck<NOD"11-D
 .c)9E /c)9F %%%%%%%%%%%%5%%%5%%%%%%%%%%%%%6>#6#66#66666#666666656665666666666>666>666#66666666'%'%''''%''''''6'''6''''''%'''''''  MN$M$MM $MMMMM $MMMMMMM6MMM6MMM MMMMMMNMMMNMMM$MMMMMMMM$$--$----$------6---6---$----------'T6+<+<=S+TT'+TTTTT'+TTTT'TTT+TTTTTTTT(-(8(8?'(89?R?9R????9R??????'???'????????????(8???9???R???????r(   c                   | dz  g t        j                         dfd}t        d      D cg c]  }t        j                  |d| f       }}|D ]  }|j	                           |D ]  }|j                           j                  }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                  |      t        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            dx}x}x}x}	}j                  }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                  |      t        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            dx}x}x}x}	}yc c}w )uI   normal/fallback 동시 fire — atomic ack 가 정확히 1 winner 보장.ztask-9006.callback-ack.jsonc                    t        dt        j                  |       \  }}5  j                  |       d d d        y # 1 sw Y   y xY w)Nz	task-9006)r,   winning_callback_typewinning_callback_cron_id)r   r   rJ   append)cron_idacquired_r   lockresultss      r&   workerz1test_ack_single_winner_under_race.<locals>.worker   sI    %"."5"5%,	
!  	%NN8$	% 	% 	%s	   ?A   zcron-)targetargsT   rR   )zK%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.count
}(%(py4)s)
} == %(py9)sr   )rW   rX   rY   rZ   py9zassert %(py11)spy11NF   )r   str)	threadingLockrangeThreadstartjoincountru   rv   rw   rx   ry   rz   r{   r|   )r   r   ithreadstr   r   r   @py_assert8r   @py_format10@py_format12r   r   r   s               @@@r&   !test_ack_single_winner_under_racer      s   
2
2CG>>D% GLBiAB	aSk^<G   		 	==##=#!#!####!######7###7###=#########!#######==%%=%2%2%%%%2%%%%%%7%%%7%%%=%%%%%%%%%2%%%%%%%%s   "Jc                   | dz  }t        dddd      }t        ||t              }|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}}	d |j                  D        }t!        |      }|sddt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d x}}y )Nztask-9007.callback-ack.jsonz	task-9007FT)ztask-9007.result.jsonztask-9007.report.md)r,   r?   rP   rR   )zZ%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.RESULT_MISSING
}rU   r	   rV   r[   r\   r]   re   r`   rb   rc   c              3  $   K   | ]  }d |v  
 yw)missing_required_markerNrH   .0rs     r&   	<genexpr>z&test_result_missing.<locals>.<genexpr>  s     H!(A-H   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyrW   rX   rY   )rN   r   r'   r%   r	   RESULT_MISSINGru   rv   rw   rx   ry   rz   r{   r|   r   r   r   )r   r   r   rU   r   r   r   r   r   r   r   r   r   s                r&   test_result_missingr     s   
2
2C
%*#'#
C ,S(8C >!>!>>!>>>>>!>>>>>>>3>>>3>>>>>>>>>>>>>>>!>>>>>>>>$$,,$,,,,$,,,,,,3,,,3,,,$,,,,,,,,,,Hs7G7GHH3HHHHHHHHH3HHH3HHHHHHHHHHHHHHr(   c                   | dz  }t        dt        d            }t        ||t              }|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}}d}	|j                  }
|	|
v }|st        j                  d|fd|	|
f      t        j                  |	      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |
      dz  }dd|iz  }t        t        j                  |            d x}	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 )Nztask-9008.callback-ack.jsonz	task-9008   )forbidden_path_count)r,   rF   rP   rR   )zV%(py2)s
{%(py2)s = %(py0)s.classification
} == %(py6)s
{%(py6)s = %(py4)s.CRITICAL_7
}rU   r	   rV   r[   r\   FORBIDDEN_PATH_INTRUSIONr   )z6%(py1)s in %(py5)s
{%(py5)s = %(py3)s.critical_7_hit
}r   rb   rc   Tr]   re   r`   )rN   r   r   r'   r%   r	   
CRITICAL_7ru   rv   rw   rx   ry   rz   r{   r|   critical_7_hitr   r   s                 r&   test_critical_7_routingr   #  s   
2
2C
['q2Q
RC
+S(8C :!:!::!:::::!:::::::3:::3:::::::::::::::!::::::::%;););;%);;;;;%);;;;%;;;;;;;;;;;;);;;;;;;;$$,,$,,,,$,,,,,,3,,,3,,,$,,,,,,,,,,r(   c                ,   | dz  }t        dt        d            }t        ||t              }|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}}d}	|j                  }
|	|
v }|st        j                  d|fd|	|
f      t        j                  |	      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |
      dz  }dd|iz  }t        t        j                  |            d x}	x}}
y )Nztask-9009.callback-ack.jsonz	task-9009r   )forbidden_write_targets_changed)r,   r@   rP   rR   r   rU   r	   rV   r[   r\   #forbidden_action_postcheck_violatedr   r   r   rb   rc   )rN   r
   r   r'   r%   r	   r   ru   rv   rw   rx   ry   rz   r{   r|   r   r   s                 r&   %test_forbidden_action_holds_for_chairr   /  sJ   
2
2C
#;,-$
C ,S(8C >!>!>>!>>>>>!>>>>>>>3>>>3>>>>>>>>>>>>>>>!>>>>>>>>0DC4D4DD04DDDDD04DDDD0DDDDDDCDDDCDDD4DDDDDDDDr(   c                    | dz  }t        dddi      }t        ||t              }|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}}d |j                  D        }t        |      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }	t        t        j                  |	            d x}}y )Nztask-9010.callback-ack.jsonz	task-9010rD   mismatch)r,   rB   rP   rR   r   rU   r	   rV   r[   r\   c              3  $   K   | ]  }d |v  
 yw)preservation_anchor_mismatchNrH   r   s     r&   r   z:test_preservation_anchor_mismatch_holds.<locals>.<genexpr>H  s     Mq-2Mr   r   r   r   )rN   r   r'   r%   r	   r   ru   rv   rw   rx   ry   rz   r{   r|   r   r   )
r   r   r   rU   r   r   r   r   r   r   s
             r&   'test_preservation_anchor_mismatch_holdsr   >  s7   
2
2C
0*=C ,S(8C >!>!>>!>>>>>!>>>>>>>3>>>3>>>>>>>>>>>>>>>!>>>>>>>>MC<L<LMM3MMMMMMMMM3MMM3MMMMMMMMMMMMMMr(   c                   | dz  }t        t        d      |t              }| dz  }|j                  t	        j
                  |j                  dd      d	
       t	        j                  |j                  d	
            }t        |      }g }||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}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t!        t        j"                  |            d x}
x}}|d   }
d }|
|u}|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t!        t        j"                  |            d x}
x}}y )Nztask-9011.callback-ack.jsonz	task-9011r,   rP   z$task-9011.anu-delegation-result.jsonr   F)indentensure_asciir   r   rR   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   reloadedrW   rh   ri   rZ   r[   r\   r%   r   rl   rm   rn   rZ   codex_post_result_review_refis not)z%(py1)s is not %(py4)s)r   rN   r'   
write_textrs   r   r$   loads	read_textr   ru   rv   rw   rx   ry   rz   r{   r|   )r   r   rU   outr   r   r   r   r   r   r   r   r   s                r&   test_pass_marker_persistabler  N  s   
2
2C
+;'.C
 ;
;CNN

3((G   zz#---9:H%h/525/25555/2555555%555%555555h555h555/55525555555$%//%////%///%//////////23?4?34????34???3???4???????r(   c                     t        j                  t              5  t        i t        j
                         d d d        y # 1 sw Y   y xY wN)pytestraisesr   r   r	   r   rH   r(   r&   5test_post_result_review_default_invoker_no_real_codexr	  c  s8    	-	. B(^-@-@AB B Bs	   >Ac                ~   | dz  }t        t        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}}|j                  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                  }t        |      }g }||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)u9  기본 invoker 미주입 시 advisory SKIP 으로 안전 진행 (분류 불변).

    spec §3 계약: ``codex_post_result_review_ref`` 는 *marker path | null*.
    review 미수행(SKIP)이면 상태 문자열이 아니라 **null** 이어야 한다
    (task-2595_2+1 항목 1 — status 문자열 제거).
    ztask-9012.callback-ack.jsonz	task-9012r   rR   rT   rU   r	   rV   r[   r\   Nr]   )zD%(py2)s
{%(py2)s = %(py0)s.codex_post_result_review_ref
} is %(py5)sr`   rb   rc   r   z%(py1)s is %(py4)srm   rn   rZ   rf   r   rg   rj   rk   )r   rN   r%   r	   r   ru   rv   rw   rx   ry   rz   r{   r|   r   r$   r   )r   r   rU   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                    r&   )test_post_result_review_default_safe_skipr  h  s0    2
2C
+J{,KS
QC4!4!44!44444!444444434443444444444444444!44444444++3t3+t3333+t33333333333333+333t3333333  !?@HDH@DHHHH@DHHH@HHHDHHHHHHH&)&;&;B%&;<BB<BBBB<BBBBBB%BBB%BBBBBBcBBBcBBB&;BBB<BBBBBBBBBBr(   c                   | dz  }t        t        d      |t              }|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}}d |j                  D        }t        |      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)uJ   codex 가 실행 수행 보고 시 (회장 §7 위반) → HOLD_FOR_CHAIR.ztask-9013.callback-ack.jsonz	task-9013r   rP   rR   r   rU   r	   rV   r[   r\   Nc              3  $   K   | ]  }d |v  
 yw)BOUNDARY_VIOLATIONNrH   r   s     r&   r   zCtest_post_result_review_boundary_violation_holds.<locals>.<genexpr>  s     CQ#q(Cr   r   r   r   )r   rN   r*   r%   r	   r   ru   rv   rw   rx   ry   rz   r{   r|   r   r   )	r   r   rU   r   r   r   r   r   r   s	            r&   0test_post_result_review_boundary_violation_holdsr  x  s&   
2
2C
+;'<C
 >!>!>>!>>>>>!>>>>>>>3>>>3>>>>>>>>>>>>>>>!>>>>>>>>C#2B2BCC3CCCCCCCCC3CCC3CCCCCCCCCCCCCCr(   c                   | dz  }t        t        d      |t              }|j                  }d}||u }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      d	z  }d
d|iz  }t        t	        j                  |            dx}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}x}}	y)uL   회장 §5 — 자동 closeout 권한 미부여. PASS 라도 candidate only.ztask-9014.callback-ack.jsonz	task-9014r   rP   Tr]   rd   rU   r`   rb   rc   Nauto_closeout_performedz9assert not %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrrW   rh   ri   ra   )r   rN   r'   r~   ru   rv   rw   rx   ry   rz   r{   r|   r  )r   r   rU   r   r   r   r   r   r   r   r   s              r&   *test_auto_closeout_authority_never_grantedr    s   
2
2C
+;'.C
 !!)T)!T))))!T))))))3)))3)))!)))T)))))))56ws566666666666w666w666666s666s66656666666666r(   c                ,    t        j                  |       S )u   AST 로 실행 코드만 분석 — docstring/comment prose 는 제외.

    spec §8 boundary 를 *문서로 설명*하는 것은 허용·필수 (회장 §3 명시
    의무). 금지는 **기능적** watcher/polling/daemon 구현이다.
    )astparse)srcs    r&   _strip_docstrings_and_coder    s     99S>r(   c            	     Z   t        t              } h d}d}d}d}t        j                  |       D ]H  }t	        |t        j
                        r"|j                  D ]  }|j                  j                  d      d   }||v}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndd	z  }	t        j                  d
|j                         dz   d|	iz  }
t!        t        j"                  |
            d} t	        |t        j$                        r|j&                  xs dj                  d      d   }||v}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndd	z  }	t        j                  d|j&                         dz   d|	iz  }
t!        t        j"                  |
            d}t	        |t        j(                        r>t	        |j*                  t        j,                        r|j*                  j.                  du rd}t	        |t        j0                        s|j2                  }t	        |t        j4                        s|j6                  dk(  rd}|j6                  dv s|j6                  j9                  d      sGd}K d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d      dz   d|iz  }t!        t        j"                  |            dx}}d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d      dz   d|iz  }t!        t        j"                  |            dx}}d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d      dz   d|iz  }t!        t        j"                  |            dx}}y)u	  시나리오 7 — 기능적 watcher/polling/daemon/systemd 패턴 0 (AST 검증).

    docstring 의 boundary 설명 prose 는 false-positive 아님 (회장 §3 —
    boundary 를 명시 문서화하는 것은 의무). AST 로 실행 구문만 점검한다.
    >
   scheddaemonsignalasynciosystemdschedulewatchdogr   
subprocessapschedulerF.r   rq   )z%(py0)s not in %(py2)srootforbidden_import_roots)rW   rX   zforbidden import: z
>assert %(py4)srY   N zforbidden import-from: Tsleep)systempopenexecr]   )z%(py0)s is %(py3)swhile_true_foundrW   ri   z infinite while-True loop present
>assert %(py5)sra   sleep_call_foundzsleep() call present (polling)process_exec_founduC   process-exec (os.system/popen/exec*) present — real cron reg path)r  
MODULE_SRCr  walk
isinstanceImportnamesnamesplitru   rv   rw   rx   ry   rz   _format_assertmsgr{   r|   
ImportFrommoduleWhiletestConstantvalueCallfunc	Attributeattr
startswith)treer'  r-  r0  r1  nodear&  r   @py_format3r   fr   @py_format4r   s                  r&   'test_no_watcher_polling_daemon_patternsrK    s/    &j1D  .dCJJ'ZZ vv||C(+#99   t#9  6     	   6   $:  	 $:     )1    
 dCNN+KK%2,,S1!4D55  45  v     I   v    6  I  6    *$++7     dCII&499cll3IIOOt+#'  dCHH%		A!S]]+66W$'+$6600AFF4E4Ef4M)-&9.<  %Hu$HHHuHHHHHHHHHHHHuHHH&HHHHHHH$Fu$FFFuFFFFFFFFFFFFuFFF&FFFFFFF!& &                "'    	N    r(   c                 0   t        d      } | d   }g }d}||v }|}|rd}||v }|}|sXt        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }d	d
|iz  }	|j                  |	       |rt        j                  dfd|f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }
dd|
iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            dx}x}x}x}x}}ddlm} d}|j                  }||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd
|iz  }	t        t        j                  |	            dx}x}}d |j                  D        }t        |      }| }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}}y)u  spec §4 — cokacdir --cron 템플릿은 contract *데이터* 이지 실행 아님.

    템플릿 문자열 존재는 spec §4 의무. 본 모듈이 그 문자열을 *실행*하는
    경로(subprocess/os.system 등)가 없음을 위 AST 테스트가 보증한다.
    anu-key-ref"callback_register_command_templatecokacdirz--cronr   )z%(py3)s in %(py5)stmpl)ri   ra   %(py7)src   )z%(py10)s in %(py12)s)rk   rt   z%(py14)spy14r   zassert %(py17)spy17Nr   )z/%(py1)s in %(py5)s
{%(py5)s = %(py3)s.__all__
}mr   rb   c              3  >   K   | ]  }|j                  d         yw)register_realN)rD  r   ns     r&   r   zGtest_spec_s4_contract_template_is_data_not_execution.<locals>.<genexpr>  s     DQ1<<0Ds   0assert not %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}r   r   )r   ru   rv   rz   rw   rx   ry   r   _format_boolopr{   r|   (utils.anu_delegation_completion_callback"anu_delegation_completion_callback__all__r   )contractrP  r   r   r   r   r   @py_assert11r   r   r   @py_format15@py_format16@py_format18rT  r   r   s                    r&   4test_spec_s4_contract_template_is_data_not_executionrc    s    2-@H89D2:2:2(2(d"22222:222:2222222222222222(d222(222222d222d222222222222228.;!));.);;;;.);;;.;;;;;;!;;;!;;;);;;;;;;D!))DDsDDDDDDDDDDDDsDDDsDDDDDDDDDDDDDDr(   c                 2   ddl m}  d | j                  D        }t        |      }| }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}}t        d      }t        |      }g }||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}|
|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}
}y)uR   모듈은 cron 등록 함수를 노출하지 않는다 (compute/build schema 만).r   Nc              3  <   K   | ]  }d |v xr
 d|v xr d|v  yw)registercallbackcommandNrH   rW  s     r&   r   z5test_no_real_cron_registration_api.<locals>.<genexpr>  s2       
q	CZ1_	C!1C	Cs   rY  r   r   rM  rR   r   r   r^  r   r[   r\   dispatch_py_untouchedTr]   r  rm   rn   rZ   callback_chat_id)z%(py1)s == %(py3)sr   rh   ri   assert %(py5)sra   )r[  r\  r]  r   rw   rx   ru   ry   rz   r{   r|   r   r   rv   r   )rT  r   r   r   r   r^  r   r   r   r   r   r   rJ  s                r&   "test_no_real_cron_registration_apirm    s	   8 s                            2-@H0:@b@:b@@@@:b@@@@@@0@@@0@@@@@@@@@@@@:@@@b@@@@@@@+,44,4444,444,4444444444&'?'+?????'+????'??????+????+????????r(   c                    d} t        |       }d}d}||z  }| |z   }d}d}||z  }||z   }	||	k(  }
|
sst        j                  d|
fd||	f      dt        j                         v st        j
                  t               rt        j                  t               ndd	t        j                         v st        j
                  |       rt        j                  |       nd	t        j                  |      d	t        j                         v st        j
                  |       rt        j                  |       nd	t        j                  |      t        j                  |      t        j                  |      t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}
x}x}x}x}x}x}x}}	d}t        | |      }
d}d}||z  }| |z   }d}d}||z  }||z   }|
|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	t        j                         v st        j
                  |       rt        j                  |       nd	t        j                  |      t        j                  |      t        j                  |      t        j                  |      d	z  }dd|iz  }t        t        j                  |            dx}x}
x}x}x}x}x}x}x}x}}y)uL   회장 §6 — fallback = dispatch_ts + ttl + 10m. 계산만, cron 등록 X.g    .A   i  
   <   rR   )zb%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == ((%(py5)s + (%(py7)s * %(py9)s)) + (%(py13)s * %(py15)s))r   rM   )rW   rh   ri   ra   rc   r   py13py15assert %(py19)spy19Nr   )task_ttl_hours)z{%(py5)s
{%(py5)s = %(py0)s(%(py1)s, task_ttl_hours=%(py3)s)
} == ((%(py7)s + (%(py9)s * %(py11)s)) + (%(py15)s * %(py17)s)))	rW   rh   ri   ra   rc   r   r   rs  rS  zassert %(py21)spy21)	r   ru   rv   rw   rx   ry   rz   r{   r|   )rM   r   r   r   @py_assert10r_  @py_assert12@py_assert14@py_assert16@py_assert17r   rb  @py_format20@py_assert13@py_assert18@py_assert19@py_format22s                    r&    test_compute_fallback_ttl_marginr    s   D*40M1MtM1t8MD8OMbM2Mb2gMOg4MM04MMMMM04MMMMMMM*MMM*MMMMMM4MMM4MMM0MMMMMMDMMMDMMM1MMMtMMMbMMM2MMMMMMMMM=>'Q?d((?"$"WW$?$	%  ?$     	(   	(     )-   )-   >?   	@                     #%        r(   c                 v   ddi} t        |       }g }||k7  }|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                  |      dz  }dd|iz  }t        t        j                  |            d x} x}x}}i } t        |       }g }||k7  }|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                  |      dz  }dd|iz  }t        t        j                  |            d x} x}x}}dd
i} t        |       }g }||k7  }|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                  |      dz  }dd|iz  }t        t        j                  |            d x} x}x}}y )Nro   wrong!=)z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} != %(py7)sr   )rW   rX   rY   rc   zassert %(py9)sr   r   xr   )r   ru   rv   rw   rx   ry   rz   r{   r|   r   r   )r   r   r   r   r   r   s         r&   test_schema_validation_negativer    s   '/&9@%&9:@b@:b@@@@:b@@@@@@%@@@%@@@&9@@@:@@@b@@@@@@@13:04::4::::4::::::0:::0::::::4::::::::::)13>'8>B>8B>>>>8B>>>>>>'>>>'>>>>>>8>>>B>>>>>>>r(   c                   | dz  }t        t        d      |t              }|j                  }t	        |      }g }||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}}|j                  S )uE   spec §3 계약을 만족하는 정상 anu_delegation_result_v1 dict.ztask-9100.callback-ack.jsonz	task-9100r   rP   rR   rf   r   rU   rg   rj   rk   N)r   rN   r'   r$   r   ru   rv   rw   rx   ry   rz   r{   r|   )	r   r   rU   r   r   r   r   r   r   s	            r&   _valid_result_fixturer    s    
2
2C
+;'.C '*&;&;B%&;<BB<BBBB<BBBBBB%BBB%BBBBBBcBBBcBBB&;BBB<BBBBBBBBBB   r(   c                   t        |       }d|d<   t        |      }g }||k7  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d      dz   d	|iz  }t        t        j                  |            d
x}}d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d
x}}y
)u   항목 1/4 — review_ref 가 status 문자열이면 validate() 가 거부.

    보강 전: validate() 가 shape 를 검사하지 않아 통과(RED).
    보강 후: marker path|null 이 아니므로 errors 반환(GREEN).
    z&post_result_review:PASS(advisory=True)r   r  z%(py0)s != %(py3)serrorsr.  uE   status 문자열 review_ref 가 거부되지 않음 (drift 미검출)r/  ra   Nc              3  $   K   | ]  }d |v  
 yw)r   NrH   r   es     r&   r   zBtest_negative_review_ref_status_string_rejected.<locals>.<genexpr>*  s     Cq-2Cr   r   r   r   r  r   ru   rv   rw   rx   ry   rz   r9  r{   r|   r   	r   dr  r   r   rJ  r   r   r   s	            r&   /test_negative_review_ref_status_string_rejectedr     s     	h'A(PA$%'*F`6R<```6R``````6```6```R``````````CFCC3CCCCCCCCC3CCC3CCCCCCCCCCCCCCr(   c                ~   | dz  }t        t        d      |t              }|j                  d   }g }d}||u }|}|sag }t	        |t
              }	|	}
|	rI|j                  }d} ||      }|}
|r/d}||v}|}
|r%d	}||v}|}
|r|j                  }d
} ||      }| }|}
|
}|s`t        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }|j                  |       |szddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  	      dz  }j                  |       |	rHddt        j                         v st        j                  |      rt        j                  |      ndt        j                        t        j                        t        j                        dz  }|j                  |       |rt        j                  dfd|f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }|j                  |       |r"t        j                  dfd|f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }|j                  |       |rd dt        j                         v st        j                  |      rt        j                  |      ndt        j                        t        j                        t        j                        d!z  }|j                  |       t        j                  |d"      i z  }d#d$|iz  } |j                  |        t        j                  |d%      i z  }!t        j                   d&|      d'z   d(|!iz  }"t#        t        j$                  |"            dx}x}x}x}x}
x}x}	x}x}x}x}x}x}x}x}x}x}}g }d}||u}|}|r t'        |      }#|#j(                  }$ |$       }%|%}|st        j                  d)|fd*||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }|j                  |       |rd+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  }&|j                  |&       t        j                  |d"      i z  }'d.d/|'iz  }(t#        t        j$                  |(            dx}x}x}x}x}#x}$}%|j                  })t+        |)      }g }*||*k(  }+|+s
t        j                  d0|+fd1||*f      d2t        j                         v st        j                  t*              rt        j                  t*              nd2d3t        j                         v st        j                  |      rt        j                  |      nd3t        j                  |)      t        j                  |      t        j                  |*      d4z  },d5d6|,iz  }-t#        t        j$                  |-            dx})x}x}+}*y)7u   항목 1/4 — collector 출력 review_ref 는 절대 status 문자열이 아니다.

    marker path (.json) 또는 None 만 허용. status 패턴 문자열 출현 시 실패.
    ztask-9101.callback-ack.jsonz	task-9101r   rP   r   Nz.json(=zpost_result_review:r]   )z%(py2)s is %(py5)sref)rX   ra   rQ  rc   z3%(py15)s
{%(py15)s = %(py11)s(%(py12)s, %(py13)s)
}r4  r   )r   rt   rr  rs  zI%(py23)s
{%(py23)s = %(py19)s
{%(py19)s = %(py17)s.endswith
}(%(py21)s)
})rS  ru  rw  py23rq   )z%(py26)s not in %(py28)s)py26py28z%(py30)spy30)z%(py33)s not in %(py35)s)py33py35z%(py37)spy37zOnot %(py45)s
{%(py45)s = %(py41)s
{%(py41)s = %(py39)s.startswith
}(%(py43)s)
})py39py41py43py45r   z%(py49)spy49r   u/   review_ref 가 marker path|null 계약 위반: z
>assert %(py52)spy52r   )z%(py2)s is not %(py5)sz`%(py16)s
{%(py16)s = %(py14)s
{%(py14)s = %(py12)s
{%(py12)s = %(py9)s(%(py10)s)
}.is_file
}()
}r   )r   rk   rt   rR  py16rt  ru  rR   rf   r   rU   rg   rj   rk   )r   rN   r'   r$   r4  r   endswithrD  ru   rv   rw   rx   ry   rz   r   rZ  r9  r{   r|   r   is_filer   ).r   r   rU   r  r   r   r   r   rx  rz  r   r  @py_assert20@py_assert22@py_assert25@py_assert27@py_assert32@py_assert34@py_assert40@py_assert42@py_assert44@py_assert46r   r   ra  @py_format24@py_format29@py_format31@py_format36@py_format38@py_format47@py_format48@py_format50@py_format51@py_format53r_  r~  @py_assert15@py_format17rb  r}  r   r   r   r   r   s.                                                 r&   9test_negative_collector_review_ref_is_marker_path_or_nullr  -  s   
 2
2C
+;'.C
 

 >
?CA$ A3$; A3AALLA A!A!A!A sNA 	A sN	A
 A
  5A
 45A
 65A
 6A A 0A/@A3$ A A ;A&A A )A(@  A A 8Ay  A A 8Ay  A A A ;A&A ;AA A ;A&A A )A(@ 	A A 8Ay 	A A ;A&A A )A(@ A A 8Ay A A ;A&A A )A(@ A A 8Ay A A 8Ay 	A A ;A&A ;A 	A ;A&A A )A(@	 A A 8Ay	 A A 8Ay	 A A 8Ay	 !A A 8Ay	 "A A ;A&A ;A	 "A 0A/@A sA A 8Ay A A ;A&A A )A(@ A A 8Ay A A A ;A&A ;AA 0A/@A s	A A 8Ay 	A A ;A&A A )A(@ 	A A 8Ay 	A A A ;A&A ;AA A ;A&A A )A(@ A A 8Ay A A 8Ay A A 8Ay  5A A 8Ay 6A A ;A&A ;AA 3A.A A A ;A&A ;AA 3A.A A 0A/@	8@A A A .A-@A A A A A A 3d23d?2tCy2y00202222223d22222232223222d2222222222t222t222222C222C222y222022222222222222222&)&;&;B%&;<BB<BBBB<BBBBBB%BBB%BBBBBBcBBBcBBB&;BBB<BBBBBBBBBBr(   c                   t        |       }d|d   d<   t        |      }g }||k7  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d      d	z   d
|iz  }t        t        j                  |            dx}}d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u   항목 2/4 — stale_distinction_evidence 미명세 key 는 거부.

    보강 전: validate() 가 nested key 화이트리스트를 모르므로 통과(RED).
    보강 후: 허용 key 집합 외 → errors(GREEN).
    Tr6   surprise_unspecified_keyr  r  r  r.  u=   미명세 stale key 가 거부되지 않음 (drift 미검출)r/  ra   Nc              3  $   K   | ]  }d |v  
 yw)r  NrH   r  s     r&   r   z?test_negative_unspecified_stale_key_rejected.<locals>.<genexpr>O  s     ?1)Q.?r   r   r   r   r  r  s	            r&   ,test_negative_unspecified_stale_key_rejectedr  E  s     	h'ABFA"#$>?'*FX6R<XXX6RXXXXXX6XXX6XXXRXXXXXXXXXX???3?????????3???3??????????????r(   c                  
 d}|D ]  
t        |       }|d   j                  
d       t        |      }g }||k7  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d
       d	z   d
|iz  }t        t        j                  |            dx}}
fd|D        }t        |      }|st        j                  d
 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}} y)u   항목 3/4 — spec §3 7 nested key 중 하나라도 누락 시 validate() 실패.

    보강 전 validate() 는 normal_callback_cron_id / ttl_expiry_ts_utc 를
    검사하지 않았다 → 누락을 통과(RED). 보강 후 누락 검출(GREEN).
    )r8   r9   r:   ttl_expiry_ts_utcr;   r<   r=   r6   Nr  r  r  r.  u   nested key 누락 미검출: r/  ra   c              3  &   K   | ]  }|v  
 y wr  rH   )r   r  drops     r&   r   zBtest_negative_missing_stale_nested_key_rejected.<locals>.<genexpr>f  s     -419-s   u   누락 key 'u&   ' 가 errors 에 명시되지 않음: z.
>assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}r   r   )r  popr   ru   rv   rw   rx   ry   rz   r9  r{   r|   r   )r   spec_nested_keysr  r  r   r   rJ  r   r   r   r  s             @r&   /test_negative_missing_stale_nested_key_rejectedr  R  sb    ! 
!(+	
&'++D$7+A.Cv|CCCvCCCCCCvCCCvCCCCCC<TFCCCCCCC-f- 	
s-- 	
- 	
  4& FvhO	
 	
	6	
 	
   	
 	
 		  	
 	
 		 . 	
 	
 		 . 	
 	
 	
 	
 	

r(   c                 	   ddl m} m} h d}t        |      }||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                  |      dt        j                         v st	        j                  |      rt	        j                  |      ndd	z  }d
d|iz  }t        t	        j                  |            dx}}t        |       }||k  }|s#t	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      nddt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      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h}
||
z  }||k(  }|s7t	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |       rt	        j                  |       ndt	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |
      dz  }dd|iz  }t        t	        j                  |            dx}x}x}
}y)u   항목 2 — 허용 key 집합이 모듈에 명시 정의되어 있어야 한다.

    spec §3 7 key + 운영 필요 키(evidence_collection_failed) 명시 등재.
    r   )'STALE_DISTINCTION_EVIDENCE_ALLOWED_KEYS$STALE_DISTINCTION_EVIDENCE_SPEC_KEYS>   r;   r:   r  r<   r=   r9   r8   rR   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)ssetr  spec7r  rb   rc   N)<=)z0%(py0)s <= %(py5)s
{%(py5)s = %(py2)s(%(py3)s)
}r  )rW   rX   ri   ra   r   r   )z%(py1)s in %(py3)srk  rl  ra   )z<%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == (%(py5)s | %(py7)s))rW   rh   ri   ra   rc   rj   rk   )r[  r  r  r  ru   rv   rw   rx   ry   rz   r{   r|   )r  r  r  r   r   r   r   r   r   rJ  r   r   r   r   s                 r&   /test_stale_evidence_allowed_key_set_is_explicitr  k  s   

E 34=4====4======3===3======3===3===4================?@@5@@@@@5@@@@@@@5@@@5@@@@@@C@@@C@@@@@@?@@@?@@@@@@@@@@@'R'+RRRRR'+RRRR'RRRRRR+RRRR+RRRRRRRR67 $D 5 D < 7 <    7 <                7    7    8      <A    <A   D       r(   c                D   t        |       }d|d<   t        |      }g }||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}}y)
uV   항목 1 — review_ref == null 은 spec §3 계약상 유효 (false-positive 방지).Nr   rR   r   r   r  r   r[   r\   )
r  r   ru   rv   rw   rx   ry   rz   r{   r|   )r   r  r   r   r   r   r   s          r&   &test_negative_review_ref_null_is_validr    s    h'A(,A$%%a(.B.(B....(B......%...%......a...a...(...B.......r(   __main__z-v)returnr   )r  r   )r  r   )r  rI   )O__doc__
__future__r   builtinsrw   _pytest.assertion.rewrite	assertionrewriteru   r  rs   sysr   pathlibr   r  __file__resolveparent	WORKSPACEr   pathremoveinsertutils.anu_codex_bounded_loopr   r[  r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r  r2  r'   r*   rN   r   r   r   r   r   r   r   r   r   r   r  r	  r  r  r  r  rK  rc  rm  r  r  r  r  r  r  r  r  r  __name__exitmainrH   r(   r&   <module>r     s  . #   
  
    N""$++2299	y>SXXHHOOC	N# 3y> " 0    ( AA)W) !BB*20H4@.&<I(	-E
N @*B
C 	D
7 :zE @?
!
DC0
@
2:/ zCHH[V[[(D)*+ r(   