MicroFish/backend/tests/test_adversarial_router.py

70 lines
2.9 KiB
Python

import adversarial_router as ar
def _agent(aid: str, role: str, view: str) -> dict:
return {"agent_id": aid, "role": role, "view": view,
"score": 5.0, "confidence": 0.7, "thesis": "t", "note": "n"}
def _balanced_agents() -> list[dict]:
agents = [_agent(f"bull-{i}", ar.BULL_LEANING[i % 3], "bullish") for i in range(8)]
agents += [_agent(f"bear-{i}", ar.BEAR_LEANING[i % 3], "bearish") for i in range(8)]
return agents
def test_classify_agent():
assert ar.classify_agent("growth") == "bull"
assert ar.classify_agent("risk") == "bear"
assert ar.classify_agent("macro") == "neutral"
def test_balanced_fixture_low_reinforcement():
pool = ar.synthetic_bear_market_pool(8, 8, 0, seed=0) # 50% bull, 50% bear notes
agents = _balanced_agents() # 8 bull-leaning + 8 bear-leaning
assignments = [[a, *ar.route_notes(a, pool, k=8, seed=0)] for a in agents]
rate = ar.reinforcement_rate(assignments)
assert rate < 0.10, f"reinforcement too high: {rate}"
def test_routing_is_deterministic():
pool = ar.synthetic_bear_market_pool(6, 6, 4, seed=1)
agent = _agent("x", "growth", "bullish")
a = ar.route_notes(agent, pool, k=8, seed=42)
b = ar.route_notes(agent, pool, k=8, seed=42)
assert a == b, "same seed + agent must yield identical routing"
def test_same_view_only_when_no_opposite_or_neutral():
agent = _agent("self", "growth", "bullish")
all_bull = [{"agent_id": f"b{i}", "view": "bullish", "score": 5,
"confidence": 0.5, "thesis": "t", "note": "n"} for i in range(5)]
out = ar.route_notes(agent, all_bull, k=8, seed=0)
assert len(out) > 0, "must fall back to same-view when nothing else exists"
assert all(n["view"] == "bullish" for n in out)
assert ar.reinforcement_rate([[agent, *out]]) == 1.0 # same-view counts
# once an opposite note appears, same-view must disappear
pool = all_bull + [{"agent_id": "bear1", "view": "bearish", "score": 5,
"confidence": 0.5, "thesis": "t", "note": "n"}]
out2 = ar.route_notes(agent, pool, k=8, seed=0)
assert len(out2) > 0
assert all(n["view"] == "bearish" for n in out2), "opposite exists -> no same-view"
def test_self_note_never_returned():
pool = ar.synthetic_bear_market_pool(5, 5, 2, seed=3)
agent = _agent(pool[0]["agent_id"], "quality", "bearish")
out = ar.route_notes(agent, pool, k=8, seed=0)
assert out, "expected some notes"
assert all(n.get("agent_id") != agent["agent_id"] for n in out)
def test_dedup_holds():
base = {"view": "bearish", "score": 5, "confidence": 0.5, "thesis": "t", "note": "n"}
pool = [{**base, "agent_id": "dup"}, {**base, "agent_id": "dup"},
{**base, "agent_id": "dup"}, {**base, "agent_id": "other"}]
agent = _agent("self", "growth", "bullish")
out = ar.route_notes(agent, pool, k=8, seed=0)
ids = [n.get("agent_id") for n in out]
assert len(ids) == len(set(ids)), "duplicate agent_ids returned"