diff --git a/.gitignore b/.gitignore index 27835c3e..546ab119 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ lerna-debug.log* # =========================== .auto-claude/ .planning/ +.planning-archive/ .auto-build-security.json .auto-claude-security.json .auto-claude-status diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md deleted file mode 100644 index 3ce1b9df..00000000 --- a/.planning/PROJECT.md +++ /dev/null @@ -1,69 +0,0 @@ -# PR Review System Robustness - -## What This Is - -Improvements to Auto Claude's PR review system to make it trustworthy enough to replace human review. The system uses specialist agents (security, logic, quality, codebase-fit) with a finding-validator that re-investigates findings before presenting them. This milestone fixes gaps that cause false positives and missed context. - -## Core Value - -**When the system flags something, it's a real issue.** Trustworthy PR reviews that are faster, more thorough, and more accurate than human review. - -## Requirements - -### Validated - -- ✓ Multi-agent PR review architecture — existing -- ✓ Specialist agents (security, logic, quality, codebase-fit) — existing -- ✓ Finding-validator for follow-up reviews — existing -- ✓ Dismissal tracking with reasons — existing -- ✓ CI status enforcement — existing -- ✓ Context gathering (diff, comments, related files) — existing - -### Active - -- [ ] **REQ-001**: Finding-validator runs on initial reviews (not just follow-ups) -- [ ] **REQ-002**: Fix line 1288 bug — include ai_reviews in follow-up context -- [ ] **REQ-003**: Fetch formal PR reviews from `/pulls/{pr}/reviews` API -- [ ] **REQ-004**: Add Read/Grep/Glob tool instructions to all specialist prompts -- [ ] **REQ-005**: Expand JS/TS import analysis (path aliases, CommonJS, re-exports) -- [ ] **REQ-006**: Add Python import analysis (currently skipped) -- [ ] **REQ-007**: Increase related files limit from 20 to 50 with prioritization -- [ ] **REQ-008**: Add reverse dependency analysis (what imports changed files) - -### Out of Scope - -- Real-time review streaming — complexity, not needed for accuracy goal -- Review caching/memoization — premature optimization -- Custom specialist agents — current four dimensions sufficient - -## Context - -**Problem**: False positives in PR reviews erode trust. Users have to second-guess every finding, defeating the purpose of automated review. - -**Root cause**: Finding-validator (which catches false positives) only runs during follow-up reviews. Initial reviews present unvalidated findings. Additionally, context gathering has bugs and gaps that cause the AI to make claims without complete information. - -**Existing system**: -- `apps/backend/runners/github/` — PR review orchestration -- `apps/backend/runners/github/services/parallel_orchestrator_reviewer.py` — initial review -- `apps/backend/runners/github/services/parallel_followup_reviewer.py` — follow-up review (has finding-validator) -- `apps/backend/runners/github/context_gatherer.py` — gathers PR context -- `apps/backend/prompts/github/pr_*.md` — specialist agent prompts - -**Reference**: Full PRD at `docs/PR_REVIEW_SYSTEM_IMPROVEMENTS.md` - -## Constraints - -- **Existing architecture**: Work within current multi-agent PR review structure -- **Backward compatibility**: Don't break existing review workflows -- **Performance**: Validation step should not significantly slow reviews (run in parallel where possible) - -## Key Decisions - -| Decision | Rationale | Outcome | -|----------|-----------|---------| -| Add finding-validator to initial reviews | Catches false positives before user sees them | — Pending | -| Same validator for initial and follow-up | Consistency, proven approach from follow-up reviews | — Pending | -| Expand import analysis incrementally | JS/TS first (REQ-005), Python second (REQ-006) | — Pending | - ---- -*Last updated: 2026-01-19 after initialization* diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md deleted file mode 100644 index 276b9594..00000000 --- a/.planning/codebase/ARCHITECTURE.md +++ /dev/null @@ -1,193 +0,0 @@ -# Architecture - -**Analysis Date:** 2026-01-19 - -## Pattern Overview - -**Overall:** Multi-Agent Orchestration with Electron Desktop UI - -**Key Characteristics:** -- Dual-app architecture: Python backend (CLI + agents) + Electron frontend (desktop UI) -- Agent-based autonomous coding via Claude Agent SDK -- Git worktree isolation for safe parallel development -- Phase-based pipeline execution for spec creation and implementation -- Event-driven IPC communication between frontend and backend - -## Layers - -**Frontend (Electron Main Process):** -- Purpose: Desktop application shell, native OS integration, IPC coordination -- Location: `apps/frontend/src/main/` -- Contains: Window management, IPC handlers, service managers (terminal, python env, CLI tools) -- Depends on: Backend Python CLI, Claude Code CLI -- Used by: Renderer process via IPC - -**Frontend (Renderer Process):** -- Purpose: React-based user interface -- Location: `apps/frontend/src/renderer/` -- Contains: Components, Zustand stores, hooks, contexts -- Depends on: Main process via preload IPC bridge -- Used by: End users - -**Backend Core:** -- Purpose: Authentication, SDK client factory, security, workspace management -- Location: `apps/backend/core/` -- Contains: `client.py` (SDK factory), `auth.py`, `worktree.py`, `workspace.py`, security hooks -- Depends on: Claude Agent SDK, project analyzer -- Used by: Agents, CLI commands, runners - -**Backend Agents:** -- Purpose: AI agent implementations for autonomous coding -- Location: `apps/backend/agents/` -- Contains: Coder, planner, memory manager, session management -- Depends on: Core client, prompts, phase config -- Used by: CLI commands, QA loop - -**Backend QA:** -- Purpose: Quality assurance validation loop -- Location: `apps/backend/qa/` -- Contains: QA reviewer, QA fixer, criteria validation, issue tracking -- Depends on: Agents, core client -- Used by: CLI commands after build completion - -**Backend Spec:** -- Purpose: Spec creation pipeline with complexity-based phases -- Location: `apps/backend/spec/` -- Contains: Pipeline orchestrator, complexity assessment, validation -- Depends on: Core client, agents -- Used by: CLI spec commands, frontend task creation - -**Backend Security:** -- Purpose: Command validation, allowlist management, secrets scanning -- Location: `apps/backend/security/` -- Contains: Validators, hooks, command parser, secrets scanner -- Depends on: Project analyzer -- Used by: Core client via pre-tool-use hooks - -**Backend CLI:** -- Purpose: Command-line interface and argument routing -- Location: `apps/backend/cli/` -- Contains: Main entry, build/spec/workspace/QA commands -- Depends on: All backend modules -- Used by: Entry point (`run.py`), frontend terminal - -## Data Flow - -**Spec Creation Flow:** -1. User creates task via frontend or CLI (`--task "description"`) -2. `SpecOrchestrator` (`spec/pipeline/orchestrator.py`) initializes -3. Complexity assessment determines phase count (3-8 phases) -4. `AgentRunner` executes phases: Discovery -> Requirements -> [Research] -> Context -> Spec -> Plan -> Validate -5. Each phase uses Claude Agent SDK session with phase-specific prompts -6. Output: `spec.md`, `requirements.json`, `context.json`, `implementation_plan.json` - -**Implementation Flow:** -1. CLI starts with `python run.py --spec 001` -2. `run_autonomous_agent()` in `agents/coder.py` orchestrates -3. Planner agent creates subtask-based `implementation_plan.json` -4. Coder agent implements subtasks in iteration loop -5. Each subtask runs as Claude Agent SDK session -6. On completion, QA validation loop runs (`qa/loop.py`) -7. QA reviewer validates -> QA fixer fixes issues -> loop until approved - -**Frontend-Backend IPC Flow:** -1. Renderer component dispatches action (e.g., start task) -2. Zustand store calls `window.api.invoke('ipc-channel', args)` -3. Preload script bridges to main process -4. IPC handler in `ipc-handlers/` processes request -5. Handler spawns Python subprocess or manages terminal -6. Events streamed back via IPC to update stores - -**State Management:** -- Frontend: Zustand stores per domain (`task-store`, `project-store`, `settings-store`, etc.) -- Backend: File-based state (`implementation_plan.json`, `qa_report.md`) -- Session recovery: `RecoveryManager` tracks agent sessions for resumption - -## Key Abstractions - -**ClaudeSDKClient:** -- Purpose: Configured Claude Agent SDK client with security hooks -- Examples: `apps/backend/core/client.py:create_client()` -- Pattern: Factory function with multi-layered security (sandbox, permissions, hooks) - -**SpecOrchestrator:** -- Purpose: Coordinates spec creation pipeline phases -- Examples: `apps/backend/spec/pipeline/orchestrator.py` -- Pattern: Orchestrator with dynamic phase selection based on complexity - -**WorktreeManager:** -- Purpose: Git worktree isolation for safe parallel builds -- Examples: `apps/backend/core/worktree.py` -- Pattern: Each spec gets isolated worktree branch (`auto-claude/{spec-name}`) - -**SecurityProfile:** -- Purpose: Dynamic command allowlist based on project analysis -- Examples: `apps/backend/project_analyzer.py`, `apps/backend/security/` -- Pattern: Base + stack-specific + custom commands cached in `.auto-claude-security.json` - -**IPC Handlers:** -- Purpose: Bridge between Electron renderer and backend services -- Examples: `apps/frontend/src/main/ipc-handlers/` -- Pattern: Domain-specific handler modules registered via `ipc-setup.ts` - -## Entry Points - -**Backend CLI:** -- Location: `apps/backend/run.py` -- Triggers: Terminal, frontend subprocess spawn, direct invocation -- Responsibilities: Argument parsing, command routing to `cli/` modules - -**Electron Main:** -- Location: `apps/frontend/src/main/index.ts` -- Triggers: Application launch -- Responsibilities: Window creation, IPC setup, service initialization - -**Renderer Entry:** -- Location: `apps/frontend/src/renderer/main.tsx` -- Triggers: Window load -- Responsibilities: React app mount, store initialization - -**Spec Pipeline:** -- Location: `apps/backend/spec/pipeline/orchestrator.py:SpecOrchestrator` -- Triggers: CLI `--task`, frontend task creation -- Responsibilities: Dynamic phase execution for spec creation - -**Agent Loop:** -- Location: `apps/backend/agents/coder.py:run_autonomous_agent()` -- Triggers: CLI `--spec 001`, frontend build start -- Responsibilities: Subtask iteration, session management, recovery - -## Error Handling - -**Strategy:** Multi-level error handling with recovery support - -**Patterns:** -- Agent sessions: `RecoveryManager` tracks state for resumption after interruption -- Security validation: Pre-tool-use hooks reject dangerous commands before execution -- QA loop: Escalation to human review after max iterations (`MAX_QA_ITERATIONS`) -- Git operations: Retry with exponential backoff for network errors -- Frontend: Error boundaries with toast notifications - -## Cross-Cutting Concerns - -**Logging:** -- Backend: Python `logging` module with task-specific loggers (`task_logger/`) -- Frontend: Electron app logger (`app-logger.ts`), Sentry integration - -**Validation:** -- Command security: `security/` validators with dynamic allowlists -- Spec validation: `spec/validate_pkg/` for implementation plan schema -- Tool input: `security/tool_input_validator.py` for Claude tool arguments - -**Authentication:** -- OAuth flow: `core/auth.py` manages Claude OAuth tokens -- Token storage: Keychain (macOS), Credential Manager (Windows), encrypted file (Linux) -- Token validation: Pre-SDK-call validation to prevent encrypted token errors - -**Internationalization:** -- Frontend: `react-i18next` with namespace-organized JSON files -- Location: `apps/frontend/src/shared/i18n/locales/{en,fr}/` - ---- - -*Architecture analysis: 2026-01-19* diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md deleted file mode 100644 index fb904710..00000000 --- a/.planning/codebase/CONCERNS.md +++ /dev/null @@ -1,224 +0,0 @@ -# Codebase Concerns - -**Analysis Date:** 2026-01-19 - -## Tech Debt - -**Large File Complexity:** -- Issue: Several core files exceed 1000+ lines, indicating potential need for further modularization -- Files: - - `apps/backend/core/workspace.py` (2096 lines) - Already refactored but remains large - - `apps/backend/runners/github/orchestrator.py` (1607 lines) - - `apps/backend/core/worktree.py` (1404 lines) - - `apps/backend/runners/github/context_gatherer.py` (1292 lines) - - `apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts` (3149 lines) - - `apps/frontend/src/main/ipc-handlers/github/pr-handlers.ts` (2874 lines) -- Impact: Difficult to navigate, test, and maintain; increases risk of merge conflicts -- Fix approach: Continue modular extraction pattern (workspace.py partially done); extract sub-modules for GitHub orchestrator - -**Deprecated Modules Still in Codebase:** -- Issue: Deprecated code remains active and produces warnings -- Files: - - `apps/backend/runners/github/confidence.py` - Marked deprecated, uses DeprecationWarning - - `apps/frontend/src/main/terminal/terminal-manager.ts` - Contains deprecated sync methods - - `apps/frontend/src/main/terminal/session-handler.ts` - persistAllSessions deprecated -- Impact: Technical confusion, potential runtime warnings, maintenance burden -- Fix approach: Remove deprecated modules or complete migration to evidence-based validation - -**Global State / Module-Level Caches:** -- Issue: Multiple modules use global variables and module-level caches that are not thread-safe -- Files: - - `apps/backend/security/profile.py` (5 global variables for caching) - - `apps/backend/core/client.py` (_PROJECT_INDEX_CACHE, _CLAUDE_CLI_CACHE) - - `apps/backend/core/io_utils.py` (_pipe_broken global) - - `apps/backend/core/sentry.py` (_sentry_initialized, _sentry_enabled) - - `apps/backend/task_logger/utils.py` (_current_logger global) -- Impact: Potential race conditions in multi-threaded scenarios; difficult to test in isolation -- Fix approach: Convert to class-based singletons with proper locking; use thread-local storage where appropriate - -**Incomplete TODO Implementation:** -- Issue: Critical features have TODO placeholders -- Files: - - `apps/backend/core/workspace.py:1578` - `_record_merge_completion` not implemented - - `apps/backend/merge/conflict_analysis.py:272-283` - Advanced implicit conflict detection not implemented - - `apps/frontend/src/renderer/stores/settings-store.ts:214` - i18n keys not implemented - - `apps/frontend/src/renderer/components/ideation/EnvConfigModal.tsx:1` - Props interface not defined -- Impact: Missing functionality, potential runtime issues -- Fix approach: Implement or remove features; document if intentionally deferred - -**Empty Exception Handlers:** -- Issue: Many `pass` statements in exception handlers swallow errors silently -- Files: 237+ instances of `pass` after exception handling across backend -- Locations include: - - `apps/backend/core/worktree.py:448` - - `apps/backend/services/orchestrator.py:384, 396, 411, 423` - - `apps/backend/cli/workspace_commands.py:339-359` (multiple) - - `apps/backend/runners/github/memory_integration.py` (multiple) -- Impact: Silent failures make debugging difficult; errors may propagate unexpectedly -- Fix approach: Add logging to catch blocks; re-raise critical exceptions; document intentional suppressions - -## Known Bugs - -**Status Flip-Flop Bug (Task Store):** -- Symptoms: Task status may incorrectly change between terminal states -- Files: `apps/frontend/src/renderer/stores/task-store.ts:278, 282, 324, 346` -- Trigger: Phase transitions in updateTaskFromPlan -- Workaround: Multiple FIX comments added inline; logic guards terminal phases - -**BulkPRDialog Error Detection:** -- Symptoms: String-based error detection is fragile -- Files: `apps/frontend/src/renderer/components/BulkPRDialog.tsx:32` -- Trigger: API error messages changing format -- Workaround: None - TODO comment acknowledges the issue - -## Security Considerations - -**Shell=True Usage:** -- Risk: Command injection if inputs not properly sanitized -- Files: - - `apps/backend/core/git_executable.py:134` - Windows 'where' command - - `apps/backend/core/gh_executable.py:61` - Windows 'where' command -- Current mitigation: Limited to Windows platform detection, not user-controlled input -- Recommendations: Document why shell=True is required; ensure no user input reaches these calls - -**Subprocess Execution Spread Across Codebase:** -- Risk: Inconsistent security validation; command injection if not properly controlled -- Files: 50+ files with subprocess.run/Popen calls -- Current mitigation: Security hooks in `apps/backend/security/hooks.py`; allowlist in project_analyzer -- Recommendations: Consolidate subprocess calls through centralized wrappers; audit all subprocess calls - -**Environment Variable Handling:** -- Risk: Sensitive data exposure through env vars -- Files: 100+ os.environ references across backend -- Current mitigation: Token validation in `apps/backend/core/auth.py`; encrypted token detection -- Recommendations: Audit all env var usage; ensure secrets are not logged; use secure storage APIs - -**Token Decryption Not Implemented:** -- Risk: Encrypted tokens fail silently, requiring manual workarounds -- Files: `apps/backend/core/auth.py:103-228` -- Current mitigation: Clear error messages directing users to alternatives -- Recommendations: Implement cross-platform token decryption or improve error UX - -## Performance Bottlenecks - -**Blocking Sleep Calls:** -- Problem: time.sleep() calls block threads -- Files: - - `apps/backend/core/workspace/models.py:129, 218` - - `apps/backend/core/worktree.py:95, 106` - - `apps/backend/services/orchestrator.py:451` - - `apps/backend/runners/github/file_lock.py:172` - - `apps/backend/runners/gitlab/glab_client.py:168` -- Cause: Synchronous retry logic with exponential backoff -- Improvement path: Convert to async operations where possible; use asyncio.sleep for async code - -**Project Index Cache TTL:** -- Problem: 5-minute TTL may cause stale data or unnecessary reloads -- Files: `apps/backend/core/client.py:43` (_CACHE_TTL_SECONDS = 300) -- Cause: Fixed TTL doesn't adapt to project activity -- Improvement path: Implement file-watcher invalidation; make TTL configurable - -**Security Profile Cache:** -- Problem: Module-level cache with no size limits -- Files: `apps/backend/security/profile.py:23-27` -- Cause: Global state without eviction policy -- Improvement path: Add LRU eviction; consider bounded cache - -## Fragile Areas - -**Merge System:** -- Files: - - `apps/backend/core/workspace.py` (complex merge orchestration) - - `apps/backend/merge/` directory (conflict detection, resolution) -- Why fragile: Complex state machine for parallel merges; many edge cases in git operations -- Safe modification: Always test with multiple concurrent specs; use DEBUG=true for verbose logging -- Test coverage: Tests exist but may not cover all race conditions - -**GitHub Integration:** -- Files: - - `apps/backend/runners/github/orchestrator.py` - - `apps/backend/runners/github/rate_limiter.py` - - `apps/backend/runners/github/gh_client.py` -- Why fragile: External API dependencies; rate limiting complexity; async/await patterns -- Safe modification: Mock external calls in tests; test rate limit scenarios explicitly -- Test coverage: Good coverage in `tests/test_github_*.py` - -**Terminal Integration (Frontend):** -- Files: - - `apps/frontend/src/renderer/stores/terminal-store.ts` - - `apps/frontend/src/main/terminal/claude-integration-handler.ts` -- Why fragile: Complex state management; IPC communication; PTY lifecycle -- Safe modification: Test terminal creation/destruction cycles; watch for memory leaks -- Test coverage: Tests exist in `__tests__/` directories - -**Auth/Token Handling:** -- Files: `apps/backend/core/auth.py` (898 lines) -- Why fragile: Platform-specific code paths; external dependency on Claude CLI; keyring integration -- Safe modification: Test on all platforms; verify OAuth flow end-to-end -- Test coverage: `tests/test_auth.py` exists - -## Scaling Limits - -**Concurrent Agent Sessions:** -- Current capacity: Limited by Claude SDK rate limits and system resources -- Limit: No explicit session pooling or queuing -- Scaling path: Implement session pool; add retry queues for rate limits - -**Graphiti Memory Database:** -- Current capacity: LadybugDB (embedded Kuzu) - single-process access -- Limit: No concurrent write support across multiple processes -- Scaling path: Consider distributed graph database for multi-user scenarios - -## Dependencies at Risk - -**Deprecated Python Packages:** -- Risk: `secretstorage` on Linux has complex DBus dependencies -- Impact: Installation failures on minimal Linux systems -- Migration plan: Document fallback to .env storage; improve error messages - -**Platform-Specific Code:** -- Risk: Windows/macOS/Linux code paths diverge -- Impact: Platform-specific bugs (documented in CLAUDE.md) -- Migration plan: Centralized platform abstraction in `apps/backend/core/platform/` - -## Missing Critical Features - -**Implicit Conflict Detection:** -- Problem: Function rename + usage conflicts not detected -- Blocks: Accurate parallel merge conflict resolution -- Files: `apps/backend/merge/conflict_analysis.py:272-283` - -**_record_merge_completion:** -- Problem: Merge completion not recorded for timeline tracking -- Blocks: Full merge history audit trail -- Files: `apps/backend/core/workspace.py:1578` - -## Test Coverage Gaps - -**Async Code Testing:** -- What's not tested: Many async functions have limited coverage -- Files: 70+ files with async functions, 92+ with await statements -- Risk: Race conditions in async code may go unnoticed -- Priority: High - async bugs are hard to reproduce - -**Platform-Specific Paths:** -- What's not tested: Windows-specific code paths on Linux CI -- Files: Platform detection in `apps/backend/core/platform/__init__.py` -- Risk: Windows-only bugs not caught until user reports -- Priority: Medium - CI now runs on all platforms per CLAUDE.md - -**Global State Reset:** -- What's not tested: Cache invalidation edge cases -- Files: All files with module-level caches -- Risk: State leakage between tests -- Priority: Medium - add cache reset fixtures - -**Exception Handler Behavior:** -- What's not tested: Error paths through empty except blocks -- Files: 237+ `pass` statements in exception handlers -- Risk: Silent failures in production -- Priority: High - add tests that trigger exception paths - ---- - -*Concerns audit: 2026-01-19* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md deleted file mode 100644 index 65af1e71..00000000 --- a/.planning/codebase/CONVENTIONS.md +++ /dev/null @@ -1,283 +0,0 @@ -# Coding Conventions - -**Analysis Date:** 2026-01-19 - -## Naming Patterns - -**Files:** -- Python: `snake_case.py` (e.g., `project_analyzer.py`, `qa_report.py`) -- TypeScript: `kebab-case.ts` or `PascalCase.tsx` for React components -- Test files: `test_*.py` (Python), `*.test.ts` (TypeScript) -- Config files: lowercase with extension (e.g., `ruff.toml`, `tsconfig.json`) - -**Functions:** -- Python: `snake_case` (e.g., `validate_command()`, `get_security_profile()`) -- TypeScript: `camelCase` (e.g., `detectRateLimit()`, `parsePhaseEvent()`) - -**Variables:** -- Python: `snake_case` for locals, `UPPER_SNAKE_CASE` for constants -- TypeScript: `camelCase` for locals, `UPPER_SNAKE_CASE` for constants - -**Classes/Types:** -- Python: `PascalCase` (e.g., `SecurityProfile`, `ClaudeSDKClient`) -- TypeScript: `PascalCase` for types/interfaces (e.g., `ExecutionParserContext`) - -**Constants:** -- Module-level: `UPPER_SNAKE_CASE` (e.g., `DEFAULT_UTILITY_MODEL`, `SAFE_COMMANDS`) -- Private cache variables: `_UPPER_SNAKE_CASE` (e.g., `_PROJECT_INDEX_CACHE`) - -## Code Style - -**Formatting - Python (Backend):** -- Tool: Ruff (v0.14.10 via pre-commit) -- Quote style: Double quotes -- Indent style: Spaces (4 spaces per PEP 8) -- Line endings: Auto -- Key rules enabled: - - `E`, `W` (pycodestyle) - - `F` (Pyflakes) - - `I` (isort) - - `B` (flake8-bugbear) - - `C4` (flake8-comprehensions) - - `UP` (pyupgrade) - -**Formatting - TypeScript (Frontend):** -- Tool: Biome (v2.3.11) -- Commands: - ```bash - cd apps/frontend && npx biome check --write . # Lint + format - ``` -- TypeScript compiler: `tsc --noEmit` for type checking -- Strict mode enabled in `tsconfig.json` - -**Linting:** -- Python: Ruff handles both linting and formatting -- TypeScript: Biome handles both (replaced ESLint for 15-25x faster performance) - -## Import Organization - -**Python Order (enforced by isort via Ruff):** -1. Standard library imports (`import os`, `import json`) -2. Third-party imports (`from claude_agent_sdk import ...`) -3. Local imports (`from core.client import create_client`) - -**TypeScript Order:** -1. React/external library imports -2. Local component imports -3. Type imports - -**Path Aliases (TypeScript):** -```typescript -// tsconfig.json paths -"@/*": ["src/renderer/*"] -"@shared/*": ["src/shared/*"] -"@preload/*": ["src/preload/*"] -"@features/*": ["src/renderer/features/*"] -"@components/*": ["src/renderer/shared/components/*"] -"@hooks/*": ["src/renderer/shared/hooks/*"] -"@lib/*": ["src/renderer/shared/lib/*"] -``` - -## Error Handling - -**Python Patterns:** -```python -# Try-except with specific exceptions -try: - result = subprocess.run(cmd, capture_output=True, timeout=5) -except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as e: - logger.debug(f"Operation failed: {e}") - return None - -# Validation with early return -def validate_something(value: str) -> tuple[bool, str]: - if not value: - return False, "Value is required" - if invalid_condition: - return False, "Value is invalid because..." - return True, "" -``` - -**TypeScript Patterns:** -```typescript -// Result object pattern for detection functions -interface DetectionResult { - isDetected: boolean; - message?: string; - details?: Record; -} - -function detectSomething(input: string): DetectionResult { - if (!input) { - return { isDetected: false }; - } - // Detection logic... - return { isDetected: true, message: "Detected condition X" }; -} -``` - -## Logging - -**Python Framework:** Standard library `logging` - -**Patterns:** -```python -import logging - -logger = logging.getLogger(__name__) - -# Debug for verbose/diagnostic info -logger.debug(f"Cache HIT for {key}") - -# Info for significant operations -logger.info(f"Found Claude CLI: {path} (v{version})") - -# Warning for recoverable issues -logger.warning(f"Invalid configuration: {value}, using default") - -# Error with context -logger.error(f"Failed to process {file}: {error}") -``` - -**TypeScript Logging:** Console-based in development, suppressed in tests. - -## Comments - -**When to Comment:** -- Public functions: Always document with docstrings/JSDoc -- Complex algorithms: Explain the "why" not the "what" -- Security-related code: Explain security implications -- Workarounds: Reference issue numbers - -**Python Docstrings:** -```python -def create_client( - project_dir: Path, - spec_dir: Path, - model: str, - agent_type: str = "coder", -) -> ClaudeSDKClient: - """ - Create a Claude Agent SDK client with multi-layered security. - - Uses AGENT_CONFIGS for phase-aware tool and MCP server configuration. - - Args: - project_dir: Root directory for the project (working directory) - spec_dir: Directory containing the spec (for settings file) - model: Claude model to use - agent_type: Agent type identifier from AGENT_CONFIGS - - Returns: - Configured ClaudeSDKClient - - Raises: - ValueError: If agent_type is not found in AGENT_CONFIGS - """ -``` - -**TypeScript JSDoc:** -```typescript -/** - * Detect rate limit from CLI output. - * - * @param output - Raw CLI output string - * @returns Detection result with isRateLimited flag and optional resetTime - */ -function detectRateLimit(output: string): RateLimitResult { - // ... -} -``` - -## Function Design - -**Size:** Keep functions focused on a single responsibility. Functions over 50 lines should be considered for splitting. - -**Parameters:** -- Python: Use type hints for all parameters -- TypeScript: Use explicit types, avoid `any` -- Default values for optional parameters -- Keyword arguments for functions with 3+ parameters - -**Return Values:** -- Python: Use tuple for multiple returns `-> tuple[bool, str]` -- TypeScript: Use result objects for complex returns -- Always annotate return types - -## Module Design - -**Python Exports:** -- Use `__all__` in `__init__.py` to control public API -- Prefix internal functions/classes with underscore - -**TypeScript Barrel Files:** -```typescript -// index.ts barrel export pattern -export { ExecutionPhaseParser } from './execution-phase-parser'; -export { IdeationPhaseParser } from './ideation-phase-parser'; -export type { ExecutionParserContext } from './types'; -``` - -## Security Conventions - -**Validation First:** -```python -# Always validate input before processing -def _validate_custom_mcp_server(server: dict) -> bool: - """Validate a custom MCP server configuration for security.""" - if not isinstance(server, dict): - return False - - # Required fields - required_fields = {"id", "name", "type"} - if not all(field in server for field in required_fields): - return False - - # Blocklist dangerous commands - DANGEROUS_COMMANDS = {"bash", "sh", "cmd", "powershell"} - if command in DANGEROUS_COMMANDS: - logger.warning(f"Rejected dangerous command: {command}") - return False - - return True -``` - -**Sensitive Commands:** Always use allowlist approach, never blocklist alone. - -## Internationalization (Frontend) - -**Always use i18n for user-facing text:** -```tsx -import { useTranslation } from 'react-i18next'; - -const { t } = useTranslation(['navigation', 'common']); - -// Correct -{t('navigation:items.githubPRs')} - -// Wrong - hardcoded string -GitHub PRs -``` - -**Translation file structure:** -- `apps/frontend/src/shared/i18n/locales/en/*.json` -- `apps/frontend/src/shared/i18n/locales/fr/*.json` - -## Platform-Specific Code - -**Use platform abstraction module:** -```typescript -// Correct - use abstraction -import { isWindows, getPathDelimiter } from './platform'; - -// Wrong - direct check -if (process.platform === 'win32') { ... } -``` - -**Platform modules:** -- Frontend: `apps/frontend/src/main/platform/` -- Backend: `apps/backend/core/platform/` - ---- - -*Convention analysis: 2026-01-19* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md deleted file mode 100644 index 730a21ce..00000000 --- a/.planning/codebase/INTEGRATIONS.md +++ /dev/null @@ -1,204 +0,0 @@ -# External Integrations - -**Analysis Date:** 2026-01-19 - -## APIs & External Services - -**Claude AI (Primary):** -- Service: Anthropic Claude API via Claude Agent SDK -- SDK: `claude-agent-sdk` >= 0.1.19 (Python backend) -- Auth: OAuth tokens via system keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) -- Env: `CLAUDE_CODE_OAUTH_TOKEN` or auto-detected from system credential store -- Implementation: `apps/backend/core/client.py`, `apps/backend/core/auth.py` - -**CRITICAL: Never use `anthropic.Anthropic()` directly. Always use `create_client()` from `core.client`.** - -**Context7 MCP (Documentation Lookup):** -- Service: Upstash Context7 documentation retrieval -- SDK: `@upstash/context7-mcp` (spawned via npx) -- Auth: None (public MCP server) -- Implementation: Configured in `apps/backend/core/client.py` MCP servers -- Usage: Automatically available to agents for documentation queries - -**Linear (Optional Project Management):** -- Service: Linear issue tracking and project management -- SDK: Linear MCP server (HTTP-based) -- Auth: `LINEAR_API_KEY` (Bearer token) -- Env: `LINEAR_API_KEY`, `LINEAR_TEAM_ID`, `LINEAR_PROJECT_ID` -- Implementation: `apps/backend/integrations/linear/integration.py` -- Features: Subtask-to-issue sync, progress tracking, stuck task escalation - -**GitHub:** -- Service: GitHub API for issues, PRs, releases -- SDK: `gh` CLI (subprocess calls) -- Auth: GitHub CLI auth (`gh auth login`) -- Implementation: `apps/frontend/src/main/ipc-handlers/github/` -- Features: Import issues, create PRs, manage releases, triage automation - -**GitLab (Optional):** -- Service: GitLab API for issues and merge requests -- SDK: `glab` CLI or Personal Access Token -- Auth: `glab auth login` or `GITLAB_TOKEN` -- Env: `GITLAB_INSTANCE_URL`, `GITLAB_TOKEN`, `GITLAB_PROJECT` -- Implementation: `apps/frontend/src/main/ipc-handlers/gitlab/` - -## Data Storage - -**Databases:** -- LadybugDB (embedded graph database) - - Connection: Local file at `~/.auto-claude/memories/{database_name}` - - Client: `real_ladybug` Python package (requires Python 3.12+) - - No Docker required - fully embedded - - Provider-specific database naming to prevent embedding dimension mismatches - -**File Storage:** -- Local filesystem only -- Project data: `.auto-claude/` directory per project -- Specs: `.auto-claude/specs/{id}-{name}/` -- Worktrees: `.auto-claude/worktrees/` (git worktree isolation) - -**Caching:** -- Project index cache (5 minute TTL, thread-safe) -- CLI path cache (per-session) -- Implementation: `apps/backend/core/client.py` (`_PROJECT_INDEX_CACHE`) - -## Memory System (Graphiti) - -**Graph Memory:** -- Engine: Graphiti-core + LadybugDB -- Purpose: Cross-session context retention, pattern learning -- Data: Episodes (insights, discoveries, patterns, gotchas, outcomes) -- Config: `apps/backend/integrations/graphiti/config.py` -- Memory: `apps/backend/integrations/graphiti/memory.py` - -**Multi-Provider Support:** - -| Provider | LLM | Embedder | Env Vars | -|----------|-----|----------|----------| -| OpenAI | Yes | Yes | `OPENAI_API_KEY`, `OPENAI_MODEL` | -| Anthropic | Yes | No | `ANTHROPIC_API_KEY`, `GRAPHITI_ANTHROPIC_MODEL` | -| Azure OpenAI | Yes | Yes | `AZURE_OPENAI_*` (API_KEY, BASE_URL, deployments) | -| Voyage AI | No | Yes | `VOYAGE_API_KEY`, `VOYAGE_EMBEDDING_MODEL` | -| Google AI | Yes | Yes | `GOOGLE_API_KEY`, `GOOGLE_LLM_MODEL` | -| Ollama | Yes | Yes | `OLLAMA_*` (BASE_URL, models, embedding dim) | -| OpenRouter | Yes | Yes | `OPENROUTER_API_KEY`, `OPENROUTER_*_MODEL` | - -**Provider Implementation:** `apps/backend/integrations/graphiti/providers_pkg/` - -## Authentication & Identity - -**Claude OAuth:** -- Provider: Anthropic Claude Code OAuth -- Implementation: `apps/backend/core/auth.py` -- Storage: - - macOS: Keychain (`/usr/bin/security find-generic-password`) - - Windows: `~/.claude/.credentials.json` or Credential Manager - - Linux: Secret Service API via DBus (`secretstorage` package) -- Token format: `sk-ant-oat01-*` (OAuth access token) -- Login flow: `claude` CLI with `/login` command (opens browser) - -**GitHub Auth:** -- Provider: GitHub CLI OAuth -- Implementation: IPC handlers in frontend -- Storage: Managed by `gh` CLI - -**GitLab Auth:** -- Provider: GitLab Personal Access Token or glab CLI OAuth -- Implementation: `apps/frontend/src/main/ipc-handlers/gitlab/` -- Storage: Managed by `glab` CLI or `.env` file - -## Monitoring & Observability - -**Error Tracking:** -- Service: Sentry (optional) -- SDK: `@sentry/electron` 7.5.0 -- Auth: `SENTRY_DSN` (set in CI for official builds) -- Env: `SENTRY_DSN`, `SENTRY_TRACES_SAMPLE_RATE`, `SENTRY_PROFILES_SAMPLE_RATE` -- Implementation: `apps/frontend/src/main/sentry.ts` -- Note: Disabled in forks unless SENTRY_DSN is explicitly set - -**Logs:** -- Backend: Python `logging` module (structured JSON in debug mode) -- Frontend: `electron-log` (file + console) -- Location: Platform-specific logs directory -- Debug: Set `DEBUG=true` for verbose output - -## CI/CD & Deployment - -**Hosting:** -- Distribution: GitHub Releases (electron-updater compatible) -- Auto-update: electron-updater checks GitHub releases - -**CI Pipeline:** -- Service: GitHub Actions -- Workflow: `.github/workflows/ci.yml` -- Matrix: Linux, Windows, macOS -- Jobs: test-python, test-frontend, ci-complete (gate job) - -**Release Pipeline:** -- Workflow: `.github/workflows/release.yml` (triggered on tag) -- Artifacts: DMG, ZIP (macOS), NSIS/ZIP (Windows), AppImage/DEB/Flatpak (Linux) - -## Environment Configuration - -**Required env vars (backend):** -``` -CLAUDE_CODE_OAUTH_TOKEN # Or use system keychain -GRAPHITI_ENABLED=true # Enable memory system -``` - -**Optional env vars (backend):** -``` -ANTHROPIC_BASE_URL # Custom API endpoint -LINEAR_API_KEY # Linear integration -ELECTRON_MCP_ENABLED # E2E testing -DEBUG=true # Verbose logging -``` - -**Required env vars (frontend):** -``` -# None required - optional debug/Sentry settings -``` - -**Secrets location:** -- Development: `.env` files (gitignored) -- CI/CD: GitHub Secrets -- Production: System credential stores (no secrets in app bundle) - -## MCP (Model Context Protocol) Servers - -**Built-in MCP Servers:** - -| Server | Purpose | Agent Access | Configuration | -|--------|---------|--------------|---------------| -| context7 | Documentation lookup | All agents | Auto-enabled | -| linear | Project management | All agents | `LINEAR_API_KEY` | -| electron | Desktop app automation | QA agents only | `ELECTRON_MCP_ENABLED` | -| puppeteer | Web browser automation | QA agents only | Project capability detection | -| graphiti-memory | Knowledge graph | All agents | `GRAPHITI_MCP_URL` | -| auto-claude | Custom tools | Phase-specific | Auto-enabled | - -**Custom MCP Servers:** -- Config: `.auto-claude/.env` (`CUSTOM_MCP_SERVERS` JSON array) -- Validation: `apps/backend/core/client.py` (`_validate_custom_mcp_server`) -- Allowed commands: `npx`, `npm`, `node`, `python`, `python3`, `uv`, `uvx` - -**Per-Agent MCP Overrides:** -- Add servers: `AGENT_MCP_{agent}_ADD=server1,server2` -- Remove servers: `AGENT_MCP_{agent}_REMOVE=server1,server2` - -## Webhooks & Callbacks - -**Incoming:** -- None (desktop application, no server) - -**Outgoing:** -- GitHub API calls (via `gh` CLI) -- GitLab API calls (via `glab` CLI or REST) -- Linear MCP server (HTTP) -- Sentry error reports (if configured) -- Auto-update checks (GitHub Releases API) - ---- - -*Integration audit: 2026-01-19* diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md deleted file mode 100644 index c818c358..00000000 --- a/.planning/codebase/STACK.md +++ /dev/null @@ -1,140 +0,0 @@ -# Technology Stack - -**Analysis Date:** 2026-01-19 - -## Languages - -**Primary:** -- TypeScript 5.9.3 - Electron frontend (desktop UI, IPC handlers, state management) -- Python 3.12+ - Backend agents, CLI, integrations, security - -**Secondary:** -- JavaScript (ES modules) - Build scripts, configuration -- JSON - Configuration, data storage, IPC communication - -## Runtime - -**Environment:** -- Node.js >= 24.0.0 (Electron main/renderer processes) -- Python 3.12+ (required for LadybugDB/Graphiti memory system) - -**Package Manager:** -- npm 10.0.0+ (root monorepo, frontend) -- uv (Python backend - fast pip alternative) -- Lockfiles: `package-lock.json` (present), Python deps in `requirements.txt` - -## Frameworks - -**Core:** -- Electron 39.2.7 - Cross-platform desktop application shell -- React 19.2.3 - UI components and state management -- Claude Agent SDK >= 0.1.19 - AI agent orchestration (CRITICAL: NOT raw Anthropic API) - -**Testing:** -- Vitest 4.0.16 - Frontend unit tests -- Playwright 1.52.0 - E2E testing for Electron -- pytest 7.0.0+ - Backend Python tests -- pytest-asyncio 0.21.0+ - Async test support - -**Build/Dev:** -- electron-vite 5.0.0 - Electron build toolchain -- Vite 7.2.7 - Frontend bundler -- electron-builder 26.4.0 - Cross-platform packaging (dmg, exe, AppImage, deb, flatpak) - -## Key Dependencies - -**Critical (AI/Agent):** -- `claude-agent-sdk` >= 0.1.19 - Core AI agent SDK (replaces direct Anthropic API) -- `@anthropic-ai/sdk` 0.71.2 - Anthropic client (used by Graphiti providers) - -**Infrastructure:** -- `@lydell/node-pty` 1.1.0 - Terminal emulation (native module) -- `@xterm/xterm` 6.0.0 - Terminal rendering -- `electron-updater` 6.6.2 - Auto-update mechanism -- `chokidar` 5.0.0 - File system watching -- `zustand` 5.0.9 - React state management - -**UI Components:** -- `@radix-ui/*` - Accessible UI primitives (dialogs, dropdowns, tabs, etc.) -- `tailwindcss` 4.1.17 - Utility-first CSS -- `lucide-react` 0.562.0 - Icons -- `motion` 12.23.26 - Animations - -**Memory/Database:** -- `real_ladybug` >= 0.13.0 - Embedded graph database (Python 3.12+, no Docker) -- `graphiti-core` >= 0.5.0 - Knowledge graph memory layer - -**Observability:** -- `@sentry/electron` 7.5.0 - Error tracking (optional, requires SENTRY_DSN) -- `electron-log` 5.4.3 - Structured logging - -**Internationalization:** -- `i18next` 25.7.3 + `react-i18next` 16.5.0 - Multi-language support (en, fr) - -## Configuration - -**Environment:** -- Backend: `apps/backend/.env` (OAuth tokens, integrations, memory config) -- Frontend: `apps/frontend/.env` (debug settings, Sentry DSN) -- Example files: `.env.example` in both directories - -**Key Backend Env Vars:** -``` -CLAUDE_CODE_OAUTH_TOKEN # Required: OAuth token (or use system keychain) -ANTHROPIC_BASE_URL # Optional: Custom API endpoint -GRAPHITI_ENABLED # Required: true to enable memory -GRAPHITI_LLM_PROVIDER # openai|anthropic|azure_openai|ollama|google|openrouter -GRAPHITI_EMBEDDER_PROVIDER # openai|voyage|azure_openai|ollama|google|openrouter -LINEAR_API_KEY # Optional: Linear integration -ELECTRON_MCP_ENABLED # Optional: E2E testing via Electron MCP -``` - -**Build:** -- `apps/frontend/electron.vite.config.ts` - Electron/Vite build config -- `apps/frontend/vitest.config.ts` - Test configuration -- `apps/frontend/package.json` (build section) - electron-builder config -- `ruff.toml` - Python linting/formatting - -## Platform Requirements - -**Development:** -- macOS, Windows, or Linux -- Node.js 24+, Python 3.12+ -- Git (required for worktree isolation) -- Git Bash (Windows only, for Claude Code CLI) - -**Production:** -- macOS: DMG/ZIP (arm64 + x64) -- Windows: NSIS installer/ZIP -- Linux: AppImage, DEB, Flatpak -- Bundled Python runtime (downloaded via `scripts/download-python.cjs`) - -**CI/CD:** -- GitHub Actions (`.github/workflows/ci.yml`) -- Matrix testing: Linux, Windows, macOS -- Python 3.12 + 3.13 (Linux only) - -## Monorepo Structure - -``` -autonomous-coding/ -├── apps/ -│ ├── backend/ # Python (uv, requirements.txt) -│ └── frontend/ # Electron/React (npm, package.json) -├── tests/ # Shared test suite -├── scripts/ # Build/release scripts -└── package.json # Root workspace config -``` - -**Workspace Commands:** -```bash -npm run install:all # Install both frontend and backend -npm run dev # Start Electron in dev mode -npm run build # Build frontend -npm run package # Package for current platform -npm run test:backend # Run Python tests -``` - ---- - -*Stack analysis: 2026-01-19* diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md deleted file mode 100644 index 91d85eae..00000000 --- a/.planning/codebase/STRUCTURE.md +++ /dev/null @@ -1,219 +0,0 @@ -# Codebase Structure - -**Analysis Date:** 2026-01-19 - -## Directory Layout - -``` -autonomous-coding/ -├── apps/ -│ ├── backend/ # Python backend - CLI, agents, core logic -│ │ ├── agents/ # Agent implementations (coder, planner, memory) -│ │ ├── cli/ # Command-line interface modules -│ │ ├── core/ # Client factory, auth, worktree, security -│ │ ├── integrations/ # External integrations (Graphiti, Linear) -│ │ ├── memory/ # Memory system (sessions, patterns) -│ │ ├── merge/ # Git merge conflict resolution -│ │ ├── prompts/ # Agent system prompts (.md files) -│ │ ├── qa/ # QA validation loop -│ │ ├── runners/ # Feature runners (GitHub, GitLab, roadmap, spec) -│ │ ├── security/ # Command validators, secrets scanning -│ │ ├── spec/ # Spec creation pipeline -│ │ └── ui/ # CLI output formatting -│ └── frontend/ # Electron desktop app -│ ├── src/ -│ │ ├── main/ # Electron main process -│ │ ├── renderer/ # React renderer (components, stores) -│ │ ├── preload/ # IPC bridge scripts -│ │ └── shared/ # Shared types, constants, i18n -│ └── resources/ # App icons, assets -├── tests/ # Python test suite -├── scripts/ # Build and utility scripts -├── docs/ # Documentation -└── guides/ # User guides -``` - -## Directory Purposes - -**`apps/backend/`:** -- Purpose: All Python backend code (CLI, agents, core infrastructure) -- Contains: Agent implementations, CLI modules, security, integrations -- Key files: `run.py` (entry point), `core/client.py` (SDK factory) - -**`apps/backend/agents/`:** -- Purpose: AI agent implementations for autonomous coding -- Contains: Coder agent loop, planner, memory manager, session utilities -- Key files: `coder.py`, `planner.py`, `memory_manager.py`, `session.py` - -**`apps/backend/cli/`:** -- Purpose: CLI command implementations -- Contains: Build, spec, workspace, QA, batch commands -- Key files: `main.py`, `build_commands.py`, `workspace_commands.py` - -**`apps/backend/core/`:** -- Purpose: Core infrastructure (client, auth, workspace, platform) -- Contains: SDK client factory, OAuth, worktree manager, platform abstraction -- Key files: `client.py`, `auth.py`, `worktree.py`, `workspace.py` - -**`apps/backend/qa/`:** -- Purpose: QA validation after build completion -- Contains: QA loop, reviewer, fixer, criteria validation, issue tracking -- Key files: `loop.py`, `reviewer.py`, `fixer.py`, `criteria.py` - -**`apps/backend/spec/`:** -- Purpose: Spec creation pipeline -- Contains: Pipeline orchestrator, complexity assessment, validation -- Key files: `pipeline/orchestrator.py`, `complexity.py`, `validate_pkg/` - -**`apps/backend/security/`:** -- Purpose: Bash command validation and security -- Contains: Validators, hooks, command parser, secrets scanner -- Key files: `hooks.py`, `validator.py`, `parser.py`, `scan_secrets.py` - -**`apps/backend/prompts/`:** -- Purpose: Agent system prompts (Markdown files) -- Contains: Prompts for coder, planner, QA, spec agents -- Key files: `coder.md`, `planner.md`, `qa_reviewer.md`, `spec_gatherer.md` - -**`apps/backend/runners/`:** -- Purpose: Feature-specific execution runners -- Contains: GitHub PR review, roadmap generation, spec creation -- Key files: `github/orchestrator.py`, `spec_runner.py`, `roadmap_runner.py` - -**`apps/frontend/src/main/`:** -- Purpose: Electron main process -- Contains: Window management, IPC handlers, service managers -- Key files: `index.ts`, `ipc-setup.ts`, `cli-tool-manager.ts` - -**`apps/frontend/src/renderer/`:** -- Purpose: React UI -- Contains: Components, stores, hooks, contexts -- Key files: `App.tsx`, `components/`, `stores/` - -**`apps/frontend/src/shared/`:** -- Purpose: Shared code between main and renderer -- Contains: Types, constants, i18n, utilities -- Key files: `types/`, `constants/`, `i18n/` - -## Key File Locations - -**Entry Points:** -- `apps/backend/run.py`: Backend CLI entry point -- `apps/frontend/src/main/index.ts`: Electron main entry -- `apps/frontend/src/renderer/main.tsx`: React app entry - -**Configuration:** -- `apps/backend/.env`: Backend environment variables -- `apps/backend/.env.example`: Backend env template -- `apps/frontend/.env`: Frontend environment variables -- `apps/backend/requirements.txt`: Python dependencies -- `apps/frontend/package.json`: Frontend dependencies - -**Core Logic:** -- `apps/backend/core/client.py`: Claude SDK client factory -- `apps/backend/core/auth.py`: OAuth token management -- `apps/backend/core/worktree.py`: Git worktree isolation -- `apps/backend/agents/coder.py`: Main agent loop -- `apps/backend/spec/pipeline/orchestrator.py`: Spec creation pipeline - -**Testing:** -- `tests/`: All Python tests (pytest) -- `tests/conftest.py`: Pytest fixtures and configuration -- `apps/frontend/src/main/__tests__/`: Main process tests -- `apps/frontend/src/renderer/__tests__/`: Renderer tests - -## Naming Conventions - -**Files:** -- Python modules: `snake_case.py` (e.g., `workspace_commands.py`) -- TypeScript modules: `kebab-case.ts` (e.g., `cli-tool-manager.ts`) -- React components: `PascalCase.tsx` (e.g., `KanbanBoard.tsx`) -- Prompts: `snake_case.md` (e.g., `qa_reviewer.md`) -- Tests: `test_*.py` (Python), `*.test.ts/tsx` (TypeScript) - -**Directories:** -- Python packages: `snake_case/` with `__init__.py` -- TypeScript modules: `kebab-case/` -- Package submodules: `*_pkg/` suffix (e.g., `tools_pkg/`, `queries_pkg/`) - -**Classes and Functions:** -- Python classes: `PascalCase` (e.g., `SpecOrchestrator`) -- Python functions: `snake_case` (e.g., `run_autonomous_agent`) -- TypeScript/React: `camelCase` functions, `PascalCase` components - -## Where to Add New Code - -**New Agent Feature:** -- Primary code: `apps/backend/agents/` -- Prompt: `apps/backend/prompts/{agent_name}.md` -- Tests: `tests/test_agent_*.py` - -**New CLI Command:** -- Implementation: `apps/backend/cli/{domain}_commands.py` -- Registration: `apps/backend/cli/main.py` (argument parsing) -- Tests: `tests/test_{command}.py` - -**New Frontend Component:** -- Implementation: `apps/frontend/src/renderer/components/{ComponentName}.tsx` -- Translations: `apps/frontend/src/shared/i18n/locales/en/{namespace}.json` -- Tests: `apps/frontend/src/renderer/components/__tests__/` - -**New Frontend Store:** -- Implementation: `apps/frontend/src/renderer/stores/{domain}-store.ts` -- Pattern: Use Zustand with typed state and actions - -**New IPC Handler:** -- Handler module: `apps/frontend/src/main/ipc-handlers/{domain}-handlers.ts` -- Registration: `apps/frontend/src/main/ipc-handlers/index.ts` -- Types: `apps/frontend/src/shared/types/` - -**New Security Validator:** -- Implementation: `apps/backend/security/validator.py` -- Registration: Add to `VALIDATORS` dict in same file -- Tests: `tests/test_security.py` - -**New Integration:** -- Implementation: `apps/backend/integrations/{service}/` -- Configuration: Add env vars to `.env.example` -- Documentation: Update `CLAUDE.md` - -**Utilities:** -- Backend shared helpers: `apps/backend/core/` or domain-specific module -- Frontend shared helpers: `apps/frontend/src/shared/utils/` - -## Special Directories - -**`.auto-claude/`:** -- Purpose: Per-project spec storage and build state -- Generated: Yes (by backend during spec creation) -- Committed: No (gitignored) -- Contents: `specs/`, `worktrees/tasks/`, `insights/` - -**`.worktrees/`:** -- Purpose: Legacy worktree location (deprecated) -- Generated: Yes (by worktree manager) -- Committed: No (gitignored) - -**`node_modules/`:** -- Purpose: Frontend npm dependencies -- Generated: Yes (by npm install) -- Committed: No (gitignored) - -**`.venv/`:** -- Purpose: Python virtual environment -- Generated: Yes (by uv venv) -- Committed: No (gitignored) - -**`dist/` and `out/`:** -- Purpose: Build outputs -- Generated: Yes (by build scripts) -- Committed: No (gitignored) - -**`.planning/`:** -- Purpose: GSD planning documents -- Generated: Yes (by GSD commands) -- Committed: Optional (project choice) - ---- - -*Structure analysis: 2026-01-19* diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md deleted file mode 100644 index 9fdd16de..00000000 --- a/.planning/codebase/TESTING.md +++ /dev/null @@ -1,485 +0,0 @@ -# Testing Patterns - -**Analysis Date:** 2026-01-19 - -## Test Framework - -**Backend (Python):** -- Runner: pytest (>=7.0.0) -- Config: `tests/pytest.ini` -- Async support: pytest-asyncio (>=0.21.0) -- Coverage: pytest-cov (>=4.0.0) -- Mocking: pytest-mock (>=3.0.0) - -**Frontend (TypeScript):** -- Runner: Vitest (v4.0.16) -- Config: `apps/frontend/vitest.config.ts` -- DOM testing: @testing-library/react, @testing-library/dom -- Mocking: Vitest built-in `vi` - -**Run Commands:** -```bash -# Backend - all tests -apps/backend/.venv/bin/pytest tests/ -v - -# Backend - skip slow tests (recommended for development) -apps/backend/.venv/bin/pytest tests/ -m "not slow" -v - -# Backend - single test file -apps/backend/.venv/bin/pytest tests/test_security.py -v - -# Backend - specific test -apps/backend/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v - -# Frontend - all tests -cd apps/frontend && npm test - -# Frontend - watch mode -cd apps/frontend && npm run test:watch - -# Frontend - coverage -cd apps/frontend && npm run test:coverage - -# From root (convenience) -npm run test:backend -npm run test (frontend) -``` - -## Test File Organization - -**Backend Location:** Co-located at root `tests/` directory -``` -tests/ -├── pytest.ini # Pytest configuration -├── conftest.py # Shared fixtures -├── test_fixtures.py # Sample data constants -├── review_fixtures.py # Review system fixtures -├── qa_report_helpers.py # QA test helpers -├── requirements-test.txt # Test dependencies -├── test_security.py # Security module tests -├── test_client.py # SDK client tests -├── test_qa_loop.py # QA system tests -└── ... -``` - -**Frontend Location:** Co-located with source, in `__tests__/` directories -``` -apps/frontend/src/ -├── __tests__/ -│ ├── setup.ts # Test setup (mocks, globals) -│ └── integration/ # Integration tests -├── main/__tests__/ # Main process tests -│ ├── parsers.test.ts -│ ├── rate-limit-detector.test.ts -│ └── ... -├── renderer/__tests__/ # Renderer tests -│ ├── task-store.test.ts -│ └── ... -└── renderer/components/__tests__/ # Component tests -``` - -**Naming:** -- Python: `test_*.py` (e.g., `test_security.py`) -- TypeScript: `*.test.ts` or `*.test.tsx` (e.g., `parsers.test.ts`) - -## Test Structure - -**Python - pytest Pattern:** -```python -#!/usr/bin/env python3 -""" -Tests for Security System -========================= - -Tests the security.py module functionality including: -- Command extraction and parsing -- Command allowlist validation -""" - -import pytest -from security import validate_command, extract_commands - - -class TestCommandExtraction: - """Tests for command extraction from shell strings.""" - - def test_simple_command(self): - """Extracts single command correctly.""" - commands = extract_commands("ls -la") - assert commands == ["ls"] - - def test_piped_commands(self): - """Extracts all commands from pipeline.""" - commands = extract_commands("cat file.txt | grep pattern | wc -l") - assert commands == ["cat", "grep", "wc"] - - -class TestValidateCommand: - """Tests for full command validation.""" - - def test_base_commands_allowed(self, temp_dir): - """Base commands are always allowed.""" - for cmd in ["ls", "cat", "grep"]: - allowed, reason = validate_command(cmd, temp_dir) - assert allowed is True, f"{cmd} should be allowed" -``` - -**TypeScript - Vitest Pattern:** -```typescript -/** - * Phase Parsers Tests - * ==================== - * Unit tests for the specialized phase parsers. - */ - -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { ExecutionPhaseParser } from '../agent/parsers'; - -describe('ExecutionPhaseParser', () => { - const parser = new ExecutionPhaseParser(); - - const makeContext = (currentPhase: string): ExecutionParserContext => ({ - currentPhase, - isTerminal: currentPhase === 'complete' - }); - - describe('structured event parsing', () => { - it('should parse structured phase events', () => { - const log = '__EXEC_PHASE__:{"phase":"coding","message":"Starting"}'; - const result = parser.parse(log, makeContext('planning')); - - expect(result).toEqual({ - phase: 'coding', - message: 'Starting', - currentSubtask: undefined - }); - }); - }); - - describe('terminal state handling', () => { - it('should not change phase when current phase is complete', () => { - const log = 'Starting coder agent...'; - const result = parser.parse(log, makeContext('complete')); - - expect(result).toBeNull(); - }); - }); -}); -``` - -## Mocking - -**Python - pytest fixtures and unittest.mock:** -```python -from unittest.mock import MagicMock, patch - -@pytest.fixture -def mock_task_logger(): - """Mock TaskLogger for testing PhaseExecutor.""" - logger = MagicMock() - logger.log = MagicMock() - logger.start_phase = MagicMock() - logger.end_phase = MagicMock() - return logger - -# Using patch decorator -@patch('core.client.find_claude_cli') -def test_client_creation(mock_find_cli): - mock_find_cli.return_value = '/usr/local/bin/claude' - # Test code... - -# Using monkeypatch fixture -def test_with_env_var(monkeypatch): - monkeypatch.setenv("CLAUDE_CLI_PATH", "/custom/path") - # Test code... -``` - -**TypeScript - Vitest vi.mock:** -```typescript -// Mock at module level (hoisted) -vi.mock('../claude-profile-manager', () => ({ - getClaudeProfileManager: vi.fn(() => ({ - getActiveProfile: vi.fn(() => ({ - id: 'test-profile-id', - name: 'Test Profile' - })), - recordRateLimitEvent: vi.fn() - })) -})); - -describe('Rate Limit Detector', () => { - beforeEach(() => { - vi.resetModules(); - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - it('should detect rate limit', async () => { - const { detectRateLimit } = await import('../rate-limit-detector'); - const result = detectRateLimit('Limit reached · resets Dec 17'); - expect(result.isRateLimited).toBe(true); - }); -}); -``` - -**What to Mock:** -- External APIs (Claude SDK, GitHub API) -- File system operations in unit tests -- Network requests -- System time (for time-sensitive tests) -- Heavy dependencies (databases, MCP servers) - -**What NOT to Mock:** -- Pure functions under test -- Simple data transformations -- Validation logic - -## Fixtures and Factories - -**Python Fixtures (conftest.py):** -```python -@pytest.fixture -def temp_dir() -> Generator[Path, None, None]: - """Create a temporary directory that's cleaned up after the test.""" - temp_path = Path(tempfile.mkdtemp()) - yield temp_path - shutil.rmtree(temp_path, ignore_errors=True) - -@pytest.fixture -def temp_git_repo(temp_dir: Path) -> Generator[Path, None, None]: - """Create a temporary git repository with initial commit.""" - # Clear git environment variables to isolate from parent repo - orig_env = {} - git_vars_to_clear = ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE"] - for key in git_vars_to_clear: - orig_env[key] = os.environ.get(key) - if key in os.environ: - del os.environ[key] - - try: - subprocess.run(["git", "init"], cwd=temp_dir, capture_output=True) - subprocess.run(["git", "config", "user.email", "test@example.com"], cwd=temp_dir) - # ... - yield temp_dir - finally: - # Restore environment - for key, value in orig_env.items(): - if value is None: - os.environ.pop(key, None) - else: - os.environ[key] = value - -@pytest.fixture -def python_project(temp_git_repo: Path) -> Path: - """Create a sample Python project structure.""" - (temp_git_repo / "pyproject.toml").write_text(toml_content) - (temp_git_repo / "app" / "__init__.py").write_text("# App module\n") - return temp_git_repo -``` - -**TypeScript Setup (setup.ts):** -```typescript -import { vi, beforeEach, afterEach } from 'vitest'; - -// Mock localStorage for tests -const localStorageMock = (() => { - let store: Record = {}; - return { - getItem: vi.fn((key: string) => store[key] || null), - setItem: vi.fn((key: string, value: string) => { store[key] = value; }), - clear: vi.fn(() => { store = {}; }) - }; -})(); - -Object.defineProperty(global, 'localStorage', { value: localStorageMock }); - -// Mock window.electronAPI for renderer tests -if (typeof window !== 'undefined') { - (window as any).electronAPI = { - getTasks: vi.fn(), - createTask: vi.fn(), - getSettings: vi.fn(), - // ... - }; -} - -beforeEach(() => { - localStorageMock.clear(); -}); - -afterEach(() => { - vi.clearAllMocks(); - vi.resetModules(); -}); -``` - -**Sample Data (test_fixtures.py):** -```python -SAMPLE_REACT_COMPONENT = '''import React from 'react'; -import { useState } from 'react'; - -function App() { - const [count, setCount] = useState(0); - return

Hello World

; -} -export default App; -''' - -SAMPLE_PYTHON_MODULE = '''"""Sample Python module.""" -import os -from pathlib import Path - -def hello(): - """Say hello.""" - print("Hello") -''' -``` - -## Coverage - -**Requirements:** No enforced minimum threshold, but aim for meaningful coverage - -**View Coverage:** -```bash -# Backend -apps/backend/.venv/bin/pytest tests/ --cov=apps/backend --cov-report=html - -# Frontend -cd apps/frontend && npm run test:coverage -``` - -**Coverage Output:** -- Backend: `.coverage` file, HTML report in `htmlcov/` -- Frontend: `coverage/` directory with JSON, text, and HTML reports - -## Test Types - -**Unit Tests:** -- Test individual functions/classes in isolation -- Mock external dependencies -- Fast execution (sub-second) -- Location: `tests/test_*.py`, `src/**/*.test.ts` - -**Integration Tests:** -- Test interactions between components -- May use real file system, git repos -- Slower execution -- Markers: `@pytest.mark.integration` (Python) -- Location: `tests/` (Python), `src/__tests__/integration/` (TypeScript) - -**E2E Tests (Frontend):** -- Framework: Playwright (configured but limited use) -- Config: `apps/frontend/e2e/playwright.config.ts` -- Run: `npm run test:e2e` - -## Common Patterns - -**Async Testing (Python):** -```python -import pytest - -@pytest.mark.asyncio -async def test_async_function(): - result = await some_async_operation() - assert result is not None - -# pytest.ini enables asyncio_mode = auto -# No need to manually mark simple async tests -``` - -**Async Testing (TypeScript):** -```typescript -it('should handle async operation', async () => { - const { detectRateLimit } = await import('../rate-limit-detector'); - const result = detectRateLimit('some output'); - expect(result.isRateLimited).toBe(false); -}); -``` - -**Error Testing (Python):** -```python -def test_blocked_dangerous_command(self, temp_dir): - """Dangerous commands not in allowlist are blocked.""" - allowed, reason = validate_command("rm -rf /", temp_dir) - assert allowed is False - assert "not allowed for safety" in reason - -def test_raises_on_invalid_input(): - """Should raise ValueError on invalid input.""" - with pytest.raises(ValueError, match="Invalid configuration"): - process_config(None) -``` - -**Error Testing (TypeScript):** -```typescript -it('should return false for empty output', async () => { - const { detectRateLimit } = await import('../rate-limit-detector'); - const result = detectRateLimit(''); - expect(result.isRateLimited).toBe(false); -}); - -it('should handle malformed input gracefully', () => { - expect(() => parser.parse(null as any)).not.toThrow(); -}); -``` - -**Parameterized Tests (Python):** -```python -@pytest.mark.parametrize("cmd,expected", [ - ("ls -la", ["ls"]), - ("cat file | grep pattern", ["cat", "grep"]), - ("", []), -]) -def test_extract_commands(cmd, expected): - assert extract_commands(cmd) == expected -``` - -**Parameterized Tests (TypeScript):** -```typescript -const testCases = [ - 'rate limit exceeded', - 'usage limit reached', - 'too many requests' -]; - -for (const output of testCases) { - const result = detectRateLimit(output); - expect(result.isRateLimited).toBe(true); -} -``` - -## Pre-commit Testing - -**Configuration:** `.pre-commit-config.yaml` - -Tests run automatically on commit: -- Python: `pytest -m "not slow and not integration"` (fast tests only) -- TypeScript: Biome lint + TypeScript type check - -Skipped tests in pre-commit: -- `test_graphiti.py` (external dependencies) -- `test_worktree.py` (git-sensitive) -- `test_workspace.py` (Windows path issues) - -## Test Markers (Python) - -```python -@pytest.mark.slow # Long-running tests -@pytest.mark.integration # Integration tests -@pytest.mark.asyncio # Async tests (auto-applied via config) -``` - -**Run specific markers:** -```bash -# Skip slow tests -pytest tests/ -m "not slow" - -# Run only integration tests -pytest tests/ -m "integration" -``` - ---- - -*Testing analysis: 2026-01-19* diff --git a/.planning/config.json b/.planning/config.json deleted file mode 100644 index f23a5804..00000000 --- a/.planning/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mode": "yolo", - "depth": "comprehensive", - "parallelization": true, - "created": "2026-01-19" -}