feat(dashboard): Add phase-aware task view integration (#016-6) - #215
Conversation
This commit integrates phase-aware components into the Dashboard for the planning phase automation feature. Key changes: ## New Components - TaskList: Real-time task view during development phase with status filtering, progress display, agent assignment, and quality gates ## Dashboard Integration - Phase-aware Tasks tab: Shows TaskReview during planning, TaskList during development/review, and TaskTreeView for other phases - Tab badges: "Review (N)" badge during planning, "X/Y" progress badge during development ## Performance Optimization - Adaptive SWR polling: 5-second refresh during active work, 30-second refresh during idle phases - Computed `isActiveWork` state to detect when agents are working ## Tests - 35 new TaskList component tests covering rendering, filtering, styling, accessibility, and real-time updates - 7 new Dashboard integration tests for phase-aware rendering and badges - All 1483 tests pass Files changed: - web-ui/src/components/TaskList.tsx (new) - web-ui/__tests__/components/TaskList.test.tsx (new) - web-ui/src/components/Dashboard.tsx (modified) - web-ui/__tests__/components/Dashboard.test.tsx (modified)
WalkthroughDashboard now renders phase-aware task views (TaskReview for planning, TaskList for development/review, TaskTreeView otherwise), adds adaptive SWR polling intervals based on isActiveWork (5s vs 30s), and introduces TaskList plus comprehensive tests; test mocks now use data-testid attributes. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant Dashboard as Dashboard UI
participant SWR as SWR hooks
participant API as Backend/API
participant View as TaskView (TaskList/TaskReview/TaskTreeView)
Note over Dashboard,SWR: mount / tab select triggers data fetch
User->>Dashboard: Select "Tasks" tab
Dashboard->>SWR: request project, agents, issues, blockers (refreshInterval depends on isActiveWork)
SWR->>API: fetch data
API-->>SWR: return data
SWR-->>Dashboard: provide data (agents, tasks, phase)
alt phase == planning
Dashboard->>View: render TaskReview (inside ErrorBoundary)
View-->>User: show review UI + "Awaiting Approval" badge
else phase == development or review
Dashboard->>View: render TaskList (inside ErrorBoundary)
View-->>User: show list UI + "In Development" badge
else
Dashboard->>View: render TaskTreeView
View-->>User: show tree UI (no phase badge)
end
Note right of SWR: if isActiveWork -> interval=5s\nelse -> interval=30s
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
PR Review: Phase-Aware Task View Integration (#16-6)SummaryThis PR successfully implements phase-aware task rendering in the Dashboard Tasks tab, adding the new TaskList component for real-time task monitoring during development phases and integrating adaptive SWR polling. The implementation follows the project's architecture patterns and includes comprehensive test coverage. ✅ Strengths1. Excellent Component Architecture
2. Comprehensive Test Coverage
3. Smart Performance OptimizationThe adaptive polling logic is well-designed: // Active work: 5s, Idle: 30s
const isActiveWork = useMemo(() => {
const activeAgents = agents.filter(a => a.status === 'working' || a.status === 'blocked');
const activeTasks = tasks.filter(t => t.status === 'in_progress');
return activeAgents.length > 0 || activeTasks.length > 0;
}, [agents, tasks]);This significantly reduces unnecessary API calls during idle periods. 4. Accessibility First
5. shadcn/ui Nova Compliance
🔍 Issues & Recommendations1. Critical: Missing
|
| Priority | Issue | Action |
|---|---|---|
| HIGH | Missing 'pending' filter option | Add to FILTER_OPTIONS array |
| MEDIUM | Missing ErrorBoundary in TaskList | Wrap QualityGateStatus in ErrorBoundary |
| LOW | Empty state message clarity | Update message to mention "development phase" |
| LOW | Phase normalization readability | Extract to variable for clarity |
✨ Final Verdict
APPROVE with minor recommendations ✅
This is a high-quality PR that:
- ✅ Implements the feature spec correctly
- ✅ Includes comprehensive tests (100% scenario coverage)
- ✅ Follows project conventions and architecture
- ✅ Optimizes performance with adaptive polling
- ✅ Maintains accessibility standards
The identified issues are minor and don't block merging. The missing pending filter is the only notable gap, but since tests pass and the component functions correctly, it can be addressed in a follow-up PR if needed.
Recommended merge after addressing the HIGH priority issue (pending filter).
📚 Documentation
The PR description is excellent and includes:
- ✅ Clear summary of changes
- ✅ Comprehensive test checklist
- ✅ Build/lint verification
Suggestion: Add a note about the adaptive polling feature to the PR description, as it's a significant performance improvement.
Great work on this feature! The phase-aware dashboard integration significantly improves the UX during project development. 🚀
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @web-ui/__tests__/components/TaskList.test.tsx:
- Around line 428-453: The test is trying to override the useAgentState mock
with jest.doMock after TaskList has already been imported, so the new mock is
ignored; fix by isolating module imports: call jest.resetModules(), call
jest.doMock('@/hooks/useAgentState', ...) with the null-progress task, then
dynamically import TaskList (e.g., const { default: TaskList } = await
import('@/components/TaskList')) and render it to assert it doesn't throw;
alternatively move this edge-case into a separate test file where the mock can
be set before importing TaskList.
🧹 Nitpick comments (8)
web-ui/__tests__/components/Dashboard.test.tsx (1)
1400-1426: Consider adding a 'review' phase test for badge consistency.The tests cover
activephase but notreviewphase for the development badge. Since Dashboard.tsx shows the same badge for bothdevelopmentandreviewphases, consider adding a test forphase: 'review'to ensure consistent behavior.Optional: Add review phase test
it('renders TaskList component in Tasks tab during review phase', async () => { const reviewPhaseData = { ...mockProjectData, phase: 'review', }; (api.projectsApi.getStatus as jest.Mock).mockResolvedValue({ data: reviewPhaseData, }); renderWithSWR( <AgentStateProvider projectId={1}> <Dashboard projectId={1} /> </AgentStateProvider> ); await waitFor(() => { expect(screen.getByText(/Test Project/i)).toBeInTheDocument(); }); const tasksTab = screen.getByTestId('tasks-tab'); fireEvent.click(tasksTab); await waitFor(() => { expect(screen.getByTestId('task-list-component')).toBeInTheDocument(); }); });web-ui/src/components/TaskList.tsx (2)
241-249: Connection status uses hardcoded colors instead of semantic tokens.The connection indicator uses hardcoded
bg-green-500andbg-red-500colors, which deviates from the coding guidelines that recommend using semantic color palette tokens.Use semantic color tokens for connection status
<span - className={`w-2 h-2 rounded-full ${ - wsConnected ? 'bg-green-500 animate-pulse' : 'bg-red-500' - }`} + className={`w-2 h-2 rounded-full ${ + wsConnected ? 'bg-secondary animate-pulse' : 'bg-destructive' + }`} /> <span className="text-xs text-muted-foreground"> {wsConnected ? 'Live updates enabled' : 'Reconnecting...'} </span>
128-132: Consider using Hugeicons instead of emoji for blocked indicator.Per coding guidelines, Hugeicons (@hugeicons/react) should be used for icons. The blocked indicator currently uses the 🚫 emoji.
Replace emoji with Hugeicon
Add import at top:
import { Cancel01Icon } from '@hugeicons/react';Then update the blocked indicator:
{isBlocked && task.blocked_by && task.blocked_by.length > 0 && ( <div className="text-sm text-destructive mb-2"> - <span>🚫 Blocked by {task.blocked_by.length} task{task.blocked_by.length !== 1 ? 's' : ''}</span> + <span className="flex items-center gap-1"> + <Cancel01Icon className="w-4 h-4" /> + Blocked by {task.blocked_by.length} task{task.blocked_by.length !== 1 ? 's' : ''} + </span> </div> )}web-ui/src/components/Dashboard.tsx (4)
163-165: Consider moving polling interval constants outside the component.The
ACTIVE_REFRESH_INTERVALandIDLE_REFRESH_INTERVALconstants are defined inside the component, causing them to be recreated on each render. Moving them outside would be more efficient.Move constants outside component
+// Polling intervals for adaptive refresh (016-6) +const ACTIVE_REFRESH_INTERVAL = 5000; +const IDLE_REFRESH_INTERVAL = 30000; + export default function Dashboard({ projectId }: DashboardProps) { // ... - // Polling intervals based on activity (016-6) - // Active work: 5 seconds, Idle: 30 seconds - const ACTIVE_REFRESH_INTERVAL = 5000; - const IDLE_REFRESH_INTERVAL = 30000; const refreshInterval = isActiveWork ? ACTIVE_REFRESH_INTERVAL : IDLE_REFRESH_INTERVAL;
178-186: Blockers SWR uses inline ternary instead ofrefreshIntervalvariable.The blockers fetch uses an inline ternary for
refreshIntervalinstead of the pre-computedrefreshIntervalvariable defined on line 165. This is inconsistent and duplicates logic.Use the pre-computed refreshInterval variable
// Fetch blockers with adaptive polling const { data: blockersData, mutate: mutateBlockers } = useSWR( `/projects/${projectId}/blockers`, () => blockersApi.list(projectId).then((res) => res.data?.blockers || []), { - refreshInterval: isActiveWork ? ACTIVE_REFRESH_INTERVAL : IDLE_REFRESH_INTERVAL, + refreshInterval, revalidateOnFocus: true, } );
199-208: Issues SWR also uses inline ternary instead ofrefreshInterval.Same inconsistency as blockers - should use the pre-computed variable.
Use the pre-computed refreshInterval variable
// Fetch issues/tasks data (cf-26) with adaptive polling const { data: issuesData } = useSWR<IssuesResponse>( `/projects/${projectId}/issues`, () => projectsApi.getIssues(projectId).then((res) => res.data), { shouldRetryOnError: false, - refreshInterval: isActiveWork ? ACTIVE_REFRESH_INTERVAL : IDLE_REFRESH_INTERVAL, + refreshInterval, revalidateOnFocus: true, } );
429-437: Badge styling uses hardcoded purple/green colors instead of semantic tokens.The phase badges use hardcoded color classes (
bg-purple-100,bg-green-100, etc.) instead of semantic color palette tokens. This is inconsistent with other semantic styling in the component.Consider using semantic color tokens for badges
While the current colors work well visually, for consistency with the coding guidelines recommending semantic color palette usage, consider defining these as semantic tokens or using existing ones like
bg-secondary:<span data-testid="tasks-tab-badge-planning" - className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200 transition-opacity duration-200" + className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-accent text-accent-foreground transition-opacity duration-200" >Alternatively, if distinct colors are required for visual clarity, document why hardcoded colors are necessary here.
web-ui/__tests__/components/TaskList.test.tsx (1)
378-387: Keyboard navigation test may be flaky.The test assumes Tab will move focus to
filterButtons[1]after focusingfilterButtons[0]. However, the actual focus order depends on the DOM structure and may include other interactive elements between filter buttons.Consider a more robust focus test
it('should be keyboard navigable', async () => { const user = userEvent.setup(); render(<TaskList {...defaultProps} />); const filterGroup = screen.getByRole('group', { name: /filter tasks/i }); const filterButtons = within(filterGroup).getAllByRole('button'); // Focus first button filterButtons[0].focus(); expect(filterButtons[0]).toHaveFocus(); // Tab to next button within the group await user.keyboard('{Tab}'); // Verify some button in the group has focus expect(filterGroup).toContainElement(document.activeElement as Element); });
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
web-ui/__tests__/components/Dashboard.test.tsxweb-ui/__tests__/components/TaskList.test.tsxweb-ui/src/components/Dashboard.tsxweb-ui/src/components/TaskList.tsx
🧰 Additional context used
📓 Path-based instructions (4)
web-ui/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web-ui/src/**/*.{ts,tsx}: Use TypeScript 5.3+ for frontend development with React 18, Next.js 14, Tailwind CSS, and Hugeicons for icons
Use TypeScript strict mode and ensure 100% type safety with no hardcoded types or any usage in frontend code
Files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
web-ui/src/components/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
web-ui/src/components/**/*.tsx: Use shadcn/ui Nova template components with semantic color palette (bg-card, text-foreground, etc.) and avoid hardcoded color values
Use cn() utility for conditional Tailwind CSS classes and follow Nova's compact spacing conventions
Files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
web-ui/src/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Replace all icon usage with Hugeicons (@hugeicons/react) and do not mix with lucide-react
Files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
web-ui/src/components/Dashboard.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Use React.memo on all Dashboard sub-components and useMemo for derived state to optimize performance with multi-agent support
Files:
web-ui/src/components/Dashboard.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T19:08:54.154Z
Learning: Applies to specs/*/tasks.md : Feature task files (tasks.md) must include phase-by-phase task breakdown with unique task identifiers (T001, T002, etc.), acceptance criteria per task, beads issue references, and estimated effort
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/src/components/**/*.{ts,tsx} : Use functional React components with TypeScript interfaces
Applied to files:
web-ui/src/components/TaskList.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/**/*.{ts,tsx} : Use TypeScript 5.3+ for frontend development with React 18, Next.js 14, Tailwind CSS, and Hugeicons for icons
Applied to files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/components/Dashboard.tsx : Use React.memo on all Dashboard sub-components and useMemo for derived state to optimize performance with multi-agent support
Applied to files:
web-ui/src/components/TaskList.tsxweb-ui/__tests__/components/Dashboard.test.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/contexts/AgentStateContext.ts : Use context-based state management with React Context + useReducer pattern for Dashboard with AgentStateContext, agentReducer, and useAgentState hook
Applied to files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/**/__tests__/**/*.test.{ts,tsx} : Create JavaScript test files colocated or in __tests__/ as *.test.ts
Applied to files:
web-ui/__tests__/components/TaskList.test.tsxweb-ui/__tests__/components/Dashboard.test.tsx
📚 Learning: 2025-11-25T19:08:54.154Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T19:08:54.154Z
Learning: Applies to specs/*/tasks.md : Feature task files (tasks.md) must include phase-by-phase task breakdown with unique task identifiers (T001, T002, etc.), acceptance criteria per task, beads issue references, and estimated effort
Applied to files:
web-ui/__tests__/components/Dashboard.test.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/src/**/*.{ts,tsx} : Use SWR for server state management and useState for local state in React
Applied to files:
web-ui/src/components/Dashboard.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/app/page.tsx : Implement automatic project discovery start after project creation with loading state transitions and 'Start Discovery' button for idle projects
Applied to files:
web-ui/src/components/Dashboard.tsx
🧬 Code graph analysis (1)
web-ui/__tests__/components/Dashboard.test.tsx (2)
web-ui/src/components/AgentStateProvider.tsx (1)
AgentStateProvider(44-254)web-ui/src/components/Dashboard.tsx (1)
Dashboard(72-860)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Backend Unit Tests
- GitHub Check: Frontend Unit Tests
- GitHub Check: E2E Smoke Tests (Chromium)
- GitHub Check: claude-review
🔇 Additional comments (17)
web-ui/__tests__/components/Dashboard.test.tsx (5)
55-64: Well-structured mocks for phase-aware component testing.The mock components correctly include
data-testidattributes that align with the assertions in the phase integration tests. This enables reliable component detection during phase transitions.
1228-1268: Comprehensive planning phase test coverage.The test correctly verifies TaskReview rendering and "Awaiting Approval" badge during planning phase. Good isolation of phase-specific behavior.
1269-1303: Active phase test validates TaskList rendering.The test properly mocks
phase: 'active'and asserts TaskList component presence with "In Development" badge.
1305-1336: Discovery phase fallback correctly tested.Good coverage for the TaskTreeView fallback when neither planning nor active/review phase.
1338-1369: Badge count test uses mock data correctly.The test mocks
total_tasks: 5from issuesData and correctly asserts "Review (5)" badge content.web-ui/src/components/TaskList.tsx (4)
12-16: Clean imports and TypeScript interface.Good use of TypeScript interfaces for props and proper type imports from the types module.
38-50: Status styling uses semantic color palette correctly.The
getStatusStylesfunction appropriately uses semantic Tailwind classes (bg-primary/10,bg-destructive/10, etc.) as per coding guidelines.
68-154: TaskCard is properly memoized with displayName.Good adherence to coding guidelines with
React.memoanddisplayNameassignment. The component structure is clean with proper accessibility attributes on the progress bar.
161-174: Consider memoizing projectTasks filtering with useMemo dependency array.The
projectTasksfiltering is correctly memoized. However, iftasksarray reference changes frequently due to real-time updates, consider whether the filtering logic could benefit from more granular memoization or stable task IDs comparison.web-ui/src/components/Dashboard.tsx (4)
38-39: TaskList and TaskReview imports added.Clean imports for the new phase-aware components.
153-165: Adaptive polling logic is well-implemented.The
isActiveWorkcomputation correctly identifies active agents and tasks. The polling intervals (5s active, 30s idle) are reasonable for balancing responsiveness with resource usage.
422-445: Phase-aware badges implementation is correct.The badges correctly show "Review (N)" during planning and "X/Y" progress during development/review phases. The conditional rendering with
normalizePhaseensures consistency with the phase mapping.
667-706: Phase-aware task view rendering with ErrorBoundary protection.Good implementation with ErrorBoundary wrapping each component. The fallback messages are user-friendly and actionable.
web-ui/__tests__/components/TaskList.test.tsx (4)
18-70: Well-structured mock data and hook mocking.The mock tasks cover all status types (completed, in_progress, blocked, pending) with appropriate test data. The mock includes all necessary fields for comprehensive testing.
84-141: Thorough rendering tests with proper assertions.Tests cover task titles, status badges, agent assignments, progress display, and empty state. Good coverage of the main rendering scenarios.
143-245: Comprehensive filtering tests using userEvent.Good use of
userEvent.setup()for realistic user interactions. The tests properly verify filter state changes and task visibility.
363-394: Accessibility tests verify ARIA structure.Good coverage of list roles, listitem roles, and aria-labels. The keyboard navigation test is useful for accessibility compliance.
- Add missing 'pending' filter to FILTER_OPTIONS - Wrap QualityGateStatus in ErrorBoundary for error isolation - Fix empty state message to be more accurate - Add comprehensive polling strategy documentation comments - Add test for pending filter functionality (36 tests total) All 1484 tests pass, lint clean, no type errors.
Follow-Up Review: Post-FixesThank you for addressing the feedback! I can see that the "Pending" filter has been added to ✅ Fixed Issues from Previous Review
🔍 Remaining Minor IssueHardcoded Colors in Connection Status (TaskList.tsx:246-248) The connection indicator still uses hardcoded Tailwind colors instead of semantic tokens: // Current (hardcoded colors)
wsConnected ? 'bg-green-500 animate-pulse' : 'bg-red-500'
// Recommended (semantic tokens per CLAUDE.md)
wsConnected ? 'bg-secondary animate-pulse' : 'bg-destructive'Per CLAUDE.md guidelines (UI Template Configuration section), the Nova template requires semantic color palette variables. This is a very minor style consistency issue and does not block merging. ✨ Final VerdictAPPROVED ✅ All critical issues have been addressed:
The hardcoded color issue is cosmetic and can be addressed in a future PR if desired. The implementation is production-ready! Excellent work on the quick turnaround addressing the feedback! 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (6)
web-ui/__tests__/components/TaskList.test.tsx (1)
148-152: Consider usinggetByRolewithnameoption instead offind()with non-null assertions.The pattern of using
screen.getAllByRole('button').find(...)followed by non-null assertion (!) is fragile. If the button isn't found, the test will fail with a confusing error. Using Testing Library's built-in matchers provides clearer error messages.♻️ Suggested improvement for one example
- const inProgressButton = screen.getAllByRole('button').find( - (btn) => btn.textContent?.includes('In Progress') - ); - expect(inProgressButton).toBeInTheDocument(); - await user.click(inProgressButton!); + const inProgressButton = screen.getByRole('button', { name: /In Progress/i }); + await user.click(inProgressButton);Also applies to: 160-164, 177-180, 191-194, 205-208, 212-215, 227-230, 252-255
web-ui/src/components/TaskList.tsx (3)
245-252: Connection status uses hardcoded colors instead of semantic palette.Per coding guidelines, components should use semantic color palette (e.g.,
bg-secondary,text-destructive) and avoid hardcoded color values likebg-green-500andbg-red-500.♻️ Suggested fix using semantic colors
<span - className={`w-2 h-2 rounded-full ${ - wsConnected ? 'bg-green-500 animate-pulse' : 'bg-red-500' - }`} + className={`w-2 h-2 rounded-full ${ + wsConnected ? 'bg-primary animate-pulse' : 'bg-destructive' + }`} /> <span className="text-xs text-muted-foreground"> {wsConnected ? 'Live updates enabled' : 'Reconnecting...'} </span>
84-84: Consider usingcn()utility for conditional Tailwind CSS classes.Per coding guidelines for
web-ui/src/components/**/*.tsx, conditional Tailwind classes should use thecn()utility instead of template literals. This improves readability and handles edge cases with class merging.♻️ Example refactor for filter button styling
+import { cn } from '@/lib/utils'; // In the filter button: - className={`px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${ - activeFilter === option.status - ? 'bg-primary text-primary-foreground' - : 'bg-muted text-muted-foreground hover:bg-muted/80' - }`} + className={cn( + 'px-3 py-1.5 rounded-md text-sm font-medium transition-colors', + activeFilter === option.status + ? 'bg-primary text-primary-foreground' + : 'bg-muted text-muted-foreground hover:bg-muted/80' + )}Also applies to: 92-92, 119-119, 131-131, 142-142, 261-265
132-132: Consider using Hugeicons instead of emoji characters.Per coding guidelines, icon usage should use Hugeicons (
@hugeicons/react) instead of emoji characters like "🚫". This applies to other emojis in the codebase as well.web-ui/src/components/Dashboard.tsx (2)
161-165: Consider extracting polling interval constants to module scope.Moving
ACTIVE_REFRESH_INTERVALandIDLE_REFRESH_INTERVALoutside the component prevents recreation on each render and makes them easier to configure or test.♻️ Extract constants to module scope
+// Polling intervals for adaptive refresh strategy (016-6) +const ACTIVE_REFRESH_INTERVAL = 5000; // 5 seconds during active work +const IDLE_REFRESH_INTERVAL = 30000; // 30 seconds when idle const TaskList = memo(function TaskList({ projectId }: TaskListProps) { // ... - // Polling intervals based on activity (016-6) - // Active work: 5 seconds, Idle: 30 seconds - const ACTIVE_REFRESH_INTERVAL = 5000; - const IDLE_REFRESH_INTERVAL = 30000; const refreshInterval = isActiveWork ? ACTIVE_REFRESH_INTERVAL : IDLE_REFRESH_INTERVAL;
448-454: Potential division by zero in badge display.If
tasks.lengthis 0, displaying{tasks.filter(...).length}/{tasks.length}shows "0/0", which is technically correct but could be confusing. Consider hiding the badge when there are no tasks.♻️ Hide badge when no tasks exist
- {(normalizePhase(projectData.phase) === 'development' || normalizePhase(projectData.phase) === 'review') && ( + {(normalizePhase(projectData.phase) === 'development' || normalizePhase(projectData.phase) === 'review') && tasks.length > 0 && ( <span data-testid="tasks-tab-badge-development" className="..." > {tasks.filter(t => t.status === 'completed').length}/{tasks.length} </span> )}
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
web-ui/__tests__/components/TaskList.test.tsxweb-ui/src/components/Dashboard.tsxweb-ui/src/components/TaskList.tsx
🧰 Additional context used
📓 Path-based instructions (4)
web-ui/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web-ui/src/**/*.{ts,tsx}: Use TypeScript 5.3+ for frontend development with React 18, Next.js 14, Tailwind CSS, and Hugeicons for icons
Use TypeScript strict mode and ensure 100% type safety with no hardcoded types or any usage in frontend code
Files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
web-ui/src/components/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
web-ui/src/components/**/*.tsx: Use shadcn/ui Nova template components with semantic color palette (bg-card, text-foreground, etc.) and avoid hardcoded color values
Use cn() utility for conditional Tailwind CSS classes and follow Nova's compact spacing conventions
Files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
web-ui/src/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Replace all icon usage with Hugeicons (@hugeicons/react) and do not mix with lucide-react
Files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
web-ui/src/components/Dashboard.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Use React.memo on all Dashboard sub-components and useMemo for derived state to optimize performance with multi-agent support
Files:
web-ui/src/components/Dashboard.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T19:08:54.154Z
Learning: Applies to specs/*/tasks.md : Feature task files (tasks.md) must include phase-by-phase task breakdown with unique task identifiers (T001, T002, etc.), acceptance criteria per task, beads issue references, and estimated effort
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Use feature branches from main with Conventional Commits format (feat/fix/docs scope): description
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/**/__tests__/**/*.test.{ts,tsx} : Create JavaScript test files colocated or in __tests__/ as *.test.ts
Applied to files:
web-ui/__tests__/components/TaskList.test.tsx
📚 Learning: 2025-11-25T19:08:54.154Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T19:08:54.154Z
Learning: Applies to specs/*/tasks.md : Feature task files (tasks.md) must include phase-by-phase task breakdown with unique task identifiers (T001, T002, etc.), acceptance criteria per task, beads issue references, and estimated effort
Applied to files:
web-ui/__tests__/components/TaskList.test.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2025-12-17T19:21:40.014Z
Learnt from: frankbria
Repo: frankbria/codeframe PR: 128
File: tests/agents/test_bottleneck_detection.py:486-500
Timestamp: 2025-12-17T19:21:40.014Z
Learning: In tests/agents/test_bottleneck_detection.py, test_skip_agents_below_threshold should be async and mock _get_agent_workload to return workload below AGENT_OVERLOAD_THRESHOLD (5) while providing non-empty tasks list to prevent early return in detect_bottlenecks().
Applied to files:
web-ui/__tests__/components/TaskList.test.tsx
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/src/components/**/*.{ts,tsx} : Use functional React components with TypeScript interfaces
Applied to files:
web-ui/src/components/TaskList.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/**/*.{ts,tsx} : Use TypeScript 5.3+ for frontend development with React 18, Next.js 14, Tailwind CSS, and Hugeicons for icons
Applied to files:
web-ui/src/components/TaskList.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/components/Dashboard.tsx : Use React.memo on all Dashboard sub-components and useMemo for derived state to optimize performance with multi-agent support
Applied to files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/contexts/AgentStateContext.ts : Use context-based state management with React Context + useReducer pattern for Dashboard with AgentStateContext, agentReducer, and useAgentState hook
Applied to files:
web-ui/src/components/TaskList.tsxweb-ui/src/components/Dashboard.tsx
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/src/**/*.{ts,tsx} : Use SWR for server state management and useState for local state in React
Applied to files:
web-ui/src/components/Dashboard.tsx
🧬 Code graph analysis (1)
web-ui/src/components/Dashboard.tsx (2)
web-ui/src/lib/api.ts (2)
projectsApi(30-73)blockersApi(87-107)web-ui/src/types/api.ts (2)
PRDResponse(95-101)IssuesResponse(106-112)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Frontend Unit Tests
- GitHub Check: Backend Unit Tests
- GitHub Check: E2E Smoke Tests (Chromium)
- GitHub Check: claude-review
🔇 Additional comments (11)
web-ui/__tests__/components/TaskList.test.tsx (3)
1-16: Well-structured test file with comprehensive coverage.The test file follows TDD principles with clear documentation of expected behavior. The mock setup and imports are properly organized.
18-70: Mock setup is well-organized with representative test data.The mock data covers all task statuses (completed, in_progress, blocked, pending) with appropriate fields. The QualityGateStatus mock prevents async issues during testing.
380-410: Good accessibility test coverage.The tests verify proper ARIA roles, list structure, keyboard navigation, and descriptive labels. This aligns well with accessibility best practices.
web-ui/src/components/TaskList.tsx (3)
70-160: TaskCard component is well-memoized with proper displayName.The component follows the coding guideline to use
React.memoon Dashboard sub-components. The structure is clean with clear sections for header, assignment, progress, blocked info, and quality gates.
165-178: Good use ofuseMemofor derived state.The component correctly uses
useMemoforprojectTasks,filterCounts, andfilteredTasks, which aligns with the coding guideline to optimize performance with multi-agent support.Also applies to: 181-206
208-223: Stable callbacks withuseCallbackfor handlers.Both
handleViewQualityGatesandhandleFilterChangeuseuseCallbackwith appropriate dependency arrays, preventing unnecessary re-renders of child components.web-ui/src/components/Dashboard.tsx (5)
38-39: New component imports for phase-aware rendering.TaskList and TaskReview are correctly imported to enable the phase-aware task view integration.
153-165: Well-designed adaptive polling heuristic.The
isActiveWorkcomputation correctly identifies active work periods by checking for working/blocked agents and in-progress tasks. The 5s/30s interval split is reasonable for balancing responsiveness and API load.
439-455: Phase-aware badges use hardcoded theme colors.The badge styling uses
bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200and similar patterns. Per coding guidelines, prefer semantic color palette variables. However, this may be intentional to distinguish phase states visually.Verify if these specific color choices are intentional for phase differentiation, or if semantic alternatives like
bg-primary/10should be used instead for consistency with the design system.
676-716: Phase-aware task view rendering with proper error boundaries.The conditional rendering logic correctly maps phases to appropriate views:
planning→ TaskReview (for task approval)development/review→ TaskList (for active tasks)- Other phases → TaskTreeView (traditional view)
Each view is wrapped in an ErrorBoundary with appropriate fallback messaging.
177-218: SWR configurations properly implement adaptive polling strategy.The documentation block (lines 167-175) clearly explains the polling strategy. Each SWR hook is configured appropriately:
- Project status: adaptive polling with revalidation on focus/reconnect
- Blockers: adaptive polling (critical during active work)
- PRD: static content with
refreshInterval: 0- Issues: adaptive polling for task status updates
- Replace hardcoded bg-green-500/bg-red-500 with semantic bg-secondary/bg-destructive per Nova template guidelines in CLAUDE.md - Fix edge case test that incorrectly used jest.doMock after module import - Simplified test to verify zero/missing progress handling without mock override All 1484 tests pass, lint clean, no type errors.
Code Review: Phase-Aware Task View Integration (#16-6)OverviewThis PR successfully implements phase-aware task rendering in the Dashboard with the new TaskList component, adaptive polling, and comprehensive test coverage. The implementation is solid and production-ready. ✅ Strengths1. Excellent Component DesignThe TaskList component (web-ui/src/components/TaskList.tsx) demonstrates strong React best practices:
2. Smart Adaptive Polling StrategyThe Dashboard polling optimization (Dashboard.tsx:153-165) is well-designed: const isActiveWork = useMemo(() => {
const activeAgents = agents.filter(a => a.status === 'working' || a.status === 'blocked');
const activeTasks = tasks.filter(t => t.status === 'in_progress');
return activeAgents.length > 0 || activeTasks.length > 0;
}, [agents, tasks]);
3. Comprehensive Test CoverageOutstanding test quality with 463 lines of TaskList tests:
4. Phase-Aware Rendering LogicClean phase detection (Dashboard.tsx:677-716):
5. shadcn/ui Nova ComplianceConsistent adherence to project standards:
🔍 Minor Observations (Non-Blocking)1. Connection Status Indicator (TaskList.tsx:240-253)Good implementation using semantic tokens! The connection indicator correctly uses: wsConnected ? 'bg-secondary animate-pulse' : 'bg-destructive'This follows CLAUDE.md guidelines for Nova template color palette. ✅ 2. Quality Gates Toggle Pattern (TaskList.tsx:208-218)The Set-based toggle is functional but slightly unconventional: setQualityGatesVisible((prev) => {
const newSet = new Set(prev);
if (newSet.has(taskId)) {
newSet.delete(taskId);
} else {
newSet.add(taskId);
}
return newSet;
});Observation: This works correctly and is acceptable. Alternative would be to use a 3. Empty State Message (TaskList.tsx:233)The message "Tasks will appear here during the development phase" is accurate since TaskList is only shown during development/review phases. ✅ 4. Polling Strategy Documentation (Dashboard.tsx:167-175)Excellent inline documentation explaining the adaptive polling strategy! This makes the code maintainable for future developers. 🔒 Security Review✅ No security concerns identified:
⚡ Performance AnalysisOptimizations Present:
Complexity Analysis:
📊 Code Quality Assessment✅ Follows CLAUDE.md Guidelines:
✅ React Best Practices:
✅ Testing Best Practices:
📋 Checklist ReviewBased on PR description:
🎯 Final VerdictAPPROVED ✅ This is a high-quality, production-ready PR that:
The implementation demonstrates strong engineering practices with excellent attention to detail. The adaptive polling strategy alone is a significant performance improvement. Ready to merge. 🚀 📝 Suggestions for Future Enhancements (Optional)
Great work on this feature! The phase-aware dashboard integration significantly improves the development workflow. 👏 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
web-ui/__tests__/components/TaskList.test.tsx (2)
180-180: Consider adding expect checks before non-null assertions for clearer error messages.Several test cases use the non-null assertion operator (
!) when clicking buttons without first verifying the button exists. While this works in tests (they'll fail either way), adding explicitexpectchecks beforehand would provide clearer error messages.♻️ Example improvement
For consistency with line 163-164, consider this pattern:
const blockedButton = screen.getAllByRole('button').find( (btn) => btn.textContent?.includes('Blocked') ); +expect(blockedButton).toBeInTheDocument(); await user.click(blockedButton!);Apply similar checks at lines 194, 208, 214, 228, and 252.
Also applies to: 194-194, 208-208, 214-214, 228-228, 252-252
445-458: Good fix for the jest.doMock issue, but test name could be more precise.The previous review concern about
jest.doMockhas been properly addressed by simplifying the test. However, the test name claims to handle "zero or missing progress" but the mock data only includes tasks withprogress: 0, notundefinedornullvalues.♻️ Optional: Make test name match actual coverage
Either update the test name to reflect what's actually tested:
-it('should handle tasks with zero or missing progress gracefully', () => { +it('should handle tasks with zero progress gracefully', () => {Or add a task with undefined progress to the scenario to truly test "missing progress".
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
web-ui/__tests__/components/TaskList.test.tsxweb-ui/src/components/TaskList.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- web-ui/src/components/TaskList.tsx
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T19:08:54.154Z
Learning: Applies to specs/*/tasks.md : Feature task files (tasks.md) must include phase-by-phase task breakdown with unique task identifiers (T001, T002, etc.), acceptance criteria per task, beads issue references, and estimated effort
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Use feature branches from main with Conventional Commits format (feat/fix/docs scope): description
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/components/Dashboard.tsx : Use React.memo on all Dashboard sub-components and useMemo for derived state to optimize performance with multi-agent support
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/**/__tests__/**/*.test.{ts,tsx} : Create JavaScript test files colocated or in __tests__/ as *.test.ts
Applied to files:
web-ui/__tests__/components/TaskList.test.tsx
📚 Learning: 2026-01-04T06:26:12.870Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T06:26:12.870Z
Learning: Applies to web-ui/src/**/*.{ts,tsx} : Use TypeScript strict mode and ensure 100% type safety with no hardcoded types or any usage in frontend code
Applied to files:
web-ui/__tests__/components/TaskList.test.tsx
📚 Learning: 2025-12-17T19:21:40.014Z
Learnt from: frankbria
Repo: frankbria/codeframe PR: 128
File: tests/agents/test_bottleneck_detection.py:486-500
Timestamp: 2025-12-17T19:21:40.014Z
Learning: In tests/agents/test_bottleneck_detection.py, test_skip_agents_below_threshold should be async and mock _get_agent_workload to return workload below AGENT_OVERLOAD_THRESHOLD (5) while providing non-empty tasks list to prevent early return in detect_bottlenecks().
Applied to files:
web-ui/__tests__/components/TaskList.test.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Frontend Unit Tests
- GitHub Check: Backend Unit Tests
- GitHub Check: E2E Smoke Tests (Chromium)
- GitHub Check: claude-review
🔇 Additional comments (1)
web-ui/__tests__/components/TaskList.test.tsx (1)
1-468: Excellent comprehensive test coverage for TaskList component.This test suite provides thorough coverage of the TaskList component with 35 well-organized test cases covering:
- Core rendering and filtering functionality
- Status-specific styling with semantic CSS classes
- Accessibility (ARIA attributes, keyboard navigation)
- Real-time updates and responsive design
- Edge cases
The test structure is clean, properly typed, and aligns with the phase-aware Dashboard integration described in the PR objectives.
Summary
Test plan
Summary by CodeRabbit
New Features
Performance
Tests
✏️ Tip: You can customize this high-level summary in your review settings.