* feat(web): add project-based dashboard architecture
- Add project query parameter to API routes
- Filter sessions by project in both SSR and SSE
- Update useSessionEvents hook to accept project param
- Update Dashboard and pass project to hook
- Add unit tests for project filtering
- Add architecture spec document
Implements project-based architecture as defined in docs/specs/project-based-dashboard-architecture.md:
- GET /api/sessions?project=X returns sessions for project X
- GET /api/events?project=X streams only sessions for project X
- Dashboard uses project filter from config
- SSE URL includes project param when provided
- Project matching uses projectId and sessionPrefix
- Full backward compatibility maintained (no param = all sessions)
* fix: remove duplicate export default in page.tsx
* fix(web): clean project-scoped dashboard verification
* fix(web): scope dashboard using project id
* fix(web): address Bugbot findings in project-scoped dashboard
- Consolidate triplicated matchesProject into shared lib/project-utils.ts
- Fix Dashboard to receive both projectId (for SSE filtering) and projectName (for display)
- Remove inline matchesProject definitions from page.tsx, sessions/route.ts, events/route.ts
* fix(web): resolve Bugbot issues in project-scoped dashboard
- Add ?project=all query param support in SSR page to show all sessions
(previously getPrimaryProjectId() always returned non-empty, making
else branches unreachable)
- Exclude orchestrator sessions from SSE stream to match SSR/API behavior
(orchestrator sessions get their own button, not a card)
- Add tests for SSE stream orchestrator exclusion and project filtering
Addresses Bugbot issues:
- #2903595986: Dead else branches when project filter always applied
- #2903595995: SSE stream includes orchestrator sessions unlike SSR/API
* feat(web): add project navigation sidebar
Add visible left sidebar with project navigation for multi-project setups:
- ProjectSidebar component with active state styling
- /api/projects endpoint to fetch configured projects
- getAllProjects() helper in project-name.ts
- Sidebar appears only when 2+ projects configured
- Click navigation updates ?project= query param
- Active project highlighted with accent color
Tests:
- ProjectSidebar component tests (8 tests)
- API routes tests with proper mocking
- All 386 web tests passing
Manual test steps:
1. Configure 2+ projects in agent-orchestrator.yaml
2. Start dashboard - sidebar should appear on left
3. Click different projects - URL updates, sessions filter
4. Click "All Projects" - shows all sessions across projects
5. Active project highlighted in sidebar
* fix(web): remove duplicate import in test file
* fix(web): consolidate ProjectInfo type to shared source
Remove duplicated ProjectInfo interface definitions from Dashboard.tsx and
ProjectSidebar.tsx. Both now import the type from @/lib/project-name where it is exported as the single source of truth.
This addresses Bugbot issue #2906835895: Triplicated ProjectInfo type instead of shared import.
* fix(web): integrate globalPause state from main
* fix(web): consolidate duplicate @/lib/types import
* feat(web): add project-based dashboard architecture
- Add project query parameter to API routes
- Filter sessions by project in both SSR and SSE
- Update useSessionEvents hook to accept project param
- Update Dashboard and pass project to hook
- Add unit tests for project filtering
- Add architecture spec document
Implements project-based architecture as defined in docs/specs/project-based-dashboard-architecture.md:
- GET /api/sessions?project=X returns sessions for project X
- GET /api/events?project=X streams only sessions for project X
- Dashboard uses project filter from config
- SSE URL includes project param when provided
- Project matching uses projectId and sessionPrefix
- Full backward compatibility maintained (no param = all sessions)
* fix: remove duplicate export default in page.tsx
* fix(web): clean project-scoped dashboard verification
* fix(web): scope dashboard using project id
* fix(web): address Bugbot findings in project-scoped dashboard
- Consolidate triplicated matchesProject into shared lib/project-utils.ts
- Fix Dashboard to receive both projectId (for SSE filtering) and projectName (for display)
- Remove inline matchesProject definitions from page.tsx, sessions/route.ts, events/route.ts
* fix(web): resolve Bugbot issues in project-scoped dashboard
- Add ?project=all query param support in SSR page to show all sessions
(previously getPrimaryProjectId() always returned non-empty, making
else branches unreachable)
- Exclude orchestrator sessions from SSE stream to match SSR/API behavior
(orchestrator sessions get their own button, not a card)
- Add tests for SSE stream orchestrator exclusion and project filtering
Addresses Bugbot issues:
- #2903595986: Dead else branches when project filter always applied
- #2903595995: SSE stream includes orchestrator sessions unlike SSR/API
* feat(web): add project navigation sidebar
Add visible left sidebar with project navigation for multi-project setups:
- ProjectSidebar component with active state styling
- /api/projects endpoint to fetch configured projects
- getAllProjects() helper in project-name.ts
- Sidebar appears only when 2+ projects configured
- Click navigation updates ?project= query param
- Active project highlighted with accent color
Tests:
- ProjectSidebar component tests (8 tests)
- API routes tests with proper mocking
- All 386 web tests passing
Manual test steps:
1. Configure 2+ projects in agent-orchestrator.yaml
2. Start dashboard - sidebar should appear on left
3. Click different projects - URL updates, sessions filter
4. Click "All Projects" - shows all sessions across projects
5. Active project highlighted in sidebar
* fix(web): remove duplicate import in test file
* fix(web): consolidate ProjectInfo type to shared source
Remove duplicated ProjectInfo interface definitions from Dashboard.tsx and
ProjectSidebar.tsx. Both now import the type from @/lib/project-name where it is exported as the single source of truth.
This addresses Bugbot issue #2906835895: Triplicated ProjectInfo type instead of shared import.
* fix(web): integrate globalPause state from main
* fix(web): consolidate duplicate @/lib/types import
* fix(web): restore global pause state and membership refresh
* fix(web): satisfy lint in project-scoped page defaults
* fix(web): remove dead global pause reducer action
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* fix(web): restore global pause resume time
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* chore(web): retrigger bugbot after thread reset
* refactor(web): centralize project session filtering helpers
* fix(web): reset pause banner dismissal on new pause
* fix(web): remove useless orchestrator assignment
* fix(web): derive header stats from live session state
* fix(web): restore project name in dashboard header
* fix(web): restore backlog poller startup in events stream
* refactor(web): keep project-utils helpers internal
* chore: retrigger bugbot evaluation
* chore: retrigger stuck bugbot check
* fix: address latest bugbot findings for dashboard events
* test(web): add dashboard bugbot regression coverage
* refactor(web): simplify projectId selection in dashboard props
* fix(web): derive selected project name from project filter
* refactor(web): initialize dashboard defaults before service load
* fix(web): satisfy lint in dashboard page error path