- Add reusable useFocusTrap hook for modal focus management with
Escape key support and focus restoration on close
- Task board: add role=region and aria-label to kanban columns,
role=button and keyboard support (Enter/Space) to task cards,
role=alert on error display, role=status on loading spinner
- Modals: add role=dialog, aria-modal, aria-labelledby, focus
trapping, backdrop click to close, aria-label on close buttons
- Tab interface: add role=tablist/tab/tabpanel with aria-selected
and aria-controls for task detail tabs
- Forms: add htmlFor/id associations on all modal form labels
- Layout: add skip-to-content link for keyboard navigation,
id=main-content on main element
Addresses #40
- Create OfficePanel with Office floor plan and Org Chart view modes
- Desk-style cards with status glow, emoji indicators, pulse animation for busy agents
- Agent detail modal with task stats, activity, session info
- Auto-refresh every 10 seconds for real-time updates
- Status summary in header (working/idle/error/away counts)
- Add OfficeIcon and office nav item in CORE group
- Register office route in page.tsx
Closes#115
Co-authored-by: bhavikprit <petrobhakti@gmail.com>
* fix: migrate middleware.ts to proxy.ts for Next.js 16 (#88)
Next.js 16 deprecated the `middleware` file convention in favor of
`proxy`. The proxy runs on the Node.js runtime instead of Edge, so
safeCompare now uses crypto.timingSafeEqual instead of manual XOR.
All auth logic, CSRF validation, host matching, and security headers
are preserved unchanged.
* feat: add "Update Available" banner with GitHub release check
Add a dismissible emerald banner that appears when a newer GitHub release
exists, so self-hosting users know an update is available. The banner
dismisses per-version (reappears for new releases).
- Create src/lib/version.ts as single source of truth from package.json
- Add /api/releases/check route with 1hr caching and graceful fallback
- Add UpdateBanner component mirroring LocalModeBanner pattern
- Add update state to Zustand store with localStorage persistence
- Fix hardcoded v2.0 in header-bar.tsx and 2.0.0 in websocket.ts
Move page.tsx to [[...panel]] optional catch-all route so each panel
gets its own URL (e.g. /tasks, /agents, /settings). URL is the source
of truth — synced into Zustand via usePathname on every navigation.
Enables bookmarking, refresh persistence, deep-linking, and browser
back/forward.