Skip to content

Conversation

@JoshuaRileyDev
Copy link
Contributor

@JoshuaRileyDev JoshuaRileyDev commented Dec 29, 2025

🎯 Queue System v2: Intelligent Task Flow Management

A complete overhaul of the task queue system with automatic promotion, intelligent capacity management, and seamless workflow automation.


📋 Overview

This PR implements a fully automated queue system that intelligently manages task execution based on configurable parallel task limits. Tasks automatically flow from Planning → Queue → In Progress without manual intervention, ensuring optimal resource utilization.


✨ Key Features

1. Automatic Queue Management

  • Auto-Queue on Capacity: When In Progress reaches the limit, new tasks automatically move to Queue instead of being blocked
  • Auto-Promotion (FIFO): Tasks in Queue automatically promote to In Progress when slots become available
  • Smart Batching: Bulk operations fill all available capacity in one action

2. Visual Capacity Indicators

  • In Progress Header: Shows current capacity (e.g., "2/3")
  • Warning Colors: Badge turns amber when at capacity
  • Real-time Updates: Counts update instantly as tasks move

3. Batch Queue Button

  • ListPlus Icon (≡+) in Planning column header
  • One-Click Queuing: Move all Planning tasks to Queue instantly
  • Auto-Fill: Automatically promotes tasks to fill available In Progress slots
  • Smart Ordering: Respects FIFO queue order

4. Multi-Trigger Auto-Promotion

Queue processing automatically triggers when:

  • ✅ Task dragged out of In Progress
  • ✅ Task stopped via Stop button
  • ✅ Bulk queue button clicked
  • ✅ Task completes (moves to Review/Done)

🔄 User Workflows

Workflow 1: Manual Start with Auto-Queue

Scenario: Limit is 3, try to start 4th task

Before (blocking):

User clicks Start on 4th task
→ ❌ Alert: "Cannot start, limit reached"
→ Task stuck in Planning

Now (auto-queue):

User clicks Start on 4th task
→ ✅ Task automatically moves to Queue
→ Will auto-promote when slot opens

Workflow 2: Batch Queue

Scenario: 5 tasks in Planning, limit is 3

User clicks ListPlus (≡+) icon
→ All 5 tasks move to Queue
→ Auto-promotion fills In Progress:
  - Task 1, 2, 3 → In Progress (3/3 FULL)
  - Task 4, 5 → Queue (waiting)

When Task 1 completes:
→ Task 4 auto-promotes to In Progress (3/3)
→ Task 5 remains in Queue

When Task 2 completes:
→ Task 5 auto-promotes to In Progress (3/3)
→ Queue empty

Workflow 3: Stop Button Auto-Promotion

Scenario: 3 tasks running (3/3), 1 in queue

User stops Task A
→ Task A moves to Planning
→ Auto-promotion triggered (500ms delay)
→ Queued task auto-promotes to In Progress (3/3)
→ No manual intervention needed

🏗️ Technical Implementation

Core Components

1. Queue Limit Enforcement

Location: KanbanBoard.tsx (drag-drop) + task-store.ts (start button)

// Check capacity using live store state (prevents race conditions)
const currentTasks = useTaskStore.getState().tasks;
const inProgressCount = currentTasks.filter(t => 
  t.status === 'in_progress' && !t.metadata?.archivedAt
).length;

// Auto-queue if full
if (inProgressCount >= maxParallelTasks) {
  newStatus = 'queue'; // Instead of blocking
}

2. Auto-Promotion Engine

Location: KanbanBoard.tsx + task-store.ts

const processQueue = async () => {
  while (true) {
    // Get fresh state each iteration
    const currentTasks = useTaskStore.getState().tasks;
    const inProgressCount = /* calculate */;
    const queuedTasks = /* filter */;

    // Stop if full or queue empty
    if (inProgressCount >= maxParallelTasks || queuedTasks.length === 0) {
      break;
    }

    // Promote oldest task (FIFO)
    const nextTask = queuedTasks.sort(by createdAt)[0];
    await persistTaskStatus(nextTask.id, 'in_progress');
  }
};

3. Multi-Trigger Integration

Drag & Drop:

// handleDragEnd in KanbanBoard.tsx
if (oldStatus === 'in_progress' && newStatus !== 'in_progress') {
  await processQueue();
}

Stop Button:

// stopTask in task-store.ts
export async function stopTask(taskId: string) {
  window.electronAPI.stopTask(taskId);
  
  if (task.status === 'in_progress') {
    setTimeout(() => processQueueForProject(...), 500);
  }
}

Bulk Queue:

// handleQueueAll in KanbanBoard.tsx
for (const task of backlogTasks) {
  await persistTaskStatus(task.id, 'queue');
}
await processQueue(); // Fill all available slots

🐛 Bug Fixes

1. Race Condition in Limit Enforcement

Problem: Rapid task starts bypassed limit (all tasks got through)
Fix: Read from useTaskStore.getState() instead of stale props/memoized values

2. Single Task Promotion

Problem: Bulk queue only promoted 1 task, leaving others waiting
Fix: Loop until capacity full or queue empty

3. No Auto-Promotion on Stop

Problem: Stopping tasks didn't trigger queue processing
Fix: Added queue processing to stopTask() function


🌐 Internationalization

English Translations:

{
  "queue": {
    "movedToQueue": "Task moved to Queue ({current}/{max} tasks running)",
    "autoPromoted": "Task automatically promoted from Queue to In Progress",
    "capacityAvailable": "{available} slot(s) available"
  },
  "tooltips": {
    "queueAll": "Move all tasks to Queue",
    "addTask": "Add new task"
  }
}

French Translations:

{
  "queue": {
    "movedToQueue": "Tâche déplacée vers la file d'attente ({current}/{max} tâches en cours)",
    "autoPromoted": "Tâche automatiquement promue de la file d'attente vers En cours",
    "capacityAvailable": "{available} emplacement(s) disponible(s)"
  },
  "tooltips": {
    "queueAll": "Déplacer toutes les tâches vers la file d'attente",
    "addTask": "Ajouter une nouvelle tâche"
  }
}

📊 Visual Changes

Planning Column Header

Before: [ Planning ] [ 5 ] [ + ]
                      count  add

After:  [ Planning ] [ 5 ] [ ≡+ ] [ + ]
                      count  queue add
                              all

In Progress Column Header

Before: [ In Progress ] [ 3 ]
                         count

After:  [ In Progress ] [ 3/3 ] ← Capacity indicator
                         current/max (amber when full)

🧪 Testing Scenarios

Test 1: Auto-Queue on Start

  1. Set maxParallelTasks to 3
  2. Start 3 tasks (all go to In Progress)
  3. Click Start on 4th task
  4. ✅ Verify: Task 4 moves to Queue (not blocked)

Test 2: Bulk Queue

  1. Create 5 tasks in Planning
  2. Set limit to 3
  3. Click ListPlus icon
  4. ✅ Verify: 3 tasks in In Progress, 2 in Queue

Test 3: Auto-Promotion

  1. 3 tasks in In Progress (3/3), 1 in Queue
  2. Stop one running task
  3. ✅ Verify: Queued task auto-promotes after 500ms

Test 4: Capacity Indicator

  1. Start tasks until limit reached
  2. ✅ Verify: In Progress shows "3/3" in amber
  3. Complete one task
  4. ✅ Verify: Shows "2/3" in normal color

📁 Files Changed

Core Logic

  • apps/frontend/src/renderer/components/KanbanBoard.tsx

    • Added handleQueueAll() for bulk queuing
    • Enhanced processQueue() to fill all capacity
    • Added capacity indicators
    • Added batch queue button
  • apps/frontend/src/renderer/stores/task-store.ts

    • Enhanced startTask() with queue enforcement
    • Enhanced stopTask() with auto-promotion
    • Added processQueueForProject() helper

Translations

  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json

🚀 Performance Considerations

  • Real-time State: Uses useTaskStore.getState() for instant access
  • Efficient Loops: Breaks immediately when capacity full
  • Async Processing: All queue operations are async for responsiveness
  • Debounced Updates: 500ms delay on stop to avoid race conditions

🔮 Future Enhancements (Not in this PR)

  • Priority levels (High/Medium/Low) for queue ordering
  • Manual queue reordering (drag within queue)
  • Queue analytics (average wait time, throughput)
  • Toast notifications instead of alerts
  • Configurable auto-promotion delay
  • Queue pause/resume functionality

✅ Checklist

  • Auto-queue when capacity reached
  • Auto-promotion (FIFO) on slot availability
  • Batch queue button with ListPlus icon
  • Visual capacity indicators
  • Multi-trigger auto-promotion
  • Race condition fixes
  • Full internationalization (EN/FR)
  • Enhanced console logging for debugging
  • Handles archived tasks correctly
  • Multi-project support (filters by projectId)

🎥 Demo Flow

1. Create 5 tasks in Planning
2. Click ListPlus (≡+) icon
   → All 5 tasks move to Queue
   → 3 auto-promote to In Progress (3/3 FULL)
   → 2 remain in Queue

3. Stop one running task
   → Task moves to Planning
   → 1 task auto-promotes from Queue (3/3)
   → 1 remains in Queue

4. Complete one task
   → Task moves to Done
   → Last task auto-promotes from Queue (3/3)
   → Queue empty

5. Try to start new task
   → Auto-queued (3/3 full)
   → Waits for slot

The queue system now works seamlessly across all entry points with zero manual intervention required! 🎉

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 [email protected]

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced task queue system with configurable parallel task limits to prevent resource overload.
    • Added Queue Settings modal to control maximum concurrent tasks (1–10 default).
    • Auto-promotes queued tasks to in-progress when capacity becomes available.
    • Added download progress tracking with speed and time estimates.
    • New Queue column in Kanban board displaying capacity status.
  • Chores

    • Added Contributor License Agreement.
    • Updated localization for queue-related features in English and French.

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

AndyMik90 and others added 30 commits December 26, 2025 12:01
Tasks in ai_review status were incorrectly showing "Task Appears Stuck"
in the detail modal. This happened because the isRunning check included
ai_review status, triggering stuck detection when no process was found.

However, ai_review means "all subtasks completed, awaiting QA" - no build
process is expected to be running. This aligns the detail modal logic with
TaskCard which correctly only checks for in_progress status.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…ge.json

Previously the beta-release workflow committed version changes to package.json
on the develop branch, which caused two issues:
1. Permission errors (github-actions[bot] denied push access)
2. Beta versions polluted develop, making merges to main unclean

Now the workflow creates only a git tag and injects the version at build time
using electron-builder's --config.extraMetadata.version flag. This keeps
package.json at the next stable version and avoids any commits to develop.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The Ollama detection was failing in packaged builds because the
Python script path resolution only checked development paths.
In packaged apps, __dirname points to the app bundle, and the
relative path "../../../backend" doesn't resolve correctly.

Added process.resourcesPath for packaged builds (checked first via
app.isPackaged) which correctly locates the backend scripts in
the Resources folder. Also added DEBUG-only logging to help
troubleshoot script location issues.

Closes AndyMik90#129

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace all legacy 'auto-claude/' source path detection with 'apps/backend'.
Services now validate paths using runners/spec_runner.py as the marker
instead of requirements.txt, ensuring only valid backend directories match.

- Remove legacy fallback paths from all getAutoBuildSourcePath() implementations
- Add startup validation in index.ts to skip invalid saved paths
- Update project-initializer to detect apps/backend for local dev projects
- Standardize path detection across all services

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Fixes from PR AndyMik90#300 reviews:

CRITICAL:
- path-resolver.ts: Update marker from requirements.txt to runners/spec_runner.py
  for consistent backend detection across all files

HIGH:
- useTaskDetail.ts: Restore stuck task detection for ai_review status
  (CHANGELOG documents this feature)
- TerminalGrid.tsx: Include legacy terminals without projectPath
  (prevents hiding terminals after upgrade)
- memory-handlers.ts: Add packaged app path in OLLAMA_PULL_MODEL handler
  (fixes production builds)

MEDIUM:
- OAuthStep.tsx: Stricter profile slug sanitization
  (only allow alphanumeric and dashes)
- project-store.ts: Fix regex to not truncate at # in code blocks
  (uses \n#{1,6}\s to match valid markdown headings only)
- memory-service.ts: Add backend structure validation with spec_runner.py marker
- subprocess-spawn.test.ts: Update test to use new marker pattern

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add validation to prevent empty config directory path when profile name
contains only special characters (e.g., "!!!"). Shows user-friendly error
message requiring at least one letter or number.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…endencies

Updated checkDepsInstalled() to verify BOTH claude_agent_sdk AND dotenv
are importable. Previously, only claude_agent_sdk was checked, which could
cause the app to skip reinstalling dependencies if some packages were
missing (like python-dotenv).

Fixes: AndyMik90#359

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…#379)

The close button in DialogContent was missing z-index, causing it to be
covered by content elements with relative positioning or overflow
properties. This prevented clicks from reaching the button in modals
like TaskCreationWizard.

Added z-10 to match the pattern used in FullScreenDialogContent.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…ctly

The "+" button in the project tab bar was bypassing the AddProjectModal
and directly opening a file explorer. Now it correctly shows the modal
which gives users the choice between "Open Existing Project" and
"Create New Project" with the full creation form flow.
Agents now read the project's CLAUDE.md file and include its instructions
in the system prompt. This allows per-project customization of agent behavior.

- Add useClaudeMd toggle to ProjectSettings (default: ON)
- Pass USE_CLAUDE_MD env var from frontend to backend
- Backend loads CLAUDE.md content when setting is enabled
- Add i18n translations for EN and FR
Replace standalone `clippy` (which isn't invoked directly) with proper
cargo subcommand binaries and add commonly-used Rust development tools
including cargo-watch, cargo-nextest, cross-compilation, and WASM tooling.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…nstalled()

Updated the checkDepsInstalled() method to verify all necessary dependencies for the backend, including claude_agent_sdk, dotenv, google.generativeai, and optional Graphiti dependencies for Python 3.12+. This change ensures users have all required packages installed, preventing broken functionality. Increased timeout for dependency checks to improve reliability.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Fixed the X close button in the new task modal to properly close the dialog when clicked.

Fixes AndyMik90#379
xterm.js was capturing all keyboard events when a terminal had focus,
preventing Cmd/Ctrl+1-9 and Cmd/Ctrl+Tab shortcuts from reaching
the window-level handlers in ProjectTabBar.

Uses attachCustomKeyEventHandler to let these specific key combinations
bubble up to the global handlers for project tab switching.
Eliminates runtime pip install failures that were causing user adoption issues.
Python dependencies are now installed during build and bundled with the app.

Changes:
- Extended download-python.cjs to install packages and strip unnecessary files
- Added site-packages to electron-builder extraResources
- Updated PythonEnvManager to detect and use bundled packages via PYTHONPATH
- Updated all spawn calls in agent files to include pythonEnv
- Added python-runtime/** to eslint ignores

The app now starts instantly without requiring pip install on first launch.
Dev mode continues to work with venv-based setup as before.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Terminal names now dynamically adjust their max-width based on how many
terminals are displayed. With fewer terminals, titles can be wider (up
to 256px with 1-2 terminals), and with more terminals they become
narrower (down to 96px with 10-12 terminals) to ensure all header
elements fit properly.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The "Open Terminal" and "Open Project in Terminal" buttons in
WorkspaceStatus and StagedSuccessMessage were creating PTY processes
in the backend but not updating the Zustand store, causing terminals
to not appear in the TerminalGrid UI.

Instead of fixing the sync issue, removed the buttons entirely since
users should use their preferred IDE or terminal application.

Closes AndyMik90#99

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add qwen3-embedding:4b (recommended/balanced), :8b (highest quality), and
:0.6b (fastest) as new local embedding model options in both backend and
frontend. Models display with visible badges indicating their purpose.

Key changes:
- Use Ollama HTTP API for downloads with proper NDJSON progress streaming
- Create global download store (Zustand) to track downloads across app
- Add floating GlobalDownloadIndicator that persists when navigating away
- Fix model installation detection to match exact version tags (not base name)
- Add indeterminate progress bar animation while waiting for events

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…ture

When the project moved from /auto-claude to /apps/backend structure,
some developers' settings files retained the old path causing startup
warnings. The app now auto-detects this pattern and migrates the
setting on startup, saving the corrected path back to settings.json.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…ew UI

Implements phase-aware tool and MCP server configuration to reduce context
window bloat and improve agent startup performance. Each agent phase now
gets only the MCP servers and tools it needs.

Key changes:
- Add AGENT_CONFIGS registry in models.py as single source of truth
- Add simple_client.py factory for utility operations (commit, merge, etc.)
- Migrate 11 direct SDK clients to use factory pattern
- Add get_required_mcp_servers() for dynamic server selection
- Add Flutter/Dart support to command registry
- Add MCP Overview sidebar tab showing servers/tools per agent phase
- Fix followup_reviewer to use user's thinking level settings
- Consolidate THINKING_BUDGET_MAP to phase_config.py (remove duplicate)

MCP servers are now loaded conditionally:
- Spec phases: minimal (no MCP for most)
- Build phases: context7 + graphiti + auto-claude
- QA phases: + electron OR puppeteer (based on project type)
- Utility phases: minimal or none

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Conflicts resolved:
- client.py: Merged CLAUDE.md support (HEAD) with output_format support (develop)
- analyzer.py: Combined Dart/Flutter hash files (HEAD) with Java/Kotlin/Swift (develop)
- followup_reviewer.py: Use SDK query() with structured outputs + configurable thinking budget
- agent-process.ts: Merged imports and combined env setup approaches
- index.ts: Kept autoBuildPath migration logic from HEAD
- worktree-handlers.ts: Combined imports from both branches
- App.tsx: Kept handleOpenInbuiltTerminal (develop) with showAddProjectModal (HEAD)
- OllamaModelSelector.tsx: Kept global download store approach (HEAD)
- useTerminalHandler.ts: Deleted (HEAD decision to remove broken terminal buttons)
- WorkspaceStatus.tsx: Used HEAD version (removed terminal dropdown due to missing task prop bug)
- useTerminalEvents.ts: Combined terminalBufferManager (develop) with ref pattern (HEAD)
- terminal-store.ts: Used develop's projectPath validation
- test_agent_configs.py: Updated test to reflect qa_reviewer now has write tools

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Expand SupportedIDE type from 7 to 62+ options covering VS Code ecosystem,
AI-powered editors (Cursor, Windsurf, Zed, PearAI, Kiro), JetBrains suite,
classic editors (Vim, Neovim, Emacs), platform-specific IDEs, and cloud IDEs.

Expand SupportedTerminal type from 7 to 37+ options including GPU-accelerated
terminals (Alacritty, Kitty, WezTerm), macOS/Windows/Linux native terminals,
and modern options (Warp, Ghostty, Rio).

Add smart platform-native detection:
- macOS: Uses Spotlight (mdfind) for fast app discovery
- Windows: Queries registry via PowerShell
- Linux: Parses .desktop files from standard locations

UI improvements:
- Add DevToolsStep to onboarding wizard for initial configuration
- Add DevToolsSettings component for settings page
- Alphabetically sort IDE/terminal dropdowns for easy scanning
- Show detection status (checkmark) for installed tools

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The PR review was only detecting 1 bot comment when there were actually 8
(CodeRabbit + GitHub Advanced Security). Expanded AI_BOT_PATTERNS from 22
to 62 patterns covering:

- AI Code Review: Greptile, Sourcery, Qodo variants
- AI Assistants: Copilot SWE Agent, Sweep AI, Bito, Codeium, Devin
- GitHub Native: Dependabot, Merge Queue, Advanced Security
- Code Quality: DeepSource, CodeClimate, CodeFactor, Codacy
- Security: Snyk, GitGuardian, Semgrep
- Coverage: Codecov, Coveralls
- Automation: Renovate, Mergify, Imgbot, Allstar, Percy

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Fixes multiple security vulnerabilities and code quality issues identified
in PR AndyMik90#388 code review:

Security fixes:
- Fix command injection in Terminal.app/iTerm2 AppleScript by escaping paths
- Fix command injection in Windows cmd.exe terminal launch using spawn()
- Fix command injection in Linux xterm fallback with proper escaping
- Fix command injection in custom IDE/terminal paths using execFileAsync()
- Add path traversal validation after environment variable expansion
- Fix file system race condition in settings migration by re-reading file
- Use SystemRoot env var for Windows tar path instead of hardcoded C:\Windows

Code quality fixes:
- Remove unused electron_mcp_enabled variable in client.py
- Remove unused json and timezone imports in test_ollama_embedding_memory.py
- Remove unused useTranslation import and t variable in AgentTools.tsx
- Fix Windows process kill to use platform-specific termination
- Add 10-second timeout to macOS Spotlight app detection
- Dynamically detect Python version in venv instead of hardcoding 3.12
- Fix README download links (version was repeated 3 times)

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…king

Addresses remaining medium-priority issues from PR AndyMik90#388 review:

1. Background file writes (worktree-handlers.ts):
   - Add retry logic with exponential backoff (3 attempts)
   - Add write verification by reading back the file
   - Log warnings if main plan write fails after retries

2. Venv process tracking (python-env-manager.ts):
   - Track spawned processes in activeProcesses Set
   - Add 2-minute timeout for hung venv creation
   - Add cleanup() method to kill orphaned processes
   - Register cleanup on app 'will-quit' event

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Remove unused escapeWindowsCmdPath function (replaced by spawn with args)
- Fix race condition in settings migration by removing existsSync check
  and catching read errors atomically

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The app.on('will-quit') handler fails in test environments where the
Electron app module is mocked without the 'on' method. Add a guard
to check if app.on is a function before calling it.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Fixes 4 CodeQL alerts from PR AndyMik90#388:

1. Clear-text logging (HIGH): Change "password hashing" to "credential hashing"
   in test discovery dict to avoid false positive

2. File system race condition (HIGH): Simplify settings migration in index.ts
   to use existing settings object instead of re-reading file (TOCTOU fix)

3. File system race condition (HIGH): Use EAFP pattern in worktree-handlers.ts
   - Remove existsSync check before read/write
   - Handle ENOENT in catch block instead

4. Unused import (NOTE): Use importlib.util.find_spec() instead of try/import
   to check claude_agent_sdk availability in batch_validator.py

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The `Run tests` step had `if: matrix.python-version != '3.12'` which
skipped regular test execution for Python 3.12. Now tests run on both
3.12 and 3.13, with coverage reporting still only on 3.12.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
AlexMadera and others added 11 commits December 29, 2025 09:52
…ection

This fixes several cross-platform compatibility issues that broke the app
on Windows:

**subprocess-runner.ts:**
- getPythonPath() now returns Scripts/python.exe on Windows, bin/python on Unix
- validateGitHubModule() now uses `where gh` on Windows instead of `which gh`
- Added platform-specific install instructions (winget/brew/URL)
- venvPath check now uses getPythonPath() instead of hardcoded Unix path

**python-env-manager.ts:**
- Fixed Windows site-packages path (Lib/site-packages, not Lib/python3.x/site-packages)
- Windows venv structure doesn't have python version subfolder

**generator.ts:**
- Fixed PATH split to use path.delimiter instead of hardcoded ':'

These issues were causing GitHub automation, Python environment detection,
and dependency loading to fail on Windows systems.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The cache invalidation tests were failing intermittently on CI with
Python 3.13 because some filesystems have 1-second mtime resolution.
The previous 0.1s sleep was not sufficient to guarantee a different
mtime between file writes.

Changes:
- Increase sleep from 0.1s to 1.0s in both cache invalidation tests
- Compute hash before first call to ensure consistency
- Add clearer comments explaining the timing requirements

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Migrates from per-commit DCO sign-off to a one-time Contributor License
Agreement (CLA) using CLA Assistant GitHub Action.

Why:
- DCO required sign-off on every commit, causing 99% of PRs to fail checks
- CLA is one-time: contributors sign once and it applies to all future PRs
- CLA grants licensing flexibility for potential future enterprise options
  while keeping the project open source under AGPL-3.0
- Contributors retain full copyright ownership of their contributions

Changes:
- Add CLA.md (Apache ICLA-style agreement)
- Add .github/workflows/cla.yml (CLA enforcement via GitHub Action)
- Update pr-status-gate.yml to require CLA check instead of DCO
- Update CONTRIBUTING.md with CLA signing instructions
- Remove .github/workflows/quality-dco.yml

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…rees

The execution handlers were only reading `project.settings.mainBranch` for
determining which branch to create worktrees from, ignoring the task-level
override stored in `task.metadata.baseBranch`.

This fix ensures the branch selection priority is:
1. Task-level override (task.metadata.baseBranch) - if user selected a
   specific branch for this task in the Git Options
2. Project default (project.settings.mainBranch) - fallback to project
   settings if no task-level override

Fixed in three code paths:
- TASK_START handler (line 121)
- TASK_UPDATE_STATUS auto-start logic (line 488)
- TASK_RECOVER_STUCK auto-restart logic (line 765)

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add a new "Queue" board between Planning and In Progress that allows
users to stage tasks before execution. Includes a settings modal to
configure the maximum number of parallel tasks (default: 3).

Changes:
- Add 'queue' status to task types and constants
- Create Queue column in Kanban board between Planning and In Progress
- Add QueueSettingsModal component for configuring max parallel tasks
- Add maxParallelTasks to ProjectSettings (project-level setting)
- Implement full i18n support (English and French)
- Add queue column styling with cyan color theme
- Add settings icon to queue column header

The queue system provides a manual staging area for tasks, allowing
better workflow control and visibility into task execution order.

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Major improvements to queue system with automatic task management:

**Core Features:**
- Auto-queue tasks when In Progress limit reached (no more blocking)
- FIFO automatic promotion when slots become available
- Visual capacity indicators (e.g., "2/3" in In Progress header)
- Enforced limits across both drag-drop and start button

**Changes:**
1. Queue Limit Enforcement (KanbanBoard + task-store):
   - Tasks automatically move to Queue when limit reached
   - Works for both drag-drop and start button clicks
   - Uses live store state to prevent race conditions

2. Automatic Queue Processing:
   - processQueue() auto-promotes oldest task when slot opens
   - Triggered when any task leaves In Progress
   - FIFO ordering based on createdAt timestamp

3. Visual Improvements:
   - In Progress header shows capacity: "2/3"
   - Warning color when at capacity
   - Enhanced empty states for Queue column

4. UX Improvements:
   - No blocking alerts - tasks smoothly queue
   - Automatic promotion feels natural
   - Clear visual feedback on capacity

5. Internationalization:
   - Updated EN/FR translations for queue messages
   - New keys: movedToQueue, autoPromoted

**Technical Details:**
- Fixed race condition by reading from useTaskStore.getState()
- Proper handling of archived tasks in counts
- Exception: tasks from Queue always allowed to In Progress

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add an ArrowRight icon button next to the Add button in Planning column
that moves all tasks from Planning to Queue in batch, then auto-promotes
tasks to In Progress based on capacity.

**Features:**
- ArrowRight icon next to Plus icon in Planning column header
- Only shows when there are tasks in Planning
- Moves all backlog tasks to Queue with one click
- Automatically processes queue after batch move
- Tasks auto-promote to In Progress based on maxParallelTasks limit

**User Flow:**
1. User clicks ArrowRight icon in Planning
2. All Planning tasks → Queue
3. Queue auto-processes (FIFO)
4. Up to N tasks move to In Progress (based on limit)
5. Remaining tasks stay in Queue until slots open

**Implementation:**
- handleQueueAll() - batch moves all backlog tasks to queue
- Calls processQueue() after batch to start auto-promotion
- Cyan hover color matches Queue column theme
- Full i18n support (EN/FR)

**Translations:**
- en: "Move all tasks to Queue"
- fr: "Déplacer toutes les tâches vers la file d'attente"

This completes the queue system workflow:
Planning → [Batch Queue] → Queue → [Auto-Promote] → In Progress

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Change the batch queue button icon and position:
- Icon: ArrowRight → ListPlus (3 lines with plus symbol)
- Position: Right of Add button → Left of Add button

Planning column header now shows:
[Planning] [count] [ListPlus] [Plus]
                    Queue All  Add Task

The ListPlus icon better represents "add all to queue" visually.

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Fix processQueue() to promote multiple tasks instead of just one.
Previously only promoted the first task, leaving remaining slots empty.

**Problem:**
- 4 tasks bulk queued with limit of 3
- Only 1 task promoted to In Progress
- 3 tasks left in Queue (should be 1)

**Solution:**
- Change processQueue() to loop until capacity is full
- Promotes tasks one-by-one while:
  1. inProgressCount < maxParallelTasks
  2. queuedTasks.length > 0
- Reads fresh state from store on each iteration

**Now works correctly:**
- 4 tasks → Queue
- Loop iteration 1: Task 1 → In Progress (1/3)
- Loop iteration 2: Task 2 → In Progress (2/3)
- Loop iteration 3: Task 3 → In Progress (3/3 FULL)
- Loop stops: Task 4 stays in Queue ✓

Enhanced console logging shows progress: "(1/3)", "(2/3)", "(3/3)"

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add automatic queue processing when stopping a task in In Progress.
Previously only worked for drag-drop movements.

**Changes:**

1. Enhanced stopTask() function:
   - Now async to support queue processing
   - Checks if stopped task was in_progress
   - Gets maxParallelTasks from project settings
   - Calls processQueueForProject() after 500ms delay

2. New processQueueForProject() function:
   - Standalone queue processor for task-store.ts
   - Filters tasks by projectId (multi-project support)
   - Same FIFO logic as KanbanBoard's processQueue
   - Loops until capacity full or queue empty

**User Flow:**

Before:
- In Progress: [Task A, Task B, Task C] (3/3)
- Queue: [Task D]
- Stop Task A → backlog
- In Progress: [Task B, Task C] (2/3)
- Queue: [Task D] ← Still there ❌

After:
- In Progress: [Task A, Task B, Task C] (3/3)
- Queue: [Task D]
- Stop Task A → backlog
- Auto-promote triggered
- In Progress: [Task B, Task C, Task D] (3/3) ✅
- Queue: [] ← Empty

**Technical Details:**
- 500ms delay ensures backend status update completes first
- Filters by projectId for multi-project correctness
- Excludes archived tasks from counts

Now auto-promotion works for:
✅ Drag task out of In Progress
✅ Stop button (NEW)
✅ Bulk queue button
✅ Manual drag from Queue

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

This PR introduces a queue-based task management system with parallelism limits on the Kanban board. It adds a new 'queue' task status between backlog and in_progress, implements auto-promotion logic when capacity opens, provides a modal for configuring maximum parallel tasks, updates task types and constants, and adds related internationalization strings. A CLA agreement file and download progress store are also added.

Changes

Cohort / File(s) Change Summary
Contributor License Agreement
CLA.md
New file containing Auto Claude Individual Contributor License Agreement with copyright/patent grant terms, future licensing flexibility, representations, and signing instructions. Based on Apache Foundation v2.0 template.
Queue-Enabled Kanban Board
apps/frontend/src/renderer/components/KanbanBoard.tsx
Major refactor: adds queue-based task flow with project-level maxParallelTasks capacity enforcement. Introduces processQueue routine for FIFO auto-promotion, reworks drag-and-drop to route overflowing tasks to queue, integrates QueueSettingsModal, adds capacity display in column headers, and uses useTaskStore for current state during operations.
Queue Settings Modal
apps/frontend/src/renderer/components/QueueSettingsModal.tsx
New component: modal dialog for configuring maximum parallel tasks (1–10 range) with input validation, error handling, save/cancel actions, and descriptive help text.
Task & Project Type Extensions
apps/frontend/src/shared/types/task.ts, apps/frontend/src/shared/types/project.ts
TaskStatus type now includes 'queue' status; ProjectSettings interface adds optional maxParallelTasks?: number field for per-project capacity configuration.
Task Status Constants & Styling
apps/frontend/src/shared/constants/task.ts, apps/frontend/src/renderer/styles/globals.css
TASK_STATUS_COLUMNS, TASK_STATUS_LABELS, and TASK_STATUS_COLORS now include 'queue' entries. New CSS classes: .animate-indeterminate keyframe animation and .column-queue Kanban column modifier with cyan info color border.
Task State Management
apps/frontend/src/renderer/stores/task-store.ts
startTask now checks project's maxParallelTasks and routes to queue if at capacity; stopTask converted to async, triggers queue processor to auto-promote pending tasks. New internal processQueueForProject routine implements FIFO promotion by createdAt.
Download Progress Store
apps/frontend/src/renderer/stores/download-store.ts
New zustand-based store (DownloadState) tracks per-model download progress with status transitions, speed/time-remaining computation, and actions: startDownload, updateProgress, completeDownload, failDownload, clearDownload. Exports initDownloadProgressListener to subscribe to IPC events.
Internationalization
apps/frontend/src/shared/i18n/locales/en/tasks.json, apps/frontend/src/shared/i18n/locales/fr/tasks.json, apps/frontend/src/shared/i18n/locales/en/navigation.json, apps/frontend/src/shared/i18n/locales/fr/navigation.json
English & French: add queue-related tooltip keys (addTask, queueAll), kanban empty states (emptyQueue, emptyQueueHint), and new top-level queue object with limitReached, movedToQueue, autoPromoted, capacityAvailable, and nested settings (title, maxParallel, description, save). Navigation locales reorder gitlabMRs entry.
Backend Summary Update
apps/backend/runners/github/services/orchestrator_reviewer.py
Minor text change: PR summary footer updated from "Generated by Auto Claude Orchestrating PR Reviewer (Opus 4.5)" to "Generated by Auto Claude Orchestrating PR Reviewer".

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant KanbanBoard
    participant ProjectStore
    participant TaskStore
    participant QueueProcessor

    User->>KanbanBoard: Drag task to In Progress
    KanbanBoard->>ProjectStore: Get maxParallelTasks
    ProjectStore-->>KanbanBoard: maxParallelTasks (e.g., 3)
    KanbanBoard->>KanbanBoard: Check in_progress count vs capacity
    
    alt At Capacity
        KanbanBoard->>TaskStore: persistTaskStatus(task, 'queue')
        TaskStore-->>KanbanBoard: ✓ Task moved to queue
        KanbanBoard->>User: Show "Queue is full" feedback
    else Capacity Available
        KanbanBoard->>TaskStore: persistTaskStatus(task, 'in_progress')
        TaskStore-->>KanbanBoard: ✓ Task started
    end

    User->>KanbanBoard: Stop/complete task in In Progress
    KanbanBoard->>TaskStore: persistTaskStatus(task, 'done')
    TaskStore->>QueueProcessor: processQueueForProject(projectId, maxParallelTasks)
    
    loop While capacity available & queued tasks exist
        QueueProcessor->>TaskStore: Get oldest queued task by createdAt
        QueueProcessor->>TaskStore: persistTaskStatus(queuedTask, 'in_progress')
        TaskStore-->>QueueProcessor: ✓ Auto-promoted
        QueueProcessor->>KanbanBoard: Update UI
    end
    
    KanbanBoard->>User: Show auto-promoted task feedback
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #141: Introduces onDownloadProgress IPC listener and event shape that the new download-store.ts and initDownloadProgressListener directly depend upon.
  • PR #248: Establishes the i18n system infrastructure (i18next, namespace structure, base locale files) upon which the queue-related translation keys in this PR are built.

Suggested labels

area/frontend, 🔄 Checking, size/XL

Suggested reviewers

  • AndyMik90
  • AlexMadera

Poem

🐰 Hops with glee
A queue now orders the task flow,
Capacity caps prevent overflow—
Each rabbit knows: wait in line,
And when a slot opens, you'll shine! 🎪

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changeset: introducing a queue system with auto-promotion and smart task management, which is the core feature across multiple files (KanbanBoard, task-store, new QueueSettingsModal, etc.).
Docstring Coverage ✅ Passed Docstring coverage is 83.15% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

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

currentMaxParallel = 3,
onSave
}: QueueSettingsModalProps) {
const { t } = useTranslation('tasks');

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable t.
@AlexMadera AlexMadera self-assigned this Dec 29, 2025
Copy link
Contributor

@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: 46

Caution

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

⚠️ Outside diff range comments (4)
apps/frontend/src/renderer/styles/globals.css (1)

143-145: Use a CSS variable for theme consistency.

The hardcoded cyan color #06B6D4 won't adapt to different themes. Most other column status classes use CSS variables (e.g., var(--info), var(--success), var(--warning)). Consider using an existing semantic variable or defining a queue-specific variable in the @theme block.

🔎 Suggested refactor using existing variable

If cyan semantically represents "queued" status, consider using var(--info) or another existing variable:

 .column-queue {
-  border-top-color: #06B6D4; /* cyan-500 */
+  border-top-color: var(--info);
 }

Alternatively, define a new semantic variable in the @theme block (lines 8-98) for better clarity:

 @theme {
   /* ... existing variables ... */
   
+  --color-queued: #06B6D4;
+
   /* Animations */

Then use it:

 .column-queue {
-  border-top-color: #06B6D4; /* cyan-500 */
+  border-top-color: var(--queued);
 }
apps/frontend/scripts/download-python.cjs (1)

629-765: Good implementation with one robustness concern.

The bundling workflow with marker files is well-designed and provides good error recovery. However, there's a fragile path assumption:

Line 659: The requirementsPath construction assumes the script is in frontend/scripts/ and backend/ is a sibling of frontend/. This breaks if the directory structure changes.

🔎 More robust path resolution
+ // Find project root by looking for package.json or a known marker
+ function findProjectRoot(startDir) {
+   let currentDir = startDir;
+   while (currentDir !== path.dirname(currentDir)) { // Until we reach root
+     if (fs.existsSync(path.join(currentDir, 'pnpm-workspace.yaml')) ||
+         fs.existsSync(path.join(currentDir, 'package.json'))) {
+       return currentDir;
+     }
+     currentDir = path.dirname(currentDir);
+   }
+   throw new Error('Could not find project root');
+ }
+
  async function downloadPython(targetPlatform, targetArch, options = {}) {
    const platform = targetPlatform || os.platform();
    const arch = targetArch || os.arch();
    const { skipPackages = false, requirementsPath: customRequirementsPath } = options;

    const info = getDownloadInfo(platform, arch);
    console.log(`[download-python] Setting up Python ${PYTHON_VERSION} for ${info.outputDir}`);

    const frontendDir = path.join(__dirname, '..');
    const runtimeDir = path.join(frontendDir, OUTPUT_DIR);
    const platformDir = path.join(runtimeDir, info.outputDir);

    // Paths for Python binary and site-packages
    const pythonBin = info.nodePlatform === 'win32'
      ? path.join(platformDir, 'python', 'python.exe')
      : path.join(platformDir, 'python', 'bin', 'python3');

    const sitePackagesDir = path.join(platformDir, 'site-packages');

-   // Path to requirements.txt (in backend directory)
-   const requirementsPath = customRequirementsPath || path.join(frontendDir, '..', 'backend', 'requirements.txt');
+   // Path to requirements.txt (in backend directory, relative to project root)
+   const requirementsPath = customRequirementsPath || (() => {
+     try {
+       const projectRoot = findProjectRoot(__dirname);
+       return path.join(projectRoot, 'apps', 'backend', 'requirements.txt');
+     } catch {
+       // Fallback to old behavior
+       return path.join(frontendDir, '..', 'backend', 'requirements.txt');
+     }
+   })();

    // ... rest of function
  }

Otherwise, the implementation is solid:

  • ✅ Marker file approach prevents redundant installations
  • ✅ Clean reinstall when verification fails
  • ✅ Graceful handling of missing requirements.txt
  • ✅ Comprehensive error recovery
apps/backend/runners/github/services/orchestrator_reviewer.py (1)

1156-1156: Inconsistent hardcoded model reference in footer.

The summary footer still references "Opus 4.5" but the model is now dynamically configured. This creates a mismatch when users select a different model.

🔎 Proposed fix
-        lines.append("_Generated by Auto Claude Orchestrating PR Reviewer (Opus 4.5)_")
+        lines.append("_Generated by Auto Claude Orchestrating PR Reviewer_")

Alternatively, if you want to include the model name, you'd need to pass it to _generate_summary and interpolate it.

apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts (1)

1566-1573: Replace execSync with execFileSync to prevent shell injection.

Line 1566 uses execSync(\git merge-base --is-ancestor ${specBranch} HEAD`, ...)which interpolatestask.specIdinto a shell command string. IfspecIdcontains spaces or special characters (e.g.,foo; rm -rf /), arbitrary commands will execute. Use execFileSync` with an argument array instead—the correct pattern is already used 10 lines earlier in the same function (line 1556) and throughout the codebase.

-                      execSync(
-                        `git merge-base --is-ancestor ${specBranch} HEAD`,
-                        { cwd: project.path, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
-                      );
+                      execFileSync(
+                        getToolPath('git'),
+                        ['merge-base', '--is-ancestor', specBranch, 'HEAD'],
+                        { cwd: project.path, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
+                      );
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 321c971 and 57ecb55.

📒 Files selected for processing (99)
  • .github/workflows/ci.yml
  • .github/workflows/cla.yml
  • .github/workflows/pr-status-gate.yml
  • .github/workflows/quality-dco.yml
  • .github/workflows/release.yml
  • CLA.md
  • CONTRIBUTING.md
  • LICENSE
  • README.md
  • apps/backend/agents/tools_pkg/__init__.py
  • apps/backend/agents/tools_pkg/models.py
  • apps/backend/agents/tools_pkg/permissions.py
  • apps/backend/analysis/insight_extractor.py
  • apps/backend/commit_message.py
  • apps/backend/core/client.py
  • apps/backend/core/simple_client.py
  • apps/backend/core/workspace.py
  • apps/backend/core/workspace/setup.py
  • apps/backend/integrations/graphiti/test_ollama_embedding_memory.py
  • apps/backend/merge/ai_resolver/claude_client.py
  • apps/backend/ollama_model_detector.py
  • apps/backend/project/analyzer.py
  • apps/backend/project/command_registry/frameworks.py
  • apps/backend/project/command_registry/languages.py
  • apps/backend/project/framework_detector.py
  • apps/backend/project/stack_detector.py
  • apps/backend/runners/github/batch_issues.py
  • apps/backend/runners/github/batch_validator.py
  • apps/backend/runners/github/context_gatherer.py
  • apps/backend/runners/github/gh_client.py
  • apps/backend/runners/github/models.py
  • apps/backend/runners/github/services/followup_reviewer.py
  • apps/backend/runners/github/services/orchestrator_reviewer.py
  • apps/backend/spec/compaction.py
  • apps/frontend/eslint.config.mjs
  • apps/frontend/package.json
  • apps/frontend/scripts/download-python.cjs
  • apps/frontend/src/main/agent/agent-manager.ts
  • apps/frontend/src/main/agent/agent-process.ts
  • apps/frontend/src/main/agent/agent-queue.ts
  • apps/frontend/src/main/changelog/generator.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/main/ipc-handlers/github/utils/subprocess-runner.ts
  • apps/frontend/src/main/ipc-handlers/project-handlers.ts
  • apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts
  • apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
  • apps/frontend/src/main/python-env-manager.ts
  • apps/frontend/src/preload/api/task-api.ts
  • apps/frontend/src/renderer/App.tsx
  • apps/frontend/src/renderer/components/AgentTools.tsx
  • apps/frontend/src/renderer/components/GlobalDownloadIndicator.tsx
  • apps/frontend/src/renderer/components/Insights.tsx
  • apps/frontend/src/renderer/components/KanbanBoard.tsx
  • apps/frontend/src/renderer/components/QueueSettingsModal.tsx
  • apps/frontend/src/renderer/components/Sidebar.tsx
  • apps/frontend/src/renderer/components/Terminal.tsx
  • apps/frontend/src/renderer/components/TerminalGrid.tsx
  • apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts
  • apps/frontend/src/renderer/components/onboarding/DevToolsStep.tsx
  • apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx
  • apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx
  • apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
  • apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx
  • apps/frontend/src/renderer/components/settings/AppSettings.tsx
  • apps/frontend/src/renderer/components/settings/DevToolsSettings.tsx
  • apps/frontend/src/renderer/components/task-detail/TaskReview.tsx
  • apps/frontend/src/renderer/components/task-detail/hooks/useTerminalHandler.ts
  • apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx
  • apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx
  • apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx
  • apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx
  • apps/frontend/src/renderer/components/terminal/types.ts
  • apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts
  • apps/frontend/src/renderer/components/terminal/useXterm.ts
  • apps/frontend/src/renderer/components/ui/dialog.tsx
  • apps/frontend/src/renderer/lib/mocks/workspace-mock.ts
  • apps/frontend/src/renderer/stores/download-store.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/renderer/styles/globals.css
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/shared/constants/task.ts
  • apps/frontend/src/shared/i18n/locales/en/common.json
  • apps/frontend/src/shared/i18n/locales/en/navigation.json
  • apps/frontend/src/shared/i18n/locales/en/onboarding.json
  • apps/frontend/src/shared/i18n/locales/en/settings.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/common.json
  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • apps/frontend/src/shared/i18n/locales/fr/onboarding.json
  • apps/frontend/src/shared/i18n/locales/fr/settings.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/shared/types/project.ts
  • apps/frontend/src/shared/types/settings.ts
  • apps/frontend/src/shared/types/task.ts
  • tests/test_agent_architecture.py
  • tests/test_agent_configs.py
  • tests/test_security_cache.py
💤 Files with no reviewable changes (4)
  • .github/workflows/ci.yml
  • apps/frontend/src/renderer/components/task-detail/hooks/useTerminalHandler.ts
  • .github/workflows/quality-dco.yml
  • apps/frontend/src/renderer/components/task-detail/TaskReview.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/shared/types/project.ts
  • apps/frontend/src/renderer/components/ui/dialog.tsx
  • apps/frontend/src/main/changelog/generator.ts
  • apps/frontend/src/renderer/components/terminal/useXterm.ts
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/renderer/components/onboarding/DevToolsStep.tsx
  • apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx
  • apps/frontend/src/renderer/components/AgentTools.tsx
  • apps/frontend/src/renderer/components/Insights.tsx
  • apps/frontend/src/renderer/components/GlobalDownloadIndicator.tsx
  • apps/frontend/src/renderer/components/QueueSettingsModal.tsx
  • apps/frontend/src/renderer/lib/mocks/workspace-mock.ts
  • apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/shared/constants/task.ts
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/renderer/stores/download-store.ts
  • apps/frontend/src/shared/types/settings.ts
  • apps/frontend/src/renderer/components/TerminalGrid.tsx
  • apps/frontend/src/main/agent/agent-process.ts
  • apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx
  • apps/frontend/src/main/ipc-handlers/github/utils/subprocess-runner.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/main/ipc-handlers/project-handlers.ts
  • apps/frontend/src/renderer/components/Sidebar.tsx
  • apps/frontend/src/renderer/components/terminal/types.ts
  • apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts
  • apps/frontend/src/renderer/App.tsx
  • apps/frontend/src/shared/types/task.ts
  • apps/frontend/src/renderer/components/Terminal.tsx
  • apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
  • apps/frontend/src/main/python-env-manager.ts
  • apps/frontend/src/renderer/components/KanbanBoard.tsx
  • apps/frontend/src/renderer/components/settings/DevToolsSettings.tsx
  • apps/frontend/src/main/agent/agent-manager.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx
  • apps/frontend/src/main/agent/agent-queue.ts
  • apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx
  • apps/frontend/src/renderer/components/settings/AppSettings.tsx
  • apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx
  • apps/frontend/src/preload/api/task-api.ts
  • apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts
  • apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx
  • apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts
  • apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/shared/types/project.ts
  • apps/frontend/src/renderer/components/ui/dialog.tsx
  • apps/frontend/src/main/changelog/generator.ts
  • apps/frontend/src/renderer/components/terminal/useXterm.ts
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/renderer/components/onboarding/DevToolsStep.tsx
  • apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx
  • apps/frontend/src/renderer/components/AgentTools.tsx
  • apps/frontend/src/renderer/components/Insights.tsx
  • apps/frontend/src/renderer/components/GlobalDownloadIndicator.tsx
  • apps/frontend/src/renderer/components/QueueSettingsModal.tsx
  • apps/frontend/src/renderer/lib/mocks/workspace-mock.ts
  • apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/shared/constants/task.ts
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/renderer/stores/download-store.ts
  • apps/frontend/src/shared/types/settings.ts
  • apps/frontend/src/renderer/components/TerminalGrid.tsx
  • apps/frontend/src/main/agent/agent-process.ts
  • apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx
  • apps/frontend/src/main/ipc-handlers/github/utils/subprocess-runner.ts
  • apps/frontend/src/main/index.ts
  • apps/frontend/src/main/ipc-handlers/project-handlers.ts
  • apps/frontend/src/renderer/components/Sidebar.tsx
  • apps/frontend/src/renderer/components/terminal/types.ts
  • apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts
  • apps/frontend/src/renderer/App.tsx
  • apps/frontend/src/shared/types/task.ts
  • apps/frontend/src/renderer/components/Terminal.tsx
  • apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
  • apps/frontend/src/main/python-env-manager.ts
  • apps/frontend/src/renderer/components/KanbanBoard.tsx
  • apps/frontend/src/renderer/components/settings/DevToolsSettings.tsx
  • apps/frontend/src/main/agent/agent-manager.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx
  • apps/frontend/src/main/agent/agent-queue.ts
  • apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx
  • apps/frontend/src/renderer/components/settings/AppSettings.tsx
  • apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx
  • apps/frontend/src/preload/api/task-api.ts
  • apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts
  • apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx
  • apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts
  • apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
apps/backend/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

apps/backend/**/*.py: Always use the Claude Agent SDK (create_client() from core.client) for AI interactions - NEVER use anthropic.Anthropic() directly
Use create_client() from apps/backend/core/client.py with proper parameters: project_dir, spec_dir, model, agent_type, and optional max_thinking_tokens

Files:

  • apps/backend/commit_message.py
  • apps/backend/analysis/insight_extractor.py
  • apps/backend/project/command_registry/frameworks.py
  • apps/backend/project/stack_detector.py
  • apps/backend/core/simple_client.py
  • apps/backend/integrations/graphiti/test_ollama_embedding_memory.py
  • apps/backend/runners/github/gh_client.py
  • apps/backend/runners/github/batch_validator.py
  • apps/backend/runners/github/batch_issues.py
  • apps/backend/agents/tools_pkg/permissions.py
  • apps/backend/spec/compaction.py
  • apps/backend/runners/github/models.py
  • apps/backend/core/workspace.py
  • apps/backend/project/analyzer.py
  • apps/backend/runners/github/context_gatherer.py
  • apps/backend/runners/github/services/followup_reviewer.py
  • apps/backend/merge/ai_resolver/claude_client.py
  • apps/backend/agents/tools_pkg/__init__.py
  • apps/backend/agents/tools_pkg/models.py
  • apps/backend/project/command_registry/languages.py
  • apps/backend/core/client.py
  • apps/backend/runners/github/services/orchestrator_reviewer.py
  • apps/backend/ollama_model_detector.py
  • apps/backend/project/framework_detector.py
  • apps/backend/core/workspace/setup.py

⚙️ CodeRabbit configuration file

apps/backend/**/*.py: Focus on Python best practices, type hints, and async patterns.
Check for proper error handling and security considerations.
Verify compatibility with Python 3.12+.

Files:

  • apps/backend/commit_message.py
  • apps/backend/analysis/insight_extractor.py
  • apps/backend/project/command_registry/frameworks.py
  • apps/backend/project/stack_detector.py
  • apps/backend/core/simple_client.py
  • apps/backend/integrations/graphiti/test_ollama_embedding_memory.py
  • apps/backend/runners/github/gh_client.py
  • apps/backend/runners/github/batch_validator.py
  • apps/backend/runners/github/batch_issues.py
  • apps/backend/agents/tools_pkg/permissions.py
  • apps/backend/spec/compaction.py
  • apps/backend/runners/github/models.py
  • apps/backend/core/workspace.py
  • apps/backend/project/analyzer.py
  • apps/backend/runners/github/context_gatherer.py
  • apps/backend/runners/github/services/followup_reviewer.py
  • apps/backend/merge/ai_resolver/claude_client.py
  • apps/backend/agents/tools_pkg/__init__.py
  • apps/backend/agents/tools_pkg/models.py
  • apps/backend/project/command_registry/languages.py
  • apps/backend/core/client.py
  • apps/backend/runners/github/services/orchestrator_reviewer.py
  • apps/backend/ollama_model_detector.py
  • apps/backend/project/framework_detector.py
  • apps/backend/core/workspace/setup.py
apps/frontend/src/shared/i18n/locales/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

Add new translation keys to ALL language files (minimum: en/*.json and fr/*.json) in apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/shared/i18n/locales/en/onboarding.json
  • apps/frontend/src/shared/i18n/locales/en/settings.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/onboarding.json
  • apps/frontend/src/shared/i18n/locales/fr/common.json
  • apps/frontend/src/shared/i18n/locales/en/common.json
  • apps/frontend/src/shared/i18n/locales/fr/settings.json
  • apps/frontend/src/shared/i18n/locales/en/navigation.json
tests/**

⚙️ CodeRabbit configuration file

tests/**: Ensure tests are comprehensive and follow pytest conventions.
Check for proper mocking and test isolation.

Files:

  • tests/test_agent_architecture.py
  • tests/test_agent_configs.py
  • tests/test_security_cache.py
apps/backend/agents/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Graphiti memory system (get_graphiti_memory() from integrations/graphiti/) for session context and insight management in backend agents

Files:

  • apps/backend/agents/tools_pkg/permissions.py
  • apps/backend/agents/tools_pkg/__init__.py
  • apps/backend/agents/tools_pkg/models.py
🧠 Learnings (13)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/agents/{qa_reviewer,qa_fixer}.py : QA agents should use Electron MCP tools like `click_by_text`, `fill_input`, `take_screenshot`, and `get_page_structure` for automated frontend testing

Applied to files:

  • apps/frontend/src/renderer/components/AgentTools.tsx
  • tests/test_agent_architecture.py
  • apps/backend/agents/tools_pkg/models.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/**/*.py : Always use the Claude Agent SDK (`create_client()` from `core.client`) for AI interactions - NEVER use `anthropic.Anthropic()` directly

Applied to files:

  • apps/backend/commit_message.py
  • apps/backend/analysis/insight_extractor.py
  • apps/backend/core/simple_client.py
  • apps/backend/runners/github/batch_validator.py
  • apps/backend/runners/github/batch_issues.py
  • apps/backend/spec/compaction.py
  • apps/backend/core/workspace.py
  • apps/backend/merge/ai_resolver/claude_client.py
  • apps/backend/core/client.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/**/*.py : Use `create_client()` from `apps/backend/core/client.py` with proper parameters: `project_dir`, `spec_dir`, `model`, `agent_type`, and optional `max_thinking_tokens`

Applied to files:

  • apps/backend/commit_message.py
  • apps/backend/analysis/insight_extractor.py
  • apps/backend/core/simple_client.py
  • apps/backend/runners/github/batch_validator.py
  • apps/backend/runners/github/batch_issues.py
  • apps/backend/spec/compaction.py
  • apps/backend/core/workspace.py
  • apps/backend/merge/ai_resolver/claude_client.py
  • apps/backend/core/client.py
  • apps/backend/runners/github/services/orchestrator_reviewer.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/shared/i18n/locales/en/onboarding.json
  • apps/frontend/src/shared/i18n/locales/en/settings.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/onboarding.json
  • apps/frontend/src/shared/i18n/locales/fr/common.json
  • apps/frontend/src/shared/i18n/locales/en/common.json
  • apps/frontend/src/shared/i18n/locales/fr/settings.json
  • apps/frontend/src/shared/i18n/locales/en/navigation.json
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/agents/{qa_reviewer,qa_fixer}.py : For frontend bug fixes and feature implementations, use the Electron MCP server for automated E2E testing when the app is running with `--remote-debugging-port=9222`

Applied to files:

  • tests/test_agent_architecture.py
  • apps/backend/agents/tools_pkg/models.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/.env* : Enable Electron MCP in `apps/backend/.env` with `ELECTRON_MCP_ENABLED=true` and `ELECTRON_DEBUG_PORT=9222` to allow QA agents to interact with running Electron app

Applied to files:

  • tests/test_agent_architecture.py
  • apps/backend/agents/tools_pkg/models.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)

Applied to files:

  • apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`

Applied to files:

  • apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
📚 Learning: 2025-12-22T22:43:58.052Z
Learnt from: AndyMik90
Repo: AndyMik90/Auto-Claude PR: 150
File: apps/frontend/src/renderer/components/settings/ProjectSettingsContent.tsx:0-0
Timestamp: 2025-12-22T22:43:58.052Z
Learning: In the AndyMik90/Auto-Claude repository, the ESLint configuration only allows `console.warn` and `console.error` levels, not `console.log` or `console.info`.

Applied to files:

  • README.md
📚 Learning: 2025-12-19T15:00:48.233Z
Learnt from: AndyMik90
Repo: AndyMik90/Auto-Claude PR: 41
File: auto-claude/qa/loop.py:126-136
Timestamp: 2025-12-19T15:00:48.233Z
Learning: In auto-claude/qa/loop.py, when creating clients for QA fixer sessions (including human feedback processing), use get_phase_model(spec_dir, "qa", model) instead of hardcoding "sonnet" as the fallback to support dynamic model selection based on profiles.

Applied to files:

  • apps/backend/core/workspace.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Use git worktrees for isolated builds with branch naming convention `auto-claude/{spec-name}` - do NOT automatically push to GitHub

Applied to files:

  • apps/frontend/src/main/agent/agent-manager.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Implement three-layer security defense: OS Sandbox, Filesystem Permissions, and Command Allowlist using `security.py` and `project_analyzer.py`

Applied to files:

  • apps/backend/core/client.py
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Cache security profile in `.auto-claude-security.json` based on project analysis from `security.py` and `project_analyzer.py`

Applied to files:

  • tests/test_security_cache.py
🧬 Code graph analysis (33)
apps/frontend/src/shared/types/ipc.ts (1)
apps/frontend/src/shared/types/settings.ts (2)
  • SupportedIDE (14-88)
  • SupportedTerminal (92-144)
apps/frontend/src/renderer/components/onboarding/DevToolsStep.tsx (1)
apps/frontend/src/shared/types/settings.ts (2)
  • SupportedIDE (14-88)
  • SupportedTerminal (92-144)
apps/frontend/src/renderer/components/GlobalDownloadIndicator.tsx (3)
apps/frontend/src/renderer/stores/download-store.ts (1)
  • useDownloadStore (28-115)
.design-system/src/lib/utils.ts (1)
  • cn (4-6)
.design-system/src/lib/icons.ts (2)
  • Check (21-21)
  • X (37-37)
apps/frontend/src/renderer/components/QueueSettingsModal.tsx (3)
apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts (3)
  • error (18-18)
  • setError (19-19)
  • handleSave (52-52)
.design-system/src/components/Input.tsx (1)
  • Input (4-24)
.design-system/src/components/Button.tsx (1)
  • Button (10-44)
apps/backend/commit_message.py (1)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx (1)
apps/frontend/src/renderer/components/onboarding/DevToolsStep.tsx (1)
  • DevToolsStep (88-439)
apps/backend/analysis/insight_extractor.py (1)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/frontend/src/main/agent/agent-process.ts (3)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (776-776)
apps/frontend/src/main/python-env-manager.ts (1)
  • pythonEnvManager (690-690)
apps/frontend/src/main/python-detector.ts (1)
  • parsePythonCommand (215-258)
apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx (3)
apps/frontend/src/shared/types/task.ts (1)
  • Task (235-255)
apps/frontend/src/renderer/components/terminal/types.ts (1)
  • getTitleMaxWidthClass (21-27)
.design-system/src/lib/utils.ts (1)
  • cn (4-6)
apps/frontend/src/main/ipc-handlers/github/utils/subprocess-runner.ts (1)
apps/frontend/src/main/python-env-manager.ts (1)
  • getPythonPath (594-596)
tests/test_agent_architecture.py (1)
apps/backend/agents/tools_pkg/permissions.py (1)
  • get_allowed_tools (30-77)
apps/backend/integrations/graphiti/test_ollama_embedding_memory.py (1)
apps/backend/integrations/graphiti/queries_pkg/graphiti.py (6)
  • GraphitiMemory (26-392)
  • group_id (100-115)
  • save_session_insights (214-230)
  • save_pattern (248-259)
  • save_gotcha (261-272)
  • save_codebase_discoveries (232-246)
apps/backend/runners/github/batch_validator.py (1)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/backend/runners/github/batch_issues.py (1)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/backend/spec/compaction.py (1)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx (1)
apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts (2)
  • settings (15-15)
  • setSettings (16-16)
apps/backend/core/workspace.py (2)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/backend/core/workspace/models.py (1)
  • ParallelMergeResult (43-50)
apps/frontend/src/main/python-env-manager.ts (1)
apps/frontend/src/main/python-detector.ts (1)
  • getBundledPythonPath (12-33)
apps/backend/runners/github/context_gatherer.py (2)
apps/backend/runners/github/providers/github_provider.py (1)
  • gh_client (70-72)
apps/backend/runners/github/gh_client.py (1)
  • get_reviews_since (698-763)
apps/backend/merge/ai_resolver/claude_client.py (1)
apps/backend/core/simple_client.py (1)
  • create_simple_client (32-97)
apps/frontend/src/renderer/components/KanbanBoard.tsx (3)
apps/frontend/src/renderer/stores/project-store.ts (1)
  • useProjectStore (44-206)
apps/frontend/src/renderer/stores/task-store.ts (2)
  • persistTaskStatus (347-368)
  • useTaskStore (29-176)
apps/frontend/src/renderer/components/QueueSettingsModal.tsx (1)
  • QueueSettingsModal (23-109)
apps/frontend/src/renderer/components/settings/DevToolsSettings.tsx (1)
apps/frontend/src/shared/types/settings.ts (3)
  • AppSettings (215-265)
  • SupportedIDE (14-88)
  • SupportedTerminal (92-144)
apps/backend/agents/tools_pkg/models.py (3)
apps/frontend/scripts/download-python.cjs (2)
  • os (22-22)
  • config (198-198)
apps/backend/runners/github/lifecycle.py (1)
  • get (406-414)
apps/backend/core/client.py (1)
  • is_electron_mcp_enabled (53-61)
apps/backend/core/client.py (2)
apps/backend/agents/tools_pkg/permissions.py (1)
  • get_allowed_tools (30-77)
apps/backend/agents/tools_pkg/models.py (1)
  • get_required_mcp_servers (340-386)
apps/frontend/src/renderer/stores/task-store.ts (1)
apps/frontend/src/renderer/stores/project-store.ts (1)
  • useProjectStore (44-206)
apps/backend/runners/github/services/orchestrator_reviewer.py (1)
apps/backend/core/client.py (1)
  • create_client (93-368)
apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx (3)
apps/frontend/src/shared/types/settings.ts (2)
  • SupportedIDE (14-88)
  • SupportedTerminal (92-144)
apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts (1)
  • settings (15-15)
.design-system/src/components/Button.tsx (1)
  • Button (10-44)
apps/frontend/src/main/agent/agent-queue.ts (1)
apps/frontend/src/main/python-env-manager.ts (1)
  • pythonEnvManager (690-690)
tests/test_security_cache.py (1)
apps/backend/security/profile.py (2)
  • get_security_profile (42-88)
  • reset_profile_cache (91-97)
apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx (1)
apps/frontend/src/renderer/stores/download-store.ts (1)
  • useDownloadStore (28-115)
apps/frontend/src/renderer/components/settings/AppSettings.tsx (2)
apps/frontend/src/renderer/components/settings/DevToolsSettings.tsx (1)
  • DevToolsSettings (79-385)
apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts (2)
  • settings (15-15)
  • setSettings (16-16)
apps/frontend/src/preload/api/task-api.ts (2)
apps/frontend/src/shared/types/settings.ts (2)
  • SupportedIDE (14-88)
  • SupportedTerminal (92-144)
apps/frontend/src/shared/constants/ipc.ts (1)
  • IPC_CHANNELS (6-370)
apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts (1)
apps/frontend/src/renderer/stores/terminal-store.ts (1)
  • useTerminalStore (58-213)
🪛 Biome (2.1.2)
apps/frontend/src/renderer/components/AgentTools.tsx

[error] 343-346: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 580-583: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🪛 GitHub Check: CodeQL
apps/frontend/src/renderer/components/QueueSettingsModal.tsx

[notice] 30-30: Unused variable, import, function or class
Unused variable t.

🪛 LanguageTool
CLA.md

[grammar] ~32-~32: Use a hyphen to join words.
Context: ...ns be introduced in the future. The open source version of the Project will conti...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
CLA.md

13-13: Bare URL used

(MD034, no-bare-urls)


68-68: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (2)
  • GitHub Check: CodeQL (python)
  • GitHub Check: CodeQL (javascript-typescript)

Comment on lines 369 to 382
# Use simple_client for insight extraction
from pathlib import Path

from core.simple_client import create_simple_client

client = create_simple_client(
agent_type="insights",
model=model,
system_prompt=(
"You are an expert code analyst. You extract structured insights from coding sessions. "
"Always respond with valid JSON only, no markdown formatting or explanations."
),
cwd=Path(cwd) if cwd else None,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Redundant import and unnecessary conditional.

  1. Path is already imported at line 18, so the import on line 370 is unnecessary.
  2. The cwd variable on line 381 will always be truthy (set on line 366), making the conditional if cwd else None misleading.
🔎 Proposed simplification
-        # Use simple_client for insight extraction
-        from pathlib import Path
-
-        from core.simple_client import create_simple_client
+        from core.simple_client import create_simple_client

         client = create_simple_client(
             agent_type="insights",
             model=model,
             system_prompt=(
                 "You are an expert code analyst. You extract structured insights from coding sessions. "
                 "Always respond with valid JSON only, no markdown formatting or explanations."
             ),
-            cwd=Path(cwd) if cwd else None,
+            cwd=Path(cwd),
         )
🤖 Prompt for AI Agents
In apps/backend/analysis/insight_extractor.py around lines 369 to 382, remove
the redundant "from pathlib import Path" import (Path is already imported at
line 18) and simplify the create_simple_client call by passing cwd=Path(cwd)
directly (the existing conditional if cwd else None is unnecessary because cwd
is always set on line 366); keep the rest of the call unchanged.

Comment on lines 67 to 71
# Get authentication
oauth_token = require_auth_token()
import os

os.environ["CLAUDE_CODE_OAUTH_TOKEN"] = oauth_token
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Move os import to module level.

The import os statement inside the function should be at the module level for better code organization and slight performance improvement (avoiding repeated import lookup).

🔎 Proposed fix

Add at module level (after line 24):

import os

Then remove line 69:

     # Get authentication
     oauth_token = require_auth_token()
-    import os
-
     os.environ["CLAUDE_CODE_OAUTH_TOKEN"] = oauth_token

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/backend/core/simple_client.py around lines 67 to 71, the code currently
does an in-function import ("import os") which should be moved to module level;
add "import os" near the other imports (e.g., after line 24) and remove the
"import os" line at line 69 so the function simply sets
os.environ["CLAUDE_CODE_OAUTH_TOKEN"] = oauth_token without importing inside the
function.

Comment on lines 407 to 410
# Brief wait for embedding processing
print()
print_info("Waiting 3 seconds for embedding processing...")
await asyncio.sleep(3)
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider making embedding processing wait configurable or adaptive.

The hardcoded 3-4 second sleeps for embedding processing could cause flaky tests if the Ollama server is slower than expected, or waste time if faster.

For robustness, consider polling for completion status or making the wait time configurable via environment variable. However, for an integration test script this is acceptable.

Also applies to: 597-600

Comment on lines 56 to 60
client = create_simple_client(
agent_type="merge_resolver",
model="sonnet",
system_prompt=system,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the create_simple_client function definition
echo "=== Finding create_simple_client implementation ==="
rg -n "def create_simple_client" apps/backend --type py -A20

echo ""
echo "=== Checking usage of create_simple_client with model parameter ==="
rg -n "create_simple_client" apps/backend --type py -B2 -A5 | head -100

echo ""
echo "=== Checking for model name mappings or resolution ==="
rg -n "sonnet" apps/backend --type py -C3

Repository: AndyMik90/Auto-Claude

Length of output: 35218


🏁 Script executed:

#!/bin/bash
# Get the full implementation of create_simple_client
echo "=== Full create_simple_client implementation ==="
sed -n '32,100p' apps/backend/core/simple_client.py

echo ""
echo "=== Check how model is used in create_simple_client ==="
sed -n '32,120p' apps/backend/core/simple_client.py | grep -A 100 "def create_simple_client"

echo ""
echo "=== Check resolve_model_id implementation ==="
sed -n '92,110p' apps/backend/phase_config.py

Repository: AndyMik90/Auto-Claude

Length of output: 5965


🏁 Script executed:

#!/bin/bash
# Check for tests or error handling around this code
echo "=== Check for tests of claude_client.py ==="
fd -n "test.*claude_client" apps/backend --type f -o fd -n "claude_client.*test" apps/backend --type f

echo ""
echo "=== Check if there's error handling or try-catch around the merge resolver ==="
grep -r "sonnet" apps/backend/merge --type py -B5 -A5

echo ""
echo "=== Check if other create_simple_client calls use full IDs consistently ==="
rg "create_simple_client" apps/backend --type py -A1 | grep -E "(create_simple_client|model=)" | head -30

Repository: AndyMik90/Auto-Claude

Length of output: 2441


🏁 Script executed:

#!/bin/bash
# Get the actual model parameters from each create_simple_client call
echo "=== Model parameters in each create_simple_client call ==="
echo ""

echo "1. commit_message.py:"
sed -n '205,210p' apps/backend/commit_message.py

echo ""
echo "2. spec/compaction.py:"
sed -n '61,65p' apps/backend/spec/compaction.py

echo ""
echo "3. merge/ai_resolver/claude_client.py (the one under review):"
sed -n '56,60p' apps/backend/merge/ai_resolver/claude_client.py

echo ""
echo "4. runners/github/batch_issues.py:"
sed -n '155,160p' apps/backend/runners/github/batch_issues.py

echo ""
echo "5. core/workspace.py:"
sed -n '1419,1423p' apps/backend/core/workspace.py

echo ""
echo "=== Check if any other files pass 'sonnet' shorthand ==="
rg "create_simple_client" apps/backend -A2 | rg "sonnet"

Repository: AndyMik90/Auto-Claude

Length of output: 1717


🏁 Script executed:

#!/bin/bash
# Check the context of where this code is called from
echo "=== Full context of claude_client.py around the create_simple_client call ==="
sed -n '40,75p' apps/backend/merge/ai_resolver/claude_client.py

echo ""
echo "=== Check function signature that contains this code ==="
sed -n '1,60p' apps/backend/merge/ai_resolver/claude_client.py

Repository: AndyMik90/Auto-Claude

Length of output: 3219


Replace model="sonnet" with a full model ID or dynamic model resolution.

The create_simple_client() function passes the model parameter directly to the Claude SDK without resolving shorthands. Using "sonnet" will fail at runtime; provide the full model identifier like "claude-sonnet-4-5-20250929". Alternatively, use resolve_model_id("sonnet") from phase_config.py to handle the conversion. For consistency with the framework's phase-aware model selection, consider using get_phase_model(spec_dir, "merge_resolver", model) to support dynamic model selection based on profiles instead of hardcoding model names.

🤖 Prompt for AI Agents
In apps/backend/merge/ai_resolver/claude_client.py around lines 56 to 60, the
client is created with model="sonnet" which will fail at runtime because
shorthands are not resolved; replace the hardcoded shorthand with a resolved
full model ID (for example "claude-sonnet-4-5-20250929") or call the existing
resolver utilities—either import and use resolve_model_id("sonnet") from
phase_config.py or use get_phase_model(spec_dir, "merge_resolver", "sonnet") to
select the phase-aware model—then pass the resolved model string into
create_simple_client; ensure you add the necessary import and use spec_dir (or
available config) when calling get_phase_model.

Comment on lines 392 to 394
elif progress.get("status") == "success":
# Download complete
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider logging or emitting a progress event for download completion.

The pass statement silently handles the "success" status. While the final output_json at line 398-405 signals completion, emitting a progress event here would provide real-time feedback to the UI.

🔎 Optional enhancement
                     elif progress.get("status") == "success":
                         # Download complete
-                        pass
+                        print(
+                            json.dumps({"status": "success"}),
+                            file=sys.stderr,
+                            flush=True,
+                        )
🤖 Prompt for AI Agents
In apps/backend/ollama_model_detector.py around lines 392 to 394, the branch
handling progress.get("status") == "success" currently does nothing; instead
emit or log a download-complete progress event there so the UI receives
immediate feedback. Replace the pass by calling the existing progress-emission
helper (or process_logger.info if no helper exists) with a clear message and
status payload matching other progress events (e.g.,
{"status":"success","stage":"download","message":"model download
complete","percent":100}); ensure this is non-blocking and consistent with the
final output_json structure so UI consumers can react immediately.

Comment on lines 229 to 263
export function startTask(taskId: string, options?: { parallel?: boolean; workers?: number }): void {
const store = useTaskStore.getState();
const task = store.tasks.find((t) => t.id === taskId || t.specId === taskId);

if (!task) {
console.error('[startTask] Task not found:', taskId);
return;
}

// ============================================
// QUEUE SYSTEM: Enforce parallel task limit
// ============================================
// Get project settings to check maxParallelTasks
const projectId = task.projectId;
if (projectId) {
const projectStore = useProjectStore.getState();
const project = projectStore.projects.find((p) => p.id === projectId);
const maxParallelTasks = project?.settings.maxParallelTasks ?? 3;

// Count current in-progress tasks (excluding archived)
const inProgressCount = store.tasks.filter((t) =>
t.status === 'in_progress' && !t.metadata?.archivedAt
).length;

// If limit reached, move to queue instead of starting immediately
if (inProgressCount >= maxParallelTasks) {
console.log(`[Queue] In Progress full (${inProgressCount}/${maxParallelTasks}), moving task to Queue`);
// Move to queue - it will auto-promote when a slot opens
persistTaskStatus(taskId, 'queue');
return;
}
}

window.electronAPI.startTask(taskId, options);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's check the file structure and locate the relevant files
find apps/frontend -name "task-store.ts" -type f

Repository: AndyMik90/Auto-Claude

Length of output: 112


🏁 Script executed:

# Let's also check if there's an i18n configuration to understand the project setup
find apps/frontend -name "locales" -o -name "i18n" | head -20

Repository: AndyMik90/Auto-Claude

Length of output: 132


🏁 Script executed:

# Search for persistTaskStatus definition to see if it's async
rg -n "persistTaskStatus" --type=ts --type=tsx -B2 -A5 | head -100

Repository: AndyMik90/Auto-Claude

Length of output: 92


🏁 Script executed:

# Search for all startTask call sites
rg -n "startTask\s*\(" --type=ts --type=tsx -B2 -A2 | head -150

Repository: AndyMik90/Auto-Claude

Length of output: 92


🏁 Script executed:

# Read the task-store.ts file to see the actual implementation
wc -l apps/frontend/src/renderer/stores/task-store.ts

Repository: AndyMik90/Auto-Claude

Length of output: 116


🏁 Script executed:

# Read the file around the startTask function and persistTaskStatus
cat -n apps/frontend/src/renderer/stores/task-store.ts | head -300

Repository: AndyMik90/Auto-Claude

Length of output: 11996


🏁 Script executed:

# Search for persistTaskStatus definition and startTask calls without tsx type
rg -n "persistTaskStatus" --type=ts -B2 -A5 | head -200

Repository: AndyMik90/Auto-Claude

Length of output: 7971


🏁 Script executed:

# Search for all calls to startTask (not the definition)
rg -n "startTask\s*\(" --type=ts | grep -v "export function startTask" | grep -v "export async function startTask"

Repository: AndyMik90/Auto-Claude

Length of output: 782


🏁 Script executed:

# Get more context on persistTaskStatus definition
sed -n '347,380p' apps/frontend/src/renderer/stores/task-store.ts

Repository: AndyMik90/Auto-Claude

Length of output: 1000


🏁 Script executed:

# Search for where startTask is imported and used
rg -n "startTask" --type=ts -B2 -A2 | head -200

Repository: AndyMik90/Auto-Claude

Length of output: 15520


🏁 Script executed:

# Let's examine the call sites more closely to understand the impact
sed -n '101,105p' apps/frontend/src/renderer/components/TaskCard.tsx
sed -n '31,35p' apps/frontend/src/renderer/components/task-detail/TaskDetailPanel.tsx
sed -n '78,82p' apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 289


🏁 Script executed:

# Check if there's any error handling around these startTask calls
rg -n "startTask" --type=ts -B5 -A5 apps/frontend/src/renderer/components/TaskCard.tsx | head -40

Repository: AndyMik90/Auto-Claude

Length of output: 862


🏁 Script executed:

# Verify the complete persistTaskStatus implementation and any side effects
sed -n '345,380p' apps/frontend/src/renderer/stores/task-store.ts

Repository: AndyMik90/Auto-Claude

Length of output: 1046


🏁 Script executed:

# Let's check how other functions in task-store.ts handle persistTaskStatus
rg -n "persistTaskStatus" apps/frontend/src/renderer/stores/task-store.ts -B2 -A2

Repository: AndyMik90/Auto-Claude

Length of output: 690


🏁 Script executed:

# Check the full startTask function flow to understand the complete picture
sed -n '226,290p' apps/frontend/src/renderer/stores/task-store.ts

Repository: AndyMik90/Auto-Claude

Length of output: 2383


Critical race condition: persistTaskStatus not awaited at line 257.

persistTaskStatus is an async function but the call at line 257 doesn't await it. This creates a race condition where:

  • The function returns immediately while the status update to 'queue' is still pending
  • The file persistence completes asynchronously, potentially after other code paths have already executed
  • Another operation could run before the queue status is actually persisted to disk, causing inconsistency between in-memory state and persisted state

Additionally, there's no validation that the task isn't already in a conflicting state (e.g., already in_progress or queue), which could allow duplicate queueing.

Fix: Make startTask async and await the persistTaskStatus call. Update the three call sites (TaskCard.tsx:103, TaskDetailPanel.tsx:33, TaskDetailModal.tsx:80) to handle the async function appropriately.

🤖 Prompt for AI Agents
In apps/frontend/src/renderer/stores/task-store.ts around lines 229 to 263,
startTask calls the async persistTaskStatus without awaiting it and lacks
validation of the task's current status; change startTask to be async, await
persistTaskStatus(...) when moving a task to 'queue', and add a guard that
returns early if the task.status is already 'in_progress' or 'queue' (or
archived) to prevent duplicate queueing; then update the three call sites
(TaskCard.tsx:103, TaskDetailPanel.tsx:33, TaskDetailModal.tsx:80) to call
and/or await the now-async startTask and handle any returned promise/errors
appropriately.

Comment on lines +268 to +290
export async function stopTask(taskId: string): Promise<void> {
const store = useTaskStore.getState();
const task = store.tasks.find((t) => t.id === taskId || t.specId === taskId);

// Stop the task
window.electronAPI.stopTask(taskId);

// If the task was in progress, process queue to fill the now-empty slot
if (task && task.status === 'in_progress') {
// Get project settings for maxParallelTasks
const projectId = task.projectId;
if (projectId) {
const projectStore = useProjectStore.getState();
const project = projectStore.projects.find((p) => p.id === projectId);
const maxParallelTasks = project?.settings.maxParallelTasks ?? 3;

// Wait a bit for the backend to update the task status
setTimeout(async () => {
await processQueueForProject(projectId, maxParallelTasks);
}, 500);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read the relevant section
cat -n apps/frontend/src/renderer/stores/task-store.ts | sed -n '260,300p'

Repository: AndyMik90/Auto-Claude

Length of output: 1790


🏁 Script executed:

# Look for the processQueueForProject function
rg "processQueueForProject" -A 10 apps/frontend/

Repository: AndyMik90/Auto-Claude

Length of output: 1785


🏁 Script executed:

# Search for window.electronAPI.stopTask or similar IPC handler
rg "stopTask" apps/frontend/ -B 2 -A 5

Repository: AndyMik90/Auto-Claude

Length of output: 10136


🏁 Script executed:

# Look for event listeners or IPC event handlers related to task status
rg "taskStatus|task.*status.*change|taskUpdated|task.*complete" apps/frontend/ -i

Repository: AndyMik90/Auto-Claude

Length of output: 41556


🏁 Script executed:

# Get the complete processQueueForProject function
cat -n apps/frontend/src/renderer/stores/task-store.ts | sed -n '295,350p'

Repository: AndyMik90/Auto-Claude

Length of output: 2197


🏁 Script executed:

# Also check if there's any event-based listening for task completion
rg "onTaskStatusChange" apps/frontend/src/renderer/ -B 3 -A 3

Repository: AndyMik90/Auto-Claude

Length of output: 1144


Timing fragility remains despite fresh state reads inside processQueueForProject.

The 500ms setTimeout delay (line 285) is still problematic. While processQueueForProject correctly reads fresh state on each loop iteration (line 299), the core issue persists:

  1. Backend update timing is unpredictable: Task status may not update in exactly 500ms. If slower, inProgressCount will still reflect the stopped task, and queue won't promote. If faster, you've added unnecessary latency.

  2. Event-based approach exists but unused: The codebase already has window.electronAPI.onTaskStatusChange() (used in useIpc.ts) that broadcasts when the backend updates task status. Rather than guessing a delay, listen for the actual status change event before calling processQueueForProject.

  3. Better pattern: Replace the setTimeout with an event listener that waits for onTaskStatusChange to fire with the stopped task, then call processQueueForProject.

Comment on lines +292 to 320
/**
* Process queue for a specific project - auto-promote tasks to fill capacity
*/
async function processQueueForProject(projectId: string, maxParallelTasks: number): Promise<void> {
// Loop until capacity is full or queue is empty
while (true) {
// Get CURRENT state from store
const currentTasks = useTaskStore.getState().tasks;
const projectTasks = currentTasks.filter((t) => t.projectId === projectId && !t.metadata?.archivedAt);

const inProgressCount = projectTasks.filter((t) => t.status === 'in_progress').length;
const queuedTasks = projectTasks.filter((t) => t.status === 'queue');

// Stop if no capacity or no queued tasks
if (inProgressCount >= maxParallelTasks || queuedTasks.length === 0) {
break;
}

// Get the oldest task in queue (FIFO ordering)
const nextTask = queuedTasks.sort((a, b) => {
const dateA = new Date(a.createdAt).getTime();
const dateB = new Date(b.createdAt).getTime();
return dateA - dateB;
})[0];

console.log(`[Queue] Auto-promoting task ${nextTask.id} from Queue to In Progress (${inProgressCount + 1}/${maxParallelTasks})`);
await persistTaskStatus(nextTask.id, 'in_progress');
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling and infinite loop protection.

The processQueueForProject function has several robustness concerns:

  1. No error handling: If persistTaskStatus fails (line 318), the error is silently swallowed, and the loop continues. This could:

    • Lead to an infinite loop if persist keeps failing
    • Cause silent promotion failures with no user feedback
    • Create inconsistent state
  2. No infinite loop protection: While the logic appears correct, there's no max iteration count. If there's a bug in the counting logic, the app could hang.

  3. No validation before promotion: Between filtering the queued tasks and calling persist, the task's state could have changed (e.g., another operation moved it).

🔎 Proposed improvements
 async function processQueueForProject(projectId: string, maxParallelTasks: number): Promise<void> {
+  const MAX_ITERATIONS = 50; // Safety limit to prevent infinite loops
+  let iterations = 0;
+
   // Loop until capacity is full or queue is empty
   while (true) {
+    // Safety check to prevent infinite loops
+    if (++iterations > MAX_ITERATIONS) {
+      console.error(`[Queue] Exceeded max iterations (${MAX_ITERATIONS}) while processing queue for project ${projectId}`);
+      break;
+    }
+
     // Get CURRENT state from store
     const currentTasks = useTaskStore.getState().tasks;
     const projectTasks = currentTasks.filter((t) => t.projectId === projectId && !t.metadata?.archivedAt);
 
     const inProgressCount = projectTasks.filter((t) => t.status === 'in_progress').length;
     const queuedTasks = projectTasks.filter((t) => t.status === 'queue');
 
     // Stop if no capacity or no queued tasks
     if (inProgressCount >= maxParallelTasks || queuedTasks.length === 0) {
       break;
     }
 
     // Get the oldest task in queue (FIFO ordering)
     const nextTask = queuedTasks.sort((a, b) => {
       const dateA = new Date(a.createdAt).getTime();
       const dateB = new Date(b.createdAt).getTime();
       return dateA - dateB;
     })[0];
 
+    // Validate task is still in queue (could have changed)
+    if (nextTask.status !== 'queue') {
+      console.warn(`[Queue] Task ${nextTask.id} is no longer in queue, skipping`);
+      continue;
+    }
+
     console.log(`[Queue] Auto-promoting task ${nextTask.id} from Queue to In Progress (${inProgressCount + 1}/${maxParallelTasks})`);
-    await persistTaskStatus(nextTask.id, 'in_progress');
+    
+    try {
+      const success = await persistTaskStatus(nextTask.id, 'in_progress');
+      if (!success) {
+        console.error(`[Queue] Failed to promote task ${nextTask.id}, stopping queue processing`);
+        break;
+      }
+    } catch (error) {
+      console.error(`[Queue] Error promoting task ${nextTask.id}:`, error);
+      break;
+    }
   }
 }
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/stores/task-store.ts around lines 292 to 320, add
error handling, infinite-loop protection, and a pre-promotion validation: wrap
the persistTaskStatus call in a try/catch that logs the error and stops or
aborts the promotion loop on repeated failures; introduce a max iterations
safeguard (e.g., counter with a sensible limit) to guarantee the while loop
cannot run forever; before calling persistTaskStatus re-fetch or re-check the
task from useTaskStore.getState() to ensure it is still in 'queue' and not
archived/changed and skip if it no longer qualifies; on transient failures
consider a limited retry attempt per task, otherwise break out of the loop and
surface/log the error so promotions do not silently fail.

import type { ExecutionPhase as ExecutionPhaseType } from '../constants/phase-protocol';

export type TaskStatus = 'backlog' | 'in_progress' | 'ai_review' | 'human_review' | 'done';
export type TaskStatus = 'backlog' | 'queue' | 'in_progress' | 'ai_review' | 'human_review' | 'done';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's check the current state of the task.ts file
echo "=== Checking task.ts file ==="
cat -n apps/frontend/src/shared/types/task.ts

echo -e "\n=== Checking task constants file ==="
cat -n apps/frontend/src/shared/constants/task.ts

echo -e "\n=== Finding switch statements on status ==="
rg -n -B 2 -A 10 "switch.*status" apps/frontend/src --type ts --type tsx -g '!*.test.*' | head -80

echo -e "\n=== Finding case statements with status values ==="
rg -n "case 'backlog'|case 'in_progress'|case 'ai_review'|case 'done'" apps/frontend/src --type ts --type tsx -g '!*.test.*' | head -50

echo -e "\n=== Finding status comparisons ==="
rg -n "status === '(backlog|in_progress|ai_review|done|human_review)'" apps/frontend/src --type ts --type tsx -g '!*.test.*' | head -50

echo -e "\n=== Checking for hardcoded status strings in UI ==="
rg -n "'queue'|'backlog'|'in_progress'" apps/frontend/src --type tsx -g '!*.test.*' | grep -E "(JSX|return|<|>)" | head -30

Repository: AndyMik90/Auto-Claude

Length of output: 25778


🏁 Script executed:

#!/bin/bash
echo "=== Finding all TaskStatus type usages ==="
rg -n "TaskStatus" apps/frontend/src --type ts -A 2 -B 2 | head -100

echo -e "\n=== Finding hardcoded status string usages ==="
rg -n "status.*===|status.*!==|status.*==|case 'backlog'|case 'queue'|case 'in_progress'|case 'done'|case 'ai_review'|case 'human_review'" apps/frontend/src --type ts -A 2 | head -100

echo -e "\n=== Looking for status filter/mapping functions ==="
rg -n "function.*status|const.*status.*=|\.status|getStatus|statusLabel|statusColor" apps/frontend/src --type ts -A 3 | head -150

echo -e "\n=== Searching for any remaining hardcoded status strings in components ==="
rg -n "'backlog'|'queue'|'in_progress'|'done'|'ai_review'|'human_review'" apps/frontend/src --type ts -B 1 -A 1 | grep -v node_modules | head -80

Repository: AndyMik90/Auto-Claude

Length of output: 32849


🏁 Script executed:

#!/bin/bash
echo "=== Checking TaskCard.tsx getStatusColor switch (full context) ==="
sed -n '125,140p' apps/frontend/src/renderer/components/TaskCard.tsx

echo -e "\n=== Checking TaskCard.tsx getStatusLabel switch (full context) ==="
sed -n '140,155p' apps/frontend/src/renderer/components/TaskCard.tsx

echo -e "\n=== Searching for 'queue' in translation/i18n files ==="
find apps/frontend/src/shared/i18n -type f -name "*.json" -o -name "*.ts" 2>/dev/null | xargs grep -l "queue" 2>/dev/null | head -5

echo -e "\n=== Checking translation files for status labels ==="
find apps/frontend/src/shared/i18n -type f \( -name "*.json" -o -name "*.ts" \) -exec grep -l "labels\|status" {} \;

echo -e "\n=== Full TaskCard.tsx status handling methods ==="
sed -n '122,155p' apps/frontend/src/renderer/components/TaskCard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 2181


🏁 Script executed:

#!/bin/bash
echo "=== Checking English tasks.json for queue and status labels ==="
cat -n apps/frontend/src/shared/i18n/locales/en/tasks.json

echo -e "\n=== Checking English common.json for label definitions ==="
cat -n apps/frontend/src/shared/i18n/locales/en/common.json

echo -e "\n=== Checking if backlog has a translation key ==="
grep -r "backlog\|backlog" apps/frontend/src/shared/i18n/locales/en/ --include="*.json"

Repository: AndyMik90/Auto-Claude

Length of output: 8692


🏁 Script executed:

#!/bin/bash
echo "=== Searching for all components that use getStatusLabel or status display ==="
rg -n "getStatusLabel\|getStatusBadgeVariant\|status.*===" apps/frontend/src/renderer/components --type ts -A 2 | head -60

echo -e "\n=== Checking if 'queue' appears in other status-related components ==="
rg -n "backlog\|in_progress\|ai_review" apps/frontend/src/renderer/components --type ts | grep -v "test\|mock" | head -40

echo -e "\n=== Checking Kanban-related components for status handling ==="
fd "kanban\|Kanban" apps/frontend/src/renderer/components --type ts --type tsx 2>/dev/null

echo -e "\n=== Verifying if StatusBadge or similar exists ==="
fd "StatusBadge\|Status.*Badge\|status.*badge" apps/frontend/src/renderer/components -i --type ts --type tsx 2>/dev/null

Repository: AndyMik90/Auto-Claude

Length of output: 331


🏁 Script executed:

#!/bin/bash
echo "=== Checking TaskCard.tsx for how status is displayed to users ==="
rg -n "getStatusLabel\|getStatusBadgeVariant\|task\.status" apps/frontend/src/renderer/components/TaskCard.tsx | head -30

echo -e "\n=== Looking for all JSX/TSX files that display task status ==="
rg -l "task\.status\|status.*queue\|status.*backlog" apps/frontend/src/renderer --type ts -A 1 | head -20

echo -e "\n=== Checking if there's a StatusBadge component anywhere ==="
find apps/frontend/src -name "*[Ss]tatus*" -type f 2>/dev/null | grep -E "\.(ts|tsx)$" | head -20

echo -e "\n=== Finding where getStatusLabel is actually used ==="
rg -rn "getStatusLabel\|getStatusBadgeVariant" apps/frontend/src/renderer/components/TaskCard.tsx -A 5 -B 5 | head -80

Repository: AndyMik90/Auto-Claude

Length of output: 801


🏁 Script executed:

#!/bin/bash
echo "=== Reading TaskCard.tsx to find where getStatusLabel is used ==="
wc -l apps/frontend/src/renderer/components/TaskCard.tsx

echo -e "\n=== Extracting the JSX where status is displayed ==="
grep -n "getStatusLabel\|getStatusBadgeVariant\|<Badge\|statusBadge" apps/frontend/src/renderer/components/TaskCard.tsx | head -20

echo -e "\n=== Reading the return/JSX section of TaskCard ==="
tail -200 apps/frontend/src/renderer/components/TaskCard.tsx | head -100

echo -e "\n=== Checking StatusBadge component ==="
cat apps/frontend/src/renderer/components/project-settings/StatusBadge.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 5790


🏁 Script executed:

#!/bin/bash
echo "=== Finding all components that display task status in UI ==="
rg -l "task\.status" apps/frontend/src/renderer/components --type ts -A 1 | grep -v test | head -20

echo -e "\n=== Checking KanbanBoard/Kanban components for status handling ==="
rg -l "kanban\|Kanban" apps/frontend/src/renderer/components -i --type ts | head -10

echo -e "\n=== Searching for other getStatusLabel or similar functions ==="
rg -rn "getStatus|statusLabel|TASK_STATUS_LABELS" apps/frontend/src/renderer --type ts | grep -v test | grep -v node_modules | head -30

Repository: AndyMik90/Auto-Claude

Length of output: 3684


🏁 Script executed:

#!/bin/bash
echo "=== Checking what 'n' constant is (for status labels) ==="
grep -n "export.*const.*n\|^const n" apps/frontend/src/shared/constants/index.ts apps/frontend/src/shared/constants/task.ts | head -10

echo -e "\n=== Checking TaskCard.tsx function names more carefully ==="
grep -n "const.*Status\|function.*Status" apps/frontend/src/renderer/components/TaskCard.tsx | head -20

echo -e "\n=== Looking at shared constants index to see what is exported ==="
head -50 apps/frontend/src/shared/constants/index.ts

echo -e "\n=== Searching for TASK_STATUS_LABELS usage ==="
rg -n "TASK_STATUS_LABELS\|TASK_STATUS_COLORS" apps/frontend/src --type ts | grep -v test | head -20

Repository: AndyMik90/Auto-Claude

Length of output: 2163


🏁 Script executed:

#!/bin/bash
echo "=== Checking imports in TaskCard.tsx ==="
head -30 apps/frontend/src/renderer/components/TaskCard.tsx

echo -e "\n=== Checking imports in KanbanBoard.tsx ==="
head -30 apps/frontend/src/renderer/components/KanbanBoard.tsx

echo -e "\n=== Checking TaskHeader.tsx imports ==="
head -30 apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx

echo -e "\n=== Searching for what 'n' is defined as ==="
rg -n "^import.*n['\"]|^const n =|^export.*n\s*=" apps/frontend/src/renderer/components/TaskCard.tsx apps/frontend/src/renderer/components/KanbanBoard.tsx apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 3529


🏁 Script executed:

#!/bin/bash
echo "=== Checking how TaskHeader.tsx uses TASK_STATUS_LABELS ==="
sed -n '1,80p' apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx | tail -60

echo -e "\n=== Checking the full section where status is displayed in TaskHeader ==="
rg -n "task.status\|TASK_STATUS_LABELS" apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx -A 3 -B 3 | head -40

echo -e "\n=== Verifying TaskCard doesn't import TASK_STATUS_LABELS ==="
grep "TASK_STATUS_LABELS\|TASK_STATUS_COLORS" apps/frontend/src/renderer/components/TaskCard.tsx

echo -e "\n=== Checking if TaskCard should be updated to use constants ==="
sed -n '126,155p' apps/frontend/src/renderer/components/TaskCard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 3484


Update TaskCard.tsx and TaskHeader.tsx to handle the 'queue' status with proper styling and labels.

Adding 'queue' to the TaskStatus union type is correct for the Queue System v2 feature and the constants are properly configured. However, the switch statements in TaskCard.tsx and TaskHeader.tsx don't explicitly handle 'queue' and 'backlog' statuses, causing them to display with generic fallback styling ("Pending" label with "secondary" variant instead of "Queue" with cyan).

TaskCard.tsx (lines 126-155): The getStatusBadgeVariant() and getStatusLabel() switch statements are missing cases for 'queue' and 'backlog'. These should use the properly configured TASK_STATUS_LABELS and TASK_STATUS_COLORS constants instead of maintaining duplicate logic.

TaskHeader.tsx: The inline variant logic for status badges also needs to map 'queue' explicitly rather than defaulting to 'secondary'.

Additionally, add translation keys for 'labels.queue' and 'labels.backlog' in the i18n locale files to maintain consistency with the coding guidelines for user-facing text.

🤖 Prompt for AI Agents
In apps/frontend/src/shared/types/task.ts around line 8 and in
apps/frontend/src/components/TaskCard.tsx (lines ~126-155) and TaskHeader.tsx,
the switch logic doesn't explicitly handle the new 'queue' and existing
'backlog' statuses so they fall back to generic styling/labels; update
getStatusBadgeVariant() and getStatusLabel() in TaskCard.tsx to include cases
for 'queue' and 'backlog' that return TASK_STATUS_COLORS[status] and
TASK_STATUS_LABELS[status] respectively (remove duplicated logic and use the
constants), update the inline badge variant logic in TaskHeader.tsx to map
'queue' to the cyan variant instead of defaulting to 'secondary', and add
translation keys labels.queue and labels.backlog to the i18n locale files so
labels use translated strings.

Copy link
Contributor

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

Review continued from previous batch...

Comment on lines 80 to 107
def _get_mcp_tools_for_servers(servers: list[str]) -> list[str]:
"""
Get the list of MCP tools for QA agents based on project capabilities.
Get the list of MCP tools for a list of required servers.
This function determines which MCP tools to include based on:
1. Project type detection (Electron, web frontend, etc.)
2. Environment variables (ELECTRON_MCP_ENABLED)
Maps server names to their corresponding tool lists.
Args:
project_capabilities: Dict from detect_project_capabilities() or None
servers: List of MCP server names (e.g., ['context7', 'linear', 'electron'])
Returns:
List of MCP tool names to include
List of MCP tool names for all specified servers
"""
tools = []

# If no capabilities provided, fall back to legacy behavior
# (check env var only)
if project_capabilities is None:
if is_electron_mcp_enabled():
for server in servers:
if server == "context7":
tools.extend(CONTEXT7_TOOLS)
elif server == "linear":
tools.extend(LINEAR_TOOLS)
elif server == "graphiti":
tools.extend(GRAPHITI_MCP_TOOLS)
elif server == "electron":
tools.extend(ELECTRON_TOOLS)
return tools
elif server == "puppeteer":
tools.extend(PUPPETEER_TOOLS)
# auto-claude tools are already added via config["auto_claude_tools"]

# Project-capability-based tool selection
is_electron = project_capabilities.get("is_electron", False)
is_web_frontend = project_capabilities.get("is_web_frontend", False)
return tools
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding a fallback or logging for unknown server names.

The _get_mcp_tools_for_servers function silently ignores unknown server names. While the comment on line 105 explains that auto-claude tools are handled separately, other unknown servers would be silently skipped. Consider adding debug logging for unknown servers to aid troubleshooting.

🔎 Proposed enhancement
 def _get_mcp_tools_for_servers(servers: list[str]) -> list[str]:
     """
     Get the list of MCP tools for a list of required servers.

     Maps server names to their corresponding tool lists.

     Args:
         servers: List of MCP server names (e.g., ['context7', 'linear', 'electron'])

     Returns:
         List of MCP tool names for all specified servers
     """
     tools = []
+    known_servers = {"context7", "linear", "graphiti", "electron", "puppeteer", "auto-claude"}

     for server in servers:
         if server == "context7":
             tools.extend(CONTEXT7_TOOLS)
         elif server == "linear":
             tools.extend(LINEAR_TOOLS)
         elif server == "graphiti":
             tools.extend(GRAPHITI_MCP_TOOLS)
         elif server == "electron":
             tools.extend(ELECTRON_TOOLS)
         elif server == "puppeteer":
             tools.extend(PUPPETEER_TOOLS)
         # auto-claude tools are already added via config["auto_claude_tools"]
+        elif server not in known_servers:
+            # Log unknown servers for debugging (could indicate config drift)
+            import logging
+            logging.getLogger(__name__).debug(f"Unknown MCP server '{server}' has no tool mapping")

     return tools
🤖 Prompt for AI Agents
In apps/backend/agents/tools_pkg/permissions.py around lines 80 to 107, the
_get_mcp_tools_for_servers function currently ignores unknown server names
silently; add a fallback path that logs a debug/warning when an unrecognized
server is encountered (including the server name and optionally the full servers
list/context) so callers can diagnose mis-typed or unsupported server names, and
ensure the function still returns the accumulated tools; use the project’s
logger (or import one if needed) and keep the message concise and consistent
with existing logging levels.

Comment on lines 992 to 1070
async function openInTerminal(dirPath: string, terminal: SupportedTerminal, customPath?: string): Promise<{ success: boolean; error?: string }> {
const platform = process.platform as 'darwin' | 'win32' | 'linux';

try {
if (terminal === 'custom' && customPath) {
// Use custom terminal path with execFileAsync to prevent shell injection
if (!isPathSafe(customPath)) {
return { success: false, error: 'Invalid custom terminal path' };
}
await execFileAsync(customPath, [dirPath]);
return { success: true };
}

const config = TERMINAL_DETECTION[terminal];
if (!config) {
return { success: false, error: `Unknown terminal: ${terminal}` };
}

const commands = config.commands[platform];
if (!commands || commands.length === 0) {
// Fall back to opening the folder in system file manager
await shell.openPath(dirPath);
return { success: true };
}

if (platform === 'darwin') {
// macOS: Use open command with the directory
// Escape single quotes in dirPath to prevent AppleScript injection
const escapedPath = escapeAppleScriptPath(dirPath);

if (terminal === 'system') {
// Use AppleScript to open Terminal.app at the directory
const script = `tell application "Terminal" to do script "cd '${escapedPath}'"`;
await execFileAsync('osascript', ['-e', script]);
} else if (terminal === 'iterm2') {
// Use AppleScript to open iTerm2 at the directory
const script = `tell application "iTerm"
create window with default profile
tell current session of current window
write text "cd '${escapedPath}'"
end tell
end tell`;
await execFileAsync('osascript', ['-e', script]);
} else if (terminal === 'warp') {
// Warp can be opened with just the directory using execFileAsync
await execFileAsync('open', ['-a', 'Warp', dirPath]);
} else {
// For other terminals, use execFileAsync with arguments array
await execFileAsync(commands[0], [...commands.slice(1), dirPath]);
}
} else if (platform === 'win32') {
// Windows: Start terminal at directory using spawn to avoid shell injection
if (terminal === 'system') {
// Use spawn with proper argument separation
spawn('cmd.exe', ['/K', 'cd', '/d', dirPath], { detached: true, stdio: 'ignore' }).unref();
} else if (commands.length > 0) {
spawn(commands[0], [...commands.slice(1), dirPath], { detached: true, stdio: 'ignore' }).unref();
}
} else {
// Linux: Use the configured terminal with execFileAsync
if (terminal === 'system') {
// Try common terminal emulators with proper argument arrays
try {
await execFileAsync('x-terminal-emulator', ['--working-directory', dirPath, '-e', 'bash']);
} catch {
try {
await execFileAsync('gnome-terminal', ['--working-directory', dirPath]);
} catch {
// xterm doesn't have --working-directory, use -e with a script
// Escape the path for shell use within the xterm command
const escapedPath = escapeAppleScriptPath(dirPath);
await execFileAsync('xterm', ['-e', `cd '${escapedPath}' && bash`]);
}
}
} else {
// Use execFileAsync with arguments array
await execFileAsync(commands[0], [...commands.slice(1), dirPath]);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd "worktree-handlers.ts" --type f

Repository: AndyMik90/Auto-Claude

Length of output: 126


🏁 Script executed:

cat -n apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts | sed -n '992,1070p'

Repository: AndyMik90/Auto-Claude

Length of output: 4119


🏁 Script executed:

# Find TERMINAL_DETECTION definition in the same file
rg "TERMINAL_DETECTION\s*=" apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts -A 100

Repository: AndyMik90/Auto-Claude

Length of output: 47


🏁 Script executed:

rg "TERMINAL_DETECTION" apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts -B 2 -A 150

Repository: AndyMik90/Auto-Claude

Length of output: 15159


Fix argument construction for terminal flags expecting --flag=<path> format.

The TERMINAL_DETECTION config includes multiple terminals with flags ending in = (e.g., --working-directory=, --cd=) that expect the path appended directly. The current code at lines 1068 (Linux) and 1048 (Windows) appends dirPath as a separate argument, resulting in ['--flag=', '/path'] instead of ['--flag=/path'], causing these CLIs to fail.

Affected terminals:

  • Linux: gnometerminal, xfce4terminal, mate-terminal, terminator, tilix
  • Windows: gitbash

Apply the suggested pattern in both branches to check if the last argument ends with = and append the path directly, otherwise pass it as a separate argument.

🤖 Prompt for AI Agents
In apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts around lines
992–1070 (notably the Windows branch around ~1048 and the Linux branch around
~1068), the code currently appends dirPath as a separate argument which breaks
terminals whose flags are provided as “--flag=” and expect the path appended;
update argument construction so when building the final argument array you check
the last flag string: if it endsWith('=') then replace that last element with
lastElement + dirPath (concatenate) otherwise push dirPath as a separate
element; apply this same check/concatenation for both the Windows spawn/exec
branch (e.g., gitbash) and the Linux execFileAsync calls
(gnome-terminal/xfce4/terminator/tilix/mate-terminal fallback) so flags like
'--working-directory=' or '--cd=' become '--working-directory=/path' instead of
['--working-directory=', '/path'].

Comment on lines 94 to 143
/**
* Check if claude-agent-sdk is installed
* Get the path to bundled site-packages (for packaged apps).
* These are pre-installed during the build process.
*/
private getBundledSitePackagesPath(): string | null {
if (!app.isPackaged) {
return null;
}

const sitePackagesPath = path.join(process.resourcesPath, 'python-site-packages');

if (existsSync(sitePackagesPath)) {
console.log(`[PythonEnvManager] Found bundled site-packages at: ${sitePackagesPath}`);
return sitePackagesPath;
}

console.log(`[PythonEnvManager] Bundled site-packages not found at: ${sitePackagesPath}`);
return null;
}

/**
* Check if bundled packages are available and valid.
* For packaged apps, we check if the bundled site-packages directory exists
* and contains the marker file indicating successful bundling.
*/
private hasBundledPackages(): boolean {
const sitePackagesPath = this.getBundledSitePackagesPath();
if (!sitePackagesPath) {
return false;
}

// Check for the marker file that indicates successful bundling
const markerPath = path.join(sitePackagesPath, '.bundled');
if (existsSync(markerPath)) {
console.log(`[PythonEnvManager] Found bundle marker, using bundled packages`);
return true;
}

// Fallback: check if key packages exist
// This handles cases where the marker might be missing but packages are there
const claudeSdkPath = path.join(sitePackagesPath, 'claude_agent_sdk');
const dotenvPath = path.join(sitePackagesPath, 'dotenv');
if (existsSync(claudeSdkPath) || existsSync(dotenvPath)) {
console.log(`[PythonEnvManager] Found key packages, using bundled packages`);
return true;
}

return false;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Bundled/venv split and env propagation are well-structured; consider extending process tracking.

The manager cleanly prefers bundled Python + site-packages (with a .bundled marker or key-package check) and falls back to a venv with robust dependency verification. getPythonEnv() and the new sitePackagesPath / usingBundledPackages flags give callers enough information to wire correct PYTHONPATH, and the venv creation timeout + activeProcesses cleanup on will-quit is a solid reliability improvement.

If you see venv dependency installs hanging in practice, you might also add those spawned pip/ensurepip processes to activeProcesses for symmetrical cleanup, but it's not strictly required.

Also applies to: 220-268, 452-575, 619-639, 670-687

🤖 Prompt for AI Agents
In apps/frontend/src/main/python-env-manager.ts around lines 94-143 (also apply
same change to 220-268, 452-575, 619-639, 670-687): spawned pip/ensurepip
subprocesses used for venv creation or dependency installs are not added to
activeProcesses, so they can hang and not be cleaned up on app quit; when you
spawn those child processes, push the ChildProcess object into
this.activeProcesses immediately, and on the child's 'close'/'exit' remove it
from this.activeProcesses (and handle errors similarly), ensuring the existing
will-quit cleanup will terminate them if still running.

Comment on lines +189 to 199
{status === 'queue' && onQueueSettings && (
<Button
variant="ghost"
size="icon"
className="h-7 w-7 hover:bg-primary/10 hover:text-primary transition-colors"
onClick={onAddClick}
className="h-7 w-7 hover:bg-cyan-500/10 hover:text-cyan-400 transition-colors"
onClick={onQueueSettings}
title="Queue Settings"
>
<Plus className="h-4 w-4" />
<Settings className="h-4 w-4" />
</Button>
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Localize the “Queue Settings” tooltip text.

The title attribute for the queue settings button is hard-coded:

title="Queue Settings"

Per the frontend i18n guidelines, this should use a translation key via t(...) (e.g., t('tooltips.queueSettings')) and be backed by entries in the EN/FR locale files.

🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/KanbanBoard.tsx around lines 189 to
199, the button's title is hard-coded as "Queue Settings"; replace it with a
localized string using the i18n helper (e.g.,
title={t('tooltips.queueSettings')}). Ensure the component imports and calls the
translation hook (useTranslation or t from your i18n setup) and add matching
keys to the EN and FR locale files (tooltips.queueSettings -> "Queue Settings" /
"Paramètres de la file" or equivalent).

Comment on lines +364 to +377
const handleQueueAll = async () => {
const backlogTasks = tasksByStatus.backlog;
if (backlogTasks.length === 0) return;

console.log(`[Queue] Moving ${backlogTasks.length} tasks from Planning to Queue`);

// Move all backlog tasks to queue
for (const task of backlogTasks) {
await persistTaskStatus(task.id, 'queue');
}

// After all tasks are queued, process the queue to start filling In Progress
await processQueue();
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's check if the file exists and understand its structure
ls -la apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 168


🏁 Script executed:

# Get line count to understand the file size
wc -l apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 122


🏁 Script executed:

# Now let's examine the specific lines mentioned in the review (364-377)
sed -n '364,377p' apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 530


🏁 Script executed:

# Also check the lines mentioned in "Also applies to: 441-500"
sed -n '441,500p' apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 2601


🏁 Script executed:

# Let's search for the processQueue function definition
rg "const processQueue" apps/frontend/src/renderer/components/KanbanBoard.tsx -A 30

Repository: AndyMik90/Auto-Claude

Length of output: 1246


🏁 Script executed:

# Search for handleDragEnd function
rg "const handleDragEnd" apps/frontend/src/renderer/components/KanbanBoard.tsx -A 40

Repository: AndyMik90/Auto-Claude

Length of output: 1415


🏁 Script executed:

# Look for hardcoded strings, especially "Queue Settings"
rg "Queue Settings" apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 136


🏁 Script executed:

# Check if projectId is used in the component
rg "projectId" apps/frontend/src/renderer/components/KanbanBoard.tsx -B 2 -A 2

Repository: AndyMik90/Auto-Claude

Length of output: 1281


🏁 Script executed:

# Search for hardcoded strings in JSX (looking for common patterns like title, placeholder, label, aria-label, etc.)
rg '(title|placeholder|label|aria-label|aria-placeholder)=["'"'"']' apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 101


🏁 Script executed:

# Also check for hardcoded text in JSX elements (words directly in JSX without variables)
rg '<(button|div|span|p|h[1-6]|label).*>' apps/frontend/src/renderer/components/KanbanBoard.tsx -A 1 | grep -E '(Queue|Settings|Planning|Progress|Done|Backlog|Archive|Clear)' | head -20

Repository: AndyMik90/Auto-Claude

Length of output: 47


🏁 Script executed:

# Look at the entire handleDragEnd to verify the exact projectId issue
sed -n '441,478p' apps/frontend/src/renderer/components/KanbanBoard.tsx

Repository: AndyMik90/Auto-Claude

Length of output: 1703


Scope queue capacity and auto-promotion per project, not globally.

Both the drag-end capacity check in handleDragEnd (lines 454-465) and processQueue count all in_progress / queue tasks in useTaskStore.getState().tasks without filtering by projectId, while maxParallelTasks is derived from the active project. If multiple projects are loaded, one project's tasks can incorrectly consume capacity and block promotions for another. Since projectId is available in the component, filter task counts by project when enforcing capacity limits.

Also, the hardcoded string title="Queue Settings" in the JSX violates the i18n guideline. Replace with a translation key using the useTranslation() hook (format: namespace:section.key).

Example refactor to make processQueue project-aware
-  const processQueue = async () => {
+  const processQueue = async () => {
+    if (!projectId) {
+      return;
+    }
     // Loop until capacity is full or queue is empty
     while (true) {
       // Get CURRENT state from store to ensure accuracy
       const currentTasks = useTaskStore.getState().tasks;
-      const inProgressCount = currentTasks.filter((t) =>
-        t.status === 'in_progress' && !t.metadata?.archivedAt
-      ).length;
-      const queuedTasks = currentTasks.filter((t) =>
-        t.status === 'queue' && !t.metadata?.archivedAt
-      );
+      const projectTasks = currentTasks.filter(
+        (t) => t.projectId === projectId && !t.metadata?.archivedAt
+      );
+      const inProgressCount = projectTasks.filter(
+        (t) => t.status === 'in_progress'
+      ).length;
+      const queuedTasks = projectTasks.filter(
+        (t) => t.status === 'queue'
+      );
@@
-      console.log(`[Queue] Auto-promoting task ${nextTask.id} from Queue to In Progress (${inProgressCount + 1}/${maxParallelTasks})`);
+      console.log(
+        `[Queue] Auto-promoting task ${nextTask.id} from Queue to In Progress (${inProgressCount + 1}/${maxParallelTasks})`
+      );
       await persistTaskStatus(nextTask.id, 'in_progress');
     }
   };

And in handleDragEnd, use the same project-scoped inProgressCount:

-      const currentTasks = useTaskStore.getState().tasks;
-      const inProgressCount = currentTasks.filter((t) =>
-        t.status === 'in_progress' && !t.metadata?.archivedAt
-      ).length;
+      const currentTasks = useTaskStore.getState().tasks;
+      const inProgressCount = currentTasks.filter(
+        (t) =>
+          t.projectId === projectId &&
+          t.status === 'in_progress' &&
+          !t.metadata?.archivedAt
+      ).length;

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 117 to 185
// Progress tracking state for speed calculation
const progressTracker: Record<string, { lastCompleted: number; lastUpdate: number }> = {};

/**
* Subscribe to download progress events from the main process.
* Call this once when the app starts.
*/
export function initDownloadProgressListener(): () => void {
const handleProgress = (data: {
modelName: string;
status: string;
completed: number;
total: number;
percentage: number;
}) => {
const store = useDownloadStore.getState();
const now = Date.now();

// Initialize tracking for this model if needed
if (!progressTracker[data.modelName]) {
progressTracker[data.modelName] = {
lastCompleted: data.completed,
lastUpdate: now,
};
}

const prevData = progressTracker[data.modelName];
const timeDelta = now - prevData.lastUpdate;
const bytesDelta = data.completed - prevData.lastCompleted;

// Calculate speed only if we have meaningful time delta (> 100ms)
let speedStr = '';
let timeStr = '';

if (timeDelta > 100 && bytesDelta > 0) {
const speed = (bytesDelta / timeDelta) * 1000; // bytes per second
const remaining = data.total - data.completed;
const timeRemaining = speed > 0 ? Math.ceil(remaining / speed) : 0;

// Format speed (MB/s or KB/s)
if (speed > 1024 * 1024) {
speedStr = `${(speed / (1024 * 1024)).toFixed(1)} MB/s`;
} else if (speed > 1024) {
speedStr = `${(speed / 1024).toFixed(1)} KB/s`;
} else if (speed > 0) {
speedStr = `${Math.round(speed)} B/s`;
}

// Format time remaining
if (timeRemaining > 3600) {
timeStr = `${Math.ceil(timeRemaining / 3600)}h remaining`;
} else if (timeRemaining > 60) {
timeStr = `${Math.ceil(timeRemaining / 60)}m remaining`;
} else if (timeRemaining > 0) {
timeStr = `${Math.ceil(timeRemaining)}s remaining`;
}
}

// Update tracking
progressTracker[data.modelName] = {
lastCompleted: data.completed,
lastUpdate: now,
};

store.updateProgress(data.modelName, {
percentage: data.percentage,
speed: speedStr || undefined,
timeRemaining: timeStr || undefined,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Reset progressTracker when a download restarts to avoid bogus speed/ETA.

progressTracker never clears per modelName, so re-downloading the same model after completion can reuse stale lastCompleted/lastUpdate, yielding negative bytesDelta or nonsensical speed/timeRemaining. Consider resetting the tracker when a new progress event clearly indicates a fresh download (e.g., percentage drops, or completed < prevData.lastCompleted), or when status transitions back to starting in the store.

🤖 Prompt for AI Agents
In apps/frontend/src/renderer/stores/download-store.ts around lines 117-185, the
progressTracker is never reset for a modelName so a restarted download can use
stale lastCompleted/lastUpdate producing negative bytesDelta or wrong speed/ETA;
detect a fresh restart (for example if data.percentage is less than
prevData.percentage or data.completed < prevData.lastCompleted, or if
data.status === 'starting') and in that case reinitialize
progressTracker[data.modelName] to current completed and now before computing
deltas so speed/timeRemaining are calculated from the fresh start; ensure the
same reset happens when status transitions back to a starting state in the
store.

Address CodeRabbit review comment - use proper hyphenation for compound adjective modifying 'version'.
Copy link
Contributor

@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

♻️ Duplicate comments (1)
CLA.md (1)

32-32: ✓ Hyphenation corrected.

The prior review suggestion to hyphenate "open-source" as a compound adjective has been applied correctly. Thank you for addressing this.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57ecb55 and dc28a6c.

📒 Files selected for processing (1)
  • CLA.md
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/agents/{qa_reviewer,qa_fixer}.py : For frontend bug fixes and feature implementations, use the Electron MCP server for automated E2E testing when the app is running with `--remote-debugging-port=9222`
🪛 markdownlint-cli2 (0.18.1)
CLA.md

13-13: Bare URL used

(MD034, no-bare-urls)


68-68: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (2)
  • GitHub Check: CodeQL (javascript-typescript)
  • GitHub Check: CodeQL (python)
🔇 Additional comments (1)
CLA.md (1)

1-76: CLA document structure is comprehensive and well-written.

The document follows the Apache ASF Individual CLA v2.0 template and includes all essential sections: clear definitions, copyright and patent grants, future licensing flexibility, representations, warranty disclaimers, contributor rights, notification requirements, and signing instructions. The language is legally sound and contributor-friendly.

Critical Security Fix:
- Replace execSync with execFileSync in worktree-handlers.ts to prevent shell injection vulnerability
- Prevents arbitrary command execution through malicious specId values

Code Quality Improvements:
- Replace hardcoded cyan color with CSS variable in globals.css for theme consistency
- Remove hardcoded model reference in orchestrator_reviewer.py footer
- Add findProjectRoot() helper in download-python.cjs for robust path resolution
- Fallback to old path behavior if project root detection fails

These fixes address all actionable comments from CodeRabbit review on PR AndyMik90#405.

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Copy link
Contributor

@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

Caution

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

⚠️ Outside diff range comments (1)
apps/frontend/src/renderer/styles/globals.css (1)

143-145: Verify the color choice for Queue column.

The .column-queue class uses var(--info) for its border-top-color, which is identical to .column-in-progress (line 148). Since Queue and In Progress are distinct states in the workflow, consider whether Queue should have a visually distinct color to avoid confusion.

If the shared color is intentional to show these states are related/sequential, that's fine—just ensure it aligns with the design intent.

♻️ Duplicate comments (7)
apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts (1)

1042-1069: Fix terminal flag construction for --flag= patterns (past review not addressed).

This is a duplicate of a past review comment that remains unaddressed. Lines 1048 (Windows branch) and 1068 (Linux branch) append dirPath as a separate argument, which breaks terminals whose flags end with = and expect the path concatenated directly.

Affected terminals:

  • Windows: Git Bash (--cd=)
  • Linux: GNOME Terminal, XFCE4 Terminal, MATE Terminal, Terminator, Tilix, Foot (all use --working-directory=)

These terminals will receive ['--cd=', '/path'] instead of ['--cd=/path'], causing them to fail.

🔎 Proposed fix for both Windows and Linux branches
    } else if (platform === 'win32') {
      // Windows: Start terminal at directory using spawn to avoid shell injection
      if (terminal === 'system') {
        // Use spawn with proper argument separation
        spawn('cmd.exe', ['/K', 'cd', '/d', dirPath], { detached: true, stdio: 'ignore' }).unref();
      } else if (commands.length > 0) {
-       spawn(commands[0], [...commands.slice(1), dirPath], { detached: true, stdio: 'ignore' }).unref();
+       // Check if last flag ends with '=' and needs path concatenated
+       const args = commands.slice(1);
+       if (args.length > 0 && args[args.length - 1].endsWith('=')) {
+         args[args.length - 1] = args[args.length - 1] + dirPath;
+       } else {
+         args.push(dirPath);
+       }
+       spawn(commands[0], args, { detached: true, stdio: 'ignore' }).unref();
      }
    } else {
      // Linux: Use the configured terminal with execFileAsync
      if (terminal === 'system') {
        // Try common terminal emulators with proper argument arrays
        try {
          await execFileAsync('x-terminal-emulator', ['--working-directory', dirPath, '-e', 'bash']);
        } catch {
          try {
            await execFileAsync('gnome-terminal', ['--working-directory', dirPath]);
          } catch {
            // xterm doesn't have --working-directory, use -e with a script
            // Escape the path for shell use within the xterm command
            const escapedPath = escapeAppleScriptPath(dirPath);
            await execFileAsync('xterm', ['-e', `cd '${escapedPath}' && bash`]);
          }
        }
      } else {
-       // Use execFileAsync with arguments array
-       await execFileAsync(commands[0], [...commands.slice(1), dirPath]);
+       // Check if last flag ends with '=' and needs path concatenated
+       const args = commands.slice(1);
+       if (args.length > 0 && args[args.length - 1].endsWith('=')) {
+         args[args.length - 1] = args[args.length - 1] + dirPath;
+       } else {
+         args.push(dirPath);
+       }
+       await execFileAsync(commands[0], args);
      }
    }
apps/frontend/scripts/download-python.cjs (6)

28-117: Aggressive file stripping patterns remain unaddressed.

The previous review raised concerns about STRIP_PATTERNS removing .toml, .ini, .cfg, and .txt files that may be required at runtime by some packages. This issue has not been addressed in the current commit.


408-437: Symlink handling still missing.

The previous review suggested adding symlink detection to prevent infinite loops from circular symlinks. This has not been addressed.


439-446: Binary unit label mismatch still present.

The previous review suggested using KiB/MiB labels for binary divisors (1024) instead of KB/MB. This has not been changed.


448-526: Minor inefficiencies remain unaddressed.

The previous review suggested simplifying shouldRemoveFile by only checking lowerName and moving LICENSE preservation logic earlier. These optimizations have not been implemented.


528-559: Requirements.txt parsing gaps remain.

The previous review noted that the parser doesn't handle editable installs (-e), direct URLs (pkg @ url), or Git URLs with #egg=. This has not been addressed.


561-627: Redundant environment variable still present.

The previous review noted that PYTHONDONTWRITEBYTECODE: '1' (line 594) is redundant with the --no-compile flag (line 581). This has not been changed.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc28a6c and 047366b.

📒 Files selected for processing (4)
  • apps/backend/runners/github/services/orchestrator_reviewer.py
  • apps/frontend/scripts/download-python.cjs
  • apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
  • apps/frontend/src/renderer/styles/globals.css
🧰 Additional context used
📓 Path-based instructions (3)
apps/backend/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

apps/backend/**/*.py: Always use the Claude Agent SDK (create_client() from core.client) for AI interactions - NEVER use anthropic.Anthropic() directly
Use create_client() from apps/backend/core/client.py with proper parameters: project_dir, spec_dir, model, agent_type, and optional max_thinking_tokens

Files:

  • apps/backend/runners/github/services/orchestrator_reviewer.py

⚙️ CodeRabbit configuration file

apps/backend/**/*.py: Focus on Python best practices, type hints, and async patterns.
Check for proper error handling and security considerations.
Verify compatibility with Python 3.12+.

Files:

  • apps/backend/runners/github/services/orchestrator_reviewer.py
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/**/*.{ts,tsx}: Always use translation keys with useTranslation() for all user-facing text in React/TypeScript frontend components - use format namespace:section.key (e.g., navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from apps/frontend/src/shared/i18n/locales/

Files:

  • apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
🧠 Learnings (1)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/backend/**/*.py : Use `create_client()` from `apps/backend/core/client.py` with proper parameters: `project_dir`, `spec_dir`, `model`, `agent_type`, and optional `max_thinking_tokens`

Applied to files:

  • apps/backend/runners/github/services/orchestrator_reviewer.py
🧬 Code graph analysis (2)
apps/backend/runners/github/services/orchestrator_reviewer.py (1)
apps/backend/core/client.py (1)
  • create_client (93-368)
apps/frontend/scripts/download-python.cjs (1)
apps/frontend/src/main/updater/http-client.ts (1)
  • downloadFile (89-189)
⏰ 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). (3)
  • GitHub Check: CodeQL
  • GitHub Check: CodeQL (javascript-typescript)
  • GitHub Check: CodeQL (python)
🔇 Additional comments (13)
apps/frontend/src/renderer/styles/globals.css (2)

93-97: LGTM! Standard indeterminate animation pattern.

The keyframes definition correctly implements a horizontal sweep animation suitable for indeterminate progress indicators. The -100% to 400% translation creates a smooth, continuous effect.


105-107: LGTM! Follows established animation utility pattern.

The utility class correctly applies the indeterminate animation and follows the same pattern as .animate-pulse-subtle. Proper placement outside @theme ensures Tailwind v4 compatibility.

apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts (4)

1464-1485: LGTM! Correct platform-specific process termination.

The platform-specific termination logic is well-implemented:

  • Windows uses .kill() without a signal parameter (correct for Windows process tree termination)
  • Unix uses SIGTERM first with a 5-second grace period, then SIGKILL as a fallback

1651-1694: Excellent retry pattern with write verification.

The updatePlanWithRetry function is well-designed:

  • Uses EAFP (try/catch) to avoid TOCTOU race conditions
  • Verifies writes by reading back and checking the status fields match
  • Implements exponential backoff (100ms, 200ms, 400ms) for transient failures
  • Correctly distinguishes between critical main plan failures and non-critical worktree plan failures

This is a solid pattern for resilient file I/O operations.


2143-2214: LGTM! New IPC handlers are well-implemented.

The three new IPC handlers for tool detection and worktree opening follow established patterns:

  • Proper error handling with try/catch blocks
  • Path existence validation before operations
  • Descriptive error messages
  • Consistent return type structure (IPCResult)

1439-1440: Good: Python environment integration for bundled packages.

The code correctly retrieves and includes the Python environment from pythonEnvManagerSingleton.getPythonEnv() to ensure bundled packages are available in the PYTHONPATH for the merge process.

apps/backend/runners/github/services/orchestrator_reviewer.py (4)

24-24: LGTM: Import statements are correct.

The get_thinking_budget import is properly included in both the try and except blocks, following the existing pattern for handling different import contexts.

Also applies to: 55-55


233-233: Improved user visibility with dynamic model information.

The updated waiting message now reflects the actual model and thinking level in use, which is excellent for debugging and user transparency.


1156-1156: Fix trailing underscore in footer message.

The trailing underscore in the footer text appears unintentional and should be removed for a cleaner user-facing message.

🔎 Proposed fix
-        lines.append("_Generated by Auto Claude Orchestrating PR Reviewer_")
+        lines.append("_Generated by Auto Claude Orchestrating PR Reviewer_")

Wait, looking at the markdown syntax, underscores are used for italics. If both leading and trailing underscores are present, the text will be italicized correctly. However, the diff shows the line was changed, and based on the AI summary it was changed from "(Opus 4.5)" to just an underscore. Let me reconsider...

Actually, in Markdown, _text_ renders as italics. So _Generated by Auto Claude Orchestrating PR Reviewer_ would render as "Generated by Auto Claude Orchestrating PR Reviewer" (italicized). This is intentional formatting. Let me verify this is the correct interpretation by checking if there's a leading underscore too.

Looking at line 1156: lines.append("_Generated by Auto Claude Orchestrating PR Reviewer_")

Yes, there's both a leading underscore and trailing underscore, so this is Markdown italic formatting. This is NOT a typo - it's intentional Markdown syntax to italicize the footer text.

Let me revise my analysis - this is actually correct and I should not flag it.

# No fix needed - the underscores are Markdown formatting for italics

Actually, reviewing more carefully, the underscores are Markdown syntax for italics (_text_ = text). This is intentional formatting, not a typo.


183-210: Excellent implementation of dynamic model configuration.

This change correctly implements config-driven model and thinking budget selection, properly using create_client() with the required parameters as per coding guidelines. The logging and fallback values improve robustness.

The implementation already handles edge cases gracefully: get_thinking_budget() validates the thinking level against supported values and safely defaults to "medium" if invalid, so no additional error handling is needed.

Likely an incorrect or invalid review comment.

apps/frontend/scripts/download-python.cjs (3)

353-358: Good improvement for Windows compatibility.

Using the SystemRoot environment variable with fallback to windir improves robustness on non-standard Windows installations. The fallback chain is well-designed.


629-647: Well-implemented project root finder.

The new findProjectRoot function correctly walks up the directory tree and stops at the filesystem root. The logic is sound and error handling is appropriate.


679-687: Good use of findProjectRoot with fallback.

The implementation correctly uses findProjectRoot with a try/catch fallback to the previous path construction. This provides both robustness (project-root-based discovery) and backward compatibility (fallback behavior).

Comment on lines 765 to 792
// Install packages unless skipped
if (!skipPackages) {
if (!fs.existsSync(requirementsPath)) {
console.warn(`[download-python] Warning: requirements.txt not found at ${requirementsPath}`);
console.warn(`[download-python] Skipping package installation`);
} else {
// Remove existing site-packages to ensure clean install
if (fs.existsSync(sitePackagesDir)) {
console.log(`[download-python] Removing existing site-packages...`);
fs.rmSync(sitePackagesDir, { recursive: true, force: true });
}

// Install packages
installPackages(pythonBin, requirementsPath, sitePackagesDir);

// Create marker file to indicate successful bundling
fs.writeFileSync(packagesMarker, JSON.stringify({
bundledAt: new Date().toISOString(),
pythonVersion: PYTHON_VERSION,
platform: info.nodePlatform,
arch: arch,
}, null, 2));

console.log(`[download-python] Created bundle marker: ${packagesMarker}`);
}
}

return { success: true, pythonPath: pythonBin };
return { success: true, pythonPath: pythonBin, sitePackagesPath: sitePackagesDir };
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider conditional sitePackagesPath in return value.

When skipPackages is true or requirementsPath doesn't exist, packages are not installed (lines 766-790), but the function still returns sitePackagesPath pointing to a potentially non-existent directory (line 792). Consider returning sitePackagesPath only when packages were actually installed:

+  let actualSitePackagesPath = undefined;
   if (!skipPackages) {
     if (!fs.existsSync(requirementsPath)) {
       console.warn(`[download-python] Warning: requirements.txt not found at ${requirementsPath}`);
       console.warn(`[download-python] Skipping package installation`);
     } else {
       // ... installation code ...
+      actualSitePackagesPath = sitePackagesDir;
     }
   }

-  return { success: true, pythonPath: pythonBin, sitePackagesPath: sitePackagesDir };
+  const result = { success: true, pythonPath: pythonBin };
+  if (actualSitePackagesPath) {
+    result.sitePackagesPath = actualSitePackagesPath;
+  }
+  return result;

This makes the return value more explicit about whether packages were installed.

🤖 Prompt for AI Agents
In apps/frontend/scripts/download-python.cjs around lines 765 to 792, the
function currently always returns sitePackagesPath even when skipPackages is
true or requirements.txt is missing; change the return to only include
sitePackagesPath when packages were actually installed (e.g., set a flag
installedPackages when installPackages runs or when requirementsPath exists and
installation completes, and return sitePackagesPath only if that flag is true,
otherwise return null/undefined or omit the property) and ensure the marker file
creation remains coupled to the installedPackages flag so the return value
accurately reflects whether packages were bundled.

@MikeeBuilds MikeeBuilds added feature New feature or request area/fullstack This is Frontend + Backend labels Dec 29, 2025
@AndyMik90 AndyMik90 self-assigned this Dec 29, 2025
@AlexMadera AlexMadera added this to the Release 2.8 milestone Dec 30, 2025
@CLAassistant
Copy link

CLAassistant commented Dec 30, 2025

CLA assistant check
All committers have signed the CLA.

Resolved merge conflicts in:
- CLA.md (add/add - kept ours)
- README.md (accepted upstream)
- apps/backend/core/client.py (merged spec_path permissions)
- apps/frontend/scripts/download-python.cjs (accepted upstream)
- apps/frontend/src/main/index.ts (accepted upstream)
- apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts (accepted upstream)
- apps/frontend/src/renderer/components/Sidebar.tsx (added GitLab MRs nav item)
- apps/frontend/src/renderer/components/settings/AppSettings.tsx (added Debug section)
- apps/frontend/src/renderer/stores/download-store.ts (add/add - kept ours)
- All i18n translation files (merged both sets of keys)
- apps/frontend/src/shared/types/project.ts (kept maxParallelTasks from queue system)

Queue system functionality preserved:
- Max parallel tasks configuration
- Queue status and auto-promotion
- Batch queue button and capacity indicators

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

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@github-actions
Copy link

Thank you for your contribution! Before we can accept your PR, you need to sign our Contributor License Agreement (CLA).

To sign the CLA, please comment on this PR with exactly:

I have read the CLA Document and I hereby sign the CLA

You can read the full CLA here: CLA.md


Why do we need a CLA?

Auto Claude is licensed under AGPL-3.0. The CLA ensures the project has proper licensing flexibility should we introduce additional licensing options in the future.

You retain full copyright ownership of your contributions.


I have read the CLA Document and I hereby sign the CLA


0 out of 3 committers have signed the CLA.
@AndyMik90
@AlexMadera
@JoshuaRileyDev
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Copy link
Contributor

@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

Caution

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

⚠️ Outside diff range comments (4)
apps/frontend/src/shared/i18n/locales/fr/tasks.json (2)

19-29: Add missing status label translations for 'queue' and 'backlog'.

The new 'queue' status (and existing 'backlog' status) are missing from the labels section. According to the previous review, UI components like TaskCard.tsx use these label keys to display status badges to users. Without these entries, the status display will fall back to generic/untranslated text.

Based on coding guidelines, all user-facing text must use i18n translation keys.

🔎 Proposed additions
   "labels": {
     "running": "En cours",
     "aiReview": "Révision IA",
     "needsReview": "À réviser",
     "pending": "En attente",
+    "queue": "File d'attente",
+    "backlog": "Backlog",
     "stuck": "Bloqué",
     "incomplete": "Incomplet",
     "recovering": "Récupération...",
     "needsRecovery": "Récupération requise",
     "needsResume": "Reprise requise"
   },

2-9: Consider adding 'queue' to the status section for consistency.

The status section defines display names for task statuses but is missing the new 'queue' status. While the labels section is used for status badges, having 'queue' in the status section would ensure consistency if other parts of the UI reference this section.

🔎 Proposed addition
   "status": {
     "backlog": "Backlog",
+    "queue": "File d'attente",
     "todo": "À faire",
     "in_progress": "En cours",
     "review": "Révision",
     "complete": "Terminé",
     "archived": "Archivé"
   },
apps/frontend/src/shared/i18n/locales/en/tasks.json (2)

19-29: Add missing status label translations for 'queue' and 'backlog'.

The new 'queue' status (and existing 'backlog' status) are missing from the labels section. According to the previous review, UI components like TaskCard.tsx use these label keys to display status badges to users. Without these entries, the status display will fall back to generic/untranslated text.

Based on coding guidelines, all user-facing text must use i18n translation keys.

🔎 Proposed additions
   "labels": {
     "running": "Running",
     "aiReview": "AI Review",
     "needsReview": "Needs Review",
     "pending": "Pending",
+    "queue": "Queue",
+    "backlog": "Backlog",
     "stuck": "Stuck",
     "incomplete": "Incomplete",
     "recovering": "Recovering...",
     "needsRecovery": "Needs Recovery",
     "needsResume": "Needs Resume"
   },

2-9: Consider adding 'queue' to the status section for consistency.

The status section defines display names for task statuses but is missing the new 'queue' status. While the labels section is used for status badges, having 'queue' in the status section would ensure consistency if other parts of the UI reference this section.

🔎 Proposed addition
   "status": {
     "backlog": "Backlog",
+    "queue": "Queue",
     "todo": "To Do",
     "in_progress": "In Progress",
     "review": "Review",
     "complete": "Complete",
     "archived": "Archived"
   },
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 047366b and 13f8043.

📒 Files selected for processing (7)
  • apps/backend/runners/github/services/orchestrator_reviewer.py
  • apps/frontend/src/shared/i18n/locales/en/navigation.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/types/project.ts
  • apps/frontend/src/shared/types/task.ts
🧰 Additional context used
📓 Path-based instructions (5)
apps/backend/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

apps/backend/**/*.py: Always use the Claude Agent SDK (claude-agent-sdk package) for all AI interactions, never use the Anthropic API directly
Use the create_client() function from apps/backend/core/client.py to instantiate Claude SDK clients, not direct ClaudeSDKClient initialization

Files:

  • apps/backend/runners/github/services/orchestrator_reviewer.py

⚙️ CodeRabbit configuration file

apps/backend/**/*.py: Focus on Python best practices, type hints, and async patterns.
Check for proper error handling and security considerations.
Verify compatibility with Python 3.12+.

Files:

  • apps/backend/runners/github/services/orchestrator_reviewer.py
apps/frontend/src/shared/i18n/locales/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/shared/i18n/locales/**/*.json: Store translation strings in namespace-organized JSON files at apps/frontend/src/shared/i18n/locales/{lang}/*.json for each supported language
When implementing new frontend features, add translation keys to all language files (minimum: en/.json and fr/.json)

Files:

  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
  • apps/frontend/src/shared/i18n/locales/en/navigation.json
apps/frontend/src/**/*.{ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use i18n translation keys for all user-facing text in the frontend instead of hardcoded strings

Files:

  • apps/frontend/src/shared/types/task.ts
  • apps/frontend/src/shared/types/project.ts
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use useTranslation() hook with namespace prefixes (e.g., 'navigation:items.key') for accessing translation strings in React components

Files:

  • apps/frontend/src/shared/types/task.ts
  • apps/frontend/src/shared/types/project.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/shared/types/task.ts
  • apps/frontend/src/shared/types/project.ts
🧠 Learnings (1)
📚 Learning: 2025-12-30T16:38:36.276Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T16:38:36.276Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : When implementing new frontend features, add translation keys to all language files (minimum: en/*.json and fr/*.json)

Applied to files:

  • apps/frontend/src/shared/i18n/locales/fr/navigation.json
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
⏰ 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). (3)
  • GitHub Check: CodeQL
  • GitHub Check: CodeQL (python)
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (6)
apps/backend/runners/github/services/orchestrator_reviewer.py (1)

1156-1156: LGTM! Removing hardcoded model version improves accuracy.

The change removes the hardcoded "(Opus 4.5)" reference from the footer, which is appropriate since the system supports configurable models (line 191). The generic footer text is more accurate and maintainable, as it doesn't need updates when different models are used.

apps/frontend/src/shared/i18n/locales/en/navigation.json (1)

18-19: Verify that this change belongs in this PR.

The addition of the gitlabMRs navigation item appears unrelated to the PR's stated purpose (Queue System v2 with auto-promotion and task management). Please confirm whether:

  • This change was accidentally included from another branch, or
  • There's a valid reason for including GitLab MRs navigation changes in this PR

The translation itself is correct and follows coding guidelines by updating both EN and FR files consistently.

apps/frontend/src/shared/i18n/locales/fr/navigation.json (1)

18-19: Translation is correct, but verify PR scope.

The French translation "MRs GitLab" correctly follows French grammar conventions (modifier after noun) and is consistent with the English file changes. However, as noted in the English file review, this GitLab MRs navigation change appears unrelated to the Queue System v2 PR objectives.

apps/frontend/src/shared/types/task.ts (1)

8-8: LGTM: 'queue' status addition is correct.

The addition of 'queue' to the TaskStatus union type properly extends the task lifecycle to support the new Queue System v2 feature. The type definition itself is sound.

Note: A previous review identified that UI components (TaskCard.tsx, TaskHeader.tsx) need updates to handle the new 'queue' status in their switch statements and that translation keys for status labels are needed. Please refer to that review for integration details.

apps/frontend/src/shared/i18n/locales/fr/tasks.json (1)

90-101: LGTM: Queue translations are comprehensive and correctly structured.

The queue section includes all necessary keys with proper interpolation variables ({{count}}, {{current}}, {{max}}, {{available}}). The nested settings structure is well-organized, and the French translations are accurate and natural.

apps/frontend/src/shared/i18n/locales/en/tasks.json (1)

90-101: LGTM: Queue translations are comprehensive and correctly structured.

The queue section includes all necessary keys with proper interpolation variables ({{count}}, {{current}}, {{max}}, {{available}}). The nested settings structure is well-organized and provides clear, user-friendly messages for the queue system.

Comment on lines +29 to +30
/** Maximum number of tasks that can run in parallel in "In Progress" (default: 3) */
maxParallelTasks?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding validation bounds or using a branded type for maxParallelTasks.

The maxParallelTasks property allows any number, including invalid values (zero, negative, or excessively large numbers). These could break queue processing logic or lead to poor UX. Consider one of the following:

  1. Add runtime validation where this value is set/used (e.g., min: 1, max: 10 or 20)
  2. Document the expected range in the JSDoc
  3. Use a branded type or constraint to enforce bounds at compile time
📋 Example: Enhanced JSDoc with constraints
-  /** Maximum number of tasks that can run in parallel in "In Progress" (default: 3) */
+  /** Maximum number of tasks that can run in parallel in "In Progress" (default: 3, valid range: 1-20) */
   maxParallelTasks?: number;
📝 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
/** Maximum number of tasks that can run in parallel in "In Progress" (default: 3) */
maxParallelTasks?: number;
/** Maximum number of tasks that can run in parallel in "In Progress" (default: 3, valid range: 1-20) */
maxParallelTasks?: number;
🤖 Prompt for AI Agents
In apps/frontend/src/shared/types/project.ts around lines 29-30,
maxParallelTasks is currently an unconstrained optional number which can be
zero, negative, or excessively large; add clear constraints and enforcement:
update the JSDoc to document an explicit valid range (e.g., min 1, max 20),
replace or complement the plain number with a branded/alias type to express the
constraint at compile time (export a NamedBranded type for validated task
counts), and add runtime validation where the value is read/assigned to either
clamp to the allowed range or throw a descriptive error so invalid values cannot
propagate into queue processing logic.

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

Labels

area/fullstack This is Frontend + Backend feature New feature or request ❌ MERGE CONFLICTS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants