Skip to content

Conversation

@Shironex
Copy link
Collaborator

@Shironex Shironex commented Jan 21, 2026

image

Summary by CodeRabbit

  • New Features
    • Multi-project Overview dashboard: project cards, aggregate metrics, recent activity feed, and running agents panel; new Overview page and actions to open it.
  • API
    • Projects overview endpoint returning aggregated project statuses, activity feed, and totals.
  • UI
    • Logo and navigation now target Overview; header quick-access Overview actions; subtle footer styling update.
  • Types
    • Shared types for overview payloads and activity/feed models.
  • Tests
    • End-to-end suites covering overview flows, empty/error states, and navigation.

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

- Introduced a new Projects Overview link in the sidebar footer for easy navigation.
- Added a button for Projects Overview in the dashboard view, enhancing accessibility to project insights.
- Updated types to include project overview-related definitions, supporting the new features.
@Shironex Shironex self-assigned this Jan 21, 2026
@Shironex Shironex added Testers-Requested Request for others to test an enhancement or bug fix/etc. Work-In-Progress Currently being addressed. Do Not Merge Use this label if something should not be merged. type: feature A new capability or functionality that does not exist yet. labels Jan 21, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a multi-project overview feature: server GET /api/projects/overview route and handler, new types, a frontend OverviewView with cards/feed/agents, a polling data hook, navigation updates to point to /overview, and end-to-end tests.

Changes

Cohort / File(s) Summary
Backend: Route registration
apps/server/src/index.ts
Mounts createProjectsRoutes at /api/projects.
Backend: Projects API
apps/server/src/routes/projects/index.ts, apps/server/src/routes/projects/routes/overview.ts, apps/server/src/routes/projects/common.ts
Adds projects router and GET /overview handler that enumerates projects, loads per-project data (features/counts, auto-mode, notifications, last activity), computes health, and returns a MultiProjectOverview. Exports createProjectsRoutes / createOverviewHandler.
Types
libs/types/src/project-overview.ts, libs/types/src/index.ts
New type definitions and exports for project health, feature counts, aggregates, activity feed, MultiProjectOverview, and ProjectOverviewError.
Frontend: Overview UI
apps/ui/src/components/views/overview-view.tsx, apps/ui/src/components/views/overview/project-status-card.tsx, apps/ui/src/components/views/overview/recent-activity-feed.tsx, apps/ui/src/components/views/overview/running-agents-panel.tsx
Adds OverviewView and subcomponents: project cards, recent activity feed, running agents panel; includes project init/open flows, modals, navigation, and error handling.
Frontend: Data hook
apps/ui/src/hooks/use-multi-project-status.ts
New useMultiProjectStatus hook to fetch /api/projects/overview, manage auth headers, polling, and error state.
Frontend: Routing & navigation
apps/ui/src/routes/overview.tsx, apps/ui/src/components/views/dashboard-view.tsx, apps/ui/src/components/layout/sidebar/*, apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx, apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx
Registers /overview route; adds Overview buttons; updates logo/navigation IDs/targets from /dashboard to /overview; minor footer styling tweak.
Tests
apps/ui/tests/projects/overview-dashboard.spec.ts, tests/e2e/multi-project-dashboard.spec.ts
New Playwright E2E tests covering overview navigation, rendering, aggregates, cards, empty/error states, and interactions.
Public types re-export
libs/types/src/index.ts
Re-exports new overview types for consumption by clients.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Client as UI Client
    participant Server as API Server
    participant Services as Services (FeatureLoader / AutoMode / Settings / Notifications)

    User->>Client: Navigate to /overview
    Client->>Client: Render OverviewView\ncall useMultiProjectStatus()
    Client->>Server: GET /api/projects/overview (auth)
    Server->>Services: Load global settings (enumerate projects)
    Server->>Services: Concurrent per-project requests:\nfeatures & counts, auto-mode, notifications, last activity
    Services-->>Server: Return per-project data
    Server->>Server: Compute health per project\nAggregate metrics & recent activity
    Server-->>Client: 200 MultiProjectOverview
    Client->>Client: Update state\nRender ProjectStatusCard[], RecentActivityFeed, RunningAgentsPanel
    Client-->>User: Display aggregated dashboard
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Possibly related PRs

Suggested labels

Enhancement

Poem

🐰 I hopped through routes and UI bright,

Gathered projects, day and night,
Cards and feeds in tidy rows,
Agents hum and metrics glow,
Click to hop — the overview's right!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: projects overview dashboard' clearly and concisely summarizes the main change—adding a new projects overview/dashboard UI feature. It accurately reflects the extensive changeset including backend routes, frontend components, types, and tests.

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

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Shironex, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a significant new feature: a "Projects Overview" dashboard. This dashboard provides users with a high-level, real-time summary of all their managed projects, consolidating critical information such as project health, feature progress, and agent activity into a single, easily digestible view. It enhances the user's ability to monitor and manage their entire workspace efficiently, moving beyond single-project focus to a comprehensive multi-project perspective.

Highlights

  • New Projects Overview Dashboard: Introduced a dedicated UI for a multi-project overview, providing a centralized view of all projects.
  • Backend API for Project Aggregation: Implemented a new "/api/projects/overview" endpoint to fetch and aggregate status data from multiple projects.
  • Comprehensive Project Status Display: Each project card in the overview shows health status, feature counts (pending, running, completed, failed, verified), auto-mode status, and unread notifications.
  • Aggregate Metrics and Activity Feed: The dashboard includes aggregate statistics across all projects and a placeholder for a recent activity feed.
  • UI Navigation Integration: Added "Projects Overview" links to the sidebar and a button on the main dashboard for easy access.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new projects overview dashboard, a significant feature that provides a unified view for monitoring multiple projects. The implementation is well-structured, with a new backend API endpoint, corresponding frontend components, a data-fetching hook, and new type definitions. The backend efficiently processes projects in parallel, and the frontend is well-componentized. I've identified a few areas for improvement related to error logging, data modeling for a future feature, and code maintainability. Overall, this is a solid and valuable addition to the application.

Comment on lines 123 to 140
const initResult = await initializeProject(
// We need to find the project path - use projectId as workaround
// In real implementation, this would look up the path from projects list
activity.projectId
);

// Navigate to the project
const projectPath = activity.projectId;
const projectName = activity.projectName;

upsertAndSetCurrentProject(projectPath, projectName);

if (activity.featureId) {
// Navigate to the specific feature
navigate({ to: '/board', search: { featureId: activity.featureId } });
} else {
navigate({ to: '/board' });
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This block has two issues:

  1. It incorrectly uses activity.projectId as the project path, which will cause an error when initializeProject is called. You should use activity.projectPath (which I've suggested adding to the RecentActivity type).
  2. The result of initializeProject is not checked for success. If it fails, the code will proceed and likely throw another error. You should check initResult.success and handle the error gracefully.

The suggested code fixes both issues.

Suggested change
const initResult = await initializeProject(
// We need to find the project path - use projectId as workaround
// In real implementation, this would look up the path from projects list
activity.projectId
);
// Navigate to the project
const projectPath = activity.projectId;
const projectName = activity.projectName;
upsertAndSetCurrentProject(projectPath, projectName);
if (activity.featureId) {
// Navigate to the specific feature
navigate({ to: '/board', search: { featureId: activity.featureId } });
} else {
navigate({ to: '/board' });
}
const initResult = await initializeProject(activity.projectPath);
if (!initResult.success) {
toast.error('Failed to open project', {
description: initResult.error || 'Unknown error',
});
return;
}
// Navigate to the project
upsertAndSetCurrentProject(activity.projectPath, activity.projectName);
if (activity.featureId) {
// Navigate to the specific feature
navigate({ to: '/board', search: { featureId: activity.featureId } });
} else {
navigate({ to: '/board' });
}

/** Unique identifier for this activity entry */
id: string;
/** Project this activity belongs to */
projectId: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The RecentActivity interface is missing the projectPath. While you have projectId, the frontend will need the projectPath to navigate to the project. Relying on looking up the path from the project list on the frontend is less efficient and makes the RecentActivityFeed component less self-contained. It's better to denormalize this data and include projectPath directly in the RecentActivity type.

Suggested change
projectId: string;
projectId: string;
/** Absolute filesystem path to project */
projectPath: string;

Comment on lines +112 to +134
for (const feature of features) {
// Check startedAt timestamp (the main timestamp available on Feature)
if (feature.startedAt) {
const timestamp = new Date(feature.startedAt).getTime();
if (!isNaN(timestamp) && timestamp > latestTimestamp) {
latestTimestamp = timestamp;
}
}

// Also check planSpec timestamps if available
if (feature.planSpec?.generatedAt) {
const timestamp = new Date(feature.planSpec.generatedAt).getTime();
if (!isNaN(timestamp) && timestamp > latestTimestamp) {
latestTimestamp = timestamp;
}
}
if (feature.planSpec?.approvedAt) {
const timestamp = new Date(feature.planSpec.approvedAt).getTime();
if (!isNaN(timestamp) && timestamp > latestTimestamp) {
latestTimestamp = timestamp;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The logic for finding the latest timestamp is repeated for startedAt, planSpec.generatedAt, and planSpec.approvedAt. This repetition can be reduced to make the code more concise and easier to maintain. Consider iterating through a list of potential timestamp properties to find the maximum value.

  for (const feature of features) {
    const potentialTimestamps = [
      feature.startedAt,
      feature.planSpec?.generatedAt,
      feature.planSpec?.approvedAt,
    ];

    for (const ts of potentialTimestamps) {
      if (ts) {
        const timestamp = new Date(ts).getTime();
        if (!isNaN(timestamp) && timestamp > latestTimestamp) {
          latestTimestamp = timestamp;
        }
      }
    }
  }

unreadNotificationCount,
};
} catch (error) {
// Return a minimal status for projects that fail to load
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

In this catch block, you're gracefully handling errors for individual project loading by returning a minimal status. However, the error itself is not logged. For better observability and easier debugging of server-side issues, it would be beneficial to log the error that occurred. You can use the logError utility that's already available in this file's scope.

          logError(error, `Failed to load status for project ${projectRef.path}`);
          // Return a minimal status for projects that fail to load

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/release.yml (1)

60-87: Missing blockmap files in artifact upload steps.

The release upload step (lines 117-125) expects *.blockmap files from all platforms, but the artifact upload steps don't include them. Blockmap files won't be available during the upload job, causing the release to be incomplete for delta/auto-updates.

🔧 Proposed fix to include blockmap files in artifact uploads
       - name: Upload macOS artifacts
         if: matrix.os == 'macos-latest'
         uses: actions/upload-artifact@v4
         with:
           name: macos-builds
           path: |
             apps/ui/release/*.dmg
             apps/ui/release/*.zip
+            apps/ui/release/*.blockmap
           retention-days: 30

       - name: Upload Windows artifacts
         if: matrix.os == 'windows-latest'
         uses: actions/upload-artifact@v4
         with:
           name: windows-builds
-          path: apps/ui/release/*.exe
+          path: |
+            apps/ui/release/*.exe
+            apps/ui/release/*.blockmap
           retention-days: 30

       - name: Upload Linux artifacts
         if: matrix.os == 'ubuntu-latest'
         uses: actions/upload-artifact@v4
         with:
           name: linux-builds
           path: |
             apps/ui/release/*.AppImage
             apps/ui/release/*.deb
             apps/ui/release/*.rpm
+            apps/ui/release/*.blockmap
           retention-days: 30
🤖 Fix all issues with AI agents
In `@apps/ui/src/components/views/overview/project-status-card.tsx`:
- Around line 90-102: The container returned in the ProjectStatusCard component
is a non-interactive <div> that uses handleClick and has
data-testid={`project-status-card-${project.projectId}`}, so make it
keyboard-accessible by converting the div into a semantic <button> (or <a> if
navigation) or, if keeping the div, add role="button", tabIndex={0}, and an
onKeyDown handler that invokes handleClick on Enter/Space; ensure ARIA and
visual styles remain (preserve cn className and data-testid) and update any
tests or styles expecting a div accordingly.

In `@apps/ui/src/components/views/overview/recent-activity-feed.tsx`:
- Around line 167-172: The activity rows currently rendered as a clickable <div>
(keyed by activity.id) are not keyboard-accessible; update the element that
renders each row in recent-activity-feed.tsx to be keyboard operable by either
replacing the <div> with an interactive element (<button> or <a>) or by adding
role="button", tabIndex={0}, and key handlers that call
handleActivityClick(activity) on Enter/Space keypress; ensure the data-testid
and existing onClick behavior remain unchanged and that any visual styles still
apply to the new/updated element.
- Around line 120-140: handleActivityClick is passing activity.projectId into
initializeProject (which expects a filesystem path) and ignores the init result;
update the handler to resolve the actual project path (either by reading it from
your projects store/state or by adding projectPath to the RecentActivity shape)
and pass that path into initializeProject, await and check the initResult for
success, and only call upsertAndSetCurrentProject and navigate when
initialization succeeds; on failure, abort navigation and surface/log an error
so you don't create a broken project context (refer to initializeProject,
handleActivityClick, upsertAndSetCurrentProject, navigate, and RecentActivity to
locate the changes).

In `@apps/ui/src/components/views/overview/running-agents-panel.tsx`:
- Around line 81-86: The agent card div in RunningAgentsPanel is not
keyboard-accessible; make it activate via keyboard by adding focusability and
ARIA semantics and wiring keyboard events: give the container role="button" and
tabIndex={0} (keep data-testid={`running-agent-${agent.projectId}`}), add an
onKeyDown handler (e.g., handleAgentKeyDown or inline) that listens for Enter
and Space and calls handleAgentClick(agent), and ensure an appropriate
aria-label or aria-describedby is present for screen readers; also preserve the
existing onClick behavior and styling.

In `@apps/ui/src/hooks/use-multi-project-status.ts`:
- Around line 64-68: The error handling uses data.error?.message but the server
returns error as a string; update the throw to use the string directly. In the
fetch flow (after awaiting response.json()) replace the thrown Error creation to
use data.error (or fallback text) instead of data.error?.message so the code
reads something like throw new Error(data.error || 'Failed to fetch project
overview'); target the block that reads response.json() and the throw new
Error(...) statement in use-multi-project-status (the variable data and the
error throw are the unique symbols to edit).

In `@tests/e2e/multi-project-dashboard.spec.ts`:
- Line 1: The file starts with a JSDoc comment token (/**) and fails Prettier
formatting; run the project's Prettier formatter (e.g., prettier --write) on
this test file to fix code style, then stage/commit the formatted changes so the
pipeline passes — ensure you use the repo's Prettier config so the test spec
(the multi-project dashboard e2e spec) is reformatted consistently.
🧹 Nitpick comments (8)
apps/ui/tests/projects/overview-dashboard.spec.ts (1)

56-61: Prefer a stable selector for the back button.
The current button + svg heuristic can break if the header adds more icon buttons. Consider using a dedicated data-testid (or accessible name) for the back button to reduce flakiness.

apps/ui/src/components/views/overview/running-agents-panel.tsx (1)

112-117: Consider using GitBranch icon for branch display.

The Folder icon is used to display the active branch, but GitBranch from lucide-react would be more semantically appropriate for git branch information.

Proposed fix
-import { Bot, Activity, Folder, ArrowRight } from 'lucide-react';
+import { Bot, Activity, GitBranch, ArrowRight } from 'lucide-react';
              {agent.activeBranch && (
                <span className="flex items-center gap-1">
-                 <Folder className="w-3 h-3" />
+                 <GitBranch className="w-3 h-3" />
                  {agent.activeBranch}
                </span>
              )}
apps/server/src/routes/projects/routes/overview.ts (1)

190-208: Consider logging per-project load failures for debugging.

The catch block at line 190 catches errors but doesn't log them. While returning a fallback status is correct, logging would help with debugging failed project loads.

Proposed fix
        } catch (error) {
+         logError(error, `Failed to load project: ${projectRef.name}`);
          // Return a minimal status for projects that fail to load
          return {
            projectId: projectRef.id,
apps/server/src/routes/projects/index.ts (1)

5-10: Inconsistent import style for FeatureLoader.

FeatureLoader is imported as a value (line 6) while the other services use type imports. Since FeatureLoader is only used as a type annotation in the function signature, consider using a type import for consistency.

Proposed fix
 import { Router } from 'express';
-import { FeatureLoader } from '../../services/feature-loader.js';
+import type { FeatureLoader } from '../../services/feature-loader.js';
 import type { AutoModeService } from '../../services/auto-mode-service.js';
tests/e2e/multi-project-dashboard.spec.ts (2)

67-67: Avoid waitForTimeout for more reliable tests.

page.waitForTimeout(2000) introduces arbitrary delays and can cause flaky tests. Consider using Playwright's auto-waiting capabilities or explicit conditions.

Proposed fix
-   // Wait for loading to complete (either shows content or error)
-   await page.waitForTimeout(2000);
+   // Wait for loading to complete by checking for expected elements
+   await expect(
+     page.locator('[data-testid^="project-status-card-"], :text("No projects yet"), :text("Failed to load overview")')
+       .first()
+   ).toBeVisible({ timeout: 5000 });

101-119: Reduce reliance on waitForTimeout in refresh test.

Lines 105 and 115 use waitForTimeout which can cause flakiness. Consider waiting for specific network responses or UI state changes instead.

Proposed improvement
  test('should refresh data when refresh button is clicked', async ({ page }) => {
    await page.goto('/overview');

-   // Wait for initial load
-   await page.waitForTimeout(1000);
+   // Wait for initial load by checking the view is visible
+   await expect(page.getByTestId('overview-view')).toBeVisible();

    // Find the refresh button
    const refreshButton = page.locator('button').filter({ hasText: 'Refresh' });

    if (await refreshButton.isVisible({ timeout: 2000 }).catch(() => false)) {
+     // Set up response listener before clicking
+     const responsePromise = page.waitForResponse(
+       (resp) => resp.url().includes('/api/projects/overview') && resp.status() === 200
+     );
+
      await refreshButton.click();

-     // The button should show loading state (spinner icon)
-     // Wait a moment for the refresh to complete
-     await page.waitForTimeout(1000);
+     // Wait for the API response
+     await responsePromise;

      // Page should still be on overview
      await expect(page).toHaveURL(/\/overview/);
    }
  });
apps/ui/src/components/views/overview-view.tsx (1)

274-279: Consider specifying locale options for consistent time formatting.

The toLocaleTimeString() call without options may produce inconsistent results across different browser locales.

♻️ Optional: Add time format options for consistency
             {/* Footer timestamp */}
             <div className="text-center text-xs text-muted-foreground pt-4">
-              Last updated: {new Date(overview.generatedAt).toLocaleTimeString()}
+              Last updated: {new Date(overview.generatedAt).toLocaleTimeString(undefined, {
+                hour: '2-digit',
+                minute: '2-digit',
+                second: '2-digit',
+              })}
             </div>
apps/ui/src/components/views/dashboard-view.tsx (1)

574-584: Consider adding data-testid to the mobile Overview button for test consistency.

The desktop button has data-testid="projects-overview-button" but the mobile version lacks one, which could make E2E testing on mobile viewports more difficult.

♻️ Add data-testid to mobile button
               <Button
                 variant="outline"
                 size="icon"
                 onClick={() => navigate({ to: '/overview' })}
                 title="Projects Overview"
+                data-testid="projects-overview-button-mobile"
               >
                 <LayoutDashboard className="w-4 h-4" />
               </Button>

stefandevo and others added 4 commits January 22, 2026 18:08
Add new unified-sidebar component for layout improvements.
- Export UnifiedSidebar from layout components
- Update root route to use new sidebar structure
Merge the unified-sidebar implementation into the standard sidebar
folder structure. The unified sidebar becomes the canonical sidebar
with improved features including collapsible sections, scroll
indicators, and enhanced mobile support.

- Delete old sidebar.tsx
- Move unified-sidebar components to sidebar/components
- Rename UnifiedSidebar to Sidebar
- Update all imports in __root.tsx
- Remove redundant unified-sidebar folder
…ebar

- Add try/catch for getElectronAPI() in sidebar-footer with window.open fallback
- Use formatShortcut() for OS-aware hotkey display in sidebar-header
- Remove unnecessary optional chaining on project.icon
- Remove redundant ternary in sidebar-navigation className
- Update E2E tests to use new project-dropdown-trigger data-testid

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@stefandevo stefandevo changed the base branch from main to v0.14.0rc January 23, 2026 01:08
stefandevo and others added 7 commits January 23, 2026 02:09
…9-gg62' into feature/unified-sidebar

# Conflicts:
#	apps/server/src/index.ts
#	apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx
#	libs/types/src/index.ts
Replace separate Dashboard and Projects Overview nav items with a single
Dashboard item that links to /overview. Update all logo click handlers
to navigate to /overview for consistency.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove back button and rename title from "Projects Overview" to "Dashboard"
since the overview is now the main dashboard accessed via sidebar.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add project creation and folder opening functionality directly to the
Dashboard view header for quick access. Includes NewProjectModal with
template support and WorkspacePickerModal integration.

Also renamed title to "Automaker Dashboard".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Keyboard accessibility:
- Add role="button", tabIndex, onKeyDown, and aria-label to clickable divs
  in project-status-card, recent-activity-feed, and running-agents-panel

Bug fixes:
- Fix handleActivityClick to use projectPath instead of projectId for
  initializeProject and check result before navigating
- Fix error handling in use-multi-project-status to use data.error string
  directly instead of data.error?.message

Improvements:
- Use GitBranch icon instead of Folder for branch display in running-agents-panel
- Add error logging for failed project loads in overview.ts
- Use type import for FeatureLoader in projects/index.ts
- Add data-testid to mobile Overview button in dashboard-view
- Add locale options for consistent time formatting in overview-view

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

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 `@apps/ui/src/components/views/overview-view.tsx`:
- Around line 124-167: The create flows (e.g., handleCreateBlankProject)
currently proceed to addProject, setCurrentProject and navigate even if
initializeProject fails; change the flow to await and verify initializeProject
succeeded before mutating state or navigating: after calling
initializeProject(projectPath) check its return value (or wrap initializeProject
in a try/catch and rethrow on failure) and only create the project object, call
addProject, setCurrentProject and navigate when initialization succeeds; if
initialization fails, throw or return early so the catch block handles
logging/toast and setIsCreating(false). Apply the same guard to the other
creation handlers mentioned (the blocks around lines 170-215 and 217-256).
🧹 Nitpick comments (1)
apps/ui/src/components/views/overview-view.tsx (1)

18-25: Prefer components barrel imports for intra-app UI components.

Consider importing UI/dialog components (and overview subcomponents if exported) from the components index barrel to keep internal imports stable. Based on learnings, ...

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@apps/server/src/routes/projects/routes/overview.ts`:
- Around line 72-99: computeHealthStatus currently never returns 'waiting'
because pending work with no running/auto mode falls through to 'idle'; update
the function (computeHealthStatus) to return 'waiting' when
featureCounts.pending > 0 and featureCounts.running === 0 and !isAutoModeRunning
(or when pending exists but not actively running), before the final 'idle'
branch. Keep the existing early 'error' and 'active' checks
(featureCounts.failed and featureCounts.running || (isAutoModeRunning &&
featureCounts.pending)), and retain the 'completed' logic using totalFeatures
and pending===0 & running===0; insert the 'waiting' return just after those
checks so pending-only projects map to 'waiting' instead of 'idle'.

In `@apps/ui/src/components/views/overview/running-agents-panel.tsx`:
- Around line 68-75: The handler uses an undefined type RunningAgentInfo; update
the type reference in handleAgentKeyDown to use the locally declared
RunningAgent interface instead (replace RunningAgentInfo with RunningAgent
wherever it appears in the handleAgentKeyDown signature and related callbacks,
e.g., the useCallback parameter and any usages that pass agent to
handleAgentClick) so the component compiles against the correct local type.
♻️ Duplicate comments (1)
apps/ui/src/components/views/overview-view.tsx (1)

124-166: Guard creation flows on initializeProject success.
Right now initializeProject(...) is awaited but its result is ignored, so the app can add/set projects and navigate even when init fails. Please short‑circuit on failure in all three create flows.

🐛 Suggested fix pattern
-        await initializeProject(projectPath);
+        const initResult = await initializeProject(projectPath);
+        if (!initResult.success) {
+          toast.error('Failed to initialize project', {
+            description: initResult.error || 'Unknown error occurred',
+          });
+          return;
+        }
-        await initializeProject(cloneResult.projectPath);
+        const initResult = await initializeProject(cloneResult.projectPath);
+        if (!initResult.success) {
+          toast.error('Failed to initialize project', {
+            description: initResult.error || 'Unknown error occurred',
+          });
+          return;
+        }
-        await initializeProject(cloneResult.projectPath);
+        const initResult = await initializeProject(cloneResult.projectPath);
+        if (!initResult.success) {
+          toast.error('Failed to initialize project', {
+            description: initResult.error || 'Unknown error occurred',
+          });
+          return;
+        }

Also applies to: 170-215, 217-256

🧹 Nitpick comments (1)
apps/server/src/routes/projects/routes/overview.ts (1)

139-297: Consider moving aggregation logic into a service.
The handler owns sizable business logic; extracting into services/ will improve testability and keep routes thin. As per coding guidelines, ...

stefandevo and others added 2 commits January 23, 2026 02:37
Check the return value of initializeProject in all three create handlers
(handleCreateBlankProject, handleCreateFromTemplate, handleCreateFromCustomUrl)
and return early with an error toast if initialization fails, preventing
addProject/setCurrentProject/navigate from being called on failure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'waiting' status to computeHealthStatus for projects with pending
  features but no active execution (fixes status never being emitted)
- Fix undefined RunningAgentInfo type to use local RunningAgent interface

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

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 `@apps/ui/src/components/views/overview-view.tsx`:
- Around line 53-81: The handleOpenProject useCallback currently has an empty
dependency array and closes over initializeAndOpenProject, which can change;
update the dependency array of handleOpenProject to include
initializeAndOpenProject (i.e. useCallback(..., [initializeAndOpenProject])) so
the callback always uses the latest initializeAndOpenProject reference; locate
the handleOpenProject definition in overview-view.tsx and replace the [] with
[initializeAndOpenProject], then run lint/TS checks to ensure no other related
missing deps remain.
🧹 Nitpick comments (2)
apps/ui/src/components/views/overview-view.tsx (2)

18-25: Prefer components barrel exports for intra-app UI imports.

Line 18–25: Consider importing UI/dialog/view components from the app’s components index barrel (if exported) to avoid deep paths and relative imports. This aligns with the intra-app import convention and improves refactorability. Based on learnings, ...


101-103: Consider centralizing project open state updates.

Lines 101–103, 159–160, 210–211, 259–260: These repeated addProject + setCurrentProject sequences could be consolidated via the existing upsertAndSetCurrentProject helper (used elsewhere in overview components) to keep state updates consistent and reduce duplication.

Also applies to: 159-160, 210-211, 259-260

stefandevo and others added 2 commits January 23, 2026 02:57
- Fix handleOpenProject dependency array to include initializeAndOpenProject
- Use upsertAndSetCurrentProject instead of separate addProject + setCurrentProject
- Reorder callback declarations to avoid use-before-definition
- Update E2E tests to match renamed Dashboard UI (was "Projects Overview")
- Add success: true to mock API responses for proper test functioning
- Fix strict mode violation in project status card test

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change 'waiting_approval' status to 'in_progress' and add handling for 'waiting_approval' as pending.
- Introduce counting of live running features per project in the overview handler by fetching all running agents.
- Ensure accurate representation of project statuses in the overview.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@Shironex Shironex merged commit 7a33940 into v0.14.0rc Jan 23, 2026
4 of 6 checks passed
@Shironex Shironex deleted the feature/v0.14.0rc-1768981697539-gg62 branch January 23, 2026 09:13
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@apps/server/src/routes/projects/routes/overview.ts`:
- Around line 175-181: The code overwrites featureCounts.running with
liveRunningCount which can desync totals and incorrectly mark projects
completed; instead either (A) keep the live count separate by assigning
liveRunningCount to a new key (e.g., featureCounts.liveRunning) and leave
featureCounts.running as the state-derived running count, or (B) if you must
replace running, recompute featureCounts.total and any derived completion logic
immediately after using all state counts so totalFeatures remains consistent;
locate usage of allRunningAgents, projectRef.path, and featureCounts in this
block and apply one of these fixes so totals and completion status stay correct.

In `@apps/ui/tests/projects/overview-dashboard.spec.ts`:
- Around line 371-376: The mocked error response in the test's route.fulfill
call doesn't include the API's `success: false` field; update the JSON payload
passed to route.fulfill (the body object in the failing response) to include
"success": false so the mock matches the real API contract and client error
handling is exercised correctly.
🧹 Nitpick comments (2)
apps/server/src/routes/projects/routes/overview.ts (1)

28-146: Consider moving overview computations into a service layer.

computeFeatureCounts, computeHealthStatus, and getLastActivityAt are business logic living in the route module. Extracting these into services/ (and keeping the handler as orchestration only) will keep routing thin and make reuse/testing easier. As per coding guidelines, consider moving these helpers into a service module.

apps/ui/src/components/views/overview-view.tsx (1)

23-25: Prefer barrel exports for overview subcomponents.

If the overview folder (or components index) exposes a barrel, consider importing these subcomponents from it to keep paths stable and refactors easier.

♻️ Example (if an index barrel exists)
-import { ProjectStatusCard } from './overview/project-status-card';
-import { RecentActivityFeed } from './overview/recent-activity-feed';
-import { RunningAgentsPanel } from './overview/running-agents-panel';
+import { ProjectStatusCard, RecentActivityFeed, RunningAgentsPanel } from './overview';

Based on learnings, prefer barrel exports for intra-app UI components.

Comment on lines +175 to +181
// Count live running features for this project (across all branches)
// This ensures we only count features that are actually running in memory
const liveRunningCount = allRunningAgents.filter(
(agent) => agent.projectPath === projectRef.path
).length;
featureCounts.running = liveRunningCount;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep feature counts consistent after overriding running.

Overwriting featureCounts.running with liveRunningCount can desync counts from totalFeatures and can mark a project completed even if there are still features in non‑completed states. Consider reconciling the counts when you override running, or keep live running count separate.

🛠️ Possible fix to keep totals consistent
-          const liveRunningCount = allRunningAgents.filter(
+          const liveRunningCount = allRunningAgents.filter(
             (agent) => agent.projectPath === projectRef.path
           ).length;
-          featureCounts.running = liveRunningCount;
+          if (liveRunningCount !== featureCounts.running) {
+            const delta = liveRunningCount - featureCounts.running;
+            featureCounts.running = liveRunningCount;
+            if (delta > 0) {
+              featureCounts.pending = Math.max(0, featureCounts.pending - delta);
+            } else if (delta < 0) {
+              featureCounts.pending += -delta;
+            }
+          }
🤖 Prompt for AI Agents
In `@apps/server/src/routes/projects/routes/overview.ts` around lines 175 - 181,
The code overwrites featureCounts.running with liveRunningCount which can desync
totals and incorrectly mark projects completed; instead either (A) keep the live
count separate by assigning liveRunningCount to a new key (e.g.,
featureCounts.liveRunning) and leave featureCounts.running as the state-derived
running count, or (B) if you must replace running, recompute featureCounts.total
and any derived completion logic immediately after using all state counts so
totalFeatures remains consistent; locate usage of allRunningAgents,
projectRef.path, and featureCounts in this block and apply one of these fixes so
totals and completion status stay correct.

Comment on lines +371 to +376
await route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({
error: 'Internal server error',
}),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align error mock with API contract (success: false).

The server’s error response includes success: false; adding it here keeps the mock aligned with real responses and avoids divergent client handling.

✅ Suggested adjustment
-        body: JSON.stringify({
-          error: 'Internal server error',
-        }),
+        body: JSON.stringify({
+          success: false,
+          error: 'Internal server error',
+        }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({
error: 'Internal server error',
}),
await route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({
success: false,
error: 'Internal server error',
}),
🤖 Prompt for AI Agents
In `@apps/ui/tests/projects/overview-dashboard.spec.ts` around lines 371 - 376,
The mocked error response in the test's route.fulfill call doesn't include the
API's `success: false` field; update the JSON payload passed to route.fulfill
(the body object in the failing response) to include "success": false so the
mock matches the real API contract and client error handling is exercised
correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Do Not Merge Use this label if something should not be merged. Testers-Requested Request for others to test an enhancement or bug fix/etc. type: feature A new capability or functionality that does not exist yet. Work-In-Progress Currently being addressed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants