Compare commits

...

66 Commits

Author SHA1 Message Date
JoshuaRileyDev fef07c9517 feat: add terminal dropdown with inbuilt and external options in task review (#347)
* feat: add dropdown to select inbuilt or external terminal in task review

Replace the single terminal button on the task review modal with a dropdown
menu that allows users to choose between:
- Opening in an inbuilt terminal tab (existing behavior)
- Opening in the system's default external terminal application

Changes:
- Add IPC channel SHELL_OPEN_TERMINAL for opening paths in system terminal
- Create IPC handler with cross-platform support (macOS, Windows, Linux)
- Update ShellAPI with openTerminal method
- Extend useTerminalHandler hook to support both terminal types
- Create TerminalDropdown component with dropdown menu UI
- Update WorkspaceStatus to use dropdown for both terminal buttons

Cross-platform support:
- macOS: Uses 'open -a Terminal' to open Terminal.app
- Windows: Uses 'start cmd' to open Command Prompt
- Linux: Tries common terminal emulators (gnome-terminal, konsole, xfce4-terminal, xterm)

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

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

* fix: correct import paths in TerminalDropdown component

* feat: add modal close and view switch for inbuilt terminal option

When opening the inbuilt terminal from the task review modal, the UI now:
- Closes the task detail modal
- Switches to the Agent Terminals view
- Creates the terminal in that view

This provides a better user experience by automatically navigating to where
the terminal is created, rather than keeping the user in the modal.

Changes:
- Added onSwitchToTerminals prop to TaskDetailModal, TaskReview, and WorkspaceStatus
- Updated TerminalDropdown handlers to call onClose and onSwitchToTerminals before creating terminal
- Wired up App.tsx to pass setActiveView callback to TaskDetailModal

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

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

* fix: pass terminal creation callback to parent to prevent unmount race condition

The previous implementation called openTerminal from the WorkspaceStatus component,
but when the modal closed and view switched, the component unmounted before the
terminal could be created.

This fix passes terminal creation parameters up to App.tsx where the modal close,
view switch, and terminal creation are handled in the correct order at the parent level.

Changes:
- Added onOpenInbuiltTerminal callback prop through component hierarchy
  (TaskDetailModal → TaskReview → WorkspaceStatus)
- Created handleOpenInbuiltTerminal in App.tsx that:
  1. Closes the modal (setSelectedTask(null))
  2. Switches to terminals view (setActiveView('terminals'))
  3. Creates the terminal (window.electronAPI.createTerminal)
- Updated TerminalDropdown handlers in WorkspaceStatus to call the callback
  instead of creating terminal directly

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

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

* fix: add terminal to frontend store to display in UI

The previous implementation created the terminal in the backend but didn't
add it to the frontend terminal store, so TerminalGrid had no terminal to render.

The correct flow is:
1. Add terminal to store (creates Terminal object in frontend)
2. Terminal component mounts
3. usePtyProcess hook creates backend PTY process

Changes:
- Updated handleOpenInbuiltTerminal to use useTerminalStore.getState().addTerminal()
- Removed direct window.electronAPI.createTerminal() call
- Terminal now appears in TerminalGrid after creation

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

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

* fix: add openTerminal to ElectronAPI type and browser mock

TypeScript was complaining about missing openTerminal method:
- Added openTerminal to ElectronAPI interface in ipc.ts
- Added openTerminal mock to infrastructure-mock.ts for browser mode

This fixes the typecheck errors in CI.

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

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

* fix: use node: prefix for child_process import for better TypeScript resolution

Changed from 'child_process' to 'node:child_process' to ensure TypeScript
properly resolves the execSync import in all environments including CI.

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

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

* refactor: improve terminal command security, deterministic mounting, and i18n

This commit addresses several issues with the terminal dropdown feature:

1. **Improved Windows Command Security** (settings-handlers.ts):
   - Removed fragile nested quotes from Windows terminal command
   - Changed from `"cd /d "${dirPath}""` to `cd /d "${sanitizedPath}"`
   - Added path sanitization to escape double quotes and prevent command injection
   - Simplified command structure for better reliability

2. **Deterministic Component Readiness** (App.tsx, TerminalGrid.tsx):
   - Replaced hardcoded 100ms timeout with deterministic readiness signal
   - Added `onMounted` prop to TerminalGrid that fires when component mounts
   - Created Promise-based waiting mechanism in handleOpenInbuiltTerminal
   - Checks if terminals view is already active to avoid unnecessary waiting
   - Ensures Terminal component is mounted before creating backend PTY

3. **i18n Compliance** (TerminalDropdown.tsx):
   - Replaced all hardcoded English strings with translation keys
   - Added useTranslation hook with 'taskReview' namespace
   - Updated button title: "Open terminal" → t('terminal.openTerminal')
   - Updated menu items:
     - "Open in Inbuilt Terminal" → t('terminal.openInbuilt')
     - "Open in External Terminal" → t('terminal.openExternal')
   - Created taskReview.json translation files for English and French

Files Changed:
- src/main/ipc-handlers/settings-handlers.ts
- src/renderer/App.tsx
- src/renderer/components/TerminalGrid.tsx
- src/renderer/components/task-detail/task-review/TerminalDropdown.tsx
- src/shared/i18n/locales/en/taskReview.json (new)
- src/shared/i18n/locales/fr/taskReview.json (new)

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

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

* fix: use execFileSync with argument arrays to prevent command injection

Security Fix: Replaced all execSync shell commands with execFileSync and
argument arrays to completely eliminate command injection vulnerabilities.

Previous issue:
- Incomplete escaping: only escaped double quotes, not backslashes
- Shell interpretation could lead to command injection with crafted paths

Solution:
- macOS: execFileSync('open', ['-a', 'Terminal', dirPath])
- Windows: execFileSync('cmd.exe', ['/K', 'cd', '/d', dirPath], {shell: false})
- Linux: execFileSync(terminal, ['--working-directory', dirPath])

Benefits:
- No shell interpretation - arguments passed directly to executables
- No escaping needed - OS handles path special characters correctly
- Prevents all forms of command injection
- More reliable cross-platform behavior

For xterm (Linux fallback), single quotes are properly escaped using the
pattern: dirPath.replace(/'/g, "'\\''") which handles single quotes in paths.

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

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

* fix: register taskReview namespace with i18n configuration

The taskReview translation files were created but not registered with the
i18n configuration, causing translation keys to be displayed literally
instead of the actual translated text.

Changes:
- Imported enTaskReview and frTaskReview translation files
- Added taskReview to resources object for both en and fr
- Added 'taskReview' to the ns (namespaces) array in i18n.init()

This fixes the dropdown menu displaying "terminal.openInbuilt" instead of
"Open in Inbuilt Terminal".

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

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

* fix: remove unused onMounted callback and Promise-based readiness signaling

- Remove handleTerminalGridMounted function reference that caused runtime error
- Remove onMounted prop from TerminalGrid interface
- Remove useEffect hook that called onMounted callback
- Simplify handleOpenInbuiltTerminal to directly add terminal to store
- TerminalGrid is always mounted (just hidden), so no readiness signaling needed

This fixes "handleTerminalGridMounted is not defined" error and simplifies
the terminal creation flow.

* chore: remove unused imports (useRef, useCallback) from App.tsx

* refactor: add input validation and remove unused import in terminal handler

Security and code quality improvements:

1. Add comprehensive input validation for dirPath:
   - Check for non-empty string
   - Resolve to absolute path with path.resolve()
   - Verify path exists with existsSync()
   - Confirm it's a directory with statSync().isDirectory()
   - Return clear, actionable error messages if any check fails

2. Replace all uses of dirPath with validated resolvedPath

3. Remove unused execSync import from node:child_process

4. Add statSync to fs imports for directory validation

This prevents potential issues with invalid paths and improves error
handling with specific error messages for each validation failure.

* refactor: rename unused id parameter to _id in handleOpenInbuiltTerminal

- Prefix parameter with underscore to indicate intentionally unused
- Add comment explaining terminal ID is auto-generated by addTerminal()
- Keep parameter for callback signature consistency with callers
- Remove id from console.log since it's not used in the logic

This satisfies linter requirements while maintaining callback compatibility.

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 17:29:29 +01:00
Mitsu 9d43abedde refactor: remove deprecated code across backend and frontend (#348)
## Backend
- Delete `agents/auto_claude_tools.py` (compatibility shim)
- Delete `implementation_plan/main.py` (compatibility shim)
- Remove `--dev` flag and `dev_mode` parameter from:
  - cli/main.py, cli/utils.py, cli/spec_commands.py
  - runners/spec_runner.py
  - spec/pipeline/models.py, orchestrator.py
  - spec/complexity.py
- Remove `ClaudeSimilarityDetector` class from batch_issues.py
- Remove unused `self.detector` alias

## Frontend
- Remove `PROJECT_UPDATE_AUTOBUILD` IPC channel
- Remove `updateProjectAutoBuild` from:
  - project-handlers.ts (IPC handler)
  - project-api.ts (preload API)
  - project-store.ts (store function)
  - project-mock.ts (mock)
- Remove deprecated `appendOutput`/`clearOutputBuffer` from terminal-store
- Update useTerminalEvents to use terminalBufferManager directly
- Remove deprecated "Update Auto Claude" dialog from Sidebar
- Remove `handleUpdate` from useProjectSettings hook

## Tests
- Remove `test_dev_mode_param_ignored` test
2025-12-27 16:33:26 +01:00
HSSAINI Saad d51f45621b feat: centralize CLI tool path management (#341)
* feat: centralize CLI tool path management

Created centralized CLI tool manager with multi-level detection
priority (user config → venv → Homebrew → system PATH).

Key changes:
- New cli-tool-manager.ts with platform-aware detection (macOS
  Apple Silicon/Intel, Windows, Linux)
- Migrated 75 hardcoded CLI tool usages across 12 files (Python,
  Git, GitHub CLI)
- Added Settings UI for user configuration with auto-detection
  display showing detected path, version, and source
- Implemented version validation (Python 3.10+ required)
- Session-based caching without TTL expiration
- Full i18n support (EN/FR) for new Settings UI elements

This eliminates hardcoded tool paths and provides consistent,
configurable CLI tool management across the application.

* fix(lint): resolve linting issues in CLI tool manager

- Remove unused getAugmentedEnv import
- Replace console.log with console.warn for logging
- Fix template string syntax error in release-service.ts (backtick vs quote)

Reduces lint errors from 185 to 179 (0 errors, 179 warnings)

* fix(security): address CodeRabbit review feedback

- Fix command injection vulnerability in validateGitHubCLI using execFileSync
- Remove redundant execSync calls in release-service.ts
- Fix Electron context separation by moving ToolDetectionResult to shared types
- Add loading state to Settings UI to prevent flashing 'Not detected'
- Improve error handling with safe string conversion

Addresses security and code quality issues identified by automated review.

* fix(security): fix all command injection vulnerabilities in CLI tool usage

Replace all execSync calls using getToolPath() with execFileSync to prevent
command injection attacks. This fixes CodeQL security warnings about unsanitized
environment variables in command execution.

Changes:
- settings-handlers.ts: 1 fix (git init)
- release-service.ts: 20 fixes (git/gh commands in release flow)
- worktree-handlers.ts: 22 fixes (git worktree operations)
- project-handlers.ts: 3 fixes (git branch operations)
- github/utils.ts: 1 fix (gh auth token)
- github/oauth-handlers.ts: 11 fixes (gh API and git remote operations)
- github/release-handlers.ts: 3 fixes (gh auth, git describe, git log)
- changelog/git-integration.ts: 6 fixes (git branch and tag operations)

Total: 67 command injection vulnerabilities fixed

Security Impact:
- Prevents malicious users from injecting arbitrary commands via CLI tool paths
- Uses execFileSync which executes binaries directly without shell interpolation
- Passes arguments as array instead of concatenated string
- Eliminates shell redirection patterns (2>/dev/null) with try-catch blocks

* fix(security): fix remaining command injection vulnerabilities and remove unused imports

Fix all remaining CodeQL security warnings:

CLI tool validation (cli-tool-manager.ts):
- validateGit: Replace execSync with execFileSync for git --version

Project initialization (project-initializer.ts):
- Replace all 7 execSync calls with execFileSync
- git rev-parse, git init, git status, git add, git commit

Release service (release-service.ts):
- checkTagExists: Fix git tag -l and git ls-remote
- getGitHubReleaseUrl: Fix gh release view
- Fix worktree merge detection (2 more git commands)
- Remove unused execSync import

Code cleanup:
- Remove unused execSync imports from:
  - github/utils.ts
  - project-handlers.ts
  - settings-handlers.ts
  - release-service.ts

Total: 12 additional command injection fixes + 4 unused imports removed

This completes the security audit with 0 remaining vulnerabilities.

* refactor(code-quality): remove useless variable assignments

Fix CodeQL warnings about unused initial variable values:
- mainBranch: Declare without initial value, assign in try-catch
- unmergedCommits: Declare without initial value, assign in try-catch

The initial values were never used since they were always overwritten
either in the try block (success) or catch block (error fallback).

* test(security): update oauth-handlers tests to use execFileSync mocks

Update test mocks in oauth-handlers.spec.ts to match the security fix
that changed from execSync to execFileSync. All 525 tests now passing.

Changes:
- gh CLI Check Handler tests: Use mockExecFileSync with array args
- gh Auth Check Handler tests: Use mockExecFileSync with array args
- Fixed argument pattern: cmd + args array instead of single command string

Related to command injection prevention in oauth-handlers.ts
2025-12-27 15:53:49 +01:00
Mitsu 787667e98e refactor(components): remove deprecated TaskDetailPanel re-export (#344)
Remove the backwards compatibility re-export file `TaskDetailPanel.tsx`
that was only re-exporting from `./task-detail/`. This file was unused -
the app imports directly from `./task-detail/TaskDetailModal`.

Removed:
- `src/renderer/components/TaskDetailPanel.tsx` - unused re-export file
- Export from `index.ts`
2025-12-27 15:30:32 +01:00
souky-byte 9734b70b05 chore: Refactor/kanban realtime status sync (#249)
* fix(execution): add structured phase event emission and improve phase transition handling

- Add emit_phase() calls in coder.py for PLANNING, CODING, COMPLETE, and FAILED phases
- Add emit_phase() calls in planner.py for follow-up planning phase
- Add emit_phase() calls in qa/loop.py for QA_REVIEW, QA_FIXING, COMPLETE, and FAILED phases
- Add parsePhaseEvent() to agent-events.ts to prioritize structured events over log parsing
- Default to 'planning' phase in PhaseProgressIndicator when running but phase

* fix(execution): prevent premature 'complete' phase during QA workflow

- Remove COMPLETE phase emission from coder.py when subtasks finish (QA hasn't run yet)
- Add phase regression prevention in agent-events.ts to block fallback text matching from moving backwards (e.g., QA → coding)
- Remove 'complete' phase detection from "BUILD COMPLETE" banner text (only structured emit_phase(COMPLETE) from QA approval should set complete)
- Add line buffering in agent-process.ts to prevent split __EXEC_PHASE

* fix(execution): prevent phase regression and improve JSON parsing robustness

- Add phase regression check to 'planning' phase detection in agent-events.ts
- Prevent 'failed' phase from overwriting 'complete' or 'failed' from structured events in agent-process.ts
- Add extractJsonObject() to handle JSON with trailing garbage in phase-event-parser.ts
  - Implements brace-matching parser that handles escaped quotes and nested objects
  - Prevents parse failures when __EXEC_PHASE__ JSON is followed by log

* refactor: improve variable naming clarity in phase event parsing

- Rename 'escape' to 'isEscaped' in extractJsonObject() for better readability
- Rename list comprehension variable 'l' to 'line' in test_phase_event.py

* feat(agent-events): add Zod validation and refactor phase event parsing

- Add zod dependency (^4.2.1) for runtime type validation
- Refactor phase event parsing into specialized parser classes:
  - ExecutionPhaseParser for task execution phases
  - IdeationPhaseParser for ideation workflow phases
  - RoadmapPhaseParser for roadmap generation phases
- Add strict Zod schemas for phase event validation:
  - Reject invalid message types (must be string)
  - Reject invalid progress values (must be 0-100

* refactor(agent-events): remove parser delegation and inline phase detection logic

- Remove ExecutionPhaseParser, IdeationPhaseParser, and RoadmapPhaseParser delegation
- Inline all phase detection logic directly into AgentEvents methods
- Add wouldPhaseRegress() check to prevent fallback text matching from moving backwards
- Add parsePhaseEvent() call to prioritize structured __EXEC_PHASE__ events
- Add checkRegression() helper to validate phase transitions before applying fallback matches
- Filter

* test(subprocess): update test expectations to include newlines in buffered output

- Update subprocess-spawn.test.ts to append '\n' to test data and expectations
- Reflects line buffering behavior where output is processed line-by-line
- Skip ipc-handlers.test.ts exit event test (status change logic removed)
- Remove exit code 0 test case that no longer applies after status change removal

* refactor(ideation-phase-parser): add terminal state guard and extract progress calculation

- Add terminal state check to prevent phase changes after completion
- Extract calculateGeneratingProgress() helper with division-by-zero protection
- Return 90% progress fallback when totalTypes is 0 or negative
- Apply helper to both progress calculation paths (no phase change and phase detected)

* fix(phase-parser): prevent premature QA phase detection during planning

Add canEnterQAPhase guard to fallback text matching in agent-events.ts
and execution-phase-parser.ts. QA phases can now only be triggered via
text matching if currentPhase is already 'coding', 'qa_review', or
'qa_fixing'. This prevents tasks from jumping to QA Review column when
planning phase output contains QA-related text.

Structured events from backend (__EXEC_PHASE__:...) bypass this check.

* fix(task-store): prevent stale plan data from overriding status during active execution

When a task is restarted, the file watcher immediately reads the existing
implementation_plan.json and calls updateTaskFromPlan. If the old plan has
all subtasks completed, it would set status to 'ai_review' before the agent
process emits the 'planning' phase event.

This fix checks if the task is in an active execution phase (planning,
coding, qa_review, qa_fixing) and if so, does NOT let the plan data
override the status. The execution phase takes precedence.

Added 4 tests to verify the behavior.

* Reorder imports in coder.py for clarity

Moved the import of ExecutionPhase and emit_phase from phase_event to follow the project's import organization conventions and improve code readability.

* fix: address PR review comments from CodeRabbit

- Clamp progress values to 0-100 range in phase_event.py
- Remove unused PhaseEvent import in test file
- Simplify terminal phase check in ideation-phase-parser.ts
- Add regression prevention in roadmap-phase-parser.ts
- Use z.infer for PhaseEvent type derivation

* fix: add type assertions for Zod-validated phase values

TypeScript couldn't infer the literal type from Zod enum validation.
Added explicit type assertions since the phase is already validated.

* fix: correct misleading test name for QA loop transition

The test was named 'should not regress' but actually verified that
qa_fixing → qa_review IS allowed (valid re-review after fix).
Renamed to clarify the expected behavior.

* fix: define phase variable from rawPhase in PhaseProgressIndicator

The prop was renamed during destructuring but the derived variable
was never defined, causing 'phase is not defined' runtime error.

* fix(security): add Python path validation to prevent command injection

Add validatePythonPath() function that validates user-configurable Python
paths before use in spawn(). This prevents potential command injection
attacks via malicious paths.

Security checks implemented:
- Block shell metacharacters (;|&<> etc.)
- Validate against allowlist of known Python locations
- Verify file exists and is executable
- Confirm it's actually Python via --version

Applied validation to all affected locations:
- AgentProcessManager.configure()
- InsightsConfig.configure()
- ChangelogService.configure()
- TitleGenerator.configure()

Addresses: PR #249 review - CRITICAL security finding

* fix: add sequence tracking to prevent race conditions in state updates

Add sequenceNumber field to ExecutionProgress to track update order and
prevent stale updates from overwriting newer state.

Changes:
- Add sequenceNumber to ExecutionProgress interface
- updateExecutionProgress now rejects updates with lower sequence numbers
- All execution-progress emissions now include monotonically increasing
  sequence numbers

This prevents race conditions where out-of-order updates could cause
incorrect task state display.

Addresses: PR #249 review - HIGH severity race condition finding

* refactor: extract helper methods from spawnProcess() to reduce complexity

Break down the 294-line spawnProcess() into smaller focused methods:
- setupProcessEnvironment(): Creates the process environment object
- handleProcessFailure(): Orchestrates rate limit and auth failure handling
- handleRateLimitWithAutoSwap(): Handles auto-swap logic for rate limits
- handleAuthFailure(): Detects and handles authentication failures

The main spawnProcess() is now significantly cleaner with single-responsibility
helper methods that are easier to test and maintain.

Addresses: PR #249 review - HIGH severity complexity finding

* fix: improve phase handling with type guards and better error reporting

- Add type guard validation in checkRegression() before calling
  wouldPhaseRegress() to prevent undefined lookups in PHASE_ORDER_INDEX
- Add warning log when calculateOverallProgress() receives unknown phase
  instead of silently returning 0%
- Change 'failed' phase index from 5 to 99 to clearly indicate it's
  outside normal progression (like 'idle' uses -1)

These changes improve defensive programming and debugging capabilities
for phase state management.

Addresses: PR #249 review - MEDIUM severity findings

* refactor(security): consolidate Python path validation logic into reusable helper

Extract repeated validation pattern into getValidatedPythonPath() helper to reduce code duplication across services.

Changes:
- Add getValidatedPythonPath() helper that encapsulates validation logic
- Replace duplicated validation blocks in ChangelogService, InsightsConfig, and TitleGenerator with helper call
- Improve isSafePythonCommand() to normalize whitespace before checking
- Add newline/carriage return to DANGEROUS_SHELL_CHARS regex

* fix(tests): enable exit event forwarding test

- Remove it.skip from 'should forward exit events with status change on failure'
- Add proper test setup: create project and task before emitting exit event
- Add mock for notificationService to prevent errors during test

* fix(security): use mkdtempSync for secure temp directory in tests

Addresses CodeQL 'Insecure temporary file' warning by using
mkdtempSync with a random suffix instead of a predictable path.

---------

Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
Co-authored-by: Alex <63423455+AlexMadera@users.noreply.github.com>
2025-12-27 15:21:35 +01:00
Mitsu fec6b9f339 refactor(settings): remove deprecated ProjectSettings modal and hooks (#343)
The old ProjectSettings modal has been replaced by the unified AppSettings
dialog. This removes:

- `ProjectSettings.tsx` - deprecated modal component
- `project-settings/ProjectSettings.tsx` - unused refactored version
- `hooks/useProjectSettings.ts` - replaced by project-settings/hooks/
- `hooks/useEnvironmentConfig.ts` - only used by deprecated modal
- `hooks/useClaudeAuth.ts` - only used by deprecated modal
- `hooks/useLinearConnection.ts` - only used by deprecated modal
- `hooks/useGitHubConnection.ts` - only used by deprecated modal
- `hooks/useInfrastructureStatus.ts` - only used by deprecated modal

Updated index files to remove deprecated exports.
2025-12-27 15:02:58 +01:00
JoshuaRileyDev d3a63b09fd perf: convert synchronous I/O to async operations in worktree handlers (#337)
This commit optimizes the merge handler to prevent UI blocking by converting synchronous file operations to asynchronous I/O:

- Make handleProcessExit async to support async operations
- Replace readFileSync with fsPromises.readFile for commit message reading
- Refactor plan persistence to use async I/O with parallel updates via Promise.all()
- Implement fire-and-forget pattern for plan updates to prevent blocking the response
- Improve error handling with separate tracking for main vs worktree plans

These changes eliminate blocking I/O operations that could freeze the UI during merge operations, particularly when updating implementation plans across both the main project and worktree.

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

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 14:13:53 +01:00
Alex 50e3111ae2 feat: bump version (#329) 2025-12-26 22:55:47 +01:00
Michael Ludlow 8a80b1d5c8 fix(ci): remove version bump to fix branch protection conflict (#325) 2025-12-26 22:05:27 +01:00
Alex cb6b216534 fix(tasks): sync status to worktree implementation plan to prevent reset (#243) (#323)
Co-authored-by: Black Circle Sentinel <mludlow000@icloud.com>
2025-12-26 21:19:41 +01:00
Michael Ludlow 661e47c341 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>
2025-12-26 19:21:32 +01:00
Michael Ludlow e80ef79d12 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'.
2025-12-26 19:18:36 +01:00
Michael Ludlow e1b0f743bf 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
2025-12-26 17:48:32 +01:00
Alex 92c6f2786d 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>
2025-12-26 17:14:57 +01:00
Oluwatosin Oyeladun 1c14227324 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>
2025-12-26 15:21:26 +01:00
Andy c0a02a453d 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>
2025-12-26 14:36:20 +01:00
AndyMik90 086429cb49 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>
2025-12-26 14:19:54 +01:00
AndyMik90 d9fb8f29d5 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>
2025-12-26 14:15:15 +01:00
Andy d0b0b3df0d 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>
2025-12-26 13:55:47 +01:00
Andy 937a60f8bd 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>
2025-12-26 13:51:24 +01:00
Andy 7a51cbd5e5 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>
2025-12-26 13:47:19 +01:00
Andy 26beefe39d 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>
2025-12-26 13:42:45 +01:00
Alex 8416f3076a 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>
2025-12-26 10:31:27 +01:00
Andy 217249c8a3 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.
2025-12-26 09:24:01 +01:00
Andy 8bb3df917e 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>
2025-12-26 09:01:31 +01:00
Andy 5106c6e9b2 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>
2025-12-26 08:53:14 +01:00
Andy 3ff612742f 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>
2025-12-26 08:51:06 +01:00
Andy 7f19c2e1f3 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>
2025-12-25 22:38:05 +01:00
Todd W. Bucy d98e28305d 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>
2025-12-25 22:26:04 +01:00
AndyMik90 0b874d4b33 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>
2025-12-25 21:34:38 +01:00
dependabot[bot] 50dd10788a 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>
2025-12-25 21:05:35 +01:00
AndyMik90 f1cc5a09f2 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>
2025-12-25 20:53:03 +01:00
Andy b005fa5c86 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>
2025-12-25 20:52:22 +01:00
Andy d79f2da411 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>
2025-12-25 20:31:57 +01:00
dependabot[bot] 5ac566e2a2 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>
2025-12-25 20:05:29 +01:00
dependabot[bot] f49d4817b1 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>
2025-12-25 20:03:05 +01:00
Andy 1e1d7d9b68 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
2025-12-25 19:55:08 +01:00
Daniel Frey e74a3dffd2 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>
2025-12-25 19:53:55 +01:00
Daniel Frey 6ac8250b5b 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>
2025-12-25 19:53:33 +01:00
dependabot[bot] a2cee6941f 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>
2025-12-25 19:46:00 +01:00
dependabot[bot] d4cad80a73 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>
2025-12-25 19:42:21 +01:00
Andy 596e95137b 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>
2025-12-25 19:29:04 +01:00
Alex d42041c5b5 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>
2025-12-25 15:51:55 +01:00
delyethan a3f87540c6 fix: update path resolution for ollama_model_detector.py in memory handlers (#263) 2025-12-25 09:54:31 +01:00
Mitsu f843811292 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.
2025-12-24 17:37:31 +01:00
Andy 5e8c53080f Revert "Feat/Auto Fix Github issues and do extensive AI PR reviews (#250)" (#251)
This reverts commit 348de6dfe7.
2025-12-24 17:02:47 +01:00
Andy 348de6dfe7 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>
2025-12-24 16:43:20 +01:00
HSSAINI Saad 0f7d6e0530 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.
2025-12-24 14:03:49 +01:00
Joris Slagter 5ccdb6abc5 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>
2025-12-24 07:12:10 +01:00
souky-byte 6ec8549f63 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
2025-12-23 18:02:45 +01:00
Andy 53527293cd 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>
2025-12-23 18:00:55 +01:00
Fernando Possebon 02bef954f3 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>
2025-12-23 17:58:55 +01:00
Fernando Possebon f168bdc3ac fix: Add Python 3.10+ version validation and GitHub Actions Python setup (#180 #167) (#208)
This fixes critical bug where macOS users with default Python 3.9.6 couldn't use Auto-Claude because claude-agent-sdk requires Python 3.10+.

Root Cause:
- Auto-Claude doesn't bundle Python, relies on system Python
- python-detector.ts accepted any Python 3.x without checking minimum version
- macOS ships with Python 3.9.6 by default (incompatible)
- GitHub Actions runners didn't explicitly set Python version

Changes:
1. python-detector.ts:
   - Added getPythonVersion() to extract version from command
   - Added validatePythonVersion() to check if >= 3.10.0
   - Updated findPythonCommand() to skip Python < 3.10 with clear error messages

2. python-env-manager.ts:
   - Import and use findPythonCommand() (already has version validation)
   - Simplified findSystemPython() to use shared validation logic
   - Updated error message from "Python 3.9+" to "Python 3.10+" with download link

3. .github/workflows/release.yml:
   - Added Python 3.11 setup to all 4 build jobs (macOS Intel, macOS ARM64, Windows, Linux)
   - Ensures consistent Python version across all platforms during build

Impact:
- macOS users with Python 3.9 now see clear error with download link
- macOS users with Python 3.10+ work normally
- CI/CD builds use consistent Python 3.11
- Prevents "ModuleNotFoundError: dotenv" and dependency install failures

Fixes #180, #167

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

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 16:34:02 +01:00
Andy e3eec68aab fix(ci): correct welcome workflow PR message (#206)
- Change branch reference from main to develop
- Fix contribution guide link to use full URL
- Remove hyphen from "Auto Claude" in welcome message
2025-12-23 15:58:59 +01:00
Andy 407a0bee5e Feat/beta release (#193)
* chore: update README version to 2.7.1

Updated the version badge and download links in the README to reflect the new release version 2.7.1, ensuring users have the correct information for downloading the latest builds.

* feat(releases): add beta release system with user opt-in

Implements a complete beta release workflow that allows users to opt-in
to receiving pre-release versions. This enables testing new features
before they're included in stable releases.

Changes:
- Add beta-release.yml workflow for creating beta releases from develop
- Add betaUpdates setting with UI toggle in Settings > Updates
- Add update channel support to electron-updater (beta vs latest)
- Extract shared settings-utils.ts to reduce code duplication
- Add prepare-release.yml workflow for automated release preparation
- Document beta release process in CONTRIBUTING.md and RELEASE.md

Users can enable beta updates in Settings > Updates, and maintainers
can trigger beta releases via the GitHub Actions workflow.

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

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

* workflow update

* ci(github): update Discord link and redirect feature requests to discussions

Update Discord invite link to correct URL (QhRnz9m5HE) across all GitHub
templates and workflows. Redirect feature requests from issue template
to GitHub Discussions for better community engagement.

Changes:
- config.yml: Add feature request link to Discussions, fix Discord URL
- question.yml: Update Discord link in pre-question guidance
- welcome.yml: Update Discord link in first-time contributor message

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 15:20:09 +01:00
Andy 8f766ad16e feat/beta-release (#190)
* chore: update README version to 2.7.1

Updated the version badge and download links in the README to reflect the new release version 2.7.1, ensuring users have the correct information for downloading the latest builds.

* feat(releases): add beta release system with user opt-in

Implements a complete beta release workflow that allows users to opt-in
to receiving pre-release versions. This enables testing new features
before they're included in stable releases.

Changes:
- Add beta-release.yml workflow for creating beta releases from develop
- Add betaUpdates setting with UI toggle in Settings > Updates
- Add update channel support to electron-updater (beta vs latest)
- Extract shared settings-utils.ts to reduce code duplication
- Add prepare-release.yml workflow for automated release preparation
- Document beta release process in CONTRIBUTING.md and RELEASE.md

Users can enable beta updates in Settings > Updates, and maintainers
can trigger beta releases via the GitHub Actions workflow.

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

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

* workflow update

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 14:28:09 +01:00
Andy ced2ad479f fix/PRs from old main setup to apps structure (#185)
* fix(core): add task persistence, terminal handling, and HTTP 300 fixes

Consolidated bug fixes from PRs #168, #170, #171:

- Task persistence (#168): Scan worktrees for tasks on app restart
  to prevent loss of in-progress work and wasted API credits. Tasks
  in .worktrees/*/specs are now loaded and deduplicated with main.

- Terminal buttons (#170): Fix "Open Terminal" buttons silently
  failing on macOS by properly awaiting createTerminal() Promise.
  Added useTerminalHandler hook with loading states and error display.

- HTTP 300 errors (#171): Handle branch/tag name collisions that
  cause update failures. Added validation script to prevent conflicts
  before releases and user-friendly error messages with manual
  download links.

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

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

* fix(platform): add path resolution, spaces handling, and XDG support

This commit consolidates multiple bug fixes from community PRs:

- PR #187: Path resolution fix - Update path detection to find apps/backend
  instead of legacy auto-claude directory after v2.7.2 restructure

- PR #182/#155: Python path spaces fix - Improve parsePythonCommand() to
  handle quoted paths and paths containing spaces without splitting

- PR #161: Ollama detection fix - Add new apps structure paths for
  ollama_model_detector.py script discovery

- PR #160: AppImage support - Add XDG Base Directory compliant paths for
  Linux sandboxed environments (AppImage, Flatpak, Snap). New files:
  - config-paths.ts: XDG path utilities
  - fs-utils.ts: Filesystem utilities with fallback support

- PR #159: gh CLI PATH fix - Add getAugmentedEnv() utility to include
  common binary locations (Homebrew, snap, local) in PATH for child
  processes. Fixes gh CLI not found when app launched from Finder/Dock.

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

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

* fix: address CodeRabbit/Cursor review comments on PR #185

Fixes from code review:
- http-client.ts: Use GITHUB_CONFIG instead of hardcoded owner in HTTP 300 error message
- validate-release.js: Fix substring matching bug in branch detection that could cause false positives (e.g., v2.7 matching v2.7.2)
- bump-version.js: Remove unnecessary try-catch wrapper (exec() already exits on failure)
- execution-handlers.ts: Capture original subtask status before mutation for accurate logging
- fs-utils.ts: Add error handling to safeWriteFile with proper logging

Dismissed as trivial/not applicable:
- config-paths.ts: Exhaustive switch check (over-engineering)
- env-utils.ts: PATH priority documentation (existing comments sufficient)

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

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

* fix: address additional CodeRabbit review comments (round 2)

Fixes from second round of code review:
- fs-utils.ts: Wrap test file cleanup in try-catch for Windows file locking
- fs-utils.ts: Add error handling to safeReadFile for consistency with safeWriteFile
- http-client.ts: Use GITHUB_CONFIG in fetchJson (missed in first round)
- validate-release.js: Exclude symbolic refs (origin/HEAD -> origin/main) from branch check
- python-detector.ts: Return cleanPath instead of pythonPath for empty input edge case

Dismissed as trivial/not applicable:
- execution-handlers.ts: Redundant checkSubtasksCompletion call (micro-optimization)

🤖 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>
2025-12-23 13:33:11 +01:00
Andy 05f5d3038b fix: hide status badge when execution phase badge is showing (#154)
* fix: analyzer Python compatibility and settings integration

Fixes project index analyzer failing with TypeError on Python type hints.

Changes:
- Added 'from __future__ import annotations' to all analysis modules
- Fixed project discovery to support new analyzer JSON format
- Read Python path directly from settings.json instead of pythonEnvManager
- Added stderr/stdout logging for analyzer debugging

Resolves 'Discovered 0 files' and 'TypeError: unsupported operand type' issues.

* auto-claude: subtask-1-1 - Hide status badge when execution phase badge is showing

When a task has an active execution (planning, coding, etc.), the
execution phase badge already displays the correct state with a spinner.
The status badge was also rendering, causing duplicate/confusing badges
(e.g., both "Planning" and "Pending" showing at the same time).

This fix wraps the status badge in a conditional that only renders when
there's no active execution, eliminating the redundant badge display.

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

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

* fix(ipc): remove unused pythonEnvManager parameter and fix ES6 import

Address CodeRabbit review feedback:
- Remove unused pythonEnvManager parameter from registerProjectContextHandlers
  and registerContextHandlers (the code reads Python path directly from
  settings.json instead)
- Replace require('electron').app with proper ES6 import for consistency

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

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

* chore(lint): fix import sorting in analysis module

Run ruff --fix to resolve I001 lint errors after merging develop.
All 23 files in apps/backend/analysis/ now have properly sorted imports.

---------

Co-authored-by: Joris Slagter <mail@jorisslagter.nl>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:31:44 +01:00
Enes Cingöz 6951251b33 feat: Add UI scale feature with 75-200% range (#125)
* feat: add UI scale feature

* refactor: extract UI scale bounds to shared constants

* fix: duplicated import
2025-12-23 12:30:32 +01:00
AndyMik90 30e7536b63 fix(task): stop running process when task status changes away from in_progress
When a user drags a running task back to Planning (or any other column),
the process was not being stopped, leaving a "ghost" process that
prevented deletion with "Cannot delete a running task" error.

Now the task process is automatically killed when status changes away
from in_progress, ensuring the process state stays in sync with the UI.
2025-12-23 00:11:48 +01:00
Andy 220faf0fb4 Fix/linear 400 error
* fix: Linear API authentication and GraphQL types

- Remove Bearer prefix from Authorization header (Linear API keys are sent directly)
- Change GraphQL variable types from String! to ID! for teamId and issue IDs
- Improve error handling to show detailed Linear API error messages

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

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

* fix: Radix Select empty value error in Linear import modal

Use '__all__' sentinel value instead of empty string for "All projects"
option, as Radix Select does not allow empty string values.

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

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

* feat: add CodeRabbit configuration file

Introduce a new .coderabbit.yaml file to configure CodeRabbit settings, including review profiles, automatic review options, path filters, and specific instructions for different file types. This enhances the code review process by providing tailored guidelines for Python, TypeScript, and test files.

* fix: correct GraphQL types for Linear team queries

Linear API uses different types for different queries:
- team(id:) expects String!
- issues(filter: { team: { id: { eq: } } }) expects ID!

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

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

* fix: refresh task list after Linear import

Call loadTasks() after successful Linear import to update the kanban
board without requiring a page reload.

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

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

* cleanup

* cleanup

* fix: address CodeRabbit review comments for Linear integration

- Fix unsafe JSON parsing: check response.ok before parsing JSON to handle
  non-JSON error responses (e.g., 503 from proxy) gracefully
- Use ID! type instead of String! for teamId in LINEAR_GET_PROJECTS query
  for GraphQL type consistency
- Remove debug console.log (ESLint config only allows warn/error)
- Refresh task list on partial import success (imported > 0) instead of
  requiring full success
- Fix pre-existing TypeScript and lint issues blocking commit

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

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

* version sync logic

* lints for develop branch

* chore: update CI workflow to include develop branch

- Modified the CI configuration to trigger on pushes and pull requests to both main and develop branches, enhancing the workflow for development and integration processes.

* fix: update project directory auto-detection for apps/backend structure

The project directory auto-detection was checking for the old `auto-claude/`
directory name but needed to check for `apps/backend/`. When running from
`apps/backend/`, the directory name is `backend` not `auto-claude`, so the
check would fail and `project_dir` would incorrectly remain as `apps/backend/`
instead of resolving to the project root (2 levels up).

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

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

* fix: use GraphQL variables instead of string interpolation in LINEAR_GET_ISSUES

Replace direct string interpolation of teamId and linearProjectId with
proper GraphQL variables. This prevents potential query syntax errors if
IDs contain special characters like double quotes, and aligns with the
variable-based approach used elsewhere in the file.

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

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

* fix(ui): correct logging level and await loadTasks on import complete

- Change console.warn to console.log for import success messages
  (warn is incorrect severity for normal completion)
- Make onImportComplete callback async and await loadTasks()
  to prevent potential unhandled promise rejections

Applies CodeRabbit review feedback across 3 LinearTaskImportModal usages.

* fix(hooks): use POSIX-compliant find instead of bash glob

The pre-commit hook uses #!/bin/sh but had bash-specific ** glob
pattern for staging ruff-formatted files. The ** pattern only works
in bash with globstar enabled - in POSIX sh it expands literally
and won't match subdirectories, causing formatted files in nested
directories to not be staged.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:01:19 +01:00
Joris Slagter f96c6301f4 fix: remove legacy path from auto-claude source detection (#148)
Removes the legacy 'auto-claude' path from the possiblePaths array
in agent-process.ts. This path was from before the monorepo
restructure (v2.7.2) and is no longer needed.

The legacy path was causing spec_runner.py to be looked up at the
wrong location:
- OLD (wrong): /path/to/auto-claude/auto-claude/runners/spec_runner.py
- NEW (correct): /path/to/apps/backend/runners/spec_runner.py

This aligns with the new monorepo structure where all backend code
lives in apps/backend/.

Fixes #147

Co-authored-by: Joris Slagter <mail@jorisslagter.nl>
2025-12-22 22:59:48 +01:00
Joris Slagter ebd8340d82 fix: resolve Python environment race condition (#142)
Implemented promise queue pattern in PythonEnvManager to handle
concurrent initialization requests. Previously, multiple simultaneous
requests (e.g., startup + merge) would fail with "Already
initializing" error.

Also fixed parsePythonCommand() to handle file paths with spaces by
checking file existence before splitting on whitespace.

Changes:
- Added initializationPromise field to queue concurrent requests
- Split initialize() into public and private _doInitialize()
- Enhanced parsePythonCommand() with existsSync() check

Co-authored-by: Joris Slagter <mail@jorisslagter.nl>
2025-12-22 22:50:56 +01:00
rayBlock df779530e7 Feat: Ollama download progress tracking with new apps structure (#141)
* feat(ollama): add real-time download progress tracking for model downloads

Implement comprehensive download progress tracking with:
- NDJSON parsing for streaming progress data from Ollama API
- Real-time speed calculation (MB/s, KB/s, B/s) with useRef for delta tracking
- Time remaining estimation based on download speed
- Animated progress bars in OllamaModelSelector component
- IPC event streaming from main process to renderer
- Proper listener management with cleanup functions

Changes:
- memory-handlers.ts: Parse NDJSON from Ollama stderr, emit progress events
- OllamaModelSelector.tsx: Display progress bars with speed and time remaining
- project-api.ts: Implement onDownloadProgress listener with cleanup
- ipc.ts types: Define onDownloadProgress listener interface
- infrastructure-mock.ts: Add mock implementation for browser testing

This allows users to see real-time feedback when downloading Ollama models,
including percentage complete, current download speed, and estimated time remaining.

* test: add focused test coverage for Ollama download progress feature

Add unit tests for the critical paths of the real-time download progress tracking:

- Progress calculation tests (52 tests): Speed/time/percentage calculations with comprehensive edge case coverage (zero speeds, NaN, Infinity, large numbers)
- NDJSON parser tests (33 tests): Streaming JSON parsing from Ollama, buffer management for incomplete lines, error handling

All 562 unit tests passing with clean dependencies. Tests focus on critical mathematical logic and data processing - the most important paths that need verification.

Test coverage:
 Speed calculation and formatting (B/s, KB/s, MB/s)
 Time remaining calculations (seconds, minutes, hours)
 Percentage clamping (0-100%)
 NDJSON streaming with partial line buffering
 Invalid JSON handling
 Real Ollama API responses
 Multi-chunk streaming scenarios

* docs: add comprehensive JSDoc docstrings for Ollama download progress feature

- Enhanced OllamaModelSelector component with detailed JSDoc
  * Documented component props, behavior, and usage examples
  * Added docstrings to internal functions (checkInstalledModels, handleDownload, handleSelect)
  * Explained progress tracking algorithm and useRef usage

- Improved memory-handlers.ts documentation
  * Added docstring to main registerMemoryHandlers function
  * Documented all Ollama-related IPC handlers (check-status, list-embedding-models, pull-model)
  * Added JSDoc to executeOllamaDetector helper function
  * Documented interface types (OllamaStatus, OllamaModel, OllamaEmbeddingModel, OllamaPullResult)
  * Explained NDJSON parsing and progress event structure

- Enhanced test file documentation
  * Added docstrings to NDJSON parser test utilities with algorithm explanation
  * Documented all calculation functions (speed, time, percentage)
  * Added detailed comments on formatting and bounds-checking logic

- Improved overall code maintainability
  * Docstring coverage now meets 80%+ threshold for code review
  * Clear explanation of progress tracking implementation details
  * Better context for future maintainers working with download streaming

* feat: add batch task creation and management CLI commands

- Handle batch task creation from JSON files
- Show status of all specs in project
- Cleanup tool for completed specs
- Full integration with new apps/backend structure
- Compatible with implementation_plan.json workflow

* test: add batch task test file and testing checklist

- batch_test.json: Sample tasks for testing batch creation
- TESTING_CHECKLIST.md: Comprehensive testing guide for Ollama and batch tasks
- Includes UI testing steps, CLI testing steps, and edge cases
- Ready for manual and automated testing

* chore: update package-lock.json to match v2.7.2

* test: update checklist with verification results and architecture validation

* docs: add comprehensive implementation summary for Ollama + Batch features

* docs: add comprehensive Phase 2 testing guide with checklists and procedures

* docs: add NEXT_STEPS guide for Phase 2 testing

* fix: resolve merge conflict in project-api.ts from Ollama feature cherry-pick

* fix: remove duplicate Ollama check status handler registration

* test: update checklist with Phase 2 bug findings and fixes

---------

Co-authored-by: ray <ray@rays-MacBook-Pro.local>
2025-12-22 22:40:20 +01:00
Andy 0adaddacaa Feature/apps restructure v2.7.2 (#138)
* refactor: restructure project to Apps/frontend and Apps/backend

- Move auto-claude-ui to Apps/frontend with feature-based architecture
- Move auto-claude to Apps/backend
- Switch from pnpm to npm for frontend
- Update Node.js requirement to v24.12.0 LTS
- Add pre-commit hooks for lint, typecheck, and security audit
- Add commit-msg hook for conventional commits
- Fix CommonJS compatibility issues (postcss.config, postinstall scripts)
- Update README with comprehensive setup and contribution guidelines
- Configure ESLint to ignore .cjs files
- 0 npm vulnerabilities

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>

* feat(refactor): clean code and move to npm

* feat(refactor): clean code and move to npm

* chore: update to v2.7.0, remove Docker deps (LadybugDB is embedded)

* feat: v2.8.0 - update workflows and configs for Apps/ structure, npm

* fix: resolve Python lint errors (F401, I001)

* fix: update test paths for Apps/backend structure

* fix: add missing facade files and update paths for Apps/backend structure

- Fix ruff lint error I001 in auto_claude_tools.py
- Create missing facade files to match upstream (agent, ci_discovery, critique, etc.)
- Update test paths from auto-claude/ to Apps/backend/
- Update .pre-commit-config.yaml paths for Apps/ structure
- Add pytest to pre-commit hooks (skip slow/integration/Windows-incompatible tests)
- Fix Unicode encoding in test_agent_architecture.py for Windows

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>

* feat: improve readme

* fix: new path

* fix: correct release workflow and docs for Apps/ restructure

- Fix ARM64 macOS build: pnpm → npm, auto-claude-ui → Apps/frontend
- Fix artifact upload paths in release.yml
- Update Node.js version to 24 for consistency
- Update CLI-USAGE.md with Apps/backend paths
- Update RELEASE.md with Apps/frontend/package.json paths

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

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

* refactor: rename Apps/ to apps/ and fix backend path resolution

- Rename Apps/ folder to apps/ for consistency with JS/Node conventions
- Update all path references across CI/CD workflows, docs, and config files
- Fix frontend Python path resolver to look for 'backend' instead of 'auto-claude'
- Update path-resolver.ts to correctly find apps/backend in development mode

This completes the Apps restructure from PR #122 and prepares for v2.8.0 release.

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

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

* fix(electron): correct preload script path from .js to .mjs

electron-vite builds the preload script as ESM (index.mjs) but the main
process was looking for CommonJS (index.js). This caused the preload to
fail silently, making the app fall back to browser mock mode with fake
data and non-functional IPC handlers.

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

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

* - Introduced `dev:debug` script to enable debugging during development.
- Added `dev:mcp` script for running the frontend in MCP mode.

These enhancements streamline the development process for frontend developers.

* refactor(memory): make Graphiti memory mandatory and remove Docker dependency

Memory is now a core component of Auto Claude rather than optional:
- Python 3.12+ is required for the backend (not just memory layer)
- Graphiti is enabled by default in .env.example
- Removed all FalkorDB/Docker references (migrated to embedded LadybugDB)
- Deleted guides/DOCKER-SETUP.md and docker-handlers.ts
- Updated onboarding UI to remove "optional" language
- Updated all documentation to reflect LadybugDB architecture

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

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

* feat: add cross-platform Windows support for npm scripts

- Add scripts/install-backend.js for cross-platform Python venv setup
  - Auto-detects Python 3.12 (py -3.12 on Windows, python3.12 on Unix)
  - Handles platform-specific venv paths
- Add scripts/test-backend.js for cross-platform pytest execution
- Update package.json to use Node.js scripts instead of shell commands
- Update CONTRIBUTING.md with correct paths and instructions:
  - apps/backend/ and apps/frontend/ paths
  - Python 3.12 requirement (memory system now required)
  - Platform-specific install commands (winget, brew, apt)
  - npm instead of pnpm
  - Quick Start section with npm run install:all

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

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

* remove doc

* fix(frontend): correct Ollama detector script path after apps restructure

The Ollama status check was failing because memory-handlers.ts
was looking for ollama_model_detector.py at auto-claude/ but the
script is now at apps/backend/ after the directory restructure.

This caused "Ollama not running" to display even when Ollama was
actually running and accessible.

* chore: bump version to 2.7.2

Downgrade version from 2.8.0 to 2.7.2 as the Apps/ restructure
is better suited as a patch release rather than a minor release.

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

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

* chore: update package-lock.json for Windows compatibility

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

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

* docs(contributing): add hotfix workflow and update paths for apps/ structure

Add Git Flow hotfix workflow documentation with step-by-step guide
and ASCII diagram showing the branching strategy.

Update all paths from auto-claude/auto-claude-ui to apps/backend/apps/frontend
and migrate package manager references from pnpm to npm to match the
new project structure.

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

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

* fix(ci): remove duplicate ARM64 build from Intel runner

The Intel runner was building both x64 and arm64 architectures,
while a separate ARM64 runner also builds arm64 natively. This
caused duplicate ARM64 builds, wasting CI resources.

Now each runner builds only its native architecture:
- Intel runner: x64 only
- ARM64 runner: arm64 only

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

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

---------

Co-authored-by: Alex Madera <e.a_madera@hotmail.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 21:34:51 +01:00
AndyMik90 91f7051dda docs: Add Git Flow branching strategy to CONTRIBUTING.md
- Add comprehensive branching strategy documentation
- Explain main, develop, feature, fix, release, and hotfix branches
- Clarify that all PRs should target develop (not main)
- Add release process documentation for maintainers
- Update PR process to branch from develop
- Expand table of contents with new sections
2025-12-22 20:20:59 +01:00
1246 changed files with 57781 additions and 29989 deletions
+65
View File
@@ -0,0 +1,65 @@
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
# CodeRabbit Configuration
# Documentation: https://docs.coderabbit.ai/reference/configuration
language: "en-US"
reviews:
# Review profile: "chill" for fewer comments, "assertive" for more thorough feedback
profile: "assertive"
# Generate high-level summary in PR description
high_level_summary: true
# Automatic review settings
auto_review:
enabled: true
auto_incremental_review: true
# Target branches for review (in addition to default branch)
base_branches:
- develop
- "release/*"
- "hotfix/*"
# Skip review for PRs with these title keywords (case-insensitive)
ignore_title_keywords:
- "[WIP]"
- "WIP:"
- "DO NOT MERGE"
# Don't review draft PRs
drafts: false
# Path filters - exclude generated/vendor files
path_filters:
- "!**/node_modules/**"
- "!**/.venv/**"
- "!**/dist/**"
- "!**/build/**"
- "!**/*.lock"
- "!**/package-lock.json"
- "!**/*.min.js"
- "!**/*.min.css"
# Path-specific review instructions
path_instructions:
- path: "apps/backend/**/*.py"
instructions: |
Focus on Python best practices, type hints, and async patterns.
Check for proper error handling and security considerations.
Verify compatibility with Python 3.12+.
- path: "apps/frontend/**/*.{ts,tsx}"
instructions: |
Review React patterns and TypeScript type safety.
Check for proper state management and component composition.
- path: "tests/**"
instructions: |
Ensure tests are comprehensive and follow pytest conventions.
Check for proper mocking and test isolation.
chat:
auto_reply: true
knowledge_base:
opt_out: false
learnings:
scope: "auto"
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: AndyMik90
+50 -77
View File
@@ -1,75 +1,27 @@
name: Bug Report
description: Report a bug or unexpected behavior
labels: ["bug", "triage"]
name: 🐛 Bug Report
description: Something isn't working
labels: ["bug", "needs-triage"]
body:
- type: markdown
- type: checkboxes
id: checklist
attributes:
value: |
Thanks for taking the time to report a bug! Please fill out the sections below.
- type: textarea
id: description
attributes:
label: Bug Description
description: A clear and concise description of the bug.
placeholder: What happened?
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: What did you expect to happen?
placeholder: What should have happened?
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. Run command '...'
2. Click on '...'
3. See error
validations:
required: true
- type: textarea
id: logs
attributes:
label: Error Messages / Logs
description: If applicable, paste any error messages or logs.
render: shell
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain the problem.
label: Checklist
options:
- label: I searched existing issues and this hasn't been reported
required: true
- type: dropdown
id: component
id: area
attributes:
label: Component
description: Which part of Auto Claude is affected?
label: Area
options:
- Python Backend (auto-claude/)
- Electron UI (auto-claude-ui/)
- Both
- Frontend
- Backend
- Fullstack
- Not sure
validations:
required: true
- type: input
id: version
attributes:
label: Auto Claude Version
description: What version are you running? (check package.json or git tag)
placeholder: "v2.0.1"
- type: dropdown
id: os
attributes:
@@ -78,26 +30,47 @@ body:
- macOS
- Windows
- Linux
- Other
validations:
required: true
- type: input
id: python-version
id: version
attributes:
label: Python Version
description: Output of `python --version`
placeholder: "3.12.0"
- type: input
id: node-version
attributes:
label: Node.js Version (for UI issues)
description: Output of `node --version`
placeholder: "20.10.0"
label: Version
placeholder: "e.g., 2.5.5"
validations:
required: true
- type: textarea
id: additional
id: description
attributes:
label: Additional Context
description: Any other context about the problem.
label: What happened?
placeholder: Describe the bug clearly and concisely. Include any error messages you encountered.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. Run command '...' or click on '...'
2. Observe behavior '...'
3. See error or unexpected result
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
placeholder: What did you expect to happen instead? Describe the correct behavior.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs / Screenshots
description: Required for UI bugs. Attach relevant logs, screenshots, or error output.
render: shell
+5 -5
View File
@@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions & Discussions
- name: 💡 Feature Request
url: https://github.com/AndyMik90/Auto-Claude/discussions
about: Ask questions and discuss ideas with the community
- name: Documentation
url: https://github.com/AndyMik90/Auto-Claude#readme
about: Check the documentation before opening an issue
about: Suggest new features in GitHub Discussions
- name: 💬 Discord Community
url: https://discord.gg/QhRnz9m5HE
about: Questions and discussions - join our Discord!
+37
View File
@@ -0,0 +1,37 @@
name: 📚 Documentation
description: Improvements or additions to documentation
labels: ["documentation", "needs-triage", "help wanted"]
body:
- type: dropdown
id: type
attributes:
label: Type
options:
- Missing documentation
- Incorrect/outdated info
- Improvement suggestion
- Typo/grammar fix
validations:
required: true
- type: input
id: location
attributes:
label: Location
description: Which file or page?
placeholder: "e.g., README.md or guides/setup.md"
- type: textarea
id: description
attributes:
label: Description
description: What needs to change?
validations:
required: true
- type: checkboxes
id: contribute
attributes:
label: Contribution
options:
- label: I'm willing to submit a PR for this
@@ -1,70 +0,0 @@
name: Feature Request
description: Suggest a new feature or enhancement
labels: ["enhancement", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for suggesting a feature! Please describe your idea below.
- type: textarea
id: problem
attributes:
label: Problem Statement
description: What problem does this feature solve? Is this related to a frustration?
placeholder: I'm always frustrated when...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: Describe the solution you'd like to see.
placeholder: I would like Auto Claude to...
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: Have you considered any alternative solutions or workarounds?
placeholder: I've tried...
- type: dropdown
id: component
attributes:
label: Component
description: Which part of Auto Claude would this affect?
options:
- Python Backend (auto-claude/)
- Electron UI (auto-claude-ui/)
- Both
- New component
- Not sure
validations:
required: true
- type: dropdown
id: priority
attributes:
label: How important is this feature to you?
options:
- Nice to have
- Important for my workflow
- Critical / Blocking my use
- type: checkboxes
id: contribution
attributes:
label: Contribution
description: Would you be willing to help implement this?
options:
- label: I'm willing to submit a PR for this feature
- type: textarea
id: additional
attributes:
label: Additional Context
description: Add any other context, mockups, or screenshots about the feature request.
+61
View File
@@ -0,0 +1,61 @@
name: ❓ Question
description: Needs clarification
labels: ["question", "needs-triage"]
body:
- type: markdown
attributes:
value: |
**Before asking:** Check [Discord](https://discord.gg/QhRnz9m5HE) - your question may already be answered there!
- type: checkboxes
id: checklist
attributes:
label: Checklist
options:
- label: I searched existing issues and Discord for similar questions
required: true
- type: dropdown
id: area
attributes:
label: Area
options:
- Setup/Installation
- Frontend
- Backend
- Configuration
- Other
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: Which version are you using?
placeholder: "e.g., 2.7.1"
validations:
required: true
- type: textarea
id: question
attributes:
label: Question
placeholder: "Describe your question in detail..."
validations:
required: true
- type: textarea
id: context
attributes:
label: Context
description: What are you trying to achieve?
validations:
required: true
- type: textarea
id: attempts
attributes:
label: What have you already tried?
description: What steps have you taken to resolve this?
placeholder: "e.g., I tried reading the docs, searched for..."
+59 -27
View File
@@ -1,44 +1,76 @@
## Summary
## Base Branch
<!-- Brief description of what this PR does -->
- [ ] This PR targets the `develop` branch (required for all feature/fix PRs)
- [ ] This PR targets `main` (hotfix only - maintainers)
## Description
<!-- What does this PR do? 2-3 sentences -->
## Related Issue
Closes #
## Type of Change
- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] Tests (adding or updating tests)
- [ ] 🐛 Bug fix
- [ ] New feature
- [ ] 📚 Documentation
- [ ] ♻️ Refactor
- [ ] 🧪 Test
## Related Issues
## Area
<!-- Link any related issues: Fixes #123, Closes #456 -->
- [ ] Frontend
- [ ] Backend
- [ ] Fullstack
## Changes Made
## Commit Message Format
<!-- List the main changes in this PR -->
Follow conventional commits: `<type>: <subject>`
-
-
-
**Types:** feat, fix, docs, style, refactor, test, chore
## Screenshots
<!-- If applicable, add screenshots for UI changes -->
**Example:** `feat: add user authentication system`
## Checklist
- [ ] I have run `pre-commit run --all-files` and fixed any issues
- [ ] I have added tests for my changes (if applicable)
- [ ] All existing tests pass locally
- [ ] I have updated documentation (if applicable)
- [ ] My code follows the project's code style
- [ ] I've synced with `develop` branch
- [ ] I've tested my changes locally
- [ ] I've followed the code principles (SOLID, DRY, KISS)
- [ ] My PR is small and focused (< 400 lines ideally)
## Testing
## CI/Testing Requirements
<!-- Describe how you tested these changes -->
- [ ] All CI checks pass
- [ ] All existing tests pass
- [ ] New features include test coverage
- [ ] Bug fixes include regression tests
## Additional Notes
## Screenshots
<!-- Any additional context or notes for reviewers -->
<!-- Required for UI changes. Delete if not applicable. -->
| Before | After |
|--------|-------|
| | |
## Feature Toggle
<!-- If feature is incomplete or experimental, how is it hidden from users? -->
<!-- This ensures incomplete work can be merged without affecting production. -->
- [ ] Behind localStorage flag: `use_feature_name`
- [ ] Behind settings toggle
- [ ] Behind environment variable/config
- [ ] N/A - Feature is complete and ready for all users
## Breaking Changes
<!-- Does this PR introduce breaking changes? If yes, describe what breaks and migration steps. -->
<!-- Delete this section if not applicable. -->
**Breaking:** Yes / No
**Details:**
<!-- What breaks? What do users/developers need to change? -->
+37
View File
@@ -0,0 +1,37 @@
version: 2
updates:
# Python dependencies
- package-ecosystem: pip
directory: /apps/backend
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies
- python
commit-message:
prefix: "chore(deps)"
# npm dependencies
- package-ecosystem: npm
directory: /apps/frontend
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies
- javascript
commit-message:
prefix: "chore(deps)"
# GitHub Actions
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies
- ci
commit-message:
prefix: "ci(deps)"
+419
View File
@@ -0,0 +1,419 @@
name: Beta Release
# Manual trigger for beta releases from develop branch
on:
workflow_dispatch:
inputs:
version:
description: 'Beta version (e.g., 2.8.0-beta.1)'
required: true
type: string
dry_run:
description: 'Test build without creating release'
required: false
default: false
type: boolean
jobs:
validate-version:
name: Validate beta version format
runs-on: ubuntu-latest
steps:
- name: Validate version format
run: |
VERSION="${{ github.event.inputs.version }}"
# Check if version matches beta semver pattern
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-(beta|alpha|rc)\.[0-9]+$ ]]; then
echo "::error::Invalid version format: $VERSION"
echo "Version must match pattern: X.Y.Z-beta.N (e.g., 2.8.0-beta.1)"
exit 1
fi
echo "Valid beta version: $VERSION"
create-tag:
name: Create beta tag
needs: validate-version
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
version: ${{ github.event.inputs.version }}
steps:
- uses: actions/checkout@v4
with:
ref: develop
- name: Create and push tag
if: ${{ github.event.inputs.dry_run != 'true' }}
run: |
VERSION="${{ github.event.inputs.version }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v$VERSION" -m "Beta release v$VERSION"
git push origin "v$VERSION"
echo "Created tag v$VERSION"
- name: Create tag only (dry run)
if: ${{ github.event.inputs.dry_run == 'true' }}
run: |
VERSION="${{ github.event.inputs.version }}"
echo "DRY RUN: Would create tag v$VERSION"
# Intel build on Intel runner for native compilation
build-macos-intel:
needs: create-tag
runs-on: macos-15-intel
steps:
- uses: actions/checkout@v4
with:
# Use tag for real releases, develop branch for dry runs
ref: ${{ github.event.inputs.dry_run == 'true' && 'develop' || format('v{0}', needs.create-tag.outputs.version) }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-x64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-x64-
- name: Build application
run: cd apps/frontend && npm run build
- name: Package macOS (Intel)
run: |
VERSION="${{ needs.create-tag.outputs.version }}"
cd apps/frontend && npm run package:mac -- --x64 --config.extraMetadata.version="$VERSION"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
- name: Notarize macOS Intel app
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
if [ -z "$APPLE_ID" ]; then
echo "Skipping notarization: APPLE_ID not configured"
exit 0
fi
cd apps/frontend
for dmg in dist/*.dmg; do
echo "Notarizing $dmg..."
xcrun notarytool submit "$dmg" \
--apple-id "$APPLE_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait
xcrun stapler staple "$dmg"
echo "Successfully notarized and stapled $dmg"
done
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: macos-intel-builds
path: |
apps/frontend/dist/*.dmg
apps/frontend/dist/*.zip
apps/frontend/dist/*.yml
# Apple Silicon build on ARM64 runner for native compilation
build-macos-arm64:
needs: create-tag
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
# Use tag for real releases, develop branch for dry runs
ref: ${{ github.event.inputs.dry_run == 'true' && 'develop' || format('v{0}', needs.create-tag.outputs.version) }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-arm64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-arm64-
- name: Build application
run: cd apps/frontend && npm run build
- name: Package macOS (Apple Silicon)
run: |
VERSION="${{ needs.create-tag.outputs.version }}"
cd apps/frontend && npm run package:mac -- --arm64 --config.extraMetadata.version="$VERSION"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
- name: Notarize macOS ARM64 app
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
if [ -z "$APPLE_ID" ]; then
echo "Skipping notarization: APPLE_ID not configured"
exit 0
fi
cd apps/frontend
for dmg in dist/*.dmg; do
echo "Notarizing $dmg..."
xcrun notarytool submit "$dmg" \
--apple-id "$APPLE_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait
xcrun stapler staple "$dmg"
echo "Successfully notarized and stapled $dmg"
done
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: macos-arm64-builds
path: |
apps/frontend/dist/*.dmg
apps/frontend/dist/*.zip
apps/frontend/dist/*.yml
build-windows:
needs: create-tag
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
# Use tag for real releases, develop branch for dry runs
ref: ${{ github.event.inputs.dry_run == 'true' && 'develop' || format('v{0}', needs.create-tag.outputs.version) }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
- name: Get npm cache directory
id: npm-cache
shell: bash
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-x64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-x64-
- name: Build application
run: cd apps/frontend && npm run build
- name: Package Windows
shell: bash
run: |
VERSION="${{ needs.create-tag.outputs.version }}"
cd apps/frontend && npm run package:win -- --config.extraMetadata.version="$VERSION"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.WIN_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.WIN_CERTIFICATE_PASSWORD }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: windows-builds
path: |
apps/frontend/dist/*.exe
apps/frontend/dist/*.yml
build-linux:
needs: create-tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Use tag for real releases, develop branch for dry runs
ref: ${{ github.event.inputs.dry_run == 'true' && 'develop' || format('v{0}', needs.create-tag.outputs.version) }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-x64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-x64-
- name: Build application
run: cd apps/frontend && npm run build
- name: Package Linux
run: |
VERSION="${{ needs.create-tag.outputs.version }}"
cd apps/frontend && npm run package:linux -- --config.extraMetadata.version="$VERSION"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: linux-builds
path: |
apps/frontend/dist/*.AppImage
apps/frontend/dist/*.deb
apps/frontend/dist/*.yml
create-release:
needs: [create-tag, build-macos-intel, build-macos-arm64, build-windows, build-linux]
runs-on: ubuntu-latest
if: ${{ github.event.inputs.dry_run != 'true' }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: v${{ needs.create-tag.outputs.version }}
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist
- name: Flatten and validate artifacts
run: |
mkdir -p release-assets
find dist -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" -o -name "*.yml" \) -exec cp {} release-assets/ \;
# Validate that at least one artifact was copied
artifact_count=$(find release-assets -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" \) | wc -l)
if [ "$artifact_count" -eq 0 ]; then
echo "::error::No build artifacts found! Expected .dmg, .zip, .exe, .AppImage, or .deb files."
exit 1
fi
echo "Found $artifact_count artifact(s):"
ls -la release-assets/
- name: Generate checksums
run: |
cd release-assets
sha256sum ./* > checksums.sha256
cat checksums.sha256
- name: Create Beta Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-tag.outputs.version }}
name: v${{ needs.create-tag.outputs.version }} (Beta)
body: |
## Beta Release v${{ needs.create-tag.outputs.version }}
This is a **beta release** for testing new features. It may contain bugs or incomplete functionality.
### How to opt-in to beta updates
1. Open Auto Claude
2. Go to Settings > Updates
3. Enable "Beta Updates" toggle
### Reporting Issues
Please report any issues at https://github.com/AndyMik90/Auto-Claude/issues
---
**Full Changelog**: https://github.com/${{ github.repository }}/compare/main...v${{ needs.create-tag.outputs.version }}
files: release-assets/*
draft: false
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
dry-run-summary:
needs: [create-tag, build-macos-intel, build-macos-arm64, build-windows, build-linux]
runs-on: ubuntu-latest
if: ${{ github.event.inputs.dry_run == 'true' }}
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist
- name: Dry run summary
run: |
echo "## Beta Release Dry Run Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ needs.create-tag.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Build artifacts created successfully:" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
find dist -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" \) >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "To create a real release, run this workflow again with dry_run unchecked." >> $GITHUB_STEP_SUMMARY
+7 -12
View File
@@ -32,22 +32,17 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
node-version: '24'
- name: Install Visual Studio Build Tools
uses: microsoft/setup-msbuild@v2
- name: Install node-pty and rebuild for Electron
working-directory: auto-claude-ui
working-directory: apps/frontend
shell: pwsh
run: |
# Install only node-pty
pnpm add node-pty@1.1.0-beta42
npm install node-pty@1.1.0-beta42
# Get Electron ABI version
$electronAbi = (npx electron-abi $env:ELECTRON_VERSION)
@@ -57,7 +52,7 @@ jobs:
npx @electron/rebuild --version $env:ELECTRON_VERSION --module-dir node_modules/node-pty --arch ${{ matrix.arch }}
- name: Package prebuilt binaries
working-directory: auto-claude-ui
working-directory: apps/frontend
shell: pwsh
run: |
$electronAbi = (npx electron-abi $env:ELECTRON_VERSION)
@@ -83,7 +78,7 @@ jobs:
Get-ChildItem $prebuildDir
- name: Create archive
working-directory: auto-claude-ui
working-directory: apps/frontend
shell: pwsh
run: |
$electronAbi = (npx electron-abi $env:ELECTRON_VERSION)
@@ -98,14 +93,14 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: node-pty-win32-${{ matrix.arch }}
path: auto-claude-ui/node-pty-*.zip
path: apps/frontend/node-pty-*.zip
retention-days: 90
- name: Upload to release
if: github.event_name == 'release'
uses: softprops/action-gh-release@v1
with:
files: auto-claude-ui/node-pty-*.zip
files: apps/frontend/node-pty-*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+39 -31
View File
@@ -2,9 +2,17 @@ name: CI
on:
push:
branches: [main]
branches: [main, develop]
pull_request:
branches: [main]
branches: [main, develop]
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
actions: read
jobs:
# Python tests
@@ -29,30 +37,35 @@ jobs:
version: "latest"
- name: Install dependencies
working-directory: auto-claude
working-directory: apps/backend
run: |
uv venv
uv pip install -r requirements.txt
uv pip install -r ../tests/requirements-test.txt
uv pip install -r ../../tests/requirements-test.txt
- name: Run tests
working-directory: auto-claude
if: matrix.python-version != '3.12'
working-directory: apps/backend
env:
PYTHONPATH: ${{ github.workspace }}/apps/backend
run: |
source .venv/bin/activate
pytest ../tests/ -v --tb=short -x
pytest ../../tests/ -v --tb=short -x
- name: Run tests with coverage
if: matrix.python-version == '3.12'
working-directory: auto-claude
working-directory: apps/backend
env:
PYTHONPATH: ${{ github.workspace }}/apps/backend
run: |
source .venv/bin/activate
pytest ../tests/ -v --cov=. --cov-report=xml --cov-report=term-missing
pytest ../../tests/ -v --cov=. --cov-report=xml --cov-report=term-missing --cov-fail-under=20
- name: Upload coverage reports
if: matrix.python-version == '3.12'
uses: codecov/codecov-action@v4
with:
file: ./auto-claude/coverage.xml
file: ./apps/backend/coverage.xml
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -67,39 +80,34 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Get pnpm store directory
id: pnpm-cache
run: echo "dir=$(pnpm store path)" >> "$GITHUB_OUTPUT"
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"
- uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.dir }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
working-directory: auto-claude-ui
run: pnpm install --frozen-lockfile --ignore-scripts
working-directory: apps/frontend
run: npm ci --ignore-scripts
- name: Lint
working-directory: auto-claude-ui
run: pnpm run lint
working-directory: apps/frontend
run: npm run lint
- name: Type check
working-directory: auto-claude-ui
run: pnpm run typecheck
working-directory: apps/frontend
run: npm run typecheck
- name: Run tests
working-directory: auto-claude-ui
run: pnpm run test
working-directory: apps/frontend
run: npm run test
- name: Build
working-directory: auto-claude-ui
run: pnpm run build
working-directory: apps/frontend
run: npm run build
+53
View File
@@ -0,0 +1,53 @@
name: Issue Auto Label
on:
issues:
types: [opened]
jobs:
label-area:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add area label from form
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const body = issue.body || '';
console.log(`Processing issue #${issue.number}: ${issue.title}`);
// Map form selection to label
const areaMap = {
'Frontend': 'area/frontend',
'Backend': 'area/backend',
'Fullstack': 'area/fullstack'
};
const labels = [];
for (const [key, label] of Object.entries(areaMap)) {
if (body.includes(key)) {
console.log(`Found area: ${key}, adding label: ${label}`);
labels.push(label);
break;
}
}
if (labels.length > 0) {
try {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: labels
});
console.log(`Successfully added labels: ${labels.join(', ')}`);
} catch (error) {
core.setFailed(`Failed to add labels: ${error.message}`);
}
} else {
console.log('No matching area found in issue body');
}
+8 -32
View File
@@ -2,9 +2,13 @@ name: Lint
on:
push:
branches: [main]
branches: [main, develop]
pull_request:
branches: [main]
branches: [main, develop]
concurrency:
group: lint-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# Python linting
@@ -23,36 +27,8 @@ jobs:
run: pip install ruff
- name: Run ruff check
run: ruff check auto-claude/ --output-format=github
run: ruff check apps/backend/ --output-format=github
- name: Run ruff format check
run: ruff format auto-claude/ --check --diff
run: ruff format apps/backend/ --check --diff
# TypeScript/React linting
frontend:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
working-directory: auto-claude-ui
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Run ESLint
working-directory: auto-claude-ui
run: pnpm lint
- name: Run TypeScript check
working-directory: auto-claude-ui
run: pnpm typecheck
+227
View File
@@ -0,0 +1,227 @@
name: PR Auto Label
on:
pull_request:
types: [opened, synchronize, reopened]
# Cancel in-progress runs for the same PR
concurrency:
group: pr-auto-label-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
jobs:
label:
name: Auto Label PR
runs-on: ubuntu-latest
# Don't run on fork PRs (they can't write labels)
if: github.event.pull_request.head.repo.full_name == github.repository
timeout-minutes: 5
steps:
- name: Auto-label PR
uses: actions/github-script@v7
with:
retries: 3
retry-exempt-status-codes: 400,401,403,404,422
script: |
const { owner, repo } = context.repo;
const pr = context.payload.pull_request;
const prNumber = pr.number;
const title = pr.title;
console.log(`::group::PR #${prNumber} - Auto-labeling`);
console.log(`Title: ${title}`);
const labelsToAdd = new Set();
const labelsToRemove = new Set();
// ═══════════════════════════════════════════════════════════════
// TYPE LABELS (from PR title - Conventional Commits)
// ═══════════════════════════════════════════════════════════════
const typeMap = {
'feat': 'feature',
'fix': 'bug',
'docs': 'documentation',
'refactor': 'refactor',
'test': 'test',
'ci': 'ci',
'chore': 'chore',
'perf': 'performance',
'style': 'style',
'build': 'build'
};
const typeMatch = title.match(/^(\w+)(\(.+?\))?(!)?:/);
if (typeMatch) {
const type = typeMatch[1].toLowerCase();
const isBreaking = typeMatch[3] === '!';
if (typeMap[type]) {
labelsToAdd.add(typeMap[type]);
console.log(` 📝 Type: ${type} → ${typeMap[type]}`);
}
if (isBreaking) {
labelsToAdd.add('breaking-change');
console.log(` ⚠️ Breaking change detected`);
}
} else {
console.log(` ⚠️ No conventional commit prefix found in title`);
}
// ═══════════════════════════════════════════════════════════════
// AREA LABELS (from changed files)
// ═══════════════════════════════════════════════════════════════
let files = [];
try {
const { data } = await github.rest.pulls.listFiles({
owner,
repo,
pull_number: prNumber,
per_page: 100
});
files = data;
} catch (e) {
console.log(` ⚠️ Could not fetch files: ${e.message}`);
}
const areas = {
frontend: false,
backend: false,
ci: false,
docs: false,
tests: false
};
for (const file of files) {
const path = file.filename;
if (path.startsWith('apps/frontend/')) areas.frontend = true;
if (path.startsWith('apps/backend/')) areas.backend = true;
if (path.startsWith('.github/')) areas.ci = true;
if (path.endsWith('.md') || path.startsWith('docs/')) areas.docs = true;
if (path.startsWith('tests/') || path.includes('.test.') || path.includes('.spec.')) areas.tests = true;
}
// Determine area label (mutually exclusive)
const areaLabels = ['area/frontend', 'area/backend', 'area/fullstack', 'area/ci'];
if (areas.frontend && areas.backend) {
labelsToAdd.add('area/fullstack');
areaLabels.filter(l => l !== 'area/fullstack').forEach(l => labelsToRemove.add(l));
console.log(` 📁 Area: fullstack (${files.length} files)`);
} else if (areas.frontend) {
labelsToAdd.add('area/frontend');
areaLabels.filter(l => l !== 'area/frontend').forEach(l => labelsToRemove.add(l));
console.log(` 📁 Area: frontend (${files.length} files)`);
} else if (areas.backend) {
labelsToAdd.add('area/backend');
areaLabels.filter(l => l !== 'area/backend').forEach(l => labelsToRemove.add(l));
console.log(` 📁 Area: backend (${files.length} files)`);
} else if (areas.ci) {
labelsToAdd.add('area/ci');
areaLabels.filter(l => l !== 'area/ci').forEach(l => labelsToRemove.add(l));
console.log(` 📁 Area: ci (${files.length} files)`);
}
// ═══════════════════════════════════════════════════════════════
// SIZE LABELS (from lines changed)
// ═══════════════════════════════════════════════════════════════
const additions = pr.additions || 0;
const deletions = pr.deletions || 0;
const totalLines = additions + deletions;
const sizeLabels = ['size/XS', 'size/S', 'size/M', 'size/L', 'size/XL'];
let sizeLabel;
if (totalLines < 10) sizeLabel = 'size/XS';
else if (totalLines < 100) sizeLabel = 'size/S';
else if (totalLines < 500) sizeLabel = 'size/M';
else if (totalLines < 1000) sizeLabel = 'size/L';
else sizeLabel = 'size/XL';
labelsToAdd.add(sizeLabel);
sizeLabels.filter(l => l !== sizeLabel).forEach(l => labelsToRemove.add(l));
console.log(` 📏 Size: ${sizeLabel} (+${additions}/-${deletions} = ${totalLines} lines)`);
console.log('::endgroup::');
// ═══════════════════════════════════════════════════════════════
// APPLY LABELS
// ═══════════════════════════════════════════════════════════════
console.log(`::group::Applying labels`);
// Remove old labels (in parallel)
const removeArray = [...labelsToRemove].filter(l => !labelsToAdd.has(l));
if (removeArray.length > 0) {
const removePromises = removeArray.map(async (label) => {
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: label
});
console.log(` ✓ Removed: ${label}`);
} catch (e) {
if (e.status !== 404) {
console.log(` ⚠ Could not remove ${label}: ${e.message}`);
}
}
});
await Promise.all(removePromises);
}
// Add new labels
const addArray = [...labelsToAdd];
if (addArray.length > 0) {
try {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: addArray
});
console.log(` ✓ Added: ${addArray.join(', ')}`);
} catch (e) {
// Some labels might not exist
if (e.status === 404) {
core.warning(`Some labels do not exist. Please create them in repository settings.`);
// Try adding one by one
for (const label of addArray) {
try {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: [label]
});
} catch (e2) {
console.log(` ⚠ Label '${label}' does not exist`);
}
}
} else {
throw e;
}
}
}
console.log('::endgroup::');
// Summary
console.log(`✅ PR #${prNumber} labeled: ${addArray.join(', ')}`);
// Write job summary
core.summary
.addHeading(`PR #${prNumber} Auto-Labels`, 3)
.addTable([
[{data: 'Category', header: true}, {data: 'Label', header: true}],
['Type', typeMatch ? typeMap[typeMatch[1].toLowerCase()] || 'none' : 'none'],
['Area', areas.frontend && areas.backend ? 'fullstack' : areas.frontend ? 'frontend' : areas.backend ? 'backend' : 'other'],
['Size', sizeLabel]
])
.addRaw(`\n**Files changed:** ${files.length}\n`)
.addRaw(`**Lines:** +${additions} / -${deletions}\n`);
await core.summary.write();
+72
View File
@@ -0,0 +1,72 @@
name: PR Status Check
on:
pull_request:
types: [opened, synchronize, reopened]
# Cancel in-progress runs for the same PR
concurrency:
group: pr-status-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
pull-requests: write
jobs:
mark-checking:
name: Set Checking Status
runs-on: ubuntu-latest
# Don't run on fork PRs (they can't write labels)
if: github.event.pull_request.head.repo.full_name == github.repository
timeout-minutes: 5
steps:
- name: Update PR status label
uses: actions/github-script@v7
with:
retries: 3
retry-exempt-status-codes: 400,401,403,404,422
script: |
const { owner, repo } = context.repo;
const prNumber = context.payload.pull_request.number;
const statusLabels = ['🔄 Checking', '✅ Ready for Review', '❌ Checks Failed'];
console.log(`::group::PR #${prNumber} - Setting status to Checking`);
// Remove old status labels (parallel for speed)
const removePromises = statusLabels.map(async (label) => {
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: label
});
console.log(` ✓ Removed: ${label}`);
} catch (e) {
if (e.status !== 404) {
console.log(` ⚠ Could not remove ${label}: ${e.message}`);
}
}
});
await Promise.all(removePromises);
// Add checking label
try {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: ['🔄 Checking']
});
console.log(` ✓ Added: 🔄 Checking`);
} catch (e) {
// Label might not exist - create helpful error
if (e.status === 404) {
core.warning(`Label '🔄 Checking' does not exist. Please create it in repository settings.`);
}
throw e;
}
console.log('::endgroup::');
console.log(`✅ PR #${prNumber} marked as checking`);
+195
View File
@@ -0,0 +1,195 @@
name: PR Status Gate
on:
workflow_run:
workflows: [CI, Lint, Quality Security, Quality DCO, Quality Commit Lint]
types: [completed]
permissions:
pull-requests: write
checks: read
jobs:
update-status:
name: Update PR Status
runs-on: ubuntu-latest
# Only run if this workflow_run is associated with a PR
if: github.event.workflow_run.pull_requests[0] != null
timeout-minutes: 5
steps:
- name: Check all required checks and update label
uses: actions/github-script@v7
with:
retries: 3
retry-exempt-status-codes: 400,401,403,404,422
script: |
const { owner, repo } = context.repo;
const prNumber = context.payload.workflow_run.pull_requests[0].number;
const headSha = context.payload.workflow_run.head_sha;
const triggerWorkflow = context.payload.workflow_run.name;
// ═══════════════════════════════════════════════════════════════════════
// REQUIRED CHECK RUNS - Job-level checks (not workflow-level)
// ═══════════════════════════════════════════════════════════════════════
// Format: "{Workflow Name} / {Job Name} (pull_request)"
//
// To find check names: Go to PR → Checks tab → copy exact name
// To update: Edit this list when workflow jobs are added/renamed/removed
//
// Last validated: 2025-12-26
// ═══════════════════════════════════════════════════════════════════════
const requiredChecks = [
// CI workflow (ci.yml) - 3 checks
'CI / test-frontend (pull_request)',
'CI / test-python (3.12) (pull_request)',
'CI / test-python (3.13) (pull_request)',
// Lint workflow (lint.yml) - 1 check
'Lint / python (pull_request)',
// Quality Security workflow (quality-security.yml) - 4 checks
'Quality Security / CodeQL (javascript-typescript) (pull_request)',
'Quality Security / CodeQL (python) (pull_request)',
'Quality Security / Python Security (Bandit) (pull_request)',
'Quality Security / Security Summary (pull_request)',
// Quality DCO workflow (quality-dco.yml) - 1 check
'Quality DCO / DCO Check (pull_request)',
// Quality Commit Lint workflow (quality-commit-lint.yml) - 1 check
'Quality Commit Lint / Conventional Commits (pull_request)'
];
const statusLabels = {
checking: '🔄 Checking',
passed: '✅ Ready for Review',
failed: '❌ Checks Failed'
};
console.log(`::group::PR #${prNumber} - Checking required checks`);
console.log(`Triggered by: ${triggerWorkflow}`);
console.log(`Head SHA: ${headSha}`);
console.log(`Required checks: ${requiredChecks.length}`);
console.log('');
// Fetch all check runs for this commit
let allCheckRuns = [];
try {
const { data } = await github.rest.checks.listForRef({
owner,
repo,
ref: headSha,
per_page: 100
});
allCheckRuns = data.check_runs;
console.log(`Found ${allCheckRuns.length} total check runs`);
} catch (error) {
// Add warning annotation so maintainers are alerted
core.warning(`Failed to fetch check runs for PR #${prNumber}: ${error.message}. PR label may be outdated.`);
console.log(`::error::Failed to fetch check runs: ${error.message}`);
console.log('::endgroup::');
return;
}
let allComplete = true;
let anyFailed = false;
const results = [];
// Check each required check
for (const checkName of requiredChecks) {
const check = allCheckRuns.find(c => c.name === checkName);
if (!check) {
results.push({ name: checkName, status: '⏳ Pending', complete: false });
allComplete = false;
} else if (check.status !== 'completed') {
results.push({ name: checkName, status: '🔄 Running', complete: false });
allComplete = false;
} else if (check.conclusion === 'success') {
results.push({ name: checkName, status: '✅ Passed', complete: true });
} else if (check.conclusion === 'skipped') {
// Skipped checks are treated as passed (e.g., path filters, conditional jobs)
results.push({ name: checkName, status: '⏭️ Skipped', complete: true, skipped: true });
} else {
results.push({ name: checkName, status: '❌ Failed', complete: true, failed: true });
anyFailed = true;
}
}
// Print results table
console.log('');
console.log('Check Status:');
console.log('─'.repeat(70));
for (const r of results) {
const shortName = r.name.length > 55 ? r.name.substring(0, 52) + '...' : r.name;
console.log(` ${r.status.padEnd(12)} ${shortName}`);
}
console.log('─'.repeat(70));
console.log('::endgroup::');
// Only update label if all required checks are complete
if (!allComplete) {
const pending = results.filter(r => !r.complete).length;
console.log(`⏳ ${pending}/${requiredChecks.length} checks still pending - keeping current label`);
return;
}
// Determine final label
const newLabel = anyFailed ? statusLabels.failed : statusLabels.passed;
console.log(`::group::Updating PR #${prNumber} label`);
// Remove old status labels
for (const label of Object.values(statusLabels)) {
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: label
});
console.log(` ✓ Removed: ${label}`);
} catch (e) {
if (e.status !== 404) {
console.log(` ⚠ Could not remove ${label}: ${e.message}`);
}
}
}
// Add final status label
try {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: [newLabel]
});
console.log(` ✓ Added: ${newLabel}`);
} catch (e) {
if (e.status === 404) {
core.warning(`Label '${newLabel}' does not exist. Please create it in repository settings.`);
}
throw e;
}
console.log('::endgroup::');
// Summary
const passedCount = results.filter(r => r.status === '✅ Passed').length;
const skippedCount = results.filter(r => r.skipped).length;
const failedCount = results.filter(r => r.failed).length;
if (anyFailed) {
console.log(`❌ PR #${prNumber} has ${failedCount} failing check(s)`);
core.summary.addRaw(`## ❌ PR #${prNumber} - Checks Failed\n\n`);
core.summary.addRaw(`**${failedCount}** of **${requiredChecks.length}** required checks failed.\n\n`);
} else {
const skippedNote = skippedCount > 0 ? ` (${skippedCount} skipped)` : '';
const totalSuccessful = passedCount + skippedCount;
console.log(`✅ PR #${prNumber} is ready for review (${totalSuccessful}/${requiredChecks.length} checks succeeded${skippedNote})`);
core.summary.addRaw(`## ✅ PR #${prNumber} - Ready for Review\n\n`);
core.summary.addRaw(`All **${requiredChecks.length}** required checks succeeded${skippedNote}.\n\n`);
}
// Add results to summary
core.summary.addTable([
[{data: 'Check', header: true}, {data: 'Status', header: true}],
...results.map(r => [r.name, r.status])
]);
await core.summary.write();
+109
View File
@@ -0,0 +1,109 @@
name: Prepare Release
# Triggers when code is pushed to main (e.g., merging develop → main)
# If package.json version is newer than the latest tag, creates a new tag
# which then triggers the release.yml workflow
on:
push:
branches: [main]
paths:
- 'apps/frontend/package.json'
- 'package.json'
jobs:
check-and-tag:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
should_release: ${{ steps.check.outputs.should_release }}
new_version: ${{ steps.check.outputs.new_version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get package version
id: package
run: |
VERSION=$(node -p "require('./apps/frontend/package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Package version: $VERSION"
- name: Get latest tag version
id: latest_tag
run: |
# Get the latest version tag (v*)
LATEST_TAG=$(git tag -l 'v*' --sort=-version:refname | head -n1)
if [ -z "$LATEST_TAG" ]; then
echo "No existing tags found"
echo "version=0.0.0" >> $GITHUB_OUTPUT
else
# Remove 'v' prefix
LATEST_VERSION=${LATEST_TAG#v}
echo "version=$LATEST_VERSION" >> $GITHUB_OUTPUT
echo "Latest tag: $LATEST_TAG (version: $LATEST_VERSION)"
fi
- name: Check if release needed
id: check
run: |
PACKAGE_VERSION="${{ steps.package.outputs.version }}"
LATEST_VERSION="${{ steps.latest_tag.outputs.version }}"
echo "Comparing: package=$PACKAGE_VERSION vs latest_tag=$LATEST_VERSION"
# Use sort -V for version comparison
HIGHER=$(printf '%s\n%s' "$PACKAGE_VERSION" "$LATEST_VERSION" | sort -V | tail -n1)
if [ "$HIGHER" = "$PACKAGE_VERSION" ] && [ "$PACKAGE_VERSION" != "$LATEST_VERSION" ]; then
echo "should_release=true" >> $GITHUB_OUTPUT
echo "new_version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT
echo "✅ New release needed: v$PACKAGE_VERSION"
else
echo "should_release=false" >> $GITHUB_OUTPUT
echo "⏭️ No release needed (package version not newer than latest tag)"
fi
- name: Create and push tag
if: steps.check.outputs.should_release == 'true'
run: |
VERSION="${{ steps.check.outputs.new_version }}"
TAG="v$VERSION"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
echo "Creating tag: $TAG"
git tag -a "$TAG" -m "Release $TAG"
git push origin "$TAG"
echo "✅ Tag $TAG created and pushed"
echo "🚀 This will trigger the release workflow"
- name: Summary
run: |
if [ "${{ steps.check.outputs.should_release }}" = "true" ]; then
echo "## 🚀 Release Triggered" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** v${{ steps.check.outputs.new_version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The release workflow has been triggered and will:" >> $GITHUB_STEP_SUMMARY
echo "1. Build binaries for all platforms" >> $GITHUB_STEP_SUMMARY
echo "2. Generate changelog from PRs" >> $GITHUB_STEP_SUMMARY
echo "3. Create GitHub release" >> $GITHUB_STEP_SUMMARY
echo "4. Update README with new version" >> $GITHUB_STEP_SUMMARY
else
echo "## ⏭️ No Release Needed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Package version:** ${{ steps.package.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**Latest tag:** v${{ steps.latest_tag.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The package version is not newer than the latest tag." >> $GITHUB_STEP_SUMMARY
echo "To trigger a release, bump the version using:" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "node scripts/bump-version.js patch # or minor/major" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
fi
+115
View File
@@ -0,0 +1,115 @@
name: Quality Commit Lint
on:
pull_request:
branches: [main, develop]
types: [opened, edited, synchronize, reopened]
permissions:
contents: read
pull-requests: read
jobs:
check:
name: Conventional Commits
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Validate PR title
uses: actions/github-script@v7
with:
retries: 3
script: |
const pr = context.payload.pull_request;
const title = pr.title;
// Sanitize title for safe markdown interpolation (prevent injection)
const sanitizedTitle = title.replace(/`/g, "'").replace(/\[/g, '\\[').replace(/\]/g, '\\]');
console.log(`::group::PR #${pr.number} - Validating PR title`);
console.log(`Title: ${title}`);
// Conventional Commits pattern for PR title
// type(scope)?: description (max 100 chars)
// Optional ! for breaking changes: feat!: or feat(scope)!:
// Scope allows: letters, numbers, hyphens, underscores, slashes, dots
const pattern = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-zA-Z0-9_\-\/\.]+\))?!?: .{1,100}$/;
const isValid = pattern.test(title);
console.log(`Valid: ${isValid}`);
console.log('::endgroup::');
if (!isValid) {
// Log helpful error message to console (visible in workflow logs)
console.log('');
console.log('❌ PR title does not follow Conventional Commits format');
console.log('');
console.log('Expected format: type(scope): description');
console.log('');
console.log('Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert');
console.log('');
console.log('Examples of valid PR titles:');
console.log(' ✓ feat(auth): add OAuth2 login support');
console.log(' ✓ fix(api): handle null response correctly');
console.log(' ✓ docs: update README installation steps');
console.log(' ✓ chore: update dependencies');
console.log('');
console.log(`Your title: "${title}"`);
console.log('');
console.log('Suggested fix for your title:');
// Try to suggest a fix based on the title
const lowerTitle = title.toLowerCase();
const placeholder = '[add description here]';
if (lowerTitle.includes('fix') || lowerTitle.includes('bug')) {
const cleaned = title.replace(/^(fix(ed|es|ing)?|bug)[:\s]*/i, '').trim();
console.log(` → fix: ${cleaned || placeholder}`);
} else if (lowerTitle.includes('add') || lowerTitle.includes('new') || lowerTitle.includes('feature')) {
const cleaned = title.replace(/^(add(ed|s|ing)?|new|features?)[:\s]*/i, '').trim();
console.log(` → feat: ${cleaned || placeholder}`);
} else if (lowerTitle.includes('update') || lowerTitle.includes('change')) {
const cleaned = title.replace(/^(update[ds]?|chang(ed|es|ing)?)[:\s]*/i, '').trim();
console.log(` → chore: ${cleaned || placeholder}`);
} else if (lowerTitle.includes('doc') || lowerTitle.includes('readme')) {
const cleaned = title.replace(/^(docs?|readme)[:\s]*/i, '').trim();
console.log(` → docs: ${cleaned || placeholder}`);
} else {
console.log(` → feat: ${title}`);
console.log(` → fix: ${title}`);
console.log(` → chore: ${title}`);
}
console.log('');
let errorMsg = '## ❌ PR Title Validation Failed\n\n';
errorMsg += `Your PR title does not follow [Conventional Commits](https://www.conventionalcommits.org/) format:\n\n`;
errorMsg += `> \`${sanitizedTitle}\`\n\n`;
errorMsg += '### Expected Format\n\n';
errorMsg += '```\ntype(scope): description\n```\n\n';
errorMsg += '| Type | Description |\n';
errorMsg += '|------|-------------|\n';
errorMsg += '| `feat` | New feature |\n';
errorMsg += '| `fix` | Bug fix |\n';
errorMsg += '| `docs` | Documentation only |\n';
errorMsg += '| `style` | Code style (formatting, etc.) |\n';
errorMsg += '| `refactor` | Code refactoring |\n';
errorMsg += '| `perf` | Performance improvement |\n';
errorMsg += '| `test` | Adding/updating tests |\n';
errorMsg += '| `build` | Build system changes |\n';
errorMsg += '| `ci` | CI/CD changes |\n';
errorMsg += '| `chore` | Maintenance tasks |\n';
errorMsg += '| `revert` | Reverting changes |\n\n';
errorMsg += '### Examples\n\n';
errorMsg += '```\nfeat(auth): add OAuth2 login support\nfix(api/users): handle null response correctly\nfix(package.json): update dependencies\ndocs: update README installation steps\nci: add automated release workflow\n```\n\n';
errorMsg += '### How to Fix\n\n';
errorMsg += 'Edit your PR title to follow the format above.\n';
core.summary.addRaw(errorMsg);
await core.summary.write();
core.setFailed('PR title does not follow Conventional Commits format');
} else {
console.log(`✅ PR title follows Conventional Commits format`);
core.summary
.addHeading('✅ PR Title Valid', 3)
.addRaw(`PR title follows Conventional Commits format: \`${sanitizedTitle}\``);
await core.summary.write();
}
+70
View File
@@ -0,0 +1,70 @@
name: Quality DCO
on:
pull_request:
branches: [main, develop]
permissions:
contents: read
pull-requests: read
jobs:
check:
name: DCO Check
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check DCO Sign-off
uses: dcoapp/dco-check@v1
with:
require-signoff: true
- name: DCO Help on Failure
if: failure()
uses: actions/github-script@v7
with:
script: |
const helpMsg = `## ❌ DCO Sign-off Required
This project requires all commits to be signed off with the Developer Certificate of Origin (DCO).
### How to Fix
**Option 1: Sign off your last commit**
\`\`\`bash
git commit --amend --signoff
git push --force-with-lease
\`\`\`
**Option 2: Sign off all commits in this PR**
\`\`\`bash
git rebase HEAD~N --signoff # Replace N with number of commits
git push --force-with-lease
\`\`\`
**Option 3: Configure git to always sign off**
\`\`\`bash
git config --global format.signoff true
\`\`\`
### What is DCO?
The [Developer Certificate of Origin](https://developercertificate.org/) is a lightweight way for contributors to certify that they wrote or have the right to submit the code they are contributing.
By signing off, you agree to the DCO terms:
- The contribution was created by you
- You have the right to submit it under the project's license
- You understand the contribution is public and recorded
### Sign-off Format
Your commit message should end with:
\`\`\`
Signed-off-by: Your Name <your.email@example.com>
\`\`\`
This line is automatically added when you use \`git commit -s\` or \`git commit --signoff\`.
`;
core.summary.addRaw(helpMsg);
await core.summary.write();
+178
View File
@@ -0,0 +1,178 @@
name: Quality Security
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
schedule:
- cron: '0 0 * * 1' # Weekly on Monday at midnight UTC
# Cancel in-progress runs for the same branch/PR
concurrency:
group: security-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
security-events: write
actions: read
jobs:
codeql:
name: CodeQL (${{ matrix.language }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
language: [python, javascript-typescript]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: +security-extended,security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
python-security:
name: Python Security (Bandit)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Bandit
run: pip install bandit
- name: Run Bandit security scan
id: bandit
run: |
echo "::group::Running Bandit security scan"
# Run Bandit; exit code 1 means issues found (expected), other codes are errors
# Flags: -r=recursive, -ll=severity LOW+, -ii=confidence LOW+, -f=format, -o=output
bandit -r apps/backend/ -ll -ii -f json -o bandit-report.json || BANDIT_EXIT=$?
if [ "${BANDIT_EXIT:-0}" -gt 1 ]; then
echo "::error::Bandit scan failed with exit code $BANDIT_EXIT"
exit 1
fi
echo "::endgroup::"
- name: Analyze Bandit results
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Check if report exists
if (!fs.existsSync('bandit-report.json')) {
core.setFailed('Bandit report not found - scan may have failed');
return;
}
const report = JSON.parse(fs.readFileSync('bandit-report.json', 'utf8'));
const results = report.results || [];
// Categorize by severity
const high = results.filter(r => r.issue_severity === 'HIGH');
const medium = results.filter(r => r.issue_severity === 'MEDIUM');
const low = results.filter(r => r.issue_severity === 'LOW');
console.log(`::group::Bandit Security Scan Results`);
console.log(`Found ${results.length} issues:`);
console.log(` 🔴 HIGH: ${high.length}`);
console.log(` 🟡 MEDIUM: ${medium.length}`);
console.log(` 🟢 LOW: ${low.length}`);
console.log('');
// Print high severity issues
if (high.length > 0) {
console.log('High Severity Issues:');
console.log('─'.repeat(60));
for (const issue of high) {
console.log(` ${issue.filename}:${issue.line_number}`);
console.log(` ${issue.issue_text}`);
console.log(` Test: ${issue.test_id} (${issue.test_name})`);
console.log('');
}
}
console.log('::endgroup::');
// Build summary
let summary = `## 🔒 Python Security Scan (Bandit)\n\n`;
summary += `| Severity | Count |\n`;
summary += `|----------|-------|\n`;
summary += `| 🔴 High | ${high.length} |\n`;
summary += `| 🟡 Medium | ${medium.length} |\n`;
summary += `| 🟢 Low | ${low.length} |\n\n`;
if (high.length > 0) {
summary += `### High Severity Issues\n\n`;
for (const issue of high) {
summary += `- **${issue.filename}:${issue.line_number}**\n`;
summary += ` - ${issue.issue_text}\n`;
summary += ` - Test: \`${issue.test_id}\` (${issue.test_name})\n\n`;
}
}
core.summary.addRaw(summary);
await core.summary.write();
// Fail if high severity issues found
if (high.length > 0) {
core.setFailed(`Found ${high.length} high severity security issue(s)`);
} else {
console.log('✅ No high severity security issues found');
}
# Summary job that waits for all security checks
security-summary:
name: Security Summary
runs-on: ubuntu-latest
needs: [codeql, python-security]
if: always()
timeout-minutes: 5
steps:
- name: Check security results
uses: actions/github-script@v7
with:
script: |
const codeql = '${{ needs.codeql.result }}';
const bandit = '${{ needs.python-security.result }}';
console.log('Security Check Results:');
console.log(` CodeQL: ${codeql}`);
console.log(` Bandit: ${bandit}`);
// Only 'failure' is a real failure; 'skipped' is acceptable (e.g., path filters)
const acceptable = ['success', 'skipped'];
const codeqlOk = acceptable.includes(codeql);
const banditOk = acceptable.includes(bandit);
const allPassed = codeqlOk && banditOk;
if (allPassed) {
console.log('\n✅ All security checks passed');
core.summary.addRaw('## ✅ Security Checks Passed\n\nAll security scans completed successfully.');
} else {
console.log('\n❌ Some security checks failed');
core.summary.addRaw('## ❌ Security Checks Failed\n\nOne or more security scans found issues.');
core.setFailed('Security checks failed');
}
await core.summary.write();
+150 -69
View File
@@ -20,34 +20,42 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Get pnpm store directory
id: pnpm-cache
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.dir }}
key: ${{ runner.os }}-x64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-x64-pnpm-
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd auto-claude-ui && pnpm install --frozen-lockfile
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-x64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-x64-
- name: Build application
run: cd auto-claude-ui && pnpm run build
run: cd apps/frontend && npm run build
- name: Package macOS (Intel)
run: cd auto-claude-ui && pnpm run package:mac -- --arch=x64
run: cd apps/frontend && npm run package:mac -- --x64
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
@@ -63,7 +71,7 @@ jobs:
echo "Skipping notarization: APPLE_ID not configured"
exit 0
fi
cd auto-claude-ui
cd apps/frontend
for dmg in dist/*.dmg; do
echo "Notarizing $dmg..."
xcrun notarytool submit "$dmg" \
@@ -80,8 +88,8 @@ jobs:
with:
name: macos-intel-builds
path: |
auto-claude-ui/dist/*.dmg
auto-claude-ui/dist/*.zip
apps/frontend/dist/*.dmg
apps/frontend/dist/*.zip
# Apple Silicon build on ARM64 runner for native compilation
build-macos-arm64:
@@ -89,34 +97,42 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Get pnpm store directory
id: pnpm-cache
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.dir }}
key: ${{ runner.os }}-arm64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-arm64-pnpm-
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd auto-claude-ui && pnpm install --frozen-lockfile
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-arm64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-arm64-
- name: Build application
run: cd auto-claude-ui && pnpm run build
run: cd apps/frontend && npm run build
- name: Package macOS (Apple Silicon)
run: cd auto-claude-ui && pnpm run package:mac -- --arch=arm64
run: cd apps/frontend && npm run package:mac -- --arm64
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
@@ -132,7 +148,7 @@ jobs:
echo "Skipping notarization: APPLE_ID not configured"
exit 0
fi
cd auto-claude-ui
cd apps/frontend
for dmg in dist/*.dmg; do
echo "Notarizing $dmg..."
xcrun notarytool submit "$dmg" \
@@ -149,43 +165,51 @@ jobs:
with:
name: macos-arm64-builds
path: |
auto-claude-ui/dist/*.dmg
auto-claude-ui/dist/*.zip
apps/frontend/dist/*.dmg
apps/frontend/dist/*.zip
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Get pnpm store directory
id: pnpm-cache
- name: Get npm cache directory
id: npm-cache
shell: bash
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.dir }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd auto-claude-ui && pnpm install --frozen-lockfile
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-x64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-x64-
- name: Build application
run: cd auto-claude-ui && pnpm run build
run: cd apps/frontend && npm run build
- name: Package Windows
run: cd auto-claude-ui && pnpm run package:win
run: cd apps/frontend && npm run package:win
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.WIN_CERTIFICATE }}
@@ -196,41 +220,49 @@ jobs:
with:
name: windows-builds
path: |
auto-claude-ui/dist/*.exe
apps/frontend/dist/*.exe
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Get pnpm store directory
id: pnpm-cache
run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Get npm cache directory
id: npm-cache
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.dir }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
run: cd auto-claude-ui && pnpm install --frozen-lockfile
run: cd apps/frontend && npm ci
- name: Cache bundled Python
uses: actions/cache@v4
with:
path: apps/frontend/python-runtime
key: python-bundle-${{ runner.os }}-x64-3.12.8
restore-keys: |
python-bundle-${{ runner.os }}-x64-
- name: Build application
run: cd auto-claude-ui && pnpm run build
run: cd apps/frontend && npm run build
- name: Package Linux
run: cd auto-claude-ui && pnpm run package:linux
run: cd apps/frontend && npm run package:linux
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -239,8 +271,8 @@ jobs:
with:
name: linux-builds
path: |
auto-claude-ui/dist/*.AppImage
auto-claude-ui/dist/*.deb
apps/frontend/dist/*.AppImage
apps/frontend/dist/*.deb
create-release:
needs: [build-macos-intel, build-macos-arm64, build-windows, build-linux]
@@ -451,3 +483,52 @@ jobs:
prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Update README with new version after successful release
update-readme:
needs: [create-release]
runs-on: ubuntu-latest
if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: main
token: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
id: version
run: |
# Extract version from tag (v2.7.2 -> 2.7.2)
VERSION=${GITHUB_REF_NAME#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Updating README to version: $VERSION"
- name: Update README.md
run: |
VERSION="${{ steps.version.outputs.version }}"
# Update version badge: version-X.Y.Z-blue
sed -i "s/version-[0-9]*\.[0-9]*\.[0-9]*-blue/version-${VERSION}-blue/g" README.md
# Update download links: Auto-Claude-X.Y.Z
sed -i "s/Auto-Claude-[0-9]*\.[0-9]*\.[0-9]*/Auto-Claude-${VERSION}/g" README.md
echo "README.md updated to version $VERSION"
grep -E "(version-|Auto-Claude-)" README.md | head -10
- name: Commit and push README update
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Check if there are changes to commit
if git diff --quiet README.md; then
echo "No changes to README.md, skipping commit"
exit 0
fi
git add README.md
git commit -m "docs: update README to v${{ steps.version.outputs.version }} [skip ci]"
git push origin main
+25
View File
@@ -0,0 +1,25 @@
name: Stale Issues
on:
schedule:
- cron: '0 0 * * 0' # Every Sunday
workflow_dispatch:
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/stale@v9
with:
stale-issue-message: |
This issue has been inactive for 60 days. It will be closed in 14 days if there's no activity.
- If this is still relevant, please comment or update the issue
- If you're working on this, add the `in-progress` label
close-issue-message: 'Closed due to inactivity. Feel free to reopen if still relevant.'
stale-issue-label: 'stale'
days-before-stale: 60
days-before-close: 14
exempt-issue-labels: 'priority/critical,priority/high,in-progress,blocked'
+11 -14
View File
@@ -28,17 +28,19 @@ jobs:
version: "latest"
- name: Install dependencies
working-directory: auto-claude
working-directory: apps/backend
run: |
uv venv
uv pip install -r requirements.txt
uv pip install -r ../tests/requirements-test.txt
uv pip install -r ../../tests/requirements-test.txt
- name: Run tests
working-directory: auto-claude
working-directory: apps/backend
env:
PYTHONPATH: ${{ github.workspace }}/apps/backend
run: |
source .venv/bin/activate
pytest ../tests/ -v --tb=short
pytest ../../tests/ -v --tb=short
# Frontend tests
test-frontend:
@@ -50,17 +52,12 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
node-version: '24'
- name: Install dependencies
working-directory: auto-claude-ui
run: pnpm install --frozen-lockfile --ignore-scripts
working-directory: apps/frontend
run: npm ci --ignore-scripts
- name: Run tests
working-directory: auto-claude-ui
run: pnpm test
working-directory: apps/frontend
run: npm run test
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
id: package_version
run: |
# Read version from package.json
PACKAGE_VERSION=$(node -p "require('./auto-claude-ui/package.json').version")
PACKAGE_VERSION=$(node -p "require('./apps/frontend/package.json').version")
echo "version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT
echo "Package.json version: $PACKAGE_VERSION"
+33
View File
@@ -0,0 +1,33 @@
name: Welcome
on:
pull_request_target:
types: [opened]
issues:
types: [opened]
jobs:
welcome:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: |
👋 Thanks for opening your first issue!
A maintainer will triage this soon. In the meantime:
- Make sure you've provided all the requested info
- Join our [Discord](https://discord.gg/QhRnz9m5HE) for faster help
pr-message: |
🎉 Thanks for your first PR!
A maintainer will review it soon. Please make sure:
- Your branch is synced with `develop`
- CI checks pass
- You've followed our [contribution guide](https://github.com/AndyMik90/Auto-Claude/blob/develop/CONTRIBUTING.md)
Welcome to the Auto Claude community!
+112 -36
View File
@@ -1,31 +1,69 @@
# OS
# ===========================
# OS Files
# ===========================
.DS_Store
.DS_Store?
._*
Thumbs.db
ehthumbs.db
Desktop.ini
# Environment files (contain API keys)
# ===========================
# Security - Environment & Secrets
# ===========================
.env
.env.local
.env.*
!.env.example
*.pem
*.key
*.crt
*.p12
*.pfx
.secrets
secrets/
credentials/
# Git worktrees (used by auto-build parallel mode)
.worktrees/
# IDE
# ===========================
# IDE & Editors
# ===========================
.idea/
.vscode/
*.swp
*.swo
*.sublime-workspace
*.sublime-project
.project
.classpath
.settings/
# ===========================
# Logs
# ===========================
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Personal notes
OPUS_ANALYSIS_AND_IDEAS.md
# ===========================
# Git Worktrees (parallel builds)
# ===========================
.worktrees/
# Documentation
docs/
# ===========================
# Auto Claude Generated
# ===========================
.auto-claude/
.auto-build-security.json
.auto-claude-security.json
.auto-claude-status
.claude_settings.json
.update-metadata.json
# Python
# ===========================
# Python (apps/backend)
# ===========================
__pycache__/
*.py[cod]
*$py.class
@@ -33,25 +71,19 @@ __pycache__/
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
/lib/
/lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Virtual environments
.venv/
venv/
ENV/
env/
.conda/
# Testing
.pytest_cache/
@@ -64,26 +96,70 @@ coverage.xml
*.py,cover
.hypothesis/
# mypy
# Type checking
.mypy_cache/
.dmypy.json
dmypy.json
.pytype/
.pyre/
# Auto-build generated files
.auto-build-security.json
.auto-claude-security.json
.auto-claude-status
.claude_settings.json
.update-metadata.json
# ===========================
# Node.js (apps/frontend)
# ===========================
node_modules/
.npm
.yarn/
.pnp.*
# Development of Auto Build with Auto Build
# Build output
dist/
out/
*.tsbuildinfo
apps/frontend/python-runtime/
# Cache
.cache/
.parcel-cache/
.turbo/
.eslintcache
.prettiercache
# ===========================
# Electron
# ===========================
apps/frontend/dist/
apps/frontend/out/
*.asar
*.blockmap
*.snap
*.deb
*.rpm
*.AppImage
*.dmg
*.exe
*.msi
# ===========================
# Testing
# ===========================
coverage/
.nyc_output/
test-results/
playwright-report/
playwright/.cache/
# ===========================
# Misc
# ===========================
*.local
*.bak
*.tmp
*.temp
# Development
dev/
.auto-claude/
_bmad/
_bmad-output/
.claude/
/docs
_bmad
_bmad-output
.claude
OPUS_ANALYSIS_AND_IDEAS.md
+73
View File
@@ -0,0 +1,73 @@
#!/bin/sh
# Commit message validation
# Enforces conventional commit format: type(scope): description
#
# Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
# Examples:
# feat(tasks): add drag and drop support
# fix(terminal): resolve scroll position issue
# docs: update README with setup instructions
# chore: update dependencies
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
# Regex for conventional commits
# Format: type(optional-scope): description
pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9-]+\))?: .{1,100}$"
# Allow merge commits
if echo "$commit_msg" | grep -qE "^Merge "; then
exit 0
fi
# Allow revert commits
if echo "$commit_msg" | grep -qE "^Revert "; then
exit 0
fi
# Check first line against pattern
first_line=$(echo "$commit_msg" | head -n 1)
if ! echo "$first_line" | grep -qE "$pattern"; then
echo ""
echo "ERROR: Invalid commit message format!"
echo ""
echo "Your message: $first_line"
echo ""
echo "Expected format: type(scope): description"
echo ""
echo "Valid types:"
echo " feat - A new feature"
echo " fix - A bug fix"
echo " docs - Documentation changes"
echo " style - Code style changes (formatting, semicolons, etc.)"
echo " refactor - Code refactoring (no feature/fix)"
echo " perf - Performance improvements"
echo " test - Adding or updating tests"
echo " build - Build system or dependencies"
echo " ci - CI/CD configuration"
echo " chore - Other changes (maintenance)"
echo " revert - Reverting a previous commit"
echo ""
echo "Examples:"
echo " feat(tasks): add drag and drop support"
echo " fix(terminal): resolve scroll position issue"
echo " docs: update README"
echo " chore: update dependencies"
echo ""
exit 1
fi
# Check description length (max 100 chars for first line)
if [ ${#first_line} -gt 100 ]; then
echo ""
echo "ERROR: Commit message first line is too long!"
echo "Maximum: 100 characters"
echo "Current: ${#first_line} characters"
echo ""
exit 1
fi
exit 0
+155 -3
View File
@@ -1,6 +1,158 @@
#!/bin/sh
# Run lint-staged in auto-claude-ui if there are staged files there
if git diff --cached --name-only | grep -q "^auto-claude-ui/"; then
cd auto-claude-ui && pnpm exec lint-staged
echo "Running pre-commit checks..."
# =============================================================================
# VERSION SYNC - Keep all version references in sync with root package.json
# =============================================================================
# Check if package.json is staged
if git diff --cached --name-only | grep -q "^package.json$"; then
echo "package.json changed, syncing version to all files..."
# Extract version from root package.json
VERSION=$(node -p "require('./package.json').version")
if [ -n "$VERSION" ]; then
# Sync to apps/frontend/package.json
if [ -f "apps/frontend/package.json" ]; then
node -e "
const fs = require('fs');
const pkg = require('./apps/frontend/package.json');
if (pkg.version !== '$VERSION') {
pkg.version = '$VERSION';
fs.writeFileSync('./apps/frontend/package.json', JSON.stringify(pkg, null, 2) + '\n');
console.log(' Updated apps/frontend/package.json to $VERSION');
}
"
git add apps/frontend/package.json
fi
# Sync to apps/backend/__init__.py
if [ -f "apps/backend/__init__.py" ]; then
sed -i.bak "s/__version__ = \"[^\"]*\"/__version__ = \"$VERSION\"/" apps/backend/__init__.py
rm -f apps/backend/__init__.py.bak
git add apps/backend/__init__.py
echo " Updated apps/backend/__init__.py to $VERSION"
fi
# Sync to README.md
if [ -f "README.md" ]; then
# Update version badge
sed -i.bak "s/version-[0-9]*\.[0-9]*\.[0-9]*-blue/version-$VERSION-blue/g" README.md
# Update download links
sed -i.bak "s/Auto-Claude-[0-9]*\.[0-9]*\.[0-9]*/Auto-Claude-$VERSION/g" README.md
rm -f README.md.bak
git add README.md
echo " Updated README.md to $VERSION"
fi
echo "Version sync complete: $VERSION"
fi
fi
# =============================================================================
# BACKEND CHECKS (Python) - Run first, before frontend
# =============================================================================
# Check if there are staged Python files in apps/backend
if git diff --cached --name-only | grep -q "^apps/backend/.*\.py$"; then
echo "Python changes detected, running backend checks..."
# Determine ruff command (venv or global)
RUFF=""
if [ -f "apps/backend/.venv/bin/ruff" ]; then
RUFF="apps/backend/.venv/bin/ruff"
elif [ -f "apps/backend/.venv/Scripts/ruff.exe" ]; then
RUFF="apps/backend/.venv/Scripts/ruff.exe"
elif command -v ruff >/dev/null 2>&1; then
RUFF="ruff"
fi
if [ -n "$RUFF" ]; then
# Run ruff linting (auto-fix)
echo "Running ruff lint..."
$RUFF check apps/backend/ --fix
if [ $? -ne 0 ]; then
echo "Ruff lint failed. Please fix Python linting errors before committing."
exit 1
fi
# Run ruff format (auto-fix)
echo "Running ruff format..."
$RUFF format apps/backend/
# Stage any files that were auto-fixed by ruff (POSIX-compliant)
find apps/backend -name "*.py" -type f -exec git add {} + 2>/dev/null || true
else
echo "Warning: ruff not found, skipping Python linting. Install with: uv pip install ruff"
fi
# Run pytest (skip slow/integration tests and Windows-incompatible tests for pre-commit speed)
echo "Running Python tests..."
cd apps/backend
# Tests to skip: graphiti (external deps), merge_file_tracker/service_orchestrator/worktree/workspace (Windows path/git issues)
IGNORE_TESTS="--ignore=../../tests/test_graphiti.py --ignore=../../tests/test_merge_file_tracker.py --ignore=../../tests/test_service_orchestrator.py --ignore=../../tests/test_worktree.py --ignore=../../tests/test_workspace.py"
if [ -d ".venv" ]; then
# Use venv if it exists
if [ -f ".venv/bin/pytest" ]; then
PYTHONPATH=. .venv/bin/pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
elif [ -f ".venv/Scripts/pytest.exe" ]; then
# Windows
PYTHONPATH=. .venv/Scripts/pytest.exe ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
else
PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
fi
else
PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
fi
if [ $? -ne 0 ]; then
echo "Python tests failed. Please fix failing tests before committing."
exit 1
fi
cd ../..
echo "Backend checks passed!"
fi
# =============================================================================
# FRONTEND CHECKS (TypeScript/React)
# =============================================================================
# Check if there are staged files in apps/frontend
if git diff --cached --name-only | grep -q "^apps/frontend/"; then
echo "Frontend changes detected, running frontend checks..."
cd apps/frontend
# Run lint-staged (handles staged .ts/.tsx files)
npm exec lint-staged
# Run TypeScript type check
echo "Running type check..."
npm run typecheck
if [ $? -ne 0 ]; then
echo "Type check failed. Please fix TypeScript errors before committing."
exit 1
fi
# Run linting
echo "Running lint..."
npm run lint
if [ $? -ne 0 ]; then
echo "Lint failed. Run 'npm run lint:fix' to auto-fix issues."
exit 1
fi
# Check for vulnerabilities (only high severity)
echo "Checking for vulnerabilities..."
npm audit --audit-level=high
if [ $? -ne 0 ]; then
echo "High severity vulnerabilities found. Run 'npm audit fix' to resolve."
exit 1
fi
cd ../..
echo "Frontend checks passed!"
fi
echo "All pre-commit checks passed!"
+41 -8
View File
@@ -1,29 +1,62 @@
repos:
# Python linting (auto-claude/)
# Version sync - propagate root package.json version to all files
- repo: local
hooks:
- id: version-sync
name: Version Sync
entry: bash -c '
VERSION=$(node -p "require(\"./package.json\").version");
if [ -n "$VERSION" ]; then
# Sync to apps/frontend/package.json
node -e "const fs=require(\"fs\");const p=require(\"./apps/frontend/package.json\");if(p.version!==\"$VERSION\"){p.version=\"$VERSION\";fs.writeFileSync(\"./apps/frontend/package.json\",JSON.stringify(p,null,2)+\"\n\");}";
# Sync to apps/backend/__init__.py
sed -i.bak "s/__version__ = \"[^\"]*\"/__version__ = \"$VERSION\"/" apps/backend/__init__.py && rm -f apps/backend/__init__.py.bak;
# Sync to README.md
sed -i.bak "s/version-[0-9]*\.[0-9]*\.[0-9]*-blue/version-$VERSION-blue/g" README.md;
sed -i.bak "s/Auto-Claude-[0-9]*\.[0-9]*\.[0-9]*/Auto-Claude-$VERSION/g" README.md && rm -f README.md.bak;
git add apps/frontend/package.json apps/backend/__init__.py README.md 2>/dev/null || true;
fi
'
language: system
files: ^package\.json$
pass_filenames: false
# Python linting (apps/backend/)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.3
hooks:
- id: ruff
args: [--fix]
files: ^auto-claude/
files: ^apps/backend/
- id: ruff-format
files: ^auto-claude/
files: ^apps/backend/
# Frontend linting (auto-claude-ui/)
# Python tests (apps/backend/) - skip slow/integration tests for pre-commit speed
# Tests to skip: graphiti (external deps), merge_file_tracker/service_orchestrator/worktree/workspace (Windows path/git issues)
- repo: local
hooks:
- id: pytest
name: Python Tests
entry: bash -c 'cd apps/backend && PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" --ignore=../../tests/test_graphiti.py --ignore=../../tests/test_merge_file_tracker.py --ignore=../../tests/test_service_orchestrator.py --ignore=../../tests/test_worktree.py --ignore=../../tests/test_workspace.py'
language: system
files: ^(apps/backend/.*\.py$|tests/.*\.py$)
pass_filenames: false
# Frontend linting (apps/frontend/)
- repo: local
hooks:
- id: eslint
name: ESLint
entry: bash -c 'cd auto-claude-ui && pnpm lint'
entry: bash -c 'cd apps/frontend && npm run lint'
language: system
files: ^auto-claude-ui/.*\.(ts|tsx|js|jsx)$
files: ^apps/frontend/.*\.(ts|tsx|js|jsx)$
pass_filenames: false
- id: typecheck
name: TypeScript Check
entry: bash -c 'cd auto-claude-ui && pnpm typecheck'
entry: bash -c 'cd apps/frontend && npm run typecheck'
language: system
files: ^auto-claude-ui/.*\.(ts|tsx)$
files: ^apps/frontend/.*\.(ts|tsx)$
pass_filenames: false
# General checks
+326 -67
View File
@@ -4,94 +4,150 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Auto Claude is a multi-agent autonomous coding framework that builds software through coordinated AI agent sessions. It uses the Claude Code SDK to run agents in isolated workspaces with security controls.
Auto Claude is a multi-agent autonomous coding framework that builds software through coordinated AI agent sessions. It uses the Claude Agent SDK to run agents in isolated workspaces with security controls.
**CRITICAL: All AI interactions use the Claude Agent SDK (`claude-agent-sdk` package), NOT the Anthropic API directly.**
## Project Structure
```
autonomous-coding/
├── apps/
│ ├── backend/ # Python backend/CLI - ALL agent logic lives here
│ │ ├── core/ # Client, auth, security
│ │ ├── agents/ # Agent implementations
│ │ ├── spec_agents/ # Spec creation agents
│ │ ├── integrations/ # Graphiti, Linear, GitHub
│ │ └── prompts/ # Agent system prompts
│ └── frontend/ # Electron desktop UI
├── guides/ # Documentation
├── tests/ # Test suite
└── scripts/ # Build and utility scripts
```
**When working with AI/LLM code:**
- Look in `apps/backend/core/client.py` for the Claude SDK client setup
- Reference `apps/backend/agents/` for working agent implementations
- Check `apps/backend/spec_agents/` for spec creation agent examples
- NEVER use `anthropic.Anthropic()` directly - always use `create_client()` from `core.client`
**Frontend (Electron Desktop App):**
- Built with Electron, React, TypeScript
- AI agents can perform E2E testing using the Electron MCP server
- When bug fixing or implementing features, use the Electron MCP server for automated testing
- See "End-to-End Testing" section below for details
## Commands
### Setup
**Requirements:**
- Python 3.12+ (required for backend)
- Node.js (for frontend)
```bash
# Install dependencies (from auto-claude/)
uv venv && uv pip install -r requirements.txt
# Or: python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
# Install all dependencies from root
npm run install:all
# Or install separately:
# Backend (from apps/backend/)
cd apps/backend && uv venv && uv pip install -r requirements.txt
# Frontend (from apps/frontend/)
cd apps/frontend && npm install
# Set up OAuth token
claude setup-token
# Add to auto-claude/.env: CLAUDE_CODE_OAUTH_TOKEN=your-token
# Add to apps/backend/.env: CLAUDE_CODE_OAUTH_TOKEN=your-token
```
### Creating and Running Specs
```bash
cd apps/backend
# Create a spec interactively
python auto-claude/spec_runner.py --interactive
python spec_runner.py --interactive
# Create spec from task description
python auto-claude/spec_runner.py --task "Add user authentication"
python spec_runner.py --task "Add user authentication"
# Force complexity level (simple/standard/complex)
python auto-claude/spec_runner.py --task "Fix button" --complexity simple
python spec_runner.py --task "Fix button" --complexity simple
# Run autonomous build
python auto-claude/run.py --spec 001
python run.py --spec 001
# List all specs
python auto-claude/run.py --list
python run.py --list
```
### Workspace Management
```bash
cd apps/backend
# Review changes in isolated worktree
python auto-claude/run.py --spec 001 --review
python run.py --spec 001 --review
# Merge completed build into project
python auto-claude/run.py --spec 001 --merge
python run.py --spec 001 --merge
# Discard build
python auto-claude/run.py --spec 001 --discard
python run.py --spec 001 --discard
```
### QA Validation
```bash
cd apps/backend
# Run QA manually
python auto-claude/run.py --spec 001 --qa
python run.py --spec 001 --qa
# Check QA status
python auto-claude/run.py --spec 001 --qa-status
python run.py --spec 001 --qa-status
```
### Testing
```bash
# Install test dependencies (required first time)
cd auto-claude && uv pip install -r ../tests/requirements-test.txt
cd apps/backend && uv pip install -r ../../tests/requirements-test.txt
# Run all tests (use virtual environment pytest)
auto-claude/.venv/bin/pytest tests/ -v
apps/backend/.venv/bin/pytest tests/ -v
# Run single test file
auto-claude/.venv/bin/pytest tests/test_security.py -v
apps/backend/.venv/bin/pytest tests/test_security.py -v
# Run specific test
auto-claude/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v
apps/backend/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v
# Skip slow tests
auto-claude/.venv/bin/pytest tests/ -m "not slow"
apps/backend/.venv/bin/pytest tests/ -m "not slow"
# Or from root
npm run test:backend
```
### Spec Validation
```bash
python auto-claude/validate_spec.py --spec-dir auto-claude/specs/001-feature --checkpoint all
python apps/backend/validate_spec.py --spec-dir apps/backend/specs/001-feature --checkpoint all
```
### Releases
```bash
# Automated version bump and release (recommended)
node scripts/bump-version.js patch # 2.5.5 -> 2.5.6
node scripts/bump-version.js minor # 2.5.5 -> 2.6.0
node scripts/bump-version.js major # 2.5.5 -> 3.0.0
node scripts/bump-version.js 2.6.0 # Set specific version
# 1. Bump version on your branch (creates commit, no tag)
node scripts/bump-version.js patch # 2.8.0 -> 2.8.1
node scripts/bump-version.js minor # 2.8.0 -> 2.9.0
node scripts/bump-version.js major # 2.8.0 -> 3.0.0
# Then push to trigger GitHub release workflows
git push origin main
git push origin v2.6.0
# 2. Push and create PR to main
git push origin your-branch
gh pr create --base main
# 3. Merge PR → GitHub Actions automatically:
# - Creates tag
# - Builds all platforms
# - Creates release with changelog
# - Updates README
```
See [RELEASE.md](RELEASE.md) for detailed release process documentation.
@@ -108,21 +164,43 @@ See [RELEASE.md](RELEASE.md) for detailed release process documentation.
**Implementation (run.py → agent.py)** - Multi-session build:
1. Planner Agent creates subtask-based implementation plan
2. Coder Agent implements subtasks (can spawn subagents for parallel work)
3. QA Reviewer validates acceptance criteria
4. QA Fixer resolves issues in a loop
3. QA Reviewer validates acceptance criteria (can perform E2E testing via Electron MCP for frontend changes)
4. QA Fixer resolves issues in a loop (with E2E testing to verify fixes)
### Key Components
### Key Components (apps/backend/)
- **client.py** - Claude SDK client with security hooks and tool permissions
- **security.py** + **project_analyzer.py** - Dynamic command allowlisting based on detected project stack
- **worktree.py** - Git worktree isolation for safe feature development
- **memory.py** - File-based session memory (primary, always-available storage)
- **graphiti_memory.py** - Optional graph-based cross-session memory with semantic search
- **graphiti_providers.py** - Multi-provider factory for Graphiti (OpenAI, Anthropic, Azure, Ollama, Google AI)
**Core Infrastructure:**
- **core/client.py** - Claude Agent SDK client factory with security hooks and tool permissions
- **core/security.py** - Dynamic command allowlisting based on detected project stack
- **core/auth.py** - OAuth token management for Claude SDK authentication
- **agents/** - Agent implementations (planner, coder, qa_reviewer, qa_fixer)
- **spec_agents/** - Spec creation agents (gatherer, researcher, writer, critic)
**Memory & Context:**
- **integrations/graphiti/** - Graphiti memory system (mandatory)
- `queries_pkg/graphiti.py` - Main GraphitiMemory class
- `queries_pkg/client.py` - LadybugDB client wrapper
- `queries_pkg/queries.py` - Graph query operations
- `queries_pkg/search.py` - Semantic search logic
- `queries_pkg/schema.py` - Graph schema definitions
- **graphiti_config.py** - Configuration and validation for Graphiti integration
- **linear_updater.py** - Optional Linear integration for progress tracking
- **graphiti_providers.py** - Multi-provider factory (OpenAI, Anthropic, Azure, Ollama, Google AI)
- **agents/memory_manager.py** - Session memory orchestration
### Agent Prompts (auto-claude/prompts/)
**Workspace & Security:**
- **cli/worktree.py** - Git worktree isolation for safe feature development
- **context/project_analyzer.py** - Project stack detection for dynamic tooling
- **auto_claude_tools.py** - Custom MCP tools integration
**Integrations:**
- **linear_updater.py** - Optional Linear integration for progress tracking
- **runners/github/** - GitHub Issues & PRs automation
- **Electron MCP** - E2E testing integration for QA agents (Chrome DevTools Protocol)
- Enabled with `ELECTRON_MCP_ENABLED=true` in `.env`
- Allows QA agents to interact with running Electron app
- See "End-to-End Testing" section for details
### Agent Prompts (apps/backend/prompts/)
| Prompt | Purpose |
|--------|---------|
@@ -139,7 +217,7 @@ See [RELEASE.md](RELEASE.md) for detailed release process documentation.
### Spec Directory Structure
Each spec in `auto-claude/specs/XXX-name/` contains:
Each spec in `.auto-claude/specs/XXX-name/` contains:
- `spec.md` - Feature specification
- `requirements.json` - Structured user requirements
- `context.json` - Discovered codebase context
@@ -179,44 +257,225 @@ Three-layer defense:
Security profile cached in `.auto-claude-security.json`.
### Claude Agent SDK Integration
**CRITICAL: Auto Claude uses the Claude Agent SDK for ALL AI interactions. Never use the Anthropic API directly.**
**Client Location:** `apps/backend/core/client.py`
The `create_client()` function creates a configured `ClaudeSDKClient` instance with:
- Multi-layered security (sandbox, permissions, security hooks)
- Agent-specific tool permissions (planner, coder, qa_reviewer, qa_fixer)
- Dynamic MCP server integration based on project capabilities
- Extended thinking token budget control
**Example usage in agents:**
```python
from core.client import create_client
# Create SDK client (NOT raw Anthropic API client)
client = create_client(
project_dir=project_dir,
spec_dir=spec_dir,
model="claude-sonnet-4-5-20250929",
agent_type="coder",
max_thinking_tokens=None # or 5000/10000/16000
)
# Run agent session
response = client.create_agent_session(
name="coder-agent-session",
starting_message="Implement the authentication feature"
)
```
**Why use the SDK:**
- Pre-configured security (sandbox, allowlists, hooks)
- Automatic MCP server integration (Context7, Linear, Graphiti, Electron, Puppeteer)
- Tool permissions based on agent role
- Session management and recovery
- Unified API across all agent types
**Where to find working examples:**
- `apps/backend/agents/planner.py` - Planner agent
- `apps/backend/agents/coder.py` - Coder agent
- `apps/backend/agents/qa_reviewer.py` - QA reviewer
- `apps/backend/agents/qa_fixer.py` - QA fixer
- `apps/backend/spec_agents/` - Spec creation agents
### Memory System
Dual-layer memory architecture:
**Graphiti Memory (Mandatory)** - `integrations/graphiti/`
**File-Based Memory (Primary)** - `memory.py`
- Zero dependencies, always available
- Human-readable files in `specs/XXX/memory/`
- Session insights, patterns, gotchas, codebase map
Auto Claude uses Graphiti as its primary memory system with embedded LadybugDB (no Docker required):
**Graphiti Memory (Optional Enhancement)** - `graphiti_memory.py`
- Graph database with semantic search (LadybugDB - embedded, no Docker)
- Cross-session context retrieval
- Requires Python 3.12+
- Multi-provider support:
- **Graph database with semantic search** - Knowledge graph for cross-session context
- **Session insights** - Patterns, gotchas, discoveries automatically extracted
- **Multi-provider support:**
- LLM: OpenAI, Anthropic, Azure OpenAI, Ollama, Google AI (Gemini)
- Embedders: OpenAI, Voyage AI, Azure OpenAI, Ollama, Google AI
- **Modular architecture:** (`integrations/graphiti/queries_pkg/`)
- `graphiti.py` - Main GraphitiMemory class
- `client.py` - LadybugDB client wrapper
- `queries.py` - Graph query operations
- `search.py` - Semantic search logic
- `schema.py` - Graph schema definitions
```bash
# Setup (requires Python 3.12+)
pip install real_ladybug graphiti-core
**Configuration:**
- Set provider credentials in `apps/backend/.env` (see `.env.example`)
- Required env vars: `GRAPHITI_ENABLED=true`, `ANTHROPIC_API_KEY` or other provider keys
- Memory data stored in `.auto-claude/specs/XXX/graphiti/`
**Usage in agents:**
```python
from integrations.graphiti.memory import get_graphiti_memory
memory = get_graphiti_memory(spec_dir, project_dir)
context = memory.get_context_for_session("Implementing feature X")
memory.add_session_insight("Pattern: use React hooks for state")
```
Enable with: `GRAPHITI_ENABLED=true` + provider credentials. See `.env.example`.
## Development Guidelines
## Project Structure
### Frontend Internationalization (i18n)
Auto Claude can be used in two ways:
**CRITICAL: Always use i18n translation keys for all user-facing text in the frontend.**
**As a standalone CLI tool** (original project):
```bash
python auto-claude/run.py --spec 001
The frontend uses `react-i18next` for internationalization. All labels, buttons, messages, and user-facing text MUST use translation keys.
**Translation file locations:**
- `apps/frontend/src/shared/i18n/locales/en/*.json` - English translations
- `apps/frontend/src/shared/i18n/locales/fr/*.json` - French translations
**Translation namespaces:**
- `common.json` - Shared labels, buttons, common terms
- `navigation.json` - Sidebar navigation items, sections
- `settings.json` - Settings page content
- `dialogs.json` - Dialog boxes and modals
- `tasks.json` - Task/spec related content
- `onboarding.json` - Onboarding wizard content
- `welcome.json` - Welcome screen content
**Usage pattern:**
```tsx
import { useTranslation } from 'react-i18next';
// In component
const { t } = useTranslation(['navigation', 'common']);
// Use translation keys, NOT hardcoded strings
<span>{t('navigation:items.githubPRs')}</span> // ✅ CORRECT
<span>GitHub PRs</span> // ❌ WRONG
```
**With the optional Electron frontend** (`auto-claude-ui/`):
- Provides a GUI for task management and progress tracking
- Wraps the CLI commands - the backend works independently
**When adding new UI text:**
1. Add the translation key to ALL language files (at minimum: `en/*.json` and `fr/*.json`)
2. Use `namespace:section.key` format (e.g., `navigation:items.githubPRs`)
3. Never use hardcoded strings in JSX/TSX files
**Directory layout:**
- `auto-claude/` - Python backend/CLI (the framework code)
- `auto-claude-ui/` - Optional Electron frontend
- `.auto-claude/specs/` - Per-project data (specs, plans, QA reports) - gitignored
### End-to-End Testing (Electron App)
**IMPORTANT: When bug fixing or implementing new features in the frontend, AI agents can perform automated E2E testing using the Electron MCP server.**
The Electron MCP server allows QA agents to interact with the running Electron app via Chrome DevTools Protocol:
**Setup:**
1. Start the Electron app with remote debugging enabled:
```bash
npm run dev # Already configured with --remote-debugging-port=9222
```
2. Enable Electron MCP in `apps/backend/.env`:
```bash
ELECTRON_MCP_ENABLED=true
ELECTRON_DEBUG_PORT=9222 # Default port
```
**Available Testing Capabilities:**
QA agents (`qa_reviewer` and `qa_fixer`) automatically get access to Electron MCP tools:
1. **Window Management**
- `mcp__electron__get_electron_window_info` - Get info about running windows
- `mcp__electron__take_screenshot` - Capture screenshots for visual verification
2. **UI Interaction**
- `mcp__electron__send_command_to_electron` with commands:
- `click_by_text` - Click buttons/links by visible text
- `click_by_selector` - Click elements by CSS selector
- `fill_input` - Fill form fields by placeholder or selector
- `select_option` - Select dropdown options
- `send_keyboard_shortcut` - Send keyboard shortcuts (Enter, Ctrl+N, etc.)
- `navigate_to_hash` - Navigate to hash routes (#settings, #create, etc.)
3. **Page Inspection**
- `get_page_structure` - Get organized overview of page elements
- `debug_elements` - Get debugging info about buttons and forms
- `verify_form_state` - Check form state and validation
- `eval` - Execute custom JavaScript code
4. **Logging**
- `mcp__electron__read_electron_logs` - Read console logs for debugging
**Example E2E Test Flow:**
```python
# 1. Agent takes screenshot to see current state
agent: "Take a screenshot to see the current UI"
# Uses: mcp__electron__take_screenshot
# 2. Agent inspects page structure
agent: "Get page structure to find available buttons"
# Uses: mcp__electron__send_command_to_electron (command: "get_page_structure")
# 3. Agent clicks a button to navigate
agent: "Click the 'Create New Spec' button"
# Uses: mcp__electron__send_command_to_electron (command: "click_by_text", args: {text: "Create New Spec"})
# 4. Agent fills out a form
agent: "Fill the task description field"
# Uses: mcp__electron__send_command_to_electron (command: "fill_input", args: {placeholder: "Describe your task", value: "Add login feature"})
# 5. Agent submits and verifies
agent: "Click Submit and verify success"
# Uses: click_by_text → take_screenshot → verify result
```
**When to Use E2E Testing:**
- **Bug Fixes**: Reproduce the bug, apply fix, verify it's resolved
- **New Features**: Implement feature, test the UI flow end-to-end
- **UI Changes**: Verify visual changes and interactions work correctly
- **Form Validation**: Test form submission, validation, error handling
**Configuration in `core/client.py`:**
The client automatically enables Electron MCP tools for QA agents when:
- Project is detected as Electron (`is_electron` capability)
- `ELECTRON_MCP_ENABLED=true` is set
- Agent type is `qa_reviewer` or `qa_fixer`
**Note:** Screenshots are automatically compressed (1280x720, quality 60, JPEG) to stay under Claude SDK's 1MB JSON message buffer limit.
## Running the Application
**As a standalone CLI tool**:
```bash
cd apps/backend
python run.py --spec 001
```
**With the Electron frontend**:
```bash
npm start # Build and run desktop app
npm run dev # Run in development mode (includes --remote-debugging-port=9222 for E2E testing)
```
**For E2E Testing with QA Agents:**
1. Start the Electron app: `npm run dev`
2. Enable Electron MCP in `apps/backend/.env`: `ELECTRON_MCP_ENABLED=true`
3. Run QA: `python run.py --spec 001 --qa`
4. QA agents will automatically interact with the running app for testing
**Project data storage:**
- `.auto-claude/specs/` - Per-project data (specs, plans, QA reports, memory) - gitignored
+285 -59
View File
@@ -5,6 +5,7 @@ Thank you for your interest in contributing to Auto Claude! This document provid
## Table of Contents
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Development Setup](#development-setup)
- [Python Backend](#python-backend)
- [Electron Frontend](#electron-frontend)
@@ -14,7 +15,13 @@ Thank you for your interest in contributing to Auto Claude! This document provid
- [Testing](#testing)
- [Continuous Integration](#continuous-integration)
- [Git Workflow](#git-workflow)
- [Branch Overview](#branch-overview)
- [Main Branches](#main-branches)
- [Supporting Branches](#supporting-branches)
- [Branch Naming](#branch-naming)
- [Where to Branch From](#where-to-branch-from)
- [Pull Request Targets](#pull-request-targets)
- [Release Process](#release-process-maintainers)
- [Commit Messages](#commit-messages)
- [Pull Request Process](#pull-request-process)
- [Issue Reporting](#issue-reporting)
@@ -24,37 +31,77 @@ Thank you for your interest in contributing to Auto Claude! This document provid
Before contributing, ensure you have the following installed:
- **Python 3.8+** - For the backend framework
- **Node.js 18+** - For the Electron frontend
- **pnpm** - Package manager for the frontend (`npm install -g pnpm`)
- **Python 3.12+** - For the backend framework
- **Node.js 24+** - For the Electron frontend
- **npm 10+** - Package manager for the frontend (comes with Node.js)
- **uv** (recommended) or **pip** - Python package manager
- **Git** - Version control
### Installing Python 3.12
**Windows:**
```bash
winget install Python.Python.3.12
```
**macOS:**
```bash
brew install python@3.12
```
**Linux (Ubuntu/Debian):**
```bash
sudo apt install python3.12 python3.12-venv
```
## Quick Start
The fastest way to get started:
```bash
# Clone the repository
git clone https://github.com/AndyMik90/Auto-Claude.git
cd Auto-Claude
# Install all dependencies (cross-platform)
npm run install:all
# Run in development mode
npm run dev
# Or build and run production
npm start
```
## Development Setup
The project consists of two main components:
1. **Python Backend** (`auto-claude/`) - The core autonomous coding framework
2. **Electron Frontend** (`auto-claude-ui/`) - Optional desktop UI
1. **Python Backend** (`apps/backend/`) - The core autonomous coding framework
2. **Electron Frontend** (`apps/frontend/`) - Optional desktop UI
### Python Backend
The recommended way is to use `npm run install:backend`, but you can also set up manually:
```bash
# Navigate to the auto-claude directory
cd auto-claude
# Navigate to the backend directory
cd apps/backend
# Create virtual environment (using uv - recommended)
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv pip install -r requirements.txt
# Create virtual environment
# Windows:
py -3.12 -m venv .venv
.venv\Scripts\activate
# Or using standard Python
python3 -m venv .venv
# macOS/Linux:
python3.12 -m venv .venv
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Install test dependencies
pip install -r ../tests/requirements-test.txt
pip install -r ../../tests/requirements-test.txt
# Set up environment
cp .env.example .env
@@ -64,31 +111,31 @@ cp .env.example .env
### Electron Frontend
```bash
# Navigate to the UI directory
cd auto-claude-ui
# Navigate to the frontend directory
cd apps/frontend
# Install dependencies
pnpm install
npm install
# Start development server
pnpm dev
npm run dev
# Build for production
pnpm build
npm run build
# Package for distribution
pnpm package
npm run package
```
## Running from Source
If you want to run Auto Claude from source (for development or testing unreleased features), follow these steps:
### Step 1: Clone and Set Up Python Backend
### Step 1: Clone and Set Up
```bash
git clone https://github.com/AndyMik90/Auto-Claude.git
cd Auto-Claude/auto-claude
cd Auto-Claude/apps/backend
# Using uv (recommended)
uv venv && uv pip install -r requirements.txt
@@ -99,6 +146,7 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt
# Set up environment
cd apps/backend
cp .env.example .env
# Edit .env and add your CLAUDE_CODE_OAUTH_TOKEN (get it via: claude setup-token)
```
@@ -106,16 +154,16 @@ cp .env.example .env
### Step 2: Run the Desktop UI
```bash
cd ../auto-claude-ui
cd ../frontend
# Install dependencies
pnpm install
npm install
# Development mode (hot reload)
pnpm dev
npm run dev
# Or production build
pnpm run build && pnpm run start
npm run build && npm run start
```
<details>
@@ -126,7 +174,7 @@ Auto Claude automatically downloads prebuilt binaries for Windows. If prebuilts
1. Download [Visual Studio Build Tools 2022](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
2. Select "Desktop development with C++" workload
3. In "Individual Components", add "MSVC v143 - VS 2022 C++ x64/x86 Spectre-mitigated libs"
4. Restart terminal and run `pnpm install` again
4. Restart terminal and run `npm install` again
</details>
@@ -152,10 +200,10 @@ When you commit, the following checks run automatically:
| Check | Scope | Description |
|-------|-------|-------------|
| **ruff** | `auto-claude/` | Python linter with auto-fix |
| **ruff-format** | `auto-claude/` | Python code formatter |
| **eslint** | `auto-claude-ui/` | TypeScript/React linter |
| **typecheck** | `auto-claude-ui/` | TypeScript type checking |
| **ruff** | `apps/backend/` | Python linter with auto-fix |
| **ruff-format** | `apps/backend/` | Python code formatter |
| **eslint** | `apps/frontend/` | TypeScript/React linter |
| **typecheck** | `apps/frontend/` | TypeScript type checking |
| **trailing-whitespace** | All files | Removes trailing whitespace |
| **end-of-file-fixer** | All files | Ensures files end with newline |
| **check-yaml** | All files | Validates YAML syntax |
@@ -212,7 +260,7 @@ def gnc(sd):
### TypeScript/React
- Use TypeScript strict mode
- Follow the existing component patterns in `auto-claude-ui/src/`
- Follow the existing component patterns in `apps/frontend/src/`
- Use functional components with hooks
- Prefer named exports over default exports
- Use the UI components from `src/renderer/components/ui/`
@@ -242,20 +290,25 @@ export default function(props) {
### Python Tests
```bash
# Run all tests
pytest tests/ -v
# Run all tests (from repository root)
npm run test:backend
# Or manually with pytest
cd apps/backend
.venv/Scripts/pytest.exe ../tests -v # Windows
.venv/bin/pytest ../tests -v # macOS/Linux
# Run a specific test file
pytest tests/test_security.py -v
npm run test:backend -- tests/test_security.py -v
# Run a specific test
pytest tests/test_security.py::test_bash_command_validation -v
npm run test:backend -- tests/test_security.py::test_bash_command_validation -v
# Skip slow tests
pytest tests/ -m "not slow"
npm run test:backend -- -m "not slow"
# Run with coverage
pytest tests/ --cov=auto-claude --cov-report=html
pytest tests/ --cov=apps/backend --cov-report=html
```
Test configuration is in `tests/pytest.ini`.
@@ -263,26 +316,26 @@ Test configuration is in `tests/pytest.ini`.
### Frontend Tests
```bash
cd auto-claude-ui
cd apps/frontend
# Run unit tests
pnpm test
npm test
# Run tests in watch mode
pnpm test:watch
npm run test:watch
# Run with coverage
pnpm test:coverage
npm run test:coverage
# Run E2E tests (requires built app)
pnpm build
pnpm test:e2e
npm run build
npm run test:e2e
# Run linting
pnpm lint
npm run lint
# Run type checking
pnpm typecheck
npm run typecheck
```
### Testing Requirements
@@ -320,19 +373,50 @@ Before a PR can be merged:
```bash
# Python tests
cd auto-claude
cd apps/backend
source .venv/bin/activate
pytest ../tests/ -v
pytest ../../tests/ -v
# Frontend tests
cd auto-claude-ui
pnpm test
pnpm lint
pnpm typecheck
cd apps/frontend
npm test
npm run lint
npm run typecheck
```
## Git Workflow
We use a **Git Flow** branching strategy to manage releases and parallel development.
### Branch Overview
```
main (stable) ← Only released, tested code (tagged versions)
develop ← Integration branch - all PRs merge here first
├── feature/xxx ← New features
├── fix/xxx ← Bug fixes
├── release/vX.Y.Z ← Release preparation
└── hotfix/xxx ← Emergency production fixes
```
### Main Branches
| Branch | Purpose | Protected |
|--------|---------|-----------|
| `main` | Production-ready code. Only receives merges from `release/*` or `hotfix/*` branches. Every merge is tagged (v2.7.0, v2.8.0, etc.) | ✅ Yes |
| `develop` | Integration branch where all features and fixes are combined. This is the default target for all PRs. | ✅ Yes |
### Supporting Branches
| Branch Type | Branch From | Merge To | Purpose |
|-------------|-------------|----------|---------|
| `feature/*` | `develop` | `develop` | New features and enhancements |
| `fix/*` | `develop` | `develop` | Bug fixes (non-critical) |
| `release/*` | `develop` | `main` + `develop` | Release preparation and final testing |
| `hotfix/*` | `main` | `main` + `develop` | Critical production bug fixes |
### Branch Naming
Use descriptive branch names with a prefix indicating the type of change:
@@ -341,10 +425,146 @@ Use descriptive branch names with a prefix indicating the type of change:
|--------|---------|---------|
| `feature/` | New feature | `feature/add-dark-mode` |
| `fix/` | Bug fix | `fix/memory-leak-in-worker` |
| `hotfix/` | Urgent production fix | `hotfix/critical-crash-fix` |
| `docs/` | Documentation | `docs/update-readme` |
| `refactor/` | Code refactoring | `refactor/simplify-auth-flow` |
| `test/` | Test additions/fixes | `test/add-integration-tests` |
| `chore/` | Maintenance tasks | `chore/update-dependencies` |
| `release/` | Release preparation | `release/v2.8.0` |
| `hotfix/` | Emergency fixes | `hotfix/critical-auth-bug` |
### Where to Branch From
```bash
# For features and bug fixes - ALWAYS branch from develop
git checkout develop
git pull origin develop
git checkout -b feature/my-new-feature
# For hotfixes only - branch from main
git checkout main
git pull origin main
git checkout -b hotfix/critical-fix
```
### Pull Request Targets
> ⚠️ **Important:** All PRs should target `develop`, NOT `main`!
| Your Branch Type | Target Branch |
|------------------|---------------|
| `feature/*` | `develop` |
| `fix/*` | `develop` |
| `docs/*` | `develop` |
| `refactor/*` | `develop` |
| `test/*` | `develop` |
| `chore/*` | `develop` |
| `hotfix/*` | `main` (maintainers only) |
| `release/*` | `main` (maintainers only) |
### Release Process (Maintainers)
When ready to release a new version:
```bash
# 1. Create release branch from develop
git checkout develop
git pull origin develop
git checkout -b release/v2.8.0
# 2. Update version numbers, CHANGELOG, final fixes only
# No new features allowed in release branches!
# 3. Merge to main and tag
git checkout main
git merge release/v2.8.0
git tag v2.8.0
git push origin main --tags
# 4. Merge back to develop (important!)
git checkout develop
git merge release/v2.8.0
git push origin develop
# 5. Delete release branch
git branch -d release/v2.8.0
git push origin --delete release/v2.8.0
```
### Beta Release Process (Maintainers)
Beta releases allow users to test new features before they're included in a stable release. Beta releases are published from the `develop` branch.
**Creating a Beta Release:**
1. Go to **Actions****Beta Release** workflow in GitHub
2. Click **Run workflow**
3. Enter the beta version (e.g., `2.8.0-beta.1`)
4. Optionally enable dry run to test without publishing
5. Click **Run workflow**
The workflow will:
- Validate the version format
- Update `package.json` on develop
- Create and push a tag (e.g., `v2.8.0-beta.1`)
- Build installers for all platforms
- Create a GitHub pre-release
**Version Format:**
```
X.Y.Z-beta.N (e.g., 2.8.0-beta.1, 2.8.0-beta.2)
X.Y.Z-alpha.N (e.g., 2.8.0-alpha.1)
X.Y.Z-rc.N (e.g., 2.8.0-rc.1)
```
**For Users:**
Users can opt into beta updates in Settings → Updates → "Beta Updates" toggle. When enabled, the app will check for and install beta versions. Users can switch back to stable at any time.
### Hotfix Workflow
For urgent production fixes that can't wait for the normal release cycle:
**1. Create hotfix from main**
```bash
git checkout main
git pull origin main
git checkout -b hotfix/150-critical-fix
```
**2. Fix the issue**
```bash
# ... make changes ...
git commit -m "hotfix: fix critical crash on startup"
```
**3. Open PR to main (fast-track review)**
```bash
gh pr create --base main --title "hotfix: fix critical crash on startup"
```
**4. After merge to main, sync to develop**
```bash
git checkout develop
git pull origin develop
git merge main
git push origin develop
```
```
main ─────●─────●─────●─────●───── (production)
↑ ↑ ↑ ↑
develop ──●─────●─────●─────●───── (integration)
↑ ↑ ↑
feature/123 ────●
feature/124 ──────────●
hotfix/125 ─────────────────●───── (from main, merge to both)
```
> **Note:** Hotfixes branch FROM `main` and merge TO `main` first, then sync back to `develop` to keep branches aligned.
### Commit Messages
@@ -378,17 +598,23 @@ git commit -m "WIP"
## Pull Request Process
1. **Fork the repository** and create your branch from `main`
1. **Fork the repository** and create your branch from `develop` (not main!)
```bash
git checkout develop
git pull origin develop
git checkout -b feature/your-feature-name
```
2. **Make your changes** following the code style guidelines
3. **Test thoroughly**:
```bash
# Python
pytest tests/ -v
# Python (from repository root)
npm run test:backend
# Frontend
cd auto-claude-ui && pnpm test && pnpm lint && pnpm typecheck
cd apps/frontend && npm test && npm run lint && npm run typecheck
```
4. **Update documentation** if your changes affect:
@@ -447,7 +673,7 @@ When requesting a feature:
Auto Claude consists of two main parts:
### Python Backend (`auto-claude/`)
### Python Backend (`apps/backend/`)
The core autonomous coding framework:
@@ -457,9 +683,9 @@ The core autonomous coding framework:
- **Memory**: `memory.py` (file-based), `graphiti_memory.py` (graph-based)
- **QA**: `qa_loop.py`, `prompts/qa_*.md`
### Electron Frontend (`auto-claude-ui/`)
### Electron Frontend (`apps/frontend/`)
Optional desktop interface:
Desktop interface:
- **Main Process**: `src/main/` - Electron main process, IPC handlers
- **Renderer**: `src/renderer/` - React UI components
+161 -208
View File
@@ -1,269 +1,222 @@
# Auto Claude
Your AI coding companion. Build features, fix bugs, and ship faster — with autonomous agents that plan, code, and validate for you.
**Autonomous multi-agent coding framework that plans, builds, and validates software for you.**
![Auto Claude Kanban Board](.github/assets/Auto-Claude-Kanban.png)
[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/KCXaPBr4Dj)
[![Version](https://img.shields.io/badge/version-2.7.2-blue?style=flat-square)](https://github.com/AndyMik90/Auto-Claude/releases/latest)
[![License](https://img.shields.io/badge/license-AGPL--3.0-green?style=flat-square)](./agpl-3.0.txt)
[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/KCXaPBr4Dj)
[![CI](https://img.shields.io/github/actions/workflow/status/AndyMik90/Auto-Claude/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/AndyMik90/Auto-Claude/actions)
## What It Does ✨
---
**Auto Claude is a desktop app that supercharges your AI coding workflow.** Whether you're a vibe coder just getting started or an experienced developer, Auto Claude meets you where you are.
## Download
- **Autonomous Tasks** — Describe what you want to build, and agents handle planning, coding, and validation while you focus on other work
- **Agent Terminals** — Run Claude Code in up to 12 terminals with a clean layout, smart naming based on context, and one-click task context injection
- **Safe by Default** — All work happens in git worktrees, keeping your main branch undisturbed until you're ready to merge
- **Self-Validating** — Built-in QA agents check their own work before you review
Get the latest pre-built release for your platform:
**The result?** 10x your output while maintaining code quality.
| Platform | Download | Notes |
|----------|----------|-------|
| **Windows** | [Auto-Claude-2.7.2.exe](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Installer (NSIS) |
| **macOS (Apple Silicon)** | [Auto-Claude-2.7.2-arm64.dmg](https://github.com/AndyMik90/Auto-Claude/releases/latest) | M1/M2/M3 Macs |
| **macOS (Intel)** | [Auto-Claude-2.7.2-x64.dmg](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Intel Macs |
| **Linux** | [Auto-Claude-2.7.2.AppImage](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Universal |
| **Linux (Debian)** | [Auto-Claude-2.7.2.deb](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Ubuntu/Debian |
## Key Features
> All releases include SHA256 checksums and VirusTotal scan results for security verification.
- **Parallel Agents**: Run multiple builds simultaneously while you focus on other work
- **Context Engineering**: Agents understand your codebase structure before writing code
- **Self-Validating**: Built-in QA loop catches issues before you review
- **Isolated Workspaces**: All work happens in git worktrees — your code stays safe
- **AI Merge Resolution**: Intelligent conflict resolution when merging back to main — no manual conflict fixing
- **Cross-Platform**: Desktop app runs on Mac, Windows, and Linux
- **Any Project Type**: Build web apps, APIs, CLIs — works with any software project
---
## Requirements
- **Claude Pro/Max subscription** - [Get one here](https://claude.ai/upgrade)
- **Claude Code CLI** - `npm install -g @anthropic-ai/claude-code`
- **Git repository** - Your project must be initialized as a git repo
- **Python 3.12+** - Required for the backend and Memory Layer
---
## Quick Start
### Download Auto Claude
Download the latest release for your platform from [GitHub Releases](https://github.com/AndyMik90/Auto-Claude/releases/latest):
| Platform | Download |
|----------|----------|
| **macOS (Apple Silicon M1-M4)** | `*-arm64.dmg` |
| **macOS (Intel)** | `*-x64.dmg` |
| **Windows** | `*.exe` |
| **Linux** | `*.AppImage` or `*.deb` |
> **Not sure which Mac?** Click the Apple menu () > "About This Mac". Look for "Chip" - M1/M2/M3/M4 = Apple Silicon, otherwise Intel.
### Prerequisites
Before using Auto Claude, you need:
1. **Claude Subscription** - Requires [Claude Pro or Max](https://claude.ai/upgrade) for Claude Code access
2. **Claude Code CLI** - Install with: `npm install -g @anthropic-ai/claude-code`
### Install and Run
1. **Download** the installer for your platform from the table above
2. **Install**:
- **macOS**: Open the `.dmg`, drag Auto Claude to Applications
- **Windows**: Run the `.exe` installer (see note below about security warning)
- **Linux**: Make the AppImage executable (`chmod +x`) and run it, or install the `.deb`
3. **Launch** Auto Claude
4. **Add your project** and start building!
<details>
<summary><b>Windows users:</b> Security warning when installing</summary>
The Windows installer is not yet code-signed, so you may see a "Windows protected your PC" warning from Microsoft Defender SmartScreen.
**To proceed:**
1. Click "More info"
2. Click "Run anyway"
This is safe — all releases are automatically scanned with VirusTotal before publishing. You can verify any installer by checking the **VirusTotal Scan Results** section in each [release's notes](https://github.com/AndyMik90/Auto-Claude/releases).
We're working on obtaining a code signing certificate for future releases.
</details>
> **Want to build from source?** See [CONTRIBUTING.md](CONTRIBUTING.md#running-from-source) for development setup.
1. **Download and install** the app for your platform
2. **Open your project** - Select a git repository folder
3. **Connect Claude** - The app will guide you through OAuth setup
4. **Create a task** - Describe what you want to build
5. **Watch it work** - Agents plan, code, and validate autonomously
---
## 🎯 Features
## Features
| Feature | Description |
|---------|-------------|
| **Autonomous Tasks** | Describe your goal; agents handle planning, implementation, and validation |
| **Parallel Execution** | Run multiple builds simultaneously with up to 12 agent terminals |
| **Isolated Workspaces** | All changes happen in git worktrees - your main branch stays safe |
| **Self-Validating QA** | Built-in quality assurance loop catches issues before you review |
| **AI-Powered Merge** | Automatic conflict resolution when integrating back to main |
| **Memory Layer** | Agents retain insights across sessions for smarter builds |
| **Cross-Platform** | Native desktop apps for Windows, macOS, and Linux |
| **Auto-Updates** | App updates automatically when new versions are released |
---
## Interface
### Kanban Board
Plan tasks and let AI handle the planning, coding, and validation — all in a visual interface. Track progress from "Planning" to "Done" while agents work autonomously.
Visual task management from planning through completion. Create tasks and monitor agent progress in real-time.
### Agent Terminals
AI-powered terminals with one-click task context injection. Spawn multiple agents for parallel work.
Spawn up to 12 AI-powered terminals for hands-on coding. Inject task context with a click, reference files from your project, and work rapidly across multiple sessions.
**Power users:** Connect multiple Claude Code subscriptions to run even more agents in parallel — perfect for teams or heavy workloads.
![Auto Claude Agent Terminals](.github/assets/Auto-Claude-Agents-terminals.png)
### Insights
Have a conversation about your project in a ChatGPT-style interface. Ask questions, get explanations, and explore your codebase through natural dialogue.
![Agent Terminals](.github/assets/Auto-Claude-Agents-terminals.png)
### Roadmap
AI-assisted feature planning with competitor analysis and audience targeting.
Based on your target audience, AI anticipates and plans the most impactful features you should focus on. Prioritize what matters most to your users.
![Roadmap](.github/assets/Auto-Claude-roadmap.png)
![Auto Claude Roadmap](.github/assets/Auto-Claude-roadmap.png)
### Ideation
Let AI help you create a project that shines. Rapidly understand your codebase and discover:
- Code improvements and refactoring opportunities
- Performance bottlenecks
- Security vulnerabilities
- Documentation gaps
- UI/UX enhancements
- Overall code quality issues
### Changelog
Write professional changelogs effortlessly. Generate release notes from completed Auto Claude tasks or integrate with GitHub to create masterclass changelogs automatically.
### Context
See exactly what Auto Claude understands about your project — the tech stack, file structure, patterns, and insights it uses to write better code.
### AI Merge Resolution
When your main branch evolves while a build is in progress, Auto Claude automatically resolves merge conflicts using AI — no manual `<<<<<<< HEAD` fixing required.
**How it works:**
1. **Git Auto-Merge First** — Simple non-conflicting changes merge instantly without AI
2. **Conflict-Only AI** — For actual conflicts, AI receives only the specific conflict regions (not entire files), achieving ~98% prompt reduction
3. **Parallel Processing** — Multiple conflicting files resolve simultaneously for faster merges
4. **Syntax Validation** — Every merge is validated before being applied
**The result:** A build that was 50+ commits behind main merges in seconds instead of requiring manual conflict resolution.
### Additional Features
- **Insights** - Chat interface for exploring your codebase
- **Ideation** - Discover improvements, performance issues, and vulnerabilities
- **Changelog** - Generate release notes from completed tasks
---
## CLI Usage (Terminal-Only)
For terminal-based workflows, headless servers, or CI/CD integration, see **[guides/CLI-USAGE.md](guides/CLI-USAGE.md)**.
## ⚙️ How It Works
Auto Claude focuses on three core principles: **context engineering** (understanding your codebase before writing code), **good coding standards** (following best practices and patterns), and **validation logic** (ensuring code works before you see it).
### The Agent Pipeline
**Phase 1: Spec Creation** (3-8 phases based on complexity)
Before any code is written, agents gather context and create a detailed specification:
1. **Discovery** — Analyzes your project structure and tech stack
2. **Requirements** — Gathers what you want to build through interactive conversation
3. **Research** — Validates external integrations against real documentation
4. **Context Discovery** — Finds relevant files in your codebase
5. **Spec Writer** — Creates a comprehensive specification document
6. **Spec Critic** — Self-critiques using extended thinking to find issues early
7. **Planner** — Breaks work into subtasks with dependencies
8. **Validation** — Ensures all outputs are valid before proceeding
**Phase 2: Implementation**
With a validated spec, coding agents execute the plan:
1. **Planner Agent** — Creates subtask-based implementation plan
2. **Coder Agent** — Implements subtasks one-by-one with verification
3. **QA Reviewer** — Validates all acceptance criteria
4. **QA Fixer** — Fixes issues in a self-healing loop (up to 50 iterations)
Each session runs with a fresh context window. Progress is tracked via `implementation_plan.json` and Git commits.
**Phase 3: Merge**
When you're ready to merge, AI handles any conflicts that arose while you were working:
1. **Conflict Detection** — Identifies files modified in both main and the build
2. **3-Tier Resolution** — Git auto-merge → Conflict-only AI → Full-file AI (fallback)
3. **Parallel Merge** — Multiple files resolve simultaneously
4. **Staged for Review** — Changes are staged but not committed, so you can review before finalizing
### 🔒 Security Model
Three-layer defense keeps your code safe:
- **OS Sandbox** — Bash commands run in isolation
- **Filesystem Restrictions** — Operations limited to project directory
- **Command Allowlist** — Only approved commands based on your project's stack
## Project Structure
```
your-project/
├── .worktrees/ # Created during build (git-ignored)
── auto-claude/ # Isolated workspace for AI coding
├── .auto-claude/ # Per-project data (specs, plans, QA reports)
│ ├── specs/ # Task specifications
│ ├── roadmap/ # Project roadmap
│ └── ideation/ # Ideas and planning
├── auto-claude/ # Python backend (framework code)
│ ├── run.py # Build entry point
│ ├── spec_runner.py # Spec creation orchestrator
│ ├── prompts/ # Agent prompt templates
│ └── ...
└── auto-claude-ui/ # Electron desktop application
└── ...
Auto-Claude/
├── apps/
── backend/ # Python agents, specs, QA pipeline
│ └── frontend/ # Electron desktop application
├── guides/ # Additional documentation
├── tests/ # Test suite
└── scripts/ # Build utilities
```
### Understanding the Folders
---
**You don't create these folders manually** - they serve different purposes:
## CLI Usage
- **`auto-claude/`** - The framework repository itself (clone this once from GitHub)
- **`.auto-claude/`** - Created automatically in YOUR project when you run Auto Claude (stores specs, plans, QA reports)
- **`.worktrees/`** - Temporary isolated workspaces created during builds (git-ignored, deleted after merge)
For headless operation, CI/CD integration, or terminal-only workflows:
**When using Auto Claude on your project:**
```bash
cd your-project/ # Your own project directory
python /path/to/auto-claude/run.py --spec 001
# Auto Claude creates .auto-claude/ automatically in your-project/
cd apps/backend
# Create a spec interactively
python spec_runner.py --interactive
# Run autonomous build
python run.py --spec 001
# Review and merge
python run.py --spec 001 --review
python run.py --spec 001 --merge
```
**When developing Auto Claude itself:**
See [guides/CLI-USAGE.md](guides/CLI-USAGE.md) for complete CLI documentation.
---
## Configuration
Create `apps/backend/.env` from the example:
```bash
git clone https://github.com/yourusername/auto-claude
cd auto-claude/ # You're working in the framework repo
cp apps/backend/.env.example apps/backend/.env
```
The `.auto-claude/` directory is gitignored and project-specific - you'll have one per project you use Auto Claude on.
## Environment Variables (CLI Only)
> **Desktop UI users:** These are configured through the app settings — no manual setup needed.
| Variable | Required | Description |
|----------|----------|-------------|
| `CLAUDE_CODE_OAUTH_TOKEN` | Yes | OAuth token from `claude setup-token` |
| `AUTO_BUILD_MODEL` | No | Model override (default: claude-opus-4-5-20251101) |
| `GRAPHITI_ENABLED` | No | Enable Memory Layer for cross-session context |
| `AUTO_BUILD_MODEL` | No | Override the default Claude model |
See `auto-claude/.env.example` for complete configuration options.
---
## 💬 Community
## Building from Source
Join our Discord to get help, share what you're building, and connect with other Auto Claude users:
For contributors and development:
[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/KCXaPBr4Dj)
```bash
# Clone the repository
git clone https://github.com/AndyMik90/Auto-Claude.git
cd Auto-Claude
## 🤝 Contributing
# Install all dependencies
npm run install:all
We welcome contributions! Whether it's bug fixes, new features, or documentation improvements.
# Run in development mode
npm run dev
See **[CONTRIBUTING.md](CONTRIBUTING.md)** for guidelines on how to get started.
# Or build and run
npm start
```
## Acknowledgments
**System requirements for building:**
- Node.js 24+
- Python 3.12+
- npm 10+
This framework was inspired by Anthropic's [Autonomous Coding Agent](https://github.com/anthropics/claude-quickstarts/tree/main/autonomous-coding). Thank you to the Anthropic team for their innovative work on autonomous coding systems.
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development setup.
---
## Security
Auto Claude uses a three-layer security model:
1. **OS Sandbox** - Bash commands run in isolation
2. **Filesystem Restrictions** - Operations limited to project directory
3. **Dynamic Command Allowlist** - Only approved commands based on detected project stack
All releases are:
- Scanned with VirusTotal before publishing
- Include SHA256 checksums for verification
- Code-signed where applicable (macOS)
---
## Available Scripts
| Command | Description |
|---------|-------------|
| `npm run install:all` | Install backend and frontend dependencies |
| `npm start` | Build and run the desktop app |
| `npm run dev` | Run in development mode with hot reload |
| `npm run package` | Package for current platform |
| `npm run package:mac` | Package for macOS |
| `npm run package:win` | Package for Windows |
| `npm run package:linux` | Package for Linux |
| `npm run lint` | Run linter |
| `npm test` | Run frontend tests |
| `npm run test:backend` | Run backend tests |
---
## Contributing
We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for:
- Development setup instructions
- Code style guidelines
- Testing requirements
- Pull request process
---
## Community
- **Discord** - [Join our community](https://discord.gg/KCXaPBr4Dj)
- **Issues** - [Report bugs or request features](https://github.com/AndyMik90/Auto-Claude/issues)
- **Discussions** - [Ask questions](https://github.com/AndyMik90/Auto-Claude/discussions)
---
## License
**AGPL-3.0** - GNU Affero General Public License v3.0
This software is licensed under AGPL-3.0, which means:
Auto Claude is free to use. If you modify and distribute it, or run it as a service, your code must also be open source under AGPL-3.0.
- **Attribution Required**: You must give appropriate credit, provide a link to the license, and indicate if changes were made. When using Auto Claude, please credit the project.
- **Open Source Required**: If you modify this software and distribute it or run it as a service, you must release your source code under AGPL-3.0.
- **Network Use (Copyleft)**: If you run this software as a network service (e.g., SaaS), users interacting with it over a network must be able to receive the source code.
- **No Closed-Source Usage**: You cannot use this software in proprietary/closed-source projects without open-sourcing your entire project under AGPL-3.0.
**In simple terms**: You can use Auto Claude freely, but if you build on it, your code must also be open source under AGPL-3.0 and attribute this project. Closed-source commercial use requires a separate license.
For commercial licensing inquiries (closed-source usage), please contact the maintainers.
Commercial licensing available for closed-source use cases.
+163 -161
View File
@@ -1,186 +1,188 @@
# Release Process
This document describes how to create a new release of Auto Claude.
This document describes how releases are created for Auto Claude.
## Automated Release Process (Recommended)
## Overview
We provide an automated script that handles version bumping, git commits, and tagging to ensure version consistency.
### Prerequisites
- Clean git working directory (no uncommitted changes)
- You're on the branch you want to release from (usually `main`)
### Steps
1. **Run the version bump script:**
```bash
# Bump patch version (2.5.5 -> 2.5.6)
node scripts/bump-version.js patch
# Bump minor version (2.5.5 -> 2.6.0)
node scripts/bump-version.js minor
# Bump major version (2.5.5 -> 3.0.0)
node scripts/bump-version.js major
# Set specific version
node scripts/bump-version.js 2.6.0
```
This script will:
- ✅ Update `auto-claude-ui/package.json` with the new version
- ✅ Create a git commit with the version change
- ✅ Create a git tag (e.g., `v2.5.6`)
- ⚠️ **NOT** push to remote (you control when to push)
2. **Review the changes:**
```bash
git log -1 # View the commit
git show v2.5.6 # View the tag
```
3. **Push to GitHub:**
```bash
# Push the commit
git push origin main
# Push the tag
git push origin v2.5.6
```
4. **Create GitHub Release:**
- Go to [GitHub Releases](https://github.com/AndyMik90/Auto-Claude/releases)
- Click "Draft a new release"
- Select the tag you just pushed (e.g., `v2.5.6`)
- Add release notes (describe what changed)
- Click "Publish release"
5. **Automated builds will trigger:**
- ✅ Version validation workflow will verify version consistency
- ✅ Tests will run (`test-on-tag.yml`)
- ✅ Native module prebuilds will be created (`build-prebuilds.yml`)
- ✅ Discord notification will be sent (`discord-release.yml`)
## Manual Release Process (Not Recommended)
If you need to create a release manually, follow these steps **carefully** to avoid version mismatches:
1. **Update `auto-claude-ui/package.json`:**
```json
{
"version": "2.5.6"
}
```
2. **Commit the change:**
```bash
git add auto-claude-ui/package.json
git commit -m "chore: bump version to 2.5.6"
```
3. **Create and push tag:**
```bash
git tag -a v2.5.6 -m "Release v2.5.6"
git push origin main
git push origin v2.5.6
```
4. **Create GitHub Release** (same as step 4 above)
## Version Validation
A GitHub Action automatically validates that the version in `package.json` matches the git tag.
If there's a mismatch, the workflow will **fail** with a clear error message:
Auto Claude uses an automated release pipeline that ensures releases are only published after all builds succeed. This prevents version mismatches between documentation and actual releases.
```
❌ ERROR: Version mismatch detected!
The version in package.json (2.5.0) does not match
the git tag version (2.5.5).
To fix this:
1. Delete this tag: git tag -d v2.5.5
2. Update package.json version to 2.5.5
3. Commit the change
4. Recreate the tag: git tag -a v2.5.5 -m 'Release v2.5.5'
┌─────────────────────────────────────────────────────────────────────────────┐
│ RELEASE FLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ develop branch main branch │
│ ────────────── ─────────── │
│ │ │ │
│ │ 1. bump-version.js │ │
│ │ (creates commit) │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────┐ │ │
│ │ v2.8.0 │ 2. Create PR │ │
│ │ commit │ ────────────────────► │ │
│ └─────────┘ │ │
│ │ │
│ 3. Merge PR ▼ │
│ ┌──────────┐ │
│ │ v2.8.0 │ │
│ │ on main │ │
│ └────┬─────┘ │
│ │ │
│ ┌───────────────────┴───────────────────┐ │
│ │ GitHub Actions (automatic) │ │
│ ├───────────────────────────────────────┤ │
│ │ 4. prepare-release.yml │ │
│ │ - Detects version > latest tag │ │
│ │ - Creates tag v2.8.0 │ │
│ │ │ │
│ │ 5. release.yml (triggered by tag) │ │
│ │ - Builds macOS (Intel + ARM) │ │
│ │ - Builds Windows │ │
│ │ - Builds Linux │ │
│ │ - Generates changelog │ │
│ │ - Creates GitHub release │ │
│ │ - Updates README │ │
│ └───────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
This validation ensures we never ship a release where the updater shows the wrong version.
## For Maintainers: Creating a Release
## Troubleshooting
### Step 1: Bump the Version
### Version Mismatch Error
If you see a version mismatch error in GitHub Actions:
1. **Delete the incorrect tag:**
```bash
git tag -d v2.5.6 # Delete locally
git push origin :refs/tags/v2.5.6 # Delete remotely
```
2. **Use the automated script:**
```bash
node scripts/bump-version.js 2.5.6
git push origin main
git push origin v2.5.6
```
### Git Working Directory Not Clean
If the version bump script fails with "Git working directory is not clean":
On your development branch (typically `develop` or a feature branch):
```bash
# Commit or stash your changes first
git status
git add .
git commit -m "your changes"
# Navigate to project root
cd /path/to/auto-claude
# Then run the version bump script
node scripts/bump-version.js patch
# Bump version (choose one)
node scripts/bump-version.js patch # 2.7.1 -> 2.7.2 (bug fixes)
node scripts/bump-version.js minor # 2.7.1 -> 2.8.0 (new features)
node scripts/bump-version.js major # 2.7.1 -> 3.0.0 (breaking changes)
node scripts/bump-version.js 2.8.0 # Set specific version
```
## Release Checklist
This will:
- Update `apps/frontend/package.json`
- Update `package.json` (root)
- Update `apps/backend/__init__.py`
- Create a commit with message `chore: bump version to X.Y.Z`
Use this checklist when creating a new release:
### Step 2: Push and Create PR
- [ ] All tests passing on main branch
- [ ] CHANGELOG updated (if applicable)
- [ ] Run `node scripts/bump-version.js <type>`
- [ ] Review commit and tag
- [ ] Push commit and tag to GitHub
- [ ] Create GitHub Release with release notes
- [ ] Verify version validation passed
- [ ] Verify builds completed successfully
- [ ] Test the updater shows correct version
```bash
# Push your branch
git push origin your-branch
## What Gets Released
# Create PR to main (via GitHub UI or gh CLI)
gh pr create --base main --title "Release v2.8.0"
```
When you create a release, the following are built and published:
### Step 3: Merge to Main
1. **Native module prebuilds** - Windows node-pty binaries
2. **Electron app packages** - Desktop installers (triggered manually or via electron-builder)
3. **Discord notification** - Sent to the Auto Claude community
Once the PR is approved and merged to `main`, GitHub Actions will automatically:
1. **Detect the version bump** (`prepare-release.yml`)
2. **Create a git tag** (e.g., `v2.8.0`)
3. **Trigger the release workflow** (`release.yml`)
4. **Build binaries** for all platforms:
- macOS Intel (x64) - code signed & notarized
- macOS Apple Silicon (arm64) - code signed & notarized
- Windows (NSIS installer) - code signed
- Linux (AppImage + .deb)
5. **Generate changelog** from merged PRs (using release-drafter)
6. **Scan binaries** with VirusTotal
7. **Create GitHub release** with all artifacts
8. **Update README** with new version badge and download links
### Step 4: Verify
After merging, check:
- [GitHub Actions](https://github.com/AndyMik90/Auto-Claude/actions) - ensure all workflows pass
- [Releases](https://github.com/AndyMik90/Auto-Claude/releases) - verify release was created
- [README](https://github.com/AndyMik90/Auto-Claude#download) - confirm version updated
## Version Numbering
We follow [Semantic Versioning (SemVer)](https://semver.org/):
We follow [Semantic Versioning](https://semver.org/):
- **MAJOR** version (X.0.0) - Breaking changes
- **MINOR** version (0.X.0) - New features (backward compatible)
- **PATCH** version (0.0.X) - Bug fixes (backward compatible)
- **MAJOR** (X.0.0): Breaking changes, incompatible API changes
- **MINOR** (0.X.0): New features, backwards compatible
- **PATCH** (0.0.X): Bug fixes, backwards compatible
Examples:
- `2.5.5 -> 2.5.6` - Bug fix
- `2.5.6 -> 2.6.0` - New feature
- `2.6.0 -> 3.0.0` - Breaking change
## Changelog Generation
Changelogs are automatically generated from merged PRs using [Release Drafter](https://github.com/release-drafter/release-drafter).
### PR Labels for Changelog Categories
| Label | Category |
|-------|----------|
| `feature`, `enhancement` | New Features |
| `bug`, `fix` | Bug Fixes |
| `improvement`, `refactor` | Improvements |
| `documentation` | Documentation |
| (any other) | Other Changes |
**Tip:** Add appropriate labels to your PRs for better changelog organization.
## Workflows
| Workflow | Trigger | Purpose |
|----------|---------|---------|
| `prepare-release.yml` | Push to `main` | Detects version bump, creates tag |
| `release.yml` | Tag `v*` pushed | Builds binaries, creates release |
| `validate-version.yml` | Tag `v*` pushed | Validates tag matches package.json |
| `update-readme` (in release.yml) | After release | Updates README with new version |
## Troubleshooting
### Release didn't trigger after merge
1. Check if version in `package.json` is greater than latest tag:
```bash
git tag -l 'v*' --sort=-version:refname | head -1
cat apps/frontend/package.json | grep version
```
2. Ensure the merge commit touched `package.json`:
```bash
git diff HEAD~1 --name-only | grep package.json
```
### Build failed after tag was created
- The release won't be published if builds fail
- Fix the issue and create a new patch version
- Don't reuse failed version numbers
### README shows wrong version
- README is only updated after successful release
- If release failed, README keeps the previous version (this is intentional)
- Once you successfully release, README will update automatically
## Manual Release (Emergency Only)
In rare cases where you need to bypass the automated flow:
```bash
# Create tag manually (NOT RECOMMENDED)
git tag -a v2.8.0 -m "Release v2.8.0"
git push origin v2.8.0
# This will trigger release.yml directly
```
**Warning:** Only do this if you're certain the version in package.json matches the tag.
## Security
- All macOS binaries are code signed with Apple Developer certificate
- All macOS binaries are notarized by Apple
- Windows binaries are code signed
- All binaries are scanned with VirusTotal
- SHA256 checksums are generated for all artifacts
@@ -117,9 +117,9 @@
# ELECTRON_DEBUG_PORT=9222
# =============================================================================
# GRAPHITI MEMORY INTEGRATION (OPTIONAL)
# GRAPHITI MEMORY INTEGRATION (REQUIRED)
# =============================================================================
# Enable Graphiti-based persistent memory layer for cross-session context
# Graphiti-based persistent memory layer for cross-session context
# retention. Uses LadybugDB as the embedded graph database.
#
# REQUIREMENTS:
@@ -133,8 +133,8 @@
# - Ollama (local, fully offline)
# - Google AI (Gemini)
# Enable Graphiti integration (default: false)
# GRAPHITI_ENABLED=true
# Graphiti is enabled by default. Set to false to disable memory features.
GRAPHITI_ENABLED=true
# =============================================================================
# GRAPHITI: Database Settings
@@ -153,10 +153,10 @@
# Choose which providers to use for LLM and embeddings.
# Default is "openai" for both.
# LLM provider: openai | anthropic | azure_openai | ollama | google
# LLM provider: openai | anthropic | azure_openai | ollama | google | openrouter
# GRAPHITI_LLM_PROVIDER=openai
# Embedder provider: openai | voyage | azure_openai | ollama | google
# Embedder provider: openai | voyage | azure_openai | ollama | google | openrouter
# GRAPHITI_EMBEDDER_PROVIDER=openai
# =============================================================================
@@ -221,6 +221,28 @@
# Google Embedding Model (default: text-embedding-004)
# GOOGLE_EMBEDDING_MODEL=text-embedding-004
# =============================================================================
# GRAPHITI: OpenRouter Provider (Multi-provider aggregator)
# =============================================================================
# Use OpenRouter to access multiple LLM providers through a single API.
# OpenRouter provides access to Anthropic, OpenAI, Google, and many other models.
# Get API key from: https://openrouter.ai/keys
#
# Required: OPENROUTER_API_KEY
# OpenRouter API Key
# OPENROUTER_API_KEY=sk-or-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# OpenRouter Base URL (default: https://openrouter.ai/api/v1)
# OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
# OpenRouter LLM Model (default: anthropic/claude-3.5-sonnet)
# Popular choices: anthropic/claude-3.5-sonnet, openai/gpt-4o, google/gemini-2.0-flash
# OPENROUTER_LLM_MODEL=anthropic/claude-3.5-sonnet
# OpenRouter Embedding Model (default: openai/text-embedding-3-small)
# OPENROUTER_EMBEDDING_MODEL=openai/text-embedding-3-small
# =============================================================================
# GRAPHITI: Azure OpenAI Provider
# =============================================================================
@@ -307,3 +329,11 @@
# GRAPHITI_LLM_PROVIDER=google
# GRAPHITI_EMBEDDER_PROVIDER=google
# GOOGLE_API_KEY=AIzaSyxxxxxxxx
#
# --- Example 6: OpenRouter (multi-provider aggregator) ---
# GRAPHITI_ENABLED=true
# GRAPHITI_LLM_PROVIDER=openrouter
# GRAPHITI_EMBEDDER_PROVIDER=openrouter
# OPENROUTER_API_KEY=sk-or-xxxxxxxx
# OPENROUTER_LLM_MODEL=anthropic/claude-3.5-sonnet
# OPENROUTER_EMBEDDING_MODEL=openai/text-embedding-3-small
@@ -61,3 +61,6 @@ Thumbs.db
# Tests (development only)
tests/
# Auto Claude data directory
.auto-claude/
+120
View File
@@ -0,0 +1,120 @@
# Auto Claude Backend
Autonomous coding framework powered by Claude AI. Builds software features through coordinated multi-agent sessions.
## Getting Started
### 1. Install
```bash
cd apps/backend
python -m pip install -r requirements.txt
```
### 2. Configure
```bash
cp .env.example .env
```
Set your Claude API token in `.env`:
```
CLAUDE_CODE_OAUTH_TOKEN=your-token-here
```
Get your token by running: `claude setup-token`
### 3. Run
```bash
# List available specs
python run.py --list
# Run a spec
python run.py --spec 001
```
## Requirements
- Python 3.10+
- Claude API token
## Commands
| Command | Description |
|---------|-------------|
| `--list` | List all specs |
| `--spec 001` | Run spec 001 |
| `--spec 001 --isolated` | Run in isolated workspace |
| `--spec 001 --direct` | Run directly in repo |
| `--spec 001 --merge` | Merge completed build |
| `--spec 001 --review` | Review build changes |
| `--spec 001 --discard` | Discard build |
| `--spec 001 --qa` | Run QA validation |
| `--list-worktrees` | List all worktrees |
| `--help` | Show all options |
## Configuration
Optional `.env` settings:
| Variable | Description |
|----------|-------------|
| `AUTO_BUILD_MODEL` | Override Claude model |
| `DEBUG=true` | Enable debug logging |
| `LINEAR_API_KEY` | Enable Linear integration |
| `GRAPHITI_ENABLED=true` | Enable memory system |
## Troubleshooting
**"tree-sitter not available"** - Safe to ignore, uses regex fallback.
**Missing module errors** - Run `python -m pip install -r requirements.txt`
**Debug mode** - Set `DEBUG=true DEBUG_LEVEL=2` before running.
---
## For Developers
### Project Structure
```
backend/
├── agents/ # AI agent execution
├── analysis/ # Code analysis
├── cli/ # Command-line interface
├── core/ # Core utilities
├── integrations/ # External services (Linear, Graphiti)
├── merge/ # Git merge handling
├── project/ # Project detection
├── prompts/ # Prompt templates
├── qa/ # QA validation
├── spec/ # Spec management
└── ui/ # Terminal UI
```
### Design Principles
- **SOLID** - Single responsibility, clean interfaces
- **DRY** - Shared utilities in `core/`
- **KISS** - Simple flat imports via facade modules
### Import Convention
```python
# Use facade modules for clean imports
from debug import debug, debug_error
from progress import count_subtasks
from workspace import setup_workspace
```
### Adding Features
1. Create module in appropriate folder
2. Export API in `__init__.py`
3. Add facade module at root if commonly imported
## License
AGPL-3.0
+23
View File
@@ -0,0 +1,23 @@
"""
Auto Claude Backend - Autonomous Coding Framework
==================================================
Multi-agent autonomous coding framework that builds software through
coordinated AI agent sessions.
This package provides:
- Autonomous agent execution for building features from specs
- Workspace isolation via git worktrees
- QA validation loops
- Memory management (Graphiti + file-based)
- Linear integration for project management
Quick Start:
python run.py --spec 001 # Run a spec
python run.py --list # List all specs
See README.md for full documentation.
"""
__version__ = "2.7.2"
__author__ = "Auto Claude Team"
+92
View File
@@ -0,0 +1,92 @@
"""
Agents Module
=============
Modular agent system for autonomous coding.
This module provides:
- run_autonomous_agent: Main coder agent loop
- run_followup_planner: Follow-up planner for completed specs
- Memory management (Graphiti + file-based fallback)
- Session management and post-processing
- Utility functions for git and plan management
Uses lazy imports to avoid circular dependencies.
"""
__all__ = [
# Main API
"run_autonomous_agent",
"run_followup_planner",
# Memory
"debug_memory_system_status",
"get_graphiti_context",
"save_session_memory",
"save_session_to_graphiti",
# Session
"run_agent_session",
"post_session_processing",
# Utils
"get_latest_commit",
"get_commit_count",
"load_implementation_plan",
"find_subtask_in_plan",
"find_phase_for_subtask",
"sync_plan_to_source",
# Constants
"AUTO_CONTINUE_DELAY_SECONDS",
"HUMAN_INTERVENTION_FILE",
]
def __getattr__(name):
"""Lazy imports to avoid circular dependencies."""
if name in ("AUTO_CONTINUE_DELAY_SECONDS", "HUMAN_INTERVENTION_FILE"):
from .base import AUTO_CONTINUE_DELAY_SECONDS, HUMAN_INTERVENTION_FILE
return locals()[name]
elif name == "run_autonomous_agent":
from .coder import run_autonomous_agent
return run_autonomous_agent
elif name in (
"debug_memory_system_status",
"get_graphiti_context",
"save_session_memory",
"save_session_to_graphiti",
):
from .memory_manager import (
debug_memory_system_status,
get_graphiti_context,
save_session_memory,
save_session_to_graphiti,
)
return locals()[name]
elif name == "run_followup_planner":
from .planner import run_followup_planner
return run_followup_planner
elif name in ("post_session_processing", "run_agent_session"):
from .session import post_session_processing, run_agent_session
return locals()[name]
elif name in (
"find_phase_for_subtask",
"find_subtask_in_plan",
"get_commit_count",
"get_latest_commit",
"load_implementation_plan",
"sync_plan_to_source",
):
from .utils import (
find_phase_for_subtask,
find_subtask_in_plan,
get_commit_count,
get_latest_commit,
load_implementation_plan,
sync_plan_to_source,
)
return locals()[name]
raise AttributeError(f"module 'agents' has no attribute '{name}'")
@@ -18,6 +18,7 @@ from linear_updater import (
linear_task_stuck,
)
from phase_config import get_phase_model, get_phase_thinking_budget
from phase_event import ExecutionPhase, emit_phase
from progress import (
count_subtasks,
count_subtasks_detailed,
@@ -146,6 +147,7 @@ async def run_autonomous_agent(
# Update status for planning phase
status_manager.update(state=BuildState.PLANNING)
emit_phase(ExecutionPhase.PLANNING, "Creating implementation plan")
is_planning_phase = True
current_log_phase = LogPhase.PLANNING
@@ -173,6 +175,9 @@ async def run_autonomous_agent(
if task_logger:
task_logger.start_phase(LogPhase.CODING, "Continuing implementation...")
# Emit phase event when continuing build
emit_phase(ExecutionPhase.CODING, "Continuing implementation")
# Show human intervention hint
content = [
bold("INTERACTIVE CONTROLS"),
@@ -273,6 +278,7 @@ async def run_autonomous_agent(
if is_planning_phase:
is_planning_phase = False
current_log_phase = LogPhase.CODING
emit_phase(ExecutionPhase.CODING, "Starting implementation")
if task_logger:
task_logger.end_phase(
LogPhase.PLANNING,
@@ -386,10 +392,11 @@ async def run_autonomous_agent(
# Handle session status
if status == "complete":
# Don't emit COMPLETE here - subtasks are done but QA hasn't run yet
# QA loop will emit COMPLETE after actual approval
print_build_complete_banner(spec_dir)
status_manager.update(state=BuildState.COMPLETE)
# End coding phase in task logger
if task_logger:
task_logger.end_phase(
LogPhase.CODING,
@@ -397,7 +404,6 @@ async def run_autonomous_agent(
message="All subtasks completed successfully",
)
# Notify Linear that build is complete (moving to QA)
if linear_task and linear_task.task_id:
await linear_build_complete(spec_dir)
print_status("Linear notified: build complete, ready for QA", "success")
@@ -432,6 +438,7 @@ async def run_autonomous_agent(
await asyncio.sleep(AUTO_CONTINUE_DELAY_SECONDS)
elif status == "error":
emit_phase(ExecutionPhase.FAILED, "Session encountered an error")
print_status("Session encountered an error", "error")
print(muted("Will retry with a fresh session..."))
status_manager.update(state=BuildState.ERROR)
@@ -10,6 +10,7 @@ from pathlib import Path
from core.client import create_client
from phase_config import get_phase_thinking_budget
from phase_event import ExecutionPhase, emit_phase
from task_logger import (
LogPhase,
get_task_logger,
@@ -67,6 +68,7 @@ async def run_followup_planner(
# Initialize status manager for ccstatusline
status_manager = StatusManager(project_dir)
status_manager.set_active(spec_dir.name, BuildState.PLANNING)
emit_phase(ExecutionPhase.PLANNING, "Follow-up planning")
# Initialize task logger for persistent logging
task_logger = get_task_logger(spec_dir)
@@ -77,6 +77,12 @@ def get_allowed_tools(
TOOL_GET_SESSION_CONTEXT,
],
},
"pr_reviewer": {
# PR reviewers can ONLY read - no bash, no edits, no writes
# This prevents the agent from switching branches or making changes
"base": BASE_READ_TOOLS,
"auto_claude": [], # No auto-claude tools needed for PR review
},
"qa_fixer": {
"base": BASE_READ_TOOLS + BASE_WRITE_TOOLS,
"auto_claude": [
@@ -6,6 +6,9 @@ Code analysis and project scanning tools.
"""
# Import from analyzers subpackage (these are the modular analyzers)
from __future__ import annotations
from .analyzers import (
ProjectAnalyzer as ModularProjectAnalyzer,
)
@@ -27,6 +27,8 @@ This module now serves as a facade to the modular analyzer system in the analyze
All actual implementation is in focused submodules for better maintainability.
"""
from __future__ import annotations
import json
from pathlib import Path
@@ -11,6 +11,8 @@ Main exports:
- analyze_service: Convenience function for service analysis
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -5,6 +5,8 @@ Base Analyzer Module
Provides common constants, utilities, and base functionality shared across all analyzers.
"""
from __future__ import annotations
import json
from pathlib import Path
@@ -5,6 +5,8 @@ Context Analyzer Package
Contains specialized detectors for comprehensive project context analysis.
"""
from __future__ import annotations
from .api_docs_detector import ApiDocsDetector
from .auth_detector import AuthDetector
from .env_detector import EnvironmentDetector
@@ -8,6 +8,8 @@ Detects API documentation tools and configurations:
- API documentation endpoints
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -11,6 +11,8 @@ Detects authentication and authorization patterns:
- Auth middleware and decorators
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Any
@@ -9,6 +9,8 @@ Detects and analyzes environment variables from multiple sources:
- Source code (os.getenv, process.env)
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Any
@@ -9,6 +9,8 @@ Detects background job and task queue systems:
- Scheduled tasks and cron jobs
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Any
@@ -10,6 +10,8 @@ Detects database migration tools and configurations:
- Prisma
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -9,6 +9,8 @@ Detects monitoring and observability setup:
- Logging infrastructure
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -13,6 +13,8 @@ Detects external service integrations based on dependencies:
- Monitoring tools (Sentry, Datadog, New Relic)
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Any
@@ -14,6 +14,8 @@ Orchestrates comprehensive project context analysis including:
This module delegates to specialized detectors for clean separation of concerns.
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -7,6 +7,8 @@ Detects database models and schemas across different ORMs:
- JavaScript/TypeScript: Prisma, TypeORM, Drizzle, Mongoose
"""
from __future__ import annotations
import re
from pathlib import Path
@@ -6,6 +6,8 @@ Detects programming languages, frameworks, and related technologies across diffe
Supports Python, Node.js/TypeScript, Go, Rust, and Ruby frameworks.
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -6,6 +6,8 @@ Detects application ports from multiple sources including entry points,
environment files, Docker Compose, configuration files, and scripts.
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Any
@@ -5,6 +5,8 @@ Project Analyzer Module
Analyzes entire projects, detecting monorepo structures, services, infrastructure, and conventions.
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
@@ -9,6 +9,8 @@ Detects API routes and endpoints across different frameworks:
- Rust: Axum, Actix
"""
from __future__ import annotations
import re
from pathlib import Path
@@ -6,6 +6,8 @@ Main ServiceAnalyzer class that coordinates all analysis for a single service/pa
Integrates framework detection, route analysis, database models, and context extraction.
"""
from __future__ import annotations
import re
from pathlib import Path
from typing import Any
@@ -22,6 +22,8 @@ Usage:
print(f"Test Commands: {result.test_commands}")
"""
from __future__ import annotations
import json
import re
from dataclasses import dataclass, field
@@ -9,6 +9,8 @@ Uses the Claude Agent SDK (same as the rest of the system) for extraction.
Falls back to generic insights if extraction fails (never blocks the build).
"""
from __future__ import annotations
import json
import logging
import os
@@ -28,6 +28,9 @@ needed for the detected tech stack, while blocking dangerous operations.
"""
# Re-export all public API from the project module
from __future__ import annotations
from project import (
# Command registries
BASE_COMMANDS,
@@ -21,6 +21,8 @@ Usage:
test_types = classifier.get_required_test_types(spec_dir)
"""
from __future__ import annotations
import json
from dataclasses import dataclass, field
from pathlib import Path
@@ -21,6 +21,8 @@ Usage:
print("Security issues found - blocking QA approval")
"""
from __future__ import annotations
import json
import subprocess
from dataclasses import dataclass, field
@@ -22,6 +22,8 @@ Usage:
print(f"Test command: {result['test_command']}")
"""
from __future__ import annotations
import json
from dataclasses import dataclass, field
from pathlib import Path
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
"""
Analyzer facade module.
Provides backward compatibility for scripts that import from analyzer.py at the root.
Actual implementation is in analysis/analyzer.py.
"""
from analysis.analyzer import (
ProjectAnalyzer,
ServiceAnalyzer,
analyze_project,
analyze_service,
main,
)
__all__ = [
"ServiceAnalyzer",
"ProjectAnalyzer",
"analyze_project",
"analyze_service",
"main",
]
if __name__ == "__main__":
main()
+36
View File
@@ -0,0 +1,36 @@
"""
Auto Claude tools module facade.
Provides MCP tools for agent operations.
Re-exports from agents.tools_pkg for clean imports.
"""
from agents.tools_pkg.models import ( # noqa: F401
ELECTRON_TOOLS,
TOOL_GET_BUILD_PROGRESS,
TOOL_GET_SESSION_CONTEXT,
TOOL_RECORD_DISCOVERY,
TOOL_RECORD_GOTCHA,
TOOL_UPDATE_QA_STATUS,
TOOL_UPDATE_SUBTASK_STATUS,
is_electron_mcp_enabled,
)
from agents.tools_pkg.permissions import get_allowed_tools # noqa: F401
from agents.tools_pkg.registry import ( # noqa: F401
create_auto_claude_mcp_server,
is_tools_available,
)
__all__ = [
"create_auto_claude_mcp_server",
"get_allowed_tools",
"is_tools_available",
"TOOL_UPDATE_SUBTASK_STATUS",
"TOOL_GET_BUILD_PROGRESS",
"TOOL_RECORD_DISCOVERY",
"TOOL_RECORD_GOTCHA",
"TOOL_GET_SESSION_CONTEXT",
"TOOL_UPDATE_QA_STATUS",
"ELECTRON_TOOLS",
"is_electron_mcp_enabled",
]
+216
View File
@@ -0,0 +1,216 @@
"""
Batch Task Management Commands
==============================
Commands for creating and managing multiple tasks from batch files.
"""
import json
from pathlib import Path
from ui import highlight, print_status
def handle_batch_create_command(batch_file: str, project_dir: str) -> bool:
"""
Create multiple tasks from a batch JSON file.
Args:
batch_file: Path to JSON file with task definitions
project_dir: Project directory
Returns:
True if successful
"""
batch_path = Path(batch_file)
if not batch_path.exists():
print_status(f"Batch file not found: {batch_file}", "error")
return False
try:
with open(batch_path) as f:
batch_data = json.load(f)
except json.JSONDecodeError as e:
print_status(f"Invalid JSON in batch file: {e}", "error")
return False
tasks = batch_data.get("tasks", [])
if not tasks:
print_status("No tasks found in batch file", "warning")
return False
print_status(f"Creating {len(tasks)} tasks from batch file", "info")
print()
specs_dir = Path(project_dir) / ".auto-claude" / "specs"
specs_dir.mkdir(parents=True, exist_ok=True)
# Find next spec ID
existing_specs = [d.name for d in specs_dir.iterdir() if d.is_dir()]
next_id = (
max([int(s.split("-")[0]) for s in existing_specs if s[0].isdigit()] or [0]) + 1
)
created_specs = []
for idx, task in enumerate(tasks, 1):
spec_id = f"{next_id:03d}"
task_title = task.get("title", f"Task {idx}")
task_slug = task_title.lower().replace(" ", "-")[:50]
spec_name = f"{spec_id}-{task_slug}"
spec_dir = specs_dir / spec_name
spec_dir.mkdir(exist_ok=True)
# Create requirements.json
requirements = {
"task_description": task.get("description", task_title),
"description": task.get("description", task_title),
"workflow_type": task.get("workflow_type", "feature"),
"services_involved": task.get("services", ["frontend"]),
"priority": task.get("priority", 5),
"complexity_inferred": task.get("complexity", "standard"),
"inferred_from": {},
"created_at": Path(spec_dir).stat().st_mtime,
"estimate": {
"estimated_hours": task.get("estimated_hours", 4.0),
"estimated_days": task.get("estimated_days", 0.5),
},
}
req_file = spec_dir / "requirements.json"
with open(req_file, "w") as f:
json.dump(requirements, f, indent=2, default=str)
created_specs.append(
{
"id": spec_id,
"name": spec_name,
"title": task_title,
"status": "pending_spec_creation",
}
)
print_status(
f"[{idx}/{len(tasks)}] Created {spec_id} - {task_title}", "success"
)
next_id += 1
print()
print_status(f"Created {len(created_specs)} spec(s) successfully", "success")
print()
# Show summary
print(highlight("Next steps:"))
print(" 1. Generate specs: spec_runner.py --continue <spec_id>")
print(" 2. Approve specs and build them")
print(" 3. Run: python run.py --spec <id> to execute")
return True
def handle_batch_status_command(project_dir: str) -> bool:
"""
Show status of all specs in project.
Args:
project_dir: Project directory
Returns:
True if successful
"""
specs_dir = Path(project_dir) / ".auto-claude" / "specs"
if not specs_dir.exists():
print_status("No specs found in project", "warning")
return True
specs = sorted([d for d in specs_dir.iterdir() if d.is_dir()])
if not specs:
print_status("No specs found", "warning")
return True
print_status(f"Found {len(specs)} spec(s)", "info")
print()
for spec_dir in specs:
spec_name = spec_dir.name
req_file = spec_dir / "requirements.json"
status = "unknown"
title = spec_name
if req_file.exists():
try:
with open(req_file) as f:
req = json.load(f)
title = req.get("task_description", title)
except json.JSONDecodeError:
pass
# Determine status
if (spec_dir / "spec.md").exists():
status = "spec_created"
elif (spec_dir / "implementation_plan.json").exists():
status = "building"
elif (spec_dir / "qa_report.md").exists():
status = "qa_approved"
else:
status = "pending_spec"
status_icon = {
"pending_spec": "",
"spec_created": "📋",
"building": "⚙️",
"qa_approved": "",
"unknown": "",
}.get(status, "")
print(f"{status_icon} {spec_name:<40} {title}")
return True
def handle_batch_cleanup_command(project_dir: str, dry_run: bool = True) -> bool:
"""
Clean up completed specs and worktrees.
Args:
project_dir: Project directory
dry_run: If True, show what would be deleted
Returns:
True if successful
"""
specs_dir = Path(project_dir) / ".auto-claude" / "specs"
worktrees_dir = Path(project_dir) / ".worktrees"
if not specs_dir.exists():
print_status("No specs directory found", "info")
return True
# Find completed specs
completed = []
for spec_dir in specs_dir.iterdir():
if spec_dir.is_dir() and (spec_dir / "qa_report.md").exists():
completed.append(spec_dir.name)
if not completed:
print_status("No completed specs to clean up", "info")
return True
print_status(f"Found {len(completed)} completed spec(s)", "info")
if dry_run:
print()
print("Would remove:")
for spec_name in completed:
print(f" - {spec_name}")
wt_path = worktrees_dir / spec_name
if wt_path.exists():
print(f" └─ .worktrees/{spec_name}/")
print()
print("Run with --no-dry-run to actually delete")
return True
@@ -15,11 +15,12 @@ _PARENT_DIR = Path(__file__).parent.parent
if str(_PARENT_DIR) not in sys.path:
sys.path.insert(0, str(_PARENT_DIR))
from ui import (
Icons,
icon,
)
from .batch_commands import (
handle_batch_cleanup_command,
handle_batch_create_command,
handle_batch_status_command,
)
from .build_commands import handle_build_command
from .followup_commands import handle_followup_command
from .qa_commands import (
@@ -196,13 +197,6 @@ Environment Variables:
help="Show human review/approval status for a spec",
)
# Dev mode (deprecated)
parser.add_argument(
"--dev",
action="store_true",
help="[Deprecated] No longer has any effect - kept for compatibility",
)
# Non-interactive mode (for UI/automation)
parser.add_argument(
"--auto-continue",
@@ -237,6 +231,30 @@ Environment Variables:
help="Base branch for creating worktrees (default: auto-detect or current branch)",
)
# Batch task management
parser.add_argument(
"--batch-create",
type=str,
default=None,
metavar="FILE",
help="Create multiple tasks from a batch JSON file",
)
parser.add_argument(
"--batch-status",
action="store_true",
help="Show status of all specs in the project",
)
parser.add_argument(
"--batch-cleanup",
action="store_true",
help="Clean up completed specs (dry-run by default)",
)
parser.add_argument(
"--no-dry-run",
action="store_true",
help="Actually delete files in cleanup (not just preview)",
)
return parser.parse_args()
@@ -261,16 +279,10 @@ def main() -> None:
# Get model (with env var fallback)
model = args.model or os.environ.get("AUTO_BUILD_MODEL", DEFAULT_MODEL)
# Note: --dev flag is deprecated but kept for API compatibility
if args.dev:
print(
f"\n{icon(Icons.GEAR)} Note: --dev flag is deprecated. All specs now use .auto-claude/specs/\n"
)
# Handle --list command
if args.list:
print_banner()
print_specs_list(project_dir, args.dev)
print_specs_list(project_dir)
return
# Handle --list-worktrees command
@@ -283,6 +295,19 @@ def main() -> None:
handle_cleanup_worktrees_command(project_dir)
return
# Handle batch commands
if args.batch_create:
handle_batch_create_command(args.batch_create, str(project_dir))
return
if args.batch_status:
handle_batch_status_command(str(project_dir))
return
if args.batch_cleanup:
handle_batch_cleanup_command(str(project_dir), dry_run=not args.no_dry_run)
return
# Require --spec if not listing
if not args.spec:
print_banner()
@@ -295,14 +320,14 @@ def main() -> None:
sys.exit(1)
# Find the spec
debug("run.py", "Finding spec", spec_identifier=args.spec, dev_mode=args.dev)
spec_dir = find_spec(project_dir, args.spec, args.dev)
debug("run.py", "Finding spec", spec_identifier=args.spec)
spec_dir = find_spec(project_dir, args.spec)
if not spec_dir:
debug_error("run.py", "Spec not found", spec=args.spec)
print_banner()
print(f"\nError: Spec '{args.spec}' not found")
print("\nAvailable specs:")
print_specs_list(project_dir, args.dev)
print_specs_list(project_dir)
sys.exit(1)
debug_success("run.py", "Spec found", spec_dir=str(spec_dir))
@@ -19,18 +19,17 @@ from workspace import get_existing_build_worktree
from .utils import get_specs_dir
def list_specs(project_dir: Path, dev_mode: bool = False) -> list[dict]:
def list_specs(project_dir: Path) -> list[dict]:
"""
List all specs in the project.
Args:
project_dir: Project root directory
dev_mode: If True, use dev/auto-claude/specs/
Returns:
List of spec info dicts with keys: number, name, path, status, progress
"""
specs_dir = get_specs_dir(project_dir, dev_mode)
specs_dir = get_specs_dir(project_dir)
specs = []
if not specs_dir.exists():
@@ -93,14 +92,73 @@ def list_specs(project_dir: Path, dev_mode: bool = False) -> list[dict]:
return specs
def print_specs_list(project_dir: Path, dev_mode: bool = False) -> None:
"""Print a formatted list of all specs."""
specs = list_specs(project_dir, dev_mode)
def print_specs_list(project_dir: Path, auto_create: bool = True) -> None:
"""Print a formatted list of all specs.
Args:
project_dir: Project root directory
auto_create: If True and no specs exist, automatically launch spec creation
"""
import subprocess
specs = list_specs(project_dir)
if not specs:
print("\nNo specs found.")
print("\nCreate your first spec:")
print(" claude /spec")
if auto_create:
# Get the backend directory and find spec_runner.py
backend_dir = Path(__file__).parent.parent
spec_runner = backend_dir / "runners" / "spec_runner.py"
# Find Python executable - use current interpreter
python_path = sys.executable
if spec_runner.exists() and python_path:
# Quick prompt for task description
print("\n" + "=" * 60)
print(" QUICK START")
print("=" * 60)
print("\nWhat do you want to build?")
print(
"(Enter a brief description, or press Enter for interactive mode)\n"
)
try:
task = input("> ").strip()
except (EOFError, KeyboardInterrupt):
print("\nCancelled.")
return
if task:
# Direct mode: create spec and start building
print(f"\nStarting build for: {task}\n")
subprocess.run(
[
python_path,
str(spec_runner),
"--task",
task,
"--complexity",
"simple",
"--auto-approve",
],
cwd=project_dir,
)
else:
# Interactive mode
print("\nLaunching interactive mode...\n")
subprocess.run(
[python_path, str(spec_runner), "--interactive"],
cwd=project_dir,
)
return
else:
print("\nCreate your first spec:")
print(" python runners/spec_runner.py --interactive")
else:
print("\nCreate your first spec:")
print(" python runners/spec_runner.py --interactive")
return
print("\n" + "=" * 70)
@@ -54,35 +54,56 @@ def setup_environment() -> Path:
return script_dir
def find_spec(
project_dir: Path, spec_identifier: str, dev_mode: bool = False
) -> Path | None:
def find_spec(project_dir: Path, spec_identifier: str) -> Path | None:
"""
Find a spec by number or full name.
Args:
project_dir: Project root directory
spec_identifier: Either "001" or "001-feature-name"
dev_mode: If True, use dev/auto-claude/specs/
Returns:
Path to spec folder, or None if not found
"""
specs_dir = get_specs_dir(project_dir, dev_mode)
specs_dir = get_specs_dir(project_dir)
if not specs_dir.exists():
return None
if specs_dir.exists():
# Try exact match first
exact_path = specs_dir / spec_identifier
if exact_path.exists() and (exact_path / "spec.md").exists():
return exact_path
# Try exact match first
exact_path = specs_dir / spec_identifier
if exact_path.exists() and (exact_path / "spec.md").exists():
return exact_path
# Try matching by number prefix
for spec_folder in specs_dir.iterdir():
if spec_folder.is_dir() and spec_folder.name.startswith(
spec_identifier + "-"
):
if (spec_folder / "spec.md").exists():
return spec_folder
# Try matching by number prefix
for spec_folder in specs_dir.iterdir():
if spec_folder.is_dir() and spec_folder.name.startswith(spec_identifier + "-"):
if (spec_folder / "spec.md").exists():
return spec_folder
# Check worktree specs (for merge-preview, merge, review, discard operations)
worktree_base = project_dir / ".worktrees"
if worktree_base.exists():
# Try exact match in worktree
worktree_spec = (
worktree_base / spec_identifier / ".auto-claude" / "specs" / spec_identifier
)
if worktree_spec.exists() and (worktree_spec / "spec.md").exists():
return worktree_spec
# Try matching by prefix in worktrees
for worktree_dir in worktree_base.iterdir():
if worktree_dir.is_dir() and worktree_dir.name.startswith(
spec_identifier + "-"
):
spec_in_worktree = (
worktree_dir / ".auto-claude" / "specs" / worktree_dir.name
)
if (
spec_in_worktree.exists()
and (spec_in_worktree / "spec.md").exists()
):
return spec_in_worktree
return None
@@ -185,9 +206,9 @@ def get_project_dir(provided_dir: Path | None) -> Path:
project_dir = Path.cwd()
# Auto-detect if running from within auto-claude directory (the source code)
if project_dir.name == "auto-claude" and (project_dir / "run.py").exists():
# Running from within auto-claude/ source directory, go up 1 level
project_dir = project_dir.parent
# Auto-detect if running from within apps/backend directory (the source code)
if project_dir.name == "backend" and (project_dir / "run.py").exists():
# Running from within apps/backend/ source directory, go up 2 levels
project_dir = project_dir.parent.parent
return project_dir
@@ -14,7 +14,14 @@ _PARENT_DIR = Path(__file__).parent.parent
if str(_PARENT_DIR) not in sys.path:
sys.path.insert(0, str(_PARENT_DIR))
from core.workspace.git_utils import _is_auto_claude_file, is_lock_file
from core.workspace.git_utils import (
_is_auto_claude_file,
apply_path_mapping,
detect_file_renames,
get_file_content_from_ref,
get_merge_base,
is_lock_file,
)
from debug import debug_warning
from ui import (
Icons,
@@ -680,6 +687,58 @@ def handle_merge_preview_command(
# but we want to show the user all files that will be merged
total_files_from_git = len(all_changed_files)
# Detect files that need AI merge due to path mappings (file renames)
# This happens when the target branch has renamed/moved files that the
# worktree modified at their old locations
path_mapped_ai_merges: list[dict] = []
path_mappings: dict[str, str] = {}
if git_conflicts["needs_rebase"] and git_conflicts["commits_behind"] > 0:
# Get the merge-base between the branches
spec_branch = git_conflicts["spec_branch"]
base_branch = git_conflicts["base_branch"]
merge_base = get_merge_base(project_dir, spec_branch, base_branch)
if merge_base:
# Detect file renames between merge-base and current base branch
path_mappings = detect_file_renames(
project_dir, merge_base, base_branch
)
if path_mappings:
debug(
MODULE,
f"Detected {len(path_mappings)} file rename(s) between merge-base and target",
sample_mappings={
k: v for k, v in list(path_mappings.items())[:3]
},
)
# Check which changed files have path mappings and need AI merge
for file_path in all_changed_files:
mapped_path = apply_path_mapping(file_path, path_mappings)
if mapped_path != file_path:
# File was renamed - check if both versions exist
worktree_content = get_file_content_from_ref(
project_dir, spec_branch, file_path
)
target_content = get_file_content_from_ref(
project_dir, base_branch, mapped_path
)
if worktree_content and target_content:
path_mapped_ai_merges.append(
{
"oldPath": file_path,
"newPath": mapped_path,
"reason": "File was renamed/moved and modified in both branches",
}
)
debug(
MODULE,
f"Path-mapped file needs AI merge: {file_path} -> {mapped_path}",
)
result = {
"success": True,
# Use git diff files as the authoritative list of files to merge
@@ -693,6 +752,9 @@ def handle_merge_preview_command(
"commitsBehind": git_conflicts["commits_behind"],
"baseBranch": git_conflicts["base_branch"],
"specBranch": git_conflicts["spec_branch"],
# Path-mapped files that need AI merge due to renames
"pathMappedAIMerges": path_mapped_ai_merges,
"totalRenames": len(path_mappings),
},
"summary": {
# Use git diff count, not semantic tracker count
@@ -702,6 +764,8 @@ def handle_merge_preview_command(
"autoMergeable": summary.get("auto_mergeable", 0),
"hasGitConflicts": git_conflicts["has_conflicts"]
and len(non_lock_conflicting_files) > 0,
# Include path-mapped AI merge count for UI display
"pathMappedAIMergeCount": len(path_mapped_ai_merges),
},
# Include lock files info so UI can optionally show them
"lockFilesExcluded": lock_files_excluded,
@@ -716,6 +780,8 @@ def handle_merge_preview_command(
total_conflicts=result["summary"]["totalConflicts"],
has_git_conflicts=git_conflicts["has_conflicts"],
auto_mergeable=result["summary"]["autoMergeable"],
path_mapped_ai_merges=len(path_mapped_ai_merges),
total_renames=len(path_mappings),
)
return result
@@ -736,5 +802,6 @@ def handle_merge_preview_command(
"conflictFiles": 0,
"totalConflicts": 0,
"autoMergeable": 0,
"pathMappedAIMergeCount": 0,
},
}
+25
View File
@@ -0,0 +1,25 @@
"""
Claude client module facade.
Provides Claude API client utilities.
Uses lazy imports to avoid circular dependencies.
"""
def __getattr__(name):
"""Lazy import to avoid circular imports with auto_claude_tools."""
from core import client as _client
return getattr(_client, name)
def create_client(*args, **kwargs):
"""Create a Claude client instance."""
from core.client import create_client as _create_client
return _create_client(*args, **kwargs)
__all__ = [
"create_client",
]

Some files were not shown because too many files have changed in this diff Show More