# Design: Tool Session Progress and Live Updates ## Goals / Non-Goals **Goals:** - Provide structured, real-time progress feedback for every tool lifecycle action. - Ensure all session lists (nav, dashboard, sessions page) update immediately after create/delete. - Remove blocking and card-dimming overlays that hide context and provide no step detail. - Keep the change frontend-only, reusing existing SSE and session APIs. **Non-Goals:** - No new backend endpoints or event types. - No changes to the actual Docker/container orchestration logic. - No redesign of the session card layout beyond action/progress affordances. ## Decisions ### Decision: Global progress panel in the corner A fixed panel (bottom-right desktop, bottom sheet style on mobile) lists in-flight operations. Each operation shows: - Action icon + session display name - Current step label derived from the latest SSE event - A compact stepper: Created → Building → Starting → Probing → Ready/Error - Dismiss button once settled This is non-blocking, works across pages, and does not interfere with the modal create flow. ### Decision: SSE event-driven updates The panel subscribes to `useEvents`. When an operation is started we record `instanceId` + `action`. Incoming events that match a tracked instance update the operation's message, status, and step. Events handled: - `instance.created`, `instance.started`, `instance.restarted` → advance - `instance.health_changed` with `status=running` → complete success - `instance.error` → complete error - `instance.stopped` → complete for stop action - `instance.deleted` → complete for delete action ### Decision: Shared session state `SessionsContext` is promoted from a nav-only data holder to the authoritative session list: - Holds `sessions`, `isLoading`, `error`, `refreshSessions()`. - Provides `addOrUpdateSession`, `removeSession` for optimistic updates. - `AppShell`, `DashboardPage`, and `SessionsPage` read from this context instead of fetching independently. ### Decision: Optimistic create/delete updates - **Create**: after the API returns a pending instance, add it to shared state and start tracking. Subsequent SSE events update its status. - **Delete**: remove from shared state as soon as the API succeeds; the progress panel tracks the action until the `instance.deleted` event confirms it. - **Other actions**: keep the existing per-action busy flag on the card for button disabled states, but the panel provides the detailed progress. ### Decision: Remove legacy overlays - Delete `loading-overlay` and workflow step markup from `CreateSessionForm`. - Remove `session-busy-overlay` and `instance-busy-overlay` (the dimming overlays), but keep button disabled states and small inline spinners. ## Risks / Trade-offs **Risk: Shared context causes extra re-renders** → Mitigation: context value is memoized; lists use the same data they already fetched. **Risk: SSE events arriving before operation is tracked** → Mitigation: start tracking before calling the create/start API; for deletes the removal is optimistic and the panel reconciles on the event. **Risk: Duplicate feedback between panel and toasts** → Mitigation: panel shows in-flight steps; toasts remain for terminal success/error only. Existing `EventToastBridge` logic is left largely unchanged. ## Migration Plan 1. Extend `SessionsContext` with loading/error/refresh/update helpers. 2. Create `SessionOperationsContext` + `SessionProgressPanel` and render it in `AppShell`. 3. Update `useInstanceActions` to use shared state and start/stop tracking operations. 4. Update `ToolStarter`/`StartToolFAB` to add pending sessions and start tracking. 5. Update `CreateSessionForm` to remove overlay and report status to parent. 6. Update `InstanceList` to refresh shared state after create/delete. 7. Update `SessionsPage` and `DashboardPage` to consume shared context. 8. Remove legacy overlay styles. 9. Run typecheck, lint, and tests.