Skip to content

feat(task): add delete and retry functionality for stuck/failed tasks#6

Open
youngmrz wants to merge 23 commits intodevelopfrom
fix/task-cleanup
Open

feat(task): add delete and retry functionality for stuck/failed tasks#6
youngmrz wants to merge 23 commits intodevelopfrom
fix/task-cleanup

Conversation

@youngmrz
Copy link
Owner

Summary

  • Add TASK_DELETE_AND_RETRY IPC channel for cleaning up stuck/failed tasks
  • Add deleteAndRetryTask function to task store for UI integration
  • Implementation includes:
    • Stop running task process if active
    • Clean up git worktree with git worktree remove --force
    • Delete associated branch and prune dangling worktrees
    • Remove spec directory from .auto-claude/specs/
    • Optionally recreate task with retriedFrom metadata for retry tracking

Fixes AndyMik90#1103 - Orphaned spec directories remain after task failures

Test plan

  • Delete a failed task and verify worktree is cleaned up
  • Delete and retry a task - verify new spec is created with retriedFrom metadata
  • Verify running task is stopped before deletion

🤖 Generated with Claude Code

youngmrz pushed a commit that referenced this pull request Jan 15, 2026
…ik90#1038)

* feat: Add OpenRouter as LLM/embedding provider (#162)

* feat: Add OpenRouter as LLM/embedding provider

Add OpenRouter provider support for Graphiti memory integration,
enabling access to multiple LLM providers through a single API.

Changes:
Backend:
- Created openrouter_llm.py: OpenRouter LLM provider using OpenAI-compatible API
- Created openrouter_embedder.py: OpenRouter embedder provider
- Updated config.py: Added OpenRouter to provider enums and configuration
  - New fields: openrouter_api_key, openrouter_base_url, openrouter_llm_model, openrouter_embedding_model
  - Validation methods updated for OpenRouter
- Updated factory.py: Added OpenRouter to LLM and embedder factories
- Updated provider __init__.py files: Exported new OpenRouter functions

Frontend:
- Updated project.ts types: Added 'openrouter' to provider type unions
  - GraphitiProviderConfig extended with OpenRouter fields
- Updated GraphitiStep.tsx: Added OpenRouter to provider arrays
  - LLM_PROVIDERS: 'Multi-provider aggregator'
  - EMBEDDING_PROVIDERS: 'OpenAI-compatible embeddings'
  - Added OpenRouter API key input field with show/hide toggle
  - Link to https://openrouter.ai/keys
- Updated env-handlers.ts: OpenRouter .env generation and parsing
  - Template generation for OPENROUTER_* variables
  - Parsing from .env files with proper type casting

Documentation:
- Updated .env.example with OpenRouter section
  - Configuration examples
  - Popular model recommendations
  - Example configuration (#6)

Fixes #92

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor: address CodeRabbit review comments for OpenRouter

- Add globalOpenRouterApiKey to settings types and store updates
- Initialize openrouterApiKey from global settings
- Update documentation to include OpenRouter in provider lists
- Add OpenRouter handling to get_embedding_dimension() method
- Add openrouter to provider cleanup list
- Add OpenRouter to get_available_providers() function
- Clarify Legacy comment for openrouterLlmModel

These changes complete the OpenRouter integration by ensuring proper
settings persistence and provider detection across the application.

* fix: apply ruff formatting to OpenRouter code

- Break long error message across multiple lines
- Format provider list with one item per line
- Fixes lint CI failure

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(core): add global spec numbering lock to prevent collisions (#209)

Implements distributed file-based locking for spec number coordination
across main project and all worktrees. Previously, parallel spec creation
could assign the same number to different specs (e.g., 042-bmad-task and
042-gitlab-integration both using number 042).

The fix adds SpecNumberLock class that:
- Acquires exclusive lock before calculating spec numbers
- Scans ALL locations (main project + worktrees) for global maximum
- Creates spec directories atomically within the lock
- Handles stale locks via PID-based detection with 30s timeout

Applied to both Python backend (spec_runner.py flow) and TypeScript
frontend (ideation conversion, GitHub/GitLab issue import).

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Fix/ideation status sync (#212)

* fix(ideation): add missing event forwarders for status sync

- Add event forwarders in ideation-handlers.ts for progress, log,
  type-complete, type-failed, complete, error, and stopped events
- Fix ideation-type-complete to load actual ideas array from JSON files
  instead of emitting only the count

Resolves UI getting stuck at 0/3 complete during ideation generation.

* fix(ideation): fix UI not updating after actions

- Fix getIdeationSummary to count only active ideas (exclude dismissed/archived)
  This ensures header stats match the visible ideas count
- Add transformSessionFromSnakeCase to properly transform session data
  from backend snake_case to frontend camelCase on ideation-complete event
- Transform raw session before emitting ideation-complete event

Resolves header showing stale counts after dismissing/deleting ideas.

* fix(ideation): improve type safety and async handling in ideation type completion

- Replace synchronous readFileSync with async fsPromises.readFile in ideation-type-complete handler
- Wrap async file read in IIFE with proper error handling to prevent unhandled promise rejections
- Add type validation for IdeationType with VALID_IDEATION_TYPES set and isValidIdeationType guard
- Add validateEnabledTypes function to filter out invalid type values and log dropped entries
- Handle ENOENT separately

* fix(ideation): improve generation state management and error handling

- Add explicit isGenerating flag to prevent race conditions during async operations
- Implement 5-minute timeout for generation with automatic cleanup and error state
- Add ideation-stopped event emission when process is intentionally killed
- Replace console.warn/error with proper ideation-error events in agent-queue
- Add resetGeneratingTypes helper to transition all generating types to a target state
- Filter out dismissed/

* refactor(ideation): improve event listener cleanup and timeout management

- Extract event handler functions in ideation-handlers.ts to enable proper cleanup
- Return cleanup function from registerIdeationHandlers to remove all listeners
- Replace single generationTimeoutId with Map to support multiple concurrent projects
- Add clearGenerationTimeout helper to centralize timeout cleanup logic
- Extract loadIdeationType IIFE to named function for better error context
- Enhance error logging with projectId,

* refactor: use async file read for ideation and roadmap session loading

- Replace synchronous readFileSync with async fsPromises.readFile
- Prevents blocking the event loop during file operations
- Consistent with async pattern used elsewhere in the codebase
- Improved error handling with proper event emission

* fix(agent-queue): improve roadmap completion handling and error reporting

- Add transformRoadmapFromSnakeCase to convert backend snake_case to frontend camelCase
- Transform raw roadmap data before emitting roadmap-complete event
- Add roadmap-error emission for unexpected errors during completion
- Add roadmap-error emission when project path is unavailable
- Remove duplicate ideation-type-complete emission from error handler (event already emitted in loadIdeationType)
- Update error log message

* fix: add future annotations import to discovery.py (#229)

Adds 'from __future__ import annotations' to spec/discovery.py for
Python 3.9+ compatibility with type hints.

This completes the Python compatibility fixes that were partially
applied in previous commits. All 26 analysis and spec Python files
now have the future annotations import.

Related: #128

Co-authored-by: Joris Slagter <mail@jorisslagter.nl>

* fix: resolve Python detection and backend packaging issues (#241)

* fix: resolve Python detection and backend packaging issues

- Fix backend packaging path (auto-claude -> backend) to match path-resolver.ts expectations
- Add future annotations import to config_parser.py for Python 3.9+ compatibility
- Use findPythonCommand() in project-context-handlers to prioritize Homebrew Python
- Improve Python detection to prefer Homebrew paths over system Python on macOS

This resolves the following issues:
- 'analyzer.py not found' error due to incorrect packaging destination
- TypeError with 'dict | None' syntax on Python < 3.10
- Wrong Python interpreter being used (system Python instead of Homebrew Python 3.10+)

Tested on macOS with packaged app - project index now loads successfully.

* refactor: address PR review feedback

- Extract findHomebrewPython() helper to eliminate code duplication between
  findPythonCommand() and getDefaultPythonCommand()
- Remove hardcoded version-specific paths (python3.12) and rely only on
  generic Homebrew symlinks for better maintainability
- Remove unnecessary 'from __future__ import annotations' from config_parser.py
  since backend requires Python 3.12+ where union types are native

These changes make the code more maintainable, less fragile to Python version
changes, and properly reflect the project's Python 3.12+ requirement.

* Feat/Auto Fix Github issues and do extensive AI PR reviews (#250)

* feat(github): add GitHub automation system for issues and PRs

Implements comprehensive GitHub automation with three major components:

1. Issue Auto-Fix: Automatically creates specs from labeled issues
   - AutoFixButton component with progress tracking
   - useAutoFix hook for config and queue management
   - Backend handlers for spec creation from issues

2. GitHub PRs Tool: AI-powered PR review sidebar
   - New sidebar tab (Cmd+Shift+P) alongside GitHub Issues
   - PRList/PRDetail components for viewing PRs
   - Review system with findings by severity
   - Post review comments to GitHub

3. Issue Triage: Duplicate/spam/feature-creep detection
   - Triage handlers with label application
   - Configurable detection thresholds

Also adds:
- Debug logging (DEBUG=true) for all GitHub handlers
- Backend runners/github module with orchestrator
- AI prompts for PR review, triage, duplicate/spam detection
- dev:debug npm script for development with logging

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

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

* fix(github-runner): resolve import errors for direct script execution

Changes runner.py and orchestrator.py to handle both:
- Package import: `from runners.github import ...`
- Direct script: `python runners/github/runner.py`

Uses try/except pattern for relative vs direct imports.

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

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

* fix(github): correct argparse argument order for runner.py

Move --project global argument before subcommand so argparse can
correctly parse it. Fixes "unrecognized arguments: --project" error.

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

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

* logs when debug mode is on

* refactor(github): extract service layer and fix linting errors

Major refactoring to improve maintainability and code quality:

Backend (Python):
- Extracted orchestrator.py (2,600 → 835 lines, 68% reduction) into 7 service modules:
  - prompt_manager.py: Prompt template management
  - response_parsers.py: AI response parsing
  - pr_review_engine.py: PR review orchestration
  - triage_engine.py: Issue triage logic
  - autofix_processor.py: Auto-fix workflow
  - batch_processor.py: Batch issue handling
- Fixed 18 ruff linting errors (F401, C405, C414, E741):
  - Removed unused imports (BatchValidationResult, AuditAction, locked_json_write)
  - Optimized collection literals (set([n]) → {n})
  - Removed unnecessary list() calls
  - Renamed ambiguous variable 'l' to 'label' throughout

Frontend (TypeScript):
- Refactored IPC handlers (19% overall reduction) with shared utilities:
  - autofix-handlers.ts: 1,042 → 818 lines
  - pr-handlers.ts: 648 → 543 lines
  - triage-handlers.ts: 437 lines (no duplication)
- Created utils layer: logger, ipc-communicator, project-middleware, subprocess-runner
- Split github-store.ts into focused stores: issues, pr-review, investigation, sync-status
- Split ReviewFindings.tsx into focused components

All imports verified, type checks passing, linting clean.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Revert "Feat/Auto Fix Github issues and do extensive AI PR reviews (#250)" (#251)

This reverts commit 348de6dfe793ab111043677c61b8452bc5ecb2cc.

* feat: add i18n internationalization system (#248)

* Add multilingual support and i18n integration

- Implemented i18n framework using `react-i18next` for translation management.
- Added support for English and French languages with translation files.
- Integrated language selector into settings.
- Updated all text strings in UI components to use translation keys.
- Ensured smooth language switching with live updates.

* Migrate remaining hard-coded strings to i18n system

- TaskCard: status labels, review reasons, badges, action buttons
- PhaseProgressIndicator: execution phases, progress labels
- KanbanBoard: drop zone, show archived, tooltips
- CustomModelModal: dialog title, description, labels
- ProactiveSwapListener: account switch notifications
- AgentProfileSelector: phase labels, custom configuration
- GeneralSettings: agent framework option

Added translation keys for en/fr locales in tasks.json, common.json,
and settings.json for complete i18n coverage.

* Add i18n support to dialogs and settings components

- AddFeatureDialog: form labels, validation messages, buttons
- AddProjectModal: dialog steps, form fields, actions
- RateLimitIndicator: rate limit notifications
- RateLimitModal: account switching, upgrade prompts
- AdvancedSettings: updates and notifications sections
- ThemeSettings: theme selection labels
- Updated dialogs.json locales (en/fr)

* Fix truncated 'ready' message in dialogs locales

* Fix backlog terminology in i18n locales

Change "Planning"/"Planification" to standard PM term "Backlog"

* Migrate settings navigation and integration labels to i18n

- AppSettings: nav items, section titles, buttons
- IntegrationSettings: Claude accounts, auto-switch, API keys labels
- Added settings nav/projectSections/integrations translation keys
- Added buttons.saving to common translations

* Migrate AgentProfileSettings and Sidebar init dialog to i18n

- AgentProfileSettings: migrate phase config labels, section title,
  description, and all hardcoded strings to settings namespace
- Sidebar: migrate init dialog strings to dialogs namespace with
  common buttons from common namespace
- Add new translation keys for agent profile settings and update dialog

* Migrate AppSettings navigation labels to i18n

- Add useTranslation hook to AppSettings.tsx
- Replace hardcoded section labels with dynamic translations
- Add projectSections translations for project settings nav
- Add rerunWizardDescription translation key

* Add explicit typing to notificationItems array

Import NotificationSettings type and use keyof to properly type
the notification item keys, removing manual type assertion.

* fix: update path resolution for ollama_model_detector.py in memory handlers (#263)

* ci: implement enterprise-grade PR quality gates and security scanning (#266)

* ci: implement enterprise-grade PR quality gates and security scanning

* ci: implement enterprise-grade PR quality gates and security scanning

* fix:pr comments and improve code

* fix: improve commit linting and code quality

* Removed the dependency-review job (i added it)

* fix: address CodeRabbit review comments

- Expand scope pattern to allow uppercase, underscores, slashes, dots
- Add concurrency control to cancel duplicate security scan runs
- Add explanatory comment for Bandit CLI flags
- Remove dependency-review job (requires repo settings)

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

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

* docs: update commit lint examples with expanded scope patterns

Show slashes and dots in scope examples to demonstrate
the newly allowed characters (api/users, package.json)

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

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

* chore: remove feature request issue template

Feature requests are directed to GitHub Discussions
via the issue template config.yml

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

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

* fix: address security vulnerabilities in service orchestrator

- Fix port parsing crash on malformed docker-compose entries
- Fix shell injection risk by using shlex.split() with shell=False

Prevents crashes when docker-compose.yml contains environment
variables in port mappings (e.g., '${PORT}:8080') and eliminates
shell injection vulnerabilities in subprocess execution.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(github): add automated PR review with follow-up support (#252)

* feat(github): add GitHub automation system for issues and PRs

Implements comprehensive GitHub automation with three major components:

1. Issue Auto-Fix: Automatically creates specs from labeled issues
   - AutoFixButton component with progress tracking
   - useAutoFix hook for config and queue management
   - Backend handlers for spec creation from issues

2. GitHub PRs Tool: AI-powered PR review sidebar
   - New sidebar tab (Cmd+Shift+P) alongside GitHub Issues
   - PRList/PRDetail components for viewing PRs
   - Review system with findings by severity
   - Post review comments to GitHub

3. Issue Triage: Duplicate/spam/feature-creep detection
   - Triage handlers with label application
   - Configurable detection thresholds

Also adds:
- Debug logging (DEBUG=true) for all GitHub handlers
- Backend runners/github module with orchestrator
- AI prompts for PR review, triage, duplicate/spam detection
- dev:debug npm script for development with logging

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

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

* fix(github-runner): resolve import errors for direct script execution

Changes runner.py and orchestrator.py to handle both:
- Package import: `from runners.github import ...`
- Direct script: `python runners/github/runner.py`

Uses try/except pattern for relative vs direct imports.

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

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

* fix(github): correct argparse argument order for runner.py

Move --project global argument before subcommand so argparse can
correctly parse it. Fixes "unrecognized arguments: --project" error.

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

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

* logs when debug mode is on

* refactor(github): extract service layer and fix linting errors

Major refactoring to improve maintainability and code quality:

Backend (Python):
- Extracted orchestrator.py (2,600 → 835 lines, 68% reduction) into 7 service modules:
  - prompt_manager.py: Prompt template management
  - response_parsers.py: AI response parsing
  - pr_review_engine.py: PR review orchestration
  - triage_engine.py: Issue triage logic
  - autofix_processor.py: Auto-fix workflow
  - batch_processor.py: Batch issue handling
- Fixed 18 ruff linting errors (F401, C405, C414, E741):
  - Removed unused imports (BatchValidationResult, AuditAction, locked_json_write)
  - Optimized collection literals (set([n]) → {n})
  - Removed unnecessary list() calls
  - Renamed ambiguous variable 'l' to 'label' throughout

Frontend (TypeScript):
- Refactored IPC handlers (19% overall reduction) with shared utilities:
  - autofix-handlers.ts: 1,042 → 818 lines
  - pr-handlers.ts: 648 → 543 lines
  - triage-handlers.ts: 437 lines (no duplication)
- Created utils layer: logger, ipc-communicator, project-middleware, subprocess-runner
- Split github-store.ts into focused stores: issues, pr-review, investigation, sync-status
- Split ReviewFindings.tsx into focused components

All imports verified, type checks passing, linting clean.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fixes during testing of PR

* feat(github): implement PR merge, assign, and comment features

- Add auto-assignment when clicking "Run AI Review"
- Implement PR merge functionality with squash method
- Add ability to post comments on PRs
- Display assignees in PR UI
- Add Approve and Merge buttons when review passes
- Update backend gh_client with pr_merge, pr_comment, pr_assign methods
- Create IPC handlers for new PR operations
- Update TypeScript interfaces and browser mocks

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Improve PR review AI

* fix(github): use temp files for PR review posting to avoid shell escaping issues

When posting PR reviews with findings containing special characters (backticks,
parentheses, quotes), the shell command was interpreting them as commands instead
of literal text, causing syntax errors.

Changed both postPRReview and postPRComment handlers to write the body content
to temporary files and use gh CLI's --body-file flag instead of --body with
inline content. This safely handles ALL special characters without escaping issues.

Fixes shell errors when posting reviews with suggested fixes containing code snippets.

* fix(i18n): add missing GitHub PRs translation and document i18n requirements

Fixed missing translation key for GitHub PRs feature that was causing
"items.githubPRs" to display instead of the proper translated text.

Added comprehensive i18n guidelines to CLAUDE.md to ensure all future
frontend development follows the translation key pattern instead of
using hardcoded strings.

Also fixed missing deletePRReview mock function in browser-mock.ts
to resolve TypeScript compilation errors.

Changes:
- Added githubPRs translation to en/navigation.json
- Added githubPRs translation to fr/navigation.json
- Added Development Guidelines section to CLAUDE.md with i18n requirements
- Documented translation file locations and namespace usage patterns
- Added deletePRReview mock function to browser-mock.ts

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix ui loading

* Github PR fixes

* improve claude.md

* lints/tests

* fix(github): handle PRs exceeding GitHub's 20K line diff limit

- Add PRTooLargeError exception for large PR detection
- Update pr_diff() to catch and raise PRTooLargeError for HTTP 406 errors
- Gracefully handle large PRs by skipping full diff and using individual file patches
- Add diff_truncated flag to PRContext to track when diff was skipped
- Large PRs will now review successfully using per-file diffs instead of failing

Fixes issue with PR #252 which has 100+ files exceeding the 20,000 line limit.

* fix: implement individual file patch fetching for large PRs

The PR review was getting stuck for large PRs (>20K lines) because when we
skipped the full diff due to GitHub API limits, we had no code to analyze.
The individual file patches were also empty, leaving the AI with just
file names and metadata.

Changes:
- Implemented _get_file_patch() to fetch individual patches via git diff
- Updated PR review engine to build composite diff from file patches when
  diff_truncated is True
- Added missing 'state' field to PRContext dataclass
- Limits composite diff to first 50 files for very large PRs
- Shows appropriate warnings when using reconstructed diffs

This allows AI review to proceed with actual code analysis even when the
full PR diff exceeds GitHub's limits.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* 1min reduction

* docs: add GitHub Sponsors funding configuration

Enable the Sponsor button on the repository by adding FUNDING.yml
with the AndyMik90 GitHub Sponsors profile.

* feat(github-pr): add orchestrating agent for thorough PR reviews

Implement a new Opus 4.5 orchestrating agent that performs comprehensive
PR reviews regardless of size. Key changes:

- Add orchestrator_reviewer.py with strategic review workflow
- Add review_tools.py with subagent spawning capabilities
- Add pr_orchestrator.md prompt emphasizing thorough analysis
- Add pr_security_agent.md and pr_quality_agent.md subagent prompts
- Integrate orchestrator into pr_review_engine.py with config flag
- Fix critical bug where findings were extracted but not processed
  (indentation issue in _parse_orchestrator_output)

The orchestrator now correctly identifies issues in PRs that were
previously approved as "trivial". Testing showed 7 findings detected
vs 0 before the fix.

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

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

* i18n

* fix(github-pr): restrict pr_reviewer to read-only permissions

The PR review agent was using qa_reviewer agent type which has Bash
access, allowing it to checkout branches and make changes during
review. Created new pr_reviewer agent type with BASE_READ_TOOLS only
(no Bash, no writes, no auto-claude tools).

This prevents the PR review from accidentally modifying code or
switching branches during analysis.

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

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

* fix(github-pr): robust category mapping and JSON parsing for PR review

The orchestrator PR review was failing to extract findings because:

1. AI generates category names like 'correctness', 'consistency', 'testing'
   that aren't in our ReviewCategory enum - added flexible mapping

2. JSON sometimes embedded in markdown code blocks (```json) which broke
   parsing - added code block extraction as first parsing attempt

Changes:
- Add _CATEGORY_MAPPING dict to map AI categories to valid enum values
- Add _map_category() helper function with fallback to QUALITY
- Add severity parsing with fallback to MEDIUM
- Add markdown code block detection (```json) before raw JSON parsing
- Add _extract_findings_from_data() helper to reduce code duplication
- Apply same fixes to review_tools.py for subagent parsing

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

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

* fix(pr-review): improve post findings UX with batch support and feedback

- Fix post findings failing on own PRs by falling back from REQUEST_CHANGES
  to COMMENT when GitHub returns 422 error
- Change status badge to show "Reviewed" instead of "Commented" until
  findings are actually posted to GitHub
- Add success notification when findings are posted (auto-dismisses after 3s)
- Add batch posting support: track posted findings, show "Posted" badge,
  allow posting remaining findings in additional batches
- Show loading state on button while posting

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

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

* fix(github): resolve stale timestamp and null author bugs

- Fix stale timestamp in batch_issues.py: Move updated_at assignment
  BEFORE to_dict() serialization so the saved JSON contains the correct
  timestamp instead of the old value

- Fix AttributeError in context_gatherer.py: Handle null author/user
  fields when GitHub API returns null for deleted/suspended users
  instead of an empty object

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

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

* fix(security): address all high and medium severity PR review findings

HIGH severity fixes:
- Command Injection in autofix-handlers.ts: Use execFileSync with args array
- Command Injection in pr-handlers.ts (3 locations): Use execFileSync + validation
- Command Injection in triage-handlers.ts: Use execFileSync + label validation
- Token Exposure in bot_detection.py: Pass token via GH_TOKEN env var

MEDIUM severity fixes:
- Environment variable leakage in subprocess-runner.ts: Filter to safe vars only
- Debug logging in subprocess-runner.ts: Only log in development mode
- Delimiter escape bypass in sanitize.py: Use regex pattern for variations
- Insecure file permissions in trust.py: Use os.open with 0o600 mode
- No file locking in learning.py: Use FileLock + atomic_write utilities
- Bare except in confidence.py: Log error with specific exception info
- Fragile module import in pr_review_engine.py: Import at module level
- State transition validation in models.py: Enforce can_transition_to()

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

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

* PR followup

* fix(security): add usedforsecurity=False to MD5 hash calls

MD5 is used for generating unique IDs/cache keys, not for security purposes.
Adding usedforsecurity=False resolves Bandit B324 warnings.

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

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

* fix(security): address all high-priority PR review findings

Fixes 5 high-priority issues from Auto Claude PR Review:

1. orchestrator_reviewer.py: Token budget tracking now increments
   total_tokens from API response usage data

2. pr_review_engine.py: Async exceptions now re-raise RuntimeError
   instead of silently returning empty results

3. batch_issues.py: IssueBatch.save() now uses locked_json_write
   for atomic file operations with file locking

4. project-middleware.ts: Added validateProjectPath() to prevent
   path traversal attacks (checks absolute, no .., exists, is dir)

5. orchestrator.py: Exception handling now logs full traceback and
   preserves exception type/context in error messages

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

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

* fix(security): address all high-priority PR review findings

Fixes 5 high-priority issues from Auto Claude PR Review:

1. orchestrator_reviewer.py: Token budget tracking now increments
   total_tokens from API response usage data

2. pr_review_engine.py: Async exceptions now re-raise RuntimeError
   instead of silently returning empty results

3. batch_issues.py: IssueBatch.save() now uses locked_json_write
   for atomic file operations with file locking

4. project-middleware.ts: Added validateProjectPath() to prevent
   path traversal attacks (checks absolute, no .., exists, is dir)

5. orchestrator.py: Exception handling now logs full traceback and
   preserves exception type/context in error messages

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

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

* feat(ui): add PR status labels to list view

Add secondary status badges to the PR list showing review state at a glance:
- "Changes Requested" (warning) - PRs with blocking issues (critical/high)
- "Ready to Merge" (green) - PRs with only non-blocking suggestions
- "Ready for Follow-up" (blue) - PRs with new commits since last review

The "Ready for Follow-up" badge uses a cached new commits check from the
store, only shown after the detail view confirms new commits via SHA
comparison. This prevents false positives from PR updatedAt timestamp
changes (which can happen from comments, labels, etc).

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

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

* PR labels

* auto-claude: Initialize subtask-based implementation plan

- Workflow type: feature
- Phases: 3
- Subtasks: 6
- Ready for autonomous implementation

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* chore(deps): bump vitest from 4.0.15 to 4.0.16 in /apps/frontend (#272)

Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.0.15 to 4.0.16.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.0.16/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 4.0.16
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump @electron/rebuild in /apps/frontend (#271)

Bumps [@electron/rebuild](https://github.com/electron/rebuild) from 3.7.2 to 4.0.2.
- [Release notes](https://github.com/electron/rebuild/releases)
- [Commits](https://github.com/electron/rebuild/compare/v3.7.2...v4.0.2)

---
updated-dependencies:
- dependency-name: "@electron/rebuild"
  dependency-version: 4.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>

* fix(paths): normalize relative paths to posix (#239)

Co-authored-by: danielfrey63 <daniel.frey@sbb.ch>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>

* fix: accept bug_fix workflow_type alias during planning (#240)

* fix(planning): accept bug_fix workflow_type alias

* style(planning): ruff format

* fix: refatored common logic

* fix: remove ruff errors

* fix: remove duplicate _normalize_workflow_type method

Remove the incorrectly placed duplicate method inside ContextLoader class.
The module-level function is the correct implementation being used.

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

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

---------

Co-authored-by: danielfrey63 <daniel.frey@sbb.ch>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
Co-authored-by: AndyMik90 <andre@mikalsenutvikling.no>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ci): use develop branch for dry-run builds in beta-release workflow (#276)

When dry_run=true, the workflow skipped creating the version tag but
build jobs still tried to checkout that non-existent tag, causing all
4 platform builds to fail with "git failed with exit code 1".

Now build jobs checkout develop branch for dry runs while still using
the version tag for real releases.

Closes: GitHub Actions run #20464082726

* chore(deps): bump typescript-eslint in /apps/frontend (#269)

Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.49.0 to 8.50.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.50.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.50.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>

* chore(deps): bump jsdom from 26.1.0 to 27.3.0 in /apps/frontend (#268)

Bumps [jsdom](https://github.com/jsdom/jsdom) from 26.1.0 to 27.3.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/main/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/26.1.0...27.3.0)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-version: 27.3.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>

* fix(ci): use correct electron-builder arch flags (#278)

The project switched from pnpm to npm, which handles script argument
passing differently. pnpm adds a -- separator that caused electron-builder
to ignore the --arch argument, but npm passes it directly.

Since --arch is a deprecated electron-builder argument, use the
recommended flags instead:
- --arch=x64 → --x64
- --arch=arm64 → --arm64

This fixes Mac Intel and ARM64 builds failing with "Unknown argument: arch"

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): resolve CodeQL file system race conditions and unused variables (#277)

* fix(security): resolve CodeQL file system race conditions and unused variables

Fix high severity CodeQL alerts:
- Remove TOCTOU (time-of-check-time-of-use) race conditions by eliminating
  existsSync checks followed by file operations. Use try-catch instead.
- Files affected: pr-handlers.ts, spec-utils.ts

Fix unused variable warnings:
- Remove unused imports (FeatureModelConfig, FeatureThinkingConfig,
  withProjectSyncOrNull, getBackendPath, validateRunner, githubFetch)
- Prefix intentionally unused destructured variables with underscore
- Remove unused local variables (existing, actualEvent)
- Files affected: pr-handlers.ts, autofix-handlers.ts, triage-handlers.ts,
  PRDetail.tsx, pr-review-store.ts

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

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

* fix(security): resolve remaining CodeQL alerts for TOCTOU, network data validation, and unused variables

Address CodeRabbit and CodeQL security alerts from PR #277 review:

- HIGH: Fix 12+ file system race conditions (TOCTOU) by replacing
  existsSync() checks with try/catch blocks in pr-handlers.ts,
  autofix-handlers.ts, triage-handlers.ts, and spec-utils.ts
- MEDIUM: Add sanitizeNetworkData() function to validate/sanitize
  GitHub API data before writing to disk, preventing injection attacks
- Clean up 20+ unused variables, imports, and useless assignments
  across frontend components and handlers
- Fix Python Protocol typing in testing.py (add return type annotations)

All changes verified with TypeScript compilation and ESLint (no errors).

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(github): resolve follow-up review API issues

- Fix gh_client.py: use query string syntax for `since` parameter instead
  of `-f` flag which sends POST body fields, causing GitHub API errors
- Fix followup_reviewer.py: use raw Anthropic client for message API calls
  instead of ClaudeSDKClient which is for agent sessions

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

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

* chore(deps): bump @xterm/xterm from 5.5.0 to 6.0.0 in /apps/frontend (#270)

* chore(deps): bump @xterm/xterm from 5.5.0 to 6.0.0 in /apps/frontend

Bumps [@xterm/xterm](https://github.com/xtermjs/xterm.js) from 5.5.0 to 6.0.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/5.5.0...6.0.0)

---
updated-dependencies:
- dependency-name: "@xterm/xterm"
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(deps): update xterm addons for 6.0.0 compatibility and use public APIs

CRITICAL: Updated all xterm addons to versions compatible with xterm 6.0.0:
- @xterm/addon-fit: ^0.10.0 → ^0.11.0
- @xterm/addon-serialize: ^0.13.0 → ^0.14.0
- @xterm/addon-web-links: ^0.11.0 → ^0.12.0
- @xterm/addon-webgl: ^0.18.0 → ^0.19.0

HIGH: Refactored scroll-controller.ts to use public xterm APIs:
- Replaced internal _core access with public buffer/scroll APIs
- Uses onScroll and onWriteParsed events for scroll tracking
- Uses scrollLines() for scroll position restoration
- Proper IDisposable cleanup for event listeners
- Falls back gracefully if onWriteParsed is not available

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

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: AndyMik90 <andre@mikalsenutvikling.no>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ci): add write permissions to beta-release update-version job

The update-version job needs contents: write permission to push the
version bump commit and tag to the repository. Without this, the
workflow fails with a 403 error when trying to git push.

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

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

* fix: resolve spawn python ENOENT error on Linux by using getAugmentedEnv() (#281)

- Use getAugmentedEnv() in project-context-handlers.ts to ensure Python is in PATH
- Add /usr/bin and /usr/sbin to Linux paths in env-utils.ts for system Python
- Fixes GUI-launched apps not inheriting shell environment on Ubuntu 24.04

Fixes #215

Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>

* feat(python): bundle Python 3.12 with packaged Electron app (#284)

* feat(python): bundle Python 3.12 with packaged Electron app

Resolves issue #258 where users with Python aliases couldn't run the app
because shell aliases aren't visible to Electron's subprocess calls.

Changes:
- Add download-python.cjs script to fetch python-build-standalone
- Bundle Python 3.12.8 in extraResources for packaged apps
- Update python-detector.ts to prioritize bundled Python
- Add Python caching to CI workflows for faster builds

Packaged apps now include Python (~35MB), eliminating the need for users
to have Python installed. Dev mode still falls back to system Python.

Closes #258

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

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

* fix: address PR review feedback for Python bundling

Security improvements:
- Add SHA256 checksum verification for downloaded Python binaries
- Replace execSync with spawnSync to prevent command injection
- Add input validation to prevent log injection from CLI args
- Add download timeout (5 minutes) and redirect limit (10)
- Proper file/connection cleanup on errors

Bug fixes:
- Fix platform naming mismatch: use "mac"/"win" (electron-builder)
  instead of "darwin"/"win32" (Node.js) for output directories
- Handle empty path edge case in parsePythonCommand

Improvements:
- Add restore-keys to CI cache steps for better cache hit rates
- Improve error messages and logging

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

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

* fix mac node.js naming

* security: add SHA256 checksums for all Python platforms

Fetched actual checksums from python-build-standalone release:
- darwin-arm64: abe1de24...
- darwin-x64: 867c1af1...
- win32-x64: 1a702b34...
- linux-x64: 698e53b2...
- linux-arm64: fb983ec8...

All platforms now have cryptographic verification for downloaded
Python binaries, eliminating the supply chain risk.

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

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

* chore: add python-runtime to root .gitignore

Ensures bundled Python runtime is ignored from both root and
frontend .gitignore files.

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(frontend): validate backend source path before using it (#287)

* fix(frontend): validate backend source path before using it

The path resolver was returning invalid autoBuildPath settings without
validating they contained the required backend files. When settings
pointed to a legacy /auto-claude/ directory (missing requirements.txt
and analyzer.py), the project indexer would fail with "can't open file"
errors.

Now validates that all source paths contain requirements.txt before
returning them, falling back to bundled source path detection when
the configured path is invalid.

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

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

* auto-claude: Initialize subtask-based implementation plan

- Workflow type: feature
- Phases: 4
- Subtasks: 9
- Ready for autonomous implementation

Parallel execution enabled: phases 1 and 2 can run simultaneously

* auto-claude: Initialize subtask-based implementation plan

- Workflow type: investigation
- Phases: 5
- Subtasks: 13
- Ready for autonomous implementation

* fix merge conflict check loop

* fix(frontend): add warning when fallback path is also invalid

Address CodeRabbit review feedback - the fallback path in
getBundledSourcePath() was returning an unvalidated path which could
still cause the same analyzer.py error. Now logs a warning when the
fallback path also lacks requirements.txt.

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Potential fix for code scanning alert no. 224: Uncontrolled command line (#285)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(frontend): support archiving tasks across all worktree locations (#286)

* archive across all worktress and if not in folder

* fix(frontend): address PR security and race condition issues

- Add taskId validation to prevent path traversal attacks
- Fix TOCTOU race conditions in archiveTasks by removing existsSync
- Fix TOCTOU race conditions in unarchiveTasks by removing existsSync

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(github): add explicit GET method to gh api comment fetches (#294)

The gh api command defaults to POST for comment endpoints, causing
GitHub to reject the 'since' query parameter as an invalid POST body
field. Adding --method GET explicitly forces a GET request, allowing
the since parameter to work correctly for fetching comments.

This completes the fix started in f1cc5a09 which only changed from
-f flag to query string syntax but didn't address the HTTP method.

* feat: enhance the logs for the commit linting stage (#293)

* ci: implement enterprise-grade PR quality gates and security scanning

* ci: implement enterprise-grade PR quality gates and security scanning

* fix:pr comments and improve code

* fix: improve commit linting and code quality

* Removed the dependency-review job (i added it)

* fix: address CodeRabbit review comments

- Expand scope pattern to allow uppercase, underscores, slashes, dots
- Add concurrency control to cancel duplicate security scan runs
- Add explanatory comment for Bandit CLI flags
- Remove dependency-review job (requires repo settings)

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

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

* docs: update commit lint examples with expanded scope patterns

Show slashes and dots in scope examples to demonstrate
the newly allowed characters (api/users, package.json)

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

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

* chore: remove feature request issue template

Feature requests are directed to GitHub Discussions
via the issue template config.yml

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

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

* fix: address security vulnerabilities in service orchestrator

- Fix port parsing crash on malformed docker-compose entries
- Fix shell injection risk by using shlex.split() with shell=False

Prevents crashes when docker-compose.yml contains environment
variables in port mappings (e.g., '${PORT}:8080') and eliminates
shell injection vulnerabilities in subprocess execution.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(ci): improve PR title validation error messages with examples

Add helpful console output when PR title validation fails:
- Show expected format and valid types
- Provide examples of valid PR titles
- Display the user's current title
- Suggest fixes based on keywords in the title
- Handle verb variations (fixed, adding, updated, etc.)
- Show placeholder when description is empty after cleanup

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

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

* lower coverage

* feat: improve status gate to label correctly based on required checks

* fix(ci): address PR review findings for security and efficiency

- Add explicit permissions block to ci.yml (least privilege principle)
- Skip duplicate test run for Python 3.12 (tests with coverage only)
- Sanitize PR title in markdown output to prevent injection

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

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

* fix typo

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(merge,oauth): add path-aware AI merge resolution and device code streaming (#296)

* improve/merge-confclit-layer

* improve AI resolution

* fix caching on merge conflicts

* imrpove merge layer with rebase

* fix(github): add OAuth authentication to follow-up PR review

The follow-up PR review AI analysis was failing with "Could not resolve
authentication method" because AsyncAnthropic() was instantiated without
credentials. The codebase uses OAuth tokens (not ANTHROPIC_API_KEY), so
the client needs the auth_token parameter.

Uses get_auth_token() from core.auth to retrieve the OAuth token from
environment variables or macOS Keychain, matching how initial reviews
authenticate via create_client().

* fix(merge): add validation to prevent AI writing natural language to files

When AI merge receives truncated file contents (due to character limits),
it sometimes responds with explanations like "I need to see the complete
file contents..." instead of actual merged code. This garbage was being
written directly to source files.

Adds two validation layers after AI merge:
1. Natural language detection - catches patterns like "I need to", "Let me"
2. Syntax validation - uses esbuild to verify TypeScript/JavaScript syntax

If either validation fails, the merge returns an error instead of writing
invalid content to the file.

Also adds project_dir field to ParallelMergeTask to enable syntax validation.

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

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

* fix(merge): skip git merge when AI already resolved path-mapped files

When AI successfully merges path-mapped files (due to file renames
between branches), the check only looked at `conflicts_resolved` which
was 0 for path-mapped cases. This caused the code to fall through to
`git merge` which then failed with conflicts.

Now also checks `files_merged` and `ai_assisted` stats to determine
if AI has already handled the merge. When files are AI-merged, they're
already written and staged - no need for git merge.

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

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

* fix device code issue with github

* fix(frontend): remember GitHub auth method (OAuth vs PAT) in settings

Previously, after authenticating via GitHub OAuth, the settings page
would show "Personal Access Token" input even though OAuth was used.
This was confusing for users who expected to see their OAuth status.

Added githubAuthMethod field to track how authentication was performed.
Settings UI now shows "Authenticated via GitHub OAuth" when OAuth was
used, with option to switch to manual token if needed. The auth method
persists across settings reopening.

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

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

* refactor(backend): centralize OAuth client creation in core/client.py

- Add create_message_client() for simple message API calls
- Refactor followup_reviewer.py to use centralized client factory
- Remove direct anthropic.AsyncAnthropic import from followup_reviewer
- Add proper ValueError handling for missing OAuth token
- Update docstrings to document both client factories

This ensures all AI interactions use the centralized OAuth authentication
in core/, avoiding direct ANTHROPIC_API_KEY usage per CLAUDE.md guidelines.

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

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

* fix(frontend): remove unused statusColor variable in WorkspaceStatus

Dead code cleanup - the statusColor variable was computed but never
used in the component.

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

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

* fix(tests): add BrowserWindow mock to oauth-handlers tests

The sendDeviceCodeToRenderer function uses BrowserWindow.getAllWindows()
which wasn't mocked, causing unhandled rejection errors in tests.

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

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

* fix(backend): use ClaudeSDKClient instead of raw anthropic SDK

Remove direct anthropic SDK import from core/client.py and update
followup_reviewer.py to use ClaudeSDKClient directly as per project
conventions. All AI interactions should use claude-agent-sdk.

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

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

* fix(backend): add debug logging for AI response in followup_reviewer

Add logging to diagnose why AI review returns no JSON - helps identify
if response is in thinking blocks vs text blocks.

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Fix/2.7.2 fixes (#300)

* fix(frontend): prevent false stuck detection for ai_review tasks

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 <noreply@anthropic.com>

* ci(beta-release): use tag-based versioning instead of modifying package.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 <noreply@anthropic.com>

* fix(ollama): add packaged app path resolution for Ollama detector script

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 #129

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

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

* refactor(paths): remove legacy auto-claude path fallbacks

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 <noreply@anthropic.com>

* fix(frontend): address PR review feedback from Auto Claude and bots

Fixes from PR #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 <noreply@anthropic.com>

* fix(frontend): validate empty profile slug after sanitization

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 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix: stop tracking spec files in git (#295)

* fix: stop tracking spec files in git

- Remove git commit instructions from planner.md for spec files
- Spec files (implementation_plan.json, init.sh, build-progress.txt) should be gitignored
- Untrack existing spec files that were accidentally committed
- AI agents should only commit code changes, not spec metadata

The .auto-claude/specs/ directory is gitignored by design - spec files are
local project metadata that shouldn't be version controlled.

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

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

* fix(prompts): remove git commit instructions for gitignored spec files

The spec files (build-progress.txt, qa_report.md, implementation_plan.json,
QA_FIX_REQUEST.md) are all stored in .auto-claude/specs/ which is gitignored.

Removed instructions telling agents to commit these files, replaced with
notes explaining they're tracked automatically by the framework.

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(build): add --force-local flag to tar on Windows (#303)

On Windows, paths like D:\path are misinterpreted by tar as remote
host:path syntax (Unix tar convention). Adding --force-local tells
tar to treat colons as part of the filename, fixing the extraction
failure in GitHub Actions Windows builds.

Error was: "tar (child): Cannot connect to D: resolve failed"

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(build): use PowerShell for tar extraction on Windows

The previous fix using --force-local and path conversion still failed
due to shell escaping issues. PowerShell handles Windows paths natively
and has built-in tar support on Windows 10+, avoiding all path escaping
problems.

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

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

* fix(github): add augmented PATH env to all gh CLI calls

When running from a packaged macOS app (.dmg), the PATH environment
variable doesn't include common locations like /opt/homebrew/bin where
gh is typically installed via Homebrew.

The getAugmentedEnv() function was already being used in some places
but was missing from:
- spawn() call in registerStartGhAuth
- execSync calls for gh auth token, gh api user, gh repo list
- execFileSync calls for gh api, gh repo create
- execFileSync calls in pr-handlers.ts and triage-handlers.ts

This caused "gh: command not found" errors when connecting projects
to GitHub in the packaged app.

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

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

* fix(build): use explicit Windows System32 tar path (#308)

The previous PowerShell fix still found Git Bash's /usr/bin/tar which
interprets D: as a remote host. Using the explicit path to Windows'
built-in bsdtar (C:\Windows\System32\tar.exe) avoids this issue.

Windows Server 2019+ (GitHub Actions) has bsdtar in System32.

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* chore(ci): cancel in-progress runs (#302)

Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
Co-authored-by: Alex <63423455+AlexMadera@users.noreply.github.com>

* fix(python): use venv Python for all services to fix dotenv errors (#311)

* fix(python): use venv Python for all services to fix dotenv errors

Services were spawning Python processes using findPythonCommand() which
returns the bundled Python directly. However, dependencies like python-dotenv
are only installed in the venv created from the bundled Python.

Changes:
- Add getConfiguredPythonPath() helper that returns venv Python when ready
- Update all services to use venv Python instead of bundled Python directly:
  - memory-service.ts
  - memory-handlers.ts
  - agent-process.ts
  - changelog-service.ts
  - title-generator.ts
  - insights/config.ts
  - project-context-handlers.ts
  - worktree-handlers.ts
- Fix availability checks to use findPythonCommand() (can return null)
- Add python:verify script for bundling verification

The flow now works correctly:
1. App starts → findPythonCommand() finds bundled Python
2. pythonEnvManager creates venv using bundled Python
3. pip installs dependencies (dotenv, claude-agent-sdk, etc.)
4. All services use venv Python → has all dependencies

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

Co-Authored-By: Claude <noreply@anthropic.com>

* fix lintin and test

---------

Co-authored-by: Claude <noreply@anthropic.com>

* fix(updater): proper semver comparison for pre-release versions (#313)

Fixes the beta auto-update bug where the app was offering downgrades
(e.g., showing v2.7.1 as "new version available" when on v2.7.2-beta.6).

Changes:
- version-manager.ts: New parseVersion() function that separates base
  version from pre-release suffix. Updated compareVersions() to handle
  pre-release versions correctly (alpha < beta < rc < stable).
- app-updater.ts: Import and use compareVersions() for proper version
  comparison instead of simple string inequality.
- Added comprehensive unit tests for version comparison logic.

Pre-release ordering:
- 2.7.1 < 2.7.2-alpha.1 < 2.7.2-beta.1 < 2.7.2-rc.1 < 2.7.2 (stable)
- 2.7.2-beta.6 < 2.7.2-beta.7

* fix(project): fix task status persistence reverting on refresh (#246) (#318)

Correctly validate persisted task status against calculated status.
Previously, if a task was 'in_progress' but had no active subtasks (e.g. still in planning or between phases),
the calculated status 'backlog' would override the stored status, causing the UI to revert to 'Start'.

This fix adds 'in_progress' to the list of active process statuses and explicitly allows 'in_progress' status
to persist when the underlying plan status is also 'in_progress'.

* fix(ci): add auto-updater manifest files and version auto-update (#317)

Combined PR with:
1. Alex's version auto-update changes from PR #316
2. Auto-updater manifest file generation fix

Changes:
- Add --publish never to package scripts to generate .yml manifests
- Update all build jobs to upload .yml files as artifacts
- Update release step to include .yml files in GitHub release
- Auto-bump version in package.json files before tagging

This enables the in-app auto-updater to work properly by ensuring
latest-mac.yml, latest-linux.yml, and latest.yml are published
with each release.

Co-authored-by: Alex <63423455+AlexMadera@users.noreply.github.com>

* f…
AndyMik90 and others added 8 commits January 17, 2026 20:47
…ik90#1216)

* auto-claude: subtask-1-1 - Add detailed console logging to handleAddProfile f

* auto-claude: subtask-1-2 - Add detailed logging to CLAUDE_PROFILE_SAVE and CLAUDE_PROFILE_INITIALIZE IPC handlers

* auto-claude: subtask-1-3 - Add logging to ClaudeProfileManager initialization

* auto-claude: subtask-1-4 - Reproduce issue: Open Settings → Integrations → Cl

Created REPRODUCTION_LOGS.md documenting:
- Complete reproduction steps
- App initialization logs (ClaudeProfileManager verified with 2 profiles)
- Code analysis of handleAddProfile and IPC handlers
- Expected log patterns for renderer and main process
- Potential failure points and debugging checklist
- Investigation hypotheses

Note: Actual button click interaction requires manual testing or QA agent
as coder agent cannot interact with Electron GUI. App is running and ready
for testing at http://localhost:5175/

* auto-claude: subtask-2-1 - Analyze reproduction logs to identify where execut

* auto-claude: subtask-2-2 - Test Hypothesis 1: Verify IPC handler registration timing

Added comprehensive timestamp logging to track IPC handler registration timing:

1. Handler Registration (terminal-handlers.ts):
   - Log registration start time with ISO timestamp
   - Log CLAUDE_PROFILE_SAVE handler registration (elapsed time)
   - Log CLAUDE_PROFILE_INITIALIZE handler registration (elapsed time)
   - Log total registration time and completion timestamp

2. App Initialization (index.ts):
   - Log IPC setup start/end times
   - Log window creation start/end times
   - Show elapsed time between setup and window creation

This verifies Hypothesis 2 from INVESTIGATION.md: handlers are registered
before UI becomes interactive. Expected result: handlers register in <10ms,
well before window loads (~100-500ms).

Used --no-verify due to unrelated @lydell/node-pty TypeScript errors.

* auto-claude: subtask-2-3 - Test Hypothesis 2: Check if Profile Manager is ini

* auto-claude: subtask-2-4 - Test Hypothesis 3: Verify terminal creation succeeds

* auto-claude: subtask-2-5 - Document root cause with evidence and proposed fix

* auto-claude: subtask-3-1 - Improve error handling for Claude account authentication

Add specific error messages and better user feedback when terminal creation fails.
This addresses the root cause identified in Phase 2 investigation (Terminal Creation
Failure - Hypothesis 4).

Changes:
- Added specific translation keys for different error scenarios:
  * Max terminals reached - suggests closing terminals
  * Terminal creation failed - shows specific error details
  * General terminal errors - provides error context
  * Authentication process failed - generic fallback message
- Enhanced error handling in handleAddProfile (+ Add button)
- Enhanced error handling in handleAuthenticateProfile (Re-Auth button)
- Added translations to both English and French locales

This fix provides users with clear feedback when authentication fails, helping them
understand and resolve issues like having too many terminals open or platform-specific
terminal creation problems.

* auto-claude: subtask-3-2 - Add user-facing error notifications for authentication failures

* auto-claude: subtask-3-3 - Verify Re-Auth button functionality restored

Verified that the Re-Auth button functionality was already restored by subtask-3-1.
The Re-Auth button (RefreshCw icon) calls handleAuthenticateProfile() which was
enhanced with improved error handling in subtask-3-1.

Both '+ Add' and 'Re-Auth' buttons shared the same root cause (terminal creation
failure) and were fixed by the same code change.

Verification completed:
- Re-Auth button at lines 562-574 correctly wired to handleAuthenticateProfile()
- handleAuthenticateProfile() has enhanced error handling (lines 279-328)
- Error messages now cover all failure scenarios (max terminals, creation failed, etc.)
- No additional code changes needed

No files modified (fix already applied in subtask-3-1).

* docs: Add subtask-3-3 verification report

Document verification that Re-Auth button functionality was restored by subtask-3-1.
Includes detailed code analysis, verification checklist, and manual testing instructions.

* auto-claude: subtask-3-4 - Remove debug logging added during investigation ph

* auto-claude: subtask-4-1 - Add unit test for handleAddProfile function to ver

* auto-claude: subtask-4-2 - Add integration test for CLAUDE_PROFILE_SAVE and CLAUDE_PROFILE_INITIALIZE IPC handlers

* auto-claude: subtask-4-3 - Add E2E test using Playwright to verify full account addition flow

* fix: address PR review findings for error handling and cleanup

- Remove investigation debug logging from main/index.ts
- Add error logging to terminal IPC handlers
- Delete investigation documentation files
- Add user feedback toast for loadClaudeProfiles failures
- Improve profile init failure UX with clear status message
- Add i18n translations for new error messages (en/fr)

Note: Pre-commit hook skipped due to pre-existing npm audit vulnerabilities
in electron-builder dependencies (not introduced by this commit)

* fix: add error feedback for profile operations

- Add toast notifications for handleDeleteProfile failures
- Add toast notifications for handleRenameProfile failures
- Add toast notifications for handleSetActiveProfile failures
- Add i18n translations for new error messages (en/fr)

Addresses follow-up PR review findings for silent error handling.

* fix: address CodeQL security findings

- Use secure temp directory with mkdtempSync instead of hardcoded /tmp path
- Fix useless variable initialization in handleAuthenticateProfile
- Resolves 6 high severity 'Insecure temporary file' alerts
- Resolves 2 warning 'Useless assignment to local variable' alerts

* fix: address remaining CodeQL insecure temp file findings

- Use secure temp directories with mkdtempSync in claude-profile-ipc.test.ts
- Use secure temp directories with mkdtempSync in subprocess-spawn.test.ts
- Both test files now use os.tmpdir() with random suffixes instead of
  hardcoded /tmp paths, preventing potential security vulnerabilities
- Resolves additional 'Insecure temporary file' CodeQL alerts

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

---------

Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(ui): reset all form fields when opening task modal without draft (qa-requested)

When opening the task creation modal after previously creating a task with
attachments (screenshots, referenced files, etc.), the old data would persist
due to incomplete state reset in the draft-loading useEffect hook.

The else branch (when no draft exists) now resets ALL form state fields to
their defaults, ensuring a clean slate for new task creation. This matches
the behavior of the existing resetForm() function.

Fixes:
- Images/screenshots persisting after task creation
- Referenced files persisting after task creation
- Form content (title, description) persisting
- Classification fields persisting

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

* fix(ui): reset baseBranch, useWorktree, and UI toggles when opening modal without draft

Addresses PR review findings: when opening the task creation modal without
a saved draft, the following state variables were not being reset to their
defaults (while resetForm() correctly resets all of them):

- baseBranch: now resets to PROJECT_DEFAULT_BRANCH
- useWorktree: now resets to true (safe default)
- showFileExplorer: now resets to false
- showGitOptions: now resets to false

This ensures consistent form state when reopening the modal after closing
without saving a draft.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Test User <test@example.com>
* auto-claude: subtask-1-1 - Add markReviewPosted function to useGitHubPRs hook

Fix PR list not updating when "Post Status" button is clicked for blocked PRs.

Changes:
- Add markReviewPosted function to useGitHubPRs hook that updates the store
  with hasPostedFindings: true
- Pass markReviewPosted through GitHubPRs.tsx to PRDetail component
- Call onMarkReviewPosted in handlePostBlockedStatus after successful post

This ensures the PR list status display updates immediately when posting
blocked status (BLOCKED/NEEDS_REVISION verdicts with no findings).

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

* fix: persist hasPostedFindings flag to disk in markReviewPosted

The markReviewPosted function was only updating the in-memory Zustand
store without persisting the has_posted_findings flag to the review
JSON file on disk. After an app restart, the flag would be lost.

This commit adds:
- New IPC handler GITHUB_PR_MARK_REVIEW_POSTED that updates the review
  JSON file on disk with has_posted_findings=true and posted_at timestamp
- New API method markReviewPosted in github-api.ts
- Updated markReviewPosted in useGitHubPRs.ts to call the IPC handler
  first, then update the in-memory store

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

* fix: address follow-up review findings for markReviewPosted

Fixes several issues identified in the follow-up PR review:

1. Race condition with prNumber: onMarkReviewPosted callback now accepts
   prNumber as a parameter instead of relying on closure state, preventing
   wrong PR updates when user switches PRs during async operations.

2. Silent failure handling: handlePostBlockedStatus now checks the return
   value of onPostComment and only marks review as posted on success.

3. Missing postedAt timestamp: markReviewPosted now includes postedAt
   timestamp in the store update for consistency with disk state.

4. Store not updated when result not loaded: If the review result hasn't
   been loaded yet (race condition), markReviewPosted now reloads it from
   disk after persistence to ensure the UI reflects the correct state.

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

* fix: update PostCommentFn type in PRDetail tests to match new signature

Update the mock type to return Promise<boolean> instead of void | Promise<void>
to match the updated onPostComment interface that now returns success status.

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

* fix: correct mock return value type in PRDetail integration test

The mockOnPostComment.mockResolvedValue() was passing undefined instead of
boolean, causing TypeScript type check failures in CI. PostCommentFn returns
Promise<boolean>, so the mock must also return a boolean value.

* fix(security): eliminate TOCTOU race condition in markReviewPosted handler

Remove separate fs.existsSync() check before fs.readFileSync() to prevent
time-of-check to time-of-use (TOCTOU) race condition flagged by CodeQL.

Instead, let readFileSync throw ENOENT if file doesn't exist and handle it
in the catch block with specific error code checking.

* chore: merge develop and fix additional test type error

Resolve merge conflict in ipc.ts by keeping both new IPC channels:
- GITHUB_PR_MARK_REVIEW_POSTED (from this branch)
- GITHUB_PR_UPDATE_BRANCH (from develop)

Fix second occurrence of mockOnPostComment.mockResolvedValue(undefined)
type error in PRDetail integration tests.

---------

Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…ik90#1259)

* fix(windows): prevent zombie process accumulation on app close

- Use taskkill /f /t on Windows to properly kill process trees
  (SIGTERM/SIGKILL are ignored on Windows)
- Make killAllProcesses() wait for process exit events with timeout
- Kill PTY daemon process on shutdown
- Clear periodic update check interval on app quit

Fixes process accumulation in Task Manager after closing Auto-Claude.

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

* fix(windows): extract killProcessGracefully utility with timer cleanup

- Extract shared killProcessGracefully() to platform module
- Fix Issue #1: Move taskkill outside try-catch scope
- Fix Issue #2: Track exit state to skip unnecessary taskkill
- Fix Issue #3: Add GRACEFUL_KILL_TIMEOUT_MS constant
- Fix Issue #4: Use consistent 5000ms timeout everywhere
- Fix Issue #5: Add debug logging for catch blocks
- Fix Issue #6: Log warning when process.once unavailable
- Fix Issue AndyMik90#7: Eliminate code duplication across 3 files
- Fix timer leak: Clear timeout on process exit/error, unref timer

Add comprehensive tests (19 test cases) covering:
- Windows taskkill fallback behavior
- Unix SIGTERM/SIGKILL sequence
- Timer cleanup and memory leak prevention
- Edge cases and error handling

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
* auto-claude: subtask-1-1 - Add fit trigger after drag-drop completes in TerminalGrid

When terminals are reordered via drag-drop, the xterm instances need to be
refitted to their containers to prevent black screens. This change:

- Dispatches a 'terminal-refit-all' custom event from TerminalGrid after
  terminal reordering completes (with 50ms delay to allow DOM update)
- Adds event listener in useXterm that triggers fit on all terminals
  when the event is received

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

* auto-claude: subtask-1-2 - Pass fit callback from useXterm to Terminal component

- Export TerminalHandle interface from Terminal component with fit() method
- Use forwardRef and useImperativeHandle to expose fit callback to parent components
- Export SortableTerminalWrapperHandle interface with fit() method
- Forward fit callback through SortableTerminalWrapper to enable external triggering
- This allows parent components to trigger terminal resize after container changes

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

* auto-claude: subtask-1-3 - Add fit trigger on expansion state change

Add useEffect that calls fit() when isExpanded prop changes. This ensures
the terminal content properly resizes to fill the container when a terminal
is expanded or collapsed.

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

* auto-claude: subtask-2-1 - Add displayOrder field to TerminalSession type def

* auto-claude: subtask-2-2 - Add displayOrder field to renderer Terminal interface

- Added displayOrder?: number to Terminal interface for tab persistence
- Updated addTerminal to set displayOrder based on current array length
- Updated addRestoredTerminal to restore displayOrder from session
- Updated addExternalTerminal to set displayOrder for new terminals
- Updated reorderTerminals to update displayOrder values after drag-drop
- Updated restoreTerminalSessions to sort sessions by displayOrder

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

* auto-claude: subtask-2-3 - Persist displayOrder when saving terminal sessions

Add displayOrder field to TerminalSession interface in the main process
terminal-session-store.ts. This field stores the UI position for ordering
terminals after drag-drop, enabling order persistence across app restarts.

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

* auto-claude: subtask-2-4 - Save order after drag-drop reorder and restore on app startup

Implements terminal display order persistence:
- Added TERMINAL_UPDATE_DISPLAY_ORDERS IPC channel
- Added updateDisplayOrders method to TerminalSessionStore
- Added session-handler and terminal-manager wrapper functions
- Added IPC handler in terminal-handlers.ts
- Added ElectronAPI type and preload API method
- Updated TerminalGrid.tsx to persist order after drag-drop reorder
- Added browser mock for updateTerminalDisplayOrders

Now when terminals are reordered via drag-drop, the new order is
persisted to disk and restored when the app restarts.

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

* auto-claude: subtask-3-1 - Add WebLinksAddon callback to open links via openExternal IPC

* fix(main): add error handling to setWindowOpenHandler shell.openExternal

The setWindowOpenHandler calls shell.openExternal without handling its promise,
causing unhandled rejection errors when the OS cannot open a URL (e.g., no
registered handler for the protocol).

While PR AndyMik90#1215 fixes terminal link clicks by routing them through IPC with
proper error handling, this setWindowOpenHandler is still used as a fallback
for any other window.open() calls (e.g., from third-party libraries).

This change adds a .catch() handler to gracefully log failures instead of
causing Sentry errors.

Fixes: Sentry error "No application found to open URL" in production v2.7.4

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

* fix(terminal): resolve PR review findings for persistence and security

- Preserve displayOrder when updating existing sessions to prevent tab
  order loss during periodic saves
- Sort sessions by displayOrder in handleRestoreFromDate to maintain
  user's custom tab ordering when restoring from history
- Add URL scheme allowlist (http, https, mailto) in setWindowOpenHandler
  for security hardening against malicious URL schemes
- Extract 50ms DOM update delay to TERMINAL_DOM_UPDATE_DELAY_MS constant
- Add error handling for IPC persistence calls in TerminalGrid
- Add .catch() handler to WebLinksAddon openExternal promise

---------

Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…dyMik90#1087) (AndyMik90#1124)

* fix: auto-commit .gitignore changes during project initialization (AndyMik90#1087)

When Auto-Claude modifies .gitignore to add its own entries, those
changes were not being committed. This caused merge failures with
"local changes would be overwritten by merge: .gitignore".

Changes:
- Add _is_git_repo() helper to check if directory is a git repo
- Add _commit_gitignore() helper to commit .gitignore changes
- Update ensure_all_gitignore_entries() to accept auto_commit parameter
- Update init_auto_claude_dir() and repair_gitignore() to auto-commit

The commit message "chore: add auto-claude entries to .gitignore" is
used for these automatic commits.

Fixes AndyMik90#1087

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

* style: fix ruff formatting for function signature

Split long function signature across multiple lines to satisfy
ruff format requirements.

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

* fix: add subprocess timeouts and improve error handling

- Add timeout=10 to git rev-parse call in _is_git_repo
- Add timeout=30 to git add and git commit calls in _commit_gitignore
- Check both stdout and stderr for "nothing to commit" message
  (location varies by git version/locale)
- Log warning when auto-commit fails to help diagnose merge issues
- Catch subprocess.TimeoutExpired explicitly

Addresses CodeRabbit MAJOR review comments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: youngmrz <elliott.zach@gmail.com>

* fix: use LC_ALL=C for locale-independent git output parsing

Set LC_ALL=C environment variable when running git commands to
ensure English output messages regardless of user locale. This
prevents "nothing to commit" detection from failing in non-English
environments.

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

* fix: only commit .gitignore file, not all staged changes

Previously, `git commit -m "..."` would commit ALL staged files,
potentially including unrelated user changes. This fix explicitly
specifies .gitignore as the file to commit.

Addresses CRITICAL bot feedback about unintentionally committing
user's staged changes during project initialization.

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

* style: format git commit args per ruff

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

* refactor: use get_git_executable() for cross-platform git resolution

Use the platform abstraction module (core.git_executable) to resolve
the git executable path instead of hardcoding "git". This ensures
proper operation on Windows where git may not be in PATH.

Addresses CodeRabbit suggestion for consistent cross-platform behavior.

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

* fix: add debug logging for exception handling in git operations

Address CodeRabbit feedback to log exceptions at DEBUG level in
_is_git_repo and _commit_gitignore functions for better debugging.
Also update repair_gitignore docstring to document auto-commit behavior.

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

---------

Signed-off-by: youngmrz <elliott.zach@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
…ttempt failure (AndyMik90#1213)

* fix(terminal): sync worktree config after PTY creation to fix first-attempt failure

When selecting a worktree immediately after app launch, the terminal
would fail to spawn on the first attempt but succeed on the second.

Root cause: IPC calls to setTerminalWorktreeConfig and setTerminalTitle
happened before the terminal existed in the main process, so the config
wasn't persisted. On recreation, the new PTY was created but without
the worktree association.

Changes:
- Add pendingWorktreeConfigRef to store config during recreation
- Re-sync worktree config to main process in onCreated callback
- Increase MAX_RECREATION_RETRIES from 10 to 30 (1s → 3s) to handle
  slow app startup scenarios where xterm dimensions take longer

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

* fix(terminal): address PR review findings for worktree config race conditions

- Clear pendingWorktreeConfigRef on PTY creation error to prevent stale config
- Add try/catch error handling for IPC calls in onCreated callback
- Extract duplicated worktree recreation logic into applyWorktreeConfig helper

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
import { getOAuthModeClearVars } from './env-utils';
import { getAugmentedEnv } from '../env-utils';
import { getToolInfo } from '../cli-tool-manager';
import { isWindows, killProcessGracefully } from '../platform';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import isWindows.

Copilot Autofix

AI about 2 months ago

In general, unused imports should be removed or, if the value is truly needed, the code should be updated to use them. Here, the only unused element is the isWindows named import from ../platform, while killProcessGracefully is presumably still used. The minimal, behavior-preserving fix is to adjust the import statement so that it only imports killProcessGracefully.

Concretely, in apps/frontend/src/main/agent/agent-process.ts, at line 27, change import { isWindows, killProcessGracefully } from '../platform'; to import { killProcessGracefully } from '../platform';. No other code changes or new imports are required, because we are only removing an unused binding.

Suggested changeset 1
apps/frontend/src/main/agent/agent-process.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/apps/frontend/src/main/agent/agent-process.ts b/apps/frontend/src/main/agent/agent-process.ts
--- a/apps/frontend/src/main/agent/agent-process.ts
+++ b/apps/frontend/src/main/agent/agent-process.ts
@@ -24,7 +24,7 @@
 import { getOAuthModeClearVars } from './env-utils';
 import { getAugmentedEnv } from '../env-utils';
 import { getToolInfo } from '../cli-tool-manager';
-import { isWindows, killProcessGracefully } from '../platform';
+import { killProcessGracefully } from '../platform';
 
 /**
  * Type for supported CLI tools
EOF
@@ -24,7 +24,7 @@
import { getOAuthModeClearVars } from './env-utils';
import { getAugmentedEnv } from '../env-utils';
import { getToolInfo } from '../cli-tool-manager';
import { isWindows, killProcessGracefully } from '../platform';
import { killProcessGracefully } from '../platform';

/**
* Type for supported CLI tools
Copilot is powered by AI and may make mistakes. Always verify output.
AndyMik90 and others added 3 commits January 17, 2026 23:16
* auto-claude: subtask-1-1 - Add TaskOrderState type to task.ts

Add TaskOrderState type as Record<TaskStatus, string[]> to map kanban
columns to ordered task IDs for drag-and-drop reordering.

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

* auto-claude: subtask-1-2 - Add task order state and actions to task-store.ts

- Import arrayMove from @dnd-kit/sortable
- Import TaskOrderState type from shared types
- Add taskOrder state (TaskOrderState | null) for per-column ordering
- Add setTaskOrder action to set full task order state
- Add reorderTasksInColumn action using arrayMove pattern
- Add loadTaskOrder action to load from localStorage
- Add saveTaskOrder action to persist to localStorage
- Add helper functions: getTaskOrderKey, createEmptyTaskOrder
- Update clearTasks to also clear taskOrder state

* auto-claude: subtask-1-3 - Add localStorage persistence helpers for task order

Add clearTaskOrder function to complete the localStorage persistence
helpers for task order management. The loadTaskOrder and saveTaskOrder
functions were already implemented. This adds:
- clearTaskOrder(projectId): Removes task order from localStorage and resets state

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

* auto-claude: subtask-2-1 - Import arrayMove from @dnd-kit/sortable and add wi

- Import arrayMove from @dnd-kit/sortable in KanbanBoard.tsx
- Import useTaskStore to access reorderTasksInColumn and saveTaskOrder actions
- Add within-column reorder logic to handleDragEnd:
  - Detect same-column drops (when task.status === overTask.status)
  - Call reorderTasksInColumn to update order in store via arrayMove
  - Persist order to localStorage via saveTaskOrder

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

* auto-claude: subtask-2-2 - Update tasksByStatus useMemo to apply custom order

Updated the tasksByStatus useMemo in KanbanBoard to support custom task ordering:
- Added taskOrder state selector from useTaskStore
- If custom order exists for a column, sort tasks by their order index
- Filter out stale IDs (task IDs in order that no longer exist)
- Prepend new tasks (not in order) at top with createdAt sort
- Fallback to createdAt sort (newest first) when no custom order exists

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

* auto-claude: subtask-2-3 - Add useEffect to load task order on mount and when project changes

* auto-claude: subtask-3-1 - Handle cross-column drag: place task at top

When a task is moved to a new column via drag-and-drop:
- Added moveTaskToColumnTop action to task-store.ts
- Removes task from source column order array
- Adds task to index 0 (top) of target column order array
- Persists order to localStorage after cross-column moves
- Works for both dropping on column and dropping on task in diff column

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

* auto-claude: subtask-3-2 - Handle new task placement: new tasks added to backlog appear at index 0

- Modified addTask() to also update taskOrder state when adding new tasks
- New tasks are inserted at index 0 (top) of their status column's order array
- Follows the existing pattern from moveTaskToColumnTop()
- Includes safety check to prevent duplicate task IDs in order array

* auto-claude: subtask-3-3 - Handle deleted/stale tasks in kanban order

Add cleanup effect that detects and removes stale task IDs from the
persisted task order when tasks are deleted. This ensures the order
stored in localStorage stays in sync with actual tasks.

- Add setTaskOrder store selector for updating order state
- Add useEffect that filters out stale IDs when tasks change
- Persist cleaned order to localStorage when stale IDs are found

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

* auto-claude: subtask-4-1 - Create unit tests for task order state management

Add comprehensive unit tests for kanban board drag-and-drop reordering:
- Test setTaskOrder: basic setting, replacing, empty columns, all column orders
- Test reorderTasksInColumn with arrayMove: various reordering scenarios,
  edge cases (null order, missing IDs, single task, adjacent tasks)
- Test loadTaskOrder: localStorage retrieval, empty state creation,
  project-specific keys, error handling for corrupted/inaccessible data
- Test saveTaskOrder: localStorage persistence, null handling, error handling
- Test clearTaskOrder: removal from localStorage, project-specific keys
- Test moveTaskToColumnTop: cross-column moves, source removal, deduplication
- Test addTask integration: new tasks added to top of column order
- Integration tests: full load/reorder/save cycle, project switching

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

* auto-claude: subtask-4-2 - Add localStorage persistence edge case tests

* auto-claude: subtask-4-3 - Add unit tests for order filtering

Add comprehensive unit tests for task order filtering logic:
- Stale ID removal tests: verify IDs for deleted tasks are filtered out
- New task placement tests: verify new tasks appear at top of column
- Cross-column move tests: verify order updates when tasks move between columns

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

* fix(kanban): address follow-up review findings

- Wrap saveTaskOrder in useCallback to prevent useEffect dependency loop
- Add runtime validation for localStorage data in loadTaskOrder
- Remove variable shadowing of projectId in handleDragEnd

* test: update task-order tests to match new validation behavior

loadTaskOrder now validates localStorage data and resets to empty order
when invalid data (null, arrays) is found instead of storing it directly.

* fix(kanban): improve task order validation and reordering reliability

- Add comprehensive validation for localStorage task order data:
  - Validate each column value is a string array
  - Merge with empty order to handle partial/corrupted data
- Fix saveTaskOrder to return false when nothing to save
- Fix reordering for tasks not yet in order array by syncing
  visual order before calling reorderTasksInColumn

Resolves PR review findings: NEWCODE-001, NEW-001, NEW-005

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

---------

Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix 12 max limit terminals per project

* fix(tests): address PR review findings and CI failures

- Extract duplicated terminal counting logic to helper function
  (getActiveProjectTerminalCount) to improve maintainability
- Add comprehensive rationale comment for 12-terminal limit
  explaining memory/resource constraints
- Add debug logging when terminal limit is reached for better
  observability
- Document that addRestoredTerminal intentionally bypasses limit
  to preserve user state from previous sessions
- Fix macOS test failure: use globalThis instead of window in
  requestAnimationFrame mock (terminal-copy-paste.test.ts)
- Fix Windows test timeouts: add 15000ms timeouts to all
  subprocess-spawn tests for slower CI environments
- Increase PRDetail.integration.test.tsx timeout to 15000ms

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…0#1268)

* fix(pr-review): allow re-review when previous review failed

Previously, when a PR review failed (e.g., SDK validation error), the
bot detector would mark the commit as 'already reviewed' and refuse to
retry. This caused instant failures on subsequent review attempts.

Now, the orchestrator checks if the existing review was successful before
returning it. Failed reviews are no longer treated as blocking - instead,
the system allows a fresh review attempt.

Fixes: PR reviews failing instantly with 'Review failed: None'

* fix(pr-review): address PR review feedback

- Rename test_failed_review_allows_re_review to test_failed_review_model_persistence
  with updated docstring to accurately reflect what it tests (model persistence,
  not orchestrator re-review behavior)
- Extract duplicate skip result creation into _create_skip_result helper method
  to reduce code duplication in orchestrator.py

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* auto-claude: subtask-1-1 - Add 'planning' phase to stuck detection skip logic

Add 'planning' phase to the stuck detection skip logic in TaskCard.tsx.
Previously only 'complete' and 'failed' phases were skipped. Now 'planning'
is also skipped since process tracking is async and may show false negatives
during initial startup.

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

* auto-claude: subtask-1-2 - Add debug logging to stuck detection for better di

Add debug logging when stuck check is skipped due to planning phase or
terminal phases (complete/failed). This helps diagnose false-positive
stuck detection issues by logging when and why the check was bypassed.

The logging uses the existing window.DEBUG flag pattern to avoid noise
in production while enabling diagnostics when needed.

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

* fix(ui): add 'planning' phase to useTaskDetail.ts stuck detection and extract constant

- Add 'planning' phase check at lines 113 and 126 in useTaskDetail.ts
  to match TaskCard.tsx behavior, preventing false stuck indicators
  during initial task startup
- Extract STUCK_CHECK_SKIP_PHASES constant and shouldSkipStuckCheck()
  helper in TaskCard.tsx to reduce code duplication

Fixes PR review findings: ed766093f258 (HIGH), 91a0a4fcd67b (LOW)

* fix(ui): don't set hasCheckedRunning for planning phase

Fixes regression where stuck detection was disabled after planning→coding
transition because hasCheckedRunning remained true from planning phase.

Now 'planning' phase only clears isStuck without setting hasCheckedRunning,
allowing proper stuck detection when task transitions to 'coding' phase.

Fixes NEW-001 from PR review.

* fix(ui): move stuck check constants outside TaskCard component

Move STUCK_CHECK_SKIP_PHASES constant and shouldSkipStuckCheck function
outside the TaskCard component to avoid recreation on every render.

Addresses PR review finding NEW-003 (code quality).

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

* fix(ui): reset hasCheckedRunning when task stops in planning phase

Move the !isActiveTask check to run FIRST before any phase checks.
This ensures hasCheckedRunning is always reset when a task becomes
inactive, even if it stops while in 'planning' phase.

Previously, the planning phase check returned early, preventing the
!isActiveTask reset from running, which caused stale hasCheckedRunning
state and skipped stuck checks on task restart.

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

* fix(test): use callback(0) instead of callback.call(window, 0)

Fix unhandled ReferenceError in terminal-copy-paste.test.ts where
window was not defined when requestAnimationFrame callback executed
asynchronously. The callback just needs the timestamp parameter.

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Test User <test@example.com>
AndyMik90 and others added 11 commits January 17, 2026 23:47
* fix(frontend): resolve preload API duplicates and terminal session corruption

- Remove duplicate API spreads (IdeationAPI, InsightsAPI, GitLabAPI) from
  createElectronAPI() - these are already included via createAgentAPI()
- Fix "object is not iterable" error in Electron sandbox renderer
- Implement atomic writes for TerminalSessionStore using temp file + rename
- Add backup rotation and automatic recovery from corrupted session files
- Prevents data loss on app crash or interrupted writes

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

* fix(hooks): use perl for cross-platform README version sync

BSD sed (macOS) doesn't support the {block} syntax with address ranges.
Replace sed with perl for the download links update which works
consistently across macOS and Linux.

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

* chore: bump version to 2.7.5

* perf(frontend): optimize terminal session store async operations

- Replace sync existsSync() with async fileExists() helper in saveAsync()
- Add pendingDeleteTimers Map to prevent timer accumulation on rapid deletes
- Cancel existing cleanup timers before creating new ones
- Add comprehensive unit tests (28 tests) covering:
  - Atomic write pattern (temp file -> backup rotation -> rename)
  - Backup recovery from corrupted main file
  - Race condition prevention via pendingDelete
  - Write serialization with writeInProgress/writePending
  - Timer cleanup for pendingDeleteTimers
  - Session CRUD operations, output buffer, display order

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…riables (AndyMik90#1267)

* fix(worktree): prevent cross-worktree file leakage via environment variables

When pre-commit hook runs in a worktree, it sets GIT_DIR and GIT_WORK_TREE
environment variables. These variables were persisting and leaking into
subsequent git operations in other worktrees or the main repository, causing
files to appear as untracked in the wrong location.

Root cause confirmed by 5 independent investigation agents:
- GIT_DIR/GIT_WORK_TREE exports persist across shell sessions
- Version sync section runs git add without env isolation
- Tests already clear these vars but production code didn't

Fix:
- Clear GIT_DIR/GIT_WORK_TREE when NOT in a worktree context
- Add auto-detection and repair of corrupted core.worktree config
- Add comprehensive documentation explaining the bug and fix

* fix(worktree): add git env isolation to frontend subprocess calls

Extend worktree corruption fix to TypeScript frontend:

- Create git-isolation.ts utility with getIsolatedGitEnv()
- Fix task/worktree-handlers.ts: merge, preview, PR creation spawns
- Fix terminal/worktree-handlers.ts: all 10 execFileSync git calls
- Use getToolPath('git') consistently for cross-platform support

Clears GIT_DIR, GIT_WORK_TREE, GIT_INDEX_FILE, and author/committer
env vars to prevent cross-contamination between worktrees.

Part of fix for mysterious file leakage between worktrees.

* fix(pre-commit): improve robustness of git worktree handling

Address PR review findings:

1. Improve .git file parsing for worktree detection:
   - Use sed -n with /p to only print matching lines
   - Add head -1 to handle malformed files with multiple lines
   - Add directory existence check before setting GIT_DIR

2. Add error handling for git config --unset:
   - Wrap in conditional to detect failures
   - Print warning if unset fails (permissions, locked config, etc.)

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

* fix(worktree): align git env isolation between TypeScript and Python

Address PR review findings for consistency:

1. Add GIT_AUTHOR_DATE and GIT_COMMITTER_DATE to TypeScript
   GIT_ENV_VARS_TO_CLEAR array to match Python implementation

2. Add HUSKY=0 to Python get_isolated_git_env() to match
   TypeScript implementation and prevent double-hook execution

3. Add getIsolatedGitEnv() to listOtherWorktrees() for consistency
   with all other git operations in the file

Also fix ruff linting (UP045): Replace Optional[dict] with dict | None

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

* fix(workspace): migrate remaining git calls to use run_git for env isolation

Replace all direct subprocess.run git calls in workspace.py with run_git()
to ensure consistent environment isolation across all backend git operations.

This prevents potential cross-worktree contamination from environment
variables (GIT_DIR, GIT_WORK_TREE, etc.) that could be set by pre-commit
hooks or other git configurations.

Converted 13 subprocess.run calls:
- git rev-parse --abbrev-ref HEAD
- git merge-base (2 locations)
- git add (10 locations)

Also:
- Remove now-unused subprocess import
- Fix cross-platform issue: use getToolPath('git') in listOtherWorktrees

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

* fix(worktree): add unit tests and fix pythonEnv git isolation bypass

- Add comprehensive Python tests for git_executable module (20 tests)
- Add TypeScript tests for getIsolatedGitEnv utility (19 tests)
- Migrate GitLab handlers to use getIsolatedGitEnv for git commands
- Fix critical bug: getPythonEnv() now uses getIsolatedGitEnv() as base
  to prevent git env vars from being re-added when pythonEnv is spread

The pythonEnv bypass bug caused git isolation to be defeated when:
  env: { ...getIsolatedGitEnv(), ...pythonEnv, ... }
because pythonEnv contained a copy of process.env with git vars intact.

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

* fix(worktree): add git env isolation to execution-handlers

Add getIsolatedGitEnv() to 6 git commands in execution-handlers.ts:
- QA review rejection: reset, checkout, clean (lines 407-430)
- Task discard cleanup: rev-parse, worktree remove, branch -D (lines 573-599)

Without env isolation, these commands could operate on the wrong
repository if GIT_DIR/GIT_WORK_TREE vars were set from a previous
worktree operation.

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

* fix(pre-commit): clear git env vars when worktree detection fails

When .git is a file but WORKTREE_GIT_DIR parsing fails (empty or invalid
directory), any inherited GIT_DIR/GIT_WORK_TREE environment variables
were left in place, potentially causing cross-worktree contamination.

Now explicitly unsets these variables in the failure case, matching the
behavior of the main repo branch.

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

* chore(tests): remove unused pytest import

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add `deleteAndRetryTask` IPC handler and store function that:
- Stops any running task process
- Cleans up git worktree with `git worktree remove --force`
- Deletes associated branch and prunes dangling worktrees
- Removes spec directory from .auto-claude/specs/
- Optionally recreates the task for retry with retriedFrom metadata

This provides a clean way to handle orphaned specs and worktrees when
tasks fail or get stuck, fixing issue AndyMik90#1103.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address Gemini HIGH severity feedback:
- Convert readdirSync, mkdirSync, writeFileSync to async equivalents
  from fs/promises to prevent blocking the main process
- Add console.warn/error logging to empty catch blocks for better
  debugging when git branch operations or task recreation fails

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: youngmrz <elliott.zach@gmail.com>
…erns

Address Gemini MEDIUM severity feedback:
- Remove unused readdirSync import (was left after async conversion)
- Remove existsSync check before rm() since force:true handles missing paths
- Replace existsSync check before readdir() with async try/catch pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: youngmrz <elliott.zach@gmail.com>
- Add comments explaining best-effort worktree cleanup design
- Fix duplicate invalidateTasksCache by moving to each return path
- Update mock to simulate recreatedTask scenario for UI testing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: youngmrz <elliott.zach@gmail.com>
Ensure projectStore.invalidateTasksCache() is called even when
spec directory deletion fails. This prevents stale UI state when
worktree cleanup succeeds but spec deletion fails.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add missing retriedFrom field to TaskMetadata interface. This field
is used by deleteAndRetryTask to track the original task specId when
a task is recreated.

Fixes TypeScript error in browser mock.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract shared generateSpecId() utility function to eliminate duplicate
  slug generation logic between crud-handlers.ts and execution-handlers.ts
- Fix cleanedUpWorktree flag logic: set flag immediately after worktree
  remove succeeds, before attempting branch delete or prune operations
- Wrap worktree prune in separate try-catch so prune failures don't
  affect the cleanup flag
- Standardize catch variable naming (e -> error) for consistency

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: youngmrz <elliott.zach@gmail.com>
Wrap the spec number calculation and directory creation in withSpecNumberLock
to prevent race conditions when multiple concurrent deleteAndRetryTask calls
try to create new specs simultaneously.

This ensures each recreated task gets a unique spec number even under
concurrent load, preventing file overwrites and corrupted task specs.

Addresses Sentry HIGH severity feedback about missing lock for specNum.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…reate

Addresses review comments:
- CRITICAL: Move mkdir inside withSpecNumberLock callback to prevent race
  condition where two concurrent calls could get the same spec number before
  either creates their directory
- Handle falsy taskDescription in recreate check with explicit null/undefined
  checks, returning recreationSkipped response when data is missing
- Add recreationSkipped field to response type for UI feedback

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed tasks leave orphaned spec directories and git worktrees

3 participants