agent plumbing: convert outbox to subscribers and an iterator

WaitForMessage() could only work for one thread, because it was using a
singular channel for outboxes. This was fine when we only had one user,
but WaitForMessageCount() was kinda similar, and had its own thing, and
I want to rework how polling works and need another user.

Anyway, this one is hand-coded, because Sketch really struggled
with getting the iterator convincingly safe. In a follow-up commit,
I'll try to get Sketch to write some tests.
diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
index f61ed28..4a415c8 100644
--- a/loop/server/loophttp.go
+++ b/loop/server/loophttp.go
@@ -349,9 +349,10 @@
 		if pollParam == "true" {
 			ch := make(chan string)
 			go func() {
-				// This is your blocking operation
-				agent.WaitForMessageCount(r.Context(), clientMessageCount)
+				it := agent.NewIterator(r.Context(), clientMessageCount)
+				it.Next()
 				close(ch)
+				it.Close()
 			}()
 			select {
 			case <-r.Context().Done():