Repository navigation
Description
Note
🤖 Claude Opus 5.5 opening this issue on behalf of Will
What happened
My iPhone got 40+ copies of one "thread done" alert. It happened twice in ten minutes. Each time, one thread finished on my Mac. In the next two minutes the server sent about 89 agent-activity publishes to the relay for other threads. Those threads finished weeks ago. Nothing about them changed.
The relay then re-sent the fresh "done" alert once per publish. That half is #28932 / #15015. This issue is the server half: these publishes shouldn't be sent at all.
Diagnosis
One open PR is linked to 187 of my threads. When that PR changes (a push, CI), PullRequestSyncReactor dispatches thread.pull-request-link.sync for every linked thread. That part is expected.
Each thread.pull-request-synced event queues an awareness publish (apps/server/src/relay/AgentAwarenessRelay.ts:96). A finished, settled thread projects to null. The unchanged-state skip never works for null:
- After publishing
null, the server deletes the thread frompublishedStateByThread(:645) instead of storing the"null"identity. - On the next event,
get(threadId)isundefined. So the unchanged check fails, andundefined !== agentAwarenessPublishIdentity(null)(:561) asks for confirmation. Five seconds later it publishes the tombstone again.
So every PR update sends one state-clear per linked top-level thread, every time. Each one makes the relay recompute the aggregate and deliver to every device.
Expected: once a thread's clear has been published, PR updates on it stay quiet until it has state again.
Steps to reproduce
Seen on my machine. I haven't run a controlled test.
- Link an environment to an iPhone through T3 Connect. Notifications on, Live Activities off.
- Link one open PR to many threads, and let them finish and settle.
- Finish another thread. Within 2 minutes, update the PR (push, or let CI report).
- In
server.trace.ndjson, each linked thread logsagent activity publish deferred pending confirmation, thenagent activity deferred publish confirmedwithstatePhase: null. This repeats on every PR update. The phone gets one "done" alert per publish.
Version
Desktop app and its server 0.1.6 (2359643c). iOS App Store app 2.2.0. The code involved is unchanged on main as of 2026-11-02.
Environment
macOS arm64 (Darwin 27.2.0). Desktop app running its local server. Linked through T3 Connect to one iPhone with Live Activities off.
Evidence
Server trace, 2026-11-02 UTC:
| Thread finished | Clears for other threads in the next 2 min | Distinct threads |
|---|---|---|
| 14:01:30 | 88 | 88 |
| 14:06:15 | 141 | 89 |
| 14:10:02 | 89 | 89 |
- All the cleared threads link the same open PR.
- 1,122
thread.pull-request-link.syncdispatches across 187 threads between 13:59 and 14:14. - One October thread was synced and cleared at 14:01:45, 14:04:50, 14:06:43, 14:07:52, 14:10:57 and 14:14:00.
- The finished thread published
completedonce each time. - The 14:01 and 14:10 bursts reached the phone.
Not verified: what the relay delivered. Relay spans export to T3 Connect, not to the local trace.
Related issues
- [Bug]: Every agent-activity publish queues a push while any thread waits for input (burst of identical "Input:" pushes) #28932: the relay fallback queues a push on every unrelated publish (the "Input:" variant)
- fix(relay): an iPad no longer gets a Done alert for every unrelated publish #15015: open relay fix for the "done" variant
- fix(server): subagent threads stop publishing tombstones to the relay #15016: subagent threads stopped publishing tombstones; this is the same problem for top-level threads
- [Bug]: Renaming a thread fires a push notification to other devices (title-only metadata change) #25582: renaming a thread fires a push
Fix applied or workaround
I unlinked the PR from the 89 settled threads that kept sending clears. Whether that stops the bursts isn't confirmed yet.
Filed by
Claude Opus 5.5 (Claude Code, run from T3 Code's triage flow), on behalf of Will.
Activity