Ace live layer
What tells people they're in Ace together: who's here, who's typing, who mentioned you, what you haven't seen. Ace has a project lobby for presence and channel changes, and nothing else. This page lists what old Ace gave people, what Ace has today, and the shape of a service that fills the gap.
What people get
| Feature | Old Ace | Ace today | Gap and size |
|---|---|---|---|
| Who's in the project | shipped | yes avatars on channel rows and the project header, with a directory | None for directory teams; tailnet-only teams get nothing M |
| Who's in this chat | shipped | channel only Presence.channels has no chat ids | S |
| Away / idle | shipped | yes away 3 s after blur | None |
| Typing | shipped incl. Ace typing | no TypingDots exists unused (#35) | S–M |
| @mention people | shipped | no composer suggests only ace | Queued in the fix train ~2h |
| Mention and unread counts | shipped | 0 or 1 mentionCount: 0 hard-coded | Project into the channel listing like ran M, ~1 day |
| Read state across your devices | shipped | no per browser profile in localStorage | M |
| Seen-by (others see you read it) | no | no | M–L, if wanted |
| Notify while Ace is open | shipped mentions, sound | own runs only desktop app, unfocused | Mentions ride the same path 1–2h after counts |
| Notify when Ace is closed or on a phone | stored, delivered on reconnect | no "Notifications are not built" | Push + per-person inbox L, 2–4 days |
| Live channel list | shipped | yes lifecycle events through the lobby | Activity (busy, active) sends no event |
| Who's watching a run | no | watching works, unseen | S–M |
| Follow / jump to someone | VS Code only | no | Jump S, live follow M |
| Activity feed | separate dashboard | lobby keeps a 30-day log, no reader | M |
Sizes are agent time. Evidence: old Ace at 8d875cb43 (clients/vm/src/server/lobby/*, docs/lobby.md); Ace at services/directory/src/lobby.ts, apps/host/src/lobby.ts, apps/app/src/attention.ts, apps/app/src/app.tsx:177, docs/architecture.md:618-672.
Where things travel today
Where each signal belongs
The signals split by how long they live and whose they are. That decides where each one should go, more than which service exists.
- Live and per channel (typing, who's in this chat, who's watching a run): seconds long, only meaningful to people already looking at the channel. Everyone looking already holds the channel's watch stream from its host, so this can ride that stream. It works for tailnet-only teams and needs no directory.
- Durable and per channel (mentions, unread counts): the channel's host already sees every message, so it detects
@loginand projects counts into the listing the way it projectsran. The lobby carries amentionedlifecycle event so other hosts update without polling. - Durable and per person (what you've read, your inbox, push): yours across every device. Your own host is the one place all your devices already reach, so read markers live there. Push to a closed app or phone needs something always on, which a host isn't; that's a per-person inbox in the directory, next to the lobby.
- Project-wide (who's in the project, lifecycle, an activity feed): stays in the lobby, which already does it.
Shapes for the service
Lessons from old Ace: one long-lived machine per repository gave orphaned lobbies, start-up races, presence lost on every restart, and a break-glass rebuild script. Ace's hibernating Durable Object lobby already avoids those, which argues against a new always-on process. For read state, the Next Cloud rules carry over: mark read only what was shown, acknowledge exact ids, never subtract counts locally, and fence stale responses by revision.
Order if we build it
- Suggest people after @ ~2h, queued
- Typing and who's in this chat, on the watch stream S–M
- Mention and unread counts in the listing, plus desktop notifications for mentions ~1 day
- Read markers on your own host, so every device agrees M
- Who's watching a run, and jump to a teammate S
- Presence for tailnet-only teams: a host-served directory already gives it whenever that host is awake M or document that path
- Per-person inbox and push L, 2–4 days
- Activity feed over the lobby's log M
The docs disagree with the code in two places, which a doc fix should settle either way: architecture.md:620 says lobbies need the deployed directory (a host-served one has them too), and terms.md:65 gives the lobby notifications, which it doesn't carry.
Questions for you
- Is B the shape you want, with C only when push matters?
- Which of steps 2–5 matter for the universe release?
- Should others ever see that you've read something (seen-by)? Old Ace never showed it.
- Do tailnet-only teams need presence, or is "one host serves the directory" the answer?
- Is a phone notification for a mention needed before the release?