
    j5                       d Z ddlmZ ddlZddlmc mZ ddl	Z	e	j                  j                  dd       ddlZddlZddlZddlZddlZej"                  j%                  dd       ddlmZmZmZmZmZ ej2                  d        Zej2                  d	        Z G d
 d      Z G d d      Z G d d      Z G d d      Z G d d      Z  G d d      Z!d Z" G d d      Z#y)aH  Tests for v3.6 Layer 1: Dispatch Marker Writer.

chair_authorization_id=CHAIR-AUTH-TASK-2704-V36-CONTROL-PLANE-P0-MVP-260528

Coverage:
- 7-field schema PASS
- safe-fail: corrupted args do not raise
- bot_key_hash redaction confirmed (raw key NOT stored)
- fixture sample written and validated
- dispatch_method enum validation
    )annotationsNz/home/jay/workspaceANU_V36_HARNESS_TEST_MODE1)write_dispatch_marker_REQUIRED_FIELDSMARKER_VERSIONMARKER_TYPEDISPATCH_METHODSc                B    | dz  }|j                          t        |      S )Nevents)mkdirstr)tmp_path
events_dirs     F/home/jay/workspace/tests/harness/test_v36_dispatch_marker_contract.py
tmp_eventsr   &   s"    H$Jz?    c                *    t        ddddddd d| 	      S )	N	task-2704BE5161A0dev1-team/hermeszraw-secret-key-do-not-store2026-05-28T13:22:33+09:00z&Implement task-2704 v3.6 control planedispatch_py	task_idschedule_idexecutorbot_key	fire_timeprompttask_md_sha_beforedispatch_methodr   )dict)r   s    r   
valid_argsr$   -   s*    #--7%
 
r   c                  L    e 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)TestDispatchMarkerSchemaz 7-field schema validation tests.c                t   t        di |}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}}t        D ]  }||v }|st        j                  d	|fd
||f      dt        j                         v st        j
                  |      rt        j                  |      nddt        j                         v st        j
                  |      rt        j                  |      nddz  }t        j                  d|       dz   d|iz  }	t        t        j                  |	            d} y)z*Marker must contain all 7 required fields.Nis notz%(py0)s is not %(py3)sresultpy0py3z$write_dispatch_marker should succeed
>assert %(py5)spy5inz%(py0)s in %(py2)sfieldr-   py2zRequired field missing: 
>assert %(py4)spy4 )r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationr   )
selfr$   r+   @py_assert2@py_assert1@py_format4@py_format6r4   @py_format3@py_format5s
             r   "test_all_7_required_fields_presentz;TestDispatchMarkerSchema.test_all_7_required_fields_presentA   s    &44!IvT!IIIvTIIIIIIvIIIvIIITIII#IIIIIII% 	GEF?FFF5FFFFFFF5FFF5FFFFFFFFFFFFFFF&>ug$FFFFFFF	Gr   c                   t        di |}|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 )	Nmarker_version==z%(py1)s == %(py3)sr   py1r.   assert %(py5)sr0   r9   )
r   r   r:   r;   r?   r<   r=   r>   rA   rB   rC   r$   r+   @py_assert0rD   rF   rG   s          r   test_marker_version_fieldz2TestDispatchMarkerSchema.test_marker_version_fieldH   sq    &44&'9'>9999'>999'999999>999>9999999r   c                   t        di |}|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 )	Nmarker_typerM   rO   r	   rP   rR   r0   r9   )
r   r	   r:   r;   r?   r<   r=   r>   rA   rB   rS   s          r   test_marker_type_fieldz/TestDispatchMarkerSchema.test_marker_type_fieldL   sp    &44m$3$3333$333$3333333333333333r   c                   t        di |}|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   rM   z%(py1)s == %(py4)srQ   r8   assert %(py6)spy6r9   r   r:   r;   r?   rA   rB   rC   r$   r+   rT   @py_assert3rD   rI   @py_format7s           r   test_schedule_id_storedz0TestDispatchMarkerSchema.test_schedule_id_storedP   sa    &44m$2
2$
2222$
222$222
2222222r   c                   t        di |}|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   rM   rZ   r[   r\   r]   r9   r^   r_   s           r   test_executor_storedz-TestDispatchMarkerSchema.test_executor_storedT   se    &44j!7%77!%77777!%7777!777%77777777r   c                   t        di |}|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   rM   rZ   r[   r\   r]   r9   r^   r_   s           r   test_fire_time_storedz.TestDispatchMarkerSchema.test_fire_time_storedX   se    &44k"A&AA"&AAAAA"&AAAA"AAA&AAAAAAAAr   c                   t        di |}|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   rM   rZ   r[   r\   r]   r9   r^   r_   s           r   test_dispatch_method_storedz4TestDispatchMarkerSchema.test_dispatch_method_stored\   sb    &44'(9M9(M9999(M999(999M9999999r   c                b   t        di |}d}||u}|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}}|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)zHtask_md_sha_before may be None per spec (not yet available at dispatch).Nr(   r*   r+   r,   rR   r0   r!   isz%(py1)s is %(py4)sr[   r\   r]   r9   	r   r:   r;   r<   r=   r>   r?   rA   rB   )rC   r$   r+   rD   rE   rF   rG   rT   r`   rI   ra   s              r   $test_task_md_sha_before_none_allowedz=TestDispatchMarkerSchema.test_task_md_sha_before_none_allowed`   s    &44!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!*+3t3+t3333+t333+333t3333333r   c                b   t        di |}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}|d   }d}||u }|slt        j                  d	|fd
||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)ua   task-2705+1 contract: chair_authorization_id is dynamic (per-call arg). When not passed → None.chair_authorization_idr1   z%(py1)s in %(py3)sr+   rP   rR   r0   Nrj   rl   r[   r\   r]   r9   )	r   r:   r;   r?   r<   r=   r>   rA   rB   )
rC   r$   r+   rT   rD   rF   rG   r`   rI   ra   s
             r   (test_chair_authorization_id_default_nonezATestDispatchMarkerSchema.test_chair_authorization_id_default_nonef   s    &44'1'61111'6111'111111611161111111./747/47777/4777/77747777777r   c                *   i |ddi}t        d	i |}|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)
zNtask-2705+1 contract: caller-supplied chair_authorization_id is round-tripped.rp   zCHAIR-AUTH-TEST-2705PLUS1rM   rZ   r[   r\   r]   Nr9   r^   r_   s           r   *test_chair_authorization_id_passed_throughzCTestDispatchMarkerSchema.test_chair_authorization_id_passed_throughl   sy    Z
Z$<>YZ
&44./N3NN/3NNNNN/3NNNN/NNN3NNNNNNNNr   N)__name__
__module____qualname____doc__rJ   rU   rX   rb   rd   rf   rh   rn   rr   rt   r9   r   r   r&   r&   >   s:    *G:438B:48Or   r&   c                  (    e Zd ZdZd Zd Zd Zd Zy)TestBotKeyRedactionu3   Confirm raw key is never stored — only hash[:16].c                   |d   }t        di |}d }||u}|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}}|j                         D ]  }	t        |	t              s||	v}|st        j                  d|fd	||	f      d
t        j                         v st        j
                  |      rt        j                  |      nd
dt        j                         v st        j
                  |	      rt        j                  |	      nddz  }
t        j                  d      dz   d|
iz  }t        t        j                  |            d } y )Nr   r(   r*   r+   r,   rR   r0   not inz%(py0)s not in %(py2)sraw_keyvr5   z Raw bot key must never be storedr7   r8   r9   )r   r:   r;   r<   r=   r>   r?   rA   rB   values
isinstancer   r@   )rC   r$   r   r   r+   rD   rE   rF   rG   r   rH   rI   s               r   test_raw_key_not_in_markerz.TestBotKeyRedaction.test_raw_key_not_in_markerv   s   Y'&44!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!! 	LA!S!a'KKKwaKKKKKKwKKKwKKKKKKaKKKaKKKK)KKKKKKK	Lr   c                   |d   }t        d
i | t        j                  |      D ]#  }t        j                  j	                  ||      }t        |      j                         }||v}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|       dz   d	|iz  }	t        t        j                  |	            d }& y )Nr   r|   r~   r   contentr5   zRaw key found in file r7   r8   r9   )r   oslistdirpathjoinopenreadr:   r;   r<   r=   r>   r?   r@   rA   rB   )
rC   r$   r   r   fnamefpathr   rE   rH   rI   s
             r   test_raw_key_not_in_filez,TestBotKeyRedaction.test_raw_key_not_in_file   s    Y'+
+ZZ
+ 	LEGGLLU3E5k&&(G')KKK7'KKKKKK7KKK7KKKKKK'KKK'KKKK-CE7+KKKKKKK	Lr   c                   |d   }t        j                  |j                  d            j                         d d }t	        di |}|d   }||k(  }|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 )Nr   utf-8   bot_key_hashrM   rO   expected_hashrP   rR   r0   r9   hashlibsha256encode	hexdigestr   r:   r;   r?   r<   r=   r>   rA   rB   )	rC   r$   r   r   r+   rT   rD   rF   rG   s	            r   %test_bot_key_hash_is_sha256_prefix_16z9TestBotKeyRedaction.test_bot_key_hash_is_sha256_prefix_16   s    Y'w~~g'>?IIKCRP&44n%6%6666%666%6666666666666666r   c                   t        d	i |}|d   }t        |      }d}||k(  }|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 )
Nr   r   rM   z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)slenr-   r6   r8   py7assert %(py9)spy9r9   )
r   r   r:   r;   r<   r=   r>   r?   rA   rB   )	rC   r$   r+   rE   r`   @py_assert6@py_assert5@py_format8@py_format10s	            r   test_bot_key_hash_length_16z/TestBotKeyRedaction.test_bot_key_hash_length_16   s    &44.)0s)*0b0*b0000*b000000s000s000)000*000b0000000r   N)ru   rv   rw   rx   r   r   r   r   r9   r   r   rz   rz   s   s    =LL71r   rz   c                      e Zd ZdZd Zy)TestPromptShazprompt_sha is sha256(prompt).c                   |d   }t        j                  |j                  d            j                         }t	        d
i |}|d   }||k(  }|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 )Nr    r   
prompt_sharM   rO   expectedrP   rR   r0   r9   r   )	rC   r$   r    r   r+   rT   rD   rF   rG   s	            r   test_prompt_sha_correctz%TestPromptSha.test_prompt_sha_correct   s    H%>>&--"89CCE&44l#/#x////#x///#//////x///x///////r   N)ru   rv   rw   rx   r   r9   r   r   r   r      s
    '0r   r   c                  "    e Zd ZdZd Zd Zd Zy)TestFileWrittenz0Marker file is atomically written to events_dir.c                   t        di | t        j                  |      }|D cg c]  }d|v s|j                  d      s| }}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}}y c c}w )N
dispatchedz.json   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr   dispatch_files)r-   rQ   r.   r]   zMarker file should be writtenz
>assert %(py8)spy8r9   )r   r   r   endswithr   r:   r;   r<   r=   r>   r?   r@   rA   rB   )rC   r$   r   filesfr   rD   r   @py_assert4ra   @py_format9s              r   test_file_created_in_events_dirz/TestFileWritten.test_file_created_in_events_dir   s    +
+

:&%*Xla.?AJJwDW!XX>"HaH"a'HHH"aHHHHHHsHHHsHHHHHH>HHH>HHH"HHHaHHH)HHHHHHHH Ys   	E/E/E/c                b   t        di | t        j                  |      D cg c]	  }d|v s| }}|s{t        j                  d      dz   ddt        j                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            t        t        j                  j                  ||d               5 }t        j                  |      }d d d        d}|v }	|	st        j                   d|	fd	||f      t        j                  |      d
t        j                         v st        j                  |      rt        j                  |      nd
dz  }
dd|
iz  }t        t        j                  |            d x}}	y c c}w # 1 sw Y   xY w)Nr   zNo dispatched files foundz
>assert %(py0)sr-   r   r   r   r1   rq   datarP   rR   r0   r9   )r   r   r   r:   r@   r<   r=   r>   r?   rA   rB   r   r   r   jsonloadr;   )rC   r$   r   r   r   @py_format1fhr   rT   rD   rF   rG   s               r   test_file_is_valid_jsonz'TestFileWritten.test_file_is_valid_json   s   +
+JJz2Hqla6GHH111111111u111u11111"'',,z5845 	!99R=D	! yD    yD   y      D   D       	 I	! 	!s   	F F F%%F.c                   t         j                  j                  t         j                  j                  t              d      }t        |      5 }t        j                  |      }ddd       t        D ]  }|v }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|       d	z   d
|iz  }t!        t        j"                  |            d} 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}|	|k(  }|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   }|t&        v }
|
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# 1 sw Y   xY w)!z>Validate the committed fixture sample against required fields.z(fixtures/v36_dispatch_marker_sample.jsonNr1   r3   r4   sampler5   z Fixture missing required field: r7   r8   rL   v1rM   rZ   r[   r\   r]   rW   dispatch_markerr   r   r   r   r   r   r   r"   rq   r
   rP   rR   r0   )r   r   r   dirname__file__r   r   r   r   r:   r;   r<   r=   r>   r?   r@   rA   rB   r   r
   )rC   fixture_pathr   r   r4   rE   rH   rI   rT   r`   rD   ra   r   r   r   r   rF   rG   s                     r   "test_fixture_sample_matches_schemaz2TestFileWritten.test_fixture_sample_matches_schema   sw   ww||GGOOH%6
 , 	#2YYr]F	#% 	OEF?NNN5FNNNNNN5NNN5NNNNNNFNNNFNNNN&Fug$NNNNNNN	O&'/4/'4////'4///'///4///////m$9(99$(99999$(9999$999(99999999.)0s)*0b0*b0000*b000000s000s000)000*000b0000000'(<(,<<<<<(,<<<<(<<<<<<,<<<<,<<<<<<<<	# 	#s   P  P
N)ru   rv   rw   rx   r   r   r   r9   r   r   r   r      s    :I!=r   r   c                  ^    e Zd ZdZej
                  j                  dg d      d        Zd Zy)TestDispatchMethodEnumz4dispatch_method must be one of the 3 allowed values.method)r   direct_cron_bot_keyfallback_safety_netc                   ||d<   t        di |}d }||u}|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}}|d   }	|	|k(  }|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 )Nr"   r(   r*   r+   r,   rR   r0   rM   rO   r   rP   r9   rm   )
rC   r$   r   r   r+   rD   rE   rF   rG   rT   s
             r   test_valid_dispatch_methodsz2TestDispatchMethodEnum.test_valid_dispatch_methods   s    (.
$%&44!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!'(2(F2222(F222(222222F222F2222222r   c                   d|d<   t        di |}d}||u}|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}}|d   }|t        v }|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)u?   Invalid dispatch_method should not raise — safe default used.not_a_valid_methodr"   Nr(   r*   r+   r,   rR   r0   r1   rq   r
   rP   r9   )
r   r:   r;   r<   r=   r>   r?   rA   rB   r
   )	rC   r$   r   r+   rD   rE   rF   rG   rT   s	            r   *test_invalid_dispatch_method_uses_fallbackzATestDispatchMethodEnum.test_invalid_dispatch_method_uses_fallback   s    (<
$%&44!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!'(<(,<<<<<(,<<<<(<<<<<<,<<<<,<<<<<<<<r   N)	ru   rv   rw   rx   pytestmarkparametrizer   r   r9   r   r   r   r      s/    >[[X'de3 f3=r   r   c                  .    e Zd ZdZd Zd Zd Zd Zd Zy)TestSafeFailz4Safe-fail: corrupted or missing args must not raise.c                   t        d dddddd d|	      }g }d }||u }|}|st        |t              }|}|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                  |	       |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
dt        j                         v st        j                  t              rt        j                  t              ndt        j                        dz  }
|j                  |
       t        j                  |d      i z  }dd|iz  }t        t        j                  |            d x}x}x}x}}y )Nscheddev1key2026-01-01T00:00:00Ztestr   r   rj   )z%(py2)s is %(py5)sr+   r6   r0   %(py7)sr   z2%(py13)s
{%(py13)s = %(py9)s(%(py10)s, %(py11)s)
}r   r#   )r   py10py11py13r   zassert %(py16)spy16)r   r   r#   r:   r;   r<   r=   r>   r?   append_format_booloprA   rB   )rC   r   r+   rE   r   r`   rT   @py_assert12rG   r   @py_format14@py_format15@py_format17s                r   test_none_task_id_safe_failz(TestSafeFail.test_none_task_id_safe_fail   s   &,#)!

 	:9v~9FD!99!9999v999999v999v9999999999999999999999F999F999999D999D999!99999999999999r   c                v    	 t        dddd ddd d|	      }y # t        $ r t        j                  d       Y y w xY w)	Nr   r   r   r   r   r   r   zBwrite_dispatch_marker must not raise on corrupted args (safe-fail)r   	Exceptionr   fail)rC   r   r+   s      r   test_none_bot_key_safe_failz(TestSafeFail.test_none_bot_key_safe_fail   sM    	^*##0#' -%
F  	^KK\]	^s    88c                n    d|d<   	 t        di |}y # t        $ r t        j                  d       Y y w xY w)Nz%/nonexistent/path/that/does/not/existr   zFwrite_dispatch_marker must not raise on invalid events_dir (safe-fail)r9   r   )rC   r$   r+   s      r   !test_invalid_events_dir_safe_failz.TestSafeFail.test_invalid_events_dir_safe_fail   s=    #J
< 	b*8Z8F 	bKK`a	b    44c                n    d|d<   	 t        di |}y # t        $ r t        j                  d       Y y w xY w)N r   z5write_dispatch_marker must not raise on empty bot_keyr9   r   )rC   r$   r   r+   s       r   test_empty_bot_key_safe_failz)TestSafeFail.test_empty_bot_key_safe_fail   s=     "
9	Q*8Z8F 	QKKOP	Qr   c                   ddl m} |j                  dt        d            5  t	        di |}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dd       y# 1 sw Y   yxY w)zFEven if the logger import fails, write_dispatch_marker must not raise.r   NzFscripts.harness.v36.dispatch_marker_writer._write_dispatch_marker_implzsimulated internal error)side_effectrj   z%(py0)s is %(py3)sr+   r,   z1On internal error, should return None (safe-fail)r/   r0   r9   )unittest.mockmockpatchRuntimeErrorr   r:   r;   r<   r=   r>   r?   r@   rA   rB   )	rC   r$   r   r   r+   rD   rE   rF   rG   s	            r   +test_exception_in_logger_does_not_propagatez8TestSafeFail.test_exception_in_logger_does_not_propagate  s    $ZZT$%?@  
 	W +8Z8F!V6T>VVV6TVVVVVV6VVV6VVVTVVV#VVVVVVV	W 	W 	Ws   CC33C<N)	ru   rv   rw   rx   r   r   r   r   r   r9   r   r   r   r      s"    >: ^"bQWr   r   c                 *   ddl } ddl}d}| j                  j                  d|      }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}
}	| j                  j                  |      }||j                   |j"                  <   |j                  j%                  |       |S )zLoad /home/jay/workspace/dispatch/__init__.py directly via importlib.

    Necessary because pytest collects `tests/dispatch/__init__.py` as a package
    earlier in sys.modules, shadowing the real dispatch package.
    r   Nz(/home/jay/workspace/dispatch/__init__.pydispatch_real_task_2705_plus_3r(   )z%(py2)s is not %(py5)sspecr   r   r   )z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)r   r   py14z%(py16)sr   zassert %(py19)spy19)importlib.utilsysutilspec_from_file_locationloaderr:   r;   r<   r=   r>   r?   r   r   rA   rB   module_from_specmodulesnameexec_module)	importlib_sys	real_pathr   rE   r   r`   rT   @py_assert10@py_assert13r   rG   r   r   r   @py_format18@py_format20modules                     r   _load_real_dispatch_moduler    s@    :I>>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^^,,T2F$DLLKKF#Mr   c                  .    e Zd ZdZd Zd Zd Zd Zd Zy) TestCallerChairAuthIdPropagationz^task-2705+3 contract: caller (dispatch.__init__) extracts chair_authorization_id from task md.c                   t               }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}}|j                  }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}}y)	zFdispatch.__init__ exposes _safe_extract_chair_authorization_id helper.$_safe_extract_chair_authorization_idz5assert %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrdispatch_mod)r-   rQ   r.   r0   Nzfassert %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s._safe_extract_chair_authorization_id
})
}callable)r  r  r<   r=   r:   r>   r?   rA   rB   r  r  )rC   r  rD   r   rG   s        r   6test_safe_extract_chair_authorization_id_helper_existszWTestCallerChairAuthIdPropagation.test_safe_extract_chair_authorization_id_helper_exists'  s   13%KLw|%KLLLLLLLLwLLLwLLLLLL|LLL|LLL%KLLLLLLLLLL$IIJxIJJJJJJJJxJJJxJJJJJJJJJJJJIJJJJJJJJJJr   c                   t               }|j                  d      }d}||u }|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)	u%   Missing task md → None (safe-fail).ztask-nonexistent-xxx-9999Nrj   r   r+   r,   rR   r0   
r  r  r:   r;   r<   r=   r>   r?   rA   rB   	rC   r   monkeypatchr  r+   rD   rE   rF   rG   s	            r   /test_safe_extract_returns_none_for_missing_taskzPTestCallerChairAuthIdPropagation.test_safe_extract_returns_none_for_missing_task-  ss    13BBC^_v~vvvr   c                   t               }|j                  d      }d}||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	)
u7   Real task md → chair_authorization_id verbatim value.ztask-2705+3:CHAIR-AUTH-TASK-2705PLUS3-V36-CHAIR-AUTH-CALLER-FIX-260529rM   )z%(py0)s == %(py3)sr+   r,   rR   r0   Nr  r  s	            r   <test_safe_extract_parses_chair_authorization_id_from_task_mdz]TestCallerChairAuthIdPropagation.test_safe_extract_parses_chair_authorization_id_from_task_md3  sv    13BB=QUUvUUUUUvUUUUUUUvUUUvUUUUUUUUUUUr   c                   t               }|j                  }d} ||      }d}||u }|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)	u   Empty task_id → None.r   Nrj   )zj%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s._safe_extract_chair_authorization_id
}(%(py4)s)
} is %(py9)sr  )r-   r6   r8   r]   r   zassert %(py11)sr   r  )	rC   r  rE   r`   r   @py_assert8@py_assert7r   @py_format12s	            r   'test_safe_extract_handles_empty_task_idzHTestCallerChairAuthIdPropagation.test_safe_extract_handles_empty_task_id;  s    13@@LL@DLLDLLLLDLLLLLL|LLL|LLL@LLLLLLDLLLLLLLLLLLr   c                   i |t        |      dd}t        di |}d}||u}|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}}|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)z:End-to-end: caller-extracted value flows into marker JSON.r#  )r   rp   Nr(   r*   r+   r,   rR   r0   rp   rM   rZ   r[   r\   r]   r9   )
r   r   r:   r;   r<   r=   r>   r?   rA   rB   )rC   r$   r   r   r+   rD   rE   rF   rG   rT   r`   rI   ra   s                r   5test_dispatch_marker_receives_extracted_chair_auth_idzVTestCallerChairAuthIdPropagation.test_dispatch_marker_receives_extracted_chair_auth_id@  s    

j/&b


 '44!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!./o3oo/3ooooo/3oooo/ooo3oooooooor   N)	ru   rv   rw   rx   r  r!  r$  r)  r+  r9   r   r   r  r  $  s"    hKVM
	pr   r  )$rx   
__future__r   builtinsr<   _pytest.assertion.rewrite	assertionrewriter:   r  r   insertr   r   r   tempfiler   environ
setdefault*scripts.harness.v36.dispatch_marker_writerr   r   r   r	   r
   fixturer   r$   r&   rz   r   r   r   r   r  r  r9   r   r   <module>r7     s   
 #   
 ( )   	   

  13 7      2O 2Oj1 1@0 0= =B= =&:W :W@&%p %pr   