## Why

Currently, each WebSocket connection to a terminal spawns a new `docker exec` process. When the user disconnects (e.g., closes the browser tab, navigates away, or loses network), their shell session is killed and all state is lost. This is frustrating for users who expect their terminal session to persist like a traditional SSH session. We need persistent terminal sessions that survive reconnections.

## What Changes

- **Backend**: Refactor `TerminalManager` to track sessions by `instance_id` instead of generating a new session per WebSocket connection
- **Backend**: Support reattaching to an existing `docker exec` process when a WebSocket reconnects
- **Backend**: Add session reset functionality (kill existing shell and start fresh)
- **Backend**: Add idle timeout-based cleanup for abandoned sessions
- **Frontend**: Add "Reset Terminal" button in the UI
- **Frontend**: Handle reconnection gracefully with buffer replay of recent output

## Capabilities

### New Capabilities
- `persistent-terminal`: Terminal sessions persist across WebSocket reconnections, maintaining shell state and history

### Modified Capabilities
- `terminal-session-management`: Existing terminal session creation and lifecycle behavior changes to support reconnection instead of always creating new sessions

## Impact

- `apps/api/src/services/terminal_manager.py`: Major refactoring to support instance-keyed sessions
- `apps/api/src/services/terminal_session.py`: Support multiple/detached WebSocket connections
- `apps/api/src/api/terminal.py`: Attach to existing session logic
- `apps/web/src/components/terminal.tsx` or related: Add reset button, handle reconnection
- `apps/web/src/hooks/use-terminal.ts` or related: Buffer replay on reconnect

