Files
Harbor/tests/test_work.py
T
KeelrLeek dbfd1720c5 Harbor as of 2026-10-05: the coordination hub for the Open Sea's decomp team
Messages, threads, acknowledgements, claims, bands, tasks, review items and
stop flags for a team of AI agents; the chat page and board; host hooks and
MCP server; autopilot; tools/watch.py. Put under version control after the
weekend's changes so they have history and can be rolled back. Local only.
2026-10-05 10:44:23 -05:00

225 lines
13 KiB
Python

"""Tasks, handoffs, pins, the human's availability, corrections, due times, search filters, connections, doctor."""
import json
import os
import re
import shutil
import unittest
from helpers import HarborCase, make_home, temp_dir
from harbor import doctor, install
from harbor.core import Harbor, HarborError
class Tasks(HarborCase):
def test_next_takes_by_priority_and_dependencies(self):
low = self.h.add_task("Claude", "tidy names", priority="low")
first = self.h.add_task("Claude", "make 0x445310 readable", scope="fn:0x445310", priority="high")
after = self.h.add_task("Claude", "make its caller readable", scope="fn:0x445400", priority="urgent",
after=[first["id"]])
self.assertEqual(after["waiting_on"], [first["id"]])
took = self.h.next_task("DeepSeek")
self.assertEqual((took["id"], took["state"], took["assignee"]), (first["id"], "in_progress", "DeepSeek"))
self.assertEqual(self.h.active_claims(agent="DeepSeek")[0]["scope"], "fn:0x445310")
self.assertIn(f"task #{first['id']}", next(a for a in self.h.agents() if a["name"] == "DeepSeek")["doing"])
self.assertEqual(self.h.next_task("Codex")["id"], low["id"]) # the urgent one still waits
with self.assertRaises(HarborError):
self.h.take_task("OpenCode", after["id"])
self.h.update_task("DeepSeek", first["id"], "done", note="landed in abc")
self.assertEqual(self.h.active_claims(agent="DeepSeek"), []) # claim released
self.assertIsNone(next(a for a in self.h.agents() if a["name"] == "DeepSeek")["doing"])
self.assertEqual(self.h.next_task("OpenCode")["id"], after["id"])
self.assertIn("is done", self.h.inbox("Claude")[-1]["body"]) # the creator hears about it
def test_claims_and_bands_steer_next(self):
self.h.claim("Claude", "range:0x440000-0x47FFFF", kind="band", on_behalf_of="DeepSeek")
inside = self.h.add_task("Claude", "inside DeepSeek's band", scope="fn:0x450000")
held = self.h.add_task("Claude", "already drafted", scope="fn:0x490000")
self.h.claim("OpenCode", "fn:0x490000")
self.assertIsNone(self.h.next_task("Codex"))
self.assertEqual(self.h.next_task("DeepSeek")["id"], inside["id"])
self.assertEqual(self.h.next_task("OpenCode", take=False)["id"], held["id"])
assigned = self.h.add_task("Claude", "for Codex inside the band", scope="fn:0x451000", assignee="Codex")
self.assertEqual(self.h.next_task("Codex")["id"], assigned["id"]) # explicit assignment wins
self.assertEqual(self.h.inbox("Codex")[-1]["refs"]["task"], assigned["id"])
self.h.update_task("Codex", assigned["id"], "open", note="later") # handed back for now
self.assertEqual(self.h.task(assigned["id"])[0]["assignee"], "Codex") # still the coordinator's choice
self.assertEqual(self.h.next_task("Codex", take=False)["id"], assigned["id"])
def test_permissions_block_release_cancel(self):
with self.assertRaises(HarborError):
self.h.add_task("Codex", "for someone else", assignee="Kimi")
mine = self.h.add_task("Codex", "my own", assignee="Codex")
self.h.take_task("Codex", mine["id"])
with self.assertRaises(HarborError):
self.h.update_task("Codex", mine["id"], "blocked") # say why
with self.assertRaises(HarborError):
self.h.update_task("Kimi", mine["id"], "done")
self.h.update_task("Codex", mine["id"], "blocked", note="needs 0x4E2680 named first")
self.assertTrue(any(a["kind"] == "task_blocked" for a in self.h.attention()))
self.assertIn("blocked", self.h.inbox("Claude")[-1]["body"])
self.h.update_task("Codex", mine["id"], "open")
self.assertIsNone(self.h.task(mine["id"])[0]["assignee"]) # handed back
self.h.update_task("Claude", mine["id"], "cancelled", note="no longer needed")
self.h.update_task("Codex", mine["id"], "open") # the creator may reopen
with self.assertRaises(HarborError):
self.h.update_task("Codex", mine["id"], "review")
web = self.h.add_task("User", "from the board", origin="web", priority="urgent")
self.assertEqual(web["created_by"], "User")
with self.assertRaises(HarborError):
self.h.add_task("User", "pretend", origin="cli")
def test_review_items_drive_their_task(self):
task = self.h.next_task("DeepSeek") if False else self.h.add_task("Claude", "make 0x445310 readable",
scope="fn:0x445310")
self.h.take_task("DeepSeek", task["id"])
item = self.h.submit("DeepSeek", "RouteCellCost readable", commit="abc1234", task=task["id"])
self.assertEqual(self.h.task(task["id"])[0]["state"], "review")
self.assertEqual(self.h.item(item["id"])[0]["scope"], "fn:0x445310") # scope comes from the task
self.h.transition("Claude", item["id"], "changes_requested", note="signed read")
self.assertEqual(self.h.task(task["id"])[0]["state"], "in_progress")
self.h.transition("DeepSeek", item["id"], "submitted", commit="def5678")
self.assertEqual(self.h.task(task["id"])[0]["state"], "review")
self.h.transition("Claude", item["id"], "approved")
self.h.transition("Claude", item["id"], "landed", commit="b4b44f0")
done = self.h.task(task["id"])[0]
self.assertEqual((done["state"], done["item_id"]), ("done", item["id"]))
self.assertEqual(self.h.active_claims(agent="DeepSeek"), [])
with self.assertRaises(HarborError):
self.h.submit("Codex", "not mine", task=task["id"])
class Continuity(HarborCase):
def test_handoff_brief_and_restart_prompt(self):
with self.assertRaises(HarborError):
self.h.handoff("Kimi", " ")
self.h.handoff("Kimi", "Reviewed batch 48.\nIn flight: 0x406F60 VisitTavern, half the strings checked.\nNext: batch 49.")
brief = self.h.brief("Kimi")
self.assertIn("Your last handoff", brief)
self.assertIn("In flight: 0x406F60", brief)
self.h.add_task("Claude", "review 0x406F60", scope="fn:0x406F60", assignee="Kimi")
prompt = self.h.restart_prompt("Kimi")
for part in ("You are Kimi", "Team coordination (Harbor)", "Your tasks", "In flight: 0x406F60", "--as Kimi brief"):
self.assertIn(part, prompt)
self.h.set_flag("stop:Kimi", "on", "Claude", "cli")
self.assertIn("STOPPED", self.h.restart_prompt("Kimi"))
self.assertNotIn("Your last handoff", self.h.brief("Kimi")) # stopped: no nudge to continue
def test_pins_and_decisions(self):
rule = self.h.send("Claude", "All", "Main-thread float math is single precision.", kind="decision")
self.h.pin("Codex", rule["id"], note="single precision rule")
self.assertIn("single precision rule", self.h.brief("Kimi"))
self.assertEqual([m["id"] for m in self.h.decisions()], [rule["id"]])
self.h.unpin("Kimi", rule["id"])
self.assertEqual(self.h.pins(), [])
with self.assertRaises(HarborError):
self.h.pin("Kimi", 99999)
def test_human_availability(self):
with self.assertRaises(HarborError):
self.h.set_presence("User", "cli", "away")
with self.assertRaises(HarborError):
self.h.set_presence("Codex", "web", "away")
self.h.set_presence("User", "web", "away", until="2h", note="decide with Claude")
self.assertIn("User is away until", self.h.brief("Codex"))
question = self.h.send("Codex", ["User"], "Should I rename 0x445310?")
self.assertTrue(any(a["kind"] == "human_away" and a["message_id"] == question["id"] for a in self.h.attention()))
self.clock.t += 3 * 3600
self.assertEqual(self.h.presence()["status"], "here") # the away time ran out
self.assertNotIn("is away", self.h.brief("Codex"))
class Messages(HarborCase):
def test_corrections(self):
wrong = self.h.send("Codex", ["DeepSeek", "Kimi"], "0x445310 uses a signed read", thread="fn:0x445310")
fix = self.h.send("Codex", None, "It is unsigned (movzx), not signed.", corrects=wrong["id"])
self.assertEqual((fix["thread_id"], sorted(fix["targets"])), (wrong["thread_id"], ["DeepSeek", "Kimi"]))
self.assertEqual(self.h.message(fix["id"])["kind"], "retraction")
self.assertEqual(self.h.corrections_for([wrong["id"]]), {wrong["id"]: [fix["id"]]})
self.assertIn(f"corrects #{wrong['id']}", self.mirror.read_text(encoding="utf-8"))
with self.assertRaises(HarborError):
self.h.send("Kimi", None, "not yours", corrects=wrong["id"])
self.assertTrue(self.h.send("Claude", None, "coordinator correction", corrects=wrong["id"])["id"])
def test_due_times(self):
q = self.h.send("Claude", ["Kimi"], "Is 0x406F60 exact?", due="30m")
self.assertIn("Answers due from you", self.h.brief("Kimi"))
self.assertFalse(any(a["kind"] == "due_overdue" for a in self.h.attention()))
self.clock.t += 3600
self.assertTrue(any(a["kind"] == "due_overdue" and a["message_id"] == q["id"] for a in self.h.attention()))
self.h.ack("Kimi", [q["id"]], note="yes, exact")
self.assertFalse(any(a["kind"] == "due_overdue" for a in self.h.attention()))
with self.assertRaises(HarborError):
self.h.send("Claude", ["Kimi"], "x", due="whenever")
def test_search_filters_and_paging(self):
self.h.send("Codex", "All", "LayoutTextMesh glyph key", thread="fn:0x50A720")
self.h.send("Kimi", ["Claude"], "LayoutTextMesh reviewed", kind="decision")
self.h.send("Kimi", ["Codex"], "unrelated words")
self.assertEqual(len(self.h.search("LayoutTextMesh")), 2)
self.assertEqual([m["sender"] for m in self.h.search("LayoutTextMesh from:kimi")], ["Kimi"])
self.assertEqual(len(self.h.search("kind:decision")), 1)
self.assertEqual(len(self.h.search("thread:fn:0x50A720")), 1)
self.assertEqual(len(self.h.search("to:Codex")), 1) # not its own broadcast
self.assertEqual(len(self.h.search("since:1h LayoutTextMesh")), 2)
ids = [m["id"] for m in self.h.recent(10)]
self.assertEqual([m["id"] for m in self.h.messages_before(ids[-1], limit=1)], [ids[-2]])
def test_connections_and_activity(self):
self.h.connect("Codex", "mcp", "codex")
self.h.activity("Codex", "shell", "codex")
links = {(r["channel"], r["host"]) for r in self.h.connections()["Codex"]}
self.assertEqual(links, {("mcp", "codex"), ("hook", "codex")})
codex = next(a for a in self.h.agents() if a["name"] == "Codex")
self.assertTrue(self.h.working(codex))
self.assertEqual(codex["last_tool"], "shell")
self.clock.t += 600
self.assertFalse(self.h.working(next(a for a in self.h.agents() if a["name"] == "Codex")))
def test_opening_twice_does_not_rewrite(self):
before = self.h.conn.execute("SELECT value FROM meta WHERE key='signature'").fetchone()["value"]
again = Harbor(self.project, clock=self.clock)
self.assertEqual(again.conn.execute("SELECT value FROM meta WHERE key='signature'").fetchone()["value"], before)
again.close()
class Doctor(unittest.TestCase):
def test_reports_hosts_and_live_connections(self):
d = temp_dir()
home = d / "user"
(home / ".codex").mkdir(parents=True)
(home / ".codex" / "config.toml").write_text('model = "x"\n', encoding="utf-8")
harbor_home = d / "harbor-home"
project = make_home(harbor_home)["test"]
text = project.source.read_text(encoding="utf-8").replace('name = "Codex"\n', 'name = "Codex"\nhost = "codex"\n')
project.source.write_text(text, encoding="utf-8")
saved = {k: os.environ.get(k) for k in ("HARBOR_INSTALL_HOME", "HARBOR_HOME", "HARBOR_PROJECT")}
os.environ.update(HARBOR_INSTALL_HOME=str(home), HARBOR_HOME=str(harbor_home))
os.environ.pop("HARBOR_PROJECT", None)
try:
from harbor import projects
project = projects.load_named("test")
h = Harbor(project)
before = {(c["area"], c["check"]): c["status"] for c in doctor.run(project, h, port=8797)}
self.assertEqual(before[("Codex", "MCP server")], "fail")
self.assertEqual(before[("Database", "integrity")], "ok")
self.assertEqual(before[("Server", "http://127.0.0.1:8797")], "warn")
install.install("codex", python="py -3.12")
h.connect("Codex", "mcp", "codex")
after = {(c["area"], c["check"]): c["status"] for c in doctor.run(project, h, port=8797)}
self.assertEqual((after[("Codex", "MCP server")], after[("Codex", "hooks")]), ("ok", "ok"))
self.assertEqual(after[("Codex", "hooks trusted")], "warn")
self.assertEqual(after[("Codex", "live connection")], "ok")
self.assertIn("FAIL", doctor.render(doctor.run(project, h, port=8797)) + "FAIL")
h.close()
finally:
for k, v in saved.items():
if v is None:
os.environ.pop(k, None)
else:
os.environ[k] = v
shutil.rmtree(d, ignore_errors=True)
if __name__ == "__main__":
unittest.main()