import time
import os 
import sys 
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'src'))
from core.agent import EmoCoreAgent
def test_time_decay_reduces_budget():
    agent = EmoCoreAgent()
    
    # Needs positive pressure to generate positive budget to decay from
    # With 0.0 state defaults, budget might be 0.0
    r1 = agent.step(reward=0.0, novelty=1.0, urgency=1.0)
    
    time.sleep(0.2)
    # Step again with same inputs -> State accumulates -> Budget should go UP from governance
    # BUT we want to test decay. 
    # Decay happens in the step. 
    # If we want to verify decay reduced the *output* compared to non-decayed?
    # Or just that it's lower than previous if inputs were 0?
    
    # If inputs are 0, state is constant (no integration).
    # If state constant, governance output constant.
    # Governance output - decay.
    # If dt > 0, decay > 0. 
    # So r2 should be same base - decay.
    # r1 was same base - tiny decay.
    # No, wait. 
    # r1: t0. dt=small.
    # r2: t0+0.2. dt=0.2.
    # Governance output is identical for both if state is 0.0.
    # So r2 budget = base - decay(0.2).
    # r1 budget = base - decay(small).
    # Thus r2 < r1.
    
    # HOWEVER, default state is 0.0. 
    # Governance W * 0.0 = 0.0.
    # Budget is 0.0. 
    # 0.0 - decay = 0.0 (max(0, ...)).
    # So assertion fails 0.0 < 0.0.
    
    # Fix: Inject pressure first to get budget > 0.
    
    # Inject pressure manually or via step
    # 1. Step with high impact
    r0 = agent.step(reward=1.0, novelty=1.0, urgency=1.0)
    
    # Now state has values. Budget > 0.
    # Now wait
    time.sleep(0.2)
    
    # Step with 0 delta (so state remains same-ish, actually integrate({}) adds 0)
    r_decayed = agent.step(reward=0.0, novelty=0.0, urgency=0.0)
    
    # Compare with what it would be without wait?
    # Hard to compare across steps since state changed.
    
    # Alternative:
    # r_decayed computation uses dt=0.2.
    # We can check if it applied decay.
    # But we can't inspect internal calculation easily.
    
    # Let's rely on the fact that persistence decays.
    # If we have high persistence, then wait, then step, it should be lower than strict governance output?
    # Or simply:
    # Can we get Y?
    # agent.engine.governance.compute(agent.engine.state, dt=0.0).
    
    # Force state to valid nonzero
    from core.state import PressureState
    agent.engine.state = PressureState(confidence=1.0, arousal=1.0)
    
    # Step with dt > 0 (via sleep + step)
    time.sleep(0.2)
    r_decayed = agent.step(0,0,0)
    
    # Compute baseline
    gov_budget = agent.engine.governance.compute(agent.engine.state, dt=0.0)
    
    # Verify decay
    assert r_decayed.budget.persistence < gov_budget.persistence
def test_recovery_happens_over_time():
    """
    Test that recovery increases effort/persistence ONLY when in RECOVERING mode.
    
    New invariant: Recovery occurs ONLY when mode == RECOVERING.
    To trigger RECOVERING, effort or persistence must drop below 0.3.
    """
    from core.modes import Mode
    
    core = EmoCoreAgent()
    
    # Drive effort down by running multiple steps with zero/negative input
    # This accumulates frustration and reduces effort via governance
    for _ in range(10):
        r = core.step(-0.5, 0.0, 0.0)
    
    # Check we're in or approaching RECOVERING mode
    # If not yet recovering, continue until we are
    while r.mode != Mode.RECOVERING and not r.halted:
        r = core.step(-0.5, 0.0, 0.0)
        if r.halted:
            # If we halted, test can't proceed - this is acceptable
            return
    
    e_before_recovery = r.budget.effort
    
    # Wait for recovery delay and step again
    time.sleep(0.6)  # BALANCED profile has recovery_delay=0.5
    
    r_after = core.step(0.0, 0.0, 0.0)
    
    # In RECOVERING mode with dt >= recovery_delay, effort should increase
    # (bounded by stable budget and recovery cap)
    if r_after.mode == Mode.RECOVERING and not r_after.halted:
        assert r_after.budget.effort >= e_before_recovery, \
            f"Recovery should increase effort: {r_after.budget.effort} >= {e_before_recovery}"
