Rig Pocket: phone status page and ntfy notifier for OpenRig

Installable PWA showing rigs, seats (working, idle, waiting for an answer),
queue items and recent commits; seat screens with replies; push through ntfy.
Reads state through the rig CLI only, Python standard library, no build step,
styled entirely with the shared weirsoe-theme.

Claude-Session: https://claude.ai/code/session_01QhLkBGEip8wQdaZ54z4AqJ
This commit is contained in:
Asger Geel Weirsøe
2026-10-20 17:43:55 +02:00
commit 69cb255120
14 changed files with 674 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
import unittest
import server
def snap(commits=(), queue=(), waiting=False):
return {
"rigs": [{"name": "team", "seats": [{"name": "dev-qa@team", "waiting": waiting}]}],
"queue": list(queue),
"repos": [{"name": "repo", "commits": [{"hash": h, "subject": f"commit {h}"} for h in commits]}],
}
def q(qid, state, dest="orch-lead@team"):
return {"id": qid, "state": state, "dest": dest, "source": "operator-agent@kernel", "summary": f"task {qid}"}
class WatcherTest(unittest.TestCase):
def test_first_snapshot_only_seeds(self):
w = server.Watcher()
self.assertEqual(w.events(snap(commits=["a"], queue=[q("1", "in-progress")])), [])
def test_new_commits_grouped_per_repo(self):
w = server.Watcher()
w.events(snap(commits=["a"]))
ev = w.events(snap(commits=["a", "b", "c"]))
self.assertEqual(len(ev), 1)
self.assertIn("2 ny commits", ev[0][0])
def test_lead_task_done_notifies_once(self):
w = server.Watcher()
w.events(snap(queue=[q("1", "in-progress"), q("2", "in-progress", "dev-build@team")]))
ev = w.events(snap(queue=[q("1", "done"), q("2", "done", "dev-build@team")]))
self.assertEqual([e[0] for e in ev], ["Opgave done: orch-lead@team"])
self.assertEqual(w.events(snap(queue=[q("1", "done")])), [])
def test_new_request_to_human_notifies(self):
w = server.Watcher()
w.events(snap())
ev = w.events(snap(queue=[q("9", "in-progress", "operator-agent@kernel")]))
self.assertEqual(ev[0][0], "Teamet spørger dig")
def test_prompt_must_survive_two_polls(self):
w = server.Watcher()
self.assertEqual(w.events(snap(waiting=True)), [])
ev = w.events(snap(waiting=True))
self.assertEqual(ev[0][0], "dev-qa@team venter på svar")
self.assertEqual(w.events(snap(waiting=True)), [])
w.events(snap(waiting=False))
w.events(snap(waiting=True))
self.assertEqual(len(w.events(snap(waiting=True))), 1)
def test_prompt_pattern(self):
self.assertTrue(server.PROMPT.search(" Do you want to proceed?\n ❯ 1. Yes"))
self.assertFalse(server.PROMPT.search("❯ yes, launch it"))
def test_seat_names(self):
self.assertTrue(server.SEAT.match("dev-qa@ubl-workshop"))
self.assertFalse(server.SEAT.match("x; rm -rf /"))
self.assertFalse(server.SEAT.match("../etc@x/y"))
if __name__ == "__main__":
unittest.main()