Architecture: S185: How to persist Studio chat sessions across page refres...
Documentation for Sessions
🏗️ Architecture: S185: How to persist Studio chat sessions across page refres...
Date: 2026-03-07
Time: 01:36:52 UTC
Session: gspace1-185.4
Agent: storage
Confidence: 95%
Status: ✅ Documented
📋 Decision Context
Question:
S185: How to persist Studio chat sessions across page refresh without corrupting the shared persistence service?
Task: S185: Fix Studio chat session persistence across page refresh
🎯 Decision Made
Chosen:
Two-phase restore pattern: Phase 1 (immediate) tries switchSession which succeeds if IndexedDB has loaded. Phase 2 (effect watching isHydrated signal) retries after IndexedDB loads and switches to the real session. localStorage stores the session ID as the synchronous anchor. No modifications to ensureActiveSession, no placeholders in state, no context filter.
Options Considered:
- Force-switch with placeholder sessions in state (corrupts IndexedDB)
- Modify ensureActiveSession to respect context filter (breaks all routes)
- sessionStorage persistence for context filter (timing issues)
- Two-phase restore with effect watching isHydrated (chosen - cooperative approach)
💭 Reasoning
Root cause: autoFlashState (IndexedDB) loads asynchronously with unpredictable timing. The persistence service's ensureActiveSession() creates a generic session when it can't find the active session in allSessions(). Five approaches failed: (1) Force-switch with placeholder — placeholder got persisted to IndexedDB, corrupting real data, causing alternating behavior. (2) Modifying ensureActiveSession to bail on context filter — broke all non-Studio routes. (3) sessionStorage for context filter — set before Studio init, caused empty sidebar. (4) Early return in ensureActiveSession when ID set but not found — broke everywhere. (5) Force-switch without placeholder — ensureActiveSession still overrode. The working solution accepts that ensureActiveSession will do its thing, and simply overwrites its result after IndexedDB loads via a reactive effect. This is cooperative, not adversarial.
📁 Files Involved
libs/libs-structural/vitto-studio/src/lib/services/studio-session.service.tslibs/libs-ai/vitto-chat/src/lib/services/vitto-chat-persistence.service.ts
🔗 Related
- Decision ID:
dev_1772847412402_d72s4vw - Session: 185
- Workspace: gspace1
Auto-generated by MCP Smart Consolidation