
    ui24                        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 ddlmZmZmZmZmZ e	j$                  j'                  dd       d Zd Zd Zd	 Zd
 Zd Zd Zd Zd Zd Zedk(  rp ed        ed        ed        e         e         e         e         e         e         e         e         e         ed        ed        ed       yy)u  
Tests for Story 2.06 (Track B): JITHydrationInterceptor — Wires Hydration Into Chain

Black-box tests:
  BB1: After pre_execute, payload has "system_injection" with "<ZERO_AMNESIA_STATE>"
  BB2: On hydration error → payload has system_injection with ERROR tag
  BB3: on_correction payload has "CORRECTION: " prefix in prompt
  BB4: on_error returns dict with error envelope

White-box tests:
  WB1: Priority == 10 (verify metadata.priority == 10)
  WB2: post_execute does NOT mutate the result dict
  WB3: post_execute logs to events.jsonl (mock file write)
  WB4: metadata.name == "jit_hydration"
  WB5: on_correction without "prompt" key doesn't crash

All mocked — no external I/O.
    NPath)	AsyncMock	MagicMockpatch	mock_opencallz/mnt/e/genesis-systemc                 H    t        j                         j                  |       S )z/Execute a coroutine synchronously for test use.)asyncioget_event_looprun_until_complete)coros    6/mnt/e/genesis-system/tests/track_b/test_story_2_06.py_runr   !   s    !!#66t<<    c                     ddl m}  dt        dt        fd} |        }ddd}t        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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}}d}|d   }	||	v }|st        j                  d|fd||	f      t        j                  |      t        j                  |	      dz  }
t        j                  d      dz   d|
iz  }t        t        j                  |            dx}x}}	|d   }d}	||	k(  }|st        j                  d|fd||	f      t        j                  |      t        j                  |	      dz  }
t        j                  d      dz   d|
iz  }t        t        j                  |            dx}x}}	t        d       y# 1 sw Y   xY w)zSBB1: After pre_execute, payload has 'system_injection' with '<ZERO_AMNESIA_STATE>'.r   JITHydrationInterceptorpayloadreturnc                    K   d| d<   | S w)NzQ<ZERO_AMNESIA_STATE><WORKING_CONTEXT>state</WORKING_CONTEXT></ZERO_AMNESIA_STATE>system_injection r   s    r   mock_hydrationzFtest_bb1_pre_execute_attaches_system_injection.<locals>.mock_hydration.   s     &y"#   
t1zDo somethingtask_idprompt?core.memory.jit_hydration_interceptor.interceptor_jit_hydrationside_effectNr   inz%(py1)s in %(py3)sresultpy1py3z)BB1: system_injection key must be present
>assert %(py5)spy5z<ZERO_AMNESIA_STATE>z%(py1)s in %(py4)sr)   py4z9BB1: system_injection must contain '<ZERO_AMNESIA_STATE>'
>assert %(py6)spy6r   ==z%(py1)s == %(py4)sz$BB1: original keys must be preserveduN   BB1 PASSED — pre_execute attaches system_injection with <ZERO_AMNESIA_STATE>%core.memory.jit_hydration_interceptorr   dictr   r   pre_execute
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_name_format_assertmsgAssertionError_format_explanationprint)r   r   interceptorr   r'   @py_assert0@py_assert2@py_format4@py_format6@py_assert3@py_format5@py_format7s               r   .test_bb1_pre_execute_attaches_system_injectionrK   *   s   Md t  *+K.9G	I"
 8 k--g67	8 T'TTTTTTTTTTTTTTTTTTT)TTTTTTT! DV,>%? D!%?? D2C2CD!%? D D:C) " D D:C) &@ D D2C2CCD D D0C0CD D)LL$LLLLLLLLLLLL&LLLLLLLL	
Z[8 8s   IIc                     ddl m}  dt        dt        fd} |        }ddd}t        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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}}d}|d   }	||	v }|st        j                  d|fd||	f      t        j                  |      t        j                  |	      dz  }
t        j                  d      dz   d|
iz  }t        t        j                  |            dx}x}}	d}|d   }	||	v }|st        j                  d|fd||	f      t        j                  |      t        j                  |	      dz  }
t        j                  d      dz   d|
iz  }t        t        j                  |            dx}x}}	t        d       y# 1 sw Y   xY w)zHBB2: When interceptor_jit_hydration raises, payload gets ERROR envelope.r   r   r   r   c                     K   t        d      w)NzRedis offline)RuntimeErrorr   s    r   failing_hydrationzKtest_bb2_hydration_error_produces_error_envelope.<locals>.failing_hydrationK   s     ?++s   t_errz	some taskr   r!   r"   Nr   r$   r&   r'   r(   z/BB2: system_injection must be set even on errorr+   r,   <ERROR>r-   r.   zCBB2: system_injection must contain <ERROR> tag on hydration failurer0   r1   zHydration failedz3BB2: system_injection must state 'Hydration failed'uM   BB2 PASSED — hydration error produces ERROR envelope, execution not blockedr5   )r   rO   rC   r   r'   rD   rE   rF   rG   rH   rI   rJ   s               r   0test_bb2_hydration_error_produces_error_enveloperR   G   s   M, ,$ , *+K![9G	I%
 8 k--g67	8 Z'ZZZZZZZZZZZZZZZZZZZ)ZZZZZZZ N12 N922 N<M<MN92 N NDMI  N NDMI 3 N N<M<MMN N N:M:MN N >(:!; >!;; >,=,=>!; > >4=I  > >4=I "< > >,=,==> > >*=*=> > 

YZ8 8s   IIc                     ddl m}  dt        dt        fd} |        }ddd}t        d	|
      5  t	        |j                  |            }ddd       d   }|j                  }d} ||      }|st        j                  d|d   dd        dz   t        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }	t        t        j                  |	            dx}x}x}}d}|d   }
||
v }|st        j                  d|fd||
f      t        j                  |      t        j                  |
      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}
d}||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}}t!        d       y# 1 sw Y   xY w) zDBB3: on_correction should prepend 'CORRECTION: ' to existing prompt.r   r   r   r   c                    K   d| d<   | S w)NzU<ZERO_AMNESIA_STATE><WORKING_CONTEXT>corrected</WORKING_CONTEXT></ZERO_AMNESIA_STATE>r   r   r   s    r   r   zItest_bb3_on_correction_prepends_correction_prefix.<locals>.mock_hydrationh        &}"#r   t_corrzoriginal prompt textr   r!   r"   Nr    CORRECTION: z1BB3: prompt must start with 'CORRECTION: ', got:    zN
>assert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.startswith
}(%(py5)s)
})r)   r*   r,   py7r$   r-   r.   z8BB3: original prompt text must be preserved after prefixr0   r1   r   r&   r'   r(   z5BB3: system_injection must be set after on_correctionr+   r,   uN   BB3 PASSED — on_correction prepends 'CORRECTION: ' to prompt and re-hydrates)r6   r   r7   r   r   on_correction
startswithr9   r?   r;   r@   rA   r:   r<   r=   r>   rB   )r   r   rC   r   r'   rD   rE   @py_assert4@py_assert6@py_format8rH   rI   rJ   rF   rG   s                  r   1test_bb3_on_correction_prepends_correction_prefixr_   d   s   Md t  *+K".DEG	I"
 : k//89	: ( T&& T~ T&~6 T6 TBSBS
;F8<LSb<Q;RST TJS)  T TJS) ' T TJS) (6 T TJS) 7 T T T@S@ST T T! CVH%5 C!%55 C1B1BC!%5 C C9B " C C9B &6 C C1B1BBC C C/B/BC C @' @.?.?@ @ @6?i  @ @9?@ @'?'? "( @ @6?i "( @ @.?.??@ @ @,?,?@ @ 

Z[: :s   I''I1c                  	   ddl m}   |        }t        d      }ddd}t        |j	                  ||            }t        |t              }|s!t        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
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  }	t        j                  d      dz   d|	iz  }
t        t        j                  |
            dx}}d}|d   }||v }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}d}||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}}d}|d   }||v }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}t!        d        y)!zTBB4: on_error returns dict with 'error', 'task_payload', and error system_injection.r   r   zsomething broke	t_onerrorz	task textr   z BB4: on_error must return a dictz7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancer'   r7   )py0r)   py2r/   Nerrorr$   r&   r(   z!BB4: result must have 'error' keyr+   r,   r-   r.   z7BB4: result['error'] must contain the exception messager0   r1   task_payloadz(BB4: result must have 'task_payload' keyr   z,BB4: result must have 'system_injection' keyrQ   z.BB4: system_injection must contain <ERROR> tagu8   BB4 PASSED — on_error returns dict with error envelope)r6   r   
ValueErrorr   on_errorrb   r7   r9   r?   r<   r=   r>   r;   r@   rA   r:   rB   )r   rC   excr   r'   rH   rI   rD   rE   rF   rG   rJ   s               r   (test_bb4_on_error_returns_error_enveloperj      s/   M)+K
&
'C%=G+&&sG45Ffd#G#GG%GGGGGGG:GGG:GGGGGGfGGGfGGGGGGdGGGdGGG#GGGGGGA7fAAA7fAAA7AAAAAAfAAAfAAAAAAAAAAA Bw B/ B0A0AB B B8A	  B B8A	 !0 B B0A0AAB B B.A.AB BO>V#OOO>VOOO>OOOOOOVOOOVOOOO%OOOOOOOW'WWWWWWWWWWWWWWWWWWW)WWWWWWW 912 9922 9'8'8992 9 9/8y  9 9/8y 3 9 9'8'889 9 9%8%89 9 

DEr   c                  b   ddl m}   |        }|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  }t	        j                  d|j                  j                         d	z   d
|iz  }t        t	        j                  |            dx}x}x}}t        d       y)z=WB1: JITHydrationInterceptor.metadata.priority must equal 10.r   r   
   r2   )zN%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.metadata
}.priority
} == %(py7)srC   rc   rd   r/   rY   z(WB1: Expected priority=10, got priority=
>assert %(py9)spy9Nu&   WB1 PASSED — metadata.priority == 10)r6   r   metadatapriorityr9   r:   r<   r=   r>   r;   r?   r@   rA   rB   r   rC   @py_assert1rH   r]   @py_assert5r^   @py_format10s           r   test_wb1_priority_is_10rv      s0   M)+K S(( SB S(B. SARARS(B S SLRFS S:R:R  S SIR  S SIR   S SIR ) S SIR -/ S SARAR
2;3G3G3P3P2QRS S S?R?RS S S 

23r   c                  .   ddl m}   |        }ddd}t        |      }ddd}t        d	t	                     5  t        d
      5 }t               |_        d |_        t        |j                  ||             ddd       ddd       ||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                   d| d|       dz   d|iz  }t#        t        j$                  |            d}t'        d       y# 1 sw Y   	xY w# 1 sw Y   xY w)zDWB2: post_execute must not add, remove, or change any key in result.r   r   zagent answerok)outputstatust_wb2zM<ZERO_AMNESIA_STATE><WORKING_CONTEXT>x</WORKING_CONTEXT></ZERO_AMNESIA_STATE>r   r   builtins.open0core.memory.jit_hydration_interceptor.EVENTS_DIRc                     t        d      S Nz/tmp/events.jsonlr   selfothers     r   <lambda>z>test_wb2_post_execute_does_not_mutate_result.<locals>.<lambda>       48K3L r   Nr2   )z%(py0)s == %(py2)sresult_beforeresult_snapshot)rc   rd   z1WB2: post_execute must not mutate result. Before=z, After=z
>assert %(py4)sr/   u7   WB2 PASSED — post_execute does not mutate result dict)r6   r   r7   r   r   r   mkdir__truediv__r   post_executer9   r:   r<   r=   r>   r;   r?   r@   rA   rB   )	r   rC   r   r   rf   mock_dirrs   @py_format3rI   s	            r   ,test_wb2_post_execute_does_not_mutate_resultr      s   M)+K->M=)OkL
 
		, D	A	BDFN"L[%%m\BC	D D O+ eSdSde=O e e^d^de eLdLd  e e[d[d  e e^d^de eLdLd , e e[d[d , e eSdSd
;O;LHUbTcde e eQdQde e 

CDD D D Ds#   F
3E=6F
=F	F

Fc                  \	   ddl m}   |        }ddd}ddi}g t               }fd|j                  j                  j                  _        t        d	|      5  t        d
      5 }t               |_        d |_	        t        |j                  ||             ddd       ddd       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}}t-        j.                  d         }|d   }d}||k(  }|st        j                  d|fd||f      t        j$                  |      t        j$                  |      dz  }t        j&                  d      dz   d|iz  }	t)        t        j*                  |	            dx}x}}|d   }d}||k(  }|st        j                  d|fd||f      t        j$                  |      t        j$                  |      dz  }t        j&                  d      dz   d|iz  }	t)        t        j*                  |	            dx}x}}d }||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}}t1        d*       y# 1 sw Y   xY w# 1 sw Y   xY w)+zIWB3: post_execute writes a JSON line to events.jsonl with correct fields.r   r   t_wb3z5<ZERO_AMNESIA_STATE>some content</ZERO_AMNESIA_STATE>r|   ry   donec                 &    j                  |       S )N)append)datawritten_liness    r   r   z<test_wb3_post_execute_logs_to_events_jsonl.<locals>.<lambda>   s    }?S?STX?Y r   r}   r~   c                     t        d      S r   r   r   s     r   r   z<test_wb3_post_execute_logs_to_events_jsonl.<locals>.<lambda>   r   r   N   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenr   )rc   r)   r*   r1   z.WB3: post_execute must write at least one linez
>assert %(py8)spy8
event_typejit_hydration_completer2   r4   r.   z0WB3: event_type must be 'jit_hydration_complete'r0   r1   r   z'WB3: task_id must match payload task_idinjection_lengthr$   r&   written_jsonr(   z.WB3: event must include injection_length fieldr+   r,   	timestampz'WB3: event must include timestamp fielduC   WB3 PASSED — post_execute logs correct JSON event to events.jsonl)r6   r   r   return_value	__enter__writer   r   r   r   r   r   r   r9   r:   r<   r=   r>   r;   r?   r@   rA   jsonloadsrB   )r   rC   rf   r'   mr   rE   rt   r\   rJ   @py_format9r   rD   rH   rI   rF   rG   r   s                    @r   *test_wb3_post_execute_logs_to_events_jsonlr      s   M)+KSL FMA2YANN))/		" =	A	B=FN"L[%%fl;<	= = }TT"TTTTTTTTT3TTT3TTTTTT}TTT}TTTTTTTTT$TTTTTTTT::mA./L% ;)A ;%)AA ;):):;%)A ; ;1: & ; ;1: *B ; ;):)::; ; ;':':; ;	" 2g 2"g- 2 1 12"g 2 2(1	 # 2 2(1	 '. 2 2 1 112 2 2112 2 9- 9'8'89 9 9/8y  9 928&9 9 8 8 ". 9 9/8y ". 9 9'8'889 9 9%8%89 9 2;,& 2 1 12;, 2 2(1	  2 2+162 211 ' 2 2(1	 ' 2 2 1 112 2 2112 2 

OP#= = = =s$   R!$3RR!R	R!!R+c                  d   ddl m}   |        }|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  }t	        j                  d|j                  j                   d	      d
z   d|iz  }t        t	        j                  |            dx}x}x}}t        d       y)z+WB4: metadata.name must be 'jit_hydration'.r   r   jit_hydrationr2   )zJ%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.metadata
}.name
} == %(py7)srC   rm   z.WB4: Expected name='jit_hydration', got name=''rn   ro   Nu/   WB4 PASSED — metadata.name == 'jit_hydration')r6   r   rp   namer9   r:   r<   r=   r>   r;   r?   r@   rA   rB   rr   s           r   'test_wb4_metadata_name_is_jit_hydrationr      s3   M)+K V$$ V V$7 VDUDUV$ V VOUvV V=U=U  V VLUI  V VLUI   V VLUI % V VLUI )8 V VDUDU
89M9M9R9R8SSTUV V VBUBUV V V 

;<r   c                     ddl m}  dt        dt        fd} |        }ddd}t        d	|
      5  	 t	        |j                  |            }	 ddd       g }d}|v}|}	|s4|j                  }
d}d} |
||      }|j                  }d} ||      }| }|}	|	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  }|j!                  |       |sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  
      t        j                        t        j                        t        j                        t        j                        t        j                        t        j                        dz  }|j!                  |       t        j"                  |d      i z  }t        j$                  d      dz   d|iz  }t        t        j&                  |            dx}	x}x}x}x}
x}x}x}x}x}x}}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}	}t)        d#       y# t        $ r}t        d|       d}~ww xY w# 1 sw Y   xY w)$zNWB5: on_correction with no 'prompt' key must not raise and must still hydrate.r   r   r   r   c                    K   d| d<   | S w)NzU<ZERO_AMNESIA_STATE><WORKING_CONTEXT>no-prompt</WORKING_CONTEXT></ZERO_AMNESIA_STATE>r   r   r   s    r   r   zAtest_wb5_on_correction_no_prompt_key_safe.<locals>.mock_hydration  rU   r   
t_nopromptztask without explicit prompt)r   descriptionr!   r"   zAWB5: on_correction must not raise when 'prompt' key absent. Got: Nr     rW   )not in)z%(py3)s not in %(py5)sr'   )r*   r,   z%(py7)srY   znot %(py23)s
{%(py23)s = %(py19)s
{%(py19)s = %(py17)s
{%(py17)s = %(py11)s
{%(py11)s = %(py9)s.get
}(%(py13)s, %(py15)s)
}.startswith
}(%(py21)s)
})ro   py11py13py15py17py19py21py23r   zEWB5: Should not add 'CORRECTION: ' prefix when no 'prompt' key existsz
>assert %(py27)spy27r   r$   r&   r(   zAWB5: system_injection must still be set even without 'prompt' keyr+   r,   uR   WB5 PASSED — on_correction without 'prompt' key safe, system_injection still set)r6   r   r7   r   r   rZ   	Exceptionr@   getr[   r9   r:   r;   r<   r=   r>   r   _format_boolopr?   rA   rB   )r   r   rC   r   r'   ers   rE   r\   rD   @py_assert10@py_assert12@py_assert14@py_assert16@py_assert18@py_assert20@py_assert22@py_assert24rG   r^   @py_format25@py_format26@py_format28rF   s                           r   )test_wb5_on_correction_no_prompt_key_safer     s   Md t  *+K&7UVG	I"
 		+33G<=F	P8 P86! P PH Pb PHb)A P)A)L)L P^ P)L^)\ P)\%\ P%\ P P>O>OP86 P PFOi  P PIOP P7O7O " P PFOi " P P PIOPIOP PIOP P7O7O *0 P PFOi *0 P PFOi *4 P PFOi 5= P PFOi ?A P PFOi *B P PFOi *M P PFOi N\ P PFOi *] P PIOPIOPAOP P>O>OOP P P<O<OP P P P P L' L:K:KL L LBK)  L LEKVL L3K3K "( L LBK) "( L L:K:KKL L L8K8KL L 

^_  	 STUSVW 		 	s(   ML==	MMMMM&__main__zA=================================================================u,   Story 2.06 — JITHydrationInterceptor Testsu+   ALL 9 TESTS PASSED — Story 2.06 (Track B)) __doc__builtinsr<   _pytest.assertion.rewrite	assertionrewriter9   r   r   syspathlibr   unittest.mockr   r   r   r   r	   pathinsertr   rK   rR   r_   rj   rv   r   r   r   r   __name__rB   r   r   r   <module>r      s   $    
  F F * +=\:[:\>F4	4 E8!QP	= `D z	(O	
89	(O244657,.02.0+--/	(O	
78	(O# r   