Files
box/tests/test_completion.py
T

371 lines
14 KiB
Python

"""Tests for the completion-enforcement loop: on_no_result fallbacks,
proof-of-result followups, the NACK acted-variant, and the auditor funnel."""
import importlib.util
import json
import sys
import types
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
def _load(mod_name, rel_path):
spec = importlib.util.spec_from_file_location(mod_name, REPO_ROOT / rel_path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
sw = _load("sweeper_completion", "bin/followup-sweeper.py")
harv = _load("harvester_completion", "bin/response-harvester.py")
aud = _load("completion_audit_mod", "bin/completion-audit.py")
grav = _load("gravity_completion", "bin/gravity.py")
class DeriveJobName(unittest.TestCase):
def test_valid(self):
self.assertEqual(
sw.derive_job_name("autonomy-pulse-646-20261006-060000-ed9a26af"),
"autonomy-pulse-646",
)
def test_invalid_shapes(self):
for bad in (None, "", "nonsense", "job-2026-1-abc",
"nonexistent-job-20261006-060000-ed9a26af"):
self.assertIsNone(sw.derive_job_name(bad), bad)
class LoadJobFallback(unittest.TestCase):
def test_seeded_pulse_jobs(self):
for name in ("autonomy-pulse-646", "autonomy-pulse-pip",
"autonomy-pulse-opm"):
spec, err = sw.load_job_fallback(name)
self.assertIsNone(err, name)
self.assertIsNotNone(spec, name)
self.assertEqual(spec["op"], "swarm.spawn")
self.assertEqual(spec["args"]["count"], 2)
def test_absent_is_none(self):
spec, err = sw.load_job_fallback("646-daily-checkin")
self.assertIsNone(spec)
self.assertIsNone(err)
class RunNoResultFallback(unittest.TestCase):
def test_unresolvable_rec(self):
out = sw.run_no_result_fallback({"dm_id": "x"})
self.assertFalse(out["ran"])
self.assertFalse(out["configured"])
def test_job_without_spec(self):
out = sw.run_no_result_fallback(
{"dm_id": "x", "job_id": "646-daily-checkin-20261006-090000-abcdef12",
"recipient": "646"})
self.assertFalse(out["ran"])
self.assertFalse(out["configured"])
def test_dry_run_marks_configured(self):
out = sw.run_no_result_fallback(
{"dm_id": "x",
"job_id": "autonomy-pulse-646-20261006-060000-ed9a26af",
"recipient": "646"},
dry_run=True)
self.assertTrue(out["configured"])
self.assertFalse(out["ran"])
def test_op_path_uses_validated_build(self):
calls = {}
class FakeOpError(Exception):
pass
def fake_validate(args):
calls["validated"] = dict(args)
return {"echo": "yes"}
def fake_build(clean):
calls["built"] = clean
return ["/bin/echo", "fallback-ok"]
fake_mod = types.SimpleNamespace(
OPS={"probe.op": {"validate": fake_validate, "build": fake_build,
"timeout": 10}})
orig_exec, orig_load, orig_derive = (
sw._load_exec_ops, sw.load_job_fallback, sw.derive_job_name)
sw._load_exec_ops = lambda: fake_mod
sw.load_job_fallback = lambda name: (
({"op": "probe.op", "args": {"a": 1}}, None))
sw.derive_job_name = lambda jid: "autonomy-pulse-646"
try:
out = sw.run_no_result_fallback(
{"dm_id": "x", "job_id": "whatever", "recipient": "646"})
finally:
sw._load_exec_ops, sw.load_job_fallback, sw.derive_job_name = (
orig_exec, orig_load, orig_derive)
self.assertTrue(out["ran"], out)
self.assertEqual(out["mode"], "op")
self.assertEqual(calls["validated"], {"a": 1})
self.assertEqual(calls["built"], {"echo": "yes"})
self.assertIn("fallback-ok", out["detail"])
def test_unknown_op_is_outcome_not_raise(self):
orig_exec, orig_load, orig_derive = (
sw._load_exec_ops, sw.load_job_fallback, sw.derive_job_name)
sw._load_exec_ops = lambda: types.SimpleNamespace(OPS={})
sw.load_job_fallback = lambda name: ({"op": "nope.nope"}, None)
sw.derive_job_name = lambda jid: "autonomy-pulse-646"
try:
out = sw.run_no_result_fallback(
{"dm_id": "x", "job_id": "whatever", "recipient": "646"})
finally:
sw._load_exec_ops, sw.load_job_fallback, sw.derive_job_name = (
orig_exec, orig_load, orig_derive)
self.assertTrue(out["configured"])
self.assertFalse(out["ran"])
self.assertIn("unknown op", out["detail"])
class FallbackDue(unittest.TestCase):
def test_fresh_record_due(self):
self.assertTrue(sw.fallback_due({"dm_id": "x"}))
def test_ran_never_due(self):
self.assertFalse(sw.fallback_due(
{"fallback": {"ran": True, "ts": "2026-10-06T00:00:00+00:00"}}))
def test_failed_recent_not_due(self):
from datetime import datetime, timezone, timedelta
ts = (datetime.now(timezone.utc) - timedelta(minutes=5)).isoformat()
self.assertFalse(sw.fallback_due(
{"fallback": {"ran": False, "ts": ts}}))
def test_failed_old_due(self):
self.assertTrue(sw.fallback_due(
{"fallback": {"ran": False, "ts": "2026-10-05T00:00:00+00:00"}}))
class GravityFallback(unittest.TestCase):
def test_dry_run_configured(self):
rec = {"dm_id": "x",
"job_id": "autonomy-pulse-646-20261006-060000-ed9a26af",
"recipient": "646"}
out = grav.maybe_run_terminal_fallback(
rec, "2026-10-06T08:00:00+00:00", dry_run=True)
self.assertIsNotNone(out)
self.assertFalse(out["ran"])
self.assertNotIn("fallback", rec)
def test_no_spec_returns_none(self):
rec = {"dm_id": "x",
"job_id": "646-daily-checkin-20261006-090000-abcdef12",
"recipient": "646"}
self.assertIsNone(grav.maybe_run_terminal_fallback(
rec, "2026-10-06T08:00:00+00:00", dry_run=True))
def test_already_ran_returns_none(self):
rec = {"dm_id": "x",
"job_id": "autonomy-pulse-646-20261006-060000-ed9a26af",
"recipient": "646",
"fallback": {"ran": True, "ts": "2026-10-06T07:00:00+00:00"}}
self.assertIsNone(grav.maybe_run_terminal_fallback(
rec, "2026-10-06T08:00:00+00:00", dry_run=True))
class GravityEntry(unittest.TestCase):
def test_no_args_prints_help(self):
import io
from contextlib import redirect_stdout
buf = io.StringIO()
with redirect_stdout(buf):
rc = grav.main([])
self.assertEqual(rc, 2)
self.assertIn("remediate", buf.getvalue())
def test_remediate_dry_run_returns_json(self):
import io
from contextlib import redirect_stdout
buf = io.StringIO()
with redirect_stdout(buf):
rc = grav.main(["--remediate", "--dry-run"])
self.assertEqual(rc, 0)
data = json.loads(buf.getvalue())
self.assertTrue(data["ok"])
self.assertTrue(data["dry_run"])
class ResultEvidence(unittest.TestCase):
def test_positives(self):
for text in (
"done, swarm sw-20261006-060000-ab12 reported 2/2",
"wrote /tmp/out.json with 40 rows",
"timer id: pulse-15m restarted",
"thread 1dfb3199-2f99-446c-83e3-848ae2da0a12 swept",
"3/3 slots complete",
):
self.assertTrue(harv.result_has_evidence(text), text)
def test_negatives(self):
for text in ("OK all good", "done, nothing to report", "", None):
self.assertFalse(harv.result_has_evidence(text), repr(text))
class ProofRequest(unittest.TestCase):
def _patch(self, tmp_path):
orig = (harv.NUDGE_TRACKER_FILE, harv.JOB_LOG, harv.execute_agent_tool,
getattr(harv, "PROOF_REQUESTS_ENABLED", False))
harv.NUDGE_TRACKER_FILE = tmp_path / "tracker.json"
harv.JOB_LOG = tmp_path / "job-log.jsonl"
harv.PROOF_REQUESTS_ENABLED = True
calls = []
harv.execute_agent_tool = lambda a, op, args: (
calls.append((a, op, args)), (True, "scheduled"))[1]
return orig, calls
def test_bare_result_schedules_proof(self):
import tempfile
with tempfile.TemporaryDirectory() as td:
orig, calls = self._patch(Path(td))
try:
ok = harv.maybe_request_proof(
"646", "1dfb3199-2f99-446c-83e3-848ae2da0a12",
"job-1", "OK all good")
finally:
(harv.NUDGE_TRACKER_FILE, harv.JOB_LOG,
harv.execute_agent_tool,
harv.PROOF_REQUESTS_ENABLED) = orig
self.assertTrue(ok)
self.assertEqual(calls[0][1], "followup.create")
self.assertEqual(calls[0][2]["in_m"], 30)
self.assertIn("PROOF", calls[0][2]["prompt"])
def test_evidence_skips(self):
ok = harv.maybe_request_proof(
"646", "1dfb3199-2f99-446c-83e3-848ae2da0a12",
"job-1", "done, swarm sw-20261006-060000-ab12")
self.assertFalse(ok)
def test_bad_thread_and_dry_run_skip(self):
self.assertFalse(harv.maybe_request_proof(
"646", "main", "job-1", "OK"))
self.assertFalse(harv.maybe_request_proof(
"646", "1dfb3199-2f99-446c-83e3-848ae2da0a12",
"job-1", "OK", dry_run=True))
def test_one_shot_per_job(self):
import tempfile
with tempfile.TemporaryDirectory() as td:
orig, calls = self._patch(Path(td))
try:
kw = dict(agent="646",
thread_id="1dfb3199-2f99-446c-83e3-848ae2da0a12",
job_id="job-9", result_text="OK")
self.assertTrue(harv.maybe_request_proof(**kw))
self.assertFalse(harv.maybe_request_proof(**kw))
finally:
(harv.NUDGE_TRACKER_FILE, harv.JOB_LOG,
harv.execute_agent_tool,
harv.PROOF_REQUESTS_ENABLED) = orig
self.assertEqual(len(calls), 1)
class NackActedVariant(unittest.TestCase):
def test_acted_variant_text(self):
import tempfile
sent = []
fake = types.ModuleType("muse_hybrid")
fake.send_message = lambda a, m, thread_id=None, wait=0: sent.append(m)
with tempfile.TemporaryDirectory() as td:
tp = Path(td)
(tp / "followups.json").write_text(json.dumps({
"m1": {"status": "pending",
"thread_uuid": "1dfb3199-2f99-446c-83e3-848ae2da0a12",
"job_id": "job-7", "recipient": "646"}}))
orig = (harv.NUDGE_TRACKER_FILE, harv.FOLLOWUPS_FILE,
sys.modules.get("muse_hybrid"))
harv.NUDGE_TRACKER_FILE = tp / "tracker.json"
harv.FOLLOWUPS_FILE = tp / "followups.json"
sys.modules["muse_hybrid"] = fake
try:
harv.maybe_nudge_untagged_sidechat(
"646", "1dfb3199-2f99-446c-83e3-848ae2da0a12",
"646 tasks", "mid-1", "some prose", acted=True)
finally:
(harv.NUDGE_TRACKER_FILE, harv.FOLLOWUPS_FILE,
old_mod) = orig
if old_mod is None:
sys.modules.pop("muse_hybrid", None)
else:
sys.modules["muse_hybrid"] = old_mod
self.assertEqual(len(sent), 1)
self.assertIn("Action received", sent[0])
self.assertIn("[RESULT job-7]", sent[0])
self.assertNotIn("STRICT ENFORCEMENT", sent[0])
class AuditorFunnel(unittest.TestCase):
def _events(self):
base = "2026-10-06T07:00:00+00:00"
return [
{"ts": base, "type": "job_sent",
"job_id": "work-finder-20261006-070000-aaaaaaaa"},
{"ts": base, "type": "job_dispatched",
"job_id": "work-finder-20261006-070000-aaaaaaaa"},
{"ts": base, "type": "tool_exec", "op": "swarm.spawn",
"success": True},
{"ts": base, "type": "job_result",
"job_id": "work-finder-20261006-070000-aaaaaaaa",
"success": True},
{"ts": base, "type": "job_sent",
"job_id": "pulse-20261006-070000-bbbbbbbb"},
{"ts": base, "type": "job_failed",
"job_id": "pulse-20261006-070000-bbbbbbbb"},
]
def test_funnel_counts(self):
from datetime import datetime, timezone
fam, tools = aud.compute_funnel(
self._events(), datetime(2026, 10, 6, 6, 0, tzinfo=timezone.utc))
self.assertEqual(fam["work-finder"]["sent"], 1)
self.assertEqual(fam["work-finder"]["results"], 1)
self.assertEqual(fam["pulse"]["failed"], 1)
self.assertEqual(tools["tools"]["total"], 1)
self.assertEqual(tools["tools"]["ok"], 1)
def test_family_of(self):
self.assertEqual(aud.family_of("a-b-20261006-070000-aaaaaaaa"), "a-b")
self.assertEqual(aud.family_of("weird"), "weird")
def test_digest_verdicts(self):
healthy = {"ts": "2026-10-06T07:00:00+00:00", "window_h": 6,
"totals": {"sent": 4, "dispatched": 4, "results": 4,
"ok": 4},
"tools": {"tools": {"total": 3, "ok": 3}, "tool_errs": {}},
"families": {}, "silent_families": [], "swarms": {},
"stale_running": [], "followups": {"pending": 1},
"degraded": False, "reasons": []}
out = aud.render_digest(healthy)
self.assertIn("HEALTHY", out)
self.assertIn("4 sent", out)
bad = dict(healthy, degraded=True,
reasons=["1 silent families: x"],
silent_families=["x"])
self.assertIn("DEGRADED", aud.render_digest(bad))
def test_should_post_policy(self):
import tempfile
with tempfile.TemporaryDirectory() as td:
orig = aud.STATE_FILE
aud.STATE_FILE = Path(td) / "state.json"
try:
self.assertTrue(aud.should_post({"degraded": True})[0])
ok, why = aud.should_post({"degraded": False})
self.assertTrue(ok)
self.assertEqual(why, "heartbeat")
finally:
aud.STATE_FILE = orig
if __name__ == "__main__":
unittest.main()