fix: handle project removal for cloud-only projects

**Problem:** Cloud projects that exist only in the database (not in
config.json) couldn't be removed. The error "Project 'name' not found"
occurred because config validation failed before database deletion.

**Root cause:**
- In cloud mode, projects can exist in database without config entries
- ProjectService.remove_project() called config_manager.remove_project()
  first, which raised ValueError if project wasn't in config
- This prevented removal of cloud-only projects

**Solution:**
1. Check database first for project existence (source of truth)
2. Validate default project status from both database and config
3. Try to remove from config, but catch ValueError if not found
4. Always remove from database if project exists there

**Additional fix:**
- Project list Default column now shows in local mode (always) and in
  cloud mode only if default_project_mode is enabled
- This fixes integration tests that expect to see default marker

Fixes cloud-only project deletion bug.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
phernandez
2025-10-28 17:49:06 -05:00
parent b049c5cbc3
commit bc37ecf64c
2 changed files with 22 additions and 11 deletions
+5 -4
View File
@@ -89,8 +89,9 @@ def list_projects() -> None:
if config.cloud_mode_enabled:
table.add_column("Local Path", style="yellow", no_wrap=True, overflow="fold")
# Only show Default column if default_project_mode is enabled
if config.default_project_mode:
# Show Default column in local mode or if default_project_mode is enabled in cloud mode
show_default_column = not config.cloud_mode_enabled or config.default_project_mode
if show_default_column:
table.add_column("Default", style="magenta")
for project in result.projects:
@@ -108,8 +109,8 @@ def list_projects() -> None:
local_path = format_path(local_path)
row.append(local_path)
# Add default indicator if default_project_mode is enabled
if config.default_project_mode:
# Add default indicator if showing default column
if show_default_column:
row.append(is_default)
table.add_row(*row)
+17 -7
View File
@@ -234,16 +234,26 @@ class ProjectService:
if not self.repository: # pragma: no cover
raise ValueError("Repository is required for remove_project")
# Get project path before removing from config
# Get project from database first
project = await self.get_project(name)
project_path = project.path if project else None
if not project:
raise ValueError(f"Project '{name}' not found")
# First remove from config (this will validate the project exists and is not default)
self.config_manager.remove_project(name)
project_path = project.path
# Then remove from database using robust lookup
if project:
await self.repository.delete(project.id)
# Check if project is default (in cloud mode, check database; in local mode, check config)
if project.is_default or name == self.config_manager.config.default_project:
raise ValueError(f"Cannot remove the default project '{name}'")
# Remove from config if it exists there (may not exist in cloud mode)
try:
self.config_manager.remove_project(name)
except ValueError:
# Project not in config - that's OK in cloud mode, continue with database deletion
logger.debug(f"Project '{name}' not found in config, removing from database only")
# Remove from database
await self.repository.delete(project.id)
logger.info(f"Project '{name}' removed from configuration and database")