| name | maintain-session-sidebar |
| description | Maintain the Chat/Live session sidebar, new-task and clear-all controls, session rows, mode markers, and footer chrome. Use when changing history navigation, session actions, labels, or sidebar layout and accessibility. |
Maintain the session sidebar
Role and boundary
Keep the sidebar as a projection of ChatStore plus current provider/session chrome. It owns row rendering and user actions, not persistence rules, generation orchestration, or Live's native lifecycle; delegate those concerns to their owners.
Source map
src/main.ts: renderApp() sidebar markup and wireStatusChrome footer projection; src/chat.ts: wireChat, row rendering, delegated row listeners, clear confirmation, and reset projection; src/chat-turn.ts: guarded activate/delete/clear/new-task ordering across speech and Live.
src/chat-store.ts: ChatStore, ChatState, ChatSession, newSession, activate, deleteSession, clearSessions, and subscriber notifications.
src/style.css: .sidebar, .sidebar-actions, .session-navigation, .session-list, .session-item*, .clear-all-button, and .sidebar-footer selectors.
src/chat-message-view.ts: tool-message rendering reached from a selected session; tests/chat-turn.test.ts, tests/chat-store.test.ts, tests/live.test.ts, and tests/voice-shortcuts.test.ts: action and persistence contracts.
Cover
- Render sessions most-recently-updated first with
aria-current, accessible titles, text-safe mode markers ([l]/[c]), ellipsis-safe labels, and a separately labelled permanent-delete button.
- Keep New task's empty-session reuse, first-message title truncation, clear-all confirmation, final-session replacement, and disabled actions while generation or a session mutation is active.
- Treat
ChatController.isInteractionBlocked() as the authoritative turn/session race guard. Do not rely on button disability alone; controller methods must reject competing programmatic or already-queued actions while speech or Live teardown is pending.
- Await speech stop and, when needed, Live stop before switching, deleting, or clearing so late native events cannot write to a removed session; clear the composer draft and restore focus after activation.
- Preserve the footer's real session count/provider label and the sidebar's Chat/Live-only visibility; Settings and Debug must not expose session controls.
- Inspect current
ChatStore invariants before changing row behavior. Do not infer voice provenance, status, or mode from CSS; read typed session/message fields.
Validate and accept
- Run
bun test tests/chat-turn.test.ts tests/chat-store.test.ts tests/live.test.ts tests/voice-draft-provenance.test.ts and exercise keyboard focus, long titles, empty/final-session deletion, and clear confirmation.
- Run
git diff --check against the actual files changed; run just check when the change crosses TypeScript/Rust/build boundaries. Inspect the sidebar at 1200×900 and responsive breakpoints; use $test-voice-layer-app for packaged focus/accessibility acceptance.
- Treat persistence reload, Live/session races, and human confirmation behavior as acceptance checks beyond unit coverage.
Relationships
Use $maintain-sessions for storage/schema and lifecycle semantics, $maintain-chat for composer/generation, $maintain-live for pinned Live sessions, and $maintain-navigation for destination switching.