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/agent_git_test.go b/loop/agent_git_test.go
index 399943b..053b8af 100644
--- a/loop/agent_git_test.go
+++ b/loop/agent_git_test.go
@@ -8,7 +8,6 @@
 	"path/filepath"
 	"strings"
 	"testing"
-	"time"
 )
 
 // TestGitCommitTracking tests the git commit tracking functionality
@@ -67,7 +66,6 @@
 	agent := &Agent{
 		workingDir:    tempDir,
 		repoRoot:      tempDir, // Set repoRoot to same as workingDir for this test
-		outbox:        make(chan AgentMessage, 100),
 		seenCommits:   make(map[string]bool),
 		initialCommit: initialCommit,
 	}
@@ -97,13 +95,7 @@
 	}
 
 	// Check if we received a commit message
-	var commitMsg AgentMessage
-	select {
-	case commitMsg = <-agent.outbox:
-		// We got a message
-	case <-time.After(500 * time.Millisecond):
-		t.Fatal("Timed out waiting for commit message")
-	}
+	var commitMsg AgentMessage = agent.history[len(agent.history)-1]
 
 	// Verify the commit message
 	if commitMsg.Type != CommitMessageType {
@@ -162,7 +154,6 @@
 	}
 
 	// Reset the outbox channel and seen commits map
-	agent.outbox = make(chan AgentMessage, 100)
 	agent.seenCommits = make(map[string]bool)
 
 	// Call handleGitCommits again - it should still work but only show at most 100 commits
@@ -172,12 +163,7 @@
 	}
 
 	// Check if we received a commit message
-	select {
-	case commitMsg = <-agent.outbox:
-		// We got a message
-	case <-time.After(500 * time.Millisecond):
-		t.Fatal("Timed out waiting for commit message")
-	}
+	commitMsg = agent.history[len(agent.history)-1]
 
 	// Should have at most 100 commits due to the -n 100 limit in git log
 	if len(commitMsg.Commits) > 100 {