- Create SearchResults component with virtualized list, term highlighting via <mark>, keyboard navigation, loading/empty states
- Add search scope toggle (All Channels / This Channel) with radio group accessibility
- Integrate debounced (300ms) IPC search into CommunicationHub with stale response discard via requestId
- Update CommunicationSlice with search state (query, scope, results, loading, requestId)
- Modify FilterBar to accept scopeToggle prop and Escape key handler
- AnimatePresence cross-fade between SearchResults and MessageList views
- Install @tanstack/react-virtual for virtualized list rendering
- Create useRovingTabIndex hook in src/renderer/lib/keyboard.ts for arrow-key navigation
- Add virtualization to 6 lists: TaskQueue, ApprovalList, ActivityList, CostList, AgentRoster, MessageList
- MessageList uses measureElement for variable-height message items with auto-scroll
- All 6 lists have role="listbox" with role="option" on rows for accessibility
- All 6 lists support ArrowDown/ArrowUp/j/k/Home/End keyboard navigation
- Add 8 unit tests for useRovingTabIndex covering all key bindings and edge cases
- CommunicationHub.tsx: main layout shell with sidebar + message area
- ChannelSidebar.tsx: channel list with unread badges and filter bar
- MessageList.tsx: message display with threading and empty states
- MessageItem.tsx: message bubble, task comment bubble, agent avatar
- MessageComposer.tsx: message input, task discussion composer, compose modal
- ChannelHeader.tsx: channel info bar with stats
- channel-utils.ts: shared channel derivation and message filtering logic
- Original communication.tsx replaced with backward-compatible re-exports
- All sub-components under 300 lines, TypeScript compilation passes