|
| 1 | +# Workspace Last Viewed Target Design |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +Persist the user's last viewed workspace/session target on the server so refreshes and new devices can restore the same place. The value is global to the instance, last-write-wins, and stored in `user_settings` without a schema change. |
| 6 | + |
| 7 | +## Problem |
| 8 | + |
| 9 | +Today the active workspace is kept only in browser memory, so a refresh falls back to the first workspace. Mobile also has no reliable cross-device way to restore the current session inside that workspace. |
| 10 | + |
| 11 | +## Goals |
| 12 | + |
| 13 | +- Restore the last viewed workspace across refreshes and devices. |
| 14 | +- Restore the last viewed session on mobile after the workspace is restored. |
| 15 | +- Keep desktop behavior simple: restore the workspace tab only, not pane layout. |
| 16 | +- Avoid database migrations. |
| 17 | + |
| 18 | +## Non-Goals |
| 19 | + |
| 20 | +- Per-user isolation. |
| 21 | +- Syncing pane layout through this feature. |
| 22 | +- Changing the existing `/workspace` route shape. |
| 23 | + |
| 24 | +## Data Model |
| 25 | + |
| 26 | +Store one JSON value in `user_settings`: |
| 27 | + |
| 28 | +```json |
| 29 | +{ |
| 30 | + "workspaceId": "ws_123", |
| 31 | + "sessionId": "sess_456", |
| 32 | + "updatedAt": 1770000000000 |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +- `workspaceId` is required. |
| 37 | +- `sessionId` is optional. |
| 38 | +- `updatedAt` is server-written metadata for debugging and conflict transparency. |
| 39 | + |
| 40 | +Suggested key: `workspace.lastViewedTarget`. |
| 41 | + |
| 42 | +## Server Behavior |
| 43 | + |
| 44 | +- Add a dedicated internal command for writing the target, instead of reusing the public settings UI path. |
| 45 | +- Read path stays simple: `settings.get` already returns all `user_settings` keys, so the client can hydrate from the existing settings payload. |
| 46 | +- Validate that `workspaceId` exists before writing. |
| 47 | +- If `sessionId` is provided but missing or not in the workspace, keep the workspace target and drop the session reference. |
| 48 | +- Writes are best-effort and last-write-wins. |
| 49 | + |
| 50 | +## Client Behavior |
| 51 | + |
| 52 | +- Hydrate the stored target during app bootstrap, after workspaces are loaded. |
| 53 | +- If the saved workspace still exists, set it as the active workspace intent. |
| 54 | +- Desktop: |
| 55 | + - switch to the saved workspace tab |
| 56 | + - do not force pane/layout changes |
| 57 | +- Mobile: |
| 58 | + - switch to the saved workspace |
| 59 | + - then select the saved session if it still exists |
| 60 | + - otherwise fall back to the workspace's `uiState.activeSessionId` |
| 61 | + - otherwise fall back to the most recent available session |
| 62 | + |
| 63 | +## Write Triggers |
| 64 | + |
| 65 | +Update the global target only from explicit user focus changes: |
| 66 | + |
| 67 | +- workspace tab selection |
| 68 | +- session card selection |
| 69 | +- mobile workspace/session selection |
| 70 | +- notification click focus |
| 71 | +- workspace launch into an opened workspace |
| 72 | + |
| 73 | +Do not mirror current active state back to the server from passive render effects or hydration effects. |
| 74 | + |
| 75 | +## Fallbacks |
| 76 | + |
| 77 | +- Missing workspace: fall back to the current first-workspace behavior. |
| 78 | +- Missing session: restore the workspace only. |
| 79 | +- No saved target yet: use current default bootstrap behavior. |
| 80 | + |
| 81 | +## Testing |
| 82 | + |
| 83 | +- Server command tests for read/write and validation. |
| 84 | +- Web tests for bootstrap restore on desktop and mobile. |
| 85 | +- E2E coverage for refresh restoring the same workspace, and mobile restoring the same session. |
| 86 | +- Regression test for missing workspace/session fallback. |
| 87 | + |
| 88 | +## Acceptance Criteria |
| 89 | + |
| 90 | +- Refresh no longer resets the app to the first workspace when a saved target exists. |
| 91 | +- Desktop restores the saved workspace tab only. |
| 92 | +- Mobile restores the saved workspace and session. |
| 93 | +- No schema migration is required. |
0 commit comments