chore: remove .planning from tracking and gitignore .planning-archive

These directories contain local planning data that should not be in the repository.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
AndyMik90
2026-01-27 07:10:42 +01:00
parent 496b2b96a5
commit e2d45bcd7d
10 changed files with 1 additions and 1823 deletions
+1
View File
@@ -57,6 +57,7 @@ lerna-debug.log*
# ===========================
.auto-claude/
.planning/
.planning-archive/
.auto-build-security.json
.auto-claude-security.json
.auto-claude-status
-69
View File
@@ -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*
-193
View File
@@ -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*
-224
View File
@@ -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*
-283
View File
@@ -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<string, unknown>;
}
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
<span>{t('navigation:items.githubPRs')}</span>
// Wrong - hardcoded string
<span>GitHub PRs</span>
```
**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*
-204
View File
@@ -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*
-140
View File
@@ -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*
-219
View File
@@ -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*
-485
View File
@@ -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<string, string> = {};
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 <div><h1>Hello World</h1></div>;
}
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*
-6
View File
@@ -1,6 +0,0 @@
{
"mode": "yolo",
"depth": "comprehensive",
"parallelization": true,
"created": "2026-01-19"
}