Skip to content

feat(dashboard): Add phase-aware task view integration (#016-6) - #215

Merged
frankbria merged 3 commits into
mainfrom
feature/016-6-dashboard-phase-integration
Jan 7, 2026
Merged

feat(dashboard): Add phase-aware task view integration (#016-6)#215
frankbria merged 3 commits into
mainfrom
feature/016-6-dashboard-phase-integration

Conversation

@frankbria

@frankbria frankbria commented Jan 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add TaskList component for real-time task view during development phase
  • Integrate phase-aware rendering in Dashboard Tasks tab (TaskReview for planning, TaskList for development, TaskTreeView fallback)
  • Add tab badges showing task counts and progress based on project phase
  • Optimize SWR polling with adaptive refresh intervals (5s active, 30s idle)

Test plan

  • All 1483 tests pass (54 test suites)
  • 35 new TaskList component tests
  • 7 new Dashboard integration tests for phase-aware features
  • ESLint: No warnings or errors
  • TypeScript: No type errors
  • Build: Successful
  • Manual testing of phase transitions in UI

Summary by CodeRabbit

  • New Features

    • New Task List view with status filters, per-task progress, agent assignment display, quality-gates toggle, and responsive layout.
    • Phase-aware Dashboard: Tasks area switches views and shows phase-specific badges (e.g., Awaiting Approval, In Development).
  • Performance

    • Adaptive polling: faster refresh during active work, slower when idle.
  • Tests

    • Expanded tests covering task list behavior, phase-driven dashboard rendering, badges, accessibility, responsiveness, and real-time updates.

✏️ Tip: You can customize this high-level summary in your review settings.

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)
@coderabbitai

coderabbitai Bot commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Dashboard 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

Cohort / File(s) Summary
Dashboard Phase & Polling
web-ui/src/components/Dashboard.tsx, web-ui/__tests__/components/Dashboard.test.tsx
Adds phase-driven conditional rendering of the Tasks tab (TaskReview, TaskList, TaskTreeView), phase-specific tab badges, adaptive SWR polling (ACTIVE_REFRESH_INTERVAL/IDLE_REFRESH_INTERVAL) based on computed isActiveWork, and tests validating phase-driven rendering and badges.
New TaskList & Tests
web-ui/src/components/TaskList.tsx, web-ui/__tests__/components/TaskList.test.tsx
Adds new TaskList component (and TaskCard) with filters, status badges, assignment display, per-task progress, blocked-by info, per-task QualityGate toggle, live connection indicator, responsive layout, empty states, and extensive unit tests covering rendering, filtering, accessibility, realtime/updating, responsiveness, and edge cases.
Test Mocks / Component Stubs
web-ui/__tests__/components/Dashboard.test.tsx
Replaces text-based mocks with data-testid-based mocks for TaskTreeView, TaskList, and TaskReview to assert presence in tab panels across phases.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

🐇 I hopped through phases, bright and spry,

Planning, building, trees to spy,
Badges blink and lists unfold,
Polling hums as stories roll,
A little rabbit cheers the code.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding phase-aware task view integration to the Dashboard, which is the core objective reflected across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/016-6-dashboard-phase-integration

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude

claude Bot commented Jan 7, 2026

Copy link
Copy Markdown

PR Review: Phase-Aware Task View Integration (#16-6)

Summary

This 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.


✅ Strengths

1. Excellent Component Architecture

  • TaskList.tsx: Clean, well-structured component with proper separation of concerns
    • Memoized sub-components (TaskCard) for performance
    • Proper use of useMemo and useCallback hooks
    • Clear separation between presentation and business logic

2. Comprehensive Test Coverage

  • 463 lines of tests for TaskList with excellent coverage:
    • Rendering scenarios (empty states, status badges, progress)
    • Status filtering (all 4 status types + counts)
    • Quality gates integration
    • Accessibility (ARIA labels, keyboard navigation)
    • Edge cases (null progress, long titles)
  • 210 lines of new Dashboard tests for phase-aware integration
  • All 1483 tests passing ✅

3. Smart Performance Optimization

The 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

  • Proper ARIA attributes (role="list", role="listitem", aria-label)
  • Progress bars with aria-valuenow, aria-valuemin, aria-valuemax
  • Semantic HTML structure
  • Keyboard navigation support

5. shadcn/ui Nova Compliance

  • Consistent use of Nova color palette (bg-card, text-foreground, etc.)
  • No hardcoded colors
  • Proper use of design tokens

🔍 Issues & Recommendations

1. Critical: Missing pending Filter in FILTER_OPTIONS

File: web-ui/src/components/TaskList.tsx:28-33

The FILTER_OPTIONS array is missing the 'pending' status, but the component tracks it in filterCounts:

const FILTER_OPTIONS: FilterConfig[] = [
  { label: 'All', status: 'all' },
  { label: 'In Progress', status: 'in_progress' },
  { label: 'Blocked', status: 'blocked' },
  { label: 'Completed', status: 'completed' },
  // Missing: 'pending' ❌
];

Impact: Users cannot filter to see only pending tasks, but the test at line 46 expects 'pending' status styling.

Fix: Add pending filter option:

const FILTER_OPTIONS: FilterConfig[] = [
  { label: 'All', status: 'all' },
  { label: 'Pending', status: 'pending' },  // Add this
  { label: 'In Progress', status: 'in_progress' },
  { label: 'Blocked', status: 'blocked' },
  { label: 'Completed', status: 'completed' },
];

2. Potential Race Condition in Quality Gates Toggle

File: web-ui/src/components/TaskList.tsx:204-214

The handleViewQualityGates function uses Set mutation which could cause issues with React's state reconciliation:

const handleViewQualityGates = useCallback((taskId: number) => {
  setQualityGatesVisible((prev) => {
    const newSet = new Set(prev);  // This works, but...
    if (newSet.has(taskId)) {
      newSet.delete(taskId);
    } else {
      newSet.add(taskId);
    }
    return newSet;
  });
}, []);

Recommendation: This is fine for now, but for consistency with React patterns, consider using a Set<number> or a simpler number[] approach. The current implementation is acceptable but slightly unconventional.

3. Inconsistent Phase Normalization Logic

File: web-ui/src/components/Dashboard.tsx:667-693

The phase-aware rendering uses normalizePhase() which maps 'active' → 'development', but the tab badge checks both:

{(normalizePhase(projectData.phase) === 'development' || 
  normalizePhase(projectData.phase) === 'review') && (
  <span data-testid="tasks-tab-badge-development">...</span>
)}

Question: What happens when projectData.phase === 'active'?

  • Does normalizePhase('active') return 'development'? ✅ (Yes, based on line 47)

Observation: The logic is correct, but the condition could be clearer:

// More explicit
const normalizedPhase = normalizePhase(projectData.phase);
const isDevelopmentPhase = normalizedPhase === 'development' || normalizedPhase === 'review';

4. Missing Error Handling for Quality Gates

File: web-ui/src/components/TaskList.tsx:145-149

The QualityGateStatus component is rendered without error boundaries:

{showQualityGates && (
  <div className="mt-2">
    <QualityGateStatus taskId={task.id} />  // No ErrorBoundary ❌
  </div>
)}

Recommendation: Wrap in ErrorBoundary like Dashboard does (Dashboard.tsx:676):

<ErrorBoundary fallback={<div className="text-destructive text-xs">Failed to load quality gates</div>}>
  <QualityGateStatus taskId={task.id} />
</ErrorBoundary>

5. Adaptive Polling Applied to PRD Data

File: web-ui/src/components/Dashboard.tsx:188-195

The PRD data fetch has refreshInterval: 0 (manual only), which is good! But the comment says "less frequent, only refresh on focus" which matches the implementation. ✅

Suggestion: Consider adding a similar comment for the other endpoints to document the polling strategy.

6. Minor: Empty State Message Inconsistency

File: web-ui/src/components/TaskList.tsx:228-229

The empty state says:

"Tasks will appear here once the project enters development phase"

But TaskList is shown during both development AND review phases. Consider:

<p className="text-sm mt-2">
  Tasks will appear here during the development phase
</p>

🧪 Test Quality

Excellent Coverage:

  • ✅ Phase transitions (planning → development → discovery)
  • ✅ Badge rendering for each phase
  • ✅ Status filtering with counts
  • ✅ Quality gates integration
  • ✅ Accessibility attributes
  • ✅ Edge cases (null progress, empty states)

Test Mocking Strategy:

The mocking approach is solid:

jest.mock('@/hooks/useAgentState', () => ({
  useAgentState: () => ({
    tasks: mockTasks,
    agents: [...],
    // ...
  }),
}));

One observation: Tests use a static mock that doesn't allow per-test customization. For future tests involving dynamic scenarios, consider using jest.fn().mockReturnValue(...) to allow per-test overrides.


🔒 Security Considerations

✅ No security concerns identified:

  • No user input rendering without sanitization
  • No dynamic class name injection
  • Proper TypeScript types prevent injection attacks
  • ARIA attributes use static strings

📊 Performance Considerations

✅ Optimizations Present:

  1. Memoized TaskCard component prevents unnecessary re-renders
  2. useMemo for expensive filtering operations (lines 171, 177, 196)
  3. useCallback for event handlers (lines 204, 217)
  4. Adaptive polling reduces API load by 6x during idle periods (30s vs 5s)

Potential Concern:

The isActiveWork computation (Dashboard.tsx:154-159) runs on every agent/task state change. For projects with many tasks, consider adding a dependency array optimization:

const isActiveWork = useMemo(() => {
  // Current implementation is fine for now
  // Only becomes an issue with 100+ tasks
}, [agents, tasks]); // Already optimized ✅

Verdict: Current implementation is performant for typical project sizes.


📝 Code Quality & Best Practices

✅ Follows CLAUDE.md Guidelines:

  • shadcn/ui Nova template compliance
  • TypeScript strict mode compliance
  • Proper file organization
  • Comprehensive JSDoc comments

✅ React Best Practices:

✅ Testing Best Practices:

  • TDD-style documentation in test file header
  • Descriptive test names
  • Isolated test cases
  • Proper use of waitFor for async operations

🎯 Recommendations Summary

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. 🚀

@frankbria frankbria linked an issue Jan 7, 2026 that may be closed by this pull request
19 tasks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 active phase but not review phase for the development badge. Since Dashboard.tsx shows the same badge for both development and review phases, consider adding a test for phase: '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-500 and bg-red-500 colors, 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_INTERVAL and IDLE_REFRESH_INTERVAL constants 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 of refreshInterval variable.

The blockers fetch uses an inline ternary for refreshInterval instead of the pre-computed refreshInterval variable 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 of refreshInterval.

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 focusing filterButtons[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

📥 Commits

Reviewing files that changed from the base of the PR and between 557ab51 and 460cd0a.

📒 Files selected for processing (4)
  • web-ui/__tests__/components/Dashboard.test.tsx
  • web-ui/__tests__/components/TaskList.test.tsx
  • web-ui/src/components/Dashboard.tsx
  • web-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.tsx
  • web-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.tsx
  • web-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.tsx
  • web-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.tsx
  • 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/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.tsx
  • web-ui/__tests__/components/Dashboard.test.tsx
  • 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/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.tsx
  • web-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.tsx
  • web-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.tsx
  • web-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-testid attributes 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: 5 from 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 getStatusStyles function 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.memo and displayName assignment. The component structure is clean with proper accessibility attributes on the progress bar.


161-174: Consider memoizing projectTasks filtering with useMemo dependency array.

The projectTasks filtering is correctly memoized. However, if tasks array 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 isActiveWork computation 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 normalizePhase ensures 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.

Comment thread web-ui/__tests__/components/TaskList.test.tsx
- 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.
@claude

claude Bot commented Jan 7, 2026

Copy link
Copy Markdown

Follow-Up Review: Post-Fixes

Thank you for addressing the feedback! I can see that the "Pending" filter has been added to FILTER_OPTIONS (TaskList.tsx:31) and ErrorBoundary now wraps QualityGateStatus (TaskList.tsx:149). Great work! 👍


✅ Fixed Issues from Previous Review

  1. Pending filter added - TaskList.tsx:31-32 now includes { label: 'Pending', status: 'pending' }
  2. ErrorBoundary added - QualityGateStatus is wrapped at line 149 with a proper fallback

🔍 Remaining Minor Issue

Hardcoded 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 Verdict

APPROVED

All critical issues have been addressed:

  • ✅ Pending filter implemented
  • ✅ ErrorBoundary added for robustness
  • ✅ All 1483 tests passing
  • ✅ Comprehensive test coverage
  • ✅ Phase-aware rendering working correctly

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! 🚀

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
web-ui/__tests__/components/TaskList.test.tsx (1)

148-152: Consider using getByRole with name option instead of find() 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 like bg-green-500 and bg-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 using cn() utility for conditional Tailwind CSS classes.

Per coding guidelines for web-ui/src/components/**/*.tsx, conditional Tailwind classes should use the cn() 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_INTERVAL and IDLE_REFRESH_INTERVAL outside 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.length is 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

📥 Commits

Reviewing files that changed from the base of the PR and between 460cd0a and eedf8cd.

📒 Files selected for processing (3)
  • web-ui/__tests__/components/TaskList.test.tsx
  • web-ui/src/components/Dashboard.tsx
  • web-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.tsx
  • web-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.tsx
  • web-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.tsx
  • web-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.tsx
  • web-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.tsx
  • 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/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.tsx
  • web-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.memo on Dashboard sub-components. The structure is clean with clear sections for header, assignment, progress, blocked info, and quality gates.


165-178: Good use of useMemo for derived state.

The component correctly uses useMemo for projectTasks, filterCounts, and filteredTasks, which aligns with the coding guideline to optimize performance with multi-agent support.

Also applies to: 181-206


208-223: Stable callbacks with useCallback for handlers.

Both handleViewQualityGates and handleFilterChange use useCallback with 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 isActiveWork computation 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-200 and 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/10 should 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.
@claude

claude Bot commented Jan 7, 2026

Copy link
Copy Markdown

Code Review: Phase-Aware Task View Integration (#16-6)

Overview

This 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.


Strengths

1. Excellent Component Design

The TaskList component (web-ui/src/components/TaskList.tsx) demonstrates strong React best practices:

  • Performance optimized: Memoized TaskCard component, proper use of useMemo and useCallback
  • Clean architecture: Clear separation of concerns with dedicated utility functions (getStatusStyles, formatStatus)
  • Accessibility first: Comprehensive ARIA attributes (role="list", aria-label, aria-pressed, progress bars with aria-valuenow)

2. Smart Adaptive Polling Strategy

The 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]);
  • 5s refresh during active work (agents working or tasks in progress)
  • 30s refresh during idle periods
  • 6x reduction in unnecessary API calls while maintaining responsiveness

3. Comprehensive Test Coverage

Outstanding test quality with 463 lines of TaskList tests:

  • ✅ All rendering scenarios (empty states, badges, progress indicators)
  • ✅ Status filtering with accurate counts
  • ✅ Quality gates integration with ErrorBoundary
  • ✅ Accessibility (keyboard navigation, ARIA labels)
  • ✅ Edge cases (null progress, long titles)
  • ✅ 7 new Dashboard integration tests for phase-aware rendering
  • All 1483 tests passing

4. Phase-Aware Rendering Logic

Clean phase detection (Dashboard.tsx:677-716):

  • Planning phase → TaskReview with "Awaiting Approval" badge
  • Development/Review phases → TaskList with "In Development" badge
  • Discovery/Complete phases → TaskTreeView fallback
  • All views wrapped in ErrorBoundary for robustness

5. shadcn/ui Nova Compliance

Consistent adherence to project standards:

  • ✅ Semantic color tokens (bg-card, text-foreground, bg-primary)
  • ✅ No hardcoded colors (connection status at line 247 uses bg-secondary and bg-destructive)
  • ✅ Proper Tailwind utility classes

🔍 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 Record<number, boolean> for clearer intent, but current implementation is fine.

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:

  • No user input rendering without sanitization
  • TypeScript types prevent injection attacks
  • ARIA attributes use static strings
  • No dynamic class name injection vulnerabilities

Performance Analysis

Optimizations Present:

  1. ✅ Memoized TaskCard prevents unnecessary re-renders (line 70)
  2. useMemo for expensive filtering operations (lines 175, 181, 200)
  3. useCallback for event handlers to prevent callback recreation (lines 208, 221)
  4. ✅ Adaptive polling reduces API load by 6x during idle periods
  5. displayName set for better React DevTools debugging

Complexity Analysis:

  • isActiveWork computation: O(n) where n = agents + tasks
  • For typical projects (<100 tasks), this is negligible
  • Properly memoized with correct dependencies

📊 Code Quality Assessment

✅ Follows CLAUDE.md Guidelines:

  • shadcn/ui Nova template compliance
  • TypeScript strict mode (no type errors)
  • Proper project structure
  • Comprehensive JSDoc comments

✅ React Best Practices:

  • Proper hook dependency arrays
  • Key props on list items (line 284)
  • Controlled component patterns
  • ErrorBoundary usage for robustness (line 149, 686, 699)

✅ Testing Best Practices:

  • TDD-style documentation in test headers
  • Descriptive test names with clear intent
  • Isolated test cases
  • Proper async handling with waitFor

📋 Checklist Review

Based on PR description:

  • ✅ All 1483 tests pass (54 test suites)
  • ✅ 35 new TaskList component tests
  • ✅ 7 new Dashboard integration tests
  • ✅ ESLint: No warnings or errors
  • ✅ TypeScript: No type errors
  • ✅ Build: Successful
  • ⏳ Manual testing of phase transitions (awaiting user confirmation)

🎯 Final Verdict

APPROVED

This is a high-quality, production-ready PR that:

  • ✅ Implements the feature spec correctly with phase-aware rendering
  • ✅ Includes comprehensive test coverage (100% scenario coverage)
  • ✅ Follows all project conventions and architecture guidelines
  • ✅ Optimizes performance with intelligent adaptive polling
  • ✅ Maintains accessibility standards throughout
  • ✅ Handles errors gracefully with ErrorBoundary wrappers
  • ✅ Addresses all previous review feedback

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)

  1. Task Sorting: Consider adding sort options (by status, agent, progress) in a future PR
  2. Bulk Actions: For projects with many tasks, bulk status updates could improve UX
  3. Metrics Dashboard: The adaptive polling could feed into a "API Usage" metrics panel

Great work on this feature! The phase-aware dashboard integration significantly improves the development workflow. 👏

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 explicit expect checks 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.doMock has 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 with progress: 0, not undefined or null values.

♻️ 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

📥 Commits

Reviewing files that changed from the base of the PR and between eedf8cd and 4cf1ed5.

📒 Files selected for processing (2)
  • web-ui/__tests__/components/TaskList.test.tsx
  • web-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.

@frankbria
frankbria merged commit 8e279ab into main Jan 7, 2026
12 checks passed
@frankbria
frankbria deleted the feature/016-6-dashboard-phase-integration branch January 7, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

016-6: Dashboard Integration + Polish

1 participant