Files
openswarm/backend/tests/test_flight_recorder.py

85 lines
3.3 KiB
Python

"""The flight recorder's contract: cheap crumbs, bounded rings, envelopes that name everything,
and a near-miss ledger that counts silent recoveries."""
from backend.apps.agents.core import flight_recorder as fr
def test_ring_is_bounded_and_ordered():
sid = "t-ring"
fr.drop_session(sid)
for i in range(100):
fr.crumb(sid, "step", n=i)
crumbs = fr.breadcrumbs(sid, last=100)
assert len(crumbs) == 64, "ring must cap at 64"
assert crumbs[-1]["n"] == 99 and crumbs[0]["n"] == 36, "oldest drop first"
fr.drop_session(sid)
assert fr.breadcrumbs(sid) == []
def test_meta_values_are_truncated_and_typed():
sid = "t-meta"
fr.drop_session(sid)
fr.crumb(sid, "err", msg="x" * 999, count=3, flag=True, skipped=None)
c = fr.breadcrumbs(sid)[0]
assert len(c["msg"]) == 200 and c["count"] == 3 and c["flag"] is True and "skipped" not in c
fr.drop_session(sid)
def test_lane_classification_matches_the_routing_reality():
assert fr.lane_for_model("sonnet-cc") == "cc"
assert fr.lane_for_model("cx/gpt-5.2") == "cx"
assert fr.lane_for_model("gemini-2.5-pro") == "gc"
assert fr.lane_for_model("openrouter/meta/llama") == "openrouter"
assert fr.lane_for_model("cp-openai/local") == "custom"
assert fr.lane_for_model("sonnet") == "api"
assert fr.lane_for_model(None) == "api"
def test_envelope_carries_cause_context_and_crumbs():
sid = "t-env"
fr.drop_session(sid)
fr.crumb(sid, "router-retry", attempt=1)
class FakeSession:
status = "running"
env = fr.build_envelope(sid, "model_error", "unclassified", "sonnet-cc", "stream", 2, {"a": FakeSession(), "b": FakeSession()})
assert env["family"] == "model_error" and env["lane"] == "cc" and env["phase"] == "stream"
assert env["attempts"] == 2 and env["breadcrumbs"][0]["l"] == "router-retry"
assert env["concurrency"] == {"sessions_total": 2, "turns_running": 2}
fr.drop_session(sid)
def test_recovery_ledger_emits_a_countable_diagnostic(monkeypatch):
sent = []
import backend.apps.service.client as svc
monkeypatch.setattr(svc, "submit_diagnostic", lambda d: sent.append(d))
fr.record_recovery("t-rec-12345678", "router-resume", "sonnet-cc", 1, None)
assert len(sent) == 1
d = sent[0]
assert d["kind"] == "recovered" and d["subkind"] == "router-resume" and d["lane"] == "cc" and d["attempts"] == 1
fr.drop_session("t-rec-12345678")
def test_envelope_carries_journey_and_auth_context():
sid = "t-journey"
fr.drop_session(sid)
env = fr.build_envelope(sid, "model_error", "auth", "sonnet-cc", "spawn", 1, {})
j = env["journey"]
assert set(j) >= {"stage", "signed_in"}, "stage + signed_in are the minimum honest context"
assert j["stage"] in ("onboarding", "returning", "unknown")
fr.drop_session(sid)
def test_breadcrumb_trail_reaches_ten_across_a_normal_spawn():
# The spawn pipeline now crumbs every phase; ten is the bar for reconstructing a turn.
sid = "t-trail"
fr.drop_session(sid)
for label in ["turn-start", "options-build", "mcp-build", "provider-env", "context-guard",
"client-acquire", "cli-connect-start", "cli-connect-done", "first-event",
"assistant-msg", "result-msg"]:
fr.crumb(sid, label)
assert len(fr.breadcrumbs(sid, last=20)) >= 10
fr.drop_session(sid)