"""Infra-overhead + thrash signal tests (WP-0005 T02).""" import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from session_memory.detect.signals import ( # noqa: E402 build_context, extract_signals, sig_infra_overhead, sig_schema_thrash, sig_tool_thrash, tool_bucket, ) def _digest(uid="claude:a", repo="r1", tools=None): return {"session_uid": uid, "flavor": "claude", "repo": repo, "outcome": "success", "cost": {"input_tokens": 1, "output_tokens": 1}, "markers": {"errors": 0, "retries": 0, "test_runs": 0}, "tool_histogram": tools or {}} CTX = {"infra_min_calls": 20, "infra_overhead_threshold": 0.30, "schema_thrash_threshold": 5, "tool_thrash_threshold": 80} def test_tool_bucket_mapping(): assert tool_bucket("mcp__state-hub__update_task_status") == "statehub_mcp" assert tool_bucket("ToolSearch") == "schema_load" assert tool_bucket("TaskUpdate") == "task_mgmt" assert tool_bucket("Bash") == "shell" assert tool_bucket("Edit") == "edit" def test_infra_overhead_fires_above_share(): # 18 statehub of 30 total = 60% overhead d = _digest(tools={"mcp__state-hub__create_task": 18, "Bash": 8, "Edit": 4}) sig = sig_infra_overhead(d, CTX) assert sig and sig[0].type == "infra_overhead" assert sig[0].magnitude >= 0.30 assert sig[0].detail["statehub"] == 18 def test_infra_overhead_quiet_when_mostly_work(): d = _digest(tools={"mcp__state-hub__create_task": 3, "Bash": 40, "Edit": 30}) assert sig_infra_overhead(d, CTX) == [] def test_infra_overhead_ignores_tiny_sessions(): d = _digest(tools={"mcp__state-hub__create_task": 5}) # below infra_min_calls assert sig_infra_overhead(d, CTX) == [] def test_schema_thrash_fires(): d = _digest(tools={"ToolSearch": 9, "Bash": 5}) sig = sig_schema_thrash(d, CTX) assert sig and sig[0].type == "schema_thrash" assert sig[0].detail["tool_searches"] == 9 def test_tool_thrash_fires_on_dominant_tool(): d = _digest(tools={"Bash": 120, "Edit": 5}) sig = sig_tool_thrash(d, CTX) assert sig and sig[0].locus == "tool:Bash" def test_extract_signals_includes_infra(): d = _digest(tools={"mcp__state-hub__create_task": 18, "Bash": 8, "Edit": 4, "ToolSearch": 6}) types = {s.type for s in extract_signals([d])} assert "infra_overhead" in types assert "schema_thrash" in types def test_build_context_has_infra_defaults(): ctx = build_context([]) assert ctx["infra_overhead_threshold"] == 0.30 assert ctx["schema_thrash_threshold"] == 5