Skip to content

Conversation

@illia1f
Copy link
Contributor

@illia1f illia1f commented Jan 2, 2026

Summary

Fixes #283 - Resolves silent failures when project folders are moved, renamed, or deleted from the filesystem.

Changes

Path Validation System

  • New validation utility (validate-project-path.ts): Centralized async path validation with existence and directory checks
  • Validation dialog (project-path-validation-dialog.tsx): User-friendly dialog when invalid paths are detected, offering:
    • Locate Project: Update path to new location
    • Remove: Delete project from list
    • Dismiss: Cancel action and stay on welcome page

Consistent Validation Across All Entry Points

  • Keyboard shortcuts (Q/E) - use-validated-project-cycling.ts: New hook validates paths before cycling, automatically skips invalid projects
  • Project selector dropdown - project-selector-with-options.tsx: Validates on manual selection
  • App startup - __root.tsx: Validates currentProject before auto-restoring to board view
  • Trash restoration - use-trash-operations.ts: Prevents restoring projects with missing directories

Supporting Infrastructure

  • Store hydration hook use-store-hydration.ts: Ensures validation only runs after persisted state loads
  • Updated sidebar (sidebar.tsx): Uses validated cycling instead of direct store methods

Behavior

Before: Keyboard shortcuts bypassed validation, app would silently break on invalid paths, data loss on restart

After:

  • All project switches validate paths first
  • Invalid paths trigger clear dialog with actionable options
  • Keyboard shortcuts automatically skip invalid projects
  • No silent failures or data loss

Screenshots

image_2026-01-02_00-59-16

Testing

Verified:

  • ✅ Keyboard shortcuts (Q/E) skip deleted projects
  • ✅ Manual selection shows dialog for invalid paths
  • ✅ App startup validates and prompts if current project path missing
  • ✅ Trash restoration blocks invalid paths with clear error
  • ✅ Path update via "Locate Project" works correctly
  • ✅ Project removal cleans up state properly

Summary by CodeRabbit

  • New Features

    • Projects now validate path accessibility before switching or cycling; invalid projects are skipped during cycling.
    • A recovery dialog appears for projects with missing/invalid paths, letting you locate (Enter/Ctrl/Cmd+Enter), refresh, or remove a project.
    • App startup restoration includes validated checks and will prompt recovery when needed.
    • Restores/undelete now validate project paths and show errors if invalid.
  • Tests

    • UI tests support using a temporary filesystem project path for path-validation scenarios.

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

- Introduced ProjectPathValidationDialog component to handle scenarios where project paths are invalid or inaccessible.
- Implemented path validation logic in project selection and trash operations, ensuring users are notified of invalid paths and can update or remove projects accordingly.
- Enhanced project cycling functionality to skip invalid paths automatically, improving user experience when navigating through project history.
- Added validateProjectPath utility to check the existence and accessibility of project directories.
@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Adds end-to-end project-path validation: new validator, dialog component, and hooks that detect invalid project folders, prompt the user (refresh/remove/dismiss), and ensure project switching, cycling, restoration, and trash-restore flows validate paths before navigation. (≈29 words)

Changes

Cohort / File(s) Summary
Path Validation Utility
apps/ui/src/lib/validate-project-path.ts
New async validator that verifies a project's path exists and is a directory via Electron APIs; returns boolean and logs errors.
Dialog Component
apps/ui/src/components/dialogs/project-path-validation-dialog.tsx
New modal displaying project name/path with actions: Dismiss, Remove, Locate (file browser); hotkey-enabled Locate and suppressed outside interaction.
Project Path Validation Hook
apps/ui/src/hooks/use-project-path-validation.ts
New hook managing dialog state and handlers (show, refresh, remove, dismiss); validates/refreshed paths, updates store, navigates optionally, and shows toasts.
Project Restoration Hook
apps/ui/src/hooks/use-project-restoration.ts
New hook run on app init to validate current project (optional IPC ping); opens validation dialog for invalid paths or navigates to /board when valid.
Validated Cycling Hook
apps/ui/src/hooks/use-validated-project-cycling.ts
New hook providing cyclePrevProject / cycleNextProject that skip invalid or missing projects and update store/router on valid targets.
Store Hydration Hook & Barrel Exports
apps/ui/src/hooks/use-store-hydration.ts, apps/ui/src/hooks/index.ts
New hook to track store persist hydration; barrel exports updated to include new hooks.
Sidebar: Cycling & Trash Integration
apps/ui/src/components/layout/sidebar.tsx
Sidebar now consumes useValidatedProjectCycling; navigation wiring updated; useTrashOperations now receives trashedProjects.
Project Selector: Validation Flow
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
Validates target project path on select; opens ProjectPathValidationDialog if invalid; wired dialog handlers for refresh/remove.
Trash Operations: Restore Validation
apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
useTrashOperations API extended to accept trashedProjects; handleRestoreProject is async and validates path before restoring with descriptive toasts.
Root Route Integration
apps/ui/src/routes/__root.tsx
Replaced manual hydration with useStoreHydration; integrated useProjectRestoration and useProjectPathValidation; injected ProjectPathValidationDialog into root layout.
Tests: Profile Setup & Temp Dir
apps/ui/tests/..., apps/ui/tests/utils/project/setup.ts
Tests support real filesystem paths via temp dir; setupMockProjectWithProfiles accepts optional projectPath to enable path validation in tests.
Misc: Test submodule pointers
apps/ui/test/...
Multiple test submodule commit pointer updates (metadata only).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as Selector / Shortcut / Root
    participant Validator as validateProjectPath()
    participant Dialog as ProjectPathValidationDialog
    participant Store as AppStore
    participant FS as File Browser / Electron API
    participant Router as Router

    User->>UI: Request switch or app init
    UI->>Validator: validate target project path
    alt Path valid
        Validator-->>UI: true
        UI->>Store: set currentProject / update history
        UI->>Router: navigate /board
    else Path invalid
        Validator-->>UI: false
        UI->>Dialog: open(invalidProject)
        Dialog-->>User: show options (Locate / Remove / Dismiss)
        alt User chooses Locate
            User->>Dialog: open file browser
            Dialog->>FS: pick new path
            FS-->>Dialog: newPath
            Dialog->>Validator: validate newPath
            alt newPath valid
                Validator-->>Dialog: true
                Dialog->>Store: update project.path, set currentProject
                Dialog->>Router: navigate /board
            else newPath invalid
                Validator-->>Dialog: false
                Dialog-->>User: show error toast
            end
        else User chooses Remove
            User->>Dialog: remove project
            Dialog->>Store: remove project, clear currentProject
            Dialog->>Router: navigate /home
        else User chooses Dismiss
            User->>Dialog: dismiss
            Dialog-->>UI: close dialog
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Bug, Enhancement

Suggested reviewers

  • Shironex

Poem

🐰 I hop through folders, nose to the ground,
If paths are missing I give a soft sound.
Refresh, remove, or gently dismiss—
I tidy the routes so projects won't miss.
Hooray, steady switches with breadcrumbs found.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective: adding project path validation across all project switching methods, which is the core of the PR.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #283: validates paths across all switching methods (keyboard shortcuts, manual selection, app startup, trash restoration), provides clear user feedback via dialog, and prevents silent failures.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #283 objectives: validation infrastructure, dialog UI, hook integrations, and test updates support the core requirement of consistent path validation across switching methods.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58903a8 and 61eb3a0.

📒 Files selected for processing (4)
  • apps/ui/src/components/layout/sidebar.tsx
  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
  • apps/ui/src/hooks/index.ts
  • apps/ui/src/routes/__root.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ui/src/hooks/index.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
  • apps/ui/src/components/layout/sidebar.tsx
  • apps/ui/src/routes/__root.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
  • apps/ui/src/components/layout/sidebar.tsx
  • apps/ui/src/routes/__root.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.

Applied to files:

  • apps/ui/src/components/layout/sidebar.tsx
  • apps/ui/src/routes/__root.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory

Applied to files:

  • apps/ui/src/routes/__root.tsx
🧬 Code graph analysis (3)
apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts (3)
apps/ui/src/lib/electron.ts (1)
  • TrashedProject (2945-2948)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
  • useTrashOperations (5-5)
apps/ui/src/lib/validate-project-path.ts (1)
  • validateProjectPath (4-34)
apps/ui/src/components/layout/sidebar.tsx (2)
apps/ui/src/hooks/index.ts (1)
  • useValidatedProjectCycling (13-13)
apps/ui/src/hooks/use-validated-project-cycling.ts (1)
  • useValidatedProjectCycling (20-109)
apps/ui/src/routes/__root.tsx (5)
apps/ui/src/hooks/use-store-hydration.ts (1)
  • useStoreHydration (19-36)
apps/ui/src/store/app-store.ts (1)
  • useAppStore (1059-3041)
apps/ui/src/hooks/use-project-path-validation.ts (1)
  • useProjectPathValidation (16-94)
apps/ui/src/hooks/use-project-restoration.ts (1)
  • useProjectRestoration (22-86)
apps/ui/src/components/dialogs/project-path-validation-dialog.tsx (1)
  • ProjectPathValidationDialog (24-129)
⏰ 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). (1)
  • GitHub Check: e2e
🔇 Additional comments (11)
apps/ui/src/routes/__root.tsx (5)

26-27: LGTM!

The imports correctly bring in the new hooks and dialog component needed for the centralized project path validation flow. Using path aliases for app-specific modules is appropriate.


45-46: LGTM!

The refactor to use useStoreHydration cleanly centralizes hydration state management for both stores, reducing boilerplate and improving maintainability.


51-59: LGTM!

The useProjectPathValidation hook properly encapsulates dialog state and handlers. All returned values are correctly utilized later in the component (dialog integration and restoration flow).


290-299: Excellent refactor that addresses previous review concerns!

The extraction of restoration logic into useProjectRestoration directly resolves the two issues raised in prior reviews:

  1. Code duplication eliminated: The validate-and-restore logic is now centralized in the hook instead of duplicated across Electron and web branches.
  2. Concurrent validation prevented: The hook uses isValidatingRef (visible in the relevant code snippets) to guard against overlapping async validation attempts.

All required dependencies are correctly passed, and the hook properly handles both Electron IPC checks and web mode flows.


417-424: LGTM!

The ProjectPathValidationDialog is correctly integrated into the layout with all props properly wired to the validation hook's state and handlers. The dialog provides the expected user actions (Locate Project, Remove, Dismiss) for handling invalid project paths.

apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts (3)

7-7: LGTM: Clean integration of validation dependency.

The import and interface extension correctly prepare the hook to validate projects before restoration.

Also applies to: 13-13, 20-20


26-42: Excellent defensive validation with clear user guidance.

The two-stage validation (project existence + path validation) prevents silent failures and provides actionable error messages. The approach aligns perfectly with the PR objectives to "offer actionable options" when project directories are missing.


55-55: Correct dependency array.

Properly includes both trashedProjects (used in line 28) and restoreTrashedProject (used in line 44).

apps/ui/src/components/layout/sidebar.tsx (3)

9-9: LGTM: Proper import of validated cycling hook.


76-77: Excellent integration of validated project cycling.

The hook automatically validates and skips invalid projects during keyboard shortcuts (Q/E), preventing silent failures while maintaining smooth UX. The comment accurately describes the behavior.


153-153: Correct prop passing for trash validation.

Properly passes trashedProjects to enable path validation during project restoration, matching the updated hook interface.


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 @illia1f, 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 significantly enhances the application's robustness by implementing a comprehensive project path validation system. It addresses issues where projects could become inaccessible due to filesystem changes, leading to silent failures. By integrating validation at every project access point and providing clear user feedback through a dedicated dialog, the PR ensures a more stable and user-friendly experience, preventing data loss and improving overall application reliability.

Highlights

  • Path Validation System: Introduced a new centralized utility (validate-project-path.ts) for asynchronous path validation, checking for existence and directory status. A user-friendly dialog (project-path-validation-dialog.tsx) is displayed when invalid paths are detected, offering options to locate the project, remove it, or dismiss the alert.
  • Consistent Validation Across Entry Points: Project path validation is now enforced across all methods of project switching: keyboard shortcuts (Q/E) via a new useValidatedProjectCycling hook, manual selection from the project selector dropdown, during app startup when restoring the currentProject, and when restoring projects from the trash.
  • Improved User Experience: This change resolves silent failures and potential data loss that occurred when project folders were moved, renamed, or deleted. The application now provides clear, actionable feedback to the user, automatically skipping invalid projects during cycling and preventing restoration of projects with missing directories.
  • Store Hydration Hook: A new useStoreHydration hook ensures that path validation and other state-dependent operations only run after the persisted application state has been fully loaded, preventing race conditions and ensuring data integrity.

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

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 robust path validation system for projects, which is a great improvement to prevent silent failures. The changes are well-structured, with new hooks and components for validation logic and UI. The validation is consistently applied across different ways of switching projects.

My review focuses on improving maintainability by reducing code duplication and enhancing type safety. I've identified several areas where similar logic is repeated across components (__root.tsx and project-selector-with-options.tsx) and within hooks (use-validated-project-cycling.ts). Extracting this duplicated logic into shared hooks or helper functions would make the code cleaner and easier to maintain. I also found a minor bug where a dialog doesn't close as expected. Additionally, I've suggested some minor improvements to logging and typing for better developer experience and robustness.

Overall, this is a solid contribution that addresses an important issue. The suggested refactorings will help to improve the quality of the new code even further.

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

🧹 Nitpick comments (3)
apps/ui/src/hooks/use-store-hydration.ts (1)

12-12: Improve type safety for the store parameter.

The any type bypasses TypeScript's type checking. Define an interface or use a constrained generic type to ensure the store has the expected persist API.

🔎 Proposed fix with a constrained interface
+interface StoreWithPersist {
+  persist?: {
+    hasHydrated?: () => boolean;
+    onFinishHydration?: (callback: () => void) => (() => void) | undefined;
+  };
+}
+
-export function useStoreHydration(store: any) {
+export function useStoreHydration(store: StoreWithPersist) {
   const [hydrated, setHydrated] = useState(() => store.persist?.hasHydrated?.() ?? false);
apps/ui/src/lib/validate-project-path.ts (1)

4-39: Consider optimizing the validation flow.

The function makes two separate API calls: exists() followed by stat(). Since stat() will fail if the path doesn't exist, you could simplify by using only stat() and checking both success and isDirectory in one operation. This would reduce API calls and improve performance.

🔎 Proposed optimization
 export const validateProjectPath = async (project: Project): Promise<boolean> => {
   try {
     if (!project?.path) {
       console.error('[Validation] No project path provided');
       return false;
     }
 
     console.log('[Validation] Checking path:', project.path);
 
     const api = getElectronAPI();
-    // Check if path exists
-    const exists = await api.exists(project.path);
-    console.log('[Validation] Exists result:', exists);
-
-    if (exists !== true) {
-      console.error('[Validation] Path does not exist');
-      return false;
-    }
-
-    // Verify it's a directory
     const statResult = await api.stat(project.path);
     console.log('[Validation] Stat result:', statResult);
 
     if (!statResult.success || !statResult.stats?.isDirectory) {
-      console.error('[Validation] Path is not a directory or stat failed');
+      console.error('[Validation] Path does not exist, is not a directory, or stat failed');
       return false;
     }
 
     console.log('[Validation] Path is valid!');
     return true;
   } catch (error) {
     // Treat errors as invalid (permissions, network issues, etc.)
     console.error('[Validation] Exception during validation:', error);
     return false;
   }
 };
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1)

101-132: Consider extracting shared validation handlers to reduce duplication.

The handleRefreshPath and handleRemoveProject implementations here are nearly identical to those in apps/ui/src/routes/__root.tsx (lines 365-404). Both:

  1. Validate the new path with validateProjectPath
  2. Update projects via setProjects with the same mapping logic
  3. Update currentProject and navigate
  4. Show the same toast messages

Consider extracting these handlers into a shared hook (e.g., useProjectPathValidation) to centralize the logic and reduce maintenance burden.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab9ef0d and 4abf4bb.

📒 Files selected for processing (9)
  • apps/ui/src/components/dialogs/project-path-validation-dialog.tsx
  • apps/ui/src/components/layout/sidebar.tsx
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
  • apps/ui/src/hooks/index.ts
  • apps/ui/src/hooks/use-store-hydration.ts
  • apps/ui/src/hooks/use-validated-project-cycling.ts
  • apps/ui/src/lib/validate-project-path.ts
  • apps/ui/src/routes/__root.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/hooks/index.ts
  • apps/ui/src/hooks/use-store-hydration.ts
  • apps/ui/src/lib/validate-project-path.ts
  • apps/ui/src/hooks/use-validated-project-cycling.ts
  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/components/dialogs/project-path-validation-dialog.tsx
  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/components/layout/sidebar.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/hooks/index.ts
  • apps/ui/src/hooks/use-store-hydration.ts
  • apps/ui/src/lib/validate-project-path.ts
  • apps/ui/src/hooks/use-validated-project-cycling.ts
  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/components/dialogs/project-path-validation-dialog.tsx
  • apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/components/layout/sidebar.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.

Applied to files:

  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/components/dialogs/project-path-validation-dialog.tsx
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/components/layout/sidebar.tsx
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory

Applied to files:

  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
🧬 Code graph analysis (7)
apps/ui/src/hooks/use-store-hydration.ts (1)
apps/ui/src/hooks/index.ts (1)
  • useStoreHydration (11-11)
apps/ui/src/lib/validate-project-path.ts (2)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (728-737)
apps/ui/src/lib/http-api-client.ts (1)
  • exists (820-825)
apps/ui/src/hooks/use-validated-project-cycling.ts (1)
apps/ui/src/lib/validate-project-path.ts (1)
  • validateProjectPath (4-39)
apps/ui/src/routes/__root.tsx (4)
apps/ui/src/hooks/use-store-hydration.ts (1)
  • useStoreHydration (12-29)
apps/ui/src/lib/electron.ts (2)
  • Project (2826-2832)
  • getElectronAPI (728-737)
apps/ui/src/lib/validate-project-path.ts (1)
  • validateProjectPath (4-39)
apps/ui/src/components/dialogs/project-path-validation-dialog.tsx (1)
  • ProjectPathValidationDialog (24-129)
apps/ui/src/components/dialogs/project-path-validation-dialog.tsx (1)
apps/ui/src/components/ui/hotkey-button.tsx (1)
  • HotkeyButton (169-288)
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (3)
apps/ui/src/hooks/use-validated-project-cycling.ts (1)
  • useValidatedProjectCycling (20-144)
apps/ui/src/lib/validate-project-path.ts (1)
  • validateProjectPath (4-39)
apps/ui/src/components/dialogs/project-path-validation-dialog.tsx (1)
  • ProjectPathValidationDialog (24-129)
apps/ui/src/components/layout/sidebar.tsx (2)
apps/ui/src/hooks/index.ts (1)
  • useValidatedProjectCycling (12-12)
apps/ui/src/hooks/use-validated-project-cycling.ts (1)
  • useValidatedProjectCycling (20-144)
⏰ 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). (1)
  • GitHub Check: e2e
🔇 Additional comments (16)
apps/ui/src/hooks/index.ts (1)

11-12: LGTM!

The new exports follow the existing pattern and correctly expose the new hooks.

apps/ui/src/components/dialogs/project-path-validation-dialog.tsx (3)

62-68: LGTM: Dialog interaction correctly prevents dismissal.

Preventing onInteractOutside and hiding the close button appropriately forces users to make an explicit choice (Locate/Remove/Dismiss) when facing an invalid project path, which aligns well with the PR objectives to prevent silent failures.


114-124: LGTM: Keyboard shortcut implementation is correct.

The HotkeyButton configuration with Cmd/Ctrl+Enter follows the expected API and provides good keyboard accessibility for the primary action.


34-49: Review comment is not applicable — dialog closes after successful path refresh.

Both parent component implementations (__root.tsx and project-selector-with-options.tsx) properly close the dialog by calling setValidationDialogOpen(false) after onRefreshPath completes successfully. The dialog's state management is delegated to the parent component, which is an appropriate architectural pattern.

apps/ui/src/hooks/use-validated-project-cycling.ts (3)

26-36: LGTM: State update helper is correctly implemented.

The switchProjectForCycling helper appropriately updates all related state fields without reordering history, matching the cycling semantics described in the comments.


38-85: Excellent validation and error handling.

Both cycling functions properly:

  • Guard against concurrent operations with isValidating
  • Filter to valid history before cycling
  • Validate each candidate path before switching
  • Handle the case where all projects are invalid gracefully
  • Use correct wraparound arithmetic for array cycling

The implementation aligns well with the PR objectives to prevent silent failures.

Also applies to: 87-137


38-85: Cycling direction semantics are correct—no changes needed.

The projectHistory array in app-store.ts is explicitly documented as "MRU order (most recent first)" (line 403), with new projects added to the front via [project.id, ...filteredHistory] (line 1129). The cycling logic aligns correctly: cyclePrevProject moves to higher indices (older projects), and cycleNextProject moves to lower indices (newer/recent projects). The naming and implementation match typical user expectations for MRU history navigation.

apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts (1)

22-53: LGTM! Well-structured async validation before restore.

The validation flow correctly:

  1. Looks up the trashed project first
  2. Validates path existence before calling restoreTrashedProject
  3. Provides clear error messaging with actionable guidance
  4. Updates the dependency array appropriately
apps/ui/src/components/layout/sidebar.tsx (3)

6-6: LGTM! Clean integration of validated project cycling.

The import correctly uses the @/hooks path alias, and the hook cleanly encapsulates the validation logic that was previously missing from keyboard shortcuts.


73-74: Good refactor: Validation now integrated into cycling.

Sourcing cyclePrevProject and cycleNextProject from the new hook ensures keyboard shortcuts (Q/E) validate paths before switching, addressing the silent failure issue described in the PR objectives.


146-151: Correct: trashedProjects passed to support path validation in restore flow.

This aligns with the updated useTrashOperations interface that now requires trashedProjects for path validation during project restoration.

apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (2)

231-243: LGTM! Validation before project switch is correct.

The async onSelect handler properly:

  1. Closes the dropdown immediately (good UX)
  2. Validates the path before switching
  3. Opens the validation dialog if invalid, otherwise sets the current project

One consideration: if validation fails, the dropdown is already closed but no project switch occurs. This is acceptable UX since the dialog provides next steps.


426-432: Dialog integration looks correct.

The ProjectPathValidationDialog is properly wired with all required props. The dialog will display when a user selects a project with an invalid path.

apps/ui/src/routes/__root.tsx (3)

365-410: Dialog handlers work correctly but duplicate logic from project-selector.

As noted in the project-selector review, these handlers (handleRefreshPath, handleRemoveProject, handleDismiss) share significant logic with the same-named handlers in project-selector-with-options.tsx. The handleDismiss here additionally clears currentProject, which is appropriate for the startup context where the user dismisses an invalid project.


46-47: Good: Hydration hooks ensure validation runs after persisted state loads.

Using useStoreHydration for both appHydrated and setupHydrated ensures the restoration logic waits for Zustand persistence to complete before attempting to validate the currentProject path. This prevents race conditions where validation runs against stale or uninitialized state.


507-514: LGTM! Dialog correctly placed and wired.

The ProjectPathValidationDialog is rendered with all required props including the onDismiss handler, which is specific to the root context (clears currentProject when user dismisses).

- Introduced useProjectPathValidation hook to centralize project path validation logic, enhancing code reusability and maintainability.
- Updated ProjectSelectorWithOptions component to utilize the new hook, streamlining project path handling and validation.
- Refactored RootLayoutContent to integrate project restoration logic with path validation, improving user experience during project navigation.
- Added useProjectRestoration hook for managing project restoration on app initialization, ensuring valid project paths before navigation.
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

🧹 Nitpick comments (1)
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1)

199-210: Add error handling for the async validation in onSelect.

The validateProjectPath call could throw an exception, but there's no try-catch wrapper. While the validation function has internal error handling that returns false, wrapping in try-catch would provide defense-in-depth.

🔎 Suggested fix
                     onSelect={async (p) => {
                       setIsProjectPickerOpen(false);

-                      // Validate path before switching
-                      const isValid = await validateProjectPath(p);
-
-                      if (!isValid) {
-                        showValidationDialog(p);
-                      } else {
-                        setCurrentProject(p);
+                      try {
+                        // Validate path before switching
+                        const isValid = await validateProjectPath(p);
+
+                        if (!isValid) {
+                          showValidationDialog(p);
+                        } else {
+                          setCurrentProject(p);
+                        }
+                      } catch (error) {
+                        console.error('Failed to validate project path:', error);
+                        showValidationDialog(p);
                       }
                     }}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4abf4bb and d58f756.

📒 Files selected for processing (7)
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/hooks/index.ts
  • apps/ui/src/hooks/use-project-path-validation.ts
  • apps/ui/src/hooks/use-project-restoration.ts
  • apps/ui/src/hooks/use-store-hydration.ts
  • apps/ui/src/lib/validate-project-path.ts
  • apps/ui/src/routes/__root.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/ui/src/lib/validate-project-path.ts
  • apps/ui/src/hooks/use-store-hydration.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/hooks/index.ts
  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/hooks/use-project-restoration.ts
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/hooks/use-project-path-validation.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/hooks/index.ts
  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/hooks/use-project-restoration.ts
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
  • apps/ui/src/hooks/use-project-path-validation.ts
🧠 Learnings (2)
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Frontend UI must use TanStack Router for file-based routing, organize components in components/views/, implement stores with Zustand, and use custom hooks in hooks/ directory

Applied to files:

  • apps/ui/src/routes/__root.tsx
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.

Applied to files:

  • apps/ui/src/routes/__root.tsx
  • apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx
🧬 Code graph analysis (2)
apps/ui/src/routes/__root.tsx (4)
apps/ui/src/hooks/use-store-hydration.ts (1)
  • useStoreHydration (19-36)
apps/ui/src/hooks/use-project-path-validation.ts (1)
  • useProjectPathValidation (16-95)
apps/ui/src/hooks/use-project-restoration.ts (1)
  • useProjectRestoration (22-86)
apps/ui/src/components/dialogs/project-path-validation-dialog.tsx (1)
  • ProjectPathValidationDialog (24-129)
apps/ui/src/hooks/use-project-restoration.ts (4)
apps/ui/src/hooks/index.ts (1)
  • useProjectRestoration (13-13)
apps/ui/src/lib/electron.ts (1)
  • getElectronAPI (728-737)
apps/ui/src/lib/validate-project-path.ts (1)
  • validateProjectPath (4-34)
apps/ui/src/lib/http-api-client.ts (1)
  • isElectronMode (114-122)
⏰ 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). (1)
  • GitHub Check: e2e
🔇 Additional comments (15)
apps/ui/src/hooks/index.ts (1)

11-14: LGTM!

The new hook exports follow the established pattern and are correctly re-exported from the barrel file.

apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1)

36-39: LGTM!

The new imports for validation hooks and dialog component are correctly structured.

apps/ui/src/routes/__root.tsx (5)

25-26: LGTM!

Clean import of the new hooks and dialog component from the centralized locations.


41-42: LGTM!

The useStoreHydration hook is correctly applied to both stores, replacing the previous manual hydration tracking logic.


47-55: LGTM!

The useProjectPathValidation hook is correctly initialized with default options, and all necessary values are destructured for use in the component.


286-295: LGTM!

The useProjectRestoration hook is correctly wired with all necessary state and the validation dialog callback, fulfilling the PR objective of validating project paths on app startup.


413-420: LGTM!

The ProjectPathValidationDialog is correctly integrated with all necessary props, including onDismiss for proper cleanup when the user dismisses the dialog.

apps/ui/src/hooks/use-project-restoration.ts (4)

1-5: LGTM!

Imports are correctly structured, using local lib paths as appropriate for this UI app.


7-15: LGTM!

The options interface is well-structured with clear typing for all restoration prerequisites.


36-66: LGTM!

The validateAndRestore callback correctly implements the IPC check, path validation, and navigation flow. The isValidatingRef pattern properly prevents concurrent validation attempts, addressing previous review feedback.


68-85: LGTM!

The effect has comprehensive guards and the dependency array correctly includes all reactive values. The isValidatingRef check prevents duplicate validation runs even when validateAndRestore is recreated due to dependency changes.

apps/ui/src/hooks/use-project-path-validation.ts (4)

1-6: LGTM!

Imports are correctly structured and include all necessary dependencies.


70-79: LGTM!

The handleRemoveProject callback correctly removes the project, clears state, closes the dialog, and navigates to the home page.


81-84: LGTM!

The handleDismiss callback correctly clears the current project to prevent the user from being left in a broken state with an invalid project selected.


86-94: LGTM!

The hook returns a complete API with all necessary state and handlers for managing the validation dialog.

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: 0

🧹 Nitpick comments (1)
apps/ui/src/hooks/use-validated-project-cycling.ts (1)

26-36: Consider tightening the project parameter type.

The parameter project: typeof currentProject infers Project | null, but this helper is always called with a non-null Project (line 77, inside the if (targetProject && ...) guard). Changing the type to project: Project would more accurately reflect the call sites.

🔎 Suggested type refinement
 const switchProjectForCycling = useCallback(
-  (project: typeof currentProject, validHistory: string[], newIndex: number) => {
+  (project: Project, validHistory: string[], newIndex: number) => {
     useAppStore.setState({
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d58f756 and bbe533d.

📒 Files selected for processing (2)
  • apps/ui/src/hooks/use-project-path-validation.ts
  • apps/ui/src/hooks/use-validated-project-cycling.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ui/src/hooks/use-project-path-validation.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/hooks/use-validated-project-cycling.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/hooks/use-validated-project-cycling.ts
🧬 Code graph analysis (1)
apps/ui/src/hooks/use-validated-project-cycling.ts (1)
apps/ui/src/lib/validate-project-path.ts (1)
  • validateProjectPath (4-34)
⏰ 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). (1)
  • GitHub Check: e2e
🔇 Additional comments (2)
apps/ui/src/hooks/use-validated-project-cycling.ts (2)

39-94: Excellent consolidation of cycling logic!

The shared cycleProject helper with a direction parameter eliminates duplication and addresses the previous review's suggestion. The index calculation correctly cycles through all projects (with wraparound) while skipping the current project, and the sequential validation approach is appropriate for keyboard-driven cycling.


96-102: LGTM!

The wrapper functions provide a clean, direction-specific interface while reusing the shared logic.

@webdevcody
Copy link
Collaborator

e2e tests

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: 0

🧹 Nitpick comments (1)
apps/ui/tests/utils/project/setup.ts (1)

790-790: Consider implications of the fallback path.

The fallback to /mock/test-project maintains backward compatibility, but tests that don't provide projectPath will fail validation if they trigger path validation flows. While the JSDoc makes the requirement clear, existing tests using this function may need updates.

Consider whether tests that require path validation should explicitly fail without a valid projectPath rather than silently using a non-existent fallback path. However, the current approach with clear documentation is acceptable.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbe533d and 21e6daa.

📒 Files selected for processing (2)
  • apps/ui/tests/profiles/profiles-crud.spec.ts
  • apps/ui/tests/utils/project/setup.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/tests/utils/project/setup.ts
  • apps/ui/tests/profiles/profiles-crud.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/tests/utils/project/setup.ts
  • apps/ui/tests/profiles/profiles-crud.spec.ts
🧬 Code graph analysis (1)
apps/ui/tests/profiles/profiles-crud.spec.ts (2)
apps/ui/tests/utils/git/worktree.ts (2)
  • createTempDirPath (52-55)
  • cleanupTempDir (157-161)
apps/ui/tests/utils/project/setup.ts (1)
  • setupMockProjectWithProfiles (777-884)
⏰ 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). (1)
  • GitHub Check: e2e
🔇 Additional comments (4)
apps/ui/tests/utils/project/setup.ts (1)

782-783: Good documentation of the new parameter.

The JSDoc comment clearly indicates that projectPath is required for path validation, helping test authors understand when to provide a real filesystem path.

apps/ui/tests/profiles/profiles-crud.spec.ts (3)

8-8: Appropriate imports for test infrastructure.

The fs import and test utility imports (createTempDirPath, cleanupTempDir) are necessary for managing the temporary directory required for path validation testing.

Also applies to: 20-21


24-38: Well-structured temporary directory lifecycle.

The implementation properly manages the test directory lifecycle:

  • Unique path per test run prevents conflicts
  • Directory created in beforeAll ensures it exists for path validation
  • Cleanup in afterAll prevents test pollution

41-44: Test properly adapted for path validation.

Passing projectPath: TEST_TEMP_DIR ensures the test uses a real filesystem path, allowing the new project path validation flows to succeed. This change aligns with the PR's objective of implementing centralized path validation.

@illia1f
Copy link
Contributor Author

illia1f commented Jan 2, 2026

e2e tests

Tweaked and work :)

@webdevcody
Copy link
Collaborator

closing because of conflicts, reopen if this is still an issue

@webdevcody webdevcody closed this Jan 14, 2026
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.

Project Folder Validation Issues

2 participants