# Feature Specification: Session Explorer Core

> Feature ID: FEATURE-029-A
> Version: v1.0
> Status: Refined
> Last Updated: 02-11-2026

## Version History

| Version | Date | Description |
|---------|------|-------------|
| v1.0 | 02-11-2026 | Initial specification |

## Linked Mockups

| Mockup | Type | Path | Description | Status |
|--------|------|------|-------------|--------|
| Console Explorer v1 | HTML | [mockups/console-explorer-v1.html](mockups/console-explorer-v1.html) | Full interactive mockup with 6 scenarios: Default, 5 Sessions, Rename, Hover Preview, Max Sessions, Collapsed | current |

> **Note:** UI/UX requirements and acceptance criteria below are derived from mockups marked as "current".
> Mockups marked as "outdated" are directional references only — do not use for AC comparison.

## Overview

FEATURE-029-A delivers the **Session Explorer Core** — the MVP of the Console Session Explorer change request. It replaces the current 2-pane split-terminal layout (FEATURE-005 Phase 3) with a single-session view backed by a right-side explorer panel that lists up to 10 independent terminal sessions.

This feature is needed because the existing 2-pane split is limited to 2 simultaneous terminals and forces visible real estate to be split even when users only interact with one session at a time. The Session Explorer provides a scalable model where 10 sessions can run concurrently but only the active session occupies the full console area, maximizing terminal visibility while keeping all sessions accessible.

The primary users are **developers** using the X-IPE console for multi-session workflows — running servers, executing tests, monitoring logs, and editing configurations across independent terminal sessions.

## User Stories

1. As a **developer**, I want to **create multiple terminal sessions from an explorer panel**, so that **I can run different processes concurrently without splitting my terminal view**.

2. As a **developer**, I want to **switch between sessions by clicking their name in the explorer**, so that **I can quickly navigate between running processes while maintaining full-width terminal output**.

3. As a **developer**, I want **only the active session visible** in the console area, so that **I get maximum terminal real estate for the session I'm currently working in**.

4. As a **developer**, I want **a default session auto-created on console load**, so that **I can immediately start working without any setup step**.

5. As a **developer**, I want **my non-active sessions to continue running in the background**, so that **long-running processes (servers, builds) are not interrupted when I switch to another session**.

## Acceptance Criteria

### AC-029-A.1: Explorer Panel Rendering
- [ ] Session Explorer panel renders on the right side of the console window
- [ ] Panel displays a vertically scrollable list of session bars
- [ ] Each session bar shows the session name
- [ ] UI layout MUST match the approved mockup (console-explorer-v1.html) for the explorer panel structure
- [ ] Visual styling (colors, spacing, typography) MUST be consistent with mockup (console-explorer-v1.html)

### AC-029-A.2: Session Creation
- [ ] A "+" button is visible in the explorer panel header
- [ ] Clicking "+" creates a new PTY session via Socket.IO `attach` event
- [ ] New session is assigned a default name "Session N" where N is the next sequential number
- [ ] New session becomes the active session immediately after creation
- [ ] Maximum of 10 concurrent sessions enforced; "+" button is disabled when limit reached

### AC-029-A.3: Single-Session View
- [ ] Only the active session's xterm.js terminal is visible in the console area
- [ ] Non-active sessions' xterm.js instances remain mounted in the DOM with `display: none`
- [ ] No side-by-side split-pane layout — the `.pane-splitter` and multi-pane flex row are removed
- [ ] The active terminal occupies the full width of the console area (minus explorer panel width)

### AC-029-A.4: Session Switching
- [ ] Clicking a session bar in the explorer switches the active session
- [ ] The previously active terminal is hidden (`display: none`), the selected terminal is shown (`display: block`)
- [ ] Terminal output is fully preserved on switch — no content loss
- [ ] Cursor position and scrollback history are maintained across switches
- [ ] Interactive elements shown in mockup (console-explorer-v1.html) MUST be present and functional

### AC-029-A.5: Background Session Continuity
- [ ] All non-active PTY processes remain alive and continue executing
- [ ] Output generated by background sessions is buffered by `OutputBuffer` (10KB circular)
- [ ] Socket.IO connections for background sessions remain open
- [ ] When switching back to a background session, all buffered output is visible

### AC-029-A.6: Default Session on Load
- [ ] On console panel first expand, 1 session is auto-created named "Session 1"
- [ ] The auto-created session is set as the active session
- [ ] Explorer panel is expanded by default showing the single session

### AC-029-A.7: Backward Compatibility
- [ ] WebSocket reconnection with exponential backoff (1-5s) continues to work for all sessions
- [ ] Buffer replay on reconnect works correctly (10KB `OutputBuffer`)
- [ ] Connection status indicator (green/yellow/red dot) reflects the active session's state
- [ ] Terminal resize (FitAddon) works correctly for the active session
- [ ] Zen mode continues to function (full-screen overlay with explorer hidden)
- [ ] Console panel collapse/expand (header toggle) works as before

## Functional Requirements

### FR-029-A.1: Explorer Panel Layout

**Description:** The console window layout changes from a horizontal multi-pane split to a main terminal area + right-side explorer panel.

**Details:**
- Input: Console panel DOM structure
- Process: Replace `.terminal-panes` flex-row multi-pane layout with single `.terminal-content` area + `.session-explorer` panel
- Output: Console area = `[terminal-content | session-explorer]` where terminal-content has `flex: 1` and session-explorer has fixed width (220px default)

### FR-029-A.2: Session Lifecycle Management

**Description:** Frontend `TerminalManager` manages creation, switching, and tracking of up to 10 sessions.

**Details:**
- Input: User clicks "+", clicks session bar, or console loads
- Process: Create xterm.js instance + Socket.IO connection + PTY session. Track in sessions map (keyed by session_id). Set active session index.
- Output: Session appears in explorer, terminal visible if active

### FR-029-A.3: xterm.js Instance Management

**Description:** Each session has its own xterm.js `Terminal` instance that persists for the session lifetime.

**Details:**
- Input: Session creation triggers `new Terminal(config)` + `terminal.open(container)`
- Process: Container is a `<div>` inside `.terminal-content`, one per session. Only active session's container has `display: block`; others have `display: none`.
- Output: Terminal ready for I/O. FitAddon called only on active session's terminal.

### FR-029-A.4: Socket.IO Session Binding

**Description:** Each session maintains its own Socket.IO connection following the existing 1:1 pattern.

**Details:**
- Input: Session creation or page reload with stored session_id
- Process: Create Socket.IO connection, emit `attach` with `{session_id, rows, cols}`. Listen for `output`, `session_id`, `new_session`, `reconnected` events.
- Output: Bidirectional terminal I/O stream between browser and PTY

### FR-029-A.5: Session Data Model

**Description:** Frontend maintains a session data model for each session.

**Details:**
- Input: Session creation events
- Process: Store per-session data: `{ session_id, name, terminal, socket, fitAddon, container, isActive }`
- Output: Sessions map accessible for switching, rendering explorer list, and cleanup

## Non-Functional Requirements

### NFR-029-A.1: Performance
- Session switching MUST complete within 50ms (CSS display toggle, no re-render)
- Creating a new session MUST complete within 2s (including PTY spawn)
- Explorer panel rendering MUST not cause layout shift or jank on the terminal area

### NFR-029-A.2: Memory
- Each xterm.js instance uses ~2MB memory (1000-line scrollback)
- Maximum memory footprint: 10 sessions × 2MB = 20MB for terminal instances
- OutputBuffer: 10 sessions × 10KB = 100KB

### NFR-029-A.3: Compatibility
- All new code follows existing patterns in `terminal.js` and `terminal_service.py`
- One Socket.IO connection per session (no multiplexing)
- Backend `SessionManager` class reused without structural changes

### NFR-029-A.4: Resilience
- If a PTY process dies (exit/signal), its session shows "[Process exited]" in the terminal
- Socket.IO disconnect for one session MUST NOT affect other sessions
- Page reload reconnects to all sessions with valid `session_id` in localStorage

## UI/UX Requirements

### Layout Structure

```
┌────────────────────────────────────────────────────────────┐
│ Console Header  [status] [voice] [+ btn] [zen] [collapse]  │
├──────────────────────────────────┬─────────────────────────┤
│                                  │  Session Explorer       │
│                                  │  ┌───────────────────┐  │
│   Active Terminal                │  │ ● Session 1    ✎ 🗑│  │
│   (full width - explorer)        │  ├───────────────────┤  │
│                                  │  │ ○ Session 2    ✎ 🗑│  │
│                                  │  ├───────────────────┤  │
│                                  │  │ ○ Session 3    ✎ 🗑│  │
│                                  │  └───────────────────┘  │
│                                  │                         │
│                                  │        [ + ]            │
└──────────────────────────────────┴─────────────────────────┘
```

### UI Elements

| Element | Type | Location | Behavior |
|---------|------|----------|----------|
| Session Explorer Panel | `<div>` | Right side of console | Fixed width (220px default), vertical session list |
| Session Bar | `<div>` | Inside explorer | Shows session name + status indicator. Clickable to switch. |
| Status Indicator | `<span>` | Left of session name | Green filled dot (●) = active, dim dot (○) = background |
| "+" Button | `<button>` | Explorer panel bottom or header | Creates new session. Disabled at 10/10. |
| Terminal Content Area | `<div>` | Left of explorer | Holds all xterm.js containers (only active visible) |

### User Flows

**Flow 1: First Console Open**
1. User expands console panel (click header or first open)
2. System creates "Session 1" PTY + xterm.js + Socket.IO
3. Explorer panel shows "Session 1" with active indicator
4. Terminal area shows "Session 1" output

**Flow 2: Create New Session**
1. User clicks "+" in explorer
2. System creates "Session N" (next sequential number)
3. New session becomes active — previous session hidden
4. Explorer highlights new session, previous shows dim indicator

**Flow 3: Switch Session**
1. User clicks "Session 2" bar in explorer
2. Active terminal container set to `display: none`
3. Session 2 container set to `display: block`
4. FitAddon resizes Session 2 terminal
5. Explorer indicator updates (Session 2 = active)

### Empty & Error States

| State | Behavior |
|-------|----------|
| No sessions (impossible by design) | Auto-create "Session 1" |
| PTY creation failure | Show error toast, "+" button re-enabled, existing sessions unaffected |
| Session at limit (10/10) | "+" button disabled, tooltip "Maximum 10 sessions" |
| Socket disconnect on one session | Show yellow indicator for that session, auto-reconnect per existing logic |

## Dependencies

### Internal Dependencies
- **FEATURE-005 (CR):** Extends existing console terminal infrastructure — reuses `SessionManager`, `PersistentSession`, `OutputBuffer`, Socket.IO event protocol, xterm.js configuration. Replaces split-pane model.

### External Dependencies
- **xterm.js 5.3.0:** Terminal emulator library (already installed)
- **@xterm/addon-fit:** Terminal resize addon (already installed)
- **Socket.IO 4.x client:** WebSocket communication (already installed)
- **Flask-SocketIO 5.x:** Server-side WebSocket handling (already installed)

### File Dependencies

| File | Change Type | Description |
|------|-------------|-------------|
| `src/x_ipe/static/js/terminal.js` | Major refactor | Replace `TerminalManager` multi-pane model with sessions map, add explorer rendering |
| `src/x_ipe/templates/index.html` | Modify | Replace `terminal-panes` structure with `terminal-content` + `session-explorer` |
| `src/x_ipe/static/css/terminal.css` | Major update | Add explorer panel styles, remove split-pane styles |
| `src/x_ipe/services/terminal_service.py` | Minor | Raise MAX_TERMINALS constant if exists (frontend is primary enforcer) |

## Business Rules

### BR-1: Session Limit
**Rule:** Maximum 10 concurrent terminal sessions per user. This balances usability with resource consumption (PTY processes, Socket.IO connections, memory).

### BR-2: Default Session
**Rule:** Console MUST always have at least 1 session. If no sessions exist (first load or all deleted), auto-create "Session 1".

### BR-3: Sequential Naming
**Rule:** Default session names follow "Session N" pattern where N increments from the highest existing number + 1. Users can rename sessions later (FEATURE-029-B).

### BR-4: Active Session Exclusivity
**Rule:** Exactly one session is active at any time. There is no split-view or multi-session-visible mode.

## Edge Cases & Constraints

### Edge Case 1: Rapid Session Creation
**Scenario:** User clicks "+" rapidly 10 times in succession.
**Expected Behavior:** Each click creates one session sequentially. When 10th is created, "+" becomes disabled. No duplicate sessions, no race conditions. PTY creation errors show toast per session.

### Edge Case 2: PTY Process Dies
**Scenario:** A background session's shell process exits (e.g., `exit` command or killed externally).
**Expected Behavior:** Terminal shows "[Process exited]" or similar. Session remains in explorer (not auto-removed). User can delete it manually (FEATURE-029-B) or switch to see the exit message.

### Edge Case 3: Page Reload with Active Sessions
**Scenario:** User reloads page while 5 sessions are running.
**Expected Behavior:** All session_ids stored in localStorage. On reload, system reconnects to each via `attach` with stored session_id. Buffer replay restores recent output. Sessions that timed out (>1hr) create new PTY.

### Edge Case 4: Socket.IO Disconnect on Background Session
**Scenario:** Network glitch causes Socket.IO disconnect for a background session.
**Expected Behavior:** Auto-reconnect attempts (exponential backoff 1-5s). When user switches to that session, buffer replay fills in any missed output. No disruption to other sessions.

### Edge Case 5: Browser Tab Backgrounding
**Scenario:** User switches to another browser tab for extended time.
**Expected Behavior:** Socket.IO connections may be throttled by browser. On tab return, all sessions reconnect and replay buffers. No data loss.

### Edge Case 6: xterm.js Container Not Visible on Switch
**Scenario:** Switching to a session whose container has `display: none`.
**Expected Behavior:** Set `display: block`, then call `fitAddon.fit()` to recalculate dimensions. Terminal renders correctly at current container size.

### Constraints
- `Terminal.open(element)` is one-time per xterm.js instance — cannot detach and reattach
- Browser enforces ~6 concurrent WebSocket connections per host (HTTP/1.1); Socket.IO uses single connection multiplexed by namespace, but our pattern uses separate connections — verify browser limit compatibility
- PTY creation (`pty.fork()`) can fail if OS ulimit is reached

## Out of Scope

- Keyboard shortcuts for session navigation (Ctrl+Tab) — planned for future
- Drag-to-reorder sessions in the explorer — future enhancement
- Session grouping or tagging — future enhancement
- Split-pane view within a single session — explicitly removed
- Session sharing or duplication — future
- Inline rename and delete actions — FEATURE-029-B
- Hover preview — FEATURE-029-C
- Collapse/expand/resize controls — FEATURE-029-D
- Session name persistence in localStorage — FEATURE-029-D

## Technical Considerations

- The `TerminalManager` class must be refactored from an array-based model (2 panes) to a Map-based model (keyed by session_id) supporting up to 10 sessions
- The `.terminal-panes` container with its flex-row multi-pane layout should be replaced with a `.terminal-content` (single active terminal) + `.session-explorer` (right panel) layout
- xterm.js instances should be created once via `terminal.open(container)` and toggled via CSS `display` — never detached/reattached
- `FitAddon.fit()` must be called on the active terminal after any switch or resize event, since `display: none` terminals report zero dimensions
- The existing `add-terminal-btn` in the header can be relocated to the explorer panel
- Connection status indicator should reflect the active session's connection state
- Session IDs should be stored in localStorage as an array for reconnection on reload
- The backend `SessionManager` has no hardcoded limit — the 10-session limit is enforced purely in the frontend

## Open Questions

1. **Socket.IO Connection Limit:** Should we verify browser WebSocket connection limits (6 per host in HTTP/1.1)? If Socket.IO uses a single transport connection, this may not be an issue. If each session opens a separate connection, we need to test with 10 concurrent sessions.

2. **Zen Mode + Explorer:** When zen mode is active, should the explorer panel be visible or hidden? Current assumption: hidden (terminal takes full screen).

3. **Console Voice Controls (FEATURE-021):** The voice control buttons are in the terminal header center. Do they apply to the active session only? This is an integration detail for spec refactoring.
