Ace map · discussion · 2026-10-22

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

FeatureOld AceAce todayGap and size
Who's in the projectshippedyes avatars on channel rows and the project header, with a directoryNone for directory teams; tailnet-only teams get nothing M
Who's in this chatshippedchannel only Presence.channels has no chat idsS
Away / idleshippedyes away 3 s after blurNone
Typingshipped incl. Ace typingno TypingDots exists unused (#35)S–M
@mention peopleshippedno composer suggests only aceQueued in the fix train ~2h
Mention and unread countsshipped0 or 1 mentionCount: 0 hard-codedProject into the channel listing like ran M, ~1 day
Read state across your devicesshippedno per browser profile in localStorageM
Seen-by (others see you read it)nonoM–L, if wanted
Notify while Ace is openshipped mentions, soundown runs only desktop app, unfocusedMentions ride the same path 1–2h after counts
Notify when Ace is closed or on a phonestored, delivered on reconnectno "Notifications are not built"Push + per-person inbox L, 2–4 days
Live channel listshippedyes lifecycle events through the lobbyActivity (busy, active) sends no event
Who's watching a runnowatching works, unseenS–M
Follow / jump to someoneVS Code onlynoJump S, live follow M
Activity feedseparate dashboardlobby keeps a 30-day log, no readerM

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

Nate's appread state: browser Sam's appread state: browser Nate's hostchannels, messages Sam's hostchannels, messages Project lobbydirectory or a host push: none own host only peers: listings, watches presence, lifecycle
Apps talk only to their own host. Hosts share presence and channel changes through the project lobby, and listings and live watches with each other. Read state lives in each browser, and nothing reaches an app that isn't running.

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 @login and projects counts into the listing the way it projects ran. The lobby carries a mentioned lifecycle 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

A. Grow the lobby into everything

Typing, chat presence, mentions and read state all go through the project lobby. One place to look, but only teams with a directory get any of it, every keystroke crosses the internet even when everyone is on one tailnet, and the lobby's 2 KB per-socket presence budget is already near its limit.

Leaning

B. Put each signal where it already flows

Typing and chat presence on the channel's watch stream; mentions and counts projected by the channel's host and announced through the lobby; read state on your own host; the lobby stays project presence and lifecycle. Nearly all of it works without a directory, and nothing needs a new service until push.

C. B, plus a per-person inbox cell for push

When Ace has to reach a closed app or a phone: one Durable Object per person in the directory Worker, fed by the same mentioned and ran events, holding undelivered items and sending Web Push or APNs. This is the "events stream" piece. It's tied to per-person identity (#511), since today's identity is an unverified gh login.

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

  1. Suggest people after @ ~2h, queued
  2. Typing and who's in this chat, on the watch stream S–M
  3. Mention and unread counts in the listing, plus desktop notifications for mentions ~1 day
  4. Read markers on your own host, so every device agrees M
  5. Who's watching a run, and jump to a teammate S
  6. Presence for tailnet-only teams: a host-served directory already gives it whenever that host is awake M or document that path
  7. Per-person inbox and push L, 2–4 days
  8. 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

  1. Is B the shape you want, with C only when push matters?
  2. Which of steps 2–5 matter for the universe release?
  3. Should others ever see that you've read something (seen-by)? Old Ace never showed it.
  4. Do tailnet-only teams need presence, or is "one host serves the directory" the answer?
  5. Is a phone notification for a mention needed before the release?