Files
openswarm/backend/tests/test_wedge_verdict.py
T

51 lines
1.8 KiB
Python

"""Pins the ENG-353 two-stage wedge contract: a fresh heartbeat (alive sidecar, slow tool) must not
be shot at the first deadline; a stale one must; nothing survives the late deadline. Five healthy
kills in one loaded evening were every one of the "MCP disconnected" reports."""
import os
import tempfile
from backend.apps.agents.manager.streaming.unwedge_sidecar import (
HARD_WEDGE_SECONDS,
HEARTBEAT_FRESH_S,
LATE_WEDGE_SECONDS,
WEDGE_SECONDS,
heartbeat_age,
wedge_verdict,
)
def test_stale_heartbeat_kills_at_first_deadline():
assert wedge_verdict(WEDGE_SECONDS + 1, HEARTBEAT_FRESH_S + 1) == "kill"
def test_fresh_heartbeat_extends_instead_of_killing():
assert wedge_verdict(WEDGE_SECONDS + 1, 2.0) == "extend"
def test_late_deadline_with_fresh_heartbeat_extends_to_the_hard_ceiling():
# ENG-368: an alive sidecar mid-way through a long call is not wedged; only the hard ceiling ends it.
assert wedge_verdict(LATE_WEDGE_SECONDS + 1, 0.5) == "extend"
assert wedge_verdict(LATE_WEDGE_SECONDS + 1, HEARTBEAT_FRESH_S + 1) == "kill"
assert wedge_verdict(HARD_WEDGE_SECONDS + 1, 0.5) == "kill"
assert HARD_WEDGE_SECONDS > LATE_WEDGE_SECONDS > WEDGE_SECONDS
def test_missing_heartbeat_reads_as_wedged():
assert heartbeat_age("no-such-session-anywhere") > 1e8
def test_real_heartbeat_file_reads_fresh():
sid = "wedge-verdict-test"
path = os.path.join(tempfile.gettempdir(), f"osw-mcp-hb-{sid}")
with open(path, "a"):
os.utime(path, None)
try:
assert heartbeat_age(sid) < 5.0
assert wedge_verdict(WEDGE_SECONDS + 1, heartbeat_age(sid)) == "extend"
finally:
os.unlink(path)
def test_negative_control_old_behavior_without_heartbeat():
age = heartbeat_age("no-such-session-anywhere")
assert wedge_verdict(WEDGE_SECONDS + 1, age) == "kill"