Confirmed with synthetic live feed events at 5d641845 (Node v24.14.1, macOS arm64). Priority: medium for Remote users with long-lived/multiple agents. No private transcript or live app was used.
Expected and actual behavior
The phone should retain a bounded live transcript window, and should not accumulate full transcripts for every session the user has never opened. Older content should remain available through durable pagination.
TranscriptStore constructor ingests all sessions' live entries independently of view subscriptions. ingestRawEntries retains every UUID in seen, inserts tool objects into unbounded indexes, and copies/appends the entire entries array for every burst. There is no live entry count/byte window here. Session-list removal, transcript roll, and store disposal clear state, but simply not viewing a still-live session does not.
The desktop already has liveEntryWindow (2,000-entry and 32 MiB triggers with ownership constraints). The phone reuses several desktop reducers but does not apply that retention discipline.
Reproduction and measurements
Instantiate the actual TranscriptStore with a fake feed that captures the registered event callbacks, lists one synthetic Claude session, and has zero view subscriptions. Use the real Claude transcript mapper and real indexEntryIntoMaps/empty state helpers. Deliver 4,096 unique newline-equivalent assistant entries through onSessionJsonlEntries, each containing one unique Read tool call and an 8,192-character ASCII text block. Use a stable synthetic transcript filename.
The harness transpiled the store source in memory, substituted only the renderer capability registry with the actual Claude mapper factory, and left unused semantic-event modules inert. No semantic events were exercised.
| Delivered entries |
Retained entries |
Retained text bytes |
Tool-use index |
Seen UUIDs |
View subscribers |
| 1,024 |
1,024 |
8,388,608 |
1,024 |
1,024 |
0 |
| 2,048 |
2,048 |
16,777,216 |
2,048 |
2,048 |
0 |
| 4,096 |
4,096 |
33,554,432 |
4,096 |
4,096 |
0 |
These are retained logical payload sizes and collection cardinalities, not browser heap measurements. Tool input bodies, object/index overhead and semantic state are additional, unmeasured costs. The test stops after 4,096 entries; there is no eviction branch in this append path.
User impact and next steps
Memory grows with all received conversation/tool output while sessions remain live, even on the list screen. Phone tab reloads/termination under memory pressure and increasing append/render cost are plausible consequences; no actual mobile crash or FPS regression was measured.
- Introduce byte- and count-bounded live retention with a smaller budget for unviewed sessions, or negotiate server interest and backfill on selection.
- Keep entry, seen-id, tool-use/result indexes, pagination marker/offset, and semantic ownership state consistent when trimming. Never merely slice entries while leaving indexes holding the same bodies.
- Share the desktop retention policy where practical, but explicitly adapt its ghost/history/live-turn invariants to the remote store rather than importing the entire desktop workspace.
- Preserve paginated history and retry/reconnect semantics. Trimming must not cause duplicate rows or tool results to lose their owners.
- Add a regression covering sustained large entries on several unviewed sessions, bounded cardinalities/bytes, later selection/backfill, and session removal.
Tradeoff: smaller retained windows increase backfill requests and may affect scroll position; no estimated percentage improvement is claimed. This is independent of the main-process socket queue bound and of B7's #795 external operator implementation.
Refs #103, #375, #475.
Related transport backlog issue: #804. A bounded send queue does not limit what a healthy receiving phone retains.
Confirmed with synthetic live feed events at
5d641845(Node v24.14.1, macOS arm64). Priority: medium for Remote users with long-lived/multiple agents. No private transcript or live app was used.Expected and actual behavior
The phone should retain a bounded live transcript window, and should not accumulate full transcripts for every session the user has never opened. Older content should remain available through durable pagination.
TranscriptStore constructor ingests all sessions' live entries independently of view subscriptions. ingestRawEntries retains every UUID in
seen, inserts tool objects into unbounded indexes, and copies/appends the entire entries array for every burst. There is no live entry count/byte window here. Session-list removal, transcript roll, and store disposal clear state, but simply not viewing a still-live session does not.The desktop already has liveEntryWindow (2,000-entry and 32 MiB triggers with ownership constraints). The phone reuses several desktop reducers but does not apply that retention discipline.
Reproduction and measurements
Instantiate the actual TranscriptStore with a fake feed that captures the registered event callbacks, lists one synthetic Claude session, and has zero view subscriptions. Use the real Claude transcript mapper and real
indexEntryIntoMaps/empty state helpers. Deliver 4,096 unique newline-equivalent assistant entries throughonSessionJsonlEntries, each containing one unique Read tool call and an 8,192-character ASCII text block. Use a stable synthetic transcript filename.The harness transpiled the store source in memory, substituted only the renderer capability registry with the actual Claude mapper factory, and left unused semantic-event modules inert. No semantic events were exercised.
These are retained logical payload sizes and collection cardinalities, not browser heap measurements. Tool input bodies, object/index overhead and semantic state are additional, unmeasured costs. The test stops after 4,096 entries; there is no eviction branch in this append path.
User impact and next steps
Memory grows with all received conversation/tool output while sessions remain live, even on the list screen. Phone tab reloads/termination under memory pressure and increasing append/render cost are plausible consequences; no actual mobile crash or FPS regression was measured.
Tradeoff: smaller retained windows increase backfill requests and may affect scroll position; no estimated percentage improvement is claimed. This is independent of the main-process socket queue bound and of B7's #795 external operator implementation.
Refs #103, #375, #475.
Related transport backlog issue: #804. A bounded send queue does not limit what a healthy receiving phone retains.