import json import unittest from tests.fakes import Harness class FakeProbe: def __init__(self, counts): self.counts = counts def process_count(self, name): return self.counts.get(name, 0) class SkipReasonTest(unittest.TestCase): """Why a Todo item was not dispatched: heartbeat "skipped", logged once per new reason.""" def setUp(self): self.h = Harness() self.p = self.h.plane self.lines = [] self.h.d.log = lambda msg: self.lines.append(msg) def tearDown(self): self.h.close() def skipped(self): hb = json.loads((self.h.d.store.dir / "heartbeat.json").read_text()) return {s["item"]: (s["terminal"], s["reason"]) for s in hb["skipped"]} def not_dispatched(self): return [l for l in self.lines if "not dispatched" in l] def test_reasons_in_heartbeat_and_logged_once(self): self.p.add_issue(1) # starts on win10 self.p.add_issue(2) # win10 full self.p.add_issue(3, assignee="kappiee") # no terminal for kappiee self.p.add_issue(4, assignee="oregon", labels=["needs-game"]) # starts on oregon, holds the game group self.p.add_issue(5, assignee="oregon", labels=["needs-game"]) # group held self.h.tick() self.assertEqual(self.skipped(), { "GW-2": ("win10", "concurrency 1/1 (GW-1)"), "GW-3": (None, "no route for assignee kappiee"), "GW-5": ("oregon", "serialize_group game held by GW-4"), }) self.assertEqual(len(self.not_dispatched()), 3) self.h.tick() # same reasons: heartbeat still has them, the log does not repeat them self.assertEqual(len(self.skipped()), 3) self.assertEqual(len(self.not_dispatched()), 3) def test_busy_process_and_relay_down(self): self.h.cfg.terminals["win10"]["busy_processes"] = ["codex"] probe = FakeProbe({"codex": 1}) self.h.d.transport_factory = lambda term: probe self.p.add_issue(1) self.h.tick() self.assertEqual(self.skipped(), {"GW-1": ("win10", "busy_process codex (1 running, not started by agentd)")}) probe.counts = {} self.h.tick() # leftover codex.exe gone: dispatched, nothing skipped self.assertEqual(self.skipped(), {}) self.assertEqual(self.p.state_of("i1"), "In Progress") self.p.add_issue(2, assignee="oregon") self.h.cfg.terminals["oregon"]["busy_processes"] = ["claude"] probe.counts = {"claude": None} # probe fails: relay down probe.process_count = lambda name: None self.h.tick() self.assertEqual(self.skipped()["GW-2"], ("oregon", "relay down")) if __name__ == "__main__": unittest.main()