File size: 3,951 Bytes
5c4e77e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""Session 11 - Perception subagent tests (deterministic Python; no LLM).

Per cortex/CLAUDE.md binding (Perception is pure Python) and Phase A
Decisions 9 (V2 KeyError) + 63 (salient_signals cap at 5).
"""

from __future__ import annotations

from typing import Iterable

import pytest

from cortex.schemas import PerceptionReport
from cortex.subagents import perception_for
from CrisisWorldCortex.models import (
    CrisisworldcortexObservation,
    LegalConstraint,
    RegionTelemetry,
    ResourceInventory,
    Restriction,
)


def _make_obs(
    cases_per_region: Iterable[int] = (5, 1, 0, 0),
    hospital_loads: Iterable[float] = (0.7, 0.1, 0.1, 0.1),
    test_kits: int = 200,
    hospital_beds_free: int = 50,
    mobile_units: int = 2,
    vaccine_doses: int = 300,
    restrictions: Iterable[Restriction] = (),
    legal_constraints: Iterable[LegalConstraint] = (),
) -> CrisisworldcortexObservation:
    cases = list(cases_per_region)
    loads = list(hospital_loads)
    return CrisisworldcortexObservation(
        regions=[
            RegionTelemetry(
                region=f"R{i + 1}",
                reported_cases_d_ago=cases[i],
                hospital_load=loads[i],
                compliance_proxy=0.85,
            )
            for i in range(4)
        ],
        resources=ResourceInventory(
            test_kits=test_kits,
            hospital_beds_free=hospital_beds_free,
            mobile_units=mobile_units,
            vaccine_doses=vaccine_doses,
        ),
        active_restrictions=list(restrictions),
        legal_constraints=list(legal_constraints),
        tick=3,
        ticks_remaining=9,
        cognition_budget_remaining=5200,
        recent_action_log=[],
    )


# T1
def test_perception_runs_without_llm_call() -> None:
    """Perception is pure Python; the function does not take an LLMClient."""
    obs = _make_obs()
    for brain in ("epidemiology", "logistics", "governance"):
        report = perception_for(brain, obs)
        assert isinstance(report, PerceptionReport)
        assert report.brain == brain
        assert isinstance(report.confidence, float)
        assert 0.0 <= report.confidence <= 1.0


# T2
def test_perception_for_v2_brain_raises_key_error() -> None:
    obs = _make_obs()
    for v2_brain in ("communications", "equity"):
        with pytest.raises(KeyError):
            perception_for(v2_brain, obs)
    with pytest.raises(KeyError):
        perception_for("not_a_brain", obs)


# T3
@pytest.mark.parametrize("brain", ["epidemiology", "logistics", "governance"])
def test_perception_brain_specific_signals(brain: str) -> None:
    obs = _make_obs(
        cases_per_region=(20, 1, 0, 0),
        hospital_loads=(0.7, 0.1, 0.1, 0.1),
        test_kits=100,  # below threshold (300)
        hospital_beds_free=50,  # below threshold (100)
        mobile_units=2,  # below threshold (5)
        vaccine_doses=200,  # below threshold (500)
        restrictions=[
            Restriction(region="R1", severity="moderate", ticks_remaining=3),
        ],
        legal_constraints=[
            LegalConstraint(rule_id="L1", blocked_action="restrict_movement.strict"),
        ],
    )
    report = perception_for(brain, obs)

    assert report.brain == brain
    # Decision 63 / OQ-2 cap: at most 5 entries
    assert len(report.salient_signals) <= 5

    if brain == "epidemiology":
        assert any("R1" in s for s in report.salient_signals), (
            f"epi salient_signals should reference R1, got {report.salient_signals}"
        )
    elif brain == "logistics":
        joined = " ".join(report.salient_signals).lower()
        assert "kits" in joined or "mobile" in joined or "vaccine" in joined or "beds" in joined
    elif brain == "governance":
        assert any("R1" in s and "moderate" in s.lower() for s in report.salient_signals), (
            f"governance salient_signals should mention R1 moderate, got {report.salient_signals}"
        )