Show agent update outcomes automatically
Agent update outcomes now show up in Settings and the palette on their own, including for restored jobs. You no longer have to press Refresh. The app listens for terminal changes on the original owner's control connection and then reads that owner's retained receipts. A reconnect, a withdrawn policy or a detached owner stops the listening. A signal can never start an update or count as success; only a bounded read of the original receipt sets an outcome.
#21469 (recovery across restarts) has merged, so this PR is now just the observation layer on top of feat-cmux-next:
AgentCLIUpdateActions+Observation.swift:follow(_:),observe(_:route:)andterminalChanges(...). The terminal-change stream comes from the captured source/serial only.Route.changesis captured inRoute.capture. Explicit refresh and the follow task both use the sameobserve(_:route:). That function keeps base's unknown-outcome field and its closed-tab (terminalGone) settle path.- When base's
owner(of:)swaps in a re-captured route after a reconnect, it restarts observation on the new route.rememberrestarts it when a batch gains a receipt. terminal-registry-changedoutlives snapshots, collapses to the newest event per source/serial in the event inbox, and is delivered through side events.
Merge note (adopted 2026-10-20): base rebuilt #21469 after this branch forked from it. Every conflict takes base's side, and only the observation commit (23441cccc) and its later fixes are re-applied on top.
Changelog
Fixed: Agent update outcomes appear without pressing Refresh.
Observed / Not run
- Ran:
scripts/cmux-next/prepush-gate.py(no new violations) andscripts/web-lint.sh. Fleet Swift suites (CmuxNext, 4 shards) on the head: see the comment below. - Not run: GUI dogfood.
Agent session: cosmic-gray
🤖 Generated with Claude Code