The list keys (BOARDS_KEY, PROFILES_KEY, PROJECTS_KEY, ORCHESTRATION_KEY)
were module-level consts, so their scope segment was evaluated once at
import and stayed 'local' for the life of the app — the boards list, the
query behind the reported symptom, never got the cache miss the scoping
promised. The per-slug builders read host.state.connectionId.get() during
render with no subscription, so when the slug was the same on both
gateways (the default '' is) the observer kept the old-scoped key, the
twin's refetch stored the new gateway's data under the old scope, and the
next re-render flipped the key into a second fetch.
Every builder now takes the scope explicitly: rendering components get it
from useKanbanScope() (useValue on the SDK atom, so a switch re-renders
them and their observers move to the new key), non-rendering actions
(mutation settles, socket frames) from kanbanConnectionScope() at call
time. boardKeyPrefix(scope) replaces the raw ['kanban', 'board'] arrays
that leaked the key shape into six call sites.