diff --git a/backend/apps/dashboards/models.py b/backend/apps/dashboards/models.py index 926f4f28..5a6e7fa7 100644 --- a/backend/apps/dashboards/models.py +++ b/backend/apps/dashboards/models.py @@ -40,6 +40,8 @@ class BrowserCardPosition(BaseModel): spawned_by: Optional[str] = None # When the agent leaves the deliverable on the page (a video playing, a page to read), it sets this so the frontend's auto-close on parent finish skips the card and the browser stays put. keep_open: bool = False + # The dashboard this card calls home. Persisted so the home survives a save; without it the card reloads untagged and renders on EVERY dashboard (the cross-dashboard bleed). + dashboard_id: Optional[str] = None class NotePosition(BaseModel): diff --git a/frontend/src/shared/state/dashboardLayoutSlice.ts b/frontend/src/shared/state/dashboardLayoutSlice.ts index 77661a7b..7c9afecf 100644 --- a/frontend/src/shared/state/dashboardLayoutSlice.ts +++ b/frontend/src/shared/state/dashboardLayoutSlice.ts @@ -1344,8 +1344,9 @@ const dashboardLayoutSlice = createSlice({ // Merge, don't replace: the keep-alive browser cards resetLayout preserved are ALREADY in state.browserCards with their webContents live. Keep them and add this dashboard's saved cards on top; on overlap (switching back to their own dashboard) the live data wins so the mounted webview isn't disturbed. const keptAlive = state.browserCards; const incoming = action.payload.browserCards; + // Default a missing home to the dashboard we're loading (legacy/untagged cards), but DON'T overwrite a real persisted home: a card saved here yet owned elsewhere is leftover from the old untagged-shows-everywhere bug, leaving its true home lets it park off-screen and get cleaned on the next save instead of bleeding. for (const card of Object.values(incoming)) { - card.dashboard_id = ownerDashboardId; + if (!card.dashboard_id) card.dashboard_id = ownerDashboardId; } // New cards boot parked (no guest process, title placeholder); the suspend hook wakes viewport-sized and agent-driven ones on its first pass. NEVER re-park a live keep-alive card, that snapshot-swap would kill its session. for (const id of Object.keys(incoming)) {