
    i              	      Z   U d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlmZ ddlZe
j                  j!                  d e ee      j'                         j(                  j(                               ddlmZmZmZ ddlmZ ddlmZ 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#ddl$m$Z%m&Z'  e%dddddde'jP                        Z)de*d<   ddddd'dZ+d  Z,d! Z-d" Z.e/d#k(  r& e0d$        e,         e-         e.         e0d%       yy)(a  
Phase C2a integration tests: Orchestrator + Reconciler wiring.

3 tests against in-memory orchestrator with a stub reconciler.

  1. orchestrator runs watchdog every N iterations (cadence honored)
  2. orchestrator without reconciler doesn't crash, doesn't call watchdog
  3. orchestrator continues running when watchdog raises (failure isolation)

Run:
    cd ~/apex_v16
    python tests/test_orchestrator_phase_c2a.py
    )annotationsN)Path)RuntimeConfigRunModeAccountKind)Orchestrator)SessionStatec                     t        d|         y )Nz  ok  )print)labels    8/home/work/apex_v16/tests/test_orchestrator_phase_c2a.py_okr      s    	F5'
    c                      e Zd ZddZy)FakeAINc                *   K   ddl m}  |d d      S w)Nr   )
AIResponseunknown)text
error_kind)brain.ai_clientr   )selfprompttemperature
max_tokensr   s        r   askz
FakeAI.ask'   s     .t	::s   )g?N)__name__
__module____qualname__r    r   r   r   r   &   s    ;r   r   c                      e Zd Zd Zd Zy)	JsonlSinkc                    g | _         y N)eventsr   s    r   __init__zJsonlSink.__init__-   s	    r   c                B    | j                   j                  d|i|       y )Nevent)r%   appendr   r)   fieldss      r   writezJsonlSink.write/   s    GU5f56r   N)r   r   r   r'   r-   r    r   r   r"   r"   ,   s    7r   r"   c                  *    e Zd Zd Zd Zd Zd Zd Zy)
FakeLoggerc                    dd l }t               | _        t               | _        t               | _        |j                  d      | _        y )Nr   ztest.c2a)loggingr"   	brain_logsession_log	error_log	getLoggersystem)r   r1   s     r   r'   zFakeLogger.__init__4   s3    "$;"''
3r   c                >     | j                   j                  |fi | y r$   )r3   r-   r+   s      r   log_session_eventzFakeLogger.log_session_event:   s    u//r   c                B     | j                   j                  d||d| y )N)whereerror)r;   )r4   r-   )r   r:   r;   extras       r   	log_errorzFakeLogger.log_error<   s     HEH%Hr   c                <     | j                   j                  di | y )N)trade_openedr2   r-   r   r,   s     r   log_trade_openedzFakeLogger.log_trade_opened>       6v6r   c                <     | j                   j                  di | y )N)trade_closedr@   rA   s     r   log_trade_closedzFakeLogger.log_trade_closed@   rC   r   N)r   r   r   r'   r8   r=   rB   rF   r    r   r   r/   r/   3   s    40I77r   r/   c                      e Zd Zd Zy)FakeProviderc                :   K   t        j                  g d      S w)N)openhighlowclosevolume)columns)pd	DataFrame)r   symbol	timeframens       r   get_barszFakeProvider.get_barsE   s     ||$NOOs   N)r   r   r   rU   r    r   r   rH   rH   D   s    Pr   rH   c                      e Zd Zd Zy)_MemoryStorec                     y r$   r    )r   states     r   savez_MemoryStore.saveJ   s    r   N)r   r   r   rZ   r    r   r   rW   rW   I   s    r   rW   c                  &    e Zd ZdZdddZd Zd Zy)FakeReconcilerz=Counts watchdog/startup calls. Optionally raises in watchdog.c                .    d| _         d| _        || _        y )Nr   )startup_callswatchdog_calls_raise)r   raise_in_watchdogs     r   r'   zFakeReconciler.__init__O   s    'r   c                6   K   | xj                   dz  c_         y w)N   )r^   r&   s    r   reconcile_startupz FakeReconciler.reconcile_startupT   s     as   c                d   K   | xj                   dz  c_         | j                  rt        d      y w)Nrc   zwatchdog boom)r_   r`   RuntimeErrorr&   s    r   watchdog_naked_positionsz'FakeReconciler.watchdog_naked_positionsX   s,     q ;;//s   .0N)F)ra   bool)r   r   r   __doc__r'   rd   rg   r    r   r   r\   r\   M   s    G(
r   r\   )datetimetimezonei           )tzinfo_dtFIXED_DAY_UTC   
reconcilermax_iterationseveryc                   t        t        j                  t        j                        }dg|_        d|_        d|_        d|_        ||_	        t        |t               t               t               t               t               i d | d |      S )N)modeaccountMESg        r   c                     t         S r$   )rq   r    r   r   <lambda>zmake_orch.<locals>.<lambda>t   s     r   )config	ai_clientmarket_data_providerrY   storeloggerbrain_dispatchbrokerrt   now_utc_providerru   )r   r   PAPERr   
INELIGIBLEasset_filterscan_loop_phase_offset_secondsmanage_loop_interval_seconds!maintenance_loop_interval_secondsreconcile_interval_iterationsr   r   rH   r	   rW   r/   )rt   ru   rv   cfgs       r   	make_orchr   g   sv    
W]]K4J4J
KCwC),C&'(C$,-C)(-C%fh)^nLN:<$.% r   c                 f   t               } t        | dd      }t        j                  |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                  |      dz  }t        j                  d| j                         d	z   d
|iz  }t        t        j                  |            dx}x}}t        d       y)z:V16 3-loop: watchdog fires every N maintenance_loop iters.rl   rr   rs   ==z6%(py2)s
{%(py2)s = %(py0)s.watchdog_calls
} == %(py5)srecpy0py2py5z/expected 2 watchdog calls (iters 2 and 4), got 
>assert %(py7)spy7Nu3   watchdog: V16 cadence — every N maintenance ticks)r\   r   asynciorunr_   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationr   )r   orch@py_assert1@py_assert4@py_assert3@py_format6@py_format8s          r   (test_watchdog_cadence_every_n_iterationsr   }   s   

C AQ?DKK
 O O" O=N=NO O OHNO O6N6N  O OENY  O OENY  O OENY "# O O=N=N
9#:L:L9MNO O O;N;NO O=>r   c                    t        ddd      } 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                  |      d	z  }t        j                  d
|       dz   d|iz  }t        t        j                  |            dx}}t        d       y)z@reconciler=None -> orchestrator runs cleanly across all 3 loops.N   rr   rs   r   r   z%(py0)s == %(py3)srcr   py3z orchestrator must return 0, got 
>assert %(py5)sr   z2no reconciler: orchestrator runs cleanly, no crash)r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   @py_assert2r   @py_format4r   s         r   0test_no_reconciler_doesnt_call_watchdog_or_crashr      s    Qa@D	TXXZ	 B;27;;;2;;;;;;2;;;2;;;;;;6rd;;;;;;;<=r   c                    t        d      } t        | dd      }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                  |      d
z  }t	        j                  d      dz   d|iz  }t        t	        j                  |            dx}}| 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                  |      dz  }t	        j                  d| j                         dz   d|iz  }	t        t	        j                  |	            dx}x}}t        d       y)z;watchdog raising -> warning logged, orchestrator continues.T)ra   rl   rr   rs   r   r   r   r   r   z4orchestrator must keep running after watchdog raisesr   r   Nr   r   r   z0watchdog called both ticks despite raising, got r   r   z:watchdog: exception isolated, loop continues to completion)r\   r   r   r   r   r   r   r   r   r   r   r   r   r_   r   )
r   r   r   r   r   r   r   r   r   r   s
             r   'test_watchdog_failure_doesnt_break_loopr      s   
4
0CAQ?D	TXXZ	 BJ27JJJ2JJJJJJ2JJJ2JJJJJJJJJJJJJ P P" P>O>OP P PIOP P7O7O  P PFOi  P PFOi  P PFOi "# P P>O>O
:3;M;M:NOP P P<O<OP PDEr   __main__ztest_orchestrator_phase_c2a.pyzALL 3 TESTS PASSED)r   strreturnNone)r   r   )1ri   
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r   syspathlibr   pandasrP   pathinsertr   __file__resolveparentcore.configr   r   r   orchestratorr   persistence.state_storer	   r   r   r"   r/   rH   rW   r\   rj   rp   rk   _tzutcrq   __annotations__r   r   r   r   r   r   r    r   r   <module>r      s   #    
   3tH~--/66==> ? ; ; % 0; ;7 77 7"P P
    , 6q"b!Qsww?s ? !! ,	?>F z	
*+,.46+-	
 r   