
    jlE                     R   d Z ddlZddlmc mZ ddlZddl	Z	ddl
Z
ddlZddlmZ  ee      j                         j                   d   Z ee      ej&                  vr"ej&                  j)                  d ee             ddlZdedefdZ edd	        ed
d        edd      ZddlmZmZ  ee      j                         j                   d   dz  dz  Zd Zd Zej<                  j?                  dg d      d        Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d  Z*d! Z+d" Z,d# Z-y)$u_  Regression tests for callback lifecycle classifier **wiring** (task-2630, L4).

L3 가 classifier core(utils/callback_lifecycle_classifier.py)를 검증한다면, 본
파일은 그 core 를 executor completion contract 에 **실결선**한 경로
(dispatch.executor_completion_contract)를 검증한다.

회장 verbatim 필수 regression 10항 (memory/tasks/task-2630.md):
  1. task-2625 fixture → SELF_KEY_FIRED_NON_AUTHORITATIVE
  2. task-2628 fixture → FINISH_TASK_GIT_GATE_BLOCKED_BEFORE_CALLBACK + FOREIGN_DIRTY_BLOCKER
  3. task-2628+1 fixture → FALLBACK_COLLECTOR_APPLIED + ENVELOPE_PREPARED_NOT_FIRED
  4. UNKNOWN / INSUFFICIENT_EVIDENCE fixture
  5. 기존 callback contract 9 fields 유지
  6. fields 10~14 append 확인
  7. callback_lifecycle.json idempotent artifact 생성
  8. live workspace 의존 0
  9. foreign dirty 미접촉
  10. callback 재발사 0

규칙:
- 순수 함수 + 격리 tmp_path 만 (실 cron 0 · 실 발사 0 · subprocess 0 · live workspace 의존 0)
- frozen fixture 만 입력 (tests/fixtures/callback_lifecycle/) — fixture 수정/날조 0
- pytest 로 실행 가능
    N)Path   modnamerelpathc                    t         j                  j                  |       }|t        |dd      j	                  |      r|S t
        j                  j                  | t        |z        }g }d}||u}|}|r|j                  }d}	||	u}
|
}|slt        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!                  |       |rt        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  }|j!                  |       t        j"                  |d      i z  }dd|iz  }t%        t        j&                  |            dx}x}x}x}x}x}
}	t
        j                  j)                  |      }|t         j                  | <   |j                  j+                  |       |S )u   tests/dispatch 패키지 shadow 를 우회해 실 dispatch 모듈을 파일 경로로 로드.

    (기존 test_callback_runtime_enforcement_2626.py 와 동일 패턴.)
    N__file__ )is not)z%(py2)s is not %(py5)sspec)py2py5z%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16r   zassert %(py19)spy19)sysmodulesgetgetattrendswith	importlibutilspec_from_file_location_WORKTREE_ROOTloader
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprappend_format_boolopAssertionError_format_explanationmodule_from_specexec_module)r   r   existingr   @py_assert1@py_assert4@py_assert3@py_assert0@py_assert10@py_assert13@py_assert12@py_format6@py_format8@py_format15@py_format17@py_format18@py_format20mods                     K/home/jay/workspace/tests/regression/test_callback_lifecycle_wiring_2630.py
_load_realr:   '   sd   
 {{w'H*b A J J7 S>>11'>G;STD7t74t77474 777774t77777747774777t77777774777777777777777477777777777777
..
)
)$
/CCKKKKC J    z dispatch.callback_owner_enforcerz#dispatch/callback_owner_enforcer.pyz(dispatch.normal_fallback_callback_helperz+dispatch/normal_fallback_callback_helper.pyz%dispatch.executor_completion_contractz(dispatch/executor_completion_contract.py_contract_fieldsCALLBACK_KIND_NORMAL   fixturescallback_lifecyclec                     t         | z  }t        j                  |dz  j                  d            }t        j                  |dz  j                  d            }||fS )Nzevidence.jsonutf-8encodingzexpected.json)FIXTURE_ROOTjsonloads	read_text)fixture_dir_namebaseevidenceexpecteds       r9   _load_fixturerN   E   sZ    **Dzz4/1<<g<NOHzz4/1<<g<NOHXr;   c            	      .    t        dt        ddddd      S )uR   단일소스(_contract_fields)에서 실제 9-field callback contract dict 생성.ztask_id=task-2630 doneDEAD1234ENVELOPE_PREPARED_NOT_FIREDTr	   F)callback_promptkindcron_idstatusenvelope_onlyfallback_promptfallback_registeredr<    r;   r9   _real_nine_fieldsrZ   L   s$    0!,! r;   fixture_dir)	task-2625	task-2628task-2628_plus_1unknown_insufficientc           	      	   t        |       \  }}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
   }	t        |	      }|d
   }
t        |
      }||k(  }|s&t	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |	      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |
      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}	x}x}x}
}|d
   }	t        |	      }|d
   }
t        |
      }||k(  }|s&t	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |	      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |
      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}	x}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|v r|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y)uU   결선 경로(classify_completion_lifecycle → artifact)가 회장 매핑과 일치.task_iddelivery_outcome==z%(py1)s == %(py4)spy1py4assert %(py6)spy6Nnormal_callback_miss_causeroot_cause_tags)zP%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py10)s
{%(py10)s = %(py6)s(%(py8)s)
}set)py0r   rh   rj   py8py10assert %(py12)spy12lenevidence_completenessclassification)rN   ecc!build_callback_lifecycle_artifactr   r   r   r#   r&   r'   rm   r    r!   r"   rs   )r[   rL   rM   artifactr.   r-   @py_assert2@py_format5@py_format7r+   @py_assert7@py_assert9@py_assert5@py_format11@py_format13s                  r9   !test_wiring_path_matches_expectedr   ^   sB    '{3Hh44Y,hH &'G84F+GG'+GGGGG'+GGGG'GGG+GGGGGGGG01[X>Z5[[15[[[[[15[[[[1[[[5[[[[[[[[)*O3*+O8<M3NOs3N/OO+/OOOOO+/OOOOOOO3OOO3OOO*OOO+OOOOOOsOOOsOOO3NOOO/OOOOOOOO)*O3*+O8<M3NOs3N/OO+/OOOOO+/OOOOOOO3OOO3OOO*OOO+OOOOOOsOOOsOOO3NOOO/OOOOOOOO+,Q9P0QQ,0QQQQQ,0QQQQ,QQQ0QQQQQQQQ8#()GX6F-GG)-GGGGG)-GGGG)GGG-GGGGGGGG $r;   c                  J   t        d      \  } }t        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   }d
}||k7  }|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}}y	)u   regression 1 — task-2625: self-key 실발사 = incident(SELF_KEY_FIRED_NON_AUTHORITATIVE).

    SELF_KEY_FAIL_CLOSED_BEFORE_FIRE 와 분리 유지(ANCHOR-3 / 필수구현 9).
    r\   rk    SELF_KEY_FIRED_NON_AUTHORITATIVErc   re   rf   ri   rj   N SELF_KEY_FAIL_CLOSED_BEFORE_FIRE!=z%(py1)s != %(py4)sru   incidentrN   rv   classify_completion_lifecycler   r   r#   r&   r'   rL   _resr.   r-   ry   rz   r{   s           r9   2test_regression_1_self_key_fired_non_authoritativer   u   s#   
  ,KHa

+
+H
5C+,R0RR,0RRRRR,0RRRR,RRR0RRRRRRRR+,R0RR,0RRRRR,0RRRR,RRR0RRRRRRRR .J. J.... J... ...J.......r;   c                  H   t        d      \  } }t        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
}|d   }||v }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|d   }d}||k7  }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)uO   regression 2 — task-2628: GIT-GATE 차단 + FOREIGN_DIRTY_BLOCKER root cause.r]   rk   ,FINISH_TASK_GIT_GATE_BLOCKED_BEFORE_CALLBACKrc   re   rf   ri   rj   NFOREIGN_DIRTY_BLOCKERrl   in)z%(py1)s in %(py4)sCALLBACK_DELIVERY_GAPr   r   r   r   s           r9   5test_regression_2_git_gate_blocked_with_foreign_dirtyr      s$   ,KHa

+
+H
5C+,^0^^,0^^^^^,0^^^^,^^^0^^^^^^^^"<c*;&<<"&<<<<<"&<<<<"<<<&<<<<<<<<+,G0GG,0GGGGG,0GGGG,GGG0GGGGGGGGr;   c                  J   t        d      \  } }t        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
   }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	)uW   regression 3 — task-2628+1: FALLBACK_COLLECTOR_APPLIED + ENVELOPE_PREPARED_NOT_FIRED.r^   rb   FALLBACK_COLLECTOR_APPLIEDrc   re   rf   ri   rj   Nrk   rQ   r   r   s           r9   ,test_regression_3_fallback_collector_appliedr      s     23KHa

+
+H
5C!"B&BB"&BBBBB"&BBBB"BBB&BBBBBBBB+,M0MM,0MMMMM,0MMMM,MMM0MMMMMMMMr;   c                  J   t        d      \  } }t        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
   }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   }g }||k(  }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)u^   regression 4 — 증거 결핍 → UNKNOWN/INSUFFICIENT_EVIDENCE (추정 0 · 필수구현 7).r_   rb   UNKNOWN_INSUFFICIENT_EVIDENCErc   re   rf   ri   rj   Nrk   rt   MISSINGrl   r   r   s           r9   8test_regression_4_unknown_insufficient_evidence_no_guessr      su    67KHa

+
+H
5C!"E&EE"&EEEEE"&EEEE"EEE&EEEEEEEE+,O0OO,0OOOOO,0OOOO,OOO0OOOOOOOO&'494'94444'9444'44494444444 !'R'!R''''!R'''!'''R'''''''r;   c                  
   t        d      \  } }t               }|j                  } |       }t        |      }t        j
                  }||k(  }|sgt        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }dd	|iz  }	t        t        j                  |	            d x}x}x}x}}t        j                  ||       }
t        j
                  D ]T  }||
v }|st        j                  d
|fd||
f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |
      rt        j                  |
      nddz  }dd|iz  }t        t        j                  |            d }|
|   }||   }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}W |j                  } |       }t        |      }t        j
                  }t        |      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      d	z  }dd|iz  }t        t        j                  |            d x}x}x}x}x}}y )Nr^   rc   )z%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.keys
}()
})
} == %(py11)s
{%(py11)s = %(py9)s.CALLBACK_CONTRACT_9_FIELDS
}tupleninerv   )rn   rg   py3r   r   r   r   assert %(py13)spy13r   z%(py0)s in %(py2)skmergedrn   r   assert %(py4)srh   re   rf   ri   rj   )z%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.keys
}()
})
} == %(py14)s
{%(py14)s = %(py9)s(%(py12)s
{%(py12)s = %(py10)s.CALLBACK_CONTRACT_9_FIELDS
})
}rm   )	rn   rg   r   r   r   r   rp   rr   r   zassert %(py16)sr   )rN   rZ   keysr   rv   CALLBACK_CONTRACT_9_FIELDSr   r   r    r!   r"   r#   r&   r'   append_lifecycle_fieldsrm   )rL   r   r   ry   r,   @py_assert6r/   @py_assert8@py_format12@py_format14r   r   r+   @py_format3rz   r.   r-   r{   @py_assert11r0   r4   r5   s                         r9   'test_regression_5_nine_fields_preservedr      s    23KHaD??5?!?!??!?????!???????5???5??????????????????????????????!????????((x8F++ $F{qFqqFFay#DG#yG####yG###y###G#######$ yyBy{B3{B3#A#ABs#ABBBBBBBBBBBBBB3BBB3BBBBBBtBBBtBBByBBB{BBBBBBBBBsBBBsBBBBBB3BBB3BBB#ABBBBBBBBBBBBr;   c                      t        d      \  } }ddi}t        j                  t              5  t        j                  ||        ddd       y# 1 sw Y   yxY w)u[   9-field 키와 충돌하는 lifecycle field 가 있으면 ValueError (덮어쓰기 금지).r\   rb   SHOULD_NOT_BE_OVERWRITTENN)rN   pytestraises
ValueErrorrv   r   )rL   r   poisoneds      r9   1test_regression_5b_append_only_collision_rejectedr      sL    ,KHa"$?@H	z	" 8##Hh78 8 8s   AAc                  2
   t        d      \  } }t               }t        j                  ||       }t        j                  D ]  }||v }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d } t        |      }d
}	t        j                  }
t        |
      }|	|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                  t              rt        j                  t              nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}x}	x}
x}}|d   }t        |t               }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dz  }t        t        j                  |            d x}}|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}}y )Nr]   r   r   r   r   r   u   field 10~14 누락: 
>assert %(py4)srh   	   rc   )z%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == (%(py6)s + %(py12)s
{%(py12)s = %(py7)s(%(py10)s
{%(py10)s = %(py8)s.LIFECYCLE_RESULT_FIELDS
})
})rs   rv   )rn   rg   r   rj   r   ro   rp   rr   zassert %(py15)spy15lifecycle_state_evidencez5assert %(py5)s
{%(py5)s = %(py0)s(%(py2)s, %(py3)s)
}
isinstancedict)rn   r   r   r   classified_byzauto-classifierre   rf   ri   rj   rb   )rN   rZ   rv   r   LIFECYCLE_RESULT_FIELDSr   r   r    r!   r"   r#   _format_assertmsgr&   r'   rs   r   r   )rL   rM   r   r   r   r+   r   rz   ry   r~   r}   r   r0   r,   r   @py_format16r2   r.   r-   r{   s                       r9   *test_regression_6_fields_10_to_14_appendedr      s   &{3HhD((x8F(( 7F{666qF666666q666q666666F666F666621#66666667 v;>!>#"="=>c"=>>!>>>;>>>>>;>>>>>>>3>>>3>>>>>>v>>>v>>>;>>>!>>>>>>c>>>c>>>>>>#>>>#>>>"=>>>>>>>>>>>>78?:8$????????:???:???8??????$???$??????????/"7&77"&77777"&7777"777&77777777$%E2D)EE%)EEEEE%)EEEE%EEE)EEEEEEEEr;   c            	         t        d      \  } }t        j                  d|       }|d   }|j                  } |       }t	        |      }h 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                  |      t        j                  |      d	z  }	d
d|	iz  }
t        t        j                  |
            dx}x}x}x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }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)uT   필수구현 5 — gate PASS / notification sent / collector received 분리 기록.r^   task-2628+1callback_stage_separation>   notification_sentcallback_gate_passcollector_receivedrc   )zb%(py7)s
{%(py7)s = %(py0)s(%(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py1)s.keys
}()
})
} == %(py10)srm   sep)rn   rg   r   r   r   rp   rq   rr   Nr   T)is)z%(py1)s is %(py4)srf   ri   rj   r   Fr   )rN   rv   rw   r   rm   r   r   r    r!   r"   r#   r&   r'   )rL   r   rx   r   ry   r,   r   r}   r   r   r   r.   r-   rz   r{   s                  r9   ,test_regression_6b_stage_separation_recordedr      s    23KHa44]HMH
.
/Cxx_xz_3z?___?_____?_______3___3______s___s___x___z___?___________#$,,$,,,,$,,,$,,,,,,,,,,"#,u,#u,,,,#u,,,#,,,u,,,,,,,#$,,$,,,,$,,,$,,,,,,,,,,r;   c                     t        d      \  } }t        j                  d|       }|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd	|iz  }t        t	        j                  |            d
x}x}}|d   }t        j                  }||k(  }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd	|iz  }t        t	        j                  |            d
x}x}}t        j                  dd      }|j                  }	d}
 |	|
      }|sddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |	      t	        j                  |
      t	        j                  |      dz  }t        t	        j                  |            d
x}	x}
}d}||v}|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd|iz  }t        t	        j                  |            d
x}}d}||v}|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd|iz  }t        t	        j                  |            d
x}}y
)u\   필수구현 6 — lifecycle classifier artifact 가 fallback collector artifact 와 구분.r^   r   artifact_kindrc   )zH%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CALLBACK_LIFECYCLE_ARTIFACT_KIND
}rv   )rg   r   r   assert %(py7)sr   Nschema)zJ%(py1)s == %(py5)s
{%(py5)s = %(py3)s.CALLBACK_LIFECYCLE_ARTIFACT_SCHEMA
}z/tmp/anywherez.callback_lifecycle.jsonzJassert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.endswith
}(%(py4)s)
}path)rn   r   rh   rj   zindependent-anu-collector)not in)z%(py1)s not in %(py3)s)rg   r   assert %(py5)sr   fallback_collector_applied)rN   rv   rw    CALLBACK_LIFECYCLE_ARTIFACT_KINDr   r   r#   r    r!   r"   r&   r'   "CALLBACK_LIFECYCLE_ARTIFACT_SCHEMA callback_lifecycle_artifact_pathr   )rL   r   rx   r.   r,   ry   r2   r3   r   r+   r-   r~   r{   @py_format4s                 r9   2test_regression_6c_fallback_artifact_distinguishedr      sP    23KHa44]HMHO$L(L(LL$(LLLLL$(LLLL$LLLLLLLLLLLL(LLLLLLLLHG!G!GG!GGGGG!GGGGGGGGGGGGGGGG!GGGGGGGG//OD==434=34444444444444444=44434444444444&2&d2222&d222&222222d222d2222222'3't3333't333'333333t333t3333333r;   c                 Z
   t        d      \  }}| dz  dz  }t        j                  d|t        |            }t	        |      j                         }t        j                  j                  |      }t        j                  d|t        |            }t	        |      j                         }t        j                  j                  |      }	||k(  }
|
st        j                  d|
fd||f      dt        j                         v st        j                  |      rt        j                  |      ndd	t        j                         v st        j                  |      rt        j                  |      nd	d
z  }dd|iz  }t        t        j                   |            d }
||k(  }
|
st        j                  d|
fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      ndd
z  }t        j"                  d      dz   d|iz  }t        t        j                   |            d }
||	k(  }
|
st        j                  d|
fd||	f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |	      rt        j                  |	      ndd
z  }t        j"                  d      dz   d|iz  }t        t        j                   |            d }
t        j$                  }
 |
|      }dg}||k(  }|s
t        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t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                   |            d x}
x}x}}t'        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 ) Nr^   memoryeventsr   
events_dirrc   )z%(py0)s == %(py2)sp1p2r   r   rh   b1b2u?   동일 입력 2회 → byte-identical 이어야 함(idempotent)r   m1m2u2   동일 내용이면 재기록 금지(mtime 보존)z#task-2628+1.callback_lifecycle.json)zM%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.listdir
}(%(py3)s)
} == %(py8)sosr   )rn   r   r   r   ro   zassert %(py10)srp   ra   re   rf   ri   rj   )rN   rv   !write_callback_lifecycle_artifactstrr   
read_bytesr   r   getmtimer   r   r    r!   r"   r#   r&   r'   r   listdirrG   rH   )tmp_pathrL   r   r   r   r   r   r   r   r   r+   r   rz   r,   r|   r   @py_format9r   parsedr.   r-   ry   r{   s                          r9   %test_regression_7_artifact_idempotentr      s    23KHaH$x/J		.	.xC
O 
/ 
B 
b			B			"	B		.	.xC
O 
/ 
B 
b			B			"	B8OOO2OOOOOO2OOO2OOOOOOOOOOOOOOOO8VVV2VVVVVV2VVV2VVVVVVVVVVVVVVVVVVVV8III2IIIIII2III2IIIIIIIIIIIIIIIIIIII::L:j!L&K%LL!%LLLLL!%LLLLLLL2LLL2LLL:LLLLLLjLLLjLLL!LLL%LLLLLLLLZZ^F)-------------------r;   c           	         |j                  dt        |              t        j                         }d}| |z  }d}||z  }t        |      }||k(  }|sKt	        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                  |      t	        j                  |      t	        j                  |      d	z  }	d
d|	iz  }
t        t	        j                  |
            dx}x}x}x}x}}t        d      \  }}t        j                  |      }|d   }|s8ddt	        j                  |      iz  }t        t	        j                  |            d}t        j                  d|      }t        |       }||v }|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        |      }|j                   } |       }|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                  |      t	        j                  |      dz  }t        t	        j                  |            dx}x}}y)uR   WORKSPACE_ROOT override 로 events dir 가 격리 경로로 해석(live 의존 0).WORKSPACE_ROOTr   r   rc   )zJ%(py0)s == %(py11)s
{%(py11)s = %(py2)s(((%(py3)s / %(py5)s) / %(py8)s))
}r   r   r   )rn   r   r   r   ro   r   r   r   Nr\   rb   zassert %(py1)srg   r   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} in %(py5)sp)rn   rg   r   r   r   r   z_assert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.exists
}()
}r   )rn   rg   r   r   r   )setenvr   rv   default_events_dirr   r   r    r!   r"   r#   r&   r'   rN   r   r   r   exists)r   monkeypatchr   r,   r   r|   r}   r/   r+   r   r   rL   r   r   r.   @py_format2r   ry   r2   r3   s                       r9   .test_regression_8_no_live_workspace_dependencyr     s   'X7'')J(0<X0<8<08;<;<<:<<<<<:<<<<<<<:<<<:<<<<<<<<<<<<<<<X<<<X<<<<<<8<<<<<<<<<<<<,KHa

+
+H
5C!""""""""""""--k8DAx==A=A33xx=AA77>>>447>r;   c           
         | dz  dz  }|j                  d       ddd}|j                         D ]  \  }}||z  j                  |d	        t        d
      \  }}t        j                  d
|t        |             |j                         D ]w  \  }}||z  }|j                  }d}	 ||		      }
|
|k(  }|sCt        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t        j                  |      t        j                  |	      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}x}x}	x}
}z t!        t#        j$                  |            t!        |j'                               z
  }dh}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)uS   writer 는 lifecycle artifact 1개만 만들고, foreign dirty 파일은 미접촉.r   r   T)parentszORIGINAL-DO-NOT-TOUCHzORIGINAL-SPEC)zutils__replacement_pr_runner.pyzanu-system-spec.mdrC   rD   r]   r   rc   )ze%(py8)s
{%(py8)s = %(py4)s
{%(py4)s = (%(py0)s / %(py1)s).read_text
}(encoding=%(py6)s)
} == %(py10)sr   namecontent)rn   rg   rh   rj   ro   rp   rq   rr   Nz!task-2628.callback_lifecycle.jsonz%(py0)s == %(py3)screatedrn   r   r   r   )mkdiritems
write_textrN   rv   r   r   rI   r   r   r    r!   r"   r#   r&   r'   rm   r   r   r   )r   r   	sentinelsr   r   rL   r   ry   r-   r~   r|   r}   r   r   r   r+   r   r2   s                     r9   )test_regression_9_foreign_dirty_untouchedr    s   H$x/JT" ,C-I #* Bg	d	&&w&AB  ,KHa))X#j/ * 
 #* JgT!I!,,IgI,g>I>'IIII>'IIIIII
III
IIIIIITIIITIII,IIIgIII>IIIIII'III'IIIIIIIIJ "**Z()C	0@,AAG:;;7;;;;;7;;;;;;;7;;;7;;;;;;;;;;;r;   c                    g fd}fd}ddl }|j                  |d|d       |j                  |d|d       |j                  |d	|d       |j                  t        d
|d       t        d      \  }}t	               }t
        j                  ||       t
        j                  d|       t
        j                  d|t        | dz               g }|k(  }	|	st        j                  d|	fd|f      dt        j                         v st        j                        rt        j                        ndt        j                  |      dz  }
t        j                   d       dz   d|
iz  }t#        t        j$                  |            dx}	}dD ](  }t'        t
        |      }| }|sddt        j                         v st        j                  t&              rt        j                  t&              nddt        j                         v st        j                  t
              rt        j                  t
              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t#        t        j$                  |            dx}}+ y)uT   전체 결선 경로가 subprocess/os.system 을 단 한 번도 호출하지 않음.c                  B    j                  d| |f       t        d      )N
subprocessu=   subprocess 호출 발생 — callback 재발사 금지 위반r$   r&   ar   callss     r9   _boomz4test_regression_10_no_callback_refire.<locals>._boom:  s"    lAq)*\]]r;   c                  B    j                  d| |f       t        d      )Nz	os.systemu<   os.system 호출 발생 — callback 재발사 금지 위반r  r	  s     r9   _boom_systemz;test_regression_10_no_callback_refire.<locals>._boom_system>  s"    k1a()[\\r;   r   NrunT)raisingPopencallsystemr\   evr   rc   r   r  r   u.   발사/subprocess 호출 0 이어야 함, got z
>assert %(py5)sr   )fire_callbackregister_cronremove_cronsend_callbackz9assert not %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}hasattrrv   	forbidden)rn   rg   r   rh   )r  setattrr   rN   rZ   rv   r   rw   r   r   r   r   r    r!   r"   r#   r   r&   r'   r  )r   r   r  r  r  rL   r   r   ry   r+   r   r2   r  r-   r~   r  s                  @r9   %test_regression_10_no_callback_refirer  6  s   E^] 
E5$?
GUDA
FE4@HlDA,KHaDh/))+x@))X#ho*> *  P5B;PPP5BPPPPPP5PPP5PPPBPPPHPPPPPPPW +	3	***********7***7******3***3******	***	**********+r;   ).__doc__builtinsr    _pytest.assertion.rewrite	assertionrewriter   importlib.utilr   rG   r   r   pathlibr   r   resolver   r   r   r   insertr   r:   rv   (dispatch.normal_fallback_callback_helperr=   r>   rF   rN   rZ   markparametrizer   r   r   r   r   r   r   r   r   r   r   r   r  r  rY   r;   r9   <module>r)     sO  0     	 
  h'')11!4~chh&HHOOAs>*+  c " -/T U 
57d e8:de H~%%'//2Z?BVV
$  ) HH"	/HN(C8F 	-
4".<&<:+r;   