Problem
A worker running graphcode mail inbox reported that the mailbox was oversized and the command timed out. The room is bounded, but the inbox read path still transports and broadcasts the entire project graph rather than a bounded mailbox response.
Observed on the odang graph:
- 35 nodes
- 220 retained mailroom posts
- persisted project graph JSON: about 204 KB
mail list --json: 146,840 bytes
- auto-triaged
mail inbox: 19,501 bytes across 221 lines
The read-only mail list --json completes quickly in isolation, so the likely problem is amplification under the live graph with many connected workers rather than rendering alone.
Current flow
mail inbox currently:
- Opens the project and receives a full
LoopGraph snapshot, including every retained mail body.
- Sends
mailroomInbox to advance the calling node cursor.
- Persists the whole graph and broadcasts another full
graphChanged snapshot to all connected clients.
- Waits for that broadcast, then renders unread mail from the original snapshot.
Concurrent workers checking mail can therefore produce repeated roughly 200 KB broadcasts to every connected client, even though the final output is headline-triaged to roughly 20 KB.
There is also a known cursor race: a post arriving between the initial snapshot and cursor advancement can be marked read without being included in the rendered output.
Expected
Inbox reads should have bounded cost based on the unread response, not the size of the entire graph or the number of connected clients. The cursor should advance only through the highest post actually returned to the reader.
Potential direction: add a dedicated mailbox request/response carrying bounded unread headlines plus the highest delivered post ID, and update the cursor without requiring a full graph broadcast as the acknowledgement.
Problem
A worker running
graphcode mail inboxreported that the mailbox was oversized and the command timed out. The room is bounded, but the inbox read path still transports and broadcasts the entire project graph rather than a bounded mailbox response.Observed on the odang graph:
mail list --json: 146,840 bytesmail inbox: 19,501 bytes across 221 linesThe read-only
mail list --jsoncompletes quickly in isolation, so the likely problem is amplification under the live graph with many connected workers rather than rendering alone.Current flow
mail inboxcurrently:LoopGraphsnapshot, including every retained mail body.mailroomInboxto advance the calling node cursor.graphChangedsnapshot to all connected clients.Concurrent workers checking mail can therefore produce repeated roughly 200 KB broadcasts to every connected client, even though the final output is headline-triaged to roughly 20 KB.
There is also a known cursor race: a post arriving between the initial snapshot and cursor advancement can be marked read without being included in the rendered output.
Expected
Inbox reads should have bounded cost based on the unread response, not the size of the entire graph or the number of connected clients. The cursor should advance only through the highest post actually returned to the reader.
Potential direction: add a dedicated mailbox request/response carrying bounded unread headlines plus the highest delivered post ID, and update the cursor without requiring a full graph broadcast as the acknowledgement.