DSH sessions: UI specification

August 22, 2026 · View on GitHub

Status: proposed vNext.

This document defines how the session tree appears in the DSH Web client. It keeps the existing sidebar and the existing active-session subagent control; the new tree adds only the navigation needed for fork sessions.

The implementation contract for the tools and physical logs is in SPEC.md.

1. Product decision

The sidebar is for durable sessions that a user may navigate to directly:

  • main sessions;
  • fork sessions.

Subagents are not sidebar items. They already appear in the active session header, as shown by the existing 2 个子代理 control. Keeping them there prevents the same helper session from appearing twice and keeps the workspace list navigable.

sidebar                         active conversation
────────                         ───────────────────
main session                    session header
└── forks                       └── subagent dropdown
    └── fork                        ├── helper 1
                                     └── helper 2

The backend still returns subagents in session_status. The UI is allowed to project only the parts relevant to navigation.

2. Sidebar layout

The current DSH sidebar remains the base layout:

┌─────────────────────────────────────────┐
│  whale  DSH Local Build             ◫   │
│                                         │
│              ⊕  新会话                  │
│                                         │
│  快捷入口                                │
│      ▣  技能                         ›   │
│                                         │
│  工作区             ⌕  ☷  ▣+            │
│  📁 dsh-playground                      │
│                                         │
│  ⌄  Simple greeting session       刚刚  │
│     │                                   │
│     └─ FORKS                             │
│        └─ Authentication branch  idle   │
│           [worktree]                    │
│                                         │
│  ›  Another session                刚刚  │
└─────────────────────────────────────────┘

No new global panel, graph view, or second navigation column is required for the first version.

2.1 Main session rows

A main session keeps the current row treatment:

  • title is the primary label;
  • last-updated text remains right-aligned;
  • the selected row uses the existing rounded gray selection fill;
  • a caret appears only when the session has at least one fork;
  • clicking the title opens the session;
  • clicking the caret expands or collapses its fork list.

When a main session has no forks, it behaves exactly like an existing flat session row. There is no empty FORKS group.

2.2 Fork rows

Forks appear directly below their main parent, indented one level under a small FORKS group label. A fork row shows:

  • a branch/fork icon;
  • the fork title;
  • its status dot or short status label;
  • a compact worktree badge only when it uses a separate worktree.

The full session ID, log path, and absolute worktree path are not shown in the row. They are available through the session details or context menu.

⌄  Simple greeting session                         刚刚

   └─ FORKS
      ├─ Authentication branch       worktree   idle
      └─ UI cleanup fork                         cold

If a fork contains subagents, the sidebar does not add another nested SUBAGENTS section. Opening that fork displays its own subagent control in the conversation header.

2.3 Worktree presentation

worktree is a small state badge, not a second workspace tree. It indicates that the fork's cwd differs because the host provisioned a worktree.

The UI must not display a guessed path such as .worktrees/<name>. If the user opens details, it may show the actual provider-returned cwd and offer a copy action. If the worktree is unavailable, show a neutral warning state and keep the session row selectable.

3. Active-session header

The active session header remains the operational home for subagents:

Simple greeting session   ◌ Ephemeral AI Harness   2 个子代理 ︿
                                                   ┌──────────────────┐
                                                   │ ● greeting 1      │
                                                   │   6.4K tok · 7秒  │
                                                   │                  │
                                                   │ ● greeting 2      │
                                                   │   3.2K tok · 2秒  │
                                                   └──────────────────┘

The dropdown may show:

  • subagent title;
  • running/idle/ready status;
  • token or activity summary when already provided by the host;
  • continue or message actions for continuable subagents;
  • a link or action to open the subagent if the host supports it.

The session tree sidebar must not duplicate this list.

3.1 Recursive behavior

When a user opens a fork, the header dropdown shows the fork's own subagents. When a subagent creates another subagent, the child remains within that operational control hierarchy. The sidebar still shows only the durable main/fork navigation path.

sidebar navigation                  header for selected session
──────────────────                  ───────────────────────────
main                                subagents of main
└── fork                            subagents of fork when fork selected
                                    subagents may create more subagents

The UI does not need to render recursion as a second graph. The current session context and the header dropdown provide the necessary scope.

4. Data projection

session_status returns a complete nested response:

{
  "tree": {
    "session_id": "main-123",
    "kind": "main",
    "title": "Simple greeting session",
    "forks": [
      {
        "session_id": "fork-456",
        "kind": "fork",
        "title": "Authentication branch",
        "worktree": "/actual/provider/path",
        "forks": [],
        "subagents": [
          {
            "session_id": "agent-789",
            "kind": "subagent",
            "title": "Source checker",
            "forks": [],
            "subagents": []
          }
        ]
      }
    ],
    "subagents": []
  }
}

The sidebar projection is intentionally narrower:

renderSessionRow(tree)
renderForkRows(tree.forks)
// Do not render tree.subagents in the sidebar.

The active-session header uses the current session's subagents collection. It may use the host's live subagent catalog for token and continuation state, but it must keep the same parent-session scope.

5. Interaction rules

ActionResult
Click main-session titleOpen the main session
Click main-session caretExpand/collapse its forks
Click fork titleOpen the fork session
Click worktree badgeOpen details or copy the actual cwd
Open active-session subagent controlShow subagents of that session
Continue/message a subagentUse session_send within the allowed parent scope
Search workspaceSearch main and fork rows; do not flatten subagents into results
Rename sessionChange title only; preserve ID, path, and relationships

Selecting a subagent from the header, if supported by the host, may open that subagent as a focused conversation. It must not make the subagent a permanent top-level sidebar row.

6. Empty, loading, and failure states

No forks

Render the normal session row with no caret and no FORKS label.

Forks loading

Keep the main session row visible and show a small inline loading indicator in the expanded area. Do not reorder the workspace or duplicate the main row.

Missing or cold fork

Keep the fork selectable. Use the host's existing cold/missing status treatment and let the normal session-open flow report whether the session can be resumed.

Worktree unavailable

Keep the fork visible, show a warning indicator, and expose the recorded worktree path in details. Do not silently fall back to the parent's cwd.

No active subagents

The session header keeps its existing zero-subagent state. The sidebar does not gain an empty subagent section.

7. Accessibility and visual rules

  • Main and fork rows are keyboard-focusable controls.
  • The caret is a separate button or has an equivalent accessible control name; it must not make expanding a row impossible without opening the session.
  • Use aria-expanded and aria-controls for expanded fork groups.
  • The selected session uses more than color alone: focus, selection fill, and the active title provide redundant state.
  • Status must not rely on color alone; include a text label or accessible name.
  • Worktree is supplemental metadata and must have an accessible label.
  • Preserve the existing DSH sidebar width, typography, spacing, borders, and icon language. Do not introduce a new icon library or a large card layout.

8. Explicit non-goals

The first UI version does not include:

  • subagent rows in the workspace sidebar;
  • a DAG/canvas/graph view;
  • a second sidebar for agents;
  • raw session IDs in normal rows;
  • absolute log paths in normal rows;
  • automatic worktree creation when expanding a row;
  • a new subagent execution panel;
  • a separate browser-side session index.

The result should feel like the current DSH sidebar with one additional expandable FORKS section, while the existing header remains responsible for subagent visibility and control.