
    tYjkQ                       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mZ ddlmZ ddlZ ed      Zedz  Zedz  Zed	z  Zdd
Zd Z G d d      ZddZddZddZdd	 	 	 	 	 	 	 	 	 ddZdZdZdZd Z d Z!d Z"d Z#d Z$y)u  task-2708 P2-A 회귀 테스트 RS-1~5.

아르고스 (dev1 QA/테스터) — CHAIR-AUTH-TASK-2708-P2A-CALLBACK-BEFORE-FAILFAST-PREREGISTRATION-260529

대상: scripts/harness/v36/callback_preregistration.py (헬퍼 코드 수정 0)
전략:
  - importlib.util.spec_from_file_location 으로 헬퍼/dispatch 직접 파일 로드
    (패키지 시스템 shadow 문제 회피: tests/dispatch/__init__.py 가 존재)
  - dispatch.normal_fallback_callback_helper 를 sys.modules 에 미리 주입 →
    exec_module 내 'import dispatch.normal_fallback_callback_helper as _cb_helper' 가
    sys.modules 캐시 히트로 성공
  - monkeypatch 로 prereg._cb_helper.launch_callback 을 mock (실제 cron 등록 회피)
  - tmp_path 로 events_dir / envelope 완전 격리
    )annotationsN)Path)Listz/home/jay/workspacez/scripts/harness/v36/callback_preregistration.pyz+dispatch/normal_fallback_callback_helper.pyzdispatch/__init__.pyc                 F
   t         j                  j                  d      } | t        | dd      t	        t
              k(  ryt	        t              }|t         j                  vr t         j                  j                  d|       t         j                  j                  d      }|t        |dd      t	        t              k7  r@t        j                  j                  dt        t	        t        dz        g      }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                  j1                  |      }t	        t        dz        g|_        d|_        |t         j                  d<   |j                  j7                  |       t        j                  j                  dt
              }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                  j1                  |      }d|_        |t         j                  d<   |j                  j7                  |       t9        |d|       y)u  dispatch.normal_fallback_callback_helper 를 sys.modules 에 주입.

    tests/dispatch/__init__.py 가 tests/ 하위에 존재하여 pytest 패키지 import
    로 올바른 dispatch 모듈을 찾지 못하는 문제를 우회한다.
    importlib.util.spec_from_file_location 으로 파일 경로에서 직접 로드하여
    sys.modules 에 올바른 모듈을 등록한다.
    z(dispatch.normal_fallback_callback_helperN__file__ r   dispatch)submodule_search_locationsis notz%(py2)s is not %(py5)sspec_dpy2py5%(py7)spy7z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)spy9py11py14%(py16)spy16assert %(py19)spy19spec_hnormal_fallback_callback_helper)sysmodulesgetgetattrstr_CB_HELPER_PATH
_WORKSPACEpathinsert_DISPATCH_INIT_PATH	importlibutilspec_from_file_locationloader
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprappend_format_boolopAssertionError_format_explanationmodule_from_spec__path____package__exec_modulesetattr)existingwsdispatch_pkgr   @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_format20r   cb_helper_mods                      F/home/jay/workspace/tests/harness/test_p2a_callback_preregistration.py_ensure_dispatch_in_sysmodulesrN   !   s+    {{IJH*b ASEY Y 
ZB	2 ;;??:.Lw|ZDL_H``77+(+J,C(D'E 8 
 	@T?vT!?fmm?4?m4&?????vT??????v???v???T???????m4??????f???f???m???4?????????????? ~~66v>!$Z*%<!= >#- ".J!!,/ ^^332F <;6;&--;t;-t";;;;;6;;;;;;6;;;6;;;;;;;;;;-t;;;;;;&;;;&;;;-;;;t;;;;;;;;;;;;;;NN33F;M *M>KCKK:;
MMm,L;]K    c                 v   t                t        j                  j                  dd       t        j
                  j                  dt              } 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                  d<   | j                  j)                  |       |S )u  callback_preregistration 모듈을 매 테스트 함수마다 깨끗하게 로드.

    _ensure_dispatch_in_sysmodules() 호출로 dispatch.normal_fallback_callback_helper
    가 sys.modules 에 올바르게 등록된 후 exec_module 을 실행한다.
    #callback_preregistration_under_testNr   r   specr   r   r   r   r   r   r   r   r   r   )rN   r   r    popr)   r*   r+   _HELPER_PATHr,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r:   )rR   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   mods                  rM   _load_preregrV   Q   sM    #$ KKOO94@>>11-|D 8t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
..
)
)$
/C9<CKK56KKC JrO   c                  4    e Zd ZdZdddZedd       Zd	dZy)
_FakeDecisionu?   LaunchDecision 의 가벼운 mock (ok/verdict/reasons/to_json).Nc                6    || _         || _        |xs g | _        y N)_okverdictreasons)selfokr\   r]   s       rM   __init__z_FakeDecision.__init__k   s    }"rO   c                    | j                   S rZ   )r[   r^   s    rM   r_   z_FakeDecision.okp   s    xxrO   c                4    | j                   | j                  dS )N)r\   r_   )r\   r[   rb   s    rM   to_jsonz_FakeDecision.to_jsont   s    <<txx88rO   rZ   )r_   boolr\   r#   r]   zList[str] | None)returnre   )rf   dict)__name__
__module____qualname____doc__r`   propertyr_   rd    rO   rM   rX   rX   h   s#    I%
  9rO   rX   c                     t        dd      S )NTPASS)r_   r\   rX   rm   rO   rM   _pass_decisionrq   x   s    D&11rO   c                      t        dddg      S )NFFAIL_CLOSEDzself-key detected)r_   r\   r]   rp   rm   rO   rM   _fail_closed_decisionrt   |   s    E=CVBWXXrO   c                h    | | dz  }|j                  t        j                  |dd      d       |S )u/   dummy envelope 파일 생성 후 경로 반환.z.envelope.jsonnormal)task_idkindzutf-8)encoding)
write_textjsondumps)tmp_pathrw   ps      rM   _make_enveloper      s6    gYn--ALLBCgLVHrO   )	workspacec               J    dd|d|d|d|d|d|d|d	|g}	| j                  |	      S )
u+   prereg.main() 을 argv 리스트로 호출.launchz	--task-idz--kindz--owner-keyz	--chat-idz--executor-keyz--envelope-pathz--events-dirz--workspace)main)
preregrw   rx   	owner_keyexecutor_keychat_idenvelope_path
events_dirr   argvs
             rM   _invoker      sG    
 	W$yW,=
y
D ;;trO   c119085addb0f8b7zexecutor-self-key-other
6937032012c                   t        d      }t        j                  |j                               }|d   }t	               }g fd}|j                  |j                  d|       | dz  }|j                          t        | |      }t        |||d   |d   |d   |d	   t        |      t        |      
      }	d}
|	|
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z  }|j(                  } |       }|st        j"                  d|       dz   dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }t%        t        j&                  |            dx}}t        j                  |j                               }|d   }d}||k(  }
|
st        j                  d|
fd||f      t        j                   |      t        j                   |      dz  }t        j"                  d|d          dz   d|iz  }t%        t        j&                  |            dx}x}
}|d    }d!}||u }
|
st        j                  d"|
fd#||f      t        j                   |      t        j                   |      dz  }t        j"                  d$      dz   d|iz  }t%        t        j&                  |            dx}x}
}|| d%z  }|j(                  } |       }|st        j"                  d&|       dz   d't        j                         v st        j                  |      rt        j                   |      nd't        j                   |      t        j                   |      dz  }t%        t        j&                  |            dx}}t+              }
d(}|
|k(  }|st        j                  d|fd)|
|f      d*t        j                         v st        j                  t*              rt        j                   t*              nd*d+t        j                         v st        j                        rt        j                         nd+t        j                   |
      t        j                   |      d,z  }t        j"                  d-t+                     d.z   d/|iz  }t%        t        j&                  |            dx}
x}}y)0u.  RS-1: envelope 존재 + ANU owner → pre-registration PASS.

    검증:
      - exit 0
      - {task_id}.callback-prereg-launch.json 존재
      - 마커 status == "ANU_OWNED_READY"
      - lock 파일 존재 ({task_id}.callback-prereg-lock)
      - launch_callback 이 정확히 1회 호출됨
    zH/home/jay/workspace/tests/fixtures/p2a/task-2707-tdd-check-failfast.jsonrw   c                 :    j                  d       t               S Ncalledr3   rq   kwargscall_logs    rM   fake_launch_callbackzGtest_rs1_failfast_path_registers_callback.<locals>.fake_launch_callback       !rO   launch_callbackeventsrx   r   r   r   rw   rx   r   r   r   r   r   r   ==z%(py0)s == %(py3)srcpy0py3z!RS-1: exit code should be 0, got 
>assert %(py5)sr   N.callback-prereg-launch.jsonzRS-1: launch marker not found: C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}launch_markerr   r   py4statusANU_OWNED_READYz%(py1)s == %(py4)spy1r   z+RS-1: expected status ANU_OWNED_READY, got 
>assert %(py6)spy6r   T)is)z%(py1)s is %(py4)sz RS-1: prereg flag should be True.callback-prereg-lockzRS-1: lock file not found: lock   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr   r   r   r   r   z9RS-1: launch_callback should be called exactly once, got 
>assert %(py8)spy8r   r{   loads	read_textrV   r;   
_cb_helpermkdirr   r   r#   r-   r.   r/   r0   r1   r2   _format_assertmsgr5   r6   existsr   )r}   monkeypatchfixture_pathfixturerw   r   r   r   enveloper   @py_assert2r?   @py_format4rF   r   rA   @py_format5marker_datarB   @py_format7r   @py_assert5r@   @py_format9r   s                           @rM   )test_rs1_failfast_path_registers_callbackr      s    bcLjj//12Gi G^FH  ))+<>RSH$Jh0H	V_+&^,	"(mz?	
B <27<<<2<<<<<<2<<<2<<<<<<7t<<<<<<<G9,H!IIMT!T!TT%D]O#TTTTTTT=TTT=TTTTTT!TTTTTT**]4467Kx  $5  $55   $5    !    %6    6k(6K5LM     x LDL D(LLL DLLL LLLDLLL*LLLLLLLL7)#899D;;>;=>=>>7v>>>>>>>4>>>4>>>;>>>=>>>>>>x=jAj=Ajjj=Ajjjjjj3jjj3jjjjjjxjjjxjjj=jjjAjjj!Z[^_g[hZijjjjjjjjrO   c                   t        d      }t        j                  |j                               }|d   }t	               }g fd}|j                  |j                  d|       | dz  }|j                          t        | |      }t        |||d   |d   |d   |d	   t        |      t        |      
      }	d}
|	|
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z  }|j(                  } |       }|st        j"                  d|       dz   dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }t%        t        j&                  |            dx}}t        j                  |j                               }|d   }d}||k(  }
|
st        j                  d|
fd||f      t        j                   |      t        j                   |      dz  }t        j"                  d|d          dz   d|iz  }t%        t        j&                  |            dx}x}
}|d   }d }||k(  }
|
st        j                  d|
fd||f      t        j                   |      t        j                   |      dz  }t        j"                  d!      dz   d|iz  }t%        t        j&                  |            dx}x}
}|| d"z  }|j(                  } |       }|st        j"                  d#|       dz   d$t        j                         v st        j                  |      rt        j                   |      nd$t        j                   |      t        j                   |      dz  }t%        t        j&                  |            dx}}t+              }
d%}|
|k(  }|st        j                  d|fd&|
|f      d't        j                         v st        j                  t*              rt        j                   t*              nd'd(t        j                         v st        j                        rt        j                         nd(t        j                   |
      t        j                   |      d)z  }t        j"                  d*t+                     d+z   d,|iz  }t%        t        j&                  |            dx}
x}}y)-uH  RS-2: fallback kind, envelope 존재 + ANU owner → PASS.

    scope_guard fail 이 발생해도 fail-fast 이전 fallback pre-reg 가 동작함을 검증.
    검증:
      - {task_id}.callback-fallback-launch.json 존재
      - status == "ANU_OWNED_READY"
      - fallback lock ({task_id}.callback-fallback-lock) 존재
    zD/home/jay/workspace/tests/fixtures/p2a/scope-guard-violation-35.jsonrw   c                 :    j                  d       t               S r   r   r   s    rM   r   zEtest_rs2_scope_guard_failfast_registers.<locals>.fake_launch_callback   r   rO   r   r   rx   r   r   r   r   r   r   r   r   r   z!RS-2: exit code should be 0, got r   r   N.callback-fallback-launch.jsonz(RS-2: fallback launch marker not found: r   fallback_markerr   r   r   r   r   z+RS-2: expected status ANU_OWNED_READY, got r   r   fallbackzRS-2: kind should be fallback.callback-fallback-lockzRS-2: fallback lock not found: fallback_lockr   r   r   r   r   z1RS-2: launch_callback should be called once, got r   r   r   )r}   r   r   r   rw   r   r   r   r   r   r   r?   r   rF   r   rA   r   r   rB   r   r   r   r@   r   r   s                           @rM   'test_rs2_scope_guard_failfast_registersr      s    ^_Ljj//12Gi G^FH  ))+<>RSH$Jh0H	V_+&^,	"(mz?	
B <27<<<2<<<<<<2<<<2<<<<<<7t<<<<<<< gY.L#MMO!!a!#a#aa'OP_O`%aaaaaaa?aaa?aaa!aaa#aaaaaa**_6689Kx  $5  $55   $5    !    %6    6k(6K5LM     vN*N*,NNN*NNNNNN*NNN0MNNNNNNNG9,C!DDMT!T!TT%D]O#TTTTTTT=TTT=TTTTTT!TTTTTTx=bAb=Abbb=Abbbbbb3bbb3bbbbbbxbbbxbbb=bbbAbbb!RSVW_S`RabbbbbbbbrO   c                P   t        d      }t        j                  |j                               }|d   }t	               }g fd}|j                  |j                  d|       | dz  }|j                          t        | dz        }t        ||dt        t        t        |t        |            }	d	}
|	|
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z  }|j,                  } |       }| }|st        j&                  d      dz   dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }t)        t        j*                  |            dx}x}}t/              }
d	}|
|k(  }|st        j                  d
|fd|
|f      dt        j                          v st        j"                  t.              rt        j$                  t.              nddt        j                          v st        j"                        rt        j$                        ndt        j$                  |
      t        j$                  |      dz  }t        j&                  d      dz   d|iz  }t)        t        j*                  |            dx}
x}}| dz  }|j                          t1        | |      }t        ||dt        t        t        t        |      t        |            }d	}
||
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z  }|j,                  } |       }|st        j&                  d!|       d"z   d#t        j                          v st        j"                  |      rt        j$                  |      nd#t        j$                  |      t        j$                  |      dz  }t)        t        j*                  |            dx}}t        j                  |j                               }|d$   }d%}||k(  }
|
st        j                  d
|
fd&||f      t        j$                  |      t        j$                  |      d'z  }t        j&                  d(|d$          d)z   d*|iz  }t)        t        j*                  |            dx}x}
}t/              }
d+}|
|k(  }|st        j                  d
|fd|
|f      dt        j                          v st        j"                  t.              rt        j$                  t.              nddt        j                          v st        j"                        rt        j$                        ndt        j$                  |
      t        j$                  |      dz  }t        j&                  d,t/                     dz   d|iz  }t)        t        j*                  |            dx}
x}}y)-u   RS-3: 두 케이스 모두 검증.

    Case A: envelope 부재 → skip, exit 0, launch 마커 없음 (success path 깨지지 않음)
    Case B: envelope 존재 + ANU → 정상 prereg-launch 마커 생성
    z>/home/jay/workspace/tests/fixtures/p2a/success-baseline-5.jsonrw   c                 :    j                  d       t               S r   r   r   s    rM   r   zGtest_rs3_success_baseline_normal_callback.<locals>.fake_launch_callback)  r   rO   r   events_azdoes_not_exist.envelope.jsonrv   r   r   r   r   rc_ar   z(RS-3 Case A: exit code should be 0, got r   r   Nr   z>RS-3 Case A: launch marker must NOT exist when envelope absentzG
>assert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}launch_marker_ar   r   r   r   r   zDRS-3 Case A: launch_callback must not be called when envelope absentr   r   events_brc_bz(RS-3 Case B: exit code should be 0, got z)RS-3 Case B: launch marker should exist: r   launch_marker_br   r   r   r   z+RS-3 Case B: expected ANU_OWNED_READY, got r   r   r   zBRS-3 Case B: launch_callback should be called once in Case B, got )r   r{   r   r   rV   r;   r   r   r#   r   ANU_OWNER_KEYEXECUTOR_OTHER_KEYCHAT_IDr-   r.   r/   r0   r1   r2   r   r5   r6   r   r   r   )r}   r   r   r   rw   r   r   events_dir_amissing_enveloper   r   r?   r   rF   r   rA   r   r@   r   r   events_dir_b
envelope_br   r   r   r   rB   r   s                              @rM   )test_rs3_success_baseline_normal_callbackr     s    XYLjj//12Gi G^FH  ))+<>RS j(L8&DDE'&|$	D G419GGG41GGGGGG4GGG4GGG1GGG@GGGGGGG"y0L%MMO%%i%'i''i'ii)iiiiiiiiiiiii%iii'iiiiiix=eAe=Aeee=Aeeeeee3eee3eeeeeexeeexeee=eeeAeeeeeeeeeee j(L'2J'*o|$	D G419GGG41GGGGGG4GGG4GGG1GGG@GGGGGGG"y0L%MMO!!b!#b#bb'PQ`Pa%bbbbbbb?bbb?bbb!bbb#bbbbbb**_6689Kx  $5  $55   $5    !    %6    6k(6K5LM     x=sAs=Asss=Assssss3sss3ssssssxsssxsss=sssAsss!cdghpdqcrssssssssrO   c                   t        d      }t        j                  |j                               }|d   }t	               }g fd}|j                  |j                  d|       | dz  }|j                          t        | |      }t        |dt        t        t        t        |      t        |            }	t        |fi |	}
d}|
|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z  }|j0                  } |       }|st        j*                  d      dz   dt#        j$                         v st        j&                  |      rt        j(                  |      ndt        j(                  |      t        j(                  |      dz  }t-        t        j.                  |            dx}}|j3                         j4                  }t7              }d}||k(  }|st        j                   d	|fd||f      dt#        j$                         v st        j&                  t6              rt        j(                  t6              nddt#        j$                         v st        j&                        rt        j(                        ndt        j(                  |      t        j(                  |      dz  }t        j*                  dt7                     dz   d|iz  }t-        t        j.                  |            dx}x}}|| dz  }|j0                  } |       }|st        j*                  d      dz   d t#        j$                         v st        j&                  |      rt        j(                  |      nd t        j(                  |      t        j(                  |      dz  }t-        t        j.                  |            dx}}t        |fi |	}d}||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}}t7              }d}||k(  }|st        j                   d	|fd||f      dt#        j$                         v st        j&                  t6              rt        j(                  t6              nddt#        j$                         v st        j&                        rt        j(                        ndt        j(                  |      t        j(                  |      dz  }t        j*                  d#t7                     dz   d|iz  }t-        t        j.                  |            dx}x}}|j3                         j4                  }||k(  }|st        j                   d	|fd$||f      d%t#        j$                         v st        j&                  |      rt        j(                  |      nd%d&t#        j$                         v st        j&                  |      rt        j(                  |      nd&d'z  }t        j*                  d(      d)z   d*|iz  }t-        t        j.                  |            d}y)+u  RS-4: 1차 호출(ANU PASS) → lock+marker 생성. 2차 호출 → silent skip.

    검증:
      - launch_callback call count == 1 (2차 호출에서 호출 안 됨)
      - 마커 재생성 안 됨 (mtime 변화 없음)
      - lock 존재
      - 두 번 모두 exit 0
    z?/home/jay/workspace/tests/fixtures/p2a/duplicate-call-mock.jsonrw   c                 :    j                  d       t               S r   r   r   s    rM   r   z@test_rs4_duplicate_idempotent_skip.<locals>.fake_launch_callbacks  r   rO   r   r   rv   r   r   r   r   rc1r   z*RS-4: 1st call exit code should be 0, got r   r   Nr   z/RS-4: launch marker should exist after 1st callr   r   r   r   r   r   r   r   z=RS-4: after 1st call, launch_callback count should be 1, got r   r   r   z&RS-4: lock should exist after 1st callr   rc2z*RS-4: 2nd call exit code should be 0, got zJRS-4: after 2nd call, launch_callback should still be 1 (idempotent), got )z%(py0)s == %(py2)smtime_after_firstmtime_after_second)r   r   uN   RS-4: launch marker must NOT be recreated on 2nd call (idempotent §5.3/§9.2)z
>assert %(py4)sr   )r   r{   r   r   rV   r;   r   r   r   rg   r   r   r   r#   r   r-   r.   r/   r0   r1   r2   r   r5   r6   r   statst_mtimer   )r}   r   r   r   rw   r   r   r   r   common_argsr   r   r?   r   rF   r   rA   r   r   r   r@   r   r   r   r   r   @py_format3r   s                              @rM   "test_rs4_duplicate_idempotent_skipr   c  s    YZLjj//12Gi G^FH  ))+<>RSH$Jh0H'(mz?K &
(K
(CG3!8GGG3!GGGGGG3GGG3GGG!GGGA#GGGGGGGG9,H!IIMT!T!TT#TTTTTTT=TTT=TTTTTT!TTTTTT%**,55x=nAn=Annn=Annnnnn3nnn3nnnnnnxnnnxnnn=nnnAnnn!^_bck_l^mnnnnnnnn7)#899D;;B;=B=BBBBBBBBB4BBB4BBB;BBB=BBBBBB &
(K
(CG3!8GGG3!GGGGGG3GGG3GGG!GGGA#GGGGGGGx= A =A   =A                                UUXYaUbTcd    
 '++-66 22   2                !3    !3    	Y    rO   c                (   t        d      }t        j                  |j                               }|d   }t	               }g fd}|j                  |j                  d|       | dz  }|j                          t        | |      }t        |dt        t        t        t        |      t        |            }	t        |fi |	}
d}|
|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z  }|j0                  } |       }|st        j*                  d|       dz   dt#        j$                         v st        j&                  |      rt        j(                  |      ndt        j(                  |      t        j(                  |      dz  }t-        t        j.                  |            dx}}t        j                  |j                               }|d   }d}||k(  }|st        j                   d	|fd||f      t        j(                  |      t        j(                  |      dz  }t        j*                  d|d          dz   d|iz  }t-        t        j.                  |            dx}x}}|d   }d}||k(  }|st        j                   d	|fd||f      t        j(                  |      t        j(                  |      dz  }t        j*                  d      dz   d|iz  }t-        t        j.                  |            dx}x}}|| dz  }|j0                  } |       }|st        j*                  d |       dz   d!t#        j$                         v st        j&                  |      rt        j(                  |      nd!t        j(                  |      t        j(                  |      dz  }t-        t        j.                  |            dx}}t3              }d"}||k(  }|st        j                   d	|fd#||f      d$t#        j$                         v st        j&                  t2              rt        j(                  t2              nd$d%t#        j$                         v st        j&                        rt        j(                        nd%t        j(                  |      t        j(                  |      d&z  }t        j*                  d't3                     d(z   d)|iz  }t-        t        j.                  |            dx}x}}t        |fi |	}d}||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}}t3              }d"}||k(  }|st        j                   d	|fd#||f      d$t#        j$                         v st        j&                  t2              rt        j(                  t2              nd$d%t#        j$                         v st        j&                        rt        j(                        nd%t        j(                  |      t        j(                  |      d&z  }t        j*                  d,t3                     d(z   d)|iz  }t-        t        j.                  |            dx}x}}y)-ul  RS-5: fallback kind 1차 호출 → fallback-launch.json 생성 + fallback-lock.

    fallback lock 존재 → 재호출 시 silent skip (무한 재귀 방지).
    검증:
      - {task_id}.callback-fallback-launch.json 존재, status ANU_OWNED_READY
      - fallback lock 존재
      - 2차 호출 시 launch_callback 호출 안 됨 (total call count == 1)
    zA/home/jay/workspace/tests/fixtures/p2a/layer1-self-fail-mock.jsonrw   c                 :    j                  d       t               S r   r   r   s    rM   r   zDtest_rs5_layer1_self_fail_no_recursion.<locals>.fake_launch_callback  r   rO   r   r   r   r   r   r   r   r   r   z*RS-5: 1st call exit code should be 0, got r   r   Nr   z(RS-5: fallback launch marker not found: r   r   r   r   r   r   r   z$RS-5: expected ANU_OWNED_READY, got r   r   rx   zRS-5: kind should be fallbackr   zRS-5: fallback lock not found: r   r   r   r   r   r   z-RS-5: after 1st call, count should be 1, got r   r   r   z*RS-5: 2nd call exit code should be 0, got zaRS-5: 2nd call must NOT invoke launch_callback again (no recursion). Expected total count=1, got )r   r{   r   r   rV   r;   r   r   r   rg   r   r   r   r#   r   r-   r.   r/   r0   r1   r2   r   r5   r6   r   r   )r}   r   r   r   rw   r   r   r   r   r   r   r   r?   r   rF   r   rA   r   r   rB   r   r   r   r@   r   r   r   s                             @rM   &test_rs5_layer1_self_fail_no_recursionr     sS    [\Ljj//12Gi G^FH  ))+<>RSH$Jh0H'(mz?K &
(K
(CG3!8GGG3!GGGGGG3GGG3GGG!GGGA#GGGGGGG gY.L#MMO!!a!#a#aa'OP_O`%aaaaaaa?aaa?aaa!aaa#aaaaaa**_6689Kx  $5  $55   $5    !    %6    /{8/D.EF     vM*M*,MMM*MMMMMM*MMM.MMMMMMMMG9,C!DDMT!T!TT%D]O#TTTTTTT=TTT=TTTTTT!TTTTTTx=^A^=A^^^=A^^^^^^3^^^3^^^^^^x^^^x^^^=^^^A^^^!NsS[}o^^^^^^^^ &
(K
(CG3!8GGG3!GGGGGG3GGG3GGG!GGGA#GGGGGGGx= A =A   =A                               ''*8}o	7     rO   )rf   None)rf   rX   )r}   r   rw   r#   rf   r   )rw   r#   rx   r#   r   r#   r   r#   r   r#   r   r#   r   r#   r   r#   rf   int)%rk   
__future__r   builtinsr/   _pytest.assertion.rewrite	assertionrewriter-   importlib.utilr)   r{   r   pathlibr   typingr   pytestr%   rT   r$   r(   rN   rV   rX   rq   rt   r   r   r   r   r   r   r   r   r   r   rm   rO   rM   <module>r      s    #      
    '(
MMLL #99 +L`.9 9 2Y 3),:=7:& #. 
5kx4cv@tN=H=rO   