
    #iX                        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
mZmZmZ ddlmZ ej                   j#                  dd       ddlZddlZddlmZmZmZmZmZmZ ddlmZ ddlmZ  G d	 d
e      Z G d de      Z de!de"f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) G d d      Z*y)u  
Module 1 Integration Tests — Black Box
Story 1.06 — Track B

Tests the complete interceptor pipeline from the outside.
All tests exercise public API contracts only — no internal state inspection.

Test classes:
    TestAbstractInstantiation   — BaseInterceptor ABC enforcement
    TestChainOrdering           — Priority-order execution, disabled interceptor skipping
    TestChainRegistration       — register/unregister/len public API
    TestDispatchToSwarm         — task_id assignment, success/error paths, concurrency
    TestNullInterceptor         — pass-through contract
    TestTelemetryInterceptor    — event logging contract
    TestFullPipeline            — end-to-end dispatch with multiple interceptors
    N)	AsyncMockpatch	MagicMock)Pathz/mnt/e/genesis-system)BaseInterceptorInterceptorMetadataInterceptorChaindispatch_to_swarmGLOBAL_CHAINregister_interceptor)ExecutionTelemetryInterceptor)NullInterceptorc                   l    e Zd ZdZdededefdZdedefdZ	d	ededd
fdZ
dededefdZdedefdZy
)_OrderTrackingInterceptorzLMinimal concrete interceptor that records execution order via a shared list.nameprioritycall_logc                 8    t        ||d      | _        || _        y )NTr   r   enabled)r   metadata	_call_log)selfr   r   r   s       A/mnt/e/genesis-system/tests/interceptors/test_base_interceptor.py__init__z"_OrderTrackingInterceptor.__init__/   s    +RVW!    task_payloadreturnc                 l   K   | j                   j                  | j                  j                         |S wN)r   appendr   r   r   r   s     r   pre_executez%_OrderTrackingInterceptor.pre_execute3   s(     dmm001s   24resultNc                    K   y wr     r   r$   r   s      r   post_executez&_OrderTrackingInterceptor.post_execute7   	        errorc                 $   K   dt        |      iS wNr+   strr   r+   r   s      r   on_errorz"_OrderTrackingInterceptor.on_error:        U$$   correction_payloadc                    K   |S wr    r&   r   r4   s     r   on_correctionz'_OrderTrackingInterceptor.on_correction=        !!   )__name__
__module____qualname____doc__r/   intlistr   dictr#   r(   	Exceptionr1   r7   r&   r   r   r   r   ,   sy    V"S "C "4 "d t  T d %I %T %d %"d "t "r   r   c                   n    e Zd ZdZddededefdZdedefdZd	ededd
fdZ	de
dedefdZdedefdZy
)_EnrichingInterceptorzIAdds a known key to the payload so we can verify enrichment from outside.keyvaluer   c                 L    t        d| |d      | _        || _        || _        y )N	enricher_Tr   )r   r   _key_value)r   rD   rE   r   s       r   r   z_EnrichingInterceptor.__init__D   s(    +9SE1BX_cd	r   r   r   c                 B   K   i || j                   | j                  iS wr    )rH   rI   r"   s     r   r#   z!_EnrichingInterceptor.pre_executeI   s      7,7		4;;77s   r$   Nc                    K   y wr    r&   r'   s      r   r(   z"_EnrichingInterceptor.post_executeL   r)   r*   r+   c                 $   K   dt        |      iS wr-   r.   r0   s      r   r1   z_EnrichingInterceptor.on_errorO   r2   r3   r4   c                    K   |S wr    r&   r6   s     r   r7   z#_EnrichingInterceptor.on_correctionR   r8   r9   )
   )r:   r;   r<   r=   r/   r>   r   r@   r#   r(   rA   r1   r7   r&   r   r   rC   rC   A   sy    SC  s 
8d 8t 8 T d %I %T %d %"d "t "r   rC   rE   r   c                 x    	 t        j                  | d      }t        |      | k(  S # t        t        f$ r Y yw xY w)zCTrue if *value* is a canonical UUID-4 string (36 chars, 4 hyphens).   )versionF)uuidUUIDr/   
ValueErrorAttributeError)rE   parseds     r   _is_valid_uuid4rW   V   s=    5!,6{e##' s   $' 99c                   "    e Zd ZdZd Zd Zd Zy)TestAbstractInstantiationuB   BaseInterceptor is an ABC — it must refuse direct instantiation.c                 t    t        j                  t              5  t                ddd       y# 1 sw Y   yxY w)uC   BaseInterceptor is abstract — instantiation must raise TypeError.N)pytestraises	TypeErrorr   )r   s    r   (test_cannot_instantiate_base_interceptorzBTestAbstractInstantiation.test_cannot_instantiate_base_interceptorf   s)    ]]9% 		 	 	s   .7c                 X   t               }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                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)z;A complete concrete subclass is instantiable without error.5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancenullr   py0py1py2py4N
r   ra   r   @py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationr   rb   @py_assert3@py_format5s       r   ;test_concrete_subclass_with_all_methods_can_be_instantiatedzUTestAbstractInstantiation.test_concrete_subclass_with_all_methods_can_be_instantiatedk        $00000000z000z000000$000$0000000000000000000r   c                      G d dt               }t        j                  t              5   |        ddd       y# 1 sw Y   yxY w)z?Subclass missing any abstract method must also raise TypeError.c                   0    e Zd Z edd      ZdedefdZy)hTestAbstractInstantiation.test_partial_subclass_missing_methods_cannot_be_instantiated.<locals>._Partialpartialr   )r   r   r   r   c                    K   |S wr    r&   r"   s     r   r#   ztTestAbstractInstantiation.test_partial_subclass_missing_methods_cannot_be_instantiated.<locals>._Partial.pre_executev   s     ##r9   N)r:   r;   r<   r   r   r@   r#   r&   r   r   _Partialrw   s   s!    *	AFH$d $t $r   rz   N)r   r[   r\   r]   )r   rz   s     r   <test_partial_subclass_missing_methods_cannot_be_instantiatedzVTestAbstractInstantiation.test_partial_subclass_missing_methods_cannot_be_instantiatedp   s6    	$ 	$ ]]9% 	J	 	 	s	   :AN)r:   r;   r<   r=   r^   rs   r{   r&   r   r   rY   rY   c   s    L
1
r   rY   c                   (    e Zd ZdZd Zd Zd Zd Zy)TestChainOrderingz8Chain executes interceptors in ascending priority order.c                    g }t               }|j                  t        dd|             |j                  t        dd|             |j                  t        dd|             t        j                  |j                  dd	i             g 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}}y)z>Lower-priority-number interceptors execute before higher ones.high_100d   r   r   mid_502   low_10rN   promptzordering test)r   r   r   ==z%(py0)s == %(py3)sr   rd   py3zUnexpected execution order: 
>assert %(py5)spy5N)r	   registerr   asynciorunexecute_prerk   _call_reprcompareri   rj   rl   rm   _format_assertmsgrn   ro   )r   r   chain@py_assert2@py_assert1@py_format4@py_format6s          r   +test_interceptors_execute_in_priority_orderz=TestChainOrdering.test_interceptors_execute_in_priority_order   s    " 	0cT\]^0RS[\]0RS[\]E%%x&ABC; 	
x;; 	
 	
x; 	
 	
	6	
 	
   	
 	
 		  	
 	
 		 < 	
 	
  +8*5	
 	
 	
 	
 	
r   c                    g }t               }dD ]  }|j                  t        |d|             ! t        j                  |j                  ddi             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                  |      dz  }t        j                  d|       dz   d|iz  }t        t        j                  |            dx}x}}y)zCAll interceptors with identical priority execute (no silent skips).)abc   r   r   zequal priorities>   r   r   r   r   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)ssetr   rd   re   r   py6zExpected all three; got: z
>assert %(py8)spy8N)r	   r   r   r   r   r   r   rk   r   ri   rj   rl   rm   r   rn   ro   )	r   r   r   r   r   @py_assert5@py_assert4@py_format7@py_format9s	            r   ,test_equal_priority_interceptors_all_executez>TestChainOrdering.test_equal_priority_interceptors_all_execute   s     "# 	[DNN4TAPXYZ	[ 	E%%x1C&DEF8}WW}/WWW}WWWWWWsWWWsWWWWWW8WWW8WWW}WWWWWW3LXJ1WWWWWWWWr   c                    g }t               }t        dd|      }t        dd|      }t        ddd      |_        |j	                  |       |j	                  |       t        j                  |j                  d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  }t        j                  d      dz   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  }t        j                  d      dz   d|iz  }t        t        j                   |            dx}}y)z8Disabled interceptors are excluded from chain execution.activerN   r   inactive   Fr   r   zdisabled testinz%(py1)s in %(py3)sr   re   r   z Enabled interceptor must executer   r   Nnot inz%(py1)s not in %(py3)sz$Disabled interceptor must be skipped)r	   r   r   r   r   r   r   r   rk   r   rm   ri   rj   rl   r   rn   ro   )	r   r   r   r   r   @py_assert0r   r   r   s	            r   !test_disabled_interceptor_skippedz3TestChainOrdering.test_disabled_interceptor_skipped   s;    ",X"xX,Z"xX/Z"V[\vx E%%x&ABCIxX%IIIxXIIIxIIIIIIXIIIXIIII'IIIIIIIQz)QQQzQQQzQQQQQQQQQQQQQ+QQQQQQQr   c                    t               }|j                  t        ddd             |j                  t        ddd             t        j                  |j                  dd	i            }|j                  }d} ||      }d}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}x}x}}|j                  }d} ||      }d}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}x}x}}y)zREach interceptor in the chain receives the enriched payload from the previous one.key_afrom_arN   r   key_bfrom_br   r   zsequential enrichmentr   zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} == %(py9)sr$   rd   rf   rg   r   py9assert %(py11)spy11N)r	   r   rC   r   r   r   getrk   r   ri   rj   rl   rm   rn   ro   
r   r   r$   r   rq   r   @py_assert8@py_assert7@py_format10@py_format12s
             r   /test_payload_enriched_sequentially_across_chainzATestChainOrdering.test_payload_enriched_sequentially_across_chain   s    ",WhLM,WhLMU..:Q/RST zz.'.z'".h."h...."h......v...v...z...'..."...h.......zz.'.z'".h."h...."h......v...v...z...'..."...h........r   N)r:   r;   r<   r=   r   r   r   r   r&   r   r   r}   r}      s    B
 	XR"
/r   r}   c                   (    e Zd ZdZd Zd Zd Zd Zy)TestChainRegistrationz-Public register/unregister/len API contracts.c                    t               }t        |      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|j                  t                      t        |      }d
}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|j                  t                      t        |      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)z:Each registered interceptor increases chain length by one.r   r   r   lenr   r   assert %(py8)sr   N      )r	   r   rk   r   ri   rj   rl   rm   rn   ro   r   r   r   )r   r   r   r   r   r   r   s          r   $test_register_increases_chain_lengthz:TestChainRegistration.test_register_increases_chain_length   s    "5zQzQzQss55zQ()5zQzQzQss55zQ4675zQzQzQss55zQr   c                    t               }|j                  t                      t        |      }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}|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}}t        |      }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}y	)z<unregister() removes the named interceptor and returns True.r   r   r   r   r   r   r   r   Nnull_interceptorTisz%(py0)s is %(py3)sremovedr   assert %(py5)sr   r   )r	   r   r   r   rk   r   ri   rj   rl   rm   rn   ro   
unregister)r   r   r   r   r   r   r   r   r   r   r   s              r   +test_unregister_by_name_removes_interceptorzATestChainRegistration.test_unregister_by_name_removes_interceptor   s    "()5zQzQzQss55zQ""#56w$w$ww$5zQzQzQss55zQr   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	)
z6unregister() returns False when the name is not found.does_not_existFr   r   r$   r   r   r   N)
r	   r   rk   r   ri   rj   rl   rm   rn   ro   )r   r   r$   r   r   r   r   s          r   *test_unregister_unknown_name_returns_falsez@TestChainRegistration.test_unregister_unknown_name_returns_false   ss     "!!"23vvvvr   c                    t               }|j                  t                      |j                         }t	        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|d
   }|d   }	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}
|	|
u }|slt        j                  d|fd|	|
f      t        j                  |	      t        j                  |
      dz  }dd|iz  }t        t        j                  |            d	x}	x}}
y	)zMget_chain_summary() returns the correct metadata for registered interceptors.r   r   r   r   summaryr   r   r   Nr   r   r   z%(py1)s == %(py4)sre   rg   assert %(py6)sr   r   r   r   Tr   )z%(py1)s is %(py4)s)r	   r   r   get_chain_summaryr   rk   r   ri   rj   rl   rm   rn   ro   )r   r   r   r   r   r   r   r   entryr   rq   rr   s               r   7test_get_chain_summary_reflects_registered_interceptorszMTestChainRegistration.test_get_chain_summary_reflects_registered_interceptors   s    "()))+7| q |q    |q      s   s      7   7   |   q       
V}2 22} 22222} 2222}222 22222222Z &B& B&&&& B&&& &&&B&&&&&&&Y'4'4''''4''''''4'''''''r   N)r:   r;   r<   r=   r   r   r   r   r&   r   r   r   r      s    7
(r   r   c                      e Zd ZdZej
                  j                  d        Zej
                  j                  d        Zej
                  j                  d        Z	ej
                  j                  d        Z
ej
                  j                  d        Zej
                  j                  d        Zej
                  j                  d        Zy	)
TestDispatchToSwarmz'Public dispatch_to_swarm API contracts.c                 4  K   t        ddi       d{   }|j                  dd      }t        |      }|st        j                  d|      dz   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}y7 w)
z@dispatch_to_swarm assigns a UUID4 task_id when none is provided.r   helloNtask_id zNot a valid UUID4: .
>assert %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}rW   rd   re   r   )r
   r   rW   rk   r   ri   rj   rl   rm   rn   ro   )r   r$   r   r   r   s        r   "test_dispatch_assigns_uuid_task_idz6TestDispatchToSwarm.test_dispatch_assigns_uuid_task_id   s      )(G)<==**Y+w'J'JJ+>wk)JJJJJJJJJJJJJJJJwJJJwJJJ'JJJJJJ >s   DDDDc                   K   t        t        j                               }t        d|d       d{   }|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7 w)zEdispatch_to_swarm preserves a task_id already present in the payload.z
keep my idr   r   Nr   r   )z%(py1)s == %(py3)s	custom_idr   r   r   )r/   rR   uuid4r
   rk   r   rm   ri   rj   rl   rn   ro   )r   r   r$   r   r   r   r   s          r   /test_dispatch_preserves_caller_supplied_task_idzCTestDispatchToSwarm.test_dispatch_preserves_caller_supplied_task_id   s      

%	(LY)WXXi - I---- I--- ------I---I------- Ys   /C"C B/C"c                   K   t        ddi       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}||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7 +w)zCSuccessful dispatch returns status: completed with task_id present.r   zsuccess testNstatus	completedr   r   r   r   r   r   r   r   r$   r   r   r   )	r
   rk   r   rm   rn   ro   ri   rj   rl   	r   r$   r   rq   r   rr   r   r   r   s	            r   test_dispatch_success_pathz.TestDispatchToSwarm.test_dispatch_success_path   s      )(N)CDDh.;.;....;......;......."yF""""yF"""y""""""F"""F""""""" Es   ED>D+Ec                 2  K   t        dt        t        d            5  t        ddi       d{   }dd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}||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7 # 1 sw Y   xY ww)zIException during _execute_task returns status: error with correction key.zcore.interceptors._execute_taskzexecutor exploded)new_callableside_effectr   z	will failNr   r+   r   r   r   r   r   r   r   r   r$   r   r   r   
correction)r   r   RuntimeErrorr
   rk   r   rm   rn   ro   ri   rj   rl   r   s	            r   test_dispatch_error_pathz,TestDispatchToSwarm.test_dispatch_error_path  sX     -"$%89
 	F
 -h-DEEF	F h*7*7****7******7*******"yF""""yF"""y""""""F"""F"""""""%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%	 F	F 	Fs,   HH
HH
GHH

HHc                 4  K   t        d      D cg c]	  }dd| i }}t        j                  |D cg c]  }t        |       c}  d{   }|D cg c]  }|d   	 }}t	        |      }t        |      }t        |      }	||	k(  }
|
s t        j                  d|
fd||	f      dt        j                         v st        j                  t
              rt        j                  t
              ndd	t        j                         v st        j                  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                  |      rt        j                  |      nd
t        j                  |	      dz  }t        j                  dt        |       d      dz   d|iz  }t        t        j                  |            dx}x}x}
}	|D ]  }t        |      }|st        j                  d|      dz   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} yc c}w c c}w 7 Dc c}w w)zIMultiple concurrent dispatches each receive an independent UUID4 task_id.r   r   zconcurrent-Nr   r   )zn%(py6)s
{%(py6)s = %(py0)s(%(py4)s
{%(py4)s = %(py1)s(%(py2)s)
})
} == %(py11)s
{%(py11)s = %(py8)s(%(py9)s)
}r   r   task_ids)rd   re   rf   rg   r   r   r   r   z"Duplicate task_ids detected among z concurrent dispatchesz
>assert %(py13)spy13zNon-UUID4 task_id: r   rW   tidr   )ranger   gatherr
   r   r   rk   r   ri   rj   rl   rm   r   rn   ro   rW   )r   ipayloadspresultsrr   rq   r   @py_assert10r   r   @py_format14r   r   r   s                   r   "test_concurrent_dispatch_isolationz6TestDispatchToSwarm.test_concurrent_dispatch_isolation  s     <A9EaXQC01EEx(P!):1)=(PQQ*12QAiL22x= 	
s=! 	
S] 	
!]2 	
 	
 	
!] 	
 	
	6	
 	
   	
 	
 		  	
 	
	6	
 	
   	
 	
 		  	
 	
	6	
 	
    	
 	
 		   	
 	
 		 ! 	
 	
 		 " 	
 	
	6	
 	
  &) 	
 	
 		 &) 	
 	
	6	
 	
  *2 	
 	
 		 *2 	
 	
 		 &3 	
 	
  1X?UV	
 	
 	
 	
 	
 	
  	GC"3'F'FF+>sg)FFFFFFF?FFF?FFFFFF3FFF3FFF'FFFFFF	G F(PQ2s9   NNNNNNNN!L0NNc                   K   ddi}t        |       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}}|d   }ddl	m	} |j                  |      }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7 lw)zHdispatch_to_swarm stamps dispatched_at timestamp in ISO-8601 UTC format.r   ztimestamp testNdispatched_atr   r   payloadr   r   r   r   )datetimeis notz%(py0)s is not %(py3)srV   r   )r
   rk   r   rm   ri   rj   rl   rn   ro   r  fromisoformat)
r   r  r   r   r   r   tsr  rV   r   s
             r   "test_dispatch_stamps_dispatched_atz6TestDispatchToSwarm.test_dispatch_stamps_dispatched_at$  s      "#34((()'))))')))))))))')))')))))))_%%''+!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!! 	)s   FFE,Fc                 >  K   t        ddid       d{   }|d   }d}||k(  }|slt        j                  d|fd	||f      t        j                  |      t        j                  |      d
z  }dd|iz  }t	        t        j
                  |            dx}x}}y7 w)zMPassing tier= argument writes it to the payload and returns it in the result.r   z	tier testgold)tierNr   r   r   r   r   r   r   )r
   rk   r   rm   rn   ro   )r   r$   r   rq   r   rr   r   s          r   %test_dispatch_tags_tier_when_providedz9TestDispatchToSwarm.test_dispatch_tags_tier_when_provided1  sv      )(K)@vNN h.;.;....;......;....... Os   BBBBN)r:   r;   r<   r=   r[   markr   r   r   r   r   r	  r  r  r&   r   r   r   r      s    1[[K K [[. . [[# # [[& & [[G G [[
" 
" [[	/ 	/r   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)TestNullInterceptorz-NullInterceptor pass-through public contract.c                 X   t               }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                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)z6NullInterceptor can be instantiated without arguments.r`   ra   rb   r   rc   Nrh   rp   s       r   !test_null_interceptor_is_concretez5TestNullInterceptor.test_null_interceptor_is_concreteE  rt   r   c                    t               }|j                  }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}|j                  }|j                  }d	}||k(  }|st        j                  d|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}|j                  }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)z9NullInterceptor metadata matches the documented defaults.r   r   )zJ%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.metadata
}.name
} == %(py7)srb   rd   rf   rg   py7assert %(py9)sr   Nr   zN%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.metadata
}.priority
} == %(py7)sTr   )zM%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.metadata
}.enabled
} is %(py7)s)r   r   r   rk   r   ri   rj   rl   rm   rn   ro   r   r   )r   rb   r   rq   @py_assert6r   @py_format8r   s           r   test_null_interceptor_metadataz2TestNullInterceptor.test_null_interceptor_metadataJ  s    }}7}!!7%77!%77777!%7777777t777t777}777!777%77777777}}+}%%++%++++%++++++t+++t+++}+++%++++++++++}},}$$,,$,,,,$,,,,,,t,,,t,,,},,,$,,,,,,,,,,r   c                 X   t               }ddd}t        j                  |j                  |            }||u }|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}d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)uC   pre_execute returns the exact same object — no copy, no mutation.zpass through*   )tasknumr   z%(py0)s is %(py2)sr$   r  rd   rf   assert %(py4)srg   Nr   r   r   r   r   )r   r   r   r#   rk   r   ri   rj   rl   rm   rn   ro   )
r   rb   r  r$   r   @py_format3rr   r   r   r   s
             r   0test_null_interceptor_passes_through_pre_executezDTestNullInterceptor.test_null_interceptor_passes_through_pre_executeQ  s     )"5T--g67    v      v   v                "0<<v<<<<<v<<<<<<<v<<<v<<<<<<<<<<<r   c                 h   t               }ddi}t        j                  |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	)
z6on_correction adds CORRECTION: prefix to prompt field.r   zretry this taskzCORRECTION: retry this taskr   r   r   r   r   N)	r   r   r   r7   rk   r   rm   rn   ro   )	r   rb   r  r$   r   rq   r   rr   r   s	            r   3test_null_interceptor_on_correction_prepends_prefixzGTestNullInterceptor.test_null_interceptor_on_correction_prepends_prefixZ  s     ./T//89h@#@@#@@@@@#@@@@@@@#@@@@@@@@r   c                    t               }ddi}t        j                  |j                  |            }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}||k(  }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            d
x}x}}y
)zAon_correction leaves payload unchanged when prompt key is absent.	other_keydatar   r   r   r$   r   r   r   Nr   r   r   r   r   )r   r   r   r7   rk   r   rm   ri   rj   rl   rn   ro   )r   rb   r  r$   r   r   r   r   rq   rr   r   s              r   6test_null_interceptor_on_correction_without_prompt_keyzJTestNullInterceptor.test_null_interceptor_on_correction_without_prompt_keya  s     'T//89%xv%%%%xv%%%x%%%%%%v%%%v%%%%%%%k",f,"f,,,,"f,,,",,,f,,,,,,,r   N)	r:   r;   r<   r=   r  r$  r-  r/  r3  r&   r   r   r  r  B  s    71
-=A-r   r  c                   4    e Zd ZdZd Zd Zd Zd Zd Zd Z	y)	TestTelemetryInterceptorz2ExecutionTelemetryInterceptor observable contract.c                 X   t               }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                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)zDExecutionTelemetryInterceptor can be instantiated without arguments.r`   ra   telr   rc   N)
r   ra   r   ri   rj   rk   rl   rm   rn   ro   )r   r7  rq   rr   s       r   &test_telemetry_interceptor_is_concretez?TestTelemetryInterceptor.test_telemetry_interceptor_is_concreteq  s    +-#////////z///z//////#///#///////////////////r   c                    t               }|j                  }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)	z6Telemetry interceptor has priority=0 so it runs first.r   r   r!  r7  r  r   r   N)r   r   r   rk   r   ri   rj   rl   rm   rn   ro   )r   r7  r   rq   r"  r   r#  r   s           r   +test_telemetry_interceptor_priority_is_zerozDTestTelemetryInterceptor.test_telemetry_interceptor_priority_is_zerov  s    +-||)|$$))$))))$))))))s)))s)))|)))$))))))))))r   c                    t               }ddd}t        j                  |d      5  t        j                  |j                  |            }ddd       |u }|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# 1 sw Y   xY w)zBpre_execute must return the payload unchanged (side-effects only).zabc-123testr   r   _appendNr   r)  r$   r  r*  z-pre_execute must return the same payload dictz
>assert %(py4)srg   )r   r   objectr   r   r#   rk   r   ri   rj   rl   rm   r   rn   ro   )r   r7  r  r$   r   r,  rr   s          r   1test_telemetry_pre_execute_passes_payload_throughzJTestTelemetryInterceptor.test_telemetry_pre_execute_passes_payload_through{  s    +-'6:\\#y) 	;[[!9:F	;  QQQvQQQQQQvQQQvQQQQQQQQQQQQQ"QQQQQQQ	; 	;s   %D88Ec                    t               }g }t        j                  |d|j                        5  t	        j
                  |j                  ddd             ddd       t        |      }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  t              rt        j                  t              nd
dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|d   }|d   }	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# 1 sw Y    xY w)z2pre_execute appends a dispatch_start event record.r>  r   zt-001z	record mer=  Nr   r   r   r   appendedr   r   r   r   eventdispatch_startr   r   r   r   r   )r   r   r?  r!   r   r   r#   r   rk   r   ri   rj   rl   rm   rn   ro   )r   r7  rC  r   r   r   r   r   recordr   rq   rr   s               r   +test_telemetry_records_dispatch_start_eventzDTestTelemetryInterceptor.test_telemetry_records_dispatch_start_event  s   +-\\#yhooF 	VKKG{(STU	V 8}!!}!!!!}!!!!!!s!!!s!!!!!!8!!!8!!!}!!!!!!!!!!!g2"22"22222"2222222"22222222i +G+ G++++ G+++ +++G+++++++	V 	Vs   (I55I?c                    t               }g }ddd}t        j                  |d|j                        5  t	        j
                  |j                  |             t	        j
                  |j                  ddi|             ddd       |D cg c]  }|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# 1 sw Y   xY wc c}w )z6post_execute appends a dispatch_complete event record.zt-002zcomplete mer=  r>  rB  r   r   NrD  dispatch_completer   r   eventsr   r   r   )r   r   r?  r!   r   r   r#   r(   rk   r   rm   ri   rj   rl   rn   ro   )
r   r7  rC  r  r  rJ  r   r   r   r   s
             r   .test_telemetry_records_dispatch_complete_eventzGTestTelemetryInterceptor.test_telemetry_records_dispatch_complete_event  s    +-%?\\#yhooF 	LKK01KK(((K)@'JK	L
 '//!G*//","f,,,,"f,,,",,,,,,f,,,f,,,,,,,	L 	L
 0s   AE E E	c                    t               }g }ddi}t        j                  |d|j                        5  t	        j
                  |j                  t        d      |            }ddd       |D cg c]  }|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}}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# 1 sw Y   gxY wc c}w )zBon_error appends a dispatch_error event and returns an error dict.r   zt-003r>  rB  zsomething brokeNrD  dispatch_errorr   r   rJ  r   r   r   r+   r$   )r   r   r?  r!   r   r   r1   rT   rk   r   rm   ri   rj   rl   rn   ro   )r   r7  rC  r  r$   r  rJ  r   r   r   r   s              r   +test_telemetry_records_dispatch_error_eventzDTestTelemetryInterceptor.test_telemetry_records_dispatch_error_event  s6   +-g&\\#yhooF 	[[Z(9:GDF	
 '//!G*//)6))))6)))))))))6)))6))))))) w&    w&   w      &   &       	 	
 0s   /G.GGN)
r:   r;   r<   r=   r8  r:  r@  rG  rK  rN  r&   r   r   r5  r5  n  s$    <0
*
R,-!r   r5  c                   `   e Zd ZdZej
                  j                  d        Zej
                  j                  d        Zej
                  j                  d        Z	ej
                  j                  d        Z
ej
                  j                  d        Zej
                  j                  d        Zy)	TestFullPipelineuM   End-to-end integration: register interceptors → dispatch → verify result.c                 "  K   t               }t               }t        j                  |d      5  |j	                  t                      |j	                  |       ddi}t        t        j                               |d<   |j                  |       d{   }|d   |j                  dd      dd}|j                  ||       d{    dd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   }t#        |      }|sddt%        j&                         v st        j(                  t"              rt        j                  t"              ndt        j                  |      t        j                  |      dz  }	t        t        j                   |	            dx}}y7 l7 <# 1 sw Y   <xY ww)uW   Full pipeline: fresh chain with NullInterceptor + Telemetry → dispatch → completed.r>  r   zfull pipeline testr   Nr   r   )r   outputr   r   r   r   r   r   r   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}rW   )rd   rf   rg   )r	   r   r   r?  r   r   r/   rR   r   r   r   execute_postrk   r   rm   rn   ro   rW   ri   rj   rl   )r   r   r7  r  enrichedtask_resultr   rq   r   rr   r   r   s               r   *test_end_to_end_dispatch_with_interceptorsz;TestFullPipeline.test_end_to_end_dispatch_with_interceptors  s     !" ,-\\#y) 	<NN?,-NN3  !56G!$TZZ\!2GI"..w77H $I.",,x4%K
 $$[(;;;	<" 8$33$3333$333$3333333333*95656666666666666656666666666 8 <	< 	<sB   +HA#HG<2HG?HD4H<H?HHHc                   K   t               }|j                  t        ddd             |j                  t        ddd             dd	i}|j                  |       d
{   }|j                  }d} ||      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d
x}x}x}x}}|j                  }d} ||      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d
x}x}x}x}}y
7 w)zMMultiple interceptors all contribute enrichments; result carries all of them.
enriched_avalue_arN   r   
enriched_bvalue_br   r   zmulti-enrichmentNr   r   r$   r   r   r   )r	   r   rC   r   r   rk   r   ri   rj   rl   rm   rn   ro   )r   r   r  r$   r   rq   r   r   r   r   r   s              r   2test_dispatch_with_multiple_enriching_interceptorszCTestFullPipeline.test_dispatch_with_multiple_enriching_interceptors  s     !",\9rRS,\9rRS/0((11zz4,4z,'494'94444'9444444v444v444z444,444'44494444444zz4,4z,'494'94444'9444444v444v444z444,444'444944444444 2s   AI$I! HI$c                   K   t               }|j                  t                      ddd}t        d      }|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}}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                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |	      dz  }
t        t        j                  |
            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7 pw)zPexecute_error returns a correction payload from the first handler that succeeds.zerr-testz
will errorr=  ztest failureNr  r  r   r   r   r   r`   ra   r@   rc   r+   r   r   r   )r	   r   r   r   execute_errorrk   r   ri   rj   rl   rm   rn   ro   ra   r@   )r   r   r  r+   r   r   r   r   r   rq   rr   r   s               r   +test_error_chain_returns_correction_payloadz<TestFullPipeline.test_error_chain_returns_correction_payload  s     !"()(LA^, ..ug>>
 "&%z%%%%z%%%%%%z%%%z%%%%%%%%%%*d++++++++z+++z++++++*+++*++++++d+++d++++++++++$w*$$$$w*$$$w$$$$$$*$$$*$$$$$$$ ?s   A	J>J;I0J>c                   K   t               }ddd}|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  }d
d|iz  }t        t        j                  |            d}y7 ԭw)z7An empty chain's execute_pre returns the payload as-is.zempty chainxr   Nr   )z%(py0)s == %(py2)sr$   r  r*  r+  rg   )
r	   r   rk   r   ri   rj   rl   rm   rn   ro   )r   r   r  r$   r   r,  rr   s          r   6test_empty_chain_execute_pre_returns_payload_unchangedzGTestFullPipeline.test_empty_chain_execute_pre_returns_payload_unchanged  s      !"*s;((11    v      v   v                 2s   $C=C;CC=c                 f  K   t               }|j                  t        d      i        d{   }|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7 w)z?An empty chain's execute_error returns unhandled=True sentinel.zno handlersN	unhandledTr   )zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)sr$   r   r   r   )r	   r^  r   r   rk   r   ri   rj   rl   rm   rn   ro   r   s
             r   9test_empty_chain_execute_error_returns_unhandled_sentinelzJTestFullPipeline.test_empty_chain_execute_error_returns_unhandled_sentinel  s      !"**<+FKKzz.+.z+&.$.&$....&$......v...v...z...+...&...$........ Ls   )D1D.DD1c                   K   t        t              }t        ddg       }t        |       t        t              }d}||z   }||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                  t              rt	        j                  t              ndt	        j                  |      d	t        j                         v st	        j                  |      rt	        j                  |      nd	t	        j                  |      d
z  }dd|iz  }t        t	        j                  |            dx}x}x}}t        j                  d       t        t              }||k(  }|s+t	        j
                  d|fd||f      dt        j                         v st	        j                  t               rt	        j                  t               nddt        j                         v st	        j                  t              rt	        j                  t              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}}yw)z@register_interceptor() adds to GLOBAL_CHAIN (not a fresh chain).__integration_test_sentinel__i  )r   r   r   r   r   )z<%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == (%(py5)s + %(py7)s)r   r   before)rd   re   r   r   r  zassert %(py10)spy10N)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)s)rd   re   r   r   zassert %(py7)sr  )r   r   r   r   rk   r   ri   rj   rl   rm   rn   ro   r   )r   rh  sentinelr   r"  r   r   r   @py_format11r   r#  s              r   <test_register_interceptor_global_helper_adds_to_global_chainzMTestFullPipeline.test_register_interceptor_global_helper_adds_to_global_chain  s     \",0

 	X&< .Q.FQJ. J.... J......s...s......<...<... ......F...F...Q....... ?@< * F**** F******s***s******<***<*** ******F***F*******s   K*K,N)r:   r;   r<   r=   r[   r  r   rV  r\  r_  rb  re  rl  r&   r   r   rP  rP    s    W[[7 74 [[
5 
5 [[% % [[! ! [[/ / [[+ +r   rP  )+r=   builtinsri   _pytest.assertion.rewrite	assertionrewriterk   r   sysrR   unittest.mockr   r   r   pathlibr   pathinsertr[   pytest_asynciocore.interceptorsr   r   r	   r
   r   r   %core.interceptors.execution_telemetryr   'core.interceptors.integration_contractsr   r   rC   r/   boolrW   rY   r}   r   r   r  r5  rP  r&   r   r   <module>r{     s       
  5 5  * +    P C" "*"O "*3 4  >9/ 9/@&( &(ZL/ L/f%- %-X?! ?!LV+ V+r   