7.0 KiB
Agent Note: Workspace Sidebar Order and Folding
Status: implemented
English | 中文
Problem
A Workspace with many Sessions can consume the entire sidebar and push other Workspaces out of reach. A compact list needs a bounded default while preserving an explicit route to every Session. The sidebar also needs an activity-oriented order, but WorkspaceView.sessionIds is the durable manual account and must not be rewritten by Session activity.
Workspace groups themselves had no user-controlled durable order. Browser-native drag additionally rejects a drop released outside the list and animates the row back even when the application still has a valid insertion marker. Expanded Workspace sections make header-only hit testing ambiguous because the visual boundary between two groups does not match either header's midpoint.
Decision
Workspace order
The Workspace registry owns a durable workspaceIds order and exposes insertBefore(id, beforeId?) with DOM insertBefore semantics. The Host RPC workspace.insertBefore returns the complete committed order, and a pure order mutation emits host/workspace-order-changed with the same complete order. Unknown source or anchor ids reject as workspace-not-found; self-anchored and already-positioned moves do not write.
The client installs a Workspace drag optimistically. Request and frame generations ensure that only the latest unary echo can replace local order and that a newer Host frame outranks an older response; a latest rejected request restores the last complete order accepted from a Host baseline, frame, or current unary echo. Every successful list baseline restores Host order so reconnects adopt durable changes made elsewhere.
Session folding and view order
Each Workspace persists one browser-local open state: closed means zero Session rows and open means up to five. When more Sessions exist, Show more reveals the remainder only for the current mount; closing the whole Workspace clears this transient expansion, so reopening returns to five. The current Session's group opens automatically only when the user has not already stored an explicit state for that Workspace. After a ready Workspace baseline changes, the browser removes expansion, order, and observed-timestamp records for ids absent from that baseline while retaining the Ungrouped key for expansion, order, and observed timestamps.
The combined view menu offers Manual and Last updated over one browser-local persisted order per group. A real Workspace initializes from WorkspaceView.sessionIds; Ungrouped initializes from recency and has no Host Session account. Entering Last updated performs one complete recency sort; a later user prompt or steer promotes that Session once, and dragging may edit the resulting order. Returning to Manual preserves the current order and only disables later activity promotion. Manual-mode drags for a real Workspace also write the Host Session account, while Ungrouped drags and activity promotion remain browser-local. The flat list uses recency because it has no single group account for Session drag.
Drag and compact chrome
Workspace hit testing uses the complete rendered group section, including visible Session rows. One insertion boundary is shared by the preceding group's lower half and the following group's upper half, and the indicator is an absolutely positioned line that does not affect layout. A tree-body overlay draws the first boundary at the same negative offset outside the scrolling clip, so its hollow leading circle remains visible without moving the list. During a Workspace or Session drag, document-level dragover and drop handlers accept the native operation; if release occurs outside the Workspace list, dragend commits the last valid marker.
Search is a header action while collapsed and expands across the title and trailing actions. An outside click collapses a query that is empty after trimming but retains a non-empty query. Compact Workspace and Session rows, a 24px bottom fade, and the absence of per-Workspace Session counts preserve vertical space without removing navigation affordances.
Alternatives considered
Write every activity promotion into Workspace.sessionIds. A browser presentation preference would overwrite the shared Host account whenever a user submits a prompt.
Keep independent Manual and Last updated orders. Switching modes would replace the visible list with stale positions from the other order, even though choosing Manual only means that later activity stops moving rows.
Always show every Session in an open Workspace. One large Workspace would continue to crowd out the rest, and remembering only the whole-group open state would not bound its height.
Persist the expanded-remainder state. A Workspace reopened much later could unexpectedly occupy the full sidebar. Only the zero-or-five state represents a stable navigation preference; revealing the remainder is a local inspection.
Use numeric drop indices or header-only hit testing. Indices drift when rows change during a drag, while header midpoints disagree with the visible boundary when a Workspace is expanded. Anchor ids and full-section geometry remain stable under both conditions.
Let the browser reject an outside release. The application would commit the last valid marker while the browser displays a rejected-drop animation, presenting contradictory feedback.
Consequences
- Workspace order is durable and shared through the Host, while grouping, open state, per-group Session view order, and query state remain browser-local presentation preferences. Ungrouped supports the same drag and promotion rules, but its order is browser-local because no Workspace owns those Sessions.
- Last updated performs a complete recency sort on entry, then preserves manual adjustments until a user prompt or steer advances one Session and moves it to the front. Returning to Manual preserves every current position.
- Opening a Workspace never shows more than five Sessions without an explicit Show more gesture, and closing it resets only that transient gesture.
- The Host Session account retains the manual-order meaning established by Session List Browsing and Manual Workspace Order.
Testing
Domain and Host tests cover durable Workspace moves, no-op and invalid anchors, restart recovery, full-order RPC responses, order frames, and one Workspace snapshot per Host-stream baseline. Runtime tests cover optimistic order, frame/response precedence, overlapping rejection rollback to Host-confirmed order, reconnect baselines, and New Session target priority. UI tests cover five-row folding, transient expansion reset, pruning persisted state after Workspace removal, order-preserving mode switches, one-time recent-update promotion, browser-local Ungrouped drag persistence in both modes, selected view indicators, expanded-section Workspace hit testing, an unclipped first insertion boundary, outside-list Workspace and Session drops, search collapse rules, and compact CSS dimensions.