Location: packages/devframe/src/utils/shared-state.ts
createSharedState uses a Set<string> named syncIds to prevent echo loops when patches or mutations are synchronized across RPC boundaries. Every patch() and mutate() call records its syncId, but the set is never pruned.
For short-lived states this is minor, but long-lived frequently updated states will retain every sync ID for the lifetime of the process. The terminal plugin is a realistic example because it updates session state from a polling loop; similar shared-state users will accumulate IDs indefinitely.
The implementation currently adds IDs in both mutation paths and exposes the set for duplicate detection, but there is no eviction, cap or lifecycle cleanup for old IDs.
Recommended fix: Replace direct syncIds.add(syncId) calls with a bounded FIFO helper. A fixed cap such as 1,000 recent IDs preserves near-term echo-loop prevention while bounding memory growth.
Location:
packages/devframe/src/utils/shared-state.tscreateSharedStateuses aSet<string>namedsyncIdsto prevent echo loops when patches or mutations are synchronized across RPC boundaries. Everypatch()andmutate()call records itssyncId, but the set is never pruned.For short-lived states this is minor, but long-lived frequently updated states will retain every sync ID for the lifetime of the process. The terminal plugin is a realistic example because it updates session state from a polling loop; similar shared-state users will accumulate IDs indefinitely.
The implementation currently adds IDs in both mutation paths and exposes the set for duplicate detection, but there is no eviction, cap or lifecycle cleanup for old IDs.
Recommended fix: Replace direct
syncIds.add(syncId)calls with a bounded FIFO helper. A fixed cap such as 1,000 recent IDs preserves near-term echo-loop prevention while bounding memory growth.